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