FLANG
check-omp-structure.h
1//===-- lib/Semantics/check-omp-structure.h ---------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9// OpenMP structure validity check list
10// 1. invalid clauses on directive
11// 2. invalid repeated clauses on directive
12// 3. TODO: invalid nesting of regions
13
14#ifndef FORTRAN_SEMANTICS_CHECK_OMP_STRUCTURE_H_
15#define FORTRAN_SEMANTICS_CHECK_OMP_STRUCTURE_H_
16
17#include "check-directive-structure.h"
18#include "flang/Common/enum-set.h"
19#include "flang/Parser/parse-tree.h"
20#include "flang/Semantics/openmp-directive-sets.h"
21#include "flang/Semantics/semantics.h"
22
23using OmpClauseSet =
25
26#define GEN_FLANG_DIRECTIVE_CLAUSE_SETS
27#include "llvm/Frontend/OpenMP/OMP.inc"
28
29namespace llvm {
30namespace omp {
31static OmpClauseSet privateSet{
32 Clause::OMPC_private, Clause::OMPC_firstprivate, Clause::OMPC_lastprivate};
33static OmpClauseSet privateReductionSet{
34 OmpClauseSet{Clause::OMPC_reduction} | privateSet};
35// omp.td cannot differentiate allowed/not allowed clause list for few
36// directives for fortran. nowait is not allowed on begin directive clause list
37// for below list of directives. Directives with conflicting list of clauses are
38// included in below list.
39static const OmpDirectiveSet noWaitClauseNotAllowedSet{
40 Directive::OMPD_do,
41 Directive::OMPD_do_simd,
42 Directive::OMPD_sections,
43 Directive::OMPD_single,
44 Directive::OMPD_workshare,
45};
46} // namespace omp
47} // namespace llvm
48
49namespace Fortran::semantics {
50struct AnalyzedCondStmt;
51
52namespace omp {
53struct LoopSequence;
54}
55
56// Mapping from 'Symbol' to 'Source' to keep track of the variables
57// used in multiple clauses
58using SymbolSourceMap = std::multimap<const Symbol *, parser::CharBlock>;
59// Multimap to check the triple <current_dir, enclosing_dir, enclosing_clause>
60using DirectivesClauseTriple = std::multimap<llvm::omp::Directive,
61 std::pair<llvm::omp::Directive, const OmpClauseSet>>;
62
63using OmpStructureCheckerBase = DirectiveStructureChecker<llvm::omp::Directive,
64 llvm::omp::Clause, parser::OmpClause, llvm::omp::Clause_enumSize>;
65
66class OmpStructureChecker : public OmpStructureCheckerBase {
67public:
68 using Base = OmpStructureCheckerBase;
69
70 OmpStructureChecker(SemanticsContext &context);
71
72 using llvmOmpClause = const llvm::omp::Clause;
73
74 bool Enter(const parser::MainProgram &);
75 void Leave(const parser::MainProgram &);
76 bool Enter(const parser::BlockData &);
77 void Leave(const parser::BlockData &);
78 bool Enter(const parser::Module &);
79 void Leave(const parser::Module &);
80 bool Enter(const parser::Submodule &);
81 void Leave(const parser::Submodule &);
82 bool Enter(const parser::SubroutineStmt &);
83 bool Enter(const parser::EndSubroutineStmt &);
84 bool Enter(const parser::FunctionStmt &);
85 bool Enter(const parser::EndFunctionStmt &);
86 bool Enter(const parser::BlockConstruct &);
87 void Leave(const parser::BlockConstruct &);
88
89 void Enter(const parser::SpecificationPart &);
90 void Leave(const parser::SpecificationPart &);
91 void Enter(const parser::ExecutionPart &);
92 void Leave(const parser::ExecutionPart &);
93
94 void Enter(const parser::OpenMPConstruct &);
95 void Leave(const parser::OpenMPConstruct &);
96 void Enter(const parser::OpenMPInteropConstruct &);
97 void Leave(const parser::OpenMPInteropConstruct &);
98 void Enter(const parser::OpenMPDeclarativeConstruct &);
99 void Leave(const parser::OpenMPDeclarativeConstruct &);
100
101 void Enter(const parser::OpenMPMisplacedEndDirective &);
102 void Leave(const parser::OpenMPMisplacedEndDirective &);
103 void Enter(const parser::OpenMPInvalidDirective &);
104 void Leave(const parser::OpenMPInvalidDirective &);
105
106 void Enter(const parser::OpenMPLoopConstruct &);
107 void Leave(const parser::OpenMPLoopConstruct &);
108 void Enter(const parser::OmpEndLoopDirective &);
109 void Leave(const parser::OmpEndLoopDirective &);
110
111 void Enter(const parser::OpenMPAssumeConstruct &);
112 void Leave(const parser::OpenMPAssumeConstruct &);
113 void Enter(const parser::OpenMPDeclarativeAssumes &);
114 void Leave(const parser::OpenMPDeclarativeAssumes &);
115 void Enter(const parser::OmpBlockConstruct &);
116 void Leave(const parser::OmpBlockConstruct &);
117 void Leave(const parser::OmpBeginDirective &);
118 void Enter(const parser::OmpEndDirective &);
119 void Leave(const parser::OmpEndDirective &);
120
121 void Enter(const parser::OpenMPSectionsConstruct &);
122 void Leave(const parser::OpenMPSectionsConstruct &);
123 void Enter(const parser::OmpEndSectionsDirective &);
124 void Leave(const parser::OmpEndSectionsDirective &);
125
126 void Enter(const parser::OmpDeclareVariantDirective &);
127 void Leave(const parser::OmpDeclareVariantDirective &);
128 void Enter(const parser::OpenMPDeclareSimdConstruct &);
129 void Leave(const parser::OpenMPDeclareSimdConstruct &);
130 void Enter(const parser::OmpAllocateDirective &);
131 void Leave(const parser::OmpAllocateDirective &);
132 void Enter(const parser::OpenMPDeclareMapperConstruct &);
133 void Leave(const parser::OpenMPDeclareMapperConstruct &);
134 void Enter(const parser::OpenMPDeclareReductionConstruct &);
135 void Leave(const parser::OpenMPDeclareReductionConstruct &);
136 void Enter(const parser::OpenMPDeclareTargetConstruct &);
137 void Leave(const parser::OpenMPDeclareTargetConstruct &);
138 void Enter(const parser::OpenMPDepobjConstruct &);
139 void Leave(const parser::OpenMPDepobjConstruct &);
140 void Enter(const parser::OpenMPDispatchConstruct &);
141 void Leave(const parser::OpenMPDispatchConstruct &);
142 void Enter(const parser::OmpErrorDirective &);
143 void Leave(const parser::OmpErrorDirective &);
144 void Enter(const parser::OmpNothingDirective &);
145 void Leave(const parser::OmpNothingDirective &);
146 void Enter(const parser::OpenMPAllocatorsConstruct &);
147 void Leave(const parser::OpenMPAllocatorsConstruct &);
148 void Enter(const parser::OpenMPRequiresConstruct &);
149 void Leave(const parser::OpenMPRequiresConstruct &);
150 void Enter(const parser::OpenMPGroupprivate &);
151 void Leave(const parser::OpenMPGroupprivate &);
152 void Enter(const parser::OpenMPThreadprivate &);
153 void Leave(const parser::OpenMPThreadprivate &);
154
155 void Enter(const parser::OpenMPSimpleStandaloneConstruct &);
156 void Leave(const parser::OpenMPSimpleStandaloneConstruct &);
157 void Enter(const parser::OpenMPFlushConstruct &);
158 void Leave(const parser::OpenMPFlushConstruct &);
159 void Enter(const parser::OpenMPCancelConstruct &);
160 void Leave(const parser::OpenMPCancelConstruct &);
163 void Enter(const parser::OpenMPCriticalConstruct &);
164 void Leave(const parser::OpenMPCriticalConstruct &);
165 void Enter(const parser::OpenMPAtomicConstruct &);
166 void Leave(const parser::OpenMPAtomicConstruct &);
167
168 void Leave(const parser::OmpClauseList &);
169 void Enter(const parser::OmpClause &);
170
171 void Enter(const parser::DoConstruct &);
172 void Leave(const parser::DoConstruct &);
173
174 void Enter(const parser::OmpDirectiveSpecification &);
175 void Leave(const parser::OmpDirectiveSpecification &);
176
177 void Enter(const parser::OmpMetadirectiveDirective &);
178 void Leave(const parser::OmpMetadirectiveDirective &);
179
180 void Enter(const parser::OmpContextSelector &);
181 void Leave(const parser::OmpContextSelector &);
182
183#define GEN_FLANG_CLAUSE_CHECK_ENTER
184#include "llvm/Frontend/OpenMP/OMP.inc"
185
186private:
187 bool CheckAllowedClause(llvmOmpClause clause);
188 void CheckVariableListItem(const SymbolSourceMap &symbols);
189 void CheckDirectiveSpelling(
190 parser::CharBlock spelling, llvm::omp::Directive id);
191 void AnalyzeObject(const parser::OmpObject &object);
192 void AnalyzeObjects(const parser::OmpObjectList &objects);
193 void CheckMultipleOccurrence(semantics::UnorderedSymbolSet &listVars,
194 const std::list<parser::Name> &nameList, const parser::CharBlock &item,
195 const std::string &clauseName);
196 void CheckMultListItems();
197 void CheckStructureComponent(
198 const parser::OmpObjectList &objects, llvm::omp::Clause clauseId);
199 bool HasInvalidWorksharingNesting(
200 const parser::OmpDirectiveName &name, const OmpDirectiveSet &);
201
202 bool IsCloselyNestedRegion(const OmpDirectiveSet &set);
203 bool IsNestedInDirective(llvm::omp::Directive directive);
204 bool IsCombinedParallelWorksharing(llvm::omp::Directive directive) const;
205 bool InTargetRegion();
206 void HasInvalidTeamsNesting(
207 const llvm::omp::Directive &dir, const parser::CharBlock &source);
208 void HasInvalidDistributeNesting(const parser::OpenMPLoopConstruct &x);
209 void HasInvalidLoopBinding(const parser::OpenMPLoopConstruct &x);
210 bool HasRequires(llvm::omp::Clause req);
211 // specific clause related
212 void CheckAllowedMapTypes(
213 parser::OmpMapType::Value, llvm::ArrayRef<parser::OmpMapType::Value>);
214
215 const std::list<parser::OmpTraitProperty> &GetTraitPropertyList(
217 std::optional<llvm::omp::Clause> GetClauseFromProperty(
219
220 void CheckTraitSelectorList(const std::list<parser::OmpTraitSelector> &);
221 void CheckTraitSetSelector(const parser::OmpTraitSetSelector &);
222 void CheckTraitScore(const parser::OmpTraitScore &);
223 bool VerifyTraitPropertyLists(
225 void CheckTraitSelector(
227 void CheckTraitADMO(
229 void CheckTraitCondition(
231 void CheckTraitDeviceNum(
233 void CheckTraitRequires(
235 void CheckTraitSimd(
237
238 llvm::StringRef getClauseName(llvm::omp::Clause clause) override;
239 llvm::StringRef getDirectiveName(llvm::omp::Directive directive) override;
240
241 template < //
242 typename LessTy, typename RangeTy,
243 typename IterTy = decltype(std::declval<RangeTy>().begin())>
244 std::optional<IterTy> FindDuplicate(RangeTy &&);
245
246 void CheckDependList(const parser::DataRef &);
247 void CheckDependArraySection(
249 void CheckDoacross(const parser::OmpDoacross &doa);
250 void CheckDimsModifier(parser::CharBlock source, size_t numValues,
251 const parser::OmpDimsModifier &x);
252 bool IsDataRefTypeParamInquiry(const parser::DataRef *dataRef);
253 void CheckVarIsNotPartOfAnotherVar(const parser::CharBlock &source,
254 const parser::OmpObject &obj, llvm::StringRef clause = "");
255 void CheckVarIsNotPartOfAnotherVar(const parser::CharBlock &source,
256 const parser::OmpObjectList &objList, llvm::StringRef clause = "");
257 void CheckThreadprivateOrDeclareTargetVar(const parser::Designator &);
258 void CheckThreadprivateOrDeclareTargetVar(const parser::Name &);
259 void CheckThreadprivateOrDeclareTargetVar(const parser::OmpObject &);
260 void CheckThreadprivateOrDeclareTargetVar(const parser::OmpObjectList &);
261 void CheckSymbolName(
262 const parser::CharBlock &source, const parser::OmpObject &object);
263 void CheckSymbolNames(
264 const parser::CharBlock &source, const parser::OmpObjectList &objList);
265 void CheckIntentInPointer(SymbolSourceMap &, const llvm::omp::Clause);
266 void CheckAssumedSizeArray(SymbolSourceMap &, const llvm::omp::Clause);
267 void CheckProcedurePointer(SymbolSourceMap &, const llvm::omp::Clause);
268 void CheckCrayPointee(const parser::OmpObjectList &objectList,
269 llvm::StringRef clause, bool suggestToUseCrayPointer = true);
270 void GetSymbolsInObjectList(const parser::OmpObjectList &, SymbolSourceMap &);
271 void CheckDefinableObjects(SymbolSourceMap &, const llvm::omp::Clause);
272 void CheckCopyingPolymorphicAllocatable(
273 SymbolSourceMap &, const llvm::omp::Clause);
274 void CheckPrivateSymbolsInOuterCxt(
275 SymbolSourceMap &, DirectivesClauseTriple &, const llvm::omp::Clause);
276 const parser::Name GetLoopIndex(const parser::DoConstruct *x);
277 void SetLoopInfo(const parser::OpenMPLoopConstruct &x);
278 void CheckIsLoopIvPartOfClause(
279 llvmOmpClause clause, const parser::OmpObjectList &ompObjectList);
280 bool CheckTargetBlockOnlyTeams(const parser::Block &);
281 void CheckWorkshareBlockStmts(const parser::Block &, parser::CharBlock);
282 void CheckWorkdistributeBlockStmts(const parser::Block &, parser::CharBlock);
283 void CheckIndividualAllocateDirective(
284 const parser::OmpAllocateDirective &x, bool isExecutable);
285 void CheckExecutableAllocateDirective(const parser::OmpAllocateDirective &x);
286
287 void CheckIteratorRange(const parser::OmpIteratorSpecifier &x);
288 void CheckIteratorModifier(const parser::OmpIterator &x);
289 void CheckIterationVariableType(const parser::OpenMPLoopConstruct &x);
290 void CheckDoWhile(const parser::OpenMPLoopConstruct &x);
291 void CheckAssociatedLoopConstraints(const parser::OpenMPLoopConstruct &x);
292 template <typename T, typename D> bool IsOperatorValid(const T &, const D &);
293
294 void CheckStorageOverlap(const evaluate::Expr<evaluate::SomeType> &,
296 void ErrorShouldBeVariable(const MaybeExpr &expr, parser::CharBlock source);
297 void CheckAtomicType(SymbolRef sym, parser::CharBlock source,
298 std::string_view name, bool checkTypeOnPointer = true);
299 void CheckAtomicVariable(const evaluate::Expr<evaluate::SomeType> &,
300 parser::CharBlock, bool checkTypeOnPointer = true);
301 std::pair<const parser::ExecutionPartConstruct *,
303 CheckUpdateCapture(const parser::ExecutionPartConstruct *ec1,
305 void CheckAtomicCaptureAssignment(const evaluate::Assignment &capture,
306 const SomeExpr &atom, parser::CharBlock source);
307 void CheckAtomicReadAssignment(
308 const evaluate::Assignment &read, parser::CharBlock source);
309 void CheckAtomicWriteAssignment(
310 const evaluate::Assignment &write, parser::CharBlock source);
311 std::optional<evaluate::Assignment> CheckAtomicUpdateAssignment(
312 const evaluate::Assignment &update, parser::CharBlock source);
313 std::pair<bool, bool> CheckAtomicUpdateAssignmentRhs(const SomeExpr &atom,
314 const SomeExpr &rhs, parser::CharBlock source, bool suppressDiagnostics);
315 void CheckAtomicConditionalUpdateAssignment(const SomeExpr &cond,
316 parser::CharBlock condSource, const evaluate::Assignment &assign,
317 parser::CharBlock assignSource);
318 void CheckAtomicConditionalUpdateStmt(
319 const AnalyzedCondStmt &update, parser::CharBlock source);
320 void CheckAtomicUpdateOnly(const parser::OpenMPAtomicConstruct &x,
321 const parser::Block &body, parser::CharBlock source);
322 void CheckAtomicConditionalUpdate(const parser::OpenMPAtomicConstruct &x,
323 const parser::Block &body, parser::CharBlock source);
324 void CheckAtomicUpdateCapture(const parser::OpenMPAtomicConstruct &x,
325 const parser::Block &body, parser::CharBlock source);
326 void CheckAtomicConditionalUpdateCapture(
327 const parser::OpenMPAtomicConstruct &x, const parser::Block &body,
328 parser::CharBlock source);
329 void CheckAtomicRead(const parser::OpenMPAtomicConstruct &x);
330 void CheckAtomicWrite(const parser::OpenMPAtomicConstruct &x);
331 void CheckAtomicUpdate(const parser::OpenMPAtomicConstruct &x);
332
333 void CheckScanModifier(const parser::OmpClause::Reduction &x);
334 void CheckDistLinear(const parser::OpenMPLoopConstruct &x);
335 void CheckSIMDNest(const parser::OpenMPConstruct &x);
336 void CheckRectangularNest(const parser::OmpDirectiveSpecification &spec,
337 const omp::LoopSequence &nest);
338 void CheckNestedConstruct(const parser::OpenMPLoopConstruct &x);
339 void CheckTargetNest(const parser::OpenMPConstruct &x);
340 void CheckTargetUpdate();
341 void CheckTaskgraph(const parser::OmpBlockConstruct &x);
342 void CheckDependenceType(const parser::OmpDependenceType::Value &x);
343 void CheckTaskDependenceType(const parser::OmpTaskDependenceType::Value &x);
344 std::optional<llvm::omp::Directive> GetCancelType(
345 llvm::omp::Directive cancelDir, const parser::CharBlock &cancelSource,
346 const std::optional<parser::OmpClauseList> &maybeClauses);
347 void CheckCancellationNest(
348 const parser::CharBlock &source, llvm::omp::Directive type);
349 std::int64_t GetOrdCollapseLevel(const parser::OpenMPLoopConstruct &x);
350 void CheckReductionObjects(
351 const parser::OmpObjectList &objects, llvm::omp::Clause clauseId);
352 bool CheckReductionOperator(const parser::OmpReductionIdentifier &ident,
353 parser::CharBlock source, llvm::omp::Clause clauseId);
354 void CheckReductionObjectTypes(const parser::OmpObjectList &objects,
355 const parser::OmpReductionIdentifier &ident);
356 void CheckReductionModifier(const parser::OmpReductionModifier &);
357 void CheckLastprivateModifier(const parser::OmpLastprivateModifier &);
358 void CheckMasterNesting(const parser::OmpBlockConstruct &x);
359 void ChecksOnOrderedAsBlock();
360 void CheckBarrierNesting(const parser::OpenMPSimpleStandaloneConstruct &x);
361 void CheckScan(const parser::OpenMPSimpleStandaloneConstruct &x);
362 void ChecksOnOrderedAsStandalone();
363 void CheckOrderedDependClause(std::optional<std::int64_t> orderedValue);
364 void CheckReductionArraySection(
365 const parser::OmpObjectList &ompObjectList, llvm::omp::Clause clauseId);
366 void CheckArraySection(const parser::ArrayElement &arrayElement,
367 const parser::Name &name, const llvm::omp::Clause clause);
368 void CheckLastPartRefForArraySection(
369 const parser::Designator &designator, llvm::omp::Clause clauseId);
370 void CheckSharedBindingInOuterContext(
371 const parser::OmpObjectList &ompObjectList);
372 void CheckIfContiguous(const parser::OmpObject &object);
373 const parser::Name *GetObjectName(const parser::OmpObject &object);
374 void CheckInitOnDepobj(const parser::OpenMPDepobjConstruct &depobj,
375 const parser::OmpClause &initClause);
376
377 void CheckAllowedRequiresClause(llvmOmpClause clause);
378 bool deviceConstructFound_{false};
379
380 void AddEndDirectiveClauses(const parser::OmpClauseList &clauses);
381
382 void EnterDirectiveNest(const int index) { directiveNest_[index]++; }
383 void ExitDirectiveNest(const int index) { directiveNest_[index]--; }
384 int GetDirectiveNest(const int index) { return directiveNest_[index]; }
385 inline void ErrIfAllocatableVariable(const parser::Variable &);
386 inline void ErrIfLHSAndRHSSymbolsMatch(
387 const parser::Variable &, const parser::Expr &);
388 inline void ErrIfNonScalarAssignmentStmt(
389 const parser::Variable &, const parser::Expr &);
390 enum directiveNestType : int {
391 SIMDNest,
392 TargetBlockOnlyTeams,
393 TargetNest,
394 DeclarativeNest,
395 ContextSelectorNest,
396 MetadirectiveNest,
397 LastType = MetadirectiveNest,
398 };
399 int directiveNest_[LastType + 1] = {0};
400
401 int allocateDirectiveLevel{0};
402 parser::CharBlock visitedAtomicSource_;
403 SymbolSourceMap deferredNonVariables_;
404
405 using LoopConstruct = std::variant<const parser::DoConstruct *,
407 std::vector<LoopConstruct> loopStack_;
408 // Scopes for scoping units.
409 std::vector<const Scope *> scopeStack_;
410
411 enum class PartKind : int {
412 // There are also other "parts", such as internal-subprogram-part, etc,
413 // but we're keeping track of these two for now.
414 SpecificationPart,
415 ExecutionPart,
416 };
417 std::vector<PartKind> partStack_;
418};
419
422template <typename LessTy, typename RangeTy, typename IterTy>
423std::optional<IterTy> OmpStructureChecker::FindDuplicate(RangeTy &&range) {
424 // Deal with iterators, since the actual elements may be rvalues (i.e.
425 // have no addresses), for example with custom-constructed ranges that
426 // are not simple c.begin()..c.end().
427 std::set<IterTy, LessTy> uniq;
428 for (auto it{range.begin()}, end{range.end()}; it != end; ++it) {
429 if (!uniq.insert(it).second) {
430 return it;
431 }
432 }
433 return std::nullopt;
434}
435
436} // namespace Fortran::semantics
437#endif // FORTRAN_SEMANTICS_CHECK_OMP_STRUCTURE_H_
Definition enum-set.h:28
Definition indirection.h:31
Definition expression.h:908
Definition common.h:215
Definition char-block.h:28
Definition check-directive-structure.h:208
Definition semantics.h:67
Definition FIRType.h:103
Definition parse-tree.h:1896
Definition parse-tree.h:2180
Definition parse-tree.h:3018
Definition parse-tree.h:1806
Definition parse-tree.h:1845
Definition parse-tree.h:2323
Definition parse-tree.h:554
Definition parse-tree.h:1693
Definition parse-tree.h:3137
Definition parse-tree.h:2927
Definition parse-tree.h:2962
Definition parse-tree.h:587
Definition parse-tree.h:5278
Definition parse-tree.h:5072
Definition parse-tree.h:5082
Definition parse-tree.h:5041
Definition parse-tree.h:5025
Definition parse-tree.h:3492
Definition parse-tree.h:5048
Definition parse-tree.h:4472
Definition parse-tree.h:5077
Definition parse-tree.h:5419
Definition parse-tree.h:5148
Definition parse-tree.h:5110
Definition parse-tree.h:5095
Definition parse-tree.h:5104
Definition parse-tree.h:3537
Definition parse-tree.h:3525
Definition parse-tree.h:3581
Definition parse-tree.h:5304
Definition parse-tree.h:5137
Definition parse-tree.h:5309
Definition parse-tree.h:5346
Definition parse-tree.h:5450
Definition parse-tree.h:5294
Definition parse-tree.h:5125
Definition parse-tree.h:5357
Definition parse-tree.h:5371
Definition parse-tree.h:5387
Definition parse-tree.h:5233
Definition parse-tree.h:5395
Definition parse-tree.h:5468
Definition parse-tree.h:5424
Definition parse-tree.h:5239
Definition parse-tree.h:5163
Definition parse-tree.h:5245
Definition parse-tree.h:451
Definition parse-tree.h:3004
Definition parse-tree.h:3156
Definition parse-tree.h:1853
Definition parse-tree.h:3974
Definition parse-tree.h:4040
Definition parse-tree.h:4050
Definition parse-tree.h:4058
Definition parse-tree.h:4199
Definition parse-tree.h:3727
Definition parse-tree.h:3693
Definition parse-tree.h:3766
Definition parse-tree.h:3788
Definition check-omp-atomic.cpp:242
Definition openmp-utils.h:245