public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [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).