From fe55e42eff2466d1fffae30cf24037636f44b04c Mon Sep 17 00:00:00 2001 From: Paul Scoropan <1paulscoropan@gmail.com> Date: Mon, 6 Feb 2023 19:09:10 +0000 Subject: [PATCH] [Flang] [Semantics] More descript warning message for same named external statements and interfaces For issue: https://github.com/llvm/llvm-project/issues/56605. Previous error messages are not descriptive of problem. Issuing warnings instead that do not halt compilation but offer better description of problem. Reviewed By: klausler Differential Revision: https://reviews.llvm.org/D143426 --- flang/lib/Semantics/resolve-names.cpp | 31 +++++++++++++++++++++------ flang/test/Semantics/resolve20.f90 | 2 +- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp index f4d3d88abff14..12e4f4dd2d994 100644 --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -3911,11 +3911,19 @@ bool SubprogramVisitor::HandlePreviousCalls( // ENTRY's name. We have to replace that symbol in situ to avoid the // obligation to rewrite symbol pointers in the parse tree. if (!symbol.test(subpFlag)) { - Say2(name, - subpFlag == Symbol::Flag::Function - ? "'%s' was previously called as a subroutine"_err_en_US - : "'%s' was previously called as a function"_err_en_US, - symbol, "Previous call of '%s'"_en_US); + // External statements issue an explicit EXTERNAL attribute. + if (symbol.attrs().test(Attr::EXTERNAL) && + !symbol.implicitAttrs().test(Attr::EXTERNAL)) { + // Warn if external statement previously declared. + Say(name, + "EXTERNAL attribute was already specified on '%s'"_warn_en_US); + } else { + Say2(name, + subpFlag == Symbol::Flag::Function + ? "'%s' was previously called as a subroutine"_err_en_US + : "'%s' was previously called as a function"_err_en_US, + symbol, "Previous call of '%s'"_en_US); + } } EntityDetails entity; if (proc->type()) { @@ -4333,8 +4341,17 @@ bool DeclarationVisitor::Pre(const parser::ExternalStmt &x) { for (const auto &name : x.v) { auto *symbol{FindSymbol(name)}; if (!ConvertToProcEntity(DEREF(symbol))) { - SayWithDecl( - name, *symbol, "EXTERNAL attribute not allowed on '%s'"_err_en_US); + // Check if previous symbol is an interface. + if (auto *details{symbol->detailsIf()}) { + if (details->isInterface()) { + // Warn if interface previously declared. + Say(name, + "EXTERNAL attribute was already specified on '%s'"_warn_en_US); + } + } else { + SayWithDecl( + name, *symbol, "EXTERNAL attribute not allowed on '%s'"_err_en_US); + } } else if (symbol->attrs().test(Attr::INTRINSIC)) { // C840 Say(symbol->name(), "Symbol '%s' cannot have both INTRINSIC and EXTERNAL attributes"_err_en_US, diff --git a/flang/test/Semantics/resolve20.f90 b/flang/test/Semantics/resolve20.f90 index b1d73341b57b1..a3d240dbc5982 100644 --- a/flang/test/Semantics/resolve20.f90 +++ b/flang/test/Semantics/resolve20.f90 @@ -48,7 +48,7 @@ subroutine forward external :: a, b, c, d !ERROR: EXTERNAL attribute not allowed on 'm' external :: m - !ERROR: EXTERNAL attribute not allowed on 'foo' + !WARNING: EXTERNAL attribute was already specified on 'foo' external :: foo !ERROR: EXTERNAL attribute not allowed on 'bar' external :: bar