aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog34
-rw-r--r--gcc/cp/call.c50
-rw-r--r--gcc/cp/class.c69
-rw-r--r--gcc/cp/cp-tree.h22
-rw-r--r--gcc/cp/cxx-pretty-print.c6
-rw-r--r--gcc/cp/decl.c40
-rw-r--r--gcc/cp/init.c4
-rw-r--r--gcc/cp/parser.c8
-rw-r--r--gcc/cp/semantics.c26
-rw-r--r--gcc/cp/tree.c116
-rw-r--r--gcc/cp/typeck.c4
11 files changed, 294 insertions, 85 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 4265fa9..81cc8e0 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,37 @@
+2009-07-16 Jason Merrill <jason@redhat.com>
+
+ PR libstdc++/37907
+ Split POD into "standard-layout" and "trivial" as per N2230,
+ Support std::is_standard_layout and std::is_trivial traits.
+ * cp-tree.h (enum cp_trait_kind): Add CPTK_IS_STD_LAYOUT,
+ CPTK_IS_TRIVIAL.
+ (struct lang_type_class): Add non_std_layout.
+ (CLASSTYPE_NON_STD_LAYOUT): New.
+ * class.c (check_bases): Set it.
+ (check_field_decls): Likewise.
+ (check_bases_and_members): Likewise.
+ * parser.c (cp_parser_primary_expression): Handle RID_IS_STD_LAYOUT,
+ RID_IS_TRIVIAL.
+ (cp_parser_trait_expr): Likewise.
+ * semantics.c (trait_expr_value): Handle CPTK_IS_STD_LAYOUT,
+ CPTK_IS_TRIVIAL.
+ (finish_trait_expr): Likewise.
+ * tree.c (scalarish_type_p, trivial_type_p, std_layout_type_p): New.
+ (pod_type_p): Use them.
+ (type_has_nontrivial_copy_init, type_has_nontrivial_default_init): New.
+
+ Adjust bits of the language that no longer refer to POD types.
+ * call.c (convert_arg_to_ellipsis): Use type_has_nontrivial_copy_init
+ and TYPE_HAS_NONTRIVIAL_DESTRUCTOR rather than pod_type_p.
+ (build_x_va_arg): Likewise.
+ (call_builtin_trap): Remove.
+ * decl.c (declare_local_label): Use type_has_nontrivial_default_init
+ and TYPE_HAS_NONTRIVIAL_DESTRUCTOR rather than pod_type_p.
+ (cp_finish_decl): Likewise.
+ (check_previous_goto_1, check_goto): Adjust error.
+ * typeck.c (build_class_member_access_expr): Check
+ CLASSTYPE_NON_STD_LAYOUT rather than CLASSTYPE_NON_POD_P.
+
2009-07-14 Taras Glek <tglek@mozilla.com>
Rafael Espindola <espindola@google.com>
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 588c997..6a7a1b8 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -197,7 +197,6 @@ static conversion *direct_reference_binding (tree, conversion *);
static bool promoted_arithmetic_type_p (tree);
static conversion *conditional_conversion (tree, tree);
static char *name_as_c_string (tree, tree, bool *);
-static tree call_builtin_trap (void);
static tree prep_operand (tree);
static void add_candidates (tree, const VEC(tree,gc) *, tree, bool, tree, tree,
int, struct z_candidate **);
@@ -5042,18 +5041,6 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
return expr;
}
-/* Build a call to __builtin_trap. */
-
-static tree
-call_builtin_trap (void)
-{
- tree fn = implicit_built_in_decls[BUILT_IN_TRAP];
-
- gcc_assert (fn != NULL);
- fn = build_call_n (fn, 0);
- return fn;
-}
-
/* ARG is being passed to a varargs function. Perform any conversions
required. Return the converted value. */
@@ -5082,20 +5069,23 @@ convert_arg_to_ellipsis (tree arg)
arg = require_complete_type (arg);
if (arg != error_mark_node
- && !pod_type_p (TREE_TYPE (arg)))
+ && (type_has_nontrivial_copy_init (TREE_TYPE (arg))
+ || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (arg))))
{
- /* Undefined behavior [expr.call] 5.2.2/7. We used to just warn
- here and do a bitwise copy, but now cp_expr_size will abort if we
- try to do that.
+ /* [expr.call] 5.2.2/7:
+ Passing a potentially-evaluated argument of class type (Clause 9)
+ with a non-trivial copy constructor or a non-trivial destructor
+ with no corresponding parameter is conditionally-supported, with
+ implementation-defined semantics.
+
+ We used to just warn here and do a bitwise copy, but now
+ cp_expr_size will abort if we try to do that.
+
If the call appears in the context of a sizeof expression,
- there is no need to emit a warning, since the expression won't be
- evaluated. We keep the builtin_trap just as a safety check. */
+ it is not potentially-evaluated. */
if (cp_unevaluated_operand == 0)
- warning (0, "cannot pass objects of non-POD type %q#T through %<...%>; "
- "call will abort at runtime", TREE_TYPE (arg));
- arg = call_builtin_trap ();
- arg = build2 (COMPOUND_EXPR, integer_type_node, arg,
- integer_zero_node);
+ error ("cannot pass objects of non-trivially-copyable "
+ "type %q#T through %<...%>", TREE_TYPE (arg));
}
return arg;
@@ -5114,16 +5104,16 @@ build_x_va_arg (tree expr, tree type)
if (expr == error_mark_node || !type)
return error_mark_node;
- if (! pod_type_p (type))
+ if (type_has_nontrivial_copy_init (type)
+ || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)
+ || TREE_CODE (type) == REFERENCE_TYPE)
{
/* Remove reference types so we don't ICE later on. */
tree type1 = non_reference (type);
- /* Undefined behavior [expr.call] 5.2.2/7. */
- warning (0, "cannot receive objects of non-POD type %q#T through %<...%>; "
- "call will abort at runtime", type);
+ /* conditionally-supported behavior [expr.call] 5.2.2/7. */
+ error ("cannot receive objects of non-trivially-copyable type %q#T "
+ "through %<...%>; ", type);
expr = convert (build_pointer_type (type1), null_node);
- expr = build2 (COMPOUND_EXPR, TREE_TYPE (expr),
- call_builtin_trap (), expr);
expr = cp_build_indirect_ref (expr, NULL, tf_warning_or_error);
return expr;
}
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 4668c68..373f457 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -1248,9 +1248,15 @@ check_bases (tree t,
int seen_non_virtual_nearly_empty_base_p;
tree base_binfo;
tree binfo;
+ tree field = NULL_TREE;
seen_non_virtual_nearly_empty_base_p = 0;
+ if (!CLASSTYPE_NON_STD_LAYOUT (t))
+ for (field = TYPE_FIELDS (t); field; field = TREE_CHAIN (field))
+ if (TREE_CODE (field) == FIELD_DECL)
+ break;
+
for (binfo = TYPE_BINFO (t), i = 0;
BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
{
@@ -1305,6 +1311,36 @@ check_bases (tree t,
CLASSTYPE_CONTAINS_EMPTY_CLASS_P (t)
|= CLASSTYPE_CONTAINS_EMPTY_CLASS_P (basetype);
TYPE_HAS_COMPLEX_DFLT (t) |= TYPE_HAS_COMPLEX_DFLT (basetype);
+
+ /* A standard-layout class is a class that:
+ ...
+ * has no non-standard-layout base classes, */
+ CLASSTYPE_NON_STD_LAYOUT (t) |= CLASSTYPE_NON_STD_LAYOUT (basetype);
+ if (!CLASSTYPE_NON_STD_LAYOUT (t))
+ {
+ tree basefield;
+ /* ...has no base classes of the same type as the first non-static
+ data member... */
+ if (field && DECL_CONTEXT (field) == t
+ && (same_type_ignoring_top_level_qualifiers_p
+ (TREE_TYPE (field), basetype)))
+ CLASSTYPE_NON_STD_LAYOUT (t) = 1;
+ else
+ /* ...either has no non-static data members in the most-derived
+ class and at most one base class with non-static data
+ members, or has no base classes with non-static data
+ members */
+ for (basefield = TYPE_FIELDS (basetype); basefield;
+ basefield = TREE_CHAIN (basefield))
+ if (TREE_CODE (basefield) == FIELD_DECL)
+ {
+ if (field)
+ CLASSTYPE_NON_STD_LAYOUT (t) = 1;
+ else
+ field = basefield;
+ break;
+ }
+ }
}
}
@@ -2870,6 +2906,7 @@ check_field_decls (tree t, tree *access_decls,
bool has_pointers;
int any_default_members;
int cant_pack = 0;
+ int field_access = -1;
/* Assume there are no access declarations. */
*access_decls = NULL_TREE;
@@ -2883,6 +2920,7 @@ check_field_decls (tree t, tree *access_decls,
{
tree x = *field;
tree type = TREE_TYPE (x);
+ int this_field_access;
next = &TREE_CHAIN (x);
@@ -2957,10 +2995,21 @@ check_field_decls (tree t, tree *access_decls,
if (TREE_PRIVATE (x) || TREE_PROTECTED (x))
CLASSTYPE_NON_AGGREGATE (t) = 1;
+ /* A standard-layout class is a class that:
+ ...
+ has the same access control (Clause 11) for all non-static data members,
+ ... */
+ this_field_access = TREE_PROTECTED (x) ? 1 : TREE_PRIVATE (x) ? 2 : 0;
+ if (field_access == -1)
+ field_access = this_field_access;
+ else if (this_field_access != field_access)
+ CLASSTYPE_NON_STD_LAYOUT (t) = 1;
+
/* If this is of reference type, check if it needs an init. */
if (TREE_CODE (type) == REFERENCE_TYPE)
{
- CLASSTYPE_NON_POD_P (t) = 1;
+ CLASSTYPE_NON_LAYOUT_POD_P (t) = 1;
+ CLASSTYPE_NON_STD_LAYOUT (t) = 1;
if (DECL_INITIAL (x) == NULL_TREE)
SET_CLASSTYPE_REF_FIELDS_NEED_INIT (t, 1);
@@ -2975,7 +3024,7 @@ check_field_decls (tree t, tree *access_decls,
if (TYPE_PACKED (t))
{
- if (!pod_type_p (type) && !TYPE_PACKED (type))
+ if (!layout_pod_type_p (type) && !TYPE_PACKED (type))
{
warning
(0,
@@ -3024,10 +3073,13 @@ check_field_decls (tree t, tree *access_decls,
if (DECL_MUTABLE_P (x) || TYPE_HAS_MUTABLE_P (type))
CLASSTYPE_HAS_MUTABLE (t) = 1;
- if (! pod_type_p (type))
+ if (! layout_pod_type_p (type))
/* DR 148 now allows pointers to members (which are POD themselves),
to be allowed in POD structs. */
- CLASSTYPE_NON_POD_P (t) = 1;
+ CLASSTYPE_NON_LAYOUT_POD_P (t) = 1;
+
+ if (!std_layout_type_p (type))
+ CLASSTYPE_NON_STD_LAYOUT (t) = 1;
if (! zero_init_p (type))
CLASSTYPE_NON_ZERO_INIT_P (t) = 1;
@@ -4280,7 +4332,7 @@ type_requires_array_cookie (tree type)
/* Check the validity of the bases and members declared in T. Add any
implicitly-generated functions (like copy-constructors and
assignment operators). Compute various flag bits (like
- CLASSTYPE_NON_POD_T) for T. This routine works purely at the C++
+ CLASSTYPE_NON_LAYOUT_POD_T) for T. This routine works purely at the C++
level: i.e., independently of the ABI in use. */
static void
@@ -4346,9 +4398,12 @@ check_bases_and_members (tree t)
elsewhere. */
CLASSTYPE_NON_AGGREGATE (t)
|= (type_has_user_provided_constructor (t) || TYPE_POLYMORPHIC_P (t));
- CLASSTYPE_NON_POD_P (t)
+ /* This is the C++98/03 definition of POD; it changed in C++0x, but we
+ retain the old definition internally for ABI reasons. */
+ CLASSTYPE_NON_LAYOUT_POD_P (t)
|= (CLASSTYPE_NON_AGGREGATE (t)
|| saved_nontrivial_dtor || saved_complex_asn_ref);
+ CLASSTYPE_NON_STD_LAYOUT (t) |= TYPE_CONTAINS_VPTR_P (t);
TYPE_HAS_COMPLEX_ASSIGN_REF (t) |= TYPE_CONTAINS_VPTR_P (t);
TYPE_HAS_COMPLEX_DFLT (t) |= TYPE_CONTAINS_VPTR_P (t);
@@ -5031,7 +5086,7 @@ layout_class_type (tree t, tree *virtuals_p)
/* Create the version of T used for virtual bases. We do not use
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 (CLASSTYPE_NON_LAYOUT_POD_P (t) || CLASSTYPE_EMPTY_P (t))
{
base_t = make_node (TREE_CODE (t));
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 933da19..6ad039a 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -494,6 +494,8 @@ typedef enum cp_trait_kind
CPTK_IS_ENUM,
CPTK_IS_POD,
CPTK_IS_POLYMORPHIC,
+ CPTK_IS_STD_LAYOUT,
+ CPTK_IS_TRIVIAL,
CPTK_IS_UNION
} cp_trait_kind;
@@ -1124,6 +1126,7 @@ struct GTY(()) lang_type_class {
unsigned non_aggregate : 1;
unsigned has_complex_dflt : 1;
unsigned has_list_ctor : 1;
+ unsigned non_std_layout : 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
@@ -1132,7 +1135,7 @@ struct GTY(()) lang_type_class {
/* There are some bits left to fill out a 32-bit word. Keep track
of this by updating the size of this bitfield whenever you add or
remove a flag. */
- unsigned dummy : 10;
+ unsigned dummy : 9;
tree primary_base;
VEC(tree_pair_s,gc) *vcall_indices;
@@ -1385,8 +1388,14 @@ struct GTY(()) lang_type {
#define CLASSTYPE_HAS_MUTABLE(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->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) (LANG_TYPE_CLASS_CHECK (NODE)->non_pod_class)
+/* Nonzero means that this class type is not POD for the purpose of layout
+ (as defined in the ABI). This is different from the language's POD. */
+#define CLASSTYPE_NON_LAYOUT_POD_P(NODE) \
+ (LANG_TYPE_CLASS_CHECK (NODE)->non_pod_class)
+
+/* Nonzero means that this class type is a non-standard-layout class. */
+#define CLASSTYPE_NON_STD_LAYOUT(NODE) \
+ (LANG_TYPE_CLASS_CHECK (NODE)->non_std_layout)
/* Nonzero means that this class contains pod types whose default
initialization is not a zero initialization (namely, pointers to
@@ -4877,7 +4886,12 @@ extern void stabilize_aggr_init (tree, tree *);
extern bool stabilize_init (tree, tree *);
extern tree add_stmt_to_compound (tree, tree);
extern void init_tree (void);
-extern int pod_type_p (const_tree);
+extern bool pod_type_p (const_tree);
+extern bool layout_pod_type_p (const_tree);
+extern bool std_layout_type_p (const_tree);
+extern bool trivial_type_p (const_tree);
+extern bool type_has_nontrivial_default_init (const_tree);
+extern bool type_has_nontrivial_copy_init (const_tree);
extern bool class_tmpl_impl_spec_p (const_tree);
extern int zero_init_p (const_tree);
extern tree strip_typedefs (tree);
diff --git a/gcc/cp/cxx-pretty-print.c b/gcc/cp/cxx-pretty-print.c
index b8732896..0b13bc1 100644
--- a/gcc/cp/cxx-pretty-print.c
+++ b/gcc/cp/cxx-pretty-print.c
@@ -2296,6 +2296,12 @@ pp_cxx_trait_expression (cxx_pretty_printer *pp, tree t)
case CPTK_IS_POLYMORPHIC:
pp_cxx_ws_string (pp, "__is_polymorphic");
break;
+ case CPTK_IS_STD_LAYOUT:
+ pp_cxx_ws_string (pp, "__is_std_layout");
+ break;
+ case CPTK_IS_TRIVIAL:
+ pp_cxx_ws_string (pp, "__is_trivial");
+ break;
case CPTK_IS_UNION:
pp_cxx_ws_string (pp, "__is_union");
break;
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index e1b6678..e65e636 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -2473,20 +2473,28 @@ declare_local_label (tree id)
static int
decl_jump_unsafe (tree decl)
{
+ /* [stmt.dcl]/3: A program that jumps from a point where a local variable
+ with automatic storage duration is not in scope to a point where it is
+ in scope is ill-formed unless the variable has scalar type, class type
+ with a trivial default constructor and a trivial destructor, a
+ cv-qualified version of one of these types, or an array of one of the
+ preceding types and is declared without an initializer (8.5). */
+ tree type = TREE_TYPE (decl);
+
if (TREE_CODE (decl) != VAR_DECL || TREE_STATIC (decl)
- || TREE_TYPE (decl) == error_mark_node)
+ || type == error_mark_node)
return 0;
- if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))
+ type = strip_array_types (type);
+
+ if (type_has_nontrivial_default_init (TREE_TYPE (decl))
|| DECL_NONTRIVIALLY_INITIALIZED_P (decl))
return 2;
- if (pod_type_p (TREE_TYPE (decl)))
- return 0;
+ if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (decl)))
+ return 1;
- /* The POD stuff is just pedantry; why should it matter if the class
- contains a field of pointer to member type? */
- return 1;
+ return 0;
}
/* A subroutine of check_previous_goto_1 to identify a branch to the user. */
@@ -2541,7 +2549,8 @@ check_previous_goto_1 (tree decl, struct cp_binding_level* level, tree names,
if (problem > 1)
error (" crosses initialization of %q+#D", new_decls);
else
- permerror (input_location, " enters scope of non-POD %q+#D", new_decls);
+ permerror (input_location, " enters scope of %q+#D which has "
+ "non-trivial destructor", new_decls);
}
if (b == level)
@@ -2656,7 +2665,8 @@ check_goto (tree decl)
else if (u > 1)
error (" skips initialization of %q+#D", b);
else
- permerror (input_location, " enters scope of non-POD %q+#D", b);
+ permerror (input_location, " enters scope of %q+#D which has "
+ "non-trivial destructor", b);
}
if (ent->in_try_scope)
@@ -5687,11 +5697,13 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
if (TREE_CODE (decl) == VAR_DECL)
{
- /* Only PODs can have thread-local storage. Other types may require
- various kinds of non-trivial initialization. */
- if (DECL_THREAD_LOCAL_P (decl) && !pod_type_p (TREE_TYPE (decl)))
- error ("%qD cannot be thread-local because it has non-POD type %qT",
- decl, TREE_TYPE (decl));
+ /* Only variables with trivial initialization and destruction can
+ have thread-local storage. */
+ if (DECL_THREAD_LOCAL_P (decl)
+ && (type_has_nontrivial_default_init (TREE_TYPE (decl))
+ || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (decl))))
+ error ("%qD cannot be thread-local because it has non-trivial "
+ "type %qT", decl, TREE_TYPE (decl));
/* If this is a local variable that will need a mangled name,
register it now. We must do this before processing the
initializer for the variable, since the initialization might
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 19b2489..9118c61 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -2703,7 +2703,7 @@ build_vec_init (tree base, tree maxindex, tree init,
|| ! TYPE_HAS_NONTRIVIAL_DESTRUCTOR (inner_elt_type)))
|| from_array))
{
- /* Do non-default initialization of POD arrays resulting from
+ /* Do non-default initialization of trivial arrays resulting from
brace-enclosed initializers. In this case, digest_init and
store_constructor will handle the semantics for us. */
@@ -2769,7 +2769,7 @@ build_vec_init (tree base, tree maxindex, tree init,
if (init != NULL_TREE && TREE_CODE (init) == CONSTRUCTOR)
{
- /* Do non-default initialization of non-POD arrays resulting from
+ /* Do non-default initialization of non-trivial arrays resulting from
brace-enclosed initializers. */
unsigned HOST_WIDE_INT idx;
tree elt;
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 94fba02..e64d0bf 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -3399,6 +3399,8 @@ cp_parser_primary_expression (cp_parser *parser,
case RID_IS_ENUM:
case RID_IS_POD:
case RID_IS_POLYMORPHIC:
+ case RID_IS_STD_LAYOUT:
+ case RID_IS_TRIVIAL:
case RID_IS_UNION:
return cp_parser_trait_expr (parser, token->keyword);
@@ -6865,6 +6867,12 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword)
case RID_IS_POLYMORPHIC:
kind = CPTK_IS_POLYMORPHIC;
break;
+ case RID_IS_STD_LAYOUT:
+ kind = CPTK_IS_STD_LAYOUT;
+ break;
+ case RID_IS_TRIVIAL:
+ kind = CPTK_IS_TRIVIAL;
+ break;
case RID_IS_UNION:
kind = CPTK_IS_UNION;
break;
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 61dff51..4473c49 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -4878,6 +4878,7 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
switch (kind)
{
case CPTK_HAS_NOTHROW_ASSIGN:
+ type1 = strip_array_types (type1);
return (!CP_TYPE_CONST_P (type1) && type_code1 != REFERENCE_TYPE
&& (trait_expr_value (CPTK_HAS_TRIVIAL_ASSIGN, type1, type2)
|| (CLASS_TYPE_P (type1)
@@ -4885,8 +4886,11 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
true))));
case CPTK_HAS_TRIVIAL_ASSIGN:
+ /* ??? The standard seems to be missing the "or array of such a class
+ type" wording for this trait. */
+ type1 = strip_array_types (type1);
return (!CP_TYPE_CONST_P (type1) && type_code1 != REFERENCE_TYPE
- && (pod_type_p (type1)
+ && (trivial_type_p (type1)
|| (CLASS_TYPE_P (type1)
&& TYPE_HAS_TRIVIAL_ASSIGN_REF (type1))));
@@ -4899,21 +4903,25 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
case CPTK_HAS_TRIVIAL_CONSTRUCTOR:
type1 = strip_array_types (type1);
- return (pod_type_p (type1)
+ return (trivial_type_p (type1)
|| (CLASS_TYPE_P (type1) && TYPE_HAS_TRIVIAL_DFLT (type1)));
case CPTK_HAS_NOTHROW_COPY:
+ type1 = strip_array_types (type1);
return (trait_expr_value (CPTK_HAS_TRIVIAL_COPY, type1, type2)
|| (CLASS_TYPE_P (type1)
&& classtype_has_nothrow_assign_or_copy_p (type1, false)));
case CPTK_HAS_TRIVIAL_COPY:
- return (pod_type_p (type1) || type_code1 == REFERENCE_TYPE
+ /* ??? The standard seems to be missing the "or array of such a class
+ type" wording for this trait. */
+ type1 = strip_array_types (type1);
+ return (trivial_type_p (type1) || type_code1 == REFERENCE_TYPE
|| (CLASS_TYPE_P (type1) && TYPE_HAS_TRIVIAL_INIT_REF (type1)));
case CPTK_HAS_TRIVIAL_DESTRUCTOR:
type1 = strip_array_types (type1);
- return (pod_type_p (type1) || type_code1 == REFERENCE_TYPE
+ return (trivial_type_p (type1) || type_code1 == REFERENCE_TYPE
|| (CLASS_TYPE_P (type1)
&& TYPE_HAS_TRIVIAL_DESTRUCTOR (type1)));
@@ -4947,6 +4955,12 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
case CPTK_IS_POLYMORPHIC:
return (CLASS_TYPE_P (type1) && TYPE_POLYMORPHIC_P (type1));
+ case CPTK_IS_STD_LAYOUT:
+ return (std_layout_type_p (type1));
+
+ case CPTK_IS_TRIVIAL:
+ return (trivial_type_p (type1));
+
case CPTK_IS_UNION:
return (type_code1 == UNION_TYPE);
@@ -4995,6 +5009,8 @@ finish_trait_expr (cp_trait_kind kind, tree type1, tree type2)
|| kind == CPTK_IS_ENUM
|| kind == CPTK_IS_POD
|| kind == CPTK_IS_POLYMORPHIC
+ || kind == CPTK_IS_STD_LAYOUT
+ || kind == CPTK_IS_TRIVIAL
|| kind == CPTK_IS_UNION);
if (kind == CPTK_IS_CONVERTIBLE_TO)
@@ -5036,6 +5052,8 @@ finish_trait_expr (cp_trait_kind kind, tree type1, tree type2)
case CPTK_IS_EMPTY:
case CPTK_IS_POD:
case CPTK_IS_POLYMORPHIC:
+ case CPTK_IS_STD_LAYOUT:
+ case CPTK_IS_TRIVIAL:
if (!check_trait_type (type1))
{
error ("incomplete type %qT not allowed", type1);
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index a003b44..255a297 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -2238,36 +2238,108 @@ is_dummy_object (const_tree ob)
&& TREE_OPERAND (ob, 0) == void_zero_node);
}
+/* Returns 1 iff type T is something we want to treat as a scalar type for
+ the purpose of deciding whether it is trivial/POD/standard-layout. */
+
+static bool
+scalarish_type_p (const_tree t)
+{
+ if (t == error_mark_node)
+ return 1;
+
+ return (SCALAR_TYPE_P (t)
+ || TREE_CODE (t) == VECTOR_TYPE);
+}
+
+/* Returns true iff T requires non-trivial default initialization. */
+
+bool
+type_has_nontrivial_default_init (const_tree t)
+{
+ t = strip_array_types (CONST_CAST_TREE (t));
+
+ if (CLASS_TYPE_P (t))
+ return TYPE_HAS_COMPLEX_DFLT (t);
+ else
+ return 0;
+}
+
+/* Returns true iff copying an object of type T is non-trivial. */
+
+bool
+type_has_nontrivial_copy_init (const_tree t)
+{
+ t = strip_array_types (CONST_CAST_TREE (t));
+
+ if (CLASS_TYPE_P (t))
+ return TYPE_HAS_COMPLEX_INIT_REF (t);
+ else
+ return 0;
+}
+
+/* Returns 1 iff type T is a trivial type, as defined in [basic.types]. */
+
+bool
+trivial_type_p (const_tree t)
+{
+ t = strip_array_types (CONST_CAST_TREE (t));
+
+ if (CLASS_TYPE_P (t))
+ return !(TYPE_HAS_COMPLEX_DFLT (t)
+ || TYPE_HAS_COMPLEX_INIT_REF (t)
+ || TYPE_HAS_COMPLEX_ASSIGN_REF (t)
+ || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t));
+ else
+ return scalarish_type_p (t);
+}
+
/* Returns 1 iff type T is a POD type, as defined in [basic.types]. */
-int
+bool
pod_type_p (const_tree t)
{
/* This CONST_CAST is okay because strip_array_types returns its
argument unmodified and we assign it to a const_tree. */
t = strip_array_types (CONST_CAST_TREE(t));
- if (t == error_mark_node)
- return 1;
- if (INTEGRAL_OR_ENUMERATION_TYPE_P (t))
- return 1; /* integral, character or enumeral type */
- if (FLOAT_TYPE_P (t))
- return 1;
- if (TYPE_PTR_P (t))
- return 1; /* pointer to non-member */
- if (TYPE_PTR_TO_MEMBER_P (t))
- return 1; /* pointer to member */
-
- if (TREE_CODE (t) == VECTOR_TYPE)
- return 1; /* vectors are (small) arrays of scalars */
-
- if (! RECORD_OR_UNION_CODE_P (TREE_CODE (t)))
- return 0; /* other non-class type (reference or function) */
- if (! CLASS_TYPE_P (t))
- return 1; /* struct created by the back end */
- if (CLASSTYPE_NON_POD_P (t))
- return 0;
- return 1;
+ if (CLASS_TYPE_P (t))
+ /* [class]/10: A POD struct is a class that is both a trivial class and a
+ standard-layout class, and has no non-static data members of type
+ non-POD struct, non-POD union (or array of such types).
+
+ We don't need to check individual members because if a member is
+ non-std-layout or non-trivial, the class will be too. */
+ return (std_layout_type_p (t) && trivial_type_p (t));
+ else
+ return scalarish_type_p (t);
+}
+
+/* Returns true iff T is POD for the purpose of layout, as defined in the
+ C++ ABI. */
+
+bool
+layout_pod_type_p (const_tree t)
+{
+ t = strip_array_types (CONST_CAST_TREE (t));
+
+ if (CLASS_TYPE_P (t))
+ return !CLASSTYPE_NON_LAYOUT_POD_P (t);
+ else
+ return scalarish_type_p (t);
+}
+
+/* Returns true iff T is a standard-layout type, as defined in
+ [basic.types]. */
+
+bool
+std_layout_type_p (const_tree t)
+{
+ t = strip_array_types (CONST_CAST_TREE (t));
+
+ if (CLASS_TYPE_P (t))
+ return !CLASSTYPE_NON_STD_LAYOUT (t);
+ else
+ return scalarish_type_p (t);
}
/* Nonzero iff type T is a class template implicit specialization. */
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 6a4802e..9e49ce5 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -2017,7 +2017,7 @@ build_class_member_access_expr (tree object, tree member,
in various testsuite cases where a null object is passed where a
vtable access is required. */
if (null_object_p && warn_invalid_offsetof
- && CLASSTYPE_NON_POD_P (object_type)
+ && CLASSTYPE_NON_STD_LAYOUT (object_type)
&& !DECL_FIELD_IS_BASE (member)
&& cp_unevaluated_operand == 0
&& (complain & tf_warning))
@@ -3134,7 +3134,7 @@ convert_arguments (tree typelist, VEC(tree,gc) **values, tree fndecl,
if (fndecl && DECL_BUILT_IN (fndecl)
&& DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CONSTANT_P)
/* Don't do ellipsis conversion for __built_in_constant_p
- as this will result in spurious warnings for non-POD
+ as this will result in spurious errors for non-trivial
types. */
val = require_complete_type (val);
else