From: Tim Keith Date: Sun, 24 Feb 2019 18:05:43 +0000 (-0800) Subject: [flang] Fix resolution of function prefix type X-Git-Tag: llvmorg-12-init~9537^2~1709 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=9a497ddbadd6480eb4bdb0ce8e94b49c03bb0443;p=platform%2Fupstream%2Fllvm.git [flang] Fix resolution of function prefix type When a function-stmt has a type in the prefix (`type(t) function f()`), the type cannot be resolve until after processing the USE and IMPLICIT statements. So save the parse-tree of the type and process it at the end of the specification section. Add `ProcessTypeSpec()` to handle the process of setting up to walk a type spec, walking it, restoring the state, and returning the type spec. We do this several other places too. Original-commit: flang-compiler/f18@bcde294d0e62c6ef8506392f66816814ae976dff 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 8bebe31..61be4a7 100644 --- a/flang/lib/semantics/resolve-names.cc +++ b/flang/lib/semantics/resolve-names.cc @@ -280,10 +280,19 @@ protected: } derived; }; + // Walk the parse tree of a type spec and return the DeclTypeSpec for it. + template const DeclTypeSpec *ProcessTypeSpec(const T &x) { + auto save{common::ScopedSet(state_, State{})}; + BeginDeclTypeSpec(); + Walk(x); + const auto *type{GetDeclTypeSpec()}; + EndDeclTypeSpec(); + return type; + } + const DeclTypeSpec *GetDeclTypeSpec(); void BeginDeclTypeSpec(); void EndDeclTypeSpec(); - State SetDeclTypeSpecState(State); void SetDeclTypeSpec(const DeclTypeSpec &); void SetDeclTypeSpecCategory(DeclTypeSpec::Category); DeclTypeSpec::Category GetDeclTypeSpecCategory() const { @@ -599,14 +608,22 @@ public: bool Pre(const parser::SeparateModuleSubprogram &); void Post(const parser::SeparateModuleSubprogram &); bool Pre(const parser::Suffix &); + bool Pre(const parser::PrefixSpec &); protected: // Set when we see a stmt function that is really an array element assignment bool badStmtFuncFound_{false}; + void HandleFunctionPrefixType(); private: - // Function result name from parser::Suffix, if any. - const parser::Name *funcResultName_{nullptr}; + // Info about the current function: parse tree of the type in the PrefixSpec; + // name and symbol of the function result from the Suffix; source location. + struct { + const parser::DeclarationTypeSpec *parsedType{nullptr}; + const parser::Name *resultName{nullptr}; + Symbol *resultSymbol{nullptr}; + const SourceName *source{nullptr}; + } funcInfo_; bool BeginSubprogram(const parser::Name &, Symbol::Flag, bool hasModulePrefix, const std::optional &); @@ -949,7 +966,6 @@ public: template bool Pre(const T &) { return true; } template void Post(const T &) {} - bool Pre(const parser::PrefixSpec &); void Post(const parser::SpecificationPart &); bool Pre(const parser::MainProgram &); void Post(const parser::EndProgramStmt &); @@ -1187,12 +1203,6 @@ void DeclTypeSpecVisitor::EndDeclTypeSpec() { state_ = {}; } -DeclTypeSpecVisitor::State DeclTypeSpecVisitor::SetDeclTypeSpecState(State x) { - auto result{state_}; - state_ = x; - return result; -} - void DeclTypeSpecVisitor::SetDeclTypeSpecCategory( DeclTypeSpec::Category category) { CHECK(state_.expectDeclTypeSpec); @@ -2168,11 +2178,28 @@ bool SubprogramVisitor::HandleStmtFunction(const parser::StmtFunctionStmt &x) { bool SubprogramVisitor::Pre(const parser::Suffix &suffix) { if (suffix.resultName) { - funcResultName_ = &suffix.resultName.value(); + funcInfo_.resultName = &suffix.resultName.value(); } return true; } +bool SubprogramVisitor::Pre(const parser::PrefixSpec &x) { + // Save this to process after UseStmt and ImplicitPart + funcInfo_.parsedType = std::get_if(&x.u); + funcInfo_.source = currStmtSource(); + return funcInfo_.parsedType == nullptr; +} + +void SubprogramVisitor::HandleFunctionPrefixType() { + if (funcInfo_.parsedType) { + messageHandler().set_currStmtSource(funcInfo_.source); + if (const auto *type{ProcessTypeSpec(*funcInfo_.parsedType)}) { + funcInfo_.resultSymbol->SetType(*type); + } + } + funcInfo_ = {}; +} + bool HasModulePrefix(const std::list &prefixes) { for (const auto &prefix : prefixes) { if (std::holds_alternative(prefix.u)) { @@ -2234,10 +2261,6 @@ bool SubprogramVisitor::Pre(const parser::SubroutineStmt &stmt) { return BeginAttrs(); } bool SubprogramVisitor::Pre(const parser::FunctionStmt &stmt) { - if (!subpNamesOnly_) { - BeginDeclTypeSpec(); - CHECK(!funcResultName_); - } return BeginAttrs(); } @@ -2259,23 +2282,18 @@ void SubprogramVisitor::Post(const parser::FunctionStmt &stmt) { Symbol &dummy{MakeSymbol(dummyName, EntityDetails(true))}; details.add_dummyArg(dummy); } - // add function result to function scope - EntityDetails funcResultDetails; - funcResultDetails.set_funcResult(true); - if (auto *type{GetDeclTypeSpec()}) { - funcResultDetails.set_type(*type); - } - EndDeclTypeSpec(); - const parser::Name *funcResultName; - if (funcResultName_ && funcResultName_->source != name.source) { - funcResultName = funcResultName_; + if (funcInfo_.resultName && funcInfo_.resultName->source != name.source) { + funcResultName = funcInfo_.resultName; } else { EraseSymbol(name); // was added by PushSubprogramScope funcResultName = &name; } - details.set_result(MakeSymbol(*funcResultName, funcResultDetails)); - funcResultName_ = nullptr; + // add function result to function scope + EntityDetails funcResultDetails; + funcResultDetails.set_funcResult(true); + funcInfo_.resultSymbol = &MakeSymbol(*funcResultName, funcResultDetails); + details.set_result(*funcInfo_.resultSymbol); } SubprogramDetails &SubprogramVisitor::PostSubprogramStmt( @@ -3255,14 +3273,8 @@ void DeclarationVisitor::Post(const parser::AllocateStmt &) { } bool DeclarationVisitor::Pre(const parser::StructureConstructor &x) { - auto savedState{SetDeclTypeSpecState({})}; - BeginDeclTypeSpec(); auto &parsedType{std::get(x.t)}; - Walk(parsedType); - const DeclTypeSpec *type{GetDeclTypeSpec()}; - EndDeclTypeSpec(); - SetDeclTypeSpecState(savedState); - + const DeclTypeSpec *type{ProcessTypeSpec(parsedType)}; if (type == nullptr) { return false; } @@ -3645,10 +3657,7 @@ Symbol *DeclarationVisitor::DeclareStatementEntity(const parser::Name &name, return nullptr; // error was reported in DeclareEntity } if (type.has_value()) { - BeginDeclTypeSpec(); - DeclarationVisitor::Post(*type); - declTypeSpec = GetDeclTypeSpec(); - EndDeclTypeSpec(); + declTypeSpec = ProcessTypeSpec(*type); } if (declTypeSpec != nullptr) { SetType(name, *declTypeSpec); @@ -3848,12 +3857,7 @@ bool ConstructVisitor::Pre(const parser::LocalitySpec::Shared &x) { } bool ConstructVisitor::Pre(const parser::AcSpec &x) { - // AcSpec can occur within a TypeDeclarationStmt: save and restore state - auto savedState{SetDeclTypeSpecState({})}; - BeginDeclTypeSpec(); - Walk(x.type); - EndDeclTypeSpec(); - SetDeclTypeSpecState(savedState); + ProcessTypeSpec(x.type); PushScope(Scope::Kind::ImpliedDos, nullptr); Walk(x.values); PopScope(); @@ -4143,10 +4147,6 @@ const DeclTypeSpec &ConstructVisitor::ToDeclTypeSpec( // ResolveNamesVisitor implementation -bool ResolveNamesVisitor::Pre(const parser::PrefixSpec &x) { - return true; // TODO -} - bool ResolveNamesVisitor::Pre(const parser::FunctionReference &x) { HandleCall(Symbol::Flag::Function, x.v); return false; @@ -4474,6 +4474,7 @@ static bool NeedsExplicitType(const Symbol &symbol) { void ResolveNamesVisitor::Post(const parser::SpecificationPart &) { badStmtFuncFound_ = false; CheckImports(); + HandleFunctionPrefixType(); bool inModule{currScope().kind() == Scope::Kind::Module}; for (auto &pair : currScope()) { auto &symbol{*pair.second}; diff --git a/flang/test/semantics/modfile04.f90 b/flang/test/semantics/modfile04.f90 index 539c598..2b82e39 100644 --- a/flang/test/semantics/modfile04.f90 +++ b/flang/test/semantics/modfile04.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. @@ -14,7 +14,9 @@ ! modfile with subprograms -module m +module m1 + type :: t + end type contains pure subroutine s(x, y) bind(c) @@ -34,8 +36,20 @@ contains end -!Expect: m.mod -!module m +module m2 +contains + type(t) function f3() + use m1 + end + function f4() result(x) + implicit complex(x) + end +end + +!Expect: m1.mod +!module m1 +!type::t +!end type !contains !pure subroutine s(x,y) bind(c) !logical(4),intent(in)::x @@ -49,3 +63,14 @@ end !complex(4)::y !end !end + +!Expect: m2.mod +!module m2 +!contains +!function f3() +!type(t)::f3 +!end +!function f4() result(x) +!complex(4)::x +!end +!end