Bug Summary

File:build/source/clang/lib/Sema/SemaOpenMP.cpp
Warning:line 8239, column 58
Called C++ object pointer is null

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name SemaOpenMP.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -mframe-pointer=none -relaxed-aliasing -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/build/source/build-llvm -resource-dir /usr/lib/llvm-17/lib/clang/17 -I tools/clang/lib/Sema -I /build/source/clang/lib/Sema -I /build/source/clang/include -I tools/clang/include -I include -I /build/source/llvm/include -D _DEBUG -D _GLIBCXX_ASSERTIONS -D _GNU_SOURCE -D _LIBCPP_ENABLE_ASSERTIONS -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -D _FORTIFY_SOURCE=2 -D NDEBUG -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/x86_64-linux-gnu/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/backward -internal-isystem /usr/lib/llvm-17/lib/clang/17/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/build/source/build-llvm=build-llvm -fmacro-prefix-map=/build/source/= -fcoverage-prefix-map=/build/source/build-llvm=build-llvm -fcoverage-prefix-map=/build/source/= -O3 -Wno-unused-command-line-argument -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-class-memaccess -Wno-redundant-move -Wno-pessimizing-move -Wno-noexcept-type -Wno-comment -Wno-misleading-indentation -std=c++17 -fdeprecated-macro -fdebug-compilation-dir=/build/source/build-llvm -fdebug-prefix-map=/build/source/build-llvm=build-llvm -fdebug-prefix-map=/build/source/= -fdebug-prefix-map=/build/source/build-llvm=build-llvm -fdebug-prefix-map=/build/source/= -ferror-limit 19 -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcolor-diagnostics -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2023-05-10-133810-16478-1 -x c++ /build/source/clang/lib/Sema/SemaOpenMP.cpp
1//===--- SemaOpenMP.cpp - Semantic Analysis for OpenMP constructs ---------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8/// \file
9/// This file implements semantic analysis for OpenMP directives and
10/// clauses.
11///
12//===----------------------------------------------------------------------===//
13
14#include "TreeTransform.h"
15#include "clang/AST/ASTContext.h"
16#include "clang/AST/ASTMutationListener.h"
17#include "clang/AST/CXXInheritance.h"
18#include "clang/AST/Decl.h"
19#include "clang/AST/DeclCXX.h"
20#include "clang/AST/DeclOpenMP.h"
21#include "clang/AST/OpenMPClause.h"
22#include "clang/AST/StmtCXX.h"
23#include "clang/AST/StmtOpenMP.h"
24#include "clang/AST/StmtVisitor.h"
25#include "clang/AST/TypeOrdering.h"
26#include "clang/Basic/DiagnosticSema.h"
27#include "clang/Basic/OpenMPKinds.h"
28#include "clang/Basic/PartialDiagnostic.h"
29#include "clang/Basic/TargetInfo.h"
30#include "clang/Sema/EnterExpressionEvaluationContext.h"
31#include "clang/Sema/Initialization.h"
32#include "clang/Sema/Lookup.h"
33#include "clang/Sema/Scope.h"
34#include "clang/Sema/ScopeInfo.h"
35#include "clang/Sema/SemaInternal.h"
36#include "llvm/ADT/IndexedMap.h"
37#include "llvm/ADT/PointerEmbeddedInt.h"
38#include "llvm/ADT/STLExtras.h"
39#include "llvm/ADT/SmallSet.h"
40#include "llvm/ADT/StringExtras.h"
41#include "llvm/Frontend/OpenMP/OMPAssume.h"
42#include "llvm/Frontend/OpenMP/OMPConstants.h"
43#include <optional>
44#include <set>
45
46using namespace clang;
47using namespace llvm::omp;
48
49//===----------------------------------------------------------------------===//
50// Stack of data-sharing attributes for variables
51//===----------------------------------------------------------------------===//
52
53static const Expr *checkMapClauseExpressionBase(
54 Sema &SemaRef, Expr *E,
55 OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents,
56 OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose);
57
58namespace {
59/// Default data sharing attributes, which can be applied to directive.
60enum DefaultDataSharingAttributes {
61 DSA_unspecified = 0, /// Data sharing attribute not specified.
62 DSA_none = 1 << 0, /// Default data sharing attribute 'none'.
63 DSA_shared = 1 << 1, /// Default data sharing attribute 'shared'.
64 DSA_private = 1 << 2, /// Default data sharing attribute 'private'.
65 DSA_firstprivate = 1 << 3, /// Default data sharing attribute 'firstprivate'.
66};
67
68/// Stack for tracking declarations used in OpenMP directives and
69/// clauses and their data-sharing attributes.
70class DSAStackTy {
71public:
72 struct DSAVarData {
73 OpenMPDirectiveKind DKind = OMPD_unknown;
74 OpenMPClauseKind CKind = OMPC_unknown;
75 unsigned Modifier = 0;
76 const Expr *RefExpr = nullptr;
77 DeclRefExpr *PrivateCopy = nullptr;
78 SourceLocation ImplicitDSALoc;
79 bool AppliedToPointee = false;
80 DSAVarData() = default;
81 DSAVarData(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind,
82 const Expr *RefExpr, DeclRefExpr *PrivateCopy,
83 SourceLocation ImplicitDSALoc, unsigned Modifier,
84 bool AppliedToPointee)
85 : DKind(DKind), CKind(CKind), Modifier(Modifier), RefExpr(RefExpr),
86 PrivateCopy(PrivateCopy), ImplicitDSALoc(ImplicitDSALoc),
87 AppliedToPointee(AppliedToPointee) {}
88 };
89 using OperatorOffsetTy =
90 llvm::SmallVector<std::pair<Expr *, OverloadedOperatorKind>, 4>;
91 using DoacrossDependMapTy =
92 llvm::DenseMap<OMPDependClause *, OperatorOffsetTy>;
93 /// Kind of the declaration used in the uses_allocators clauses.
94 enum class UsesAllocatorsDeclKind {
95 /// Predefined allocator
96 PredefinedAllocator,
97 /// User-defined allocator
98 UserDefinedAllocator,
99 /// The declaration that represent allocator trait
100 AllocatorTrait,
101 };
102
103private:
104 struct DSAInfo {
105 OpenMPClauseKind Attributes = OMPC_unknown;
106 unsigned Modifier = 0;
107 /// Pointer to a reference expression and a flag which shows that the
108 /// variable is marked as lastprivate(true) or not (false).
109 llvm::PointerIntPair<const Expr *, 1, bool> RefExpr;
110 DeclRefExpr *PrivateCopy = nullptr;
111 /// true if the attribute is applied to the pointee, not the variable
112 /// itself.
113 bool AppliedToPointee = false;
114 };
115 using DeclSAMapTy = llvm::SmallDenseMap<const ValueDecl *, DSAInfo, 8>;
116 using UsedRefMapTy = llvm::SmallDenseMap<const ValueDecl *, const Expr *, 8>;
117 using LCDeclInfo = std::pair<unsigned, VarDecl *>;
118 using LoopControlVariablesMapTy =
119 llvm::SmallDenseMap<const ValueDecl *, LCDeclInfo, 8>;
120 /// Struct that associates a component with the clause kind where they are
121 /// found.
122 struct MappedExprComponentTy {
123 OMPClauseMappableExprCommon::MappableExprComponentLists Components;
124 OpenMPClauseKind Kind = OMPC_unknown;
125 };
126 using MappedExprComponentsTy =
127 llvm::DenseMap<const ValueDecl *, MappedExprComponentTy>;
128 using CriticalsWithHintsTy =
129 llvm::StringMap<std::pair<const OMPCriticalDirective *, llvm::APSInt>>;
130 struct ReductionData {
131 using BOKPtrType = llvm::PointerEmbeddedInt<BinaryOperatorKind, 16>;
132 SourceRange ReductionRange;
133 llvm::PointerUnion<const Expr *, BOKPtrType> ReductionOp;
134 ReductionData() = default;
135 void set(BinaryOperatorKind BO, SourceRange RR) {
136 ReductionRange = RR;
137 ReductionOp = BO;
138 }
139 void set(const Expr *RefExpr, SourceRange RR) {
140 ReductionRange = RR;
141 ReductionOp = RefExpr;
142 }
143 };
144 using DeclReductionMapTy =
145 llvm::SmallDenseMap<const ValueDecl *, ReductionData, 4>;
146 struct DefaultmapInfo {
147 OpenMPDefaultmapClauseModifier ImplicitBehavior =
148 OMPC_DEFAULTMAP_MODIFIER_unknown;
149 SourceLocation SLoc;
150 DefaultmapInfo() = default;
151 DefaultmapInfo(OpenMPDefaultmapClauseModifier M, SourceLocation Loc)
152 : ImplicitBehavior(M), SLoc(Loc) {}
153 };
154
155 struct SharingMapTy {
156 DeclSAMapTy SharingMap;
157 DeclReductionMapTy ReductionMap;
158 UsedRefMapTy AlignedMap;
159 UsedRefMapTy NontemporalMap;
160 MappedExprComponentsTy MappedExprComponents;
161 LoopControlVariablesMapTy LCVMap;
162 DefaultDataSharingAttributes DefaultAttr = DSA_unspecified;
163 SourceLocation DefaultAttrLoc;
164 DefaultmapInfo DefaultmapMap[OMPC_DEFAULTMAP_unknown];
165 OpenMPDirectiveKind Directive = OMPD_unknown;
166 DeclarationNameInfo DirectiveName;
167 Scope *CurScope = nullptr;
168 DeclContext *Context = nullptr;
169 SourceLocation ConstructLoc;
170 /// Set of 'depend' clauses with 'sink|source' dependence kind. Required to
171 /// get the data (loop counters etc.) about enclosing loop-based construct.
172 /// This data is required during codegen.
173 DoacrossDependMapTy DoacrossDepends;
174 /// First argument (Expr *) contains optional argument of the
175 /// 'ordered' clause, the second one is true if the regions has 'ordered'
176 /// clause, false otherwise.
177 std::optional<std::pair<const Expr *, OMPOrderedClause *>> OrderedRegion;
178 bool RegionHasOrderConcurrent = false;
179 unsigned AssociatedLoops = 1;
180 bool HasMutipleLoops = false;
181 const Decl *PossiblyLoopCounter = nullptr;
182 bool NowaitRegion = false;
183 bool UntiedRegion = false;
184 bool CancelRegion = false;
185 bool LoopStart = false;
186 bool BodyComplete = false;
187 SourceLocation PrevScanLocation;
188 SourceLocation PrevOrderedLocation;
189 SourceLocation InnerTeamsRegionLoc;
190 /// Reference to the taskgroup task_reduction reference expression.
191 Expr *TaskgroupReductionRef = nullptr;
192 llvm::DenseSet<QualType> MappedClassesQualTypes;
193 SmallVector<Expr *, 4> InnerUsedAllocators;
194 llvm::DenseSet<CanonicalDeclPtr<Decl>> ImplicitTaskFirstprivates;
195 /// List of globals marked as declare target link in this target region
196 /// (isOpenMPTargetExecutionDirective(Directive) == true).
197 llvm::SmallVector<DeclRefExpr *, 4> DeclareTargetLinkVarDecls;
198 /// List of decls used in inclusive/exclusive clauses of the scan directive.
199 llvm::DenseSet<CanonicalDeclPtr<Decl>> UsedInScanDirective;
200 llvm::DenseMap<CanonicalDeclPtr<const Decl>, UsesAllocatorsDeclKind>
201 UsesAllocatorsDecls;
202 /// Data is required on creating capture fields for implicit
203 /// default first|private clause.
204 struct ImplicitDefaultFDInfoTy {
205 /// Field decl.
206 const FieldDecl *FD = nullptr;
207 /// Nesting stack level
208 size_t StackLevel = 0;
209 /// Capture variable decl.
210 VarDecl *VD = nullptr;
211 ImplicitDefaultFDInfoTy(const FieldDecl *FD, size_t StackLevel,
212 VarDecl *VD)
213 : FD(FD), StackLevel(StackLevel), VD(VD) {}
214 };
215 /// List of captured fields
216 llvm::SmallVector<ImplicitDefaultFDInfoTy, 8>
217 ImplicitDefaultFirstprivateFDs;
218 Expr *DeclareMapperVar = nullptr;
219 SmallVector<VarDecl *, 16> IteratorVarDecls;
220 SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name,
221 Scope *CurScope, SourceLocation Loc)
222 : Directive(DKind), DirectiveName(Name), CurScope(CurScope),
223 ConstructLoc(Loc) {}
224 SharingMapTy() = default;
225 };
226
227 using StackTy = SmallVector<SharingMapTy, 4>;
228
229 /// Stack of used declaration and their data-sharing attributes.
230 DeclSAMapTy Threadprivates;
231 const FunctionScopeInfo *CurrentNonCapturingFunctionScope = nullptr;
232 SmallVector<std::pair<StackTy, const FunctionScopeInfo *>, 4> Stack;
233 /// true, if check for DSA must be from parent directive, false, if
234 /// from current directive.
235 OpenMPClauseKind ClauseKindMode = OMPC_unknown;
236 Sema &SemaRef;
237 bool ForceCapturing = false;
238 /// true if all the variables in the target executable directives must be
239 /// captured by reference.
240 bool ForceCaptureByReferenceInTargetExecutable = false;
241 CriticalsWithHintsTy Criticals;
242 unsigned IgnoredStackElements = 0;
243
244 /// Iterators over the stack iterate in order from innermost to outermost
245 /// directive.
246 using const_iterator = StackTy::const_reverse_iterator;
247 const_iterator begin() const {
248 return Stack.empty() ? const_iterator()
249 : Stack.back().first.rbegin() + IgnoredStackElements;
250 }
251 const_iterator end() const {
252 return Stack.empty() ? const_iterator() : Stack.back().first.rend();
253 }
254 using iterator = StackTy::reverse_iterator;
255 iterator begin() {
256 return Stack.empty() ? iterator()
257 : Stack.back().first.rbegin() + IgnoredStackElements;
258 }
259 iterator end() {
260 return Stack.empty() ? iterator() : Stack.back().first.rend();
261 }
262
263 // Convenience operations to get at the elements of the stack.
264
265 bool isStackEmpty() const {
266 return Stack.empty() ||
267 Stack.back().second != CurrentNonCapturingFunctionScope ||
268 Stack.back().first.size() <= IgnoredStackElements;
269 }
270 size_t getStackSize() const {
271 return isStackEmpty() ? 0
272 : Stack.back().first.size() - IgnoredStackElements;
273 }
274
275 SharingMapTy *getTopOfStackOrNull() {
276 size_t Size = getStackSize();
277 if (Size == 0)
278 return nullptr;
279 return &Stack.back().first[Size - 1];
280 }
281 const SharingMapTy *getTopOfStackOrNull() const {
282 return const_cast<DSAStackTy &>(*this).getTopOfStackOrNull();
283 }
284 SharingMapTy &getTopOfStack() {
285 assert(!isStackEmpty() && "no current directive")(static_cast <bool> (!isStackEmpty() && "no current directive"
) ? void (0) : __assert_fail ("!isStackEmpty() && \"no current directive\""
, "clang/lib/Sema/SemaOpenMP.cpp", 285, __extension__ __PRETTY_FUNCTION__
))
;
286 return *getTopOfStackOrNull();
287 }
288 const SharingMapTy &getTopOfStack() const {
289 return const_cast<DSAStackTy &>(*this).getTopOfStack();
290 }
291
292 SharingMapTy *getSecondOnStackOrNull() {
293 size_t Size = getStackSize();
294 if (Size <= 1)
295 return nullptr;
296 return &Stack.back().first[Size - 2];
297 }
298 const SharingMapTy *getSecondOnStackOrNull() const {
299 return const_cast<DSAStackTy &>(*this).getSecondOnStackOrNull();
300 }
301
302 /// Get the stack element at a certain level (previously returned by
303 /// \c getNestingLevel).
304 ///
305 /// Note that nesting levels count from outermost to innermost, and this is
306 /// the reverse of our iteration order where new inner levels are pushed at
307 /// the front of the stack.
308 SharingMapTy &getStackElemAtLevel(unsigned Level) {
309 assert(Level < getStackSize() && "no such stack element")(static_cast <bool> (Level < getStackSize() &&
"no such stack element") ? void (0) : __assert_fail ("Level < getStackSize() && \"no such stack element\""
, "clang/lib/Sema/SemaOpenMP.cpp", 309, __extension__ __PRETTY_FUNCTION__
))
;
310 return Stack.back().first[Level];
311 }
312 const SharingMapTy &getStackElemAtLevel(unsigned Level) const {
313 return const_cast<DSAStackTy &>(*this).getStackElemAtLevel(Level);
314 }
315
316 DSAVarData getDSA(const_iterator &Iter, ValueDecl *D) const;
317
318 /// Checks if the variable is a local for OpenMP region.
319 bool isOpenMPLocal(VarDecl *D, const_iterator Iter) const;
320
321 /// Vector of previously declared requires directives
322 SmallVector<const OMPRequiresDecl *, 2> RequiresDecls;
323 /// omp_allocator_handle_t type.
324 QualType OMPAllocatorHandleT;
325 /// omp_depend_t type.
326 QualType OMPDependT;
327 /// omp_event_handle_t type.
328 QualType OMPEventHandleT;
329 /// omp_alloctrait_t type.
330 QualType OMPAlloctraitT;
331 /// Expression for the predefined allocators.
332 Expr *OMPPredefinedAllocators[OMPAllocateDeclAttr::OMPUserDefinedMemAlloc] = {
333 nullptr};
334 /// Vector of previously encountered target directives
335 SmallVector<SourceLocation, 2> TargetLocations;
336 SourceLocation AtomicLocation;
337 /// Vector of declare variant construct traits.
338 SmallVector<llvm::omp::TraitProperty, 8> ConstructTraits;
339
340public:
341 explicit DSAStackTy(Sema &S) : SemaRef(S) {}
342
343 /// Sets omp_allocator_handle_t type.
344 void setOMPAllocatorHandleT(QualType Ty) { OMPAllocatorHandleT = Ty; }
345 /// Gets omp_allocator_handle_t type.
346 QualType getOMPAllocatorHandleT() const { return OMPAllocatorHandleT; }
347 /// Sets omp_alloctrait_t type.
348 void setOMPAlloctraitT(QualType Ty) { OMPAlloctraitT = Ty; }
349 /// Gets omp_alloctrait_t type.
350 QualType getOMPAlloctraitT() const { return OMPAlloctraitT; }
351 /// Sets the given default allocator.
352 void setAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
353 Expr *Allocator) {
354 OMPPredefinedAllocators[AllocatorKind] = Allocator;
355 }
356 /// Returns the specified default allocator.
357 Expr *getAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind) const {
358 return OMPPredefinedAllocators[AllocatorKind];
359 }
360 /// Sets omp_depend_t type.
361 void setOMPDependT(QualType Ty) { OMPDependT = Ty; }
362 /// Gets omp_depend_t type.
363 QualType getOMPDependT() const { return OMPDependT; }
364
365 /// Sets omp_event_handle_t type.
366 void setOMPEventHandleT(QualType Ty) { OMPEventHandleT = Ty; }
367 /// Gets omp_event_handle_t type.
368 QualType getOMPEventHandleT() const { return OMPEventHandleT; }
369
370 bool isClauseParsingMode() const { return ClauseKindMode != OMPC_unknown; }
371 OpenMPClauseKind getClauseParsingMode() const {
372 assert(isClauseParsingMode() && "Must be in clause parsing mode.")(static_cast <bool> (isClauseParsingMode() && "Must be in clause parsing mode."
) ? void (0) : __assert_fail ("isClauseParsingMode() && \"Must be in clause parsing mode.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 372, __extension__ __PRETTY_FUNCTION__
))
;
373 return ClauseKindMode;
374 }
375 void setClauseParsingMode(OpenMPClauseKind K) { ClauseKindMode = K; }
376
377 bool isBodyComplete() const {
378 const SharingMapTy *Top = getTopOfStackOrNull();
379 return Top && Top->BodyComplete;
380 }
381 void setBodyComplete() { getTopOfStack().BodyComplete = true; }
382
383 bool isForceVarCapturing() const { return ForceCapturing; }
384 void setForceVarCapturing(bool V) { ForceCapturing = V; }
385
386 void setForceCaptureByReferenceInTargetExecutable(bool V) {
387 ForceCaptureByReferenceInTargetExecutable = V;
388 }
389 bool isForceCaptureByReferenceInTargetExecutable() const {
390 return ForceCaptureByReferenceInTargetExecutable;
391 }
392
393 void push(OpenMPDirectiveKind DKind, const DeclarationNameInfo &DirName,
394 Scope *CurScope, SourceLocation Loc) {
395 assert(!IgnoredStackElements &&(static_cast <bool> (!IgnoredStackElements && "cannot change stack while ignoring elements"
) ? void (0) : __assert_fail ("!IgnoredStackElements && \"cannot change stack while ignoring elements\""
, "clang/lib/Sema/SemaOpenMP.cpp", 396, __extension__ __PRETTY_FUNCTION__
))
396 "cannot change stack while ignoring elements")(static_cast <bool> (!IgnoredStackElements && "cannot change stack while ignoring elements"
) ? void (0) : __assert_fail ("!IgnoredStackElements && \"cannot change stack while ignoring elements\""
, "clang/lib/Sema/SemaOpenMP.cpp", 396, __extension__ __PRETTY_FUNCTION__
))
;
397 if (Stack.empty() ||
398 Stack.back().second != CurrentNonCapturingFunctionScope)
399 Stack.emplace_back(StackTy(), CurrentNonCapturingFunctionScope);
400 Stack.back().first.emplace_back(DKind, DirName, CurScope, Loc);
401 Stack.back().first.back().DefaultAttrLoc = Loc;
402 }
403
404 void pop() {
405 assert(!IgnoredStackElements &&(static_cast <bool> (!IgnoredStackElements && "cannot change stack while ignoring elements"
) ? void (0) : __assert_fail ("!IgnoredStackElements && \"cannot change stack while ignoring elements\""
, "clang/lib/Sema/SemaOpenMP.cpp", 406, __extension__ __PRETTY_FUNCTION__
))
406 "cannot change stack while ignoring elements")(static_cast <bool> (!IgnoredStackElements && "cannot change stack while ignoring elements"
) ? void (0) : __assert_fail ("!IgnoredStackElements && \"cannot change stack while ignoring elements\""
, "clang/lib/Sema/SemaOpenMP.cpp", 406, __extension__ __PRETTY_FUNCTION__
))
;
407 assert(!Stack.back().first.empty() &&(static_cast <bool> (!Stack.back().first.empty() &&
"Data-sharing attributes stack is empty!") ? void (0) : __assert_fail
("!Stack.back().first.empty() && \"Data-sharing attributes stack is empty!\""
, "clang/lib/Sema/SemaOpenMP.cpp", 408, __extension__ __PRETTY_FUNCTION__
))
408 "Data-sharing attributes stack is empty!")(static_cast <bool> (!Stack.back().first.empty() &&
"Data-sharing attributes stack is empty!") ? void (0) : __assert_fail
("!Stack.back().first.empty() && \"Data-sharing attributes stack is empty!\""
, "clang/lib/Sema/SemaOpenMP.cpp", 408, __extension__ __PRETTY_FUNCTION__
))
;
409 Stack.back().first.pop_back();
410 }
411
412 /// RAII object to temporarily leave the scope of a directive when we want to
413 /// logically operate in its parent.
414 class ParentDirectiveScope {
415 DSAStackTy &Self;
416 bool Active;
417
418 public:
419 ParentDirectiveScope(DSAStackTy &Self, bool Activate)
420 : Self(Self), Active(false) {
421 if (Activate)
422 enable();
423 }
424 ~ParentDirectiveScope() { disable(); }
425 void disable() {
426 if (Active) {
427 --Self.IgnoredStackElements;
428 Active = false;
429 }
430 }
431 void enable() {
432 if (!Active) {
433 ++Self.IgnoredStackElements;
434 Active = true;
435 }
436 }
437 };
438
439 /// Marks that we're started loop parsing.
440 void loopInit() {
441 assert(isOpenMPLoopDirective(getCurrentDirective()) &&(static_cast <bool> (isOpenMPLoopDirective(getCurrentDirective
()) && "Expected loop-based directive.") ? void (0) :
__assert_fail ("isOpenMPLoopDirective(getCurrentDirective()) && \"Expected loop-based directive.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 442, __extension__ __PRETTY_FUNCTION__
))
442 "Expected loop-based directive.")(static_cast <bool> (isOpenMPLoopDirective(getCurrentDirective
()) && "Expected loop-based directive.") ? void (0) :
__assert_fail ("isOpenMPLoopDirective(getCurrentDirective()) && \"Expected loop-based directive.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 442, __extension__ __PRETTY_FUNCTION__
))
;
443 getTopOfStack().LoopStart = true;
444 }
445 /// Start capturing of the variables in the loop context.
446 void loopStart() {
447 assert(isOpenMPLoopDirective(getCurrentDirective()) &&(static_cast <bool> (isOpenMPLoopDirective(getCurrentDirective
()) && "Expected loop-based directive.") ? void (0) :
__assert_fail ("isOpenMPLoopDirective(getCurrentDirective()) && \"Expected loop-based directive.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 448, __extension__ __PRETTY_FUNCTION__
))
448 "Expected loop-based directive.")(static_cast <bool> (isOpenMPLoopDirective(getCurrentDirective
()) && "Expected loop-based directive.") ? void (0) :
__assert_fail ("isOpenMPLoopDirective(getCurrentDirective()) && \"Expected loop-based directive.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 448, __extension__ __PRETTY_FUNCTION__
))
;
449 getTopOfStack().LoopStart = false;
450 }
451 /// true, if variables are captured, false otherwise.
452 bool isLoopStarted() const {
453 assert(isOpenMPLoopDirective(getCurrentDirective()) &&(static_cast <bool> (isOpenMPLoopDirective(getCurrentDirective
()) && "Expected loop-based directive.") ? void (0) :
__assert_fail ("isOpenMPLoopDirective(getCurrentDirective()) && \"Expected loop-based directive.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 454, __extension__ __PRETTY_FUNCTION__
))
454 "Expected loop-based directive.")(static_cast <bool> (isOpenMPLoopDirective(getCurrentDirective
()) && "Expected loop-based directive.") ? void (0) :
__assert_fail ("isOpenMPLoopDirective(getCurrentDirective()) && \"Expected loop-based directive.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 454, __extension__ __PRETTY_FUNCTION__
))
;
455 return !getTopOfStack().LoopStart;
456 }
457 /// Marks (or clears) declaration as possibly loop counter.
458 void resetPossibleLoopCounter(const Decl *D = nullptr) {
459 getTopOfStack().PossiblyLoopCounter = D ? D->getCanonicalDecl() : D;
460 }
461 /// Gets the possible loop counter decl.
462 const Decl *getPossiblyLoopCunter() const {
463 return getTopOfStack().PossiblyLoopCounter;
464 }
465 /// Start new OpenMP region stack in new non-capturing function.
466 void pushFunction() {
467 assert(!IgnoredStackElements &&(static_cast <bool> (!IgnoredStackElements && "cannot change stack while ignoring elements"
) ? void (0) : __assert_fail ("!IgnoredStackElements && \"cannot change stack while ignoring elements\""
, "clang/lib/Sema/SemaOpenMP.cpp", 468, __extension__ __PRETTY_FUNCTION__
))
468 "cannot change stack while ignoring elements")(static_cast <bool> (!IgnoredStackElements && "cannot change stack while ignoring elements"
) ? void (0) : __assert_fail ("!IgnoredStackElements && \"cannot change stack while ignoring elements\""
, "clang/lib/Sema/SemaOpenMP.cpp", 468, __extension__ __PRETTY_FUNCTION__
))
;
469 const FunctionScopeInfo *CurFnScope = SemaRef.getCurFunction();
470 assert(!isa<CapturingScopeInfo>(CurFnScope))(static_cast <bool> (!isa<CapturingScopeInfo>(CurFnScope
)) ? void (0) : __assert_fail ("!isa<CapturingScopeInfo>(CurFnScope)"
, "clang/lib/Sema/SemaOpenMP.cpp", 470, __extension__ __PRETTY_FUNCTION__
))
;
471 CurrentNonCapturingFunctionScope = CurFnScope;
472 }
473 /// Pop region stack for non-capturing function.
474 void popFunction(const FunctionScopeInfo *OldFSI) {
475 assert(!IgnoredStackElements &&(static_cast <bool> (!IgnoredStackElements && "cannot change stack while ignoring elements"
) ? void (0) : __assert_fail ("!IgnoredStackElements && \"cannot change stack while ignoring elements\""
, "clang/lib/Sema/SemaOpenMP.cpp", 476, __extension__ __PRETTY_FUNCTION__
))
476 "cannot change stack while ignoring elements")(static_cast <bool> (!IgnoredStackElements && "cannot change stack while ignoring elements"
) ? void (0) : __assert_fail ("!IgnoredStackElements && \"cannot change stack while ignoring elements\""
, "clang/lib/Sema/SemaOpenMP.cpp", 476, __extension__ __PRETTY_FUNCTION__
))
;
477 if (!Stack.empty() && Stack.back().second == OldFSI) {
478 assert(Stack.back().first.empty())(static_cast <bool> (Stack.back().first.empty()) ? void
(0) : __assert_fail ("Stack.back().first.empty()", "clang/lib/Sema/SemaOpenMP.cpp"
, 478, __extension__ __PRETTY_FUNCTION__))
;
479 Stack.pop_back();
480 }
481 CurrentNonCapturingFunctionScope = nullptr;
482 for (const FunctionScopeInfo *FSI : llvm::reverse(SemaRef.FunctionScopes)) {
483 if (!isa<CapturingScopeInfo>(FSI)) {
484 CurrentNonCapturingFunctionScope = FSI;
485 break;
486 }
487 }
488 }
489
490 void addCriticalWithHint(const OMPCriticalDirective *D, llvm::APSInt Hint) {
491 Criticals.try_emplace(D->getDirectiveName().getAsString(), D, Hint);
492 }
493 const std::pair<const OMPCriticalDirective *, llvm::APSInt>
494 getCriticalWithHint(const DeclarationNameInfo &Name) const {
495 auto I = Criticals.find(Name.getAsString());
496 if (I != Criticals.end())
497 return I->second;
498 return std::make_pair(nullptr, llvm::APSInt());
499 }
500 /// If 'aligned' declaration for given variable \a D was not seen yet,
501 /// add it and return NULL; otherwise return previous occurrence's expression
502 /// for diagnostics.
503 const Expr *addUniqueAligned(const ValueDecl *D, const Expr *NewDE);
504 /// If 'nontemporal' declaration for given variable \a D was not seen yet,
505 /// add it and return NULL; otherwise return previous occurrence's expression
506 /// for diagnostics.
507 const Expr *addUniqueNontemporal(const ValueDecl *D, const Expr *NewDE);
508
509 /// Register specified variable as loop control variable.
510 void addLoopControlVariable(const ValueDecl *D, VarDecl *Capture);
511 /// Check if the specified variable is a loop control variable for
512 /// current region.
513 /// \return The index of the loop control variable in the list of associated
514 /// for-loops (from outer to inner).
515 const LCDeclInfo isLoopControlVariable(const ValueDecl *D) const;
516 /// Check if the specified variable is a loop control variable for
517 /// parent region.
518 /// \return The index of the loop control variable in the list of associated
519 /// for-loops (from outer to inner).
520 const LCDeclInfo isParentLoopControlVariable(const ValueDecl *D) const;
521 /// Check if the specified variable is a loop control variable for
522 /// current region.
523 /// \return The index of the loop control variable in the list of associated
524 /// for-loops (from outer to inner).
525 const LCDeclInfo isLoopControlVariable(const ValueDecl *D,
526 unsigned Level) const;
527 /// Get the loop control variable for the I-th loop (or nullptr) in
528 /// parent directive.
529 const ValueDecl *getParentLoopControlVariable(unsigned I) const;
530
531 /// Marks the specified decl \p D as used in scan directive.
532 void markDeclAsUsedInScanDirective(ValueDecl *D) {
533 if (SharingMapTy *Stack = getSecondOnStackOrNull())
534 Stack->UsedInScanDirective.insert(D);
535 }
536
537 /// Checks if the specified declaration was used in the inner scan directive.
538 bool isUsedInScanDirective(ValueDecl *D) const {
539 if (const SharingMapTy *Stack = getTopOfStackOrNull())
540 return Stack->UsedInScanDirective.contains(D);
541 return false;
542 }
543
544 /// Adds explicit data sharing attribute to the specified declaration.
545 void addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
546 DeclRefExpr *PrivateCopy = nullptr, unsigned Modifier = 0,
547 bool AppliedToPointee = false);
548
549 /// Adds additional information for the reduction items with the reduction id
550 /// represented as an operator.
551 void addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
552 BinaryOperatorKind BOK);
553 /// Adds additional information for the reduction items with the reduction id
554 /// represented as reduction identifier.
555 void addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
556 const Expr *ReductionRef);
557 /// Returns the location and reduction operation from the innermost parent
558 /// region for the given \p D.
559 const DSAVarData
560 getTopMostTaskgroupReductionData(const ValueDecl *D, SourceRange &SR,
561 BinaryOperatorKind &BOK,
562 Expr *&TaskgroupDescriptor) const;
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 const Expr *&ReductionRef,
568 Expr *&TaskgroupDescriptor) const;
569 /// Return reduction reference expression for the current taskgroup or
570 /// parallel/worksharing directives with task reductions.
571 Expr *getTaskgroupReductionRef() const {
572 assert((getTopOfStack().Directive == OMPD_taskgroup ||(static_cast <bool> ((getTopOfStack().Directive == OMPD_taskgroup
|| ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
!isOpenMPSimdDirective(getTopOfStack().Directive))) &&
"taskgroup reference expression requested for non taskgroup or "
"parallel/worksharing directive.") ? void (0) : __assert_fail
("(getTopOfStack().Directive == OMPD_taskgroup || ((isOpenMPParallelDirective(getTopOfStack().Directive) || isOpenMPWorksharingDirective(getTopOfStack().Directive)) && !isOpenMPSimdDirective(getTopOfStack().Directive))) && \"taskgroup reference expression requested for non taskgroup or \" \"parallel/worksharing directive.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 577, __extension__ __PRETTY_FUNCTION__
))
573 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||(static_cast <bool> ((getTopOfStack().Directive == OMPD_taskgroup
|| ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
!isOpenMPSimdDirective(getTopOfStack().Directive))) &&
"taskgroup reference expression requested for non taskgroup or "
"parallel/worksharing directive.") ? void (0) : __assert_fail
("(getTopOfStack().Directive == OMPD_taskgroup || ((isOpenMPParallelDirective(getTopOfStack().Directive) || isOpenMPWorksharingDirective(getTopOfStack().Directive)) && !isOpenMPSimdDirective(getTopOfStack().Directive))) && \"taskgroup reference expression requested for non taskgroup or \" \"parallel/worksharing directive.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 577, __extension__ __PRETTY_FUNCTION__
))
574 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&(static_cast <bool> ((getTopOfStack().Directive == OMPD_taskgroup
|| ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
!isOpenMPSimdDirective(getTopOfStack().Directive))) &&
"taskgroup reference expression requested for non taskgroup or "
"parallel/worksharing directive.") ? void (0) : __assert_fail
("(getTopOfStack().Directive == OMPD_taskgroup || ((isOpenMPParallelDirective(getTopOfStack().Directive) || isOpenMPWorksharingDirective(getTopOfStack().Directive)) && !isOpenMPSimdDirective(getTopOfStack().Directive))) && \"taskgroup reference expression requested for non taskgroup or \" \"parallel/worksharing directive.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 577, __extension__ __PRETTY_FUNCTION__
))
575 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&(static_cast <bool> ((getTopOfStack().Directive == OMPD_taskgroup
|| ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
!isOpenMPSimdDirective(getTopOfStack().Directive))) &&
"taskgroup reference expression requested for non taskgroup or "
"parallel/worksharing directive.") ? void (0) : __assert_fail
("(getTopOfStack().Directive == OMPD_taskgroup || ((isOpenMPParallelDirective(getTopOfStack().Directive) || isOpenMPWorksharingDirective(getTopOfStack().Directive)) && !isOpenMPSimdDirective(getTopOfStack().Directive))) && \"taskgroup reference expression requested for non taskgroup or \" \"parallel/worksharing directive.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 577, __extension__ __PRETTY_FUNCTION__
))
576 "taskgroup reference expression requested for non taskgroup or "(static_cast <bool> ((getTopOfStack().Directive == OMPD_taskgroup
|| ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
!isOpenMPSimdDirective(getTopOfStack().Directive))) &&
"taskgroup reference expression requested for non taskgroup or "
"parallel/worksharing directive.") ? void (0) : __assert_fail
("(getTopOfStack().Directive == OMPD_taskgroup || ((isOpenMPParallelDirective(getTopOfStack().Directive) || isOpenMPWorksharingDirective(getTopOfStack().Directive)) && !isOpenMPSimdDirective(getTopOfStack().Directive))) && \"taskgroup reference expression requested for non taskgroup or \" \"parallel/worksharing directive.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 577, __extension__ __PRETTY_FUNCTION__
))
577 "parallel/worksharing directive.")(static_cast <bool> ((getTopOfStack().Directive == OMPD_taskgroup
|| ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
!isOpenMPSimdDirective(getTopOfStack().Directive))) &&
"taskgroup reference expression requested for non taskgroup or "
"parallel/worksharing directive.") ? void (0) : __assert_fail
("(getTopOfStack().Directive == OMPD_taskgroup || ((isOpenMPParallelDirective(getTopOfStack().Directive) || isOpenMPWorksharingDirective(getTopOfStack().Directive)) && !isOpenMPSimdDirective(getTopOfStack().Directive))) && \"taskgroup reference expression requested for non taskgroup or \" \"parallel/worksharing directive.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 577, __extension__ __PRETTY_FUNCTION__
))
;
578 return getTopOfStack().TaskgroupReductionRef;
579 }
580 /// Checks if the given \p VD declaration is actually a taskgroup reduction
581 /// descriptor variable at the \p Level of OpenMP regions.
582 bool isTaskgroupReductionRef(const ValueDecl *VD, unsigned Level) const {
583 return getStackElemAtLevel(Level).TaskgroupReductionRef &&
584 cast<DeclRefExpr>(getStackElemAtLevel(Level).TaskgroupReductionRef)
585 ->getDecl() == VD;
586 }
587
588 /// Returns data sharing attributes from top of the stack for the
589 /// specified declaration.
590 const DSAVarData getTopDSA(ValueDecl *D, bool FromParent);
591 /// Returns data-sharing attributes for the specified declaration.
592 const DSAVarData getImplicitDSA(ValueDecl *D, bool FromParent) const;
593 /// Returns data-sharing attributes for the specified declaration.
594 const DSAVarData getImplicitDSA(ValueDecl *D, unsigned Level) const;
595 /// Checks if the specified variables has data-sharing attributes which
596 /// match specified \a CPred predicate in any directive which matches \a DPred
597 /// predicate.
598 const DSAVarData
599 hasDSA(ValueDecl *D,
600 const llvm::function_ref<bool(OpenMPClauseKind, bool,
601 DefaultDataSharingAttributes)>
602 CPred,
603 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
604 bool FromParent) const;
605 /// Checks if the specified variables has data-sharing attributes which
606 /// match specified \a CPred predicate in any innermost directive which
607 /// matches \a DPred predicate.
608 const DSAVarData
609 hasInnermostDSA(ValueDecl *D,
610 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
611 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
612 bool FromParent) const;
613 /// Checks if the specified variables has explicit data-sharing
614 /// attributes which match specified \a CPred predicate at the specified
615 /// OpenMP region.
616 bool
617 hasExplicitDSA(const ValueDecl *D,
618 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
619 unsigned Level, bool NotLastprivate = false) const;
620
621 /// Returns true if the directive at level \Level matches in the
622 /// specified \a DPred predicate.
623 bool hasExplicitDirective(
624 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
625 unsigned Level) const;
626
627 /// Finds a directive which matches specified \a DPred predicate.
628 bool hasDirective(
629 const llvm::function_ref<bool(
630 OpenMPDirectiveKind, const DeclarationNameInfo &, SourceLocation)>
631 DPred,
632 bool FromParent) const;
633
634 /// Returns currently analyzed directive.
635 OpenMPDirectiveKind getCurrentDirective() const {
636 const SharingMapTy *Top = getTopOfStackOrNull();
637 return Top ? Top->Directive : OMPD_unknown;
638 }
639 /// Returns directive kind at specified level.
640 OpenMPDirectiveKind getDirective(unsigned Level) const {
641 assert(!isStackEmpty() && "No directive at specified level.")(static_cast <bool> (!isStackEmpty() && "No directive at specified level."
) ? void (0) : __assert_fail ("!isStackEmpty() && \"No directive at specified level.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 641, __extension__ __PRETTY_FUNCTION__
))
;
642 return getStackElemAtLevel(Level).Directive;
643 }
644 /// Returns the capture region at the specified level.
645 OpenMPDirectiveKind getCaptureRegion(unsigned Level,
646 unsigned OpenMPCaptureLevel) const {
647 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
648 getOpenMPCaptureRegions(CaptureRegions, getDirective(Level));
649 return CaptureRegions[OpenMPCaptureLevel];
650 }
651 /// Returns parent directive.
652 OpenMPDirectiveKind getParentDirective() const {
653 const SharingMapTy *Parent = getSecondOnStackOrNull();
654 return Parent ? Parent->Directive : OMPD_unknown;
655 }
656
657 /// Add requires decl to internal vector
658 void addRequiresDecl(OMPRequiresDecl *RD) { RequiresDecls.push_back(RD); }
659
660 /// Checks if the defined 'requires' directive has specified type of clause.
661 template <typename ClauseType> bool hasRequiresDeclWithClause() const {
662 return llvm::any_of(RequiresDecls, [](const OMPRequiresDecl *D) {
663 return llvm::any_of(D->clauselists(), [](const OMPClause *C) {
664 return isa<ClauseType>(C);
665 });
666 });
667 }
668
669 /// Checks for a duplicate clause amongst previously declared requires
670 /// directives
671 bool hasDuplicateRequiresClause(ArrayRef<OMPClause *> ClauseList) const {
672 bool IsDuplicate = false;
673 for (OMPClause *CNew : ClauseList) {
674 for (const OMPRequiresDecl *D : RequiresDecls) {
675 for (const OMPClause *CPrev : D->clauselists()) {
676 if (CNew->getClauseKind() == CPrev->getClauseKind()) {
677 SemaRef.Diag(CNew->getBeginLoc(),
678 diag::err_omp_requires_clause_redeclaration)
679 << getOpenMPClauseName(CNew->getClauseKind());
680 SemaRef.Diag(CPrev->getBeginLoc(),
681 diag::note_omp_requires_previous_clause)
682 << getOpenMPClauseName(CPrev->getClauseKind());
683 IsDuplicate = true;
684 }
685 }
686 }
687 }
688 return IsDuplicate;
689 }
690
691 /// Add location of previously encountered target to internal vector
692 void addTargetDirLocation(SourceLocation LocStart) {
693 TargetLocations.push_back(LocStart);
694 }
695
696 /// Add location for the first encountered atomicc directive.
697 void addAtomicDirectiveLoc(SourceLocation Loc) {
698 if (AtomicLocation.isInvalid())
699 AtomicLocation = Loc;
700 }
701
702 /// Returns the location of the first encountered atomic directive in the
703 /// module.
704 SourceLocation getAtomicDirectiveLoc() const { return AtomicLocation; }
705
706 // Return previously encountered target region locations.
707 ArrayRef<SourceLocation> getEncounteredTargetLocs() const {
708 return TargetLocations;
709 }
710
711 /// Set default data sharing attribute to none.
712 void setDefaultDSANone(SourceLocation Loc) {
713 getTopOfStack().DefaultAttr = DSA_none;
714 getTopOfStack().DefaultAttrLoc = Loc;
715 }
716 /// Set default data sharing attribute to shared.
717 void setDefaultDSAShared(SourceLocation Loc) {
718 getTopOfStack().DefaultAttr = DSA_shared;
719 getTopOfStack().DefaultAttrLoc = Loc;
720 }
721 /// Set default data sharing attribute to private.
722 void setDefaultDSAPrivate(SourceLocation Loc) {
723 getTopOfStack().DefaultAttr = DSA_private;
724 getTopOfStack().DefaultAttrLoc = Loc;
725 }
726 /// Set default data sharing attribute to firstprivate.
727 void setDefaultDSAFirstPrivate(SourceLocation Loc) {
728 getTopOfStack().DefaultAttr = DSA_firstprivate;
729 getTopOfStack().DefaultAttrLoc = Loc;
730 }
731 /// Set default data mapping attribute to Modifier:Kind
732 void setDefaultDMAAttr(OpenMPDefaultmapClauseModifier M,
733 OpenMPDefaultmapClauseKind Kind, SourceLocation Loc) {
734 DefaultmapInfo &DMI = getTopOfStack().DefaultmapMap[Kind];
735 DMI.ImplicitBehavior = M;
736 DMI.SLoc = Loc;
737 }
738 /// Check whether the implicit-behavior has been set in defaultmap
739 bool checkDefaultmapCategory(OpenMPDefaultmapClauseKind VariableCategory) {
740 if (VariableCategory == OMPC_DEFAULTMAP_unknown)
741 return getTopOfStack()
742 .DefaultmapMap[OMPC_DEFAULTMAP_aggregate]
743 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown ||
744 getTopOfStack()
745 .DefaultmapMap[OMPC_DEFAULTMAP_scalar]
746 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown ||
747 getTopOfStack()
748 .DefaultmapMap[OMPC_DEFAULTMAP_pointer]
749 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown;
750 return getTopOfStack().DefaultmapMap[VariableCategory].ImplicitBehavior !=
751 OMPC_DEFAULTMAP_MODIFIER_unknown;
752 }
753
754 ArrayRef<llvm::omp::TraitProperty> getConstructTraits() {
755 return ConstructTraits;
756 }
757 void handleConstructTrait(ArrayRef<llvm::omp::TraitProperty> Traits,
758 bool ScopeEntry) {
759 if (ScopeEntry)
760 ConstructTraits.append(Traits.begin(), Traits.end());
761 else
762 for (llvm::omp::TraitProperty Trait : llvm::reverse(Traits)) {
763 llvm::omp::TraitProperty Top = ConstructTraits.pop_back_val();
764 assert(Top == Trait && "Something left a trait on the stack!")(static_cast <bool> (Top == Trait && "Something left a trait on the stack!"
) ? void (0) : __assert_fail ("Top == Trait && \"Something left a trait on the stack!\""
, "clang/lib/Sema/SemaOpenMP.cpp", 764, __extension__ __PRETTY_FUNCTION__
))
;
765 (void)Trait;
766 (void)Top;
767 }
768 }
769
770 DefaultDataSharingAttributes getDefaultDSA(unsigned Level) const {
771 return getStackSize() <= Level ? DSA_unspecified
772 : getStackElemAtLevel(Level).DefaultAttr;
773 }
774 DefaultDataSharingAttributes getDefaultDSA() const {
775 return isStackEmpty() ? DSA_unspecified : getTopOfStack().DefaultAttr;
776 }
777 SourceLocation getDefaultDSALocation() const {
778 return isStackEmpty() ? SourceLocation() : getTopOfStack().DefaultAttrLoc;
779 }
780 OpenMPDefaultmapClauseModifier
781 getDefaultmapModifier(OpenMPDefaultmapClauseKind Kind) const {
782 return isStackEmpty()
783 ? OMPC_DEFAULTMAP_MODIFIER_unknown
784 : getTopOfStack().DefaultmapMap[Kind].ImplicitBehavior;
785 }
786 OpenMPDefaultmapClauseModifier
787 getDefaultmapModifierAtLevel(unsigned Level,
788 OpenMPDefaultmapClauseKind Kind) const {
789 return getStackElemAtLevel(Level).DefaultmapMap[Kind].ImplicitBehavior;
790 }
791 bool isDefaultmapCapturedByRef(unsigned Level,
792 OpenMPDefaultmapClauseKind Kind) const {
793 OpenMPDefaultmapClauseModifier M =
794 getDefaultmapModifierAtLevel(Level, Kind);
795 if (Kind == OMPC_DEFAULTMAP_scalar || Kind == OMPC_DEFAULTMAP_pointer) {
796 return (M == OMPC_DEFAULTMAP_MODIFIER_alloc) ||
797 (M == OMPC_DEFAULTMAP_MODIFIER_to) ||
798 (M == OMPC_DEFAULTMAP_MODIFIER_from) ||
799 (M == OMPC_DEFAULTMAP_MODIFIER_tofrom);
800 }
801 return true;
802 }
803 static bool mustBeFirstprivateBase(OpenMPDefaultmapClauseModifier M,
804 OpenMPDefaultmapClauseKind Kind) {
805 switch (Kind) {
806 case OMPC_DEFAULTMAP_scalar:
807 case OMPC_DEFAULTMAP_pointer:
808 return (M == OMPC_DEFAULTMAP_MODIFIER_unknown) ||
809 (M == OMPC_DEFAULTMAP_MODIFIER_firstprivate) ||
810 (M == OMPC_DEFAULTMAP_MODIFIER_default);
811 case OMPC_DEFAULTMAP_aggregate:
812 return M == OMPC_DEFAULTMAP_MODIFIER_firstprivate;
813 default:
814 break;
815 }
816 llvm_unreachable("Unexpected OpenMPDefaultmapClauseKind enum")::llvm::llvm_unreachable_internal("Unexpected OpenMPDefaultmapClauseKind enum"
, "clang/lib/Sema/SemaOpenMP.cpp", 816)
;
817 }
818 bool mustBeFirstprivateAtLevel(unsigned Level,
819 OpenMPDefaultmapClauseKind Kind) const {
820 OpenMPDefaultmapClauseModifier M =
821 getDefaultmapModifierAtLevel(Level, Kind);
822 return mustBeFirstprivateBase(M, Kind);
823 }
824 bool mustBeFirstprivate(OpenMPDefaultmapClauseKind Kind) const {
825 OpenMPDefaultmapClauseModifier M = getDefaultmapModifier(Kind);
826 return mustBeFirstprivateBase(M, Kind);
827 }
828
829 /// Checks if the specified variable is a threadprivate.
830 bool isThreadPrivate(VarDecl *D) {
831 const DSAVarData DVar = getTopDSA(D, false);
832 return isOpenMPThreadPrivate(DVar.CKind);
833 }
834
835 /// Marks current region as ordered (it has an 'ordered' clause).
836 void setOrderedRegion(bool IsOrdered, const Expr *Param,
837 OMPOrderedClause *Clause) {
838 if (IsOrdered)
839 getTopOfStack().OrderedRegion.emplace(Param, Clause);
840 else
841 getTopOfStack().OrderedRegion.reset();
842 }
843 /// Returns true, if region is ordered (has associated 'ordered' clause),
844 /// false - otherwise.
845 bool isOrderedRegion() const {
846 if (const SharingMapTy *Top = getTopOfStackOrNull())
847 return Top->OrderedRegion.has_value();
848 return false;
849 }
850 /// Returns optional parameter for the ordered region.
851 std::pair<const Expr *, OMPOrderedClause *> getOrderedRegionParam() const {
852 if (const SharingMapTy *Top = getTopOfStackOrNull())
853 if (Top->OrderedRegion)
854 return *Top->OrderedRegion;
855 return std::make_pair(nullptr, nullptr);
856 }
857 /// Returns true, if parent region is ordered (has associated
858 /// 'ordered' clause), false - otherwise.
859 bool isParentOrderedRegion() const {
860 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
861 return Parent->OrderedRegion.has_value();
862 return false;
863 }
864 /// Returns optional parameter for the ordered region.
865 std::pair<const Expr *, OMPOrderedClause *>
866 getParentOrderedRegionParam() const {
867 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
868 if (Parent->OrderedRegion)
869 return *Parent->OrderedRegion;
870 return std::make_pair(nullptr, nullptr);
871 }
872 /// Marks current region as having an 'order' clause.
873 void setRegionHasOrderConcurrent(bool HasOrderConcurrent) {
874 getTopOfStack().RegionHasOrderConcurrent = HasOrderConcurrent;
875 }
876 /// Returns true, if parent region is order (has associated
877 /// 'order' clause), false - otherwise.
878 bool isParentOrderConcurrent() const {
879 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
880 return Parent->RegionHasOrderConcurrent;
881 return false;
882 }
883 /// Marks current region as nowait (it has a 'nowait' clause).
884 void setNowaitRegion(bool IsNowait = true) {
885 getTopOfStack().NowaitRegion = IsNowait;
886 }
887 /// Returns true, if parent region is nowait (has associated
888 /// 'nowait' clause), false - otherwise.
889 bool isParentNowaitRegion() const {
890 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
891 return Parent->NowaitRegion;
892 return false;
893 }
894 /// Marks current region as untied (it has a 'untied' clause).
895 void setUntiedRegion(bool IsUntied = true) {
896 getTopOfStack().UntiedRegion = IsUntied;
897 }
898 /// Return true if current region is untied.
899 bool isUntiedRegion() const {
900 const SharingMapTy *Top = getTopOfStackOrNull();
901 return Top ? Top->UntiedRegion : false;
902 }
903 /// Marks parent region as cancel region.
904 void setParentCancelRegion(bool Cancel = true) {
905 if (SharingMapTy *Parent = getSecondOnStackOrNull())
906 Parent->CancelRegion |= Cancel;
907 }
908 /// Return true if current region has inner cancel construct.
909 bool isCancelRegion() const {
910 const SharingMapTy *Top = getTopOfStackOrNull();
911 return Top ? Top->CancelRegion : false;
912 }
913
914 /// Mark that parent region already has scan directive.
915 void setParentHasScanDirective(SourceLocation Loc) {
916 if (SharingMapTy *Parent = getSecondOnStackOrNull())
917 Parent->PrevScanLocation = Loc;
918 }
919 /// Return true if current region has inner cancel construct.
920 bool doesParentHasScanDirective() const {
921 const SharingMapTy *Top = getSecondOnStackOrNull();
922 return Top ? Top->PrevScanLocation.isValid() : false;
923 }
924 /// Return true if current region has inner cancel construct.
925 SourceLocation getParentScanDirectiveLoc() const {
926 const SharingMapTy *Top = getSecondOnStackOrNull();
927 return Top ? Top->PrevScanLocation : SourceLocation();
928 }
929 /// Mark that parent region already has ordered directive.
930 void setParentHasOrderedDirective(SourceLocation Loc) {
931 if (SharingMapTy *Parent = getSecondOnStackOrNull())
932 Parent->PrevOrderedLocation = Loc;
933 }
934 /// Return true if current region has inner ordered construct.
935 bool doesParentHasOrderedDirective() const {
936 const SharingMapTy *Top = getSecondOnStackOrNull();
937 return Top ? Top->PrevOrderedLocation.isValid() : false;
938 }
939 /// Returns the location of the previously specified ordered directive.
940 SourceLocation getParentOrderedDirectiveLoc() const {
941 const SharingMapTy *Top = getSecondOnStackOrNull();
942 return Top ? Top->PrevOrderedLocation : SourceLocation();
943 }
944
945 /// Set collapse value for the region.
946 void setAssociatedLoops(unsigned Val) {
947 getTopOfStack().AssociatedLoops = Val;
948 if (Val > 1)
949 getTopOfStack().HasMutipleLoops = true;
950 }
951 /// Return collapse value for region.
952 unsigned getAssociatedLoops() const {
953 const SharingMapTy *Top = getTopOfStackOrNull();
954 return Top ? Top->AssociatedLoops : 0;
955 }
956 /// Returns true if the construct is associated with multiple loops.
957 bool hasMutipleLoops() const {
958 const SharingMapTy *Top = getTopOfStackOrNull();
959 return Top ? Top->HasMutipleLoops : false;
960 }
961
962 /// Marks current target region as one with closely nested teams
963 /// region.
964 void setParentTeamsRegionLoc(SourceLocation TeamsRegionLoc) {
965 if (SharingMapTy *Parent = getSecondOnStackOrNull())
966 Parent->InnerTeamsRegionLoc = TeamsRegionLoc;
967 }
968 /// Returns true, if current region has closely nested teams region.
969 bool hasInnerTeamsRegion() const {
970 return getInnerTeamsRegionLoc().isValid();
971 }
972 /// Returns location of the nested teams region (if any).
973 SourceLocation getInnerTeamsRegionLoc() const {
974 const SharingMapTy *Top = getTopOfStackOrNull();
975 return Top ? Top->InnerTeamsRegionLoc : SourceLocation();
976 }
977
978 Scope *getCurScope() const {
979 const SharingMapTy *Top = getTopOfStackOrNull();
980 return Top ? Top->CurScope : nullptr;
981 }
982 void setContext(DeclContext *DC) { getTopOfStack().Context = DC; }
983 SourceLocation getConstructLoc() const {
984 const SharingMapTy *Top = getTopOfStackOrNull();
985 return Top ? Top->ConstructLoc : SourceLocation();
986 }
987
988 /// Do the check specified in \a Check to all component lists and return true
989 /// if any issue is found.
990 bool checkMappableExprComponentListsForDecl(
991 const ValueDecl *VD, bool CurrentRegionOnly,
992 const llvm::function_ref<
993 bool(OMPClauseMappableExprCommon::MappableExprComponentListRef,
994 OpenMPClauseKind)>
995 Check) const {
996 if (isStackEmpty())
997 return false;
998 auto SI = begin();
999 auto SE = end();
1000
1001 if (SI == SE)
1002 return false;
1003
1004 if (CurrentRegionOnly)
1005 SE = std::next(SI);
1006 else
1007 std::advance(SI, 1);
1008
1009 for (; SI != SE; ++SI) {
1010 auto MI = SI->MappedExprComponents.find(VD);
1011 if (MI != SI->MappedExprComponents.end())
1012 for (OMPClauseMappableExprCommon::MappableExprComponentListRef L :
1013 MI->second.Components)
1014 if (Check(L, MI->second.Kind))
1015 return true;
1016 }
1017 return false;
1018 }
1019
1020 /// Do the check specified in \a Check to all component lists at a given level
1021 /// and return true if any issue is found.
1022 bool checkMappableExprComponentListsForDeclAtLevel(
1023 const ValueDecl *VD, unsigned Level,
1024 const llvm::function_ref<
1025 bool(OMPClauseMappableExprCommon::MappableExprComponentListRef,
1026 OpenMPClauseKind)>
1027 Check) const {
1028 if (getStackSize() <= Level)
1029 return false;
1030
1031 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1032 auto MI = StackElem.MappedExprComponents.find(VD);
1033 if (MI != StackElem.MappedExprComponents.end())
1034 for (OMPClauseMappableExprCommon::MappableExprComponentListRef L :
1035 MI->second.Components)
1036 if (Check(L, MI->second.Kind))
1037 return true;
1038 return false;
1039 }
1040
1041 /// Create a new mappable expression component list associated with a given
1042 /// declaration and initialize it with the provided list of components.
1043 void addMappableExpressionComponents(
1044 const ValueDecl *VD,
1045 OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
1046 OpenMPClauseKind WhereFoundClauseKind) {
1047 MappedExprComponentTy &MEC = getTopOfStack().MappedExprComponents[VD];
1048 // Create new entry and append the new components there.
1049 MEC.Components.resize(MEC.Components.size() + 1);
1050 MEC.Components.back().append(Components.begin(), Components.end());
1051 MEC.Kind = WhereFoundClauseKind;
1052 }
1053
1054 unsigned getNestingLevel() const {
1055 assert(!isStackEmpty())(static_cast <bool> (!isStackEmpty()) ? void (0) : __assert_fail
("!isStackEmpty()", "clang/lib/Sema/SemaOpenMP.cpp", 1055, __extension__
__PRETTY_FUNCTION__))
;
1056 return getStackSize() - 1;
1057 }
1058 void addDoacrossDependClause(OMPDependClause *C,
1059 const OperatorOffsetTy &OpsOffs) {
1060 SharingMapTy *Parent = getSecondOnStackOrNull();
1061 assert(Parent && isOpenMPWorksharingDirective(Parent->Directive))(static_cast <bool> (Parent && isOpenMPWorksharingDirective
(Parent->Directive)) ? void (0) : __assert_fail ("Parent && isOpenMPWorksharingDirective(Parent->Directive)"
, "clang/lib/Sema/SemaOpenMP.cpp", 1061, __extension__ __PRETTY_FUNCTION__
))
;
1062 Parent->DoacrossDepends.try_emplace(C, OpsOffs);
1063 }
1064 llvm::iterator_range<DoacrossDependMapTy::const_iterator>
1065 getDoacrossDependClauses() const {
1066 const SharingMapTy &StackElem = getTopOfStack();
1067 if (isOpenMPWorksharingDirective(StackElem.Directive)) {
1068 const DoacrossDependMapTy &Ref = StackElem.DoacrossDepends;
1069 return llvm::make_range(Ref.begin(), Ref.end());
1070 }
1071 return llvm::make_range(StackElem.DoacrossDepends.end(),
1072 StackElem.DoacrossDepends.end());
1073 }
1074
1075 // Store types of classes which have been explicitly mapped
1076 void addMappedClassesQualTypes(QualType QT) {
1077 SharingMapTy &StackElem = getTopOfStack();
1078 StackElem.MappedClassesQualTypes.insert(QT);
1079 }
1080
1081 // Return set of mapped classes types
1082 bool isClassPreviouslyMapped(QualType QT) const {
1083 const SharingMapTy &StackElem = getTopOfStack();
1084 return StackElem.MappedClassesQualTypes.contains(QT);
1085 }
1086
1087 /// Adds global declare target to the parent target region.
1088 void addToParentTargetRegionLinkGlobals(DeclRefExpr *E) {
1089 assert(*OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration((static_cast <bool> (*OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration
( E->getDecl()) == OMPDeclareTargetDeclAttr::MT_Link &&
"Expected declare target link global.") ? void (0) : __assert_fail
("*OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration( E->getDecl()) == OMPDeclareTargetDeclAttr::MT_Link && \"Expected declare target link global.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 1091, __extension__ __PRETTY_FUNCTION__
))
1090 E->getDecl()) == OMPDeclareTargetDeclAttr::MT_Link &&(static_cast <bool> (*OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration
( E->getDecl()) == OMPDeclareTargetDeclAttr::MT_Link &&
"Expected declare target link global.") ? void (0) : __assert_fail
("*OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration( E->getDecl()) == OMPDeclareTargetDeclAttr::MT_Link && \"Expected declare target link global.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 1091, __extension__ __PRETTY_FUNCTION__
))
1091 "Expected declare target link global.")(static_cast <bool> (*OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration
( E->getDecl()) == OMPDeclareTargetDeclAttr::MT_Link &&
"Expected declare target link global.") ? void (0) : __assert_fail
("*OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration( E->getDecl()) == OMPDeclareTargetDeclAttr::MT_Link && \"Expected declare target link global.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 1091, __extension__ __PRETTY_FUNCTION__
))
;
1092 for (auto &Elem : *this) {
1093 if (isOpenMPTargetExecutionDirective(Elem.Directive)) {
1094 Elem.DeclareTargetLinkVarDecls.push_back(E);
1095 return;
1096 }
1097 }
1098 }
1099
1100 /// Returns the list of globals with declare target link if current directive
1101 /// is target.
1102 ArrayRef<DeclRefExpr *> getLinkGlobals() const {
1103 assert(isOpenMPTargetExecutionDirective(getCurrentDirective()) &&(static_cast <bool> (isOpenMPTargetExecutionDirective(getCurrentDirective
()) && "Expected target executable directive.") ? void
(0) : __assert_fail ("isOpenMPTargetExecutionDirective(getCurrentDirective()) && \"Expected target executable directive.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 1104, __extension__ __PRETTY_FUNCTION__
))
1104 "Expected target executable directive.")(static_cast <bool> (isOpenMPTargetExecutionDirective(getCurrentDirective
()) && "Expected target executable directive.") ? void
(0) : __assert_fail ("isOpenMPTargetExecutionDirective(getCurrentDirective()) && \"Expected target executable directive.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 1104, __extension__ __PRETTY_FUNCTION__
))
;
1105 return getTopOfStack().DeclareTargetLinkVarDecls;
1106 }
1107
1108 /// Adds list of allocators expressions.
1109 void addInnerAllocatorExpr(Expr *E) {
1110 getTopOfStack().InnerUsedAllocators.push_back(E);
1111 }
1112 /// Return list of used allocators.
1113 ArrayRef<Expr *> getInnerAllocators() const {
1114 return getTopOfStack().InnerUsedAllocators;
1115 }
1116 /// Marks the declaration as implicitly firstprivate nin the task-based
1117 /// regions.
1118 void addImplicitTaskFirstprivate(unsigned Level, Decl *D) {
1119 getStackElemAtLevel(Level).ImplicitTaskFirstprivates.insert(D);
1120 }
1121 /// Checks if the decl is implicitly firstprivate in the task-based region.
1122 bool isImplicitTaskFirstprivate(Decl *D) const {
1123 return getTopOfStack().ImplicitTaskFirstprivates.contains(D);
1124 }
1125
1126 /// Marks decl as used in uses_allocators clause as the allocator.
1127 void addUsesAllocatorsDecl(const Decl *D, UsesAllocatorsDeclKind Kind) {
1128 getTopOfStack().UsesAllocatorsDecls.try_emplace(D, Kind);
1129 }
1130 /// Checks if specified decl is used in uses allocator clause as the
1131 /// allocator.
1132 std::optional<UsesAllocatorsDeclKind>
1133 isUsesAllocatorsDecl(unsigned Level, const Decl *D) const {
1134 const SharingMapTy &StackElem = getTopOfStack();
1135 auto I = StackElem.UsesAllocatorsDecls.find(D);
1136 if (I == StackElem.UsesAllocatorsDecls.end())
1137 return std::nullopt;
1138 return I->getSecond();
1139 }
1140 std::optional<UsesAllocatorsDeclKind>
1141 isUsesAllocatorsDecl(const Decl *D) const {
1142 const SharingMapTy &StackElem = getTopOfStack();
1143 auto I = StackElem.UsesAllocatorsDecls.find(D);
1144 if (I == StackElem.UsesAllocatorsDecls.end())
1145 return std::nullopt;
1146 return I->getSecond();
1147 }
1148
1149 void addDeclareMapperVarRef(Expr *Ref) {
1150 SharingMapTy &StackElem = getTopOfStack();
1151 StackElem.DeclareMapperVar = Ref;
1152 }
1153 const Expr *getDeclareMapperVarRef() const {
1154 const SharingMapTy *Top = getTopOfStackOrNull();
1155 return Top ? Top->DeclareMapperVar : nullptr;
1156 }
1157
1158 /// Add a new iterator variable.
1159 void addIteratorVarDecl(VarDecl *VD) {
1160 SharingMapTy &StackElem = getTopOfStack();
1161 StackElem.IteratorVarDecls.push_back(VD->getCanonicalDecl());
1162 }
1163 /// Check if variable declaration is an iterator VarDecl.
1164 bool isIteratorVarDecl(const VarDecl *VD) const {
1165 const SharingMapTy *Top = getTopOfStackOrNull();
1166 if (!Top)
1167 return false;
1168
1169 return llvm::any_of(Top->IteratorVarDecls, [VD](const VarDecl *IteratorVD) {
1170 return IteratorVD == VD->getCanonicalDecl();
1171 });
1172 }
1173 /// get captured field from ImplicitDefaultFirstprivateFDs
1174 VarDecl *getImplicitFDCapExprDecl(const FieldDecl *FD) const {
1175 const_iterator I = begin();
1176 const_iterator EndI = end();
1177 size_t StackLevel = getStackSize();
1178 for (; I != EndI; ++I) {
1179 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1180 break;
1181 StackLevel--;
1182 }
1183 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI))(static_cast <bool> ((StackLevel > 0 && I !=
EndI) || (StackLevel == 0 && I == EndI)) ? void (0) :
__assert_fail ("(StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI)"
, "clang/lib/Sema/SemaOpenMP.cpp", 1183, __extension__ __PRETTY_FUNCTION__
))
;
1184 if (I == EndI)
1185 return nullptr;
1186 for (const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1187 if (IFD.FD == FD && IFD.StackLevel == StackLevel)
1188 return IFD.VD;
1189 return nullptr;
1190 }
1191 /// Check if capture decl is field captured in ImplicitDefaultFirstprivateFDs
1192 bool isImplicitDefaultFirstprivateFD(VarDecl *VD) const {
1193 const_iterator I = begin();
1194 const_iterator EndI = end();
1195 for (; I != EndI; ++I)
1196 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1197 break;
1198 if (I == EndI)
1199 return false;
1200 for (const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1201 if (IFD.VD == VD)
1202 return true;
1203 return false;
1204 }
1205 /// Store capture FD info in ImplicitDefaultFirstprivateFDs
1206 void addImplicitDefaultFirstprivateFD(const FieldDecl *FD, VarDecl *VD) {
1207 iterator I = begin();
1208 const_iterator EndI = end();
1209 size_t StackLevel = getStackSize();
1210 for (; I != EndI; ++I) {
1211 if (I->DefaultAttr == DSA_private || I->DefaultAttr == DSA_firstprivate) {
1212 I->ImplicitDefaultFirstprivateFDs.emplace_back(FD, StackLevel, VD);
1213 break;
1214 }
1215 StackLevel--;
1216 }
1217 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI))(static_cast <bool> ((StackLevel > 0 && I !=
EndI) || (StackLevel == 0 && I == EndI)) ? void (0) :
__assert_fail ("(StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI)"
, "clang/lib/Sema/SemaOpenMP.cpp", 1217, __extension__ __PRETTY_FUNCTION__
))
;
1218 }
1219};
1220
1221bool isImplicitTaskingRegion(OpenMPDirectiveKind DKind) {
1222 return isOpenMPParallelDirective(DKind) || isOpenMPTeamsDirective(DKind);
1223}
1224
1225bool isImplicitOrExplicitTaskingRegion(OpenMPDirectiveKind DKind) {
1226 return isImplicitTaskingRegion(DKind) || isOpenMPTaskingDirective(DKind) ||
1227 DKind == OMPD_unknown;
1228}
1229
1230} // namespace
1231
1232static const Expr *getExprAsWritten(const Expr *E) {
1233 if (const auto *FE = dyn_cast<FullExpr>(E))
1234 E = FE->getSubExpr();
1235
1236 if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E))
1237 E = MTE->getSubExpr();
1238
1239 while (const auto *Binder = dyn_cast<CXXBindTemporaryExpr>(E))
1240 E = Binder->getSubExpr();
1241
1242 if (const auto *ICE = dyn_cast<ImplicitCastExpr>(E))
1243 E = ICE->getSubExprAsWritten();
1244 return E->IgnoreParens();
1245}
1246
1247static Expr *getExprAsWritten(Expr *E) {
1248 return const_cast<Expr *>(getExprAsWritten(const_cast<const Expr *>(E)));
1249}
1250
1251static const ValueDecl *getCanonicalDecl(const ValueDecl *D) {
1252 if (const auto *CED = dyn_cast<OMPCapturedExprDecl>(D))
1253 if (const auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
1254 D = ME->getMemberDecl();
1255 const auto *VD = dyn_cast<VarDecl>(D);
1256 const auto *FD = dyn_cast<FieldDecl>(D);
1257 if (VD != nullptr) {
1258 VD = VD->getCanonicalDecl();
1259 D = VD;
1260 } else {
1261 assert(FD)(static_cast <bool> (FD) ? void (0) : __assert_fail ("FD"
, "clang/lib/Sema/SemaOpenMP.cpp", 1261, __extension__ __PRETTY_FUNCTION__
))
;
1262 FD = FD->getCanonicalDecl();
1263 D = FD;
1264 }
1265 return D;
1266}
1267
1268static ValueDecl *getCanonicalDecl(ValueDecl *D) {
1269 return const_cast<ValueDecl *>(
1270 getCanonicalDecl(const_cast<const ValueDecl *>(D)));
1271}
1272
1273DSAStackTy::DSAVarData DSAStackTy::getDSA(const_iterator &Iter,
1274 ValueDecl *D) const {
1275 D = getCanonicalDecl(D);
1276 auto *VD = dyn_cast<VarDecl>(D);
1277 const auto *FD = dyn_cast<FieldDecl>(D);
1278 DSAVarData DVar;
1279 if (Iter == end()) {
1280 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1281 // in a region but not in construct]
1282 // File-scope or namespace-scope variables referenced in called routines
1283 // in the region are shared unless they appear in a threadprivate
1284 // directive.
1285 if (VD && !VD->isFunctionOrMethodVarDecl() && !isa<ParmVarDecl>(VD))
1286 DVar.CKind = OMPC_shared;
1287
1288 // OpenMP [2.9.1.2, Data-sharing Attribute Rules for Variables Referenced
1289 // in a region but not in construct]
1290 // Variables with static storage duration that are declared in called
1291 // routines in the region are shared.
1292 if (VD && VD->hasGlobalStorage())
1293 DVar.CKind = OMPC_shared;
1294
1295 // Non-static data members are shared by default.
1296 if (FD)
1297 DVar.CKind = OMPC_shared;
1298
1299 return DVar;
1300 }
1301
1302 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1303 // in a Construct, C/C++, predetermined, p.1]
1304 // Variables with automatic storage duration that are declared in a scope
1305 // inside the construct are private.
1306 if (VD && isOpenMPLocal(VD, Iter) && VD->isLocalVarDecl() &&
1307 (VD->getStorageClass() == SC_Auto || VD->getStorageClass() == SC_None)) {
1308 DVar.CKind = OMPC_private;
1309 return DVar;
1310 }
1311
1312 DVar.DKind = Iter->Directive;
1313 // Explicitly specified attributes and local variables with predetermined
1314 // attributes.
1315 if (Iter->SharingMap.count(D)) {
1316 const DSAInfo &Data = Iter->SharingMap.lookup(D);
1317 DVar.RefExpr = Data.RefExpr.getPointer();
1318 DVar.PrivateCopy = Data.PrivateCopy;
1319 DVar.CKind = Data.Attributes;
1320 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1321 DVar.Modifier = Data.Modifier;
1322 DVar.AppliedToPointee = Data.AppliedToPointee;
1323 return DVar;
1324 }
1325
1326 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1327 // in a Construct, C/C++, implicitly determined, p.1]
1328 // In a parallel or task construct, the data-sharing attributes of these
1329 // variables are determined by the default clause, if present.
1330 switch (Iter->DefaultAttr) {
1331 case DSA_shared:
1332 DVar.CKind = OMPC_shared;
1333 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1334 return DVar;
1335 case DSA_none:
1336 return DVar;
1337 case DSA_firstprivate:
1338 if (VD && VD->getStorageDuration() == SD_Static &&
1339 VD->getDeclContext()->isFileContext()) {
1340 DVar.CKind = OMPC_unknown;
1341 } else {
1342 DVar.CKind = OMPC_firstprivate;
1343 }
1344 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1345 return DVar;
1346 case DSA_private:
1347 // each variable with static storage duration that is declared
1348 // in a namespace or global scope and referenced in the construct,
1349 // and that does not have a predetermined data-sharing attribute
1350 if (VD && VD->getStorageDuration() == SD_Static &&
1351 VD->getDeclContext()->isFileContext()) {
1352 DVar.CKind = OMPC_unknown;
1353 } else {
1354 DVar.CKind = OMPC_private;
1355 }
1356 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1357 return DVar;
1358 case DSA_unspecified:
1359 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1360 // in a Construct, implicitly determined, p.2]
1361 // In a parallel construct, if no default clause is present, these
1362 // variables are shared.
1363 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1364 if ((isOpenMPParallelDirective(DVar.DKind) &&
1365 !isOpenMPTaskLoopDirective(DVar.DKind)) ||
1366 isOpenMPTeamsDirective(DVar.DKind)) {
1367 DVar.CKind = OMPC_shared;
1368 return DVar;
1369 }
1370
1371 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1372 // in a Construct, implicitly determined, p.4]
1373 // In a task construct, if no default clause is present, a variable that in
1374 // the enclosing context is determined to be shared by all implicit tasks
1375 // bound to the current team is shared.
1376 if (isOpenMPTaskingDirective(DVar.DKind)) {
1377 DSAVarData DVarTemp;
1378 const_iterator I = Iter, E = end();
1379 do {
1380 ++I;
1381 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables
1382 // Referenced in a Construct, implicitly determined, p.6]
1383 // In a task construct, if no default clause is present, a variable
1384 // whose data-sharing attribute is not determined by the rules above is
1385 // firstprivate.
1386 DVarTemp = getDSA(I, D);
1387 if (DVarTemp.CKind != OMPC_shared) {
1388 DVar.RefExpr = nullptr;
1389 DVar.CKind = OMPC_firstprivate;
1390 return DVar;
1391 }
1392 } while (I != E && !isImplicitTaskingRegion(I->Directive));
1393 DVar.CKind =
1394 (DVarTemp.CKind == OMPC_unknown) ? OMPC_firstprivate : OMPC_shared;
1395 return DVar;
1396 }
1397 }
1398 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1399 // in a Construct, implicitly determined, p.3]
1400 // For constructs other than task, if no default clause is present, these
1401 // variables inherit their data-sharing attributes from the enclosing
1402 // context.
1403 return getDSA(++Iter, D);
1404}
1405
1406const Expr *DSAStackTy::addUniqueAligned(const ValueDecl *D,
1407 const Expr *NewDE) {
1408 assert(!isStackEmpty() && "Data sharing attributes stack is empty")(static_cast <bool> (!isStackEmpty() && "Data sharing attributes stack is empty"
) ? void (0) : __assert_fail ("!isStackEmpty() && \"Data sharing attributes stack is empty\""
, "clang/lib/Sema/SemaOpenMP.cpp", 1408, __extension__ __PRETTY_FUNCTION__
))
;
1409 D = getCanonicalDecl(D);
1410 SharingMapTy &StackElem = getTopOfStack();
1411 auto It = StackElem.AlignedMap.find(D);
1412 if (It == StackElem.AlignedMap.end()) {
1413 assert(NewDE && "Unexpected nullptr expr to be added into aligned map")(static_cast <bool> (NewDE && "Unexpected nullptr expr to be added into aligned map"
) ? void (0) : __assert_fail ("NewDE && \"Unexpected nullptr expr to be added into aligned map\""
, "clang/lib/Sema/SemaOpenMP.cpp", 1413, __extension__ __PRETTY_FUNCTION__
))
;
1414 StackElem.AlignedMap[D] = NewDE;
1415 return nullptr;
1416 }
1417 assert(It->second && "Unexpected nullptr expr in the aligned map")(static_cast <bool> (It->second && "Unexpected nullptr expr in the aligned map"
) ? void (0) : __assert_fail ("It->second && \"Unexpected nullptr expr in the aligned map\""
, "clang/lib/Sema/SemaOpenMP.cpp", 1417, __extension__ __PRETTY_FUNCTION__
))
;
1418 return It->second;
1419}
1420
1421const Expr *DSAStackTy::addUniqueNontemporal(const ValueDecl *D,
1422 const Expr *NewDE) {
1423 assert(!isStackEmpty() && "Data sharing attributes stack is empty")(static_cast <bool> (!isStackEmpty() && "Data sharing attributes stack is empty"
) ? void (0) : __assert_fail ("!isStackEmpty() && \"Data sharing attributes stack is empty\""
, "clang/lib/Sema/SemaOpenMP.cpp", 1423, __extension__ __PRETTY_FUNCTION__
))
;
1424 D = getCanonicalDecl(D);
1425 SharingMapTy &StackElem = getTopOfStack();
1426 auto It = StackElem.NontemporalMap.find(D);
1427 if (It == StackElem.NontemporalMap.end()) {
1428 assert(NewDE && "Unexpected nullptr expr to be added into aligned map")(static_cast <bool> (NewDE && "Unexpected nullptr expr to be added into aligned map"
) ? void (0) : __assert_fail ("NewDE && \"Unexpected nullptr expr to be added into aligned map\""
, "clang/lib/Sema/SemaOpenMP.cpp", 1428, __extension__ __PRETTY_FUNCTION__
))
;
1429 StackElem.NontemporalMap[D] = NewDE;
1430 return nullptr;
1431 }
1432 assert(It->second && "Unexpected nullptr expr in the aligned map")(static_cast <bool> (It->second && "Unexpected nullptr expr in the aligned map"
) ? void (0) : __assert_fail ("It->second && \"Unexpected nullptr expr in the aligned map\""
, "clang/lib/Sema/SemaOpenMP.cpp", 1432, __extension__ __PRETTY_FUNCTION__
))
;
1433 return It->second;
1434}
1435
1436void DSAStackTy::addLoopControlVariable(const ValueDecl *D, VarDecl *Capture) {
1437 assert(!isStackEmpty() && "Data-sharing attributes stack is empty")(static_cast <bool> (!isStackEmpty() && "Data-sharing attributes stack is empty"
) ? void (0) : __assert_fail ("!isStackEmpty() && \"Data-sharing attributes stack is empty\""
, "clang/lib/Sema/SemaOpenMP.cpp", 1437, __extension__ __PRETTY_FUNCTION__
))
;
1438 D = getCanonicalDecl(D);
1439 SharingMapTy &StackElem = getTopOfStack();
1440 StackElem.LCVMap.try_emplace(
1441 D, 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")(static_cast <bool> (!isStackEmpty() && "Data-sharing attributes stack is empty"
) ? void (0) : __assert_fail ("!isStackEmpty() && \"Data-sharing attributes stack is empty\""
, "clang/lib/Sema/SemaOpenMP.cpp", 1446, __extension__ __PRETTY_FUNCTION__
))
;
1447 D = getCanonicalDecl(D);
1448 const SharingMapTy &StackElem = getTopOfStack();
1449 auto It = StackElem.LCVMap.find(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")(static_cast <bool> (!isStackEmpty() && "Data-sharing attributes stack is empty"
) ? void (0) : __assert_fail ("!isStackEmpty() && \"Data-sharing attributes stack is empty\""
, "clang/lib/Sema/SemaOpenMP.cpp", 1457, __extension__ __PRETTY_FUNCTION__
))
;
1458 D = getCanonicalDecl(D);
1459 for (unsigned I = Level + 1; I > 0; --I) {
1460 const SharingMapTy &StackElem = getStackElemAtLevel(I - 1);
1461 auto It = StackElem.LCVMap.find(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")(static_cast <bool> (Parent && "Data-sharing attributes stack is empty"
) ? void (0) : __assert_fail ("Parent && \"Data-sharing attributes stack is empty\""
, "clang/lib/Sema/SemaOpenMP.cpp", 1471, __extension__ __PRETTY_FUNCTION__
))
;
1472 D = getCanonicalDecl(D);
1473 auto It = Parent->LCVMap.find(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")(static_cast <bool> (Parent && "Data-sharing attributes stack is empty"
) ? void (0) : __assert_fail ("Parent && \"Data-sharing attributes stack is empty\""
, "clang/lib/Sema/SemaOpenMP.cpp", 1481, __extension__ __PRETTY_FUNCTION__
))
;
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) ||(static_cast <bool> (Data.Attributes == OMPC_unknown ||
(A == Data.Attributes) || (A == OMPC_firstprivate &&
Data.Attributes == OMPC_lastprivate) || (A == OMPC_lastprivate
&& Data.Attributes == OMPC_firstprivate) || (isLoopControlVariable
(D).first && A == OMPC_private)) ? void (0) : __assert_fail
("Data.Attributes == OMPC_unknown || (A == Data.Attributes) || (A == OMPC_firstprivate && Data.Attributes == OMPC_lastprivate) || (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) || (isLoopControlVariable(D).first && A == OMPC_private)"
, "clang/lib/Sema/SemaOpenMP.cpp", 1505, __extension__ __PRETTY_FUNCTION__
))
1503 (A == OMPC_firstprivate && Data.Attributes == OMPC_lastprivate) ||(static_cast <bool> (Data.Attributes == OMPC_unknown ||
(A == Data.Attributes) || (A == OMPC_firstprivate &&
Data.Attributes == OMPC_lastprivate) || (A == OMPC_lastprivate
&& Data.Attributes == OMPC_firstprivate) || (isLoopControlVariable
(D).first && A == OMPC_private)) ? void (0) : __assert_fail
("Data.Attributes == OMPC_unknown || (A == Data.Attributes) || (A == OMPC_firstprivate && Data.Attributes == OMPC_lastprivate) || (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) || (isLoopControlVariable(D).first && A == OMPC_private)"
, "clang/lib/Sema/SemaOpenMP.cpp", 1505, __extension__ __PRETTY_FUNCTION__
))
1504 (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) ||(static_cast <bool> (Data.Attributes == OMPC_unknown ||
(A == Data.Attributes) || (A == OMPC_firstprivate &&
Data.Attributes == OMPC_lastprivate) || (A == OMPC_lastprivate
&& Data.Attributes == OMPC_firstprivate) || (isLoopControlVariable
(D).first && A == OMPC_private)) ? void (0) : __assert_fail
("Data.Attributes == OMPC_unknown || (A == Data.Attributes) || (A == OMPC_firstprivate && Data.Attributes == OMPC_lastprivate) || (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) || (isLoopControlVariable(D).first && A == OMPC_private)"
, "clang/lib/Sema/SemaOpenMP.cpp", 1505, __extension__ __PRETTY_FUNCTION__
))
1505 (isLoopControlVariable(D).first && A == OMPC_private))(static_cast <bool> (Data.Attributes == OMPC_unknown ||
(A == Data.Attributes) || (A == OMPC_firstprivate &&
Data.Attributes == OMPC_lastprivate) || (A == OMPC_lastprivate
&& Data.Attributes == OMPC_firstprivate) || (isLoopControlVariable
(D).first && A == OMPC_private)) ? void (0) : __assert_fail
("Data.Attributes == OMPC_unknown || (A == Data.Attributes) || (A == OMPC_firstprivate && Data.Attributes == OMPC_lastprivate) || (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) || (isLoopControlVariable(D).first && A == OMPC_private)"
, "clang/lib/Sema/SemaOpenMP.cpp", 1505, __extension__ __PRETTY_FUNCTION__
))
;
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(E, 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(Type, Loc);
1535 auto *Decl =
1536 VarDecl::Create(SemaRef.Context, DC, Loc, Loc, II, Type, TInfo, 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")(static_cast <bool> (!isStackEmpty() && "Data-sharing attributes stack is empty"
) ? void (0) : __assert_fail ("!isStackEmpty() && \"Data-sharing attributes stack is empty\""
, "clang/lib/Sema/SemaOpenMP.cpp", 1563, __extension__ __PRETTY_FUNCTION__
))
;
1564 assert((static_cast <bool> (getTopOfStack().SharingMap[D].Attributes
== OMPC_reduction && "Additional reduction info may be specified only for reduction items."
) ? void (0) : __assert_fail ("getTopOfStack().SharingMap[D].Attributes == OMPC_reduction && \"Additional reduction info may be specified only for reduction items.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 1566, __extension__ __PRETTY_FUNCTION__
))
1565 getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&(static_cast <bool> (getTopOfStack().SharingMap[D].Attributes
== OMPC_reduction && "Additional reduction info may be specified only for reduction items."
) ? void (0) : __assert_fail ("getTopOfStack().SharingMap[D].Attributes == OMPC_reduction && \"Additional reduction info may be specified only for reduction items.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 1566, __extension__ __PRETTY_FUNCTION__
))
1566 "Additional reduction info may be specified only for reduction items.")(static_cast <bool> (getTopOfStack().SharingMap[D].Attributes
== OMPC_reduction && "Additional reduction info may be specified only for reduction items."
) ? void (0) : __assert_fail ("getTopOfStack().SharingMap[D].Attributes == OMPC_reduction && \"Additional reduction info may be specified only for reduction items.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 1566, __extension__ __PRETTY_FUNCTION__
))
;
1567 ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1568 assert(ReductionData.ReductionRange.isInvalid() &&(static_cast <bool> (ReductionData.ReductionRange.isInvalid
() && (getTopOfStack().Directive == OMPD_taskgroup ||
((isOpenMPParallelDirective(getTopOfStack().Directive) || isOpenMPWorksharingDirective
(getTopOfStack().Directive)) && !isOpenMPSimdDirective
(getTopOfStack().Directive))) && "Additional reduction info may be specified only once for reduction "
"items.") ? void (0) : __assert_fail ("ReductionData.ReductionRange.isInvalid() && (getTopOfStack().Directive == OMPD_taskgroup || ((isOpenMPParallelDirective(getTopOfStack().Directive) || isOpenMPWorksharingDirective(getTopOfStack().Directive)) && !isOpenMPSimdDirective(getTopOfStack().Directive))) && \"Additional reduction info may be specified only once for reduction \" \"items.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 1574, __extension__ __PRETTY_FUNCTION__
))
1569 (getTopOfStack().Directive == OMPD_taskgroup ||(static_cast <bool> (ReductionData.ReductionRange.isInvalid
() && (getTopOfStack().Directive == OMPD_taskgroup ||
((isOpenMPParallelDirective(getTopOfStack().Directive) || isOpenMPWorksharingDirective
(getTopOfStack().Directive)) && !isOpenMPSimdDirective
(getTopOfStack().Directive))) && "Additional reduction info may be specified only once for reduction "
"items.") ? void (0) : __assert_fail ("ReductionData.ReductionRange.isInvalid() && (getTopOfStack().Directive == OMPD_taskgroup || ((isOpenMPParallelDirective(getTopOfStack().Directive) || isOpenMPWorksharingDirective(getTopOfStack().Directive)) && !isOpenMPSimdDirective(getTopOfStack().Directive))) && \"Additional reduction info may be specified only once for reduction \" \"items.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 1574, __extension__ __PRETTY_FUNCTION__
))
1570 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||(static_cast <bool> (ReductionData.ReductionRange.isInvalid
() && (getTopOfStack().Directive == OMPD_taskgroup ||
((isOpenMPParallelDirective(getTopOfStack().Directive) || isOpenMPWorksharingDirective
(getTopOfStack().Directive)) && !isOpenMPSimdDirective
(getTopOfStack().Directive))) && "Additional reduction info may be specified only once for reduction "
"items.") ? void (0) : __assert_fail ("ReductionData.ReductionRange.isInvalid() && (getTopOfStack().Directive == OMPD_taskgroup || ((isOpenMPParallelDirective(getTopOfStack().Directive) || isOpenMPWorksharingDirective(getTopOfStack().Directive)) && !isOpenMPSimdDirective(getTopOfStack().Directive))) && \"Additional reduction info may be specified only once for reduction \" \"items.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 1574, __extension__ __PRETTY_FUNCTION__
))
1571 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&(static_cast <bool> (ReductionData.ReductionRange.isInvalid
() && (getTopOfStack().Directive == OMPD_taskgroup ||
((isOpenMPParallelDirective(getTopOfStack().Directive) || isOpenMPWorksharingDirective
(getTopOfStack().Directive)) && !isOpenMPSimdDirective
(getTopOfStack().Directive))) && "Additional reduction info may be specified only once for reduction "
"items.") ? void (0) : __assert_fail ("ReductionData.ReductionRange.isInvalid() && (getTopOfStack().Directive == OMPD_taskgroup || ((isOpenMPParallelDirective(getTopOfStack().Directive) || isOpenMPWorksharingDirective(getTopOfStack().Directive)) && !isOpenMPSimdDirective(getTopOfStack().Directive))) && \"Additional reduction info may be specified only once for reduction \" \"items.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 1574, __extension__ __PRETTY_FUNCTION__
))
1572 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&(static_cast <bool> (ReductionData.ReductionRange.isInvalid
() && (getTopOfStack().Directive == OMPD_taskgroup ||
((isOpenMPParallelDirective(getTopOfStack().Directive) || isOpenMPWorksharingDirective
(getTopOfStack().Directive)) && !isOpenMPSimdDirective
(getTopOfStack().Directive))) && "Additional reduction info may be specified only once for reduction "
"items.") ? void (0) : __assert_fail ("ReductionData.ReductionRange.isInvalid() && (getTopOfStack().Directive == OMPD_taskgroup || ((isOpenMPParallelDirective(getTopOfStack().Directive) || isOpenMPWorksharingDirective(getTopOfStack().Directive)) && !isOpenMPSimdDirective(getTopOfStack().Directive))) && \"Additional reduction info may be specified only once for reduction \" \"items.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 1574, __extension__ __PRETTY_FUNCTION__
))
1573 "Additional reduction info may be specified only once for reduction "(static_cast <bool> (ReductionData.ReductionRange.isInvalid
() && (getTopOfStack().Directive == OMPD_taskgroup ||
((isOpenMPParallelDirective(getTopOfStack().Directive) || isOpenMPWorksharingDirective
(getTopOfStack().Directive)) && !isOpenMPSimdDirective
(getTopOfStack().Directive))) && "Additional reduction info may be specified only once for reduction "
"items.") ? void (0) : __assert_fail ("ReductionData.ReductionRange.isInvalid() && (getTopOfStack().Directive == OMPD_taskgroup || ((isOpenMPParallelDirective(getTopOfStack().Directive) || isOpenMPWorksharingDirective(getTopOfStack().Directive)) && !isOpenMPSimdDirective(getTopOfStack().Directive))) && \"Additional reduction info may be specified only once for reduction \" \"items.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 1574, __extension__ __PRETTY_FUNCTION__
))
1574 "items.")(static_cast <bool> (ReductionData.ReductionRange.isInvalid
() && (getTopOfStack().Directive == OMPD_taskgroup ||
((isOpenMPParallelDirective(getTopOfStack().Directive) || isOpenMPWorksharingDirective
(getTopOfStack().Directive)) && !isOpenMPSimdDirective
(getTopOfStack().Directive))) && "Additional reduction info may be specified only once for reduction "
"items.") ? void (0) : __assert_fail ("ReductionData.ReductionRange.isInvalid() && (getTopOfStack().Directive == OMPD_taskgroup || ((isOpenMPParallelDirective(getTopOfStack().Directive) || isOpenMPWorksharingDirective(getTopOfStack().Directive)) && !isOpenMPSimdDirective(getTopOfStack().Directive))) && \"Additional reduction info may be specified only once for reduction \" \"items.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 1574, __extension__ __PRETTY_FUNCTION__
))
;
1575 ReductionData.set(BOK, 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")(static_cast <bool> (!isStackEmpty() && "Data-sharing attributes stack is empty"
) ? void (0) : __assert_fail ("!isStackEmpty() && \"Data-sharing attributes stack is empty\""
, "clang/lib/Sema/SemaOpenMP.cpp", 1588, __extension__ __PRETTY_FUNCTION__
))
;
1589 assert((static_cast <bool> (getTopOfStack().SharingMap[D].Attributes
== OMPC_reduction && "Additional reduction info may be specified only for reduction items."
) ? void (0) : __assert_fail ("getTopOfStack().SharingMap[D].Attributes == OMPC_reduction && \"Additional reduction info may be specified only for reduction items.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 1591, __extension__ __PRETTY_FUNCTION__
))
1590 getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&(static_cast <bool> (getTopOfStack().SharingMap[D].Attributes
== OMPC_reduction && "Additional reduction info may be specified only for reduction items."
) ? void (0) : __assert_fail ("getTopOfStack().SharingMap[D].Attributes == OMPC_reduction && \"Additional reduction info may be specified only for reduction items.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 1591, __extension__ __PRETTY_FUNCTION__
))
1591 "Additional reduction info may be specified only for reduction items.")(static_cast <bool> (getTopOfStack().SharingMap[D].Attributes
== OMPC_reduction && "Additional reduction info may be specified only for reduction items."
) ? void (0) : __assert_fail ("getTopOfStack().SharingMap[D].Attributes == OMPC_reduction && \"Additional reduction info may be specified only for reduction items.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 1591, __extension__ __PRETTY_FUNCTION__
))
;
1592 ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1593 assert(ReductionData.ReductionRange.isInvalid() &&(static_cast <bool> (ReductionData.ReductionRange.isInvalid
() && (getTopOfStack().Directive == OMPD_taskgroup ||
((isOpenMPParallelDirective(getTopOfStack().Directive) || isOpenMPWorksharingDirective
(getTopOfStack().Directive)) && !isOpenMPSimdDirective
(getTopOfStack().Directive))) && "Additional reduction info may be specified only once for reduction "
"items.") ? void (0) : __assert_fail ("ReductionData.ReductionRange.isInvalid() && (getTopOfStack().Directive == OMPD_taskgroup || ((isOpenMPParallelDirective(getTopOfStack().Directive) || isOpenMPWorksharingDirective(getTopOfStack().Directive)) && !isOpenMPSimdDirective(getTopOfStack().Directive))) && \"Additional reduction info may be specified only once for reduction \" \"items.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 1599, __extension__ __PRETTY_FUNCTION__
))
1594 (getTopOfStack().Directive == OMPD_taskgroup ||(static_cast <bool> (ReductionData.ReductionRange.isInvalid
() && (getTopOfStack().Directive == OMPD_taskgroup ||
((isOpenMPParallelDirective(getTopOfStack().Directive) || isOpenMPWorksharingDirective
(getTopOfStack().Directive)) && !isOpenMPSimdDirective
(getTopOfStack().Directive))) && "Additional reduction info may be specified only once for reduction "
"items.") ? void (0) : __assert_fail ("ReductionData.ReductionRange.isInvalid() && (getTopOfStack().Directive == OMPD_taskgroup || ((isOpenMPParallelDirective(getTopOfStack().Directive) || isOpenMPWorksharingDirective(getTopOfStack().Directive)) && !isOpenMPSimdDirective(getTopOfStack().Directive))) && \"Additional reduction info may be specified only once for reduction \" \"items.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 1599, __extension__ __PRETTY_FUNCTION__
))
1595 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||(static_cast <bool> (ReductionData.ReductionRange.isInvalid
() && (getTopOfStack().Directive == OMPD_taskgroup ||
((isOpenMPParallelDirective(getTopOfStack().Directive) || isOpenMPWorksharingDirective
(getTopOfStack().Directive)) && !isOpenMPSimdDirective
(getTopOfStack().Directive))) && "Additional reduction info may be specified only once for reduction "
"items.") ? void (0) : __assert_fail ("ReductionData.ReductionRange.isInvalid() && (getTopOfStack().Directive == OMPD_taskgroup || ((isOpenMPParallelDirective(getTopOfStack().Directive) || isOpenMPWorksharingDirective(getTopOfStack().Directive)) && !isOpenMPSimdDirective(getTopOfStack().Directive))) && \"Additional reduction info may be specified only once for reduction \" \"items.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 1599, __extension__ __PRETTY_FUNCTION__
))
1596 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&(static_cast <bool> (ReductionData.ReductionRange.isInvalid
() && (getTopOfStack().Directive == OMPD_taskgroup ||
((isOpenMPParallelDirective(getTopOfStack().Directive) || isOpenMPWorksharingDirective
(getTopOfStack().Directive)) && !isOpenMPSimdDirective
(getTopOfStack().Directive))) && "Additional reduction info may be specified only once for reduction "
"items.") ? void (0) : __assert_fail ("ReductionData.ReductionRange.isInvalid() && (getTopOfStack().Directive == OMPD_taskgroup || ((isOpenMPParallelDirective(getTopOfStack().Directive) || isOpenMPWorksharingDirective(getTopOfStack().Directive)) && !isOpenMPSimdDirective(getTopOfStack().Directive))) && \"Additional reduction info may be specified only once for reduction \" \"items.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 1599, __extension__ __PRETTY_FUNCTION__
))
1597 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&(static_cast <bool> (ReductionData.ReductionRange.isInvalid
() && (getTopOfStack().Directive == OMPD_taskgroup ||
((isOpenMPParallelDirective(getTopOfStack().Directive) || isOpenMPWorksharingDirective
(getTopOfStack().Directive)) && !isOpenMPSimdDirective
(getTopOfStack().Directive))) && "Additional reduction info may be specified only once for reduction "
"items.") ? void (0) : __assert_fail ("ReductionData.ReductionRange.isInvalid() && (getTopOfStack().Directive == OMPD_taskgroup || ((isOpenMPParallelDirective(getTopOfStack().Directive) || isOpenMPWorksharingDirective(getTopOfStack().Directive)) && !isOpenMPSimdDirective(getTopOfStack().Directive))) && \"Additional reduction info may be specified only once for reduction \" \"items.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 1599, __extension__ __PRETTY_FUNCTION__
))
1598 "Additional reduction info may be specified only once for reduction "(static_cast <bool> (ReductionData.ReductionRange.isInvalid
() && (getTopOfStack().Directive == OMPD_taskgroup ||
((isOpenMPParallelDirective(getTopOfStack().Directive) || isOpenMPWorksharingDirective
(getTopOfStack().Directive)) && !isOpenMPSimdDirective
(getTopOfStack().Directive))) && "Additional reduction info may be specified only once for reduction "
"items.") ? void (0) : __assert_fail ("ReductionData.ReductionRange.isInvalid() && (getTopOfStack().Directive == OMPD_taskgroup || ((isOpenMPParallelDirective(getTopOfStack().Directive) || isOpenMPWorksharingDirective(getTopOfStack().Directive)) && !isOpenMPSimdDirective(getTopOfStack().Directive))) && \"Additional reduction info may be specified only once for reduction \" \"items.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 1599, __extension__ __PRETTY_FUNCTION__
))
1599 "items.")(static_cast <bool> (ReductionData.ReductionRange.isInvalid
() && (getTopOfStack().Directive == OMPD_taskgroup ||
((isOpenMPParallelDirective(getTopOfStack().Directive) || isOpenMPWorksharingDirective
(getTopOfStack().Directive)) && !isOpenMPSimdDirective
(getTopOfStack().Directive))) && "Additional reduction info may be specified only once for reduction "
"items.") ? void (0) : __assert_fail ("ReductionData.ReductionRange.isInvalid() && (getTopOfStack().Directive == OMPD_taskgroup || ((isOpenMPParallelDirective(getTopOfStack().Directive) || isOpenMPWorksharingDirective(getTopOfStack().Directive)) && !isOpenMPSimdDirective(getTopOfStack().Directive))) && \"Additional reduction info may be specified only once for reduction \" \"items.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 1599, __extension__ __PRETTY_FUNCTION__
))
;
1600 ReductionData.set(ReductionRef, 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.")(static_cast <bool> (!isStackEmpty() && "Data-sharing attributes stack is empty."
) ? void (0) : __assert_fail ("!isStackEmpty() && \"Data-sharing attributes stack is empty.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 1614, __extension__ __PRETTY_FUNCTION__
))
;
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(D);
1621 if (!ReductionData.ReductionOp ||
1622 ReductionData.ReductionOp.is<const Expr *>())
1623 return DSAVarData();
1624 SR = ReductionData.ReductionRange;
1625 BOK = ReductionData.ReductionOp.get<ReductionData::BOKPtrType>();
1626 assert(I->TaskgroupReductionRef && "taskgroup reduction reference "(static_cast <bool> (I->TaskgroupReductionRef &&
"taskgroup reduction reference " "expression for the descriptor is not "
"set.") ? void (0) : __assert_fail ("I->TaskgroupReductionRef && \"taskgroup reduction reference \" \"expression for the descriptor is not \" \"set.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 1628, __extension__ __PRETTY_FUNCTION__
))
1627 "expression for the descriptor is not "(static_cast <bool> (I->TaskgroupReductionRef &&
"taskgroup reduction reference " "expression for the descriptor is not "
"set.") ? void (0) : __assert_fail ("I->TaskgroupReductionRef && \"taskgroup reduction reference \" \"expression for the descriptor is not \" \"set.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 1628, __extension__ __PRETTY_FUNCTION__
))
1628 "set.")(static_cast <bool> (I->TaskgroupReductionRef &&
"taskgroup reduction reference " "expression for the descriptor is not "
"set.") ? void (0) : __assert_fail ("I->TaskgroupReductionRef && \"taskgroup reduction reference \" \"expression for the descriptor is not \" \"set.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 1628, __extension__ __PRETTY_FUNCTION__
))
;
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.")(static_cast <bool> (!isStackEmpty() && "Data-sharing attributes stack is empty."
) ? void (0) : __assert_fail ("!isStackEmpty() && \"Data-sharing attributes stack is empty.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 1641, __extension__ __PRETTY_FUNCTION__
))
;
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(D);
1648 if (!ReductionData.ReductionOp ||
1649 !ReductionData.ReductionOp.is<const Expr *>())
1650 return DSAVarData();
1651 SR = ReductionData.ReductionRange;
1652 ReductionRef = ReductionData.ReductionOp.get<const Expr *>();
1653 assert(I->TaskgroupReductionRef && "taskgroup reduction reference "(static_cast <bool> (I->TaskgroupReductionRef &&
"taskgroup reduction reference " "expression for the descriptor is not "
"set.") ? void (0) : __assert_fail ("I->TaskgroupReductionRef && \"taskgroup reduction reference \" \"expression for the descriptor is not \" \"set.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 1655, __extension__ __PRETTY_FUNCTION__
))
1654 "expression for the descriptor is not "(static_cast <bool> (I->TaskgroupReductionRef &&
"taskgroup reduction reference " "expression for the descriptor is not "
"set.") ? void (0) : __assert_fail ("I->TaskgroupReductionRef && \"taskgroup reduction reference \" \"expression for the descriptor is not \" \"set.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 1655, __extension__ __PRETTY_FUNCTION__
))
1655 "set.")(static_cast <bool> (I->TaskgroupReductionRef &&
"taskgroup reduction reference " "expression for the descriptor is not "
"set.") ? void (0) : __assert_fail ("I->TaskgroupReductionRef && \"taskgroup reduction reference \" \"expression for the descriptor is not \" \"set.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 1655, __extension__ __PRETTY_FUNCTION__
))
;
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(Context);
1691 Type = Context.getBaseElementType(Type);
1692 const CXXRecordDecl *RD = AcceptIfMutable && SemaRef.getLangOpts().CPlusPlus
1693 ? Type->getAsCXXRecordDecl()
1694 : nullptr;
1695 if (const auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(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)) {
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) << getOpenMPClauseName(CKind);
1716 if (!ListItemNotVar && D) {
1717 const VarDecl *VD = dyn_cast<VarDecl>(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>(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(begin(), end(), [](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(VD, 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.isOpenMPCapturedByRef(D,
1793 std::distance(ParentIterTarget, End),
1794 /*OpenMPCaptureLevel=*/0)) {
1795 DVar.RefExpr =
1796 buildDeclRefExpr(SemaRef, VD, D->getType().getNonReferenceType(),
1797 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, 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(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(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(begin(), getStackSize() - 1 - Level);
1909 return getDSA(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(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(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(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(Skip, 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 Sema::InitDataSharingAttributesStack() {
2003 VarDataSharingAttributesStack = new DSAStackTy(*this);
2004}
2005
2006#define DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
static_cast<DSAStackTy *>(VarDataSharingAttributesStack)
2007
2008void Sema::pushOpenMPFunctionRegion() { DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->pushFunction(); }
2009
2010void Sema::popOpenMPFunctionRegion(const FunctionScopeInfo *OldFSI) {
2011 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->popFunction(OldFSI);
2012}
2013
2014static bool isOpenMPDeviceDelayedContext(Sema &S) {
2015 assert(S.LangOpts.OpenMP && S.LangOpts.OpenMPIsDevice &&(static_cast <bool> (S.LangOpts.OpenMP && S.LangOpts
.OpenMPIsDevice && "Expected OpenMP device compilation."
) ? void (0) : __assert_fail ("S.LangOpts.OpenMP && S.LangOpts.OpenMPIsDevice && \"Expected OpenMP device compilation.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 2016, __extension__ __PRETTY_FUNCTION__
))
2016 "Expected OpenMP device compilation.")(static_cast <bool> (S.LangOpts.OpenMP && S.LangOpts
.OpenMPIsDevice && "Expected OpenMP device compilation."
) ? void (0) : __assert_fail ("S.LangOpts.OpenMP && S.LangOpts.OpenMPIsDevice && \"Expected OpenMP device compilation.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 2016, __extension__ __PRETTY_FUNCTION__
))
;
2017 return !S.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
2029Sema::SemaDiagnosticBuilder
2030Sema::diagIfOpenMPDeviceCode(SourceLocation Loc, unsigned DiagID,
2031 const FunctionDecl *FD) {
2032 assert(LangOpts.OpenMP && LangOpts.OpenMPIsDevice &&(static_cast <bool> (LangOpts.OpenMP && LangOpts
.OpenMPIsDevice && "Expected OpenMP device compilation."
) ? void (0) : __assert_fail ("LangOpts.OpenMP && LangOpts.OpenMPIsDevice && \"Expected OpenMP device compilation.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 2033, __extension__ __PRETTY_FUNCTION__
))
2033 "Expected OpenMP device compilation.")(static_cast <bool> (LangOpts.OpenMP && LangOpts
.OpenMPIsDevice && "Expected OpenMP device compilation."
) ? void (0) : __assert_fail ("LangOpts.OpenMP && LangOpts.OpenMPIsDevice && \"Expected OpenMP device compilation.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 2033, __extension__ __PRETTY_FUNCTION__
))
;
2034
2035 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2036 if (FD) {
2037 FunctionEmissionStatus FES = getEmissionStatus(FD);
2038 switch (FES) {
2039 case FunctionEmissionStatus::Emitted:
2040 Kind = SemaDiagnosticBuilder::K_Immediate;
2041 break;
2042 case 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(*this)
2051 ? SemaDiagnosticBuilder::K_Deferred
2052 : SemaDiagnosticBuilder::K_Immediate;
2053 break;
2054 case FunctionEmissionStatus::TemplateDiscarded:
2055 case FunctionEmissionStatus::OMPDiscarded:
2056 Kind = SemaDiagnosticBuilder::K_Nop;
2057 break;
2058 case FunctionEmissionStatus::CUDADiscarded:
2059 llvm_unreachable("CUDADiscarded unexpected in OpenMP device compilation")::llvm::llvm_unreachable_internal("CUDADiscarded unexpected in OpenMP device compilation"
, "clang/lib/Sema/SemaOpenMP.cpp", 2059)
;
2060 break;
2061 }
2062 }
2063
2064 return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, *this);
2065}
2066
2067Sema::SemaDiagnosticBuilder Sema::diagIfOpenMPHostCode(SourceLocation Loc,
2068 unsigned DiagID,
2069 const FunctionDecl *FD) {
2070 assert(LangOpts.OpenMP && !LangOpts.OpenMPIsDevice &&(static_cast <bool> (LangOpts.OpenMP && !LangOpts
.OpenMPIsDevice && "Expected OpenMP host compilation."
) ? void (0) : __assert_fail ("LangOpts.OpenMP && !LangOpts.OpenMPIsDevice && \"Expected OpenMP host compilation.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 2071, __extension__ __PRETTY_FUNCTION__
))
2071 "Expected OpenMP host compilation.")(static_cast <bool> (LangOpts.OpenMP && !LangOpts
.OpenMPIsDevice && "Expected OpenMP host compilation."
) ? void (0) : __assert_fail ("LangOpts.OpenMP && !LangOpts.OpenMPIsDevice && \"Expected OpenMP host compilation.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 2071, __extension__ __PRETTY_FUNCTION__
))
;
2072
2073 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2074 if (FD) {
2075 FunctionEmissionStatus FES = getEmissionStatus(FD);
2076 switch (FES) {
2077 case FunctionEmissionStatus::Emitted:
2078 Kind = SemaDiagnosticBuilder::K_Immediate;
2079 break;
2080 case FunctionEmissionStatus::Unknown:
2081 Kind = SemaDiagnosticBuilder::K_Deferred;
2082 break;
2083 case FunctionEmissionStatus::TemplateDiscarded:
2084 case FunctionEmissionStatus::OMPDiscarded:
2085 case FunctionEmissionStatus::CUDADiscarded:
2086 Kind = SemaDiagnosticBuilder::K_Nop;
2087 break;
2088 }
2089 }
2090
2091 return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, *this);
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 Sema::isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level,
2109 unsigned OpenMPCaptureLevel) const {
2110 assert(LangOpts.OpenMP && "OpenMP is not allowed")(static_cast <bool> (LangOpts.OpenMP && "OpenMP is not allowed"
) ? void (0) : __assert_fail ("LangOpts.OpenMP && \"OpenMP is not allowed\""
, "clang/lib/Sema/SemaOpenMP.cpp", 2110, __extension__ __PRETTY_FUNCTION__
))
;
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 (DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->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 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->checkMappableExprComponentListsForDeclAtLevel(
2184 D, Level,
2185 [&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!")(static_cast <bool> (EI != EE && "Invalid map expression!"
) ? void (0) : __assert_fail ("EI != EE && \"Invalid map expression!\""
, "clang/lib/Sema/SemaOpenMP.cpp", 2199, __extension__ __PRETTY_FUNCTION__
))
;
2200
2201 if (isa<DeclRefExpr>(EI->getAssociatedExpression()))
2202 IsVariableUsedInMapClause |= EI->getAssociatedDeclaration() == D;
2203
2204 ++EI;
2205 if (EI == EE)
2206 return false;
2207 auto Last = std::prev(EE);
2208 const auto *UO =
2209 dyn_cast<UnaryOperator>(Last->getAssociatedExpression());
2210 if ((UO && UO->getOpcode() == UO_Deref) ||
2211 isa<ArraySubscriptExpr>(Last->getAssociatedExpression()) ||
2212 isa<OMPArraySectionExpr>(Last->getAssociatedExpression()) ||
2213 isa<MemberExpr>(EI->getAssociatedExpression()) ||
2214 isa<OMPArrayShapingExpr>(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 = (DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isForceCaptureByReferenceInTargetExecutable() &&
2233 !Ty->isAnyPointerType()) ||
2234 !Ty->isScalarType() ||
2235 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isDefaultmapCapturedByRef(
2236 Level, getVariableCategoryFromDecl(LangOpts, D)) ||
2237 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->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 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCaptureRegion(Level, OpenMPCaptureLevel) ==
2250 OMPD_target) ||
2251 !(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->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 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->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 !((DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getDefaultDSA() == DSA_firstprivate ||
2266 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getDefaultDSA() == DSA_private) &&
2267 !DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->hasExplicitDSA(
2268 D, [](OpenMPClauseKind K, bool) { return K != OMPC_unknown; },
2269 Level) &&
2270 !DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->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(Ty) >
2278 Ctx.getTypeSizeInChars(Ctx.getUIntPtrType()) ||
2279 Ctx.getAlignOfGlobalVarInChars(Ty) >
2280 Ctx.getTypeAlignInChars(Ctx.getUIntPtrType()))) {
2281 IsByRef = true;
2282 }
2283
2284 return IsByRef;
2285}
2286
2287unsigned Sema::getOpenMPNestingLevel() const {
2288 assert(getLangOpts().OpenMP)(static_cast <bool> (getLangOpts().OpenMP) ? void (0) :
__assert_fail ("getLangOpts().OpenMP", "clang/lib/Sema/SemaOpenMP.cpp"
, 2288, __extension__ __PRETTY_FUNCTION__))
;
2289 return DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getNestingLevel();
2290}
2291
2292bool Sema::isInOpenMPTaskUntiedContext() const {
2293 return isOpenMPTaskingDirective(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective()) &&
2294 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isUntiedRegion();
2295}
2296
2297bool Sema::isInOpenMPTargetExecutionDirective() const {
2298 return (isOpenMPTargetExecutionDirective(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective()) &&
2299 !DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isClauseParsingMode()) ||
2300 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->hasDirective(
2301 [](OpenMPDirectiveKind K, const DeclarationNameInfo &,
2302 SourceLocation) -> bool {
2303 return isOpenMPTargetExecutionDirective(K);
2304 },
2305 false);
2306}
2307
2308bool Sema::isOpenMPRebuildMemberExpr(ValueDecl *D) {
2309 // Only rebuild for Field.
2310 if (!dyn_cast<FieldDecl>(D))
2311 return false;
2312 DSAStackTy::DSAVarData DVarPrivate = DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->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 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->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 *Sema::isOpenMPCapturedDecl(ValueDecl *D, bool CheckScopeInfo,
2332 unsigned StopAt) {
2333 assert(LangOpts.OpenMP && "OpenMP is not allowed")(static_cast <bool> (LangOpts.OpenMP && "OpenMP is not allowed"
) ? void (0) : __assert_fail ("LangOpts.OpenMP && \"OpenMP is not allowed\""
, "clang/lib/Sema/SemaOpenMP.cpp", 2333, __extension__ __PRETTY_FUNCTION__
))
;
2334 D = getCanonicalDecl(D);
2335
2336 auto *VD = dyn_cast<VarDecl>(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 *DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
, CheckScopeInfo && DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->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 (getCurCapturedRegion() || getCurBlock() || getCurLambda())) {
2353 if (isInOpenMPTargetExecutionDirective()) {
2354 DSAStackTy::DSAVarData DVarTop =
2355 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getTopDSA(D, DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isClauseParsingMode());
2356 if (DVarTop.CKind != OMPC_unknown && DVarTop.RefExpr)
2357 return VD;
2358 // If the declaration is enclosed in a 'declare target' directive,
2359 // then it should not be captured.
2360 //
2361 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2362 return nullptr;
2363 CapturedRegionScopeInfo *CSI = nullptr;
2364 for (FunctionScopeInfo *FSI : llvm::drop_begin(
2365 llvm::reverse(FunctionScopes),
2366 CheckScopeInfo ? (FunctionScopes.size() - (StopAt + 1)) : 0)) {
2367 if (!isa<CapturingScopeInfo>(FSI))
2368 return nullptr;
2369 if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2370 if (RSI->CapRegionKind == CR_OpenMP) {
2371 CSI = RSI;
2372 break;
2373 }
2374 }
2375 assert(CSI && "Failed to find CapturedRegionScopeInfo")(static_cast <bool> (CSI && "Failed to find CapturedRegionScopeInfo"
) ? void (0) : __assert_fail ("CSI && \"Failed to find CapturedRegionScopeInfo\""
, "clang/lib/Sema/SemaOpenMP.cpp", 2375, __extension__ __PRETTY_FUNCTION__
))
;
2376 SmallVector<OpenMPDirectiveKind, 4> Regions;
2377 getOpenMPCaptureRegions(Regions,
2378 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getDirective(CSI->OpenMPLevel));
2379 if (Regions[CSI->OpenMPCaptureLevel] != OMPD_task)
2380 return VD;
2381 }
2382 if (isInOpenMPDeclareTargetContext()) {
2383 // Try to mark variable as declare target if it is used in capturing
2384 // regions.
2385 if (LangOpts.OpenMP <= 45 &&
2386 !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2387 checkDeclIsAllowedInOpenMPTarget(nullptr, VD);
2388 return nullptr;
2389 }
2390 }
2391
2392 if (CheckScopeInfo) {
2393 bool OpenMPFound = false;
2394 for (unsigned I = StopAt + 1; I > 0; --I) {
2395 FunctionScopeInfo *FSI = FunctionScopes[I - 1];
2396 if (!isa<CapturingScopeInfo>(FSI))
2397 return nullptr;
2398 if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2399 if (RSI->CapRegionKind == CR_OpenMP) {
2400 OpenMPFound = true;
2401 break;
2402 }
2403 }
2404 if (!OpenMPFound)
2405 return nullptr;
2406 }
2407
2408 if (DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective() != OMPD_unknown &&
2409 (!DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isClauseParsingMode() ||
2410 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getParentDirective() != OMPD_unknown)) {
2411 auto &&Info = DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isLoopControlVariable(D);
2412 if (Info.first ||
2413 (VD && VD->hasLocalStorage() &&
2414 isImplicitOrExplicitTaskingRegion(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective())) ||
2415 (VD && DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isForceVarCapturing()))
2416 return VD ? VD : Info.second;
2417 DSAStackTy::DSAVarData DVarTop =
2418 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getTopDSA(D, DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isClauseParsingMode());
2419 if (DVarTop.CKind != OMPC_unknown && isOpenMPPrivate(DVarTop.CKind) &&
2420 (!VD || VD->hasLocalStorage() || !DVarTop.AppliedToPointee))
2421 return VD ? VD : cast<VarDecl>(DVarTop.PrivateCopy->getDecl());
2422 // Threadprivate variables must not be captured.
2423 if (isOpenMPThreadPrivate(DVarTop.CKind))
2424 return nullptr;
2425 // The variable is not private or it is the variable in the directive with
2426 // default(none) clause and not used in any clause.
2427 DSAStackTy::DSAVarData DVarPrivate = DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->hasDSA(
2428 D,
2429 [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
2430 return isOpenMPPrivate(C) && !AppliedToPointee;
2431 },
2432 [](OpenMPDirectiveKind) { return true; },
2433 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isClauseParsingMode());
2434 // Global shared must not be captured.
2435 if (VD && !VD->hasLocalStorage() && DVarPrivate.CKind == OMPC_unknown &&
2436 ((DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getDefaultDSA() != DSA_none &&
2437 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getDefaultDSA() != DSA_private &&
2438 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getDefaultDSA() != DSA_firstprivate) ||
2439 DVarTop.CKind == OMPC_shared))
2440 return nullptr;
2441 auto *FD = dyn_cast<FieldDecl>(D);
2442 if (DVarPrivate.CKind != OMPC_unknown && !VD && FD &&
2443 !DVarPrivate.PrivateCopy) {
2444 DSAStackTy::DSAVarData DVarPrivate = DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->hasDSA(
2445 D,
2446 [](OpenMPClauseKind C, bool AppliedToPointee,
2447 DefaultDataSharingAttributes DefaultAttr) {
2448 return isOpenMPPrivate(C) && !AppliedToPointee &&
2449 (DefaultAttr == DSA_firstprivate ||
2450 DefaultAttr == DSA_private);
2451 },
2452 [](OpenMPDirectiveKind) { return true; },
2453 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isClauseParsingMode());
2454 if (DVarPrivate.CKind == OMPC_unknown)
2455 return nullptr;
2456
2457 VarDecl *VD = DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getImplicitFDCapExprDecl(FD);
2458 if (VD)
2459 return VD;
2460 if (getCurrentThisType().isNull())
2461 return nullptr;
2462 Expr *ThisExpr = BuildCXXThisExpr(SourceLocation(), getCurrentThisType(),
2463 /*IsImplicit=*/true);
2464 const CXXScopeSpec CS = CXXScopeSpec();
2465 Expr *ME = BuildMemberExpr(ThisExpr, /*IsArrow=*/true, SourceLocation(),
2466 NestedNameSpecifierLoc(), SourceLocation(), FD,
2467 DeclAccessPair::make(FD, FD->getAccess()),
2468 /*HadMultipleCandidates=*/false,
2469 DeclarationNameInfo(), FD->getType(),
2470 VK_LValue, OK_Ordinary);
2471 OMPCapturedExprDecl *CD = buildCaptureDecl(
2472 *this, FD->getIdentifier(), ME, DVarPrivate.CKind != OMPC_private,
2473 CurContext->getParent(), /*AsExpression=*/false);
2474 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
2475 *this, CD, CD->getType().getNonReferenceType(), SourceLocation());
2476 VD = cast<VarDecl>(VDPrivateRefExpr->getDecl());
2477 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->addImplicitDefaultFirstprivateFD(FD, VD);
2478 return VD;
2479 }
2480 if (DVarPrivate.CKind != OMPC_unknown ||
2481 (VD && (DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getDefaultDSA() == DSA_none ||
2482 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getDefaultDSA() == DSA_private ||
2483 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getDefaultDSA() == DSA_firstprivate)))
2484 return VD ? VD : cast<VarDecl>(DVarPrivate.PrivateCopy->getDecl());
2485 }
2486 return nullptr;
2487}
2488
2489void Sema::adjustOpenMPTargetScopeIndex(unsigned &FunctionScopesIndex,
2490 unsigned Level) const {
2491 FunctionScopesIndex -= getOpenMPCaptureLevels(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getDirective(Level));
2492}
2493
2494void Sema::startOpenMPLoop() {
2495 assert(LangOpts.OpenMP && "OpenMP must be enabled.")(static_cast <bool> (LangOpts.OpenMP && "OpenMP must be enabled."
) ? void (0) : __assert_fail ("LangOpts.OpenMP && \"OpenMP must be enabled.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 2495, __extension__ __PRETTY_FUNCTION__
))
;
2496 if (isOpenMPLoopDirective(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective()))
2497 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->loopInit();
2498}
2499
2500void Sema::startOpenMPCXXRangeFor() {
2501 assert(LangOpts.OpenMP && "OpenMP must be enabled.")(static_cast <bool> (LangOpts.OpenMP && "OpenMP must be enabled."
) ? void (0) : __assert_fail ("LangOpts.OpenMP && \"OpenMP must be enabled.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 2501, __extension__ __PRETTY_FUNCTION__
))
;
2502 if (isOpenMPLoopDirective(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective())) {
2503 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->resetPossibleLoopCounter();
2504 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->loopStart();
2505 }
2506}
2507
2508OpenMPClauseKind Sema::isOpenMPPrivateDecl(ValueDecl *D, unsigned Level,
2509 unsigned CapLevel) const {
2510 assert(LangOpts.OpenMP && "OpenMP is not allowed")(static_cast <bool> (LangOpts.OpenMP && "OpenMP is not allowed"
) ? void (0) : __assert_fail ("LangOpts.OpenMP && \"OpenMP is not allowed\""
, "clang/lib/Sema/SemaOpenMP.cpp", 2510, __extension__ __PRETTY_FUNCTION__
))
;
2511 if (DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective() != OMPD_unknown &&
2512 (!DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isClauseParsingMode() ||
2513 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getParentDirective() != OMPD_unknown)) {
2514 DSAStackTy::DSAVarData DVarPrivate = DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->hasDSA(
2515 D,
2516 [](OpenMPClauseKind C, bool AppliedToPointee,
2517 DefaultDataSharingAttributes DefaultAttr) {
2518 return isOpenMPPrivate(C) && !AppliedToPointee &&
2519 DefaultAttr == DSA_private;
2520 },
2521 [](OpenMPDirectiveKind) { return true; },
2522 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isClauseParsingMode());
2523 if (DVarPrivate.CKind == OMPC_private && isa<OMPCapturedExprDecl>(D) &&
2524 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isImplicitDefaultFirstprivateFD(cast<VarDecl>(D)) &&
2525 !DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isLoopControlVariable(D).first)
2526 return OMPC_private;
2527 }
2528 if (DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->hasExplicitDirective(isOpenMPTaskingDirective, Level)) {
2529 bool IsTriviallyCopyable =
2530 D->getType().getNonReferenceType().isTriviallyCopyableType(Context) &&
2531 !D->getType()
2532 .getNonReferenceType()
2533 .getCanonicalType()
2534 ->getAsCXXRecordDecl();
2535 OpenMPDirectiveKind DKind = DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getDirective(Level);
2536 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
2537 getOpenMPCaptureRegions(CaptureRegions, DKind);
2538 if (isOpenMPTaskingDirective(CaptureRegions[CapLevel]) &&
2539 (IsTriviallyCopyable ||
2540 !isOpenMPTaskLoopDirective(CaptureRegions[CapLevel]))) {
2541 if (DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->hasExplicitDSA(
2542 D,
2543 [](OpenMPClauseKind K, bool) { return K == OMPC_firstprivate; },
2544 Level, /*NotLastprivate=*/true))
2545 return OMPC_firstprivate;
2546 DSAStackTy::DSAVarData DVar = DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getImplicitDSA(D, Level);
2547 if (DVar.CKind != OMPC_shared &&
2548 !DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isLoopControlVariable(D, Level).first && !DVar.RefExpr) {
2549 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->addImplicitTaskFirstprivate(Level, D);
2550 return OMPC_firstprivate;
2551 }
2552 }
2553 }
2554 if (isOpenMPLoopDirective(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective())) {
2555 if (DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getAssociatedLoops() > 0 && !DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isLoopStarted()) {
2556 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->resetPossibleLoopCounter(D);
2557 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->loopStart();
2558 return OMPC_private;
2559 }
2560 if ((DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getPossiblyLoopCunter() == D->getCanonicalDecl() ||
2561 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isLoopControlVariable(D).first) &&
2562 !DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->hasExplicitDSA(
2563 D, [](OpenMPClauseKind K, bool) { return K != OMPC_private; },
2564 Level) &&
2565 !isOpenMPSimdDirective(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective()))
2566 return OMPC_private;
2567 }
2568 if (const auto *VD = dyn_cast<VarDecl>(D)) {
2569 if (DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isThreadPrivate(const_cast<VarDecl *>(VD)) &&
2570 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isForceVarCapturing() &&
2571 !DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->hasExplicitDSA(
2572 D, [](OpenMPClauseKind K, bool) { return K == OMPC_copyin; },
2573 Level))
2574 return OMPC_private;
2575 }
2576 // User-defined allocators are private since they must be defined in the
2577 // context of target region.
2578 if (DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->hasExplicitDirective(isOpenMPTargetExecutionDirective, Level) &&
2579 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isUsesAllocatorsDecl(Level, D).value_or(
2580 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
2581 DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator)
2582 return OMPC_private;
2583 return (DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->hasExplicitDSA(
2584 D, [](OpenMPClauseKind K, bool) { return K == OMPC_private; },
2585 Level) ||
2586 (DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isClauseParsingMode() &&
2587 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getClauseParsingMode() == OMPC_private) ||
2588 // Consider taskgroup reduction descriptor variable a private
2589 // to avoid possible capture in the region.
2590 (DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->hasExplicitDirective(
2591 [](OpenMPDirectiveKind K) {
2592 return K == OMPD_taskgroup ||
2593 ((isOpenMPParallelDirective(K) ||
2594 isOpenMPWorksharingDirective(K)) &&
2595 !isOpenMPSimdDirective(K));
2596 },
2597 Level) &&
2598 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isTaskgroupReductionRef(D, Level)))
2599 ? OMPC_private
2600 : OMPC_unknown;
2601}
2602
2603void Sema::setOpenMPCaptureKind(FieldDecl *FD, const ValueDecl *D,
2604 unsigned Level) {
2605 assert(LangOpts.OpenMP && "OpenMP is not allowed")(static_cast <bool> (LangOpts.OpenMP && "OpenMP is not allowed"
) ? void (0) : __assert_fail ("LangOpts.OpenMP && \"OpenMP is not allowed\""
, "clang/lib/Sema/SemaOpenMP.cpp", 2605, __extension__ __PRETTY_FUNCTION__
))
;
2606 D = getCanonicalDecl(D);
2607 OpenMPClauseKind OMPC = OMPC_unknown;
2608 for (unsigned I = DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getNestingLevel() + 1; I > Level; --I) {
2609 const unsigned NewLevel = I - 1;
2610 if (DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->hasExplicitDSA(
2611 D,
2612 [&OMPC](const OpenMPClauseKind K, bool AppliedToPointee) {
2613 if (isOpenMPPrivate(K) && !AppliedToPointee) {
2614 OMPC = K;
2615 return true;
2616 }
2617 return false;
2618 },
2619 NewLevel))
2620 break;
2621 if (DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->checkMappableExprComponentListsForDeclAtLevel(
2622 D, NewLevel,
2623 [](OMPClauseMappableExprCommon::MappableExprComponentListRef,
2624 OpenMPClauseKind) { return true; })) {
2625 OMPC = OMPC_map;
2626 break;
2627 }
2628 if (DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->hasExplicitDirective(isOpenMPTargetExecutionDirective,
2629 NewLevel)) {
2630 OMPC = OMPC_map;
2631 if (DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->mustBeFirstprivateAtLevel(
2632 NewLevel, getVariableCategoryFromDecl(LangOpts, D)))
2633 OMPC = OMPC_firstprivate;
2634 break;
2635 }
2636 }
2637 if (OMPC != OMPC_unknown)
2638 FD->addAttr(OMPCaptureKindAttr::CreateImplicit(Context, unsigned(OMPC)));
2639}
2640
2641bool Sema::isOpenMPTargetCapturedDecl(const ValueDecl *D, unsigned Level,
2642 unsigned CaptureLevel) const {
2643 assert(LangOpts.OpenMP && "OpenMP is not allowed")(static_cast <bool> (LangOpts.OpenMP && "OpenMP is not allowed"
) ? void (0) : __assert_fail ("LangOpts.OpenMP && \"OpenMP is not allowed\""
, "clang/lib/Sema/SemaOpenMP.cpp", 2643, __extension__ __PRETTY_FUNCTION__
))
;
2644 // Return true if the current level is no longer enclosed in a target region.
2645
2646 SmallVector<OpenMPDirectiveKind, 4> Regions;
2647 getOpenMPCaptureRegions(Regions, DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getDirective(Level));
2648 const auto *VD = dyn_cast<VarDecl>(D);
2649 return VD && !VD->hasLocalStorage() &&
2650 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->hasExplicitDirective(isOpenMPTargetExecutionDirective,
2651 Level) &&
2652 Regions[CaptureLevel] != OMPD_task;
2653}
2654
2655bool Sema::isOpenMPGlobalCapturedDecl(ValueDecl *D, unsigned Level,
2656 unsigned CaptureLevel) const {
2657 assert(LangOpts.OpenMP && "OpenMP is not allowed")(static_cast <bool> (LangOpts.OpenMP && "OpenMP is not allowed"
) ? void (0) : __assert_fail ("LangOpts.OpenMP && \"OpenMP is not allowed\""
, "clang/lib/Sema/SemaOpenMP.cpp", 2657, __extension__ __PRETTY_FUNCTION__
))
;
2658 // Return true if the current level is no longer enclosed in a target region.
2659
2660 if (const auto *VD = dyn_cast<VarDecl>(D)) {
2661 if (!VD->hasLocalStorage()) {
2662 if (isInOpenMPTargetExecutionDirective())
2663 return true;
2664 DSAStackTy::DSAVarData TopDVar =
2665 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getTopDSA(D, /*FromParent=*/false);
2666 unsigned NumLevels =
2667 getOpenMPCaptureLevels(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getDirective(Level));
2668 if (Level == 0)
2669 // non-file scope static variale with default(firstprivate)
2670 // should be gloabal captured.
2671 return (NumLevels == CaptureLevel + 1 &&
2672 (TopDVar.CKind != OMPC_shared ||
2673 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getDefaultDSA() == DSA_firstprivate));
2674 do {
2675 --Level;
2676 DSAStackTy::DSAVarData DVar = DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getImplicitDSA(D, Level);
2677 if (DVar.CKind != OMPC_shared)
2678 return true;
2679 } while (Level > 0);
2680 }
2681 }
2682 return true;
2683}
2684
2685void Sema::DestroyDataSharingAttributesStack() { delete DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
; }
2686
2687void Sema::ActOnOpenMPBeginDeclareVariant(SourceLocation Loc,
2688 OMPTraitInfo &TI) {
2689 OMPDeclareVariantScopes.push_back(OMPDeclareVariantScope(TI));
2690}
2691
2692void Sema::ActOnOpenMPEndDeclareVariant() {
2693 assert(isInOpenMPDeclareVariantScope() &&(static_cast <bool> (isInOpenMPDeclareVariantScope() &&
"Not in OpenMP declare variant scope!") ? void (0) : __assert_fail
("isInOpenMPDeclareVariantScope() && \"Not in OpenMP declare variant scope!\""
, "clang/lib/Sema/SemaOpenMP.cpp", 2694, __extension__ __PRETTY_FUNCTION__
))
2694 "Not in OpenMP declare variant scope!")(static_cast <bool> (isInOpenMPDeclareVariantScope() &&
"Not in OpenMP declare variant scope!") ? void (0) : __assert_fail
("isInOpenMPDeclareVariantScope() && \"Not in OpenMP declare variant scope!\""
, "clang/lib/Sema/SemaOpenMP.cpp", 2694, __extension__ __PRETTY_FUNCTION__
))
;
2695
2696 OMPDeclareVariantScopes.pop_back();
2697}
2698
2699void Sema::finalizeOpenMPDelayedAnalysis(const FunctionDecl *Caller,
2700 const FunctionDecl *Callee,
2701 SourceLocation Loc) {
2702 assert(LangOpts.OpenMP && "Expected OpenMP compilation mode.")(static_cast <bool> (LangOpts.OpenMP && "Expected OpenMP compilation mode."
) ? void (0) : __assert_fail ("LangOpts.OpenMP && \"Expected OpenMP compilation mode.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 2702, __extension__ __PRETTY_FUNCTION__
))
;
2703 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2704 OMPDeclareTargetDeclAttr::getDeviceType(Caller->getMostRecentDecl());
2705 // Ignore host functions during device analyzis.
2706 if (LangOpts.OpenMPIsDevice &&
2707 (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host))
2708 return;
2709 // Ignore nohost functions during host analyzis.
2710 if (!LangOpts.OpenMPIsDevice && DevTy &&
2711 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
2712 return;
2713 const FunctionDecl *FD = Callee->getMostRecentDecl();
2714 DevTy = OMPDeclareTargetDeclAttr::getDeviceType(FD);
2715 if (LangOpts.OpenMPIsDevice && DevTy &&
2716 *DevTy == OMPDeclareTargetDeclAttr::DT_Host) {
2717 // Diagnose host function called during device codegen.
2718 StringRef HostDevTy =
2719 getOpenMPSimpleClauseTypeName(OMPC_device_type, OMPC_DEVICE_TYPE_host);
2720 Diag(Loc, diag::err_omp_wrong_device_function_call) << HostDevTy << 0;
2721 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2722 diag::note_omp_marked_device_type_here)
2723 << HostDevTy;
2724 return;
2725 }
2726 if (!LangOpts.OpenMPIsDevice && !LangOpts.OpenMPOffloadMandatory && DevTy &&
2727 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) {
2728 // In OpenMP 5.2 or later, if the function has a host variant then allow
2729 // that to be called instead
2730 auto &&HasHostAttr = [](const FunctionDecl *Callee) {
2731 for (OMPDeclareVariantAttr *A :
2732 Callee->specific_attrs<OMPDeclareVariantAttr>()) {
2733 auto *DeclRefVariant = cast<DeclRefExpr>(A->getVariantFuncRef());
2734 auto *VariantFD = cast<FunctionDecl>(DeclRefVariant->getDecl());
2735 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2736 OMPDeclareTargetDeclAttr::getDeviceType(
2737 VariantFD->getMostRecentDecl());
2738 if (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host)
2739 return true;
2740 }
2741 return false;
2742 };
2743 if (getLangOpts().OpenMP >= 52 &&
2744 Callee->hasAttr<OMPDeclareVariantAttr>() && HasHostAttr(Callee))
2745 return;
2746 // Diagnose nohost function called during host codegen.
2747 StringRef NoHostDevTy = getOpenMPSimpleClauseTypeName(
2748 OMPC_device_type, OMPC_DEVICE_TYPE_nohost);
2749 Diag(Loc, diag::err_omp_wrong_device_function_call) << NoHostDevTy << 1;
2750 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2751 diag::note_omp_marked_device_type_here)
2752 << NoHostDevTy;
2753 }
2754}
2755
2756void Sema::StartOpenMPDSABlock(OpenMPDirectiveKind DKind,
2757 const DeclarationNameInfo &DirName,
2758 Scope *CurScope, SourceLocation Loc) {
2759 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->push(DKind, DirName, CurScope, Loc);
2760 PushExpressionEvaluationContext(
2761 ExpressionEvaluationContext::PotentiallyEvaluated);
2762}
2763
2764void Sema::StartOpenMPClause(OpenMPClauseKind K) {
2765 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->setClauseParsingMode(K);
2766}
2767
2768void Sema::EndOpenMPClause() {
2769 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->setClauseParsingMode(/*K=*/OMPC_unknown);
2770 CleanupVarDeclMarking();
2771}
2772
2773static std::pair<ValueDecl *, bool>
2774getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc,
2775 SourceRange &ERange, bool AllowArraySection = false,
2776 StringRef DiagType = "");
2777
2778/// Check consistency of the reduction clauses.
2779static void checkReductionClauses(Sema &S, DSAStackTy *Stack,
2780 ArrayRef<OMPClause *> Clauses) {
2781 bool InscanFound = false;
2782 SourceLocation InscanLoc;
2783 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions.
2784 // A reduction clause without the inscan reduction-modifier may not appear on
2785 // a construct on which a reduction clause with the inscan reduction-modifier
2786 // appears.
2787 for (OMPClause *C : Clauses) {
2788 if (C->getClauseKind() != OMPC_reduction)
2789 continue;
2790 auto *RC = cast<OMPReductionClause>(C);
2791 if (RC->getModifier() == OMPC_REDUCTION_inscan) {
2792 InscanFound = true;
2793 InscanLoc = RC->getModifierLoc();
2794 continue;
2795 }
2796 if (RC->getModifier() == OMPC_REDUCTION_task) {
2797 // OpenMP 5.0, 2.19.5.4 reduction Clause.
2798 // A reduction clause with the task reduction-modifier may only appear on
2799 // a parallel construct, a worksharing construct or a combined or
2800 // composite construct for which any of the aforementioned constructs is a
2801 // constituent construct and simd or loop are not constituent constructs.
2802 OpenMPDirectiveKind CurDir = Stack->getCurrentDirective();
2803 if (!(isOpenMPParallelDirective(CurDir) ||
2804 isOpenMPWorksharingDirective(CurDir)) ||
2805 isOpenMPSimdDirective(CurDir))
2806 S.Diag(RC->getModifierLoc(),
2807 diag::err_omp_reduction_task_not_parallel_or_worksharing);
2808 continue;
2809 }
2810 }
2811 if (InscanFound) {
2812 for (OMPClause *C : Clauses) {
2813 if (C->getClauseKind() != OMPC_reduction)
2814 continue;
2815 auto *RC = cast<OMPReductionClause>(C);
2816 if (RC->getModifier() != OMPC_REDUCTION_inscan) {
2817 S.Diag(RC->getModifier() == OMPC_REDUCTION_unknown
2818 ? RC->getBeginLoc()
2819 : RC->getModifierLoc(),
2820 diag::err_omp_inscan_reduction_expected);
2821 S.Diag(InscanLoc, diag::note_omp_previous_inscan_reduction);
2822 continue;
2823 }
2824 for (Expr *Ref : RC->varlists()) {
2825 assert(Ref && "NULL expr in OpenMP nontemporal clause.")(static_cast <bool> (Ref && "NULL expr in OpenMP nontemporal clause."
) ? void (0) : __assert_fail ("Ref && \"NULL expr in OpenMP nontemporal clause.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 2825, __extension__ __PRETTY_FUNCTION__
))
;
2826 SourceLocation ELoc;
2827 SourceRange ERange;
2828 Expr *SimpleRefExpr = Ref;
2829 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
2830 /*AllowArraySection=*/true);
2831 ValueDecl *D = Res.first;
2832 if (!D)
2833 continue;
2834 if (!Stack->isUsedInScanDirective(getCanonicalDecl(D))) {
2835 S.Diag(Ref->getExprLoc(),
2836 diag::err_omp_reduction_not_inclusive_exclusive)
2837 << Ref->getSourceRange();
2838 }
2839 }
2840 }
2841 }
2842}
2843
2844static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
2845 ArrayRef<OMPClause *> Clauses);
2846static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
2847 bool WithInit);
2848
2849static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
2850 const ValueDecl *D,
2851 const DSAStackTy::DSAVarData &DVar,
2852 bool IsLoopIterVar = false);
2853
2854void Sema::EndOpenMPDSABlock(Stmt *CurDirective) {
2855 // OpenMP [2.14.3.5, Restrictions, C/C++, p.1]
2856 // A variable of class type (or array thereof) that appears in a lastprivate
2857 // clause requires an accessible, unambiguous default constructor for the
2858 // class type, unless the list item is also specified in a firstprivate
2859 // clause.
2860 if (const auto *D = dyn_cast_or_null<OMPExecutableDirective>(CurDirective)) {
2861 for (OMPClause *C : D->clauses()) {
2862 if (auto *Clause = dyn_cast<OMPLastprivateClause>(C)) {
2863 SmallVector<Expr *, 8> PrivateCopies;
2864 for (Expr *DE : Clause->varlists()) {
2865 if (DE->isValueDependent() || DE->isTypeDependent()) {
2866 PrivateCopies.push_back(nullptr);
2867 continue;
2868 }
2869 auto *DRE = cast<DeclRefExpr>(DE->IgnoreParens());
2870 auto *VD = cast<VarDecl>(DRE->getDecl());
2871 QualType Type = VD->getType().getNonReferenceType();
2872 const DSAStackTy::DSAVarData DVar =
2873 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getTopDSA(VD, /*FromParent=*/false);
2874 if (DVar.CKind == OMPC_lastprivate) {
2875 // Generate helper private variable and initialize it with the
2876 // default value. The address of the original variable is replaced
2877 // by the address of the new private variable in CodeGen. This new
2878 // variable is not added to IdResolver, so the code in the OpenMP
2879 // region uses original variable for proper diagnostics.
2880 VarDecl *VDPrivate = buildVarDecl(
2881 *this, DE->getExprLoc(), Type.getUnqualifiedType(),
2882 VD->getName(), VD->hasAttrs() ? &VD->getAttrs() : nullptr, DRE);
2883 ActOnUninitializedDecl(VDPrivate);
2884 if (VDPrivate->isInvalidDecl()) {
2885 PrivateCopies.push_back(nullptr);
2886 continue;
2887 }
2888 PrivateCopies.push_back(buildDeclRefExpr(
2889 *this, VDPrivate, DE->getType(), DE->getExprLoc()));
2890 } else {
2891 // The variable is also a firstprivate, so initialization sequence
2892 // for private copy is generated already.
2893 PrivateCopies.push_back(nullptr);
2894 }
2895 }
2896 Clause->setPrivateCopies(PrivateCopies);
2897 continue;
2898 }
2899 // Finalize nontemporal clause by handling private copies, if any.
2900 if (auto *Clause = dyn_cast<OMPNontemporalClause>(C)) {
2901 SmallVector<Expr *, 8> PrivateRefs;
2902 for (Expr *RefExpr : Clause->varlists()) {
2903 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.")(static_cast <bool> (RefExpr && "NULL expr in OpenMP nontemporal clause."
) ? void (0) : __assert_fail ("RefExpr && \"NULL expr in OpenMP nontemporal clause.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 2903, __extension__ __PRETTY_FUNCTION__
))
;
2904 SourceLocation ELoc;
2905 SourceRange ERange;
2906 Expr *SimpleRefExpr = RefExpr;
2907 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
2908 if (Res.second)
2909 // It will be analyzed later.
2910 PrivateRefs.push_back(RefExpr);
2911 ValueDecl *D = Res.first;
2912 if (!D)
2913 continue;
2914
2915 const DSAStackTy::DSAVarData DVar =
2916 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getTopDSA(D, /*FromParent=*/false);
2917 PrivateRefs.push_back(DVar.PrivateCopy ? DVar.PrivateCopy
2918 : SimpleRefExpr);
2919 }
2920 Clause->setPrivateRefs(PrivateRefs);
2921 continue;
2922 }
2923 if (auto *Clause = dyn_cast<OMPUsesAllocatorsClause>(C)) {
2924 for (unsigned I = 0, E = Clause->getNumberOfAllocators(); I < E; ++I) {
2925 OMPUsesAllocatorsClause::Data D = Clause->getAllocatorData(I);
2926 auto *DRE = dyn_cast<DeclRefExpr>(D.Allocator->IgnoreParenImpCasts());
2927 if (!DRE)
2928 continue;
2929 ValueDecl *VD = DRE->getDecl();
2930 if (!VD || !isa<VarDecl>(VD))
2931 continue;
2932 DSAStackTy::DSAVarData DVar =
2933 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getTopDSA(VD, /*FromParent=*/false);
2934 // OpenMP [2.12.5, target Construct]
2935 // Memory allocators that appear in a uses_allocators clause cannot
2936 // appear in other data-sharing attribute clauses or data-mapping
2937 // attribute clauses in the same construct.
2938 Expr *MapExpr = nullptr;
2939 if (DVar.RefExpr ||
2940 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->checkMappableExprComponentListsForDecl(
2941 VD, /*CurrentRegionOnly=*/true,
2942 [VD, &MapExpr](
2943 OMPClauseMappableExprCommon::MappableExprComponentListRef
2944 MapExprComponents,
2945 OpenMPClauseKind C) {
2946 auto MI = MapExprComponents.rbegin();
2947 auto ME = MapExprComponents.rend();
2948 if (MI != ME &&
2949 MI->getAssociatedDeclaration()->getCanonicalDecl() ==
2950 VD->getCanonicalDecl()) {
2951 MapExpr = MI->getAssociatedExpression();
2952 return true;
2953 }
2954 return false;
2955 })) {
2956 Diag(D.Allocator->getExprLoc(),
2957 diag::err_omp_allocator_used_in_clauses)
2958 << D.Allocator->getSourceRange();
2959 if (DVar.RefExpr)
2960 reportOriginalDsa(*this, DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
, VD, DVar);
2961 else
2962 Diag(MapExpr->getExprLoc(), diag::note_used_here)
2963 << MapExpr->getSourceRange();
2964 }
2965 }
2966 continue;
2967 }
2968 }
2969 // Check allocate clauses.
2970 if (!CurContext->isDependentContext())
2971 checkAllocateClauses(*this, DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
, D->clauses());
2972 checkReductionClauses(*this, DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
, D->clauses());
2973 }
2974
2975 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->pop();
2976 DiscardCleanupsInEvaluationContext();
2977 PopExpressionEvaluationContext();
2978}
2979
2980static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
2981 Expr *NumIterations, Sema &SemaRef,
2982 Scope *S, DSAStackTy *Stack);
2983
2984namespace {
2985
2986class VarDeclFilterCCC final : public CorrectionCandidateCallback {
2987private:
2988 Sema &SemaRef;
2989
2990public:
2991 explicit VarDeclFilterCCC(Sema &S) : SemaRef(S) {}
2992 bool ValidateCandidate(const TypoCorrection &Candidate) override {
2993 NamedDecl *ND = Candidate.getCorrectionDecl();
2994 if (const auto *VD = dyn_cast_or_null<VarDecl>(ND)) {
2995 return VD->hasGlobalStorage() &&
2996 SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(),
2997 SemaRef.getCurScope());
2998 }
2999 return false;
3000 }
3001
3002 std::unique_ptr<CorrectionCandidateCallback> clone() override {
3003 return std::make_unique<VarDeclFilterCCC>(*this);
3004 }
3005};
3006
3007class VarOrFuncDeclFilterCCC final : public CorrectionCandidateCallback {
3008private:
3009 Sema &SemaRef;
3010
3011public:
3012 explicit VarOrFuncDeclFilterCCC(Sema &S) : SemaRef(S) {}
3013 bool ValidateCandidate(const TypoCorrection &Candidate) override {
3014 NamedDecl *ND = Candidate.getCorrectionDecl();
3015 if (ND && ((isa<VarDecl>(ND) && ND->getKind() == Decl::Var) ||
3016 isa<FunctionDecl>(ND))) {
3017 return SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(),
3018 SemaRef.getCurScope());
3019 }
3020 return false;
3021 }
3022
3023 std::unique_ptr<CorrectionCandidateCallback> clone() override {
3024 return std::make_unique<VarOrFuncDeclFilterCCC>(*this);
3025 }
3026};
3027
3028} // namespace
3029
3030ExprResult Sema::ActOnOpenMPIdExpression(Scope *CurScope,
3031 CXXScopeSpec &ScopeSpec,
3032 const DeclarationNameInfo &Id,
3033 OpenMPDirectiveKind Kind) {
3034 LookupResult Lookup(*this, Id, LookupOrdinaryName);
3035 LookupParsedName(Lookup, CurScope, &ScopeSpec, true);
3036
3037 if (Lookup.isAmbiguous())
3038 return ExprError();
3039
3040 VarDecl *VD;
3041 if (!Lookup.isSingleResult()) {
3042 VarDeclFilterCCC CCC(*this);
3043 if (TypoCorrection Corrected =
3044 CorrectTypo(Id, LookupOrdinaryName, CurScope, nullptr, CCC,
3045 CTK_ErrorRecovery)) {
3046 diagnoseTypo(Corrected,
3047 PDiag(Lookup.empty()
3048 ? diag::err_undeclared_var_use_suggest
3049 : diag::err_omp_expected_var_arg_suggest)
3050 << Id.getName());
3051 VD = Corrected.getCorrectionDeclAs<VarDecl>();
3052 } else {
3053 Diag(Id.getLoc(), Lookup.empty() ? diag::err_undeclared_var_use
3054 : diag::err_omp_expected_var_arg)
3055 << Id.getName();
3056 return ExprError();
3057 }
3058 } else if (!(VD = Lookup.getAsSingle<VarDecl>())) {
3059 Diag(Id.getLoc(), diag::err_omp_expected_var_arg) << Id.getName();
3060 Diag(Lookup.getFoundDecl()->getLocation(), diag::note_declared_at);
3061 return ExprError();
3062 }
3063 Lookup.suppressDiagnostics();
3064
3065 // OpenMP [2.9.2, Syntax, C/C++]
3066 // Variables must be file-scope, namespace-scope, or static block-scope.
3067 if (Kind == OMPD_threadprivate && !VD->hasGlobalStorage()) {
3068 Diag(Id.getLoc(), diag::err_omp_global_var_arg)
3069 << getOpenMPDirectiveName(Kind) << !VD->isStaticLocal();
3070 bool IsDecl =
3071 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3072 Diag(VD->getLocation(),
3073 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3074 << VD;
3075 return ExprError();
3076 }
3077
3078 VarDecl *CanonicalVD = VD->getCanonicalDecl();
3079 NamedDecl *ND = CanonicalVD;
3080 // OpenMP [2.9.2, Restrictions, C/C++, p.2]
3081 // A threadprivate directive for file-scope variables must appear outside
3082 // any definition or declaration.
3083 if (CanonicalVD->getDeclContext()->isTranslationUnit() &&
3084 !getCurLexicalContext()->isTranslationUnit()) {
3085 Diag(Id.getLoc(), diag::err_omp_var_scope)
3086 << getOpenMPDirectiveName(Kind) << VD;
3087 bool IsDecl =
3088 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3089 Diag(VD->getLocation(),
3090 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3091 << VD;
3092 return ExprError();
3093 }
3094 // OpenMP [2.9.2, Restrictions, C/C++, p.3]
3095 // A threadprivate directive for static class member variables must appear
3096 // in the class definition, in the same scope in which the member
3097 // variables are declared.
3098 if (CanonicalVD->isStaticDataMember() &&
3099 !CanonicalVD->getDeclContext()->Equals(getCurLexicalContext())) {
3100 Diag(Id.getLoc(), diag::err_omp_var_scope)
3101 << getOpenMPDirectiveName(Kind) << VD;
3102 bool IsDecl =
3103 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3104 Diag(VD->getLocation(),
3105 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3106 << VD;
3107 return ExprError();
3108 }
3109 // OpenMP [2.9.2, Restrictions, C/C++, p.4]
3110 // A threadprivate directive for namespace-scope variables must appear
3111 // outside any definition or declaration other than the namespace
3112 // definition itself.
3113 if (CanonicalVD->getDeclContext()->isNamespace() &&
3114 (!getCurLexicalContext()->isFileContext() ||
3115 !getCurLexicalContext()->Encloses(CanonicalVD->getDeclContext()))) {
3116 Diag(Id.getLoc(), diag::err_omp_var_scope)
3117 << getOpenMPDirectiveName(Kind) << VD;
3118 bool IsDecl =
3119 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3120 Diag(VD->getLocation(),
3121 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3122 << VD;
3123 return ExprError();
3124 }
3125 // OpenMP [2.9.2, Restrictions, C/C++, p.6]
3126 // A threadprivate directive for static block-scope variables must appear
3127 // in the scope of the variable and not in a nested scope.
3128 if (CanonicalVD->isLocalVarDecl() && CurScope &&
3129 !isDeclInScope(ND, getCurLexicalContext(), CurScope)) {
3130 Diag(Id.getLoc(), diag::err_omp_var_scope)
3131 << getOpenMPDirectiveName(Kind) << VD;
3132 bool IsDecl =
3133 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3134 Diag(VD->getLocation(),
3135 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3136 << VD;
3137 return ExprError();
3138 }
3139
3140 // OpenMP [2.9.2, Restrictions, C/C++, p.2-6]
3141 // A threadprivate directive must lexically precede all references to any
3142 // of the variables in its list.
3143 if (Kind == OMPD_threadprivate && VD->isUsed() &&
3144 !DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isThreadPrivate(VD)) {
3145 Diag(Id.getLoc(), diag::err_omp_var_used)
3146 << getOpenMPDirectiveName(Kind) << VD;
3147 return ExprError();
3148 }
3149
3150 QualType ExprType = VD->getType().getNonReferenceType();
3151 return DeclRefExpr::Create(Context, NestedNameSpecifierLoc(),
3152 SourceLocation(), VD,
3153 /*RefersToEnclosingVariableOrCapture=*/false,
3154 Id.getLoc(), ExprType, VK_LValue);
3155}
3156
3157Sema::DeclGroupPtrTy
3158Sema::ActOnOpenMPThreadprivateDirective(SourceLocation Loc,
3159 ArrayRef<Expr *> VarList) {
3160 if (OMPThreadPrivateDecl *D = CheckOMPThreadPrivateDecl(Loc, VarList)) {
3161 CurContext->addDecl(D);
3162 return DeclGroupPtrTy::make(DeclGroupRef(D));
3163 }
3164 return nullptr;
3165}
3166
3167namespace {
3168class LocalVarRefChecker final
3169 : public ConstStmtVisitor<LocalVarRefChecker, bool> {
3170 Sema &SemaRef;
3171
3172public:
3173 bool VisitDeclRefExpr(const DeclRefExpr *E) {
3174 if (const auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
3175 if (VD->hasLocalStorage()) {
3176 SemaRef.Diag(E->getBeginLoc(),
3177 diag::err_omp_local_var_in_threadprivate_init)
3178 << E->getSourceRange();
3179 SemaRef.Diag(VD->getLocation(), diag::note_defined_here)
3180 << VD << VD->getSourceRange();
3181 return true;
3182 }
3183 }
3184 return false;
3185 }
3186 bool VisitStmt(const Stmt *S) {
3187 for (const Stmt *Child : S->children()) {
3188 if (Child && Visit(Child))
3189 return true;
3190 }
3191 return false;
3192 }
3193 explicit LocalVarRefChecker(Sema &SemaRef) : SemaRef(SemaRef) {}
3194};
3195} // namespace
3196
3197OMPThreadPrivateDecl *
3198Sema::CheckOMPThreadPrivateDecl(SourceLocation Loc, ArrayRef<Expr *> VarList) {
3199 SmallVector<Expr *, 8> Vars;
3200 for (Expr *RefExpr : VarList) {
3201 auto *DE = cast<DeclRefExpr>(RefExpr);
3202 auto *VD = cast<VarDecl>(DE->getDecl());
3203 SourceLocation ILoc = DE->getExprLoc();
3204
3205 // Mark variable as used.
3206 VD->setReferenced();
3207 VD->markUsed(Context);
3208
3209 QualType QType = VD->getType();
3210 if (QType->isDependentType() || QType->isInstantiationDependentType()) {
3211 // It will be analyzed later.
3212 Vars.push_back(DE);
3213 continue;
3214 }
3215
3216 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3217 // A threadprivate variable must not have an incomplete type.
3218 if (RequireCompleteType(ILoc, VD->getType(),
3219 diag::err_omp_threadprivate_incomplete_type)) {
3220 continue;
3221 }
3222
3223 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3224 // A threadprivate variable must not have a reference type.
3225 if (VD->getType()->isReferenceType()) {
3226 Diag(ILoc, diag::err_omp_ref_type_arg)
3227 << getOpenMPDirectiveName(OMPD_threadprivate) << VD->getType();
3228 bool IsDecl =
3229 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3230 Diag(VD->getLocation(),
3231 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3232 << VD;
3233 continue;
3234 }
3235
3236 // Check if this is a TLS variable. If TLS is not being supported, produce
3237 // the corresponding diagnostic.
3238 if ((VD->getTLSKind() != VarDecl::TLS_None &&
3239 !(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
3240 getLangOpts().OpenMPUseTLS &&
3241 getASTContext().getTargetInfo().isTLSSupported())) ||
3242 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3243 !VD->isLocalVarDecl())) {
3244 Diag(ILoc, diag::err_omp_var_thread_local)
3245 << VD << ((VD->getTLSKind() != VarDecl::TLS_None) ? 0 : 1);
3246 bool IsDecl =
3247 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3248 Diag(VD->getLocation(),
3249 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3250 << VD;
3251 continue;
3252 }
3253
3254 // Check if initial value of threadprivate variable reference variable with
3255 // local storage (it is not supported by runtime).
3256 if (const Expr *Init = VD->getAnyInitializer()) {
3257 LocalVarRefChecker Checker(*this);
3258 if (Checker.Visit(Init))
3259 continue;
3260 }
3261
3262 Vars.push_back(RefExpr);
3263 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->addDSA(VD, DE, OMPC_threadprivate);
3264 VD->addAttr(OMPThreadPrivateDeclAttr::CreateImplicit(
3265 Context, SourceRange(Loc, Loc)));
3266 if (ASTMutationListener *ML = Context.getASTMutationListener())
3267 ML->DeclarationMarkedOpenMPThreadPrivate(VD);
3268 }
3269 OMPThreadPrivateDecl *D = nullptr;
3270 if (!Vars.empty()) {
3271 D = OMPThreadPrivateDecl::Create(Context, getCurLexicalContext(), Loc,
3272 Vars);
3273 D->setAccess(AS_public);
3274 }
3275 return D;
3276}
3277
3278static OMPAllocateDeclAttr::AllocatorTypeTy
3279getAllocatorKind(Sema &S, DSAStackTy *Stack, Expr *Allocator) {
3280 if (!Allocator)
3281 return OMPAllocateDeclAttr::OMPNullMemAlloc;
3282 if (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3283 Allocator->isInstantiationDependent() ||
3284 Allocator->containsUnexpandedParameterPack())
3285 return OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3286 auto AllocatorKindRes = OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3287 llvm::FoldingSetNodeID AEId;
3288 const Expr *AE = Allocator->IgnoreParenImpCasts();
3289 AE->IgnoreImpCasts()->Profile(AEId, S.getASTContext(), /*Canonical=*/true);
3290 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
3291 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
3292 const Expr *DefAllocator = Stack->getAllocator(AllocatorKind);
3293 llvm::FoldingSetNodeID DAEId;
3294 DefAllocator->IgnoreImpCasts()->Profile(DAEId, S.getASTContext(),
3295 /*Canonical=*/true);
3296 if (AEId == DAEId) {
3297 AllocatorKindRes = AllocatorKind;
3298 break;
3299 }
3300 }
3301 return AllocatorKindRes;
3302}
3303
3304static bool checkPreviousOMPAllocateAttribute(
3305 Sema &S, DSAStackTy *Stack, Expr *RefExpr, VarDecl *VD,
3306 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind, Expr *Allocator) {
3307 if (!VD->hasAttr<OMPAllocateDeclAttr>())
3308 return false;
3309 const auto *A = VD->getAttr<OMPAllocateDeclAttr>();
3310 Expr *PrevAllocator = A->getAllocator();
3311 OMPAllocateDeclAttr::AllocatorTypeTy PrevAllocatorKind =
3312 getAllocatorKind(S, Stack, PrevAllocator);
3313 bool AllocatorsMatch = AllocatorKind == PrevAllocatorKind;
3314 if (AllocatorsMatch &&
3315 AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc &&
3316 Allocator && PrevAllocator) {
3317 const Expr *AE = Allocator->IgnoreParenImpCasts();
3318 const Expr *PAE = PrevAllocator->IgnoreParenImpCasts();
3319 llvm::FoldingSetNodeID AEId, PAEId;
3320 AE->Profile(AEId, S.Context, /*Canonical=*/true);
3321 PAE->Profile(PAEId, S.Context, /*Canonical=*/true);
3322 AllocatorsMatch = AEId == PAEId;
3323 }
3324 if (!AllocatorsMatch) {
3325 SmallString<256> AllocatorBuffer;
3326 llvm::raw_svector_ostream AllocatorStream(AllocatorBuffer);
3327 if (Allocator)
3328 Allocator->printPretty(AllocatorStream, nullptr, S.getPrintingPolicy());
3329 SmallString<256> PrevAllocatorBuffer;
3330 llvm::raw_svector_ostream PrevAllocatorStream(PrevAllocatorBuffer);
3331 if (PrevAllocator)
3332 PrevAllocator->printPretty(PrevAllocatorStream, nullptr,
3333 S.getPrintingPolicy());
3334
3335 SourceLocation AllocatorLoc =
3336 Allocator ? Allocator->getExprLoc() : RefExpr->getExprLoc();
3337 SourceRange AllocatorRange =
3338 Allocator ? Allocator->getSourceRange() : RefExpr->getSourceRange();
3339 SourceLocation PrevAllocatorLoc =
3340 PrevAllocator ? PrevAllocator->getExprLoc() : A->getLocation();
3341 SourceRange PrevAllocatorRange =
3342 PrevAllocator ? PrevAllocator->getSourceRange() : A->getRange();
3343 S.Diag(AllocatorLoc, diag::warn_omp_used_different_allocator)
3344 << (Allocator ? 1 : 0) << AllocatorStream.str()
3345 << (PrevAllocator ? 1 : 0) << PrevAllocatorStream.str()
3346 << AllocatorRange;
3347 S.Diag(PrevAllocatorLoc, diag::note_omp_previous_allocator)
3348 << PrevAllocatorRange;
3349 return true;
3350 }
3351 return false;
3352}
3353
3354static void
3355applyOMPAllocateAttribute(Sema &S, VarDecl *VD,
3356 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
3357 Expr *Allocator, Expr *Alignment, SourceRange SR) {
3358 if (VD->hasAttr<OMPAllocateDeclAttr>())
3359 return;
3360 if (Alignment &&
3361 (Alignment->isTypeDependent() || Alignment->isValueDependent() ||
3362 Alignment->isInstantiationDependent() ||
3363 Alignment->containsUnexpandedParameterPack()))
3364 // Apply later when we have a usable value.
3365 return;
3366 if (Allocator &&
3367 (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3368 Allocator->isInstantiationDependent() ||
3369 Allocator->containsUnexpandedParameterPack()))
3370 return;
3371 auto *A = OMPAllocateDeclAttr::CreateImplicit(S.Context, AllocatorKind,
3372 Allocator, Alignment, SR);
3373 VD->addAttr(A);
3374 if (ASTMutationListener *ML = S.Context.getASTMutationListener())
3375 ML->DeclarationMarkedOpenMPAllocate(VD, A);
3376}
3377
3378Sema::DeclGroupPtrTy
3379Sema::ActOnOpenMPAllocateDirective(SourceLocation Loc, ArrayRef<Expr *> VarList,
3380 ArrayRef<OMPClause *> Clauses,
3381 DeclContext *Owner) {
3382 assert(Clauses.size() <= 2 && "Expected at most two clauses.")(static_cast <bool> (Clauses.size() <= 2 && "Expected at most two clauses."
) ? void (0) : __assert_fail ("Clauses.size() <= 2 && \"Expected at most two clauses.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 3382, __extension__ __PRETTY_FUNCTION__
))
;
3383 Expr *Alignment = nullptr;
3384 Expr *Allocator = nullptr;
3385 if (Clauses.empty()) {
3386 // OpenMP 5.0, 2.11.3 allocate Directive, Restrictions.
3387 // allocate directives that appear in a target region must specify an
3388 // allocator clause unless a requires directive with the dynamic_allocators
3389 // clause is present in the same compilation unit.
3390 if (LangOpts.OpenMPIsDevice &&
3391 !DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
3392 targetDiag(Loc, diag::err_expected_allocator_clause);
3393 } else {
3394 for (const OMPClause *C : Clauses)
3395 if (const auto *AC = dyn_cast<OMPAllocatorClause>(C))
3396 Allocator = AC->getAllocator();
3397 else if (const auto *AC = dyn_cast<OMPAlignClause>(C))
3398 Alignment = AC->getAlignment();
3399 else
3400 llvm_unreachable("Unexpected clause on allocate directive")::llvm::llvm_unreachable_internal("Unexpected clause on allocate directive"
, "clang/lib/Sema/SemaOpenMP.cpp", 3400)
;
3401 }
3402 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
3403 getAllocatorKind(*this, DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
, Allocator);
3404 SmallVector<Expr *, 8> Vars;
3405 for (Expr *RefExpr : VarList) {
3406 auto *DE = cast<DeclRefExpr>(RefExpr);
3407 auto *VD = cast<VarDecl>(DE->getDecl());
3408
3409 // Check if this is a TLS variable or global register.
3410 if (VD->getTLSKind() != VarDecl::TLS_None ||
3411 VD->hasAttr<OMPThreadPrivateDeclAttr>() ||
3412 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3413 !VD->isLocalVarDecl()))
3414 continue;
3415
3416 // If the used several times in the allocate directive, the same allocator
3417 // must be used.
3418 if (checkPreviousOMPAllocateAttribute(*this, DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
, RefExpr, VD,
3419 AllocatorKind, Allocator))
3420 continue;
3421
3422 // OpenMP, 2.11.3 allocate Directive, Restrictions, C / C++
3423 // If a list item has a static storage type, the allocator expression in the
3424 // allocator clause must be a constant expression that evaluates to one of
3425 // the predefined memory allocator values.
3426 if (Allocator && VD->hasGlobalStorage()) {
3427 if (AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc) {
3428 Diag(Allocator->getExprLoc(),
3429 diag::err_omp_expected_predefined_allocator)
3430 << Allocator->getSourceRange();
3431 bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
3432 VarDecl::DeclarationOnly;
3433 Diag(VD->getLocation(),
3434 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3435 << VD;
3436 continue;
3437 }
3438 }
3439
3440 Vars.push_back(RefExpr);
3441 applyOMPAllocateAttribute(*this, VD, AllocatorKind, Allocator, Alignment,
3442 DE->getSourceRange());
3443 }
3444 if (Vars.empty())
3445 return nullptr;
3446 if (!Owner)
3447 Owner = getCurLexicalContext();
3448 auto *D = OMPAllocateDecl::Create(Context, Owner, Loc, Vars, Clauses);
3449 D->setAccess(AS_public);
3450 Owner->addDecl(D);
3451 return DeclGroupPtrTy::make(DeclGroupRef(D));
3452}
3453
3454Sema::DeclGroupPtrTy
3455Sema::ActOnOpenMPRequiresDirective(SourceLocation Loc,
3456 ArrayRef<OMPClause *> ClauseList) {
3457 OMPRequiresDecl *D = nullptr;
3458 if (!CurContext->isFileContext()) {
3459 Diag(Loc, diag::err_omp_invalid_scope) << "requires";
3460 } else {
3461 D = CheckOMPRequiresDecl(Loc, ClauseList);
3462 if (D) {
3463 CurContext->addDecl(D);
3464 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->addRequiresDecl(D);
3465 }
3466 }
3467 return DeclGroupPtrTy::make(DeclGroupRef(D));
3468}
3469
3470void Sema::ActOnOpenMPAssumesDirective(SourceLocation Loc,
3471 OpenMPDirectiveKind DKind,
3472 ArrayRef<std::string> Assumptions,
3473 bool SkippedClauses) {
3474 if (!SkippedClauses && Assumptions.empty())
3475 Diag(Loc, diag::err_omp_no_clause_for_directive)
3476 << llvm::omp::getAllAssumeClauseOptions()
3477 << llvm::omp::getOpenMPDirectiveName(DKind);
3478
3479 auto *AA = AssumptionAttr::Create(Context, llvm::join(Assumptions, ","), Loc);
3480 if (DKind == llvm::omp::Directive::OMPD_begin_assumes) {
3481 OMPAssumeScoped.push_back(AA);
3482 return;
3483 }
3484
3485 // Global assumes without assumption clauses are ignored.
3486 if (Assumptions.empty())
3487 return;
3488
3489 assert(DKind == llvm::omp::Directive::OMPD_assumes &&(static_cast <bool> (DKind == llvm::omp::Directive::OMPD_assumes
&& "Unexpected omp assumption directive!") ? void (0
) : __assert_fail ("DKind == llvm::omp::Directive::OMPD_assumes && \"Unexpected omp assumption directive!\""
, "clang/lib/Sema/SemaOpenMP.cpp", 3490, __extension__ __PRETTY_FUNCTION__
))
3490 "Unexpected omp assumption directive!")(static_cast <bool> (DKind == llvm::omp::Directive::OMPD_assumes
&& "Unexpected omp assumption directive!") ? void (0
) : __assert_fail ("DKind == llvm::omp::Directive::OMPD_assumes && \"Unexpected omp assumption directive!\""
, "clang/lib/Sema/SemaOpenMP.cpp", 3490, __extension__ __PRETTY_FUNCTION__
))
;
3491 OMPAssumeGlobal.push_back(AA);
3492
3493 // The OMPAssumeGlobal scope above will take care of new declarations but
3494 // we also want to apply the assumption to existing ones, e.g., to
3495 // declarations in included headers. To this end, we traverse all existing
3496 // declaration contexts and annotate function declarations here.
3497 SmallVector<DeclContext *, 8> DeclContexts;
3498 auto *Ctx = CurContext;
3499 while (Ctx->getLexicalParent())
3500 Ctx = Ctx->getLexicalParent();
3501 DeclContexts.push_back(Ctx);
3502 while (!DeclContexts.empty()) {
3503 DeclContext *DC = DeclContexts.pop_back_val();
3504 for (auto *SubDC : DC->decls()) {
3505 if (SubDC->isInvalidDecl())
3506 continue;
3507 if (auto *CTD = dyn_cast<ClassTemplateDecl>(SubDC)) {
3508 DeclContexts.push_back(CTD->getTemplatedDecl());
3509 llvm::append_range(DeclContexts, CTD->specializations());
3510 continue;
3511 }
3512 if (auto *DC = dyn_cast<DeclContext>(SubDC))
3513 DeclContexts.push_back(DC);
3514 if (auto *F = dyn_cast<FunctionDecl>(SubDC)) {
3515 F->addAttr(AA);
3516 continue;
3517 }
3518 }
3519 }
3520}
3521
3522void Sema::ActOnOpenMPEndAssumesDirective() {
3523 assert(isInOpenMPAssumeScope() && "Not in OpenMP assumes scope!")(static_cast <bool> (isInOpenMPAssumeScope() &&
"Not in OpenMP assumes scope!") ? void (0) : __assert_fail (
"isInOpenMPAssumeScope() && \"Not in OpenMP assumes scope!\""
, "clang/lib/Sema/SemaOpenMP.cpp", 3523, __extension__ __PRETTY_FUNCTION__
))
;
3524 OMPAssumeScoped.pop_back();
3525}
3526
3527OMPRequiresDecl *Sema::CheckOMPRequiresDecl(SourceLocation Loc,
3528 ArrayRef<OMPClause *> ClauseList) {
3529 /// For target specific clauses, the requires directive cannot be
3530 /// specified after the handling of any of the target regions in the
3531 /// current compilation unit.
3532 ArrayRef<SourceLocation> TargetLocations =
3533 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getEncounteredTargetLocs();
3534 SourceLocation AtomicLoc = DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getAtomicDirectiveLoc();
3535 if (!TargetLocations.empty() || !AtomicLoc.isInvalid()) {
3536 for (const OMPClause *CNew : ClauseList) {
3537 // Check if any of the requires clauses affect target regions.
3538 if (isa<OMPUnifiedSharedMemoryClause>(CNew) ||
3539 isa<OMPUnifiedAddressClause>(CNew) ||
3540 isa<OMPReverseOffloadClause>(CNew) ||
3541 isa<OMPDynamicAllocatorsClause>(CNew)) {
3542 Diag(Loc, diag::err_omp_directive_before_requires)
3543 << "target" << getOpenMPClauseName(CNew->getClauseKind());
3544 for (SourceLocation TargetLoc : TargetLocations) {
3545 Diag(TargetLoc, diag::note_omp_requires_encountered_directive)
3546 << "target";
3547 }
3548 } else if (!AtomicLoc.isInvalid() &&
3549 isa<OMPAtomicDefaultMemOrderClause>(CNew)) {
3550 Diag(Loc, diag::err_omp_directive_before_requires)
3551 << "atomic" << getOpenMPClauseName(CNew->getClauseKind());
3552 Diag(AtomicLoc, diag::note_omp_requires_encountered_directive)
3553 << "atomic";
3554 }
3555 }
3556 }
3557
3558 if (!DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->hasDuplicateRequiresClause(ClauseList))
3559 return OMPRequiresDecl::Create(Context, getCurLexicalContext(), Loc,
3560 ClauseList);
3561 return nullptr;
3562}
3563
3564static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
3565 const ValueDecl *D,
3566 const DSAStackTy::DSAVarData &DVar,
3567 bool IsLoopIterVar) {
3568 if (DVar.RefExpr) {
3569 SemaRef.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa)
3570 << getOpenMPClauseName(DVar.CKind);
3571 return;
3572 }
3573 enum {
3574 PDSA_StaticMemberShared,
3575 PDSA_StaticLocalVarShared,
3576 PDSA_LoopIterVarPrivate,
3577 PDSA_LoopIterVarLinear,
3578 PDSA_LoopIterVarLastprivate,
3579 PDSA_ConstVarShared,
3580 PDSA_GlobalVarShared,
3581 PDSA_TaskVarFirstprivate,
3582 PDSA_LocalVarPrivate,
3583 PDSA_Implicit
3584 } Reason = PDSA_Implicit;
3585 bool ReportHint = false;
3586 auto ReportLoc = D->getLocation();
3587 auto *VD = dyn_cast<VarDecl>(D);
3588 if (IsLoopIterVar) {
3589 if (DVar.CKind == OMPC_private)
3590 Reason = PDSA_LoopIterVarPrivate;
3591 else if (DVar.CKind == OMPC_lastprivate)
3592 Reason = PDSA_LoopIterVarLastprivate;
3593 else
3594 Reason = PDSA_LoopIterVarLinear;
3595 } else if (isOpenMPTaskingDirective(DVar.DKind) &&
3596 DVar.CKind == OMPC_firstprivate) {
3597 Reason = PDSA_TaskVarFirstprivate;
3598 ReportLoc = DVar.ImplicitDSALoc;
3599 } else if (VD && VD->isStaticLocal())
3600 Reason = PDSA_StaticLocalVarShared;
3601 else if (VD && VD->isStaticDataMember())
3602 Reason = PDSA_StaticMemberShared;
3603 else if (VD && VD->isFileVarDecl())
3604 Reason = PDSA_GlobalVarShared;
3605 else if (D->getType().isConstant(SemaRef.getASTContext()))
3606 Reason = PDSA_ConstVarShared;
3607 else if (VD && VD->isLocalVarDecl() && DVar.CKind == OMPC_private) {
3608 ReportHint = true;
3609 Reason = PDSA_LocalVarPrivate;
3610 }
3611 if (Reason != PDSA_Implicit) {
3612 SemaRef.Diag(ReportLoc, diag::note_omp_predetermined_dsa)
3613 << Reason << ReportHint
3614 << getOpenMPDirectiveName(Stack->getCurrentDirective());
3615 } else if (DVar.ImplicitDSALoc.isValid()) {
3616 SemaRef.Diag(DVar.ImplicitDSALoc, diag::note_omp_implicit_dsa)
3617 << getOpenMPClauseName(DVar.CKind);
3618 }
3619}
3620
3621static OpenMPMapClauseKind
3622getMapClauseKindFromModifier(OpenMPDefaultmapClauseModifier M,
3623 bool IsAggregateOrDeclareTarget) {
3624 OpenMPMapClauseKind Kind = OMPC_MAP_unknown;
3625 switch (M) {
3626 case OMPC_DEFAULTMAP_MODIFIER_alloc:
3627 Kind = OMPC_MAP_alloc;
3628 break;
3629 case OMPC_DEFAULTMAP_MODIFIER_to:
3630 Kind = OMPC_MAP_to;
3631 break;
3632 case OMPC_DEFAULTMAP_MODIFIER_from:
3633 Kind = OMPC_MAP_from;
3634 break;
3635 case OMPC_DEFAULTMAP_MODIFIER_tofrom:
3636 Kind = OMPC_MAP_tofrom;
3637 break;
3638 case OMPC_DEFAULTMAP_MODIFIER_present:
3639 // OpenMP 5.1 [2.21.7.3] defaultmap clause, Description]
3640 // If implicit-behavior is present, each variable referenced in the
3641 // construct in the category specified by variable-category is treated as if
3642 // it had been listed in a map clause with the map-type of alloc and
3643 // map-type-modifier of present.
3644 Kind = OMPC_MAP_alloc;
3645 break;
3646 case OMPC_DEFAULTMAP_MODIFIER_firstprivate:
3647 case OMPC_DEFAULTMAP_MODIFIER_last:
3648 llvm_unreachable("Unexpected defaultmap implicit behavior")::llvm::llvm_unreachable_internal("Unexpected defaultmap implicit behavior"
, "clang/lib/Sema/SemaOpenMP.cpp", 3648)
;
3649 case OMPC_DEFAULTMAP_MODIFIER_none:
3650 case OMPC_DEFAULTMAP_MODIFIER_default:
3651 case OMPC_DEFAULTMAP_MODIFIER_unknown:
3652 // IsAggregateOrDeclareTarget could be true if:
3653 // 1. the implicit behavior for aggregate is tofrom
3654 // 2. it's a declare target link
3655 if (IsAggregateOrDeclareTarget) {
3656 Kind = OMPC_MAP_tofrom;
3657 break;
3658 }
3659 llvm_unreachable("Unexpected defaultmap implicit behavior")::llvm::llvm_unreachable_internal("Unexpected defaultmap implicit behavior"
, "clang/lib/Sema/SemaOpenMP.cpp", 3659)
;
3660 }
3661 assert(Kind != OMPC_MAP_unknown && "Expect map kind to be known")(static_cast <bool> (Kind != OMPC_MAP_unknown &&
"Expect map kind to be known") ? void (0) : __assert_fail ("Kind != OMPC_MAP_unknown && \"Expect map kind to be known\""
, "clang/lib/Sema/SemaOpenMP.cpp", 3661, __extension__ __PRETTY_FUNCTION__
))
;
3662 return Kind;
3663}
3664
3665namespace {
3666class DSAAttrChecker final : public StmtVisitor<DSAAttrChecker, void> {
3667 DSAStackTy *Stack;
3668 Sema &SemaRef;
3669 bool ErrorFound = false;
3670 bool TryCaptureCXXThisMembers = false;
3671 CapturedStmt *CS = nullptr;
3672 const static unsigned DefaultmapKindNum = OMPC_DEFAULTMAP_pointer + 1;
3673 llvm::SmallVector<Expr *, 4> ImplicitFirstprivate;
3674 llvm::SmallVector<Expr *, 4> ImplicitPrivate;
3675 llvm::SmallVector<Expr *, 4> ImplicitMap[DefaultmapKindNum][OMPC_MAP_delete];
3676 llvm::SmallVector<OpenMPMapModifierKind, NumberOfOMPMapClauseModifiers>
3677 ImplicitMapModifier[DefaultmapKindNum];
3678 Sema::VarsWithInheritedDSAType VarsWithInheritedDSA;
3679 llvm::SmallDenseSet<const ValueDecl *, 4> ImplicitDeclarations;
3680
3681 void VisitSubCaptures(OMPExecutableDirective *S) {
3682 // Check implicitly captured variables.
3683 if (!S->hasAssociatedStmt() || !S->getAssociatedStmt())
3684 return;
3685 if (S->getDirectiveKind() == OMPD_atomic ||
3686 S->getDirectiveKind() == OMPD_critical ||
3687 S->getDirectiveKind() == OMPD_section ||
3688 S->getDirectiveKind() == OMPD_master ||
3689 S->getDirectiveKind() == OMPD_masked ||
3690 isOpenMPLoopTransformationDirective(S->getDirectiveKind())) {
3691 Visit(S->getAssociatedStmt());
3692 return;
3693 }
3694 visitSubCaptures(S->getInnermostCapturedStmt());
3695 // Try to capture inner this->member references to generate correct mappings
3696 // and diagnostics.
3697 if (TryCaptureCXXThisMembers ||
3698 (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) &&
3699 llvm::any_of(S->getInnermostCapturedStmt()->captures(),
3700 [](const CapturedStmt::Capture &C) {
3701 return C.capturesThis();
3702 }))) {
3703 bool SavedTryCaptureCXXThisMembers = TryCaptureCXXThisMembers;
3704 TryCaptureCXXThisMembers = true;
3705 Visit(S->getInnermostCapturedStmt()->getCapturedStmt());
3706 TryCaptureCXXThisMembers = SavedTryCaptureCXXThisMembers;
3707 }
3708 // In tasks firstprivates are not captured anymore, need to analyze them
3709 // explicitly.
3710 if (isOpenMPTaskingDirective(S->getDirectiveKind()) &&
3711 !isOpenMPTaskLoopDirective(S->getDirectiveKind())) {
3712 for (OMPClause *C : S->clauses())
3713 if (auto *FC = dyn_cast<OMPFirstprivateClause>(C)) {
3714 for (Expr *Ref : FC->varlists())
3715 Visit(Ref);
3716 }
3717 }
3718 }
3719
3720public:
3721 void VisitDeclRefExpr(DeclRefExpr *E) {
3722 if (TryCaptureCXXThisMembers || E->isTypeDependent() ||
3723 E->isValueDependent() || E->containsUnexpandedParameterPack() ||
3724 E->isInstantiationDependent())
3725 return;
3726 if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
3727 // Check the datasharing rules for the expressions in the clauses.
3728 if (!CS || (isa<OMPCapturedExprDecl>(VD) && !CS->capturesVariable(VD) &&
3729 !Stack->getTopDSA(VD, /*FromParent=*/false).RefExpr &&
3730 !Stack->isImplicitDefaultFirstprivateFD(VD))) {
3731 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(VD))
3732 if (!CED->hasAttr<OMPCaptureNoInitAttr>()) {
3733 Visit(CED->getInit());
3734 return;
3735 }
3736 } else if (VD->isImplicit() || isa<OMPCapturedExprDecl>(VD))
3737 // Do not analyze internal variables and do not enclose them into
3738 // implicit clauses.
3739 if (!Stack->isImplicitDefaultFirstprivateFD(VD))
3740 return;
3741 VD = VD->getCanonicalDecl();
3742 // Skip internally declared variables.
3743 if (VD->hasLocalStorage() && CS && !CS->capturesVariable(VD) &&
3744 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
3745 !Stack->isImplicitTaskFirstprivate(VD))
3746 return;
3747 // Skip allocators in uses_allocators clauses.
3748 if (Stack->isUsesAllocatorsDecl(VD))
3749 return;
3750
3751 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false);
3752 // Check if the variable has explicit DSA set and stop analysis if it so.
3753 if (DVar.RefExpr || !ImplicitDeclarations.insert(VD).second)
3754 return;
3755
3756 // Skip internally declared static variables.
3757 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
3758 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
3759 if (VD->hasGlobalStorage() && CS && !CS->capturesVariable(VD) &&
3760 (Stack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
3761 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) &&
3762 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
3763 !Stack->isImplicitTaskFirstprivate(VD))
3764 return;
3765
3766 SourceLocation ELoc = E->getExprLoc();
3767 OpenMPDirectiveKind DKind = Stack->getCurrentDirective();
3768 // The default(none) clause requires that each variable that is referenced
3769 // in the construct, and does not have a predetermined data-sharing
3770 // attribute, must have its data-sharing attribute explicitly determined
3771 // by being listed in a data-sharing attribute clause.
3772 if (DVar.CKind == OMPC_unknown &&
3773 (Stack->getDefaultDSA() == DSA_none ||
3774 Stack->getDefaultDSA() == DSA_private ||
3775 Stack->getDefaultDSA() == DSA_firstprivate) &&
3776 isImplicitOrExplicitTaskingRegion(DKind) &&
3777 VarsWithInheritedDSA.count(VD) == 0) {
3778 bool InheritedDSA = Stack->getDefaultDSA() == DSA_none;
3779 if (!InheritedDSA && (Stack->getDefaultDSA() == DSA_firstprivate ||
3780 Stack->getDefaultDSA() == DSA_private)) {
3781 DSAStackTy::DSAVarData DVar =
3782 Stack->getImplicitDSA(VD, /*FromParent=*/false);
3783 InheritedDSA = DVar.CKind == OMPC_unknown;
3784 }
3785 if (InheritedDSA)
3786 VarsWithInheritedDSA[VD] = E;
3787 if (Stack->getDefaultDSA() == DSA_none)
3788 return;
3789 }
3790
3791 // OpenMP 5.0 [2.19.7.2, defaultmap clause, Description]
3792 // If implicit-behavior is none, each variable referenced in the
3793 // construct that does not have a predetermined data-sharing attribute
3794 // and does not appear in a to or link clause on a declare target
3795 // directive must be listed in a data-mapping attribute clause, a
3796 // data-sharing attribute clause (including a data-sharing attribute
3797 // clause on a combined construct where target. is one of the
3798 // constituent constructs), or an is_device_ptr clause.
3799 OpenMPDefaultmapClauseKind ClauseKind =
3800 getVariableCategoryFromDecl(SemaRef.getLangOpts(), VD);
3801 if (SemaRef.getLangOpts().OpenMP >= 50) {
3802 bool IsModifierNone = Stack->getDefaultmapModifier(ClauseKind) ==
3803 OMPC_DEFAULTMAP_MODIFIER_none;
3804 if (DVar.CKind == OMPC_unknown && IsModifierNone &&
3805 VarsWithInheritedDSA.count(VD) == 0 && !Res) {
3806 // Only check for data-mapping attribute and is_device_ptr here
3807 // since we have already make sure that the declaration does not
3808 // have a data-sharing attribute above
3809 if (!Stack->checkMappableExprComponentListsForDecl(
3810 VD, /*CurrentRegionOnly=*/true,
3811 [VD](OMPClauseMappableExprCommon::MappableExprComponentListRef
3812 MapExprComponents,
3813 OpenMPClauseKind) {
3814 auto MI = MapExprComponents.rbegin();
3815 auto ME = MapExprComponents.rend();
3816 return MI != ME && MI->getAssociatedDeclaration() == VD;
3817 })) {
3818 VarsWithInheritedDSA[VD] = E;
3819 return;
3820 }
3821 }
3822 }
3823 if (SemaRef.getLangOpts().OpenMP > 50) {
3824 bool IsModifierPresent = Stack->getDefaultmapModifier(ClauseKind) ==
3825 OMPC_DEFAULTMAP_MODIFIER_present;
3826 if (IsModifierPresent) {
3827 if (!llvm::is_contained(ImplicitMapModifier[ClauseKind],
3828 OMPC_MAP_MODIFIER_present)) {
3829 ImplicitMapModifier[ClauseKind].push_back(
3830 OMPC_MAP_MODIFIER_present);
3831 }
3832 }
3833 }
3834
3835 if (isOpenMPTargetExecutionDirective(DKind) &&
3836 !Stack->isLoopControlVariable(VD).first) {
3837 if (!Stack->checkMappableExprComponentListsForDecl(
3838 VD, /*CurrentRegionOnly=*/true,
3839 [this](OMPClauseMappableExprCommon::MappableExprComponentListRef
3840 StackComponents,
3841 OpenMPClauseKind) {
3842 if (SemaRef.LangOpts.OpenMP >= 50)
3843 return !StackComponents.empty();
3844 // Variable is used if it has been marked as an array, array
3845 // section, array shaping or the variable iself.
3846 return StackComponents.size() == 1 ||
3847 llvm::all_of(
3848 llvm::drop_begin(llvm::reverse(StackComponents)),
3849 [](const OMPClauseMappableExprCommon::
3850 MappableComponent &MC) {
3851 return MC.getAssociatedDeclaration() ==
3852 nullptr &&
3853 (isa<OMPArraySectionExpr>(
3854 MC.getAssociatedExpression()) ||
3855 isa<OMPArrayShapingExpr>(
3856 MC.getAssociatedExpression()) ||
3857 isa<ArraySubscriptExpr>(
3858 MC.getAssociatedExpression()));
3859 });
3860 })) {
3861 bool IsFirstprivate = false;
3862 // By default lambdas are captured as firstprivates.
3863 if (const auto *RD =
3864 VD->getType().getNonReferenceType()->getAsCXXRecordDecl())
3865 IsFirstprivate = RD->isLambda();
3866 IsFirstprivate =
3867 IsFirstprivate || (Stack->mustBeFirstprivate(ClauseKind) && !Res);
3868 if (IsFirstprivate) {
3869 ImplicitFirstprivate.emplace_back(E);
3870 } else {
3871 OpenMPDefaultmapClauseModifier M =
3872 Stack->getDefaultmapModifier(ClauseKind);
3873 OpenMPMapClauseKind Kind = getMapClauseKindFromModifier(
3874 M, ClauseKind == OMPC_DEFAULTMAP_aggregate || Res);
3875 ImplicitMap[ClauseKind][Kind].emplace_back(E);
3876 }
3877 return;
3878 }
3879 }
3880
3881 // OpenMP [2.9.3.6, Restrictions, p.2]
3882 // A list item that appears in a reduction clause of the innermost
3883 // enclosing worksharing or parallel construct may not be accessed in an
3884 // explicit task.
3885 DVar = Stack->hasInnermostDSA(
3886 VD,
3887 [](OpenMPClauseKind C, bool AppliedToPointee) {
3888 return C == OMPC_reduction && !AppliedToPointee;
3889 },
3890 [](OpenMPDirectiveKind K) {
3891 return isOpenMPParallelDirective(K) ||
3892 isOpenMPWorksharingDirective(K) || isOpenMPTeamsDirective(K);
3893 },
3894 /*FromParent=*/true);
3895 if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
3896 ErrorFound = true;
3897 SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
3898 reportOriginalDsa(SemaRef, Stack, VD, DVar);
3899 return;
3900 }
3901
3902 // Define implicit data-sharing attributes for task.
3903 DVar = Stack->getImplicitDSA(VD, /*FromParent=*/false);
3904 if (((isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared) ||
3905 (((Stack->getDefaultDSA() == DSA_firstprivate &&
3906 DVar.CKind == OMPC_firstprivate) ||
3907 (Stack->getDefaultDSA() == DSA_private &&
3908 DVar.CKind == OMPC_private)) &&
3909 !DVar.RefExpr)) &&
3910 !Stack->isLoopControlVariable(VD).first) {
3911 if (Stack->getDefaultDSA() == DSA_private)
3912 ImplicitPrivate.push_back(E);
3913 else
3914 ImplicitFirstprivate.push_back(E);
3915 return;
3916 }
3917
3918 // Store implicitly used globals with declare target link for parent
3919 // target.
3920 if (!isOpenMPTargetExecutionDirective(DKind) && Res &&
3921 *Res == OMPDeclareTargetDeclAttr::MT_Link) {
3922 Stack->addToParentTargetRegionLinkGlobals(E);
3923 return;
3924 }
3925 }
3926 }
3927 void VisitMemberExpr(MemberExpr *E) {
3928 if (E->isTypeDependent() || E->isValueDependent() ||
3929 E->containsUnexpandedParameterPack() || E->isInstantiationDependent())
3930 return;
3931 auto *FD = dyn_cast<FieldDecl>(E->getMemberDecl());
3932 OpenMPDirectiveKind DKind = Stack->getCurrentDirective();
3933 if (auto *TE = dyn_cast<CXXThisExpr>(E->getBase()->IgnoreParenCasts())) {
3934 if (!FD)
3935 return;
3936 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(FD, /*FromParent=*/false);
3937 // Check if the variable has explicit DSA set and stop analysis if it
3938 // so.
3939 if (DVar.RefExpr || !ImplicitDeclarations.insert(FD).second)
3940 return;
3941
3942 if (isOpenMPTargetExecutionDirective(DKind) &&
3943 !Stack->isLoopControlVariable(FD).first &&
3944 !Stack->checkMappableExprComponentListsForDecl(
3945 FD, /*CurrentRegionOnly=*/true,
3946 [](OMPClauseMappableExprCommon::MappableExprComponentListRef
3947 StackComponents,
3948 OpenMPClauseKind) {
3949 return isa<CXXThisExpr>(
3950 cast<MemberExpr>(
3951 StackComponents.back().getAssociatedExpression())
3952 ->getBase()
3953 ->IgnoreParens());
3954 })) {
3955 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
3956 // A bit-field cannot appear in a map clause.
3957 //
3958 if (FD->isBitField())
3959 return;
3960
3961 // Check to see if the member expression is referencing a class that
3962 // has already been explicitly mapped
3963 if (Stack->isClassPreviouslyMapped(TE->getType()))
3964 return;
3965
3966 OpenMPDefaultmapClauseModifier Modifier =
3967 Stack->getDefaultmapModifier(OMPC_DEFAULTMAP_aggregate);
3968 OpenMPDefaultmapClauseKind ClauseKind =
3969 getVariableCategoryFromDecl(SemaRef.getLangOpts(), FD);
3970 OpenMPMapClauseKind Kind = getMapClauseKindFromModifier(
3971 Modifier, /*IsAggregateOrDeclareTarget*/ true);
3972 ImplicitMap[ClauseKind][Kind].emplace_back(E);
3973 return;
3974 }
3975
3976 SourceLocation ELoc = E->getExprLoc();
3977 // OpenMP [2.9.3.6, Restrictions, p.2]
3978 // A list item that appears in a reduction clause of the innermost
3979 // enclosing worksharing or parallel construct may not be accessed in
3980 // an explicit task.
3981 DVar = Stack->hasInnermostDSA(
3982 FD,
3983 [](OpenMPClauseKind C, bool AppliedToPointee) {
3984 return C == OMPC_reduction && !AppliedToPointee;
3985 },
3986 [](OpenMPDirectiveKind K) {
3987 return isOpenMPParallelDirective(K) ||
3988 isOpenMPWorksharingDirective(K) || isOpenMPTeamsDirective(K);
3989 },
3990 /*FromParent=*/true);
3991 if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
3992 ErrorFound = true;
3993 SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
3994 reportOriginalDsa(SemaRef, Stack, FD, DVar);
3995 return;
3996 }
3997
3998 // Define implicit data-sharing attributes for task.
3999 DVar = Stack->getImplicitDSA(FD, /*FromParent=*/false);
4000 if (isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared &&
4001 !Stack->isLoopControlVariable(FD).first) {
4002 // Check if there is a captured expression for the current field in the
4003 // region. Do not mark it as firstprivate unless there is no captured
4004 // expression.
4005 // TODO: try to make it firstprivate.
4006 if (DVar.CKind != OMPC_unknown)
4007 ImplicitFirstprivate.push_back(E);
4008 }
4009 return;
4010 }
4011 if (isOpenMPTargetExecutionDirective(DKind)) {
4012 OMPClauseMappableExprCommon::MappableExprComponentList CurComponents;
4013 if (!checkMapClauseExpressionBase(SemaRef, E, CurComponents, OMPC_map,
4014 Stack->getCurrentDirective(),
4015 /*NoDiagnose=*/true))
4016 return;
4017 const auto *VD = cast<ValueDecl>(
4018 CurComponents.back().getAssociatedDeclaration()->getCanonicalDecl());
4019 if (!Stack->checkMappableExprComponentListsForDecl(
4020 VD, /*CurrentRegionOnly=*/true,
4021 [&CurComponents](
4022 OMPClauseMappableExprCommon::MappableExprComponentListRef
4023 StackComponents,
4024 OpenMPClauseKind) {
4025 auto CCI = CurComponents.rbegin();
4026 auto CCE = CurComponents.rend();
4027 for (const auto &SC : llvm::reverse(StackComponents)) {
4028 // Do both expressions have the same kind?
4029 if (CCI->getAssociatedExpression()->getStmtClass() !=
4030 SC.getAssociatedExpression()->getStmtClass())
4031 if (!((isa<OMPArraySectionExpr>(
4032 SC.getAssociatedExpression()) ||
4033 isa<OMPArrayShapingExpr>(
4034 SC.getAssociatedExpression())) &&
4035 isa<ArraySubscriptExpr>(
4036 CCI->getAssociatedExpression())))
4037 return false;
4038
4039 const Decl *CCD = CCI->getAssociatedDeclaration();
4040 const Decl *SCD = SC.getAssociatedDeclaration();
4041 CCD = CCD ? CCD->getCanonicalDecl() : nullptr;
4042 SCD = SCD ? SCD->getCanonicalDecl() : nullptr;
4043 if (SCD != CCD)
4044 return false;
4045 std::advance(CCI, 1);
4046 if (CCI == CCE)
4047 break;
4048 }
4049 return true;
4050 })) {
4051 Visit(E->getBase());
4052 }
4053 } else if (!TryCaptureCXXThisMembers) {
4054 Visit(E->getBase());
4055 }
4056 }
4057 void VisitOMPExecutableDirective(OMPExecutableDirective *S) {
4058 for (OMPClause *C : S->clauses()) {
4059 // Skip analysis of arguments of private clauses for task|target
4060 // directives.
4061 if (isa_and_nonnull<OMPPrivateClause>(C))
4062 continue;
4063 // Skip analysis of arguments of implicitly defined firstprivate clause
4064 // for task|target directives.
4065 // Skip analysis of arguments of implicitly defined map clause for target
4066 // directives.
4067 if (C && !((isa<OMPFirstprivateClause>(C) || isa<OMPMapClause>(C)) &&
4068 C->isImplicit() &&
4069 !isOpenMPTaskingDirective(Stack->getCurrentDirective()))) {
4070 for (Stmt *CC : C->children()) {
4071 if (CC)
4072 Visit(CC);
4073 }
4074 }
4075 }
4076 // Check implicitly captured variables.
4077 VisitSubCaptures(S);
4078 }
4079
4080 void VisitOMPLoopTransformationDirective(OMPLoopTransformationDirective *S) {
4081 // Loop transformation directives do not introduce data sharing
4082 VisitStmt(S);
4083 }
4084
4085 void VisitCallExpr(CallExpr *S) {
4086 for (Stmt *C : S->arguments()) {
4087 if (C) {
4088 // Check implicitly captured variables in the task-based directives to
4089 // check if they must be firstprivatized.
4090 Visit(C);
4091 }
4092 }
4093 if (Expr *Callee = S->getCallee()) {
4094 auto *CI = Callee->IgnoreParenImpCasts();
4095 if (auto *CE = dyn_cast<MemberExpr>(CI))
4096 Visit(CE->getBase());
4097 else if (auto *CE = dyn_cast<DeclRefExpr>(CI))
4098 Visit(CE);
4099 }
4100 }
4101 void VisitStmt(Stmt *S) {
4102 for (Stmt *C : S->children()) {
4103 if (C) {
4104 // Check implicitly captured variables in the task-based directives to
4105 // check if they must be firstprivatized.
4106 Visit(C);
4107 }
4108 }
4109 }
4110
4111 void visitSubCaptures(CapturedStmt *S) {
4112 for (const CapturedStmt::Capture &Cap : S->captures()) {
4113 if (!Cap.capturesVariable() && !Cap.capturesVariableByCopy())
4114 continue;
4115 VarDecl *VD = Cap.getCapturedVar();
4116 // Do not try to map the variable if it or its sub-component was mapped
4117 // already.
4118 if (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) &&
4119 Stack->checkMappableExprComponentListsForDecl(
4120 VD, /*CurrentRegionOnly=*/true,
4121 [](OMPClauseMappableExprCommon::MappableExprComponentListRef,
4122 OpenMPClauseKind) { return true; }))
4123 continue;
4124 DeclRefExpr *DRE = buildDeclRefExpr(
4125 SemaRef, VD, VD->getType().getNonLValueExprType(SemaRef.Context),
4126 Cap.getLocation(), /*RefersToCapture=*/true);
4127 Visit(DRE);
4128 }
4129 }
4130 bool isErrorFound() const { return ErrorFound; }
4131 ArrayRef<Expr *> getImplicitFirstprivate() const {
4132 return ImplicitFirstprivate;
4133 }
4134 ArrayRef<Expr *> getImplicitPrivate() const { return ImplicitPrivate; }
4135 ArrayRef<Expr *> getImplicitMap(OpenMPDefaultmapClauseKind DK,
4136 OpenMPMapClauseKind MK) const {
4137 return ImplicitMap[DK][MK];
4138 }
4139 ArrayRef<OpenMPMapModifierKind>
4140 getImplicitMapModifier(OpenMPDefaultmapClauseKind Kind) const {
4141 return ImplicitMapModifier[Kind];
4142 }
4143 const Sema::VarsWithInheritedDSAType &getVarsWithInheritedDSA() const {
4144 return VarsWithInheritedDSA;
4145 }
4146
4147 DSAAttrChecker(DSAStackTy *S, Sema &SemaRef, CapturedStmt *CS)
4148 : Stack(S), SemaRef(SemaRef), ErrorFound(false), CS(CS) {
4149 // Process declare target link variables for the target directives.
4150 if (isOpenMPTargetExecutionDirective(S->getCurrentDirective())) {
4151 for (DeclRefExpr *E : Stack->getLinkGlobals())
4152 Visit(E);
4153 }
4154 }
4155};
4156} // namespace
4157
4158static void handleDeclareVariantConstructTrait(DSAStackTy *Stack,
4159 OpenMPDirectiveKind DKind,
4160 bool ScopeEntry) {
4161 SmallVector<llvm::omp::TraitProperty, 8> Traits;
4162 if (isOpenMPTargetExecutionDirective(DKind))
4163 Traits.emplace_back(llvm::omp::TraitProperty::construct_target_target);
4164 if (isOpenMPTeamsDirective(DKind))
4165 Traits.emplace_back(llvm::omp::TraitProperty::construct_teams_teams);
4166 if (isOpenMPParallelDirective(DKind))
4167 Traits.emplace_back(llvm::omp::TraitProperty::construct_parallel_parallel);
4168 if (isOpenMPWorksharingDirective(DKind))
4169 Traits.emplace_back(llvm::omp::TraitProperty::construct_for_for);
4170 if (isOpenMPSimdDirective(DKind))
4171 Traits.emplace_back(llvm::omp::TraitProperty::construct_simd_simd);
4172 Stack->handleConstructTrait(Traits, ScopeEntry);
4173}
4174
4175void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
4176 switch (DKind) {
4177 case OMPD_parallel:
4178 case OMPD_parallel_for:
4179 case OMPD_parallel_for_simd:
4180 case OMPD_parallel_sections:
4181 case OMPD_parallel_master:
4182 case OMPD_parallel_masked:
4183 case OMPD_parallel_loop:
4184 case OMPD_teams:
4185 case OMPD_teams_distribute:
4186 case OMPD_teams_distribute_simd: {
4187 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4188 QualType KmpInt32PtrTy =
4189 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4190 Sema::CapturedParamNameType Params[] = {
4191 std::make_pair(".global_tid.", KmpInt32PtrTy),
4192 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4193 std::make_pair(StringRef(), QualType()) // __context with shared vars
4194 };
4195 ActOnCapturedRegionStart(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getConstructLoc(), CurScope, CR_OpenMP,
4196 Params);
4197 break;
4198 }
4199 case OMPD_target_teams:
4200 case OMPD_target_parallel:
4201 case OMPD_target_parallel_for:
4202 case OMPD_target_parallel_for_simd:
4203 case OMPD_target_teams_loop:
4204 case OMPD_target_parallel_loop:
4205 case OMPD_target_teams_distribute:
4206 case OMPD_target_teams_distribute_simd: {
4207 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4208 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4209 QualType KmpInt32PtrTy =
4210 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4211 QualType Args[] = {VoidPtrTy};
4212 FunctionProtoType::ExtProtoInfo EPI;
4213 EPI.Variadic = true;
4214 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4215 Sema::CapturedParamNameType Params[] = {
4216 std::make_pair(".global_tid.", KmpInt32Ty),
4217 std::make_pair(".part_id.", KmpInt32PtrTy),
4218 std::make_pair(".privates.", VoidPtrTy),
4219 std::make_pair(
4220 ".copy_fn.",
4221 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4222 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4223 std::make_pair(StringRef(), QualType()) // __context with shared vars
4224 };
4225 ActOnCapturedRegionStart(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getConstructLoc(), CurScope, CR_OpenMP,
4226 Params, /*OpenMPCaptureLevel=*/0);
4227 // Mark this captured region as inlined, because we don't use outlined
4228 // function directly.
4229 getCurCapturedRegion()->TheCapturedDecl->addAttr(
4230 AlwaysInlineAttr::CreateImplicit(
4231 Context, {}, AlwaysInlineAttr::Keyword_forceinline));
4232 Sema::CapturedParamNameType ParamsTarget[] = {
4233 std::make_pair(StringRef(), QualType()) // __context with shared vars
4234 };
4235 // Start a captured region for 'target' with no implicit parameters.
4236 ActOnCapturedRegionStart(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getConstructLoc(), CurScope, CR_OpenMP,
4237 ParamsTarget, /*OpenMPCaptureLevel=*/1);
4238 Sema::CapturedParamNameType ParamsTeamsOrParallel[] = {
4239 std::make_pair(".global_tid.", KmpInt32PtrTy),
4240 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4241 std::make_pair(StringRef(), QualType()) // __context with shared vars
4242 };
4243 // Start a captured region for 'teams' or 'parallel'. Both regions have
4244 // the same implicit parameters.
4245 ActOnCapturedRegionStart(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getConstructLoc(), CurScope, CR_OpenMP,
4246 ParamsTeamsOrParallel, /*OpenMPCaptureLevel=*/2);
4247 break;
4248 }
4249 case OMPD_target:
4250 case OMPD_target_simd: {
4251 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4252 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4253 QualType KmpInt32PtrTy =
4254 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4255 QualType Args[] = {VoidPtrTy};
4256 FunctionProtoType::ExtProtoInfo EPI;
4257 EPI.Variadic = true;
4258 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4259 Sema::CapturedParamNameType Params[] = {
4260 std::make_pair(".global_tid.", KmpInt32Ty),
4261 std::make_pair(".part_id.", KmpInt32PtrTy),
4262 std::make_pair(".privates.", VoidPtrTy),
4263 std::make_pair(
4264 ".copy_fn.",
4265 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4266 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4267 std::make_pair(StringRef(), QualType()) // __context with shared vars
4268 };
4269 ActOnCapturedRegionStart(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getConstructLoc(), CurScope, CR_OpenMP,
4270 Params, /*OpenMPCaptureLevel=*/0);
4271 // Mark this captured region as inlined, because we don't use outlined
4272 // function directly.
4273 getCurCapturedRegion()->TheCapturedDecl->addAttr(
4274 AlwaysInlineAttr::CreateImplicit(
4275 Context, {}, AlwaysInlineAttr::Keyword_forceinline));
4276 ActOnCapturedRegionStart(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getConstructLoc(), CurScope, CR_OpenMP,
4277 std::make_pair(StringRef(), QualType()),
4278 /*OpenMPCaptureLevel=*/1);
4279 break;
4280 }
4281 case OMPD_atomic:
4282 case OMPD_critical:
4283 case OMPD_section:
4284 case OMPD_master:
4285 case OMPD_masked:
4286 case OMPD_tile:
4287 case OMPD_unroll:
4288 break;
4289 case OMPD_loop:
4290 // TODO: 'loop' may require additional parameters depending on the binding.
4291 // Treat similar to OMPD_simd/OMPD_for for now.
4292 case OMPD_simd:
4293 case OMPD_for:
4294 case OMPD_for_simd:
4295 case OMPD_sections:
4296 case OMPD_single:
4297 case OMPD_taskgroup:
4298 case OMPD_distribute:
4299 case OMPD_distribute_simd:
4300 case OMPD_ordered:
4301 case OMPD_target_data:
4302 case OMPD_dispatch: {
4303 Sema::CapturedParamNameType Params[] = {
4304 std::make_pair(StringRef(), QualType()) // __context with shared vars
4305 };
4306 ActOnCapturedRegionStart(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getConstructLoc(), CurScope, CR_OpenMP,
4307 Params);
4308 break;
4309 }
4310 case OMPD_task: {
4311 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4312 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4313 QualType KmpInt32PtrTy =
4314 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4315 QualType Args[] = {VoidPtrTy};
4316 FunctionProtoType::ExtProtoInfo EPI;
4317 EPI.Variadic = true;
4318 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4319 Sema::CapturedParamNameType Params[] = {
4320 std::make_pair(".global_tid.", KmpInt32Ty),
4321 std::make_pair(".part_id.", KmpInt32PtrTy),
4322 std::make_pair(".privates.", VoidPtrTy),
4323 std::make_pair(
4324 ".copy_fn.",
4325 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4326 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4327 std::make_pair(StringRef(), QualType()) // __context with shared vars
4328 };
4329 ActOnCapturedRegionStart(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getConstructLoc(), CurScope, CR_OpenMP,
4330 Params);
4331 // Mark this captured region as inlined, because we don't use outlined
4332 // function directly.
4333 getCurCapturedRegion()->TheCapturedDecl->addAttr(
4334 AlwaysInlineAttr::CreateImplicit(
4335 Context, {}, AlwaysInlineAttr::Keyword_forceinline));
4336 break;
4337 }
4338 case OMPD_taskloop:
4339 case OMPD_taskloop_simd:
4340 case OMPD_master_taskloop:
4341 case OMPD_masked_taskloop:
4342 case OMPD_masked_taskloop_simd:
4343 case OMPD_master_taskloop_simd: {
4344 QualType KmpInt32Ty =
4345 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1)
4346 .withConst();
4347 QualType KmpUInt64Ty =
4348 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0)
4349 .withConst();
4350 QualType KmpInt64Ty =
4351 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1)
4352 .withConst();
4353 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4354 QualType KmpInt32PtrTy =
4355 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4356 QualType Args[] = {VoidPtrTy};
4357 FunctionProtoType::ExtProtoInfo EPI;
4358 EPI.Variadic = true;
4359 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4360 Sema::CapturedParamNameType Params[] = {
4361 std::make_pair(".global_tid.", KmpInt32Ty),
4362 std::make_pair(".part_id.", KmpInt32PtrTy),
4363 std::make_pair(".privates.", VoidPtrTy),
4364 std::make_pair(
4365 ".copy_fn.",
4366 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4367 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4368 std::make_pair(".lb.", KmpUInt64Ty),
4369 std::make_pair(".ub.", KmpUInt64Ty),
4370 std::make_pair(".st.", KmpInt64Ty),
4371 std::make_pair(".liter.", KmpInt32Ty),
4372 std::make_pair(".reductions.", VoidPtrTy),
4373 std::make_pair(StringRef(), QualType()) // __context with shared vars
4374 };
4375 ActOnCapturedRegionStart(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getConstructLoc(), CurScope, CR_OpenMP,
4376 Params);
4377 // Mark this captured region as inlined, because we don't use outlined
4378 // function directly.
4379 getCurCapturedRegion()->TheCapturedDecl->addAttr(
4380 AlwaysInlineAttr::CreateImplicit(
4381 Context, {}, AlwaysInlineAttr::Keyword_forceinline));
4382 break;
4383 }
4384 case OMPD_parallel_masked_taskloop:
4385 case OMPD_parallel_masked_taskloop_simd:
4386 case OMPD_parallel_master_taskloop:
4387 case OMPD_parallel_master_taskloop_simd: {
4388 QualType KmpInt32Ty =
4389 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1)
4390 .withConst();
4391 QualType KmpUInt64Ty =
4392 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0)
4393 .withConst();
4394 QualType KmpInt64Ty =
4395 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1)
4396 .withConst();
4397 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4398 QualType KmpInt32PtrTy =
4399 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4400 Sema::CapturedParamNameType ParamsParallel[] = {
4401 std::make_pair(".global_tid.", KmpInt32PtrTy),
4402 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4403 std::make_pair(StringRef(), QualType()) // __context with shared vars
4404 };
4405 // Start a captured region for 'parallel'.
4406 ActOnCapturedRegionStart(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getConstructLoc(), CurScope, CR_OpenMP,
4407 ParamsParallel, /*OpenMPCaptureLevel=*/0);
4408 QualType Args[] = {VoidPtrTy};
4409 FunctionProtoType::ExtProtoInfo EPI;
4410 EPI.Variadic = true;
4411 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4412 Sema::CapturedParamNameType Params[] = {
4413 std::make_pair(".global_tid.", KmpInt32Ty),
4414 std::make_pair(".part_id.", KmpInt32PtrTy),
4415 std::make_pair(".privates.", VoidPtrTy),
4416 std::make_pair(
4417 ".copy_fn.",
4418 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4419 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4420 std::make_pair(".lb.", KmpUInt64Ty),
4421 std::make_pair(".ub.", KmpUInt64Ty),
4422 std::make_pair(".st.", KmpInt64Ty),
4423 std::make_pair(".liter.", KmpInt32Ty),
4424 std::make_pair(".reductions.", VoidPtrTy),
4425 std::make_pair(StringRef(), QualType()) // __context with shared vars
4426 };
4427 ActOnCapturedRegionStart(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getConstructLoc(), CurScope, CR_OpenMP,
4428 Params, /*OpenMPCaptureLevel=*/1);
4429 // Mark this captured region as inlined, because we don't use outlined
4430 // function directly.
4431 getCurCapturedRegion()->TheCapturedDecl->addAttr(
4432 AlwaysInlineAttr::CreateImplicit(
4433 Context, {}, AlwaysInlineAttr::Keyword_forceinline));
4434 break;
4435 }
4436 case OMPD_distribute_parallel_for_simd:
4437 case OMPD_distribute_parallel_for: {
4438 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4439 QualType KmpInt32PtrTy =
4440 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4441 Sema::CapturedParamNameType Params[] = {
4442 std::make_pair(".global_tid.", KmpInt32PtrTy),
4443 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4444 std::make_pair(".previous.lb.", Context.getSizeType().withConst()),
4445 std::make_pair(".previous.ub.", Context.getSizeType().withConst()),
4446 std::make_pair(StringRef(), QualType()) // __context with shared vars
4447 };
4448 ActOnCapturedRegionStart(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getConstructLoc(), CurScope, CR_OpenMP,
4449 Params);
4450 break;
4451 }
4452 case OMPD_target_teams_distribute_parallel_for:
4453 case OMPD_target_teams_distribute_parallel_for_simd: {
4454 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4455 QualType KmpInt32PtrTy =
4456 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4457 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4458
4459 QualType Args[] = {VoidPtrTy};
4460 FunctionProtoType::ExtProtoInfo EPI;
4461 EPI.Variadic = true;
4462 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4463 Sema::CapturedParamNameType Params[] = {
4464 std::make_pair(".global_tid.", KmpInt32Ty),
4465 std::make_pair(".part_id.", KmpInt32PtrTy),
4466 std::make_pair(".privates.", VoidPtrTy),
4467 std::make_pair(
4468 ".copy_fn.",
4469 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4470 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4471 std::make_pair(StringRef(), QualType()) // __context with shared vars
4472 };
4473 ActOnCapturedRegionStart(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getConstructLoc(), CurScope, CR_OpenMP,
4474 Params, /*OpenMPCaptureLevel=*/0);
4475 // Mark this captured region as inlined, because we don't use outlined
4476 // function directly.
4477 getCurCapturedRegion()->TheCapturedDecl->addAttr(
4478 AlwaysInlineAttr::CreateImplicit(
4479 Context, {}, AlwaysInlineAttr::Keyword_forceinline));
4480 Sema::CapturedParamNameType ParamsTarget[] = {
4481 std::make_pair(StringRef(), QualType()) // __context with shared vars
4482 };
4483 // Start a captured region for 'target' with no implicit parameters.
4484 ActOnCapturedRegionStart(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getConstructLoc(), CurScope, CR_OpenMP,
4485 ParamsTarget, /*OpenMPCaptureLevel=*/1);
4486
4487 Sema::CapturedParamNameType ParamsTeams[] = {
4488 std::make_pair(".global_tid.", KmpInt32PtrTy),
4489 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4490 std::make_pair(StringRef(), QualType()) // __context with shared vars
4491 };
4492 // Start a captured region for 'target' with no implicit parameters.
4493 ActOnCapturedRegionStart(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getConstructLoc(), CurScope, CR_OpenMP,
4494 ParamsTeams, /*OpenMPCaptureLevel=*/2);
4495
4496 Sema::CapturedParamNameType ParamsParallel[] = {
4497 std::make_pair(".global_tid.", KmpInt32PtrTy),
4498 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4499 std::make_pair(".previous.lb.", Context.getSizeType().withConst()),
4500 std::make_pair(".previous.ub.", Context.getSizeType().withConst()),
4501 std::make_pair(StringRef(), QualType()) // __context with shared vars
4502 };
4503 // Start a captured region for 'teams' or 'parallel'. Both regions have
4504 // the same implicit parameters.
4505 ActOnCapturedRegionStart(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getConstructLoc(), CurScope, CR_OpenMP,
4506 ParamsParallel, /*OpenMPCaptureLevel=*/3);
4507 break;
4508 }
4509
4510 case OMPD_teams_loop: {
4511 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4512 QualType KmpInt32PtrTy =
4513 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4514
4515 Sema::CapturedParamNameType ParamsTeams[] = {
4516 std::make_pair(".global_tid.", KmpInt32PtrTy),
4517 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4518 std::make_pair(StringRef(), QualType()) // __context with shared vars
4519 };
4520 // Start a captured region for 'teams'.
4521 ActOnCapturedRegionStart(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getConstructLoc(), CurScope, CR_OpenMP,
4522 ParamsTeams, /*OpenMPCaptureLevel=*/0);
4523 break;
4524 }
4525
4526 case OMPD_teams_distribute_parallel_for:
4527 case OMPD_teams_distribute_parallel_for_simd: {
4528 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4529 QualType KmpInt32PtrTy =
4530 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4531
4532 Sema::CapturedParamNameType ParamsTeams[] = {
4533 std::make_pair(".global_tid.", KmpInt32PtrTy),
4534 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4535 std::make_pair(StringRef(), QualType()) // __context with shared vars
4536 };
4537 // Start a captured region for 'target' with no implicit parameters.
4538 ActOnCapturedRegionStart(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getConstructLoc(), CurScope, CR_OpenMP,
4539 ParamsTeams, /*OpenMPCaptureLevel=*/0);
4540
4541 Sema::CapturedParamNameType ParamsParallel[] = {
4542 std::make_pair(".global_tid.", KmpInt32PtrTy),
4543 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4544 std::make_pair(".previous.lb.", Context.getSizeType().withConst()),
4545 std::make_pair(".previous.ub.", Context.getSizeType().withConst()),
4546 std::make_pair(StringRef(), QualType()) // __context with shared vars
4547 };
4548 // Start a captured region for 'teams' or 'parallel'. Both regions have
4549 // the same implicit parameters.
4550 ActOnCapturedRegionStart(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getConstructLoc(), CurScope, CR_OpenMP,
4551 ParamsParallel, /*OpenMPCaptureLevel=*/1);
4552 break;
4553 }
4554 case OMPD_target_update:
4555 case OMPD_target_enter_data:
4556 case OMPD_target_exit_data: {
4557 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4558 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4559 QualType KmpInt32PtrTy =
4560 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4561 QualType Args[] = {VoidPtrTy};
4562 FunctionProtoType::ExtProtoInfo EPI;
4563 EPI.Variadic = true;
4564 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4565 Sema::CapturedParamNameType Params[] = {
4566 std::make_pair(".global_tid.", KmpInt32Ty),
4567 std::make_pair(".part_id.", KmpInt32PtrTy),
4568 std::make_pair(".privates.", VoidPtrTy),
4569 std::make_pair(
4570 ".copy_fn.",
4571 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4572 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4573 std::make_pair(StringRef(), QualType()) // __context with shared vars
4574 };
4575 ActOnCapturedRegionStart(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getConstructLoc(), CurScope, CR_OpenMP,
4576 Params);
4577 // Mark this captured region as inlined, because we don't use outlined
4578 // function directly.
4579 getCurCapturedRegion()->TheCapturedDecl->addAttr(
4580 AlwaysInlineAttr::CreateImplicit(
4581 Context, {}, AlwaysInlineAttr::Keyword_forceinline));
4582 break;
4583 }
4584 case OMPD_threadprivate:
4585 case OMPD_allocate:
4586 case OMPD_taskyield:
4587 case OMPD_error:
4588 case OMPD_barrier:
4589 case OMPD_taskwait:
4590 case OMPD_cancellation_point:
4591 case OMPD_cancel:
4592 case OMPD_flush:
4593 case OMPD_depobj:
4594 case OMPD_scan:
4595 case OMPD_declare_reduction:
4596 case OMPD_declare_mapper:
4597 case OMPD_declare_simd:
4598 case OMPD_declare_target:
4599 case OMPD_end_declare_target:
4600 case OMPD_requires:
4601 case OMPD_declare_variant:
4602 case OMPD_begin_declare_variant:
4603 case OMPD_end_declare_variant:
4604 case OMPD_metadirective:
4605 llvm_unreachable("OpenMP Directive is not allowed")::llvm::llvm_unreachable_internal("OpenMP Directive is not allowed"
, "clang/lib/Sema/SemaOpenMP.cpp", 4605)
;
4606 case OMPD_unknown:
4607 default:
4608 llvm_unreachable("Unknown OpenMP directive")::llvm::llvm_unreachable_internal("Unknown OpenMP directive",
"clang/lib/Sema/SemaOpenMP.cpp", 4608)
;
4609 }
4610 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->setContext(CurContext);
4611 handleDeclareVariantConstructTrait(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
, DKind, /* ScopeEntry */ true);
4612}
4613
4614int Sema::getNumberOfConstructScopes(unsigned Level) const {
4615 return getOpenMPCaptureLevels(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getDirective(Level));
4616}
4617
4618int Sema::getOpenMPCaptureLevels(OpenMPDirectiveKind DKind) {
4619 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
4620 getOpenMPCaptureRegions(CaptureRegions, DKind);
4621 return CaptureRegions.size();
4622}
4623
4624static OMPCapturedExprDecl *buildCaptureDecl(Sema &S, IdentifierInfo *Id,
4625 Expr *CaptureExpr, bool WithInit,
4626 DeclContext *CurContext,
4627 bool AsExpression) {
4628 assert(CaptureExpr)(static_cast <bool> (CaptureExpr) ? void (0) : __assert_fail
("CaptureExpr", "clang/lib/Sema/SemaOpenMP.cpp", 4628, __extension__
__PRETTY_FUNCTION__))
;
4629 ASTContext &C = S.getASTContext();
4630 Expr *Init = AsExpression ? CaptureExpr : CaptureExpr->IgnoreImpCasts();
4631 QualType Ty = Init->getType();
4632 if (CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue()) {
4633 if (S.getLangOpts().CPlusPlus) {
4634 Ty = C.getLValueReferenceType(Ty);
4635 } else {
4636 Ty = C.getPointerType(Ty);
4637 ExprResult Res =
4638 S.CreateBuiltinUnaryOp(CaptureExpr->getExprLoc(), UO_AddrOf, Init);
4639 if (!Res.isUsable())
4640 return nullptr;
4641 Init = Res.get();
4642 }
4643 WithInit = true;
4644 }
4645 auto *CED = OMPCapturedExprDecl::Create(C, CurContext, Id, Ty,
4646 CaptureExpr->getBeginLoc());
4647 if (!WithInit)
4648 CED->addAttr(OMPCaptureNoInitAttr::CreateImplicit(C));
4649 CurContext->addHiddenDecl(CED);
4650 Sema::TentativeAnalysisScope Trap(S);
4651 S.AddInitializerToDecl(CED, Init, /*DirectInit=*/false);
4652 return CED;
4653}
4654
4655static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
4656 bool WithInit) {
4657 OMPCapturedExprDecl *CD;
4658 if (VarDecl *VD = S.isOpenMPCapturedDecl(D))
4659 CD = cast<OMPCapturedExprDecl>(VD);
4660 else
4661 CD = buildCaptureDecl(S, D->getIdentifier(), CaptureExpr, WithInit,
4662 S.CurContext,
4663 /*AsExpression=*/false);
4664 return buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
4665 CaptureExpr->getExprLoc());
4666}
4667
4668static ExprResult buildCapture(Sema &S, Expr *CaptureExpr, DeclRefExpr *&Ref,
4669 StringRef Name) {
4670 CaptureExpr = S.DefaultLvalueConversion(CaptureExpr).get();
4671 if (!Ref) {
4672 OMPCapturedExprDecl *CD = buildCaptureDecl(
4673 S, &S.getASTContext().Idents.get(Name), CaptureExpr,
4674 /*WithInit=*/true, S.CurContext, /*AsExpression=*/true);
4675 Ref = buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
4676 CaptureExpr->getExprLoc());
4677 }
4678 ExprResult Res = Ref;
4679 if (!S.getLangOpts().CPlusPlus &&
4680 CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue() &&
4681 Ref->getType()->isPointerType()) {
4682 Res = S.CreateBuiltinUnaryOp(CaptureExpr->getExprLoc(), UO_Deref, Ref);
4683 if (!Res.isUsable())
4684 return ExprError();
4685 }
4686 return S.DefaultLvalueConversion(Res.get());
4687}
4688
4689namespace {
4690// OpenMP directives parsed in this section are represented as a
4691// CapturedStatement with an associated statement. If a syntax error
4692// is detected during the parsing of the associated statement, the
4693// compiler must abort processing and close the CapturedStatement.
4694//
4695// Combined directives such as 'target parallel' have more than one
4696// nested CapturedStatements. This RAII ensures that we unwind out
4697// of all the nested CapturedStatements when an error is found.
4698class CaptureRegionUnwinderRAII {
4699private:
4700 Sema &S;
4701 bool &ErrorFound;
4702 OpenMPDirectiveKind DKind = OMPD_unknown;
4703
4704public:
4705 CaptureRegionUnwinderRAII(Sema &S, bool &ErrorFound,
4706 OpenMPDirectiveKind DKind)
4707 : S(S), ErrorFound(ErrorFound), DKind(DKind) {}
4708 ~CaptureRegionUnwinderRAII() {
4709 if (ErrorFound) {
4710 int ThisCaptureLevel = S.getOpenMPCaptureLevels(DKind);
4711 while (--ThisCaptureLevel >= 0)
4712 S.ActOnCapturedRegionError();
4713 }
4714 }
4715};
4716} // namespace
4717
4718void Sema::tryCaptureOpenMPLambdas(ValueDecl *V) {
4719 // Capture variables captured by reference in lambdas for target-based
4720 // directives.
4721 if (!CurContext->isDependentContext() &&
4722 (isOpenMPTargetExecutionDirective(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective()) ||
4723 isOpenMPTargetDataManagementDirective(
4724 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective()))) {
4725 QualType Type = V->getType();
4726 if (const auto *RD = Type.getCanonicalType()
4727 .getNonReferenceType()
4728 ->getAsCXXRecordDecl()) {
4729 bool SavedForceCaptureByReferenceInTargetExecutable =
4730 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isForceCaptureByReferenceInTargetExecutable();
4731 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->setForceCaptureByReferenceInTargetExecutable(
4732 /*V=*/true);
4733 if (RD->isLambda()) {
4734 llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
4735 FieldDecl *ThisCapture;
4736 RD->getCaptureFields(Captures, ThisCapture);
4737 for (const LambdaCapture &LC : RD->captures()) {
4738 if (LC.getCaptureKind() == LCK_ByRef) {
4739 VarDecl *VD = cast<VarDecl>(LC.getCapturedVar());
4740 DeclContext *VDC = VD->getDeclContext();
4741 if (!VDC->Encloses(CurContext))
4742 continue;
4743 MarkVariableReferenced(LC.getLocation(), VD);
4744 } else if (LC.getCaptureKind() == LCK_This) {
4745 QualType ThisTy = getCurrentThisType();
4746 if (!ThisTy.isNull() &&
4747 Context.typesAreCompatible(ThisTy, ThisCapture->getType()))
4748 CheckCXXThisCapture(LC.getLocation());
4749 }
4750 }
4751 }
4752 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->setForceCaptureByReferenceInTargetExecutable(
4753 SavedForceCaptureByReferenceInTargetExecutable);
4754 }
4755 }
4756}
4757
4758static bool checkOrderedOrderSpecified(Sema &S,
4759 const ArrayRef<OMPClause *> Clauses) {
4760 const OMPOrderedClause *Ordered = nullptr;
4761 const OMPOrderClause *Order = nullptr;
4762
4763 for (const OMPClause *Clause : Clauses) {
4764 if (Clause->getClauseKind() == OMPC_ordered)
4765 Ordered = cast<OMPOrderedClause>(Clause);
4766 else if (Clause->getClauseKind() == OMPC_order) {
4767 Order = cast<OMPOrderClause>(Clause);
4768 if (Order->getKind() != OMPC_ORDER_concurrent)
4769 Order = nullptr;
4770 }
4771 if (Ordered && Order)
4772 break;
4773 }
4774
4775 if (Ordered && Order) {
4776 S.Diag(Order->getKindKwLoc(),
4777 diag::err_omp_simple_clause_incompatible_with_ordered)
4778 << getOpenMPClauseName(OMPC_order)
4779 << getOpenMPSimpleClauseTypeName(OMPC_order, OMPC_ORDER_concurrent)
4780 << SourceRange(Order->getBeginLoc(), Order->getEndLoc());
4781 S.Diag(Ordered->getBeginLoc(), diag::note_omp_ordered_param)
4782 << 0 << SourceRange(Ordered->getBeginLoc(), Ordered->getEndLoc());
4783 return true;
4784 }
4785 return false;
4786}
4787
4788StmtResult Sema::ActOnOpenMPRegionEnd(StmtResult S,
4789 ArrayRef<OMPClause *> Clauses) {
4790 handleDeclareVariantConstructTrait(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
, DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective(),
4791 /* ScopeEntry */ false);
4792 if (DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective() == OMPD_atomic ||
4793 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective() == OMPD_critical ||
4794 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective() == OMPD_section ||
4795 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective() == OMPD_master ||
4796 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective() == OMPD_masked)
4797 return S;
4798
4799 bool ErrorFound = false;
4800 CaptureRegionUnwinderRAII CaptureRegionUnwinder(
4801 *this, ErrorFound, DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective());
4802 if (!S.isUsable()) {
4803 ErrorFound = true;
4804 return StmtError();
4805 }
4806
4807 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
4808 getOpenMPCaptureRegions(CaptureRegions, DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective());
4809 OMPOrderedClause *OC = nullptr;
4810 OMPScheduleClause *SC = nullptr;
4811 SmallVector<const OMPLinearClause *, 4> LCs;
4812 SmallVector<const OMPClauseWithPreInit *, 4> PICs;
4813 // This is required for proper codegen.
4814 for (OMPClause *Clause : Clauses) {
4815 if (!LangOpts.OpenMPSimd &&
4816 (isOpenMPTaskingDirective(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective()) ||
4817 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective() == OMPD_target) &&
4818 Clause->getClauseKind() == OMPC_in_reduction) {
4819 // Capture taskgroup task_reduction descriptors inside the tasking regions
4820 // with the corresponding in_reduction items.
4821 auto *IRC = cast<OMPInReductionClause>(Clause);
4822 for (Expr *E : IRC->taskgroup_descriptors())
4823 if (E)
4824 MarkDeclarationsReferencedInExpr(E);
4825 }
4826 if (isOpenMPPrivate(Clause->getClauseKind()) ||
4827 Clause->getClauseKind() == OMPC_copyprivate ||
4828 (getLangOpts().OpenMPUseTLS &&
4829 getASTContext().getTargetInfo().isTLSSupported() &&
4830 Clause->getClauseKind() == OMPC_copyin)) {
4831 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->setForceVarCapturing(Clause->getClauseKind() == OMPC_copyin);
4832 // Mark all variables in private list clauses as used in inner region.
4833 for (Stmt *VarRef : Clause->children()) {
4834 if (auto *E = cast_or_null<Expr>(VarRef)) {
4835 MarkDeclarationsReferencedInExpr(E);
4836 }
4837 }
4838 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->setForceVarCapturing(/*V=*/false);
4839 } else if (isOpenMPLoopTransformationDirective(
4840 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective())) {
4841 assert(CaptureRegions.empty() &&(static_cast <bool> (CaptureRegions.empty() && "No captured regions in loop transformation directives."
) ? void (0) : __assert_fail ("CaptureRegions.empty() && \"No captured regions in loop transformation directives.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 4842, __extension__ __PRETTY_FUNCTION__
))
4842 "No captured regions in loop transformation directives.")(static_cast <bool> (CaptureRegions.empty() && "No captured regions in loop transformation directives."
) ? void (0) : __assert_fail ("CaptureRegions.empty() && \"No captured regions in loop transformation directives.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 4842, __extension__ __PRETTY_FUNCTION__
))
;
4843 } else if (CaptureRegions.size() > 1 ||
4844 CaptureRegions.back() != OMPD_unknown) {
4845 if (auto *C = OMPClauseWithPreInit::get(Clause))
4846 PICs.push_back(C);
4847 if (auto *C = OMPClauseWithPostUpdate::get(Clause)) {
4848 if (Expr *E = C->getPostUpdateExpr())
4849 MarkDeclarationsReferencedInExpr(E);
4850 }
4851 }
4852 if (Clause->getClauseKind() == OMPC_schedule)
4853 SC = cast<OMPScheduleClause>(Clause);
4854 else if (Clause->getClauseKind() == OMPC_ordered)
4855 OC = cast<OMPOrderedClause>(Clause);
4856 else if (Clause->getClauseKind() == OMPC_linear)
4857 LCs.push_back(cast<OMPLinearClause>(Clause));
4858 }
4859 // Capture allocator expressions if used.
4860 for (Expr *E : DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getInnerAllocators())
4861 MarkDeclarationsReferencedInExpr(E);
4862 // OpenMP, 2.7.1 Loop Construct, Restrictions
4863 // The nonmonotonic modifier cannot be specified if an ordered clause is
4864 // specified.
4865 if (SC &&
4866 (SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
4867 SC->getSecondScheduleModifier() ==
4868 OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
4869 OC) {
4870 Diag(SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic
4871 ? SC->getFirstScheduleModifierLoc()
4872 : SC->getSecondScheduleModifierLoc(),
4873 diag::err_omp_simple_clause_incompatible_with_ordered)
4874 << getOpenMPClauseName(OMPC_schedule)
4875 << getOpenMPSimpleClauseTypeName(OMPC_schedule,
4876 OMPC_SCHEDULE_MODIFIER_nonmonotonic)
4877 << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4878 ErrorFound = true;
4879 }
4880 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Restrictions.
4881 // If an order(concurrent) clause is present, an ordered clause may not appear
4882 // on the same directive.
4883 if (checkOrderedOrderSpecified(*this, Clauses))
4884 ErrorFound = true;
4885 if (!LCs.empty() && OC && OC->getNumForLoops()) {
4886 for (const OMPLinearClause *C : LCs) {
4887 Diag(C->getBeginLoc(), diag::err_omp_linear_ordered)
4888 << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4889 }
4890 ErrorFound = true;
4891 }
4892 if (isOpenMPWorksharingDirective(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective()) &&
4893 isOpenMPSimdDirective(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective()) && OC &&
4894 OC->getNumForLoops()) {
4895 Diag(OC->getBeginLoc(), diag::err_omp_ordered_simd)
4896 << getOpenMPDirectiveName(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective());
4897 ErrorFound = true;
4898 }
4899 if (ErrorFound) {
4900 return StmtError();
4901 }
4902 StmtResult SR = S;
4903 unsigned CompletedRegions = 0;
4904 for (OpenMPDirectiveKind ThisCaptureRegion : llvm::reverse(CaptureRegions)) {
4905 // Mark all variables in private list clauses as used in inner region.
4906 // Required for proper codegen of combined directives.
4907 // TODO: add processing for other clauses.
4908 if (ThisCaptureRegion != OMPD_unknown) {
4909 for (const clang::OMPClauseWithPreInit *C : PICs) {
4910 OpenMPDirectiveKind CaptureRegion = C->getCaptureRegion();
4911 // Find the particular capture region for the clause if the
4912 // directive is a combined one with multiple capture regions.
4913 // If the directive is not a combined one, the capture region
4914 // associated with the clause is OMPD_unknown and is generated
4915 // only once.
4916 if (CaptureRegion == ThisCaptureRegion ||
4917 CaptureRegion == OMPD_unknown) {
4918 if (auto *DS = cast_or_null<DeclStmt>(C->getPreInitStmt())) {
4919 for (Decl *D : DS->decls())
4920 MarkVariableReferenced(D->getLocation(), cast<VarDecl>(D));
4921 }
4922 }
4923 }
4924 }
4925 if (ThisCaptureRegion == OMPD_target) {
4926 // Capture allocator traits in the target region. They are used implicitly
4927 // and, thus, are not captured by default.
4928 for (OMPClause *C : Clauses) {
4929 if (const auto *UAC = dyn_cast<OMPUsesAllocatorsClause>(C)) {
4930 for (unsigned I = 0, End = UAC->getNumberOfAllocators(); I < End;
4931 ++I) {
4932 OMPUsesAllocatorsClause::Data D = UAC->getAllocatorData(I);
4933 if (Expr *E = D.AllocatorTraits)
4934 MarkDeclarationsReferencedInExpr(E);
4935 }
4936 continue;
4937 }
4938 }
4939 }
4940 if (ThisCaptureRegion == OMPD_parallel) {
4941 // Capture temp arrays for inscan reductions and locals in aligned
4942 // clauses.
4943 for (OMPClause *C : Clauses) {
4944 if (auto *RC = dyn_cast<OMPReductionClause>(C)) {
4945 if (RC->getModifier() != OMPC_REDUCTION_inscan)
4946 continue;
4947 for (Expr *E : RC->copy_array_temps())
4948 MarkDeclarationsReferencedInExpr(E);
4949 }
4950 if (auto *AC = dyn_cast<OMPAlignedClause>(C)) {
4951 for (Expr *E : AC->varlists())
4952 MarkDeclarationsReferencedInExpr(E);
4953 }
4954 }
4955 }
4956 if (++CompletedRegions == CaptureRegions.size())
4957 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->setBodyComplete();
4958 SR = ActOnCapturedRegionEnd(SR.get());
4959 }
4960 return SR;
4961}
4962
4963static bool checkCancelRegion(Sema &SemaRef, OpenMPDirectiveKind CurrentRegion,
4964 OpenMPDirectiveKind CancelRegion,
4965 SourceLocation StartLoc) {
4966 // CancelRegion is only needed for cancel and cancellation_point.
4967 if (CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_cancellation_point)
4968 return false;
4969
4970 if (CancelRegion == OMPD_parallel || CancelRegion == OMPD_for ||
4971 CancelRegion == OMPD_sections || CancelRegion == OMPD_taskgroup)
4972 return false;
4973
4974 SemaRef.Diag(StartLoc, diag::err_omp_wrong_cancel_region)
4975 << getOpenMPDirectiveName(CancelRegion);
4976 return true;
4977}
4978
4979static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack,
4980 OpenMPDirectiveKind CurrentRegion,
4981 const DeclarationNameInfo &CurrentName,
4982 OpenMPDirectiveKind CancelRegion,
4983 OpenMPBindClauseKind BindKind,
4984 SourceLocation StartLoc) {
4985 if (Stack->getCurScope()) {
4986 OpenMPDirectiveKind ParentRegion = Stack->getParentDirective();
4987 OpenMPDirectiveKind OffendingRegion = ParentRegion;
4988 bool NestingProhibited = false;
4989 bool CloseNesting = true;
4990 bool OrphanSeen = false;
4991 enum {
4992 NoRecommend,
4993 ShouldBeInParallelRegion,
4994 ShouldBeInOrderedRegion,
4995 ShouldBeInTargetRegion,
4996 ShouldBeInTeamsRegion,
4997 ShouldBeInLoopSimdRegion,
4998 } Recommend = NoRecommend;
4999 if (SemaRef.LangOpts.OpenMP >= 51 && Stack->isParentOrderConcurrent() &&
5000 CurrentRegion != OMPD_simd && CurrentRegion != OMPD_loop &&
5001 CurrentRegion != OMPD_parallel &&
5002 !isOpenMPCombinedParallelADirective(CurrentRegion)) {
5003 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_order)
5004 << getOpenMPDirectiveName(CurrentRegion);
5005 return true;
5006 }
5007 if (isOpenMPSimdDirective(ParentRegion) &&
5008 ((SemaRef.LangOpts.OpenMP <= 45 && CurrentRegion != OMPD_ordered) ||
5009 (SemaRef.LangOpts.OpenMP >= 50 && CurrentRegion != OMPD_ordered &&
5010 CurrentRegion != OMPD_simd && CurrentRegion != OMPD_atomic &&
5011 CurrentRegion != OMPD_scan))) {
5012 // OpenMP [2.16, Nesting of Regions]
5013 // OpenMP constructs may not be nested inside a simd region.
5014 // OpenMP [2.8.1,simd Construct, Restrictions]
5015 // An ordered construct with the simd clause is the only OpenMP
5016 // construct that can appear in the simd region.
5017 // Allowing a SIMD construct nested in another SIMD construct is an
5018 // extension. The OpenMP 4.5 spec does not allow it. Issue a warning
5019 // message.
5020 // OpenMP 5.0 [2.9.3.1, simd Construct, Restrictions]
5021 // The only OpenMP constructs that can be encountered during execution of
5022 // a simd region are the atomic construct, the loop construct, the simd
5023 // construct and the ordered construct with the simd clause.
5024 SemaRef.Diag(StartLoc, (CurrentRegion != OMPD_simd)
5025 ? diag::err_omp_prohibited_region_simd
5026 : diag::warn_omp_nesting_simd)
5027 << (SemaRef.LangOpts.OpenMP >= 50 ? 1 : 0);
5028 return CurrentRegion != OMPD_simd;
5029 }
5030 if (ParentRegion == OMPD_atomic) {
5031 // OpenMP [2.16, Nesting of Regions]
5032 // OpenMP constructs may not be nested inside an atomic region.
5033 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_atomic);
5034 return true;
5035 }
5036 if (CurrentRegion == OMPD_section) {
5037 // OpenMP [2.7.2, sections Construct, Restrictions]
5038 // Orphaned section directives are prohibited. That is, the section
5039 // directives must appear within the sections construct and must not be
5040 // encountered elsewhere in the sections region.
5041 if (ParentRegion != OMPD_sections &&
5042 ParentRegion != OMPD_parallel_sections) {
5043 SemaRef.Diag(StartLoc, diag::err_omp_orphaned_section_directive)
5044 << (ParentRegion != OMPD_unknown)
5045 << getOpenMPDirectiveName(ParentRegion);
5046 return true;
5047 }
5048 return false;
5049 }
5050 // Allow some constructs (except teams and cancellation constructs) to be
5051 // orphaned (they could be used in functions, called from OpenMP regions
5052 // with the required preconditions).
5053 if (ParentRegion == OMPD_unknown &&
5054 !isOpenMPNestingTeamsDirective(CurrentRegion) &&
5055 CurrentRegion != OMPD_cancellation_point &&
5056 CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_scan)
5057 return false;
5058 if (CurrentRegion == OMPD_cancellation_point ||
5059 CurrentRegion == OMPD_cancel) {
5060 // OpenMP [2.16, Nesting of Regions]
5061 // A cancellation point construct for which construct-type-clause is
5062 // taskgroup must be nested inside a task construct. A cancellation
5063 // point construct for which construct-type-clause is not taskgroup must
5064 // be closely nested inside an OpenMP construct that matches the type
5065 // specified in construct-type-clause.
5066 // A cancel construct for which construct-type-clause is taskgroup must be
5067 // nested inside a task construct. A cancel construct for which
5068 // construct-type-clause is not taskgroup must be closely nested inside an
5069 // OpenMP construct that matches the type specified in
5070 // construct-type-clause.
5071 NestingProhibited =
5072 !((CancelRegion == OMPD_parallel &&
5073 (ParentRegion == OMPD_parallel ||
5074 ParentRegion == OMPD_target_parallel)) ||
5075 (CancelRegion == OMPD_for &&
5076 (ParentRegion == OMPD_for || ParentRegion == OMPD_parallel_for ||
5077 ParentRegion == OMPD_target_parallel_for ||
5078 ParentRegion == OMPD_distribute_parallel_for ||
5079 ParentRegion == OMPD_teams_distribute_parallel_for ||
5080 ParentRegion == OMPD_target_teams_distribute_parallel_for)) ||
5081 (CancelRegion == OMPD_taskgroup &&
5082 (ParentRegion == OMPD_task ||
5083 (SemaRef.getLangOpts().OpenMP >= 50 &&
5084 (ParentRegion == OMPD_taskloop ||
5085 ParentRegion == OMPD_master_taskloop ||
5086 ParentRegion == OMPD_masked_taskloop ||
5087 ParentRegion == OMPD_parallel_masked_taskloop ||
5088 ParentRegion == OMPD_parallel_master_taskloop)))) ||
5089 (CancelRegion == OMPD_sections &&
5090 (ParentRegion == OMPD_section || ParentRegion == OMPD_sections ||
5091 ParentRegion == OMPD_parallel_sections)));
5092 OrphanSeen = ParentRegion == OMPD_unknown;
5093 } else if (CurrentRegion == OMPD_master || CurrentRegion == OMPD_masked) {
5094 // OpenMP 5.1 [2.22, Nesting of Regions]
5095 // A masked region may not be closely nested inside a worksharing, loop,
5096 // atomic, task, or taskloop region.
5097 NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
5098 isOpenMPGenericLoopDirective(ParentRegion) ||
5099 isOpenMPTaskingDirective(ParentRegion);
5100 } else if (CurrentRegion == OMPD_critical && CurrentName.getName()) {
5101 // OpenMP [2.16, Nesting of Regions]
5102 // A critical region may not be nested (closely or otherwise) inside a
5103 // critical region with the same name. Note that this restriction is not
5104 // sufficient to prevent deadlock.
5105 SourceLocation PreviousCriticalLoc;
5106 bool DeadLock = Stack->hasDirective(
5107 [CurrentName, &PreviousCriticalLoc](OpenMPDirectiveKind K,
5108 const DeclarationNameInfo &DNI,
5109 SourceLocation Loc) {
5110 if (K == OMPD_critical && DNI.getName() == CurrentName.getName()) {
5111 PreviousCriticalLoc = Loc;
5112 return true;
5113 }
5114 return false;
5115 },
5116 false /* skip top directive */);
5117 if (DeadLock) {
5118 SemaRef.Diag(StartLoc,
5119 diag::err_omp_prohibited_region_critical_same_name)
5120 << CurrentName.getName();
5121 if (PreviousCriticalLoc.isValid())
5122 SemaRef.Diag(PreviousCriticalLoc,
5123 diag::note_omp_previous_critical_region);
5124 return true;
5125 }
5126 } else if (CurrentRegion == OMPD_barrier) {
5127 // OpenMP 5.1 [2.22, Nesting of Regions]
5128 // A barrier region may not be closely nested inside a worksharing, loop,
5129 // task, taskloop, critical, ordered, atomic, or masked region.
5130 NestingProhibited =
5131 isOpenMPWorksharingDirective(ParentRegion) ||
5132 isOpenMPGenericLoopDirective(ParentRegion) ||
5133 isOpenMPTaskingDirective(ParentRegion) ||
5134 ParentRegion == OMPD_master || ParentRegion == OMPD_masked ||
5135 ParentRegion == OMPD_parallel_master ||
5136 ParentRegion == OMPD_parallel_masked ||
5137 ParentRegion == OMPD_critical || ParentRegion == OMPD_ordered;
5138 } else if (isOpenMPWorksharingDirective(CurrentRegion) &&
5139 !isOpenMPParallelDirective(CurrentRegion) &&
5140 !isOpenMPTeamsDirective(CurrentRegion)) {
5141 // OpenMP 5.1 [2.22, Nesting of Regions]
5142 // A loop region that binds to a parallel region or a worksharing region
5143 // may not be closely nested inside a worksharing, loop, task, taskloop,
5144 // critical, ordered, atomic, or masked region.
5145 NestingProhibited =
5146 isOpenMPWorksharingDirective(ParentRegion) ||
5147 isOpenMPGenericLoopDirective(ParentRegion) ||
5148 isOpenMPTaskingDirective(ParentRegion) ||
5149 ParentRegion == OMPD_master || ParentRegion == OMPD_masked ||
5150 ParentRegion == OMPD_parallel_master ||
5151 ParentRegion == OMPD_parallel_masked ||
5152 ParentRegion == OMPD_critical || ParentRegion == OMPD_ordered;
5153 Recommend = ShouldBeInParallelRegion;
5154 } else if (CurrentRegion == OMPD_ordered) {
5155 // OpenMP [2.16, Nesting of Regions]
5156 // An ordered region may not be closely nested inside a critical,
5157 // atomic, or explicit task region.
5158 // An ordered region must be closely nested inside a loop region (or
5159 // parallel loop region) with an ordered clause.
5160 // OpenMP [2.8.1,simd Construct, Restrictions]
5161 // An ordered construct with the simd clause is the only OpenMP construct
5162 // that can appear in the simd region.
5163 NestingProhibited = ParentRegion == OMPD_critical ||
5164 isOpenMPTaskingDirective(ParentRegion) ||
5165 !(isOpenMPSimdDirective(ParentRegion) ||
5166 Stack->isParentOrderedRegion());
5167 Recommend = ShouldBeInOrderedRegion;
5168 } else if (isOpenMPNestingTeamsDirective(CurrentRegion)) {
5169 // OpenMP [2.16, Nesting of Regions]
5170 // If specified, a teams construct must be contained within a target
5171 // construct.
5172 NestingProhibited =
5173 (SemaRef.LangOpts.OpenMP <= 45 && ParentRegion != OMPD_target) ||
5174 (SemaRef.LangOpts.OpenMP >= 50 && ParentRegion != OMPD_unknown &&
5175 ParentRegion != OMPD_target);
5176 OrphanSeen = ParentRegion == OMPD_unknown;
5177 Recommend = ShouldBeInTargetRegion;
5178 } else if (CurrentRegion == OMPD_scan) {
5179 // OpenMP [2.16, Nesting of Regions]
5180 // If specified, a teams construct must be contained within a target
5181 // construct.
5182 NestingProhibited =
5183 SemaRef.LangOpts.OpenMP < 50 ||
5184 (ParentRegion != OMPD_simd && ParentRegion != OMPD_for &&
5185 ParentRegion != OMPD_for_simd && ParentRegion != OMPD_parallel_for &&
5186 ParentRegion != OMPD_parallel_for_simd);
5187 OrphanSeen = ParentRegion == OMPD_unknown;
5188 Recommend = ShouldBeInLoopSimdRegion;
5189 }
5190 if (!NestingProhibited &&
5191 !isOpenMPTargetExecutionDirective(CurrentRegion) &&
5192 !isOpenMPTargetDataManagementDirective(CurrentRegion) &&
5193 (ParentRegion == OMPD_teams || ParentRegion == OMPD_target_teams)) {
5194 // OpenMP [5.1, 2.22, Nesting of Regions]
5195 // distribute, distribute simd, distribute parallel worksharing-loop,
5196 // distribute parallel worksharing-loop SIMD, loop, parallel regions,
5197 // including any parallel regions arising from combined constructs,
5198 // omp_get_num_teams() regions, and omp_get_team_num() regions are the
5199 // only OpenMP regions that may be strictly nested inside the teams
5200 // region.
5201 //
5202 // As an extension, we permit atomic within teams as well.
5203 NestingProhibited = !isOpenMPParallelDirective(CurrentRegion) &&
5204 !isOpenMPDistributeDirective(CurrentRegion) &&
5205 CurrentRegion != OMPD_loop &&
5206 !(SemaRef.getLangOpts().OpenMPExtensions &&
5207 CurrentRegion == OMPD_atomic);
5208 Recommend = ShouldBeInParallelRegion;
5209 }
5210 if (!NestingProhibited && CurrentRegion == OMPD_loop) {
5211 // OpenMP [5.1, 2.11.7, loop Construct, Restrictions]
5212 // If the bind clause is present on the loop construct and binding is
5213 // teams then the corresponding loop region must be strictly nested inside
5214 // a teams region.
5215 NestingProhibited = BindKind == OMPC_BIND_teams &&
5216 ParentRegion != OMPD_teams &&
5217 ParentRegion != OMPD_target_teams;
5218 Recommend = ShouldBeInTeamsRegion;
5219 }
5220 if (!NestingProhibited &&
5221 isOpenMPNestingDistributeDirective(CurrentRegion)) {
5222 // OpenMP 4.5 [2.17 Nesting of Regions]
5223 // The region associated with the distribute construct must be strictly
5224 // nested inside a teams region
5225 NestingProhibited =
5226 (ParentRegion != OMPD_teams && ParentRegion != OMPD_target_teams);
5227 Recommend = ShouldBeInTeamsRegion;
5228 }
5229 if (!NestingProhibited &&
5230 (isOpenMPTargetExecutionDirective(CurrentRegion) ||
5231 isOpenMPTargetDataManagementDirective(CurrentRegion))) {
5232 // OpenMP 4.5 [2.17 Nesting of Regions]
5233 // If a target, target update, target data, target enter data, or
5234 // target exit data construct is encountered during execution of a
5235 // target region, the behavior is unspecified.
5236 NestingProhibited = Stack->hasDirective(
5237 [&OffendingRegion](OpenMPDirectiveKind K, const DeclarationNameInfo &,
5238 SourceLocation) {
5239 if (isOpenMPTargetExecutionDirective(K)) {
5240 OffendingRegion = K;
5241 return true;
5242 }
5243 return false;
5244 },
5245 false /* don't skip top directive */);
5246 CloseNesting = false;
5247 }
5248 if (NestingProhibited) {
5249 if (OrphanSeen) {
5250 SemaRef.Diag(StartLoc, diag::err_omp_orphaned_device_directive)
5251 << getOpenMPDirectiveName(CurrentRegion) << Recommend;
5252 } else {
5253 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region)
5254 << CloseNesting << getOpenMPDirectiveName(OffendingRegion)
5255 << Recommend << getOpenMPDirectiveName(CurrentRegion);
5256 }
5257 return true;
5258 }
5259 }
5260 return false;
5261}
5262
5263struct Kind2Unsigned {
5264 using argument_type = OpenMPDirectiveKind;
5265 unsigned operator()(argument_type DK) { return unsigned(DK); }
5266};
5267static bool checkIfClauses(Sema &S, OpenMPDirectiveKind Kind,
5268 ArrayRef<OMPClause *> Clauses,
5269 ArrayRef<OpenMPDirectiveKind> AllowedNameModifiers) {
5270 bool ErrorFound = false;
5271 unsigned NamedModifiersNumber = 0;
5272 llvm::IndexedMap<const OMPIfClause *, Kind2Unsigned> FoundNameModifiers;
5273 FoundNameModifiers.resize(llvm::omp::Directive_enumSize + 1);
5274 SmallVector<SourceLocation, 4> NameModifierLoc;
5275 for (const OMPClause *C : Clauses) {
5276 if (const auto *IC = dyn_cast_or_null<OMPIfClause>(C)) {
5277 // At most one if clause without a directive-name-modifier can appear on
5278 // the directive.
5279 OpenMPDirectiveKind CurNM = IC->getNameModifier();
5280 if (FoundNameModifiers[CurNM]) {
5281 S.Diag(C->getBeginLoc(), diag::err_omp_more_one_clause)
5282 << getOpenMPDirectiveName(Kind) << getOpenMPClauseName(OMPC_if)
5283 << (CurNM != OMPD_unknown) << getOpenMPDirectiveName(CurNM);
5284 ErrorFound = true;
5285 } else if (CurNM != OMPD_unknown) {
5286 NameModifierLoc.push_back(IC->getNameModifierLoc());
5287 ++NamedModifiersNumber;
5288 }
5289 FoundNameModifiers[CurNM] = IC;
5290 if (CurNM == OMPD_unknown)
5291 continue;
5292 // Check if the specified name modifier is allowed for the current
5293 // directive.
5294 // At most one if clause with the particular directive-name-modifier can
5295 // appear on the directive.
5296 if (!llvm::is_contained(AllowedNameModifiers, CurNM)) {
5297 S.Diag(IC->getNameModifierLoc(),
5298 diag::err_omp_wrong_if_directive_name_modifier)
5299 << getOpenMPDirectiveName(CurNM) << getOpenMPDirectiveName(Kind);
5300 ErrorFound = true;
5301 }
5302 }
5303 }
5304 // If any if clause on the directive includes a directive-name-modifier then
5305 // all if clauses on the directive must include a directive-name-modifier.
5306 if (FoundNameModifiers[OMPD_unknown] && NamedModifiersNumber > 0) {
5307 if (NamedModifiersNumber == AllowedNameModifiers.size()) {
5308 S.Diag(FoundNameModifiers[OMPD_unknown]->getBeginLoc(),
5309 diag::err_omp_no_more_if_clause);
5310 } else {
5311 std::string Values;
5312 std::string Sep(", ");
5313 unsigned AllowedCnt = 0;
5314 unsigned TotalAllowedNum =
5315 AllowedNameModifiers.size() - NamedModifiersNumber;
5316 for (unsigned Cnt = 0, End = AllowedNameModifiers.size(); Cnt < End;
5317 ++Cnt) {
5318 OpenMPDirectiveKind NM = AllowedNameModifiers[Cnt];
5319 if (!FoundNameModifiers[NM]) {
5320 Values += "'";
5321 Values += getOpenMPDirectiveName(NM);
5322 Values += "'";
5323 if (AllowedCnt + 2 == TotalAllowedNum)
5324 Values += " or ";
5325 else if (AllowedCnt + 1 != TotalAllowedNum)
5326 Values += Sep;
5327 ++AllowedCnt;
5328 }
5329 }
5330 S.Diag(FoundNameModifiers[OMPD_unknown]->getCondition()->getBeginLoc(),
5331 diag::err_omp_unnamed_if_clause)
5332 << (TotalAllowedNum > 1) << Values;
5333 }
5334 for (SourceLocation Loc : NameModifierLoc) {
5335 S.Diag(Loc, diag::note_omp_previous_named_if_clause);
5336 }
5337 ErrorFound = true;
5338 }
5339 return ErrorFound;
5340}
5341
5342static std::pair<ValueDecl *, bool> getPrivateItem(Sema &S, Expr *&RefExpr,
5343 SourceLocation &ELoc,
5344 SourceRange &ERange,
5345 bool AllowArraySection,
5346 StringRef DiagType) {
5347 if (RefExpr->isTypeDependent() || RefExpr->isValueDependent() ||
5348 RefExpr->containsUnexpandedParameterPack())
5349 return std::make_pair(nullptr, true);
5350
5351 // OpenMP [3.1, C/C++]
5352 // A list item is a variable name.
5353 // OpenMP [2.9.3.3, Restrictions, p.1]
5354 // A variable that is part of another variable (as an array or
5355 // structure element) cannot appear in a private clause.
5356 RefExpr = RefExpr->IgnoreParens();
5357 enum {
5358 NoArrayExpr = -1,
5359 ArraySubscript = 0,
5360 OMPArraySection = 1
5361 } IsArrayExpr = NoArrayExpr;
5362 if (AllowArraySection) {
5363 if (auto *ASE = dyn_cast_or_null<ArraySubscriptExpr>(RefExpr)) {
5364 Expr *Base = ASE->getBase()->IgnoreParenImpCasts();
5365 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
5366 Base = TempASE->getBase()->IgnoreParenImpCasts();
5367 RefExpr = Base;
5368 IsArrayExpr = ArraySubscript;
5369 } else if (auto *OASE = dyn_cast_or_null<OMPArraySectionExpr>(RefExpr)) {
5370 Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
5371 while (auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base))
5372 Base = TempOASE->getBase()->IgnoreParenImpCasts();
5373 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
5374 Base = TempASE->getBase()->IgnoreParenImpCasts();
5375 RefExpr = Base;
5376 IsArrayExpr = OMPArraySection;
5377 }
5378 }
5379 ELoc = RefExpr->getExprLoc();
5380 ERange = RefExpr->getSourceRange();
5381 RefExpr = RefExpr->IgnoreParenImpCasts();
5382 auto *DE = dyn_cast_or_null<DeclRefExpr>(RefExpr);
5383 auto *ME = dyn_cast_or_null<MemberExpr>(RefExpr);
5384 if ((!DE || !isa<VarDecl>(DE->getDecl())) &&
5385 (S.getCurrentThisType().isNull() || !ME ||
5386 !isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()) ||
5387 !isa<FieldDecl>(ME->getMemberDecl()))) {
5388 if (IsArrayExpr != NoArrayExpr) {
5389 S.Diag(ELoc, diag::err_omp_expected_base_var_name)
5390 << IsArrayExpr << ERange;
5391 } else if (!DiagType.empty()) {
5392 unsigned DiagSelect = S.getLangOpts().CPlusPlus
5393 ? (S.getCurrentThisType().isNull() ? 1 : 2)
5394 : 0;
5395 S.Diag(ELoc, diag::err_omp_expected_var_name_member_expr_with_type)
5396 << DiagSelect << DiagType << ERange;
5397 } else {
5398 S.Diag(ELoc,
5399 AllowArraySection
5400 ? diag::err_omp_expected_var_name_member_expr_or_array_item
5401 : diag::err_omp_expected_var_name_member_expr)
5402 << (S.getCurrentThisType().isNull() ? 0 : 1) << ERange;
5403 }
5404 return std::make_pair(nullptr, false);
5405 }
5406 return std::make_pair(
5407 getCanonicalDecl(DE ? DE->getDecl() : ME->getMemberDecl()), false);
5408}
5409
5410namespace {
5411/// Checks if the allocator is used in uses_allocators clause to be allowed in
5412/// target regions.
5413class AllocatorChecker final : public ConstStmtVisitor<AllocatorChecker, bool> {
5414 DSAStackTy *S = nullptr;
5415
5416public:
5417 bool VisitDeclRefExpr(const DeclRefExpr *E) {
5418 return S->isUsesAllocatorsDecl(E->getDecl())
5419 .value_or(DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
5420 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait;
5421 }
5422 bool VisitStmt(const Stmt *S) {
5423 for (const Stmt *Child : S->children()) {
5424 if (Child && Visit(Child))
5425 return true;
5426 }
5427 return false;
5428 }
5429 explicit AllocatorChecker(DSAStackTy *S) : S(S) {}
5430};
5431} // namespace
5432
5433static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
5434 ArrayRef<OMPClause *> Clauses) {
5435 assert(!S.CurContext->isDependentContext() &&(static_cast <bool> (!S.CurContext->isDependentContext
() && "Expected non-dependent context.") ? void (0) :
__assert_fail ("!S.CurContext->isDependentContext() && \"Expected non-dependent context.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 5436, __extension__ __PRETTY_FUNCTION__
))
5436 "Expected non-dependent context.")(static_cast <bool> (!S.CurContext->isDependentContext
() && "Expected non-dependent context.") ? void (0) :
__assert_fail ("!S.CurContext->isDependentContext() && \"Expected non-dependent context.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 5436, __extension__ __PRETTY_FUNCTION__
))
;
5437 auto AllocateRange =
5438 llvm::make_filter_range(Clauses, OMPAllocateClause::classof);
5439 llvm::DenseMap<CanonicalDeclPtr<Decl>, CanonicalDeclPtr<VarDecl>> DeclToCopy;
5440 auto PrivateRange = llvm::make_filter_range(Clauses, [](const OMPClause *C) {
5441 return isOpenMPPrivate(C->getClauseKind());
5442 });
5443 for (OMPClause *Cl : PrivateRange) {
5444 MutableArrayRef<Expr *>::iterator I, It, Et;
5445 if (Cl->getClauseKind() == OMPC_private) {
5446 auto *PC = cast<OMPPrivateClause>(Cl);
5447 I = PC->private_copies().begin();
5448 It = PC->varlist_begin();
5449 Et = PC->varlist_end();
5450 } else if (Cl->getClauseKind() == OMPC_firstprivate) {
5451 auto *PC = cast<OMPFirstprivateClause>(Cl);
5452 I = PC->private_copies().begin();
5453 It = PC->varlist_begin();
5454 Et = PC->varlist_end();
5455 } else if (Cl->getClauseKind() == OMPC_lastprivate) {
5456 auto *PC = cast<OMPLastprivateClause>(Cl);
5457 I = PC->private_copies().begin();
5458 It = PC->varlist_begin();
5459 Et = PC->varlist_end();
5460 } else if (Cl->getClauseKind() == OMPC_linear) {
5461 auto *PC = cast<OMPLinearClause>(Cl);
5462 I = PC->privates().begin();
5463 It = PC->varlist_begin();
5464 Et = PC->varlist_end();
5465 } else if (Cl->getClauseKind() == OMPC_reduction) {
5466 auto *PC = cast<OMPReductionClause>(Cl);
5467 I = PC->privates().begin();
5468 It = PC->varlist_begin();
5469 Et = PC->varlist_end();
5470 } else if (Cl->getClauseKind() == OMPC_task_reduction) {
5471 auto *PC = cast<OMPTaskReductionClause>(Cl);
5472 I = PC->privates().begin();
5473 It = PC->varlist_begin();
5474 Et = PC->varlist_end();
5475 } else if (Cl->getClauseKind() == OMPC_in_reduction) {
5476 auto *PC = cast<OMPInReductionClause>(Cl);
5477 I = PC->privates().begin();
5478 It = PC->varlist_begin();
5479 Et = PC->varlist_end();
5480 } else {
5481 llvm_unreachable("Expected private clause.")::llvm::llvm_unreachable_internal("Expected private clause.",
"clang/lib/Sema/SemaOpenMP.cpp", 5481)
;
5482 }
5483 for (Expr *E : llvm::make_range(It, Et)) {
5484 if (!*I) {
5485 ++I;
5486 continue;
5487 }
5488 SourceLocation ELoc;
5489 SourceRange ERange;
5490 Expr *SimpleRefExpr = E;
5491 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
5492 /*AllowArraySection=*/true);
5493 DeclToCopy.try_emplace(Res.first,
5494 cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()));
5495 ++I;
5496 }
5497 }
5498 for (OMPClause *C : AllocateRange) {
5499 auto *AC = cast<OMPAllocateClause>(C);
5500 if (S.getLangOpts().OpenMP >= 50 &&
5501 !Stack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>() &&
5502 isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) &&
5503 AC->getAllocator()) {
5504 Expr *Allocator = AC->getAllocator();
5505 // OpenMP, 2.12.5 target Construct
5506 // Memory allocators that do not appear in a uses_allocators clause cannot
5507 // appear as an allocator in an allocate clause or be used in the target
5508 // region unless a requires directive with the dynamic_allocators clause
5509 // is present in the same compilation unit.
5510 AllocatorChecker Checker(Stack);
5511 if (Checker.Visit(Allocator))
5512 S.Diag(Allocator->getExprLoc(),
5513 diag::err_omp_allocator_not_in_uses_allocators)
5514 << Allocator->getSourceRange();
5515 }
5516 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
5517 getAllocatorKind(S, Stack, AC->getAllocator());
5518 // OpenMP, 2.11.4 allocate Clause, Restrictions.
5519 // For task, taskloop or target directives, allocation requests to memory
5520 // allocators with the trait access set to thread result in unspecified
5521 // behavior.
5522 if (AllocatorKind == OMPAllocateDeclAttr::OMPThreadMemAlloc &&
5523 (isOpenMPTaskingDirective(Stack->getCurrentDirective()) ||
5524 isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()))) {
5525 S.Diag(AC->getAllocator()->getExprLoc(),
5526 diag::warn_omp_allocate_thread_on_task_target_directive)
5527 << getOpenMPDirectiveName(Stack->getCurrentDirective());
5528 }
5529 for (Expr *E : AC->varlists()) {
5530 SourceLocation ELoc;
5531 SourceRange ERange;
5532 Expr *SimpleRefExpr = E;
5533 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange);
5534 ValueDecl *VD = Res.first;
5535 DSAStackTy::DSAVarData Data = Stack->getTopDSA(VD, /*FromParent=*/false);
5536 if (!isOpenMPPrivate(Data.CKind)) {
5537 S.Diag(E->getExprLoc(),
5538 diag::err_omp_expected_private_copy_for_allocate);
5539 continue;
5540 }
5541 VarDecl *PrivateVD = DeclToCopy[VD];
5542 if (checkPreviousOMPAllocateAttribute(S, Stack, E, PrivateVD,
5543 AllocatorKind, AC->getAllocator()))
5544 continue;
5545 // Placeholder until allocate clause supports align modifier.
5546 Expr *Alignment = nullptr;
5547 applyOMPAllocateAttribute(S, PrivateVD, AllocatorKind, AC->getAllocator(),
5548 Alignment, E->getSourceRange());
5549 }
5550 }
5551}
5552
5553namespace {
5554/// Rewrite statements and expressions for Sema \p Actions CurContext.
5555///
5556/// Used to wrap already parsed statements/expressions into a new CapturedStmt
5557/// context. DeclRefExpr used inside the new context are changed to refer to the
5558/// captured variable instead.
5559class CaptureVars : public TreeTransform<CaptureVars> {
5560 using BaseTransform = TreeTransform<CaptureVars>;
5561
5562public:
5563 CaptureVars(Sema &Actions) : BaseTransform(Actions) {}
5564
5565 bool AlwaysRebuild() { return true; }
5566};
5567} // namespace
5568
5569static VarDecl *precomputeExpr(Sema &Actions,
5570 SmallVectorImpl<Stmt *> &BodyStmts, Expr *E,
5571 StringRef Name) {
5572 Expr *NewE = AssertSuccess(CaptureVars(Actions).TransformExpr(E));
5573 VarDecl *NewVar = buildVarDecl(Actions, {}, NewE->getType(), Name, nullptr,
5574 dyn_cast<DeclRefExpr>(E->IgnoreImplicit()));
5575 auto *NewDeclStmt = cast<DeclStmt>(AssertSuccess(
5576 Actions.ActOnDeclStmt(Actions.ConvertDeclToDeclGroup(NewVar), {}, {})));
5577 Actions.AddInitializerToDecl(NewDeclStmt->getSingleDecl(), NewE, false);
5578 BodyStmts.push_back(NewDeclStmt);
5579 return NewVar;
5580}
5581
5582/// Create a closure that computes the number of iterations of a loop.
5583///
5584/// \param Actions The Sema object.
5585/// \param LogicalTy Type for the logical iteration number.
5586/// \param Rel Comparison operator of the loop condition.
5587/// \param StartExpr Value of the loop counter at the first iteration.
5588/// \param StopExpr Expression the loop counter is compared against in the loop
5589/// condition. \param StepExpr Amount of increment after each iteration.
5590///
5591/// \return Closure (CapturedStmt) of the distance calculation.
5592static CapturedStmt *buildDistanceFunc(Sema &Actions, QualType LogicalTy,
5593 BinaryOperator::Opcode Rel,
5594 Expr *StartExpr, Expr *StopExpr,
5595 Expr *StepExpr) {
5596 ASTContext &Ctx = Actions.getASTContext();
5597 TypeSourceInfo *LogicalTSI = Ctx.getTrivialTypeSourceInfo(LogicalTy);
5598
5599 // Captured regions currently don't support return values, we use an
5600 // out-parameter instead. All inputs are implicit captures.
5601 // TODO: Instead of capturing each DeclRefExpr occurring in
5602 // StartExpr/StopExpr/Step, these could also be passed as a value capture.
5603 QualType ResultTy = Ctx.getLValueReferenceType(LogicalTy);
5604 Sema::CapturedParamNameType Params[] = {{"Distance", ResultTy},
5605 {StringRef(), QualType()}};
5606 Actions.ActOnCapturedRegionStart({}, nullptr, CR_Default, Params);
5607
5608 Stmt *Body;
5609 {
5610 Sema::CompoundScopeRAII CompoundScope(Actions);
5611 CapturedDecl *CS = cast<CapturedDecl>(Actions.CurContext);
5612
5613 // Get the LValue expression for the result.
5614 ImplicitParamDecl *DistParam = CS->getParam(0);
5615 DeclRefExpr *DistRef = Actions.BuildDeclRefExpr(
5616 DistParam, LogicalTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5617
5618 SmallVector<Stmt *, 4> BodyStmts;
5619
5620 // Capture all referenced variable references.
5621 // TODO: Instead of computing NewStart/NewStop/NewStep inside the
5622 // CapturedStmt, we could compute them before and capture the result, to be
5623 // used jointly with the LoopVar function.
5624 VarDecl *NewStart = precomputeExpr(Actions, BodyStmts, StartExpr, ".start");
5625 VarDecl *NewStop = precomputeExpr(Actions, BodyStmts, StopExpr, ".stop");
5626 VarDecl *NewStep = precomputeExpr(Actions, BodyStmts, StepExpr, ".step");
5627 auto BuildVarRef = [&](VarDecl *VD) {
5628 return buildDeclRefExpr(Actions, VD, VD->getType(), {});
5629 };
5630
5631 IntegerLiteral *Zero = IntegerLiteral::Create(
5632 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 0), LogicalTy, {});
5633 IntegerLiteral *One = IntegerLiteral::Create(
5634 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 1), LogicalTy, {});
5635 Expr *Dist;
5636 if (Rel == BO_NE) {
5637 // When using a != comparison, the increment can be +1 or -1. This can be
5638 // dynamic at runtime, so we need to check for the direction.
5639 Expr *IsNegStep = AssertSuccess(
5640 Actions.BuildBinOp(nullptr, {}, BO_LT, BuildVarRef(NewStep), Zero));
5641
5642 // Positive increment.
5643 Expr *ForwardRange = AssertSuccess(Actions.BuildBinOp(
5644 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5645 ForwardRange = AssertSuccess(
5646 Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, ForwardRange));
5647 Expr *ForwardDist = AssertSuccess(Actions.BuildBinOp(
5648 nullptr, {}, BO_Div, ForwardRange, BuildVarRef(NewStep)));
5649
5650 // Negative increment.
5651 Expr *BackwardRange = AssertSuccess(Actions.BuildBinOp(
5652 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5653 BackwardRange = AssertSuccess(
5654 Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, BackwardRange));
5655 Expr *NegIncAmount = AssertSuccess(
5656 Actions.BuildUnaryOp(nullptr, {}, UO_Minus, BuildVarRef(NewStep)));
5657 Expr *BackwardDist = AssertSuccess(
5658 Actions.BuildBinOp(nullptr, {}, BO_Div, BackwardRange, NegIncAmount));
5659
5660 // Use the appropriate case.
5661 Dist = AssertSuccess(Actions.ActOnConditionalOp(
5662 {}, {}, IsNegStep, BackwardDist, ForwardDist));
5663 } else {
5664 assert((Rel == BO_LT || Rel == BO_LE || Rel == BO_GE || Rel == BO_GT) &&(static_cast <bool> ((Rel == BO_LT || Rel == BO_LE || Rel
== BO_GE || Rel == BO_GT) && "Expected one of these relational operators"
) ? void (0) : __assert_fail ("(Rel == BO_LT || Rel == BO_LE || Rel == BO_GE || Rel == BO_GT) && \"Expected one of these relational operators\""
, "clang/lib/Sema/SemaOpenMP.cpp", 5665, __extension__ __PRETTY_FUNCTION__
))
5665 "Expected one of these relational operators")(static_cast <bool> ((Rel == BO_LT || Rel == BO_LE || Rel
== BO_GE || Rel == BO_GT) && "Expected one of these relational operators"
) ? void (0) : __assert_fail ("(Rel == BO_LT || Rel == BO_LE || Rel == BO_GE || Rel == BO_GT) && \"Expected one of these relational operators\""
, "clang/lib/Sema/SemaOpenMP.cpp", 5665, __extension__ __PRETTY_FUNCTION__
))
;
5666
5667 // We can derive the direction from any other comparison operator. It is
5668 // non well-formed OpenMP if Step increments/decrements in the other
5669 // directions. Whether at least the first iteration passes the loop
5670 // condition.
5671 Expr *HasAnyIteration = AssertSuccess(Actions.BuildBinOp(
5672 nullptr, {}, Rel, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5673
5674 // Compute the range between first and last counter value.
5675 Expr *Range;
5676 if (Rel == BO_GE || Rel == BO_GT)
5677 Range = AssertSuccess(Actions.BuildBinOp(
5678 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5679 else
5680 Range = AssertSuccess(Actions.BuildBinOp(
5681 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5682
5683 // Ensure unsigned range space.
5684 Range =
5685 AssertSuccess(Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, Range));
5686
5687 if (Rel == BO_LE || Rel == BO_GE) {
5688 // Add one to the range if the relational operator is inclusive.
5689 Range =
5690 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Add, Range, One));
5691 }
5692
5693 // Divide by the absolute step amount. If the range is not a multiple of
5694 // the step size, rounding-up the effective upper bound ensures that the
5695 // last iteration is included.
5696 // Note that the rounding-up may cause an overflow in a temporry that
5697 // could be avoided, but would have occurred in a C-style for-loop as well.
5698 Expr *Divisor = BuildVarRef(NewStep);
5699 if (Rel == BO_GE || Rel == BO_GT)
5700 Divisor =
5701 AssertSuccess(Actions.BuildUnaryOp(nullptr, {}, UO_Minus, Divisor));
5702 Expr *DivisorMinusOne =
5703 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Sub, Divisor, One));
5704 Expr *RangeRoundUp = AssertSuccess(
5705 Actions.BuildBinOp(nullptr, {}, BO_Add, Range, DivisorMinusOne));
5706 Dist = AssertSuccess(
5707 Actions.BuildBinOp(nullptr, {}, BO_Div, RangeRoundUp, Divisor));
5708
5709 // If there is not at least one iteration, the range contains garbage. Fix
5710 // to zero in this case.
5711 Dist = AssertSuccess(
5712 Actions.ActOnConditionalOp({}, {}, HasAnyIteration, Dist, Zero));
5713 }
5714
5715 // Assign the result to the out-parameter.
5716 Stmt *ResultAssign = AssertSuccess(Actions.BuildBinOp(
5717 Actions.getCurScope(), {}, BO_Assign, DistRef, Dist));
5718 BodyStmts.push_back(ResultAssign);
5719
5720 Body = AssertSuccess(Actions.ActOnCompoundStmt({}, {}, BodyStmts, false));
5721 }
5722
5723 return cast<CapturedStmt>(
5724 AssertSuccess(Actions.ActOnCapturedRegionEnd(Body)));
5725}
5726
5727/// Create a closure that computes the loop variable from the logical iteration
5728/// number.
5729///
5730/// \param Actions The Sema object.
5731/// \param LoopVarTy Type for the loop variable used for result value.
5732/// \param LogicalTy Type for the logical iteration number.
5733/// \param StartExpr Value of the loop counter at the first iteration.
5734/// \param Step Amount of increment after each iteration.
5735/// \param Deref Whether the loop variable is a dereference of the loop
5736/// counter variable.
5737///
5738/// \return Closure (CapturedStmt) of the loop value calculation.
5739static CapturedStmt *buildLoopVarFunc(Sema &Actions, QualType LoopVarTy,
5740 QualType LogicalTy,
5741 DeclRefExpr *StartExpr, Expr *Step,
5742 bool Deref) {
5743 ASTContext &Ctx = Actions.getASTContext();
5744
5745 // Pass the result as an out-parameter. Passing as return value would require
5746 // the OpenMPIRBuilder to know additional C/C++ semantics, such as how to
5747 // invoke a copy constructor.
5748 QualType TargetParamTy = Ctx.getLValueReferenceType(LoopVarTy);
5749 Sema::CapturedParamNameType Params[] = {{"LoopVar", TargetParamTy},
5750 {"Logical", LogicalTy},
5751 {StringRef(), QualType()}};
5752 Actions.ActOnCapturedRegionStart({}, nullptr, CR_Default, Params);
5753
5754 // Capture the initial iterator which represents the LoopVar value at the
5755 // zero's logical iteration. Since the original ForStmt/CXXForRangeStmt update
5756 // it in every iteration, capture it by value before it is modified.
5757 VarDecl *StartVar = cast<VarDecl>(StartExpr->getDecl());
5758 bool Invalid = Actions.tryCaptureVariable(StartVar, {},
5759 Sema::TryCapture_ExplicitByVal, {});
5760 (void)Invalid;
5761 assert(!Invalid && "Expecting capture-by-value to work.")(static_cast <bool> (!Invalid && "Expecting capture-by-value to work."
) ? void (0) : __assert_fail ("!Invalid && \"Expecting capture-by-value to work.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 5761, __extension__ __PRETTY_FUNCTION__
))
;
5762
5763 Expr *Body;
5764 {
5765 Sema::CompoundScopeRAII CompoundScope(Actions);
5766 auto *CS = cast<CapturedDecl>(Actions.CurContext);
5767
5768 ImplicitParamDecl *TargetParam = CS->getParam(0);
5769 DeclRefExpr *TargetRef = Actions.BuildDeclRefExpr(
5770 TargetParam, LoopVarTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5771 ImplicitParamDecl *IndvarParam = CS->getParam(1);
5772 DeclRefExpr *LogicalRef = Actions.BuildDeclRefExpr(
5773 IndvarParam, LogicalTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5774
5775 // Capture the Start expression.
5776 CaptureVars Recap(Actions);
5777 Expr *NewStart = AssertSuccess(Recap.TransformExpr(StartExpr));
5778 Expr *NewStep = AssertSuccess(Recap.TransformExpr(Step));
5779
5780 Expr *Skip = AssertSuccess(
5781 Actions.BuildBinOp(nullptr, {}, BO_Mul, NewStep, LogicalRef));
5782 // TODO: Explicitly cast to the iterator's difference_type instead of
5783 // relying on implicit conversion.
5784 Expr *Advanced =
5785 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Add, NewStart, Skip));
5786
5787 if (Deref) {
5788 // For range-based for-loops convert the loop counter value to a concrete
5789 // loop variable value by dereferencing the iterator.
5790 Advanced =
5791 AssertSuccess(Actions.BuildUnaryOp(nullptr, {}, UO_Deref, Advanced));
5792 }
5793
5794 // Assign the result to the output parameter.
5795 Body = AssertSuccess(Actions.BuildBinOp(Actions.getCurScope(), {},
5796 BO_Assign, TargetRef, Advanced));
5797 }
5798 return cast<CapturedStmt>(
5799 AssertSuccess(Actions.ActOnCapturedRegionEnd(Body)));
5800}
5801
5802StmtResult Sema::ActOnOpenMPCanonicalLoop(Stmt *AStmt) {
5803 ASTContext &Ctx = getASTContext();
5804
5805 // Extract the common elements of ForStmt and CXXForRangeStmt:
5806 // Loop variable, repeat condition, increment
5807 Expr *Cond, *Inc;
5808 VarDecl *LIVDecl, *LUVDecl;
5809 if (auto *For = dyn_cast<ForStmt>(AStmt)) {
5810 Stmt *Init = For->getInit();
5811 if (auto *LCVarDeclStmt = dyn_cast<DeclStmt>(Init)) {
5812 // For statement declares loop variable.
5813 LIVDecl = cast<VarDecl>(LCVarDeclStmt->getSingleDecl());
5814 } else if (auto *LCAssign = dyn_cast<BinaryOperator>(Init)) {
5815 // For statement reuses variable.
5816 assert(LCAssign->getOpcode() == BO_Assign &&(static_cast <bool> (LCAssign->getOpcode() == BO_Assign
&& "init part must be a loop variable assignment") ?
void (0) : __assert_fail ("LCAssign->getOpcode() == BO_Assign && \"init part must be a loop variable assignment\""
, "clang/lib/Sema/SemaOpenMP.cpp", 5817, __extension__ __PRETTY_FUNCTION__
))
5817 "init part must be a loop variable assignment")(static_cast <bool> (LCAssign->getOpcode() == BO_Assign
&& "init part must be a loop variable assignment") ?
void (0) : __assert_fail ("LCAssign->getOpcode() == BO_Assign && \"init part must be a loop variable assignment\""
, "clang/lib/Sema/SemaOpenMP.cpp", 5817, __extension__ __PRETTY_FUNCTION__
))
;
5818 auto *CounterRef = cast<DeclRefExpr>(LCAssign->getLHS());
5819 LIVDecl = cast<VarDecl>(CounterRef->getDecl());
5820 } else
5821 llvm_unreachable("Cannot determine loop variable")::llvm::llvm_unreachable_internal("Cannot determine loop variable"
, "clang/lib/Sema/SemaOpenMP.cpp", 5821)
;
5822 LUVDecl = LIVDecl;
5823
5824 Cond = For->getCond();
5825 Inc = For->getInc();
5826 } else if (auto *RangeFor = dyn_cast<CXXForRangeStmt>(AStmt)) {
5827 DeclStmt *BeginStmt = RangeFor->getBeginStmt();
5828 LIVDecl = cast<VarDecl>(BeginStmt->getSingleDecl());
5829 LUVDecl = RangeFor->getLoopVariable();
5830
5831 Cond = RangeFor->getCond();
5832 Inc = RangeFor->getInc();
5833 } else
5834 llvm_unreachable("unhandled kind of loop")::llvm::llvm_unreachable_internal("unhandled kind of loop", "clang/lib/Sema/SemaOpenMP.cpp"
, 5834)
;
5835
5836 QualType CounterTy = LIVDecl->getType();
5837 QualType LVTy = LUVDecl->getType();
5838
5839 // Analyze the loop condition.
5840 Expr *LHS, *RHS;
5841 BinaryOperator::Opcode CondRel;
5842 Cond = Cond->IgnoreImplicit();
5843 if (auto *CondBinExpr = dyn_cast<BinaryOperator>(Cond)) {
5844 LHS = CondBinExpr->getLHS();
5845 RHS = CondBinExpr->getRHS();
5846 CondRel = CondBinExpr->getOpcode();
5847 } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Cond)) {
5848 assert(CondCXXOp->getNumArgs() == 2 && "Comparison should have 2 operands")(static_cast <bool> (CondCXXOp->getNumArgs() == 2 &&
"Comparison should have 2 operands") ? void (0) : __assert_fail
("CondCXXOp->getNumArgs() == 2 && \"Comparison should have 2 operands\""
, "clang/lib/Sema/SemaOpenMP.cpp", 5848, __extension__ __PRETTY_FUNCTION__
))
;
5849 LHS = CondCXXOp->getArg(0);
5850 RHS = CondCXXOp->getArg(1);
5851 switch (CondCXXOp->getOperator()) {
5852 case OO_ExclaimEqual:
5853 CondRel = BO_NE;
5854 break;
5855 case OO_Less:
5856 CondRel = BO_LT;
5857 break;
5858 case OO_LessEqual:
5859 CondRel = BO_LE;
5860 break;
5861 case OO_Greater:
5862 CondRel = BO_GT;
5863 break;
5864 case OO_GreaterEqual:
5865 CondRel = BO_GE;
5866 break;
5867 default:
5868 llvm_unreachable("unexpected iterator operator")::llvm::llvm_unreachable_internal("unexpected iterator operator"
, "clang/lib/Sema/SemaOpenMP.cpp", 5868)
;
5869 }
5870 } else
5871 llvm_unreachable("unexpected loop condition")::llvm::llvm_unreachable_internal("unexpected loop condition"
, "clang/lib/Sema/SemaOpenMP.cpp", 5871)
;
5872
5873 // Normalize such that the loop counter is on the LHS.
5874 if (!isa<DeclRefExpr>(LHS->IgnoreImplicit()) ||
5875 cast<DeclRefExpr>(LHS->IgnoreImplicit())->getDecl() != LIVDecl) {
5876 std::swap(LHS, RHS);
5877 CondRel = BinaryOperator::reverseComparisonOp(CondRel);
5878 }
5879 auto *CounterRef = cast<DeclRefExpr>(LHS->IgnoreImplicit());
5880
5881 // Decide the bit width for the logical iteration counter. By default use the
5882 // unsigned ptrdiff_t integer size (for iterators and pointers).
5883 // TODO: For iterators, use iterator::difference_type,
5884 // std::iterator_traits<>::difference_type or decltype(it - end).
5885 QualType LogicalTy = Ctx.getUnsignedPointerDiffType();
5886 if (CounterTy->isIntegerType()) {
5887 unsigned BitWidth = Ctx.getIntWidth(CounterTy);
5888 LogicalTy = Ctx.getIntTypeForBitwidth(BitWidth, false);
5889 }
5890
5891 // Analyze the loop increment.
5892 Expr *Step;
5893 if (auto *IncUn = dyn_cast<UnaryOperator>(Inc)) {
5894 int Direction;
5895 switch (IncUn->getOpcode()) {
5896 case UO_PreInc:
5897 case UO_PostInc:
5898 Direction = 1;
5899 break;
5900 case UO_PreDec:
5901 case UO_PostDec:
5902 Direction = -1;
5903 break;
5904 default:
5905 llvm_unreachable("unhandled unary increment operator")::llvm::llvm_unreachable_internal("unhandled unary increment operator"
, "clang/lib/Sema/SemaOpenMP.cpp", 5905)
;
5906 }
5907 Step = IntegerLiteral::Create(
5908 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), Direction), LogicalTy, {});
5909 } else if (auto *IncBin = dyn_cast<BinaryOperator>(Inc)) {
5910 if (IncBin->getOpcode() == BO_AddAssign) {
5911 Step = IncBin->getRHS();
5912 } else if (IncBin->getOpcode() == BO_SubAssign) {
5913 Step =
5914 AssertSuccess(BuildUnaryOp(nullptr, {}, UO_Minus, IncBin->getRHS()));
5915 } else
5916 llvm_unreachable("unhandled binary increment operator")::llvm::llvm_unreachable_internal("unhandled binary increment operator"
, "clang/lib/Sema/SemaOpenMP.cpp", 5916)
;
5917 } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Inc)) {
5918 switch (CondCXXOp->getOperator()) {
5919 case OO_PlusPlus:
5920 Step = IntegerLiteral::Create(
5921 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 1), LogicalTy, {});
5922 break;
5923 case OO_MinusMinus:
5924 Step = IntegerLiteral::Create(
5925 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), -1), LogicalTy, {});
5926 break;
5927 case OO_PlusEqual:
5928 Step = CondCXXOp->getArg(1);
5929 break;
5930 case OO_MinusEqual:
5931 Step = AssertSuccess(
5932 BuildUnaryOp(nullptr, {}, UO_Minus, CondCXXOp->getArg(1)));
5933 break;
5934 default:
5935 llvm_unreachable("unhandled overloaded increment operator")::llvm::llvm_unreachable_internal("unhandled overloaded increment operator"
, "clang/lib/Sema/SemaOpenMP.cpp", 5935)
;
5936 }
5937 } else
5938 llvm_unreachable("unknown increment expression")::llvm::llvm_unreachable_internal("unknown increment expression"
, "clang/lib/Sema/SemaOpenMP.cpp", 5938)
;
5939
5940 CapturedStmt *DistanceFunc =
5941 buildDistanceFunc(*this, LogicalTy, CondRel, LHS, RHS, Step);
5942 CapturedStmt *LoopVarFunc = buildLoopVarFunc(
5943 *this, LVTy, LogicalTy, CounterRef, Step, isa<CXXForRangeStmt>(AStmt));
5944 DeclRefExpr *LVRef = BuildDeclRefExpr(LUVDecl, LUVDecl->getType(), VK_LValue,
5945 {}, nullptr, nullptr, {}, nullptr);
5946 return OMPCanonicalLoop::create(getASTContext(), AStmt, DistanceFunc,
5947 LoopVarFunc, LVRef);
5948}
5949
5950StmtResult Sema::ActOnOpenMPLoopnest(Stmt *AStmt) {
5951 // Handle a literal loop.
5952 if (isa<ForStmt>(AStmt) || isa<CXXForRangeStmt>(AStmt))
5953 return ActOnOpenMPCanonicalLoop(AStmt);
5954
5955 // If not a literal loop, it must be the result of a loop transformation.
5956 OMPExecutableDirective *LoopTransform = cast<OMPExecutableDirective>(AStmt);
5957 assert((static_cast <bool> (isOpenMPLoopTransformationDirective
(LoopTransform->getDirectiveKind()) && "Loop transformation directive expected"
) ? void (0) : __assert_fail ("isOpenMPLoopTransformationDirective(LoopTransform->getDirectiveKind()) && \"Loop transformation directive expected\""
, "clang/lib/Sema/SemaOpenMP.cpp", 5959, __extension__ __PRETTY_FUNCTION__
))
5958 isOpenMPLoopTransformationDirective(LoopTransform->getDirectiveKind()) &&(static_cast <bool> (isOpenMPLoopTransformationDirective
(LoopTransform->getDirectiveKind()) && "Loop transformation directive expected"
) ? void (0) : __assert_fail ("isOpenMPLoopTransformationDirective(LoopTransform->getDirectiveKind()) && \"Loop transformation directive expected\""
, "clang/lib/Sema/SemaOpenMP.cpp", 5959, __extension__ __PRETTY_FUNCTION__
))
5959 "Loop transformation directive expected")(static_cast <bool> (isOpenMPLoopTransformationDirective
(LoopTransform->getDirectiveKind()) && "Loop transformation directive expected"
) ? void (0) : __assert_fail ("isOpenMPLoopTransformationDirective(LoopTransform->getDirectiveKind()) && \"Loop transformation directive expected\""
, "clang/lib/Sema/SemaOpenMP.cpp", 5959, __extension__ __PRETTY_FUNCTION__
))
;
5960 return LoopTransform;
5961}
5962
5963static ExprResult buildUserDefinedMapperRef(Sema &SemaRef, Scope *S,
5964 CXXScopeSpec &MapperIdScopeSpec,
5965 const DeclarationNameInfo &MapperId,
5966 QualType Type,
5967 Expr *UnresolvedMapper);
5968
5969/// Perform DFS through the structure/class data members trying to find
5970/// member(s) with user-defined 'default' mapper and generate implicit map
5971/// clauses for such members with the found 'default' mapper.
5972static void
5973processImplicitMapsWithDefaultMappers(Sema &S, DSAStackTy *Stack,
5974 SmallVectorImpl<OMPClause *> &Clauses) {
5975 // Check for the deault mapper for data members.
5976 if (S.getLangOpts().OpenMP < 50)
5977 return;
5978 SmallVector<OMPClause *, 4> ImplicitMaps;
5979 for (int Cnt = 0, EndCnt = Clauses.size(); Cnt < EndCnt; ++Cnt) {
5980 auto *C = dyn_cast<OMPMapClause>(Clauses[Cnt]);
5981 if (!C)
5982 continue;
5983 SmallVector<Expr *, 4> SubExprs;
5984 auto *MI = C->mapperlist_begin();
5985 for (auto I = C->varlist_begin(), End = C->varlist_end(); I != End;
5986 ++I, ++MI) {
5987 // Expression is mapped using mapper - skip it.
5988 if (*MI)
5989 continue;
5990 Expr *E = *I;
5991 // Expression is dependent - skip it, build the mapper when it gets
5992 // instantiated.
5993 if (E->isTypeDependent() || E->isValueDependent() ||
5994 E->containsUnexpandedParameterPack())
5995 continue;
5996 // Array section - need to check for the mapping of the array section
5997 // element.
5998 QualType CanonType = E->getType().getCanonicalType();
5999 if (CanonType->isSpecificBuiltinType(BuiltinType::OMPArraySection)) {
6000 const auto *OASE = cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts());
6001 QualType BaseType =
6002 OMPArraySectionExpr::getBaseOriginalType(OASE->getBase());
6003 QualType ElemType;
6004 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
6005 ElemType = ATy->getElementType();
6006 else
6007 ElemType = BaseType->getPointeeType();
6008 CanonType = ElemType;
6009 }
6010
6011 // DFS over data members in structures/classes.
6012 SmallVector<std::pair<QualType, FieldDecl *>, 4> Types(
6013 1, {CanonType, nullptr});
6014 llvm::DenseMap<const Type *, Expr *> Visited;
6015 SmallVector<std::pair<FieldDecl *, unsigned>, 4> ParentChain(
6016 1, {nullptr, 1});
6017 while (!Types.empty()) {
6018 QualType BaseType;
6019 FieldDecl *CurFD;
6020 std::tie(BaseType, CurFD) = Types.pop_back_val();
6021 while (ParentChain.back().second == 0)
6022 ParentChain.pop_back();
6023 --ParentChain.back().second;
6024 if (BaseType.isNull())
6025 continue;
6026 // Only structs/classes are allowed to have mappers.
6027 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
6028 if (!RD)
6029 continue;
6030 auto It = Visited.find(BaseType.getTypePtr());
6031 if (It == Visited.end()) {
6032 // Try to find the associated user-defined mapper.
6033 CXXScopeSpec MapperIdScopeSpec;
6034 DeclarationNameInfo DefaultMapperId;
6035 DefaultMapperId.setName(S.Context.DeclarationNames.getIdentifier(
6036 &S.Context.Idents.get("default")));
6037 DefaultMapperId.setLoc(E->getExprLoc());
6038 ExprResult ER = buildUserDefinedMapperRef(
6039 S, Stack->getCurScope(), MapperIdScopeSpec, DefaultMapperId,
6040 BaseType, /*UnresolvedMapper=*/nullptr);
6041 if (ER.isInvalid())
6042 continue;
6043 It = Visited.try_emplace(BaseType.getTypePtr(), ER.get()).first;
6044 }
6045 // Found default mapper.
6046 if (It->second) {
6047 auto *OE = new (S.Context) OpaqueValueExpr(E->getExprLoc(), CanonType,
6048 VK_LValue, OK_Ordinary, E);
6049 OE->setIsUnique(/*V=*/true);
6050 Expr *BaseExpr = OE;
6051 for (const auto &P : ParentChain) {
6052 if (P.first) {
6053 BaseExpr = S.BuildMemberExpr(
6054 BaseExpr, /*IsArrow=*/false, E->getExprLoc(),
6055 NestedNameSpecifierLoc(), SourceLocation(), P.first,
6056 DeclAccessPair::make(P.first, P.first->getAccess()),
6057 /*HadMultipleCandidates=*/false, DeclarationNameInfo(),
6058 P.first->getType(), VK_LValue, OK_Ordinary);
6059 BaseExpr = S.DefaultLvalueConversion(BaseExpr).get();
6060 }
6061 }
6062 if (CurFD)
6063 BaseExpr = S.BuildMemberExpr(
6064 BaseExpr, /*IsArrow=*/false, E->getExprLoc(),
6065 NestedNameSpecifierLoc(), SourceLocation(), CurFD,
6066 DeclAccessPair::make(CurFD, CurFD->getAccess()),
6067 /*HadMultipleCandidates=*/false, DeclarationNameInfo(),
6068 CurFD->getType(), VK_LValue, OK_Ordinary);
6069 SubExprs.push_back(BaseExpr);
6070 continue;
6071 }
6072 // Check for the "default" mapper for data members.
6073 bool FirstIter = true;
6074 for (FieldDecl *FD : RD->fields()) {
6075 if (!FD)
6076 continue;
6077 QualType FieldTy = FD->getType();
6078 if (FieldTy.isNull() ||
6079 !(FieldTy->isStructureOrClassType() || FieldTy->isUnionType()))
6080 continue;
6081 if (FirstIter) {
6082 FirstIter = false;
6083 ParentChain.emplace_back(CurFD, 1);
6084 } else {
6085 ++ParentChain.back().second;
6086 }
6087 Types.emplace_back(FieldTy, FD);
6088 }
6089 }
6090 }
6091 if (SubExprs.empty())
6092 continue;
6093 CXXScopeSpec MapperIdScopeSpec;
6094 DeclarationNameInfo MapperId;
6095 if (OMPClause *NewClause = S.ActOnOpenMPMapClause(
6096 nullptr, C->getMapTypeModifiers(), C->getMapTypeModifiersLoc(),
6097 MapperIdScopeSpec, MapperId, C->getMapType(),
6098 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(),
6099 SubExprs, OMPVarListLocTy()))
6100 Clauses.push_back(NewClause);
6101 }
6102}
6103
6104StmtResult Sema::ActOnOpenMPExecutableDirective(
6105 OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
6106 OpenMPDirectiveKind CancelRegion, ArrayRef<OMPClause *> Clauses,
6107 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
6108 StmtResult Res = StmtError();
6109 OpenMPBindClauseKind BindKind = OMPC_BIND_unknown;
6110 if (const OMPBindClause *BC =
6111 OMPExecutableDirective::getSingleClause<OMPBindClause>(Clauses))
6112 BindKind = BC->getBindKind();
6113 // First check CancelRegion which is then used in checkNestingOfRegions.
6114 if (checkCancelRegion(*this, Kind, CancelRegion, StartLoc) ||
6115 checkNestingOfRegions(*this, DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
, Kind, DirName, CancelRegion,
6116 BindKind, StartLoc))
6117 return StmtError();
6118
6119 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
6120 if (getLangOpts().HIP && (isOpenMPTargetExecutionDirective(Kind) ||
6121 isOpenMPTargetDataManagementDirective(Kind)))
6122 Diag(StartLoc, diag::warn_hip_omp_target_directives);
6123
6124 llvm::SmallVector<OMPClause *, 8> ClausesWithImplicit;
6125 VarsWithInheritedDSAType VarsWithInheritedDSA;
6126 bool ErrorFound = false;
6127 ClausesWithImplicit.append(Clauses.begin(), Clauses.end());
6128 if (AStmt && !CurContext->isDependentContext() && Kind != OMPD_atomic &&
6129 Kind != OMPD_critical && Kind != OMPD_section && Kind != OMPD_master &&
6130 Kind != OMPD_masked && !isOpenMPLoopTransformationDirective(Kind)) {
6131 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected")(static_cast <bool> (isa<CapturedStmt>(AStmt) &&
"Captured statement expected") ? void (0) : __assert_fail ("isa<CapturedStmt>(AStmt) && \"Captured statement expected\""
, "clang/lib/Sema/SemaOpenMP.cpp", 6131, __extension__ __PRETTY_FUNCTION__
))
;
6132
6133 // Check default data sharing attributes for referenced variables.
6134 DSAAttrChecker DSAChecker(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
, *this, cast<CapturedStmt>(AStmt));
6135 int ThisCaptureLevel = getOpenMPCaptureLevels(Kind);
6136 Stmt *S = AStmt;
6137 while (--ThisCaptureLevel >= 0)
6138 S = cast<CapturedStmt>(S)->getCapturedStmt();
6139 DSAChecker.Visit(S);
6140 if (!isOpenMPTargetDataManagementDirective(Kind) &&
6141 !isOpenMPTaskingDirective(Kind)) {
6142 // Visit subcaptures to generate implicit clauses for captured vars.
6143 auto *CS = cast<CapturedStmt>(AStmt);
6144 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
6145 getOpenMPCaptureRegions(CaptureRegions, Kind);
6146 // Ignore outer tasking regions for target directives.
6147 if (CaptureRegions.size() > 1 && CaptureRegions.front() == OMPD_task)
6148 CS = cast<CapturedStmt>(CS->getCapturedStmt());
6149 DSAChecker.visitSubCaptures(CS);
6150 }
6151 if (DSAChecker.isErrorFound())
6152 return StmtError();
6153 // Generate list of implicitly defined firstprivate variables.
6154 VarsWithInheritedDSA = DSAChecker.getVarsWithInheritedDSA();
6155
6156 SmallVector<Expr *, 4> ImplicitFirstprivates(
6157 DSAChecker.getImplicitFirstprivate().begin(),
6158 DSAChecker.getImplicitFirstprivate().end());
6159 SmallVector<Expr *, 4> ImplicitPrivates(
6160 DSAChecker.getImplicitPrivate().begin(),
6161 DSAChecker.getImplicitPrivate().end());
6162 const unsigned DefaultmapKindNum = OMPC_DEFAULTMAP_pointer + 1;
6163 SmallVector<Expr *, 4> ImplicitMaps[DefaultmapKindNum][OMPC_MAP_delete];
6164 SmallVector<OpenMPMapModifierKind, NumberOfOMPMapClauseModifiers>
6165 ImplicitMapModifiers[DefaultmapKindNum];
6166 SmallVector<SourceLocation, NumberOfOMPMapClauseModifiers>
6167 ImplicitMapModifiersLoc[DefaultmapKindNum];
6168 // Get the original location of present modifier from Defaultmap clause.
6169 SourceLocation PresentModifierLocs[DefaultmapKindNum];
6170 for (OMPClause *C : Clauses) {
6171 if (auto *DMC = dyn_cast<OMPDefaultmapClause>(C))
6172 if (DMC->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_present)
6173 PresentModifierLocs[DMC->getDefaultmapKind()] =
6174 DMC->getDefaultmapModifierLoc();
6175 }
6176 for (unsigned VC = 0; VC < DefaultmapKindNum; ++VC) {
6177 auto Kind = static_cast<OpenMPDefaultmapClauseKind>(VC);
6178 for (unsigned I = 0; I < OMPC_MAP_delete; ++I) {
6179 ArrayRef<Expr *> ImplicitMap = DSAChecker.getImplicitMap(
6180 Kind, static_cast<OpenMPMapClauseKind>(I));
6181 ImplicitMaps[VC][I].append(ImplicitMap.begin(), ImplicitMap.end());
6182 }
6183 ArrayRef<OpenMPMapModifierKind> ImplicitModifier =
6184 DSAChecker.getImplicitMapModifier(Kind);
6185 ImplicitMapModifiers[VC].append(ImplicitModifier.begin(),
6186 ImplicitModifier.end());
6187 std::fill_n(std::back_inserter(ImplicitMapModifiersLoc[VC]),
6188 ImplicitModifier.size(), PresentModifierLocs[VC]);
6189 }
6190 // Mark taskgroup task_reduction descriptors as implicitly firstprivate.
6191 for (OMPClause *C : Clauses) {
6192 if (auto *IRC = dyn_cast<OMPInReductionClause>(C)) {
6193 for (Expr *E : IRC->taskgroup_descriptors())
6194 if (E)
6195 ImplicitFirstprivates.emplace_back(E);
6196 }
6197 // OpenMP 5.0, 2.10.1 task Construct
6198 // [detach clause]... The event-handle will be considered as if it was
6199 // specified on a firstprivate clause.
6200 if (auto *DC = dyn_cast<OMPDetachClause>(C))
6201 ImplicitFirstprivates.push_back(DC->getEventHandler());
6202 }
6203 if (!ImplicitFirstprivates.empty()) {
6204 if (OMPClause *Implicit = ActOnOpenMPFirstprivateClause(
6205 ImplicitFirstprivates, SourceLocation(), SourceLocation(),
6206 SourceLocation())) {
6207 ClausesWithImplicit.push_back(Implicit);
6208 ErrorFound = cast<OMPFirstprivateClause>(Implicit)->varlist_size() !=
6209 ImplicitFirstprivates.size();
6210 } else {
6211 ErrorFound = true;
6212 }
6213 }
6214 if (!ImplicitPrivates.empty()) {
6215 if (OMPClause *Implicit =
6216 ActOnOpenMPPrivateClause(ImplicitPrivates, SourceLocation(),
6217 SourceLocation(), SourceLocation())) {
6218 ClausesWithImplicit.push_back(Implicit);
6219 ErrorFound = cast<OMPPrivateClause>(Implicit)->varlist_size() !=
6220 ImplicitPrivates.size();
6221 } else {
6222 ErrorFound = true;
6223 }
6224 }
6225 // OpenMP 5.0 [2.19.7]
6226 // If a list item appears in a reduction, lastprivate or linear
6227 // clause on a combined target construct then it is treated as
6228 // if it also appears in a map clause with a map-type of tofrom
6229 if (getLangOpts().OpenMP >= 50 && Kind != OMPD_target &&
6230 isOpenMPTargetExecutionDirective(Kind)) {
6231 SmallVector<Expr *, 4> ImplicitExprs;
6232 for (OMPClause *C : Clauses) {
6233 if (auto *RC = dyn_cast<OMPReductionClause>(C))
6234 for (Expr *E : RC->varlists())
6235 if (!isa<DeclRefExpr>(E->IgnoreParenImpCasts()))
6236 ImplicitExprs.emplace_back(E);
6237 }
6238 if (!ImplicitExprs.empty()) {
6239 ArrayRef<Expr *> Exprs = ImplicitExprs;
6240 CXXScopeSpec MapperIdScopeSpec;
6241 DeclarationNameInfo MapperId;
6242 if (OMPClause *Implicit = ActOnOpenMPMapClause(
6243 nullptr, OMPC_MAP_MODIFIER_unknown, SourceLocation(),
6244 MapperIdScopeSpec, MapperId, OMPC_MAP_tofrom,
6245 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(),
6246 Exprs, OMPVarListLocTy(), /*NoDiagnose=*/true))
6247 ClausesWithImplicit.emplace_back(Implicit);
6248 }
6249 }
6250 for (unsigned I = 0, E = DefaultmapKindNum; I < E; ++I) {
6251 int ClauseKindCnt = -1;
6252 for (ArrayRef<Expr *> ImplicitMap : ImplicitMaps[I]) {
6253 ++ClauseKindCnt;
6254 if (ImplicitMap.empty())
6255 continue;
6256 CXXScopeSpec MapperIdScopeSpec;
6257 DeclarationNameInfo MapperId;
6258 auto Kind = static_cast<OpenMPMapClauseKind>(ClauseKindCnt);
6259 if (OMPClause *Implicit = ActOnOpenMPMapClause(
6260 nullptr, ImplicitMapModifiers[I], ImplicitMapModifiersLoc[I],
6261 MapperIdScopeSpec, MapperId, Kind, /*IsMapTypeImplicit=*/true,
6262 SourceLocation(), SourceLocation(), ImplicitMap,
6263 OMPVarListLocTy())) {
6264 ClausesWithImplicit.emplace_back(Implicit);
6265 ErrorFound |= cast<OMPMapClause>(Implicit)->varlist_size() !=
6266 ImplicitMap.size();
6267 } else {
6268 ErrorFound = true;
6269 }
6270 }
6271 }
6272 // Build expressions for implicit maps of data members with 'default'
6273 // mappers.
6274 if (LangOpts.OpenMP >= 50)
6275 processImplicitMapsWithDefaultMappers(*this, DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
,
6276 ClausesWithImplicit);
6277 }
6278
6279 llvm::SmallVector<OpenMPDirectiveKind, 4> AllowedNameModifiers;
6280 switch (Kind) {
6281 case OMPD_parallel:
6282 Res = ActOnOpenMPParallelDirective(ClausesWithImplicit, AStmt, StartLoc,
6283 EndLoc);
6284 AllowedNameModifiers.push_back(OMPD_parallel);
6285 break;
6286 case OMPD_simd:
6287 Res = ActOnOpenMPSimdDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc,
6288 VarsWithInheritedDSA);
6289 if (LangOpts.OpenMP >= 50)
6290 AllowedNameModifiers.push_back(OMPD_simd);
6291 break;
6292 case OMPD_tile:
6293 Res =
6294 ActOnOpenMPTileDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6295 break;
6296 case OMPD_unroll:
6297 Res = ActOnOpenMPUnrollDirective(ClausesWithImplicit, AStmt, StartLoc,
6298 EndLoc);
6299 break;
6300 case OMPD_for:
6301 Res = ActOnOpenMPForDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc,
6302 VarsWithInheritedDSA);
6303 break;
6304 case OMPD_for_simd:
6305 Res = ActOnOpenMPForSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6306 EndLoc, VarsWithInheritedDSA);
6307 if (LangOpts.OpenMP >= 50)
6308 AllowedNameModifiers.push_back(OMPD_simd);
6309 break;
6310 case OMPD_sections:
6311 Res = ActOnOpenMPSectionsDirective(ClausesWithImplicit, AStmt, StartLoc,
6312 EndLoc);
6313 break;
6314 case OMPD_section:
6315 assert(ClausesWithImplicit.empty() &&(static_cast <bool> (ClausesWithImplicit.empty() &&
"No clauses are allowed for 'omp section' directive") ? void
(0) : __assert_fail ("ClausesWithImplicit.empty() && \"No clauses are allowed for 'omp section' directive\""
, "clang/lib/Sema/SemaOpenMP.cpp", 6316, __extension__ __PRETTY_FUNCTION__
))
6316 "No clauses are allowed for 'omp section' directive")(static_cast <bool> (ClausesWithImplicit.empty() &&
"No clauses are allowed for 'omp section' directive") ? void
(0) : __assert_fail ("ClausesWithImplicit.empty() && \"No clauses are allowed for 'omp section' directive\""
, "clang/lib/Sema/SemaOpenMP.cpp", 6316, __extension__ __PRETTY_FUNCTION__
))
;
6317 Res = ActOnOpenMPSectionDirective(AStmt, StartLoc, EndLoc);
6318 break;
6319 case OMPD_single:
6320 Res = ActOnOpenMPSingleDirective(ClausesWithImplicit, AStmt, StartLoc,
6321 EndLoc);
6322 break;
6323 case OMPD_master:
6324 assert(ClausesWithImplicit.empty() &&(static_cast <bool> (ClausesWithImplicit.empty() &&
"No clauses are allowed for 'omp master' directive") ? void (
0) : __assert_fail ("ClausesWithImplicit.empty() && \"No clauses are allowed for 'omp master' directive\""
, "clang/lib/Sema/SemaOpenMP.cpp", 6325, __extension__ __PRETTY_FUNCTION__
))
6325 "No clauses are allowed for 'omp master' directive")(static_cast <bool> (ClausesWithImplicit.empty() &&
"No clauses are allowed for 'omp master' directive") ? void (
0) : __assert_fail ("ClausesWithImplicit.empty() && \"No clauses are allowed for 'omp master' directive\""
, "clang/lib/Sema/SemaOpenMP.cpp", 6325, __extension__ __PRETTY_FUNCTION__
))
;
6326 Res = ActOnOpenMPMasterDirective(AStmt, StartLoc, EndLoc);
6327 break;
6328 case OMPD_masked:
6329 Res = ActOnOpenMPMaskedDirective(ClausesWithImplicit, AStmt, StartLoc,
6330 EndLoc);
6331 break;
6332 case OMPD_critical:
6333 Res = ActOnOpenMPCriticalDirective(DirName, ClausesWithImplicit, AStmt,
6334 StartLoc, EndLoc);
6335 break;
6336 case OMPD_parallel_for:
6337 Res = ActOnOpenMPParallelForDirective(ClausesWithImplicit, AStmt, StartLoc,
6338 EndLoc, VarsWithInheritedDSA);
6339 AllowedNameModifiers.push_back(OMPD_parallel);
6340 break;
6341 case OMPD_parallel_for_simd:
6342 Res = ActOnOpenMPParallelForSimdDirective(
6343 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6344 AllowedNameModifiers.push_back(OMPD_parallel);
6345 if (LangOpts.OpenMP >= 50)
6346 AllowedNameModifiers.push_back(OMPD_simd);
6347 break;
6348 case OMPD_parallel_master:
6349 Res = ActOnOpenMPParallelMasterDirective(ClausesWithImplicit, AStmt,
6350 StartLoc, EndLoc);
6351 AllowedNameModifiers.push_back(OMPD_parallel);
6352 break;
6353 case OMPD_parallel_masked:
6354 Res = ActOnOpenMPParallelMaskedDirective(ClausesWithImplicit, AStmt,
6355 StartLoc, EndLoc);
6356 AllowedNameModifiers.push_back(OMPD_parallel);
6357 break;
6358 case OMPD_parallel_sections:
6359 Res = ActOnOpenMPParallelSectionsDirective(ClausesWithImplicit, AStmt,
6360 StartLoc, EndLoc);
6361 AllowedNameModifiers.push_back(OMPD_parallel);
6362 break;
6363 case OMPD_task:
6364 Res =
6365 ActOnOpenMPTaskDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6366 AllowedNameModifiers.push_back(OMPD_task);
6367 break;
6368 case OMPD_taskyield:
6369 assert(ClausesWithImplicit.empty() &&(static_cast <bool> (ClausesWithImplicit.empty() &&
"No clauses are allowed for 'omp taskyield' directive") ? void
(0) : __assert_fail ("ClausesWithImplicit.empty() && \"No clauses are allowed for 'omp taskyield' directive\""
, "clang/lib/Sema/SemaOpenMP.cpp", 6370, __extension__ __PRETTY_FUNCTION__
))
6370 "No clauses are allowed for 'omp taskyield' directive")(static_cast <bool> (ClausesWithImplicit.empty() &&
"No clauses are allowed for 'omp taskyield' directive") ? void
(0) : __assert_fail ("ClausesWithImplicit.empty() && \"No clauses are allowed for 'omp taskyield' directive\""
, "clang/lib/Sema/SemaOpenMP.cpp", 6370, __extension__ __PRETTY_FUNCTION__
))
;
6371 assert(AStmt == nullptr &&(static_cast <bool> (AStmt == nullptr && "No associated statement allowed for 'omp taskyield' directive"
) ? void (0) : __assert_fail ("AStmt == nullptr && \"No associated statement allowed for 'omp taskyield' directive\""
, "clang/lib/Sema/SemaOpenMP.cpp", 6372, __extension__ __PRETTY_FUNCTION__
))
6372 "No associated statement allowed for 'omp taskyield' directive")(static_cast <bool> (AStmt == nullptr && "No associated statement allowed for 'omp taskyield' directive"
) ? void (0) : __assert_fail ("AStmt == nullptr && \"No associated statement allowed for 'omp taskyield' directive\""
, "clang/lib/Sema/SemaOpenMP.cpp", 6372, __extension__ __PRETTY_FUNCTION__
))
;
6373 Res = ActOnOpenMPTaskyieldDirective(StartLoc, EndLoc);
6374 break;
6375 case OMPD_error:
6376 assert(AStmt == nullptr &&(static_cast <bool> (AStmt == nullptr && "No associated statement allowed for 'omp error' directive"
) ? void (0) : __assert_fail ("AStmt == nullptr && \"No associated statement allowed for 'omp error' directive\""
, "clang/lib/Sema/SemaOpenMP.cpp", 6377, __extension__ __PRETTY_FUNCTION__
))
6377 "No associated statement allowed for 'omp error' directive")(static_cast <bool> (AStmt == nullptr && "No associated statement allowed for 'omp error' directive"
) ? void (0) : __assert_fail ("AStmt == nullptr && \"No associated statement allowed for 'omp error' directive\""
, "clang/lib/Sema/SemaOpenMP.cpp", 6377, __extension__ __PRETTY_FUNCTION__
))
;
6378 Res = ActOnOpenMPErrorDirective(ClausesWithImplicit, StartLoc, EndLoc);
6379 break;
6380 case OMPD_barrier:
6381 assert(ClausesWithImplicit.empty() &&(static_cast <bool> (ClausesWithImplicit.empty() &&
"No clauses are allowed for 'omp barrier' directive") ? void
(0) : __assert_fail ("ClausesWithImplicit.empty() && \"No clauses are allowed for 'omp barrier' directive\""
, "clang/lib/Sema/SemaOpenMP.cpp", 6382, __extension__ __PRETTY_FUNCTION__
))
6382 "No clauses are allowed for 'omp barrier' directive")(static_cast <bool> (ClausesWithImplicit.empty() &&
"No clauses are allowed for 'omp barrier' directive") ? void
(0) : __assert_fail ("ClausesWithImplicit.empty() && \"No clauses are allowed for 'omp barrier' directive\""
, "clang/lib/Sema/SemaOpenMP.cpp", 6382, __extension__ __PRETTY_FUNCTION__
))
;
6383 assert(AStmt == nullptr &&(static_cast <bool> (AStmt == nullptr && "No associated statement allowed for 'omp barrier' directive"
) ? void (0) : __assert_fail ("AStmt == nullptr && \"No associated statement allowed for 'omp barrier' directive\""
, "clang/lib/Sema/SemaOpenMP.cpp", 6384, __extension__ __PRETTY_FUNCTION__
))
6384 "No associated statement allowed for 'omp barrier' directive")(static_cast <bool> (AStmt == nullptr && "No associated statement allowed for 'omp barrier' directive"
) ? void (0) : __assert_fail ("AStmt == nullptr && \"No associated statement allowed for 'omp barrier' directive\""
, "clang/lib/Sema/SemaOpenMP.cpp", 6384, __extension__ __PRETTY_FUNCTION__
))
;
6385 Res = ActOnOpenMPBarrierDirective(StartLoc, EndLoc);
6386 break;
6387 case OMPD_taskwait:
6388 assert(AStmt == nullptr &&(static_cast <bool> (AStmt == nullptr && "No associated statement allowed for 'omp taskwait' directive"
) ? void (0) : __assert_fail ("AStmt == nullptr && \"No associated statement allowed for 'omp taskwait' directive\""
, "clang/lib/Sema/SemaOpenMP.cpp", 6389, __extension__ __PRETTY_FUNCTION__
))
6389 "No associated statement allowed for 'omp taskwait' directive")(static_cast <bool> (AStmt == nullptr && "No associated statement allowed for 'omp taskwait' directive"
) ? void (0) : __assert_fail ("AStmt == nullptr && \"No associated statement allowed for 'omp taskwait' directive\""
, "clang/lib/Sema/SemaOpenMP.cpp", 6389, __extension__ __PRETTY_FUNCTION__
))
;
6390 Res = ActOnOpenMPTaskwaitDirective(ClausesWithImplicit, StartLoc, EndLoc);
6391 break;
6392 case OMPD_taskgroup:
6393 Res = ActOnOpenMPTaskgroupDirective(ClausesWithImplicit, AStmt, StartLoc,
6394 EndLoc);
6395 break;
6396 case OMPD_flush:
6397 assert(AStmt == nullptr &&(static_cast <bool> (AStmt == nullptr && "No associated statement allowed for 'omp flush' directive"
) ? void (0) : __assert_fail ("AStmt == nullptr && \"No associated statement allowed for 'omp flush' directive\""
, "clang/lib/Sema/SemaOpenMP.cpp", 6398, __extension__ __PRETTY_FUNCTION__
))
6398 "No associated statement allowed for 'omp flush' directive")(static_cast <bool> (AStmt == nullptr && "No associated statement allowed for 'omp flush' directive"
) ? void (0) : __assert_fail ("AStmt == nullptr && \"No associated statement allowed for 'omp flush' directive\""
, "clang/lib/Sema/SemaOpenMP.cpp", 6398, __extension__ __PRETTY_FUNCTION__
))
;
6399 Res = ActOnOpenMPFlushDirective(ClausesWithImplicit, StartLoc, EndLoc);
6400 break;
6401 case OMPD_depobj:
6402 assert(AStmt == nullptr &&(static_cast <bool> (AStmt == nullptr && "No associated statement allowed for 'omp depobj' directive"
) ? void (0) : __assert_fail ("AStmt == nullptr && \"No associated statement allowed for 'omp depobj' directive\""
, "clang/lib/Sema/SemaOpenMP.cpp", 6403, __extension__ __PRETTY_FUNCTION__
))
6403 "No associated statement allowed for 'omp depobj' directive")(static_cast <bool> (AStmt == nullptr && "No associated statement allowed for 'omp depobj' directive"
) ? void (0) : __assert_fail ("AStmt == nullptr && \"No associated statement allowed for 'omp depobj' directive\""
, "clang/lib/Sema/SemaOpenMP.cpp", 6403, __extension__ __PRETTY_FUNCTION__
))
;
6404 Res = ActOnOpenMPDepobjDirective(ClausesWithImplicit, StartLoc, EndLoc);
6405 break;
6406 case OMPD_scan:
6407 assert(AStmt == nullptr &&(static_cast <bool> (AStmt == nullptr && "No associated statement allowed for 'omp scan' directive"
) ? void (0) : __assert_fail ("AStmt == nullptr && \"No associated statement allowed for 'omp scan' directive\""
, "clang/lib/Sema/SemaOpenMP.cpp", 6408, __extension__ __PRETTY_FUNCTION__
))
6408 "No associated statement allowed for 'omp scan' directive")(static_cast <bool> (AStmt == nullptr && "No associated statement allowed for 'omp scan' directive"
) ? void (0) : __assert_fail ("AStmt == nullptr && \"No associated statement allowed for 'omp scan' directive\""
, "clang/lib/Sema/SemaOpenMP.cpp", 6408, __extension__ __PRETTY_FUNCTION__
))
;
6409 Res = ActOnOpenMPScanDirective(ClausesWithImplicit, StartLoc, EndLoc);
6410 break;
6411 case OMPD_ordered:
6412 Res = ActOnOpenMPOrderedDirective(ClausesWithImplicit, AStmt, StartLoc,
6413 EndLoc);
6414 break;
6415 case OMPD_atomic:
6416 Res = ActOnOpenMPAtomicDirective(ClausesWithImplicit, AStmt, StartLoc,
6417 EndLoc);
6418 break;
6419 case OMPD_teams:
6420 Res =
6421 ActOnOpenMPTeamsDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6422 break;
6423 case OMPD_target:
6424 Res = ActOnOpenMPTargetDirective(ClausesWithImplicit, AStmt, StartLoc,
6425 EndLoc);
6426 AllowedNameModifiers.push_back(OMPD_target);
6427 break;
6428 case OMPD_target_parallel:
6429 Res = ActOnOpenMPTargetParallelDirective(ClausesWithImplicit, AStmt,
6430 StartLoc, EndLoc);
6431 AllowedNameModifiers.push_back(OMPD_target);
6432 AllowedNameModifiers.push_back(OMPD_parallel);
6433 break;
6434 case OMPD_target_parallel_for:
6435 Res = ActOnOpenMPTargetParallelForDirective(
6436 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6437 AllowedNameModifiers.push_back(OMPD_target);
6438 AllowedNameModifiers.push_back(OMPD_parallel);
6439 break;
6440 case OMPD_cancellation_point:
6441 assert(ClausesWithImplicit.empty() &&(static_cast <bool> (ClausesWithImplicit.empty() &&
"No clauses are allowed for 'omp cancellation point' directive"
) ? void (0) : __assert_fail ("ClausesWithImplicit.empty() && \"No clauses are allowed for 'omp cancellation point' directive\""
, "clang/lib/Sema/SemaOpenMP.cpp", 6442, __extension__ __PRETTY_FUNCTION__
))
6442 "No clauses are allowed for 'omp cancellation point' directive")(static_cast <bool> (ClausesWithImplicit.empty() &&
"No clauses are allowed for 'omp cancellation point' directive"
) ? void (0) : __assert_fail ("ClausesWithImplicit.empty() && \"No clauses are allowed for 'omp cancellation point' directive\""
, "clang/lib/Sema/SemaOpenMP.cpp", 6442, __extension__ __PRETTY_FUNCTION__
))
;
6443 assert(AStmt == nullptr && "No associated statement allowed for 'omp "(static_cast <bool> (AStmt == nullptr && "No associated statement allowed for 'omp "
"cancellation point' directive") ? void (0) : __assert_fail (
"AStmt == nullptr && \"No associated statement allowed for 'omp \" \"cancellation point' directive\""
, "clang/lib/Sema/SemaOpenMP.cpp", 6444, __extension__ __PRETTY_FUNCTION__
))
6444 "cancellation point' directive")(static_cast <bool> (AStmt == nullptr && "No associated statement allowed for 'omp "
"cancellation point' directive") ? void (0) : __assert_fail (
"AStmt == nullptr && \"No associated statement allowed for 'omp \" \"cancellation point' directive\""
, "clang/lib/Sema/SemaOpenMP.cpp", 6444, __extension__ __PRETTY_FUNCTION__
))
;
6445 Res = ActOnOpenMPCancellationPointDirective(StartLoc, EndLoc, CancelRegion);
6446 break;
6447 case OMPD_cancel:
6448 assert(AStmt == nullptr &&(static_cast <bool> (AStmt == nullptr && "No associated statement allowed for 'omp cancel' directive"
) ? void (0) : __assert_fail ("AStmt == nullptr && \"No associated statement allowed for 'omp cancel' directive\""
, "clang/lib/Sema/SemaOpenMP.cpp", 6449, __extension__ __PRETTY_FUNCTION__
))
6449 "No associated statement allowed for 'omp cancel' directive")(static_cast <bool> (AStmt == nullptr && "No associated statement allowed for 'omp cancel' directive"
) ? void (0) : __assert_fail ("AStmt == nullptr && \"No associated statement allowed for 'omp cancel' directive\""
, "clang/lib/Sema/SemaOpenMP.cpp", 6449, __extension__ __PRETTY_FUNCTION__
))
;
6450 Res = ActOnOpenMPCancelDirective(ClausesWithImplicit, StartLoc, EndLoc,
6451 CancelRegion);
6452 AllowedNameModifiers.push_back(OMPD_cancel);
6453 break;
6454 case OMPD_target_data:
6455 Res = ActOnOpenMPTargetDataDirective(ClausesWithImplicit, AStmt, StartLoc,
6456 EndLoc);
6457 AllowedNameModifiers.push_back(OMPD_target_data);
6458 break;
6459 case OMPD_target_enter_data:
6460 Res = ActOnOpenMPTargetEnterDataDirective(ClausesWithImplicit, StartLoc,
6461 EndLoc, AStmt);
6462 AllowedNameModifiers.push_back(OMPD_target_enter_data);
6463 break;
6464 case OMPD_target_exit_data:
6465 Res = ActOnOpenMPTargetExitDataDirective(ClausesWithImplicit, StartLoc,
6466 EndLoc, AStmt);
6467 AllowedNameModifiers.push_back(OMPD_target_exit_data);
6468 break;
6469 case OMPD_taskloop:
6470 Res = ActOnOpenMPTaskLoopDirective(ClausesWithImplicit, AStmt, StartLoc,
6471 EndLoc, VarsWithInheritedDSA);
6472 AllowedNameModifiers.push_back(OMPD_taskloop);
6473 break;
6474 case OMPD_taskloop_simd:
6475 Res = ActOnOpenMPTaskLoopSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6476 EndLoc, VarsWithInheritedDSA);
6477 AllowedNameModifiers.push_back(OMPD_taskloop);
6478 if (LangOpts.OpenMP >= 50)
6479 AllowedNameModifiers.push_back(OMPD_simd);
6480 break;
6481 case OMPD_master_taskloop:
6482 Res = ActOnOpenMPMasterTaskLoopDirective(
6483 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6484 AllowedNameModifiers.push_back(OMPD_taskloop);
6485 break;
6486 case OMPD_masked_taskloop:
6487 Res = ActOnOpenMPMaskedTaskLoopDirective(
6488 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6489 AllowedNameModifiers.push_back(OMPD_taskloop);
6490 break;
6491 case OMPD_master_taskloop_simd:
6492 Res = ActOnOpenMPMasterTaskLoopSimdDirective(
6493 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6494 AllowedNameModifiers.push_back(OMPD_taskloop);
6495 if (LangOpts.OpenMP >= 50)
6496 AllowedNameModifiers.push_back(OMPD_simd);
6497 break;
6498 case OMPD_masked_taskloop_simd:
6499 Res = ActOnOpenMPMaskedTaskLoopSimdDirective(
6500 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6501 if (LangOpts.OpenMP >= 51) {
6502 AllowedNameModifiers.push_back(OMPD_taskloop);
6503 AllowedNameModifiers.push_back(OMPD_simd);
6504 }
6505 break;
6506 case OMPD_parallel_master_taskloop:
6507 Res = ActOnOpenMPParallelMasterTaskLoopDirective(
6508 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6509 AllowedNameModifiers.push_back(OMPD_taskloop);
6510 AllowedNameModifiers.push_back(OMPD_parallel);
6511 break;
6512 case OMPD_parallel_masked_taskloop:
6513 Res = ActOnOpenMPParallelMaskedTaskLoopDirective(
6514 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6515 if (LangOpts.OpenMP >= 51) {
6516 AllowedNameModifiers.push_back(OMPD_taskloop);
6517 AllowedNameModifiers.push_back(OMPD_parallel);
6518 }
6519 break;
6520 case OMPD_parallel_master_taskloop_simd:
6521 Res = ActOnOpenMPParallelMasterTaskLoopSimdDirective(
6522 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6523 AllowedNameModifiers.push_back(OMPD_taskloop);
6524 AllowedNameModifiers.push_back(OMPD_parallel);
6525 if (LangOpts.OpenMP >= 50)
6526 AllowedNameModifiers.push_back(OMPD_simd);
6527 break;
6528 case OMPD_parallel_masked_taskloop_simd:
6529 Res = ActOnOpenMPParallelMaskedTaskLoopSimdDirective(
6530 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6531 if (LangOpts.OpenMP >= 51) {
6532 AllowedNameModifiers.push_back(OMPD_taskloop);
6533 AllowedNameModifiers.push_back(OMPD_parallel);
6534 AllowedNameModifiers.push_back(OMPD_simd);
6535 }
6536 break;
6537 case OMPD_distribute:
6538 Res = ActOnOpenMPDistributeDirective(ClausesWithImplicit, AStmt, StartLoc,
6539 EndLoc, VarsWithInheritedDSA);
6540 break;
6541 case OMPD_target_update:
6542 Res = ActOnOpenMPTargetUpdateDirective(ClausesWithImplicit, StartLoc,
6543 EndLoc, AStmt);
6544 AllowedNameModifiers.push_back(OMPD_target_update);
6545 break;
6546 case OMPD_distribute_parallel_for:
6547 Res = ActOnOpenMPDistributeParallelForDirective(
6548 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6549 AllowedNameModifiers.push_back(OMPD_parallel);
6550 break;
6551 case OMPD_distribute_parallel_for_simd:
6552 Res = ActOnOpenMPDistributeParallelForSimdDirective(
6553 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6554 AllowedNameModifiers.push_back(OMPD_parallel);
6555 if (LangOpts.OpenMP >= 50)
6556 AllowedNameModifiers.push_back(OMPD_simd);
6557 break;
6558 case OMPD_distribute_simd:
6559 Res = ActOnOpenMPDistributeSimdDirective(
6560 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6561 if (LangOpts.OpenMP >= 50)
6562 AllowedNameModifiers.push_back(OMPD_simd);
6563 break;
6564 case OMPD_target_parallel_for_simd:
6565 Res = ActOnOpenMPTargetParallelForSimdDirective(
6566 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6567 AllowedNameModifiers.push_back(OMPD_target);
6568 AllowedNameModifiers.push_back(OMPD_parallel);
6569 if (LangOpts.OpenMP >= 50)
6570 AllowedNameModifiers.push_back(OMPD_simd);
6571 break;
6572 case OMPD_target_simd:
6573 Res = ActOnOpenMPTargetSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6574 EndLoc, VarsWithInheritedDSA);
6575 AllowedNameModifiers.push_back(OMPD_target);
6576 if (LangOpts.OpenMP >= 50)
6577 AllowedNameModifiers.push_back(OMPD_simd);
6578 break;
6579 case OMPD_teams_distribute:
6580 Res = ActOnOpenMPTeamsDistributeDirective(
6581 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6582 break;
6583 case OMPD_teams_distribute_simd:
6584 Res = ActOnOpenMPTeamsDistributeSimdDirective(
6585 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6586 if (LangOpts.OpenMP >= 50)
6587 AllowedNameModifiers.push_back(OMPD_simd);
6588 break;
6589 case OMPD_teams_distribute_parallel_for_simd:
6590 Res = ActOnOpenMPTeamsDistributeParallelForSimdDirective(
6591 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6592 AllowedNameModifiers.push_back(OMPD_parallel);
6593 if (LangOpts.OpenMP >= 50)
6594 AllowedNameModifiers.push_back(OMPD_simd);
6595 break;
6596 case OMPD_teams_distribute_parallel_for:
6597 Res = ActOnOpenMPTeamsDistributeParallelForDirective(
6598 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6599 AllowedNameModifiers.push_back(OMPD_parallel);
6600 break;
6601 case OMPD_target_teams:
6602 Res = ActOnOpenMPTargetTeamsDirective(ClausesWithImplicit, AStmt, StartLoc,
6603 EndLoc);
6604 AllowedNameModifiers.push_back(OMPD_target);
6605 break;
6606 case OMPD_target_teams_distribute:
6607 Res = ActOnOpenMPTargetTeamsDistributeDirective(
6608 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6609 AllowedNameModifiers.push_back(OMPD_target);
6610 break;
6611 case OMPD_target_teams_distribute_parallel_for:
6612 Res = ActOnOpenMPTargetTeamsDistributeParallelForDirective(
6613 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6614 AllowedNameModifiers.push_back(OMPD_target);
6615 AllowedNameModifiers.push_back(OMPD_parallel);
6616 break;
6617 case OMPD_target_teams_distribute_parallel_for_simd:
6618 Res = ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective(
6619 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6620 AllowedNameModifiers.push_back(OMPD_target);
6621 AllowedNameModifiers.push_back(OMPD_parallel);
6622 if (LangOpts.OpenMP >= 50)
6623 AllowedNameModifiers.push_back(OMPD_simd);
6624 break;
6625 case OMPD_target_teams_distribute_simd:
6626 Res = ActOnOpenMPTargetTeamsDistributeSimdDirective(
6627 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6628 AllowedNameModifiers.push_back(OMPD_target);
6629 if (LangOpts.OpenMP >= 50)
6630 AllowedNameModifiers.push_back(OMPD_simd);
6631 break;
6632 case OMPD_interop:
6633 assert(AStmt == nullptr &&(static_cast <bool> (AStmt == nullptr && "No associated statement allowed for 'omp interop' directive"
) ? void (0) : __assert_fail ("AStmt == nullptr && \"No associated statement allowed for 'omp interop' directive\""
, "clang/lib/Sema/SemaOpenMP.cpp", 6634, __extension__ __PRETTY_FUNCTION__
))
6634 "No associated statement allowed for 'omp interop' directive")(static_cast <bool> (AStmt == nullptr && "No associated statement allowed for 'omp interop' directive"
) ? void (0) : __assert_fail ("AStmt == nullptr && \"No associated statement allowed for 'omp interop' directive\""
, "clang/lib/Sema/SemaOpenMP.cpp", 6634, __extension__ __PRETTY_FUNCTION__
))
;
6635 Res = ActOnOpenMPInteropDirective(ClausesWithImplicit, StartLoc, EndLoc);
6636 break;
6637 case OMPD_dispatch:
6638 Res = ActOnOpenMPDispatchDirective(ClausesWithImplicit, AStmt, StartLoc,
6639 EndLoc);
6640 break;
6641 case OMPD_loop:
6642 Res = ActOnOpenMPGenericLoopDirective(ClausesWithImplicit, AStmt, StartLoc,
6643 EndLoc, VarsWithInheritedDSA);
6644 break;
6645 case OMPD_teams_loop:
6646 Res = ActOnOpenMPTeamsGenericLoopDirective(
6647 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6648 break;
6649 case OMPD_target_teams_loop:
6650 Res = ActOnOpenMPTargetTeamsGenericLoopDirective(
6651 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6652 break;
6653 case OMPD_parallel_loop:
6654 Res = ActOnOpenMPParallelGenericLoopDirective(
6655 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6656 break;
6657 case OMPD_target_parallel_loop:
6658 Res = ActOnOpenMPTargetParallelGenericLoopDirective(
6659 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6660 break;
6661 case OMPD_declare_target:
6662 case OMPD_end_declare_target:
6663 case OMPD_threadprivate:
6664 case OMPD_allocate:
6665 case OMPD_declare_reduction:
6666 case OMPD_declare_mapper:
6667 case OMPD_declare_simd:
6668 case OMPD_requires:
6669 case OMPD_declare_variant:
6670 case OMPD_begin_declare_variant:
6671 case OMPD_end_declare_variant:
6672 llvm_unreachable("OpenMP Directive is not allowed")::llvm::llvm_unreachable_internal("OpenMP Directive is not allowed"
, "clang/lib/Sema/SemaOpenMP.cpp", 6672)
;
6673 case OMPD_unknown:
6674 default:
6675 llvm_unreachable("Unknown OpenMP directive")::llvm::llvm_unreachable_internal("Unknown OpenMP directive",
"clang/lib/Sema/SemaOpenMP.cpp", 6675)
;
6676 }
6677
6678 ErrorFound = Res.isInvalid() || ErrorFound;
6679
6680 // Check variables in the clauses if default(none) or
6681 // default(firstprivate) was specified.
6682 if (DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getDefaultDSA() == DSA_none ||
6683 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getDefaultDSA() == DSA_private ||
6684 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getDefaultDSA() == DSA_firstprivate) {
6685 DSAAttrChecker DSAChecker(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
, *this, nullptr);
6686 for (OMPClause *C : Clauses) {
6687 switch (C->getClauseKind()) {
6688 case OMPC_num_threads:
6689 case OMPC_dist_schedule:
6690 // Do not analyse if no parent teams directive.
6691 if (isOpenMPTeamsDirective(Kind))
6692 break;
6693 continue;
6694 case OMPC_if:
6695 if (isOpenMPTeamsDirective(Kind) &&
6696 cast<OMPIfClause>(C)->getNameModifier() != OMPD_target)
6697 break;
6698 if (isOpenMPParallelDirective(Kind) &&
6699 isOpenMPTaskLoopDirective(Kind) &&
6700 cast<OMPIfClause>(C)->getNameModifier() != OMPD_parallel)
6701 break;
6702 continue;
6703 case OMPC_schedule:
6704 case OMPC_detach:
6705 break;
6706 case OMPC_grainsize:
6707 case OMPC_num_tasks:
6708 case OMPC_final:
6709 case OMPC_priority:
6710 case OMPC_novariants:
6711 case OMPC_nocontext:
6712 // Do not analyze if no parent parallel directive.
6713 if (isOpenMPParallelDirective(Kind))
6714 break;
6715 continue;
6716 case OMPC_ordered:
6717 case OMPC_device:
6718 case OMPC_num_teams:
6719 case OMPC_thread_limit:
6720 case OMPC_hint:
6721 case OMPC_collapse:
6722 case OMPC_safelen:
6723 case OMPC_simdlen:
6724 case OMPC_sizes:
6725 case OMPC_default:
6726 case OMPC_proc_bind:
6727 case OMPC_private:
6728 case OMPC_firstprivate:
6729 case OMPC_lastprivate:
6730 case OMPC_shared:
6731 case OMPC_reduction:
6732 case OMPC_task_reduction:
6733 case OMPC_in_reduction:
6734 case OMPC_linear:
6735 case OMPC_aligned:
6736 case OMPC_copyin:
6737 case OMPC_copyprivate:
6738 case OMPC_nowait:
6739 case OMPC_untied:
6740 case OMPC_mergeable:
6741 case OMPC_allocate:
6742 case OMPC_read:
6743 case OMPC_write:
6744 case OMPC_update:
6745 case OMPC_capture:
6746 case OMPC_compare:
6747 case OMPC_seq_cst:
6748 case OMPC_acq_rel:
6749 case OMPC_acquire:
6750 case OMPC_release:
6751 case OMPC_relaxed:
6752 case OMPC_depend:
6753 case OMPC_threads:
6754 case OMPC_simd:
6755 case OMPC_map:
6756 case OMPC_nogroup:
6757 case OMPC_defaultmap:
6758 case OMPC_to:
6759 case OMPC_from:
6760 case OMPC_use_device_ptr:
6761 case OMPC_use_device_addr:
6762 case OMPC_is_device_ptr:
6763 case OMPC_has_device_addr:
6764 case OMPC_nontemporal:
6765 case OMPC_order:
6766 case OMPC_destroy:
6767 case OMPC_inclusive:
6768 case OMPC_exclusive:
6769 case OMPC_uses_allocators:
6770 case OMPC_affinity:
6771 case OMPC_bind:
6772 case OMPC_filter:
6773 continue;
6774 case OMPC_allocator:
6775 case OMPC_flush:
6776 case OMPC_depobj:
6777 case OMPC_threadprivate:
6778 case OMPC_uniform:
6779 case OMPC_unknown:
6780 case OMPC_unified_address:
6781 case OMPC_unified_shared_memory:
6782 case OMPC_reverse_offload:
6783 case OMPC_dynamic_allocators:
6784 case OMPC_atomic_default_mem_order:
6785 case OMPC_device_type:
6786 case OMPC_match:
6787 case OMPC_when:
6788 case OMPC_at:
6789 case OMPC_severity:
6790 case OMPC_message:
6791 default:
6792 llvm_unreachable("Unexpected clause")::llvm::llvm_unreachable_internal("Unexpected clause", "clang/lib/Sema/SemaOpenMP.cpp"
, 6792)
;
6793 }
6794 for (Stmt *CC : C->children()) {
6795 if (CC)
6796 DSAChecker.Visit(CC);
6797 }
6798 }
6799 for (const auto &P : DSAChecker.getVarsWithInheritedDSA())
6800 VarsWithInheritedDSA[P.getFirst()] = P.getSecond();
6801 }
6802 for (const auto &P : VarsWithInheritedDSA) {
6803 if (P.getFirst()->isImplicit() || isa<OMPCapturedExprDecl>(P.getFirst()))
6804 continue;
6805 ErrorFound = true;
6806 if (DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getDefaultDSA() == DSA_none ||
6807 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getDefaultDSA() == DSA_private ||
6808 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getDefaultDSA() == DSA_firstprivate) {
6809 Diag(P.second->getExprLoc(), diag::err_omp_no_dsa_for_variable)
6810 << P.first << P.second->getSourceRange();
6811 Diag(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getDefaultDSALocation(), diag::note_omp_default_dsa_none);
6812 } else if (getLangOpts().OpenMP >= 50) {
6813 Diag(P.second->getExprLoc(),
6814 diag::err_omp_defaultmap_no_attr_for_variable)
6815 << P.first << P.second->getSourceRange();
6816 Diag(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getDefaultDSALocation(),
6817 diag::note_omp_defaultmap_attr_none);
6818 }
6819 }
6820
6821 if (!AllowedNameModifiers.empty())
6822 ErrorFound = checkIfClauses(*this, Kind, Clauses, AllowedNameModifiers) ||
6823 ErrorFound;
6824
6825 if (ErrorFound)
6826 return StmtError();
6827
6828 if (!CurContext->isDependentContext() &&
6829 isOpenMPTargetExecutionDirective(Kind) &&
6830 !(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
6831 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->hasRequiresDeclWithClause<OMPUnifiedAddressClause>() ||
6832 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->hasRequiresDeclWithClause<OMPReverseOffloadClause>() ||
6833 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())) {
6834 // Register target to DSA Stack.
6835 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->addTargetDirLocation(StartLoc);
6836 }
6837
6838 return Res;
6839}
6840
6841Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareSimdDirective(
6842 DeclGroupPtrTy DG, OMPDeclareSimdDeclAttr::BranchStateTy BS, Expr *Simdlen,
6843 ArrayRef<Expr *> Uniforms, ArrayRef<Expr *> Aligneds,
6844 ArrayRef<Expr *> Alignments, ArrayRef<Expr *> Linears,
6845 ArrayRef<unsigned> LinModifiers, ArrayRef<Expr *> Steps, SourceRange SR) {
6846 assert(Aligneds.size() == Alignments.size())(static_cast <bool> (Aligneds.size() == Alignments.size
()) ? void (0) : __assert_fail ("Aligneds.size() == Alignments.size()"
, "clang/lib/Sema/SemaOpenMP.cpp", 6846, __extension__ __PRETTY_FUNCTION__
))
;
6847 assert(Linears.size() == LinModifiers.size())(static_cast <bool> (Linears.size() == LinModifiers.size
()) ? void (0) : __assert_fail ("Linears.size() == LinModifiers.size()"
, "clang/lib/Sema/SemaOpenMP.cpp", 6847, __extension__ __PRETTY_FUNCTION__
))
;
6848 assert(Linears.size() == Steps.size())(static_cast <bool> (Linears.size() == Steps.size()) ? void
(0) : __assert_fail ("Linears.size() == Steps.size()", "clang/lib/Sema/SemaOpenMP.cpp"
, 6848, __extension__ __PRETTY_FUNCTION__))
;
6849 if (!DG || DG.get().isNull())
6850 return DeclGroupPtrTy();
6851
6852 const int SimdId = 0;
6853 if (!DG.get().isSingleDecl()) {
6854 Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
6855 << SimdId;
6856 return DG;
6857 }
6858 Decl *ADecl = DG.get().getSingleDecl();
6859 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
6860 ADecl = FTD->getTemplatedDecl();
6861
6862 auto *FD = dyn_cast<FunctionDecl>(ADecl);
6863 if (!FD) {
6864 Diag(ADecl->getLocation(), diag::err_omp_function_expected) << SimdId;
6865 return DeclGroupPtrTy();
6866 }
6867
6868 // OpenMP [2.8.2, declare simd construct, Description]
6869 // The parameter of the simdlen clause must be a constant positive integer
6870 // expression.
6871 ExprResult SL;
6872 if (Simdlen)
6873 SL = VerifyPositiveIntegerConstantInClause(Simdlen, OMPC_simdlen);
6874 // OpenMP [2.8.2, declare simd construct, Description]
6875 // The special this pointer can be used as if was one of the arguments to the
6876 // function in any of the linear, aligned, or uniform clauses.
6877 // The uniform clause declares one or more arguments to have an invariant
6878 // value for all concurrent invocations of the function in the execution of a
6879 // single SIMD loop.
6880 llvm::DenseMap<const Decl *, const Expr *> UniformedArgs;
6881 const Expr *UniformedLinearThis = nullptr;
6882 for (const Expr *E : Uniforms) {
6883 E = E->IgnoreParenImpCasts();
6884 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
6885 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl()))
6886 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6887 FD->getParamDecl(PVD->getFunctionScopeIndex())
6888 ->getCanonicalDecl() == PVD->getCanonicalDecl()) {
6889 UniformedArgs.try_emplace(PVD->getCanonicalDecl(), E);
6890 continue;
6891 }
6892 if (isa<CXXThisExpr>(E)) {
6893 UniformedLinearThis = E;
6894 continue;
6895 }
6896 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
6897 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
6898 }
6899 // OpenMP [2.8.2, declare simd construct, Description]
6900 // The aligned clause declares that the object to which each list item points
6901 // is aligned to the number of bytes expressed in the optional parameter of
6902 // the aligned clause.
6903 // The special this pointer can be used as if was one of the arguments to the
6904 // function in any of the linear, aligned, or uniform clauses.
6905 // The type of list items appearing in the aligned clause must be array,
6906 // pointer, reference to array, or reference to pointer.
6907 llvm::DenseMap<const Decl *, const Expr *> AlignedArgs;
6908 const Expr *AlignedThis = nullptr;
6909 for (const Expr *E : Aligneds) {
6910 E = E->IgnoreParenImpCasts();
6911 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
6912 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
6913 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
6914 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6915 FD->getParamDecl(PVD->getFunctionScopeIndex())
6916 ->getCanonicalDecl() == CanonPVD) {
6917 // OpenMP [2.8.1, simd construct, Restrictions]
6918 // A list-item cannot appear in more than one aligned clause.
6919 if (AlignedArgs.count(CanonPVD) > 0) {
6920 Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice)
6921 << 1 << getOpenMPClauseName(OMPC_aligned)
6922 << E->getSourceRange();
6923 Diag(AlignedArgs[CanonPVD]->getExprLoc(),
6924 diag::note_omp_explicit_dsa)
6925 << getOpenMPClauseName(OMPC_aligned);
6926 continue;
6927 }
6928 AlignedArgs[CanonPVD] = E;
6929 QualType QTy = PVD->getType()
6930 .getNonReferenceType()
6931 .getUnqualifiedType()
6932 .getCanonicalType();
6933 const Type *Ty = QTy.getTypePtrOrNull();
6934 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
6935 Diag(E->getExprLoc(), diag::err_omp_aligned_expected_array_or_ptr)
6936 << QTy << getLangOpts().CPlusPlus << E->getSourceRange();
6937 Diag(PVD->getLocation(), diag::note_previous_decl) << PVD;
6938 }
6939 continue;
6940 }
6941 }
6942 if (isa<CXXThisExpr>(E)) {
6943 if (AlignedThis) {
6944 Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice)
6945 << 2 << getOpenMPClauseName(OMPC_aligned) << E->getSourceRange();
6946 Diag(AlignedThis->getExprLoc(), diag::note_omp_explicit_dsa)
6947 << getOpenMPClauseName(OMPC_aligned);
6948 }
6949 AlignedThis = E;
6950 continue;
6951 }
6952 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
6953 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
6954 }
6955 // The optional parameter of the aligned clause, alignment, must be a constant
6956 // positive integer expression. If no optional parameter is specified,
6957 // implementation-defined default alignments for SIMD instructions on the
6958 // target platforms are assumed.
6959 SmallVector<const Expr *, 4> NewAligns;
6960 for (Expr *E : Alignments) {
6961 ExprResult Align;
6962 if (E)
6963 Align = VerifyPositiveIntegerConstantInClause(E, OMPC_aligned);
6964 NewAligns.push_back(Align.get());
6965 }
6966 // OpenMP [2.8.2, declare simd construct, Description]
6967 // The linear clause declares one or more list items to be private to a SIMD
6968 // lane and to have a linear relationship with respect to the iteration space
6969 // of a loop.
6970 // The special this pointer can be used as if was one of the arguments to the
6971 // function in any of the linear, aligned, or uniform clauses.
6972 // When a linear-step expression is specified in a linear clause it must be
6973 // either a constant integer expression or an integer-typed parameter that is
6974 // specified in a uniform clause on the directive.
6975 llvm::DenseMap<const Decl *, const Expr *> LinearArgs;
6976 const bool IsUniformedThis = UniformedLinearThis != nullptr;
6977 auto MI = LinModifiers.begin();
6978 for (const Expr *E : Linears) {
6979 auto LinKind = static_cast<OpenMPLinearClauseKind>(*MI);
6980 ++MI;
6981 E = E->IgnoreParenImpCasts();
6982 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
6983 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
6984 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
6985 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6986 FD->getParamDecl(PVD->getFunctionScopeIndex())
6987 ->getCanonicalDecl() == CanonPVD) {
6988 // OpenMP [2.15.3.7, linear Clause, Restrictions]
6989 // A list-item cannot appear in more than one linear clause.
6990 if (LinearArgs.count(CanonPVD) > 0) {
6991 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
6992 << getOpenMPClauseName(OMPC_linear)
6993 << getOpenMPClauseName(OMPC_linear) << E->getSourceRange();
6994 Diag(LinearArgs[CanonPVD]->getExprLoc(),
6995 diag::note_omp_explicit_dsa)
6996 << getOpenMPClauseName(OMPC_linear);
6997 continue;
6998 }
6999 // Each argument can appear in at most one uniform or linear clause.
7000 if (UniformedArgs.count(CanonPVD) > 0) {
7001 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
7002 << getOpenMPClauseName(OMPC_linear)
7003 << getOpenMPClauseName(OMPC_uniform) << E->getSourceRange();
7004 Diag(UniformedArgs[CanonPVD]->getExprLoc(),
7005 diag::note_omp_explicit_dsa)
7006 << getOpenMPClauseName(OMPC_uniform);
7007 continue;
7008 }
7009 LinearArgs[CanonPVD] = E;
7010 if (E->isValueDependent() || E->isTypeDependent() ||
7011 E->isInstantiationDependent() ||
7012 E->containsUnexpandedParameterPack())
7013 continue;
7014 (void)CheckOpenMPLinearDecl(CanonPVD, E->getExprLoc(), LinKind,
7015 PVD->getOriginalType(),
7016 /*IsDeclareSimd=*/true);
7017 continue;
7018 }
7019 }
7020 if (isa<CXXThisExpr>(E)) {
7021 if (UniformedLinearThis) {
7022 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
7023 << getOpenMPClauseName(OMPC_linear)
7024 << getOpenMPClauseName(IsUniformedThis ? OMPC_uniform : OMPC_linear)
7025 << E->getSourceRange();
7026 Diag(UniformedLinearThis->getExprLoc(), diag::note_omp_explicit_dsa)
7027 << getOpenMPClauseName(IsUniformedThis ? OMPC_uniform
7028 : OMPC_linear);
7029 continue;
7030 }
7031 UniformedLinearThis = E;
7032 if (E->isValueDependent() || E->isTypeDependent() ||
7033 E->isInstantiationDependent() || E->containsUnexpandedParameterPack())
7034 continue;
7035 (void)CheckOpenMPLinearDecl(/*D=*/nullptr, E->getExprLoc(), LinKind,
7036 E->getType(), /*IsDeclareSimd=*/true);
7037 continue;
7038 }
7039 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
7040 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
7041 }
7042 Expr *Step = nullptr;
7043 Expr *NewStep = nullptr;
7044 SmallVector<Expr *, 4> NewSteps;
7045 for (Expr *E : Steps) {
7046 // Skip the same step expression, it was checked already.
7047 if (Step == E || !E) {
7048 NewSteps.push_back(E ? NewStep : nullptr);
7049 continue;
7050 }
7051 Step = E;
7052 if (const auto *DRE = dyn_cast<DeclRefExpr>(Step))
7053 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7054 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7055 if (UniformedArgs.count(CanonPVD) == 0) {
7056 Diag(Step->getExprLoc(), diag::err_omp_expected_uniform_param)
7057 << Step->getSourceRange();
7058 } else if (E->isValueDependent() || E->isTypeDependent() ||
7059 E->isInstantiationDependent() ||
7060 E->containsUnexpandedParameterPack() ||
7061 CanonPVD->getType()->hasIntegerRepresentation()) {
7062 NewSteps.push_back(Step);
7063 } else {
7064 Diag(Step->getExprLoc(), diag::err_omp_expected_int_param)
7065 << Step->getSourceRange();
7066 }
7067 continue;
7068 }
7069 NewStep = Step;
7070 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
7071 !Step->isInstantiationDependent() &&
7072 !Step->containsUnexpandedParameterPack()) {
7073 NewStep = PerformOpenMPImplicitIntegerConversion(Step->getExprLoc(), Step)
7074 .get();
7075 if (NewStep)
7076 NewStep =
7077 VerifyIntegerConstantExpression(NewStep, /*FIXME*/ AllowFold).get();
7078 }
7079 NewSteps.push_back(NewStep);
7080 }
7081 auto *NewAttr = OMPDeclareSimdDeclAttr::CreateImplicit(
7082 Context, BS, SL.get(), const_cast<Expr **>(Uniforms.data()),
7083 Uniforms.size(), const_cast<Expr **>(Aligneds.data()), Aligneds.size(),
7084 const_cast<Expr **>(NewAligns.data()), NewAligns.size(),
7085 const_cast<Expr **>(Linears.data()), Linears.size(),
7086 const_cast<unsigned *>(LinModifiers.data()), LinModifiers.size(),
7087 NewSteps.data(), NewSteps.size(), SR);
7088 ADecl->addAttr(NewAttr);
7089 return DG;
7090}
7091
7092static void setPrototype(Sema &S, FunctionDecl *FD, FunctionDecl *FDWithProto,
7093 QualType NewType) {
7094 assert(NewType->isFunctionProtoType() &&(static_cast <bool> (NewType->isFunctionProtoType() &&
"Expected function type with prototype.") ? void (0) : __assert_fail
("NewType->isFunctionProtoType() && \"Expected function type with prototype.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 7095, __extension__ __PRETTY_FUNCTION__
))
7095 "Expected function type with prototype.")(static_cast <bool> (NewType->isFunctionProtoType() &&
"Expected function type with prototype.") ? void (0) : __assert_fail
("NewType->isFunctionProtoType() && \"Expected function type with prototype.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 7095, __extension__ __PRETTY_FUNCTION__
))
;
7096 assert(FD->getType()->isFunctionNoProtoType() &&(static_cast <bool> (FD->getType()->isFunctionNoProtoType
() && "Expected function with type with no prototype."
) ? void (0) : __assert_fail ("FD->getType()->isFunctionNoProtoType() && \"Expected function with type with no prototype.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 7097, __extension__ __PRETTY_FUNCTION__
))
7097 "Expected function with type with no prototype.")(static_cast <bool> (FD->getType()->isFunctionNoProtoType
() && "Expected function with type with no prototype."
) ? void (0) : __assert_fail ("FD->getType()->isFunctionNoProtoType() && \"Expected function with type with no prototype.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 7097, __extension__ __PRETTY_FUNCTION__
))
;
7098 assert(FDWithProto->getType()->isFunctionProtoType() &&(static_cast <bool> (FDWithProto->getType()->isFunctionProtoType
() && "Expected function with prototype.") ? void (0)
: __assert_fail ("FDWithProto->getType()->isFunctionProtoType() && \"Expected function with prototype.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 7099, __extension__ __PRETTY_FUNCTION__
))
7099 "Expected function with prototype.")(static_cast <bool> (FDWithProto->getType()->isFunctionProtoType
() && "Expected function with prototype.") ? void (0)
: __assert_fail ("FDWithProto->getType()->isFunctionProtoType() && \"Expected function with prototype.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 7099, __extension__ __PRETTY_FUNCTION__
))
;
7100 // Synthesize parameters with the same types.
7101 FD->setType(NewType);
7102 SmallVector<ParmVarDecl *, 16> Params;
7103 for (const ParmVarDecl *P : FDWithProto->parameters()) {
7104 auto *Param = ParmVarDecl::Create(S.getASTContext(), FD, SourceLocation(),
7105 SourceLocation(), nullptr, P->getType(),
7106 /*TInfo=*/nullptr, SC_None, nullptr);
7107 Param->setScopeInfo(0, Params.size());
7108 Param->setImplicit();
7109 Params.push_back(Param);
7110 }
7111
7112 FD->setParams(Params);
7113}
7114
7115void Sema::ActOnFinishedFunctionDefinitionInOpenMPAssumeScope(Decl *D) {
7116 if (D->isInvalidDecl())
7117 return;
7118 FunctionDecl *FD = nullptr;
7119 if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D))
7120 FD = UTemplDecl->getTemplatedDecl();
7121 else
7122 FD = cast<FunctionDecl>(D);
7123 assert(FD && "Expected a function declaration!")(static_cast <bool> (FD && "Expected a function declaration!"
) ? void (0) : __assert_fail ("FD && \"Expected a function declaration!\""
, "clang/lib/Sema/SemaOpenMP.cpp", 7123, __extension__ __PRETTY_FUNCTION__
))
;
7124
7125 // If we are instantiating templates we do *not* apply scoped assumptions but
7126 // only global ones. We apply scoped assumption to the template definition
7127 // though.
7128 if (!inTemplateInstantiation()) {
7129 for (AssumptionAttr *AA : OMPAssumeScoped)
7130 FD->addAttr(AA);
7131 }
7132 for (AssumptionAttr *AA : OMPAssumeGlobal)
7133 FD->addAttr(AA);
7134}
7135
7136Sema::OMPDeclareVariantScope::OMPDeclareVariantScope(OMPTraitInfo &TI)
7137 : TI(&TI), NameSuffix(TI.getMangledName()) {}
7138
7139void Sema::ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope(
7140 Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParamLists,
7141 SmallVectorImpl<FunctionDecl *> &Bases) {
7142 if (!D.getIdentifier())
7143 return;
7144
7145 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7146
7147 // Template specialization is an extension, check if we do it.
7148 bool IsTemplated = !TemplateParamLists.empty();
7149 if (IsTemplated &
7150 !DVScope.TI->isExtensionActive(
7151 llvm::omp::TraitProperty::implementation_extension_allow_templates))
7152 return;
7153
7154 IdentifierInfo *BaseII = D.getIdentifier();
7155 LookupResult Lookup(*this, DeclarationName(BaseII), D.getIdentifierLoc(),
7156 LookupOrdinaryName);
7157 LookupParsedName(Lookup, S, &D.getCXXScopeSpec());
7158
7159 TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
7160 QualType FType = TInfo->getType();
7161
7162 bool IsConstexpr =
7163 D.getDeclSpec().getConstexprSpecifier() == ConstexprSpecKind::Constexpr;
7164 bool IsConsteval =
7165 D.getDeclSpec().getConstexprSpecifier() == ConstexprSpecKind::Consteval;
7166
7167 for (auto *Candidate : Lookup) {
7168 auto *CandidateDecl = Candidate->getUnderlyingDecl();
7169 FunctionDecl *UDecl = nullptr;
7170 if (IsTemplated && isa<FunctionTemplateDecl>(CandidateDecl)) {
7171 auto *FTD = cast<FunctionTemplateDecl>(CandidateDecl);
7172 if (FTD->getTemplateParameters()->size() == TemplateParamLists.size())
7173 UDecl = FTD->getTemplatedDecl();
7174 } else if (!IsTemplated)
7175 UDecl = dyn_cast<FunctionDecl>(CandidateDecl);
7176 if (!UDecl)
7177 continue;
7178
7179 // Don't specialize constexpr/consteval functions with
7180 // non-constexpr/consteval functions.
7181 if (UDecl->isConstexpr() && !IsConstexpr)
7182 continue;
7183 if (UDecl->isConsteval() && !IsConsteval)
7184 continue;
7185
7186 QualType UDeclTy = UDecl->getType();
7187 if (!UDeclTy->isDependentType()) {
7188 QualType NewType = Context.mergeFunctionTypes(
7189 FType, UDeclTy, /* OfBlockPointer */ false,
7190 /* Unqualified */ false, /* AllowCXX */ true);
7191 if (NewType.isNull())
7192 continue;
7193 }
7194
7195 // Found a base!
7196 Bases.push_back(UDecl);
7197 }
7198
7199 bool UseImplicitBase = !DVScope.TI->isExtensionActive(
7200 llvm::omp::TraitProperty::implementation_extension_disable_implicit_base);
7201 // If no base was found we create a declaration that we use as base.
7202 if (Bases.empty() && UseImplicitBase) {
7203 D.setFunctionDefinitionKind(FunctionDefinitionKind::Declaration);
7204 Decl *BaseD = HandleDeclarator(S, D, TemplateParamLists);
7205 BaseD->setImplicit(true);
7206 if (auto *BaseTemplD = dyn_cast<FunctionTemplateDecl>(BaseD))
7207 Bases.push_back(BaseTemplD->getTemplatedDecl());
7208 else
7209 Bases.push_back(cast<FunctionDecl>(BaseD));
7210 }
7211
7212 std::string MangledName;
7213 MangledName += D.getIdentifier()->getName();
7214 MangledName += getOpenMPVariantManglingSeparatorStr();
7215 MangledName += DVScope.NameSuffix;
7216 IdentifierInfo &VariantII = Context.Idents.get(MangledName);
7217
7218 VariantII.setMangledOpenMPVariantName(true);
7219 D.SetIdentifier(&VariantII, D.getBeginLoc());
7220}
7221
7222void Sema::ActOnFinishedFunctionDefinitionInOpenMPDeclareVariantScope(
7223 Decl *D, SmallVectorImpl<FunctionDecl *> &Bases) {
7224 // Do not mark function as is used to prevent its emission if this is the
7225 // only place where it is used.
7226 EnterExpressionEvaluationContext Unevaluated(
7227 *this, Sema::ExpressionEvaluationContext::Unevaluated);
7228
7229 FunctionDecl *FD = nullptr;
7230 if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D))
7231 FD = UTemplDecl->getTemplatedDecl();
7232 else
7233 FD = cast<FunctionDecl>(D);
7234 auto *VariantFuncRef = DeclRefExpr::Create(
7235 Context, NestedNameSpecifierLoc(), SourceLocation(), FD,
7236 /* RefersToEnclosingVariableOrCapture */ false,
7237 /* NameLoc */ FD->getLocation(), FD->getType(),
7238 ExprValueKind::VK_PRValue);
7239
7240 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7241 auto *OMPDeclareVariantA = OMPDeclareVariantAttr::CreateImplicit(
7242 Context, VariantFuncRef, DVScope.TI,
7243 /*NothingArgs=*/nullptr, /*NothingArgsSize=*/0,
7244 /*NeedDevicePtrArgs=*/nullptr, /*NeedDevicePtrArgsSize=*/0,
7245 /*AppendArgs=*/nullptr, /*AppendArgsSize=*/0);
7246 for (FunctionDecl *BaseFD : Bases)
7247 BaseFD->addAttr(OMPDeclareVariantA);
7248}
7249
7250ExprResult Sema::ActOnOpenMPCall(ExprResult Call, Scope *Scope,
7251 SourceLocation LParenLoc,
7252 MultiExprArg ArgExprs,
7253 SourceLocation RParenLoc, Expr *ExecConfig) {
7254 // The common case is a regular call we do not want to specialize at all. Try
7255 // to make that case fast by bailing early.
7256 CallExpr *CE = dyn_cast<CallExpr>(Call.get());
7257 if (!CE)
7258 return Call;
7259
7260 FunctionDecl *CalleeFnDecl = CE->getDirectCallee();
7261 if (!CalleeFnDecl)
7262 return Call;
7263
7264 if (LangOpts.OpenMP >= 51 && CalleeFnDecl->getIdentifier() &&
7265 CalleeFnDecl->getName().startswith_insensitive("omp_")) {
7266 // checking for any calls inside an Order region
7267 if (Scope && Scope->isOpenMPOrderClauseScope())
7268 Diag(LParenLoc, diag::err_omp_unexpected_call_to_omp_runtime_api);
7269 }
7270
7271 if (!CalleeFnDecl->hasAttr<OMPDeclareVariantAttr>())
7272 return Call;
7273
7274 ASTContext &Context = getASTContext();
7275 std::function<void(StringRef)> DiagUnknownTrait = [this,
7276 CE](StringRef ISATrait) {
7277 // TODO Track the selector locations in a way that is accessible here to
7278 // improve the diagnostic location.
7279 Diag(CE->getBeginLoc(), diag::warn_unknown_declare_variant_isa_trait)
7280 << ISATrait;
7281 };
7282 TargetOMPContext OMPCtx(Context, std::move(DiagUnknownTrait),
7283 getCurFunctionDecl(), DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getConstructTraits());
7284
7285 QualType CalleeFnType = CalleeFnDecl->getType();
7286
7287 SmallVector<Expr *, 4> Exprs;
7288 SmallVector<VariantMatchInfo, 4> VMIs;
7289 while (CalleeFnDecl) {
7290 for (OMPDeclareVariantAttr *A :
7291 CalleeFnDecl->specific_attrs<OMPDeclareVariantAttr>()) {
7292 Expr *VariantRef = A->getVariantFuncRef();
7293
7294 VariantMatchInfo VMI;
7295 OMPTraitInfo &TI = A->getTraitInfo();
7296 TI.getAsVariantMatchInfo(Context, VMI);
7297 if (!isVariantApplicableInContext(VMI, OMPCtx,
7298 /* DeviceSetOnly */ false))
7299 continue;
7300
7301 VMIs.push_back(VMI);
7302 Exprs.push_back(VariantRef);
7303 }
7304
7305 CalleeFnDecl = CalleeFnDecl->getPreviousDecl();
7306 }
7307
7308 ExprResult NewCall;
7309 do {
7310 int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx);
7311 if (BestIdx < 0)
7312 return Call;
7313 Expr *BestExpr = cast<DeclRefExpr>(Exprs[BestIdx]);
7314 Decl *BestDecl = cast<DeclRefExpr>(BestExpr)->getDecl();
7315
7316 {
7317 // Try to build a (member) call expression for the current best applicable
7318 // variant expression. We allow this to fail in which case we continue
7319 // with the next best variant expression. The fail case is part of the
7320 // implementation defined behavior in the OpenMP standard when it talks
7321 // about what differences in the function prototypes: "Any differences
7322 // that the specific OpenMP context requires in the prototype of the
7323 // variant from the base function prototype are implementation defined."
7324 // This wording is there to allow the specialized variant to have a
7325 // different type than the base function. This is intended and OK but if
7326 // we cannot create a call the difference is not in the "implementation
7327 // defined range" we allow.
7328 Sema::TentativeAnalysisScope Trap(*this);
7329
7330 if (auto *SpecializedMethod = dyn_cast<CXXMethodDecl>(BestDecl)) {
7331 auto *MemberCall = dyn_cast<CXXMemberCallExpr>(CE);
7332 BestExpr = MemberExpr::CreateImplicit(
7333 Context, MemberCall->getImplicitObjectArgument(),
7334 /* IsArrow */ false, SpecializedMethod, Context.BoundMemberTy,
7335 MemberCall->getValueKind(), MemberCall->getObjectKind());
7336 }
7337 NewCall = BuildCallExpr(Scope, BestExpr, LParenLoc, ArgExprs, RParenLoc,
7338 ExecConfig);
7339 if (NewCall.isUsable()) {
7340 if (CallExpr *NCE = dyn_cast<CallExpr>(NewCall.get())) {
7341 FunctionDecl *NewCalleeFnDecl = NCE->getDirectCallee();
7342 QualType NewType = Context.mergeFunctionTypes(
7343 CalleeFnType, NewCalleeFnDecl->getType(),
7344 /* OfBlockPointer */ false,
7345 /* Unqualified */ false, /* AllowCXX */ true);
7346 if (!NewType.isNull())
7347 break;
7348 // Don't use the call if the function type was not compatible.
7349 NewCall = nullptr;
7350 }
7351 }
7352 }
7353
7354 VMIs.erase(VMIs.begin() + BestIdx);
7355 Exprs.erase(Exprs.begin() + BestIdx);
7356 } while (!VMIs.empty());
7357
7358 if (!NewCall.isUsable())
7359 return Call;
7360 return PseudoObjectExpr::Create(Context, CE, {NewCall.get()}, 0);
7361}
7362
7363std::optional<std::pair<FunctionDecl *, Expr *>>
7364Sema::checkOpenMPDeclareVariantFunction(Sema::DeclGroupPtrTy DG,
7365 Expr *VariantRef, OMPTraitInfo &TI,
7366 unsigned NumAppendArgs,
7367 SourceRange SR) {
7368 if (!DG || DG.get().isNull())
7369 return std::nullopt;
7370
7371 const int VariantId = 1;
7372 // Must be applied only to single decl.
7373 if (!DG.get().isSingleDecl()) {
7374 Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
7375 << VariantId << SR;
7376 return std::nullopt;
7377 }
7378 Decl *ADecl = DG.get().getSingleDecl();
7379 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
7380 ADecl = FTD->getTemplatedDecl();
7381
7382 // Decl must be a function.
7383 auto *FD = dyn_cast<FunctionDecl>(ADecl);
7384 if (!FD) {
7385 Diag(ADecl->getLocation(), diag::err_omp_function_expected)
7386 << VariantId << SR;
7387 return std::nullopt;
7388 }
7389
7390 auto &&HasMultiVersionAttributes = [](const FunctionDecl *FD) {
7391 // The 'target' attribute needs to be separately checked because it does
7392 // not always signify a multiversion function declaration.
7393 return FD->isMultiVersion() || FD->hasAttr<TargetAttr>();
7394 };
7395 // OpenMP is not compatible with multiversion function attributes.
7396 if (HasMultiVersionAttributes(FD)) {
7397 Diag(FD->getLocation(), diag::err_omp_declare_variant_incompat_attributes)
7398 << SR;
7399 return std::nullopt;
7400 }
7401
7402 // Allow #pragma omp declare variant only if the function is not used.
7403 if (FD->isUsed(false))
7404 Diag(SR.getBegin(), diag::warn_omp_declare_variant_after_used)
7405 << FD->getLocation();
7406
7407 // Check if the function was emitted already.
7408 const FunctionDecl *Definition;
7409 if (!FD->isThisDeclarationADefinition() && FD->isDefined(Definition) &&
7410 (LangOpts.EmitAllDecls || Context.DeclMustBeEmitted(Definition)))
7411 Diag(SR.getBegin(), diag::warn_omp_declare_variant_after_emitted)
7412 << FD->getLocation();
7413
7414 // The VariantRef must point to function.
7415 if (!VariantRef) {
7416 Diag(SR.getBegin(), diag::err_omp_function_expected) << VariantId;
7417 return std::nullopt;
7418 }
7419
7420 auto ShouldDelayChecks = [](Expr *&E, bool) {
7421 return E && (E->isTypeDependent() || E->isValueDependent() ||
7422 E->containsUnexpandedParameterPack() ||
7423 E->isInstantiationDependent());
7424 };
7425 // Do not check templates, wait until instantiation.
7426 if (FD->isDependentContext() || ShouldDelayChecks(VariantRef, false) ||
7427 TI.anyScoreOrCondition(ShouldDelayChecks))
7428 return std::make_pair(FD, VariantRef);
7429
7430 // Deal with non-constant score and user condition expressions.
7431 auto HandleNonConstantScoresAndConditions = [this](Expr *&E,
7432 bool IsScore) -> bool {
7433 if (!E || E->isIntegerConstantExpr(Context))
7434 return false;
7435
7436 if (IsScore) {
7437 // We warn on non-constant scores and pretend they were not present.
7438 Diag(E->getExprLoc(), diag::warn_omp_declare_variant_score_not_constant)
7439 << E;
7440 E = nullptr;
7441 } else {
7442 // We could replace a non-constant user condition with "false" but we
7443 // will soon need to handle these anyway for the dynamic version of
7444 // OpenMP context selectors.
7445 Diag(E->getExprLoc(),
7446 diag::err_omp_declare_variant_user_condition_not_constant)
7447 << E;
7448 }
7449 return true;
7450 };
7451 if (TI.anyScoreOrCondition(HandleNonConstantScoresAndConditions))
7452 return std::nullopt;
7453
7454 QualType AdjustedFnType = FD->getType();
7455 if (NumAppendArgs) {
7456 const auto *PTy = AdjustedFnType->getAsAdjusted<FunctionProtoType>();
7457 if (!PTy) {
7458 Diag(FD->getLocation(), diag::err_omp_declare_variant_prototype_required)
7459 << SR;
7460 return std::nullopt;
7461 }
7462 // Adjust the function type to account for an extra omp_interop_t for each
7463 // specified in the append_args clause.
7464 const TypeDecl *TD = nullptr;
7465 LookupResult Result(*this, &Context.Idents.get("omp_interop_t"),
7466 SR.getBegin(), Sema::LookupOrdinaryName);
7467 if (LookupName(Result, getCurScope())) {
7468 NamedDecl *ND = Result.getFoundDecl();
7469 TD = dyn_cast_or_null<TypeDecl>(ND);
7470 }
7471 if (!TD) {
7472 Diag(SR.getBegin(), diag::err_omp_interop_type_not_found) << SR;
7473 return std::nullopt;
7474 }
7475 QualType InteropType = Context.getTypeDeclType(TD);
7476 if (PTy->isVariadic()) {
7477 Diag(FD->getLocation(), diag::err_omp_append_args_with_varargs) << SR;
7478 return std::nullopt;
7479 }
7480 llvm::SmallVector<QualType, 8> Params;
7481 Params.append(PTy->param_type_begin(), PTy->param_type_end());
7482 Params.insert(Params.end(), NumAppendArgs, InteropType);
7483 AdjustedFnType = Context.getFunctionType(PTy->getReturnType(), Params,
7484 PTy->getExtProtoInfo());
7485 }
7486
7487 // Convert VariantRef expression to the type of the original function to
7488 // resolve possible conflicts.
7489 ExprResult VariantRefCast = VariantRef;
7490 if (LangOpts.CPlusPlus) {
7491 QualType FnPtrType;
7492 auto *Method = dyn_cast<CXXMethodDecl>(FD);
7493 if (Method && !Method->isStatic()) {
7494 const Type *ClassType =
7495 Context.getTypeDeclType(Method->getParent()).getTypePtr();
7496 FnPtrType = Context.getMemberPointerType(AdjustedFnType, ClassType);
7497 ExprResult ER;
7498 {
7499 // Build adrr_of unary op to correctly handle type checks for member
7500 // functions.
7501 Sema::TentativeAnalysisScope Trap(*this);
7502 ER = CreateBuiltinUnaryOp(VariantRef->getBeginLoc(), UO_AddrOf,
7503 VariantRef);
7504 }
7505 if (!ER.isUsable()) {
7506 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7507 << VariantId << VariantRef->getSourceRange();
7508 return std::nullopt;
7509 }
7510 VariantRef = ER.get();
7511 } else {
7512 FnPtrType = Context.getPointerType(AdjustedFnType);
7513 }
7514 QualType VarianPtrType = Context.getPointerType(VariantRef->getType());
7515 if (VarianPtrType.getUnqualifiedType() != FnPtrType.getUnqualifiedType()) {
7516 ImplicitConversionSequence ICS = TryImplicitConversion(
7517 VariantRef, FnPtrType.getUnqualifiedType(),
7518 /*SuppressUserConversions=*/false, AllowedExplicit::None,
7519 /*InOverloadResolution=*/false,
7520 /*CStyle=*/false,
7521 /*AllowObjCWritebackConversion=*/false);
7522 if (ICS.isFailure()) {
7523 Diag(VariantRef->getExprLoc(),
7524 diag::err_omp_declare_variant_incompat_types)
7525 << VariantRef->getType()
7526 << ((Method && !Method->isStatic()) ? FnPtrType : FD->getType())
7527 << (NumAppendArgs ? 1 : 0) << VariantRef->getSourceRange();
7528 return std::nullopt;
7529 }
7530 VariantRefCast = PerformImplicitConversion(
7531 VariantRef, FnPtrType.getUnqualifiedType(), AA_Converting);
7532 if (!VariantRefCast.isUsable())
7533 return std::nullopt;
7534 }
7535 // Drop previously built artificial addr_of unary op for member functions.
7536 if (Method && !Method->isStatic()) {
7537 Expr *PossibleAddrOfVariantRef = VariantRefCast.get();
7538 if (auto *UO = dyn_cast<UnaryOperator>(
7539 PossibleAddrOfVariantRef->IgnoreImplicit()))
7540 VariantRefCast = UO->getSubExpr();
7541 }
7542 }
7543
7544 ExprResult ER = CheckPlaceholderExpr(VariantRefCast.get());
7545 if (!ER.isUsable() ||
7546 !ER.get()->IgnoreParenImpCasts()->getType()->isFunctionType()) {
7547 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7548 << VariantId << VariantRef->getSourceRange();
7549 return std::nullopt;
7550 }
7551
7552 // The VariantRef must point to function.
7553 auto *DRE = dyn_cast<DeclRefExpr>(ER.get()->IgnoreParenImpCasts());
7554 if (!DRE) {
7555 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7556 << VariantId << VariantRef->getSourceRange();
7557 return std::nullopt;
7558 }
7559 auto *NewFD = dyn_cast_or_null<FunctionDecl>(DRE->getDecl());
7560 if (!NewFD) {
7561 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7562 << VariantId << VariantRef->getSourceRange();
7563 return std::nullopt;
7564 }
7565
7566 if (FD->getCanonicalDecl() == NewFD->getCanonicalDecl()) {
7567 Diag(VariantRef->getExprLoc(),
7568 diag::err_omp_declare_variant_same_base_function)
7569 << VariantRef->getSourceRange();
7570 return std::nullopt;
7571 }
7572
7573 // Check if function types are compatible in C.
7574 if (!LangOpts.CPlusPlus) {
7575 QualType NewType =
7576 Context.mergeFunctionTypes(AdjustedFnType, NewFD->getType());
7577 if (NewType.isNull()) {
7578 Diag(VariantRef->getExprLoc(),
7579 diag::err_omp_declare_variant_incompat_types)
7580 << NewFD->getType() << FD->getType() << (NumAppendArgs ? 1 : 0)
7581 << VariantRef->getSourceRange();
7582 return std::nullopt;
7583 }
7584 if (NewType->isFunctionProtoType()) {
7585 if (FD->getType()->isFunctionNoProtoType())
7586 setPrototype(*this, FD, NewFD, NewType);
7587 else if (NewFD->getType()->isFunctionNoProtoType())
7588 setPrototype(*this, NewFD, FD, NewType);
7589 }
7590 }
7591
7592 // Check if variant function is not marked with declare variant directive.
7593 if (NewFD->hasAttrs() && NewFD->hasAttr<OMPDeclareVariantAttr>()) {
7594 Diag(VariantRef->getExprLoc(),
7595 diag::warn_omp_declare_variant_marked_as_declare_variant)
7596 << VariantRef->getSourceRange();
7597 SourceRange SR =
7598 NewFD->specific_attr_begin<OMPDeclareVariantAttr>()->getRange();
7599 Diag(SR.getBegin(), diag::note_omp_marked_declare_variant_here) << SR;
7600 return std::nullopt;
7601 }
7602
7603 enum DoesntSupport {
7604 VirtFuncs = 1,
7605 Constructors = 3,
7606 Destructors = 4,
7607 DeletedFuncs = 5,
7608 DefaultedFuncs = 6,
7609 ConstexprFuncs = 7,
7610 ConstevalFuncs = 8,
7611 };
7612 if (const auto *CXXFD = dyn_cast<CXXMethodDecl>(FD)) {
7613 if (CXXFD->isVirtual()) {
7614 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7615 << VirtFuncs;
7616 return std::nullopt;
7617 }
7618
7619 if (isa<CXXConstructorDecl>(FD)) {
7620 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7621 << Constructors;
7622 return std::nullopt;
7623 }
7624
7625 if (isa<CXXDestructorDecl>(FD)) {
7626 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7627 << Destructors;
7628 return std::nullopt;
7629 }
7630 }
7631
7632 if (FD->isDeleted()) {
7633 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7634 << DeletedFuncs;
7635 return std::nullopt;
7636 }
7637
7638 if (FD->isDefaulted()) {
7639 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7640 << DefaultedFuncs;
7641 return std::nullopt;
7642 }
7643
7644 if (FD->isConstexpr()) {
7645 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7646 << (NewFD->isConsteval() ? ConstevalFuncs : ConstexprFuncs);
7647 return std::nullopt;
7648 }
7649
7650 // Check general compatibility.
7651 if (areMultiversionVariantFunctionsCompatible(
7652 FD, NewFD, PartialDiagnostic::NullDiagnostic(),
7653 PartialDiagnosticAt(SourceLocation(),
7654 PartialDiagnostic::NullDiagnostic()),
7655 PartialDiagnosticAt(
7656 VariantRef->getExprLoc(),
7657 PDiag(diag::err_omp_declare_variant_doesnt_support)),
7658 PartialDiagnosticAt(VariantRef->getExprLoc(),
7659 PDiag(diag::err_omp_declare_variant_diff)
7660 << FD->getLocation()),
7661 /*TemplatesSupported=*/true, /*ConstexprSupported=*/false,
7662 /*CLinkageMayDiffer=*/true))
7663 return std::nullopt;
7664 return std::make_pair(FD, cast<Expr>(DRE));
7665}
7666
7667void Sema::ActOnOpenMPDeclareVariantDirective(
7668 FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI,
7669 ArrayRef<Expr *> AdjustArgsNothing,
7670 ArrayRef<Expr *> AdjustArgsNeedDevicePtr,
7671 ArrayRef<OMPInteropInfo> AppendArgs, SourceLocation AdjustArgsLoc,
7672 SourceLocation AppendArgsLoc, SourceRange SR) {
7673
7674 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7675 // An adjust_args clause or append_args clause can only be specified if the
7676 // dispatch selector of the construct selector set appears in the match
7677 // clause.
7678
7679 SmallVector<Expr *, 8> AllAdjustArgs;
7680 llvm::append_range(AllAdjustArgs, AdjustArgsNothing);
7681 llvm::append_range(AllAdjustArgs, AdjustArgsNeedDevicePtr);
7682
7683 if (!AllAdjustArgs.empty() || !AppendArgs.empty()) {
7684 VariantMatchInfo VMI;
7685 TI.getAsVariantMatchInfo(Context, VMI);
7686 if (!llvm::is_contained(
7687 VMI.ConstructTraits,
7688 llvm::omp::TraitProperty::construct_dispatch_dispatch)) {
7689 if (!AllAdjustArgs.empty())
7690 Diag(AdjustArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7691 << getOpenMPClauseName(OMPC_adjust_args);
7692 if (!AppendArgs.empty())
7693 Diag(AppendArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7694 << getOpenMPClauseName(OMPC_append_args);
7695 return;
7696 }
7697 }
7698
7699 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7700 // Each argument can only appear in a single adjust_args clause for each
7701 // declare variant directive.
7702 llvm::SmallPtrSet<const VarDecl *, 4> AdjustVars;
7703
7704 for (Expr *E : AllAdjustArgs) {
7705 E = E->IgnoreParenImpCasts();
7706 if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
7707 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7708 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7709 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7710 FD->getParamDecl(PVD->getFunctionScopeIndex())
7711 ->getCanonicalDecl() == CanonPVD) {
7712 // It's a parameter of the function, check duplicates.
7713 if (!AdjustVars.insert(CanonPVD).second) {
7714 Diag(DRE->getLocation(), diag::err_omp_adjust_arg_multiple_clauses)
7715 << PVD;
7716 return;
7717 }
7718 continue;
7719 }
7720 }
7721 }
7722 // Anything that is not a function parameter is an error.
7723 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause) << FD << 0;
7724 return;
7725 }
7726
7727 auto *NewAttr = OMPDeclareVariantAttr::CreateImplicit(
7728 Context, VariantRef, &TI, const_cast<Expr **>(AdjustArgsNothing.data()),
7729 AdjustArgsNothing.size(),
7730 const_cast<Expr **>(AdjustArgsNeedDevicePtr.data()),
7731 AdjustArgsNeedDevicePtr.size(),
7732 const_cast<OMPInteropInfo *>(AppendArgs.data()), AppendArgs.size(), SR);
7733 FD->addAttr(NewAttr);
7734}
7735
7736StmtResult Sema::ActOnOpenMPParallelDirective(ArrayRef<OMPClause *> Clauses,
7737 Stmt *AStmt,
7738 SourceLocation StartLoc,
7739 SourceLocation EndLoc) {
7740 if (!AStmt)
7741 return StmtError();
7742
7743 auto *CS = cast<CapturedStmt>(AStmt);
7744 // 1.2.2 OpenMP Language Terminology
7745 // Structured block - An executable statement with a single entry at the
7746 // top and a single exit at the bottom.
7747 // The point of exit cannot be a branch out of the structured block.
7748 // longjmp() and throw() must not violate the entry/exit criteria.
7749 CS->getCapturedDecl()->setNothrow();
7750
7751 setFunctionHasBranchProtectedScope();
7752
7753 return OMPParallelDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
7754 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getTaskgroupReductionRef(),
7755 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isCancelRegion());
7756}
7757
7758namespace {
7759/// Iteration space of a single for loop.
7760struct LoopIterationSpace final {
7761 /// True if the condition operator is the strict compare operator (<, > or
7762 /// !=).
7763 bool IsStrictCompare = false;
7764 /// Condition of the loop.
7765 Expr *PreCond = nullptr;
7766 /// This expression calculates the number of iterations in the loop.
7767 /// It is always possible to calculate it before starting the loop.
7768 Expr *NumIterations = nullptr;
7769 /// The loop counter variable.
7770 Expr *CounterVar = nullptr;
7771 /// Private loop counter variable.
7772 Expr *PrivateCounterVar = nullptr;
7773 /// This is initializer for the initial value of #CounterVar.
7774 Expr *CounterInit = nullptr;
7775 /// This is step for the #CounterVar used to generate its update:
7776 /// #CounterVar = #CounterInit + #CounterStep * CurrentIteration.
7777 Expr *CounterStep = nullptr;
7778 /// Should step be subtracted?
7779 bool Subtract = false;
7780 /// Source range of the loop init.
7781 SourceRange InitSrcRange;
7782 /// Source range of the loop condition.
7783 SourceRange CondSrcRange;
7784 /// Source range of the loop increment.
7785 SourceRange IncSrcRange;
7786 /// Minimum value that can have the loop control variable. Used to support
7787 /// non-rectangular loops. Applied only for LCV with the non-iterator types,
7788 /// since only such variables can be used in non-loop invariant expressions.
7789 Expr *MinValue = nullptr;
7790 /// Maximum value that can have the loop control variable. Used to support
7791 /// non-rectangular loops. Applied only for LCV with the non-iterator type,
7792 /// since only such variables can be used in non-loop invariant expressions.
7793 Expr *MaxValue = nullptr;
7794 /// true, if the lower bound depends on the outer loop control var.
7795 bool IsNonRectangularLB = false;
7796 /// true, if the upper bound depends on the outer loop control var.
7797 bool IsNonRectangularUB = false;
7798 /// Index of the loop this loop depends on and forms non-rectangular loop
7799 /// nest.
7800 unsigned LoopDependentIdx = 0;
7801 /// Final condition for the non-rectangular loop nest support. It is used to
7802 /// check that the number of iterations for this particular counter must be
7803 /// finished.
7804 Expr *FinalCondition = nullptr;
7805};
7806
7807/// Helper class for checking canonical form of the OpenMP loops and
7808/// extracting iteration space of each loop in the loop nest, that will be used
7809/// for IR generation.
7810class OpenMPIterationSpaceChecker {
7811 /// Reference to Sema.
7812 Sema &SemaRef;
7813 /// Does the loop associated directive support non-rectangular loops?
7814 bool SupportsNonRectangular;
7815 /// Data-sharing stack.
7816 DSAStackTy &Stack;
7817 /// A location for diagnostics (when there is no some better location).
7818 SourceLocation DefaultLoc;
7819 /// A location for diagnostics (when increment is not compatible).
7820 SourceLocation ConditionLoc;
7821 /// A source location for referring to loop init later.
7822 SourceRange InitSrcRange;
7823 /// A source location for referring to condition later.
7824 SourceRange ConditionSrcRange;
7825 /// A source location for referring to increment later.
7826 SourceRange IncrementSrcRange;
7827 /// Loop variable.
7828 ValueDecl *LCDecl = nullptr;
7829 /// Reference to loop variable.
7830 Expr *LCRef = nullptr;
7831 /// Lower bound (initializer for the var).
7832 Expr *LB = nullptr;
7833 /// Upper bound.
7834 Expr *UB = nullptr;
7835 /// Loop step (increment).
7836 Expr *Step = nullptr;
7837 /// This flag is true when condition is one of:
7838 /// Var < UB
7839 /// Var <= UB
7840 /// UB > Var
7841 /// UB >= Var
7842 /// This will have no value when the condition is !=
7843 std::optional<bool> TestIsLessOp;
7844 /// This flag is true when condition is strict ( < or > ).
7845 bool TestIsStrictOp = false;
7846 /// This flag is true when step is subtracted on each iteration.
7847 bool SubtractStep = false;
7848 /// The outer loop counter this loop depends on (if any).
7849 const ValueDecl *DepDecl = nullptr;
7850 /// Contains number of loop (starts from 1) on which loop counter init
7851 /// expression of this loop depends on.
7852 std::optional<unsigned> InitDependOnLC;
7853 /// Contains number of loop (starts from 1) on which loop counter condition
7854 /// expression of this loop depends on.
7855 std::optional<unsigned> CondDependOnLC;
7856 /// Checks if the provide statement depends on the loop counter.
7857 std::optional<unsigned> doesDependOnLoopCounter(const Stmt *S,
7858 bool IsInitializer);
7859 /// Original condition required for checking of the exit condition for
7860 /// non-rectangular loop.
7861 Expr *Condition = nullptr;
7862
7863public:
7864 OpenMPIterationSpaceChecker(Sema &SemaRef, bool SupportsNonRectangular,
7865 DSAStackTy &Stack, SourceLocation DefaultLoc)
7866 : SemaRef(SemaRef), SupportsNonRectangular(SupportsNonRectangular),
7867 Stack(Stack), DefaultLoc(DefaultLoc), ConditionLoc(DefaultLoc) {}
7868 /// Check init-expr for canonical loop form and save loop counter
7869 /// variable - #Var and its initialization value - #LB.
7870 bool checkAndSetInit(Stmt *S, bool EmitDiags = true);
7871 /// Check test-expr for canonical form, save upper-bound (#UB), flags
7872 /// for less/greater and for strict/non-strict comparison.
7873 bool checkAndSetCond(Expr *S);
7874 /// Check incr-expr for canonical loop form and return true if it
7875 /// does not conform, otherwise save loop step (#Step).
7876 bool checkAndSetInc(Expr *S);
7877 /// Return the loop counter variable.
7878 ValueDecl *getLoopDecl() const { return LCDecl; }
7879 /// Return the reference expression to loop counter variable.
7880 Expr *getLoopDeclRefExpr() const { return LCRef; }
7881 /// Source range of the loop init.
7882 SourceRange getInitSrcRange() const { return InitSrcRange; }
7883 /// Source range of the loop condition.
7884 SourceRange getConditionSrcRange() const { return ConditionSrcRange; }
7885 /// Source range of the loop increment.
7886 SourceRange getIncrementSrcRange() const { return IncrementSrcRange; }
7887 /// True if the step should be subtracted.
7888 bool shouldSubtractStep() const { return SubtractStep; }
7889 /// True, if the compare operator is strict (<, > or !=).
7890 bool isStrictTestOp() const { return TestIsStrictOp; }
7891 /// Build the expression to calculate the number of iterations.
7892 Expr *buildNumIterations(
7893 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
7894 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
7895 /// Build the precondition expression for the loops.
7896 Expr *
7897 buildPreCond(Scope *S, Expr *Cond,
7898 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
7899 /// Build reference expression to the counter be used for codegen.
7900 DeclRefExpr *
7901 buildCounterVar(llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
7902 DSAStackTy &DSA) const;
7903 /// Build reference expression to the private counter be used for
7904 /// codegen.
7905 Expr *buildPrivateCounterVar() const;
7906 /// Build initialization of the counter be used for codegen.
7907 Expr *buildCounterInit() const;
7908 /// Build step of the counter be used for codegen.
7909 Expr *buildCounterStep() const;
7910 /// Build loop data with counter value for depend clauses in ordered
7911 /// directives.
7912 Expr *
7913 buildOrderedLoopData(Scope *S, Expr *Counter,
7914 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
7915 SourceLocation Loc, Expr *Inc = nullptr,
7916 OverloadedOperatorKind OOK = OO_Amp);
7917 /// Builds the minimum value for the loop counter.
7918 std::pair<Expr *, Expr *> buildMinMaxValues(
7919 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
7920 /// Builds final condition for the non-rectangular loops.
7921 Expr *buildFinalCondition(Scope *S) const;
7922 /// Return true if any expression is dependent.
7923 bool dependent() const;
7924 /// Returns true if the initializer forms non-rectangular loop.
7925 bool doesInitDependOnLC() const { return InitDependOnLC.has_value(); }
7926 /// Returns true if the condition forms non-rectangular loop.
7927 bool doesCondDependOnLC() const { return CondDependOnLC.has_value(); }
7928 /// Returns index of the loop we depend on (starting from 1), or 0 otherwise.
7929 unsigned getLoopDependentIdx() const {
7930 return InitDependOnLC.value_or(CondDependOnLC.value_or(0));
7931 }
7932
7933private:
7934 /// Check the right-hand side of an assignment in the increment
7935 /// expression.
7936 bool checkAndSetIncRHS(Expr *RHS);
7937 /// Helper to set loop counter variable and its initializer.
7938 bool setLCDeclAndLB(ValueDecl *NewLCDecl, Expr *NewDeclRefExpr, Expr *NewLB,
7939 bool EmitDiags);
7940 /// Helper to set upper bound.
7941 bool setUB(Expr *NewUB, std::optional<bool> LessOp, bool StrictOp,
7942 SourceRange SR, SourceLocation SL);
7943 /// Helper to set loop increment.
7944 bool setStep(Expr *NewStep, bool Subtract);
7945};
7946
7947bool OpenMPIterationSpaceChecker::dependent() const {
7948 if (!LCDecl) {
7949 assert(!LB && !UB && !Step)(static_cast <bool> (!LB && !UB && !Step
) ? void (0) : __assert_fail ("!LB && !UB && !Step"
, "clang/lib/Sema/SemaOpenMP.cpp", 7949, __extension__ __PRETTY_FUNCTION__
))
;
7950 return false;
7951 }
7952 return LCDecl->getType()->isDependentType() ||
7953 (LB && LB->isValueDependent()) || (UB && UB->isValueDependent()) ||
7954 (Step && Step->isValueDependent());
7955}
7956
7957bool OpenMPIterationSpaceChecker::setLCDeclAndLB(ValueDecl *NewLCDecl,
7958 Expr *NewLCRefExpr,
7959 Expr *NewLB, bool EmitDiags) {
7960 // State consistency checking to ensure correct usage.
7961 assert(LCDecl == nullptr && LB == nullptr && LCRef == nullptr &&(static_cast <bool> (LCDecl == nullptr && LB ==
nullptr && LCRef == nullptr && UB == nullptr
&& Step == nullptr && !TestIsLessOp &&
!TestIsStrictOp) ? void (0) : __assert_fail ("LCDecl == nullptr && LB == nullptr && LCRef == nullptr && UB == nullptr && Step == nullptr && !TestIsLessOp && !TestIsStrictOp"
, "clang/lib/Sema/SemaOpenMP.cpp", 7962, __extension__ __PRETTY_FUNCTION__
))
7962 UB == nullptr && Step == nullptr && !TestIsLessOp && !TestIsStrictOp)(static_cast <bool> (LCDecl == nullptr && LB ==
nullptr && LCRef == nullptr && UB == nullptr
&& Step == nullptr && !TestIsLessOp &&
!TestIsStrictOp) ? void (0) : __assert_fail ("LCDecl == nullptr && LB == nullptr && LCRef == nullptr && UB == nullptr && Step == nullptr && !TestIsLessOp && !TestIsStrictOp"
, "clang/lib/Sema/SemaOpenMP.cpp", 7962, __extension__ __PRETTY_FUNCTION__
))
;
7963 if (!NewLCDecl || !NewLB || NewLB->containsErrors())
7964 return true;
7965 LCDecl = getCanonicalDecl(NewLCDecl);
7966 LCRef = NewLCRefExpr;
7967 if (auto *CE = dyn_cast_or_null<CXXConstructExpr>(NewLB))
7968 if (const CXXConstructorDecl *Ctor = CE->getConstructor())
7969 if ((Ctor->isCopyOrMoveConstructor() ||
7970 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
7971 CE->getNumArgs() > 0 && CE->getArg(0) != nullptr)
7972 NewLB = CE->getArg(0)->IgnoreParenImpCasts();
7973 LB = NewLB;
7974 if (EmitDiags)
7975 InitDependOnLC = doesDependOnLoopCounter(LB, /*IsInitializer=*/true);
7976 return false;
7977}
7978
7979bool OpenMPIterationSpaceChecker::setUB(Expr *NewUB, std::optional<bool> LessOp,
7980 bool StrictOp, SourceRange SR,
7981 SourceLocation SL) {
7982 // State consistency checking to ensure correct usage.
7983 assert(LCDecl != nullptr && LB != nullptr && UB == nullptr &&(static_cast <bool> (LCDecl != nullptr && LB !=
nullptr && UB == nullptr && Step == nullptr &&
!TestIsLessOp && !TestIsStrictOp) ? void (0) : __assert_fail
("LCDecl != nullptr && LB != nullptr && UB == nullptr && Step == nullptr && !TestIsLessOp && !TestIsStrictOp"
, "clang/lib/Sema/SemaOpenMP.cpp", 7984, __extension__ __PRETTY_FUNCTION__
))
7984 Step == nullptr && !TestIsLessOp && !TestIsStrictOp)(static_cast <bool> (LCDecl != nullptr && LB !=
nullptr && UB == nullptr && Step == nullptr &&
!TestIsLessOp && !TestIsStrictOp) ? void (0) : __assert_fail
("LCDecl != nullptr && LB != nullptr && UB == nullptr && Step == nullptr && !TestIsLessOp && !TestIsStrictOp"
, "clang/lib/Sema/SemaOpenMP.cpp", 7984, __extension__ __PRETTY_FUNCTION__
))
;
7985 if (!NewUB || NewUB->containsErrors())
7986 return true;
7987 UB = NewUB;
7988 if (LessOp)
7989 TestIsLessOp = LessOp;
7990 TestIsStrictOp = StrictOp;
7991 ConditionSrcRange = SR;
7992 ConditionLoc = SL;
7993 CondDependOnLC = doesDependOnLoopCounter(UB, /*IsInitializer=*/false);
7994 return false;
7995}
7996
7997bool OpenMPIterationSpaceChecker::setStep(Expr *NewStep, bool Subtract) {
7998 // State consistency checking to ensure correct usage.
7999 assert(LCDecl != nullptr && LB != nullptr && Step == nullptr)(static_cast <bool> (LCDecl != nullptr && LB !=
nullptr && Step == nullptr) ? void (0) : __assert_fail
("LCDecl != nullptr && LB != nullptr && Step == nullptr"
, "clang/lib/Sema/SemaOpenMP.cpp", 7999, __extension__ __PRETTY_FUNCTION__
))
;
8000 if (!NewStep || NewStep->containsErrors())
8001 return true;
8002 if (!NewStep->isValueDependent()) {
8003 // Check that the step is integer expression.
8004 SourceLocation StepLoc = NewStep->getBeginLoc();
8005 ExprResult Val = SemaRef.PerformOpenMPImplicitIntegerConversion(
8006 StepLoc, getExprAsWritten(NewStep));
8007 if (Val.isInvalid())
8008 return true;
8009 NewStep = Val.get();
8010
8011 // OpenMP [2.6, Canonical Loop Form, Restrictions]
8012 // If test-expr is of form var relational-op b and relational-op is < or
8013 // <= then incr-expr must cause var to increase on each iteration of the
8014 // loop. If test-expr is of form var relational-op b and relational-op is
8015 // > or >= then incr-expr must cause var to decrease on each iteration of
8016 // the loop.
8017 // If test-expr is of form b relational-op var and relational-op is < or
8018 // <= then incr-expr must cause var to decrease on each iteration of the
8019 // loop. If test-expr is of form b relational-op var and relational-op is
8020 // > or >= then incr-expr must cause var to increase on each iteration of
8021 // the loop.
8022 std::optional<llvm::APSInt> Result =
8023 NewStep->getIntegerConstantExpr(SemaRef.Context);
8024 bool IsUnsigned = !NewStep->getType()->hasSignedIntegerRepresentation();
8025 bool IsConstNeg =
8026 Result && Result->isSigned() && (Subtract != Result->isNegative());
8027 bool IsConstPos =
8028 Result && Result->isSigned() && (Subtract == Result->isNegative());
8029 bool IsConstZero = Result && !Result->getBoolValue();
8030
8031 // != with increment is treated as <; != with decrement is treated as >
8032 if (!TestIsLessOp)
8033 TestIsLessOp = IsConstPos || (IsUnsigned && !Subtract);
8034 if (UB && (IsConstZero ||
8035 (*TestIsLessOp ? (IsConstNeg || (IsUnsigned && Subtract))
8036 : (IsConstPos || (IsUnsigned && !Subtract))))) {
8037 SemaRef.Diag(NewStep->getExprLoc(),
8038 diag::err_omp_loop_incr_not_compatible)
8039 << LCDecl << *TestIsLessOp << NewStep->getSourceRange();
8040 SemaRef.Diag(ConditionLoc,
8041 diag::note_omp_loop_cond_requres_compatible_incr)
8042 << *TestIsLessOp << ConditionSrcRange;
8043 return true;
8044 }
8045 if (*TestIsLessOp == Subtract) {
8046 NewStep =
8047 SemaRef.CreateBuiltinUnaryOp(NewStep->getExprLoc(), UO_Minus, NewStep)
8048 .get();
8049 Subtract = !Subtract;
8050 }
8051 }
8052
8053 Step = NewStep;
8054 SubtractStep = Subtract;
8055 return false;
8056}
8057
8058namespace {
8059/// Checker for the non-rectangular loops. Checks if the initializer or
8060/// condition expression references loop counter variable.
8061class LoopCounterRefChecker final
8062 : public ConstStmtVisitor<LoopCounterRefChecker, bool> {
8063 Sema &SemaRef;
8064 DSAStackTy &Stack;
8065 const ValueDecl *CurLCDecl = nullptr;
8066 const ValueDecl *DepDecl = nullptr;
8067 const ValueDecl *PrevDepDecl = nullptr;
8068 bool IsInitializer = true;
8069 bool SupportsNonRectangular;
8070 unsigned BaseLoopId = 0;
8071 bool checkDecl(const Expr *E, const ValueDecl *VD) {
8072 if (getCanonicalDecl(VD) == getCanonicalDecl(CurLCDecl)) {
8073 SemaRef.Diag(E->getExprLoc(), diag::err_omp_stmt_depends_on_loop_counter)
8074 << (IsInitializer ? 0 : 1);
8075 return false;
8076 }
8077 const auto &&Data = Stack.isLoopControlVariable(VD);
8078 // OpenMP, 2.9.1 Canonical Loop Form, Restrictions.
8079 // The type of the loop iterator on which we depend may not have a random
8080 // access iterator type.
8081 if (Data.first && VD->getType()->isRecordType()) {
8082 SmallString<128> Name;
8083 llvm::raw_svector_ostream OS(Name);
8084 VD->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(),
8085 /*Qualified=*/true);
8086 SemaRef.Diag(E->getExprLoc(),
8087 diag::err_omp_wrong_dependency_iterator_type)
8088 << OS.str();
8089 SemaRef.Diag(VD->getLocation(), diag::note_previous_decl) << VD;
8090 return false;
8091 }
8092 if (Data.first && !SupportsNonRectangular) {
8093 SemaRef.Diag(E->getExprLoc(), diag::err_omp_invariant_dependency);
8094 return false;
8095 }
8096 if (Data.first &&
8097 (DepDecl || (PrevDepDecl &&
8098 getCanonicalDecl(VD) != getCanonicalDecl(PrevDepDecl)))) {
8099 if (!DepDecl && PrevDepDecl)
8100 DepDecl = PrevDepDecl;
8101 SmallString<128> Name;
8102 llvm::raw_svector_ostream OS(Name);
8103 DepDecl->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(),
8104 /*Qualified=*/true);
8105 SemaRef.Diag(E->getExprLoc(),
8106 diag::err_omp_invariant_or_linear_dependency)
8107 << OS.str();
8108 return false;
8109 }
8110 if (Data.first) {
8111 DepDecl = VD;
8112 BaseLoopId = Data.first;
8113 }
8114 return Data.first;
8115 }
8116
8117public:
8118 bool VisitDeclRefExpr(const DeclRefExpr *E) {
8119 const ValueDecl *VD = E->getDecl();
8120 if (isa<VarDecl>(VD))
8121 return checkDecl(E, VD);
8122 return false;
8123 }
8124 bool VisitMemberExpr(const MemberExpr *E) {
8125 if (isa<CXXThisExpr>(E->getBase()->IgnoreParens())) {
8126 const ValueDecl *VD = E->getMemberDecl();
8127 if (isa<VarDecl>(VD) || isa<FieldDecl>(VD))
8128 return checkDecl(E, VD);
8129 }
8130 return false;
8131 }
8132 bool VisitStmt(const Stmt *S) {
8133 bool Res = false;
8134 for (const Stmt *Child : S->children())
8135 Res = (Child && Visit(Child)) || Res;
8136 return Res;
8137 }
8138 explicit LoopCounterRefChecker(Sema &SemaRef, DSAStackTy &Stack,
8139 const ValueDecl *CurLCDecl, bool IsInitializer,
8140 const ValueDecl *PrevDepDecl = nullptr,
8141 bool SupportsNonRectangular = true)
8142 : SemaRef(SemaRef), Stack(Stack), CurLCDecl(CurLCDecl),
8143 PrevDepDecl(PrevDepDecl), IsInitializer(IsInitializer),
8144 SupportsNonRectangular(SupportsNonRectangular) {}
8145 unsigned getBaseLoopId() const {
8146 assert(CurLCDecl && "Expected loop dependency.")(static_cast <bool> (CurLCDecl && "Expected loop dependency."
) ? void (0) : __assert_fail ("CurLCDecl && \"Expected loop dependency.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 8146, __extension__ __PRETTY_FUNCTION__
))
;
8147 return BaseLoopId;
8148 }
8149 const ValueDecl *getDepDecl() const {
8150 assert(CurLCDecl && "Expected loop dependency.")(static_cast <bool> (CurLCDecl && "Expected loop dependency."
) ? void (0) : __assert_fail ("CurLCDecl && \"Expected loop dependency.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 8150, __extension__ __PRETTY_FUNCTION__
))
;
8151 return DepDecl;
8152 }
8153};
8154} // namespace
8155
8156std::optional<unsigned>
8157OpenMPIterationSpaceChecker::doesDependOnLoopCounter(const Stmt *S,
8158 bool IsInitializer) {
8159 // Check for the non-rectangular loops.
8160 LoopCounterRefChecker LoopStmtChecker(SemaRef, Stack, LCDecl, IsInitializer,
8161 DepDecl, SupportsNonRectangular);
8162 if (LoopStmtChecker.Visit(S)) {
8163 DepDecl = LoopStmtChecker.getDepDecl();
8164 return LoopStmtChecker.getBaseLoopId();
8165 }
8166 return std::nullopt;
8167}
8168
8169bool OpenMPIterationSpaceChecker::checkAndSetInit(Stmt *S, bool EmitDiags) {
8170 // Check init-expr for canonical loop form and save loop counter
8171 // variable - #Var and its initialization value - #LB.
8172 // OpenMP [2.6] Canonical loop form. init-expr may be one of the following:
8173 // var = lb
8174 // integer-type var = lb
8175 // random-access-iterator-type var = lb
8176 // pointer-type var = lb
8177 //
8178 if (!S
8.1
'S' is non-null
) {
9
Taking false branch
8179 if (EmitDiags) {
8180 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_init);
8181 }
8182 return true;
8183 }
8184 if (auto *ExprTemp
10.1
'ExprTemp' is null
= dyn_cast<ExprWithCleanups>(S))
10
Assuming 'S' is not a 'CastReturnType'
11
Taking false branch
8185 if (!ExprTemp->cleanupsHaveSideEffects())
8186 S = ExprTemp->getSubExpr();
8187
8188 InitSrcRange = S->getSourceRange();
8189 if (Expr *E
12.1
'E' is null
= dyn_cast<Expr>(S))
12
Assuming 'S' is not a 'CastReturnType'
13
Taking false branch
8190 S = E->IgnoreParens();
8191 if (auto *BO
15.1
'BO' is null
= dyn_cast<BinaryOperator>(S)) {
14
Assuming 'S' is not a 'CastReturnType'
15
'BO' initialized to a null pointer value
16
Taking false branch
8192 if (BO->getOpcode() == BO_Assign) {
8193 Expr *LHS = BO->getLHS()->IgnoreParens();
8194 if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8195 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
8196 if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
8197 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8198 EmitDiags);
8199 return setLCDeclAndLB(DRE->getDecl(), DRE, BO->getRHS(), EmitDiags);
8200 }
8201 if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
8202 if (ME->isArrow() &&
8203 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8204 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8205 EmitDiags);
8206 }
8207 }
8208 } else if (auto *DS
17.1
'DS' is null
= dyn_cast<DeclStmt>(S)) {
17
Assuming 'S' is not a 'CastReturnType'
18
Taking false branch
8209 if (DS->isSingleDecl()) {
8210 if (auto *Var = dyn_cast_or_null<VarDecl>(DS->getSingleDecl())) {
8211 if (Var->hasInit() && !Var->getType()->isReferenceType()) {
8212 // Accept non-canonical init form here but emit ext. warning.
8213 if (Var->getInitStyle() != VarDecl::CInit && EmitDiags)
8214 SemaRef.Diag(S->getBeginLoc(),
8215 diag::ext_omp_loop_not_canonical_init)
8216 << S->getSourceRange();
8217 return setLCDeclAndLB(
8218 Var,
8219 buildDeclRefExpr(SemaRef, Var,
8220 Var->getType().getNonReferenceType(),
8221 DS->getBeginLoc()),
8222 Var->getInit(), EmitDiags);
8223 }
8224 }
8225 }
8226 } else if (auto *CE
19.1
'CE' is non-null
= dyn_cast<CXXOperatorCallExpr>(S)) {
19
Assuming 'S' is a 'CastReturnType'
20
Taking true branch
8227 if (CE->getOperator() == OO_Equal) {
21
Assuming the condition is true
22
Taking true branch
8228 Expr *LHS = CE->getArg(0);
8229 if (auto *DRE
23.1
'DRE' is null
= dyn_cast<DeclRefExpr>(LHS)) {
23
Assuming 'LHS' is not a 'CastReturnType'
24
Taking false branch
8230 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
8231 if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
8232 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8233 EmitDiags);
8234 return setLCDeclAndLB(DRE->getDecl(), DRE, CE->getArg(1), EmitDiags);
8235 }
8236 if (auto *ME
25.1
'ME' is non-null
= dyn_cast<MemberExpr>(LHS)) {
25
Assuming 'LHS' is a 'CastReturnType'
8237 if (ME->isArrow() &&
26
Assuming the condition is true
28
Taking true branch
8238 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
27
Assuming the object is a 'class clang::CXXThisExpr &'
8239 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
29
Called C++ object pointer is null
8240 EmitDiags);
8241 }
8242 }
8243 }
8244
8245 if (dependent() || SemaRef.CurContext->isDependentContext())
8246 return false;
8247 if (EmitDiags) {
8248 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_init)
8249 << S->getSourceRange();
8250 }
8251 return true;
8252}
8253
8254/// Ignore parenthesizes, implicit casts, copy constructor and return the
8255/// variable (which may be the loop variable) if possible.
8256static const ValueDecl *getInitLCDecl(const Expr *E) {
8257 if (!E)
8258 return nullptr;
8259 E = getExprAsWritten(E);
8260 if (const auto *CE = dyn_cast_or_null<CXXConstructExpr>(E))
8261 if (const CXXConstructorDecl *Ctor = CE->getConstructor())
8262 if ((Ctor->isCopyOrMoveConstructor() ||
8263 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
8264 CE->getNumArgs() > 0 && CE->getArg(0) != nullptr)
8265 E = CE->getArg(0)->IgnoreParenImpCasts();
8266 if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(E)) {
8267 if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
8268 return getCanonicalDecl(VD);
8269 }
8270 if (const auto *ME = dyn_cast_or_null<MemberExpr>(E))
8271 if (ME->isArrow() && isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8272 return getCanonicalDecl(ME->getMemberDecl());
8273 return nullptr;
8274}
8275
8276bool OpenMPIterationSpaceChecker::checkAndSetCond(Expr *S) {
8277 // Check test-expr for canonical form, save upper-bound UB, flags for
8278 // less/greater and for strict/non-strict comparison.
8279 // OpenMP [2.9] Canonical loop form. Test-expr may be one of the following:
8280 // var relational-op b
8281 // b relational-op var
8282 //
8283 bool IneqCondIsCanonical = SemaRef.getLangOpts().OpenMP >= 50;
8284 if (!S) {
8285 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_cond)
8286 << (IneqCondIsCanonical ? 1 : 0) << LCDecl;
8287 return true;
8288 }
8289 Condition = S;
8290 S = getExprAsWritten(S);
8291 SourceLocation CondLoc = S->getBeginLoc();
8292 auto &&CheckAndSetCond =
8293 [this, IneqCondIsCanonical](BinaryOperatorKind Opcode, const Expr *LHS,
8294 const Expr *RHS, SourceRange SR,
8295 SourceLocation OpLoc) -> std::optional<bool> {
8296 if (BinaryOperator::isRelationalOp(Opcode)) {
8297 if (getInitLCDecl(LHS) == LCDecl)
8298 return setUB(const_cast<Expr *>(RHS),
8299 (Opcode == BO_LT || Opcode == BO_LE),
8300 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8301 if (getInitLCDecl(RHS) == LCDecl)
8302 return setUB(const_cast<Expr *>(LHS),
8303 (Opcode == BO_GT || Opcode == BO_GE),
8304 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8305 } else if (IneqCondIsCanonical && Opcode == BO_NE) {
8306 return setUB(const_cast<Expr *>(getInitLCDecl(LHS) == LCDecl ? RHS : LHS),
8307 /*LessOp=*/std::nullopt,
8308 /*StrictOp=*/true, SR, OpLoc);
8309 }
8310 return std::nullopt;
8311 };
8312 std::optional<bool> Res;
8313 if (auto *RBO = dyn_cast<CXXRewrittenBinaryOperator>(S)) {
8314 CXXRewrittenBinaryOperator::DecomposedForm DF = RBO->getDecomposedForm();
8315 Res = CheckAndSetCond(DF.Opcode, DF.LHS, DF.RHS, RBO->getSourceRange(),
8316 RBO->getOperatorLoc());
8317 } else if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8318 Res = CheckAndSetCond(BO->getOpcode(), BO->getLHS(), BO->getRHS(),
8319 BO->getSourceRange(), BO->getOperatorLoc());
8320 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8321 if (CE->getNumArgs() == 2) {
8322 Res = CheckAndSetCond(
8323 BinaryOperator::getOverloadedOpcode(CE->getOperator()), CE->getArg(0),
8324 CE->getArg(1), CE->getSourceRange(), CE->getOperatorLoc());
8325 }
8326 }
8327 if (Res)
8328 return *Res;
8329 if (dependent() || SemaRef.CurContext->isDependentContext())
8330 return false;
8331 SemaRef.Diag(CondLoc, diag::err_omp_loop_not_canonical_cond)
8332 << (IneqCondIsCanonical ? 1 : 0) << S->getSourceRange() << LCDecl;
8333 return true;
8334}
8335
8336bool OpenMPIterationSpaceChecker::checkAndSetIncRHS(Expr *RHS) {
8337 // RHS of canonical loop form increment can be:
8338 // var + incr
8339 // incr + var
8340 // var - incr
8341 //
8342 RHS = RHS->IgnoreParenImpCasts();
8343 if (auto *BO = dyn_cast<BinaryOperator>(RHS)) {
8344 if (BO->isAdditiveOp()) {
8345 bool IsAdd = BO->getOpcode() == BO_Add;
8346 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8347 return setStep(BO->getRHS(), !IsAdd);
8348 if (IsAdd && getInitLCDecl(BO->getRHS()) == LCDecl)
8349 return setStep(BO->getLHS(), /*Subtract=*/false);
8350 }
8351 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(RHS)) {
8352 bool IsAdd = CE->getOperator() == OO_Plus;
8353 if ((IsAdd || CE->getOperator() == OO_Minus) && CE->getNumArgs() == 2) {
8354 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8355 return setStep(CE->getArg(1), !IsAdd);
8356 if (IsAdd && getInitLCDecl(CE->getArg(1)) == LCDecl)
8357 return setStep(CE->getArg(0), /*Subtract=*/false);
8358 }
8359 }
8360 if (dependent() || SemaRef.CurContext->isDependentContext())
8361 return false;
8362 SemaRef.Diag(RHS->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8363 << RHS->getSourceRange() << LCDecl;
8364 return true;
8365}
8366
8367bool OpenMPIterationSpaceChecker::checkAndSetInc(Expr *S) {
8368 // Check incr-expr for canonical loop form and return true if it
8369 // does not conform.
8370 // OpenMP [2.6] Canonical loop form. Test-expr may be one of the following:
8371 // ++var
8372 // var++
8373 // --var
8374 // var--
8375 // var += incr
8376 // var -= incr
8377 // var = var + incr
8378 // var = incr + var
8379 // var = var - incr
8380 //
8381 if (!S) {
8382 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_incr) << LCDecl;
8383 return true;
8384 }
8385 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8386 if (!ExprTemp->cleanupsHaveSideEffects())
8387 S = ExprTemp->getSubExpr();
8388
8389 IncrementSrcRange = S->getSourceRange();
8390 S = S->IgnoreParens();
8391 if (auto *UO = dyn_cast<UnaryOperator>(S)) {
8392 if (UO->isIncrementDecrementOp() &&
8393 getInitLCDecl(UO->getSubExpr()) == LCDecl)
8394 return setStep(SemaRef
8395 .ActOnIntegerConstant(UO->getBeginLoc(),
8396 (UO->isDecrementOp() ? -1 : 1))
8397 .get(),
8398 /*Subtract=*/false);
8399 } else if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8400 switch (BO->getOpcode()) {
8401 case BO_AddAssign:
8402 case BO_SubAssign:
8403 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8404 return setStep(BO->getRHS(), BO->getOpcode() == BO_SubAssign);
8405 break;
8406 case BO_Assign:
8407 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8408 return checkAndSetIncRHS(BO->getRHS());
8409 break;
8410 default:
8411 break;
8412 }
8413 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8414 switch (CE->getOperator()) {
8415 case OO_PlusPlus:
8416 case OO_MinusMinus:
8417 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8418 return setStep(SemaRef
8419 .ActOnIntegerConstant(
8420 CE->getBeginLoc(),
8421 ((CE->getOperator() == OO_MinusMinus) ? -1 : 1))
8422 .get(),
8423 /*Subtract=*/false);
8424 break;
8425 case OO_PlusEqual:
8426 case OO_MinusEqual:
8427 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8428 return setStep(CE->getArg(1), CE->getOperator() == OO_MinusEqual);
8429 break;
8430 case OO_Equal:
8431 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8432 return checkAndSetIncRHS(CE->getArg(1));
8433 break;
8434 default:
8435 break;
8436 }
8437 }
8438 if (dependent() || SemaRef.CurContext->isDependentContext())
8439 return false;
8440 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8441 << S->getSourceRange() << LCDecl;
8442 return true;
8443}
8444
8445static ExprResult
8446tryBuildCapture(Sema &SemaRef, Expr *Capture,
8447 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8448 StringRef Name = ".capture_expr.") {
8449 if (SemaRef.CurContext->isDependentContext() || Capture->containsErrors())
8450 return Capture;
8451 if (Capture->isEvaluatable(SemaRef.Context, Expr::SE_AllowSideEffects))
8452 return SemaRef.PerformImplicitConversion(
8453 Capture->IgnoreImpCasts(), Capture->getType(), Sema::AA_Converting,
8454 /*AllowExplicit=*/true);
8455 auto I = Captures.find(Capture);
8456 if (I != Captures.end())
8457 return buildCapture(SemaRef, Capture, I->second, Name);
8458 DeclRefExpr *Ref = nullptr;
8459 ExprResult Res = buildCapture(SemaRef, Capture, Ref, Name);
8460 Captures[Capture] = Ref;
8461 return Res;
8462}
8463
8464/// Calculate number of iterations, transforming to unsigned, if number of
8465/// iterations may be larger than the original type.
8466static Expr *
8467calculateNumIters(Sema &SemaRef, Scope *S, SourceLocation DefaultLoc,
8468 Expr *Lower, Expr *Upper, Expr *Step, QualType LCTy,
8469 bool TestIsStrictOp, bool RoundToStep,
8470 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
8471 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures, ".new_step");
8472 if (!NewStep.isUsable())
8473 return nullptr;
8474 llvm::APSInt LRes, SRes;
8475 bool IsLowerConst = false, IsStepConst = false;
8476 if (std::optional<llvm::APSInt> Res =
8477 Lower->getIntegerConstantExpr(SemaRef.Context)) {
8478 LRes = *Res;
8479 IsLowerConst = true;
8480 }
8481 if (std::optional<llvm::APSInt> Res =
8482 Step->getIntegerConstantExpr(SemaRef.Context)) {
8483 SRes = *Res;
8484 IsStepConst = true;
8485 }
8486 bool NoNeedToConvert = IsLowerConst && !RoundToStep &&
8487 ((!TestIsStrictOp && LRes.isNonNegative()) ||
8488 (TestIsStrictOp && LRes.isStrictlyPositive()));
8489 bool NeedToReorganize = false;
8490 // Check if any subexpressions in Lower -Step [+ 1] lead to overflow.
8491 if (!NoNeedToConvert && IsLowerConst &&
8492 (TestIsStrictOp || (RoundToStep && IsStepConst))) {
8493 NoNeedToConvert = true;
8494 if (RoundToStep) {
8495 unsigned BW = LRes.getBitWidth() > SRes.getBitWidth()
8496 ? LRes.getBitWidth()
8497 : SRes.getBitWidth();
8498 LRes = LRes.extend(BW + 1);
8499 LRes.setIsSigned(true);
8500 SRes = SRes.extend(BW + 1);
8501 SRes.setIsSigned(true);
8502 LRes -= SRes;
8503 NoNeedToConvert = LRes.trunc(BW).extend(BW + 1) == LRes;
8504 LRes = LRes.trunc(BW);
8505 }
8506 if (TestIsStrictOp) {
8507 unsigned BW = LRes.getBitWidth();
8508 LRes = LRes.extend(BW + 1);
8509 LRes.setIsSigned(true);
8510 ++LRes;
8511 NoNeedToConvert =
8512 NoNeedToConvert && LRes.trunc(BW).extend(BW + 1) == LRes;
8513 // truncate to the original bitwidth.
8514 LRes = LRes.trunc(BW);
8515 }
8516 NeedToReorganize = NoNeedToConvert;
8517 }
8518 llvm::APSInt URes;
8519 bool IsUpperConst = false;
8520 if (std::optional<llvm::APSInt> Res =
8521 Upper->getIntegerConstantExpr(SemaRef.Context)) {
8522 URes = *Res;
8523 IsUpperConst = true;
8524 }
8525 if (NoNeedToConvert && IsLowerConst && IsUpperConst &&
8526 (!RoundToStep || IsStepConst)) {
8527 unsigned BW = LRes.getBitWidth() > URes.getBitWidth() ? LRes.getBitWidth()
8528 : URes.getBitWidth();
8529 LRes = LRes.extend(BW + 1);
8530 LRes.setIsSigned(true);
8531 URes = URes.extend(BW + 1);
8532 URes.setIsSigned(true);
8533 URes -= LRes;
8534 NoNeedToConvert = URes.trunc(BW).extend(BW + 1) == URes;
8535 NeedToReorganize = NoNeedToConvert;
8536 }
8537 // If the boundaries are not constant or (Lower - Step [+ 1]) is not constant
8538 // or less than zero (Upper - (Lower - Step [+ 1]) may overflow) - promote to
8539 // unsigned.
8540 if ((!NoNeedToConvert || (LRes.isNegative() && !IsUpperConst)) &&
8541 !LCTy->isDependentType() && LCTy->isIntegerType()) {
8542 QualType LowerTy = Lower->getType();
8543 QualType UpperTy = Upper->getType();
8544 uint64_t LowerSize = SemaRef.Context.getTypeSize(LowerTy);
8545 uint64_t UpperSize = SemaRef.Context.getTypeSize(UpperTy);
8546 if ((LowerSize <= UpperSize && UpperTy->hasSignedIntegerRepresentation()) ||
8547 (LowerSize > UpperSize && LowerTy->hasSignedIntegerRepresentation())) {
8548 QualType CastType = SemaRef.Context.getIntTypeForBitwidth(
8549 LowerSize > UpperSize ? LowerSize : UpperSize, /*Signed=*/0);
8550 Upper =
8551 SemaRef
8552 .PerformImplicitConversion(
8553 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Upper).get(),
8554 CastType, Sema::AA_Converting)
8555 .get();
8556 Lower = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Lower).get();
8557 NewStep = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, NewStep.get());
8558 }
8559 }
8560 if (!Lower || !Upper || NewStep.isInvalid())
8561 return nullptr;
8562
8563 ExprResult Diff;
8564 // If need to reorganize, then calculate the form as Upper - (Lower - Step [+
8565 // 1]).
8566 if (NeedToReorganize) {
8567 Diff = Lower;
8568
8569 if (RoundToStep) {
8570 // Lower - Step
8571 Diff =
8572 SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Diff.get(), NewStep.get());
8573 if (!Diff.isUsable())
8574 return nullptr;
8575 }
8576
8577 // Lower - Step [+ 1]
8578 if (TestIsStrictOp)
8579 Diff = SemaRef.BuildBinOp(
8580 S, DefaultLoc, BO_Add, Diff.get(),
8581 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
8582 if (!Diff.isUsable())
8583 return nullptr;
8584
8585 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8586 if (!Diff.isUsable())
8587 return nullptr;
8588
8589 // Upper - (Lower - Step [+ 1]).
8590 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Diff.get());
8591 if (!Diff.isUsable())
8592 return nullptr;
8593 } else {
8594 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Lower);
8595
8596 if (!Diff.isUsable() && LCTy->getAsCXXRecordDecl()) {
8597 // BuildBinOp already emitted error, this one is to point user to upper
8598 // and lower bound, and to tell what is passed to 'operator-'.
8599 SemaRef.Diag(Upper->getBeginLoc(), diag::err_omp_loop_diff_cxx)
8600 << Upper->getSourceRange() << Lower->getSourceRange();
8601 return nullptr;
8602 }
8603
8604 if (!Diff.isUsable())
8605 return nullptr;
8606
8607 // Upper - Lower [- 1]
8608 if (TestIsStrictOp)
8609 Diff = SemaRef.BuildBinOp(
8610 S, DefaultLoc, BO_Sub, Diff.get(),
8611 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
8612 if (!Diff.isUsable())
8613 return nullptr;
8614
8615 if (RoundToStep) {
8616 // Upper - Lower [- 1] + Step
8617 Diff =
8618 SemaRef.BuildBinOp(S, DefaultLoc, BO_Add, Diff.get(), NewStep.get());
8619 if (!Diff.isUsable())
8620 return nullptr;
8621 }
8622 }
8623
8624 // Parentheses (for dumping/debugging purposes only).
8625 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8626 if (!Diff.isUsable())
8627 return nullptr;
8628
8629 // (Upper - Lower [- 1] + Step) / Step or (Upper - Lower) / Step
8630 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Div, Diff.get(), NewStep.get());
8631 if (!Diff.isUsable())
8632 return nullptr;
8633
8634 return Diff.get();
8635}
8636
8637/// Build the expression to calculate the number of iterations.
8638Expr *OpenMPIterationSpaceChecker::buildNumIterations(
8639 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
8640 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
8641 QualType VarType = LCDecl->getType().getNonReferenceType();
8642 if (!VarType->isIntegerType() && !VarType->isPointerType() &&
8643 !SemaRef.getLangOpts().CPlusPlus)
8644 return nullptr;
8645 Expr *LBVal = LB;
8646 Expr *UBVal = UB;
8647 // OuterVar = (LB = TestIsLessOp.getValue() ? min(LB(MinVal), LB(MaxVal)) :
8648 // max(LB(MinVal), LB(MaxVal)))
8649 if (InitDependOnLC) {
8650 const LoopIterationSpace &IS = ResultIterSpaces[*InitDependOnLC - 1];
8651 if (!IS.MinValue || !IS.MaxValue)
8652 return nullptr;
8653 // OuterVar = Min
8654 ExprResult MinValue =
8655 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MinValue);
8656 if (!MinValue.isUsable())
8657 return nullptr;
8658
8659 ExprResult LBMinVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8660 IS.CounterVar, MinValue.get());
8661 if (!LBMinVal.isUsable())
8662 return nullptr;
8663 // OuterVar = Min, LBVal
8664 LBMinVal =
8665 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, LBMinVal.get(), LBVal);
8666 if (!LBMinVal.isUsable())
8667 return nullptr;
8668 // (OuterVar = Min, LBVal)
8669 LBMinVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, LBMinVal.get());
8670 if (!LBMinVal.isUsable())
8671 return nullptr;
8672
8673 // OuterVar = Max
8674 ExprResult MaxValue =
8675 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MaxValue);
8676 if (!MaxValue.isUsable())
8677 return nullptr;
8678
8679 ExprResult LBMaxVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8680 IS.CounterVar, MaxValue.get());
8681 if (!LBMaxVal.isUsable())
8682 return nullptr;
8683 // OuterVar = Max, LBVal
8684 LBMaxVal =
8685 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, LBMaxVal.get(), LBVal);
8686 if (!LBMaxVal.isUsable())
8687 return nullptr;
8688 // (OuterVar = Max, LBVal)
8689 LBMaxVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, LBMaxVal.get());
8690 if (!LBMaxVal.isUsable())
8691 return nullptr;
8692
8693 Expr *LBMin =
8694 tryBuildCapture(SemaRef, LBMinVal.get(), Captures, ".lb_min").get();
8695 Expr *LBMax =
8696 tryBuildCapture(SemaRef, LBMaxVal.get(), Captures, ".lb_max").get();
8697 if (!LBMin || !LBMax)
8698 return nullptr;
8699 // LB(MinVal) < LB(MaxVal)
8700 ExprResult MinLessMaxRes =
8701 SemaRef.BuildBinOp(S, DefaultLoc, BO_LT, LBMin, LBMax);
8702 if (!MinLessMaxRes.isUsable())
8703 return nullptr;
8704 Expr *MinLessMax =
8705 tryBuildCapture(SemaRef, MinLessMaxRes.get(), Captures, ".min_less_max")
8706 .get();
8707 if (!MinLessMax)
8708 return nullptr;
8709 if (*TestIsLessOp) {
8710 // LB(MinVal) < LB(MaxVal) ? LB(MinVal) : LB(MaxVal) - min(LB(MinVal),
8711 // LB(MaxVal))
8712 ExprResult MinLB = SemaRef.ActOnConditionalOp(DefaultLoc, DefaultLoc,
8713 MinLessMax, LBMin, LBMax);
8714 if (!MinLB.isUsable())
8715 return nullptr;
8716 LBVal = MinLB.get();
8717 } else {
8718 // LB(MinVal) < LB(MaxVal) ? LB(MaxVal) : LB(MinVal) - max(LB(MinVal),
8719 // LB(MaxVal))
8720 ExprResult MaxLB = SemaRef.ActOnConditionalOp(DefaultLoc, DefaultLoc,
8721 MinLessMax, LBMax, LBMin);
8722 if (!MaxLB.isUsable())
8723 return nullptr;
8724 LBVal = MaxLB.get();
8725 }
8726 // OuterVar = LB
8727 LBMinVal =
8728 SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign, IS.CounterVar, LBVal);
8729 if (!LBMinVal.isUsable())
8730 return nullptr;
8731 LBVal = LBMinVal.get();
8732 }
8733 // UB = TestIsLessOp.getValue() ? max(UB(MinVal), UB(MaxVal)) :
8734 // min(UB(MinVal), UB(MaxVal))
8735 if (CondDependOnLC) {
8736 const LoopIterationSpace &IS = ResultIterSpaces[*CondDependOnLC - 1];
8737 if (!IS.MinValue || !IS.MaxValue)
8738 return nullptr;
8739 // OuterVar = Min
8740 ExprResult MinValue =
8741 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MinValue);
8742 if (!MinValue.isUsable())
8743 return nullptr;
8744
8745 ExprResult UBMinVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8746 IS.CounterVar, MinValue.get());
8747 if (!UBMinVal.isUsable())
8748 return nullptr;
8749 // OuterVar = Min, UBVal
8750 UBMinVal =
8751 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, UBMinVal.get(), UBVal);
8752 if (!UBMinVal.isUsable())
8753 return nullptr;
8754 // (OuterVar = Min, UBVal)
8755 UBMinVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, UBMinVal.get());
8756 if (!UBMinVal.isUsable())
8757 return nullptr;
8758
8759 // OuterVar = Max
8760 ExprResult MaxValue =
8761 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MaxValue);
8762 if (!MaxValue.isUsable())
8763 return nullptr;
8764
8765 ExprResult UBMaxVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8766 IS.CounterVar, MaxValue.get());
8767 if (!UBMaxVal.isUsable())
8768 return nullptr;
8769 // OuterVar = Max, UBVal
8770 UBMaxVal =
8771 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, UBMaxVal.get(), UBVal);
8772 if (!UBMaxVal.isUsable())
8773 return nullptr;
8774 // (OuterVar = Max, UBVal)
8775 UBMaxVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, UBMaxVal.get());
8776 if (!UBMaxVal.isUsable())
8777 return nullptr;
8778
8779 Expr *UBMin =
8780 tryBuildCapture(SemaRef, UBMinVal.get(), Captures, ".ub_min").get();
8781 Expr *UBMax =
8782 tryBuildCapture(SemaRef, UBMaxVal.get(), Captures, ".ub_max").get();
8783 if (!UBMin || !UBMax)
8784 return nullptr;
8785 // UB(MinVal) > UB(MaxVal)
8786 ExprResult MinGreaterMaxRes =
8787 SemaRef.BuildBinOp(S, DefaultLoc, BO_GT, UBMin, UBMax);
8788 if (!MinGreaterMaxRes.isUsable())
8789 return nullptr;
8790 Expr *MinGreaterMax = tryBuildCapture(SemaRef, MinGreaterMaxRes.get(),
8791 Captures, ".min_greater_max")
8792 .get();
8793 if (!MinGreaterMax)
8794 return nullptr;
8795 if (*TestIsLessOp) {
8796 // UB(MinVal) > UB(MaxVal) ? UB(MinVal) : UB(MaxVal) - max(UB(MinVal),
8797 // UB(MaxVal))
8798 ExprResult MaxUB = SemaRef.ActOnConditionalOp(
8799 DefaultLoc, DefaultLoc, MinGreaterMax, UBMin, UBMax);
8800 if (!MaxUB.isUsable())
8801 return nullptr;
8802 UBVal = MaxUB.get();
8803 } else {
8804 // UB(MinVal) > UB(MaxVal) ? UB(MaxVal) : UB(MinVal) - min(UB(MinVal),
8805 // UB(MaxVal))
8806 ExprResult MinUB = SemaRef.ActOnConditionalOp(
8807 DefaultLoc, DefaultLoc, MinGreaterMax, UBMax, UBMin);
8808 if (!MinUB.isUsable())
8809 return nullptr;
8810 UBVal = MinUB.get();
8811 }
8812 }
8813 Expr *UBExpr = *TestIsLessOp ? UBVal : LBVal;
8814 Expr *LBExpr = *TestIsLessOp ? LBVal : UBVal;
8815 Expr *Upper = tryBuildCapture(SemaRef, UBExpr, Captures, ".upper").get();
8816 Expr *Lower = tryBuildCapture(SemaRef, LBExpr, Captures, ".lower").get();
8817 if (!Upper || !Lower)
8818 return nullptr;
8819
8820 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
8821 Step, VarType, TestIsStrictOp,
8822 /*RoundToStep=*/true, Captures);
8823 if (!Diff.isUsable())
8824 return nullptr;
8825
8826 // OpenMP runtime requires 32-bit or 64-bit loop variables.
8827 QualType Type = Diff.get()->getType();
8828 ASTContext &C = SemaRef.Context;
8829 bool UseVarType = VarType->hasIntegerRepresentation() &&
8830 C.getTypeSize(Type) > C.getTypeSize(VarType);
8831 if (!Type->isIntegerType() || UseVarType) {
8832 unsigned NewSize =
8833 UseVarType ? C.getTypeSize(VarType) : C.getTypeSize(Type);
8834 bool IsSigned = UseVarType ? VarType->hasSignedIntegerRepresentation()
8835 : Type->hasSignedIntegerRepresentation();
8836 Type = C.getIntTypeForBitwidth(NewSize, IsSigned);
8837 if (!SemaRef.Context.hasSameType(Diff.get()->getType(), Type)) {
8838 Diff = SemaRef.PerformImplicitConversion(
8839 Diff.get(), Type, Sema::AA_Converting, /*AllowExplicit=*/true);
8840 if (!Diff.isUsable())
8841 return nullptr;
8842 }
8843 }
8844 if (LimitedType) {
8845 unsigned NewSize = (C.getTypeSize(Type) > 32) ? 64 : 32;
8846 if (NewSize != C.getTypeSize(Type)) {
8847 if (NewSize < C.getTypeSize(Type)) {
8848 assert(NewSize == 64 && "incorrect loop var size")(static_cast <bool> (NewSize == 64 && "incorrect loop var size"
) ? void (0) : __assert_fail ("NewSize == 64 && \"incorrect loop var size\""
, "clang/lib/Sema/SemaOpenMP.cpp", 8848, __extension__ __PRETTY_FUNCTION__
))
;
8849 SemaRef.Diag(DefaultLoc, diag::warn_omp_loop_64_bit_var)
8850 << InitSrcRange << ConditionSrcRange;
8851 }
8852 QualType NewType = C.getIntTypeForBitwidth(
8853 NewSize, Type->hasSignedIntegerRepresentation() ||
8854 C.getTypeSize(Type) < NewSize);
8855 if (!SemaRef.Context.hasSameType(Diff.get()->getType(), NewType)) {
8856 Diff = SemaRef.PerformImplicitConversion(Diff.get(), NewType,
8857 Sema::AA_Converting, true);
8858 if (!Diff.isUsable())
8859 return nullptr;
8860 }
8861 }
8862 }
8863
8864 return Diff.get();
8865}
8866
8867std::pair<Expr *, Expr *> OpenMPIterationSpaceChecker::buildMinMaxValues(
8868 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
8869 // Do not build for iterators, they cannot be used in non-rectangular loop
8870 // nests.
8871 if (LCDecl->getType()->isRecordType())
8872 return std::make_pair(nullptr, nullptr);
8873 // If we subtract, the min is in the condition, otherwise the min is in the
8874 // init value.
8875 Expr *MinExpr = nullptr;
8876 Expr *MaxExpr = nullptr;
8877 Expr *LBExpr = *TestIsLessOp ? LB : UB;
8878 Expr *UBExpr = *TestIsLessOp ? UB : LB;
8879 bool LBNonRect =
8880 *TestIsLessOp ? InitDependOnLC.has_value() : CondDependOnLC.has_value();
8881 bool UBNonRect =
8882 *TestIsLessOp ? CondDependOnLC.has_value() : InitDependOnLC.has_value();
8883 Expr *Lower =
8884 LBNonRect ? LBExpr : tryBuildCapture(SemaRef, LBExpr, Captures).get();
8885 Expr *Upper =
8886 UBNonRect ? UBExpr : tryBuildCapture(SemaRef, UBExpr, Captures).get();
8887 if (!Upper || !Lower)
8888 return std::make_pair(nullptr, nullptr);
8889
8890 if (*TestIsLessOp)
8891 MinExpr = Lower;
8892 else
8893 MaxExpr = Upper;
8894
8895 // Build minimum/maximum value based on number of iterations.
8896 QualType VarType = LCDecl->getType().getNonReferenceType();
8897
8898 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
8899 Step, VarType, TestIsStrictOp,
8900 /*RoundToStep=*/false, Captures);
8901 if (!Diff.isUsable())
8902 return std::make_pair(nullptr, nullptr);
8903
8904 // ((Upper - Lower [- 1]) / Step) * Step
8905 // Parentheses (for dumping/debugging purposes only).
8906 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8907 if (!Diff.isUsable())
8908 return std::make_pair(nullptr, nullptr);
8909
8910 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures, ".new_step");
8911 if (!NewStep.isUsable())
8912 return std::make_pair(nullptr, nullptr);
8913 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Mul, Diff.get(), NewStep.get());
8914 if (!Diff.isUsable())
8915 return std::make_pair(nullptr, nullptr);
8916
8917 // Parentheses (for dumping/debugging purposes only).
8918 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8919 if (!Diff.isUsable())
8920 return std::make_pair(nullptr, nullptr);
8921
8922 // Convert to the ptrdiff_t, if original type is pointer.
8923 if (VarType->isAnyPointerType() &&
8924 !SemaRef.Context.hasSameType(
8925 Diff.get()->getType(),
8926 SemaRef.Context.getUnsignedPointerDiffType())) {
8927 Diff = SemaRef.PerformImplicitConversion(
8928 Diff.get(), SemaRef.Context.getUnsignedPointerDiffType(),
8929 Sema::AA_Converting, /*AllowExplicit=*/true);
8930 }
8931 if (!Diff.isUsable())
8932 return std::make_pair(nullptr, nullptr);
8933
8934 if (*TestIsLessOp) {
8935 // MinExpr = Lower;
8936 // MaxExpr = Lower + (((Upper - Lower [- 1]) / Step) * Step)
8937 Diff = SemaRef.BuildBinOp(
8938 S, DefaultLoc, BO_Add,
8939 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Lower).get(),
8940 Diff.get());
8941 if (!Diff.isUsable())
8942 return std::make_pair(nullptr, nullptr);
8943 } else {
8944 // MaxExpr = Upper;
8945 // MinExpr = Upper - (((Upper - Lower [- 1]) / Step) * Step)
8946 Diff = SemaRef.BuildBinOp(
8947 S, DefaultLoc, BO_Sub,
8948 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Upper).get(),
8949 Diff.get());
8950 if (!Diff.isUsable())
8951 return std::make_pair(nullptr, nullptr);
8952 }
8953
8954 // Convert to the original type.
8955 if (SemaRef.Context.hasSameType(Diff.get()->getType(), VarType))
8956 Diff = SemaRef.PerformImplicitConversion(Diff.get(), VarType,
8957 Sema::AA_Converting,
8958 /*AllowExplicit=*/true);
8959 if (!Diff.isUsable())
8960 return std::make_pair(nullptr, nullptr);
8961
8962 Sema::TentativeAnalysisScope Trap(SemaRef);
8963 Diff = SemaRef.ActOnFinishFullExpr(Diff.get(), /*DiscardedValue=*/false);
8964 if (!Diff.isUsable())
8965 return std::make_pair(nullptr, nullptr);
8966
8967 if (*TestIsLessOp)
8968 MaxExpr = Diff.get();
8969 else
8970 MinExpr = Diff.get();
8971
8972 return std::make_pair(MinExpr, MaxExpr);
8973}
8974
8975Expr *OpenMPIterationSpaceChecker::buildFinalCondition(Scope *S) const {
8976 if (InitDependOnLC || CondDependOnLC)
8977 return Condition;
8978 return nullptr;
8979}
8980
8981Expr *OpenMPIterationSpaceChecker::buildPreCond(
8982 Scope *S, Expr *Cond,
8983 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
8984 // Do not build a precondition when the condition/initialization is dependent
8985 // to prevent pessimistic early loop exit.
8986 // TODO: this can be improved by calculating min/max values but not sure that
8987 // it will be very effective.
8988 if (CondDependOnLC || InitDependOnLC)
8989 return SemaRef
8990 .PerformImplicitConversion(
8991 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get(),
8992 SemaRef.Context.BoolTy, /*Action=*/Sema::AA_Casting,
8993 /*AllowExplicit=*/true)
8994 .get();
8995
8996 // Try to build LB <op> UB, where <op> is <, >, <=, or >=.
8997 Sema::TentativeAnalysisScope Trap(SemaRef);
8998
8999 ExprResult NewLB = tryBuildCapture(SemaRef, LB, Captures);
9000 ExprResult NewUB = tryBuildCapture(SemaRef, UB, Captures);
9001 if (!NewLB.isUsable() || !NewUB.isUsable())
9002 return nullptr;
9003
9004 ExprResult CondExpr =
9005 SemaRef.BuildBinOp(S, DefaultLoc,
9006 *TestIsLessOp ? (TestIsStrictOp ? BO_LT : BO_LE)
9007 : (TestIsStrictOp ? BO_GT : BO_GE),
9008 NewLB.get(), NewUB.get());
9009 if (CondExpr.isUsable()) {
9010 if (!SemaRef.Context.hasSameUnqualifiedType(CondExpr.get()->getType(),
9011 SemaRef.Context.BoolTy))
9012 CondExpr = SemaRef.PerformImplicitConversion(
9013 CondExpr.get(), SemaRef.Context.BoolTy, /*Action=*/Sema::AA_Casting,
9014 /*AllowExplicit=*/true);
9015 }
9016
9017 // Otherwise use original loop condition and evaluate it in runtime.
9018 return CondExpr.isUsable() ? CondExpr.get() : Cond;
9019}
9020
9021/// Build reference expression to the counter be used for codegen.
9022DeclRefExpr *OpenMPIterationSpaceChecker::buildCounterVar(
9023 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9024 DSAStackTy &DSA) const {
9025 auto *VD = dyn_cast<VarDecl>(LCDecl);
9026 if (!VD) {
9027 VD = SemaRef.isOpenMPCapturedDecl(LCDecl);
9028 DeclRefExpr *Ref = buildDeclRefExpr(
9029 SemaRef, VD, VD->getType().getNonReferenceType(), DefaultLoc);
9030 const DSAStackTy::DSAVarData Data =
9031 DSA.getTopDSA(LCDecl, /*FromParent=*/false);
9032 // If the loop control decl is explicitly marked as private, do not mark it
9033 // as captured again.
9034 if (!isOpenMPPrivate(Data.CKind) || !Data.RefExpr)
9035 Captures.insert(std::make_pair(LCRef, Ref));
9036 return Ref;
9037 }
9038 return cast<DeclRefExpr>(LCRef);
9039}
9040
9041Expr *OpenMPIterationSpaceChecker::buildPrivateCounterVar() const {
9042 if (LCDecl && !LCDecl->isInvalidDecl()) {
9043 QualType Type = LCDecl->getType().getNonReferenceType();
9044 VarDecl *PrivateVar = buildVarDecl(
9045 SemaRef, DefaultLoc, Type, LCDecl->getName(),
9046 LCDecl->hasAttrs() ? &LCDecl->getAttrs() : nullptr,
9047 isa<VarDecl>(LCDecl)
9048 ? buildDeclRefExpr(SemaRef, cast<VarDecl>(LCDecl), Type, DefaultLoc)
9049 : nullptr);
9050 if (PrivateVar->isInvalidDecl())
9051 return nullptr;
9052 return buildDeclRefExpr(SemaRef, PrivateVar, Type, DefaultLoc);
9053 }
9054 return nullptr;
9055}
9056
9057/// Build initialization of the counter to be used for codegen.
9058Expr *OpenMPIterationSpaceChecker::buildCounterInit() const { return LB; }
9059
9060/// Build step of the counter be used for codegen.
9061Expr *OpenMPIterationSpaceChecker::buildCounterStep() const { return Step; }
9062
9063Expr *OpenMPIterationSpaceChecker::buildOrderedLoopData(
9064 Scope *S, Expr *Counter,
9065 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures, SourceLocation Loc,
9066 Expr *Inc, OverloadedOperatorKind OOK) {
9067 Expr *Cnt = SemaRef.DefaultLvalueConversion(Counter).get();
9068 if (!Cnt)
9069 return nullptr;
9070 if (Inc) {
9071 assert((OOK == OO_Plus || OOK == OO_Minus) &&(static_cast <bool> ((OOK == OO_Plus || OOK == OO_Minus
) && "Expected only + or - operations for depend clauses."
) ? void (0) : __assert_fail ("(OOK == OO_Plus || OOK == OO_Minus) && \"Expected only + or - operations for depend clauses.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 9072, __extension__ __PRETTY_FUNCTION__
))
9072 "Expected only + or - operations for depend clauses.")(static_cast <bool> ((OOK == OO_Plus || OOK == OO_Minus
) && "Expected only + or - operations for depend clauses."
) ? void (0) : __assert_fail ("(OOK == OO_Plus || OOK == OO_Minus) && \"Expected only + or - operations for depend clauses.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 9072, __extension__ __PRETTY_FUNCTION__
))
;
9073 BinaryOperatorKind BOK = (OOK == OO_Plus) ? BO_Add : BO_Sub;
9074 Cnt = SemaRef.BuildBinOp(S, Loc, BOK, Cnt, Inc).get();
9075 if (!Cnt)
9076 return nullptr;
9077 }
9078 QualType VarType = LCDecl->getType().getNonReferenceType();
9079 if (!VarType->isIntegerType() && !VarType->isPointerType() &&
9080 !SemaRef.getLangOpts().CPlusPlus)
9081 return nullptr;
9082 // Upper - Lower
9083 Expr *Upper =
9084 *TestIsLessOp ? Cnt : tryBuildCapture(SemaRef, LB, Captures).get();
9085 Expr *Lower =
9086 *TestIsLessOp ? tryBuildCapture(SemaRef, LB, Captures).get() : Cnt;
9087 if (!Upper || !Lower)
9088 return nullptr;
9089
9090 ExprResult Diff = calculateNumIters(
9091 SemaRef, S, DefaultLoc, Lower, Upper, Step, VarType,
9092 /*TestIsStrictOp=*/false, /*RoundToStep=*/false, Captures);
9093 if (!Diff.isUsable())
9094 return nullptr;
9095
9096 return Diff.get();
9097}
9098} // namespace
9099
9100void Sema::ActOnOpenMPLoopInitialization(SourceLocation ForLoc, Stmt *Init) {
9101 assert(getLangOpts().OpenMP && "OpenMP is not active.")(static_cast <bool> (getLangOpts().OpenMP && "OpenMP is not active."
) ? void (0) : __assert_fail ("getLangOpts().OpenMP && \"OpenMP is not active.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 9101, __extension__ __PRETTY_FUNCTION__
))
;
1
Assuming field 'OpenMP' is not equal to 0
2
'?' condition is true
9102 assert(Init && "Expected loop in canonical form.")(static_cast <bool> (Init && "Expected loop in canonical form."
) ? void (0) : __assert_fail ("Init && \"Expected loop in canonical form.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 9102, __extension__ __PRETTY_FUNCTION__
))
;
3
Assuming 'Init' is non-null
4
'?' condition is true
9103 unsigned AssociatedLoops = DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getAssociatedLoops();
9104 if (AssociatedLoops > 0 &&
5
Assuming 'AssociatedLoops' is > 0
7
Taking true branch
9105 isOpenMPLoopDirective(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective())
) {
6
Assuming the condition is true
9106 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->loopStart();
9107 OpenMPIterationSpaceChecker ISC(*this, /*SupportsNonRectangular=*/true,
9108 *DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
, ForLoc);
9109 if (!ISC.checkAndSetInit(Init, /*EmitDiags=*/false)) {
8
Calling 'OpenMPIterationSpaceChecker::checkAndSetInit'
9110 if (ValueDecl *D = ISC.getLoopDecl()) {
9111 auto *VD = dyn_cast<VarDecl>(D);
9112 DeclRefExpr *PrivateRef = nullptr;
9113 if (!VD) {
9114 if (VarDecl *Private = isOpenMPCapturedDecl(D)) {
9115 VD = Private;
9116 } else {
9117 PrivateRef = buildCapture(*this, D, ISC.getLoopDeclRefExpr(),
9118 /*WithInit=*/false);
9119 VD = cast<VarDecl>(PrivateRef->getDecl());
9120 }
9121 }
9122 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->addLoopControlVariable(D, VD);
9123 const Decl *LD = DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getPossiblyLoopCunter();
9124 if (LD != D->getCanonicalDecl()) {
9125 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->resetPossibleLoopCounter();
9126 if (auto *Var = dyn_cast_or_null<VarDecl>(LD))
9127 MarkDeclarationsReferencedInExpr(
9128 buildDeclRefExpr(*this, const_cast<VarDecl *>(Var),
9129 Var->getType().getNonLValueExprType(Context),
9130 ForLoc, /*RefersToCapture=*/true));
9131 }
9132 OpenMPDirectiveKind DKind = DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective();
9133 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables
9134 // Referenced in a Construct, C/C++]. The loop iteration variable in the
9135 // associated for-loop of a simd construct with just one associated
9136 // for-loop may be listed in a linear clause with a constant-linear-step
9137 // that is the increment of the associated for-loop. The loop iteration
9138 // variable(s) in the associated for-loop(s) of a for or parallel for
9139 // construct may be listed in a private or lastprivate clause.
9140 DSAStackTy::DSAVarData DVar =
9141 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getTopDSA(D, /*FromParent=*/false);
9142 // If LoopVarRefExpr is nullptr it means the corresponding loop variable
9143 // is declared in the loop and it is predetermined as a private.
9144 Expr *LoopDeclRefExpr = ISC.getLoopDeclRefExpr();
9145 OpenMPClauseKind PredeterminedCKind =
9146 isOpenMPSimdDirective(DKind)
9147 ? (DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->hasMutipleLoops() ? OMPC_lastprivate : OMPC_linear)
9148 : OMPC_private;
9149 if (((isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
9150 DVar.CKind != PredeterminedCKind && DVar.RefExpr &&
9151 (LangOpts.OpenMP <= 45 || (DVar.CKind != OMPC_lastprivate &&
9152 DVar.CKind != OMPC_private))) ||
9153 ((isOpenMPWorksharingDirective(DKind) || DKind == OMPD_taskloop ||
9154 DKind == OMPD_master_taskloop || DKind == OMPD_masked_taskloop ||
9155 DKind == OMPD_parallel_master_taskloop ||
9156 DKind == OMPD_parallel_masked_taskloop ||
9157 isOpenMPDistributeDirective(DKind)) &&
9158 !isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
9159 DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) &&
9160 (DVar.CKind != OMPC_private || DVar.RefExpr)) {
9161 Diag(Init->getBeginLoc(), diag::err_omp_loop_var_dsa)
9162 << getOpenMPClauseName(DVar.CKind)
9163 << getOpenMPDirectiveName(DKind)
9164 << getOpenMPClauseName(PredeterminedCKind);
9165 if (DVar.RefExpr == nullptr)
9166 DVar.CKind = PredeterminedCKind;
9167 reportOriginalDsa(*this, DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
, D, DVar,
9168 /*IsLoopIterVar=*/true);
9169 } else if (LoopDeclRefExpr) {
9170 // Make the loop iteration variable private (for worksharing
9171 // constructs), linear (for simd directives with the only one
9172 // associated loop) or lastprivate (for simd directives with several
9173 // collapsed or ordered loops).
9174 if (DVar.CKind == OMPC_unknown)
9175 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->addDSA(D, LoopDeclRefExpr, PredeterminedCKind,
9176 PrivateRef);
9177 }
9178 }
9179 }
9180 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->setAssociatedLoops(AssociatedLoops - 1);
9181 }
9182}
9183
9184/// Called on a for stmt to check and extract its iteration space
9185/// for further processing (such as collapsing).
9186static bool checkOpenMPIterationSpace(
9187 OpenMPDirectiveKind DKind, Stmt *S, Sema &SemaRef, DSAStackTy &DSA,
9188 unsigned CurrentNestedLoopCount, unsigned NestedLoopCount,
9189 unsigned TotalNestedLoopCount, Expr *CollapseLoopCountExpr,
9190 Expr *OrderedLoopCountExpr,
9191 Sema::VarsWithInheritedDSAType &VarsWithImplicitDSA,
9192 llvm::MutableArrayRef<LoopIterationSpace> ResultIterSpaces,
9193 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9194 bool SupportsNonRectangular = !isOpenMPLoopTransformationDirective(DKind);
9195 // OpenMP [2.9.1, Canonical Loop Form]
9196 // for (init-expr; test-expr; incr-expr) structured-block
9197 // for (range-decl: range-expr) structured-block
9198 if (auto *CanonLoop = dyn_cast_or_null<OMPCanonicalLoop>(S))
9199 S = CanonLoop->getLoopStmt();
9200 auto *For = dyn_cast_or_null<ForStmt>(S);
9201 auto *CXXFor = dyn_cast_or_null<CXXForRangeStmt>(S);
9202 // Ranged for is supported only in OpenMP 5.0.
9203 if (!For && (SemaRef.LangOpts.OpenMP <= 45 || !CXXFor)) {
9204 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_not_for)
9205 << (CollapseLoopCountExpr != nullptr || OrderedLoopCountExpr != nullptr)
9206 << getOpenMPDirectiveName(DKind) << TotalNestedLoopCount
9207 << (CurrentNestedLoopCount > 0) << CurrentNestedLoopCount;
9208 if (TotalNestedLoopCount > 1) {
9209 if (CollapseLoopCountExpr && OrderedLoopCountExpr)
9210 SemaRef.Diag(DSA.getConstructLoc(),
9211 diag::note_omp_collapse_ordered_expr)
9212 << 2 << CollapseLoopCountExpr->getSourceRange()
9213 << OrderedLoopCountExpr->getSourceRange();
9214 else if (CollapseLoopCountExpr)
9215 SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(),
9216 diag::note_omp_collapse_ordered_expr)
9217 << 0 << CollapseLoopCountExpr->getSourceRange();
9218 else
9219 SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(),
9220 diag::note_omp_collapse_ordered_expr)
9221 << 1 << OrderedLoopCountExpr->getSourceRange();
9222 }
9223 return true;
9224 }
9225 assert(((For && For->getBody()) || (CXXFor && CXXFor->getBody())) &&(static_cast <bool> (((For && For->getBody()
) || (CXXFor && CXXFor->getBody())) && "No loop body."
) ? void (0) : __assert_fail ("((For && For->getBody()) || (CXXFor && CXXFor->getBody())) && \"No loop body.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 9226, __extension__ __PRETTY_FUNCTION__
))
9226 "No loop body.")(static_cast <bool> (((For && For->getBody()
) || (CXXFor && CXXFor->getBody())) && "No loop body."
) ? void (0) : __assert_fail ("((For && For->getBody()) || (CXXFor && CXXFor->getBody())) && \"No loop body.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 9226, __extension__ __PRETTY_FUNCTION__
))
;
9227 // Postpone analysis in dependent contexts for ranged for loops.
9228 if (CXXFor && SemaRef.CurContext->isDependentContext())
9229 return false;
9230
9231 OpenMPIterationSpaceChecker ISC(SemaRef, SupportsNonRectangular, DSA,
9232 For ? For->getForLoc() : CXXFor->getForLoc());
9233
9234 // Check init.
9235 Stmt *Init = For ? For->getInit() : CXXFor->getBeginStmt();
9236 if (ISC.checkAndSetInit(Init))
9237 return true;
9238
9239 bool HasErrors = false;
9240
9241 // Check loop variable's type.
9242 if (ValueDecl *LCDecl = ISC.getLoopDecl()) {
9243 // OpenMP [2.6, Canonical Loop Form]
9244 // Var is one of the following:
9245 // A variable of signed or unsigned integer type.
9246 // For C++, a variable of a random access iterator type.
9247 // For C, a variable of a pointer type.
9248 QualType VarType = LCDecl->getType().getNonReferenceType();
9249 if (!VarType->isDependentType() && !VarType->isIntegerType() &&
9250 !VarType->isPointerType() &&
9251 !(SemaRef.getLangOpts().CPlusPlus && VarType->isOverloadableType())) {
9252 SemaRef.Diag(Init->getBeginLoc(), diag::err_omp_loop_variable_type)
9253 << SemaRef.getLangOpts().CPlusPlus;
9254 HasErrors = true;
9255 }
9256
9257 // OpenMP, 2.14.1.1 Data-sharing Attribute Rules for Variables Referenced in
9258 // a Construct
9259 // The loop iteration variable(s) in the associated for-loop(s) of a for or
9260 // parallel for construct is (are) private.
9261 // The loop iteration variable in the associated for-loop of a simd
9262 // construct with just one associated for-loop is linear with a
9263 // constant-linear-step that is the increment of the associated for-loop.
9264 // Exclude loop var from the list of variables with implicitly defined data
9265 // sharing attributes.
9266 VarsWithImplicitDSA.erase(LCDecl);
9267
9268 assert(isOpenMPLoopDirective(DKind) && "DSA for non-loop vars")(static_cast <bool> (isOpenMPLoopDirective(DKind) &&
"DSA for non-loop vars") ? void (0) : __assert_fail ("isOpenMPLoopDirective(DKind) && \"DSA for non-loop vars\""
, "clang/lib/Sema/SemaOpenMP.cpp", 9268, __extension__ __PRETTY_FUNCTION__
))
;
9269
9270 // Check test-expr.
9271 HasErrors |= ISC.checkAndSetCond(For ? For->getCond() : CXXFor->getCond());
9272
9273 // Check incr-expr.
9274 HasErrors |= ISC.checkAndSetInc(For ? For->getInc() : CXXFor->getInc());
9275 }
9276
9277 if (ISC.dependent() || SemaRef.CurContext->isDependentContext() || HasErrors)
9278 return HasErrors;
9279
9280 // Build the loop's iteration space representation.
9281 ResultIterSpaces[CurrentNestedLoopCount].PreCond = ISC.buildPreCond(
9282 DSA.getCurScope(), For ? For->getCond() : CXXFor->getCond(), Captures);
9283 ResultIterSpaces[CurrentNestedLoopCount].NumIterations =
9284 ISC.buildNumIterations(DSA.getCurScope(), ResultIterSpaces,
9285 (isOpenMPWorksharingDirective(DKind) ||
9286 isOpenMPGenericLoopDirective(DKind) ||
9287 isOpenMPTaskLoopDirective(DKind) ||
9288 isOpenMPDistributeDirective(DKind) ||
9289 isOpenMPLoopTransformationDirective(DKind)),
9290 Captures);
9291 ResultIterSpaces[CurrentNestedLoopCount].CounterVar =
9292 ISC.buildCounterVar(Captures, DSA);
9293 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar =
9294 ISC.buildPrivateCounterVar();
9295 ResultIterSpaces[CurrentNestedLoopCount].CounterInit = ISC.buildCounterInit();
9296 ResultIterSpaces[CurrentNestedLoopCount].CounterStep = ISC.buildCounterStep();
9297 ResultIterSpaces[CurrentNestedLoopCount].InitSrcRange = ISC.getInitSrcRange();
9298 ResultIterSpaces[CurrentNestedLoopCount].CondSrcRange =
9299 ISC.getConditionSrcRange();
9300 ResultIterSpaces[CurrentNestedLoopCount].IncSrcRange =
9301 ISC.getIncrementSrcRange();
9302 ResultIterSpaces[CurrentNestedLoopCount].Subtract = ISC.shouldSubtractStep();
9303 ResultIterSpaces[CurrentNestedLoopCount].IsStrictCompare =
9304 ISC.isStrictTestOp();
9305 std::tie(ResultIterSpaces[CurrentNestedLoopCount].MinValue,
9306 ResultIterSpaces[CurrentNestedLoopCount].MaxValue) =
9307 ISC.buildMinMaxValues(DSA.getCurScope(), Captures);
9308 ResultIterSpaces[CurrentNestedLoopCount].FinalCondition =
9309 ISC.buildFinalCondition(DSA.getCurScope());
9310 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularLB =
9311 ISC.doesInitDependOnLC();
9312 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularUB =
9313 ISC.doesCondDependOnLC();
9314 ResultIterSpaces[CurrentNestedLoopCount].LoopDependentIdx =
9315 ISC.getLoopDependentIdx();
9316
9317 HasErrors |=
9318 (ResultIterSpaces[CurrentNestedLoopCount].PreCond == nullptr ||
9319 ResultIterSpaces[CurrentNestedLoopCount].NumIterations == nullptr ||
9320 ResultIterSpaces[CurrentNestedLoopCount].CounterVar == nullptr ||
9321 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar == nullptr ||
9322 ResultIterSpaces[CurrentNestedLoopCount].CounterInit == nullptr ||
9323 ResultIterSpaces[CurrentNestedLoopCount].CounterStep == nullptr);
9324 if (!HasErrors && DSA.isOrderedRegion()) {
9325 if (DSA.getOrderedRegionParam().second->getNumForLoops()) {
9326 if (CurrentNestedLoopCount <
9327 DSA.getOrderedRegionParam().second->getLoopNumIterations().size()) {
9328 DSA.getOrderedRegionParam().second->setLoopNumIterations(
9329 CurrentNestedLoopCount,
9330 ResultIterSpaces[CurrentNestedLoopCount].NumIterations);
9331 DSA.getOrderedRegionParam().second->setLoopCounter(
9332 CurrentNestedLoopCount,
9333 ResultIterSpaces[CurrentNestedLoopCount].CounterVar);
9334 }
9335 }
9336 for (auto &Pair : DSA.getDoacrossDependClauses()) {
9337 if (CurrentNestedLoopCount >= Pair.first->getNumLoops()) {
9338 // Erroneous case - clause has some problems.
9339 continue;
9340 }
9341 if (Pair.first->getDependencyKind() == OMPC_DEPEND_sink &&
9342 Pair.second.size() <= CurrentNestedLoopCount) {
9343 // Erroneous case - clause has some problems.
9344 Pair.first->setLoopData(CurrentNestedLoopCount, nullptr);
9345 continue;
9346 }
9347 Expr *CntValue;
9348 if (Pair.first->getDependencyKind() == OMPC_DEPEND_source)
9349 CntValue = ISC.buildOrderedLoopData(
9350 DSA.getCurScope(),
9351 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9352 Pair.first->getDependencyLoc());
9353 else
9354 CntValue = ISC.buildOrderedLoopData(
9355 DSA.getCurScope(),
9356 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9357 Pair.first->getDependencyLoc(),
9358 Pair.second[CurrentNestedLoopCount].first,
9359 Pair.second[CurrentNestedLoopCount].second);
9360 Pair.first->setLoopData(CurrentNestedLoopCount, CntValue);
9361 }
9362 }
9363
9364 return HasErrors;
9365}
9366
9367/// Build 'VarRef = Start.
9368static ExprResult
9369buildCounterInit(Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef,
9370 ExprResult Start, bool IsNonRectangularLB,
9371 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9372 // Build 'VarRef = Start.
9373 ExprResult NewStart = IsNonRectangularLB
9374 ? Start.get()
9375 : tryBuildCapture(SemaRef, Start.get(), Captures);
9376 if (!NewStart.isUsable())
9377 return ExprError();
9378 if (!SemaRef.Context.hasSameType(NewStart.get()->getType(),
9379 VarRef.get()->getType())) {
9380 NewStart = SemaRef.PerformImplicitConversion(
9381 NewStart.get(), VarRef.get()->getType(), Sema::AA_Converting,
9382 /*AllowExplicit=*/true);
9383 if (!NewStart.isUsable())
9384 return ExprError();
9385 }
9386
9387 ExprResult Init =
9388 SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), NewStart.get());
9389 return Init;
9390}
9391
9392/// Build 'VarRef = Start + Iter * Step'.
9393static ExprResult buildCounterUpdate(
9394 Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef,
9395 ExprResult Start, ExprResult Iter, ExprResult Step, bool Subtract,
9396 bool IsNonRectangularLB,
9397 llvm::MapVector<const Expr *, DeclRefExpr *> *Captures = nullptr) {
9398 // Add parentheses (for debugging purposes only).
9399 Iter = SemaRef.ActOnParenExpr(Loc, Loc, Iter.get());
9400 if (!VarRef.isUsable() || !Start.isUsable() || !Iter.isUsable() ||
9401 !Step.isUsable())
9402 return ExprError();
9403
9404 ExprResult NewStep = Step;
9405 if (Captures)
9406 NewStep = tryBuildCapture(SemaRef, Step.get(), *Captures);
9407 if (NewStep.isInvalid())
9408 return ExprError();
9409 ExprResult Update =
9410 SemaRef.BuildBinOp(S, Loc, BO_Mul, Iter.get(), NewStep.get());
9411 if (!Update.isUsable())
9412 return ExprError();
9413
9414 // Try to build 'VarRef = Start, VarRef (+|-)= Iter * Step' or
9415 // 'VarRef = Start (+|-) Iter * Step'.
9416 if (!Start.isUsable())
9417 return ExprError();
9418 ExprResult NewStart = SemaRef.ActOnParenExpr(Loc, Loc, Start.get());
9419 if (!NewStart.isUsable())
9420 return ExprError();
9421 if (Captures && !IsNonRectangularLB)
9422 NewStart = tryBuildCapture(SemaRef, Start.get(), *Captures);
9423 if (NewStart.isInvalid())
9424 return ExprError();
9425
9426 // First attempt: try to build 'VarRef = Start, VarRef += Iter * Step'.
9427 ExprResult SavedUpdate = Update;
9428 ExprResult UpdateVal;
9429 if (VarRef.get()->getType()->isOverloadableType() ||
9430 NewStart.get()->getType()->isOverloadableType() ||
9431 Update.get()->getType()->isOverloadableType()) {
9432 Sema::TentativeAnalysisScope Trap(SemaRef);
9433
9434 Update =
9435 SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), NewStart.get());
9436 if (Update.isUsable()) {
9437 UpdateVal =
9438 SemaRef.BuildBinOp(S, Loc, Subtract ? BO_SubAssign : BO_AddAssign,
9439 VarRef.get(), SavedUpdate.get());
9440 if (UpdateVal.isUsable()) {
9441 Update = SemaRef.CreateBuiltinBinOp(Loc, BO_Comma, Update.get(),
9442 UpdateVal.get());
9443 }
9444 }
9445 }
9446
9447 // Second attempt: try to build 'VarRef = Start (+|-) Iter * Step'.
9448 if (!Update.isUsable() || !UpdateVal.isUsable()) {
9449 Update = SemaRef.BuildBinOp(S, Loc, Subtract ? BO_Sub : BO_Add,
9450 NewStart.get(), SavedUpdate.get());
9451 if (!Update.isUsable())
9452 return ExprError();
9453
9454 if (!SemaRef.Context.hasSameType(Update.get()->getType(),
9455 VarRef.get()->getType())) {
9456 Update = SemaRef.PerformImplicitConversion(
9457 Update.get(), VarRef.get()->getType(), Sema::AA_Converting, true);
9458 if (!Update.isUsable())
9459 return ExprError();
9460 }
9461
9462 Update = SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), Update.get());
9463 }
9464 return Update;
9465}
9466
9467/// Convert integer expression \a E to make it have at least \a Bits
9468/// bits.
9469static ExprResult widenIterationCount(unsigned Bits, Expr *E, Sema &SemaRef) {
9470 if (E == nullptr)
9471 return ExprError();
9472 ASTContext &C = SemaRef.Context;
9473 QualType OldType = E->getType();
9474 unsigned HasBits = C.getTypeSize(OldType);
9475 if (HasBits >= Bits)
9476 return ExprResult(E);
9477 // OK to convert to signed, because new type has more bits than old.
9478 QualType NewType = C.getIntTypeForBitwidth(Bits, /* Signed */ true);
9479 return SemaRef.PerformImplicitConversion(E, NewType, Sema::AA_Converting,
9480 true);
9481}
9482
9483/// Check if the given expression \a E is a constant integer that fits
9484/// into \a Bits bits.
9485static bool fitsInto(unsigned Bits, bool Signed, const Expr *E, Sema &SemaRef) {
9486 if (E == nullptr)
9487 return false;
9488 if (std::optional<llvm::APSInt> Result =
9489 E->getIntegerConstantExpr(SemaRef.Context))
9490 return Signed ? Result->isSignedIntN(Bits) : Result->isIntN(Bits);
9491 return false;
9492}
9493
9494/// Build preinits statement for the given declarations.
9495static Stmt *buildPreInits(ASTContext &Context,
9496 MutableArrayRef<Decl *> PreInits) {
9497 if (!PreInits.empty()) {
9498 return new (Context) DeclStmt(
9499 DeclGroupRef::Create(Context, PreInits.begin(), PreInits.size()),
9500 SourceLocation(), SourceLocation());
9501 }
9502 return nullptr;
9503}
9504
9505/// Build preinits statement for the given declarations.
9506static Stmt *
9507buildPreInits(ASTContext &Context,
9508 const llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9509 if (!Captures.empty()) {
9510 SmallVector<Decl *, 16> PreInits;
9511 for (const auto &Pair : Captures)
9512 PreInits.push_back(Pair.second->getDecl());
9513 return buildPreInits(Context, PreInits);
9514 }
9515 return nullptr;
9516}
9517
9518/// Build postupdate expression for the given list of postupdates expressions.
9519static Expr *buildPostUpdate(Sema &S, ArrayRef<Expr *> PostUpdates) {
9520 Expr *PostUpdate = nullptr;
9521 if (!PostUpdates.empty()) {
9522 for (Expr *E : PostUpdates) {
9523 Expr *ConvE = S.BuildCStyleCastExpr(
9524 E->getExprLoc(),
9525 S.Context.getTrivialTypeSourceInfo(S.Context.VoidTy),
9526 E->getExprLoc(), E)
9527 .get();
9528 PostUpdate = PostUpdate
9529 ? S.CreateBuiltinBinOp(ConvE->getExprLoc(), BO_Comma,
9530 PostUpdate, ConvE)
9531 .get()
9532 : ConvE;
9533 }
9534 }
9535 return PostUpdate;
9536}
9537
9538/// Called on a for stmt to check itself and nested loops (if any).
9539/// \return Returns 0 if one of the collapsed stmts is not canonical for loop,
9540/// number of collapsed loops otherwise.
9541static unsigned
9542checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
9543 Expr *OrderedLoopCountExpr, Stmt *AStmt, Sema &SemaRef,
9544 DSAStackTy &DSA,
9545 Sema::VarsWithInheritedDSAType &VarsWithImplicitDSA,
9546 OMPLoopBasedDirective::HelperExprs &Built) {
9547 unsigned NestedLoopCount = 1;
9548 bool SupportsNonPerfectlyNested = (SemaRef.LangOpts.OpenMP >= 50) &&
9549 !isOpenMPLoopTransformationDirective(DKind);
9550
9551 if (CollapseLoopCountExpr) {
9552 // Found 'collapse' clause - calculate collapse number.
9553 Expr::EvalResult Result;
9554 if (!CollapseLoopCountExpr->isValueDependent() &&
9555 CollapseLoopCountExpr->EvaluateAsInt(Result, SemaRef.getASTContext())) {
9556 NestedLoopCount = Result.Val.getInt().getLimitedValue();
9557 } else {
9558 Built.clear(/*Size=*/1);
9559 return 1;
9560 }
9561 }
9562 unsigned OrderedLoopCount = 1;
9563 if (OrderedLoopCountExpr) {
9564 // Found 'ordered' clause - calculate collapse number.
9565 Expr::EvalResult EVResult;
9566 if (!OrderedLoopCountExpr->isValueDependent() &&
9567 OrderedLoopCountExpr->EvaluateAsInt(EVResult,
9568 SemaRef.getASTContext())) {
9569 llvm::APSInt Result = EVResult.Val.getInt();
9570 if (Result.getLimitedValue() < NestedLoopCount) {
9571 SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(),
9572 diag::err_omp_wrong_ordered_loop_count)
9573 << OrderedLoopCountExpr->getSourceRange();
9574 SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(),
9575 diag::note_collapse_loop_count)
9576 << CollapseLoopCountExpr->getSourceRange();
9577 }
9578 OrderedLoopCount = Result.getLimitedValue();
9579 } else {
9580 Built.clear(/*Size=*/1);
9581 return 1;
9582 }
9583 }
9584 // This is helper routine for loop directives (e.g., 'for', 'simd',
9585 // 'for simd', etc.).
9586 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
9587 unsigned NumLoops = std::max(OrderedLoopCount, NestedLoopCount);
9588 SmallVector<LoopIterationSpace, 4> IterSpaces(NumLoops);
9589 if (!OMPLoopBasedDirective::doForAllLoops(
9590 AStmt->IgnoreContainers(!isOpenMPLoopTransformationDirective(DKind)),
9591 SupportsNonPerfectlyNested, NumLoops,
9592 [DKind, &SemaRef, &DSA, NumLoops, NestedLoopCount,
9593 CollapseLoopCountExpr, OrderedLoopCountExpr, &VarsWithImplicitDSA,
9594 &IterSpaces, &Captures](unsigned Cnt, Stmt *CurStmt) {
9595 if (checkOpenMPIterationSpace(
9596 DKind, CurStmt, SemaRef, DSA, Cnt, NestedLoopCount,
9597 NumLoops, CollapseLoopCountExpr, OrderedLoopCountExpr,
9598 VarsWithImplicitDSA, IterSpaces, Captures))
9599 return true;
9600 if (Cnt > 0 && Cnt >= NestedLoopCount &&
9601 IterSpaces[Cnt].CounterVar) {
9602 // Handle initialization of captured loop iterator variables.
9603 auto *DRE = cast<DeclRefExpr>(IterSpaces[Cnt].CounterVar);
9604 if (isa<OMPCapturedExprDecl>(DRE->getDecl())) {
9605 Captures[DRE] = DRE;
9606 }
9607 }
9608 return false;
9609 },
9610 [&SemaRef, &Captures](OMPLoopTransformationDirective *Transform) {
9611 Stmt *DependentPreInits = Transform->getPreInits();
9612 if (!DependentPreInits)
9613 return;
9614 for (Decl *C : cast<DeclStmt>(DependentPreInits)->getDeclGroup()) {
9615 auto *D = cast<VarDecl>(C);
9616 DeclRefExpr *Ref = buildDeclRefExpr(SemaRef, D, D->getType(),
9617 Transform->getBeginLoc());
9618 Captures[Ref] = Ref;
9619 }
9620 }))
9621 return 0;
9622
9623 Built.clear(/* size */ NestedLoopCount);
9624
9625 if (SemaRef.CurContext->isDependentContext())
9626 return NestedLoopCount;
9627
9628 // An example of what is generated for the following code:
9629 //
9630 // #pragma omp simd collapse(2) ordered(2)
9631 // for (i = 0; i < NI; ++i)
9632 // for (k = 0; k < NK; ++k)
9633 // for (j = J0; j < NJ; j+=2) {
9634 // <loop body>
9635 // }
9636 //
9637 // We generate the code below.
9638 // Note: the loop body may be outlined in CodeGen.
9639 // Note: some counters may be C++ classes, operator- is used to find number of
9640 // iterations and operator+= to calculate counter value.
9641 // Note: decltype(NumIterations) must be integer type (in 'omp for', only i32
9642 // or i64 is currently supported).
9643 //
9644 // #define NumIterations (NI * ((NJ - J0 - 1 + 2) / 2))
9645 // for (int[32|64]_t IV = 0; IV < NumIterations; ++IV ) {
9646 // .local.i = IV / ((NJ - J0 - 1 + 2) / 2);
9647 // .local.j = J0 + (IV % ((NJ - J0 - 1 + 2) / 2)) * 2;
9648 // // similar updates for vars in clauses (e.g. 'linear')
9649 // <loop body (using local i and j)>
9650 // }
9651 // i = NI; // assign final values of counters
9652 // j = NJ;
9653 //
9654
9655 // Last iteration number is (I1 * I2 * ... In) - 1, where I1, I2 ... In are
9656 // the iteration counts of the collapsed for loops.
9657 // Precondition tests if there is at least one iteration (all conditions are
9658 // true).
9659 auto PreCond = ExprResult(IterSpaces[0].PreCond);
9660 Expr *N0 = IterSpaces[0].NumIterations;
9661 ExprResult LastIteration32 =
9662 widenIterationCount(/*Bits=*/32,
9663 SemaRef
9664 .PerformImplicitConversion(
9665 N0->IgnoreImpCasts(), N0->getType(),
9666 Sema::AA_Converting, /*AllowExplicit=*/true)
9667 .get(),
9668 SemaRef);
9669 ExprResult LastIteration64 = widenIterationCount(
9670 /*Bits=*/64,
9671 SemaRef
9672 .PerformImplicitConversion(N0->IgnoreImpCasts(), N0->getType(),
9673 Sema::AA_Converting,
9674 /*AllowExplicit=*/true)
9675 .get(),
9676 SemaRef);
9677
9678 if (!LastIteration32.isUsable() || !LastIteration64.isUsable())
9679 return NestedLoopCount;
9680
9681 ASTContext &C = SemaRef.Context;
9682 bool AllCountsNeedLessThan32Bits = C.getTypeSize(N0->getType()) < 32;
9683
9684 Scope *CurScope = DSA.getCurScope();
9685 for (unsigned Cnt = 1; Cnt < NestedLoopCount; ++Cnt) {
9686 if (PreCond.isUsable()) {
9687 PreCond =
9688 SemaRef.BuildBinOp(CurScope, PreCond.get()->getExprLoc(), BO_LAnd,
9689 PreCond.get(), IterSpaces[Cnt].PreCond);
9690 }
9691 Expr *N = IterSpaces[Cnt].NumIterations;
9692 SourceLocation Loc = N->getExprLoc();
9693 AllCountsNeedLessThan32Bits &= C.getTypeSize(N->getType()) < 32;
9694 if (LastIteration32.isUsable())
9695 LastIteration32 = SemaRef.BuildBinOp(
9696 CurScope, Loc, BO_Mul, LastIteration32.get(),
9697 SemaRef
9698 .PerformImplicitConversion(N->IgnoreImpCasts(), N->getType(),
9699 Sema::AA_Converting,
9700 /*AllowExplicit=*/true)
9701 .get());
9702 if (LastIteration64.isUsable())
9703 LastIteration64 = SemaRef.BuildBinOp(
9704 CurScope, Loc, BO_Mul, LastIteration64.get(),
9705 SemaRef
9706 .PerformImplicitConversion(N->IgnoreImpCasts(), N->getType(),
9707 Sema::AA_Converting,
9708 /*AllowExplicit=*/true)
9709 .get());
9710 }
9711
9712 // Choose either the 32-bit or 64-bit version.
9713 ExprResult LastIteration = LastIteration64;
9714 if (SemaRef.getLangOpts().OpenMPOptimisticCollapse ||
9715 (LastIteration32.isUsable() &&
9716 C.getTypeSize(LastIteration32.get()->getType()) == 32 &&
9717 (AllCountsNeedLessThan32Bits || NestedLoopCount == 1 ||
9718 fitsInto(
9719 /*Bits=*/32,
9720 LastIteration32.get()->getType()->hasSignedIntegerRepresentation(),
9721 LastIteration64.get(), SemaRef))))
9722 LastIteration = LastIteration32;
9723 QualType VType = LastIteration.get()->getType();
9724 QualType RealVType = VType;
9725 QualType StrideVType = VType;
9726 if (isOpenMPTaskLoopDirective(DKind)) {
9727 VType =
9728 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0);
9729 StrideVType =
9730 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
9731 }
9732
9733 if (!LastIteration.isUsable())
9734 return 0;
9735
9736 // Save the number of iterations.
9737 ExprResult NumIterations = LastIteration;
9738 {
9739 LastIteration = SemaRef.BuildBinOp(
9740 CurScope, LastIteration.get()->getExprLoc(), BO_Sub,
9741 LastIteration.get(),
9742 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
9743 if (!LastIteration.isUsable())
9744 return 0;
9745 }
9746
9747 // Calculate the last iteration number beforehand instead of doing this on
9748 // each iteration. Do not do this if the number of iterations may be kfold-ed.
9749 bool IsConstant = LastIteration.get()->isIntegerConstantExpr(SemaRef.Context);
9750 ExprResult CalcLastIteration;
9751 if (!IsConstant) {
9752 ExprResult SaveRef =
9753 tryBuildCapture(SemaRef, LastIteration.get(), Captures);
9754 LastIteration = SaveRef;
9755
9756 // Prepare SaveRef + 1.
9757 NumIterations = SemaRef.BuildBinOp(
9758 CurScope, SaveRef.get()->getExprLoc(), BO_Add, SaveRef.get(),
9759 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
9760 if (!NumIterations.isUsable())
9761 return 0;
9762 }
9763
9764 SourceLocation InitLoc = IterSpaces[0].InitSrcRange.getBegin();
9765
9766 // Build variables passed into runtime, necessary for worksharing directives.
9767 ExprResult LB, UB, IL, ST, EUB, CombLB, CombUB, PrevLB, PrevUB, CombEUB;
9768 if (isOpenMPWorksharingDirective(DKind) || isOpenMPTaskLoopDirective(DKind) ||
9769 isOpenMPDistributeDirective(DKind) ||
9770 isOpenMPGenericLoopDirective(DKind) ||
9771 isOpenMPLoopTransformationDirective(DKind)) {
9772 // Lower bound variable, initialized with zero.
9773 VarDecl *LBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.lb");
9774 LB = buildDeclRefExpr(SemaRef, LBDecl, VType, InitLoc);
9775 SemaRef.AddInitializerToDecl(LBDecl,
9776 SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
9777 /*DirectInit*/ false);
9778
9779 // Upper bound variable, initialized with last iteration number.
9780 VarDecl *UBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.ub");
9781 UB = buildDeclRefExpr(SemaRef, UBDecl, VType, InitLoc);
9782 SemaRef.AddInitializerToDecl(UBDecl, LastIteration.get(),
9783 /*DirectInit*/ false);
9784
9785 // A 32-bit variable-flag where runtime returns 1 for the last iteration.
9786 // This will be used to implement clause 'lastprivate'.
9787 QualType Int32Ty = SemaRef.Context.getIntTypeForBitwidth(32, true);
9788 VarDecl *ILDecl = buildVarDecl(SemaRef, InitLoc, Int32Ty, ".omp.is_last");
9789 IL = buildDeclRefExpr(SemaRef, ILDecl, Int32Ty, InitLoc);
9790 SemaRef.AddInitializerToDecl(ILDecl,
9791 SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
9792 /*DirectInit*/ false);
9793
9794 // Stride variable returned by runtime (we initialize it to 1 by default).
9795 VarDecl *STDecl =
9796 buildVarDecl(SemaRef, InitLoc, StrideVType, ".omp.stride");
9797 ST = buildDeclRefExpr(SemaRef, STDecl, StrideVType, InitLoc);
9798 SemaRef.AddInitializerToDecl(STDecl,
9799 SemaRef.ActOnIntegerConstant(InitLoc, 1).get(),
9800 /*DirectInit*/ false);
9801
9802 // Build expression: UB = min(UB, LastIteration)
9803 // It is necessary for CodeGen of directives with static scheduling.
9804 ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, InitLoc, BO_GT,
9805 UB.get(), LastIteration.get());
9806 ExprResult CondOp = SemaRef.ActOnConditionalOp(
9807 LastIteration.get()->getExprLoc(), InitLoc, IsUBGreater.get(),
9808 LastIteration.get(), UB.get());
9809 EUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, UB.get(),
9810 CondOp.get());
9811 EUB = SemaRef.ActOnFinishFullExpr(EUB.get(), /*DiscardedValue*/ false);
9812
9813 // If we have a combined directive that combines 'distribute', 'for' or
9814 // 'simd' we need to be able to access the bounds of the schedule of the
9815 // enclosing region. E.g. in 'distribute parallel for' the bounds obtained
9816 // by scheduling 'distribute' have to be passed to the schedule of 'for'.
9817 if (isOpenMPLoopBoundSharingDirective(DKind)) {
9818 // Lower bound variable, initialized with zero.
9819 VarDecl *CombLBDecl =
9820 buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.lb");
9821 CombLB = buildDeclRefExpr(SemaRef, CombLBDecl, VType, InitLoc);
9822 SemaRef.AddInitializerToDecl(
9823 CombLBDecl, SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
9824 /*DirectInit*/ false);
9825
9826 // Upper bound variable, initialized with last iteration number.
9827 VarDecl *CombUBDecl =
9828 buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.ub");
9829 CombUB = buildDeclRefExpr(SemaRef, CombUBDecl, VType, InitLoc);
9830 SemaRef.AddInitializerToDecl(CombUBDecl, LastIteration.get(),
9831 /*DirectInit*/ false);
9832
9833 ExprResult CombIsUBGreater = SemaRef.BuildBinOp(
9834 CurScope, InitLoc, BO_GT, CombUB.get(), LastIteration.get());
9835 ExprResult CombCondOp =
9836 SemaRef.ActOnConditionalOp(InitLoc, InitLoc, CombIsUBGreater.get(),
9837 LastIteration.get(), CombUB.get());
9838 CombEUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, CombUB.get(),
9839 CombCondOp.get());
9840 CombEUB =
9841 SemaRef.ActOnFinishFullExpr(CombEUB.get(), /*DiscardedValue*/ false);
9842
9843 const CapturedDecl *CD = cast<CapturedStmt>(AStmt)->getCapturedDecl();
9844 // We expect to have at least 2 more parameters than the 'parallel'
9845 // directive does - the lower and upper bounds of the previous schedule.
9846 assert(CD->getNumParams() >= 4 &&(static_cast <bool> (CD->getNumParams() >= 4 &&
"Unexpected number of parameters in loop combined directive"
) ? void (0) : __assert_fail ("CD->getNumParams() >= 4 && \"Unexpected number of parameters in loop combined directive\""
, "clang/lib/Sema/SemaOpenMP.cpp", 9847, __extension__ __PRETTY_FUNCTION__
))
9847 "Unexpected number of parameters in loop combined directive")(static_cast <bool> (CD->getNumParams() >= 4 &&
"Unexpected number of parameters in loop combined directive"
) ? void (0) : __assert_fail ("CD->getNumParams() >= 4 && \"Unexpected number of parameters in loop combined directive\""
, "clang/lib/Sema/SemaOpenMP.cpp", 9847, __extension__ __PRETTY_FUNCTION__
))
;
9848
9849 // Set the proper type for the bounds given what we learned from the
9850 // enclosed loops.
9851 ImplicitParamDecl *PrevLBDecl = CD->getParam(/*PrevLB=*/2);
9852 ImplicitParamDecl *PrevUBDecl = CD->getParam(/*PrevUB=*/3);
9853
9854 // Previous lower and upper bounds are obtained from the region
9855 // parameters.
9856 PrevLB =
9857 buildDeclRefExpr(SemaRef, PrevLBDecl, PrevLBDecl->getType(), InitLoc);
9858 PrevUB =
9859 buildDeclRefExpr(SemaRef, PrevUBDecl, PrevUBDecl->getType(), InitLoc);
9860 }
9861 }
9862
9863 // Build the iteration variable and its initialization before loop.
9864 ExprResult IV;
9865 ExprResult Init, CombInit;
9866 {
9867 VarDecl *IVDecl = buildVarDecl(SemaRef, InitLoc, RealVType, ".omp.iv");
9868 IV = buildDeclRefExpr(SemaRef, IVDecl, RealVType, InitLoc);
9869 Expr *RHS = (isOpenMPWorksharingDirective(DKind) ||
9870 isOpenMPGenericLoopDirective(DKind) ||
9871 isOpenMPTaskLoopDirective(DKind) ||
9872 isOpenMPDistributeDirective(DKind) ||
9873 isOpenMPLoopTransformationDirective(DKind))
9874 ? LB.get()
9875 : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
9876 Init = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), RHS);
9877 Init = SemaRef.ActOnFinishFullExpr(Init.get(), /*DiscardedValue*/ false);
9878
9879 if (isOpenMPLoopBoundSharingDirective(DKind)) {
9880 Expr *CombRHS =
9881 (isOpenMPWorksharingDirective(DKind) ||
9882 isOpenMPGenericLoopDirective(DKind) ||
9883 isOpenMPTaskLoopDirective(DKind) ||
9884 isOpenMPDistributeDirective(DKind))
9885 ? CombLB.get()
9886 : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
9887 CombInit =
9888 SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), CombRHS);
9889 CombInit =
9890 SemaRef.ActOnFinishFullExpr(CombInit.get(), /*DiscardedValue*/ false);
9891 }
9892 }
9893
9894 bool UseStrictCompare =
9895 RealVType->hasUnsignedIntegerRepresentation() &&
9896 llvm::all_of(IterSpaces, [](const LoopIterationSpace &LIS) {
9897 return LIS.IsStrictCompare;
9898 });
9899 // Loop condition (IV < NumIterations) or (IV <= UB or IV < UB + 1 (for
9900 // unsigned IV)) for worksharing loops.
9901 SourceLocation CondLoc = AStmt->getBeginLoc();
9902 Expr *BoundUB = UB.get();
9903 if (UseStrictCompare) {
9904 BoundUB =
9905 SemaRef
9906 .BuildBinOp(CurScope, CondLoc, BO_Add, BoundUB,
9907 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
9908 .get();
9909 BoundUB =
9910 SemaRef.ActOnFinishFullExpr(BoundUB, /*DiscardedValue*/ false).get();
9911 }
9912 ExprResult Cond =
9913 (isOpenMPWorksharingDirective(DKind) ||
9914 isOpenMPGenericLoopDirective(DKind) ||
9915 isOpenMPTaskLoopDirective(DKind) || isOpenMPDistributeDirective(DKind) ||
9916 isOpenMPLoopTransformationDirective(DKind))
9917 ? SemaRef.BuildBinOp(CurScope, CondLoc,
9918 UseStrictCompare ? BO_LT : BO_LE, IV.get(),
9919 BoundUB)
9920 : SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(),
9921 NumIterations.get());
9922 ExprResult CombDistCond;
9923 if (isOpenMPLoopBoundSharingDirective(DKind)) {
9924 CombDistCond = SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(),
9925 NumIterations.get());
9926 }
9927
9928 ExprResult CombCond;
9929 if (isOpenMPLoopBoundSharingDirective(DKind)) {
9930 Expr *BoundCombUB = CombUB.get();
9931 if (UseStrictCompare) {
9932 BoundCombUB =
9933 SemaRef
9934 .BuildBinOp(
9935 CurScope, CondLoc, BO_Add, BoundCombUB,
9936 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
9937 .get();
9938 BoundCombUB =
9939 SemaRef.ActOnFinishFullExpr(BoundCombUB, /*DiscardedValue*/ false)
9940 .get();
9941 }
9942 CombCond =
9943 SemaRef.BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
9944 IV.get(), BoundCombUB);
9945 }
9946 // Loop increment (IV = IV + 1)
9947 SourceLocation IncLoc = AStmt->getBeginLoc();
9948 ExprResult Inc =
9949 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, IV.get(),
9950 SemaRef.ActOnIntegerConstant(IncLoc, 1).get());
9951 if (!Inc.isUsable())
9952 return 0;
9953 Inc = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, IV.get(), Inc.get());
9954 Inc = SemaRef.ActOnFinishFullExpr(Inc.get(), /*DiscardedValue*/ false);
9955 if (!Inc.isUsable())
9956 return 0;
9957
9958 // Increments for worksharing loops (LB = LB + ST; UB = UB + ST).
9959 // Used for directives with static scheduling.
9960 // In combined construct, add combined version that use CombLB and CombUB
9961 // base variables for the update
9962 ExprResult NextLB, NextUB, CombNextLB, CombNextUB;
9963 if (isOpenMPWorksharingDirective(DKind) || isOpenMPTaskLoopDirective(DKind) ||
9964 isOpenMPGenericLoopDirective(DKind) ||
9965 isOpenMPDistributeDirective(DKind) ||
9966 isOpenMPLoopTransformationDirective(DKind)) {
9967 // LB + ST
9968 NextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, LB.get(), ST.get());
9969 if (!NextLB.isUsable())
9970 return 0;
9971 // LB = LB + ST
9972 NextLB =
9973 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, LB.get(), NextLB.get());
9974 NextLB =
9975 SemaRef.ActOnFinishFullExpr(NextLB.get(), /*DiscardedValue*/ false);
9976 if (!NextLB.isUsable())
9977 return 0;
9978 // UB + ST
9979 NextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, UB.get(), ST.get());
9980 if (!NextUB.isUsable())
9981 return 0;
9982 // UB = UB + ST
9983 NextUB =
9984 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, UB.get(), NextUB.get());
9985 NextUB =
9986 SemaRef.ActOnFinishFullExpr(NextUB.get(), /*DiscardedValue*/ false);
9987 if (!NextUB.isUsable())
9988 return 0;
9989 if (isOpenMPLoopBoundSharingDirective(DKind)) {
9990 CombNextLB =
9991 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, CombLB.get(), ST.get());
9992 if (!NextLB.isUsable())
9993 return 0;
9994 // LB = LB + ST
9995 CombNextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombLB.get(),
9996 CombNextLB.get());
9997 CombNextLB = SemaRef.ActOnFinishFullExpr(CombNextLB.get(),
9998 /*DiscardedValue*/ false);
9999 if (!CombNextLB.isUsable())
10000 return 0;
10001 // UB + ST
10002 CombNextUB =
10003 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, CombUB.get(), ST.get());
10004 if (!CombNextUB.isUsable())
10005 return 0;
10006 // UB = UB + ST
10007 CombNextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombUB.get(),
10008 CombNextUB.get());
10009 CombNextUB = SemaRef.ActOnFinishFullExpr(CombNextUB.get(),
10010 /*DiscardedValue*/ false);
10011 if (!CombNextUB.isUsable())
10012 return 0;
10013 }
10014 }
10015
10016 // Create increment expression for distribute loop when combined in a same
10017 // directive with for as IV = IV + ST; ensure upper bound expression based
10018 // on PrevUB instead of NumIterations - used to implement 'for' when found
10019 // in combination with 'distribute', like in 'distribute parallel for'
10020 SourceLocation DistIncLoc = AStmt->getBeginLoc();
10021 ExprResult DistCond, DistInc, PrevEUB, ParForInDistCond;
10022 if (isOpenMPLoopBoundSharingDirective(DKind)) {
10023 DistCond = SemaRef.BuildBinOp(
10024 CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE, IV.get(), BoundUB);
10025 assert(DistCond.isUsable() && "distribute cond expr was not built")(static_cast <bool> (DistCond.isUsable() && "distribute cond expr was not built"
) ? void (0) : __assert_fail ("DistCond.isUsable() && \"distribute cond expr was not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 10025, __extension__ __PRETTY_FUNCTION__
))
;
10026
10027 DistInc =
10028 SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Add, IV.get(), ST.get());
10029 assert(DistInc.isUsable() && "distribute inc expr was not built")(static_cast <bool> (DistInc.isUsable() && "distribute inc expr was not built"
) ? void (0) : __assert_fail ("DistInc.isUsable() && \"distribute inc expr was not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 10029, __extension__ __PRETTY_FUNCTION__
))
;
10030 DistInc = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, IV.get(),
10031 DistInc.get());
10032 DistInc =
10033 SemaRef.ActOnFinishFullExpr(DistInc.get(), /*DiscardedValue*/ false);
10034 assert(DistInc.isUsable() && "distribute inc expr was not built")(static_cast <bool> (DistInc.isUsable() && "distribute inc expr was not built"
) ? void (0) : __assert_fail ("DistInc.isUsable() && \"distribute inc expr was not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 10034, __extension__ __PRETTY_FUNCTION__
))
;
10035
10036 // Build expression: UB = min(UB, prevUB) for #for in composite or combined
10037 // construct
10038 ExprResult NewPrevUB = PrevUB;
10039 SourceLocation DistEUBLoc = AStmt->getBeginLoc();
10040 if (!SemaRef.Context.hasSameType(UB.get()->getType(),
10041 PrevUB.get()->getType())) {
10042 NewPrevUB = SemaRef.BuildCStyleCastExpr(
10043 DistEUBLoc,
10044 SemaRef.Context.getTrivialTypeSourceInfo(UB.get()->getType()),
10045 DistEUBLoc, NewPrevUB.get());
10046 if (!NewPrevUB.isUsable())
10047 return 0;
10048 }
10049 ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, DistEUBLoc, BO_GT,
10050 UB.get(), NewPrevUB.get());
10051 ExprResult CondOp = SemaRef.ActOnConditionalOp(
10052 DistEUBLoc, DistEUBLoc, IsUBGreater.get(), NewPrevUB.get(), UB.get());
10053 PrevEUB = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, UB.get(),
10054 CondOp.get());
10055 PrevEUB =
10056 SemaRef.ActOnFinishFullExpr(PrevEUB.get(), /*DiscardedValue*/ false);
10057
10058 // Build IV <= PrevUB or IV < PrevUB + 1 for unsigned IV to be used in
10059 // parallel for is in combination with a distribute directive with
10060 // schedule(static, 1)
10061 Expr *BoundPrevUB = PrevUB.get();
10062 if (UseStrictCompare) {
10063 BoundPrevUB =
10064 SemaRef
10065 .BuildBinOp(
10066 CurScope, CondLoc, BO_Add, BoundPrevUB,
10067 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
10068 .get();
10069 BoundPrevUB =
10070 SemaRef.ActOnFinishFullExpr(BoundPrevUB, /*DiscardedValue*/ false)
10071 .get();
10072 }
10073 ParForInDistCond =
10074 SemaRef.BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
10075 IV.get(), BoundPrevUB);
10076 }
10077
10078 // Build updates and final values of the loop counters.
10079 bool HasErrors = false;
10080 Built.Counters.resize(NestedLoopCount);
10081 Built.Inits.resize(NestedLoopCount);
10082 Built.Updates.resize(NestedLoopCount);
10083 Built.Finals.resize(NestedLoopCount);
10084 Built.DependentCounters.resize(NestedLoopCount);
10085 Built.DependentInits.resize(NestedLoopCount);
10086 Built.FinalsConditions.resize(NestedLoopCount);
10087 {
10088 // We implement the following algorithm for obtaining the
10089 // original loop iteration variable values based on the
10090 // value of the collapsed loop iteration variable IV.
10091 //
10092 // Let n+1 be the number of collapsed loops in the nest.
10093 // Iteration variables (I0, I1, .... In)
10094 // Iteration counts (N0, N1, ... Nn)
10095 //
10096 // Acc = IV;
10097 //
10098 // To compute Ik for loop k, 0 <= k <= n, generate:
10099 // Prod = N(k+1) * N(k+2) * ... * Nn;
10100 // Ik = Acc / Prod;
10101 // Acc -= Ik * Prod;
10102 //
10103 ExprResult Acc = IV;
10104 for (unsigned int Cnt = 0; Cnt < NestedLoopCount; ++Cnt) {
10105 LoopIterationSpace &IS = IterSpaces[Cnt];
10106 SourceLocation UpdLoc = IS.IncSrcRange.getBegin();
10107 ExprResult Iter;
10108
10109 // Compute prod
10110 ExprResult Prod = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get();
10111 for (unsigned int K = Cnt + 1; K < NestedLoopCount; ++K)
10112 Prod = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, Prod.get(),
10113 IterSpaces[K].NumIterations);
10114
10115 // Iter = Acc / Prod
10116 // If there is at least one more inner loop to avoid
10117 // multiplication by 1.
10118 if (Cnt + 1 < NestedLoopCount)
10119 Iter =
10120 SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Div, Acc.get(), Prod.get());
10121 else
10122 Iter = Acc;
10123 if (!Iter.isUsable()) {
10124 HasErrors = true;
10125 break;
10126 }
10127
10128 // Update Acc:
10129 // Acc -= Iter * Prod
10130 // Check if there is at least one more inner loop to avoid
10131 // multiplication by 1.
10132 if (Cnt + 1 < NestedLoopCount)
10133 Prod = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, Iter.get(),
10134 Prod.get());
10135 else
10136 Prod = Iter;
10137 Acc = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Sub, Acc.get(), Prod.get());
10138
10139 // Build update: IS.CounterVar(Private) = IS.Start + Iter * IS.Step
10140 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IS.CounterVar)->getDecl());
10141 DeclRefExpr *CounterVar = buildDeclRefExpr(
10142 SemaRef, VD, IS.CounterVar->getType(), IS.CounterVar->getExprLoc(),
10143 /*RefersToCapture=*/true);
10144 ExprResult Init =
10145 buildCounterInit(SemaRef, CurScope, UpdLoc, CounterVar,
10146 IS.CounterInit, IS.IsNonRectangularLB, Captures);
10147 if (!Init.isUsable()) {
10148 HasErrors = true;
10149 break;
10150 }
10151 ExprResult Update = buildCounterUpdate(
10152 SemaRef, CurScope, UpdLoc, CounterVar, IS.CounterInit, Iter,
10153 IS.CounterStep, IS.Subtract, IS.IsNonRectangularLB, &Captures);
10154 if (!Update.isUsable()) {
10155 HasErrors = true;
10156 break;
10157 }
10158
10159 // Build final: IS.CounterVar = IS.Start + IS.NumIters * IS.Step
10160 ExprResult Final =
10161 buildCounterUpdate(SemaRef, CurScope, UpdLoc, CounterVar,
10162 IS.CounterInit, IS.NumIterations, IS.CounterStep,
10163 IS.Subtract, IS.IsNonRectangularLB, &Captures);
10164 if (!Final.isUsable()) {
10165 HasErrors = true;
10166 break;
10167 }
10168
10169 if (!Update.isUsable() || !Final.isUsable()) {
10170 HasErrors = true;
10171 break;
10172 }
10173 // Save results
10174 Built.Counters[Cnt] = IS.CounterVar;
10175 Built.PrivateCounters[Cnt] = IS.PrivateCounterVar;
10176 Built.Inits[Cnt] = Init.get();
10177 Built.Updates[Cnt] = Update.get();
10178 Built.Finals[Cnt] = Final.get();
10179 Built.DependentCounters[Cnt] = nullptr;
10180 Built.DependentInits[Cnt] = nullptr;
10181 Built.FinalsConditions[Cnt] = nullptr;
10182 if (IS.IsNonRectangularLB || IS.IsNonRectangularUB) {
10183 Built.DependentCounters[Cnt] = Built.Counters[IS.LoopDependentIdx - 1];
10184 Built.DependentInits[Cnt] = Built.Inits[IS.LoopDependentIdx - 1];
10185 Built.FinalsConditions[Cnt] = IS.FinalCondition;
10186 }
10187 }
10188 }
10189
10190 if (HasErrors)
10191 return 0;
10192
10193 // Save results
10194 Built.IterationVarRef = IV.get();
10195 Built.LastIteration = LastIteration.get();
10196 Built.NumIterations = NumIterations.get();
10197 Built.CalcLastIteration = SemaRef
10198 .ActOnFinishFullExpr(CalcLastIteration.get(),
10199 /*DiscardedValue=*/false)
10200 .get();
10201 Built.PreCond = PreCond.get();
10202 Built.PreInits = buildPreInits(C, Captures);
10203 Built.Cond = Cond.get();
10204 Built.Init = Init.get();
10205 Built.Inc = Inc.get();
10206 Built.LB = LB.get();
10207 Built.UB = UB.get();
10208 Built.IL = IL.get();
10209 Built.ST = ST.get();
10210 Built.EUB = EUB.get();
10211 Built.NLB = NextLB.get();
10212 Built.NUB = NextUB.get();
10213 Built.PrevLB = PrevLB.get();
10214 Built.PrevUB = PrevUB.get();
10215 Built.DistInc = DistInc.get();
10216 Built.PrevEUB = PrevEUB.get();
10217 Built.DistCombinedFields.LB = CombLB.get();
10218 Built.DistCombinedFields.UB = CombUB.get();
10219 Built.DistCombinedFields.EUB = CombEUB.get();
10220 Built.DistCombinedFields.Init = CombInit.get();
10221 Built.DistCombinedFields.Cond = CombCond.get();
10222 Built.DistCombinedFields.NLB = CombNextLB.get();
10223 Built.DistCombinedFields.NUB = CombNextUB.get();
10224 Built.DistCombinedFields.DistCond = CombDistCond.get();
10225 Built.DistCombinedFields.ParForInDistCond = ParForInDistCond.get();
10226
10227 return NestedLoopCount;
10228}
10229
10230static Expr *getCollapseNumberExpr(ArrayRef<OMPClause *> Clauses) {
10231 auto CollapseClauses =
10232 OMPExecutableDirective::getClausesOfKind<OMPCollapseClause>(Clauses);
10233 if (CollapseClauses.begin() != CollapseClauses.end())
10234 return (*CollapseClauses.begin())->getNumForLoops();
10235 return nullptr;
10236}
10237
10238static Expr *getOrderedNumberExpr(ArrayRef<OMPClause *> Clauses) {
10239 auto OrderedClauses =
10240 OMPExecutableDirective::getClausesOfKind<OMPOrderedClause>(Clauses);
10241 if (OrderedClauses.begin() != OrderedClauses.end())
10242 return (*OrderedClauses.begin())->getNumForLoops();
10243 return nullptr;
10244}
10245
10246static bool checkSimdlenSafelenSpecified(Sema &S,
10247 const ArrayRef<OMPClause *> Clauses) {
10248 const OMPSafelenClause *Safelen = nullptr;
10249 const OMPSimdlenClause *Simdlen = nullptr;
10250
10251 for (const OMPClause *Clause : Clauses) {
10252 if (Clause->getClauseKind() == OMPC_safelen)
10253 Safelen = cast<OMPSafelenClause>(Clause);
10254 else if (Clause->getClauseKind() == OMPC_simdlen)
10255 Simdlen = cast<OMPSimdlenClause>(Clause);
10256 if (Safelen && Simdlen)
10257 break;
10258 }
10259
10260 if (Simdlen && Safelen) {
10261 const Expr *SimdlenLength = Simdlen->getSimdlen();
10262 const Expr *SafelenLength = Safelen->getSafelen();
10263 if (SimdlenLength->isValueDependent() || SimdlenLength->isTypeDependent() ||
10264 SimdlenLength->isInstantiationDependent() ||
10265 SimdlenLength->containsUnexpandedParameterPack())
10266 return false;
10267 if (SafelenLength->isValueDependent() || SafelenLength->isTypeDependent() ||
10268 SafelenLength->isInstantiationDependent() ||
10269 SafelenLength->containsUnexpandedParameterPack())
10270 return false;
10271 Expr::EvalResult SimdlenResult, SafelenResult;
10272 SimdlenLength->EvaluateAsInt(SimdlenResult, S.Context);
10273 SafelenLength->EvaluateAsInt(SafelenResult, S.Context);
10274 llvm::APSInt SimdlenRes = SimdlenResult.Val.getInt();
10275 llvm::APSInt SafelenRes = SafelenResult.Val.getInt();
10276 // OpenMP 4.5 [2.8.1, simd Construct, Restrictions]
10277 // If both simdlen and safelen clauses are specified, the value of the
10278 // simdlen parameter must be less than or equal to the value of the safelen
10279 // parameter.
10280 if (SimdlenRes > SafelenRes) {
10281 S.Diag(SimdlenLength->getExprLoc(),
10282 diag::err_omp_wrong_simdlen_safelen_values)
10283 << SimdlenLength->getSourceRange() << SafelenLength->getSourceRange();
10284 return true;
10285 }
10286 }
10287 return false;
10288}
10289
10290StmtResult
10291Sema::ActOnOpenMPSimdDirective(ArrayRef<OMPClause *> Clauses, Stmt *AStmt,
10292 SourceLocation StartLoc, SourceLocation EndLoc,
10293 VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10294 if (!AStmt)
10295 return StmtError();
10296
10297 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected")(static_cast <bool> (isa<CapturedStmt>(AStmt) &&
"Captured statement expected") ? void (0) : __assert_fail ("isa<CapturedStmt>(AStmt) && \"Captured statement expected\""
, "clang/lib/Sema/SemaOpenMP.cpp", 10297, __extension__ __PRETTY_FUNCTION__
))
;
10298 OMPLoopBasedDirective::HelperExprs B;
10299 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10300 // define the nested loops number.
10301 unsigned NestedLoopCount = checkOpenMPLoop(
10302 OMPD_simd, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10303 AStmt, *this, *DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
, VarsWithImplicitDSA, B);
10304 if (NestedLoopCount == 0)
10305 return StmtError();
10306
10307 assert((CurContext->isDependentContext() || B.builtAll()) &&(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp simd loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp simd loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 10308, __extension__ __PRETTY_FUNCTION__
))
10308 "omp simd loop exprs were not built")(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp simd loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp simd loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 10308, __extension__ __PRETTY_FUNCTION__
))
;
10309
10310 if (!CurContext->isDependentContext()) {
10311 // Finalize the clauses that need pre-built expressions for CodeGen.
10312 for (OMPClause *C : Clauses) {
10313 if (auto *LC = dyn_cast<OMPLinearClause>(C))
10314 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
10315 B.NumIterations, *this, CurScope,
10316 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
))
10317 return StmtError();
10318 }
10319 }
10320
10321 if (checkSimdlenSafelenSpecified(*this, Clauses))
10322 return StmtError();
10323
10324 setFunctionHasBranchProtectedScope();
10325 return OMPSimdDirective::Create(Context, StartLoc, EndLoc, NestedLoopCount,
10326 Clauses, AStmt, B);
10327}
10328
10329StmtResult
10330Sema::ActOnOpenMPForDirective(ArrayRef<OMPClause *> Clauses, Stmt *AStmt,
10331 SourceLocation StartLoc, SourceLocation EndLoc,
10332 VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10333 if (!AStmt)
10334 return StmtError();
10335
10336 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected")(static_cast <bool> (isa<CapturedStmt>(AStmt) &&
"Captured statement expected") ? void (0) : __assert_fail ("isa<CapturedStmt>(AStmt) && \"Captured statement expected\""
, "clang/lib/Sema/SemaOpenMP.cpp", 10336, __extension__ __PRETTY_FUNCTION__
))
;
10337 OMPLoopBasedDirective::HelperExprs B;
10338 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10339 // define the nested loops number.
10340 unsigned NestedLoopCount = checkOpenMPLoop(
10341 OMPD_for, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10342 AStmt, *this, *DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
, VarsWithImplicitDSA, B);
10343 if (NestedLoopCount == 0)
10344 return StmtError();
10345
10346 assert((CurContext->isDependentContext() || B.builtAll()) &&(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp for loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp for loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 10347, __extension__ __PRETTY_FUNCTION__
))
10347 "omp for loop exprs were not built")(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp for loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp for loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 10347, __extension__ __PRETTY_FUNCTION__
))
;
10348
10349 if (!CurContext->isDependentContext()) {
10350 // Finalize the clauses that need pre-built expressions for CodeGen.
10351 for (OMPClause *C : Clauses) {
10352 if (auto *LC = dyn_cast<OMPLinearClause>(C))
10353 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
10354 B.NumIterations, *this, CurScope,
10355 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
))
10356 return StmtError();
10357 }
10358 }
10359
10360 setFunctionHasBranchProtectedScope();
10361 return OMPForDirective::Create(
10362 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10363 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getTaskgroupReductionRef(), DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isCancelRegion());
10364}
10365
10366StmtResult Sema::ActOnOpenMPForSimdDirective(
10367 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10368 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10369 if (!AStmt)
10370 return StmtError();
10371
10372 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected")(static_cast <bool> (isa<CapturedStmt>(AStmt) &&
"Captured statement expected") ? void (0) : __assert_fail ("isa<CapturedStmt>(AStmt) && \"Captured statement expected\""
, "clang/lib/Sema/SemaOpenMP.cpp", 10372, __extension__ __PRETTY_FUNCTION__
))
;
10373 OMPLoopBasedDirective::HelperExprs B;
10374 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10375 // define the nested loops number.
10376 unsigned NestedLoopCount =
10377 checkOpenMPLoop(OMPD_for_simd, getCollapseNumberExpr(Clauses),
10378 getOrderedNumberExpr(Clauses), AStmt, *this, *DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
,
10379 VarsWithImplicitDSA, B);
10380 if (NestedLoopCount == 0)
10381 return StmtError();
10382
10383 assert((CurContext->isDependentContext() || B.builtAll()) &&(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp for simd loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp for simd loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 10384, __extension__ __PRETTY_FUNCTION__
))
10384 "omp for simd loop exprs were not built")(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp for simd loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp for simd loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 10384, __extension__ __PRETTY_FUNCTION__
))
;
10385
10386 if (!CurContext->isDependentContext()) {
10387 // Finalize the clauses that need pre-built expressions for CodeGen.
10388 for (OMPClause *C : Clauses) {
10389 if (auto *LC = dyn_cast<OMPLinearClause>(C))
10390 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
10391 B.NumIterations, *this, CurScope,
10392 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
))
10393 return StmtError();
10394 }
10395 }
10396
10397 if (checkSimdlenSafelenSpecified(*this, Clauses))
10398 return StmtError();
10399
10400 setFunctionHasBranchProtectedScope();
10401 return OMPForSimdDirective::Create(Context, StartLoc, EndLoc, NestedLoopCount,
10402 Clauses, AStmt, B);
10403}
10404
10405StmtResult Sema::ActOnOpenMPSectionsDirective(ArrayRef<OMPClause *> Clauses,
10406 Stmt *AStmt,
10407 SourceLocation StartLoc,
10408 SourceLocation EndLoc) {
10409 if (!AStmt)
10410 return StmtError();
10411
10412 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected")(static_cast <bool> (isa<CapturedStmt>(AStmt) &&
"Captured statement expected") ? void (0) : __assert_fail ("isa<CapturedStmt>(AStmt) && \"Captured statement expected\""
, "clang/lib/Sema/SemaOpenMP.cpp", 10412, __extension__ __PRETTY_FUNCTION__
))
;
10413 auto BaseStmt = AStmt;
10414 while (auto *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt))
10415 BaseStmt = CS->getCapturedStmt();
10416 if (auto *C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) {
10417 auto S = C->children();
10418 if (S.begin() == S.end())
10419 return StmtError();
10420 // All associated statements must be '#pragma omp section' except for
10421 // the first one.
10422 for (Stmt *SectionStmt : llvm::drop_begin(S)) {
10423 if (!SectionStmt || !isa<OMPSectionDirective>(SectionStmt)) {
10424 if (SectionStmt)
10425 Diag(SectionStmt->getBeginLoc(),
10426 diag::err_omp_sections_substmt_not_section);
10427 return StmtError();
10428 }
10429 cast<OMPSectionDirective>(SectionStmt)
10430 ->setHasCancel(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isCancelRegion());
10431 }
10432 } else {
10433 Diag(AStmt->getBeginLoc(), diag::err_omp_sections_not_compound_stmt);
10434 return StmtError();
10435 }
10436
10437 setFunctionHasBranchProtectedScope();
10438
10439 return OMPSectionsDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
10440 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getTaskgroupReductionRef(),
10441 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isCancelRegion());
10442}
10443
10444StmtResult Sema::ActOnOpenMPSectionDirective(Stmt *AStmt,
10445 SourceLocation StartLoc,
10446 SourceLocation EndLoc) {
10447 if (!AStmt)
10448 return StmtError();
10449
10450 setFunctionHasBranchProtectedScope();
10451 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->setParentCancelRegion(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isCancelRegion());
10452
10453 return OMPSectionDirective::Create(Context, StartLoc, EndLoc, AStmt,
10454 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isCancelRegion());
10455}
10456
10457static Expr *getDirectCallExpr(Expr *E) {
10458 E = E->IgnoreParenCasts()->IgnoreImplicit();
10459 if (auto *CE = dyn_cast<CallExpr>(E))
10460 if (CE->getDirectCallee())
10461 return E;
10462 return nullptr;
10463}
10464
10465StmtResult Sema::ActOnOpenMPDispatchDirective(ArrayRef<OMPClause *> Clauses,
10466 Stmt *AStmt,
10467 SourceLocation StartLoc,
10468 SourceLocation EndLoc) {
10469 if (!AStmt)
10470 return StmtError();
10471
10472 Stmt *S = cast<CapturedStmt>(AStmt)->getCapturedStmt();
10473
10474 // 5.1 OpenMP
10475 // expression-stmt : an expression statement with one of the following forms:
10476 // expression = target-call ( [expression-list] );
10477 // target-call ( [expression-list] );
10478
10479 SourceLocation TargetCallLoc;
10480
10481 if (!CurContext->isDependentContext()) {
10482 Expr *TargetCall = nullptr;
10483
10484 auto *E = dyn_cast<Expr>(S);
10485 if (!E) {
10486 Diag(S->getBeginLoc(), diag::err_omp_dispatch_statement_call);
10487 return StmtError();
10488 }
10489
10490 E = E->IgnoreParenCasts()->IgnoreImplicit();
10491
10492 if (auto *BO = dyn_cast<BinaryOperator>(E)) {
10493 if (BO->getOpcode() == BO_Assign)
10494 TargetCall = getDirectCallExpr(BO->getRHS());
10495 } else {
10496 if (auto *COCE = dyn_cast<CXXOperatorCallExpr>(E))
10497 if (COCE->getOperator() == OO_Equal)
10498 TargetCall = getDirectCallExpr(COCE->getArg(1));
10499 if (!TargetCall)
10500 TargetCall = getDirectCallExpr(E);
10501 }
10502 if (!TargetCall) {
10503 Diag(E->getBeginLoc(), diag::err_omp_dispatch_statement_call);
10504 return StmtError();
10505 }
10506 TargetCallLoc = TargetCall->getExprLoc();
10507 }
10508
10509 setFunctionHasBranchProtectedScope();
10510
10511 return OMPDispatchDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
10512 TargetCallLoc);
10513}
10514
10515static bool checkGenericLoopLastprivate(Sema &S, ArrayRef<OMPClause *> Clauses,
10516 OpenMPDirectiveKind K,
10517 DSAStackTy *Stack) {
10518 bool ErrorFound = false;
10519 for (OMPClause *C : Clauses) {
10520 if (auto *LPC = dyn_cast<OMPLastprivateClause>(C)) {
10521 for (Expr *RefExpr : LPC->varlists()) {
10522 SourceLocation ELoc;
10523 SourceRange ERange;
10524 Expr *SimpleRefExpr = RefExpr;
10525 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange);
10526 if (ValueDecl *D = Res.first) {
10527 auto &&Info = Stack->isLoopControlVariable(D);
10528 if (!Info.first) {
10529 S.Diag(ELoc, diag::err_omp_lastprivate_loop_var_non_loop_iteration)
10530 << getOpenMPDirectiveName(K);
10531 ErrorFound = true;
10532 }
10533 }
10534 }
10535 }
10536 }
10537 return ErrorFound;
10538}
10539
10540StmtResult Sema::ActOnOpenMPGenericLoopDirective(
10541 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10542 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10543 if (!AStmt)
10544 return StmtError();
10545
10546 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10547 // A list item may not appear in a lastprivate clause unless it is the
10548 // loop iteration variable of a loop that is associated with the construct.
10549 if (checkGenericLoopLastprivate(*this, Clauses, OMPD_loop, DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
))
10550 return StmtError();
10551
10552 auto *CS = cast<CapturedStmt>(AStmt);
10553 // 1.2.2 OpenMP Language Terminology
10554 // Structured block - An executable statement with a single entry at the
10555 // top and a single exit at the bottom.
10556 // The point of exit cannot be a branch out of the structured block.
10557 // longjmp() and throw() must not violate the entry/exit criteria.
10558 CS->getCapturedDecl()->setNothrow();
10559
10560 OMPLoopDirective::HelperExprs B;
10561 // In presence of clause 'collapse', it will define the nested loops number.
10562 unsigned NestedLoopCount = checkOpenMPLoop(
10563 OMPD_loop, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10564 AStmt, *this, *DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
, VarsWithImplicitDSA, B);
10565 if (NestedLoopCount == 0)
10566 return StmtError();
10567
10568 assert((CurContext->isDependentContext() || B.builtAll()) &&(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 10569, __extension__ __PRETTY_FUNCTION__
))
10569 "omp loop exprs were not built")(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 10569, __extension__ __PRETTY_FUNCTION__
))
;
10570
10571 setFunctionHasBranchProtectedScope();
10572 return OMPGenericLoopDirective::Create(Context, StartLoc, EndLoc,
10573 NestedLoopCount, Clauses, AStmt, B);
10574}
10575
10576StmtResult Sema::ActOnOpenMPTeamsGenericLoopDirective(
10577 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10578 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10579 if (!AStmt)
10580 return StmtError();
10581
10582 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10583 // A list item may not appear in a lastprivate clause unless it is the
10584 // loop iteration variable of a loop that is associated with the construct.
10585 if (checkGenericLoopLastprivate(*this, Clauses, OMPD_teams_loop, DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
))
10586 return StmtError();
10587
10588 auto *CS = cast<CapturedStmt>(AStmt);
10589 // 1.2.2 OpenMP Language Terminology
10590 // Structured block - An executable statement with a single entry at the
10591 // top and a single exit at the bottom.
10592 // The point of exit cannot be a branch out of the structured block.
10593 // longjmp() and throw() must not violate the entry/exit criteria.
10594 CS->getCapturedDecl()->setNothrow();
10595 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_teams_loop);
10596 ThisCaptureLevel > 1; --ThisCaptureLevel) {
10597 CS = cast<CapturedStmt>(CS->getCapturedStmt());
10598 // 1.2.2 OpenMP Language Terminology
10599 // Structured block - An executable statement with a single entry at the
10600 // top and a single exit at the bottom.
10601 // The point of exit cannot be a branch out of the structured block.
10602 // longjmp() and throw() must not violate the entry/exit criteria.
10603 CS->getCapturedDecl()->setNothrow();
10604 }
10605
10606 OMPLoopDirective::HelperExprs B;
10607 // In presence of clause 'collapse', it will define the nested loops number.
10608 unsigned NestedLoopCount =
10609 checkOpenMPLoop(OMPD_teams_loop, getCollapseNumberExpr(Clauses),
10610 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
,
10611 VarsWithImplicitDSA, B);
10612 if (NestedLoopCount == 0)
10613 return StmtError();
10614
10615 assert((CurContext->isDependentContext() || B.builtAll()) &&(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 10616, __extension__ __PRETTY_FUNCTION__
))
10616 "omp loop exprs were not built")(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 10616, __extension__ __PRETTY_FUNCTION__
))
;
10617
10618 setFunctionHasBranchProtectedScope();
10619 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->setParentTeamsRegionLoc(StartLoc);
10620
10621 return OMPTeamsGenericLoopDirective::Create(
10622 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10623}
10624
10625StmtResult Sema::ActOnOpenMPTargetTeamsGenericLoopDirective(
10626 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10627 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10628 if (!AStmt)
10629 return StmtError();
10630
10631 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10632 // A list item may not appear in a lastprivate clause unless it is the
10633 // loop iteration variable of a loop that is associated with the construct.
10634 if (checkGenericLoopLastprivate(*this, Clauses, OMPD_target_teams_loop,
10635 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
))
10636 return StmtError();
10637
10638 auto *CS = cast<CapturedStmt>(AStmt);
10639 // 1.2.2 OpenMP Language Terminology
10640 // Structured block - An executable statement with a single entry at the
10641 // top and a single exit at the bottom.
10642 // The point of exit cannot be a branch out of the structured block.
10643 // longjmp() and throw() must not violate the entry/exit criteria.
10644 CS->getCapturedDecl()->setNothrow();
10645 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_teams_loop);
10646 ThisCaptureLevel > 1; --ThisCaptureLevel) {
10647 CS = cast<CapturedStmt>(CS->getCapturedStmt());
10648 // 1.2.2 OpenMP Language Terminology
10649 // Structured block - An executable statement with a single entry at the
10650 // top and a single exit at the bottom.
10651 // The point of exit cannot be a branch out of the structured block.
10652 // longjmp() and throw() must not violate the entry/exit criteria.
10653 CS->getCapturedDecl()->setNothrow();
10654 }
10655
10656 OMPLoopDirective::HelperExprs B;
10657 // In presence of clause 'collapse', it will define the nested loops number.
10658 unsigned NestedLoopCount =
10659 checkOpenMPLoop(OMPD_target_teams_loop, getCollapseNumberExpr(Clauses),
10660 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
,
10661 VarsWithImplicitDSA, B);
10662 if (NestedLoopCount == 0)
10663 return StmtError();
10664
10665 assert((CurContext->isDependentContext() || B.builtAll()) &&(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 10666, __extension__ __PRETTY_FUNCTION__
))
10666 "omp loop exprs were not built")(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 10666, __extension__ __PRETTY_FUNCTION__
))
;
10667
10668 setFunctionHasBranchProtectedScope();
10669
10670 return OMPTargetTeamsGenericLoopDirective::Create(
10671 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10672}
10673
10674StmtResult Sema::ActOnOpenMPParallelGenericLoopDirective(
10675 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10676 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10677 if (!AStmt)
10678 return StmtError();
10679
10680 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10681 // A list item may not appear in a lastprivate clause unless it is the
10682 // loop iteration variable of a loop that is associated with the construct.
10683 if (checkGenericLoopLastprivate(*this, Clauses, OMPD_parallel_loop, DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
))
10684 return StmtError();
10685
10686 auto *CS = cast<CapturedStmt>(AStmt);
10687 // 1.2.2 OpenMP Language Terminology
10688 // Structured block - An executable statement with a single entry at the
10689 // top and a single exit at the bottom.
10690 // The point of exit cannot be a branch out of the structured block.
10691 // longjmp() and throw() must not violate the entry/exit criteria.
10692 CS->getCapturedDecl()->setNothrow();
10693 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_parallel_loop);
10694 ThisCaptureLevel > 1; --ThisCaptureLevel) {
10695 CS = cast<CapturedStmt>(CS->getCapturedStmt());
10696 // 1.2.2 OpenMP Language Terminology
10697 // Structured block - An executable statement with a single entry at the
10698 // top and a single exit at the bottom.
10699 // The point of exit cannot be a branch out of the structured block.
10700 // longjmp() and throw() must not violate the entry/exit criteria.
10701 CS->getCapturedDecl()->setNothrow();
10702 }
10703
10704 OMPLoopDirective::HelperExprs B;
10705 // In presence of clause 'collapse', it will define the nested loops number.
10706 unsigned NestedLoopCount =
10707 checkOpenMPLoop(OMPD_parallel_loop, getCollapseNumberExpr(Clauses),
10708 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
,
10709 VarsWithImplicitDSA, B);
10710 if (NestedLoopCount == 0)
10711 return StmtError();
10712
10713 assert((CurContext->isDependentContext() || B.builtAll()) &&(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 10714, __extension__ __PRETTY_FUNCTION__
))
10714 "omp loop exprs were not built")(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 10714, __extension__ __PRETTY_FUNCTION__
))
;
10715
10716 setFunctionHasBranchProtectedScope();
10717
10718 return OMPParallelGenericLoopDirective::Create(
10719 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10720}
10721
10722StmtResult Sema::ActOnOpenMPTargetParallelGenericLoopDirective(
10723 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10724 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10725 if (!AStmt)
10726 return StmtError();
10727
10728 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10729 // A list item may not appear in a lastprivate clause unless it is the
10730 // loop iteration variable of a loop that is associated with the construct.
10731 if (checkGenericLoopLastprivate(*this, Clauses, OMPD_target_parallel_loop,
10732 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
))
10733 return StmtError();
10734
10735 auto *CS = cast<CapturedStmt>(AStmt);
10736 // 1.2.2 OpenMP Language Terminology
10737 // Structured block - An executable statement with a single entry at the
10738 // top and a single exit at the bottom.
10739 // The point of exit cannot be a branch out of the structured block.
10740 // longjmp() and throw() must not violate the entry/exit criteria.
10741 CS->getCapturedDecl()->setNothrow();
10742 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_parallel_loop);
10743 ThisCaptureLevel > 1; --ThisCaptureLevel) {
10744 CS = cast<CapturedStmt>(CS->getCapturedStmt());
10745 // 1.2.2 OpenMP Language Terminology
10746 // Structured block - An executable statement with a single entry at the
10747 // top and a single exit at the bottom.
10748 // The point of exit cannot be a branch out of the structured block.
10749 // longjmp() and throw() must not violate the entry/exit criteria.
10750 CS->getCapturedDecl()->setNothrow();
10751 }
10752
10753 OMPLoopDirective::HelperExprs B;
10754 // In presence of clause 'collapse', it will define the nested loops number.
10755 unsigned NestedLoopCount =
10756 checkOpenMPLoop(OMPD_target_parallel_loop, getCollapseNumberExpr(Clauses),
10757 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
,
10758 VarsWithImplicitDSA, B);
10759 if (NestedLoopCount == 0)
10760 return StmtError();
10761
10762 assert((CurContext->isDependentContext() || B.builtAll()) &&(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 10763, __extension__ __PRETTY_FUNCTION__
))
10763 "omp loop exprs were not built")(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 10763, __extension__ __PRETTY_FUNCTION__
))
;
10764
10765 setFunctionHasBranchProtectedScope();
10766
10767 return OMPTargetParallelGenericLoopDirective::Create(
10768 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10769}
10770
10771StmtResult Sema::ActOnOpenMPSingleDirective(ArrayRef<OMPClause *> Clauses,
10772 Stmt *AStmt,
10773 SourceLocation StartLoc,
10774 SourceLocation EndLoc) {
10775 if (!AStmt)
10776 return StmtError();
10777
10778 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected")(static_cast <bool> (isa<CapturedStmt>(AStmt) &&
"Captured statement expected") ? void (0) : __assert_fail ("isa<CapturedStmt>(AStmt) && \"Captured statement expected\""
, "clang/lib/Sema/SemaOpenMP.cpp", 10778, __extension__ __PRETTY_FUNCTION__
))
;
10779
10780 setFunctionHasBranchProtectedScope();
10781
10782 // OpenMP [2.7.3, single Construct, Restrictions]
10783 // The copyprivate clause must not be used with the nowait clause.
10784 const OMPClause *Nowait = nullptr;
10785 const OMPClause *Copyprivate = nullptr;
10786 for (const OMPClause *Clause : Clauses) {
10787 if (Clause->getClauseKind() == OMPC_nowait)
10788 Nowait = Clause;
10789 else if (Clause->getClauseKind() == OMPC_copyprivate)
10790 Copyprivate = Clause;
10791 if (Copyprivate && Nowait) {
10792 Diag(Copyprivate->getBeginLoc(),
10793 diag::err_omp_single_copyprivate_with_nowait);
10794 Diag(Nowait->getBeginLoc(), diag::note_omp_nowait_clause_here);
10795 return StmtError();
10796 }
10797 }
10798
10799 return OMPSingleDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
10800}
10801
10802StmtResult Sema::ActOnOpenMPMasterDirective(Stmt *AStmt,
10803 SourceLocation StartLoc,
10804 SourceLocation EndLoc) {
10805 if (!AStmt)
10806 return StmtError();
10807
10808 setFunctionHasBranchProtectedScope();
10809
10810 return OMPMasterDirective::Create(Context, StartLoc, EndLoc, AStmt);
10811}
10812
10813StmtResult Sema::ActOnOpenMPMaskedDirective(ArrayRef<OMPClause *> Clauses,
10814 Stmt *AStmt,
10815 SourceLocation StartLoc,
10816 SourceLocation EndLoc) {
10817 if (!AStmt)
10818 return StmtError();
10819
10820 setFunctionHasBranchProtectedScope();
10821
10822 return OMPMaskedDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
10823}
10824
10825StmtResult Sema::ActOnOpenMPCriticalDirective(
10826 const DeclarationNameInfo &DirName, ArrayRef<OMPClause *> Clauses,
10827 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
10828 if (!AStmt)
10829 return StmtError();
10830
10831 bool ErrorFound = false;
10832 llvm::APSInt Hint;
10833 SourceLocation HintLoc;
10834 bool DependentHint = false;
10835 for (const OMPClause *C : Clauses) {
10836 if (C->getClauseKind() == OMPC_hint) {
10837 if (!DirName.getName()) {
10838 Diag(C->getBeginLoc(), diag::err_omp_hint_clause_no_name);
10839 ErrorFound = true;
10840 }
10841 Expr *E = cast<OMPHintClause>(C)->getHint();
10842 if (E->isTypeDependent() || E->isValueDependent() ||
10843 E->isInstantiationDependent()) {
10844 DependentHint = true;
10845 } else {
10846 Hint = E->EvaluateKnownConstInt(Context);
10847 HintLoc = C->getBeginLoc();
10848 }
10849 }
10850 }
10851 if (ErrorFound)
10852 return StmtError();
10853 const auto Pair = DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCriticalWithHint(DirName);
10854 if (Pair.first && DirName.getName() && !DependentHint) {
10855 if (llvm::APSInt::compareValues(Hint, Pair.second) != 0) {
10856 Diag(StartLoc, diag::err_omp_critical_with_hint);
10857 if (HintLoc.isValid())
10858 Diag(HintLoc, diag::note_omp_critical_hint_here)
10859 << 0 << toString(Hint, /*Radix=*/10, /*Signed=*/false);
10860 else
10861 Diag(StartLoc, diag::note_omp_critical_no_hint) << 0;
10862 if (const auto *C = Pair.first->getSingleClause<OMPHintClause>()) {
10863 Diag(C->getBeginLoc(), diag::note_omp_critical_hint_here)
10864 << 1
10865 << toString(C->getHint()->EvaluateKnownConstInt(Context),
10866 /*Radix=*/10, /*Signed=*/false);
10867 } else {
10868 Diag(Pair.first->getBeginLoc(), diag::note_omp_critical_no_hint) << 1;
10869 }
10870 }
10871 }
10872
10873 setFunctionHasBranchProtectedScope();
10874
10875 auto *Dir = OMPCriticalDirective::Create(Context, DirName, StartLoc, EndLoc,
10876 Clauses, AStmt);
10877 if (!Pair.first && DirName.getName() && !DependentHint)
10878 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->addCriticalWithHint(Dir, Hint);
10879 return Dir;
10880}
10881
10882StmtResult Sema::ActOnOpenMPParallelForDirective(
10883 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10884 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10885 if (!AStmt)
10886 return StmtError();
10887
10888 auto *CS = cast<CapturedStmt>(AStmt);
10889 // 1.2.2 OpenMP Language Terminology
10890 // Structured block - An executable statement with a single entry at the
10891 // top and a single exit at the bottom.
10892 // The point of exit cannot be a branch out of the structured block.
10893 // longjmp() and throw() must not violate the entry/exit criteria.
10894 CS->getCapturedDecl()->setNothrow();
10895
10896 OMPLoopBasedDirective::HelperExprs B;
10897 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10898 // define the nested loops number.
10899 unsigned NestedLoopCount =
10900 checkOpenMPLoop(OMPD_parallel_for, getCollapseNumberExpr(Clauses),
10901 getOrderedNumberExpr(Clauses), AStmt, *this, *DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
,
10902 VarsWithImplicitDSA, B);
10903 if (NestedLoopCount == 0)
10904 return StmtError();
10905
10906 assert((CurContext->isDependentContext() || B.builtAll()) &&(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp parallel for loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp parallel for loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 10907, __extension__ __PRETTY_FUNCTION__
))
10907 "omp parallel for loop exprs were not built")(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp parallel for loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp parallel for loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 10907, __extension__ __PRETTY_FUNCTION__
))
;
10908
10909 if (!CurContext->isDependentContext()) {
10910 // Finalize the clauses that need pre-built expressions for CodeGen.
10911 for (OMPClause *C : Clauses) {
10912 if (auto *LC = dyn_cast<OMPLinearClause>(C))
10913 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
10914 B.NumIterations, *this, CurScope,
10915 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
))
10916 return StmtError();
10917 }
10918 }
10919
10920 setFunctionHasBranchProtectedScope();
10921 return OMPParallelForDirective::Create(
10922 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10923 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getTaskgroupReductionRef(), DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isCancelRegion());
10924}
10925
10926StmtResult Sema::ActOnOpenMPParallelForSimdDirective(
10927 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10928 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10929 if (!AStmt)
10930 return StmtError();
10931
10932 auto *CS = cast<CapturedStmt>(AStmt);
10933 // 1.2.2 OpenMP Language Terminology
10934 // Structured block - An executable statement with a single entry at the
10935 // top and a single exit at the bottom.
10936 // The point of exit cannot be a branch out of the structured block.
10937 // longjmp() and throw() must not violate the entry/exit criteria.
10938 CS->getCapturedDecl()->setNothrow();
10939
10940 OMPLoopBasedDirective::HelperExprs B;
10941 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10942 // define the nested loops number.
10943 unsigned NestedLoopCount =
10944 checkOpenMPLoop(OMPD_parallel_for_simd, getCollapseNumberExpr(Clauses),
10945 getOrderedNumberExpr(Clauses), AStmt, *this, *DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
,
10946 VarsWithImplicitDSA, B);
10947 if (NestedLoopCount == 0)
10948 return StmtError();
10949
10950 if (!CurContext->isDependentContext()) {
10951 // Finalize the clauses that need pre-built expressions for CodeGen.
10952 for (OMPClause *C : Clauses) {
10953 if (auto *LC = dyn_cast<OMPLinearClause>(C))
10954 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
10955 B.NumIterations, *this, CurScope,
10956 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
))
10957 return StmtError();
10958 }
10959 }
10960
10961 if (checkSimdlenSafelenSpecified(*this, Clauses))
10962 return StmtError();
10963
10964 setFunctionHasBranchProtectedScope();
10965 return OMPParallelForSimdDirective::Create(
10966 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10967}
10968
10969StmtResult
10970Sema::ActOnOpenMPParallelMasterDirective(ArrayRef<OMPClause *> Clauses,
10971 Stmt *AStmt, SourceLocation StartLoc,
10972 SourceLocation EndLoc) {
10973 if (!AStmt)
10974 return StmtError();
10975
10976 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected")(static_cast <bool> (isa<CapturedStmt>(AStmt) &&
"Captured statement expected") ? void (0) : __assert_fail ("isa<CapturedStmt>(AStmt) && \"Captured statement expected\""
, "clang/lib/Sema/SemaOpenMP.cpp", 10976, __extension__ __PRETTY_FUNCTION__
))
;
10977 auto *CS = cast<CapturedStmt>(AStmt);
10978 // 1.2.2 OpenMP Language Terminology
10979 // Structured block - An executable statement with a single entry at the
10980 // top and a single exit at the bottom.
10981 // The point of exit cannot be a branch out of the structured block.
10982 // longjmp() and throw() must not violate the entry/exit criteria.
10983 CS->getCapturedDecl()->setNothrow();
10984
10985 setFunctionHasBranchProtectedScope();
10986
10987 return OMPParallelMasterDirective::Create(
10988 Context, StartLoc, EndLoc, Clauses, AStmt,
10989 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getTaskgroupReductionRef());
10990}
10991
10992StmtResult
10993Sema::ActOnOpenMPParallelMaskedDirective(ArrayRef<OMPClause *> Clauses,
10994 Stmt *AStmt, SourceLocation StartLoc,
10995 SourceLocation EndLoc) {
10996 if (!AStmt)
10997 return StmtError();
10998
10999 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected")(static_cast <bool> (isa<CapturedStmt>(AStmt) &&
"Captured statement expected") ? void (0) : __assert_fail ("isa<CapturedStmt>(AStmt) && \"Captured statement expected\""
, "clang/lib/Sema/SemaOpenMP.cpp", 10999, __extension__ __PRETTY_FUNCTION__
))
;
11000 auto *CS = cast<CapturedStmt>(AStmt);
11001 // 1.2.2 OpenMP Language Terminology
11002 // Structured block - An executable statement with a single entry at the
11003 // top and a single exit at the bottom.
11004 // The point of exit cannot be a branch out of the structured block.
11005 // longjmp() and throw() must not violate the entry/exit criteria.
11006 CS->getCapturedDecl()->setNothrow();
11007
11008 setFunctionHasBranchProtectedScope();
11009
11010 return OMPParallelMaskedDirective::Create(
11011 Context, StartLoc, EndLoc, Clauses, AStmt,
11012 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getTaskgroupReductionRef());
11013}
11014
11015StmtResult
11016Sema::ActOnOpenMPParallelSectionsDirective(ArrayRef<OMPClause *> Clauses,
11017 Stmt *AStmt, SourceLocation StartLoc,
11018 SourceLocation EndLoc) {
11019 if (!AStmt)
11020 return StmtError();
11021
11022 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected")(static_cast <bool> (isa<CapturedStmt>(AStmt) &&
"Captured statement expected") ? void (0) : __assert_fail ("isa<CapturedStmt>(AStmt) && \"Captured statement expected\""
, "clang/lib/Sema/SemaOpenMP.cpp", 11022, __extension__ __PRETTY_FUNCTION__
))
;
11023 auto BaseStmt = AStmt;
11024 while (auto *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt))
11025 BaseStmt = CS->getCapturedStmt();
11026 if (auto *C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) {
11027 auto S = C->children();
11028 if (S.begin() == S.end())
11029 return StmtError();
11030 // All associated statements must be '#pragma omp section' except for
11031 // the first one.
11032 for (Stmt *SectionStmt : llvm::drop_begin(S)) {
11033 if (!SectionStmt || !isa<OMPSectionDirective>(SectionStmt)) {
11034 if (SectionStmt)
11035 Diag(SectionStmt->getBeginLoc(),
11036 diag::err_omp_parallel_sections_substmt_not_section);
11037 return StmtError();
11038 }
11039 cast<OMPSectionDirective>(SectionStmt)
11040 ->setHasCancel(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isCancelRegion());
11041 }
11042 } else {
11043 Diag(AStmt->getBeginLoc(),
11044 diag::err_omp_parallel_sections_not_compound_stmt);
11045 return StmtError();
11046 }
11047
11048 setFunctionHasBranchProtectedScope();
11049
11050 return OMPParallelSectionsDirective::Create(
11051 Context, StartLoc, EndLoc, Clauses, AStmt,
11052 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getTaskgroupReductionRef(), DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isCancelRegion());
11053}
11054
11055/// Find and diagnose mutually exclusive clause kinds.
11056static bool checkMutuallyExclusiveClauses(
11057 Sema &S, ArrayRef<OMPClause *> Clauses,
11058 ArrayRef<OpenMPClauseKind> MutuallyExclusiveClauses) {
11059 const OMPClause *PrevClause = nullptr;
11060 bool ErrorFound = false;
11061 for (const OMPClause *C : Clauses) {
11062 if (llvm::is_contained(MutuallyExclusiveClauses, C->getClauseKind())) {
11063 if (!PrevClause) {
11064 PrevClause = C;
11065 } else if (PrevClause->getClauseKind() != C->getClauseKind()) {
11066 S.Diag(C->getBeginLoc(), diag::err_omp_clauses_mutually_exclusive)
11067 << getOpenMPClauseName(C->getClauseKind())
11068 << getOpenMPClauseName(PrevClause->getClauseKind());
11069 S.Diag(PrevClause->getBeginLoc(), diag::note_omp_previous_clause)
11070 << getOpenMPClauseName(PrevClause->getClauseKind());
11071 ErrorFound = true;
11072 }
11073 }
11074 }
11075 return ErrorFound;
11076}
11077
11078StmtResult Sema::ActOnOpenMPTaskDirective(ArrayRef<OMPClause *> Clauses,
11079 Stmt *AStmt, SourceLocation StartLoc,
11080 SourceLocation EndLoc) {
11081 if (!AStmt)
11082 return StmtError();
11083
11084 // OpenMP 5.0, 2.10.1 task Construct
11085 // If a detach clause appears on the directive, then a mergeable clause cannot
11086 // appear on the same directive.
11087 if (checkMutuallyExclusiveClauses(*this, Clauses,
11088 {OMPC_detach, OMPC_mergeable}))
11089 return StmtError();
11090
11091 auto *CS = cast<CapturedStmt>(AStmt);
11092 // 1.2.2 OpenMP Language Terminology
11093 // Structured block - An executable statement with a single entry at the
11094 // top and a single exit at the bottom.
11095 // The point of exit cannot be a branch out of the structured block.
11096 // longjmp() and throw() must not violate the entry/exit criteria.
11097 CS->getCapturedDecl()->setNothrow();
11098
11099 setFunctionHasBranchProtectedScope();
11100
11101 return OMPTaskDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
11102 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isCancelRegion());
11103}
11104
11105StmtResult Sema::ActOnOpenMPTaskyieldDirective(SourceLocation StartLoc,
11106 SourceLocation EndLoc) {
11107 return OMPTaskyieldDirective::Create(Context, StartLoc, EndLoc);
11108}
11109
11110StmtResult Sema::ActOnOpenMPBarrierDirective(SourceLocation StartLoc,
11111 SourceLocation EndLoc) {
11112 return OMPBarrierDirective::Create(Context, StartLoc, EndLoc);
11113}
11114
11115StmtResult Sema::ActOnOpenMPErrorDirective(ArrayRef<OMPClause *> Clauses,
11116 SourceLocation StartLoc,
11117 SourceLocation EndLoc,
11118 bool InExContext) {
11119 const OMPAtClause *AtC =
11120 OMPExecutableDirective::getSingleClause<OMPAtClause>(Clauses);
11121
11122 if (AtC && !InExContext && AtC->getAtKind() == OMPC_AT_execution) {
11123 Diag(AtC->getAtKindKwLoc(), diag::err_omp_unexpected_execution_modifier);
11124 return StmtError();
11125 }
11126
11127 const OMPSeverityClause *SeverityC =
11128 OMPExecutableDirective::getSingleClause<OMPSeverityClause>(Clauses);
11129 const OMPMessageClause *MessageC =
11130 OMPExecutableDirective::getSingleClause<OMPMessageClause>(Clauses);
11131 Expr *ME = MessageC ? MessageC->getMessageString() : nullptr;
11132
11133 if (!AtC || AtC->getAtKind() == OMPC_AT_compilation) {
11134 if (SeverityC && SeverityC->getSeverityKind() == OMPC_SEVERITY_warning)
11135 Diag(SeverityC->getSeverityKindKwLoc(), diag::warn_diagnose_if_succeeded)
11136 << (ME ? cast<StringLiteral>(ME)->getString() : "WARNING");
11137 else
11138 Diag(StartLoc, diag::err_diagnose_if_succeeded)
11139 << (ME ? cast<StringLiteral>(ME)->getString() : "ERROR");
11140 if (!SeverityC || SeverityC->getSeverityKind() != OMPC_SEVERITY_warning)
11141 return StmtError();
11142 }
11143 return OMPErrorDirective::Create(Context, StartLoc, EndLoc, Clauses);
11144}
11145
11146StmtResult Sema::ActOnOpenMPTaskwaitDirective(ArrayRef<OMPClause *> Clauses,
11147 SourceLocation StartLoc,
11148 SourceLocation EndLoc) {
11149 const OMPNowaitClause *NowaitC =
11150 OMPExecutableDirective::getSingleClause<OMPNowaitClause>(Clauses);
11151 bool HasDependC =
11152 !OMPExecutableDirective::getClausesOfKind<OMPDependClause>(Clauses)
11153 .empty();
11154 if (NowaitC && !HasDependC) {
11155 Diag(StartLoc, diag::err_omp_nowait_clause_without_depend);
11156 return StmtError();
11157 }
11158
11159 return OMPTaskwaitDirective::Create(Context, StartLoc, EndLoc, Clauses);
11160}
11161
11162StmtResult Sema::ActOnOpenMPTaskgroupDirective(ArrayRef<OMPClause *> Clauses,
11163 Stmt *AStmt,
11164 SourceLocation StartLoc,
11165 SourceLocation EndLoc) {
11166 if (!AStmt)
11167 return StmtError();
11168
11169 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected")(static_cast <bool> (isa<CapturedStmt>(AStmt) &&
"Captured statement expected") ? void (0) : __assert_fail ("isa<CapturedStmt>(AStmt) && \"Captured statement expected\""
, "clang/lib/Sema/SemaOpenMP.cpp", 11169, __extension__ __PRETTY_FUNCTION__
))
;
11170
11171 setFunctionHasBranchProtectedScope();
11172
11173 return OMPTaskgroupDirective::Create(Context, StartLoc, EndLoc, Clauses,
11174 AStmt,
11175 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getTaskgroupReductionRef());
11176}
11177
11178StmtResult Sema::ActOnOpenMPFlushDirective(ArrayRef<OMPClause *> Clauses,
11179 SourceLocation StartLoc,
11180 SourceLocation EndLoc) {
11181 OMPFlushClause *FC = nullptr;
11182 OMPClause *OrderClause = nullptr;
11183 for (OMPClause *C : Clauses) {
11184 if (C->getClauseKind() == OMPC_flush)
11185 FC = cast<OMPFlushClause>(C);
11186 else
11187 OrderClause = C;
11188 }
11189 OpenMPClauseKind MemOrderKind = OMPC_unknown;
11190 SourceLocation MemOrderLoc;
11191 for (const OMPClause *C : Clauses) {
11192 if (C->getClauseKind() == OMPC_acq_rel ||
11193 C->getClauseKind() == OMPC_acquire ||
11194 C->getClauseKind() == OMPC_release) {
11195 if (MemOrderKind != OMPC_unknown) {
11196 Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
11197 << getOpenMPDirectiveName(OMPD_flush) << 1
11198 << SourceRange(C->getBeginLoc(), C->getEndLoc());
11199 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
11200 << getOpenMPClauseName(MemOrderKind);
11201 } else {
11202 MemOrderKind = C->getClauseKind();
11203 MemOrderLoc = C->getBeginLoc();
11204 }
11205 }
11206 }
11207 if (FC && OrderClause) {
11208 Diag(FC->getLParenLoc(), diag::err_omp_flush_order_clause_and_list)
11209 << getOpenMPClauseName(OrderClause->getClauseKind());
11210 Diag(OrderClause->getBeginLoc(), diag::note_omp_flush_order_clause_here)
11211 << getOpenMPClauseName(OrderClause->getClauseKind());
11212 return StmtError();
11213 }
11214 return OMPFlushDirective::Create(Context, StartLoc, EndLoc, Clauses);
11215}
11216
11217StmtResult Sema::ActOnOpenMPDepobjDirective(ArrayRef<OMPClause *> Clauses,
11218 SourceLocation StartLoc,
11219 SourceLocation EndLoc) {
11220 if (Clauses.empty()) {
11221 Diag(StartLoc, diag::err_omp_depobj_expected);
11222 return StmtError();
11223 } else if (Clauses[0]->getClauseKind() != OMPC_depobj) {
11224 Diag(Clauses[0]->getBeginLoc(), diag::err_omp_depobj_expected);
11225 return StmtError();
11226 }
11227 // Only depobj expression and another single clause is allowed.
11228 if (Clauses.size() > 2) {
11229 Diag(Clauses[2]->getBeginLoc(),
11230 diag::err_omp_depobj_single_clause_expected);
11231 return StmtError();
11232 } else if (Clauses.size() < 1) {
11233 Diag(Clauses[0]->getEndLoc(), diag::err_omp_depobj_single_clause_expected);
11234 return StmtError();
11235 }
11236 return OMPDepobjDirective::Create(Context, StartLoc, EndLoc, Clauses);
11237}
11238
11239StmtResult Sema::ActOnOpenMPScanDirective(ArrayRef<OMPClause *> Clauses,
11240 SourceLocation StartLoc,
11241 SourceLocation EndLoc) {
11242 // Check that exactly one clause is specified.
11243 if (Clauses.size() != 1) {
11244 Diag(Clauses.empty() ? EndLoc : Clauses[1]->getBeginLoc(),
11245 diag::err_omp_scan_single_clause_expected);
11246 return StmtError();
11247 }
11248 // Check that scan directive is used in the scopeof the OpenMP loop body.
11249 if (Scope *S = DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurScope()) {
11250 Scope *ParentS = S->getParent();
11251 if (!ParentS || ParentS->getParent() != ParentS->getBreakParent() ||
11252 !ParentS->getBreakParent()->isOpenMPLoopScope())
11253 return StmtError(Diag(StartLoc, diag::err_omp_orphaned_device_directive)
11254 << getOpenMPDirectiveName(OMPD_scan) << 5);
11255 }
11256 // Check that only one instance of scan directives is used in the same outer
11257 // region.
11258 if (DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->doesParentHasScanDirective()) {
11259 Diag(StartLoc, diag::err_omp_several_directives_in_region) << "scan";
11260 Diag(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getParentScanDirectiveLoc(),
11261 diag::note_omp_previous_directive)
11262 << "scan";
11263 return StmtError();
11264 }
11265 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->setParentHasScanDirective(StartLoc);
11266 return OMPScanDirective::Create(Context, StartLoc, EndLoc, Clauses);
11267}
11268
11269StmtResult Sema::ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses,
11270 Stmt *AStmt,
11271 SourceLocation StartLoc,
11272 SourceLocation EndLoc) {
11273 const OMPClause *DependFound = nullptr;
11274 const OMPClause *DependSourceClause = nullptr;
11275 const OMPClause *DependSinkClause = nullptr;
11276 bool ErrorFound = false;
11277 const OMPThreadsClause *TC = nullptr;
11278 const OMPSIMDClause *SC = nullptr;
11279 for (const OMPClause *C : Clauses) {
11280 if (auto *DC = dyn_cast<OMPDependClause>(C)) {
11281 DependFound = C;
11282 if (DC->getDependencyKind() == OMPC_DEPEND_source) {
11283 if (DependSourceClause) {
11284 Diag(C->getBeginLoc(), diag::err_omp_more_one_clause)
11285 << getOpenMPDirectiveName(OMPD_ordered)
11286 << getOpenMPClauseName(OMPC_depend) << 2;
11287 ErrorFound = true;
11288 } else {
11289 DependSourceClause = C;
11290 }
11291 if (DependSinkClause) {
11292 Diag(C->getBeginLoc(), diag::err_omp_depend_sink_source_not_allowed)
11293 << 0;
11294 ErrorFound = true;
11295 }
11296 } else if (DC->getDependencyKind() == OMPC_DEPEND_sink) {
11297 if (DependSourceClause) {
11298 Diag(C->getBeginLoc(), diag::err_omp_depend_sink_source_not_allowed)
11299 << 1;
11300 ErrorFound = true;
11301 }
11302 DependSinkClause = C;
11303 }
11304 } else if (C->getClauseKind() == OMPC_threads) {
11305 TC = cast<OMPThreadsClause>(C);
11306 } else if (C->getClauseKind() == OMPC_simd) {
11307 SC = cast<OMPSIMDClause>(C);
11308 }
11309 }
11310 if (!ErrorFound && !SC &&
11311 isOpenMPSimdDirective(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getParentDirective())) {
11312 // OpenMP [2.8.1,simd Construct, Restrictions]
11313 // An ordered construct with the simd clause is the only OpenMP construct
11314 // that can appear in the simd region.
11315 Diag(StartLoc, diag::err_omp_prohibited_region_simd)
11316 << (LangOpts.OpenMP >= 50 ? 1 : 0);
11317 ErrorFound = true;
11318 } else if (DependFound && (TC || SC)) {
11319 Diag(DependFound->getBeginLoc(), diag::err_omp_depend_clause_thread_simd)
11320 << getOpenMPClauseName(TC ? TC->getClauseKind() : SC->getClauseKind());
11321 ErrorFound = true;
11322 } else if (DependFound && !DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getParentOrderedRegionParam().first) {
11323 Diag(DependFound->getBeginLoc(),
11324 diag::err_omp_ordered_directive_without_param);
11325 ErrorFound = true;
11326 } else if (TC || Clauses.empty()) {
11327 if (const Expr *Param = DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getParentOrderedRegionParam().first) {
11328 SourceLocation ErrLoc = TC ? TC->getBeginLoc() : StartLoc;
11329 Diag(ErrLoc, diag::err_omp_ordered_directive_with_param)
11330 << (TC != nullptr);
11331 Diag(Param->getBeginLoc(), diag::note_omp_ordered_param) << 1;
11332 ErrorFound = true;
11333 }
11334 }
11335 if ((!AStmt && !DependFound) || ErrorFound)
11336 return StmtError();
11337
11338 // OpenMP 5.0, 2.17.9, ordered Construct, Restrictions.
11339 // During execution of an iteration of a worksharing-loop or a loop nest
11340 // within a worksharing-loop, simd, or worksharing-loop SIMD region, a thread
11341 // must not execute more than one ordered region corresponding to an ordered
11342 // construct without a depend clause.
11343 if (!DependFound) {
11344 if (DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->doesParentHasOrderedDirective()) {
11345 Diag(StartLoc, diag::err_omp_several_directives_in_region) << "ordered";
11346 Diag(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getParentOrderedDirectiveLoc(),
11347 diag::note_omp_previous_directive)
11348 << "ordered";
11349 return StmtError();
11350 }
11351 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->setParentHasOrderedDirective(StartLoc);
11352 }
11353
11354 if (AStmt) {
11355 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected")(static_cast <bool> (isa<CapturedStmt>(AStmt) &&
"Captured statement expected") ? void (0) : __assert_fail ("isa<CapturedStmt>(AStmt) && \"Captured statement expected\""
, "clang/lib/Sema/SemaOpenMP.cpp", 11355, __extension__ __PRETTY_FUNCTION__
))
;
11356
11357 setFunctionHasBranchProtectedScope();
11358 }
11359
11360 return OMPOrderedDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
11361}
11362
11363namespace {
11364/// Helper class for checking expression in 'omp atomic [update]'
11365/// construct.
11366class OpenMPAtomicUpdateChecker {
11367 /// Error results for atomic update expressions.
11368 enum ExprAnalysisErrorCode {
11369 /// A statement is not an expression statement.
11370 NotAnExpression,
11371 /// Expression is not builtin binary or unary operation.
11372 NotABinaryOrUnaryExpression,
11373 /// Unary operation is not post-/pre- increment/decrement operation.
11374 NotAnUnaryIncDecExpression,
11375 /// An expression is not of scalar type.
11376 NotAScalarType,
11377 /// A binary operation is not an assignment operation.
11378 NotAnAssignmentOp,
11379 /// RHS part of the binary operation is not a binary expression.
11380 NotABinaryExpression,
11381 /// RHS part is not additive/multiplicative/shift/biwise binary
11382 /// expression.
11383 NotABinaryOperator,
11384 /// RHS binary operation does not have reference to the updated LHS
11385 /// part.
11386 NotAnUpdateExpression,
11387 /// No errors is found.
11388 NoError
11389 };
11390 /// Reference to Sema.
11391 Sema &SemaRef;
11392 /// A location for note diagnostics (when error is found).
11393 SourceLocation NoteLoc;
11394 /// 'x' lvalue part of the source atomic expression.
11395 Expr *X;
11396 /// 'expr' rvalue part of the source atomic expression.
11397 Expr *E;
11398 /// Helper expression of the form
11399 /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11400 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11401 Expr *UpdateExpr;
11402 /// Is 'x' a LHS in a RHS part of full update expression. It is
11403 /// important for non-associative operations.
11404 bool IsXLHSInRHSPart;
11405 BinaryOperatorKind Op;
11406 SourceLocation OpLoc;
11407 /// true if the source expression is a postfix unary operation, false
11408 /// if it is a prefix unary operation.
11409 bool IsPostfixUpdate;
11410
11411public:
11412 OpenMPAtomicUpdateChecker(Sema &SemaRef)
11413 : SemaRef(SemaRef), X(nullptr), E(nullptr), UpdateExpr(nullptr),
11414 IsXLHSInRHSPart(false), Op(BO_PtrMemD), IsPostfixUpdate(false) {}
11415 /// Check specified statement that it is suitable for 'atomic update'
11416 /// constructs and extract 'x', 'expr' and Operation from the original
11417 /// expression. If DiagId and NoteId == 0, then only check is performed
11418 /// without error notification.
11419 /// \param DiagId Diagnostic which should be emitted if error is found.
11420 /// \param NoteId Diagnostic note for the main error message.
11421 /// \return true if statement is not an update expression, false otherwise.
11422 bool checkStatement(Stmt *S, unsigned DiagId = 0, unsigned NoteId = 0);
11423 /// Return the 'x' lvalue part of the source atomic expression.
11424 Expr *getX() const { return X; }
11425 /// Return the 'expr' rvalue part of the source atomic expression.
11426 Expr *getExpr() const { return E; }
11427 /// Return the update expression used in calculation of the updated
11428 /// value. Always has form 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11429 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11430 Expr *getUpdateExpr() const { return UpdateExpr; }
11431 /// Return true if 'x' is LHS in RHS part of full update expression,
11432 /// false otherwise.
11433 bool isXLHSInRHSPart() const { return IsXLHSInRHSPart; }
11434
11435 /// true if the source expression is a postfix unary operation, false
11436 /// if it is a prefix unary operation.
11437 bool isPostfixUpdate() const { return IsPostfixUpdate; }
11438
11439private:
11440 bool checkBinaryOperation(BinaryOperator *AtomicBinOp, unsigned DiagId = 0,
11441 unsigned NoteId = 0);
11442};
11443
11444bool OpenMPAtomicUpdateChecker::checkBinaryOperation(
11445 BinaryOperator *AtomicBinOp, unsigned DiagId, unsigned NoteId) {
11446 ExprAnalysisErrorCode ErrorFound = NoError;
11447 SourceLocation ErrorLoc, NoteLoc;
11448 SourceRange ErrorRange, NoteRange;
11449 // Allowed constructs are:
11450 // x = x binop expr;
11451 // x = expr binop x;
11452 if (AtomicBinOp->getOpcode() == BO_Assign) {
11453 X = AtomicBinOp->getLHS();
11454 if (const auto *AtomicInnerBinOp = dyn_cast<BinaryOperator>(
11455 AtomicBinOp->getRHS()->IgnoreParenImpCasts())) {
11456 if (AtomicInnerBinOp->isMultiplicativeOp() ||
11457 AtomicInnerBinOp->isAdditiveOp() || AtomicInnerBinOp->isShiftOp() ||
11458 AtomicInnerBinOp->isBitwiseOp()) {
11459 Op = AtomicInnerBinOp->getOpcode();
11460 OpLoc = AtomicInnerBinOp->getOperatorLoc();
11461 Expr *LHS = AtomicInnerBinOp->getLHS();
11462 Expr *RHS = AtomicInnerBinOp->getRHS();
11463 llvm::FoldingSetNodeID XId, LHSId, RHSId;
11464 X->IgnoreParenImpCasts()->Profile(XId, SemaRef.getASTContext(),
11465 /*Canonical=*/true);
11466 LHS->IgnoreParenImpCasts()->Profile(LHSId, SemaRef.getASTContext(),
11467 /*Canonical=*/true);
11468 RHS->IgnoreParenImpCasts()->Profile(RHSId, SemaRef.getASTContext(),
11469 /*Canonical=*/true);
11470 if (XId == LHSId) {
11471 E = RHS;
11472 IsXLHSInRHSPart = true;
11473 } else if (XId == RHSId) {
11474 E = LHS;
11475 IsXLHSInRHSPart = false;
11476 } else {
11477 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11478 ErrorRange = AtomicInnerBinOp->getSourceRange();
11479 NoteLoc = X->getExprLoc();
11480 NoteRange = X->getSourceRange();
11481 ErrorFound = NotAnUpdateExpression;
11482 }
11483 } else {
11484 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11485 ErrorRange = AtomicInnerBinOp->getSourceRange();
11486 NoteLoc = AtomicInnerBinOp->getOperatorLoc();
11487 NoteRange = SourceRange(NoteLoc, NoteLoc);
11488 ErrorFound = NotABinaryOperator;
11489 }
11490 } else {
11491 NoteLoc = ErrorLoc = AtomicBinOp->getRHS()->getExprLoc();
11492 NoteRange = ErrorRange = AtomicBinOp->getRHS()->getSourceRange();
11493 ErrorFound = NotABinaryExpression;
11494 }
11495 } else {
11496 ErrorLoc = AtomicBinOp->getExprLoc();
11497 ErrorRange = AtomicBinOp->getSourceRange();
11498 NoteLoc = AtomicBinOp->getOperatorLoc();
11499 NoteRange = SourceRange(NoteLoc, NoteLoc);
11500 ErrorFound = NotAnAssignmentOp;
11501 }
11502 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11503 SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange;
11504 SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11505 return true;
11506 }
11507 if (SemaRef.CurContext->isDependentContext())
11508 E = X = UpdateExpr = nullptr;
11509 return ErrorFound != NoError;
11510}
11511
11512bool OpenMPAtomicUpdateChecker::checkStatement(Stmt *S, unsigned DiagId,
11513 unsigned NoteId) {
11514 ExprAnalysisErrorCode ErrorFound = NoError;
11515 SourceLocation ErrorLoc, NoteLoc;
11516 SourceRange ErrorRange, NoteRange;
11517 // Allowed constructs are:
11518 // x++;
11519 // x--;
11520 // ++x;
11521 // --x;
11522 // x binop= expr;
11523 // x = x binop expr;
11524 // x = expr binop x;
11525 if (auto *AtomicBody = dyn_cast<Expr>(S)) {
11526 AtomicBody = AtomicBody->IgnoreParenImpCasts();
11527 if (AtomicBody->getType()->isScalarType() ||
11528 AtomicBody->isInstantiationDependent()) {
11529 if (const auto *AtomicCompAssignOp = dyn_cast<CompoundAssignOperator>(
11530 AtomicBody->IgnoreParenImpCasts())) {
11531 // Check for Compound Assignment Operation
11532 Op = BinaryOperator::getOpForCompoundAssignment(
11533 AtomicCompAssignOp->getOpcode());
11534 OpLoc = AtomicCompAssignOp->getOperatorLoc();
11535 E = AtomicCompAssignOp->getRHS();
11536 X = AtomicCompAssignOp->getLHS()->IgnoreParens();
11537 IsXLHSInRHSPart = true;
11538 } else if (auto *AtomicBinOp = dyn_cast<BinaryOperator>(
11539 AtomicBody->IgnoreParenImpCasts())) {
11540 // Check for Binary Operation
11541 if (checkBinaryOperation(AtomicBinOp, DiagId, NoteId))
11542 return true;
11543 } else if (const auto *AtomicUnaryOp = dyn_cast<UnaryOperator>(
11544 AtomicBody->IgnoreParenImpCasts())) {
11545 // Check for Unary Operation
11546 if (AtomicUnaryOp->isIncrementDecrementOp()) {
11547 IsPostfixUpdate = AtomicUnaryOp->isPostfix();
11548 Op = AtomicUnaryOp->isIncrementOp() ? BO_Add : BO_Sub;
11549 OpLoc = AtomicUnaryOp->getOperatorLoc();
11550 X = AtomicUnaryOp->getSubExpr()->IgnoreParens();
11551 E = SemaRef.ActOnIntegerConstant(OpLoc, /*uint64_t Val=*/1).get();
11552 IsXLHSInRHSPart = true;
11553 } else {
11554 ErrorFound = NotAnUnaryIncDecExpression;
11555 ErrorLoc = AtomicUnaryOp->getExprLoc();
11556 ErrorRange = AtomicUnaryOp->getSourceRange();
11557 NoteLoc = AtomicUnaryOp->getOperatorLoc();
11558 NoteRange = SourceRange(NoteLoc, NoteLoc);
11559 }
11560 } else if (!AtomicBody->isInstantiationDependent()) {
11561 ErrorFound = NotABinaryOrUnaryExpression;
11562 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11563 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11564 }
11565 } else {
11566 ErrorFound = NotAScalarType;
11567 NoteLoc = ErrorLoc = AtomicBody->getBeginLoc();
11568 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
11569 }
11570 } else {
11571 ErrorFound = NotAnExpression;
11572 NoteLoc = ErrorLoc = S->getBeginLoc();
11573 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
11574 }
11575 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11576 SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange;
11577 SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11578 return true;
11579 }
11580 if (SemaRef.CurContext->isDependentContext())
11581 E = X = UpdateExpr = nullptr;
11582 if (ErrorFound == NoError && E && X) {
11583 // Build an update expression of form 'OpaqueValueExpr(x) binop
11584 // OpaqueValueExpr(expr)' or 'OpaqueValueExpr(expr) binop
11585 // OpaqueValueExpr(x)' and then cast it to the type of the 'x' expression.
11586 auto *OVEX = new (SemaRef.getASTContext())
11587 OpaqueValueExpr(X->getExprLoc(), X->getType(), VK_PRValue);
11588 auto *OVEExpr = new (SemaRef.getASTContext())
11589 OpaqueValueExpr(E->getExprLoc(), E->getType(), VK_PRValue);
11590 ExprResult Update =
11591 SemaRef.CreateBuiltinBinOp(OpLoc, Op, IsXLHSInRHSPart ? OVEX : OVEExpr,
11592 IsXLHSInRHSPart ? OVEExpr : OVEX);
11593 if (Update.isInvalid())
11594 return true;
11595 Update = SemaRef.PerformImplicitConversion(Update.get(), X->getType(),
11596 Sema::AA_Casting);
11597 if (Update.isInvalid())
11598 return true;
11599 UpdateExpr = Update.get();
11600 }
11601 return ErrorFound != NoError;
11602}
11603
11604/// Get the node id of the fixed point of an expression \a S.
11605llvm::FoldingSetNodeID getNodeId(ASTContext &Context, const Expr *S) {
11606 llvm::FoldingSetNodeID Id;
11607 S->IgnoreParenImpCasts()->Profile(Id, Context, true);
11608 return Id;
11609}
11610
11611/// Check if two expressions are same.
11612bool checkIfTwoExprsAreSame(ASTContext &Context, const Expr *LHS,
11613 const Expr *RHS) {
11614 return getNodeId(Context, LHS) == getNodeId(Context, RHS);
11615}
11616
11617class OpenMPAtomicCompareChecker {
11618public:
11619 /// All kinds of errors that can occur in `atomic compare`
11620 enum ErrorTy {
11621 /// Empty compound statement.
11622 NoStmt = 0,
11623 /// More than one statement in a compound statement.
11624 MoreThanOneStmt,
11625 /// Not an assignment binary operator.
11626 NotAnAssignment,
11627 /// Not a conditional operator.
11628 NotCondOp,
11629 /// Wrong false expr. According to the spec, 'x' should be at the false
11630 /// expression of a conditional expression.
11631 WrongFalseExpr,
11632 /// The condition of a conditional expression is not a binary operator.
11633 NotABinaryOp,
11634 /// Invalid binary operator (not <, >, or ==).
11635 InvalidBinaryOp,
11636 /// Invalid comparison (not x == e, e == x, x ordop expr, or expr ordop x).
11637 InvalidComparison,
11638 /// X is not a lvalue.
11639 XNotLValue,
11640 /// Not a scalar.
11641 NotScalar,
11642 /// Not an integer.
11643 NotInteger,
11644 /// 'else' statement is not expected.
11645 UnexpectedElse,
11646 /// Not an equality operator.
11647 NotEQ,
11648 /// Invalid assignment (not v == x).
11649 InvalidAssignment,
11650 /// Not if statement
11651 NotIfStmt,
11652 /// More than two statements in a compund statement.
11653 MoreThanTwoStmts,
11654 /// Not a compound statement.
11655 NotCompoundStmt,
11656 /// No else statement.
11657 NoElse,
11658 /// Not 'if (r)'.
11659 InvalidCondition,
11660 /// No error.
11661 NoError,
11662 };
11663
11664 struct ErrorInfoTy {
11665 ErrorTy Error;
11666 SourceLocation ErrorLoc;
11667 SourceRange ErrorRange;
11668 SourceLocation NoteLoc;
11669 SourceRange NoteRange;
11670 };
11671
11672 OpenMPAtomicCompareChecker(Sema &S) : ContextRef(S.getASTContext()) {}
11673
11674 /// Check if statement \a S is valid for <tt>atomic compare</tt>.
11675 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11676
11677 Expr *getX() const { return X; }
11678 Expr *getE() const { return E; }
11679 Expr *getD() const { return D; }
11680 Expr *getCond() const { return C; }
11681 bool isXBinopExpr() const { return IsXBinopExpr; }
11682
11683protected:
11684 /// Reference to ASTContext
11685 ASTContext &ContextRef;
11686 /// 'x' lvalue part of the source atomic expression.
11687 Expr *X = nullptr;
11688 /// 'expr' or 'e' rvalue part of the source atomic expression.
11689 Expr *E = nullptr;
11690 /// 'd' rvalue part of the source atomic expression.
11691 Expr *D = nullptr;
11692 /// 'cond' part of the source atomic expression. It is in one of the following
11693 /// forms:
11694 /// expr ordop x
11695 /// x ordop expr
11696 /// x == e
11697 /// e == x
11698 Expr *C = nullptr;
11699 /// True if the cond expr is in the form of 'x ordop expr'.
11700 bool IsXBinopExpr = true;
11701
11702 /// Check if it is a valid conditional update statement (cond-update-stmt).
11703 bool checkCondUpdateStmt(IfStmt *S, ErrorInfoTy &ErrorInfo);
11704
11705 /// Check if it is a valid conditional expression statement (cond-expr-stmt).
11706 bool checkCondExprStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11707
11708 /// Check if all captured values have right type.
11709 bool checkType(ErrorInfoTy &ErrorInfo) const;
11710
11711 static bool CheckValue(const Expr *E, ErrorInfoTy &ErrorInfo,
11712 bool ShouldBeLValue, bool ShouldBeInteger = false) {
11713 if (E->isInstantiationDependent())
11714 return true;
11715
11716 if (ShouldBeLValue && !E->isLValue()) {
11717 ErrorInfo.Error = ErrorTy::XNotLValue;
11718 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11719 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11720 return false;
11721 }
11722
11723 QualType QTy = E->getType();
11724 if (!QTy->isScalarType()) {
11725 ErrorInfo.Error = ErrorTy::NotScalar;
11726 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11727 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11728 return false;
11729 }
11730 if (ShouldBeInteger && !QTy->isIntegerType()) {
11731 ErrorInfo.Error = ErrorTy::NotInteger;
11732 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11733 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11734 return false;
11735 }
11736
11737 return true;
11738 }
11739 };
11740
11741bool OpenMPAtomicCompareChecker::checkCondUpdateStmt(IfStmt *S,
11742 ErrorInfoTy &ErrorInfo) {
11743 auto *Then = S->getThen();
11744 if (auto *CS = dyn_cast<CompoundStmt>(Then)) {
11745 if (CS->body_empty()) {
11746 ErrorInfo.Error = ErrorTy::NoStmt;
11747 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11748 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11749 return false;
11750 }
11751 if (CS->size() > 1) {
11752 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11753 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11754 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
11755 return false;
11756 }
11757 Then = CS->body_front();
11758 }
11759
11760 auto *BO = dyn_cast<BinaryOperator>(Then);
11761 if (!BO) {
11762 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11763 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
11764 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
11765 return false;
11766 }
11767 if (BO->getOpcode() != BO_Assign) {
11768 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11769 ErrorInfo.ErrorLoc = BO->getExprLoc();
11770 ErrorInfo.NoteLoc = BO->getOperatorLoc();
11771 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
11772 return false;
11773 }
11774
11775 X = BO->getLHS();
11776
11777 auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
11778 if (!Cond) {
11779 ErrorInfo.Error = ErrorTy::NotABinaryOp;
11780 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
11781 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
11782 return false;
11783 }
11784
11785 switch (Cond->getOpcode()) {
11786 case BO_EQ: {
11787 C = Cond;
11788 D = BO->getRHS();
11789 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS())) {
11790 E = Cond->getRHS();
11791 } else if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
11792 E = Cond->getLHS();
11793 } else {
11794 ErrorInfo.Error = ErrorTy::InvalidComparison;
11795 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11796 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11797 return false;
11798 }
11799 break;
11800 }
11801 case BO_LT:
11802 case BO_GT: {
11803 E = BO->getRHS();
11804 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS()) &&
11805 checkIfTwoExprsAreSame(ContextRef, E, Cond->getRHS())) {
11806 C = Cond;
11807 } else if (checkIfTwoExprsAreSame(ContextRef, E, Cond->getLHS()) &&
11808 checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
11809 C = Cond;
11810 IsXBinopExpr = false;
11811 } else {
11812 ErrorInfo.Error = ErrorTy::InvalidComparison;
11813 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11814 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11815 return false;
11816 }
11817 break;
11818 }
11819 default:
11820 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
11821 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11822 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11823 return false;
11824 }
11825
11826 if (S->getElse()) {
11827 ErrorInfo.Error = ErrorTy::UnexpectedElse;
11828 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getElse()->getBeginLoc();
11829 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getElse()->getSourceRange();
11830 return false;
11831 }
11832
11833 return true;
11834}
11835
11836bool OpenMPAtomicCompareChecker::checkCondExprStmt(Stmt *S,
11837 ErrorInfoTy &ErrorInfo) {
11838 auto *BO = dyn_cast<BinaryOperator>(S);
11839 if (!BO) {
11840 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11841 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
11842 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
11843 return false;
11844 }
11845 if (BO->getOpcode() != BO_Assign) {
11846 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11847 ErrorInfo.ErrorLoc = BO->getExprLoc();
11848 ErrorInfo.NoteLoc = BO->getOperatorLoc();
11849 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
11850 return false;
11851 }
11852
11853 X = BO->getLHS();
11854
11855 auto *CO = dyn_cast<ConditionalOperator>(BO->getRHS()->IgnoreParenImpCasts());
11856 if (!CO) {
11857 ErrorInfo.Error = ErrorTy::NotCondOp;
11858 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getRHS()->getExprLoc();
11859 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getRHS()->getSourceRange();
11860 return false;
11861 }
11862
11863 if (!checkIfTwoExprsAreSame(ContextRef, X, CO->getFalseExpr())) {
11864 ErrorInfo.Error = ErrorTy::WrongFalseExpr;
11865 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getFalseExpr()->getExprLoc();
11866 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11867 CO->getFalseExpr()->getSourceRange();
11868 return false;
11869 }
11870
11871 auto *Cond = dyn_cast<BinaryOperator>(CO->getCond());
11872 if (!Cond) {
11873 ErrorInfo.Error = ErrorTy::NotABinaryOp;
11874 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
11875 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11876 CO->getCond()->getSourceRange();
11877 return false;
11878 }
11879
11880 switch (Cond->getOpcode()) {
11881 case BO_EQ: {
11882 C = Cond;
11883 D = CO->getTrueExpr();
11884 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS())) {
11885 E = Cond->getRHS();
11886 } else if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
11887 E = Cond->getLHS();
11888 } else {
11889 ErrorInfo.Error = ErrorTy::InvalidComparison;
11890 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11891 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11892 return false;
11893 }
11894 break;
11895 }
11896 case BO_LT:
11897 case BO_GT: {
11898 E = CO->getTrueExpr();
11899 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS()) &&
11900 checkIfTwoExprsAreSame(ContextRef, E, Cond->getRHS())) {
11901 C = Cond;
11902 } else if (checkIfTwoExprsAreSame(ContextRef, E, Cond->getLHS()) &&
11903 checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
11904 C = Cond;
11905 IsXBinopExpr = false;
11906 } else {
11907 ErrorInfo.Error = ErrorTy::InvalidComparison;
11908 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11909 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11910 return false;
11911 }
11912 break;
11913 }
11914 default:
11915 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
11916 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11917 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11918 return false;
11919 }
11920
11921 return true;
11922}
11923
11924bool OpenMPAtomicCompareChecker::checkType(ErrorInfoTy &ErrorInfo) const {
11925 // 'x' and 'e' cannot be nullptr
11926 assert(X && E && "X and E cannot be nullptr")(static_cast <bool> (X && E && "X and E cannot be nullptr"
) ? void (0) : __assert_fail ("X && E && \"X and E cannot be nullptr\""
, "clang/lib/Sema/SemaOpenMP.cpp", 11926, __extension__ __PRETTY_FUNCTION__
))
;
11927
11928 if (!CheckValue(X, ErrorInfo, true))
11929 return false;
11930
11931 if (!CheckValue(E, ErrorInfo, false))
11932 return false;
11933
11934 if (D && !CheckValue(D, ErrorInfo, false))
11935 return false;
11936
11937 return true;
11938}
11939
11940bool OpenMPAtomicCompareChecker::checkStmt(
11941 Stmt *S, OpenMPAtomicCompareChecker::ErrorInfoTy &ErrorInfo) {
11942 auto *CS = dyn_cast<CompoundStmt>(S);
11943 if (CS) {
11944 if (CS->body_empty()) {
11945 ErrorInfo.Error = ErrorTy::NoStmt;
11946 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11947 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11948 return false;
11949 }
11950
11951 if (CS->size() != 1) {
11952 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11953 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11954 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11955 return false;
11956 }
11957 S = CS->body_front();
11958 }
11959
11960 auto Res = false;
11961
11962 if (auto *IS = dyn_cast<IfStmt>(S)) {
11963 // Check if the statement is in one of the following forms
11964 // (cond-update-stmt):
11965 // if (expr ordop x) { x = expr; }
11966 // if (x ordop expr) { x = expr; }
11967 // if (x == e) { x = d; }
11968 Res = checkCondUpdateStmt(IS, ErrorInfo);
11969 } else {
11970 // Check if the statement is in one of the following forms (cond-expr-stmt):
11971 // x = expr ordop x ? expr : x;
11972 // x = x ordop expr ? expr : x;
11973 // x = x == e ? d : x;
11974 Res = checkCondExprStmt(S, ErrorInfo);
11975 }
11976
11977 if (!Res)
11978 return false;
11979
11980 return checkType(ErrorInfo);
11981}
11982
11983class OpenMPAtomicCompareCaptureChecker final
11984 : public OpenMPAtomicCompareChecker {
11985public:
11986 OpenMPAtomicCompareCaptureChecker(Sema &S) : OpenMPAtomicCompareChecker(S) {}
11987
11988 Expr *getV() const { return V; }
11989 Expr *getR() const { return R; }
11990 bool isFailOnly() const { return IsFailOnly; }
11991 bool isPostfixUpdate() const { return IsPostfixUpdate; }
11992
11993 /// Check if statement \a S is valid for <tt>atomic compare capture</tt>.
11994 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11995
11996private:
11997 bool checkType(ErrorInfoTy &ErrorInfo);
11998
11999 // NOTE: Form 3, 4, 5 in the following comments mean the 3rd, 4th, and 5th
12000 // form of 'conditional-update-capture-atomic' structured block on the v5.2
12001 // spec p.p. 82:
12002 // (1) { v = x; cond-update-stmt }
12003 // (2) { cond-update-stmt v = x; }
12004 // (3) if(x == e) { x = d; } else { v = x; }
12005 // (4) { r = x == e; if(r) { x = d; } }
12006 // (5) { r = x == e; if(r) { x = d; } else { v = x; } }
12007
12008 /// Check if it is valid 'if(x == e) { x = d; } else { v = x; }' (form 3)
12009 bool checkForm3(IfStmt *S, ErrorInfoTy &ErrorInfo);
12010
12011 /// Check if it is valid '{ r = x == e; if(r) { x = d; } }',
12012 /// or '{ r = x == e; if(r) { x = d; } else { v = x; } }' (form 4 and 5)
12013 bool checkForm45(Stmt *S, ErrorInfoTy &ErrorInfo);
12014
12015 /// 'v' lvalue part of the source atomic expression.
12016 Expr *V = nullptr;
12017 /// 'r' lvalue part of the source atomic expression.
12018 Expr *R = nullptr;
12019 /// If 'v' is only updated when the comparison fails.
12020 bool IsFailOnly = false;
12021 /// If original value of 'x' must be stored in 'v', not an updated one.
12022 bool IsPostfixUpdate = false;
12023};
12024
12025bool OpenMPAtomicCompareCaptureChecker::checkType(ErrorInfoTy &ErrorInfo) {
12026 if (!OpenMPAtomicCompareChecker::checkType(ErrorInfo))
12027 return false;
12028
12029 if (V && !CheckValue(V, ErrorInfo, true))
12030 return false;
12031
12032 if (R && !CheckValue(R, ErrorInfo, true, true))
12033 return false;
12034
12035 return true;
12036}
12037
12038bool OpenMPAtomicCompareCaptureChecker::checkForm3(IfStmt *S,
12039 ErrorInfoTy &ErrorInfo) {
12040 IsFailOnly = true;
12041
12042 auto *Then = S->getThen();
12043 if (auto *CS = dyn_cast<CompoundStmt>(Then)) {
12044 if (CS->body_empty()) {
12045 ErrorInfo.Error = ErrorTy::NoStmt;
12046 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12047 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12048 return false;
12049 }
12050 if (CS->size() > 1) {
12051 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12052 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12053 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12054 return false;
12055 }
12056 Then = CS->body_front();
12057 }
12058
12059 auto *BO = dyn_cast<BinaryOperator>(Then);
12060 if (!BO) {
12061 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12062 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
12063 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
12064 return false;
12065 }
12066 if (BO->getOpcode() != BO_Assign) {
12067 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12068 ErrorInfo.ErrorLoc = BO->getExprLoc();
12069 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12070 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12071 return false;
12072 }
12073
12074 X = BO->getLHS();
12075 D = BO->getRHS();
12076
12077 auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
12078 if (!Cond) {
12079 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12080 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12081 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12082 return false;
12083 }
12084 if (Cond->getOpcode() != BO_EQ) {
12085 ErrorInfo.Error = ErrorTy::NotEQ;
12086 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12087 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12088 return false;
12089 }
12090
12091 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS())) {
12092 E = Cond->getRHS();
12093 } else if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
12094 E = Cond->getLHS();
12095 } else {
12096 ErrorInfo.Error = ErrorTy::InvalidComparison;
12097 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12098 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12099 return false;
12100 }
12101
12102 C = Cond;
12103
12104 if (!S->getElse()) {
12105 ErrorInfo.Error = ErrorTy::NoElse;
12106 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12107 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12108 return false;
12109 }
12110
12111 auto *Else = S->getElse();
12112 if (auto *CS = dyn_cast<CompoundStmt>(Else)) {
12113 if (CS->body_empty()) {
12114 ErrorInfo.Error = ErrorTy::NoStmt;
12115 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12116 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12117 return false;
12118 }
12119 if (CS->size() > 1) {
12120 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12121 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12122 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12123 return false;
12124 }
12125 Else = CS->body_front();
12126 }
12127
12128 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12129 if (!ElseBO) {
12130 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12131 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12132 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12133 return false;
12134 }
12135 if (ElseBO->getOpcode() != BO_Assign) {
12136 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12137 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12138 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12139 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12140 return false;
12141 }
12142
12143 if (!checkIfTwoExprsAreSame(ContextRef, X, ElseBO->getRHS())) {
12144 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12145 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseBO->getRHS()->getExprLoc();
12146 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12147 ElseBO->getRHS()->getSourceRange();
12148 return false;
12149 }
12150
12151 V = ElseBO->getLHS();
12152
12153 return checkType(ErrorInfo);
12154}
12155
12156bool OpenMPAtomicCompareCaptureChecker::checkForm45(Stmt *S,
12157 ErrorInfoTy &ErrorInfo) {
12158 // We don't check here as they should be already done before call this
12159 // function.
12160 auto *CS = cast<CompoundStmt>(S);
12161 assert(CS->size() == 2 && "CompoundStmt size is not expected")(static_cast <bool> (CS->size() == 2 && "CompoundStmt size is not expected"
) ? void (0) : __assert_fail ("CS->size() == 2 && \"CompoundStmt size is not expected\""
, "clang/lib/Sema/SemaOpenMP.cpp", 12161, __extension__ __PRETTY_FUNCTION__
))
;
12162 auto *S1 = cast<BinaryOperator>(CS->body_front());
12163 auto *S2 = cast<IfStmt>(CS->body_back());
12164 assert(S1->getOpcode() == BO_Assign && "unexpected binary operator")(static_cast <bool> (S1->getOpcode() == BO_Assign &&
"unexpected binary operator") ? void (0) : __assert_fail ("S1->getOpcode() == BO_Assign && \"unexpected binary operator\""
, "clang/lib/Sema/SemaOpenMP.cpp", 12164, __extension__ __PRETTY_FUNCTION__
))
;
12165
12166 if (!checkIfTwoExprsAreSame(ContextRef, S1->getLHS(), S2->getCond())) {
12167 ErrorInfo.Error = ErrorTy::InvalidCondition;
12168 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getCond()->getExprLoc();
12169 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S1->getLHS()->getSourceRange();
12170 return false;
12171 }
12172
12173 R = S1->getLHS();
12174
12175 auto *Then = S2->getThen();
12176 if (auto *ThenCS = dyn_cast<CompoundStmt>(Then)) {
12177 if (ThenCS->body_empty()) {
12178 ErrorInfo.Error = ErrorTy::NoStmt;
12179 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12180 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12181 return false;
12182 }
12183 if (ThenCS->size() > 1) {
12184 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12185 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12186 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12187 return false;
12188 }
12189 Then = ThenCS->body_front();
12190 }
12191
12192 auto *ThenBO = dyn_cast<BinaryOperator>(Then);
12193 if (!ThenBO) {
12194 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12195 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getBeginLoc();
12196 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S2->getSourceRange();
12197 return false;
12198 }
12199 if (ThenBO->getOpcode() != BO_Assign) {
12200 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12201 ErrorInfo.ErrorLoc = ThenBO->getExprLoc();
12202 ErrorInfo.NoteLoc = ThenBO->getOperatorLoc();
12203 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenBO->getSourceRange();
12204 return false;
12205 }
12206
12207 X = ThenBO->getLHS();
12208 D = ThenBO->getRHS();
12209
12210 auto *BO = cast<BinaryOperator>(S1->getRHS()->IgnoreImpCasts());
12211 if (BO->getOpcode() != BO_EQ) {
12212 ErrorInfo.Error = ErrorTy::NotEQ;
12213 ErrorInfo.ErrorLoc = BO->getExprLoc();
12214 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12215 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12216 return false;
12217 }
12218
12219 C = BO;
12220
12221 if (checkIfTwoExprsAreSame(ContextRef, X, BO->getLHS())) {
12222 E = BO->getRHS();
12223 } else if (checkIfTwoExprsAreSame(ContextRef, X, BO->getRHS())) {
12224 E = BO->getLHS();
12225 } else {
12226 ErrorInfo.Error = ErrorTy::InvalidComparison;
12227 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getExprLoc();
12228 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12229 return false;
12230 }
12231
12232 if (S2->getElse()) {
12233 IsFailOnly = true;
12234
12235 auto *Else = S2->getElse();
12236 if (auto *ElseCS = dyn_cast<CompoundStmt>(Else)) {
12237 if (ElseCS->body_empty()) {
12238 ErrorInfo.Error = ErrorTy::NoStmt;
12239 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12240 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12241 return false;
12242 }
12243 if (ElseCS->size() > 1) {
12244 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12245 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12246 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12247 return false;
12248 }
12249 Else = ElseCS->body_front();
12250 }
12251
12252 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12253 if (!ElseBO) {
12254 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12255 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12256 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12257 return false;
12258 }
12259 if (ElseBO->getOpcode() != BO_Assign) {
12260 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12261 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12262 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12263 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12264 return false;
12265 }
12266 if (!checkIfTwoExprsAreSame(ContextRef, X, ElseBO->getRHS())) {
12267 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12268 ErrorInfo.ErrorLoc = ElseBO->getRHS()->getExprLoc();
12269 ErrorInfo.NoteLoc = X->getExprLoc();
12270 ErrorInfo.ErrorRange = ElseBO->getRHS()->getSourceRange();
12271 ErrorInfo.NoteRange = X->getSourceRange();
12272 return false;
12273 }
12274
12275 V = ElseBO->getLHS();
12276 }
12277
12278 return checkType(ErrorInfo);
12279}
12280
12281bool OpenMPAtomicCompareCaptureChecker::checkStmt(Stmt *S,
12282 ErrorInfoTy &ErrorInfo) {
12283 // if(x == e) { x = d; } else { v = x; }
12284 if (auto *IS = dyn_cast<IfStmt>(S))
12285 return checkForm3(IS, ErrorInfo);
12286
12287 auto *CS = dyn_cast<CompoundStmt>(S);
12288 if (!CS) {
12289 ErrorInfo.Error = ErrorTy::NotCompoundStmt;
12290 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12291 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12292 return false;
12293 }
12294 if (CS->body_empty()) {
12295 ErrorInfo.Error = ErrorTy::NoStmt;
12296 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12297 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12298 return false;
12299 }
12300
12301 // { if(x == e) { x = d; } else { v = x; } }
12302 if (CS->size() == 1) {
12303 auto *IS = dyn_cast<IfStmt>(CS->body_front());
12304 if (!IS) {
12305 ErrorInfo.Error = ErrorTy::NotIfStmt;
12306 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->body_front()->getBeginLoc();
12307 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12308 CS->body_front()->getSourceRange();
12309 return false;
12310 }
12311
12312 return checkForm3(IS, ErrorInfo);
12313 } else if (CS->size() == 2) {
12314 auto *S1 = CS->body_front();
12315 auto *S2 = CS->body_back();
12316
12317 Stmt *UpdateStmt = nullptr;
12318 Stmt *CondUpdateStmt = nullptr;
12319 Stmt *CondExprStmt = nullptr;
12320
12321 if (auto *BO = dyn_cast<BinaryOperator>(S1)) {
12322 // It could be one of the following cases:
12323 // { v = x; cond-update-stmt }
12324 // { v = x; cond-expr-stmt }
12325 // { cond-expr-stmt; v = x; }
12326 // form 45
12327 if (isa<BinaryOperator>(BO->getRHS()->IgnoreImpCasts()) ||
12328 isa<ConditionalOperator>(BO->getRHS()->IgnoreImpCasts())) {
12329 // check if form 45
12330 if (isa<IfStmt>(S2))
12331 return checkForm45(CS, ErrorInfo);
12332 // { cond-expr-stmt; v = x; }
12333 CondExprStmt = S1;
12334 UpdateStmt = S2;
12335 } else {
12336 IsPostfixUpdate = true;
12337 UpdateStmt = S1;
12338 if (isa<IfStmt>(S2)) {
12339 // { v = x; cond-update-stmt }
12340 CondUpdateStmt = S2;
12341 } else {
12342 // { v = x; cond-expr-stmt }
12343 CondExprStmt = S2;
12344 }
12345 }
12346 } else {
12347 // { cond-update-stmt v = x; }
12348 UpdateStmt = S2;
12349 CondUpdateStmt = S1;
12350 }
12351
12352 auto CheckCondUpdateStmt = [this, &ErrorInfo](Stmt *CUS) {
12353 auto *IS = dyn_cast<IfStmt>(CUS);
12354 if (!IS) {
12355 ErrorInfo.Error = ErrorTy::NotIfStmt;
12356 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CUS->getBeginLoc();
12357 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CUS->getSourceRange();
12358 return false;
12359 }
12360
12361 return checkCondUpdateStmt(IS, ErrorInfo);
12362 };
12363
12364 // CheckUpdateStmt has to be called *after* CheckCondUpdateStmt.
12365 auto CheckUpdateStmt = [this, &ErrorInfo](Stmt *US) {
12366 auto *BO = dyn_cast<BinaryOperator>(US);
12367 if (!BO) {
12368 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12369 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = US->getBeginLoc();
12370 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = US->getSourceRange();
12371 return false;
12372 }
12373 if (BO->getOpcode() != BO_Assign) {
12374 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12375 ErrorInfo.ErrorLoc = BO->getExprLoc();
12376 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12377 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12378 return false;
12379 }
12380 if (!checkIfTwoExprsAreSame(ContextRef, this->X, BO->getRHS())) {
12381 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12382 ErrorInfo.ErrorLoc = BO->getRHS()->getExprLoc();
12383 ErrorInfo.NoteLoc = this->X->getExprLoc();
12384 ErrorInfo.ErrorRange = BO->getRHS()->getSourceRange();
12385 ErrorInfo.NoteRange = this->X->getSourceRange();
12386 return false;
12387 }
12388
12389 this->V = BO->getLHS();
12390
12391 return true;
12392 };
12393
12394 if (CondUpdateStmt && !CheckCondUpdateStmt(CondUpdateStmt))
12395 return false;
12396 if (CondExprStmt && !checkCondExprStmt(CondExprStmt, ErrorInfo))
12397 return false;
12398 if (!CheckUpdateStmt(UpdateStmt))
12399 return false;
12400 } else {
12401 ErrorInfo.Error = ErrorTy::MoreThanTwoStmts;
12402 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12403 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12404 return false;
12405 }
12406
12407 return checkType(ErrorInfo);
12408}
12409} // namespace
12410
12411StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
12412 Stmt *AStmt,
12413 SourceLocation StartLoc,
12414 SourceLocation EndLoc) {
12415 // Register location of the first atomic directive.
12416 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->addAtomicDirectiveLoc(StartLoc);
12417 if (!AStmt)
12418 return StmtError();
12419
12420 // 1.2.2 OpenMP Language Terminology
12421 // Structured block - An executable statement with a single entry at the
12422 // top and a single exit at the bottom.
12423 // The point of exit cannot be a branch out of the structured block.
12424 // longjmp() and throw() must not violate the entry/exit criteria.
12425 OpenMPClauseKind AtomicKind = OMPC_unknown;
12426 SourceLocation AtomicKindLoc;
12427 OpenMPClauseKind MemOrderKind = OMPC_unknown;
12428 SourceLocation MemOrderLoc;
12429 bool MutexClauseEncountered = false;
12430 llvm::SmallSet<OpenMPClauseKind, 2> EncounteredAtomicKinds;
12431 for (const OMPClause *C : Clauses) {
12432 switch (C->getClauseKind()) {
12433 case OMPC_read:
12434 case OMPC_write:
12435 case OMPC_update:
12436 MutexClauseEncountered = true;
12437 [[fallthrough]];
12438 case OMPC_capture:
12439 case OMPC_compare: {
12440 if (AtomicKind != OMPC_unknown && MutexClauseEncountered) {
12441 Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12442 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12443 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12444 << getOpenMPClauseName(AtomicKind);
12445 } else {
12446 AtomicKind = C->getClauseKind();
12447 AtomicKindLoc = C->getBeginLoc();
12448 if (!EncounteredAtomicKinds.insert(C->getClauseKind()).second) {
12449 Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12450 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12451 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12452 << getOpenMPClauseName(AtomicKind);
12453 }
12454 }
12455 break;
12456 }
12457 case OMPC_seq_cst:
12458 case OMPC_acq_rel:
12459 case OMPC_acquire:
12460 case OMPC_release:
12461 case OMPC_relaxed: {
12462 if (MemOrderKind != OMPC_unknown) {
12463 Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
12464 << getOpenMPDirectiveName(OMPD_atomic) << 0
12465 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12466 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12467 << getOpenMPClauseName(MemOrderKind);
12468 } else {
12469 MemOrderKind = C->getClauseKind();
12470 MemOrderLoc = C->getBeginLoc();
12471 }
12472 break;
12473 }
12474 // The following clauses are allowed, but we don't need to do anything here.
12475 case OMPC_hint:
12476 break;
12477 default:
12478 llvm_unreachable("unknown clause is encountered")::llvm::llvm_unreachable_internal("unknown clause is encountered"
, "clang/lib/Sema/SemaOpenMP.cpp", 12478)
;
12479 }
12480 }
12481 bool IsCompareCapture = false;
12482 if (EncounteredAtomicKinds.contains(OMPC_compare) &&
12483 EncounteredAtomicKinds.contains(OMPC_capture)) {
12484 IsCompareCapture = true;
12485 AtomicKind = OMPC_compare;
12486 }
12487 // OpenMP 5.0, 2.17.7 atomic Construct, Restrictions
12488 // If atomic-clause is read then memory-order-clause must not be acq_rel or
12489 // release.
12490 // If atomic-clause is write then memory-order-clause must not be acq_rel or
12491 // acquire.
12492 // If atomic-clause is update or not present then memory-order-clause must not
12493 // be acq_rel or acquire.
12494 if ((AtomicKind == OMPC_read &&
12495 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_release)) ||
12496 ((AtomicKind == OMPC_write || AtomicKind == OMPC_update ||
12497 AtomicKind == OMPC_unknown) &&
12498 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_acquire))) {
12499 SourceLocation Loc = AtomicKindLoc;
12500 if (AtomicKind == OMPC_unknown)
12501 Loc = StartLoc;
12502 Diag(Loc, diag::err_omp_atomic_incompatible_mem_order_clause)
12503 << getOpenMPClauseName(AtomicKind)
12504 << (AtomicKind == OMPC_unknown ? 1 : 0)
12505 << getOpenMPClauseName(MemOrderKind);
12506 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12507 << getOpenMPClauseName(MemOrderKind);
12508 }
12509
12510 Stmt *Body = AStmt;
12511 if (auto *EWC = dyn_cast<ExprWithCleanups>(Body))
12512 Body = EWC->getSubExpr();
12513
12514 Expr *X = nullptr;
12515 Expr *V = nullptr;
12516 Expr *E = nullptr;
12517 Expr *UE = nullptr;
12518 Expr *D = nullptr;
12519 Expr *CE = nullptr;
12520 Expr *R = nullptr;
12521 bool IsXLHSInRHSPart = false;
12522 bool IsPostfixUpdate = false;
12523 bool IsFailOnly = false;
12524 // OpenMP [2.12.6, atomic Construct]
12525 // In the next expressions:
12526 // * x and v (as applicable) are both l-value expressions with scalar type.
12527 // * During the execution of an atomic region, multiple syntactic
12528 // occurrences of x must designate the same storage location.
12529 // * Neither of v and expr (as applicable) may access the storage location
12530 // designated by x.
12531 // * Neither of x and expr (as applicable) may access the storage location
12532 // designated by v.
12533 // * expr is an expression with scalar type.
12534 // * binop is one of +, *, -, /, &, ^, |, <<, or >>.
12535 // * binop, binop=, ++, and -- are not overloaded operators.
12536 // * The expression x binop expr must be numerically equivalent to x binop
12537 // (expr). This requirement is satisfied if the operators in expr have
12538 // precedence greater than binop, or by using parentheses around expr or
12539 // subexpressions of expr.
12540 // * The expression expr binop x must be numerically equivalent to (expr)
12541 // binop x. This requirement is satisfied if the operators in expr have
12542 // precedence equal to or greater than binop, or by using parentheses around
12543 // expr or subexpressions of expr.
12544 // * For forms that allow multiple occurrences of x, the number of times
12545 // that x is evaluated is unspecified.
12546 if (AtomicKind == OMPC_read) {
12547 enum {
12548 NotAnExpression,
12549 NotAnAssignmentOp,
12550 NotAScalarType,
12551 NotAnLValue,
12552 NoError
12553 } ErrorFound = NoError;
12554 SourceLocation ErrorLoc, NoteLoc;
12555 SourceRange ErrorRange, NoteRange;
12556 // If clause is read:
12557 // v = x;
12558 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12559 const auto *AtomicBinOp =
12560 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12561 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12562 X = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
12563 V = AtomicBinOp->getLHS()->IgnoreParenImpCasts();
12564 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
12565 (V->isInstantiationDependent() || V->getType()->isScalarType())) {
12566 if (!X->isLValue() || !V->isLValue()) {
12567 const Expr *NotLValueExpr = X->isLValue() ? V : X;
12568 ErrorFound = NotAnLValue;
12569 ErrorLoc = AtomicBinOp->getExprLoc();
12570 ErrorRange = AtomicBinOp->getSourceRange();
12571 NoteLoc = NotLValueExpr->getExprLoc();
12572 NoteRange = NotLValueExpr->getSourceRange();
12573 }
12574 } else if (!X->isInstantiationDependent() ||
12575 !V->isInstantiationDependent()) {
12576 const Expr *NotScalarExpr =
12577 (X->isInstantiationDependent() || X->getType()->isScalarType())
12578 ? V
12579 : X;
12580 ErrorFound = NotAScalarType;
12581 ErrorLoc = AtomicBinOp->getExprLoc();
12582 ErrorRange = AtomicBinOp->getSourceRange();
12583 NoteLoc = NotScalarExpr->getExprLoc();
12584 NoteRange = NotScalarExpr->getSourceRange();
12585 }
12586 } else if (!AtomicBody->isInstantiationDependent()) {
12587 ErrorFound = NotAnAssignmentOp;
12588 ErrorLoc = AtomicBody->getExprLoc();
12589 ErrorRange = AtomicBody->getSourceRange();
12590 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12591 : AtomicBody->getExprLoc();
12592 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12593 : AtomicBody->getSourceRange();
12594 }
12595 } else {
12596 ErrorFound = NotAnExpression;
12597 NoteLoc = ErrorLoc = Body->getBeginLoc();
12598 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
12599 }
12600 if (ErrorFound != NoError) {
12601 Diag(ErrorLoc, diag::err_omp_atomic_read_not_expression_statement)
12602 << ErrorRange;
12603 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12604 << ErrorFound << NoteRange;
12605 return StmtError();
12606 }
12607 if (CurContext->isDependentContext())
12608 V = X = nullptr;
12609 } else if (AtomicKind == OMPC_write) {
12610 enum {
12611 NotAnExpression,
12612 NotAnAssignmentOp,
12613 NotAScalarType,
12614 NotAnLValue,
12615 NoError
12616 } ErrorFound = NoError;
12617 SourceLocation ErrorLoc, NoteLoc;
12618 SourceRange ErrorRange, NoteRange;
12619 // If clause is write:
12620 // x = expr;
12621 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12622 const auto *AtomicBinOp =
12623 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12624 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12625 X = AtomicBinOp->getLHS();
12626 E = AtomicBinOp->getRHS();
12627 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
12628 (E->isInstantiationDependent() || E->getType()->isScalarType())) {
12629 if (!X->isLValue()) {
12630 ErrorFound = NotAnLValue;
12631 ErrorLoc = AtomicBinOp->getExprLoc();
12632 ErrorRange = AtomicBinOp->getSourceRange();
12633 NoteLoc = X->getExprLoc();
12634 NoteRange = X->getSourceRange();
12635 }
12636 } else if (!X->isInstantiationDependent() ||
12637 !E->isInstantiationDependent()) {
12638 const Expr *NotScalarExpr =
12639 (X->isInstantiationDependent() || X->getType()->isScalarType())
12640 ? E
12641 : X;
12642 ErrorFound = NotAScalarType;
12643 ErrorLoc = AtomicBinOp->getExprLoc();
12644 ErrorRange = AtomicBinOp->getSourceRange();
12645 NoteLoc = NotScalarExpr->getExprLoc();
12646 NoteRange = NotScalarExpr->getSourceRange();
12647 }
12648 } else if (!AtomicBody->isInstantiationDependent()) {
12649 ErrorFound = NotAnAssignmentOp;
12650 ErrorLoc = AtomicBody->getExprLoc();
12651 ErrorRange = AtomicBody->getSourceRange();
12652 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12653 : AtomicBody->getExprLoc();
12654 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12655 : AtomicBody->getSourceRange();
12656 }
12657 } else {
12658 ErrorFound = NotAnExpression;
12659 NoteLoc = ErrorLoc = Body->getBeginLoc();
12660 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
12661 }
12662 if (ErrorFound != NoError) {
12663 Diag(ErrorLoc, diag::err_omp_atomic_write_not_expression_statement)
12664 << ErrorRange;
12665 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12666 << ErrorFound << NoteRange;
12667 return StmtError();
12668 }
12669 if (CurContext->isDependentContext())
12670 E = X = nullptr;
12671 } else if (AtomicKind == OMPC_update || AtomicKind == OMPC_unknown) {
12672 // If clause is update:
12673 // x++;
12674 // x--;
12675 // ++x;
12676 // --x;
12677 // x binop= expr;
12678 // x = x binop expr;
12679 // x = expr binop x;
12680 OpenMPAtomicUpdateChecker Checker(*this);
12681 if (Checker.checkStatement(
12682 Body,
12683 (AtomicKind == OMPC_update)
12684 ? diag::err_omp_atomic_update_not_expression_statement
12685 : diag::err_omp_atomic_not_expression_statement,
12686 diag::note_omp_atomic_update))
12687 return StmtError();
12688 if (!CurContext->isDependentContext()) {
12689 E = Checker.getExpr();
12690 X = Checker.getX();
12691 UE = Checker.getUpdateExpr();
12692 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12693 }
12694 } else if (AtomicKind == OMPC_capture) {
12695 enum {
12696 NotAnAssignmentOp,
12697 NotACompoundStatement,
12698 NotTwoSubstatements,
12699 NotASpecificExpression,
12700 NoError
12701 } ErrorFound = NoError;
12702 SourceLocation ErrorLoc, NoteLoc;
12703 SourceRange ErrorRange, NoteRange;
12704 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12705 // If clause is a capture:
12706 // v = x++;
12707 // v = x--;
12708 // v = ++x;
12709 // v = --x;
12710 // v = x binop= expr;
12711 // v = x = x binop expr;
12712 // v = x = expr binop x;
12713 const auto *AtomicBinOp =
12714 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12715 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12716 V = AtomicBinOp->getLHS();
12717 Body = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
12718 OpenMPAtomicUpdateChecker Checker(*this);
12719 if (Checker.checkStatement(
12720 Body, diag::err_omp_atomic_capture_not_expression_statement,
12721 diag::note_omp_atomic_update))
12722 return StmtError();
12723 E = Checker.getExpr();
12724 X = Checker.getX();
12725 UE = Checker.getUpdateExpr();
12726 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12727 IsPostfixUpdate = Checker.isPostfixUpdate();
12728 } else if (!AtomicBody->isInstantiationDependent()) {
12729 ErrorLoc = AtomicBody->getExprLoc();
12730 ErrorRange = AtomicBody->getSourceRange();
12731 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12732 : AtomicBody->getExprLoc();
12733 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12734 : AtomicBody->getSourceRange();
12735 ErrorFound = NotAnAssignmentOp;
12736 }
12737 if (ErrorFound != NoError) {
12738 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_expression_statement)
12739 << ErrorRange;
12740 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
12741 return StmtError();
12742 }
12743 if (CurContext->isDependentContext())
12744 UE = V = E = X = nullptr;
12745 } else {
12746 // If clause is a capture:
12747 // { v = x; x = expr; }
12748 // { v = x; x++; }
12749 // { v = x; x--; }
12750 // { v = x; ++x; }
12751 // { v = x; --x; }
12752 // { v = x; x binop= expr; }
12753 // { v = x; x = x binop expr; }
12754 // { v = x; x = expr binop x; }
12755 // { x++; v = x; }
12756 // { x--; v = x; }
12757 // { ++x; v = x; }
12758 // { --x; v = x; }
12759 // { x binop= expr; v = x; }
12760 // { x = x binop expr; v = x; }
12761 // { x = expr binop x; v = x; }
12762 if (auto *CS = dyn_cast<CompoundStmt>(Body)) {
12763 // Check that this is { expr1; expr2; }
12764 if (CS->size() == 2) {
12765 Stmt *First = CS->body_front();
12766 Stmt *Second = CS->body_back();
12767 if (auto *EWC = dyn_cast<ExprWithCleanups>(First))
12768 First = EWC->getSubExpr()->IgnoreParenImpCasts();
12769 if (auto *EWC = dyn_cast<ExprWithCleanups>(Second))
12770 Second = EWC->getSubExpr()->IgnoreParenImpCasts();
12771 // Need to find what subexpression is 'v' and what is 'x'.
12772 OpenMPAtomicUpdateChecker Checker(*this);
12773 bool IsUpdateExprFound = !Checker.checkStatement(Second);
12774 BinaryOperator *BinOp = nullptr;
12775 if (IsUpdateExprFound) {
12776 BinOp = dyn_cast<BinaryOperator>(First);
12777 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
12778 }
12779 if (IsUpdateExprFound && !CurContext->isDependentContext()) {
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 // Check that the first expression has form v = x.
12788 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
12789 llvm::FoldingSetNodeID XId, PossibleXId;
12790 Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
12791 PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
12792 IsUpdateExprFound = XId == PossibleXId;
12793 if (IsUpdateExprFound) {
12794 V = BinOp->getLHS();
12795 X = Checker.getX();
12796 E = Checker.getExpr();
12797 UE = Checker.getUpdateExpr();
12798 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12799 IsPostfixUpdate = true;
12800 }
12801 }
12802 if (!IsUpdateExprFound) {
12803 IsUpdateExprFound = !Checker.checkStatement(First);
12804 BinOp = nullptr;
12805 if (IsUpdateExprFound) {
12806 BinOp = dyn_cast<BinaryOperator>(Second);
12807 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
12808 }
12809 if (IsUpdateExprFound && !CurContext->isDependentContext()) {
12810 // { x++; v = x; }
12811 // { x--; v = x; }
12812 // { ++x; v = x; }
12813 // { --x; v = x; }
12814 // { x binop= expr; v = x; }
12815 // { x = x binop expr; v = x; }
12816 // { x = expr binop x; v = x; }
12817 // Check that the second expression has form v = x.
12818 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
12819 llvm::FoldingSetNodeID XId, PossibleXId;
12820 Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
12821 PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
12822 IsUpdateExprFound = XId == PossibleXId;
12823 if (IsUpdateExprFound) {
12824 V = BinOp->getLHS();
12825 X = Checker.getX();
12826 E = Checker.getExpr();
12827 UE = Checker.getUpdateExpr();
12828 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12829 IsPostfixUpdate = false;
12830 }
12831 }
12832 }
12833 if (!IsUpdateExprFound) {
12834 // { v = x; x = expr; }
12835 auto *FirstExpr = dyn_cast<Expr>(First);
12836 auto *SecondExpr = dyn_cast<Expr>(Second);
12837 if (!FirstExpr || !SecondExpr ||
12838 !(FirstExpr->isInstantiationDependent() ||
12839 SecondExpr->isInstantiationDependent())) {
12840 auto *FirstBinOp = dyn_cast<BinaryOperator>(First);
12841 if (!FirstBinOp || FirstBinOp->getOpcode() != BO_Assign) {
12842 ErrorFound = NotAnAssignmentOp;
12843 NoteLoc = ErrorLoc = FirstBinOp ? FirstBinOp->getOperatorLoc()
12844 : First->getBeginLoc();
12845 NoteRange = ErrorRange = FirstBinOp
12846 ? FirstBinOp->getSourceRange()
12847 : SourceRange(ErrorLoc, ErrorLoc);
12848 } else {
12849 auto *SecondBinOp = dyn_cast<BinaryOperator>(Second);
12850 if (!SecondBinOp || SecondBinOp->getOpcode() != BO_Assign) {
12851 ErrorFound = NotAnAssignmentOp;
12852 NoteLoc = ErrorLoc = SecondBinOp
12853 ? SecondBinOp->getOperatorLoc()
12854 : Second->getBeginLoc();
12855 NoteRange = ErrorRange =
12856 SecondBinOp ? SecondBinOp->getSourceRange()
12857 : SourceRange(ErrorLoc, ErrorLoc);
12858 } else {
12859 Expr *PossibleXRHSInFirst =
12860 FirstBinOp->getRHS()->IgnoreParenImpCasts();
12861 Expr *PossibleXLHSInSecond =
12862 SecondBinOp->getLHS()->IgnoreParenImpCasts();
12863 llvm::FoldingSetNodeID X1Id, X2Id;
12864 PossibleXRHSInFirst->Profile(X1Id, Context,
12865 /*Canonical=*/true);
12866 PossibleXLHSInSecond->Profile(X2Id, Context,
12867 /*Canonical=*/true);
12868 IsUpdateExprFound = X1Id == X2Id;
12869 if (IsUpdateExprFound) {
12870 V = FirstBinOp->getLHS();
12871 X = SecondBinOp->getLHS();
12872 E = SecondBinOp->getRHS();
12873 UE = nullptr;
12874 IsXLHSInRHSPart = false;
12875 IsPostfixUpdate = true;
12876 } else {
12877 ErrorFound = NotASpecificExpression;
12878 ErrorLoc = FirstBinOp->getExprLoc();
12879 ErrorRange = FirstBinOp->getSourceRange();
12880 NoteLoc = SecondBinOp->getLHS()->getExprLoc();
12881 NoteRange = SecondBinOp->getRHS()->getSourceRange();
12882 }
12883 }
12884 }
12885 }
12886 }
12887 } else {
12888 NoteLoc = ErrorLoc = Body->getBeginLoc();
12889 NoteRange = ErrorRange =
12890 SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
12891 ErrorFound = NotTwoSubstatements;
12892 }
12893 } else {
12894 NoteLoc = ErrorLoc = Body->getBeginLoc();
12895 NoteRange = ErrorRange =
12896 SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
12897 ErrorFound = NotACompoundStatement;
12898 }
12899 }
12900 if (ErrorFound != NoError) {
12901 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_compound_statement)
12902 << ErrorRange;
12903 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
12904 return StmtError();
12905 }
12906 if (CurContext->isDependentContext())
12907 UE = V = E = X = nullptr;
12908 } else if (AtomicKind == OMPC_compare) {
12909 if (IsCompareCapture) {
12910 OpenMPAtomicCompareCaptureChecker::ErrorInfoTy ErrorInfo;
12911 OpenMPAtomicCompareCaptureChecker Checker(*this);
12912 if (!Checker.checkStmt(Body, ErrorInfo)) {
12913 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare_capture)
12914 << ErrorInfo.ErrorRange;
12915 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
12916 << ErrorInfo.Error << ErrorInfo.NoteRange;
12917 return StmtError();
12918 }
12919 X = Checker.getX();
12920 E = Checker.getE();
12921 D = Checker.getD();
12922 CE = Checker.getCond();
12923 V = Checker.getV();
12924 R = Checker.getR();
12925 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
12926 IsXLHSInRHSPart = Checker.isXBinopExpr();
12927 IsFailOnly = Checker.isFailOnly();
12928 IsPostfixUpdate = Checker.isPostfixUpdate();
12929 } else {
12930 OpenMPAtomicCompareChecker::ErrorInfoTy ErrorInfo;
12931 OpenMPAtomicCompareChecker Checker(*this);
12932 if (!Checker.checkStmt(Body, ErrorInfo)) {
12933 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare)
12934 << ErrorInfo.ErrorRange;
12935 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
12936 << ErrorInfo.Error << ErrorInfo.NoteRange;
12937 return StmtError();
12938 }
12939 X = Checker.getX();
12940 E = Checker.getE();
12941 D = Checker.getD();
12942 CE = Checker.getCond();
12943 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
12944 IsXLHSInRHSPart = Checker.isXBinopExpr();
12945 }
12946 }
12947
12948 setFunctionHasBranchProtectedScope();
12949
12950 return OMPAtomicDirective::Create(
12951 Context, StartLoc, EndLoc, Clauses, AStmt,
12952 {X, V, R, E, UE, D, CE, IsXLHSInRHSPart, IsPostfixUpdate, IsFailOnly});
12953}
12954
12955StmtResult Sema::ActOnOpenMPTargetDirective(ArrayRef<OMPClause *> Clauses,
12956 Stmt *AStmt,
12957 SourceLocation StartLoc,
12958 SourceLocation EndLoc) {
12959 if (!AStmt)
12960 return StmtError();
12961
12962 auto *CS = cast<CapturedStmt>(AStmt);
12963 // 1.2.2 OpenMP Language Terminology
12964 // Structured block - An executable statement with a single entry at the
12965 // top and a single exit at the bottom.
12966 // The point of exit cannot be a branch out of the structured block.
12967 // longjmp() and throw() must not violate the entry/exit criteria.
12968 CS->getCapturedDecl()->setNothrow();
12969 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target);
12970 ThisCaptureLevel > 1; --ThisCaptureLevel) {
12971 CS = cast<CapturedStmt>(CS->getCapturedStmt());
12972 // 1.2.2 OpenMP Language Terminology
12973 // Structured block - An executable statement with a single entry at the
12974 // top and a single exit at the bottom.
12975 // The point of exit cannot be a branch out of the structured block.
12976 // longjmp() and throw() must not violate the entry/exit criteria.
12977 CS->getCapturedDecl()->setNothrow();
12978 }
12979
12980 // OpenMP [2.16, Nesting of Regions]
12981 // If specified, a teams construct must be contained within a target
12982 // construct. That target construct must contain no statements or directives
12983 // outside of the teams construct.
12984 if (DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->hasInnerTeamsRegion()) {
12985 const Stmt *S = CS->IgnoreContainers(/*IgnoreCaptured=*/true);
12986 bool OMPTeamsFound = true;
12987 if (const auto *CS = dyn_cast<CompoundStmt>(S)) {
12988 auto I = CS->body_begin();
12989 while (I != CS->body_end()) {
12990 const auto *OED = dyn_cast<OMPExecutableDirective>(*I);
12991 if (!OED || !isOpenMPTeamsDirective(OED->getDirectiveKind()) ||
12992 OMPTeamsFound) {
12993
12994 OMPTeamsFound = false;
12995 break;
12996 }
12997 ++I;
12998 }
12999 assert(I != CS->body_end() && "Not found statement")(static_cast <bool> (I != CS->body_end() && "Not found statement"
) ? void (0) : __assert_fail ("I != CS->body_end() && \"Not found statement\""
, "clang/lib/Sema/SemaOpenMP.cpp", 12999, __extension__ __PRETTY_FUNCTION__
))
;
13000 S = *I;
13001 } else {
13002 const auto *OED = dyn_cast<OMPExecutableDirective>(S);
13003 OMPTeamsFound = OED && isOpenMPTeamsDirective(OED->getDirectiveKind());
13004 }
13005 if (!OMPTeamsFound) {
13006 Diag(StartLoc, diag::err_omp_target_contains_not_only_teams);
13007 Diag(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getInnerTeamsRegionLoc(),
13008 diag::note_omp_nested_teams_construct_here);
13009 Diag(S->getBeginLoc(), diag::note_omp_nested_statement_here)
13010 << isa<OMPExecutableDirective>(S);
13011 return StmtError();
13012 }
13013 }
13014
13015 setFunctionHasBranchProtectedScope();
13016
13017 return OMPTargetDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
13018}
13019
13020StmtResult
13021Sema::ActOnOpenMPTargetParallelDirective(ArrayRef<OMPClause *> Clauses,
13022 Stmt *AStmt, SourceLocation StartLoc,
13023 SourceLocation EndLoc) {
13024 if (!AStmt)
13025 return StmtError();
13026
13027 auto *CS = cast<CapturedStmt>(AStmt);
13028 // 1.2.2 OpenMP Language Terminology
13029 // Structured block - An executable statement with a single entry at the
13030 // top and a single exit at the bottom.
13031 // The point of exit cannot be a branch out of the structured block.
13032 // longjmp() and throw() must not violate the entry/exit criteria.
13033 CS->getCapturedDecl()->setNothrow();
13034 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_parallel);
13035 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13036 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13037 // 1.2.2 OpenMP Language Terminology
13038 // Structured block - An executable statement with a single entry at the
13039 // top and a single exit at the bottom.
13040 // The point of exit cannot be a branch out of the structured block.
13041 // longjmp() and throw() must not violate the entry/exit criteria.
13042 CS->getCapturedDecl()->setNothrow();
13043 }
13044
13045 setFunctionHasBranchProtectedScope();
13046
13047 return OMPTargetParallelDirective::Create(
13048 Context, StartLoc, EndLoc, Clauses, AStmt,
13049 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getTaskgroupReductionRef(), DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isCancelRegion());
13050}
13051
13052StmtResult Sema::ActOnOpenMPTargetParallelForDirective(
13053 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13054 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13055 if (!AStmt)
13056 return StmtError();
13057
13058 auto *CS = cast<CapturedStmt>(AStmt);
13059 // 1.2.2 OpenMP Language Terminology
13060 // Structured block - An executable statement with a single entry at the
13061 // top and a single exit at the bottom.
13062 // The point of exit cannot be a branch out of the structured block.
13063 // longjmp() and throw() must not violate the entry/exit criteria.
13064 CS->getCapturedDecl()->setNothrow();
13065 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_parallel_for);
13066 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13067 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13068 // 1.2.2 OpenMP Language Terminology
13069 // Structured block - An executable statement with a single entry at the
13070 // top and a single exit at the bottom.
13071 // The point of exit cannot be a branch out of the structured block.
13072 // longjmp() and throw() must not violate the entry/exit criteria.
13073 CS->getCapturedDecl()->setNothrow();
13074 }
13075
13076 OMPLoopBasedDirective::HelperExprs B;
13077 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13078 // define the nested loops number.
13079 unsigned NestedLoopCount =
13080 checkOpenMPLoop(OMPD_target_parallel_for, getCollapseNumberExpr(Clauses),
13081 getOrderedNumberExpr(Clauses), CS, *this, *DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
,
13082 VarsWithImplicitDSA, B);
13083 if (NestedLoopCount == 0)
13084 return StmtError();
13085
13086 assert((CurContext->isDependentContext() || B.builtAll()) &&(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp target parallel for loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp target parallel for loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 13087, __extension__ __PRETTY_FUNCTION__
))
13087 "omp target parallel for loop exprs were not built")(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp target parallel for loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp target parallel for loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 13087, __extension__ __PRETTY_FUNCTION__
))
;
13088
13089 if (!CurContext->isDependentContext()) {
13090 // Finalize the clauses that need pre-built expressions for CodeGen.
13091 for (OMPClause *C : Clauses) {
13092 if (auto *LC = dyn_cast<OMPLinearClause>(C))
13093 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
13094 B.NumIterations, *this, CurScope,
13095 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
))
13096 return StmtError();
13097 }
13098 }
13099
13100 setFunctionHasBranchProtectedScope();
13101 return OMPTargetParallelForDirective::Create(
13102 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13103 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getTaskgroupReductionRef(), DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isCancelRegion());
13104}
13105
13106/// Check for existence of a map clause in the list of clauses.
13107static bool hasClauses(ArrayRef<OMPClause *> Clauses,
13108 const OpenMPClauseKind K) {
13109 return llvm::any_of(
13110 Clauses, [K](const OMPClause *C) { return C->getClauseKind() == K; });
13111}
13112
13113template <typename... Params>
13114static bool hasClauses(ArrayRef<OMPClause *> Clauses, const OpenMPClauseKind K,
13115 const Params... ClauseTypes) {
13116 return hasClauses(Clauses, K) || hasClauses(Clauses, ClauseTypes...);
13117}
13118
13119/// Check if the variables in the mapping clause are externally visible.
13120static bool isClauseMappable(ArrayRef<OMPClause *> Clauses) {
13121 for (const OMPClause *C : Clauses) {
13122 if (auto *TC = dyn_cast<OMPToClause>(C))
13123 return llvm::all_of(TC->all_decls(), [](ValueDecl *VD) {
13124 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13125 (VD->isExternallyVisible() &&
13126 VD->getVisibility() != HiddenVisibility);
13127 });
13128 else if (auto *FC = dyn_cast<OMPFromClause>(C))
13129 return llvm::all_of(FC->all_decls(), [](ValueDecl *VD) {
13130 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13131 (VD->isExternallyVisible() &&
13132 VD->getVisibility() != HiddenVisibility);
13133 });
13134 }
13135
13136 return true;
13137}
13138
13139StmtResult Sema::ActOnOpenMPTargetDataDirective(ArrayRef<OMPClause *> Clauses,
13140 Stmt *AStmt,
13141 SourceLocation StartLoc,
13142 SourceLocation EndLoc) {
13143 if (!AStmt)
13144 return StmtError();
13145
13146 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected")(static_cast <bool> (isa<CapturedStmt>(AStmt) &&
"Captured statement expected") ? void (0) : __assert_fail ("isa<CapturedStmt>(AStmt) && \"Captured statement expected\""
, "clang/lib/Sema/SemaOpenMP.cpp", 13146, __extension__ __PRETTY_FUNCTION__
))
;
13147
13148 // OpenMP [2.12.2, target data Construct, Restrictions]
13149 // At least one map, use_device_addr or use_device_ptr clause must appear on
13150 // the directive.
13151 if (!hasClauses(Clauses, OMPC_map, OMPC_use_device_ptr) &&
13152 (LangOpts.OpenMP < 50 || !hasClauses(Clauses, OMPC_use_device_addr))) {
13153 StringRef Expected;
13154 if (LangOpts.OpenMP < 50)
13155 Expected = "'map' or 'use_device_ptr'";
13156 else
13157 Expected = "'map', 'use_device_ptr', or 'use_device_addr'";
13158 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13159 << Expected << getOpenMPDirectiveName(OMPD_target_data);
13160 return StmtError();
13161 }
13162
13163 setFunctionHasBranchProtectedScope();
13164
13165 return OMPTargetDataDirective::Create(Context, StartLoc, EndLoc, Clauses,
13166 AStmt);
13167}
13168
13169StmtResult
13170Sema::ActOnOpenMPTargetEnterDataDirective(ArrayRef<OMPClause *> Clauses,
13171 SourceLocation StartLoc,
13172 SourceLocation EndLoc, Stmt *AStmt) {
13173 if (!AStmt)
13174 return StmtError();
13175
13176 auto *CS = cast<CapturedStmt>(AStmt);
13177 // 1.2.2 OpenMP Language Terminology
13178 // Structured block - An executable statement with a single entry at the
13179 // top and a single exit at the bottom.
13180 // The point of exit cannot be a branch out of the structured block.
13181 // longjmp() and throw() must not violate the entry/exit criteria.
13182 CS->getCapturedDecl()->setNothrow();
13183 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_enter_data);
13184 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13185 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13186 // 1.2.2 OpenMP Language Terminology
13187 // Structured block - An executable statement with a single entry at the
13188 // top and a single exit at the bottom.
13189 // The point of exit cannot be a branch out of the structured block.
13190 // longjmp() and throw() must not violate the entry/exit criteria.
13191 CS->getCapturedDecl()->setNothrow();
13192 }
13193
13194 // OpenMP [2.10.2, Restrictions, p. 99]
13195 // At least one map clause must appear on the directive.
13196 if (!hasClauses(Clauses, OMPC_map)) {
13197 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13198 << "'map'" << getOpenMPDirectiveName(OMPD_target_enter_data);
13199 return StmtError();
13200 }
13201
13202 return OMPTargetEnterDataDirective::Create(Context, StartLoc, EndLoc, Clauses,
13203 AStmt);
13204}
13205
13206StmtResult
13207Sema::ActOnOpenMPTargetExitDataDirective(ArrayRef<OMPClause *> Clauses,
13208 SourceLocation StartLoc,
13209 SourceLocation EndLoc, Stmt *AStmt) {
13210 if (!AStmt)
13211 return StmtError();
13212
13213 auto *CS = cast<CapturedStmt>(AStmt);
13214 // 1.2.2 OpenMP Language Terminology
13215 // Structured block - An executable statement with a single entry at the
13216 // top and a single exit at the bottom.
13217 // The point of exit cannot be a branch out of the structured block.
13218 // longjmp() and throw() must not violate the entry/exit criteria.
13219 CS->getCapturedDecl()->setNothrow();
13220 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_exit_data);
13221 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13222 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13223 // 1.2.2 OpenMP Language Terminology
13224 // Structured block - An executable statement with a single entry at the
13225 // top and a single exit at the bottom.
13226 // The point of exit cannot be a branch out of the structured block.
13227 // longjmp() and throw() must not violate the entry/exit criteria.
13228 CS->getCapturedDecl()->setNothrow();
13229 }
13230
13231 // OpenMP [2.10.3, Restrictions, p. 102]
13232 // At least one map clause must appear on the directive.
13233 if (!hasClauses(Clauses, OMPC_map)) {
13234 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13235 << "'map'" << getOpenMPDirectiveName(OMPD_target_exit_data);
13236 return StmtError();
13237 }
13238
13239 return OMPTargetExitDataDirective::Create(Context, StartLoc, EndLoc, Clauses,
13240 AStmt);
13241}
13242
13243StmtResult Sema::ActOnOpenMPTargetUpdateDirective(ArrayRef<OMPClause *> Clauses,
13244 SourceLocation StartLoc,
13245 SourceLocation EndLoc,
13246 Stmt *AStmt) {
13247 if (!AStmt)
13248 return StmtError();
13249
13250 auto *CS = cast<CapturedStmt>(AStmt);
13251 // 1.2.2 OpenMP Language Terminology
13252 // Structured block - An executable statement with a single entry at the
13253 // top and a single exit at the bottom.
13254 // The point of exit cannot be a branch out of the structured block.
13255 // longjmp() and throw() must not violate the entry/exit criteria.
13256 CS->getCapturedDecl()->setNothrow();
13257 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_update);
13258 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13259 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13260 // 1.2.2 OpenMP Language Terminology
13261 // Structured block - An executable statement with a single entry at the
13262 // top and a single exit at the bottom.
13263 // The point of exit cannot be a branch out of the structured block.
13264 // longjmp() and throw() must not violate the entry/exit criteria.
13265 CS->getCapturedDecl()->setNothrow();
13266 }
13267
13268 if (!hasClauses(Clauses, OMPC_to, OMPC_from)) {
13269 Diag(StartLoc, diag::err_omp_at_least_one_motion_clause_required);
13270 return StmtError();
13271 }
13272
13273 if (!isClauseMappable(Clauses)) {
13274 Diag(StartLoc, diag::err_omp_cannot_update_with_internal_linkage);
13275 return StmtError();
13276 }
13277
13278 return OMPTargetUpdateDirective::Create(Context, StartLoc, EndLoc, Clauses,
13279 AStmt);
13280}
13281
13282StmtResult Sema::ActOnOpenMPTeamsDirective(ArrayRef<OMPClause *> Clauses,
13283 Stmt *AStmt, SourceLocation StartLoc,
13284 SourceLocation EndLoc) {
13285 if (!AStmt)
13286 return StmtError();
13287
13288 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
13289 if (getLangOpts().HIP && (DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getParentDirective() == OMPD_target))
13290 Diag(StartLoc, diag::warn_hip_omp_target_directives);
13291
13292 auto *CS = cast<CapturedStmt>(AStmt);
13293 // 1.2.2 OpenMP Language Terminology
13294 // Structured block - An executable statement with a single entry at the
13295 // top and a single exit at the bottom.
13296 // The point of exit cannot be a branch out of the structured block.
13297 // longjmp() and throw() must not violate the entry/exit criteria.
13298 CS->getCapturedDecl()->setNothrow();
13299
13300 setFunctionHasBranchProtectedScope();
13301
13302 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->setParentTeamsRegionLoc(StartLoc);
13303
13304 return OMPTeamsDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
13305}
13306
13307StmtResult
13308Sema::ActOnOpenMPCancellationPointDirective(SourceLocation StartLoc,
13309 SourceLocation EndLoc,
13310 OpenMPDirectiveKind CancelRegion) {
13311 if (DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isParentNowaitRegion()) {
13312 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 0;
13313 return StmtError();
13314 }
13315 if (DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isParentOrderedRegion()) {
13316 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 0;
13317 return StmtError();
13318 }
13319 return OMPCancellationPointDirective::Create(Context, StartLoc, EndLoc,
13320 CancelRegion);
13321}
13322
13323StmtResult Sema::ActOnOpenMPCancelDirective(ArrayRef<OMPClause *> Clauses,
13324 SourceLocation StartLoc,
13325 SourceLocation EndLoc,
13326 OpenMPDirectiveKind CancelRegion) {
13327 if (DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isParentNowaitRegion()) {
13328 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 1;
13329 return StmtError();
13330 }
13331 if (DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isParentOrderedRegion()) {
13332 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 1;
13333 return StmtError();
13334 }
13335 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->setParentCancelRegion(/*Cancel=*/true);
13336 return OMPCancelDirective::Create(Context, StartLoc, EndLoc, Clauses,
13337 CancelRegion);
13338}
13339
13340static bool checkReductionClauseWithNogroup(Sema &S,
13341 ArrayRef<OMPClause *> Clauses) {
13342 const OMPClause *ReductionClause = nullptr;
13343 const OMPClause *NogroupClause = nullptr;
13344 for (const OMPClause *C : Clauses) {
13345 if (C->getClauseKind() == OMPC_reduction) {
13346 ReductionClause = C;
13347 if (NogroupClause)
13348 break;
13349 continue;
13350 }
13351 if (C->getClauseKind() == OMPC_nogroup) {
13352 NogroupClause = C;
13353 if (ReductionClause)
13354 break;
13355 continue;
13356 }
13357 }
13358 if (ReductionClause && NogroupClause) {
13359 S.Diag(ReductionClause->getBeginLoc(), diag::err_omp_reduction_with_nogroup)
13360 << SourceRange(NogroupClause->getBeginLoc(),
13361 NogroupClause->getEndLoc());
13362 return true;
13363 }
13364 return false;
13365}
13366
13367StmtResult Sema::ActOnOpenMPTaskLoopDirective(
13368 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13369 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13370 if (!AStmt)
13371 return StmtError();
13372
13373 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected")(static_cast <bool> (isa<CapturedStmt>(AStmt) &&
"Captured statement expected") ? void (0) : __assert_fail ("isa<CapturedStmt>(AStmt) && \"Captured statement expected\""
, "clang/lib/Sema/SemaOpenMP.cpp", 13373, __extension__ __PRETTY_FUNCTION__
))
;
13374 OMPLoopBasedDirective::HelperExprs B;
13375 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13376 // define the nested loops number.
13377 unsigned NestedLoopCount =
13378 checkOpenMPLoop(OMPD_taskloop, getCollapseNumberExpr(Clauses),
13379 /*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
,
13380 VarsWithImplicitDSA, B);
13381 if (NestedLoopCount == 0)
13382 return StmtError();
13383
13384 assert((CurContext->isDependentContext() || B.builtAll()) &&(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp for loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp for loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 13385, __extension__ __PRETTY_FUNCTION__
))
13385 "omp for loop exprs were not built")(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp for loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp for loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 13385, __extension__ __PRETTY_FUNCTION__
))
;
13386
13387 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13388 // The grainsize clause and num_tasks clause are mutually exclusive and may
13389 // not appear on the same taskloop directive.
13390 if (checkMutuallyExclusiveClauses(*this, Clauses,
13391 {OMPC_grainsize, OMPC_num_tasks}))
13392 return StmtError();
13393 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13394 // If a reduction clause is present on the taskloop directive, the nogroup
13395 // clause must not be specified.
13396 if (checkReductionClauseWithNogroup(*this, Clauses))
13397 return StmtError();
13398
13399 setFunctionHasBranchProtectedScope();
13400 return OMPTaskLoopDirective::Create(Context, StartLoc, EndLoc,
13401 NestedLoopCount, Clauses, AStmt, B,
13402 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isCancelRegion());
13403}
13404
13405StmtResult Sema::ActOnOpenMPTaskLoopSimdDirective(
13406 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13407 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13408 if (!AStmt)
13409 return StmtError();
13410
13411 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected")(static_cast <bool> (isa<CapturedStmt>(AStmt) &&
"Captured statement expected") ? void (0) : __assert_fail ("isa<CapturedStmt>(AStmt) && \"Captured statement expected\""
, "clang/lib/Sema/SemaOpenMP.cpp", 13411, __extension__ __PRETTY_FUNCTION__
))
;
13412 OMPLoopBasedDirective::HelperExprs B;
13413 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13414 // define the nested loops number.
13415 unsigned NestedLoopCount =
13416 checkOpenMPLoop(OMPD_taskloop_simd, getCollapseNumberExpr(Clauses),
13417 /*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
,
13418 VarsWithImplicitDSA, B);
13419 if (NestedLoopCount == 0)
13420 return StmtError();
13421
13422 assert((CurContext->isDependentContext() || B.builtAll()) &&(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp for loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp for loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 13423, __extension__ __PRETTY_FUNCTION__
))
13423 "omp for loop exprs were not built")(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp for loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp for loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 13423, __extension__ __PRETTY_FUNCTION__
))
;
13424
13425 if (!CurContext->isDependentContext()) {
13426 // Finalize the clauses that need pre-built expressions for CodeGen.
13427 for (OMPClause *C : Clauses) {
13428 if (auto *LC = dyn_cast<OMPLinearClause>(C))
13429 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
13430 B.NumIterations, *this, CurScope,
13431 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
))
13432 return StmtError();
13433 }
13434 }
13435
13436 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13437 // The grainsize clause and num_tasks clause are mutually exclusive and may
13438 // not appear on the same taskloop directive.
13439 if (checkMutuallyExclusiveClauses(*this, Clauses,
13440 {OMPC_grainsize, OMPC_num_tasks}))
13441 return StmtError();
13442 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13443 // If a reduction clause is present on the taskloop directive, the nogroup
13444 // clause must not be specified.
13445 if (checkReductionClauseWithNogroup(*this, Clauses))
13446 return StmtError();
13447 if (checkSimdlenSafelenSpecified(*this, Clauses))
13448 return StmtError();
13449
13450 setFunctionHasBranchProtectedScope();
13451 return OMPTaskLoopSimdDirective::Create(Context, StartLoc, EndLoc,
13452 NestedLoopCount, Clauses, AStmt, B);
13453}
13454
13455StmtResult Sema::ActOnOpenMPMasterTaskLoopDirective(
13456 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13457 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13458 if (!AStmt)
13459 return StmtError();
13460
13461 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected")(static_cast <bool> (isa<CapturedStmt>(AStmt) &&
"Captured statement expected") ? void (0) : __assert_fail ("isa<CapturedStmt>(AStmt) && \"Captured statement expected\""
, "clang/lib/Sema/SemaOpenMP.cpp", 13461, __extension__ __PRETTY_FUNCTION__
))
;
13462 OMPLoopBasedDirective::HelperExprs B;
13463 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13464 // define the nested loops number.
13465 unsigned NestedLoopCount =
13466 checkOpenMPLoop(OMPD_master_taskloop, getCollapseNumberExpr(Clauses),
13467 /*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
,
13468 VarsWithImplicitDSA, B);
13469 if (NestedLoopCount == 0)
13470 return StmtError();
13471
13472 assert((CurContext->isDependentContext() || B.builtAll()) &&(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp for loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp for loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 13473, __extension__ __PRETTY_FUNCTION__
))
13473 "omp for loop exprs were not built")(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp for loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp for loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 13473, __extension__ __PRETTY_FUNCTION__
))
;
13474
13475 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13476 // The grainsize clause and num_tasks clause are mutually exclusive and may
13477 // not appear on the same taskloop directive.
13478 if (checkMutuallyExclusiveClauses(*this, Clauses,
13479 {OMPC_grainsize, OMPC_num_tasks}))
13480 return StmtError();
13481 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13482 // If a reduction clause is present on the taskloop directive, the nogroup
13483 // clause must not be specified.
13484 if (checkReductionClauseWithNogroup(*this, Clauses))
13485 return StmtError();
13486
13487 setFunctionHasBranchProtectedScope();
13488 return OMPMasterTaskLoopDirective::Create(Context, StartLoc, EndLoc,
13489 NestedLoopCount, Clauses, AStmt, B,
13490 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isCancelRegion());
13491}
13492
13493StmtResult Sema::ActOnOpenMPMaskedTaskLoopDirective(
13494 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13495 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13496 if (!AStmt)
13497 return StmtError();
13498
13499 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected")(static_cast <bool> (isa<CapturedStmt>(AStmt) &&
"Captured statement expected") ? void (0) : __assert_fail ("isa<CapturedStmt>(AStmt) && \"Captured statement expected\""
, "clang/lib/Sema/SemaOpenMP.cpp", 13499, __extension__ __PRETTY_FUNCTION__
))
;
13500 OMPLoopBasedDirective::HelperExprs B;
13501 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13502 // define the nested loops number.
13503 unsigned NestedLoopCount =
13504 checkOpenMPLoop(OMPD_masked_taskloop, getCollapseNumberExpr(Clauses),
13505 /*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
,
13506 VarsWithImplicitDSA, B);
13507 if (NestedLoopCount == 0)
13508 return StmtError();
13509
13510 assert((CurContext->isDependentContext() || B.builtAll()) &&(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp for loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp for loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 13511, __extension__ __PRETTY_FUNCTION__
))
13511 "omp for loop exprs were not built")(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp for loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp for loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 13511, __extension__ __PRETTY_FUNCTION__
))
;
13512
13513 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13514 // The grainsize clause and num_tasks clause are mutually exclusive and may
13515 // not appear on the same taskloop directive.
13516 if (checkMutuallyExclusiveClauses(*this, Clauses,
13517 {OMPC_grainsize, OMPC_num_tasks}))
13518 return StmtError();
13519 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13520 // If a reduction clause is present on the taskloop directive, the nogroup
13521 // clause must not be specified.
13522 if (checkReductionClauseWithNogroup(*this, Clauses))
13523 return StmtError();
13524
13525 setFunctionHasBranchProtectedScope();
13526 return OMPMaskedTaskLoopDirective::Create(Context, StartLoc, EndLoc,
13527 NestedLoopCount, Clauses, AStmt, B,
13528 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isCancelRegion());
13529}
13530
13531StmtResult Sema::ActOnOpenMPMasterTaskLoopSimdDirective(
13532 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13533 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13534 if (!AStmt)
13535 return StmtError();
13536
13537 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected")(static_cast <bool> (isa<CapturedStmt>(AStmt) &&
"Captured statement expected") ? void (0) : __assert_fail ("isa<CapturedStmt>(AStmt) && \"Captured statement expected\""
, "clang/lib/Sema/SemaOpenMP.cpp", 13537, __extension__ __PRETTY_FUNCTION__
))
;
13538 OMPLoopBasedDirective::HelperExprs B;
13539 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13540 // define the nested loops number.
13541 unsigned NestedLoopCount =
13542 checkOpenMPLoop(OMPD_master_taskloop_simd, getCollapseNumberExpr(Clauses),
13543 /*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
,
13544 VarsWithImplicitDSA, B);
13545 if (NestedLoopCount == 0)
13546 return StmtError();
13547
13548 assert((CurContext->isDependentContext() || B.builtAll()) &&(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp for loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp for loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 13549, __extension__ __PRETTY_FUNCTION__
))
13549 "omp for loop exprs were not built")(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp for loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp for loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 13549, __extension__ __PRETTY_FUNCTION__
))
;
13550
13551 if (!CurContext->isDependentContext()) {
13552 // Finalize the clauses that need pre-built expressions for CodeGen.
13553 for (OMPClause *C : Clauses) {
13554 if (auto *LC = dyn_cast<OMPLinearClause>(C))
13555 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
13556 B.NumIterations, *this, CurScope,
13557 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
))
13558 return StmtError();
13559 }
13560 }
13561
13562 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13563 // The grainsize clause and num_tasks clause are mutually exclusive and may
13564 // not appear on the same taskloop directive.
13565 if (checkMutuallyExclusiveClauses(*this, Clauses,
13566 {OMPC_grainsize, OMPC_num_tasks}))
13567 return StmtError();
13568 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13569 // If a reduction clause is present on the taskloop directive, the nogroup
13570 // clause must not be specified.
13571 if (checkReductionClauseWithNogroup(*this, Clauses))
13572 return StmtError();
13573 if (checkSimdlenSafelenSpecified(*this, Clauses))
13574 return StmtError();
13575
13576 setFunctionHasBranchProtectedScope();
13577 return OMPMasterTaskLoopSimdDirective::Create(
13578 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13579}
13580
13581StmtResult Sema::ActOnOpenMPMaskedTaskLoopSimdDirective(
13582 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13583 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13584 if (!AStmt)
13585 return StmtError();
13586
13587 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected")(static_cast <bool> (isa<CapturedStmt>(AStmt) &&
"Captured statement expected") ? void (0) : __assert_fail ("isa<CapturedStmt>(AStmt) && \"Captured statement expected\""
, "clang/lib/Sema/SemaOpenMP.cpp", 13587, __extension__ __PRETTY_FUNCTION__
))
;
13588 OMPLoopBasedDirective::HelperExprs B;
13589 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13590 // define the nested loops number.
13591 unsigned NestedLoopCount =
13592 checkOpenMPLoop(OMPD_masked_taskloop_simd, getCollapseNumberExpr(Clauses),
13593 /*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
,
13594 VarsWithImplicitDSA, B);
13595 if (NestedLoopCount == 0)
13596 return StmtError();
13597
13598 assert((CurContext->isDependentContext() || B.builtAll()) &&(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp for loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp for loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 13599, __extension__ __PRETTY_FUNCTION__
))
13599 "omp for loop exprs were not built")(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp for loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp for loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 13599, __extension__ __PRETTY_FUNCTION__
))
;
13600
13601 if (!CurContext->isDependentContext()) {
13602 // Finalize the clauses that need pre-built expressions for CodeGen.
13603 for (OMPClause *C : Clauses) {
13604 if (auto *LC = dyn_cast<OMPLinearClause>(C))
13605 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
13606 B.NumIterations, *this, CurScope,
13607 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
))
13608 return StmtError();
13609 }
13610 }
13611
13612 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13613 // The grainsize clause and num_tasks clause are mutually exclusive and may
13614 // not appear on the same taskloop directive.
13615 if (checkMutuallyExclusiveClauses(*this, Clauses,
13616 {OMPC_grainsize, OMPC_num_tasks}))
13617 return StmtError();
13618 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13619 // If a reduction clause is present on the taskloop directive, the nogroup
13620 // clause must not be specified.
13621 if (checkReductionClauseWithNogroup(*this, Clauses))
13622 return StmtError();
13623 if (checkSimdlenSafelenSpecified(*this, Clauses))
13624 return StmtError();
13625
13626 setFunctionHasBranchProtectedScope();
13627 return OMPMaskedTaskLoopSimdDirective::Create(
13628 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13629}
13630
13631StmtResult Sema::ActOnOpenMPParallelMasterTaskLoopDirective(
13632 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13633 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13634 if (!AStmt)
13635 return StmtError();
13636
13637 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected")(static_cast <bool> (isa<CapturedStmt>(AStmt) &&
"Captured statement expected") ? void (0) : __assert_fail ("isa<CapturedStmt>(AStmt) && \"Captured statement expected\""
, "clang/lib/Sema/SemaOpenMP.cpp", 13637, __extension__ __PRETTY_FUNCTION__
))
;
13638 auto *CS = cast<CapturedStmt>(AStmt);
13639 // 1.2.2 OpenMP Language Terminology
13640 // Structured block - An executable statement with a single entry at the
13641 // top and a single exit at the bottom.
13642 // The point of exit cannot be a branch out of the structured block.
13643 // longjmp() and throw() must not violate the entry/exit criteria.
13644 CS->getCapturedDecl()->setNothrow();
13645 for (int ThisCaptureLevel =
13646 getOpenMPCaptureLevels(OMPD_parallel_master_taskloop);
13647 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13648 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13649 // 1.2.2 OpenMP Language Terminology
13650 // Structured block - An executable statement with a single entry at the
13651 // top and a single exit at the bottom.
13652 // The point of exit cannot be a branch out of the structured block.
13653 // longjmp() and throw() must not violate the entry/exit criteria.
13654 CS->getCapturedDecl()->setNothrow();
13655 }
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, getCollapseNumberExpr(Clauses),
13662 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
,
13663 VarsWithImplicitDSA, B);
13664 if (NestedLoopCount == 0)
13665 return StmtError();
13666
13667 assert((CurContext->isDependentContext() || B.builtAll()) &&(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp for loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp for loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 13668, __extension__ __PRETTY_FUNCTION__
))
13668 "omp for loop exprs were not built")(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp for loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp for loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 13668, __extension__ __PRETTY_FUNCTION__
))
;
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(*this, 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(*this, Clauses))
13680 return StmtError();
13681
13682 setFunctionHasBranchProtectedScope();
13683 return OMPParallelMasterTaskLoopDirective::Create(
13684 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13685 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isCancelRegion());
13686}
13687
13688StmtResult Sema::ActOnOpenMPParallelMaskedTaskLoopDirective(
13689 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13690 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13691 if (!AStmt)
13692 return StmtError();
13693
13694 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected")(static_cast <bool> (isa<CapturedStmt>(AStmt) &&
"Captured statement expected") ? void (0) : __assert_fail ("isa<CapturedStmt>(AStmt) && \"Captured statement expected\""
, "clang/lib/Sema/SemaOpenMP.cpp", 13694, __extension__ __PRETTY_FUNCTION__
))
;
13695 auto *CS = cast<CapturedStmt>(AStmt);
13696 // 1.2.2 OpenMP Language Terminology
13697 // Structured block - An executable statement with a single entry at the
13698 // top and a single exit at the bottom.
13699 // The point of exit cannot be a branch out of the structured block.
13700 // longjmp() and throw() must not violate the entry/exit criteria.
13701 CS->getCapturedDecl()->setNothrow();
13702 for (int ThisCaptureLevel =
13703 getOpenMPCaptureLevels(OMPD_parallel_masked_taskloop);
13704 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13705 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13706 // 1.2.2 OpenMP Language Terminology
13707 // Structured block - An executable statement with a single entry at the
13708 // top and a single exit at the bottom.
13709 // The point of exit cannot be a branch out of the structured block.
13710 // longjmp() and throw() must not violate the entry/exit criteria.
13711 CS->getCapturedDecl()->setNothrow();
13712 }
13713
13714 OMPLoopBasedDirective::HelperExprs B;
13715 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13716 // define the nested loops number.
13717 unsigned NestedLoopCount = checkOpenMPLoop(
13718 OMPD_parallel_masked_taskloop, getCollapseNumberExpr(Clauses),
13719 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
,
13720 VarsWithImplicitDSA, B);
13721 if (NestedLoopCount == 0)
13722 return StmtError();
13723
13724 assert((CurContext->isDependentContext() || B.builtAll()) &&(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp for loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp for loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 13725, __extension__ __PRETTY_FUNCTION__
))
13725 "omp for loop exprs were not built")(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp for loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp for loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 13725, __extension__ __PRETTY_FUNCTION__
))
;
13726
13727 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13728 // The grainsize clause and num_tasks clause are mutually exclusive and may
13729 // not appear on the same taskloop directive.
13730 if (checkMutuallyExclusiveClauses(*this, Clauses,
13731 {OMPC_grainsize, OMPC_num_tasks}))
13732 return StmtError();
13733 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13734 // If a reduction clause is present on the taskloop directive, the nogroup
13735 // clause must not be specified.
13736 if (checkReductionClauseWithNogroup(*this, Clauses))
13737 return StmtError();
13738
13739 setFunctionHasBranchProtectedScope();
13740 return OMPParallelMaskedTaskLoopDirective::Create(
13741 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13742 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isCancelRegion());
13743}
13744
13745StmtResult Sema::ActOnOpenMPParallelMasterTaskLoopSimdDirective(
13746 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13747 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13748 if (!AStmt)
13749 return StmtError();
13750
13751 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected")(static_cast <bool> (isa<CapturedStmt>(AStmt) &&
"Captured statement expected") ? void (0) : __assert_fail ("isa<CapturedStmt>(AStmt) && \"Captured statement expected\""
, "clang/lib/Sema/SemaOpenMP.cpp", 13751, __extension__ __PRETTY_FUNCTION__
))
;
13752 auto *CS = cast<CapturedStmt>(AStmt);
13753 // 1.2.2 OpenMP Language Terminology
13754 // Structured block - An executable statement with a single entry at the
13755 // top and a single exit at the bottom.
13756 // The point of exit cannot be a branch out of the structured block.
13757 // longjmp() and throw() must not violate the entry/exit criteria.
13758 CS->getCapturedDecl()->setNothrow();
13759 for (int ThisCaptureLevel =
13760 getOpenMPCaptureLevels(OMPD_parallel_master_taskloop_simd);
13761 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13762 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13763 // 1.2.2 OpenMP Language Terminology
13764 // Structured block - An executable statement with a single entry at the
13765 // top and a single exit at the bottom.
13766 // The point of exit cannot be a branch out of the structured block.
13767 // longjmp() and throw() must not violate the entry/exit criteria.
13768 CS->getCapturedDecl()->setNothrow();
13769 }
13770
13771 OMPLoopBasedDirective::HelperExprs B;
13772 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13773 // define the nested loops number.
13774 unsigned NestedLoopCount = checkOpenMPLoop(
13775 OMPD_parallel_master_taskloop_simd, getCollapseNumberExpr(Clauses),
13776 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
,
13777 VarsWithImplicitDSA, B);
13778 if (NestedLoopCount == 0)
13779 return StmtError();
13780
13781 assert((CurContext->isDependentContext() || B.builtAll()) &&(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp for loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp for loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 13782, __extension__ __PRETTY_FUNCTION__
))
13782 "omp for loop exprs were not built")(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp for loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp for loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 13782, __extension__ __PRETTY_FUNCTION__
))
;
13783
13784 if (!CurContext->isDependentContext()) {
13785 // Finalize the clauses that need pre-built expressions for CodeGen.
13786 for (OMPClause *C : Clauses) {
13787 if (auto *LC = dyn_cast<OMPLinearClause>(C))
13788 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
13789 B.NumIterations, *this, CurScope,
13790 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
))
13791 return StmtError();
13792 }
13793 }
13794
13795 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13796 // The grainsize clause and num_tasks clause are mutually exclusive and may
13797 // not appear on the same taskloop directive.
13798 if (checkMutuallyExclusiveClauses(*this, Clauses,
13799 {OMPC_grainsize, OMPC_num_tasks}))
13800 return StmtError();
13801 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13802 // If a reduction clause is present on the taskloop directive, the nogroup
13803 // clause must not be specified.
13804 if (checkReductionClauseWithNogroup(*this, Clauses))
13805 return StmtError();
13806 if (checkSimdlenSafelenSpecified(*this, Clauses))
13807 return StmtError();
13808
13809 setFunctionHasBranchProtectedScope();
13810 return OMPParallelMasterTaskLoopSimdDirective::Create(
13811 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13812}
13813
13814StmtResult Sema::ActOnOpenMPParallelMaskedTaskLoopSimdDirective(
13815 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13816 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13817 if (!AStmt)
13818 return StmtError();
13819
13820 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected")(static_cast <bool> (isa<CapturedStmt>(AStmt) &&
"Captured statement expected") ? void (0) : __assert_fail ("isa<CapturedStmt>(AStmt) && \"Captured statement expected\""
, "clang/lib/Sema/SemaOpenMP.cpp", 13820, __extension__ __PRETTY_FUNCTION__
))
;
13821 auto *CS = cast<CapturedStmt>(AStmt);
13822 // 1.2.2 OpenMP Language Terminology
13823 // Structured block - An executable statement with a single entry at the
13824 // top and a single exit at the bottom.
13825 // The point of exit cannot be a branch out of the structured block.
13826 // longjmp() and throw() must not violate the entry/exit criteria.
13827 CS->getCapturedDecl()->setNothrow();
13828 for (int ThisCaptureLevel =
13829 getOpenMPCaptureLevels(OMPD_parallel_masked_taskloop_simd);
13830 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13831 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13832 // 1.2.2 OpenMP Language Terminology
13833 // Structured block - An executable statement with a single entry at the
13834 // top and a single exit at the bottom.
13835 // The point of exit cannot be a branch out of the structured block.
13836 // longjmp() and throw() must not violate the entry/exit criteria.
13837 CS->getCapturedDecl()->setNothrow();
13838 }
13839
13840 OMPLoopBasedDirective::HelperExprs B;
13841 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13842 // define the nested loops number.
13843 unsigned NestedLoopCount = checkOpenMPLoop(
13844 OMPD_parallel_masked_taskloop_simd, getCollapseNumberExpr(Clauses),
13845 /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
,
13846 VarsWithImplicitDSA, B);
13847 if (NestedLoopCount == 0)
13848 return StmtError();
13849
13850 assert((CurContext->isDependentContext() || B.builtAll()) &&(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp for loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp for loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 13851, __extension__ __PRETTY_FUNCTION__
))
13851 "omp for loop exprs were not built")(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp for loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp for loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 13851, __extension__ __PRETTY_FUNCTION__
))
;
13852
13853 if (!CurContext->isDependentContext()) {
13854 // Finalize the clauses that need pre-built expressions for CodeGen.
13855 for (OMPClause *C : Clauses) {
13856 if (auto *LC = dyn_cast<OMPLinearClause>(C))
13857 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
13858 B.NumIterations, *this, CurScope,
13859 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
))
13860 return StmtError();
13861 }
13862 }
13863
13864 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13865 // The grainsize clause and num_tasks clause are mutually exclusive and may
13866 // not appear on the same taskloop directive.
13867 if (checkMutuallyExclusiveClauses(*this, Clauses,
13868 {OMPC_grainsize, OMPC_num_tasks}))
13869 return StmtError();
13870 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13871 // If a reduction clause is present on the taskloop directive, the nogroup
13872 // clause must not be specified.
13873 if (checkReductionClauseWithNogroup(*this, Clauses))
13874 return StmtError();
13875 if (checkSimdlenSafelenSpecified(*this, Clauses))
13876 return StmtError();
13877
13878 setFunctionHasBranchProtectedScope();
13879 return OMPParallelMaskedTaskLoopSimdDirective::Create(
13880 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13881}
13882
13883StmtResult Sema::ActOnOpenMPDistributeDirective(
13884 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13885 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13886 if (!AStmt)
13887 return StmtError();
13888
13889 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected")(static_cast <bool> (isa<CapturedStmt>(AStmt) &&
"Captured statement expected") ? void (0) : __assert_fail ("isa<CapturedStmt>(AStmt) && \"Captured statement expected\""
, "clang/lib/Sema/SemaOpenMP.cpp", 13889, __extension__ __PRETTY_FUNCTION__
))
;
13890 OMPLoopBasedDirective::HelperExprs B;
13891 // In presence of clause 'collapse' with number of loops, it will
13892 // define the nested loops number.
13893 unsigned NestedLoopCount =
13894 checkOpenMPLoop(OMPD_distribute, getCollapseNumberExpr(Clauses),
13895 nullptr /*ordered not a clause on distribute*/, AStmt,
13896 *this, *DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
, VarsWithImplicitDSA, B);
13897 if (NestedLoopCount == 0)
13898 return StmtError();
13899
13900 assert((CurContext->isDependentContext() || B.builtAll()) &&(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp for loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp for loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 13901, __extension__ __PRETTY_FUNCTION__
))
13901 "omp for loop exprs were not built")(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp for loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp for loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 13901, __extension__ __PRETTY_FUNCTION__
))
;
13902
13903 setFunctionHasBranchProtectedScope();
13904 return OMPDistributeDirective::Create(Context, StartLoc, EndLoc,
13905 NestedLoopCount, Clauses, AStmt, B);
13906}
13907
13908StmtResult Sema::ActOnOpenMPDistributeParallelForDirective(
13909 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13910 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13911 if (!AStmt)
13912 return StmtError();
13913
13914 auto *CS = cast<CapturedStmt>(AStmt);
13915 // 1.2.2 OpenMP Language Terminology
13916 // Structured block - An executable statement with a single entry at the
13917 // top and a single exit at the bottom.
13918 // The point of exit cannot be a branch out of the structured block.
13919 // longjmp() and throw() must not violate the entry/exit criteria.
13920 CS->getCapturedDecl()->setNothrow();
13921 for (int ThisCaptureLevel =
13922 getOpenMPCaptureLevels(OMPD_distribute_parallel_for);
13923 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13924 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13925 // 1.2.2 OpenMP Language Terminology
13926 // Structured block - An executable statement with a single entry at the
13927 // top and a single exit at the bottom.
13928 // The point of exit cannot be a branch out of the structured block.
13929 // longjmp() and throw() must not violate the entry/exit criteria.
13930 CS->getCapturedDecl()->setNothrow();
13931 }
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_distribute_parallel_for, getCollapseNumberExpr(Clauses),
13938 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
,
13939 VarsWithImplicitDSA, B);
13940 if (NestedLoopCount == 0)
13941 return StmtError();
13942
13943 assert((CurContext->isDependentContext() || B.builtAll()) &&(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp for loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp for loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 13944, __extension__ __PRETTY_FUNCTION__
))
13944 "omp for loop exprs were not built")(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp for loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp for loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 13944, __extension__ __PRETTY_FUNCTION__
))
;
13945
13946 setFunctionHasBranchProtectedScope();
13947 return OMPDistributeParallelForDirective::Create(
13948 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13949 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getTaskgroupReductionRef(), DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isCancelRegion());
13950}
13951
13952StmtResult Sema::ActOnOpenMPDistributeParallelForSimdDirective(
13953 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13954 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13955 if (!AStmt)
13956 return StmtError();
13957
13958 auto *CS = cast<CapturedStmt>(AStmt);
13959 // 1.2.2 OpenMP Language Terminology
13960 // Structured block - An executable statement with a single entry at the
13961 // top and a single exit at the bottom.
13962 // The point of exit cannot be a branch out of the structured block.
13963 // longjmp() and throw() must not violate the entry/exit criteria.
13964 CS->getCapturedDecl()->setNothrow();
13965 for (int ThisCaptureLevel =
13966 getOpenMPCaptureLevels(OMPD_distribute_parallel_for_simd);
13967 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13968 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13969 // 1.2.2 OpenMP Language Terminology
13970 // Structured block - An executable statement with a single entry at the
13971 // top and a single exit at the bottom.
13972 // The point of exit cannot be a branch out of the structured block.
13973 // longjmp() and throw() must not violate the entry/exit criteria.
13974 CS->getCapturedDecl()->setNothrow();
13975 }
13976
13977 OMPLoopBasedDirective::HelperExprs B;
13978 // In presence of clause 'collapse' with number of loops, it will
13979 // define the nested loops number.
13980 unsigned NestedLoopCount = checkOpenMPLoop(
13981 OMPD_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses),
13982 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
,
13983 VarsWithImplicitDSA, B);
13984 if (NestedLoopCount == 0)
13985 return StmtError();
13986
13987 assert((CurContext->isDependentContext() || B.builtAll()) &&(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp for loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp for loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 13988, __extension__ __PRETTY_FUNCTION__
))
13988 "omp for loop exprs were not built")(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp for loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp for loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 13988, __extension__ __PRETTY_FUNCTION__
))
;
13989
13990 if (!CurContext->isDependentContext()) {
13991 // Finalize the clauses that need pre-built expressions for CodeGen.
13992 for (OMPClause *C : Clauses) {
13993 if (auto *LC = dyn_cast<OMPLinearClause>(C))
13994 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
13995 B.NumIterations, *this, CurScope,
13996 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
))
13997 return StmtError();
13998 }
13999 }
14000
14001 if (checkSimdlenSafelenSpecified(*this, Clauses))
14002 return StmtError();
14003
14004 setFunctionHasBranchProtectedScope();
14005 return OMPDistributeParallelForSimdDirective::Create(
14006 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14007}
14008
14009StmtResult Sema::ActOnOpenMPDistributeSimdDirective(
14010 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14011 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14012 if (!AStmt)
14013 return StmtError();
14014
14015 auto *CS = cast<CapturedStmt>(AStmt);
14016 // 1.2.2 OpenMP Language Terminology
14017 // Structured block - An executable statement with a single entry at the
14018 // top and a single exit at the bottom.
14019 // The point of exit cannot be a branch out of the structured block.
14020 // longjmp() and throw() must not violate the entry/exit criteria.
14021 CS->getCapturedDecl()->setNothrow();
14022 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_distribute_simd);
14023 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14024 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14025 // 1.2.2 OpenMP Language Terminology
14026 // Structured block - An executable statement with a single entry at the
14027 // top and a single exit at the bottom.
14028 // The point of exit cannot be a branch out of the structured block.
14029 // longjmp() and throw() must not violate the entry/exit criteria.
14030 CS->getCapturedDecl()->setNothrow();
14031 }
14032
14033 OMPLoopBasedDirective::HelperExprs B;
14034 // In presence of clause 'collapse' with number of loops, it will
14035 // define the nested loops number.
14036 unsigned NestedLoopCount =
14037 checkOpenMPLoop(OMPD_distribute_simd, getCollapseNumberExpr(Clauses),
14038 nullptr /*ordered not a clause on distribute*/, CS, *this,
14039 *DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
, VarsWithImplicitDSA, B);
14040 if (NestedLoopCount == 0)
14041 return StmtError();
14042
14043 assert((CurContext->isDependentContext() || B.builtAll()) &&(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp for loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp for loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 14044, __extension__ __PRETTY_FUNCTION__
))
14044 "omp for loop exprs were not built")(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp for loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp for loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 14044, __extension__ __PRETTY_FUNCTION__
))
;
14045
14046 if (!CurContext->isDependentContext()) {
14047 // Finalize the clauses that need pre-built expressions for CodeGen.
14048 for (OMPClause *C : Clauses) {
14049 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14050 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14051 B.NumIterations, *this, CurScope,
14052 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
))
14053 return StmtError();
14054 }
14055 }
14056
14057 if (checkSimdlenSafelenSpecified(*this, Clauses))
14058 return StmtError();
14059
14060 setFunctionHasBranchProtectedScope();
14061 return OMPDistributeSimdDirective::Create(Context, StartLoc, EndLoc,
14062 NestedLoopCount, Clauses, AStmt, B);
14063}
14064
14065StmtResult Sema::ActOnOpenMPTargetParallelForSimdDirective(
14066 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14067 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14068 if (!AStmt)
14069 return StmtError();
14070
14071 auto *CS = cast<CapturedStmt>(AStmt);
14072 // 1.2.2 OpenMP Language Terminology
14073 // Structured block - An executable statement with a single entry at the
14074 // top and a single exit at the bottom.
14075 // The point of exit cannot be a branch out of the structured block.
14076 // longjmp() and throw() must not violate the entry/exit criteria.
14077 CS->getCapturedDecl()->setNothrow();
14078 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_parallel_for);
14079 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14080 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14081 // 1.2.2 OpenMP Language Terminology
14082 // Structured block - An executable statement with a single entry at the
14083 // top and a single exit at the bottom.
14084 // The point of exit cannot be a branch out of the structured block.
14085 // longjmp() and throw() must not violate the entry/exit criteria.
14086 CS->getCapturedDecl()->setNothrow();
14087 }
14088
14089 OMPLoopBasedDirective::HelperExprs B;
14090 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14091 // define the nested loops number.
14092 unsigned NestedLoopCount = checkOpenMPLoop(
14093 OMPD_target_parallel_for_simd, getCollapseNumberExpr(Clauses),
14094 getOrderedNumberExpr(Clauses), CS, *this, *DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
, VarsWithImplicitDSA,
14095 B);
14096 if (NestedLoopCount == 0)
14097 return StmtError();
14098
14099 assert((CurContext->isDependentContext() || B.builtAll()) &&(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp target parallel for simd loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp target parallel for simd loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 14100, __extension__ __PRETTY_FUNCTION__
))
14100 "omp target parallel for simd loop exprs were not built")(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp target parallel for simd loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp target parallel for simd loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 14100, __extension__ __PRETTY_FUNCTION__
))
;
14101
14102 if (!CurContext->isDependentContext()) {
14103 // Finalize the clauses that need pre-built expressions for CodeGen.
14104 for (OMPClause *C : Clauses) {
14105 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14106 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14107 B.NumIterations, *this, CurScope,
14108 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
))
14109 return StmtError();
14110 }
14111 }
14112 if (checkSimdlenSafelenSpecified(*this, Clauses))
14113 return StmtError();
14114
14115 setFunctionHasBranchProtectedScope();
14116 return OMPTargetParallelForSimdDirective::Create(
14117 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14118}
14119
14120StmtResult Sema::ActOnOpenMPTargetSimdDirective(
14121 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14122 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14123 if (!AStmt)
14124 return StmtError();
14125
14126 auto *CS = cast<CapturedStmt>(AStmt);
14127 // 1.2.2 OpenMP Language Terminology
14128 // Structured block - An executable statement with a single entry at the
14129 // top and a single exit at the bottom.
14130 // The point of exit cannot be a branch out of the structured block.
14131 // longjmp() and throw() must not violate the entry/exit criteria.
14132 CS->getCapturedDecl()->setNothrow();
14133 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_simd);
14134 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14135 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14136 // 1.2.2 OpenMP Language Terminology
14137 // Structured block - An executable statement with a single entry at the
14138 // top and a single exit at the bottom.
14139 // The point of exit cannot be a branch out of the structured block.
14140 // longjmp() and throw() must not violate the entry/exit criteria.
14141 CS->getCapturedDecl()->setNothrow();
14142 }
14143
14144 OMPLoopBasedDirective::HelperExprs B;
14145 // In presence of clause 'collapse' with number of loops, it will define the
14146 // nested loops number.
14147 unsigned NestedLoopCount =
14148 checkOpenMPLoop(OMPD_target_simd, getCollapseNumberExpr(Clauses),
14149 getOrderedNumberExpr(Clauses), CS, *this, *DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
,
14150 VarsWithImplicitDSA, B);
14151 if (NestedLoopCount == 0)
14152 return StmtError();
14153
14154 assert((CurContext->isDependentContext() || B.builtAll()) &&(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp target simd loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp target simd loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 14155, __extension__ __PRETTY_FUNCTION__
))
14155 "omp target simd loop exprs were not built")(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp target simd loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp target simd loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 14155, __extension__ __PRETTY_FUNCTION__
))
;
14156
14157 if (!CurContext->isDependentContext()) {
14158 // Finalize the clauses that need pre-built expressions for CodeGen.
14159 for (OMPClause *C : Clauses) {
14160 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14161 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14162 B.NumIterations, *this, CurScope,
14163 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
))
14164 return StmtError();
14165 }
14166 }
14167
14168 if (checkSimdlenSafelenSpecified(*this, Clauses))
14169 return StmtError();
14170
14171 setFunctionHasBranchProtectedScope();
14172 return OMPTargetSimdDirective::Create(Context, StartLoc, EndLoc,
14173 NestedLoopCount, Clauses, AStmt, B);
14174}
14175
14176StmtResult Sema::ActOnOpenMPTeamsDistributeDirective(
14177 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14178 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14179 if (!AStmt)
14180 return StmtError();
14181
14182 auto *CS = cast<CapturedStmt>(AStmt);
14183 // 1.2.2 OpenMP Language Terminology
14184 // Structured block - An executable statement with a single entry at the
14185 // top and a single exit at the bottom.
14186 // The point of exit cannot be a branch out of the structured block.
14187 // longjmp() and throw() must not violate the entry/exit criteria.
14188 CS->getCapturedDecl()->setNothrow();
14189 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_teams_distribute);
14190 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14191 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14192 // 1.2.2 OpenMP Language Terminology
14193 // Structured block - An executable statement with a single entry at the
14194 // top and a single exit at the bottom.
14195 // The point of exit cannot be a branch out of the structured block.
14196 // longjmp() and throw() must not violate the entry/exit criteria.
14197 CS->getCapturedDecl()->setNothrow();
14198 }
14199
14200 OMPLoopBasedDirective::HelperExprs B;
14201 // In presence of clause 'collapse' with number of loops, it will
14202 // define the nested loops number.
14203 unsigned NestedLoopCount =
14204 checkOpenMPLoop(OMPD_teams_distribute, getCollapseNumberExpr(Clauses),
14205 nullptr /*ordered not a clause on distribute*/, CS, *this,
14206 *DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
, VarsWithImplicitDSA, B);
14207 if (NestedLoopCount == 0)
14208 return StmtError();
14209
14210 assert((CurContext->isDependentContext() || B.builtAll()) &&(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp teams distribute loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp teams distribute loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 14211, __extension__ __PRETTY_FUNCTION__
))
14211 "omp teams distribute loop exprs were not built")(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp teams distribute loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp teams distribute loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 14211, __extension__ __PRETTY_FUNCTION__
))
;
14212
14213 setFunctionHasBranchProtectedScope();
14214
14215 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->setParentTeamsRegionLoc(StartLoc);
14216
14217 return OMPTeamsDistributeDirective::Create(
14218 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14219}
14220
14221StmtResult Sema::ActOnOpenMPTeamsDistributeSimdDirective(
14222 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14223 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14224 if (!AStmt)
14225 return StmtError();
14226
14227 auto *CS = cast<CapturedStmt>(AStmt);
14228 // 1.2.2 OpenMP Language Terminology
14229 // Structured block - An executable statement with a single entry at the
14230 // top and a single exit at the bottom.
14231 // The point of exit cannot be a branch out of the structured block.
14232 // longjmp() and throw() must not violate the entry/exit criteria.
14233 CS->getCapturedDecl()->setNothrow();
14234 for (int ThisCaptureLevel =
14235 getOpenMPCaptureLevels(OMPD_teams_distribute_simd);
14236 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14237 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14238 // 1.2.2 OpenMP Language Terminology
14239 // Structured block - An executable statement with a single entry at the
14240 // top and a single exit at the bottom.
14241 // The point of exit cannot be a branch out of the structured block.
14242 // longjmp() and throw() must not violate the entry/exit criteria.
14243 CS->getCapturedDecl()->setNothrow();
14244 }
14245
14246 OMPLoopBasedDirective::HelperExprs B;
14247 // In presence of clause 'collapse' with number of loops, it will
14248 // define the nested loops number.
14249 unsigned NestedLoopCount = checkOpenMPLoop(
14250 OMPD_teams_distribute_simd, getCollapseNumberExpr(Clauses),
14251 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
,
14252 VarsWithImplicitDSA, B);
14253
14254 if (NestedLoopCount == 0)
14255 return StmtError();
14256
14257 assert((CurContext->isDependentContext() || B.builtAll()) &&(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp teams distribute simd loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp teams distribute simd loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 14258, __extension__ __PRETTY_FUNCTION__
))
14258 "omp teams distribute simd loop exprs were not built")(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp teams distribute simd loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp teams distribute simd loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 14258, __extension__ __PRETTY_FUNCTION__
))
;
14259
14260 if (!CurContext->isDependentContext()) {
14261 // Finalize the clauses that need pre-built expressions for CodeGen.
14262 for (OMPClause *C : Clauses) {
14263 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14264 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14265 B.NumIterations, *this, CurScope,
14266 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
))
14267 return StmtError();
14268 }
14269 }
14270
14271 if (checkSimdlenSafelenSpecified(*this, Clauses))
14272 return StmtError();
14273
14274 setFunctionHasBranchProtectedScope();
14275
14276 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->setParentTeamsRegionLoc(StartLoc);
14277
14278 return OMPTeamsDistributeSimdDirective::Create(
14279 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14280}
14281
14282StmtResult Sema::ActOnOpenMPTeamsDistributeParallelForSimdDirective(
14283 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14284 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14285 if (!AStmt)
14286 return StmtError();
14287
14288 auto *CS = cast<CapturedStmt>(AStmt);
14289 // 1.2.2 OpenMP Language Terminology
14290 // Structured block - An executable statement with a single entry at the
14291 // top and a single exit at the bottom.
14292 // The point of exit cannot be a branch out of the structured block.
14293 // longjmp() and throw() must not violate the entry/exit criteria.
14294 CS->getCapturedDecl()->setNothrow();
14295
14296 for (int ThisCaptureLevel =
14297 getOpenMPCaptureLevels(OMPD_teams_distribute_parallel_for_simd);
14298 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14299 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14300 // 1.2.2 OpenMP Language Terminology
14301 // Structured block - An executable statement with a single entry at the
14302 // top and a single exit at the bottom.
14303 // The point of exit cannot be a branch out of the structured block.
14304 // longjmp() and throw() must not violate the entry/exit criteria.
14305 CS->getCapturedDecl()->setNothrow();
14306 }
14307
14308 OMPLoopBasedDirective::HelperExprs B;
14309 // In presence of clause 'collapse' with number of loops, it will
14310 // define the nested loops number.
14311 unsigned NestedLoopCount = checkOpenMPLoop(
14312 OMPD_teams_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses),
14313 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
,
14314 VarsWithImplicitDSA, B);
14315
14316 if (NestedLoopCount == 0)
14317 return StmtError();
14318
14319 assert((CurContext->isDependentContext() || B.builtAll()) &&(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp for loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp for loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 14320, __extension__ __PRETTY_FUNCTION__
))
14320 "omp for loop exprs were not built")(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp for loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp for loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 14320, __extension__ __PRETTY_FUNCTION__
))
;
14321
14322 if (!CurContext->isDependentContext()) {
14323 // Finalize the clauses that need pre-built expressions for CodeGen.
14324 for (OMPClause *C : Clauses) {
14325 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14326 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14327 B.NumIterations, *this, CurScope,
14328 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
))
14329 return StmtError();
14330 }
14331 }
14332
14333 if (checkSimdlenSafelenSpecified(*this, Clauses))
14334 return StmtError();
14335
14336 setFunctionHasBranchProtectedScope();
14337
14338 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->setParentTeamsRegionLoc(StartLoc);
14339
14340 return OMPTeamsDistributeParallelForSimdDirective::Create(
14341 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14342}
14343
14344StmtResult Sema::ActOnOpenMPTeamsDistributeParallelForDirective(
14345 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14346 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14347 if (!AStmt)
14348 return StmtError();
14349
14350 auto *CS = cast<CapturedStmt>(AStmt);
14351 // 1.2.2 OpenMP Language Terminology
14352 // Structured block - An executable statement with a single entry at the
14353 // top and a single exit at the bottom.
14354 // The point of exit cannot be a branch out of the structured block.
14355 // longjmp() and throw() must not violate the entry/exit criteria.
14356 CS->getCapturedDecl()->setNothrow();
14357
14358 for (int ThisCaptureLevel =
14359 getOpenMPCaptureLevels(OMPD_teams_distribute_parallel_for);
14360 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14361 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14362 // 1.2.2 OpenMP Language Terminology
14363 // Structured block - An executable statement with a single entry at the
14364 // top and a single exit at the bottom.
14365 // The point of exit cannot be a branch out of the structured block.
14366 // longjmp() and throw() must not violate the entry/exit criteria.
14367 CS->getCapturedDecl()->setNothrow();
14368 }
14369
14370 OMPLoopBasedDirective::HelperExprs B;
14371 // In presence of clause 'collapse' with number of loops, it will
14372 // define the nested loops number.
14373 unsigned NestedLoopCount = checkOpenMPLoop(
14374 OMPD_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses),
14375 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
,
14376 VarsWithImplicitDSA, B);
14377
14378 if (NestedLoopCount == 0)
14379 return StmtError();
14380
14381 assert((CurContext->isDependentContext() || B.builtAll()) &&(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp for loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp for loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 14382, __extension__ __PRETTY_FUNCTION__
))
14382 "omp for loop exprs were not built")(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp for loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp for loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 14382, __extension__ __PRETTY_FUNCTION__
))
;
14383
14384 setFunctionHasBranchProtectedScope();
14385
14386 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->setParentTeamsRegionLoc(StartLoc);
14387
14388 return OMPTeamsDistributeParallelForDirective::Create(
14389 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14390 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getTaskgroupReductionRef(), DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isCancelRegion());
14391}
14392
14393StmtResult Sema::ActOnOpenMPTargetTeamsDirective(ArrayRef<OMPClause *> Clauses,
14394 Stmt *AStmt,
14395 SourceLocation StartLoc,
14396 SourceLocation EndLoc) {
14397 if (!AStmt)
14398 return StmtError();
14399
14400 auto *CS = cast<CapturedStmt>(AStmt);
14401 // 1.2.2 OpenMP Language Terminology
14402 // Structured block - An executable statement with a single entry at the
14403 // top and a single exit at the bottom.
14404 // The point of exit cannot be a branch out of the structured block.
14405 // longjmp() and throw() must not violate the entry/exit criteria.
14406 CS->getCapturedDecl()->setNothrow();
14407
14408 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_teams);
14409 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14410 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14411 // 1.2.2 OpenMP Language Terminology
14412 // Structured block - An executable statement with a single entry at the
14413 // top and a single exit at the bottom.
14414 // The point of exit cannot be a branch out of the structured block.
14415 // longjmp() and throw() must not violate the entry/exit criteria.
14416 CS->getCapturedDecl()->setNothrow();
14417 }
14418 setFunctionHasBranchProtectedScope();
14419
14420 return OMPTargetTeamsDirective::Create(Context, StartLoc, EndLoc, Clauses,
14421 AStmt);
14422}
14423
14424StmtResult Sema::ActOnOpenMPTargetTeamsDistributeDirective(
14425 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14426 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14427 if (!AStmt)
14428 return StmtError();
14429
14430 auto *CS = cast<CapturedStmt>(AStmt);
14431 // 1.2.2 OpenMP Language Terminology
14432 // Structured block - An executable statement with a single entry at the
14433 // top and a single exit at the bottom.
14434 // The point of exit cannot be a branch out of the structured block.
14435 // longjmp() and throw() must not violate the entry/exit criteria.
14436 CS->getCapturedDecl()->setNothrow();
14437 for (int ThisCaptureLevel =
14438 getOpenMPCaptureLevels(OMPD_target_teams_distribute);
14439 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14440 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14441 // 1.2.2 OpenMP Language Terminology
14442 // Structured block - An executable statement with a single entry at the
14443 // top and a single exit at the bottom.
14444 // The point of exit cannot be a branch out of the structured block.
14445 // longjmp() and throw() must not violate the entry/exit criteria.
14446 CS->getCapturedDecl()->setNothrow();
14447 }
14448
14449 OMPLoopBasedDirective::HelperExprs B;
14450 // In presence of clause 'collapse' with number of loops, it will
14451 // define the nested loops number.
14452 unsigned NestedLoopCount = checkOpenMPLoop(
14453 OMPD_target_teams_distribute, getCollapseNumberExpr(Clauses),
14454 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
,
14455 VarsWithImplicitDSA, B);
14456 if (NestedLoopCount == 0)
14457 return StmtError();
14458
14459 assert((CurContext->isDependentContext() || B.builtAll()) &&(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp target teams distribute loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp target teams distribute loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 14460, __extension__ __PRETTY_FUNCTION__
))
14460 "omp target teams distribute loop exprs were not built")(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp target teams distribute loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp target teams distribute loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 14460, __extension__ __PRETTY_FUNCTION__
))
;
14461
14462 setFunctionHasBranchProtectedScope();
14463 return OMPTargetTeamsDistributeDirective::Create(
14464 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14465}
14466
14467StmtResult Sema::ActOnOpenMPTargetTeamsDistributeParallelForDirective(
14468 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14469 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14470 if (!AStmt)
14471 return StmtError();
14472
14473 auto *CS = cast<CapturedStmt>(AStmt);
14474 // 1.2.2 OpenMP Language Terminology
14475 // Structured block - An executable statement with a single entry at the
14476 // top and a single exit at the bottom.
14477 // The point of exit cannot be a branch out of the structured block.
14478 // longjmp() and throw() must not violate the entry/exit criteria.
14479 CS->getCapturedDecl()->setNothrow();
14480 for (int ThisCaptureLevel =
14481 getOpenMPCaptureLevels(OMPD_target_teams_distribute_parallel_for);
14482 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14483 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14484 // 1.2.2 OpenMP Language Terminology
14485 // Structured block - An executable statement with a single entry at the
14486 // top and a single exit at the bottom.
14487 // The point of exit cannot be a branch out of the structured block.
14488 // longjmp() and throw() must not violate the entry/exit criteria.
14489 CS->getCapturedDecl()->setNothrow();
14490 }
14491
14492 OMPLoopBasedDirective::HelperExprs B;
14493 // In presence of clause 'collapse' with number of loops, it will
14494 // define the nested loops number.
14495 unsigned NestedLoopCount = checkOpenMPLoop(
14496 OMPD_target_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses),
14497 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
,
14498 VarsWithImplicitDSA, B);
14499 if (NestedLoopCount == 0)
14500 return StmtError();
14501
14502 assert((CurContext->isDependentContext() || B.builtAll()) &&(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp target teams distribute parallel for loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp target teams distribute parallel for loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 14503, __extension__ __PRETTY_FUNCTION__
))
14503 "omp target teams distribute parallel for loop exprs were not built")(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp target teams distribute parallel for loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp target teams distribute parallel for loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 14503, __extension__ __PRETTY_FUNCTION__
))
;
14504
14505 if (!CurContext->isDependentContext()) {
14506 // Finalize the clauses that need pre-built expressions for CodeGen.
14507 for (OMPClause *C : Clauses) {
14508 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14509 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14510 B.NumIterations, *this, CurScope,
14511 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
))
14512 return StmtError();
14513 }
14514 }
14515
14516 setFunctionHasBranchProtectedScope();
14517 return OMPTargetTeamsDistributeParallelForDirective::Create(
14518 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14519 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getTaskgroupReductionRef(), DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isCancelRegion());
14520}
14521
14522StmtResult Sema::ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective(
14523 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14524 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14525 if (!AStmt)
14526 return StmtError();
14527
14528 auto *CS = cast<CapturedStmt>(AStmt);
14529 // 1.2.2 OpenMP Language Terminology
14530 // Structured block - An executable statement with a single entry at the
14531 // top and a single exit at the bottom.
14532 // The point of exit cannot be a branch out of the structured block.
14533 // longjmp() and throw() must not violate the entry/exit criteria.
14534 CS->getCapturedDecl()->setNothrow();
14535 for (int ThisCaptureLevel = getOpenMPCaptureLevels(
14536 OMPD_target_teams_distribute_parallel_for_simd);
14537 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14538 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14539 // 1.2.2 OpenMP Language Terminology
14540 // Structured block - An executable statement with a single entry at the
14541 // top and a single exit at the bottom.
14542 // The point of exit cannot be a branch out of the structured block.
14543 // longjmp() and throw() must not violate the entry/exit criteria.
14544 CS->getCapturedDecl()->setNothrow();
14545 }
14546
14547 OMPLoopBasedDirective::HelperExprs B;
14548 // In presence of clause 'collapse' with number of loops, it will
14549 // define the nested loops number.
14550 unsigned NestedLoopCount =
14551 checkOpenMPLoop(OMPD_target_teams_distribute_parallel_for_simd,
14552 getCollapseNumberExpr(Clauses),
14553 nullptr /*ordered not a clause on distribute*/, CS, *this,
14554 *DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
, VarsWithImplicitDSA, B);
14555 if (NestedLoopCount == 0)
14556 return StmtError();
14557
14558 assert((CurContext->isDependentContext() || B.builtAll()) &&(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp target teams distribute parallel for simd loop exprs were not "
"built") ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp target teams distribute parallel for simd loop exprs were not \" \"built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 14560, __extension__ __PRETTY_FUNCTION__
))
14559 "omp target teams distribute parallel for simd loop exprs were not "(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp target teams distribute parallel for simd loop exprs were not "
"built") ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp target teams distribute parallel for simd loop exprs were not \" \"built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 14560, __extension__ __PRETTY_FUNCTION__
))
14560 "built")(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp target teams distribute parallel for simd loop exprs were not "
"built") ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp target teams distribute parallel for simd loop exprs were not \" \"built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 14560, __extension__ __PRETTY_FUNCTION__
))
;
14561
14562 if (!CurContext->isDependentContext()) {
14563 // Finalize the clauses that need pre-built expressions for CodeGen.
14564 for (OMPClause *C : Clauses) {
14565 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14566 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14567 B.NumIterations, *this, CurScope,
14568 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
))
14569 return StmtError();
14570 }
14571 }
14572
14573 if (checkSimdlenSafelenSpecified(*this, Clauses))
14574 return StmtError();
14575
14576 setFunctionHasBranchProtectedScope();
14577 return OMPTargetTeamsDistributeParallelForSimdDirective::Create(
14578 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14579}
14580
14581StmtResult Sema::ActOnOpenMPTargetTeamsDistributeSimdDirective(
14582 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14583 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14584 if (!AStmt)
14585 return StmtError();
14586
14587 auto *CS = cast<CapturedStmt>(AStmt);
14588 // 1.2.2 OpenMP Language Terminology
14589 // Structured block - An executable statement with a single entry at the
14590 // top and a single exit at the bottom.
14591 // The point of exit cannot be a branch out of the structured block.
14592 // longjmp() and throw() must not violate the entry/exit criteria.
14593 CS->getCapturedDecl()->setNothrow();
14594 for (int ThisCaptureLevel =
14595 getOpenMPCaptureLevels(OMPD_target_teams_distribute_simd);
14596 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14597 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14598 // 1.2.2 OpenMP Language Terminology
14599 // Structured block - An executable statement with a single entry at the
14600 // top and a single exit at the bottom.
14601 // The point of exit cannot be a branch out of the structured block.
14602 // longjmp() and throw() must not violate the entry/exit criteria.
14603 CS->getCapturedDecl()->setNothrow();
14604 }
14605
14606 OMPLoopBasedDirective::HelperExprs B;
14607 // In presence of clause 'collapse' with number of loops, it will
14608 // define the nested loops number.
14609 unsigned NestedLoopCount = checkOpenMPLoop(
14610 OMPD_target_teams_distribute_simd, getCollapseNumberExpr(Clauses),
14611 nullptr /*ordered not a clause on distribute*/, CS, *this, *DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
,
14612 VarsWithImplicitDSA, B);
14613 if (NestedLoopCount == 0)
14614 return StmtError();
14615
14616 assert((CurContext->isDependentContext() || B.builtAll()) &&(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp target teams distribute simd loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp target teams distribute simd loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 14617, __extension__ __PRETTY_FUNCTION__
))
14617 "omp target teams distribute simd loop exprs were not built")(static_cast <bool> ((CurContext->isDependentContext
() || B.builtAll()) && "omp target teams distribute simd loop exprs were not built"
) ? void (0) : __assert_fail ("(CurContext->isDependentContext() || B.builtAll()) && \"omp target teams distribute simd loop exprs were not built\""
, "clang/lib/Sema/SemaOpenMP.cpp", 14617, __extension__ __PRETTY_FUNCTION__
))
;
14618
14619 if (!CurContext->isDependentContext()) {
14620 // Finalize the clauses that need pre-built expressions for CodeGen.
14621 for (OMPClause *C : Clauses) {
14622 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14623 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14624 B.NumIterations, *this, CurScope,
14625 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
))
14626 return StmtError();
14627 }
14628 }
14629
14630 if (checkSimdlenSafelenSpecified(*this, Clauses))
14631 return StmtError();
14632
14633 setFunctionHasBranchProtectedScope();
14634 return OMPTargetTeamsDistributeSimdDirective::Create(
14635 Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14636}
14637
14638bool Sema::checkTransformableLoopNest(
14639 OpenMPDirectiveKind Kind, Stmt *AStmt, int NumLoops,
14640 SmallVectorImpl<OMPLoopBasedDirective::HelperExprs> &LoopHelpers,
14641 Stmt *&Body,
14642 SmallVectorImpl<SmallVector<llvm::PointerUnion<Stmt *, Decl *>, 0>>
14643 &OriginalInits) {
14644 OriginalInits.emplace_back();
14645 bool Result = OMPLoopBasedDirective::doForAllLoops(
14646 AStmt->IgnoreContainers(), /*TryImperfectlyNestedLoops=*/false, NumLoops,
14647 [this, &LoopHelpers, &Body, &OriginalInits, Kind](unsigned Cnt,
14648 Stmt *CurStmt) {
14649 VarsWithInheritedDSAType TmpDSA;
14650 unsigned SingleNumLoops =
14651 checkOpenMPLoop(Kind, nullptr, nullptr, CurStmt, *this, *DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
,
14652 TmpDSA, LoopHelpers[Cnt]);
14653 if (SingleNumLoops == 0)
14654 return true;
14655 assert(SingleNumLoops == 1 && "Expect single loop iteration space")(static_cast <bool> (SingleNumLoops == 1 && "Expect single loop iteration space"
) ? void (0) : __assert_fail ("SingleNumLoops == 1 && \"Expect single loop iteration space\""
, "clang/lib/Sema/SemaOpenMP.cpp", 14655, __extension__ __PRETTY_FUNCTION__
))
;
14656 if (auto *For = dyn_cast<ForStmt>(CurStmt)) {
14657 OriginalInits.back().push_back(For->getInit());
14658 Body = For->getBody();
14659 } else {
14660 assert(isa<CXXForRangeStmt>(CurStmt) &&(static_cast <bool> (isa<CXXForRangeStmt>(CurStmt
) && "Expected canonical for or range-based for loops."
) ? void (0) : __assert_fail ("isa<CXXForRangeStmt>(CurStmt) && \"Expected canonical for or range-based for loops.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 14661, __extension__ __PRETTY_FUNCTION__
))
14661 "Expected canonical for or range-based for loops.")(static_cast <bool> (isa<CXXForRangeStmt>(CurStmt
) && "Expected canonical for or range-based for loops."
) ? void (0) : __assert_fail ("isa<CXXForRangeStmt>(CurStmt) && \"Expected canonical for or range-based for loops.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 14661, __extension__ __PRETTY_FUNCTION__
))
;
14662 auto *CXXFor = cast<CXXForRangeStmt>(CurStmt);
14663 OriginalInits.back().push_back(CXXFor->getBeginStmt());
14664 Body = CXXFor->getBody();
14665 }
14666 OriginalInits.emplace_back();
14667 return false;
14668 },
14669 [&OriginalInits](OMPLoopBasedDirective *Transform) {
14670 Stmt *DependentPreInits;
14671 if (auto *Dir = dyn_cast<OMPTileDirective>(Transform))
14672 DependentPreInits = Dir->getPreInits();
14673 else if (auto *Dir = dyn_cast<OMPUnrollDirective>(Transform))
14674 DependentPreInits = Dir->getPreInits();
14675 else
14676 llvm_unreachable("Unhandled loop transformation")::llvm::llvm_unreachable_internal("Unhandled loop transformation"
, "clang/lib/Sema/SemaOpenMP.cpp", 14676)
;
14677 if (!DependentPreInits)
14678 return;
14679 llvm::append_range(OriginalInits.back(),
14680 cast<DeclStmt>(DependentPreInits)->getDeclGroup());
14681 });
14682 assert(OriginalInits.back().empty() && "No preinit after innermost loop")(static_cast <bool> (OriginalInits.back().empty() &&
"No preinit after innermost loop") ? void (0) : __assert_fail
("OriginalInits.back().empty() && \"No preinit after innermost loop\""
, "clang/lib/Sema/SemaOpenMP.cpp", 14682, __extension__ __PRETTY_FUNCTION__
))
;
14683 OriginalInits.pop_back();
14684 return Result;
14685}
14686
14687StmtResult Sema::ActOnOpenMPTileDirective(ArrayRef<OMPClause *> Clauses,
14688 Stmt *AStmt, SourceLocation StartLoc,
14689 SourceLocation EndLoc) {
14690 auto SizesClauses =
14691 OMPExecutableDirective::getClausesOfKind<OMPSizesClause>(Clauses);
14692 if (SizesClauses.empty()) {
14693 // A missing 'sizes' clause is already reported by the parser.
14694 return StmtError();
14695 }
14696 const OMPSizesClause *SizesClause = *SizesClauses.begin();
14697 unsigned NumLoops = SizesClause->getNumSizes();
14698
14699 // Empty statement should only be possible if there already was an error.
14700 if (!AStmt)
14701 return StmtError();
14702
14703 // Verify and diagnose loop nest.
14704 SmallVector<OMPLoopBasedDirective::HelperExprs, 4> LoopHelpers(NumLoops);
14705 Stmt *Body = nullptr;
14706 SmallVector<SmallVector<llvm::PointerUnion<Stmt *, Decl *>, 0>, 4>
14707 OriginalInits;
14708 if (!checkTransformableLoopNest(OMPD_tile, AStmt, NumLoops, LoopHelpers, Body,
14709 OriginalInits))
14710 return StmtError();
14711
14712 // Delay tiling to when template is completely instantiated.
14713 if (CurContext->isDependentContext())
14714 return OMPTileDirective::Create(Context, StartLoc, EndLoc, Clauses,
14715 NumLoops, AStmt, nullptr, nullptr);
14716
14717 SmallVector<Decl *, 4> PreInits;
14718
14719 // Create iteration variables for the generated loops.
14720 SmallVector<VarDecl *, 4> FloorIndVars;
14721 SmallVector<VarDecl *, 4> TileIndVars;
14722 FloorIndVars.resize(NumLoops);
14723 TileIndVars.resize(NumLoops);
14724 for (unsigned I = 0; I < NumLoops; ++I) {
14725 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14726
14727 assert(LoopHelper.Counters.size() == 1 &&(static_cast <bool> (LoopHelper.Counters.size() == 1 &&
"Expect single-dimensional loop iteration space") ? void (0)
: __assert_fail ("LoopHelper.Counters.size() == 1 && \"Expect single-dimensional loop iteration space\""
, "clang/lib/Sema/SemaOpenMP.cpp", 14728, __extension__ __PRETTY_FUNCTION__
))
14728 "Expect single-dimensional loop iteration space")(static_cast <bool> (LoopHelper.Counters.size() == 1 &&
"Expect single-dimensional loop iteration space") ? void (0)
: __assert_fail ("LoopHelper.Counters.size() == 1 && \"Expect single-dimensional loop iteration space\""
, "clang/lib/Sema/SemaOpenMP.cpp", 14728, __extension__ __PRETTY_FUNCTION__
))
;
14729 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
14730 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
14731 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
14732 QualType CntTy = IterVarRef->getType();
14733
14734 // Iteration variable for the floor (i.e. outer) loop.
14735 {
14736 std::string FloorCntName =
14737 (Twine(".floor_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
14738 VarDecl *FloorCntDecl =
14739 buildVarDecl(*this, {}, CntTy, FloorCntName, nullptr, OrigCntVar);
14740 FloorIndVars[I] = FloorCntDecl;
14741 }
14742
14743 // Iteration variable for the tile (i.e. inner) loop.
14744 {
14745 std::string TileCntName =
14746 (Twine(".tile_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
14747
14748 // Reuse the iteration variable created by checkOpenMPLoop. It is also
14749 // used by the expressions to derive the original iteration variable's
14750 // value from the logical iteration number.
14751 auto *TileCntDecl = cast<VarDecl>(IterVarRef->getDecl());
14752 TileCntDecl->setDeclName(&PP.getIdentifierTable().get(TileCntName));
14753 TileIndVars[I] = TileCntDecl;
14754 }
14755 for (auto &P : OriginalInits[I]) {
14756 if (auto *D = P.dyn_cast<Decl *>())
14757 PreInits.push_back(D);
14758 else if (auto *PI = dyn_cast_or_null<DeclStmt>(P.dyn_cast<Stmt *>()))
14759 PreInits.append(PI->decl_begin(), PI->decl_end());
14760 }
14761 if (auto *PI = cast_or_null<DeclStmt>(LoopHelper.PreInits))
14762 PreInits.append(PI->decl_begin(), PI->decl_end());
14763 // Gather declarations for the data members used as counters.
14764 for (Expr *CounterRef : LoopHelper.Counters) {
14765 auto *CounterDecl = cast<DeclRefExpr>(CounterRef)->getDecl();
14766 if (isa<OMPCapturedExprDecl>(CounterDecl))
14767 PreInits.push_back(CounterDecl);
14768 }
14769 }
14770
14771 // Once the original iteration values are set, append the innermost body.
14772 Stmt *Inner = Body;
14773
14774 // Create tile loops from the inside to the outside.
14775 for (int I = NumLoops - 1; I >= 0; --I) {
14776 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14777 Expr *NumIterations = LoopHelper.NumIterations;
14778 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
14779 QualType CntTy = OrigCntVar->getType();
14780 Expr *DimTileSize = SizesClause->getSizesRefs()[I];
14781 Scope *CurScope = getCurScope();
14782
14783 // Commonly used variables.
14784 DeclRefExpr *TileIV = buildDeclRefExpr(*this, TileIndVars[I], CntTy,
14785 OrigCntVar->getExprLoc());
14786 DeclRefExpr *FloorIV = buildDeclRefExpr(*this, FloorIndVars[I], CntTy,
14787 OrigCntVar->getExprLoc());
14788
14789 // For init-statement: auto .tile.iv = .floor.iv
14790 AddInitializerToDecl(TileIndVars[I], DefaultLvalueConversion(FloorIV).get(),
14791 /*DirectInit=*/false);
14792 Decl *CounterDecl = TileIndVars[I];
14793 StmtResult InitStmt = new (Context)
14794 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
14795 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
14796 if (!InitStmt.isUsable())
14797 return StmtError();
14798
14799 // For cond-expression: .tile.iv < min(.floor.iv + DimTileSize,
14800 // NumIterations)
14801 ExprResult EndOfTile = BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(),
14802 BO_Add, FloorIV, DimTileSize);
14803 if (!EndOfTile.isUsable())
14804 return StmtError();
14805 ExprResult IsPartialTile =
14806 BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14807 NumIterations, EndOfTile.get());
14808 if (!IsPartialTile.isUsable())
14809 return StmtError();
14810 ExprResult MinTileAndIterSpace = ActOnConditionalOp(
14811 LoopHelper.Cond->getBeginLoc(), LoopHelper.Cond->getEndLoc(),
14812 IsPartialTile.get(), NumIterations, EndOfTile.get());
14813 if (!MinTileAndIterSpace.isUsable())
14814 return StmtError();
14815 ExprResult CondExpr = BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(),
14816 BO_LT, TileIV, MinTileAndIterSpace.get());
14817 if (!CondExpr.isUsable())
14818 return StmtError();
14819
14820 // For incr-statement: ++.tile.iv
14821 ExprResult IncrStmt =
14822 BuildUnaryOp(CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, TileIV);
14823 if (!IncrStmt.isUsable())
14824 return StmtError();
14825
14826 // Statements to set the original iteration variable's value from the
14827 // logical iteration number.
14828 // Generated for loop is:
14829 // Original_for_init;
14830 // for (auto .tile.iv = .floor.iv; .tile.iv < min(.floor.iv + DimTileSize,
14831 // NumIterations); ++.tile.iv) {
14832 // Original_Body;
14833 // Original_counter_update;
14834 // }
14835 // FIXME: If the innermost body is an loop itself, inserting these
14836 // statements stops it being recognized as a perfectly nested loop (e.g.
14837 // for applying tiling again). If this is the case, sink the expressions
14838 // further into the inner loop.
14839 SmallVector<Stmt *, 4> BodyParts;
14840 BodyParts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
14841 BodyParts.push_back(Inner);
14842 Inner = CompoundStmt::Create(Context, BodyParts, FPOptionsOverride(),
14843 Inner->getBeginLoc(), Inner->getEndLoc());
14844 Inner = new (Context)
14845 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
14846 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
14847 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14848 }
14849
14850 // Create floor loops from the inside to the outside.
14851 for (int I = NumLoops - 1; I >= 0; --I) {
14852 auto &LoopHelper = LoopHelpers[I];
14853 Expr *NumIterations = LoopHelper.NumIterations;
14854 DeclRefExpr *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
14855 QualType CntTy = OrigCntVar->getType();
14856 Expr *DimTileSize = SizesClause->getSizesRefs()[I];
14857 Scope *CurScope = getCurScope();
14858
14859 // Commonly used variables.
14860 DeclRefExpr *FloorIV = buildDeclRefExpr(*this, FloorIndVars[I], CntTy,
14861 OrigCntVar->getExprLoc());
14862
14863 // For init-statement: auto .floor.iv = 0
14864 AddInitializerToDecl(
14865 FloorIndVars[I],
14866 ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
14867 /*DirectInit=*/false);
14868 Decl *CounterDecl = FloorIndVars[I];
14869 StmtResult InitStmt = new (Context)
14870 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
14871 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
14872 if (!InitStmt.isUsable())
14873 return StmtError();
14874
14875 // For cond-expression: .floor.iv < NumIterations
14876 ExprResult CondExpr = BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(),
14877 BO_LT, FloorIV, NumIterations);
14878 if (!CondExpr.isUsable())
14879 return StmtError();
14880
14881 // For incr-statement: .floor.iv += DimTileSize
14882 ExprResult IncrStmt = BuildBinOp(CurScope, LoopHelper.Inc->getExprLoc(),
14883 BO_AddAssign, FloorIV, DimTileSize);
14884 if (!IncrStmt.isUsable())
14885 return StmtError();
14886
14887 Inner = new (Context)
14888 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
14889 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
14890 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14891 }
14892
14893 return OMPTileDirective::Create(Context, StartLoc, EndLoc, Clauses, NumLoops,
14894 AStmt, Inner,
14895 buildPreInits(Context, PreInits));
14896}
14897
14898StmtResult Sema::ActOnOpenMPUnrollDirective(ArrayRef<OMPClause *> Clauses,
14899 Stmt *AStmt,
14900 SourceLocation StartLoc,
14901 SourceLocation EndLoc) {
14902 // Empty statement should only be possible if there already was an error.
14903 if (!AStmt)
14904 return StmtError();
14905
14906 if (checkMutuallyExclusiveClauses(*this, Clauses, {OMPC_partial, OMPC_full}))
14907 return StmtError();
14908
14909 const OMPFullClause *FullClause =
14910 OMPExecutableDirective::getSingleClause<OMPFullClause>(Clauses);
14911 const OMPPartialClause *PartialClause =
14912 OMPExecutableDirective::getSingleClause<OMPPartialClause>(Clauses);
14913 assert(!(FullClause && PartialClause) &&(static_cast <bool> (!(FullClause && PartialClause
) && "mutual exclusivity must have been checked before"
) ? void (0) : __assert_fail ("!(FullClause && PartialClause) && \"mutual exclusivity must have been checked before\""
, "clang/lib/Sema/SemaOpenMP.cpp", 14914, __extension__ __PRETTY_FUNCTION__
))
14914 "mutual exclusivity must have been checked before")(static_cast <bool> (!(FullClause && PartialClause
) && "mutual exclusivity must have been checked before"
) ? void (0) : __assert_fail ("!(FullClause && PartialClause) && \"mutual exclusivity must have been checked before\""
, "clang/lib/Sema/SemaOpenMP.cpp", 14914, __extension__ __PRETTY_FUNCTION__
))
;
14915
14916 constexpr unsigned NumLoops = 1;
14917 Stmt *Body = nullptr;
14918 SmallVector<OMPLoopBasedDirective::HelperExprs, NumLoops> LoopHelpers(
14919 NumLoops);
14920 SmallVector<SmallVector<llvm::PointerUnion<Stmt *, Decl *>, 0>, NumLoops + 1>
14921 OriginalInits;
14922 if (!checkTransformableLoopNest(OMPD_unroll, AStmt, NumLoops, LoopHelpers,
14923 Body, OriginalInits))
14924 return StmtError();
14925
14926 unsigned NumGeneratedLoops = PartialClause ? 1 : 0;
14927
14928 // Delay unrolling to when template is completely instantiated.
14929 if (CurContext->isDependentContext())
14930 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
14931 NumGeneratedLoops, nullptr, nullptr);
14932
14933 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
14934
14935 if (FullClause) {
14936 if (!VerifyPositiveIntegerConstantInClause(
14937 LoopHelper.NumIterations, OMPC_full, /*StrictlyPositive=*/false,
14938 /*SuppressExprDiags=*/true)
14939 .isUsable()) {
14940 Diag(AStmt->getBeginLoc(), diag::err_omp_unroll_full_variable_trip_count);
14941 Diag(FullClause->getBeginLoc(), diag::note_omp_directive_here)
14942 << "#pragma omp unroll full";
14943 return StmtError();
14944 }
14945 }
14946
14947 // The generated loop may only be passed to other loop-associated directive
14948 // when a partial clause is specified. Without the requirement it is
14949 // sufficient to generate loop unroll metadata at code-generation.
14950 if (NumGeneratedLoops == 0)
14951 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
14952 NumGeneratedLoops, nullptr, nullptr);
14953
14954 // Otherwise, we need to provide a de-sugared/transformed AST that can be
14955 // associated with another loop directive.
14956 //
14957 // The canonical loop analysis return by checkTransformableLoopNest assumes
14958 // the following structure to be the same loop without transformations or
14959 // directives applied: \code OriginalInits; LoopHelper.PreInits;
14960 // LoopHelper.Counters;
14961 // for (; IV < LoopHelper.NumIterations; ++IV) {
14962 // LoopHelper.Updates;
14963 // Body;
14964 // }
14965 // \endcode
14966 // where IV is a variable declared and initialized to 0 in LoopHelper.PreInits
14967 // and referenced by LoopHelper.IterationVarRef.
14968 //
14969 // The unrolling directive transforms this into the following loop:
14970 // \code
14971 // OriginalInits; \
14972 // LoopHelper.PreInits; > NewPreInits
14973 // LoopHelper.Counters; /
14974 // for (auto UIV = 0; UIV < LoopHelper.NumIterations; UIV+=Factor) {
14975 // #pragma clang loop unroll_count(Factor)
14976 // for (IV = UIV; IV < UIV + Factor && UIV < LoopHelper.NumIterations; ++IV)
14977 // {
14978 // LoopHelper.Updates;
14979 // Body;
14980 // }
14981 // }
14982 // \endcode
14983 // where UIV is a new logical iteration counter. IV must be the same VarDecl
14984 // as the original LoopHelper.IterationVarRef because LoopHelper.Updates
14985 // references it. If the partially unrolled loop is associated with another
14986 // loop directive (like an OMPForDirective), it will use checkOpenMPLoop to
14987 // analyze this loop, i.e. the outer loop must fulfill the constraints of an
14988 // OpenMP canonical loop. The inner loop is not an associable canonical loop
14989 // and only exists to defer its unrolling to LLVM's LoopUnroll instead of
14990 // doing it in the frontend (by adding loop metadata). NewPreInits becomes a
14991 // property of the OMPLoopBasedDirective instead of statements in
14992 // CompoundStatement. This is to allow the loop to become a non-outermost loop
14993 // of a canonical loop nest where these PreInits are emitted before the
14994 // outermost directive.
14995
14996 // Determine the PreInit declarations.
14997 SmallVector<Decl *, 4> PreInits;
14998 assert(OriginalInits.size() == 1 &&(static_cast <bool> (OriginalInits.size() == 1 &&
"Expecting a single-dimensional loop iteration space") ? void
(0) : __assert_fail ("OriginalInits.size() == 1 && \"Expecting a single-dimensional loop iteration space\""
, "clang/lib/Sema/SemaOpenMP.cpp", 14999, __extension__ __PRETTY_FUNCTION__
))
14999 "Expecting a single-dimensional loop iteration space")(static_cast <bool> (OriginalInits.size() == 1 &&
"Expecting a single-dimensional loop iteration space") ? void
(0) : __assert_fail ("OriginalInits.size() == 1 && \"Expecting a single-dimensional loop iteration space\""
, "clang/lib/Sema/SemaOpenMP.cpp", 14999, __extension__ __PRETTY_FUNCTION__
))
;
15000 for (auto &P : OriginalInits[0]) {
15001 if (auto *D = P.dyn_cast<Decl *>())
15002 PreInits.push_back(D);
15003 else if (auto *PI = dyn_cast_or_null<DeclStmt>(P.dyn_cast<Stmt *>()))
15004 PreInits.append(PI->decl_begin(), PI->decl_end());
15005 }
15006 if (auto *PI = cast_or_null<DeclStmt>(LoopHelper.PreInits))
15007 PreInits.append(PI->decl_begin(), PI->decl_end());
15008 // Gather declarations for the data members used as counters.
15009 for (Expr *CounterRef : LoopHelper.Counters) {
15010 auto *CounterDecl = cast<DeclRefExpr>(CounterRef)->getDecl();
15011 if (isa<OMPCapturedExprDecl>(CounterDecl))
15012 PreInits.push_back(CounterDecl);
15013 }
15014
15015 auto *IterationVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
15016 QualType IVTy = IterationVarRef->getType();
15017 assert(LoopHelper.Counters.size() == 1 &&(static_cast <bool> (LoopHelper.Counters.size() == 1 &&
"Expecting a single-dimensional loop iteration space") ? void
(0) : __assert_fail ("LoopHelper.Counters.size() == 1 && \"Expecting a single-dimensional loop iteration space\""
, "clang/lib/Sema/SemaOpenMP.cpp", 15018, __extension__ __PRETTY_FUNCTION__
))
15018 "Expecting a single-dimensional loop iteration space")(static_cast <bool> (LoopHelper.Counters.size() == 1 &&
"Expecting a single-dimensional loop iteration space") ? void
(0) : __assert_fail ("LoopHelper.Counters.size() == 1 && \"Expecting a single-dimensional loop iteration space\""
, "clang/lib/Sema/SemaOpenMP.cpp", 15018, __extension__ __PRETTY_FUNCTION__
))
;
15019 auto *OrigVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
15020
15021 // Determine the unroll factor.
15022 uint64_t Factor;
15023 SourceLocation FactorLoc;
15024 if (Expr *FactorVal = PartialClause->getFactor()) {
15025 Factor = FactorVal->getIntegerConstantExpr(Context)->getZExtValue();
15026 FactorLoc = FactorVal->getExprLoc();
15027 } else {
15028 // TODO: Use a better profitability model.
15029 Factor = 2;
15030 }
15031 assert(Factor > 0 && "Expected positive unroll factor")(static_cast <bool> (Factor > 0 && "Expected positive unroll factor"
) ? void (0) : __assert_fail ("Factor > 0 && \"Expected positive unroll factor\""
, "clang/lib/Sema/SemaOpenMP.cpp", 15031, __extension__ __PRETTY_FUNCTION__
))
;
15032 auto MakeFactorExpr = [this, Factor, IVTy, FactorLoc]() {
15033 return IntegerLiteral::Create(
15034 Context, llvm::APInt(Context.getIntWidth(IVTy), Factor), IVTy,
15035 FactorLoc);
15036 };
15037
15038 // Iteration variable SourceLocations.
15039 SourceLocation OrigVarLoc = OrigVar->getExprLoc();
15040 SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
15041 SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
15042
15043 // Internal variable names.
15044 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
15045 std::string OuterIVName = (Twine(".unrolled.iv.") + OrigVarName).str();
15046 std::string InnerIVName = (Twine(".unroll_inner.iv.") + OrigVarName).str();
15047 std::string InnerTripCountName =
15048 (Twine(".unroll_inner.tripcount.") + OrigVarName).str();
15049
15050 // Create the iteration variable for the unrolled loop.
15051 VarDecl *OuterIVDecl =
15052 buildVarDecl(*this, {}, IVTy, OuterIVName, nullptr, OrigVar);
15053 auto MakeOuterRef = [this, OuterIVDecl, IVTy, OrigVarLoc]() {
15054 return buildDeclRefExpr(*this, OuterIVDecl, IVTy, OrigVarLoc);
15055 };
15056
15057 // Iteration variable for the inner loop: Reuse the iteration variable created
15058 // by checkOpenMPLoop.
15059 auto *InnerIVDecl = cast<VarDecl>(IterationVarRef->getDecl());
15060 InnerIVDecl->setDeclName(&PP.getIdentifierTable().get(InnerIVName));
15061 auto MakeInnerRef = [this, InnerIVDecl, IVTy, OrigVarLoc]() {
15062 return buildDeclRefExpr(*this, InnerIVDecl, IVTy, OrigVarLoc);
15063 };
15064
15065 // Make a copy of the NumIterations expression for each use: By the AST
15066 // constraints, every expression object in a DeclContext must be unique.
15067 CaptureVars CopyTransformer(*this);
15068 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() -> Expr * {
15069 return AssertSuccess(
15070 CopyTransformer.TransformExpr(LoopHelper.NumIterations));
15071 };
15072
15073 // Inner For init-statement: auto .unroll_inner.iv = .unrolled.iv
15074 ExprResult LValueConv = DefaultLvalueConversion(MakeOuterRef());
15075 AddInitializerToDecl(InnerIVDecl, LValueConv.get(), /*DirectInit=*/false);
15076 StmtResult InnerInit = new (Context)
15077 DeclStmt(DeclGroupRef(InnerIVDecl), OrigVarLocBegin, OrigVarLocEnd);
15078 if (!InnerInit.isUsable())
15079 return StmtError();
15080
15081 // Inner For cond-expression:
15082 // \code
15083 // .unroll_inner.iv < .unrolled.iv + Factor &&
15084 // .unroll_inner.iv < NumIterations
15085 // \endcode
15086 // This conjunction of two conditions allows ScalarEvolution to derive the
15087 // maximum trip count of the inner loop.
15088 ExprResult EndOfTile = BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(),
15089 BO_Add, MakeOuterRef(), MakeFactorExpr());
15090 if (!EndOfTile.isUsable())
15091 return StmtError();
15092 ExprResult InnerCond1 = BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(),
15093 BO_LT, MakeInnerRef(), EndOfTile.get());
15094 if (!InnerCond1.isUsable())
15095 return StmtError();
15096 ExprResult InnerCond2 =
15097 BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT, MakeInnerRef(),
15098 MakeNumIterations());
15099 if (!InnerCond2.isUsable())
15100 return StmtError();
15101 ExprResult InnerCond =
15102 BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LAnd,
15103 InnerCond1.get(), InnerCond2.get());
15104 if (!InnerCond.isUsable())
15105 return StmtError();
15106
15107 // Inner For incr-statement: ++.unroll_inner.iv
15108 ExprResult InnerIncr = BuildUnaryOp(CurScope, LoopHelper.Inc->getExprLoc(),
15109 UO_PreInc, MakeInnerRef());
15110 if (!InnerIncr.isUsable())
15111 return StmtError();
15112
15113 // Inner For statement.
15114 SmallVector<Stmt *> InnerBodyStmts;
15115 InnerBodyStmts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
15116 InnerBodyStmts.push_back(Body);
15117 CompoundStmt *InnerBody =
15118 CompoundStmt::Create(Context, InnerBodyStmts, FPOptionsOverride(),
15119 Body->getBeginLoc(), Body->getEndLoc());
15120 ForStmt *InnerFor = new (Context)
15121 ForStmt(Context, InnerInit.get(), InnerCond.get(), nullptr,
15122 InnerIncr.get(), InnerBody, LoopHelper.Init->getBeginLoc(),
15123 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15124
15125 // Unroll metadata for the inner loop.
15126 // This needs to take into account the remainder portion of the unrolled loop,
15127 // hence `unroll(full)` does not apply here, even though the LoopUnroll pass
15128 // supports multiple loop exits. Instead, unroll using a factor equivalent to
15129 // the maximum trip count, which will also generate a remainder loop. Just
15130 // `unroll(enable)` (which could have been useful if the user has not
15131 // specified a concrete factor; even though the outer loop cannot be
15132 // influenced anymore, would avoid more code bloat than necessary) will refuse
15133 // the loop because "Won't unroll; remainder loop could not be generated when
15134 // assuming runtime trip count". Even if it did work, it must not choose a
15135 // larger unroll factor than the maximum loop length, or it would always just
15136 // execute the remainder loop.
15137 LoopHintAttr *UnrollHintAttr =
15138 LoopHintAttr::CreateImplicit(Context, LoopHintAttr::UnrollCount,
15139 LoopHintAttr::Numeric, MakeFactorExpr());
15140 AttributedStmt *InnerUnrolled =
15141 AttributedStmt::Create(Context, StartLoc, {UnrollHintAttr}, InnerFor);
15142
15143 // Outer For init-statement: auto .unrolled.iv = 0
15144 AddInitializerToDecl(
15145 OuterIVDecl, ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
15146 /*DirectInit=*/false);
15147 StmtResult OuterInit = new (Context)
15148 DeclStmt(DeclGroupRef(OuterIVDecl), OrigVarLocBegin, OrigVarLocEnd);
15149 if (!OuterInit.isUsable())
15150 return StmtError();
15151
15152 // Outer For cond-expression: .unrolled.iv < NumIterations
15153 ExprResult OuterConde =
15154 BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT, MakeOuterRef(),
15155 MakeNumIterations());
15156 if (!OuterConde.isUsable())
15157 return StmtError();
15158
15159 // Outer For incr-statement: .unrolled.iv += Factor
15160 ExprResult OuterIncr =
15161 BuildBinOp(CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
15162 MakeOuterRef(), MakeFactorExpr());
15163 if (!OuterIncr.isUsable())
15164 return StmtError();
15165
15166 // Outer For statement.
15167 ForStmt *OuterFor = new (Context)
15168 ForStmt(Context, OuterInit.get(), OuterConde.get(), nullptr,
15169 OuterIncr.get(), InnerUnrolled, LoopHelper.Init->getBeginLoc(),
15170 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15171
15172 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
15173 NumGeneratedLoops, OuterFor,
15174 buildPreInits(Context, PreInits));
15175}
15176
15177OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
15178 SourceLocation StartLoc,
15179 SourceLocation LParenLoc,
15180 SourceLocation EndLoc) {
15181 OMPClause *Res = nullptr;
15182 switch (Kind) {
15183 case OMPC_final:
15184 Res = ActOnOpenMPFinalClause(Expr, StartLoc, LParenLoc, EndLoc);
15185 break;
15186 case OMPC_num_threads:
15187 Res = ActOnOpenMPNumThreadsClause(Expr, StartLoc, LParenLoc, EndLoc);
15188 break;
15189 case OMPC_safelen:
15190 Res = ActOnOpenMPSafelenClause(Expr, StartLoc, LParenLoc, EndLoc);
15191 break;
15192 case OMPC_simdlen:
15193 Res = ActOnOpenMPSimdlenClause(Expr, StartLoc, LParenLoc, EndLoc);
15194 break;
15195 case OMPC_allocator:
15196 Res = ActOnOpenMPAllocatorClause(Expr, StartLoc, LParenLoc, EndLoc);
15197 break;
15198 case OMPC_collapse:
15199 Res = ActOnOpenMPCollapseClause(Expr, StartLoc, LParenLoc, EndLoc);
15200 break;
15201 case OMPC_ordered:
15202 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc, LParenLoc, Expr);
15203 break;
15204 case OMPC_num_teams:
15205 Res = ActOnOpenMPNumTeamsClause(Expr, StartLoc, LParenLoc, EndLoc);
15206 break;
15207 case OMPC_thread_limit:
15208 Res = ActOnOpenMPThreadLimitClause(Expr, StartLoc, LParenLoc, EndLoc);
15209 break;
15210 case OMPC_priority:
15211 Res = ActOnOpenMPPriorityClause(Expr, StartLoc, LParenLoc, EndLoc);
15212 break;
15213 case OMPC_hint:
15214 Res = ActOnOpenMPHintClause(Expr, StartLoc, LParenLoc, EndLoc);
15215 break;
15216 case OMPC_depobj:
15217 Res = ActOnOpenMPDepobjClause(Expr, StartLoc, LParenLoc, EndLoc);
15218 break;
15219 case OMPC_detach:
15220 Res = ActOnOpenMPDetachClause(Expr, StartLoc, LParenLoc, EndLoc);
15221 break;
15222 case OMPC_novariants:
15223 Res = ActOnOpenMPNovariantsClause(Expr, StartLoc, LParenLoc, EndLoc);
15224 break;
15225 case OMPC_nocontext:
15226 Res = ActOnOpenMPNocontextClause(Expr, StartLoc, LParenLoc, EndLoc);
15227 break;
15228 case OMPC_filter:
15229 Res = ActOnOpenMPFilterClause(Expr, StartLoc, LParenLoc, EndLoc);
15230 break;
15231 case OMPC_partial:
15232 Res = ActOnOpenMPPartialClause(Expr, StartLoc, LParenLoc, EndLoc);
15233 break;
15234 case OMPC_message:
15235 Res = ActOnOpenMPMessageClause(Expr, StartLoc, LParenLoc, EndLoc);
15236 break;
15237 case OMPC_align:
15238 Res = ActOnOpenMPAlignClause(Expr, StartLoc, LParenLoc, EndLoc);
15239 break;
15240 case OMPC_ompx_dyn_cgroup_mem:
15241 Res = ActOnOpenMPXDynCGroupMemClause(Expr, StartLoc, LParenLoc, EndLoc);
15242 break;
15243 case OMPC_grainsize:
15244 case OMPC_num_tasks:
15245 case OMPC_device:
15246 case OMPC_if:
15247 case OMPC_default:
15248 case OMPC_proc_bind:
15249 case OMPC_schedule:
15250 case OMPC_private:
15251 case OMPC_firstprivate:
15252 case OMPC_lastprivate:
15253 case OMPC_shared:
15254 case OMPC_reduction:
15255 case OMPC_task_reduction:
15256 case OMPC_in_reduction:
15257 case OMPC_linear:
15258 case OMPC_aligned:
15259 case OMPC_copyin:
15260 case OMPC_copyprivate:
15261 case OMPC_nowait:
15262 case OMPC_untied:
15263 case OMPC_mergeable:
15264 case OMPC_threadprivate:
15265 case OMPC_sizes:
15266 case OMPC_allocate:
15267 case OMPC_flush:
15268 case OMPC_read:
15269 case OMPC_write:
15270 case OMPC_update:
15271 case OMPC_capture:
15272 case OMPC_compare:
15273 case OMPC_seq_cst:
15274 case OMPC_acq_rel:
15275 case OMPC_acquire:
15276 case OMPC_release:
15277 case OMPC_relaxed:
15278 case OMPC_depend:
15279 case OMPC_threads:
15280 case OMPC_simd:
15281 case OMPC_map:
15282 case OMPC_nogroup:
15283 case OMPC_dist_schedule:
15284 case OMPC_defaultmap:
15285 case OMPC_unknown:
15286 case OMPC_uniform:
15287 case OMPC_to:
15288 case OMPC_from:
15289 case OMPC_use_device_ptr:
15290 case OMPC_use_device_addr:
15291 case OMPC_is_device_ptr:
15292 case OMPC_unified_address:
15293 case OMPC_unified_shared_memory:
15294 case OMPC_reverse_offload:
15295 case OMPC_dynamic_allocators:
15296 case OMPC_atomic_default_mem_order:
15297 case OMPC_device_type:
15298 case OMPC_match:
15299 case OMPC_nontemporal:
15300 case OMPC_order:
15301 case OMPC_at:
15302 case OMPC_severity:
15303 case OMPC_destroy:
15304 case OMPC_inclusive:
15305 case OMPC_exclusive:
15306 case OMPC_uses_allocators:
15307 case OMPC_affinity:
15308 case OMPC_when:
15309 case OMPC_bind:
15310 default:
15311 llvm_unreachable("Clause is not allowed.")::llvm::llvm_unreachable_internal("Clause is not allowed.", "clang/lib/Sema/SemaOpenMP.cpp"
, 15311)
;
15312 }
15313 return Res;
15314}
15315
15316// An OpenMP directive such as 'target parallel' has two captured regions:
15317// for the 'target' and 'parallel' respectively. This function returns
15318// the region in which to capture expressions associated with a clause.
15319// A return value of OMPD_unknown signifies that the expression should not
15320// be captured.
15321static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
15322 OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, unsigned OpenMPVersion,
15323 OpenMPDirectiveKind NameModifier = OMPD_unknown) {
15324 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
15325 switch (CKind) {
15326 case OMPC_if:
15327 switch (DKind) {
15328 case OMPD_target_parallel_for_simd:
15329 if (OpenMPVersion >= 50 &&
15330 (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)) {
15331 CaptureRegion = OMPD_parallel;
15332 break;
15333 }
15334 [[fallthrough]];
15335 case OMPD_target_parallel:
15336 case OMPD_target_parallel_for:
15337 case OMPD_target_parallel_loop:
15338 // If this clause applies to the nested 'parallel' region, capture within
15339 // the 'target' region, otherwise do not capture.
15340 if (NameModifier == OMPD_unknown || NameModifier == OMPD_parallel)
15341 CaptureRegion = OMPD_target;
15342 break;
15343 case OMPD_target_teams_distribute_parallel_for_simd:
15344 if (OpenMPVersion >= 50 &&
15345 (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)) {
15346 CaptureRegion = OMPD_parallel;
15347 break;
15348 }
15349 [[fallthrough]];
15350 case OMPD_target_teams_distribute_parallel_for:
15351 // If this clause applies to the nested 'parallel' region, capture within
15352 // the 'teams' region, otherwise do not capture.
15353 if (NameModifier == OMPD_unknown || NameModifier == OMPD_parallel)
15354 CaptureRegion = OMPD_teams;
15355 break;
15356 case OMPD_teams_distribute_parallel_for_simd:
15357 if (OpenMPVersion >= 50 &&
15358 (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)) {
15359 CaptureRegion = OMPD_parallel;
15360 break;
15361 }
15362 [[fallthrough]];
15363 case OMPD_teams_distribute_parallel_for:
15364 CaptureRegion = OMPD_teams;
15365 break;
15366 case OMPD_target_update:
15367 case OMPD_target_enter_data:
15368 case OMPD_target_exit_data:
15369 CaptureRegion = OMPD_task;
15370 break;
15371 case OMPD_parallel_masked_taskloop:
15372 if (NameModifier == OMPD_unknown || NameModifier == OMPD_taskloop)
15373 CaptureRegion = OMPD_parallel;
15374 break;
15375 case OMPD_parallel_master_taskloop:
15376 if (NameModifier == OMPD_unknown || NameModifier == OMPD_taskloop)
15377 CaptureRegion = OMPD_parallel;
15378 break;
15379 case OMPD_parallel_masked_taskloop_simd:
15380 if ((OpenMPVersion <= 45 && NameModifier == OMPD_unknown) ||
15381 NameModifier == OMPD_taskloop) {
15382 CaptureRegion = OMPD_parallel;
15383 break;
15384 }
15385 if (OpenMPVersion <= 45)
15386 break;
15387 if (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)
15388 CaptureRegion = OMPD_taskloop;
15389 break;
15390 case OMPD_parallel_master_taskloop_simd:
15391 if ((OpenMPVersion <= 45 && NameModifier == OMPD_unknown) ||
15392 NameModifier == OMPD_taskloop) {
15393 CaptureRegion = OMPD_parallel;
15394 break;
15395 }
15396 if (OpenMPVersion <= 45)
15397 break;
15398 if (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)
15399 CaptureRegion = OMPD_taskloop;
15400 break;
15401 case OMPD_parallel_for_simd:
15402 if (OpenMPVersion <= 45)
15403 break;
15404 if (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)
15405 CaptureRegion = OMPD_parallel;
15406 break;
15407 case OMPD_taskloop_simd:
15408 case OMPD_master_taskloop_simd:
15409 case OMPD_masked_taskloop_simd:
15410 if (OpenMPVersion <= 45)
15411 break;
15412 if (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)
15413 CaptureRegion = OMPD_taskloop;
15414 break;
15415 case OMPD_distribute_parallel_for_simd:
15416 if (OpenMPVersion <= 45)
15417 break;
15418 if (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)
15419 CaptureRegion = OMPD_parallel;
15420 break;
15421 case OMPD_target_simd:
15422 if (OpenMPVersion >= 50 &&
15423 (NameModifier == OMPD_unknown || NameModifier == OMPD_simd))
15424 CaptureRegion = OMPD_target;
15425 break;
15426 case OMPD_teams_distribute_simd:
15427 case OMPD_target_teams_distribute_simd:
15428 if (OpenMPVersion >= 50 &&
15429 (NameModifier == OMPD_unknown || NameModifier == OMPD_simd))
15430 CaptureRegion = OMPD_teams;
15431 break;
15432 case OMPD_cancel:
15433 case OMPD_parallel:
15434 case OMPD_parallel_master:
15435 case OMPD_parallel_masked:
15436 case OMPD_parallel_sections:
15437 case OMPD_parallel_for:
15438 case OMPD_parallel_loop:
15439 case OMPD_target:
15440 case OMPD_target_teams:
15441 case OMPD_target_teams_distribute:
15442 case OMPD_target_teams_loop:
15443 case OMPD_distribute_parallel_for:
15444 case OMPD_task:
15445 case OMPD_taskloop:
15446 case OMPD_master_taskloop:
15447 case OMPD_masked_taskloop:
15448 case OMPD_target_data:
15449 case OMPD_simd:
15450 case OMPD_for_simd:
15451 case OMPD_distribute_simd:
15452 // Do not capture if-clause expressions.
15453 break;
15454 case OMPD_threadprivate:
15455 case OMPD_allocate:
15456 case OMPD_taskyield:
15457 case OMPD_error:
15458 case OMPD_barrier:
15459 case OMPD_taskwait:
15460 case OMPD_cancellation_point:
15461 case OMPD_flush:
15462 case OMPD_depobj:
15463 case OMPD_scan:
15464 case OMPD_declare_reduction:
15465 case OMPD_declare_mapper:
15466 case OMPD_declare_simd:
15467 case OMPD_declare_variant:
15468 case OMPD_begin_declare_variant:
15469 case OMPD_end_declare_variant:
15470 case OMPD_declare_target:
15471 case OMPD_end_declare_target:
15472 case OMPD_loop:
15473 case OMPD_teams_loop:
15474 case OMPD_teams:
15475 case OMPD_tile:
15476 case OMPD_unroll:
15477 case OMPD_for:
15478 case OMPD_sections:
15479 case OMPD_section:
15480 case OMPD_single:
15481 case OMPD_master:
15482 case OMPD_masked:
15483 case OMPD_critical:
15484 case OMPD_taskgroup:
15485 case OMPD_distribute:
15486 case OMPD_ordered:
15487 case OMPD_atomic:
15488 case OMPD_teams_distribute:
15489 case OMPD_requires:
15490 case OMPD_metadirective:
15491 llvm_unreachable("Unexpected OpenMP directive with if-clause")::llvm::llvm_unreachable_internal("Unexpected OpenMP directive with if-clause"
, "clang/lib/Sema/SemaOpenMP.cpp", 15491)
;
15492 case OMPD_unknown:
15493 default:
15494 llvm_unreachable("Unknown OpenMP directive")::llvm::llvm_unreachable_internal("Unknown OpenMP directive",
"clang/lib/Sema/SemaOpenMP.cpp", 15494)
;
15495 }
15496 break;
15497 case OMPC_num_threads:
15498 switch (DKind) {
15499 case OMPD_target_parallel:
15500 case OMPD_target_parallel_for:
15501 case OMPD_target_parallel_for_simd:
15502 case OMPD_target_parallel_loop:
15503 CaptureRegion = OMPD_target;
15504 break;
15505 case OMPD_teams_distribute_parallel_for:
15506 case OMPD_teams_distribute_parallel_for_simd:
15507 case OMPD_target_teams_distribute_parallel_for:
15508 case OMPD_target_teams_distribute_parallel_for_simd:
15509 CaptureRegion = OMPD_teams;
15510 break;
15511 case OMPD_parallel:
15512 case OMPD_parallel_master:
15513 case OMPD_parallel_masked:
15514 case OMPD_parallel_sections:
15515 case OMPD_parallel_for:
15516 case OMPD_parallel_for_simd:
15517 case OMPD_parallel_loop:
15518 case OMPD_distribute_parallel_for:
15519 case OMPD_distribute_parallel_for_simd:
15520 case OMPD_parallel_master_taskloop:
15521 case OMPD_parallel_masked_taskloop:
15522 case OMPD_parallel_master_taskloop_simd:
15523 case OMPD_parallel_masked_taskloop_simd:
15524 // Do not capture num_threads-clause expressions.
15525 break;
15526 case OMPD_target_data:
15527 case OMPD_target_enter_data:
15528 case OMPD_target_exit_data:
15529 case OMPD_target_update:
15530 case OMPD_target:
15531 case OMPD_target_simd:
15532 case OMPD_target_teams:
15533 case OMPD_target_teams_distribute:
15534 case OMPD_target_teams_distribute_simd:
15535 case OMPD_cancel:
15536 case OMPD_task:
15537 case OMPD_taskloop:
15538 case OMPD_taskloop_simd:
15539 case OMPD_master_taskloop:
15540 case OMPD_masked_taskloop:
15541 case OMPD_master_taskloop_simd:
15542 case OMPD_masked_taskloop_simd:
15543 case OMPD_threadprivate:
15544 case OMPD_allocate:
15545 case OMPD_taskyield:
15546 case OMPD_error:
15547 case OMPD_barrier:
15548 case OMPD_taskwait:
15549 case OMPD_cancellation_point:
15550 case OMPD_flush:
15551 case OMPD_depobj:
15552 case OMPD_scan:
15553 case OMPD_declare_reduction:
15554 case OMPD_declare_mapper:
15555 case OMPD_declare_simd:
15556 case OMPD_declare_variant:
15557 case OMPD_begin_declare_variant:
15558 case OMPD_end_declare_variant:
15559 case OMPD_declare_target:
15560 case OMPD_end_declare_target:
15561 case OMPD_loop:
15562 case OMPD_teams_loop:
15563 case OMPD_target_teams_loop:
15564 case OMPD_teams:
15565 case OMPD_simd:
15566 case OMPD_tile:
15567 case OMPD_unroll:
15568 case OMPD_for:
15569 case OMPD_for_simd:
15570 case OMPD_sections:
15571 case OMPD_section:
15572 case OMPD_single:
15573 case OMPD_master:
15574 case OMPD_masked:
15575 case OMPD_critical:
15576 case OMPD_taskgroup:
15577 case OMPD_distribute:
15578 case OMPD_ordered:
15579 case OMPD_atomic:
15580 case OMPD_distribute_simd:
15581 case OMPD_teams_distribute:
15582 case OMPD_teams_distribute_simd:
15583 case OMPD_requires:
15584 case OMPD_metadirective:
15585 llvm_unreachable("Unexpected OpenMP directive with num_threads-clause")::llvm::llvm_unreachable_internal("Unexpected OpenMP directive with num_threads-clause"
, "clang/lib/Sema/SemaOpenMP.cpp", 15585)
;
15586 case OMPD_unknown:
15587 default:
15588 llvm_unreachable("Unknown OpenMP directive")::llvm::llvm_unreachable_internal("Unknown OpenMP directive",
"clang/lib/Sema/SemaOpenMP.cpp", 15588)
;
15589 }
15590 break;
15591 case OMPC_num_teams:
15592 switch (DKind) {
15593 case OMPD_target_teams:
15594 case OMPD_target_teams_distribute:
15595 case OMPD_target_teams_distribute_simd:
15596 case OMPD_target_teams_distribute_parallel_for:
15597 case OMPD_target_teams_distribute_parallel_for_simd:
15598 case OMPD_target_teams_loop:
15599 CaptureRegion = OMPD_target;
15600 break;
15601 case OMPD_teams_distribute_parallel_for:
15602 case OMPD_teams_distribute_parallel_for_simd:
15603 case OMPD_teams:
15604 case OMPD_teams_distribute:
15605 case OMPD_teams_distribute_simd:
15606 case OMPD_teams_loop:
15607 // Do not capture num_teams-clause expressions.
15608 break;
15609 case OMPD_distribute_parallel_for:
15610 case OMPD_distribute_parallel_for_simd:
15611 case OMPD_task:
15612 case OMPD_taskloop:
15613 case OMPD_taskloop_simd:
15614 case OMPD_master_taskloop:
15615 case OMPD_masked_taskloop:
15616 case OMPD_master_taskloop_simd:
15617 case OMPD_masked_taskloop_simd:
15618 case OMPD_parallel_master_taskloop:
15619 case OMPD_parallel_masked_taskloop:
15620 case OMPD_parallel_master_taskloop_simd:
15621 case OMPD_parallel_masked_taskloop_simd:
15622 case OMPD_target_data:
15623 case OMPD_target_enter_data:
15624 case OMPD_target_exit_data:
15625 case OMPD_target_update:
15626 case OMPD_cancel:
15627 case OMPD_parallel:
15628 case OMPD_parallel_master:
15629 case OMPD_parallel_masked:
15630 case OMPD_parallel_sections:
15631 case OMPD_parallel_for:
15632 case OMPD_parallel_for_simd:
15633 case OMPD_parallel_loop:
15634 case OMPD_target:
15635 case OMPD_target_simd:
15636 case OMPD_target_parallel:
15637 case OMPD_target_parallel_for:
15638 case OMPD_target_parallel_for_simd:
15639 case OMPD_target_parallel_loop:
15640 case OMPD_threadprivate:
15641 case OMPD_allocate:
15642 case OMPD_taskyield:
15643 case OMPD_error:
15644 case OMPD_barrier:
15645 case OMPD_taskwait:
15646 case OMPD_cancellation_point:
15647 case OMPD_flush:
15648 case OMPD_depobj:
15649 case OMPD_scan:
15650 case OMPD_declare_reduction:
15651 case OMPD_declare_mapper:
15652 case OMPD_declare_simd:
15653 case OMPD_declare_variant:
15654 case OMPD_begin_declare_variant:
15655 case OMPD_end_declare_variant:
15656 case OMPD_declare_target:
15657 case OMPD_end_declare_target:
15658 case OMPD_loop:
15659 case OMPD_simd:
15660 case OMPD_tile:
15661 case OMPD_unroll:
15662 case OMPD_for:
15663 case OMPD_for_simd:
15664 case OMPD_sections:
15665 case OMPD_section:
15666 case OMPD_single:
15667 case OMPD_master:
15668 case OMPD_masked:
15669 case OMPD_critical:
15670 case OMPD_taskgroup:
15671 case OMPD_distribute:
15672 case OMPD_ordered:
15673 case OMPD_atomic:
15674 case OMPD_distribute_simd:
15675 case OMPD_requires:
15676 case OMPD_metadirective:
15677 llvm_unreachable("Unexpected OpenMP directive with num_teams-clause")::llvm::llvm_unreachable_internal("Unexpected OpenMP directive with num_teams-clause"
, "clang/lib/Sema/SemaOpenMP.cpp", 15677)
;
15678 case OMPD_unknown:
15679 default:
15680 llvm_unreachable("Unknown OpenMP directive")::llvm::llvm_unreachable_internal("Unknown OpenMP directive",
"clang/lib/Sema/SemaOpenMP.cpp", 15680)
;
15681 }
15682 break;
15683 case OMPC_thread_limit:
15684 switch (DKind) {
15685 case OMPD_target:
15686 case OMPD_target_teams:
15687 case OMPD_target_teams_distribute:
15688 case OMPD_target_teams_distribute_simd:
15689 case OMPD_target_teams_distribute_parallel_for:
15690 case OMPD_target_teams_distribute_parallel_for_simd:
15691 case OMPD_target_teams_loop:
15692 CaptureRegion = OMPD_target;
15693 break;
15694 case OMPD_teams_distribute_parallel_for:
15695 case OMPD_teams_distribute_parallel_for_simd:
15696 case OMPD_teams:
15697 case OMPD_teams_distribute:
15698 case OMPD_teams_distribute_simd:
15699 case OMPD_teams_loop:
15700 // Do not capture thread_limit-clause expressions.
15701 break;
15702 case OMPD_distribute_parallel_for:
15703 case OMPD_distribute_parallel_for_simd:
15704 case OMPD_task:
15705 case OMPD_taskloop:
15706 case OMPD_taskloop_simd:
15707 case OMPD_master_taskloop:
15708 case OMPD_masked_taskloop:
15709 case OMPD_master_taskloop_simd:
15710 case OMPD_masked_taskloop_simd:
15711 case OMPD_parallel_master_taskloop:
15712 case OMPD_parallel_masked_taskloop:
15713 case OMPD_parallel_master_taskloop_simd:
15714 case OMPD_parallel_masked_taskloop_simd:
15715 case OMPD_target_data:
15716 case OMPD_target_enter_data:
15717 case OMPD_target_exit_data:
15718 case OMPD_target_update:
15719 case OMPD_cancel:
15720 case OMPD_parallel:
15721 case OMPD_parallel_master:
15722 case OMPD_parallel_masked:
15723 case OMPD_parallel_sections:
15724 case OMPD_parallel_for:
15725 case OMPD_parallel_for_simd:
15726 case OMPD_parallel_loop:
15727 case OMPD_target_simd:
15728 case OMPD_target_parallel:
15729 case OMPD_target_parallel_for:
15730 case OMPD_target_parallel_for_simd:
15731 case OMPD_target_parallel_loop:
15732 case OMPD_threadprivate:
15733 case OMPD_allocate:
15734 case OMPD_taskyield:
15735 case OMPD_error:
15736 case OMPD_barrier:
15737 case OMPD_taskwait:
15738 case OMPD_cancellation_point:
15739 case OMPD_flush:
15740 case OMPD_depobj:
15741 case OMPD_scan:
15742 case OMPD_declare_reduction:
15743 case OMPD_declare_mapper:
15744 case OMPD_declare_simd:
15745 case OMPD_declare_variant:
15746 case OMPD_begin_declare_variant:
15747 case OMPD_end_declare_variant:
15748 case OMPD_declare_target:
15749 case OMPD_end_declare_target:
15750 case OMPD_loop:
15751 case OMPD_simd:
15752 case OMPD_tile:
15753 case OMPD_unroll:
15754 case OMPD_for:
15755 case OMPD_for_simd:
15756 case OMPD_sections:
15757 case OMPD_section:
15758 case OMPD_single:
15759 case OMPD_master:
15760 case OMPD_masked:
15761 case OMPD_critical:
15762 case OMPD_taskgroup:
15763 case OMPD_distribute:
15764 case OMPD_ordered:
15765 case OMPD_atomic:
15766 case OMPD_distribute_simd:
15767 case OMPD_requires:
15768 case OMPD_metadirective:
15769 llvm_unreachable("Unexpected OpenMP directive with thread_limit-clause")::llvm::llvm_unreachable_internal("Unexpected OpenMP directive with thread_limit-clause"
, "clang/lib/Sema/SemaOpenMP.cpp", 15769)
;
15770 case OMPD_unknown:
15771 default:
15772 llvm_unreachable("Unknown OpenMP directive")::llvm::llvm_unreachable_internal("Unknown OpenMP directive",
"clang/lib/Sema/SemaOpenMP.cpp", 15772)
;
15773 }
15774 break;
15775 case OMPC_schedule:
15776 switch (DKind) {
15777 case OMPD_parallel_for:
15778 case OMPD_parallel_for_simd:
15779 case OMPD_distribute_parallel_for:
15780 case OMPD_distribute_parallel_for_simd:
15781 case OMPD_teams_distribute_parallel_for:
15782 case OMPD_teams_distribute_parallel_for_simd:
15783 case OMPD_target_parallel_for:
15784 case OMPD_target_parallel_for_simd:
15785 case OMPD_target_teams_distribute_parallel_for:
15786 case OMPD_target_teams_distribute_parallel_for_simd:
15787 CaptureRegion = OMPD_parallel;
15788 break;
15789 case OMPD_for:
15790 case OMPD_for_simd:
15791 // Do not capture schedule-clause expressions.
15792 break;
15793 case OMPD_task:
15794 case OMPD_taskloop:
15795 case OMPD_taskloop_simd:
15796 case OMPD_master_taskloop:
15797 case OMPD_masked_taskloop:
15798 case OMPD_master_taskloop_simd:
15799 case OMPD_masked_taskloop_simd:
15800 case OMPD_parallel_master_taskloop:
15801 case OMPD_parallel_masked_taskloop:
15802 case OMPD_parallel_master_taskloop_simd:
15803 case OMPD_parallel_masked_taskloop_simd:
15804 case OMPD_target_data:
15805 case OMPD_target_enter_data:
15806 case OMPD_target_exit_data:
15807 case OMPD_target_update:
15808 case OMPD_teams:
15809 case OMPD_teams_distribute:
15810 case OMPD_teams_distribute_simd:
15811 case OMPD_target_teams_distribute:
15812 case OMPD_target_teams_distribute_simd:
15813 case OMPD_target:
15814 case OMPD_target_simd:
15815 case OMPD_target_parallel:
15816 case OMPD_cancel:
15817 case OMPD_parallel:
15818 case OMPD_parallel_master:
15819 case OMPD_parallel_masked:
15820 case OMPD_parallel_sections:
15821 case OMPD_threadprivate:
15822 case OMPD_allocate:
15823 case OMPD_taskyield:
15824 case OMPD_error:
15825 case OMPD_barrier:
15826 case OMPD_taskwait:
15827 case OMPD_cancellation_point:
15828 case OMPD_flush:
15829 case OMPD_depobj:
15830 case OMPD_scan:
15831 case OMPD_declare_reduction:
15832 case OMPD_declare_mapper:
15833 case OMPD_declare_simd:
15834 case OMPD_declare_variant:
15835 case OMPD_begin_declare_variant:
15836 case OMPD_end_declare_variant:
15837 case OMPD_declare_target:
15838 case OMPD_end_declare_target:
15839 case OMPD_loop:
15840 case OMPD_teams_loop:
15841 case OMPD_target_teams_loop:
15842 case OMPD_parallel_loop:
15843 case OMPD_target_parallel_loop:
15844 case OMPD_simd:
15845 case OMPD_tile:
15846 case OMPD_unroll:
15847 case OMPD_sections:
15848 case OMPD_section:
15849 case OMPD_single:
15850 case OMPD_master:
15851 case OMPD_masked:
15852 case OMPD_critical:
15853 case OMPD_taskgroup:
15854 case OMPD_distribute:
15855 case OMPD_ordered:
15856 case OMPD_atomic:
15857 case OMPD_distribute_simd:
15858 case OMPD_target_teams:
15859 case OMPD_requires:
15860 case OMPD_metadirective:
15861 llvm_unreachable("Unexpected OpenMP directive with schedule clause")::llvm::llvm_unreachable_internal("Unexpected OpenMP directive with schedule clause"
, "clang/lib/Sema/SemaOpenMP.cpp", 15861)
;
15862 case OMPD_unknown:
15863 default:
15864 llvm_unreachable("Unknown OpenMP directive")::llvm::llvm_unreachable_internal("Unknown OpenMP directive",
"clang/lib/Sema/SemaOpenMP.cpp", 15864)
;
15865 }
15866 break;
15867 case OMPC_dist_schedule:
15868 switch (DKind) {
15869 case OMPD_teams_distribute_parallel_for:
15870 case OMPD_teams_distribute_parallel_for_simd:
15871 case OMPD_teams_distribute:
15872 case OMPD_teams_distribute_simd:
15873 case OMPD_target_teams_distribute_parallel_for:
15874 case OMPD_target_teams_distribute_parallel_for_simd:
15875 case OMPD_target_teams_distribute:
15876 case OMPD_target_teams_distribute_simd:
15877 CaptureRegion = OMPD_teams;
15878 break;
15879 case OMPD_distribute_parallel_for:
15880 case OMPD_distribute_parallel_for_simd:
15881 case OMPD_distribute:
15882 case OMPD_distribute_simd:
15883 // Do not capture dist_schedule-clause expressions.
15884 break;
15885 case OMPD_parallel_for:
15886 case OMPD_parallel_for_simd:
15887 case OMPD_target_parallel_for_simd:
15888 case OMPD_target_parallel_for:
15889 case OMPD_task:
15890 case OMPD_taskloop:
15891 case OMPD_taskloop_simd:
15892 case OMPD_master_taskloop:
15893 case OMPD_masked_taskloop:
15894 case OMPD_master_taskloop_simd:
15895 case OMPD_masked_taskloop_simd:
15896 case OMPD_parallel_master_taskloop:
15897 case OMPD_parallel_masked_taskloop:
15898 case OMPD_parallel_master_taskloop_simd:
15899 case OMPD_parallel_masked_taskloop_simd:
15900 case OMPD_target_data:
15901 case OMPD_target_enter_data:
15902 case OMPD_target_exit_data:
15903 case OMPD_target_update:
15904 case OMPD_teams:
15905 case OMPD_target:
15906 case OMPD_target_simd:
15907 case OMPD_target_parallel:
15908 case OMPD_cancel:
15909 case OMPD_parallel:
15910 case OMPD_parallel_master:
15911 case OMPD_parallel_masked:
15912 case OMPD_parallel_sections:
15913 case OMPD_threadprivate:
15914 case OMPD_allocate:
15915 case OMPD_taskyield:
15916 case OMPD_error:
15917 case OMPD_barrier:
15918 case OMPD_taskwait:
15919 case OMPD_cancellation_point:
15920 case OMPD_flush:
15921 case OMPD_depobj:
15922 case OMPD_scan:
15923 case OMPD_declare_reduction:
15924 case OMPD_declare_mapper:
15925 case OMPD_declare_simd:
15926 case OMPD_declare_variant:
15927 case OMPD_begin_declare_variant:
15928 case OMPD_end_declare_variant:
15929 case OMPD_declare_target:
15930 case OMPD_end_declare_target:
15931 case OMPD_loop:
15932 case OMPD_teams_loop:
15933 case OMPD_target_teams_loop:
15934 case OMPD_parallel_loop:
15935 case OMPD_target_parallel_loop:
15936 case OMPD_simd:
15937 case OMPD_tile:
15938 case OMPD_unroll:
15939 case OMPD_for:
15940 case OMPD_for_simd:
15941 case OMPD_sections:
15942 case OMPD_section:
15943 case OMPD_single:
15944 case OMPD_master:
15945 case OMPD_masked:
15946 case OMPD_critical:
15947 case OMPD_taskgroup:
15948 case OMPD_ordered:
15949 case OMPD_atomic:
15950 case OMPD_target_teams:
15951 case OMPD_requires:
15952 case OMPD_metadirective:
15953 llvm_unreachable("Unexpected OpenMP directive with dist_schedule clause")::llvm::llvm_unreachable_internal("Unexpected OpenMP directive with dist_schedule clause"
, "clang/lib/Sema/SemaOpenMP.cpp", 15953)
;
15954 case OMPD_unknown:
15955 default:
15956 llvm_unreachable("Unknown OpenMP directive")::llvm::llvm_unreachable_internal("Unknown OpenMP directive",
"clang/lib/Sema/SemaOpenMP.cpp", 15956)
;
15957 }
15958 break;
15959 case OMPC_ompx_dyn_cgroup_mem:
15960 switch (DKind) {
15961 case OMPD_target:
15962 case OMPD_target_simd:
15963 case OMPD_target_teams:
15964 case OMPD_target_parallel:
15965 case OMPD_target_teams_distribute:
15966 case OMPD_target_teams_distribute_simd:
15967 case OMPD_target_parallel_for:
15968 case OMPD_target_parallel_for_simd:
15969 case OMPD_target_parallel_loop:
15970 case OMPD_target_teams_distribute_parallel_for:
15971 case OMPD_target_teams_distribute_parallel_for_simd:
15972 case OMPD_target_teams_loop:
15973 CaptureRegion = OMPD_target;
15974 break;
15975 default:
15976 llvm_unreachable("Unknown OpenMP directive")::llvm::llvm_unreachable_internal("Unknown OpenMP directive",
"clang/lib/Sema/SemaOpenMP.cpp", 15976)
;
15977 }
15978 break;
15979 case OMPC_device:
15980 switch (DKind) {
15981 case OMPD_target_update:
15982 case OMPD_target_enter_data:
15983 case OMPD_target_exit_data:
15984 case OMPD_target:
15985 case OMPD_target_simd:
15986 case OMPD_target_teams:
15987 case OMPD_target_parallel:
15988 case OMPD_target_teams_distribute:
15989 case OMPD_target_teams_distribute_simd:
15990 case OMPD_target_parallel_for:
15991 case OMPD_target_parallel_for_simd:
15992 case OMPD_target_parallel_loop:
15993 case OMPD_target_teams_distribute_parallel_for:
15994 case OMPD_target_teams_distribute_parallel_for_simd:
15995 case OMPD_target_teams_loop:
15996 case OMPD_dispatch:
15997 CaptureRegion = OMPD_task;
15998 break;
15999 case OMPD_target_data:
16000 case OMPD_interop:
16001 // Do not capture device-clause expressions.
16002 break;
16003 case OMPD_teams_distribute_parallel_for:
16004 case OMPD_teams_distribute_parallel_for_simd:
16005 case OMPD_teams:
16006 case OMPD_teams_distribute:
16007 case OMPD_teams_distribute_simd:
16008 case OMPD_distribute_parallel_for:
16009 case OMPD_distribute_parallel_for_simd:
16010 case OMPD_task:
16011 case OMPD_taskloop:
16012 case OMPD_taskloop_simd:
16013 case OMPD_master_taskloop:
16014 case OMPD_masked_taskloop:
16015 case OMPD_master_taskloop_simd:
16016 case OMPD_masked_taskloop_simd:
16017 case OMPD_parallel_master_taskloop:
16018 case OMPD_parallel_masked_taskloop:
16019 case OMPD_parallel_master_taskloop_simd:
16020 case OMPD_parallel_masked_taskloop_simd:
16021 case OMPD_cancel:
16022 case OMPD_parallel:
16023 case OMPD_parallel_master:
16024 case OMPD_parallel_masked:
16025 case OMPD_parallel_sections:
16026 case OMPD_parallel_for:
16027 case OMPD_parallel_for_simd:
16028 case OMPD_threadprivate:
16029 case OMPD_allocate:
16030 case OMPD_taskyield:
16031 case OMPD_error:
16032 case OMPD_barrier:
16033 case OMPD_taskwait:
16034 case OMPD_cancellation_point:
16035 case OMPD_flush:
16036 case OMPD_depobj:
16037 case OMPD_scan:
16038 case OMPD_declare_reduction:
16039 case OMPD_declare_mapper:
16040 case OMPD_declare_simd:
16041 case OMPD_declare_variant:
16042 case OMPD_begin_declare_variant:
16043 case OMPD_end_declare_variant:
16044 case OMPD_declare_target:
16045 case OMPD_end_declare_target:
16046 case OMPD_loop:
16047 case OMPD_teams_loop:
16048 case OMPD_parallel_loop:
16049 case OMPD_simd:
16050 case OMPD_tile:
16051 case OMPD_unroll:
16052 case OMPD_for:
16053 case OMPD_for_simd:
16054 case OMPD_sections:
16055 case OMPD_section:
16056 case OMPD_single:
16057 case OMPD_master:
16058 case OMPD_masked:
16059 case OMPD_critical:
16060 case OMPD_taskgroup:
16061 case OMPD_distribute:
16062 case OMPD_ordered:
16063 case OMPD_atomic:
16064 case OMPD_distribute_simd:
16065 case OMPD_requires:
16066 case OMPD_metadirective:
16067 llvm_unreachable("Unexpected OpenMP directive with device-clause")::llvm::llvm_unreachable_internal("Unexpected OpenMP directive with device-clause"
, "clang/lib/Sema/SemaOpenMP.cpp", 16067)
;
16068 case OMPD_unknown:
16069 default:
16070 llvm_unreachable("Unknown OpenMP directive")::llvm::llvm_unreachable_internal("Unknown OpenMP directive",
"clang/lib/Sema/SemaOpenMP.cpp", 16070)
;
16071 }
16072 break;
16073 case OMPC_grainsize:
16074 case OMPC_num_tasks:
16075 case OMPC_final:
16076 case OMPC_priority:
16077 switch (DKind) {
16078 case OMPD_task:
16079 case OMPD_taskloop:
16080 case OMPD_taskloop_simd:
16081 case OMPD_master_taskloop:
16082 case OMPD_masked_taskloop:
16083 case OMPD_master_taskloop_simd:
16084 case OMPD_masked_taskloop_simd:
16085 break;
16086 case OMPD_parallel_masked_taskloop:
16087 case OMPD_parallel_masked_taskloop_simd:
16088 case OMPD_parallel_master_taskloop:
16089 case OMPD_parallel_master_taskloop_simd:
16090 CaptureRegion = OMPD_parallel;
16091 break;
16092 case OMPD_target_update:
16093 case OMPD_target_enter_data:
16094 case OMPD_target_exit_data:
16095 case OMPD_target:
16096 case OMPD_target_simd:
16097 case OMPD_target_teams:
16098 case OMPD_target_parallel:
16099 case OMPD_target_teams_distribute:
16100 case OMPD_target_teams_distribute_simd:
16101 case OMPD_target_parallel_for:
16102 case OMPD_target_parallel_for_simd:
16103 case OMPD_target_teams_distribute_parallel_for:
16104 case OMPD_target_teams_distribute_parallel_for_simd:
16105 case OMPD_target_data:
16106 case OMPD_teams_distribute_parallel_for:
16107 case OMPD_teams_distribute_parallel_for_simd:
16108 case OMPD_teams:
16109 case OMPD_teams_distribute:
16110 case OMPD_teams_distribute_simd:
16111 case OMPD_distribute_parallel_for:
16112 case OMPD_distribute_parallel_for_simd:
16113 case OMPD_cancel:
16114 case OMPD_parallel:
16115 case OMPD_parallel_master:
16116 case OMPD_parallel_masked:
16117 case OMPD_parallel_sections:
16118 case OMPD_parallel_for:
16119 case OMPD_parallel_for_simd:
16120 case OMPD_threadprivate:
16121 case OMPD_allocate:
16122 case OMPD_taskyield:
16123 case OMPD_error:
16124 case OMPD_barrier:
16125 case OMPD_taskwait:
16126 case OMPD_cancellation_point:
16127 case OMPD_flush:
16128 case OMPD_depobj:
16129 case OMPD_scan:
16130 case OMPD_declare_reduction:
16131 case OMPD_declare_mapper:
16132 case OMPD_declare_simd:
16133 case OMPD_declare_variant:
16134 case OMPD_begin_declare_variant:
16135 case OMPD_end_declare_variant:
16136 case OMPD_declare_target:
16137 case OMPD_end_declare_target:
16138 case OMPD_loop:
16139 case OMPD_teams_loop:
16140 case OMPD_target_teams_loop:
16141 case OMPD_parallel_loop:
16142 case OMPD_target_parallel_loop:
16143 case OMPD_simd:
16144 case OMPD_tile:
16145 case OMPD_unroll:
16146 case OMPD_for:
16147 case OMPD_for_simd:
16148 case OMPD_sections:
16149 case OMPD_section:
16150 case OMPD_single:
16151 case OMPD_master:
16152 case OMPD_masked:
16153 case OMPD_critical:
16154 case OMPD_taskgroup:
16155 case OMPD_distribute:
16156 case OMPD_ordered:
16157 case OMPD_atomic:
16158 case OMPD_distribute_simd:
16159 case OMPD_requires:
16160 case OMPD_metadirective:
16161 llvm_unreachable("Unexpected OpenMP directive with grainsize-clause")::llvm::llvm_unreachable_internal("Unexpected OpenMP directive with grainsize-clause"
, "clang/lib/Sema/SemaOpenMP.cpp", 16161)
;
16162 case OMPD_unknown:
16163 default:
16164 llvm_unreachable("Unknown OpenMP directive")::llvm::llvm_unreachable_internal("Unknown OpenMP directive",
"clang/lib/Sema/SemaOpenMP.cpp", 16164)
;
16165 }
16166 break;
16167 case OMPC_novariants:
16168 case OMPC_nocontext:
16169 switch (DKind) {
16170 case OMPD_dispatch:
16171 CaptureRegion = OMPD_task;
16172 break;
16173 default:
16174 llvm_unreachable("Unexpected OpenMP directive")::llvm::llvm_unreachable_internal("Unexpected OpenMP directive"
, "clang/lib/Sema/SemaOpenMP.cpp", 16174)
;
16175 }
16176 break;
16177 case OMPC_filter:
16178 // Do not capture filter-clause expressions.
16179 break;
16180 case OMPC_when:
16181 if (DKind == OMPD_metadirective) {
16182 CaptureRegion = OMPD_metadirective;
16183 } else if (DKind == OMPD_unknown) {
16184 llvm_unreachable("Unknown OpenMP directive")::llvm::llvm_unreachable_internal("Unknown OpenMP directive",
"clang/lib/Sema/SemaOpenMP.cpp", 16184)
;
16185 } else {
16186 llvm_unreachable("Unexpected OpenMP directive with when clause")::llvm::llvm_unreachable_internal("Unexpected OpenMP directive with when clause"
, "clang/lib/Sema/SemaOpenMP.cpp", 16186)
;
16187 }
16188 break;
16189 case OMPC_firstprivate:
16190 case OMPC_lastprivate:
16191 case OMPC_reduction:
16192 case OMPC_task_reduction:
16193 case OMPC_in_reduction:
16194 case OMPC_linear:
16195 case OMPC_default:
16196 case OMPC_proc_bind:
16197 case OMPC_safelen:
16198 case OMPC_simdlen:
16199 case OMPC_sizes:
16200 case OMPC_allocator:
16201 case OMPC_collapse:
16202 case OMPC_private:
16203 case OMPC_shared:
16204 case OMPC_aligned:
16205 case OMPC_copyin:
16206 case OMPC_copyprivate:
16207 case OMPC_ordered:
16208 case OMPC_nowait:
16209 case OMPC_untied:
16210 case OMPC_mergeable:
16211 case OMPC_threadprivate:
16212 case OMPC_allocate:
16213 case OMPC_flush:
16214 case OMPC_depobj:
16215 case OMPC_read:
16216 case OMPC_write:
16217 case OMPC_update:
16218 case OMPC_capture:
16219 case OMPC_compare:
16220 case OMPC_seq_cst:
16221 case OMPC_acq_rel:
16222 case OMPC_acquire:
16223 case OMPC_release:
16224 case OMPC_relaxed:
16225 case OMPC_depend:
16226 case OMPC_threads:
16227 case OMPC_simd:
16228 case OMPC_map:
16229 case OMPC_nogroup:
16230 case OMPC_hint:
16231 case OMPC_defaultmap:
16232 case OMPC_unknown:
16233 case OMPC_uniform:
16234 case OMPC_to:
16235 case OMPC_from:
16236 case OMPC_use_device_ptr:
16237 case OMPC_use_device_addr:
16238 case OMPC_is_device_ptr:
16239 case OMPC_unified_address:
16240 case OMPC_unified_shared_memory:
16241 case OMPC_reverse_offload:
16242 case OMPC_dynamic_allocators:
16243 case OMPC_atomic_default_mem_order:
16244 case OMPC_device_type:
16245 case OMPC_match:
16246 case OMPC_nontemporal:
16247 case OMPC_order:
16248 case OMPC_at:
16249 case OMPC_severity:
16250 case OMPC_message:
16251 case OMPC_destroy:
16252 case OMPC_detach:
16253 case OMPC_inclusive:
16254 case OMPC_exclusive:
16255 case OMPC_uses_allocators:
16256 case OMPC_affinity:
16257 case OMPC_bind:
16258 default:
16259 llvm_unreachable("Unexpected OpenMP clause.")::llvm::llvm_unreachable_internal("Unexpected OpenMP clause."
, "clang/lib/Sema/SemaOpenMP.cpp", 16259)
;
16260 }
16261 return CaptureRegion;
16262}
16263
16264OMPClause *Sema::ActOnOpenMPIfClause(OpenMPDirectiveKind NameModifier,
16265 Expr *Condition, SourceLocation StartLoc,
16266 SourceLocation LParenLoc,
16267 SourceLocation NameModifierLoc,
16268 SourceLocation ColonLoc,
16269 SourceLocation EndLoc) {
16270 Expr *ValExpr = Condition;
16271 Stmt *HelperValStmt = nullptr;
16272 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
16273 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
16274 !Condition->isInstantiationDependent() &&
16275 !Condition->containsUnexpandedParameterPack()) {
16276 ExprResult Val = CheckBooleanCondition(StartLoc, Condition);
16277 if (Val.isInvalid())
16278 return nullptr;
16279
16280 ValExpr = Val.get();
16281
16282 OpenMPDirectiveKind DKind = DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective();
16283 CaptureRegion = getOpenMPCaptureRegionForClause(
16284 DKind, OMPC_if, LangOpts.OpenMP, NameModifier);
16285 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
16286 ValExpr = MakeFullExpr(ValExpr).get();
16287 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16288 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
16289 HelperValStmt = buildPreInits(Context, Captures);
16290 }
16291 }
16292
16293 return new (Context)
16294 OMPIfClause(NameModifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
16295 LParenLoc, NameModifierLoc, ColonLoc, EndLoc);
16296}
16297
16298OMPClause *Sema::ActOnOpenMPFinalClause(Expr *Condition,
16299 SourceLocation StartLoc,
16300 SourceLocation LParenLoc,
16301 SourceLocation EndLoc) {
16302 Expr *ValExpr = Condition;
16303 Stmt *HelperValStmt = nullptr;
16304 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
16305 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
16306 !Condition->isInstantiationDependent() &&
16307 !Condition->containsUnexpandedParameterPack()) {
16308 ExprResult Val = CheckBooleanCondition(StartLoc, Condition);
16309 if (Val.isInvalid())
16310 return nullptr;
16311
16312 ValExpr = MakeFullExpr(Val.get()).get();
16313
16314 OpenMPDirectiveKind DKind = DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective();
16315 CaptureRegion =
16316 getOpenMPCaptureRegionForClause(DKind, OMPC_final, LangOpts.OpenMP);
16317 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
16318 ValExpr = MakeFullExpr(ValExpr).get();
16319 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16320 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
16321 HelperValStmt = buildPreInits(Context, Captures);
16322 }
16323 }
16324
16325 return new (Context) OMPFinalClause(ValExpr, HelperValStmt, CaptureRegion,
16326 StartLoc, LParenLoc, EndLoc);
16327}
16328
16329ExprResult Sema::PerformOpenMPImplicitIntegerConversion(SourceLocation Loc,
16330 Expr *Op) {
16331 if (!Op)
16332 return ExprError();
16333
16334 class IntConvertDiagnoser : public ICEConvertDiagnoser {
16335 public:
16336 IntConvertDiagnoser()
16337 : ICEConvertDiagnoser(/*AllowScopedEnumerations*/ false, false, true) {}
16338 SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
16339 QualType T) override {
16340 return S.Diag(Loc, diag::err_omp_not_integral) << T;
16341 }
16342 SemaDiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation Loc,
16343 QualType T) override {
16344 return S.Diag(Loc, diag::err_omp_incomplete_type) << T;
16345 }
16346 SemaDiagnosticBuilder diagnoseExplicitConv(Sema &S, SourceLocation Loc,
16347 QualType T,
16348 QualType ConvTy) override {
16349 return S.Diag(Loc, diag::err_omp_explicit_conversion) << T << ConvTy;
16350 }
16351 SemaDiagnosticBuilder noteExplicitConv(Sema &S, CXXConversionDecl *Conv,
16352 QualType ConvTy) override {
16353 return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
16354 << ConvTy->isEnumeralType() << ConvTy;
16355 }
16356 SemaDiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,
16357 QualType T) override {
16358 return S.Diag(Loc, diag::err_omp_ambiguous_conversion) << T;
16359 }
16360 SemaDiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl *Conv,
16361 QualType ConvTy) override {
16362 return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
16363 << ConvTy->isEnumeralType() << ConvTy;
16364 }
16365 SemaDiagnosticBuilder diagnoseConversion(Sema &, SourceLocation, QualType,
16366 QualType) override {
16367 llvm_unreachable("conversion functions are permitted")::llvm::llvm_unreachable_internal("conversion functions are permitted"
, "clang/lib/Sema/SemaOpenMP.cpp", 16367)
;
16368 }
16369 } ConvertDiagnoser;
16370 return PerformContextualImplicitConversion(Loc, Op, ConvertDiagnoser);
16371}
16372
16373static bool
16374isNonNegativeIntegerValue(Expr *&ValExpr, Sema &SemaRef, OpenMPClauseKind CKind,
16375 bool StrictlyPositive, bool BuildCapture = false,
16376 OpenMPDirectiveKind DKind = OMPD_unknown,
16377 OpenMPDirectiveKind *CaptureRegion = nullptr,
16378 Stmt **HelperValStmt = nullptr) {
16379 if (!ValExpr->isTypeDependent() && !ValExpr->isValueDependent() &&
16380 !ValExpr->isInstantiationDependent()) {
16381 SourceLocation Loc = ValExpr->getExprLoc();
16382 ExprResult Value =
16383 SemaRef.PerformOpenMPImplicitIntegerConversion(Loc, ValExpr);
16384 if (Value.isInvalid())
16385 return false;
16386
16387 ValExpr = Value.get();
16388 // The expression must evaluate to a non-negative integer value.
16389 if (std::optional<llvm::APSInt> Result =
16390 ValExpr->getIntegerConstantExpr(SemaRef.Context)) {
16391 if (Result->isSigned() &&
16392 !((!StrictlyPositive && Result->isNonNegative()) ||
16393 (StrictlyPositive && Result->isStrictlyPositive()))) {
16394 SemaRef.Diag(Loc, diag::err_omp_negative_expression_in_clause)
16395 << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0)
16396 << ValExpr->getSourceRange();
16397 return false;
16398 }
16399 }
16400 if (!BuildCapture)
16401 return true;
16402 *CaptureRegion =
16403 getOpenMPCaptureRegionForClause(DKind, CKind, SemaRef.LangOpts.OpenMP);
16404 if (*CaptureRegion != OMPD_unknown &&
16405 !SemaRef.CurContext->isDependentContext()) {
16406 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16407 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16408 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16409 *HelperValStmt = buildPreInits(SemaRef.Context, Captures);
16410 }
16411 }
16412 return true;
16413}
16414
16415OMPClause *Sema::ActOnOpenMPNumThreadsClause(Expr *NumThreads,
16416 SourceLocation StartLoc,
16417 SourceLocation LParenLoc,
16418 SourceLocation EndLoc) {
16419 Expr *ValExpr = NumThreads;
16420 Stmt *HelperValStmt = nullptr;
16421
16422 // OpenMP [2.5, Restrictions]
16423 // The num_threads expression must evaluate to a positive integer value.
16424 if (!isNonNegativeIntegerValue(ValExpr, *this, OMPC_num_threads,
16425 /*StrictlyPositive=*/true))
16426 return nullptr;
16427
16428 OpenMPDirectiveKind DKind = DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective();
16429 OpenMPDirectiveKind CaptureRegion =
16430 getOpenMPCaptureRegionForClause(DKind, OMPC_num_threads, LangOpts.OpenMP);
16431 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
16432 ValExpr = MakeFullExpr(ValExpr).get();
16433 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16434 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
16435 HelperValStmt = buildPreInits(Context, Captures);
16436 }
16437
16438 return new (Context) OMPNumThreadsClause(
16439 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
16440}
16441
16442ExprResult Sema::VerifyPositiveIntegerConstantInClause(Expr *E,
16443 OpenMPClauseKind CKind,
16444 bool StrictlyPositive,
16445 bool SuppressExprDiags) {
16446 if (!E)
16447 return ExprError();
16448 if (E->isValueDependent() || E->isTypeDependent() ||
16449 E->isInstantiationDependent() || E->containsUnexpandedParameterPack())
16450 return E;
16451
16452 llvm::APSInt Result;
16453 ExprResult ICE;
16454 if (SuppressExprDiags) {
16455 // Use a custom diagnoser that suppresses 'note' diagnostics about the
16456 // expression.
16457 struct SuppressedDiagnoser : public Sema::VerifyICEDiagnoser {
16458 SuppressedDiagnoser() : VerifyICEDiagnoser(/*Suppress=*/true) {}
16459 Sema::SemaDiagnosticBuilder diagnoseNotICE(Sema &S,
16460 SourceLocation Loc) override {
16461 llvm_unreachable("Diagnostic suppressed")::llvm::llvm_unreachable_internal("Diagnostic suppressed", "clang/lib/Sema/SemaOpenMP.cpp"
, 16461)
;
16462 }
16463 } Diagnoser;
16464 ICE = VerifyIntegerConstantExpression(E, &Result, Diagnoser, AllowFold);
16465 } else {
16466 ICE = VerifyIntegerConstantExpression(E, &Result, /*FIXME*/ AllowFold);
16467 }
16468 if (ICE.isInvalid())
16469 return ExprError();
16470
16471 if ((StrictlyPositive && !Result.isStrictlyPositive()) ||
16472 (!StrictlyPositive && !Result.isNonNegative())) {
16473 Diag(E->getExprLoc(), diag::err_omp_negative_expression_in_clause)
16474 << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0)
16475 << E->getSourceRange();
16476 return ExprError();
16477 }
16478 if ((CKind == OMPC_aligned || CKind == OMPC_align) && !Result.isPowerOf2()) {
16479 Diag(E->getExprLoc(), diag::warn_omp_alignment_not_power_of_two)
16480 << E->getSourceRange();
16481 return ExprError();
16482 }
16483 if (CKind == OMPC_collapse && DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getAssociatedLoops() == 1)
16484 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->setAssociatedLoops(Result.getExtValue());
16485 else if (CKind == OMPC_ordered)
16486 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->setAssociatedLoops(Result.getExtValue());
16487 return ICE;
16488}
16489
16490OMPClause *Sema::ActOnOpenMPSafelenClause(Expr *Len, SourceLocation StartLoc,
16491 SourceLocation LParenLoc,
16492 SourceLocation EndLoc) {
16493 // OpenMP [2.8.1, simd construct, Description]
16494 // The parameter of the safelen clause must be a constant
16495 // positive integer expression.
16496 ExprResult Safelen = VerifyPositiveIntegerConstantInClause(Len, OMPC_safelen);
16497 if (Safelen.isInvalid())
16498 return nullptr;
16499 return new (Context)
16500 OMPSafelenClause(Safelen.get(), StartLoc, LParenLoc, EndLoc);
16501}
16502
16503OMPClause *Sema::ActOnOpenMPSimdlenClause(Expr *Len, SourceLocation StartLoc,
16504 SourceLocation LParenLoc,
16505 SourceLocation EndLoc) {
16506 // OpenMP [2.8.1, simd construct, Description]
16507 // The parameter of the simdlen clause must be a constant
16508 // positive integer expression.
16509 ExprResult Simdlen = VerifyPositiveIntegerConstantInClause(Len, OMPC_simdlen);
16510 if (Simdlen.isInvalid())
16511 return nullptr;
16512 return new (Context)
16513 OMPSimdlenClause(Simdlen.get(), StartLoc, LParenLoc, EndLoc);
16514}
16515
16516/// Tries to find omp_allocator_handle_t type.
16517static bool findOMPAllocatorHandleT(Sema &S, SourceLocation Loc,
16518 DSAStackTy *Stack) {
16519 if (!Stack->getOMPAllocatorHandleT().isNull())
16520 return true;
16521
16522 // Set the allocator handle type.
16523 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_allocator_handle_t");
16524 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
16525 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
16526 S.Diag(Loc, diag::err_omp_implied_type_not_found)
16527 << "omp_allocator_handle_t";
16528 return false;
16529 }
16530 QualType AllocatorHandleEnumTy = PT.get();
16531 AllocatorHandleEnumTy.addConst();
16532 Stack->setOMPAllocatorHandleT(AllocatorHandleEnumTy);
16533
16534 // Fill the predefined allocator map.
16535 bool ErrorFound = false;
16536 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
16537 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
16538 StringRef Allocator =
16539 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
16540 DeclarationName AllocatorName = &S.getASTContext().Idents.get(Allocator);
16541 auto *VD = dyn_cast_or_null<ValueDecl>(
16542 S.LookupSingleName(S.TUScope, AllocatorName, Loc, Sema::LookupAnyName));
16543 if (!VD) {
16544 ErrorFound = true;
16545 break;
16546 }
16547 QualType AllocatorType =
16548 VD->getType().getNonLValueExprType(S.getASTContext());
16549 ExprResult Res = S.BuildDeclRefExpr(VD, AllocatorType, VK_LValue, Loc);
16550 if (!Res.isUsable()) {
16551 ErrorFound = true;
16552 break;
16553 }
16554 Res = S.PerformImplicitConversion(Res.get(), AllocatorHandleEnumTy,
16555 Sema::AA_Initializing,
16556 /* AllowExplicit */ true);
16557 if (!Res.isUsable()) {
16558 ErrorFound = true;
16559 break;
16560 }
16561 Stack->setAllocator(AllocatorKind, Res.get());
16562 }
16563 if (ErrorFound) {
16564 S.Diag(Loc, diag::err_omp_implied_type_not_found)
16565 << "omp_allocator_handle_t";
16566 return false;
16567 }
16568
16569 return true;
16570}
16571
16572OMPClause *Sema::ActOnOpenMPAllocatorClause(Expr *A, SourceLocation StartLoc,
16573 SourceLocation LParenLoc,
16574 SourceLocation EndLoc) {
16575 // OpenMP [2.11.3, allocate Directive, Description]
16576 // allocator is an expression of omp_allocator_handle_t type.
16577 if (!findOMPAllocatorHandleT(*this, A->getExprLoc(), DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
))
16578 return nullptr;
16579
16580 ExprResult Allocator = DefaultLvalueConversion(A);
16581 if (Allocator.isInvalid())
16582 return nullptr;
16583 Allocator = PerformImplicitConversion(Allocator.get(),
16584 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getOMPAllocatorHandleT(),
16585 Sema::AA_Initializing,
16586 /*AllowExplicit=*/true);
16587 if (Allocator.isInvalid())
16588 return nullptr;
16589 return new (Context)
16590 OMPAllocatorClause(Allocator.get(), StartLoc, LParenLoc, EndLoc);
16591}
16592
16593OMPClause *Sema::ActOnOpenMPCollapseClause(Expr *NumForLoops,
16594 SourceLocation StartLoc,
16595 SourceLocation LParenLoc,
16596 SourceLocation EndLoc) {
16597 // OpenMP [2.7.1, loop construct, Description]
16598 // OpenMP [2.8.1, simd construct, Description]
16599 // OpenMP [2.9.6, distribute construct, Description]
16600 // The parameter of the collapse clause must be a constant
16601 // positive integer expression.
16602 ExprResult NumForLoopsResult =
16603 VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_collapse);
16604 if (NumForLoopsResult.isInvalid())
16605 return nullptr;
16606 return new (Context)
16607 OMPCollapseClause(NumForLoopsResult.get(), StartLoc, LParenLoc, EndLoc);
16608}
16609
16610OMPClause *Sema::ActOnOpenMPOrderedClause(SourceLocation StartLoc,
16611 SourceLocation EndLoc,
16612 SourceLocation LParenLoc,
16613 Expr *NumForLoops) {
16614 // OpenMP [2.7.1, loop construct, Description]
16615 // OpenMP [2.8.1, simd construct, Description]
16616 // OpenMP [2.9.6, distribute construct, Description]
16617 // The parameter of the ordered clause must be a constant
16618 // positive integer expression if any.
16619 if (NumForLoops && LParenLoc.isValid()) {
16620 ExprResult NumForLoopsResult =
16621 VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_ordered);
16622 if (NumForLoopsResult.isInvalid())
16623 return nullptr;
16624 NumForLoops = NumForLoopsResult.get();
16625 } else {
16626 NumForLoops = nullptr;
16627 }
16628 auto *Clause = OMPOrderedClause::Create(
16629 Context, NumForLoops, NumForLoops ? DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getAssociatedLoops() : 0,
16630 StartLoc, LParenLoc, EndLoc);
16631 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->setOrderedRegion(/*IsOrdered=*/true, NumForLoops, Clause);
16632 return Clause;
16633}
16634
16635OMPClause *Sema::ActOnOpenMPSimpleClause(
16636 OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc,
16637 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
16638 OMPClause *Res = nullptr;
16639 switch (Kind) {
16640 case OMPC_default:
16641 Res = ActOnOpenMPDefaultClause(static_cast<DefaultKind>(Argument),
16642 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16643 break;
16644 case OMPC_proc_bind:
16645 Res = ActOnOpenMPProcBindClause(static_cast<ProcBindKind>(Argument),
16646 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16647 break;
16648 case OMPC_atomic_default_mem_order:
16649 Res = ActOnOpenMPAtomicDefaultMemOrderClause(
16650 static_cast<OpenMPAtomicDefaultMemOrderClauseKind>(Argument),
16651 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16652 break;
16653 case OMPC_update:
16654 Res = ActOnOpenMPUpdateClause(static_cast<OpenMPDependClauseKind>(Argument),
16655 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16656 break;
16657 case OMPC_bind:
16658 Res = ActOnOpenMPBindClause(static_cast<OpenMPBindClauseKind>(Argument),
16659 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16660 break;
16661 case OMPC_at:
16662 Res = ActOnOpenMPAtClause(static_cast<OpenMPAtClauseKind>(Argument),
16663 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16664 break;
16665 case OMPC_severity:
16666 Res = ActOnOpenMPSeverityClause(
16667 static_cast<OpenMPSeverityClauseKind>(Argument), ArgumentLoc, StartLoc,
16668 LParenLoc, EndLoc);
16669 break;
16670 case OMPC_if:
16671 case OMPC_final:
16672 case OMPC_num_threads:
16673 case OMPC_safelen:
16674 case OMPC_simdlen:
16675 case OMPC_sizes:
16676 case OMPC_allocator:
16677 case OMPC_collapse:
16678 case OMPC_schedule:
16679 case OMPC_private:
16680 case OMPC_firstprivate:
16681 case OMPC_lastprivate:
16682 case OMPC_shared:
16683 case OMPC_reduction:
16684 case OMPC_task_reduction:
16685 case OMPC_in_reduction:
16686 case OMPC_linear:
16687 case OMPC_aligned:
16688 case OMPC_copyin:
16689 case OMPC_copyprivate:
16690 case OMPC_ordered:
16691 case OMPC_nowait:
16692 case OMPC_untied:
16693 case OMPC_mergeable:
16694 case OMPC_threadprivate:
16695 case OMPC_allocate:
16696 case OMPC_flush:
16697 case OMPC_depobj:
16698 case OMPC_read:
16699 case OMPC_write:
16700 case OMPC_capture:
16701 case OMPC_compare:
16702 case OMPC_seq_cst:
16703 case OMPC_acq_rel:
16704 case OMPC_acquire:
16705 case OMPC_release:
16706 case OMPC_relaxed:
16707 case OMPC_depend:
16708 case OMPC_device:
16709 case OMPC_threads:
16710 case OMPC_simd:
16711 case OMPC_map:
16712 case OMPC_num_teams:
16713 case OMPC_thread_limit:
16714 case OMPC_priority:
16715 case OMPC_grainsize:
16716 case OMPC_nogroup:
16717 case OMPC_num_tasks:
16718 case OMPC_hint:
16719 case OMPC_dist_schedule:
16720 case OMPC_defaultmap:
16721 case OMPC_unknown:
16722 case OMPC_uniform:
16723 case OMPC_to:
16724 case OMPC_from:
16725 case OMPC_use_device_ptr:
16726 case OMPC_use_device_addr:
16727 case OMPC_is_device_ptr:
16728 case OMPC_has_device_addr:
16729 case OMPC_unified_address:
16730 case OMPC_unified_shared_memory:
16731 case OMPC_reverse_offload:
16732 case OMPC_dynamic_allocators:
16733 case OMPC_device_type:
16734 case OMPC_match:
16735 case OMPC_nontemporal:
16736 case OMPC_destroy:
16737 case OMPC_novariants:
16738 case OMPC_nocontext:
16739 case OMPC_detach:
16740 case OMPC_inclusive:
16741 case OMPC_exclusive:
16742 case OMPC_uses_allocators:
16743 case OMPC_affinity:
16744 case OMPC_when:
16745 case OMPC_message:
16746 default:
16747 llvm_unreachable("Clause is not allowed.")::llvm::llvm_unreachable_internal("Clause is not allowed.", "clang/lib/Sema/SemaOpenMP.cpp"
, 16747)
;
16748 }
16749 return Res;
16750}
16751
16752static std::string
16753getListOfPossibleValues(OpenMPClauseKind K, unsigned First, unsigned Last,
16754 ArrayRef<unsigned> Exclude = std::nullopt) {
16755 SmallString<256> Buffer;
16756 llvm::raw_svector_ostream Out(Buffer);
16757 unsigned Skipped = Exclude.size();
16758 for (unsigned I = First; I < Last; ++I) {
16759 if (llvm::is_contained(Exclude, I)) {
16760 --Skipped;
16761 continue;
16762 }
16763 Out << "'" << getOpenMPSimpleClauseTypeName(K, I) << "'";
16764 if (I + Skipped + 2 == Last)
16765 Out << " or ";
16766 else if (I + Skipped + 1 != Last)
16767 Out << ", ";
16768 }
16769 return std::string(Out.str());
16770}
16771
16772OMPClause *Sema::ActOnOpenMPDefaultClause(DefaultKind Kind,
16773 SourceLocation KindKwLoc,
16774 SourceLocation StartLoc,
16775 SourceLocation LParenLoc,
16776 SourceLocation EndLoc) {
16777 if (Kind == OMP_DEFAULT_unknown) {
16778 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16779 << getListOfPossibleValues(OMPC_default, /*First=*/0,
16780 /*Last=*/unsigned(OMP_DEFAULT_unknown))
16781 << getOpenMPClauseName(OMPC_default);
16782 return nullptr;
16783 }
16784
16785 switch (Kind) {
16786 case OMP_DEFAULT_none:
16787 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->setDefaultDSANone(KindKwLoc);
16788 break;
16789 case OMP_DEFAULT_shared:
16790 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->setDefaultDSAShared(KindKwLoc);
16791 break;
16792 case OMP_DEFAULT_firstprivate:
16793 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->setDefaultDSAFirstPrivate(KindKwLoc);
16794 break;
16795 case OMP_DEFAULT_private:
16796 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->setDefaultDSAPrivate(KindKwLoc);
16797 break;
16798 default:
16799 llvm_unreachable("DSA unexpected in OpenMP default clause")::llvm::llvm_unreachable_internal("DSA unexpected in OpenMP default clause"
, "clang/lib/Sema/SemaOpenMP.cpp", 16799)
;
16800 }
16801
16802 return new (Context)
16803 OMPDefaultClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
16804}
16805
16806OMPClause *Sema::ActOnOpenMPProcBindClause(ProcBindKind Kind,
16807 SourceLocation KindKwLoc,
16808 SourceLocation StartLoc,
16809 SourceLocation LParenLoc,
16810 SourceLocation EndLoc) {
16811 if (Kind == OMP_PROC_BIND_unknown) {
16812 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16813 << getListOfPossibleValues(OMPC_proc_bind,
16814 /*First=*/unsigned(OMP_PROC_BIND_master),
16815 /*Last=*/
16816 unsigned(LangOpts.OpenMP > 50
16817 ? OMP_PROC_BIND_primary
16818 : OMP_PROC_BIND_spread) +
16819 1)
16820 << getOpenMPClauseName(OMPC_proc_bind);
16821 return nullptr;
16822 }
16823 if (Kind == OMP_PROC_BIND_primary && LangOpts.OpenMP < 51)
16824 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16825 << getListOfPossibleValues(OMPC_proc_bind,
16826 /*First=*/unsigned(OMP_PROC_BIND_master),
16827 /*Last=*/
16828 unsigned(OMP_PROC_BIND_spread) + 1)
16829 << getOpenMPClauseName(OMPC_proc_bind);
16830 return new (Context)
16831 OMPProcBindClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
16832}
16833
16834OMPClause *Sema::ActOnOpenMPAtomicDefaultMemOrderClause(
16835 OpenMPAtomicDefaultMemOrderClauseKind Kind, SourceLocation KindKwLoc,
16836 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
16837 if (Kind == OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown) {
16838 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16839 << getListOfPossibleValues(
16840 OMPC_atomic_default_mem_order, /*First=*/0,
16841 /*Last=*/OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown)
16842 << getOpenMPClauseName(OMPC_atomic_default_mem_order);
16843 return nullptr;
16844 }
16845 return new (Context) OMPAtomicDefaultMemOrderClause(Kind, KindKwLoc, StartLoc,
16846 LParenLoc, EndLoc);
16847}
16848
16849OMPClause *Sema::ActOnOpenMPAtClause(OpenMPAtClauseKind Kind,
16850 SourceLocation KindKwLoc,
16851 SourceLocation StartLoc,
16852 SourceLocation LParenLoc,
16853 SourceLocation EndLoc) {
16854 if (Kind == OMPC_AT_unknown) {
16855 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16856 << getListOfPossibleValues(OMPC_at, /*First=*/0,
16857 /*Last=*/OMPC_AT_unknown)
16858 << getOpenMPClauseName(OMPC_at);
16859 return nullptr;
16860 }
16861 return new (Context)
16862 OMPAtClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
16863}
16864
16865OMPClause *Sema::ActOnOpenMPSeverityClause(OpenMPSeverityClauseKind Kind,
16866 SourceLocation KindKwLoc,
16867 SourceLocation StartLoc,
16868 SourceLocation LParenLoc,
16869 SourceLocation EndLoc) {
16870 if (Kind == OMPC_SEVERITY_unknown) {
16871 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16872 << getListOfPossibleValues(OMPC_severity, /*First=*/0,
16873 /*Last=*/OMPC_SEVERITY_unknown)
16874 << getOpenMPClauseName(OMPC_severity);
16875 return nullptr;
16876 }
16877 return new (Context)
16878 OMPSeverityClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
16879}
16880
16881OMPClause *Sema::ActOnOpenMPMessageClause(Expr *ME, SourceLocation StartLoc,
16882 SourceLocation LParenLoc,
16883 SourceLocation EndLoc) {
16884 assert(ME && "NULL expr in Message clause")(static_cast <bool> (ME && "NULL expr in Message clause"
) ? void (0) : __assert_fail ("ME && \"NULL expr in Message clause\""
, "clang/lib/Sema/SemaOpenMP.cpp", 16884, __extension__ __PRETTY_FUNCTION__
))
;
16885 if (!isa<StringLiteral>(ME)) {
16886 Diag(ME->getBeginLoc(), diag::warn_clause_expected_string)
16887 << getOpenMPClauseName(OMPC_message);
16888 return nullptr;
16889 }
16890 return new (Context) OMPMessageClause(ME, StartLoc, LParenLoc, EndLoc);
16891}
16892
16893OMPClause *Sema::ActOnOpenMPOrderClause(
16894 OpenMPOrderClauseModifier Modifier, OpenMPOrderClauseKind Kind,
16895 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
16896 SourceLocation KindLoc, SourceLocation EndLoc) {
16897 if (Kind != OMPC_ORDER_concurrent ||
16898 (LangOpts.OpenMP < 51 && MLoc.isValid())) {
16899 // Kind should be concurrent,
16900 // Modifiers introduced in OpenMP 5.1
16901 static_assert(OMPC_ORDER_unknown > 0,
16902 "OMPC_ORDER_unknown not greater than 0");
16903
16904 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
16905 << getListOfPossibleValues(OMPC_order,
16906 /*First=*/0,
16907 /*Last=*/OMPC_ORDER_unknown)
16908 << getOpenMPClauseName(OMPC_order);
16909 return nullptr;
16910 }
16911 if (LangOpts.OpenMP >= 51) {
16912 if (Modifier == OMPC_ORDER_MODIFIER_unknown && MLoc.isValid()) {
16913 Diag(MLoc, diag::err_omp_unexpected_clause_value)
16914 << getListOfPossibleValues(OMPC_order,
16915 /*First=*/OMPC_ORDER_MODIFIER_unknown + 1,
16916 /*Last=*/OMPC_ORDER_MODIFIER_last)
16917 << getOpenMPClauseName(OMPC_order);
16918 } else {
16919 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->setRegionHasOrderConcurrent(/*HasOrderConcurrent=*/true);
16920 if (DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurScope()) {
16921 // mark the current scope with 'order' flag
16922 unsigned existingFlags = DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurScope()->getFlags();
16923 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurScope()->setFlags(existingFlags |
16924 Scope::OpenMPOrderClauseScope);
16925 }
16926 }
16927 }
16928 return new (Context) OMPOrderClause(Kind, KindLoc, StartLoc, LParenLoc,
16929 EndLoc, Modifier, MLoc);
16930}
16931
16932OMPClause *Sema::ActOnOpenMPUpdateClause(OpenMPDependClauseKind Kind,
16933 SourceLocation KindKwLoc,
16934 SourceLocation StartLoc,
16935 SourceLocation LParenLoc,
16936 SourceLocation EndLoc) {
16937 if (Kind == OMPC_DEPEND_unknown || Kind == OMPC_DEPEND_source ||
16938 Kind == OMPC_DEPEND_sink || Kind == OMPC_DEPEND_depobj) {
16939 SmallVector<unsigned> Except = {
16940 OMPC_DEPEND_source, OMPC_DEPEND_sink, OMPC_DEPEND_depobj,
16941 OMPC_DEPEND_outallmemory, OMPC_DEPEND_inoutallmemory};
16942 if (LangOpts.OpenMP < 51)
16943 Except.push_back(OMPC_DEPEND_inoutset);
16944 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16945 << getListOfPossibleValues(OMPC_depend, /*First=*/0,
16946 /*Last=*/OMPC_DEPEND_unknown, Except)
16947 << getOpenMPClauseName(OMPC_update);
16948 return nullptr;
16949 }
16950 return OMPUpdateClause::Create(Context, StartLoc, LParenLoc, KindKwLoc, Kind,
16951 EndLoc);
16952}
16953
16954OMPClause *Sema::ActOnOpenMPSizesClause(ArrayRef<Expr *> SizeExprs,
16955 SourceLocation StartLoc,
16956 SourceLocation LParenLoc,
16957 SourceLocation EndLoc) {
16958 for (Expr *SizeExpr : SizeExprs) {
16959 ExprResult NumForLoopsResult = VerifyPositiveIntegerConstantInClause(
16960 SizeExpr, OMPC_sizes, /*StrictlyPositive=*/true);
16961 if (!NumForLoopsResult.isUsable())
16962 return nullptr;
16963 }
16964
16965 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->setAssociatedLoops(SizeExprs.size());
16966 return OMPSizesClause::Create(Context, StartLoc, LParenLoc, EndLoc,
16967 SizeExprs);
16968}
16969
16970OMPClause *Sema::ActOnOpenMPFullClause(SourceLocation StartLoc,
16971 SourceLocation EndLoc) {
16972 return OMPFullClause::Create(Context, StartLoc, EndLoc);
16973}
16974
16975OMPClause *Sema::ActOnOpenMPPartialClause(Expr *FactorExpr,
16976 SourceLocation StartLoc,
16977 SourceLocation LParenLoc,
16978 SourceLocation EndLoc) {
16979 if (FactorExpr) {
16980 // If an argument is specified, it must be a constant (or an unevaluated
16981 // template expression).
16982 ExprResult FactorResult = VerifyPositiveIntegerConstantInClause(
16983 FactorExpr, OMPC_partial, /*StrictlyPositive=*/true);
16984 if (FactorResult.isInvalid())
16985 return nullptr;
16986 FactorExpr = FactorResult.get();
16987 }
16988
16989 return OMPPartialClause::Create(Context, StartLoc, LParenLoc, EndLoc,
16990 FactorExpr);
16991}
16992
16993OMPClause *Sema::ActOnOpenMPAlignClause(Expr *A, SourceLocation StartLoc,
16994 SourceLocation LParenLoc,
16995 SourceLocation EndLoc) {
16996 ExprResult AlignVal;
16997 AlignVal = VerifyPositiveIntegerConstantInClause(A, OMPC_align);
16998 if (AlignVal.isInvalid())
16999 return nullptr;
17000 return OMPAlignClause::Create(Context, AlignVal.get(), StartLoc, LParenLoc,
17001 EndLoc);
17002}
17003
17004OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause(
17005 OpenMPClauseKind Kind, ArrayRef<unsigned> Argument, Expr *Expr,
17006 SourceLocation StartLoc, SourceLocation LParenLoc,
17007 ArrayRef<SourceLocation> ArgumentLoc, SourceLocation DelimLoc,
17008 SourceLocation EndLoc) {
17009 OMPClause *Res = nullptr;
17010 switch (Kind) {
17011 case OMPC_schedule:
17012 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
17013 assert(Argument.size() == NumberOfElements &&(static_cast <bool> (Argument.size() == NumberOfElements
&& ArgumentLoc.size() == NumberOfElements) ? void (0
) : __assert_fail ("Argument.size() == NumberOfElements && ArgumentLoc.size() == NumberOfElements"
, "clang/lib/Sema/SemaOpenMP.cpp", 17014, __extension__ __PRETTY_FUNCTION__
))
17014 ArgumentLoc.size() == NumberOfElements)(static_cast <bool> (Argument.size() == NumberOfElements
&& ArgumentLoc.size() == NumberOfElements) ? void (0
) : __assert_fail ("Argument.size() == NumberOfElements && ArgumentLoc.size() == NumberOfElements"
, "clang/lib/Sema/SemaOpenMP.cpp", 17014, __extension__ __PRETTY_FUNCTION__
))
;
17015 Res = ActOnOpenMPScheduleClause(
17016 static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier1]),
17017 static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier2]),
17018 static_cast<OpenMPScheduleClauseKind>(Argument[ScheduleKind]), Expr,
17019 StartLoc, LParenLoc, ArgumentLoc[Modifier1], ArgumentLoc[Modifier2],
17020 ArgumentLoc[ScheduleKind], DelimLoc, EndLoc);
17021 break;
17022 case OMPC_if:
17023 assert(Argument.size() == 1 && ArgumentLoc.size() == 1)(static_cast <bool> (Argument.size() == 1 && ArgumentLoc
.size() == 1) ? void (0) : __assert_fail ("Argument.size() == 1 && ArgumentLoc.size() == 1"
, "clang/lib/Sema/SemaOpenMP.cpp", 17023, __extension__ __PRETTY_FUNCTION__
))
;
17024 Res = ActOnOpenMPIfClause(static_cast<OpenMPDirectiveKind>(Argument.back()),
17025 Expr, StartLoc, LParenLoc, ArgumentLoc.back(),
17026 DelimLoc, EndLoc);
17027 break;
17028 case OMPC_dist_schedule:
17029 Res = ActOnOpenMPDistScheduleClause(
17030 static_cast<OpenMPDistScheduleClauseKind>(Argument.back()), Expr,
17031 StartLoc, LParenLoc, ArgumentLoc.back(), DelimLoc, EndLoc);
17032 break;
17033 case OMPC_defaultmap:
17034 enum { Modifier, DefaultmapKind };
17035 Res = ActOnOpenMPDefaultmapClause(
17036 static_cast<OpenMPDefaultmapClauseModifier>(Argument[Modifier]),
17037 static_cast<OpenMPDefaultmapClauseKind>(Argument[DefaultmapKind]),
17038 StartLoc, LParenLoc, ArgumentLoc[Modifier], ArgumentLoc[DefaultmapKind],
17039 EndLoc);
17040 break;
17041 case OMPC_order:
17042 enum { OrderModifier, OrderKind };
17043 Res = ActOnOpenMPOrderClause(
17044 static_cast<OpenMPOrderClauseModifier>(Argument[OrderModifier]),
17045 static_cast<OpenMPOrderClauseKind>(Argument[OrderKind]), StartLoc,
17046 LParenLoc, ArgumentLoc[OrderModifier], ArgumentLoc[OrderKind], EndLoc);
17047 break;
17048 case OMPC_device:
17049 assert(Argument.size() == 1 && ArgumentLoc.size() == 1)(static_cast <bool> (Argument.size() == 1 && ArgumentLoc
.size() == 1) ? void (0) : __assert_fail ("Argument.size() == 1 && ArgumentLoc.size() == 1"
, "clang/lib/Sema/SemaOpenMP.cpp", 17049, __extension__ __PRETTY_FUNCTION__
))
;
17050 Res = ActOnOpenMPDeviceClause(
17051 static_cast<OpenMPDeviceClauseModifier>(Argument.back()), Expr,
17052 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
17053 break;
17054 case OMPC_grainsize:
17055 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&(static_cast <bool> (Argument.size() == 1 && ArgumentLoc
.size() == 1 && "Modifier for grainsize clause and its location are expected."
) ? void (0) : __assert_fail ("Argument.size() == 1 && ArgumentLoc.size() == 1 && \"Modifier for grainsize clause and its location are expected.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 17056, __extension__ __PRETTY_FUNCTION__
))
17056 "Modifier for grainsize clause and its location are expected.")(static_cast <bool> (Argument.size() == 1 && ArgumentLoc
.size() == 1 && "Modifier for grainsize clause and its location are expected."
) ? void (0) : __assert_fail ("Argument.size() == 1 && ArgumentLoc.size() == 1 && \"Modifier for grainsize clause and its location are expected.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 17056, __extension__ __PRETTY_FUNCTION__
))
;
17057 Res = ActOnOpenMPGrainsizeClause(
17058 static_cast<OpenMPGrainsizeClauseModifier>(Argument.back()), Expr,
17059 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
17060 break;
17061 case OMPC_num_tasks:
17062 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&(static_cast <bool> (Argument.size() == 1 && ArgumentLoc
.size() == 1 && "Modifier for num_tasks clause and its location are expected."
) ? void (0) : __assert_fail ("Argument.size() == 1 && ArgumentLoc.size() == 1 && \"Modifier for num_tasks clause and its location are expected.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 17063, __extension__ __PRETTY_FUNCTION__
))
17063 "Modifier for num_tasks clause and its location are expected.")(static_cast <bool> (Argument.size() == 1 && ArgumentLoc
.size() == 1 && "Modifier for num_tasks clause and its location are expected."
) ? void (0) : __assert_fail ("Argument.size() == 1 && ArgumentLoc.size() == 1 && \"Modifier for num_tasks clause and its location are expected.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 17063, __extension__ __PRETTY_FUNCTION__
))
;
17064 Res = ActOnOpenMPNumTasksClause(
17065 static_cast<OpenMPNumTasksClauseModifier>(Argument.back()), Expr,
17066 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
17067 break;
17068 case OMPC_final:
17069 case OMPC_num_threads:
17070 case OMPC_safelen:
17071 case OMPC_simdlen:
17072 case OMPC_sizes:
17073 case OMPC_allocator:
17074 case OMPC_collapse:
17075 case OMPC_default:
17076 case OMPC_proc_bind:
17077 case OMPC_private:
17078 case OMPC_firstprivate:
17079 case OMPC_lastprivate:
17080 case OMPC_shared:
17081 case OMPC_reduction:
17082 case OMPC_task_reduction:
17083 case OMPC_in_reduction:
17084 case OMPC_linear:
17085 case OMPC_aligned:
17086 case OMPC_copyin:
17087 case OMPC_copyprivate:
17088 case OMPC_ordered:
17089 case OMPC_nowait:
17090 case OMPC_untied:
17091 case OMPC_mergeable:
17092 case OMPC_threadprivate:
17093 case OMPC_allocate:
17094 case OMPC_flush:
17095 case OMPC_depobj:
17096 case OMPC_read:
17097 case OMPC_write:
17098 case OMPC_update:
17099 case OMPC_capture:
17100 case OMPC_compare:
17101 case OMPC_seq_cst:
17102 case OMPC_acq_rel:
17103 case OMPC_acquire:
17104 case OMPC_release:
17105 case OMPC_relaxed:
17106 case OMPC_depend:
17107 case OMPC_threads:
17108 case OMPC_simd:
17109 case OMPC_map:
17110 case OMPC_num_teams:
17111 case OMPC_thread_limit:
17112 case OMPC_priority:
17113 case OMPC_nogroup:
17114 case OMPC_hint:
17115 case OMPC_unknown:
17116 case OMPC_uniform:
17117 case OMPC_to:
17118 case OMPC_from:
17119 case OMPC_use_device_ptr:
17120 case OMPC_use_device_addr:
17121 case OMPC_is_device_ptr:
17122 case OMPC_has_device_addr:
17123 case OMPC_unified_address:
17124 case OMPC_unified_shared_memory:
17125 case OMPC_reverse_offload:
17126 case OMPC_dynamic_allocators:
17127 case OMPC_atomic_default_mem_order:
17128 case OMPC_device_type:
17129 case OMPC_match:
17130 case OMPC_nontemporal:
17131 case OMPC_at:
17132 case OMPC_severity:
17133 case OMPC_message:
17134 case OMPC_destroy:
17135 case OMPC_novariants:
17136 case OMPC_nocontext:
17137 case OMPC_detach:
17138 case OMPC_inclusive:
17139 case OMPC_exclusive:
17140 case OMPC_uses_allocators:
17141 case OMPC_affinity:
17142 case OMPC_when:
17143 case OMPC_bind:
17144 default:
17145 llvm_unreachable("Clause is not allowed.")::llvm::llvm_unreachable_internal("Clause is not allowed.", "clang/lib/Sema/SemaOpenMP.cpp"
, 17145)
;
17146 }
17147 return Res;
17148}
17149
17150static bool checkScheduleModifiers(Sema &S, OpenMPScheduleClauseModifier M1,
17151 OpenMPScheduleClauseModifier M2,
17152 SourceLocation M1Loc, SourceLocation M2Loc) {
17153 if (M1 == OMPC_SCHEDULE_MODIFIER_unknown && M1Loc.isValid()) {
17154 SmallVector<unsigned, 2> Excluded;
17155 if (M2 != OMPC_SCHEDULE_MODIFIER_unknown)
17156 Excluded.push_back(M2);
17157 if (M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)
17158 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_monotonic);
17159 if (M2 == OMPC_SCHEDULE_MODIFIER_monotonic)
17160 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_nonmonotonic);
17161 S.Diag(M1Loc, diag::err_omp_unexpected_clause_value)
17162 << getListOfPossibleValues(OMPC_schedule,
17163 /*First=*/OMPC_SCHEDULE_MODIFIER_unknown + 1,
17164 /*Last=*/OMPC_SCHEDULE_MODIFIER_last,
17165 Excluded)
17166 << getOpenMPClauseName(OMPC_schedule);
17167 return true;
17168 }
17169 return false;
17170}
17171
17172OMPClause *Sema::ActOnOpenMPScheduleClause(
17173 OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2,
17174 OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
17175 SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc,
17176 SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc) {
17177 if (checkScheduleModifiers(*this, M1, M2, M1Loc, M2Loc) ||
17178 checkScheduleModifiers(*this, M2, M1, M2Loc, M1Loc))
17179 return nullptr;
17180 // OpenMP, 2.7.1, Loop Construct, Restrictions
17181 // Either the monotonic modifier or the nonmonotonic modifier can be specified
17182 // but not both.
17183 if ((M1 == M2 && M1 != OMPC_SCHEDULE_MODIFIER_unknown) ||
17184 (M1 == OMPC_SCHEDULE_MODIFIER_monotonic &&
17185 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) ||
17186 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic &&
17187 M2 == OMPC_SCHEDULE_MODIFIER_monotonic)) {
17188 Diag(M2Loc, diag::err_omp_unexpected_schedule_modifier)
17189 << getOpenMPSimpleClauseTypeName(OMPC_schedule, M2)
17190 << getOpenMPSimpleClauseTypeName(OMPC_schedule, M1);
17191 return nullptr;
17192 }
17193 if (Kind == OMPC_SCHEDULE_unknown) {
17194 std::string Values;
17195 if (M1Loc.isInvalid() && M2Loc.isInvalid()) {
17196 unsigned Exclude[] = {OMPC_SCHEDULE_unknown};
17197 Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
17198 /*Last=*/OMPC_SCHEDULE_MODIFIER_last,
17199 Exclude);
17200 } else {
17201 Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
17202 /*Last=*/OMPC_SCHEDULE_unknown);
17203 }
17204 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
17205 << Values << getOpenMPClauseName(OMPC_schedule);
17206 return nullptr;
17207 }
17208 // OpenMP, 2.7.1, Loop Construct, Restrictions
17209 // The nonmonotonic modifier can only be specified with schedule(dynamic) or
17210 // schedule(guided).
17211 // OpenMP 5.0 does not have this restriction.
17212 if (LangOpts.OpenMP < 50 &&
17213 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
17214 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
17215 Kind != OMPC_SCHEDULE_dynamic && Kind != OMPC_SCHEDULE_guided) {
17216 Diag(M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ? M1Loc : M2Loc,
17217 diag::err_omp_schedule_nonmonotonic_static);
17218 return nullptr;
17219 }
17220 Expr *ValExpr = ChunkSize;
17221 Stmt *HelperValStmt = nullptr;
17222 if (ChunkSize) {
17223 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
17224 !ChunkSize->isInstantiationDependent() &&
17225 !ChunkSize->containsUnexpandedParameterPack()) {
17226 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
17227 ExprResult Val =
17228 PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize);
17229 if (Val.isInvalid())
17230 return nullptr;
17231
17232 ValExpr = Val.get();
17233
17234 // OpenMP [2.7.1, Restrictions]
17235 // chunk_size must be a loop invariant integer expression with a positive
17236 // value.
17237 if (std::optional<llvm::APSInt> Result =
17238 ValExpr->getIntegerConstantExpr(Context)) {
17239 if (Result->isSigned() && !Result->isStrictlyPositive()) {
17240 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
17241 << "schedule" << 1 << ChunkSize->getSourceRange();
17242 return nullptr;
17243 }
17244 } else if (getOpenMPCaptureRegionForClause(
17245 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective(), OMPC_schedule,
17246 LangOpts.OpenMP) != OMPD_unknown &&
17247 !CurContext->isDependentContext()) {
17248 ValExpr = MakeFullExpr(ValExpr).get();
17249 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17250 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
17251 HelperValStmt = buildPreInits(Context, Captures);
17252 }
17253 }
17254 }
17255
17256 return new (Context)
17257 OMPScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc, Kind,
17258 ValExpr, HelperValStmt, M1, M1Loc, M2, M2Loc);
17259}
17260
17261OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind,
17262 SourceLocation StartLoc,
17263 SourceLocation EndLoc) {
17264 OMPClause *Res = nullptr;
17265 switch (Kind) {
17266 case OMPC_ordered:
17267 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc);
17268 break;
17269 case OMPC_nowait:
17270 Res = ActOnOpenMPNowaitClause(StartLoc, EndLoc);
17271 break;
17272 case OMPC_untied:
17273 Res = ActOnOpenMPUntiedClause(StartLoc, EndLoc);
17274 break;
17275 case OMPC_mergeable:
17276 Res = ActOnOpenMPMergeableClause(StartLoc, EndLoc);
17277 break;
17278 case OMPC_read:
17279 Res = ActOnOpenMPReadClause(StartLoc, EndLoc);
17280 break;
17281 case OMPC_write:
17282 Res = ActOnOpenMPWriteClause(StartLoc, EndLoc);
17283 break;
17284 case OMPC_update:
17285 Res = ActOnOpenMPUpdateClause(StartLoc, EndLoc);
17286 break;
17287 case OMPC_capture:
17288 Res = ActOnOpenMPCaptureClause(StartLoc, EndLoc);
17289 break;
17290 case OMPC_compare:
17291 Res = ActOnOpenMPCompareClause(StartLoc, EndLoc);
17292 break;
17293 case OMPC_seq_cst:
17294 Res = ActOnOpenMPSeqCstClause(StartLoc, EndLoc);
17295 break;
17296 case OMPC_acq_rel:
17297 Res = ActOnOpenMPAcqRelClause(StartLoc, EndLoc);
17298 break;
17299 case OMPC_acquire:
17300 Res = ActOnOpenMPAcquireClause(StartLoc, EndLoc);
17301 break;
17302 case OMPC_release:
17303 Res = ActOnOpenMPReleaseClause(StartLoc, EndLoc);
17304 break;
17305 case OMPC_relaxed:
17306 Res = ActOnOpenMPRelaxedClause(StartLoc, EndLoc);
17307 break;
17308 case OMPC_threads:
17309 Res = ActOnOpenMPThreadsClause(StartLoc, EndLoc);
17310 break;
17311 case OMPC_simd:
17312 Res = ActOnOpenMPSIMDClause(StartLoc, EndLoc);
17313 break;
17314 case OMPC_nogroup:
17315 Res = ActOnOpenMPNogroupClause(StartLoc, EndLoc);
17316 break;
17317 case OMPC_unified_address:
17318 Res = ActOnOpenMPUnifiedAddressClause(StartLoc, EndLoc);
17319 break;
17320 case OMPC_unified_shared_memory:
17321 Res = ActOnOpenMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
17322 break;
17323 case OMPC_reverse_offload:
17324 Res = ActOnOpenMPReverseOffloadClause(StartLoc, EndLoc);
17325 break;
17326 case OMPC_dynamic_allocators:
17327 Res = ActOnOpenMPDynamicAllocatorsClause(StartLoc, EndLoc);
17328 break;
17329 case OMPC_destroy:
17330 Res = ActOnOpenMPDestroyClause(/*InteropVar=*/nullptr, StartLoc,
17331 /*LParenLoc=*/SourceLocation(),
17332 /*VarLoc=*/SourceLocation(), EndLoc);
17333 break;
17334 case OMPC_full:
17335 Res = ActOnOpenMPFullClause(StartLoc, EndLoc);
17336 break;
17337 case OMPC_partial:
17338 Res = ActOnOpenMPPartialClause(nullptr, StartLoc, /*LParenLoc=*/{}, EndLoc);
17339 break;
17340 case OMPC_if:
17341 case OMPC_final:
17342 case OMPC_num_threads:
17343 case OMPC_safelen:
17344 case OMPC_simdlen:
17345 case OMPC_sizes:
17346 case OMPC_allocator:
17347 case OMPC_collapse:
17348 case OMPC_schedule:
17349 case OMPC_private:
17350 case OMPC_firstprivate:
17351 case OMPC_lastprivate:
17352 case OMPC_shared:
17353 case OMPC_reduction:
17354 case OMPC_task_reduction:
17355 case OMPC_in_reduction:
17356 case OMPC_linear:
17357 case OMPC_aligned:
17358 case OMPC_copyin:
17359 case OMPC_copyprivate:
17360 case OMPC_default:
17361 case OMPC_proc_bind:
17362 case OMPC_threadprivate:
17363 case OMPC_allocate:
17364 case OMPC_flush:
17365 case OMPC_depobj:
17366 case OMPC_depend:
17367 case OMPC_device:
17368 case OMPC_map:
17369 case OMPC_num_teams:
17370 case OMPC_thread_limit:
17371 case OMPC_priority:
17372 case OMPC_grainsize:
17373 case OMPC_num_tasks:
17374 case OMPC_hint:
17375 case OMPC_dist_schedule:
17376 case OMPC_defaultmap:
17377 case OMPC_unknown:
17378 case OMPC_uniform:
17379 case OMPC_to:
17380 case OMPC_from:
17381 case OMPC_use_device_ptr:
17382 case OMPC_use_device_addr:
17383 case OMPC_is_device_ptr:
17384 case OMPC_has_device_addr:
17385 case OMPC_atomic_default_mem_order:
17386 case OMPC_device_type:
17387 case OMPC_match:
17388 case OMPC_nontemporal:
17389 case OMPC_order:
17390 case OMPC_at:
17391 case OMPC_severity:
17392 case OMPC_message:
17393 case OMPC_novariants:
17394 case OMPC_nocontext:
17395 case OMPC_detach:
17396 case OMPC_inclusive:
17397 case OMPC_exclusive:
17398 case OMPC_uses_allocators:
17399 case OMPC_affinity:
17400 case OMPC_when:
17401 case OMPC_ompx_dyn_cgroup_mem:
17402 default:
17403 llvm_unreachable("Clause is not allowed.")::llvm::llvm_unreachable_internal("Clause is not allowed.", "clang/lib/Sema/SemaOpenMP.cpp"
, 17403)
;
17404 }
17405 return Res;
17406}
17407
17408OMPClause *Sema::ActOnOpenMPNowaitClause(SourceLocation StartLoc,
17409 SourceLocation EndLoc) {
17410 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->setNowaitRegion();
17411 return new (Context) OMPNowaitClause(StartLoc, EndLoc);
17412}
17413
17414OMPClause *Sema::ActOnOpenMPUntiedClause(SourceLocation StartLoc,
17415 SourceLocation EndLoc) {
17416 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->setUntiedRegion();
17417 return new (Context) OMPUntiedClause(StartLoc, EndLoc);
17418}
17419
17420OMPClause *Sema::ActOnOpenMPMergeableClause(SourceLocation StartLoc,
17421 SourceLocation EndLoc) {
17422 return new (Context) OMPMergeableClause(StartLoc, EndLoc);
17423}
17424
17425OMPClause *Sema::ActOnOpenMPReadClause(SourceLocation StartLoc,
17426 SourceLocation EndLoc) {
17427 return new (Context) OMPReadClause(StartLoc, EndLoc);
17428}
17429
17430OMPClause *Sema::ActOnOpenMPWriteClause(SourceLocation StartLoc,
17431 SourceLocation EndLoc) {
17432 return new (Context) OMPWriteClause(StartLoc, EndLoc);
17433}
17434
17435OMPClause *Sema::ActOnOpenMPUpdateClause(SourceLocation StartLoc,
17436 SourceLocation EndLoc) {
17437 return OMPUpdateClause::Create(Context, StartLoc, EndLoc);
17438}
17439
17440OMPClause *Sema::ActOnOpenMPCaptureClause(SourceLocation StartLoc,
17441 SourceLocation EndLoc) {
17442 return new (Context) OMPCaptureClause(StartLoc, EndLoc);
17443}
17444
17445OMPClause *Sema::ActOnOpenMPCompareClause(SourceLocation StartLoc,
17446 SourceLocation EndLoc) {
17447 return new (Context) OMPCompareClause(StartLoc, EndLoc);
17448}
17449
17450OMPClause *Sema::ActOnOpenMPSeqCstClause(SourceLocation StartLoc,
17451 SourceLocation EndLoc) {
17452 return new (Context) OMPSeqCstClause(StartLoc, EndLoc);
17453}
17454
17455OMPClause *Sema::ActOnOpenMPAcqRelClause(SourceLocation StartLoc,
17456 SourceLocation EndLoc) {
17457 return new (Context) OMPAcqRelClause(StartLoc, EndLoc);
17458}
17459
17460OMPClause *Sema::ActOnOpenMPAcquireClause(SourceLocation StartLoc,
17461 SourceLocation EndLoc) {
17462 return new (Context) OMPAcquireClause(StartLoc, EndLoc);
17463}
17464
17465OMPClause *Sema::ActOnOpenMPReleaseClause(SourceLocation StartLoc,
17466 SourceLocation EndLoc) {
17467 return new (Context) OMPReleaseClause(StartLoc, EndLoc);
17468}
17469
17470OMPClause *Sema::ActOnOpenMPRelaxedClause(SourceLocation StartLoc,
17471 SourceLocation EndLoc) {
17472 return new (Context) OMPRelaxedClause(StartLoc, EndLoc);
17473}
17474
17475OMPClause *Sema::ActOnOpenMPThreadsClause(SourceLocation StartLoc,
17476 SourceLocation EndLoc) {
17477 return new (Context) OMPThreadsClause(StartLoc, EndLoc);
17478}
17479
17480OMPClause *Sema::ActOnOpenMPSIMDClause(SourceLocation StartLoc,
17481 SourceLocation EndLoc) {
17482 return new (Context) OMPSIMDClause(StartLoc, EndLoc);
17483}
17484
17485OMPClause *Sema::ActOnOpenMPNogroupClause(SourceLocation StartLoc,
17486 SourceLocation EndLoc) {
17487 return new (Context) OMPNogroupClause(StartLoc, EndLoc);
17488}
17489
17490OMPClause *Sema::ActOnOpenMPUnifiedAddressClause(SourceLocation StartLoc,
17491 SourceLocation EndLoc) {
17492 return new (Context) OMPUnifiedAddressClause(StartLoc, EndLoc);
17493}
17494
17495OMPClause *Sema::ActOnOpenMPUnifiedSharedMemoryClause(SourceLocation StartLoc,
17496 SourceLocation EndLoc) {
17497 return new (Context) OMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
17498}
17499
17500OMPClause *Sema::ActOnOpenMPReverseOffloadClause(SourceLocation StartLoc,
17501 SourceLocation EndLoc) {
17502 return new (Context) OMPReverseOffloadClause(StartLoc, EndLoc);
17503}
17504
17505OMPClause *Sema::ActOnOpenMPDynamicAllocatorsClause(SourceLocation StartLoc,
17506 SourceLocation EndLoc) {
17507 return new (Context) OMPDynamicAllocatorsClause(StartLoc, EndLoc);
17508}
17509
17510StmtResult Sema::ActOnOpenMPInteropDirective(ArrayRef<OMPClause *> Clauses,
17511 SourceLocation StartLoc,
17512 SourceLocation EndLoc) {
17513
17514 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17515 // At least one action-clause must appear on a directive.
17516 if (!hasClauses(Clauses, OMPC_init, OMPC_use, OMPC_destroy, OMPC_nowait)) {
17517 StringRef Expected = "'init', 'use', 'destroy', or 'nowait'";
17518 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
17519 << Expected << getOpenMPDirectiveName(OMPD_interop);
17520 return StmtError();
17521 }
17522
17523 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17524 // A depend clause can only appear on the directive if a targetsync
17525 // interop-type is present or the interop-var was initialized with
17526 // the targetsync interop-type.
17527
17528 // If there is any 'init' clause diagnose if there is no 'init' clause with
17529 // interop-type of 'targetsync'. Cases involving other directives cannot be
17530 // diagnosed.
17531 const OMPDependClause *DependClause = nullptr;
17532 bool HasInitClause = false;
17533 bool IsTargetSync = false;
17534 for (const OMPClause *C : Clauses) {
17535 if (IsTargetSync)
17536 break;
17537 if (const auto *InitClause = dyn_cast<OMPInitClause>(C)) {
17538 HasInitClause = true;
17539 if (InitClause->getIsTargetSync())
17540 IsTargetSync = true;
17541 } else if (const auto *DC = dyn_cast<OMPDependClause>(C)) {
17542 DependClause = DC;
17543 }
17544 }
17545 if (DependClause && HasInitClause && !IsTargetSync) {
17546 Diag(DependClause->getBeginLoc(), diag::err_omp_interop_bad_depend_clause);
17547 return StmtError();
17548 }
17549
17550 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17551 // Each interop-var may be specified for at most one action-clause of each
17552 // interop construct.
17553 llvm::SmallPtrSet<const ValueDecl *, 4> InteropVars;
17554 for (OMPClause *C : Clauses) {
17555 OpenMPClauseKind ClauseKind = C->getClauseKind();
17556 std::pair<ValueDecl *, bool> DeclResult;
17557 SourceLocation ELoc;
17558 SourceRange ERange;
17559
17560 if (ClauseKind == OMPC_init) {
17561 auto *E = cast<OMPInitClause>(C)->getInteropVar();
17562 DeclResult = getPrivateItem(*this, E, ELoc, ERange);
17563 } else if (ClauseKind == OMPC_use) {
17564 auto *E = cast<OMPUseClause>(C)->getInteropVar();
17565 DeclResult = getPrivateItem(*this, E, ELoc, ERange);
17566 } else if (ClauseKind == OMPC_destroy) {
17567 auto *E = cast<OMPDestroyClause>(C)->getInteropVar();
17568 DeclResult = getPrivateItem(*this, E, ELoc, ERange);
17569 }
17570
17571 if (DeclResult.first) {
17572 if (!InteropVars.insert(DeclResult.first).second) {
17573 Diag(ELoc, diag::err_omp_interop_var_multiple_actions)
17574 << DeclResult.first;
17575 return StmtError();
17576 }
17577 }
17578 }
17579
17580 return OMPInteropDirective::Create(Context, StartLoc, EndLoc, Clauses);
17581}
17582
17583static bool isValidInteropVariable(Sema &SemaRef, Expr *InteropVarExpr,
17584 SourceLocation VarLoc,
17585 OpenMPClauseKind Kind) {
17586 SourceLocation ELoc;
17587 SourceRange ERange;
17588 Expr *RefExpr = InteropVarExpr;
17589 auto Res =
17590 getPrivateItem(SemaRef, RefExpr, ELoc, ERange,
17591 /*AllowArraySection=*/false, /*DiagType=*/"omp_interop_t");
17592
17593 if (Res.second) {
17594 // It will be analyzed later.
17595 return true;
17596 }
17597
17598 if (!Res.first)
17599 return false;
17600
17601 // Interop variable should be of type omp_interop_t.
17602 bool HasError = false;
17603 QualType InteropType;
17604 LookupResult Result(SemaRef, &SemaRef.Context.Idents.get("omp_interop_t"),
17605 VarLoc, Sema::LookupOrdinaryName);
17606 if (SemaRef.LookupName(Result, SemaRef.getCurScope())) {
17607 NamedDecl *ND = Result.getFoundDecl();
17608 if (const auto *TD = dyn_cast<TypeDecl>(ND)) {
17609 InteropType = QualType(TD->getTypeForDecl(), 0);
17610 } else {
17611 HasError = true;
17612 }
17613 } else {
17614 HasError = true;
17615 }
17616
17617 if (HasError) {
17618 SemaRef.Diag(VarLoc, diag::err_omp_implied_type_not_found)
17619 << "omp_interop_t";
17620 return false;
17621 }
17622
17623 QualType VarType = InteropVarExpr->getType().getUnqualifiedType();
17624 if (!SemaRef.Context.hasSameType(InteropType, VarType)) {
17625 SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_wrong_type);
17626 return false;
17627 }
17628
17629 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17630 // The interop-var passed to init or destroy must be non-const.
17631 if ((Kind == OMPC_init || Kind == OMPC_destroy) &&
17632 isConstNotMutableType(SemaRef, InteropVarExpr->getType())) {
17633 SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_expected)
17634 << /*non-const*/ 1;
17635 return false;
17636 }
17637 return true;
17638}
17639
17640OMPClause *
17641Sema::ActOnOpenMPInitClause(Expr *InteropVar, OMPInteropInfo &InteropInfo,
17642 SourceLocation StartLoc, SourceLocation LParenLoc,
17643 SourceLocation VarLoc, SourceLocation EndLoc) {
17644
17645 if (!isValidInteropVariable(*this, InteropVar, VarLoc, OMPC_init))
17646 return nullptr;
17647
17648 // Check prefer_type values. These foreign-runtime-id values are either
17649 // string literals or constant integral expressions.
17650 for (const Expr *E : InteropInfo.PreferTypes) {
17651 if (E->isValueDependent() || E->isTypeDependent() ||
17652 E->isInstantiationDependent() || E->containsUnexpandedParameterPack())
17653 continue;
17654 if (E->isIntegerConstantExpr(Context))
17655 continue;
17656 if (isa<StringLiteral>(E))
17657 continue;
17658 Diag(E->getExprLoc(), diag::err_omp_interop_prefer_type);
17659 return nullptr;
17660 }
17661
17662 return OMPInitClause::Create(Context, InteropVar, InteropInfo, StartLoc,
17663 LParenLoc, VarLoc, EndLoc);
17664}
17665
17666OMPClause *Sema::ActOnOpenMPUseClause(Expr *InteropVar, SourceLocation StartLoc,
17667 SourceLocation LParenLoc,
17668 SourceLocation VarLoc,
17669 SourceLocation EndLoc) {
17670
17671 if (!isValidInteropVariable(*this, InteropVar, VarLoc, OMPC_use))
17672 return nullptr;
17673
17674 return new (Context)
17675 OMPUseClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
17676}
17677
17678OMPClause *Sema::ActOnOpenMPDestroyClause(Expr *InteropVar,
17679 SourceLocation StartLoc,
17680 SourceLocation LParenLoc,
17681 SourceLocation VarLoc,
17682 SourceLocation EndLoc) {
17683 if (!InteropVar && LangOpts.OpenMP >= 52 &&
17684 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective() == OMPD_depobj) {
17685 Diag(StartLoc, diag::err_omp_expected_clause_argument)
17686 << getOpenMPClauseName(OMPC_destroy)
17687 << getOpenMPDirectiveName(OMPD_depobj);
17688 return nullptr;
17689 }
17690 if (InteropVar &&
17691 !isValidInteropVariable(*this, InteropVar, VarLoc, OMPC_destroy))
17692 return nullptr;
17693
17694 return new (Context)
17695 OMPDestroyClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
17696}
17697
17698OMPClause *Sema::ActOnOpenMPNovariantsClause(Expr *Condition,
17699 SourceLocation StartLoc,
17700 SourceLocation LParenLoc,
17701 SourceLocation EndLoc) {
17702 Expr *ValExpr = Condition;
17703 Stmt *HelperValStmt = nullptr;
17704 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
17705 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
17706 !Condition->isInstantiationDependent() &&
17707 !Condition->containsUnexpandedParameterPack()) {
17708 ExprResult Val = CheckBooleanCondition(StartLoc, Condition);
17709 if (Val.isInvalid())
17710 return nullptr;
17711
17712 ValExpr = MakeFullExpr(Val.get()).get();
17713
17714 OpenMPDirectiveKind DKind = DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective();
17715 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_novariants,
17716 LangOpts.OpenMP);
17717 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
17718 ValExpr = MakeFullExpr(ValExpr).get();
17719 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17720 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
17721 HelperValStmt = buildPreInits(Context, Captures);
17722 }
17723 }
17724
17725 return new (Context) OMPNovariantsClause(
17726 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
17727}
17728
17729OMPClause *Sema::ActOnOpenMPNocontextClause(Expr *Condition,
17730 SourceLocation StartLoc,
17731 SourceLocation LParenLoc,
17732 SourceLocation EndLoc) {
17733 Expr *ValExpr = Condition;
17734 Stmt *HelperValStmt = nullptr;
17735 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
17736 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
17737 !Condition->isInstantiationDependent() &&
17738 !Condition->containsUnexpandedParameterPack()) {
17739 ExprResult Val = CheckBooleanCondition(StartLoc, Condition);
17740 if (Val.isInvalid())
17741 return nullptr;
17742
17743 ValExpr = MakeFullExpr(Val.get()).get();
17744
17745 OpenMPDirectiveKind DKind = DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective();
17746 CaptureRegion =
17747 getOpenMPCaptureRegionForClause(DKind, OMPC_nocontext, LangOpts.OpenMP);
17748 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
17749 ValExpr = MakeFullExpr(ValExpr).get();
17750 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17751 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
17752 HelperValStmt = buildPreInits(Context, Captures);
17753 }
17754 }
17755
17756 return new (Context) OMPNocontextClause(ValExpr, HelperValStmt, CaptureRegion,
17757 StartLoc, LParenLoc, EndLoc);
17758}
17759
17760OMPClause *Sema::ActOnOpenMPFilterClause(Expr *ThreadID,
17761 SourceLocation StartLoc,
17762 SourceLocation LParenLoc,
17763 SourceLocation EndLoc) {
17764 Expr *ValExpr = ThreadID;
17765 Stmt *HelperValStmt = nullptr;
17766
17767 OpenMPDirectiveKind DKind = DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective();
17768 OpenMPDirectiveKind CaptureRegion =
17769 getOpenMPCaptureRegionForClause(DKind, OMPC_filter, LangOpts.OpenMP);
17770 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
17771 ValExpr = MakeFullExpr(ValExpr).get();
17772 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17773 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
17774 HelperValStmt = buildPreInits(Context, Captures);
17775 }
17776
17777 return new (Context) OMPFilterClause(ValExpr, HelperValStmt, CaptureRegion,
17778 StartLoc, LParenLoc, EndLoc);
17779}
17780
17781OMPClause *Sema::ActOnOpenMPVarListClause(OpenMPClauseKind Kind,
17782 ArrayRef<Expr *> VarList,
17783 const OMPVarListLocTy &Locs,
17784 OpenMPVarListDataTy &Data) {
17785 SourceLocation StartLoc = Locs.StartLoc;
17786 SourceLocation LParenLoc = Locs.LParenLoc;
17787 SourceLocation EndLoc = Locs.EndLoc;
17788 OMPClause *Res = nullptr;
17789 int ExtraModifier = Data.ExtraModifier;
17790 SourceLocation ExtraModifierLoc = Data.ExtraModifierLoc;
17791 SourceLocation ColonLoc = Data.ColonLoc;
17792 switch (Kind) {
17793 case OMPC_private:
17794 Res = ActOnOpenMPPrivateClause(VarList, StartLoc, LParenLoc, EndLoc);
17795 break;
17796 case OMPC_firstprivate:
17797 Res = ActOnOpenMPFirstprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
17798 break;
17799 case OMPC_lastprivate:
17800 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LASTPRIVATE_unknown &&(static_cast <bool> (0 <= ExtraModifier && ExtraModifier
<= OMPC_LASTPRIVATE_unknown && "Unexpected lastprivate modifier."
) ? void (0) : __assert_fail ("0 <= ExtraModifier && ExtraModifier <= OMPC_LASTPRIVATE_unknown && \"Unexpected lastprivate modifier.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 17801, __extension__ __PRETTY_FUNCTION__
))
17801 "Unexpected lastprivate modifier.")(static_cast <bool> (0 <= ExtraModifier && ExtraModifier
<= OMPC_LASTPRIVATE_unknown && "Unexpected lastprivate modifier."
) ? void (0) : __assert_fail ("0 <= ExtraModifier && ExtraModifier <= OMPC_LASTPRIVATE_unknown && \"Unexpected lastprivate modifier.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 17801, __extension__ __PRETTY_FUNCTION__
))
;
17802 Res = ActOnOpenMPLastprivateClause(
17803 VarList, static_cast<OpenMPLastprivateModifier>(ExtraModifier),
17804 ExtraModifierLoc, ColonLoc, StartLoc, LParenLoc, EndLoc);
17805 break;
17806 case OMPC_shared:
17807 Res = ActOnOpenMPSharedClause(VarList, StartLoc, LParenLoc, EndLoc);
17808 break;
17809 case OMPC_reduction:
17810 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_REDUCTION_unknown &&(static_cast <bool> (0 <= ExtraModifier && ExtraModifier
<= OMPC_REDUCTION_unknown && "Unexpected lastprivate modifier."
) ? void (0) : __assert_fail ("0 <= ExtraModifier && ExtraModifier <= OMPC_REDUCTION_unknown && \"Unexpected lastprivate modifier.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 17811, __extension__ __PRETTY_FUNCTION__
))
17811 "Unexpected lastprivate modifier.")(static_cast <bool> (0 <= ExtraModifier && ExtraModifier
<= OMPC_REDUCTION_unknown && "Unexpected lastprivate modifier."
) ? void (0) : __assert_fail ("0 <= ExtraModifier && ExtraModifier <= OMPC_REDUCTION_unknown && \"Unexpected lastprivate modifier.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 17811, __extension__ __PRETTY_FUNCTION__
))
;
17812 Res = ActOnOpenMPReductionClause(
17813 VarList, static_cast<OpenMPReductionClauseModifier>(ExtraModifier),
17814 StartLoc, LParenLoc, ExtraModifierLoc, ColonLoc, EndLoc,
17815 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
17816 break;
17817 case OMPC_task_reduction:
17818 Res = ActOnOpenMPTaskReductionClause(
17819 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
17820 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
17821 break;
17822 case OMPC_in_reduction:
17823 Res = ActOnOpenMPInReductionClause(
17824 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
17825 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
17826 break;
17827 case OMPC_linear:
17828 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LINEAR_unknown &&(static_cast <bool> (0 <= ExtraModifier && ExtraModifier
<= OMPC_LINEAR_unknown && "Unexpected linear modifier."
) ? void (0) : __assert_fail ("0 <= ExtraModifier && ExtraModifier <= OMPC_LINEAR_unknown && \"Unexpected linear modifier.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 17829, __extension__ __PRETTY_FUNCTION__
))
17829 "Unexpected linear modifier.")(static_cast <bool> (0 <= ExtraModifier && ExtraModifier
<= OMPC_LINEAR_unknown && "Unexpected linear modifier."
) ? void (0) : __assert_fail ("0 <= ExtraModifier && ExtraModifier <= OMPC_LINEAR_unknown && \"Unexpected linear modifier.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 17829, __extension__ __PRETTY_FUNCTION__
))
;
17830 Res = ActOnOpenMPLinearClause(
17831 VarList, Data.DepModOrTailExpr, StartLoc, LParenLoc,
17832 static_cast<OpenMPLinearClauseKind>(ExtraModifier), ExtraModifierLoc,
17833 ColonLoc, EndLoc);
17834 break;
17835 case OMPC_aligned:
17836 Res = ActOnOpenMPAlignedClause(VarList, Data.DepModOrTailExpr, StartLoc,
17837 LParenLoc, ColonLoc, EndLoc);
17838 break;
17839 case OMPC_copyin:
17840 Res = ActOnOpenMPCopyinClause(VarList, StartLoc, LParenLoc, EndLoc);
17841 break;
17842 case OMPC_copyprivate:
17843 Res = ActOnOpenMPCopyprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
17844 break;
17845 case OMPC_flush:
17846 Res = ActOnOpenMPFlushClause(VarList, StartLoc, LParenLoc, EndLoc);
17847 break;
17848 case OMPC_depend:
17849 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_DEPEND_unknown &&(static_cast <bool> (0 <= ExtraModifier && ExtraModifier
<= OMPC_DEPEND_unknown && "Unexpected depend modifier."
) ? void (0) : __assert_fail ("0 <= ExtraModifier && ExtraModifier <= OMPC_DEPEND_unknown && \"Unexpected depend modifier.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 17850, __extension__ __PRETTY_FUNCTION__
))
17850 "Unexpected depend modifier.")(static_cast <bool> (0 <= ExtraModifier && ExtraModifier
<= OMPC_DEPEND_unknown && "Unexpected depend modifier."
) ? void (0) : __assert_fail ("0 <= ExtraModifier && ExtraModifier <= OMPC_DEPEND_unknown && \"Unexpected depend modifier.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 17850, __extension__ __PRETTY_FUNCTION__
))
;
17851 Res = ActOnOpenMPDependClause(
17852 {static_cast<OpenMPDependClauseKind>(ExtraModifier), ExtraModifierLoc,
17853 ColonLoc, Data.OmpAllMemoryLoc},
17854 Data.DepModOrTailExpr, VarList, StartLoc, LParenLoc, EndLoc);
17855 break;
17856 case OMPC_map:
17857 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_MAP_unknown &&(static_cast <bool> (0 <= ExtraModifier && ExtraModifier
<= OMPC_MAP_unknown && "Unexpected map modifier."
) ? void (0) : __assert_fail ("0 <= ExtraModifier && ExtraModifier <= OMPC_MAP_unknown && \"Unexpected map modifier.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 17858, __extension__ __PRETTY_FUNCTION__
))
17858 "Unexpected map modifier.")(static_cast <bool> (0 <= ExtraModifier && ExtraModifier
<= OMPC_MAP_unknown && "Unexpected map modifier."
) ? void (0) : __assert_fail ("0 <= ExtraModifier && ExtraModifier <= OMPC_MAP_unknown && \"Unexpected map modifier.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 17858, __extension__ __PRETTY_FUNCTION__
))
;
17859 Res = ActOnOpenMPMapClause(
17860 Data.IteratorExpr, Data.MapTypeModifiers, Data.MapTypeModifiersLoc,
17861 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId,
17862 static_cast<OpenMPMapClauseKind>(ExtraModifier), Data.IsMapTypeImplicit,
17863 ExtraModifierLoc, ColonLoc, VarList, Locs);
17864 break;
17865 case OMPC_to:
17866 Res =
17867 ActOnOpenMPToClause(Data.MotionModifiers, Data.MotionModifiersLoc,
17868 Data.ReductionOrMapperIdScopeSpec,
17869 Data.ReductionOrMapperId, ColonLoc, VarList, Locs);
17870 break;
17871 case OMPC_from:
17872 Res = ActOnOpenMPFromClause(Data.MotionModifiers, Data.MotionModifiersLoc,
17873 Data.ReductionOrMapperIdScopeSpec,
17874 Data.ReductionOrMapperId, ColonLoc, VarList,
17875 Locs);
17876 break;
17877 case OMPC_use_device_ptr:
17878 Res = ActOnOpenMPUseDevicePtrClause(VarList, Locs);
17879 break;
17880 case OMPC_use_device_addr:
17881 Res = ActOnOpenMPUseDeviceAddrClause(VarList, Locs);
17882 break;
17883 case OMPC_is_device_ptr:
17884 Res = ActOnOpenMPIsDevicePtrClause(VarList, Locs);
17885 break;
17886 case OMPC_has_device_addr:
17887 Res = ActOnOpenMPHasDeviceAddrClause(VarList, Locs);
17888 break;
17889 case OMPC_allocate:
17890 Res = ActOnOpenMPAllocateClause(Data.DepModOrTailExpr, VarList, StartLoc,
17891 LParenLoc, ColonLoc, EndLoc);
17892 break;
17893 case OMPC_nontemporal:
17894 Res = ActOnOpenMPNontemporalClause(VarList, StartLoc, LParenLoc, EndLoc);
17895 break;
17896 case OMPC_inclusive:
17897 Res = ActOnOpenMPInclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
17898 break;
17899 case OMPC_exclusive:
17900 Res = ActOnOpenMPExclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
17901 break;
17902 case OMPC_affinity:
17903 Res = ActOnOpenMPAffinityClause(StartLoc, LParenLoc, ColonLoc, EndLoc,
17904 Data.DepModOrTailExpr, VarList);
17905 break;
17906 case OMPC_if:
17907 case OMPC_depobj:
17908 case OMPC_final:
17909 case OMPC_num_threads:
17910 case OMPC_safelen:
17911 case OMPC_simdlen:
17912 case OMPC_sizes:
17913 case OMPC_allocator:
17914 case OMPC_collapse:
17915 case OMPC_default:
17916 case OMPC_proc_bind:
17917 case OMPC_schedule:
17918 case OMPC_ordered:
17919 case OMPC_nowait:
17920 case OMPC_untied:
17921 case OMPC_mergeable:
17922 case OMPC_threadprivate:
17923 case OMPC_read:
17924 case OMPC_write:
17925 case OMPC_update:
17926 case OMPC_capture:
17927 case OMPC_compare:
17928 case OMPC_seq_cst:
17929 case OMPC_acq_rel:
17930 case OMPC_acquire:
17931 case OMPC_release:
17932 case OMPC_relaxed:
17933 case OMPC_device:
17934 case OMPC_threads:
17935 case OMPC_simd:
17936 case OMPC_num_teams:
17937 case OMPC_thread_limit:
17938 case OMPC_priority:
17939 case OMPC_grainsize:
17940 case OMPC_nogroup:
17941 case OMPC_num_tasks:
17942 case OMPC_hint:
17943 case OMPC_dist_schedule:
17944 case OMPC_defaultmap:
17945 case OMPC_unknown:
17946 case OMPC_uniform:
17947 case OMPC_unified_address:
17948 case OMPC_unified_shared_memory:
17949 case OMPC_reverse_offload:
17950 case OMPC_dynamic_allocators:
17951 case OMPC_atomic_default_mem_order:
17952 case OMPC_device_type:
17953 case OMPC_match:
17954 case OMPC_order:
17955 case OMPC_at:
17956 case OMPC_severity:
17957 case OMPC_message:
17958 case OMPC_destroy:
17959 case OMPC_novariants:
17960 case OMPC_nocontext:
17961 case OMPC_detach:
17962 case OMPC_uses_allocators:
17963 case OMPC_when:
17964 case OMPC_bind:
17965 default:
17966 llvm_unreachable("Clause is not allowed.")::llvm::llvm_unreachable_internal("Clause is not allowed.", "clang/lib/Sema/SemaOpenMP.cpp"
, 17966)
;
17967 }
17968 return Res;
17969}
17970
17971ExprResult Sema::getOpenMPCapturedExpr(VarDecl *Capture, ExprValueKind VK,
17972 ExprObjectKind OK, SourceLocation Loc) {
17973 ExprResult Res = BuildDeclRefExpr(
17974 Capture, Capture->getType().getNonReferenceType(), VK_LValue, Loc);
17975 if (!Res.isUsable())
17976 return ExprError();
17977 if (OK == OK_Ordinary && !getLangOpts().CPlusPlus) {
17978 Res = CreateBuiltinUnaryOp(Loc, UO_Deref, Res.get());
17979 if (!Res.isUsable())
17980 return ExprError();
17981 }
17982 if (VK != VK_LValue && Res.get()->isGLValue()) {
17983 Res = DefaultLvalueConversion(Res.get());
17984 if (!Res.isUsable())
17985 return ExprError();
17986 }
17987 return Res;
17988}
17989
17990OMPClause *Sema::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
17991 SourceLocation StartLoc,
17992 SourceLocation LParenLoc,
17993 SourceLocation EndLoc) {
17994 SmallVector<Expr *, 8> Vars;
17995 SmallVector<Expr *, 8> PrivateCopies;
17996 bool IsImplicitClause =
17997 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
17998 for (Expr *RefExpr : VarList) {
17999 assert(RefExpr && "NULL expr in OpenMP private clause.")(static_cast <bool> (RefExpr && "NULL expr in OpenMP private clause."
) ? void (0) : __assert_fail ("RefExpr && \"NULL expr in OpenMP private clause.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 17999, __extension__ __PRETTY_FUNCTION__
))
;
18000 SourceLocation ELoc;
18001 SourceRange ERange;
18002 Expr *SimpleRefExpr = RefExpr;
18003 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
18004 if (Res.second) {
18005 // It will be analyzed later.
18006 Vars.push_back(RefExpr);
18007 PrivateCopies.push_back(nullptr);
18008 }
18009 ValueDecl *D = Res.first;
18010 if (!D)
18011 continue;
18012
18013 QualType Type = D->getType();
18014 auto *VD = dyn_cast<VarDecl>(D);
18015
18016 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
18017 // A variable that appears in a private clause must not have an incomplete
18018 // type or a reference type.
18019 if (RequireCompleteType(ELoc, Type, diag::err_omp_private_incomplete_type))
18020 continue;
18021 Type = Type.getNonReferenceType();
18022
18023 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
18024 // A variable that is privatized must not have a const-qualified type
18025 // unless it is of class type with a mutable member. This restriction does
18026 // not apply to the firstprivate clause.
18027 //
18028 // OpenMP 3.1 [2.9.3.3, private clause, Restrictions]
18029 // A variable that appears in a private clause must not have a
18030 // const-qualified type unless it is of class type with a mutable member.
18031 if (rejectConstNotMutableType(*this, D, Type, OMPC_private, ELoc))
18032 continue;
18033
18034 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
18035 // in a Construct]
18036 // Variables with the predetermined data-sharing attributes may not be
18037 // listed in data-sharing attributes clauses, except for the cases
18038 // listed below. For these exceptions only, listing a predetermined
18039 // variable in a data-sharing attribute clause is allowed and overrides
18040 // the variable's predetermined data-sharing attributes.
18041 DSAStackTy::DSAVarData DVar = DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getTopDSA(D, /*FromParent=*/false);
18042 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private) {
18043 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
18044 << getOpenMPClauseName(OMPC_private);
18045 reportOriginalDsa(*this, DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
, D, DVar);
18046 continue;
18047 }
18048
18049 OpenMPDirectiveKind CurrDir = DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective();
18050 // Variably modified types are not supported for tasks.
18051 if (!Type->isAnyPointerType() && Type->isVariablyModifiedType() &&
18052 isOpenMPTaskingDirective(CurrDir)) {
18053 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
18054 << getOpenMPClauseName(OMPC_private) << Type
18055 << getOpenMPDirectiveName(CurrDir);
18056 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
18057 VarDecl::DeclarationOnly;
18058 Diag(D->getLocation(),
18059 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18060 << D;
18061 continue;
18062 }
18063
18064 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
18065 // A list item cannot appear in both a map clause and a data-sharing
18066 // attribute clause on the same construct
18067 //
18068 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
18069 // A list item cannot appear in both a map clause and a data-sharing
18070 // attribute clause on the same construct unless the construct is a
18071 // combined construct.
18072 if ((LangOpts.OpenMP <= 45 && isOpenMPTargetExecutionDirective(CurrDir)) ||
18073 CurrDir == OMPD_target) {
18074 OpenMPClauseKind ConflictKind;
18075 if (DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->checkMappableExprComponentListsForDecl(
18076 VD, /*CurrentRegionOnly=*/true,
18077 [&](OMPClauseMappableExprCommon::MappableExprComponentListRef,
18078 OpenMPClauseKind WhereFoundClauseKind) -> bool {
18079 ConflictKind = WhereFoundClauseKind;
18080 return true;
18081 })) {
18082 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
18083 << getOpenMPClauseName(OMPC_private)
18084 << getOpenMPClauseName(ConflictKind)
18085 << getOpenMPDirectiveName(CurrDir);
18086 reportOriginalDsa(*this, DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
, D, DVar);
18087 continue;
18088 }
18089 }
18090
18091 // OpenMP [2.9.3.3, Restrictions, C/C++, p.1]
18092 // A variable of class type (or array thereof) that appears in a private
18093 // clause requires an accessible, unambiguous default constructor for the
18094 // class type.
18095 // Generate helper private variable and initialize it with the default
18096 // value. The address of the original variable is replaced by the address of
18097 // the new private variable in CodeGen. This new variable is not added to
18098 // IdResolver, so the code in the OpenMP region uses original variable for
18099 // proper diagnostics.
18100 Type = Type.getUnqualifiedType();
18101 VarDecl *VDPrivate =
18102 buildVarDecl(*this, ELoc, Type, D->getName(),
18103 D->hasAttrs() ? &D->getAttrs() : nullptr,
18104 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
18105 ActOnUninitializedDecl(VDPrivate);
18106 if (VDPrivate->isInvalidDecl())
18107 continue;
18108 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
18109 *this, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
18110
18111 DeclRefExpr *Ref = nullptr;
18112 if (!VD && !CurContext->isDependentContext()) {
18113 auto *FD = dyn_cast<FieldDecl>(D);
18114 VarDecl *VD = FD ? DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getImplicitFDCapExprDecl(FD) : nullptr;
18115 if (VD)
18116 Ref = buildDeclRefExpr(*this, VD, VD->getType().getNonReferenceType(),
18117 RefExpr->getExprLoc());
18118 else
18119 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/false);
18120 }
18121 if (!IsImplicitClause)
18122 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->addDSA(D, RefExpr->IgnoreParens(), OMPC_private, Ref);
18123 Vars.push_back((VD || CurContext->isDependentContext())
18124 ? RefExpr->IgnoreParens()
18125 : Ref);
18126 PrivateCopies.push_back(VDPrivateRefExpr);
18127 }
18128
18129 if (Vars.empty())
18130 return nullptr;
18131
18132 return OMPPrivateClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars,
18133 PrivateCopies);
18134}
18135
18136OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
18137 SourceLocation StartLoc,
18138 SourceLocation LParenLoc,
18139 SourceLocation EndLoc) {
18140 SmallVector<Expr *, 8> Vars;
18141 SmallVector<Expr *, 8> PrivateCopies;
18142 SmallVector<Expr *, 8> Inits;
18143 SmallVector<Decl *, 4> ExprCaptures;
18144 bool IsImplicitClause =
18145 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
18146 SourceLocation ImplicitClauseLoc = DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getConstructLoc();
18147
18148 for (Expr *RefExpr : VarList) {
18149 assert(RefExpr && "NULL expr in OpenMP firstprivate clause.")(static_cast <bool> (RefExpr && "NULL expr in OpenMP firstprivate clause."
) ? void (0) : __assert_fail ("RefExpr && \"NULL expr in OpenMP firstprivate clause.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 18149, __extension__ __PRETTY_FUNCTION__
))
;
18150 SourceLocation ELoc;
18151 SourceRange ERange;
18152 Expr *SimpleRefExpr = RefExpr;
18153 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
18154 if (Res.second) {
18155 // It will be analyzed later.
18156 Vars.push_back(RefExpr);
18157 PrivateCopies.push_back(nullptr);
18158 Inits.push_back(nullptr);
18159 }
18160 ValueDecl *D = Res.first;
18161 if (!D)
18162 continue;
18163
18164 ELoc = IsImplicitClause ? ImplicitClauseLoc : ELoc;
18165 QualType Type = D->getType();
18166 auto *VD = dyn_cast<VarDecl>(D);
18167
18168 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
18169 // A variable that appears in a private clause must not have an incomplete
18170 // type or a reference type.
18171 if (RequireCompleteType(ELoc, Type,
18172 diag::err_omp_firstprivate_incomplete_type))
18173 continue;
18174 Type = Type.getNonReferenceType();
18175
18176 // OpenMP [2.9.3.4, Restrictions, C/C++, p.1]
18177 // A variable of class type (or array thereof) that appears in a private
18178 // clause requires an accessible, unambiguous copy constructor for the
18179 // class type.
18180 QualType ElemType = Context.getBaseElementType(Type).getNonReferenceType();
18181
18182 // If an implicit firstprivate variable found it was checked already.
18183 DSAStackTy::DSAVarData TopDVar;
18184 if (!IsImplicitClause) {
18185 DSAStackTy::DSAVarData DVar =
18186 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getTopDSA(D, /*FromParent=*/false);
18187 TopDVar = DVar;
18188 OpenMPDirectiveKind CurrDir = DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective();
18189 bool IsConstant = ElemType.isConstant(Context);
18190 // OpenMP [2.4.13, Data-sharing Attribute Clauses]
18191 // A list item that specifies a given variable may not appear in more
18192 // than one clause on the same directive, except that a variable may be
18193 // specified in both firstprivate and lastprivate clauses.
18194 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
18195 // A list item may appear in a firstprivate or lastprivate clause but not
18196 // both.
18197 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
18198 (isOpenMPDistributeDirective(CurrDir) ||
18199 DVar.CKind != OMPC_lastprivate) &&
18200 DVar.RefExpr) {
18201 Diag(ELoc, diag::err_omp_wrong_dsa)
18202 << getOpenMPClauseName(DVar.CKind)
18203 << getOpenMPClauseName(OMPC_firstprivate);
18204 reportOriginalDsa(*this, DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
, D, DVar);
18205 continue;
18206 }
18207
18208 // OpenMP [2.9.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. For these exceptions only, listing a predetermined
18213 // variable in a data-sharing attribute clause is allowed and overrides
18214 // the variable's predetermined data-sharing attributes.
18215 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
18216 // in a Construct, C/C++, p.2]
18217 // Variables with const-qualified type having no mutable member may be
18218 // listed in a firstprivate clause, even if they are static data members.
18219 if (!(IsConstant || (VD && VD->isStaticDataMember())) && !DVar.RefExpr &&
18220 DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared) {
18221 Diag(ELoc, diag::err_omp_wrong_dsa)
18222 << getOpenMPClauseName(DVar.CKind)
18223 << getOpenMPClauseName(OMPC_firstprivate);
18224 reportOriginalDsa(*this, DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
, D, DVar);
18225 continue;
18226 }
18227
18228 // OpenMP [2.9.3.4, Restrictions, p.2]
18229 // A list item that is private within a parallel region must not appear
18230 // in a firstprivate clause on a worksharing construct if any of the
18231 // worksharing regions arising from the worksharing construct ever bind
18232 // to any of the parallel regions arising from the parallel construct.
18233 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
18234 // A list item that is private within a teams region must not appear in a
18235 // firstprivate clause on a distribute construct if any of the distribute
18236 // regions arising from the distribute construct ever bind to any of the
18237 // teams regions arising from the teams construct.
18238 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
18239 // A list item that appears in a reduction clause of a teams construct
18240 // must not appear in a firstprivate clause on a distribute construct if
18241 // any of the distribute regions arising from the distribute construct
18242 // ever bind to any of the teams regions arising from the teams construct.
18243 if ((isOpenMPWorksharingDirective(CurrDir) ||
18244 isOpenMPDistributeDirective(CurrDir)) &&
18245 !isOpenMPParallelDirective(CurrDir) &&
18246 !isOpenMPTeamsDirective(CurrDir)) {
18247 DVar = DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getImplicitDSA(D, true);
18248 if (DVar.CKind != OMPC_shared &&
18249 (isOpenMPParallelDirective(DVar.DKind) ||
18250 isOpenMPTeamsDirective(DVar.DKind) ||
18251 DVar.DKind == OMPD_unknown)) {
18252 Diag(ELoc, diag::err_omp_required_access)
18253 << getOpenMPClauseName(OMPC_firstprivate)
18254 << getOpenMPClauseName(OMPC_shared);
18255 reportOriginalDsa(*this, DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
, D, DVar);
18256 continue;
18257 }
18258 }
18259 // OpenMP [2.9.3.4, Restrictions, p.3]
18260 // A list item that appears in a reduction clause of a parallel construct
18261 // must not appear in a firstprivate clause on a worksharing or task
18262 // construct if any of the worksharing or task regions arising from the
18263 // worksharing or task construct ever bind to any of the parallel regions
18264 // arising from the parallel construct.
18265 // OpenMP [2.9.3.4, Restrictions, p.4]
18266 // A list item that appears in a reduction clause in worksharing
18267 // construct must not appear in a firstprivate clause in a task construct
18268 // encountered during execution of any of the worksharing regions arising
18269 // from the worksharing construct.
18270 if (isOpenMPTaskingDirective(CurrDir)) {
18271 DVar = DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->hasInnermostDSA(
18272 D,
18273 [](OpenMPClauseKind C, bool AppliedToPointee) {
18274 return C == OMPC_reduction && !AppliedToPointee;
18275 },
18276 [](OpenMPDirectiveKind K) {
18277 return isOpenMPParallelDirective(K) ||
18278 isOpenMPWorksharingDirective(K) ||
18279 isOpenMPTeamsDirective(K);
18280 },
18281 /*FromParent=*/true);
18282 if (DVar.CKind == OMPC_reduction &&
18283 (isOpenMPParallelDirective(DVar.DKind) ||
18284 isOpenMPWorksharingDirective(DVar.DKind) ||
18285 isOpenMPTeamsDirective(DVar.DKind))) {
18286 Diag(ELoc, diag::err_omp_parallel_reduction_in_task_firstprivate)
18287 << getOpenMPDirectiveName(DVar.DKind);
18288 reportOriginalDsa(*this, DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
, D, DVar);
18289 continue;
18290 }
18291 }
18292
18293 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
18294 // A list item cannot appear in both a map clause and a data-sharing
18295 // attribute clause on the same construct
18296 //
18297 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
18298 // A list item cannot appear in both a map clause and a data-sharing
18299 // attribute clause on the same construct unless the construct is a
18300 // combined construct.
18301 if ((LangOpts.OpenMP <= 45 &&
18302 isOpenMPTargetExecutionDirective(CurrDir)) ||
18303 CurrDir == OMPD_target) {
18304 OpenMPClauseKind ConflictKind;
18305 if (DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->checkMappableExprComponentListsForDecl(
18306 VD, /*CurrentRegionOnly=*/true,
18307 [&ConflictKind](
18308 OMPClauseMappableExprCommon::MappableExprComponentListRef,
18309 OpenMPClauseKind WhereFoundClauseKind) {
18310 ConflictKind = WhereFoundClauseKind;
18311 return true;
18312 })) {
18313 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
18314 << getOpenMPClauseName(OMPC_firstprivate)
18315 << getOpenMPClauseName(ConflictKind)
18316 << getOpenMPDirectiveName(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective());
18317 reportOriginalDsa(*this, DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
, D, DVar);
18318 continue;
18319 }
18320 }
18321 }
18322
18323 // Variably modified types are not supported for tasks.
18324 if (!Type->isAnyPointerType() && Type->isVariablyModifiedType() &&
18325 isOpenMPTaskingDirective(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective())) {
18326 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
18327 << getOpenMPClauseName(OMPC_firstprivate) << Type
18328 << getOpenMPDirectiveName(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective());
18329 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
18330 VarDecl::DeclarationOnly;
18331 Diag(D->getLocation(),
18332 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18333 << D;
18334 continue;
18335 }
18336
18337 Type = Type.getUnqualifiedType();
18338 VarDecl *VDPrivate =
18339 buildVarDecl(*this, ELoc, Type, D->getName(),
18340 D->hasAttrs() ? &D->getAttrs() : nullptr,
18341 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
18342 // Generate helper private variable and initialize it with the value of the
18343 // original variable. The address of the original variable is replaced by
18344 // the address of the new private variable in the CodeGen. This new variable
18345 // is not added to IdResolver, so the code in the OpenMP region uses
18346 // original variable for proper diagnostics and variable capturing.
18347 Expr *VDInitRefExpr = nullptr;
18348 // For arrays generate initializer for single element and replace it by the
18349 // original array element in CodeGen.
18350 if (Type->isArrayType()) {
18351 VarDecl *VDInit =
18352 buildVarDecl(*this, RefExpr->getExprLoc(), ElemType, D->getName());
18353 VDInitRefExpr = buildDeclRefExpr(*this, VDInit, ElemType, ELoc);
18354 Expr *Init = DefaultLvalueConversion(VDInitRefExpr).get();
18355 ElemType = ElemType.getUnqualifiedType();
18356 VarDecl *VDInitTemp = buildVarDecl(*this, RefExpr->getExprLoc(), ElemType,
18357 ".firstprivate.temp");
18358 InitializedEntity Entity =
18359 InitializedEntity::InitializeVariable(VDInitTemp);
18360 InitializationKind Kind = InitializationKind::CreateCopy(ELoc, ELoc);
18361
18362 InitializationSequence InitSeq(*this, Entity, Kind, Init);
18363 ExprResult Result = InitSeq.Perform(*this, Entity, Kind, Init);
18364 if (Result.isInvalid())
18365 VDPrivate->setInvalidDecl();
18366 else
18367 VDPrivate->setInit(Result.getAs<Expr>());
18368 // Remove temp variable declaration.
18369 Context.Deallocate(VDInitTemp);
18370 } else {
18371 VarDecl *VDInit = buildVarDecl(*this, RefExpr->getExprLoc(), Type,
18372 ".firstprivate.temp");
18373 VDInitRefExpr = buildDeclRefExpr(*this, VDInit, RefExpr->getType(),
18374 RefExpr->getExprLoc());
18375 AddInitializerToDecl(VDPrivate,
18376 DefaultLvalueConversion(VDInitRefExpr).get(),
18377 /*DirectInit=*/false);
18378 }
18379 if (VDPrivate->isInvalidDecl()) {
18380 if (IsImplicitClause) {
18381 Diag(RefExpr->getExprLoc(),
18382 diag::note_omp_task_predetermined_firstprivate_here);
18383 }
18384 continue;
18385 }
18386 CurContext->addDecl(VDPrivate);
18387 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
18388 *this, VDPrivate, RefExpr->getType().getUnqualifiedType(),
18389 RefExpr->getExprLoc());
18390 DeclRefExpr *Ref = nullptr;
18391 if (!VD && !CurContext->isDependentContext()) {
18392 if (TopDVar.CKind == OMPC_lastprivate) {
18393 Ref = TopDVar.PrivateCopy;
18394 } else {
18395 auto *FD = dyn_cast<FieldDecl>(D);
18396 VarDecl *VD = FD ? DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getImplicitFDCapExprDecl(FD) : nullptr;
18397 if (VD)
18398 Ref = buildDeclRefExpr(*this, VD, VD->getType().getNonReferenceType(),
18399 RefExpr->getExprLoc());
18400 else
18401 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true);
18402 if (VD || !isOpenMPCapturedDecl(D))
18403 ExprCaptures.push_back(Ref->getDecl());
18404 }
18405 }
18406 if (!IsImplicitClause)
18407 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
18408 Vars.push_back((VD || CurContext->isDependentContext())
18409 ? RefExpr->IgnoreParens()
18410 : Ref);
18411 PrivateCopies.push_back(VDPrivateRefExpr);
18412 Inits.push_back(VDInitRefExpr);
18413 }
18414
18415 if (Vars.empty())
18416 return nullptr;
18417
18418 return OMPFirstprivateClause::Create(Context, StartLoc, LParenLoc, EndLoc,
18419 Vars, PrivateCopies, Inits,
18420 buildPreInits(Context, ExprCaptures));
18421}
18422
18423OMPClause *Sema::ActOnOpenMPLastprivateClause(
18424 ArrayRef<Expr *> VarList, OpenMPLastprivateModifier LPKind,
18425 SourceLocation LPKindLoc, SourceLocation ColonLoc, SourceLocation StartLoc,
18426 SourceLocation LParenLoc, SourceLocation EndLoc) {
18427 if (LPKind == OMPC_LASTPRIVATE_unknown && LPKindLoc.isValid()) {
18428 assert(ColonLoc.isValid() && "Colon location must be valid.")(static_cast <bool> (ColonLoc.isValid() && "Colon location must be valid."
) ? void (0) : __assert_fail ("ColonLoc.isValid() && \"Colon location must be valid.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 18428, __extension__ __PRETTY_FUNCTION__
))
;
18429 Diag(LPKindLoc, diag::err_omp_unexpected_clause_value)
18430 << getListOfPossibleValues(OMPC_lastprivate, /*First=*/0,
18431 /*Last=*/OMPC_LASTPRIVATE_unknown)
18432 << getOpenMPClauseName(OMPC_lastprivate);
18433 return nullptr;
18434 }
18435
18436 SmallVector<Expr *, 8> Vars;
18437 SmallVector<Expr *, 8> SrcExprs;
18438 SmallVector<Expr *, 8> DstExprs;
18439 SmallVector<Expr *, 8> AssignmentOps;
18440 SmallVector<Decl *, 4> ExprCaptures;
18441 SmallVector<Expr *, 4> ExprPostUpdates;
18442 for (Expr *RefExpr : VarList) {
18443 assert(RefExpr && "NULL expr in OpenMP lastprivate clause.")(static_cast <bool> (RefExpr && "NULL expr in OpenMP lastprivate clause."
) ? void (0) : __assert_fail ("RefExpr && \"NULL expr in OpenMP lastprivate clause.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 18443, __extension__ __PRETTY_FUNCTION__
))
;
18444 SourceLocation ELoc;
18445 SourceRange ERange;
18446 Expr *SimpleRefExpr = RefExpr;
18447 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
18448 if (Res.second) {
18449 // It will be analyzed later.
18450 Vars.push_back(RefExpr);
18451 SrcExprs.push_back(nullptr);
18452 DstExprs.push_back(nullptr);
18453 AssignmentOps.push_back(nullptr);
18454 }
18455 ValueDecl *D = Res.first;
18456 if (!D)
18457 continue;
18458
18459 QualType Type = D->getType();
18460 auto *VD = dyn_cast<VarDecl>(D);
18461
18462 // OpenMP [2.14.3.5, Restrictions, C/C++, p.2]
18463 // A variable that appears in a lastprivate clause must not have an
18464 // incomplete type or a reference type.
18465 if (RequireCompleteType(ELoc, Type,
18466 diag::err_omp_lastprivate_incomplete_type))
18467 continue;
18468 Type = Type.getNonReferenceType();
18469
18470 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
18471 // A variable that is privatized must not have a const-qualified type
18472 // unless it is of class type with a mutable member. This restriction does
18473 // not apply to the firstprivate clause.
18474 //
18475 // OpenMP 3.1 [2.9.3.5, lastprivate clause, Restrictions]
18476 // A variable that appears in a lastprivate clause must not have a
18477 // const-qualified type unless it is of class type with a mutable member.
18478 if (rejectConstNotMutableType(*this, D, Type, OMPC_lastprivate, ELoc))
18479 continue;
18480
18481 // OpenMP 5.0 [2.19.4.5 lastprivate Clause, Restrictions]
18482 // A list item that appears in a lastprivate clause with the conditional
18483 // modifier must be a scalar variable.
18484 if (LPKind == OMPC_LASTPRIVATE_conditional && !Type->isScalarType()) {
18485 Diag(ELoc, diag::err_omp_lastprivate_conditional_non_scalar);
18486 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
18487 VarDecl::DeclarationOnly;
18488 Diag(D->getLocation(),
18489 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18490 << D;
18491 continue;
18492 }
18493
18494 OpenMPDirectiveKind CurrDir = DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective();
18495 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
18496 // in a Construct]
18497 // Variables with the predetermined data-sharing attributes may not be
18498 // listed in data-sharing attributes clauses, except for the cases
18499 // listed below.
18500 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
18501 // A list item may appear in a firstprivate or lastprivate clause but not
18502 // both.
18503 DSAStackTy::DSAVarData DVar = DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getTopDSA(D, /*FromParent=*/false);
18504 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_lastprivate &&
18505 (isOpenMPDistributeDirective(CurrDir) ||
18506 DVar.CKind != OMPC_firstprivate) &&
18507 (DVar.CKind != OMPC_private || DVar.RefExpr != nullptr)) {
18508 Diag(ELoc, diag::err_omp_wrong_dsa)
18509 << getOpenMPClauseName(DVar.CKind)
18510 << getOpenMPClauseName(OMPC_lastprivate);
18511 reportOriginalDsa(*this, DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
, D, DVar);
18512 continue;
18513 }
18514
18515 // OpenMP [2.14.3.5, Restrictions, p.2]
18516 // A list item that is private within a parallel region, or that appears in
18517 // the reduction clause of a parallel construct, must not appear in a
18518 // lastprivate clause on a worksharing construct if any of the corresponding
18519 // worksharing regions ever binds to any of the corresponding parallel
18520 // regions.
18521 DSAStackTy::DSAVarData TopDVar = DVar;
18522 if (isOpenMPWorksharingDirective(CurrDir) &&
18523 !isOpenMPParallelDirective(CurrDir) &&
18524 !isOpenMPTeamsDirective(CurrDir)) {
18525 DVar = DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getImplicitDSA(D, true);
18526 if (DVar.CKind != OMPC_shared) {
18527 Diag(ELoc, diag::err_omp_required_access)
18528 << getOpenMPClauseName(OMPC_lastprivate)
18529 << getOpenMPClauseName(OMPC_shared);
18530 reportOriginalDsa(*this, DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
, D, DVar);
18531 continue;
18532 }
18533 }
18534
18535 // OpenMP [2.14.3.5, Restrictions, C++, p.1,2]
18536 // A variable of class type (or array thereof) that appears in a
18537 // lastprivate clause requires an accessible, unambiguous default
18538 // constructor for the class type, unless the list item is also specified
18539 // in a firstprivate clause.
18540 // A variable of class type (or array thereof) that appears in a
18541 // lastprivate clause requires an accessible, unambiguous copy assignment
18542 // operator for the class type.
18543 Type = Context.getBaseElementType(Type).getNonReferenceType();
18544 VarDecl *SrcVD = buildVarDecl(*this, ERange.getBegin(),
18545 Type.getUnqualifiedType(), ".lastprivate.src",
18546 D->hasAttrs() ? &D->getAttrs() : nullptr);
18547 DeclRefExpr *PseudoSrcExpr =
18548 buildDeclRefExpr(*this, SrcVD, Type.getUnqualifiedType(), ELoc);
18549 VarDecl *DstVD =
18550 buildVarDecl(*this, ERange.getBegin(), Type, ".lastprivate.dst",
18551 D->hasAttrs() ? &D->getAttrs() : nullptr);
18552 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(*this, DstVD, Type, ELoc);
18553 // For arrays generate assignment operation for single element and replace
18554 // it by the original array element in CodeGen.
18555 ExprResult AssignmentOp = BuildBinOp(/*S=*/nullptr, ELoc, BO_Assign,
18556 PseudoDstExpr, PseudoSrcExpr);
18557 if (AssignmentOp.isInvalid())
18558 continue;
18559 AssignmentOp =
18560 ActOnFinishFullExpr(AssignmentOp.get(), ELoc, /*DiscardedValue*/ false);
18561 if (AssignmentOp.isInvalid())
18562 continue;
18563
18564 DeclRefExpr *Ref = nullptr;
18565 if (!VD && !CurContext->isDependentContext()) {
18566 if (TopDVar.CKind == OMPC_firstprivate) {
18567 Ref = TopDVar.PrivateCopy;
18568 } else {
18569 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/false);
18570 if (!isOpenMPCapturedDecl(D))
18571 ExprCaptures.push_back(Ref->getDecl());
18572 }
18573 if ((TopDVar.CKind == OMPC_firstprivate && !TopDVar.PrivateCopy) ||
18574 (!isOpenMPCapturedDecl(D) &&
18575 Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>())) {
18576 ExprResult RefRes = DefaultLvalueConversion(Ref);
18577 if (!RefRes.isUsable())
18578 continue;
18579 ExprResult PostUpdateRes =
18580 BuildBinOp(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurScope(), ELoc, BO_Assign, SimpleRefExpr,
18581 RefRes.get());
18582 if (!PostUpdateRes.isUsable())
18583 continue;
18584 ExprPostUpdates.push_back(
18585 IgnoredValueConversions(PostUpdateRes.get()).get());
18586 }
18587 }
18588 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->addDSA(D, RefExpr->IgnoreParens(), OMPC_lastprivate, Ref);
18589 Vars.push_back((VD || CurContext->isDependentContext())
18590 ? RefExpr->IgnoreParens()
18591 : Ref);
18592 SrcExprs.push_back(PseudoSrcExpr);
18593 DstExprs.push_back(PseudoDstExpr);
18594 AssignmentOps.push_back(AssignmentOp.get());
18595 }
18596
18597 if (Vars.empty())
18598 return nullptr;
18599
18600 return OMPLastprivateClause::Create(Context, StartLoc, LParenLoc, EndLoc,
18601 Vars, SrcExprs, DstExprs, AssignmentOps,
18602 LPKind, LPKindLoc, ColonLoc,
18603 buildPreInits(Context, ExprCaptures),
18604 buildPostUpdate(*this, ExprPostUpdates));
18605}
18606
18607OMPClause *Sema::ActOnOpenMPSharedClause(ArrayRef<Expr *> VarList,
18608 SourceLocation StartLoc,
18609 SourceLocation LParenLoc,
18610 SourceLocation EndLoc) {
18611 SmallVector<Expr *, 8> Vars;
18612 for (Expr *RefExpr : VarList) {
18613 assert(RefExpr && "NULL expr in OpenMP lastprivate clause.")(static_cast <bool> (RefExpr && "NULL expr in OpenMP lastprivate clause."
) ? void (0) : __assert_fail ("RefExpr && \"NULL expr in OpenMP lastprivate clause.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 18613, __extension__ __PRETTY_FUNCTION__
))
;
18614 SourceLocation ELoc;
18615 SourceRange ERange;
18616 Expr *SimpleRefExpr = RefExpr;
18617 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
18618 if (Res.second) {
18619 // It will be analyzed later.
18620 Vars.push_back(RefExpr);
18621 }
18622 ValueDecl *D = Res.first;
18623 if (!D)
18624 continue;
18625
18626 auto *VD = dyn_cast<VarDecl>(D);
18627 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
18628 // in a Construct]
18629 // Variables with the predetermined data-sharing attributes may not be
18630 // listed in data-sharing attributes clauses, except for the cases
18631 // listed below. For these exceptions only, listing a predetermined
18632 // variable in a data-sharing attribute clause is allowed and overrides
18633 // the variable's predetermined data-sharing attributes.
18634 DSAStackTy::DSAVarData DVar = DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getTopDSA(D, /*FromParent=*/false);
18635 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared &&
18636 DVar.RefExpr) {
18637 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
18638 << getOpenMPClauseName(OMPC_shared);
18639 reportOriginalDsa(*this, DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
, D, DVar);
18640 continue;
18641 }
18642
18643 DeclRefExpr *Ref = nullptr;
18644 if (!VD && isOpenMPCapturedDecl(D) && !CurContext->isDependentContext())
18645 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true);
18646 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->addDSA(D, RefExpr->IgnoreParens(), OMPC_shared, Ref);
18647 Vars.push_back((VD || !Ref || CurContext->isDependentContext())
18648 ? RefExpr->IgnoreParens()
18649 : Ref);
18650 }
18651
18652 if (Vars.empty())
18653 return nullptr;
18654
18655 return OMPSharedClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars);
18656}
18657
18658namespace {
18659class DSARefChecker : public StmtVisitor<DSARefChecker, bool> {
18660 DSAStackTy *Stack;
18661
18662public:
18663 bool VisitDeclRefExpr(DeclRefExpr *E) {
18664 if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
18665 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false);
18666 if (DVar.CKind == OMPC_shared && !DVar.RefExpr)
18667 return false;
18668 if (DVar.CKind != OMPC_unknown)
18669 return true;
18670 DSAStackTy::DSAVarData DVarPrivate = Stack->hasDSA(
18671 VD,
18672 [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
18673 return isOpenMPPrivate(C) && !AppliedToPointee;
18674 },
18675 [](OpenMPDirectiveKind) { return true; },
18676 /*FromParent=*/true);
18677 return DVarPrivate.CKind != OMPC_unknown;
18678 }
18679 return false;
18680 }
18681 bool VisitStmt(Stmt *S) {
18682 for (Stmt *Child : S->children()) {
18683 if (Child && Visit(Child))
18684 return true;
18685 }
18686 return false;
18687 }
18688 explicit DSARefChecker(DSAStackTy *S) : Stack(S) {}
18689};
18690} // namespace
18691
18692namespace {
18693// Transform MemberExpression for specified FieldDecl of current class to
18694// DeclRefExpr to specified OMPCapturedExprDecl.
18695class TransformExprToCaptures : public TreeTransform<TransformExprToCaptures> {
18696 typedef TreeTransform<TransformExprToCaptures> BaseTransform;
18697 ValueDecl *Field = nullptr;
18698 DeclRefExpr *CapturedExpr = nullptr;
18699
18700public:
18701 TransformExprToCaptures(Sema &SemaRef, ValueDecl *FieldDecl)
18702 : BaseTransform(SemaRef), Field(FieldDecl), CapturedExpr(nullptr) {}
18703
18704 ExprResult TransformMemberExpr(MemberExpr *E) {
18705 if (isa<CXXThisExpr>(E->getBase()->IgnoreParenImpCasts()) &&
18706 E->getMemberDecl() == Field) {
18707 CapturedExpr = buildCapture(SemaRef, Field, E, /*WithInit=*/false);
18708 return CapturedExpr;
18709 }
18710 return BaseTransform::TransformMemberExpr(E);
18711 }
18712 DeclRefExpr *getCapturedExpr() { return CapturedExpr; }
18713};
18714} // namespace
18715
18716template <typename T, typename U>
18717static T filterLookupForUDReductionAndMapper(
18718 SmallVectorImpl<U> &Lookups, const llvm::function_ref<T(ValueDecl *)> Gen) {
18719 for (U &Set : Lookups) {
18720 for (auto *D : Set) {
18721 if (T Res = Gen(cast<ValueDecl>(D)))
18722 return Res;
18723 }
18724 }
18725 return T();
18726}
18727
18728static NamedDecl *findAcceptableDecl(Sema &SemaRef, NamedDecl *D) {
18729 assert(!LookupResult::isVisible(SemaRef, D) && "not in slow case")(static_cast <bool> (!LookupResult::isVisible(SemaRef, D
) && "not in slow case") ? void (0) : __assert_fail (
"!LookupResult::isVisible(SemaRef, D) && \"not in slow case\""
, "clang/lib/Sema/SemaOpenMP.cpp", 18729, __extension__ __PRETTY_FUNCTION__
))
;
18730
18731 for (auto *RD : D->redecls()) {
18732 // Don't bother with extra checks if we already know this one isn't visible.
18733 if (RD == D)
18734 continue;
18735
18736 auto ND = cast<NamedDecl>(RD);
18737 if (LookupResult::isVisible(SemaRef, ND))
18738 return ND;
18739 }
18740
18741 return nullptr;
18742}
18743
18744static void
18745argumentDependentLookup(Sema &SemaRef, const DeclarationNameInfo &Id,
18746 SourceLocation Loc, QualType Ty,
18747 SmallVectorImpl<UnresolvedSet<8>> &Lookups) {
18748 // Find all of the associated namespaces and classes based on the
18749 // arguments we have.
18750 Sema::AssociatedNamespaceSet AssociatedNamespaces;
18751 Sema::AssociatedClassSet AssociatedClasses;
18752 OpaqueValueExpr OVE(Loc, Ty, VK_LValue);
18753 SemaRef.FindAssociatedClassesAndNamespaces(Loc, &OVE, AssociatedNamespaces,
18754 AssociatedClasses);
18755
18756 // C++ [basic.lookup.argdep]p3:
18757 // Let X be the lookup set produced by unqualified lookup (3.4.1)
18758 // and let Y be the lookup set produced by argument dependent
18759 // lookup (defined as follows). If X contains [...] then Y is
18760 // empty. Otherwise Y is the set of declarations found in the
18761 // namespaces associated with the argument types as described
18762 // below. The set of declarations found by the lookup of the name
18763 // is the union of X and Y.
18764 //
18765 // Here, we compute Y and add its members to the overloaded
18766 // candidate set.
18767 for (auto *NS : AssociatedNamespaces) {
18768 // When considering an associated namespace, the lookup is the
18769 // same as the lookup performed when the associated namespace is
18770 // used as a qualifier (3.4.3.2) except that:
18771 //
18772 // -- Any using-directives in the associated namespace are
18773 // ignored.
18774 //
18775 // -- Any namespace-scope friend functions declared in
18776 // associated classes are visible within their respective
18777 // namespaces even if they are not visible during an ordinary
18778 // lookup (11.4).
18779 DeclContext::lookup_result R = NS->lookup(Id.getName());
18780 for (auto *D : R) {
18781 auto *Underlying = D;
18782 if (auto *USD = dyn_cast<UsingShadowDecl>(D))
18783 Underlying = USD->getTargetDecl();
18784
18785 if (!isa<OMPDeclareReductionDecl>(Underlying) &&
18786 !isa<OMPDeclareMapperDecl>(Underlying))
18787 continue;
18788
18789 if (!SemaRef.isVisible(D)) {
18790 D = findAcceptableDecl(SemaRef, D);
18791 if (!D)
18792 continue;
18793 if (auto *USD = dyn_cast<UsingShadowDecl>(D))
18794 Underlying = USD->getTargetDecl();
18795 }
18796 Lookups.emplace_back();
18797 Lookups.back().addDecl(Underlying);
18798 }
18799 }
18800}
18801
18802static ExprResult
18803buildDeclareReductionRef(Sema &SemaRef, SourceLocation Loc, SourceRange Range,
18804 Scope *S, CXXScopeSpec &ReductionIdScopeSpec,
18805 const DeclarationNameInfo &ReductionId, QualType Ty,
18806 CXXCastPath &BasePath, Expr *UnresolvedReduction) {
18807 if (ReductionIdScopeSpec.isInvalid())
18808 return ExprError();
18809 SmallVector<UnresolvedSet<8>, 4> Lookups;
18810 if (S) {
18811 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
18812 Lookup.suppressDiagnostics();
18813 while (S && SemaRef.LookupParsedName(Lookup, S, &ReductionIdScopeSpec)) {
18814 NamedDecl *D = Lookup.getRepresentativeDecl();
18815 do {
18816 S = S->getParent();
18817 } while (S && !S->isDeclScope(D));
18818 if (S)
18819 S = S->getParent();
18820 Lookups.emplace_back();
18821 Lookups.back().append(Lookup.begin(), Lookup.end());
18822 Lookup.clear();
18823 }
18824 } else if (auto *ULE =
18825 cast_or_null<UnresolvedLookupExpr>(UnresolvedReduction)) {
18826 Lookups.push_back(UnresolvedSet<8>());
18827 Decl *PrevD = nullptr;
18828 for (NamedDecl *D : ULE->decls()) {
18829 if (D == PrevD)
18830 Lookups.push_back(UnresolvedSet<8>());
18831 else if (auto *DRD = dyn_cast<OMPDeclareReductionDecl>(D))
18832 Lookups.back().addDecl(DRD);
18833 PrevD = D;
18834 }
18835 }
18836 if (SemaRef.CurContext->isDependentContext() || Ty->isDependentType() ||
18837 Ty->isInstantiationDependentType() ||
18838 Ty->containsUnexpandedParameterPack() ||
18839 filterLookupForUDReductionAndMapper<bool>(Lookups, [](ValueDecl *D) {
18840 return !D->isInvalidDecl() &&
18841 (D->getType()->isDependentType() ||
18842 D->getType()->isInstantiationDependentType() ||
18843 D->getType()->containsUnexpandedParameterPack());
18844 })) {
18845 UnresolvedSet<8> ResSet;
18846 for (const UnresolvedSet<8> &Set : Lookups) {
18847 if (Set.empty())
18848 continue;
18849 ResSet.append(Set.begin(), Set.end());
18850 // The last item marks the end of all declarations at the specified scope.
18851 ResSet.addDecl(Set[Set.size() - 1]);
18852 }
18853 return UnresolvedLookupExpr::Create(
18854 SemaRef.Context, /*NamingClass=*/nullptr,
18855 ReductionIdScopeSpec.getWithLocInContext(SemaRef.Context), ReductionId,
18856 /*ADL=*/true, /*Overloaded=*/true, ResSet.begin(), ResSet.end());
18857 }
18858 // Lookup inside the classes.
18859 // C++ [over.match.oper]p3:
18860 // For a unary operator @ with an operand of a type whose
18861 // cv-unqualified version is T1, and for a binary operator @ with
18862 // a left operand of a type whose cv-unqualified version is T1 and
18863 // a right operand of a type whose cv-unqualified version is T2,
18864 // three sets of candidate functions, designated member
18865 // candidates, non-member candidates and built-in candidates, are
18866 // constructed as follows:
18867 // -- If T1 is a complete class type or a class currently being
18868 // defined, the set of member candidates is the result of the
18869 // qualified lookup of T1::operator@ (13.3.1.1.1); otherwise,
18870 // the set of member candidates is empty.
18871 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
18872 Lookup.suppressDiagnostics();
18873 if (const auto *TyRec = Ty->getAs<RecordType>()) {
18874 // Complete the type if it can be completed.
18875 // If the type is neither complete nor being defined, bail out now.
18876 if (SemaRef.isCompleteType(Loc, Ty) || TyRec->isBeingDefined() ||
18877 TyRec->getDecl()->getDefinition()) {
18878 Lookup.clear();
18879 SemaRef.LookupQualifiedName(Lookup, TyRec->getDecl());
18880 if (Lookup.empty()) {
18881 Lookups.emplace_back();
18882 Lookups.back().append(Lookup.begin(), Lookup.end());
18883 }
18884 }
18885 }
18886 // Perform ADL.
18887 if (SemaRef.getLangOpts().CPlusPlus)
18888 argumentDependentLookup(SemaRef, ReductionId, Loc, Ty, Lookups);
18889 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
18890 Lookups, [&SemaRef, Ty](ValueDecl *D) -> ValueDecl * {
18891 if (!D->isInvalidDecl() &&
18892 SemaRef.Context.hasSameType(D->getType(), Ty))
18893 return D;
18894 return nullptr;
18895 }))
18896 return SemaRef.BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(),
18897 VK_LValue, Loc);
18898 if (SemaRef.getLangOpts().CPlusPlus) {
18899 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
18900 Lookups, [&SemaRef, Ty, Loc](ValueDecl *D) -> ValueDecl * {
18901 if (!D->isInvalidDecl() &&
18902 SemaRef.IsDerivedFrom(Loc, Ty, D->getType()) &&
18903 !Ty.isMoreQualifiedThan(D->getType()))
18904 return D;
18905 return nullptr;
18906 })) {
18907 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
18908 /*DetectVirtual=*/false);
18909 if (SemaRef.IsDerivedFrom(Loc, Ty, VD->getType(), Paths)) {
18910 if (!Paths.isAmbiguous(SemaRef.Context.getCanonicalType(
18911 VD->getType().getUnqualifiedType()))) {
18912 if (SemaRef.CheckBaseClassAccess(
18913 Loc, VD->getType(), Ty, Paths.front(),
18914 /*DiagID=*/0) != Sema::AR_inaccessible) {
18915 SemaRef.BuildBasePathArray(Paths, BasePath);
18916 return SemaRef.BuildDeclRefExpr(
18917 VD, VD->getType().getNonReferenceType(), VK_LValue, Loc);
18918 }
18919 }
18920 }
18921 }
18922 }
18923 if (ReductionIdScopeSpec.isSet()) {
18924 SemaRef.Diag(Loc, diag::err_omp_not_resolved_reduction_identifier)
18925 << Ty << Range;
18926 return ExprError();
18927 }
18928 return ExprEmpty();
18929}
18930
18931namespace {
18932/// Data for the reduction-based clauses.
18933struct ReductionData {
18934 /// List of original reduction items.
18935 SmallVector<Expr *, 8> Vars;
18936 /// List of private copies of the reduction items.
18937 SmallVector<Expr *, 8> Privates;
18938 /// LHS expressions for the reduction_op expressions.
18939 SmallVector<Expr *, 8> LHSs;
18940 /// RHS expressions for the reduction_op expressions.
18941 SmallVector<Expr *, 8> RHSs;
18942 /// Reduction operation expression.
18943 SmallVector<Expr *, 8> ReductionOps;
18944 /// inscan copy operation expressions.
18945 SmallVector<Expr *, 8> InscanCopyOps;
18946 /// inscan copy temp array expressions for prefix sums.
18947 SmallVector<Expr *, 8> InscanCopyArrayTemps;
18948 /// inscan copy temp array element expressions for prefix sums.
18949 SmallVector<Expr *, 8> InscanCopyArrayElems;
18950 /// Taskgroup descriptors for the corresponding reduction items in
18951 /// in_reduction clauses.
18952 SmallVector<Expr *, 8> TaskgroupDescriptors;
18953 /// List of captures for clause.
18954 SmallVector<Decl *, 4> ExprCaptures;
18955 /// List of postupdate expressions.
18956 SmallVector<Expr *, 4> ExprPostUpdates;
18957 /// Reduction modifier.
18958 unsigned RedModifier = 0;
18959 ReductionData() = delete;
18960 /// Reserves required memory for the reduction data.
18961 ReductionData(unsigned Size, unsigned Modifier = 0) : RedModifier(Modifier) {
18962 Vars.reserve(Size);
18963 Privates.reserve(Size);
18964 LHSs.reserve(Size);
18965 RHSs.reserve(Size);
18966 ReductionOps.reserve(Size);
18967 if (RedModifier == OMPC_REDUCTION_inscan) {
18968 InscanCopyOps.reserve(Size);
18969 InscanCopyArrayTemps.reserve(Size);
18970 InscanCopyArrayElems.reserve(Size);
18971 }
18972 TaskgroupDescriptors.reserve(Size);
18973 ExprCaptures.reserve(Size);
18974 ExprPostUpdates.reserve(Size);
18975 }
18976 /// Stores reduction item and reduction operation only (required for dependent
18977 /// reduction item).
18978 void push(Expr *Item, Expr *ReductionOp) {
18979 Vars.emplace_back(Item);
18980 Privates.emplace_back(nullptr);
18981 LHSs.emplace_back(nullptr);
18982 RHSs.emplace_back(nullptr);
18983 ReductionOps.emplace_back(ReductionOp);
18984 TaskgroupDescriptors.emplace_back(nullptr);
18985 if (RedModifier == OMPC_REDUCTION_inscan) {
18986 InscanCopyOps.push_back(nullptr);
18987 InscanCopyArrayTemps.push_back(nullptr);
18988 InscanCopyArrayElems.push_back(nullptr);
18989 }
18990 }
18991 /// Stores reduction data.
18992 void push(Expr *Item, Expr *Private, Expr *LHS, Expr *RHS, Expr *ReductionOp,
18993 Expr *TaskgroupDescriptor, Expr *CopyOp, Expr *CopyArrayTemp,
18994 Expr *CopyArrayElem) {
18995 Vars.emplace_back(Item);
18996 Privates.emplace_back(Private);
18997 LHSs.emplace_back(LHS);
18998 RHSs.emplace_back(RHS);
18999 ReductionOps.emplace_back(ReductionOp);
19000 TaskgroupDescriptors.emplace_back(TaskgroupDescriptor);
19001 if (RedModifier == OMPC_REDUCTION_inscan) {
19002 InscanCopyOps.push_back(CopyOp);
19003 InscanCopyArrayTemps.push_back(CopyArrayTemp);
19004 InscanCopyArrayElems.push_back(CopyArrayElem);
19005 } else {
19006 assert(CopyOp == nullptr && CopyArrayTemp == nullptr &&(static_cast <bool> (CopyOp == nullptr && CopyArrayTemp
== nullptr && CopyArrayElem == nullptr && "Copy operation must be used for inscan reductions only."
) ? void (0) : __assert_fail ("CopyOp == nullptr && CopyArrayTemp == nullptr && CopyArrayElem == nullptr && \"Copy operation must be used for inscan reductions only.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 19008, __extension__ __PRETTY_FUNCTION__
))
19007 CopyArrayElem == nullptr &&(static_cast <bool> (CopyOp == nullptr && CopyArrayTemp
== nullptr && CopyArrayElem == nullptr && "Copy operation must be used for inscan reductions only."
) ? void (0) : __assert_fail ("CopyOp == nullptr && CopyArrayTemp == nullptr && CopyArrayElem == nullptr && \"Copy operation must be used for inscan reductions only.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 19008, __extension__ __PRETTY_FUNCTION__
))
19008 "Copy operation must be used for inscan reductions only.")(static_cast <bool> (CopyOp == nullptr && CopyArrayTemp
== nullptr && CopyArrayElem == nullptr && "Copy operation must be used for inscan reductions only."
) ? void (0) : __assert_fail ("CopyOp == nullptr && CopyArrayTemp == nullptr && CopyArrayElem == nullptr && \"Copy operation must be used for inscan reductions only.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 19008, __extension__ __PRETTY_FUNCTION__
))
;
19009 }
19010 }
19011};
19012} // namespace
19013
19014static bool checkOMPArraySectionConstantForReduction(
19015 ASTContext &Context, const OMPArraySectionExpr *OASE, bool &SingleElement,
19016 SmallVectorImpl<llvm::APSInt> &ArraySizes) {
19017 const Expr *Length = OASE->getLength();
19018 if (Length == nullptr) {
19019 // For array sections of the form [1:] or [:], we would need to analyze
19020 // the lower bound...
19021 if (OASE->getColonLocFirst().isValid())
19022 return false;
19023
19024 // This is an array subscript which has implicit length 1!
19025 SingleElement = true;
19026 ArraySizes.push_back(llvm::APSInt::get(1));
19027 } else {
19028 Expr::EvalResult Result;
19029 if (!Length->EvaluateAsInt(Result, Context))
19030 return false;
19031
19032 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
19033 SingleElement = (ConstantLengthValue.getSExtValue() == 1);
19034 ArraySizes.push_back(ConstantLengthValue);
19035 }
19036
19037 // Get the base of this array section and walk up from there.
19038 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
19039
19040 // We require length = 1 for all array sections except the right-most to
19041 // guarantee that the memory region is contiguous and has no holes in it.
19042 while (const auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base)) {
19043 Length = TempOASE->getLength();
19044 if (Length == nullptr) {
19045 // For array sections of the form [1:] or [:], we would need to analyze
19046 // the lower bound...
19047 if (OASE->getColonLocFirst().isValid())
19048 return false;
19049
19050 // This is an array subscript which has implicit length 1!
19051 ArraySizes.push_back(llvm::APSInt::get(1));
19052 } else {
19053 Expr::EvalResult Result;
19054 if (!Length->EvaluateAsInt(Result, Context))
19055 return false;
19056
19057 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
19058 if (ConstantLengthValue.getSExtValue() != 1)
19059 return false;
19060
19061 ArraySizes.push_back(ConstantLengthValue);
19062 }
19063 Base = TempOASE->getBase()->IgnoreParenImpCasts();
19064 }
19065
19066 // If we have a single element, we don't need to add the implicit lengths.
19067 if (!SingleElement) {
19068 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) {
19069 // Has implicit length 1!
19070 ArraySizes.push_back(llvm::APSInt::get(1));
19071 Base = TempASE->getBase()->IgnoreParenImpCasts();
19072 }
19073 }
19074
19075 // This array section can be privatized as a single value or as a constant
19076 // sized array.
19077 return true;
19078}
19079
19080static BinaryOperatorKind
19081getRelatedCompoundReductionOp(BinaryOperatorKind BOK) {
19082 if (BOK == BO_Add)
19083 return BO_AddAssign;
19084 if (BOK == BO_Mul)
19085 return BO_MulAssign;
19086 if (BOK == BO_And)
19087 return BO_AndAssign;
19088 if (BOK == BO_Or)
19089 return BO_OrAssign;
19090 if (BOK == BO_Xor)
19091 return BO_XorAssign;
19092 return BOK;
19093}
19094
19095static bool actOnOMPReductionKindClause(
19096 Sema &S, DSAStackTy *Stack, OpenMPClauseKind ClauseKind,
19097 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
19098 SourceLocation ColonLoc, SourceLocation EndLoc,
19099 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
19100 ArrayRef<Expr *> UnresolvedReductions, ReductionData &RD) {
19101 DeclarationName DN = ReductionId.getName();
19102 OverloadedOperatorKind OOK = DN.getCXXOverloadedOperator();
19103 BinaryOperatorKind BOK = BO_Comma;
19104
19105 ASTContext &Context = S.Context;
19106 // OpenMP [2.14.3.6, reduction clause]
19107 // C
19108 // reduction-identifier is either an identifier or one of the following
19109 // operators: +, -, *, &, |, ^, && and ||
19110 // C++
19111 // reduction-identifier is either an id-expression or one of the following
19112 // operators: +, -, *, &, |, ^, && and ||
19113 switch (OOK) {
19114 case OO_Plus:
19115 case OO_Minus:
19116 BOK = BO_Add;
19117 break;
19118 case OO_Star:
19119 BOK = BO_Mul;
19120 break;
19121 case OO_Amp:
19122 BOK = BO_And;
19123 break;
19124 case OO_Pipe:
19125 BOK = BO_Or;
19126 break;
19127 case OO_Caret:
19128 BOK = BO_Xor;
19129 break;
19130 case OO_AmpAmp:
19131 BOK = BO_LAnd;
19132 break;
19133 case OO_PipePipe:
19134 BOK = BO_LOr;
19135 break;
19136 case OO_New:
19137 case OO_Delete:
19138 case OO_Array_New:
19139 case OO_Array_Delete:
19140 case OO_Slash:
19141 case OO_Percent:
19142 case OO_Tilde:
19143 case OO_Exclaim:
19144 case OO_Equal:
19145 case OO_Less:
19146 case OO_Greater:
19147 case OO_LessEqual:
19148 case OO_GreaterEqual:
19149 case OO_PlusEqual:
19150 case OO_MinusEqual:
19151 case OO_StarEqual:
19152 case OO_SlashEqual:
19153 case OO_PercentEqual:
19154 case OO_CaretEqual:
19155 case OO_AmpEqual:
19156 case OO_PipeEqual:
19157 case OO_LessLess:
19158 case OO_GreaterGreater:
19159 case OO_LessLessEqual:
19160 case OO_GreaterGreaterEqual:
19161 case OO_EqualEqual:
19162 case OO_ExclaimEqual:
19163 case OO_Spaceship:
19164 case OO_PlusPlus:
19165 case OO_MinusMinus:
19166 case OO_Comma:
19167 case OO_ArrowStar:
19168 case OO_Arrow:
19169 case OO_Call:
19170 case OO_Subscript:
19171 case OO_Conditional:
19172 case OO_Coawait:
19173 case NUM_OVERLOADED_OPERATORS:
19174 llvm_unreachable("Unexpected reduction identifier")::llvm::llvm_unreachable_internal("Unexpected reduction identifier"
, "clang/lib/Sema/SemaOpenMP.cpp", 19174)
;
19175 case OO_None:
19176 if (IdentifierInfo *II = DN.getAsIdentifierInfo()) {
19177 if (II->isStr("max"))
19178 BOK = BO_GT;
19179 else if (II->isStr("min"))
19180 BOK = BO_LT;
19181 }
19182 break;
19183 }
19184 SourceRange ReductionIdRange;
19185 if (ReductionIdScopeSpec.isValid())
19186 ReductionIdRange.setBegin(ReductionIdScopeSpec.getBeginLoc());
19187 else
19188 ReductionIdRange.setBegin(ReductionId.getBeginLoc());
19189 ReductionIdRange.setEnd(ReductionId.getEndLoc());
19190
19191 auto IR = UnresolvedReductions.begin(), ER = UnresolvedReductions.end();
19192 bool FirstIter = true;
19193 for (Expr *RefExpr : VarList) {
19194 assert(RefExpr && "nullptr expr in OpenMP reduction clause.")(static_cast <bool> (RefExpr && "nullptr expr in OpenMP reduction clause."
) ? void (0) : __assert_fail ("RefExpr && \"nullptr expr in OpenMP reduction clause.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 19194, __extension__ __PRETTY_FUNCTION__
))
;
19195 // OpenMP [2.1, C/C++]
19196 // A list item is a variable or array section, subject to the restrictions
19197 // specified in Section 2.4 on page 42 and in each of the sections
19198 // describing clauses and directives for which a list appears.
19199 // OpenMP [2.14.3.3, Restrictions, p.1]
19200 // A variable that is part of another variable (as an array or
19201 // structure element) cannot appear in a private clause.
19202 if (!FirstIter && IR != ER)
19203 ++IR;
19204 FirstIter = false;
19205 SourceLocation ELoc;
19206 SourceRange ERange;
19207 Expr *SimpleRefExpr = RefExpr;
19208 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
19209 /*AllowArraySection=*/true);
19210 if (Res.second) {
19211 // Try to find 'declare reduction' corresponding construct before using
19212 // builtin/overloaded operators.
19213 QualType Type = Context.DependentTy;
19214 CXXCastPath BasePath;
19215 ExprResult DeclareReductionRef = buildDeclareReductionRef(
19216 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
19217 ReductionId, Type, BasePath, IR == ER ? nullptr : *IR);
19218 Expr *ReductionOp = nullptr;
19219 if (S.CurContext->isDependentContext() &&
19220 (DeclareReductionRef.isUnset() ||
19221 isa<UnresolvedLookupExpr>(DeclareReductionRef.get())))
19222 ReductionOp = DeclareReductionRef.get();
19223 // It will be analyzed later.
19224 RD.push(RefExpr, ReductionOp);
19225 }
19226 ValueDecl *D = Res.first;
19227 if (!D)
19228 continue;
19229
19230 Expr *TaskgroupDescriptor = nullptr;
19231 QualType Type;
19232 auto *ASE = dyn_cast<ArraySubscriptExpr>(RefExpr->IgnoreParens());
19233 auto *OASE = dyn_cast<OMPArraySectionExpr>(RefExpr->IgnoreParens());
19234 if (ASE) {
19235 Type = ASE->getType().getNonReferenceType();
19236 } else if (OASE) {
19237 QualType BaseType =
19238 OMPArraySectionExpr::getBaseOriginalType(OASE->getBase());
19239 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
19240 Type = ATy->getElementType();
19241 else
19242 Type = BaseType->getPointeeType();
19243 Type = Type.getNonReferenceType();
19244 } else {
19245 Type = Context.getBaseElementType(D->getType().getNonReferenceType());
19246 }
19247 auto *VD = dyn_cast<VarDecl>(D);
19248
19249 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
19250 // A variable that appears in a private clause must not have an incomplete
19251 // type or a reference type.
19252 if (S.RequireCompleteType(ELoc, D->getType(),
19253 diag::err_omp_reduction_incomplete_type))
19254 continue;
19255 // OpenMP [2.14.3.6, reduction clause, Restrictions]
19256 // A list item that appears in a reduction clause must not be
19257 // const-qualified.
19258 if (rejectConstNotMutableType(S, D, Type, ClauseKind, ELoc,
19259 /*AcceptIfMutable*/ false, ASE || OASE))
19260 continue;
19261
19262 OpenMPDirectiveKind CurrDir = Stack->getCurrentDirective();
19263 // OpenMP [2.9.3.6, Restrictions, C/C++, p.4]
19264 // If a list-item is a reference type then it must bind to the same object
19265 // for all threads of the team.
19266 if (!ASE && !OASE) {
19267 if (VD) {
19268 VarDecl *VDDef = VD->getDefinition();
19269 if (VD->getType()->isReferenceType() && VDDef && VDDef->hasInit()) {
19270 DSARefChecker Check(Stack);
19271 if (Check.Visit(VDDef->getInit())) {
19272 S.Diag(ELoc, diag::err_omp_reduction_ref_type_arg)
19273 << getOpenMPClauseName(ClauseKind) << ERange;
19274 S.Diag(VDDef->getLocation(), diag::note_defined_here) << VDDef;
19275 continue;
19276 }
19277 }
19278 }
19279
19280 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
19281 // in a Construct]
19282 // Variables with the predetermined data-sharing attributes may not be
19283 // listed in data-sharing attributes clauses, except for the cases
19284 // listed below. For these exceptions only, listing a predetermined
19285 // variable in a data-sharing attribute clause is allowed and overrides
19286 // the variable's predetermined data-sharing attributes.
19287 // OpenMP [2.14.3.6, Restrictions, p.3]
19288 // Any number of reduction clauses can be specified on the directive,
19289 // but a list item can appear only once in the reduction clauses for that
19290 // directive.
19291 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
19292 if (DVar.CKind == OMPC_reduction) {
19293 S.Diag(ELoc, diag::err_omp_once_referenced)
19294 << getOpenMPClauseName(ClauseKind);
19295 if (DVar.RefExpr)
19296 S.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_referenced);
19297 continue;
19298 }
19299 if (DVar.CKind != OMPC_unknown) {
19300 S.Diag(ELoc, diag::err_omp_wrong_dsa)
19301 << getOpenMPClauseName(DVar.CKind)
19302 << getOpenMPClauseName(OMPC_reduction);
19303 reportOriginalDsa(S, Stack, D, DVar);
19304 continue;
19305 }
19306
19307 // OpenMP [2.14.3.6, Restrictions, p.1]
19308 // A list item that appears in a reduction clause of a worksharing
19309 // construct must be shared in the parallel regions to which any of the
19310 // worksharing regions arising from the worksharing construct bind.
19311 if (isOpenMPWorksharingDirective(CurrDir) &&
19312 !isOpenMPParallelDirective(CurrDir) &&
19313 !isOpenMPTeamsDirective(CurrDir)) {
19314 DVar = Stack->getImplicitDSA(D, true);
19315 if (DVar.CKind != OMPC_shared) {
19316 S.Diag(ELoc, diag::err_omp_required_access)
19317 << getOpenMPClauseName(OMPC_reduction)
19318 << getOpenMPClauseName(OMPC_shared);
19319 reportOriginalDsa(S, Stack, D, DVar);
19320 continue;
19321 }
19322 }
19323 } else {
19324 // Threadprivates cannot be shared between threads, so dignose if the base
19325 // is a threadprivate variable.
19326 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
19327 if (DVar.CKind == OMPC_threadprivate) {
19328 S.Diag(ELoc, diag::err_omp_wrong_dsa)
19329 << getOpenMPClauseName(DVar.CKind)
19330 << getOpenMPClauseName(OMPC_reduction);
19331 reportOriginalDsa(S, Stack, D, DVar);
19332 continue;
19333 }
19334 }
19335
19336 // Try to find 'declare reduction' corresponding construct before using
19337 // builtin/overloaded operators.
19338 CXXCastPath BasePath;
19339 ExprResult DeclareReductionRef = buildDeclareReductionRef(
19340 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
19341 ReductionId, Type, BasePath, IR == ER ? nullptr : *IR);
19342 if (DeclareReductionRef.isInvalid())
19343 continue;
19344 if (S.CurContext->isDependentContext() &&
19345 (DeclareReductionRef.isUnset() ||
19346 isa<UnresolvedLookupExpr>(DeclareReductionRef.get()))) {
19347 RD.push(RefExpr, DeclareReductionRef.get());
19348 continue;
19349 }
19350 if (BOK == BO_Comma && DeclareReductionRef.isUnset()) {
19351 // Not allowed reduction identifier is found.
19352 S.Diag(ReductionId.getBeginLoc(),
19353 diag::err_omp_unknown_reduction_identifier)
19354 << Type << ReductionIdRange;
19355 continue;
19356 }
19357
19358 // OpenMP [2.14.3.6, reduction clause, Restrictions]
19359 // The type of a list item that appears in a reduction clause must be valid
19360 // for the reduction-identifier. For a max or min reduction in C, the type
19361 // of the list item must be an allowed arithmetic data type: char, int,
19362 // float, double, or _Bool, possibly modified with long, short, signed, or
19363 // unsigned. For a max or min reduction in C++, the type of the list item
19364 // must be an allowed arithmetic data type: char, wchar_t, int, float,
19365 // double, or bool, possibly modified with long, short, signed, or unsigned.
19366 if (DeclareReductionRef.isUnset()) {
19367 if ((BOK == BO_GT || BOK == BO_LT) &&
19368 !(Type->isScalarType() ||
19369 (S.getLangOpts().CPlusPlus && Type->isArithmeticType()))) {
19370 S.Diag(ELoc, diag::err_omp_clause_not_arithmetic_type_arg)
19371 << getOpenMPClauseName(ClauseKind) << S.getLangOpts().CPlusPlus;
19372 if (!ASE && !OASE) {
19373 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
19374 VarDecl::DeclarationOnly;
19375 S.Diag(D->getLocation(),
19376 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19377 << D;
19378 }
19379 continue;
19380 }
19381 if ((BOK == BO_OrAssign || BOK == BO_AndAssign || BOK == BO_XorAssign) &&
19382 !S.getLangOpts().CPlusPlus && Type->isFloatingType()) {
19383 S.Diag(ELoc, diag::err_omp_clause_floating_type_arg)
19384 << getOpenMPClauseName(ClauseKind);
19385 if (!ASE && !OASE) {
19386 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
19387 VarDecl::DeclarationOnly;
19388 S.Diag(D->getLocation(),
19389 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19390 << D;
19391 }
19392 continue;
19393 }
19394 }
19395
19396 Type = Type.getNonLValueExprType(Context).getUnqualifiedType();
19397 VarDecl *LHSVD = buildVarDecl(S, ELoc, Type, ".reduction.lhs",
19398 D->hasAttrs() ? &D->getAttrs() : nullptr);
19399 VarDecl *RHSVD = buildVarDecl(S, ELoc, Type, D->getName(),
19400 D->hasAttrs() ? &D->getAttrs() : nullptr);
19401 QualType PrivateTy = Type;
19402
19403 // Try if we can determine constant lengths for all array sections and avoid
19404 // the VLA.
19405 bool ConstantLengthOASE = false;
19406 if (OASE) {
19407 bool SingleElement;
19408 llvm::SmallVector<llvm::APSInt, 4> ArraySizes;
19409 ConstantLengthOASE = checkOMPArraySectionConstantForReduction(
19410 Context, OASE, SingleElement, ArraySizes);
19411
19412 // If we don't have a single element, we must emit a constant array type.
19413 if (ConstantLengthOASE && !SingleElement) {
19414 for (llvm::APSInt &Size : ArraySizes)
19415 PrivateTy = Context.getConstantArrayType(PrivateTy, Size, nullptr,
19416 ArrayType::Normal,
19417 /*IndexTypeQuals=*/0);
19418 }
19419 }
19420
19421 if ((OASE && !ConstantLengthOASE) ||
19422 (!OASE && !ASE &&
19423 D->getType().getNonReferenceType()->isVariablyModifiedType())) {
19424 if (!Context.getTargetInfo().isVLASupported()) {
19425 if (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective())) {
19426 S.Diag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
19427 S.Diag(ELoc, diag::note_vla_unsupported);
19428 continue;
19429 } else {
19430 S.targetDiag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
19431 S.targetDiag(ELoc, diag::note_vla_unsupported);
19432 }
19433 }
19434 // For arrays/array sections only:
19435 // Create pseudo array type for private copy. The size for this array will
19436 // be generated during codegen.
19437 // For array subscripts or single variables Private Ty is the same as Type
19438 // (type of the variable or single array element).
19439 PrivateTy = Context.getVariableArrayType(
19440 Type,
19441 new (Context)
19442 OpaqueValueExpr(ELoc, Context.getSizeType(), VK_PRValue),
19443 ArrayType::Normal, /*IndexTypeQuals=*/0, SourceRange());
19444 } else if (!ASE && !OASE &&
19445 Context.getAsArrayType(D->getType().getNonReferenceType())) {
19446 PrivateTy = D->getType().getNonReferenceType();
19447 }
19448 // Private copy.
19449 VarDecl *PrivateVD =
19450 buildVarDecl(S, ELoc, PrivateTy, D->getName(),
19451 D->hasAttrs() ? &D->getAttrs() : nullptr,
19452 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
19453 // Add initializer for private variable.
19454 Expr *Init = nullptr;
19455 DeclRefExpr *LHSDRE = buildDeclRefExpr(S, LHSVD, Type, ELoc);
19456 DeclRefExpr *RHSDRE = buildDeclRefExpr(S, RHSVD, Type, ELoc);
19457 if (DeclareReductionRef.isUsable()) {
19458 auto *DRDRef = DeclareReductionRef.getAs<DeclRefExpr>();
19459 auto *DRD = cast<OMPDeclareReductionDecl>(DRDRef->getDecl());
19460 if (DRD->getInitializer()) {
19461 Init = DRDRef;
19462 RHSVD->setInit(DRDRef);
19463 RHSVD->setInitStyle(VarDecl::CallInit);
19464 }
19465 } else {
19466 switch (BOK) {
19467 case BO_Add:
19468 case BO_Xor:
19469 case BO_Or:
19470 case BO_LOr:
19471 // '+', '-', '^', '|', '||' reduction ops - initializer is '0'.
19472 if (Type->isScalarType() || Type->isAnyComplexType())
19473 Init = S.ActOnIntegerConstant(ELoc, /*Val=*/0).get();
19474 break;
19475 case BO_Mul:
19476 case BO_LAnd:
19477 if (Type->isScalarType() || Type->isAnyComplexType()) {
19478 // '*' and '&&' reduction ops - initializer is '1'.
19479 Init = S.ActOnIntegerConstant(ELoc, /*Val=*/1).get();
19480 }
19481 break;
19482 case BO_And: {
19483 // '&' reduction op - initializer is '~0'.
19484 QualType OrigType = Type;
19485 if (auto *ComplexTy = OrigType->getAs<ComplexType>())
19486 Type = ComplexTy->getElementType();
19487 if (Type->isRealFloatingType()) {
19488 llvm::APFloat InitValue = llvm::APFloat::getAllOnesValue(
19489 Context.getFloatTypeSemantics(Type));
19490 Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
19491 Type, ELoc);
19492 } else if (Type->isScalarType()) {
19493 uint64_t Size = Context.getTypeSize(Type);
19494 QualType IntTy = Context.getIntTypeForBitwidth(Size, /*Signed=*/0);
19495 llvm::APInt InitValue = llvm::APInt::getAllOnes(Size);
19496 Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
19497 }
19498 if (Init && OrigType->isAnyComplexType()) {
19499 // Init = 0xFFFF + 0xFFFFi;
19500 auto *Im = new (Context) ImaginaryLiteral(Init, OrigType);
19501 Init = S.CreateBuiltinBinOp(ELoc, BO_Add, Init, Im).get();
19502 }
19503 Type = OrigType;
19504 break;
19505 }
19506 case BO_LT:
19507 case BO_GT: {
19508 // 'min' reduction op - initializer is 'Largest representable number in
19509 // the reduction list item type'.
19510 // 'max' reduction op - initializer is 'Least representable number in
19511 // the reduction list item type'.
19512 if (Type->isIntegerType() || Type->isPointerType()) {
19513 bool IsSigned = Type->hasSignedIntegerRepresentation();
19514 uint64_t Size = Context.getTypeSize(Type);
19515 QualType IntTy =
19516 Context.getIntTypeForBitwidth(Size, /*Signed=*/IsSigned);
19517 llvm::APInt InitValue =
19518 (BOK != BO_LT) ? IsSigned ? llvm::APInt::getSignedMinValue(Size)
19519 : llvm::APInt::getMinValue(Size)
19520 : IsSigned ? llvm::APInt::getSignedMaxValue(Size)
19521 : llvm::APInt::getMaxValue(Size);
19522 Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
19523 if (Type->isPointerType()) {
19524 // Cast to pointer type.
19525 ExprResult CastExpr = S.BuildCStyleCastExpr(
19526 ELoc, Context.getTrivialTypeSourceInfo(Type, ELoc), ELoc, Init);
19527 if (CastExpr.isInvalid())
19528 continue;
19529 Init = CastExpr.get();
19530 }
19531 } else if (Type->isRealFloatingType()) {
19532 llvm::APFloat InitValue = llvm::APFloat::getLargest(
19533 Context.getFloatTypeSemantics(Type), BOK != BO_LT);
19534 Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
19535 Type, ELoc);
19536 }
19537 break;
19538 }
19539 case BO_PtrMemD:
19540 case BO_PtrMemI:
19541 case BO_MulAssign:
19542 case BO_Div:
19543 case BO_Rem:
19544 case BO_Sub:
19545 case BO_Shl:
19546 case BO_Shr:
19547 case BO_LE:
19548 case BO_GE:
19549 case BO_EQ:
19550 case BO_NE:
19551 case BO_Cmp:
19552 case BO_AndAssign:
19553 case BO_XorAssign:
19554 case BO_OrAssign:
19555 case BO_Assign:
19556 case BO_AddAssign:
19557 case BO_SubAssign:
19558 case BO_DivAssign:
19559 case BO_RemAssign:
19560 case BO_ShlAssign:
19561 case BO_ShrAssign:
19562 case BO_Comma:
19563 llvm_unreachable("Unexpected reduction operation")::llvm::llvm_unreachable_internal("Unexpected reduction operation"
, "clang/lib/Sema/SemaOpenMP.cpp", 19563)
;
19564 }
19565 }
19566 if (Init && DeclareReductionRef.isUnset()) {
19567 S.AddInitializerToDecl(RHSVD, Init, /*DirectInit=*/false);
19568 // Store initializer for single element in private copy. Will be used
19569 // during codegen.
19570 PrivateVD->setInit(RHSVD->getInit());
19571 PrivateVD->setInitStyle(RHSVD->getInitStyle());
19572 } else if (!Init) {
19573 S.ActOnUninitializedDecl(RHSVD);
19574 // Store initializer for single element in private copy. Will be used
19575 // during codegen.
19576 PrivateVD->setInit(RHSVD->getInit());
19577 PrivateVD->setInitStyle(RHSVD->getInitStyle());
19578 }
19579 if (RHSVD->isInvalidDecl())
19580 continue;
19581 if (!RHSVD->hasInit() && DeclareReductionRef.isUnset()) {
19582 S.Diag(ELoc, diag::err_omp_reduction_id_not_compatible)
19583 << Type << ReductionIdRange;
19584 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
19585 VarDecl::DeclarationOnly;
19586 S.Diag(D->getLocation(),
19587 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19588 << D;
19589 continue;
19590 }
19591 DeclRefExpr *PrivateDRE = buildDeclRefExpr(S, PrivateVD, PrivateTy, ELoc);
19592 ExprResult ReductionOp;
19593 if (DeclareReductionRef.isUsable()) {
19594 QualType RedTy = DeclareReductionRef.get()->getType();
19595 QualType PtrRedTy = Context.getPointerType(RedTy);
19596 ExprResult LHS = S.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, LHSDRE);
19597 ExprResult RHS = S.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, RHSDRE);
19598 if (!BasePath.empty()) {
19599 LHS = S.DefaultLvalueConversion(LHS.get());
19600 RHS = S.DefaultLvalueConversion(RHS.get());
19601 LHS = ImplicitCastExpr::Create(
19602 Context, PtrRedTy, CK_UncheckedDerivedToBase, LHS.get(), &BasePath,
19603 LHS.get()->getValueKind(), FPOptionsOverride());
19604 RHS = ImplicitCastExpr::Create(
19605 Context, PtrRedTy, CK_UncheckedDerivedToBase, RHS.get(), &BasePath,
19606 RHS.get()->getValueKind(), FPOptionsOverride());
19607 }
19608 FunctionProtoType::ExtProtoInfo EPI;
19609 QualType Params[] = {PtrRedTy, PtrRedTy};
19610 QualType FnTy = Context.getFunctionType(Context.VoidTy, Params, EPI);
19611 auto *OVE = new (Context) OpaqueValueExpr(
19612 ELoc, Context.getPointerType(FnTy), VK_PRValue, OK_Ordinary,
19613 S.DefaultLvalueConversion(DeclareReductionRef.get()).get());
19614 Expr *Args[] = {LHS.get(), RHS.get()};
19615 ReductionOp =
19616 CallExpr::Create(Context, OVE, Args, Context.VoidTy, VK_PRValue, ELoc,
19617 S.CurFPFeatureOverrides());
19618 } else {
19619 BinaryOperatorKind CombBOK = getRelatedCompoundReductionOp(BOK);
19620 if (Type->isRecordType() && CombBOK != BOK) {
19621 Sema::TentativeAnalysisScope Trap(S);
19622 ReductionOp =
19623 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
19624 CombBOK, LHSDRE, RHSDRE);
19625 }
19626 if (!ReductionOp.isUsable()) {
19627 ReductionOp =
19628 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(), BOK,
19629 LHSDRE, RHSDRE);
19630 if (ReductionOp.isUsable()) {
19631 if (BOK != BO_LT && BOK != BO_GT) {
19632 ReductionOp =
19633 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
19634 BO_Assign, LHSDRE, ReductionOp.get());
19635 } else {
19636 auto *ConditionalOp = new (Context)
19637 ConditionalOperator(ReductionOp.get(), ELoc, LHSDRE, ELoc,
19638 RHSDRE, Type, VK_LValue, OK_Ordinary);
19639 ReductionOp =
19640 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
19641 BO_Assign, LHSDRE, ConditionalOp);
19642 }
19643 }
19644 }
19645 if (ReductionOp.isUsable())
19646 ReductionOp = S.ActOnFinishFullExpr(ReductionOp.get(),
19647 /*DiscardedValue*/ false);
19648 if (!ReductionOp.isUsable())
19649 continue;
19650 }
19651
19652 // Add copy operations for inscan reductions.
19653 // LHS = RHS;
19654 ExprResult CopyOpRes, TempArrayRes, TempArrayElem;
19655 if (ClauseKind == OMPC_reduction &&
19656 RD.RedModifier == OMPC_REDUCTION_inscan) {
19657 ExprResult RHS = S.DefaultLvalueConversion(RHSDRE);
19658 CopyOpRes = S.BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, LHSDRE,
19659 RHS.get());
19660 if (!CopyOpRes.isUsable())
19661 continue;
19662 CopyOpRes =
19663 S.ActOnFinishFullExpr(CopyOpRes.get(), /*DiscardedValue=*/true);
19664 if (!CopyOpRes.isUsable())
19665 continue;
19666 // For simd directive and simd-based directives in simd mode no need to
19667 // construct temp array, need just a single temp element.
19668 if (Stack->getCurrentDirective() == OMPD_simd ||
19669 (S.getLangOpts().OpenMPSimd &&
19670 isOpenMPSimdDirective(Stack->getCurrentDirective()))) {
19671 VarDecl *TempArrayVD =
19672 buildVarDecl(S, ELoc, PrivateTy, D->getName(),
19673 D->hasAttrs() ? &D->getAttrs() : nullptr);
19674 // Add a constructor to the temp decl.
19675 S.ActOnUninitializedDecl(TempArrayVD);
19676 TempArrayRes = buildDeclRefExpr(S, TempArrayVD, PrivateTy, ELoc);
19677 } else {
19678 // Build temp array for prefix sum.
19679 auto *Dim = new (S.Context)
19680 OpaqueValueExpr(ELoc, S.Context.getSizeType(), VK_PRValue);
19681 QualType ArrayTy =
19682 S.Context.getVariableArrayType(PrivateTy, Dim, ArrayType::Normal,
19683 /*IndexTypeQuals=*/0, {ELoc, ELoc});
19684 VarDecl *TempArrayVD =
19685 buildVarDecl(S, ELoc, ArrayTy, D->getName(),
19686 D->hasAttrs() ? &D->getAttrs() : nullptr);
19687 // Add a constructor to the temp decl.
19688 S.ActOnUninitializedDecl(TempArrayVD);
19689 TempArrayRes = buildDeclRefExpr(S, TempArrayVD, ArrayTy, ELoc);
19690 TempArrayElem =
19691 S.DefaultFunctionArrayLvalueConversion(TempArrayRes.get());
19692 auto *Idx = new (S.Context)
19693 OpaqueValueExpr(ELoc, S.Context.getSizeType(), VK_PRValue);
19694 TempArrayElem = S.CreateBuiltinArraySubscriptExpr(TempArrayElem.get(),
19695 ELoc, Idx, ELoc);
19696 }
19697 }
19698
19699 // OpenMP [2.15.4.6, Restrictions, p.2]
19700 // A list item that appears in an in_reduction clause of a task construct
19701 // must appear in a task_reduction clause of a construct associated with a
19702 // taskgroup region that includes the participating task in its taskgroup
19703 // set. The construct associated with the innermost region that meets this
19704 // condition must specify the same reduction-identifier as the in_reduction
19705 // clause.
19706 if (ClauseKind == OMPC_in_reduction) {
19707 SourceRange ParentSR;
19708 BinaryOperatorKind ParentBOK;
19709 const Expr *ParentReductionOp = nullptr;
19710 Expr *ParentBOKTD = nullptr, *ParentReductionOpTD = nullptr;
19711 DSAStackTy::DSAVarData ParentBOKDSA =
19712 Stack->getTopMostTaskgroupReductionData(D, ParentSR, ParentBOK,
19713 ParentBOKTD);
19714 DSAStackTy::DSAVarData ParentReductionOpDSA =
19715 Stack->getTopMostTaskgroupReductionData(
19716 D, ParentSR, ParentReductionOp, ParentReductionOpTD);
19717 bool IsParentBOK = ParentBOKDSA.DKind != OMPD_unknown;
19718 bool IsParentReductionOp = ParentReductionOpDSA.DKind != OMPD_unknown;
19719 if ((DeclareReductionRef.isUnset() && IsParentReductionOp) ||
19720 (DeclareReductionRef.isUsable() && IsParentBOK) ||
19721 (IsParentBOK && BOK != ParentBOK) || IsParentReductionOp) {
19722 bool EmitError = true;
19723 if (IsParentReductionOp && DeclareReductionRef.isUsable()) {
19724 llvm::FoldingSetNodeID RedId, ParentRedId;
19725 ParentReductionOp->Profile(ParentRedId, Context, /*Canonical=*/true);
19726 DeclareReductionRef.get()->Profile(RedId, Context,
19727 /*Canonical=*/true);
19728 EmitError = RedId != ParentRedId;
19729 }
19730 if (EmitError) {
19731 S.Diag(ReductionId.getBeginLoc(),
19732 diag::err_omp_reduction_identifier_mismatch)
19733 << ReductionIdRange << RefExpr->getSourceRange();
19734 S.Diag(ParentSR.getBegin(),
19735 diag::note_omp_previous_reduction_identifier)
19736 << ParentSR
19737 << (IsParentBOK ? ParentBOKDSA.RefExpr
19738 : ParentReductionOpDSA.RefExpr)
19739 ->getSourceRange();
19740 continue;
19741 }
19742 }
19743 TaskgroupDescriptor = IsParentBOK ? ParentBOKTD : ParentReductionOpTD;
19744 }
19745
19746 DeclRefExpr *Ref = nullptr;
19747 Expr *VarsExpr = RefExpr->IgnoreParens();
19748 if (!VD && !S.CurContext->isDependentContext()) {
19749 if (ASE || OASE) {
19750 TransformExprToCaptures RebuildToCapture(S, D);
19751 VarsExpr =
19752 RebuildToCapture.TransformExpr(RefExpr->IgnoreParens()).get();
19753 Ref = RebuildToCapture.getCapturedExpr();
19754 } else {
19755 VarsExpr = Ref = buildCapture(S, D, SimpleRefExpr, /*WithInit=*/false);
19756 }
19757 if (!S.isOpenMPCapturedDecl(D)) {
19758 RD.ExprCaptures.emplace_back(Ref->getDecl());
19759 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
19760 ExprResult RefRes = S.DefaultLvalueConversion(Ref);
19761 if (!RefRes.isUsable())
19762 continue;
19763 ExprResult PostUpdateRes =
19764 S.BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, SimpleRefExpr,
19765 RefRes.get());
19766 if (!PostUpdateRes.isUsable())
19767 continue;
19768 if (isOpenMPTaskingDirective(Stack->getCurrentDirective()) ||
19769 Stack->getCurrentDirective() == OMPD_taskgroup) {
19770 S.Diag(RefExpr->getExprLoc(),
19771 diag::err_omp_reduction_non_addressable_expression)
19772 << RefExpr->getSourceRange();
19773 continue;
19774 }
19775 RD.ExprPostUpdates.emplace_back(
19776 S.IgnoredValueConversions(PostUpdateRes.get()).get());
19777 }
19778 }
19779 }
19780 // All reduction items are still marked as reduction (to do not increase
19781 // code base size).
19782 unsigned Modifier = RD.RedModifier;
19783 // Consider task_reductions as reductions with task modifier. Required for
19784 // correct analysis of in_reduction clauses.
19785 if (CurrDir == OMPD_taskgroup && ClauseKind == OMPC_task_reduction)
19786 Modifier = OMPC_REDUCTION_task;
19787 Stack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, Ref, Modifier,
19788 ASE || OASE);
19789 if (Modifier == OMPC_REDUCTION_task &&
19790 (CurrDir == OMPD_taskgroup ||
19791 ((isOpenMPParallelDirective(CurrDir) ||
19792 isOpenMPWorksharingDirective(CurrDir)) &&
19793 !isOpenMPSimdDirective(CurrDir)))) {
19794 if (DeclareReductionRef.isUsable())
19795 Stack->addTaskgroupReductionData(D, ReductionIdRange,
19796 DeclareReductionRef.get());
19797 else
19798 Stack->addTaskgroupReductionData(D, ReductionIdRange, BOK);
19799 }
19800 RD.push(VarsExpr, PrivateDRE, LHSDRE, RHSDRE, ReductionOp.get(),
19801 TaskgroupDescriptor, CopyOpRes.get(), TempArrayRes.get(),
19802 TempArrayElem.get());
19803 }
19804 return RD.Vars.empty();
19805}
19806
19807OMPClause *Sema::ActOnOpenMPReductionClause(
19808 ArrayRef<Expr *> VarList, OpenMPReductionClauseModifier Modifier,
19809 SourceLocation StartLoc, SourceLocation LParenLoc,
19810 SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc,
19811 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
19812 ArrayRef<Expr *> UnresolvedReductions) {
19813 if (ModifierLoc.isValid() && Modifier == OMPC_REDUCTION_unknown) {
19814 Diag(LParenLoc, diag::err_omp_unexpected_clause_value)
19815 << getListOfPossibleValues(OMPC_reduction, /*First=*/0,
19816 /*Last=*/OMPC_REDUCTION_unknown)
19817 << getOpenMPClauseName(OMPC_reduction);
19818 return nullptr;
19819 }
19820 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions
19821 // A reduction clause with the inscan reduction-modifier may only appear on a
19822 // worksharing-loop construct, a worksharing-loop SIMD construct, a simd
19823 // construct, a parallel worksharing-loop construct or a parallel
19824 // worksharing-loop SIMD construct.
19825 if (Modifier == OMPC_REDUCTION_inscan &&
19826 (DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective() != OMPD_for &&
19827 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective() != OMPD_for_simd &&
19828 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective() != OMPD_simd &&
19829 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective() != OMPD_parallel_for &&
19830 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective() != OMPD_parallel_for_simd)) {
19831 Diag(ModifierLoc, diag::err_omp_wrong_inscan_reduction);
19832 return nullptr;
19833 }
19834
19835 ReductionData RD(VarList.size(), Modifier);
19836 if (actOnOMPReductionKindClause(*this, DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
, OMPC_reduction, VarList,
19837 StartLoc, LParenLoc, ColonLoc, EndLoc,
19838 ReductionIdScopeSpec, ReductionId,
19839 UnresolvedReductions, RD))
19840 return nullptr;
19841
19842 return OMPReductionClause::Create(
19843 Context, StartLoc, LParenLoc, ModifierLoc, ColonLoc, EndLoc, Modifier,
19844 RD.Vars, ReductionIdScopeSpec.getWithLocInContext(Context), ReductionId,
19845 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.InscanCopyOps,
19846 RD.InscanCopyArrayTemps, RD.InscanCopyArrayElems,
19847 buildPreInits(Context, RD.ExprCaptures),
19848 buildPostUpdate(*this, RD.ExprPostUpdates));
19849}
19850
19851OMPClause *Sema::ActOnOpenMPTaskReductionClause(
19852 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
19853 SourceLocation ColonLoc, SourceLocation EndLoc,
19854 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
19855 ArrayRef<Expr *> UnresolvedReductions) {
19856 ReductionData RD(VarList.size());
19857 if (actOnOMPReductionKindClause(*this, DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
, OMPC_task_reduction, VarList,
19858 StartLoc, LParenLoc, ColonLoc, EndLoc,
19859 ReductionIdScopeSpec, ReductionId,
19860 UnresolvedReductions, RD))
19861 return nullptr;
19862
19863 return OMPTaskReductionClause::Create(
19864 Context, StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
19865 ReductionIdScopeSpec.getWithLocInContext(Context), ReductionId,
19866 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps,
19867 buildPreInits(Context, RD.ExprCaptures),
19868 buildPostUpdate(*this, RD.ExprPostUpdates));
19869}
19870
19871OMPClause *Sema::ActOnOpenMPInReductionClause(
19872 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
19873 SourceLocation ColonLoc, SourceLocation EndLoc,
19874 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
19875 ArrayRef<Expr *> UnresolvedReductions) {
19876 ReductionData RD(VarList.size());
19877 if (actOnOMPReductionKindClause(*this, DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
, OMPC_in_reduction, VarList,
19878 StartLoc, LParenLoc, ColonLoc, EndLoc,
19879 ReductionIdScopeSpec, ReductionId,
19880 UnresolvedReductions, RD))
19881 return nullptr;
19882
19883 return OMPInReductionClause::Create(
19884 Context, StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
19885 ReductionIdScopeSpec.getWithLocInContext(Context), ReductionId,
19886 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.TaskgroupDescriptors,
19887 buildPreInits(Context, RD.ExprCaptures),
19888 buildPostUpdate(*this, RD.ExprPostUpdates));
19889}
19890
19891bool Sema::CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind,
19892 SourceLocation LinLoc) {
19893 if ((!LangOpts.CPlusPlus && LinKind != OMPC_LINEAR_val) ||
19894 LinKind == OMPC_LINEAR_unknown) {
19895 Diag(LinLoc, diag::err_omp_wrong_linear_modifier) << LangOpts.CPlusPlus;
19896 return true;
19897 }
19898 return false;
19899}
19900
19901bool Sema::CheckOpenMPLinearDecl(const ValueDecl *D, SourceLocation ELoc,
19902 OpenMPLinearClauseKind LinKind, QualType Type,
19903 bool IsDeclareSimd) {
19904 const auto *VD = dyn_cast_or_null<VarDecl>(D);
19905 // A variable must not have an incomplete type or a reference type.
19906 if (RequireCompleteType(ELoc, Type, diag::err_omp_linear_incomplete_type))
19907 return true;
19908 if ((LinKind == OMPC_LINEAR_uval || LinKind == OMPC_LINEAR_ref) &&
19909 !Type->isReferenceType()) {
19910 Diag(ELoc, diag::err_omp_wrong_linear_modifier_non_reference)
19911 << Type << getOpenMPSimpleClauseTypeName(OMPC_linear, LinKind);
19912 return true;
19913 }
19914 Type = Type.getNonReferenceType();
19915
19916 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
19917 // A variable that is privatized must not have a const-qualified type
19918 // unless it is of class type with a mutable member. This restriction does
19919 // not apply to the firstprivate clause, nor to the linear clause on
19920 // declarative directives (like declare simd).
19921 if (!IsDeclareSimd &&
19922 rejectConstNotMutableType(*this, D, Type, OMPC_linear, ELoc))
19923 return true;
19924
19925 // A list item must be of integral or pointer type.
19926 Type = Type.getUnqualifiedType().getCanonicalType();
19927 const auto *Ty = Type.getTypePtrOrNull();
19928 if (!Ty || (LinKind != OMPC_LINEAR_ref && !Ty->isDependentType() &&
19929 !Ty->isIntegralType(Context) && !Ty->isPointerType())) {
19930 Diag(ELoc, diag::err_omp_linear_expected_int_or_ptr) << Type;
19931 if (D) {
19932 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
19933 VarDecl::DeclarationOnly;
19934 Diag(D->getLocation(),
19935 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19936 << D;
19937 }
19938 return true;
19939 }
19940 return false;
19941}
19942
19943OMPClause *Sema::ActOnOpenMPLinearClause(
19944 ArrayRef<Expr *> VarList, Expr *Step, SourceLocation StartLoc,
19945 SourceLocation LParenLoc, OpenMPLinearClauseKind LinKind,
19946 SourceLocation LinLoc, SourceLocation ColonLoc, SourceLocation EndLoc) {
19947 SmallVector<Expr *, 8> Vars;
19948 SmallVector<Expr *, 8> Privates;
19949 SmallVector<Expr *, 8> Inits;
19950 SmallVector<Decl *, 4> ExprCaptures;
19951 SmallVector<Expr *, 4> ExprPostUpdates;
19952 if (CheckOpenMPLinearModifier(LinKind, LinLoc))
19953 LinKind = OMPC_LINEAR_val;
19954 for (Expr *RefExpr : VarList) {
19955 assert(RefExpr && "NULL expr in OpenMP linear clause.")(static_cast <bool> (RefExpr && "NULL expr in OpenMP linear clause."
) ? void (0) : __assert_fail ("RefExpr && \"NULL expr in OpenMP linear clause.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 19955, __extension__ __PRETTY_FUNCTION__
))
;
19956 SourceLocation ELoc;
19957 SourceRange ERange;
19958 Expr *SimpleRefExpr = RefExpr;
19959 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
19960 if (Res.second) {
19961 // It will be analyzed later.
19962 Vars.push_back(RefExpr);
19963 Privates.push_back(nullptr);
19964 Inits.push_back(nullptr);
19965 }
19966 ValueDecl *D = Res.first;
19967 if (!D)
19968 continue;
19969
19970 QualType Type = D->getType();
19971 auto *VD = dyn_cast<VarDecl>(D);
19972
19973 // OpenMP [2.14.3.7, linear clause]
19974 // A list-item cannot appear in more than one linear clause.
19975 // A list-item that appears in a linear clause cannot appear in any
19976 // other data-sharing attribute clause.
19977 DSAStackTy::DSAVarData DVar = DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getTopDSA(D, /*FromParent=*/false);
19978 if (DVar.RefExpr) {
19979 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
19980 << getOpenMPClauseName(OMPC_linear);
19981 reportOriginalDsa(*this, DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
, D, DVar);
19982 continue;
19983 }
19984
19985 if (CheckOpenMPLinearDecl(D, ELoc, LinKind, Type))
19986 continue;
19987 Type = Type.getNonReferenceType().getUnqualifiedType().getCanonicalType();
19988
19989 // Build private copy of original var.
19990 VarDecl *Private =
19991 buildVarDecl(*this, ELoc, Type, D->getName(),
19992 D->hasAttrs() ? &D->getAttrs() : nullptr,
19993 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
19994 DeclRefExpr *PrivateRef = buildDeclRefExpr(*this, Private, Type, ELoc);
19995 // Build var to save initial value.
19996 VarDecl *Init = buildVarDecl(*this, ELoc, Type, ".linear.start");
19997 Expr *InitExpr;
19998 DeclRefExpr *Ref = nullptr;
19999 if (!VD && !CurContext->isDependentContext()) {
20000 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/false);
20001 if (!isOpenMPCapturedDecl(D)) {
20002 ExprCaptures.push_back(Ref->getDecl());
20003 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
20004 ExprResult RefRes = DefaultLvalueConversion(Ref);
20005 if (!RefRes.isUsable())
20006 continue;
20007 ExprResult PostUpdateRes =
20008 BuildBinOp(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurScope(), ELoc, BO_Assign,
20009 SimpleRefExpr, RefRes.get());
20010 if (!PostUpdateRes.isUsable())
20011 continue;
20012 ExprPostUpdates.push_back(
20013 IgnoredValueConversions(PostUpdateRes.get()).get());
20014 }
20015 }
20016 }
20017 if (LinKind == OMPC_LINEAR_uval)
20018 InitExpr = VD ? VD->getInit() : SimpleRefExpr;
20019 else
20020 InitExpr = VD ? SimpleRefExpr : Ref;
20021 AddInitializerToDecl(Init, DefaultLvalueConversion(InitExpr).get(),
20022 /*DirectInit=*/false);
20023 DeclRefExpr *InitRef = buildDeclRefExpr(*this, Init, Type, ELoc);
20024
20025 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->addDSA(D, RefExpr->IgnoreParens(), OMPC_linear, Ref);
20026 Vars.push_back((VD || CurContext->isDependentContext())
20027 ? RefExpr->IgnoreParens()
20028 : Ref);
20029 Privates.push_back(PrivateRef);
20030 Inits.push_back(InitRef);
20031 }
20032
20033 if (Vars.empty())
20034 return nullptr;
20035
20036 Expr *StepExpr = Step;
20037 Expr *CalcStepExpr = nullptr;
20038 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
20039 !Step->isInstantiationDependent() &&
20040 !Step->containsUnexpandedParameterPack()) {
20041 SourceLocation StepLoc = Step->getBeginLoc();
20042 ExprResult Val = PerformOpenMPImplicitIntegerConversion(StepLoc, Step);
20043 if (Val.isInvalid())
20044 return nullptr;
20045 StepExpr = Val.get();
20046
20047 // Build var to save the step value.
20048 VarDecl *SaveVar =
20049 buildVarDecl(*this, StepLoc, StepExpr->getType(), ".linear.step");
20050 ExprResult SaveRef =
20051 buildDeclRefExpr(*this, SaveVar, StepExpr->getType(), StepLoc);
20052 ExprResult CalcStep =
20053 BuildBinOp(CurScope, StepLoc, BO_Assign, SaveRef.get(), StepExpr);
20054 CalcStep = ActOnFinishFullExpr(CalcStep.get(), /*DiscardedValue*/ false);
20055
20056 // Warn about zero linear step (it would be probably better specified as
20057 // making corresponding variables 'const').
20058 if (std::optional<llvm::APSInt> Result =
20059 StepExpr->getIntegerConstantExpr(Context)) {
20060 if (!Result->isNegative() && !Result->isStrictlyPositive())
20061 Diag(StepLoc, diag::warn_omp_linear_step_zero)
20062 << Vars[0] << (Vars.size() > 1);
20063 } else if (CalcStep.isUsable()) {
20064 // Calculate the step beforehand instead of doing this on each iteration.
20065 // (This is not used if the number of iterations may be kfold-ed).
20066 CalcStepExpr = CalcStep.get();
20067 }
20068 }
20069
20070 return OMPLinearClause::Create(Context, StartLoc, LParenLoc, LinKind, LinLoc,
20071 ColonLoc, EndLoc, Vars, Privates, Inits,
20072 StepExpr, CalcStepExpr,
20073 buildPreInits(Context, ExprCaptures),
20074 buildPostUpdate(*this, ExprPostUpdates));
20075}
20076
20077static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
20078 Expr *NumIterations, Sema &SemaRef,
20079 Scope *S, DSAStackTy *Stack) {
20080 // Walk the vars and build update/final expressions for the CodeGen.
20081 SmallVector<Expr *, 8> Updates;
20082 SmallVector<Expr *, 8> Finals;
20083 SmallVector<Expr *, 8> UsedExprs;
20084 Expr *Step = Clause.getStep();
20085 Expr *CalcStep = Clause.getCalcStep();
20086 // OpenMP [2.14.3.7, linear clause]
20087 // If linear-step is not specified it is assumed to be 1.
20088 if (!Step)
20089 Step = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get();
20090 else if (CalcStep)
20091 Step = cast<BinaryOperator>(CalcStep)->getLHS();
20092 bool HasErrors = false;
20093 auto CurInit = Clause.inits().begin();
20094 auto CurPrivate = Clause.privates().begin();
20095 OpenMPLinearClauseKind LinKind = Clause.getModifier();
20096 for (Expr *RefExpr : Clause.varlists()) {
20097 SourceLocation ELoc;
20098 SourceRange ERange;
20099 Expr *SimpleRefExpr = RefExpr;
20100 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
20101 ValueDecl *D = Res.first;
20102 if (Res.second || !D) {
20103 Updates.push_back(nullptr);
20104 Finals.push_back(nullptr);
20105 HasErrors = true;
20106 continue;
20107 }
20108 auto &&Info = Stack->isLoopControlVariable(D);
20109 // OpenMP [2.15.11, distribute simd Construct]
20110 // A list item may not appear in a linear clause, unless it is the loop
20111 // iteration variable.
20112 if (isOpenMPDistributeDirective(Stack->getCurrentDirective()) &&
20113 isOpenMPSimdDirective(Stack->getCurrentDirective()) && !Info.first) {
20114 SemaRef.Diag(ELoc,
20115 diag::err_omp_linear_distribute_var_non_loop_iteration);
20116 Updates.push_back(nullptr);
20117 Finals.push_back(nullptr);
20118 HasErrors = true;
20119 continue;
20120 }
20121 Expr *InitExpr = *CurInit;
20122
20123 // Build privatized reference to the current linear var.
20124 auto *DE = cast<DeclRefExpr>(SimpleRefExpr);
20125 Expr *CapturedRef;
20126 if (LinKind == OMPC_LINEAR_uval)
20127 CapturedRef = cast<VarDecl>(DE->getDecl())->getInit();
20128 else
20129 CapturedRef =
20130 buildDeclRefExpr(SemaRef, cast<VarDecl>(DE->getDecl()),
20131 DE->getType().getUnqualifiedType(), DE->getExprLoc(),
20132 /*RefersToCapture=*/true);
20133
20134 // Build update: Var = InitExpr + IV * Step
20135 ExprResult Update;
20136 if (!Info.first)
20137 Update = buildCounterUpdate(
20138 SemaRef, S, RefExpr->getExprLoc(), *CurPrivate, InitExpr, IV, Step,
20139 /*Subtract=*/false, /*IsNonRectangularLB=*/false);
20140 else
20141 Update = *CurPrivate;
20142 Update = SemaRef.ActOnFinishFullExpr(Update.get(), DE->getBeginLoc(),
20143 /*DiscardedValue*/ false);
20144
20145 // Build final: Var = PrivCopy;
20146 ExprResult Final;
20147 if (!Info.first)
20148 Final = SemaRef.BuildBinOp(
20149 S, RefExpr->getExprLoc(), BO_Assign, CapturedRef,
20150 SemaRef.DefaultLvalueConversion(*CurPrivate).get());
20151 else
20152 Final = *CurPrivate;
20153 Final = SemaRef.ActOnFinishFullExpr(Final.get(), DE->getBeginLoc(),
20154 /*DiscardedValue*/ false);
20155
20156 if (!Update.isUsable() || !Final.isUsable()) {
20157 Updates.push_back(nullptr);
20158 Finals.push_back(nullptr);
20159 UsedExprs.push_back(nullptr);
20160 HasErrors = true;
20161 } else {
20162 Updates.push_back(Update.get());
20163 Finals.push_back(Final.get());
20164 if (!Info.first)
20165 UsedExprs.push_back(SimpleRefExpr);
20166 }
20167 ++CurInit;
20168 ++CurPrivate;
20169 }
20170 if (Expr *S = Clause.getStep())
20171 UsedExprs.push_back(S);
20172 // Fill the remaining part with the nullptr.
20173 UsedExprs.append(Clause.varlist_size() + 1 - UsedExprs.size(), nullptr);
20174 Clause.setUpdates(Updates);
20175 Clause.setFinals(Finals);
20176 Clause.setUsedExprs(UsedExprs);
20177 return HasErrors;
20178}
20179
20180OMPClause *Sema::ActOnOpenMPAlignedClause(
20181 ArrayRef<Expr *> VarList, Expr *Alignment, SourceLocation StartLoc,
20182 SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc) {
20183 SmallVector<Expr *, 8> Vars;
20184 for (Expr *RefExpr : VarList) {
20185 assert(RefExpr && "NULL expr in OpenMP linear clause.")(static_cast <bool> (RefExpr && "NULL expr in OpenMP linear clause."
) ? void (0) : __assert_fail ("RefExpr && \"NULL expr in OpenMP linear clause.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 20185, __extension__ __PRETTY_FUNCTION__
))
;
20186 SourceLocation ELoc;
20187 SourceRange ERange;
20188 Expr *SimpleRefExpr = RefExpr;
20189 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
20190 if (Res.second) {
20191 // It will be analyzed later.
20192 Vars.push_back(RefExpr);
20193 }
20194 ValueDecl *D = Res.first;
20195 if (!D)
20196 continue;
20197
20198 QualType QType = D->getType();
20199 auto *VD = dyn_cast<VarDecl>(D);
20200
20201 // OpenMP [2.8.1, simd construct, Restrictions]
20202 // The type of list items appearing in the aligned clause must be
20203 // array, pointer, reference to array, or reference to pointer.
20204 QType = QType.getNonReferenceType().getUnqualifiedType().getCanonicalType();
20205 const Type *Ty = QType.getTypePtrOrNull();
20206 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
20207 Diag(ELoc, diag::err_omp_aligned_expected_array_or_ptr)
20208 << QType << getLangOpts().CPlusPlus << ERange;
20209 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
20210 VarDecl::DeclarationOnly;
20211 Diag(D->getLocation(),
20212 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20213 << D;
20214 continue;
20215 }
20216
20217 // OpenMP [2.8.1, simd construct, Restrictions]
20218 // A list-item cannot appear in more than one aligned clause.
20219 if (const Expr *PrevRef = DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->addUniqueAligned(D, SimpleRefExpr)) {
20220 Diag(ELoc, diag::err_omp_used_in_clause_twice)
20221 << 0 << getOpenMPClauseName(OMPC_aligned) << ERange;
20222 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
20223 << getOpenMPClauseName(OMPC_aligned);
20224 continue;
20225 }
20226
20227 DeclRefExpr *Ref = nullptr;
20228 if (!VD && isOpenMPCapturedDecl(D))
20229 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true);
20230 Vars.push_back(DefaultFunctionArrayConversion(
20231 (VD || !Ref) ? RefExpr->IgnoreParens() : Ref)
20232 .get());
20233 }
20234
20235 // OpenMP [2.8.1, simd construct, Description]
20236 // The parameter of the aligned clause, alignment, must be a constant
20237 // positive integer expression.
20238 // If no optional parameter is specified, implementation-defined default
20239 // alignments for SIMD instructions on the target platforms are assumed.
20240 if (Alignment != nullptr) {
20241 ExprResult AlignResult =
20242 VerifyPositiveIntegerConstantInClause(Alignment, OMPC_aligned);
20243 if (AlignResult.isInvalid())
20244 return nullptr;
20245 Alignment = AlignResult.get();
20246 }
20247 if (Vars.empty())
20248 return nullptr;
20249
20250 return OMPAlignedClause::Create(Context, StartLoc, LParenLoc, ColonLoc,
20251 EndLoc, Vars, Alignment);
20252}
20253
20254OMPClause *Sema::ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList,
20255 SourceLocation StartLoc,
20256 SourceLocation LParenLoc,
20257 SourceLocation EndLoc) {
20258 SmallVector<Expr *, 8> Vars;
20259 SmallVector<Expr *, 8> SrcExprs;
20260 SmallVector<Expr *, 8> DstExprs;
20261 SmallVector<Expr *, 8> AssignmentOps;
20262 for (Expr *RefExpr : VarList) {
20263 assert(RefExpr && "NULL expr in OpenMP copyin clause.")(static_cast <bool> (RefExpr && "NULL expr in OpenMP copyin clause."
) ? void (0) : __assert_fail ("RefExpr && \"NULL expr in OpenMP copyin clause.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 20263, __extension__ __PRETTY_FUNCTION__
))
;
20264 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
20265 // It will be analyzed later.
20266 Vars.push_back(RefExpr);
20267 SrcExprs.push_back(nullptr);
20268 DstExprs.push_back(nullptr);
20269 AssignmentOps.push_back(nullptr);
20270 continue;
20271 }
20272
20273 SourceLocation ELoc = RefExpr->getExprLoc();
20274 // OpenMP [2.1, C/C++]
20275 // A list item is a variable name.
20276 // OpenMP [2.14.4.1, Restrictions, p.1]
20277 // A list item that appears in a copyin clause must be threadprivate.
20278 auto *DE = dyn_cast<DeclRefExpr>(RefExpr);
20279 if (!DE || !isa<VarDecl>(DE->getDecl())) {
20280 Diag(ELoc, diag::err_omp_expected_var_name_member_expr)
20281 << 0 << RefExpr->getSourceRange();
20282 continue;
20283 }
20284
20285 Decl *D = DE->getDecl();
20286 auto *VD = cast<VarDecl>(D);
20287
20288 QualType Type = VD->getType();
20289 if (Type->isDependentType() || Type->isInstantiationDependentType()) {
20290 // It will be analyzed later.
20291 Vars.push_back(DE);
20292 SrcExprs.push_back(nullptr);
20293 DstExprs.push_back(nullptr);
20294 AssignmentOps.push_back(nullptr);
20295 continue;
20296 }
20297
20298 // OpenMP [2.14.4.1, Restrictions, C/C++, p.1]
20299 // A list item that appears in a copyin clause must be threadprivate.
20300 if (!DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isThreadPrivate(VD)) {
20301 Diag(ELoc, diag::err_omp_required_access)
20302 << getOpenMPClauseName(OMPC_copyin)
20303 << getOpenMPDirectiveName(OMPD_threadprivate);
20304 continue;
20305 }
20306
20307 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
20308 // A variable of class type (or array thereof) that appears in a
20309 // copyin clause requires an accessible, unambiguous copy assignment
20310 // operator for the class type.
20311 QualType ElemType = Context.getBaseElementType(Type).getNonReferenceType();
20312 VarDecl *SrcVD =
20313 buildVarDecl(*this, DE->getBeginLoc(), ElemType.getUnqualifiedType(),
20314 ".copyin.src", VD->hasAttrs() ? &VD->getAttrs() : nullptr);
20315 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(
20316 *this, SrcVD, ElemType.getUnqualifiedType(), DE->getExprLoc());
20317 VarDecl *DstVD =
20318 buildVarDecl(*this, DE->getBeginLoc(), ElemType, ".copyin.dst",
20319 VD->hasAttrs() ? &VD->getAttrs() : nullptr);
20320 DeclRefExpr *PseudoDstExpr =
20321 buildDeclRefExpr(*this, DstVD, ElemType, DE->getExprLoc());
20322 // For arrays generate assignment operation for single element and replace
20323 // it by the original array element in CodeGen.
20324 ExprResult AssignmentOp =
20325 BuildBinOp(/*S=*/nullptr, DE->getExprLoc(), BO_Assign, PseudoDstExpr,
20326 PseudoSrcExpr);
20327 if (AssignmentOp.isInvalid())
20328 continue;
20329 AssignmentOp = ActOnFinishFullExpr(AssignmentOp.get(), DE->getExprLoc(),
20330 /*DiscardedValue*/ false);
20331 if (AssignmentOp.isInvalid())
20332 continue;
20333
20334 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->addDSA(VD, DE, OMPC_copyin);
20335 Vars.push_back(DE);
20336 SrcExprs.push_back(PseudoSrcExpr);
20337 DstExprs.push_back(PseudoDstExpr);
20338 AssignmentOps.push_back(AssignmentOp.get());
20339 }
20340
20341 if (Vars.empty())
20342 return nullptr;
20343
20344 return OMPCopyinClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars,
20345 SrcExprs, DstExprs, AssignmentOps);
20346}
20347
20348OMPClause *Sema::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList,
20349 SourceLocation StartLoc,
20350 SourceLocation LParenLoc,
20351 SourceLocation EndLoc) {
20352 SmallVector<Expr *, 8> Vars;
20353 SmallVector<Expr *, 8> SrcExprs;
20354 SmallVector<Expr *, 8> DstExprs;
20355 SmallVector<Expr *, 8> AssignmentOps;
20356 for (Expr *RefExpr : VarList) {
20357 assert(RefExpr && "NULL expr in OpenMP linear clause.")(static_cast <bool> (RefExpr && "NULL expr in OpenMP linear clause."
) ? void (0) : __assert_fail ("RefExpr && \"NULL expr in OpenMP linear clause.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 20357, __extension__ __PRETTY_FUNCTION__
))
;
20358 SourceLocation ELoc;
20359 SourceRange ERange;
20360 Expr *SimpleRefExpr = RefExpr;
20361 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
20362 if (Res.second) {
20363 // It will be analyzed later.
20364 Vars.push_back(RefExpr);
20365 SrcExprs.push_back(nullptr);
20366 DstExprs.push_back(nullptr);
20367 AssignmentOps.push_back(nullptr);
20368 }
20369 ValueDecl *D = Res.first;
20370 if (!D)
20371 continue;
20372
20373 QualType Type = D->getType();
20374 auto *VD = dyn_cast<VarDecl>(D);
20375
20376 // OpenMP [2.14.4.2, Restrictions, p.2]
20377 // A list item that appears in a copyprivate clause may not appear in a
20378 // private or firstprivate clause on the single construct.
20379 if (!VD || !DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isThreadPrivate(VD)) {
20380 DSAStackTy::DSAVarData DVar =
20381 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getTopDSA(D, /*FromParent=*/false);
20382 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_copyprivate &&
20383 DVar.RefExpr) {
20384 Diag(ELoc, diag::err_omp_wrong_dsa)
20385 << getOpenMPClauseName(DVar.CKind)
20386 << getOpenMPClauseName(OMPC_copyprivate);
20387 reportOriginalDsa(*this, DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
, D, DVar);
20388 continue;
20389 }
20390
20391 // OpenMP [2.11.4.2, Restrictions, p.1]
20392 // All list items that appear in a copyprivate clause must be either
20393 // threadprivate or private in the enclosing context.
20394 if (DVar.CKind == OMPC_unknown) {
20395 DVar = DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getImplicitDSA(D, false);
20396 if (DVar.CKind == OMPC_shared) {
20397 Diag(ELoc, diag::err_omp_required_access)
20398 << getOpenMPClauseName(OMPC_copyprivate)
20399 << "threadprivate or private in the enclosing context";
20400 reportOriginalDsa(*this, DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
, D, DVar);
20401 continue;
20402 }
20403 }
20404 }
20405
20406 // Variably modified types are not supported.
20407 if (!Type->isAnyPointerType() && Type->isVariablyModifiedType()) {
20408 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
20409 << getOpenMPClauseName(OMPC_copyprivate) << Type
20410 << getOpenMPDirectiveName(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective());
20411 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
20412 VarDecl::DeclarationOnly;
20413 Diag(D->getLocation(),
20414 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20415 << D;
20416 continue;
20417 }
20418
20419 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
20420 // A variable of class type (or array thereof) that appears in a
20421 // copyin clause requires an accessible, unambiguous copy assignment
20422 // operator for the class type.
20423 Type = Context.getBaseElementType(Type.getNonReferenceType())
20424 .getUnqualifiedType();
20425 VarDecl *SrcVD =
20426 buildVarDecl(*this, RefExpr->getBeginLoc(), Type, ".copyprivate.src",
20427 D->hasAttrs() ? &D->getAttrs() : nullptr);
20428 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(*this, SrcVD, Type, ELoc);
20429 VarDecl *DstVD =
20430 buildVarDecl(*this, RefExpr->getBeginLoc(), Type, ".copyprivate.dst",
20431 D->hasAttrs() ? &D->getAttrs() : nullptr);
20432 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(*this, DstVD, Type, ELoc);
20433 ExprResult AssignmentOp = BuildBinOp(
20434 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurScope(), ELoc, BO_Assign, PseudoDstExpr, PseudoSrcExpr);
20435 if (AssignmentOp.isInvalid())
20436 continue;
20437 AssignmentOp =
20438 ActOnFinishFullExpr(AssignmentOp.get(), ELoc, /*DiscardedValue*/ false);
20439 if (AssignmentOp.isInvalid())
20440 continue;
20441
20442 // No need to mark vars as copyprivate, they are already threadprivate or
20443 // implicitly private.
20444 assert(VD || isOpenMPCapturedDecl(D))(static_cast <bool> (VD || isOpenMPCapturedDecl(D)) ? void
(0) : __assert_fail ("VD || isOpenMPCapturedDecl(D)", "clang/lib/Sema/SemaOpenMP.cpp"
, 20444, __extension__ __PRETTY_FUNCTION__))
;
20445 Vars.push_back(
20446 VD ? RefExpr->IgnoreParens()
20447 : buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/false));
20448 SrcExprs.push_back(PseudoSrcExpr);
20449 DstExprs.push_back(PseudoDstExpr);
20450 AssignmentOps.push_back(AssignmentOp.get());
20451 }
20452
20453 if (Vars.empty())
20454 return nullptr;
20455
20456 return OMPCopyprivateClause::Create(Context, StartLoc, LParenLoc, EndLoc,
20457 Vars, SrcExprs, DstExprs, AssignmentOps);
20458}
20459
20460OMPClause *Sema::ActOnOpenMPFlushClause(ArrayRef<Expr *> VarList,
20461 SourceLocation StartLoc,
20462 SourceLocation LParenLoc,
20463 SourceLocation EndLoc) {
20464 if (VarList.empty())
20465 return nullptr;
20466
20467 return OMPFlushClause::Create(Context, StartLoc, LParenLoc, EndLoc, VarList);
20468}
20469
20470/// Tries to find omp_depend_t. type.
20471static bool findOMPDependT(Sema &S, SourceLocation Loc, DSAStackTy *Stack,
20472 bool Diagnose = true) {
20473 QualType OMPDependT = Stack->getOMPDependT();
20474 if (!OMPDependT.isNull())
20475 return true;
20476 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_depend_t");
20477 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
20478 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
20479 if (Diagnose)
20480 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_depend_t";
20481 return false;
20482 }
20483 Stack->setOMPDependT(PT.get());
20484 return true;
20485}
20486
20487OMPClause *Sema::ActOnOpenMPDepobjClause(Expr *Depobj, SourceLocation StartLoc,
20488 SourceLocation LParenLoc,
20489 SourceLocation EndLoc) {
20490 if (!Depobj)
20491 return nullptr;
20492
20493 bool OMPDependTFound = findOMPDependT(*this, StartLoc, DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
);
20494
20495 // OpenMP 5.0, 2.17.10.1 depobj Construct
20496 // depobj is an lvalue expression of type omp_depend_t.
20497 if (!Depobj->isTypeDependent() && !Depobj->isValueDependent() &&
20498 !Depobj->isInstantiationDependent() &&
20499 !Depobj->containsUnexpandedParameterPack() &&
20500 (OMPDependTFound &&
20501 !Context.typesAreCompatible(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getOMPDependT(), Depobj->getType(),
20502 /*CompareUnqualified=*/true))) {
20503 Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
20504 << 0 << Depobj->getType() << Depobj->getSourceRange();
20505 }
20506
20507 if (!Depobj->isLValue()) {
20508 Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
20509 << 1 << Depobj->getSourceRange();
20510 }
20511
20512 return OMPDepobjClause::Create(Context, StartLoc, LParenLoc, EndLoc, Depobj);
20513}
20514
20515OMPClause *
20516Sema::ActOnOpenMPDependClause(const OMPDependClause::DependDataTy &Data,
20517 Expr *DepModifier, ArrayRef<Expr *> VarList,
20518 SourceLocation StartLoc, SourceLocation LParenLoc,
20519 SourceLocation EndLoc) {
20520 OpenMPDependClauseKind DepKind = Data.DepKind;
20521 SourceLocation DepLoc = Data.DepLoc;
20522 if (DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective() == OMPD_ordered &&
20523 DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink) {
20524 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
20525 << "'source' or 'sink'" << getOpenMPClauseName(OMPC_depend);
20526 return nullptr;
20527 }
20528 if (DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective() == OMPD_taskwait &&
20529 DepKind == OMPC_DEPEND_mutexinoutset) {
20530 Diag(DepLoc, diag::err_omp_taskwait_depend_mutexinoutset_not_allowed);
20531 return nullptr;
20532 }
20533 if ((DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective() != OMPD_ordered ||
20534 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective() == OMPD_depobj) &&
20535 (DepKind == OMPC_DEPEND_unknown || DepKind == OMPC_DEPEND_source ||
20536 DepKind == OMPC_DEPEND_sink ||
20537 ((LangOpts.OpenMP < 50 ||
20538 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective() == OMPD_depobj) &&
20539 DepKind == OMPC_DEPEND_depobj))) {
20540 SmallVector<unsigned, 6> Except = {OMPC_DEPEND_source, OMPC_DEPEND_sink,
20541 OMPC_DEPEND_outallmemory,
20542 OMPC_DEPEND_inoutallmemory};
20543 if (LangOpts.OpenMP < 50 || DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective() == OMPD_depobj)
20544 Except.push_back(OMPC_DEPEND_depobj);
20545 if (LangOpts.OpenMP < 51)
20546 Except.push_back(OMPC_DEPEND_inoutset);
20547 std::string Expected = (LangOpts.OpenMP >= 50 && !DepModifier)
20548 ? "depend modifier(iterator) or "
20549 : "";
20550 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
20551 << Expected + getListOfPossibleValues(OMPC_depend, /*First=*/0,
20552 /*Last=*/OMPC_DEPEND_unknown,
20553 Except)
20554 << getOpenMPClauseName(OMPC_depend);
20555 return nullptr;
20556 }
20557 if (DepModifier &&
20558 (DepKind == OMPC_DEPEND_source || DepKind == OMPC_DEPEND_sink)) {
20559 Diag(DepModifier->getExprLoc(),
20560 diag::err_omp_depend_sink_source_with_modifier);
20561 return nullptr;
20562 }
20563 if (DepModifier &&
20564 !DepModifier->getType()->isSpecificBuiltinType(BuiltinType::OMPIterator))
20565 Diag(DepModifier->getExprLoc(), diag::err_omp_depend_modifier_not_iterator);
20566
20567 SmallVector<Expr *, 8> Vars;
20568 DSAStackTy::OperatorOffsetTy OpsOffs;
20569 llvm::APSInt DepCounter(/*BitWidth=*/32);
20570 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
20571 if (DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) {
20572 if (const Expr *OrderedCountExpr =
20573 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getParentOrderedRegionParam().first) {
20574 TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(Context);
20575 TotalDepCount.setIsUnsigned(/*Val=*/true);
20576 }
20577 }
20578 for (Expr *RefExpr : VarList) {
20579 assert(RefExpr && "NULL expr in OpenMP shared clause.")(static_cast <bool> (RefExpr && "NULL expr in OpenMP shared clause."
) ? void (0) : __assert_fail ("RefExpr && \"NULL expr in OpenMP shared clause.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 20579, __extension__ __PRETTY_FUNCTION__
))
;
20580 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
20581 // It will be analyzed later.
20582 Vars.push_back(RefExpr);
20583 continue;
20584 }
20585
20586 SourceLocation ELoc = RefExpr->getExprLoc();
20587 Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
20588 if (DepKind == OMPC_DEPEND_sink) {
20589 if (DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getParentOrderedRegionParam().first &&
20590 DepCounter >= TotalDepCount) {
20591 Diag(ELoc, diag::err_omp_depend_sink_unexpected_expr);
20592 continue;
20593 }
20594 ++DepCounter;
20595 // OpenMP [2.13.9, Summary]
20596 // depend(dependence-type : vec), where dependence-type is:
20597 // 'sink' and where vec is the iteration vector, which has the form:
20598 // x1 [+- d1], x2 [+- d2 ], . . . , xn [+- dn]
20599 // where n is the value specified by the ordered clause in the loop
20600 // directive, xi denotes the loop iteration variable of the i-th nested
20601 // loop associated with the loop directive, and di is a constant
20602 // non-negative integer.
20603 if (CurContext->isDependentContext()) {
20604 // It will be analyzed later.
20605 Vars.push_back(RefExpr);
20606 continue;
20607 }
20608 SimpleExpr = SimpleExpr->IgnoreImplicit();
20609 OverloadedOperatorKind OOK = OO_None;
20610 SourceLocation OOLoc;
20611 Expr *LHS = SimpleExpr;
20612 Expr *RHS = nullptr;
20613 if (auto *BO = dyn_cast<BinaryOperator>(SimpleExpr)) {
20614 OOK = BinaryOperator::getOverloadedOperator(BO->getOpcode());
20615 OOLoc = BO->getOperatorLoc();
20616 LHS = BO->getLHS()->IgnoreParenImpCasts();
20617 RHS = BO->getRHS()->IgnoreParenImpCasts();
20618 } else if (auto *OCE = dyn_cast<CXXOperatorCallExpr>(SimpleExpr)) {
20619 OOK = OCE->getOperator();
20620 OOLoc = OCE->getOperatorLoc();
20621 LHS = OCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
20622 RHS = OCE->getArg(/*Arg=*/1)->IgnoreParenImpCasts();
20623 } else if (auto *MCE = dyn_cast<CXXMemberCallExpr>(SimpleExpr)) {
20624 OOK = MCE->getMethodDecl()
20625 ->getNameInfo()
20626 .getName()
20627 .getCXXOverloadedOperator();
20628 OOLoc = MCE->getCallee()->getExprLoc();
20629 LHS = MCE->getImplicitObjectArgument()->IgnoreParenImpCasts();
20630 RHS = MCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
20631 }
20632 SourceLocation ELoc;
20633 SourceRange ERange;
20634 auto Res = getPrivateItem(*this, LHS, ELoc, ERange);
20635 if (Res.second) {
20636 // It will be analyzed later.
20637 Vars.push_back(RefExpr);
20638 }
20639 ValueDecl *D = Res.first;
20640 if (!D)
20641 continue;
20642
20643 if (OOK != OO_Plus && OOK != OO_Minus && (RHS || OOK != OO_None)) {
20644 Diag(OOLoc, diag::err_omp_depend_sink_expected_plus_minus);
20645 continue;
20646 }
20647 if (RHS) {
20648 ExprResult RHSRes = VerifyPositiveIntegerConstantInClause(
20649 RHS, OMPC_depend, /*StrictlyPositive=*/false);
20650 if (RHSRes.isInvalid())
20651 continue;
20652 }
20653 if (!CurContext->isDependentContext() &&
20654 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getParentOrderedRegionParam().first &&
20655 DepCounter != DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isParentLoopControlVariable(D).first) {
20656 const ValueDecl *VD =
20657 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getParentLoopControlVariable(DepCounter.getZExtValue());
20658 if (VD)
20659 Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
20660 << 1 << VD;
20661 else
20662 Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration) << 0;
20663 continue;
20664 }
20665 OpsOffs.emplace_back(RHS, OOK);
20666 } else {
20667 bool OMPDependTFound = LangOpts.OpenMP >= 50;
20668 if (OMPDependTFound)
20669 OMPDependTFound = findOMPDependT(*this, StartLoc, DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
,
20670 DepKind == OMPC_DEPEND_depobj);
20671 if (DepKind == OMPC_DEPEND_depobj) {
20672 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
20673 // List items used in depend clauses with the depobj dependence type
20674 // must be expressions of the omp_depend_t type.
20675 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
20676 !RefExpr->isInstantiationDependent() &&
20677 !RefExpr->containsUnexpandedParameterPack() &&
20678 (OMPDependTFound &&
20679 !Context.hasSameUnqualifiedType(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getOMPDependT(),
20680 RefExpr->getType()))) {
20681 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
20682 << 0 << RefExpr->getType() << RefExpr->getSourceRange();
20683 continue;
20684 }
20685 if (!RefExpr->isLValue()) {
20686 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
20687 << 1 << RefExpr->getType() << RefExpr->getSourceRange();
20688 continue;
20689 }
20690 } else {
20691 // OpenMP 5.0 [2.17.11, Restrictions]
20692 // List items used in depend clauses cannot be zero-length array
20693 // sections.
20694 QualType ExprTy = RefExpr->getType().getNonReferenceType();
20695 const auto *OASE = dyn_cast<OMPArraySectionExpr>(SimpleExpr);
20696 if (OASE) {
20697 QualType BaseType =
20698 OMPArraySectionExpr::getBaseOriginalType(OASE->getBase());
20699 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
20700 ExprTy = ATy->getElementType();
20701 else
20702 ExprTy = BaseType->getPointeeType();
20703 ExprTy = ExprTy.getNonReferenceType();
20704 const Expr *Length = OASE->getLength();
20705 Expr::EvalResult Result;
20706 if (Length && !Length->isValueDependent() &&
20707 Length->EvaluateAsInt(Result, Context) &&
20708 Result.Val.getInt().isZero()) {
20709 Diag(ELoc,
20710 diag::err_omp_depend_zero_length_array_section_not_allowed)
20711 << SimpleExpr->getSourceRange();
20712 continue;
20713 }
20714 }
20715
20716 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
20717 // List items used in depend clauses with the in, out, inout,
20718 // inoutset, or mutexinoutset dependence types cannot be
20719 // expressions of the omp_depend_t type.
20720 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
20721 !RefExpr->isInstantiationDependent() &&
20722 !RefExpr->containsUnexpandedParameterPack() &&
20723 (!RefExpr->IgnoreParenImpCasts()->isLValue() ||
20724 (OMPDependTFound &&
20725 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getOMPDependT().getTypePtr() == ExprTy.getTypePtr()))) {
20726 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
20727 << (LangOpts.OpenMP >= 50 ? 1 : 0)
20728 << (LangOpts.OpenMP >= 50 ? 1 : 0) << RefExpr->getSourceRange();
20729 continue;
20730 }
20731
20732 auto *ASE = dyn_cast<ArraySubscriptExpr>(SimpleExpr);
20733 if (ASE && !ASE->getBase()->isTypeDependent() &&
20734 !ASE->getBase()->getType().getNonReferenceType()->isPointerType() &&
20735 !ASE->getBase()->getType().getNonReferenceType()->isArrayType()) {
20736 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
20737 << (LangOpts.OpenMP >= 50 ? 1 : 0)
20738 << (LangOpts.OpenMP >= 50 ? 1 : 0) << RefExpr->getSourceRange();
20739 continue;
20740 }
20741
20742 ExprResult Res;
20743 {
20744 Sema::TentativeAnalysisScope Trap(*this);
20745 Res = CreateBuiltinUnaryOp(ELoc, UO_AddrOf,
20746 RefExpr->IgnoreParenImpCasts());
20747 }
20748 if (!Res.isUsable() && !isa<OMPArraySectionExpr>(SimpleExpr) &&
20749 !isa<OMPArrayShapingExpr>(SimpleExpr)) {
20750 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
20751 << (LangOpts.OpenMP >= 50 ? 1 : 0)
20752 << (LangOpts.OpenMP >= 50 ? 1 : 0) << RefExpr->getSourceRange();
20753 continue;
20754 }
20755 }
20756 }
20757 Vars.push_back(RefExpr->IgnoreParenImpCasts());
20758 }
20759
20760 if (!CurContext->isDependentContext() && DepKind == OMPC_DEPEND_sink &&
20761 TotalDepCount > VarList.size() &&
20762 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getParentOrderedRegionParam().first &&
20763 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getParentLoopControlVariable(VarList.size() + 1)) {
20764 Diag(EndLoc, diag::err_omp_depend_sink_expected_loop_iteration)
20765 << 1 << DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getParentLoopControlVariable(VarList.size() + 1);
20766 }
20767 if (DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink &&
20768 DepKind != OMPC_DEPEND_outallmemory &&
20769 DepKind != OMPC_DEPEND_inoutallmemory && Vars.empty())
20770 return nullptr;
20771
20772 auto *C = OMPDependClause::Create(
20773 Context, StartLoc, LParenLoc, EndLoc,
20774 {DepKind, DepLoc, Data.ColonLoc, Data.OmpAllMemoryLoc}, DepModifier, Vars,
20775 TotalDepCount.getZExtValue());
20776 if ((DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) &&
20777 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isParentOrderedRegion())
20778 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->addDoacrossDependClause(C, OpsOffs);
20779 return C;
20780}
20781
20782OMPClause *Sema::ActOnOpenMPDeviceClause(OpenMPDeviceClauseModifier Modifier,
20783 Expr *Device, SourceLocation StartLoc,
20784 SourceLocation LParenLoc,
20785 SourceLocation ModifierLoc,
20786 SourceLocation EndLoc) {
20787 assert((ModifierLoc.isInvalid() || LangOpts.OpenMP >= 50) &&(static_cast <bool> ((ModifierLoc.isInvalid() || LangOpts
.OpenMP >= 50) && "Unexpected device modifier in OpenMP < 50."
) ? void (0) : __assert_fail ("(ModifierLoc.isInvalid() || LangOpts.OpenMP >= 50) && \"Unexpected device modifier in OpenMP < 50.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 20788, __extension__ __PRETTY_FUNCTION__
))
20788 "Unexpected device modifier in OpenMP < 50.")(static_cast <bool> ((ModifierLoc.isInvalid() || LangOpts
.OpenMP >= 50) && "Unexpected device modifier in OpenMP < 50."
) ? void (0) : __assert_fail ("(ModifierLoc.isInvalid() || LangOpts.OpenMP >= 50) && \"Unexpected device modifier in OpenMP < 50.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 20788, __extension__ __PRETTY_FUNCTION__
))
;
20789
20790 bool ErrorFound = false;
20791 if (ModifierLoc.isValid() && Modifier == OMPC_DEVICE_unknown) {
20792 std::string Values =
20793 getListOfPossibleValues(OMPC_device, /*First=*/0, OMPC_DEVICE_unknown);
20794 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
20795 << Values << getOpenMPClauseName(OMPC_device);
20796 ErrorFound = true;
20797 }
20798
20799 Expr *ValExpr = Device;
20800 Stmt *HelperValStmt = nullptr;
20801
20802 // OpenMP [2.9.1, Restrictions]
20803 // The device expression must evaluate to a non-negative integer value.
20804 ErrorFound = !isNonNegativeIntegerValue(ValExpr, *this, OMPC_device,
20805 /*StrictlyPositive=*/false) ||
20806 ErrorFound;
20807 if (ErrorFound)
20808 return nullptr;
20809
20810 // OpenMP 5.0 [2.12.5, Restrictions]
20811 // In case of ancestor device-modifier, a requires directive with
20812 // the reverse_offload clause must be specified.
20813 if (Modifier == OMPC_DEVICE_ancestor) {
20814 if (!DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->hasRequiresDeclWithClause<OMPReverseOffloadClause>()) {
20815 targetDiag(
20816 StartLoc,
20817 diag::err_omp_device_ancestor_without_requires_reverse_offload);
20818 ErrorFound = true;
20819 }
20820 }
20821
20822 OpenMPDirectiveKind DKind = DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective();
20823 OpenMPDirectiveKind CaptureRegion =
20824 getOpenMPCaptureRegionForClause(DKind, OMPC_device, LangOpts.OpenMP);
20825 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
20826 ValExpr = MakeFullExpr(ValExpr).get();
20827 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
20828 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
20829 HelperValStmt = buildPreInits(Context, Captures);
20830 }
20831
20832 return new (Context)
20833 OMPDeviceClause(Modifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
20834 LParenLoc, ModifierLoc, EndLoc);
20835}
20836
20837static bool checkTypeMappable(SourceLocation SL, SourceRange SR, Sema &SemaRef,
20838 DSAStackTy *Stack, QualType QTy,
20839 bool FullCheck = true) {
20840 if (SemaRef.RequireCompleteType(SL, QTy, diag::err_incomplete_type))
20841 return false;
20842 if (FullCheck && !SemaRef.CurContext->isDependentContext() &&
20843 !QTy.isTriviallyCopyableType(SemaRef.Context))
20844 SemaRef.Diag(SL, diag::warn_omp_non_trivial_type_mapped) << QTy << SR;
20845 return true;
20846}
20847
20848/// Return true if it can be proven that the provided array expression
20849/// (array section or array subscript) does NOT specify the whole size of the
20850/// array whose base type is \a BaseQTy.
20851static bool checkArrayExpressionDoesNotReferToWholeSize(Sema &SemaRef,
20852 const Expr *E,
20853 QualType BaseQTy) {
20854 const auto *OASE = dyn_cast<OMPArraySectionExpr>(E);
20855
20856 // If this is an array subscript, it refers to the whole size if the size of
20857 // the dimension is constant and equals 1. Also, an array section assumes the
20858 // format of an array subscript if no colon is used.
20859 if (isa<ArraySubscriptExpr>(E) ||
20860 (OASE && OASE->getColonLocFirst().isInvalid())) {
20861 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
20862 return ATy->getSize().getSExtValue() != 1;
20863 // Size can't be evaluated statically.
20864 return false;
20865 }
20866
20867 assert(OASE && "Expecting array section if not an array subscript.")(static_cast <bool> (OASE && "Expecting array section if not an array subscript."
) ? void (0) : __assert_fail ("OASE && \"Expecting array section if not an array subscript.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 20867, __extension__ __PRETTY_FUNCTION__
))
;
20868 const Expr *LowerBound = OASE->getLowerBound();
20869 const Expr *Length = OASE->getLength();
20870
20871 // If there is a lower bound that does not evaluates to zero, we are not
20872 // covering the whole dimension.
20873 if (LowerBound) {
20874 Expr::EvalResult Result;
20875 if (!LowerBound->EvaluateAsInt(Result, SemaRef.getASTContext()))
20876 return false; // Can't get the integer value as a constant.
20877
20878 llvm::APSInt ConstLowerBound = Result.Val.getInt();
20879 if (ConstLowerBound.getSExtValue())
20880 return true;
20881 }
20882
20883 // If we don't have a length we covering the whole dimension.
20884 if (!Length)
20885 return false;
20886
20887 // If the base is a pointer, we don't have a way to get the size of the
20888 // pointee.
20889 if (BaseQTy->isPointerType())
20890 return false;
20891
20892 // We can only check if the length is the same as the size of the dimension
20893 // if we have a constant array.
20894 const auto *CATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr());
20895 if (!CATy)
20896 return false;
20897
20898 Expr::EvalResult Result;
20899 if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext()))
20900 return false; // Can't get the integer value as a constant.
20901
20902 llvm::APSInt ConstLength = Result.Val.getInt();
20903 return CATy->getSize().getSExtValue() != ConstLength.getSExtValue();
20904}
20905
20906// Return true if it can be proven that the provided array expression (array
20907// section or array subscript) does NOT specify a single element of the array
20908// whose base type is \a BaseQTy.
20909static bool checkArrayExpressionDoesNotReferToUnitySize(Sema &SemaRef,
20910 const Expr *E,
20911 QualType BaseQTy) {
20912 const auto *OASE = dyn_cast<OMPArraySectionExpr>(E);
20913
20914 // An array subscript always refer to a single element. Also, an array section
20915 // assumes the format of an array subscript if no colon is used.
20916 if (isa<ArraySubscriptExpr>(E) ||
20917 (OASE && OASE->getColonLocFirst().isInvalid()))
20918 return false;
20919
20920 assert(OASE && "Expecting array section if not an array subscript.")(static_cast <bool> (OASE && "Expecting array section if not an array subscript."
) ? void (0) : __assert_fail ("OASE && \"Expecting array section if not an array subscript.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 20920, __extension__ __PRETTY_FUNCTION__
))
;
20921 const Expr *Length = OASE->getLength();
20922
20923 // If we don't have a length we have to check if the array has unitary size
20924 // for this dimension. Also, we should always expect a length if the base type
20925 // is pointer.
20926 if (!Length) {
20927 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
20928 return ATy->getSize().getSExtValue() != 1;
20929 // We cannot assume anything.
20930 return false;
20931 }
20932
20933 // Check if the length evaluates to 1.
20934 Expr::EvalResult Result;
20935 if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext()))
20936 return false; // Can't get the integer value as a constant.
20937
20938 llvm::APSInt ConstLength = Result.Val.getInt();
20939 return ConstLength.getSExtValue() != 1;
20940}
20941
20942// The base of elements of list in a map clause have to be either:
20943// - a reference to variable or field.
20944// - a member expression.
20945// - an array expression.
20946//
20947// E.g. if we have the expression 'r.S.Arr[:12]', we want to retrieve the
20948// reference to 'r'.
20949//
20950// If we have:
20951//
20952// struct SS {
20953// Bla S;
20954// foo() {
20955// #pragma omp target map (S.Arr[:12]);
20956// }
20957// }
20958//
20959// We want to retrieve the member expression 'this->S';
20960
20961// OpenMP 5.0 [2.19.7.1, map Clause, Restrictions, p.2]
20962// If a list item is an array section, it must specify contiguous storage.
20963//
20964// For this restriction it is sufficient that we make sure only references
20965// to variables or fields and array expressions, and that no array sections
20966// exist except in the rightmost expression (unless they cover the whole
20967// dimension of the array). E.g. these would be invalid:
20968//
20969// r.ArrS[3:5].Arr[6:7]
20970//
20971// r.ArrS[3:5].x
20972//
20973// but these would be valid:
20974// r.ArrS[3].Arr[6:7]
20975//
20976// r.ArrS[3].x
20977namespace {
20978class MapBaseChecker final : public StmtVisitor<MapBaseChecker, bool> {
20979 Sema &SemaRef;
20980 OpenMPClauseKind CKind = OMPC_unknown;
20981 OpenMPDirectiveKind DKind = OMPD_unknown;
20982 OMPClauseMappableExprCommon::MappableExprComponentList &Components;
20983 bool IsNonContiguous = false;
20984 bool NoDiagnose = false;
20985 const Expr *RelevantExpr = nullptr;
20986 bool AllowUnitySizeArraySection = true;
20987 bool AllowWholeSizeArraySection = true;
20988 bool AllowAnotherPtr = true;
20989 SourceLocation ELoc;
20990 SourceRange ERange;
20991
20992 void emitErrorMsg() {
20993 // If nothing else worked, this is not a valid map clause expression.
20994 if (SemaRef.getLangOpts().OpenMP < 50) {
20995 SemaRef.Diag(ELoc,
20996 diag::err_omp_expected_named_var_member_or_array_expression)
20997 << ERange;
20998 } else {
20999 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
21000 << getOpenMPClauseName(CKind) << ERange;
21001 }
21002 }
21003
21004public:
21005 bool VisitDeclRefExpr(DeclRefExpr *DRE) {
21006 if (!isa<VarDecl>(DRE->getDecl())) {
21007 emitErrorMsg();
21008 return false;
21009 }
21010 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr")(static_cast <bool> (!RelevantExpr && "RelevantExpr is expected to be nullptr"
) ? void (0) : __assert_fail ("!RelevantExpr && \"RelevantExpr is expected to be nullptr\""
, "clang/lib/Sema/SemaOpenMP.cpp", 21010, __extension__ __PRETTY_FUNCTION__
))
;
21011 RelevantExpr = DRE;
21012 // Record the component.
21013 Components.emplace_back(DRE, DRE->getDecl(), IsNonContiguous);
21014 return true;
21015 }
21016
21017 bool VisitMemberExpr(MemberExpr *ME) {
21018 Expr *E = ME;
21019 Expr *BaseE = ME->getBase()->IgnoreParenCasts();
21020
21021 if (isa<CXXThisExpr>(BaseE)) {
21022 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr")(static_cast <bool> (!RelevantExpr && "RelevantExpr is expected to be nullptr"
) ? void (0) : __assert_fail ("!RelevantExpr && \"RelevantExpr is expected to be nullptr\""
, "clang/lib/Sema/SemaOpenMP.cpp", 21022, __extension__ __PRETTY_FUNCTION__
))
;
21023 // We found a base expression: this->Val.
21024 RelevantExpr = ME;
21025 } else {
21026 E = BaseE;
21027 }
21028
21029 if (!isa<FieldDecl>(ME->getMemberDecl())) {
21030 if (!NoDiagnose) {
21031 SemaRef.Diag(ELoc, diag::err_omp_expected_access_to_data_field)
21032 << ME->getSourceRange();
21033 return false;
21034 }
21035 if (RelevantExpr)
21036 return false;
21037 return Visit(E);
21038 }
21039
21040 auto *FD = cast<FieldDecl>(ME->getMemberDecl());
21041
21042 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
21043 // A bit-field cannot appear in a map clause.
21044 //
21045 if (FD->isBitField()) {
21046 if (!NoDiagnose) {
21047 SemaRef.Diag(ELoc, diag::err_omp_bit_fields_forbidden_in_clause)
21048 << ME->getSourceRange() << getOpenMPClauseName(CKind);
21049 return false;
21050 }
21051 if (RelevantExpr)
21052 return false;
21053 return Visit(E);
21054 }
21055
21056 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
21057 // If the type of a list item is a reference to a type T then the type
21058 // will be considered to be T for all purposes of this clause.
21059 QualType CurType = BaseE->getType().getNonReferenceType();
21060
21061 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.2]
21062 // A list item cannot be a variable that is a member of a structure with
21063 // a union type.
21064 //
21065 if (CurType->isUnionType()) {
21066 if (!NoDiagnose) {
21067 SemaRef.Diag(ELoc, diag::err_omp_union_type_not_allowed)
21068 << ME->getSourceRange();
21069 return false;
21070 }
21071 return RelevantExpr || Visit(E);
21072 }
21073
21074 // If we got a member expression, we should not expect any array section
21075 // before that:
21076 //
21077 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.7]
21078 // If a list item is an element of a structure, only the rightmost symbol
21079 // of the variable reference can be an array section.
21080 //
21081 AllowUnitySizeArraySection = false;
21082 AllowWholeSizeArraySection = false;
21083
21084 // Record the component.
21085 Components.emplace_back(ME, FD, IsNonContiguous);
21086 return RelevantExpr || Visit(E);
21087 }
21088
21089 bool VisitArraySubscriptExpr(ArraySubscriptExpr *AE) {
21090 Expr *E = AE->getBase()->IgnoreParenImpCasts();
21091
21092 if (!E->getType()->isAnyPointerType() && !E->getType()->isArrayType()) {
21093 if (!NoDiagnose) {
21094 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
21095 << 0 << AE->getSourceRange();
21096 return false;
21097 }
21098 return RelevantExpr || Visit(E);
21099 }
21100
21101 // If we got an array subscript that express the whole dimension we
21102 // can have any array expressions before. If it only expressing part of
21103 // the dimension, we can only have unitary-size array expressions.
21104 if (checkArrayExpressionDoesNotReferToWholeSize(SemaRef, AE, E->getType()))
21105 AllowWholeSizeArraySection = false;
21106
21107 if (const auto *TE = dyn_cast<CXXThisExpr>(E->IgnoreParenCasts())) {
21108 Expr::EvalResult Result;
21109 if (!AE->getIdx()->isValueDependent() &&
21110 AE->getIdx()->EvaluateAsInt(Result, SemaRef.getASTContext()) &&
21111 !Result.Val.getInt().isZero()) {
21112 SemaRef.Diag(AE->getIdx()->getExprLoc(),
21113 diag::err_omp_invalid_map_this_expr);
21114 SemaRef.Diag(AE->getIdx()->getExprLoc(),
21115 diag::note_omp_invalid_subscript_on_this_ptr_map);
21116 }
21117 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr")(static_cast <bool> (!RelevantExpr && "RelevantExpr is expected to be nullptr"
) ? void (0) : __assert_fail ("!RelevantExpr && \"RelevantExpr is expected to be nullptr\""
, "clang/lib/Sema/SemaOpenMP.cpp", 21117, __extension__ __PRETTY_FUNCTION__
))
;
21118 RelevantExpr = TE;
21119 }
21120
21121 // Record the component - we don't have any declaration associated.
21122 Components.emplace_back(AE, nullptr, IsNonContiguous);
21123
21124 return RelevantExpr || Visit(E);
21125 }
21126
21127 bool VisitOMPArraySectionExpr(OMPArraySectionExpr *OASE) {
21128 // After OMP 5.0 Array section in reduction clause will be implicitly
21129 // mapped
21130 assert(!(SemaRef.getLangOpts().OpenMP < 50 && NoDiagnose) &&(static_cast <bool> (!(SemaRef.getLangOpts().OpenMP <
50 && NoDiagnose) && "Array sections cannot be implicitly mapped."
) ? void (0) : __assert_fail ("!(SemaRef.getLangOpts().OpenMP < 50 && NoDiagnose) && \"Array sections cannot be implicitly mapped.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 21131, __extension__ __PRETTY_FUNCTION__
))
21131 "Array sections cannot be implicitly mapped.")(static_cast <bool> (!(SemaRef.getLangOpts().OpenMP <
50 && NoDiagnose) && "Array sections cannot be implicitly mapped."
) ? void (0) : __assert_fail ("!(SemaRef.getLangOpts().OpenMP < 50 && NoDiagnose) && \"Array sections cannot be implicitly mapped.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 21131, __extension__ __PRETTY_FUNCTION__
))
;
21132 Expr *E = OASE->getBase()->IgnoreParenImpCasts();
21133 QualType CurType =
21134 OMPArraySectionExpr::getBaseOriginalType(E).getCanonicalType();
21135
21136 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
21137 // If the type of a list item is a reference to a type T then the type
21138 // will be considered to be T for all purposes of this clause.
21139 if (CurType->isReferenceType())
21140 CurType = CurType->getPointeeType();
21141
21142 bool IsPointer = CurType->isAnyPointerType();
21143
21144 if (!IsPointer && !CurType->isArrayType()) {
21145 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
21146 << 0 << OASE->getSourceRange();
21147 return false;
21148 }
21149
21150 bool NotWhole =
21151 checkArrayExpressionDoesNotReferToWholeSize(SemaRef, OASE, CurType);
21152 bool NotUnity =
21153 checkArrayExpressionDoesNotReferToUnitySize(SemaRef, OASE, CurType);
21154
21155 if (AllowWholeSizeArraySection) {
21156 // Any array section is currently allowed. Allowing a whole size array
21157 // section implies allowing a unity array section as well.
21158 //
21159 // If this array section refers to the whole dimension we can still
21160 // accept other array sections before this one, except if the base is a
21161 // pointer. Otherwise, only unitary sections are accepted.
21162 if (NotWhole || IsPointer)
21163 AllowWholeSizeArraySection = false;
21164 } else if (DKind == OMPD_target_update &&
21165 SemaRef.getLangOpts().OpenMP >= 50) {
21166 if (IsPointer && !AllowAnotherPtr)
21167 SemaRef.Diag(ELoc, diag::err_omp_section_length_undefined)
21168 << /*array of unknown bound */ 1;
21169 else
21170 IsNonContiguous = true;
21171 } else if (AllowUnitySizeArraySection && NotUnity) {
21172 // A unity or whole array section is not allowed and that is not
21173 // compatible with the properties of the current array section.
21174 if (NoDiagnose)
21175 return false;
21176 SemaRef.Diag(ELoc,
21177 diag::err_array_section_does_not_specify_contiguous_storage)
21178 << OASE->getSourceRange();
21179 return false;
21180 }
21181
21182 if (IsPointer)
21183 AllowAnotherPtr = false;
21184
21185 if (const auto *TE = dyn_cast<CXXThisExpr>(E)) {
21186 Expr::EvalResult ResultR;
21187 Expr::EvalResult ResultL;
21188 if (!OASE->getLength()->isValueDependent() &&
21189 OASE->getLength()->EvaluateAsInt(ResultR, SemaRef.getASTContext()) &&
21190 !ResultR.Val.getInt().isOne()) {
21191 SemaRef.Diag(OASE->getLength()->getExprLoc(),
21192 diag::err_omp_invalid_map_this_expr);
21193 SemaRef.Diag(OASE->getLength()->getExprLoc(),
21194 diag::note_omp_invalid_length_on_this_ptr_mapping);
21195 }
21196 if (OASE->getLowerBound() && !OASE->getLowerBound()->isValueDependent() &&
21197 OASE->getLowerBound()->EvaluateAsInt(ResultL,
21198 SemaRef.getASTContext()) &&
21199 !ResultL.Val.getInt().isZero()) {
21200 SemaRef.Diag(OASE->getLowerBound()->getExprLoc(),
21201 diag::err_omp_invalid_map_this_expr);
21202 SemaRef.Diag(OASE->getLowerBound()->getExprLoc(),
21203 diag::note_omp_invalid_lower_bound_on_this_ptr_mapping);
21204 }
21205 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr")(static_cast <bool> (!RelevantExpr && "RelevantExpr is expected to be nullptr"
) ? void (0) : __assert_fail ("!RelevantExpr && \"RelevantExpr is expected to be nullptr\""
, "clang/lib/Sema/SemaOpenMP.cpp", 21205, __extension__ __PRETTY_FUNCTION__
))
;
21206 RelevantExpr = TE;
21207 }
21208
21209 // Record the component - we don't have any declaration associated.
21210 Components.emplace_back(OASE, nullptr, /*IsNonContiguous=*/false);
21211 return RelevantExpr || Visit(E);
21212 }
21213 bool VisitOMPArrayShapingExpr(OMPArrayShapingExpr *E) {
21214 Expr *Base = E->getBase();
21215
21216 // Record the component - we don't have any declaration associated.
21217 Components.emplace_back(E, nullptr, IsNonContiguous);
21218
21219 return Visit(Base->IgnoreParenImpCasts());
21220 }
21221
21222 bool VisitUnaryOperator(UnaryOperator *UO) {
21223 if (SemaRef.getLangOpts().OpenMP < 50 || !UO->isLValue() ||
21224 UO->getOpcode() != UO_Deref) {
21225 emitErrorMsg();
21226 return false;
21227 }
21228 if (!RelevantExpr) {
21229 // Record the component if haven't found base decl.
21230 Components.emplace_back(UO, nullptr, /*IsNonContiguous=*/false);
21231 }
21232 return RelevantExpr || Visit(UO->getSubExpr()->IgnoreParenImpCasts());
21233 }
21234 bool VisitBinaryOperator(BinaryOperator *BO) {
21235 if (SemaRef.getLangOpts().OpenMP < 50 || !BO->getType()->isPointerType()) {
21236 emitErrorMsg();
21237 return false;
21238 }
21239
21240 // Pointer arithmetic is the only thing we expect to happen here so after we
21241 // make sure the binary operator is a pointer type, the only thing we need
21242 // to do is to visit the subtree that has the same type as root (so that we
21243 // know the other subtree is just an offset)
21244 Expr *LE = BO->getLHS()->IgnoreParenImpCasts();
21245 Expr *RE = BO->getRHS()->IgnoreParenImpCasts();
21246 Components.emplace_back(BO, nullptr, false);
21247 assert((LE->getType().getTypePtr() == BO->getType().getTypePtr() ||(static_cast <bool> ((LE->getType().getTypePtr() == BO
->getType().getTypePtr() || RE->getType().getTypePtr() ==
BO->getType().getTypePtr()) && "Either LHS or RHS have base decl inside"
) ? void (0) : __assert_fail ("(LE->getType().getTypePtr() == BO->getType().getTypePtr() || RE->getType().getTypePtr() == BO->getType().getTypePtr()) && \"Either LHS or RHS have base decl inside\""
, "clang/lib/Sema/SemaOpenMP.cpp", 21249, __extension__ __PRETTY_FUNCTION__
))
21248 RE->getType().getTypePtr() == BO->getType().getTypePtr()) &&(static_cast <bool> ((LE->getType().getTypePtr() == BO
->getType().getTypePtr() || RE->getType().getTypePtr() ==
BO->getType().getTypePtr()) && "Either LHS or RHS have base decl inside"
) ? void (0) : __assert_fail ("(LE->getType().getTypePtr() == BO->getType().getTypePtr() || RE->getType().getTypePtr() == BO->getType().getTypePtr()) && \"Either LHS or RHS have base decl inside\""
, "clang/lib/Sema/SemaOpenMP.cpp", 21249, __extension__ __PRETTY_FUNCTION__
))
21249 "Either LHS or RHS have base decl inside")(static_cast <bool> ((LE->getType().getTypePtr() == BO
->getType().getTypePtr() || RE->getType().getTypePtr() ==
BO->getType().getTypePtr()) && "Either LHS or RHS have base decl inside"
) ? void (0) : __assert_fail ("(LE->getType().getTypePtr() == BO->getType().getTypePtr() || RE->getType().getTypePtr() == BO->getType().getTypePtr()) && \"Either LHS or RHS have base decl inside\""
, "clang/lib/Sema/SemaOpenMP.cpp", 21249, __extension__ __PRETTY_FUNCTION__
))
;
21250 if (BO->getType().getTypePtr() == LE->getType().getTypePtr())
21251 return RelevantExpr || Visit(LE);
21252 return RelevantExpr || Visit(RE);
21253 }
21254 bool VisitCXXThisExpr(CXXThisExpr *CTE) {
21255 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr")(static_cast <bool> (!RelevantExpr && "RelevantExpr is expected to be nullptr"
) ? void (0) : __assert_fail ("!RelevantExpr && \"RelevantExpr is expected to be nullptr\""
, "clang/lib/Sema/SemaOpenMP.cpp", 21255, __extension__ __PRETTY_FUNCTION__
))
;
21256 RelevantExpr = CTE;
21257 Components.emplace_back(CTE, nullptr, IsNonContiguous);
21258 return true;
21259 }
21260 bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *COCE) {
21261 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr")(static_cast <bool> (!RelevantExpr && "RelevantExpr is expected to be nullptr"
) ? void (0) : __assert_fail ("!RelevantExpr && \"RelevantExpr is expected to be nullptr\""
, "clang/lib/Sema/SemaOpenMP.cpp", 21261, __extension__ __PRETTY_FUNCTION__
))
;
21262 Components.emplace_back(COCE, nullptr, IsNonContiguous);
21263 return true;
21264 }
21265 bool VisitOpaqueValueExpr(OpaqueValueExpr *E) {
21266 Expr *Source = E->getSourceExpr();
21267 if (!Source) {
21268 emitErrorMsg();
21269 return false;
21270 }
21271 return Visit(Source);
21272 }
21273 bool VisitStmt(Stmt *) {
21274 emitErrorMsg();
21275 return false;
21276 }
21277 const Expr *getFoundBase() const { return RelevantExpr; }
21278 explicit MapBaseChecker(
21279 Sema &SemaRef, OpenMPClauseKind CKind, OpenMPDirectiveKind DKind,
21280 OMPClauseMappableExprCommon::MappableExprComponentList &Components,
21281 bool NoDiagnose, SourceLocation &ELoc, SourceRange &ERange)
21282 : SemaRef(SemaRef), CKind(CKind), DKind(DKind), Components(Components),
21283 NoDiagnose(NoDiagnose), ELoc(ELoc), ERange(ERange) {}
21284};
21285} // namespace
21286
21287/// Return the expression of the base of the mappable expression or null if it
21288/// cannot be determined and do all the necessary checks to see if the
21289/// expression is valid as a standalone mappable expression. In the process,
21290/// record all the components of the expression.
21291static const Expr *checkMapClauseExpressionBase(
21292 Sema &SemaRef, Expr *E,
21293 OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents,
21294 OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose) {
21295 SourceLocation ELoc = E->getExprLoc();
21296 SourceRange ERange = E->getSourceRange();
21297 MapBaseChecker Checker(SemaRef, CKind, DKind, CurComponents, NoDiagnose, ELoc,
21298 ERange);
21299 if (Checker.Visit(E->IgnoreParens())) {
21300 // Check if the highest dimension array section has length specified
21301 if (SemaRef.getLangOpts().OpenMP >= 50 && !CurComponents.empty() &&
21302 (CKind == OMPC_to || CKind == OMPC_from)) {
21303 auto CI = CurComponents.rbegin();
21304 auto CE = CurComponents.rend();
21305 for (; CI != CE; ++CI) {
21306 const auto *OASE =
21307 dyn_cast<OMPArraySectionExpr>(CI->getAssociatedExpression());
21308 if (!OASE)
21309 continue;
21310 if (OASE && OASE->getLength())
21311 break;
21312 SemaRef.Diag(ELoc, diag::err_array_section_does_not_specify_length)
21313 << ERange;
21314 }
21315 }
21316 return Checker.getFoundBase();
21317 }
21318 return nullptr;
21319}
21320
21321// Return true if expression E associated with value VD has conflicts with other
21322// map information.
21323static bool checkMapConflicts(
21324 Sema &SemaRef, DSAStackTy *DSAS, const ValueDecl *VD, const Expr *E,
21325 bool CurrentRegionOnly,
21326 OMPClauseMappableExprCommon::MappableExprComponentListRef CurComponents,
21327 OpenMPClauseKind CKind) {
21328 assert(VD && E)(static_cast <bool> (VD && E) ? void (0) : __assert_fail
("VD && E", "clang/lib/Sema/SemaOpenMP.cpp", 21328, __extension__
__PRETTY_FUNCTION__))
;
21329 SourceLocation ELoc = E->getExprLoc();
21330 SourceRange ERange = E->getSourceRange();
21331
21332 // In order to easily check the conflicts we need to match each component of
21333 // the expression under test with the components of the expressions that are
21334 // already in the stack.
21335
21336 assert(!CurComponents.empty() && "Map clause expression with no components!")(static_cast <bool> (!CurComponents.empty() && "Map clause expression with no components!"
) ? void (0) : __assert_fail ("!CurComponents.empty() && \"Map clause expression with no components!\""
, "clang/lib/Sema/SemaOpenMP.cpp", 21336, __extension__ __PRETTY_FUNCTION__
))
;
21337 assert(CurComponents.back().getAssociatedDeclaration() == VD &&(static_cast <bool> (CurComponents.back().getAssociatedDeclaration
() == VD && "Map clause expression with unexpected base!"
) ? void (0) : __assert_fail ("CurComponents.back().getAssociatedDeclaration() == VD && \"Map clause expression with unexpected base!\""
, "clang/lib/Sema/SemaOpenMP.cpp", 21338, __extension__ __PRETTY_FUNCTION__
))
21338 "Map clause expression with unexpected base!")(static_cast <bool> (CurComponents.back().getAssociatedDeclaration
() == VD && "Map clause expression with unexpected base!"
) ? void (0) : __assert_fail ("CurComponents.back().getAssociatedDeclaration() == VD && \"Map clause expression with unexpected base!\""
, "clang/lib/Sema/SemaOpenMP.cpp", 21338, __extension__ __PRETTY_FUNCTION__
))
;
21339
21340 // Variables to help detecting enclosing problems in data environment nests.
21341 bool IsEnclosedByDataEnvironmentExpr = false;
21342 const Expr *EnclosingExpr = nullptr;
21343
21344 bool FoundError = DSAS->checkMappableExprComponentListsForDecl(
21345 VD, CurrentRegionOnly,
21346 [&IsEnclosedByDataEnvironmentExpr, &SemaRef, VD, CurrentRegionOnly, ELoc,
21347 ERange, CKind, &EnclosingExpr,
21348 CurComponents](OMPClauseMappableExprCommon::MappableExprComponentListRef
21349 StackComponents,
21350 OpenMPClauseKind Kind) {
21351 if (CKind == Kind && SemaRef.LangOpts.OpenMP >= 50)
21352 return false;
21353 assert(!StackComponents.empty() &&(static_cast <bool> (!StackComponents.empty() &&
"Map clause expression with no components!") ? void (0) : __assert_fail
("!StackComponents.empty() && \"Map clause expression with no components!\""
, "clang/lib/Sema/SemaOpenMP.cpp", 21354, __extension__ __PRETTY_FUNCTION__
))
21354 "Map clause expression with no components!")(static_cast <bool> (!StackComponents.empty() &&
"Map clause expression with no components!") ? void (0) : __assert_fail
("!StackComponents.empty() && \"Map clause expression with no components!\""
, "clang/lib/Sema/SemaOpenMP.cpp", 21354, __extension__ __PRETTY_FUNCTION__
))
;
21355 assert(StackComponents.back().getAssociatedDeclaration() == VD &&(static_cast <bool> (StackComponents.back().getAssociatedDeclaration
() == VD && "Map clause expression with unexpected base!"
) ? void (0) : __assert_fail ("StackComponents.back().getAssociatedDeclaration() == VD && \"Map clause expression with unexpected base!\""
, "clang/lib/Sema/SemaOpenMP.cpp", 21356, __extension__ __PRETTY_FUNCTION__
))
21356 "Map clause expression with unexpected base!")(static_cast <bool> (StackComponents.back().getAssociatedDeclaration
() == VD && "Map clause expression with unexpected base!"
) ? void (0) : __assert_fail ("StackComponents.back().getAssociatedDeclaration() == VD && \"Map clause expression with unexpected base!\""
, "clang/lib/Sema/SemaOpenMP.cpp", 21356, __extension__ __PRETTY_FUNCTION__
))
;
21357 (void)VD;
21358
21359 // The whole expression in the stack.
21360 const Expr *RE = StackComponents.front().getAssociatedExpression();
21361
21362 // Expressions must start from the same base. Here we detect at which
21363 // point both expressions diverge from each other and see if we can
21364 // detect if the memory referred to both expressions is contiguous and
21365 // do not overlap.
21366 auto CI = CurComponents.rbegin();
21367 auto CE = CurComponents.rend();
21368 auto SI = StackComponents.rbegin();
21369 auto SE = StackComponents.rend();
21370 for (; CI != CE && SI != SE; ++CI, ++SI) {
21371
21372 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.3]
21373 // At most one list item can be an array item derived from a given
21374 // variable in map clauses of the same construct.
21375 if (CurrentRegionOnly &&
21376 (isa<ArraySubscriptExpr>(CI->getAssociatedExpression()) ||
21377 isa<OMPArraySectionExpr>(CI->getAssociatedExpression()) ||
21378 isa<OMPArrayShapingExpr>(CI->getAssociatedExpression())) &&
21379 (isa<ArraySubscriptExpr>(SI->getAssociatedExpression()) ||
21380 isa<OMPArraySectionExpr>(SI->getAssociatedExpression()) ||
21381 isa<OMPArrayShapingExpr>(SI->getAssociatedExpression()))) {
21382 SemaRef.Diag(CI->getAssociatedExpression()->getExprLoc(),
21383 diag::err_omp_multiple_array_items_in_map_clause)
21384 << CI->getAssociatedExpression()->getSourceRange();
21385 SemaRef.Diag(SI->getAssociatedExpression()->getExprLoc(),
21386 diag::note_used_here)
21387 << SI->getAssociatedExpression()->getSourceRange();
21388 return true;
21389 }
21390
21391 // Do both expressions have the same kind?
21392 if (CI->getAssociatedExpression()->getStmtClass() !=
21393 SI->getAssociatedExpression()->getStmtClass())
21394 break;
21395
21396 // Are we dealing with different variables/fields?
21397 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
21398 break;
21399 }
21400 // Check if the extra components of the expressions in the enclosing
21401 // data environment are redundant for the current base declaration.
21402 // If they are, the maps completely overlap, which is legal.
21403 for (; SI != SE; ++SI) {
21404 QualType Type;
21405 if (const auto *ASE =
21406 dyn_cast<ArraySubscriptExpr>(SI->getAssociatedExpression())) {
21407 Type = ASE->getBase()->IgnoreParenImpCasts()->getType();
21408 } else if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(
21409 SI->getAssociatedExpression())) {
21410 const Expr *E = OASE->getBase()->IgnoreParenImpCasts();
21411 Type =
21412 OMPArraySectionExpr::getBaseOriginalType(E).getCanonicalType();
21413 } else if (const auto *OASE = dyn_cast<OMPArrayShapingExpr>(
21414 SI->getAssociatedExpression())) {
21415 Type = OASE->getBase()->getType()->getPointeeType();
21416 }
21417 if (Type.isNull() || Type->isAnyPointerType() ||
21418 checkArrayExpressionDoesNotReferToWholeSize(
21419 SemaRef, SI->getAssociatedExpression(), Type))
21420 break;
21421 }
21422
21423 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
21424 // List items of map clauses in the same construct must not share
21425 // original storage.
21426 //
21427 // If the expressions are exactly the same or one is a subset of the
21428 // other, it means they are sharing storage.
21429 if (CI == CE && SI == SE) {
21430 if (CurrentRegionOnly) {
21431 if (CKind == OMPC_map) {
21432 SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
21433 } else {
21434 assert(CKind == OMPC_to || CKind == OMPC_from)(static_cast <bool> (CKind == OMPC_to || CKind == OMPC_from
) ? void (0) : __assert_fail ("CKind == OMPC_to || CKind == OMPC_from"
, "clang/lib/Sema/SemaOpenMP.cpp", 21434, __extension__ __PRETTY_FUNCTION__
))
;
21435 SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
21436 << ERange;
21437 }
21438 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
21439 << RE->getSourceRange();
21440 return true;
21441 }
21442 // If we find the same expression in the enclosing data environment,
21443 // that is legal.
21444 IsEnclosedByDataEnvironmentExpr = true;
21445 return false;
21446 }
21447
21448 QualType DerivedType =
21449 std::prev(CI)->getAssociatedDeclaration()->getType();
21450 SourceLocation DerivedLoc =
21451 std::prev(CI)->getAssociatedExpression()->getExprLoc();
21452
21453 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
21454 // If the type of a list item is a reference to a type T then the type
21455 // will be considered to be T for all purposes of this clause.
21456 DerivedType = DerivedType.getNonReferenceType();
21457
21458 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.1]
21459 // A variable for which the type is pointer and an array section
21460 // derived from that variable must not appear as list items of map
21461 // clauses of the same construct.
21462 //
21463 // Also, cover one of the cases in:
21464 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
21465 // If any part of the original storage of a list item has corresponding
21466 // storage in the device data environment, all of the original storage
21467 // must have corresponding storage in the device data environment.
21468 //
21469 if (DerivedType->isAnyPointerType()) {
21470 if (CI == CE || SI == SE) {
21471 SemaRef.Diag(
21472 DerivedLoc,
21473 diag::err_omp_pointer_mapped_along_with_derived_section)
21474 << DerivedLoc;
21475 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
21476 << RE->getSourceRange();
21477 return true;
21478 }
21479 if (CI->getAssociatedExpression()->getStmtClass() !=
21480 SI->getAssociatedExpression()->getStmtClass() ||
21481 CI->getAssociatedDeclaration()->getCanonicalDecl() ==
21482 SI->getAssociatedDeclaration()->getCanonicalDecl()) {
21483 assert(CI != CE && SI != SE)(static_cast <bool> (CI != CE && SI != SE) ? void
(0) : __assert_fail ("CI != CE && SI != SE", "clang/lib/Sema/SemaOpenMP.cpp"
, 21483, __extension__ __PRETTY_FUNCTION__))
;
21484 SemaRef.Diag(DerivedLoc, diag::err_omp_same_pointer_dereferenced)
21485 << DerivedLoc;
21486 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
21487 << RE->getSourceRange();
21488 return true;
21489 }
21490 }
21491
21492 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
21493 // List items of map clauses in the same construct must not share
21494 // original storage.
21495 //
21496 // An expression is a subset of the other.
21497 if (CurrentRegionOnly && (CI == CE || SI == SE)) {
21498 if (CKind == OMPC_map) {
21499 if (CI != CE || SI != SE) {
21500 // Allow constructs like this: map(s, s.ptr[0:1]), where s.ptr is
21501 // a pointer.
21502 auto Begin =
21503 CI != CE ? CurComponents.begin() : StackComponents.begin();
21504 auto End = CI != CE ? CurComponents.end() : StackComponents.end();
21505 auto It = Begin;
21506 while (It != End && !It->getAssociatedDeclaration())
21507 std::advance(It, 1);
21508 assert(It != End &&(static_cast <bool> (It != End && "Expected at least one component with the declaration."
) ? void (0) : __assert_fail ("It != End && \"Expected at least one component with the declaration.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 21509, __extension__ __PRETTY_FUNCTION__
))
21509 "Expected at least one component with the declaration.")(static_cast <bool> (It != End && "Expected at least one component with the declaration."
) ? void (0) : __assert_fail ("It != End && \"Expected at least one component with the declaration.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 21509, __extension__ __PRETTY_FUNCTION__
))
;
21510 if (It != Begin && It->getAssociatedDeclaration()
21511 ->getType()
21512 .getCanonicalType()
21513 ->isAnyPointerType()) {
21514 IsEnclosedByDataEnvironmentExpr = false;
21515 EnclosingExpr = nullptr;
21516 return false;
21517 }
21518 }
21519 SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
21520 } else {
21521 assert(CKind == OMPC_to || CKind == OMPC_from)(static_cast <bool> (CKind == OMPC_to || CKind == OMPC_from
) ? void (0) : __assert_fail ("CKind == OMPC_to || CKind == OMPC_from"
, "clang/lib/Sema/SemaOpenMP.cpp", 21521, __extension__ __PRETTY_FUNCTION__
))
;
21522 SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
21523 << ERange;
21524 }
21525 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
21526 << RE->getSourceRange();
21527 return true;
21528 }
21529
21530 // The current expression uses the same base as other expression in the
21531 // data environment but does not contain it completely.
21532 if (!CurrentRegionOnly && SI != SE)
21533 EnclosingExpr = RE;
21534
21535 // The current expression is a subset of the expression in the data
21536 // environment.
21537 IsEnclosedByDataEnvironmentExpr |=
21538 (!CurrentRegionOnly && CI != CE && SI == SE);
21539
21540 return false;
21541 });
21542
21543 if (CurrentRegionOnly)
21544 return FoundError;
21545
21546 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
21547 // If any part of the original storage of a list item has corresponding
21548 // storage in the device data environment, all of the original storage must
21549 // have corresponding storage in the device data environment.
21550 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.6]
21551 // If a list item is an element of a structure, and a different element of
21552 // the structure has a corresponding list item in the device data environment
21553 // prior to a task encountering the construct associated with the map clause,
21554 // then the list item must also have a corresponding list item in the device
21555 // data environment prior to the task encountering the construct.
21556 //
21557 if (EnclosingExpr && !IsEnclosedByDataEnvironmentExpr) {
21558 SemaRef.Diag(ELoc,
21559 diag::err_omp_original_storage_is_shared_and_does_not_contain)
21560 << ERange;
21561 SemaRef.Diag(EnclosingExpr->getExprLoc(), diag::note_used_here)
21562 << EnclosingExpr->getSourceRange();
21563 return true;
21564 }
21565
21566 return FoundError;
21567}
21568
21569// Look up the user-defined mapper given the mapper name and mapped type, and
21570// build a reference to it.
21571static ExprResult buildUserDefinedMapperRef(Sema &SemaRef, Scope *S,
21572 CXXScopeSpec &MapperIdScopeSpec,
21573 const DeclarationNameInfo &MapperId,
21574 QualType Type,
21575 Expr *UnresolvedMapper) {
21576 if (MapperIdScopeSpec.isInvalid())
21577 return ExprError();
21578 // Get the actual type for the array type.
21579 if (Type->isArrayType()) {
21580 assert(Type->getAsArrayTypeUnsafe() && "Expect to get a valid array type")(static_cast <bool> (Type->getAsArrayTypeUnsafe() &&
"Expect to get a valid array type") ? void (0) : __assert_fail
("Type->getAsArrayTypeUnsafe() && \"Expect to get a valid array type\""
, "clang/lib/Sema/SemaOpenMP.cpp", 21580, __extension__ __PRETTY_FUNCTION__
))
;
21581 Type = Type->getAsArrayTypeUnsafe()->getElementType().getCanonicalType();
21582 }
21583 // Find all user-defined mappers with the given MapperId.
21584 SmallVector<UnresolvedSet<8>, 4> Lookups;
21585 LookupResult Lookup(SemaRef, MapperId, Sema::LookupOMPMapperName);
21586 Lookup.suppressDiagnostics();
21587 if (S) {
21588 while (S && SemaRef.LookupParsedName(Lookup, S, &MapperIdScopeSpec)) {
21589 NamedDecl *D = Lookup.getRepresentativeDecl();
21590 while (S && !S->isDeclScope(D))
21591 S = S->getParent();
21592 if (S)
21593 S = S->getParent();
21594 Lookups.emplace_back();
21595 Lookups.back().append(Lookup.begin(), Lookup.end());
21596 Lookup.clear();
21597 }
21598 } else if (auto *ULE = cast_or_null<UnresolvedLookupExpr>(UnresolvedMapper)) {
21599 // Extract the user-defined mappers with the given MapperId.
21600 Lookups.push_back(UnresolvedSet<8>());
21601 for (NamedDecl *D : ULE->decls()) {
21602 auto *DMD = cast<OMPDeclareMapperDecl>(D);
21603 assert(DMD && "Expect valid OMPDeclareMapperDecl during instantiation.")(static_cast <bool> (DMD && "Expect valid OMPDeclareMapperDecl during instantiation."
) ? void (0) : __assert_fail ("DMD && \"Expect valid OMPDeclareMapperDecl during instantiation.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 21603, __extension__ __PRETTY_FUNCTION__
))
;
21604 Lookups.back().addDecl(DMD);
21605 }
21606 }
21607 // Defer the lookup for dependent types. The results will be passed through
21608 // UnresolvedMapper on instantiation.
21609 if (SemaRef.CurContext->isDependentContext() || Type->isDependentType() ||
21610 Type->isInstantiationDependentType() ||
21611 Type->containsUnexpandedParameterPack() ||
21612 filterLookupForUDReductionAndMapper<bool>(Lookups, [](ValueDecl *D) {
21613 return !D->isInvalidDecl() &&
21614 (D->getType()->isDependentType() ||
21615 D->getType()->isInstantiationDependentType() ||
21616 D->getType()->containsUnexpandedParameterPack());
21617 })) {
21618 UnresolvedSet<8> URS;
21619 for (const UnresolvedSet<8> &Set : Lookups) {
21620 if (Set.empty())
21621 continue;
21622 URS.append(Set.begin(), Set.end());
21623 }
21624 return UnresolvedLookupExpr::Create(
21625 SemaRef.Context, /*NamingClass=*/nullptr,
21626 MapperIdScopeSpec.getWithLocInContext(SemaRef.Context), MapperId,
21627 /*ADL=*/false, /*Overloaded=*/true, URS.begin(), URS.end());
21628 }
21629 SourceLocation Loc = MapperId.getLoc();
21630 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
21631 // The type must be of struct, union or class type in C and C++
21632 if (!Type->isStructureOrClassType() && !Type->isUnionType() &&
21633 (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default")) {
21634 SemaRef.Diag(Loc, diag::err_omp_mapper_wrong_type);
21635 return ExprError();
21636 }
21637 // Perform argument dependent lookup.
21638 if (SemaRef.getLangOpts().CPlusPlus && !MapperIdScopeSpec.isSet())
21639 argumentDependentLookup(SemaRef, MapperId, Loc, Type, Lookups);
21640 // Return the first user-defined mapper with the desired type.
21641 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
21642 Lookups, [&SemaRef, Type](ValueDecl *D) -> ValueDecl * {
21643 if (!D->isInvalidDecl() &&
21644 SemaRef.Context.hasSameType(D->getType(), Type))
21645 return D;
21646 return nullptr;
21647 }))
21648 return SemaRef.BuildDeclRefExpr(VD, Type, VK_LValue, Loc);
21649 // Find the first user-defined mapper with a type derived from the desired
21650 // type.
21651 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
21652 Lookups, [&SemaRef, Type, Loc](ValueDecl *D) -> ValueDecl * {
21653 if (!D->isInvalidDecl() &&
21654 SemaRef.IsDerivedFrom(Loc, Type, D->getType()) &&
21655 !Type.isMoreQualifiedThan(D->getType()))
21656 return D;
21657 return nullptr;
21658 })) {
21659 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
21660 /*DetectVirtual=*/false);
21661 if (SemaRef.IsDerivedFrom(Loc, Type, VD->getType(), Paths)) {
21662 if (!Paths.isAmbiguous(SemaRef.Context.getCanonicalType(
21663 VD->getType().getUnqualifiedType()))) {
21664 if (SemaRef.CheckBaseClassAccess(
21665 Loc, VD->getType(), Type, Paths.front(),
21666 /*DiagID=*/0) != Sema::AR_inaccessible) {
21667 return SemaRef.BuildDeclRefExpr(VD, Type, VK_LValue, Loc);
21668 }
21669 }
21670 }
21671 }
21672 // Report error if a mapper is specified, but cannot be found.
21673 if (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default") {
21674 SemaRef.Diag(Loc, diag::err_omp_invalid_mapper)
21675 << Type << MapperId.getName();
21676 return ExprError();
21677 }
21678 return ExprEmpty();
21679}
21680
21681namespace {
21682// Utility struct that gathers all the related lists associated with a mappable
21683// expression.
21684struct MappableVarListInfo {
21685 // The list of expressions.
21686 ArrayRef<Expr *> VarList;
21687 // The list of processed expressions.
21688 SmallVector<Expr *, 16> ProcessedVarList;
21689 // The mappble components for each expression.
21690 OMPClauseMappableExprCommon::MappableExprComponentLists VarComponents;
21691 // The base declaration of the variable.
21692 SmallVector<ValueDecl *, 16> VarBaseDeclarations;
21693 // The reference to the user-defined mapper associated with every expression.
21694 SmallVector<Expr *, 16> UDMapperList;
21695
21696 MappableVarListInfo(ArrayRef<Expr *> VarList) : VarList(VarList) {
21697 // We have a list of components and base declarations for each entry in the
21698 // variable list.
21699 VarComponents.reserve(VarList.size());
21700 VarBaseDeclarations.reserve(VarList.size());
21701 }
21702};
21703} // namespace
21704
21705// Check the validity of the provided variable list for the provided clause kind
21706// \a CKind. In the check process the valid expressions, mappable expression
21707// components, variables, and user-defined mappers are extracted and used to
21708// fill \a ProcessedVarList, \a VarComponents, \a VarBaseDeclarations, and \a
21709// UDMapperList in MVLI. \a MapType, \a IsMapTypeImplicit, \a MapperIdScopeSpec,
21710// and \a MapperId are expected to be valid if the clause kind is 'map'.
21711static void checkMappableExpressionList(
21712 Sema &SemaRef, DSAStackTy *DSAS, OpenMPClauseKind CKind,
21713 MappableVarListInfo &MVLI, SourceLocation StartLoc,
21714 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo MapperId,
21715 ArrayRef<Expr *> UnresolvedMappers,
21716 OpenMPMapClauseKind MapType = OMPC_MAP_unknown,
21717 ArrayRef<OpenMPMapModifierKind> Modifiers = std::nullopt,
21718 bool IsMapTypeImplicit = false, bool NoDiagnose = false) {
21719 // We only expect mappable expressions in 'to', 'from', and 'map' clauses.
21720 assert((CKind == OMPC_map || CKind == OMPC_to || CKind == OMPC_from) &&(static_cast <bool> ((CKind == OMPC_map || CKind == OMPC_to
|| CKind == OMPC_from) && "Unexpected clause kind with mappable expressions!"
) ? void (0) : __assert_fail ("(CKind == OMPC_map || CKind == OMPC_to || CKind == OMPC_from) && \"Unexpected clause kind with mappable expressions!\""
, "clang/lib/Sema/SemaOpenMP.cpp", 21721, __extension__ __PRETTY_FUNCTION__
))
21721 "Unexpected clause kind with mappable expressions!")(static_cast <bool> ((CKind == OMPC_map || CKind == OMPC_to
|| CKind == OMPC_from) && "Unexpected clause kind with mappable expressions!"
) ? void (0) : __assert_fail ("(CKind == OMPC_map || CKind == OMPC_to || CKind == OMPC_from) && \"Unexpected clause kind with mappable expressions!\""
, "clang/lib/Sema/SemaOpenMP.cpp", 21721, __extension__ __PRETTY_FUNCTION__
))
;
21722
21723 // If the identifier of user-defined mapper is not specified, it is "default".
21724 // We do not change the actual name in this clause to distinguish whether a
21725 // mapper is specified explicitly, i.e., it is not explicitly specified when
21726 // MapperId.getName() is empty.
21727 if (!MapperId.getName() || MapperId.getName().isEmpty()) {
21728 auto &DeclNames = SemaRef.getASTContext().DeclarationNames;
21729 MapperId.setName(DeclNames.getIdentifier(
21730 &SemaRef.getASTContext().Idents.get("default")));
21731 MapperId.setLoc(StartLoc);
21732 }
21733
21734 // Iterators to find the current unresolved mapper expression.
21735 auto UMIt = UnresolvedMappers.begin(), UMEnd = UnresolvedMappers.end();
21736 bool UpdateUMIt = false;
21737 Expr *UnresolvedMapper = nullptr;
21738
21739 bool HasHoldModifier =
21740 llvm::is_contained(Modifiers, OMPC_MAP_MODIFIER_ompx_hold);
21741
21742 // Keep track of the mappable components and base declarations in this clause.
21743 // Each entry in the list is going to have a list of components associated. We
21744 // record each set of the components so that we can build the clause later on.
21745 // In the end we should have the same amount of declarations and component
21746 // lists.
21747
21748 for (Expr *RE : MVLI.VarList) {
21749 assert(RE && "Null expr in omp to/from/map clause")(static_cast <bool> (RE && "Null expr in omp to/from/map clause"
) ? void (0) : __assert_fail ("RE && \"Null expr in omp to/from/map clause\""
, "clang/lib/Sema/SemaOpenMP.cpp", 21749, __extension__ __PRETTY_FUNCTION__
))
;
21750 SourceLocation ELoc = RE->getExprLoc();
21751
21752 // Find the current unresolved mapper expression.
21753 if (UpdateUMIt && UMIt != UMEnd) {
21754 UMIt++;
21755 assert((static_cast <bool> (UMIt != UMEnd && "Expect the size of UnresolvedMappers to match with that of VarList"
) ? void (0) : __assert_fail ("UMIt != UMEnd && \"Expect the size of UnresolvedMappers to match with that of VarList\""
, "clang/lib/Sema/SemaOpenMP.cpp", 21757, __extension__ __PRETTY_FUNCTION__
))
21756 UMIt != UMEnd &&(static_cast <bool> (UMIt != UMEnd && "Expect the size of UnresolvedMappers to match with that of VarList"
) ? void (0) : __assert_fail ("UMIt != UMEnd && \"Expect the size of UnresolvedMappers to match with that of VarList\""
, "clang/lib/Sema/SemaOpenMP.cpp", 21757, __extension__ __PRETTY_FUNCTION__
))
21757 "Expect the size of UnresolvedMappers to match with that of VarList")(static_cast <bool> (UMIt != UMEnd && "Expect the size of UnresolvedMappers to match with that of VarList"
) ? void (0) : __assert_fail ("UMIt != UMEnd && \"Expect the size of UnresolvedMappers to match with that of VarList\""
, "clang/lib/Sema/SemaOpenMP.cpp", 21757, __extension__ __PRETTY_FUNCTION__
))
;
21758 }
21759 UpdateUMIt = true;
21760 if (UMIt != UMEnd)
21761 UnresolvedMapper = *UMIt;
21762
21763 const Expr *VE = RE->IgnoreParenLValueCasts();
21764
21765 if (VE->isValueDependent() || VE->isTypeDependent() ||
21766 VE->isInstantiationDependent() ||
21767 VE->containsUnexpandedParameterPack()) {
21768 // Try to find the associated user-defined mapper.
21769 ExprResult ER = buildUserDefinedMapperRef(
21770 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
21771 VE->getType().getCanonicalType(), UnresolvedMapper);
21772 if (ER.isInvalid())
21773 continue;
21774 MVLI.UDMapperList.push_back(ER.get());
21775 // We can only analyze this information once the missing information is
21776 // resolved.
21777 MVLI.ProcessedVarList.push_back(RE);
21778 continue;
21779 }
21780
21781 Expr *SimpleExpr = RE->IgnoreParenCasts();
21782
21783 if (!RE->isLValue()) {
21784 if (SemaRef.getLangOpts().OpenMP < 50) {
21785 SemaRef.Diag(
21786 ELoc, diag::err_omp_expected_named_var_member_or_array_expression)
21787 << RE->getSourceRange();
21788 } else {
21789 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
21790 << getOpenMPClauseName(CKind) << RE->getSourceRange();
21791 }
21792 continue;
21793 }
21794
21795 OMPClauseMappableExprCommon::MappableExprComponentList CurComponents;
21796 ValueDecl *CurDeclaration = nullptr;
21797
21798 // Obtain the array or member expression bases if required. Also, fill the
21799 // components array with all the components identified in the process.
21800 const Expr *BE =
21801 checkMapClauseExpressionBase(SemaRef, SimpleExpr, CurComponents, CKind,
21802 DSAS->getCurrentDirective(), NoDiagnose);
21803 if (!BE)
21804 continue;
21805
21806 assert(!CurComponents.empty() &&(static_cast <bool> (!CurComponents.empty() && "Invalid mappable expression information."
) ? void (0) : __assert_fail ("!CurComponents.empty() && \"Invalid mappable expression information.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 21807, __extension__ __PRETTY_FUNCTION__
))
21807 "Invalid mappable expression information.")(static_cast <bool> (!CurComponents.empty() && "Invalid mappable expression information."
) ? void (0) : __assert_fail ("!CurComponents.empty() && \"Invalid mappable expression information.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 21807, __extension__ __PRETTY_FUNCTION__
))
;
21808
21809 if (const auto *TE = dyn_cast<CXXThisExpr>(BE)) {
21810 // Add store "this" pointer to class in DSAStackTy for future checking
21811 DSAS->addMappedClassesQualTypes(TE->getType());
21812 // Try to find the associated user-defined mapper.
21813 ExprResult ER = buildUserDefinedMapperRef(
21814 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
21815 VE->getType().getCanonicalType(), UnresolvedMapper);
21816 if (ER.isInvalid())
21817 continue;
21818 MVLI.UDMapperList.push_back(ER.get());
21819 // Skip restriction checking for variable or field declarations
21820 MVLI.ProcessedVarList.push_back(RE);
21821 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
21822 MVLI.VarComponents.back().append(CurComponents.begin(),
21823 CurComponents.end());
21824 MVLI.VarBaseDeclarations.push_back(nullptr);
21825 continue;
21826 }
21827
21828 // For the following checks, we rely on the base declaration which is
21829 // expected to be associated with the last component. The declaration is
21830 // expected to be a variable or a field (if 'this' is being mapped).
21831 CurDeclaration = CurComponents.back().getAssociatedDeclaration();
21832 assert(CurDeclaration && "Null decl on map clause.")(static_cast <bool> (CurDeclaration && "Null decl on map clause."
) ? void (0) : __assert_fail ("CurDeclaration && \"Null decl on map clause.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 21832, __extension__ __PRETTY_FUNCTION__
))
;
21833 assert((static_cast <bool> (CurDeclaration->isCanonicalDecl
() && "Expecting components to have associated only canonical declarations."
) ? void (0) : __assert_fail ("CurDeclaration->isCanonicalDecl() && \"Expecting components to have associated only canonical declarations.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 21835, __extension__ __PRETTY_FUNCTION__
))
21834 CurDeclaration->isCanonicalDecl() &&(static_cast <bool> (CurDeclaration->isCanonicalDecl
() && "Expecting components to have associated only canonical declarations."
) ? void (0) : __assert_fail ("CurDeclaration->isCanonicalDecl() && \"Expecting components to have associated only canonical declarations.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 21835, __extension__ __PRETTY_FUNCTION__
))
21835 "Expecting components to have associated only canonical declarations.")(static_cast <bool> (CurDeclaration->isCanonicalDecl
() && "Expecting components to have associated only canonical declarations."
) ? void (0) : __assert_fail ("CurDeclaration->isCanonicalDecl() && \"Expecting components to have associated only canonical declarations.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 21835, __extension__ __PRETTY_FUNCTION__
))
;
21836
21837 auto *VD = dyn_cast<VarDecl>(CurDeclaration);
21838 const auto *FD = dyn_cast<FieldDecl>(CurDeclaration);
21839
21840 assert((VD || FD) && "Only variables or fields are expected here!")(static_cast <bool> ((VD || FD) && "Only variables or fields are expected here!"
) ? void (0) : __assert_fail ("(VD || FD) && \"Only variables or fields are expected here!\""
, "clang/lib/Sema/SemaOpenMP.cpp", 21840, __extension__ __PRETTY_FUNCTION__
))
;
21841 (void)FD;
21842
21843 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.10]
21844 // threadprivate variables cannot appear in a map clause.
21845 // OpenMP 4.5 [2.10.5, target update Construct]
21846 // threadprivate variables cannot appear in a from clause.
21847 if (VD && DSAS->isThreadPrivate(VD)) {
21848 if (NoDiagnose)
21849 continue;
21850 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false);
21851 SemaRef.Diag(ELoc, diag::err_omp_threadprivate_in_clause)
21852 << getOpenMPClauseName(CKind);
21853 reportOriginalDsa(SemaRef, DSAS, VD, DVar);
21854 continue;
21855 }
21856
21857 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
21858 // A list item cannot appear in both a map clause and a data-sharing
21859 // attribute clause on the same construct.
21860
21861 // Check conflicts with other map clause expressions. We check the conflicts
21862 // with the current construct separately from the enclosing data
21863 // environment, because the restrictions are different. We only have to
21864 // check conflicts across regions for the map clauses.
21865 if (checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
21866 /*CurrentRegionOnly=*/true, CurComponents, CKind))
21867 break;
21868 if (CKind == OMPC_map &&
21869 (SemaRef.getLangOpts().OpenMP <= 45 || StartLoc.isValid()) &&
21870 checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
21871 /*CurrentRegionOnly=*/false, CurComponents, CKind))
21872 break;
21873
21874 // OpenMP 4.5 [2.10.5, target update Construct]
21875 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
21876 // If the type of a list item is a reference to a type T then the type will
21877 // be considered to be T for all purposes of this clause.
21878 auto I = llvm::find_if(
21879 CurComponents,
21880 [](const OMPClauseMappableExprCommon::MappableComponent &MC) {
21881 return MC.getAssociatedDeclaration();
21882 });
21883 assert(I != CurComponents.end() && "Null decl on map clause.")(static_cast <bool> (I != CurComponents.end() &&
"Null decl on map clause.") ? void (0) : __assert_fail ("I != CurComponents.end() && \"Null decl on map clause.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 21883, __extension__ __PRETTY_FUNCTION__
))
;
21884 (void)I;
21885 QualType Type;
21886 auto *ASE = dyn_cast<ArraySubscriptExpr>(VE->IgnoreParens());
21887 auto *OASE = dyn_cast<OMPArraySectionExpr>(VE->IgnoreParens());
21888 auto *OAShE = dyn_cast<OMPArrayShapingExpr>(VE->IgnoreParens());
21889 if (ASE) {
21890 Type = ASE->getType().getNonReferenceType();
21891 } else if (OASE) {
21892 QualType BaseType =
21893 OMPArraySectionExpr::getBaseOriginalType(OASE->getBase());
21894 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
21895 Type = ATy->getElementType();
21896 else
21897 Type = BaseType->getPointeeType();
21898 Type = Type.getNonReferenceType();
21899 } else if (OAShE) {
21900 Type = OAShE->getBase()->getType()->getPointeeType();
21901 } else {
21902 Type = VE->getType();
21903 }
21904
21905 // OpenMP 4.5 [2.10.5, target update Construct, Restrictions, p.4]
21906 // A list item in a to or from clause must have a mappable type.
21907 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
21908 // A list item must have a mappable type.
21909 if (!checkTypeMappable(VE->getExprLoc(), VE->getSourceRange(), SemaRef,
21910 DSAS, Type, /*FullCheck=*/true))
21911 continue;
21912
21913 if (CKind == OMPC_map) {
21914 // target enter data
21915 // OpenMP [2.10.2, Restrictions, p. 99]
21916 // A map-type must be specified in all map clauses and must be either
21917 // to or alloc. Starting with OpenMP 5.2 the default map type is `to` if
21918 // no map type is present.
21919 OpenMPDirectiveKind DKind = DSAS->getCurrentDirective();
21920 if (DKind == OMPD_target_enter_data &&
21921 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_alloc ||
21922 SemaRef.getLangOpts().OpenMP >= 52)) {
21923 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
21924 << (IsMapTypeImplicit ? 1 : 0)
21925 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
21926 << getOpenMPDirectiveName(DKind);
21927 continue;
21928 }
21929
21930 // target exit_data
21931 // OpenMP [2.10.3, Restrictions, p. 102]
21932 // A map-type must be specified in all map clauses and must be either
21933 // from, release, or delete. Starting with OpenMP 5.2 the default map
21934 // type is `from` if no map type is present.
21935 if (DKind == OMPD_target_exit_data &&
21936 !(MapType == OMPC_MAP_from || MapType == OMPC_MAP_release ||
21937 MapType == OMPC_MAP_delete || SemaRef.getLangOpts().OpenMP >= 52)) {
21938 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
21939 << (IsMapTypeImplicit ? 1 : 0)
21940 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
21941 << getOpenMPDirectiveName(DKind);
21942 continue;
21943 }
21944
21945 // The 'ompx_hold' modifier is specifically intended to be used on a
21946 // 'target' or 'target data' directive to prevent data from being unmapped
21947 // during the associated statement. It is not permitted on a 'target
21948 // enter data' or 'target exit data' directive, which have no associated
21949 // statement.
21950 if ((DKind == OMPD_target_enter_data || DKind == OMPD_target_exit_data) &&
21951 HasHoldModifier) {
21952 SemaRef.Diag(StartLoc,
21953 diag::err_omp_invalid_map_type_modifier_for_directive)
21954 << getOpenMPSimpleClauseTypeName(OMPC_map,
21955 OMPC_MAP_MODIFIER_ompx_hold)
21956 << getOpenMPDirectiveName(DKind);
21957 continue;
21958 }
21959
21960 // target, target data
21961 // OpenMP 5.0 [2.12.2, Restrictions, p. 163]
21962 // OpenMP 5.0 [2.12.5, Restrictions, p. 174]
21963 // A map-type in a map clause must be to, from, tofrom or alloc
21964 if ((DKind == OMPD_target_data ||
21965 isOpenMPTargetExecutionDirective(DKind)) &&
21966 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||
21967 MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc)) {
21968 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
21969 << (IsMapTypeImplicit ? 1 : 0)
21970 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
21971 << getOpenMPDirectiveName(DKind);
21972 continue;
21973 }
21974
21975 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
21976 // A list item cannot appear in both a map clause and a data-sharing
21977 // attribute clause on the same construct
21978 //
21979 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
21980 // A list item cannot appear in both a map clause and a data-sharing
21981 // attribute clause on the same construct unless the construct is a
21982 // combined construct.
21983 if (VD && ((SemaRef.LangOpts.OpenMP <= 45 &&
21984 isOpenMPTargetExecutionDirective(DKind)) ||
21985 DKind == OMPD_target)) {
21986 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false);
21987 if (isOpenMPPrivate(DVar.CKind)) {
21988 SemaRef.Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
21989 << getOpenMPClauseName(DVar.CKind)
21990 << getOpenMPClauseName(OMPC_map)
21991 << getOpenMPDirectiveName(DSAS->getCurrentDirective());
21992 reportOriginalDsa(SemaRef, DSAS, CurDeclaration, DVar);
21993 continue;
21994 }
21995 }
21996 }
21997
21998 // Try to find the associated user-defined mapper.
21999 ExprResult ER = buildUserDefinedMapperRef(
22000 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
22001 Type.getCanonicalType(), UnresolvedMapper);
22002 if (ER.isInvalid())
22003 continue;
22004 MVLI.UDMapperList.push_back(ER.get());
22005
22006 // Save the current expression.
22007 MVLI.ProcessedVarList.push_back(RE);
22008
22009 // Store the components in the stack so that they can be used to check
22010 // against other clauses later on.
22011 DSAS->addMappableExpressionComponents(CurDeclaration, CurComponents,
22012 /*WhereFoundClauseKind=*/OMPC_map);
22013
22014 // Save the components and declaration to create the clause. For purposes of
22015 // the clause creation, any component list that has base 'this' uses
22016 // null as base declaration.
22017 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
22018 MVLI.VarComponents.back().append(CurComponents.begin(),
22019 CurComponents.end());
22020 MVLI.VarBaseDeclarations.push_back(isa<MemberExpr>(BE) ? nullptr
22021 : CurDeclaration);
22022 }
22023}
22024
22025OMPClause *Sema::ActOnOpenMPMapClause(
22026 Expr *IteratorModifier, ArrayRef<OpenMPMapModifierKind> MapTypeModifiers,
22027 ArrayRef<SourceLocation> MapTypeModifiersLoc,
22028 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
22029 OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation MapLoc,
22030 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
22031 const OMPVarListLocTy &Locs, bool NoDiagnose,
22032 ArrayRef<Expr *> UnresolvedMappers) {
22033 OpenMPMapModifierKind Modifiers[] = {
22034 OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown,
22035 OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown,
22036 OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown};
22037 SourceLocation ModifiersLoc[NumberOfOMPMapClauseModifiers];
22038
22039 if (IteratorModifier && !IteratorModifier->getType()->isSpecificBuiltinType(
22040 BuiltinType::OMPIterator))
22041 Diag(IteratorModifier->getExprLoc(),
22042 diag::err_omp_map_modifier_not_iterator);
22043
22044 // Process map-type-modifiers, flag errors for duplicate modifiers.
22045 unsigned Count = 0;
22046 for (unsigned I = 0, E = MapTypeModifiers.size(); I < E; ++I) {
22047 if (MapTypeModifiers[I] != OMPC_MAP_MODIFIER_unknown &&
22048 llvm::is_contained(Modifiers, MapTypeModifiers[I])) {
22049 Diag(MapTypeModifiersLoc[I], diag::err_omp_duplicate_map_type_modifier);
22050 continue;
22051 }
22052 assert(Count < NumberOfOMPMapClauseModifiers &&(static_cast <bool> (Count < NumberOfOMPMapClauseModifiers
&& "Modifiers exceed the allowed number of map type modifiers"
) ? void (0) : __assert_fail ("Count < NumberOfOMPMapClauseModifiers && \"Modifiers exceed the allowed number of map type modifiers\""
, "clang/lib/Sema/SemaOpenMP.cpp", 22053, __extension__ __PRETTY_FUNCTION__
))
22053 "Modifiers exceed the allowed number of map type modifiers")(static_cast <bool> (Count < NumberOfOMPMapClauseModifiers
&& "Modifiers exceed the allowed number of map type modifiers"
) ? void (0) : __assert_fail ("Count < NumberOfOMPMapClauseModifiers && \"Modifiers exceed the allowed number of map type modifiers\""
, "clang/lib/Sema/SemaOpenMP.cpp", 22053, __extension__ __PRETTY_FUNCTION__
))
;
22054 Modifiers[Count] = MapTypeModifiers[I];
22055 ModifiersLoc[Count] = MapTypeModifiersLoc[I];
22056 ++Count;
22057 }
22058
22059 MappableVarListInfo MVLI(VarList);
22060 checkMappableExpressionList(*this, DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
, OMPC_map, MVLI, Locs.StartLoc,
22061 MapperIdScopeSpec, MapperId, UnresolvedMappers,
22062 MapType, Modifiers, IsMapTypeImplicit,
22063 NoDiagnose);
22064
22065 // We need to produce a map clause even if we don't have variables so that
22066 // other diagnostics related with non-existing map clauses are accurate.
22067 return OMPMapClause::Create(
22068 Context, Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
22069 MVLI.VarComponents, MVLI.UDMapperList, IteratorModifier, Modifiers,
22070 ModifiersLoc, MapperIdScopeSpec.getWithLocInContext(Context), MapperId,
22071 MapType, IsMapTypeImplicit, MapLoc);
22072}
22073
22074QualType Sema::ActOnOpenMPDeclareReductionType(SourceLocation TyLoc,
22075 TypeResult ParsedType) {
22076 assert(ParsedType.isUsable())(static_cast <bool> (ParsedType.isUsable()) ? void (0) :
__assert_fail ("ParsedType.isUsable()", "clang/lib/Sema/SemaOpenMP.cpp"
, 22076, __extension__ __PRETTY_FUNCTION__))
;
22077
22078 QualType ReductionType = GetTypeFromParser(ParsedType.get());
22079 if (ReductionType.isNull())
22080 return QualType();
22081
22082 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions, C\C++
22083 // A type name in a declare reduction directive cannot be a function type, an
22084 // array type, a reference type, or a type qualified with const, volatile or
22085 // restrict.
22086 if (ReductionType.hasQualifiers()) {
22087 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 0;
22088 return QualType();
22089 }
22090
22091 if (ReductionType->isFunctionType()) {
22092 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 1;
22093 return QualType();
22094 }
22095 if (ReductionType->isReferenceType()) {
22096 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 2;
22097 return QualType();
22098 }
22099 if (ReductionType->isArrayType()) {
22100 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 3;
22101 return QualType();
22102 }
22103 return ReductionType;
22104}
22105
22106Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareReductionDirectiveStart(
22107 Scope *S, DeclContext *DC, DeclarationName Name,
22108 ArrayRef<std::pair<QualType, SourceLocation>> ReductionTypes,
22109 AccessSpecifier AS, Decl *PrevDeclInScope) {
22110 SmallVector<Decl *, 8> Decls;
22111 Decls.reserve(ReductionTypes.size());
22112
22113 LookupResult Lookup(*this, Name, SourceLocation(), LookupOMPReductionName,
22114 forRedeclarationInCurContext());
22115 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions
22116 // A reduction-identifier may not be re-declared in the current scope for the
22117 // same type or for a type that is compatible according to the base language
22118 // rules.
22119 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
22120 OMPDeclareReductionDecl *PrevDRD = nullptr;
22121 bool InCompoundScope = true;
22122 if (S != nullptr) {
22123 // Find previous declaration with the same name not referenced in other
22124 // declarations.
22125 FunctionScopeInfo *ParentFn = getEnclosingFunction();
22126 InCompoundScope =
22127 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
22128 LookupName(Lookup, S);
22129 FilterLookupForScope(Lookup, DC, S, /*ConsiderLinkage=*/false,
22130 /*AllowInlineNamespace=*/false);
22131 llvm::DenseMap<OMPDeclareReductionDecl *, bool> UsedAsPrevious;
22132 LookupResult::Filter Filter = Lookup.makeFilter();
22133 while (Filter.hasNext()) {
22134 auto *PrevDecl = cast<OMPDeclareReductionDecl>(Filter.next());
22135 if (InCompoundScope) {
22136 auto I = UsedAsPrevious.find(PrevDecl);
22137 if (I == UsedAsPrevious.end())
22138 UsedAsPrevious[PrevDecl] = false;
22139 if (OMPDeclareReductionDecl *D = PrevDecl->getPrevDeclInScope())
22140 UsedAsPrevious[D] = true;
22141 }
22142 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
22143 PrevDecl->getLocation();
22144 }
22145 Filter.done();
22146 if (InCompoundScope) {
22147 for (const auto &PrevData : UsedAsPrevious) {
22148 if (!PrevData.second) {
22149 PrevDRD = PrevData.first;
22150 break;
22151 }
22152 }
22153 }
22154 } else if (PrevDeclInScope != nullptr) {
22155 auto *PrevDRDInScope = PrevDRD =
22156 cast<OMPDeclareReductionDecl>(PrevDeclInScope);
22157 do {
22158 PreviousRedeclTypes[PrevDRDInScope->getType().getCanonicalType()] =
22159 PrevDRDInScope->getLocation();
22160 PrevDRDInScope = PrevDRDInScope->getPrevDeclInScope();
22161 } while (PrevDRDInScope != nullptr);
22162 }
22163 for (const auto &TyData : ReductionTypes) {
22164 const auto I = PreviousRedeclTypes.find(TyData.first.getCanonicalType());
22165 bool Invalid = false;
22166 if (I != PreviousRedeclTypes.end()) {
22167 Diag(TyData.second, diag::err_omp_declare_reduction_redefinition)
22168 << TyData.first;
22169 Diag(I->second, diag::note_previous_definition);
22170 Invalid = true;
22171 }
22172 PreviousRedeclTypes[TyData.first.getCanonicalType()] = TyData.second;
22173 auto *DRD = OMPDeclareReductionDecl::Create(Context, DC, TyData.second,
22174 Name, TyData.first, PrevDRD);
22175 DC->addDecl(DRD);
22176 DRD->setAccess(AS);
22177 Decls.push_back(DRD);
22178 if (Invalid)
22179 DRD->setInvalidDecl();
22180 else
22181 PrevDRD = DRD;
22182 }
22183
22184 return DeclGroupPtrTy::make(
22185 DeclGroupRef::Create(Context, Decls.begin(), Decls.size()));
22186}
22187
22188void Sema::ActOnOpenMPDeclareReductionCombinerStart(Scope *S, Decl *D) {
22189 auto *DRD = cast<OMPDeclareReductionDecl>(D);
22190
22191 // Enter new function scope.
22192 PushFunctionScope();
22193 setFunctionHasBranchProtectedScope();
22194 getCurFunction()->setHasOMPDeclareReductionCombiner();
22195
22196 if (S != nullptr)
22197 PushDeclContext(S, DRD);
22198 else
22199 CurContext = DRD;
22200
22201 PushExpressionEvaluationContext(
22202 ExpressionEvaluationContext::PotentiallyEvaluated);
22203
22204 QualType ReductionType = DRD->getType();
22205 // Create 'T* omp_parm;T omp_in;'. All references to 'omp_in' will
22206 // be replaced by '*omp_parm' during codegen. This required because 'omp_in'
22207 // uses semantics of argument handles by value, but it should be passed by
22208 // reference. C lang does not support references, so pass all parameters as
22209 // pointers.
22210 // Create 'T omp_in;' variable.
22211 VarDecl *OmpInParm =
22212 buildVarDecl(*this, D->getLocation(), ReductionType, "omp_in");
22213 // Create 'T* omp_parm;T omp_out;'. All references to 'omp_out' will
22214 // be replaced by '*omp_parm' during codegen. This required because 'omp_out'
22215 // uses semantics of argument handles by value, but it should be passed by
22216 // reference. C lang does not support references, so pass all parameters as
22217 // pointers.
22218 // Create 'T omp_out;' variable.
22219 VarDecl *OmpOutParm =
22220 buildVarDecl(*this, D->getLocation(), ReductionType, "omp_out");
22221 if (S != nullptr) {
22222 PushOnScopeChains(OmpInParm, S);
22223 PushOnScopeChains(OmpOutParm, S);
22224 } else {
22225 DRD->addDecl(OmpInParm);
22226 DRD->addDecl(OmpOutParm);
22227 }
22228 Expr *InE =
22229 ::buildDeclRefExpr(*this, OmpInParm, ReductionType, D->getLocation());
22230 Expr *OutE =
22231 ::buildDeclRefExpr(*this, OmpOutParm, ReductionType, D->getLocation());
22232 DRD->setCombinerData(InE, OutE);
22233}
22234
22235void Sema::ActOnOpenMPDeclareReductionCombinerEnd(Decl *D, Expr *Combiner) {
22236 auto *DRD = cast<OMPDeclareReductionDecl>(D);
22237 DiscardCleanupsInEvaluationContext();
22238 PopExpressionEvaluationContext();
22239
22240 PopDeclContext();
22241 PopFunctionScopeInfo();
22242
22243 if (Combiner != nullptr)
22244 DRD->setCombiner(Combiner);
22245 else
22246 DRD->setInvalidDecl();
22247}
22248
22249VarDecl *Sema::ActOnOpenMPDeclareReductionInitializerStart(Scope *S, Decl *D) {
22250 auto *DRD = cast<OMPDeclareReductionDecl>(D);
22251
22252 // Enter new function scope.
22253 PushFunctionScope();
22254 setFunctionHasBranchProtectedScope();
22255
22256 if (S != nullptr)
22257 PushDeclContext(S, DRD);
22258 else
22259 CurContext = DRD;
22260
22261 PushExpressionEvaluationContext(
22262 ExpressionEvaluationContext::PotentiallyEvaluated);
22263
22264 QualType ReductionType = DRD->getType();
22265 // Create 'T* omp_parm;T omp_priv;'. All references to 'omp_priv' will
22266 // be replaced by '*omp_parm' during codegen. This required because 'omp_priv'
22267 // uses semantics of argument handles by value, but it should be passed by
22268 // reference. C lang does not support references, so pass all parameters as
22269 // pointers.
22270 // Create 'T omp_priv;' variable.
22271 VarDecl *OmpPrivParm =
22272 buildVarDecl(*this, D->getLocation(), ReductionType, "omp_priv");
22273 // Create 'T* omp_parm;T omp_orig;'. All references to 'omp_orig' will
22274 // be replaced by '*omp_parm' during codegen. This required because 'omp_orig'
22275 // uses semantics of argument handles by value, but it should be passed by
22276 // reference. C lang does not support references, so pass all parameters as
22277 // pointers.
22278 // Create 'T omp_orig;' variable.
22279 VarDecl *OmpOrigParm =
22280 buildVarDecl(*this, D->getLocation(), ReductionType, "omp_orig");
22281 if (S != nullptr) {
22282 PushOnScopeChains(OmpPrivParm, S);
22283 PushOnScopeChains(OmpOrigParm, S);
22284 } else {
22285 DRD->addDecl(OmpPrivParm);
22286 DRD->addDecl(OmpOrigParm);
22287 }
22288 Expr *OrigE =
22289 ::buildDeclRefExpr(*this, OmpOrigParm, ReductionType, D->getLocation());
22290 Expr *PrivE =
22291 ::buildDeclRefExpr(*this, OmpPrivParm, ReductionType, D->getLocation());
22292 DRD->setInitializerData(OrigE, PrivE);
22293 return OmpPrivParm;
22294}
22295
22296void Sema::ActOnOpenMPDeclareReductionInitializerEnd(Decl *D, Expr *Initializer,
22297 VarDecl *OmpPrivParm) {
22298 auto *DRD = cast<OMPDeclareReductionDecl>(D);
22299 DiscardCleanupsInEvaluationContext();
22300 PopExpressionEvaluationContext();
22301
22302 PopDeclContext();
22303 PopFunctionScopeInfo();
22304
22305 if (Initializer != nullptr) {
22306 DRD->setInitializer(Initializer, OMPDeclareReductionDecl::CallInit);
22307 } else if (OmpPrivParm->hasInit()) {
22308 DRD->setInitializer(OmpPrivParm->getInit(),
22309 OmpPrivParm->isDirectInit()
22310 ? OMPDeclareReductionDecl::DirectInit
22311 : OMPDeclareReductionDecl::CopyInit);
22312 } else {
22313 DRD->setInvalidDecl();
22314 }
22315}
22316
22317Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareReductionDirectiveEnd(
22318 Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid) {
22319 for (Decl *D : DeclReductions.get()) {
22320 if (IsValid) {
22321 if (S)
22322 PushOnScopeChains(cast<OMPDeclareReductionDecl>(D), S,
22323 /*AddToContext=*/false);
22324 } else {
22325 D->setInvalidDecl();
22326 }
22327 }
22328 return DeclReductions;
22329}
22330
22331TypeResult Sema::ActOnOpenMPDeclareMapperVarDecl(Scope *S, Declarator &D) {
22332 TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
22333 QualType T = TInfo->getType();
22334 if (D.isInvalidType())
22335 return true;
22336
22337 if (getLangOpts().CPlusPlus) {
22338 // Check that there are no default arguments (C++ only).
22339 CheckExtraCXXDefaultArguments(D);
22340 }
22341
22342 return CreateParsedType(T, TInfo);
22343}
22344
22345QualType Sema::ActOnOpenMPDeclareMapperType(SourceLocation TyLoc,
22346 TypeResult ParsedType) {
22347 assert(ParsedType.isUsable() && "Expect usable parsed mapper type")(static_cast <bool> (ParsedType.isUsable() && "Expect usable parsed mapper type"
) ? void (0) : __assert_fail ("ParsedType.isUsable() && \"Expect usable parsed mapper type\""
, "clang/lib/Sema/SemaOpenMP.cpp", 22347, __extension__ __PRETTY_FUNCTION__
))
;
22348
22349 QualType MapperType = GetTypeFromParser(ParsedType.get());
22350 assert(!MapperType.isNull() && "Expect valid mapper type")(static_cast <bool> (!MapperType.isNull() && "Expect valid mapper type"
) ? void (0) : __assert_fail ("!MapperType.isNull() && \"Expect valid mapper type\""
, "clang/lib/Sema/SemaOpenMP.cpp", 22350, __extension__ __PRETTY_FUNCTION__
))
;
22351
22352 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
22353 // The type must be of struct, union or class type in C and C++
22354 if (!MapperType->isStructureOrClassType() && !MapperType->isUnionType()) {
22355 Diag(TyLoc, diag::err_omp_mapper_wrong_type);
22356 return QualType();
22357 }
22358 return MapperType;
22359}
22360
22361Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareMapperDirective(
22362 Scope *S, DeclContext *DC, DeclarationName Name, QualType MapperType,
22363 SourceLocation StartLoc, DeclarationName VN, AccessSpecifier AS,
22364 Expr *MapperVarRef, ArrayRef<OMPClause *> Clauses, Decl *PrevDeclInScope) {
22365 LookupResult Lookup(*this, Name, SourceLocation(), LookupOMPMapperName,
22366 forRedeclarationInCurContext());
22367 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
22368 // A mapper-identifier may not be redeclared in the current scope for the
22369 // same type or for a type that is compatible according to the base language
22370 // rules.
22371 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
22372 OMPDeclareMapperDecl *PrevDMD = nullptr;
22373 bool InCompoundScope = true;
22374 if (S != nullptr) {
22375 // Find previous declaration with the same name not referenced in other
22376 // declarations.
22377 FunctionScopeInfo *ParentFn = getEnclosingFunction();
22378 InCompoundScope =
22379 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
22380 LookupName(Lookup, S);
22381 FilterLookupForScope(Lookup, DC, S, /*ConsiderLinkage=*/false,
22382 /*AllowInlineNamespace=*/false);
22383 llvm::DenseMap<OMPDeclareMapperDecl *, bool> UsedAsPrevious;
22384 LookupResult::Filter Filter = Lookup.makeFilter();
22385 while (Filter.hasNext()) {
22386 auto *PrevDecl = cast<OMPDeclareMapperDecl>(Filter.next());
22387 if (InCompoundScope) {
22388 auto I = UsedAsPrevious.find(PrevDecl);
22389 if (I == UsedAsPrevious.end())
22390 UsedAsPrevious[PrevDecl] = false;
22391 if (OMPDeclareMapperDecl *D = PrevDecl->getPrevDeclInScope())
22392 UsedAsPrevious[D] = true;
22393 }
22394 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
22395 PrevDecl->getLocation();
22396 }
22397 Filter.done();
22398 if (InCompoundScope) {
22399 for (const auto &PrevData : UsedAsPrevious) {
22400 if (!PrevData.second) {
22401 PrevDMD = PrevData.first;
22402 break;
22403 }
22404 }
22405 }
22406 } else if (PrevDeclInScope) {
22407 auto *PrevDMDInScope = PrevDMD =
22408 cast<OMPDeclareMapperDecl>(PrevDeclInScope);
22409 do {
22410 PreviousRedeclTypes[PrevDMDInScope->getType().getCanonicalType()] =
22411 PrevDMDInScope->getLocation();
22412 PrevDMDInScope = PrevDMDInScope->getPrevDeclInScope();
22413 } while (PrevDMDInScope != nullptr);
22414 }
22415 const auto I = PreviousRedeclTypes.find(MapperType.getCanonicalType());
22416 bool Invalid = false;
22417 if (I != PreviousRedeclTypes.end()) {
22418 Diag(StartLoc, diag::err_omp_declare_mapper_redefinition)
22419 << MapperType << Name;
22420 Diag(I->second, diag::note_previous_definition);
22421 Invalid = true;
22422 }
22423 // Build expressions for implicit maps of data members with 'default'
22424 // mappers.
22425 SmallVector<OMPClause *, 4> ClausesWithImplicit(Clauses.begin(),
22426 Clauses.end());
22427 if (LangOpts.OpenMP >= 50)
22428 processImplicitMapsWithDefaultMappers(*this, DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
, ClausesWithImplicit);
22429 auto *DMD =
22430 OMPDeclareMapperDecl::Create(Context, DC, StartLoc, Name, MapperType, VN,
22431 ClausesWithImplicit, PrevDMD);
22432 if (S)
22433 PushOnScopeChains(DMD, S);
22434 else
22435 DC->addDecl(DMD);
22436 DMD->setAccess(AS);
22437 if (Invalid)
22438 DMD->setInvalidDecl();
22439
22440 auto *VD = cast<DeclRefExpr>(MapperVarRef)->getDecl();
22441 VD->setDeclContext(DMD);
22442 VD->setLexicalDeclContext(DMD);
22443 DMD->addDecl(VD);
22444 DMD->setMapperVarRef(MapperVarRef);
22445
22446 return DeclGroupPtrTy::make(DeclGroupRef(DMD));
22447}
22448
22449ExprResult
22450Sema::ActOnOpenMPDeclareMapperDirectiveVarDecl(Scope *S, QualType MapperType,
22451 SourceLocation StartLoc,
22452 DeclarationName VN) {
22453 TypeSourceInfo *TInfo =
22454 Context.getTrivialTypeSourceInfo(MapperType, StartLoc);
22455 auto *VD = VarDecl::Create(Context, Context.getTranslationUnitDecl(),
22456 StartLoc, StartLoc, VN.getAsIdentifierInfo(),
22457 MapperType, TInfo, SC_None);
22458 if (S)
22459 PushOnScopeChains(VD, S, /*AddToContext=*/false);
22460 Expr *E = buildDeclRefExpr(*this, VD, MapperType, StartLoc);
22461 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->addDeclareMapperVarRef(E);
22462 return E;
22463}
22464
22465void Sema::ActOnOpenMPIteratorVarDecl(VarDecl *VD) {
22466 if (DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getDeclareMapperVarRef())
22467 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->addIteratorVarDecl(VD);
22468}
22469
22470bool Sema::isOpenMPDeclareMapperVarDeclAllowed(const VarDecl *VD) const {
22471 assert(LangOpts.OpenMP && "Expected OpenMP mode.")(static_cast <bool> (LangOpts.OpenMP && "Expected OpenMP mode."
) ? void (0) : __assert_fail ("LangOpts.OpenMP && \"Expected OpenMP mode.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 22471, __extension__ __PRETTY_FUNCTION__
))
;
22472 const Expr *Ref = DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getDeclareMapperVarRef();
22473 if (const auto *DRE = cast_or_null<DeclRefExpr>(Ref)) {
22474 if (VD->getCanonicalDecl() == DRE->getDecl()->getCanonicalDecl())
22475 return true;
22476 if (VD->isUsableInConstantExpressions(Context))
22477 return true;
22478 if (LangOpts.OpenMP >= 52 && DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isIteratorVarDecl(VD))
22479 return true;
22480 return false;
22481 }
22482 return true;
22483}
22484
22485const ValueDecl *Sema::getOpenMPDeclareMapperVarName() const {
22486 assert(LangOpts.OpenMP && "Expected OpenMP mode.")(static_cast <bool> (LangOpts.OpenMP && "Expected OpenMP mode."
) ? void (0) : __assert_fail ("LangOpts.OpenMP && \"Expected OpenMP mode.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 22486, __extension__ __PRETTY_FUNCTION__
))
;
22487 return cast<DeclRefExpr>(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getDeclareMapperVarRef())->getDecl();
22488}
22489
22490OMPClause *Sema::ActOnOpenMPNumTeamsClause(Expr *NumTeams,
22491 SourceLocation StartLoc,
22492 SourceLocation LParenLoc,
22493 SourceLocation EndLoc) {
22494 Expr *ValExpr = NumTeams;
22495 Stmt *HelperValStmt = nullptr;
22496
22497 // OpenMP [teams Constrcut, Restrictions]
22498 // The num_teams expression must evaluate to a positive integer value.
22499 if (!isNonNegativeIntegerValue(ValExpr, *this, OMPC_num_teams,
22500 /*StrictlyPositive=*/true))
22501 return nullptr;
22502
22503 OpenMPDirectiveKind DKind = DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective();
22504 OpenMPDirectiveKind CaptureRegion =
22505 getOpenMPCaptureRegionForClause(DKind, OMPC_num_teams, LangOpts.OpenMP);
22506 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
22507 ValExpr = MakeFullExpr(ValExpr).get();
22508 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22509 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
22510 HelperValStmt = buildPreInits(Context, Captures);
22511 }
22512
22513 return new (Context) OMPNumTeamsClause(ValExpr, HelperValStmt, CaptureRegion,
22514 StartLoc, LParenLoc, EndLoc);
22515}
22516
22517OMPClause *Sema::ActOnOpenMPThreadLimitClause(Expr *ThreadLimit,
22518 SourceLocation StartLoc,
22519 SourceLocation LParenLoc,
22520 SourceLocation EndLoc) {
22521 Expr *ValExpr = ThreadLimit;
22522 Stmt *HelperValStmt = nullptr;
22523
22524 // OpenMP [teams Constrcut, Restrictions]
22525 // The thread_limit expression must evaluate to a positive integer value.
22526 if (!isNonNegativeIntegerValue(ValExpr, *this, OMPC_thread_limit,
22527 /*StrictlyPositive=*/true))
22528 return nullptr;
22529
22530 OpenMPDirectiveKind DKind = DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective();
22531 OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause(
22532 DKind, OMPC_thread_limit, LangOpts.OpenMP);
22533 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
22534 ValExpr = MakeFullExpr(ValExpr).get();
22535 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22536 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
22537 HelperValStmt = buildPreInits(Context, Captures);
22538 }
22539
22540 return new (Context) OMPThreadLimitClause(
22541 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
22542}
22543
22544OMPClause *Sema::ActOnOpenMPPriorityClause(Expr *Priority,
22545 SourceLocation StartLoc,
22546 SourceLocation LParenLoc,
22547 SourceLocation EndLoc) {
22548 Expr *ValExpr = Priority;
22549 Stmt *HelperValStmt = nullptr;
22550 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
22551
22552 // OpenMP [2.9.1, task Constrcut]
22553 // The priority-value is a non-negative numerical scalar expression.
22554 if (!isNonNegativeIntegerValue(
22555 ValExpr, *this, OMPC_priority,
22556 /*StrictlyPositive=*/false, /*BuildCapture=*/true,
22557 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
22558 return nullptr;
22559
22560 return new (Context) OMPPriorityClause(ValExpr, HelperValStmt, CaptureRegion,
22561 StartLoc, LParenLoc, EndLoc);
22562}
22563
22564OMPClause *Sema::ActOnOpenMPGrainsizeClause(
22565 OpenMPGrainsizeClauseModifier Modifier, Expr *Grainsize,
22566 SourceLocation StartLoc, SourceLocation LParenLoc,
22567 SourceLocation ModifierLoc, SourceLocation EndLoc) {
22568 assert((ModifierLoc.isInvalid() || LangOpts.OpenMP >= 51) &&(static_cast <bool> ((ModifierLoc.isInvalid() || LangOpts
.OpenMP >= 51) && "Unexpected grainsize modifier in OpenMP < 51."
) ? void (0) : __assert_fail ("(ModifierLoc.isInvalid() || LangOpts.OpenMP >= 51) && \"Unexpected grainsize modifier in OpenMP < 51.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 22569, __extension__ __PRETTY_FUNCTION__
))
22569 "Unexpected grainsize modifier in OpenMP < 51.")(static_cast <bool> ((ModifierLoc.isInvalid() || LangOpts
.OpenMP >= 51) && "Unexpected grainsize modifier in OpenMP < 51."
) ? void (0) : __assert_fail ("(ModifierLoc.isInvalid() || LangOpts.OpenMP >= 51) && \"Unexpected grainsize modifier in OpenMP < 51.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 22569, __extension__ __PRETTY_FUNCTION__
))
;
22570
22571 if (ModifierLoc.isValid() && Modifier == OMPC_GRAINSIZE_unknown) {
22572 std::string Values = getListOfPossibleValues(OMPC_grainsize, /*First=*/0,
22573 OMPC_GRAINSIZE_unknown);
22574 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
22575 << Values << getOpenMPClauseName(OMPC_grainsize);
22576 return nullptr;
22577 }
22578
22579 Expr *ValExpr = Grainsize;
22580 Stmt *HelperValStmt = nullptr;
22581 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
22582
22583 // OpenMP [2.9.2, taskloop Constrcut]
22584 // The parameter of the grainsize clause must be a positive integer
22585 // expression.
22586 if (!isNonNegativeIntegerValue(ValExpr, *this, OMPC_grainsize,
22587 /*StrictlyPositive=*/true,
22588 /*BuildCapture=*/true,
22589 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective(),
22590 &CaptureRegion, &HelperValStmt))
22591 return nullptr;
22592
22593 return new (Context)
22594 OMPGrainsizeClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
22595 StartLoc, LParenLoc, ModifierLoc, EndLoc);
22596}
22597
22598OMPClause *Sema::ActOnOpenMPNumTasksClause(
22599 OpenMPNumTasksClauseModifier Modifier, Expr *NumTasks,
22600 SourceLocation StartLoc, SourceLocation LParenLoc,
22601 SourceLocation ModifierLoc, SourceLocation EndLoc) {
22602 assert((ModifierLoc.isInvalid() || LangOpts.OpenMP >= 51) &&(static_cast <bool> ((ModifierLoc.isInvalid() || LangOpts
.OpenMP >= 51) && "Unexpected num_tasks modifier in OpenMP < 51."
) ? void (0) : __assert_fail ("(ModifierLoc.isInvalid() || LangOpts.OpenMP >= 51) && \"Unexpected num_tasks modifier in OpenMP < 51.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 22603, __extension__ __PRETTY_FUNCTION__
))
22603 "Unexpected num_tasks modifier in OpenMP < 51.")(static_cast <bool> ((ModifierLoc.isInvalid() || LangOpts
.OpenMP >= 51) && "Unexpected num_tasks modifier in OpenMP < 51."
) ? void (0) : __assert_fail ("(ModifierLoc.isInvalid() || LangOpts.OpenMP >= 51) && \"Unexpected num_tasks modifier in OpenMP < 51.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 22603, __extension__ __PRETTY_FUNCTION__
))
;
22604
22605 if (ModifierLoc.isValid() && Modifier == OMPC_NUMTASKS_unknown) {
22606 std::string Values = getListOfPossibleValues(OMPC_num_tasks, /*First=*/0,
22607 OMPC_NUMTASKS_unknown);
22608 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
22609 << Values << getOpenMPClauseName(OMPC_num_tasks);
22610 return nullptr;
22611 }
22612
22613 Expr *ValExpr = NumTasks;
22614 Stmt *HelperValStmt = nullptr;
22615 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
22616
22617 // OpenMP [2.9.2, taskloop Constrcut]
22618 // The parameter of the num_tasks clause must be a positive integer
22619 // expression.
22620 if (!isNonNegativeIntegerValue(
22621 ValExpr, *this, OMPC_num_tasks,
22622 /*StrictlyPositive=*/true, /*BuildCapture=*/true,
22623 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
22624 return nullptr;
22625
22626 return new (Context)
22627 OMPNumTasksClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
22628 StartLoc, LParenLoc, ModifierLoc, EndLoc);
22629}
22630
22631OMPClause *Sema::ActOnOpenMPHintClause(Expr *Hint, SourceLocation StartLoc,
22632 SourceLocation LParenLoc,
22633 SourceLocation EndLoc) {
22634 // OpenMP [2.13.2, critical construct, Description]
22635 // ... where hint-expression is an integer constant expression that evaluates
22636 // to a valid lock hint.
22637 ExprResult HintExpr =
22638 VerifyPositiveIntegerConstantInClause(Hint, OMPC_hint, false);
22639 if (HintExpr.isInvalid())
22640 return nullptr;
22641 return new (Context)
22642 OMPHintClause(HintExpr.get(), StartLoc, LParenLoc, EndLoc);
22643}
22644
22645/// Tries to find omp_event_handle_t type.
22646static bool findOMPEventHandleT(Sema &S, SourceLocation Loc,
22647 DSAStackTy *Stack) {
22648 QualType OMPEventHandleT = Stack->getOMPEventHandleT();
22649 if (!OMPEventHandleT.isNull())
22650 return true;
22651 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_event_handle_t");
22652 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
22653 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
22654 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_event_handle_t";
22655 return false;
22656 }
22657 Stack->setOMPEventHandleT(PT.get());
22658 return true;
22659}
22660
22661OMPClause *Sema::ActOnOpenMPDetachClause(Expr *Evt, SourceLocation StartLoc,
22662 SourceLocation LParenLoc,
22663 SourceLocation EndLoc) {
22664 if (!Evt->isValueDependent() && !Evt->isTypeDependent() &&
22665 !Evt->isInstantiationDependent() &&
22666 !Evt->containsUnexpandedParameterPack()) {
22667 if (!findOMPEventHandleT(*this, Evt->getExprLoc(), DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
))
22668 return nullptr;
22669 // OpenMP 5.0, 2.10.1 task Construct.
22670 // event-handle is a variable of the omp_event_handle_t type.
22671 auto *Ref = dyn_cast<DeclRefExpr>(Evt->IgnoreParenImpCasts());
22672 if (!Ref) {
22673 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
22674 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
22675 return nullptr;
22676 }
22677 auto *VD = dyn_cast_or_null<VarDecl>(Ref->getDecl());
22678 if (!VD) {
22679 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
22680 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
22681 return nullptr;
22682 }
22683 if (!Context.hasSameUnqualifiedType(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getOMPEventHandleT(),
22684 VD->getType()) ||
22685 VD->getType().isConstant(Context)) {
22686 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
22687 << "omp_event_handle_t" << 1 << VD->getType()
22688 << Evt->getSourceRange();
22689 return nullptr;
22690 }
22691 // OpenMP 5.0, 2.10.1 task Construct
22692 // [detach clause]... The event-handle will be considered as if it was
22693 // specified on a firstprivate clause.
22694 DSAStackTy::DSAVarData DVar = DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getTopDSA(VD, /*FromParent=*/false);
22695 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
22696 DVar.RefExpr) {
22697 Diag(Evt->getExprLoc(), diag::err_omp_wrong_dsa)
22698 << getOpenMPClauseName(DVar.CKind)
22699 << getOpenMPClauseName(OMPC_firstprivate);
22700 reportOriginalDsa(*this, DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
, VD, DVar);
22701 return nullptr;
22702 }
22703 }
22704
22705 return new (Context) OMPDetachClause(Evt, StartLoc, LParenLoc, EndLoc);
22706}
22707
22708OMPClause *Sema::ActOnOpenMPDistScheduleClause(
22709 OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
22710 SourceLocation LParenLoc, SourceLocation KindLoc, SourceLocation CommaLoc,
22711 SourceLocation EndLoc) {
22712 if (Kind == OMPC_DIST_SCHEDULE_unknown) {
22713 std::string Values;
22714 Values += "'";
22715 Values += getOpenMPSimpleClauseTypeName(OMPC_dist_schedule, 0);
22716 Values += "'";
22717 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22718 << Values << getOpenMPClauseName(OMPC_dist_schedule);
22719 return nullptr;
22720 }
22721 Expr *ValExpr = ChunkSize;
22722 Stmt *HelperValStmt = nullptr;
22723 if (ChunkSize) {
22724 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
22725 !ChunkSize->isInstantiationDependent() &&
22726 !ChunkSize->containsUnexpandedParameterPack()) {
22727 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
22728 ExprResult Val =
22729 PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize);
22730 if (Val.isInvalid())
22731 return nullptr;
22732
22733 ValExpr = Val.get();
22734
22735 // OpenMP [2.7.1, Restrictions]
22736 // chunk_size must be a loop invariant integer expression with a positive
22737 // value.
22738 if (std::optional<llvm::APSInt> Result =
22739 ValExpr->getIntegerConstantExpr(Context)) {
22740 if (Result->isSigned() && !Result->isStrictlyPositive()) {
22741 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
22742 << "dist_schedule" << ChunkSize->getSourceRange();
22743 return nullptr;
22744 }
22745 } else if (getOpenMPCaptureRegionForClause(
22746 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective(), OMPC_dist_schedule,
22747 LangOpts.OpenMP) != OMPD_unknown &&
22748 !CurContext->isDependentContext()) {
22749 ValExpr = MakeFullExpr(ValExpr).get();
22750 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22751 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
22752 HelperValStmt = buildPreInits(Context, Captures);
22753 }
22754 }
22755 }
22756
22757 return new (Context)
22758 OMPDistScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc,
22759 Kind, ValExpr, HelperValStmt);
22760}
22761
22762OMPClause *Sema::ActOnOpenMPDefaultmapClause(
22763 OpenMPDefaultmapClauseModifier M, OpenMPDefaultmapClauseKind Kind,
22764 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
22765 SourceLocation KindLoc, SourceLocation EndLoc) {
22766 if (getLangOpts().OpenMP < 50) {
22767 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom ||
22768 Kind != OMPC_DEFAULTMAP_scalar) {
22769 std::string Value;
22770 SourceLocation Loc;
22771 Value += "'";
22772 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom) {
22773 Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
22774 OMPC_DEFAULTMAP_MODIFIER_tofrom);
22775 Loc = MLoc;
22776 } else {
22777 Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
22778 OMPC_DEFAULTMAP_scalar);
22779 Loc = KindLoc;
22780 }
22781 Value += "'";
22782 Diag(Loc, diag::err_omp_unexpected_clause_value)
22783 << Value << getOpenMPClauseName(OMPC_defaultmap);
22784 return nullptr;
22785 }
22786 } else {
22787 bool isDefaultmapModifier = (M != OMPC_DEFAULTMAP_MODIFIER_unknown);
22788 bool isDefaultmapKind = (Kind != OMPC_DEFAULTMAP_unknown) ||
22789 (LangOpts.OpenMP >= 50 && KindLoc.isInvalid());
22790 if (!isDefaultmapKind || !isDefaultmapModifier) {
22791 StringRef KindValue = "'scalar', 'aggregate', 'pointer'";
22792 if (LangOpts.OpenMP == 50) {
22793 StringRef ModifierValue = "'alloc', 'from', 'to', 'tofrom', "
22794 "'firstprivate', 'none', 'default'";
22795 if (!isDefaultmapKind && isDefaultmapModifier) {
22796 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22797 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
22798 } else if (isDefaultmapKind && !isDefaultmapModifier) {
22799 Diag(MLoc, diag::err_omp_unexpected_clause_value)
22800 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
22801 } else {
22802 Diag(MLoc, diag::err_omp_unexpected_clause_value)
22803 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
22804 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22805 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
22806 }
22807 } else {
22808 StringRef ModifierValue =
22809 "'alloc', 'from', 'to', 'tofrom', "
22810 "'firstprivate', 'none', 'default', 'present'";
22811 if (!isDefaultmapKind && isDefaultmapModifier) {
22812 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22813 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
22814 } else if (isDefaultmapKind && !isDefaultmapModifier) {
22815 Diag(MLoc, diag::err_omp_unexpected_clause_value)
22816 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
22817 } else {
22818 Diag(MLoc, diag::err_omp_unexpected_clause_value)
22819 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
22820 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22821 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
22822 }
22823 }
22824 return nullptr;
22825 }
22826
22827 // OpenMP [5.0, 2.12.5, Restrictions, p. 174]
22828 // At most one defaultmap clause for each category can appear on the
22829 // directive.
22830 if (DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->checkDefaultmapCategory(Kind)) {
22831 Diag(StartLoc, diag::err_omp_one_defaultmap_each_category);
22832 return nullptr;
22833 }
22834 }
22835 if (Kind == OMPC_DEFAULTMAP_unknown) {
22836 // Variable category is not specified - mark all categories.
22837 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_aggregate, StartLoc);
22838 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_scalar, StartLoc);
22839 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_pointer, StartLoc);
22840 } else {
22841 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->setDefaultDMAAttr(M, Kind, StartLoc);
22842 }
22843
22844 return new (Context)
22845 OMPDefaultmapClause(StartLoc, LParenLoc, MLoc, KindLoc, EndLoc, Kind, M);
22846}
22847
22848bool Sema::ActOnStartOpenMPDeclareTargetContext(
22849 DeclareTargetContextInfo &DTCI) {
22850 DeclContext *CurLexicalContext = getCurLexicalContext();
22851 if (!CurLexicalContext->isFileContext() &&
22852 !CurLexicalContext->isExternCContext() &&
22853 !CurLexicalContext->isExternCXXContext() &&
22854 !isa<CXXRecordDecl>(CurLexicalContext) &&
22855 !isa<ClassTemplateDecl>(CurLexicalContext) &&
22856 !isa<ClassTemplatePartialSpecializationDecl>(CurLexicalContext) &&
22857 !isa<ClassTemplateSpecializationDecl>(CurLexicalContext)) {
22858 Diag(DTCI.Loc, diag::err_omp_region_not_file_context);
22859 return false;
22860 }
22861
22862 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
22863 if (getLangOpts().HIP)
22864 Diag(DTCI.Loc, diag::warn_hip_omp_target_directives);
22865
22866 DeclareTargetNesting.push_back(DTCI);
22867 return true;
22868}
22869
22870const Sema::DeclareTargetContextInfo
22871Sema::ActOnOpenMPEndDeclareTargetDirective() {
22872 assert(!DeclareTargetNesting.empty() &&(static_cast <bool> (!DeclareTargetNesting.empty() &&
"check isInOpenMPDeclareTargetContext() first!") ? void (0) :
__assert_fail ("!DeclareTargetNesting.empty() && \"check isInOpenMPDeclareTargetContext() first!\""
, "clang/lib/Sema/SemaOpenMP.cpp", 22873, __extension__ __PRETTY_FUNCTION__
))
22873 "check isInOpenMPDeclareTargetContext() first!")(static_cast <bool> (!DeclareTargetNesting.empty() &&
"check isInOpenMPDeclareTargetContext() first!") ? void (0) :
__assert_fail ("!DeclareTargetNesting.empty() && \"check isInOpenMPDeclareTargetContext() first!\""
, "clang/lib/Sema/SemaOpenMP.cpp", 22873, __extension__ __PRETTY_FUNCTION__
))
;
22874 return DeclareTargetNesting.pop_back_val();
22875}
22876
22877void Sema::ActOnFinishedOpenMPDeclareTargetContext(
22878 DeclareTargetContextInfo &DTCI) {
22879 for (auto &It : DTCI.ExplicitlyMapped)
22880 ActOnOpenMPDeclareTargetName(It.first, It.second.Loc, It.second.MT, DTCI);
22881}
22882
22883void Sema::DiagnoseUnterminatedOpenMPDeclareTarget() {
22884 if (DeclareTargetNesting.empty())
22885 return;
22886 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
22887 Diag(DTCI.Loc, diag::warn_omp_unterminated_declare_target)
22888 << getOpenMPDirectiveName(DTCI.Kind);
22889}
22890
22891NamedDecl *Sema::lookupOpenMPDeclareTargetName(Scope *CurScope,
22892 CXXScopeSpec &ScopeSpec,
22893 const DeclarationNameInfo &Id) {
22894 LookupResult Lookup(*this, Id, LookupOrdinaryName);
22895 LookupParsedName(Lookup, CurScope, &ScopeSpec, true);
22896
22897 if (Lookup.isAmbiguous())
22898 return nullptr;
22899 Lookup.suppressDiagnostics();
22900
22901 if (!Lookup.isSingleResult()) {
22902 VarOrFuncDeclFilterCCC CCC(*this);
22903 if (TypoCorrection Corrected =
22904 CorrectTypo(Id, LookupOrdinaryName, CurScope, nullptr, CCC,
22905 CTK_ErrorRecovery)) {
22906 diagnoseTypo(Corrected, PDiag(diag::err_undeclared_var_use_suggest)
22907 << Id.getName());
22908 checkDeclIsAllowedInOpenMPTarget(nullptr, Corrected.getCorrectionDecl());
22909 return nullptr;
22910 }
22911
22912 Diag(Id.getLoc(), diag::err_undeclared_var_use) << Id.getName();
22913 return nullptr;
22914 }
22915
22916 NamedDecl *ND = Lookup.getAsSingle<NamedDecl>();
22917 if (!isa<VarDecl>(ND) && !isa<FunctionDecl>(ND) &&
22918 !isa<FunctionTemplateDecl>(ND)) {
22919 Diag(Id.getLoc(), diag::err_omp_invalid_target_decl) << Id.getName();
22920 return nullptr;
22921 }
22922 return ND;
22923}
22924
22925void Sema::ActOnOpenMPDeclareTargetName(NamedDecl *ND, SourceLocation Loc,
22926 OMPDeclareTargetDeclAttr::MapTypeTy MT,
22927 DeclareTargetContextInfo &DTCI) {
22928 assert((isa<VarDecl>(ND) || isa<FunctionDecl>(ND) ||(static_cast <bool> ((isa<VarDecl>(ND) || isa<
FunctionDecl>(ND) || isa<FunctionTemplateDecl>(ND)) &&
"Expected variable, function or function template.") ? void (
0) : __assert_fail ("(isa<VarDecl>(ND) || isa<FunctionDecl>(ND) || isa<FunctionTemplateDecl>(ND)) && \"Expected variable, function or function template.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 22930, __extension__ __PRETTY_FUNCTION__
))
22929 isa<FunctionTemplateDecl>(ND)) &&(static_cast <bool> ((isa<VarDecl>(ND) || isa<
FunctionDecl>(ND) || isa<FunctionTemplateDecl>(ND)) &&
"Expected variable, function or function template.") ? void (
0) : __assert_fail ("(isa<VarDecl>(ND) || isa<FunctionDecl>(ND) || isa<FunctionTemplateDecl>(ND)) && \"Expected variable, function or function template.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 22930, __extension__ __PRETTY_FUNCTION__
))
22930 "Expected variable, function or function template.")(static_cast <bool> ((isa<VarDecl>(ND) || isa<
FunctionDecl>(ND) || isa<FunctionTemplateDecl>(ND)) &&
"Expected variable, function or function template.") ? void (
0) : __assert_fail ("(isa<VarDecl>(ND) || isa<FunctionDecl>(ND) || isa<FunctionTemplateDecl>(ND)) && \"Expected variable, function or function template.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 22930, __extension__ __PRETTY_FUNCTION__
))
;
22931
22932 // Diagnose marking after use as it may lead to incorrect diagnosis and
22933 // codegen.
22934 if (LangOpts.OpenMP >= 50 &&
22935 (ND->isUsed(/*CheckUsedAttr=*/false) || ND->isReferenced()))
22936 Diag(Loc, diag::warn_omp_declare_target_after_first_use);
22937
22938 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
22939 if (getLangOpts().HIP)
22940 Diag(Loc, diag::warn_hip_omp_target_directives);
22941
22942 // Explicit declare target lists have precedence.
22943 const unsigned Level = -1;
22944
22945 auto *VD = cast<ValueDecl>(ND);
22946 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
22947 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
22948 if (ActiveAttr && (*ActiveAttr)->getDevType() != DTCI.DT &&
22949 (*ActiveAttr)->getLevel() == Level) {
22950 Diag(Loc, diag::err_omp_device_type_mismatch)
22951 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(DTCI.DT)
22952 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(
22953 (*ActiveAttr)->getDevType());
22954 return;
22955 }
22956 if (ActiveAttr && (*ActiveAttr)->getMapType() != MT &&
22957 (*ActiveAttr)->getLevel() == Level) {
22958 Diag(Loc, diag::err_omp_declare_target_to_and_link) << ND;
22959 return;
22960 }
22961
22962 if (ActiveAttr && (*ActiveAttr)->getLevel() == Level)
22963 return;
22964
22965 Expr *IndirectE = nullptr;
22966 bool IsIndirect = false;
22967 if (DTCI.Indirect) {
22968 IndirectE = *DTCI.Indirect;
22969 if (!IndirectE)
22970 IsIndirect = true;
22971 }
22972 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
22973 Context, MT, DTCI.DT, IndirectE, IsIndirect, Level,
22974 SourceRange(Loc, Loc));
22975 ND->addAttr(A);
22976 if (ASTMutationListener *ML = Context.getASTMutationListener())
22977 ML->DeclarationMarkedOpenMPDeclareTarget(ND, A);
22978 checkDeclIsAllowedInOpenMPTarget(nullptr, ND, Loc);
22979}
22980
22981static void checkDeclInTargetContext(SourceLocation SL, SourceRange SR,
22982 Sema &SemaRef, Decl *D) {
22983 if (!D || !isa<VarDecl>(D))
22984 return;
22985 auto *VD = cast<VarDecl>(D);
22986 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> MapTy =
22987 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
22988 if (SemaRef.LangOpts.OpenMP >= 50 &&
22989 (SemaRef.getCurLambda(/*IgnoreNonLambdaCapturingScope=*/true) ||
22990 SemaRef.getCurBlock() || SemaRef.getCurCapturedRegion()) &&
22991 VD->hasGlobalStorage()) {
22992 if (!MapTy || (*MapTy != OMPDeclareTargetDeclAttr::MT_To &&
22993 *MapTy != OMPDeclareTargetDeclAttr::MT_Enter)) {
22994 // OpenMP 5.0, 2.12.7 declare target Directive, Restrictions
22995 // If a lambda declaration and definition appears between a
22996 // declare target directive and the matching end declare target
22997 // directive, all variables that are captured by the lambda
22998 // expression must also appear in a to clause.
22999 SemaRef.Diag(VD->getLocation(),
23000 diag::err_omp_lambda_capture_in_declare_target_not_to);
23001 SemaRef.Diag(SL, diag::note_var_explicitly_captured_here)
23002 << VD << 0 << SR;
23003 return;
23004 }
23005 }
23006 if (MapTy)
23007 return;
23008 SemaRef.Diag(VD->getLocation(), diag::warn_omp_not_in_target_context);
23009 SemaRef.Diag(SL, diag::note_used_here) << SR;
23010}
23011
23012static bool checkValueDeclInTarget(SourceLocation SL, SourceRange SR,
23013 Sema &SemaRef, DSAStackTy *Stack,
23014 ValueDecl *VD) {
23015 return OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) ||
23016 checkTypeMappable(SL, SR, SemaRef, Stack, VD->getType(),
23017 /*FullCheck=*/false);
23018}
23019
23020void Sema::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D,
23021 SourceLocation IdLoc) {
23022 if (!D || D->isInvalidDecl())
23023 return;
23024 SourceRange SR = E ? E->getSourceRange() : D->getSourceRange();
23025 SourceLocation SL = E ? E->getBeginLoc() : D->getLocation();
23026 if (auto *VD = dyn_cast<VarDecl>(D)) {
23027 // Only global variables can be marked as declare target.
23028 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
23029 !VD->isStaticDataMember())
23030 return;
23031 // 2.10.6: threadprivate variable cannot appear in a declare target
23032 // directive.
23033 if (DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isThreadPrivate(VD)) {
23034 Diag(SL, diag::err_omp_threadprivate_in_target);
23035 reportOriginalDsa(*this, DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
, VD, DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getTopDSA(VD, false));
23036 return;
23037 }
23038 }
23039 if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(D))
23040 D = FTD->getTemplatedDecl();
23041 if (auto *FD = dyn_cast<FunctionDecl>(D)) {
23042 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
23043 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD);
23044 if (IdLoc.isValid() && Res && *Res == OMPDeclareTargetDeclAttr::MT_Link) {
23045 Diag(IdLoc, diag::err_omp_function_in_link_clause);
23046 Diag(FD->getLocation(), diag::note_defined_here) << FD;
23047 return;
23048 }
23049 }
23050 if (auto *VD = dyn_cast<ValueDecl>(D)) {
23051 // Problem if any with var declared with incomplete type will be reported
23052 // as normal, so no need to check it here.
23053 if ((E || !VD->getType()->isIncompleteType()) &&
23054 !checkValueDeclInTarget(SL, SR, *this, DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
, VD))
23055 return;
23056 if (!E && isInOpenMPDeclareTargetContext()) {
23057 // Checking declaration inside declare target region.
23058 if (isa<VarDecl>(D) || isa<FunctionDecl>(D) ||
23059 isa<FunctionTemplateDecl>(D)) {
23060 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
23061 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
23062 unsigned Level = DeclareTargetNesting.size();
23063 if (ActiveAttr && (*ActiveAttr)->getLevel() >= Level)
23064 return;
23065 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
23066 Expr *IndirectE = nullptr;
23067 bool IsIndirect = false;
23068 if (DTCI.Indirect) {
23069 IndirectE = *DTCI.Indirect;
23070 if (!IndirectE)
23071 IsIndirect = true;
23072 }
23073 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
23074 Context,
23075 getLangOpts().OpenMP >= 52 ? OMPDeclareTargetDeclAttr::MT_Enter
23076 : OMPDeclareTargetDeclAttr::MT_To,
23077 DTCI.DT, IndirectE, IsIndirect, Level,
23078 SourceRange(DTCI.Loc, DTCI.Loc));
23079 D->addAttr(A);
23080 if (ASTMutationListener *ML = Context.getASTMutationListener())
23081 ML->DeclarationMarkedOpenMPDeclareTarget(D, A);
23082 }
23083 return;
23084 }
23085 }
23086 if (!E)
23087 return;
23088 checkDeclInTargetContext(E->getExprLoc(), E->getSourceRange(), *this, D);
23089}
23090
23091OMPClause *Sema::ActOnOpenMPToClause(
23092 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
23093 ArrayRef<SourceLocation> MotionModifiersLoc,
23094 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
23095 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
23096 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
23097 OpenMPMotionModifierKind Modifiers[] = {OMPC_MOTION_MODIFIER_unknown,
23098 OMPC_MOTION_MODIFIER_unknown};
23099 SourceLocation ModifiersLoc[NumberOfOMPMotionModifiers];
23100
23101 // Process motion-modifiers, flag errors for duplicate modifiers.
23102 unsigned Count = 0;
23103 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
23104 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
23105 llvm::is_contained(Modifiers, MotionModifiers[I])) {
23106 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
23107 continue;
23108 }
23109 assert(Count < NumberOfOMPMotionModifiers &&(static_cast <bool> (Count < NumberOfOMPMotionModifiers
&& "Modifiers exceed the allowed number of motion modifiers"
) ? void (0) : __assert_fail ("Count < NumberOfOMPMotionModifiers && \"Modifiers exceed the allowed number of motion modifiers\""
, "clang/lib/Sema/SemaOpenMP.cpp", 23110, __extension__ __PRETTY_FUNCTION__
))
23110 "Modifiers exceed the allowed number of motion modifiers")(static_cast <bool> (Count < NumberOfOMPMotionModifiers
&& "Modifiers exceed the allowed number of motion modifiers"
) ? void (0) : __assert_fail ("Count < NumberOfOMPMotionModifiers && \"Modifiers exceed the allowed number of motion modifiers\""
, "clang/lib/Sema/SemaOpenMP.cpp", 23110, __extension__ __PRETTY_FUNCTION__
))
;
23111 Modifiers[Count] = MotionModifiers[I];
23112 ModifiersLoc[Count] = MotionModifiersLoc[I];
23113 ++Count;
23114 }
23115
23116 MappableVarListInfo MVLI(VarList);
23117 checkMappableExpressionList(*this, DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
, OMPC_to, MVLI, Locs.StartLoc,
23118 MapperIdScopeSpec, MapperId, UnresolvedMappers);
23119 if (MVLI.ProcessedVarList.empty())
23120 return nullptr;
23121
23122 return OMPToClause::Create(
23123 Context, Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23124 MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc,
23125 MapperIdScopeSpec.getWithLocInContext(Context), MapperId);
23126}
23127
23128OMPClause *Sema::ActOnOpenMPFromClause(
23129 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
23130 ArrayRef<SourceLocation> MotionModifiersLoc,
23131 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
23132 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
23133 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
23134 OpenMPMotionModifierKind Modifiers[] = {OMPC_MOTION_MODIFIER_unknown,
23135 OMPC_MOTION_MODIFIER_unknown};
23136 SourceLocation ModifiersLoc[NumberOfOMPMotionModifiers];
23137
23138 // Process motion-modifiers, flag errors for duplicate modifiers.
23139 unsigned Count = 0;
23140 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
23141 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
23142 llvm::is_contained(Modifiers, MotionModifiers[I])) {
23143 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
23144 continue;
23145 }
23146 assert(Count < NumberOfOMPMotionModifiers &&(static_cast <bool> (Count < NumberOfOMPMotionModifiers
&& "Modifiers exceed the allowed number of motion modifiers"
) ? void (0) : __assert_fail ("Count < NumberOfOMPMotionModifiers && \"Modifiers exceed the allowed number of motion modifiers\""
, "clang/lib/Sema/SemaOpenMP.cpp", 23147, __extension__ __PRETTY_FUNCTION__
))
23147 "Modifiers exceed the allowed number of motion modifiers")(static_cast <bool> (Count < NumberOfOMPMotionModifiers
&& "Modifiers exceed the allowed number of motion modifiers"
) ? void (0) : __assert_fail ("Count < NumberOfOMPMotionModifiers && \"Modifiers exceed the allowed number of motion modifiers\""
, "clang/lib/Sema/SemaOpenMP.cpp", 23147, __extension__ __PRETTY_FUNCTION__
))
;
23148 Modifiers[Count] = MotionModifiers[I];
23149 ModifiersLoc[Count] = MotionModifiersLoc[I];
23150 ++Count;
23151 }
23152
23153 MappableVarListInfo MVLI(VarList);
23154 checkMappableExpressionList(*this, DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
, OMPC_from, MVLI, Locs.StartLoc,
23155 MapperIdScopeSpec, MapperId, UnresolvedMappers);
23156 if (MVLI.ProcessedVarList.empty())
23157 return nullptr;
23158
23159 return OMPFromClause::Create(
23160 Context, Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23161 MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc,
23162 MapperIdScopeSpec.getWithLocInContext(Context), MapperId);
23163}
23164
23165OMPClause *Sema::ActOnOpenMPUseDevicePtrClause(ArrayRef<Expr *> VarList,
23166 const OMPVarListLocTy &Locs) {
23167 MappableVarListInfo MVLI(VarList);
23168 SmallVector<Expr *, 8> PrivateCopies;
23169 SmallVector<Expr *, 8> Inits;
23170
23171 for (Expr *RefExpr : VarList) {
23172 assert(RefExpr && "NULL expr in OpenMP use_device_ptr clause.")(static_cast <bool> (RefExpr && "NULL expr in OpenMP use_device_ptr clause."
) ? void (0) : __assert_fail ("RefExpr && \"NULL expr in OpenMP use_device_ptr clause.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 23172, __extension__ __PRETTY_FUNCTION__
))
;
23173 SourceLocation ELoc;
23174 SourceRange ERange;
23175 Expr *SimpleRefExpr = RefExpr;
23176 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
23177 if (Res.second) {
23178 // It will be analyzed later.
23179 MVLI.ProcessedVarList.push_back(RefExpr);
23180 PrivateCopies.push_back(nullptr);
23181 Inits.push_back(nullptr);
23182 }
23183 ValueDecl *D = Res.first;
23184 if (!D)
23185 continue;
23186
23187 QualType Type = D->getType();
23188 Type = Type.getNonReferenceType().getUnqualifiedType();
23189
23190 auto *VD = dyn_cast<VarDecl>(D);
23191
23192 // Item should be a pointer or reference to pointer.
23193 if (!Type->isPointerType()) {
23194 Diag(ELoc, diag::err_omp_usedeviceptr_not_a_pointer)
23195 << 0 << RefExpr->getSourceRange();
23196 continue;
23197 }
23198
23199 // Build the private variable and the expression that refers to it.
23200 auto VDPrivate =
23201 buildVarDecl(*this, ELoc, Type, D->getName(),
23202 D->hasAttrs() ? &D->getAttrs() : nullptr,
23203 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
23204 if (VDPrivate->isInvalidDecl())
23205 continue;
23206
23207 CurContext->addDecl(VDPrivate);
23208 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
23209 *this, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
23210
23211 // Add temporary variable to initialize the private copy of the pointer.
23212 VarDecl *VDInit =
23213 buildVarDecl(*this, RefExpr->getExprLoc(), Type, ".devptr.temp");
23214 DeclRefExpr *VDInitRefExpr = buildDeclRefExpr(
23215 *this, VDInit, RefExpr->getType(), RefExpr->getExprLoc());
23216 AddInitializerToDecl(VDPrivate,
23217 DefaultLvalueConversion(VDInitRefExpr).get(),
23218 /*DirectInit=*/false);
23219
23220 // If required, build a capture to implement the privatization initialized
23221 // with the current list item value.
23222 DeclRefExpr *Ref = nullptr;
23223 if (!VD)
23224 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true);
23225 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
23226 PrivateCopies.push_back(VDPrivateRefExpr);
23227 Inits.push_back(VDInitRefExpr);
23228
23229 // We need to add a data sharing attribute for this variable to make sure it
23230 // is correctly captured. A variable that shows up in a use_device_ptr has
23231 // similar properties of a first private variable.
23232 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
23233
23234 // Create a mappable component for the list item. List items in this clause
23235 // only need a component.
23236 MVLI.VarBaseDeclarations.push_back(D);
23237 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23238 MVLI.VarComponents.back().emplace_back(SimpleRefExpr, D,
23239 /*IsNonContiguous=*/false);
23240 }
23241
23242 if (MVLI.ProcessedVarList.empty())
23243 return nullptr;
23244
23245 return OMPUseDevicePtrClause::Create(
23246 Context, Locs, MVLI.ProcessedVarList, PrivateCopies, Inits,
23247 MVLI.VarBaseDeclarations, MVLI.VarComponents);
23248}
23249
23250OMPClause *Sema::ActOnOpenMPUseDeviceAddrClause(ArrayRef<Expr *> VarList,
23251 const OMPVarListLocTy &Locs) {
23252 MappableVarListInfo MVLI(VarList);
23253
23254 for (Expr *RefExpr : VarList) {
23255 assert(RefExpr && "NULL expr in OpenMP use_device_addr clause.")(static_cast <bool> (RefExpr && "NULL expr in OpenMP use_device_addr clause."
) ? void (0) : __assert_fail ("RefExpr && \"NULL expr in OpenMP use_device_addr clause.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 23255, __extension__ __PRETTY_FUNCTION__
))
;
23256 SourceLocation ELoc;
23257 SourceRange ERange;
23258 Expr *SimpleRefExpr = RefExpr;
23259 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange,
23260 /*AllowArraySection=*/true);
23261 if (Res.second) {
23262 // It will be analyzed later.
23263 MVLI.ProcessedVarList.push_back(RefExpr);
23264 }
23265 ValueDecl *D = Res.first;
23266 if (!D)
23267 continue;
23268 auto *VD = dyn_cast<VarDecl>(D);
23269
23270 // If required, build a capture to implement the privatization initialized
23271 // with the current list item value.
23272 DeclRefExpr *Ref = nullptr;
23273 if (!VD)
23274 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true);
23275 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
23276
23277 // We need to add a data sharing attribute for this variable to make sure it
23278 // is correctly captured. A variable that shows up in a use_device_addr has
23279 // similar properties of a first private variable.
23280 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
23281
23282 // Create a mappable component for the list item. List items in this clause
23283 // only need a component.
23284 MVLI.VarBaseDeclarations.push_back(D);
23285 MVLI.VarComponents.emplace_back();
23286 Expr *Component = SimpleRefExpr;
23287 if (VD && (isa<OMPArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) ||
23288 isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts())))
23289 Component = DefaultFunctionArrayLvalueConversion(SimpleRefExpr).get();
23290 MVLI.VarComponents.back().emplace_back(Component, D,
23291 /*IsNonContiguous=*/false);
23292 }
23293
23294 if (MVLI.ProcessedVarList.empty())
23295 return nullptr;
23296
23297 return OMPUseDeviceAddrClause::Create(Context, Locs, MVLI.ProcessedVarList,
23298 MVLI.VarBaseDeclarations,
23299 MVLI.VarComponents);
23300}
23301
23302OMPClause *Sema::ActOnOpenMPIsDevicePtrClause(ArrayRef<Expr *> VarList,
23303 const OMPVarListLocTy &Locs) {
23304 MappableVarListInfo MVLI(VarList);
23305 for (Expr *RefExpr : VarList) {
23306 assert(RefExpr && "NULL expr in OpenMP is_device_ptr clause.")(static_cast <bool> (RefExpr && "NULL expr in OpenMP is_device_ptr clause."
) ? void (0) : __assert_fail ("RefExpr && \"NULL expr in OpenMP is_device_ptr clause.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 23306, __extension__ __PRETTY_FUNCTION__
))
;
23307 SourceLocation ELoc;
23308 SourceRange ERange;
23309 Expr *SimpleRefExpr = RefExpr;
23310 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
23311 if (Res.second) {
23312 // It will be analyzed later.
23313 MVLI.ProcessedVarList.push_back(RefExpr);
23314 }
23315 ValueDecl *D = Res.first;
23316 if (!D)
23317 continue;
23318
23319 QualType Type = D->getType();
23320 // item should be a pointer or array or reference to pointer or array
23321 if (!Type.getNonReferenceType()->isPointerType() &&
23322 !Type.getNonReferenceType()->isArrayType()) {
23323 Diag(ELoc, diag::err_omp_argument_type_isdeviceptr)
23324 << 0 << RefExpr->getSourceRange();
23325 continue;
23326 }
23327
23328 // Check if the declaration in the clause does not show up in any data
23329 // sharing attribute.
23330 DSAStackTy::DSAVarData DVar = DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getTopDSA(D, /*FromParent=*/false);
23331 if (isOpenMPPrivate(DVar.CKind)) {
23332 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
23333 << getOpenMPClauseName(DVar.CKind)
23334 << getOpenMPClauseName(OMPC_is_device_ptr)
23335 << getOpenMPDirectiveName(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective());
23336 reportOriginalDsa(*this, DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
, D, DVar);
23337 continue;
23338 }
23339
23340 const Expr *ConflictExpr;
23341 if (DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->checkMappableExprComponentListsForDecl(
23342 D, /*CurrentRegionOnly=*/true,
23343 [&ConflictExpr](
23344 OMPClauseMappableExprCommon::MappableExprComponentListRef R,
23345 OpenMPClauseKind) -> bool {
23346 ConflictExpr = R.front().getAssociatedExpression();
23347 return true;
23348 })) {
23349 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
23350 Diag(ConflictExpr->getExprLoc(), diag::note_used_here)
23351 << ConflictExpr->getSourceRange();
23352 continue;
23353 }
23354
23355 // Store the components in the stack so that they can be used to check
23356 // against other clauses later on.
23357 OMPClauseMappableExprCommon::MappableComponent MC(
23358 SimpleRefExpr, D, /*IsNonContiguous=*/false);
23359 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->addMappableExpressionComponents(
23360 D, MC, /*WhereFoundClauseKind=*/OMPC_is_device_ptr);
23361
23362 // Record the expression we've just processed.
23363 MVLI.ProcessedVarList.push_back(SimpleRefExpr);
23364
23365 // Create a mappable component for the list item. List items in this clause
23366 // only need a component. We use a null declaration to signal fields in
23367 // 'this'.
23368 assert((isa<DeclRefExpr>(SimpleRefExpr) ||(static_cast <bool> ((isa<DeclRefExpr>(SimpleRefExpr
) || isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr
)->getBase())) && "Unexpected device pointer expression!"
) ? void (0) : __assert_fail ("(isa<DeclRefExpr>(SimpleRefExpr) || isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) && \"Unexpected device pointer expression!\""
, "clang/lib/Sema/SemaOpenMP.cpp", 23370, __extension__ __PRETTY_FUNCTION__
))
23369 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&(static_cast <bool> ((isa<DeclRefExpr>(SimpleRefExpr
) || isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr
)->getBase())) && "Unexpected device pointer expression!"
) ? void (0) : __assert_fail ("(isa<DeclRefExpr>(SimpleRefExpr) || isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) && \"Unexpected device pointer expression!\""
, "clang/lib/Sema/SemaOpenMP.cpp", 23370, __extension__ __PRETTY_FUNCTION__
))
23370 "Unexpected device pointer expression!")(static_cast <bool> ((isa<DeclRefExpr>(SimpleRefExpr
) || isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr
)->getBase())) && "Unexpected device pointer expression!"
) ? void (0) : __assert_fail ("(isa<DeclRefExpr>(SimpleRefExpr) || isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) && \"Unexpected device pointer expression!\""
, "clang/lib/Sema/SemaOpenMP.cpp", 23370, __extension__ __PRETTY_FUNCTION__
))
;
23371 MVLI.VarBaseDeclarations.push_back(
23372 isa<DeclRefExpr>(SimpleRefExpr) ? D : nullptr);
23373 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23374 MVLI.VarComponents.back().push_back(MC);
23375 }
23376
23377 if (MVLI.ProcessedVarList.empty())
23378 return nullptr;
23379
23380 return OMPIsDevicePtrClause::Create(Context, Locs, MVLI.ProcessedVarList,
23381 MVLI.VarBaseDeclarations,
23382 MVLI.VarComponents);
23383}
23384
23385OMPClause *Sema::ActOnOpenMPHasDeviceAddrClause(ArrayRef<Expr *> VarList,
23386 const OMPVarListLocTy &Locs) {
23387 MappableVarListInfo MVLI(VarList);
23388 for (Expr *RefExpr : VarList) {
23389 assert(RefExpr && "NULL expr in OpenMP has_device_addr clause.")(static_cast <bool> (RefExpr && "NULL expr in OpenMP has_device_addr clause."
) ? void (0) : __assert_fail ("RefExpr && \"NULL expr in OpenMP has_device_addr clause.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 23389, __extension__ __PRETTY_FUNCTION__
))
;
23390 SourceLocation ELoc;
23391 SourceRange ERange;
23392 Expr *SimpleRefExpr = RefExpr;
23393 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange,
23394 /*AllowArraySection=*/true);
23395 if (Res.second) {
23396 // It will be analyzed later.
23397 MVLI.ProcessedVarList.push_back(RefExpr);
23398 }
23399 ValueDecl *D = Res.first;
23400 if (!D)
23401 continue;
23402
23403 // Check if the declaration in the clause does not show up in any data
23404 // sharing attribute.
23405 DSAStackTy::DSAVarData DVar = DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getTopDSA(D, /*FromParent=*/false);
23406 if (isOpenMPPrivate(DVar.CKind)) {
23407 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
23408 << getOpenMPClauseName(DVar.CKind)
23409 << getOpenMPClauseName(OMPC_has_device_addr)
23410 << getOpenMPDirectiveName(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective());
23411 reportOriginalDsa(*this, DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
, D, DVar);
23412 continue;
23413 }
23414
23415 const Expr *ConflictExpr;
23416 if (DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->checkMappableExprComponentListsForDecl(
23417 D, /*CurrentRegionOnly=*/true,
23418 [&ConflictExpr](
23419 OMPClauseMappableExprCommon::MappableExprComponentListRef R,
23420 OpenMPClauseKind) -> bool {
23421 ConflictExpr = R.front().getAssociatedExpression();
23422 return true;
23423 })) {
23424 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
23425 Diag(ConflictExpr->getExprLoc(), diag::note_used_here)
23426 << ConflictExpr->getSourceRange();
23427 continue;
23428 }
23429
23430 // Store the components in the stack so that they can be used to check
23431 // against other clauses later on.
23432 Expr *Component = SimpleRefExpr;
23433 auto *VD = dyn_cast<VarDecl>(D);
23434 if (VD && (isa<OMPArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) ||
23435 isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts())))
23436 Component = DefaultFunctionArrayLvalueConversion(SimpleRefExpr).get();
23437 OMPClauseMappableExprCommon::MappableComponent MC(
23438 Component, D, /*IsNonContiguous=*/false);
23439 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->addMappableExpressionComponents(
23440 D, MC, /*WhereFoundClauseKind=*/OMPC_has_device_addr);
23441
23442 // Record the expression we've just processed.
23443 if (!VD && !CurContext->isDependentContext()) {
23444 DeclRefExpr *Ref =
23445 buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true);
23446 assert(Ref && "has_device_addr capture failed")(static_cast <bool> (Ref && "has_device_addr capture failed"
) ? void (0) : __assert_fail ("Ref && \"has_device_addr capture failed\""
, "clang/lib/Sema/SemaOpenMP.cpp", 23446, __extension__ __PRETTY_FUNCTION__
))
;
23447 MVLI.ProcessedVarList.push_back(Ref);
23448 } else
23449 MVLI.ProcessedVarList.push_back(RefExpr->IgnoreParens());
23450
23451 // Create a mappable component for the list item. List items in this clause
23452 // only need a component. We use a null declaration to signal fields in
23453 // 'this'.
23454 assert((isa<DeclRefExpr>(SimpleRefExpr) ||(static_cast <bool> ((isa<DeclRefExpr>(SimpleRefExpr
) || isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr
)->getBase())) && "Unexpected device pointer expression!"
) ? void (0) : __assert_fail ("(isa<DeclRefExpr>(SimpleRefExpr) || isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) && \"Unexpected device pointer expression!\""
, "clang/lib/Sema/SemaOpenMP.cpp", 23456, __extension__ __PRETTY_FUNCTION__
))
23455 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&(static_cast <bool> ((isa<DeclRefExpr>(SimpleRefExpr
) || isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr
)->getBase())) && "Unexpected device pointer expression!"
) ? void (0) : __assert_fail ("(isa<DeclRefExpr>(SimpleRefExpr) || isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) && \"Unexpected device pointer expression!\""
, "clang/lib/Sema/SemaOpenMP.cpp", 23456, __extension__ __PRETTY_FUNCTION__
))
23456 "Unexpected device pointer expression!")(static_cast <bool> ((isa<DeclRefExpr>(SimpleRefExpr
) || isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr
)->getBase())) && "Unexpected device pointer expression!"
) ? void (0) : __assert_fail ("(isa<DeclRefExpr>(SimpleRefExpr) || isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) && \"Unexpected device pointer expression!\""
, "clang/lib/Sema/SemaOpenMP.cpp", 23456, __extension__ __PRETTY_FUNCTION__
))
;
23457 MVLI.VarBaseDeclarations.push_back(
23458 isa<DeclRefExpr>(SimpleRefExpr) ? D : nullptr);
23459 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23460 MVLI.VarComponents.back().push_back(MC);
23461 }
23462
23463 if (MVLI.ProcessedVarList.empty())
23464 return nullptr;
23465
23466 return OMPHasDeviceAddrClause::Create(Context, Locs, MVLI.ProcessedVarList,
23467 MVLI.VarBaseDeclarations,
23468 MVLI.VarComponents);
23469}
23470
23471OMPClause *Sema::ActOnOpenMPAllocateClause(
23472 Expr *Allocator, ArrayRef<Expr *> VarList, SourceLocation StartLoc,
23473 SourceLocation ColonLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
23474 if (Allocator) {
23475 // OpenMP [2.11.4 allocate Clause, Description]
23476 // allocator is an expression of omp_allocator_handle_t type.
23477 if (!findOMPAllocatorHandleT(*this, Allocator->getExprLoc(), DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
))
23478 return nullptr;
23479
23480 ExprResult AllocatorRes = DefaultLvalueConversion(Allocator);
23481 if (AllocatorRes.isInvalid())
23482 return nullptr;
23483 AllocatorRes = PerformImplicitConversion(AllocatorRes.get(),
23484 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getOMPAllocatorHandleT(),
23485 Sema::AA_Initializing,
23486 /*AllowExplicit=*/true);
23487 if (AllocatorRes.isInvalid())
23488 return nullptr;
23489 Allocator = AllocatorRes.get();
23490 } else {
23491 // OpenMP 5.0, 2.11.4 allocate Clause, Restrictions.
23492 // allocate clauses that appear on a target construct or on constructs in a
23493 // target region must specify an allocator expression unless a requires
23494 // directive with the dynamic_allocators clause is present in the same
23495 // compilation unit.
23496 if (LangOpts.OpenMPIsDevice &&
23497 !DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
23498 targetDiag(StartLoc, diag::err_expected_allocator_expression);
23499 }
23500 // Analyze and build list of variables.
23501 SmallVector<Expr *, 8> Vars;
23502 for (Expr *RefExpr : VarList) {
23503 assert(RefExpr && "NULL expr in OpenMP private clause.")(static_cast <bool> (RefExpr && "NULL expr in OpenMP private clause."
) ? void (0) : __assert_fail ("RefExpr && \"NULL expr in OpenMP private clause.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 23503, __extension__ __PRETTY_FUNCTION__
))
;
23504 SourceLocation ELoc;
23505 SourceRange ERange;
23506 Expr *SimpleRefExpr = RefExpr;
23507 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
23508 if (Res.second) {
23509 // It will be analyzed later.
23510 Vars.push_back(RefExpr);
23511 }
23512 ValueDecl *D = Res.first;
23513 if (!D)
23514 continue;
23515
23516 auto *VD = dyn_cast<VarDecl>(D);
23517 DeclRefExpr *Ref = nullptr;
23518 if (!VD && !CurContext->isDependentContext())
23519 Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/false);
23520 Vars.push_back((VD || CurContext->isDependentContext())
23521 ? RefExpr->IgnoreParens()
23522 : Ref);
23523 }
23524
23525 if (Vars.empty())
23526 return nullptr;
23527
23528 if (Allocator)
23529 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->addInnerAllocatorExpr(Allocator);
23530 return OMPAllocateClause::Create(Context, StartLoc, LParenLoc, Allocator,
23531 ColonLoc, EndLoc, Vars);
23532}
23533
23534OMPClause *Sema::ActOnOpenMPNontemporalClause(ArrayRef<Expr *> VarList,
23535 SourceLocation StartLoc,
23536 SourceLocation LParenLoc,
23537 SourceLocation EndLoc) {
23538 SmallVector<Expr *, 8> Vars;
23539 for (Expr *RefExpr : VarList) {
23540 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.")(static_cast <bool> (RefExpr && "NULL expr in OpenMP nontemporal clause."
) ? void (0) : __assert_fail ("RefExpr && \"NULL expr in OpenMP nontemporal clause.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 23540, __extension__ __PRETTY_FUNCTION__
))
;
23541 SourceLocation ELoc;
23542 SourceRange ERange;
23543 Expr *SimpleRefExpr = RefExpr;
23544 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
23545 if (Res.second)
23546 // It will be analyzed later.
23547 Vars.push_back(RefExpr);
23548 ValueDecl *D = Res.first;
23549 if (!D)
23550 continue;
23551
23552 // OpenMP 5.0, 2.9.3.1 simd Construct, Restrictions.
23553 // A list-item cannot appear in more than one nontemporal clause.
23554 if (const Expr *PrevRef =
23555 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->addUniqueNontemporal(D, SimpleRefExpr)) {
23556 Diag(ELoc, diag::err_omp_used_in_clause_twice)
23557 << 0 << getOpenMPClauseName(OMPC_nontemporal) << ERange;
23558 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
23559 << getOpenMPClauseName(OMPC_nontemporal);
23560 continue;
23561 }
23562
23563 Vars.push_back(RefExpr);
23564 }
23565
23566 if (Vars.empty())
23567 return nullptr;
23568
23569 return OMPNontemporalClause::Create(Context, StartLoc, LParenLoc, EndLoc,
23570 Vars);
23571}
23572
23573OMPClause *Sema::ActOnOpenMPInclusiveClause(ArrayRef<Expr *> VarList,
23574 SourceLocation StartLoc,
23575 SourceLocation LParenLoc,
23576 SourceLocation EndLoc) {
23577 SmallVector<Expr *, 8> Vars;
23578 for (Expr *RefExpr : VarList) {
23579 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.")(static_cast <bool> (RefExpr && "NULL expr in OpenMP nontemporal clause."
) ? void (0) : __assert_fail ("RefExpr && \"NULL expr in OpenMP nontemporal clause.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 23579, __extension__ __PRETTY_FUNCTION__
))
;
23580 SourceLocation ELoc;
23581 SourceRange ERange;
23582 Expr *SimpleRefExpr = RefExpr;
23583 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange,
23584 /*AllowArraySection=*/true);
23585 if (Res.second)
23586 // It will be analyzed later.
23587 Vars.push_back(RefExpr);
23588 ValueDecl *D = Res.first;
23589 if (!D)
23590 continue;
23591
23592 const DSAStackTy::DSAVarData DVar =
23593 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getTopDSA(D, /*FromParent=*/true);
23594 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
23595 // A list item that appears in the inclusive or exclusive clause must appear
23596 // in a reduction clause with the inscan modifier on the enclosing
23597 // worksharing-loop, worksharing-loop SIMD, or simd construct.
23598 if (DVar.CKind != OMPC_reduction || DVar.Modifier != OMPC_REDUCTION_inscan)
23599 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
23600 << RefExpr->getSourceRange();
23601
23602 if (DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getParentDirective() != OMPD_unknown)
23603 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->markDeclAsUsedInScanDirective(D);
23604 Vars.push_back(RefExpr);
23605 }
23606
23607 if (Vars.empty())
23608 return nullptr;
23609
23610 return OMPInclusiveClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars);
23611}
23612
23613OMPClause *Sema::ActOnOpenMPExclusiveClause(ArrayRef<Expr *> VarList,
23614 SourceLocation StartLoc,
23615 SourceLocation LParenLoc,
23616 SourceLocation EndLoc) {
23617 SmallVector<Expr *, 8> Vars;
23618 for (Expr *RefExpr : VarList) {
23619 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.")(static_cast <bool> (RefExpr && "NULL expr in OpenMP nontemporal clause."
) ? void (0) : __assert_fail ("RefExpr && \"NULL expr in OpenMP nontemporal clause.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 23619, __extension__ __PRETTY_FUNCTION__
))
;
23620 SourceLocation ELoc;
23621 SourceRange ERange;
23622 Expr *SimpleRefExpr = RefExpr;
23623 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange,
23624 /*AllowArraySection=*/true);
23625 if (Res.second)
23626 // It will be analyzed later.
23627 Vars.push_back(RefExpr);
23628 ValueDecl *D = Res.first;
23629 if (!D)
23630 continue;
23631
23632 OpenMPDirectiveKind ParentDirective = DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getParentDirective();
23633 DSAStackTy::DSAVarData DVar;
23634 if (ParentDirective != OMPD_unknown)
23635 DVar = DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getTopDSA(D, /*FromParent=*/true);
23636 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
23637 // A list item that appears in the inclusive or exclusive clause must appear
23638 // in a reduction clause with the inscan modifier on the enclosing
23639 // worksharing-loop, worksharing-loop SIMD, or simd construct.
23640 if (ParentDirective == OMPD_unknown || DVar.CKind != OMPC_reduction ||
23641 DVar.Modifier != OMPC_REDUCTION_inscan) {
23642 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
23643 << RefExpr->getSourceRange();
23644 } else {
23645 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->markDeclAsUsedInScanDirective(D);
23646 }
23647 Vars.push_back(RefExpr);
23648 }
23649
23650 if (Vars.empty())
23651 return nullptr;
23652
23653 return OMPExclusiveClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars);
23654}
23655
23656/// Tries to find omp_alloctrait_t type.
23657static bool findOMPAlloctraitT(Sema &S, SourceLocation Loc, DSAStackTy *Stack) {
23658 QualType OMPAlloctraitT = Stack->getOMPAlloctraitT();
23659 if (!OMPAlloctraitT.isNull())
23660 return true;
23661 IdentifierInfo &II = S.PP.getIdentifierTable().get("omp_alloctrait_t");
23662 ParsedType PT = S.getTypeName(II, Loc, S.getCurScope());
23663 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
23664 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_alloctrait_t";
23665 return false;
23666 }
23667 Stack->setOMPAlloctraitT(PT.get());
23668 return true;
23669}
23670
23671OMPClause *Sema::ActOnOpenMPUsesAllocatorClause(
23672 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc,
23673 ArrayRef<UsesAllocatorsData> Data) {
23674 // OpenMP [2.12.5, target Construct]
23675 // allocator is an identifier of omp_allocator_handle_t type.
23676 if (!findOMPAllocatorHandleT(*this, StartLoc, DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
))
23677 return nullptr;
23678 // OpenMP [2.12.5, target Construct]
23679 // allocator-traits-array is an identifier of const omp_alloctrait_t * type.
23680 if (llvm::any_of(
23681 Data,
23682 [](const UsesAllocatorsData &D) { return D.AllocatorTraits; }) &&
23683 !findOMPAlloctraitT(*this, StartLoc, DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
))
23684 return nullptr;
23685 llvm::SmallPtrSet<CanonicalDeclPtr<Decl>, 4> PredefinedAllocators;
23686 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
23687 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
23688 StringRef Allocator =
23689 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
23690 DeclarationName AllocatorName = &Context.Idents.get(Allocator);
23691 PredefinedAllocators.insert(LookupSingleName(
23692 TUScope, AllocatorName, StartLoc, Sema::LookupAnyName));
23693 }
23694
23695 SmallVector<OMPUsesAllocatorsClause::Data, 4> NewData;
23696 for (const UsesAllocatorsData &D : Data) {
23697 Expr *AllocatorExpr = nullptr;
23698 // Check allocator expression.
23699 if (D.Allocator->isTypeDependent()) {
23700 AllocatorExpr = D.Allocator;
23701 } else {
23702 // Traits were specified - need to assign new allocator to the specified
23703 // allocator, so it must be an lvalue.
23704 AllocatorExpr = D.Allocator->IgnoreParenImpCasts();
23705 auto *DRE = dyn_cast<DeclRefExpr>(AllocatorExpr);
23706 bool IsPredefinedAllocator = false;
23707 if (DRE) {
23708 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorTy =
23709 getAllocatorKind(*this, DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
, AllocatorExpr);
23710 IsPredefinedAllocator =
23711 AllocatorTy !=
23712 OMPAllocateDeclAttr::AllocatorTypeTy::OMPUserDefinedMemAlloc;
23713 }
23714 QualType OMPAllocatorHandleT = DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getOMPAllocatorHandleT();
23715 QualType AllocatorExprType = AllocatorExpr->getType();
23716 bool IsTypeCompatible = IsPredefinedAllocator;
23717 IsTypeCompatible = IsTypeCompatible ||
23718 Context.hasSameUnqualifiedType(AllocatorExprType,
23719 OMPAllocatorHandleT);
23720 IsTypeCompatible =
23721 IsTypeCompatible ||
23722 Context.typesAreCompatible(AllocatorExprType, OMPAllocatorHandleT);
23723 bool IsNonConstantLValue =
23724 !AllocatorExprType.isConstant(Context) && AllocatorExpr->isLValue();
23725 if (!DRE || !IsTypeCompatible ||
23726 (!IsPredefinedAllocator && !IsNonConstantLValue)) {
23727 Diag(D.Allocator->getExprLoc(), diag::err_omp_var_expected)
23728 << "omp_allocator_handle_t" << (DRE ? 1 : 0)
23729 << AllocatorExpr->getType() << D.Allocator->getSourceRange();
23730 continue;
23731 }
23732 // OpenMP [2.12.5, target Construct]
23733 // Predefined allocators appearing in a uses_allocators clause cannot have
23734 // traits specified.
23735 if (IsPredefinedAllocator && D.AllocatorTraits) {
23736 Diag(D.AllocatorTraits->getExprLoc(),
23737 diag::err_omp_predefined_allocator_with_traits)
23738 << D.AllocatorTraits->getSourceRange();
23739 Diag(D.Allocator->getExprLoc(), diag::note_omp_predefined_allocator)
23740 << cast<NamedDecl>(DRE->getDecl())->getName()
23741 << D.Allocator->getSourceRange();
23742 continue;
23743 }
23744 // OpenMP [2.12.5, target Construct]
23745 // Non-predefined allocators appearing in a uses_allocators clause must
23746 // have traits specified.
23747 if (!IsPredefinedAllocator && !D.AllocatorTraits) {
23748 Diag(D.Allocator->getExprLoc(),
23749 diag::err_omp_nonpredefined_allocator_without_traits);
23750 continue;
23751 }
23752 // No allocator traits - just convert it to rvalue.
23753 if (!D.AllocatorTraits)
23754 AllocatorExpr = DefaultLvalueConversion(AllocatorExpr).get();
23755 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->addUsesAllocatorsDecl(
23756 DRE->getDecl(),
23757 IsPredefinedAllocator
23758 ? DSAStackTy::UsesAllocatorsDeclKind::PredefinedAllocator
23759 : DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator);
23760 }
23761 Expr *AllocatorTraitsExpr = nullptr;
23762 if (D.AllocatorTraits) {
23763 if (D.AllocatorTraits->isTypeDependent()) {
23764 AllocatorTraitsExpr = D.AllocatorTraits;
23765 } else {
23766 // OpenMP [2.12.5, target Construct]
23767 // Arrays that contain allocator traits that appear in a uses_allocators
23768 // clause must be constant arrays, have constant values and be defined
23769 // in the same scope as the construct in which the clause appears.
23770 AllocatorTraitsExpr = D.AllocatorTraits->IgnoreParenImpCasts();
23771 // Check that traits expr is a constant array.
23772 QualType TraitTy;
23773 if (const ArrayType *Ty =
23774 AllocatorTraitsExpr->getType()->getAsArrayTypeUnsafe())
23775 if (const auto *ConstArrayTy = dyn_cast<ConstantArrayType>(Ty))
23776 TraitTy = ConstArrayTy->getElementType();
23777 if (TraitTy.isNull() ||
23778 !(Context.hasSameUnqualifiedType(TraitTy,
23779 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getOMPAlloctraitT()) ||
23780 Context.typesAreCompatible(TraitTy, DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getOMPAlloctraitT(),
23781 /*CompareUnqualified=*/true))) {
23782 Diag(D.AllocatorTraits->getExprLoc(),
23783 diag::err_omp_expected_array_alloctraits)
23784 << AllocatorTraitsExpr->getType();
23785 continue;
23786 }
23787 // Do not map by default allocator traits if it is a standalone
23788 // variable.
23789 if (auto *DRE = dyn_cast<DeclRefExpr>(AllocatorTraitsExpr))
23790 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->addUsesAllocatorsDecl(
23791 DRE->getDecl(),
23792 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait);
23793 }
23794 }
23795 OMPUsesAllocatorsClause::Data &NewD = NewData.emplace_back();
23796 NewD.Allocator = AllocatorExpr;
23797 NewD.AllocatorTraits = AllocatorTraitsExpr;
23798 NewD.LParenLoc = D.LParenLoc;
23799 NewD.RParenLoc = D.RParenLoc;
23800 }
23801 return OMPUsesAllocatorsClause::Create(Context, StartLoc, LParenLoc, EndLoc,
23802 NewData);
23803}
23804
23805OMPClause *Sema::ActOnOpenMPAffinityClause(
23806 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
23807 SourceLocation EndLoc, Expr *Modifier, ArrayRef<Expr *> Locators) {
23808 SmallVector<Expr *, 8> Vars;
23809 for (Expr *RefExpr : Locators) {
23810 assert(RefExpr && "NULL expr in OpenMP shared clause.")(static_cast <bool> (RefExpr && "NULL expr in OpenMP shared clause."
) ? void (0) : __assert_fail ("RefExpr && \"NULL expr in OpenMP shared clause.\""
, "clang/lib/Sema/SemaOpenMP.cpp", 23810, __extension__ __PRETTY_FUNCTION__
))
;
23811 if (isa<DependentScopeDeclRefExpr>(RefExpr) || RefExpr->isTypeDependent()) {
23812 // It will be analyzed later.
23813 Vars.push_back(RefExpr);
23814 continue;
23815 }
23816
23817 SourceLocation ELoc = RefExpr->getExprLoc();
23818 Expr *SimpleExpr = RefExpr->IgnoreParenImpCasts();
23819
23820 if (!SimpleExpr->isLValue()) {
23821 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
23822 << 1 << 0 << RefExpr->getSourceRange();
23823 continue;
23824 }
23825
23826 ExprResult Res;
23827 {
23828 Sema::TentativeAnalysisScope Trap(*this);
23829 Res = CreateBuiltinUnaryOp(ELoc, UO_AddrOf, SimpleExpr);
23830 }
23831 if (!Res.isUsable() && !isa<OMPArraySectionExpr>(SimpleExpr) &&
23832 !isa<OMPArrayShapingExpr>(SimpleExpr)) {
23833 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
23834 << 1 << 0 << RefExpr->getSourceRange();
23835 continue;
23836 }
23837 Vars.push_back(SimpleExpr);
23838 }
23839
23840 return OMPAffinityClause::Create(Context, StartLoc, LParenLoc, ColonLoc,
23841 EndLoc, Modifier, Vars);
23842}
23843
23844OMPClause *Sema::ActOnOpenMPBindClause(OpenMPBindClauseKind Kind,
23845 SourceLocation KindLoc,
23846 SourceLocation StartLoc,
23847 SourceLocation LParenLoc,
23848 SourceLocation EndLoc) {
23849 if (Kind == OMPC_BIND_unknown) {
23850 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23851 << getListOfPossibleValues(OMPC_bind, /*First=*/0,
23852 /*Last=*/unsigned(OMPC_BIND_unknown))
23853 << getOpenMPClauseName(OMPC_bind);
23854 return nullptr;
23855 }
23856
23857 return OMPBindClause::Create(Context, Kind, KindLoc, StartLoc, LParenLoc,
23858 EndLoc);
23859}
23860
23861OMPClause *Sema::ActOnOpenMPXDynCGroupMemClause(Expr *Size,
23862 SourceLocation StartLoc,
23863 SourceLocation LParenLoc,
23864 SourceLocation EndLoc) {
23865 Expr *ValExpr = Size;
23866 Stmt *HelperValStmt = nullptr;
23867
23868 // OpenMP [2.5, Restrictions]
23869 // The ompx_dyn_cgroup_mem expression must evaluate to a positive integer
23870 // value.
23871 if (!isNonNegativeIntegerValue(ValExpr, *this, OMPC_ompx_dyn_cgroup_mem,
23872 /*StrictlyPositive=*/false))
23873 return nullptr;
23874
23875 OpenMPDirectiveKind DKind = DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective();
23876 OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause(
23877 DKind, OMPC_ompx_dyn_cgroup_mem, LangOpts.OpenMP);
23878 if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
23879 ValExpr = MakeFullExpr(ValExpr).get();
23880 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
23881 ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
23882 HelperValStmt = buildPreInits(Context, Captures);
23883 }
23884
23885 return new (Context) OMPXDynCGroupMemClause(
23886 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
23887}