From: Tim Keith Date: Wed, 30 May 2018 21:11:45 +0000 (-0700) Subject: [flang] Extract DeclarationVisitor from ResolveNamesVisitor X-Git-Tag: llvmorg-12-init~9537^2~2524 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=06440bc34de41532e11a9161c333cb898d860bf0;p=platform%2Fupstream%2Fllvm.git [flang] Extract DeclarationVisitor from ResolveNamesVisitor The is a refactoring to move all handling of declarations from ResolveNamesVisitor to a new class. No function change. Original-commit: flang-compiler/f18@2a5589ab969421b1723c63105fe6922941ec1096 Reviewed-on: https://github.com/flang-compiler/f18/pull/97 Tree-same-pre-rewrite: false --- diff --git a/flang/lib/semantics/resolve-names.cc b/flang/lib/semantics/resolve-names.cc index 4370c4a..f01af9a 100644 --- a/flang/lib/semantics/resolve-names.cc +++ b/flang/lib/semantics/resolve-names.cc @@ -428,10 +428,51 @@ private: Symbol *GetSpecificFromGeneric(const parser::Name &); }; +class DeclarationVisitor : public ArraySpecVisitor, + public virtual ScopeHandler { +public: + using ArraySpecVisitor::Post; + using ArraySpecVisitor::Pre; + + void Post(const parser::EntityDecl &); + void Post(const parser::ObjectDecl &); + bool Pre(const parser::AsynchronousStmt &); + bool Pre(const parser::ContiguousStmt &); + bool Pre(const parser::ExternalStmt &); + bool Pre(const parser::IntrinsicStmt &); + bool Pre(const parser::OptionalStmt &); + bool Pre(const parser::ProtectedStmt &); + bool Pre(const parser::ValueStmt &); + bool Pre(const parser::VolatileStmt &); + bool Pre(const parser::AllocatableStmt &) { + objectDeclAttr_ = Attr::ALLOCATABLE; + return true; + } + void Post(const parser::AllocatableStmt &) { objectDeclAttr_ = std::nullopt; } + bool Pre(const parser::TargetStmt &x) { + objectDeclAttr_ = Attr::TARGET; + return true; + } + void Post(const parser::TargetStmt &) { objectDeclAttr_ = std::nullopt; } + void Post(const parser::DimensionStmt::Declaration &); + +protected: + bool BeginDecl(); + void EndDecl(); + +private: + // The attribute corresponding to the statement containing an ObjectDecl + std::optional objectDeclAttr_; + + // Handle a statement that sets an attribute on a list of names. + bool HandleAttributeStmt(Attr, const std::list &); + void DeclareEntity(const parser::Name &, Attrs); +}; + // Walk the parse tree and resolve names to symbols. -class ResolveNamesVisitor : public ArraySpecVisitor, - public ModuleVisitor, - public SubprogramVisitor { +class ResolveNamesVisitor : public ModuleVisitor, + public SubprogramVisitor, + public DeclarationVisitor { public: using ArraySpecVisitor::Post; using ArraySpecVisitor::Pre; @@ -443,6 +484,8 @@ public: using ModuleVisitor::Pre; using SubprogramVisitor::Post; using SubprogramVisitor::Pre; + using DeclarationVisitor::Post; + using DeclarationVisitor::Pre; // Default action for a parse tree node is to visit children. template bool Pre(const T &) { return true; } @@ -456,35 +499,13 @@ public: void Post(const parser::DataComponentDefStmt &) { EndDecl(); } bool Pre(const parser::TypeDeclarationStmt &) { return BeginDecl(); } void Post(const parser::TypeDeclarationStmt &) { EndDecl(); } - void Post(const parser::EntityDecl &); - void Post(const parser::ObjectDecl &); void Post(const parser::ComponentDecl &); bool Pre(const parser::PrefixSpec &); - bool Pre(const parser::AsynchronousStmt &); - bool Pre(const parser::ContiguousStmt &); - bool Pre(const parser::ExternalStmt &); - bool Pre(const parser::IntrinsicStmt &); - bool Pre(const parser::OptionalStmt &); - bool Pre(const parser::ProtectedStmt &); - bool Pre(const parser::ValueStmt &); - bool Pre(const parser::VolatileStmt &); void Post(const parser::SpecificationPart &); bool Pre(const parser::MainProgram &); void Post(const parser::EndProgramStmt &); void Post(const parser::Program &); - bool Pre(const parser::AllocatableStmt &) { - objectDeclAttr_ = Attr::ALLOCATABLE; - return true; - } - void Post(const parser::AllocatableStmt &) { objectDeclAttr_ = std::nullopt; } - bool Pre(const parser::TargetStmt &x) { - objectDeclAttr_ = Attr::TARGET; - return true; - } - void Post(const parser::TargetStmt &) { objectDeclAttr_ = std::nullopt; } - void Post(const parser::DimensionStmt::Declaration &); - void Post(const parser::Expr &x) { CheckImplicitSymbol(GetVariableName(x)); } void Post(const parser::Variable &x) { CheckImplicitSymbol(GetVariableName(x)); @@ -493,14 +514,6 @@ public: void Post(const parser::ProcedureDesignator &); private: - // The attribute corresponding to the statement containing an ObjectDecl - std::optional objectDeclAttr_; - - bool BeginDecl(); - void EndDecl(); - // Handle a statement that sets an attribute on a list of names. - bool HandleAttributeStmt(Attr, const std::list &); - void DeclareEntity(const parser::Name &, Attrs); const parser::Name *GetVariableName(const parser::DataRef &); const parser::Name *GetVariableName(const parser::Designator &); const parser::Name *GetVariableName(const parser::Expr &); @@ -1539,121 +1552,57 @@ Symbol *SubprogramVisitor::GetSpecificFromGeneric(const parser::Name &name) { return nullptr; } -// ResolveNamesVisitor implementation - -void ResolveNamesVisitor::Post(const parser::EntityDecl &x) { - // TODO: may be under StructureStmt - const auto &name{std::get(x.t)}; - // TODO: CoarraySpec, CharLength, Initialization - DeclareEntity(name, attrs_ ? *attrs_ : Attrs()); -} +// DeclarationVisitor implementation -bool ResolveNamesVisitor::BeginDecl() { +bool DeclarationVisitor::BeginDecl() { BeginDeclTypeSpec(); BeginAttrs(); BeginArraySpec(); return true; } -void ResolveNamesVisitor::EndDecl() { +void DeclarationVisitor::EndDecl() { EndDeclTypeSpec(); EndAttrs(); EndArraySpec(); } -bool ResolveNamesVisitor::Pre(const parser::TypeParamDefStmt &x) { - BeginDeclTypeSpec(); - return true; -} -void ResolveNamesVisitor::Post(const parser::TypeParamDefStmt &x) { - EndDeclTypeSpec(); - // TODO: TypeParamDefStmt -} - -bool ResolveNamesVisitor::Pre(const parser::CommonBlockObject &x) { - BeginArraySpec(); - return true; -} -void ResolveNamesVisitor::Post(const parser::CommonBlockObject &x) { - ClearArraySpec(); - // TODO: CommonBlockObject -} - -void ResolveNamesVisitor::Post(const parser::ComponentDecl &) { - ClearArraySpec(); -} - -bool ResolveNamesVisitor::Pre(const parser::PrefixSpec &x) { - return true; // TODO -} - -bool ResolveNamesVisitor::CheckUseError( - const SourceName &name, const Symbol &symbol) { - const auto *details = symbol.detailsIf(); - if (!details) { - return false; - } - Message &msg{Say(name, "Reference to '%s' is ambiguous"_err_en_US)}; - for (const auto &pair : details->occurrences()) { - const SourceName &location{*pair.first}; - const SourceName &moduleName{pair.second->name()}; - msg.Attach(location, - MessageFormattedText{"'%s' was use-associated from module '%s'"_en_US, - name.ToString().data(), moduleName.ToString().data()}); - } - return true; +void DeclarationVisitor::Post(const parser::DimensionStmt::Declaration &x) { + const auto &name = std::get(x.t); + DeclareEntity(name, Attrs{}); } -void ResolveNamesVisitor::Post(const parser::ProcedureDesignator &x) { - if (const auto *name = std::get_if(&x.u)) { - Symbol &symbol{MakeSymbol(name->source)}; - if (symbol.has()) { - if (isImplicitNoneExternal() && !symbol.attrs().test(Attr::EXTERNAL)) { - Say(*name, - "'%s' is an external procedure without the EXTERNAL" - " attribute in a scope with IMPLICIT NONE(EXTERNAL)"_err_en_US); - } - symbol.attrs().set(Attr::EXTERNAL); - symbol.set_details(SubprogramDetails{}); - } else if (CheckUseError(name->source, symbol)) { - // error was reported - } else if (!symbol.isSubprogram()) { - auto *details = symbol.detailsIf(); - if (!details || !details->isArray()) { - Say(*name, - "Use of '%s' as a procedure conflicts with its declaration"_err_en_US) - .Attach(symbol.name(), - MessageFormattedText{"Declaration of '%s'"_en_US, - symbol.name().ToString().data()}); - } - } - } +void DeclarationVisitor::Post(const parser::EntityDecl &x) { + // TODO: may be under StructureStmt + const auto &name{std::get(x.t)}; + // TODO: CoarraySpec, CharLength, Initialization + DeclareEntity(name, attrs_ ? *attrs_ : Attrs()); } -bool ResolveNamesVisitor::Pre(const parser::AsynchronousStmt &x) { +bool DeclarationVisitor::Pre(const parser::AsynchronousStmt &x) { return HandleAttributeStmt(Attr::ASYNCHRONOUS, x.v); } -bool ResolveNamesVisitor::Pre(const parser::ContiguousStmt &x) { +bool DeclarationVisitor::Pre(const parser::ContiguousStmt &x) { return HandleAttributeStmt(Attr::CONTIGUOUS, x.v); } -bool ResolveNamesVisitor::Pre(const parser::ExternalStmt &x) { +bool DeclarationVisitor::Pre(const parser::ExternalStmt &x) { return HandleAttributeStmt(Attr::EXTERNAL, x.v); } -bool ResolveNamesVisitor::Pre(const parser::IntrinsicStmt &x) { +bool DeclarationVisitor::Pre(const parser::IntrinsicStmt &x) { return HandleAttributeStmt(Attr::INTRINSIC, x.v); } -bool ResolveNamesVisitor::Pre(const parser::OptionalStmt &x) { +bool DeclarationVisitor::Pre(const parser::OptionalStmt &x) { return HandleAttributeStmt(Attr::OPTIONAL, x.v); } -bool ResolveNamesVisitor::Pre(const parser::ProtectedStmt &x) { +bool DeclarationVisitor::Pre(const parser::ProtectedStmt &x) { return HandleAttributeStmt(Attr::PROTECTED, x.v); } -bool ResolveNamesVisitor::Pre(const parser::ValueStmt &x) { +bool DeclarationVisitor::Pre(const parser::ValueStmt &x) { return HandleAttributeStmt(Attr::VALUE, x.v); } -bool ResolveNamesVisitor::Pre(const parser::VolatileStmt &x) { +bool DeclarationVisitor::Pre(const parser::VolatileStmt &x) { return HandleAttributeStmt(Attr::VOLATILE, x.v); } -bool ResolveNamesVisitor::HandleAttributeStmt( +bool DeclarationVisitor::HandleAttributeStmt( Attr attr, const std::list &names) { for (const auto &name : names) { const auto pair = CurrScope().try_emplace(name.source, Attrs{attr}); @@ -1672,18 +1621,13 @@ bool ResolveNamesVisitor::HandleAttributeStmt( return false; } -void ResolveNamesVisitor::Post(const parser::ObjectDecl &x) { +void DeclarationVisitor::Post(const parser::ObjectDecl &x) { CHECK(objectDeclAttr_.has_value()); const auto &name = std::get(x.t); DeclareEntity(name, Attrs{*objectDeclAttr_}); } -void ResolveNamesVisitor::Post(const parser::DimensionStmt::Declaration &x) { - const auto &name = std::get(x.t); - DeclareEntity(name, Attrs{}); -} - -void ResolveNamesVisitor::DeclareEntity(const parser::Name &name, Attrs attrs) { +void DeclarationVisitor::DeclareEntity(const parser::Name &name, Attrs attrs) { Symbol &symbol{MakeSymbol(name.source, attrs)}; // TODO: check attribute consistency if (symbol.has()) { @@ -1727,6 +1671,77 @@ void ResolveNamesVisitor::DeclareEntity(const parser::Name &name, Attrs attrs) { } } +// ResolveNamesVisitor implementation + +bool ResolveNamesVisitor::Pre(const parser::TypeParamDefStmt &x) { + BeginDeclTypeSpec(); + return true; +} +void ResolveNamesVisitor::Post(const parser::TypeParamDefStmt &x) { + EndDeclTypeSpec(); + // TODO: TypeParamDefStmt +} + +bool ResolveNamesVisitor::Pre(const parser::CommonBlockObject &x) { + BeginArraySpec(); + return true; +} +void ResolveNamesVisitor::Post(const parser::CommonBlockObject &x) { + ClearArraySpec(); + // TODO: CommonBlockObject +} + +void ResolveNamesVisitor::Post(const parser::ComponentDecl &) { + ClearArraySpec(); +} + +bool ResolveNamesVisitor::Pre(const parser::PrefixSpec &x) { + return true; // TODO +} + +bool ResolveNamesVisitor::CheckUseError( + const SourceName &name, const Symbol &symbol) { + const auto *details = symbol.detailsIf(); + if (!details) { + return false; + } + Message &msg{Say(name, "Reference to '%s' is ambiguous"_err_en_US)}; + for (const auto &pair : details->occurrences()) { + const SourceName &location{*pair.first}; + const SourceName &moduleName{pair.second->name()}; + msg.Attach(location, + MessageFormattedText{"'%s' was use-associated from module '%s'"_en_US, + name.ToString().data(), moduleName.ToString().data()}); + } + return true; +} + +void ResolveNamesVisitor::Post(const parser::ProcedureDesignator &x) { + if (const auto *name = std::get_if(&x.u)) { + Symbol &symbol{MakeSymbol(name->source)}; + if (symbol.has()) { + if (isImplicitNoneExternal() && !symbol.attrs().test(Attr::EXTERNAL)) { + Say(*name, + "'%s' is an external procedure without the EXTERNAL" + " attribute in a scope with IMPLICIT NONE(EXTERNAL)"_err_en_US); + } + symbol.attrs().set(Attr::EXTERNAL); + symbol.set_details(SubprogramDetails{}); + } else if (CheckUseError(name->source, symbol)) { + // error was reported + } else if (!symbol.isSubprogram()) { + auto *details = symbol.detailsIf(); + if (!details || !details->isArray()) { + Say(*name, + "Use of '%s' as a procedure conflicts with its declaration"_err_en_US) + .Attach(symbol.name(), + MessageFormattedText{"Declaration of '%s'"_en_US, + symbol.name().ToString().data()}); + } + } + } +} + bool ModuleVisitor::Pre(const parser::AccessStmt &x) { Attr accessAttr = AccessSpecToAttr(std::get(x.t)); if (CurrScope().kind() != Scope::Kind::Module) {