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
This commit is contained in:
parent
216c12abf6
commit
6a6dac5293
|
@ -1,3 +1,23 @@
|
|||
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>
|
||||
|
||||
PR driver/57651
|
||||
|
|
|
@ -797,7 +797,7 @@ void varpool_analyze_node (struct varpool_node *);
|
|||
struct varpool_node * varpool_extra_name_alias (tree, tree);
|
||||
struct varpool_node * varpool_create_variable_alias (tree, tree);
|
||||
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 (*) (struct varpool_node *, void *),
|
||||
void *, bool);
|
||||
|
|
|
@ -762,8 +762,7 @@ process_function_and_variable_attributes (struct cgraph_node *first,
|
|||
{
|
||||
tree decl = vnode->symbol.decl;
|
||||
if (DECL_EXTERNAL (decl)
|
||||
&& DECL_INITIAL (decl)
|
||||
&& const_value_known_p (decl))
|
||||
&& DECL_INITIAL (decl))
|
||||
varpool_finalize_decl (decl);
|
||||
if (DECL_PRESERVE_P (decl))
|
||||
vnode->symbol.force_output = true;
|
||||
|
|
130
gcc/expr.c
130
gcc/expr.c
|
@ -9698,6 +9698,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
|
|||
{
|
||||
tree array = treeop0;
|
||||
tree index = treeop1;
|
||||
tree init;
|
||||
|
||||
/* Fold an expression like: "foo"[2].
|
||||
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,
|
|||
&& modifier != EXPAND_INITIALIZER
|
||||
&& modifier != EXPAND_MEMORY
|
||||
&& TREE_READONLY (array) && ! TREE_SIDE_EFFECTS (array)
|
||||
&& TREE_CODE (array) == VAR_DECL && DECL_INITIAL (array)
|
||||
&& TREE_CODE (DECL_INITIAL (array)) != ERROR_MARK
|
||||
&& const_value_known_p (array))
|
||||
&& TREE_CODE (index) == INTEGER_CST
|
||||
&& (TREE_CODE (array) == VAR_DECL
|
||||
|| 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)
|
||||
{
|
||||
unsigned HOST_WIDE_INT ix;
|
||||
tree field, value;
|
||||
FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (init), ix,
|
||||
field, value)
|
||||
if (tree_int_cst_equal (field, index))
|
||||
{
|
||||
if (TREE_SIDE_EFFECTS (value))
|
||||
break;
|
||||
|
||||
FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (init), ix,
|
||||
field, value)
|
||||
if (tree_int_cst_equal (field, index))
|
||||
if (TREE_CODE (value) == CONSTRUCTOR)
|
||||
{
|
||||
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;
|
||||
|
||||
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 low_bound = array_ref_low_bound (exp);
|
||||
index1 = fold_convert_loc (loc, sizetype,
|
||||
treeop1);
|
||||
tree type = TREE_TYPE (TREE_TYPE (init));
|
||||
enum machine_mode mode = TYPE_MODE (type);
|
||||
|
||||
/* 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 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);
|
||||
}
|
||||
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)
|
|||
|| TREE_CODE (array) == CONST_DECL)
|
||||
{
|
||||
int length;
|
||||
tree init = ctor_for_folding (array);
|
||||
|
||||
/* Variables initialized to string literals can be handled too. */
|
||||
if (!const_value_known_p (array)
|
||||
|| !DECL_INITIAL (array)
|
||||
|| TREE_CODE (DECL_INITIAL (array)) != STRING_CST)
|
||||
if (init == error_mark_node
|
||||
|| !init
|
||||
|| TREE_CODE (init) != STRING_CST)
|
||||
return 0;
|
||||
|
||||
/* Avoid const char foo[4] = "abcde"; */
|
||||
if (DECL_SIZE_UNIT (array) == NULL_TREE
|
||||
|| 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)
|
||||
return 0;
|
||||
|
||||
|
@ -10699,7 +10697,7 @@ string_constant (tree arg, tree *ptr_offset)
|
|||
return 0;
|
||||
|
||||
*ptr_offset = offset;
|
||||
return DECL_INITIAL (array);
|
||||
return init;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -192,9 +192,9 @@ canonicalize_constructor_val (tree cval, tree from_decl)
|
|||
tree
|
||||
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)
|
||||
{
|
||||
val = canonicalize_constructor_val (unshare_expr (val), sym);
|
||||
|
@ -2695,19 +2695,18 @@ get_base_constructor (tree base, HOST_WIDE_INT *bit_offset,
|
|||
switch (TREE_CODE (base))
|
||||
{
|
||||
case VAR_DECL:
|
||||
if (!const_value_known_p (base))
|
||||
return NULL_TREE;
|
||||
|
||||
/* Fallthru. */
|
||||
case CONST_DECL:
|
||||
if (!DECL_INITIAL (base)
|
||||
&& (TREE_STATIC (base) || DECL_EXTERNAL (base)))
|
||||
return error_mark_node;
|
||||
/* Do not return an error_mark_node DECL_INITIAL. LTO uses this
|
||||
as special marker (_not_ zero ...) for its own purposes. */
|
||||
if (DECL_INITIAL (base) == error_mark_node)
|
||||
return NULL_TREE;
|
||||
return DECL_INITIAL (base);
|
||||
{
|
||||
tree init = ctor_for_folding (base);
|
||||
|
||||
/* Our semantic is exact oposite of ctor_for_folding;
|
||||
NULL means unknown, while error_mark_node is 0. */
|
||||
if (init == error_mark_node)
|
||||
return NULL_TREE;
|
||||
if (!init)
|
||||
return error_mark_node;
|
||||
return init;
|
||||
}
|
||||
|
||||
case ARRAY_REF:
|
||||
case COMPONENT_REF:
|
||||
|
|
|
@ -2106,8 +2106,9 @@ param_change_prob (gimple stmt, int i)
|
|||
struct record_modified_bb_info info;
|
||||
bitmap_iterator bi;
|
||||
unsigned index;
|
||||
tree init = ctor_for_folding (base);
|
||||
|
||||
if (const_value_known_p (base))
|
||||
if (init != error_mark_node)
|
||||
return 0;
|
||||
if (!bb->frequency)
|
||||
return REG_BR_PROB_BASE;
|
||||
|
|
|
@ -145,7 +145,9 @@ process_references (struct ipa_ref_list *list,
|
|||
constant folding. Keep references alive so partitioning
|
||||
knows about potential references. */
|
||||
|| (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);
|
||||
enqueue_node ((symtab_node) node, first, reachable);
|
||||
}
|
||||
|
@ -400,6 +402,7 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
|
|||
}
|
||||
else if (!pointer_set_contains (reachable, vnode))
|
||||
{
|
||||
tree init;
|
||||
if (vnode->symbol.definition)
|
||||
{
|
||||
if (file)
|
||||
|
@ -411,8 +414,10 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
|
|||
vnode->symbol.aux = NULL;
|
||||
|
||||
/* 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);
|
||||
else
|
||||
DECL_INITIAL (vnode->symbol.decl) = init;
|
||||
ipa_remove_all_references (&vnode->symbol.ref_list);
|
||||
}
|
||||
else
|
||||
|
|
|
@ -766,10 +766,9 @@ compute_ltrans_boundary (lto_symtab_encoder_t in_encoder)
|
|||
symtab_node node = lto_symtab_encoder_deref (encoder, i);
|
||||
if (varpool_node *vnode = dyn_cast <varpool_node> (node))
|
||||
{
|
||||
if (DECL_INITIAL (vnode->symbol.decl)
|
||||
&& !lto_symtab_encoder_encode_initializer_p (encoder,
|
||||
vnode)
|
||||
&& const_value_known_p (vnode->symbol.decl))
|
||||
if (!lto_symtab_encoder_encode_initializer_p (encoder,
|
||||
vnode)
|
||||
&& ctor_for_folding (vnode->symbol.decl) != error_mark_node)
|
||||
{
|
||||
lto_set_symtab_encoder_encode_initializer (encoder, vnode);
|
||||
add_references (encoder, &vnode->symbol.ref_list);
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
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>
|
||||
|
||||
* 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)
|
|||
Recursively look into the initializers of the constant variable and add
|
||||
references, too. */
|
||||
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))
|
||||
{
|
||||
if (!part->initializers_visited)
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
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>
|
||||
|
||||
* c-c++-common/cilk-plus/AN/builtin_fn_custom.c: Replaced all the
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
/* { 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)
|
|||
while (handled_component_p (base))
|
||||
base = TREE_OPERAND (base, 0);
|
||||
if ((DECL_P (base)
|
||||
&& const_value_known_p (base))
|
||||
&& ctor_for_folding (base) != error_mark_node)
|
||||
|| CONSTANT_CLASS_P (base))
|
||||
{
|
||||
/* If so, see if we understand all the indices. */
|
||||
|
|
|
@ -66,12 +66,15 @@ void
|
|||
varpool_remove_node (struct varpool_node *node)
|
||||
{
|
||||
symtab_unregister_node ((symtab_node)node);
|
||||
tree init;
|
||||
|
||||
/* Because we remove references from external functions before final compilation,
|
||||
we may end up removing useful constructors.
|
||||
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);
|
||||
else
|
||||
DECL_INITIAL (node->symbol.decl) = init;
|
||||
ggc_free (node);
|
||||
}
|
||||
|
||||
|
@ -109,7 +112,7 @@ dump_varpool_node (FILE *f, struct varpool_node *node)
|
|||
fprintf (f, " output");
|
||||
if (TREE_READONLY (node->symbol.decl))
|
||||
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, "\n");
|
||||
}
|
||||
|
@ -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
|
||||
constant folding using DECL_INITIAL (decl)). */
|
||||
constant folding using DECL_INITIAL (decl)).
|
||||
Return ERROR_MARK_NODE when value is unknown. */
|
||||
|
||||
bool
|
||||
const_value_known_p (tree decl)
|
||||
tree
|
||||
ctor_for_folding (tree decl)
|
||||
{
|
||||
struct varpool_node *node, *real_node;
|
||||
tree real_decl;
|
||||
|
||||
if (TREE_CODE (decl) != VAR_DECL
|
||||
&&TREE_CODE (decl) != CONST_DECL)
|
||||
return false;
|
||||
&& TREE_CODE (decl) != CONST_DECL)
|
||||
return error_mark_node;
|
||||
|
||||
if (TREE_CODE (decl) == CONST_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);
|
||||
|
||||
if (!TREE_READONLY (decl) || TREE_THIS_VOLATILE (decl))
|
||||
return false;
|
||||
node = varpool_get_node (decl);
|
||||
if (node)
|
||||
{
|
||||
real_node = varpool_variable_node (node);
|
||||
real_decl = real_node->symbol.decl;
|
||||
}
|
||||
else
|
||||
real_decl = decl;
|
||||
|
||||
/* Gimplifier takes away constructors of local vars */
|
||||
if (!TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
|
||||
return DECL_INITIAL (decl) != NULL;
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
|
||||
gcc_assert (TREE_STATIC (decl) || DECL_EXTERNAL (decl));
|
||||
/* Vtables are defined by their types and must match no matter of interposition
|
||||
rules. */
|
||||
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;
|
||||
|
||||
/* 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
|
||||
have zero as the initializer if they may not be
|
||||
overridden at link or run time. */
|
||||
if (!DECL_INITIAL (decl)
|
||||
&& (DECL_EXTERNAL (decl)
|
||||
|| decl_replaceable_p (decl)))
|
||||
return false;
|
||||
if (!DECL_INITIAL (real_decl)
|
||||
&& (DECL_EXTERNAL (decl) || decl_replaceable_p (decl)))
|
||||
return error_mark_node;
|
||||
|
||||
/* Variables declared `const' with an initializer are considered
|
||||
to not be overwritable with different initializer by default.
|
||||
|
||||
??? Previously we behaved so for scalar variables but not for array
|
||||
accesses. */
|
||||
return true;
|
||||
return DECL_INITIAL (real_decl);
|
||||
}
|
||||
|
||||
/* Add the variable DECL to the varpool.
|
||||
|
|
Loading…
Reference in New Issue