Re: [C++ Patch] PR 58980

2014-01-23 Thread Jason Merrill

On 01/22/2014 04:29 PM, Paolo Carlini wrote:

On 01/22/2014 10:10 PM, Jason Merrill wrote:

Yep, that's along the lines I was thinking of. But again, prev_scope
is irrelevant here, so the new code shouldn't mention it at all.

Well, in practice I have to mention it in the error_at itself.


Why?  prev_scope is the context where the name is written, i.e. 
current_class_type.  Why should the diagnostic treat it as an explicit 
qualifier?


Jason



Re: [C++ Patch] PR 58980

2014-01-23 Thread Paolo Carlini

Hi,

On 01/23/2014 03:05 PM, Jason Merrill wrote:

On 01/22/2014 04:29 PM, Paolo Carlini wrote:

On 01/22/2014 10:10 PM, Jason Merrill wrote:

Yep, that's along the lines I was thinking of. But again, prev_scope
is irrelevant here, so the new code shouldn't mention it at all.

Well, in practice I have to mention it in the error_at itself.
Why?  prev_scope is the context where the name is written, i.e. 
current_class_type.  Why should the diagnostic treat it as an explicit 
qualifier?
Jason, no problem, you choose. I only wanted to use the same compact 
form 'A::B' used in the non-template case. Which form do you prefer?


Paolo.


Re: [C++ Patch] PR 58980

2014-01-23 Thread Paolo Carlini

On 01/23/2014 04:01 PM, Paolo Carlini wrote:

Hi,

On 01/23/2014 03:05 PM, Jason Merrill wrote:

On 01/22/2014 04:29 PM, Paolo Carlini wrote:

On 01/22/2014 10:10 PM, Jason Merrill wrote:

Yep, that's along the lines I was thinking of. But again, prev_scope
is irrelevant here, so the new code shouldn't mention it at all.

Well, in practice I have to mention it in the error_at itself.
Why?  prev_scope is the context where the name is written, i.e. 
current_class_type.  Why should the diagnostic treat it as an 
explicit qualifier?
Jason, no problem, you choose. I only wanted to use the same compact 
form 'A::B' used in the non-template case. Which form do you prefer?

To be clear if we use %qT with nested_name_specifier we get:

58980.C:5:8: error: ‘typename A template-parameter-1-1 ::B’ has not 
been declared


which frankly seems suboptimal to me, both vs the non-template case and 
the use of typename.


Thus, as far as I can see, either what I posted, which is consistent 
with the '... has not been declared' message of the non-template case (I 
understand that we want to focus on the 'has not been declared' issue) 
or just '%%E%' or even just '%E' and nested_name_specifier.


Paolo.


Re: [C++ Patch] PR 58980

2014-01-23 Thread Jason Merrill

On 01/23/2014 10:30 AM, Paolo Carlini wrote:

To be clear if we use %qT with nested_name_specifier we get:

58980.C:5:8: error: ‘typename A template-parameter-1-1 ::B’ has not
been declared

which frankly seems suboptimal to me, both vs the non-template case and
the use of typename.


If you want to break apart the typename and do %T::%E with TYPE_CONTEXT 
(nested_name_specifier) on the left side, that's fine too.


Jason



Re: [C++ Patch] PR 58980

2014-01-23 Thread Paolo Carlini

On 01/23/2014 04:50 PM, Jason Merrill wrote:

On 01/23/2014 10:30 AM, Paolo Carlini wrote:

To be clear if we use %qT with nested_name_specifier we get:

58980.C:5:8: error: ‘typename A template-parameter-1-1 ::B’ has not
been declared

which frankly seems suboptimal to me, both vs the non-template case and
the use of typename.
If you want to break apart the typename and do %T::%E with 
TYPE_CONTEXT (nested_name_specifier) on the left side, that's fine too.
Ah, Ok, I was missing that we really want to use TYPE_CONTEXT. To 
confirm, then we get:


58980.C:5:8: error: ‘A template-parameter-1-1 ::B’ has not been declared

I'm finishing testing the below.

Thanks,
Paolo.

///
Index: cp/parser.c
===
--- cp/parser.c (revision 206958)
+++ cp/parser.c (working copy)
@@ -15469,9 +15469,18 @@ cp_parser_enum_specifier (cp_parser* parser)
error_at (type_start_token-location, cannot add an enumerator 
  list to a template instantiation);
 
+ if (TREE_CODE (nested_name_specifier) == TYPENAME_TYPE)
+   {
+ error_at (type_start_token-location,
+   %%T::%E% has not been declared,
+   TYPE_CONTEXT (nested_name_specifier),
+   nested_name_specifier);
+ type = error_mark_node;
+   }
  /* If that scope does not contain the scope in which the
 class was originally declared, the program is invalid.  */
- if (prev_scope  !is_ancestor (prev_scope, nested_name_specifier))
+ else if (prev_scope  !is_ancestor (prev_scope,
+  nested_name_specifier))
{
  if (at_namespace_scope_p ())
error_at (type_start_token-location,
@@ -15480,7 +15489,8 @@ cp_parser_enum_specifier (cp_parser* parser)
  type, prev_scope, nested_name_specifier);
  else
error_at (type_start_token-location,
- declaration of %qD in %qD which does not enclose 
%qD,
+ declaration of %qD in %qD which does not 
+ enclose %qD,
  type, prev_scope, nested_name_specifier);
  type = error_mark_node;
}
Index: testsuite/g++.dg/parse/enum11.C
===
--- testsuite/g++.dg/parse/enum11.C (revision 0)
+++ testsuite/g++.dg/parse/enum11.C (working copy)
@@ -0,0 +1,6 @@
+// PR c++/58980
+
+templatetypename struct A
+{ 
+  enum A::B::C {};   // { dg-error has not been declared }
+};


Re: [C++ Patch] PR 58980

2014-01-23 Thread Jason Merrill

OK, thanks.

Jason


Re: [C++ Patch] PR 58980

2014-01-22 Thread Paolo Carlini

On 01/21/2014 04:16 PM, Paolo Carlini wrote:

+  if (TREE_CODE (child) == TYPENAME_TYPE)
+return false;
+

Maybe we want instead to do

if (WILDCARD_TYPE_P (child))
return false;

(which also passes testing, of course).

Thanks,
Paolo.



Re: [C++ Patch] PR 58980

2014-01-22 Thread Jason Merrill

On 01/21/2014 09:55 AM, Jason Merrill wrote:

I think I would prefer to change the child assert to be
MAYBE_CLASS_TYPE_P rather than CLASS_TYPE_P.


On second thought, no, I think we do want to specifically handle 
TYPENAME_TYPE.  But I think we want a different error message; getting a 
TYPENAME_TYPE here means that B has not been declared.  The current 
scope is irrelevant.  So we want to check for TYPENAME_TYPE before we 
think about checking prev_scope.


Jason



Re: [C++ Patch] PR 58980

2014-01-22 Thread Paolo Carlini

Hi,

On 01/22/2014 06:13 PM, Jason Merrill wrote:

On 01/21/2014 09:55 AM, Jason Merrill wrote:

I think I would prefer to change the child assert to be
MAYBE_CLASS_TYPE_P rather than CLASS_TYPE_P.
On second thought, no, I think we do want to specifically handle 
TYPENAME_TYPE.  But I think we want a different error message; getting 
a TYPENAME_TYPE here means that B has not been declared. The current 
scope is irrelevant.  So we want to check for TYPENAME_TYPE before we 
think about checking prev_scope.
Ok. In fact I entertained myself this kind of reasoning, a couple of 
days ago...


I tested the below, which uses by hand %Es instead of %qT for more 
concise error messages (consistent with the non-template case).


Thanks,
Paolo.


/cp
2014-01-22  Paolo Carlini  paolo.carl...@oracle.com

PR c++/58980
* parser.c (cp_parser_enum_specifier): Handle TYPENAME_TYPE as
nested_name_specifier.

/testsuite
2014-01-22  Paolo Carlini  paolo.carl...@oracle.com

PR c++/58980
* g++.dg/parse/enum11.C: New.
Index: cp/parser.c
===
--- cp/parser.c (revision 206933)
+++ cp/parser.c (working copy)
@@ -15469,9 +15469,17 @@ cp_parser_enum_specifier (cp_parser* parser)
error_at (type_start_token-location, cannot add an enumerator 
  list to a template instantiation);
 
+ if (prev_scope  TREE_CODE (nested_name_specifier) == TYPENAME_TYPE)
+   {
+ error_at (type_start_token-location,
+   %%E::%E% has not been declared,
+   prev_scope, nested_name_specifier);
+ type = error_mark_node;
+   }
  /* If that scope does not contain the scope in which the
 class was originally declared, the program is invalid.  */
- if (prev_scope  !is_ancestor (prev_scope, nested_name_specifier))
+ else if (prev_scope  !is_ancestor (prev_scope,
+  nested_name_specifier))
{
  if (at_namespace_scope_p ())
error_at (type_start_token-location,
@@ -15480,7 +15488,8 @@ cp_parser_enum_specifier (cp_parser* parser)
  type, prev_scope, nested_name_specifier);
  else
error_at (type_start_token-location,
- declaration of %qD in %qD which does not enclose 
%qD,
+ declaration of %qD in %qD which does not 
+ enclose %qD,
  type, prev_scope, nested_name_specifier);
  type = error_mark_node;
}
Index: testsuite/g++.dg/parse/enum11.C
===
--- testsuite/g++.dg/parse/enum11.C (revision 0)
+++ testsuite/g++.dg/parse/enum11.C (working copy)
@@ -0,0 +1,6 @@
+// PR c++/58980
+
+templatetypename struct A
+{ 
+  enum A::B::C {};   // { dg-error has not been declared }
+};


Re: [C++ Patch] PR 58980

2014-01-22 Thread Jason Merrill
Yep, that's along the lines I was thinking of. But again, prev_scope is 
irrelevant here, so the new code shouldn't mention it at all.

 Original Message 
 From: Paolo Carlini paolo.carl...@oracle.com
 Sent: Wed, Jan 22, 2014 03:34 PM
 To: Jason Merrill ja...@redhat.com; gcc-patches@gcc.gnu.org
 CC: 
 Subject: Re: [C++ Patch] PR 58980

Hi,

On 01/22/2014 06:13 PM, Jason Merrill wrote:
 On 01/21/2014 09:55 AM, Jason Merrill wrote:
 I think I would prefer to change the child assert to be
 MAYBE_CLASS_TYPE_P rather than CLASS_TYPE_P.
 On second thought, no, I think we do want to specifically handle 
 TYPENAME_TYPE.  But I think we want a different error message; getting 
 a TYPENAME_TYPE here means that B has not been declared. The current 
 scope is irrelevant.  So we want to check for TYPENAME_TYPE before we 
 think about checking prev_scope.
Ok. In fact I entertained myself this kind of reasoning, a couple of 
days ago...

I tested the below, which uses by hand %Es instead of %qT for more 
concise error messages (consistent with the non-template case).

Thanks,
Paolo.




Re: [C++ Patch] PR 58980

2014-01-22 Thread Paolo Carlini

On 01/22/2014 10:10 PM, Jason Merrill wrote:

Yep, that's along the lines I was thinking of. But again, prev_scope is 
irrelevant here, so the new code shouldn't mention it at all.
Well, in practice I have to mention it in the error_at itself. Otherwise 
I'm finishing testing the below.


Paolo.

//
Index: cp/parser.c
===
--- cp/parser.c (revision 206933)
+++ cp/parser.c (working copy)
@@ -15469,9 +15469,17 @@ cp_parser_enum_specifier (cp_parser* parser)
error_at (type_start_token-location, cannot add an enumerator 
  list to a template instantiation);
 
+ if (TREE_CODE (nested_name_specifier) == TYPENAME_TYPE)
+   {
+ error_at (type_start_token-location,
+   %%E::%E% has not been declared,
+   prev_scope, nested_name_specifier);
+ type = error_mark_node;
+   }
  /* If that scope does not contain the scope in which the
 class was originally declared, the program is invalid.  */
- if (prev_scope  !is_ancestor (prev_scope, nested_name_specifier))
+ else if (prev_scope  !is_ancestor (prev_scope,
+  nested_name_specifier))
{
  if (at_namespace_scope_p ())
error_at (type_start_token-location,
@@ -15480,7 +15488,8 @@ cp_parser_enum_specifier (cp_parser* parser)
  type, prev_scope, nested_name_specifier);
  else
error_at (type_start_token-location,
- declaration of %qD in %qD which does not enclose 
%qD,
+ declaration of %qD in %qD which does not 
+ enclose %qD,
  type, prev_scope, nested_name_specifier);
  type = error_mark_node;
}
Index: testsuite/g++.dg/parse/enum11.C
===
--- testsuite/g++.dg/parse/enum11.C (revision 0)
+++ testsuite/g++.dg/parse/enum11.C (working copy)
@@ -0,0 +1,6 @@
+// PR c++/58980
+
+templatetypename struct A
+{ 
+  enum A::B::C {};   // { dg-error has not been declared }
+};


[C++ Patch] PR 58980

2014-01-21 Thread Paolo Carlini

Hi,

in this relatively serious ICE on invalid regression (we don't emit any 
sensible diagnostic before ICE-ing) the problem is that is_ancestor 
simply asserts that the second argument can be only a NAMESPACE_DECL or 
a CLASS_TYPE_P, whereas in the erroneous input at issue it's a 
TYPENAME_TYPE. Thus the idea of not calling is_ancestor at all in this 
case + adjusting the two error_at calls to use %qT instead of %qD 
(dump_type can handle a NAMESPACE_DECL whereas dump_type can't handle a 
TYPENAME_TYPE).


Tested x86_64-linux.

Thanks,
Paolo.

//
/cp
2014-01-21  Paolo Carlini  paolo.carl...@oracle.com

PR c++/58980
* parser.c (cp_parser_enum_specifier): Handle TYPENAME_TYPE as
nested_name_specifier.

/testsuite
2014-01-21  Paolo Carlini  paolo.carl...@oracle.com

PR c++/58980
* g++.dg/parse/enum11.C: New.
Index: cp/parser.c
===
--- cp/parser.c (revision 206875)
+++ cp/parser.c (working copy)
@@ -15471,16 +15471,19 @@ cp_parser_enum_specifier (cp_parser* parser)
 
  /* If that scope does not contain the scope in which the
 class was originally declared, the program is invalid.  */
- if (prev_scope  !is_ancestor (prev_scope, nested_name_specifier))
+ if (prev_scope
+  (TREE_CODE (nested_name_specifier) == TYPENAME_TYPE
+ || !is_ancestor (prev_scope, nested_name_specifier)))
{
  if (at_namespace_scope_p ())
error_at (type_start_token-location,
  declaration of %qD in namespace %qD which does not 
- enclose %qD,
+ enclose %qT,
  type, prev_scope, nested_name_specifier);
  else
error_at (type_start_token-location,
- declaration of %qD in %qD which does not enclose 
%qD,
+ declaration of %qD in %qD which does not 
+ enclose %qT,
  type, prev_scope, nested_name_specifier);
  type = error_mark_node;
}
Index: testsuite/g++.dg/parse/enum11.C
===
--- testsuite/g++.dg/parse/enum11.C (revision 0)
+++ testsuite/g++.dg/parse/enum11.C (working copy)
@@ -0,0 +1,6 @@
+// PR c++/58980
+
+templatetypename struct A
+{ 
+  enum A::B::C {};   // { dg-error does not enclose }
+};


Re: [C++ Patch] PR 58980

2014-01-21 Thread Jason Merrill
I think I would prefer to change the child assert to be 
MAYBE_CLASS_TYPE_P rather than CLASS_TYPE_P.


Jason


Re: [C++ Patch] PR 58980

2014-01-21 Thread Paolo Carlini

Hi,

On 01/21/2014 03:55 PM, Jason Merrill wrote:
I think I would prefer to change the child assert to be 
MAYBE_CLASS_TYPE_P rather than CLASS_TYPE_P.
.. Ok, but then it seems to me that we have to explicitly handle the 
TYPENAME_TYPE case, otherwise we end up simply accepting the testcase 
(even if the template is instantiated!). Something like the below...


Paolo.

//
Index: cp/name-lookup.c
===
--- cp/name-lookup.c(revision 206880)
+++ cp/name-lookup.c(working copy)
@@ -2723,12 +2723,15 @@ is_ancestor (tree root, tree child)
   || TREE_CODE (root) == FUNCTION_DECL
   || CLASS_TYPE_P (root)));
   gcc_assert ((TREE_CODE (child) == NAMESPACE_DECL
-  || CLASS_TYPE_P (child)));
+  || MAYBE_CLASS_TYPE_P (child)));
 
   /* The global namespace encloses everything.  */
   if (root == global_namespace)
 return true;
 
+  if (TREE_CODE (child) == TYPENAME_TYPE)
+return false;
+
   while (true)
 {
   /* If we've run out of scopes, stop.  */
Index: cp/parser.c
===
--- cp/parser.c (revision 206880)
+++ cp/parser.c (working copy)
@@ -15476,11 +15476,12 @@ cp_parser_enum_specifier (cp_parser* parser)
  if (at_namespace_scope_p ())
error_at (type_start_token-location,
  declaration of %qD in namespace %qD which does not 
- enclose %qD,
+ enclose %qT,
  type, prev_scope, nested_name_specifier);
  else
error_at (type_start_token-location,
- declaration of %qD in %qD which does not enclose 
%qD,
+ declaration of %qD in %qD which does not 
+ enclose %qT,
  type, prev_scope, nested_name_specifier);
  type = error_mark_node;
}
Index: testsuite/g++.dg/parse/enum11.C
===
--- testsuite/g++.dg/parse/enum11.C (revision 0)
+++ testsuite/g++.dg/parse/enum11.C (working copy)
@@ -0,0 +1,6 @@
+// PR c++/58980
+
+templatetypename struct A
+{ 
+  enum A::B::C {};  // { dg-error does not enclose }
+};