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;
{
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;
}
void
check_for_override (tree decl, tree ctype)
{
+ bool overrides_found = false;
if (TREE_CODE (decl) == TEMPLATE_DECL)
/* In [temp.mem] we have:
/* 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.
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,
/* 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
}
else
{
+ location_t loc = input_location;
/* Avoid the non_lvalue wrapper added by fold for PLUS_EXPRs. */
STRIP_NOPS (w);
/* detect invalid field size. */
+ input_location = DECL_SOURCE_LOCATION (field);
w = cxx_constant_value (w);
+ input_location = loc;
if (TREE_CODE (w) != INTEGER_CST)
{
tree fns;
if (!CLASS_TYPE_P (t))
- return false;
+ {
+ /* 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 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
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.
&& !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
itself. */
if (TREE_CODE (instance) == VAR_DECL
&& DECL_INITIAL (instance)
+ && !type_dependent_expression_p_push (DECL_INITIAL (instance))
&& !htab_find (ht, instance))
{
tree type;
{
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))
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;
}
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"