[Lldb-commits] [lldb] 406ad18 - [lldb/DataFormatters] Display null C++ pointers as nullptr
Jonas Devlieghere via lldb-commits
lldb-commits at lists.llvm.org
Thu Nov 12 15:24:14 PST 2020
Author: Jonas Devlieghere
Date: 2020-11-12T15:24:06-08:00
New Revision: 406ad187486b4277fc82a2c0714ae53396e47928
URL: https://github.com/llvm/llvm-project/commit/406ad187486b4277fc82a2c0714ae53396e47928
DIFF: https://github.com/llvm/llvm-project/commit/406ad187486b4277fc82a2c0714ae53396e47928.diff
LOG: [lldb/DataFormatters] Display null C++ pointers as nullptr
Display null pointer as `nullptr`, `nil` and `NULL` for C++,
Objective-C/Objective-C++ and C respectively. The original motivation
for this patch was to display a null std::string pointer as nullptr
instead of "", but the fix seemed generic enough to be done for all
summary providers.
Differential revision: https://reviews.llvm.org/D77153
Added:
lldb/test/API/lang/objcxx/objc-builtin-types/Makefile
lldb/test/API/lang/objcxx/objc-builtin-types/TestObjCBuiltinTypes.py
lldb/test/API/lang/objcxx/objc-builtin-types/main.cpp
Modified:
lldb/include/lldb/Target/Language.h
lldb/source/DataFormatters/ValueObjectPrinter.cpp
lldb/source/Expression/UserExpression.cpp
lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h
lldb/source/Plugins/Language/ObjC/ObjCLanguage.h
lldb/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.h
lldb/test/API/commands/expression/import-std-module/forward_decl_from_module/TestForwardDeclFromStdModule.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/main.cpp
lldb/test/API/lang/c/anonymous/TestAnonymous.py
Removed:
lldb/test/API/lang/objc/objc-builtin-types/Makefile
lldb/test/API/lang/objc/objc-builtin-types/TestObjCBuiltinTypes.py
lldb/test/API/lang/objc/objc-builtin-types/main.cpp
################################################################################
diff --git a/lldb/include/lldb/Target/Language.h b/lldb/include/lldb/Target/Language.h
index 9dc9df363d79..6368828e36da 100644
--- a/lldb/include/lldb/Target/Language.h
+++ b/lldb/include/lldb/Target/Language.h
@@ -211,6 +211,10 @@ class Language : public PluginInterface {
// nil/null object, this method returns true
virtual bool IsNilReference(ValueObject &valobj);
+ /// Returns the summary string for ValueObjects for which IsNilReference() is
+ /// true.
+ virtual llvm::StringRef GetNilReferenceSummaryString() { 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
diff --git a/lldb/source/DataFormatters/ValueObjectPrinter.cpp b/lldb/source/DataFormatters/ValueObjectPrinter.cpp
index c8a306334cf5..082ad344d2d1 100644
--- a/lldb/source/DataFormatters/ValueObjectPrinter.cpp
+++ b/lldb/source/DataFormatters/ValueObjectPrinter.cpp
@@ -355,22 +355,33 @@ void ValueObjectPrinter::GetValueSummaryError(std::string &value,
if (err_cstr)
error.assign(err_cstr);
- if (ShouldPrintValueObject()) {
- if (IsNil())
- summary.assign("nil");
- else if (IsUninitialized())
- summary.assign("<uninitialized>");
- else if (m_options.m_omit_summary_depth == 0) {
- TypeSummaryImpl *entry = GetSummaryFormatter();
- if (entry)
- m_valobj->GetSummaryAsCString(entry, summary,
- m_options.m_varformat_language);
- else {
- const char *sum_cstr =
- m_valobj->GetSummaryAsCString(m_options.m_varformat_language);
- if (sum_cstr)
- summary.assign(sum_cstr);
- }
+ if (!ShouldPrintValueObject())
+ return;
+
+ if (IsNil()) {
+ lldb::LanguageType lang_type =
+ (m_options.m_varformat_language == lldb::eLanguageTypeUnknown)
+ ? m_valobj->GetPreferredDisplayLanguage()
+ : m_options.m_varformat_language;
+ if (Language *lang_plugin = Language::FindPlugin(lang_type)) {
+ summary.assign(lang_plugin->GetNilReferenceSummaryString().str());
+ } else {
+ // We treat C as the fallback language rather than as a separate Language
+ // plugin.
+ summary.assign("NULL");
+ }
+ } else if (IsUninitialized()) {
+ summary.assign("<uninitialized>");
+ } else if (m_options.m_omit_summary_depth == 0) {
+ TypeSummaryImpl *entry = GetSummaryFormatter();
+ if (entry) {
+ m_valobj->GetSummaryAsCString(entry, summary,
+ m_options.m_varformat_language);
+ } else {
+ const char *sum_cstr =
+ m_valobj->GetSummaryAsCString(m_options.m_varformat_language);
+ if (sum_cstr)
+ summary.assign(sum_cstr);
}
}
}
@@ -403,7 +414,9 @@ bool ValueObjectPrinter::PrintValueAndSummaryIfNeeded(bool &value_printed,
// this thing is nil (but show the value if the user passes a format
// explicitly)
TypeSummaryImpl *entry = GetSummaryFormatter();
- if (!IsNil() && !IsUninitialized() && !m_value.empty() &&
+ const bool has_nil_or_uninitialized_summary =
+ (IsNil() || IsUninitialized()) && !m_summary.empty();
+ if (!has_nil_or_uninitialized_summary && !m_value.empty() &&
(entry == nullptr ||
(entry->DoesPrintValue(m_valobj) ||
m_options.m_format != eFormatDefault) ||
diff --git a/lldb/source/Expression/UserExpression.cpp b/lldb/source/Expression/UserExpression.cpp
index 47d13f052bfb..5beed4657b37 100644
--- a/lldb/source/Expression/UserExpression.cpp
+++ b/lldb/source/Expression/UserExpression.cpp
@@ -358,6 +358,7 @@ UserExpression::Evaluate(ExecutionContext &exe_ctx,
} else {
if (expr_result) {
result_valobj_sp = expr_result->GetValueObject();
+ result_valobj_sp->SetPreferredDisplayLanguage(language);
LLDB_LOG(log,
"== [UserExpression::Evaluate] Execution completed "
diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
index 83a140ebd5e7..d844498fd8a3 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
@@ -1134,6 +1134,15 @@ CPlusPlusLanguage::GetHardcodedSynthetics() {
return g_formatters;
}
+bool CPlusPlusLanguage::IsNilReference(ValueObject &valobj) {
+ if (!Language::LanguageIsCPlusPlus(valobj.GetObjectRuntimeLanguage()) ||
+ !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++"};
diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h
index 89dea08a2c53..e2b5d2918753 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h
+++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h
@@ -88,6 +88,10 @@ class CPlusPlusLanguage : public Language {
HardcodedFormatters::HardcodedSyntheticFinder
GetHardcodedSynthetics() override;
+ bool IsNilReference(ValueObject &valobj) override;
+
+ llvm::StringRef GetNilReferenceSummaryString() override { return "nullptr"; }
+
bool IsSourceFile(llvm::StringRef file_path) const override;
const Highlighter *GetHighlighter() const override { return &m_highlighter; }
diff --git a/lldb/source/Plugins/Language/ObjC/ObjCLanguage.h b/lldb/source/Plugins/Language/ObjC/ObjCLanguage.h
index bed62a5c447a..02c15e86046b 100644
--- a/lldb/source/Plugins/Language/ObjC/ObjCLanguage.h
+++ b/lldb/source/Plugins/Language/ObjC/ObjCLanguage.h
@@ -119,6 +119,8 @@ class ObjCLanguage : public Language {
bool IsNilReference(ValueObject &valobj) override;
+ llvm::StringRef GetNilReferenceSummaryString() override { return "nil"; }
+
bool IsSourceFile(llvm::StringRef file_path) const override;
const Highlighter *GetHighlighter() const override { return &m_highlighter; }
diff --git a/lldb/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.h b/lldb/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.h
index 4b3d23653347..233fd5c00a7a 100644
--- a/lldb/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.h
+++ b/lldb/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.h
@@ -27,6 +27,8 @@ class ObjCPlusPlusLanguage : public Language {
return lldb::eLanguageTypeObjC_plus_plus;
}
+ llvm::StringRef GetNilReferenceSummaryString() override { return "nil"; }
+
bool IsSourceFile(llvm::StringRef file_path) const override;
const Highlighter *GetHighlighter() const override { return &m_highlighter; }
diff --git a/lldb/test/API/commands/expression/import-std-module/forward_decl_from_module/TestForwardDeclFromStdModule.py b/lldb/test/API/commands/expression/import-std-module/forward_decl_from_module/TestForwardDeclFromStdModule.py
index 4ed1271aa8a7..e3b3705c332a 100644
--- a/lldb/test/API/commands/expression/import-std-module/forward_decl_from_module/TestForwardDeclFromStdModule.py
+++ b/lldb/test/API/commands/expression/import-std-module/forward_decl_from_module/TestForwardDeclFromStdModule.py
@@ -39,4 +39,4 @@ def test(self):
# Both `std::vector` and the type of the member have forward
# declarations before their definitions.
self.expect("expr --raw -- v",
- substrs=['(std::__1::vector<int>) $0 = {', 'f = 0x', '}'])
+ substrs=['(std::__1::vector<int>) $0 = {', 'f = nullptr', '}'])
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/string/TestDataFormatterLibcxxString.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/string/TestDataFormatterLibcxxString.py
index 0f6d8a4ac3cf..93e3a2ca1a9e 100644
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/string/TestDataFormatterLibcxxString.py
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/string/TestDataFormatterLibcxxString.py
@@ -80,6 +80,7 @@ def cleanup():
'(%s::u32string) u32_empty = ""'%ns,
'(%s::basic_string<unsigned char, %s::char_traits<unsigned char>, '
'%s::allocator<unsigned char> >) uchar = "aaaaa"'%(ns,ns,ns),
+ '(%s::string *) null_str = nullptr'%ns,
])
self.runCmd("n")
@@ -117,6 +118,7 @@ def cleanup():
'(%s::u32string) u32_empty = ""'%ns,
'(%s::basic_string<unsigned char, %s::char_traits<unsigned char>, '
'%s::allocator<unsigned char> >) uchar = "aaaaa"'%(ns,ns,ns),
+ '(%s::string *) null_str = nullptr'%ns,
])
# The test assumes that std::string is in its cap-size-data layout.
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/string/main.cpp b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/string/main.cpp
index e9a3a4bd8bbd..365af0522c11 100644
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/string/main.cpp
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/string/main.cpp
@@ -74,6 +74,7 @@ int main()
std::u32string u32_string(U"🍄🍅🍆🍌");
std::u32string u32_empty(U"");
std::basic_string<unsigned char> uchar(5, 'a');
+ std::string *null_str = nullptr;
#if _LIBCPP_ABI_VERSION == 1
std::string garbage1, garbage2, garbage3, garbage4, garbage5;
diff --git a/lldb/test/API/lang/c/anonymous/TestAnonymous.py b/lldb/test/API/lang/c/anonymous/TestAnonymous.py
index 69e23e3510b6..a89c0e83d24c 100644
--- a/lldb/test/API/lang/c/anonymous/TestAnonymous.py
+++ b/lldb/test/API/lang/c/anonymous/TestAnonymous.py
@@ -62,7 +62,7 @@ def test_expr_parent(self):
# These should display correctly.
self.expect("expression pz", VARIABLES_DISPLAYED_CORRECTLY,
- substrs=["(type_z *) $", " = 0x0000"])
+ substrs=["(type_z *) $", " = NULL"])
self.expect("expression z.y", VARIABLES_DISPLAYED_CORRECTLY,
substrs=["(type_y) $", "dummy = 2"])
diff --git a/lldb/test/API/lang/objc/objc-builtin-types/Makefile b/lldb/test/API/lang/objcxx/objc-builtin-types/Makefile
similarity index 100%
rename from lldb/test/API/lang/objc/objc-builtin-types/Makefile
rename to lldb/test/API/lang/objcxx/objc-builtin-types/Makefile
diff --git a/lldb/test/API/lang/objc/objc-builtin-types/TestObjCBuiltinTypes.py b/lldb/test/API/lang/objcxx/objc-builtin-types/TestObjCBuiltinTypes.py
similarity index 88%
rename from lldb/test/API/lang/objc/objc-builtin-types/TestObjCBuiltinTypes.py
rename to lldb/test/API/lang/objcxx/objc-builtin-types/TestObjCBuiltinTypes.py
index 2e6f6a5274dd..7e7ac75ae948 100644
--- a/lldb/test/API/lang/objc/objc-builtin-types/TestObjCBuiltinTypes.py
+++ b/lldb/test/API/lang/objcxx/objc-builtin-types/TestObjCBuiltinTypes.py
@@ -1,7 +1,5 @@
"""Test that the expression parser doesn't get confused by 'id' and 'Class'"""
-
-
import lldb
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
@@ -21,7 +19,6 @@ def setUp(self):
self.main_source, '// Set breakpoint here.')
@add_test_categories(['pyapi'])
- #<rdar://problem/10591460> [regression] Can't print ivar value: error: reference to 'id' is ambiguous
def test_with_python_api(self):
"""Test expression parser respect for ObjC built-in types."""
self.build()
@@ -57,4 +54,7 @@ def test_with_python_api(self):
self.expect("expr (foo)", patterns=["\(ns::id\) \$.* = 0"])
- self.expect("expr id my_id = 0; my_id", patterns=["\(id\) \$.* = nil"])
+ self.expect("expr --language Objective-C++ -- id my_id = 0; my_id",
+ patterns=["\(id\) \$.* = nil"])
+ self.expect("expr --language C++ -- id my_id = 0; my_id",
+ patterns=["\(id\) \$.* = nullptr"])
diff --git a/lldb/test/API/lang/objc/objc-builtin-types/main.cpp b/lldb/test/API/lang/objcxx/objc-builtin-types/main.cpp
similarity index 100%
rename from lldb/test/API/lang/objc/objc-builtin-types/main.cpp
rename to lldb/test/API/lang/objcxx/objc-builtin-types/main.cpp
More information about the lldb-commits
mailing list