Bug 30260 - add support for pointer-to-member types
Summary: add support for pointer-to-member types
Status: RESOLVED FIXED
Alias: None
Product: libabigail
Classification: Unclassified
Component: default (show other bugs)
Version: unspecified
: P2 normal
Target Milestone: ---
Assignee: Dodji Seketeli
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2023-03-22 11:37 UTC by gprocida
Modified: 2023-12-01 16:04 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed: 2023-10-24 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description gprocida 2023-03-22 11:37:05 UTC
libabigail currently lacks support for pointer-to-member types.

These are very simple to model but there may be complexities around building type names and referring to their components (as no standardised naming seems to exist).

Useful references:

* https://eel.is/c++draft/expr.mptr.oper
* https://eel.is/c++draft/dcl.mptr - "there is no 'reference-to-member' type"
* https://en.cppreference.com/w/cpp/language/pointer#Pointers_to_members

Test case:

struct X {
  void f(int);
  int a;
};
struct Y;

int X::* pmi = &X::a;
void (X::* pmf)(int) = &X::f;
double X::* pmd;
char Y::* pmc;

typedef struct { int t; } T;
auto pmy = &T::t;

namespace {
struct Z { int z; };
}
int Z::* pmz = &Z::z;

union U { int u; };
auto pmu = &U::u;

typedef const U CU;
auto pmcu = &CU::u;

Model:

* no intrinsic name
* containing type (in practice: can be class/struct, union or typedef; after typedef resolution can be qualified or anonymous)
* (member) type

Naming:

$ c++decl declare x as pointer to member of class NAME function returning int  
int (NAME::*x)()
$ c++decl declare x as array 7 of pointer to member of class NAME int
int NAME::*x[7]

But this doesn't account for the more complex cases for NAME (see the test case above).

Component naming (for diff reporting):

¯\_(ツ)_/¯

Concrete representation in XML:

¯\_(ツ)_/¯
Comment 1 gprocida 2023-03-22 12:29:42 UTC
$ c++decl declare x as pointer to member of class NAME array 7 of int
int (NAME::*x)[7]
Comment 2 gprocida 2023-03-24 09:45:20 UTC
Naming of these types appears to follow all the same rules as naming normal pointer types, including when parentheses are needed.

pointer to: ... * ...

becomes

pointer to X member: ... X::* ...

Extra complications are:

1. the syntax immediately to the left of the * or X::* may need to be separated by a space

int*x; // no space needed before *
int X::*x; // space is needed before X
int (X::*x)(); // space would look odd inside the bracket

2. this is normally written as just the tag, without struct / class / union

but you might want to include the keyword for clarity or for simplicity of coding

int struct X::*x;
Comment 3 Dodji Seketeli 2023-10-24 15:24:27 UTC
Indeed, thank you for filing such a detailed enhancement request.  Libabigail needs to support this.
Comment 4 Ben Woodard 2023-10-24 15:43:49 UTC
Please note that pointer to member happens to be one of the challenging areas in DWARF5, I think it is fine in the underlying type system but if the pointer to member variable is passed as a parameter to a function and is in a register, then I believe that the DWARF to represent that is currently undefined.

DWARF6 is supposed to resolve that issue.

https://github.com/ccoutant/dwarf-locations/blob/f74b6d8b95ad5cfea80c4493f11e7dae441f02eb/location-description-on-the-dwarf-stack-concept-proposal.txt#L252
Comment 5 Dodji Seketeli 2023-11-30 16:35:21 UTC
I have started to add patches to support the pointer-to-member feature in the branch https://sourceware.org/git/?p=libabigail.git;a=shortlog;h=refs/heads/users/dodji/PR30260.

The code can be tested at this point, FWIW.
Comment 6 gprocida 2023-11-30 21:51:59 UTC
FWIW, STG diff output looks like this:

function symbol 'int struct S::* s2()' {_Z2s2v} was added

function symbol 'int s10(int struct S::*)' {_Z3s10M1Si} was added

function symbol 'void pmz_fun()' {_Z7pmz_funv} was added

variable symbol 'char struct Y::* pmc' was added

variable symbol 'int union U::* pmcu' was added

variable symbol 'double struct X::* pmd' was added

variable symbol 'void(struct X::* pmf)(struct X*, int)' was added

variable symbol 'int struct X::* pmi' was added

variable symbol 'int union U::* pmu' was added

variable symbol 'int struct { int t; }::* pmy' was added

variable symbol 'int struct S::* s0' was added

variable symbol 'int struct S::** s1' was added

variable symbol 'int struct S::*(* s3)()' was added

variable symbol 'int struct S::* s4[7]' was added

variable symbol 'int* struct S::* s5' was added

variable symbol 'int(* struct S::* s6)()' was added

variable symbol 'int(struct S::* s7)(struct S*)' was added

variable symbol 'int(struct S::* s8)[7]' was added

variable symbol 'const int struct S::* volatile s9' was added

variable symbol changed from 'char struct A::* diff' to 'int struct B::* diff'
  type changed from 'char struct A::*' to 'int struct B::*'
    containing type changed from 'struct A' to 'struct B'
    type changed from 'char' to 'int'

If you have any better ideas than "containing type" and "type", I might steal them. :-)

"pointed-to-member type"???
Comment 7 Dodji Seketeli 2023-12-01 16:03:30 UTC
Thanks.

The output of abidiff looks like this:

Functions changes summary: 0 Removed, 0 Changed, 0 Added function
Variables changes summary: 0 Removed, 1 Changed, 0 Added variable

1 Changed variable:

  [C] 'int S::* pm' was changed to 'char S::* pm' at test-ptr-to-mbr1-v1.cc:6:1:
    type of variable changed:
      pointer-to-member type changed from: 'int S::* to: 'char S::*'
      in data member type 'int' of pointed-to-member type 'int S::*':
        type name changed from 'int' to 'char'
        type size changed from 32 to 8 (in bits)
      in containing type 'struct S' of pointed-to-member type 'int S::*' at test-ptr-to-mbr1-v1.cc:1:1:
        type size changed from 32 to 8 (in bits)
        1 data member change:
          type of 'int m' changed:
            type name changed from 'int' to 'char'
            type size changed from 32 to 8 (in bits)

The output of the relevant tests are available at https://sourceware.org/git/?p=libabigail.git;a=tree;f=tests/data/test-abidiff-exit/pointer-to-member;h=61ced53e13335af7b31962b8a3736774be5b68db;hb=HEAD.

And one such output is:

https://sourceware.org/git/?p=libabigail.git;a=blob;f=tests/data/test-abidiff-exit/pointer-to-member/test-ptr-to-mbr1-output-1.txt;h=a88d96fbec1d301d52e57f5f6a6e233d97de62b1;hb=HEAD
Comment 8 Dodji Seketeli 2023-12-01 16:04:23 UTC
This feature should now be implemented by commit https://sourceware.org/git/?p=libabigail.git;a=commit;h=d4ca1088e4cdc4b3e4c3e67284458911c24a7c59 and should be available in libabigail 2.5.

Thank you for filing this enhancement request.