* [PATCH] fix PR c++/37410
@ 2008-10-02 12:34 Dodji Seketeli
2008-10-02 22:52 ` Jason Merrill
0 siblings, 1 reply; 4+ messages in thread
From: Dodji Seketeli @ 2008-10-02 12:34 UTC (permalink / raw)
To: Gcc Patch List; +Cc: Jason Merrill, Jakub Jelinek, Jan Kratochvil
[-- Attachment #1: Type: text/plain, Size: 721 bytes --]
Hello,
When a "using namespace foo;" construct (aka using-directive) happens to
be in a lexical block nested in a function, the dwarf info generated by
g++ does not take in account the innermost lexical block, but rather
attaches the using-directive to the containing function.
This this patch tries to address the problem.
However, I have a problem to come up with a way to write a dejagnu test
for this. The test would have to make sure the DW_TAG_imported_module is
a child node of its innermost DW_TAG_lexical_block rather than a child
of the containing DW_TAG_lexical_block. I have no idea how to write such
a test.
Besides that the patch passes regtest on trunk for the x86_64 platform.
Cheers,
Dodji.
[-- Attachment #2: PR37410-patch-1.txt --]
[-- Type: text/plain, Size: 13669 bytes --]
gcc/ChangeLog:
2008-09-30 Dodji Seketeli <dodji@redhat.com>
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:
2008-09-30 Dodji Seketeli <dodji@redhat.com>
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:
2008-09-30 Dodji Seketeli <dodji@redhat.com>
PR c++/37410
* g++.dg/debug/dwarf2/imported-module.C: New test.
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index 243b1c6..a1542b9 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 a04d731..0da373c 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 e39e687..5556339 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,21 @@ 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. */
-
+ IMPORTED_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 imported_module_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 +15381,17 @@ 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;
+ 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 +15415,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));
+ if (imported_module_name)
+ add_AT_string (imported_die, DW_AT_name,
+ IDENTIFIER_POINTER (imported_module_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 +15559,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 16ba392..fb9f126 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/g++.dg/debug/dwarf2/imported-module.C b/gcc/testsuite/g++.dg/debug/dwarf2/imported-module.C
new file mode 100644
index 0000000..7b25233
--- /dev/null
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/imported-module.C
@@ -0,0 +1,35 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// 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 3d2f3e1..f480cbd 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 ef103cd..bde59b7 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 4c046c2..85704e6 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;
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] fix PR c++/37410
2008-10-02 12:34 [PATCH] fix PR c++/37410 Dodji Seketeli
@ 2008-10-02 22:52 ` Jason Merrill
2008-10-03 16:19 ` Dodji Seketeli
0 siblings, 1 reply; 4+ messages in thread
From: Jason Merrill @ 2008-10-02 22:52 UTC (permalink / raw)
To: Dodji Seketeli; +Cc: Gcc Patch List, Jakub Jelinek, Jan Kratochvil
Dodji Seketeli wrote:
> -dwarf2out_imported_module_or_decl (tree decl, tree name, tree context,
> - bool child)
> +dwarf2out_imported_module_or_decl_1 (tree decl,
> + tree imported_module_name,
Why change the name of the "name" parameter? It seems to me that it can
apply to imported decls as well.
> + else if (TREE_CODE (decl) == IMPORTED_DECL)
> + {
> + tree imported_ns_decl;
> + 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);
I'm still not sure why we need this assert. Wouldn't this
code work just as well for another sort of imported decl, given a
language that supports such a thing? If you want to keep the assert,
please add a comment that there's no real reason why other decls are
inappropriate, they just aren't supported here yet.
Jason
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] fix PR c++/37410
2008-10-02 22:52 ` Jason Merrill
@ 2008-10-03 16:19 ` Dodji Seketeli
2008-10-03 19:01 ` Jason Merrill
0 siblings, 1 reply; 4+ messages in thread
From: Dodji Seketeli @ 2008-10-03 16:19 UTC (permalink / raw)
To: Jason Merrill; +Cc: Gcc Patch List, Jakub Jelinek, Jan Kratochvil
[-- Attachment #1: Type: text/plain, Size: 134 bytes --]
Hello Jason,
The attached patch should hopefully address your comments.
It has been regtested for x86_84 on trunk.
Cheers,
Dodji.
[-- Attachment #2: PR37410-patch-2.txt --]
[-- Type: text/plain, Size: 13651 bytes --]
gcc/ChangeLog:
2008-09-30 Dodji Seketeli <dodji@redhat.com>
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:
2008-09-30 Dodji Seketeli <dodji@redhat.com>
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:
2008-09-30 Dodji Seketeli <dodji@redhat.com>
PR c++/37410
* g++.dg/debug/dwarf2/imported-module.C: New test.
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index 243b1c6..a1542b9 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 a04d731..0da373c 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 e39e687..5629462 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,21 @@ 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. */
-
+ IMPORTED_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 +15381,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 +15417,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 +15561,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 16ba392..fb9f126 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/g++.dg/debug/dwarf2/imported-module.C b/gcc/testsuite/g++.dg/debug/dwarf2/imported-module.C
new file mode 100644
index 0000000..7b25233
--- /dev/null
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/imported-module.C
@@ -0,0 +1,35 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// 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 3d2f3e1..f480cbd 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 ef103cd..bde59b7 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 4c046c2..85704e6 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;
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] fix PR c++/37410
2008-10-03 16:19 ` Dodji Seketeli
@ 2008-10-03 19:01 ` Jason Merrill
0 siblings, 0 replies; 4+ messages in thread
From: Jason Merrill @ 2008-10-03 19:01 UTC (permalink / raw)
To: Dodji Seketeli; +Cc: Gcc Patch List, Jakub Jelinek, Jan Kratochvil
> + IMPORTED_MODULE_NAME is non-NULL name in the lexical block
> + if the decl has been renamed.
The comment still has the changed name. OK with that corrected.
Jason
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2008-10-03 18:18 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-10-02 12:34 [PATCH] fix PR c++/37410 Dodji Seketeli
2008-10-02 22:52 ` Jason Merrill
2008-10-03 16:19 ` Dodji Seketeli
2008-10-03 19:01 ` Jason Merrill
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).