-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[LLDB][NativePDB] Use typedef compiler type for typedef types #156250
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 2 commits
a8c1e42
7c29cbb
7a89a4c
5fcae23
7bf7895
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
// REQUIRES: lld | ||
|
||
// Test that simple types can be found | ||
// RUN: %build --std=c++20 --nodefaultlib --compiler=clang-cl --arch=64 -o %t.exe -- %s | ||
// RUN: lldb-test symbols %t.exe | FileCheck %s | ||
|
||
bool *PB; | ||
bool &RB = *PB; | ||
bool *&RPB = PB; | ||
const bool &CRB = RB; | ||
bool *const BC = 0; | ||
const bool *const CBC = 0; | ||
|
||
long AL[2]; | ||
|
||
const volatile short CVS = 0; | ||
const short CS = 0; | ||
volatile short VS; | ||
|
||
struct ReturnedStruct1 {}; | ||
struct ReturnedStruct2 {}; | ||
|
||
struct MyStruct { | ||
static ReturnedStruct1 static_fn(char *) { return {}; } | ||
ReturnedStruct2 const_member_fn(char *) const { return {}; } | ||
void volatile_member_fn() volatile {}; | ||
void member_fn() {}; | ||
}; | ||
|
||
void (*PF)(int, bool *, const float, ...); | ||
|
||
|
||
using Func = void(char16_t, MyStruct &); | ||
Func *PF2; | ||
|
||
using SomeTypedef = long; | ||
SomeTypedef ST; | ||
|
||
int main() { | ||
bool b; | ||
char c; | ||
unsigned char uc; | ||
char8_t c8; | ||
|
||
short s; | ||
unsigned short us; | ||
wchar_t wc; | ||
char16_t c16; | ||
|
||
int i; | ||
unsigned int ui; | ||
long l; | ||
unsigned long ul; | ||
char32_t c32; | ||
|
||
long long ll; | ||
unsigned long long ull; | ||
|
||
float f; | ||
double d; | ||
|
||
MyStruct my_struct; | ||
|
||
decltype(nullptr) np; | ||
} | ||
|
||
// CHECK-DAG: Type{{.*}} , name = "std::nullptr_t", size = 0, compiler_type = 0x{{[0-9a-f]+}} nullptr_t | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here, the size of this type is 0. This is explicitly set in the code. The DIA plugin doesn't set the size to 0 if types are unsized (e.g. the function types below). I'm not sure if it's bad that the native plugin sets this to 0. When calling There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. FWIW, the DWARF plugin doesn't set the size explicitly to 0, in which case
Can we do the same? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure, I can do this in a followup PR. |
||
|
||
// CHECK-DAG: Type{{.*}} , name = "bool", size = 1, compiler_type = 0x{{[0-9a-f]+}} _Bool | ||
// CHECK-DAG: Type{{.*}} , name = "char", size = 1, compiler_type = 0x{{[0-9a-f]+}} char | ||
// CHECK-DAG: Type{{.*}} , name = "unsigned char", size = 1, compiler_type = 0x{{[0-9a-f]+}} unsigned char | ||
// CHECK-DAG: Type{{.*}} , name = "char8_t", size = 1, compiler_type = 0x{{[0-9a-f]+}} char8_t | ||
|
||
// CHECK-DAG: Type{{.*}} , size = 2, compiler_type = 0x{{[0-9a-f]+}} short | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing: |
||
|
||
// CHECK-DAG: Type{{.*}} , name = "unsigned short", size = 2, compiler_type = 0x{{[0-9a-f]+}} unsigned short | ||
// CHECK-DAG: Type{{.*}} , name = "wchar_t", size = 2, compiler_type = 0x{{[0-9a-f]+}} wchar_t | ||
// CHECK-DAG: Type{{.*}} , name = "char16_t", size = 2, compiler_type = 0x{{[0-9a-f]+}} char16_t | ||
|
||
// CHECK-DAG: Type{{.*}} , name = "int", size = 4, compiler_type = 0x{{[0-9a-f]+}} int | ||
// CHECK-DAG: Type{{.*}} , name = "unsigned", size = 4, compiler_type = 0x{{[0-9a-f]+}} unsigned int | ||
// CHECK-DAG: Type{{.*}} , name = "long", size = 4, compiler_type = 0x{{[0-9a-f]+}} long | ||
// CHECK-DAG: Type{{.*}} , name = "unsigned long", size = 4, compiler_type = 0x{{[0-9a-f]+}} unsigned long | ||
// CHECK-DAG: Type{{.*}} , name = "char32_t", size = 4, compiler_type = 0x{{[0-9a-f]+}} char32_t | ||
|
||
// CHECK-DAG: Type{{.*}} , name = "int64_t", size = 8, compiler_type = 0x{{[0-9a-f]+}} long long | ||
// CHECK-DAG: Type{{.*}} , name = "uint64_t", size = 8, compiler_type = 0x{{[0-9a-f]+}} unsigned long long | ||
Comment on lines
+86
to
+87
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing/incompatible: |
||
|
||
// CHECK-DAG: Type{{.*}} , name = "float", size = 4, compiler_type = 0x{{[0-9a-f]+}} float | ||
// CHECK-DAG: Type{{.*}} , name = "float", size = 4, compiler_type = 0x{{[0-9a-f]+}} const float | ||
// CHECK-DAG: Type{{.*}} , name = "double", size = 8, compiler_type = 0x{{[0-9a-f]+}} double | ||
|
||
// CHECK-DAG: Type{{.*}} , name = "ReturnedStruct1", size = 1, decl = simple-types.cpp:20, compiler_type = 0x{{[0-9a-f]+}} struct ReturnedStruct1 { | ||
// CHECK-DAG: Type{{.*}} , name = "ReturnedStruct2", size = 1, decl = simple-types.cpp:21, compiler_type = 0x{{[0-9a-f]+}} struct ReturnedStruct2 { | ||
// CHECK-DAG: Type{{.*}} , name = "MyStruct", size = 1, decl = simple-types.cpp:23, compiler_type = 0x{{[0-9a-f]+}} struct MyStruct { | ||
|
||
// CHECK-DAG: Type{{.*}} , size = 8, compiler_type = 0x{{[0-9a-f]+}} struct MyStruct *const | ||
// CHECK-DAG: Type{{.*}} , size = 8, compiler_type = 0x{{[0-9a-f]+}} const struct MyStruct *const | ||
// CHECK-DAG: Type{{.*}} , size = 8, compiler_type = 0x{{[0-9a-f]+}} volatile struct MyStruct *const | ||
// CHECK-DAG: Type{{.*}} , size = 8, compiler_type = 0x{{[0-9a-f]+}} struct MyStruct & | ||
|
||
// CHECK-DAG: Type{{.*}} , name = "bool", size = 1, compiler_type = 0x{{[0-9a-f]+}} const _Bool | ||
// CHECK-DAG: Type{{.*}} , size = 8, compiler_type = 0x{{[0-9a-f]+}} _Bool & | ||
// CHECK-DAG: Type{{.*}} , size = 8, compiler_type = 0x{{[0-9a-f]+}} _Bool * | ||
// CHECK-DAG: Type{{.*}} , size = 8, compiler_type = 0x{{[0-9a-f]+}} _Bool *& | ||
// CHECK-DAG: Type{{.*}} , size = 8, compiler_type = 0x{{[0-9a-f]+}} const _Bool & | ||
// CHECK-DAG: Type{{.*}} , size = 8, compiler_type = 0x{{[0-9a-f]+}} _Bool *const | ||
// CHECK-DAG: Type{{.*}} , size = 8, compiler_type = 0x{{[0-9a-f]+}} const _Bool *const | ||
|
||
// CHECK-DAG: Type{{.*}} , size = 2, compiler_type = 0x{{[0-9a-f]+}} const volatile short | ||
// CHECK-DAG: Type{{.*}} , size = 2, compiler_type = 0x{{[0-9a-f]+}} const short | ||
// CHECK-DAG: Type{{.*}} , size = 2, compiler_type = 0x{{[0-9a-f]+}} volatile short | ||
|
||
// CHECK-DAG: Type{{.*}} , name = "SomeTypedef", size = 4, compiler_type = 0x{{[0-9a-f]+}} typedef SomeTypedef | ||
// CHECK-DAG: Type{{.*}} , name = "Func", size = 0, compiler_type = 0x{{[0-9a-f]+}} typedef Func | ||
|
||
// CHECK-DAG: Type{{.*}} , size = 0, compiler_type = 0x{{[0-9a-f]+}} int (void) | ||
// CHECK-DAG: Type{{.*}} , size = 0, compiler_type = 0x{{[0-9a-f]+}} void (void) | ||
|
||
// CHECK-DAG: Type{{.*}} , size = 0, compiler_type = 0x{{[0-9a-f]+}} void (int, _Bool *, const float, ...) | ||
// CHECK-DAG: Type{{.*}} , size = 8, compiler_type = 0x{{[0-9a-f]+}} void (*)(int, _Bool *, const float, ...) | ||
|
||
// CHECK-DAG: Type{{.*}} , size = 0, compiler_type = 0x{{[0-9a-f]+}} void (char16_t, struct MyStruct &) | ||
// CHECK-DAG: Type{{.*}} , size = 8, compiler_type = 0x{{[0-9a-f]+}} void (*)(char16_t, struct MyStruct &) | ||
|
||
// CHECK-DAG: Type{{.*}} , size = 0, compiler_type = 0x{{[0-9a-f]+}} struct ReturnedStruct1 (char *) | ||
// CHECK-DAG: Type{{.*}} , size = 0, compiler_type = 0x{{[0-9a-f]+}} struct ReturnedStruct2 (char *) | ||
|
||
// CHECK-DAG: Type{{.*}} , size = 8, compiler_type = 0x{{[0-9a-f]+}} long[2] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This feels a bit wrong, because
PdbAstParser::GetOrCreateTypedefDecl
already knows this compiler type. However, it returns a decl, so we need to go back through the AST to resolve the type.The method isn't used elsewhere, so the return type could be changed to a
CompilerType
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What use does
GetOrCreateType
have here? If that's not the thing that creates the correctTypedefType
? Or in other words, could you elaborate on how this fixes the issue?Is it that
GetOrCreateTypedefDecl
creates a new decl, but the associatedTypedefType
is different from the type created byGetOrCreateType
? Does that mean we create two different typedefs?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I left out the confusing/unintuitive part:
Currently, in the PDBs produced by both MSVC and LLVM, type aliases are not in the "type system" (TPI stream/
LF_*
records; https://redirect.github.com/llvm/llvm-project/pull/153936 attempts to change this in LLVM).GetOrCreateType
looks in the PDB type stream TPI. The typedefs we currently have are fromS_UDT
records in the globals stream, so they're represented as "symbols" andGetOrCreateType
would not be able to create the type.Because of this, they're handled differently.
No,
clang::ASTContext::getTypeDeclType
will useTypeForDecl
to get back to the type.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah I see, thanks for the context
So what does
GetOrCreateType
achieve in this case? If it's not able to create theTypedefType
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I see what you mean. The
GetOrCreateType(udt.Type)
above creates the typedef'd type. So forusing Foo = Bar
, it would get/createBar
.