diff mbox

[C++,/,RFC] PR 50864

Message ID 4EA867B7.7050406@oracle.com
State New
Headers show

Commit Message

Paolo Carlini Oct. 26, 2011, 8:04 p.m. UTC
Hi,

one more / RFC, for the ICE on invalid part of these issues with '->'.

The below tries to catch the problem very early, in 
cp_parser_postfix_dot_deref_expression and apparently works fine, passes 
the testsuite, etc. Is it too early? Is the check tight enough?

Thanks,
Paolo.

//////////////////////

Comments

Jason Merrill Oct. 26, 2011, 8:25 p.m. UTC | #1
On 10/26/2011 04:04 PM, Paolo Carlini wrote:
> The below tries to catch the problem very early, in
> cp_parser_postfix_dot_deref_expression and apparently works fine, passes
> the testsuite, etc. Is it too early? Is the check tight enough?

At a glance, it looks too early; it's valid to have namespace-qualified 
names after ->.

namespace A
{
   struct B
   {
     int i;
   };
};

A::B* b;
int i = b->A::B::i;

Jason
Paolo Carlini Oct. 26, 2011, 8:30 p.m. UTC | #2
Hi,
> At a glance, it looks too early; it's valid to have 
> namespace-qualified names after ->.
>
> namespace A
> {
>   struct B
>   {
>     int i;
>   };
> };
>
> A::B* b;
> int i = b->A::B::i;
I was also trying to construct such kind of example myself... but my 
patch does not regress on the testcase you wrote down. I can tell you 
exactly why, if you like..

Paolo.
Paolo Carlini Oct. 26, 2011, 8:35 p.m. UTC | #3
On 10/26/2011 10:30 PM, Paolo Carlini wrote:
> Hi,
>> At a glance, it looks too early; it's valid to have 
>> namespace-qualified names after ->.
>>
>> namespace A
>> {
>>   struct B
>>   {
>>     int i;
>>   };
>> };
>>
>> A::B* b;
>> int i = b->A::B::i;
> I was also trying to construct such kind of example myself... but my 
> patch does not regress on the testcase you wrote down. I can tell you 
> exactly why, if you like..
We have that parser->scope is a RECORD_TYPE and postfix_expression is an 
INDIRECT_REF.

Paolo.
Paolo Carlini Oct. 26, 2011, 9:37 p.m. UTC | #4
On 10/26/2011 10:35 PM, Paolo Carlini wrote:
> On 10/26/2011 10:30 PM, Paolo Carlini wrote:
>> Hi,
>>> At a glance, it looks too early; it's valid to have 
>>> namespace-qualified names after ->.
>>>
>>> namespace A
>>> {
>>>   struct B
>>>   {
>>>     int i;
>>>   };
>>> };
>>>
>>> A::B* b;
>>> int i = b->A::B::i;
>> I was also trying to construct such kind of example myself... but my 
>> patch does not regress on the testcase you wrote down. I can tell you 
>> exactly why, if you like..
> We have that parser->scope is a RECORD_TYPE and postfix_expression is 
> an INDIRECT_REF.
In this case, for example (like PR50870):

namespace impl
{
   struct inner
   {
     template <class T> T create();
   };
}

template <class T, class U, __SIZE_TYPE__
       = sizeof(impl::inner::create<T>() -> impl::inner::create<U>())>
struct foo;

we are also Ok, code is accepted, because name is a BASELINK and the new 
check isn't even reached (postfix_expression would be an ARROW_EXPR, but 
parser->scope again a RECORD_TYPE. More generally, in all the legal 
tests I tried by hand (outside the testsuite), when we get there 
parser->scope is always a RECORD_TYPE)

But if you feel more comfortable about performing the check elsewhere, I 
can try that of course.

Paolo.
Jason Merrill Nov. 7, 2011, 9:45 p.m. UTC | #5
On 10/26/2011 04:35 PM, Paolo Carlini wrote:
> We have that parser->scope is a RECORD_TYPE and postfix_expression is an
> INDIRECT_REF.

Ah, OK.  I guess we swallow up the namespace while parsing the full 
nested-name-specifier and it isn't a problem.  So I think handling this 
here should be OK.  But why check for ARROW_EXPR?  Can't you construct a 
similar testcase using .?

I'll deal with 50870.

Jason
diff mbox

Patch

Index: testsuite/g++.dg/template/crash109.C
===================================================================
--- testsuite/g++.dg/template/crash109.C	(revision 0)
+++ testsuite/g++.dg/template/crash109.C	(revision 0)
@@ -0,0 +1,10 @@ 
+// PR c++/50864
+
+namespace impl
+{
+  template <class T> T create();
+}
+
+template <class T, class U, __SIZE_TYPE__
+	  = sizeof(impl::create<T>() -> impl::create<U>())>  // { dg-error "not a class member" } 
+struct foo;
Index: cp/parser.c
===================================================================
--- cp/parser.c	(revision 180532)
+++ cp/parser.c	(working copy)
@@ -5673,6 +5673,15 @@  cp_parser_postfix_dot_deref_expression (cp_parser
 	{
 	  if (name != error_mark_node && !BASELINK_P (name) && parser->scope)
 	    {
+	      if (TREE_CODE (parser->scope) == NAMESPACE_DECL
+		  && TREE_CODE (postfix_expression) == ARROW_EXPR)
+		{
+		  error_at (token->location, "%<%D::%D%> is not a class member",
+			    parser->scope, name);
+		  parser->context->object_type = NULL_TREE;
+		  return error_mark_node;
+		}
+
 	      name = build_qualified_name (/*type=*/NULL_TREE,
 					   parser->scope,
 					   name,