Bug Summary

File:build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/clang/lib/Sema/SemaOpenMP.cpp
Warning:line 20512, column 7
Value stored to 'ErrorFound' is never read

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/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/build-llvm -resource-dir /usr/lib/llvm-16/lib/clang/16.0.0 -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I tools/clang/lib/Sema -I /build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/clang/lib/Sema -I /build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/clang/include -I tools/clang/include -I include -I /build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/llvm/include -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-16/lib/clang/16.0.0/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/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/build-llvm=build-llvm -fmacro-prefix-map=/build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/= -fcoverage-prefix-map=/build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/build-llvm=build-llvm -fcoverage-prefix-map=/build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/= -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/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/build-llvm -fdebug-prefix-map=/build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/build-llvm=build-llvm -fdebug-prefix-map=/build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/= -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-2022-09-04-125545-48738-1 -x c++ /build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/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/Initialization.h"
31#include "clang/Sema/Lookup.h"
32#include "clang/Sema/Scope.h"
33#include "clang/Sema/ScopeInfo.h"
34#include "clang/Sema/SemaInternal.h"
35#include "llvm/ADT/IndexedMap.h"
36#include "llvm/ADT/PointerEmbeddedInt.h"
37#include "llvm/ADT/STLExtras.h"
38#include "llvm/ADT/SmallSet.h"
39#include "llvm/ADT/StringExtras.h"
40#include "llvm/Frontend/OpenMP/OMPAssume.h"
41#include "llvm/Frontend/OpenMP/OMPConstants.h"
42#include <set>
43
44using namespace clang;
45using namespace llvm::omp;
46
47//===----------------------------------------------------------------------===//
48// Stack of data-sharing attributes for variables
49//===----------------------------------------------------------------------===//
50
51static const Expr *checkMapClauseExpressionBase(
52 Sema &SemaRef, Expr *E,
53 OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents,
54 OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose);
55
56namespace {
57/// Default data sharing attributes, which can be applied to directive.
58enum DefaultDataSharingAttributes {
59 DSA_unspecified = 0, /// Data sharing attribute not specified.
60 DSA_none = 1 << 0, /// Default data sharing attribute 'none'.
61 DSA_shared = 1 << 1, /// Default data sharing attribute 'shared'.
62 DSA_private = 1 << 2, /// Default data sharing attribute 'private'.
63 DSA_firstprivate = 1 << 3, /// Default data sharing attribute 'firstprivate'.
64};
65
66/// Stack for tracking declarations used in OpenMP directives and
67/// clauses and their data-sharing attributes.
68class DSAStackTy {
69public:
70 struct DSAVarData {
71 OpenMPDirectiveKind DKind = OMPD_unknown;
72 OpenMPClauseKind CKind = OMPC_unknown;
73 unsigned Modifier = 0;
74 const Expr *RefExpr = nullptr;
75 DeclRefExpr *PrivateCopy = nullptr;
76 SourceLocation ImplicitDSALoc;
77 bool AppliedToPointee = false;
78 DSAVarData() = default;
79 DSAVarData(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind,
80 const Expr *RefExpr, DeclRefExpr *PrivateCopy,
81 SourceLocation ImplicitDSALoc, unsigned Modifier,
82 bool AppliedToPointee)
83 : DKind(DKind), CKind(CKind), Modifier(Modifier), RefExpr(RefExpr),
84 PrivateCopy(PrivateCopy), ImplicitDSALoc(ImplicitDSALoc),
85 AppliedToPointee(AppliedToPointee) {}
86 };
87 using OperatorOffsetTy =
88 llvm::SmallVector<std::pair<Expr *, OverloadedOperatorKind>, 4>;
89 using DoacrossDependMapTy =
90 llvm::DenseMap<OMPDependClause *, OperatorOffsetTy>;
91 /// Kind of the declaration used in the uses_allocators clauses.
92 enum class UsesAllocatorsDeclKind {
93 /// Predefined allocator
94 PredefinedAllocator,
95 /// User-defined allocator
96 UserDefinedAllocator,
97 /// The declaration that represent allocator trait
98 AllocatorTrait,
99 };
100
101private:
102 struct DSAInfo {
103 OpenMPClauseKind Attributes = OMPC_unknown;
104 unsigned Modifier = 0;
105 /// Pointer to a reference expression and a flag which shows that the
106 /// variable is marked as lastprivate(true) or not (false).
107 llvm::PointerIntPair<const Expr *, 1, bool> RefExpr;
108 DeclRefExpr *PrivateCopy = nullptr;
109 /// true if the attribute is applied to the pointee, not the variable
110 /// itself.
111 bool AppliedToPointee = false;
112 };
113 using DeclSAMapTy = llvm::SmallDenseMap<const ValueDecl *, DSAInfo, 8>;
114 using UsedRefMapTy = llvm::SmallDenseMap<const ValueDecl *, const Expr *, 8>;
115 using LCDeclInfo = std::pair<unsigned, VarDecl *>;
116 using LoopControlVariablesMapTy =
117 llvm::SmallDenseMap<const ValueDecl *, LCDeclInfo, 8>;
118 /// Struct that associates a component with the clause kind where they are
119 /// found.
120 struct MappedExprComponentTy {
121 OMPClauseMappableExprCommon::MappableExprComponentLists Components;
122 OpenMPClauseKind Kind = OMPC_unknown;
123 };
124 using MappedExprComponentsTy =
125 llvm::DenseMap<const ValueDecl *, MappedExprComponentTy>;
126 using CriticalsWithHintsTy =
127 llvm::StringMap<std::pair<const OMPCriticalDirective *, llvm::APSInt>>;
128 struct ReductionData {
129 using BOKPtrType = llvm::PointerEmbeddedInt<BinaryOperatorKind, 16>;
130 SourceRange ReductionRange;
131 llvm::PointerUnion<const Expr *, BOKPtrType> ReductionOp;
132 ReductionData() = default;
133 void set(BinaryOperatorKind BO, SourceRange RR) {
134 ReductionRange = RR;
135 ReductionOp = BO;
136 }
137 void set(const Expr *RefExpr, SourceRange RR) {
138 ReductionRange = RR;
139 ReductionOp = RefExpr;
140 }
141 };
142 using DeclReductionMapTy =
143 llvm::SmallDenseMap<const ValueDecl *, ReductionData, 4>;
144 struct DefaultmapInfo {
145 OpenMPDefaultmapClauseModifier ImplicitBehavior =
146 OMPC_DEFAULTMAP_MODIFIER_unknown;
147 SourceLocation SLoc;
148 DefaultmapInfo() = default;
149 DefaultmapInfo(OpenMPDefaultmapClauseModifier M, SourceLocation Loc)
150 : ImplicitBehavior(M), SLoc(Loc) {}
151 };
152
153 struct SharingMapTy {
154 DeclSAMapTy SharingMap;
155 DeclReductionMapTy ReductionMap;
156 UsedRefMapTy AlignedMap;
157 UsedRefMapTy NontemporalMap;
158 MappedExprComponentsTy MappedExprComponents;
159 LoopControlVariablesMapTy LCVMap;
160 DefaultDataSharingAttributes DefaultAttr = DSA_unspecified;
161 SourceLocation DefaultAttrLoc;
162 DefaultmapInfo DefaultmapMap[OMPC_DEFAULTMAP_unknown];
163 OpenMPDirectiveKind Directive = OMPD_unknown;
164 DeclarationNameInfo DirectiveName;
165 Scope *CurScope = nullptr;
166 DeclContext *Context = nullptr;
167 SourceLocation ConstructLoc;
168 /// Set of 'depend' clauses with 'sink|source' dependence kind. Required to
169 /// get the data (loop counters etc.) about enclosing loop-based construct.
170 /// This data is required during codegen.
171 DoacrossDependMapTy DoacrossDepends;
172 /// First argument (Expr *) contains optional argument of the
173 /// 'ordered' clause, the second one is true if the regions has 'ordered'
174 /// clause, false otherwise.
175 llvm::Optional<std::pair<const Expr *, OMPOrderedClause *>> OrderedRegion;
176 unsigned AssociatedLoops = 1;
177 bool HasMutipleLoops = false;
178 const Decl *PossiblyLoopCounter = nullptr;
179 bool NowaitRegion = false;
180 bool UntiedRegion = false;
181 bool CancelRegion = false;
182 bool LoopStart = false;
183 bool BodyComplete = false;
184 SourceLocation PrevScanLocation;
185 SourceLocation PrevOrderedLocation;
186 SourceLocation InnerTeamsRegionLoc;
187 /// Reference to the taskgroup task_reduction reference expression.
188 Expr *TaskgroupReductionRef = nullptr;
189 llvm::DenseSet<QualType> MappedClassesQualTypes;
190 SmallVector<Expr *, 4> InnerUsedAllocators;
191 llvm::DenseSet<CanonicalDeclPtr<Decl>> ImplicitTaskFirstprivates;
192 /// List of globals marked as declare target link in this target region
193 /// (isOpenMPTargetExecutionDirective(Directive) == true).
194 llvm::SmallVector<DeclRefExpr *, 4> DeclareTargetLinkVarDecls;
195 /// List of decls used in inclusive/exclusive clauses of the scan directive.
196 llvm::DenseSet<CanonicalDeclPtr<Decl>> UsedInScanDirective;
197 llvm::DenseMap<CanonicalDeclPtr<const Decl>, UsesAllocatorsDeclKind>
198 UsesAllocatorsDecls;
199 /// Data is required on creating capture fields for implicit
200 /// default first|private clause.
201 struct ImplicitDefaultFDInfoTy {
202 /// Field decl.
203 const FieldDecl *FD = nullptr;
204 /// Nesting stack level
205 size_t StackLevel = 0;
206 /// Capture variable decl.
207 VarDecl *VD = nullptr;
208 ImplicitDefaultFDInfoTy(const FieldDecl *FD, size_t StackLevel,
209 VarDecl *VD)
210 : FD(FD), StackLevel(StackLevel), VD(VD) {}
211 };
212 /// List of captured fields
213 llvm::SmallVector<ImplicitDefaultFDInfoTy, 8>
214 ImplicitDefaultFirstprivateFDs;
215 Expr *DeclareMapperVar = nullptr;
216 SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name,
217 Scope *CurScope, SourceLocation Loc)
218 : Directive(DKind), DirectiveName(Name), CurScope(CurScope),
219 ConstructLoc(Loc) {}
220 SharingMapTy() = default;
221 };
222
223 using StackTy = SmallVector<SharingMapTy, 4>;
224
225 /// Stack of used declaration and their data-sharing attributes.
226 DeclSAMapTy Threadprivates;
227 const FunctionScopeInfo *CurrentNonCapturingFunctionScope = nullptr;
228 SmallVector<std::pair<StackTy, const FunctionScopeInfo *>, 4> Stack;
229 /// true, if check for DSA must be from parent directive, false, if
230 /// from current directive.
231 OpenMPClauseKind ClauseKindMode = OMPC_unknown;
232 Sema &SemaRef;
233 bool ForceCapturing = false;
234 /// true if all the variables in the target executable directives must be
235 /// captured by reference.
236 bool ForceCaptureByReferenceInTargetExecutable = false;
237 CriticalsWithHintsTy Criticals;
238 unsigned IgnoredStackElements = 0;
239
240 /// Iterators over the stack iterate in order from innermost to outermost
241 /// directive.
242 using const_iterator = StackTy::const_reverse_iterator;
243 const_iterator begin() const {
244 return Stack.empty() ? const_iterator()
245 : Stack.back().first.rbegin() + IgnoredStackElements;
246 }
247 const_iterator end() const {
248 return Stack.empty() ? const_iterator() : Stack.back().first.rend();
249 }
250 using iterator = StackTy::reverse_iterator;
251 iterator begin() {
252 return Stack.empty() ? iterator()
253 : Stack.back().first.rbegin() + IgnoredStackElements;
254 }
255 iterator end() {
256 return Stack.empty() ? iterator() : Stack.back().first.rend();
257 }
258
259 // Convenience operations to get at the elements of the stack.
260
261 bool isStackEmpty() const {
262 return Stack.empty() ||
263 Stack.back().second != CurrentNonCapturingFunctionScope ||
264 Stack.back().first.size() <= IgnoredStackElements;
265 }
266 size_t getStackSize() const {
267 return isStackEmpty() ? 0
268 : Stack.back().first.size() - IgnoredStackElements;
269 }
270
271 SharingMapTy *getTopOfStackOrNull() {
272 size_t Size = getStackSize();
273 if (Size == 0)
274 return nullptr;
275 return &Stack.back().first[Size - 1];
276 }
277 const SharingMapTy *getTopOfStackOrNull() const {
278 return const_cast<DSAStackTy &>(*this).getTopOfStackOrNull();
279 }
280 SharingMapTy &getTopOfStack() {
281 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", 281, __extension__ __PRETTY_FUNCTION__
))
;
282 return *getTopOfStackOrNull();
283 }
284 const SharingMapTy &getTopOfStack() const {
285 return const_cast<DSAStackTy &>(*this).getTopOfStack();
286 }
287
288 SharingMapTy *getSecondOnStackOrNull() {
289 size_t Size = getStackSize();
290 if (Size <= 1)
291 return nullptr;
292 return &Stack.back().first[Size - 2];
293 }
294 const SharingMapTy *getSecondOnStackOrNull() const {
295 return const_cast<DSAStackTy &>(*this).getSecondOnStackOrNull();
296 }
297
298 /// Get the stack element at a certain level (previously returned by
299 /// \c getNestingLevel).
300 ///
301 /// Note that nesting levels count from outermost to innermost, and this is
302 /// the reverse of our iteration order where new inner levels are pushed at
303 /// the front of the stack.
304 SharingMapTy &getStackElemAtLevel(unsigned Level) {
305 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", 305, __extension__ __PRETTY_FUNCTION__
))
;
306 return Stack.back().first[Level];
307 }
308 const SharingMapTy &getStackElemAtLevel(unsigned Level) const {
309 return const_cast<DSAStackTy &>(*this).getStackElemAtLevel(Level);
310 }
311
312 DSAVarData getDSA(const_iterator &Iter, ValueDecl *D) const;
313
314 /// Checks if the variable is a local for OpenMP region.
315 bool isOpenMPLocal(VarDecl *D, const_iterator Iter) const;
316
317 /// Vector of previously declared requires directives
318 SmallVector<const OMPRequiresDecl *, 2> RequiresDecls;
319 /// omp_allocator_handle_t type.
320 QualType OMPAllocatorHandleT;
321 /// omp_depend_t type.
322 QualType OMPDependT;
323 /// omp_event_handle_t type.
324 QualType OMPEventHandleT;
325 /// omp_alloctrait_t type.
326 QualType OMPAlloctraitT;
327 /// Expression for the predefined allocators.
328 Expr *OMPPredefinedAllocators[OMPAllocateDeclAttr::OMPUserDefinedMemAlloc] = {
329 nullptr};
330 /// Vector of previously encountered target directives
331 SmallVector<SourceLocation, 2> TargetLocations;
332 SourceLocation AtomicLocation;
333 /// Vector of declare variant construct traits.
334 SmallVector<llvm::omp::TraitProperty, 8> ConstructTraits;
335
336public:
337 explicit DSAStackTy(Sema &S) : SemaRef(S) {}
338
339 /// Sets omp_allocator_handle_t type.
340 void setOMPAllocatorHandleT(QualType Ty) { OMPAllocatorHandleT = Ty; }
341 /// Gets omp_allocator_handle_t type.
342 QualType getOMPAllocatorHandleT() const { return OMPAllocatorHandleT; }
343 /// Sets omp_alloctrait_t type.
344 void setOMPAlloctraitT(QualType Ty) { OMPAlloctraitT = Ty; }
345 /// Gets omp_alloctrait_t type.
346 QualType getOMPAlloctraitT() const { return OMPAlloctraitT; }
347 /// Sets the given default allocator.
348 void setAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
349 Expr *Allocator) {
350 OMPPredefinedAllocators[AllocatorKind] = Allocator;
351 }
352 /// Returns the specified default allocator.
353 Expr *getAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind) const {
354 return OMPPredefinedAllocators[AllocatorKind];
355 }
356 /// Sets omp_depend_t type.
357 void setOMPDependT(QualType Ty) { OMPDependT = Ty; }
358 /// Gets omp_depend_t type.
359 QualType getOMPDependT() const { return OMPDependT; }
360
361 /// Sets omp_event_handle_t type.
362 void setOMPEventHandleT(QualType Ty) { OMPEventHandleT = Ty; }
363 /// Gets omp_event_handle_t type.
364 QualType getOMPEventHandleT() const { return OMPEventHandleT; }
365
366 bool isClauseParsingMode() const { return ClauseKindMode != OMPC_unknown; }
367 OpenMPClauseKind getClauseParsingMode() const {
368 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", 368, __extension__ __PRETTY_FUNCTION__
))
;
369 return ClauseKindMode;
370 }
371 void setClauseParsingMode(OpenMPClauseKind K) { ClauseKindMode = K; }
372
373 bool isBodyComplete() const {
374 const SharingMapTy *Top = getTopOfStackOrNull();
375 return Top && Top->BodyComplete;
376 }
377 void setBodyComplete() { getTopOfStack().BodyComplete = true; }
378
379 bool isForceVarCapturing() const { return ForceCapturing; }
380 void setForceVarCapturing(bool V) { ForceCapturing = V; }
381
382 void setForceCaptureByReferenceInTargetExecutable(bool V) {
383 ForceCaptureByReferenceInTargetExecutable = V;
384 }
385 bool isForceCaptureByReferenceInTargetExecutable() const {
386 return ForceCaptureByReferenceInTargetExecutable;
387 }
388
389 void push(OpenMPDirectiveKind DKind, const DeclarationNameInfo &DirName,
390 Scope *CurScope, SourceLocation Loc) {
391 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", 392, __extension__ __PRETTY_FUNCTION__
))
392 "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", 392, __extension__ __PRETTY_FUNCTION__
))
;
393 if (Stack.empty() ||
394 Stack.back().second != CurrentNonCapturingFunctionScope)
395 Stack.emplace_back(StackTy(), CurrentNonCapturingFunctionScope);
396 Stack.back().first.emplace_back(DKind, DirName, CurScope, Loc);
397 Stack.back().first.back().DefaultAttrLoc = Loc;
398 }
399
400 void pop() {
401 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", 402, __extension__ __PRETTY_FUNCTION__
))
402 "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", 402, __extension__ __PRETTY_FUNCTION__
))
;
403 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", 404, __extension__ __PRETTY_FUNCTION__
))
404 "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", 404, __extension__ __PRETTY_FUNCTION__
))
;
405 Stack.back().first.pop_back();
406 }
407
408 /// RAII object to temporarily leave the scope of a directive when we want to
409 /// logically operate in its parent.
410 class ParentDirectiveScope {
411 DSAStackTy &Self;
412 bool Active;
413
414 public:
415 ParentDirectiveScope(DSAStackTy &Self, bool Activate)
416 : Self(Self), Active(false) {
417 if (Activate)
418 enable();
419 }
420 ~ParentDirectiveScope() { disable(); }
421 void disable() {
422 if (Active) {
423 --Self.IgnoredStackElements;
424 Active = false;
425 }
426 }
427 void enable() {
428 if (!Active) {
429 ++Self.IgnoredStackElements;
430 Active = true;
431 }
432 }
433 };
434
435 /// Marks that we're started loop parsing.
436 void loopInit() {
437 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", 438, __extension__ __PRETTY_FUNCTION__
))
438 "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", 438, __extension__ __PRETTY_FUNCTION__
))
;
439 getTopOfStack().LoopStart = true;
440 }
441 /// Start capturing of the variables in the loop context.
442 void loopStart() {
443 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", 444, __extension__ __PRETTY_FUNCTION__
))
444 "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", 444, __extension__ __PRETTY_FUNCTION__
))
;
445 getTopOfStack().LoopStart = false;
446 }
447 /// true, if variables are captured, false otherwise.
448 bool isLoopStarted() const {
449 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", 450, __extension__ __PRETTY_FUNCTION__
))
450 "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", 450, __extension__ __PRETTY_FUNCTION__
))
;
451 return !getTopOfStack().LoopStart;
452 }
453 /// Marks (or clears) declaration as possibly loop counter.
454 void resetPossibleLoopCounter(const Decl *D = nullptr) {
455 getTopOfStack().PossiblyLoopCounter = D ? D->getCanonicalDecl() : D;
456 }
457 /// Gets the possible loop counter decl.
458 const Decl *getPossiblyLoopCunter() const {
459 return getTopOfStack().PossiblyLoopCounter;
460 }
461 /// Start new OpenMP region stack in new non-capturing function.
462 void pushFunction() {
463 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", 464, __extension__ __PRETTY_FUNCTION__
))
464 "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", 464, __extension__ __PRETTY_FUNCTION__
))
;
465 const FunctionScopeInfo *CurFnScope = SemaRef.getCurFunction();
466 assert(!isa<CapturingScopeInfo>(CurFnScope))(static_cast <bool> (!isa<CapturingScopeInfo>(CurFnScope
)) ? void (0) : __assert_fail ("!isa<CapturingScopeInfo>(CurFnScope)"
, "clang/lib/Sema/SemaOpenMP.cpp", 466, __extension__ __PRETTY_FUNCTION__
))
;
467 CurrentNonCapturingFunctionScope = CurFnScope;
468 }
469 /// Pop region stack for non-capturing function.
470 void popFunction(const FunctionScopeInfo *OldFSI) {
471 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", 472, __extension__ __PRETTY_FUNCTION__
))
472 "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", 472, __extension__ __PRETTY_FUNCTION__
))
;
473 if (!Stack.empty() && Stack.back().second == OldFSI) {
474 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"
, 474, __extension__ __PRETTY_FUNCTION__))
;
475 Stack.pop_back();
476 }
477 CurrentNonCapturingFunctionScope = nullptr;
478 for (const FunctionScopeInfo *FSI : llvm::reverse(SemaRef.FunctionScopes)) {
479 if (!isa<CapturingScopeInfo>(FSI)) {
480 CurrentNonCapturingFunctionScope = FSI;
481 break;
482 }
483 }
484 }
485
486 void addCriticalWithHint(const OMPCriticalDirective *D, llvm::APSInt Hint) {
487 Criticals.try_emplace(D->getDirectiveName().getAsString(), D, Hint);
488 }
489 const std::pair<const OMPCriticalDirective *, llvm::APSInt>
490 getCriticalWithHint(const DeclarationNameInfo &Name) const {
491 auto I = Criticals.find(Name.getAsString());
492 if (I != Criticals.end())
493 return I->second;
494 return std::make_pair(nullptr, llvm::APSInt());
495 }
496 /// If 'aligned' declaration for given variable \a D was not seen yet,
497 /// add it and return NULL; otherwise return previous occurrence's expression
498 /// for diagnostics.
499 const Expr *addUniqueAligned(const ValueDecl *D, const Expr *NewDE);
500 /// If 'nontemporal' 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 *addUniqueNontemporal(const ValueDecl *D, const Expr *NewDE);
504
505 /// Register specified variable as loop control variable.
506 void addLoopControlVariable(const ValueDecl *D, VarDecl *Capture);
507 /// Check if the specified variable is a loop control variable for
508 /// current region.
509 /// \return The index of the loop control variable in the list of associated
510 /// for-loops (from outer to inner).
511 const LCDeclInfo isLoopControlVariable(const ValueDecl *D) const;
512 /// Check if the specified variable is a loop control variable for
513 /// parent region.
514 /// \return The index of the loop control variable in the list of associated
515 /// for-loops (from outer to inner).
516 const LCDeclInfo isParentLoopControlVariable(const ValueDecl *D) const;
517 /// Check if the specified variable is a loop control variable for
518 /// current region.
519 /// \return The index of the loop control variable in the list of associated
520 /// for-loops (from outer to inner).
521 const LCDeclInfo isLoopControlVariable(const ValueDecl *D,
522 unsigned Level) const;
523 /// Get the loop control variable for the I-th loop (or nullptr) in
524 /// parent directive.
525 const ValueDecl *getParentLoopControlVariable(unsigned I) const;
526
527 /// Marks the specified decl \p D as used in scan directive.
528 void markDeclAsUsedInScanDirective(ValueDecl *D) {
529 if (SharingMapTy *Stack = getSecondOnStackOrNull())
530 Stack->UsedInScanDirective.insert(D);
531 }
532
533 /// Checks if the specified declaration was used in the inner scan directive.
534 bool isUsedInScanDirective(ValueDecl *D) const {
535 if (const SharingMapTy *Stack = getTopOfStackOrNull())
536 return Stack->UsedInScanDirective.contains(D);
537 return false;
538 }
539
540 /// Adds explicit data sharing attribute to the specified declaration.
541 void addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
542 DeclRefExpr *PrivateCopy = nullptr, unsigned Modifier = 0,
543 bool AppliedToPointee = false);
544
545 /// Adds additional information for the reduction items with the reduction id
546 /// represented as an operator.
547 void addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
548 BinaryOperatorKind BOK);
549 /// Adds additional information for the reduction items with the reduction id
550 /// represented as reduction identifier.
551 void addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
552 const Expr *ReductionRef);
553 /// Returns the location and reduction operation from the innermost parent
554 /// region for the given \p D.
555 const DSAVarData
556 getTopMostTaskgroupReductionData(const ValueDecl *D, SourceRange &SR,
557 BinaryOperatorKind &BOK,
558 Expr *&TaskgroupDescriptor) const;
559 /// Returns the location and reduction operation from the innermost parent
560 /// region for the given \p D.
561 const DSAVarData
562 getTopMostTaskgroupReductionData(const ValueDecl *D, SourceRange &SR,
563 const Expr *&ReductionRef,
564 Expr *&TaskgroupDescriptor) const;
565 /// Return reduction reference expression for the current taskgroup or
566 /// parallel/worksharing directives with task reductions.
567 Expr *getTaskgroupReductionRef() const {
568 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", 573, __extension__ __PRETTY_FUNCTION__
))
569 ((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", 573, __extension__ __PRETTY_FUNCTION__
))
570 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", 573, __extension__ __PRETTY_FUNCTION__
))
571 !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", 573, __extension__ __PRETTY_FUNCTION__
))
572 "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", 573, __extension__ __PRETTY_FUNCTION__
))
573 "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", 573, __extension__ __PRETTY_FUNCTION__
))
;
574 return getTopOfStack().TaskgroupReductionRef;
575 }
576 /// Checks if the given \p VD declaration is actually a taskgroup reduction
577 /// descriptor variable at the \p Level of OpenMP regions.
578 bool isTaskgroupReductionRef(const ValueDecl *VD, unsigned Level) const {
579 return getStackElemAtLevel(Level).TaskgroupReductionRef &&
580 cast<DeclRefExpr>(getStackElemAtLevel(Level).TaskgroupReductionRef)
581 ->getDecl() == VD;
582 }
583
584 /// Returns data sharing attributes from top of the stack for the
585 /// specified declaration.
586 const DSAVarData getTopDSA(ValueDecl *D, bool FromParent);
587 /// Returns data-sharing attributes for the specified declaration.
588 const DSAVarData getImplicitDSA(ValueDecl *D, bool FromParent) const;
589 /// Returns data-sharing attributes for the specified declaration.
590 const DSAVarData getImplicitDSA(ValueDecl *D, unsigned Level) const;
591 /// Checks if the specified variables has data-sharing attributes which
592 /// match specified \a CPred predicate in any directive which matches \a DPred
593 /// predicate.
594 const DSAVarData
595 hasDSA(ValueDecl *D,
596 const llvm::function_ref<bool(OpenMPClauseKind, bool,
597 DefaultDataSharingAttributes)>
598 CPred,
599 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
600 bool FromParent) const;
601 /// Checks if the specified variables has data-sharing attributes which
602 /// match specified \a CPred predicate in any innermost directive which
603 /// matches \a DPred predicate.
604 const DSAVarData
605 hasInnermostDSA(ValueDecl *D,
606 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
607 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
608 bool FromParent) const;
609 /// Checks if the specified variables has explicit data-sharing
610 /// attributes which match specified \a CPred predicate at the specified
611 /// OpenMP region.
612 bool
613 hasExplicitDSA(const ValueDecl *D,
614 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
615 unsigned Level, bool NotLastprivate = false) const;
616
617 /// Returns true if the directive at level \Level matches in the
618 /// specified \a DPred predicate.
619 bool hasExplicitDirective(
620 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
621 unsigned Level) const;
622
623 /// Finds a directive which matches specified \a DPred predicate.
624 bool hasDirective(
625 const llvm::function_ref<bool(
626 OpenMPDirectiveKind, const DeclarationNameInfo &, SourceLocation)>
627 DPred,
628 bool FromParent) const;
629
630 /// Returns currently analyzed directive.
631 OpenMPDirectiveKind getCurrentDirective() const {
632 const SharingMapTy *Top = getTopOfStackOrNull();
633 return Top ? Top->Directive : OMPD_unknown;
634 }
635 /// Returns directive kind at specified level.
636 OpenMPDirectiveKind getDirective(unsigned Level) const {
637 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", 637, __extension__ __PRETTY_FUNCTION__
))
;
638 return getStackElemAtLevel(Level).Directive;
639 }
640 /// Returns the capture region at the specified level.
641 OpenMPDirectiveKind getCaptureRegion(unsigned Level,
642 unsigned OpenMPCaptureLevel) const {
643 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
644 getOpenMPCaptureRegions(CaptureRegions, getDirective(Level));
645 return CaptureRegions[OpenMPCaptureLevel];
646 }
647 /// Returns parent directive.
648 OpenMPDirectiveKind getParentDirective() const {
649 const SharingMapTy *Parent = getSecondOnStackOrNull();
650 return Parent ? Parent->Directive : OMPD_unknown;
651 }
652
653 /// Add requires decl to internal vector
654 void addRequiresDecl(OMPRequiresDecl *RD) { RequiresDecls.push_back(RD); }
655
656 /// Checks if the defined 'requires' directive has specified type of clause.
657 template <typename ClauseType> bool hasRequiresDeclWithClause() const {
658 return llvm::any_of(RequiresDecls, [](const OMPRequiresDecl *D) {
659 return llvm::any_of(D->clauselists(), [](const OMPClause *C) {
660 return isa<ClauseType>(C);
661 });
662 });
663 }
664
665 /// Checks for a duplicate clause amongst previously declared requires
666 /// directives
667 bool hasDuplicateRequiresClause(ArrayRef<OMPClause *> ClauseList) const {
668 bool IsDuplicate = false;
669 for (OMPClause *CNew : ClauseList) {
670 for (const OMPRequiresDecl *D : RequiresDecls) {
671 for (const OMPClause *CPrev : D->clauselists()) {
672 if (CNew->getClauseKind() == CPrev->getClauseKind()) {
673 SemaRef.Diag(CNew->getBeginLoc(),
674 diag::err_omp_requires_clause_redeclaration)
675 << getOpenMPClauseName(CNew->getClauseKind());
676 SemaRef.Diag(CPrev->getBeginLoc(),
677 diag::note_omp_requires_previous_clause)
678 << getOpenMPClauseName(CPrev->getClauseKind());
679 IsDuplicate = true;
680 }
681 }
682 }
683 }
684 return IsDuplicate;
685 }
686
687 /// Add location of previously encountered target to internal vector
688 void addTargetDirLocation(SourceLocation LocStart) {
689 TargetLocations.push_back(LocStart);
690 }
691
692 /// Add location for the first encountered atomicc directive.
693 void addAtomicDirectiveLoc(SourceLocation Loc) {
694 if (AtomicLocation.isInvalid())
695 AtomicLocation = Loc;
696 }
697
698 /// Returns the location of the first encountered atomic directive in the
699 /// module.
700 SourceLocation getAtomicDirectiveLoc() const { return AtomicLocation; }
701
702 // Return previously encountered target region locations.
703 ArrayRef<SourceLocation> getEncounteredTargetLocs() const {
704 return TargetLocations;
705 }
706
707 /// Set default data sharing attribute to none.
708 void setDefaultDSANone(SourceLocation Loc) {
709 getTopOfStack().DefaultAttr = DSA_none;
710 getTopOfStack().DefaultAttrLoc = Loc;
711 }
712 /// Set default data sharing attribute to shared.
713 void setDefaultDSAShared(SourceLocation Loc) {
714 getTopOfStack().DefaultAttr = DSA_shared;
715 getTopOfStack().DefaultAttrLoc = Loc;
716 }
717 /// Set default data sharing attribute to private.
718 void setDefaultDSAPrivate(SourceLocation Loc) {
719 getTopOfStack().DefaultAttr = DSA_private;
720 getTopOfStack().DefaultAttrLoc = Loc;
721 }
722 /// Set default data sharing attribute to firstprivate.
723 void setDefaultDSAFirstPrivate(SourceLocation Loc) {
724 getTopOfStack().DefaultAttr = DSA_firstprivate;
725 getTopOfStack().DefaultAttrLoc = Loc;
726 }
727 /// Set default data mapping attribute to Modifier:Kind
728 void setDefaultDMAAttr(OpenMPDefaultmapClauseModifier M,
729 OpenMPDefaultmapClauseKind Kind, SourceLocation Loc) {
730 DefaultmapInfo &DMI = getTopOfStack().DefaultmapMap[Kind];
731 DMI.ImplicitBehavior = M;
732 DMI.SLoc = Loc;
733 }
734 /// Check whether the implicit-behavior has been set in defaultmap
735 bool checkDefaultmapCategory(OpenMPDefaultmapClauseKind VariableCategory) {
736 if (VariableCategory == OMPC_DEFAULTMAP_unknown)
737 return getTopOfStack()
738 .DefaultmapMap[OMPC_DEFAULTMAP_aggregate]
739 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown ||
740 getTopOfStack()
741 .DefaultmapMap[OMPC_DEFAULTMAP_scalar]
742 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown ||
743 getTopOfStack()
744 .DefaultmapMap[OMPC_DEFAULTMAP_pointer]
745 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown;
746 return getTopOfStack().DefaultmapMap[VariableCategory].ImplicitBehavior !=
747 OMPC_DEFAULTMAP_MODIFIER_unknown;
748 }
749
750 ArrayRef<llvm::omp::TraitProperty> getConstructTraits() {
751 return ConstructTraits;
752 }
753 void handleConstructTrait(ArrayRef<llvm::omp::TraitProperty> Traits,
754 bool ScopeEntry) {
755 if (ScopeEntry)
756 ConstructTraits.append(Traits.begin(), Traits.end());
757 else
758 for (llvm::omp::TraitProperty Trait : llvm::reverse(Traits)) {
759 llvm::omp::TraitProperty Top = ConstructTraits.pop_back_val();
760 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", 760, __extension__ __PRETTY_FUNCTION__
))
;
761 (void)Trait;
762 (void)Top;
763 }
764 }
765
766 DefaultDataSharingAttributes getDefaultDSA(unsigned Level) const {
767 return getStackSize() <= Level ? DSA_unspecified
768 : getStackElemAtLevel(Level).DefaultAttr;
769 }
770 DefaultDataSharingAttributes getDefaultDSA() const {
771 return isStackEmpty() ? DSA_unspecified : getTopOfStack().DefaultAttr;
772 }
773 SourceLocation getDefaultDSALocation() const {
774 return isStackEmpty() ? SourceLocation() : getTopOfStack().DefaultAttrLoc;
775 }
776 OpenMPDefaultmapClauseModifier
777 getDefaultmapModifier(OpenMPDefaultmapClauseKind Kind) const {
778 return isStackEmpty()
779 ? OMPC_DEFAULTMAP_MODIFIER_unknown
780 : getTopOfStack().DefaultmapMap[Kind].ImplicitBehavior;
781 }
782 OpenMPDefaultmapClauseModifier
783 getDefaultmapModifierAtLevel(unsigned Level,
784 OpenMPDefaultmapClauseKind Kind) const {
785 return getStackElemAtLevel(Level).DefaultmapMap[Kind].ImplicitBehavior;
786 }
787 bool isDefaultmapCapturedByRef(unsigned Level,
788 OpenMPDefaultmapClauseKind Kind) const {
789 OpenMPDefaultmapClauseModifier M =
790 getDefaultmapModifierAtLevel(Level, Kind);
791 if (Kind == OMPC_DEFAULTMAP_scalar || Kind == OMPC_DEFAULTMAP_pointer) {
792 return (M == OMPC_DEFAULTMAP_MODIFIER_alloc) ||
793 (M == OMPC_DEFAULTMAP_MODIFIER_to) ||
794 (M == OMPC_DEFAULTMAP_MODIFIER_from) ||
795 (M == OMPC_DEFAULTMAP_MODIFIER_tofrom);
796 }
797 return true;
798 }
799 static bool mustBeFirstprivateBase(OpenMPDefaultmapClauseModifier M,
800 OpenMPDefaultmapClauseKind Kind) {
801 switch (Kind) {
802 case OMPC_DEFAULTMAP_scalar:
803 case OMPC_DEFAULTMAP_pointer:
804 return (M == OMPC_DEFAULTMAP_MODIFIER_unknown) ||
805 (M == OMPC_DEFAULTMAP_MODIFIER_firstprivate) ||
806 (M == OMPC_DEFAULTMAP_MODIFIER_default);
807 case OMPC_DEFAULTMAP_aggregate:
808 return M == OMPC_DEFAULTMAP_MODIFIER_firstprivate;
809 default:
810 break;
811 }
812 llvm_unreachable("Unexpected OpenMPDefaultmapClauseKind enum")::llvm::llvm_unreachable_internal("Unexpected OpenMPDefaultmapClauseKind enum"
, "clang/lib/Sema/SemaOpenMP.cpp", 812)
;
813 }
814 bool mustBeFirstprivateAtLevel(unsigned Level,
815 OpenMPDefaultmapClauseKind Kind) const {
816 OpenMPDefaultmapClauseModifier M =
817 getDefaultmapModifierAtLevel(Level, Kind);
818 return mustBeFirstprivateBase(M, Kind);
819 }
820 bool mustBeFirstprivate(OpenMPDefaultmapClauseKind Kind) const {
821 OpenMPDefaultmapClauseModifier M = getDefaultmapModifier(Kind);
822 return mustBeFirstprivateBase(M, Kind);
823 }
824
825 /// Checks if the specified variable is a threadprivate.
826 bool isThreadPrivate(VarDecl *D) {
827 const DSAVarData DVar = getTopDSA(D, false);
828 return isOpenMPThreadPrivate(DVar.CKind);
829 }
830
831 /// Marks current region as ordered (it has an 'ordered' clause).
832 void setOrderedRegion(bool IsOrdered, const Expr *Param,
833 OMPOrderedClause *Clause) {
834 if (IsOrdered)
835 getTopOfStack().OrderedRegion.emplace(Param, Clause);
836 else
837 getTopOfStack().OrderedRegion.reset();
838 }
839 /// Returns true, if region is ordered (has associated 'ordered' clause),
840 /// false - otherwise.
841 bool isOrderedRegion() const {
842 if (const SharingMapTy *Top = getTopOfStackOrNull())
843 return Top->OrderedRegion.has_value();
844 return false;
845 }
846 /// Returns optional parameter for the ordered region.
847 std::pair<const Expr *, OMPOrderedClause *> getOrderedRegionParam() const {
848 if (const SharingMapTy *Top = getTopOfStackOrNull())
849 if (Top->OrderedRegion)
850 return Top->OrderedRegion.value();
851 return std::make_pair(nullptr, nullptr);
852 }
853 /// Returns true, if parent region is ordered (has associated
854 /// 'ordered' clause), false - otherwise.
855 bool isParentOrderedRegion() const {
856 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
857 return Parent->OrderedRegion.has_value();
858 return false;
859 }
860 /// Returns optional parameter for the ordered region.
861 std::pair<const Expr *, OMPOrderedClause *>
862 getParentOrderedRegionParam() const {
863 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
864 if (Parent->OrderedRegion)
865 return Parent->OrderedRegion.value();
866 return std::make_pair(nullptr, nullptr);
867 }
868 /// Marks current region as nowait (it has a 'nowait' clause).
869 void setNowaitRegion(bool IsNowait = true) {
870 getTopOfStack().NowaitRegion = IsNowait;
871 }
872 /// Returns true, if parent region is nowait (has associated
873 /// 'nowait' clause), false - otherwise.
874 bool isParentNowaitRegion() const {
875 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
876 return Parent->NowaitRegion;
877 return false;
878 }
879 /// Marks current region as untied (it has a 'untied' clause).
880 void setUntiedRegion(bool IsUntied = true) {
881 getTopOfStack().UntiedRegion = IsUntied;
882 }
883 /// Return true if current region is untied.
884 bool isUntiedRegion() const {
885 const SharingMapTy *Top = getTopOfStackOrNull();
886 return Top ? Top->UntiedRegion : false;
887 }
888 /// Marks parent region as cancel region.
889 void setParentCancelRegion(bool Cancel = true) {
890 if (SharingMapTy *Parent = getSecondOnStackOrNull())
891 Parent->CancelRegion |= Cancel;
892 }
893 /// Return true if current region has inner cancel construct.
894 bool isCancelRegion() const {
895 const SharingMapTy *Top = getTopOfStackOrNull();
896 return Top ? Top->CancelRegion : false;
897 }
898
899 /// Mark that parent region already has scan directive.
900 void setParentHasScanDirective(SourceLocation Loc) {
901 if (SharingMapTy *Parent = getSecondOnStackOrNull())
902 Parent->PrevScanLocation = Loc;
903 }
904 /// Return true if current region has inner cancel construct.
905 bool doesParentHasScanDirective() const {
906 const SharingMapTy *Top = getSecondOnStackOrNull();
907 return Top ? Top->PrevScanLocation.isValid() : false;
908 }
909 /// Return true if current region has inner cancel construct.
910 SourceLocation getParentScanDirectiveLoc() const {
911 const SharingMapTy *Top = getSecondOnStackOrNull();
912 return Top ? Top->PrevScanLocation : SourceLocation();
913 }
914 /// Mark that parent region already has ordered directive.
915 void setParentHasOrderedDirective(SourceLocation Loc) {
916 if (SharingMapTy *Parent = getSecondOnStackOrNull())
917 Parent->PrevOrderedLocation = Loc;
918 }
919 /// Return true if current region has inner ordered construct.
920 bool doesParentHasOrderedDirective() const {
921 const SharingMapTy *Top = getSecondOnStackOrNull();
922 return Top ? Top->PrevOrderedLocation.isValid() : false;
923 }
924 /// Returns the location of the previously specified ordered directive.
925 SourceLocation getParentOrderedDirectiveLoc() const {
926 const SharingMapTy *Top = getSecondOnStackOrNull();
927 return Top ? Top->PrevOrderedLocation : SourceLocation();
928 }
929
930 /// Set collapse value for the region.
931 void setAssociatedLoops(unsigned Val) {
932 getTopOfStack().AssociatedLoops = Val;
933 if (Val > 1)
934 getTopOfStack().HasMutipleLoops = true;
935 }
936 /// Return collapse value for region.
937 unsigned getAssociatedLoops() const {
938 const SharingMapTy *Top = getTopOfStackOrNull();
939 return Top ? Top->AssociatedLoops : 0;
940 }
941 /// Returns true if the construct is associated with multiple loops.
942 bool hasMutipleLoops() const {
943 const SharingMapTy *Top = getTopOfStackOrNull();
944 return Top ? Top->HasMutipleLoops : false;
945 }
946
947 /// Marks current target region as one with closely nested teams
948 /// region.
949 void setParentTeamsRegionLoc(SourceLocation TeamsRegionLoc) {
950 if (SharingMapTy *Parent = getSecondOnStackOrNull())
951 Parent->InnerTeamsRegionLoc = TeamsRegionLoc;
952 }
953 /// Returns true, if current region has closely nested teams region.
954 bool hasInnerTeamsRegion() const {
955 return getInnerTeamsRegionLoc().isValid();
956 }
957 /// Returns location of the nested teams region (if any).
958 SourceLocation getInnerTeamsRegionLoc() const {
959 const SharingMapTy *Top = getTopOfStackOrNull();
960 return Top ? Top->InnerTeamsRegionLoc : SourceLocation();
961 }
962
963 Scope *getCurScope() const {
964 const SharingMapTy *Top = getTopOfStackOrNull();
965 return Top ? Top->CurScope : nullptr;
966 }
967 void setContext(DeclContext *DC) { getTopOfStack().Context = DC; }
968 SourceLocation getConstructLoc() const {
969 const SharingMapTy *Top = getTopOfStackOrNull();
970 return Top ? Top->ConstructLoc : SourceLocation();
971 }
972
973 /// Do the check specified in \a Check to all component lists and return true
974 /// if any issue is found.
975 bool checkMappableExprComponentListsForDecl(
976 const ValueDecl *VD, bool CurrentRegionOnly,
977 const llvm::function_ref<
978 bool(OMPClauseMappableExprCommon::MappableExprComponentListRef,
979 OpenMPClauseKind)>
980 Check) const {
981 if (isStackEmpty())
982 return false;
983 auto SI = begin();
984 auto SE = end();
985
986 if (SI == SE)
987 return false;
988
989 if (CurrentRegionOnly)
990 SE = std::next(SI);
991 else
992 std::advance(SI, 1);
993
994 for (; SI != SE; ++SI) {
995 auto MI = SI->MappedExprComponents.find(VD);
996 if (MI != SI->MappedExprComponents.end())
997 for (OMPClauseMappableExprCommon::MappableExprComponentListRef L :
998 MI->second.Components)
999 if (Check(L, MI->second.Kind))
1000 return true;
1001 }
1002 return false;
1003 }
1004
1005 /// Do the check specified in \a Check to all component lists at a given level
1006 /// and return true if any issue is found.
1007 bool checkMappableExprComponentListsForDeclAtLevel(
1008 const ValueDecl *VD, unsigned Level,
1009 const llvm::function_ref<
1010 bool(OMPClauseMappableExprCommon::MappableExprComponentListRef,
1011 OpenMPClauseKind)>
1012 Check) const {
1013 if (getStackSize() <= Level)
1014 return false;
1015
1016 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1017 auto MI = StackElem.MappedExprComponents.find(VD);
1018 if (MI != StackElem.MappedExprComponents.end())
1019 for (OMPClauseMappableExprCommon::MappableExprComponentListRef L :
1020 MI->second.Components)
1021 if (Check(L, MI->second.Kind))
1022 return true;
1023 return false;
1024 }
1025
1026 /// Create a new mappable expression component list associated with a given
1027 /// declaration and initialize it with the provided list of components.
1028 void addMappableExpressionComponents(
1029 const ValueDecl *VD,
1030 OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
1031 OpenMPClauseKind WhereFoundClauseKind) {
1032 MappedExprComponentTy &MEC = getTopOfStack().MappedExprComponents[VD];
1033 // Create new entry and append the new components there.
1034 MEC.Components.resize(MEC.Components.size() + 1);
1035 MEC.Components.back().append(Components.begin(), Components.end());
1036 MEC.Kind = WhereFoundClauseKind;
1037 }
1038
1039 unsigned getNestingLevel() const {
1040 assert(!isStackEmpty())(static_cast <bool> (!isStackEmpty()) ? void (0) : __assert_fail
("!isStackEmpty()", "clang/lib/Sema/SemaOpenMP.cpp", 1040, __extension__
__PRETTY_FUNCTION__))
;
1041 return getStackSize() - 1;
1042 }
1043 void addDoacrossDependClause(OMPDependClause *C,
1044 const OperatorOffsetTy &OpsOffs) {
1045 SharingMapTy *Parent = getSecondOnStackOrNull();
1046 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", 1046, __extension__ __PRETTY_FUNCTION__
))
;
1047 Parent->DoacrossDepends.try_emplace(C, OpsOffs);
1048 }
1049 llvm::iterator_range<DoacrossDependMapTy::const_iterator>
1050 getDoacrossDependClauses() const {
1051 const SharingMapTy &StackElem = getTopOfStack();
1052 if (isOpenMPWorksharingDirective(StackElem.Directive)) {
1053 const DoacrossDependMapTy &Ref = StackElem.DoacrossDepends;
1054 return llvm::make_range(Ref.begin(), Ref.end());
1055 }
1056 return llvm::make_range(StackElem.DoacrossDepends.end(),
1057 StackElem.DoacrossDepends.end());
1058 }
1059
1060 // Store types of classes which have been explicitly mapped
1061 void addMappedClassesQualTypes(QualType QT) {
1062 SharingMapTy &StackElem = getTopOfStack();
1063 StackElem.MappedClassesQualTypes.insert(QT);
1064 }
1065
1066 // Return set of mapped classes types
1067 bool isClassPreviouslyMapped(QualType QT) const {
1068 const SharingMapTy &StackElem = getTopOfStack();
1069 return StackElem.MappedClassesQualTypes.contains(QT);
1070 }
1071
1072 /// Adds global declare target to the parent target region.
1073 void addToParentTargetRegionLinkGlobals(DeclRefExpr *E) {
1074 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", 1076, __extension__ __PRETTY_FUNCTION__
))
1075 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", 1076, __extension__ __PRETTY_FUNCTION__
))
1076 "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", 1076, __extension__ __PRETTY_FUNCTION__
))
;
1077 for (auto &Elem : *this) {
1078 if (isOpenMPTargetExecutionDirective(Elem.Directive)) {
1079 Elem.DeclareTargetLinkVarDecls.push_back(E);
1080 return;
1081 }
1082 }
1083 }
1084
1085 /// Returns the list of globals with declare target link if current directive
1086 /// is target.
1087 ArrayRef<DeclRefExpr *> getLinkGlobals() const {
1088 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", 1089, __extension__ __PRETTY_FUNCTION__
))
1089 "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", 1089, __extension__ __PRETTY_FUNCTION__
))
;
1090 return getTopOfStack().DeclareTargetLinkVarDecls;
1091 }
1092
1093 /// Adds list of allocators expressions.
1094 void addInnerAllocatorExpr(Expr *E) {
1095 getTopOfStack().InnerUsedAllocators.push_back(E);
1096 }
1097 /// Return list of used allocators.
1098 ArrayRef<Expr *> getInnerAllocators() const {
1099 return getTopOfStack().InnerUsedAllocators;
1100 }
1101 /// Marks the declaration as implicitly firstprivate nin the task-based
1102 /// regions.
1103 void addImplicitTaskFirstprivate(unsigned Level, Decl *D) {
1104 getStackElemAtLevel(Level).ImplicitTaskFirstprivates.insert(D);
1105 }
1106 /// Checks if the decl is implicitly firstprivate in the task-based region.
1107 bool isImplicitTaskFirstprivate(Decl *D) const {
1108 return getTopOfStack().ImplicitTaskFirstprivates.contains(D);
1109 }
1110
1111 /// Marks decl as used in uses_allocators clause as the allocator.
1112 void addUsesAllocatorsDecl(const Decl *D, UsesAllocatorsDeclKind Kind) {
1113 getTopOfStack().UsesAllocatorsDecls.try_emplace(D, Kind);
1114 }
1115 /// Checks if specified decl is used in uses allocator clause as the
1116 /// allocator.
1117 Optional<UsesAllocatorsDeclKind> isUsesAllocatorsDecl(unsigned Level,
1118 const Decl *D) const {
1119 const SharingMapTy &StackElem = getTopOfStack();
1120 auto I = StackElem.UsesAllocatorsDecls.find(D);
1121 if (I == StackElem.UsesAllocatorsDecls.end())
1122 return None;
1123 return I->getSecond();
1124 }
1125 Optional<UsesAllocatorsDeclKind> isUsesAllocatorsDecl(const Decl *D) const {
1126 const SharingMapTy &StackElem = getTopOfStack();
1127 auto I = StackElem.UsesAllocatorsDecls.find(D);
1128 if (I == StackElem.UsesAllocatorsDecls.end())
1129 return None;
1130 return I->getSecond();
1131 }
1132
1133 void addDeclareMapperVarRef(Expr *Ref) {
1134 SharingMapTy &StackElem = getTopOfStack();
1135 StackElem.DeclareMapperVar = Ref;
1136 }
1137 const Expr *getDeclareMapperVarRef() const {
1138 const SharingMapTy *Top = getTopOfStackOrNull();
1139 return Top ? Top->DeclareMapperVar : nullptr;
1140 }
1141 /// get captured field from ImplicitDefaultFirstprivateFDs
1142 VarDecl *getImplicitFDCapExprDecl(const FieldDecl *FD) const {
1143 const_iterator I = begin();
1144 const_iterator EndI = end();
1145 size_t StackLevel = getStackSize();
1146 for (; I != EndI; ++I) {
1147 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1148 break;
1149 StackLevel--;
1150 }
1151 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", 1151, __extension__ __PRETTY_FUNCTION__
))
;
1152 if (I == EndI)
1153 return nullptr;
1154 for (const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1155 if (IFD.FD == FD && IFD.StackLevel == StackLevel)
1156 return IFD.VD;
1157 return nullptr;
1158 }
1159 /// Check if capture decl is field captured in ImplicitDefaultFirstprivateFDs
1160 bool isImplicitDefaultFirstprivateFD(VarDecl *VD) const {
1161 const_iterator I = begin();
1162 const_iterator EndI = end();
1163 for (; I != EndI; ++I)
1164 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1165 break;
1166 if (I == EndI)
1167 return false;
1168 for (const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1169 if (IFD.VD == VD)
1170 return true;
1171 return false;
1172 }
1173 /// Store capture FD info in ImplicitDefaultFirstprivateFDs
1174 void addImplicitDefaultFirstprivateFD(const FieldDecl *FD, VarDecl *VD) {
1175 iterator I = begin();
1176 const_iterator EndI = end();
1177 size_t StackLevel = getStackSize();
1178 for (; I != EndI; ++I) {
1179 if (I->DefaultAttr == DSA_private || I->DefaultAttr == DSA_firstprivate) {
1180 I->ImplicitDefaultFirstprivateFDs.emplace_back(FD, StackLevel, VD);
1181 break;
1182 }
1183 StackLevel--;
1184 }
1185 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", 1185, __extension__ __PRETTY_FUNCTION__
))
;
1186 }
1187};
1188
1189bool isImplicitTaskingRegion(OpenMPDirectiveKind DKind) {
1190 return isOpenMPParallelDirective(DKind) || isOpenMPTeamsDirective(DKind);
1191}
1192
1193bool isImplicitOrExplicitTaskingRegion(OpenMPDirectiveKind DKind) {
1194 return isImplicitTaskingRegion(DKind) || isOpenMPTaskingDirective(DKind) ||
1195 DKind == OMPD_unknown;
1196}
1197
1198} // namespace
1199
1200static const Expr *getExprAsWritten(const Expr *E) {
1201 if (const auto *FE = dyn_cast<FullExpr>(E))
1202 E = FE->getSubExpr();
1203
1204 if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E))
1205 E = MTE->getSubExpr();
1206
1207 while (const auto *Binder = dyn_cast<CXXBindTemporaryExpr>(E))
1208 E = Binder->getSubExpr();
1209
1210 if (const auto *ICE = dyn_cast<ImplicitCastExpr>(E))
1211 E = ICE->getSubExprAsWritten();
1212 return E->IgnoreParens();
1213}
1214
1215static Expr *getExprAsWritten(Expr *E) {
1216 return const_cast<Expr *>(getExprAsWritten(const_cast<const Expr *>(E)));
1217}
1218
1219static const ValueDecl *getCanonicalDecl(const ValueDecl *D) {
1220 if (const auto *CED = dyn_cast<OMPCapturedExprDecl>(D))
1221 if (const auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
1222 D = ME->getMemberDecl();
1223 const auto *VD = dyn_cast<VarDecl>(D);
1224 const auto *FD = dyn_cast<FieldDecl>(D);
1225 if (VD != nullptr) {
1226 VD = VD->getCanonicalDecl();
1227 D = VD;
1228 } else {
1229 assert(FD)(static_cast <bool> (FD) ? void (0) : __assert_fail ("FD"
, "clang/lib/Sema/SemaOpenMP.cpp", 1229, __extension__ __PRETTY_FUNCTION__
))
;
1230 FD = FD->getCanonicalDecl();
1231 D = FD;
1232 }
1233 return D;
1234}
1235
1236static ValueDecl *getCanonicalDecl(ValueDecl *D) {
1237 return const_cast<ValueDecl *>(
1238 getCanonicalDecl(const_cast<const ValueDecl *>(D)));
1239}
1240
1241DSAStackTy::DSAVarData DSAStackTy::getDSA(const_iterator &Iter,
1242 ValueDecl *D) const {
1243 D = getCanonicalDecl(D);
1244 auto *VD = dyn_cast<VarDecl>(D);
1245 const auto *FD = dyn_cast<FieldDecl>(D);
1246 DSAVarData DVar;
1247 if (Iter == end()) {
1248 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1249 // in a region but not in construct]
1250 // File-scope or namespace-scope variables referenced in called routines
1251 // in the region are shared unless they appear in a threadprivate
1252 // directive.
1253 if (VD && !VD->isFunctionOrMethodVarDecl() && !isa<ParmVarDecl>(VD))
1254 DVar.CKind = OMPC_shared;
1255
1256 // OpenMP [2.9.1.2, Data-sharing Attribute Rules for Variables Referenced
1257 // in a region but not in construct]
1258 // Variables with static storage duration that are declared in called
1259 // routines in the region are shared.
1260 if (VD && VD->hasGlobalStorage())
1261 DVar.CKind = OMPC_shared;
1262
1263 // Non-static data members are shared by default.
1264 if (FD)
1265 DVar.CKind = OMPC_shared;
1266
1267 return DVar;
1268 }
1269
1270 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1271 // in a Construct, C/C++, predetermined, p.1]
1272 // Variables with automatic storage duration that are declared in a scope
1273 // inside the construct are private.
1274 if (VD && isOpenMPLocal(VD, Iter) && VD->isLocalVarDecl() &&
1275 (VD->getStorageClass() == SC_Auto || VD->getStorageClass() == SC_None)) {
1276 DVar.CKind = OMPC_private;
1277 return DVar;
1278 }
1279
1280 DVar.DKind = Iter->Directive;
1281 // Explicitly specified attributes and local variables with predetermined
1282 // attributes.
1283 if (Iter->SharingMap.count(D)) {
1284 const DSAInfo &Data = Iter->SharingMap.lookup(D);
1285 DVar.RefExpr = Data.RefExpr.getPointer();
1286 DVar.PrivateCopy = Data.PrivateCopy;
1287 DVar.CKind = Data.Attributes;
1288 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1289 DVar.Modifier = Data.Modifier;
1290 DVar.AppliedToPointee = Data.AppliedToPointee;
1291 return DVar;
1292 }
1293
1294 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1295 // in a Construct, C/C++, implicitly determined, p.1]
1296 // In a parallel or task construct, the data-sharing attributes of these
1297 // variables are determined by the default clause, if present.
1298 switch (Iter->DefaultAttr) {
1299 case DSA_shared:
1300 DVar.CKind = OMPC_shared;
1301 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1302 return DVar;
1303 case DSA_none:
1304 return DVar;
1305 case DSA_firstprivate:
1306 if (VD && VD->getStorageDuration() == SD_Static &&
1307 VD->getDeclContext()->isFileContext()) {
1308 DVar.CKind = OMPC_unknown;
1309 } else {
1310 DVar.CKind = OMPC_firstprivate;
1311 }
1312 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1313 return DVar;
1314 case DSA_private:
1315 // each variable with static storage duration that is declared
1316 // in a namespace or global scope and referenced in the construct,
1317 // and that does not have a predetermined data-sharing attribute
1318 if (VD && VD->getStorageDuration() == SD_Static &&
1319 VD->getDeclContext()->isFileContext()) {
1320 DVar.CKind = OMPC_unknown;
1321 } else {
1322 DVar.CKind = OMPC_private;
1323 }
1324 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1325 return DVar;
1326 case DSA_unspecified:
1327 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1328 // in a Construct, implicitly determined, p.2]
1329 // In a parallel construct, if no default clause is present, these
1330 // variables are shared.
1331 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1332 if ((isOpenMPParallelDirective(DVar.DKind) &&
1333 !isOpenMPTaskLoopDirective(DVar.DKind)) ||
1334 isOpenMPTeamsDirective(DVar.DKind)) {
1335 DVar.CKind = OMPC_shared;
1336 return DVar;
1337 }
1338
1339 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1340 // in a Construct, implicitly determined, p.4]
1341 // In a task construct, if no default clause is present, a variable that in
1342 // the enclosing context is determined to be shared by all implicit tasks
1343 // bound to the current team is shared.
1344 if (isOpenMPTaskingDirective(DVar.DKind)) {
1345 DSAVarData DVarTemp;
1346 const_iterator I = Iter, E = end();
1347 do {
1348 ++I;
1349 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables
1350 // Referenced in a Construct, implicitly determined, p.6]
1351 // In a task construct, if no default clause is present, a variable
1352 // whose data-sharing attribute is not determined by the rules above is
1353 // firstprivate.
1354 DVarTemp = getDSA(I, D);
1355 if (DVarTemp.CKind != OMPC_shared) {
1356 DVar.RefExpr = nullptr;
1357 DVar.CKind = OMPC_firstprivate;
1358 return DVar;
1359 }
1360 } while (I != E && !isImplicitTaskingRegion(I->Directive));
1361 DVar.CKind =
1362 (DVarTemp.CKind == OMPC_unknown) ? OMPC_firstprivate : OMPC_shared;
1363 return DVar;
1364 }
1365 }
1366 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1367 // in a Construct, implicitly determined, p.3]
1368 // For constructs other than task, if no default clause is present, these
1369 // variables inherit their data-sharing attributes from the enclosing
1370 // context.
1371 return getDSA(++Iter, D);
1372}
1373
1374const Expr *DSAStackTy::addUniqueAligned(const ValueDecl *D,
1375 const Expr *NewDE) {
1376 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", 1376, __extension__ __PRETTY_FUNCTION__
))
;
1377 D = getCanonicalDecl(D);
1378 SharingMapTy &StackElem = getTopOfStack();
1379 auto It = StackElem.AlignedMap.find(D);
1380 if (It == StackElem.AlignedMap.end()) {
1381 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", 1381, __extension__ __PRETTY_FUNCTION__
))
;
1382 StackElem.AlignedMap[D] = NewDE;
1383 return nullptr;
1384 }
1385 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", 1385, __extension__ __PRETTY_FUNCTION__
))
;
1386 return It->second;
1387}
1388
1389const Expr *DSAStackTy::addUniqueNontemporal(const ValueDecl *D,
1390 const Expr *NewDE) {
1391 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", 1391, __extension__ __PRETTY_FUNCTION__
))
;
1392 D = getCanonicalDecl(D);
1393 SharingMapTy &StackElem = getTopOfStack();
1394 auto It = StackElem.NontemporalMap.find(D);
1395 if (It == StackElem.NontemporalMap.end()) {
1396 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", 1396, __extension__ __PRETTY_FUNCTION__
))
;
1397 StackElem.NontemporalMap[D] = NewDE;
1398 return nullptr;
1399 }
1400 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", 1400, __extension__ __PRETTY_FUNCTION__
))
;
1401 return It->second;
1402}
1403
1404void DSAStackTy::addLoopControlVariable(const ValueDecl *D, VarDecl *Capture) {
1405 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", 1405, __extension__ __PRETTY_FUNCTION__
))
;
1406 D = getCanonicalDecl(D);
1407 SharingMapTy &StackElem = getTopOfStack();
1408 StackElem.LCVMap.try_emplace(
1409 D, LCDeclInfo(StackElem.LCVMap.size() + 1, Capture));
1410}
1411
1412const DSAStackTy::LCDeclInfo
1413DSAStackTy::isLoopControlVariable(const ValueDecl *D) const {
1414 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", 1414, __extension__ __PRETTY_FUNCTION__
))
;
1415 D = getCanonicalDecl(D);
1416 const SharingMapTy &StackElem = getTopOfStack();
1417 auto It = StackElem.LCVMap.find(D);
1418 if (It != StackElem.LCVMap.end())
1419 return It->second;
1420 return {0, nullptr};
1421}
1422
1423const DSAStackTy::LCDeclInfo
1424DSAStackTy::isLoopControlVariable(const ValueDecl *D, unsigned Level) const {
1425 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", 1425, __extension__ __PRETTY_FUNCTION__
))
;
1426 D = getCanonicalDecl(D);
1427 for (unsigned I = Level + 1; I > 0; --I) {
1428 const SharingMapTy &StackElem = getStackElemAtLevel(I - 1);
1429 auto It = StackElem.LCVMap.find(D);
1430 if (It != StackElem.LCVMap.end())
1431 return It->second;
1432 }
1433 return {0, nullptr};
1434}
1435
1436const DSAStackTy::LCDeclInfo
1437DSAStackTy::isParentLoopControlVariable(const ValueDecl *D) const {
1438 const SharingMapTy *Parent = getSecondOnStackOrNull();
1439 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", 1439, __extension__ __PRETTY_FUNCTION__
))
;
1440 D = getCanonicalDecl(D);
1441 auto It = Parent->LCVMap.find(D);
1442 if (It != Parent->LCVMap.end())
1443 return It->second;
1444 return {0, nullptr};
1445}
1446
1447const ValueDecl *DSAStackTy::getParentLoopControlVariable(unsigned I) const {
1448 const SharingMapTy *Parent = getSecondOnStackOrNull();
1449 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", 1449, __extension__ __PRETTY_FUNCTION__
))
;
1450 if (Parent->LCVMap.size() < I)
1451 return nullptr;
1452 for (const auto &Pair : Parent->LCVMap)
1453 if (Pair.second.first == I)
1454 return Pair.first;
1455 return nullptr;
1456}
1457
1458void DSAStackTy::addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
1459 DeclRefExpr *PrivateCopy, unsigned Modifier,
1460 bool AppliedToPointee) {
1461 D = getCanonicalDecl(D);
1462 if (A == OMPC_threadprivate) {
1463 DSAInfo &Data = Threadprivates[D];
1464 Data.Attributes = A;
1465 Data.RefExpr.setPointer(E);
1466 Data.PrivateCopy = nullptr;
1467 Data.Modifier = Modifier;
1468 } else {
1469 DSAInfo &Data = getTopOfStack().SharingMap[D];
1470 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", 1473, __extension__ __PRETTY_FUNCTION__
))
1471 (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", 1473, __extension__ __PRETTY_FUNCTION__
))
1472 (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", 1473, __extension__ __PRETTY_FUNCTION__
))
1473 (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", 1473, __extension__ __PRETTY_FUNCTION__
))
;
1474 Data.Modifier = Modifier;
1475 if (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) {
1476 Data.RefExpr.setInt(/*IntVal=*/true);
1477 return;
1478 }
1479 const bool IsLastprivate =
1480 A == OMPC_lastprivate || Data.Attributes == OMPC_lastprivate;
1481 Data.Attributes = A;
1482 Data.RefExpr.setPointerAndInt(E, IsLastprivate);
1483 Data.PrivateCopy = PrivateCopy;
1484 Data.AppliedToPointee = AppliedToPointee;
1485 if (PrivateCopy) {
1486 DSAInfo &Data = getTopOfStack().SharingMap[PrivateCopy->getDecl()];
1487 Data.Modifier = Modifier;
1488 Data.Attributes = A;
1489 Data.RefExpr.setPointerAndInt(PrivateCopy, IsLastprivate);
1490 Data.PrivateCopy = nullptr;
1491 Data.AppliedToPointee = AppliedToPointee;
1492 }
1493 }
1494}
1495
1496/// Build a variable declaration for OpenMP loop iteration variable.
1497static VarDecl *buildVarDecl(Sema &SemaRef, SourceLocation Loc, QualType Type,
1498 StringRef Name, const AttrVec *Attrs = nullptr,
1499 DeclRefExpr *OrigRef = nullptr) {
1500 DeclContext *DC = SemaRef.CurContext;
1501 IdentifierInfo *II = &SemaRef.PP.getIdentifierTable().get(Name);
1502 TypeSourceInfo *TInfo = SemaRef.Context.getTrivialTypeSourceInfo(Type, Loc);
1503 auto *Decl =
1504 VarDecl::Create(SemaRef.Context, DC, Loc, Loc, II, Type, TInfo, SC_None);
1505 if (Attrs) {
1506 for (specific_attr_iterator<AlignedAttr> I(Attrs->begin()), E(Attrs->end());
1507 I != E; ++I)
1508 Decl->addAttr(*I);
1509 }
1510 Decl->setImplicit();
1511 if (OrigRef) {
1512 Decl->addAttr(
1513 OMPReferencedVarAttr::CreateImplicit(SemaRef.Context, OrigRef));
1514 }
1515 return Decl;
1516}
1517
1518static DeclRefExpr *buildDeclRefExpr(Sema &S, VarDecl *D, QualType Ty,
1519 SourceLocation Loc,
1520 bool RefersToCapture = false) {
1521 D->setReferenced();
1522 D->markUsed(S.Context);
1523 return DeclRefExpr::Create(S.getASTContext(), NestedNameSpecifierLoc(),
1524 SourceLocation(), D, RefersToCapture, Loc, Ty,
1525 VK_LValue);
1526}
1527
1528void DSAStackTy::addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
1529 BinaryOperatorKind BOK) {
1530 D = getCanonicalDecl(D);
1531 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", 1531, __extension__ __PRETTY_FUNCTION__
))
;
1532 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", 1534, __extension__ __PRETTY_FUNCTION__
))
1533 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", 1534, __extension__ __PRETTY_FUNCTION__
))
1534 "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", 1534, __extension__ __PRETTY_FUNCTION__
))
;
1535 ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1536 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", 1542, __extension__ __PRETTY_FUNCTION__
))
1537 (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", 1542, __extension__ __PRETTY_FUNCTION__
))
1538 ((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", 1542, __extension__ __PRETTY_FUNCTION__
))
1539 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", 1542, __extension__ __PRETTY_FUNCTION__
))
1540 !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", 1542, __extension__ __PRETTY_FUNCTION__
))
1541 "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", 1542, __extension__ __PRETTY_FUNCTION__
))
1542 "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", 1542, __extension__ __PRETTY_FUNCTION__
))
;
1543 ReductionData.set(BOK, SR);
1544 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1545 if (!TaskgroupReductionRef) {
1546 VarDecl *VD = buildVarDecl(SemaRef, SR.getBegin(),
1547 SemaRef.Context.VoidPtrTy, ".task_red.");
1548 TaskgroupReductionRef =
1549 buildDeclRefExpr(SemaRef, VD, SemaRef.Context.VoidPtrTy, SR.getBegin());
1550 }
1551}
1552
1553void DSAStackTy::addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
1554 const Expr *ReductionRef) {
1555 D = getCanonicalDecl(D);
1556 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", 1556, __extension__ __PRETTY_FUNCTION__
))
;
1557 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", 1559, __extension__ __PRETTY_FUNCTION__
))
1558 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", 1559, __extension__ __PRETTY_FUNCTION__
))
1559 "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", 1559, __extension__ __PRETTY_FUNCTION__
))
;
1560 ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1561 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", 1567, __extension__ __PRETTY_FUNCTION__
))
1562 (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", 1567, __extension__ __PRETTY_FUNCTION__
))
1563 ((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", 1567, __extension__ __PRETTY_FUNCTION__
))
1564 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", 1567, __extension__ __PRETTY_FUNCTION__
))
1565 !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", 1567, __extension__ __PRETTY_FUNCTION__
))
1566 "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", 1567, __extension__ __PRETTY_FUNCTION__
))
1567 "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", 1567, __extension__ __PRETTY_FUNCTION__
))
;
1568 ReductionData.set(ReductionRef, SR);
1569 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1570 if (!TaskgroupReductionRef) {
1571 VarDecl *VD = buildVarDecl(SemaRef, SR.getBegin(),
1572 SemaRef.Context.VoidPtrTy, ".task_red.");
1573 TaskgroupReductionRef =
1574 buildDeclRefExpr(SemaRef, VD, SemaRef.Context.VoidPtrTy, SR.getBegin());
1575 }
1576}
1577
1578const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1579 const ValueDecl *D, SourceRange &SR, BinaryOperatorKind &BOK,
1580 Expr *&TaskgroupDescriptor) const {
1581 D = getCanonicalDecl(D);
1582 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", 1582, __extension__ __PRETTY_FUNCTION__
))
;
1583 for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
1584 const DSAInfo &Data = I->SharingMap.lookup(D);
1585 if (Data.Attributes != OMPC_reduction ||
1586 Data.Modifier != OMPC_REDUCTION_task)
1587 continue;
1588 const ReductionData &ReductionData = I->ReductionMap.lookup(D);
1589 if (!ReductionData.ReductionOp ||
1590 ReductionData.ReductionOp.is<const Expr *>())
1591 return DSAVarData();
1592 SR = ReductionData.ReductionRange;
1593 BOK = ReductionData.ReductionOp.get<ReductionData::BOKPtrType>();
1594 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", 1596, __extension__ __PRETTY_FUNCTION__
))
1595 "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", 1596, __extension__ __PRETTY_FUNCTION__
))
1596 "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", 1596, __extension__ __PRETTY_FUNCTION__
))
;
1597 TaskgroupDescriptor = I->TaskgroupReductionRef;
1598 return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(),
1599 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1600 /*AppliedToPointee=*/false);
1601 }
1602 return DSAVarData();
1603}
1604
1605const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1606 const ValueDecl *D, SourceRange &SR, const Expr *&ReductionRef,
1607 Expr *&TaskgroupDescriptor) const {
1608 D = getCanonicalDecl(D);
1609 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", 1609, __extension__ __PRETTY_FUNCTION__
))
;
1610 for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
1611 const DSAInfo &Data = I->SharingMap.lookup(D);
1612 if (Data.Attributes != OMPC_reduction ||
1613 Data.Modifier != OMPC_REDUCTION_task)
1614 continue;
1615 const ReductionData &ReductionData = I->ReductionMap.lookup(D);
1616 if (!ReductionData.ReductionOp ||
1617 !ReductionData.ReductionOp.is<const Expr *>())
1618 return DSAVarData();
1619 SR = ReductionData.ReductionRange;
1620 ReductionRef = ReductionData.ReductionOp.get<const Expr *>();
1621 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", 1623, __extension__ __PRETTY_FUNCTION__
))
1622 "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", 1623, __extension__ __PRETTY_FUNCTION__
))
1623 "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", 1623, __extension__ __PRETTY_FUNCTION__
))
;
1624 TaskgroupDescriptor = I->TaskgroupReductionRef;
1625 return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(),
1626 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1627 /*AppliedToPointee=*/false);
1628 }
1629 return DSAVarData();
1630}
1631
1632bool DSAStackTy::isOpenMPLocal(VarDecl *D, const_iterator I) const {
1633 D = D->getCanonicalDecl();
1634 for (const_iterator E = end(); I != E; ++I) {
1635 if (isImplicitOrExplicitTaskingRegion(I->Directive) ||
1636 isOpenMPTargetExecutionDirective(I->Directive)) {
1637 if (I->CurScope) {
1638 Scope *TopScope = I->CurScope->getParent();
1639 Scope *CurScope = getCurScope();
1640 while (CurScope && CurScope != TopScope && !CurScope->isDeclScope(D))
1641 CurScope = CurScope->getParent();
1642 return CurScope != TopScope;
1643 }
1644 for (DeclContext *DC = D->getDeclContext(); DC; DC = DC->getParent())
1645 if (I->Context == DC)
1646 return true;
1647 return false;
1648 }
1649 }
1650 return false;
1651}
1652
1653static bool isConstNotMutableType(Sema &SemaRef, QualType Type,
1654 bool AcceptIfMutable = true,
1655 bool *IsClassType = nullptr) {
1656 ASTContext &Context = SemaRef.getASTContext();
1657 Type = Type.getNonReferenceType().getCanonicalType();
1658 bool IsConstant = Type.isConstant(Context);
1659 Type = Context.getBaseElementType(Type);
1660 const CXXRecordDecl *RD = AcceptIfMutable && SemaRef.getLangOpts().CPlusPlus
1661 ? Type->getAsCXXRecordDecl()
1662 : nullptr;
1663 if (const auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(RD))
1664 if (const ClassTemplateDecl *CTD = CTSD->getSpecializedTemplate())
1665 RD = CTD->getTemplatedDecl();
1666 if (IsClassType)
1667 *IsClassType = RD;
1668 return IsConstant && !(SemaRef.getLangOpts().CPlusPlus && RD &&
1669 RD->hasDefinition() && RD->hasMutableFields());
1670}
1671
1672static bool rejectConstNotMutableType(Sema &SemaRef, const ValueDecl *D,
1673 QualType Type, OpenMPClauseKind CKind,
1674 SourceLocation ELoc,
1675 bool AcceptIfMutable = true,
1676 bool ListItemNotVar = false) {
1677 ASTContext &Context = SemaRef.getASTContext();
1678 bool IsClassType;
1679 if (isConstNotMutableType(SemaRef, Type, AcceptIfMutable, &IsClassType)) {
1680 unsigned Diag = ListItemNotVar ? diag::err_omp_const_list_item
1681 : IsClassType ? diag::err_omp_const_not_mutable_variable
1682 : diag::err_omp_const_variable;
1683 SemaRef.Diag(ELoc, Diag) << getOpenMPClauseName(CKind);
1684 if (!ListItemNotVar && D) {
1685 const VarDecl *VD = dyn_cast<VarDecl>(D);
1686 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
1687 VarDecl::DeclarationOnly;
1688 SemaRef.Diag(D->getLocation(),
1689 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
1690 << D;
1691 }
1692 return true;
1693 }
1694 return false;
1695}
1696
1697const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D,
1698 bool FromParent) {
1699 D = getCanonicalDecl(D);
1700 DSAVarData DVar;
1701
1702 auto *VD = dyn_cast<VarDecl>(D);
1703 auto TI = Threadprivates.find(D);
1704 if (TI != Threadprivates.end()) {
1705 DVar.RefExpr = TI->getSecond().RefExpr.getPointer();
1706 DVar.CKind = OMPC_threadprivate;
1707 DVar.Modifier = TI->getSecond().Modifier;
1708 return DVar;
1709 }
1710 if (VD && VD->hasAttr<OMPThreadPrivateDeclAttr>()) {
1711 DVar.RefExpr = buildDeclRefExpr(
1712 SemaRef, VD, D->getType().getNonReferenceType(),
1713 VD->getAttr<OMPThreadPrivateDeclAttr>()->getLocation());
1714 DVar.CKind = OMPC_threadprivate;
1715 addDSA(D, DVar.RefExpr, OMPC_threadprivate);
1716 return DVar;
1717 }
1718 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1719 // in a Construct, C/C++, predetermined, p.1]
1720 // Variables appearing in threadprivate directives are threadprivate.
1721 if ((VD && VD->getTLSKind() != VarDecl::TLS_None &&
1722 !(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
1723 SemaRef.getLangOpts().OpenMPUseTLS &&
1724 SemaRef.getASTContext().getTargetInfo().isTLSSupported())) ||
1725 (VD && VD->getStorageClass() == SC_Register &&
1726 VD->hasAttr<AsmLabelAttr>() && !VD->isLocalVarDecl())) {
1727 DVar.RefExpr = buildDeclRefExpr(
1728 SemaRef, VD, D->getType().getNonReferenceType(), D->getLocation());
1729 DVar.CKind = OMPC_threadprivate;
1730 addDSA(D, DVar.RefExpr, OMPC_threadprivate);
1731 return DVar;
1732 }
1733 if (SemaRef.getLangOpts().OpenMPCUDAMode && VD &&
1734 VD->isLocalVarDeclOrParm() && !isStackEmpty() &&
1735 !isLoopControlVariable(D).first) {
1736 const_iterator IterTarget =
1737 std::find_if(begin(), end(), [](const SharingMapTy &Data) {
1738 return isOpenMPTargetExecutionDirective(Data.Directive);
1739 });
1740 if (IterTarget != end()) {
1741 const_iterator ParentIterTarget = IterTarget + 1;
1742 for (const_iterator Iter = begin(); Iter != ParentIterTarget; ++Iter) {
1743 if (isOpenMPLocal(VD, Iter)) {
1744 DVar.RefExpr =
1745 buildDeclRefExpr(SemaRef, VD, D->getType().getNonReferenceType(),
1746 D->getLocation());
1747 DVar.CKind = OMPC_threadprivate;
1748 return DVar;
1749 }
1750 }
1751 if (!isClauseParsingMode() || IterTarget != begin()) {
1752 auto DSAIter = IterTarget->SharingMap.find(D);
1753 if (DSAIter != IterTarget->SharingMap.end() &&
1754 isOpenMPPrivate(DSAIter->getSecond().Attributes)) {
1755 DVar.RefExpr = DSAIter->getSecond().RefExpr.getPointer();
1756 DVar.CKind = OMPC_threadprivate;
1757 return DVar;
1758 }
1759 const_iterator End = end();
1760 if (!SemaRef.isOpenMPCapturedByRef(D,
1761 std::distance(ParentIterTarget, End),
1762 /*OpenMPCaptureLevel=*/0)) {
1763 DVar.RefExpr =
1764 buildDeclRefExpr(SemaRef, VD, D->getType().getNonReferenceType(),
1765 IterTarget->ConstructLoc);
1766 DVar.CKind = OMPC_threadprivate;
1767 return DVar;
1768 }
1769 }
1770 }
1771 }
1772
1773 if (isStackEmpty())
1774 // Not in OpenMP execution region and top scope was already checked.
1775 return DVar;
1776
1777 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1778 // in a Construct, C/C++, predetermined, p.4]
1779 // Static data members are shared.
1780 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1781 // in a Construct, C/C++, predetermined, p.7]
1782 // Variables with static storage duration that are declared in a scope
1783 // inside the construct are shared.
1784 if (VD && VD->isStaticDataMember()) {
1785 // Check for explicitly specified attributes.
1786 const_iterator I = begin();
1787 const_iterator EndI = end();
1788 if (FromParent && I != EndI)
1789 ++I;
1790 if (I != EndI) {
1791 auto It = I->SharingMap.find(D);
1792 if (It != I->SharingMap.end()) {
1793 const DSAInfo &Data = It->getSecond();
1794 DVar.RefExpr = Data.RefExpr.getPointer();
1795 DVar.PrivateCopy = Data.PrivateCopy;
1796 DVar.CKind = Data.Attributes;
1797 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1798 DVar.DKind = I->Directive;
1799 DVar.Modifier = Data.Modifier;
1800 DVar.AppliedToPointee = Data.AppliedToPointee;
1801 return DVar;
1802 }
1803 }
1804
1805 DVar.CKind = OMPC_shared;
1806 return DVar;
1807 }
1808
1809 auto &&MatchesAlways = [](OpenMPDirectiveKind) { return true; };
1810 // The predetermined shared attribute for const-qualified types having no
1811 // mutable members was removed after OpenMP 3.1.
1812 if (SemaRef.LangOpts.OpenMP <= 31) {
1813 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1814 // in a Construct, C/C++, predetermined, p.6]
1815 // Variables with const qualified type having no mutable member are
1816 // shared.
1817 if (isConstNotMutableType(SemaRef, D->getType())) {
1818 // Variables with const-qualified type having no mutable member may be
1819 // listed in a firstprivate clause, even if they are static data members.
1820 DSAVarData DVarTemp = hasInnermostDSA(
1821 D,
1822 [](OpenMPClauseKind C, bool) {
1823 return C == OMPC_firstprivate || C == OMPC_shared;
1824 },
1825 MatchesAlways, FromParent);
1826 if (DVarTemp.CKind != OMPC_unknown && DVarTemp.RefExpr)
1827 return DVarTemp;
1828
1829 DVar.CKind = OMPC_shared;
1830 return DVar;
1831 }
1832 }
1833
1834 // Explicitly specified attributes and local variables with predetermined
1835 // attributes.
1836 const_iterator I = begin();
1837 const_iterator EndI = end();
1838 if (FromParent && I != EndI)
1839 ++I;
1840 if (I == EndI)
1841 return DVar;
1842 auto It = I->SharingMap.find(D);
1843 if (It != I->SharingMap.end()) {
1844 const DSAInfo &Data = It->getSecond();
1845 DVar.RefExpr = Data.RefExpr.getPointer();
1846 DVar.PrivateCopy = Data.PrivateCopy;
1847 DVar.CKind = Data.Attributes;
1848 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1849 DVar.DKind = I->Directive;
1850 DVar.Modifier = Data.Modifier;
1851 DVar.AppliedToPointee = Data.AppliedToPointee;
1852 }
1853
1854 return DVar;
1855}
1856
1857const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
1858 bool FromParent) const {
1859 if (isStackEmpty()) {
1860 const_iterator I;
1861 return getDSA(I, D);
1862 }
1863 D = getCanonicalDecl(D);
1864 const_iterator StartI = begin();
1865 const_iterator EndI = end();
1866 if (FromParent && StartI != EndI)
1867 ++StartI;
1868 return getDSA(StartI, D);
1869}
1870
1871const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
1872 unsigned Level) const {
1873 if (getStackSize() <= Level)
1874 return DSAVarData();
1875 D = getCanonicalDecl(D);
1876 const_iterator StartI = std::next(begin(), getStackSize() - 1 - Level);
1877 return getDSA(StartI, D);
1878}
1879
1880const DSAStackTy::DSAVarData
1881DSAStackTy::hasDSA(ValueDecl *D,
1882 const llvm::function_ref<bool(OpenMPClauseKind, bool,
1883 DefaultDataSharingAttributes)>
1884 CPred,
1885 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
1886 bool FromParent) const {
1887 if (isStackEmpty())
1888 return {};
1889 D = getCanonicalDecl(D);
1890 const_iterator I = begin();
1891 const_iterator EndI = end();
1892 if (FromParent && I != EndI)
1893 ++I;
1894 for (; I != EndI; ++I) {
1895 if (!DPred(I->Directive) &&
1896 !isImplicitOrExplicitTaskingRegion(I->Directive))
1897 continue;
1898 const_iterator NewI = I;
1899 DSAVarData DVar = getDSA(NewI, D);
1900 if (I == NewI && CPred(DVar.CKind, DVar.AppliedToPointee, I->DefaultAttr))
1901 return DVar;
1902 }
1903 return {};
1904}
1905
1906const DSAStackTy::DSAVarData DSAStackTy::hasInnermostDSA(
1907 ValueDecl *D, const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
1908 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
1909 bool FromParent) const {
1910 if (isStackEmpty())
1911 return {};
1912 D = getCanonicalDecl(D);
1913 const_iterator StartI = begin();
1914 const_iterator EndI = end();
1915 if (FromParent && StartI != EndI)
1916 ++StartI;
1917 if (StartI == EndI || !DPred(StartI->Directive))
1918 return {};
1919 const_iterator NewI = StartI;
1920 DSAVarData DVar = getDSA(NewI, D);
1921 return (NewI == StartI && CPred(DVar.CKind, DVar.AppliedToPointee))
1922 ? DVar
1923 : DSAVarData();
1924}
1925
1926bool DSAStackTy::hasExplicitDSA(
1927 const ValueDecl *D,
1928 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
1929 unsigned Level, bool NotLastprivate) const {
1930 if (getStackSize() <= Level)
1931 return false;
1932 D = getCanonicalDecl(D);
1933 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1934 auto I = StackElem.SharingMap.find(D);
1935 if (I != StackElem.SharingMap.end() && I->getSecond().RefExpr.getPointer() &&
1936 CPred(I->getSecond().Attributes, I->getSecond().AppliedToPointee) &&
1937 (!NotLastprivate || !I->getSecond().RefExpr.getInt()))
1938 return true;
1939 // Check predetermined rules for the loop control variables.
1940 auto LI = StackElem.LCVMap.find(D);
1941 if (LI != StackElem.LCVMap.end())
1942 return CPred(OMPC_private, /*AppliedToPointee=*/false);
1943 return false;
1944}
1945
1946bool DSAStackTy::hasExplicitDirective(
1947 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
1948 unsigned Level) const {
1949 if (getStackSize() <= Level)
1950 return false;
1951 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1952 return DPred(StackElem.Directive);
1953}
1954
1955bool DSAStackTy::hasDirective(
1956 const llvm::function_ref<bool(OpenMPDirectiveKind,
1957 const DeclarationNameInfo &, SourceLocation)>
1958 DPred,
1959 bool FromParent) const {
1960 // We look only in the enclosing region.
1961 size_t Skip = FromParent ? 2 : 1;
1962 for (const_iterator I = begin() + std::min(Skip, getStackSize()), E = end();
1963 I != E; ++I) {
1964 if (DPred(I->Directive, I->DirectiveName, I->ConstructLoc))
1965 return true;
1966 }
1967 return false;
1968}
1969
1970void Sema::InitDataSharingAttributesStack() {
1971 VarDataSharingAttributesStack = new DSAStackTy(*this);
1972}
1973
1974#define DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
static_cast<DSAStackTy *>(VarDataSharingAttributesStack)
1975
1976void Sema::pushOpenMPFunctionRegion() { DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->pushFunction(); }
1977
1978void Sema::popOpenMPFunctionRegion(const FunctionScopeInfo *OldFSI) {
1979 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->popFunction(OldFSI);
1980}
1981
1982static bool isOpenMPDeviceDelayedContext(Sema &S) {
1983 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", 1984, __extension__ __PRETTY_FUNCTION__
))
1984 "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", 1984, __extension__ __PRETTY_FUNCTION__
))
;
1985 return !S.isInOpenMPTargetExecutionDirective();
1986}
1987
1988namespace {
1989/// Status of the function emission on the host/device.
1990enum class FunctionEmissionStatus {
1991 Emitted,
1992 Discarded,
1993 Unknown,
1994};
1995} // anonymous namespace
1996
1997Sema::SemaDiagnosticBuilder Sema::diagIfOpenMPDeviceCode(SourceLocation Loc,
1998 unsigned DiagID,
1999 FunctionDecl *FD) {
2000 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", 2001, __extension__ __PRETTY_FUNCTION__
))
2001 "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", 2001, __extension__ __PRETTY_FUNCTION__
))
;
2002
2003 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2004 if (FD) {
2005 FunctionEmissionStatus FES = getEmissionStatus(FD);
2006 switch (FES) {
2007 case FunctionEmissionStatus::Emitted:
2008 Kind = SemaDiagnosticBuilder::K_Immediate;
2009 break;
2010 case FunctionEmissionStatus::Unknown:
2011 // TODO: We should always delay diagnostics here in case a target
2012 // region is in a function we do not emit. However, as the
2013 // current diagnostics are associated with the function containing
2014 // the target region and we do not emit that one, we would miss out
2015 // on diagnostics for the target region itself. We need to anchor
2016 // the diagnostics with the new generated function *or* ensure we
2017 // emit diagnostics associated with the surrounding function.
2018 Kind = isOpenMPDeviceDelayedContext(*this)
2019 ? SemaDiagnosticBuilder::K_Deferred
2020 : SemaDiagnosticBuilder::K_Immediate;
2021 break;
2022 case FunctionEmissionStatus::TemplateDiscarded:
2023 case FunctionEmissionStatus::OMPDiscarded:
2024 Kind = SemaDiagnosticBuilder::K_Nop;
2025 break;
2026 case FunctionEmissionStatus::CUDADiscarded:
2027 llvm_unreachable("CUDADiscarded unexpected in OpenMP device compilation")::llvm::llvm_unreachable_internal("CUDADiscarded unexpected in OpenMP device compilation"
, "clang/lib/Sema/SemaOpenMP.cpp", 2027)
;
2028 break;
2029 }
2030 }
2031
2032 return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, *this);
2033}
2034
2035Sema::SemaDiagnosticBuilder Sema::diagIfOpenMPHostCode(SourceLocation Loc,
2036 unsigned DiagID,
2037 FunctionDecl *FD) {
2038 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", 2039, __extension__ __PRETTY_FUNCTION__
))
2039 "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", 2039, __extension__ __PRETTY_FUNCTION__
))
;
2040
2041 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2042 if (FD) {
2043 FunctionEmissionStatus FES = getEmissionStatus(FD);
2044 switch (FES) {
2045 case FunctionEmissionStatus::Emitted:
2046 Kind = SemaDiagnosticBuilder::K_Immediate;
2047 break;
2048 case FunctionEmissionStatus::Unknown:
2049 Kind = SemaDiagnosticBuilder::K_Deferred;
2050 break;
2051 case FunctionEmissionStatus::TemplateDiscarded:
2052 case FunctionEmissionStatus::OMPDiscarded:
2053 case FunctionEmissionStatus::CUDADiscarded:
2054 Kind = SemaDiagnosticBuilder::K_Nop;
2055 break;
2056 }
2057 }
2058
2059 return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, *this);
2060}
2061
2062static OpenMPDefaultmapClauseKind
2063getVariableCategoryFromDecl(const LangOptions &LO, const ValueDecl *VD) {
2064 if (LO.OpenMP <= 45) {
2065 if (VD->getType().getNonReferenceType()->isScalarType())
2066 return OMPC_DEFAULTMAP_scalar;
2067 return OMPC_DEFAULTMAP_aggregate;
2068 }
2069 if (VD->getType().getNonReferenceType()->isAnyPointerType())
2070 return OMPC_DEFAULTMAP_pointer;
2071 if (VD->getType().getNonReferenceType()->isScalarType())
2072 return OMPC_DEFAULTMAP_scalar;
2073 return OMPC_DEFAULTMAP_aggregate;
2074}
2075
2076bool Sema::isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level,
2077 unsigned OpenMPCaptureLevel) const {
2078 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", 2078, __extension__ __PRETTY_FUNCTION__
))
;
2079
2080 ASTContext &Ctx = getASTContext();
2081 bool IsByRef = true;
2082
2083 // Find the directive that is associated with the provided scope.
2084 D = cast<ValueDecl>(D->getCanonicalDecl());
2085 QualType Ty = D->getType();
2086
2087 bool IsVariableUsedInMapClause = false;
2088 if (DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->hasExplicitDirective(isOpenMPTargetExecutionDirective, Level)) {
2089 // This table summarizes how a given variable should be passed to the device
2090 // given its type and the clauses where it appears. This table is based on
2091 // the description in OpenMP 4.5 [2.10.4, target Construct] and
2092 // OpenMP 4.5 [2.15.5, Data-mapping Attribute Rules and Clauses].
2093 //
2094 // =========================================================================
2095 // | type | defaultmap | pvt | first | is_device_ptr | map | res. |
2096 // | |(tofrom:scalar)| | pvt | | | |
2097 // =========================================================================
2098 // | scl | | | | - | | bycopy|
2099 // | scl | | - | x | - | - | bycopy|
2100 // | scl | | x | - | - | - | null |
2101 // | scl | x | | | - | | byref |
2102 // | scl | x | - | x | - | - | bycopy|
2103 // | scl | x | x | - | - | - | null |
2104 // | scl | | - | - | - | x | byref |
2105 // | scl | x | - | - | - | x | byref |
2106 //
2107 // | agg | n.a. | | | - | | byref |
2108 // | agg | n.a. | - | x | - | - | byref |
2109 // | agg | n.a. | x | - | - | - | null |
2110 // | agg | n.a. | - | - | - | x | byref |
2111 // | agg | n.a. | - | - | - | x[] | byref |
2112 //
2113 // | ptr | n.a. | | | - | | bycopy|
2114 // | ptr | n.a. | - | x | - | - | bycopy|
2115 // | ptr | n.a. | x | - | - | - | null |
2116 // | ptr | n.a. | - | - | - | x | byref |
2117 // | ptr | n.a. | - | - | - | x[] | bycopy|
2118 // | ptr | n.a. | - | - | x | | bycopy|
2119 // | ptr | n.a. | - | - | x | x | bycopy|
2120 // | ptr | n.a. | - | - | x | x[] | bycopy|
2121 // =========================================================================
2122 // Legend:
2123 // scl - scalar
2124 // ptr - pointer
2125 // agg - aggregate
2126 // x - applies
2127 // - - invalid in this combination
2128 // [] - mapped with an array section
2129 // byref - should be mapped by reference
2130 // byval - should be mapped by value
2131 // null - initialize a local variable to null on the device
2132 //
2133 // Observations:
2134 // - All scalar declarations that show up in a map clause have to be passed
2135 // by reference, because they may have been mapped in the enclosing data
2136 // environment.
2137 // - If the scalar value does not fit the size of uintptr, it has to be
2138 // passed by reference, regardless the result in the table above.
2139 // - For pointers mapped by value that have either an implicit map or an
2140 // array section, the runtime library may pass the NULL value to the
2141 // device instead of the value passed to it by the compiler.
2142
2143 if (Ty->isReferenceType())
2144 Ty = Ty->castAs<ReferenceType>()->getPointeeType();
2145
2146 // Locate map clauses and see if the variable being captured is referred to
2147 // in any of those clauses. Here we only care about variables, not fields,
2148 // because fields are part of aggregates.
2149 bool IsVariableAssociatedWithSection = false;
2150
2151 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->checkMappableExprComponentListsForDeclAtLevel(
2152 D, Level,
2153 [&IsVariableUsedInMapClause, &IsVariableAssociatedWithSection,
2154 D](OMPClauseMappableExprCommon::MappableExprComponentListRef
2155 MapExprComponents,
2156 OpenMPClauseKind WhereFoundClauseKind) {
2157 // Only the map clause information influences how a variable is
2158 // captured. E.g. is_device_ptr does not require changing the default
2159 // behavior.
2160 if (WhereFoundClauseKind != OMPC_map)
2161 return false;
2162
2163 auto EI = MapExprComponents.rbegin();
2164 auto EE = MapExprComponents.rend();
2165
2166 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", 2166, __extension__ __PRETTY_FUNCTION__
))
;
2167
2168 if (isa<DeclRefExpr>(EI->getAssociatedExpression()))
2169 IsVariableUsedInMapClause |= EI->getAssociatedDeclaration() == D;
2170
2171 ++EI;
2172 if (EI == EE)
2173 return false;
2174
2175 if (isa<ArraySubscriptExpr>(EI->getAssociatedExpression()) ||
2176 isa<OMPArraySectionExpr>(EI->getAssociatedExpression()) ||
2177 isa<MemberExpr>(EI->getAssociatedExpression()) ||
2178 isa<OMPArrayShapingExpr>(EI->getAssociatedExpression())) {
2179 IsVariableAssociatedWithSection = true;
2180 // There is nothing more we need to know about this variable.
2181 return true;
2182 }
2183
2184 // Keep looking for more map info.
2185 return false;
2186 });
2187
2188 if (IsVariableUsedInMapClause) {
2189 // If variable is identified in a map clause it is always captured by
2190 // reference except if it is a pointer that is dereferenced somehow.
2191 IsByRef = !(Ty->isPointerType() && IsVariableAssociatedWithSection);
2192 } else {
2193 // By default, all the data that has a scalar type is mapped by copy
2194 // (except for reduction variables).
2195 // Defaultmap scalar is mutual exclusive to defaultmap pointer
2196 IsByRef = (DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isForceCaptureByReferenceInTargetExecutable() &&
2197 !Ty->isAnyPointerType()) ||
2198 !Ty->isScalarType() ||
2199 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isDefaultmapCapturedByRef(
2200 Level, getVariableCategoryFromDecl(LangOpts, D)) ||
2201 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->hasExplicitDSA(
2202 D,
2203 [](OpenMPClauseKind K, bool AppliedToPointee) {
2204 return K == OMPC_reduction && !AppliedToPointee;
2205 },
2206 Level);
2207 }
2208 }
2209
2210 if (IsByRef && Ty.getNonReferenceType()->isScalarType()) {
2211 IsByRef =
2212 ((IsVariableUsedInMapClause &&
2213 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCaptureRegion(Level, OpenMPCaptureLevel) ==
2214 OMPD_target) ||
2215 !(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->hasExplicitDSA(
2216 D,
2217 [](OpenMPClauseKind K, bool AppliedToPointee) -> bool {
2218 return K == OMPC_firstprivate ||
2219 (K == OMPC_reduction && AppliedToPointee);
2220 },
2221 Level, /*NotLastprivate=*/true) ||
2222 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isUsesAllocatorsDecl(Level, D))) &&
2223 // If the variable is artificial and must be captured by value - try to
2224 // capture by value.
2225 !(isa<OMPCapturedExprDecl>(D) && !D->hasAttr<OMPCaptureNoInitAttr>() &&
2226 !cast<OMPCapturedExprDecl>(D)->getInit()->isGLValue()) &&
2227 // If the variable is implicitly firstprivate and scalar - capture by
2228 // copy
2229 !((DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getDefaultDSA() == DSA_firstprivate ||
2230 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getDefaultDSA() == DSA_private) &&
2231 !DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->hasExplicitDSA(
2232 D, [](OpenMPClauseKind K, bool) { return K != OMPC_unknown; },
2233 Level) &&
2234 !DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isLoopControlVariable(D, Level).first);
2235 }
2236
2237 // When passing data by copy, we need to make sure it fits the uintptr size
2238 // and alignment, because the runtime library only deals with uintptr types.
2239 // If it does not fit the uintptr size, we need to pass the data by reference
2240 // instead.
2241 if (!IsByRef &&
2242 (Ctx.getTypeSizeInChars(Ty) >
2243 Ctx.getTypeSizeInChars(Ctx.getUIntPtrType()) ||
2244 Ctx.getDeclAlign(D) > Ctx.getTypeAlignInChars(Ctx.getUIntPtrType()))) {
2245 IsByRef = true;
2246 }
2247
2248 return IsByRef;
2249}
2250
2251unsigned Sema::getOpenMPNestingLevel() const {
2252 assert(getLangOpts().OpenMP)(static_cast <bool> (getLangOpts().OpenMP) ? void (0) :
__assert_fail ("getLangOpts().OpenMP", "clang/lib/Sema/SemaOpenMP.cpp"
, 2252, __extension__ __PRETTY_FUNCTION__))
;
2253 return DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getNestingLevel();
2254}
2255
2256bool Sema::isInOpenMPTaskUntiedContext() const {
2257 return isOpenMPTaskingDirective(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective()) &&
2258 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isUntiedRegion();
2259}
2260
2261bool Sema::isInOpenMPTargetExecutionDirective() const {
2262 return (isOpenMPTargetExecutionDirective(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective()) &&
2263 !DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isClauseParsingMode()) ||
2264 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->hasDirective(
2265 [](OpenMPDirectiveKind K, const DeclarationNameInfo &,
2266 SourceLocation) -> bool {
2267 return isOpenMPTargetExecutionDirective(K);
2268 },
2269 false);
2270}
2271
2272bool Sema::isOpenMPRebuildMemberExpr(ValueDecl *D) {
2273 // Only rebuild for Field.
2274 if (!dyn_cast<FieldDecl>(D))
2275 return false;
2276 DSAStackTy::DSAVarData DVarPrivate = DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->hasDSA(
2277 D,
2278 [](OpenMPClauseKind C, bool AppliedToPointee,
2279 DefaultDataSharingAttributes DefaultAttr) {
2280 return isOpenMPPrivate(C) && !AppliedToPointee &&
2281 (DefaultAttr == DSA_firstprivate || DefaultAttr == DSA_private);
2282 },
2283 [](OpenMPDirectiveKind) { return true; },
2284 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isClauseParsingMode());
2285 if (DVarPrivate.CKind != OMPC_unknown)
2286 return true;
2287 return false;
2288}
2289
2290static OMPCapturedExprDecl *buildCaptureDecl(Sema &S, IdentifierInfo *Id,
2291 Expr *CaptureExpr, bool WithInit,
2292 DeclContext *CurContext,
2293 bool AsExpression);
2294
2295VarDecl *Sema::isOpenMPCapturedDecl(ValueDecl *D, bool CheckScopeInfo,
2296 unsigned StopAt) {
2297 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", 2297, __extension__ __PRETTY_FUNCTION__
))
;
2298 D = getCanonicalDecl(D);
2299
2300 auto *VD = dyn_cast<VarDecl>(D);
2301 // Do not capture constexpr variables.
2302 if (VD && VD->isConstexpr())
2303 return nullptr;
2304
2305 // If we want to determine whether the variable should be captured from the
2306 // perspective of the current capturing scope, and we've already left all the
2307 // capturing scopes of the top directive on the stack, check from the
2308 // perspective of its parent directive (if any) instead.
2309 DSAStackTy::ParentDirectiveScope InParentDirectiveRAII(
2310 *DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
, CheckScopeInfo && DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isBodyComplete());
2311
2312 // If we are attempting to capture a global variable in a directive with
2313 // 'target' we return true so that this global is also mapped to the device.
2314 //
2315 if (VD && !VD->hasLocalStorage() &&
2316 (getCurCapturedRegion() || getCurBlock() || getCurLambda())) {
2317 if (isInOpenMPTargetExecutionDirective()) {
2318 DSAStackTy::DSAVarData DVarTop =
2319 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getTopDSA(D, DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isClauseParsingMode());
2320 if (DVarTop.CKind != OMPC_unknown && DVarTop.RefExpr)
2321 return VD;
2322 // If the declaration is enclosed in a 'declare target' directive,
2323 // then it should not be captured.
2324 //
2325 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2326 return nullptr;
2327 CapturedRegionScopeInfo *CSI = nullptr;
2328 for (FunctionScopeInfo *FSI : llvm::drop_begin(
2329 llvm::reverse(FunctionScopes),
2330 CheckScopeInfo ? (FunctionScopes.size() - (StopAt + 1)) : 0)) {
2331 if (!isa<CapturingScopeInfo>(FSI))
2332 return nullptr;
2333 if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2334 if (RSI->CapRegionKind == CR_OpenMP) {
2335 CSI = RSI;
2336 break;
2337 }
2338 }
2339 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", 2339, __extension__ __PRETTY_FUNCTION__
))
;
2340 SmallVector<OpenMPDirectiveKind, 4> Regions;
2341 getOpenMPCaptureRegions(Regions,
2342 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getDirective(CSI->OpenMPLevel));
2343 if (Regions[CSI->OpenMPCaptureLevel] != OMPD_task)
2344 return VD;
2345 }
2346 if (isInOpenMPDeclareTargetContext()) {
2347 // Try to mark variable as declare target if it is used in capturing
2348 // regions.
2349 if (LangOpts.OpenMP <= 45 &&
2350 !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2351 checkDeclIsAllowedInOpenMPTarget(nullptr, VD);
2352 return nullptr;
2353 }
2354 }
2355
2356 if (CheckScopeInfo) {
2357 bool OpenMPFound = false;
2358 for (unsigned I = StopAt + 1; I > 0; --I) {
2359 FunctionScopeInfo *FSI = FunctionScopes[I - 1];
2360 if (!isa<CapturingScopeInfo>(FSI))
2361 return nullptr;
2362 if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2363 if (RSI->CapRegionKind == CR_OpenMP) {
2364 OpenMPFound = true;
2365 break;
2366 }
2367 }
2368 if (!OpenMPFound)
2369 return nullptr;
2370 }
2371
2372 if (DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective() != OMPD_unknown &&
2373 (!DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isClauseParsingMode() ||
2374 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getParentDirective() != OMPD_unknown)) {
2375 auto &&Info = DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isLoopControlVariable(D);
2376 if (Info.first ||
2377 (VD && VD->hasLocalStorage() &&
2378 isImplicitOrExplicitTaskingRegion(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective())) ||
2379 (VD && DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isForceVarCapturing()))
2380 return VD ? VD : Info.second;
2381 DSAStackTy::DSAVarData DVarTop =
2382 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getTopDSA(D, DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isClauseParsingMode());
2383 if (DVarTop.CKind != OMPC_unknown && isOpenMPPrivate(DVarTop.CKind) &&
2384 (!VD || VD->hasLocalStorage() || !DVarTop.AppliedToPointee))
2385 return VD ? VD : cast<VarDecl>(DVarTop.PrivateCopy->getDecl());
2386 // Threadprivate variables must not be captured.
2387 if (isOpenMPThreadPrivate(DVarTop.CKind))
2388 return nullptr;
2389 // The variable is not private or it is the variable in the directive with
2390 // default(none) clause and not used in any clause.
2391 DSAStackTy::DSAVarData DVarPrivate = DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->hasDSA(
2392 D,
2393 [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
2394 return isOpenMPPrivate(C) && !AppliedToPointee;
2395 },
2396 [](OpenMPDirectiveKind) { return true; },
2397 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isClauseParsingMode());
2398 // Global shared must not be captured.
2399 if (VD && !VD->hasLocalStorage() && DVarPrivate.CKind == OMPC_unknown &&
2400 ((DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getDefaultDSA() != DSA_none &&
2401 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getDefaultDSA() != DSA_private &&
2402 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getDefaultDSA() != DSA_firstprivate) ||
2403 DVarTop.CKind == OMPC_shared))
2404 return nullptr;
2405 auto *FD = dyn_cast<FieldDecl>(D);
2406 if (DVarPrivate.CKind != OMPC_unknown && !VD && FD &&
2407 !DVarPrivate.PrivateCopy) {
2408 DSAStackTy::DSAVarData DVarPrivate = DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->hasDSA(
2409 D,
2410 [](OpenMPClauseKind C, bool AppliedToPointee,
2411 DefaultDataSharingAttributes DefaultAttr) {
2412 return isOpenMPPrivate(C) && !AppliedToPointee &&
2413 (DefaultAttr == DSA_firstprivate ||
2414 DefaultAttr == DSA_private);
2415 },
2416 [](OpenMPDirectiveKind) { return true; },
2417 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isClauseParsingMode());
2418 if (DVarPrivate.CKind == OMPC_unknown)
2419 return nullptr;
2420
2421 VarDecl *VD = DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getImplicitFDCapExprDecl(FD);
2422 if (VD)
2423 return VD;
2424 if (getCurrentThisType().isNull())
2425 return nullptr;
2426 Expr *ThisExpr = BuildCXXThisExpr(SourceLocation(), getCurrentThisType(),
2427 /*IsImplicit=*/true);
2428 const CXXScopeSpec CS = CXXScopeSpec();
2429 Expr *ME = BuildMemberExpr(ThisExpr, /*IsArrow=*/true, SourceLocation(),
2430 NestedNameSpecifierLoc(), SourceLocation(), FD,
2431 DeclAccessPair::make(FD, FD->getAccess()),
2432 /*HadMultipleCandidates=*/false,
2433 DeclarationNameInfo(), FD->getType(),
2434 VK_LValue, OK_Ordinary);
2435 OMPCapturedExprDecl *CD = buildCaptureDecl(
2436 *this, FD->getIdentifier(), ME, DVarPrivate.CKind != OMPC_private,
2437 CurContext->getParent(), /*AsExpression=*/false);
2438 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
2439 *this, CD, CD->getType().getNonReferenceType(), SourceLocation());
2440 VD = cast<VarDecl>(VDPrivateRefExpr->getDecl());
2441 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->addImplicitDefaultFirstprivateFD(FD, VD);
2442 return VD;
2443 }
2444 if (DVarPrivate.CKind != OMPC_unknown ||
2445 (VD && (DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getDefaultDSA() == DSA_none ||
2446 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getDefaultDSA() == DSA_private ||
2447 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getDefaultDSA() == DSA_firstprivate)))
2448 return VD ? VD : cast<VarDecl>(DVarPrivate.PrivateCopy->getDecl());
2449 }
2450 return nullptr;
2451}
2452
2453void Sema::adjustOpenMPTargetScopeIndex(unsigned &FunctionScopesIndex,
2454 unsigned Level) const {
2455 FunctionScopesIndex -= getOpenMPCaptureLevels(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getDirective(Level));
2456}
2457
2458void Sema::startOpenMPLoop() {
2459 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", 2459, __extension__ __PRETTY_FUNCTION__
))
;
2460 if (isOpenMPLoopDirective(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective()))
2461 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->loopInit();
2462}
2463
2464void Sema::startOpenMPCXXRangeFor() {
2465 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", 2465, __extension__ __PRETTY_FUNCTION__
))
;
2466 if (isOpenMPLoopDirective(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective())) {
2467 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->resetPossibleLoopCounter();
2468 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->loopStart();
2469 }
2470}
2471
2472OpenMPClauseKind Sema::isOpenMPPrivateDecl(ValueDecl *D, unsigned Level,
2473 unsigned CapLevel) const {
2474 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", 2474, __extension__ __PRETTY_FUNCTION__
))
;
2475 if (DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective() != OMPD_unknown &&
2476 (!DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isClauseParsingMode() ||
2477 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getParentDirective() != OMPD_unknown)) {
2478 DSAStackTy::DSAVarData DVarPrivate = DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->hasDSA(
2479 D,
2480 [](OpenMPClauseKind C, bool AppliedToPointee,
2481 DefaultDataSharingAttributes DefaultAttr) {
2482 return isOpenMPPrivate(C) && !AppliedToPointee &&
2483 DefaultAttr == DSA_private;
2484 },
2485 [](OpenMPDirectiveKind) { return true; },
2486 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isClauseParsingMode());
2487 if (DVarPrivate.CKind == OMPC_private && isa<OMPCapturedExprDecl>(D) &&
2488 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isImplicitDefaultFirstprivateFD(cast<VarDecl>(D)) &&
2489 !DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isLoopControlVariable(D).first)
2490 return OMPC_private;
2491 }
2492 if (DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->hasExplicitDirective(isOpenMPTaskingDirective, Level)) {
2493 bool IsTriviallyCopyable =
2494 D->getType().getNonReferenceType().isTriviallyCopyableType(Context) &&
2495 !D->getType()
2496 .getNonReferenceType()
2497 .getCanonicalType()
2498 ->getAsCXXRecordDecl();
2499 OpenMPDirectiveKind DKind = DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getDirective(Level);
2500 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
2501 getOpenMPCaptureRegions(CaptureRegions, DKind);
2502 if (isOpenMPTaskingDirective(CaptureRegions[CapLevel]) &&
2503 (IsTriviallyCopyable ||
2504 !isOpenMPTaskLoopDirective(CaptureRegions[CapLevel]))) {
2505 if (DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->hasExplicitDSA(
2506 D,
2507 [](OpenMPClauseKind K, bool) { return K == OMPC_firstprivate; },
2508 Level, /*NotLastprivate=*/true))
2509 return OMPC_firstprivate;
2510 DSAStackTy::DSAVarData DVar = DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getImplicitDSA(D, Level);
2511 if (DVar.CKind != OMPC_shared &&
2512 !DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isLoopControlVariable(D, Level).first && !DVar.RefExpr) {
2513 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->addImplicitTaskFirstprivate(Level, D);
2514 return OMPC_firstprivate;
2515 }
2516 }
2517 }
2518 if (isOpenMPLoopDirective(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective())) {
2519 if (DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getAssociatedLoops() > 0 && !DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isLoopStarted()) {
2520 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->resetPossibleLoopCounter(D);
2521 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->loopStart();
2522 return OMPC_private;
2523 }
2524 if ((DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getPossiblyLoopCunter() == D->getCanonicalDecl() ||
2525 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isLoopControlVariable(D).first) &&
2526 !DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->hasExplicitDSA(
2527 D, [](OpenMPClauseKind K, bool) { return K != OMPC_private; },
2528 Level) &&
2529 !isOpenMPSimdDirective(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective()))
2530 return OMPC_private;
2531 }
2532 if (const auto *VD = dyn_cast<VarDecl>(D)) {
2533 if (DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isThreadPrivate(const_cast<VarDecl *>(VD)) &&
2534 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isForceVarCapturing() &&
2535 !DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->hasExplicitDSA(
2536 D, [](OpenMPClauseKind K, bool) { return K == OMPC_copyin; },
2537 Level))
2538 return OMPC_private;
2539 }
2540 // User-defined allocators are private since they must be defined in the
2541 // context of target region.
2542 if (DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->hasExplicitDirective(isOpenMPTargetExecutionDirective, Level) &&
2543 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isUsesAllocatorsDecl(Level, D).value_or(
2544 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
2545 DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator)
2546 return OMPC_private;
2547 return (DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->hasExplicitDSA(
2548 D, [](OpenMPClauseKind K, bool) { return K == OMPC_private; },
2549 Level) ||
2550 (DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isClauseParsingMode() &&
2551 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getClauseParsingMode() == OMPC_private) ||
2552 // Consider taskgroup reduction descriptor variable a private
2553 // to avoid possible capture in the region.
2554 (DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->hasExplicitDirective(
2555 [](OpenMPDirectiveKind K) {
2556 return K == OMPD_taskgroup ||
2557 ((isOpenMPParallelDirective(K) ||
2558 isOpenMPWorksharingDirective(K)) &&
2559 !isOpenMPSimdDirective(K));
2560 },
2561 Level) &&
2562 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isTaskgroupReductionRef(D, Level)))
2563 ? OMPC_private
2564 : OMPC_unknown;
2565}
2566
2567void Sema::setOpenMPCaptureKind(FieldDecl *FD, const ValueDecl *D,
2568 unsigned Level) {
2569 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", 2569, __extension__ __PRETTY_FUNCTION__
))
;
2570 D = getCanonicalDecl(D);
2571 OpenMPClauseKind OMPC = OMPC_unknown;
2572 for (unsigned I = DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getNestingLevel() + 1; I > Level; --I) {
2573 const unsigned NewLevel = I - 1;
2574 if (DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->hasExplicitDSA(
2575 D,
2576 [&OMPC](const OpenMPClauseKind K, bool AppliedToPointee) {
2577 if (isOpenMPPrivate(K) && !AppliedToPointee) {
2578 OMPC = K;
2579 return true;
2580 }
2581 return false;
2582 },
2583 NewLevel))
2584 break;
2585 if (DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->checkMappableExprComponentListsForDeclAtLevel(
2586 D, NewLevel,
2587 [](OMPClauseMappableExprCommon::MappableExprComponentListRef,
2588 OpenMPClauseKind) { return true; })) {
2589 OMPC = OMPC_map;
2590 break;
2591 }
2592 if (DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->hasExplicitDirective(isOpenMPTargetExecutionDirective,
2593 NewLevel)) {
2594 OMPC = OMPC_map;
2595 if (DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->mustBeFirstprivateAtLevel(
2596 NewLevel, getVariableCategoryFromDecl(LangOpts, D)))
2597 OMPC = OMPC_firstprivate;
2598 break;
2599 }
2600 }
2601 if (OMPC != OMPC_unknown)
2602 FD->addAttr(OMPCaptureKindAttr::CreateImplicit(Context, unsigned(OMPC)));
2603}
2604
2605bool Sema::isOpenMPTargetCapturedDecl(const ValueDecl *D, unsigned Level,
2606 unsigned CaptureLevel) const {
2607 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", 2607, __extension__ __PRETTY_FUNCTION__
))
;
2608 // Return true if the current level is no longer enclosed in a target region.
2609
2610 SmallVector<OpenMPDirectiveKind, 4> Regions;
2611 getOpenMPCaptureRegions(Regions, DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getDirective(Level));
2612 const auto *VD = dyn_cast<VarDecl>(D);
2613 return VD && !VD->hasLocalStorage() &&
2614 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->hasExplicitDirective(isOpenMPTargetExecutionDirective,
2615 Level) &&
2616 Regions[CaptureLevel] != OMPD_task;
2617}
2618
2619bool Sema::isOpenMPGlobalCapturedDecl(ValueDecl *D, unsigned Level,
2620 unsigned CaptureLevel) const {
2621 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", 2621, __extension__ __PRETTY_FUNCTION__
))
;
2622 // Return true if the current level is no longer enclosed in a target region.
2623
2624 if (const auto *VD = dyn_cast<VarDecl>(D)) {
2625 if (!VD->hasLocalStorage()) {
2626 if (isInOpenMPTargetExecutionDirective())
2627 return true;
2628 DSAStackTy::DSAVarData TopDVar =
2629 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getTopDSA(D, /*FromParent=*/false);
2630 unsigned NumLevels =
2631 getOpenMPCaptureLevels(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getDirective(Level));
2632 if (Level == 0)
2633 // non-file scope static variale with default(firstprivate)
2634 // should be gloabal captured.
2635 return (NumLevels == CaptureLevel + 1 &&
2636 (TopDVar.CKind != OMPC_shared ||
2637 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getDefaultDSA() == DSA_firstprivate));
2638 do {
2639 --Level;
2640 DSAStackTy::DSAVarData DVar = DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getImplicitDSA(D, Level);
2641 if (DVar.CKind != OMPC_shared)
2642 return true;
2643 } while (Level > 0);
2644 }
2645 }
2646 return true;
2647}
2648
2649void Sema::DestroyDataSharingAttributesStack() { delete DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
; }
2650
2651void Sema::ActOnOpenMPBeginDeclareVariant(SourceLocation Loc,
2652 OMPTraitInfo &TI) {
2653 OMPDeclareVariantScopes.push_back(OMPDeclareVariantScope(TI));
2654}
2655
2656void Sema::ActOnOpenMPEndDeclareVariant() {
2657 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", 2658, __extension__ __PRETTY_FUNCTION__
))
2658 "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", 2658, __extension__ __PRETTY_FUNCTION__
))
;
2659
2660 OMPDeclareVariantScopes.pop_back();
2661}
2662
2663void Sema::finalizeOpenMPDelayedAnalysis(const FunctionDecl *Caller,
2664 const FunctionDecl *Callee,
2665 SourceLocation Loc) {
2666 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", 2666, __extension__ __PRETTY_FUNCTION__
))
;
2667 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2668 OMPDeclareTargetDeclAttr::getDeviceType(Caller->getMostRecentDecl());
2669 // Ignore host functions during device analyzis.
2670 if (LangOpts.OpenMPIsDevice &&
2671 (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host))
2672 return;
2673 // Ignore nohost functions during host analyzis.
2674 if (!LangOpts.OpenMPIsDevice && DevTy &&
2675 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
2676 return;
2677 const FunctionDecl *FD = Callee->getMostRecentDecl();
2678 DevTy = OMPDeclareTargetDeclAttr::getDeviceType(FD);
2679 if (LangOpts.OpenMPIsDevice && DevTy &&
2680 *DevTy == OMPDeclareTargetDeclAttr::DT_Host) {
2681 // Diagnose host function called during device codegen.
2682 StringRef HostDevTy =
2683 getOpenMPSimpleClauseTypeName(OMPC_device_type, OMPC_DEVICE_TYPE_host);
2684 Diag(Loc, diag::err_omp_wrong_device_function_call) << HostDevTy << 0;
2685 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2686 diag::note_omp_marked_device_type_here)
2687 << HostDevTy;
2688 return;
2689 }
2690 if (!LangOpts.OpenMPIsDevice && !LangOpts.OpenMPOffloadMandatory && DevTy &&
2691 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) {
2692 // Diagnose nohost function called during host codegen.
2693 StringRef NoHostDevTy = getOpenMPSimpleClauseTypeName(
2694 OMPC_device_type, OMPC_DEVICE_TYPE_nohost);
2695 Diag(Loc, diag::err_omp_wrong_device_function_call) << NoHostDevTy << 1;
2696 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2697 diag::note_omp_marked_device_type_here)
2698 << NoHostDevTy;
2699 }
2700}
2701
2702void Sema::StartOpenMPDSABlock(OpenMPDirectiveKind DKind,
2703 const DeclarationNameInfo &DirName,
2704 Scope *CurScope, SourceLocation Loc) {
2705 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->push(DKind, DirName, CurScope, Loc);
2706 PushExpressionEvaluationContext(
2707 ExpressionEvaluationContext::PotentiallyEvaluated);
2708}
2709
2710void Sema::StartOpenMPClause(OpenMPClauseKind K) {
2711 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->setClauseParsingMode(K);
2712}
2713
2714void Sema::EndOpenMPClause() {
2715 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->setClauseParsingMode(/*K=*/OMPC_unknown);
2716 CleanupVarDeclMarking();
2717}
2718
2719static std::pair<ValueDecl *, bool>
2720getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc,
2721 SourceRange &ERange, bool AllowArraySection = false,
2722 StringRef DiagType = "");
2723
2724/// Check consistency of the reduction clauses.
2725static void checkReductionClauses(Sema &S, DSAStackTy *Stack,
2726 ArrayRef<OMPClause *> Clauses) {
2727 bool InscanFound = false;
2728 SourceLocation InscanLoc;
2729 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions.
2730 // A reduction clause without the inscan reduction-modifier may not appear on
2731 // a construct on which a reduction clause with the inscan reduction-modifier
2732 // appears.
2733 for (OMPClause *C : Clauses) {
2734 if (C->getClauseKind() != OMPC_reduction)
2735 continue;
2736 auto *RC = cast<OMPReductionClause>(C);
2737 if (RC->getModifier() == OMPC_REDUCTION_inscan) {
2738 InscanFound = true;
2739 InscanLoc = RC->getModifierLoc();
2740 continue;
2741 }
2742 if (RC->getModifier() == OMPC_REDUCTION_task) {
2743 // OpenMP 5.0, 2.19.5.4 reduction Clause.
2744 // A reduction clause with the task reduction-modifier may only appear on
2745 // a parallel construct, a worksharing construct or a combined or
2746 // composite construct for which any of the aforementioned constructs is a
2747 // constituent construct and simd or loop are not constituent constructs.
2748 OpenMPDirectiveKind CurDir = Stack->getCurrentDirective();
2749 if (!(isOpenMPParallelDirective(CurDir) ||
2750 isOpenMPWorksharingDirective(CurDir)) ||
2751 isOpenMPSimdDirective(CurDir))
2752 S.Diag(RC->getModifierLoc(),
2753 diag::err_omp_reduction_task_not_parallel_or_worksharing);
2754 continue;
2755 }
2756 }
2757 if (InscanFound) {
2758 for (OMPClause *C : Clauses) {
2759 if (C->getClauseKind() != OMPC_reduction)
2760 continue;
2761 auto *RC = cast<OMPReductionClause>(C);
2762 if (RC->getModifier() != OMPC_REDUCTION_inscan) {
2763 S.Diag(RC->getModifier() == OMPC_REDUCTION_unknown
2764 ? RC->getBeginLoc()
2765 : RC->getModifierLoc(),
2766 diag::err_omp_inscan_reduction_expected);
2767 S.Diag(InscanLoc, diag::note_omp_previous_inscan_reduction);
2768 continue;
2769 }
2770 for (Expr *Ref : RC->varlists()) {
2771 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", 2771, __extension__ __PRETTY_FUNCTION__
))
;
2772 SourceLocation ELoc;
2773 SourceRange ERange;
2774 Expr *SimpleRefExpr = Ref;
2775 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
2776 /*AllowArraySection=*/true);
2777 ValueDecl *D = Res.first;
2778 if (!D)
2779 continue;
2780 if (!Stack->isUsedInScanDirective(getCanonicalDecl(D))) {
2781 S.Diag(Ref->getExprLoc(),
2782 diag::err_omp_reduction_not_inclusive_exclusive)
2783 << Ref->getSourceRange();
2784 }
2785 }
2786 }
2787 }
2788}
2789
2790static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
2791 ArrayRef<OMPClause *> Clauses);
2792static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
2793 bool WithInit);
2794
2795static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
2796 const ValueDecl *D,
2797 const DSAStackTy::DSAVarData &DVar,
2798 bool IsLoopIterVar = false);
2799
2800void Sema::EndOpenMPDSABlock(Stmt *CurDirective) {
2801 // OpenMP [2.14.3.5, Restrictions, C/C++, p.1]
2802 // A variable of class type (or array thereof) that appears in a lastprivate
2803 // clause requires an accessible, unambiguous default constructor for the
2804 // class type, unless the list item is also specified in a firstprivate
2805 // clause.
2806 if (const auto *D = dyn_cast_or_null<OMPExecutableDirective>(CurDirective)) {
2807 for (OMPClause *C : D->clauses()) {
2808 if (auto *Clause = dyn_cast<OMPLastprivateClause>(C)) {
2809 SmallVector<Expr *, 8> PrivateCopies;
2810 for (Expr *DE : Clause->varlists()) {
2811 if (DE->isValueDependent() || DE->isTypeDependent()) {
2812 PrivateCopies.push_back(nullptr);
2813 continue;
2814 }
2815 auto *DRE = cast<DeclRefExpr>(DE->IgnoreParens());
2816 auto *VD = cast<VarDecl>(DRE->getDecl());
2817 QualType Type = VD->getType().getNonReferenceType();
2818 const DSAStackTy::DSAVarData DVar =
2819 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getTopDSA(VD, /*FromParent=*/false);
2820 if (DVar.CKind == OMPC_lastprivate) {
2821 // Generate helper private variable and initialize it with the
2822 // default value. The address of the original variable is replaced
2823 // by the address of the new private variable in CodeGen. This new
2824 // variable is not added to IdResolver, so the code in the OpenMP
2825 // region uses original variable for proper diagnostics.
2826 VarDecl *VDPrivate = buildVarDecl(
2827 *this, DE->getExprLoc(), Type.getUnqualifiedType(),
2828 VD->getName(), VD->hasAttrs() ? &VD->getAttrs() : nullptr, DRE);
2829 ActOnUninitializedDecl(VDPrivate);
2830 if (VDPrivate->isInvalidDecl()) {
2831 PrivateCopies.push_back(nullptr);
2832 continue;
2833 }
2834 PrivateCopies.push_back(buildDeclRefExpr(
2835 *this, VDPrivate, DE->getType(), DE->getExprLoc()));
2836 } else {
2837 // The variable is also a firstprivate, so initialization sequence
2838 // for private copy is generated already.
2839 PrivateCopies.push_back(nullptr);
2840 }
2841 }
2842 Clause->setPrivateCopies(PrivateCopies);
2843 continue;
2844 }
2845 // Finalize nontemporal clause by handling private copies, if any.
2846 if (auto *Clause = dyn_cast<OMPNontemporalClause>(C)) {
2847 SmallVector<Expr *, 8> PrivateRefs;
2848 for (Expr *RefExpr : Clause->varlists()) {
2849 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", 2849, __extension__ __PRETTY_FUNCTION__
))
;
2850 SourceLocation ELoc;
2851 SourceRange ERange;
2852 Expr *SimpleRefExpr = RefExpr;
2853 auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
2854 if (Res.second)
2855 // It will be analyzed later.
2856 PrivateRefs.push_back(RefExpr);
2857 ValueDecl *D = Res.first;
2858 if (!D)
2859 continue;
2860
2861 const DSAStackTy::DSAVarData DVar =
2862 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getTopDSA(D, /*FromParent=*/false);
2863 PrivateRefs.push_back(DVar.PrivateCopy ? DVar.PrivateCopy
2864 : SimpleRefExpr);
2865 }
2866 Clause->setPrivateRefs(PrivateRefs);
2867 continue;
2868 }
2869 if (auto *Clause = dyn_cast<OMPUsesAllocatorsClause>(C)) {
2870 for (unsigned I = 0, E = Clause->getNumberOfAllocators(); I < E; ++I) {
2871 OMPUsesAllocatorsClause::Data D = Clause->getAllocatorData(I);
2872 auto *DRE = dyn_cast<DeclRefExpr>(D.Allocator->IgnoreParenImpCasts());
2873 if (!DRE)
2874 continue;
2875 ValueDecl *VD = DRE->getDecl();
2876 if (!VD || !isa<VarDecl>(VD))
2877 continue;
2878 DSAStackTy::DSAVarData DVar =
2879 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getTopDSA(VD, /*FromParent=*/false);
2880 // OpenMP [2.12.5, target Construct]
2881 // Memory allocators that appear in a uses_allocators clause cannot
2882 // appear in other data-sharing attribute clauses or data-mapping
2883 // attribute clauses in the same construct.
2884 Expr *MapExpr = nullptr;
2885 if (DVar.RefExpr ||
2886 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->checkMappableExprComponentListsForDecl(
2887 VD, /*CurrentRegionOnly=*/true,
2888 [VD, &MapExpr](
2889 OMPClauseMappableExprCommon::MappableExprComponentListRef
2890 MapExprComponents,
2891 OpenMPClauseKind C) {
2892 auto MI = MapExprComponents.rbegin();
2893 auto ME = MapExprComponents.rend();
2894 if (MI != ME &&
2895 MI->getAssociatedDeclaration()->getCanonicalDecl() ==
2896 VD->getCanonicalDecl()) {
2897 MapExpr = MI->getAssociatedExpression();
2898 return true;
2899 }
2900 return false;
2901 })) {
2902 Diag(D.Allocator->getExprLoc(),
2903 diag::err_omp_allocator_used_in_clauses)
2904 << D.Allocator->getSourceRange();
2905 if (DVar.RefExpr)
2906 reportOriginalDsa(*this, DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
, VD, DVar);
2907 else
2908 Diag(MapExpr->getExprLoc(), diag::note_used_here)
2909 << MapExpr->getSourceRange();
2910 }
2911 }
2912 continue;
2913 }
2914 }
2915 // Check allocate clauses.
2916 if (!CurContext->isDependentContext())
2917 checkAllocateClauses(*this, DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
, D->clauses());
2918 checkReductionClauses(*this, DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
, D->clauses());
2919 }
2920
2921 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->pop();
2922 DiscardCleanupsInEvaluationContext();
2923 PopExpressionEvaluationContext();
2924}
2925
2926static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
2927 Expr *NumIterations, Sema &SemaRef,
2928 Scope *S, DSAStackTy *Stack);
2929
2930namespace {
2931
2932class VarDeclFilterCCC final : public CorrectionCandidateCallback {
2933private:
2934 Sema &SemaRef;
2935
2936public:
2937 explicit VarDeclFilterCCC(Sema &S) : SemaRef(S) {}
2938 bool ValidateCandidate(const TypoCorrection &Candidate) override {
2939 NamedDecl *ND = Candidate.getCorrectionDecl();
2940 if (const auto *VD = dyn_cast_or_null<VarDecl>(ND)) {
2941 return VD->hasGlobalStorage() &&
2942 SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(),
2943 SemaRef.getCurScope());
2944 }
2945 return false;
2946 }
2947
2948 std::unique_ptr<CorrectionCandidateCallback> clone() override {
2949 return std::make_unique<VarDeclFilterCCC>(*this);
2950 }
2951};
2952
2953class VarOrFuncDeclFilterCCC final : public CorrectionCandidateCallback {
2954private:
2955 Sema &SemaRef;
2956
2957public:
2958 explicit VarOrFuncDeclFilterCCC(Sema &S) : SemaRef(S) {}
2959 bool ValidateCandidate(const TypoCorrection &Candidate) override {
2960 NamedDecl *ND = Candidate.getCorrectionDecl();
2961 if (ND && ((isa<VarDecl>(ND) && ND->getKind() == Decl::Var) ||
2962 isa<FunctionDecl>(ND))) {
2963 return SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(),
2964 SemaRef.getCurScope());
2965 }
2966 return false;
2967 }
2968
2969 std::unique_ptr<CorrectionCandidateCallback> clone() override {
2970 return std::make_unique<VarOrFuncDeclFilterCCC>(*this);
2971 }
2972};
2973
2974} // namespace
2975
2976ExprResult Sema::ActOnOpenMPIdExpression(Scope *CurScope,
2977 CXXScopeSpec &ScopeSpec,
2978 const DeclarationNameInfo &Id,
2979 OpenMPDirectiveKind Kind) {
2980 LookupResult Lookup(*this, Id, LookupOrdinaryName);
2981 LookupParsedName(Lookup, CurScope, &ScopeSpec, true);
2982
2983 if (Lookup.isAmbiguous())
2984 return ExprError();
2985
2986 VarDecl *VD;
2987 if (!Lookup.isSingleResult()) {
2988 VarDeclFilterCCC CCC(*this);
2989 if (TypoCorrection Corrected =
2990 CorrectTypo(Id, LookupOrdinaryName, CurScope, nullptr, CCC,
2991 CTK_ErrorRecovery)) {
2992 diagnoseTypo(Corrected,
2993 PDiag(Lookup.empty()
2994 ? diag::err_undeclared_var_use_suggest
2995 : diag::err_omp_expected_var_arg_suggest)
2996 << Id.getName());
2997 VD = Corrected.getCorrectionDeclAs<VarDecl>();
2998 } else {
2999 Diag(Id.getLoc(), Lookup.empty() ? diag::err_undeclared_var_use
3000 : diag::err_omp_expected_var_arg)
3001 << Id.getName();
3002 return ExprError();
3003 }
3004 } else if (!(VD = Lookup.getAsSingle<VarDecl>())) {
3005 Diag(Id.getLoc(), diag::err_omp_expected_var_arg) << Id.getName();
3006 Diag(Lookup.getFoundDecl()->getLocation(), diag::note_declared_at);
3007 return ExprError();
3008 }
3009 Lookup.suppressDiagnostics();
3010
3011 // OpenMP [2.9.2, Syntax, C/C++]
3012 // Variables must be file-scope, namespace-scope, or static block-scope.
3013 if (Kind == OMPD_threadprivate && !VD->hasGlobalStorage()) {
3014 Diag(Id.getLoc(), diag::err_omp_global_var_arg)
3015 << getOpenMPDirectiveName(Kind) << !VD->isStaticLocal();
3016 bool IsDecl =
3017 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3018 Diag(VD->getLocation(),
3019 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3020 << VD;
3021 return ExprError();
3022 }
3023
3024 VarDecl *CanonicalVD = VD->getCanonicalDecl();
3025 NamedDecl *ND = CanonicalVD;
3026 // OpenMP [2.9.2, Restrictions, C/C++, p.2]
3027 // A threadprivate directive for file-scope variables must appear outside
3028 // any definition or declaration.
3029 if (CanonicalVD->getDeclContext()->isTranslationUnit() &&
3030 !getCurLexicalContext()->isTranslationUnit()) {
3031 Diag(Id.getLoc(), diag::err_omp_var_scope)
3032 << getOpenMPDirectiveName(Kind) << VD;
3033 bool IsDecl =
3034 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3035 Diag(VD->getLocation(),
3036 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3037 << VD;
3038 return ExprError();
3039 }
3040 // OpenMP [2.9.2, Restrictions, C/C++, p.3]
3041 // A threadprivate directive for static class member variables must appear
3042 // in the class definition, in the same scope in which the member
3043 // variables are declared.
3044 if (CanonicalVD->isStaticDataMember() &&
3045 !CanonicalVD->getDeclContext()->Equals(getCurLexicalContext())) {
3046 Diag(Id.getLoc(), diag::err_omp_var_scope)
3047 << getOpenMPDirectiveName(Kind) << VD;
3048 bool IsDecl =
3049 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3050 Diag(VD->getLocation(),
3051 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3052 << VD;
3053 return ExprError();
3054 }
3055 // OpenMP [2.9.2, Restrictions, C/C++, p.4]
3056 // A threadprivate directive for namespace-scope variables must appear
3057 // outside any definition or declaration other than the namespace
3058 // definition itself.
3059 if (CanonicalVD->getDeclContext()->isNamespace() &&
3060 (!getCurLexicalContext()->isFileContext() ||
3061 !getCurLexicalContext()->Encloses(CanonicalVD->getDeclContext()))) {
3062 Diag(Id.getLoc(), diag::err_omp_var_scope)
3063 << getOpenMPDirectiveName(Kind) << VD;
3064 bool IsDecl =
3065 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3066 Diag(VD->getLocation(),
3067 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3068 << VD;
3069 return ExprError();
3070 }
3071 // OpenMP [2.9.2, Restrictions, C/C++, p.6]
3072 // A threadprivate directive for static block-scope variables must appear
3073 // in the scope of the variable and not in a nested scope.
3074 if (CanonicalVD->isLocalVarDecl() && CurScope &&
3075 !isDeclInScope(ND, getCurLexicalContext(), CurScope)) {
3076 Diag(Id.getLoc(), diag::err_omp_var_scope)
3077 << getOpenMPDirectiveName(Kind) << VD;
3078 bool IsDecl =
3079 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3080 Diag(VD->getLocation(),
3081 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3082 << VD;
3083 return ExprError();
3084 }
3085
3086 // OpenMP [2.9.2, Restrictions, C/C++, p.2-6]
3087 // A threadprivate directive must lexically precede all references to any
3088 // of the variables in its list.
3089 if (Kind == OMPD_threadprivate && VD->isUsed() &&
3090 !DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isThreadPrivate(VD)) {
3091 Diag(Id.getLoc(), diag::err_omp_var_used)
3092 << getOpenMPDirectiveName(Kind) << VD;
3093 return ExprError();
3094 }
3095
3096 QualType ExprType = VD->getType().getNonReferenceType();
3097 return DeclRefExpr::Create(Context, NestedNameSpecifierLoc(),
3098 SourceLocation(), VD,
3099 /*RefersToEnclosingVariableOrCapture=*/false,
3100 Id.getLoc(), ExprType, VK_LValue);
3101}
3102
3103Sema::DeclGroupPtrTy
3104Sema::ActOnOpenMPThreadprivateDirective(SourceLocation Loc,
3105 ArrayRef<Expr *> VarList) {
3106 if (OMPThreadPrivateDecl *D = CheckOMPThreadPrivateDecl(Loc, VarList)) {
3107 CurContext->addDecl(D);
3108 return DeclGroupPtrTy::make(DeclGroupRef(D));
3109 }
3110 return nullptr;
3111}
3112
3113namespace {
3114class LocalVarRefChecker final
3115 : public ConstStmtVisitor<LocalVarRefChecker, bool> {
3116 Sema &SemaRef;
3117
3118public:
3119 bool VisitDeclRefExpr(const DeclRefExpr *E) {
3120 if (const auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
3121 if (VD->hasLocalStorage()) {
3122 SemaRef.Diag(E->getBeginLoc(),
3123 diag::err_omp_local_var_in_threadprivate_init)
3124 << E->getSourceRange();
3125 SemaRef.Diag(VD->getLocation(), diag::note_defined_here)
3126 << VD << VD->getSourceRange();
3127 return true;
3128 }
3129 }
3130 return false;
3131 }
3132 bool VisitStmt(const Stmt *S) {
3133 for (const Stmt *Child : S->children()) {
3134 if (Child && Visit(Child))
3135 return true;
3136 }
3137 return false;
3138 }
3139 explicit LocalVarRefChecker(Sema &SemaRef) : SemaRef(SemaRef) {}
3140};
3141} // namespace
3142
3143OMPThreadPrivateDecl *
3144Sema::CheckOMPThreadPrivateDecl(SourceLocation Loc, ArrayRef<Expr *> VarList) {
3145 SmallVector<Expr *, 8> Vars;
3146 for (Expr *RefExpr : VarList) {
3147 auto *DE = cast<DeclRefExpr>(RefExpr);
3148 auto *VD = cast<VarDecl>(DE->getDecl());
3149 SourceLocation ILoc = DE->getExprLoc();
3150
3151 // Mark variable as used.
3152 VD->setReferenced();
3153 VD->markUsed(Context);
3154
3155 QualType QType = VD->getType();
3156 if (QType->isDependentType() || QType->isInstantiationDependentType()) {
3157 // It will be analyzed later.
3158 Vars.push_back(DE);
3159 continue;
3160 }
3161
3162 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3163 // A threadprivate variable must not have an incomplete type.
3164 if (RequireCompleteType(ILoc, VD->getType(),
3165 diag::err_omp_threadprivate_incomplete_type)) {
3166 continue;
3167 }
3168
3169 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3170 // A threadprivate variable must not have a reference type.
3171 if (VD->getType()->isReferenceType()) {
3172 Diag(ILoc, diag::err_omp_ref_type_arg)
3173 << getOpenMPDirectiveName(OMPD_threadprivate) << VD->getType();
3174 bool IsDecl =
3175 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3176 Diag(VD->getLocation(),
3177 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3178 << VD;
3179 continue;
3180 }
3181
3182 // Check if this is a TLS variable. If TLS is not being supported, produce
3183 // the corresponding diagnostic.
3184 if ((VD->getTLSKind() != VarDecl::TLS_None &&
3185 !(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
3186 getLangOpts().OpenMPUseTLS &&
3187 getASTContext().getTargetInfo().isTLSSupported())) ||
3188 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3189 !VD->isLocalVarDecl())) {
3190 Diag(ILoc, diag::err_omp_var_thread_local)
3191 << VD << ((VD->getTLSKind() != VarDecl::TLS_None) ? 0 : 1);
3192 bool IsDecl =
3193 VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
3194 Diag(VD->getLocation(),
3195 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3196 << VD;
3197 continue;
3198 }
3199
3200 // Check if initial value of threadprivate variable reference variable with
3201 // local storage (it is not supported by runtime).
3202 if (const Expr *Init = VD->getAnyInitializer()) {
3203 LocalVarRefChecker Checker(*this);
3204 if (Checker.Visit(Init))
3205 continue;
3206 }
3207
3208 Vars.push_back(RefExpr);
3209 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->addDSA(VD, DE, OMPC_threadprivate);
3210 VD->addAttr(OMPThreadPrivateDeclAttr::CreateImplicit(
3211 Context, SourceRange(Loc, Loc)));
3212 if (ASTMutationListener *ML = Context.getASTMutationListener())
3213 ML->DeclarationMarkedOpenMPThreadPrivate(VD);
3214 }
3215 OMPThreadPrivateDecl *D = nullptr;
3216 if (!Vars.empty()) {
3217 D = OMPThreadPrivateDecl::Create(Context, getCurLexicalContext(), Loc,
3218 Vars);
3219 D->setAccess(AS_public);
3220 }
3221 return D;
3222}
3223
3224static OMPAllocateDeclAttr::AllocatorTypeTy
3225getAllocatorKind(Sema &S, DSAStackTy *Stack, Expr *Allocator) {
3226 if (!Allocator)
3227 return OMPAllocateDeclAttr::OMPNullMemAlloc;
3228 if (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3229 Allocator->isInstantiationDependent() ||
3230 Allocator->containsUnexpandedParameterPack())
3231 return OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3232 auto AllocatorKindRes = OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3233 const Expr *AE = Allocator->IgnoreParenImpCasts();
3234 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
3235 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
3236 const Expr *DefAllocator = Stack->getAllocator(AllocatorKind);
3237 llvm::FoldingSetNodeID AEId, DAEId;
3238 AE->Profile(AEId, S.getASTContext(), /*Canonical=*/true);
3239 DefAllocator->Profile(DAEId, S.getASTContext(), /*Canonical=*/true);
3240 if (AEId == DAEId) {
3241 AllocatorKindRes = AllocatorKind;
3242 break;
3243 }
3244 }
3245 return AllocatorKindRes;
3246}
3247
3248static bool checkPreviousOMPAllocateAttribute(
3249 Sema &S, DSAStackTy *Stack, Expr *RefExpr, VarDecl *VD,
3250 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind, Expr *Allocator) {
3251 if (!VD->hasAttr<OMPAllocateDeclAttr>())
3252 return false;
3253 const auto *A = VD->getAttr<OMPAllocateDeclAttr>();
3254 Expr *PrevAllocator = A->getAllocator();
3255 OMPAllocateDeclAttr::AllocatorTypeTy PrevAllocatorKind =
3256 getAllocatorKind(S, Stack, PrevAllocator);
3257 bool AllocatorsMatch = AllocatorKind == PrevAllocatorKind;
3258 if (AllocatorsMatch &&
3259 AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc &&
3260 Allocator && PrevAllocator) {
3261 const Expr *AE = Allocator->IgnoreParenImpCasts();
3262 const Expr *PAE = PrevAllocator->IgnoreParenImpCasts();
3263 llvm::FoldingSetNodeID AEId, PAEId;
3264 AE->Profile(AEId, S.Context, /*Canonical=*/true);
3265 PAE->Profile(PAEId, S.Context, /*Canonical=*/true);
3266 AllocatorsMatch = AEId == PAEId;
3267 }
3268 if (!AllocatorsMatch) {
3269 SmallString<256> AllocatorBuffer;
3270 llvm::raw_svector_ostream AllocatorStream(AllocatorBuffer);
3271 if (Allocator)
3272 Allocator->printPretty(AllocatorStream, nullptr, S.getPrintingPolicy());
3273 SmallString<256> PrevAllocatorBuffer;
3274 llvm::raw_svector_ostream PrevAllocatorStream(PrevAllocatorBuffer);
3275 if (PrevAllocator)
3276 PrevAllocator->printPretty(PrevAllocatorStream, nullptr,
3277 S.getPrintingPolicy());
3278
3279 SourceLocation AllocatorLoc =
3280 Allocator ? Allocator->getExprLoc() : RefExpr->getExprLoc();
3281 SourceRange AllocatorRange =
3282 Allocator ? Allocator->getSourceRange() : RefExpr->getSourceRange();
3283 SourceLocation PrevAllocatorLoc =
3284 PrevAllocator ? PrevAllocator->getExprLoc() : A->getLocation();
3285 SourceRange PrevAllocatorRange =
3286 PrevAllocator ? PrevAllocator->getSourceRange() : A->getRange();
3287 S.Diag(AllocatorLoc, diag::warn_omp_used_different_allocator)
3288 << (Allocator ? 1 : 0) << AllocatorStream.str()
3289 << (PrevAllocator ? 1 : 0) << PrevAllocatorStream.str()
3290 << AllocatorRange;
3291 S.Diag(PrevAllocatorLoc, diag::note_omp_previous_allocator)
3292 << PrevAllocatorRange;
3293 return true;
3294 }
3295 return false;
3296}
3297
3298static void
3299applyOMPAllocateAttribute(Sema &S, VarDecl *VD,
3300 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
3301 Expr *Allocator, Expr *Alignment, SourceRange SR) {
3302 if (VD->hasAttr<OMPAllocateDeclAttr>())
3303 return;
3304 if (Alignment &&
3305 (Alignment->isTypeDependent() || Alignment->isValueDependent() ||
3306 Alignment->isInstantiationDependent() ||
3307 Alignment->containsUnexpandedParameterPack()))
3308 // Apply later when we have a usable value.
3309 return;
3310 if (Allocator &&
3311 (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3312 Allocator->isInstantiationDependent() ||
3313 Allocator->containsUnexpandedParameterPack()))
3314 return;
3315 auto *A = OMPAllocateDeclAttr::CreateImplicit(S.Context, AllocatorKind,
3316 Allocator, Alignment, SR);
3317 VD->addAttr(A);
3318 if (ASTMutationListener *ML = S.Context.getASTMutationListener())
3319 ML->DeclarationMarkedOpenMPAllocate(VD, A);
3320}
3321
3322Sema::DeclGroupPtrTy
3323Sema::ActOnOpenMPAllocateDirective(SourceLocation Loc, ArrayRef<Expr *> VarList,
3324 ArrayRef<OMPClause *> Clauses,
3325 DeclContext *Owner) {
3326 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", 3326, __extension__ __PRETTY_FUNCTION__
))
;
3327 Expr *Alignment = nullptr;
3328 Expr *Allocator = nullptr;
3329 if (Clauses.empty()) {
3330 // OpenMP 5.0, 2.11.3 allocate Directive, Restrictions.
3331 // allocate directives that appear in a target region must specify an
3332 // allocator clause unless a requires directive with the dynamic_allocators
3333 // clause is present in the same compilation unit.
3334 if (LangOpts.OpenMPIsDevice &&
3335 !DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
3336 targetDiag(Loc, diag::err_expected_allocator_clause);
3337 } else {
3338 for (const OMPClause *C : Clauses)
3339 if (const auto *AC = dyn_cast<OMPAllocatorClause>(C))
3340 Allocator = AC->getAllocator();
3341 else if (const auto *AC = dyn_cast<OMPAlignClause>(C))
3342 Alignment = AC->getAlignment();
3343 else
3344 llvm_unreachable("Unexpected clause on allocate directive")::llvm::llvm_unreachable_internal("Unexpected clause on allocate directive"
, "clang/lib/Sema/SemaOpenMP.cpp", 3344)
;
3345 }
3346 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
3347 getAllocatorKind(*this, DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
, Allocator);
3348 SmallVector<Expr *, 8> Vars;
3349 for (Expr *RefExpr : VarList) {
3350 auto *DE = cast<DeclRefExpr>(RefExpr);
3351 auto *VD = cast<VarDecl>(DE->getDecl());
3352
3353 // Check if this is a TLS variable or global register.
3354 if (VD->getTLSKind() != VarDecl::TLS_None ||
3355 VD->hasAttr<OMPThreadPrivateDeclAttr>() ||
3356 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3357 !VD->isLocalVarDecl()))
3358 continue;
3359
3360 // If the used several times in the allocate directive, the same allocator
3361 // must be used.
3362 if (checkPreviousOMPAllocateAttribute(*this, DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
, RefExpr, VD,
3363 AllocatorKind, Allocator))
3364 continue;
3365
3366 // OpenMP, 2.11.3 allocate Directive, Restrictions, C / C++
3367 // If a list item has a static storage type, the allocator expression in the
3368 // allocator clause must be a constant expression that evaluates to one of
3369 // the predefined memory allocator values.
3370 if (Allocator && VD->hasGlobalStorage()) {
3371 if (AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc) {
3372 Diag(Allocator->getExprLoc(),
3373 diag::err_omp_expected_predefined_allocator)
3374 << Allocator->getSourceRange();
3375 bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
3376 VarDecl::DeclarationOnly;
3377 Diag(VD->getLocation(),
3378 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3379 << VD;
3380 continue;
3381 }
3382 }
3383
3384 Vars.push_back(RefExpr);
3385 applyOMPAllocateAttribute(*this, VD, AllocatorKind, Allocator, Alignment,
3386 DE->getSourceRange());
3387 }
3388 if (Vars.empty())
3389 return nullptr;
3390 if (!Owner)
3391 Owner = getCurLexicalContext();
3392 auto *D = OMPAllocateDecl::Create(Context, Owner, Loc, Vars, Clauses);
3393 D->setAccess(AS_public);
3394 Owner->addDecl(D);
3395 return DeclGroupPtrTy::make(DeclGroupRef(D));
3396}
3397
3398Sema::DeclGroupPtrTy
3399Sema::ActOnOpenMPRequiresDirective(SourceLocation Loc,
3400 ArrayRef<OMPClause *> ClauseList) {
3401 OMPRequiresDecl *D = nullptr;
3402 if (!CurContext->isFileContext()) {
3403 Diag(Loc, diag::err_omp_invalid_scope) << "requires";
3404 } else {
3405 D = CheckOMPRequiresDecl(Loc, ClauseList);
3406 if (D) {
3407 CurContext->addDecl(D);
3408 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->addRequiresDecl(D);
3409 }
3410 }
3411 return DeclGroupPtrTy::make(DeclGroupRef(D));
3412}
3413
3414void Sema::ActOnOpenMPAssumesDirective(SourceLocation Loc,
3415 OpenMPDirectiveKind DKind,
3416 ArrayRef<std::string> Assumptions,
3417 bool SkippedClauses) {
3418 if (!SkippedClauses && Assumptions.empty())
3419 Diag(Loc, diag::err_omp_no_clause_for_directive)
3420 << llvm::omp::getAllAssumeClauseOptions()
3421 << llvm::omp::getOpenMPDirectiveName(DKind);
3422
3423 auto *AA = AssumptionAttr::Create(Context, llvm::join(Assumptions, ","), Loc);
3424 if (DKind == llvm::omp::Directive::OMPD_begin_assumes) {
3425 OMPAssumeScoped.push_back(AA);
3426 return;
3427 }
3428
3429 // Global assumes without assumption clauses are ignored.
3430 if (Assumptions.empty())
3431 return;
3432
3433 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", 3434, __extension__ __PRETTY_FUNCTION__
))
3434 "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", 3434, __extension__ __PRETTY_FUNCTION__
))
;
3435 OMPAssumeGlobal.push_back(AA);
3436
3437 // The OMPAssumeGlobal scope above will take care of new declarations but
3438 // we also want to apply the assumption to existing ones, e.g., to
3439 // declarations in included headers. To this end, we traverse all existing
3440 // declaration contexts and annotate function declarations here.
3441 SmallVector<DeclContext *, 8> DeclContexts;
3442 auto *Ctx = CurContext;
3443 while (Ctx->getLexicalParent())
3444 Ctx = Ctx->getLexicalParent();
3445 DeclContexts.push_back(Ctx);
3446 while (!DeclContexts.empty()) {
3447 DeclContext *DC = DeclContexts.pop_back_val();
3448 for (auto *SubDC : DC->decls()) {
3449 if (SubDC->isInvalidDecl())
3450 continue;
3451 if (auto *CTD = dyn_cast<ClassTemplateDecl>(SubDC)) {
3452 DeclContexts.push_back(CTD->getTemplatedDecl());
3453 llvm::append_range(DeclContexts, CTD->specializations());
3454 continue;
3455 }
3456 if (auto *DC = dyn_cast<DeclContext>(SubDC))
3457 DeclContexts.push_back(DC);
3458 if (auto *F = dyn_cast<FunctionDecl>(SubDC)) {
3459 F->addAttr(AA);
3460 continue;
3461 }
3462 }
3463 }
3464}
3465
3466void Sema::ActOnOpenMPEndAssumesDirective() {
3467 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", 3467, __extension__ __PRETTY_FUNCTION__
))
;
3468 OMPAssumeScoped.pop_back();
3469}
3470
3471OMPRequiresDecl *Sema::CheckOMPRequiresDecl(SourceLocation Loc,
3472 ArrayRef<OMPClause *> ClauseList) {
3473 /// For target specific clauses, the requires directive cannot be
3474 /// specified after the handling of any of the target regions in the
3475 /// current compilation unit.
3476 ArrayRef<SourceLocation> TargetLocations =
3477 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getEncounteredTargetLocs();
3478 SourceLocation AtomicLoc = DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getAtomicDirectiveLoc();
3479 if (!TargetLocations.empty() || !AtomicLoc.isInvalid()) {
3480 for (const OMPClause *CNew : ClauseList) {
3481 // Check if any of the requires clauses affect target regions.
3482 if (isa<OMPUnifiedSharedMemoryClause>(CNew) ||
3483 isa<OMPUnifiedAddressClause>(CNew) ||
3484 isa<OMPReverseOffloadClause>(CNew) ||
3485 isa<OMPDynamicAllocatorsClause>(CNew)) {
3486 Diag(Loc, diag::err_omp_directive_before_requires)
3487 << "target" << getOpenMPClauseName(CNew->getClauseKind());
3488 for (SourceLocation TargetLoc : TargetLocations) {
3489 Diag(TargetLoc, diag::note_omp_requires_encountered_directive)
3490 << "target";
3491 }
3492 } else if (!AtomicLoc.isInvalid() &&
3493 isa<OMPAtomicDefaultMemOrderClause>(CNew)) {
3494 Diag(Loc, diag::err_omp_directive_before_requires)
3495 << "atomic" << getOpenMPClauseName(CNew->getClauseKind());
3496 Diag(AtomicLoc, diag::note_omp_requires_encountered_directive)
3497 << "atomic";
3498 }
3499 }
3500 }
3501
3502 if (!DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->hasDuplicateRequiresClause(ClauseList))
3503 return OMPRequiresDecl::Create(Context, getCurLexicalContext(), Loc,
3504 ClauseList);
3505 return nullptr;
3506}
3507
3508static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
3509 const ValueDecl *D,
3510 const DSAStackTy::DSAVarData &DVar,
3511 bool IsLoopIterVar) {
3512 if (DVar.RefExpr) {
3513 SemaRef.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa)
3514 << getOpenMPClauseName(DVar.CKind);
3515 return;
3516 }
3517 enum {
3518 PDSA_StaticMemberShared,
3519 PDSA_StaticLocalVarShared,
3520 PDSA_LoopIterVarPrivate,
3521 PDSA_LoopIterVarLinear,
3522 PDSA_LoopIterVarLastprivate,
3523 PDSA_ConstVarShared,
3524 PDSA_GlobalVarShared,
3525 PDSA_TaskVarFirstprivate,
3526 PDSA_LocalVarPrivate,
3527 PDSA_Implicit
3528 } Reason = PDSA_Implicit;
3529 bool ReportHint = false;
3530 auto ReportLoc = D->getLocation();
3531 auto *VD = dyn_cast<VarDecl>(D);
3532 if (IsLoopIterVar) {
3533 if (DVar.CKind == OMPC_private)
3534 Reason = PDSA_LoopIterVarPrivate;
3535 else if (DVar.CKind == OMPC_lastprivate)
3536 Reason = PDSA_LoopIterVarLastprivate;
3537 else
3538 Reason = PDSA_LoopIterVarLinear;
3539 } else if (isOpenMPTaskingDirective(DVar.DKind) &&
3540 DVar.CKind == OMPC_firstprivate) {
3541 Reason = PDSA_TaskVarFirstprivate;
3542 ReportLoc = DVar.ImplicitDSALoc;
3543 } else if (VD && VD->isStaticLocal())
3544 Reason = PDSA_StaticLocalVarShared;
3545 else if (VD && VD->isStaticDataMember())
3546 Reason = PDSA_StaticMemberShared;
3547 else if (VD && VD->isFileVarDecl())
3548 Reason = PDSA_GlobalVarShared;
3549 else if (D->getType().isConstant(SemaRef.getASTContext()))
3550 Reason = PDSA_ConstVarShared;
3551 else if (VD && VD->isLocalVarDecl() && DVar.CKind == OMPC_private) {
3552 ReportHint = true;
3553 Reason = PDSA_LocalVarPrivate;
3554 }
3555 if (Reason != PDSA_Implicit) {
3556 SemaRef.Diag(ReportLoc, diag::note_omp_predetermined_dsa)
3557 << Reason << ReportHint
3558 << getOpenMPDirectiveName(Stack->getCurrentDirective());
3559 } else if (DVar.ImplicitDSALoc.isValid()) {
3560 SemaRef.Diag(DVar.ImplicitDSALoc, diag::note_omp_implicit_dsa)
3561 << getOpenMPClauseName(DVar.CKind);
3562 }
3563}
3564
3565static OpenMPMapClauseKind
3566getMapClauseKindFromModifier(OpenMPDefaultmapClauseModifier M,
3567 bool IsAggregateOrDeclareTarget) {
3568 OpenMPMapClauseKind Kind = OMPC_MAP_unknown;
3569 switch (M) {
3570 case OMPC_DEFAULTMAP_MODIFIER_alloc:
3571 Kind = OMPC_MAP_alloc;
3572 break;
3573 case OMPC_DEFAULTMAP_MODIFIER_to:
3574 Kind = OMPC_MAP_to;
3575 break;
3576 case OMPC_DEFAULTMAP_MODIFIER_from:
3577 Kind = OMPC_MAP_from;
3578 break;
3579 case OMPC_DEFAULTMAP_MODIFIER_tofrom:
3580 Kind = OMPC_MAP_tofrom;
3581 break;
3582 case OMPC_DEFAULTMAP_MODIFIER_present:
3583 // OpenMP 5.1 [2.21.7.3] defaultmap clause, Description]
3584 // If implicit-behavior is present, each variable referenced in the
3585 // construct in the category specified by variable-category is treated as if
3586 // it had been listed in a map clause with the map-type of alloc and
3587 // map-type-modifier of present.
3588 Kind = OMPC_MAP_alloc;
3589 break;
3590 case OMPC_DEFAULTMAP_MODIFIER_firstprivate:
3591 case OMPC_DEFAULTMAP_MODIFIER_last:
3592 llvm_unreachable("Unexpected defaultmap implicit behavior")::llvm::llvm_unreachable_internal("Unexpected defaultmap implicit behavior"
, "clang/lib/Sema/SemaOpenMP.cpp", 3592)
;
3593 case OMPC_DEFAULTMAP_MODIFIER_none:
3594 case OMPC_DEFAULTMAP_MODIFIER_default:
3595 case OMPC_DEFAULTMAP_MODIFIER_unknown:
3596 // IsAggregateOrDeclareTarget could be true if:
3597 // 1. the implicit behavior for aggregate is tofrom
3598 // 2. it's a declare target link
3599 if (IsAggregateOrDeclareTarget) {
3600 Kind = OMPC_MAP_tofrom;
3601 break;
3602 }
3603 llvm_unreachable("Unexpected defaultmap implicit behavior")::llvm::llvm_unreachable_internal("Unexpected defaultmap implicit behavior"
, "clang/lib/Sema/SemaOpenMP.cpp", 3603)
;
3604 }
3605 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", 3605, __extension__ __PRETTY_FUNCTION__
))
;
3606 return Kind;
3607}
3608
3609namespace {
3610class DSAAttrChecker final : public StmtVisitor<DSAAttrChecker, void> {
3611 DSAStackTy *Stack;
3612 Sema &SemaRef;
3613 bool ErrorFound = false;
3614 bool TryCaptureCXXThisMembers = false;
3615 CapturedStmt *CS = nullptr;
3616 const static unsigned DefaultmapKindNum = OMPC_DEFAULTMAP_pointer + 1;
3617 llvm::SmallVector<Expr *, 4> ImplicitFirstprivate;
3618 llvm::SmallVector<Expr *, 4> ImplicitPrivate;
3619 llvm::SmallVector<Expr *, 4> ImplicitMap[DefaultmapKindNum][OMPC_MAP_delete];
3620 llvm::SmallVector<OpenMPMapModifierKind, NumberOfOMPMapClauseModifiers>
3621 ImplicitMapModifier[DefaultmapKindNum];
3622 Sema::VarsWithInheritedDSAType VarsWithInheritedDSA;
3623 llvm::SmallDenseSet<const ValueDecl *, 4> ImplicitDeclarations;
3624
3625 void VisitSubCaptures(OMPExecutableDirective *S) {
3626 // Check implicitly captured variables.
3627 if (!S->hasAssociatedStmt() || !S->getAssociatedStmt())
3628 return;
3629 if (S->getDirectiveKind() == OMPD_atomic ||
3630 S->getDirectiveKind() == OMPD_critical ||
3631 S->getDirectiveKind() == OMPD_section ||
3632 S->getDirectiveKind() == OMPD_master ||
3633 S->getDirectiveKind() == OMPD_masked ||
3634 isOpenMPLoopTransformationDirective(S->getDirectiveKind())) {
3635 Visit(S->getAssociatedStmt());
3636 return;
3637 }
3638 visitSubCaptures(S->getInnermostCapturedStmt());
3639 // Try to capture inner this->member references to generate correct mappings
3640 // and diagnostics.
3641 if (TryCaptureCXXThisMembers ||
3642 (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) &&
3643 llvm::any_of(S->getInnermostCapturedStmt()->captures(),
3644 [](const CapturedStmt::Capture &C) {
3645 return C.capturesThis();
3646 }))) {
3647 bool SavedTryCaptureCXXThisMembers = TryCaptureCXXThisMembers;
3648 TryCaptureCXXThisMembers = true;
3649 Visit(S->getInnermostCapturedStmt()->getCapturedStmt());
3650 TryCaptureCXXThisMembers = SavedTryCaptureCXXThisMembers;
3651 }
3652 // In tasks firstprivates are not captured anymore, need to analyze them
3653 // explicitly.
3654 if (isOpenMPTaskingDirective(S->getDirectiveKind()) &&
3655 !isOpenMPTaskLoopDirective(S->getDirectiveKind())) {
3656 for (OMPClause *C : S->clauses())
3657 if (auto *FC = dyn_cast<OMPFirstprivateClause>(C)) {
3658 for (Expr *Ref : FC->varlists())
3659 Visit(Ref);
3660 }
3661 }
3662 }
3663
3664public:
3665 void VisitDeclRefExpr(DeclRefExpr *E) {
3666 if (TryCaptureCXXThisMembers || E->isTypeDependent() ||
3667 E->isValueDependent() || E->containsUnexpandedParameterPack() ||
3668 E->isInstantiationDependent())
3669 return;
3670 if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
3671 // Check the datasharing rules for the expressions in the clauses.
3672 if (!CS || (isa<OMPCapturedExprDecl>(VD) && !CS->capturesVariable(VD) &&
3673 !Stack->getTopDSA(VD, /*FromParent=*/false).RefExpr &&
3674 !Stack->isImplicitDefaultFirstprivateFD(VD))) {
3675 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(VD))
3676 if (!CED->hasAttr<OMPCaptureNoInitAttr>()) {
3677 Visit(CED->getInit());
3678 return;
3679 }
3680 } else if (VD->isImplicit() || isa<OMPCapturedExprDecl>(VD))
3681 // Do not analyze internal variables and do not enclose them into
3682 // implicit clauses.
3683 if (!Stack->isImplicitDefaultFirstprivateFD(VD))
3684 return;
3685 VD = VD->getCanonicalDecl();
3686 // Skip internally declared variables.
3687 if (VD->hasLocalStorage() && CS && !CS->capturesVariable(VD) &&
3688 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
3689 !Stack->isImplicitTaskFirstprivate(VD))
3690 return;
3691 // Skip allocators in uses_allocators clauses.
3692 if (Stack->isUsesAllocatorsDecl(VD))
3693 return;
3694
3695 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false);
3696 // Check if the variable has explicit DSA set and stop analysis if it so.
3697 if (DVar.RefExpr || !ImplicitDeclarations.insert(VD).second)
3698 return;
3699
3700 // Skip internally declared static variables.
3701 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
3702 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
3703 if (VD->hasGlobalStorage() && CS && !CS->capturesVariable(VD) &&
3704 (Stack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
3705 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) &&
3706 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
3707 !Stack->isImplicitTaskFirstprivate(VD))
3708 return;
3709
3710 SourceLocation ELoc = E->getExprLoc();
3711 OpenMPDirectiveKind DKind = Stack->getCurrentDirective();
3712 // The default(none) clause requires that each variable that is referenced
3713 // in the construct, and does not have a predetermined data-sharing
3714 // attribute, must have its data-sharing attribute explicitly determined
3715 // by being listed in a data-sharing attribute clause.
3716 if (DVar.CKind == OMPC_unknown &&
3717 (Stack->getDefaultDSA() == DSA_none ||
3718 Stack->getDefaultDSA() == DSA_private ||
3719 Stack->getDefaultDSA() == DSA_firstprivate) &&
3720 isImplicitOrExplicitTaskingRegion(DKind) &&
3721 VarsWithInheritedDSA.count(VD) == 0) {
3722 bool InheritedDSA = Stack->getDefaultDSA() == DSA_none;
3723 if (!InheritedDSA && (Stack->getDefaultDSA() == DSA_firstprivate ||
3724 Stack->getDefaultDSA() == DSA_private)) {
3725 DSAStackTy::DSAVarData DVar =
3726 Stack->getImplicitDSA(VD, /*FromParent=*/false);
3727 InheritedDSA = DVar.CKind == OMPC_unknown;
3728 }
3729 if (InheritedDSA)
3730 VarsWithInheritedDSA[VD] = E;
3731 if (Stack->getDefaultDSA() == DSA_none)
3732 return;
3733 }
3734
3735 // OpenMP 5.0 [2.19.7.2, defaultmap clause, Description]
3736 // If implicit-behavior is none, each variable referenced in the
3737 // construct that does not have a predetermined data-sharing attribute
3738 // and does not appear in a to or link clause on a declare target
3739 // directive must be listed in a data-mapping attribute clause, a
3740 // data-sharing attribute clause (including a data-sharing attribute
3741 // clause on a combined construct where target. is one of the
3742 // constituent constructs), or an is_device_ptr clause.
3743 OpenMPDefaultmapClauseKind ClauseKind =
3744 getVariableCategoryFromDecl(SemaRef.getLangOpts(), VD);
3745 if (SemaRef.getLangOpts().OpenMP >= 50) {
3746 bool IsModifierNone = Stack->getDefaultmapModifier(ClauseKind) ==
3747 OMPC_DEFAULTMAP_MODIFIER_none;
3748 if (DVar.CKind == OMPC_unknown && IsModifierNone &&
3749 VarsWithInheritedDSA.count(VD) == 0 && !Res) {
3750 // Only check for data-mapping attribute and is_device_ptr here
3751 // since we have already make sure that the declaration does not
3752 // have a data-sharing attribute above
3753 if (!Stack->checkMappableExprComponentListsForDecl(
3754 VD, /*CurrentRegionOnly=*/true,
3755 [VD](OMPClauseMappableExprCommon::MappableExprComponentListRef
3756 MapExprComponents,
3757 OpenMPClauseKind) {
3758 auto MI = MapExprComponents.rbegin();
3759 auto ME = MapExprComponents.rend();
3760 return MI != ME && MI->getAssociatedDeclaration() == VD;
3761 })) {
3762 VarsWithInheritedDSA[VD] = E;
3763 return;
3764 }
3765 }
3766 }
3767 if (SemaRef.getLangOpts().OpenMP > 50) {
3768 bool IsModifierPresent = Stack->getDefaultmapModifier(ClauseKind) ==
3769 OMPC_DEFAULTMAP_MODIFIER_present;
3770 if (IsModifierPresent) {
3771 if (!llvm::is_contained(ImplicitMapModifier[ClauseKind],
3772 OMPC_MAP_MODIFIER_present)) {
3773 ImplicitMapModifier[ClauseKind].push_back(
3774 OMPC_MAP_MODIFIER_present);
3775 }
3776 }
3777 }
3778
3779 if (isOpenMPTargetExecutionDirective(DKind) &&
3780 !Stack->isLoopControlVariable(VD).first) {
3781 if (!Stack->checkMappableExprComponentListsForDecl(
3782 VD, /*CurrentRegionOnly=*/true,
3783 [this](OMPClauseMappableExprCommon::MappableExprComponentListRef
3784 StackComponents,
3785 OpenMPClauseKind) {
3786 if (SemaRef.LangOpts.OpenMP >= 50)
3787 return !StackComponents.empty();
3788 // Variable is used if it has been marked as an array, array
3789 // section, array shaping or the variable iself.
3790 return StackComponents.size() == 1 ||
3791 llvm::all_of(
3792 llvm::drop_begin(llvm::reverse(StackComponents)),
3793 [](const OMPClauseMappableExprCommon::
3794 MappableComponent &MC) {
3795 return MC.getAssociatedDeclaration() ==
3796 nullptr &&
3797 (isa<OMPArraySectionExpr>(
3798 MC.getAssociatedExpression()) ||
3799 isa<OMPArrayShapingExpr>(
3800 MC.getAssociatedExpression()) ||
3801 isa<ArraySubscriptExpr>(
3802 MC.getAssociatedExpression()));
3803 });
3804 })) {
3805 bool IsFirstprivate = false;
3806 // By default lambdas are captured as firstprivates.
3807 if (const auto *RD =
3808 VD->getType().getNonReferenceType()->getAsCXXRecordDecl())
3809 IsFirstprivate = RD->isLambda();
3810 IsFirstprivate =
3811 IsFirstprivate || (Stack->mustBeFirstprivate(ClauseKind) && !Res);
3812 if (IsFirstprivate) {
3813 ImplicitFirstprivate.emplace_back(E);
3814 } else {
3815 OpenMPDefaultmapClauseModifier M =
3816 Stack->getDefaultmapModifier(ClauseKind);
3817 OpenMPMapClauseKind Kind = getMapClauseKindFromModifier(
3818 M, ClauseKind == OMPC_DEFAULTMAP_aggregate || Res);
3819 ImplicitMap[ClauseKind][Kind].emplace_back(E);
3820 }
3821 return;
3822 }
3823 }
3824
3825 // OpenMP [2.9.3.6, Restrictions, p.2]
3826 // A list item that appears in a reduction clause of the innermost
3827 // enclosing worksharing or parallel construct may not be accessed in an
3828 // explicit task.
3829 DVar = Stack->hasInnermostDSA(
3830 VD,
3831 [](OpenMPClauseKind C, bool AppliedToPointee) {
3832 return C == OMPC_reduction && !AppliedToPointee;
3833 },
3834 [](OpenMPDirectiveKind K) {
3835 return isOpenMPParallelDirective(K) ||
3836 isOpenMPWorksharingDirective(K) || isOpenMPTeamsDirective(K);
3837 },
3838 /*FromParent=*/true);
3839 if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
3840 ErrorFound = true;
3841 SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
3842 reportOriginalDsa(SemaRef, Stack, VD, DVar);
3843 return;
3844 }
3845
3846 // Define implicit data-sharing attributes for task.
3847 DVar = Stack->getImplicitDSA(VD, /*FromParent=*/false);
3848 if (((isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared) ||
3849 (((Stack->getDefaultDSA() == DSA_firstprivate &&
3850 DVar.CKind == OMPC_firstprivate) ||
3851 (Stack->getDefaultDSA() == DSA_private &&
3852 DVar.CKind == OMPC_private)) &&
3853 !DVar.RefExpr)) &&
3854 !Stack->isLoopControlVariable(VD).first) {
3855 if (Stack->getDefaultDSA() == DSA_private)
3856 ImplicitPrivate.push_back(E);
3857 else
3858 ImplicitFirstprivate.push_back(E);
3859 return;
3860 }
3861
3862 // Store implicitly used globals with declare target link for parent
3863 // target.
3864 if (!isOpenMPTargetExecutionDirective(DKind) && Res &&
3865 *Res == OMPDeclareTargetDeclAttr::MT_Link) {
3866 Stack->addToParentTargetRegionLinkGlobals(E);
3867 return;
3868 }
3869 }
3870 }
3871 void VisitMemberExpr(MemberExpr *E) {
3872 if (E->isTypeDependent() || E->isValueDependent() ||
3873 E->containsUnexpandedParameterPack() || E->isInstantiationDependent())
3874 return;
3875 auto *FD = dyn_cast<FieldDecl>(E->getMemberDecl());
3876 OpenMPDirectiveKind DKind = Stack->getCurrentDirective();
3877 if (auto *TE = dyn_cast<CXXThisExpr>(E->getBase()->IgnoreParenCasts())) {
3878 if (!FD)
3879 return;
3880 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(FD, /*FromParent=*/false);
3881 // Check if the variable has explicit DSA set and stop analysis if it
3882 // so.
3883 if (DVar.RefExpr || !ImplicitDeclarations.insert(FD).second)
3884 return;
3885
3886 if (isOpenMPTargetExecutionDirective(DKind) &&
3887 !Stack->isLoopControlVariable(FD).first &&
3888 !Stack->checkMappableExprComponentListsForDecl(
3889 FD, /*CurrentRegionOnly=*/true,
3890 [](OMPClauseMappableExprCommon::MappableExprComponentListRef
3891 StackComponents,
3892 OpenMPClauseKind) {
3893 return isa<CXXThisExpr>(
3894 cast<MemberExpr>(
3895 StackComponents.back().getAssociatedExpression())
3896 ->getBase()
3897 ->IgnoreParens());
3898 })) {
3899 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
3900 // A bit-field cannot appear in a map clause.
3901 //
3902 if (FD->isBitField())
3903 return;
3904
3905 // Check to see if the member expression is referencing a class that
3906 // has already been explicitly mapped
3907 if (Stack->isClassPreviouslyMapped(TE->getType()))
3908 return;
3909
3910 OpenMPDefaultmapClauseModifier Modifier =
3911 Stack->getDefaultmapModifier(OMPC_DEFAULTMAP_aggregate);
3912 OpenMPDefaultmapClauseKind ClauseKind =
3913 getVariableCategoryFromDecl(SemaRef.getLangOpts(), FD);
3914 OpenMPMapClauseKind Kind = getMapClauseKindFromModifier(
3915 Modifier, /*IsAggregateOrDeclareTarget*/ true);
3916 ImplicitMap[ClauseKind][Kind].emplace_back(E);
3917 return;
3918 }
3919
3920 SourceLocation ELoc = E->getExprLoc();
3921 // OpenMP [2.9.3.6, Restrictions, p.2]
3922 // A list item that appears in a reduction clause of the innermost
3923 // enclosing worksharing or parallel construct may not be accessed in
3924 // an explicit task.
3925 DVar = Stack->hasInnermostDSA(
3926 FD,
3927 [](OpenMPClauseKind C, bool AppliedToPointee) {
3928 return C == OMPC_reduction && !AppliedToPointee;
3929 },
3930 [](OpenMPDirectiveKind K) {
3931 return isOpenMPParallelDirective(K) ||
3932 isOpenMPWorksharingDirective(K) || isOpenMPTeamsDirective(K);
3933 },
3934 /*FromParent=*/true);
3935 if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
3936 ErrorFound = true;
3937 SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
3938 reportOriginalDsa(SemaRef, Stack, FD, DVar);
3939 return;
3940 }
3941
3942 // Define implicit data-sharing attributes for task.
3943 DVar = Stack->getImplicitDSA(FD, /*FromParent=*/false);
3944 if (isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared &&
3945 !Stack->isLoopControlVariable(FD).first) {
3946 // Check if there is a captured expression for the current field in the
3947 // region. Do not mark it as firstprivate unless there is no captured
3948 // expression.
3949 // TODO: try to make it firstprivate.
3950 if (DVar.CKind != OMPC_unknown)
3951 ImplicitFirstprivate.push_back(E);
3952 }
3953 return;
3954 }
3955 if (isOpenMPTargetExecutionDirective(DKind)) {
3956 OMPClauseMappableExprCommon::MappableExprComponentList CurComponents;
3957 if (!checkMapClauseExpressionBase(SemaRef, E, CurComponents, OMPC_map,
3958 Stack->getCurrentDirective(),
3959 /*NoDiagnose=*/true))
3960 return;
3961 const auto *VD = cast<ValueDecl>(
3962 CurComponents.back().getAssociatedDeclaration()->getCanonicalDecl());
3963 if (!Stack->checkMappableExprComponentListsForDecl(
3964 VD, /*CurrentRegionOnly=*/true,
3965 [&CurComponents](
3966 OMPClauseMappableExprCommon::MappableExprComponentListRef
3967 StackComponents,
3968 OpenMPClauseKind) {
3969 auto CCI = CurComponents.rbegin();
3970 auto CCE = CurComponents.rend();
3971 for (const auto &SC : llvm::reverse(StackComponents)) {
3972 // Do both expressions have the same kind?
3973 if (CCI->getAssociatedExpression()->getStmtClass() !=
3974 SC.getAssociatedExpression()->getStmtClass())
3975 if (!((isa<OMPArraySectionExpr>(
3976 SC.getAssociatedExpression()) ||
3977 isa<OMPArrayShapingExpr>(
3978 SC.getAssociatedExpression())) &&
3979 isa<ArraySubscriptExpr>(
3980 CCI->getAssociatedExpression())))
3981 return false;
3982
3983 const Decl *CCD = CCI->getAssociatedDeclaration();
3984 const Decl *SCD = SC.getAssociatedDeclaration();
3985 CCD = CCD ? CCD->getCanonicalDecl() : nullptr;
3986 SCD = SCD ? SCD->getCanonicalDecl() : nullptr;
3987 if (SCD != CCD)
3988 return false;
3989 std::advance(CCI, 1);
3990 if (CCI == CCE)
3991 break;
3992 }
3993 return true;
3994 })) {
3995 Visit(E->getBase());
3996 }
3997 } else if (!TryCaptureCXXThisMembers) {
3998 Visit(E->getBase());
3999 }
4000 }
4001 void VisitOMPExecutableDirective(OMPExecutableDirective *S) {
4002 for (OMPClause *C : S->clauses()) {
4003 // Skip analysis of arguments of private clauses for task|target
4004 // directives.
4005 if (isa_and_nonnull<OMPPrivateClause>(C))
4006 continue;
4007 // Skip analysis of arguments of implicitly defined firstprivate clause
4008 // for task|target directives.
4009 // Skip analysis of arguments of implicitly defined map clause for target
4010 // directives.
4011 if (C && !((isa<OMPFirstprivateClause>(C) || isa<OMPMapClause>(C)) &&
4012 C->isImplicit() &&
4013 !isOpenMPTaskingDirective(Stack->getCurrentDirective()))) {
4014 for (Stmt *CC : C->children()) {
4015 if (CC)
4016 Visit(CC);
4017 }
4018 }
4019 }
4020 // Check implicitly captured variables.
4021 VisitSubCaptures(S);
4022 }
4023
4024 void VisitOMPLoopTransformationDirective(OMPLoopTransformationDirective *S) {
4025 // Loop transformation directives do not introduce data sharing
4026 VisitStmt(S);
4027 }
4028
4029 void VisitCallExpr(CallExpr *S) {
4030 for (Stmt *C : S->arguments()) {
4031 if (C) {
4032 // Check implicitly captured variables in the task-based directives to
4033 // check if they must be firstprivatized.
4034 Visit(C);
4035 }
4036 }
4037 if (Expr *Callee = S->getCallee())
4038 if (auto *CE = dyn_cast<MemberExpr>(Callee->IgnoreParenImpCasts()))
4039 Visit(CE->getBase());
4040 }
4041 void VisitStmt(Stmt *S) {
4042 for (Stmt *C : S->children()) {
4043 if (C) {
4044 // Check implicitly captured variables in the task-based directives to
4045 // check if they must be firstprivatized.
4046 Visit(C);
4047 }
4048 }
4049 }
4050
4051 void visitSubCaptures(CapturedStmt *S) {
4052 for (const CapturedStmt::Capture &Cap : S->captures()) {
4053 if (!Cap.capturesVariable() && !Cap.capturesVariableByCopy())
4054 continue;
4055 VarDecl *VD = Cap.getCapturedVar();
4056 // Do not try to map the variable if it or its sub-component was mapped
4057 // already.
4058 if (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) &&
4059 Stack->checkMappableExprComponentListsForDecl(
4060 VD, /*CurrentRegionOnly=*/true,
4061 [](OMPClauseMappableExprCommon::MappableExprComponentListRef,
4062 OpenMPClauseKind) { return true; }))
4063 continue;
4064 DeclRefExpr *DRE = buildDeclRefExpr(
4065 SemaRef, VD, VD->getType().getNonLValueExprType(SemaRef.Context),
4066 Cap.getLocation(), /*RefersToCapture=*/true);
4067 Visit(DRE);
4068 }
4069 }
4070 bool isErrorFound() const { return ErrorFound; }
4071 ArrayRef<Expr *> getImplicitFirstprivate() const {
4072 return ImplicitFirstprivate;
4073 }
4074 ArrayRef<Expr *> getImplicitPrivate() const { return ImplicitPrivate; }
4075 ArrayRef<Expr *> getImplicitMap(OpenMPDefaultmapClauseKind DK,
4076 OpenMPMapClauseKind MK) const {
4077 return ImplicitMap[DK][MK];
4078 }
4079 ArrayRef<OpenMPMapModifierKind>
4080 getImplicitMapModifier(OpenMPDefaultmapClauseKind Kind) const {
4081 return ImplicitMapModifier[Kind];
4082 }
4083 const Sema::VarsWithInheritedDSAType &getVarsWithInheritedDSA() const {
4084 return VarsWithInheritedDSA;
4085 }
4086
4087 DSAAttrChecker(DSAStackTy *S, Sema &SemaRef, CapturedStmt *CS)
4088 : Stack(S), SemaRef(SemaRef), ErrorFound(false), CS(CS) {
4089 // Process declare target link variables for the target directives.
4090 if (isOpenMPTargetExecutionDirective(S->getCurrentDirective())) {
4091 for (DeclRefExpr *E : Stack->getLinkGlobals())
4092 Visit(E);
4093 }
4094 }
4095};
4096} // namespace
4097
4098static void handleDeclareVariantConstructTrait(DSAStackTy *Stack,
4099 OpenMPDirectiveKind DKind,
4100 bool ScopeEntry) {
4101 SmallVector<llvm::omp::TraitProperty, 8> Traits;
4102 if (isOpenMPTargetExecutionDirective(DKind))
4103 Traits.emplace_back(llvm::omp::TraitProperty::construct_target_target);
4104 if (isOpenMPTeamsDirective(DKind))
4105 Traits.emplace_back(llvm::omp::TraitProperty::construct_teams_teams);
4106 if (isOpenMPParallelDirective(DKind))
4107 Traits.emplace_back(llvm::omp::TraitProperty::construct_parallel_parallel);
4108 if (isOpenMPWorksharingDirective(DKind))
4109 Traits.emplace_back(llvm::omp::TraitProperty::construct_for_for);
4110 if (isOpenMPSimdDirective(DKind))
4111 Traits.emplace_back(llvm::omp::TraitProperty::construct_simd_simd);
4112 Stack->handleConstructTrait(Traits, ScopeEntry);
4113}
4114
4115void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
4116 switch (DKind) {
4117 case OMPD_parallel:
4118 case OMPD_parallel_for:
4119 case OMPD_parallel_for_simd:
4120 case OMPD_parallel_sections:
4121 case OMPD_parallel_master:
4122 case OMPD_parallel_masked:
4123 case OMPD_parallel_loop:
4124 case OMPD_teams:
4125 case OMPD_teams_distribute:
4126 case OMPD_teams_distribute_simd: {
4127 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4128 QualType KmpInt32PtrTy =
4129 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4130 Sema::CapturedParamNameType Params[] = {
4131 std::make_pair(".global_tid.", KmpInt32PtrTy),
4132 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4133 std::make_pair(StringRef(), QualType()) // __context with shared vars
4134 };
4135 ActOnCapturedRegionStart(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getConstructLoc(), CurScope, CR_OpenMP,
4136 Params);
4137 break;
4138 }
4139 case OMPD_target_teams:
4140 case OMPD_target_parallel:
4141 case OMPD_target_parallel_for:
4142 case OMPD_target_parallel_for_simd:
4143 case OMPD_target_teams_loop:
4144 case OMPD_target_parallel_loop:
4145 case OMPD_target_teams_distribute:
4146 case OMPD_target_teams_distribute_simd: {
4147 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4148 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4149 QualType KmpInt32PtrTy =
4150 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4151 QualType Args[] = {VoidPtrTy};
4152 FunctionProtoType::ExtProtoInfo EPI;
4153 EPI.Variadic = true;
4154 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4155 Sema::CapturedParamNameType Params[] = {
4156 std::make_pair(".global_tid.", KmpInt32Ty),
4157 std::make_pair(".part_id.", KmpInt32PtrTy),
4158 std::make_pair(".privates.", VoidPtrTy),
4159 std::make_pair(
4160 ".copy_fn.",
4161 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4162 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4163 std::make_pair(StringRef(), QualType()) // __context with shared vars
4164 };
4165 ActOnCapturedRegionStart(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getConstructLoc(), CurScope, CR_OpenMP,
4166 Params, /*OpenMPCaptureLevel=*/0);
4167 // Mark this captured region as inlined, because we don't use outlined
4168 // function directly.
4169 getCurCapturedRegion()->TheCapturedDecl->addAttr(
4170 AlwaysInlineAttr::CreateImplicit(
4171 Context, {}, AttributeCommonInfo::AS_Keyword,
4172 AlwaysInlineAttr::Keyword_forceinline));
4173 Sema::CapturedParamNameType ParamsTarget[] = {
4174 std::make_pair(StringRef(), QualType()) // __context with shared vars
4175 };
4176 // Start a captured region for 'target' with no implicit parameters.
4177 ActOnCapturedRegionStart(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getConstructLoc(), CurScope, CR_OpenMP,
4178 ParamsTarget, /*OpenMPCaptureLevel=*/1);
4179 Sema::CapturedParamNameType ParamsTeamsOrParallel[] = {
4180 std::make_pair(".global_tid.", KmpInt32PtrTy),
4181 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4182 std::make_pair(StringRef(), QualType()) // __context with shared vars
4183 };
4184 // Start a captured region for 'teams' or 'parallel'. Both regions have
4185 // the same implicit parameters.
4186 ActOnCapturedRegionStart(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getConstructLoc(), CurScope, CR_OpenMP,
4187 ParamsTeamsOrParallel, /*OpenMPCaptureLevel=*/2);
4188 break;
4189 }
4190 case OMPD_target:
4191 case OMPD_target_simd: {
4192 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4193 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4194 QualType KmpInt32PtrTy =
4195 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4196 QualType Args[] = {VoidPtrTy};
4197 FunctionProtoType::ExtProtoInfo EPI;
4198 EPI.Variadic = true;
4199 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4200 Sema::CapturedParamNameType Params[] = {
4201 std::make_pair(".global_tid.", KmpInt32Ty),
4202 std::make_pair(".part_id.", KmpInt32PtrTy),
4203 std::make_pair(".privates.", VoidPtrTy),
4204 std::make_pair(
4205 ".copy_fn.",
4206 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4207 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4208 std::make_pair(StringRef(), QualType()) // __context with shared vars
4209 };
4210 ActOnCapturedRegionStart(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getConstructLoc(), CurScope, CR_OpenMP,
4211 Params, /*OpenMPCaptureLevel=*/0);
4212 // Mark this captured region as inlined, because we don't use outlined
4213 // function directly.
4214 getCurCapturedRegion()->TheCapturedDecl->addAttr(
4215 AlwaysInlineAttr::CreateImplicit(
4216 Context, {}, AttributeCommonInfo::AS_Keyword,
4217 AlwaysInlineAttr::Keyword_forceinline));
4218 ActOnCapturedRegionStart(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getConstructLoc(), CurScope, CR_OpenMP,
4219 std::make_pair(StringRef(), QualType()),
4220 /*OpenMPCaptureLevel=*/1);
4221 break;
4222 }
4223 case OMPD_atomic:
4224 case OMPD_critical:
4225 case OMPD_section:
4226 case OMPD_master:
4227 case OMPD_masked:
4228 case OMPD_tile:
4229 case OMPD_unroll:
4230 break;
4231 case OMPD_loop:
4232 // TODO: 'loop' may require additional parameters depending on the binding.
4233 // Treat similar to OMPD_simd/OMPD_for for now.
4234 case OMPD_simd:
4235 case OMPD_for:
4236 case OMPD_for_simd:
4237 case OMPD_sections:
4238 case OMPD_single:
4239 case OMPD_taskgroup:
4240 case OMPD_distribute:
4241 case OMPD_distribute_simd:
4242 case OMPD_ordered:
4243 case OMPD_target_data:
4244 case OMPD_dispatch: {
4245 Sema::CapturedParamNameType Params[] = {
4246 std::make_pair(StringRef(), QualType()) // __context with shared vars
4247 };
4248 ActOnCapturedRegionStart(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getConstructLoc(), CurScope, CR_OpenMP,
4249 Params);
4250 break;
4251 }
4252 case OMPD_task: {
4253 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4254 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4255 QualType KmpInt32PtrTy =
4256 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4257 QualType Args[] = {VoidPtrTy};
4258 FunctionProtoType::ExtProtoInfo EPI;
4259 EPI.Variadic = true;
4260 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4261 Sema::CapturedParamNameType Params[] = {
4262 std::make_pair(".global_tid.", KmpInt32Ty),
4263 std::make_pair(".part_id.", KmpInt32PtrTy),
4264 std::make_pair(".privates.", VoidPtrTy),
4265 std::make_pair(
4266 ".copy_fn.",
4267 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4268 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4269 std::make_pair(StringRef(), QualType()) // __context with shared vars
4270 };
4271 ActOnCapturedRegionStart(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getConstructLoc(), CurScope, CR_OpenMP,
4272 Params);
4273 // Mark this captured region as inlined, because we don't use outlined
4274 // function directly.
4275 getCurCapturedRegion()->TheCapturedDecl->addAttr(
4276 AlwaysInlineAttr::CreateImplicit(
4277 Context, {}, AttributeCommonInfo::AS_Keyword,
4278 AlwaysInlineAttr::Keyword_forceinline));
4279 break;
4280 }
4281 case OMPD_taskloop:
4282 case OMPD_taskloop_simd:
4283 case OMPD_master_taskloop:
4284 case OMPD_masked_taskloop:
4285 case OMPD_masked_taskloop_simd:
4286 case OMPD_master_taskloop_simd: {
4287 QualType KmpInt32Ty =
4288 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1)
4289 .withConst();
4290 QualType KmpUInt64Ty =
4291 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0)
4292 .withConst();
4293 QualType KmpInt64Ty =
4294 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1)
4295 .withConst();
4296 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4297 QualType KmpInt32PtrTy =
4298 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4299 QualType Args[] = {VoidPtrTy};
4300 FunctionProtoType::ExtProtoInfo EPI;
4301 EPI.Variadic = true;
4302 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4303 Sema::CapturedParamNameType Params[] = {
4304 std::make_pair(".global_tid.", KmpInt32Ty),
4305 std::make_pair(".part_id.", KmpInt32PtrTy),
4306 std::make_pair(".privates.", VoidPtrTy),
4307 std::make_pair(
4308 ".copy_fn.",
4309 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4310 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4311 std::make_pair(".lb.", KmpUInt64Ty),
4312 std::make_pair(".ub.", KmpUInt64Ty),
4313 std::make_pair(".st.", KmpInt64Ty),
4314 std::make_pair(".liter.", KmpInt32Ty),
4315 std::make_pair(".reductions.", VoidPtrTy),
4316 std::make_pair(StringRef(), QualType()) // __context with shared vars
4317 };
4318 ActOnCapturedRegionStart(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getConstructLoc(), CurScope, CR_OpenMP,
4319 Params);
4320 // Mark this captured region as inlined, because we don't use outlined
4321 // function directly.
4322 getCurCapturedRegion()->TheCapturedDecl->addAttr(
4323 AlwaysInlineAttr::CreateImplicit(
4324 Context, {}, AttributeCommonInfo::AS_Keyword,
4325 AlwaysInlineAttr::Keyword_forceinline));
4326 break;
4327 }
4328 case OMPD_parallel_masked_taskloop:
4329 case OMPD_parallel_masked_taskloop_simd:
4330 case OMPD_parallel_master_taskloop:
4331 case OMPD_parallel_master_taskloop_simd: {
4332 QualType KmpInt32Ty =
4333 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1)
4334 .withConst();
4335 QualType KmpUInt64Ty =
4336 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0)
4337 .withConst();
4338 QualType KmpInt64Ty =
4339 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1)
4340 .withConst();
4341 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4342 QualType KmpInt32PtrTy =
4343 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4344 Sema::CapturedParamNameType ParamsParallel[] = {
4345 std::make_pair(".global_tid.", KmpInt32PtrTy),
4346 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4347 std::make_pair(StringRef(), QualType()) // __context with shared vars
4348 };
4349 // Start a captured region for 'parallel'.
4350 ActOnCapturedRegionStart(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getConstructLoc(), CurScope, CR_OpenMP,
4351 ParamsParallel, /*OpenMPCaptureLevel=*/0);
4352 QualType Args[] = {VoidPtrTy};
4353 FunctionProtoType::ExtProtoInfo EPI;
4354 EPI.Variadic = true;
4355 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4356 Sema::CapturedParamNameType Params[] = {
4357 std::make_pair(".global_tid.", KmpInt32Ty),
4358 std::make_pair(".part_id.", KmpInt32PtrTy),
4359 std::make_pair(".privates.", VoidPtrTy),
4360 std::make_pair(
4361 ".copy_fn.",
4362 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4363 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4364 std::make_pair(".lb.", KmpUInt64Ty),
4365 std::make_pair(".ub.", KmpUInt64Ty),
4366 std::make_pair(".st.", KmpInt64Ty),
4367 std::make_pair(".liter.", KmpInt32Ty),
4368 std::make_pair(".reductions.", VoidPtrTy),
4369 std::make_pair(StringRef(), QualType()) // __context with shared vars
4370 };
4371 ActOnCapturedRegionStart(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getConstructLoc(), CurScope, CR_OpenMP,
4372 Params, /*OpenMPCaptureLevel=*/1);
4373 // Mark this captured region as inlined, because we don't use outlined
4374 // function directly.
4375 getCurCapturedRegion()->TheCapturedDecl->addAttr(
4376 AlwaysInlineAttr::CreateImplicit(
4377 Context, {}, AttributeCommonInfo::AS_Keyword,
4378 AlwaysInlineAttr::Keyword_forceinline));
4379 break;
4380 }
4381 case OMPD_distribute_parallel_for_simd:
4382 case OMPD_distribute_parallel_for: {
4383 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4384 QualType KmpInt32PtrTy =
4385 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4386 Sema::CapturedParamNameType Params[] = {
4387 std::make_pair(".global_tid.", KmpInt32PtrTy),
4388 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4389 std::make_pair(".previous.lb.", Context.getSizeType().withConst()),
4390 std::make_pair(".previous.ub.", Context.getSizeType().withConst()),
4391 std::make_pair(StringRef(), QualType()) // __context with shared vars
4392 };
4393 ActOnCapturedRegionStart(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getConstructLoc(), CurScope, CR_OpenMP,
4394 Params);
4395 break;
4396 }
4397 case OMPD_target_teams_distribute_parallel_for:
4398 case OMPD_target_teams_distribute_parallel_for_simd: {
4399 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4400 QualType KmpInt32PtrTy =
4401 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4402 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4403
4404 QualType Args[] = {VoidPtrTy};
4405 FunctionProtoType::ExtProtoInfo EPI;
4406 EPI.Variadic = true;
4407 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4408 Sema::CapturedParamNameType Params[] = {
4409 std::make_pair(".global_tid.", KmpInt32Ty),
4410 std::make_pair(".part_id.", KmpInt32PtrTy),
4411 std::make_pair(".privates.", VoidPtrTy),
4412 std::make_pair(
4413 ".copy_fn.",
4414 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4415 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4416 std::make_pair(StringRef(), QualType()) // __context with shared vars
4417 };
4418 ActOnCapturedRegionStart(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getConstructLoc(), CurScope, CR_OpenMP,
4419 Params, /*OpenMPCaptureLevel=*/0);
4420 // Mark this captured region as inlined, because we don't use outlined
4421 // function directly.
4422 getCurCapturedRegion()->TheCapturedDecl->addAttr(
4423 AlwaysInlineAttr::CreateImplicit(
4424 Context, {}, AttributeCommonInfo::AS_Keyword,
4425 AlwaysInlineAttr::Keyword_forceinline));
4426 Sema::CapturedParamNameType ParamsTarget[] = {
4427 std::make_pair(StringRef(), QualType()) // __context with shared vars
4428 };
4429 // Start a captured region for 'target' with no implicit parameters.
4430 ActOnCapturedRegionStart(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getConstructLoc(), CurScope, CR_OpenMP,
4431 ParamsTarget, /*OpenMPCaptureLevel=*/1);
4432
4433 Sema::CapturedParamNameType ParamsTeams[] = {
4434 std::make_pair(".global_tid.", KmpInt32PtrTy),
4435 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4436 std::make_pair(StringRef(), QualType()) // __context with shared vars
4437 };
4438 // Start a captured region for 'target' with no implicit parameters.
4439 ActOnCapturedRegionStart(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getConstructLoc(), CurScope, CR_OpenMP,
4440 ParamsTeams, /*OpenMPCaptureLevel=*/2);
4441
4442 Sema::CapturedParamNameType ParamsParallel[] = {
4443 std::make_pair(".global_tid.", KmpInt32PtrTy),
4444 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4445 std::make_pair(".previous.lb.", Context.getSizeType().withConst()),
4446 std::make_pair(".previous.ub.", Context.getSizeType().withConst()),
4447 std::make_pair(StringRef(), QualType()) // __context with shared vars
4448 };
4449 // Start a captured region for 'teams' or 'parallel'. Both regions have
4450 // the same implicit parameters.
4451 ActOnCapturedRegionStart(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getConstructLoc(), CurScope, CR_OpenMP,
4452 ParamsParallel, /*OpenMPCaptureLevel=*/3);
4453 break;
4454 }
4455
4456 case OMPD_teams_loop: {
4457 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4458 QualType KmpInt32PtrTy =
4459 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4460
4461 Sema::CapturedParamNameType ParamsTeams[] = {
4462 std::make_pair(".global_tid.", KmpInt32PtrTy),
4463 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4464 std::make_pair(StringRef(), QualType()) // __context with shared vars
4465 };
4466 // Start a captured region for 'teams'.
4467 ActOnCapturedRegionStart(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getConstructLoc(), CurScope, CR_OpenMP,
4468 ParamsTeams, /*OpenMPCaptureLevel=*/0);
4469 break;
4470 }
4471
4472 case OMPD_teams_distribute_parallel_for:
4473 case OMPD_teams_distribute_parallel_for_simd: {
4474 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4475 QualType KmpInt32PtrTy =
4476 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4477
4478 Sema::CapturedParamNameType ParamsTeams[] = {
4479 std::make_pair(".global_tid.", KmpInt32PtrTy),
4480 std::make_pair(".bound_tid.", KmpInt32PtrTy),
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 ParamsTeams, /*OpenMPCaptureLevel=*/0);
4486
4487 Sema::CapturedParamNameType ParamsParallel[] = {
4488 std::make_pair(".global_tid.", KmpInt32PtrTy),
4489 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4490 std::make_pair(".previous.lb.", Context.getSizeType().withConst()),
4491 std::make_pair(".previous.ub.", Context.getSizeType().withConst()),
4492 std::make_pair(StringRef(), QualType()) // __context with shared vars
4493 };
4494 // Start a captured region for 'teams' or 'parallel'. Both regions have
4495 // the same implicit parameters.
4496 ActOnCapturedRegionStart(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getConstructLoc(), CurScope, CR_OpenMP,
4497 ParamsParallel, /*OpenMPCaptureLevel=*/1);
4498 break;
4499 }
4500 case OMPD_target_update:
4501 case OMPD_target_enter_data:
4502 case OMPD_target_exit_data: {
4503 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4504 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4505 QualType KmpInt32PtrTy =
4506 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4507 QualType Args[] = {VoidPtrTy};
4508 FunctionProtoType::ExtProtoInfo EPI;
4509 EPI.Variadic = true;
4510 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4511 Sema::CapturedParamNameType Params[] = {
4512 std::make_pair(".global_tid.", KmpInt32Ty),
4513 std::make_pair(".part_id.", KmpInt32PtrTy),
4514 std::make_pair(".privates.", VoidPtrTy),
4515 std::make_pair(
4516 ".copy_fn.",
4517 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4518 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4519 std::make_pair(StringRef(), QualType()) // __context with shared vars
4520 };
4521 ActOnCapturedRegionStart(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getConstructLoc(), CurScope, CR_OpenMP,
4522 Params);
4523 // Mark this captured region as inlined, because we don't use outlined
4524 // function directly.
4525 getCurCapturedRegion()->TheCapturedDecl->addAttr(
4526 AlwaysInlineAttr::CreateImplicit(
4527 Context, {}, AttributeCommonInfo::AS_Keyword,
4528 AlwaysInlineAttr::Keyword_forceinline));
4529 break;
4530 }
4531 case OMPD_threadprivate:
4532 case OMPD_allocate:
4533 case OMPD_taskyield:
4534 case OMPD_barrier:
4535 case OMPD_taskwait:
4536 case OMPD_cancellation_point:
4537 case OMPD_cancel:
4538 case OMPD_flush:
4539 case OMPD_depobj:
4540 case OMPD_scan:
4541 case OMPD_declare_reduction:
4542 case OMPD_declare_mapper:
4543 case OMPD_declare_simd:
4544 case OMPD_declare_target:
4545 case OMPD_end_declare_target:
4546 case OMPD_requires:
4547 case OMPD_declare_variant:
4548 case OMPD_begin_declare_variant:
4549 case OMPD_end_declare_variant:
4550 case OMPD_metadirective:
4551 llvm_unreachable("OpenMP Directive is not allowed")::llvm::llvm_unreachable_internal("OpenMP Directive is not allowed"
, "clang/lib/Sema/SemaOpenMP.cpp", 4551)
;
4552 case OMPD_unknown:
4553 default:
4554 llvm_unreachable("Unknown OpenMP directive")::llvm::llvm_unreachable_internal("Unknown OpenMP directive",
"clang/lib/Sema/SemaOpenMP.cpp", 4554)
;
4555 }
4556 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->setContext(CurContext);
4557 handleDeclareVariantConstructTrait(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
, DKind, /* ScopeEntry */ true);
4558}
4559
4560int Sema::getNumberOfConstructScopes(unsigned Level) const {
4561 return getOpenMPCaptureLevels(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getDirective(Level));
4562}
4563
4564int Sema::getOpenMPCaptureLevels(OpenMPDirectiveKind DKind) {
4565 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
4566 getOpenMPCaptureRegions(CaptureRegions, DKind);
4567 return CaptureRegions.size();
4568}
4569
4570static OMPCapturedExprDecl *buildCaptureDecl(Sema &S, IdentifierInfo *Id,
4571 Expr *CaptureExpr, bool WithInit,
4572 DeclContext *CurContext,
4573 bool AsExpression) {
4574 assert(CaptureExpr)(static_cast <bool> (CaptureExpr) ? void (0) : __assert_fail
("CaptureExpr", "clang/lib/Sema/SemaOpenMP.cpp", 4574, __extension__
__PRETTY_FUNCTION__))
;
4575 ASTContext &C = S.getASTContext();
4576 Expr *Init = AsExpression ? CaptureExpr : CaptureExpr->IgnoreImpCasts();
4577 QualType Ty = Init->getType();
4578 if (CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue()) {
4579 if (S.getLangOpts().CPlusPlus) {
4580 Ty = C.getLValueReferenceType(Ty);
4581 } else {
4582 Ty = C.getPointerType(Ty);
4583 ExprResult Res =
4584 S.CreateBuiltinUnaryOp(CaptureExpr->getExprLoc(), UO_AddrOf, Init);
4585 if (!Res.isUsable())
4586 return nullptr;
4587 Init = Res.get();
4588 }
4589 WithInit = true;
4590 }
4591 auto *CED = OMPCapturedExprDecl::Create(C, CurContext, Id, Ty,
4592 CaptureExpr->getBeginLoc());
4593 if (!WithInit)
4594 CED->addAttr(OMPCaptureNoInitAttr::CreateImplicit(C));
4595 CurContext->addHiddenDecl(CED);
4596 Sema::TentativeAnalysisScope Trap(S);
4597 S.AddInitializerToDecl(CED, Init, /*DirectInit=*/false);
4598 return CED;
4599}
4600
4601static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
4602 bool WithInit) {
4603 OMPCapturedExprDecl *CD;
4604 if (VarDecl *VD = S.isOpenMPCapturedDecl(D))
4605 CD = cast<OMPCapturedExprDecl>(VD);
4606 else
4607 CD = buildCaptureDecl(S, D->getIdentifier(), CaptureExpr, WithInit,
4608 S.CurContext,
4609 /*AsExpression=*/false);
4610 return buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
4611 CaptureExpr->getExprLoc());
4612}
4613
4614static ExprResult buildCapture(Sema &S, Expr *CaptureExpr, DeclRefExpr *&Ref) {
4615 CaptureExpr = S.DefaultLvalueConversion(CaptureExpr).get();
4616 if (!Ref) {
4617 OMPCapturedExprDecl *CD = buildCaptureDecl(
4618 S, &S.getASTContext().Idents.get(".capture_expr."), CaptureExpr,
4619 /*WithInit=*/true, S.CurContext, /*AsExpression=*/true);
4620 Ref = buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
4621 CaptureExpr->getExprLoc());
4622 }
4623 ExprResult Res = Ref;
4624 if (!S.getLangOpts().CPlusPlus &&
4625 CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue() &&
4626 Ref->getType()->isPointerType()) {
4627 Res = S.CreateBuiltinUnaryOp(CaptureExpr->getExprLoc(), UO_Deref, Ref);
4628 if (!Res.isUsable())
4629 return ExprError();
4630 }
4631 return S.DefaultLvalueConversion(Res.get());
4632}
4633
4634namespace {
4635// OpenMP directives parsed in this section are represented as a
4636// CapturedStatement with an associated statement. If a syntax error
4637// is detected during the parsing of the associated statement, the
4638// compiler must abort processing and close the CapturedStatement.
4639//
4640// Combined directives such as 'target parallel' have more than one
4641// nested CapturedStatements. This RAII ensures that we unwind out
4642// of all the nested CapturedStatements when an error is found.
4643class CaptureRegionUnwinderRAII {
4644private:
4645 Sema &S;
4646 bool &ErrorFound;
4647 OpenMPDirectiveKind DKind = OMPD_unknown;
4648
4649public:
4650 CaptureRegionUnwinderRAII(Sema &S, bool &ErrorFound,
4651 OpenMPDirectiveKind DKind)
4652 : S(S), ErrorFound(ErrorFound), DKind(DKind) {}
4653 ~CaptureRegionUnwinderRAII() {
4654 if (ErrorFound) {
4655 int ThisCaptureLevel = S.getOpenMPCaptureLevels(DKind);
4656 while (--ThisCaptureLevel >= 0)
4657 S.ActOnCapturedRegionError();
4658 }
4659 }
4660};
4661} // namespace
4662
4663void Sema::tryCaptureOpenMPLambdas(ValueDecl *V) {
4664 // Capture variables captured by reference in lambdas for target-based
4665 // directives.
4666 if (!CurContext->isDependentContext() &&
4667 (isOpenMPTargetExecutionDirective(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective()) ||
4668 isOpenMPTargetDataManagementDirective(
4669 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective()))) {
4670 QualType Type = V->getType();
4671 if (const auto *RD = Type.getCanonicalType()
4672 .getNonReferenceType()
4673 ->getAsCXXRecordDecl()) {
4674 bool SavedForceCaptureByReferenceInTargetExecutable =
4675 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->isForceCaptureByReferenceInTargetExecutable();
4676 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->setForceCaptureByReferenceInTargetExecutable(
4677 /*V=*/true);
4678 if (RD->isLambda()) {
4679 llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
4680 FieldDecl *ThisCapture;
4681 RD->getCaptureFields(Captures, ThisCapture);
4682 for (const LambdaCapture &LC : RD->captures()) {
4683 if (LC.getCaptureKind() == LCK_ByRef) {
4684 VarDecl *VD = cast<VarDecl>(LC.getCapturedVar());
4685 DeclContext *VDC = VD->getDeclContext();
4686 if (!VDC->Encloses(CurContext))
4687 continue;
4688 MarkVariableReferenced(LC.getLocation(), VD);
4689 } else if (LC.getCaptureKind() == LCK_This) {
4690 QualType ThisTy = getCurrentThisType();
4691 if (!ThisTy.isNull() &&
4692 Context.typesAreCompatible(ThisTy, ThisCapture->getType()))
4693 CheckCXXThisCapture(LC.getLocation());
4694 }
4695 }
4696 }
4697 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->setForceCaptureByReferenceInTargetExecutable(
4698 SavedForceCaptureByReferenceInTargetExecutable);
4699 }
4700 }
4701}
4702
4703static bool checkOrderedOrderSpecified(Sema &S,
4704 const ArrayRef<OMPClause *> Clauses) {
4705 const OMPOrderedClause *Ordered = nullptr;
4706 const OMPOrderClause *Order = nullptr;
4707
4708 for (const OMPClause *Clause : Clauses) {
4709 if (Clause->getClauseKind() == OMPC_ordered)
4710 Ordered = cast<OMPOrderedClause>(Clause);
4711 else if (Clause->getClauseKind() == OMPC_order) {
4712 Order = cast<OMPOrderClause>(Clause);
4713 if (Order->getKind() != OMPC_ORDER_concurrent)
4714 Order = nullptr;
4715 }
4716 if (Ordered && Order)
4717 break;
4718 }
4719
4720 if (Ordered && Order) {
4721 S.Diag(Order->getKindKwLoc(),
4722 diag::err_omp_simple_clause_incompatible_with_ordered)
4723 << getOpenMPClauseName(OMPC_order)
4724 << getOpenMPSimpleClauseTypeName(OMPC_order, OMPC_ORDER_concurrent)
4725 << SourceRange(Order->getBeginLoc(), Order->getEndLoc());
4726 S.Diag(Ordered->getBeginLoc(), diag::note_omp_ordered_param)
4727 << 0 << SourceRange(Ordered->getBeginLoc(), Ordered->getEndLoc());
4728 return true;
4729 }
4730 return false;
4731}
4732
4733StmtResult Sema::ActOnOpenMPRegionEnd(StmtResult S,
4734 ArrayRef<OMPClause *> Clauses) {
4735 handleDeclareVariantConstructTrait(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
, DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective(),
4736 /* ScopeEntry */ false);
4737 if (DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective() == OMPD_atomic ||
4738 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective() == OMPD_critical ||
4739 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective() == OMPD_section ||
4740 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective() == OMPD_master ||
4741 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective() == OMPD_masked)
4742 return S;
4743
4744 bool ErrorFound = false;
4745 CaptureRegionUnwinderRAII CaptureRegionUnwinder(
4746 *this, ErrorFound, DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective());
4747 if (!S.isUsable()) {
4748 ErrorFound = true;
4749 return StmtError();
4750 }
4751
4752 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
4753 getOpenMPCaptureRegions(CaptureRegions, DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective());
4754 OMPOrderedClause *OC = nullptr;
4755 OMPScheduleClause *SC = nullptr;
4756 SmallVector<const OMPLinearClause *, 4> LCs;
4757 SmallVector<const OMPClauseWithPreInit *, 4> PICs;
4758 // This is required for proper codegen.
4759 for (OMPClause *Clause : Clauses) {
4760 if (!LangOpts.OpenMPSimd &&
4761 (isOpenMPTaskingDirective(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective()) ||
4762 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective() == OMPD_target) &&
4763 Clause->getClauseKind() == OMPC_in_reduction) {
4764 // Capture taskgroup task_reduction descriptors inside the tasking regions
4765 // with the corresponding in_reduction items.
4766 auto *IRC = cast<OMPInReductionClause>(Clause);
4767 for (Expr *E : IRC->taskgroup_descriptors())
4768 if (E)
4769 MarkDeclarationsReferencedInExpr(E);
4770 }
4771 if (isOpenMPPrivate(Clause->getClauseKind()) ||
4772 Clause->getClauseKind() == OMPC_copyprivate ||
4773 (getLangOpts().OpenMPUseTLS &&
4774 getASTContext().getTargetInfo().isTLSSupported() &&
4775 Clause->getClauseKind() == OMPC_copyin)) {
4776 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->setForceVarCapturing(Clause->getClauseKind() == OMPC_copyin);
4777 // Mark all variables in private list clauses as used in inner region.
4778 for (Stmt *VarRef : Clause->children()) {
4779 if (auto *E = cast_or_null<Expr>(VarRef)) {
4780 MarkDeclarationsReferencedInExpr(E);
4781 }
4782 }
4783 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->setForceVarCapturing(/*V=*/false);
4784 } else if (isOpenMPLoopTransformationDirective(
4785 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective())) {
4786 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", 4787, __extension__ __PRETTY_FUNCTION__
))
4787 "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", 4787, __extension__ __PRETTY_FUNCTION__
))
;
4788 } else if (CaptureRegions.size() > 1 ||
4789 CaptureRegions.back() != OMPD_unknown) {
4790 if (auto *C = OMPClauseWithPreInit::get(Clause))
4791 PICs.push_back(C);
4792 if (auto *C = OMPClauseWithPostUpdate::get(Clause)) {
4793 if (Expr *E = C->getPostUpdateExpr())
4794 MarkDeclarationsReferencedInExpr(E);
4795 }
4796 }
4797 if (Clause->getClauseKind() == OMPC_schedule)
4798 SC = cast<OMPScheduleClause>(Clause);
4799 else if (Clause->getClauseKind() == OMPC_ordered)
4800 OC = cast<OMPOrderedClause>(Clause);
4801 else if (Clause->getClauseKind() == OMPC_linear)
4802 LCs.push_back(cast<OMPLinearClause>(Clause));
4803 }
4804 // Capture allocator expressions if used.
4805 for (Expr *E : DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getInnerAllocators())
4806 MarkDeclarationsReferencedInExpr(E);
4807 // OpenMP, 2.7.1 Loop Construct, Restrictions
4808 // The nonmonotonic modifier cannot be specified if an ordered clause is
4809 // specified.
4810 if (SC &&
4811 (SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
4812 SC->getSecondScheduleModifier() ==
4813 OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
4814 OC) {
4815 Diag(SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic
4816 ? SC->getFirstScheduleModifierLoc()
4817 : SC->getSecondScheduleModifierLoc(),
4818 diag::err_omp_simple_clause_incompatible_with_ordered)
4819 << getOpenMPClauseName(OMPC_schedule)
4820 << getOpenMPSimpleClauseTypeName(OMPC_schedule,
4821 OMPC_SCHEDULE_MODIFIER_nonmonotonic)
4822 << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4823 ErrorFound = true;
4824 }
4825 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Restrictions.
4826 // If an order(concurrent) clause is present, an ordered clause may not appear
4827 // on the same directive.
4828 if (checkOrderedOrderSpecified(*this, Clauses))
4829 ErrorFound = true;
4830 if (!LCs.empty() && OC && OC->getNumForLoops()) {
4831 for (const OMPLinearClause *C : LCs) {
4832 Diag(C->getBeginLoc(), diag::err_omp_linear_ordered)
4833 << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4834 }
4835 ErrorFound = true;
4836 }
4837 if (isOpenMPWorksharingDirective(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective()) &&
4838 isOpenMPSimdDirective(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective()) && OC &&
4839 OC->getNumForLoops()) {
4840 Diag(OC->getBeginLoc(), diag::err_omp_ordered_simd)
4841 << getOpenMPDirectiveName(DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->getCurrentDirective());
4842 ErrorFound = true;
4843 }
4844 if (ErrorFound) {
4845 return StmtError();
4846 }
4847 StmtResult SR = S;
4848 unsigned CompletedRegions = 0;
4849 for (OpenMPDirectiveKind ThisCaptureRegion : llvm::reverse(CaptureRegions)) {
4850 // Mark all variables in private list clauses as used in inner region.
4851 // Required for proper codegen of combined directives.
4852 // TODO: add processing for other clauses.
4853 if (ThisCaptureRegion != OMPD_unknown) {
4854 for (const clang::OMPClauseWithPreInit *C : PICs) {
4855 OpenMPDirectiveKind CaptureRegion = C->getCaptureRegion();
4856 // Find the particular capture region for the clause if the
4857 // directive is a combined one with multiple capture regions.
4858 // If the directive is not a combined one, the capture region
4859 // associated with the clause is OMPD_unknown and is generated
4860 // only once.
4861 if (CaptureRegion == ThisCaptureRegion ||
4862 CaptureRegion == OMPD_unknown) {
4863 if (auto *DS = cast_or_null<DeclStmt>(C->getPreInitStmt())) {
4864 for (Decl *D : DS->decls())
4865 MarkVariableReferenced(D->getLocation(), cast<VarDecl>(D));
4866 }
4867 }
4868 }
4869 }
4870 if (ThisCaptureRegion == OMPD_target) {
4871 // Capture allocator traits in the target region. They are used implicitly
4872 // and, thus, are not captured by default.
4873 for (OMPClause *C : Clauses) {
4874 if (const auto *UAC = dyn_cast<OMPUsesAllocatorsClause>(C)) {
4875 for (unsigned I = 0, End = UAC->getNumberOfAllocators(); I < End;
4876 ++I) {
4877 OMPUsesAllocatorsClause::Data D = UAC->getAllocatorData(I);
4878 if (Expr *E = D.AllocatorTraits)
4879 MarkDeclarationsReferencedInExpr(E);
4880 }
4881 continue;
4882 }
4883 }
4884 }
4885 if (ThisCaptureRegion == OMPD_parallel) {
4886 // Capture temp arrays for inscan reductions and locals in aligned
4887 // clauses.
4888 for (OMPClause *C : Clauses) {
4889 if (auto *RC = dyn_cast<OMPReductionClause>(C)) {
4890 if (RC->getModifier() != OMPC_REDUCTION_inscan)
4891 continue;
4892 for (Expr *E : RC->copy_array_temps())
4893 MarkDeclarationsReferencedInExpr(E);
4894 }
4895 if (auto *AC = dyn_cast<OMPAlignedClause>(C)) {
4896 for (Expr *E : AC->varlists())
4897 MarkDeclarationsReferencedInExpr(E);
4898 }
4899 }
4900 }
4901 if (++CompletedRegions == CaptureRegions.size())
4902 DSAStackstatic_cast<DSAStackTy *>(VarDataSharingAttributesStack
)
->setBodyComplete();
4903 SR = ActOnCapturedRegionEnd(SR.get());
4904 }
4905 return SR;
4906}
4907
4908static bool checkCancelRegion(Sema &SemaRef, OpenMPDirectiveKind CurrentRegion,
4909 OpenMPDirectiveKind CancelRegion,
4910 SourceLocation StartLoc) {
4911 // CancelRegion is only needed for cancel and cancellation_point.
4912 if (CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_cancellation_point)
4913 return false;
4914
4915 if (CancelRegion == OMPD_parallel || CancelRegion == OMPD_for ||
4916 CancelRegion == OMPD_sections || CancelRegion == OMPD_taskgroup)
4917 return false;
4918
4919 SemaRef.Diag(StartLoc, diag::err_omp_wrong_cancel_region)
4920 << getOpenMPDirectiveName(CancelRegion);
4921 return true;
4922}
4923
4924static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack,
4925 OpenMPDirectiveKind CurrentRegion,
4926 const DeclarationNameInfo &CurrentName,
4927 OpenMPDirectiveKind CancelRegion,
4928 OpenMPBindClauseKind BindKind,
4929 SourceLocation StartLoc) {
4930 if (Stack->getCurScope()) {
4931 OpenMPDirectiveKind ParentRegion = Stack->getParentDirective();
4932 OpenMPDirectiveKind OffendingRegion = ParentRegion;
4933 bool NestingProhibited = false;
4934 bool CloseNesting = true;
4935 bool OrphanSeen = false;
4936 enum {
4937 NoRecommend,
4938 ShouldBeInParallelRegion,
4939 ShouldBeInOrderedRegion,
4940 ShouldBeInTargetRegion,
4941 ShouldBeInTeamsRegion,
4942 ShouldBeInLoopSimdRegion,
4943 } Recommend = NoRecommend;
4944 if (isOpenMPSimdDirective(ParentRegion) &&
4945 ((SemaRef.LangOpts.OpenMP <= 45 && CurrentRegion != OMPD_ordered) ||
4946 (SemaRef.LangOpts.OpenMP >= 50 && CurrentRegion != OMPD_ordered &&
4947 CurrentRegion != OMPD_simd && CurrentRegion != OMPD_atomic &&
4948 CurrentRegion != OMPD_scan))) {
4949 // OpenMP [2.16, Nesting of Regions]
4950 // OpenMP constructs may not be nested inside a simd region.
4951 // OpenMP [2.8.1,simd Construct, Restrictions]
4952 // An ordered construct with the simd clause is the only OpenMP
4953 // construct that can appear in the simd region.
4954 // Allowing a SIMD construct nested in another SIMD construct is an
4955 // extension. The OpenMP 4.5 spec does not allow it. Issue a warning
4956 // message.
4957 // OpenMP 5.0 [2.9.3.1, simd Construct, Restrictions]
4958 // The only OpenMP constructs that can be encountered during execution of
4959 // a simd region are the atomic construct, the loop construct, the simd
4960 // construct and the ordered construct with the simd clause.
4961 SemaRef.Diag(StartLoc, (CurrentRegion != OMPD_simd)
4962 ? diag::err_omp_prohibited_region_simd
4963 : diag::warn_omp_nesting_simd)
4964 << (SemaRef.LangOpts.OpenMP >= 50 ? 1 : 0);
4965 return CurrentRegion != OMPD_simd;
4966 }
4967 if (ParentRegion == OMPD_atomic) {
4968 // OpenMP [2.16, Nesting of Regions]
4969 // OpenMP constructs may not be nested inside an atomic region.
4970 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_atomic);
4971 return true;
4972 }
4973 if (CurrentRegion == OMPD_section) {
4974 // OpenMP [2.7.2, sections Construct, Restrictions]
4975 // Orphaned section directives are prohibited. That is, the section
4976 // directives must appear within the sections construct and must not be
4977 // encountered elsewhere in the sections region.
4978 if (ParentRegion != OMPD_sections &&
4979 ParentRegion != OMPD_parallel_sections) {
4980 SemaRef.Diag(StartLoc, diag::err_omp_orphaned_section_directive)
4981 << (ParentRegion != OMPD_unknown)
4982 << getOpenMPDirectiveName(ParentRegion);
4983 return true;
4984 }
4985 return false;
4986 }
4987 // Allow some constructs (except teams and cancellation constructs) to be
4988 // orphaned (they could be used in functions, called from OpenMP regions
4989 // with the required preconditions).
4990 if (ParentRegion == OMPD_unknown &&
4991 !isOpenMPNestingTeamsDirective(CurrentRegion) &&
4992 CurrentRegion != OMPD_cancellation_point &&
4993 CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_scan)
4994 return false;
4995 if (CurrentRegion == OMPD_cancellation_point ||
4996 CurrentRegion == OMPD_cancel) {
4997 // OpenMP [2.16, Nesting of Regions]
4998 // A cancellation point construct for which construct-type-clause is
4999 // taskgroup must be nested inside a task construct. A cancellation
5000 // point construct for which construct-type-clause is not taskgroup must
5001 // be closely nested inside an OpenMP construct that matches the type
5002 // specified in construct-type-clause.
5003 // A cancel construct for which construct-type-clause is taskgroup must be
5004 // nested inside a task construct. A cancel construct for which
5005 // construct-type-clause is not taskgroup must be closely nested inside an
5006 // OpenMP construct that matches the type specified in
5007 // construct-type-clause.
5008 NestingProhibited =
5009 !((CancelRegion == OMPD_parallel &&
5010 (ParentRegion == OMPD_parallel ||
5011 ParentRegion == OMPD_target_parallel)) ||
5012 (CancelRegion == OMPD_for &&
5013 (ParentRegion == OMPD_for || ParentRegion == OMPD_parallel_for ||
5014 ParentRegion == OMPD_target_parallel_for ||
5015 ParentRegion == OMPD_distribute_parallel_for ||
5016 ParentRegion == OMPD_teams_distribute_parallel_for ||
5017 ParentRegion == OMPD_target_teams_distribute_parallel_for)) ||
5018 (CancelRegion == OMPD_taskgroup &&
5019 (ParentRegion == OMPD_task ||
5020 (SemaRef.getLangOpts().OpenMP >= 50 &&
5021 (ParentRegion == OMPD_taskloop ||
5022 ParentRegion == OMPD_master_taskloop ||
5023 ParentRegion == OMPD_masked_taskloop ||
5024 ParentRegion == OMPD_parallel_masked_taskloop ||
5025 ParentRegion == OMPD_parallel_master_taskloop)))) ||
5026 (CancelRegion == OMPD_sections &&
5027 (ParentRegion == OMPD_section || ParentRegion == OMPD_sections ||
5028 ParentRegion == OMPD_parallel_sections)));
5029 OrphanSeen = ParentRegion == OMPD_unknown;
5030 } else if (CurrentRegion == OMPD_master || CurrentRegion == OMPD_masked) {
5031 // OpenMP 5.1 [2.22, Nesting of Regions]
5032 // A masked region may not be closely nested inside a worksharing, loop,
5033 // atomic, task, or taskloop region.
5034 NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
5035 isOpenMPGenericLoopDirective(ParentRegion) ||
5036 isOpenMPTaskingDirective(ParentRegion);
5037 } else if (CurrentRegion == OMPD_critical && CurrentName.getName()) {
5038 // OpenMP [2.16, Nesting of Regions]
5039 // A critical region may not be nested (closely or otherwise) inside a
5040 // critical region with the same name. Note that this restriction is not
5041 // sufficient to prevent deadlock.
5042 SourceLocation PreviousCriticalLoc;
5043 bool DeadLock = Stack->hasDirective(
5044 [CurrentName, &PreviousCriticalLoc](OpenMPDirectiveKind K,
5045 const DeclarationNameInfo &DNI,
5046 SourceLocation Loc) {
5047 if (K == OMPD_critical && DNI.getName() == CurrentName.getName()) {
5048 PreviousCriticalLoc = Loc;
5049 return true;
5050 }
5051 return false;
5052 },
5053 false /* skip top directive */);
5054 if (DeadLock) {
5055 SemaRef.Diag(StartLoc,
5056 diag::err_omp_prohibited_region_critical_same_name)
5057 << CurrentName.getName();
5058 if (PreviousCriticalLoc.isValid())
5059 SemaRef.Diag(PreviousCriticalLoc,
5060 diag::note_omp_previous_critical_region);
5061 return true;
5062 }
5063 } else if (CurrentRegion == OMPD_barrier) {
5064 // OpenMP 5.1 [2.22, Nesting of Regions]
5065 // A barrier region may not be closely nested inside a worksharing, loop,
5066 // task, taskloop, critical, ordered, atomic, or masked region.
5067 NestingProhibited =
5068 isOpenMPWorksharingDirective(ParentRegion) ||
5069 isOpenMPGenericLoopDirective(ParentRegion) ||
5070 isOpenMPTaskingDirective(ParentRegion) ||
5071 ParentRegion == OMPD_master || ParentRegion == OMPD_masked ||
5072 ParentRegion == OMPD_parallel_master ||
5073 ParentRegion == OMPD_parallel_masked ||
5074 ParentRegion == OMPD_critical || ParentRegion == OMPD_ordered;
5075 } else if (isOpenMPWorksharingDirective(CurrentRegion) &&
5076 !isOpenMPParallelDirective(CurrentRegion) &&
5077 !isOpenMPTeamsDirective(CurrentRegion)) {
5078 // OpenMP 5.1 [2.22, Nesting of Regions]
5079 // A loop region that binds to a parallel region or a worksharing region
5080 // may not be closely nested inside a worksharing, loop, task, taskloop,
5081 // critical, ordered, atomic, or masked region.
5082 NestingProhibited =
5083 isOpenMPWorksharingDirective(ParentRegion) ||
5084 isOpenMPGenericLoopDirective(ParentRegion) ||
5085 isOpenMPTaskingDirective(ParentRegion) ||
5086 ParentRegion == OMPD_master || ParentRegion == OMPD_masked ||
5087 ParentRegion == OMPD_parallel_master ||
5088 ParentRegion == OMPD_parallel_masked ||
5089 ParentRegion == OMPD_critical || ParentRegion == OMPD_ordered;
5090 Recommend = ShouldBeInParallelRegion;
5091 } else if (CurrentRegion == OMPD_ordered) {
5092 // OpenMP [2.16, Nesting of Regions]
5093 // An ordered region may not be closely nested inside a critical,
5094 // atomic, or explicit task region.
5095 // An ordered region must be closely nested inside a loop region (or
5096 // parallel loop region) with an ordered clause.
5097 // OpenMP [2.8.1,simd Construct, Restrictions]
5098 // An ordered construct with the simd clause is the only OpenMP construct
5099 // that can appear in the simd region.
5100 NestingProhibited = ParentRegion == OMPD_critical ||
5101 isOpenMPTaskingDirective(ParentRegion) ||
5102 !(isOpenMPSimdDirective(ParentRegion) ||
5103 Stack->isParentOrderedRegion());
5104 Recommend = ShouldBeInOrderedRegion;
5105 } else if (isOpenMPNestingTeamsDirective(CurrentRegion)) {
5106 // OpenMP [2.16, Nesting of Regions]
5107 // If specified, a teams construct must be contained within a target
5108 // construct.
5109 NestingProhibited =
5110 (SemaRef.LangOpts.OpenMP <= 45 && ParentRegion != OMPD_target) ||
5111 (SemaRef.LangOpts.OpenMP >= 50 && ParentRegion != OMPD_unknown &&
5112 ParentRegion != OMPD_target);
5113 OrphanSeen = ParentRegion == OMPD_unknown;
5114 Recommend = ShouldBeInTargetRegion;
5115 } else if (CurrentRegion == OMPD_scan) {
5116 // OpenMP [2.16, Nesting of Regions]
5117 // If specified, a teams construct must be contained within a target
5118 // construct.
5119 NestingProhibited =
5120 SemaRef.LangOpts.OpenMP < 50 ||
5121 (ParentRegion != OMPD_simd && ParentRegion != OMPD_for &&
5122 ParentRegion != OMPD_for_simd && ParentRegion != OMPD_parallel_for &&
5123 ParentRegion != OMPD_parallel_for_simd);
5124 OrphanSeen = ParentRegion == OMPD_unknown;
5125 Recommend = ShouldBeInLoopSimdRegion;
5126 }
5127 if (!NestingProhibited &&
5128 !isOpenMPTargetExecutionDirective(CurrentRegion) &&
5129 !isOpenMPTargetDataManagementDirective(CurrentRegion) &&
5130 (ParentRegion == OMPD_teams || ParentRegion == OMPD_target_teams)) {
5131 // OpenMP [5.1, 2.22, Nesting of Regions]
5132 // distribute, distribute simd, distribute parallel worksharing-loop,
5133 // distribute parallel worksharing-loop SIMD, loop, parallel regions,
5134 // including any parallel regions arising from combined constructs,
5135 // omp_get_num_teams() regions, and omp_get_team_num() regions are the
5136 // only OpenMP regions that may be strictly nested inside the teams
5137 // region.
5138 //
5139 // As an extension, we permit atomic within teams as well.
5140 NestingProhibited = !isOpenMPParallelDirective(CurrentRegion) &&
5141 !isOpenMPDistributeDirective(CurrentRegion) &&
5142 CurrentRegion != OMPD_loop &&
5143 !(SemaRef.getLangOpts().OpenMPExtensions &&
5144 CurrentRegion == OMPD_atomic);
5145 Recommend = ShouldBeInParallelRegion;
5146 }
5147 if (!NestingProhibited && CurrentRegion == OMPD_loop) {
5148 // OpenMP [5.1, 2.11.7, loop Construct, Restrictions]
5149 // If the bind clause is present on the loop construct and binding is
5150 // teams then the corresponding loop region must be strictly nested inside
5151 // a teams region.
5152 NestingProhibited = BindKind == OMPC_BIND_teams &&
5153 ParentRegion != OMPD_teams &&
5154 ParentRegion != OMPD_target_teams;
5155 Recommend = ShouldBeInTeamsRegion;
5156 }
5157 if (!NestingProhibited &&
5158 isOpenMPNestingDistributeDirective(CurrentRegion)) {
5159 // OpenMP 4.5 [2.17 Nesting of Regions]
5160 // The region associated with the distribute construct must be strictly
5161 // nested inside a teams region
5162 NestingProhibited =
5163 (ParentRegion != OMPD_teams && ParentRegion != OMPD_target_teams);
5164 Recommend = ShouldBeInTeamsRegion;
5165 }
5166 if (!NestingProhibited &&
5167 (isOpenMPTargetExecutionDirective(CurrentRegion) ||
5168 isOpenMPTargetDataManagementDirective(CurrentRegion))) {
5169 // OpenMP 4.5 [2.17 Nesting of Regions]
5170 // If a target, target update, target data, target enter data, or
5171 // target exit data construct is encountered during execution of a
5172 // target region, the behavior is unspecified.
5173 NestingProhibited = Stack->hasDirective(
5174 [&OffendingRegion](OpenMPDirectiveKind K, const DeclarationNameInfo &,
5175 SourceLocation) {
5176 if (isOpenMPTargetExecutionDirective(K)) {
5177 OffendingRegion = K;
5178 return true;
5179 }
5180 return false;
5181 },
5182 false /* don't skip top directive */);
5183 CloseNesting = false;
5184 }
5185 if (NestingProhibited) {
5186 if (OrphanSeen) {
5187 SemaRef.Diag(StartLoc, diag::err_omp_orphaned_device_directive)
5188 << getOpenMPDirectiveName(CurrentRegion) << Recommend;
5189 } else {
5190 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region)
5191 << CloseNesting << getOpenMPDirectiveName(OffendingRegion)
5192 << Recommend << getOpenMPDirectiveName(CurrentRegion);
5193 }
5194 return true;
5195 }
5196 }
5197 return false;
5198}
5199
5200struct Kind2Unsigned {
5201 using argument_type = OpenMPDirectiveKind;
5202 unsigned operator()(argument_type DK) { return unsigned(DK); }
5203};
5204static bool checkIfClauses(Sema &S, OpenMPDirectiveKind Kind,
5205 ArrayRef<OMPClause *> Clauses,
5206 ArrayRef<OpenMPDirectiveKind> AllowedNameModifiers) {
5207 bool ErrorFound = false;
5208 unsigned NamedModifiersNumber = 0;
5209 llvm::IndexedMap<const OMPIfClause *, Kind2Unsigned> FoundNameModifiers;
5210 FoundNameModifiers.resize(llvm::omp::Directive_enumSize + 1);
5211 SmallVector<SourceLocation, 4> NameModifierLoc;
5212 for (const OMPClause *C : Clauses) {
5213 if (const auto *IC = dyn_cast_or_null<OMPIfClause>(C)) {
5214 // At most one if clause without a directive-name-modifier can appear on
5215 // the directive.
5216 OpenMPDirectiveKind CurNM = IC->getNameModifier();
5217 if (FoundNameModifiers[CurNM]) {
5218 S.Diag(C->getBeginLoc(), diag::err_omp_more_one_clause)
5219 << getOpenMPDirectiveName(Kind) << getOpenMPClauseName(OMPC_if)
5220 << (CurNM != OMPD_unknown) << getOpenMPDirectiveName(CurNM);
5221 ErrorFound = true;
5222 } else if (CurNM != OMPD_unknown) {
5223 NameModifierLoc.push_back(IC->getNameModifierLoc());
5224 ++NamedModifiersNumber;
5225 }
5226 FoundNameModifiers[CurNM] = IC;
5227 if (CurNM == OMPD_unknown)
5228 continue;
5229 // Check if the specified name modifier is allowed for the current
5230 // directive.
5231 // At most one if clause with the particular directive-name-modifier can
5232 // appear on the directive.
5233 if (!llvm::is_contained(AllowedNameModifiers, CurNM)) {
5234 S.Diag(IC->getNameModifierLoc(),
5235 diag::err_omp_wrong_if_directive_name_modifier)
5236 << getOpenMPDirectiveName(CurNM) << getOpenMPDirectiveName(Kind);
5237 ErrorFound = true;
5238 }
5239 }
5240 }
5241 // If any if clause on the directive includes a directive-name-modifier then
5242 // all if clauses on the directive must include a directive-name-modifier.
5243 if (FoundNameModifiers[OMPD_unknown] && NamedModifiersNumber > 0) {
5244 if (NamedModifiersNumber == AllowedNameModifiers.size()) {
5245 S.Diag(FoundNameModifiers[OMPD_unknown]->getBeginLoc(),
5246 diag::err_omp_no_more_if_clause);
5247 } else {
5248 std::string Values;
5249 std::string Sep(", ");
5250 unsigned AllowedCnt = 0;
5251 unsigned TotalAllowedNum =
5252 AllowedNameModifiers.size() - NamedModifiersNumber;
5253 for (unsigned Cnt = 0, End = AllowedNameModifiers.size(); Cnt < End;
5254 ++Cnt) {
5255 OpenMPDirectiveKind NM = AllowedNameModifiers[Cnt];
5256 if (!FoundNameModifiers[NM]) {
5257 Values += "'";
5258 Values += getOpenMPDirectiveName(NM);
5259 Values += "'";
5260 if (AllowedCnt + 2 == TotalAllowedNum)
5261 Values += " or ";
5262 else if (AllowedCnt + 1 != TotalAllowedNum)
5263 Values += Sep;
5264 ++AllowedCnt;
5265 }
5266 }
5267 S.Diag(FoundNameModifiers[OMPD_unknown]->getCondition()->getBeginLoc(),
5268 diag::err_omp_unnamed_if_clause)
5269 << (TotalAllowedNum > 1) << Values;
5270 }
5271 for (SourceLocation Loc : NameModifierLoc) {
5272 S.Diag(Loc, diag::note_omp_previous_named_if_clause);
5273 }
5274 ErrorFound = true;
5275 }
5276 return ErrorFound;
5277}
5278
5279static std::pair<ValueDecl *, bool> getPrivateItem(Sema &S, Expr *&RefExpr,
5280 SourceLocation &ELoc,
5281 SourceRange &ERange,
5282 bool AllowArraySection,
5283 StringRef DiagType) {
5284 if (RefExpr->isTypeDependent() || RefExpr->isValueDependent() ||
5285 RefExpr->containsUnexpandedParameterPack())
5286 return std::make_pair(nullptr, true);
5287
5288 // OpenMP [3.1, C/C++]
5289 // A list item is a variable name.
5290 // OpenMP [2.9.3.3, Restrictions, p.1]
5291 // A variable that is part of another variable (as an array or
5292 // structure element) cannot appear in a private clause.
5293 RefExpr = RefExpr->IgnoreParens();
5294 enum {
5295 NoArrayExpr = -1,
5296 ArraySubscript = 0,
5297 OMPArraySection = 1
5298 } IsArrayExpr = NoArrayExpr;
5299 if (AllowArraySection) {
5300 if (auto *ASE = dyn_cast_or_null<ArraySubscriptExpr>(RefExpr)) {
5301 Expr *Base = ASE->getBase()->IgnoreParenImpCasts();
5302 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
5303 Base = TempASE->getBase()->IgnoreParenImpCasts();
5304 RefExpr = Base;
5305 IsArrayExpr = ArraySubscript;
5306 } else if (auto *OASE = dyn_cast_or_null<OMPArraySectionExpr>(RefExpr)) {
5307 Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
5308 while (auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base))
5309 Base = TempOASE->getBase()->IgnoreParenImpCasts();
5310 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
5311 Base = TempASE->getBase()->IgnoreParenImpCasts();
5312 RefExpr = Base;
5313 IsArrayExpr = OMPArraySection;
5314 }
5315 }
5316 ELoc = RefExpr->getExprLoc();
5317 ERange = RefExpr->getSourceRange();
5318 RefExpr = RefExpr->IgnoreParenImpCasts();
5319 auto *DE = dyn_cast_or_null<DeclRefExpr>(RefExpr);
5320 auto *ME = dyn_cast_or_null<MemberExpr>(RefExpr);
5321 if ((!DE || !isa<VarDecl>(DE->getDecl())) &&
5322 (S.getCurrentThisType().isNull() || !ME ||
5323 !isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()) ||
5324 !isa<FieldDecl>(ME->getMemberDecl()))) {
5325 if (IsArrayExpr != NoArrayExpr) {
5326 S.Diag(ELoc, diag::err_omp_expected_base_var_name)
5327 << IsArrayExpr << ERange;
5328 } else if (!DiagType.empty()) {
5329 unsigned DiagSelect = S.getLangOpts().CPlusPlus
5330 ? (S.getCurrentThisType().isNull() ? 1 : 2)
5331 : 0;
5332 S.Diag(ELoc, diag::err_omp_expected_var_name_member_expr_with_type)
5333 << DiagSelect << DiagType << ERange;
5334 } else {
5335 S.Diag(ELoc,
5336 AllowArraySection
5337 ? diag::err_omp_expected_var_name_member_expr_or_array_item
5338 : diag::err_omp_expected_var_name_member_expr)
5339 << (S.getCurrentThisType().isNull() ? 0 : 1) << ERange;
5340 }
5341 return std::make_pair(nullptr, false);
5342 }
5343 return std::make_pair(
5344 getCanonicalDecl(DE ? DE->getDecl() : ME->getMemberDecl()), false);
5345}
5346
5347namespace {
5348/// Checks if the allocator is used in uses_allocators clause to be allowed in
5349/// target regions.
5350class AllocatorChecker final : public ConstStmtVisitor<AllocatorChecker, bool> {
5351 DSAStackTy *S = nullptr;
5352
5353public:
5354 bool VisitDeclRefExpr(const DeclRefExpr *E) {
5355 return S->isUsesAllocatorsDecl(E->getDecl())
5356 .value_or(DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
5357 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait;
5358 }
5359 bool VisitStmt(const Stmt *S) {
5360 for (const Stmt *Child : S->children()) {
5361 if (Child && Visit(Child))
5362 return true;
5363 }
5364 return false;
5365 }
5366 explicit AllocatorChecker(DSAStackTy *S) : S(S) {}
5367};
5368} // namespace
5369
5370static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
5371 ArrayRef<OMPClause *> Clauses) {
5372 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", 5373, __extension__ __PRETTY_FUNCTION__
))
5373 "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", 5373, __extension__ __PRETTY_FUNCTION__
))
;
5374 auto AllocateRange =
5375 llvm::make_filter_range(Clauses, OMPAllocateClause::classof);
5376 llvm::DenseMap<CanonicalDeclPtr<Decl>, CanonicalDeclPtr<VarDecl>> DeclToCopy;
5377 auto PrivateRange = llvm::make_filter_range(Clauses, [](const OMPClause *C) {
5378 return isOpenMPPrivate(C->getClauseKind());
5379 });
5380 for (OMPClause *Cl : PrivateRange) {
5381 MutableArrayRef<Expr *>::iterator I, It, Et;
5382 if (Cl->getClauseKind() == OMPC_private) {
5383 auto *PC = cast<OMPPrivateClause>(Cl);
5384 I = PC->private_copies().begin();
5385 It = PC->varlist_begin();
5386 Et = PC->varlist_end();
5387 } else if (Cl->getClauseKind() == OMPC_firstprivate) {
5388 auto *PC = cast<OMPFirstprivateClause>(Cl);
5389 I = PC->private_copies().begin();
5390 It = PC->varlist_begin();
5391 Et = PC->varlist_end();
5392 } else if (Cl->getClauseKind() == OMPC_lastprivate) {
5393 auto *PC = cast<OMPLastprivateClause>(Cl);
5394 I = PC->private_copies().begin();
5395 It = PC->varlist_begin();
5396 Et = PC->varlist_end();
5397 } else if (Cl->getClauseKind() == OMPC_linear) {
5398 auto *PC = cast<OMPLinearClause>(Cl);
5399 I = PC->privates().begin();
5400 It = PC->varlist_begin();
5401 Et = PC->varlist_end();
5402 } else if (Cl->getClauseKind() == OMPC_reduction) {
5403 auto *PC = cast<OMPReductionClause>(Cl);
5404 I = PC->privates().begin();
5405 It = PC->varlist_begin();
5406 Et = PC->varlist_end();
5407 } else if (Cl->getClauseKind() == OMPC_task_reduction) {
5408 auto *PC = cast<OMPTaskReductionClause>(Cl);
5409 I = PC->privates().begin();
5410 It = PC->varlist_begin();
5411 Et = PC->varlist_end();
5412 } else if (Cl->getClauseKind() == OMPC_in_reduction) {
5413 auto *PC = cast<OMPInReductionClause>(Cl);
5414 I = PC->privates().begin();
5415 It = PC->varlist_begin();
5416 Et = PC->varlist_end();
5417 } else {
5418 llvm_unreachable("Expected private clause.")::llvm::llvm_unreachable_internal("Expected private clause.",
"clang/lib/Sema/SemaOpenMP.cpp", 5418)
;
5419 }
5420 for (Expr *E : llvm::make_range(It, Et)) {
5421 if (!*I) {
5422 ++I;
5423 continue;
5424 }
5425 SourceLocation ELoc;
5426 SourceRange ERange;
5427 Expr *SimpleRefExpr = E;
5428 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
5429 /*AllowArraySection=*/true);
5430 DeclToCopy.try_emplace(Res.first,
5431 cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()));
5432 ++I;
5433 }
5434 }
5435 for (OMPClause *C : AllocateRange) {
5436 auto *AC = cast<OMPAllocateClause>(C);
5437 if (S.getLangOpts().OpenMP >= 50 &&
5438 !Stack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>() &&
5439 isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) &&
5440 AC->getAllocator()) {
5441 Expr *Allocator = AC->getAllocator();
5442 // OpenMP, 2.12.5 target Construct
5443 // Memory allocators that do not appear in a uses_allocators clause cannot
5444 // appear as an allocator in an allocate clause or be used in the target
5445 // region unless a requires directive with the dynamic_allocators clause
5446 // is present in the same compilation unit.
5447 AllocatorChecker Checker(Stack);
5448 if (Checker.Visit(Allocator))
5449 S.Diag(Allocator->getExprLoc(),
5450 diag::err_omp_allocator_not_in_uses_allocators)
5451 << Allocator->getSourceRange();
5452 }
5453 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
5454 getAllocatorKind(S, Stack, AC->getAllocator());
5455 // OpenMP, 2.11.4 allocate Clause, Restrictions.
5456 // For task, taskloop or target directives, allocation requests to memory
5457 // allocators with the trait access set to thread result in unspecified
5458 // behavior.
5459 if (AllocatorKind == OMPAllocateDeclAttr::OMPThreadMemAlloc &&
5460 (isOpenMPTaskingDirective(Stack->getCurrentDirective()) ||
5461 isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()))) {
5462 S.Diag(AC->getAllocator()->getExprLoc(),
5463 diag::warn_omp_allocate_thread_on_task_target_directive)
5464 << getOpenMPDirectiveName(Stack->getCurrentDirective());
5465 }
5466 for (Expr *E : AC->varlists()) {
5467 SourceLocation ELoc;
5468 SourceRange ERange;
5469 Expr *SimpleRefExpr = E;
5470 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange);
5471 ValueDecl *VD = Res.first;
5472 DSAStackTy::DSAVarData Data = Stack->getTopDSA(VD, /*FromParent=*/false);
5473 if (!isOpenMPPrivate(Data.CKind)) {
5474 S.Diag(E->getExprLoc(),
5475 diag::err_omp_expected_private_copy_for_allocate);
5476 continue;
5477 }
5478 VarDecl *PrivateVD = DeclToCopy[VD];
5479 if (checkPreviousOMPAllocateAttribute(S, Stack, E, PrivateVD,
5480 AllocatorKind, AC->getAllocator()))
5481 continue;
5482 // Placeholder until allocate clause supports align modifier.
5483 Expr *Alignment = nullptr;
5484 applyOMPAllocateAttribute(S, PrivateVD, AllocatorKind, AC->getAllocator(),
5485 Alignment, E->getSourceRange());
5486 }
5487 }
5488}
5489
5490namespace {
5491/// Rewrite statements and expressions for Sema \p Actions CurContext.
5492///
5493/// Used to wrap already parsed statements/expressions into a new CapturedStmt
5494/// context. DeclRefExpr used inside the new context are changed to refer to the
5495/// captured variable instead.
5496class CaptureVars : public TreeTransform<CaptureVars> {
5497 using BaseTransform = TreeTransform<CaptureVars>;
5498
5499public:
5500 CaptureVars(Sema &Actions) : BaseTransform(Actions) {}
5501
5502 bool AlwaysRebuild() { return true; }
5503};
5504} // namespace
5505
5506static VarDecl *precomputeExpr(Sema &Actions,
5507 SmallVectorImpl<Stmt *> &BodyStmts, Expr *E,
5508 StringRef Name) {
5509 Expr *NewE = AssertSuccess(CaptureVars(Actions).TransformExpr(E));
5510 VarDecl *NewVar = buildVarDecl(Actions, {}, NewE->getType(), Name, nullptr,
5511 dyn_cast<DeclRefExpr>(E->IgnoreImplicit()));
5512 auto *NewDeclStmt = cast<DeclStmt>(AssertSuccess(
5513 Actions.ActOnDeclStmt(Actions.ConvertDeclToDeclGroup(NewVar), {}, {})));
5514 Actions.AddInitializerToDecl(NewDeclStmt->getSingleDecl(), NewE, false);
5515 BodyStmts.push_back(NewDeclStmt);
5516 return NewVar;
5517}
5518
5519/// Create a closure that computes the number of iterations of a loop.
5520///
5521/// \param Actions The Sema object.
5522/// \param LogicalTy Type for the logical iteration number.
5523/// \param Rel Comparison operator of the loop condition.
5524/// \param StartExpr Value of the loop counter at the first iteration.
5525/// \param StopExpr Expression the loop counter is compared against in the loop
5526/// condition. \param StepExpr Amount of increment after each iteration.
5527///
5528/// \return Closure (CapturedStmt) of the distance calculation.
5529static CapturedStmt *buildDistanceFunc(Sema &Actions, QualType LogicalTy,
5530 BinaryOperator::Opcode Rel,
5531 Expr *StartExpr, Expr *StopExpr,
5532 Expr *StepExpr) {
5533 ASTContext &Ctx = Actions.getASTContext();
5534 TypeSourceInfo *LogicalTSI = Ctx.getTrivialTypeSourceInfo(LogicalTy);
5535
5536 // Captured regions currently don't support return values, we use an
5537 // out-parameter instead. All inputs are implicit captures.
5538 // TODO: Instead of capturing each DeclRefExpr occurring in
5539 // StartExpr/StopExpr/Step, these could also be passed as a value capture.
5540 QualType ResultTy = Ctx.getLValueReferenceType(LogicalTy);
5541 Sema::CapturedParamNameType Params[] = {{"Distance", ResultTy},
5542 {StringRef(), QualType()}};
5543 Actions.ActOnCapturedRegionStart({}, nullptr, CR_Default, Params);
5544
5545 Stmt *Body;
5546 {
5547 Sema::CompoundScopeRAII CompoundScope(Actions);
5548 CapturedDecl *CS = cast<CapturedDecl>(Actions.CurContext);
5549
5550 // Get the LValue expression for the result.
5551 ImplicitParamDecl *DistParam = CS->getParam(0);
5552 DeclRefExpr *DistRef = Actions.BuildDeclRefExpr(
5553 DistParam, LogicalTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5554
5555 SmallVector<Stmt *, 4> BodyStmts;
5556
5557 // Capture all referenced variable references.
5558 // TODO: Instead of computing NewStart/NewStop/NewStep inside the
5559 // CapturedStmt, we could compute them before and capture the result, to be
5560 // used jointly with the LoopVar function.
5561 VarDecl *NewStart = precomputeExpr(Actions, BodyStmts, StartExpr, ".start");
5562 VarDecl *NewStop = precomputeExpr(Actions, BodyStmts, StopExpr, ".stop");
5563 VarDecl *NewStep = precomputeExpr(Actions, BodyStmts, StepExpr, ".step");
5564 auto BuildVarRef = [&](VarDecl *VD) {
5565 return buildDeclRefExpr(Actions, VD, VD->getType(), {});
5566 };
5567
5568 IntegerLiteral *Zero = IntegerLiteral::Create(
5569 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 0), LogicalTy, {});
5570 IntegerLiteral *One = IntegerLiteral::Create(
5571 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 1), LogicalTy, {});
5572 Expr *Dist;
5573 if (Rel == BO_NE) {
5574 // When using a != comparison, the increment can be +1 or -1. This can be
5575 // dynamic at runtime, so we need to check for the direction.
5576 Expr *IsNegStep = AssertSuccess(
5577 Actions.BuildBinOp(nullptr, {}, BO_LT, BuildVarRef(NewStep), Zero));
5578
5579 // Positive increment.
5580 Expr *ForwardRange = AssertSuccess(Actions.BuildBinOp(
5581 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5582 ForwardRange = AssertSuccess(
5583 Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, ForwardRange));
5584 Expr *ForwardDist = AssertSuccess(Actions.BuildBinOp(
5585 nullptr, {}, BO_Div, ForwardRange, BuildVarRef(NewStep)));