From 52fb276947febba5f17dbb30ad2ce2a818f714f6 Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Tue, 3 Aug 1999 15:04:49 +0000 Subject: [PATCH] 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 --- gcc/cp/ChangeLog | 11 ++++++++ gcc/cp/call.c | 14 ++++++---- gcc/cp/class.c | 80 ++++++++++++++++++++++++++++++++------------------------ gcc/cp/cp-tree.h | 6 ++++- gcc/cp/tree.c | 32 +++++++++-------------- 5 files changed, 84 insertions(+), 59 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 5f589da..74bde45 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,16 @@ 1999-08-03 Nathan Sidwell + * 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 + * class.c (duplicate_tag_error): Preserve template information. 1999-08-03 Nathan Sidwell diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 9cdfc75..fb8f129 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -3752,21 +3752,25 @@ convert_like (convs, expr) } /* 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 convert_arg_to_ellipsis (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 && (TYPE_PRECISION (TREE_TYPE (arg)) < TYPE_PRECISION (double_type_node))) /* Convert `float' to `double'. */ 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 /* Convert `short' and `char' to full-size `int'. */ arg = default_conversion (arg); diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 78ed032..8ba5694 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -3297,6 +3297,7 @@ finish_struct_1 (t) int no_const_asn_ref; int has_mutable = 0; int n_fields = 0; + int non_pod_class = 0; /* The index of the first base class which has virtual functions. Only applied to non-virtual baseclasses. */ @@ -3431,6 +3432,7 @@ finish_struct_1 (t) last_x = NULL_TREE; for (x = fields; x; x = TREE_CHAIN (x)) { + tree type = TREE_TYPE (x); GNU_xref_member (current_class_name, x); if (TREE_CODE (x) == FIELD_DECL) @@ -3472,21 +3474,24 @@ finish_struct_1 (t) /* Perform error checking that did not get done in grokdeclarator. */ - if (TREE_CODE (TREE_TYPE (x)) == FUNCTION_TYPE) + if (TREE_CODE (type) == FUNCTION_TYPE) { cp_error_at ("field `%D' invalidly declared function 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)) == METHOD_TYPE) + else if (TREE_CODE (type) == METHOD_TYPE) { 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); - TREE_TYPE (x) = build_pointer_type (TREE_TYPE (x)); + type = build_pointer_type (type); + TREE_TYPE (x) = type; } #if 0 @@ -3494,7 +3499,7 @@ finish_struct_1 (t) cant_have_default_ctor = 1; #endif - if (TREE_TYPE (x) == error_mark_node) + if (type == error_mark_node) continue; DECL_SAVED_INSNS (x) = NULL_RTX; @@ -3522,8 +3527,10 @@ finish_struct_1 (t) /* If this is of reference type, check if it needs an init. 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) ref_sans_init = 1; @@ -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; - 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; + 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 (CP_TYPE_CONST_P (TREE_TYPE (x))) + if (CP_TYPE_CONST_P (type)) { C_TYPE_FIELDS_READONLY (t) = 1; if (DECL_INITIAL (x) == NULL_TREE) @@ -3576,14 +3590,11 @@ finish_struct_1 (t) { /* A field that is pseudo-const makes the structure likewise. */ - tree t1 = TREE_TYPE (x); - while (TREE_CODE (t1) == ARRAY_TYPE) - t1 = TREE_TYPE (t1); - if (IS_AGGR_TYPE (t1)) + if (IS_AGGR_TYPE (type)) { - if (C_TYPE_FIELDS_READONLY (t1)) + if (C_TYPE_FIELDS_READONLY (type)) C_TYPE_FIELDS_READONLY (t) = 1; - if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (t1)) + if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (type)) const_sans_init = 1; } } @@ -3593,7 +3604,10 @@ finish_struct_1 (t) if (DECL_C_BIT_FIELD (x)) { /* 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) && ! INTEGRAL_TYPE_P (TREE_TYPE (x))) { @@ -3643,20 +3657,20 @@ finish_struct_1 (t) TYPE_PRECISION (long_long_unsigned_type_node)); cp_error_at (" in declaration of `%D'", x); } - else if (width > TYPE_PRECISION (TREE_TYPE (x)) - && TREE_CODE (TREE_TYPE (x)) != ENUMERAL_TYPE - && TREE_CODE (TREE_TYPE (x)) != BOOLEAN_TYPE) + else if (width > TYPE_PRECISION (type) + && TREE_CODE (type) != ENUMERAL_TYPE + && TREE_CODE (type) != BOOLEAN_TYPE) { cp_warning_at ("width of `%D' exceeds its type", x); } - else if (TREE_CODE (TREE_TYPE (x)) == ENUMERAL_TYPE - && ((min_precision (TYPE_MIN_VALUE (TREE_TYPE (x)), - TREE_UNSIGNED (TREE_TYPE (x))) > width) - || (min_precision (TYPE_MAX_VALUE (TREE_TYPE (x)), - TREE_UNSIGNED (TREE_TYPE (x))) > width))) + else if (TREE_CODE (type) == ENUMERAL_TYPE + && ((min_precision (TYPE_MIN_VALUE (type), + TREE_UNSIGNED (type)) > width) + || (min_precision (TYPE_MAX_VALUE (type), + TREE_UNSIGNED (type)) > width))) { cp_warning_at ("`%D' is too small to hold all values of `%#T'", - x, TREE_TYPE (x)); + x, type); } if (DECL_INITIAL (x)) @@ -3674,22 +3688,17 @@ finish_struct_1 (t) #ifdef PCC_BITFIELD_TYPE_MATTERS if (PCC_BITFIELD_TYPE_MATTERS) DECL_ALIGN (x) = MAX (DECL_ALIGN (x), - TYPE_ALIGN (TREE_TYPE (x))); + TYPE_ALIGN (type)); #endif } } } else /* 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 { - 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)) { /* Never let anything with uninheritable virtuals @@ -3792,6 +3801,9 @@ finish_struct_1 (t) if (! IS_SIGNATURE (t)) CLASSTYPE_NON_AGGREGATE (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_COMPLEX_ASSIGN_REF (t) |= TYPE_HAS_ASSIGN_REF (t) || TYPE_USES_VIRTUAL_BASECLASSES (t); diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index c5af6fd..31e9f8c 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -802,6 +802,7 @@ struct lang_type unsigned is_partial_instantiation : 1; unsigned has_mutable : 1; unsigned com_interface : 1; + unsigned non_pod_class : 1; /* When adding a flag here, consider whether or not it ought to apply to a template instance if it applies to the template. If so, make sure to copy it in instantiate_class_template! */ @@ -809,7 +810,7 @@ struct lang_type /* The MIPS compiler gets it wrong if this struct also does not fill out to a multiple of 4 bytes. Add a member `dummy' with new bits if you go over the edge. */ - unsigned dummy : 10; + unsigned dummy : 9; } type_flags; int vsize; @@ -1076,6 +1077,9 @@ struct lang_type #define CLASSTYPE_HAS_MUTABLE(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_mutable) #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. */ #define CLASSTYPE_COM_INTERFACE(NODE) \ (TYPE_LANG_SPECIFIC(NODE)->type_flags.com_interface) diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 9076cc7..ab71470 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -2749,30 +2749,24 @@ int pod_type_p (t) tree t; { - tree f; - while (TREE_CODE (t) == ARRAY_TYPE) 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; - - if (CLASSTYPE_NON_AGGREGATE (t) - || TYPE_HAS_COMPLEX_ASSIGN_REF (t) - || TYPE_HAS_DESTRUCTOR (t)) + if (TYPE_PTR_P (t)) + return 1; /* pointer to non-member */ + if (TYPE_PTRMEM_P (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; - - 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; } -- 2.7.4