Index: lit/SymbolFile/PDB/Inputs/TypeQualsTest.cpp =================================================================== --- /dev/null +++ lit/SymbolFile/PDB/Inputs/TypeQualsTest.cpp @@ -0,0 +1,46 @@ +// Rank > 0 array +typedef volatile int* RankNArray[10][100]; +RankNArray ArrayVar; + +typedef int __unaligned *UnalignedTypedef; +UnalignedTypedef UnVar; + +typedef long* __restrict RestrictTypedef; +RestrictTypedef RestrictVar; + +void Func1(const int* a, int const* b, const int ** const c, const int* const* d) { + return; +} + +void Func2(volatile int* a, int volatile* b) { + return; +} + +void Func3(int*& a, int& b, const int&c, int&& d) { + return; +} + +void Func4(int* __unaligned a, __unaligned int* b) { + return; +} + +void Func5(int a, int* __restrict b, int& __restrict c) { + return; +} + +void Func6(const volatile int* __restrict b) { + return; +} + +// LValue +typedef int& IntRef; +int x = 0; +IntRef IVar = x; + +// RValue +typedef int&& IIRef; +IIRef IIVar = int(1); + +int main() { + return 0; +} Index: lit/SymbolFile/PDB/type-quals.test =================================================================== --- /dev/null +++ lit/SymbolFile/PDB/type-quals.test @@ -0,0 +1,39 @@ +REQUIRES: windows +RUN: clang-cl -m32 /Z7 /c /GS- %S/Inputs/TypeQualsTest.cpp /o %T/TypeQualsTest.cpp.obj +RUN: link %T/TypeQualsTest.cpp.obj /DEBUG /nodefaultlib /ENTRY:main /OUT:%T/TypeQualsTest.cpp.exe +RUN: lldb-test symbols %T/TypeQualsTest.cpp.exe | FileCheck %s + +CHECK: Module [[MOD:.*]] +CHECK-DAG: {{^[0-9A-F]+}}: SymbolVendor ([[MOD]]) +CHECK: Type{{.*}} , name = "const int", size = 4, compiler_type = {{.*}} const int +CHECK: Type{{.*}} , size = 4, compiler_type = {{.*}} const int * +CHECK: Type{{.*}} , size = 4, compiler_type = {{.*}} const int **const +CHECK: Type{{.*}} , size = 4, compiler_type = {{.*}} const int *const +CHECK: Type{{.*}} , size = 4, compiler_type = {{.*}} const int *const * +CHECK: Type{{.*}} , name = "Func1", {{.*}}, compiler_type = {{.*}} void (const int *, const int *, const int **const, const int *const *) + +CHECK: Type{{.*}} , size = 4, compiler_type = {{.*}} volatile int * +CHECK: Type{{.*}} , name = "Func2", {{.*}}, compiler_type = {{.*}} void (volatile int *, volatile int *) + +CHECK: Type{{.*}} , size = 4, compiler_type = {{.*}} int * +CHECK: Type{{.*}} , size = 4, compiler_type = {{.*}} int *& +CHECK: Type{{.*}} , size = 4, compiler_type = {{.*}} int & +CHECK: Type{{.*}} , size = 4, compiler_type = {{.*}} const int & +CHECK: Type{{.*}} , size = 4, compiler_type = {{.*}} int && +CHECK: Type{{.*}} , name = "Func3", {{.*}}, compiler_type = {{.*}} void (int *&, int &, const int &, int &&) + +// FIXME: __unaligned is not supported. +CHECK: Type{{.*}} , name = "Func4", {{.*}}, compiler_type = {{.*}} void (int *, int *) + +CHECK: Type{{.*}} , size = 4, compiler_type = {{.*}} int *__restrict +CHECK: Type{{.*}} , size = 4, compiler_type = {{.*}} int &__restrict +CHECK: Type{{.*}} , name = "Func5", {{.*}}, compiler_type = {{.*}} void (int, int *__restrict, int &__restrict) + +CHECK: Type{{.*}} , name = "Func6", {{.*}}, compiler_type = {{.*}} void (const volatile int *__restrict) + +CHECK: Type{{.*}} , size = 400, compiler_type = {{.*}} volatile int *[100] +CHECK: Type{{.*}} , size = 4000, compiler_type = {{.*}} volatile int *[10][100] + +CHECK: Type{{.*}} , size = 4, compiler_type = {{.*}} long *__restrict + +CHECK-DAG: {{^[0-9A-F]+}}: CompileUnit{{[{]0x[0-9a-f]+[}]}}, language = "c++", file = '{{.*}}\TypeQualsTest.cpp' Index: source/Plugins/SymbolFile/PDB/PDBASTParser.cpp =================================================================== --- source/Plugins/SymbolFile/PDB/PDBASTParser.cpp +++ source/Plugins/SymbolFile/PDB/PDBASTParser.cpp @@ -288,6 +288,9 @@ m_ast.GetSymbolFile()->GetDeclContextForUID(target_type->GetID()); CompilerType ast_typedef = m_ast.CreateTypedefType(target_ast_type, name.c_str(), target_decl_ctx); + if (!ast_typedef) + return nullptr; + return std::make_shared( type_def->getSymIndexId(), m_ast.GetSymbolFile(), ConstString(name), bytes, nullptr, target_type->GetID(), @@ -361,20 +364,35 @@ auto array_type = llvm::dyn_cast(&type); assert(array_type); uint32_t num_elements = array_type->getCount(); - uint32_t element_uid = array_type->getElementType()->getSymIndexId(); + uint32_t element_uid = array_type->getElementTypeId(); uint32_t bytes = array_type->getLength(); + // If array rank > 0, PDB gives the element type at N=0. So element type + // will parsed in the order N=0, N=1,..., N=rank sequentially. lldb_private::Type *element_type = m_ast.GetSymbolFile()->ResolveTypeUID(element_uid); if (!element_type) return nullptr; - CompilerType element_ast_type = element_type->GetFullCompilerType(); + + CompilerType element_ast_type = element_type->GetForwardCompilerType(); + // If element type is UDT, it needs to be complete. + if (ClangASTContext::IsCXXClassType(element_ast_type) && + element_ast_type.GetCompleteType() == false) { + if (ClangASTContext::StartTagDeclarationDefinition(element_ast_type)) { + ClangASTContext::CompleteTagDeclarationDefinition(element_ast_type); + } else { + // We are not able to start defintion. + return nullptr; + } + } CompilerType array_ast_type = - m_ast.CreateArrayType(element_ast_type, num_elements, false); - return std::make_shared( + m_ast.CreateArrayType(element_ast_type, num_elements, /*is_gnu_vector*/false); + TypeSP type_sp = std::make_shared( array_type->getSymIndexId(), m_ast.GetSymbolFile(), ConstString(), bytes, nullptr, LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, array_ast_type, lldb_private::Type::eResolveStateFull); + type_sp->SetEncodingType(element_type); + return type_sp; } break; case PDB_SymType::BuiltinType: { auto *builtin_type = llvm::dyn_cast(&type); @@ -388,20 +406,17 @@ CompilerType builtin_ast_type = GetBuiltinTypeForPDBEncodingAndBitSize( &m_ast, builtin_type, encoding, bytes * 8); - Type::EncodingDataType encoding_data_type = Type::eEncodingIsUID; - if (builtin_type->isConstType()) { - encoding_data_type = Type::eEncodingIsConstUID; + if (builtin_type->isConstType()) builtin_ast_type = builtin_ast_type.AddConstModifier(); - } - if (builtin_type->isVolatileType()) { - encoding_data_type = Type::eEncodingIsVolatileUID; + + if (builtin_type->isVolatileType()) builtin_ast_type = builtin_ast_type.AddVolatileModifier(); - } + auto type_name = GetPDBBuiltinTypeName(builtin_type, builtin_ast_type); return std::make_shared( builtin_type->getSymIndexId(), m_ast.GetSymbolFile(), type_name, - bytes, nullptr, LLDB_INVALID_UID, encoding_data_type, + bytes, nullptr, LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, builtin_ast_type, lldb_private::Type::eResolveStateFull); } break; case PDB_SymType::PointerType: { @@ -413,18 +428,27 @@ return nullptr; CompilerType pointer_ast_type; - Type::EncodingDataType encoding_data_type = Type::eEncodingIsPointerUID; - if (pointer_type->isReference()) { - encoding_data_type = Type::eEncodingIsLValueReferenceUID; - pointer_ast_type = - pointee_type->GetFullCompilerType().GetLValueReferenceType(); - } else - pointer_ast_type = pointee_type->GetFullCompilerType().GetPointerType(); + pointer_ast_type = pointee_type->GetFullCompilerType(); + if (pointer_type->isReference()) + pointer_ast_type = pointer_ast_type.GetLValueReferenceType(); + else if (pointer_type->getRawSymbol().isRValueReference()) + pointer_ast_type = pointer_ast_type.GetRValueReferenceType(); + else + pointer_ast_type = pointer_ast_type.GetPointerType(); + + if (pointer_type->isConstType()) + pointer_ast_type = pointer_ast_type.AddConstModifier(); + + if (pointer_type->isVolatileType()) + pointer_ast_type = pointer_ast_type.AddVolatileModifier(); + + if (pointer_type->getRawSymbol().isRestrictedType()) + pointer_ast_type = pointer_ast_type.AddRestrictModifier(); return std::make_shared( pointer_type->getSymIndexId(), m_ast.GetSymbolFile(), ConstString(), pointer_type->getLength(), nullptr, LLDB_INVALID_UID, - encoding_data_type, decl, pointer_ast_type, + lldb_private::Type::eEncodingIsUID, decl, pointer_ast_type, lldb_private::Type::eResolveStateFull); } break; default: break;