@@ -323,6 +323,30 @@ void OmpStructureChecker::CheckMultListItems() {
323
323
CheckMultipleOccurrence (
324
324
listVars, nontempNameList, itr->second ->source , " NONTEMPORAL" );
325
325
}
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
+ }
326
350
}
327
351
328
352
bool OmpStructureChecker::HasInvalidWorksharingNesting (
@@ -2299,12 +2323,12 @@ void OmpStructureChecker::Leave(const parser::OmpClauseList &) {
2299
2323
}
2300
2324
}
2301
2325
}
2302
-
2303
- // Sema checks related to presence of multiple list items within the same
2304
- // clause
2305
- CheckMultListItems ();
2306
2326
} // SIMD
2307
2327
2328
+ // Semantic checks related to presence of multiple list items within the same
2329
+ // clause
2330
+ CheckMultListItems ();
2331
+
2308
2332
// 2.7.3 Single Construct Restriction
2309
2333
if (GetContext ().directive == llvm::omp::Directive::OMPD_end_single) {
2310
2334
CheckNotAllowedIfClause (
@@ -3040,16 +3064,92 @@ void OmpStructureChecker::Enter(const parser::OmpClause::If &x) {
3040
3064
void OmpStructureChecker::Enter (const parser::OmpClause::Linear &x) {
3041
3065
CheckAllowedClause (llvm::omp::Clause::OMPC_linear);
3042
3066
3067
+ parser::CharBlock source{GetContext ().clauseSource };
3043
3068
// 2.7 Loop Construct Restriction
3044
3069
if ((llvm::omp::allDoSet | llvm::omp::allSimdSet)
3045
3070
.test (GetContext ().directive )) {
3046
3071
if (std::holds_alternative<parser::OmpLinearClause::WithModifier>(x.v .u )) {
3047
- context_.Say (GetContext (). clauseSource ,
3072
+ context_.Say (source ,
3048
3073
" A modifier may not be specified in a LINEAR clause "
3049
3074
" on the %s directive" _err_en_US,
3050
3075
ContextDirectiveAsFortran ());
3076
+ return ;
3051
3077
}
3052
3078
}
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 );
3053
3153
}
3054
3154
3055
3155
void OmpStructureChecker::CheckAllowedMapTypes (
0 commit comments