aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Hubicka <hubicka@ucw.cz>2014-09-20 01:56:52 +0200
committerJan Hubicka <hubicka@gcc.gnu.org>2014-09-19 23:56:52 +0000
commitf7217cde7f382aeb19dd3e80bc8f7ffae798315f (patch)
treed7d5f6d00208bddb323b80ac27eed3ded29bed4a
parent3f99b0612f7db76b6ed1a25ecce8fa327eec9f61 (diff)
downloadgcc-f7217cde7f382aeb19dd3e80bc8f7ffae798315f.zip
gcc-f7217cde7f382aeb19dd3e80bc8f7ffae798315f.tar.gz
gcc-f7217cde7f382aeb19dd3e80bc8f7ffae798315f.tar.bz2
re PR c++/61825 (g++.dg/cpp0x/static_assert9.C FAILs)
PR c++/61825 * c-family/c-common.c (handle_alias_ifunc_attribute): Check that visibility change is possible (handle_weakref_attribute): Likewise. * cgraph.h (symtab_node): Add method get_create and field refuse_visibility_changes. (symtab_node::get_create): New method. * fold-const.c (tree_single_nonzero_warnv_p): Use get_create. * varasm.c (mark_weak): Verify that visibility change is possible. * gcc.dg/tree-ssa/nonzero-1.c: Require error to be output. From-SVN: r215409
-rw-r--r--gcc/ChangeLog13
-rw-r--r--gcc/c-family/c-common.c20
-rw-r--r--gcc/cgraph.h16
-rw-r--r--gcc/fold-const.c2
-rw-r--r--gcc/symtab.c30
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/nonzero-1.c7
-rw-r--r--gcc/varasm.c6
8 files changed, 80 insertions, 19 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 04db32a..c345dc1 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,16 @@
+2014-09-19 Jan Hubicka <hubicka@ucw.cz>
+
+ PR c++/61825
+ * c-family/c-common.c (handle_alias_ifunc_attribute): Check
+ that visibility change is possible
+ (handle_weakref_attribute): Likewise.
+ * cgraph.h (symtab_node): Add method get_create and
+ field refuse_visibility_changes.
+ (symtab_node::get_create): New method.
+ * fold-const.c (tree_single_nonzero_warnv_p): Use get_create.
+ * varasm.c (mark_weak): Verify that visibility change is
+ possible.
+
2014-09-19 Michael Meissner <meissner@linux.vnet.ibm.com>
* config/rs6000/predicates.md (fusion_gpr_mem_load): Move testing
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 39be956..818c32d 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -7757,6 +7757,19 @@ handle_alias_ifunc_attribute (bool is_alias, tree *node, tree name, tree args,
*no_add_attrs = true;
}
+ if (decl_in_symtab_p (*node))
+ {
+ struct symtab_node *n = symtab_node::get (decl);
+ if (n && n->refuse_visibility_changes)
+ {
+ if (is_alias)
+ error ("%+D declared alias after being used", decl);
+ else
+ error ("%+D declared ifunc after being used", decl);
+ }
+ }
+
+
return NULL_TREE;
}
@@ -7833,6 +7846,13 @@ handle_weakref_attribute (tree *node, tree ARG_UNUSED (name), tree args,
DECL_WEAK (*node) = 1;
}
+ if (decl_in_symtab_p (*node))
+ {
+ struct symtab_node *n = symtab_node::get (*node);
+ if (n && n->refuse_visibility_changes)
+ error ("%+D declared weakref after being used", *node);
+ }
+
return NULL_TREE;
}
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index 030a1c7..a316e40 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -346,6 +346,10 @@ public:
return decl->decl_with_vis.symtab_node;
}
+ /* Try to find a symtab node for declaration DECL and if it does not
+ exist or if it corresponds to an inline clone, create a new one. */
+ static inline symtab_node * get_create (tree node);
+
/* Return the cgraph node that has ASMNAME for its DECL_ASSEMBLER_NAME.
Return NULL if there's no such node. */
static symtab_node *get_for_asmname (const_tree asmname);
@@ -394,7 +398,9 @@ public:
unsigned analyzed : 1;
/* Set for write-only variables. */
unsigned writeonly : 1;
-
+ /* Visibility of symbol was used for further optimization; do not
+ permit further changes. */
+ unsigned refuse_visibility_changes : 1;
/*** Visibility and linkage flags. ***/
@@ -2519,4 +2525,12 @@ cgraph_node::mark_force_output (void)
gcc_checking_assert (!global.inlined_to);
}
+inline symtab_node * symtab_node::get_create (tree node)
+{
+ if (TREE_CODE (node) == VAR_DECL)
+ return varpool_node::get_create (node);
+ else
+ return cgraph_node::get_create (node);
+}
+
#endif /* GCC_CGRAPH_H */
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index f7bf525..5cfc646 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -15850,7 +15850,7 @@ tree_single_nonzero_warnv_p (tree t, bool *strict_overflow_p)
{
struct symtab_node *symbol;
- symbol = symtab_node::get (base);
+ symbol = symtab_node::get_create (base);
if (symbol)
return symbol->nonzero_address ();
else
diff --git a/gcc/symtab.c b/gcc/symtab.c
index 792b3b5..9590fc8 100644
--- a/gcc/symtab.c
+++ b/gcc/symtab.c
@@ -1811,9 +1811,9 @@ bool
symtab_node::nonzero_address ()
{
/* Weakrefs may be NULL when their target is not defined. */
- if (this->alias && this->weakref)
+ if (alias && weakref)
{
- if (this->analyzed)
+ if (analyzed)
{
symtab_node *target = ultimate_alias_target ();
@@ -1828,7 +1828,7 @@ symtab_node::nonzero_address ()
could be useful to eliminate the NULL pointer checks in LTO
programs. */
if (target->definition && !DECL_EXTERNAL (target->decl))
- return true;
+ return true;
if (target->resolution != LDPR_UNKNOWN
&& target->resolution != LDPR_UNDEF
&& flag_delete_null_pointer_checks)
@@ -1847,22 +1847,28 @@ symtab_node::nonzero_address ()
Those are handled by later check for definition.
When parsing, beware the cases when WEAK attribute is added later. */
- if (!DECL_WEAK (this->decl)
- && flag_delete_null_pointer_checks
- && symtab->state > PARSING)
- return true;
+ if (!DECL_WEAK (decl)
+ && flag_delete_null_pointer_checks)
+ {
+ refuse_visibility_changes = true;
+ return true;
+ }
/* If target is defined and not extern, we know it will be output and thus
it will bind to non-NULL.
Play safe for flag_delete_null_pointer_checks where weak definition maye
be re-defined by NULL. */
- if (this->definition && !DECL_EXTERNAL (this->decl)
- && (flag_delete_null_pointer_checks || !DECL_WEAK (this->decl)))
- return true;
+ if (definition && !DECL_EXTERNAL (decl)
+ && (flag_delete_null_pointer_checks || !DECL_WEAK (decl)))
+ {
+ if (!DECL_WEAK (decl))
+ refuse_visibility_changes = true;
+ return true;
+ }
/* As the last resort, check the resolution info. */
- if (this->resolution != LDPR_UNKNOWN
- && this->resolution != LDPR_UNDEF
+ if (resolution != LDPR_UNKNOWN
+ && resolution != LDPR_UNDEF
&& flag_delete_null_pointer_checks)
return true;
return false;
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 89c88eb..130c6a7 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2014-09-19 Jan Hubicka <hubicka@ucw.cz>
+
+ PR c++/61825
+ * gcc.dg/tree-ssa/nonzero-1.c: Require error to be output.
+
2014-09-19 Andi Kleen <ak@linux.intel.com>
* gcc.dg/pg-override.c: Only run on x86 Linux.
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/nonzero-1.c b/gcc/testsuite/gcc.dg/tree-ssa/nonzero-1.c
index c79811b..52e4a9a 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/nonzero-1.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/nonzero-1.c
@@ -1,11 +1,8 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-optimized" } */
-extern int a;
+/* { dg-options "-O2" } */
+extern int a; /* { dg-error "declared weak after being used" } */
t()
{
return &a!=0;
}
extern int a __attribute__ ((weak));
-
-/* { dg-final { scan-tree-dump-not "return 1" "optimized"} } */
-/* { dg-final { cleanup-tree-dump "optimized" } } */
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 111c657..dd3211a 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -5230,6 +5230,12 @@ output_constructor (tree exp, unsigned HOST_WIDE_INT size,
static void
mark_weak (tree decl)
{
+ if (DECL_WEAK (decl))
+ return;
+
+ struct symtab_node *n = symtab_node::get (decl);
+ if (n && n->refuse_visibility_changes)
+ error ("%+D declared weak after being used", decl);
DECL_WEAK (decl) = 1;
if (DECL_RTL_SET_P (decl)