Commit 6a6dac52 by Jan Hubicka Committed by Jan Hubicka

cgraph.h (const_value_known_p): Replace by ...


	* cgraph.h (const_value_known_p): Replace by ...
	(ctor_for_folding): .. this one.
	* cgraphunit.c (process_function_and_variable_attributes): Use it.
	* lto-cgraph.c (compute_ltrans_boundary): Use ctor_for_folding.
	* expr.c (expand_expr_real_1): Likewise.
	(string_constant): Likewise.
	* tree-ssa-loop-ivcanon.c (constant_after_peeling): Likewise.
	* ipa.c (process_references): Likewise.
	(symtab_remove_unreachable_nodes): Likewise.
	* ipa-inline-analysis.c (param_change_prob): Likewise.
	* gimple-fold.c (canonicalize_constructor_val): Likewise.
	(get_base_constructor): Likwise.
	* varpool.c (varpool_remove_node): Likewise.
	(varpool_remove_initializer): LIkewise.
	(dump_varpool_node): LIkwise.
	(const_value_known_p): Rewrite to ...
	(ctor_for_folding): ... this one.

	* lto-partition.c (add_references_to_partition): Use
	ctor_for_folding.

	* gcc.dg/tree-ssa/attr-alias-2.c: New testcase.

From-SVN: r200211
parent 216c12ab
2013-06-19 Jan Hubicka <jh@suse.cz>
* cgraph.h (const_value_known_p): Replace by ...
(ctor_for_folding): .. this one.
* cgraphunit.c (process_function_and_variable_attributes): Use it.
* lto-cgraph.c (compute_ltrans_boundary): Use ctor_for_folding.
* expr.c (expand_expr_real_1): Likewise.
(string_constant): Likewise.
* tree-ssa-loop-ivcanon.c (constant_after_peeling): Likewise.
* ipa.c (process_references): Likewise.
(symtab_remove_unreachable_nodes): Likewise.
* ipa-inline-analysis.c (param_change_prob): Likewise.
* gimple-fold.c (canonicalize_constructor_val): Likewise.
(get_base_constructor): Likwise.
* varpool.c (varpool_remove_node): Likewise.
(varpool_remove_initializer): LIkewise.
(dump_varpool_node): LIkwise.
(const_value_known_p): Rewrite to ...
(ctor_for_folding): ... this one.
2013-06-19 Jakub Jelinek <jakub@redhat.com> 2013-06-19 Jakub Jelinek <jakub@redhat.com>
PR driver/57651 PR driver/57651
......
...@@ -797,7 +797,7 @@ void varpool_analyze_node (struct varpool_node *); ...@@ -797,7 +797,7 @@ void varpool_analyze_node (struct varpool_node *);
struct varpool_node * varpool_extra_name_alias (tree, tree); struct varpool_node * varpool_extra_name_alias (tree, tree);
struct varpool_node * varpool_create_variable_alias (tree, tree); struct varpool_node * varpool_create_variable_alias (tree, tree);
void varpool_reset_queue (void); void varpool_reset_queue (void);
bool const_value_known_p (tree); tree ctor_for_folding (tree);
bool varpool_for_node_and_aliases (struct varpool_node *, bool varpool_for_node_and_aliases (struct varpool_node *,
bool (*) (struct varpool_node *, void *), bool (*) (struct varpool_node *, void *),
void *, bool); void *, bool);
......
...@@ -762,8 +762,7 @@ process_function_and_variable_attributes (struct cgraph_node *first, ...@@ -762,8 +762,7 @@ process_function_and_variable_attributes (struct cgraph_node *first,
{ {
tree decl = vnode->symbol.decl; tree decl = vnode->symbol.decl;
if (DECL_EXTERNAL (decl) if (DECL_EXTERNAL (decl)
&& DECL_INITIAL (decl) && DECL_INITIAL (decl))
&& const_value_known_p (decl))
varpool_finalize_decl (decl); varpool_finalize_decl (decl);
if (DECL_PRESERVE_P (decl)) if (DECL_PRESERVE_P (decl))
vnode->symbol.force_output = true; vnode->symbol.force_output = true;
......
...@@ -9698,6 +9698,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, ...@@ -9698,6 +9698,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
{ {
tree array = treeop0; tree array = treeop0;
tree index = treeop1; tree index = treeop1;
tree init;
/* Fold an expression like: "foo"[2]. /* Fold an expression like: "foo"[2].
This is not done in fold so it won't happen inside &. This is not done in fold so it won't happen inside &.
...@@ -9744,76 +9745,72 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, ...@@ -9744,76 +9745,72 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
&& modifier != EXPAND_INITIALIZER && modifier != EXPAND_INITIALIZER
&& modifier != EXPAND_MEMORY && modifier != EXPAND_MEMORY
&& TREE_READONLY (array) && ! TREE_SIDE_EFFECTS (array) && TREE_READONLY (array) && ! TREE_SIDE_EFFECTS (array)
&& TREE_CODE (array) == VAR_DECL && DECL_INITIAL (array) && TREE_CODE (index) == INTEGER_CST
&& TREE_CODE (DECL_INITIAL (array)) != ERROR_MARK && (TREE_CODE (array) == VAR_DECL
&& const_value_known_p (array)) || TREE_CODE (array) == CONST_DECL)
&& (init = ctor_for_folding (array)) != error_mark_node)
{ {
if (TREE_CODE (index) == INTEGER_CST) if (TREE_CODE (init) == CONSTRUCTOR)
{ {
tree init = DECL_INITIAL (array); unsigned HOST_WIDE_INT ix;
tree field, value;
if (TREE_CODE (init) == CONSTRUCTOR) FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (init), ix,
{ field, value)
unsigned HOST_WIDE_INT ix; if (tree_int_cst_equal (field, index))
tree field, value; {
if (TREE_SIDE_EFFECTS (value))
break;
FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (init), ix, if (TREE_CODE (value) == CONSTRUCTOR)
field, value)
if (tree_int_cst_equal (field, index))
{ {
if (TREE_SIDE_EFFECTS (value)) /* If VALUE is a CONSTRUCTOR, this
optimization is only useful if
this doesn't store the CONSTRUCTOR
into memory. If it does, it is more
efficient to just load the data from
the array directly. */
rtx ret = expand_constructor (value, target,
modifier, true);
if (ret == NULL_RTX)
break; break;
if (TREE_CODE (value) == CONSTRUCTOR)
{
/* If VALUE is a CONSTRUCTOR, this
optimization is only useful if
this doesn't store the CONSTRUCTOR
into memory. If it does, it is more
efficient to just load the data from
the array directly. */
rtx ret = expand_constructor (value, target,
modifier, true);
if (ret == NULL_RTX)
break;
}
return expand_expr (fold (value), target, tmode,
modifier);
} }
}
else if(TREE_CODE (init) == STRING_CST) return expand_expr (fold (value), target, tmode,
modifier);
}
}
else if(TREE_CODE (init) == STRING_CST)
{
tree index1 = index;
tree low_bound = array_ref_low_bound (exp);
index1 = fold_convert_loc (loc, sizetype,
treeop1);
/* Optimize the special-case of a zero lower bound.
We convert the low_bound to sizetype to avoid some problems
with constant folding. (E.g. suppose the lower bound is 1,
and its mode is QI. Without the conversion,l (ARRAY
+(INDEX-(unsigned char)1)) becomes ((ARRAY+(-(unsigned char)1))
+INDEX), which becomes (ARRAY+255+INDEX). Opps!) */
if (! integer_zerop (low_bound))
index1 = size_diffop_loc (loc, index1,
fold_convert_loc (loc, sizetype,
low_bound));
if (0 > compare_tree_int (index1,
TREE_STRING_LENGTH (init)))
{ {
tree index1 = index; tree type = TREE_TYPE (TREE_TYPE (init));
tree low_bound = array_ref_low_bound (exp); enum machine_mode mode = TYPE_MODE (type);
index1 = fold_convert_loc (loc, sizetype,
treeop1); if (GET_MODE_CLASS (mode) == MODE_INT
&& GET_MODE_SIZE (mode) == 1)
/* Optimize the special-case of a zero lower bound. return gen_int_mode (TREE_STRING_POINTER (init)
[TREE_INT_CST_LOW (index1)],
We convert the low_bound to sizetype to avoid some problems mode);
with constant folding. (E.g. suppose the lower bound is 1,
and its mode is QI. Without the conversion,l (ARRAY
+(INDEX-(unsigned char)1)) becomes ((ARRAY+(-(unsigned char)1))
+INDEX), which becomes (ARRAY+255+INDEX). Opps!) */
if (! integer_zerop (low_bound))
index1 = size_diffop_loc (loc, index1,
fold_convert_loc (loc, sizetype,
low_bound));
if (0 > compare_tree_int (index1,
TREE_STRING_LENGTH (init)))
{
tree type = TREE_TYPE (TREE_TYPE (init));
enum machine_mode mode = TYPE_MODE (type);
if (GET_MODE_CLASS (mode) == MODE_INT
&& GET_MODE_SIZE (mode) == 1)
return gen_int_mode (TREE_STRING_POINTER (init)
[TREE_INT_CST_LOW (index1)],
mode);
}
} }
} }
} }
...@@ -10676,17 +10673,18 @@ string_constant (tree arg, tree *ptr_offset) ...@@ -10676,17 +10673,18 @@ string_constant (tree arg, tree *ptr_offset)
|| TREE_CODE (array) == CONST_DECL) || TREE_CODE (array) == CONST_DECL)
{ {
int length; int length;
tree init = ctor_for_folding (array);
/* Variables initialized to string literals can be handled too. */ /* Variables initialized to string literals can be handled too. */
if (!const_value_known_p (array) if (init == error_mark_node
|| !DECL_INITIAL (array) || !init
|| TREE_CODE (DECL_INITIAL (array)) != STRING_CST) || TREE_CODE (init) != STRING_CST)
return 0; return 0;
/* Avoid const char foo[4] = "abcde"; */ /* Avoid const char foo[4] = "abcde"; */
if (DECL_SIZE_UNIT (array) == NULL_TREE if (DECL_SIZE_UNIT (array) == NULL_TREE
|| TREE_CODE (DECL_SIZE_UNIT (array)) != INTEGER_CST || TREE_CODE (DECL_SIZE_UNIT (array)) != INTEGER_CST
|| (length = TREE_STRING_LENGTH (DECL_INITIAL (array))) <= 0 || (length = TREE_STRING_LENGTH (init)) <= 0
|| compare_tree_int (DECL_SIZE_UNIT (array), length) < 0) || compare_tree_int (DECL_SIZE_UNIT (array), length) < 0)
return 0; return 0;
...@@ -10699,7 +10697,7 @@ string_constant (tree arg, tree *ptr_offset) ...@@ -10699,7 +10697,7 @@ string_constant (tree arg, tree *ptr_offset)
return 0; return 0;
*ptr_offset = offset; *ptr_offset = offset;
return DECL_INITIAL (array); return init;
} }
return 0; return 0;
......
...@@ -192,9 +192,9 @@ canonicalize_constructor_val (tree cval, tree from_decl) ...@@ -192,9 +192,9 @@ canonicalize_constructor_val (tree cval, tree from_decl)
tree tree
get_symbol_constant_value (tree sym) get_symbol_constant_value (tree sym)
{ {
if (const_value_known_p (sym)) tree val = ctor_for_folding (sym);
if (val != error_mark_node)
{ {
tree val = DECL_INITIAL (sym);
if (val) if (val)
{ {
val = canonicalize_constructor_val (unshare_expr (val), sym); val = canonicalize_constructor_val (unshare_expr (val), sym);
...@@ -2695,19 +2695,18 @@ get_base_constructor (tree base, HOST_WIDE_INT *bit_offset, ...@@ -2695,19 +2695,18 @@ get_base_constructor (tree base, HOST_WIDE_INT *bit_offset,
switch (TREE_CODE (base)) switch (TREE_CODE (base))
{ {
case VAR_DECL: case VAR_DECL:
if (!const_value_known_p (base))
return NULL_TREE;
/* Fallthru. */
case CONST_DECL: case CONST_DECL:
if (!DECL_INITIAL (base) {
&& (TREE_STATIC (base) || DECL_EXTERNAL (base))) tree init = ctor_for_folding (base);
return error_mark_node;
/* Do not return an error_mark_node DECL_INITIAL. LTO uses this /* Our semantic is exact oposite of ctor_for_folding;
as special marker (_not_ zero ...) for its own purposes. */ NULL means unknown, while error_mark_node is 0. */
if (DECL_INITIAL (base) == error_mark_node) if (init == error_mark_node)
return NULL_TREE; return NULL_TREE;
return DECL_INITIAL (base); if (!init)
return error_mark_node;
return init;
}
case ARRAY_REF: case ARRAY_REF:
case COMPONENT_REF: case COMPONENT_REF:
......
...@@ -2106,8 +2106,9 @@ param_change_prob (gimple stmt, int i) ...@@ -2106,8 +2106,9 @@ param_change_prob (gimple stmt, int i)
struct record_modified_bb_info info; struct record_modified_bb_info info;
bitmap_iterator bi; bitmap_iterator bi;
unsigned index; unsigned index;
tree init = ctor_for_folding (base);
if (const_value_known_p (base)) if (init != error_mark_node)
return 0; return 0;
if (!bb->frequency) if (!bb->frequency)
return REG_BR_PROB_BASE; return REG_BR_PROB_BASE;
......
...@@ -145,7 +145,9 @@ process_references (struct ipa_ref_list *list, ...@@ -145,7 +145,9 @@ process_references (struct ipa_ref_list *list,
constant folding. Keep references alive so partitioning constant folding. Keep references alive so partitioning
knows about potential references. */ knows about potential references. */
|| (TREE_CODE (node->symbol.decl) == VAR_DECL || (TREE_CODE (node->symbol.decl) == VAR_DECL
&& flag_wpa && const_value_known_p (node->symbol.decl))))) && flag_wpa
&& ctor_for_folding (node->symbol.decl)
!= error_mark_node))))
pointer_set_insert (reachable, node); pointer_set_insert (reachable, node);
enqueue_node ((symtab_node) node, first, reachable); enqueue_node ((symtab_node) node, first, reachable);
} }
...@@ -400,6 +402,7 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file) ...@@ -400,6 +402,7 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
} }
else if (!pointer_set_contains (reachable, vnode)) else if (!pointer_set_contains (reachable, vnode))
{ {
tree init;
if (vnode->symbol.definition) if (vnode->symbol.definition)
{ {
if (file) if (file)
...@@ -411,8 +414,10 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file) ...@@ -411,8 +414,10 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
vnode->symbol.aux = NULL; vnode->symbol.aux = NULL;
/* Keep body if it may be useful for constant folding. */ /* Keep body if it may be useful for constant folding. */
if (!const_value_known_p (vnode->symbol.decl)) if ((init = ctor_for_folding (vnode->symbol.decl)) == error_mark_node)
varpool_remove_initializer (vnode); varpool_remove_initializer (vnode);
else
DECL_INITIAL (vnode->symbol.decl) = init;
ipa_remove_all_references (&vnode->symbol.ref_list); ipa_remove_all_references (&vnode->symbol.ref_list);
} }
else else
......
...@@ -766,10 +766,9 @@ compute_ltrans_boundary (lto_symtab_encoder_t in_encoder) ...@@ -766,10 +766,9 @@ compute_ltrans_boundary (lto_symtab_encoder_t in_encoder)
symtab_node node = lto_symtab_encoder_deref (encoder, i); symtab_node node = lto_symtab_encoder_deref (encoder, i);
if (varpool_node *vnode = dyn_cast <varpool_node> (node)) if (varpool_node *vnode = dyn_cast <varpool_node> (node))
{ {
if (DECL_INITIAL (vnode->symbol.decl) if (!lto_symtab_encoder_encode_initializer_p (encoder,
&& !lto_symtab_encoder_encode_initializer_p (encoder, vnode)
vnode) && ctor_for_folding (vnode->symbol.decl) != error_mark_node)
&& const_value_known_p (vnode->symbol.decl))
{ {
lto_set_symtab_encoder_encode_initializer (encoder, vnode); lto_set_symtab_encoder_encode_initializer (encoder, vnode);
add_references (encoder, &vnode->symbol.ref_list); add_references (encoder, &vnode->symbol.ref_list);
......
2013-06-19 Jan Hubicka <jh@suse.cz>
* lto-partition.c (add_references_to_partition): Use
ctor_for_folding.
2013-06-18 Richard Biener <rguenther@suse.de> 2013-06-18 Richard Biener <rguenther@suse.de>
* lto.c (lto_register_var_decl_in_symtab): Pass in cache index * lto.c (lto_register_var_decl_in_symtab): Pass in cache index
......
...@@ -146,7 +146,7 @@ add_references_to_partition (ltrans_partition part, symtab_node node) ...@@ -146,7 +146,7 @@ add_references_to_partition (ltrans_partition part, symtab_node node)
Recursively look into the initializers of the constant variable and add Recursively look into the initializers of the constant variable and add
references, too. */ references, too. */
else if (is_a <varpool_node> (ref->referred) else if (is_a <varpool_node> (ref->referred)
&& const_value_known_p (ref->referred->symbol.decl) && ctor_for_folding (ref->referred->symbol.decl) != error_mark_node
&& !lto_symtab_encoder_in_partition_p (part->encoder, ref->referred)) && !lto_symtab_encoder_in_partition_p (part->encoder, ref->referred))
{ {
if (!part->initializers_visited) if (!part->initializers_visited)
......
2013-06-19 Jan Hubicka <jh@suse.cz>
* gcc.dg/tree-ssa/attr-alias-2.c: New testcase.
2013-06-19 Balaji V. Iyer <balaji.v.iyer@intel.com> 2013-06-19 Balaji V. Iyer <balaji.v.iyer@intel.com>
* c-c++-common/cilk-plus/AN/builtin_fn_custom.c: Replaced all the * c-c++-common/cilk-plus/AN/builtin_fn_custom.c: Replaced all the
......
/* { dg-do compile } */
/* { dg-require-alias "" } */
/* { dg-options "-O2 -fdump-tree-optimized" } */
static int a=4;
static int b __attribute__ ((alias("a")));
main()
{
return b+a;
}
/* { dg-final { scan-tree-dump "return 8" "optimized" } } */
/* { dg-do compile } */
/* { dg-require-alias "" } */
/* { dg-options "-O2 -fdump-tree-optimized" } */
static int a=4;
static int b __attribute__ ((alias("a")));
main()
{
return b+a;
}
/* { dg-final { scan-tree-dump "return 8" "optimized" } } */
/* { dg-do compile } */
/* { dg-require-alias "" } */
/* { dg-options "-O2 -fdump-tree-optimized" } */
static int a=4;
static int b __attribute__ ((alias("a")));
main()
{
return b+a;
}
/* { dg-final { scan-tree-dump "return 8" "optimized" } } */
...@@ -174,7 +174,7 @@ constant_after_peeling (tree op, gimple stmt, struct loop *loop) ...@@ -174,7 +174,7 @@ constant_after_peeling (tree op, gimple stmt, struct loop *loop)
while (handled_component_p (base)) while (handled_component_p (base))
base = TREE_OPERAND (base, 0); base = TREE_OPERAND (base, 0);
if ((DECL_P (base) if ((DECL_P (base)
&& const_value_known_p (base)) && ctor_for_folding (base) != error_mark_node)
|| CONSTANT_CLASS_P (base)) || CONSTANT_CLASS_P (base))
{ {
/* If so, see if we understand all the indices. */ /* If so, see if we understand all the indices. */
......
...@@ -66,12 +66,15 @@ void ...@@ -66,12 +66,15 @@ void
varpool_remove_node (struct varpool_node *node) varpool_remove_node (struct varpool_node *node)
{ {
symtab_unregister_node ((symtab_node)node); symtab_unregister_node ((symtab_node)node);
tree init;
/* Because we remove references from external functions before final compilation, /* Because we remove references from external functions before final compilation,
we may end up removing useful constructors. we may end up removing useful constructors.
FIXME: We probably want to trace boundaries better. */ FIXME: We probably want to trace boundaries better. */
if (!const_value_known_p (node->symbol.decl)) if ((init = ctor_for_folding (node->symbol.decl)) == error_mark_node)
varpool_remove_initializer (node); varpool_remove_initializer (node);
else
DECL_INITIAL (node->symbol.decl) = init;
ggc_free (node); ggc_free (node);
} }
...@@ -109,7 +112,7 @@ dump_varpool_node (FILE *f, struct varpool_node *node) ...@@ -109,7 +112,7 @@ dump_varpool_node (FILE *f, struct varpool_node *node)
fprintf (f, " output"); fprintf (f, " output");
if (TREE_READONLY (node->symbol.decl)) if (TREE_READONLY (node->symbol.decl))
fprintf (f, " read-only"); fprintf (f, " read-only");
if (const_value_known_p (node->symbol.decl)) if (ctor_for_folding (node->symbol.decl) != error_mark_node)
fprintf (f, " const-value-known"); fprintf (f, " const-value-known");
fprintf (f, "\n"); fprintf (f, "\n");
} }
...@@ -144,44 +147,93 @@ varpool_node_for_asm (tree asmname) ...@@ -144,44 +147,93 @@ varpool_node_for_asm (tree asmname)
} }
/* Return if DECL is constant and its initial value is known (so we can do /* Return if DECL is constant and its initial value is known (so we can do
constant folding using DECL_INITIAL (decl)). */ constant folding using DECL_INITIAL (decl)).
Return ERROR_MARK_NODE when value is unknown. */
bool tree
const_value_known_p (tree decl) ctor_for_folding (tree decl)
{ {
struct varpool_node *node, *real_node;
tree real_decl;
if (TREE_CODE (decl) != VAR_DECL if (TREE_CODE (decl) != VAR_DECL
&&TREE_CODE (decl) != CONST_DECL) && TREE_CODE (decl) != CONST_DECL)
return false; return error_mark_node;
if (TREE_CODE (decl) == CONST_DECL if (TREE_CODE (decl) == CONST_DECL
|| DECL_IN_CONSTANT_POOL (decl)) || DECL_IN_CONSTANT_POOL (decl))
return true; return DECL_INITIAL (decl);
if (TREE_THIS_VOLATILE (decl))
return error_mark_node;
/* Do not care about automatic variables. Those are never initialized
anyway, because gimplifier exapnds the code*/
if (!TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
{
gcc_assert (!TREE_PUBLIC (decl));
return error_mark_node;
}
gcc_assert (TREE_CODE (decl) == VAR_DECL); gcc_assert (TREE_CODE (decl) == VAR_DECL);
if (!TREE_READONLY (decl) || TREE_THIS_VOLATILE (decl)) node = varpool_get_node (decl);
return false; if (node)
{
real_node = varpool_variable_node (node);
real_decl = real_node->symbol.decl;
}
else
real_decl = decl;
/* See if we are dealing with alias.
In most cases alias is just alternative symbol pointing to a given
constructor. This allows us to use interposition rules of DECL
constructor of REAL_NODE. However weakrefs are special by being just
alternative name of their target (if defined). */
if (decl != real_decl)
{
gcc_assert (!DECL_INITIAL (decl)
|| DECL_INITIAL (decl) == error_mark_node);
if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl)))
{
node = varpool_alias_target (node);
decl = node->symbol.decl;
}
}
/* Gimplifier takes away constructors of local vars */ /* Vtables are defined by their types and must match no matter of interposition
if (!TREE_STATIC (decl) && !DECL_EXTERNAL (decl)) rules. */
return DECL_INITIAL (decl) != NULL; if (DECL_VIRTUAL_P (real_decl))
{
gcc_checking_assert (TREE_READONLY (real_decl));
return DECL_INITIAL (real_decl);
}
/* If thre is no constructor, we have nothing to do. */
if (DECL_INITIAL (real_decl) == error_mark_node)
return error_mark_node;
gcc_assert (TREE_STATIC (decl) || DECL_EXTERNAL (decl)); /* Non-readonly alias of readonly variable is also de-facto readonly,
because the variable itself is in readonly section.
We also honnor READONLY flag on alias assuming that user knows
what he is doing. */
if (!TREE_READONLY (decl) && !TREE_READONLY (real_decl))
return error_mark_node;
/* Variables declared 'const' without an initializer /* Variables declared 'const' without an initializer
have zero as the initializer if they may not be have zero as the initializer if they may not be
overridden at link or run time. */ overridden at link or run time. */
if (!DECL_INITIAL (decl) if (!DECL_INITIAL (real_decl)
&& (DECL_EXTERNAL (decl) && (DECL_EXTERNAL (decl) || decl_replaceable_p (decl)))
|| decl_replaceable_p (decl))) return error_mark_node;
return false;
/* Variables declared `const' with an initializer are considered /* Variables declared `const' with an initializer are considered
to not be overwritable with different initializer by default. to not be overwritable with different initializer by default.
??? Previously we behaved so for scalar variables but not for array ??? Previously we behaved so for scalar variables but not for array
accesses. */ accesses. */
return true; return DECL_INITIAL (real_decl);
} }
/* Add the variable DECL to the varpool. /* Add the variable DECL to the varpool.
......
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