Index: lldb/lit/SymbolFile/NativePDB/function-types-builtins.cpp =================================================================== --- lldb/lit/SymbolFile/NativePDB/function-types-builtins.cpp +++ lldb/lit/SymbolFile/NativePDB/function-types-builtins.cpp @@ -206,9 +206,9 @@ // FIXME: These currently don't work because clang-cl emits incorrect debug info // for std::nullptr_t. We should fix these in clang-cl. auto rae = &unaryret; -// CHECK: rae = +// CHECK: (nullptr_t (*)()) rae = {{.*}} auto aae = &unary; -// CHECK: (void (*)(...)) aae = {{.*}} +// CHECK: (void (*)(nullptr_t)) aae = {{.*}} int main(int argc, char **argv) { return 0; Index: lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp =================================================================== --- lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp +++ lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp @@ -673,8 +673,24 @@ pointer_ct, Type::eResolveStateFull); } +static bool IsStdNullptrT(TypeIndex ti) { + return ti.getSimpleMode() == SimpleTypeMode::NearPointer && + ti.getSimpleKind() == SimpleTypeKind::Void; +} + lldb::TypeSP SymbolFileNativePDB::CreateSimpleType(TypeIndex ti) { if (ti.getSimpleMode() != SimpleTypeMode::Direct) { + if (IsStdNullptrT(ti)) { + PdbSymUid uid = + PdbSymUid::makeTypeSymId(PDB_SymType::BuiltinType, ti, false); + CompilerType ct = m_clang->GetBasicType(eBasicTypeNullPtr); + Declaration decl; + return std::make_shared(uid.toOpaqueId(), this, + ConstString("std::nullptr_t"), 0, nullptr, + LLDB_INVALID_UID, Type::eEncodingIsUID, + decl, ct, Type::eResolveStateFull); + } + PdbSymUid uid = PdbSymUid::makeTypeSymId(PDB_SymType::PointerType, ti, false); TypeSP direct_sp = GetOrCreateType(ti.makeDirect()); @@ -694,10 +710,10 @@ return nullptr; } Declaration decl; - return std::make_shared(uid.toOpaqueId(), m_clang->GetSymbolFile(), - ConstString(), pointer_size, nullptr, - LLDB_INVALID_UID, Type::eEncodingIsUID, decl, - ct, Type::eResolveStateFull); + return std::make_shared(uid.toOpaqueId(), this, ConstString(), + pointer_size, nullptr, LLDB_INVALID_UID, + Type::eEncodingIsUID, decl, ct, + Type::eResolveStateFull); } PdbSymUid uid = PdbSymUid::makeTypeSymId(PDB_SymType::BuiltinType, ti, false); Index: llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp =================================================================== --- llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp @@ -1515,7 +1515,13 @@ case dwarf::DW_TAG_union_type: return lowerTypeUnion(cast(Ty)); case dwarf::DW_TAG_unspecified_type: - return TypeIndex::None(); + if (Ty->getName() != "decltype(nullptr)") + return TypeIndex::None(); + + // std::nullptr_t is specifically lowered using the pointer mode that + // doesn't indicate bit-width, presumably this is because std::nullptr_t + // is supposed to be compatible with any pointer type. + return TypeIndex(SimpleTypeKind::Void, SimpleTypeMode::NearPointer); default: // Use the null type index. return TypeIndex(); @@ -1983,8 +1989,8 @@ CO |= ClassOptions::Nested; // Put the Scoped flag on function-local types. MSVC puts this flag for enum - // type only when it has an immediate function scope. Clang never puts enums - // inside DILexicalBlock scopes. Enum types, as generated by clang, are + // type only when it has an immediate function scope. Clang never puts enums + // inside DILexicalBlock scopes. Enum types, as generated by clang, are // always in function, class, or file scopes. if (Ty->getTag() == dwarf::DW_TAG_enumeration_type) { if (ImmediateScope && isa(ImmediateScope)) Index: llvm/test/DebugInfo/COFF/types-std-nullptr-t.ll =================================================================== --- /dev/null +++ llvm/test/DebugInfo/COFF/types-std-nullptr-t.ll @@ -0,0 +1,42 @@ +; RUN: llc < %s -filetype=obj | llvm-readobj - -codeview | FileCheck %s + +; C++ source to regenerate: +; $ cat foo.cpp +; decltype(nullptr) NullPtr = nullptr; +; $ clang hello.cpp -S -emit-llvm -g -gcodeview -o t.ll + +; CHECK: CodeViewDebugInfo [ +; CHECK: Subsection [ +; CHECK: SubSectionType: Symbols (0xF1) +; CHECK: GlobalData { +; CHECK: Kind: S_GDATA32 (0x110D) +; CHECK: DataOffset: ?NullPtr@@3$$TA+0x0 +; CHECK: Type: void* (0x103) +; CHECK: DisplayName: NullPtr +; CHECK: LinkageName: ?NullPtr@@3$$TA +; CHECK: } + + +; ModuleID = 'foo.cpp' +source_filename = "foo.cpp" +target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-pc-windows-msvc19.15.26730" + +@"?NullPtr@@3$$TA" = dso_local global i8* null, align 8, !dbg !0 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!7, !8, !9, !10} +!llvm.ident = !{!11} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "NullPtr", linkageName: "?NullPtr@@3$$TA", scope: !2, file: !3, line: 1, type: !6, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !3, producer: "clang version 8.0.0 ", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None) +!3 = !DIFile(filename: "foo.cpp", directory: "D:\5Csrc\5Cllvmbuild\5Ccl\5CDebug\5Cx64", checksumkind: CSK_MD5, checksum: "0d5c7c9860a17e584808c03a24a135e6") +!4 = !{} +!5 = !{!0} +!6 = !DIBasicType(tag: DW_TAG_unspecified_type, name: "decltype(nullptr)") +!7 = !{i32 2, !"CodeView", i32 1} +!8 = !{i32 2, !"Debug Info Version", i32 3} +!9 = !{i32 1, !"wchar_size", i32 2} +!10 = !{i32 7, !"PIC Level", i32 2} +!11 = !{!"clang version 8.0.0 "} \ No newline at end of file