diff options
author | Marek Polacek <polacek@redhat.com> | 2023-11-09 12:25:25 -0500 |
---|---|---|
committer | Marek Polacek <polacek@redhat.com> | 2023-11-15 22:22:20 -0500 |
commit | 70060dadfbf0d0af5f4cab5f3aff3223a4523606 (patch) | |
tree | 8197907f6b80bf58e65078ab6be19c76ffe7ce7d /gcc | |
parent | 9251db0dabc8e75c31b49a5b589124e9a2bc8299 (diff) | |
download | gcc-70060dadfbf0d0af5f4cab5f3aff3223a4523606.zip gcc-70060dadfbf0d0af5f4cab5f3aff3223a4523606.tar.gz gcc-70060dadfbf0d0af5f4cab5f3aff3223a4523606.tar.bz2 |
c++: fix parsing with auto(x) [PR112410]
Here we are wrongly parsing
int y(auto(42));
which uses the C++23 cast-to-prvalue feature, and initializes y to 42.
However, we were treating the auto as an implicit template parameter.
Fixing the auto{42} case is easy, but when auto is followed by a (,
I found the fix to be much more involved. For instance, we cannot
use cp_parser_expression, because that can give hard errors. It's
also necessary to disambiguate 'auto(i)' as 'auto i', not a cast.
auto(), auto(int), auto(f)(int), auto(*), auto(i[]), auto(...), etc.
are all function declarations.
This patch rectifies that by undoing the implicit function template
modification. In the test above, we should notice that the parameter
list is ill-formed, and since we've synthesized an implicit template
parameter, we undo it by calling abort_fully_implicit_template. Then,
we'll parse the "(auto(42))" as an initializer.
PR c++/112410
gcc/cp/ChangeLog:
* parser.cc (cp_parser_direct_declarator): Maybe call
abort_fully_implicit_template if it turned out the parameter list was
ill-formed.
gcc/testsuite/ChangeLog:
* g++.dg/cpp23/auto-fncast13.C: New test.
* g++.dg/cpp23/auto-fncast14.C: New test.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/parser.cc | 13 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp23/auto-fncast13.C | 61 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp23/auto-fncast14.C | 9 |
3 files changed, 83 insertions, 0 deletions
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index 5116bcb..d110433 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -23594,6 +23594,19 @@ cp_parser_direct_declarator (cp_parser* parser, /* Consume the `)'. */ parens.require_close (parser); + /* For code like + int x(auto(42)); + A a(auto(i), 42); + we have synthesized an implicit template parameter and marked + what we thought was a function as an implicit function template. + But now, having seen the whole parameter list, we know it's not + a function declaration, so undo that. */ + if (cp_parser_error_occurred (parser) + && parser->fully_implicit_function_template_p + /* Don't do this for the inner (). */ + && parser->default_arg_ok_p) + abort_fully_implicit_template (parser); + /* If all went well, parse the cv-qualifier-seq, ref-qualifier and the exception-specification. */ if (member_p || cp_parser_parse_definitely (parser)) diff --git a/gcc/testsuite/g++.dg/cpp23/auto-fncast13.C b/gcc/testsuite/g++.dg/cpp23/auto-fncast13.C new file mode 100644 index 0000000..1bceffb --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/auto-fncast13.C @@ -0,0 +1,61 @@ +// PR c++/112410 +// { dg-do compile { target c++23 } } + +int f1 (auto(int) -> char); +int f2 (auto x); +int f3 (auto); +int f4 (auto(i)); + +int v1 (auto(42)); +int v2 (auto{42}); +int e1 (auto{i}); // { dg-error "not declared" } +int i; +int v3 (auto{i}); +int v4 (auto(i + 1)); +int v5 (auto(+i)); +int v6 (auto(i = 4)); + +int f5 (auto(i)); +int f6 (auto()); +int f7 (auto(int)); +int f8 (auto(f)(int)); +int f9 (auto(...) -> char); +// FIXME: ICEs (PR c++/89867) +//int f10 (auto(__attribute__((unused)) i)); +int f11 (auto((i))); +int f12 (auto(i[])); +int f13 (auto(*i)); +int f14 (auto(*)); + +int e2 (auto{}); // { dg-error "invalid use of .auto." } +int e3 (auto(i, i)); // { dg-error "invalid use of .auto." } + +char bar (int); +char baz (); +char qux (...); + +void +g (int i) +{ + f1 (bar); + f2 (42); + f3 (42); + f4 (42); + f5 (42); + f6 (baz); + f7 (bar); + f8 (bar); + f9 (qux); +// f10 (42); + f11 (42); + f12 (&i); + f13 (&i); + f14 (&i); + + v1 = 1; + v2 = 2; + v3 = 3; + v4 = 4; + v5 = 5; + v6 = 6; +} diff --git a/gcc/testsuite/g++.dg/cpp23/auto-fncast14.C b/gcc/testsuite/g++.dg/cpp23/auto-fncast14.C new file mode 100644 index 0000000..9e7a06c --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/auto-fncast14.C @@ -0,0 +1,9 @@ +// PR c++/112410 +// { dg-do compile { target c++23 } } + +struct A { + A(int,int); +}; + +int a; +A b1(auto(a), 42); |