From: Tim Keith Date: Tue, 26 Feb 2019 21:28:53 +0000 (-0800) Subject: [flang] Allow module procedure and generic with same name X-Git-Tag: llvmorg-12-init~9537^2~1707 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=0b9621b635d623c5c30fc67993b671d9afa5d076;p=platform%2Fupstream%2Fllvm.git [flang] Allow module procedure and generic with same name The `GenericDetails::CheckSpecific()` check was happening too early. We have to wait until all procedures of the generic have been seen. The generic can have the same name as a module procedure only if that module procedure is a specific procedure of the generic. Improve the `SayAlreadyDeclared` error message when the previous declaration is a use-association Original-commit: flang-compiler/f18@269e3db6020a5acc51a291dfea98455e6a97d2d5 Reviewed-on: https://github.com/flang-compiler/f18/pull/305 Tree-same-pre-rewrite: false --- diff --git a/flang/lib/semantics/resolve-names.cc b/flang/lib/semantics/resolve-names.cc index 61be4a7..9e462ad 100644 --- a/flang/lib/semantics/resolve-names.cc +++ b/flang/lib/semantics/resolve-names.cc @@ -414,6 +414,7 @@ public: // Special messages: already declared; referencing symbol's declaration; // about a type; two names & locations + void SayAlreadyDeclared(const SourceName &, const Symbol &); void SayAlreadyDeclared(const parser::Name &, const Symbol &); void SayWithDecl(const parser::Name &, const Symbol &, MessageFixedText &&); void SayDerivedType(const SourceName &, MessageFixedText &&, const Scope &); @@ -561,7 +562,6 @@ private: class InterfaceVisitor : public virtual ScopeHandler { public: bool Pre(const parser::InterfaceStmt &); - void Post(const parser::InterfaceStmt &); void Post(const parser::EndInterfaceStmt &); bool Pre(const parser::GenericSpec &); bool Pre(const parser::ProcedureStmt &); @@ -1483,9 +1483,23 @@ Bound ArraySpecVisitor::GetBound(const parser::SpecificationExpr &x) { void ScopeHandler::SayAlreadyDeclared( const parser::Name &name, const Symbol &prev) { - Say2(name, "'%s' is already declared in this scoping unit"_err_en_US, prev, - "Previous declaration of '%s'"_en_US); + SayAlreadyDeclared(name.source, prev); } +void ScopeHandler::SayAlreadyDeclared( + const SourceName &name, const Symbol &prev) { + auto &msg{ + Say(name, "'%s' is already declared in this scoping unit"_err_en_US)}; + if (const auto *details{prev.detailsIf()}) { + msg.Attach(details->location(), + "It is use-associated with '%s' in module '%s'"_err_en_US, + details->symbol().name().ToString().c_str(), + details->module().name().ToString().c_str()); + } else { + msg.Attach(prev.name(), "Previous declaration of '%s'"_en_US, + prev.name().ToString().c_str()); + } +} + void ScopeHandler::SayWithDecl( const parser::Name &name, const Symbol &symbol, MessageFixedText &&msg) { Say2(name, std::move(msg), symbol, @@ -1945,15 +1959,9 @@ bool InterfaceVisitor::Pre(const parser::InterfaceStmt &x) { isAbstract_ = std::holds_alternative(x.u); return true; } -void InterfaceVisitor::Post(const parser::InterfaceStmt &) {} void InterfaceVisitor::Post(const parser::EndInterfaceStmt &) { - if (genericName_) { - if (const auto *proc{GetGenericDetails().CheckSpecific()}) { - SayAlreadyDeclared(*genericName_, *proc); - } - genericName_ = nullptr; - } + genericName_ = nullptr; inInterfaceBlock_ = false; isAbstract_ = false; } @@ -2096,6 +2104,9 @@ void InterfaceVisitor::ResolveSpecificsInGeneric(Symbol &generic) { void InterfaceVisitor::CheckGenericProcedures(Symbol &generic) { ResolveSpecificsInGeneric(generic); auto &details{generic.get()}; + if (const auto *proc{details.CheckSpecific()}) { + SayAlreadyDeclared(generic.name(), *proc); + } auto &specifics{details.specificProcs()}; if (specifics.empty()) { if (details.derivedType()) { diff --git a/flang/test/semantics/resolve17.f90 b/flang/test/semantics/resolve17.f90 index 87d3eb17..a63fce0 100644 --- a/flang/test/semantics/resolve17.f90 +++ b/flang/test/semantics/resolve17.f90 @@ -1,4 +1,4 @@ -! Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. +! Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved. ! ! Licensed under the Apache License, Version 2.0 (the "License"); ! you may not use this file except in compliance with the License. @@ -29,3 +29,18 @@ contains subroutine s end subroutine end module + +module m3 + ! This is okay: so is generic and specific + interface s + procedure s2 + end interface + interface s + procedure s + end interface +contains + subroutine s() + end subroutine + subroutine s2(x) + end subroutine +end module