Index: lldb/include/lldb/Target/Language.h =================================================================== --- lldb/include/lldb/Target/Language.h +++ lldb/include/lldb/Target/Language.h @@ -211,6 +211,8 @@ // nil/null object, this method returns true virtual bool IsNilReference(ValueObject &valobj); + virtual llvm::StringRef NilReferenceSummaryString() { return {}; } + // for a ValueObject of some "reference type", if the language provides a // technique to decide whether the reference has ever been assigned to some // object, this method will return true if such detection is possible, and if Index: lldb/source/DataFormatters/ValueObjectPrinter.cpp =================================================================== --- lldb/source/DataFormatters/ValueObjectPrinter.cpp +++ lldb/source/DataFormatters/ValueObjectPrinter.cpp @@ -356,9 +356,14 @@ error.assign(err_cstr); if (ShouldPrintValueObject()) { - if (IsNil()) - summary.assign("nil"); - else if (IsUninitialized()) + if (IsNil()) { + lldb::LanguageType lang_type = + (m_options.m_varformat_language == lldb::eLanguageTypeUnknown) + ? m_valobj->GetPreferredDisplayLanguage() + : m_options.m_varformat_language; + Language *lang_plugin = Language::FindPlugin(lang_type); + summary.assign(lang_plugin->NilReferenceSummaryString().str()); + } else if (IsUninitialized()) summary.assign(""); else if (m_options.m_omit_summary_depth == 0) { TypeSummaryImpl *entry = GetSummaryFormatter(); Index: lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h =================================================================== --- lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h +++ lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h @@ -88,6 +88,10 @@ HardcodedFormatters::HardcodedSyntheticFinder GetHardcodedSynthetics() override; + bool IsNilReference(ValueObject &valobj) override; + + llvm::StringRef NilReferenceSummaryString() override { return "nullptr"; } + bool IsSourceFile(llvm::StringRef file_path) const override; const Highlighter *GetHighlighter() const override { return &m_highlighter; } Index: lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp =================================================================== --- lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp +++ lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp @@ -1134,6 +1134,16 @@ return g_formatters; } +bool CPlusPlusLanguage::IsNilReference(ValueObject &valobj) { + if (valobj.GetCompilerType().GetMinimumLanguage() != + eLanguageTypeC_plus_plus || + !valobj.IsPointerType()) + return false; + bool canReadValue = true; + bool isZero = valobj.GetValueAsUnsigned(0, &canReadValue) == 0; + return canReadValue && isZero; +} + bool CPlusPlusLanguage::IsSourceFile(llvm::StringRef file_path) const { const auto suffixes = {".cpp", ".cxx", ".c++", ".cc", ".c", ".h", ".hh", ".hpp", ".hxx", ".h++"}; Index: lldb/source/Plugins/Language/ObjC/ObjCLanguage.h =================================================================== --- lldb/source/Plugins/Language/ObjC/ObjCLanguage.h +++ lldb/source/Plugins/Language/ObjC/ObjCLanguage.h @@ -119,6 +119,8 @@ bool IsNilReference(ValueObject &valobj) override; + llvm::StringRef NilReferenceSummaryString() override { return "nil"; } + bool IsSourceFile(llvm::StringRef file_path) const override; const Highlighter *GetHighlighter() const override { return &m_highlighter; } Index: lldb/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.h =================================================================== --- lldb/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.h +++ lldb/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.h @@ -27,6 +27,8 @@ return lldb::eLanguageTypeObjC_plus_plus; } + llvm::StringRef NilReferenceSummaryString() override { return "nil"; } + bool IsSourceFile(llvm::StringRef file_path) const override; const Highlighter *GetHighlighter() const override { return &m_highlighter; } Index: lldb/test/API/commands/expression/import-std-module/forward_decl_from_module/TestForwardDeclFromStdModule.py =================================================================== --- lldb/test/API/commands/expression/import-std-module/forward_decl_from_module/TestForwardDeclFromStdModule.py +++ lldb/test/API/commands/expression/import-std-module/forward_decl_from_module/TestForwardDeclFromStdModule.py @@ -39,4 +39,4 @@ # Both `std::vector` and the type of the member have forward # declarations before their definitions. self.expect("expr --raw -- v", - substrs=['(std::__1::vector) $0 = {', 'f = 0x', '}']) + substrs=['(std::__1::vector) $0 = {', 'f = nullptr', '}']) Index: lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/string/TestDataFormatterLibcxxString.py =================================================================== --- lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/string/TestDataFormatterLibcxxString.py +++ lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/string/TestDataFormatterLibcxxString.py @@ -77,6 +77,7 @@ '(%s::u32string) u32_empty = ""'%ns, '(%s::basic_string, ' '%s::allocator >) uchar = "aaaaa"'%(ns,ns,ns), + '(%s::string *) null_str = nullptr'%ns, ]) self.runCmd("n") @@ -114,6 +115,7 @@ '(%s::u32string) u32_empty = ""'%ns, '(%s::basic_string, ' '%s::allocator >) uchar = "aaaaa"'%(ns,ns,ns), + '(%s::string *) null_str = nullptr'%ns, ]) # The test assumes that std::string is in its cap-size-data layout. Index: lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/string/main.cpp =================================================================== --- lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/string/main.cpp +++ lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/string/main.cpp @@ -74,6 +74,7 @@ std::u32string u32_string(U"🍄🍅🍆🍌"); std::u32string u32_empty(U""); std::basic_string uchar(5, 'a'); + std::string *null_str = nullptr; #if _LIBCPP_ABI_VERSION == 1 std::string garbage1, garbage2, garbage3, garbage4, garbage5; Index: lldb/test/API/lang/c/anonymous/TestAnonymous.py =================================================================== --- lldb/test/API/lang/c/anonymous/TestAnonymous.py +++ lldb/test/API/lang/c/anonymous/TestAnonymous.py @@ -62,7 +62,7 @@ # These should display correctly. self.expect("expression pz", VARIABLES_DISPLAYED_CORRECTLY, - substrs=["(type_z *) $", " = 0x0000"]) + substrs=["(type_z *) $", " = nullptr"]) self.expect("expression z.y", VARIABLES_DISPLAYED_CORRECTLY, substrs=["(type_y) $", "dummy = 2"])