aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@acm.org>1999-08-03 15:04:49 +0000
committerNathan Sidwell <nathan@gcc.gnu.org>1999-08-03 15:04:49 +0000
commit52fb276947febba5f17dbb30ad2ce2a818f714f6 (patch)
treeea01d0c326ebc211b3750d68cadb0c3e78b38bdc /gcc
parent4a30151d102fe111f5de787992494970248ae246 (diff)
downloadgcc-52fb276947febba5f17dbb30ad2ce2a818f714f6.zip
gcc-52fb276947febba5f17dbb30ad2ce2a818f714f6.tar.gz
gcc-52fb276947febba5f17dbb30ad2ce2a818f714f6.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog11
-rw-r--r--gcc/cp/call.c14
-rw-r--r--gcc/cp/class.c80
-rw-r--r--gcc/cp/cp-tree.h6
-rw-r--r--gcc/cp/tree.c32
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 <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.
1999-08-03 Nathan Sidwell <nathan@acm.org>
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;
}