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." }