[flang] Add common base class for context, Walk(), and Say()
authorTim Keith <tkeith@nvidia.com>
Sat, 17 Nov 2018 00:40:00 +0000 (16:40 -0800)
committerTim Keith <tkeith@nvidia.com>
Thu, 6 Dec 2018 15:16:52 +0000 (07:16 -0800)
We need access to the SemanticsContext and Walk() function everywhere,
so move them to a BaseVisitor, a base class at the root of the class
hierarchy.

Also move MessageHandler to be a data member of BaseVisitor and forward
Say calls to it.

Original-commit: flang-compiler/f18@eb9adc342a5495b0070a14d163f55209c63623d7
Reviewed-on: https://github.com/flang-compiler/f18/pull/238
Tree-same-pre-rewrite: false

flang/lib/semantics/resolve-names.cc

index 10727c0..6e7a427 100644 (file)
@@ -33,7 +33,11 @@ namespace Fortran::semantics {
 
 using namespace parser::literals;
 
-class MessageHandler;
+using Message = parser::Message;
+using Messages = parser::Messages;
+using MessageFixedText = parser::MessageFixedText;
+using MessageFormattedText = parser::MessageFormattedText;
+
 class ResolveNamesVisitor;
 
 static const parser::Name *GetGenericSpecName(const parser::GenericSpec &);
@@ -82,8 +86,57 @@ private:
   friend void ShowImplicitRule(std::ostream &, const ImplicitRules &, char);
 };
 
+// Track statement source locations and save messages.
+class MessageHandler {
+public:
+  void set_messages(Messages &messages) { messages_ = &messages; }
+  const SourceName *currStmtSource() { return currStmtSource_; }
+  void set_currStmtSource(const SourceName *);
+
+  // Emit a message
+  Message &Say(Message &&);
+  // Emit a message associated with the current statement source.
+  Message &Say(MessageFixedText &&);
+  // Emit a message about a SourceName
+  Message &Say(const SourceName &, MessageFixedText &&);
+  // Emit a formatted message associated with a source location.
+  Message &Say(const SourceName &, MessageFixedText &&, const SourceName &);
+  Message &Say(const SourceName &, MessageFixedText &&, const SourceName &,
+      const SourceName &);
+
+private:
+  // Where messages are emitted:
+  Messages *messages_{nullptr};
+  // Source location of current statement; null if not in a statement
+  const SourceName *currStmtSource_{nullptr};
+};
+
+class BaseVisitor {
+public:
+  template<typename T> void Walk(const T &);
+  void set_this(ResolveNamesVisitor *x) { this_ = x; }
+
+  MessageHandler &messageHandler() { return messageHandler_; }
+  const SourceName *currStmtSource();
+  SemanticsContext &context() const { return *context_; }
+  void set_context(SemanticsContext &);
+
+  template<typename... A>
+  Message &Say(const parser::Name &name, MessageFixedText &&msg, A... args) {
+    return Say(name.source, std::move(msg), std::forward<A>(args)...);
+  }
+  template<typename... A> Message &Say(A... args) {
+    return messageHandler_.Say(std::forward<A>(args)...);
+  }
+
+private:
+  ResolveNamesVisitor *this_{nullptr};
+  SemanticsContext *context_{nullptr};
+  MessageHandler messageHandler_;
+};
+
 // Provide Post methods to collect attributes into a member variable.
-class AttrsVisitor {
+class AttrsVisitor : public virtual BaseVisitor {
 public:
   bool BeginAttrs();  // always returns true
   Attrs GetAttrs();
@@ -166,9 +219,6 @@ public:
   bool Pre(const parser::TypeGuardStmt &);
   void Post(const parser::TypeGuardStmt &);
 
-  SemanticsContext &context() const { return *context_; }
-  void set_context(SemanticsContext &context) { context_ = &context; }
-
 protected:
   std::unique_ptr<DeclTypeSpec> &GetDeclTypeSpec();
   void BeginDeclTypeSpec();
@@ -180,7 +230,6 @@ protected:
 private:
   bool expectDeclTypeSpec_{false};  // should only see decl-type-spec when true
   std::unique_ptr<DeclTypeSpec> declTypeSpec_;
-  SemanticsContext *context_{nullptr};
   DerivedTypeSpec *derivedTypeSpec_{nullptr};
   const parser::Name *derivedTypeName_{nullptr};
 
@@ -190,47 +239,8 @@ private:
   ParamValue GetParamValue(const parser::TypeParamValue &);
 };
 
-// Track statement source locations and save messages.
-class MessageHandler {
-public:
-  using Message = parser::Message;
-  using MessageFixedText = parser::MessageFixedText;
-  using MessageFormattedText = parser::MessageFormattedText;
-
-  void set_messages(parser::Messages &messages) { messages_ = &messages; }
-
-  const SourceName *currStmtSource() { return currStmtSource_; }
-  void set_currStmtSource(const SourceName *x) { currStmtSource_ = x; }
-
-  // Emit a message
-  Message &Say(Message &&);
-  // Emit a message associated with the current statement source.
-  Message &Say(MessageFixedText &&);
-  // Emit a message about a SourceName
-  Message &Say(const SourceName &, MessageFixedText &&);
-  // Emit a formatted message associated with a source location.
-  Message &Say(const SourceName &, MessageFixedText &&, const SourceName &);
-  Message &Say(const SourceName &, MessageFixedText &&, const SourceName &,
-      const SourceName &);
-  template<typename... A>
-  Message &Say(const parser::Name &name, MessageFixedText &&msg, A... args) {
-    return Say(name.source, std::move(msg), std::forward<A>(args)...);
-  }
-  // Special messages: already declared; about a type; two names & locations
-  void SayAlreadyDeclared(const parser::Name &, const Symbol &);
-  void SayDerivedType(const SourceName &, MessageFixedText &&, const Scope &);
-  void Say2(const parser::Name &, MessageFixedText &&, const Symbol &,
-      MessageFixedText &&);
-
-private:
-  // Where messages are emitted:
-  parser::Messages *messages_{nullptr};
-  // Source location of current statement; null if not in a statement
-  const SourceName *currStmtSource_{nullptr};
-};
-
 // Visit ImplicitStmt and related parse tree nodes and updates implicit rules.
-class ImplicitRulesVisitor : public DeclTypeSpecVisitor, public MessageHandler {
+class ImplicitRulesVisitor : public DeclTypeSpecVisitor {
 public:
   using DeclTypeSpecVisitor::Post;
   using DeclTypeSpecVisitor::Pre;
@@ -242,11 +252,6 @@ public:
   bool Pre(const parser::ImplicitSpec &);
   void Post(const parser::ImplicitSpec &);
 
-  void set_context(SemanticsContext &context) {
-    DeclTypeSpecVisitor::set_context(context);
-    MessageHandler::set_messages(context.messages());
-  }
-
   ImplicitRules &implicitRules() { return *implicitRules_; }
   const ImplicitRules &implicitRules() const { return *implicitRules_; }
   bool isImplicitNoneType() const {
@@ -280,7 +285,7 @@ private:
 // 4. DIMENSION :: x(10)
 // 5. TODO: COMMON x(10)
 // 6. TODO: BasedPointerStmt
-class ArraySpecVisitor {
+class ArraySpecVisitor : public virtual BaseVisitor {
 public:
   bool Pre(const parser::ArraySpec &);
   void Post(const parser::AttrSpec &) { PostAttrSpec(); }
@@ -311,9 +316,6 @@ private:
 // Manage a stack of Scopes
 class ScopeHandler : public ImplicitRulesVisitor {
 public:
-  template<typename T> void Walk(const T &);
-  void set_this(ResolveNamesVisitor *x) { this_ = x; }
-
   Scope &currScope() { return *currScope_; }
   // The enclosing scope, skipping blocks and derived types.
   Scope &InclusiveScope();
@@ -330,16 +332,21 @@ public:
     ImplicitRulesVisitor::ClearScopes();
   }
 
-  //TSK: is this the right place???
   template<typename T> bool Pre(const parser::Statement<T> &x) {
-    set_currStmtSource(&x.source);
+    messageHandler().set_currStmtSource(&x.source);
     currScope_->AddSourceRange(x.source);
     return true;
   }
   template<typename T> void Post(const parser::Statement<T> &) {
-    set_currStmtSource(nullptr);
+    messageHandler().set_currStmtSource(nullptr);
   }
 
+  // Special messages: already declared; about a type; two names & locations
+  void SayAlreadyDeclared(const parser::Name &, const Symbol &);
+  void SayDerivedType(const SourceName &, MessageFixedText &&, const Scope &);
+  void Say2(const parser::Name &, MessageFixedText &&, const Symbol &,
+      MessageFixedText &&);
+
   // Search for symbol by name in current and containing scopes
   Symbol *FindSymbol(const parser::Name &);
   Symbol *FindSymbol(const Scope &, const parser::Name &);
@@ -909,6 +916,19 @@ void ShowImplicitRule(
   }
 }
 
+template<typename T> void BaseVisitor::Walk(const T &x) {
+  parser::Walk(x, *this_);
+}
+
+const SourceName *BaseVisitor::currStmtSource() {
+  return messageHandler_.currStmtSource();
+}
+
+void BaseVisitor::set_context(SemanticsContext &context) {
+  context_ = &context;
+  messageHandler_.set_messages(context.messages());
+}
+
 // AttrsVisitor implementation
 
 bool AttrsVisitor::BeginAttrs() {
@@ -1087,39 +1107,25 @@ int DeclTypeSpecVisitor::GetKindParamValue(
 
 // MessageHandler implementation
 
-MessageHandler::Message &MessageHandler::Say(MessageFixedText &&msg) {
+void MessageHandler::set_currStmtSource(const SourceName *source) {
+  currStmtSource_ = source;
+}
+Message &MessageHandler::Say(MessageFixedText &&msg) {
   CHECK(currStmtSource_);
   return messages_->Say(*currStmtSource_, std::move(msg));
 }
-MessageHandler::Message &MessageHandler::Say(
-    const SourceName &name, MessageFixedText &&msg) {
+Message &MessageHandler::Say(const SourceName &name, MessageFixedText &&msg) {
   return Say(name, std::move(msg), name);
 }
-MessageHandler::Message &MessageHandler::Say(const SourceName &location,
-    MessageFixedText &&msg, const SourceName &arg1) {
+Message &MessageHandler::Say(const SourceName &location, MessageFixedText &&msg,
+    const SourceName &arg1) {
   return messages_->Say(location, std::move(msg), arg1.ToString().c_str());
 }
-MessageHandler::Message &MessageHandler::Say(const SourceName &location,
-    MessageFixedText &&msg, const SourceName &arg1, const SourceName &arg2) {
+Message &MessageHandler::Say(const SourceName &location, MessageFixedText &&msg,
+    const SourceName &arg1, const SourceName &arg2) {
   return messages_->Say(location, std::move(msg), arg1.ToString().c_str(),
       arg2.ToString().c_str());
 }
-void MessageHandler::SayAlreadyDeclared(
-    const parser::Name &name, const Symbol &prev) {
-  Say2(name, "'%s' is already declared in this scoping unit"_err_en_US, prev,
-      "Previous declaration of '%s'"_en_US);
-}
-void MessageHandler::SayDerivedType(
-    const SourceName &name, MessageFixedText &&msg, const Scope &type) {
-  Say(name, std::move(msg), name, type.name())
-      .Attach(type.name(), "Declaration of derived type '%s'"_en_US,
-          type.name().ToString().c_str());
-}
-void MessageHandler::Say2(const parser::Name &name, MessageFixedText &&msg1,
-    const Symbol &symbol, MessageFixedText &&msg2) {
-  Say(name.source, std::move(msg1))
-      .Attach(symbol.name(), msg2, symbol.name().ToString().c_str());
-}
 
 // ImplicitRulesVisitor implementation
 
@@ -1306,6 +1312,23 @@ Bound ArraySpecVisitor::GetBound(const parser::SpecificationExpr &x) {
 
 // ScopeHandler implementation
 
+void ScopeHandler::SayAlreadyDeclared(
+    const parser::Name &name, const Symbol &prev) {
+  Say2(name, "'%s' is already declared in this scoping unit"_err_en_US, prev,
+      "Previous declaration of '%s'"_en_US);
+}
+void ScopeHandler::SayDerivedType(
+    const SourceName &name, MessageFixedText &&msg, const Scope &type) {
+  Say(name, std::move(msg), name, type.name())
+      .Attach(type.name(), "Declaration of derived type '%s'"_en_US,
+          type.name().ToString().c_str());
+}
+void ScopeHandler::Say2(const parser::Name &name, MessageFixedText &&msg1,
+    const Symbol &symbol, MessageFixedText &&msg2) {
+  Say(name.source, std::move(msg1))
+      .Attach(symbol.name(), msg2, symbol.name().ToString().c_str());
+}
+
 Scope &ScopeHandler::InclusiveScope() {
   for (auto *scope{&currScope()};; scope = &scope->parent()) {
     if (scope->kind() != Scope::Kind::Block &&
@@ -2720,7 +2743,7 @@ bool DeclarationVisitor::OkToAddComponent(
   for (bool inParent{false};; inParent = true) {
     CHECK(scope->kind() == Scope::Kind::DerivedType);
     if (auto *prev{FindInScope(*scope, name)}) {
-      parser::MessageFixedText msg{""_en_US};
+      auto msg{""_en_US};
       if (isParentComp) {
         msg = "Type cannot be extended as it has a component named"
               " '%s'"_err_en_US;
@@ -2747,10 +2770,6 @@ bool DeclarationVisitor::OkToAddComponent(
 
 // ConstructVisitor implementation
 
-template<typename T> void ScopeHandler::Walk(const T &x) {
-  parser::Walk(x, *this_);
-}
-
 bool ConstructVisitor::Pre(const parser::ConcurrentHeader &) {
   BeginDeclTypeSpec();
   return true;