Skip to content

USRGenerator doesn't handle MemberPointerType arguments in functions and template specializations #155082

@bkryza

Description

@bkryza

Current implementation of USRGenerator generates ambiguous USR values for declarations, which contain pointers to members or pointers to methods. I created a c-index-test compatible test case, which illustrates the issue. The test case as is passes to show what USR is generated for these declarations, but note that in particular the last 6 declarations, which are different, have the exact same USR.

The following test case can placed in clang/test/Index/USR/ and ran on latest LLVM repository build as:

build/bin/c-index-test core -print-source-symbols -- clang/test/Index/USR/member-pointer-types-as-arguments.cpp | build/bin/FileCheck clang/test/Index/USR/member-pointer-types-as-arguments.cpp

member-pointer-types-as-arguments.cpp:

// RUN: c-index-test core -print-source-symbols -- %s | FileCheck %s

template <typename T> struct A;
// CHECK: {{[0-9]+}}:30 | struct(Gen)/C++ | A | c:@ST>1#T@A |
// OK

template <typename R, typename Arg>
struct A<R (*)(Arg)> {};
// CHECK: {{[0-9]+}}:8 | struct(Gen,TPS)/C++ | A | c:@SP>2#T#T@A>#*Ft0.0(#t0.1) |
// OK

template<typename K, typename V> struct B;

template<typename M, typename C>
struct A<B<M,C>> {
};
// CHECK: {{[0-9]+}}:8 | struct(Gen,TPS)/C++ | A | c:@SP>2#T#T@A>#>@ST>2#T#T@B2t0.0t0.1 |
// OK

struct R {
    int *p;
};

void f(int*, int* R::* mp);
// CHECK: {{[0-9]+}}:6 | function/C | f | c:@F@f#*I# # |
// BAD - second argument is encoded as empty space

template<typename M, typename C>
struct A<M C::*> {
};
// CHECK: {{[0-9]+}}:8 | struct(Gen,TPS)/C++ | A | c:@SP>2#T#T@A>#  |
// BAD - template specialization argument is not encoded in USR
//       also note the additional empty space at the and of USR

template <typename M, typename C>
struct A<M (C::*)()> {
};
// CHECK: {{[0-9]+}}:8 | struct(Gen,TPS)/C++ | A | c:@SP>2#T#T@A># |
// BAD - template specialization argument is not encoded in USR

template <typename M, typename C, typename Arg>
struct A<M (C::*)(Arg)> {
};
// CHECK: {{[0-9]+}}:8 | struct(Gen,TPS)/C++ | A | c:@SP>3#T#T#T@A># |
// BAD - template specialization argument is not encoded in USR

template <typename M, typename C, typename Arg>
struct A<M (C::*)(Arg) const> {
};
// CHECK: {{[0-9]+}}:8 | struct(Gen,TPS)/C++ | A | c:@SP>3#T#T#T@A># |
// BAD - template specialization argument is not encoded in USR

template <typename M, typename C, typename Arg>
struct A<M (C::*)(Arg,Arg,Arg)> {
};
// CHECK: {{[0-9]+}}:8 | struct(Gen,TPS)/C++ | A | c:@SP>3#T#T#T@A># |
// BAD - template specialization argument is not encoded in USR

template <typename M, typename C, typename Arg>
struct A<M (C::*)(Arg) &> {
};
// CHECK: {{[0-9]+}}:8 | struct(Gen,TPS)/C++ | A | c:@SP>3#T#T#T@A># |
// BAD - template specialization argument is not encoded in USR

template <typename M, typename C, typename Arg>
struct A<M (C::*)(Arg) &&> {
};
// CHECK: {{[0-9]+}}:8 | struct(Gen,TPS)/C++ | A | c:@SP>3#T#T#T@A># |
// BAD - template specialization argument is not encoded in USR

template <typename M, typename C, typename Arg>
struct A<M (C::*)(Arg) const &> {
};
// CHECK: {{[0-9]+}}:8 | struct(Gen,TPS)/C++ | A | c:@SP>3#T#T#T@A># |
// BAD - template specialization argument is not encoded in USR

template <typename M, typename C, typename Arg>
struct A<M (C::*)(Arg) const &&> {
};
// CHECK: {{[0-9]+}}:8 | struct(Gen,TPS)/C++ | A | c:@SP>3#T#T#T@A># |
// BAD - template specialization argument is not encoded in USR

The question is, whether this behaviour is by design or is it an ommision in the USRGenerator::VisitType() implementation?

If it's the latter I'd be happy to contribute a fix for this. My use case is that I'd like to use USR for unique identification of declarations and types across multiple translation units, however at the momement it's not possible to this limitation...

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions