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)

Reply via email to