re PR c++/26099 (support for type traits is not available)

gcc/
2007-03-30  Paolo Carlini  <pcarlini@suse.de>

	PR c++/26099
	* c-common.h (enum rid): Add RID_HAS_NOTHROW_ASSIGN,
	RID_HAS_NOTHROW_CONSTRUCTOR, RID_HAS_NOTHROW_COPY,
	RID_HAS_TRIVIAL_ASSIGN, RID_HAS_TRIVIAL_CONSTRUCTOR,
	RID_HAS_TRIVIAL_COPY, RID_HAS_TRIVIAL_DESTRUCTOR,
	RID_HAS_VIRTUAL_DESTRUCTOR, RID_IS_ABSTRACT, RID_IS_BASE_OF,
	RID_IS_CONVERTIBLE_TO, RID_IS_CLASS, RID_IS_EMPTY, RID_IS_ENUM,
	RID_IS_POD, RID_IS_POLYMORPHIC, RID_IS_UNION, as
	C++ extensions.
	* doc/extend.texi (Extensions to the C++ Language): Add Type Traits.

gcc/cp/
2007-03-30  Paolo Carlini  <pcarlini@suse.de>

	PR c++/26099
	* cp-tree.h (enum cp_trait_kind, struct tree_trait_expr,
	TRAIT_EXPR_TYPE1, TRAIT_EXPR_TYPE2, TRAIT_EXPR_KIND): Add.
	(enum cp_tree_node_structure_enum, union lang_tree_node): Update.
	(CLASS_TYPE_NON_UNION_P): Add.
	(struct lang_type_class): Add has_complex_dflt.
	(TYPE_HAS_COMPLEX_DFLT, TYPE_HAS_TRIVIAL_DFLT): Add.
	(locate_copy, locate_ctor, locate_dtor, finish_trait_expr): Declare.
	* cp-tree.def: Add TRAIT_EXPR.
	* cp-objcp-common.c (cp_tree_size): Add TRAIT_EXPR case.
	* lex.c (struct resword): Add __has_nothrow_assign,
	__has_nothrow_constructor, __has_nothrow_copy, __has_trivial_assign,
	__has_trivial_constructor, __has_trivial_copy,
	__has_trivial_destructor, __has_virtual_destructor, __is_abstract,
	__is_base_of, __is_class, __is_convertible_to, __is_empty, __is_enum,
	__is_pod, __is_polymorphic, __is_union.
	* parser.c (cp_parser_primary_expression): Deal with the new RIDs.
	(cp_parser_trait_expr): New.
	* semantics.c (finish_trait_expr, trait_expr_value
	classtype_has_nothrow_copy_or_assign_p): New.
	* method.c (locate_copy, locate_ctor, locate_dtor): Do not define
	as static.
	* decl.c (cp_tree_node_structure): Add TRAIT_EXPR.
	* class.c (check_bases, check_field_decl, check_bases_and_members):
	Deal with TYPE_HAS_COMPLEX_DFLT (t) too.
	* pt.c (uses_template_parms, tsubst_copy_and_build,
	value_dependent_expression_p, type_dependent_expression_p): Deal with
	TRAIT_EXPR.
	* tree.c (cp_walk_subtrees): Deal with TRAIT_EXPR.

gcc/testsuite/
2007-03-30  Paolo Carlini  <pcarlini@suse.de>

	PR c++/26099
	* g++.dg/ext/is_base_of.C: New.
	* g++.dg/ext/has_virtual_destructor.C: New.
	* g++.dg/ext/is_polymorphic.C: New.
	* g++.dg/ext/is_base_of_diagnostic.C: New.
	* g++.dg/ext/is_enum.C: New.
	* g++.dg/ext/has_nothrow_assign.C: New.
	* g++.dg/ext/has_nothrow_constructor.C: New.
	* g++.dg/ext/is_empty.C: New.
	* g++.dg/ext/has_trivial_copy.C: New.
	* g++.dg/ext/has_trivial_assign.C: New.
	* g++.dg/ext/is_abstract.C: New.
	* g++.dg/ext/is_pod.C: New.
	* g++.dg/ext/has_nothrow_copy.C: New.
	* g++.dg/ext/is_class.C: New.
	* g++.dg/ext/has_trivial_constructor.C: New.
	* g++.dg/ext/is_union.C: New.
	* g++.dg/ext/has_trivial_destructor.C: New.
	* g++.dg/tree-ssa/pr22444.C: Adjust, avoid __is_pod.
	* g++.dg/template/crash43.C: Likewise.

libstdc++-v3/
2007-03-30  Paolo Carlini  <pcarlini@suse.de>

	PR c++/26099
	* include/bits/cpp_type_traits.h (struct __is_pod, struct __is_empty):
	Remove.
	* include/bits/valarray_array.h: Adjust.
	* include/bits/allocator.h: Likewise.
	* include/bits/stl_tree.h: Likewise.

From-SVN: r123366
This commit is contained in:
Paolo Carlini 2007-03-30 19:45:57 +00:00 committed by Paolo Carlini
parent c7a0240aa5
commit cb68ec5005
40 changed files with 2240 additions and 68 deletions

View File

@ -1,3 +1,16 @@
2007-03-30 Paolo Carlini <pcarlini@suse.de>
PR c++/26099
* c-common.h (enum rid): Add RID_HAS_NOTHROW_ASSIGN,
RID_HAS_NOTHROW_CONSTRUCTOR, RID_HAS_NOTHROW_COPY,
RID_HAS_TRIVIAL_ASSIGN, RID_HAS_TRIVIAL_CONSTRUCTOR,
RID_HAS_TRIVIAL_COPY, RID_HAS_TRIVIAL_DESTRUCTOR,
RID_HAS_VIRTUAL_DESTRUCTOR, RID_IS_ABSTRACT, RID_IS_BASE_OF,
RID_IS_CONVERTIBLE_TO, RID_IS_CLASS, RID_IS_EMPTY, RID_IS_ENUM,
RID_IS_POD, RID_IS_POLYMORPHIC, RID_IS_UNION, as
C++ extensions.
* doc/extend.texi (Extensions to the C++ Language): Add Type Traits.
2007-03-30 Steven Bosscher <steven@gcc.gnu.org> 2007-03-30 Steven Bosscher <steven@gcc.gnu.org>
* regmove.c: Move all of pass_stack_adjustments from here... * regmove.c: Move all of pass_stack_adjustments from here...

View File

@ -90,6 +90,17 @@ enum rid
/* casts */ /* casts */
RID_CONSTCAST, RID_DYNCAST, RID_REINTCAST, RID_STATCAST, RID_CONSTCAST, RID_DYNCAST, RID_REINTCAST, RID_STATCAST,
/* C++ extensions */
RID_HAS_NOTHROW_ASSIGN, RID_HAS_NOTHROW_CONSTRUCTOR,
RID_HAS_NOTHROW_COPY, RID_HAS_TRIVIAL_ASSIGN,
RID_HAS_TRIVIAL_CONSTRUCTOR, RID_HAS_TRIVIAL_COPY,
RID_HAS_TRIVIAL_DESTRUCTOR, RID_HAS_VIRTUAL_DESTRUCTOR,
RID_IS_ABSTRACT, RID_IS_BASE_OF,
RID_IS_CONVERTIBLE_TO, RID_IS_CLASS,
RID_IS_EMPTY, RID_IS_ENUM,
RID_IS_POD, RID_IS_POLYMORPHIC,
RID_IS_UNION,
/* C++0x */ /* C++0x */
RID_STATIC_ASSERT, RID_STATIC_ASSERT,

View File

@ -1,3 +1,35 @@
2007-03-30 Paolo Carlini <pcarlini@suse.de>
PR c++/26099
* cp-tree.h (enum cp_trait_kind, struct tree_trait_expr,
TRAIT_EXPR_TYPE1, TRAIT_EXPR_TYPE2, TRAIT_EXPR_KIND): Add.
(enum cp_tree_node_structure_enum, union lang_tree_node): Update.
(CLASS_TYPE_NON_UNION_P): Add.
(struct lang_type_class): Add has_complex_dflt.
(TYPE_HAS_COMPLEX_DFLT, TYPE_HAS_TRIVIAL_DFLT): Add.
(locate_copy, locate_ctor, locate_dtor, finish_trait_expr): Declare.
* cp-tree.def: Add TRAIT_EXPR.
* cp-objcp-common.c (cp_tree_size): Add TRAIT_EXPR case.
* lex.c (struct resword): Add __has_nothrow_assign,
__has_nothrow_constructor, __has_nothrow_copy, __has_trivial_assign,
__has_trivial_constructor, __has_trivial_copy,
__has_trivial_destructor, __has_virtual_destructor, __is_abstract,
__is_base_of, __is_class, __is_convertible_to, __is_empty, __is_enum,
__is_pod, __is_polymorphic, __is_union.
* parser.c (cp_parser_primary_expression): Deal with the new RIDs.
(cp_parser_trait_expr): New.
* semantics.c (finish_trait_expr, trait_expr_value
classtype_has_nothrow_copy_or_assign_p): New.
* method.c (locate_copy, locate_ctor, locate_dtor): Do not define
as static.
* decl.c (cp_tree_node_structure): Add TRAIT_EXPR.
* class.c (check_bases, check_field_decl, check_bases_and_members):
Deal with TYPE_HAS_COMPLEX_DFLT (t) too.
* pt.c (uses_template_parms, tsubst_copy_and_build,
value_dependent_expression_p, type_dependent_expression_p): Deal with
TRAIT_EXPR.
* tree.c (cp_walk_subtrees): Deal with TRAIT_EXPR.
2007-03-29 Richard Guenther <rguenther@suse.de> 2007-03-29 Richard Guenther <rguenther@suse.de>
* tree.c (cp_walk_subtrees): Do not set input_location. * tree.c (cp_walk_subtrees): Do not set input_location.

View File

@ -1270,6 +1270,7 @@ check_bases (tree t,
TYPE_POLYMORPHIC_P (t) |= TYPE_POLYMORPHIC_P (basetype); TYPE_POLYMORPHIC_P (t) |= TYPE_POLYMORPHIC_P (basetype);
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);
} }
} }
@ -2753,6 +2754,7 @@ check_field_decl (tree field,
|= TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type); |= TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type);
TYPE_HAS_COMPLEX_ASSIGN_REF (t) |= TYPE_HAS_COMPLEX_ASSIGN_REF (type); TYPE_HAS_COMPLEX_ASSIGN_REF (t) |= TYPE_HAS_COMPLEX_ASSIGN_REF (type);
TYPE_HAS_COMPLEX_INIT_REF (t) |= TYPE_HAS_COMPLEX_INIT_REF (type); TYPE_HAS_COMPLEX_INIT_REF (t) |= TYPE_HAS_COMPLEX_INIT_REF (type);
TYPE_HAS_COMPLEX_DFLT (t) |= TYPE_HAS_COMPLEX_DFLT (type);
} }
if (!TYPE_HAS_CONST_INIT_REF (type)) if (!TYPE_HAS_CONST_INIT_REF (type))
@ -4113,6 +4115,8 @@ check_bases_and_members (tree t)
|| TYPE_HAS_ASSIGN_REF (t)); || TYPE_HAS_ASSIGN_REF (t));
TYPE_HAS_COMPLEX_ASSIGN_REF (t) TYPE_HAS_COMPLEX_ASSIGN_REF (t)
|= TYPE_HAS_ASSIGN_REF (t) || TYPE_CONTAINS_VPTR_P (t); |= TYPE_HAS_ASSIGN_REF (t) || TYPE_CONTAINS_VPTR_P (t);
TYPE_HAS_COMPLEX_DFLT (t)
|= (TYPE_HAS_DEFAULT_CONSTRUCTOR (t) || TYPE_CONTAINS_VPTR_P (t));
/* Synthesize any needed methods. */ /* Synthesize any needed methods. */
add_implicitly_declared_members (t, add_implicitly_declared_members (t,

View File

@ -135,6 +135,9 @@ cp_tree_size (enum tree_code code)
case ARGUMENT_PACK_SELECT: case ARGUMENT_PACK_SELECT:
return sizeof (struct tree_argument_pack_select); return sizeof (struct tree_argument_pack_select);
case TRAIT_EXPR:
return sizeof (struct tree_trait_expr);
default: default:
gcc_unreachable (); gcc_unreachable ();
} }

View File

@ -422,6 +422,11 @@ DEFTREECODE (EXPR_PACK_EXPANSION, "expr_pack_expansion", tcc_expression, 1)
index is a machine integer. */ index is a machine integer. */
DEFTREECODE (ARGUMENT_PACK_SELECT, "argument_pack_select", tcc_exceptional, 0) DEFTREECODE (ARGUMENT_PACK_SELECT, "argument_pack_select", tcc_exceptional, 0)
/** C++ extensions. */
/* Represents a trait expression during template expansion. */
DEFTREECODE (TRAIT_EXPR, "trait_expr", tcc_exceptional, 0)
/* /*
Local variables: Local variables:
mode:c mode:c

View File

@ -478,6 +478,48 @@ struct tree_argument_pack_select GTY (())
int index; int index;
}; };
/* The different kinds of traits that we encounter. */
typedef enum cp_trait_kind
{
CPTK_HAS_NOTHROW_ASSIGN,
CPTK_HAS_NOTHROW_CONSTRUCTOR,
CPTK_HAS_NOTHROW_COPY,
CPTK_HAS_TRIVIAL_ASSIGN,
CPTK_HAS_TRIVIAL_CONSTRUCTOR,
CPTK_HAS_TRIVIAL_COPY,
CPTK_HAS_TRIVIAL_DESTRUCTOR,
CPTK_HAS_VIRTUAL_DESTRUCTOR,
CPTK_IS_ABSTRACT,
CPTK_IS_BASE_OF,
CPTK_IS_CLASS,
CPTK_IS_CONVERTIBLE_TO,
CPTK_IS_EMPTY,
CPTK_IS_ENUM,
CPTK_IS_POD,
CPTK_IS_POLYMORPHIC,
CPTK_IS_UNION
} cp_trait_kind;
/* The types that we are processing. */
#define TRAIT_EXPR_TYPE1(NODE) \
(((struct tree_trait_expr *)TRAIT_EXPR_CHECK (NODE))->type1)
#define TRAIT_EXPR_TYPE2(NODE) \
(((struct tree_trait_expr *)TRAIT_EXPR_CHECK (NODE))->type2)
/* The specific trait that we are processing. */
#define TRAIT_EXPR_KIND(NODE) \
(((struct tree_trait_expr *)TRAIT_EXPR_CHECK (NODE))->kind)
struct tree_trait_expr GTY (())
{
struct tree_common common;
tree type1;
tree type2;
enum cp_trait_kind kind;
};
enum cp_tree_node_structure_enum { enum cp_tree_node_structure_enum {
TS_CP_GENERIC, TS_CP_GENERIC,
TS_CP_IDENTIFIER, TS_CP_IDENTIFIER,
@ -491,6 +533,7 @@ enum cp_tree_node_structure_enum {
TS_CP_DEFAULT_ARG, TS_CP_DEFAULT_ARG,
TS_CP_STATIC_ASSERT, TS_CP_STATIC_ASSERT,
TS_CP_ARGUMENT_PACK_SELECT, TS_CP_ARGUMENT_PACK_SELECT,
TS_CP_TRAIT_EXPR,
LAST_TS_CP_ENUM LAST_TS_CP_ENUM
}; };
@ -511,6 +554,8 @@ union lang_tree_node GTY((desc ("cp_tree_node_structure (&%h)"),
static_assertion; static_assertion;
struct tree_argument_pack_select GTY ((tag ("TS_CP_ARGUMENT_PACK_SELECT"))) struct tree_argument_pack_select GTY ((tag ("TS_CP_ARGUMENT_PACK_SELECT")))
argument_pack_select; argument_pack_select;
struct tree_trait_expr GTY ((tag ("TS_CP_TRAIT_EXPR")))
trait_expression;
}; };
@ -936,6 +981,10 @@ enum languages { lang_c, lang_cplusplus, lang_java };
#define CLASS_TYPE_P(T) \ #define CLASS_TYPE_P(T) \
(IS_AGGR_TYPE_CODE (TREE_CODE (T)) && TYPE_LANG_FLAG_5 (T)) (IS_AGGR_TYPE_CODE (TREE_CODE (T)) && TYPE_LANG_FLAG_5 (T))
/* Nonzero if T is a class type but not an union. */
#define NON_UNION_CLASS_TYPE_P(T) \
(CLASS_TYPE_P (T) && TREE_CODE (T) != UNION_TYPE)
/* Keep these checks in ascending code order. */ /* Keep these checks in ascending code order. */
#define IS_AGGR_TYPE_CODE(T) \ #define IS_AGGR_TYPE_CODE(T) \
((T) == RECORD_TYPE || (T) == UNION_TYPE) ((T) == RECORD_TYPE || (T) == UNION_TYPE)
@ -1093,6 +1142,7 @@ struct lang_type_class GTY(())
unsigned has_complex_init_ref : 1; unsigned has_complex_init_ref : 1;
unsigned has_complex_assign_ref : 1; unsigned has_complex_assign_ref : 1;
unsigned non_aggregate : 1; unsigned non_aggregate : 1;
unsigned has_complex_dflt : 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
@ -1101,7 +1151,7 @@ struct lang_type_class GTY(())
/* 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 : 12; unsigned dummy : 11;
tree primary_base; tree primary_base;
VEC(tree_pair_s,gc) *vcall_indices; VEC(tree_pair_s,gc) *vcall_indices;
@ -2682,8 +2732,13 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
/* Nonzero if there is a user-defined X::op=(x&) for this class. */ /* Nonzero if there is a user-defined X::op=(x&) for this class. */
#define TYPE_HAS_COMPLEX_ASSIGN_REF(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->has_complex_assign_ref) #define TYPE_HAS_COMPLEX_ASSIGN_REF(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->has_complex_assign_ref)
/* Nonzero if there is a user-defined X::X(x&) for this class. */
#define TYPE_HAS_COMPLEX_INIT_REF(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->has_complex_init_ref) #define TYPE_HAS_COMPLEX_INIT_REF(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->has_complex_init_ref)
/* Nonzero if there is a user-defined default constructor for this class. */
#define TYPE_HAS_COMPLEX_DFLT(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->has_complex_dflt)
/* Nonzero if TYPE has a trivial destructor. From [class.dtor]: /* Nonzero if TYPE has a trivial destructor. From [class.dtor]:
A destructor is trivial if it is an implicitly declared A destructor is trivial if it is an implicitly declared
@ -2705,6 +2760,10 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
#define TYPE_HAS_NONTRIVIAL_DESTRUCTOR(NODE) \ #define TYPE_HAS_NONTRIVIAL_DESTRUCTOR(NODE) \
(TYPE_LANG_FLAG_4 (NODE)) (TYPE_LANG_FLAG_4 (NODE))
/* Nonzero for class type means that the default constructor is trivial. */
#define TYPE_HAS_TRIVIAL_DFLT(NODE) \
(TYPE_HAS_DEFAULT_CONSTRUCTOR (NODE) && ! TYPE_HAS_COMPLEX_DFLT (NODE))
/* Nonzero for class type means that copy initialization of this type can use /* Nonzero for class type means that copy initialization of this type can use
a bitwise copy. */ a bitwise copy. */
#define TYPE_HAS_TRIVIAL_INIT_REF(NODE) \ #define TYPE_HAS_TRIVIAL_INIT_REF(NODE) \
@ -4280,6 +4339,9 @@ extern tree lazily_declare_fn (special_function_kind,
extern tree skip_artificial_parms_for (tree, tree); extern tree skip_artificial_parms_for (tree, tree);
extern int num_artificial_parms_for (tree); extern int num_artificial_parms_for (tree);
extern tree make_alias_for (tree, tree); extern tree make_alias_for (tree, tree);
extern tree locate_copy (tree, void *);
extern tree locate_ctor (tree, void *);
extern tree locate_dtor (tree, void *);
/* In optimize.c */ /* In optimize.c */
extern bool maybe_clone_body (tree); extern bool maybe_clone_body (tree);
@ -4557,6 +4619,7 @@ extern bool cxx_omp_privatize_by_reference (tree);
extern tree baselink_for_fns (tree); extern tree baselink_for_fns (tree);
extern void finish_static_assert (tree, tree, location_t, extern void finish_static_assert (tree, tree, location_t,
bool); bool);
extern tree finish_trait_expr (enum cp_trait_kind, tree, tree);
/* in tree.c */ /* in tree.c */
extern void lang_check_failed (const char *, int, extern void lang_check_failed (const char *, int,

View File

@ -11739,6 +11739,7 @@ cp_tree_node_structure (union lang_tree_node * t)
case BASELINK: return TS_CP_BASELINK; case BASELINK: return TS_CP_BASELINK;
case STATIC_ASSERT: return TS_CP_STATIC_ASSERT; case STATIC_ASSERT: return TS_CP_STATIC_ASSERT;
case ARGUMENT_PACK_SELECT: return TS_CP_ARGUMENT_PACK_SELECT; case ARGUMENT_PACK_SELECT: return TS_CP_ARGUMENT_PACK_SELECT;
case TRAIT_EXPR: return TS_CP_TRAIT_EXPR;
default: return TS_CP_GENERIC; default: return TS_CP_GENERIC;
} }
} }

View File

@ -199,6 +199,23 @@ static const struct resword reswords[] =
{ "__const__", RID_CONST, 0 }, { "__const__", RID_CONST, 0 },
{ "__extension__", RID_EXTENSION, 0 }, { "__extension__", RID_EXTENSION, 0 },
{ "__func__", RID_C99_FUNCTION_NAME, 0 }, { "__func__", RID_C99_FUNCTION_NAME, 0 },
{ "__has_nothrow_assign", RID_HAS_NOTHROW_ASSIGN, 0 },
{ "__has_nothrow_constructor", RID_HAS_NOTHROW_CONSTRUCTOR, 0 },
{ "__has_nothrow_copy", RID_HAS_NOTHROW_COPY, 0 },
{ "__has_trivial_assign", RID_HAS_TRIVIAL_ASSIGN, 0 },
{ "__has_trivial_constructor", RID_HAS_TRIVIAL_CONSTRUCTOR, 0 },
{ "__has_trivial_copy", RID_HAS_TRIVIAL_COPY, 0 },
{ "__has_trivial_destructor", RID_HAS_TRIVIAL_DESTRUCTOR, 0 },
{ "__has_virtual_destructor", RID_HAS_VIRTUAL_DESTRUCTOR, 0 },
{ "__is_abstract", RID_IS_ABSTRACT, 0 },
{ "__is_base_of", RID_IS_BASE_OF, 0 },
{ "__is_class", RID_IS_CLASS, 0 },
{ "__is_convertible_to", RID_IS_CONVERTIBLE_TO, 0 },
{ "__is_empty", RID_IS_EMPTY, 0 },
{ "__is_enum", RID_IS_ENUM, 0 },
{ "__is_pod", RID_IS_POD, 0 },
{ "__is_polymorphic", RID_IS_POLYMORPHIC, 0 },
{ "__is_union", RID_IS_UNION, 0 },
{ "__imag", RID_IMAGPART, 0 }, { "__imag", RID_IMAGPART, 0 },
{ "__imag__", RID_IMAGPART, 0 }, { "__imag__", RID_IMAGPART, 0 },
{ "__inline", RID_INLINE, 0 }, { "__inline", RID_INLINE, 0 },

View File

@ -61,9 +61,6 @@ static tree thunk_adjust (tree, bool, HOST_WIDE_INT, tree);
static void do_build_assign_ref (tree); static void do_build_assign_ref (tree);
static void do_build_copy_constructor (tree); static void do_build_copy_constructor (tree);
static tree synthesize_exception_spec (tree, tree (*) (tree, void *), void *); static tree synthesize_exception_spec (tree, tree (*) (tree, void *), void *);
static tree locate_dtor (tree, void *);
static tree locate_ctor (tree, void *);
static tree locate_copy (tree, void *);
static tree make_alias_for_thunk (tree); static tree make_alias_for_thunk (tree);
/* Called once to initialize method.c. */ /* Called once to initialize method.c. */
@ -868,7 +865,7 @@ synthesize_exception_spec (tree type, tree (*extractor) (tree, void*),
/* Locate the dtor of TYPE. */ /* Locate the dtor of TYPE. */
static tree tree
locate_dtor (tree type, void *client ATTRIBUTE_UNUSED) locate_dtor (tree type, void *client ATTRIBUTE_UNUSED)
{ {
return CLASSTYPE_DESTRUCTORS (type); return CLASSTYPE_DESTRUCTORS (type);
@ -876,7 +873,7 @@ locate_dtor (tree type, void *client ATTRIBUTE_UNUSED)
/* Locate the default ctor of TYPE. */ /* Locate the default ctor of TYPE. */
static tree tree
locate_ctor (tree type, void *client ATTRIBUTE_UNUSED) locate_ctor (tree type, void *client ATTRIBUTE_UNUSED)
{ {
tree fns; tree fns;
@ -912,7 +909,7 @@ struct copy_data
points to a COPY_DATA holding the name (NULL for the ctor) points to a COPY_DATA holding the name (NULL for the ctor)
and desired qualifiers of the source operand. */ and desired qualifiers of the source operand. */
static tree tree
locate_copy (tree type, void *client_) locate_copy (tree type, void *client_)
{ {
struct copy_data *client = (struct copy_data *)client_; struct copy_data *client = (struct copy_data *)client_;

View File

@ -1897,6 +1897,8 @@ static void cp_parser_late_parsing_default_args
(cp_parser *, tree); (cp_parser *, tree);
static tree cp_parser_sizeof_operand static tree cp_parser_sizeof_operand
(cp_parser *, enum rid); (cp_parser *, enum rid);
static tree cp_parser_trait_expr
(cp_parser *, enum rid);
static bool cp_parser_declares_only_class_p static bool cp_parser_declares_only_class_p
(cp_parser *); (cp_parser *);
static void cp_parser_set_storage_class static void cp_parser_set_storage_class
@ -2959,6 +2961,25 @@ cp_parser_translation_unit (cp_parser* parser)
__builtin_va_arg ( assignment-expression , type-id ) __builtin_va_arg ( assignment-expression , type-id )
__builtin_offsetof ( type-id , offsetof-expression ) __builtin_offsetof ( type-id , offsetof-expression )
C++ Extensions:
__has_nothrow_assign ( type-id )
__has_nothrow_constructor ( type-id )
__has_nothrow_copy ( type-id )
__has_trivial_assign ( type-id )
__has_trivial_constructor ( type-id )
__has_trivial_copy ( type-id )
__has_trivial_destructor ( type-id )
__has_virtual_destructor ( type-id )
__is_abstract ( type-id )
__is_base_of ( type-id , type-id )
__is_class ( type-id )
__is_convertible_to ( type-id , type-id )
__is_empty ( type-id )
__is_enum ( type-id )
__is_pod ( type-id )
__is_polymorphic ( type-id )
__is_union ( type-id )
Objective-C++ Extension: Objective-C++ Extension:
primary-expression: primary-expression:
@ -3201,7 +3222,26 @@ cp_parser_primary_expression (cp_parser *parser,
case RID_OFFSETOF: case RID_OFFSETOF:
return cp_parser_builtin_offsetof (parser); return cp_parser_builtin_offsetof (parser);
/* Objective-C++ expressions. */ case RID_HAS_NOTHROW_ASSIGN:
case RID_HAS_NOTHROW_CONSTRUCTOR:
case RID_HAS_NOTHROW_COPY:
case RID_HAS_TRIVIAL_ASSIGN:
case RID_HAS_TRIVIAL_CONSTRUCTOR:
case RID_HAS_TRIVIAL_COPY:
case RID_HAS_TRIVIAL_DESTRUCTOR:
case RID_HAS_VIRTUAL_DESTRUCTOR:
case RID_IS_ABSTRACT:
case RID_IS_BASE_OF:
case RID_IS_CLASS:
case RID_IS_CONVERTIBLE_TO:
case RID_IS_EMPTY:
case RID_IS_ENUM:
case RID_IS_POD:
case RID_IS_POLYMORPHIC:
case RID_IS_UNION:
return cp_parser_trait_expr (parser, token->keyword);
/* Objective-C++ expressions. */
case RID_AT_ENCODE: case RID_AT_ENCODE:
case RID_AT_PROTOCOL: case RID_AT_PROTOCOL:
case RID_AT_SELECTOR: case RID_AT_SELECTOR:
@ -6309,6 +6349,112 @@ cp_parser_builtin_offsetof (cp_parser *parser)
return expr; return expr;
} }
/* Parse a trait expression. */
static tree
cp_parser_trait_expr (cp_parser* parser, enum rid keyword)
{
cp_trait_kind kind;
tree type1, type2 = NULL_TREE;
bool binary = false;
cp_decl_specifier_seq decl_specs;
switch (keyword)
{
case RID_HAS_NOTHROW_ASSIGN:
kind = CPTK_HAS_NOTHROW_ASSIGN;
break;
case RID_HAS_NOTHROW_CONSTRUCTOR:
kind = CPTK_HAS_NOTHROW_CONSTRUCTOR;
break;
case RID_HAS_NOTHROW_COPY:
kind = CPTK_HAS_NOTHROW_COPY;
break;
case RID_HAS_TRIVIAL_ASSIGN:
kind = CPTK_HAS_TRIVIAL_ASSIGN;
break;
case RID_HAS_TRIVIAL_CONSTRUCTOR:
kind = CPTK_HAS_TRIVIAL_CONSTRUCTOR;
break;
case RID_HAS_TRIVIAL_COPY:
kind = CPTK_HAS_TRIVIAL_COPY;
break;
case RID_HAS_TRIVIAL_DESTRUCTOR:
kind = CPTK_HAS_TRIVIAL_DESTRUCTOR;
break;
case RID_HAS_VIRTUAL_DESTRUCTOR:
kind = CPTK_HAS_VIRTUAL_DESTRUCTOR;
break;
case RID_IS_ABSTRACT:
kind = CPTK_IS_ABSTRACT;
break;
case RID_IS_BASE_OF:
kind = CPTK_IS_BASE_OF;
binary = true;
break;
case RID_IS_CLASS:
kind = CPTK_IS_CLASS;
break;
case RID_IS_CONVERTIBLE_TO:
kind = CPTK_IS_CONVERTIBLE_TO;
binary = true;
break;
case RID_IS_EMPTY:
kind = CPTK_IS_EMPTY;
break;
case RID_IS_ENUM:
kind = CPTK_IS_ENUM;
break;
case RID_IS_POD:
kind = CPTK_IS_POD;
break;
case RID_IS_POLYMORPHIC:
kind = CPTK_IS_POLYMORPHIC;
break;
case RID_IS_UNION:
kind = CPTK_IS_UNION;
break;
default:
gcc_unreachable ();
}
/* Consume the token. */
cp_lexer_consume_token (parser->lexer);
cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
type1 = cp_parser_type_id (parser);
/* Build a trivial decl-specifier-seq. */
clear_decl_specs (&decl_specs);
decl_specs.type = type1;
/* Call grokdeclarator to figure out what type this is. */
type1 = grokdeclarator (NULL, &decl_specs, TYPENAME,
/*initialized=*/0, /*attrlist=*/NULL);
if (binary)
{
cp_parser_require (parser, CPP_COMMA, "`,'");
type2 = cp_parser_type_id (parser);
/* Build a trivial decl-specifier-seq. */
clear_decl_specs (&decl_specs);
decl_specs.type = type2;
/* Call grokdeclarator to figure out what type this is. */
type2 = grokdeclarator (NULL, &decl_specs, TYPENAME,
/*initialized=*/0, /*attrlist=*/NULL);
}
cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
/* Complete the trait expr, which may mean either processing the
static assert now or saving it for template instantiation. */
return finish_trait_expr (kind, type1, type2);
}
/* Statements [gram.stmt.stmt] */ /* Statements [gram.stmt.stmt] */
/* Parse a statement. /* Parse a statement.

View File

@ -5818,6 +5818,7 @@ uses_template_parms (tree t)
|| TREE_CODE (t) == OVERLOAD || TREE_CODE (t) == OVERLOAD
|| TREE_CODE (t) == BASELINK || TREE_CODE (t) == BASELINK
|| TREE_CODE (t) == IDENTIFIER_NODE || TREE_CODE (t) == IDENTIFIER_NODE
|| TREE_CODE (t) == TRAIT_EXPR
|| CONSTANT_CLASS_P (t)) || CONSTANT_CLASS_P (t))
dependent_p = (type_dependent_expression_p (t) dependent_p = (type_dependent_expression_p (t)
|| value_dependent_expression_p (t)); || value_dependent_expression_p (t));
@ -10703,6 +10704,18 @@ tsubst_copy_and_build (tree t,
case OFFSETOF_EXPR: case OFFSETOF_EXPR:
return finish_offsetof (RECUR (TREE_OPERAND (t, 0))); return finish_offsetof (RECUR (TREE_OPERAND (t, 0)));
case TRAIT_EXPR:
{
tree type1 = tsubst_copy (TRAIT_EXPR_TYPE1 (t), args,
complain, in_decl);
tree type2 = TRAIT_EXPR_TYPE2 (t);
if (type2)
type2 = tsubst_copy (type2, args, complain, in_decl);
return finish_trait_expr (TRAIT_EXPR_KIND (t), type1, type2);
}
case STMT_EXPR: case STMT_EXPR:
{ {
tree old_stmt_expr = cur_stmt_expr; tree old_stmt_expr = cur_stmt_expr;
@ -14912,6 +14925,13 @@ value_dependent_expression_p (tree expression)
return false; return false;
} }
case TRAIT_EXPR:
{
tree type2 = TRAIT_EXPR_TYPE2 (expression);
return (dependent_type_p (TRAIT_EXPR_TYPE1 (expression))
|| (type2 ? dependent_type_p (type2) : false));
}
default: default:
/* A constant expression is value-dependent if any subexpression is /* A constant expression is value-dependent if any subexpression is
value-dependent. */ value-dependent. */
@ -14975,6 +14995,7 @@ type_dependent_expression_p (tree expression)
if (TREE_CODE (expression) == PSEUDO_DTOR_EXPR if (TREE_CODE (expression) == PSEUDO_DTOR_EXPR
|| TREE_CODE (expression) == SIZEOF_EXPR || TREE_CODE (expression) == SIZEOF_EXPR
|| TREE_CODE (expression) == ALIGNOF_EXPR || TREE_CODE (expression) == ALIGNOF_EXPR
|| TREE_CODE (expression) == TRAIT_EXPR
|| TREE_CODE (expression) == TYPEID_EXPR || TREE_CODE (expression) == TYPEID_EXPR
|| TREE_CODE (expression) == DELETE_EXPR || TREE_CODE (expression) == DELETE_EXPR
|| TREE_CODE (expression) == VEC_DELETE_EXPR || TREE_CODE (expression) == VEC_DELETE_EXPR

View File

@ -4007,4 +4007,210 @@ finish_static_assert (tree condition, tree message, location_t location,
} }
} }
/* Called from trait_expr_value to evaluate either __has_nothrow_copy or
__has_nothrow_assign, depending on copy_p. */
static bool
classtype_has_nothrow_copy_or_assign_p (tree type, bool copy_p)
{
if ((copy_p && TYPE_HAS_INIT_REF (type))
|| (!copy_p && TYPE_HAS_ASSIGN_REF (type)))
{
bool const_p = false;
tree t;
struct copy_data
{
tree name;
int quals;
} data;
data.name = copy_p ? NULL_TREE : ansi_assopname (NOP_EXPR);
data.quals = TYPE_QUAL_CONST;
t = locate_copy (type, &data);
if (t)
{
const_p = true;
if (!TREE_NOTHROW (t))
return false;
}
if (copy_p || !CP_TYPE_CONST_P (type))
{
data.quals = TYPE_UNQUALIFIED;
t = locate_copy (type, &data);
if (t && !TREE_NOTHROW (t))
return false;
data.quals = TYPE_QUAL_VOLATILE;
t = locate_copy (type, &data);
if (t && !TREE_NOTHROW (t))
return false;
}
data.quals = (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE);
t = locate_copy (type, &data);
if (t)
{
const_p = true;
if (!TREE_NOTHROW (t))
return false;
}
if (!copy_p && CP_TYPE_CONST_P (type) && !const_p)
return false;
}
else
return false;
return true;
}
/* Actually evaluates the trait. */
static bool
trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
{
enum tree_code type_code1;
tree t;
type_code1 = TREE_CODE (type1);
switch (kind)
{
case CPTK_HAS_NOTHROW_ASSIGN:
return (trait_expr_value (CPTK_HAS_TRIVIAL_ASSIGN, type1, type2)
|| (CLASS_TYPE_P (type1)
&& classtype_has_nothrow_copy_or_assign_p (type1, false)));
case CPTK_HAS_TRIVIAL_ASSIGN:
return (!CP_TYPE_CONST_P (type1) && type_code1 != REFERENCE_TYPE
&& (pod_type_p (type1)
|| (CLASS_TYPE_P (type1)
&& TYPE_HAS_TRIVIAL_ASSIGN_REF (type1))));
case CPTK_HAS_NOTHROW_CONSTRUCTOR:
type1 = strip_array_types (type1);
return (trait_expr_value (CPTK_HAS_TRIVIAL_CONSTRUCTOR, type1, type2)
|| (CLASS_TYPE_P (type1)
&& (t = locate_ctor (type1, NULL)) && TREE_NOTHROW (t)));
case CPTK_HAS_TRIVIAL_CONSTRUCTOR:
type1 = strip_array_types (type1);
return (pod_type_p (type1)
|| (CLASS_TYPE_P (type1) && TYPE_HAS_TRIVIAL_DFLT (type1)));
case CPTK_HAS_NOTHROW_COPY:
return (trait_expr_value (CPTK_HAS_TRIVIAL_COPY, type1, type2)
|| (CLASS_TYPE_P (type1)
&& classtype_has_nothrow_copy_or_assign_p (type1, true)));
case CPTK_HAS_TRIVIAL_COPY:
return (pod_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)
|| (CLASS_TYPE_P (type1)
&& TYPE_HAS_TRIVIAL_DESTRUCTOR (type1)));
case CPTK_HAS_VIRTUAL_DESTRUCTOR:
return (CLASS_TYPE_P (type1)
&& (t = locate_dtor (type1, NULL)) && DECL_VIRTUAL_P (t));
case CPTK_IS_ABSTRACT:
return (CLASS_TYPE_P (type1) && CLASSTYPE_PURE_VIRTUALS (type1));
case CPTK_IS_BASE_OF:
return (NON_UNION_CLASS_TYPE_P (type1) && NON_UNION_CLASS_TYPE_P (type2)
&& DERIVED_FROM_P (type1, type2));
case CPTK_IS_CLASS:
return (NON_UNION_CLASS_TYPE_P (type1));
case CPTK_IS_CONVERTIBLE_TO:
/* TODO */
return false;
case CPTK_IS_EMPTY:
return (NON_UNION_CLASS_TYPE_P (type1) && CLASSTYPE_EMPTY_P (type1));
case CPTK_IS_ENUM:
return (type_code1 == ENUMERAL_TYPE);
case CPTK_IS_POD:
return (pod_type_p (type1));
case CPTK_IS_POLYMORPHIC:
return (CLASS_TYPE_P (type1) && TYPE_POLYMORPHIC_P (type1));
case CPTK_IS_UNION:
return (type_code1 == UNION_TYPE);
default:
gcc_unreachable ();
return false;
}
}
/* Process a trait expression. */
tree
finish_trait_expr (cp_trait_kind kind, tree type1, tree type2)
{
gcc_assert (kind == CPTK_HAS_NOTHROW_ASSIGN
|| kind == CPTK_HAS_NOTHROW_CONSTRUCTOR
|| kind == CPTK_HAS_NOTHROW_COPY
|| kind == CPTK_HAS_TRIVIAL_ASSIGN
|| kind == CPTK_HAS_TRIVIAL_CONSTRUCTOR
|| kind == CPTK_HAS_TRIVIAL_COPY
|| kind == CPTK_HAS_TRIVIAL_DESTRUCTOR
|| kind == CPTK_HAS_VIRTUAL_DESTRUCTOR
|| kind == CPTK_IS_ABSTRACT
|| kind == CPTK_IS_BASE_OF
|| kind == CPTK_IS_CLASS
|| kind == CPTK_IS_CONVERTIBLE_TO
|| kind == CPTK_IS_EMPTY
|| kind == CPTK_IS_ENUM
|| kind == CPTK_IS_POD
|| kind == CPTK_IS_POLYMORPHIC
|| kind == CPTK_IS_UNION);
if (kind == CPTK_IS_CONVERTIBLE_TO)
{
sorry ("__is_convertible_to");
return error_mark_node;
}
if (type1 == error_mark_node
|| ((kind == CPTK_IS_BASE_OF || kind == CPTK_IS_CONVERTIBLE_TO)
&& type2 == error_mark_node))
return error_mark_node;
if (processing_template_decl)
{
tree trait_expr = make_node (TRAIT_EXPR);
TREE_TYPE (trait_expr) = boolean_type_node;
TRAIT_EXPR_TYPE1 (trait_expr) = type1;
TRAIT_EXPR_TYPE2 (trait_expr) = type2;
TRAIT_EXPR_KIND (trait_expr) = kind;
return trait_expr;
}
/* The only required diagnostic. */
if (kind == CPTK_IS_BASE_OF
&& NON_UNION_CLASS_TYPE_P (type1) && NON_UNION_CLASS_TYPE_P (type2)
&& !same_type_ignoring_top_level_qualifiers_p (type1, type2)
&& !COMPLETE_TYPE_P (complete_type (type2)))
{
error ("incomplete type %qT not allowed", type2);
return error_mark_node;
}
return (trait_expr_value (kind, type1, type2)
? boolean_true_node : boolean_false_node);
}
#include "gt-cp-semantics.h" #include "gt-cp-semantics.h"

View File

@ -2293,6 +2293,12 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func,
*walk_subtrees_p = 0; *walk_subtrees_p = 0;
break; break;
case TRAIT_EXPR:
WALK_SUBTREE (TRAIT_EXPR_TYPE1 (*tp));
WALK_SUBTREE (TRAIT_EXPR_TYPE2 (*tp));
*walk_subtrees_p = 0;
break;
default: default:
return NULL_TREE; return NULL_TREE;
} }

View File

@ -10675,6 +10675,7 @@ Predefined Macros,cpp,The GNU C Preprocessor}).
method denoted by a @samp{->*} or @samp{.*} expression. method denoted by a @samp{->*} or @samp{.*} expression.
* C++ Attributes:: Variable, function, and type attributes for C++ only. * C++ Attributes:: Variable, function, and type attributes for C++ only.
* Namespace Association:: Strong using-directives for namespace association. * Namespace Association:: Strong using-directives for namespace association.
* Type Traits:: Compiler support for type traits
* Java Exceptions:: Tweaking exception handling to work with Java. * Java Exceptions:: Tweaking exception handling to work with Java.
* Deprecated Features:: Things will disappear from g++. * Deprecated Features:: Things will disappear from g++.
* Backwards Compatibility:: Compatibilities with earlier definitions of C++. * Backwards Compatibility:: Compatibilities with earlier definitions of C++.
@ -11232,6 +11233,124 @@ int main()
@} @}
@end smallexample @end smallexample
@node Type Traits
@section Type Traits
The C++ front-end implements syntactic extensions that allow to
determine at compile time various characteristics of a type (or of a
pair of types).
@table @code
@item __has_nothrow_assign (type)
If @code{__has_trivial_assign (type)} is true then the trait is true, else if
@code{type} is a cv class or union type with copy assignment operators that
are known not to throw an exception then the trait is true, else it is false.
If @code{type} is const qualified, any copy assignment operator must
be both known not to throw an exception, and const qualified, for the
trait to be true. Requires: @code{type} shall be a complete type, an
array type of unknown bound, or is a @code{void} type.
@item __has_nothrow_copy (type)
If @code{__has_trivial_copy (type)} is true then the trait is true, else if
@code{type} is a cv class or union type with copy constructors that
are known not to throw an exception then the trait is true, else it is false.
Requires: @code{type} shall be a complete type, an array type of
unknown bound, or is a @code{void} type.
@item __has_nothrow_constructor (type)
If @code{__has_trivial_constructor (type)} is true then the trait is
true, else if @code{type} is a cv class or union type (or array
thereof) with a default constructor that is known not to throw an
exception then the trait is true, else it is false. Requires:
@code{type} shall be a complete type, an array type of unknown bound,
or is a @code{void} type.
@item __has_trivial_assign (type)
If @code{type} is const qualified or is a reference type then the trait is
false. Otherwise if @code{__is_pod (type)} is true then the trait is
true, else if @code{type} is a cv class or union type with a trivial
copy assignment ([class.copy]) then the trait is true, else it is
false. Requires: @code{type} shall be a complete type, an array type
of unknown bound, or is a @code{void} type.
@item __has_trivial_copy (type)
If @code{__is_pod (type)} is true or @code{type} is a reference type
then the trait is true, else if @code{type} is a cv class or union type
with a trivial copy constructor ([class.copy]) then the trait
is true, else it is false. Requires: @code{type} shall be a complete
type, an array type of unknown bound, or is a @code{void} type.
@item __has_trivial_constructor (type)
If @code{__is_pod (type)} is true then the trait is true, else if
@code{type} is a cv class or union type (or array thereof) with a
trivial default constructor ([class.ctor]) then the trait is true,
else it is false. Requires: @code{type} shall be a complete type, an
array type of unknown bound, or is a @code{void} type.
@item __has_trivial_destructor (type)
If @code{__is_pod (type)} is true or @code{type} is a reference type then
the trait is true, else if @code{type} is a cv class or union type (or
array thereof) with a trivial destructor ([class.dtor]) then the trait
is true, else it is false. Requires: @code{type} shall be a complete
type, an array type of unknown bound, or is a @code{void} type.
@item __has_virtual_destructor (type)
If @code{type} is a class type with a virtual destructor
([class.dtor]) then the trait is true, else it is false. Requires:
@code{type} shall be a complete type, an array type of unknown bound,
or is a @code{void} type.
@item __is_abstract (type)
If @code{type} is an abstract class ([class.abstract]) then the trait
is true, else it is false. Requires: @code{type} shall be a complete
type, an array type of unknown bound, or is a @code{void} type.
@item __is_base_of (base_type, derived_type)
If @code{base_type} is a base class of @code{derived_type}
([class.derived]) then the trait is true, otherwise it is false.
Top-level cv qualifications of @code{base_type} and
@code{derived_type} are ignored. For the purposes of this trait, a
class type is considered is own base. Requires: if @code{__is_class
(base_type)} and @code{__is_class (derived_type)} are true and
@code{base_type} and @code{derived_type} are not the same type
(disregarding cv-qualifiers), @code{derived_type} shall be a complete
type. Diagnostic is produced if this requirement is not met.
@item __is_class (type)
If @code{type} is a cv class type, and not a union type
([basic.compound]) the the trait is true, else it is false.
@item __is_empty (type)
If @code{__is_class (type)} is false then the trait is false.
Otherwise @code{type} is considered empty if and only if: @code{type}
has no non-static data members, or all non-static data members, if
any, are bit-fields of lenght 0, and @code{type} has no virtual
members, and @code{type} has no virtual base classes, and @code{type}
has no base classes @code{base_type} for which
@code{__is_empty (base_type)} is false. Requires: @code{type} shall
be a complete type, an array type of unknown bound, or is a
@code{void} type.
@item __is_enum (type)
If @code{type} is a cv enumeration type ([basic.compound]) the the trait is
true, else it is false.
@item __is_pod (type)
If @code{type} is a cv POD type ([basic.types]) then the trait is true,
else it is false. Requires: @code{type} shall be a complete type,
an array type of unknown bound, or is a @code{void} type.
@item __is_polymorphic (type)
If @code{type} is a polymorphic class ([class.virtual]) then the trait
is true, else it is false. Requires: @code{type} shall be a complete
type, an array type of unknown bound, or is a @code{void} type.
@item __is_union (type)
If @code{type} is a cv union type ([basic.compound]) the the trait is
true, else it is false.
@end table
@node Java Exceptions @node Java Exceptions
@section Java Exceptions @section Java Exceptions

View File

@ -1,3 +1,26 @@
2007-03-30 Paolo Carlini <pcarlini@suse.de>
PR c++/26099
* g++.dg/ext/is_base_of.C: New.
* g++.dg/ext/has_virtual_destructor.C: New.
* g++.dg/ext/is_polymorphic.C: New.
* g++.dg/ext/is_base_of_diagnostic.C: New.
* g++.dg/ext/is_enum.C: New.
* g++.dg/ext/has_nothrow_assign.C: New.
* g++.dg/ext/has_nothrow_constructor.C: New.
* g++.dg/ext/is_empty.C: New.
* g++.dg/ext/has_trivial_copy.C: New.
* g++.dg/ext/has_trivial_assign.C: New.
* g++.dg/ext/is_abstract.C: New.
* g++.dg/ext/is_pod.C: New.
* g++.dg/ext/has_nothrow_copy.C: New.
* g++.dg/ext/is_class.C: New.
* g++.dg/ext/has_trivial_constructor.C: New.
* g++.dg/ext/is_union.C: New.
* g++.dg/ext/has_trivial_destructor.C: New.
* g++.dg/tree-ssa/pr22444.C: Adjust, avoid __is_pod.
* g++.dg/template/crash43.C: Likewise.
2007-03-29 Dirk Mueller <dmueller@suse.de> 2007-03-29 Dirk Mueller <dmueller@suse.de>
* g++.dg/warn/pedantic2.C: New testcase. * g++.dg/warn/pedantic2.C: New testcase.

View File

@ -0,0 +1,152 @@
// { dg-do "run" }
#include <cassert>
struct A
{
double a;
double b;
};
struct B
{
A a;
};
struct C
: public A { };
struct D
{
D& operator=(const D&) throw() { return *this; }
};
struct E
{
E& operator=(const E&) throw(int) { return *this; }
};
struct E1
{
E1& operator=(const E1&) throw(int) { throw int(); return *this; }
};
struct F
{
F() throw(int) { }
};
struct G
{
G() throw(int) { throw int(); }
};
struct H
{
H& operator=(H&) throw(int) { return *this; }
};
struct H1
{
H1& operator=(H1&) throw(int) { throw int(); return *this; }
};
struct I
{
I& operator=(I&) throw(int) { return *this; }
I& operator=(const I&) throw() { return *this; }
};
struct I1
{
I1& operator=(I1&) throw(int) { throw int(); return *this; }
I1& operator=(const I1&) throw() { return *this; }
};
struct J
{
J& operator=(J&) throw() { return *this; }
J& operator=(const J&) throw() { return *this; }
J& operator=(volatile J&) throw() { return *this; }
J& operator=(const volatile J&) throw() { return *this; }
};
struct K
{
K& operator=(K&) throw() { return *this; }
};
struct L
{
L& operator=(const L&) throw() { return *this; }
};
template<typename T>
bool
f()
{ return __has_nothrow_assign(T); }
template<typename T>
class My
{
public:
bool
f()
{ return !!__has_nothrow_assign(T); }
};
template<typename T>
class My2
{
public:
static const bool trait = __has_nothrow_assign(T);
};
template<typename T>
const bool My2<T>::trait;
template<typename T, bool b = __has_nothrow_assign(T)>
struct My3_help
{ static const bool trait = b; };
template<typename T, bool b>
const bool My3_help<T, b>::trait;
template<typename T>
class My3
{
public:
bool
f()
{ return My3_help<T>::trait; }
};
#define PTEST(T) (__has_nothrow_assign(T) && f<T>() \
&& My<T>().f() && My2<T>::trait && My3<T>().f())
#define NTEST(T) (!__has_nothrow_assign(T) && !f<T>() \
&& !My<T>().f() && !My2<T>::trait && !My3<T>().f())
int main()
{
assert (PTEST (int));
assert (NTEST (int (int)));
assert (NTEST (void));
assert (PTEST (A));
assert (PTEST (B));
assert (PTEST (C));
assert (NTEST (C[]));
assert (PTEST (D));
assert (PTEST (E));
assert (NTEST (E1));
assert (PTEST (F));
assert (PTEST (G));
assert (PTEST (H));
assert (NTEST (H1));
assert (PTEST (I));
assert (NTEST (I1));
assert (PTEST (J));
assert (NTEST (const K));
assert (PTEST (const L));
return 0;
}

View File

@ -0,0 +1,106 @@
// { dg-do "run" }
#include <cassert>
struct A
{
double a;
double b;
};
struct B
{
A a;
};
struct C
: public A { };
struct D
{
D() throw() { }
};
struct E
{
E() throw(int) { }
};
struct E1
{
E1() throw(int) { throw int(); }
};
struct F
{
F(const F&) throw() { }
};
struct G
{
G(const G&) throw(int) { throw int(); }
};
template<typename T>
bool
f()
{ return __has_nothrow_constructor(T); }
template<typename T>
class My
{
public:
bool
f()
{ return !!__has_nothrow_constructor(T); }
};
template<typename T>
class My2
{
public:
static const bool trait = __has_nothrow_constructor(T);
};
template<typename T>
const bool My2<T>::trait;
template<typename T, bool b = __has_nothrow_constructor(T)>
struct My3_help
{ static const bool trait = b; };
template<typename T, bool b>
const bool My3_help<T, b>::trait;
template<typename T>
class My3
{
public:
bool
f()
{ return My3_help<T>::trait; }
};
#define PTEST(T) (__has_nothrow_constructor(T) && f<T>() \
&& My<T>().f() && My2<T>::trait && My3<T>().f())
#define NTEST(T) (!__has_nothrow_constructor(T) && !f<T>() \
&& !My<T>().f() && !My2<T>::trait && !My3<T>().f())
int main()
{
assert (PTEST (int));
assert (NTEST (int (int)));
assert (NTEST (void));
assert (PTEST (A));
assert (PTEST (B));
assert (PTEST (C));
assert (PTEST (C[]));
assert (PTEST (D));
assert (PTEST (E));
assert (NTEST (E1));
assert (NTEST (F));
assert (NTEST (G));
return 0;
}

View File

@ -0,0 +1,140 @@
// { dg-do "run" }
#include <cassert>
struct A
{
double a;
double b;
};
struct B
{
A a;
};
struct C
: public A { };
struct D
{
D(const D&) throw() { }
};
struct E
{
E(const E&) throw(int) { }
};
struct E1
{
E1(const E1&) throw(int) { throw int(); }
};
struct F
{
F() throw() { }
};
struct G
{
G() throw(int) { throw int(); }
};
struct H
{
H(H&) throw(int) { }
};
struct H1
{
H1(H1&) throw(int) { throw int(); }
};
struct I
{
I(I&) throw(int) { }
I(const I&) throw() { }
};
struct I1
{
I1(I1&) throw(int) { throw int(); }
I1(const I1&) throw() { }
};
struct J
{
J(J&) throw() { }
J(const J&) throw() { }
J(volatile J&) throw() { }
J(const volatile J&) throw() { }
};
template<typename T>
bool
f()
{ return __has_nothrow_copy(T); }
template<typename T>
class My
{
public:
bool
f()
{ return !!__has_nothrow_copy(T); }
};
template<typename T>
class My2
{
public:
static const bool trait = __has_nothrow_copy(T);
};
template<typename T>
const bool My2<T>::trait;
template<typename T, bool b = __has_nothrow_copy(T)>
struct My3_help
{ static const bool trait = b; };
template<typename T, bool b>
const bool My3_help<T, b>::trait;
template<typename T>
class My3
{
public:
bool
f()
{ return My3_help<T>::trait; }
};
#define PTEST(T) (__has_nothrow_copy(T) && f<T>() \
&& My<T>().f() && My2<T>::trait && My3<T>().f())
#define NTEST(T) (!__has_nothrow_copy(T) && !f<T>() \
&& !My<T>().f() && !My2<T>::trait && !My3<T>().f())
int main()
{
assert (PTEST (int));
assert (NTEST (int (int)));
assert (NTEST (void));
assert (PTEST (A));
assert (PTEST (B));
assert (PTEST (C));
assert (NTEST (C[]));
assert (PTEST (D));
assert (PTEST (E));
assert (NTEST (E1));
assert (PTEST (F));
assert (PTEST (G));
assert (PTEST (H));
assert (NTEST (H1));
assert (PTEST (I));
assert (NTEST (I1));
assert (PTEST (J));
return 0;
}

View File

@ -0,0 +1,106 @@
// { dg-do "run" }
#include <cassert>
struct A
{
double a;
double b;
};
union U
{
double a;
double b;
};
struct B
{
B& operator=(const B&) { return *this;}
};
struct C
{
virtual int f() { return 1; }
};
struct D
: public B { };
struct E
: public A { };
struct F
{
A a;
};
struct G
{
B b;
};
template<typename T>
bool
f()
{ return __has_trivial_assign(T); }
template<typename T>
class My
{
public:
bool
f()
{ return !!__has_trivial_assign(T); }
};
template<typename T>
class My2
{
public:
static const bool trait = __has_trivial_assign(T);
};
template<typename T>
const bool My2<T>::trait;
template<typename T, bool b = __has_trivial_assign(T)>
struct My3_help
{ static const bool trait = b; };
template<typename T, bool b>
const bool My3_help<T, b>::trait;
template<typename T>
class My3
{
public:
bool
f()
{ return My3_help<T>::trait; }
};
#define PTEST(T) (__has_trivial_assign(T) && f<T>() \
&& My<T>().f() && My2<T>::trait && My3<T>().f())
#define NTEST(T) (!__has_trivial_assign(T) && !f<T>() \
&& !My<T>().f() && !My2<T>::trait && !My3<T>().f())
int main()
{
assert (PTEST (int));
assert (NTEST (int (int)));
assert (NTEST (void));
assert (PTEST (A));
assert (PTEST (U));
assert (NTEST (B));
assert (NTEST (C));
assert (NTEST (D));
assert (PTEST (E));
assert (NTEST (E[]));
assert (PTEST (F));
assert (NTEST (G));
assert (NTEST (const A));
assert (NTEST (A&));
return 0;
}

View File

@ -0,0 +1,98 @@
// { dg-do "run" }
#include <cassert>
struct A
{
double a;
double b;
};
union U
{
double a;
double b;
};
struct B
{
B() { }
};
struct C
: public B { };
struct D
: public A { };
struct E
{
A a;
};
struct F
{
B b;
};
template<typename T>
bool
f()
{ return __has_trivial_constructor(T); }
template<typename T>
class My
{
public:
bool
f()
{ return !!__has_trivial_constructor(T); }
};
template<typename T>
class My2
{
public:
static const bool trait = __has_trivial_constructor(T);
};
template<typename T>
const bool My2<T>::trait;
template<typename T, bool b = __has_trivial_constructor(T)>
struct My3_help
{ static const bool trait = b; };
template<typename T, bool b>
const bool My3_help<T, b>::trait;
template<typename T>
class My3
{
public:
bool
f()
{ return My3_help<T>::trait; }
};
#define PTEST(T) (__has_trivial_constructor(T) && f<T>() \
&& My<T>().f() && My2<T>::trait && My3<T>().f())
#define NTEST(T) (!__has_trivial_constructor(T) && !f<T>() \
&& !My<T>().f() && !My2<T>::trait && !My3<T>().f())
int main()
{
assert (PTEST (int));
assert (NTEST (int (int)));
assert (NTEST (void));
assert (PTEST (A));
assert (PTEST (U));
assert (NTEST (B));
assert (NTEST (C));
assert (PTEST (D));
assert (PTEST (D[]));
assert (PTEST (E));
assert (NTEST (F));
return 0;
}

View File

@ -0,0 +1,105 @@
// { dg-do "run" }
#include <cassert>
struct A
{
double a;
double b;
};
union U
{
double a;
double b;
};
struct B
{
B(const B&) { }
};
struct C
{
virtual int f() { return 1; }
};
struct D
: public B { };
struct E
: public A { };
struct F
{
A a;
};
struct G
{
B b;
};
template<typename T>
bool
f()
{ return __has_trivial_copy(T); }
template<typename T>
class My
{
public:
bool
f()
{ return !!__has_trivial_copy(T); }
};
template<typename T>
class My2
{
public:
static const bool trait = __has_trivial_copy(T);
};
template<typename T>
const bool My2<T>::trait;
template<typename T, bool b = __has_trivial_copy(T)>
struct My3_help
{ static const bool trait = b; };
template<typename T, bool b>
const bool My3_help<T, b>::trait;
template<typename T>
class My3
{
public:
bool
f()
{ return My3_help<T>::trait; }
};
#define PTEST(T) (__has_trivial_copy(T) && f<T>() \
&& My<T>().f() && My2<T>::trait && My3<T>().f())
#define NTEST(T) (!__has_trivial_copy(T) && !f<T>() \
&& !My<T>().f() && !My2<T>::trait && !My3<T>().f())
int main()
{
assert (PTEST (int));
assert (NTEST (int (int)));
assert (NTEST (void));
assert (PTEST (A));
assert (PTEST (U));
assert (NTEST (B));
assert (NTEST (C));
assert (NTEST (D));
assert (PTEST (E));
assert (NTEST (E[]));
assert (PTEST (F));
assert (NTEST (G));
assert (PTEST (B&));
return 0;
}

View File

@ -0,0 +1,86 @@
// { dg-do "run" }
#include <cassert>
struct A
{
double a;
double b;
};
union U
{
double a;
double b;
};
struct B
{
~B() { }
};
struct C
: public B { };
struct D
: public A { };
template<typename T>
bool
f()
{ return __has_trivial_destructor(T); }
template<typename T>
class My
{
public:
bool
f()
{ return !!__has_trivial_destructor(T); }
};
template<typename T>
class My2
{
public:
static const bool trait = __has_trivial_destructor(T);
};
template<typename T>
const bool My2<T>::trait;
template<typename T, bool b = __has_trivial_destructor(T)>
struct My3_help
{ static const bool trait = b; };
template<typename T, bool b>
const bool My3_help<T, b>::trait;
template<typename T>
class My3
{
public:
bool
f()
{ return My3_help<T>::trait; }
};
#define PTEST(T) (__has_trivial_destructor(T) && f<T>() \
&& My<T>().f() && My2<T>::trait && My3<T>().f())
#define NTEST(T) (!__has_trivial_destructor(T) && !f<T>() \
&& !My<T>().f() && !My2<T>::trait && !My3<T>().f())
int main()
{
assert (PTEST (int));
assert (NTEST (int (int)));
assert (NTEST (void));
assert (PTEST (A));
assert (PTEST (U));
assert (NTEST (B));
assert (NTEST (C));
assert (PTEST (D));
assert (PTEST (D[]));
return 0;
}

View File

@ -0,0 +1,89 @@
// { dg-do "run" }
#include <cassert>
#include <exception>
struct A
{
double a;
double b;
};
union U
{
double a;
double b;
};
class B
{
virtual ~B() { }
};
class C
: public B { };
class D
{
~D() { }
};
template<typename T>
bool
f()
{ return __has_virtual_destructor(T); }
template<typename T>
class My
{
public:
bool
f()
{ return !!__has_virtual_destructor(T); }
};
template<typename T>
class My2
{
public:
static const bool trait = __has_virtual_destructor(T);
};
template<typename T>
const bool My2<T>::trait;
template<typename T, bool b = __has_virtual_destructor(T)>
struct My3_help
{ static const bool trait = b; };
template<typename T, bool b>
const bool My3_help<T, b>::trait;
template<typename T>
class My3
{
public:
bool
f()
{ return My3_help<T>::trait; }
};
#define PTEST(T) (__has_virtual_destructor(T) && f<T>() \
&& My<T>().f() && My2<T>::trait && My3<T>().f())
#define NTEST(T) (!__has_virtual_destructor(T) && !f<T>() \
&& !My<T>().f() && !My2<T>::trait && !My3<T>().f())
int main()
{
assert (NTEST (int));
assert (NTEST (void));
assert (PTEST (std::exception));
assert (NTEST (A));
assert (NTEST (U));
assert (PTEST (B));
assert (PTEST (C));
assert (NTEST (C[]));
assert (NTEST (D));
return 0;
}

View File

@ -0,0 +1,89 @@
// { dg-do "run" }
#include <cassert>
struct A
{
double a;
double b;
};
union U
{
double a;
double b;
};
class B
{
B();
};
class C
{
virtual void rotate(int) = 0;
};
class D
{
virtual void rotate(int) { }
};
template<typename T>
bool
f()
{ return __is_abstract(T); }
template<typename T>
class My
{
public:
bool
f()
{ return !!__is_abstract(T); }
};
template<typename T>
class My2
{
public:
static const bool trait = __is_abstract(T);
};
template<typename T>
const bool My2<T>::trait;
template<typename T, bool b = __is_abstract(T)>
struct My3_help
{ static const bool trait = b; };
template<typename T, bool b>
const bool My3_help<T, b>::trait;
template<typename T>
class My3
{
public:
bool
f()
{ return My3_help<T>::trait; }
};
#define PTEST(T) (__is_abstract(T) && f<T>() \
&& My<T>().f() && My2<T>::trait && My3<T>().f())
#define NTEST(T) (!__is_abstract(T) && !f<T>() \
&& !My<T>().f() && !My2<T>::trait && !My3<T>().f())
int main()
{
assert (NTEST (int));
assert (NTEST (void));
assert (NTEST (A));
assert (NTEST (U));
assert (NTEST (B));
assert (NTEST (B[]));
assert (PTEST (C));
assert (NTEST (D));
return 0;
}

View File

@ -0,0 +1,94 @@
// { dg-do "run" }
#include <cassert>
class A1
{
double a;
double b;
};
class A2
{
double a;
double b;
};
class B
: private A1 { };
class C
: private A1, private A2 { };
union U
{
double a;
double b;
};
template<typename T, typename U>
bool
f()
{ return __is_base_of(T, U); }
template<typename T, typename U>
class My
{
public:
bool
f()
{ return !!__is_base_of(T, U); }
};
template<typename T, typename U>
class My2
{
public:
static const bool trait = __is_base_of(T, U);
};
template<typename T, typename U>
const bool My2<T, U>::trait;
template<typename T, typename U, bool b = __is_base_of(T, U)>
struct My3_help
{ static const bool trait = b; };
template<typename T, typename U, bool b>
const bool My3_help<T, U, b>::trait;
template<typename T, typename U>
class My3
{
public:
bool
f()
{ return My3_help<T, U>::trait; }
};
#define PTEST(T, U) (__is_base_of(T, U) && f<T, U>() \
&& My<T, U>().f() && My2<T, U>::trait && My3<T, U>().f())
#define NTEST(T, U) (!__is_base_of(T, U) && !f<T, U>() \
&& !My<T, U>().f() && !My2<T, U>::trait && !My3<T, U>().f())
int main()
{
assert (NTEST (int, A1));
assert (NTEST (A1, void));
assert (PTEST (A1, A1));
assert (NTEST (A1*, A1*));
assert (NTEST (A1&, A1&));
assert (PTEST (A1, B));
assert (NTEST (B, A1));
assert (PTEST (A1, C));
assert (PTEST (A2, C));
assert (NTEST (C, A1));
assert (PTEST (A1, const B));
assert (NTEST (const B, A1));
assert (PTEST (A1, volatile C));
assert (PTEST (volatile A2, const C));
assert (NTEST (const volatile C, A1));
assert (NTEST (U, U));
return 0;
}

View File

@ -0,0 +1,15 @@
class A
{ };
class B;
union C
{ };
union D;
void f()
{
__is_base_of(A, B); // { dg-error "incomplete type" }
__is_base_of(C, D);
}

View File

@ -0,0 +1,76 @@
// { dg-do "run" }
#include <cassert>
struct A
{
double a;
double b;
};
class B
{
B() { }
};
union U
{
double a;
double b;
};
template<typename T>
bool
f()
{ return __is_class(T); }
template<typename T>
class My
{
public:
bool
f()
{ return !!__is_class(T); }
};
template<typename T>
class My2
{
public:
static const bool trait = __is_class(T);
};
template<typename T>
const bool My2<T>::trait;
template<typename T, bool b = __is_class(T)>
struct My3_help
{ static const bool trait = b; };
template<typename T, bool b>
const bool My3_help<T, b>::trait;
template<typename T>
class My3
{
public:
bool
f()
{ return My3_help<T>::trait; }
};
#define PTEST(T) (__is_class(T) && f<T>() \
&& My<T>().f() && My2<T>::trait && My3<T>().f())
#define NTEST(T) (!__is_class(T) && !f<T>() \
&& !My<T>().f() && !My2<T>::trait && !My3<T>().f())
int main()
{
assert (NTEST (int));
assert (NTEST (void));
assert (PTEST (A));
assert (PTEST (B));
assert (NTEST (U));
return 0;
}

View File

@ -0,0 +1,78 @@
// { dg-do "run" }
#include <cassert>
struct A
{
double a;
double b;
};
struct B
{
virtual ~B() { }
};
class C
{ };
union U
{ };
template<typename T>
bool
f()
{ return __is_empty(T); }
template<typename T>
class My
{
public:
bool
f()
{ return !!__is_empty(T); }
};
template<typename T>
class My2
{
public:
static const bool trait = __is_empty(T);
};
template<typename T>
const bool My2<T>::trait;
template<typename T, bool b = __is_empty(T)>
struct My3_help
{ static const bool trait = b; };
template<typename T, bool b>
const bool My3_help<T, b>::trait;
template<typename T>
class My3
{
public:
bool
f()
{ return My3_help<T>::trait; }
};
#define PTEST(T) (__is_empty(T) && f<T>() \
&& My<T>().f() && My2<T>::trait && My3<T>().f())
#define NTEST(T) (!__is_empty(T) && !f<T>() \
&& !My<T>().f() && !My2<T>::trait && !My3<T>().f())
int main()
{
assert (NTEST (int));
assert (NTEST (void));
assert (NTEST (A));
assert (NTEST (B));
assert (PTEST (C));
assert (NTEST (C[]));
assert (NTEST (U));
return 0;
}

View File

@ -0,0 +1,73 @@
// { dg-do "run" }
#include <cassert>
struct A
{
double a;
double b;
};
class B
{ };
enum E
{
e0
};
template<typename T>
bool
f()
{ return __is_enum(T); }
template<typename T>
class My
{
public:
bool
f()
{ return !!__is_enum(T); }
};
template<typename T>
class My2
{
public:
static const bool trait = __is_enum(T);
};
template<typename T>
const bool My2<T>::trait;
template<typename T, bool b = __is_enum(T)>
struct My3_help
{ static const bool trait = b; };
template<typename T, bool b>
const bool My3_help<T, b>::trait;
template<typename T>
class My3
{
public:
bool
f()
{ return My3_help<T>::trait; }
};
#define PTEST(T) (__is_enum(T) && f<T>() \
&& My<T>().f() && My2<T>::trait && My3<T>().f())
#define NTEST(T) (!__is_enum(T) && !f<T>() \
&& !My<T>().f() && !My2<T>::trait && !My3<T>().f())
int main()
{
assert (NTEST (int));
assert (NTEST (void));
assert (NTEST (A));
assert (NTEST (B));
assert (PTEST (E));
return 0;
}

View File

@ -0,0 +1,75 @@
// { dg-do "run" }
#include <cassert>
struct A
{
double a;
double b;
};
struct B
{
B() { }
};
struct C
: public A { };
template<typename T>
bool
f()
{ return __is_pod(T); }
template<typename T>
class My
{
public:
bool
f()
{ return !!__is_pod(T); }
};
template<typename T>
class My2
{
public:
static const bool trait = __is_pod(T);
};
template<typename T>
const bool My2<T>::trait;
template<typename T, bool b = __is_pod(T)>
struct My3_help
{ static const bool trait = b; };
template<typename T, bool b>
const bool My3_help<T, b>::trait;
template<typename T>
class My3
{
public:
bool
f()
{ return My3_help<T>::trait; }
};
#define PTEST(T) (__is_pod(T) && f<T>() \
&& My<T>().f() && My2<T>::trait && My3<T>().f())
#define NTEST(T) (!__is_pod(T) && !f<T>() \
&& !My<T>().f() && !My2<T>::trait && !My3<T>().f())
int main()
{
assert (PTEST (int));
assert (NTEST (void));
assert (PTEST (A));
assert (PTEST (A[]));
assert (NTEST (B));
assert (NTEST (C));
assert (NTEST (C[]));
return 0;
}

View File

@ -0,0 +1,83 @@
// { dg-do "run" }
#include <cassert>
#include <exception>
struct A
{
double a;
double b;
};
class B
{
virtual void rotate(int) { }
};
class C
: public B { };
union U
{
double a;
double b;
};
template<typename T>
bool
f()
{ return __is_polymorphic(T); }
template<typename T>
class My
{
public:
bool
f()
{ return !!__is_polymorphic(T); }
};
template<typename T>
class My2
{
public:
static const bool trait = __is_polymorphic(T);
};
template<typename T>
const bool My2<T>::trait;
template<typename T, bool b = __is_polymorphic(T)>
struct My3_help
{ static const bool trait = b; };
template<typename T, bool b>
const bool My3_help<T, b>::trait;
template<typename T>
class My3
{
public:
bool
f()
{ return My3_help<T>::trait; }
};
#define PTEST(T) (__is_polymorphic(T) && f<T>() \
&& My<T>().f() && My2<T>::trait && My3<T>().f())
#define NTEST(T) (!__is_polymorphic(T) && !f<T>() \
&& !My<T>().f() && !My2<T>::trait && !My3<T>().f())
int main()
{
assert (NTEST (int));
assert (NTEST (void));
assert (PTEST (std::exception));
assert (NTEST (A));
assert (PTEST (B));
assert (PTEST (C));
assert (NTEST (C[]));
assert (NTEST (U));
return 0;
}

View File

@ -0,0 +1,76 @@
// { dg-do "run" }
#include <cassert>
struct A
{
double a;
double b;
};
class B
{
B() { }
};
union U
{
double a;
double b;
};
template<typename T>
bool
f()
{ return __is_union(T); }
template<typename T>
class My
{
public:
bool
f()
{ return !!__is_union(T); }
};
template<typename T>
class My2
{
public:
static const bool trait = __is_union(T);
};
template<typename T>
const bool My2<T>::trait;
template<typename T, bool b = __is_union(T)>
struct My3_help
{ static const bool trait = b; };
template<typename T, bool b>
const bool My3_help<T, b>::trait;
template<typename T>
class My3
{
public:
bool
f()
{ return My3_help<T>::trait; }
};
#define PTEST(T) (__is_union(T) && f<T>() \
&& My<T>().f() && My2<T>::trait && My3<T>().f())
#define NTEST(T) (!__is_union(T) && !f<T>() \
&& !My<T>().f() && !My2<T>::trait && !My3<T>().f())
int main()
{
assert (NTEST (int));
assert (NTEST (void));
assert (NTEST (A));
assert (NTEST (B));
assert (PTEST (U));
return 0;
}

View File

@ -2,7 +2,7 @@
extern "C" { extern "C" {
template<typename _Tp> // { dg-error "C" } template<typename _Tp> // { dg-error "C" }
struct __is_pod { struct ___is_pod {
enum { enum {
__value = (sizeof(__gnu_internal::__test_type<_Tp>(0)))}; // { dg-error "declared|expected" } __value = (sizeof(__gnu_internal::__test_type<_Tp>(0)))}; // { dg-error "declared|expected" }

View File

@ -22,7 +22,7 @@ namespace __gnu_internal
} }
namespace std namespace std
{ {
template<typename _Tp> struct __is_pod template<typename _Tp> struct ___is_pod
{ {
enum { __value = (sizeof(__gnu_internal::__test_type<_Tp>(0))!= sizeof(__gnu_internal::__one)) }; enum { __value = (sizeof(__gnu_internal::__test_type<_Tp>(0))!= sizeof(__gnu_internal::__one)) };
}; };
@ -111,7 +111,7 @@ namespace std
typedef _Val value_type; typedef _Val value_type;
typedef value_type* pointer; typedef value_type* pointer;
typedef _Rb_tree_node* _Link_type; typedef _Rb_tree_node* _Link_type;
template<typename _Key_compare, bool _Is_pod_comparator = std::__is_pod<_Key_compare>::__value> struct _Rb_tree_impl template<typename _Key_compare, bool _Is_pod_comparator = std::___is_pod<_Key_compare>::__value> struct _Rb_tree_impl
: _Node_allocator : _Node_allocator
{ {
_Rb_tree_node_base _M_header; _Rb_tree_node_base _M_header;

View File

@ -1,3 +1,12 @@
2007-03-30 Paolo Carlini <pcarlini@suse.de>
PR c++/26099
* include/bits/cpp_type_traits.h (struct __is_pod, struct __is_empty):
Remove.
* include/bits/valarray_array.h: Adjust.
* include/bits/allocator.h: Likewise.
* include/bits/stl_tree.h: Likewise.
2007-03-30 Paolo Carlini <pcarlini@suse.de> 2007-03-30 Paolo Carlini <pcarlini@suse.de>
PR libstdc++/31401 PR libstdc++/31401

View File

@ -1,6 +1,6 @@
// Allocators -*- C++ -*- // Allocators -*- C++ -*-
// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 // Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007
// Free Software Foundation, Inc. // Free Software Foundation, Inc.
// //
// This file is part of the GNU ISO C++ Library. This library is free // This file is part of the GNU ISO C++ Library. This library is free
@ -132,7 +132,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
#undef __glibcxx_base_allocator #undef __glibcxx_base_allocator
// To implement Option 3 of DR 431. // To implement Option 3 of DR 431.
template<typename _Alloc, bool = std::__is_empty<_Alloc>::__value> template<typename _Alloc, bool = __is_empty(_Alloc)>
struct __alloc_swap struct __alloc_swap
{ static void _S_do_it(_Alloc&, _Alloc&) { } }; { static void _S_do_it(_Alloc&, _Alloc&) { } };

View File

@ -1,6 +1,6 @@
// The -*- C++ -*- type traits classes for internal use in libstdc++ // The -*- C++ -*- type traits classes for internal use in libstdc++
// Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006 // Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
// Free Software Foundation, Inc. // Free Software Foundation, Inc.
// //
// This file is part of the GNU ISO C++ Library. This library is free // This file is part of the GNU ISO C++ Library. This library is free
@ -80,20 +80,6 @@ _GLIBCXX_END_NAMESPACE
_GLIBCXX_BEGIN_NAMESPACE(std) _GLIBCXX_BEGIN_NAMESPACE(std)
namespace __detail
{
// NB: g++ can not compile these if declared within the class
// __is_pod itself.
typedef char __one;
typedef char __two[2];
template<typename _Tp>
__one __test_type(int _Tp::*);
template<typename _Tp>
__two& __test_type(...);
} // namespace __detail
struct __true_type { }; struct __true_type { };
struct __false_type { }; struct __false_type { };
@ -341,37 +327,6 @@ namespace __detail
: public __traitor<__is_arithmetic<_Tp>, __is_pointer<_Tp> > : public __traitor<__is_arithmetic<_Tp>, __is_pointer<_Tp> >
{ }; { };
// For the immediate use, the following is a good approximation.
template<typename _Tp>
struct __is_pod
{
enum
{
__value = (sizeof(__detail::__test_type<_Tp>(0))
!= sizeof(__detail::__one))
};
};
//
// A stripped-down version of std::tr1::is_empty
//
template<typename _Tp>
struct __is_empty
{
private:
template<typename>
struct __first { };
template<typename _Up>
struct __second
: public _Up { };
public:
enum
{
__value = sizeof(__first<_Tp>) == sizeof(__second<_Tp>)
};
};
// //
// For use in std::copy and std::find overloads for streambuf iterators. // For use in std::copy and std::find overloads for streambuf iterators.
// //

View File

@ -393,7 +393,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
protected: protected:
template<typename _Key_compare, template<typename _Key_compare,
bool _Is_pod_comparator = std::__is_pod<_Key_compare>::__value> bool _Is_pod_comparator = __is_pod(_Key_compare)>
struct _Rb_tree_impl : public _Node_allocator struct _Rb_tree_impl : public _Node_allocator
{ {
_Key_compare _M_key_compare; _Key_compare _M_key_compare;

View File

@ -1,6 +1,6 @@
// The template and inlines for the -*- C++ -*- internal _Array helper class. // The template and inlines for the -*- C++ -*- internal _Array helper class.
// Copyright (C) 1997, 1998, 1999, 2000, 2003, 2004, 2005, 2006 // Copyright (C) 1997, 1998, 1999, 2000, 2003, 2004, 2005, 2006, 2007
// Free Software Foundation, Inc. // Free Software Foundation, Inc.
// //
// This file is part of the GNU ISO C++ Library. This library is free // This file is part of the GNU ISO C++ Library. This library is free
@ -98,7 +98,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
inline void inline void
__valarray_default_construct(_Tp* __restrict__ __b, _Tp* __restrict__ __e) __valarray_default_construct(_Tp* __restrict__ __b, _Tp* __restrict__ __e)
{ {
_Array_default_ctor<_Tp, __is_pod<_Tp>::__value>::_S_do_it(__b, __e); _Array_default_ctor<_Tp, __is_pod(_Tp)>::_S_do_it(__b, __e);
} }
// Turn a raw-memory into an array of _Tp filled with __t // Turn a raw-memory into an array of _Tp filled with __t
@ -133,7 +133,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
__valarray_fill_construct(_Tp* __restrict__ __b, _Tp* __restrict__ __e, __valarray_fill_construct(_Tp* __restrict__ __b, _Tp* __restrict__ __e,
const _Tp __t) const _Tp __t)
{ {
_Array_init_ctor<_Tp, __is_pod<_Tp>::__value>::_S_do_it(__b, __e, __t); _Array_init_ctor<_Tp, __is_pod(_Tp)>::_S_do_it(__b, __e, __t);
} }
// //
@ -169,7 +169,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
const _Tp* __restrict__ __e, const _Tp* __restrict__ __e,
_Tp* __restrict__ __o) _Tp* __restrict__ __o)
{ {
_Array_copy_ctor<_Tp, __is_pod<_Tp>::__value>::_S_do_it(__b, __e, __o); _Array_copy_ctor<_Tp, __is_pod(_Tp)>::_S_do_it(__b, __e, __o);
} }
// copy-construct raw array [__o, *) from strided array __a[<__n : __s>] // copy-construct raw array [__o, *) from strided array __a[<__n : __s>]
@ -178,7 +178,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
__valarray_copy_construct (const _Tp* __restrict__ __a, size_t __n, __valarray_copy_construct (const _Tp* __restrict__ __a, size_t __n,
size_t __s, _Tp* __restrict__ __o) size_t __s, _Tp* __restrict__ __o)
{ {
if (__is_pod<_Tp>::__value) if (__is_pod(_Tp))
while (__n--) while (__n--)
{ {
*__o++ = *__a; *__o++ = *__a;
@ -199,7 +199,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
const size_t* __restrict__ __i, const size_t* __restrict__ __i,
_Tp* __restrict__ __o, size_t __n) _Tp* __restrict__ __o, size_t __n)
{ {
if (__is_pod<_Tp>::__value) if (__is_pod(_Tp))
while (__n--) while (__n--)
*__o++ = __a[*__i++]; *__o++ = __a[*__i++];
else else
@ -212,7 +212,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
inline void inline void
__valarray_destroy_elements(_Tp* __restrict__ __b, _Tp* __restrict__ __e) __valarray_destroy_elements(_Tp* __restrict__ __b, _Tp* __restrict__ __e)
{ {
if (!__is_pod<_Tp>::__value) if (!__is_pod(_Tp))
while (__b != __e) while (__b != __e)
{ {
__b->~_Tp(); __b->~_Tp();
@ -276,7 +276,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
__valarray_copy(const _Tp* __restrict__ __a, size_t __n, __valarray_copy(const _Tp* __restrict__ __a, size_t __n,
_Tp* __restrict__ __b) _Tp* __restrict__ __b)
{ {
_Array_copier<_Tp, __is_pod<_Tp>::__value>::_S_do_it(__a, __n, __b); _Array_copier<_Tp, __is_pod(_Tp)>::_S_do_it(__a, __n, __b);
} }
// Copy strided array __a[<__n : __s>] in plain __b[<__n>] // Copy strided array __a[<__n : __s>] in plain __b[<__n>]