Synthetic values are now automatically enabled and active by default. SBValue is set up to always wrap a synthetic value when one is available.
A new setting enable-synthetic-value is provided on the target to disable this behavior.
There also is a new GetNonSyntheticValue() API call on SBValue to go back from synthetic to non-synthetic. There is no call to go from non-synthetic to synthetic.
The test suite has been changed accordingly.
Fallout from changes to type searching: an hack has to be played to make it possible to use maps that contain std::string due to the special name replacement operated by clang
Fixing a test case that was using libstdcpp instead of libc++ - caught as a consequence of said changes to type searching


git-svn-id: https://llvm.org/svn/llvm-project/lldb/trunk@153495 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/API/SBValue.cpp b/source/API/SBValue.cpp
index c5a5fd2..b28004c 100644
--- a/source/API/SBValue.cpp
+++ b/source/API/SBValue.cpp
@@ -51,21 +51,23 @@
 {
 }
 
-SBValue::SBValue (const lldb::ValueObjectSP &value_sp) :
-    m_opaque_sp (value_sp)
+SBValue::SBValue (const lldb::ValueObjectSP &value_sp)
 {
+    SetSP(value_sp); // whenever setting the SP call SetSP() since it knows how to deal with synthetic values properly
 }
 
-SBValue::SBValue(const SBValue &rhs) :
-    m_opaque_sp (rhs.m_opaque_sp)
+SBValue::SBValue(const SBValue &rhs)
 {
+    SetSP(rhs.m_opaque_sp); // whenever setting the SP call SetSP() since it knows how to deal with synthetic values properly
 }
 
 SBValue &
 SBValue::operator = (const SBValue &rhs)
 {
     if (this != &rhs)
-        m_opaque_sp = rhs.m_opaque_sp;
+    {
+        SetSP(rhs.m_opaque_sp); // whenever setting the SP call SetSP() since it knows how to deal with synthetic values properly
+    }
     return *this;
 }
 
@@ -809,6 +811,30 @@
     return SBValue();
 }
 
+lldb::SBValue
+SBValue::GetNonSyntheticValue ()
+{
+    SBValue sb_value;
+    lldb::ValueObjectSP value_sp(GetSP());
+    if (value_sp)
+    {
+        if (value_sp->IsSynthetic())
+        {
+            TargetSP target_sp(value_sp->GetTargetSP());
+            if (target_sp)
+            {
+                Mutex::Locker api_locker (target_sp->GetAPIMutex());
+                // deliberately breaking the rules here to optimize the case where we DO NOT want
+                // the synthetic value to be returned to the user - if we did not do this, we would have to tell
+                // the target to suppress the synthetic value, and then return the flag to its original value
+                if (value_sp->GetParent())
+                    sb_value.m_opaque_sp = value_sp->GetParent()->GetSP();
+            }
+        }
+    }
+    return sb_value;
+}
+
 bool
 SBValue::IsDynamic()
 {
@@ -1124,6 +1150,8 @@
 SBValue::SetSP (const lldb::ValueObjectSP &sp)
 {
     m_opaque_sp = sp;
+    if (IsValid() && m_opaque_sp->HasSyntheticValue())
+        m_opaque_sp = m_opaque_sp->GetSyntheticValue();
 }
 
 
diff --git a/source/Core/Debugger.cpp b/source/Core/Debugger.cpp
index 6b93aa9..d7f1460 100644
--- a/source/Core/Debugger.cpp
+++ b/source/Core/Debugger.cpp
@@ -1164,7 +1164,8 @@
                                 
                                 if (*var_name_begin == 's')
                                 {
-                                    valobj = valobj->GetSyntheticValue().get();
+                                    if (!valobj->IsSynthetic())
+                                        valobj = valobj->GetSyntheticValue().get();
                                     if (!valobj)
                                         break;
                                     var_name_begin++;
diff --git a/source/Core/FormatManager.cpp b/source/Core/FormatManager.cpp
index 0496780..693ae26 100644
--- a/source/Core/FormatManager.cpp
+++ b/source/Core/FormatManager.cpp
@@ -639,18 +639,24 @@
     SyntheticChildren::Flags stl_synth_flags;
     stl_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences(false);
     
-    gnu_category_sp->GetRegexSyntheticNavigator()->Add(RegularExpressionSP(new RegularExpression("^(std::)?vector<.+>$")),
+    gnu_category_sp->GetRegexSyntheticNavigator()->Add(RegularExpressionSP(new RegularExpression("^std::vector<.+>(( )?&)?$")),
                                                        SyntheticChildrenSP(new TypeSyntheticImpl(stl_synth_flags,
                                                                                                  "gnu_libstdcpp.StdVectorSynthProvider")));
-    gnu_category_sp->GetRegexSyntheticNavigator()->Add(RegularExpressionSP(new RegularExpression("^(std::)?map<.+> >$")),
+    gnu_category_sp->GetRegexSyntheticNavigator()->Add(RegularExpressionSP(new RegularExpression("^std::map<.+> >(( )?&)?$")),
                                                        SyntheticChildrenSP(new TypeSyntheticImpl(stl_synth_flags,
                                                                                                  "gnu_libstdcpp.StdMapSynthProvider")));
-    gnu_category_sp->GetRegexSyntheticNavigator()->Add(RegularExpressionSP(new RegularExpression("^(std::)?list<.+>$")),
+    gnu_category_sp->GetRegexSyntheticNavigator()->Add(RegularExpressionSP(new RegularExpression("^std::list<.+>(( )?&)?$")),
                                                        SyntheticChildrenSP(new TypeSyntheticImpl(stl_synth_flags,
                                                                                                  "gnu_libstdcpp.StdListSynthProvider")));
     
     stl_summary_flags.SetDontShowChildren(false);
-    gnu_category_sp->GetRegexSummaryNavigator()->Add(RegularExpressionSP(new RegularExpression("^(std::)?vector<.+>$")),
+    gnu_category_sp->GetRegexSummaryNavigator()->Add(RegularExpressionSP(new RegularExpression("^std::vector<.+>(( )?&)?$")),
+                                                     TypeSummaryImplSP(new StringSummaryFormat(stl_summary_flags,
+                                                                                               "size=${svar%#}")));
+    gnu_category_sp->GetRegexSummaryNavigator()->Add(RegularExpressionSP(new RegularExpression("^std::map<.+> >(( )?&)?$")),
+                                                     TypeSummaryImplSP(new StringSummaryFormat(stl_summary_flags,
+                                                                                               "size=${svar%#}")));
+    gnu_category_sp->GetRegexSummaryNavigator()->Add(RegularExpressionSP(new RegularExpression("^std::list<.+>(( )?&)?$")),
                                                      TypeSummaryImplSP(new StringSummaryFormat(stl_summary_flags,
                                                                                                "size=${svar%#}")));
 #endif
@@ -682,22 +688,22 @@
     SyntheticChildren::Flags stl_synth_flags;
     stl_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences(false);
     
-    libcxx_category_sp->GetRegexSyntheticNavigator()->Add(RegularExpressionSP(new RegularExpression("^(std::__1::)vector<.+>$")),
+    libcxx_category_sp->GetRegexSyntheticNavigator()->Add(RegularExpressionSP(new RegularExpression("^std::__1::vector<.+>(( )?&)?$")),
                                                        SyntheticChildrenSP(new TypeSyntheticImpl(stl_synth_flags,
                                                                                                  "libcxx.stdvector_SynthProvider")));
-    libcxx_category_sp->GetRegexSyntheticNavigator()->Add(RegularExpressionSP(new RegularExpression("^(std::__1::)list<.+>$")),
+    libcxx_category_sp->GetRegexSyntheticNavigator()->Add(RegularExpressionSP(new RegularExpression("^std::__1::list<.+>(( )?&)?$")),
                                                        SyntheticChildrenSP(new TypeSyntheticImpl(stl_synth_flags,
                                                                                                  "libcxx.stdlist_SynthProvider")));
-    libcxx_category_sp->GetRegexSyntheticNavigator()->Add(RegularExpressionSP(new RegularExpression("^(std::__1::)map<.+> >$")),
+    libcxx_category_sp->GetRegexSyntheticNavigator()->Add(RegularExpressionSP(new RegularExpression("^std::__1::map<.+> >(( )?&)?$")),
                                                        SyntheticChildrenSP(new TypeSyntheticImpl(stl_synth_flags,
                                                                                                  "libcxx.stdmap_SynthProvider")));
     
     stl_summary_flags.SetDontShowChildren(false);
-    libcxx_category_sp->GetRegexSummaryNavigator()->Add(RegularExpressionSP(new RegularExpression("^(std::__1::)vector<.+>$")),
+    libcxx_category_sp->GetRegexSummaryNavigator()->Add(RegularExpressionSP(new RegularExpression("^std::__1::vector<.+>(( )?&)?")),
                                                         TypeSummaryImplSP(new StringSummaryFormat(stl_summary_flags, "size=${svar%#}")));
-    libcxx_category_sp->GetRegexSummaryNavigator()->Add(RegularExpressionSP(new RegularExpression("^(std::__1::)list<.+>$")),
+    libcxx_category_sp->GetRegexSummaryNavigator()->Add(RegularExpressionSP(new RegularExpression("^std::__1::list<.+>(( )?&)?$")),
                                                         TypeSummaryImplSP(new StringSummaryFormat(stl_summary_flags, "size=${svar%#}")));
-    libcxx_category_sp->GetRegexSummaryNavigator()->Add(RegularExpressionSP(new RegularExpression("^(std::__1::)map<.+> >$")),
+    libcxx_category_sp->GetRegexSummaryNavigator()->Add(RegularExpressionSP(new RegularExpression("^std::__1::map<.+> >(( )?&)?$")),
                                                         TypeSummaryImplSP(new StringSummaryFormat(stl_summary_flags, "size=${svar%#}")));
 #endif
 }
diff --git a/source/Core/ValueObject.cpp b/source/Core/ValueObject.cpp
index e072b49..57f887b 100644
--- a/source/Core/ValueObject.cpp
+++ b/source/Core/ValueObject.cpp
@@ -572,6 +572,7 @@
 uint32_t
 ValueObject::GetNumChildren ()
 {
+    UpdateValueIfNeeded();
     if (!m_children_count_valid)
     {
         SetNumChildren (CalculateNumChildren());
@@ -2009,6 +2010,13 @@
     if (use_synthetic == false)
         return;
     
+    TargetSP target_sp(GetTargetSP());
+    if (target_sp && (target_sp->GetEnableSyntheticValue() == false || target_sp->GetSuppressSyntheticValue() == true))
+    {
+        m_synthetic_value = NULL;
+        return;
+    }
+    
     if (!UpdateFormatsIfNeeded(m_last_format_mgr_dynamic) && m_synthetic_value)
         return;
     
@@ -3317,6 +3325,7 @@
                     ValueObject* synth_valobj;
                     ValueObjectSP synth_valobj_sp = valobj->GetSyntheticValue (options.m_use_synthetic);
                     synth_valobj = (synth_valobj_sp ? synth_valobj_sp.get() : valobj);
+                    
                     uint32_t num_children = synth_valobj->GetNumChildren();
                     bool print_dotdotdot = false;
                     if (num_children)
diff --git a/source/Core/ValueObjectSyntheticFilter.cpp b/source/Core/ValueObjectSyntheticFilter.cpp
index 6d9337b..56eb9f6 100644
--- a/source/Core/ValueObjectSyntheticFilter.cpp
+++ b/source/Core/ValueObjectSyntheticFilter.cpp
@@ -25,7 +25,7 @@
     m_synth_filter_ap(filter->GetFrontEnd(parent)),
     m_children_byindex(),
     m_name_toindex(),
-    m_children_count(UINT32_MAX)
+    m_synthetic_children_count(UINT32_MAX)
 {
 #ifdef LLDB_CONFIGURATION_DEBUG
     std::string new_name(parent.GetName().AsCString());
@@ -56,9 +56,9 @@
 ValueObjectSynthetic::CalculateNumChildren()
 {
     UpdateValueIfNeeded();
-    if (m_children_count < UINT32_MAX)
-        return m_children_count;
-    return (m_children_count = m_synth_filter_ap->CalculateNumChildren());
+    if (m_synthetic_children_count < UINT32_MAX)
+        return m_synthetic_children_count;
+    return (m_synthetic_children_count = m_synth_filter_ap->CalculateNumChildren());
 }
 
 clang::ASTContext *
@@ -99,7 +99,11 @@
         // filter said that cached values are stale
         m_children_byindex.clear();
         m_name_toindex.clear();
-        m_children_count = UINT32_MAX;
+        // usually, an object's value can change but this does not alter its children count
+        // for a synthetic VO that might indeed happen, so we need to tell the upper echelons
+        // that they need to come back to us asking for children
+        m_children_count_valid = false;
+        m_synthetic_children_count = UINT32_MAX;
     }
     
     SetValueIsValid(true);
diff --git a/source/Interpreter/ScriptInterpreterPython.cpp b/source/Interpreter/ScriptInterpreterPython.cpp
index 81bbf3f..9c84eab 100644
--- a/source/Interpreter/ScriptInterpreterPython.cpp
+++ b/source/Interpreter/ScriptInterpreterPython.cpp
@@ -234,6 +234,24 @@
         DoFreeLock();
 }
 
+class ForceDisableSyntheticChildren
+{
+public:
+    ForceDisableSyntheticChildren (Target* target) :
+        m_target(target)
+    {
+        m_old_value = target->GetSuppressSyntheticValue();
+        target->SetSuppressSyntheticValue(true);
+    }
+    ~ForceDisableSyntheticChildren ()
+    {
+        m_target->SetSuppressSyntheticValue(m_old_value);
+    }
+private:
+    Target* m_target;
+    bool m_old_value;
+};
+
 ScriptInterpreterPython::ScriptInterpreterPython (CommandInterpreter &interpreter) :
     ScriptInterpreter (interpreter, eScriptLanguagePython),
     m_embedded_python_pty (),
@@ -1328,6 +1346,7 @@
 
     {
         Locker py_lock(this);
+        ForceDisableSyntheticChildren no_synthetics(target);
         ret_val = g_swig_synthetic_script    (class_name, 
                                               python_interpreter->m_dictionary_name.c_str(),
                                               valobj);
@@ -1586,6 +1605,7 @@
     
     {
         Locker py_lock(this);
+        ForceDisableSyntheticChildren no_synthetics(GetCommandInterpreter().GetDebugger().GetSelectedTarget().get());
         ret_val = g_swig_calc_children       (implementor);
     }
     
@@ -1612,6 +1632,7 @@
     
     {
         Locker py_lock(this);
+        ForceDisableSyntheticChildren no_synthetics(GetCommandInterpreter().GetDebugger().GetSelectedTarget().get());
         child_ptr = g_swig_get_child_index       (implementor,idx);
         if (child_ptr != NULL && child_ptr != Py_None)
         {
@@ -1648,6 +1669,7 @@
     
     {
         Locker py_lock(this);
+        ForceDisableSyntheticChildren no_synthetics(GetCommandInterpreter().GetDebugger().GetSelectedTarget().get());
         ret_val = g_swig_get_index_child       (implementor, child_name);
     }
     
@@ -1672,6 +1694,7 @@
     
     {
         Locker py_lock(this);
+        ForceDisableSyntheticChildren no_synthetics(GetCommandInterpreter().GetDebugger().GetSelectedTarget().get());
         ret_val = g_swig_update_provider       (implementor);
     }
     
diff --git a/source/Target/Target.cpp b/source/Target/Target.cpp
index 6648d4c..34fb4b8 100644
--- a/source/Target/Target.cpp
+++ b/source/Target/Target.cpp
@@ -73,7 +73,8 @@
     m_source_manager(*this),
     m_stop_hooks (),
     m_stop_hook_next_id (0),
-    m_suppress_stop_hooks (false)
+    m_suppress_stop_hooks (false),
+    m_suppress_synthetic_value(false)
 {
     SetEventName (eBroadcastBitBreakpointChanged, "breakpoint-changed");
     SetEventName (eBroadcastBitModulesLoaded, "modules-loaded");
@@ -183,6 +184,7 @@
     m_stop_hooks.clear();
     m_stop_hook_next_id = 0;
     m_suppress_stop_hooks = false;
+    m_suppress_synthetic_value = false;
 }
 
 
@@ -2106,6 +2108,7 @@
 #define TSC_DEFAULT_ARCH        "default-arch"
 #define TSC_EXPR_PREFIX         "expr-prefix"
 #define TSC_PREFER_DYNAMIC      "prefer-dynamic-value"
+#define TSC_ENABLE_SYNTHETIC    "enable-synthetic-value"
 #define TSC_SKIP_PROLOGUE       "skip-prologue"
 #define TSC_SOURCE_MAP          "source-map"
 #define TSC_EXE_SEARCH_PATHS    "exec-search-paths"
@@ -2144,6 +2147,13 @@
 }
 
 static const ConstString &
+GetSettingNameForEnableSyntheticValue ()
+{
+    static ConstString g_const_string (TSC_ENABLE_SYNTHETIC);
+    return g_const_string;
+}
+
+static const ConstString &
 GetSettingNameForSourcePathMap ()
 {
     static ConstString g_const_string (TSC_SOURCE_MAP);
@@ -2291,6 +2301,7 @@
     m_expr_prefix_file (),
     m_expr_prefix_contents (),
     m_prefer_dynamic_value (2),
+    m_enable_synthetic_value(true, true),
     m_skip_prologue (true, true),
     m_source_map (NULL, NULL),
     m_exe_search_paths (),
@@ -2330,6 +2341,7 @@
     m_expr_prefix_file (rhs.m_expr_prefix_file),
     m_expr_prefix_contents (rhs.m_expr_prefix_contents),
     m_prefer_dynamic_value (rhs.m_prefer_dynamic_value),
+    m_enable_synthetic_value(rhs.m_enable_synthetic_value),
     m_skip_prologue (rhs.m_skip_prologue),
     m_source_map (rhs.m_source_map),
     m_exe_search_paths (rhs.m_exe_search_paths),
@@ -2365,6 +2377,7 @@
         m_expr_prefix_file = rhs.m_expr_prefix_file;
         m_expr_prefix_contents = rhs.m_expr_prefix_contents;
         m_prefer_dynamic_value = rhs.m_prefer_dynamic_value;
+        m_enable_synthetic_value = rhs.m_enable_synthetic_value;
         m_skip_prologue = rhs.m_skip_prologue;
         m_source_map = rhs.m_source_map;
         m_exe_search_paths = rhs.m_exe_search_paths;
@@ -2442,6 +2455,13 @@
         if (err.Success())
             m_prefer_dynamic_value = new_value;
     }
+    else if (var_name == GetSettingNameForEnableSyntheticValue())
+    {
+        bool ok;
+        bool new_value = Args::StringToBoolean(value, true, &ok);
+        if (ok)
+            m_enable_synthetic_value.SetCurrentValue(new_value);
+    }
     else if (var_name == GetSettingNameForSkipPrologue())
     {
         err = UserSettingsController::UpdateBooleanOptionValue (value, op, m_skip_prologue);
@@ -2626,6 +2646,13 @@
     {
         value.AppendString (g_dynamic_value_types[m_prefer_dynamic_value].string_value);
     }
+    else if (var_name == GetSettingNameForEnableSyntheticValue())
+    {
+        if (m_skip_prologue)
+            value.AppendString ("true");
+        else
+            value.AppendString ("false");
+    }
     else if (var_name == GetSettingNameForSkipPrologue())
     {
         if (m_skip_prologue)
@@ -2824,6 +2851,7 @@
     // =================    ==================  =============== ======================= ====== ====== =========================================================================
     { TSC_EXPR_PREFIX       , eSetVarTypeString , NULL          , NULL,                  false, false, "Path to a file containing expressions to be prepended to all expressions." },
     { TSC_PREFER_DYNAMIC    , eSetVarTypeEnum   , NULL          , g_dynamic_value_types, false, false, "Should printed values be shown as their dynamic value." },
+    { TSC_ENABLE_SYNTHETIC  , eSetVarTypeBoolean, "true"        , NULL,                  false, false, "Should synthetic values be used by default whenever available." },
     { TSC_SKIP_PROLOGUE     , eSetVarTypeBoolean, "true"        , NULL,                  false, false, "Skip function prologues when setting breakpoints by name." },
     { TSC_SOURCE_MAP        , eSetVarTypeArray  , NULL          , NULL,                  false, false, "Source path remappings to use when locating source files from debug information." },
     { TSC_EXE_SEARCH_PATHS  , eSetVarTypeArray  , NULL          , NULL,                  false, false, "Executable search paths to use when locating executable files whose paths don't match the local file system." },