On Thu, Mar 1, 2018 at 11:00 AM, Jason Merrill <ja...@redhat.com> wrote: > On Thu, Mar 1, 2018 at 9:41 AM, Jason Merrill <ja...@redhat.com> wrote: >> On Wed, Feb 28, 2018 at 4:04 PM, Paolo Carlini <paolo.carl...@oracle.com> >> wrote: >>> On 28/02/2018 20:20, Jason Merrill wrote: >>>> >>>> Hmm, the test seems wrong; the diagnostic talks about specializing the >>>> arguments, but the actual test is checking whether the enclosing scope >>>> is fully specialized. It looks like you'll give the same error for >>>> >>>> template <class T> >>>> struct A { >>>> template <class U> >>>> static const U u; >>>> }; >>>> >>>> template <class T> >>>> template <class U> >>>> const U* A<T>::u<U*> = nullptr; >>>> >>>> which does specialize the argument; since we accept >>>> >>>> template <class T> >>>> struct A { >>>> template <class U> >>>> struct B; >>>> }; >>>> >>>> template <class T> >>>> template <class U> >>>> struct A<T>::B<U*> { }; >>>> >>>> we ought to accept the above as well. >>>> >>>> So, we could reject the testcase with this error, but we would need to >>>> test for it using the same check as in process_partial_specialization. >>> >>> I see. Doing that seems relatively easy - I have a draft which appears to >>> work - but then we have immediately to change the gcc_assert at the >>> beginning of determine_specialization to let such specializations through >>> (of course it still uses the wrong test!!). I'm not sure about the best way >>> to do that... But that seems also doable. >> >> That test is correct for functions, I think we just want to restrict >> that block to functions. >> >>> The next problem is >>> duplicate_decls which apparently misses a bit of code to understand that the >>> new declaration does not conflict with the old one near line #1650... So, >>> frankly, I think that even with your great guidance I would need a few >>> iterations to get right the whole package and we are so damn close to the >>> release. What do you think? Do you want to take this over, or maybe you see >>> us restricting a bit what we'll have working in this area for 8.1.0? >> >> Yeah, I'll take it. > > Ah, needed to fix the code in start_decl that checks for a variable > template specialization to consider that a specialization can be a > template.
And this fixes the other testcase in comment 6.
commit 530608b73c7fc0345f8150ad124b57e180abfa11 Author: Jason Merrill <ja...@redhat.com> Date: Thu Mar 1 12:24:39 2018 -0500 PR c++/71569 - decltype of template. * parser.c (cp_parser_decltype_expr): Handle missing template args. diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 359460cd4d8..e1acb07d29e 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -13983,6 +13983,10 @@ cp_parser_decltype_expr (cp_parser *parser, expr = cp_parser_lookup_name_simple (parser, expr, id_expr_start_token->location); + if (expr && TREE_CODE (expr) == TEMPLATE_DECL) + /* A template without args is not a complete id-expression. */ + expr = error_mark_node; + if (expr && expr != error_mark_node && TREE_CODE (expr) != TYPE_DECL @@ -14048,6 +14052,9 @@ cp_parser_decltype_expr (cp_parser *parser, expression. */ cp_parser_abort_tentative_parse (parser); + /* Commit to the tentative_firewall so we get syntax errors. */ + cp_parser_commit_to_tentative_parse (parser); + /* Parse a full expression. */ expr = cp_parser_expression (parser, /*pidk=*/NULL, /*cast_p=*/false, /*decltype_p=*/true); diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype-33837.C b/gcc/testsuite/g++.dg/cpp0x/decltype-33837.C index fbbc6a14972..4a8f053234e 100644 --- a/gcc/testsuite/g++.dg/cpp0x/decltype-33837.C +++ b/gcc/testsuite/g++.dg/cpp0x/decltype-33837.C @@ -2,6 +2,6 @@ // PR c++/33837 void foo() { - __decltype (A::foo()); // { dg-error "was not declared|expected" } - __decltype (B); // { dg-error "was not declared" } + __decltype (A::foo()); // { dg-error "A" } + __decltype (B); // { dg-error "B" } } diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype43.C b/gcc/testsuite/g++.dg/cpp0x/decltype43.C index 4df95a1047c..7a1dcbf8744 100644 --- a/gcc/testsuite/g++.dg/cpp0x/decltype43.C +++ b/gcc/testsuite/g++.dg/cpp0x/decltype43.C @@ -22,6 +22,6 @@ struct B int main() { int x = B<decltype(A<int>::a(1))>::b(A<int>::a(1)); - int y = B<decltype(A ::a(2))>::b(A<int>::a(2)); // { dg-error "template argument" } + int y = B<decltype(A ::a(2))>::b(A<int>::a(2)); // { dg-error "template" } return x + y; } diff --git a/gcc/testsuite/g++.dg/cpp1y/var-templ59.C b/gcc/testsuite/g++.dg/cpp1y/var-templ59.C new file mode 100644 index 00000000000..da9710e1ce4 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/var-templ59.C @@ -0,0 +1,14 @@ +// PR c++/71569 +// { dg-do compile { target c++14 } } + +template <class T> +struct A { + template <class U> + static U u; +}; + +int main() +{ + decltype(A<int>::u) a; // { dg-error "missing template arguments" } + return a; +}