Bug Summary

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

Annotated Source Code

Press '?' to see keyboard shortcuts

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