diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h --- a/flang/lib/Semantics/check-omp-structure.h +++ b/flang/lib/Semantics/check-omp-structure.h @@ -216,6 +216,8 @@ const parser::CharBlock &source, const parser::OmpObjectList &objList); void CheckThreadprivateOrDeclareTargetVar( const parser::OmpObjectList &objList); + void CheckSymbolNames( + const parser::CharBlock &source, const parser::OmpObjectList &objList); void CheckIntentInPointer( const parser::OmpObjectList &, const llvm::omp::Clause); void GetSymbolsInObjectList(const parser::OmpObjectList &, SymbolSourceMap &); diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -970,6 +970,13 @@ common::visitors{ [&](const parser::Designator &) { if (const auto *name{parser::Unwrap(ompObject)}) { + // The symbol is null, return early, CheckSymbolNames + // should have already reported the missing symbol as a + // diagnostic error + if (!name->symbol) { + return; + } + if (name->symbol->GetUltimate().IsSubprogram()) { if (GetContext().directive == llvm::omp::Directive::OMPD_threadprivate) @@ -1061,6 +1068,7 @@ void OmpStructureChecker::Leave(const parser::OpenMPThreadprivate &c) { const auto &dir{std::get(c.t)}; const auto &objectList{std::get(c.t)}; + CheckSymbolNames(dir.source, objectList); CheckIsVarPartOfAnotherVar(dir.source, objectList); CheckThreadprivateOrDeclareTargetVar(objectList); dirContext_.pop_back(); @@ -1117,20 +1125,49 @@ } } +void OmpStructureChecker::CheckSymbolNames( + const parser::CharBlock &source, const parser::OmpObjectList &objList) { + for (const auto &ompObject : objList.v) { + common::visit( + common::visitors{ + [&](const parser::Designator &designator) { + if (const auto *name{parser::Unwrap(ompObject)}) { + if (!name->symbol) { + context_.Say(source, + "The given %s directive clause has an invalid argument"_err_en_US, + ContextDirectiveAsFortran()); + } + } + }, + [&](const parser::Name &name) { + if (!name.symbol) { + context_.Say(source, + "The given %s directive clause has an invalid argument"_err_en_US, + ContextDirectiveAsFortran()); + } + }, + }, + ompObject.u); + } +} + void OmpStructureChecker::Leave(const parser::OpenMPDeclareTargetConstruct &x) { const auto &dir{std::get(x.t)}; const auto &spec{std::get(x.t)}; if (const auto *objectList{parser::Unwrap(spec.u)}) { + CheckSymbolNames(dir.source, *objectList); CheckIsVarPartOfAnotherVar(dir.source, *objectList); CheckThreadprivateOrDeclareTargetVar(*objectList); } else if (const auto *clauseList{ parser::Unwrap(spec.u)}) { for (const auto &clause : clauseList->v) { if (const auto *toClause{std::get_if(&clause.u)}) { + CheckSymbolNames(dir.source, toClause->v); CheckIsVarPartOfAnotherVar(dir.source, toClause->v); CheckThreadprivateOrDeclareTargetVar(toClause->v); } else if (const auto *linkClause{ std::get_if(&clause.u)}) { + CheckSymbolNames(dir.source, linkClause->v); CheckIsVarPartOfAnotherVar(dir.source, linkClause->v); CheckThreadprivateOrDeclareTargetVar(linkClause->v); } @@ -1797,9 +1834,12 @@ common::visitors{ [&](const parser::Designator &) { if (const auto *name{ - parser::Unwrap(ompObject)}) - testThreadprivateVarErr( - name->symbol->GetUltimate(), *name, type); + parser::Unwrap(ompObject)}) { + if (name->symbol) { + testThreadprivateVarErr( + name->symbol->GetUltimate(), *name, type); + } + } }, [&](const parser::Name &name) { if (name.symbol) { diff --git a/flang/test/Semantics/OpenMP/declare-target06.f90 b/flang/test/Semantics/OpenMP/declare-target06.f90 new file mode 100644 --- /dev/null +++ b/flang/test/Semantics/OpenMP/declare-target06.f90 @@ -0,0 +1,23 @@ +! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp +! OpenMP Version 5.1 +! Check OpenMP construct validity for the following directives: +! 2.14.7 Declare Target Directive +! When used in an implicit none context. + +module test_0 + implicit none +!ERROR: The given DECLARE TARGET directive clause has an invalid argument +!ERROR: No explicit type declared for 'no_implicit_materialization_1' +!$omp declare target(no_implicit_materialization_1) + +!ERROR: The given DECLARE TARGET directive clause has an invalid argument +!ERROR: No explicit type declared for 'no_implicit_materialization_2' +!$omp declare target link(no_implicit_materialization_2) + +!ERROR: The given DECLARE TARGET directive clause has an invalid argument +!ERROR: No explicit type declared for 'no_implicit_materialization_3' +!$omp declare target to(no_implicit_materialization_3) + +INTEGER :: data_int = 10 +!$omp declare target(data_int) +end module test_0