Bug Summary

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

Annotated Source Code

Press '?' to see keyboard shortcuts

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