[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