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;
+}

Reply via email to