/* Functions related to building classes and their related objects.
Copyright (C) 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009
Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
if (!want_pointer)
/* This must happen before the call to save_expr. */
- expr = build_unary_op (ADDR_EXPR, expr, 0);
+ expr = cp_build_unary_op (ADDR_EXPR, expr, 0, tf_warning_or_error);
offset = BINFO_OFFSET (binfo);
fixed_type_p = resolves_to_fixed_type_p (expr, &nonnull);
/* Do we need to look in the vtable for the real offset? */
virtual_access = (v_binfo && fixed_type_p <= 0);
+ /* Don't bother with the calculations inside sizeof; they'll ICE if the
+ source type is incomplete and the pointer value doesn't matter. */
+ if (skip_evaluation)
+ {
+ expr = build_nop (build_pointer_type (target_type), expr);
+ if (!want_pointer)
+ expr = build_indirect_ref (EXPR_LOCATION (expr), expr, NULL);
+ return expr;
+ }
+
/* Do we need to check for a null pointer? */
if (want_pointer && !nonnull)
{
interesting to the optimizers anyway. */
&& !has_empty)
{
- expr = build_indirect_ref (expr, NULL);
+ expr = cp_build_indirect_ref (expr, NULL, tf_warning_or_error);
expr = build_simple_base_path (expr, binfo);
if (want_pointer)
expr = build_address (expr);
t = TREE_TYPE (TYPE_VFIELD (current_class_type));
t = build_pointer_type (t);
v_offset = convert (t, current_vtt_parm);
- v_offset = build_indirect_ref (v_offset, NULL);
+ v_offset = cp_build_indirect_ref (v_offset, NULL,
+ tf_warning_or_error);
}
else
- v_offset = build_vfield_ref (build_indirect_ref (expr, NULL),
+ v_offset = build_vfield_ref (cp_build_indirect_ref (expr, NULL,
+ tf_warning_or_error),
TREE_TYPE (TREE_TYPE (expr)));
v_offset = build2 (POINTER_PLUS_EXPR, TREE_TYPE (v_offset),
v_offset = build1 (NOP_EXPR,
build_pointer_type (ptrdiff_type_node),
v_offset);
- v_offset = build_indirect_ref (v_offset, NULL);
+ v_offset = cp_build_indirect_ref (v_offset, NULL, tf_warning_or_error);
TREE_CONSTANT (v_offset) = 1;
- TREE_INVARIANT (v_offset) = 1;
offset = convert_to_integer (ptrdiff_type_node,
size_diffop (offset,
null_test = NULL;
if (!want_pointer)
- expr = build_indirect_ref (expr, NULL);
+ expr = cp_build_indirect_ref (expr, NULL, tf_warning_or_error);
out:
if (null_test)
in the back end. */
temp = unary_complex_lvalue (ADDR_EXPR, expr);
if (temp)
- expr = build_indirect_ref (temp, NULL);
+ expr = cp_build_indirect_ref (temp, NULL, tf_warning_or_error);
return expr;
}
when processing a template because they do not handle C++-specific
trees. */
gcc_assert (!processing_template_decl);
- expr = build_unary_op (ADDR_EXPR, expr, /*noconvert=*/1);
+ expr = cp_build_unary_op (ADDR_EXPR, expr, /*noconvert=*/1,
+ tf_warning_or_error);
if (!integer_zerop (BINFO_OFFSET (base)))
expr = fold_build2 (POINTER_PLUS_EXPR, pointer_type, expr,
fold_convert (sizetype, BINFO_OFFSET (base)));
if (!vtbl)
vtbl = build_vfield_ref (instance, basetype);
- assemble_external (vtbl);
- aref = build_array_ref (vtbl, idx);
+ aref = build_array_ref (vtbl, idx, input_location);
TREE_CONSTANT (aref) |= TREE_CONSTANT (vtbl) && TREE_CONSTANT (idx);
- TREE_INVARIANT (aref) = TREE_CONSTANT (aref);
return aref;
}
{
tree aref;
- aref = build_vtbl_ref_1 (build_indirect_ref (instance_ptr, 0), idx);
+ aref = build_vtbl_ref_1 (cp_build_indirect_ref (instance_ptr, 0,
+ tf_warning_or_error),
+ idx);
/* When using function descriptors, the address of the
vtable entry is treated as a function pointer. */
if (TARGET_VTABLE_USES_DESCRIPTORS)
aref = build1 (NOP_EXPR, TREE_TYPE (aref),
- build_unary_op (ADDR_EXPR, aref, /*noconvert=*/1));
+ cp_build_unary_op (ADDR_EXPR, aref, /*noconvert=*/1,
+ tf_warning_or_error));
/* Remember this as a method reference, for later devirtualization. */
aref = build3 (OBJ_TYPE_REF, TREE_TYPE (aref), aref, instance_ptr, idx);
CLASSTYPE_METHOD_VEC (type) = method_vec;
}
- /* Maintain TYPE_HAS_CONSTRUCTOR, etc. */
+ /* Maintain TYPE_HAS_USER_CONSTRUCTOR, etc. */
grok_special_member_properties (method);
/* Constructors and destructors go in special slots. */
coming from the using class in overload resolution. */
if (! DECL_STATIC_FUNCTION_P (fn)
&& ! DECL_STATIC_FUNCTION_P (method)
+ && TREE_TYPE (TREE_VALUE (parms1)) != error_mark_node
+ && TREE_TYPE (TREE_VALUE (parms2)) != error_mark_node
&& (TYPE_QUALS (TREE_TYPE (TREE_VALUE (parms1)))
!= TYPE_QUALS (TREE_TYPE (TREE_VALUE (parms2)))))
continue;
BINFO_VIRTUALS (type_binfo) = BINFO_VIRTUALS (primary);
}
}
-\f
-/* Set memoizing fields and bits of T (and its variants) for later
- use. */
-static void
-finish_struct_bits (tree t)
+/* Update the variant types of T. */
+
+void
+fixup_type_variants (tree t)
{
tree variants;
- /* Fix up variants (if any). */
+ if (!t)
+ return;
+
for (variants = TYPE_NEXT_VARIANT (t);
variants;
variants = TYPE_NEXT_VARIANT (variants))
{
/* These fields are in the _TYPE part of the node, not in
the TYPE_LANG_SPECIFIC component, so they are not shared. */
- TYPE_HAS_CONSTRUCTOR (variants) = TYPE_HAS_CONSTRUCTOR (t);
+ TYPE_HAS_USER_CONSTRUCTOR (variants) = TYPE_HAS_USER_CONSTRUCTOR (t);
TYPE_NEEDS_CONSTRUCTING (variants) = TYPE_NEEDS_CONSTRUCTING (t);
TYPE_HAS_NONTRIVIAL_DESTRUCTOR (variants)
= TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t);
/* All variants of a class have the same attributes. */
TYPE_ATTRIBUTES (variants) = TYPE_ATTRIBUTES (t);
}
+}
+
+\f
+/* Set memoizing fields and bits of T (and its variants) for later
+ use. */
+
+static void
+finish_struct_bits (tree t)
+{
+ /* Fix up variants (if any). */
+ fixup_type_variants (t);
if (BINFO_N_BASE_BINFOS (TYPE_BINFO (t)) && TYPE_POLYMORPHIC_P (t))
/* For a class w/o baseclasses, 'finish_struct' has set
DECL_MODE (TYPE_MAIN_DECL (t)) = BLKmode;
for (variants = t; variants; variants = TYPE_NEXT_VARIANT (variants))
{
- TYPE_MODE (variants) = BLKmode;
+ SET_TYPE_MODE (variants, BLKmode);
TREE_ADDRESSABLE (variants) = 1;
}
}
return;
}
- if (TYPE_HAS_CONSTRUCTOR (t)
+ /* Warn about classes that have private constructors and no friends. */
+ if (TYPE_HAS_USER_CONSTRUCTOR (t)
/* Implicitly generated constructors are always public. */
&& (!CLASSTYPE_LAZY_DEFAULT_CTOR (t)
|| !CLASSTYPE_LAZY_COPY_CTOR (t)))
if (TREE_CODE (elt) != FIELD_DECL)
{
if (is_union)
- pedwarn ("%q+#D invalid; an anonymous union can "
- "only have non-static data members", elt);
+ permerror (input_location, "%q+#D invalid; an anonymous union can "
+ "only have non-static data members", elt);
else
- pedwarn ("%q+#D invalid; an anonymous struct can "
- "only have non-static data members", elt);
+ permerror (input_location, "%q+#D invalid; an anonymous struct can "
+ "only have non-static data members", elt);
continue;
}
if (TREE_PRIVATE (elt))
{
if (is_union)
- pedwarn ("private member %q+#D in anonymous union", elt);
+ permerror (input_location, "private member %q+#D in anonymous union", elt);
else
- pedwarn ("private member %q+#D in anonymous struct", elt);
+ permerror (input_location, "private member %q+#D in anonymous struct", elt);
}
else if (TREE_PROTECTED (elt))
{
if (is_union)
- pedwarn ("protected member %q+#D in anonymous union", elt);
+ permerror (input_location, "protected member %q+#D in anonymous union", elt);
else
- pedwarn ("protected member %q+#D in anonymous struct", elt);
+ permerror (input_location, "protected member %q+#D in anonymous struct", elt);
}
TREE_PRIVATE (elt) = TREE_PRIVATE (field);
}
}
- /* Default constructor. */
- if (! TYPE_HAS_CONSTRUCTOR (t))
+ /* [class.ctor]
+
+ If there is no user-declared constructor for a class, a default
+ constructor is implicitly declared. */
+ if (! TYPE_HAS_USER_CONSTRUCTOR (t))
{
TYPE_HAS_DEFAULT_CONSTRUCTOR (t) = 1;
CLASSTYPE_LAZY_DEFAULT_CTOR (t) = 1;
}
- /* Copy constructor. */
+ /* [class.ctor]
+
+ If a class definition does not explicitly declare a copy
+ constructor, one is declared implicitly. */
if (! TYPE_HAS_INIT_REF (t) && ! TYPE_FOR_JAVA (t))
{
TYPE_HAS_INIT_REF (t) = 1;
TYPE_HAS_CONST_INIT_REF (t) = !cant_have_const_cctor;
CLASSTYPE_LAZY_COPY_CTOR (t) = 1;
- TYPE_HAS_CONSTRUCTOR (t) = 1;
}
/* If there is no assignment operator, one will be created if and
warning (0, "width of %q+D exceeds its type", field);
else if (TREE_CODE (type) == ENUMERAL_TYPE
&& (0 > compare_tree_int (w,
- min_precision (TYPE_MIN_VALUE (type),
- TYPE_UNSIGNED (type)))
+ tree_int_cst_min_precision
+ (TYPE_MIN_VALUE (type),
+ TYPE_UNSIGNED (type)))
|| 0 > compare_tree_int (w,
- min_precision
+ tree_int_cst_min_precision
(TYPE_MAX_VALUE (type),
TYPE_UNSIGNED (type)))))
warning (0, "%q+D is too small to hold all values of %q#T", field, type);
if (TREE_PRIVATE (x) || TREE_PROTECTED (x))
CLASSTYPE_NON_AGGREGATE (t) = 1;
- /* If this is of reference type, check if it needs an init.
- Also do a little ANSI jig if necessary. */
+ /* If this is of reference type, check if it needs an init. */
if (TREE_CODE (type) == REFERENCE_TYPE)
{
CLASSTYPE_NON_POD_P (t) = 1;
only way to initialize nonstatic const and reference
members. */
TYPE_HAS_COMPLEX_ASSIGN_REF (t) = 1;
-
- if (! TYPE_HAS_CONSTRUCTOR (t) && CLASSTYPE_NON_AGGREGATE (t)
- && extra_warnings)
- warning (OPT_Wextra, "non-static reference %q+#D in class without a constructor", x);
}
type = strip_array_types (type);
x);
cant_pack = 1;
}
- else if (TYPE_ALIGN (TREE_TYPE (x)) > BITS_PER_UNIT)
+ else if (DECL_C_BIT_FIELD (x)
+ || TYPE_ALIGN (TREE_TYPE (x)) > BITS_PER_UNIT)
DECL_PACKED (x) = 1;
}
only way to initialize nonstatic const and reference
members. */
TYPE_HAS_COMPLEX_ASSIGN_REF (t) = 1;
-
- if (! TYPE_HAS_CONSTRUCTOR (t) && CLASSTYPE_NON_AGGREGATE (t)
- && extra_warnings)
- warning (OPT_Wextra, "non-static const member %q+#D in class without a constructor", x);
}
/* A field that is pseudo-const makes the structure likewise. */
else if (CLASS_TYPE_P (type))
/* Core issue 80: A nonstatic data member is required to have a
different name from the class iff the class has a
- user-defined constructor. */
- if (constructor_name_p (DECL_NAME (x), t) && TYPE_HAS_CONSTRUCTOR (t))
- pedwarn ("field %q+#D with same name as class", x);
+ user-declared constructor. */
+ if (constructor_name_p (DECL_NAME (x), t)
+ && TYPE_HAS_USER_CONSTRUCTOR (t))
+ permerror (input_location, "field %q+#D with same name as class", x);
/* We set DECL_C_BIT_FIELD in grokbitfield.
If the type and width are valid, we'll also set DECL_BIT_FIELD. */
This seems enough for practical purposes. */
if (warn_ecpp
&& has_pointers
- && TYPE_HAS_CONSTRUCTOR (t)
+ && TYPE_HAS_USER_CONSTRUCTOR (t)
&& TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t)
&& !(TYPE_HAS_INIT_REF (t) && TYPE_HAS_ASSIGN_REF (t)))
{
if (DECL_PURE_VIRTUAL_P (x))
VEC_safe_push (tree, gc, CLASSTYPE_PURE_VIRTUALS (t), x);
}
- /* All user-declared destructors are non-trivial. */
- if (DECL_DESTRUCTOR_P (x))
+ /* All user-provided destructors are non-trivial. */
+ if (DECL_DESTRUCTOR_P (x) && !DECL_DEFAULTED_FN (x))
TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) = 1;
}
}
clone_function_decl (OVL_CURRENT (fns), /*update_method_vec_p=*/1);
}
+/* Returns true iff class T has a user-defined constructor other than
+ the default constructor. */
+
+bool
+type_has_user_nondefault_constructor (tree t)
+{
+ tree fns;
+
+ if (!TYPE_HAS_USER_CONSTRUCTOR (t))
+ return false;
+
+ for (fns = CLASSTYPE_CONSTRUCTORS (t); fns; fns = OVL_NEXT (fns))
+ {
+ tree fn = OVL_CURRENT (fns);
+ if (!DECL_ARTIFICIAL (fn)
+ && (TREE_CODE (fn) == TEMPLATE_DECL
+ || (skip_artificial_parms_for (fn, DECL_ARGUMENTS (fn))
+ != NULL_TREE)))
+ return true;
+ }
+
+ return false;
+}
+
+/* Returns true iff FN is a user-provided function, i.e. user-declared
+ and not defaulted at its first declaration. */
+
+static bool
+user_provided_p (tree fn)
+{
+ if (TREE_CODE (fn) == TEMPLATE_DECL)
+ return true;
+ else
+ return (!DECL_ARTIFICIAL (fn)
+ && !(DECL_DEFAULTED_FN (fn)
+ && DECL_INITIALIZED_IN_CLASS_P (fn)));
+}
+
+/* Returns true iff class T has a user-provided constructor. */
+
+bool
+type_has_user_provided_constructor (tree t)
+{
+ tree fns;
+
+ if (!CLASS_TYPE_P (t))
+ return false;
+
+ if (!TYPE_HAS_USER_CONSTRUCTOR (t))
+ return false;
+
+ /* This can happen in error cases; avoid crashing. */
+ if (!CLASSTYPE_METHOD_VEC (t))
+ return false;
+
+ for (fns = CLASSTYPE_CONSTRUCTORS (t); fns; fns = OVL_NEXT (fns))
+ if (user_provided_p (OVL_CURRENT (fns)))
+ return true;
+
+ return false;
+}
+
+/* Returns true iff class T has a user-provided default constructor. */
+
+bool
+type_has_user_provided_default_constructor (tree t)
+{
+ tree fns, args;
+
+ if (!TYPE_HAS_USER_CONSTRUCTOR (t))
+ return false;
+
+ for (fns = CLASSTYPE_CONSTRUCTORS (t); fns; fns = OVL_NEXT (fns))
+ {
+ tree fn = OVL_CURRENT (fns);
+ if (TREE_CODE (fn) == FUNCTION_DECL
+ && user_provided_p (fn))
+ {
+ args = FUNCTION_FIRST_USER_PARMTYPE (fn);
+ while (args && TREE_PURPOSE (args))
+ args = TREE_CHAIN (args);
+ if (!args || args == void_list_node)
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/* Returns true if FN can be explicitly defaulted. */
+
+bool
+defaultable_fn_p (tree fn)
+{
+ if (DECL_CONSTRUCTOR_P (fn))
+ {
+ if (FUNCTION_FIRST_USER_PARMTYPE (fn) == void_list_node)
+ return true;
+ else if (copy_fn_p (fn) > 0
+ && (TREE_CHAIN (FUNCTION_FIRST_USER_PARMTYPE (fn))
+ == void_list_node))
+ return true;
+ else
+ return false;
+ }
+ else if (DECL_DESTRUCTOR_P (fn))
+ return true;
+ else if (DECL_ASSIGNMENT_OPERATOR_P (fn)
+ && DECL_OVERLOADED_OPERATOR_P (fn) == NOP_EXPR)
+ return copy_fn_p (fn);
+ else
+ return false;
+}
+
/* Remove all zero-width bit-fields from T. */
static void
second_parm = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (fn)));
if (second_parm == void_list_node)
return false;
+ /* Do not consider this function if its second argument is an
+ ellipsis. */
+ if (!second_parm)
+ continue;
/* Otherwise, if we have a two-argument function and the second
argument is `size_t', it will be the usual deallocation
function -- unless there is one-argument function, too. */
should take a non-const reference argument. */
int no_const_asn_ref;
tree access_decls;
+ bool saved_complex_asn_ref;
+ bool saved_nontrivial_dtor;
/* By default, we use const reference arguments and generate default
constructors. */
/* Check all the method declarations. */
check_methods (t);
+ /* Save the initial values of these flags which only indicate whether
+ or not the class has user-provided functions. As we analyze the
+ bases and members we can set these flags for other reasons. */
+ saved_complex_asn_ref = TYPE_HAS_COMPLEX_ASSIGN_REF (t);
+ saved_nontrivial_dtor = TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t);
+
/* Check all the data member declarations. We cannot call
check_field_decls until we have called check_bases check_methods,
as check_field_decls depends on TYPE_HAS_NONTRIVIAL_DESTRUCTOR
/* Do some bookkeeping that will guide the generation of implicitly
declared member functions. */
- TYPE_HAS_COMPLEX_INIT_REF (t)
- |= (TYPE_HAS_INIT_REF (t) || TYPE_CONTAINS_VPTR_P (t));
+ TYPE_HAS_COMPLEX_INIT_REF (t) |= TYPE_CONTAINS_VPTR_P (t);
+ /* We need to call a constructor for this class if it has a
+ user-provided constructor, or if the default constructor is going
+ to initialize the vptr. (This is not an if-and-only-if;
+ TYPE_NEEDS_CONSTRUCTING is set elsewhere if bases or members
+ themselves need constructing.) */
TYPE_NEEDS_CONSTRUCTING (t)
- |= (TYPE_HAS_CONSTRUCTOR (t) || TYPE_CONTAINS_VPTR_P (t));
+ |= (type_has_user_provided_constructor (t) || TYPE_CONTAINS_VPTR_P (t));
+ /* [dcl.init.aggr]
+
+ An aggregate is an array or a class with no user-provided
+ constructors ... and no virtual functions.
+
+ Again, other conditions for being an aggregate are checked
+ elsewhere. */
CLASSTYPE_NON_AGGREGATE (t)
- |= (TYPE_HAS_CONSTRUCTOR (t) || TYPE_POLYMORPHIC_P (t));
+ |= (type_has_user_provided_constructor (t) || TYPE_POLYMORPHIC_P (t));
CLASSTYPE_NON_POD_P (t)
|= (CLASSTYPE_NON_AGGREGATE (t)
- || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t)
- || TYPE_HAS_ASSIGN_REF (t));
- TYPE_HAS_COMPLEX_ASSIGN_REF (t)
- |= TYPE_HAS_ASSIGN_REF (t) || TYPE_CONTAINS_VPTR_P (t);
- TYPE_HAS_COMPLEX_DFLT (t)
- |= (TYPE_HAS_DEFAULT_CONSTRUCTOR (t) || TYPE_CONTAINS_VPTR_P (t));
+ || saved_nontrivial_dtor || saved_complex_asn_ref);
+ TYPE_HAS_COMPLEX_ASSIGN_REF (t) |= TYPE_CONTAINS_VPTR_P (t);
+ TYPE_HAS_COMPLEX_DFLT (t) |= TYPE_CONTAINS_VPTR_P (t);
+
+ /* If the class has no user-declared constructor, but does have
+ non-static const or reference data members that can never be
+ initialized, issue a warning. */
+ if (warn_uninitialized
+ /* Classes with user-declared constructors are presumed to
+ initialize these members. */
+ && !TYPE_HAS_USER_CONSTRUCTOR (t)
+ /* Aggregates can be initialized with brace-enclosed
+ initializers. */
+ && CLASSTYPE_NON_AGGREGATE (t))
+ {
+ tree field;
+
+ for (field = TYPE_FIELDS (t); field; field = TREE_CHAIN (field))
+ {
+ tree type;
+
+ if (TREE_CODE (field) != FIELD_DECL)
+ continue;
+
+ type = TREE_TYPE (field);
+ if (TREE_CODE (type) == REFERENCE_TYPE)
+ warning (OPT_Wuninitialized, "non-static reference %q+#D "
+ "in class without a constructor", field);
+ else if (CP_TYPE_CONST_P (type)
+ && (!CLASS_TYPE_P (type)
+ || !TYPE_HAS_DEFAULT_CONSTRUCTOR (type)))
+ warning (OPT_Wuninitialized, "non-static const member %q+#D "
+ "in class without a constructor", field);
+ }
+ }
/* Synthesize any needed methods. */
add_implicitly_declared_members (t,
must be converted to the type given the bitfield here. */
if (DECL_C_BIT_FIELD (field))
{
- tree ftype;
unsigned HOST_WIDE_INT width;
- ftype = TREE_TYPE (field);
+ tree ftype = TREE_TYPE (field);
width = tree_low_cst (DECL_SIZE (field), /*unsignedp=*/1);
if (width != TYPE_PRECISION (ftype))
- TREE_TYPE (field)
- = c_build_bitfield_integer_type (width,
- TYPE_UNSIGNED (ftype));
+ {
+ TREE_TYPE (field)
+ = c_build_bitfield_integer_type (width,
+ TYPE_UNSIGNED (ftype));
+ TREE_TYPE (field)
+ = cp_build_qualified_type (TREE_TYPE (field),
+ TYPE_QUALS (ftype));
+ }
}
/* If we needed additional padding after this field, add it
remove_zero_width_bit_fields (t);
/* Create the version of T used for virtual bases. We do not use
- make_aggr_type for this version; this is an artificial type. For
+ make_class_type for this version; this is an artificial type. For
a POD type, we just reuse T. */
if (CLASSTYPE_NON_POD_P (t) || CLASSTYPE_EMPTY_P (t))
{
if (COMPLETE_TYPE_P (t))
{
- gcc_assert (IS_AGGR_TYPE (t));
+ gcc_assert (MAYBE_CLASS_TYPE_P (t));
error ("redefinition of %q#T", t);
popclass ();
return;
return NULL_TREE;
- case NOP_EXPR:
- case CONVERT_EXPR:
+ CASE_CONVERT:
return RECUR (TREE_OPERAND (instance, 0));
case ADDR_EXPR:
case VAR_DECL:
case FIELD_DECL:
if (TREE_CODE (TREE_TYPE (instance)) == ARRAY_TYPE
- && IS_AGGR_TYPE (TREE_TYPE (TREE_TYPE (instance))))
+ && MAYBE_CLASS_TYPE_P (TREE_TYPE (TREE_TYPE (instance))))
{
if (nonnull)
*nonnull = 1;
case TARGET_EXPR:
case PARM_DECL:
case RESULT_DECL:
- if (IS_AGGR_TYPE (TREE_TYPE (instance)))
+ if (MAYBE_CLASS_TYPE_P (TREE_TYPE (instance)))
{
if (nonnull)
*nonnull = 1;
{
int i;
+ if (!CLASS_TYPE_P (t))
+ return false;
+
/* We start looking from 1 because entry 0 is from global scope,
and has no type. */
for (i = current_class_depth; i > 0; --i)
control of FLAGS. Permit pointers to member function if FLAGS
permits. If TEMPLATE_ONLY, the name of the overloaded function was
a template-id, and EXPLICIT_TARGS are the explicitly provided
- template arguments. If OVERLOAD is for one or more member
- functions, then ACCESS_PATH is the base path used to reference
- those member functions. */
+ template arguments.
+
+ If OVERLOAD is for one or more member functions, then ACCESS_PATH
+ is the base path used to reference those member functions. If
+ TF_NO_ACCESS_CONTROL is not set in FLAGS, and the address is
+ resolved to a member function, access checks will be performed and
+ errors issued if appropriate. */
static tree
resolve_address_of_overloaded_function (tree target_type,
}
else if (TREE_CHAIN (matches))
{
- /* There were too many matches. */
+ /* There were too many matches. First check if they're all
+ the same function. */
+ tree match;
- if (flags & tf_error)
+ fn = TREE_PURPOSE (matches);
+ for (match = TREE_CHAIN (matches); match; match = TREE_CHAIN (match))
+ if (!decls_match (fn, TREE_PURPOSE (matches)))
+ break;
+
+ if (match)
{
- tree match;
+ if (flags & tf_error)
+ {
+ error ("converting overloaded function %qD to type %q#T is ambiguous",
+ DECL_NAME (OVL_FUNCTION (overload)),
+ target_type);
- error ("converting overloaded function %qD to type %q#T is ambiguous",
- DECL_NAME (OVL_FUNCTION (overload)),
- target_type);
+ /* Since print_candidates expects the functions in the
+ TREE_VALUE slot, we flip them here. */
+ for (match = matches; match; match = TREE_CHAIN (match))
+ TREE_VALUE (match) = TREE_PURPOSE (match);
- /* Since print_candidates expects the functions in the
- TREE_VALUE slot, we flip them here. */
- for (match = matches; match; match = TREE_CHAIN (match))
- TREE_VALUE (match) = TREE_PURPOSE (match);
+ print_candidates (matches);
+ }
- print_candidates (matches);
+ return error_mark_node;
}
-
- return error_mark_node;
}
/* Good, exactly one match. Now, convert it to the correct type. */
if (!(flags & tf_error))
return error_mark_node;
- pedwarn ("assuming pointer to member %qD", fn);
+ permerror (input_location, "assuming pointer to member %qD", fn);
if (!explained)
{
- pedwarn ("(a pointer to member can only be formed with %<&%E%>)", fn);
+ inform (input_location, "(a pointer to member can only be formed with %<&%E%>)", fn);
explained = 1;
}
}
function will be marked as used at this point. */
if (!(flags & tf_conv))
{
+ /* Make =delete work with SFINAE. */
+ if (DECL_DELETED_FN (fn) && !(flags & tf_error))
+ return error_mark_node;
+
mark_used (fn);
- /* We could not check access when this expression was originally
- created since we did not know at that time to which function
- the expression referred. */
- if (DECL_FUNCTION_MEMBER_P (fn))
- {
- gcc_assert (access_path);
- perform_or_defer_access_check (access_path, fn, fn);
- }
+ }
+
+ /* We could not check access to member functions when this
+ expression was originally created since we did not know at that
+ time to which function the expression referred. */
+ if (!(flags & tf_no_access_control)
+ && DECL_FUNCTION_MEMBER_P (fn))
+ {
+ gcc_assert (access_path);
+ perform_or_defer_access_check (access_path, fn, fn);
}
if (TYPE_PTRFN_P (target_type) || TYPE_PTRMEMFUNC_P (target_type))
- return build_unary_op (ADDR_EXPR, fn, 0);
+ return cp_build_unary_op (ADDR_EXPR, fn, 0, flags);
else
{
- /* The target must be a REFERENCE_TYPE. Above, build_unary_op
+ /* The target must be a REFERENCE_TYPE. Above, cp_build_unary_op
will mark the function as addressed, but here we must do it
explicitly. */
cxx_mark_addressable (fn);
if (type == error_mark_node)
return 0;
- if (! IS_AGGR_TYPE (type))
+ if (! CLASS_TYPE_P (type))
return 0;
/* In G++ 3.2, whether or not a class was empty was determined by
return false;
}
+/* Returns true if TYPE contains no actual data, just various
+ possible combinations of empty classes. */
+
+bool
+is_really_empty_class (tree type)
+{
+ if (is_empty_class (type))
+ return true;
+ if (CLASS_TYPE_P (type))
+ {
+ tree field;
+ tree binfo;
+ tree base_binfo;
+ int i;
+
+ for (binfo = TYPE_BINFO (type), i = 0;
+ BINFO_BASE_ITERATE (binfo, i, base_binfo); ++i)
+ if (!is_really_empty_class (BINFO_TYPE (base_binfo)))
+ return false;
+ for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+ if (TREE_CODE (field) == FIELD_DECL
+ && !DECL_ARTIFICIAL (field)
+ && !is_really_empty_class (TREE_TYPE (field)))
+ return false;
+ return true;
+ }
+ else if (TREE_CODE (type) == ARRAY_TYPE)
+ return is_really_empty_class (TREE_TYPE (type));
+ return false;
+}
+
/* Note that NAME was looked up while the current class was being
defined and that the result of that lookup was DECL. */
A name N used in a class S shall refer to the same declaration
in its context and when re-evaluated in the completed scope of
S. */
- pedwarn ("declaration of %q#D", decl);
- pedwarn ("changes meaning of %qD from %q+#D",
+ permerror (input_location, "declaration of %q#D", decl);
+ permerror (input_location, "changes meaning of %qD from %q+#D",
DECL_NAME (OVL_CURRENT (decl)), (tree) n->value);
}
}
We first check this in update_vtable_entry_for_fn, so we handle
restored primary bases properly; we also need to do it here so we
- zero out unused slots in ctor vtables, rather than filling themff
+ zero out unused slots in ctor vtables, rather than filling them
with erroneous values (though harmless, apart from relocation
costs). */
for (b = binfo; ; b = get_primary_binfo (b))
TREE_OPERAND (init, 0),
build_int_cst (NULL_TREE, i));
TREE_CONSTANT (fdesc) = 1;
- TREE_INVARIANT (fdesc) = 1;
vfun_inits = tree_cons (NULL_TREE, fdesc, vfun_inits);
}