Mercurial > hg > CbC > CbC_llvm
diff flang/lib/Semantics/mod-file.cpp @ 207:2e18cbf3894f
LLVM12
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Tue, 08 Jun 2021 06:07:14 +0900 |
parents | 0572611fdcc8 |
children | c4bab56944e8 |
line wrap: on
line diff
--- a/flang/lib/Semantics/mod-file.cpp Mon May 25 11:55:54 2020 +0900 +++ b/flang/lib/Semantics/mod-file.cpp Tue Jun 08 06:07:14 2021 +0900 @@ -8,6 +8,7 @@ #include "mod-file.h" #include "resolve-names.h" +#include "flang/Common/restorer.h" #include "flang/Evaluate/tools.h" #include "flang/Parser/message.h" #include "flang/Parser/parsing.h" @@ -42,7 +43,7 @@ }; static std::optional<SourceName> GetSubmoduleParent(const parser::Program &); -static SymbolVector CollectSymbols(const Scope &); +static void CollectSymbols(const Scope &, SymbolVector &, SymbolVector &); static void PutEntity(llvm::raw_ostream &, const Symbol &); static void PutObjectEntity(llvm::raw_ostream &, const Symbol &); static void PutProcEntity(llvm::raw_ostream &, const Symbol &); @@ -53,8 +54,8 @@ static void PutInit(llvm::raw_ostream &, const Symbol &, const MaybeExpr &); static void PutInit(llvm::raw_ostream &, const MaybeIntExpr &); static void PutBound(llvm::raw_ostream &, const Bound &); -static llvm::raw_ostream &PutAttrs(llvm::raw_ostream &, Attrs, - const MaybeExpr & = std::nullopt, std::string before = ","s, +llvm::raw_ostream &PutAttrs(llvm::raw_ostream &, Attrs, + const std::string * = nullptr, std::string before = ","s, std::string after = ""s); static llvm::raw_ostream &PutAttr(llvm::raw_ostream &, Attr); @@ -80,8 +81,8 @@ const Scope &scope_; bool isInterface_{false}; SymbolVector need_; // symbols that are needed - SymbolSet needSet_; // symbols already in need_ - SymbolSet useSet_; // use-associations that might be needed + UnorderedSymbolSet needSet_; // symbols already in need_ + UnorderedSymbolSet useSet_; // use-associations that might be needed std::set<SourceName> imports_; // imports from host that are needed void DoSymbol(const Symbol &); @@ -99,6 +100,9 @@ }; bool ModFileWriter::WriteAll() { + // this flag affects character literals: force it to be consistent + auto restorer{ + common::ScopedSet(parser::useHexadecimalEscapeSequences, false)}; WriteAll(context_.globalScope()); return !context_.AnyFatalError(); } @@ -173,16 +177,33 @@ } // Put out the visible symbols from scope. -void ModFileWriter::PutSymbols(const Scope &scope) { - std::string buf; - llvm::raw_string_ostream typeBindings{ - buf}; // stuff after CONTAINS in derived type - for (const Symbol &symbol : CollectSymbols(scope)) { +bool ModFileWriter::PutSymbols(const Scope &scope) { + SymbolVector sorted; + SymbolVector uses; + CollectSymbols(scope, sorted, uses); + std::string buf; // stuff after CONTAINS in derived type + llvm::raw_string_ostream typeBindings{buf}; + for (const Symbol &symbol : sorted) { PutSymbol(typeBindings, symbol); } + for (const Symbol &symbol : uses) { + PutUse(symbol); + } if (auto str{typeBindings.str()}; !str.empty()) { CHECK(scope.IsDerivedType()); decls_ << "contains\n" << str; + return true; + } else { + return false; + } +} + +static llvm::raw_ostream &PutGenericName( + llvm::raw_ostream &os, const Symbol &symbol) { + if (IsGenericDefinedOp(symbol)) { + return os << "operator(" << symbol.name() << ')'; + } else { + return os << symbol.name(); } } @@ -198,8 +219,8 @@ if (symbol.owner().IsDerivedType()) { // generic binding for (const Symbol &proc : x.specificProcs()) { - typeBindings << "generic::" << symbol.name() << "=>" - << proc.name() << '\n'; + PutGenericName(typeBindings << "generic::", symbol) + << "=>" << proc.name() << '\n'; } } else { PutGeneric(symbol); @@ -253,9 +274,6 @@ decls_ << "::/" << symbol.name() << "/\n"; } }, - [&](const FinalProcDetails &) { - typeBindings << "final::" << symbol.name() << '\n'; - }, [](const HostAssocDetails &) {}, [](const MiscDetails &) {}, [&](const auto &) { PutEntity(decls_, symbol); }, @@ -283,7 +301,17 @@ if (details.sequence()) { decls_ << "sequence\n"; } - PutSymbols(typeScope); + bool contains{PutSymbols(typeScope)}; + if (!details.finals().empty()) { + const char *sep{contains ? "final::" : "contains\nfinal::"}; + for (const auto &pair : details.finals()) { + decls_ << sep << pair.second->name(); + sep = ","; + } + if (*sep == ',') { + decls_ << '\n'; + } + } decls_ << "end type\n"; } @@ -300,6 +328,10 @@ bindAttrs.set(Attr::BIND_C, true); attrs.set(Attr::BIND_C, false); } + bool isAbstract{attrs.test(Attr::ABSTRACT)}; + if (isAbstract) { + attrs.set(Attr::ABSTRACT, false); + } Attrs prefixAttrs{subprogramPrefixAttrs & attrs}; // emit any non-prefix attributes in an attribute statement attrs &= ~subprogramPrefixAttrs; @@ -312,9 +344,9 @@ bool isInterface{details.isInterface()}; llvm::raw_ostream &os{isInterface ? decls_ : contains_}; if (isInterface) { - os << "interface\n"; + os << (isAbstract ? "abstract " : "") << "interface\n"; } - PutAttrs(os, prefixAttrs, std::nullopt, ""s, " "s); + PutAttrs(os, prefixAttrs, nullptr, ""s, " "s); os << (details.isFunction() ? "function " : "subroutine "); os << symbol.name() << '('; int n = 0; @@ -322,7 +354,11 @@ if (n++ > 0) { os << ','; } - os << dummy->name(); + if (dummy) { + os << dummy->name(); + } else { + os << "*"; + } } os << ')'; PutAttrs(os, bindAttrs, details.bindName(), " "s, ""s); @@ -365,20 +401,14 @@ } } -static llvm::raw_ostream &PutGenericName( - llvm::raw_ostream &os, const Symbol &symbol) { - if (IsGenericDefinedOp(symbol)) { - return os << "operator(" << symbol.name() << ')'; - } else { - return os << symbol.name(); - } -} - void ModFileWriter::PutGeneric(const Symbol &symbol) { + const auto &genericOwner{symbol.owner()}; auto &details{symbol.get<GenericDetails>()}; PutGenericName(decls_ << "interface ", symbol) << '\n'; for (const Symbol &specific : details.specificProcs()) { - decls_ << "procedure::" << specific.name() << '\n'; + if (specific.owner() == genericOwner) { + decls_ << "procedure::" << specific.name() << '\n'; + } } decls_ << "end interface\n"; if (symbol.attrs().test(Attr::PRIVATE)) { @@ -389,7 +419,7 @@ void ModFileWriter::PutUse(const Symbol &symbol) { auto &details{symbol.get<UseDetails>()}; auto &use{details.symbol()}; - uses_ << "use " << details.module().name(); + uses_ << "use " << GetUsedModule(details).name(); PutGenericName(uses_ << ",only:", symbol); // Can have intrinsic op with different local-name and use-name // (e.g. `operator(<)` and `operator(.lt.)`) but rename is not allowed @@ -399,6 +429,9 @@ uses_ << '\n'; PutUseExtraAttr(Attr::VOLATILE, symbol, use); PutUseExtraAttr(Attr::ASYNCHRONOUS, symbol, use); + if (symbol.attrs().test(Attr::PRIVATE)) { + PutGenericName(useExtraAttrs_ << "private::", symbol) << '\n'; + } } // We have "USE local => use" in this module. If attr was added locally @@ -411,10 +444,35 @@ } } +// When a generic interface has the same name as a derived type +// in the same scope, the generic shadows the derived type. +// If the derived type were declared first, emit the generic +// interface at the position of derived type's declaration. +// (ReplaceName() is not used for this purpose because doing so +// would confusingly position error messages pertaining to the generic +// interface upon the derived type's declaration.) +static inline SourceName NameInModuleFile(const Symbol &symbol) { + if (const auto *generic{symbol.detailsIf<GenericDetails>()}) { + if (const auto *derivedTypeOverload{generic->derivedType()}) { + if (derivedTypeOverload->name().begin() < symbol.name().begin()) { + return derivedTypeOverload->name(); + } + } + } else if (const auto *use{symbol.detailsIf<UseDetails>()}) { + if (use->symbol().attrs().test(Attr::PRIVATE)) { + // Avoid the use in sorting of names created to access private + // specific procedures as a result of generic resolution; + // they're not in the cooked source. + return use->symbol().name(); + } + } + return symbol.name(); +} + // Collect the symbols of this scope sorted by their original order, not name. // Namelists are an exception: they are sorted after other symbols. -SymbolVector CollectSymbols(const Scope &scope) { - SymbolVector sorted; +void CollectSymbols( + const Scope &scope, SymbolVector &sorted, SymbolVector &uses) { SymbolVector namelist; std::size_t commonSize{scope.commonBlocks().size()}; auto symbols{scope.GetSymbols()}; @@ -426,14 +484,22 @@ } else { sorted.push_back(symbol); } + if (const auto *details{symbol->detailsIf<GenericDetails>()}) { + uses.insert(uses.end(), details->uses().begin(), details->uses().end()); + } } } + // Sort most symbols by name: use of Symbol::ReplaceName ensures the source + // location of a symbol's name is the first "real" use. + std::sort(sorted.begin(), sorted.end(), [](SymbolRef x, SymbolRef y) { + return NameInModuleFile(x).begin() < NameInModuleFile(y).begin(); + }); sorted.insert(sorted.end(), namelist.begin(), namelist.end()); for (const auto &pair : scope.commonBlocks()) { sorted.push_back(*pair.second); } - std::sort(sorted.end() - commonSize, sorted.end()); - return sorted; + std::sort( + sorted.end() - commonSize, sorted.end(), SymbolSourcePositionCompare{}); } void PutEntity(llvm::raw_ostream &os, const Symbol &symbol) { @@ -495,6 +561,9 @@ void PutProcEntity(llvm::raw_ostream &os, const Symbol &symbol) { if (symbol.attrs().test(Attr::INTRINSIC)) { os << "intrinsic::" << symbol.name() << '\n'; + if (symbol.attrs().test(Attr::PRIVATE)) { + os << "private::" << symbol.name() << '\n'; + } return; } const auto &details{symbol.get<ProcEntityDetails>()}; @@ -570,26 +639,18 @@ void PutEntity(llvm::raw_ostream &os, const Symbol &symbol, std::function<void()> writeType, Attrs attrs) { writeType(); - MaybeExpr bindName; - std::visit(common::visitors{ - [&](const SubprogramDetails &x) { bindName = x.bindName(); }, - [&](const ObjectEntityDetails &x) { bindName = x.bindName(); }, - [&](const ProcEntityDetails &x) { bindName = x.bindName(); }, - [&](const auto &) {}, - }, - symbol.details()); - PutAttrs(os, attrs, bindName); + PutAttrs(os, attrs, symbol.GetBindName()); os << "::" << symbol.name(); } // Put out each attribute to os, surrounded by `before` and `after` and // mapped to lower case. llvm::raw_ostream &PutAttrs(llvm::raw_ostream &os, Attrs attrs, - const MaybeExpr &bindName, std::string before, std::string after) { + const std::string *bindName, std::string before, std::string after) { attrs.set(Attr::PUBLIC, false); // no need to write PUBLIC attrs.set(Attr::EXTERNAL, false); // no need to write EXTERNAL if (bindName) { - bindName->AsFortran(os << before << "bind(c, name=") << ')' << after; + os << before << "bind(c, name=\"" << *bindName << "\")" << after; attrs.set(Attr::BIND_C, false); } for (std::size_t i{0}; i < Attr_enumSize; ++i) { @@ -743,7 +804,7 @@ return it->second->scope(); } } - parser::Parsing parsing{context_.allSources()}; + parser::Parsing parsing{context_.allCookedSources()}; parser::Options options; options.isModuleFile = true; options.features.Enable(common::LanguageFeature::BackslashEscapes); @@ -781,27 +842,28 @@ } else { parentScope = ancestor; } - ResolveNames(context_, *parseTree); - const auto &it{parentScope->find(name)}; - if (it == parentScope->end()) { + auto pair{parentScope->try_emplace(name, UnknownDetails{})}; + if (!pair.second) { return nullptr; } - auto &modSymbol{*it->second}; + Symbol &modSymbol{*pair.first->second}; modSymbol.set(Symbol::Flag::ModFile); - modSymbol.scope()->set_chars(parsing.cooked()); + ResolveNames(context_, *parseTree); + CHECK(modSymbol.has<ModuleDetails>()); + CHECK(modSymbol.test(Symbol::Flag::ModFile)); return modSymbol.scope(); } parser::Message &ModFileReader::Say(const SourceName &name, const std::string &ancestor, parser::MessageFixedText &&msg, const std::string &arg) { - return context_ - .Say(name, - ancestor.empty() - ? "Error reading module file for module '%s'"_err_en_US - : "Error reading module file for submodule '%s' of module '%s'"_err_en_US, - name, ancestor) - .Attach(name, std::move(msg), arg); + return context_.Say(name, "Cannot read module file for %s: %s"_err_en_US, + parser::MessageFormattedText{ancestor.empty() + ? "module '%s'"_en_US + : "submodule '%s' of module '%s'"_en_US, + name, ancestor} + .MoveString(), + parser::MessageFormattedText{std::move(msg), arg}.MoveString()); } // program was read from a .mod file for a submodule; return the name of the @@ -825,7 +887,9 @@ const auto &details{symbol_.get<SubprogramDetails>()}; isInterface_ = details.isInterface(); for (const Symbol *dummyArg : details.dummyArgs()) { - DoSymbol(DEREF(dummyArg)); + if (dummyArg) { + DoSymbol(*dummyArg); + } } if (details.isFunction()) { DoSymbol(details.result()); @@ -935,14 +999,16 @@ const SourceName &name, const Symbol &symbol) { if (!isInterface_) { return false; - } else if (symbol.owner() != scope_.parent()) { - // detect import from parent of use-associated symbol - // can be null in the case of a use-associated derived type's parent type - const auto *found{scope_.FindSymbol(name)}; - CHECK(found || symbol.has<DerivedTypeDetails>()); - return found && found->has<UseDetails>() && found->owner() != scope_; + } else if (symbol.owner().Contains(scope_)) { + return true; + } else if (const Symbol * found{scope_.FindSymbol(name)}) { + // detect import from ancestor of use-associated symbol + return found->has<UseDetails>() && found->owner() != scope_; } else { - return true; + // "found" can be null in the case of a use-associated derived type's parent + // type + CHECK(symbol.has<DerivedTypeDetails>()); + return false; } }