Re: [PR c++/84789] do not resolve typename into template-independent

2018-03-23 Thread Jason Merrill
OK.

On Fri, Mar 23, 2018 at 3:17 PM, Alexandre Oliva  wrote:
> On Mar 23, 2018, Jakub Jelinek  wrote:
>
>> On Wed, Mar 21, 2018 at 11:52:33PM -0400, Jason Merrill wrote:
>>> OK, thanks.
>
>> Note the testcase FAILs with -fconcepts when I do make check-c++-all,
>> FAIL: g++.dg/template/pr84789.C  -std=c++17 -fconcepts  (test for errors, 
>> line 12)
>> FAIL: g++.dg/template/pr84789.C  -std=c++17 -fconcepts (test for excess 
>> errors)
>> Excess errors:
>> /usr/src/gcc/gcc/testsuite/g++.dg/template/pr84789.C:12:15: error:
>> 'A::I' {aka 'int'} is not a class type
>> /usr/src/gcc/gcc/testsuite/g++.dg/template/pr84789.C:12:15: error: 'I'
>> in 'A::I' {aka 'int'} does not name a type
>
> Is this ok to install?
>
> [PR c++/84789] adjust testcase for -fconcepts
>
> When compiling with -fconcepts,
> cp_parser_template_declaration_after_export calls
> cp_parser_template_introduction and that preparses qualified-ids not
> preceded by typename in such a way that, when we get to
> cp_parser_parse_and_diagnose_invalid_type_name and then
> cp_parser_diagnose_invalid_type_name, the nested name specifier no
> longer carries the previous template-dependent context, so we don't
> stand a chance to suggest the use of 'typename' any more.  Thus,
> tolerate in the testcase the poorer error messages we get.
>
> for  gcc/testsuite/ChangeLog
>
> PR c++/84789
> * g++.dg/template/pr84789.C: Adjust for testing with
> -fconcepts too.
> ---
>  gcc/testsuite/g++.dg/template/pr84789.C |2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/gcc/testsuite/g++.dg/template/pr84789.C 
> b/gcc/testsuite/g++.dg/template/pr84789.C
> index bc1567f3fe77..63b9832fecf8 100644
> --- a/gcc/testsuite/g++.dg/template/pr84789.C
> +++ b/gcc/testsuite/g++.dg/template/pr84789.C
> @@ -9,5 +9,5 @@ template struct B : A {};
>
>  template struct C : B
>  {
> -  B::A::I::I i; // { dg-error "typename" }
> +  B::A::I::I i; // { dg-error "not a class type|does not name a 
> type|typename" }
>  };
>
>
> --
> Alexandre Oliva, freedom fighterhttp://FSFLA.org/~lxoliva/
> You must be the change you wish to see in the world. -- Gandhi
> Be Free! -- http://FSFLA.org/   FSF Latin America board member
> Free Software Evangelist|Red Hat Brasil GNU Toolchain Engineer


Re: [PR c++/84789] do not resolve typename into template-independent

2018-03-23 Thread Alexandre Oliva
On Mar 23, 2018, Jakub Jelinek  wrote:

> On Wed, Mar 21, 2018 at 11:52:33PM -0400, Jason Merrill wrote:
>> OK, thanks.

> Note the testcase FAILs with -fconcepts when I do make check-c++-all,
> FAIL: g++.dg/template/pr84789.C  -std=c++17 -fconcepts  (test for errors, 
> line 12)
> FAIL: g++.dg/template/pr84789.C  -std=c++17 -fconcepts (test for excess 
> errors)
> Excess errors:
> /usr/src/gcc/gcc/testsuite/g++.dg/template/pr84789.C:12:15: error:
> 'A::I' {aka 'int'} is not a class type
> /usr/src/gcc/gcc/testsuite/g++.dg/template/pr84789.C:12:15: error: 'I'
> in 'A::I' {aka 'int'} does not name a type

Is this ok to install?

[PR c++/84789] adjust testcase for -fconcepts

When compiling with -fconcepts,
cp_parser_template_declaration_after_export calls
cp_parser_template_introduction and that preparses qualified-ids not
preceded by typename in such a way that, when we get to
cp_parser_parse_and_diagnose_invalid_type_name and then
cp_parser_diagnose_invalid_type_name, the nested name specifier no
longer carries the previous template-dependent context, so we don't
stand a chance to suggest the use of 'typename' any more.  Thus,
tolerate in the testcase the poorer error messages we get.

for  gcc/testsuite/ChangeLog

PR c++/84789
* g++.dg/template/pr84789.C: Adjust for testing with
-fconcepts too.
---
 gcc/testsuite/g++.dg/template/pr84789.C |2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/testsuite/g++.dg/template/pr84789.C 
b/gcc/testsuite/g++.dg/template/pr84789.C
index bc1567f3fe77..63b9832fecf8 100644
--- a/gcc/testsuite/g++.dg/template/pr84789.C
+++ b/gcc/testsuite/g++.dg/template/pr84789.C
@@ -9,5 +9,5 @@ template struct B : A {};
 
 template struct C : B
 {
-  B::A::I::I i; // { dg-error "typename" }
+  B::A::I::I i; // { dg-error "not a class type|does not name a 
type|typename" }
 };


-- 
Alexandre Oliva, freedom fighterhttp://FSFLA.org/~lxoliva/
You must be the change you wish to see in the world. -- Gandhi
Be Free! -- http://FSFLA.org/   FSF Latin America board member
Free Software Evangelist|Red Hat Brasil GNU Toolchain Engineer


Re: [PR c++/84789] do not resolve typename into template-independent

2018-03-23 Thread Jakub Jelinek
On Fri, Mar 23, 2018 at 01:45:01PM -0300, Alexandre Oliva wrote:
> On Mar 23, 2018, Jakub Jelinek  wrote:
> 
> > On Wed, Mar 21, 2018 at 11:52:33PM -0400, Jason Merrill wrote:
> >> OK, thanks.
> 
> > Note the testcase FAILs with -fconcepts when I do make check-c++-all,
> 
> Hmm, I don't get that with check or check-g++.  Should we expand the
> default std_list in g++-dg.exp, or should I manually test these
> additional variants?

I think we should add the -std=c++17 mode to the list of standards cycled by
default, now that it is a released standard.  -fconcepts is experimental
and so is -std=c++2a, so perhaps those can stay out of the default and be
just checked occassionally.

The full set of check-c++-all FAILs I'm getting that don't show up with
check-g++ is:
FAIL: g++.dg/spellcheck-macro-ordering-2.C  -std=c++17 -fconcepts  (test for 
errors, line 10)
FAIL: g++.dg/spellcheck-macro-ordering-2.C  -std=c++17 -fconcepts (test for 
excess errors)
FAIL: g++.dg/spellcheck-macro-ordering.C  -std=c++17 -fconcepts  (test for 
errors, line 6)
FAIL: g++.dg/spellcheck-macro-ordering.C  -std=c++17 -fconcepts  (test for 
warnings, line 6)
FAIL: g++.dg/spellcheck-macro-ordering.C  -std=c++17 -fconcepts  (test for 
warnings, line 15)
FAIL: g++.dg/spellcheck-macro-ordering.C  -std=c++17 -fconcepts (test for 
excess errors)
FAIL: g++.dg/template/pr84789.C  -std=c++17 -fconcepts  (test for errors, line 
12)
FAIL: g++.dg/template/pr84789.C  -std=c++17 -fconcepts (test for excess errors)
FAIL: g++.dg/warn/string1.C  -std=gnu++17 (test for excess errors)
FAIL: g++.dg/warn/string1.C  -std=gnu++2a (test for excess errors)
FAIL: g++.dg/warn/string1.C  -std=gnu++17 -fconcepts (test for excess errors)

Jakub


Re: [PR c++/84789] do not resolve typename into template-independent

2018-03-23 Thread Alexandre Oliva
On Mar 23, 2018, Jakub Jelinek  wrote:

> On Wed, Mar 21, 2018 at 11:52:33PM -0400, Jason Merrill wrote:
>> OK, thanks.

> Note the testcase FAILs with -fconcepts when I do make check-c++-all,

Hmm, I don't get that with check or check-g++.  Should we expand the
default std_list in g++-dg.exp, or should I manually test these
additional variants?

Anyway, thanks for the report, I'll try to figure out why this fails
with concepts.

-- 
Alexandre Oliva, freedom fighterhttp://FSFLA.org/~lxoliva/
You must be the change you wish to see in the world. -- Gandhi
Be Free! -- http://FSFLA.org/   FSF Latin America board member
Free Software Evangelist|Red Hat Brasil GNU Toolchain Engineer


Re: [PR c++/84789] do not resolve typename into template-independent

2018-03-23 Thread Jakub Jelinek
On Wed, Mar 21, 2018 at 11:52:33PM -0400, Jason Merrill wrote:
> OK, thanks.

Note the testcase FAILs with -fconcepts when I do make check-c++-all,
FAIL: g++.dg/template/pr84789.C  -std=c++17 -fconcepts  (test for errors, line 
12)
FAIL: g++.dg/template/pr84789.C  -std=c++17 -fconcepts (test for excess errors)
Excess errors:
/usr/src/gcc/gcc/testsuite/g++.dg/template/pr84789.C:12:15: error: 'A::I' {aka 
'int'} is not a class type
/usr/src/gcc/gcc/testsuite/g++.dg/template/pr84789.C:12:15: error: 'A::I' {aka 
'int'} is not a class type
/usr/src/gcc/gcc/testsuite/g++.dg/template/pr84789.C:12:15: error: 'A::I' {aka 
'int'} is not a class type
/usr/src/gcc/gcc/testsuite/g++.dg/template/pr84789.C:12:15: error: 'A::I' {aka 
'int'} is not a class type
/usr/src/gcc/gcc/testsuite/g++.dg/template/pr84789.C:12:15: error: 'A::I' {aka 
'int'} is not a class type
/usr/src/gcc/gcc/testsuite/g++.dg/template/pr84789.C:12:15: error: 'A::I' {aka 
'int'} is not a class type
/usr/src/gcc/gcc/testsuite/g++.dg/template/pr84789.C:12:15: error: 'I' in 
'A::I' {aka 'int'} does not name a type
In all other standard modes it is fine.

Jakub


Re: [PR c++/84789] do not resolve typename into template-independent

2018-03-21 Thread Jason Merrill
OK, thanks.

On Wed, Mar 21, 2018 at 11:48 AM, Jason Merrill  wrote:
> On Tue, Mar 20, 2018 at 11:27 PM, Alexandre Oliva  wrote:
>> On Mar 20, 2018, Jason Merrill  wrote:
>>
>>> On Tue, Mar 20, 2018 at 6:07 PM, Alexandre Oliva  wrote:
 On Mar 20, 2018, Jason Merrill  wrote:
> that doesn't mean it's wrong to peek.
>>
 Huh?  We're referencing members of an unrelated template that AFAIK
 needs not even be defined at that point, and even if it is, it could
 still be specialized afterwards.  How can it possibly be right to
 short-circuit such nested names?
>>
 template struct B : A {}; // would /*: A {}*/ make any diff?
 template struct C : B // would /* : B*/ make any diff?
 {
   B::A::I::I i; // { dg-error "typename" }
 };
>>
>>> No, we look inside when we're trying to parse the qualified-id as the
>>> name of a declaration
>>
>> Yeah, but that's not the case at hand.  I guess we're miscommunicating.
>> I understood you were saying it was ok to peek in this case.  Would you
>> please state, for clarity, what your stance is on peeking in this case,
>> specifically, in the B::A::I::I within the definition of C above?
>
> It's OK when we're tentatively trying to parse it as a declarator, not
> when we're trying to parse it as a type-specifier.
>
> We seem to be talking past each other on this point: We already don't
> peek when parsing a type-specifier, we only call resolve_typename_type
> with false for only_current_p in the context of trying to parse a
> declarator.  The parser tries both interpretations for B::A::I::I.
> The type interpretation is ill-formed because of missing 'typename',
> so it tries again as a declarator, and therefore tries to resolve the
> TYPENAME_TYPE that it built while trying for a type, and trips the
> assert.
>
>>> in a declarator-id we can look into uninstantiated classes, otherwise
>>> there would be no way to define members of class templates.
>>
>>>   void X::N::f() { } // looks inside X
>>
>> Of course, but then, we wouldn't get to a template-independent member.
>> A member of a template-dependent name is still template-dependent.  It's
>> only when a qualified name maps to an external name that it might become
>> template-independent, and when this happens, I believe the qualified-id
>> is not one that can be used to define a member. Specifically:
>>
>> struct K { struct L { static double j; }; };
>> template  struct M { struct N { static int i; }; };
>> template  struct O { typedef M P; typedef K Q; };
>> template  int O::P::N::i = 42;
>> template  double O::Q::L::j = 42.0;
>>
>> if we remap O::P to M and O::Q to K, how will we realize the
>> given type-ids are not appropriate?  Where will the template parmlist
>> belong when the qualified-id is taken as equivalent to K::L::j?
>
> Agreed, these look bizarre because the template parm is used in O,
> which is not an enclosing class of i or j.  And j is clearly
> ill-formed because it declares a non-template as a template.
>
> But it's not clear to me that i is ill-formed; we allow
>
> struct A { static int i; };
> struct B { typedef ::A A; };
> int B::A::i = 0;
>
> and the i example seems analogous.  I wouldn't argue against making it
> ill-formed, but I don't see a rule that would make it so in the
> current draft standard.  And even resolving the scope to be
> non-dependent doesn't necessarily mean the declaration will be, if the
> template parameter list ends up being for a member template:
>
> struct K { struct L { template  static void f(T); }; };
> template  struct O { typedef K Q; };
> template  void O::Q::L::f(T) { }
>
> I disagree; it seems to me that the assert should allow the case where
> the scope was originally dependent, but got resolved earlier in the
> function.

 Doesn't the function always take dependent scopes?  I for some reason
 thought that was the case.
>>
>>> Yes, as the comment says, a TYPENAME_TYPE should always have a
>>> dependent scope.  In this case, the dependent scope was "typename
>>> B::A", but just above we resolved it to just A, making it no longer
>>> dependent.
>>
>> Then you got me thoroughly confused: what did you mean by 'the assert
>> should allow' a case that's a given?
>
> asserts are often used to verify that things we think of as givens are
> actually true.  :)
>
> I suppose we could remove the assert, but I'd probably move it up
> above where we start messing with 'scope'.
>
> Jason


Re: [PR c++/84789] do not resolve typename into template-independent

2018-03-21 Thread Alexandre Oliva
On Mar 21, 2018, Jason Merrill  wrote:

> On Tue, Mar 20, 2018 at 11:27 PM, Alexandre Oliva  wrote:

>> I understood you were saying it was ok to peek in this case.  Would you
>> please state, for clarity, what your stance is on peeking in this case,
>> specifically, in the B::A::I::I within the definition of C above?

> It's OK when we're tentatively trying to parse it as a declarator, not
> when we're trying to parse it as a type-specifier.

Thanks for the clarification; it had seemed to me that you were
rejecting my understanding that we shouldn't look up within the
unrelated template type when parsing the type id.  Now I understand you
were only rejecting the notion that we were parsing it as a type id.
Once I understood that, and realized why you were speaking of
declarators although the testcase at hand had a template-dependent type
id that was obviously (to me) not a declarator, it all made sense ;-)
Sorry for being so dense.


> I wouldn't argue against making it ill-formed, but I don't see a rule
> that would make it so in the current draft standard.

I have just spent some time looking for such a rule and failed to find
it too.  So I put in all of the bizarre declarators from this
conversation into new testcases, but expecting them to be accepted.

> I disagree; it seems to me that the assert should allow the case where
> the scope was originally dependent, but got resolved earlier in the
> function.

 Doesn't the function always take dependent scopes?  I for some reason
 thought that was the case.

>>> Yes, as the comment says, a TYPENAME_TYPE should always have a
>>> dependent scope.  In this case, the dependent scope was "typename
>>> B::A", but just above we resolved it to just A, making it no longer
>>> dependent.

>> Then you got me thoroughly confused: what did you mean by 'the assert
>> should allow' a case that's a given?

> asserts are often used to verify that things we think of as givens are
> actually true.  :)

Yeah, but the wording 'allow' rather than 'require'/'verify' set me off.
We used to require the opposite of X, so allowing X amounted to assert
(!X || X), which didn't sound like something you'd mean.

> I suppose we could remove the assert, but I'd probably move it up
> above where we start messing with 'scope'.

Now that makes sense to me, and it works, but I was not happy with the
errors we got, so I went ahead and arranged for the type name to be
reparsed as a non-declarator for the diagnostic, so that we get a better
diagnostic.

Regstrapping, after a successful check-g++ of a non-bootstrapped
x86_64-linux-gnu build.  Ok to install if the regstrap passes?


[PR c++/84789] do not fail to resolve typename into template-independent

Although resolve_typename_type always takes a template-dependent
type-id, and it usually resolves it to another template-dependent
type-id, it is not correct to require the latter: in declarators,
template-dependent scopes may turn out to name template-independent
types, as in the pr84789-2.C and pr84789-3.C testcases.

The ill-formed testcase pr84789.C trips the same too-strict assert,
and also gets fixed by removing the assertion on the simplified scope.
However, whereas when the dependent type cannot be resolved, we get an
error that suggests 'typename' is missing:

pr84789.C:12:3: error: need ‘typename’ before ‘typename B::A::I::I’
because ‘typename B::A::I’ is a dependent scope
   B::A::I::I i;
   ^~~~

when it can, we got errors that did not point at that possibility,
which may be confusing:

pr84789.C:9:15: error: ‘A::I’ {aka ‘int’} is not a class type
   B::A::I::I i; // { dg-error "typename" }
   ^
pr84789.C:9:15: error: ‘I’ in ‘A::I’ {aka ‘int’} does not name a type

Changing the parser diagnostic code that reports an invalid type name
so that it does not attempt to reparse the name as a declarator gets
us the superior diagnostic of a missing 'typename' keyword.


for  gcc/cp/ChangeLog

PR c++/84789
* pt.c (resolve_typename_type): Drop assert that stopped
simplification to template-independent types.  Add assert to
verify the initial scope is template dependent.
* parser.c (cp_parser_parse_and_diagnose_invalid_type_name):
Reparse the id expression as a type-name, not a declarator.

for  gcc/testsuite/ChangeLog

PR c++/84789
* g++.dg/template/pr84789.C: New.
* g++.dg/template/pr84789-2.C: New.
* g++.dg/template/pr84789-3.C: New.
* g++.dg/parse/dtor11.C: Accept alternate error message.
---
 gcc/cp/parser.c   |2 +-
 gcc/cp/pt.c   |5 +++--
 gcc/testsuite/g++.dg/parse/dtor11.C   |2 +-
 gcc/testsuite/g++.dg/template/pr84789-2.C |   26 
 gcc/testsuite/g++.dg/template/pr84789-3.C |   31 +
 gcc/testsuite/g++.dg/template/pr84789.C   |   13 
 6 files changed, 75 

Re: [PR c++/84789] do not resolve typename into template-independent

2018-03-21 Thread Jason Merrill
On Tue, Mar 20, 2018 at 11:27 PM, Alexandre Oliva  wrote:
> On Mar 20, 2018, Jason Merrill  wrote:
>
>> On Tue, Mar 20, 2018 at 6:07 PM, Alexandre Oliva  wrote:
>>> On Mar 20, 2018, Jason Merrill  wrote:
 that doesn't mean it's wrong to peek.
>
>>> Huh?  We're referencing members of an unrelated template that AFAIK
>>> needs not even be defined at that point, and even if it is, it could
>>> still be specialized afterwards.  How can it possibly be right to
>>> short-circuit such nested names?
>
>>> template struct B : A {}; // would /*: A {}*/ make any diff?
>>> template struct C : B // would /* : B*/ make any diff?
>>> {
>>>   B::A::I::I i; // { dg-error "typename" }
>>> };
>
>> No, we look inside when we're trying to parse the qualified-id as the
>> name of a declaration
>
> Yeah, but that's not the case at hand.  I guess we're miscommunicating.
> I understood you were saying it was ok to peek in this case.  Would you
> please state, for clarity, what your stance is on peeking in this case,
> specifically, in the B::A::I::I within the definition of C above?

It's OK when we're tentatively trying to parse it as a declarator, not
when we're trying to parse it as a type-specifier.

We seem to be talking past each other on this point: We already don't
peek when parsing a type-specifier, we only call resolve_typename_type
with false for only_current_p in the context of trying to parse a
declarator.  The parser tries both interpretations for B::A::I::I.
The type interpretation is ill-formed because of missing 'typename',
so it tries again as a declarator, and therefore tries to resolve the
TYPENAME_TYPE that it built while trying for a type, and trips the
assert.

>> in a declarator-id we can look into uninstantiated classes, otherwise
>> there would be no way to define members of class templates.
>
>>   void X::N::f() { } // looks inside X
>
> Of course, but then, we wouldn't get to a template-independent member.
> A member of a template-dependent name is still template-dependent.  It's
> only when a qualified name maps to an external name that it might become
> template-independent, and when this happens, I believe the qualified-id
> is not one that can be used to define a member. Specifically:
>
> struct K { struct L { static double j; }; };
> template  struct M { struct N { static int i; }; };
> template  struct O { typedef M P; typedef K Q; };
> template  int O::P::N::i = 42;
> template  double O::Q::L::j = 42.0;
>
> if we remap O::P to M and O::Q to K, how will we realize the
> given type-ids are not appropriate?  Where will the template parmlist
> belong when the qualified-id is taken as equivalent to K::L::j?

Agreed, these look bizarre because the template parm is used in O,
which is not an enclosing class of i or j.  And j is clearly
ill-formed because it declares a non-template as a template.

But it's not clear to me that i is ill-formed; we allow

struct A { static int i; };
struct B { typedef ::A A; };
int B::A::i = 0;

and the i example seems analogous.  I wouldn't argue against making it
ill-formed, but I don't see a rule that would make it so in the
current draft standard.  And even resolving the scope to be
non-dependent doesn't necessarily mean the declaration will be, if the
template parameter list ends up being for a member template:

struct K { struct L { template  static void f(T); }; };
template  struct O { typedef K Q; };
template  void O::Q::L::f(T) { }

 I disagree; it seems to me that the assert should allow the case where
 the scope was originally dependent, but got resolved earlier in the
 function.
>>>
>>> Doesn't the function always take dependent scopes?  I for some reason
>>> thought that was the case.
>
>> Yes, as the comment says, a TYPENAME_TYPE should always have a
>> dependent scope.  In this case, the dependent scope was "typename
>> B::A", but just above we resolved it to just A, making it no longer
>> dependent.
>
> Then you got me thoroughly confused: what did you mean by 'the assert
> should allow' a case that's a given?

asserts are often used to verify that things we think of as givens are
actually true.  :)

I suppose we could remove the assert, but I'd probably move it up
above where we start messing with 'scope'.

Jason


Re: [PR c++/84789] do not resolve typename into template-independent

2018-03-20 Thread Alexandre Oliva
On Mar 20, 2018, Jason Merrill  wrote:

> On Tue, Mar 20, 2018 at 6:07 PM, Alexandre Oliva  wrote:
>> On Mar 20, 2018, Jason Merrill  wrote:
>>> that doesn't mean it's wrong to peek.

>> Huh?  We're referencing members of an unrelated template that AFAIK
>> needs not even be defined at that point, and even if it is, it could
>> still be specialized afterwards.  How can it possibly be right to
>> short-circuit such nested names?

>> template struct B : A {}; // would /*: A {}*/ make any diff?
>> template struct C : B // would /* : B*/ make any diff?
>> {
>>   B::A::I::I i; // { dg-error "typename" }
>> };

> No, we look inside when we're trying to parse the qualified-id as the
> name of a declaration

Yeah, but that's not the case at hand.  I guess we're miscommunicating.
I understood you were saying it was ok to peek in this case.  Would you
please state, for clarity, what your stance is on peeking in this case,
specifically, in the B::A::I::I within the definition of C above?

> in a declarator-id we can look into uninstantiated classes, otherwise
> there would be no way to define members of class templates.

>   void X::N::f() { } // looks inside X

Of course, but then, we wouldn't get to a template-independent member.
A member of a template-dependent name is still template-dependent.  It's
only when a qualified name maps to an external name that it might become
template-independent, and when this happens, I believe the qualified-id
is not one that can be used to define a member.  Specifically:

struct K { struct L { static double j; }; };
template  struct M { struct N { static int i; }; };
template  struct O { typedef M P; typedef K Q; };
template  int O::P::N::i = 42;
template  double O::Q::L::j = 42.0;

if we remap O::P to M and O::Q to K, how will we realize the
given type-ids are not appropriate?  Where will the template parmlist
belong when the qualified-id is taken as equivalent to K::L::j?

FWIW, we silently swallow the definition of i above (I think we
shouldn't), and we fail the same assert in resolve_typename_type when
parsing the definition of j.

So, you see, we do have problems with declarators, and we have problems
with types.  AFAICT, we shouldn't simplify qualified-ids in declarators,
otherwise we'd fail to issue errors for the definitions above, and we
shouldn't simplify qualified-ids in types involving templates other than
the one we'd in.

So it's not clear to me what purpose the resolver is supposed to serve,
considering that simplifying the types seem to almost never be wanted.
But one issue is whether we can peek into dependent types, another is
whether we can and should simplify them.  The answers to these questions
don't seem to be very clear to me.  What is clear to me is that
refraining from simplifying from dependent to non-dependent enables us
to report errors that we were missing in both declarators and types, and
that simplifying from dependent to unrelated dependent prevents us from
reporting the error we should in the definition of i above.  But is
there any case in which *not* simplifying causes problems?

>>> I disagree; it seems to me that the assert should allow the case where
>>> the scope was originally dependent, but got resolved earlier in the
>>> function.
>> 
>> Doesn't the function always take dependent scopes?  I for some reason
>> thought that was the case.

> Yes, as the comment says, a TYPENAME_TYPE should always have a
> dependent scope.  In this case, the dependent scope was "typename
> B::A", but just above we resolved it to just A, making it no longer
> dependent.

Then you got me thoroughly confused: what did you mean by 'the assert
should allow' a case that's a given?

-- 
Alexandre Oliva, freedom fighterhttp://FSFLA.org/~lxoliva/
You must be the change you wish to see in the world. -- Gandhi
Be Free! -- http://FSFLA.org/   FSF Latin America board member
Free Software Evangelist|Red Hat Brasil GNU Toolchain Engineer


Re: [PR c++/84789] do not resolve typename into template-independent

2018-03-20 Thread Jason Merrill
On Tue, Mar 20, 2018 at 6:07 PM, Alexandre Oliva  wrote:
> On Mar 20, 2018, Jason Merrill  wrote:
>
>> On Fri, Mar 16, 2018 at 5:38 PM, Alexandre Oliva  wrote:
>>> resolve_typename_type may peek into template types that might still be
>>> specialized.  In some cases, e.g. g++.dg/template/friend48.C or
>>> g++.dg/template/decl2.C, that is exactly the right thing to do.  In
>>> others, like the newly-added testcase g++.dg/template/pr84789.C, it
>>> isn't, and if the qualifying scope happens to resolve to a non-template
>>> type, we resolve to that and then fail the assert that checks we still
>>> have a template-dependent scope.
>
>> We're looking inside them because we're trying to parse a declarator;
>> the tentative parse will fail in this case, because we aren't in a
>> declarator, but that doesn't mean it's wrong to peek.
>
> Huh?  We're referencing members of an unrelated template that AFAIK
> needs not even be defined at that point, and even if it is, it could
> still be specialized afterwards.  How can it possibly be right to
> short-circuit such nested names?  How would template
> instantiation/specialization get a chance to do the proper mapping?
>
> template struct B : A {}; // would /*: A {}*/ make any diff?
> template struct C : B // would /* : B*/ make any diff?
> {
>   B::A::I::I i; // { dg-error "typename" }
> };

> Is it by any chance the fact that B is a base class for C that
> makes it correct to peek into it?  I don't recall any exception of this
> sort.

No, we look inside when we're trying to parse the qualified-id as the
name of a declaration; in a declarator-id we can look into
uninstantiated classes, otherwise there would be no way to define
members of class templates.

  void X::N::f() { } // looks inside X

>> I disagree; it seems to me that the assert should allow the case where
>> the scope was originally dependent, but got resolved earlier in the
>> function.
>
> Doesn't the function always take dependent scopes?  I for some reason
> thought that was the case.

Yes, as the comment says, a TYPENAME_TYPE should always have a
dependent scope.  In this case, the dependent scope was "typename
B::A", but just above we resolved it to just A, making it no longer
dependent.

Jason


Re: [PR c++/84789] do not resolve typename into template-independent

2018-03-20 Thread Alexandre Oliva
On Mar 20, 2018, Jason Merrill  wrote:

> On Fri, Mar 16, 2018 at 5:38 PM, Alexandre Oliva  wrote:
>> resolve_typename_type may peek into template types that might still be
>> specialized.  In some cases, e.g. g++.dg/template/friend48.C or
>> g++.dg/template/decl2.C, that is exactly the right thing to do.  In
>> others, like the newly-added testcase g++.dg/template/pr84789.C, it
>> isn't, and if the qualifying scope happens to resolve to a non-template
>> type, we resolve to that and then fail the assert that checks we still
>> have a template-dependent scope.

> We're looking inside them because we're trying to parse a declarator;
> the tentative parse will fail in this case, because we aren't in a
> declarator, but that doesn't mean it's wrong to peek.

Huh?  We're referencing members of an unrelated template that AFAIK
needs not even be defined at that point, and even if it is, it could
still be specialized afterwards.  How can it possibly be right to
short-circuit such nested names?  How would template
instantiation/specialization get a chance to do the proper mapping?

template struct B : A {}; // would /*: A {}*/ make any diff?
template struct C : B // would /* : B*/ make any diff?
{
  B::A::I::I i; // { dg-error "typename" }
};

Is it by any chance the fact that B is a base class for C that
makes it correct to peek into it?  I don't recall any exception of this
sort.

> I disagree; it seems to me that the assert should allow the case where
> the scope was originally dependent, but got resolved earlier in the
> function.

Doesn't the function always take dependent scopes?  I for some reason
thought that was the case.

-- 
Alexandre Oliva, freedom fighterhttp://FSFLA.org/~lxoliva/
You must be the change you wish to see in the world. -- Gandhi
Be Free! -- http://FSFLA.org/   FSF Latin America board member
Free Software Evangelist|Red Hat Brasil GNU Toolchain Engineer


Re: [PR c++/84789] do not resolve typename into template-independent

2018-03-20 Thread Jason Merrill
On Fri, Mar 16, 2018 at 5:38 PM, Alexandre Oliva  wrote:
> resolve_typename_type may peek into template types that might still be
> specialized.  In some cases, e.g. g++.dg/template/friend48.C or
> g++.dg/template/decl2.C, that is exactly the right thing to do.  In
> others, like the newly-added testcase g++.dg/template/pr84789.C, it
> isn't, and if the qualifying scope happens to resolve to a non-template
> type, we resolve to that and then fail the assert that checks we still
> have a template-dependent scope.

We're looking inside them because we're trying to parse a declarator;
the tentative parse will fail in this case, because we aren't in a
declarator, but that doesn't mean it's wrong to peek.

Though I'm not sure why cp_parser_parse_and_diagnose_invalid_type_name
is passing true for declarator_p to cp_parser_id_expression.  I'm
going to try changing that to false and see if anything breaks.

> It appears to me that, in cases in which the assert would fail, we are
> missing the typename keyword, and we ought to report an error; if we
> just return the incoming type unchanged, that's exactly what we get.
> So, I'm turning such failed asserts into early returns, so that the
> parser can recover and report an error.

I disagree; it seems to me that the assert should allow the case where
the scope was originally dependent, but got resolved earlier in the
function.

Jason