@@ -303,6 +303,30 @@ void OmpStructureChecker::CheckMultListItems() {
303
303
CheckMultipleOccurrence (
304
304
listVars, nontempNameList, itr->second ->source , " NONTEMPORAL" );
305
305
}
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
+ }
306
330
}
307
331
308
332
bool OmpStructureChecker::HasInvalidWorksharingNesting (
@@ -2256,11 +2280,12 @@ void OmpStructureChecker::Leave(const parser::OmpClauseList &) {
2256
2280
}
2257
2281
}
2258
2282
}
2259
- // Sema checks related to presence of multiple list items within the same
2260
- // clause
2261
- CheckMultListItems ();
2262
2283
} // SIMD
2263
2284
2285
+ // Semantic checks related to presence of multiple list items within the same
2286
+ // clause
2287
+ CheckMultListItems ();
2288
+
2264
2289
// 2.7.3 Single Construct Restriction
2265
2290
if (GetContext ().directive == llvm::omp::Directive::OMPD_end_single) {
2266
2291
CheckNotAllowedIfClause (
@@ -2975,16 +3000,92 @@ void OmpStructureChecker::Enter(const parser::OmpClause::If &x) {
2975
3000
void OmpStructureChecker::Enter (const parser::OmpClause::Linear &x) {
2976
3001
CheckAllowedClause (llvm::omp::Clause::OMPC_linear);
2977
3002
3003
+ parser::CharBlock source{GetContext ().clauseSource };
2978
3004
// 2.7 Loop Construct Restriction
2979
3005
if ((llvm::omp::allDoSet | llvm::omp::allSimdSet)
2980
3006
.test (GetContext ().directive )) {
2981
3007
if (std::holds_alternative<parser::OmpLinearClause::WithModifier>(x.v .u )) {
2982
- context_.Say (GetContext (). clauseSource ,
3008
+ context_.Say (source ,
2983
3009
" A modifier may not be specified in a LINEAR clause "
2984
3010
" on the %s directive" _err_en_US,
2985
3011
ContextDirectiveAsFortran ());
3012
+ return ;
2986
3013
}
2987
3014
}
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 );
2988
3089
}
2989
3090
2990
3091
void OmpStructureChecker::CheckAllowedMapTypes (
0 commit comments