diff mbox

[05/17] C++ frontend: capture BLT information

Message ID 1500926714-56988-6-git-send-email-dmalcolm@redhat.com
State New
Headers show

Commit Message

David Malcolm July 24, 2017, 8:05 p.m. UTC
This patch extends the C++ frontend so that it optionally builds a BLT tree,
by using an auto_blt_node class within the recursive descent through the
parser, so that its ctor/dtors build the blt_node hierarchy; this is
rapidly (I hope) rejected in the no -fblt case, so that by default, no
blt nodes are created.

This version of the parser captures a blt_node for every token consumed by
cp_parser_require, so there are a lot of leaf nodes in the resulting tree.

Caveat: currently the patch blithely ignores "tentative parsing" (for
the sake of posting this kit sooner rather than later).

All of this is largely a no-op if -fblt is not provided.

gcc/cp/ChangeLog:
	* cp-tree.h (class blt_node): Forward decl.
	(struct cp_parameter_declarator): Add "bltnode" field.
	(struct cp_declarator): Likewise.
	* decl.c: Include "blt.h"
	(grokdeclarator): Rename to...
	(grokdeclarator_1): ...this.
	(grokdeclarator): Reintroduce by calling grokdeclarator_1,
	and associating any bltnode in the declarator with the new tree.
	* parser.c: Include "blt.h".
	(class auto_blt_node): New class.
	(AUTO_BLT_NODE): New macro.
	AUTO_BLT_NODE_WITH_RETURN): New macro.
	(CURRENT_BLT_NODE): New macro.
	(BLT_ADD_NEXT_TOKEN): New macro.
	(ADD_NODE_FOR_NEXT_TOKEN): New macro.
	(BLT_SET_TREE): New macro.
	(add_node_for_next_token): New functions.
	(auto_blt_node::auto_blt_node): New ctor.
	(auto_blt_node::~auto_blt_node): New dtor.
	(auto_blt_node::set_tree): New method.
	(make_declarator): Initialize the bltnode field.
	(make_parameter_declarator): Add new "bltnode" param.
	(cp_parser_identifier): Add AUTO_BLT_NODE.
	(cp_parser_translation_unit): Likewise.
	(cp_parser_primary_expression): Likewise.
	(cp_parser_id_expression): Likewise.
	(cp_parser_unqualified_id): Likewise.
	(cp_parser_postfix_expression): Likewise; add BLT_ADD_NEXT_TOKEN.
	(cp_parser_parenthesized_expression_list): Add AUTO_BLT_NODE.
	(cp_parser_unary_expression): Add AUTO_BLT_NODE.
	(cp_parser_assignment_expression): Likewise.
	(cp_parser_declaration_seq_opt): Likewise.
	(cp_parser_declaration): Likewise.
	(cp_parser_block_declaration): Likewise.
	(cp_parser_simple_declaration): Likewise.
	(cp_parser_decl_specifier_seq): Likewise; add
	ADD_NODE_FOR_NEXT_TOKEN in various places.
	(cp_parser_template_declaration): Add AUTO_BLT_NODE.
	(cp_parser_template_parameter_list): Likewise.
	(cp_parser_explicit_instantiation): Likewise.
	(cp_parser_explicit_specialization): Likewise.
	(cp_parser_type_specifier): Likewise; add ADD_NODE_FOR_NEXT_TOKEN
	in various places.
	(update_blt_for_function_definition): New function.
	(cp_parser_init_declarator): Call
	update_blt_for_function_definition.
	(cp_parser_declarator): Add AUTO_BLT_NODE.
	(cp_parser_direct_declarator): Likewise; add BLT_ADD_NEXT_TOKEN;
	set the bltnode of the declarator.
	(cp_parser_cv_qualifier_seq_opt): Add AUTO_BLT_NODE; add
	ADD_NODE_FOR_NEXT_TOKEN.
	(cp_parser_parameter_declaration_clause): Add AUTO_BLT_NODE; add
	BLT_ADD_NEXT_TOKEN in various places.  Add BLT_SET_TREE.
	(cp_parser_parameter_declaration_list): Add AUTO_BLT_NODE; add
	BLT_SET_TREE in various places.
	(cp_parser_parameter_declaration): Add AUTO_BLT_NODE; pass
	CURRENT_BLT_NODE to make_parameter_declarator.
	(cp_parser_class_specifier_1): Add AUTO_BLT_NODE; add BLT_SET_TREE.
	(cp_parser_class_head): Add AUTO_BLT_NODE.
	(cp_parser_class_key): Likewise.
	(cp_parser_member_declaration): Likewise.  Ensure decl is
	initialized, and associate it with the blt_node.
	(cp_parser_type_id_list): Add AUTO_BLT_NODE.
	(cp_parser_try_block): Likewise.
	(cp_parser_function_try_block): Likewise.
	(cp_parser_handler_seq): Likewise.
	(cp_parser_handler): Likewise.
	(cp_parser_exception_declaration): Likewise.
	(cp_parser_throw_expression): Likewise.
	(cp_parser_asm_specification_opt): Likewise.
	(cp_parser_require): Call BLT_ADD_NEXT_TOKEN.
	(c_parse_file): Implement -fdump-blt.  Set the_blt_root_node.
	* parser.h (class blt_node): Forward decl.
	(struct cp_parser): Add fields "blt_root_node" and "blt_current_node".
	* pt.c: Include "blt.h".
	(build_template_decl): Associate any blt_node for the decl with the
	template instantation.
---
 gcc/cp/cp-tree.h |   5 +
 gcc/cp/decl.c    |  27 +++-
 gcc/cp/parser.c  | 369 ++++++++++++++++++++++++++++++++++++++++++++++++++++---
 gcc/cp/parser.h  |   7 ++
 gcc/cp/pt.c      |   8 ++
 5 files changed, 394 insertions(+), 22 deletions(-)
diff mbox

Patch

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 0da8a5c..16d8a48 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -25,6 +25,8 @@  along with GCC; see the file COPYING3.  If not see
 #include "hard-reg-set.h"
 #include "function.h"
 
+class blt_node;
+
 /* In order for the format checking to accept the C++ front end
    diagnostic framework extensions, you must include this file before
    diagnostic-core.h, not after.  We override the definition of GCC_DIAG_STYLE
@@ -5699,6 +5701,8 @@  struct cp_parameter_declarator {
   tree default_argument;
   /* True iff this is a template parameter pack.  */
   bool template_parameter_pack_p;
+  /* The blt_node for this parameter, if any.  */
+  blt_node *bltnode;
 };
 
 /* A declarator.  */
@@ -5774,6 +5778,7 @@  struct cp_declarator {
       bool rvalue_ref;
     } reference;
   } u;
+  blt_node *bltnode;
 };
 
 /* A level of template instantiation.  */
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 5b8e6a2..bcf305c 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -52,6 +52,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "builtins.h"
 #include "gimplify.h"
 #include "asan.h"
+#include "blt.h"
 
 /* Possible cases of bad specifiers type used by bad_specifiers. */
 enum bad_spec_place {
@@ -9876,12 +9877,12 @@  name_unnamed_type (tree type, tree decl)
    declarator, in cases like "struct S;"), or the ERROR_MARK_NODE if an
    error occurs. */
 
-tree
-grokdeclarator (const cp_declarator *declarator,
-		cp_decl_specifier_seq *declspecs,
-		enum decl_context decl_context,
-		int initialized,
-		tree* attrlist)
+static tree
+grokdeclarator_1 (const cp_declarator *declarator,
+		  cp_decl_specifier_seq *declspecs,
+		  enum decl_context decl_context,
+		  int initialized,
+		  tree* attrlist)
 {
   tree type = NULL_TREE;
   int longlong = 0;
@@ -12349,6 +12350,20 @@  grokdeclarator (const cp_declarator *declarator,
     return decl;
   }
 }
+
+tree
+grokdeclarator (const cp_declarator *declarator,
+		cp_decl_specifier_seq *declspecs,
+		enum decl_context decl_context,
+		int initialized,
+		tree* attrlist)
+{
+  tree result = grokdeclarator_1 (declarator, declspecs, decl_context,
+				  initialized, attrlist);
+  if (declarator && declarator->bltnode)
+    declarator->bltnode->set_tree (result);
+  return result;
+}
 
 /* Subroutine of start_function.  Ensure that each of the parameter
    types (as listed in PARMS) is complete, as is required for a
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 88d0b2b..5e0b34e 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -43,6 +43,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "cp-cilkplus.h"
 #include "gcc-rich-location.h"
 #include "tree-iterator.h"
+#include "blt.h"
 
 
 /* The lexer.  */
@@ -1348,6 +1349,181 @@  cp_token_cache_new (cp_token *first, cp_token *last)
   return cache;
 }
 
+
+
+/* A RAII-style class for optionally building a concrete parse tree (or
+   at least, something close to it) as the recursive descent parser runs.
+
+   Close to a no-op if -fblt is not selected.  */
+
+class auto_blt_node
+{
+public:
+  auto_blt_node (cp_parser* parser, enum blt_kind kind,
+                 cp_expr *expr_ptr = NULL);
+  ~auto_blt_node ();
+
+  void set_tree (tree node);
+
+private:
+  cp_parser *m_parser;
+  cp_expr *m_expr_ptr;
+  blt_node *m_parent;
+};
+
+/* RAII-style construction of the blt_node tree: push a blt_node of KIND
+   onto the current stack of blt_nodes, popping it when it goes out
+   of scope.  */
+
+#define AUTO_BLT_NODE(PARSER, KIND) \
+  auto_blt_node tmp_blt_node ((PARSER), (KIND))
+
+/* As above, but with an addition cp_expr *.
+   If non-NULL, then the node's tree will be set to that of the tree
+   within the cp_expr when the AUTO_BLT_NODE_WITH_RETURN goes out of
+   scope.  */
+
+#define AUTO_BLT_NODE_WITH_RETURN(PARSER, KIND, ADDR_OF_CP_EXPR) \
+  auto_blt_node tmp_blt_node ((PARSER), (KIND), (ADDR_OF_CP_EXPR))
+
+/* The blt_node currently being constructed (the macro assumes that "parser"
+   exists in the current scope).  */
+
+#define CURRENT_BLT_NODE (parser->blt_current_node)
+
+/* Peek the next token within PARSER and a child node for it to the
+   current blt_node.  */
+
+#define BLT_ADD_NEXT_TOKEN(PARSER) \
+  add_node_for_next_token (PARSER)
+
+/* Peek the next token within "parser" and a child node for it to the
+   current blt_node, using KIND as the kind.  */
+
+#define ADD_NODE_FOR_NEXT_TOKEN(KIND) \
+  add_node_for_next_token (parser, (KIND))
+
+/* Set the tree node for the current AUTO_BLT_NODE.  */
+
+#define BLT_SET_TREE(TREE_NODE) \
+  tmp_blt_node.set_tree (TREE_NODE);
+
+/* Peek the next token within PARSER and a child node for it to the
+   current blt_node.  */
+
+static blt_node *
+add_node_for_next_token (cp_parser *parser)
+{
+  if (!flag_blt)
+    return NULL;
+
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
+  blt_node *parent = parser->blt_current_node;
+  enum blt_kind kind = (enum blt_kind)token->type;
+  blt_node *node = new blt_node (kind, token->location);
+  parent->add_child (node);
+  node->set_finish (token->location);
+  return node;
+}
+
+/* As above, but use KIND as the kind of the new blt_node.  */
+
+static blt_node *
+add_node_for_next_token (cp_parser *parser, enum blt_kind kind)
+{
+  if (!flag_blt)
+    return NULL;
+
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
+  blt_node *parent = parser->blt_current_node;
+  blt_node *node = new blt_node (kind, token->location);
+  parent->add_child (node);
+  node->set_finish (token->location);
+  return node;
+}
+
+/* auto_blt_node's constructor.
+
+   If -fblt was not enabled, return immediately.
+
+   Otherwise push a new blt_node of KIND as a child of the previous top
+   of the blt stack, effectively constructing a tree.
+
+   Set the new blt_node's start location to that of the next token
+   within PARSER.  */
+
+auto_blt_node::auto_blt_node (cp_parser *parser, enum blt_kind kind,
+                              cp_expr *expr_ptr)
+{
+  if (!flag_blt)
+    return;
+
+  /* Do this here rather than as an initializer list
+     to avoid doing work when -fblt is not set.  */
+  m_parser = parser;
+  m_expr_ptr = expr_ptr;
+  m_parent = parser->blt_current_node;
+
+  cp_token *first_token = cp_lexer_peek_token (parser->lexer);
+  blt_node *node = new blt_node (kind, first_token->location);
+  parser->blt_current_node = node;
+  if (m_parent)
+    m_parent->add_child (node);
+  else
+    parser->blt_root_node = node;
+}
+
+/* auto_blt_node's destructor.
+
+   If -fblt was not enabled, return immediately.
+
+   Otherwise, pop the current blt_node from the stack,
+   and set its finish location to that of the last
+   token that was consumed.
+
+   If m_expr_ptr was set, set the blt_node's tree to be that
+   of the m_expr_ptr.  */
+
+auto_blt_node::~auto_blt_node ()
+{
+  if (!flag_blt)
+    return;
+
+  blt_node *node = m_parser->blt_current_node;
+
+  cp_token_position prev
+    = cp_lexer_previous_token_position (m_parser->lexer);
+  node->set_finish (cp_lexer_token_at (m_parser->lexer, prev)->location);
+
+  if (0)
+    {
+      location_t start = node->get_start ();
+      location_t finish = node->get_finish ();
+      location_t range = make_location (start, start, finish);
+      inform (range, "%qs", node->get_name ());
+    }
+
+  if (m_expr_ptr)
+    node->set_tree (m_expr_ptr->get_value ());
+
+  /* Use stashed parent, rather than the curent node's parent
+     to allow for reparenting within the tree.  */
+  m_parser->blt_current_node = m_parent;
+}
+
+/* Set the tree node for the current blt_node within this AUTO_BLT_NODE.  */
+
+void
+auto_blt_node::set_tree (tree tree_node)
+{
+  if (!flag_blt)
+    return;
+
+  blt_node *node = m_parser->blt_current_node;
+  node->set_tree (tree_node);
+}
+
+
 /* Diagnose if #pragma omp declare simd isn't followed immediately
    by function declaration or definition.  */
 
@@ -1456,6 +1632,7 @@  make_declarator (cp_declarator_kind kind)
   declarator->declarator = NULL;
   declarator->parameter_pack_p = false;
   declarator->id_loc = UNKNOWN_LOCATION;
+  declarator->bltnode = NULL;
 
   return declarator;
 }
@@ -1691,7 +1868,8 @@  cp_parameter_declarator *
 make_parameter_declarator (cp_decl_specifier_seq *decl_specifiers,
 			   cp_declarator *declarator,
 			   tree default_argument,
-			   bool template_parameter_pack_p = false)
+			   bool template_parameter_pack_p = false,
+			   blt_node *bltnode = NULL)
 {
   cp_parameter_declarator *parameter;
 
@@ -1705,6 +1883,7 @@  make_parameter_declarator (cp_decl_specifier_seq *decl_specifiers,
   parameter->declarator = declarator;
   parameter->default_argument = default_argument;
   parameter->template_parameter_pack_p = template_parameter_pack_p;
+  parameter->bltnode = bltnode;
 
   return parameter;
 }
@@ -3868,6 +4047,10 @@  cp_parser_identifier (cp_parser* parser)
 {
   cp_token *token;
 
+  AUTO_BLT_NODE (parser, BLT_IDENTIFIER);
+  if (0)
+    BLT_ADD_NEXT_TOKEN (parser);
+
   /* Look for the identifier.  */
   token = cp_parser_require (parser, CPP_NAME, RT_NAME);
   /* Return the value.  */
@@ -4371,19 +4554,23 @@  cp_parser_translation_unit (cp_parser* parser)
 
   bool success;
 
-  /* Create the declarator obstack, if necessary.  */
-  if (!cp_error_declarator)
-    {
-      gcc_obstack_init (&declarator_obstack);
-      /* Create the error declarator.  */
-      cp_error_declarator = make_declarator (cdk_error);
-      /* Create the empty parameter list.  */
-      no_parameters = make_parameter_declarator (NULL, NULL, NULL_TREE);
-      /* Remember where the base of the declarator obstack lies.  */
-      declarator_obstack_base = obstack_next_free (&declarator_obstack);
-    }
+  {
+    AUTO_BLT_NODE (parser, BLT_TRANSLATION_UNIT);
 
-  cp_parser_declaration_seq_opt (parser);
+    /* Create the declarator obstack, if necessary.  */
+    if (!cp_error_declarator)
+      {
+        gcc_obstack_init (&declarator_obstack);
+        /* Create the error declarator.  */
+        cp_error_declarator = make_declarator (cdk_error);
+        /* Create the empty parameter list.  */
+        no_parameters = make_parameter_declarator (NULL, NULL, NULL_TREE);
+        /* Remember where the base of the declarator obstack lies.  */
+        declarator_obstack_base = obstack_next_free (&declarator_obstack);
+      }
+
+    cp_parser_declaration_seq_opt (parser);
+  }
 
   /* If there are no tokens left then all went well.  */
   if (cp_lexer_next_token_is (parser->lexer, CPP_EOF))
@@ -4787,6 +4974,8 @@  cp_parser_primary_expression (cp_parser *parser,
 			      bool decltype_p,
 			      cp_id_kind *idk)
 {
+  AUTO_BLT_NODE (parser, BLT_PRIMARY_EXPRESSION);
+
   cp_token *token = NULL;
 
   /* Assume the primary expression is not an id-expression.  */
@@ -5419,6 +5608,8 @@  cp_parser_id_expression (cp_parser *parser,
 			 bool declarator_p,
 			 bool optional_p)
 {
+  AUTO_BLT_NODE (parser, BLT_ID_EXPRESSION);
+
   bool global_scope_p;
   bool nested_name_specifier_p;
 
@@ -5558,6 +5749,8 @@  cp_parser_unqualified_id (cp_parser* parser,
 			  bool declarator_p,
 			  bool optional_p)
 {
+  AUTO_BLT_NODE (parser, BLT_UNQUALIFIED_ID);
+
   cp_token *token;
 
   /* Peek at the next token.  */
@@ -6419,6 +6612,8 @@  cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
   bool is_member_access = false;
   int saved_in_statement = -1;
 
+  AUTO_BLT_NODE_WITH_RETURN (parser, BLT_POSTFIX_EXPRESSION, &postfix_expression);
+
   /* Peek at the next token.  */
   token = cp_lexer_peek_token (parser->lexer);
   loc = token->location;
@@ -6438,6 +6633,8 @@  cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
 	const char *saved_message;
 	bool saved_in_type_id_in_expr_p;
 
+        BLT_ADD_NEXT_TOKEN (parser);
+
 	/* All of these can be handled in the same way from the point
 	   of view of parsing.  Begin by consuming the token
 	   identifying the cast.  */
@@ -6524,6 +6721,7 @@  cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
 	bool saved_in_type_id_in_expr_p;
 
 	/* Consume the `typeid' token.  */
+        BLT_ADD_NEXT_TOKEN (parser);
 	cp_lexer_consume_token (parser->lexer);
 	/* Look for the `(' token.  */
 	cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
@@ -7552,6 +7750,8 @@  cp_parser_parenthesized_expression_list (cp_parser* parser,
 					 bool *non_constant_p,
 					 location_t *close_paren_loc)
 {
+  AUTO_BLT_NODE (parser, BLT_EXPRESSION_LIST);
+
   vec<tree, va_gc> *expression_list;
   bool fold_expr_p = is_attribute_list != non_attr;
   tree identifier = NULL_TREE;
@@ -7830,6 +8030,8 @@  static cp_expr
 cp_parser_unary_expression (cp_parser *parser, cp_id_kind * pidk,
 			    bool address_p, bool cast_p, bool decltype_p)
 {
+  AUTO_BLT_NODE (parser, BLT_UNARY_EXPRESSION);
+
   cp_token *token;
   enum tree_code unary_operator;
 
@@ -9297,6 +9499,7 @@  static cp_expr
 cp_parser_assignment_expression (cp_parser* parser, cp_id_kind * pidk,
 				 bool cast_p, bool decltype_p)
 {
+  AUTO_BLT_NODE (parser, BLT_ASSIGNMENT_EXPRESSION);
   cp_expr expr;
 
   /* If the next token is the `throw' keyword, then we're looking at
@@ -12502,6 +12705,8 @@  cp_parser_already_scoped_statement (cp_parser* parser, bool *if_p,
 static void
 cp_parser_declaration_seq_opt (cp_parser* parser)
 {
+  AUTO_BLT_NODE (parser, BLT_DECLARATION_SEQ);
+
   while (true)
     {
       cp_token *token;
@@ -12573,6 +12778,8 @@  cp_parser_declaration_seq_opt (cp_parser* parser)
 static void
 cp_parser_declaration (cp_parser* parser)
 {
+  AUTO_BLT_NODE (parser, BLT_DECLARATION);
+
   cp_token token1;
   cp_token token2;
   int saved_pedantic;
@@ -12717,6 +12924,8 @@  cp_parser_block_declaration (cp_parser *parser,
       return;
     }
 
+  AUTO_BLT_NODE (parser, BLT_BLOCK_DECLARATION);
+
   /* Peek at the next token to figure out which kind of declaration is
      present.  */
   token1 = cp_lexer_peek_token (parser->lexer);
@@ -12801,6 +13010,8 @@  cp_parser_simple_declaration (cp_parser* parser,
 			      bool function_definition_allowed_p,
 			      tree *maybe_range_for_decl)
 {
+  AUTO_BLT_NODE (parser, BLT_SIMPLE_DECLARATION);
+
   cp_decl_specifier_seq decl_specifiers;
   int declares_class_or_enum;
   bool saw_declarator;
@@ -13291,6 +13502,8 @@  cp_parser_decl_specifier_seq (cp_parser* parser,
 			      cp_decl_specifier_seq *decl_specs,
 			      int* declares_class_or_enum)
 {
+  AUTO_BLT_NODE (parser, BLT_DECL_SPECIFIER_SEQ);
+
   bool constructor_possible_p = !parser->in_declarator_p;
   bool found_decl_spec = false;
   cp_token *start_token = NULL;
@@ -13390,6 +13603,7 @@  cp_parser_decl_specifier_seq (cp_parser* parser,
 	  else
 	    {
 	      ds = ds_friend;
+	      ADD_NODE_FOR_NEXT_TOKEN (BLT_DECL_SPECIFIER);
 	      /* Consume the token.  */
 	      cp_lexer_consume_token (parser->lexer);
 	    }
@@ -13397,6 +13611,7 @@  cp_parser_decl_specifier_seq (cp_parser* parser,
 
         case RID_CONSTEXPR:
 	  ds = ds_constexpr;
+	  ADD_NODE_FOR_NEXT_TOKEN (BLT_DECL_SPECIFIER);
           cp_lexer_consume_token (parser->lexer);
           break;
 
@@ -13419,6 +13634,7 @@  cp_parser_decl_specifier_seq (cp_parser* parser,
 	       typedef  */
 	case RID_TYPEDEF:
 	  ds = ds_typedef;
+	  ADD_NODE_FOR_NEXT_TOKEN (BLT_DECL_SPECIFIER);
 	  /* Consume the token.  */
 	  cp_lexer_consume_token (parser->lexer);
 	  /* A constructor declarator cannot appear in a typedef.  */
@@ -13443,6 +13659,7 @@  cp_parser_decl_specifier_seq (cp_parser* parser,
 	case RID_AUTO:
           if (cxx_dialect == cxx98) 
             {
+	      ADD_NODE_FOR_NEXT_TOKEN (BLT_DECL_SPECIFIER);
 	      /* Consume the token.  */
 	      cp_lexer_consume_token (parser->lexer);
 
@@ -13467,6 +13684,7 @@  cp_parser_decl_specifier_seq (cp_parser* parser,
 	case RID_STATIC:
 	case RID_EXTERN:
 	case RID_MUTABLE:
+	  ADD_NODE_FOR_NEXT_TOKEN (BLT_DECL_SPECIFIER);
 	  /* Consume the token.  */
 	  cp_lexer_consume_token (parser->lexer);
           cp_parser_set_storage_class (parser, decl_specs, token->keyword,
@@ -13475,6 +13693,7 @@  cp_parser_decl_specifier_seq (cp_parser* parser,
 	case RID_THREAD:
 	  /* Consume the token.  */
 	  ds = ds_thread;
+          ADD_NODE_FOR_NEXT_TOKEN (BLT_DECL_SPECIFIER);
 	  cp_lexer_consume_token (parser->lexer);
 	  break;
 
@@ -14852,6 +15071,8 @@  cp_parser_operator (cp_parser* parser)
 static void
 cp_parser_template_declaration (cp_parser* parser, bool member_p)
 {
+  AUTO_BLT_NODE (parser, BLT_TEMPLATE_DECLARATION);
+
   /* Check for `export'.  */
   if (cp_lexer_next_token_is_keyword (parser->lexer, RID_EXPORT))
     {
@@ -14876,6 +15097,8 @@  cp_parser_template_declaration (cp_parser* parser, bool member_p)
 static tree
 cp_parser_template_parameter_list (cp_parser* parser)
 {
+  AUTO_BLT_NODE (parser, BLT_TEMPLATE_PARAMETER_LIST);
+
   tree parameter_list = NULL_TREE;
 
   begin_template_parm_list ();
@@ -16348,6 +16571,8 @@  cp_parser_template_argument (cp_parser* parser)
 static void
 cp_parser_explicit_instantiation (cp_parser* parser)
 {
+  AUTO_BLT_NODE (parser, BLT_EXPLICIT_INSTANTIATION);
+
   int declares_class_or_enum;
   cp_decl_specifier_seq decl_specifiers;
   tree extension_specifier = NULL_TREE;
@@ -16461,6 +16686,8 @@  cp_parser_explicit_instantiation (cp_parser* parser)
 static void
 cp_parser_explicit_specialization (cp_parser* parser)
 {
+  AUTO_BLT_NODE (parser, BLT_EXPLICIT_SPECIALIZATION);
+
   bool need_lang_pop;
   cp_token *token = cp_lexer_peek_token (parser->lexer);
 
@@ -16562,6 +16789,8 @@  cp_parser_type_specifier (cp_parser* parser,
 			  int* declares_class_or_enum,
 			  bool* is_cv_qualifier)
 {
+  AUTO_BLT_NODE (parser, BLT_TYPE_SPECIFIER);
+
   tree type_spec = NULL_TREE;
   cp_token *token;
   enum rid keyword;
@@ -16652,18 +16881,21 @@  cp_parser_type_specifier (cp_parser* parser,
 
     case RID_CONST:
       ds = ds_const;
+      ADD_NODE_FOR_NEXT_TOKEN (BLT_CV_QUALIFIER);
       if (is_cv_qualifier)
 	*is_cv_qualifier = true;
       break;
 
     case RID_VOLATILE:
       ds = ds_volatile;
+      ADD_NODE_FOR_NEXT_TOKEN (BLT_CV_QUALIFIER);
       if (is_cv_qualifier)
 	*is_cv_qualifier = true;
       break;
 
     case RID_RESTRICT:
       ds = ds_restrict;
+      ADD_NODE_FOR_NEXT_TOKEN (BLT_CV_QUALIFIER);
       if (is_cv_qualifier)
 	*is_cv_qualifier = true;
       break;
@@ -19108,6 +19340,48 @@  strip_declarator_types (tree type, cp_declarator *declarator)
   return type;
 }
 
+/* Subroutine for cp_parser_init_declarator for once
+   we know we're dealing with a function-definition.
+
+   We're below a:
+   + PARENT
+     `-block-declaration
+       `-simple-declaration
+         |-decl-specifier-seq
+         |-declarator
+
+  Convert the simple-declaration to a function-definition,
+  and lose the block-declaration, resulting in:
+
+   + PARENT
+     `-function-definition
+       |-decl-specifier-seq
+       |-declarator.  */
+
+static void
+update_blt_for_function_definition (cp_parser *parser)
+{
+  if (!CURRENT_BLT_NODE)
+    return;
+
+  blt_node *block_decl
+    = CURRENT_BLT_NODE->get_ancestor_of_kind (BLT_BLOCK_DECLARATION);
+
+  if (!block_decl)
+    /* We might have a template-declaration.  */
+    return;
+
+  blt_node *simple_decl
+    = block_decl->get_first_child_of_kind (BLT_SIMPLE_DECLARATION);
+  gcc_assert (simple_decl);
+
+  blt_node *parent = block_decl->get_parent ();
+  gcc_assert (parent);
+
+  simple_decl->set_kind (BLT_FUNCTION_DEFINITION);
+  parent->replace_child (block_decl, simple_decl);
+}
+
 /* Declarators [gram.dcl.decl] */
 
 /* Parse an init-declarator.
@@ -19324,6 +19598,7 @@  cp_parser_init_declarator (cp_parser* parser,
 		      "on a function-definition");
 	  /* This is a function-definition.  */
 	  *function_definition_p = true;
+          update_blt_for_function_definition (parser);
 
 	  /* Parse the function definition.  */
 	  if (member_p)
@@ -19640,6 +19915,8 @@  cp_parser_declarator (cp_parser* parser,
 		      bool* parenthesized_p,
 		      bool member_p, bool friend_p)
 {
+  AUTO_BLT_NODE (parser, BLT_DECLARATOR);
+
   cp_declarator *declarator;
   enum tree_code code;
   cp_cv_quals cv_quals;
@@ -19741,6 +20018,8 @@  cp_parser_direct_declarator (cp_parser* parser,
 			     int* ctor_dtor_or_conv_p,
 			     bool member_p, bool friend_p)
 {
+  AUTO_BLT_NODE (parser, BLT_DIRECT_DECLARATOR);
+
   cp_token *token;
   cp_declarator *declarator = NULL;
   tree scope = NULL_TREE;
@@ -19808,6 +20087,7 @@  cp_parser_direct_declarator (cp_parser* parser,
 		cp_parser_parse_tentatively (parser);
 
 	      /* Consume the `('.  */
+	      BLT_ADD_NEXT_TOKEN (parser);
 	      cp_lexer_consume_token (parser->lexer);
 	      if (first)
 		{
@@ -20254,6 +20534,9 @@  cp_parser_direct_declarator (cp_parser* parser,
   parser->default_arg_ok_p = saved_default_arg_ok_p;
   parser->in_declarator_p = saved_in_declarator_p;
 
+  if (declarator)
+    declarator->bltnode = CURRENT_BLT_NODE;
+
   return declarator;
 }
 
@@ -20396,6 +20679,8 @@  cp_parser_ptr_operator (cp_parser* parser,
 static cp_cv_quals
 cp_parser_cv_qualifier_seq_opt (cp_parser* parser)
 {
+  AUTO_BLT_NODE (parser, BLT_CV_QUALIFIER_SEQ);
+
   cp_cv_quals cv_quals = TYPE_UNQUALIFIED;
 
   while (true)
@@ -20428,6 +20713,8 @@  cp_parser_cv_qualifier_seq_opt (cp_parser* parser)
       if (!cv_qualifier)
 	break;
 
+      ADD_NODE_FOR_NEXT_TOKEN (BLT_CV_QUALIFIER);
+
       if (cv_quals & cv_qualifier)
 	{
 	  gcc_rich_location richloc (token->location);
@@ -21039,6 +21326,8 @@  function_being_declared_is_template_p (cp_parser* parser)
 static tree
 cp_parser_parameter_declaration_clause (cp_parser* parser)
 {
+  AUTO_BLT_NODE (parser, BLT_PARAMETER_DECLARATION_CLAUSE);
+
   tree parameters;
   cp_token *token;
   bool ellipsis_p;
@@ -21068,6 +21357,7 @@  cp_parser_parameter_declaration_clause (cp_parser* parser)
   if (token->type == CPP_ELLIPSIS)
     {
       /* Consume the `...' token.  */
+      BLT_ADD_NEXT_TOKEN (parser);
       cp_lexer_consume_token (parser->lexer);
       return NULL_TREE;
     }
@@ -21089,6 +21379,7 @@  cp_parser_parameter_declaration_clause (cp_parser* parser)
 	       == CPP_CLOSE_PAREN))
     {
       /* Consume the `void' token.  */
+      BLT_ADD_NEXT_TOKEN (parser);
       cp_lexer_consume_token (parser->lexer);
       /* There are no parameters.  */
       return void_list_node;
@@ -21108,6 +21399,7 @@  cp_parser_parameter_declaration_clause (cp_parser* parser)
   if (token->type == CPP_COMMA)
     {
       /* Consume the `,'.  */
+      BLT_ADD_NEXT_TOKEN (parser);
       cp_lexer_consume_token (parser->lexer);
       /* Expect an ellipsis.  */
       ellipsis_p
@@ -21118,6 +21410,7 @@  cp_parser_parameter_declaration_clause (cp_parser* parser)
   else if (token->type == CPP_ELLIPSIS)
     {
       /* Consume the `...' token.  */
+      BLT_ADD_NEXT_TOKEN (parser);
       cp_lexer_consume_token (parser->lexer);
       /* And remember that we saw it.  */
       ellipsis_p = true;
@@ -21129,6 +21422,7 @@  cp_parser_parameter_declaration_clause (cp_parser* parser)
   if (!ellipsis_p)
     parameters = chainon (parameters, void_list_node);
 
+  BLT_SET_TREE (parameters);
   return parameters;
 }
 
@@ -21146,6 +21440,7 @@  cp_parser_parameter_declaration_clause (cp_parser* parser)
 static tree
 cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error)
 {
+  AUTO_BLT_NODE (parser, BLT_PARAMETER_DECLARATION_LIST);
   tree parameters = NULL_TREE;
   tree *tail = &parameters;
   bool saved_in_unbraced_linkage_specification_p;
@@ -21203,6 +21498,7 @@  cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error)
 				 PARM,
 				 parameter->default_argument != NULL_TREE,
 				 &parameter->decl_specifiers.attributes);
+          BLT_SET_TREE (decl);
 	}
 
       deprecated_state = DEPRECATED_NORMAL;
@@ -21253,6 +21549,7 @@  cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error)
 	    break;
 	  /* Otherwise, there must be more parameters.  Consume the
 	     `,'.  */
+          BLT_ADD_NEXT_TOKEN (parser);
 	  cp_lexer_consume_token (parser->lexer);
 	  /* When parsing something like:
 
@@ -21308,6 +21605,7 @@  cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error)
 	  }
       }
 
+  BLT_SET_TREE (parameters);
   return parameters;
 }
 
@@ -21333,6 +21631,8 @@  cp_parser_parameter_declaration (cp_parser *parser,
 				 bool template_parm_p,
 				 bool *parenthesized_p)
 {
+  AUTO_BLT_NODE (parser, BLT_PARAMETER_DECLARATION);
+
   int declares_class_or_enum;
   cp_decl_specifier_seq decl_specifiers;
   cp_declarator *declarator;
@@ -21543,7 +21843,8 @@  cp_parser_parameter_declaration (cp_parser *parser,
   return make_parameter_declarator (&decl_specifiers,
 				    declarator,
 				    default_argument,
-				    template_parameter_pack_p);
+				    template_parameter_pack_p,
+                                    CURRENT_BLT_NODE);
 }
 
 /* Parse a default argument and return it.
@@ -22207,6 +22508,8 @@  cp_parser_class_specifier_1 (cp_parser* parser)
   tree scope = NULL_TREE;
   cp_token *closing_brace;
 
+  AUTO_BLT_NODE (parser, BLT_CLASS_SPECIFIER);
+
   push_deferring_access_checks (dk_no_deferred);
 
   /* Parse the class-head.  */
@@ -22515,6 +22818,8 @@  cp_parser_class_specifier_1 (cp_parser* parser)
   parser->in_unbraced_linkage_specification_p
     = saved_in_unbraced_linkage_specification_p;
 
+  BLT_SET_TREE (type);
+
   return type;
 }
 
@@ -22563,6 +22868,8 @@  static tree
 cp_parser_class_head (cp_parser* parser,
 		      bool* nested_name_specifier_p)
 {
+  AUTO_BLT_NODE (parser, BLT_CLASS_HEAD);
+
   tree nested_name_specifier;
   enum tag_types class_key;
   tree id = NULL_TREE;
@@ -23041,6 +23348,8 @@  cp_parser_class_key (cp_parser* parser)
   cp_token *token;
   enum tag_types tag_type;
 
+  AUTO_BLT_NODE (parser, BLT_CLASS_KEY);
+
   /* Look for the class-key.  */
   token = cp_parser_require (parser, CPP_KEYWORD, RT_CLASS_KEY);
   if (!token)
@@ -23171,9 +23480,11 @@  cp_parser_member_specification_opt (cp_parser* parser)
 static void
 cp_parser_member_declaration (cp_parser* parser)
 {
+  AUTO_BLT_NODE (parser, BLT_MEMBER_DECLARATION);
+
   cp_decl_specifier_seq decl_specifiers;
   tree prefix_attributes;
-  tree decl;
+  tree decl = NULL_TREE;
   int declares_class_or_enum;
   bool friend_p;
   cp_token *token = NULL;
@@ -23677,6 +23988,7 @@  cp_parser_member_declaration (cp_parser* parser)
   cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
  out:
   parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p;
+  BLT_SET_TREE (decl);
 }
 
 /* Parse a pure-specifier.
@@ -24140,6 +24452,8 @@  cp_parser_exception_specification_opt (cp_parser* parser)
 static tree
 cp_parser_type_id_list (cp_parser* parser)
 {
+  AUTO_BLT_NODE (parser, BLT_TYPE_ID_LIST);
+
   tree types = NULL_TREE;
 
   while (true)
@@ -24189,6 +24503,8 @@  cp_parser_type_id_list (cp_parser* parser)
 static tree
 cp_parser_try_block (cp_parser* parser)
 {
+  AUTO_BLT_NODE (parser, BLT_TRY_BLOCK);
+
   tree try_block;
 
   cp_parser_require_keyword (parser, RID_TRY, RT_TRY);
@@ -24213,6 +24529,8 @@  cp_parser_try_block (cp_parser* parser)
 static bool
 cp_parser_function_try_block (cp_parser* parser)
 {
+  AUTO_BLT_NODE (parser, BLT_FUNCTION_TRY_BLOCK);
+
   tree compound_stmt;
   tree try_block;
   bool ctor_initializer_p;
@@ -24243,6 +24561,8 @@  cp_parser_function_try_block (cp_parser* parser)
 static void
 cp_parser_handler_seq (cp_parser* parser)
 {
+  AUTO_BLT_NODE (parser, BLT_HANDLER_SEQ);
+
   while (true)
     {
       cp_token *token;
@@ -24265,6 +24585,8 @@  cp_parser_handler_seq (cp_parser* parser)
 static void
 cp_parser_handler (cp_parser* parser)
 {
+  AUTO_BLT_NODE (parser, BLT_HANDLER);
+
   tree handler;
   tree declaration;
 
@@ -24292,6 +24614,8 @@  cp_parser_handler (cp_parser* parser)
 static tree
 cp_parser_exception_declaration (cp_parser* parser)
 {
+  AUTO_BLT_NODE (parser, BLT_EXCEPTION_DECLARATION);
+
   cp_decl_specifier_seq type_specifiers;
   cp_declarator *declarator;
   const char *saved_message;
@@ -24345,6 +24669,8 @@  cp_parser_throw_expression (cp_parser* parser)
   tree expression;
   cp_token* token;
 
+  AUTO_BLT_NODE (parser, BLT_THROW_EXPRESSION);
+
   cp_parser_require_keyword (parser, RID_THROW, RT_THROW);
   token = cp_lexer_peek_token (parser->lexer);
   /* Figure out whether or not there is an assignment-expression
@@ -24386,6 +24712,8 @@  cp_parser_asm_specification_opt (cp_parser* parser)
   if (!cp_parser_is_keyword (token, RID_ASM))
     return NULL_TREE;
 
+  AUTO_BLT_NODE (parser, BLT_ASM_SPECIFICATION);
+
   /* Consume the `asm' token.  */
   cp_lexer_consume_token (parser->lexer);
   /* Look for the `('.  */
@@ -28113,7 +28441,10 @@  cp_parser_require (cp_parser* parser,
 		   required_token token_desc)
 {
   if (cp_lexer_next_token_is (parser->lexer, type))
-    return cp_lexer_consume_token (parser->lexer);
+    {
+      BLT_ADD_NEXT_TOKEN (parser);
+      return cp_lexer_consume_token (parser->lexer);
+    }
   else
     {
       /* Output the MESSAGE -- unless we're parsing tentatively.  */
@@ -38647,6 +38978,12 @@  c_parse_file (void)
   push_deferring_access_checks (flag_access_control
 				? dk_no_deferred : dk_no_check);
   cp_parser_translation_unit (the_parser);
+
+  if (flag_blt && flag_dump_blt)
+    the_parser->blt_root_node->dump (stderr);
+
+  the_blt_root_node = the_parser->blt_root_node;
+
   the_parser = NULL;
 }
 
diff --git a/gcc/cp/parser.h b/gcc/cp/parser.h
index 0994e1e..49c8eb6 100644
--- a/gcc/cp/parser.h
+++ b/gcc/cp/parser.h
@@ -213,6 +213,8 @@  struct cp_oacc_routine_data : cp_omp_declare_simd_data {
   location_t loc;
 };
 
+class blt_node;
+
 /* The cp_parser structure represents the C++ parser.  */
 
 struct GTY(()) cp_parser {
@@ -412,6 +414,11 @@  struct GTY(()) cp_parser {
      context e.g., because they could never be deduced.  */
   int prevent_constrained_type_specifiers;
 
+  /* The top-level node for the translation-unit.  */
+  blt_node * GTY((skip)) blt_root_node;
+
+  /* The current node being parsed.  */
+  blt_node * GTY((skip)) blt_current_node;
 };
 
 /* In parser.c  */
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index da133bd..8db4b4b 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -41,6 +41,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "type-utils.h"
 #include "gimplify.h"
 #include "gcc-rich-location.h"
+#include "blt.h"
 
 /* The type of functions taking a tree, and some additional data, and
    returning an int.  */
@@ -4480,6 +4481,13 @@  build_template_decl (tree decl, tree parms, bool member_template_p)
   DECL_SOURCE_LOCATION (tmpl) = DECL_SOURCE_LOCATION (decl);
   DECL_MEMBER_TEMPLATE_P (tmpl) = member_template_p;
 
+  if (flag_blt)
+    {
+      blt_node *decl_bltnode = blt_get_node_for_tree (decl);
+      if (decl_bltnode)
+        blt_set_node_for_tree (tmpl, decl_bltnode);
+    }
+
   return tmpl;
 }