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:
parent
c7a0240aa5
commit
cb68ec5005
@ -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>
|
||||
|
||||
* regmove.c: Move all of pass_stack_adjustments from here...
|
||||
|
@ -90,6 +90,17 @@ enum rid
|
||||
/* casts */
|
||||
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 */
|
||||
RID_STATIC_ASSERT,
|
||||
|
||||
|
@ -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>
|
||||
|
||||
* tree.c (cp_walk_subtrees): Do not set input_location.
|
||||
|
@ -1270,6 +1270,7 @@ check_bases (tree t,
|
||||
TYPE_POLYMORPHIC_P (t) |= TYPE_POLYMORPHIC_P (basetype);
|
||||
CLASSTYPE_CONTAINS_EMPTY_CLASS_P (t)
|
||||
|= 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_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_DFLT (t) |= TYPE_HAS_COMPLEX_DFLT (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_COMPLEX_ASSIGN_REF (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. */
|
||||
add_implicitly_declared_members (t,
|
||||
|
@ -135,6 +135,9 @@ cp_tree_size (enum tree_code code)
|
||||
case ARGUMENT_PACK_SELECT:
|
||||
return sizeof (struct tree_argument_pack_select);
|
||||
|
||||
case TRAIT_EXPR:
|
||||
return sizeof (struct tree_trait_expr);
|
||||
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
@ -422,6 +422,11 @@ DEFTREECODE (EXPR_PACK_EXPANSION, "expr_pack_expansion", tcc_expression, 1)
|
||||
index is a machine integer. */
|
||||
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:
|
||||
mode:c
|
||||
|
@ -478,6 +478,48 @@ struct tree_argument_pack_select GTY (())
|
||||
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 {
|
||||
TS_CP_GENERIC,
|
||||
TS_CP_IDENTIFIER,
|
||||
@ -491,6 +533,7 @@ enum cp_tree_node_structure_enum {
|
||||
TS_CP_DEFAULT_ARG,
|
||||
TS_CP_STATIC_ASSERT,
|
||||
TS_CP_ARGUMENT_PACK_SELECT,
|
||||
TS_CP_TRAIT_EXPR,
|
||||
LAST_TS_CP_ENUM
|
||||
};
|
||||
|
||||
@ -511,6 +554,8 @@ union lang_tree_node GTY((desc ("cp_tree_node_structure (&%h)"),
|
||||
static_assertion;
|
||||
struct tree_argument_pack_select GTY ((tag ("TS_CP_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) \
|
||||
(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. */
|
||||
#define IS_AGGR_TYPE_CODE(T) \
|
||||
((T) == RECORD_TYPE || (T) == UNION_TYPE)
|
||||
@ -1093,6 +1142,7 @@ struct lang_type_class GTY(())
|
||||
unsigned has_complex_init_ref : 1;
|
||||
unsigned has_complex_assign_ref : 1;
|
||||
unsigned non_aggregate : 1;
|
||||
unsigned has_complex_dflt : 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
|
||||
@ -1101,7 +1151,7 @@ struct lang_type_class GTY(())
|
||||
/* 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 : 12;
|
||||
unsigned dummy : 11;
|
||||
|
||||
tree primary_base;
|
||||
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. */
|
||||
#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)
|
||||
|
||||
/* 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]:
|
||||
|
||||
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) \
|
||||
(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
|
||||
a bitwise copy. */
|
||||
#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 int num_artificial_parms_for (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 */
|
||||
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 void finish_static_assert (tree, tree, location_t,
|
||||
bool);
|
||||
extern tree finish_trait_expr (enum cp_trait_kind, tree, tree);
|
||||
|
||||
/* in tree.c */
|
||||
extern void lang_check_failed (const char *, int,
|
||||
|
@ -11739,6 +11739,7 @@ cp_tree_node_structure (union lang_tree_node * t)
|
||||
case BASELINK: return TS_CP_BASELINK;
|
||||
case STATIC_ASSERT: return TS_CP_STATIC_ASSERT;
|
||||
case ARGUMENT_PACK_SELECT: return TS_CP_ARGUMENT_PACK_SELECT;
|
||||
case TRAIT_EXPR: return TS_CP_TRAIT_EXPR;
|
||||
default: return TS_CP_GENERIC;
|
||||
}
|
||||
}
|
||||
|
17
gcc/cp/lex.c
17
gcc/cp/lex.c
@ -199,6 +199,23 @@ static const struct resword reswords[] =
|
||||
{ "__const__", RID_CONST, 0 },
|
||||
{ "__extension__", RID_EXTENSION, 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 },
|
||||
{ "__inline", RID_INLINE, 0 },
|
||||
|
@ -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_copy_constructor (tree);
|
||||
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);
|
||||
|
||||
/* Called once to initialize method.c. */
|
||||
@ -868,7 +865,7 @@ synthesize_exception_spec (tree type, tree (*extractor) (tree, void*),
|
||||
|
||||
/* Locate the dtor of TYPE. */
|
||||
|
||||
static tree
|
||||
tree
|
||||
locate_dtor (tree type, void *client ATTRIBUTE_UNUSED)
|
||||
{
|
||||
return CLASSTYPE_DESTRUCTORS (type);
|
||||
@ -876,7 +873,7 @@ locate_dtor (tree type, void *client ATTRIBUTE_UNUSED)
|
||||
|
||||
/* Locate the default ctor of TYPE. */
|
||||
|
||||
static tree
|
||||
tree
|
||||
locate_ctor (tree type, void *client ATTRIBUTE_UNUSED)
|
||||
{
|
||||
tree fns;
|
||||
@ -912,7 +909,7 @@ struct copy_data
|
||||
points to a COPY_DATA holding the name (NULL for the ctor)
|
||||
and desired qualifiers of the source operand. */
|
||||
|
||||
static tree
|
||||
tree
|
||||
locate_copy (tree type, void *client_)
|
||||
{
|
||||
struct copy_data *client = (struct copy_data *)client_;
|
||||
|
148
gcc/cp/parser.c
148
gcc/cp/parser.c
@ -1897,6 +1897,8 @@ static void cp_parser_late_parsing_default_args
|
||||
(cp_parser *, tree);
|
||||
static tree cp_parser_sizeof_operand
|
||||
(cp_parser *, enum rid);
|
||||
static tree cp_parser_trait_expr
|
||||
(cp_parser *, enum rid);
|
||||
static bool cp_parser_declares_only_class_p
|
||||
(cp_parser *);
|
||||
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_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:
|
||||
|
||||
primary-expression:
|
||||
@ -3201,7 +3222,26 @@ cp_parser_primary_expression (cp_parser *parser,
|
||||
case RID_OFFSETOF:
|
||||
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_PROTOCOL:
|
||||
case RID_AT_SELECTOR:
|
||||
@ -6309,6 +6349,112 @@ cp_parser_builtin_offsetof (cp_parser *parser)
|
||||
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] */
|
||||
|
||||
/* Parse a statement.
|
||||
|
21
gcc/cp/pt.c
21
gcc/cp/pt.c
@ -5818,6 +5818,7 @@ uses_template_parms (tree t)
|
||||
|| TREE_CODE (t) == OVERLOAD
|
||||
|| TREE_CODE (t) == BASELINK
|
||||
|| TREE_CODE (t) == IDENTIFIER_NODE
|
||||
|| TREE_CODE (t) == TRAIT_EXPR
|
||||
|| CONSTANT_CLASS_P (t))
|
||||
dependent_p = (type_dependent_expression_p (t)
|
||||
|| value_dependent_expression_p (t));
|
||||
@ -10703,6 +10704,18 @@ tsubst_copy_and_build (tree t,
|
||||
case OFFSETOF_EXPR:
|
||||
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:
|
||||
{
|
||||
tree old_stmt_expr = cur_stmt_expr;
|
||||
@ -14912,6 +14925,13 @@ value_dependent_expression_p (tree expression)
|
||||
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:
|
||||
/* A constant expression is value-dependent if any subexpression is
|
||||
value-dependent. */
|
||||
@ -14975,6 +14995,7 @@ type_dependent_expression_p (tree expression)
|
||||
if (TREE_CODE (expression) == PSEUDO_DTOR_EXPR
|
||||
|| TREE_CODE (expression) == SIZEOF_EXPR
|
||||
|| TREE_CODE (expression) == ALIGNOF_EXPR
|
||||
|| TREE_CODE (expression) == TRAIT_EXPR
|
||||
|| TREE_CODE (expression) == TYPEID_EXPR
|
||||
|| TREE_CODE (expression) == DELETE_EXPR
|
||||
|| TREE_CODE (expression) == VEC_DELETE_EXPR
|
||||
|
@ -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"
|
||||
|
@ -2293,6 +2293,12 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func,
|
||||
*walk_subtrees_p = 0;
|
||||
break;
|
||||
|
||||
case TRAIT_EXPR:
|
||||
WALK_SUBTREE (TRAIT_EXPR_TYPE1 (*tp));
|
||||
WALK_SUBTREE (TRAIT_EXPR_TYPE2 (*tp));
|
||||
*walk_subtrees_p = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
@ -10675,6 +10675,7 @@ Predefined Macros,cpp,The GNU C Preprocessor}).
|
||||
method denoted by a @samp{->*} or @samp{.*} expression.
|
||||
* C++ Attributes:: Variable, function, and type attributes for C++ only.
|
||||
* Namespace Association:: Strong using-directives for namespace association.
|
||||
* Type Traits:: Compiler support for type traits
|
||||
* Java Exceptions:: Tweaking exception handling to work with Java.
|
||||
* Deprecated Features:: Things will disappear from g++.
|
||||
* Backwards Compatibility:: Compatibilities with earlier definitions of C++.
|
||||
@ -11232,6 +11233,124 @@ int main()
|
||||
@}
|
||||
@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
|
||||
@section Java Exceptions
|
||||
|
||||
|
@ -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>
|
||||
|
||||
* g++.dg/warn/pedantic2.C: New testcase.
|
||||
|
152
gcc/testsuite/g++.dg/ext/has_nothrow_assign.C
Normal file
152
gcc/testsuite/g++.dg/ext/has_nothrow_assign.C
Normal 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;
|
||||
}
|
106
gcc/testsuite/g++.dg/ext/has_nothrow_constructor.C
Normal file
106
gcc/testsuite/g++.dg/ext/has_nothrow_constructor.C
Normal 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;
|
||||
}
|
140
gcc/testsuite/g++.dg/ext/has_nothrow_copy.C
Normal file
140
gcc/testsuite/g++.dg/ext/has_nothrow_copy.C
Normal 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;
|
||||
}
|
106
gcc/testsuite/g++.dg/ext/has_trivial_assign.C
Normal file
106
gcc/testsuite/g++.dg/ext/has_trivial_assign.C
Normal 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;
|
||||
}
|
98
gcc/testsuite/g++.dg/ext/has_trivial_constructor.C
Normal file
98
gcc/testsuite/g++.dg/ext/has_trivial_constructor.C
Normal 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;
|
||||
}
|
105
gcc/testsuite/g++.dg/ext/has_trivial_copy.C
Normal file
105
gcc/testsuite/g++.dg/ext/has_trivial_copy.C
Normal 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;
|
||||
}
|
86
gcc/testsuite/g++.dg/ext/has_trivial_destructor.C
Normal file
86
gcc/testsuite/g++.dg/ext/has_trivial_destructor.C
Normal 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;
|
||||
}
|
89
gcc/testsuite/g++.dg/ext/has_virtual_destructor.C
Normal file
89
gcc/testsuite/g++.dg/ext/has_virtual_destructor.C
Normal 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;
|
||||
}
|
89
gcc/testsuite/g++.dg/ext/is_abstract.C
Normal file
89
gcc/testsuite/g++.dg/ext/is_abstract.C
Normal 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;
|
||||
}
|
94
gcc/testsuite/g++.dg/ext/is_base_of.C
Normal file
94
gcc/testsuite/g++.dg/ext/is_base_of.C
Normal 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;
|
||||
}
|
15
gcc/testsuite/g++.dg/ext/is_base_of_diagnostic.C
Normal file
15
gcc/testsuite/g++.dg/ext/is_base_of_diagnostic.C
Normal 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);
|
||||
}
|
76
gcc/testsuite/g++.dg/ext/is_class.C
Normal file
76
gcc/testsuite/g++.dg/ext/is_class.C
Normal 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;
|
||||
}
|
78
gcc/testsuite/g++.dg/ext/is_empty.C
Normal file
78
gcc/testsuite/g++.dg/ext/is_empty.C
Normal 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;
|
||||
}
|
73
gcc/testsuite/g++.dg/ext/is_enum.C
Normal file
73
gcc/testsuite/g++.dg/ext/is_enum.C
Normal 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;
|
||||
}
|
75
gcc/testsuite/g++.dg/ext/is_pod.C
Normal file
75
gcc/testsuite/g++.dg/ext/is_pod.C
Normal 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;
|
||||
}
|
83
gcc/testsuite/g++.dg/ext/is_polymorphic.C
Normal file
83
gcc/testsuite/g++.dg/ext/is_polymorphic.C
Normal 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;
|
||||
}
|
76
gcc/testsuite/g++.dg/ext/is_union.C
Normal file
76
gcc/testsuite/g++.dg/ext/is_union.C
Normal 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;
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
|
||||
extern "C" {
|
||||
template<typename _Tp> // { dg-error "C" }
|
||||
struct __is_pod {
|
||||
struct ___is_pod {
|
||||
enum {
|
||||
__value = (sizeof(__gnu_internal::__test_type<_Tp>(0)))}; // { dg-error "declared|expected" }
|
||||
|
||||
|
@ -22,7 +22,7 @@ namespace __gnu_internal
|
||||
}
|
||||
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)) };
|
||||
};
|
||||
@ -111,7 +111,7 @@ namespace std
|
||||
typedef _Val value_type;
|
||||
typedef value_type* pointer;
|
||||
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
|
||||
{
|
||||
_Rb_tree_node_base _M_header;
|
||||
|
@ -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>
|
||||
|
||||
PR libstdc++/31401
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Allocators -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006
|
||||
// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007
|
||||
// Free Software Foundation, Inc.
|
||||
//
|
||||
// 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
|
||||
|
||||
// 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
|
||||
{ static void _S_do_it(_Alloc&, _Alloc&) { } };
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
// 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.
|
||||
//
|
||||
// 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)
|
||||
|
||||
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 __false_type { };
|
||||
|
||||
@ -341,37 +327,6 @@ namespace __detail
|
||||
: 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.
|
||||
//
|
||||
|
@ -393,7 +393,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
|
||||
|
||||
protected:
|
||||
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
|
||||
{
|
||||
_Key_compare _M_key_compare;
|
||||
|
@ -1,6 +1,6 @@
|
||||
// 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.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
@ -98,7 +98,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
|
||||
inline void
|
||||
__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
|
||||
@ -133,7 +133,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
|
||||
__valarray_fill_construct(_Tp* __restrict__ __b, _Tp* __restrict__ __e,
|
||||
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,
|
||||
_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>]
|
||||
@ -178,7 +178,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
|
||||
__valarray_copy_construct (const _Tp* __restrict__ __a, size_t __n,
|
||||
size_t __s, _Tp* __restrict__ __o)
|
||||
{
|
||||
if (__is_pod<_Tp>::__value)
|
||||
if (__is_pod(_Tp))
|
||||
while (__n--)
|
||||
{
|
||||
*__o++ = *__a;
|
||||
@ -199,7 +199,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
|
||||
const size_t* __restrict__ __i,
|
||||
_Tp* __restrict__ __o, size_t __n)
|
||||
{
|
||||
if (__is_pod<_Tp>::__value)
|
||||
if (__is_pod(_Tp))
|
||||
while (__n--)
|
||||
*__o++ = __a[*__i++];
|
||||
else
|
||||
@ -212,7 +212,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
|
||||
inline void
|
||||
__valarray_destroy_elements(_Tp* __restrict__ __b, _Tp* __restrict__ __e)
|
||||
{
|
||||
if (!__is_pod<_Tp>::__value)
|
||||
if (!__is_pod(_Tp))
|
||||
while (__b != __e)
|
||||
{
|
||||
__b->~_Tp();
|
||||
@ -276,7 +276,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
|
||||
__valarray_copy(const _Tp* __restrict__ __a, size_t __n,
|
||||
_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>]
|
||||
|
Loading…
x
Reference in New Issue
Block a user