1 //===-- lib/Semantics/check-omp-structure.h ---------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
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
14 #ifndef FORTRAN_SEMANTICS_CHECK_OMP_STRUCTURE_H_
15 #define FORTRAN_SEMANTICS_CHECK_OMP_STRUCTURE_H_
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 #include "llvm/Frontend/OpenMP/OMPConstants.h"
25 Fortran::common::EnumSet
<llvm::omp::Clause
, llvm::omp::Clause_enumSize
>;
27 #define GEN_FLANG_DIRECTIVE_CLAUSE_SETS
28 #include "llvm/Frontend/OpenMP/OMP.inc"
32 static OmpClauseSet privateSet
{
33 Clause::OMPC_private
, Clause::OMPC_firstprivate
, Clause::OMPC_lastprivate
};
34 static OmpClauseSet privateReductionSet
{
35 OmpClauseSet
{Clause::OMPC_reduction
} | privateSet
};
36 // omp.td cannot differentiate allowed/not allowed clause list for few
37 // directives for fortran. nowait is not allowed on begin directive clause list
38 // for below list of directives. Directives with conflicting list of clauses are
39 // included in below list.
40 static const OmpDirectiveSet noWaitClauseNotAllowedSet
{
42 Directive::OMPD_do_simd
,
43 Directive::OMPD_sections
,
44 Directive::OMPD_single
,
49 namespace Fortran::semantics
{
51 // Mapping from 'Symbol' to 'Source' to keep track of the variables
52 // used in multiple clauses
53 using SymbolSourceMap
= std::multimap
<const Symbol
*, parser::CharBlock
>;
54 // Multimap to check the triple <current_dir, enclosing_dir, enclosing_clause>
55 using DirectivesClauseTriple
= std::multimap
<llvm::omp::Directive
,
56 std::pair
<llvm::omp::Directive
, const OmpClauseSet
>>;
58 class OmpStructureChecker
59 : public DirectiveStructureChecker
<llvm::omp::Directive
, llvm::omp::Clause
,
60 parser::OmpClause
, llvm::omp::Clause_enumSize
> {
62 OmpStructureChecker(SemanticsContext
&context
)
63 : DirectiveStructureChecker(context
,
64 #define GEN_FLANG_DIRECTIVE_CLAUSE_MAP
65 #include "llvm/Frontend/OpenMP/OMP.inc"
68 using llvmOmpClause
= const llvm::omp::Clause
;
70 void Enter(const parser::OpenMPConstruct
&);
71 void Enter(const parser::OpenMPLoopConstruct
&);
72 void Leave(const parser::OpenMPLoopConstruct
&);
73 void Enter(const parser::OmpEndLoopDirective
&);
74 void Leave(const parser::OmpEndLoopDirective
&);
76 void Enter(const parser::OpenMPBlockConstruct
&);
77 void Leave(const parser::OpenMPBlockConstruct
&);
78 void Leave(const parser::OmpBeginBlockDirective
&);
79 void Enter(const parser::OmpEndBlockDirective
&);
80 void Leave(const parser::OmpEndBlockDirective
&);
82 void Enter(const parser::OpenMPSectionsConstruct
&);
83 void Leave(const parser::OpenMPSectionsConstruct
&);
84 void Enter(const parser::OmpEndSectionsDirective
&);
85 void Leave(const parser::OmpEndSectionsDirective
&);
87 void Enter(const parser::OpenMPDeclareSimdConstruct
&);
88 void Leave(const parser::OpenMPDeclareSimdConstruct
&);
89 void Enter(const parser::OpenMPDeclarativeAllocate
&);
90 void Leave(const parser::OpenMPDeclarativeAllocate
&);
91 void Enter(const parser::OpenMPDeclareTargetConstruct
&);
92 void Leave(const parser::OpenMPDeclareTargetConstruct
&);
93 void Enter(const parser::OmpDeclareTargetWithList
&);
94 void Enter(const parser::OmpDeclareTargetWithClause
&);
95 void Leave(const parser::OmpDeclareTargetWithClause
&);
96 void Enter(const parser::OpenMPExecutableAllocate
&);
97 void Leave(const parser::OpenMPExecutableAllocate
&);
98 void Enter(const parser::OpenMPAllocatorsConstruct
&);
99 void Leave(const parser::OpenMPAllocatorsConstruct
&);
100 void Enter(const parser::OpenMPRequiresConstruct
&);
101 void Leave(const parser::OpenMPRequiresConstruct
&);
102 void Enter(const parser::OpenMPThreadprivate
&);
103 void Leave(const parser::OpenMPThreadprivate
&);
105 void Enter(const parser::OpenMPSimpleStandaloneConstruct
&);
106 void Leave(const parser::OpenMPSimpleStandaloneConstruct
&);
107 void Enter(const parser::OpenMPFlushConstruct
&);
108 void Leave(const parser::OpenMPFlushConstruct
&);
109 void Enter(const parser::OpenMPCancelConstruct
&);
110 void Leave(const parser::OpenMPCancelConstruct
&);
111 void Enter(const parser::OpenMPCancellationPointConstruct
&);
112 void Leave(const parser::OpenMPCancellationPointConstruct
&);
113 void Enter(const parser::OpenMPCriticalConstruct
&);
114 void Leave(const parser::OpenMPCriticalConstruct
&);
115 void Enter(const parser::OpenMPAtomicConstruct
&);
116 void Leave(const parser::OpenMPAtomicConstruct
&);
118 void Leave(const parser::OmpClauseList
&);
119 void Enter(const parser::OmpClause
&);
121 void Enter(const parser::OmpAtomicRead
&);
122 void Leave(const parser::OmpAtomicRead
&);
123 void Enter(const parser::OmpAtomicWrite
&);
124 void Leave(const parser::OmpAtomicWrite
&);
125 void Enter(const parser::OmpAtomicUpdate
&);
126 void Leave(const parser::OmpAtomicUpdate
&);
127 void Enter(const parser::OmpAtomicCapture
&);
128 void Leave(const parser::OmpAtomic
&);
130 #define GEN_FLANG_CLAUSE_CHECK_ENTER
131 #include "llvm/Frontend/OpenMP/OMP.inc"
133 // Get the OpenMP Clause Kind for the corresponding Parser class
134 template <typename A
>
135 llvm::omp::Clause
GetClauseKindForParserClass(const A
&) {
136 #define GEN_FLANG_CLAUSE_PARSER_KIND_MAP
137 #include "llvm/Frontend/OpenMP/OMP.inc"
141 void CheckMultipleOccurrence(semantics::UnorderedSymbolSet
&listVars
,
142 const std::list
<parser::Name
> &nameList
, const parser::CharBlock
&item
,
143 const std::string
&clauseName
);
144 void CheckMultListItems();
145 void CheckStructureElement(const parser::OmpObjectList
&ompObjectList
,
146 const llvm::omp::Clause clause
);
147 bool HasInvalidWorksharingNesting(
148 const parser::CharBlock
&, const OmpDirectiveSet
&);
149 bool IsCloselyNestedRegion(const OmpDirectiveSet
&set
);
150 void HasInvalidTeamsNesting(
151 const llvm::omp::Directive
&dir
, const parser::CharBlock
&source
);
152 void HasInvalidDistributeNesting(const parser::OpenMPLoopConstruct
&x
);
153 // specific clause related
154 bool ScheduleModifierHasType(const parser::OmpScheduleClause
&,
155 const parser::OmpScheduleModifierType::ModType
&);
156 void CheckAllowedMapTypes(const parser::OmpMapType::Type
&,
157 const std::list
<parser::OmpMapType::Type
> &);
158 llvm::StringRef
getClauseName(llvm::omp::Clause clause
) override
;
159 llvm::StringRef
getDirectiveName(llvm::omp::Directive directive
) override
;
161 void CheckDependList(const parser::DataRef
&);
162 void CheckDependArraySection(
163 const common::Indirection
<parser::ArrayElement
> &, const parser::Name
&);
164 bool IsDataRefTypeParamInquiry(const parser::DataRef
*dataRef
);
165 void CheckIsVarPartOfAnotherVar(
166 const parser::CharBlock
&source
, const parser::OmpObjectList
&objList
);
167 void CheckThreadprivateOrDeclareTargetVar(
168 const parser::OmpObjectList
&objList
);
169 void CheckSymbolNames(
170 const parser::CharBlock
&source
, const parser::OmpObjectList
&objList
);
171 void CheckIntentInPointer(
172 const parser::OmpObjectList
&, const llvm::omp::Clause
);
173 void GetSymbolsInObjectList(const parser::OmpObjectList
&, SymbolSourceMap
&);
174 void CheckDefinableObjects(SymbolSourceMap
&, const llvm::omp::Clause
);
175 void CheckCopyingPolymorphicAllocatable(
176 SymbolSourceMap
&, const llvm::omp::Clause
);
177 void CheckPrivateSymbolsInOuterCxt(
178 SymbolSourceMap
&, DirectivesClauseTriple
&, const llvm::omp::Clause
);
179 const parser::Name
GetLoopIndex(const parser::DoConstruct
*x
);
180 void SetLoopInfo(const parser::OpenMPLoopConstruct
&x
);
181 void CheckIsLoopIvPartOfClause(
182 llvmOmpClause clause
, const parser::OmpObjectList
&ompObjectList
);
183 bool CheckTargetBlockOnlyTeams(const parser::Block
&);
184 void CheckWorkshareBlockStmts(const parser::Block
&, parser::CharBlock
);
186 void CheckLoopItrVariableIsInt(const parser::OpenMPLoopConstruct
&x
);
187 void CheckDoWhile(const parser::OpenMPLoopConstruct
&x
);
188 void CheckCycleConstraints(const parser::OpenMPLoopConstruct
&x
);
189 template <typename T
, typename D
> bool IsOperatorValid(const T
&, const D
&);
190 void CheckAtomicMemoryOrderClause(
191 const parser::OmpAtomicClauseList
*, const parser::OmpAtomicClauseList
*);
192 void CheckAtomicUpdateStmt(const parser::AssignmentStmt
&);
193 void CheckAtomicCaptureStmt(const parser::AssignmentStmt
&);
194 void CheckAtomicWriteStmt(const parser::AssignmentStmt
&);
195 void CheckAtomicConstructStructure(const parser::OpenMPAtomicConstruct
&);
196 void CheckDistLinear(const parser::OpenMPLoopConstruct
&x
);
197 void CheckSIMDNest(const parser::OpenMPConstruct
&x
);
198 void CheckTargetNest(const parser::OpenMPConstruct
&x
);
199 void CheckTargetUpdate();
200 void CheckCancellationNest(
201 const parser::CharBlock
&source
, const parser::OmpCancelType::Type
&type
);
202 std::int64_t GetOrdCollapseLevel(const parser::OpenMPLoopConstruct
&x
);
203 bool CheckReductionOperators(const parser::OmpClause::Reduction
&);
204 bool CheckIntrinsicOperator(
205 const parser::DefinedOperator::IntrinsicOperator
&);
206 void CheckReductionTypeList(const parser::OmpClause::Reduction
&);
207 void CheckMasterNesting(const parser::OpenMPBlockConstruct
&x
);
208 void ChecksOnOrderedAsBlock();
209 void CheckBarrierNesting(const parser::OpenMPSimpleStandaloneConstruct
&x
);
210 void ChecksOnOrderedAsStandalone();
211 void CheckOrderedDependClause(std::optional
<std::int64_t> orderedValue
);
212 void CheckReductionArraySection(const parser::OmpObjectList
&ompObjectList
);
213 void CheckIntentInPointerAndDefinable(
214 const parser::OmpObjectList
&, const llvm::omp::Clause
);
215 void CheckArraySection(const parser::ArrayElement
&arrayElement
,
216 const parser::Name
&name
, const llvm::omp::Clause clause
);
217 void CheckSharedBindingInOuterContext(
218 const parser::OmpObjectList
&ompObjectList
);
219 const parser::OmpObjectList
*GetOmpObjectList(const parser::OmpClause
&);
220 void CheckPredefinedAllocatorRestriction(const parser::CharBlock
&source
,
221 const parser::OmpObjectList
&ompObjectList
);
222 void CheckPredefinedAllocatorRestriction(
223 const parser::CharBlock
&source
, const parser::Name
&name
);
224 bool isPredefinedAllocator
{false};
226 void CheckAllowedRequiresClause(llvmOmpClause clause
);
227 bool deviceConstructFound_
{false};
229 void EnterDirectiveNest(const int index
) { directiveNest_
[index
]++; }
230 void ExitDirectiveNest(const int index
) { directiveNest_
[index
]--; }
231 int GetDirectiveNest(const int index
) { return directiveNest_
[index
]; }
232 template <typename D
> void CheckHintClause(D
*, D
*);
233 inline void ErrIfAllocatableVariable(const parser::Variable
&);
234 inline void ErrIfLHSAndRHSSymbolsMatch(
235 const parser::Variable
&, const parser::Expr
&);
236 inline void ErrIfNonScalarAssignmentStmt(
237 const parser::Variable
&, const parser::Expr
&);
238 enum directiveNestType
{
240 TargetBlockOnlyTeams
,
244 int directiveNest_
[LastType
+ 1] = {0};
246 } // namespace Fortran::semantics
247 #endif // FORTRAN_SEMANTICS_CHECK_OMP_STRUCTURE_H_