https://gcc.gnu.org/bugzilla/show_bug.cgi?id=122968
Bug ID: 122968
Summary: bitfields do not have a location
Product: gcc
Version: 15.1.1
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c
Assignee: unassigned at gcc dot gnu.org
Reporter: woodard at redhat dot com
Target Milestone: ---
given:
#include <cassert>
struct t1 {
unsigned char x : 3;
unsigned char y : 5;
};
static_assert(sizeof(t1) == 1);
int main() {
t1 v1 = {5, 3};
auto &[a_var, b_var] = v1;
assert(a_var == 5);
a_var = 1;
assert(v1.x == 1);
}
there is no location for a_var or b_var
<2><cf>: Abbrev Number: 6 (DW_TAG_variable)
<d0> DW_AT_name : (indirect string, offset: 0x2c): a_var
<d4> DW_AT_decl_file : 1
<d4> DW_AT_decl_line : 9
<d4> DW_AT_decl_column : 12
<d5> DW_AT_type : <0x13e>
<2><d9>: Abbrev Number: 6 (DW_TAG_variable)
<da> DW_AT_name : (indirect string, offset: 0x14): b_var
<de> DW_AT_decl_file : 1
<de> DW_AT_decl_line : 9
<de> DW_AT_decl_column : 19
<df> DW_AT_type : <0x145>
...
<1><13e>: Abbrev Number: 1 (DW_TAG_base_type)
<13f> DW_AT_byte_size : 1
<140> DW_AT_encoding : 7 (unsigned)
<141> DW_AT_name : (indirect string, offset: 0x32): __unknown__
<1><145>: Abbrev Number: 1 (DW_TAG_base_type)
<146> DW_AT_byte_size : 1
<147> DW_AT_encoding : 7 (unsigned)
<148> DW_AT_name : (indirect string, offset: 0x32): __unknown__
even though it is not a proper language variable a consumer should treat it as
such and therefore it should have a location. For example clang does give it a
location expression:
<2><84>: Abbrev Number: 9 (DW_TAG_variable)
<85> DW_AT_location : 12 byte block: 91 70 6 94 1 10 3d 24 10 3d 25 9f
(DW_OP_fbreg: -16; DW_OP_deref; DW_OP_deref_size: 1; DW_OP_constu: 61;
DW_OP_shl; DW_OP_constu: 61; DW_OP_shr; DW_OP_stack_value)
<92> DW_AT_name : (indexed string: 0xd): a_var
<93> DW_AT_decl_file : 0
<94> DW_AT_decl_line : 9
<95> DW_AT_type : <0xce>
<2><99>: Abbrev Number: 9 (DW_TAG_variable)
<9a> DW_AT_location : 12 byte block: 91 70 6 94 1 10 38 24 10 3b 25 9f
(DW_OP_fbreg: -16; DW_OP_deref; DW_OP_deref_size: 1; DW_OP_constu: 56;
DW_OP_shl; DW_OP_constu: 59; DW_OP_shr; DW_OP_stack_value)
<a7> DW_AT_name : (indexed string: 0xe): b_var
<a8> DW_AT_decl_file : 0
<a9> DW_AT_decl_line : 9
<aa> DW_AT_type : <0xce>
...
<1><ce>: Abbrev Number: 6 (DW_TAG_base_type)
<cf> DW_AT_name : (indexed string: 0xa): unsigned char
<d0> DW_AT_encoding : 8 (unsigned char)
<d1> DW_AT_byte_size : 1
I don't think that the location that clang gives it is the best location
because the expression seems to assume that the generic type is 64b but at
least it has a location that a consumer can reference.
rather than doing the SHL SHR dance on a generic, I think a better location
expression would be:
for a_var:
(DW_OP_fbreg: -16; DW_OP_deref; DW_OP_deref_size: 1; DW_OP_bit_piece 3 0)
for b_var:
(DW_OP_fbreg: -16; DW_OP_deref; DW_OP_deref_size: 1; DW_OP_bit_piece 5 3)