summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Malcolm <dmalcolm@redhat.com>2017-07-20 12:37:47 -0400
committerDavid Malcolm <dmalcolm@redhat.com>2017-07-28 12:47:27 -0400
commit028fafdc6d6579c4606ce8347ded8db366334477 (patch)
tree107261f720934979fffd81a24765e2799aafbfcf
parent89989f03d291c2ad031ffe5a6bd0ba4ed6148397 (diff)
downloadgcc-028fafdc6d6579c4606ce8347ded8db366334477.tar.gz
C frontend: capture BLT information
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 nothing is built by default. gcc/c/ChangeLog: * c-decl.c: Include "blt.h". (build_array_declarator): Initialize bltnode field of new declarator. (start_decl): Associate this decl with any bltnode of the declarator. (start_function): Likewise. (build_attrs_declarator): Initialize bltnode field of new declarator. (build_function_declarator): Add bltnode param, and use it to initialize the bltnode field of the new declarator. (build_id_declarator): Likewise. (make_pointer_declarator): Likewise. * c-parser.c: Include "blt.h". (struct c_parser): Add fields "last_token_location", "blt_root_node", "blt_current_node". (class auto_blt_node): New class. (AUTO_BLT_NODE): New macro. (CURRENT_BLT_NODE): New macro. (auto_blt_node::auto_blt_node): New ctor. (auto_blt_node::~auto_blt_node): New dtor. (auto_blt_node::set_tree): New method. (c_parser_consume_token): Update last_token_location. (c_parser_translation_unit): Add AUTO_BLT_NODE. (c_parser_external_declaration): Likewise. (c_parser_declspecs): Likewise, in multiple places. (c_parser_struct_or_union_specifier): Likewise. Set the tree on the struct-contents and the struct-or-union-specifier. (c_parser_struct_declaration): Add AUTO_BLT_NODE. (c_parser_declarator): Likewise. (c_parser_direct_declarator): Likewise. Set up the bltnode of the declarator. (c_parser_direct_declarator_inner): Pass the bltnode to the declarator. (c_parser_parms_declarator): Add AUTO_BLT_NODE. (c_parser_parameter_declaration): Likewise. (c_parser_expr_no_commas): Likewise. (c_parser_expression): Likewise. (c_parser_expr_list): Likewise. (c_parse_file): Handle -fdump-blt; set the_blt_root_node. * c-tree.h (class blt_node): Add forward decl. (struct c_declarator): Add "bltnode" field. (build_function_declarator): Add blt_node * param.
-rw-r--r--gcc/c/c-decl.c13
-rw-r--r--gcc/c/c-parser.c241
-rw-r--r--gcc/c/c-tree.h6
3 files changed, 221 insertions, 39 deletions
diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index 50da185e363..ff27e552445 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -54,6 +54,7 @@ along with GCC; see the file COPYING3. If not see
#include "spellcheck-tree.h"
#include "gcc-rich-location.h"
#include "asan.h"
+#include "blt.h"
/* In grokdeclarator, distinguish syntactic contexts of declarators. */
enum decl_context
@@ -4503,6 +4504,7 @@ build_array_declarator (location_t loc,
}
current_scope->had_vla_unspec = true;
}
+ declarator->bltnode = NULL;
return declarator;
}
@@ -4627,6 +4629,8 @@ start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs,
deprecated_state);
if (!decl || decl == error_mark_node)
return NULL_TREE;
+ if (declarator->bltnode)
+ declarator->bltnode->set_tree (decl);
if (expr)
add_stmt (fold_convert (void_type_node, expr));
@@ -8527,6 +8531,8 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator,
decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, true, NULL,
&attributes, NULL, NULL, DEPRECATED_NORMAL);
+ if (declarator->bltnode)
+ declarator->bltnode->set_tree (decl1);
invoke_plugin_callbacks (PLUGIN_START_PARSE_FUNCTION, decl1);
/* If the declarator is not suitable for a function definition,
@@ -9645,6 +9651,7 @@ build_attrs_declarator (tree attrs, struct c_declarator *target)
ret->kind = cdk_attrs;
ret->declarator = target;
ret->u.attrs = attrs;
+ ret->bltnode = NULL;
return ret;
}
@@ -9653,12 +9660,14 @@ build_attrs_declarator (tree attrs, struct c_declarator *target)
struct c_declarator *
build_function_declarator (struct c_arg_info *args,
- struct c_declarator *target)
+ struct c_declarator *target,
+ blt_node *bltnode)
{
struct c_declarator *ret = XOBNEW (&parser_obstack, struct c_declarator);
ret->kind = cdk_function;
ret->declarator = target;
ret->u.arg_info = args;
+ ret->bltnode = bltnode;
return ret;
}
@@ -9674,6 +9683,7 @@ build_id_declarator (tree ident)
ret->u.id = ident;
/* Default value - may get reset to a more precise location. */
ret->id_loc = input_location;
+ ret->bltnode = NULL;
return ret;
}
@@ -9700,6 +9710,7 @@ make_pointer_declarator (struct c_declspecs *type_quals_attrs,
ret->kind = cdk_pointer;
ret->declarator = itarget;
ret->u.pointer_quals = quals;
+ ret->bltnode = NULL;
return ret;
}
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index f8fbc926172..119ae237246 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -65,6 +65,7 @@ along with GCC; see the file COPYING3. If not see
#include "read-rtl-function.h"
#include "run-rtl-passes.h"
#include "intl.h"
+#include "blt.h"
/* We need to walk over decls with incomplete struct/union/enum types
after parsing the whole translation unit.
@@ -206,8 +207,115 @@ struct GTY(()) c_parser {
/* Buffer to hold all the tokens from parsing the vector attribute for the
SIMD-enabled functions (formerly known as elemental functions). */
vec <c_token, va_gc> *cilk_simd_fn_tokens;
+
+ location_t last_token_location;
+ blt_node * GTY((skip)) blt_root_node;
+ blt_node * GTY((skip)) blt_current_node;
+};
+
+/* 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 (c_parser* parser, enum blt_kind kind);
+ ~auto_blt_node ();
+
+ void set_tree (tree node);
+
+private:
+ c_parser *m_parser;
};
+/* 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))
+
+/* The blt_node currently being constructed (the macro assumes that "parser"
+ exists in the current scope). */
+
+#define CURRENT_BLT_NODE (parser->blt_current_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 (c_parser *parser, enum blt_kind kind)
+{
+ if (!flag_blt)
+ return;
+
+ /* Do this here rather than as an initializer
+ to avoid doing work when -fblt is not set. */
+ m_parser = parser;
+
+ c_token *first_token = c_parser_peek_token (parser);
+ blt_node *parent = parser->blt_current_node;
+ blt_node *node = new blt_node (kind, first_token->location);
+ parser->blt_current_node = node;
+ if (parent)
+ 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. */
+
+auto_blt_node::~auto_blt_node ()
+{
+ if (!flag_blt)
+ return;
+
+ blt_node *node = m_parser->blt_current_node;
+ node->set_finish (m_parser->last_token_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 0
+ if (m_expr_ptr)
+ node->set_tree (m_expr_ptr->get_value ());
+#endif
+
+ m_parser->blt_current_node = node->get_parent ();
+}
+
+/* Set the current blt_node's tree to be TREE_NODE.
+ Do nothing if -fblt is not set. */
+
+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);
+}
+
/* Return a pointer to the Nth token in PARSERs tokens_buf. */
c_token *
@@ -770,6 +878,7 @@ c_parser_consume_token (c_parser *parser)
gcc_assert (parser->tokens[0].type != CPP_EOF);
gcc_assert (!parser->in_pragma || parser->tokens[0].type != CPP_PRAGMA_EOL);
gcc_assert (parser->error || parser->tokens[0].type != CPP_PRAGMA);
+ parser->last_token_location = parser->tokens[0].location;
if (parser->tokens != &parser->tokens_buf[0])
parser->tokens++;
else if (parser->tokens_avail == 2)
@@ -1336,6 +1445,8 @@ static void c_parser_parse_rtl_body (c_parser *parser, char *start_with_pass);
static void
c_parser_translation_unit (c_parser *parser)
{
+ AUTO_BLT_NODE (parser, BLT_TRANSLATION_UNIT);
+
if (c_parser_next_token_is (parser, CPP_EOF))
{
pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic,
@@ -1388,6 +1499,8 @@ c_parser_translation_unit (c_parser *parser)
static void
c_parser_external_declaration (c_parser *parser)
{
+ AUTO_BLT_NODE (parser, BLT_EXTERNAL_DECLARATION);
+
int ext;
switch (c_parser_peek_token (parser)->type)
{
@@ -2378,6 +2491,8 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
bool alignspec_ok, bool auto_type_ok,
enum c_lookahead_kind la)
{
+ AUTO_BLT_NODE (parser, BLT_DECLARATION_SPECIFIERS);
+
bool attrs_ok = start_attr_ok;
bool seen_type = specs->typespec_kind != ctsk_none;
@@ -2427,6 +2542,8 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
if (seen_type || !c_parser_next_tokens_start_typename (parser, la))
break;
+ AUTO_BLT_NODE (parser, BLT_TYPE_SPECIFIER);
+
/* Now at an unknown typename (C_ID_ID), a C_ID_TYPENAME or
a C_ID_CLASSNAME. */
c_parser_consume_token (parser);
@@ -2524,48 +2641,61 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
case RID_INT_N_1:
case RID_INT_N_2:
case RID_INT_N_3:
- if (!typespec_ok)
- goto out;
- attrs_ok = true;
- seen_type = true;
- if (c_dialect_objc ())
- parser->objc_need_raw_identifier = true;
- t.kind = ctsk_resword;
- t.spec = c_parser_peek_token (parser)->value;
- t.expr = NULL_TREE;
- t.expr_const_operands = true;
- declspecs_add_type (loc, specs, t);
- c_parser_consume_token (parser);
+ {
+ if (!typespec_ok)
+ goto out;
+
+ AUTO_BLT_NODE (the_parser, BLT_TYPE_SPECIFIER);
+ attrs_ok = true;
+ seen_type = true;
+ if (c_dialect_objc ())
+ parser->objc_need_raw_identifier = true;
+ t.kind = ctsk_resword;
+ t.spec = c_parser_peek_token (parser)->value;
+ t.expr = NULL_TREE;
+ t.expr_const_operands = true;
+ declspecs_add_type (loc, specs, t);
+ c_parser_consume_token (parser);
+ }
break;
case RID_ENUM:
- if (!typespec_ok)
- goto out;
- attrs_ok = true;
- seen_type = true;
- t = c_parser_enum_specifier (parser);
- invoke_plugin_callbacks (PLUGIN_FINISH_TYPE, t.spec);
- declspecs_add_type (loc, specs, t);
+ {
+ if (!typespec_ok)
+ goto out;
+ AUTO_BLT_NODE (the_parser, BLT_TYPE_SPECIFIER);
+ attrs_ok = true;
+ seen_type = true;
+ t = c_parser_enum_specifier (parser);
+ invoke_plugin_callbacks (PLUGIN_FINISH_TYPE, t.spec);
+ declspecs_add_type (loc, specs, t);
+ }
break;
case RID_STRUCT:
case RID_UNION:
- if (!typespec_ok)
- goto out;
- attrs_ok = true;
- seen_type = true;
- t = c_parser_struct_or_union_specifier (parser);
- invoke_plugin_callbacks (PLUGIN_FINISH_TYPE, t.spec);
- declspecs_add_type (loc, specs, t);
+ {
+ if (!typespec_ok)
+ goto out;
+ AUTO_BLT_NODE (the_parser, BLT_TYPE_SPECIFIER);
+ attrs_ok = true;
+ seen_type = true;
+ t = c_parser_struct_or_union_specifier (parser);
+ invoke_plugin_callbacks (PLUGIN_FINISH_TYPE, t.spec);
+ declspecs_add_type (loc, specs, t);
+ }
break;
case RID_TYPEOF:
- /* ??? The old parser rejected typeof after other type
- specifiers, but is a syntax error the best way of
- handling this? */
- if (!typespec_ok || seen_type)
- goto out;
- attrs_ok = true;
- seen_type = true;
- t = c_parser_typeof_specifier (parser);
- declspecs_add_type (loc, specs, t);
+ {
+ /* ??? The old parser rejected typeof after other type
+ specifiers, but is a syntax error the best way of
+ handling this? */
+ if (!typespec_ok || seen_type)
+ goto out;
+ AUTO_BLT_NODE (the_parser, BLT_TYPE_SPECIFIER);
+ attrs_ok = true;
+ seen_type = true;
+ t = c_parser_typeof_specifier (parser);
+ declspecs_add_type (loc, specs, t);
+ }
break;
case RID_ATOMIC:
/* C parser handling of Objective-C constructs needs
@@ -2863,6 +2993,8 @@ c_parser_enum_specifier (c_parser *parser)
static struct c_typespec
c_parser_struct_or_union_specifier (c_parser *parser)
{
+ AUTO_BLT_NODE (parser, BLT_STRUCT_OR_UNION_SPECIFIER);
+
struct c_typespec ret;
tree attrs;
tree ident = NULL_TREE;
@@ -2898,6 +3030,8 @@ c_parser_struct_or_union_specifier (c_parser *parser)
{
/* Parse a struct or union definition. Start the scope of the
tag before parsing components. */
+ AUTO_BLT_NODE (parser, BLT_STRUCT_CONTENTS);
+
struct c_struct_parse_info *struct_info;
tree type = start_struct (struct_loc, code, ident, &struct_info);
tree postfix_attrs;
@@ -3006,6 +3140,10 @@ c_parser_struct_or_union_specifier (c_parser *parser)
ret.expr = NULL_TREE;
ret.expr_const_operands = true;
timevar_pop (TV_PARSE_STRUCT);
+
+ if (CURRENT_BLT_NODE)
+ CURRENT_BLT_NODE->set_tree (ret.spec);
+
return ret;
}
else if (!ident)
@@ -3017,7 +3155,12 @@ c_parser_struct_or_union_specifier (c_parser *parser)
ret.expr_const_operands = true;
return ret;
}
+
ret = parser_xref_tag (ident_loc, code, ident);
+
+ if (CURRENT_BLT_NODE)
+ CURRENT_BLT_NODE->set_tree (ret.spec);
+
return ret;
}
@@ -3056,6 +3199,8 @@ c_parser_struct_or_union_specifier (c_parser *parser)
static tree
c_parser_struct_declaration (c_parser *parser)
{
+ AUTO_BLT_NODE (parser, BLT_STRUCT_DECLARATION);
+
struct c_declspecs *specs;
tree prefix_attrs;
tree all_prefix_attrs;
@@ -3393,6 +3538,8 @@ struct c_declarator *
c_parser_declarator (c_parser *parser, bool type_seen_p, c_dtr_syn kind,
bool *seen_id)
{
+ AUTO_BLT_NODE (parser, BLT_DECLARATOR);
+
/* Parse any initial pointer part. */
if (c_parser_next_token_is (parser, CPP_MULT))
{
@@ -3419,6 +3566,8 @@ static struct c_declarator *
c_parser_direct_declarator (c_parser *parser, bool type_seen_p, c_dtr_syn kind,
bool *seen_id)
{
+ AUTO_BLT_NODE (parser, BLT_DIRECT_DECLARATOR);
+
/* The direct declarator must start with an identifier (possibly
omitted) or a parenthesized declarator (possibly abstract). In
an ordinary declarator, initial parentheses must start a
@@ -3462,6 +3611,7 @@ c_parser_direct_declarator (c_parser *parser, bool type_seen_p, c_dtr_syn kind,
{
struct c_declarator *inner
= build_id_declarator (c_parser_peek_token (parser)->value);
+ inner->bltnode = CURRENT_BLT_NODE;
*seen_id = true;
inner->id_loc = c_parser_peek_token (parser)->location;
c_parser_consume_token (parser);
@@ -3498,7 +3648,8 @@ c_parser_direct_declarator (c_parser *parser, bool type_seen_p, c_dtr_syn kind,
{
inner
= build_function_declarator (args,
- build_id_declarator (NULL_TREE));
+ build_id_declarator (NULL_TREE),
+ CURRENT_BLT_NODE);
return c_parser_direct_declarator_inner (parser, *seen_id,
inner);
}
@@ -3646,7 +3797,7 @@ c_parser_direct_declarator_inner (c_parser *parser, bool id_present,
return NULL;
else
{
- inner = build_function_declarator (args, inner);
+ inner = build_function_declarator (args, inner, CURRENT_BLT_NODE);
return c_parser_direct_declarator_inner (parser, id_present, inner);
}
}
@@ -3661,6 +3812,8 @@ c_parser_direct_declarator_inner (c_parser *parser, bool id_present,
static struct c_arg_info *
c_parser_parms_declarator (c_parser *parser, bool id_list_ok, tree attrs)
{
+ AUTO_BLT_NODE (parser, BLT_PARAMETER_LIST);
+
push_scope ();
declare_parm_level ();
/* If the list starts with an identifier, it is an identifier list.
@@ -3832,6 +3985,8 @@ c_parser_parms_list_declarator (c_parser *parser, tree attrs, tree expr)
static struct c_parm *
c_parser_parameter_declaration (c_parser *parser, tree attrs)
{
+ AUTO_BLT_NODE (parser, BLT_PARAMETER_DECLARATION);
+
struct c_declspecs *specs;
struct c_declarator *declarator;
tree prefix_attrs;
@@ -6422,6 +6577,8 @@ static struct c_expr
c_parser_expr_no_commas (c_parser *parser, struct c_expr *after,
tree omp_atomic_lhs)
{
+ AUTO_BLT_NODE (parser, BLT_ASSIGNMENT_EXPRESSION);
+
struct c_expr lhs, rhs, ret;
enum tree_code code;
location_t op_location, exp_location;
@@ -8655,6 +8812,8 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
static struct c_expr
c_parser_expression (c_parser *parser)
{
+ AUTO_BLT_NODE (parser, BLT_EXPRESSION);
+
location_t tloc = c_parser_peek_token (parser)->location;
struct c_expr expr;
expr = c_parser_expr_no_commas (parser, NULL);
@@ -8742,6 +8901,8 @@ c_parser_expr_list (c_parser *parser, bool convert_p, bool fold_p,
vec<location_t> *locations,
unsigned int *literal_zero_mask)
{
+ AUTO_BLT_NODE (parser, BLT_NONEMPTY_EXPR_LIST);
+
vec<tree, va_gc> *ret;
vec<tree, va_gc> *orig_types;
struct c_expr expr;
@@ -18166,6 +18327,12 @@ c_parse_file (void)
using_eh_for_cleanups ();
c_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/c/c-tree.h b/gcc/c/c-tree.h
index a8197eb768d..9455fcf386d 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -23,6 +23,8 @@ along with GCC; see the file COPYING3. If not see
#include "c-family/c-common.h"
#include "diagnostic.h"
+class blt_node;
+
/* struct lang_identifier is private to c-decl.c, but langhooks.c needs to
know how big it is. This is sanity-checked in c-decl.c. */
#define C_SIZEOF_STRUCT_LANG_IDENTIFIER \
@@ -451,6 +453,7 @@ struct c_declarator {
/* For attributes. */
tree attrs;
} u;
+ blt_node *bltnode;
};
/* A type name. */
@@ -577,7 +580,8 @@ extern struct c_parm *build_c_parm (struct c_declspecs *, tree,
extern struct c_declarator *build_attrs_declarator (tree,
struct c_declarator *);
extern struct c_declarator *build_function_declarator (struct c_arg_info *,
- struct c_declarator *);
+ struct c_declarator *,
+ blt_node *);
extern struct c_declarator *build_id_declarator (tree);
extern struct c_declarator *make_pointer_declarator (struct c_declspecs *,
struct c_declarator *);