From 7fcaf88bf807abc88688f8e3b869f5e188beeafb Mon Sep 17 00:00:00 2001 From: Tim Keith Date: Mon, 12 Aug 2019 13:50:45 -0700 Subject: [PATCH] [flang] Fix source location of some symbol names Symbols can be declared across multiple statements. The CharBlock that is used for the symbol name is from the first of these. Sometimes that is not the best choice. If a name appears in a type-declaration-stmt or a derived-type-stmt, that occurrence is a better choice. Errors referencing that symbol should normally point at that name (not its appearance in an earlier PUBLIC statement, for example). Also, the order of symbols in .mod files is based on the order of their names in the cooked source. Here is an example where it is necessary to sort `a` based on where its type-declaration-stmt occurs rather than the first occurrence of `a`: ``` public :: a type t end type type(t), parameter :: a = t() ``` The fix is to add `Symbol::ReplaceName()` so that we can update the CharBlock for a symbol name when a better one is found, without changing the actual characters that make up the name. Original-commit: flang-compiler/f18@5544f163486df1da80d0e343282afc18ce057672 Reviewed-on: https://github.com/flang-compiler/f18/pull/650 Tree-same-pre-rewrite: false --- flang/lib/semantics/resolve-names.cc | 5 ++++- flang/lib/semantics/symbol.cc | 7 +++++++ flang/lib/semantics/symbol.h | 2 ++ flang/test/semantics/modfile19.f90 | 2 +- flang/test/semantics/modfile21.f90 | 2 +- flang/test/semantics/modfile30.f90 | 15 +++++++++++++++ 6 files changed, 30 insertions(+), 3 deletions(-) diff --git a/flang/lib/semantics/resolve-names.cc b/flang/lib/semantics/resolve-names.cc index 2a6a77d..2a31b56 100644 --- a/flang/lib/semantics/resolve-names.cc +++ b/flang/lib/semantics/resolve-names.cc @@ -2647,6 +2647,7 @@ void DeclarationVisitor::Post(const parser::EntityDecl &x) { const auto &name{std::get(x.t)}; Attrs attrs{attrs_ ? HandleSaveName(name.source, *attrs_) : Attrs{}}; Symbol &symbol{DeclareUnknownEntity(name, attrs)}; + symbol.ReplaceName(name.source); if (auto &init{std::get>(x.t)}) { if (ConvertToObjectEntity(symbol)) { Initialization(name, *init, false); @@ -2658,7 +2659,8 @@ void DeclarationVisitor::Post(const parser::EntityDecl &x) { void DeclarationVisitor::Post(const parser::PointerDecl &x) { const auto &name{std::get(x.t)}; - DeclareUnknownEntity(name, Attrs{Attr::POINTER}); + Symbol &symbol{DeclareUnknownEntity(name, Attrs{Attr::POINTER})}; + symbol.ReplaceName(name.source); } bool DeclarationVisitor::Pre(const parser::BindEntity &x) { @@ -3219,6 +3221,7 @@ void DeclarationVisitor::Post(const parser::DerivedTypeStmt &x) { } } auto &symbol{MakeSymbol(name, GetAttrs(), DerivedTypeDetails{})}; + symbol.ReplaceName(name.source); derivedTypeInfo_.type = &symbol; PushScope(Scope::Kind::DerivedType, &symbol); if (extendsType != nullptr) { diff --git a/flang/lib/semantics/symbol.cc b/flang/lib/semantics/symbol.cc index b63949a..fefe6b2 100644 --- a/flang/lib/semantics/symbol.cc +++ b/flang/lib/semantics/symbol.cc @@ -247,6 +247,13 @@ bool Symbol::CanReplaceDetails(const Details &details) const { } } +// Usually a symbol's name is the first occurrence in the source, but sometimes +// we want to replace it with one at a different location (but same characters). +void Symbol::ReplaceName(const SourceName &name) { + CHECK(name == name_); + name_ = name; +} + Symbol &Symbol::GetUltimate() { return const_cast(const_cast(this)->GetUltimate()); } diff --git a/flang/lib/semantics/symbol.h b/flang/lib/semantics/symbol.h index b227238..5a86331 100644 --- a/flang/lib/semantics/symbol.h +++ b/flang/lib/semantics/symbol.h @@ -465,6 +465,8 @@ public: Scope *scope() { return scope_; } const Scope *scope() const { return scope_; } void set_scope(Scope *scope) { scope_ = scope; } + // Give the symbol a name with a different source location but same chars. + void ReplaceName(const SourceName &); // Does symbol have this type of details? template bool has() const { diff --git a/flang/test/semantics/modfile19.f90 b/flang/test/semantics/modfile19.f90 index e8e3aa0..6a8c47c 100644 --- a/flang/test/semantics/modfile19.f90 +++ b/flang/test/semantics/modfile19.f90 @@ -25,9 +25,9 @@ end !Expect: m.mod !module m ! real(4)::x -! real(4)::y ! integer(4)::i ! complex(8)::z +! real(4)::y ! namelist/nl1/x,y,i,z ! namelist/nl2/y,x !end diff --git a/flang/test/semantics/modfile21.f90 b/flang/test/semantics/modfile21.f90 index 194de9b..f29c119 100644 --- a/flang/test/semantics/modfile21.f90 +++ b/flang/test/semantics/modfile21.f90 @@ -35,9 +35,9 @@ end ! real(4)::c ! real(4)::y ! real(4)::z -! complex(4)::w ! real(4)::u ! real(4)::v +! complex(4)::w ! real(4)::cb ! common/cb2/a,b,c ! bind(c)::/cb2/ diff --git a/flang/test/semantics/modfile30.f90 b/flang/test/semantics/modfile30.f90 index cf6fd53..0156219 100644 --- a/flang/test/semantics/modfile30.f90 +++ b/flang/test/semantics/modfile30.f90 @@ -39,3 +39,18 @@ end ! integer(4)::f2(1_8:1_8*size(x,dim=1)) ! end !end + +! Order of names in PUBLIC statement shouldn't affect .mod file. +module m2 + public :: a + type t + end type + type(t), parameter :: a = t() +end + +!Expect: m2.mod +!module m2 +! type::t +! end type +! type(t),parameter::a=t() +!end -- 2.7.4