From d19c0f4b4cdf4bdffa313283207aab6d2518f34c Mon Sep 17 00:00:00 2001 From: Dodji Seketeli Date: Sun, 5 Oct 2008 21:29:32 +0000 Subject: [PATCH] re PR debug/37410 (DW_TAG_imported_module is not in its DW_TAG_lexical_block) 2008-09-30 Dodji Seketeli gcc/ChangeLog: PR c++/37410 * dwarf2out.c (dwarf2out_imported_module_or_decl): Split this function in two, making it call a new and reusable dwarf2out_imported_module_or_decl() that takes the containing BLOCK of the declaration in argument. (dwarf2out_imported_module_or_decl_real): New function. (decls_for_scope, gen_decl_die, dwarf2out_decl): Take IMPORTED_DECL in account. * tree.def: Added IMPORTED_DECL node type. * tree.h: Added accessors for IMPORTED_DECL nodes. * tree.c (init_ttree): Initialise IMPORTED_DECL node type. gcc/cp/ChangeLog: PR c++/37410 * cp-gimplify.c (cp_gimplify_expr): For each USING_STMT make sure an IMPORTED_DECL node is added to the BLOCK_VARS list of the innermost containing BLOCK. gcc/testsuite/ChangeLog: PR c++/37410 * g++.dg/debug/dwarf2/imported-module.C: New test. From-SVN: r140895 --- gcc/ChangeLog | 14 +++ gcc/cp/ChangeLog | 7 ++ gcc/cp/cp-gimplify.c | 35 +++++- gcc/cp/name-lookup.c | 11 +- gcc/dwarf2out.c | 118 ++++++++++++------ gcc/print-tree.c | 6 + gcc/testsuite/ChangeLog | 6 + .../g++.dg/debug/dwarf2/imported-module.C | 35 ++++++ gcc/tree.c | 2 + gcc/tree.def | 11 ++ gcc/tree.h | 5 + 11 files changed, 204 insertions(+), 46 deletions(-) create mode 100644 gcc/testsuite/g++.dg/debug/dwarf2/imported-module.C diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 71eaead3463..c58932c9e27 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,17 @@ +2008-10-05 Dodji Seketeli + + PR c++/37410 + * dwarf2out.c (dwarf2out_imported_module_or_decl): Split this + function in two, making it call a new and reusable + dwarf2out_imported_module_or_decl() that takes the containing + BLOCK of the declaration in argument. + (dwarf2out_imported_module_or_decl_real): New function. + (decls_for_scope, gen_decl_die, dwarf2out_decl): Take + IMPORTED_DECL in account. + * tree.def: Added IMPORTED_DECL node type. + * tree.h: Added accessors for IMPORTED_DECL nodes. + * tree.c (init_ttree): Initialise IMPORTED_DECL node type. + 2008-10-05 Ralf Wildenhues * doc/gimple.texi: Fix some typos, wrap some long lines, diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index acb766f7124..eeeb239b720 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2008-10-05 Dodji Seketeli + + PR c++/37410 + * cp-gimplify.c (cp_gimplify_expr): For each USING_STMT + make sure an IMPORTED_DECL node is added to the BLOCK_VARS list + of the innermost containing BLOCK. + 2008-10-03 Paolo Carlini PR c++/37719 diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c index 243b1c61bfb..a1542b9f804 100644 --- a/gcc/cp/cp-gimplify.c +++ b/gcc/cp/cp-gimplify.c @@ -508,6 +508,8 @@ cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p) int saved_stmts_are_full_exprs_p = 0; enum tree_code code = TREE_CODE (*expr_p); enum gimplify_status ret; + tree block = NULL; + VEC(gimple, heap) *bind_expr_stack = NULL; if (STATEMENT_CODE_P (code)) { @@ -574,8 +576,37 @@ cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p) break; case USING_STMT: - /* Just ignore for now. Eventually we will want to pass this on to - the debugger. */ + /* Get the innermost inclosing GIMPLE_BIND that has a non NULL + BLOCK, and append an IMPORTED_DECL to its + BLOCK_VARS chained list. */ + + bind_expr_stack = gimple_bind_expr_stack (); + if (bind_expr_stack) + { + int i; + for (i = VEC_length (gimple, bind_expr_stack) - 1; i >= 0; i--) + if ((block = gimple_bind_block (VEC_index (gimple, + bind_expr_stack, + i)))) + break; + } + if (block) + { + tree using_directive; + gcc_assert (TREE_OPERAND (*expr_p,0) + && NAMESPACE_DECL_CHECK (TREE_OPERAND (*expr_p, 0))); + + using_directive = make_node (IMPORTED_DECL); + TREE_TYPE (using_directive) = void_type_node; + + IMPORTED_DECL_ASSOCIATED_DECL (using_directive) + = TREE_OPERAND (*expr_p, 0); + DECL_NAME (using_directive) + = DECL_NAME (TREE_OPERAND (*expr_p, 0)); + TREE_CHAIN (using_directive) = BLOCK_VARS (block); + BLOCK_VARS (block) = using_directive; + } + /* The USING_STMT won't appear in GIMPLE. */ *expr_p = NULL; ret = GS_ALL_DONE; break; diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index a04d7312216..0da373ce2a6 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -3484,7 +3484,6 @@ do_using_directive (tree name_space) if (!toplevel_bindings_p ()) { push_using_directive (name_space); - context = current_scope (); } else { @@ -3492,12 +3491,12 @@ do_using_directive (tree name_space) add_using_namespace (current_namespace, name_space, 0); if (current_namespace != global_namespace) context = current_namespace; - } - /* Emit debugging info. */ - if (!processing_template_decl) - (*debug_hooks->imported_module_or_decl) (name_space, NULL_TREE, - context, false); + /* Emit debugging info. */ + if (!processing_template_decl) + (*debug_hooks->imported_module_or_decl) (name_space, NULL_TREE, + context, false); + } } /* Deal with a using-directive seen by the parser. Currently we only diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index e39e687edbb..37bf21f07a2 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -4489,6 +4489,8 @@ static bool dwarf2out_ignore_block (const_tree); static void dwarf2out_global_decl (tree); static void dwarf2out_type_decl (tree, int); static void dwarf2out_imported_module_or_decl (tree, tree, tree, bool); +static void dwarf2out_imported_module_or_decl_1 (tree, tree, tree, + dw_die_ref); static void dwarf2out_abstract_function (tree); static void dwarf2out_var_location (rtx); static void dwarf2out_begin_function (tree); @@ -14918,6 +14920,9 @@ decls_for_scope (tree stmt, dw_die_ref context_die, int depth) if (TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl) && !(is_fortran () && TREE_PUBLIC (decl))) ; + else if (TREE_CODE (decl) == IMPORTED_DECL) + dwarf2out_imported_module_or_decl_1 (decl, DECL_NAME (decl), + stmt, context_die); else gen_decl_die (decl, context_die); } @@ -15309,6 +15314,7 @@ gen_decl_die (tree decl, dw_die_ref context_die) break; case NAMESPACE_DECL: + case IMPORTED_DECL: gen_namespace_die (decl); break; @@ -15343,44 +15349,20 @@ dwarf2out_type_decl (tree decl, int local) } /* Output debug information for imported module or decl DECL. - NAME is non-NULL name in context if the decl has been renamed. - CHILD is true if decl is one of the renamed decls as part of - importing whole module. */ - + NAME is non-NULL name in the lexical block if the decl has been renamed. + LEXICAL_BLOCK is the lexical block (which TREE_CODE is a BLOCK) + that DECL belongs to. + LEXICAL_BLOCK_DIE is the DIE of LEXICAL_BLOCK. */ static void -dwarf2out_imported_module_or_decl (tree decl, tree name, tree context, - bool child) +dwarf2out_imported_module_or_decl_1 (tree decl, + tree name, + tree lexical_block, + dw_die_ref lexical_block_die) { - dw_die_ref imported_die, at_import_die; - dw_die_ref scope_die; expanded_location xloc; + dw_die_ref imported_die = NULL; + dw_die_ref at_import_die; - if (debug_info_level <= DINFO_LEVEL_TERSE) - return; - - gcc_assert (decl); - - /* To emit DW_TAG_imported_module or DW_TAG_imported_decl, we need two DIEs. - We need decl DIE for reference and scope die. First, get DIE for the decl - itself. */ - - /* Get the scope die for decl context. Use comp_unit_die for global module - or decl. If die is not found for non globals, force new die. */ - if (context - && TYPE_P (context) - && !should_emit_struct_debug (context, DINFO_USAGE_DIR_USE)) - return; - scope_die = get_context_die (context); - - if (child) - { - gcc_assert (scope_die->die_child); - gcc_assert (scope_die->die_child->die_tag == DW_TAG_imported_module); - gcc_assert (TREE_CODE (decl) != NAMESPACE_DECL); - scope_die = scope_die->die_child; - } - - /* For TYPE_DECL or CONST_DECL, lookup TREE_TYPE. */ if (TREE_CODE (decl) == TYPE_DECL || TREE_CODE (decl) == CONST_DECL) { if (is_base_type (TREE_TYPE (decl))) @@ -15398,6 +15380,19 @@ dwarf2out_imported_module_or_decl (tree decl, tree name, tree context, gcc_assert (at_import_die); } } + else if (TREE_CODE (decl) == IMPORTED_DECL) + { + tree imported_ns_decl; + /* IMPORTED_DECL nodes that are not imported namespace are just not + supported yet. */ + gcc_assert (DECL_INITIAL (decl) + && TREE_CODE (DECL_INITIAL (decl)) == NAMESPACE_DECL); + imported_ns_decl = DECL_INITIAL (decl); + at_import_die = lookup_decl_die (imported_ns_decl); + if (!at_import_die) + at_import_die = force_decl_die (imported_ns_decl); + gcc_assert (at_import_die); + } else { at_import_die = lookup_decl_die (decl); @@ -15421,20 +15416,66 @@ dwarf2out_imported_module_or_decl (tree decl, tree name, tree context, } } - /* OK, now we have DIEs for decl as well as scope. Emit imported die. */ if (TREE_CODE (decl) == NAMESPACE_DECL) - imported_die = new_die (DW_TAG_imported_module, scope_die, context); + imported_die = new_die (DW_TAG_imported_module, + lexical_block_die, + lexical_block); else - imported_die = new_die (DW_TAG_imported_declaration, scope_die, context); + imported_die = new_die (DW_TAG_imported_declaration, + lexical_block_die, + lexical_block); xloc = expand_location (input_location); add_AT_file (imported_die, DW_AT_decl_file, lookup_filename (xloc.file)); add_AT_unsigned (imported_die, DW_AT_decl_line, xloc.line); if (name) - add_AT_string (imported_die, DW_AT_name, IDENTIFIER_POINTER (name)); + add_AT_string (imported_die, DW_AT_name, + IDENTIFIER_POINTER (name)); add_AT_die_ref (imported_die, DW_AT_import, at_import_die); } +/* Output debug information for imported module or decl DECL. + NAME is non-NULL name in context if the decl has been renamed. + CHILD is true if decl is one of the renamed decls as part of + importing whole module. */ + +static void +dwarf2out_imported_module_or_decl (tree decl, tree name, tree context, + bool child) +{ + /* dw_die_ref at_import_die; */ + dw_die_ref scope_die; + + if (debug_info_level <= DINFO_LEVEL_TERSE) + return; + + gcc_assert (decl); + + /* To emit DW_TAG_imported_module or DW_TAG_imported_decl, we need two DIEs. + We need decl DIE for reference and scope die. First, get DIE for the decl + itself. */ + + /* Get the scope die for decl context. Use comp_unit_die for global module + or decl. If die is not found for non globals, force new die. */ + if (context + && TYPE_P (context) + && !should_emit_struct_debug (context, DINFO_USAGE_DIR_USE)) + return; + scope_die = get_context_die (context); + + if (child) + { + gcc_assert (scope_die->die_child); + gcc_assert (scope_die->die_child->die_tag == DW_TAG_imported_module); + gcc_assert (TREE_CODE (decl) != NAMESPACE_DECL); + scope_die = scope_die->die_child; + } + + /* OK, now we have DIEs for decl as well as scope. Emit imported die. */ + dwarf2out_imported_module_or_decl_1 (decl, name, context, scope_die); + +} + /* Write the debugging output for DECL. */ void @@ -15519,6 +15560,7 @@ dwarf2out_decl (tree decl) break; case NAMESPACE_DECL: + case IMPORTED_DECL: if (debug_info_level <= DINFO_LEVEL_TERSE) return; if (lookup_decl_die (decl) != NULL) diff --git a/gcc/print-tree.c b/gcc/print-tree.c index 16ba3929fab..fb9f12692c6 100644 --- a/gcc/print-tree.c +++ b/gcc/print-tree.c @@ -926,6 +926,12 @@ print_node (FILE *file, const char *prefix, tree node, int indent) case TARGET_OPTION_NODE: cl_target_option_print (file, indent + 4, TREE_TARGET_OPTION (node)); break; + case IMPORTED_DECL: + fprintf (file, " imported declaration"); + print_node_brief (file, "associated declaration", + IMPORTED_DECL_ASSOCIATED_DECL (node), + indent + 4); + break; default: if (EXCEPTIONAL_CLASS_P (node)) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index df7ba0b1e96..3edb676dcc8 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2008-10-05 Dodji Seketeli + + + PR c++/37410 + * g++.dg/debug/dwarf2/imported-module.C: New test. + 2008-10-05 Paul Thomas PR fortran/35680 diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/imported-module.C b/gcc/testsuite/g++.dg/debug/dwarf2/imported-module.C new file mode 100644 index 00000000000..7b25233f1ab --- /dev/null +++ b/gcc/testsuite/g++.dg/debug/dwarf2/imported-module.C @@ -0,0 +1,35 @@ +// Contributed by Dodji Seketeli +// Origin: PR debug/37410 +// { dg-do compile } + +namespace A1 + { + int aaa = 1; + }; +namespace A2 + { + int aaa = 2; + }; + +int +foo (void) +{ + int x; + + { + int block_create; + using namespace A1; + + block_create = aaa; /* break1 */ + } + + { + int block_create; + using namespace A2; + + block_create = aaa; /* break2 */ + } + + return x = 0; +} + diff --git a/gcc/tree.c b/gcc/tree.c index 4b178d5073f..33ab8b7078b 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -343,6 +343,8 @@ init_ttree (void) tree_contains_struct[CONST_DECL][TS_CONST_DECL] = 1; tree_contains_struct[TYPE_DECL][TS_TYPE_DECL] = 1; tree_contains_struct[FUNCTION_DECL][TS_FUNCTION_DECL] = 1; + tree_contains_struct[IMPORTED_DECL][TS_DECL_MINIMAL] = 1; + tree_contains_struct[IMPORTED_DECL][TS_DECL_COMMON] = 1; lang_hooks.init_ts (); } diff --git a/gcc/tree.def b/gcc/tree.def index ef103cdba50..bde59b7016c 100644 --- a/gcc/tree.def +++ b/gcc/tree.def @@ -371,6 +371,17 @@ DEFTREECODE (MEMORY_PARTITION_TAG, "memory_partition_tag", tcc_declaration, 0) _DECLs, providing a hierarchy of names. */ DEFTREECODE (NAMESPACE_DECL, "namespace_decl", tcc_declaration, 0) +/* A declaration import. + The C++ FE uses this to represent a using-directive; eg: + "using namespace foo". + But it could be used to represent any declaration import construct. + Whenever a declaration import appears in a lexical block, the BLOCK node + representing that lexical block in GIMPLE will contain an IMPORTED_DECL + node, linked via BLOCK_VARS accessor of the said BLOCK. + For a given NODE which code is IMPORTED_DECL, + IMPORTED_DECL_ASSOCIATED_DECL (NODE) accesses the imported declaration. */ +DEFTREECODE (IMPORTED_DECL, "imported_decl", tcc_declaration, 0) + /* A translation unit. This is not technically a declaration, since it can't be looked up, but it's close enough. */ DEFTREECODE (TRANSLATION_UNIT_DECL, "translation_unit_decl",\ diff --git a/gcc/tree.h b/gcc/tree.h index 4c046c29d64..85704e69094 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -3334,6 +3334,11 @@ struct tree_function_decl GTY(()) #define TYPE_DECL_SUPPRESS_DEBUG(NODE) \ (TYPE_DECL_CHECK (NODE)->decl_common.decl_flag_2) +/* Getter of the imported declaration associated to the + IMPORTED_DECL node. */ +#define IMPORTED_DECL_ASSOCIATED_DECL(NODE) \ +(DECL_INITIAL (IMPORTED_DECL_CHECK (NODE))) + struct tree_type_decl GTY(()) { struct tree_decl_non_common common; -- 2.30.2