Bug Summary

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