As I promised in <https://gcc.gnu.org/ml/gcc-patches/2018-08/msg00908.html>,
this patch fixes a couple of invalid cases we weren't detecting.  It's got
testcases from two PRs and another case I found out; they're intertwined so
I think it makes sense to fix them in one go.

Bootstrapped/regtested on x86_64-linux, ok for trunk?

2018-08-16  Marek Polacek  <pola...@redhat.com>

        PR c++/86942
        PR c++/67012
        * decl.c (grokdeclarator): Disallow functions with trailing return
        type with decltype(auto) as its type.  Also check the function if
        it's inner declarator doesn't exist.

        * g++.dg/cpp0x/auto52.C: New test.
        * g++.dg/cpp1y/auto-fn52.C: New test.
        * g++.dg/cpp1y/auto-fn53.C: New test.
        * g++.dg/cpp1y/auto-fn54.C: New test.

diff --git gcc/cp/decl.c gcc/cp/decl.c
index fa58bc4d2b3..8261f8e30e5 100644
--- gcc/cp/decl.c
+++ gcc/cp/decl.c
@@ -11238,7 +11238,10 @@ grokdeclarator (const cp_declarator *declarator,
 
            /* Handle a late-specified return type.  */
            tree late_return_type = declarator->u.function.late_return_type;
-           if (funcdecl_p)
+           if (funcdecl_p
+               /* This is the case e.g. for
+                  using T = auto () -> int.  */
+               || inner_declarator == NULL)
              {
                if (tree auto_node = type_uses_auto (type))
                  {
@@ -11270,6 +11273,18 @@ grokdeclarator (const cp_declarator *declarator,
                               name, type);
                        return error_mark_node;
                      }
+                   else if (is_auto (type)
+                            && (TYPE_IDENTIFIER (type)
+                                == decltype_auto_identifier))
+                     {
+                       if (funcdecl_p)
+                         error ("%qs function with trailing return type has "
+                                "%<decltype(auto)%> as its type rather than "
+                                "plain %<auto%>", name);
+                       else
+                         error ("invalid use of %<decltype(auto)%>");
+                       return error_mark_node;
+                     }
                    tree tmpl = CLASS_PLACEHOLDER_TEMPLATE (auto_node);
                    if (!tmpl)
                      if (tree late_auto = type_uses_auto (late_return_type))
diff --git gcc/testsuite/g++.dg/cpp0x/auto52.C 
gcc/testsuite/g++.dg/cpp0x/auto52.C
index e69de29bb2d..9bfe7c754b5 100644
--- gcc/testsuite/g++.dg/cpp0x/auto52.C
+++ gcc/testsuite/g++.dg/cpp0x/auto52.C
@@ -0,0 +1,6 @@
+// PR c++/86942
+// { dg-do compile { target c++11 } }
+
+using T = auto() -> int;
+using U = void() -> int; // { dg-error "function with trailing return type not 
declared with .auto." }
+using W = auto(); // { dg-error "invalid use of .auto." }
diff --git gcc/testsuite/g++.dg/cpp1y/auto-fn52.C 
gcc/testsuite/g++.dg/cpp1y/auto-fn52.C
index e69de29bb2d..e239bc27dc2 100644
--- gcc/testsuite/g++.dg/cpp1y/auto-fn52.C
+++ gcc/testsuite/g++.dg/cpp1y/auto-fn52.C
@@ -0,0 +1,4 @@
+// PR c++/67012
+// { dg-do compile { target c++14 } }
+
+decltype(auto) f() -> int; // { dg-error "function with trailing return type 
has" }
diff --git gcc/testsuite/g++.dg/cpp1y/auto-fn53.C 
gcc/testsuite/g++.dg/cpp1y/auto-fn53.C
index e69de29bb2d..720aeeb215d 100644
--- gcc/testsuite/g++.dg/cpp1y/auto-fn53.C
+++ gcc/testsuite/g++.dg/cpp1y/auto-fn53.C
@@ -0,0 +1,4 @@
+// PR c++/86942
+// { dg-do compile { target c++14 } }
+
+using T = decltype(auto) () -> int; // { dg-error "invalid use of" }
diff --git gcc/testsuite/g++.dg/cpp1y/auto-fn54.C 
gcc/testsuite/g++.dg/cpp1y/auto-fn54.C
index e69de29bb2d..f3391ddfd75 100644
--- gcc/testsuite/g++.dg/cpp1y/auto-fn54.C
+++ gcc/testsuite/g++.dg/cpp1y/auto-fn54.C
@@ -0,0 +1,3 @@
+// { dg-do compile { target c++14 } }
+
+using T = int () -> decltype(auto); // { dg-error "function with trailing 
return type not declared with .auto." }

Reply via email to