@@ -1081,110 +1081,96 @@ void OmpStructureChecker::Leave(const parser::OmpEndSectionsDirective &x) {
10811081 }
10821082}
10831083
1084+ void OmpStructureChecker::CheckThreadprivateOrDeclareTargetVar (
1085+ const parser::Designator &designator) {
1086+ auto *name{parser::Unwrap<parser::Name>(designator)};
1087+ // If the symbol is null, return early, CheckSymbolNames
1088+ // should have already reported the missing symbol as a
1089+ // diagnostic error
1090+ if (!name || !name->symbol ) {
1091+ return ;
1092+ }
1093+
1094+ llvm::omp::Directive directive{GetContext ().directive };
1095+
1096+ if (name->symbol ->GetUltimate ().IsSubprogram ()) {
1097+ if (directive == llvm::omp::Directive::OMPD_threadprivate)
1098+ context_.Say (name->source ,
1099+ " The procedure name cannot be in a %s directive" _err_en_US,
1100+ ContextDirectiveAsFortran ());
1101+ // TODO: Check for procedure name in declare target directive.
1102+ } else if (name->symbol ->attrs ().test (Attr::PARAMETER)) {
1103+ if (directive == llvm::omp::Directive::OMPD_threadprivate)
1104+ context_.Say (name->source ,
1105+ " The entity with PARAMETER attribute cannot be in a %s directive" _err_en_US,
1106+ ContextDirectiveAsFortran ());
1107+ else if (directive == llvm::omp::Directive::OMPD_declare_target)
1108+ context_.Warn (common::UsageWarning::OpenMPUsage, name->source ,
1109+ " The entity with PARAMETER attribute is used in a %s directive" _warn_en_US,
1110+ ContextDirectiveAsFortran ());
1111+ } else if (FindCommonBlockContaining (*name->symbol )) {
1112+ context_.Say (name->source ,
1113+ " A variable in a %s directive cannot be an element of a common block" _err_en_US,
1114+ ContextDirectiveAsFortran ());
1115+ } else if (FindEquivalenceSet (*name->symbol )) {
1116+ context_.Say (name->source ,
1117+ " A variable in a %s directive cannot appear in an EQUIVALENCE statement" _err_en_US,
1118+ ContextDirectiveAsFortran ());
1119+ } else if (name->symbol ->test (Symbol::Flag::OmpThreadprivate) &&
1120+ directive == llvm::omp::Directive::OMPD_declare_target) {
1121+ context_.Say (name->source ,
1122+ " A THREADPRIVATE variable cannot appear in a %s directive" _err_en_US,
1123+ ContextDirectiveAsFortran ());
1124+ } else {
1125+ const semantics::Scope &useScope{
1126+ context_.FindScope (GetContext ().directiveSource )};
1127+ const semantics::Scope &curScope = name->symbol ->GetUltimate ().owner ();
1128+ if (!curScope.IsTopLevel ()) {
1129+ const semantics::Scope &declScope =
1130+ GetProgramUnitOrBlockConstructContaining (curScope);
1131+ const semantics::Symbol *sym{
1132+ declScope.parent ().FindSymbol (name->symbol ->name ())};
1133+ if (sym &&
1134+ (sym->has <MainProgramDetails>() || sym->has <ModuleDetails>())) {
1135+ context_.Say (name->source ,
1136+ " The module name cannot be in a %s directive" _err_en_US,
1137+ ContextDirectiveAsFortran ());
1138+ } else if (!IsSaved (*name->symbol ) &&
1139+ declScope.kind () != Scope::Kind::MainProgram &&
1140+ declScope.kind () != Scope::Kind::Module) {
1141+ context_.Say (name->source ,
1142+ " A variable that appears in a %s directive must be declared in the scope of a module or have the SAVE attribute, either explicitly or implicitly" _err_en_US,
1143+ ContextDirectiveAsFortran ());
1144+ } else if (useScope != declScope) {
1145+ context_.Say (name->source ,
1146+ " The %s directive and the common block or variable in it must appear in the same declaration section of a scoping unit" _err_en_US,
1147+ ContextDirectiveAsFortran ());
1148+ }
1149+ }
1150+ }
1151+ }
1152+
1153+ void OmpStructureChecker::CheckThreadprivateOrDeclareTargetVar (
1154+ const parser::Name &name) {
1155+ if (!name.symbol ) {
1156+ return ;
1157+ }
1158+
1159+ if (auto *cb{name.symbol ->detailsIf <CommonBlockDetails>()}) {
1160+ for (const auto &obj : cb->objects ()) {
1161+ if (FindEquivalenceSet (*obj)) {
1162+ context_.Say (name.source ,
1163+ " A variable in a %s directive cannot appear in an EQUIVALENCE statement (variable '%s' from common block '/%s/')" _err_en_US,
1164+ ContextDirectiveAsFortran (), obj->name (), name.symbol ->name ());
1165+ }
1166+ }
1167+ }
1168+ }
1169+
10841170void OmpStructureChecker::CheckThreadprivateOrDeclareTargetVar (
10851171 const parser::OmpObjectList &objList) {
10861172 for (const auto &ompObject : objList.v ) {
1087- common::visit (
1088- common::visitors{
1089- [&](const parser::Designator &) {
1090- if (const auto *name{parser::Unwrap<parser::Name>(ompObject)}) {
1091- // The symbol is null, return early, CheckSymbolNames
1092- // should have already reported the missing symbol as a
1093- // diagnostic error
1094- if (!name->symbol ) {
1095- return ;
1096- }
1097-
1098- if (name->symbol ->GetUltimate ().IsSubprogram ()) {
1099- if (GetContext ().directive ==
1100- llvm::omp::Directive::OMPD_threadprivate)
1101- context_.Say (name->source ,
1102- " The procedure name cannot be in a %s "
1103- " directive" _err_en_US,
1104- ContextDirectiveAsFortran ());
1105- // TODO: Check for procedure name in declare target directive.
1106- } else if (name->symbol ->attrs ().test (Attr::PARAMETER)) {
1107- if (GetContext ().directive ==
1108- llvm::omp::Directive::OMPD_threadprivate)
1109- context_.Say (name->source ,
1110- " The entity with PARAMETER attribute cannot be in a %s "
1111- " directive" _err_en_US,
1112- ContextDirectiveAsFortran ());
1113- else if (GetContext ().directive ==
1114- llvm::omp::Directive::OMPD_declare_target)
1115- context_.Warn (common::UsageWarning::OpenMPUsage,
1116- name->source ,
1117- " The entity with PARAMETER attribute is used in a %s directive" _warn_en_US,
1118- ContextDirectiveAsFortran ());
1119- } else if (FindCommonBlockContaining (*name->symbol )) {
1120- context_.Say (name->source ,
1121- " A variable in a %s directive cannot be an element of a "
1122- " common block" _err_en_US,
1123- ContextDirectiveAsFortran ());
1124- } else if (FindEquivalenceSet (*name->symbol )) {
1125- context_.Say (name->source ,
1126- " A variable in a %s directive cannot appear in an "
1127- " EQUIVALENCE statement" _err_en_US,
1128- ContextDirectiveAsFortran ());
1129- } else if (name->symbol ->test (Symbol::Flag::OmpThreadprivate) &&
1130- GetContext ().directive ==
1131- llvm::omp::Directive::OMPD_declare_target) {
1132- context_.Say (name->source ,
1133- " A THREADPRIVATE variable cannot appear in a %s "
1134- " directive" _err_en_US,
1135- ContextDirectiveAsFortran ());
1136- } else {
1137- const semantics::Scope &useScope{
1138- context_.FindScope (GetContext ().directiveSource )};
1139- const semantics::Scope &curScope =
1140- name->symbol ->GetUltimate ().owner ();
1141- if (!curScope.IsTopLevel ()) {
1142- const semantics::Scope &declScope =
1143- GetProgramUnitOrBlockConstructContaining (curScope);
1144- const semantics::Symbol *sym{
1145- declScope.parent ().FindSymbol (name->symbol ->name ())};
1146- if (sym &&
1147- (sym->has <MainProgramDetails>() ||
1148- sym->has <ModuleDetails>())) {
1149- context_.Say (name->source ,
1150- " The module name cannot be in a %s "
1151- " directive" _err_en_US,
1152- ContextDirectiveAsFortran ());
1153- } else if (!IsSaved (*name->symbol ) &&
1154- declScope.kind () != Scope::Kind::MainProgram &&
1155- declScope.kind () != Scope::Kind::Module) {
1156- context_.Say (name->source ,
1157- " A variable that appears in a %s directive must be "
1158- " declared in the scope of a module or have the SAVE "
1159- " attribute, either explicitly or "
1160- " implicitly" _err_en_US,
1161- ContextDirectiveAsFortran ());
1162- } else if (useScope != declScope) {
1163- context_.Say (name->source ,
1164- " The %s directive and the common block or variable "
1165- " in it must appear in the same declaration section "
1166- " of a scoping unit" _err_en_US,
1167- ContextDirectiveAsFortran ());
1168- }
1169- }
1170- }
1171- }
1172- },
1173- [&](const parser::Name &name) {
1174- if (name.symbol ) {
1175- if (auto *cb{name.symbol ->detailsIf <CommonBlockDetails>()}) {
1176- for (const auto &obj : cb->objects ()) {
1177- if (FindEquivalenceSet (*obj)) {
1178- context_.Say (name.source ,
1179- " A variable in a %s directive cannot appear in an EQUIVALENCE statement (variable '%s' from common block '/%s/')" _err_en_US,
1180- ContextDirectiveAsFortran (), obj->name (),
1181- name.symbol ->name ());
1182- }
1183- }
1184- }
1185- }
1186- },
1187- },
1173+ common::visit ([&](auto &&s) { CheckThreadprivateOrDeclareTargetVar (s); },
11881174 ompObject.u );
11891175 }
11901176}
0 commit comments