Tested x86_64-pc-linux-gnu, applying to trunk. -- 8< --
In r14-1659 I added a missing error for a Concepts TS feature that we were failing to diagnose, but this PR requests a way to disable that error for code written thinking it was valid. Which seems reasonable, since it doesn't require any work beyond that and is a plausible extension by itself. While looking at this, I also noticed we were still not giving the diagnostic in a few cases, and fixing that affected a few of our old concepts testcases. PR c++/120917 gcc/ChangeLog: * doc/invoke.texi: Add -Wno-abbreviated-auto-in-template-arg. gcc/c-family/ChangeLog: * c.opt: Add -Wno-abbreviated-auto-in-template-arg. * c.opt.urls: Regenerate. gcc/cp/ChangeLog: * parser.cc (cp_parser_simple_type_specifier): Attach auto in targ in parameter to -Wabbreviated-auto-in-template-arg. (cp_parser_placeholder_type_specifier): Diagnose constrained auto in template arg. gcc/testsuite/ChangeLog: * g++.dg/concepts/auto7a.C: Add diagnostic. * g++.dg/concepts/auto7b.C: New test. * g++.dg/concepts/auto7c.C: New test. * g++.dg/cpp1y/pr85076.C: Expect 'auto' error. * g++.dg/concepts/pr67249.C: Likewise. * g++.dg/cpp1y/lambda-generic-variadic.C: Likewise. * g++.dg/cpp2a/concepts-pr67210.C: Likewise. * g++.dg/concepts/pr67249a.C: New test. * g++.dg/cpp1y/lambda-generic-variadic-a.C: New test. * g++.dg/cpp2a/concepts-pr67210a.C: New test. --- gcc/doc/invoke.texi | 18 ++++++++++++++++++ gcc/c-family/c.opt | 4 ++++ gcc/cp/parser.cc | 12 +++++++++--- gcc/testsuite/g++.dg/concepts/auto7a.C | 1 + gcc/testsuite/g++.dg/concepts/auto7b.C | 10 ++++++++++ gcc/testsuite/g++.dg/concepts/auto7c.C | 12 ++++++++++++ gcc/testsuite/g++.dg/concepts/pr67249.C | 2 +- gcc/testsuite/g++.dg/concepts/pr67249a.C | 7 +++++++ .../g++.dg/cpp1y/lambda-generic-variadic-a.C | 15 +++++++++++++++ .../g++.dg/cpp1y/lambda-generic-variadic.C | 4 ++-- gcc/testsuite/g++.dg/cpp1y/pr85076.C | 2 +- gcc/testsuite/g++.dg/cpp2a/concepts-pr67210.C | 2 +- gcc/testsuite/g++.dg/cpp2a/concepts-pr67210a.C | 11 +++++++++++ gcc/c-family/c.opt.urls | 3 +++ 14 files changed, 95 insertions(+), 8 deletions(-) create mode 100644 gcc/testsuite/g++.dg/concepts/auto7b.C create mode 100644 gcc/testsuite/g++.dg/concepts/auto7c.C create mode 100644 gcc/testsuite/g++.dg/concepts/pr67249a.C create mode 100644 gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic-a.C create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-pr67210a.C diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 7640e7d8867..74f5ee26042 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -3816,6 +3816,23 @@ Warn when a type with an ABI tag is used in a context that does not have that ABI tag. See @ref{C++ Attributes} for more information about ABI tags. +@opindex Wabbreviated-auto-in-template-arg +@opindex Wno-abbreviated-auto-in-template-arg +@item -Wno-abbreviated-auto-in-template-arg +Disable the error for an @code{auto} placeholder type used within a +template argument list to declare a C++20 abbreviated function +template, e.g. + +@smallexample +void f(S<auto>); +@end smallexample + +This feature was proposed in the Concepts TS, but was not adopted into +C++20; in the standard, a placeholder in a parameter declaration must +appear as a decl-specifier. The error can also be reduced to a +warning by @option{-fpermissive} or +@option{-Wno-error=abbreviated-auto-in-template-arg}. + @opindex Wcomma-subscript @opindex Wno-comma-subscript @item -Wcomma-subscript @r{(C++ and Objective-C++ only)} @@ -6443,6 +6460,7 @@ only by this flag, but it also downgrades some C and C++ diagnostics that have their own flag: @gccoptlist{ +-Wabbreviated-auto-in-template-arg @r{(C++ and Objective-C++ only)} -Wdeclaration-missing-parameter-type @r{(C and Objective-C only)} -Wimplicit-function-declaration @r{(C and Objective-C only)} -Wimplicit-int @r{(C and Objective-C only)} diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index 8af466d1ed1..6a55e7118d1 100644 --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt @@ -397,6 +397,10 @@ Wassign-intercept ObjC ObjC++ Var(warn_assign_intercept) Warning Warn whenever an Objective-C assignment is being intercepted by the garbage collector. +Wabbreviated-auto-in-template-arg +C++ ObjC++ Warning Var(warn_abbev_auto_targ) Init(1) +Diagnose a placeholder type in a template argument in a function parameter type. + Wbad-function-cast C ObjC Var(warn_bad_function_cast) Warning Warn about casting functions to incompatible types. diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index 44a78324c6e..239e6f9a556 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -21021,9 +21021,6 @@ cp_parser_simple_type_specifier (cp_parser* parser, "only available with " "%<-std=c++14%> or %<-std=gnu++14%>"); } - else if (parser->in_template_argument_list_p) - error_at (token->location, - "use of %<auto%> in template argument"); else if (!flag_concepts) pedwarn (token->location, OPT_Wc__20_extensions, "use of %<auto%> in parameter declaration " @@ -21033,6 +21030,11 @@ cp_parser_simple_type_specifier (cp_parser* parser, "use of %<auto%> in parameter declaration " "only available with " "%<-std=c++14%> or %<-std=gnu++14%>"); + + if (parser->in_template_argument_list_p) + permerror_opt (token->location, + OPT_Wabbreviated_auto_in_template_arg, + "use of %<auto%> in template argument"); } else type = make_auto (); @@ -21479,6 +21481,10 @@ cp_parser_placeholder_type_specifier (cp_parser *parser, location_t loc, error_at (loc, "cannot declare a parameter with %<decltype(auto)%>"); return error_mark_node; } + if (parser->in_template_argument_list_p) + permerror_opt (placeholder->location, + OPT_Wabbreviated_auto_in_template_arg, + "use of %<auto%> in template argument"); tree parm = build_constrained_parameter (con, proto, args); return synthesize_implicit_template_parm (parser, parm); } diff --git a/gcc/testsuite/g++.dg/concepts/auto7a.C b/gcc/testsuite/g++.dg/concepts/auto7a.C index 88868f45d1c..f36038d2fb4 100644 --- a/gcc/testsuite/g++.dg/concepts/auto7a.C +++ b/gcc/testsuite/g++.dg/concepts/auto7a.C @@ -2,6 +2,7 @@ template <class T> struct A { }; void f(A<auto> a) { } // { dg-error "auto. in template argument" } +// { dg-message "in parameter declaration" "" { target c++17_down } .-1 } int main() { f(A<int>()); diff --git a/gcc/testsuite/g++.dg/concepts/auto7b.C b/gcc/testsuite/g++.dg/concepts/auto7b.C new file mode 100644 index 00000000000..874192c0385 --- /dev/null +++ b/gcc/testsuite/g++.dg/concepts/auto7b.C @@ -0,0 +1,10 @@ +// PR c++/120917 +// { dg-do compile { target c++14 } } +// { dg-additional-options "-fconcepts -Wno-abbreviated-auto-in-template-arg" } + +template <class T> struct A { }; +void f(A<auto> a) { } +int main() +{ + f(A<int>()); +} diff --git a/gcc/testsuite/g++.dg/concepts/auto7c.C b/gcc/testsuite/g++.dg/concepts/auto7c.C new file mode 100644 index 00000000000..5b16027e2b6 --- /dev/null +++ b/gcc/testsuite/g++.dg/concepts/auto7c.C @@ -0,0 +1,12 @@ +// { dg-do compile { target c++17 } } +// { dg-additional-options -fconcepts } + +template <class T> +concept True = true; + +template <class T> struct A { }; +void f(A<True auto> a) { } // { dg-error "use of .auto. in template argument" } +int main() +{ + f(A<int>()); +} diff --git a/gcc/testsuite/g++.dg/concepts/pr67249.C b/gcc/testsuite/g++.dg/concepts/pr67249.C index e0f8d5ade01..e97183d1b21 100644 --- a/gcc/testsuite/g++.dg/concepts/pr67249.C +++ b/gcc/testsuite/g++.dg/concepts/pr67249.C @@ -4,4 +4,4 @@ template<class T> concept C1 = true; template<class A, class B> struct Pair {}; // We used to test "Pair<auto, C1 >". -void f(Pair<C1 auto, C1 auto>); +void f(Pair<C1 auto, C1 auto>); // { dg-error "auto" } diff --git a/gcc/testsuite/g++.dg/concepts/pr67249a.C b/gcc/testsuite/g++.dg/concepts/pr67249a.C new file mode 100644 index 00000000000..cb5d90ed361 --- /dev/null +++ b/gcc/testsuite/g++.dg/concepts/pr67249a.C @@ -0,0 +1,7 @@ +// { dg-do compile { target c++17 } } +// { dg-options "-fconcepts -Wno-abbreviated-auto-in-template-arg" } + +template<class T> concept C1 = true; +template<class A, class B> struct Pair {}; +// We used to test "Pair<auto, C1 >". +void f(Pair<C1 auto, C1 auto>); diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic-a.C b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic-a.C new file mode 100644 index 00000000000..557ecb914ec --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic-a.C @@ -0,0 +1,15 @@ +// Basic generic lambda test +// { dg-do run { target c++14 } } +// { dg-additional-options -Wno-abbreviated-auto-in-template-arg } + +template <typename T, typename U> struct pair {}; +template <typename... T> struct tuple {}; + +int main() +{ + auto a = [] (auto, pair<auto,auto> v) { return sizeof (v); }; + auto b = [] (auto, pair<pair<auto,auto>,auto>... v) { return sizeof... (v); }; + + a(1, pair<int, float>()); + b(2, pair<pair<short,char>, double>(), pair<pair<float,long>, int>()); +} diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic.C b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic.C index 6d2d250f393..971f58fea0b 100644 --- a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic.C +++ b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic.C @@ -6,8 +6,8 @@ template <typename... T> struct tuple {}; int main() { - auto a = [] (auto, pair<auto,auto> v) { return sizeof (v); }; - auto b = [] (auto, pair<pair<auto,auto>,auto>... v) { return sizeof... (v); }; + auto a = [] (auto, pair<auto,auto> v) { return sizeof (v); }; // { dg-error "auto" } + auto b = [] (auto, pair<pair<auto,auto>,auto>... v) { return sizeof... (v); }; // { dg-error "auto" } a(1, pair<int, float>()); b(2, pair<pair<short,char>, double>(), pair<pair<float,long>, int>()); diff --git a/gcc/testsuite/g++.dg/cpp1y/pr85076.C b/gcc/testsuite/g++.dg/cpp1y/pr85076.C index 6d54dea6c01..b68143b23f9 100644 --- a/gcc/testsuite/g++.dg/cpp1y/pr85076.C +++ b/gcc/testsuite/g++.dg/cpp1y/pr85076.C @@ -3,4 +3,4 @@ template<typename> struct A*; // { dg-error "expected unqualified-id before" } -auto a = [](A<auto>) {}; // { dg-error "is not a template|has incomplete type" } +auto a = [](A<auto>) {}; // { dg-error "is not a template|has incomplete type|auto" } diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-pr67210.C b/gcc/testsuite/g++.dg/cpp2a/concepts-pr67210.C index a31750eb495..baddc1cd465 100644 --- a/gcc/testsuite/g++.dg/cpp2a/concepts-pr67210.C +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-pr67210.C @@ -7,4 +7,4 @@ concept C = true; template <class T> struct A {}; -void f(A<C<int> auto >) {} +void f(A<C<int> auto >) {} // { dg-error "auto" } diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-pr67210a.C b/gcc/testsuite/g++.dg/cpp2a/concepts-pr67210a.C new file mode 100644 index 00000000000..1d63a844aa4 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-pr67210a.C @@ -0,0 +1,11 @@ +// PR c++/67210 +// { dg-do compile { target c++20 } } +// { dg-additional-options -Wno-abbreviated-auto-in-template-arg } + +template <class T, class U> +concept C = true; + +template <class T> +struct A {}; + +void f(A<C<int> auto >) {} diff --git a/gcc/c-family/c.opt.urls b/gcc/c-family/c.opt.urls index 65d1221c4ad..401e6e74138 100644 --- a/gcc/c-family/c.opt.urls +++ b/gcc/c-family/c.opt.urls @@ -139,6 +139,9 @@ UrlSuffix(gcc/Warning-Options.html#index-Warray-parameter) Wassign-intercept UrlSuffix(gcc/Objective-C-and-Objective-C_002b_002b-Dialect-Options.html#index-Wassign-intercept) +Wabbreviated-auto-in-template-arg +UrlSuffix(gcc/C_002b_002b-Dialect-Options.html#index-Wabbreviated-auto-in-template-arg) + Wbad-function-cast UrlSuffix(gcc/Warning-Options.html#index-Wbad-function-cast) base-commit: 0c73f2f1f92c135f50dcc2ab76d5e53236262a4e -- 2.49.0