Skip to content

Commit 5a4ad72

Browse files
[LLVM-Flang][OpenMP] Add some semantic checks for Linear clause based on the OpenMP 5.2 restrictions
1 parent ba5676c commit 5a4ad72

File tree

1 file changed

+105
-5
lines changed

1 file changed

+105
-5
lines changed

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

Lines changed: 105 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,30 @@ void OmpStructureChecker::CheckMultListItems() {
323323
CheckMultipleOccurrence(
324324
listVars, nontempNameList, itr->second->source, "NONTEMPORAL");
325325
}
326+
327+
// Linear clause
328+
auto linearClauses{FindClauses(llvm::omp::Clause::OMPC_linear)};
329+
for (auto itr{linearClauses.first}; itr != linearClauses.second; ++itr) {
330+
const auto &linearClause{
331+
std::get<parser::OmpClause::Linear>(itr->second->u)};
332+
std::list<parser::Name> nameList;
333+
common::visit(
334+
common::visitors{
335+
[&](const parser::OmpLinearClause::WithoutModifier
336+
&withoutModifier) {
337+
for (const auto &name : withoutModifier.names) {
338+
nameList.push_back(name);
339+
}
340+
},
341+
[&](const parser::OmpLinearClause::WithModifier &withModifier) {
342+
for (const auto &name : withModifier.names) {
343+
nameList.push_back(name);
344+
}
345+
},
346+
},
347+
linearClause.v.u);
348+
CheckMultipleOccurrence(listVars, nameList, itr->second->source, "LINEAR");
349+
}
326350
}
327351

328352
bool OmpStructureChecker::HasInvalidWorksharingNesting(
@@ -2299,12 +2323,12 @@ void OmpStructureChecker::Leave(const parser::OmpClauseList &) {
22992323
}
23002324
}
23012325
}
2302-
2303-
// Sema checks related to presence of multiple list items within the same
2304-
// clause
2305-
CheckMultListItems();
23062326
} // SIMD
23072327

2328+
// Semantic checks related to presence of multiple list items within the same
2329+
// clause
2330+
CheckMultListItems();
2331+
23082332
// 2.7.3 Single Construct Restriction
23092333
if (GetContext().directive == llvm::omp::Directive::OMPD_end_single) {
23102334
CheckNotAllowedIfClause(
@@ -3040,16 +3064,92 @@ void OmpStructureChecker::Enter(const parser::OmpClause::If &x) {
30403064
void OmpStructureChecker::Enter(const parser::OmpClause::Linear &x) {
30413065
CheckAllowedClause(llvm::omp::Clause::OMPC_linear);
30423066

3067+
parser::CharBlock source{GetContext().clauseSource};
30433068
// 2.7 Loop Construct Restriction
30443069
if ((llvm::omp::allDoSet | llvm::omp::allSimdSet)
30453070
.test(GetContext().directive)) {
30463071
if (std::holds_alternative<parser::OmpLinearClause::WithModifier>(x.v.u)) {
3047-
context_.Say(GetContext().clauseSource,
3072+
context_.Say(source,
30483073
"A modifier may not be specified in a LINEAR clause "
30493074
"on the %s directive"_err_en_US,
30503075
ContextDirectiveAsFortran());
3076+
return;
30513077
}
30523078
}
3079+
3080+
auto checkForValidLinearClause = [&](const parser::Name &name, bool is_ref) {
3081+
parser::CharBlock source{GetContext().clauseSource};
3082+
std::string listItemName{name.ToString()};
3083+
if (!is_ref && !name.symbol->GetType()->IsNumeric(TypeCategory::Integer)) {
3084+
context_.Say(source,
3085+
"The list item `%s` specified with other than linear-modifier `REF`"
3086+
" must be of type INTEGER"_err_en_US,
3087+
listItemName);
3088+
}
3089+
if (GetContext().directive == llvm::omp::Directive::OMPD_declare_simd &&
3090+
!IsDummy(*name.symbol)) {
3091+
context_.Say(source,
3092+
"The list item `%s` must be a dummy argument"_err_en_US,
3093+
listItemName);
3094+
}
3095+
if (IsPointer(*name.symbol) ||
3096+
name.symbol->test(Symbol::Flag::CrayPointer)) {
3097+
context_.Say(source,
3098+
"The list item `%s` in a LINEAR clause must not be Cray Pointer "
3099+
"or a variable with POINTER attribute"_err_en_US,
3100+
listItemName);
3101+
}
3102+
if (FindCommonBlockContaining(*name.symbol)) {
3103+
context_.Say(source,
3104+
"'%s' is a common block name and must not appear in an "
3105+
"LINEAR clause"_err_en_US,
3106+
listItemName);
3107+
}
3108+
};
3109+
3110+
// OpenMP 5.2: Linear clause Restrictions
3111+
common::visit(
3112+
common::visitors{
3113+
[&](const parser::OmpLinearClause::WithoutModifier &withoutModifier) {
3114+
for (const auto &name : withoutModifier.names) {
3115+
if (name.symbol) {
3116+
checkForValidLinearClause(name, false);
3117+
}
3118+
}
3119+
},
3120+
[&](const parser::OmpLinearClause::WithModifier &withModifier) {
3121+
for (const auto &name : withModifier.names) {
3122+
if (name.symbol) {
3123+
checkForValidLinearClause(name,
3124+
(withModifier.modifier.v ==
3125+
parser::OmpLinearModifier::Type::Ref));
3126+
std::string listItemName{name.ToString()};
3127+
if (withModifier.modifier.v !=
3128+
parser::OmpLinearModifier::Type::Val &&
3129+
IsDummy(*name.symbol) && IsValue(*name.symbol)) {
3130+
context_.Say(source,
3131+
"The list item `%s` specified with the linear-modifier "
3132+
"`REF` or `UVAL` must be a dummy argument without "
3133+
"`VALUE` attribute"_err_en_US,
3134+
listItemName);
3135+
}
3136+
if (withModifier.modifier.v ==
3137+
parser::OmpLinearModifier::Type::Ref &&
3138+
!(IsAllocatable(*name.symbol) ||
3139+
IsAssumedShape(*name.symbol) ||
3140+
IsPolymorphic(*name.symbol))) {
3141+
context_.Say(source,
3142+
"The list item `%s` specified with the linear-modifier "
3143+
"`REF` must be polymorphic variable, assumed-shape "
3144+
"array, "
3145+
"or a variable with the `ALLOCATABLE` attribute"_err_en_US,
3146+
listItemName);
3147+
}
3148+
}
3149+
}
3150+
},
3151+
},
3152+
x.v.u);
30533153
}
30543154

30553155
void OmpStructureChecker::CheckAllowedMapTypes(

0 commit comments

Comments
 (0)