This bug exists since gcc version 6 The code bellow should not compile: #include <type_traits> struct A { int i:31; }; A a; //I am not sure the standard require that (a.i) and ++a.i have the same type. static_assert(!std::is_same_v <decltype ((a.i)), decltype(++a.i)>); // int& int:31& //but I do believe that decltype(a.i+=1) and decltype(++a.i) shall have the same type static_assert(!std::is_same_v <decltype ((a.i+=1)), decltype(++a.i)>); // int& int:31& [expr.pre.incr]/1 "The expression ++x is equivalent to x+=1." Actualy those weird "int:N" types cause a lot of trouble. This code cause assembler error: //test.cpp struct A{ int i:31; }; template <class T> void f(){ } int main(){ A a; f<decltype(a.i+=1)>(); f<decltype(++a.i)>(); return 0; } `c++ test.cpp` outputs: /tmp/ccTayNZZ.s: Assembler messages: /tmp/ccTayNZZ.s:43: Error: symbol `_Z1fIRiEvv' is already defined
Confirmed.
There is most likely a missing unlowered_expr_type somewhere in the decltype handling.
There is most likely a missing call to unlowered_expr_type somewhere, most likely in finish_unary_op_expr.
PR 84516 and PR 70733 are about other unary operations too (+ and -).
The trunk branch has been updated by Marek Polacek <mpolacek@gcc.gnu.org>: https://gcc.gnu.org/g:3a2257e6b3fa288d6c50831987949b9ff7dfb865 commit r12-5823-g3a2257e6b3fa288d6c50831987949b9ff7dfb865 Author: Marek Polacek <polacek@redhat.com> Date: Sat Dec 4 12:07:41 2021 -0500 c++: Fix for decltype and bit-fields [PR95009] Here, decltype deduces the wrong type for certain expressions involving bit-fields. Unlike in C, in C++ bit-field width is explicitly not part of the type, so I think decltype should never deduce to 'int:N'. The problem isn't that we're not calling unlowered_expr_type--we are--it's that is_bitfield_expr_with_lowered_type only handles certain codes, but not others. For example, += works fine but ++ does not. This also fixes decltype-bitfield2.C where we were crashing (!), but unfortunately it does not fix 84516 or 70733 where the problem is likely a missing call to unlowered_expr_type. It occurs to me now that typeof likely has had the same issue, but this patch should fix that too. PR c++/95009 gcc/cp/ChangeLog: * typeck.c (is_bitfield_expr_with_lowered_type) <case MODIFY_EXPR>: Handle UNARY_PLUS_EXPR, NEGATE_EXPR, NON_LVALUE_EXPR, BIT_NOT_EXPR, P*CREMENT_EXPR too. gcc/testsuite/ChangeLog: * g++.dg/cpp0x/decltype-bitfield1.C: New test. * g++.dg/cpp0x/decltype-bitfield2.C: New test.
Fixed on trunk so far, will backport to gcc 11.
The releases/gcc-11 branch has been updated by Marek Polacek <mpolacek@gcc.gnu.org>: https://gcc.gnu.org/g:e3fab19a79e3dc3cdf3e54ca20107e1dc15a3927 commit r11-9363-ge3fab19a79e3dc3cdf3e54ca20107e1dc15a3927 Author: Marek Polacek <polacek@redhat.com> Date: Sat Dec 4 12:07:41 2021 -0500 c++: Fix for decltype and bit-fields [PR95009] Here, decltype deduces the wrong type for certain expressions involving bit-fields. Unlike in C, in C++ bit-field width is explicitly not part of the type, so I think decltype should never deduce to 'int:N'. The problem isn't that we're not calling unlowered_expr_type--we are--it's that is_bitfield_expr_with_lowered_type only handles certain codes, but not others. For example, += works fine but ++ does not. This also fixes decltype-bitfield2.C where we were crashing (!), but unfortunately it does not fix 84516 or 70733 where the problem is likely a missing call to unlowered_expr_type. It occurs to me now that typeof likely has had the same issue, but this patch should fix that too. PR c++/95009 gcc/cp/ChangeLog: * typeck.c (is_bitfield_expr_with_lowered_type) <case MODIFY_EXPR>: Handle UNARY_PLUS_EXPR, NEGATE_EXPR, NON_LVALUE_EXPR, BIT_NOT_EXPR, P*CREMENT_EXPR too. gcc/testsuite/ChangeLog: * g++.dg/cpp0x/decltype-bitfield1.C: New test. * g++.dg/cpp0x/decltype-bitfield2.C: New test. (cherry picked from commit 3a2257e6b3fa288d6c50831987949b9ff7dfb865)
Fixed for GCC 11+.