* [C++ Patch] PR 50732
@ 2011-10-14 18:48 Paolo Carlini
2011-10-14 18:56 ` Paolo Carlini
0 siblings, 1 reply; 10+ messages in thread
From: Paolo Carlini @ 2011-10-14 18:48 UTC (permalink / raw)
To: gcc-patches; +Cc: Jason Merrill
[-- Attachment #1: Type: text/plain, Size: 316 bytes --]
Hi,
submitter complains that, at variance with C++11, __is_base_of doesn't
handle an incomplete base type (the first parameter). The reason seems
simple: in finish_trait_expr we try to complete *both* types instead of
doing it where/when necessary.
Tested x86_64-linux. Ok?
Thanks,
Paolo.
///////////////////
[-- Attachment #2: CL_50732 --]
[-- Type: text/plain, Size: 305 bytes --]
/cp
2011-10-14 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/50732
* semantics.c (finish_trait_expr): Do not try to instantiate the
the base type of an __is_base_of trait.
/testsuite
2011-10-14 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/50732
* g++.dg/ext/is_base_of_incomplete.C: New.
[-- Attachment #3: patch_50732 --]
[-- Type: text/plain, Size: 1449 bytes --]
Index: testsuite/g++.dg/ext/is_base_of_incomplete.C
===================================================================
--- testsuite/g++.dg/ext/is_base_of_incomplete.C (revision 0)
+++ testsuite/g++.dg/ext/is_base_of_incomplete.C (revision 0)
@@ -0,0 +1,7 @@
+template <typename T>
+struct non_instantiable
+{
+ typedef typename T::THIS_TYPE_CANNOT_BE_INSTANTIATED type;
+};
+
+int check[__is_base_of(non_instantiable<int>, void) ? -1 : 1];
Index: cp/semantics.c
===================================================================
--- cp/semantics.c (revision 179997)
+++ cp/semantics.c (working copy)
@@ -5276,10 +5276,6 @@ finish_trait_expr (cp_trait_kind kind, tree type1,
return trait_expr;
}
- complete_type (type1);
- if (type2)
- complete_type (type2);
-
switch (kind)
{
case CPTK_HAS_NOTHROW_ASSIGN:
@@ -5297,6 +5293,7 @@ finish_trait_expr (cp_trait_kind kind, tree type1,
case CPTK_IS_POLYMORPHIC:
case CPTK_IS_STD_LAYOUT:
case CPTK_IS_TRIVIAL:
+ complete_type (type1);
if (!check_trait_type (type1))
{
error ("incomplete type %qT not allowed", type1);
@@ -5305,6 +5302,7 @@ finish_trait_expr (cp_trait_kind kind, tree type1,
break;
case CPTK_IS_BASE_OF:
+ complete_type (type2);
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))
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [C++ Patch] PR 50732
2011-10-14 18:48 [C++ Patch] PR 50732 Paolo Carlini
@ 2011-10-14 18:56 ` Paolo Carlini
2011-10-14 19:12 ` Paolo Carlini
0 siblings, 1 reply; 10+ messages in thread
From: Paolo Carlini @ 2011-10-14 18:56 UTC (permalink / raw)
To: Paolo Carlini; +Cc: gcc-patches, Jason Merrill
On 10/14/2011 08:23 PM, Paolo Carlini wrote:
> Hi,
>
> submitter complains that, at variance with C++11, __is_base_of doesn't
> handle an incomplete base type (the first parameter). The reason seems
> simple: in finish_trait_expr we try to complete *both* types instead
> of doing it where/when necessary.
Hmm, maybe we should be even more careful and call complete (type2) only
when
NON_UNION_CLASS_TYPE_P (type1) && NON_UNION_CLASS_TYPE_P (type2) &&
!same_type_ignoring_top_level_qualifiers_p (type1, type2)
is true?
Paolo.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [C++ Patch] PR 50732
2011-10-14 18:56 ` Paolo Carlini
@ 2011-10-14 19:12 ` Paolo Carlini
2011-10-14 19:41 ` Jason Merrill
0 siblings, 1 reply; 10+ messages in thread
From: Paolo Carlini @ 2011-10-14 19:12 UTC (permalink / raw)
To: Paolo Carlini; +Cc: gcc-patches, Jason Merrill
[-- Attachment #1: Type: text/plain, Size: 632 bytes --]
On 10/14/2011 08:30 PM, Paolo Carlini wrote:
> On 10/14/2011 08:23 PM, Paolo Carlini wrote:
>> Hi,
>>
>> submitter complains that, at variance with C++11, __is_base_of
>> doesn't handle an incomplete base type (the first parameter). The
>> reason seems simple: in finish_trait_expr we try to complete *both*
>> types instead of doing it where/when necessary.
> Hmm, maybe we should be even more careful and call complete (type2)
> only when
>
> NON_UNION_CLASS_TYPE_P (type1) && NON_UNION_CLASS_TYPE_P (type2) &&
> !same_type_ignoring_top_level_qualifiers_p (type1, type2)
>
> is true?
Like this?
Paolo.
///////////////////
[-- Attachment #2: patch_50732_alt --]
[-- Type: text/plain, Size: 1746 bytes --]
Index: testsuite/g++.dg/ext/is_base_of_incomplete.C
===================================================================
--- testsuite/g++.dg/ext/is_base_of_incomplete.C (revision 0)
+++ testsuite/g++.dg/ext/is_base_of_incomplete.C (revision 0)
@@ -0,0 +1,7 @@
+template <typename T>
+struct non_instantiable
+{
+ typedef typename T::THIS_TYPE_CANNOT_BE_INSTANTIATED type;
+};
+
+int check[__is_base_of(non_instantiable<int>, void) ? -1 : 1];
Index: cp/semantics.c
===================================================================
--- cp/semantics.c (revision 179997)
+++ cp/semantics.c (working copy)
@@ -5276,10 +5276,6 @@ finish_trait_expr (cp_trait_kind kind, tree type1,
return trait_expr;
}
- complete_type (type1);
- if (type2)
- complete_type (type2);
-
switch (kind)
{
case CPTK_HAS_NOTHROW_ASSIGN:
@@ -5297,6 +5293,7 @@ finish_trait_expr (cp_trait_kind kind, tree type1,
case CPTK_IS_POLYMORPHIC:
case CPTK_IS_STD_LAYOUT:
case CPTK_IS_TRIVIAL:
+ complete_type (type1);
if (!check_trait_type (type1))
{
error ("incomplete type %qT not allowed", type1);
@@ -5306,11 +5303,14 @@ finish_trait_expr (cp_trait_kind kind, tree type1,
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))
+ && !same_type_ignoring_top_level_qualifiers_p (type1, type2))
{
- error ("incomplete type %qT not allowed", type2);
- return error_mark_node;
+ complete_type (type2);
+ if (!COMPLETE_TYPE_P (type2))
+ {
+ error ("incomplete type %qT not allowed", type2);
+ return error_mark_node;
+ }
}
break;
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [C++ Patch] PR 50732
2011-10-14 19:12 ` Paolo Carlini
@ 2011-10-14 19:41 ` Jason Merrill
2011-10-14 23:03 ` Paolo Carlini
0 siblings, 1 reply; 10+ messages in thread
From: Jason Merrill @ 2011-10-14 19:41 UTC (permalink / raw)
To: Paolo Carlini; +Cc: gcc-patches
How about using complete_type_or_else?
Jason
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [C++ Patch] PR 50732
2011-10-14 19:41 ` Jason Merrill
@ 2011-10-14 23:03 ` Paolo Carlini
2011-10-14 23:26 ` Jason Merrill
0 siblings, 1 reply; 10+ messages in thread
From: Paolo Carlini @ 2011-10-14 23:03 UTC (permalink / raw)
To: Jason Merrill; +Cc: gcc-patches
[-- Attachment #1: Type: text/plain, Size: 659 bytes --]
On 10/14/2011 09:08 PM, Jason Merrill wrote:
> How about using complete_type_or_else?
The CPTK_IS_BASE_OF case becomes much simpler indeed, thanks. For the
unary traits, though, I don't see an advantage in using it, because in
some cases in check_trait_type we don't want to error out even when
complete_type_or_else would. Unless we can check whether we are dealing
with an array of unknown bound *before* completing the type? That is:
if (TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type)
&& COMPLETE_TYPE_P (TREE_TYPE (type)))
is the outcome always the same before and after trying to complete (type)?
Thanks,
Paolo.
//////////////////////
[-- Attachment #2: patch_50732_2 --]
[-- Type: text/plain, Size: 2111 bytes --]
Index: testsuite/g++.dg/ext/is_base_of_diagnostic.C
===================================================================
--- testsuite/g++.dg/ext/is_base_of_diagnostic.C (revision 180007)
+++ testsuite/g++.dg/ext/is_base_of_diagnostic.C (working copy)
@@ -1,7 +1,7 @@
class A
{ };
-class B;
+class B; // { dg-error "forward declaration" }
union C
{ };
Index: testsuite/g++.dg/ext/is_base_of_incomplete.C
===================================================================
--- testsuite/g++.dg/ext/is_base_of_incomplete.C (revision 0)
+++ testsuite/g++.dg/ext/is_base_of_incomplete.C (revision 0)
@@ -0,0 +1,7 @@
+template <typename T>
+struct non_instantiable
+{
+ typedef typename T::THIS_TYPE_CANNOT_BE_INSTANTIATED type;
+};
+
+int check[__is_base_of(non_instantiable<int>, void) ? -1 : 1];
Index: cp/semantics.c
===================================================================
--- cp/semantics.c (revision 180007)
+++ cp/semantics.c (working copy)
@@ -5276,10 +5276,6 @@ finish_trait_expr (cp_trait_kind kind, tree type1,
return trait_expr;
}
- complete_type (type1);
- if (type2)
- complete_type (type2);
-
switch (kind)
{
case CPTK_HAS_NOTHROW_ASSIGN:
@@ -5297,9 +5293,10 @@ finish_trait_expr (cp_trait_kind kind, tree type1,
case CPTK_IS_POLYMORPHIC:
case CPTK_IS_STD_LAYOUT:
case CPTK_IS_TRIVIAL:
+ complete_type (type1);
if (!check_trait_type (type1))
{
- error ("incomplete type %qT not allowed", type1);
+ error ("invalid use of incomplete type %qT", type1);
return error_mark_node;
}
break;
@@ -5307,11 +5304,9 @@ finish_trait_expr (cp_trait_kind kind, tree type1,
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;
- }
+ && !complete_type_or_else (type2, NULL_TREE))
+ /* We already issued an error. */
+ return error_mark_node;
break;
case CPTK_IS_CLASS:
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [C++ Patch] PR 50732
2011-10-14 23:03 ` Paolo Carlini
@ 2011-10-14 23:26 ` Jason Merrill
2011-10-15 1:17 ` Paolo Carlini
0 siblings, 1 reply; 10+ messages in thread
From: Jason Merrill @ 2011-10-14 23:26 UTC (permalink / raw)
To: Paolo Carlini; +Cc: gcc-patches
On 10/14/2011 05:58 PM, Paolo Carlini wrote:
> On 10/14/2011 09:08 PM, Jason Merrill wrote:
>> How about using complete_type_or_else?
> The CPTK_IS_BASE_OF case becomes much simpler indeed, thanks. For the
> unary traits, though, I don't see an advantage in using it, because in
> some cases in check_trait_type we don't want to error out even when
> complete_type_or_else would. Unless we can check whether we are dealing
> with an array of unknown bound *before* completing the type? That is:
>
> if (TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type)
> && COMPLETE_TYPE_P (TREE_TYPE (type)))
>
> is the outcome always the same before and after trying to complete (type)?
That should work.
Jason
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [C++ Patch] PR 50732
2011-10-14 23:26 ` Jason Merrill
@ 2011-10-15 1:17 ` Paolo Carlini
2011-10-15 20:42 ` Jason Merrill
0 siblings, 1 reply; 10+ messages in thread
From: Paolo Carlini @ 2011-10-15 1:17 UTC (permalink / raw)
To: Jason Merrill; +Cc: gcc-patches
[-- Attachment #1: Type: text/plain, Size: 245 bytes --]
On 10/15/2011 12:20 AM, Jason Merrill wrote:
> That should work.
Excellent. Then we can do something like the below, a great improvement.
I'm finishing testing it (already past g++.dg), Ok if it passes?
Thanks,
Paolo.
///////////////////////
[-- Attachment #2: CL_50732_3 --]
[-- Type: text/plain, Size: 475 bytes --]
/cp
2011-10-14 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/50732
* semantics.c (finish_trait_expr): Do not try to instantiate the
the base type of an __is_base_of trait.
(check_trait_type): Return a tree; use complete_type_or_else.
/testsuite
2011-10-14 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/50732
* g++.dg/ext/is_base_of_incomplete.C: New.
* g++.dg/ext/is_base_of_diagnostic.C: Adjust dg-errors.
* g++.dg/ext/unary_trait_incomplete.C: Likewise.
[-- Attachment #3: patch_50732_3 --]
[-- Type: text/plain, Size: 7227 bytes --]
Index: testsuite/g++.dg/ext/unary_trait_incomplete.C
===================================================================
--- testsuite/g++.dg/ext/unary_trait_incomplete.C (revision 180007)
+++ testsuite/g++.dg/ext/unary_trait_incomplete.C (working copy)
@@ -1,76 +1,76 @@
// PR c++/39475
-struct I;
+struct I; // { dg-error "forward declaration" }
struct C { };
bool nas1 = __has_nothrow_assign(I); // { dg-error "incomplete type" }
bool nas2 = __has_nothrow_assign(C[]);
-bool nas3 = __has_nothrow_assign(I[]); // { dg-error "incomplete type" }
+bool nas3 = __has_nothrow_assign(I[]); // { dg-error "unspecified bounds" }
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[]); // { dg-error "incomplete type" }
+bool tas3 = __has_trivial_assign(I[]); // { dg-error "unspecified bounds" }
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[]); // { dg-error "incomplete type" }
+bool nco3 = __has_nothrow_constructor(I[]); // { dg-error "unspecified bounds" }
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[]); // { dg-error "incomplete type" }
+bool tco3 = __has_trivial_constructor(I[]); // { dg-error "unspecified bounds" }
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[]); // { dg-error "incomplete type" }
+bool ncp3 = __has_nothrow_copy(I[]); // { dg-error "unspecified bounds" }
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[]); // { dg-error "incomplete type" }
+bool tcp3 = __has_trivial_copy(I[]); // { dg-error "unspecified bounds" }
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[]); // { dg-error "incomplete type" }
+bool vde3 = __has_virtual_destructor(I[]); // { dg-error "unspecified bounds" }
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[]); // { dg-error "incomplete type" }
+bool tde3 = __has_trivial_destructor(I[]); // { dg-error "unspecified bounds" }
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[]); // { dg-error "incomplete type" }
+bool abs3 = __is_abstract(I[]); // { dg-error "unspecified bounds" }
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[]); // { dg-error "incomplete type" }
+bool pod3 = __is_pod(I[]); // { dg-error "unspecified bounds" }
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[]); // { dg-error "incomplete type" }
+bool emp3 = __is_empty(I[]); // { dg-error "unspecified bounds" }
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[]); // { dg-error "incomplete type" }
+bool pol3 = __is_polymorphic(I[]); // { dg-error "unspecified bounds" }
bool pol4 = __is_polymorphic(void);
bool pol5 = __is_polymorphic(const void);
Index: testsuite/g++.dg/ext/is_base_of_diagnostic.C
===================================================================
--- testsuite/g++.dg/ext/is_base_of_diagnostic.C (revision 180007)
+++ testsuite/g++.dg/ext/is_base_of_diagnostic.C (working copy)
@@ -1,7 +1,7 @@
class A
{ };
-class B;
+class B; // { dg-error "forward declaration" }
union C
{ };
Index: testsuite/g++.dg/ext/is_base_of_incomplete.C
===================================================================
--- testsuite/g++.dg/ext/is_base_of_incomplete.C (revision 0)
+++ testsuite/g++.dg/ext/is_base_of_incomplete.C (revision 0)
@@ -0,0 +1,7 @@
+template <typename T>
+struct non_instantiable
+{
+ typedef typename T::THIS_TYPE_CANNOT_BE_INSTANTIATED type;
+};
+
+int check[__is_base_of(non_instantiable<int>, void) ? -1 : 1];
Index: cp/semantics.c
===================================================================
--- cp/semantics.c (revision 180007)
+++ cp/semantics.c (working copy)
@@ -5210,23 +5210,20 @@ trait_expr_value (cp_trait_kind kind, tree type1,
}
}
-/* Returns true if TYPE is a complete type, an array of unknown bound,
- or (possibly cv-qualified) void, returns false otherwise. */
+/* If TYPE is an array of unknown bound, or (possibly cv-qualified)
+ void, or a complete type, returns it, otherwise NULL_TREE. */
-static bool
+static tree
check_trait_type (tree type)
{
- if (COMPLETE_TYPE_P (type))
- return true;
-
if (TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type)
&& COMPLETE_TYPE_P (TREE_TYPE (type)))
- return true;
+ return type;
if (VOID_TYPE_P (type))
- return true;
+ return type;
- return false;
+ return complete_type_or_else (type, NULL_TREE);
}
/* Process a trait expression. */
@@ -5276,10 +5273,6 @@ finish_trait_expr (cp_trait_kind kind, tree type1,
return trait_expr;
}
- complete_type (type1);
- if (type2)
- complete_type (type2);
-
switch (kind)
{
case CPTK_HAS_NOTHROW_ASSIGN:
@@ -5298,20 +5291,15 @@ finish_trait_expr (cp_trait_kind kind, tree type1,
case CPTK_IS_STD_LAYOUT:
case CPTK_IS_TRIVIAL:
if (!check_trait_type (type1))
- {
- error ("incomplete type %qT not allowed", type1);
- return error_mark_node;
- }
+ 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;
- }
+ && !complete_type_or_else (type2, NULL_TREE))
+ /* We already issued an error. */
+ return error_mark_node;
break;
case CPTK_IS_CLASS:
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [C++ Patch] PR 50732
2011-10-15 1:17 ` Paolo Carlini
@ 2011-10-15 20:42 ` Jason Merrill
2011-10-15 21:21 ` Paolo Carlini
0 siblings, 1 reply; 10+ messages in thread
From: Jason Merrill @ 2011-10-15 20:42 UTC (permalink / raw)
To: Paolo Carlini; +Cc: gcc-patches
On 10/14/2011 06:57 PM, Paolo Carlini wrote:
> - return false;
> + return complete_type_or_else (type, NULL_TREE);
I think I'd do
complete_type_or_else (strip_array_types (type), NULL_TREE)
so that the error doesn't complain about unspecified bounds, which would
be misleading.
Jason
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [C++ Patch] PR 50732
2011-10-15 20:42 ` Jason Merrill
@ 2011-10-15 21:21 ` Paolo Carlini
2011-10-15 21:27 ` Jason Merrill
0 siblings, 1 reply; 10+ messages in thread
From: Paolo Carlini @ 2011-10-15 21:21 UTC (permalink / raw)
To: Jason Merrill; +Cc: gcc-patches
[-- Attachment #1: Type: text/plain, Size: 485 bytes --]
On 10/15/2011 08:33 PM, Jason Merrill wrote:
> On 10/14/2011 06:57 PM, Paolo Carlini wrote:
>> - return false;
>> + return complete_type_or_else (type, NULL_TREE);
>
> I think I'd do
>
> complete_type_or_else (strip_array_types (type), NULL_TREE)
>
> so that the error doesn't complain about unspecified bounds, which
> would be misleading.
Good point, thanks.
Thus, what about the below? Again, testing already past g++.dg/dg.exp.
Thanks again,
Paolo.
///////////////////////
[-- Attachment #2: patch_50732_4 --]
[-- Type: text/plain, Size: 3216 bytes --]
Index: testsuite/g++.dg/ext/unary_trait_incomplete.C
===================================================================
--- testsuite/g++.dg/ext/unary_trait_incomplete.C (revision 180046)
+++ testsuite/g++.dg/ext/unary_trait_incomplete.C (working copy)
@@ -1,6 +1,6 @@
// PR c++/39475
-struct I;
+struct I; // { dg-error "forward declaration" }
struct C { };
bool nas1 = __has_nothrow_assign(I); // { dg-error "incomplete type" }
Index: testsuite/g++.dg/ext/is_base_of_diagnostic.C
===================================================================
--- testsuite/g++.dg/ext/is_base_of_diagnostic.C (revision 180046)
+++ testsuite/g++.dg/ext/is_base_of_diagnostic.C (working copy)
@@ -1,7 +1,7 @@
class A
{ };
-class B;
+class B; // { dg-error "forward declaration" }
union C
{ };
Index: testsuite/g++.dg/ext/is_base_of_incomplete.C
===================================================================
--- testsuite/g++.dg/ext/is_base_of_incomplete.C (revision 0)
+++ testsuite/g++.dg/ext/is_base_of_incomplete.C (revision 0)
@@ -0,0 +1,9 @@
+// PR c++/50732
+
+template <typename T>
+struct non_instantiable
+{
+ typedef typename T::THIS_TYPE_CANNOT_BE_INSTANTIATED type;
+};
+
+int check[__is_base_of(non_instantiable<int>, void) ? -1 : 1];
Index: cp/semantics.c
===================================================================
--- cp/semantics.c (revision 180007)
+++ cp/semantics.c (working copy)
@@ -5210,23 +5210,20 @@ trait_expr_value (cp_trait_kind kind, tree type1,
}
}
-/* Returns true if TYPE is a complete type, an array of unknown bound,
- or (possibly cv-qualified) void, returns false otherwise. */
+/* If TYPE is an array of unknown bound, or (possibly cv-qualified)
+ void, or a complete type, returns it, otherwise NULL_TREE. */
-static bool
+static tree
check_trait_type (tree type)
{
- if (COMPLETE_TYPE_P (type))
- return true;
-
if (TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type)
&& COMPLETE_TYPE_P (TREE_TYPE (type)))
- return true;
+ return type;
if (VOID_TYPE_P (type))
- return true;
+ return type;
- return false;
+ return complete_type_or_else (strip_array_types (type), NULL_TREE);
}
/* Process a trait expression. */
@@ -5276,10 +5273,6 @@ finish_trait_expr (cp_trait_kind kind, tree type1,
return trait_expr;
}
- complete_type (type1);
- if (type2)
- complete_type (type2);
-
switch (kind)
{
case CPTK_HAS_NOTHROW_ASSIGN:
@@ -5298,20 +5291,15 @@ finish_trait_expr (cp_trait_kind kind, tree type1,
case CPTK_IS_STD_LAYOUT:
case CPTK_IS_TRIVIAL:
if (!check_trait_type (type1))
- {
- error ("incomplete type %qT not allowed", type1);
- return error_mark_node;
- }
+ 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;
- }
+ && !complete_type_or_else (type2, NULL_TREE))
+ /* We already issued an error. */
+ return error_mark_node;
break;
case CPTK_IS_CLASS:
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [C++ Patch] PR 50732
2011-10-15 21:21 ` Paolo Carlini
@ 2011-10-15 21:27 ` Jason Merrill
0 siblings, 0 replies; 10+ messages in thread
From: Jason Merrill @ 2011-10-15 21:27 UTC (permalink / raw)
To: Paolo Carlini; +Cc: gcc-patches
OK.
Jason
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2011-10-15 19:00 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-10-14 18:48 [C++ Patch] PR 50732 Paolo Carlini
2011-10-14 18:56 ` Paolo Carlini
2011-10-14 19:12 ` Paolo Carlini
2011-10-14 19:41 ` Jason Merrill
2011-10-14 23:03 ` Paolo Carlini
2011-10-14 23:26 ` Jason Merrill
2011-10-15 1:17 ` Paolo Carlini
2011-10-15 20:42 ` Jason Merrill
2011-10-15 21:21 ` Paolo Carlini
2011-10-15 21:27 ` Jason Merrill
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).