OSDN Git Service

PR c++/48948
[pf3gnuchains/gcc-fork.git] / gcc / cp / class.c
index a31aad3..4e52b18 100644 (file)
@@ -431,8 +431,7 @@ build_base_path (enum tree_code code,
  out:
   if (null_test)
     expr = fold_build3_loc (input_location, COND_EXPR, target_type, null_test, expr,
-                       fold_build1_loc (input_location, NOP_EXPR, target_type,
-                                    integer_zero_node));
+                           build_zero_cst (target_type));
 
   return expr;
 }
@@ -1269,6 +1268,10 @@ check_bases (tree t,
 
       gcc_assert (COMPLETE_TYPE_P (basetype));
 
+      if (CLASSTYPE_FINAL (basetype))
+        error ("cannot derive from %<final%> base %qT in derived type %qT",
+               basetype, t);
+
       /* If any base class is non-literal, so is the derived class.  */
       if (!CLASSTYPE_LITERAL_P (basetype))
         CLASSTYPE_LITERAL_P (t) = false;
@@ -1858,8 +1861,7 @@ layout_vtable_decl (tree binfo, int n)
   tree atype;
   tree vtable;
 
-  atype = build_cplus_array_type (vtable_entry_type,
-                                 build_index_type (size_int (n - 1)));
+  atype = build_array_of_n_type (vtable_entry_type, n);
   layout_type (atype);
 
   /* We may have to grow the vtable.  */
@@ -2252,10 +2254,10 @@ update_vtable_entry_for_fn (tree t, tree binfo, tree fn, tree* virtuals,
        {
          tree main_binfo = TYPE_BINFO (BINFO_TYPE (b));
          tree bv = chain_index (ix, BINFO_VIRTUALS (main_binfo));
-         if (BINFO_LOST_PRIMARY_P (b))
-           lost = true;
          if (!DECL_THUNK_P (TREE_VALUE (bv)))
            break;
+         if (BINFO_LOST_PRIMARY_P (b))
+           lost = true;
        }
       first_defn = b;
     }
@@ -2455,6 +2457,7 @@ get_basefndecls (tree name, tree t)
 void
 check_for_override (tree decl, tree ctype)
 {
+  bool overrides_found = false;
   if (TREE_CODE (decl) == TEMPLATE_DECL)
     /* In [temp.mem] we have:
 
@@ -2469,14 +2472,23 @@ check_for_override (tree decl, tree ctype)
     /* Set DECL_VINDEX to a value that is neither an INTEGER_CST nor
        the error_mark_node so that we know it is an overriding
        function.  */
-    DECL_VINDEX (decl) = decl;
+    {
+      DECL_VINDEX (decl) = decl;
+      overrides_found = true;
+    }
 
   if (DECL_VIRTUAL_P (decl))
     {
       if (!DECL_VINDEX (decl))
        DECL_VINDEX (decl) = error_mark_node;
       IDENTIFIER_VIRTUAL_P (DECL_NAME (decl)) = 1;
+      if (DECL_DESTRUCTOR_P (decl))
+       TYPE_HAS_NONTRIVIAL_DESTRUCTOR (ctype) = true;
     }
+  else if (DECL_FINAL_P (decl))
+    error ("%q+#D marked final, but is not virtual", decl);
+  if (DECL_OVERRIDE_P (decl) && !overrides_found)
+    error ("%q+#D marked override, but does not override", decl);
 }
 
 /* Warn about hidden virtual functions that are not overridden in t.
@@ -2639,6 +2651,70 @@ maybe_add_class_template_decl_list (tree type, tree t, int friend_p)
                   t, CLASSTYPE_DECL_LIST (type));
 }
 
+/* This function is called from declare_virt_assop_and_dtor via
+   dfs_walk_all.
+
+   DATA is a type that direcly or indirectly inherits the base
+   represented by BINFO.  If BINFO contains a virtual assignment [copy
+   assignment or move assigment] operator or a virtual constructor,
+   declare that function in DATA if it hasn't been already declared.  */
+
+static tree
+dfs_declare_virt_assop_and_dtor (tree binfo, void *data)
+{
+  tree bv, fn, t = (tree)data;
+  tree opname = ansi_assopname (NOP_EXPR);
+
+  gcc_assert (t && CLASS_TYPE_P (t));
+  gcc_assert (binfo && TREE_CODE (binfo) == TREE_BINFO);
+
+  if (!TYPE_CONTAINS_VPTR_P (BINFO_TYPE (binfo)))
+    /* A base without a vtable needs no modification, and its bases
+       are uninteresting.  */
+    return dfs_skip_bases;
+
+  if (BINFO_PRIMARY_P (binfo))
+    /* If this is a primary base, then we have already looked at the
+       virtual functions of its vtable.  */
+    return NULL_TREE;
+
+  for (bv = BINFO_VIRTUALS (binfo); bv; bv = TREE_CHAIN (bv))
+    {
+      fn = BV_FN (bv);
+
+      if (DECL_NAME (fn) == opname)
+       {
+         if (CLASSTYPE_LAZY_COPY_ASSIGN (t))
+           lazily_declare_fn (sfk_copy_assignment, t);
+         if (CLASSTYPE_LAZY_MOVE_ASSIGN (t))
+           lazily_declare_fn (sfk_move_assignment, t);
+       }
+      else if (DECL_DESTRUCTOR_P (fn)
+              && CLASSTYPE_LAZY_DESTRUCTOR (t))
+       lazily_declare_fn (sfk_destructor, t);
+    }
+
+  return NULL_TREE;
+}
+
+/* If the class type T has a direct or indirect base that contains a
+   virtual assignment operator or a virtual destructor, declare that
+   function in T if it hasn't been already declared.  */
+
+static void
+declare_virt_assop_and_dtor (tree t)
+{
+  if (!(TYPE_POLYMORPHIC_P (t)
+       && (CLASSTYPE_LAZY_COPY_ASSIGN (t)
+           || CLASSTYPE_LAZY_MOVE_ASSIGN (t)
+           || CLASSTYPE_LAZY_DESTRUCTOR (t))))
+    return;
+
+  dfs_walk_all (TYPE_BINFO (t),
+               dfs_declare_virt_assop_and_dtor,
+               NULL, t);
+}
+
 /* Create default constructors, assignment operators, and so forth for
    the type indicated by T, if they are needed.  CANT_HAVE_CONST_CTOR,
    and CANT_HAVE_CONST_ASSIGNMENT are nonzero if, for whatever reason,
@@ -2672,20 +2748,10 @@ add_implicitly_declared_members (tree t,
   if (! TYPE_HAS_USER_CONSTRUCTOR (t))
     {
       TYPE_HAS_DEFAULT_CONSTRUCTOR (t) = 1;
-      if (TYPE_HAS_TRIVIAL_DFLT (t))
-       {
-         /* A trivial default constructor is constexpr
-            if there is nothing to initialize.  */
-         if (cxx_dialect >= cxx0x && is_really_empty_class (t))
-           TYPE_HAS_CONSTEXPR_CTOR (t) = 1;
-         CLASSTYPE_LAZY_DEFAULT_CTOR (t) = 1;
-       }
-      else if (cxx_dialect >= cxx0x)
-       /* We need to go ahead and declare this to set
-          TYPE_HAS_CONSTEXPR_CTOR.  */
-       lazily_declare_fn (sfk_constructor, t);
-      else
-       CLASSTYPE_LAZY_DEFAULT_CTOR (t) = 1;
+      CLASSTYPE_LAZY_DEFAULT_CTOR (t) = 1;
+      if (cxx_dialect >= cxx0x)
+       TYPE_HAS_CONSTEXPR_CTOR (t)
+         = synthesized_default_constructor_is_constexpr (t);
     }
 
   /* [class.ctor]
@@ -2718,34 +2784,7 @@ add_implicitly_declared_members (tree t,
 
   /* We can't be lazy about declaring functions that might override
      a virtual function from a base class.  */
-  if (TYPE_POLYMORPHIC_P (t)
-      && (CLASSTYPE_LAZY_COPY_ASSIGN (t)
-         || CLASSTYPE_LAZY_MOVE_ASSIGN (t)
-         || CLASSTYPE_LAZY_DESTRUCTOR (t)))
-    {
-      tree binfo = TYPE_BINFO (t);
-      tree base_binfo;
-      int ix;
-      tree opname = ansi_assopname (NOP_EXPR);
-      for (ix = 0; BINFO_BASE_ITERATE (binfo, ix, base_binfo); ++ix)
-       {
-         tree bv;
-         for (bv = BINFO_VIRTUALS (base_binfo); bv; bv = TREE_CHAIN (bv))
-           {
-             tree fn = BV_FN (bv);
-             if (DECL_NAME (fn) == opname)
-               {
-                 if (CLASSTYPE_LAZY_COPY_ASSIGN (t))
-                   lazily_declare_fn (sfk_copy_assignment, t);
-                 if (CLASSTYPE_LAZY_MOVE_ASSIGN (t))
-                   lazily_declare_fn (sfk_move_assignment, t);
-               }
-             else if (DECL_DESTRUCTOR_P (fn)
-                      && CLASSTYPE_LAZY_DESTRUCTOR (t))
-               lazily_declare_fn (sfk_destructor, t);
-           }
-       }
-    }
+  declare_virt_assop_and_dtor (t);
 }
 
 /* Subroutine of finish_struct_1.  Recursively count the number of fields
@@ -2809,11 +2848,14 @@ check_bitfield_decl (tree field)
     }
   else
     {
+      location_t loc = input_location;
       /* Avoid the non_lvalue wrapper added by fold for PLUS_EXPRs.  */
       STRIP_NOPS (w);
 
       /* detect invalid field size.  */
-      w = integral_constant_value (w);
+      input_location = DECL_SOURCE_LOCATION (field);
+      w = cxx_constant_value (w);
+      input_location = loc;
 
       if (TREE_CODE (w) != INTEGER_CST)
        {
@@ -4338,6 +4380,18 @@ type_has_user_provided_default_constructor (tree t)
   return false;
 }
 
+/* Returns true iff for class T, a synthesized default constructor
+   would be constexpr.  */
+
+bool
+synthesized_default_constructor_is_constexpr (tree t)
+{
+  /* A defaulted default constructor is constexpr
+     if there is nothing to initialize.  */
+  /* FIXME adjust for non-static data member initializers.  */
+  return is_really_empty_class (t);
+}
+
 /* Returns true iff class T has a constexpr default constructor.  */
 
 bool
@@ -4346,8 +4400,14 @@ type_has_constexpr_default_constructor (tree t)
   tree fns;
 
   if (!CLASS_TYPE_P (t))
-    return false;
-  fns = get_default_ctor (t);
+    {
+      /* The caller should have stripped an enclosing array.  */
+      gcc_assert (TREE_CODE (t) != ARRAY_TYPE);
+      return false;
+    }
+  if (CLASSTYPE_LAZY_DEFAULT_CTOR (t))
+    return synthesized_default_constructor_is_constexpr (t);
+  fns = locate_ctor (t);
   return (fns && DECL_DECLARED_CONSTEXPR_P (fns));
 }
 
@@ -4410,6 +4470,27 @@ type_has_move_assign (tree t)
   return false;
 }
 
+/* Nonzero if we need to build up a constructor call when initializing an
+   object of this class, either because it has a user-provided constructor
+   or because it doesn't have a default constructor (so we need to give an
+   error if no initializer is provided).  Use TYPE_NEEDS_CONSTRUCTING when
+   what you care about is whether or not an object can be produced by a
+   constructor (e.g. so we don't set TREE_READONLY on const variables of
+   such type); use this function when what you care about is whether or not
+   to try to call a constructor to create an object.  The latter case is
+   the former plus some cases of constructors that cannot be called.  */
+
+bool
+type_build_ctor_call (tree t)
+{
+  tree inner;
+  if (TYPE_NEEDS_CONSTRUCTING (t))
+    return true;
+  inner = strip_array_types (t);
+  return (CLASS_TYPE_P (inner) && !TYPE_HAS_DEFAULT_CONSTRUCTOR (inner)
+         && !ANON_AGGR_TYPE_P (inner));
+}
+
 /* Remove all zero-width bit-fields from T.  */
 
 static void
@@ -4501,6 +4582,8 @@ type_requires_array_cookie (tree type)
 static void
 finalize_literal_type_property (tree t)
 {
+  tree fn;
+
   if (cxx_dialect < cxx0x
       || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t)
       /* FIXME These constraints seem unnecessary; remove from standard.
@@ -4511,18 +4594,17 @@ finalize_literal_type_property (tree t)
           && !TYPE_HAS_CONSTEXPR_CTOR (t))
     CLASSTYPE_LITERAL_P (t) = false;
 
-  if (!CLASSTYPE_LITERAL_P (t) && !CLASSTYPE_TEMPLATE_INSTANTIATION (t))
-    {
-      tree fn;
-      for (fn = TYPE_METHODS (t); fn; fn = DECL_CHAIN (fn))
-       if (DECL_DECLARED_CONSTEXPR_P (fn)
-           && DECL_NONSTATIC_MEMBER_FUNCTION_P (fn)
-           && !DECL_CONSTRUCTOR_P (fn))
-         {
-           error ("enclosing class of %q+D is not a literal type", fn);
-           DECL_DECLARED_CONSTEXPR_P (fn) = false;
-         }
-    }
+  if (!CLASSTYPE_LITERAL_P (t))
+    for (fn = TYPE_METHODS (t); fn; fn = DECL_CHAIN (fn))
+      if (DECL_DECLARED_CONSTEXPR_P (fn)
+         && TREE_CODE (fn) != TEMPLATE_DECL
+         && DECL_NONSTATIC_MEMBER_FUNCTION_P (fn)
+         && !DECL_CONSTRUCTOR_P (fn))
+       {
+         DECL_DECLARED_CONSTEXPR_P (fn) = false;
+         if (!DECL_TEMPLATE_INFO (fn))
+           error ("enclosing class of %q+#D is not a literal type", fn);
+       }
 }
 
 /* Check the validity of the bases and members declared in T.  Add any
@@ -5897,6 +5979,7 @@ fixed_type_or_null (tree instance, int *nonnull, int *cdtorp)
             itself.  */
          if (TREE_CODE (instance) == VAR_DECL
              && DECL_INITIAL (instance)
+             && !type_dependent_expression_p_push (DECL_INITIAL (instance))
              && !htab_find (ht, instance))
            {
              tree type;
@@ -5937,7 +6020,17 @@ resolves_to_fixed_type_p (tree instance, int* nonnull)
 {
   tree t = TREE_TYPE (instance);
   int cdtorp = 0;
-  tree fixed = fixed_type_or_null (instance, nonnull, &cdtorp);
+  tree fixed;
+
+  if (processing_template_decl)
+    {
+      /* In a template we only care about the type of the result.  */
+      if (nonnull)
+       *nonnull = true;
+      return true;
+    }
+
+  fixed = fixed_type_or_null (instance, nonnull, &cdtorp);
   if (fixed == NULL_TREE)
     return 0;
   if (POINTER_TYPE_P (t))
@@ -6471,14 +6564,7 @@ resolve_address_of_overloaded_function (tree target_type,
                 DECL_NAME (OVL_CURRENT (overload)),
                 target_type);
 
-         /* print_candidates expects a chain with the functions in
-            TREE_VALUE slots, so we cons one up here (we're losing anyway,
-            so why be clever?).  */
-         for (; overload; overload = OVL_NEXT (overload))
-           matches = tree_cons (NULL_TREE, OVL_CURRENT (overload),
-                                matches);
-
-         print_candidates (matches);
+         print_candidates (overload);
        }
       return error_mark_node;
     }
@@ -6765,7 +6851,7 @@ build_self_reference (void)
   DECL_CONTEXT (value) = current_class_type;
   DECL_ARTIFICIAL (value) = 1;
   SET_DECL_SELF_REFERENCE_P (value);
-  cp_set_underlying_type (value);
+  set_underlying_type (value);
 
   if (processing_template_decl)
     value = push_template_decl (value);
@@ -6825,13 +6911,11 @@ contains_empty_class_p (tree type)
 }
 
 /* Returns true if TYPE contains no actual data, just various
-   possible combinations of empty classes.  */
+   possible combinations of empty classes and possibly a vptr.  */
 
 bool
 is_really_empty_class (tree type)
 {
-  if (is_empty_class (type))
-    return true;
   if (CLASS_TYPE_P (type))
     {
       tree field;
@@ -6839,6 +6923,11 @@ is_really_empty_class (tree type)
       tree base_binfo;
       int i;
 
+      /* CLASSTYPE_EMPTY_P isn't set properly until the class is actually laid
+        out, but we'd like to be able to check this before then.  */
+      if (COMPLETE_TYPE_P (type) && is_empty_class (type))
+       return true;
+
       for (binfo = TYPE_BINFO (type), i = 0;
           BINFO_BASE_ITERATE (binfo, i, base_binfo); ++i)
        if (!is_really_empty_class (BINFO_TYPE (base_binfo)))
@@ -7295,8 +7384,8 @@ build_vtt (tree t)
     return;
 
   /* Figure out the type of the VTT.  */
-  type = build_index_type (size_int (VEC_length (constructor_elt, inits) - 1));
-  type = build_cplus_array_type (const_ptr_type_node, type);
+  type = build_array_of_n_type (const_ptr_type_node,
+                               VEC_length (constructor_elt, inits));
 
   /* Now, build the VTT object itself.  */
   vtt = build_vtable (t, mangle_vtt_for_type (t), type);
@@ -7551,8 +7640,8 @@ build_ctor_vtbl_group (tree binfo, tree t)
     }
 
   /* Figure out the type of the construction vtable.  */
-  type = build_index_type (size_int (VEC_length (constructor_elt, v) - 1));
-  type = build_cplus_array_type (vtable_entry_type, type);
+  type = build_array_of_n_type (vtable_entry_type,
+                               VEC_length (constructor_elt, v));
   layout_type (type);
   TREE_TYPE (vtbl) = type;
   DECL_SIZE (vtbl) = DECL_SIZE_UNIT (vtbl) = NULL_TREE;
@@ -8261,8 +8350,7 @@ add_vcall_offset (tree orig_fn, tree binfo, vtbl_init_data *vid)
       /* Find the overriding function.  */
       fn = find_final_overrider (vid->rtti_binfo, binfo, orig_fn);
       if (fn == error_mark_node)
-       vcall_offset = build1 (NOP_EXPR, vtable_entry_type,
-                              integer_zero_node);
+       vcall_offset = build_zero_cst (vtable_entry_type);
       else
        {
          base = TREE_VALUE (fn);
@@ -8332,34 +8420,4 @@ build_rtti_vtbl_entries (tree binfo, vtbl_init_data* vid)
   CONSTRUCTOR_APPEND_ELT (vid->inits, NULL_TREE, init);
 }
 
-/* Fold a OBJ_TYPE_REF expression to the address of a function.
-   KNOWN_TYPE carries the true type of OBJ_TYPE_REF_OBJECT(REF).  */
-
-tree
-cp_fold_obj_type_ref (tree ref, tree known_type)
-{
-  HOST_WIDE_INT index = tree_low_cst (OBJ_TYPE_REF_TOKEN (ref), 1);
-  HOST_WIDE_INT i = 0;
-  tree v = BINFO_VIRTUALS (TYPE_BINFO (known_type));
-  tree fndecl;
-
-  while (i != index)
-    {
-      i += (TARGET_VTABLE_USES_DESCRIPTORS
-           ? TARGET_VTABLE_USES_DESCRIPTORS : 1);
-      v = TREE_CHAIN (v);
-    }
-
-  fndecl = BV_FN (v);
-
-#ifdef ENABLE_CHECKING
-  gcc_assert (tree_int_cst_equal (OBJ_TYPE_REF_TOKEN (ref),
-                                 DECL_VINDEX (fndecl)));
-#endif
-
-  cgraph_node (fndecl)->local.vtable_method = true;
-
-  return build_address (fndecl);
-}
-
 #include "gt-cp-class.h"