Hi,
this patch makes it possible to fold through aliases.  It may seem unimportant, 
but we
run into those cases in C++ where extra name aliases may get used by 
devirtualization
machinery.  The patch also fixes the following long standing bug:
jh@gcc10:~/trunk/build2/gcc$ cat t.c
static int a=4;
static int b __attribute__ ((alias("a")));
main()
{
   return b+a;
}
jh@gcc10:~/trunk/build2/gcc$ gcc -O2 t.c -S
jh@gcc10:~/trunk/build2/gcc$ more t.s
        .file   "t.c"
        .text
        .p2align 4,,15
.globl main
        .type   main, @function
main:
.LFB0:
        .cfi_startproc
        movl    $4, %eax
        ret
        .cfi_endproc
.LFE0:
        .size   main, .-main
        .section        .rodata
        .align 4
        .type   a, @object
        .size   a, 4
a:
        .long   4
        .set    b,a
        .ident  "GCC: (Debian 4.4.5-8) 4.4.5"
        .section        .note.GNU-stack,"",@progbits
jh@gcc10:~/trunk/build2/gcc$ gcc --version
gcc (Debian 4.4.5-8) 4.4.5
Copyright (C) 2010 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

jh@gcc10:~/trunk/build2/gcc$ ./xgcc -B ./ -O2 t.c -S
jh@gcc10:~/trunk/build2/gcc$ more t.s
        .file   "t.c"
        .section        .text.startup,"ax",@progbits
        .p2align 4,,15
        .globl  main
        .type   main, @function
main:
.LFB0:
        .cfi_startproc
        movl    $8, %eax
        ret
        .cfi_endproc
.LFE0:
        .size   main, .-main
        .ident  "GCC: (GNU) 4.9.0 20130616 (experimental)"
        .section        .note.GNU-stack,"",@progbits

The main idea is to replace const_value_known_p predicate by ctor_for_folding
that returns the ctor and is able to look through aliases via the symbol table.
The huge change in expand_expr_real_1 is really just a reformating.

I have bootstrapped/regtested the patch on x86_64-linux and tested with Firefox 
build.
I am running now PPC64 test and will wait for Richard's renaming patch.

Honza

        * 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.
Index: cgraph.h
===================================================================
*** cgraph.h    (revision 200147)
--- cgraph.h    (working copy)
*************** void varpool_analyze_node (struct varpoo
*** 797,803 ****
  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);
  bool varpool_for_node_and_aliases (struct varpool_node *,
                                   bool (*) (struct varpool_node *, void *),
                                   void *, bool);
--- 797,803 ----
  struct varpool_node * varpool_extra_name_alias (tree, tree);
  struct varpool_node * varpool_create_variable_alias (tree, tree);
  void varpool_reset_queue (void);
! tree ctor_for_folding (tree);
  bool varpool_for_node_and_aliases (struct varpool_node *,
                                   bool (*) (struct varpool_node *, void *),
                                   void *, bool);
Index: cgraphunit.c
===================================================================
*** cgraphunit.c        (revision 200147)
--- cgraphunit.c        (working copy)
*************** process_function_and_variable_attributes
*** 761,768 ****
      {
        tree decl = vnode->symbol.decl;
        if (DECL_EXTERNAL (decl)
!         && DECL_INITIAL (decl)
!         && const_value_known_p (decl))
        varpool_finalize_decl (decl);
        if (DECL_PRESERVE_P (decl))
        vnode->symbol.force_output = true;
--- 761,767 ----
      {
        tree decl = vnode->symbol.decl;
        if (DECL_EXTERNAL (decl)
!         && DECL_INITIAL (decl))
        varpool_finalize_decl (decl);
        if (DECL_PRESERVE_P (decl))
        vnode->symbol.force_output = true;
Index: testsuite/gcc.dg/tree-ssa/attr-alias-2.c
===================================================================
*** testsuite/gcc.dg/tree-ssa/attr-alias-2.c    (revision 0)
--- testsuite/gcc.dg/tree-ssa/attr-alias-2.c    (revision 0)
***************
*** 0 ****
--- 1,10 ----
+ /* { 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" } } */
Index: lto-cgraph.c
===================================================================
*** lto-cgraph.c        (revision 200147)
--- lto-cgraph.c        (working copy)
*************** compute_ltrans_boundary (lto_symtab_enco
*** 766,775 ****
        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))
            {
              lto_set_symtab_encoder_encode_initializer (encoder, vnode);
              add_references (encoder, &vnode->symbol.ref_list);
--- 766,774 ----
        symtab_node node = lto_symtab_encoder_deref (encoder, i);
        if (varpool_node *vnode = dyn_cast <varpool_node> (node))
        {
!         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);
Index: expr.c
===================================================================
*** expr.c      (revision 200147)
--- expr.c      (working copy)
*************** expand_expr_real_1 (tree exp, rtx target
*** 9698,9703 ****
--- 9698,9704 ----
        {
        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 &.
*************** expand_expr_real_1 (tree exp, rtx target
*** 9744,9819 ****
                 && 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))
          {
!           if (TREE_CODE (index) == INTEGER_CST)
              {
!               tree init = DECL_INITIAL (array);
  
!               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;
  
!                         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)
                  {
!                   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 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);
!                     }
                  }
              }
          }
--- 9745,9816 ----
                 && modifier != EXPAND_INITIALIZER
                 && modifier != EXPAND_MEMORY
                 && TREE_READONLY (array) && ! TREE_SIDE_EFFECTS (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 (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;
  
!                     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)
!             {
!               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 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);
                  }
              }
          }
*************** string_constant (tree arg, tree *ptr_off
*** 10676,10692 ****
           || TREE_CODE (array) == CONST_DECL)
      {
        int length;
  
        /* 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)
        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
          || compare_tree_int (DECL_SIZE_UNIT (array), length) < 0)
        return 0;
  
--- 10673,10690 ----
           || TREE_CODE (array) == CONST_DECL)
      {
        int length;
+       tree init = ctor_for_folding (array);
  
        /* Variables initialized to string literals can be handled too.  */
!       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 (init)) <= 0
          || compare_tree_int (DECL_SIZE_UNIT (array), length) < 0)
        return 0;
  
*************** string_constant (tree arg, tree *ptr_off
*** 10699,10705 ****
        return 0;
  
        *ptr_offset = offset;
!       return DECL_INITIAL (array);
      }
  
    return 0;
--- 10697,10703 ----
        return 0;
  
        *ptr_offset = offset;
!       return init;
      }
  
    return 0;
Index: tree-ssa-loop-ivcanon.c
===================================================================
*** tree-ssa-loop-ivcanon.c     (revision 200147)
--- tree-ssa-loop-ivcanon.c     (working copy)
*************** constant_after_peeling (tree op, gimple
*** 174,180 ****
        while (handled_component_p (base))
        base = TREE_OPERAND (base, 0);
        if ((DECL_P (base)
!          && const_value_known_p (base))
          || CONSTANT_CLASS_P (base))
        {
          /* If so, see if we understand all the indices.  */
--- 174,180 ----
        while (handled_component_p (base))
        base = TREE_OPERAND (base, 0);
        if ((DECL_P (base)
!          && ctor_for_folding (base) != error_mark_node)
          || CONSTANT_CLASS_P (base))
        {
          /* If so, see if we understand all the indices.  */
Index: ipa.c
===================================================================
*** ipa.c       (revision 200147)
--- ipa.c       (working copy)
*************** process_references (struct ipa_ref_list
*** 145,151 ****
                     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)))))
        pointer_set_insert (reachable, node);
        enqueue_node ((symtab_node) node, first, reachable);
      }
--- 145,153 ----
                     constant folding.  Keep references alive so partitioning
                     knows about potential references.  */
                  || (TREE_CODE (node->symbol.decl) == VAR_DECL
!                     && flag_wpa
!                     && ctor_for_folding (node->symbol.decl)
!                        != error_mark_node))))
        pointer_set_insert (reachable, node);
        enqueue_node ((symtab_node) node, first, reachable);
      }
*************** symtab_remove_unreachable_nodes (bool be
*** 400,405 ****
--- 402,408 ----
        }
        else if (!pointer_set_contains (reachable, vnode))
          {
+         tree init;
          if (vnode->symbol.definition)
            {
              if (file)
*************** symtab_remove_unreachable_nodes (bool be
*** 411,418 ****
          vnode->symbol.aux = NULL;
  
          /* Keep body if it may be useful for constant folding.  */
!         if (!const_value_known_p (vnode->symbol.decl))
            varpool_remove_initializer (vnode);
          ipa_remove_all_references (&vnode->symbol.ref_list);
        }
        else
--- 414,423 ----
          vnode->symbol.aux = NULL;
  
          /* Keep body if it may be useful for constant folding.  */
!         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
Index: ipa-inline-analysis.c
===================================================================
*** ipa-inline-analysis.c       (revision 200147)
--- ipa-inline-analysis.c       (working copy)
*************** param_change_prob (gimple stmt, int i)
*** 2106,2113 ****
        struct record_modified_bb_info info;
        bitmap_iterator bi;
        unsigned index;
  
!       if (const_value_known_p (base))
        return 0;
        if (!bb->frequency)
        return REG_BR_PROB_BASE;
--- 2106,2114 ----
        struct record_modified_bb_info info;
        bitmap_iterator bi;
        unsigned index;
+       tree init = ctor_for_folding (base);
  
!       if (init != error_mark_node)
        return 0;
        if (!bb->frequency)
        return REG_BR_PROB_BASE;
Index: gimple-fold.c
===================================================================
*** gimple-fold.c       (revision 200147)
--- gimple-fold.c       (working copy)
*************** canonicalize_constructor_val (tree cval,
*** 192,200 ****
  tree
  get_symbol_constant_value (tree sym)
  {
!   if (const_value_known_p (sym))
      {
-       tree val = DECL_INITIAL (sym);
        if (val)
        {
          val = canonicalize_constructor_val (unshare_expr (val), sym);
--- 192,200 ----
  tree
  get_symbol_constant_value (tree sym)
  {
!   tree val = ctor_for_folding (sym);
!   if (val != error_mark_node)
      {
        if (val)
        {
          val = canonicalize_constructor_val (unshare_expr (val), sym);
*************** get_base_constructor (tree base, HOST_WI
*** 2695,2713 ****
    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);
  
      case ARRAY_REF:
      case COMPONENT_REF:
--- 2695,2712 ----
    switch (TREE_CODE (base))
      {
      case VAR_DECL:
      case CONST_DECL:
!       {
!       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:
Index: lto/lto-partition.c
===================================================================
*** lto/lto-partition.c (revision 200147)
--- lto/lto-partition.c (working copy)
*************** add_references_to_partition (ltrans_part
*** 146,152 ****
         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)
             && !lto_symtab_encoder_in_partition_p (part->encoder, 
ref->referred))
        {
        if (!part->initializers_visited)
--- 146,152 ----
         Recursively look into the initializers of the constant variable and add
         references, too.  */
      else if (is_a <varpool_node> (ref->referred)
!            && ctor_for_folding (ref->referred->symbol.decl) != error_mark_node
             && !lto_symtab_encoder_in_partition_p (part->encoder, 
ref->referred))
        {
        if (!part->initializers_visited)
Index: varpool.c
===================================================================
*** varpool.c   (revision 200147)
--- varpool.c   (working copy)
*************** void
*** 66,77 ****
  varpool_remove_node (struct varpool_node *node)
  {
    symtab_unregister_node ((symtab_node)node);
  
    /* 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))
      varpool_remove_initializer (node);
    ggc_free (node);
  }
  
--- 66,80 ----
  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 ((init = ctor_for_folding (node->symbol.decl)) == error_mark_node)
      varpool_remove_initializer (node);
+   else
+     DECL_INITIAL (node->symbol.decl) = init;
    ggc_free (node);
  }
  
*************** varpool_remove_initializer (struct varpo
*** 84,90 ****
        /* Keep vtables for BINFO folding.  */
        && !DECL_VIRTUAL_P (node->symbol.decl)
        /* FIXME: http://gcc.gnu.org/PR55395 */
!       && debug_info_level == DINFO_LEVEL_NONE)
      DECL_INITIAL (node->symbol.decl) = error_mark_node;
  }
  
--- 87,96 ----
        /* Keep vtables for BINFO folding.  */
        && !DECL_VIRTUAL_P (node->symbol.decl)
        /* FIXME: http://gcc.gnu.org/PR55395 */
!       && debug_info_level == DINFO_LEVEL_NONE
!       /* During LTO streaming we may have multiple nodes
!        associated to a given decl.  */
!       && cgraph_state != CGRAPH_LTO_STREAMING)
      DECL_INITIAL (node->symbol.decl) = error_mark_node;
  }
  
*************** dump_varpool_node (FILE *f, struct varpo
*** 104,110 ****
      fprintf (f, " output");
    if (TREE_READONLY (node->symbol.decl))
      fprintf (f, " read-only");
!   if (const_value_known_p (node->symbol.decl))
      fprintf (f, " const-value-known");
    fprintf (f, "\n");
  }
--- 110,116 ----
      fprintf (f, " output");
    if (TREE_READONLY (node->symbol.decl))
      fprintf (f, " read-only");
!   if (ctor_for_folding (node->symbol.decl) != error_mark_node)
      fprintf (f, " const-value-known");
    fprintf (f, "\n");
  }
*************** varpool_node_for_asm (tree asmname)
*** 139,182 ****
  }
  
  /* Return if DECL is constant and its initial value is known (so we can do
!    constant folding using DECL_INITIAL (decl)).  */
  
! bool
! const_value_known_p (tree decl)
  {
    if (TREE_CODE (decl) != VAR_DECL
!       &&TREE_CODE (decl) != CONST_DECL)
!     return false;
  
    if (TREE_CODE (decl) == CONST_DECL
        || DECL_IN_CONSTANT_POOL (decl))
!     return true;
! 
!   gcc_assert (TREE_CODE (decl) == VAR_DECL);
  
!   if (!TREE_READONLY (decl) || TREE_THIS_VOLATILE (decl))
!     return false;
  
!   /* Gimplifier takes away constructors of local vars  */
    if (!TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
!     return DECL_INITIAL (decl) != NULL;
  
!   gcc_assert (TREE_STATIC (decl) || DECL_EXTERNAL (decl));
  
    /* 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;
  
    /* 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;
  }
  
  /* Add the variable DECL to the varpool.
--- 145,237 ----
  }
  
  /* Return if DECL is constant and its initial value is known (so we can do
!    constant folding using DECL_INITIAL (decl)).
!    Return ERROR_MARK_NODE when value is unknown.  */
  
! 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 error_mark_node;
  
    if (TREE_CODE (decl) == CONST_DECL
        || DECL_IN_CONSTANT_POOL (decl))
!     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);
! 
!   node = varpool_get_node (decl);
!   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;
!       }
!     }
! 
!   /* 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 (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 DECL_INITIAL (real_decl);
  }
  
  /* Add the variable DECL to the varpool.

Reply via email to