From 305e70748106c2b8dc9596e2494d79ceb07af2de Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Thu, 20 Jul 2017 12:37:47 -0400 Subject: [PATCH 04/27] 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. --- gcc/c/c-decl.c | 13 ++- gcc/c/c-parser.c | 241 ++++++++++++++++++++++++++++++++++++++++++++++--------- gcc/c/c-tree.h | 6 +- 3 files changed, 221 insertions(+), 39 deletions(-) diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c index 50da185..ff27e55 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 f8fbc92..119ae23 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 *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 *locations, unsigned int *literal_zero_mask) { + AUTO_BLT_NODE (parser, BLT_NONEMPTY_EXPR_LIST); + vec *ret; vec *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 a8197eb..9455fcf 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 *); -- 1.8.5.3