re PR libstdc++/37907 ([c++0x] support for std::is_standard_layout)

PR libstdc++/37907
	Support std::is_standard_layout and std::is_trivial traits,
	change POD to C++0x version (except for layout).
	* gcc/c-common.c (c_common_reswords): Add __is_standard_layout
	and __is_trivial.
	* gcc/c-common.h (enum rid): Add RID_IS_STD_LAYOUT and RID_IS_TRIVIAL.
	* gcc/cp/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.
	* gcc/cp/class.c (check_bases): Set it.
	(check_field_decls): Likewise.
	(check_bases_and_members): Likewise.
	* gcc/cp/parser.c (cp_parser_primary_expression): Handle RID_IS_STD_LAYOUT,
	RID_IS_TRIVIAL.
	(cp_parser_trait_expr): Likewise.
	* gcc/cp/semantics.c (trait_expr_value): Handle CPTK_IS_STD_LAYOUT,
	CPTK_IS_TRIVIAL.
	(finish_trait_expr): Likewise.
	* gcc/cp/tree.c (scalarish_type_p, trivial_type_p, std_layout_type_p): New.
	(pod_type_p): Use them.
	* gcc/cp/typeck.c (build_class_member_access_expr): Check
	CLASSTYPE_NON_STD_LAYOUT rather than CLASSTYPE_NON_POD_P.
	* libstdc++-v3/include/std/type_traits: Add is_standard_layout, is_trivial.

From-SVN: r149721
This commit is contained in:
Jason Merrill 2009-07-16 16:36:10 -04:00 committed by Jason Merrill
parent b3c5a40978
commit c32097d8b4
37 changed files with 595 additions and 113 deletions

View File

@ -1,3 +1,12 @@
2009-07-16 Jason Merrill <jason@redhat.com>
PR libstdc++/37907
* c-common.c (c_common_reswords): Add __is_standard_layout
and __is_trivial.
* c-common.h (enum rid): Add RID_IS_STD_LAYOUT and RID_IS_TRIVIAL.
* doc/implement-cxx.texi: New.
* doc/gcc.texi: Include it.
2009-07-16 DJ Delorie <dj@redhat.com> 2009-07-16 DJ Delorie <dj@redhat.com>
* config/m32c/m32c.c (m32c_compare_redundant): Avoid removing * config/m32c/m32c.c (m32c_compare_redundant): Avoid removing

View File

@ -3777,7 +3777,7 @@ TEXI_GCC_FILES = gcc.texi gcc-common.texi gcc-vers.texi frontends.texi \
gcov.texi trouble.texi bugreport.texi service.texi \ gcov.texi trouble.texi bugreport.texi service.texi \
contribute.texi compat.texi funding.texi gnu.texi gpl_v3.texi \ contribute.texi compat.texi funding.texi gnu.texi gpl_v3.texi \
fdl.texi contrib.texi cppenv.texi cppopts.texi \ fdl.texi contrib.texi cppenv.texi cppopts.texi \
implement-c.texi arm-neon-intrinsics.texi implement-c.texi implement-cxx.texi arm-neon-intrinsics.texi
TEXI_GCCINT_FILES = gccint.texi gcc-common.texi gcc-vers.texi \ TEXI_GCCINT_FILES = gccint.texi gcc-common.texi gcc-vers.texi \
contribute.texi makefile.texi configterms.texi options.texi \ contribute.texi makefile.texi configterms.texi options.texi \

View File

@ -598,6 +598,8 @@ const struct c_common_resword c_common_reswords[] =
{ "__is_enum", RID_IS_ENUM, D_CXXONLY }, { "__is_enum", RID_IS_ENUM, D_CXXONLY },
{ "__is_pod", RID_IS_POD, D_CXXONLY }, { "__is_pod", RID_IS_POD, D_CXXONLY },
{ "__is_polymorphic", RID_IS_POLYMORPHIC, D_CXXONLY }, { "__is_polymorphic", RID_IS_POLYMORPHIC, D_CXXONLY },
{ "__is_standard_layout", RID_IS_STD_LAYOUT, D_CXXONLY },
{ "__is_trivial", RID_IS_TRIVIAL, D_CXXONLY },
{ "__is_union", RID_IS_UNION, D_CXXONLY }, { "__is_union", RID_IS_UNION, D_CXXONLY },
{ "__imag", RID_IMAGPART, 0 }, { "__imag", RID_IMAGPART, 0 },
{ "__imag__", RID_IMAGPART, 0 }, { "__imag__", RID_IMAGPART, 0 },

View File

@ -110,6 +110,7 @@ enum rid
RID_IS_CONVERTIBLE_TO, RID_IS_CLASS, RID_IS_CONVERTIBLE_TO, RID_IS_CLASS,
RID_IS_EMPTY, RID_IS_ENUM, RID_IS_EMPTY, RID_IS_ENUM,
RID_IS_POD, RID_IS_POLYMORPHIC, RID_IS_POD, RID_IS_POLYMORPHIC,
RID_IS_STD_LAYOUT, RID_IS_TRIVIAL,
RID_IS_UNION, RID_IS_UNION,
/* C++0x */ /* C++0x */

View File

@ -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> 2009-07-14 Taras Glek <tglek@mozilla.com>
Rafael Espindola <espindola@google.com> Rafael Espindola <espindola@google.com>

View File

@ -197,7 +197,6 @@ static conversion *direct_reference_binding (tree, conversion *);
static bool promoted_arithmetic_type_p (tree); static bool promoted_arithmetic_type_p (tree);
static conversion *conditional_conversion (tree, tree); static conversion *conditional_conversion (tree, tree);
static char *name_as_c_string (tree, tree, bool *); static char *name_as_c_string (tree, tree, bool *);
static tree call_builtin_trap (void);
static tree prep_operand (tree); static tree prep_operand (tree);
static void add_candidates (tree, const VEC(tree,gc) *, tree, bool, tree, tree, static void add_candidates (tree, const VEC(tree,gc) *, tree, bool, tree, tree,
int, struct z_candidate **); int, struct z_candidate **);
@ -5042,18 +5041,6 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
return expr; 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 /* ARG is being passed to a varargs function. Perform any conversions
required. Return the converted value. */ required. Return the converted value. */
@ -5082,20 +5069,23 @@ convert_arg_to_ellipsis (tree arg)
arg = require_complete_type (arg); arg = require_complete_type (arg);
if (arg != error_mark_node 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 /* [expr.call] 5.2.2/7:
here and do a bitwise copy, but now cp_expr_size will abort if we Passing a potentially-evaluated argument of class type (Clause 9)
try to do that. 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, 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 it is not potentially-evaluated. */
evaluated. We keep the builtin_trap just as a safety check. */
if (cp_unevaluated_operand == 0) if (cp_unevaluated_operand == 0)
warning (0, "cannot pass objects of non-POD type %q#T through %<...%>; " error ("cannot pass objects of non-trivially-copyable "
"call will abort at runtime", TREE_TYPE (arg)); "type %q#T through %<...%>", TREE_TYPE (arg));
arg = call_builtin_trap ();
arg = build2 (COMPOUND_EXPR, integer_type_node, arg,
integer_zero_node);
} }
return arg; return arg;
@ -5114,16 +5104,16 @@ build_x_va_arg (tree expr, tree type)
if (expr == error_mark_node || !type) if (expr == error_mark_node || !type)
return error_mark_node; 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. */ /* Remove reference types so we don't ICE later on. */
tree type1 = non_reference (type); tree type1 = non_reference (type);
/* Undefined behavior [expr.call] 5.2.2/7. */ /* conditionally-supported behavior [expr.call] 5.2.2/7. */
warning (0, "cannot receive objects of non-POD type %q#T through %<...%>; " error ("cannot receive objects of non-trivially-copyable type %q#T "
"call will abort at runtime", type); "through %<...%>; ", type);
expr = convert (build_pointer_type (type1), null_node); 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); expr = cp_build_indirect_ref (expr, NULL, tf_warning_or_error);
return expr; return expr;
} }

View File

@ -1248,9 +1248,15 @@ check_bases (tree t,
int seen_non_virtual_nearly_empty_base_p; int seen_non_virtual_nearly_empty_base_p;
tree base_binfo; tree base_binfo;
tree binfo; tree binfo;
tree field = NULL_TREE;
seen_non_virtual_nearly_empty_base_p = 0; 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; for (binfo = TYPE_BINFO (t), i = 0;
BINFO_BASE_ITERATE (binfo, i, base_binfo); i++) 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 (t)
|= CLASSTYPE_CONTAINS_EMPTY_CLASS_P (basetype); |= CLASSTYPE_CONTAINS_EMPTY_CLASS_P (basetype);
TYPE_HAS_COMPLEX_DFLT (t) |= TYPE_HAS_COMPLEX_DFLT (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; bool has_pointers;
int any_default_members; int any_default_members;
int cant_pack = 0; int cant_pack = 0;
int field_access = -1;
/* Assume there are no access declarations. */ /* Assume there are no access declarations. */
*access_decls = NULL_TREE; *access_decls = NULL_TREE;
@ -2883,6 +2920,7 @@ check_field_decls (tree t, tree *access_decls,
{ {
tree x = *field; tree x = *field;
tree type = TREE_TYPE (x); tree type = TREE_TYPE (x);
int this_field_access;
next = &TREE_CHAIN (x); next = &TREE_CHAIN (x);
@ -2957,10 +2995,21 @@ check_field_decls (tree t, tree *access_decls,
if (TREE_PRIVATE (x) || TREE_PROTECTED (x)) if (TREE_PRIVATE (x) || TREE_PROTECTED (x))
CLASSTYPE_NON_AGGREGATE (t) = 1; 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 this is of reference type, check if it needs an init. */
if (TREE_CODE (type) == REFERENCE_TYPE) 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) if (DECL_INITIAL (x) == NULL_TREE)
SET_CLASSTYPE_REF_FIELDS_NEED_INIT (t, 1); 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 (TYPE_PACKED (t))
{ {
if (!pod_type_p (type) && !TYPE_PACKED (type)) if (!layout_pod_type_p (type) && !TYPE_PACKED (type))
{ {
warning warning
(0, (0,
@ -3024,10 +3073,13 @@ check_field_decls (tree t, tree *access_decls,
if (DECL_MUTABLE_P (x) || TYPE_HAS_MUTABLE_P (type)) if (DECL_MUTABLE_P (x) || TYPE_HAS_MUTABLE_P (type))
CLASSTYPE_HAS_MUTABLE (t) = 1; 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), /* DR 148 now allows pointers to members (which are POD themselves),
to be allowed in POD structs. */ 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)) if (! zero_init_p (type))
CLASSTYPE_NON_ZERO_INIT_P (t) = 1; 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 /* Check the validity of the bases and members declared in T. Add any
implicitly-generated functions (like copy-constructors and implicitly-generated functions (like copy-constructors and
assignment operators). Compute various flag bits (like 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. */ level: i.e., independently of the ABI in use. */
static void static void
@ -4346,9 +4398,12 @@ check_bases_and_members (tree t)
elsewhere. */ elsewhere. */
CLASSTYPE_NON_AGGREGATE (t) CLASSTYPE_NON_AGGREGATE (t)
|= (type_has_user_provided_constructor (t) || TYPE_POLYMORPHIC_P (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) |= (CLASSTYPE_NON_AGGREGATE (t)
|| saved_nontrivial_dtor || saved_complex_asn_ref); || 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_ASSIGN_REF (t) |= TYPE_CONTAINS_VPTR_P (t);
TYPE_HAS_COMPLEX_DFLT (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 /* 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 make_class_type for this version; this is an artificial type. For
a POD type, we just reuse T. */ 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)); base_t = make_node (TREE_CODE (t));

View File

@ -494,6 +494,8 @@ typedef enum cp_trait_kind
CPTK_IS_ENUM, CPTK_IS_ENUM,
CPTK_IS_POD, CPTK_IS_POD,
CPTK_IS_POLYMORPHIC, CPTK_IS_POLYMORPHIC,
CPTK_IS_STD_LAYOUT,
CPTK_IS_TRIVIAL,
CPTK_IS_UNION CPTK_IS_UNION
} cp_trait_kind; } cp_trait_kind;
@ -1124,6 +1126,7 @@ struct GTY(()) lang_type_class {
unsigned non_aggregate : 1; unsigned non_aggregate : 1;
unsigned has_complex_dflt : 1; unsigned has_complex_dflt : 1;
unsigned has_list_ctor : 1; unsigned has_list_ctor : 1;
unsigned non_std_layout : 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. If 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 /* 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 of this by updating the size of this bitfield whenever you add or
remove a flag. */ remove a flag. */
unsigned dummy : 10; unsigned dummy : 9;
tree primary_base; tree primary_base;
VEC(tree_pair_s,gc) *vcall_indices; 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 CLASSTYPE_HAS_MUTABLE(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->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. */ /* Nonzero means that this class type is not POD for the purpose of layout
#define CLASSTYPE_NON_POD_P(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->non_pod_class) (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 /* Nonzero means that this class contains pod types whose default
initialization is not a zero initialization (namely, pointers to 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 bool stabilize_init (tree, tree *);
extern tree add_stmt_to_compound (tree, tree); extern tree add_stmt_to_compound (tree, tree);
extern void init_tree (void); 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 bool class_tmpl_impl_spec_p (const_tree);
extern int zero_init_p (const_tree); extern int zero_init_p (const_tree);
extern tree strip_typedefs (tree); extern tree strip_typedefs (tree);

View File

@ -2296,6 +2296,12 @@ pp_cxx_trait_expression (cxx_pretty_printer *pp, tree t)
case CPTK_IS_POLYMORPHIC: case CPTK_IS_POLYMORPHIC:
pp_cxx_ws_string (pp, "__is_polymorphic"); pp_cxx_ws_string (pp, "__is_polymorphic");
break; 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: case CPTK_IS_UNION:
pp_cxx_ws_string (pp, "__is_union"); pp_cxx_ws_string (pp, "__is_union");
break; break;

View File

@ -2473,20 +2473,28 @@ declare_local_label (tree id)
static int static int
decl_jump_unsafe (tree decl) 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) if (TREE_CODE (decl) != VAR_DECL || TREE_STATIC (decl)
|| TREE_TYPE (decl) == error_mark_node) || type == error_mark_node)
return 0; 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)) || DECL_NONTRIVIALLY_INITIALIZED_P (decl))
return 2; return 2;
if (pod_type_p (TREE_TYPE (decl))) if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (decl)))
return 0; return 1;
/* The POD stuff is just pedantry; why should it matter if the class return 0;
contains a field of pointer to member type? */
return 1;
} }
/* A subroutine of check_previous_goto_1 to identify a branch to the user. */ /* 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) if (problem > 1)
error (" crosses initialization of %q+#D", new_decls); error (" crosses initialization of %q+#D", new_decls);
else 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) if (b == level)
@ -2656,7 +2665,8 @@ check_goto (tree decl)
else if (u > 1) else if (u > 1)
error (" skips initialization of %q+#D", b); error (" skips initialization of %q+#D", b);
else 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) 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) if (TREE_CODE (decl) == VAR_DECL)
{ {
/* Only PODs can have thread-local storage. Other types may require /* Only variables with trivial initialization and destruction can
various kinds of non-trivial initialization. */ have thread-local storage. */
if (DECL_THREAD_LOCAL_P (decl) && !pod_type_p (TREE_TYPE (decl))) if (DECL_THREAD_LOCAL_P (decl)
error ("%qD cannot be thread-local because it has non-POD type %qT", && (type_has_nontrivial_default_init (TREE_TYPE (decl))
decl, 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, /* If this is a local variable that will need a mangled name,
register it now. We must do this before processing the register it now. We must do this before processing the
initializer for the variable, since the initialization might initializer for the variable, since the initialization might

View File

@ -2703,7 +2703,7 @@ build_vec_init (tree base, tree maxindex, tree init,
|| ! TYPE_HAS_NONTRIVIAL_DESTRUCTOR (inner_elt_type))) || ! TYPE_HAS_NONTRIVIAL_DESTRUCTOR (inner_elt_type)))
|| from_array)) || 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 brace-enclosed initializers. In this case, digest_init and
store_constructor will handle the semantics for us. */ 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) 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. */ brace-enclosed initializers. */
unsigned HOST_WIDE_INT idx; unsigned HOST_WIDE_INT idx;
tree elt; tree elt;

View File

@ -3399,6 +3399,8 @@ cp_parser_primary_expression (cp_parser *parser,
case RID_IS_ENUM: case RID_IS_ENUM:
case RID_IS_POD: case RID_IS_POD:
case RID_IS_POLYMORPHIC: case RID_IS_POLYMORPHIC:
case RID_IS_STD_LAYOUT:
case RID_IS_TRIVIAL:
case RID_IS_UNION: case RID_IS_UNION:
return cp_parser_trait_expr (parser, token->keyword); 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: case RID_IS_POLYMORPHIC:
kind = CPTK_IS_POLYMORPHIC; kind = CPTK_IS_POLYMORPHIC;
break; 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: case RID_IS_UNION:
kind = CPTK_IS_UNION; kind = CPTK_IS_UNION;
break; break;

View File

@ -4878,6 +4878,7 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
switch (kind) switch (kind)
{ {
case CPTK_HAS_NOTHROW_ASSIGN: case CPTK_HAS_NOTHROW_ASSIGN:
type1 = strip_array_types (type1);
return (!CP_TYPE_CONST_P (type1) && type_code1 != REFERENCE_TYPE return (!CP_TYPE_CONST_P (type1) && type_code1 != REFERENCE_TYPE
&& (trait_expr_value (CPTK_HAS_TRIVIAL_ASSIGN, type1, type2) && (trait_expr_value (CPTK_HAS_TRIVIAL_ASSIGN, type1, type2)
|| (CLASS_TYPE_P (type1) || (CLASS_TYPE_P (type1)
@ -4885,8 +4886,11 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
true)))); true))));
case CPTK_HAS_TRIVIAL_ASSIGN: 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 return (!CP_TYPE_CONST_P (type1) && type_code1 != REFERENCE_TYPE
&& (pod_type_p (type1) && (trivial_type_p (type1)
|| (CLASS_TYPE_P (type1) || (CLASS_TYPE_P (type1)
&& TYPE_HAS_TRIVIAL_ASSIGN_REF (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: case CPTK_HAS_TRIVIAL_CONSTRUCTOR:
type1 = strip_array_types (type1); type1 = strip_array_types (type1);
return (pod_type_p (type1) return (trivial_type_p (type1)
|| (CLASS_TYPE_P (type1) && TYPE_HAS_TRIVIAL_DFLT (type1))); || (CLASS_TYPE_P (type1) && TYPE_HAS_TRIVIAL_DFLT (type1)));
case CPTK_HAS_NOTHROW_COPY: case CPTK_HAS_NOTHROW_COPY:
type1 = strip_array_types (type1);
return (trait_expr_value (CPTK_HAS_TRIVIAL_COPY, type1, type2) return (trait_expr_value (CPTK_HAS_TRIVIAL_COPY, type1, type2)
|| (CLASS_TYPE_P (type1) || (CLASS_TYPE_P (type1)
&& classtype_has_nothrow_assign_or_copy_p (type1, false))); && classtype_has_nothrow_assign_or_copy_p (type1, false)));
case CPTK_HAS_TRIVIAL_COPY: 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))); || (CLASS_TYPE_P (type1) && TYPE_HAS_TRIVIAL_INIT_REF (type1)));
case CPTK_HAS_TRIVIAL_DESTRUCTOR: case CPTK_HAS_TRIVIAL_DESTRUCTOR:
type1 = strip_array_types (type1); 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) || (CLASS_TYPE_P (type1)
&& TYPE_HAS_TRIVIAL_DESTRUCTOR (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: case CPTK_IS_POLYMORPHIC:
return (CLASS_TYPE_P (type1) && TYPE_POLYMORPHIC_P (type1)); 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: case CPTK_IS_UNION:
return (type_code1 == UNION_TYPE); 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_ENUM
|| kind == CPTK_IS_POD || kind == CPTK_IS_POD
|| kind == CPTK_IS_POLYMORPHIC || kind == CPTK_IS_POLYMORPHIC
|| kind == CPTK_IS_STD_LAYOUT
|| kind == CPTK_IS_TRIVIAL
|| kind == CPTK_IS_UNION); || kind == CPTK_IS_UNION);
if (kind == CPTK_IS_CONVERTIBLE_TO) 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_EMPTY:
case CPTK_IS_POD: case CPTK_IS_POD:
case CPTK_IS_POLYMORPHIC: case CPTK_IS_POLYMORPHIC:
case CPTK_IS_STD_LAYOUT:
case CPTK_IS_TRIVIAL:
if (!check_trait_type (type1)) if (!check_trait_type (type1))
{ {
error ("incomplete type %qT not allowed", type1); error ("incomplete type %qT not allowed", type1);

View File

@ -2238,36 +2238,108 @@ is_dummy_object (const_tree ob)
&& TREE_OPERAND (ob, 0) == void_zero_node); && 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]. */ /* Returns 1 iff type T is a POD type, as defined in [basic.types]. */
int bool
pod_type_p (const_tree t) pod_type_p (const_tree t)
{ {
/* This CONST_CAST is okay because strip_array_types returns its /* This CONST_CAST is okay because strip_array_types returns its
argument unmodified and we assign it to a const_tree. */ argument unmodified and we assign it to a const_tree. */
t = strip_array_types (CONST_CAST_TREE(t)); t = strip_array_types (CONST_CAST_TREE(t));
if (t == error_mark_node) if (CLASS_TYPE_P (t))
return 1; /* [class]/10: A POD struct is a class that is both a trivial class and a
if (INTEGRAL_OR_ENUMERATION_TYPE_P (t)) standard-layout class, and has no non-static data members of type
return 1; /* integral, character or enumeral type */ non-POD struct, non-POD union (or array of such types).
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) We don't need to check individual members because if a member is
return 1; /* vectors are (small) arrays of scalars */ 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);
}
if (! RECORD_OR_UNION_CODE_P (TREE_CODE (t))) /* Returns true iff T is POD for the purpose of layout, as defined in the
return 0; /* other non-class type (reference or function) */ C++ ABI. */
if (! CLASS_TYPE_P (t))
return 1; /* struct created by the back end */ bool
if (CLASSTYPE_NON_POD_P (t)) layout_pod_type_p (const_tree t)
return 0; {
return 1; 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. */ /* Nonzero iff type T is a class template implicit specialization. */

View File

@ -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 in various testsuite cases where a null object is passed where a
vtable access is required. */ vtable access is required. */
if (null_object_p && warn_invalid_offsetof if (null_object_p && warn_invalid_offsetof
&& CLASSTYPE_NON_POD_P (object_type) && CLASSTYPE_NON_STD_LAYOUT (object_type)
&& !DECL_FIELD_IS_BASE (member) && !DECL_FIELD_IS_BASE (member)
&& cp_unevaluated_operand == 0 && cp_unevaluated_operand == 0
&& (complain & tf_warning)) && (complain & tf_warning))
@ -3134,7 +3134,7 @@ convert_arguments (tree typelist, VEC(tree,gc) **values, tree fndecl,
if (fndecl && DECL_BUILT_IN (fndecl) if (fndecl && DECL_BUILT_IN (fndecl)
&& DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CONSTANT_P) && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CONSTANT_P)
/* Don't do ellipsis conversion for __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. */ types. */
val = require_complete_type (val); val = require_complete_type (val);
else else

View File

@ -134,6 +134,7 @@ Introduction, gccint, GNU Compiler Collection (GCC) Internals}.
* Invoking GCC:: Command options supported by @samp{gcc}. * Invoking GCC:: Command options supported by @samp{gcc}.
* C Implementation:: How GCC implements the ISO C specification. * C Implementation:: How GCC implements the ISO C specification.
* C Extensions:: GNU extensions to the C language family. * C Extensions:: GNU extensions to the C language family.
* C++ Implementation:: How GCC implements the ISO C++ specification.
* C++ Extensions:: GNU extensions to the C++ language. * C++ Extensions:: GNU extensions to the C++ language.
* Objective-C:: GNU Objective-C runtime features. * Objective-C:: GNU Objective-C runtime features.
* Compatibility:: Binary Compatibility * Compatibility:: Binary Compatibility
@ -159,6 +160,7 @@ Introduction, gccint, GNU Compiler Collection (GCC) Internals}.
@include standards.texi @include standards.texi
@include invoke.texi @include invoke.texi
@include implement-c.texi @include implement-c.texi
@include implement-cxx.texi
@include extend.texi @include extend.texi
@include objc.texi @include objc.texi
@include compat.texi @include compat.texi

View File

@ -0,0 +1,47 @@
@c Copyright (C) 2009
@c Free Software Foundation, Inc.
@c This is part of the GCC manual.
@c For copying conditions, see the file gcc.texi.
@node C++ Implementation
@chapter C++ Implementation-defined behavior
@cindex implementation-defined behavior, C++ language
A conforming implementation of ISO C++ is required to document its
choice of behavior in each of the areas that are designated
``implementation defined''. The following lists all such areas,
along with the section numbers from the ISO/IEC 14822:1998 and ISO/IEC
14822:2003 standards. Some areas are only implementation-defined in
one version of the standard.
Some choices depend on the externally determined ABI for the platform
(including standard character encodings) which GCC follows; these are
listed as ``determined by ABI'' below. @xref{Compatibility, , Binary
Compatibility}, and @uref{http://gcc.gnu.org/readings.html}. Some
choices are documented in the preprocessor manual.
@xref{Implementation-defined behavior, , Implementation-defined
behavior, cpp, The C Preprocessor}. Some choices are documented in
the corresponding document for the C language. @xref{C
Implementation}. Some choices are made by the library and operating
system (or other environment when compiling for a freestanding
environment); refer to their documentation for details.
@menu
* Conditionally-supported behavior::
@end menu
@node Conditionally-supported behavior
@section Conditionally-supported behavior
@cite{Each implementation shall include documentation that identifies
all conditionally-supported constructs that it does not support (C++0x
1.4).}
@itemize @bullet
@item
@cite{Whether an argument of class type with a non-trivial copy
constructor or destructor can be passed to ... (C++0x 5.2.2).}
Such argument passing is not supported.
@end itemize

View File

@ -1,3 +1,21 @@
2009-07-16 Jason Merrill <jason@redhat.com>
PR libstdc++/37907
* g++.dg/cpp0x/std-layout1.C: New.
* g++.dg/ext/has_nothrow_assign.C: Fix.
* g++.dg/ext/has_nothrow_copy.C: Fix.
* g++.dg/ext/has_trivial_assign.C: Fix.
* g++.dg/ext/has_trivial_copy.C: Fix.
* g++.dg/ext/is_pod.C: Fix.
* g++.dg/other/offsetof3.C: Adjust.
* g++.dg/overload/ellipsis1.C: Adjust.
* g++.dg/warn/var-args1.C: Adjust.
* g++.old-deja/g++.brendan/crash63.C: Adjust.
* g++.old-deja/g++.brendan/crash64.C: Adjust.
* g++.old-deja/g++.brendan/overload8.C: Adjust.
* g++.old-deja/g++.other/vaarg3.C: Adjust.
* g++.old-deja/g++.pt/vaarg3.C: Adjust.
2009-07-16 Kaveh R. Ghazi <ghazi@caip.rutgers.edu> 2009-07-16 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* gcc.dg/torture/builtin-math-5.c: Add more cases. * gcc.dg/torture/builtin-math-5.c: Add more cases.

View File

@ -0,0 +1,91 @@
// { dg-options "-std=c++0x" }
// [basic.types]/10:
// Scalar types, standard-layout class types (Clause 9), arrays of such
// types and cv-qualified versions of these types (3.9.3) are collectively
// called standard-layout types.
// [class]/7:
// A standard-layout class is a class that:
// * has no non-static data members of type non-standard-layout class (or
// array of such types) or reference,
// * has no virtual functions (10.3) and no virtual base classes (10.1),
// * has the same access control (Clause 11) for all non-static data members,
// * has no non-standard-layout base classes,
// * 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, and
// * has no base classes of the same type as the first non-static data member.
#include <type_traits>
#define TRY(expr) static_assert (expr, #expr)
#define YES(type) TRY(std::is_standard_layout<type>::value); \
TRY(std::is_standard_layout<type[]>::value); \
TRY(std::is_standard_layout<const volatile type>::value);
#define NO(type) TRY(!std::is_standard_layout<type>::value); \
TRY(!std::is_standard_layout<type[]>::value); \
TRY(!std::is_standard_layout<const volatile type>::value);
#define NONPOD(type) TRY(!std::is_pod<type>::value); \
TRY(!std::is_pod<type[]>::value); \
TRY(!std::is_pod<const volatile type>::value);
struct A;
YES(int);
YES(__complex int);
YES(void *);
YES(int A::*);
typedef int (A::*pmf)();
YES(pmf);
struct A { ~A(); };
YES(A);
NONPOD(A);
struct F: public A { int i; };
YES(F);
NONPOD(F);
struct G: public A { A a; };
NO(G);
struct M { A a; };
YES(M);
class B
{
int i;
__complex int c;
void *p;
double ar[4];
int A::* pm;
int (A::*pmf)();
};
YES(B);
struct D: public B { };
YES(D);
struct E: public B { int q; };
NO(E);
struct D2: public B { };
YES(D2);
struct I: public D, public D2 { };
NO(I);
struct C
{
int i;
private:
int j;
};
NO(C);
struct H: public C { };
NO(H);
struct N { C c; };
NO(N);
struct J { virtual void f(); };
struct J2: J { };
NO(J);
NO(J2);
struct K { };
struct L: virtual K {};
YES(K);
NO(L);

View File

@ -0,0 +1,82 @@
// { dg-options "-std=c++0x" }
// [basic.types]/10:
// Scalar types, trivial class types (Clause 9), arrays of such types and
// cv-qualified versions of these types (3.9.3) are collectively called
// trivial types.
// [class]/6:
// A trivially copyable class is a class that:
// * has no non-trivial copy constructors (12.8),
// * has no non-trivial copy assignment operators (13.5.3, 12.8), and
// * has a trivial destructor (12.4).
// A trivial class is a class that has a trivial default constructor (12.1)
// and is trivially copyable.
#include <type_traits>
#define TRY(expr) static_assert (expr, #expr)
#define YES(type) TRY(std::is_trivial<type>::value); \
TRY(std::is_trivial<type[]>::value); \
TRY(std::is_trivial<const volatile type>::value);
#define NO(type) TRY(!std::is_trivial<type>::value); \
TRY(!std::is_trivial<type[]>::value); \
TRY(!std::is_trivial<const volatile type>::value);
struct A;
YES(int);
YES(__complex int);
YES(void *);
YES(int A::*);
typedef int (A::*pmf)();
YES(pmf);
struct A { ~A(); };
NO(A);
struct F: public A { int i; };
NO(F);
struct G: public A { A a; };
NO(G);
struct M { A a; };
NO(M);
class B
{
int i;
__complex int c;
void *p;
double ar[4];
int A::* pm;
int (A::*pmf)();
};
YES(B);
struct D: public B { };
YES(D);
struct E: public B { int q; };
YES(E);
struct D2: public B { };
YES(D2);
struct I: public D, public D2 { };
YES(I);
struct C
{
int i;
private:
int j;
};
YES(C);
struct H: public C { };
YES(H);
struct N { C c; };
YES(N);
struct J { virtual void f(); };
struct J2: J { };
NO(J);
NO(J2);
struct K { };
struct L: virtual K {};
YES(K);
NO(L);

View File

@ -134,7 +134,7 @@ int main()
assert (PTEST (A)); assert (PTEST (A));
assert (PTEST (B)); assert (PTEST (B));
assert (PTEST (C)); assert (PTEST (C));
assert (NTEST (C[])); assert (PTEST (C[]));
assert (PTEST (D)); assert (PTEST (D));
assert (NTEST (E)); assert (NTEST (E));
assert (NTEST (E1)); assert (NTEST (E1));

View File

@ -124,7 +124,7 @@ int main()
assert (PTEST (A)); assert (PTEST (A));
assert (PTEST (B)); assert (PTEST (B));
assert (PTEST (C)); assert (PTEST (C));
assert (NTEST (C[])); assert (PTEST (C[]));
assert (PTEST (D)); assert (PTEST (D));
assert (NTEST (E)); assert (NTEST (E));
assert (NTEST (E1)); assert (NTEST (E1));

View File

@ -96,7 +96,7 @@ int main()
assert (NTEST (C)); assert (NTEST (C));
assert (NTEST (D)); assert (NTEST (D));
assert (PTEST (E)); assert (PTEST (E));
assert (NTEST (E[])); assert (PTEST (E[]));
assert (PTEST (F)); assert (PTEST (F));
assert (NTEST (G)); assert (NTEST (G));
assert (NTEST (const A)); assert (NTEST (const A));

View File

@ -96,7 +96,7 @@ int main()
assert (NTEST (C)); assert (NTEST (C));
assert (NTEST (D)); assert (NTEST (D));
assert (PTEST (E)); assert (PTEST (E));
assert (NTEST (E[])); assert (PTEST (E[]));
assert (PTEST (F)); assert (PTEST (F));
assert (NTEST (G)); assert (NTEST (G));
assert (PTEST (B&)); assert (PTEST (B&));

View File

@ -68,8 +68,8 @@ int main()
assert (PTEST (A)); assert (PTEST (A));
assert (PTEST (A[])); assert (PTEST (A[]));
assert (NTEST (B)); assert (NTEST (B));
assert (NTEST (C)); assert (PTEST (C));
assert (NTEST (C[])); assert (PTEST (C[]));
return 0; return 0;
} }

View File

@ -1,16 +1,17 @@
/* Verify that offsetof warns if given a non-POD */ /* Verify that offsetof warns if given a non-standard-layout class */
/* Copyright (C) 2003 Free Software Foundation, Inc. */ /* Copyright (C) 2003 Free Software Foundation, Inc. */
/* Contributed by Matt Austern <austern@apple.com> 15 May 2003 */ /* Contributed by Matt Austern <austern@apple.com> 15 May 2003 */
/* { dg-do compile } */ /* { dg-do compile } */
struct X struct X
{ {
X() : x(3), y(4) { }
int x, y; int x, y;
protected:
int z;
}; };
typedef X* pX; typedef X* pX;
typedef __SIZE_TYPE__ size_t; typedef __SIZE_TYPE__ size_t;
size_t yoff = size_t(&(pX(0)->y)); /* { dg-warning "invalid access" "" } */ size_t yoff = size_t(&(pX(0)->y)); /* { dg-warning "invalid access" "" } */
/* { dg-warning "macro was used incorrectly" "macro" { target *-*-* } 15 } */ /* { dg-warning "macro was used incorrectly" "macro" { target *-*-* } 16 } */

View File

@ -1,9 +1,6 @@
// PR c++/15142 // PR c++/15142
// Bug: We were aborting after giving a warning about passing a non-POD. // Bug: We were aborting after giving a warning about passing a non-POD.
// Suppress the warning about undefined behavior.
// { dg-options "-w" }
struct B { struct B {
B() throw() { } B() throw() { }
B(const B&) throw() { } B(const B&) throw() { }
@ -17,5 +14,5 @@ struct X {
struct S { S(...); }; struct S { S(...); };
void SillyFunc() { void SillyFunc() {
throw S(X()); throw S(X()); // { dg-error "copy" }
} }

View File

@ -6,6 +6,6 @@ void foo(int, ...)
{ {
va_list va; va_list va;
int i; int i;
i = va_arg(va, int&); /* { dg-warning "cannot receive objects" } */ i = va_arg(va, int&); /* { dg-error "cannot receive objects" } */
} }

View File

@ -4,6 +4,7 @@ class String
{ {
public: public:
String (const char *str); String (const char *str);
String (const String&);
}; };
class UnitList class UnitList
@ -12,4 +13,4 @@ class UnitList
UnitList (...); UnitList (...);
}; };
UnitList unit_list (String("keV")); // { dg-warning "" } cannot pass non-pod UnitList unit_list (String("keV")); // { dg-error "" } cannot pass non-pod

View File

@ -16,4 +16,4 @@ struct metatype { int base_list; };
static _type_desc _type_metatype("metatype", sizeof(metatype), static _type_desc _type_metatype("metatype", sizeof(metatype),
(RF_Ptr)0, 0, 1, 1, (RF_Ptr)0, 0, 1, 1,
_im_pers_mem_spec( ((size_t)&((( metatype *)0)-> base_list )) , 1)); // { dg-warning "" } cannot pass non-pod _im_pers_mem_spec( ((size_t)&((( metatype *)0)-> base_list )) , 1));

View File

@ -6,4 +6,4 @@ class Complex{public:double re,im;
void zxcvbnm(int n,...){n=1;} void zxcvbnm(int n,...){n=1;}
int main(){complex c; Complex C; int main(){complex c; Complex C;
zxcvbnm(1,c); zxcvbnm(1,c);
zxcvbnm(1,C);} // { dg-warning "" } cannot pass non pod zxcvbnm(1,C);}

View File

@ -9,14 +9,14 @@
#include <stdarg.h> #include <stdarg.h>
struct X {int m;}; struct X {int m;};
struct Y : X {int m;}; struct Y { Y(const Y&); };
struct Z; // { dg-error "forward decl" } struct Z; // { dg-error "forward decl" }
void fn1(va_list args) void fn1(va_list args)
{ {
int i = va_arg (args, int); int i = va_arg (args, int);
Y x = va_arg (args, Y); // { dg-warning "cannot receive" } Y x = va_arg (args, Y); // { dg-error "cannot receive" }
Y y = va_arg (args, struct Y); // { dg-warning "cannot receive" } Y y = va_arg (args, struct Y); // { dg-error "cannot receive" }
int &r = va_arg (args, int &); // { dg-warning "cannot receive" } int &r = va_arg (args, int &); // { dg-error "cannot receive" }
Z z1 = va_arg (args, Z); // { dg-error "incomplete" } Z z1 = va_arg (args, Z); // { dg-error "incomplete" }
const Z &z2 = va_arg (args, Z); // { dg-error "incomplete" } const Z &z2 = va_arg (args, Z); // { dg-error "incomplete" }
@ -25,7 +25,8 @@ void fn1(va_list args)
// { dg-message "should pass" "pass" { target *-*-* } 24 } // { dg-message "should pass" "pass" { target *-*-* } 24 }
// { dg-message "abort" "abort" { target *-*-* } 24 } // { dg-message "abort" "abort" { target *-*-* } 24 }
va_arg (args, int []); // { dg-error "array with unspecified bounds" } promote va_arg (args, int []); // { dg-error "array with unspecified bounds" } promote
va_arg (args, int ()); // { dg-warning "non-POD" } promote va_arg (args, int ()); // { dg-warning "promoted" } promote
// { dg-message "abort" "abort" { target *-*-* } 28 }
va_arg (args, bool); // { dg-warning "promote" "promote" } va_arg (args, bool); // { dg-warning "promote" "promote" }
// { dg-message "abort" "abort" { target *-*-* } 29 } // { dg-message "abort" "abort" { target *-*-* } 30 }
} }

View File

@ -14,14 +14,14 @@ void PrintArgs (Type somearg, ...)
va_list argp; va_list argp;
va_start (argp, somearg); va_start (argp, somearg);
Type value; Type value;
value = va_arg (argp, Type); // { dg-warning "non-POD" } cannot pass non-POD value = va_arg (argp, Type); // { dg-error "cannot receive" } cannot pass non-POD
va_end (argp); va_end (argp);
} }
int main (void) int main (void)
{ {
A dummy; A dummy;
PrintArgs (dummy, dummy); // { dg-warning "non-POD" } cannot pass non-POD PrintArgs (dummy, dummy); // { dg-error "cannot pass" } cannot pass non-POD
// { dg-message "instantiated" "inst" { target *-*-* } 24 } // { dg-message "instantiated" "inst" { target *-*-* } 24 }
return 0; return 0;
} }

View File

@ -1,3 +1,11 @@
2009-07-16 Jason Merrill <jason@redhat.com>
PR libstdc++/37907
* include/std/type_traits: Add is_standard_layout, is_trivial.
* testsuite/20_util/make_signed/requirements/typedefs_neg.cc,
testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc:
Update line numbers.
2009-07-16 Phil Muldoon <pmuldoon@redhat.com> 2009-07-16 Phil Muldoon <pmuldoon@redhat.com>
Tom Tromey <tromey@redhat.com> Tom Tromey <tromey@redhat.com>

View File

@ -173,11 +173,18 @@ namespace std
// Member introspection. // Member introspection.
/// is_pod /// is_pod
// Could use is_standard_layout && is_trivial instead of the builtin.
template<typename _Tp> template<typename _Tp>
struct is_pod struct is_pod
: public integral_constant<bool, __is_pod(_Tp)> : public integral_constant<bool, __is_pod(_Tp)>
{ }; { };
/// is_standard_layout
template<typename _Tp>
struct is_standard_layout
: public integral_constant<bool, __is_standard_layout(_Tp)>
{ };
/// has_trivial_default_constructor /// has_trivial_default_constructor
template<typename _Tp> template<typename _Tp>
struct has_trivial_default_constructor struct has_trivial_default_constructor
@ -202,6 +209,12 @@ namespace std
: public integral_constant<bool, __has_trivial_destructor(_Tp)> : public integral_constant<bool, __has_trivial_destructor(_Tp)>
{ }; { };
/// is_trivial
template<typename _Tp>
struct is_trivial
: public integral_constant<bool, __is_trivial(_Tp)>
{ };
/// has_nothrow_default_constructor /// has_nothrow_default_constructor
template<typename _Tp> template<typename _Tp>
struct has_nothrow_default_constructor struct has_nothrow_default_constructor

View File

@ -48,8 +48,8 @@ void test01()
// { dg-error "instantiated from here" "" { target *-*-* } 40 } // { dg-error "instantiated from here" "" { target *-*-* } 40 }
// { dg-error "instantiated from here" "" { target *-*-* } 42 } // { dg-error "instantiated from here" "" { target *-*-* } 42 }
// { dg-error "invalid use of incomplete type" "" { target *-*-* } 557 } // { dg-error "invalid use of incomplete type" "" { target *-*-* } 570 }
// { dg-error "declaration of" "" { target *-*-* } 519 } // { dg-error "declaration of" "" { target *-*-* } 532 }
// { dg-excess-errors "At global scope" } // { dg-excess-errors "At global scope" }
// { dg-excess-errors "In instantiation of" } // { dg-excess-errors "In instantiation of" }

View File

@ -48,8 +48,8 @@ void test01()
// { dg-error "instantiated from here" "" { target *-*-* } 40 } // { dg-error "instantiated from here" "" { target *-*-* } 40 }
// { dg-error "instantiated from here" "" { target *-*-* } 42 } // { dg-error "instantiated from here" "" { target *-*-* } 42 }
// { dg-error "invalid use of incomplete type" "" { target *-*-* } 478 } // { dg-error "invalid use of incomplete type" "" { target *-*-* } 491 }
// { dg-error "declaration of" "" { target *-*-* } 440 } // { dg-error "declaration of" "" { target *-*-* } 453 }
// { dg-excess-errors "At global scope" } // { dg-excess-errors "At global scope" }
// { dg-excess-errors "In instantiation of" } // { dg-excess-errors "In instantiation of" }