Bug Summary

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