Commit db5f8b93 by Richard Henderson Committed by Richard Henderson

re PR debug/23190 (debug info omitted for uninitialized variables (stabs))

        PR debug/23190
        * toplev.c (wrapup_global_declaration_1): Split out ...
        (wrapup_global_declaration_2): ... from ...
        (wrapup_global_declarations): ... here.  Return bool.
        (check_global_declaration_1): Split out ...
        (check_global_declarations): from here.
        (emit_debug_global_declarations): New.
        * toplev.h (wrapup_global_declaration_1, wrapup_global_declaration_2,
        check_global_declaration_1, emit_debug_global_declarations): Declare.
        * c-decl.c (c_write_global_declarations_1): Don't create a vector
        of decls.  Call wrapup_global_declaration_1,
        wrapup_global_declaration_2, check_global_declaration_1 directly.
        (c_write_global_declarations_2): New.
        (ext_block): New.
        (c_write_global_declarations): Call c_write_global_declarations_2.
        * langhooks.c (write_global_declarations): Call
        emit_debug_global_declarations.
        * cgraphunit.c (cgraph_varpool_remove_unreferenced_decls): Don't
        remove decls that have DECL_RTL_SET_P.
        * passes.c (rest_of_decl_compilation): Invoke
        cgraph_varpool_finalize_decl for all but functions.
cp/
        * decl.c (wrapup_globals_for_namespace): Call
        emit_debug_global_declarations.
        * decl2.c (cp_finish_file): Likewise.

From-SVN: r104065
parent 41306174
2005-09-08 Richard Henderson <rth@redhat.com>
PR debug/23190
* toplev.c (wrapup_global_declaration_1): Split out ...
(wrapup_global_declaration_2): ... from ...
(wrapup_global_declarations): ... here. Return bool.
(check_global_declaration_1): Split out ...
(check_global_declarations): from here.
(emit_debug_global_declarations): New.
* toplev.h (wrapup_global_declaration_1, wrapup_global_declaration_2,
check_global_declaration_1, emit_debug_global_declarations): Declare.
* c-decl.c (c_write_global_declarations_1): Don't create a vector
of decls. Call wrapup_global_declaration_1,
wrapup_global_declaration_2, check_global_declaration_1 directly.
(c_write_global_declarations_2): New.
(ext_block): New.
(c_write_global_declarations): Call c_write_global_declarations_2.
* langhooks.c (write_global_declarations): Call
emit_debug_global_declarations.
* cgraphunit.c (cgraph_varpool_remove_unreferenced_decls): Don't
remove decls that have DECL_RTL_SET_P.
* passes.c (rest_of_decl_compilation): Invoke
cgraph_varpool_finalize_decl for all but functions.
2005-09-08 Eric Botcazou <ebotcazou@libertysurf.fr> 2005-09-08 Eric Botcazou <ebotcazou@libertysurf.fr>
* tree-vrp.c (extract_range_from_unary_expr): Do not set the range for * tree-vrp.c (extract_range_from_unary_expr): Do not set the range for
......
...@@ -7540,20 +7540,18 @@ build_cdtor (int method_type, tree cdtors) ...@@ -7540,20 +7540,18 @@ build_cdtor (int method_type, tree cdtors)
cgraph_build_static_cdtor (method_type, body, DEFAULT_INIT_PRIORITY); cgraph_build_static_cdtor (method_type, body, DEFAULT_INIT_PRIORITY);
} }
/* Perform final processing on one file scope's declarations (or the /* A subroutine of c_write_global_declarations. Perform final processing
external scope's declarations), GLOBALS. */ on one file scope's declarations (or the external scope's declarations),
GLOBALS. */
static void static void
c_write_global_declarations_1 (tree globals) c_write_global_declarations_1 (tree globals)
{ {
size_t len = list_length (globals);
tree *vec = XNEWVEC (tree, len);
size_t i;
tree decl; tree decl;
/* Process the decls in the order they were written. */ /* Process the decls in the order they were written. */
for (i = 0, decl = globals; i < len; i++, decl = TREE_CHAIN (decl)) for (decl = globals; decl; decl = TREE_CHAIN (decl))
{ {
vec[i] = decl;
/* Check for used but undefined static functions using the C /* Check for used but undefined static functions using the C
standard's definition of "used", and set TREE_NO_WARNING so standard's definition of "used", and set TREE_NO_WARNING so
that check_global_declarations doesn't repeat the check. */ that check_global_declarations doesn't repeat the check. */
...@@ -7566,18 +7564,32 @@ c_write_global_declarations_1 (tree globals) ...@@ -7566,18 +7564,32 @@ c_write_global_declarations_1 (tree globals)
pedwarn ("%q+F used but never defined", decl); pedwarn ("%q+F used but never defined", decl);
TREE_NO_WARNING (decl) = 1; TREE_NO_WARNING (decl) = 1;
} }
wrapup_global_declaration_1 (decl);
wrapup_global_declaration_2 (decl);
check_global_declaration_1 (decl);
} }
}
wrapup_global_declarations (vec, len); /* A subroutine of c_write_global_declarations Emit debug information for each
check_global_declarations (vec, len); of the declarations in GLOBALS. */
static void
c_write_global_declarations_2 (tree globals)
{
tree decl;
free (vec); for (decl = globals; decl ; decl = TREE_CHAIN (decl))
debug_hooks->global_decl (decl);
} }
/* Preserve the external declarations scope across a garbage collect. */
static GTY(()) tree ext_block;
void void
c_write_global_declarations (void) c_write_global_declarations (void)
{ {
tree ext_block, t; tree t;
/* We don't want to do this if generating a PCH. */ /* We don't want to do this if generating a PCH. */
if (pch_file) if (pch_file)
...@@ -7593,10 +7605,6 @@ c_write_global_declarations (void) ...@@ -7593,10 +7605,6 @@ c_write_global_declarations (void)
external_scope = 0; external_scope = 0;
gcc_assert (!current_scope); gcc_assert (!current_scope);
/* Process all file scopes in this compilation, and the external_scope,
through wrapup_global_declarations and check_global_declarations. */
for (t = all_translation_units; t; t = TREE_CHAIN (t))
c_write_global_declarations_1 (BLOCK_VARS (DECL_INITIAL (t)));
if (ext_block) if (ext_block)
{ {
tree tmp = BLOCK_VARS (ext_block); tree tmp = BLOCK_VARS (ext_block);
...@@ -7608,6 +7616,11 @@ c_write_global_declarations (void) ...@@ -7608,6 +7616,11 @@ c_write_global_declarations (void)
dump_end (TDI_tu, stream); dump_end (TDI_tu, stream);
} }
} }
/* Process all file scopes in this compilation, and the external_scope,
through wrapup_global_declarations and check_global_declarations. */
for (t = all_translation_units; t; t = TREE_CHAIN (t))
c_write_global_declarations_1 (BLOCK_VARS (DECL_INITIAL (t)));
c_write_global_declarations_1 (BLOCK_VARS (ext_block)); c_write_global_declarations_1 (BLOCK_VARS (ext_block));
/* Generate functions to call static constructors and destructors /* Generate functions to call static constructors and destructors
...@@ -7619,6 +7632,19 @@ c_write_global_declarations (void) ...@@ -7619,6 +7632,19 @@ c_write_global_declarations (void)
/* We're done parsing; proceed to optimize and emit assembly. /* We're done parsing; proceed to optimize and emit assembly.
FIXME: shouldn't be the front end's responsibility to call this. */ FIXME: shouldn't be the front end's responsibility to call this. */
cgraph_optimize (); cgraph_optimize ();
/* After cgraph has had a chance to emit everything that's going to
be emitted, output debug information for globals. */
if (errorcount == 0 && sorrycount == 0)
{
timevar_push (TV_SYMOUT);
for (t = all_translation_units; t; t = TREE_CHAIN (t))
c_write_global_declarations_2 (BLOCK_VARS (DECL_INITIAL (t)));
c_write_global_declarations_2 (BLOCK_VARS (ext_block));
timevar_pop (TV_SYMOUT);
}
ext_block = NULL;
} }
#include "gt-c-decl.h" #include "gt-c-decl.h"
...@@ -311,7 +311,13 @@ cgraph_varpool_remove_unreferenced_decls (void) ...@@ -311,7 +311,13 @@ cgraph_varpool_remove_unreferenced_decls (void)
&& ((DECL_ASSEMBLER_NAME_SET_P (decl) && ((DECL_ASSEMBLER_NAME_SET_P (decl)
&& TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))) && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
|| node->force_output || node->force_output
|| decide_is_variable_needed (node, decl))) || decide_is_variable_needed (node, decl)
/* ??? Cgraph does not yet rule the world with an iron hand,
and does not control the emission of debug information.
After a variable has its DECL_RTL set, we must assume that
it may be referenced by the debug information, and we can
no longer elide it. */
|| DECL_RTL_SET_P (decl)))
cgraph_varpool_mark_needed_node (node); cgraph_varpool_mark_needed_node (node);
node = next; node = next;
......
2005-09-08 Richard Henderson <rth@redhat.com>
PR debug/23190
* decl.c (wrapup_globals_for_namespace): Call
emit_debug_global_declarations.
* decl2.c (cp_finish_file): Likewise.
2005-09-08 Mark Mitchell <mark@codesourcery.com> 2005-09-08 Mark Mitchell <mark@codesourcery.com>
PR c++/23691 PR c++/23691
......
...@@ -789,6 +789,7 @@ wrapup_globals_for_namespace (tree namespace, void* data) ...@@ -789,6 +789,7 @@ wrapup_globals_for_namespace (tree namespace, void* data)
if (last_time) if (last_time)
{ {
check_global_declarations (vec, len); check_global_declarations (vec, len);
emit_debug_global_declarations (vec, len);
return 0; return 0;
} }
......
...@@ -3106,8 +3106,12 @@ cp_finish_file (void) ...@@ -3106,8 +3106,12 @@ cp_finish_file (void)
etc., and emit debugging information. */ etc., and emit debugging information. */
walk_namespaces (wrapup_globals_for_namespace, /*data=*/&reconsider); walk_namespaces (wrapup_globals_for_namespace, /*data=*/&reconsider);
if (VEC_length (tree, pending_statics) != 0) if (VEC_length (tree, pending_statics) != 0)
{
check_global_declarations (VEC_address (tree, pending_statics), check_global_declarations (VEC_address (tree, pending_statics),
VEC_length (tree, pending_statics)); VEC_length (tree, pending_statics));
emit_debug_global_declarations (VEC_address (tree, pending_statics),
VEC_length (tree, pending_statics));
}
/* Generate hidden aliases for Java. */ /* Generate hidden aliases for Java. */
build_java_method_aliases (); build_java_method_aliases ();
......
...@@ -478,8 +478,8 @@ write_global_declarations (void) ...@@ -478,8 +478,8 @@ write_global_declarations (void)
vec[len - i - 1] = decl; vec[len - i - 1] = decl;
wrapup_global_declarations (vec, len); wrapup_global_declarations (vec, len);
check_global_declarations (vec, len); check_global_declarations (vec, len);
emit_debug_global_declarations (vec, len);
/* Clean up. */ /* Clean up. */
free (vec); free (vec);
......
...@@ -158,8 +158,7 @@ rest_of_decl_compilation (tree decl, ...@@ -158,8 +158,7 @@ rest_of_decl_compilation (tree decl,
|| DECL_INITIAL (decl)) || DECL_INITIAL (decl))
&& !DECL_EXTERNAL (decl)) && !DECL_EXTERNAL (decl))
{ {
if (flag_unit_at_a_time && !cgraph_global_info_ready if (TREE_CODE (decl) != FUNCTION_DECL)
&& TREE_CODE (decl) != FUNCTION_DECL)
cgraph_varpool_finalize_decl (decl); cgraph_varpool_finalize_decl (decl);
else else
assemble_variable (decl, top_level, at_end, 0); assemble_variable (decl, top_level, at_end, 0);
......
/* PR 23190 */
/* Well, collateral damage from a proposed patch fixing 23190. We'd emit
debug info for multilib_exclusions_raw without emitting the variable
itself, leading to link errors. This reduced form is filed as PR 23777,
for not eliminating things soon enough. */
/* { dg-do link } */
static const char *const multilib_exclusions_raw[] = { 0 };
void __attribute__((noinline)) f(char *const *p)
{
__asm__ ("" : : "g"(p) : "memory");
}
void g (char **o)
{
const char *const *q = multilib_exclusions_raw;
f (o);
while (*q++)
f (o);
}
int main() { return 0; }
/* PR 23190 */
/* { dg-do compile }
/* { dg-options "-gdwarf-2 -dA" } */
/* { dg-final { scan-assembler "xyzzy\[^\\n\\r\]+DW_AT_name" } } */
void f(void)
{
static int xyzzy;
xyzzy += 3;
}
/* PR 23190 */
/* { dg-do compile }
/* { dg-options "-O2 -gdwarf-2 -dA" } */
/* { dg-final { scan-assembler "DW_OP_addr\[\\n\\r\]+\[^\\n\\r\]+foo" } } */
/* { dg-final { scan-assembler "DW_OP_addr\[\\n\\r\]+\[^\\n\\r\]+bar" } } */
static int foo;
int bar;
int main(void)
{
foo += 3;
bar *= 5;
return 0;
}
...@@ -685,45 +685,31 @@ output_file_directive (FILE *asm_file, const char *input_name) ...@@ -685,45 +685,31 @@ output_file_directive (FILE *asm_file, const char *input_name)
#endif #endif
} }
/* Do any final processing required for the declarations in VEC, of /* A subroutine of wrapup_global_declarations. We've come to the end of
which there are LEN. We write out inline functions and variables the compilation unit. All deferred variables should be undeferred,
that have been deferred until this point, but which are required. and all incomplete decls should be finalized. */
Returns nonzero if anything was put out. */
int void
wrapup_global_declarations (tree *vec, int len) wrapup_global_declaration_1 (tree decl)
{ {
tree decl; /* We're not deferring this any longer. Assignment is conditional to
int i; avoid needlessly dirtying PCH pages. */
int reconsider;
int output_something = 0;
for (i = 0; i < len; i++)
{
decl = vec[i];
/* We're not deferring this any longer. Assignment is
conditional to avoid needlessly dirtying PCH pages. */
if (CODE_CONTAINS_STRUCT (TREE_CODE (decl), TS_DECL_WITH_VIS) if (CODE_CONTAINS_STRUCT (TREE_CODE (decl), TS_DECL_WITH_VIS)
&& DECL_DEFER_OUTPUT (decl) != 0) && DECL_DEFER_OUTPUT (decl) != 0)
DECL_DEFER_OUTPUT (decl) = 0; DECL_DEFER_OUTPUT (decl) = 0;
if (TREE_CODE (decl) == VAR_DECL && DECL_SIZE (decl) == 0) if (TREE_CODE (decl) == VAR_DECL && DECL_SIZE (decl) == 0)
lang_hooks.finish_incomplete_decl (decl); lang_hooks.finish_incomplete_decl (decl);
} }
/* Now emit any global variables or functions that we have been /* A subroutine of wrapup_global_declarations. Decide whether or not DECL
putting off. We need to loop in case one of the things emitted needs to be output. Return true if it is output. */
here references another one which comes earlier in the list. */
do
{
reconsider = 0;
for (i = 0; i < len; i++)
{
decl = vec[i];
bool
wrapup_global_declaration_2 (tree decl)
{
if (TREE_ASM_WRITTEN (decl) || DECL_EXTERNAL (decl)) if (TREE_ASM_WRITTEN (decl) || DECL_EXTERNAL (decl))
continue; return false;
/* Don't write out static consts, unless we still need them. /* Don't write out static consts, unless we still need them.
...@@ -753,13 +739,13 @@ wrapup_global_declarations (tree *vec, int len) ...@@ -753,13 +739,13 @@ wrapup_global_declarations (tree *vec, int len)
if (TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl)) if (TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl))
{ {
struct cgraph_varpool_node *node; struct cgraph_varpool_node *node;
bool needed = 1; bool needed = true;
node = cgraph_varpool_node (decl); node = cgraph_varpool_node (decl);
if (node->finalized) if (node->finalized)
needed = 0; needed = false;
else if (node->alias) else if (node->alias)
needed = 0; needed = false;
else if (!cgraph_global_info_ready else if (!cgraph_global_info_ready
&& (TREE_USED (decl) && (TREE_USED (decl)
|| TREE_USED (DECL_ASSEMBLER_NAME (decl)))) || TREE_USED (DECL_ASSEMBLER_NAME (decl))))
...@@ -767,45 +753,60 @@ wrapup_global_declarations (tree *vec, int len) ...@@ -767,45 +753,60 @@ wrapup_global_declarations (tree *vec, int len)
else if (node->needed) else if (node->needed)
/* needed */; /* needed */;
else if (DECL_COMDAT (decl)) else if (DECL_COMDAT (decl))
needed = 0; needed = false;
else if (TREE_READONLY (decl) && !TREE_PUBLIC (decl) else if (TREE_READONLY (decl) && !TREE_PUBLIC (decl)
&& (optimize || !flag_keep_static_consts && (optimize || !flag_keep_static_consts
|| DECL_ARTIFICIAL (decl))) || DECL_ARTIFICIAL (decl)))
needed = 0; needed = false;
if (needed) if (needed)
{ {
reconsider = 1;
rest_of_decl_compilation (decl, 1, 1); rest_of_decl_compilation (decl, 1, 1);
return true;
} }
} }
}
return false;
}
/* Do any final processing required for the declarations in VEC, of
which there are LEN. We write out inline functions and variables
that have been deferred until this point, but which are required.
Returns nonzero if anything was put out. */
bool
wrapup_global_declarations (tree *vec, int len)
{
bool reconsider, output_something = false;
int i;
for (i = 0; i < len; i++)
wrapup_global_declaration_1 (vec[i]);
/* Now emit any global variables or functions that we have been
putting off. We need to loop in case one of the things emitted
here references another one which comes earlier in the list. */
do
{
reconsider = false;
for (i = 0; i < len; i++)
reconsider |= wrapup_global_declaration_2 (vec[i]);
if (reconsider) if (reconsider)
output_something = 1; output_something = true;
} }
while (reconsider); while (reconsider);
return output_something; return output_something;
} }
/* Issue appropriate warnings for the global declarations in VEC (of /* A subroutine of check_global_declarations. Issue appropriate warnings
which there are LEN). Output debugging information for them. */ for the global declaration DECL. */
void void
check_global_declarations (tree *vec, int len) check_global_declaration_1 (tree decl)
{ {
tree decl; /* Warn about any function declared static but not defined. We don't
int i; warn about variables, because many programs have static variables
for (i = 0; i < len; i++)
{
decl = vec[i];
/* Warn about any function
declared static but not defined.
We don't warn about variables,
because many programs have static variables
that exist only to get some text into the object file. */ that exist only to get some text into the object file. */
if (TREE_CODE (decl) == FUNCTION_DECL if (TREE_CODE (decl) == FUNCTION_DECL
&& DECL_INITIAL (decl) == 0 && DECL_INITIAL (decl) == 0
...@@ -819,8 +820,7 @@ check_global_declarations (tree *vec, int len) ...@@ -819,8 +820,7 @@ check_global_declarations (tree *vec, int len)
if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))) if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
pedwarn ("%q+F used but never defined", decl); pedwarn ("%q+F used but never defined", decl);
else else
warning (0, "%q+F declared %<static%> but never defined", warning (0, "%q+F declared %<static%> but never defined", decl);
decl);
/* This symbol is effectively an "extern" declaration now. */ /* This symbol is effectively an "extern" declaration now. */
TREE_PUBLIC (decl) = 1; TREE_PUBLIC (decl) = 1;
assemble_external (decl); assemble_external (decl);
...@@ -846,16 +846,35 @@ check_global_declarations (tree *vec, int len) ...@@ -846,16 +846,35 @@ check_global_declarations (tree *vec, int len)
/* Otherwise, ask the language. */ /* Otherwise, ask the language. */
&& lang_hooks.decls.warn_unused_global (decl)) && lang_hooks.decls.warn_unused_global (decl))
warning (0, "%q+D defined but not used", decl); warning (0, "%q+D defined but not used", decl);
}
/* Issue appropriate warnings for the global declarations in VEC (of
which there are LEN). */
void
check_global_declarations (tree *vec, int len)
{
int i;
for (i = 0; i < len; i++)
check_global_declaration_1 (vec[i]);
}
/* Emit debugging information for all global declarations in VEC. */
void
emit_debug_global_declarations (tree *vec, int len)
{
int i;
/* Avoid confusing the debug information machinery when there are errors. */
if (errorcount != 0 || sorrycount != 0)
return;
/* Avoid confusing the debug information machinery when there are
errors. */
if (errorcount == 0 && sorrycount == 0)
{
timevar_push (TV_SYMOUT); timevar_push (TV_SYMOUT);
(*debug_hooks->global_decl) (decl); for (i = 0; i < len; i++)
debug_hooks->global_decl (vec[i]);
timevar_pop (TV_SYMOUT); timevar_pop (TV_SYMOUT);
}
}
} }
/* Warn about a use of an identifier which was marked deprecated. */ /* Warn about a use of an identifier which was marked deprecated. */
......
...@@ -92,8 +92,12 @@ extern void fnotice (FILE *, const char *, ...) ...@@ -92,8 +92,12 @@ extern void fnotice (FILE *, const char *, ...)
ATTRIBUTE_PRINTF_2; ATTRIBUTE_PRINTF_2;
#endif #endif
extern int wrapup_global_declarations (tree *, int); extern void wrapup_global_declaration_1 (tree);
extern bool wrapup_global_declaration_2 (tree);
extern bool wrapup_global_declarations (tree *, int);
extern void check_global_declaration_1 (tree);
extern void check_global_declarations (tree *, int); extern void check_global_declarations (tree *, int);
extern void emit_debug_global_declarations (tree *, int);
extern void write_global_declarations (void); extern void write_global_declarations (void);
/* A unique local time stamp, might be zero if none is available. */ /* A unique local time stamp, might be zero if none is available. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment