Commit 52fb2769 by Nathan Sidwell Committed by Nathan Sidwell

call.c (convert_arg_to_ellipsis): Use pod_type_p.

        * call.c (convert_arg_to_ellipsis): Use pod_type_p.
        * cp-tree.h (struct lang_type): Added non_pod_class flag.
        (CLASSTYPE_NON_POD_P): New macro to access it.
        * class.c (finish_struct_1): Determine non-PODness.
        Check for arrays of pointers (-Weffc++).
        Remove array inspection duplicated code.
        * tree.c (pod_type_p): Detect non-pod non-aggregate types.
        Use CLASSTYPE_NON_POD_P.

From-SVN: r28475
parent 4a30151d
1999-08-03 Nathan Sidwell <nathan@acm.org> 1999-08-03 Nathan Sidwell <nathan@acm.org>
* call.c (convert_arg_to_ellipsis): Use pod_type_p.
* cp-tree.h (struct lang_type): Added non_pod_class flag.
(CLASSTYPE_NON_POD_P): New macro to access it.
* class.c (finish_struct_1): Determine non-PODness.
Check for arrays of pointers (-Weffc++).
Remove array inspection duplicated code.
* tree.c (pod_type_p): Detect non-pod non-aggregate types.
Use CLASSTYPE_NON_POD_P.
1999-08-03 Nathan Sidwell <nathan@acm.org>
* class.c (duplicate_tag_error): Preserve template information. * class.c (duplicate_tag_error): Preserve template information.
1999-08-03 Nathan Sidwell <nathan@acm.org> 1999-08-03 Nathan Sidwell <nathan@acm.org>
......
...@@ -3752,21 +3752,25 @@ convert_like (convs, expr) ...@@ -3752,21 +3752,25 @@ convert_like (convs, expr)
} }
/* ARG is being passed to a varargs function. Perform any conversions /* ARG is being passed to a varargs function. Perform any conversions
required. Return the converted value. */ required. Array/function to pointer decay must have already happened.
Return the converted value. */
tree tree
convert_arg_to_ellipsis (arg) convert_arg_to_ellipsis (arg)
tree arg; tree arg;
{ {
if (! pod_type_p (TREE_TYPE (arg)))
{
/* Undefined behaviour [expr.call] 5.2.2/7. */
cp_warning ("cannot pass objects of non-POD type `%#T' through `...'",
TREE_TYPE (arg));
}
if (TREE_CODE (TREE_TYPE (arg)) == REAL_TYPE if (TREE_CODE (TREE_TYPE (arg)) == REAL_TYPE
&& (TYPE_PRECISION (TREE_TYPE (arg)) && (TYPE_PRECISION (TREE_TYPE (arg))
< TYPE_PRECISION (double_type_node))) < TYPE_PRECISION (double_type_node)))
/* Convert `float' to `double'. */ /* Convert `float' to `double'. */
arg = cp_convert (double_type_node, arg); arg = cp_convert (double_type_node, arg);
else if (IS_AGGR_TYPE (TREE_TYPE (arg))
&& ! TYPE_HAS_TRIVIAL_INIT_REF (TREE_TYPE (arg)))
cp_warning ("cannot pass objects of type `%T' through `...'",
TREE_TYPE (arg));
else else
/* Convert `short' and `char' to full-size `int'. */ /* Convert `short' and `char' to full-size `int'. */
arg = default_conversion (arg); arg = default_conversion (arg);
......
...@@ -3297,6 +3297,7 @@ finish_struct_1 (t) ...@@ -3297,6 +3297,7 @@ finish_struct_1 (t)
int no_const_asn_ref; int no_const_asn_ref;
int has_mutable = 0; int has_mutable = 0;
int n_fields = 0; int n_fields = 0;
int non_pod_class = 0;
/* The index of the first base class which has virtual /* The index of the first base class which has virtual
functions. Only applied to non-virtual baseclasses. */ functions. Only applied to non-virtual baseclasses. */
...@@ -3431,6 +3432,7 @@ finish_struct_1 (t) ...@@ -3431,6 +3432,7 @@ finish_struct_1 (t)
last_x = NULL_TREE; last_x = NULL_TREE;
for (x = fields; x; x = TREE_CHAIN (x)) for (x = fields; x; x = TREE_CHAIN (x))
{ {
tree type = TREE_TYPE (x);
GNU_xref_member (current_class_name, x); GNU_xref_member (current_class_name, x);
if (TREE_CODE (x) == FIELD_DECL) if (TREE_CODE (x) == FIELD_DECL)
...@@ -3472,21 +3474,24 @@ finish_struct_1 (t) ...@@ -3472,21 +3474,24 @@ finish_struct_1 (t)
/* Perform error checking that did not get done in /* Perform error checking that did not get done in
grokdeclarator. */ grokdeclarator. */
if (TREE_CODE (TREE_TYPE (x)) == FUNCTION_TYPE) if (TREE_CODE (type) == FUNCTION_TYPE)
{ {
cp_error_at ("field `%D' invalidly declared function type", cp_error_at ("field `%D' invalidly declared function type",
x); x);
TREE_TYPE (x) = build_pointer_type (TREE_TYPE (x)); type = build_pointer_type (type);
TREE_TYPE (x) = type;
} }
else if (TREE_CODE (TREE_TYPE (x)) == METHOD_TYPE) else if (TREE_CODE (type) == METHOD_TYPE)
{ {
cp_error_at ("field `%D' invalidly declared method type", x); cp_error_at ("field `%D' invalidly declared method type", x);
TREE_TYPE (x) = build_pointer_type (TREE_TYPE (x)); type = build_pointer_type (type);
TREE_TYPE (x) = type;
} }
else if (TREE_CODE (TREE_TYPE (x)) == OFFSET_TYPE) else if (TREE_CODE (type) == OFFSET_TYPE)
{ {
cp_error_at ("field `%D' invalidly declared offset type", x); cp_error_at ("field `%D' invalidly declared offset type", x);
TREE_TYPE (x) = build_pointer_type (TREE_TYPE (x)); type = build_pointer_type (type);
TREE_TYPE (x) = type;
} }
#if 0 #if 0
...@@ -3494,7 +3499,7 @@ finish_struct_1 (t) ...@@ -3494,7 +3499,7 @@ finish_struct_1 (t)
cant_have_default_ctor = 1; cant_have_default_ctor = 1;
#endif #endif
if (TREE_TYPE (x) == error_mark_node) if (type == error_mark_node)
continue; continue;
DECL_SAVED_INSNS (x) = NULL_RTX; DECL_SAVED_INSNS (x) = NULL_RTX;
...@@ -3522,8 +3527,10 @@ finish_struct_1 (t) ...@@ -3522,8 +3527,10 @@ finish_struct_1 (t)
/* If this is of reference type, check if it needs an init. /* If this is of reference type, check if it needs an init.
Also do a little ANSI jig if necessary. */ Also do a little ANSI jig if necessary. */
if (TREE_CODE (TREE_TYPE (x)) == REFERENCE_TYPE) if (TREE_CODE (type) == REFERENCE_TYPE)
{ {
non_pod_class = 1;
if (DECL_INITIAL (x) == NULL_TREE) if (DECL_INITIAL (x) == NULL_TREE)
ref_sans_init = 1; ref_sans_init = 1;
...@@ -3543,14 +3550,21 @@ finish_struct_1 (t) ...@@ -3543,14 +3550,21 @@ finish_struct_1 (t)
} }
} }
if (TREE_CODE (TREE_TYPE (x)) == POINTER_TYPE) while (TREE_CODE (type) == ARRAY_TYPE)
type = TREE_TYPE (type);
if (TREE_CODE (type) == POINTER_TYPE)
has_pointers = 1; has_pointers = 1;
if (DECL_MUTABLE_P (x) || TYPE_HAS_MUTABLE_P (TREE_TYPE (x))) if (DECL_MUTABLE_P (x) || TYPE_HAS_MUTABLE_P (type))
has_mutable = 1; has_mutable = 1;
if (! pod_type_p (type) || TYPE_PTRMEM_P (type)
|| TYPE_PTRMEMFUNC_P (type))
non_pod_class = 1;
/* If any field is const, the structure type is pseudo-const. */ /* If any field is const, the structure type is pseudo-const. */
if (CP_TYPE_CONST_P (TREE_TYPE (x))) if (CP_TYPE_CONST_P (type))
{ {
C_TYPE_FIELDS_READONLY (t) = 1; C_TYPE_FIELDS_READONLY (t) = 1;
if (DECL_INITIAL (x) == NULL_TREE) if (DECL_INITIAL (x) == NULL_TREE)
...@@ -3576,14 +3590,11 @@ finish_struct_1 (t) ...@@ -3576,14 +3590,11 @@ finish_struct_1 (t)
{ {
/* A field that is pseudo-const makes the structure /* A field that is pseudo-const makes the structure
likewise. */ likewise. */
tree t1 = TREE_TYPE (x); if (IS_AGGR_TYPE (type))
while (TREE_CODE (t1) == ARRAY_TYPE)
t1 = TREE_TYPE (t1);
if (IS_AGGR_TYPE (t1))
{ {
if (C_TYPE_FIELDS_READONLY (t1)) if (C_TYPE_FIELDS_READONLY (type))
C_TYPE_FIELDS_READONLY (t) = 1; C_TYPE_FIELDS_READONLY (t) = 1;
if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (t1)) if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (type))
const_sans_init = 1; const_sans_init = 1;
} }
} }
...@@ -3593,7 +3604,10 @@ finish_struct_1 (t) ...@@ -3593,7 +3604,10 @@ finish_struct_1 (t)
if (DECL_C_BIT_FIELD (x)) if (DECL_C_BIT_FIELD (x))
{ {
/* Invalid bit-field size done by grokfield. */ /* Invalid bit-field size done by grokfield. */
/* Detect invalid bit-field type. */ /* Detect invalid bit-field type. Simply checking if TYPE is
integral is insufficient, as that is the array core of the
field type. If TREE_TYPE (x) is integral, then TYPE must be
the same. */
if (DECL_INITIAL (x) if (DECL_INITIAL (x)
&& ! INTEGRAL_TYPE_P (TREE_TYPE (x))) && ! INTEGRAL_TYPE_P (TREE_TYPE (x)))
{ {
...@@ -3643,20 +3657,20 @@ finish_struct_1 (t) ...@@ -3643,20 +3657,20 @@ finish_struct_1 (t)
TYPE_PRECISION (long_long_unsigned_type_node)); TYPE_PRECISION (long_long_unsigned_type_node));
cp_error_at (" in declaration of `%D'", x); cp_error_at (" in declaration of `%D'", x);
} }
else if (width > TYPE_PRECISION (TREE_TYPE (x)) else if (width > TYPE_PRECISION (type)
&& TREE_CODE (TREE_TYPE (x)) != ENUMERAL_TYPE && TREE_CODE (type) != ENUMERAL_TYPE
&& TREE_CODE (TREE_TYPE (x)) != BOOLEAN_TYPE) && TREE_CODE (type) != BOOLEAN_TYPE)
{ {
cp_warning_at ("width of `%D' exceeds its type", x); cp_warning_at ("width of `%D' exceeds its type", x);
} }
else if (TREE_CODE (TREE_TYPE (x)) == ENUMERAL_TYPE else if (TREE_CODE (type) == ENUMERAL_TYPE
&& ((min_precision (TYPE_MIN_VALUE (TREE_TYPE (x)), && ((min_precision (TYPE_MIN_VALUE (type),
TREE_UNSIGNED (TREE_TYPE (x))) > width) TREE_UNSIGNED (type)) > width)
|| (min_precision (TYPE_MAX_VALUE (TREE_TYPE (x)), || (min_precision (TYPE_MAX_VALUE (type),
TREE_UNSIGNED (TREE_TYPE (x))) > width))) TREE_UNSIGNED (type)) > width)))
{ {
cp_warning_at ("`%D' is too small to hold all values of `%#T'", cp_warning_at ("`%D' is too small to hold all values of `%#T'",
x, TREE_TYPE (x)); x, type);
} }
if (DECL_INITIAL (x)) if (DECL_INITIAL (x))
...@@ -3674,22 +3688,17 @@ finish_struct_1 (t) ...@@ -3674,22 +3688,17 @@ finish_struct_1 (t)
#ifdef PCC_BITFIELD_TYPE_MATTERS #ifdef PCC_BITFIELD_TYPE_MATTERS
if (PCC_BITFIELD_TYPE_MATTERS) if (PCC_BITFIELD_TYPE_MATTERS)
DECL_ALIGN (x) = MAX (DECL_ALIGN (x), DECL_ALIGN (x) = MAX (DECL_ALIGN (x),
TYPE_ALIGN (TREE_TYPE (x))); TYPE_ALIGN (type));
#endif #endif
} }
} }
} }
else else
/* Non-bit-fields are aligned for their type. */ /* Non-bit-fields are aligned for their type. */
DECL_ALIGN (x) = MAX (DECL_ALIGN (x), TYPE_ALIGN (TREE_TYPE (x))); DECL_ALIGN (x) = MAX (DECL_ALIGN (x), TYPE_ALIGN (type));
} }
else else
{ {
tree type = TREE_TYPE (x);
while (TREE_CODE (type) == ARRAY_TYPE)
type = TREE_TYPE (type);
if (CLASS_TYPE_P (type) && ! ANON_AGGR_TYPE_P (type)) if (CLASS_TYPE_P (type) && ! ANON_AGGR_TYPE_P (type))
{ {
/* Never let anything with uninheritable virtuals /* Never let anything with uninheritable virtuals
...@@ -3792,6 +3801,9 @@ finish_struct_1 (t) ...@@ -3792,6 +3801,9 @@ finish_struct_1 (t)
if (! IS_SIGNATURE (t)) if (! IS_SIGNATURE (t))
CLASSTYPE_NON_AGGREGATE (t) CLASSTYPE_NON_AGGREGATE (t)
= ! aggregate || has_virtual || TYPE_HAS_CONSTRUCTOR (t); = ! aggregate || has_virtual || TYPE_HAS_CONSTRUCTOR (t);
CLASSTYPE_NON_POD_P (t)
= non_pod_class || CLASSTYPE_NON_AGGREGATE (t)
|| TYPE_HAS_DESTRUCTOR (t) || TYPE_HAS_ASSIGN_REF (t);
TYPE_HAS_REAL_ASSIGN_REF (t) |= TYPE_HAS_ASSIGN_REF (t); TYPE_HAS_REAL_ASSIGN_REF (t) |= TYPE_HAS_ASSIGN_REF (t);
TYPE_HAS_COMPLEX_ASSIGN_REF (t) TYPE_HAS_COMPLEX_ASSIGN_REF (t)
|= TYPE_HAS_ASSIGN_REF (t) || TYPE_USES_VIRTUAL_BASECLASSES (t); |= TYPE_HAS_ASSIGN_REF (t) || TYPE_USES_VIRTUAL_BASECLASSES (t);
......
...@@ -802,6 +802,7 @@ struct lang_type ...@@ -802,6 +802,7 @@ struct lang_type
unsigned is_partial_instantiation : 1; unsigned is_partial_instantiation : 1;
unsigned has_mutable : 1; unsigned has_mutable : 1;
unsigned com_interface : 1; unsigned com_interface : 1;
unsigned non_pod_class : 1;
/* When adding a flag here, consider whether or not it ought to /* When adding a flag here, consider whether or not it ought to
apply to a template instance if it applies to the template. apply to a template instance if it applies to the template.
If so, make sure to copy it in instantiate_class_template! */ If so, make sure to copy it in instantiate_class_template! */
...@@ -809,7 +810,7 @@ struct lang_type ...@@ -809,7 +810,7 @@ struct lang_type
/* The MIPS compiler gets it wrong if this struct also /* The MIPS compiler gets it wrong if this struct also
does not fill out to a multiple of 4 bytes. Add a does not fill out to a multiple of 4 bytes. Add a
member `dummy' with new bits if you go over the edge. */ member `dummy' with new bits if you go over the edge. */
unsigned dummy : 10; unsigned dummy : 9;
} type_flags; } type_flags;
int vsize; int vsize;
...@@ -1076,6 +1077,9 @@ struct lang_type ...@@ -1076,6 +1077,9 @@ struct lang_type
#define CLASSTYPE_HAS_MUTABLE(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_mutable) #define CLASSTYPE_HAS_MUTABLE(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_mutable)
#define TYPE_HAS_MUTABLE_P(NODE) (cp_has_mutable_p (NODE)) #define TYPE_HAS_MUTABLE_P(NODE) (cp_has_mutable_p (NODE))
/* Nonzero means that this class type is a non-POD class. */
#define CLASSTYPE_NON_POD_P(NODE) (TYPE_LANG_SPECIFIC (NODE)->type_flags.non_pod_class)
/* Nonzero means that this type is meant for communication via COM. */ /* Nonzero means that this type is meant for communication via COM. */
#define CLASSTYPE_COM_INTERFACE(NODE) \ #define CLASSTYPE_COM_INTERFACE(NODE) \
(TYPE_LANG_SPECIFIC(NODE)->type_flags.com_interface) (TYPE_LANG_SPECIFIC(NODE)->type_flags.com_interface)
......
...@@ -2749,30 +2749,24 @@ int ...@@ -2749,30 +2749,24 @@ int
pod_type_p (t) pod_type_p (t)
tree t; tree t;
{ {
tree f;
while (TREE_CODE (t) == ARRAY_TYPE) while (TREE_CODE (t) == ARRAY_TYPE)
t = TREE_TYPE (t); t = TREE_TYPE (t);
if (! IS_AGGR_TYPE (t)) if (INTEGRAL_TYPE_P (t))
return 1; /* integral, character or enumeral type */
if (FLOAT_TYPE_P (t))
return 1; return 1;
if (TYPE_PTR_P (t))
if (CLASSTYPE_NON_AGGREGATE (t) return 1; /* pointer to non-member */
|| TYPE_HAS_COMPLEX_ASSIGN_REF (t) if (TYPE_PTRMEM_P (t))
|| TYPE_HAS_DESTRUCTOR (t)) return 1; /* pointer to member object */
if (TYPE_PTRMEMFUNC_P (t))
return 1; /* pointer to member function */
if (! CLASS_TYPE_P (t))
return 0; /* other non-class type (reference or function) */
if (CLASSTYPE_NON_POD_P (t))
return 0; return 0;
for (f = TYPE_FIELDS (t); f; f = TREE_CHAIN (f))
{
if (TREE_CODE (f) != FIELD_DECL)
continue;
if (TREE_CODE (TREE_TYPE (f)) == REFERENCE_TYPE
|| TYPE_PTRMEMFUNC_P (TREE_TYPE (f))
|| TYPE_PTRMEM_P (TREE_TYPE (f)))
return 0;
}
return 1; return 1;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment