Skip to content

Commit

Permalink
[flang] Expunge needless semantics::ProcInterface
Browse files Browse the repository at this point in the history
The ProcInterface structure is used only by ProcEntityDetails; it represents
what a program might have put in parentheses in a procedure-declaration-stmt,
either the name of a procedure interface or a declaration-type-spec.

If a procedure entity has an implicit interface, the function result
type (if any) can be kept in EntityDetails::type_, which already exists
and is currently redundant for ProcEntityDetails symbols.

All that is really needed is a nullable Symbol pointer in ProcEntityDetails
to point to the procedure's explicit interface, when it has one.

Also, catch the case where a procedure has an explicit interface
and a program attempts to also give it a type.

Differential Revision: https://reviews.llvm.org/D140134
  • Loading branch information
klausler committed Dec 16, 2022
1 parent 38e9660 commit 635656f
Show file tree
Hide file tree
Showing 15 changed files with 127 additions and 158 deletions.
2 changes: 0 additions & 2 deletions flang/include/flang/Evaluate/characteristics.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,6 @@ class TypeAndShape {

static std::optional<TypeAndShape> Characterize(
const semantics::Symbol &, FoldingContext &);
static std::optional<TypeAndShape> Characterize(
const semantics::ProcInterface &, FoldingContext &);
static std::optional<TypeAndShape> Characterize(
const semantics::DeclTypeSpec &, FoldingContext &);
static std::optional<TypeAndShape> Characterize(
Expand Down
22 changes: 8 additions & 14 deletions flang/include/flang/Semantics/symbol.h
Original file line number Diff line number Diff line change
Expand Up @@ -257,12 +257,9 @@ class ProcEntityDetails : public EntityDetails, public WithPassArg {
ProcEntityDetails(ProcEntityDetails &&) = default;
ProcEntityDetails &operator=(const ProcEntityDetails &) = default;

const ProcInterface &interface() const { return interface_; }
ProcInterface &interface() { return interface_; }
void set_interface(const ProcInterface &interface) { interface_ = interface; }
bool IsInterfaceSet() {
return interface_.symbol() != nullptr || interface_.type() != nullptr;
}
const Symbol *procInterface() const { return procInterface_; }
void set_procInterface(const Symbol &sym) { procInterface_ = &sym; }
bool IsInterfaceSet() { return procInterface_ || type(); }
inline bool HasExplicitInterface() const;

// Be advised: !init().has_value() => uninitialized pointer,
Expand All @@ -272,7 +269,7 @@ class ProcEntityDetails : public EntityDetails, public WithPassArg {
void set_init(std::nullptr_t) { init_ = nullptr; }

private:
ProcInterface interface_;
const Symbol *procInterface_{nullptr};
std::optional<const Symbol *> init_;
friend llvm::raw_ostream &operator<<(
llvm::raw_ostream &, const ProcEntityDetails &);
Expand Down Expand Up @@ -731,7 +728,7 @@ class Symbol {
},
[](const ObjectEntityDetails &oed) { return oed.shape().Rank(); },
[&](const ProcEntityDetails &ped) {
const Symbol *iface{ped.interface().symbol()};
const Symbol *iface{ped.procInterface()};
return iface ? iface->RankImpl(depth) : 0;
},
[](const AssocEntityDetails &aed) {
Expand Down Expand Up @@ -794,10 +791,7 @@ template <std::size_t BLOCK_SIZE> class Symbols {
// between the two shared libraries.

inline bool ProcEntityDetails::HasExplicitInterface() const {
if (auto *symbol{interface_.symbol()}) {
return symbol->HasExplicitInterface();
}
return false;
return procInterface_ && procInterface_->HasExplicitInterface();
}

inline Symbol &Symbol::GetUltimate() {
Expand Down Expand Up @@ -831,8 +825,8 @@ inline const DeclTypeSpec *Symbol::GetTypeImpl(int depth) const {
return x.isFunction() ? x.result().GetTypeImpl(depth) : nullptr;
},
[&](const ProcEntityDetails &x) {
const Symbol *symbol{x.interface().symbol()};
return symbol ? symbol->GetTypeImpl(depth) : x.interface().type();
const Symbol *symbol{x.procInterface()};
return symbol ? symbol->GetTypeImpl(depth) : x.type();
},
[&](const ProcBindingDetails &x) {
return x.symbol().GetTypeImpl(depth);
Expand Down
15 changes: 0 additions & 15 deletions flang/include/flang/Semantics/type.h
Original file line number Diff line number Diff line change
Expand Up @@ -389,21 +389,6 @@ class DeclTypeSpec {
};
llvm::raw_ostream &operator<<(llvm::raw_ostream &, const DeclTypeSpec &);

// This represents a proc-interface in the declaration of a procedure or
// procedure component. It comprises a symbol that represents the specific
// interface or a decl-type-spec that represents the function return type.
class ProcInterface {
public:
const Symbol *symbol() const { return symbol_; }
const DeclTypeSpec *type() const { return type_; }
void set_symbol(const Symbol &symbol);
void set_type(const DeclTypeSpec &type);

private:
const Symbol *symbol_{nullptr};
const DeclTypeSpec *type_{nullptr};
};

// Define some member functions here in the header so that they can be used by
// lib/Evaluate without link-time dependency on Semantics.

Expand Down
2 changes: 1 addition & 1 deletion flang/lib/Evaluate/call.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ const Symbol *ProcedureDesignator::GetInterfaceSymbol() const {
if (const Symbol * symbol{GetSymbol()}) {
const Symbol &ultimate{symbol->GetUltimate()};
if (const auto *proc{ultimate.detailsIf<semantics::ProcEntityDetails>()}) {
return proc->interface().symbol();
return proc->procInterface();
} else if (const auto *binding{
ultimate.detailsIf<semantics::ProcBindingDetails>()}) {
return &binding->symbol();
Expand Down
15 changes: 7 additions & 8 deletions flang/lib/Evaluate/characteristics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,10 @@ std::optional<TypeAndShape> TypeAndShape::Characterize(
return common::visit(
common::visitors{
[&](const semantics::ProcEntityDetails &proc) {
const semantics::ProcInterface &interface { proc.interface() };
if (interface.type()) {
return Characterize(*interface.type(), context);
} else if (interface.symbol()) {
return Characterize(*interface.symbol(), context);
if (proc.procInterface()) {
return Characterize(*proc.procInterface(), context);
} else if (proc.type()) {
return Characterize(*proc.type(), context);
} else {
return std::optional<TypeAndShape>{};
}
Expand Down Expand Up @@ -506,8 +505,8 @@ static std::optional<Procedure> CharacterizeProcedure(
}
return intrinsic;
}
const semantics::ProcInterface &interface { proc.interface() };
if (const semantics::Symbol * interfaceSymbol{interface.symbol()}) {
if (const semantics::Symbol *
interfaceSymbol{proc.procInterface()}) {
auto interface {
CharacterizeProcedure(*interfaceSymbol, context, seenProcs)
};
Expand All @@ -517,7 +516,7 @@ static std::optional<Procedure> CharacterizeProcedure(
return interface;
} else {
result.attrs.set(Procedure::Attr::ImplicitInterface);
const semantics::DeclTypeSpec *type{interface.type()};
const semantics::DeclTypeSpec *type{proc.type()};
if (symbol.test(semantics::Symbol::Flag::Subroutine)) {
// ignore any implicit typing
result.attrs.set(Procedure::Attr::Subroutine);
Expand Down
2 changes: 1 addition & 1 deletion flang/lib/Evaluate/shape.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -690,7 +690,7 @@ auto GetShapeHelper::operator()(const Symbol &symbol) const -> Result {
return ScalarShape(); // no dimensions seen
},
[&](const semantics::ProcEntityDetails &proc) {
if (const Symbol * interface{proc.interface().symbol()}) {
if (const Symbol * interface{proc.procInterface()}) {
return (*this)(*interface);
} else {
return ScalarShape();
Expand Down
13 changes: 6 additions & 7 deletions flang/lib/Evaluate/tools.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1254,9 +1254,9 @@ bool IsPureProcedure(const Symbol &original) {
// An ENTRY is pure if its containing subprogram is
const Symbol &symbol{DEREF(GetMainEntry(&original.GetUltimate()))};
if (const auto *procDetails{symbol.detailsIf<ProcEntityDetails>()}) {
if (const Symbol * procInterface{procDetails->interface().symbol()}) {
if (procDetails->procInterface()) {
// procedure with a pure interface
return IsPureProcedure(*procInterface);
return IsPureProcedure(*procDetails->procInterface());
}
} else if (const auto *details{symbol.detailsIf<ProcBindingDetails>()}) {
return IsPureProcedure(details->symbol());
Expand Down Expand Up @@ -1295,7 +1295,7 @@ bool IsElementalProcedure(const Symbol &original) {
// An ENTRY is elemental if its containing subprogram is
const Symbol &symbol{DEREF(GetMainEntry(&original.GetUltimate()))};
if (const auto *procDetails{symbol.detailsIf<ProcEntityDetails>()}) {
if (const Symbol * procInterface{procDetails->interface().symbol()}) {
if (const Symbol * procInterface{procDetails->procInterface()}) {
// procedure with an elemental interface, ignoring the elemental
// aspect of intrinsic functions
return !procInterface->attrs().test(Attr::INTRINSIC) &&
Expand All @@ -1318,9 +1318,8 @@ bool IsFunction(const Symbol &symbol) {
common::visitors{
[](const SubprogramDetails &x) { return x.isFunction(); },
[](const ProcEntityDetails &x) {
const auto &ifc{x.interface()};
return ifc.type() ||
(ifc.symbol() && IsFunction(*ifc.symbol()));
const Symbol *ifc{x.procInterface()};
return x.type() || (ifc && IsFunction(*ifc));
},
[](const ProcBindingDetails &x) {
return IsFunction(x.symbol());
Expand Down Expand Up @@ -1618,7 +1617,7 @@ static const Symbol *FindFunctionResult(
return subp.isFunction() ? &subp.result() : nullptr;
},
[&](const ProcEntityDetails &proc) {
const Symbol *iface{proc.interface().symbol()};
const Symbol *iface{proc.procInterface()};
return iface ? FindFunctionResult(*iface, seen) : nullptr;
},
[&](const ProcBindingDetails &binding) {
Expand Down
10 changes: 5 additions & 5 deletions flang/lib/Semantics/check-declarations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -823,7 +823,7 @@ void CheckHelper::CheckProcEntity(
"An ELEMENTAL subprogram may not have a dummy procedure"_err_en_US);
}
const Symbol *interface {
details.interface().symbol()
details.procInterface()
};
if (!symbol.attrs().test(Attr::INTRINSIC) &&
(IsElementalProcedure(symbol) ||
Expand Down Expand Up @@ -852,11 +852,11 @@ void CheckHelper::CheckProcEntity(
"Procedure component '%s' must have POINTER attribute"_err_en_US,
name);
}
CheckPassArg(symbol, details.interface().symbol(), details);
CheckPassArg(symbol, details.procInterface(), details);
}
if (symbol.attrs().test(Attr::POINTER)) {
CheckPointerInitialization(symbol);
if (const Symbol *interface{details.interface().symbol()}) {
if (const Symbol * interface{details.procInterface()}) {
const Symbol &ultimate{interface->GetUltimate()};
if (ultimate.attrs().test(Attr::INTRINSIC)) {
if (const auto intrinsic{
Expand Down Expand Up @@ -2056,8 +2056,8 @@ void CheckHelper::CheckBindC(const Symbol &symbol) {
}
}
if (const auto *proc{symbol.detailsIf<ProcEntityDetails>()}) {
if (!proc->interface().symbol() ||
!proc->interface().symbol()->attrs().test(Attr::BIND_C)) {
if (!proc->procInterface() ||
!proc->procInterface()->attrs().test(Attr::BIND_C)) {
messages_.Say(symbol.name(),
"An interface name with BIND attribute must be specified if the BIND attribute is specified in a procedure declaration statement"_err_en_US);
context_.SetError(symbol);
Expand Down
19 changes: 9 additions & 10 deletions flang/lib/Semantics/mod-file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -693,7 +693,6 @@ void ModFileWriter::PutProcEntity(llvm::raw_ostream &os, const Symbol &symbol) {
return;
}
const auto &details{symbol.get<ProcEntityDetails>()};
const ProcInterface &interface { details.interface() };
Attrs attrs{symbol.attrs()};
if (details.passName()) {
attrs.reset(Attr::PASS);
Expand All @@ -702,10 +701,10 @@ void ModFileWriter::PutProcEntity(llvm::raw_ostream &os, const Symbol &symbol) {
os, symbol,
[&]() {
os << "procedure(";
if (interface.symbol()) {
os << interface.symbol()->name();
} else if (interface.type()) {
PutType(os, *interface.type());
if (details.procInterface()) {
os << details.procInterface()->name();
} else if (details.type()) {
PutType(os, *details.type());
}
os << ')';
PutPassName(os, details.passName());
Expand Down Expand Up @@ -1135,8 +1134,7 @@ void SubprogramSymbolCollector::Collect() {
// Is 's' a procedure with interface 'symbol'?
if (s) {
if (const auto *sDetails{s->detailsIf<ProcEntityDetails>()}) {
const ProcInterface &sInterface{sDetails->interface()};
if (sInterface.symbol() == &symbol) {
if (sDetails->procInterface() == &symbol) {
return true;
}
}
Expand Down Expand Up @@ -1195,10 +1193,11 @@ void SubprogramSymbolCollector::DoSymbol(
}
},
[this](const ProcEntityDetails &details) {
if (const Symbol * symbol{details.interface().symbol()}) {
DoSymbol(*symbol);
if (details.procInterface()) {
DoSymbol(*details.procInterface());
} else {
DoType(details.type());
}
DoType(details.interface().type());
},
[](const auto &) {},
},
Expand Down
56 changes: 28 additions & 28 deletions flang/lib/Semantics/resolve-names-utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -798,34 +798,34 @@ void SymbolMapper::MapSymbolExprs(Symbol &symbol) {
}
}
}
common::visit(common::visitors{[&](ObjectEntityDetails &object) {
for (ShapeSpec &spec : object.shape()) {
MapShapeSpec(spec);
}
for (ShapeSpec &spec : object.coshape()) {
MapShapeSpec(spec);
}
},
[&](ProcEntityDetails &proc) {
if (const Symbol *mappedSymbol{
MapInterface(proc.interface().symbol())}) {
proc.interface().set_symbol(*mappedSymbol);
} else if (const DeclTypeSpec *mappedType{
MapType(proc.interface().type())}) {
proc.interface().set_type(*mappedType);
}
if (proc.init()) {
if (const Symbol *mapped{MapSymbol(*proc.init())}) {
proc.set_init(*mapped);
}
}
},
[&](const HostAssocDetails &hostAssoc) {
if (const Symbol *mapped{MapSymbol(hostAssoc.symbol())}) {
symbol.set_details(HostAssocDetails{*mapped});
}
},
[](const auto &) {}},
common::visit(
common::visitors{[&](ObjectEntityDetails &object) {
for (ShapeSpec &spec : object.shape()) {
MapShapeSpec(spec);
}
for (ShapeSpec &spec : object.coshape()) {
MapShapeSpec(spec);
}
},
[&](ProcEntityDetails &proc) {
if (const Symbol *
mappedSymbol{MapInterface(proc.procInterface())}) {
proc.set_procInterface(*mappedSymbol);
} else if (const DeclTypeSpec * mappedType{MapType(proc.type())}) {
proc.set_type(*mappedType);
}
if (proc.init()) {
if (const Symbol * mapped{MapSymbol(*proc.init())}) {
proc.set_init(*mapped);
}
}
},
[&](const HostAssocDetails &hostAssoc) {
if (const Symbol * mapped{MapSymbol(hostAssoc.symbol())}) {
symbol.set_details(HostAssocDetails{*mapped});
}
},
[](const auto &) {}},
symbol.details());
}

Expand Down
Loading

0 comments on commit 635656f

Please sign in to comment.