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>
* 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 \
contribute.texi compat.texi funding.texi gnu.texi gpl_v3.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 \
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_pod", RID_IS_POD, 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 },
{ "__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_EMPTY, RID_IS_ENUM,
RID_IS_POD, RID_IS_POLYMORPHIC,
RID_IS_STD_LAYOUT, RID_IS_TRIVIAL,
RID_IS_UNION,
/* 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>
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 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;
}

View File

@ -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));

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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 (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).
if (TREE_CODE (t) == VECTOR_TYPE)
return 1; /* vectors are (small) arrays of scalars */
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);
}
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;
/* 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. */

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
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

View File

@ -134,6 +134,7 @@ Introduction, gccint, GNU Compiler Collection (GCC) Internals}.
* Invoking GCC:: Command options supported by @samp{gcc}.
* C Implementation:: How GCC implements the ISO C specification.
* 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.
* Objective-C:: GNU Objective-C runtime features.
* Compatibility:: Binary Compatibility
@ -159,6 +160,7 @@ Introduction, gccint, GNU Compiler Collection (GCC) Internals}.
@include standards.texi
@include invoke.texi
@include implement-c.texi
@include implement-cxx.texi
@include extend.texi
@include objc.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>
* 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 (B));
assert (PTEST (C));
assert (NTEST (C[]));
assert (PTEST (C[]));
assert (PTEST (D));
assert (NTEST (E));
assert (NTEST (E1));

View File

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

View File

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

View File

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

View File

@ -68,8 +68,8 @@ int main()
assert (PTEST (A));
assert (PTEST (A[]));
assert (NTEST (B));
assert (NTEST (C));
assert (NTEST (C[]));
assert (PTEST (C));
assert (PTEST (C[]));
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. */
/* Contributed by Matt Austern <austern@apple.com> 15 May 2003 */
/* { dg-do compile } */
struct X
{
X() : x(3), y(4) { }
int x, y;
protected:
int z;
};
typedef X* pX;
typedef __SIZE_TYPE__ size_t;
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
// Bug: We were aborting after giving a warning about passing a non-POD.
// Suppress the warning about undefined behavior.
// { dg-options "-w" }
struct B {
B() throw() { }
B(const B&) throw() { }
@ -17,5 +14,5 @@ struct X {
struct S { S(...); };
void SillyFunc() {
throw S(X());
throw S(X()); // { dg-error "copy" }
}

View File

@ -6,6 +6,6 @@ void foo(int, ...)
{
va_list va;
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:
String (const char *str);
String (const String&);
};
class UnitList
@ -12,4 +13,4 @@ class 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),
(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;}
int main(){complex c; Complex 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>
struct X {int m;};
struct Y : X {int m;};
struct Y { Y(const Y&); };
struct Z; // { dg-error "forward decl" }
void fn1(va_list args)
{
int i = va_arg (args, int);
Y x = va_arg (args, Y); // { dg-warning "cannot receive" }
Y y = va_arg (args, struct Y); // { dg-warning "cannot receive" }
int &r = va_arg (args, int &); // { dg-warning "cannot receive" }
Y x = va_arg (args, Y); // { dg-error "cannot receive" }
Y y = va_arg (args, struct Y); // { dg-error "cannot receive" }
int &r = va_arg (args, int &); // { dg-error "cannot receive" }
Z z1 = 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 "abort" "abort" { target *-*-* } 24 }
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" }
// { 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_start (argp, somearg);
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);
}
int main (void)
{
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 }
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>
Tom Tromey <tromey@redhat.com>

View File

@ -173,11 +173,18 @@ namespace std
// Member introspection.
/// is_pod
// Could use is_standard_layout && is_trivial instead of the builtin.
template<typename _Tp>
struct is_pod
: 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
template<typename _Tp>
struct has_trivial_default_constructor
@ -202,6 +209,12 @@ namespace std
: 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
template<typename _Tp>
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 *-*-* } 42 }
// { dg-error "invalid use of incomplete type" "" { target *-*-* } 557 }
// { dg-error "declaration of" "" { target *-*-* } 519 }
// { dg-error "invalid use of incomplete type" "" { target *-*-* } 570 }
// { dg-error "declaration of" "" { target *-*-* } 532 }
// { dg-excess-errors "At global scope" }
// { 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 *-*-* } 42 }
// { dg-error "invalid use of incomplete type" "" { target *-*-* } 478 }
// { dg-error "declaration of" "" { target *-*-* } 440 }
// { dg-error "invalid use of incomplete type" "" { target *-*-* } 491 }
// { dg-error "declaration of" "" { target *-*-* } 453 }
// { dg-excess-errors "At global scope" }
// { dg-excess-errors "In instantiation of" }