Skip to content

Commit 9ce8e63

Browse files
authored
[flang] Better renaming in module files (#93106)
When a symbol from one module is used in another without an explicit USE association, the module file output code may need to use another name for it -- either with a name that is already available via USE association with renaming, or by means of a new private USE association, possibly with renaming to avoid a clash. Module file output was dealing properly with names of derived types, but wasn't accounting for symbols that appear in expressions other than initializations. This was specifically a problem with an application module that had a call to a NOPASS type-bound procedure in an array bound specification expression, which semantics had resolved to the name of a private module function. This patch implements renaming, when necessary, for all symbols appearing in expressions and type names, and replaces the previous implementation of derived type renaming. It also gets a little smarter about avoiding the creation of compiler-generated names when a name from another module has been brought into scope already by means of USE association with renaming.
1 parent 47b485c commit 9ce8e63

File tree

8 files changed

+261
-169
lines changed

8 files changed

+261
-169
lines changed

flang/include/flang/Evaluate/constant.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,8 +126,7 @@ class ConstantBase : public ConstantBounds {
126126
constexpr Result result() const { return result_; }
127127

128128
constexpr DynamicType GetType() const { return result_.GetType(); }
129-
llvm::raw_ostream &AsFortran(llvm::raw_ostream &,
130-
const parser::CharBlock *derivedTypeRename = nullptr) const;
129+
llvm::raw_ostream &AsFortran(llvm::raw_ostream &) const;
131130

132131
protected:
133132
std::vector<Element> Reshape(const ConstantSubscripts &) const;

flang/include/flang/Evaluate/expression.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -735,8 +735,7 @@ class StructureConstructor {
735735
StructureConstructor &Add(const semantics::Symbol &, Expr<SomeType> &&);
736736
int Rank() const { return 0; }
737737
DynamicType GetType() const;
738-
llvm::raw_ostream &AsFortran(llvm::raw_ostream &,
739-
const parser::CharBlock *derivedTypeRename = nullptr) const;
738+
llvm::raw_ostream &AsFortran(llvm::raw_ostream &) const;
740739

741740
private:
742741
std::optional<Expr<SomeType>> CreateParentComponent(const Symbol &) const;

flang/include/flang/Evaluate/type.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -272,9 +272,6 @@ const semantics::DerivedTypeSpec *GetDerivedTypeSpec(
272272
const semantics::DerivedTypeSpec *GetParentTypeSpec(
273273
const semantics::DerivedTypeSpec &);
274274

275-
std::string DerivedTypeSpecAsFortran(const semantics::DerivedTypeSpec &,
276-
const parser::CharBlock *derivedTypeRename = nullptr);
277-
278275
template <TypeCategory CATEGORY, int KIND = 0> struct TypeBase {
279276
static constexpr TypeCategory category{CATEGORY};
280277
static constexpr int kind{KIND};

flang/include/flang/Semantics/semantics.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,9 @@ class SemanticsContext {
110110
evaluate::FoldingContext &foldingContext() { return foldingContext_; }
111111
parser::AllCookedSources &allCookedSources() { return allCookedSources_; }
112112
ModuleDependences &moduleDependences() { return moduleDependences_; }
113+
std::map<const Symbol *, SourceName> &moduleFileOutputRenamings() {
114+
return moduleFileOutputRenamings_;
115+
}
113116

114117
SemanticsContext &set_location(
115118
const std::optional<parser::CharBlock> &location) {
@@ -299,6 +302,7 @@ class SemanticsContext {
299302
std::list<parser::Program> modFileParseTrees_;
300303
std::unique_ptr<CommonBlockMap> commonBlockMap_;
301304
ModuleDependences moduleDependences_;
305+
std::map<const Symbol *, SourceName> moduleFileOutputRenamings_;
302306
};
303307

304308
class Semantics {

flang/lib/Evaluate/formatting.cpp

Lines changed: 110 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "flang/Evaluate/fold.h"
1515
#include "flang/Evaluate/tools.h"
1616
#include "flang/Parser/characters.h"
17+
#include "flang/Semantics/semantics.h"
1718
#include "flang/Semantics/symbol.h"
1819
#include "llvm/Support/raw_ostream.h"
1920

@@ -53,7 +54,7 @@ static void ShapeAsFortran(llvm::raw_ostream &o,
5354

5455
template <typename RESULT, typename VALUE>
5556
llvm::raw_ostream &ConstantBase<RESULT, VALUE>::AsFortran(
56-
llvm::raw_ostream &o, const parser::CharBlock *derivedTypeRename) const {
57+
llvm::raw_ostream &o) const {
5758
bool hasNonDefaultLowerBound{printLbounds && HasNonDefaultLowerBound()};
5859
if (Rank() > 1 || hasNonDefaultLowerBound) {
5960
o << "reshape(";
@@ -85,8 +86,7 @@ llvm::raw_ostream &ConstantBase<RESULT, VALUE>::AsFortran(
8586
o << ".false." << '_' << Result::kind;
8687
}
8788
} else {
88-
StructureConstructor{result_.derivedTypeSpec(), value}.AsFortran(
89-
o, derivedTypeRename);
89+
StructureConstructor{result_.derivedTypeSpec(), value}.AsFortran(o);
9090
}
9191
}
9292
if (Rank() > 0) {
@@ -124,9 +124,89 @@ llvm::raw_ostream &Constant<Type<TypeCategory::Character, KIND>>::AsFortran(
124124
return o;
125125
}
126126

127+
llvm::raw_ostream &EmitVar(llvm::raw_ostream &o, const Symbol &symbol,
128+
std::optional<parser::CharBlock> name = std::nullopt) {
129+
const auto &renamings{symbol.owner().context().moduleFileOutputRenamings()};
130+
if (auto iter{renamings.find(&symbol)}; iter != renamings.end()) {
131+
return o << iter->second.ToString();
132+
} else if (name) {
133+
return o << name->ToString();
134+
} else {
135+
return o << symbol.name().ToString();
136+
}
137+
}
138+
139+
llvm::raw_ostream &EmitVar(llvm::raw_ostream &o, const std::string &lit) {
140+
return o << parser::QuoteCharacterLiteral(lit);
141+
}
142+
143+
llvm::raw_ostream &EmitVar(llvm::raw_ostream &o, const std::u16string &lit) {
144+
return o << parser::QuoteCharacterLiteral(lit);
145+
}
146+
147+
llvm::raw_ostream &EmitVar(llvm::raw_ostream &o, const std::u32string &lit) {
148+
return o << parser::QuoteCharacterLiteral(lit);
149+
}
150+
151+
template <typename A>
152+
llvm::raw_ostream &EmitVar(llvm::raw_ostream &o, const A &x) {
153+
return x.AsFortran(o);
154+
}
155+
156+
template <typename A>
157+
llvm::raw_ostream &EmitVar(llvm::raw_ostream &o, common::Reference<A> x) {
158+
return EmitVar(o, *x);
159+
}
160+
161+
template <typename A>
162+
llvm::raw_ostream &EmitVar(
163+
llvm::raw_ostream &o, const A *p, const char *kw = nullptr) {
164+
if (p) {
165+
if (kw) {
166+
o << kw;
167+
}
168+
EmitVar(o, *p);
169+
}
170+
return o;
171+
}
172+
173+
template <typename A>
174+
llvm::raw_ostream &EmitVar(
175+
llvm::raw_ostream &o, const std::optional<A> &x, const char *kw = nullptr) {
176+
if (x) {
177+
if (kw) {
178+
o << kw;
179+
}
180+
EmitVar(o, *x);
181+
}
182+
return o;
183+
}
184+
185+
template <typename A, bool COPY>
186+
llvm::raw_ostream &EmitVar(llvm::raw_ostream &o,
187+
const common::Indirection<A, COPY> &p, const char *kw = nullptr) {
188+
if (kw) {
189+
o << kw;
190+
}
191+
EmitVar(o, p.value());
192+
return o;
193+
}
194+
195+
template <typename A>
196+
llvm::raw_ostream &EmitVar(llvm::raw_ostream &o, const std::shared_ptr<A> &p) {
197+
CHECK(p);
198+
return EmitVar(o, *p);
199+
}
200+
201+
template <typename... A>
202+
llvm::raw_ostream &EmitVar(llvm::raw_ostream &o, const std::variant<A...> &u) {
203+
common::visit([&](const auto &x) { EmitVar(o, x); }, u);
204+
return o;
205+
}
206+
127207
llvm::raw_ostream &ActualArgument::AssumedType::AsFortran(
128208
llvm::raw_ostream &o) const {
129-
return o << symbol_->name().ToString();
209+
return EmitVar(o, *symbol_);
130210
}
131211

132212
llvm::raw_ostream &ActualArgument::AsFortran(llvm::raw_ostream &o) const {
@@ -504,15 +584,37 @@ llvm::raw_ostream &ExpressionBase<RESULT>::AsFortran(
504584
return o;
505585
}
506586

507-
llvm::raw_ostream &StructureConstructor::AsFortran(
508-
llvm::raw_ostream &o, const parser::CharBlock *derivedTypeRename) const {
509-
o << DerivedTypeSpecAsFortran(result_.derivedTypeSpec(), derivedTypeRename);
587+
static std::string DerivedTypeSpecAsFortran(
588+
const semantics::DerivedTypeSpec &spec) {
589+
std::string buf;
590+
llvm::raw_string_ostream ss{buf};
591+
EmitVar(ss, spec.typeSymbol(), spec.name());
592+
char ch{'('};
593+
for (const auto &[name, value] : spec.parameters()) {
594+
ss << ch << name.ToString() << '=';
595+
ch = ',';
596+
if (value.isAssumed()) {
597+
ss << '*';
598+
} else if (value.isDeferred()) {
599+
ss << ':';
600+
} else {
601+
value.GetExplicit()->AsFortran(ss);
602+
}
603+
}
604+
if (ch != '(') {
605+
ss << ')';
606+
}
607+
return ss.str();
608+
}
609+
610+
llvm::raw_ostream &StructureConstructor::AsFortran(llvm::raw_ostream &o) const {
611+
o << DerivedTypeSpecAsFortran(result_.derivedTypeSpec());
510612
if (values_.empty()) {
511613
o << '(';
512614
} else {
513615
char ch{'('};
514616
for (const auto &[symbol, value] : values_) {
515-
value.value().AsFortran(o << ch << symbol->name().ToString() << '=');
617+
value.value().AsFortran(EmitVar(o << ch, *symbol) << '=');
516618
ch = ',';
517619
}
518620
}
@@ -568,101 +670,6 @@ std::string SomeDerived::AsFortran() const {
568670
}
569671
}
570672

571-
std::string DerivedTypeSpecAsFortran(const semantics::DerivedTypeSpec &spec,
572-
const parser::CharBlock *derivedTypeRename) {
573-
std::string buf;
574-
llvm::raw_string_ostream ss{buf};
575-
ss << (derivedTypeRename ? *derivedTypeRename : spec.name()).ToString();
576-
char ch{'('};
577-
for (const auto &[name, value] : spec.parameters()) {
578-
ss << ch << name.ToString() << '=';
579-
ch = ',';
580-
if (value.isAssumed()) {
581-
ss << '*';
582-
} else if (value.isDeferred()) {
583-
ss << ':';
584-
} else {
585-
value.GetExplicit()->AsFortran(ss);
586-
}
587-
}
588-
if (ch != '(') {
589-
ss << ')';
590-
}
591-
return ss.str();
592-
}
593-
594-
llvm::raw_ostream &EmitVar(llvm::raw_ostream &o, const Symbol &symbol) {
595-
return o << symbol.name().ToString();
596-
}
597-
598-
llvm::raw_ostream &EmitVar(llvm::raw_ostream &o, const std::string &lit) {
599-
return o << parser::QuoteCharacterLiteral(lit);
600-
}
601-
602-
llvm::raw_ostream &EmitVar(llvm::raw_ostream &o, const std::u16string &lit) {
603-
return o << parser::QuoteCharacterLiteral(lit);
604-
}
605-
606-
llvm::raw_ostream &EmitVar(llvm::raw_ostream &o, const std::u32string &lit) {
607-
return o << parser::QuoteCharacterLiteral(lit);
608-
}
609-
610-
template <typename A>
611-
llvm::raw_ostream &EmitVar(llvm::raw_ostream &o, const A &x) {
612-
return x.AsFortran(o);
613-
}
614-
615-
template <typename A>
616-
llvm::raw_ostream &EmitVar(llvm::raw_ostream &o, common::Reference<A> x) {
617-
return EmitVar(o, *x);
618-
}
619-
620-
template <typename A>
621-
llvm::raw_ostream &EmitVar(
622-
llvm::raw_ostream &o, const A *p, const char *kw = nullptr) {
623-
if (p) {
624-
if (kw) {
625-
o << kw;
626-
}
627-
EmitVar(o, *p);
628-
}
629-
return o;
630-
}
631-
632-
template <typename A>
633-
llvm::raw_ostream &EmitVar(
634-
llvm::raw_ostream &o, const std::optional<A> &x, const char *kw = nullptr) {
635-
if (x) {
636-
if (kw) {
637-
o << kw;
638-
}
639-
EmitVar(o, *x);
640-
}
641-
return o;
642-
}
643-
644-
template <typename A, bool COPY>
645-
llvm::raw_ostream &EmitVar(llvm::raw_ostream &o,
646-
const common::Indirection<A, COPY> &p, const char *kw = nullptr) {
647-
if (kw) {
648-
o << kw;
649-
}
650-
EmitVar(o, p.value());
651-
return o;
652-
}
653-
654-
template <typename A>
655-
llvm::raw_ostream &EmitVar(llvm::raw_ostream &o, const std::shared_ptr<A> &p) {
656-
CHECK(p);
657-
return EmitVar(o, *p);
658-
}
659-
660-
template <typename... A>
661-
llvm::raw_ostream &EmitVar(llvm::raw_ostream &o, const std::variant<A...> &u) {
662-
common::visit([&](const auto &x) { EmitVar(o, x); }, u);
663-
return o;
664-
}
665-
666673
llvm::raw_ostream &BaseObject::AsFortran(llvm::raw_ostream &o) const {
667674
return EmitVar(o, u);
668675
}

0 commit comments

Comments
 (0)