diff --git a/flang/lib/Semantics/expression.cpp b/flang/lib/Semantics/expression.cpp --- a/flang/lib/Semantics/expression.cpp +++ b/flang/lib/Semantics/expression.cpp @@ -909,7 +909,10 @@ return std::nullopt; } else if (baseExpr->Rank() == 0) { if (const Symbol * symbol{GetLastSymbol(*baseExpr)}) { - Say("'%s' is not an array"_err_en_US, symbol->name()); + if (!context_.HasError(symbol)) { + Say("'%s' is not an array"_err_en_US, symbol->name()); + context_.SetError(const_cast(*symbol)); + } } } else if (std::optional dataRef{ ExtractDataRef(std::move(*baseExpr))}) { diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -1401,6 +1401,7 @@ bool Pre(const parser::ProgramUnit &); void Post(const parser::AssignStmt &); void Post(const parser::AssignedGotoStmt &); + void Post(const parser::ArrayElement &); // These nodes should never be reached: they are handled in ProgramUnit bool Pre(const parser::MainProgram &) { @@ -1426,6 +1427,7 @@ } void NoteExecutablePartCall(Symbol::Flag, const parser::Call &); + void NoteExecutablePartArrayElement(const parser::Name &); friend void ResolveSpecificationParts(SemanticsContext &, const Symbol &); @@ -5897,6 +5899,25 @@ } } +void ResolveNamesVisitor::NoteExecutablePartArrayElement( + const parser::Name &name) { + // See the "subtlety" comment above for why we're getting the symbol this way + Symbol *symbol{name.symbol}; + if (!symbol) { + symbol = currScope().FindSymbol(name.source); + } + if (symbol) { + if (symbol->detailsIf()) { + if (!context().HasError(*symbol)) { + SayWithDecl( + name, *symbol, "Cannot reference function '%s' as data"_err_en_US); + } + } else { + ConvertToObjectEntity(*symbol); + } + } +} + // Check and set the Function or Subroutine flag on symbol; false on error. bool ResolveNamesVisitor::SetProcFlag( const parser::Name &name, Symbol &symbol, Symbol::Flag flag) { @@ -6236,6 +6257,15 @@ } } +void ResolveNamesVisitor::Post(const parser::ArrayElement &elem) { + // To avoid converting the name of the array to a function call, note that + // the name we're referencing is an object entity + const parser::DataRef &dataRef{elem.base}; + if (const parser::Name * name{std::get_if(&dataRef.u)}) { + NoteExecutablePartArrayElement(*name); + } +} + bool ResolveNamesVisitor::Pre(const parser::ProgramUnit &x) { auto root{ProgramTree::Build(x)}; SetScope(context().globalScope()); @@ -6263,6 +6293,13 @@ template bool Pre(const A &) { return true; } template void Post(const A &) {} + void Post(const parser::ArrayElement &elem) { + // The same actions as the Post function in ResolveNamesVisitor. This + // version gets executed when resolving names for the specification part + if (const parser::Name * name{std::get_if(&elem.base.u)}) { + resolver_.NoteExecutablePartArrayElement(*name); + } + } void Post(const parser::FunctionReference &fr) { resolver_.NoteExecutablePartCall(Symbol::Flag::Function, fr.v); } diff --git a/flang/test/Semantics/resolve93.f90 b/flang/test/Semantics/resolve93.f90 new file mode 100644 --- /dev/null +++ b/flang/test/Semantics/resolve93.f90 @@ -0,0 +1,44 @@ +! RUN: %S/test_errors.sh %s %t %f18 +subroutine s1() + character(10) str + character(10) str1 + !ERROR: 'str' is not an array + print *, str(1:9), str(7) + block + character(10) str2 + character(10) str3 + !ERROR: 'str1' is not an array + print *, str1(1:9), str1(7) + !ERROR: 'str2' is not an array + print *, str2(1:9), str2(7) + !ERROR: Cannot reference function 'str3' as data + print *, str3(7), str3(1:9) + end block +end subroutine s1 + +subroutine s2() + character(10) func + !ERROR: Cannot reference function 'func' as data + print *, func(7), func(1:9) +end subroutine s2 + +subroutine s3() + real(8) :: func + !ERROR: Cannot reference function 'func' as data + print *, func(7), func(1:6) +end subroutine s3 + +subroutine s4() + real(8) :: local + real(8) :: local1 + !ERROR: 'local' is not an array + print *, local(1:6), local(7) + !ERROR: Cannot reference function 'local1' as data + print *, local1(7), local1(1:6) +end subroutine s4 + +subroutine s5(arg) + integer :: iVar + external :: arg + iVar = loc(arg) +end subroutine s5