From d384116347312114492781f23b251638dc06f11f Mon Sep 17 00:00:00 2001 From: Tim Keith Date: Fri, 23 Mar 2018 12:24:29 -0700 Subject: [PATCH] [flang] Address review comments. Use "namespace Fortran::semantics". Add helper MakeSymbol() functions to ResolveNameVisitor to make a symbol in the current scope. Start work on subroutines, similar to what's been done for functions. Original-commit: flang-compiler/f18@afe84af1c7a16f7d5de8897d0c3453f580ac7e07 Reviewed-on: https://github.com/flang-compiler/f18/pull/30 --- flang/lib/semantics/make-types.cc | 6 ++-- flang/lib/semantics/resolve-names.cc | 70 ++++++++++++++++++++++++++---------- flang/lib/semantics/scope.cc | 6 ++-- flang/lib/semantics/scope.h | 26 ++++++++------ flang/lib/semantics/symbol.cc | 7 ++-- flang/lib/semantics/symbol.h | 25 ++++++------- 6 files changed, 83 insertions(+), 57 deletions(-) diff --git a/flang/lib/semantics/make-types.cc b/flang/lib/semantics/make-types.cc index 3a20a52..5cb9255 100644 --- a/flang/lib/semantics/make-types.cc +++ b/flang/lib/semantics/make-types.cc @@ -9,8 +9,7 @@ #include #include -namespace Fortran { -namespace semantics { +namespace Fortran::semantics { static KindParamValue GetKindParamValue( const std::optional &kind); @@ -353,5 +352,4 @@ static Bound GetBound(const parser::SpecificationExpr &x) { return Bound(*GetIntExpr(x.v)); } -} // namespace semantics -} // namespace Fortran +} diff --git a/flang/lib/semantics/resolve-names.cc b/flang/lib/semantics/resolve-names.cc index 59410c4..eb06201 100644 --- a/flang/lib/semantics/resolve-names.cc +++ b/flang/lib/semantics/resolve-names.cc @@ -10,9 +10,7 @@ #include #include -// namespace Fortran::semantics { -namespace Fortran { -namespace semantics { +namespace Fortran::semantics { // Provide Post methods to collect attributes into a member variable. class AttrsVisitor { @@ -126,6 +124,16 @@ public: void PushScope(Scope &scope) { scopes_.push(&scope); } void PopScope() { scopes_.pop(); } + // Helpers to make a Symbol in the current scope + template + Symbol &MakeSymbol(const Name &name, D &&details) { + return CurrScope().MakeSymbol(name, details); + } + template + Symbol &MakeSymbol(const Name &name, const Attrs &attrs, D &&details) { + return CurrScope().MakeSymbol(name, attrs, details); + } + // Default action for a parse tree node is to visit children. template bool Pre(const T &x) { return true; } template void Post(const T &) {} @@ -149,13 +157,15 @@ public: symbol.set_details(EntityDetails()); } else if (EntityDetails *details = symbol.detailsIf()) { if (details->type().has_value()) { - std::cerr << "ERROR: symbol already has a type declared\n"; + std::cerr << "ERROR: symbol already has a type declared: " << name + << "\n"; } else { details->set_type(*declTypeSpec_); } } else { std::cerr - << "ERROR: symbol already declared, can't appear in entity-decl\n"; + << "ERROR: symbol already declared, can't appear in entity-decl: " + << name << "\n"; } } @@ -173,34 +183,57 @@ public: return true; } + bool Pre(const parser::SubroutineStmt &stmt) { + beginAttrs(); + return true; + } + + // Common Post() for functions and subroutines. + void PostSubprogram( + const parser::Name &name, const std::list &dummyNames) { + const auto attrs = endAttrs(); + MakeSymbol(name, attrs, SubprogramDetails(dummyNames)); + Scope &subpScope = CurrScope().MakeScope(Scope::Kind::Subprogram); + PushScope(subpScope); + for (const auto &dummyName : dummyNames) { + MakeSymbol(dummyName, EntityDetails(true)); + } + } + + void Post(const parser::SubroutineStmt &stmt) { + const auto &subrName = std::get(stmt.t); + std::list dummyNames; + const auto &dummyArgs = std::get>(stmt.t); + for (const parser::DummyArg &dummyArg : dummyArgs) { + const parser::Name *dummyName = std::get_if(&dummyArg.u); + CHECK(dummyName != nullptr && "TODO: alternate return indicator"); + dummyNames.push_back(*dummyName); + } + PostSubprogram(subrName, dummyNames); + MakeSymbol(subrName, SubprogramDetails(dummyNames)); + } + bool Pre(const parser::FunctionStmt &stmt) { beginAttrs(); beginDeclTypeSpec(); CHECK(!funcResultName_); return true; } + // TODO: MakeSymbol function void Post(const parser::FunctionStmt &stmt) { const auto &funcName = std::get(stmt.t); const auto &dummyNames = std::get>(stmt.t); - const auto attrs = endAttrs(); - CurrScope().MakeSymbol( - funcName, attrs, SubprogramDetails(dummyNames, funcResultName_)); - Scope &funcScope = CurrScope().MakeScope(Scope::Kind::Subprogram); - PushScope(funcScope); - // add dummies and function result to function scope - for (const auto &dummyName : dummyNames) { - funcScope.MakeSymbol(dummyName, EntityDetails(true)); - } + PostSubprogram(funcName, dummyNames); + // add function result to function scope EntityDetails funcResultDetails; if (declTypeSpec_) { funcResultDetails.set_type(*declTypeSpec_); } const auto &resultName = funcResultName_ ? *funcResultName_ : funcName; - funcScope.MakeSymbol(resultName, funcResultDetails); + MakeSymbol(resultName, funcResultDetails); if (resultName != funcName) { // add symbol for function to its scope; name can't be reused - funcScope.MakeSymbol( - funcName, SubprogramDetails(dummyNames, funcResultName_)); + MakeSymbol(funcName, SubprogramDetails(dummyNames, funcResultName_)); } endDeclTypeSpec(); funcResultName_ = std::nullopt; @@ -223,5 +256,4 @@ void ResolveNames(const parser::Program &program) { parser::Walk(program, visitor); } -} // namespace semantics -} // namespace Fortran +} diff --git a/flang/lib/semantics/scope.cc b/flang/lib/semantics/scope.cc index fd5f7f8..3914538 100644 --- a/flang/lib/semantics/scope.cc +++ b/flang/lib/semantics/scope.cc @@ -2,8 +2,7 @@ #include "symbol.h" #include -namespace Fortran { -namespace semantics { +namespace Fortran::semantics { const Scope Scope::systemScope{Scope::systemScope, Scope::Kind::System}; Scope Scope::globalScope{Scope::systemScope, Scope::Kind::Global}; @@ -46,5 +45,4 @@ std::ostream &operator<<(std::ostream &os, const Scope &scope) { return os; } -} // namespace semantics -} // namespace Fortran +} // namespace Fortran::semantics diff --git a/flang/lib/semantics/scope.h b/flang/lib/semantics/scope.h index 89c384b..6c79d58 100644 --- a/flang/lib/semantics/scope.h +++ b/flang/lib/semantics/scope.h @@ -2,16 +2,14 @@ #define FORTRAN_SEMANTICS_SCOPE_H_ #include "../parser/idioms.h" +#include "../parser/parse-tree.h" #include "attr.h" #include "symbol.h" #include #include #include -namespace Fortran { -namespace semantics { - -using Name = std::string; +namespace Fortran::semantics { class Scope { public: @@ -40,33 +38,39 @@ public: /// If there is a symbol with this name already in the scope, return it. /// Otherwise make a new one and return that. - Symbol &GetOrMakeSymbol(const Name &name); + Symbol &GetOrMakeSymbol(const parser::Name &name); /// Make a Symbol with unknown details. - Symbol &MakeSymbol(const Name &name, const Attrs &attrs = Attrs::EMPTY); + Symbol &MakeSymbol( + const parser::Name &name, const Attrs &attrs = Attrs::EMPTY); /// Make a Symbol with provided details. - template Symbol &MakeSymbol(const Name &name, D &&details) { + template + Symbol &MakeSymbol(const parser::Name &name, D &&details) { const auto &result = symbols_.try_emplace(name, *this, name, Attrs::EMPTY, details); return result.first->second; } template - Symbol &MakeSymbol(const Name &name, const Attrs &attrs, D &&details) { + Symbol &MakeSymbol( + const parser::Name &name, const Attrs &attrs, D &&details) { const auto &result = symbols_.try_emplace(name, *this, name, attrs, details); return result.first->second; } + void EraseSymbol(const parser::Name &name) { + symbols_.erase(name); + } + private: const Scope &parent_; const Kind kind_; std::list children_; - std::map symbols_; + std::map symbols_; friend std::ostream &operator<<(std::ostream &, const Scope &); }; -} // namespace semantics -} // namespace Fortran +} // namespace Fortran::semantics #endif // FORTRAN_SEMANTICS_SCOPE_H_ diff --git a/flang/lib/semantics/symbol.cc b/flang/lib/semantics/symbol.cc index 4f62e15..b735289 100644 --- a/flang/lib/semantics/symbol.cc +++ b/flang/lib/semantics/symbol.cc @@ -3,8 +3,7 @@ #include "scope.h" #include -namespace Fortran { -namespace semantics { +namespace Fortran::semantics { std::ostream &operator<<(std::ostream &os, const Symbol &sym) { os << sym.name(); @@ -32,7 +31,6 @@ std::ostream &operator<<(std::ostream &os, const Symbol &sym) { [&](const EntityDetails &x) { os << " Entity"; if (x.type()) { - // os << ' ' << *x.type(); os << " type: " << *x.type(); } }, @@ -41,5 +39,4 @@ std::ostream &operator<<(std::ostream &os, const Symbol &sym) { return os; } -} // namespace semantics -} // namespace Fortran +} // namespace Fortran::semantics diff --git a/flang/lib/semantics/symbol.h b/flang/lib/semantics/symbol.h index 1707255..4be7907 100644 --- a/flang/lib/semantics/symbol.h +++ b/flang/lib/semantics/symbol.h @@ -2,12 +2,10 @@ #define FORTRAN_SEMANTICS_SYMBOL_H_ #include "type.h" -#include #include +#include - -namespace Fortran { -namespace semantics { +namespace Fortran::semantics { /// A Symbol consists of common information (name, owner, and attributes) /// and details information specific to the kind of symbol, represented by the @@ -29,7 +27,8 @@ class SubprogramDetails { public: SubprogramDetails(const std::list &dummyNames) : isFunction_{false}, dummyNames_{dummyNames} {} - SubprogramDetails(const std::list &dummyNames, const std::optional &resultName) + SubprogramDetails( + const std::list &dummyNames, const std::optional &resultName) : isFunction_{true}, dummyNames_{dummyNames}, resultName_{resultName} {} bool isFunction() const { return isFunction_; } @@ -56,17 +55,16 @@ private: friend std::ostream &operator<<(std::ostream &, const EntityDetails &); }; -class UnknownDetails { -}; +class UnknownDetails {}; class Symbol { public: - //TODO: more kinds of details - using Details = std::variant; + // TODO: more kinds of details + using Details = std::variant; - Symbol( - const Scope &owner, const Name &name, const Attrs &attrs, Details &&details) + Symbol(const Scope &owner, const Name &name, const Attrs &attrs, + Details &&details) : owner_{owner}, name_{name}, attrs_{attrs}, details_{std::move(details)} {} const Scope &owner() const { return owner_; } const Name &name() const { return name_; } @@ -107,6 +105,5 @@ private: friend std::ostream &operator<<(std::ostream &, const Symbol &); }; -} -} +} // namespace Fortran::semantics #endif // FORTRAN_SEMANTICS_SYMBOL_H_ -- 2.7.4