Introduce a way for Languages to specify whether values of "reference types" are "nil" (not pointing to anything) or uninitialized (never made to point at anything)
This latter determination may or may not be possible on a per-language basis; and neither is mandatory to implement for any language

Use this knowledge in the ValueObjectPrinter to generalize the notion of IsObjCNil() and the respective printout

llvm-svn: 252663
diff --git a/lldb/source/Core/ValueObject.cpp b/lldb/source/Core/ValueObject.cpp
index 7513555..fa3f1ff 100644
--- a/lldb/source/Core/ValueObject.cpp
+++ b/lldb/source/Core/ValueObject.cpp
@@ -2145,15 +2145,23 @@
 }
 
 bool
-ValueObject::IsObjCNil ()
+ValueObject::IsNilReference ()
 {
-    const uint32_t mask = eTypeIsObjC | eTypeIsPointer;
-    bool isObjCpointer = (((GetCompilerType().GetTypeInfo(NULL)) & mask) == mask);
-    if (!isObjCpointer)
-        return false;
-    bool canReadValue = true;
-    bool isZero = GetValueAsUnsigned(0,&canReadValue) == 0;
-    return canReadValue && isZero;
+    if (Language *language = Language::FindPlugin(GetObjectRuntimeLanguage()))
+    {
+        return language->IsNilReference(*this);
+    }
+    return false;
+}
+
+bool
+ValueObject::IsUninitializedReference ()
+{
+    if (Language *language = Language::FindPlugin(GetObjectRuntimeLanguage()))
+    {
+        return language->IsUninitializedReference(*this);
+    }
+    return false;
 }
 
 // This allows you to create an array member using and index
diff --git a/lldb/source/DataFormatters/ValueObjectPrinter.cpp b/lldb/source/DataFormatters/ValueObjectPrinter.cpp
index 4bc33fd..4289496 100644
--- a/lldb/source/DataFormatters/ValueObjectPrinter.cpp
+++ b/lldb/source/DataFormatters/ValueObjectPrinter.cpp
@@ -73,6 +73,7 @@
     assert (m_stream && "cannot print to a NULL Stream");
     m_should_print = eLazyBoolCalculate;
     m_is_nil = eLazyBoolCalculate;
+    m_is_uninit = eLazyBoolCalculate;
     m_is_ptr = eLazyBoolCalculate;
     m_is_ref = eLazyBoolCalculate;
     m_is_aggregate = eLazyBoolCalculate;
@@ -100,12 +101,12 @@
         
         PrintDecl();
     }
-    
+
     bool value_printed = false;
     bool summary_printed = false;
     
     m_val_summary_ok = PrintValueAndSummaryIfNeeded (value_printed,summary_printed);
-    
+
     if (m_val_summary_ok)
         PrintChildrenIfNeeded (value_printed, summary_printed);
     else
@@ -194,8 +195,8 @@
 ValueObjectPrinter::GetRootNameForDisplay (const char* if_fail)
 {
     const char *root_valobj_name = m_options.m_root_valobj_name.empty() ?
-    m_valobj->GetName().AsCString() :
-    m_options.m_root_valobj_name.c_str();
+        m_valobj->GetName().AsCString() :
+        m_options.m_root_valobj_name.c_str();
     return root_valobj_name ? root_valobj_name : if_fail;
 }
 
@@ -211,11 +212,19 @@
 ValueObjectPrinter::IsNil ()
 {
     if (m_is_nil == eLazyBoolCalculate)
-        m_is_nil = m_valobj->IsObjCNil() ? eLazyBoolYes : eLazyBoolNo;
+        m_is_nil = m_valobj->IsNilReference() ? eLazyBoolYes : eLazyBoolNo;
     return m_is_nil == eLazyBoolYes;
 }
 
 bool
+ValueObjectPrinter::IsUninitialized ()
+{
+    if (m_is_uninit == eLazyBoolCalculate)
+        m_is_uninit = m_valobj->IsUninitializedReference() ? eLazyBoolYes : eLazyBoolNo;
+    return m_is_uninit == eLazyBoolYes;
+}
+
+bool
 ValueObjectPrinter::IsPtr ()
 {
     if (m_is_ptr == eLazyBoolCalculate)
@@ -426,6 +435,8 @@
     {
         if (IsNil())
             summary.assign("nil");
+        else if (IsUninitialized())
+            summary.assign("<uninitialized>");
         else if (m_options.m_omit_summary_depth == 0)
         {
             TypeSummaryImpl* entry = GetSummaryFormatter();
@@ -476,7 +487,7 @@
             // the value if this thing is nil
             // (but show the value if the user passes a format explicitly)
             TypeSummaryImpl* entry = GetSummaryFormatter();
-            if (!IsNil() && !m_value.empty() && (entry == NULL || (entry->DoesPrintValue(m_valobj) || m_options.m_format != eFormatDefault) || m_summary.empty()) && !m_options.m_hide_value)
+            if (!IsNil() && !IsUninitialized() && !m_value.empty() && (entry == NULL || (entry->DoesPrintValue(m_valobj) || m_options.m_format != eFormatDefault) || m_summary.empty()) && !m_options.m_hide_value)
             {
                 if (m_options.m_hide_pointer_value && IsPointerValue(m_valobj->GetCompilerType())) {}
                 else
@@ -503,7 +514,7 @@
     if (ShouldPrintValueObject())
     {
         // let's avoid the overly verbose no description error for a nil thing
-        if (m_options.m_use_objc && !IsNil())
+        if (m_options.m_use_objc && !IsNil() && !IsUninitialized())
         {
             if (!m_options.m_hide_value || !m_options.m_hide_name)
                 m_stream->Printf(" ");
@@ -571,6 +582,10 @@
 {
     const bool is_ref = IsRef ();
     const bool is_ptr = IsPtr ();
+    const bool is_uninit = IsUninitialized();
+    
+    if (is_uninit)
+        return false;
     
     TypeSummaryImpl* entry = GetSummaryFormatter();
     
diff --git a/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp b/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp
index e8d008c..1cec626 100644
--- a/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp
+++ b/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp
@@ -863,3 +863,15 @@
     
     return false;
 }
+
+bool
+ObjCLanguage::IsNilReference (ValueObject& valobj)
+{
+    const uint32_t mask = eTypeIsObjC | eTypeIsPointer;
+    bool isObjCpointer = (((valobj.GetCompilerType().GetTypeInfo(nullptr)) & mask) == mask);
+    if (!isObjCpointer)
+        return false;
+    bool canReadValue = true;
+    bool isZero = valobj.GetValueAsUnsigned(0,&canReadValue) == 0;
+    return canReadValue && isZero;
+}
diff --git a/lldb/source/Plugins/Language/ObjC/ObjCLanguage.h b/lldb/source/Plugins/Language/ObjC/ObjCLanguage.h
index 0f96ff8..e30aa18 100644
--- a/lldb/source/Plugins/Language/ObjC/ObjCLanguage.h
+++ b/lldb/source/Plugins/Language/ObjC/ObjCLanguage.h
@@ -153,6 +153,9 @@
     GetFormatterPrefixSuffix (ValueObject& valobj, ConstString type_hint,
                               std::string& prefix, std::string& suffix) override;
     
+    bool
+    IsNilReference (ValueObject& valobj) override;
+    
     //------------------------------------------------------------------
     // Static Functions
     //------------------------------------------------------------------
diff --git a/lldb/source/Target/Language.cpp b/lldb/source/Target/Language.cpp
index 3a53a6b..2d75bde 100644
--- a/lldb/source/Target/Language.cpp
+++ b/lldb/source/Target/Language.cpp
@@ -358,6 +358,18 @@
     return eLazyBoolCalculate;
 }
 
+bool
+Language::IsNilReference (ValueObject& valobj)
+{
+    return false;
+}
+
+bool
+Language::IsUninitializedReference (ValueObject& valobj)
+{
+    return false;
+}
+
 //----------------------------------------------------------------------
 // Constructor
 //----------------------------------------------------------------------