re PR c++/48069 (FAIL: g++.old-deja/g++.pt/spec26.C)
[gcc.git] / gcc / tree.c
index 4de73ee4d2c75c3eb55c7f850cdb08603fcef71f..d923ac89a766146369c8957efa1ad8d587e0fee6 100644 (file)
@@ -1,7 +1,7 @@
 /* Language-independent node constructors for parse phase of GNU compiler.
    Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
-   Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
+   2011 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -1362,7 +1362,7 @@ build_vector_from_ctor (tree type, VEC(constructor_elt,gc) *v)
     list = tree_cons (NULL_TREE, value, list);
   for (; idx < TYPE_VECTOR_SUBPARTS (type); ++idx)
     list = tree_cons (NULL_TREE,
-                     fold_convert (TREE_TYPE (type), integer_zero_node), list);
+                     build_zero_cst (TREE_TYPE (type)), list);
   return build_vector (type, nreverse (list));
 }
 
@@ -1376,8 +1376,8 @@ build_vector_from_val (tree vectype, tree sc)
   if (sc == error_mark_node)
     return sc;
 
-  gcc_assert (lang_hooks.types_compatible_p (TREE_TYPE (sc),
-                                            TREE_TYPE (vectype)));
+  gcc_assert (useless_type_conversion_p (TREE_TYPE (sc),
+                                        TREE_TYPE (vectype)));
 
   v = VEC_alloc (constructor_elt, gc, nunits);
   for (i = 0; i < nunits; ++i)
@@ -1599,22 +1599,52 @@ build_one_cst (tree type)
     case COMPLEX_TYPE:
       return build_complex (type,
                            build_one_cst (TREE_TYPE (type)),
-                           fold_convert (TREE_TYPE (type), integer_zero_node));
+                           build_zero_cst (TREE_TYPE (type)));
 
     default:
       gcc_unreachable ();
     }
 }
 
-/* Build 0 constant of type TYPE.  This is used by constructor folding and thus
-   the constant should correspond zero in memory representation.  */
+/* Build 0 constant of type TYPE.  This is used by constructor folding
+   and thus the constant should be represented in memory by
+   zero(es).  */
 
 tree
 build_zero_cst (tree type)
 {
-  if (!AGGREGATE_TYPE_P (type))
-    return fold_convert (type, integer_zero_node);
-  return build_constructor (type, NULL);
+  switch (TREE_CODE (type))
+    {
+    case INTEGER_TYPE: case ENUMERAL_TYPE: case BOOLEAN_TYPE:
+    case POINTER_TYPE: case REFERENCE_TYPE:
+    case OFFSET_TYPE:
+      return build_int_cst (type, 0);
+
+    case REAL_TYPE:
+      return build_real (type, dconst0);
+
+    case FIXED_POINT_TYPE:
+      return build_fixed (type, FCONST0 (TYPE_MODE (type)));
+
+    case VECTOR_TYPE:
+      {
+       tree scalar = build_zero_cst (TREE_TYPE (type));
+
+       return build_vector_from_val (type, scalar);
+      }
+
+    case COMPLEX_TYPE:
+      {
+       tree zero = build_zero_cst (TREE_TYPE (type));
+
+       return build_complex (type, zero, zero);
+      }
+
+    default:
+      if (!AGGREGATE_TYPE_P (type))
+       return fold_convert (type, integer_zero_node);
+      return build_constructor (type, NULL);
+    }
 }
 
 
@@ -2765,8 +2795,8 @@ process_call_operands (tree t)
   TREE_READONLY (t) = read_only;
 }
 \f
-/* Return 1 if EXP contains a PLACEHOLDER_EXPR; i.e., if it represents a size
-   or offset that depends on a field within a record.  */
+/* Return true if EXP contains a PLACEHOLDER_EXPR, i.e. if it represents a
+   size or offset that depends on a field within a record.  */
 
 bool
 contains_placeholder_p (const_tree exp)
@@ -2852,9 +2882,9 @@ contains_placeholder_p (const_tree exp)
   return 0;
 }
 
-/* Return true if any part of the computation of TYPE involves a
-   PLACEHOLDER_EXPR.  This includes size, bounds, qualifiers
-   (for QUAL_UNION_TYPE) and field positions.  */
+/* Return true if any part of the structure of TYPE involves a PLACEHOLDER_EXPR
+   directly.  This includes size, bounds, qualifiers (for QUAL_UNION_TYPE) and
+   field positions.  */
 
 static bool
 type_contains_placeholder_1 (const_tree type)
@@ -2863,7 +2893,8 @@ type_contains_placeholder_1 (const_tree type)
      the case of arrays) type involves a placeholder, this type does.  */
   if (CONTAINS_PLACEHOLDER_P (TYPE_SIZE (type))
       || CONTAINS_PLACEHOLDER_P (TYPE_SIZE_UNIT (type))
-      || (TREE_TYPE (type) != 0
+      || (!POINTER_TYPE_P (type)
+         && TREE_TYPE (type)
          && type_contains_placeholder_p (TREE_TYPE (type))))
     return true;
 
@@ -2891,8 +2922,8 @@ type_contains_placeholder_1 (const_tree type)
              || CONTAINS_PLACEHOLDER_P (TYPE_MAX_VALUE (type)));
 
     case ARRAY_TYPE:
-      /* We're already checked the component type (TREE_TYPE), so just check
-        the index type.  */
+      /* We have already checked the component type above, so just check the
+        domain type.  */
       return type_contains_placeholder_p (TYPE_DOMAIN (type));
 
     case RECORD_TYPE:
@@ -2917,6 +2948,8 @@ type_contains_placeholder_1 (const_tree type)
     }
 }
 
+/* Wrapper around above function used to cache its result.  */
+
 bool
 type_contains_placeholder_p (tree type)
 {
@@ -4544,6 +4577,25 @@ free_lang_data_in_decl (tree decl)
     }
   else if (TREE_CODE (decl) == TYPE_DECL)
     DECL_INITIAL (decl) = NULL_TREE;
+  else if (TREE_CODE (decl) == TRANSLATION_UNIT_DECL
+           && DECL_INITIAL (decl)
+           && TREE_CODE (DECL_INITIAL (decl)) == BLOCK)
+    {
+      /* Strip builtins from the translation-unit BLOCK.  We still have
+        targets without builtin_decl support and also builtins are
+        shared nodes and thus we can't use TREE_CHAIN in multiple
+        lists.  */
+      tree *nextp = &BLOCK_VARS (DECL_INITIAL (decl));
+      while (*nextp)
+        {
+          tree var = *nextp;
+          if (TREE_CODE (var) == FUNCTION_DECL
+              && DECL_BUILT_IN (var))
+           *nextp = TREE_CHAIN (var);
+         else
+           nextp = &TREE_CHAIN (var);
+        }
+    }
 }
 
 
@@ -5476,7 +5528,8 @@ handle_dll_attribute (tree * pnode, tree name, tree args, int flags,
         DECL_DLLIMPORT_P (node) = 1;
     }
   else if (TREE_CODE (node) == FUNCTION_DECL
-          && DECL_DECLARED_INLINE_P (node))
+          && DECL_DECLARED_INLINE_P (node)
+          && flag_keep_inline_dllexport)
     /* An exported function, even if inline, must be emitted.  */
     DECL_EXTERNAL (node) = 0;
 
@@ -5928,12 +5981,18 @@ type_hash_eq (const void *va, const void *vb)
       || TREE_TYPE (a->type) != TREE_TYPE (b->type)
       || !attribute_list_equal (TYPE_ATTRIBUTES (a->type),
                                 TYPE_ATTRIBUTES (b->type))
-      || TYPE_ALIGN (a->type) != TYPE_ALIGN (b->type)
-      || TYPE_MODE (a->type) != TYPE_MODE (b->type)
       || (TREE_CODE (a->type) != COMPLEX_TYPE
           && TYPE_NAME (a->type) != TYPE_NAME (b->type)))
     return 0;
 
+  /* Be careful about comparing arrays before and after the element type
+     has been completed; don't compare TYPE_ALIGN unless both types are
+     complete.  */
+  if (COMPLETE_TYPE_P (a->type) && COMPLETE_TYPE_P (b->type)
+      && (TYPE_ALIGN (a->type) != TYPE_ALIGN (b->type)
+         || TYPE_MODE (a->type) != TYPE_MODE (b->type)))
+    return 0;
+
   switch (TREE_CODE (a->type))
     {
     case VOID_TYPE:
@@ -5974,15 +6033,16 @@ type_hash_eq (const void *va, const void *vb)
       return TYPE_OFFSET_BASETYPE (a->type) == TYPE_OFFSET_BASETYPE (b->type);
 
     case METHOD_TYPE:
-      return (TYPE_METHOD_BASETYPE (a->type) == TYPE_METHOD_BASETYPE (b->type)
-             && (TYPE_ARG_TYPES (a->type) == TYPE_ARG_TYPES (b->type)
-                 || (TYPE_ARG_TYPES (a->type)
-                     && TREE_CODE (TYPE_ARG_TYPES (a->type)) == TREE_LIST
-                     && TYPE_ARG_TYPES (b->type)
-                     && TREE_CODE (TYPE_ARG_TYPES (b->type)) == TREE_LIST
-                     && type_list_equal (TYPE_ARG_TYPES (a->type),
-                                         TYPE_ARG_TYPES (b->type)))));
-
+      if (TYPE_METHOD_BASETYPE (a->type) == TYPE_METHOD_BASETYPE (b->type)
+         && (TYPE_ARG_TYPES (a->type) == TYPE_ARG_TYPES (b->type)
+             || (TYPE_ARG_TYPES (a->type)
+                 && TREE_CODE (TYPE_ARG_TYPES (a->type)) == TREE_LIST
+                 && TYPE_ARG_TYPES (b->type)
+                 && TREE_CODE (TYPE_ARG_TYPES (b->type)) == TREE_LIST
+                 && type_list_equal (TYPE_ARG_TYPES (a->type),
+                                     TYPE_ARG_TYPES (b->type)))))
+        break;
+      return 0;
     case ARRAY_TYPE:
       return TYPE_DOMAIN (a->type) == TYPE_DOMAIN (b->type);
 
@@ -7063,6 +7123,7 @@ static tree
 build_range_type_1 (tree type, tree lowval, tree highval, bool shared)
 {
   tree itype = make_node (INTEGER_TYPE);
+  hashval_t hashcode = 0;
 
   TREE_TYPE (itype) = type;
 
@@ -7076,6 +7137,9 @@ build_range_type_1 (tree type, tree lowval, tree highval, bool shared)
   TYPE_ALIGN (itype) = TYPE_ALIGN (type);
   TYPE_USER_ALIGN (itype) = TYPE_USER_ALIGN (type);
 
+  if (!shared)
+    return itype;
+
   if ((TYPE_MIN_VALUE (itype)
        && TREE_CODE (TYPE_MIN_VALUE (itype)) != INTEGER_CST)
       || (TYPE_MAX_VALUE (itype)
@@ -7087,13 +7151,10 @@ build_range_type_1 (tree type, tree lowval, tree highval, bool shared)
       return itype;
     }
 
-  if (shared)
-    {
-      hashval_t hash = iterative_hash_expr (TYPE_MIN_VALUE (itype), 0);
-      hash = iterative_hash_expr (TYPE_MAX_VALUE (itype), hash);
-      hash = iterative_hash_hashval_t (TYPE_HASH (type), hash);
-      itype = type_hash_canon (hash, itype);
-    }
+  hashcode = iterative_hash_expr (TYPE_MIN_VALUE (itype), hashcode);
+  hashcode = iterative_hash_expr (TYPE_MAX_VALUE (itype), hashcode);
+  hashcode = iterative_hash_hashval_t (TYPE_HASH (type), hashcode);
+  itype = type_hash_canon (hashcode, itype);
 
   return itype;
 }
@@ -8484,8 +8545,12 @@ get_file_function_name (const char *type)
     p = q = ASTRDUP (first_global_object_name);
   /* If the target is handling the constructors/destructors, they
      will be local to this file and the name is only necessary for
-     debugging purposes.  */
-  else if ((type[0] == 'I' || type[0] == 'D') && targetm.have_ctors_dtors)
+     debugging purposes. 
+     We also assign sub_I and sub_D sufixes to constructors called from
+     the global static constructors.  These are always local.  */
+  else if (((type[0] == 'I' || type[0] == 'D') && targetm.have_ctors_dtors)
+          || (strncmp (type, "sub_", 4) == 0
+              && (type[4] == 'I' || type[4] == 'D')))
     {
       const char *file = main_input_filename;
       if (! file)
@@ -9291,12 +9356,6 @@ build_common_builtin_nodes (void)
                        BUILT_IN_STACK_RESTORE,
                        "__builtin_stack_restore", ECF_NOTHROW | ECF_LEAF);
 
-  ftype = build_function_type_list (void_type_node, NULL_TREE);
-  local_define_builtin ("__builtin_profile_func_enter", ftype,
-                       BUILT_IN_PROFILE_FUNC_ENTER, "profile_func_enter", 0);
-  local_define_builtin ("__builtin_profile_func_exit", ftype,
-                       BUILT_IN_PROFILE_FUNC_EXIT, "profile_func_exit", 0);
-
   /* If there's a possibility that we might use the ARM EABI, build the
     alternate __cxa_end_cleanup node used to resume from C++ and Java.  */
   if (targetm.arm_eabi_unwinder)
@@ -9310,7 +9369,8 @@ build_common_builtin_nodes (void)
   ftype = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
   local_define_builtin ("__builtin_unwind_resume", ftype,
                        BUILT_IN_UNWIND_RESUME,
-                       (targetm.except_unwind_info () == UI_SJLJ
+                       ((targetm.except_unwind_info (&global_options)
+                         == UI_SJLJ)
                         ? "_Unwind_SjLj_Resume" : "_Unwind_Resume"),
                        ECF_NORETURN);
 
@@ -10906,17 +10966,17 @@ lhd_gcc_personality (void)
 tree
 get_binfo_at_offset (tree binfo, HOST_WIDE_INT offset, tree expected_type)
 {
-  tree type;
+  tree type = BINFO_TYPE (binfo);
 
-  type = TREE_TYPE (binfo);
-  while (offset > 0)
+  while (true)
     {
-      tree base_binfo, found_binfo;
       HOST_WIDE_INT pos, size;
       tree fld;
       int i;
 
-      if (TREE_CODE (type) != RECORD_TYPE)
+      if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (expected_type))
+         return binfo;
+      if (offset < 0)
        return NULL_TREE;
 
       for (fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
@@ -10929,27 +10989,34 @@ get_binfo_at_offset (tree binfo, HOST_WIDE_INT offset, tree expected_type)
          if (pos <= offset && (pos + size) > offset)
            break;
        }
-      if (!fld)
+      if (!fld || TREE_CODE (TREE_TYPE (fld)) != RECORD_TYPE)
        return NULL_TREE;
 
-      found_binfo = NULL_TREE;
-      for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
-       if (TREE_TYPE (base_binfo) == TREE_TYPE (fld))
-         {
-           found_binfo = base_binfo;
-           break;
-         }
-
-      if (!found_binfo)
-       return NULL_TREE;
+      if (!DECL_ARTIFICIAL (fld))
+       {
+         binfo = TYPE_BINFO (TREE_TYPE (fld));
+         if (!binfo)
+           return NULL_TREE;
+       }
+      /* Offset 0 indicates the primary base, whose vtable contents are
+        represented in the binfo for the derived class.  */
+      else if (offset != 0)
+       {
+         tree base_binfo, found_binfo = NULL_TREE;
+         for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
+           if (TREE_TYPE (base_binfo) == TREE_TYPE (fld))
+             {
+               found_binfo = base_binfo;
+               break;
+             }
+         if (!found_binfo)
+           return NULL_TREE;
+         binfo = found_binfo;
+       }
 
       type = TREE_TYPE (fld);
-      binfo = found_binfo;
       offset -= pos;
     }
-  if (type != expected_type)
-    return NULL_TREE;
-  return binfo;
 }
 
 /* Returns true if X is a typedef decl.  */
@@ -10969,4 +11036,109 @@ typedef_variant_p (tree type)
   return is_typedef_decl (TYPE_NAME (type));
 }
 
+/* Warn about a use of an identifier which was marked deprecated.  */
+void
+warn_deprecated_use (tree node, tree attr)
+{
+  const char *msg;
+
+  if (node == 0 || !warn_deprecated_decl)
+    return;
+
+  if (!attr)
+    {
+      if (DECL_P (node))
+       attr = DECL_ATTRIBUTES (node);
+      else if (TYPE_P (node))
+       {
+         tree decl = TYPE_STUB_DECL (node);
+         if (decl)
+           attr = lookup_attribute ("deprecated",
+                                    TYPE_ATTRIBUTES (TREE_TYPE (decl)));
+       }
+    }
+
+  if (attr)
+    attr = lookup_attribute ("deprecated", attr);
+
+  if (attr)
+    msg = TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr)));
+  else
+    msg = NULL;
+
+  if (DECL_P (node))
+    {
+      expanded_location xloc = expand_location (DECL_SOURCE_LOCATION (node));
+      if (msg)
+       warning (OPT_Wdeprecated_declarations,
+                "%qD is deprecated (declared at %s:%d): %s",
+                node, xloc.file, xloc.line, msg);
+      else
+       warning (OPT_Wdeprecated_declarations,
+                "%qD is deprecated (declared at %s:%d)",
+                node, xloc.file, xloc.line);
+    }
+  else if (TYPE_P (node))
+    {
+      tree what = NULL_TREE;
+      tree decl = TYPE_STUB_DECL (node);
+
+      if (TYPE_NAME (node))
+       {
+         if (TREE_CODE (TYPE_NAME (node)) == IDENTIFIER_NODE)
+           what = TYPE_NAME (node);
+         else if (TREE_CODE (TYPE_NAME (node)) == TYPE_DECL
+                  && DECL_NAME (TYPE_NAME (node)))
+           what = DECL_NAME (TYPE_NAME (node));
+       }
+
+      if (decl)
+       {
+         expanded_location xloc
+           = expand_location (DECL_SOURCE_LOCATION (decl));
+         if (what)
+           {
+             if (msg)
+               warning (OPT_Wdeprecated_declarations,
+                        "%qE is deprecated (declared at %s:%d): %s",
+                        what, xloc.file, xloc.line, msg);
+             else
+               warning (OPT_Wdeprecated_declarations,
+                        "%qE is deprecated (declared at %s:%d)", what,
+                        xloc.file, xloc.line);
+           }
+         else
+           {
+             if (msg)
+               warning (OPT_Wdeprecated_declarations,
+                        "type is deprecated (declared at %s:%d): %s",
+                        xloc.file, xloc.line, msg);
+             else
+               warning (OPT_Wdeprecated_declarations,
+                        "type is deprecated (declared at %s:%d)",
+                        xloc.file, xloc.line);
+           }
+       }
+      else
+       {
+         if (what)
+           {
+             if (msg)
+               warning (OPT_Wdeprecated_declarations, "%qE is deprecated: %s",
+                        what, msg);
+             else
+               warning (OPT_Wdeprecated_declarations, "%qE is deprecated", what);
+           }
+         else
+           {
+             if (msg)
+               warning (OPT_Wdeprecated_declarations, "type is deprecated: %s",
+                        msg);
+             else
+               warning (OPT_Wdeprecated_declarations, "type is deprecated");
+           }
+       }
+    }
+}
+
 #include "gt-tree.h"