Created attachment 44883 [details] test case The test case is attached. It has no includes and so I am attaching the *.cpp file as per https://gcc.gnu.org/bugs/ I am compiling with -std=c++17 Output of g++ -v: # g++ -v Using built-in specs. COLLECT_GCC=C:\MyProgs\msys64\mingw64\bin\g++.exe COLLECT_LTO_WRAPPER=C:/MyProgs/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.2.0/lto-wrapper.exe Target: x86_64-w64-mingw32 Configured with: ../gcc-8.2.0/configure --prefix=/mingw64 --with-local-prefix=/mingw64/local --build=x86_64-w64-mingw32 --host=x86_64-w64-mingw32 --target=x86_64-w64-mingw32 --with-native-system-header-dir=/mingw64/x86_64-w64-mingw32/include --libexecdir=/mingw64/lib --enable-bootstrap --with-arch=x86-64 --with-tune=generic --enable-languages=ada,c,lto,c++,objc,obj-c++,fortran --enable-shared --enable-static --enable-libatomic --enable-threads=posix --enable-graphite --enable-fully-dynamic-string --enable-libstdcxx-filesystem-ts=yes --enable-libstdcxx-time=yes --disable-libstdcxx-pch --disable-libstdcxx-debug --disable-isl-version-check --enable-lto --enable-libgomp --disable-multilib --enable-checking=release --disable-rpath --disable-win32-registry --disable-nls --disable-werror --disable-symvers --with-libiconv --with-system-zlib --with-gmp=/mingw64 --with-mpfr=/mingw64 --with-mpc=/mingw64 --with-isl=/mingw64 --with-pkgversion='Rev3, Built by MSYS2 project' --with-bugurl=https://sourceforge.net/projects/msys2 --with-gnu-as --with-gnu-ld Thread model: posix gcc version 8.2.0 (Rev3, Built by MSYS2 project) I tried with another build and got the same results. This one gave: # g++ -v Using built-in specs. COLLECT_GCC=/opt/wandbox/gcc-8.2.0/bin/g++ COLLECT_LTO_WRAPPER=/opt/wandbox/gcc-8.2.0/libexec/gcc/x86_64-pc-linux-gnu/8.2.0/lto-wrapper Target: x86_64-pc-linux-gnu Configured with: ../gcc-8.2.0/configure --prefix=/opt/wandbox/gcc-8.2.0 --enable-languages=c,c++ --disable-multilib --without-ppl --without-cloog-ppl --enable-checking=release --disable-nls LDFLAGS=-Wl,-rpath,/opt/wandbox/gcc-8.2.0/lib,-rpath,/opt/wandbox/gcc-8.2.0/lib64,-rpath,/opt/wandbox/gcc-8.2.0/lib32 --enable-lto Thread model: posix gcc version 8.2.0 (GCC)
Confirmed, reduced: template <class T> struct lit { lit(T) { } }; template <class T> int operator+(lit<T>, lit<T>) { return 0; } auto r2 = (lit(0)) + lit(0); 11 | auto r2 = (lit(0)) + lit(0); | ^~~ ctad.cc:2:8: note: 'template<class T> struct lit' declared here 2 | struct lit { | ^~~
Oops, I missed the first line of the diagnostic. The error from trunk is: ctad.cc:11:12: error: missing template arguments after 'lit' 11 | auto r2 = (lit(0)) + lit(0); | ^~~ ctad.cc:2:8: note: 'template<class T> struct lit' declared here 2 | struct lit { | ^~~
*** Bug 87712 has been marked as a duplicate of this bug. ***
There is a pretty good (speculative) analysis of this issue here: https://stackoverflow.com/a/52986284/331785 I am copying it to here for completeness, but credit for this goes to the author of that post: There are two kinds of expressions that look similar but have vastly different meaning: (type) + expr (expr) + expr The first is a C-style cast expression, that converts the unary expression + expr to type, the second is a binary expression that performs addition. To disambiguate an expression of form (something) + expr, GCC first assumes that something is a type and does a tentative parse. If that succeeds, then the whole expression is treated as a cast expression, otherwise, something is reparsed as an expression. Now here's where I think the bug resides: during the tentative parse, GCC wrongly believes that class template argument deduction (CTAD) cannot appear, so it issues an error when it appears. But in fact, even though the tentative parse will definitely fail in this case, something may still be a valid function-style cast expression, and thus the reparse might be successful. For cat((lit('b')), lit('d')), lit('b') + lit('d'), and (lit('b')), GCC is clever enough to see that they can't be C-style cast expression, so it does not do the tentative parse. For (lit<char>('b')) + lit('d'), there's no CTAD in lit<char>('b'), so it is fine as well. Prove of the above analysis: If + is changed to / (or most operators other than -, * or &), no error occurs, because (something) / expr can't be a valid cast expression. Similar ambiguity exists in sizeof(something) (could be sizeof(type) or sizeof(expr)), and as expected, sizeof(lit(0)) triggers a similar error.
*** Bug 88020 has been marked as a duplicate of this bug. ***
From Bug 88020: template <class T> struct S{ S(T){} }; static_assert(sizeof(S{0})); <source>:5:22: error: missing template arguments after 'S' static_assert(sizeof(S{0})); ^ <source>:2:8: note: 'template<class T> struct S' declared here struct S{ ^
*** Bug 89220 has been marked as a duplicate of this bug. ***
This was ASSIGNED but no actual assignee.
Whoops, sorry about that, I meant to assign myself. Trying again..
The master branch has been updated by Patrick Palka <ppalka@gcc.gnu.org>: https://gcc.gnu.org/g:5f1a2cb9c2dc09eed53da5d5787d14bec700b10b commit r12-99-g5f1a2cb9c2dc09eed53da5d5787d14bec700b10b Author: Patrick Palka <ppalka@redhat.com> Date: Sat Apr 24 00:01:42 2021 -0400 c++: Hard error with tentative parse and CTAD [PR87709] When parsing e.g. the operand of sizeof, where both types and expressions are accepted, if during the tentative type parse we encounter an unexpected template placeholder, we must simulate an error rather than issue a real error because the expression parse can still succeed. gcc/cp/ChangeLog: PR c++/87709 * parser.c (cp_parser_type_id_1): If we see a template placeholder, first try simulating an error before issuing a real error. gcc/testsuite/ChangeLog: PR c++/87709 * g++.dg/cpp1z/class-deduction86.C: New test.
Fixed.
*** Bug 96878 has been marked as a duplicate of this bug. ***
*** Bug 88762 has been marked as a duplicate of this bug. ***