Skip to content

Commit b88ca31

Browse files
[LLVM-Flang][OpenMP] Add some semantic checks for Linear clause based on the OpenMP 5.2 restrictions
1 parent 66b2820 commit b88ca31

File tree

1 file changed

+105
-4
lines changed

1 file changed

+105
-4
lines changed

flang/lib/Semantics/check-omp-structure.cpp

Lines changed: 105 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,30 @@ void OmpStructureChecker::CheckMultListItems() {
303303
CheckMultipleOccurrence(
304304
listVars, nontempNameList, itr->second->source, "NONTEMPORAL");
305305
}
306+
307+
// Linear clause
308+
auto linearClauses{FindClauses(llvm::omp::Clause::OMPC_linear)};
309+
for (auto itr{linearClauses.first}; itr != linearClauses.second; ++itr) {
310+
const auto &linearClause{
311+
std::get<parser::OmpClause::Linear>(itr->second->u)};
312+
std::list<parser::Name> nameList;
313+
common::visit(
314+
common::visitors{
315+
[&](const parser::OmpLinearClause::WithoutModifier
316+
&withoutModifier) {
317+
for (const auto &name : withoutModifier.names) {
318+
nameList.push_back(name);
319+
}
320+
},
321+
[&](const parser::OmpLinearClause::WithModifier &withModifier) {
322+
for (const auto &name : withModifier.names) {
323+
nameList.push_back(name);
324+
}
325+
},
326+
},
327+
linearClause.v.u);
328+
CheckMultipleOccurrence(listVars, nameList, itr->second->source, "LINEAR");
329+
}
306330
}
307331

308332
bool OmpStructureChecker::HasInvalidWorksharingNesting(
@@ -2256,11 +2280,12 @@ void OmpStructureChecker::Leave(const parser::OmpClauseList &) {
22562280
}
22572281
}
22582282
}
2259-
// Sema checks related to presence of multiple list items within the same
2260-
// clause
2261-
CheckMultListItems();
22622283
} // SIMD
22632284

2285+
// Semantic checks related to presence of multiple list items within the same
2286+
// clause
2287+
CheckMultListItems();
2288+
22642289
// 2.7.3 Single Construct Restriction
22652290
if (GetContext().directive == llvm::omp::Directive::OMPD_end_single) {
22662291
CheckNotAllowedIfClause(
@@ -2975,16 +3000,92 @@ void OmpStructureChecker::Enter(const parser::OmpClause::If &x) {
29753000
void OmpStructureChecker::Enter(const parser::OmpClause::Linear &x) {
29763001
CheckAllowedClause(llvm::omp::Clause::OMPC_linear);
29773002

3003+
parser::CharBlock source{GetContext().clauseSource};
29783004
// 2.7 Loop Construct Restriction
29793005
if ((llvm::omp::allDoSet | llvm::omp::allSimdSet)
29803006
.test(GetContext().directive)) {
29813007
if (std::holds_alternative<parser::OmpLinearClause::WithModifier>(x.v.u)) {
2982-
context_.Say(GetContext().clauseSource,
3008+
context_.Say(source,
29833009
"A modifier may not be specified in a LINEAR clause "
29843010
"on the %s directive"_err_en_US,
29853011
ContextDirectiveAsFortran());
3012+
return;
29863013
}
29873014
}
3015+
3016+
auto checkForValidLinearClause = [&](const parser::Name &name, bool is_ref) {
3017+
parser::CharBlock source{GetContext().clauseSource};
3018+
std::string listItemName{name.ToString()};
3019+
if (!is_ref && !name.symbol->GetType()->IsNumeric(TypeCategory::Integer)) {
3020+
context_.Say(source,
3021+
"The list item `%s` specified with other than linear-modifier `REF`"
3022+
" must be of type INTEGER"_err_en_US,
3023+
listItemName);
3024+
}
3025+
if (GetContext().directive == llvm::omp::Directive::OMPD_declare_simd &&
3026+
!IsDummy(*name.symbol)) {
3027+
context_.Say(source,
3028+
"The list item `%s` must be a dummy argument"_err_en_US,
3029+
listItemName);
3030+
}
3031+
if (IsPointer(*name.symbol) ||
3032+
name.symbol->test(Symbol::Flag::CrayPointer)) {
3033+
context_.Say(source,
3034+
"The list item `%s` in a LINEAR clause must not be Cray Pointer "
3035+
"or a variable with POINTER attribute"_err_en_US,
3036+
listItemName);
3037+
}
3038+
if (FindCommonBlockContaining(*name.symbol)) {
3039+
context_.Say(source,
3040+
"'%s' is a common block name and must not appear in an "
3041+
"LINEAR clause"_err_en_US,
3042+
listItemName);
3043+
}
3044+
};
3045+
3046+
// OpenMP 5.2: Linear clause Restrictions
3047+
common::visit(
3048+
common::visitors{
3049+
[&](const parser::OmpLinearClause::WithoutModifier &withoutModifier) {
3050+
for (const auto &name : withoutModifier.names) {
3051+
if (name.symbol) {
3052+
checkForValidLinearClause(name, false);
3053+
}
3054+
}
3055+
},
3056+
[&](const parser::OmpLinearClause::WithModifier &withModifier) {
3057+
for (const auto &name : withModifier.names) {
3058+
if (name.symbol) {
3059+
checkForValidLinearClause(name,
3060+
(withModifier.modifier.v ==
3061+
parser::OmpLinearModifier::Type::Ref));
3062+
std::string listItemName{name.ToString()};
3063+
if (withModifier.modifier.v !=
3064+
parser::OmpLinearModifier::Type::Val &&
3065+
IsDummy(*name.symbol) && IsValue(*name.symbol)) {
3066+
context_.Say(source,
3067+
"The list item `%s` specified with the linear-modifier "
3068+
"`REF` or `UVAL` must be a dummy argument without "
3069+
"`VALUE` attribute"_err_en_US,
3070+
listItemName);
3071+
}
3072+
if (withModifier.modifier.v ==
3073+
parser::OmpLinearModifier::Type::Ref &&
3074+
!(IsAllocatable(*name.symbol) ||
3075+
IsAssumedShape(*name.symbol) ||
3076+
IsPolymorphic(*name.symbol))) {
3077+
context_.Say(source,
3078+
"The list item `%s` specified with the linear-modifier "
3079+
"`REF` must be polymorphic variable, assumed-shape "
3080+
"array, "
3081+
"or a variable with the `ALLOCATABLE` attribute"_err_en_US,
3082+
listItemName);
3083+
}
3084+
}
3085+
}
3086+
},
3087+
},
3088+
x.v.u);
29883089
}
29893090

29903091
void OmpStructureChecker::CheckAllowedMapTypes(

0 commit comments

Comments
 (0)