From f9e24a563c36fc98860f4b282af5f6d034b2863c Mon Sep 17 00:00:00 2001 From: Pete Steinfeld Date: Tue, 30 Jun 2020 12:03:28 -0700 Subject: [PATCH] [flang] Bug fix for ambiguous references to data and functions Summary: A program may erroneously reference the same name as both a data object and as a function. Some of these references were causing an internal error in expression analysis. It was already the case that a symbol referenced in a parse tree for a call was changed from an `Entity` to a `ProcEntity`. I added code to detect when a symbol was referenced in a parse tree as an array element gets changed from an `Entity` to an `ObjectEntity`. Then, if an `ObjectEntity` gets called as a function or a `ProcEntity` gets referenced as a data object, errors get emitted. This analysis was previously confined to the name resolution of the specification part of a `ProgramTree`. I added a pass to the execution part of a `ProgramTree` to catch names declared in blocks. Reviewers: tskeith, klausler, DavidTruby Subscribers: llvm-commits Tags: #llvm, #flang Differential Revision: https://reviews.llvm.org/D82903 --- flang/lib/Semantics/expression.cpp | 5 +++- flang/lib/Semantics/resolve-names.cpp | 10 +++++++- flang/test/Semantics/resolve93.f90 | 44 +++++++++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 flang/test/Semantics/resolve93.f90 diff --git a/flang/lib/Semantics/expression.cpp b/flang/lib/Semantics/expression.cpp index 9914b57..27fcf5e2 100644 --- a/flang/lib/Semantics/expression.cpp +++ b/flang/lib/Semantics/expression.cpp @@ -909,7 +909,10 @@ MaybeExpr ExpressionAnalyzer::Analyze(const parser::ArrayElement &ae) { 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 index 51abece..4d70f03 100644 --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -5505,7 +5505,15 @@ const parser::Name *DeclarationVisitor::ResolveDataRef( }, [&](const Indirection &y) { Walk(y.value().subscripts); - return ResolveDataRef(y.value().base); + const parser::Name *name{ResolveDataRef(y.value().base)}; + if (!name) { + } else if (!name->symbol->has()) { + ConvertToObjectEntity(*name->symbol); + } else if (!context().HasError(*name->symbol)) { + SayWithDecl(*name, *name->symbol, + "Cannot reference function '%s' as data"_err_en_US); + } + return name; }, [&](const Indirection &y) { Walk(y.value().imageSelector); diff --git a/flang/test/Semantics/resolve93.f90 b/flang/test/Semantics/resolve93.f90 new file mode 100644 index 0000000..2c3764d --- /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: Cannot reference function 'str' as data + print *, str(1:9), str(7) + block + character(10) str2 + character(10) str3 + !ERROR: Cannot reference function 'str1' as data + 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: Cannot reference function 'local' as data + 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 -- 2.7.4