[flang-commits] [flang] 635656f - [flang] Expunge needless semantics::ProcInterface

Peter Klausler via flang-commits flang-commits at lists.llvm.org
Fri Dec 16 10:44:41 PST 2022


Author: Peter Klausler
Date: 2022-12-16T10:44:29-08:00
New Revision: 635656f4ff1e0b74761af109f50d33287477d1db

URL: https://github.com/llvm/llvm-project/commit/635656f4ff1e0b74761af109f50d33287477d1db
DIFF: https://github.com/llvm/llvm-project/commit/635656f4ff1e0b74761af109f50d33287477d1db.diff

LOG: [flang] Expunge needless semantics::ProcInterface

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

Added: 
    flang/test/Semantics/procinterface03.f90

Modified: 
    flang/include/flang/Evaluate/characteristics.h
    flang/include/flang/Semantics/symbol.h
    flang/include/flang/Semantics/type.h
    flang/lib/Evaluate/call.cpp
    flang/lib/Evaluate/characteristics.cpp
    flang/lib/Evaluate/shape.cpp
    flang/lib/Evaluate/tools.cpp
    flang/lib/Semantics/check-declarations.cpp
    flang/lib/Semantics/mod-file.cpp
    flang/lib/Semantics/resolve-names-utils.cpp
    flang/lib/Semantics/resolve-names.cpp
    flang/lib/Semantics/symbol.cpp
    flang/lib/Semantics/tools.cpp
    flang/lib/Semantics/type.cpp

Removed: 
    


################################################################################
diff  --git a/flang/include/flang/Evaluate/characteristics.h b/flang/include/flang/Evaluate/characteristics.h
index dd5bd47473805..7d305e563b646 100644
--- a/flang/include/flang/Evaluate/characteristics.h
+++ b/flang/include/flang/Evaluate/characteristics.h
@@ -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(

diff  --git a/flang/include/flang/Semantics/symbol.h b/flang/include/flang/Semantics/symbol.h
index 7034b0cb52aa8..1dc5cb0293a6c 100644
--- a/flang/include/flang/Semantics/symbol.h
+++ b/flang/include/flang/Semantics/symbol.h
@@ -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,
@@ -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 &);
@@ -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) {
@@ -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() {
@@ -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);

diff  --git a/flang/include/flang/Semantics/type.h b/flang/include/flang/Semantics/type.h
index c60dc9f5f6c84..6277a8b729cdb 100644
--- a/flang/include/flang/Semantics/type.h
+++ b/flang/include/flang/Semantics/type.h
@@ -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.
 

diff  --git a/flang/lib/Evaluate/call.cpp b/flang/lib/Evaluate/call.cpp
index 829af505b5f12..55631ee2a476c 100644
--- a/flang/lib/Evaluate/call.cpp
+++ b/flang/lib/Evaluate/call.cpp
@@ -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();

diff  --git a/flang/lib/Evaluate/characteristics.cpp b/flang/lib/Evaluate/characteristics.cpp
index 0b22e8de8267c..9c5f243a590a2 100644
--- a/flang/lib/Evaluate/characteristics.cpp
+++ b/flang/lib/Evaluate/characteristics.cpp
@@ -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>{};
             }
@@ -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)
               };
@@ -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);

diff  --git a/flang/lib/Evaluate/shape.cpp b/flang/lib/Evaluate/shape.cpp
index 994c1b6c7b924..661116bd4b210 100644
--- a/flang/lib/Evaluate/shape.cpp
+++ b/flang/lib/Evaluate/shape.cpp
@@ -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();

diff  --git a/flang/lib/Evaluate/tools.cpp b/flang/lib/Evaluate/tools.cpp
index 278a40e8be3ef..3b472e7249e4a 100644
--- a/flang/lib/Evaluate/tools.cpp
+++ b/flang/lib/Evaluate/tools.cpp
@@ -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());
@@ -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) &&
@@ -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());
@@ -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) {

diff  --git a/flang/lib/Semantics/check-declarations.cpp b/flang/lib/Semantics/check-declarations.cpp
index 0aca16d33bd4f..f6a7f4e5d1547 100644
--- a/flang/lib/Semantics/check-declarations.cpp
+++ b/flang/lib/Semantics/check-declarations.cpp
@@ -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) ||
@@ -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{
@@ -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);

diff  --git a/flang/lib/Semantics/mod-file.cpp b/flang/lib/Semantics/mod-file.cpp
index e635669c238cd..5a4aeef806f04 100644
--- a/flang/lib/Semantics/mod-file.cpp
+++ b/flang/lib/Semantics/mod-file.cpp
@@ -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);
@@ -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());
@@ -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;
             }
           }
@@ -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 &) {},
                 },

diff  --git a/flang/lib/Semantics/resolve-names-utils.cpp b/flang/lib/Semantics/resolve-names-utils.cpp
index b0c64abd4c696..bd628f47e26c2 100644
--- a/flang/lib/Semantics/resolve-names-utils.cpp
+++ b/flang/lib/Semantics/resolve-names-utils.cpp
@@ -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());
 }
 

diff  --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index 8d5ce36a7f9ea..29a7c2fe286d9 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -1082,7 +1082,8 @@ class DeclarationVisitor : public ArraySpecVisitor,
   bool HandleAttributeStmt(Attr, const std::list<parser::Name> &);
   Symbol &HandleAttributeStmt(Attr, const parser::Name &);
   Symbol &DeclareUnknownEntity(const parser::Name &, Attrs);
-  Symbol &DeclareProcEntity(const parser::Name &, Attrs, const ProcInterface &);
+  Symbol &DeclareProcEntity(
+      const parser::Name &, Attrs, const Symbol *interface);
   void SetType(const parser::Name &, const DeclTypeSpec &);
   std::optional<DerivedTypeSpec> ResolveDerivedType(const parser::Name &);
   std::optional<DerivedTypeSpec> ResolveExtendsType(
@@ -1156,7 +1157,7 @@ class DeclarationVisitor : public ArraySpecVisitor,
     context().SetError(symbol);
     return symbol;
   }
-  bool HasCycle(const Symbol &, const ProcInterface &);
+  bool HasCycle(const Symbol &, const Symbol *interface);
 };
 
 // Resolve construct entities and statement entities.
@@ -2377,7 +2378,7 @@ static bool NeedsType(const Symbol &symbol) {
                         [&](const ProcEntityDetails &p) {
                           return symbol.test(Symbol::Flag::Function) &&
                               !symbol.attrs().test(Attr::INTRINSIC) &&
-                              !p.interface().type() && !p.interface().symbol();
+                              !p.type() && !p.procInterface();
                         },
                         [](const auto &) { return false; },
                     },
@@ -4385,36 +4386,32 @@ Symbol &DeclarationVisitor::DeclareUnknownEntity(
 }
 
 bool DeclarationVisitor::HasCycle(
-    const Symbol &procSymbol, const ProcInterface &interface) {
+    const Symbol &procSymbol, const Symbol *interface) {
   SourceOrderedSymbolSet procsInCycle;
   procsInCycle.insert(procSymbol);
-  const ProcInterface *thisInterface{&interface};
-  bool haveInterface{true};
-  while (haveInterface) {
-    haveInterface = false;
-    if (const Symbol * interfaceSymbol{thisInterface->symbol()}) {
-      if (procsInCycle.count(*interfaceSymbol) > 0) {
-        for (const auto &procInCycle : procsInCycle) {
-          Say(procInCycle->name(),
-              "The interface for procedure '%s' is recursively "
-              "defined"_err_en_US,
-              procInCycle->name());
-          context().SetError(*procInCycle);
-        }
-        return true;
-      } else if (const auto *procDetails{
-                     interfaceSymbol->detailsIf<ProcEntityDetails>()}) {
-        haveInterface = true;
-        thisInterface = &procDetails->interface();
-        procsInCycle.insert(*interfaceSymbol);
+  while (interface) {
+    if (procsInCycle.count(*interface) > 0) {
+      for (const auto &procInCycle : procsInCycle) {
+        Say(procInCycle->name(),
+            "The interface for procedure '%s' is recursively "
+            "defined"_err_en_US,
+            procInCycle->name());
+        context().SetError(*procInCycle);
       }
+      return true;
+    } else if (const auto *procDetails{
+                   interface->detailsIf<ProcEntityDetails>()}) {
+      procsInCycle.insert(*interface);
+      interface = procDetails->procInterface();
+    } else {
+      break;
     }
   }
   return false;
 }
 
 Symbol &DeclarationVisitor::DeclareProcEntity(
-    const parser::Name &name, Attrs attrs, const ProcInterface &interface) {
+    const parser::Name &name, Attrs attrs, const Symbol *interface) {
   Symbol &symbol{DeclareEntity<ProcEntityDetails>(name, attrs)};
   if (auto *details{symbol.detailsIf<ProcEntityDetails>()}) {
     if (details->IsInterfaceSet()) {
@@ -4424,16 +4421,17 @@ Symbol &DeclarationVisitor::DeclareProcEntity(
       context().SetError(symbol);
     } else if (HasCycle(symbol, interface)) {
       return symbol;
-    } else if (interface.type()) {
-      symbol.set(Symbol::Flag::Function);
-    } else if (interface.symbol()) {
-      if (interface.symbol()->test(Symbol::Flag::Function)) {
+    } else if (interface) {
+      details->set_procInterface(*interface);
+      if (interface->test(Symbol::Flag::Function)) {
         symbol.set(Symbol::Flag::Function);
-      } else if (interface.symbol()->test(Symbol::Flag::Subroutine)) {
+      } else if (interface->test(Symbol::Flag::Subroutine)) {
         symbol.set(Symbol::Flag::Subroutine);
       }
+    } else if (auto *type{GetDeclTypeSpec()}) {
+      SetType(name, *type);
+      symbol.set(Symbol::Flag::Function);
     }
-    details->set_interface(interface);
     SetBindNameOn(symbol);
     SetPassNameOn(symbol);
   }
@@ -4960,11 +4958,9 @@ void DeclarationVisitor::Post(const parser::ProcInterface &x) {
 }
 void DeclarationVisitor::Post(const parser::ProcDecl &x) {
   const auto &name{std::get<parser::Name>(x.t)};
-  ProcInterface interface;
+  const Symbol *procInterface{nullptr};
   if (interfaceName_) {
-    interface.set_symbol(*interfaceName_->symbol);
-  } else if (auto *type{GetDeclTypeSpec()}) {
-    interface.set_type(*type);
+    procInterface = interfaceName_->symbol;
   }
   auto attrs{HandleSaveName(name.source, GetAttrs())};
   DerivedTypeDetails *dtDetails{nullptr};
@@ -4974,7 +4970,7 @@ void DeclarationVisitor::Post(const parser::ProcDecl &x) {
   if (!dtDetails) {
     attrs.set(Attr::EXTERNAL);
   }
-  Symbol &symbol{DeclareProcEntity(name, attrs, interface)};
+  Symbol &symbol{DeclareProcEntity(name, attrs, procInterface)};
   symbol.ReplaceName(name.source);
   if (dtDetails) {
     dtDetails->add_component(symbol);
@@ -5688,9 +5684,7 @@ bool DeclarationVisitor::HandleUnrestrictedSpecificIntrinsicFunction(
     const DeclTypeSpec &typeSpec{
         MakeNumericType(dyType.category(), dyType.kind())};
     ProcEntityDetails details;
-    ProcInterface procInterface;
-    procInterface.set_type(typeSpec);
-    details.set_interface(procInterface);
+    details.set_type(typeSpec);
     symbol.set_details(std::move(details));
     symbol.set(Symbol::Flag::Function);
     if (interface->IsElemental()) {
@@ -5847,6 +5841,14 @@ void DeclarationVisitor::SetType(
           "A length specifier cannot be used to declare the non-character entity '%s'"_err_en_US);
     }
   }
+  if (auto *proc{symbol.detailsIf<ProcEntityDetails>()}) {
+    if (proc->procInterface()) {
+      Say(name,
+          "'%s' has an explicit interface and may not also have a type"_err_en_US);
+      context().SetError(symbol);
+      return;
+    }
+  }
   auto *prevType{symbol.GetType()};
   if (!prevType) {
     symbol.SetType(type);
@@ -7241,7 +7243,7 @@ static bool NeedsExplicitType(const Symbol &symbol) {
   } else if (const auto *details{symbol.detailsIf<ObjectEntityDetails>()}) {
     return !details->type();
   } else if (const auto *details{symbol.detailsIf<ProcEntityDetails>()}) {
-    return !details->interface().symbol() && !details->interface().type();
+    return !details->procInterface() && !details->type();
   } else {
     return false;
   }

diff  --git a/flang/lib/Semantics/symbol.cpp b/flang/lib/Semantics/symbol.cpp
index fb30f6e4d687a..8e7db6dcbfb5b 100644
--- a/flang/lib/Semantics/symbol.cpp
+++ b/flang/lib/Semantics/symbol.cpp
@@ -137,7 +137,7 @@ void AssocEntityDetails::set_rank(int rank) { rank_ = rank; }
 void EntityDetails::ReplaceType(const DeclTypeSpec &type) { type_ = &type; }
 
 ObjectEntityDetails::ObjectEntityDetails(EntityDetails &&d)
-    : EntityDetails(d) {}
+    : EntityDetails(std::move(d)) {}
 
 void ObjectEntityDetails::set_shape(const ArraySpec &shape) {
   CHECK(shape_.empty());
@@ -152,11 +152,8 @@ void ObjectEntityDetails::set_coshape(const ArraySpec &coshape) {
   }
 }
 
-ProcEntityDetails::ProcEntityDetails(EntityDetails &&d) : EntityDetails(d) {
-  if (type()) {
-    interface_.set_type(*type());
-  }
-}
+ProcEntityDetails::ProcEntityDetails(EntityDetails &&d)
+    : EntityDetails(std::move(d)) {}
 
 UseErrorDetails::UseErrorDetails(const UseDetails &useDetails) {
   add_occurrence(useDetails.location(), *GetUsedModule(useDetails).scope());
@@ -301,7 +298,7 @@ void Symbol::SetType(const DeclTypeSpec &type) {
                     [&](EntityDetails &x) { x.set_type(type); },
                     [&](ObjectEntityDetails &x) { x.set_type(type); },
                     [&](AssocEntityDetails &x) { x.set_type(type); },
-                    [&](ProcEntityDetails &x) { x.interface().set_type(type); },
+                    [&](ProcEntityDetails &x) { x.set_type(type); },
                     [&](TypeParamDetails &x) { x.set_type(type); },
                     [](auto &) {},
                 },
@@ -401,10 +398,10 @@ llvm::raw_ostream &operator<<(
 
 llvm::raw_ostream &operator<<(
     llvm::raw_ostream &os, const ProcEntityDetails &x) {
-  if (auto *symbol{x.interface_.symbol()}) {
-    os << ' ' << symbol->name();
+  if (x.procInterface_) {
+    os << ' ' << x.procInterface_->name();
   } else {
-    DumpType(os, x.interface_.type());
+    DumpType(os, x.type());
   }
   DumpOptional(os, "bindName", x.bindName());
   DumpOptional(os, "passName", x.passName());

diff  --git a/flang/lib/Semantics/tools.cpp b/flang/lib/Semantics/tools.cpp
index c3c40ec0e57c8..73f3a20d78f13 100644
--- a/flang/lib/Semantics/tools.cpp
+++ b/flang/lib/Semantics/tools.cpp
@@ -280,9 +280,9 @@ bool IsPointerDummy(const Symbol &symbol) {
 
 bool IsBindCProcedure(const Symbol &symbol) {
   if (const auto *procDetails{symbol.detailsIf<ProcEntityDetails>()}) {
-    if (const Symbol * procInterface{procDetails->interface().symbol()}) {
+    if (procDetails->procInterface()) {
       // procedure component with a BIND(C) interface
-      return IsBindCProcedure(*procInterface);
+      return IsBindCProcedure(*procDetails->procInterface());
     }
   }
   return symbol.attrs().test(Attr::BIND_C) && IsProcedure(symbol);
@@ -456,7 +456,9 @@ const Symbol *FindInterface(const Symbol &symbol) {
   return common::visit(
       common::visitors{
           [](const ProcEntityDetails &details) {
-            const Symbol *interface { details.interface().symbol() };
+            const Symbol *interface {
+              details.procInterface()
+            };
             return interface ? FindInterface(*interface) : nullptr;
           },
           [](const ProcBindingDetails &details) {
@@ -482,8 +484,8 @@ const Symbol *FindSubprogram(const Symbol &symbol) {
   return common::visit(
       common::visitors{
           [&](const ProcEntityDetails &details) -> const Symbol * {
-            if (const Symbol * interface{details.interface().symbol()}) {
-              return FindSubprogram(*interface);
+            if (details.procInterface()) {
+              return FindSubprogram(*details.procInterface());
             } else {
               return &symbol;
             }

diff  --git a/flang/lib/Semantics/type.cpp b/flang/lib/Semantics/type.cpp
index 4560c47353835..b8fc2a67d5776 100644
--- a/flang/lib/Semantics/type.cpp
+++ b/flang/lib/Semantics/type.cpp
@@ -463,10 +463,8 @@ void InstantiateHelper::InstantiateComponent(const Symbol &oldSymbol) {
   } else if (auto *procDetails{newSymbol.detailsIf<ProcEntityDetails>()}) {
     // We have a procedure pointer.  Instantiate its return type
     if (const DeclTypeSpec * returnType{InstantiateType(newSymbol)}) {
-      ProcInterface &interface{procDetails->interface()};
-      if (!interface.symbol()) {
-        // Don't change the type for interfaces based on symbols
-        interface.set_type(*returnType);
+      if (!procDetails->procInterface()) {
+        procDetails->ReplaceType(*returnType);
       }
     }
   }
@@ -792,13 +790,4 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &o, const DeclTypeSpec &x) {
   return o << x.AsFortran();
 }
 
-void ProcInterface::set_symbol(const Symbol &symbol) {
-  CHECK(!type_);
-  symbol_ = &symbol;
-}
-void ProcInterface::set_type(const DeclTypeSpec &type) {
-  CHECK(!symbol_);
-  type_ = &type;
-}
-
 } // namespace Fortran::semantics

diff  --git a/flang/test/Semantics/procinterface03.f90 b/flang/test/Semantics/procinterface03.f90
new file mode 100644
index 0000000000000..fab2a37bf27fa
--- /dev/null
+++ b/flang/test/Semantics/procinterface03.f90
@@ -0,0 +1,5 @@
+! RUN: %python %S/test_errors.py %s %flang_fc1
+procedure(sin), pointer :: pp
+!ERROR: 'pp' has an explicit interface and may not also have a type
+real :: pp
+end


        


More information about the flang-commits mailing list