This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug c++/27369] [4.1/4.2 Regression] tree check ICE when attribute externally_visible used
- From: "hubicka at ucw dot cz" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: 21 Jul 2006 15:13:18 -0000
- Subject: [Bug c++/27369] [4.1/4.2 Regression] tree check ICE when attribute externally_visible used
- References: <bug-27369-8960@http.gcc.gnu.org/bugzilla/>
- Reply-to: gcc-bugzilla at gcc dot gnu dot org
------- Comment #13 from hubicka at ucw dot cz 2006-07-21 15:13 -------
Subject: Re: [4.1/4.2 Regression] tree check ICE when attribute
externally_visible used
>
>
> ------- Comment #12 from mmitchel at gcc dot gnu dot org 2006-07-21 08:38 -------
> I think that Comment #10 shows that handle_externally_visible should not be
> registering things with cgraph, as we shouldn't ever have anything pointing at
> a re-declaration.
Hi,
in January I made patch for similar problem that simply deffers handling
of externally visible and used attributes after compilation unit is
finalized. I am going to update it for current tree and re-test. Does
it look safe?
Hi,
at the present externally_visible on:
extern const char *mystr; /* normally in a header */
const char *mystr __attribute__ ((externally_visible));
int
main (int argc, char **argv)
{
mystr = argv[0];
return (0);
}
is cowardly ignored. This is because handle_externally_visible_attribute is
called before decl merging and it produce new cgraph node with
externally_visible flag that is never merged to real decl node.
externally_visible is in many ways symmetric to used attribute, so I looked on
how it is implemented, but found it somewhat sliperly to copy.
Used attribute is processed on cgraph_finalize_* machinery first, but since
it might be added retrospectivly, it is also processed by c frontend when
merging decls
and finally it sets TREE_SYMBOL_REFERENCED flag that survive decl merging to
get the early used attributes right. This is way too crazy and easy to break,
so I moved both attributes to new place - at the end of compilation the
declarations
are travelled and we check whether the attributes are present.
Since this is miscompilation bug, I would like to see it solved in 4.1 too.
I wonder whether this scheme seems safe to others or if I should make less
intrusive approach? (perhaps moving externally_visible only)
Bootstrapped/regtested i686-pc-gnu-linux, OK for mainline and possibly 4.1?
2006-01-19 Jan Hubicka <jh@suse.cz>
* craph.c (cgraph_varpool_nodes): Export.
(decide_is_variable_needed): Do not worry about "used" attribute.
* cgraph.h (cgraph_varpool_nodes): Declare.
* cgraphunit.c (decide_is_function_needed): Do not worry about "used"
attribute
(process_function_and_variable_attributes): New function.
(cgraph_finalize_compilation_unit): Call it.
* c-decl.c (finish_decl): Do not worry about used attribute.
* c-common.c (handle_externally_visible_attribute): Only validate.
Index: cgraph.c
===================================================================
*** cgraph.c (revision 109820)
--- cgraph.c (working copy)
*************** static GTY((param_is (struct cgraph_varp
*** 132,138 ****
struct cgraph_varpool_node *cgraph_varpool_nodes_queue,
*cgraph_varpool_first_unanalyzed_node;
/* The linked list of cgraph varpool nodes. */
! static GTY(()) struct cgraph_varpool_node *cgraph_varpool_nodes;
/* End of the varpool queue. Needs to be QTYed to work with PCH. */
static GTY(()) struct cgraph_varpool_node *cgraph_varpool_last_needed_node;
--- 132,138 ----
struct cgraph_varpool_node *cgraph_varpool_nodes_queue,
*cgraph_varpool_first_unanalyzed_node;
/* The linked list of cgraph varpool nodes. */
! struct cgraph_varpool_node *cgraph_varpool_nodes;
/* End of the varpool queue. Needs to be QTYed to work with PCH. */
static GTY(()) struct cgraph_varpool_node *cgraph_varpool_last_needed_node;
*************** bool
*** 838,845 ****
decide_is_variable_needed (struct cgraph_varpool_node *node, tree decl)
{
/* If the user told us it is used, then it must be so. */
! if (node->externally_visible
! || lookup_attribute ("used", DECL_ATTRIBUTES (decl)))
return true;
/* ??? If the assembler name is set by hand, it is possible to assemble
--- 838,844 ----
decide_is_variable_needed (struct cgraph_varpool_node *node, tree decl)
{
/* If the user told us it is used, then it must be so. */
! if (node->externally_visible)
return true;
/* ??? If the assembler name is set by hand, it is possible to assemble
Index: cgraph.h
===================================================================
*** cgraph.h (revision 109820)
--- cgraph.h (working copy)
*************** extern GTY(()) struct cgraph_node *cgrap
*** 242,247 ****
--- 242,248 ----
extern GTY(()) struct cgraph_varpool_node
*cgraph_varpool_first_unanalyzed_node;
extern GTY(()) struct cgraph_varpool_node *cgraph_varpool_nodes_queue;
+ extern GTY(()) struct cgraph_varpool_node *cgraph_varpool_nodes;
extern GTY(()) struct cgraph_asm_node *cgraph_asm_nodes;
extern GTY(()) int cgraph_order;
Index: cgraphunit.c
===================================================================
*** cgraphunit.c (revision 109820)
--- cgraphunit.c (working copy)
*************** decide_is_function_needed (struct cgraph
*** 198,205 ****
}
/* If the user told us it is used, then it must be so. */
! if (node->local.externally_visible
! || lookup_attribute ("used", DECL_ATTRIBUTES (decl)))
return true;
/* ??? If the assembler name is set by hand, it is possible to assemble
--- 198,204 ----
}
/* If the user told us it is used, then it must be so. */
! if (node->local.externally_visible)
return true;
/* ??? If the assembler name is set by hand, it is possible to assemble
*************** cgraph_analyze_function (struct cgraph_n
*** 906,911 ****
--- 905,950 ----
current_function_decl = NULL;
}
+ /* Look for externally_visible and used attributes and mark cgraph nodes
+ accordingly.
+
+ This is not easilly doable earlier in handle_*_attribute because they
might
+ be passed different copy of decl before merging. We can't do that in
+ cgraph_finalize_function either because we want to allow defining the
attributes
+ later, so we do that in separate pass at the end of unit. */
+
+ static void
+ process_function_and_variable_attributes (void)
+ {
+ struct cgraph_node *node;
+ struct cgraph_varpool_node *vnode;
+
+ for (node = cgraph_nodes; node; node = node->next)
+ {
+ tree decl = node->decl;
+ if (lookup_attribute ("used", DECL_ATTRIBUTES (decl)))
+ mark_decl_referenced (decl);
+ if (lookup_attribute ("externally_visible", DECL_ATTRIBUTES (decl)))
+ {
+ if (node->local.finalized)
+ cgraph_mark_needed_node (node);
+ node->externally_visible = true;
+ }
+ }
+ for (vnode = cgraph_varpool_nodes; vnode; vnode = vnode->next)
+ {
+ tree decl = vnode->decl;
+ if (lookup_attribute ("used", DECL_ATTRIBUTES (decl)))
+ mark_decl_referenced (decl);
+ if (lookup_attribute ("externally_visible", DECL_ATTRIBUTES (decl)))
+ {
+ if (vnode->finalized)
+ cgraph_varpool_mark_needed_node (vnode);
+ vnode->externally_visible = true;
+ }
+ }
+ }
+
/* Analyze the whole compilation unit once it is parsed completely. */
void
*************** cgraph_finalize_compilation_unit (void)
*** 916,925 ****
--- 955,965 ----
intermodule optimization. */
static struct cgraph_node *first_analyzed;
+ process_function_and_variable_attributes ();
finish_aliases_1 ();
if (!flag_unit_at_a_time)
{
cgraph_output_pending_asms ();
cgraph_assemble_pending_functions ();
return;
Index: c-decl.c
===================================================================
*** c-decl.c (revision 109820)
--- c-decl.c (working copy)
*************** finish_decl (tree decl, tree init, tree
*** 3498,3507 ****
}
}
- /* If this was marked 'used', be sure it will be output. */
- if (lookup_attribute ("used", DECL_ATTRIBUTES (decl)))
- mark_decl_referenced (decl);
-
if (TREE_CODE (decl) == TYPE_DECL)
{
if (!DECL_FILE_SCOPE_P (decl)
--- 3498,3503 ----
Index: c-common.c
===================================================================
*** c-common.c (revision 109820)
--- c-common.c (working copy)
*************** handle_externally_visible_attribute (tre
*** 4274,4293 ****
"%qE attribute have effect only on public objects", name);
*no_add_attrs = true;
}
! else if (TREE_CODE (node) == FUNCTION_DECL)
! {
! struct cgraph_node *n = cgraph_node (node);
! n->local.externally_visible = true;
! if (n->local.finalized)
! cgraph_mark_needed_node (n);
! }
! else if (TREE_CODE (node) == VAR_DECL)
! {
! struct cgraph_varpool_node *n = cgraph_varpool_node (node);
! n->externally_visible = true;
! if (n->finalized)
! cgraph_varpool_mark_needed_node (n);
! }
else
{
warning (OPT_Wattributes, "%qE attribute ignored", name);
--- 4274,4282 ----
"%qE attribute have effect only on public objects", name);
*no_add_attrs = true;
}
! else if (TREE_CODE (node) == FUNCTION_DECL
! || TREE_CODE (node) == VAR_DECL)
! ;
else
{
warning (OPT_Wattributes, "%qE attribute ignored", name);
--
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=27369