re PR c++/39475 (c++0x type-traits should error out in case of incompleteness)

/cp
2009-03-17  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/39475
	* semantics.c (check_trait_type): New.
	(finish_trait_expr): Use it.

/testsuite
2009-03-17  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/39475
	* g++.dg/ext/unary_trait_incomplete.C: New.

From-SVN: r144919
This commit is contained in:
Paolo Carlini 2009-03-17 20:49:23 +00:00 committed by Paolo Carlini
parent 3c072c6ba2
commit ff284b4bbe
4 changed files with 143 additions and 7 deletions

View File

@ -1,3 +1,9 @@
2009-03-17 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/39475
* semantics.c (check_trait_type): New.
(finish_trait_expr): Use it.
2009-03-17 Jakub Jelinek <jakub@redhat.com>
* name-lookup.c (cp_emit_debug_info_for_using): Emit USING_STMTs

View File

@ -4902,6 +4902,24 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
}
}
/* Returns true if TYPE is a complete type, an array of unknown bound,
or (possibly cv-qualified) void, returns false otherwise. */
static bool
check_trait_type (tree type)
{
if (COMPLETE_TYPE_P (type))
return true;
if (TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type))
return true;
if (VOID_TYPE_P (type))
return true;
return false;
}
/* Process a trait expression. */
tree
@ -4950,14 +4968,45 @@ finish_trait_expr (cp_trait_kind kind, tree type1, tree type2)
if (type2)
complete_type (type2);
/* 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 (type2))
switch (kind)
{
error ("incomplete type %qT not allowed", type2);
return error_mark_node;
case CPTK_HAS_NOTHROW_ASSIGN:
case CPTK_HAS_TRIVIAL_ASSIGN:
case CPTK_HAS_NOTHROW_CONSTRUCTOR:
case CPTK_HAS_TRIVIAL_CONSTRUCTOR:
case CPTK_HAS_NOTHROW_COPY:
case CPTK_HAS_TRIVIAL_COPY:
case CPTK_HAS_TRIVIAL_DESTRUCTOR:
case CPTK_HAS_VIRTUAL_DESTRUCTOR:
case CPTK_IS_ABSTRACT:
case CPTK_IS_EMPTY:
case CPTK_IS_POD:
case CPTK_IS_POLYMORPHIC:
if (!check_trait_type (type1))
{
error ("incomplete type %qT not allowed", type1);
return error_mark_node;
}
break;
case CPTK_IS_BASE_OF:
if (NON_UNION_CLASS_TYPE_P (type1) && NON_UNION_CLASS_TYPE_P (type2)
&& !same_type_ignoring_top_level_qualifiers_p (type1, type2)
&& !COMPLETE_TYPE_P (type2))
{
error ("incomplete type %qT not allowed", type2);
return error_mark_node;
}
break;
case CPTK_IS_CLASS:
case CPTK_IS_ENUM:
case CPTK_IS_UNION:
break;
case CPTK_IS_CONVERTIBLE_TO:
default:
gcc_unreachable ();
}
return (trait_expr_value (kind, type1, type2)

View File

@ -1,3 +1,8 @@
2009-03-17 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/39475
* g++.dg/ext/unary_trait_incomplete.C: New.
2009-03-17 Jing Yu <jingyu@google.com>
PR middle-end/39378

View File

@ -0,0 +1,76 @@
// PR c++/39475
struct I;
struct C { };
bool nas1 = __has_nothrow_assign(I); // { dg-error "incomplete type" }
bool nas2 = __has_nothrow_assign(C[]);
bool nas3 = __has_nothrow_assign(I[]);
bool nas4 = __has_nothrow_assign(void);
bool nas5 = __has_nothrow_assign(const void);
bool tas1 = __has_trivial_assign(I); // { dg-error "incomplete type" }
bool tas2 = __has_trivial_assign(C[]);
bool tas3 = __has_trivial_assign(I[]);
bool tas4 = __has_trivial_assign(void);
bool tas5 = __has_trivial_assign(const void);
bool nco1 = __has_nothrow_constructor(I); // { dg-error "incomplete type" }
bool nco2 = __has_nothrow_constructor(C[]);
bool nco3 = __has_nothrow_constructor(I[]);
bool nco4 = __has_nothrow_constructor(void);
bool nco5 = __has_nothrow_constructor(const void);
bool tco1 = __has_trivial_constructor(I); // { dg-error "incomplete type" }
bool tco2 = __has_trivial_constructor(C[]);
bool tco3 = __has_trivial_constructor(I[]);
bool tco4 = __has_trivial_constructor(void);
bool tco5 = __has_trivial_constructor(const void);
bool ncp1 = __has_nothrow_copy(I); // { dg-error "incomplete type" }
bool ncp2 = __has_nothrow_copy(C[]);
bool ncp3 = __has_nothrow_copy(I[]);
bool ncp4 = __has_nothrow_copy(void);
bool ncp5 = __has_nothrow_copy(const void);
bool tcp1 = __has_trivial_copy(I); // { dg-error "incomplete type" }
bool tcp2 = __has_trivial_copy(C[]);
bool tcp3 = __has_trivial_copy(I[]);
bool tcp4 = __has_trivial_copy(void);
bool tcp5 = __has_trivial_copy(const void);
bool vde1 = __has_virtual_destructor(I); // { dg-error "incomplete type" }
bool vde2 = __has_virtual_destructor(C[]);
bool vde3 = __has_virtual_destructor(I[]);
bool vde4 = __has_virtual_destructor(void);
bool vde5 = __has_virtual_destructor(const void);
bool tde1 = __has_trivial_destructor(I); // { dg-error "incomplete type" }
bool tde2 = __has_trivial_destructor(C[]);
bool tde3 = __has_trivial_destructor(I[]);
bool tde4 = __has_trivial_destructor(void);
bool tde5 = __has_trivial_destructor(const void);
bool abs1 = __is_abstract(I); // { dg-error "incomplete type" }
bool abs2 = __is_abstract(C[]);
bool abs3 = __is_abstract(I[]);
bool abs4 = __is_abstract(void);
bool abs5 = __is_abstract(const void);
bool pod1 = __is_pod(I); // { dg-error "incomplete type" }
bool pod2 = __is_pod(C[]);
bool pod3 = __is_pod(I[]);
bool pod4 = __is_pod(void);
bool pod5 = __is_pod(const void);
bool emp1 = __is_empty(I); // { dg-error "incomplete type" }
bool emp2 = __is_empty(C[]);
bool emp3 = __is_empty(I[]);
bool emp4 = __is_empty(void);
bool emp5 = __is_empty(const void);
bool pol1 = __is_polymorphic(I); // { dg-error "incomplete type" }
bool pol2 = __is_polymorphic(C[]);
bool pol3 = __is_polymorphic(I[]);
bool pol4 = __is_polymorphic(void);
bool pol5 = __is_polymorphic(const void);