[flang] Optionally dump all source members of parse tree
authorTim Keith <tkeith@nvidia.com>
Fri, 26 Apr 2019 22:06:58 +0000 (15:06 -0700)
committerTim Keith <tkeith@nvidia.com>
Fri, 26 Apr 2019 22:06:58 +0000 (15:06 -0700)
In the parse tree dumper, add a compile-time option to dump source
locations for all nodes that have them. This is a useful way to check
if they are correct, especially after parse tree rewrites.

It is enabled by defining `SHOW_ALL_SOURCE_MEMBERS` in `dump-parse-tree.h`.

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

flang/lib/parser/dump-parse-tree.h

index 6f3f024..453098b 100644 (file)
 #include "../common/indirection.h"
 #include <ostream>
 #include <string>
+#include <type_traits>
 
 namespace Fortran::parser {
 
 using namespace std::string_literals;
 
+// When SHOW_ALL_SOURCE_MEMBERS is defined, HasSource<T>::value is true if T has
+// a member named source
+template<typename T, typename = int> struct HasSource : std::false_type {};
+#ifdef SHOW_ALL_SOURCE_MEMBERS
+template<typename T>
+struct HasSource<T, decltype((void)T::source, 0)> : std::true_type {};
+#endif
+
 //
 // Dump the Parse Tree hierarchy of any node 'x' of the parse tree.
 //
@@ -711,11 +720,14 @@ public:
 #undef NODE_NAME
 
   template<typename T> bool Pre(const T &x) {
-    if (UnionTrait<T> || WrapperTrait<T>) {
+    if constexpr (!HasSource<T>::value && (UnionTrait<T> || WrapperTrait<T>)) {
       Prefix(GetNodeName(x));
     } else {
       IndentEmptyLine();
       out_ << GetNodeName(x);
+      if constexpr (HasSource<T>::value) {
+        out_ << " = '" << x.source.ToString() << '\'';
+      }
       EndLine();
       ++indent_;
     }
@@ -723,28 +735,25 @@ public:
   }
 
   template<typename T> void Post(const T &x) {
-    if (UnionTrait<T> || WrapperTrait<T>) {
+    if constexpr (!HasSource<T>::value && (UnionTrait<T> || WrapperTrait<T>)) {
       EndLineIfNonempty();
     } else {
       --indent_;
     }
   }
 
-  bool PutName(const std::string &name) {
+  bool Pre(const parser::Name &x) {
     IndentEmptyLine();
-    out_ << "Name = '" << name << '\'';
-    ++indent_;
+    out_ << "Name = '" << x.ToString() << '\'';
     EndLine();
-    return true;
+    return false;
+  }
+  bool Pre(const std::string &x) {
+    IndentEmptyLine();
+    out_ << "string = '" << x << '\'';
+    EndLine();
+    return false;
   }
-
-  bool Pre(const parser::Name &x) { return PutName(x.ToString()); }
-
-  void Post(const parser::Name &) { --indent_; }
-
-  bool Pre(const std::string &x) { return PutName(x); }
-
-  void Post(const std::string &x) { --indent_; }
 
   bool Pre(const std::int64_t &x) {
     IndentEmptyLine();
@@ -759,30 +768,39 @@ public:
   bool Pre(const std::uint64_t &x) {
     IndentEmptyLine();
     out_ << "int = '" << x << '\'';
-    ++indent_;
     EndLine();
-    return true;
+    return false;
   }
 
-  void Post(const std::uint64_t &x) { --indent_; }
-
   bool Pre(const parser::IntLiteralConstant &x) {
     IndentEmptyLine();
     out_ << "int = '" << std::get<parser::CharBlock>(x.t).ToString() << '\'';
-    ++indent_;
     EndLine();
-    return true;
+    ++indent_;
+    Walk(std::get<std::optional<KindParam>>(x.t), *this);
+    --indent_;
+    return false;
   }
-  void Post(const parser::IntLiteralConstant &) { --indent_; }
 
   bool Pre(const parser::SignedIntLiteralConstant &x) {
     IndentEmptyLine();
     out_ << "int = '" << std::get<parser::CharBlock>(x.t).ToString() << '\'';
+    EndLine();
     ++indent_;
+    Walk(std::get<std::optional<KindParam>>(x.t), *this);
+    --indent_;
+    return false;
+  }
+
+  bool Pre(const parser::RealLiteralConstant &x) {
+    Prefix(GetNodeName(x));
+    out_ << "Real = '" << x.real.source.ToString() << '\'';
     EndLine();
-    return true;
+    ++indent_;
+    Walk(x.kind, *this);
+    --indent_;
+    return false;
   }
-  void Post(const parser::SignedIntLiteralConstant &) { --indent_; }
 
   // A few types we want to ignore