Skip to content

Commit af26bf1

Browse files
[LLVM-Flang][OpenMP] Add some semantic checks for Linear clause based on the OpenMP 5.2 restrictions
1 parent 82c93b6 commit af26bf1

File tree

1 file changed

+92
-5
lines changed

1 file changed

+92
-5
lines changed

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

Lines changed: 92 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,21 @@ void OmpStructureChecker::CheckMultListItems() {
383383
CheckMultipleOccurrence(
384384
listVars, nontempNameList, clause->source, "NONTEMPORAL");
385385
}
386+
387+
// Linear clause
388+
for (auto [_, clause] : FindClauses(llvm::omp::Clause::OMPC_linear)) {
389+
const auto &linearClause{std::get<parser::OmpClause::Linear>(clause->u)};
390+
std::list<parser::Name> nameList;
391+
common::visit(
392+
common::visitors{
393+
[&](const auto &u) {
394+
std::copy(
395+
u.names.begin(), u.names.end(), std::back_inserter(nameList));
396+
},
397+
},
398+
linearClause.v.u);
399+
CheckMultipleOccurrence(listVars, nameList, clause->source, "LINEAR");
400+
}
386401
}
387402

388403
bool OmpStructureChecker::HasInvalidWorksharingNesting(
@@ -2686,12 +2701,12 @@ void OmpStructureChecker::Leave(const parser::OmpClauseList &) {
26862701
}
26872702
}
26882703
}
2689-
2690-
// Sema checks related to presence of multiple list items within the same
2691-
// clause
2692-
CheckMultListItems();
26932704
} // SIMD
26942705

2706+
// Semantic checks related to presence of multiple list items within the same
2707+
// clause
2708+
CheckMultListItems();
2709+
26952710
// 2.7.3 Single Construct Restriction
26962711
if (GetContext().directive == llvm::omp::Directive::OMPD_end_single) {
26972712
CheckNotAllowedIfClause(
@@ -3542,16 +3557,88 @@ void OmpStructureChecker::Enter(const parser::OmpClause::If &x) {
35423557
void OmpStructureChecker::Enter(const parser::OmpClause::Linear &x) {
35433558
CheckAllowedClause(llvm::omp::Clause::OMPC_linear);
35443559

3560+
parser::CharBlock source{GetContext().clauseSource};
35453561
// 2.7 Loop Construct Restriction
35463562
if ((llvm::omp::allDoSet | llvm::omp::allSimdSet)
35473563
.test(GetContext().directive)) {
35483564
if (std::holds_alternative<parser::OmpLinearClause::WithModifier>(x.v.u)) {
3549-
context_.Say(GetContext().clauseSource,
3565+
context_.Say(source,
35503566
"A modifier may not be specified in a LINEAR clause "
35513567
"on the %s directive"_err_en_US,
35523568
ContextDirectiveAsFortran());
3569+
return;
35533570
}
35543571
}
3572+
3573+
auto checkForValidLinearClause_01 = [&](const parser::Name &name,
3574+
bool is_ref) {
3575+
std::string listItemName{name.ToString()};
3576+
if (!is_ref && !name.symbol->GetType()->IsNumeric(TypeCategory::Integer)) {
3577+
context_.Say(source,
3578+
"The list item `%s` specified with other than linear-modifier `REF`"
3579+
" must be of type INTEGER"_err_en_US,
3580+
listItemName);
3581+
}
3582+
if (GetContext().directive == llvm::omp::Directive::OMPD_declare_simd &&
3583+
!IsDummy(*name.symbol)) {
3584+
context_.Say(source,
3585+
"The list item `%s` must be a dummy argument"_err_en_US,
3586+
listItemName);
3587+
}
3588+
if (IsPointer(*name.symbol) ||
3589+
name.symbol->test(Symbol::Flag::CrayPointer)) {
3590+
context_.Say(source,
3591+
"The list item `%s` in a LINEAR clause must not be Cray Pointer "
3592+
"or a variable with POINTER attribute"_err_en_US,
3593+
listItemName);
3594+
}
3595+
if (FindCommonBlockContaining(*name.symbol)) {
3596+
context_.Say(source,
3597+
"'%s' is a common block name and must not appear in an "
3598+
"LINEAR clause"_err_en_US,
3599+
listItemName);
3600+
}
3601+
};
3602+
3603+
auto checkForValidLinearClause_02 = [&](const parser::Name &name,
3604+
const parser::OmpLinearModifier::Value
3605+
&modifierValue) {
3606+
std::string listItemName{name.ToString()};
3607+
checkForValidLinearClause_01(
3608+
name, (modifierValue == parser::OmpLinearModifier::Value::Ref));
3609+
if (modifierValue != parser::OmpLinearModifier::Value::Val &&
3610+
IsDummy(*name.symbol) && IsValue(*name.symbol)) {
3611+
context_.Say(source,
3612+
"The list item `%s` specified with the linear-modifier `REF` or "
3613+
"`UVAL` must be a dummy argument without `VALUE` attribute"_err_en_US,
3614+
listItemName);
3615+
}
3616+
if (modifierValue == parser::OmpLinearModifier::Value::Ref &&
3617+
!(IsAllocatable(*name.symbol) || IsAssumedShape(*name.symbol) ||
3618+
IsPolymorphic(*name.symbol))) {
3619+
context_.Say(source,
3620+
"The list item `%s` specified with the linear-modifier `REF` "
3621+
"must be polymorphic variable, assumed-shape array, or a variable"
3622+
" with the `ALLOCATABLE` attribute"_err_en_US,
3623+
listItemName);
3624+
}
3625+
};
3626+
3627+
// OpenMP 5.2: Linear clause Restrictions
3628+
common::visit(
3629+
common::visitors{
3630+
[&](const parser::OmpLinearClause::WithoutModifier &withoutModifier) {
3631+
for (const auto &name : withoutModifier.names)
3632+
if (name.symbol)
3633+
checkForValidLinearClause_01(name, false);
3634+
},
3635+
[&](const parser::OmpLinearClause::WithModifier &withModifier) {
3636+
for (const auto &name : withModifier.names)
3637+
if (name.symbol)
3638+
checkForValidLinearClause_02(name, withModifier.modifier.v);
3639+
},
3640+
},
3641+
x.v.u);
35553642
}
35563643

35573644
void OmpStructureChecker::CheckAllowedMapTypes(

0 commit comments

Comments
 (0)