[Lldb-commits] [lldb] r129623 - in /lldb/trunk: include/lldb/API/ include/lldb/Core/ include/lldb/Target/ lldb.xcodeproj/ source/API/ source/Commands/ source/Core/ source/Expression/ source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/ source/Target/ test/ test/cpp/dynamic-value/ test/python_api/process/ tools/debugserver/debugserver.xcodeproj/

Jim Ingham jingham at apple.com
Fri Apr 15 17:01:13 PDT 2011


Author: jingham
Date: Fri Apr 15 19:01:13 2011
New Revision: 129623

URL: http://llvm.org/viewvc/llvm-project?rev=129623&view=rev
Log:
Add support for "dynamic values" for C++ classes.  This currently only works for "frame var" and for the
expressions that are simple enough to get passed to the "frame var" underpinnings.  The parser code will
have to be changed to also query for the dynamic types & offsets as it is looking up variables.

The behavior of "frame var" is controlled in two ways.  You can pass "-d {true/false} to the frame var
command to get the dynamic or static value of the variables you are printing.

There's also a general setting:

target.prefer-dynamic-value (boolean) = 'true'

which is consulted if you call "frame var" without supplying a value for the -d option.


Added:
    lldb/trunk/include/lldb/Core/ValueObjectDynamicValue.h
    lldb/trunk/include/lldb/Core/ValueObjectMemory.h
    lldb/trunk/source/Core/ValueObjectDynamicValue.cpp
    lldb/trunk/source/Core/ValueObjectMemory.cpp
    lldb/trunk/test/cpp/dynamic-value/
    lldb/trunk/test/cpp/dynamic-value/Makefile
    lldb/trunk/test/cpp/dynamic-value/TestDynamicValue.py
    lldb/trunk/test/cpp/dynamic-value/pass-to-base.cpp
Modified:
    lldb/trunk/include/lldb/API/SBFrame.h
    lldb/trunk/include/lldb/API/SBValue.h
    lldb/trunk/include/lldb/Core/ValueObject.h
    lldb/trunk/include/lldb/Core/ValueObjectConstResult.h
    lldb/trunk/include/lldb/Target/LanguageRuntime.h
    lldb/trunk/include/lldb/Target/StackFrame.h
    lldb/trunk/include/lldb/Target/Target.h
    lldb/trunk/lldb.xcodeproj/project.pbxproj
    lldb/trunk/source/API/SBFrame.cpp
    lldb/trunk/source/API/SBValue.cpp
    lldb/trunk/source/Commands/CommandObjectExpression.cpp
    lldb/trunk/source/Commands/CommandObjectExpression.h
    lldb/trunk/source/Commands/CommandObjectFrame.cpp
    lldb/trunk/source/Core/ValueObject.cpp
    lldb/trunk/source/Core/ValueObjectChild.cpp
    lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp
    lldb/trunk/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
    lldb/trunk/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h
    lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp
    lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h
    lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp
    lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h
    lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
    lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h
    lldb/trunk/source/Target/Process.cpp
    lldb/trunk/source/Target/StackFrame.cpp
    lldb/trunk/source/Target/Target.cpp
    lldb/trunk/source/Target/ThreadPlanTestCondition.cpp
    lldb/trunk/test/lldbutil.py
    lldb/trunk/test/python_api/process/TestProcessAPI.py
    lldb/trunk/tools/debugserver/debugserver.xcodeproj/project.pbxproj

Modified: lldb/trunk/include/lldb/API/SBFrame.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBFrame.h?rev=129623&r1=129622&r2=129623&view=diff
==============================================================================
--- lldb/trunk/include/lldb/API/SBFrame.h (original)
+++ lldb/trunk/include/lldb/API/SBFrame.h Fri Apr 15 19:01:13 2011
@@ -71,8 +71,12 @@
     lldb::SBBlock
     GetBlock () const;
 
+    // The version that doesn't supply a "use_dynamic" value will use the target's default.
     lldb::SBValue
-    EvaluateExpression (const char *expr);
+    EvaluateExpression (const char *expr);    
+
+    lldb::SBValue
+    EvaluateExpression (const char *expr, bool fetch_dynamic_value);
 
     // Gets the lexical block that defines the stack frame. Another way to think
     // of this is it will return the block that contains all of the variables
@@ -116,17 +120,32 @@
                   bool statics,
                   bool in_scope_only);
 
+    // The version that doesn't supply a "use_dynamic" value will use the target's default.
+    lldb::SBValueList
+    GetVariables (bool arguments,
+                  bool locals,
+                  bool statics,
+                  bool in_scope_only,
+                  bool use_dynamic);
+
     lldb::SBValueList
     GetRegisters ();
 
+    // The version that doesn't supply a "use_dynamic" value will use the target's default.
     lldb::SBValue
     FindVariable (const char *var_name);
 
+    lldb::SBValue
+    FindVariable (const char *var_name, bool use_dynamic);
+
     // Find variables, register sets, registers, or persistent variables using
     // the frame as the scope
     lldb::SBValue
     FindValue (const char *name, ValueType value_type);
 
+    lldb::SBValue
+    FindValue (const char *name, ValueType value_type, bool use_dynamic);
+
     bool
     GetDescription (lldb::SBStream &description);
 

Modified: lldb/trunk/include/lldb/API/SBValue.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBValue.h?rev=129623&r1=129622&r2=129623&view=diff
==============================================================================
--- lldb/trunk/include/lldb/API/SBValue.h (original)
+++ lldb/trunk/include/lldb/API/SBValue.h Fri Apr 15 19:01:13 2011
@@ -99,6 +99,9 @@
     lldb::SBValue
     GetChildAtIndex (uint32_t idx);
 
+    lldb::SBValue
+    GetChildAtIndex (uint32_t idx, bool use_dynamic);
+
     // Matches children of this object only and will match base classes and
     // member names if this is a clang typed object.
     uint32_t
@@ -109,6 +112,11 @@
     lldb::SBValue
     GetChildMemberWithName (const char *name);
 
+    // Matches child members of this object and child members of any base
+    // classes.
+    lldb::SBValue
+    GetChildMemberWithName (const char *name, bool use_dynamic);
+
     uint32_t
     GetNumChildren ();
 

Modified: lldb/trunk/include/lldb/Core/ValueObject.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/ValueObject.h?rev=129623&r1=129622&r2=129623&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/ValueObject.h (original)
+++ lldb/trunk/include/lldb/Core/ValueObject.h Fri Apr 15 19:01:13 2011
@@ -306,7 +306,7 @@
 
     bool
     ResolveValue (Scalar &scalar);
-
+    
     const char *
     GetLocationAsCString ();
 
@@ -325,9 +325,6 @@
     bool
     UpdateValueIfNeeded ();
 
-    const DataExtractor &
-    GetDataExtractor () const;
-
     DataExtractor &
     GetDataExtractor ();
 
@@ -345,10 +342,10 @@
     GetSyntheticArrayMemberFromPointer (int32_t index, bool can_create);
     
     lldb::ValueObjectSP
-    GetDynamicValue ()
-    {
-        return m_dynamic_value_sp;
-    }
+    GetDynamicValue (bool can_create);
+    
+    lldb::ValueObjectSP
+    GetDynamicValue (bool can_create, lldb::ValueObjectSP &owning_valobj_sp);
     
     virtual lldb::ValueObjectSP
     CreateConstantValue (const ConstString &name);
@@ -369,8 +366,11 @@
         m_object_desc_str.clear();
     }
 
-    bool
-    SetDynamicValue ();
+    virtual bool
+    IsDynamic ()
+    {
+        return false;
+    }
 
     static void
     DumpValueObject (Stream &s,
@@ -382,6 +382,7 @@
                      bool show_types,
                      bool show_location,
                      bool use_objc,
+                     bool use_dynamic,
                      bool scope_already_checked,
                      bool flat_output);
 
@@ -411,13 +412,16 @@
         m_format = format;
     }
 
-    ValueObject *
+    // Use GetParent for display purposes, but if you want to tell the parent to update itself
+    // then use m_parent.  The ValueObjectDynamicValue's parent is not the correct parent for
+    // displaying, they are really siblings, so for display it needs to route through to its grandparent.
+    virtual ValueObject *
     GetParent()
     {
         return m_parent;
     }
 
-    const ValueObject *
+    virtual const ValueObject *
     GetParent() const
     {
         return m_parent;
@@ -436,8 +440,8 @@
     //------------------------------------------------------------------
     // Classes that inherit from ValueObject can see and modify these
     //------------------------------------------------------------------
-    ValueObject*        m_parent;       // The parent value object, or NULL if this has no parent
-    EvaluationPoint   m_update_point; // Stores both the stop id and the full context at which this value was last 
+    ValueObject  *m_parent;       // The parent value object, or NULL if this has no parent
+    EvaluationPoint      m_update_point; // Stores both the stop id and the full context at which this value was last 
                                         // updated.  When we are asked to update the value object, we check whether
                                         // the context & stop id are the same before updating.
     ConstString         m_name;         // The name of this object
@@ -453,6 +457,10 @@
     std::vector<lldb::ValueObjectSP> m_children;
     std::map<ConstString, lldb::ValueObjectSP> m_synthetic_children;
     lldb::ValueObjectSP m_dynamic_value_sp;
+    lldb::ValueObjectSP m_addr_of_valobj_sp; // These two shared pointers help root the ValueObject shared pointers that
+    lldb::ValueObjectSP m_deref_valobj_sp;   // we hand out, so that we can use them in their dynamic types and ensure
+                                             // they will last as long as this ValueObject...
+
     lldb::Format        m_format;
     bool                m_value_is_valid:1,
                         m_value_did_change:1,
@@ -463,6 +471,7 @@
     
     friend class CommandObjectExpression;
     friend class ClangExpressionVariable;
+    friend class ClangExpressionDeclMap;  // For GetValue...
     friend class Target;
     friend class ValueObjectChild;
     //------------------------------------------------------------------
@@ -486,6 +495,9 @@
     virtual bool
     UpdateValue () = 0;
 
+    virtual void
+    CalculateDynamicValue ();
+    
     // Should only be called by ValueObject::GetChildAtIndex()
     virtual lldb::ValueObjectSP
     CreateChildAtIndex (uint32_t idx, bool synthetic_array_member, int32_t synthetic_index);
@@ -509,7 +521,7 @@
     void
     SetValueIsValid (bool valid);
 
-
+public:
     lldb::addr_t
     GetPointerValue (AddressType &address_type, 
                      bool scalar_is_load_address);

Modified: lldb/trunk/include/lldb/Core/ValueObjectConstResult.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/ValueObjectConstResult.h?rev=129623&r1=129622&r2=129623&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/ValueObjectConstResult.h (original)
+++ lldb/trunk/include/lldb/Core/ValueObjectConstResult.h Fri Apr 15 19:01:13 2011
@@ -91,6 +91,12 @@
     virtual bool
     UpdateValue ();
 
+    virtual void
+    CalculateDynamicValue () {} // CalculateDynamicValue doesn't change the dynamic value, since this can get
+                                // called at any time and you can't reliably fetch the dynamic value at any time.
+                                // If we want to have dynamic values for ConstResults, then we'll need to make them
+                                // up when we make the const result & stuff them in by hand.
+                                    
     clang::ASTContext *m_clang_ast; // The clang AST that the clang type comes from
     ConstString m_type_name;
     uint32_t m_byte_size;

Added: lldb/trunk/include/lldb/Core/ValueObjectDynamicValue.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/ValueObjectDynamicValue.h?rev=129623&view=auto
==============================================================================
--- lldb/trunk/include/lldb/Core/ValueObjectDynamicValue.h (added)
+++ lldb/trunk/include/lldb/Core/ValueObjectDynamicValue.h Fri Apr 15 19:01:13 2011
@@ -0,0 +1,105 @@
+//===-- ValueObjectDynamicValue.h -----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ValueObjectDynamicValue_h_
+#define liblldb_ValueObjectDynamicValue_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/ValueObject.h"
+
+namespace lldb_private {
+
+//----------------------------------------------------------------------
+// A ValueObject that represents memory at a given address, viewed as some 
+// set lldb type.
+//----------------------------------------------------------------------
+class ValueObjectDynamicValue : public ValueObject
+{
+public:
+    ValueObjectDynamicValue (ValueObject &parent);
+
+    virtual
+    ~ValueObjectDynamicValue();
+
+    virtual size_t
+    GetByteSize();
+
+    virtual clang::ASTContext *
+    GetClangAST ();
+
+    virtual lldb::clang_type_t
+    GetClangType ();
+
+    virtual ConstString
+    GetTypeName();
+
+    virtual uint32_t
+    CalculateNumChildren();
+
+    virtual lldb::ValueType
+    GetValueType() const;
+
+    virtual bool
+    IsInScope ();
+    
+    virtual bool
+    IsDynamic ()
+    {
+        return true;
+    }
+    
+    virtual ValueObject *
+    GetParent()
+    {
+        if (m_parent)
+            return m_parent->GetParent();
+        else
+            return NULL;
+    }
+
+    virtual const ValueObject *
+    GetParent() const
+    {
+        if (m_parent)
+            return m_parent->GetParent();
+        else
+            return NULL;
+    }
+
+    void
+    SetOwningSP (lldb::ValueObjectSP &owning_sp)
+    {
+        if (m_owning_valobj_sp == owning_sp)
+            return;
+            
+        assert (m_owning_valobj_sp.get() == NULL);
+        m_owning_valobj_sp = owning_sp;
+    }
+    
+protected:
+    virtual bool
+    UpdateValue ();
+
+    Address  m_address;  ///< The variable that this value object is based upon
+    lldb::TypeSP m_type_sp;
+    lldb::ValueObjectSP m_owning_valobj_sp;
+
+private:
+    //------------------------------------------------------------------
+    // For ValueObject only
+    //------------------------------------------------------------------
+    DISALLOW_COPY_AND_ASSIGN (ValueObjectDynamicValue);
+};
+
+} // namespace lldb_private
+
+#endif  // liblldb_ValueObjectDynamicValue_h_

Added: lldb/trunk/include/lldb/Core/ValueObjectMemory.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/ValueObjectMemory.h?rev=129623&view=auto
==============================================================================
--- lldb/trunk/include/lldb/Core/ValueObjectMemory.h (added)
+++ lldb/trunk/include/lldb/Core/ValueObjectMemory.h Fri Apr 15 19:01:13 2011
@@ -0,0 +1,73 @@
+//===-- ValueObjectMemory.h -----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ValueObjectMemory_h_
+#define liblldb_ValueObjectMemory_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/ValueObject.h"
+
+namespace lldb_private {
+
+//----------------------------------------------------------------------
+// A ValueObject that represents memory at a given address, viewed as some 
+// set lldb type.
+//----------------------------------------------------------------------
+class ValueObjectMemory : public ValueObject
+{
+public:
+    ValueObjectMemory (ExecutionContextScope *exe_scope, 
+                       const char *name,
+                       const Address &address, 
+                       lldb::TypeSP &type_sp);
+
+    virtual
+    ~ValueObjectMemory();
+
+    virtual size_t
+    GetByteSize();
+
+    virtual clang::ASTContext *
+    GetClangAST ();
+
+    virtual lldb::clang_type_t
+    GetClangType ();
+
+    virtual ConstString
+    GetTypeName();
+
+    virtual uint32_t
+    CalculateNumChildren();
+
+    virtual lldb::ValueType
+    GetValueType() const;
+
+    virtual bool
+    IsInScope ();
+
+protected:
+    virtual bool
+    UpdateValue ();
+
+    Address  m_address;  ///< The variable that this value object is based upon
+    lldb::TypeSP m_type_sp;
+
+private:
+    //------------------------------------------------------------------
+    // For ValueObject only
+    //------------------------------------------------------------------
+    DISALLOW_COPY_AND_ASSIGN (ValueObjectMemory);
+};
+
+} // namespace lldb_private
+
+#endif  // liblldb_ValueObjectMemory_h_

Modified: lldb/trunk/include/lldb/Target/LanguageRuntime.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/LanguageRuntime.h?rev=129623&r1=129622&r2=129623&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/LanguageRuntime.h (original)
+++ lldb/trunk/include/lldb/Target/LanguageRuntime.h Fri Apr 15 19:01:13 2011
@@ -42,9 +42,14 @@
     virtual bool
     GetObjectDescription (Stream &str, Value &value, ExecutionContextScope *exe_scope) = 0;
     
-    virtual lldb::ValueObjectSP
-    GetDynamicValue (lldb::ValueObjectSP in_value) = 0;
+    virtual bool
+    GetDynamicValue (ValueObject &in_value, lldb::TypeSP &type_sp, Address &address) = 0;
     
+    // This should be a fast test to determine whether it is likely that this value would
+    // have a dynamic type.
+    virtual bool
+    CouldHaveDynamicValue (ValueObject &in_value) = 0;
+
     virtual void
     SetExceptionBreakpoints ()
     {

Modified: lldb/trunk/include/lldb/Target/StackFrame.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/StackFrame.h?rev=129623&r1=129622&r2=129623&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/StackFrame.h (original)
+++ lldb/trunk/include/lldb/Target/StackFrame.h Fri Apr 15 19:01:13 2011
@@ -33,7 +33,8 @@
     enum ExpressionPathOption
     {
         eExpressionPathOptionCheckPtrVsMember   = (1u << 0),
-        eExpressionPathOptionsNoFragileObjcIvar = (1u << 1)
+        eExpressionPathOptionsNoFragileObjcIvar = (1u << 1),
+        eExpressionPathOptionsDynamicValue      = (1u << 2)
     };
     //------------------------------------------------------------------
     // Constructors and Destructors
@@ -133,10 +134,10 @@
     }
     
     lldb::ValueObjectSP
-    GetValueObjectForFrameVariable (const lldb::VariableSP &variable_sp);
+    GetValueObjectForFrameVariable (const lldb::VariableSP &variable_sp, bool use_dynamic);
 
     lldb::ValueObjectSP
-    TrackGlobalVariable (const lldb::VariableSP &variable_sp);
+    TrackGlobalVariable (const lldb::VariableSP &variable_sp, bool use_dynamic);
     
     //------------------------------------------------------------------
     // lldb::ExecutionContextScope pure virtual functions

Modified: lldb/trunk/include/lldb/Target/Target.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/Target.h?rev=129623&r1=129622&r2=129623&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/Target.h (original)
+++ lldb/trunk/include/lldb/Target/Target.h Fri Apr 15 19:01:13 2011
@@ -66,6 +66,12 @@
                               StringList &value,
                               Error *err);
 
+    bool
+    GetPreferDynamicValue()
+    {
+        return m_prefer_dynamic_value;
+    }
+    
 protected:
 
     void
@@ -77,6 +83,7 @@
     
     std::string m_expr_prefix_path;
     std::string m_expr_prefix_contents;
+    bool        m_prefer_dynamic_value;
 
 };
 
@@ -461,6 +468,7 @@
                         StackFrame *frame,
                         bool unwind_on_error,
                         bool keep_in_memory,
+                        bool fetch_dynamic_value,
                         lldb::ValueObjectSP &result_valobj_sp);
 
     ClangPersistentVariables &

Modified: lldb/trunk/lldb.xcodeproj/project.pbxproj
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lldb.xcodeproj/project.pbxproj?rev=129623&r1=129622&r2=129623&view=diff
==============================================================================
--- lldb/trunk/lldb.xcodeproj/project.pbxproj (original)
+++ lldb/trunk/lldb.xcodeproj/project.pbxproj Fri Apr 15 19:01:13 2011
@@ -408,6 +408,10 @@
 		26F5C37510F3F61B009D5894 /* libobjc.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 26F5C37410F3F61B009D5894 /* libobjc.dylib */; };
 		26F5C39110F3FA26009D5894 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 26F5C39010F3FA26009D5894 /* CoreFoundation.framework */; };
 		4C74CB6312288704006A8171 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C74CB6212288704006A8171 /* Carbon.framework */; };
+		4CABA9DD134A8BA800539BDD /* ValueObjectMemory.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CABA9DC134A8BA700539BDD /* ValueObjectMemory.h */; };
+		4CABA9E0134A8BCD00539BDD /* ValueObjectMemory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CABA9DF134A8BCD00539BDD /* ValueObjectMemory.cpp */; };
+		4CD0BD0D134BFAB600CB44D4 /* ValueObjectDynamicValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CD0BD0C134BFAB600CB44D4 /* ValueObjectDynamicValue.h */; };
+		4CD0BD0F134BFADF00CB44D4 /* ValueObjectDynamicValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CD0BD0E134BFADF00CB44D4 /* ValueObjectDynamicValue.cpp */; };
 		9A19A6AF1163BBB200E0D453 /* SBValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A19A6A51163BB7E00E0D453 /* SBValue.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		9A19A6B01163BBB300E0D453 /* SBValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A19A6AD1163BB9800E0D453 /* SBValue.cpp */; };
 		9A357583116CFDEE00E8ED2F /* SBValueList.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A357582116CFDEE00E8ED2F /* SBValueList.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -1103,6 +1107,8 @@
 		4C98D3E1118FB98F00E575D0 /* RecordingMemoryManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RecordingMemoryManager.h; path = include/lldb/Expression/RecordingMemoryManager.h; sourceTree = "<group>"; };
 		4CA9637911B6E99A00780E28 /* CommandObjectApropos.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandObjectApropos.cpp; path = source/Commands/CommandObjectApropos.cpp; sourceTree = "<group>"; };
 		4CA9637A11B6E99A00780E28 /* CommandObjectApropos.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandObjectApropos.h; path = source/Commands/CommandObjectApropos.h; sourceTree = "<group>"; };
+		4CABA9DC134A8BA700539BDD /* ValueObjectMemory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ValueObjectMemory.h; path = include/lldb/Core/ValueObjectMemory.h; sourceTree = "<group>"; };
+		4CABA9DF134A8BCD00539BDD /* ValueObjectMemory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ValueObjectMemory.cpp; path = source/Core/ValueObjectMemory.cpp; sourceTree = "<group>"; };
 		4CAFCE001101216B00CA63DB /* ThreadPlanRunToAddress.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThreadPlanRunToAddress.h; path = include/lldb/Target/ThreadPlanRunToAddress.h; sourceTree = "<group>"; };
 		4CAFCE031101218900CA63DB /* ThreadPlanRunToAddress.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ThreadPlanRunToAddress.cpp; path = source/Target/ThreadPlanRunToAddress.cpp; sourceTree = "<group>"; };
 		4CB4430912491DDA00C13DC2 /* LanguageRuntime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LanguageRuntime.h; path = include/lldb/Target/LanguageRuntime.h; sourceTree = "<group>"; };
@@ -1115,6 +1121,8 @@
 		4CB443F612499B6E00C13DC2 /* ObjCLanguageRuntime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ObjCLanguageRuntime.h; path = include/lldb/Target/ObjCLanguageRuntime.h; sourceTree = "<group>"; };
 		4CC2A148128C73ED001531C4 /* ThreadPlanTracer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ThreadPlanTracer.cpp; path = source/Target/ThreadPlanTracer.cpp; sourceTree = "<group>"; };
 		4CC2A14C128C7409001531C4 /* ThreadPlanTracer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThreadPlanTracer.h; path = include/lldb/Target/ThreadPlanTracer.h; sourceTree = "<group>"; };
+		4CD0BD0C134BFAB600CB44D4 /* ValueObjectDynamicValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ValueObjectDynamicValue.h; path = include/lldb/Core/ValueObjectDynamicValue.h; sourceTree = "<group>"; };
+		4CD0BD0E134BFADF00CB44D4 /* ValueObjectDynamicValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ValueObjectDynamicValue.cpp; path = source/Core/ValueObjectDynamicValue.cpp; sourceTree = "<group>"; };
 		4CEDAED311754F5E00E875A6 /* ThreadPlanStepUntil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThreadPlanStepUntil.h; path = include/lldb/Target/ThreadPlanStepUntil.h; sourceTree = "<group>"; };
 		69A01E1B1236C5D400C660B5 /* Condition.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Condition.cpp; sourceTree = "<group>"; };
 		69A01E1C1236C5D400C660B5 /* Host.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Host.cpp; sourceTree = "<group>"; };
@@ -1902,8 +1910,12 @@
 				26BC7E9B10F1B85900F91463 /* ValueObjectChild.cpp */,
 				26424E3E125986D30016D82C /* ValueObjectConstResult.h */,
 				26424E3C125986CB0016D82C /* ValueObjectConstResult.cpp */,
+				4CD0BD0C134BFAB600CB44D4 /* ValueObjectDynamicValue.h */,
+				4CD0BD0E134BFADF00CB44D4 /* ValueObjectDynamicValue.cpp */,
 				26BC7D8410F1B77400F91463 /* ValueObjectList.h */,
 				26BC7E9C10F1B85900F91463 /* ValueObjectList.cpp */,
+				4CABA9DC134A8BA700539BDD /* ValueObjectMemory.h */,
+				4CABA9DF134A8BCD00539BDD /* ValueObjectMemory.cpp */,
 				2643343A1110F63C00CDB6C6 /* ValueObjectRegister.h */,
 				264334381110F63100CDB6C6 /* ValueObjectRegister.cpp */,
 				26BC7D8510F1B77400F91463 /* ValueObjectVariable.h */,
@@ -2550,6 +2562,8 @@
 				26651A16133BF9CD005B64B7 /* Opcode.h in Headers */,
 				266603CD1345B5C0004DA8B6 /* ConnectionSharedMemory.h in Headers */,
 				2671A0CE134825F6003A87BB /* ConnectionMachPort.h in Headers */,
+				4CABA9DD134A8BA800539BDD /* ValueObjectMemory.h in Headers */,
+				4CD0BD0D134BFAB600CB44D4 /* ValueObjectDynamicValue.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -3114,6 +3128,8 @@
 				26651A18133BF9E0005B64B7 /* Opcode.cpp in Sources */,
 				266603CA1345B5A8004DA8B6 /* ConnectionSharedMemory.cpp in Sources */,
 				2671A0D013482601003A87BB /* ConnectionMachPort.cpp in Sources */,
+				4CABA9E0134A8BCD00539BDD /* ValueObjectMemory.cpp in Sources */,
+				4CD0BD0F134BFADF00CB44D4 /* ValueObjectDynamicValue.cpp in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -3209,7 +3225,6 @@
 				LLVM_CONFIGURATION = Release;
 				LLVM_SOURCE_DIR = "$(SRCROOT)/llvm";
 				ONLY_ACTIVE_ARCH = YES;
-				PREBINDING = NO;
 				VALID_ARCHS = "x86_64 i386";
 			};
 			name = Debug;
@@ -3251,7 +3266,6 @@
 				COPY_PHASE_STRIP = NO;
 				DEBUG_INFORMATION_FORMAT = dwarf;
 				GCC_DYNAMIC_NO_PIC = NO;
-				GCC_ENABLE_FIX_AND_CONTINUE = YES;
 				GCC_OPTIMIZATION_LEVEL = 0;
 				INSTALL_PATH = /Developer/usr/bin;
 				ONLY_ACTIVE_ARCH = NO;
@@ -3265,7 +3279,6 @@
 				ALWAYS_SEARCH_USER_PATHS = NO;
 				COPY_PHASE_STRIP = YES;
 				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
-				GCC_ENABLE_FIX_AND_CONTINUE = NO;
 				INSTALL_PATH = /Developer/usr/bin;
 				ONLY_ACTIVE_ARCH = NO;
 				PRODUCT_NAME = "darwin-debug";
@@ -3277,7 +3290,6 @@
 			buildSettings = {
 				ALWAYS_SEARCH_USER_PATHS = NO;
 				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
-				GCC_ENABLE_FIX_AND_CONTINUE = YES;
 				INSTALL_PATH = /Developer/usr/bin;
 				ONLY_ACTIVE_ARCH = NO;
 				PRODUCT_NAME = "darwin-debug";
@@ -3542,7 +3554,6 @@
 					"$(inherited)",
 					"\"$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks\"",
 				);
-				GCC_ENABLE_FIX_AND_CONTINUE = NO;
 				GCC_INLINES_ARE_PRIVATE_EXTERN = NO;
 				GCC_SYMBOLS_PRIVATE_EXTERN = NO;
 				HEADER_SEARCH_PATHS = "";
@@ -3730,7 +3741,6 @@
 					"$(inherited)",
 					"\"$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks\"",
 				);
-				GCC_ENABLE_FIX_AND_CONTINUE = NO;
 				GCC_INLINES_ARE_PRIVATE_EXTERN = NO;
 				GCC_SYMBOLS_PRIVATE_EXTERN = NO;
 				HEADER_SEARCH_PATHS = "";

Modified: lldb/trunk/source/API/SBFrame.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBFrame.cpp?rev=129623&r1=129622&r2=129623&view=diff
==============================================================================
--- lldb/trunk/source/API/SBFrame.cpp (original)
+++ lldb/trunk/source/API/SBFrame.cpp Fri Apr 15 19:01:13 2011
@@ -343,6 +343,13 @@
 SBValue
 SBFrame::FindVariable (const char *name)
 {
+    bool use_dynamic = m_opaque_sp->CalculateTarget()->GetPreferDynamicValue();
+    return FindVariable (name, use_dynamic);
+}
+
+SBValue
+SBFrame::FindVariable (const char *name, bool use_dynamic)
+{
     VariableSP var_sp;
     if (m_opaque_sp && name && name[0])
     {
@@ -369,7 +376,7 @@
     SBValue sb_value;
     
     if (var_sp)
-        *sb_value = ValueObjectSP (new ValueObjectVariable (m_opaque_sp.get(), var_sp));
+        *sb_value = ValueObjectSP (m_opaque_sp->GetValueObjectForFrameVariable(var_sp, use_dynamic));
 
     LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
     if (log)
@@ -382,6 +389,13 @@
 SBValue
 SBFrame::FindValue (const char *name, ValueType value_type)
 {
+    bool use_dynamic = m_opaque_sp->CalculateTarget()->GetPreferDynamicValue();
+    return FindValue (name, value_type, use_dynamic);
+}
+
+SBValue
+SBFrame::FindValue (const char *name, ValueType value_type, bool use_dynamic)
+{
     SBValue sb_value;
     if (m_opaque_sp && name && name[0])
     {
@@ -416,7 +430,8 @@
                             variable_sp->GetScope() == value_type &&
                             variable_sp->GetName() == const_name)
                         {
-                            *sb_value = ValueObjectSP (new ValueObjectVariable (m_opaque_sp.get(), variable_sp));
+                            *sb_value = ValueObjectSP (m_opaque_sp->GetValueObjectForFrameVariable(variable_sp, 
+                                                                                                   use_dynamic));
                             break;
                         }
                     }
@@ -564,6 +579,17 @@
                        bool statics,
                        bool in_scope_only)
 {
+    bool use_dynamic = m_opaque_sp->CalculateTarget()->GetPreferDynamicValue();
+    return GetVariables (arguments, locals, statics, in_scope_only, use_dynamic);
+}
+
+SBValueList
+SBFrame::GetVariables (bool arguments,
+                       bool locals,
+                       bool statics,
+                       bool in_scope_only,
+                       bool use_dynamic)
+{
     LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
 
     if (log)
@@ -619,7 +645,7 @@
                             if (in_scope_only && !variable_sp->IsInScope(m_opaque_sp.get()))
                                 continue;
 
-                            value_list.Append(m_opaque_sp->GetValueObjectForFrameVariable (variable_sp));
+                            value_list.Append(m_opaque_sp->GetValueObjectForFrameVariable (variable_sp, use_dynamic));
                         }
                     }
                 }
@@ -680,6 +706,13 @@
 SBValue
 SBFrame::EvaluateExpression (const char *expr)
 {
+    bool use_dynamic = m_opaque_sp->CalculateTarget()->GetPreferDynamicValue();
+    return EvaluateExpression (expr, use_dynamic);
+}
+
+SBValue
+SBFrame::EvaluateExpression (const char *expr, bool fetch_dynamic_value)
+{
     Mutex::Locker api_locker (m_opaque_sp->GetThread().GetProcess().GetTarget().GetAPIMutex());
 
     LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
@@ -696,14 +729,23 @@
         const bool unwind_on_error = true;
         const bool keep_in_memory = false;
 
-        exe_results = m_opaque_sp->GetThread().GetProcess().GetTarget().EvaluateExpression(expr, m_opaque_sp.get(), unwind_on_error, keep_in_memory, *expr_result);
+        exe_results = m_opaque_sp->GetThread().GetProcess().GetTarget().EvaluateExpression(expr, 
+                                                                                           m_opaque_sp.get(), 
+                                                                                           unwind_on_error, 
+                                                                                           fetch_dynamic_value, 
+                                                                                           keep_in_memory, 
+                                                                                           *expr_result);
     }
     
     if (expr_log)
-        expr_log->Printf("** [SBFrame::EvaluateExpression] Expression result is %s, summary %s **", expr_result.GetValue(*this), expr_result.GetSummary(*this));
+        expr_log->Printf("** [SBFrame::EvaluateExpression] Expression result is %s, summary %s **", 
+                         expr_result.GetValue(*this), 
+                         expr_result.GetSummary(*this));
     
     if (log)
-        log->Printf ("SBFrame(%p)::EvaluateExpression (expr=\"%s\") => SBValue(%p)", m_opaque_sp.get(), expr, expr_result.get());
+        log->Printf ("SBFrame(%p)::EvaluateExpression (expr=\"%s\") => SBValue(%p)", m_opaque_sp.get(), 
+                     expr, 
+                     expr_result.get());
 
     return expr_result;
 }

Modified: lldb/trunk/source/API/SBValue.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBValue.cpp?rev=129623&r1=129622&r2=129623&view=diff
==============================================================================
--- lldb/trunk/source/API/SBValue.cpp (original)
+++ lldb/trunk/source/API/SBValue.cpp Fri Apr 15 19:01:13 2011
@@ -339,6 +339,13 @@
 SBValue
 SBValue::GetChildAtIndex (uint32_t idx)
 {
+    bool use_dynamic_value = m_opaque_sp->GetUpdatePoint().GetTarget()->GetPreferDynamicValue();
+    return GetChildAtIndex (idx, use_dynamic_value);
+}
+
+SBValue
+SBValue::GetChildAtIndex (uint32_t idx, bool use_dynamic_value)
+{
     lldb::ValueObjectSP child_sp;
 
     if (m_opaque_sp)
@@ -346,6 +353,16 @@
         child_sp = m_opaque_sp->GetChildAtIndex (idx, true);
     }
 
+    if (use_dynamic_value)
+    {
+        if (child_sp)
+        {
+            lldb::ValueObjectSP dynamic_sp = child_sp->GetDynamicValue(true, child_sp);
+            if (dynamic_sp)
+                child_sp = dynamic_sp;
+        }
+    }
+    
     SBValue sb_value (child_sp);
     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
     if (log)
@@ -374,6 +391,13 @@
 SBValue
 SBValue::GetChildMemberWithName (const char *name)
 {
+    bool use_dynamic_value = m_opaque_sp->GetUpdatePoint().GetTarget()->GetPreferDynamicValue();
+    return GetChildMemberWithName (name, use_dynamic_value);
+}
+
+SBValue
+SBValue::GetChildMemberWithName (const char *name, bool use_dynamic_value)
+{
     lldb::ValueObjectSP child_sp;
     const ConstString str_name (name);
 
@@ -382,6 +406,16 @@
         child_sp = m_opaque_sp->GetChildMemberWithName (str_name, true);
     }
 
+    if (use_dynamic_value)
+    {
+        if (child_sp)
+        {
+            lldb::ValueObjectSP dynamic_sp = child_sp->GetDynamicValue(true, child_sp);
+            if (dynamic_sp)
+                child_sp = dynamic_sp;
+        }
+    }
+    
     SBValue sb_value (child_sp);
 
     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

Modified: lldb/trunk/source/Commands/CommandObjectExpression.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectExpression.cpp?rev=129623&r1=129622&r2=129623&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectExpression.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectExpression.cpp Fri Apr 15 19:01:13 2011
@@ -77,6 +77,23 @@
         print_object = true;
         break;
         
+    case 'd':
+        {
+            bool success;
+            bool result;
+            result = Args::StringToBoolean(option_arg, true, &success);
+            if (!success)
+                error.SetErrorStringWithFormat("Invalid dynamic value setting: \"%s\".\n", option_arg);
+            else
+            {
+                if (result)
+                    use_dynamic  = eLazyBoolYes;  
+                else
+                    use_dynamic = eLazyBoolNo;
+            }
+        }
+        break;
+        
     case 'u':
         bool success;
         unwind_on_error = Args::StringToBoolean(option_arg, true, &success);
@@ -99,6 +116,7 @@
     debug = false;
     format = eFormatDefault;
     print_object = false;
+    use_dynamic = eLazyBoolCalculate;
     unwind_on_error = true;
     show_types = true;
     show_summary = true;
@@ -239,8 +257,27 @@
         ExecutionResults exe_results;
         
         bool keep_in_memory = true;
+        bool use_dynamic;
+        // If use dynamic is not set, get it from the target:
+        switch (m_options.use_dynamic)
+        {
+        case eLazyBoolCalculate:
+            {   
+                if (m_exe_ctx.target->GetPreferDynamicValue())
+                    use_dynamic = true;
+                else
+                    use_dynamic = false;
+            }
+            break;
+        case eLazyBoolYes:
+            use_dynamic = true;
+            break;
+        case eLazyBoolNo:
+            use_dynamic = false;
+            break;
+        }
         
-        exe_results = m_exe_ctx.target->EvaluateExpression(expr, m_exe_ctx.frame, m_options.unwind_on_error, keep_in_memory, result_valobj_sp);
+        exe_results = m_exe_ctx.target->EvaluateExpression(expr, m_exe_ctx.frame, m_options.unwind_on_error, use_dynamic, keep_in_memory, result_valobj_sp);
         
         if (exe_results == eExecutionInterrupted && !m_options.unwind_on_error)
         {
@@ -266,6 +303,7 @@
                                               m_options.show_types,     // Show types when dumping?
                                               false,                    // Show locations of variables, no since this is a host address which we don't care to see
                                               m_options.print_object,   // Print the objective C object?
+                                              use_dynamic,
                                               true,                     // Scope is already checked. Const results are always in scope.
                                               false);                   // Don't flatten output
                 if (result)
@@ -389,6 +427,7 @@
 //{ LLDB_OPT_SET_1, false, "format",     'f', required_argument, NULL, 0, "[ [bool|b] | [bin] | [char|c] | [oct|o] | [dec|i|d|u] | [hex|x] | [float|f] | [cstr|s] ]",  "Specify the format that the expression output should use."},
 { LLDB_OPT_SET_1, false, "format",             'f', required_argument, NULL, 0, eArgTypeExprFormat,  "Specify the format that the expression output should use."},
 { LLDB_OPT_SET_2, false, "object-description", 'o', no_argument,       NULL, 0, eArgTypeNone, "Print the object description of the value resulting from the expression."},
+{ LLDB_OPT_SET_2, false, "dynamic-value", 'd', required_argument,       NULL, 0, eArgTypeBoolean, "Upcast the value resulting from the expression to its dynamic type if available."},
 { LLDB_OPT_SET_ALL, false, "unwind-on-error",  'u', required_argument, NULL, 0, eArgTypeBoolean, "Clean up program state if the expression causes a crash, breakpoint hit or signal."},
 { LLDB_OPT_SET_ALL, false, "debug",            'g', no_argument,       NULL, 0, eArgTypeNone, "Enable verbose debug logging of the expression parsing and evaluation."},
 { LLDB_OPT_SET_ALL, false, "use-ir",           'i', no_argument,       NULL, 0, eArgTypeNone, "[Temporary] Instructs the expression evaluator to use IR instead of ASTs."},

Modified: lldb/trunk/source/Commands/CommandObjectExpression.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectExpression.h?rev=129623&r1=129622&r2=129623&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectExpression.h (original)
+++ lldb/trunk/source/Commands/CommandObjectExpression.h Fri Apr 15 19:01:13 2011
@@ -51,6 +51,7 @@
         lldb::Format    format;
         bool        debug;
         bool        print_object;
+        LazyBool    use_dynamic;
         bool        unwind_on_error;
         bool        show_types;
         bool        show_summary;

Modified: lldb/trunk/source/Commands/CommandObjectFrame.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectFrame.cpp?rev=129623&r1=129622&r2=129623&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectFrame.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectFrame.cpp Fri Apr 15 19:01:13 2011
@@ -310,6 +310,22 @@
             switch (short_option)
             {
             case 'o':   use_objc     = true;  break;
+            case 'd':
+                {
+                    bool success;
+                    bool result;
+                    result = Args::StringToBoolean(option_arg, true, &success);
+                    if (!success)
+                        error.SetErrorStringWithFormat("Invalid dynamic value setting: \"%s\".\n", option_arg);
+                    else
+                    {
+                        if (result)
+                            use_dynamic  = eLazyBoolYes;  
+                        else
+                            use_dynamic = eLazyBoolNo;
+                    }
+                }
+                break;
             case 'r':   use_regex    = true;  break;
             case 'a':   show_args    = false; break;
             case 'l':   show_locals  = false; break;
@@ -321,7 +337,7 @@
             case 'D':   debug        = true;  break;
             case 'f':   error = Args::StringToFormat(option_arg, format); break;
             case 'F':   flat_output  = true;  break;
-            case 'd':
+            case 'A':
                 max_depth = Args::StringToUInt32 (option_arg, UINT32_MAX, 0, &success);
                 if (!success)
                     error.SetErrorStringWithFormat("Invalid max depth '%s'.\n", option_arg);
@@ -364,6 +380,7 @@
             show_decl     = false;
             debug         = false;
             flat_output   = false;
+            use_dynamic   = eLazyBoolCalculate;
             max_depth     = UINT32_MAX;
             ptr_depth     = 0;
             format        = eFormatDefault;
@@ -391,6 +408,7 @@
              show_decl:1,
              debug:1,
              flat_output:1;
+        LazyBool     use_dynamic;
         uint32_t max_depth; // The depth to print when dumping concrete (not pointers) aggreate values
         uint32_t ptr_depth; // The default depth that is dumped when we find pointers
         lldb::Format format; // The format to use when dumping variables or children of variables
@@ -461,7 +479,28 @@
 
             VariableSP var_sp;
             ValueObjectSP valobj_sp;
-            //ValueObjectList &valobj_list = exe_ctx.frame->GetValueObjectList();
+
+            bool use_dynamic;
+            
+            // If use dynamic is not set, get it from the target:
+            switch (m_options.use_dynamic)
+            {
+            case eLazyBoolCalculate:
+                {   
+                    if (exe_ctx.target->GetPreferDynamicValue())
+                        use_dynamic = true;
+                    else
+                        use_dynamic = false;
+                }
+                break;
+            case eLazyBoolYes:
+                use_dynamic = true;
+                break;
+            case eLazyBoolNo:
+                use_dynamic = false;
+                break;
+            }
+            
             const char *name_cstr = NULL;
             size_t idx;
             if (!m_options.globals.empty())
@@ -473,12 +512,17 @@
                     for (idx = 0; idx < num_globals; ++idx)
                     {
                         VariableList global_var_list;
-                        const uint32_t num_matching_globals = exe_ctx.target->GetImages().FindGlobalVariables (m_options.globals[idx], true, UINT32_MAX, global_var_list);
+                        const uint32_t num_matching_globals 
+                                = exe_ctx.target->GetImages().FindGlobalVariables (m_options.globals[idx], 
+                                                                                   true, 
+                                                                                   UINT32_MAX, 
+                                                                                   global_var_list);
 
                         if (num_matching_globals == 0)
                         {
                             ++fail_count;
-                            result.GetErrorStream().Printf ("error: can't find global variable '%s'\n", m_options.globals[idx].AsCString());
+                            result.GetErrorStream().Printf ("error: can't find global variable '%s'\n", 
+                                                            m_options.globals[idx].AsCString());
                         }
                         else
                         {
@@ -487,9 +531,9 @@
                                 var_sp = global_var_list.GetVariableAtIndex(global_idx);
                                 if (var_sp)
                                 {
-                                    valobj_sp = exe_ctx.frame->GetValueObjectForFrameVariable (var_sp);
+                                    valobj_sp = exe_ctx.frame->GetValueObjectForFrameVariable (var_sp, use_dynamic);
                                     if (!valobj_sp)
-                                        valobj_sp = exe_ctx.frame->TrackGlobalVariable (var_sp);
+                                        valobj_sp = exe_ctx.frame->TrackGlobalVariable (var_sp, use_dynamic);
 
                                     if (valobj_sp)
                                     {
@@ -501,7 +545,7 @@
                                             var_sp->GetDeclaration ().DumpStopContext (&s, false);
                                             s.PutCString (": ");
                                         }
-
+                                        
                                         ValueObject::DumpValueObject (result.GetOutputStream(), 
                                                                       valobj_sp.get(), 
                                                                       name_cstr, 
@@ -510,7 +554,8 @@
                                                                       m_options.max_depth, 
                                                                       m_options.show_types,
                                                                       m_options.show_location,
-                                                                      m_options.use_objc, 
+                                                                      m_options.use_objc,
+                                                                      use_dynamic,
                                                                       false,
                                                                       m_options.flat_output);                                        
                                     }
@@ -541,7 +586,9 @@
                             if (regex.Compile(name_cstr))
                             {
                                 size_t num_matches = 0;
-                                const size_t num_new_regex_vars = variable_list->AppendVariablesIfUnique(regex, regex_var_list, num_matches);
+                                const size_t num_new_regex_vars = variable_list->AppendVariablesIfUnique(regex, 
+                                                                                                         regex_var_list, 
+                                                                                                         num_matches);
                                 if (num_new_regex_vars > 0)
                                 {
                                     for (uint32_t regex_idx = regex_start_index, end_index = regex_var_list.GetSize(); 
@@ -551,9 +598,9 @@
                                         var_sp = regex_var_list.GetVariableAtIndex (regex_idx);
                                         if (var_sp)
                                         {
-                                            valobj_sp = exe_ctx.frame->GetValueObjectForFrameVariable (var_sp);
+                                            valobj_sp = exe_ctx.frame->GetValueObjectForFrameVariable (var_sp, use_dynamic);
                                             if (valobj_sp)
-                                            {
+                                            {                                        
                                                 if (m_options.format != eFormatDefault)
                                                     valobj_sp->SetFormat (m_options.format);
                                                 
@@ -571,7 +618,8 @@
                                                                               m_options.max_depth, 
                                                                               m_options.show_types,
                                                                               m_options.show_location,
-                                                                              m_options.use_objc, 
+                                                                              m_options.use_objc,
+                                                                              use_dynamic, 
                                                                               false,
                                                                               m_options.flat_output);                                        
                                             }
@@ -595,10 +643,20 @@
                         else
                         {
                             Error error;
-                            const uint32_t expr_path_options = StackFrame::eExpressionPathOptionCheckPtrVsMember;
+                            uint32_t expr_path_options = StackFrame::eExpressionPathOptionCheckPtrVsMember;
+                            if (use_dynamic)
+                                expr_path_options |= StackFrame::eExpressionPathOptionsDynamicValue;
+                                
                             valobj_sp = exe_ctx.frame->GetValueForVariableExpressionPath (name_cstr, expr_path_options, error);
                             if (valobj_sp)
                             {
+//                                if (use_dynamic)
+//                                {
+//                                    lldb::ValueObjectSP dynamic_sp = valobj_sp->GetDynamicValue(true, valobj_sp);
+//                                    if (dynamic_sp != NULL)
+//                                        valobj_sp = dynamic_sp;
+//                                }
+//
                                 if (m_options.format != eFormatDefault)
                                     valobj_sp->SetFormat (m_options.format);
                                 
@@ -615,7 +673,8 @@
                                                               m_options.max_depth, 
                                                               m_options.show_types,
                                                               m_options.show_location,
-                                                              m_options.use_objc, 
+                                                              m_options.use_objc,
+                                                              use_dynamic,
                                                               false,
                                                               m_options.flat_output);
                             }
@@ -639,6 +698,7 @@
                         for (uint32_t i=0; i<num_variables; i++)
                         {
                             var_sp = variable_list->GetVariableAtIndex(i);
+                            
                             bool dump_variable = true;
                             
                             switch (var_sp->GetScope())
@@ -677,7 +737,7 @@
                                 // Use the variable object code to make sure we are
                                 // using the same APIs as the the public API will be
                                 // using...
-                                valobj_sp = exe_ctx.frame->GetValueObjectForFrameVariable (var_sp);
+                                valobj_sp = exe_ctx.frame->GetValueObjectForFrameVariable (var_sp, use_dynamic);
                                 if (valobj_sp)
                                 {
                                     if (m_options.format != eFormatDefault)
@@ -700,7 +760,8 @@
                                                                       m_options.max_depth, 
                                                                       m_options.show_types,
                                                                       m_options.show_location,
-                                                                      m_options.use_objc, 
+                                                                      m_options.use_objc,
+                                                                      use_dynamic, 
                                                                       false,
                                                                       m_options.flat_output);                                        
                                     }
@@ -722,22 +783,23 @@
 OptionDefinition
 CommandObjectFrameVariable::CommandOptions::g_option_table[] =
 {
-{ LLDB_OPT_SET_1, false, "debug",      'D', no_argument,       NULL, 0, eArgTypeNone,    "Enable verbose debug information."},
-{ LLDB_OPT_SET_1, false, "depth",      'd', required_argument, NULL, 0, eArgTypeCount,   "Set the max recurse depth when dumping aggregate types (default is infinity)."},
-{ LLDB_OPT_SET_1, false, "show-globals",'g', no_argument,      NULL, 0, eArgTypeNone,    "Show the current frame source file global and static variables."},
-{ LLDB_OPT_SET_1, false, "find-global",'G', required_argument, NULL, 0, eArgTypeVarName, "Find a global variable by name (which might not be in the current stack frame source file)."},
-{ LLDB_OPT_SET_1, false, "location",   'L', no_argument,       NULL, 0, eArgTypeNone,    "Show variable location information."},
-{ LLDB_OPT_SET_1, false, "show-declaration", 'c', no_argument, NULL, 0, eArgTypeNone,    "Show variable declaration information (source file and line where the variable was declared)."},
-{ LLDB_OPT_SET_1, false, "no-args",    'a', no_argument,       NULL, 0, eArgTypeNone,    "Omit function arguments."},
-{ LLDB_OPT_SET_1, false, "no-locals",  'l', no_argument,       NULL, 0, eArgTypeNone,    "Omit local variables."},
-{ LLDB_OPT_SET_1, false, "show-types", 't', no_argument,       NULL, 0, eArgTypeNone,    "Show variable types when dumping values."},
-{ LLDB_OPT_SET_1, false, "no-summary", 'y', no_argument,       NULL, 0, eArgTypeNone,    "Omit summary information."},
-{ LLDB_OPT_SET_1, false, "scope",      's', no_argument,       NULL, 0, eArgTypeNone,    "Show variable scope (argument, local, global, static)."},
-{ LLDB_OPT_SET_1, false, "objc",       'o', no_argument,       NULL, 0, eArgTypeNone,    "When looking up a variable by name, print as an Objective-C object."},
-{ LLDB_OPT_SET_1, false, "ptr-depth",  'p', required_argument, NULL, 0, eArgTypeCount,   "The number of pointers to be traversed when dumping values (default is zero)."},
-{ LLDB_OPT_SET_1, false, "regex",      'r', no_argument,       NULL, 0, eArgTypeRegularExpression,    "The <variable-name> argument for name lookups are regular expressions."},
-{ LLDB_OPT_SET_1, false, "flat",       'F', no_argument,       NULL, 0, eArgTypeNone,    "Display results in a flat format that uses expression paths for each variable or member."},
-{ LLDB_OPT_SET_1, false, "format",     'f', required_argument, NULL, 0, eArgTypeExprFormat,  "Specify the format that the variable output should use."},
+{ LLDB_OPT_SET_1, false, "aggregate-depth", 'A', required_argument, NULL, 0, eArgTypeCount,   "Set the max recurse depth when dumping aggregate types (default is infinity)."},
+{ LLDB_OPT_SET_1, false, "no-args",         'a', no_argument,       NULL, 0, eArgTypeNone,    "Omit function arguments."},
+{ LLDB_OPT_SET_1, false, "show-declaration",'c', no_argument,       NULL, 0, eArgTypeNone,    "Show variable declaration information (source file and line where the variable was declared)."},
+{ LLDB_OPT_SET_1, false, "debug",           'D', no_argument,       NULL, 0, eArgTypeNone,    "Enable verbose debug information."},
+{ LLDB_OPT_SET_1, false, "dynamic-type",    'd', required_argument, NULL, 0, eArgTypeBoolean, "Show the object as its full dynamic type, not its static type, if available."},
+{ LLDB_OPT_SET_1, false, "format",          'f', required_argument, NULL, 0, eArgTypeExprFormat,  "Specify the format that the variable output should use."},
+{ LLDB_OPT_SET_1, false, "flat",            'F', no_argument,       NULL, 0, eArgTypeNone,    "Display results in a flat format that uses expression paths for each variable or member."},
+{ LLDB_OPT_SET_1, false, "show-globals",    'g', no_argument,       NULL, 0, eArgTypeNone,    "Show the current frame source file global and static variables."},
+{ LLDB_OPT_SET_1, false, "find-global",     'G', required_argument, NULL, 0, eArgTypeVarName, "Find a global variable by name (which might not be in the current stack frame source file)."},
+{ LLDB_OPT_SET_1, false, "location",        'L', no_argument,       NULL, 0, eArgTypeNone,    "Show variable location information."},
+{ LLDB_OPT_SET_1, false, "no-locals",       'l', no_argument,       NULL, 0, eArgTypeNone,    "Omit local variables."},
+{ LLDB_OPT_SET_1, false, "objc",            'o', no_argument,       NULL, 0, eArgTypeNone,    "When looking up a variable by name, print as an Objective-C object."},
+{ LLDB_OPT_SET_1, false, "ptr-depth",       'p', required_argument, NULL, 0, eArgTypeCount,   "The number of pointers to be traversed when dumping values (default is zero)."},
+{ LLDB_OPT_SET_1, false, "regex",           'r', no_argument,       NULL, 0, eArgTypeRegularExpression,    "The <variable-name> argument for name lookups are regular expressions."},
+{ LLDB_OPT_SET_1, false, "scope",           's', no_argument,       NULL, 0, eArgTypeNone,    "Show variable scope (argument, local, global, static)."},
+{ LLDB_OPT_SET_1, false, "show-types",      't', no_argument,       NULL, 0, eArgTypeNone,    "Show variable types when dumping values."},
+{ LLDB_OPT_SET_1, false, "no-summary",      'y', no_argument,       NULL, 0, eArgTypeNone,    "Omit summary information."},
 { 0, false, NULL, 0, 0, NULL, NULL, eArgTypeNone, NULL }
 };
 #pragma mark CommandObjectMultiwordFrame

Modified: lldb/trunk/source/Core/ValueObject.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ValueObject.cpp?rev=129623&r1=129622&r2=129623&view=diff
==============================================================================
--- lldb/trunk/source/Core/ValueObject.cpp (original)
+++ lldb/trunk/source/Core/ValueObject.cpp Fri Apr 15 19:01:13 2011
@@ -22,6 +22,7 @@
 #include "lldb/Core/StreamString.h"
 #include "lldb/Core/ValueObjectChild.h"
 #include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/Core/ValueObjectDynamicValue.h"
 #include "lldb/Core/ValueObjectList.h"
 
 #include "lldb/Host/Endian.h"
@@ -159,15 +160,10 @@
     return m_error.Success();
 }
 
-const DataExtractor &
-ValueObject::GetDataExtractor () const
-{
-    return m_data;
-}
-
 DataExtractor &
 ValueObject::GetDataExtractor ()
 {
+    UpdateValueIfNeeded();
     return m_data;
 }
 
@@ -281,17 +277,20 @@
 ValueObject::GetChildAtIndex (uint32_t idx, bool can_create)
 {
     ValueObjectSP child_sp;
-    if (idx < GetNumChildren())
+    if (UpdateValueIfNeeded())
     {
-        // Check if we have already made the child value object?
-        if (can_create && m_children[idx].get() == NULL)
+        if (idx < GetNumChildren())
         {
-            // No we haven't created the child at this index, so lets have our
-            // subclass do it and cache the result for quick future access.
-            m_children[idx] = CreateChildAtIndex (idx, false, 0);
-        }
+            // Check if we have already made the child value object?
+            if (can_create && m_children[idx].get() == NULL)
+            {
+                // No we haven't created the child at this index, so lets have our
+                // subclass do it and cache the result for quick future access.
+                m_children[idx] = CreateChildAtIndex (idx, false, 0);
+            }
 
-        child_sp = m_children[idx];
+            child_sp = m_children[idx];
+        }
     }
     return child_sp;
 }
@@ -312,34 +311,38 @@
     // when getting a child by name, it could be buried inside some base
     // classes (which really aren't part of the expression path), so we
     // need a vector of indexes that can get us down to the correct child
-    std::vector<uint32_t> child_indexes;
-    clang::ASTContext *clang_ast = GetClangAST();
-    void *clang_type = GetClangType();
-    bool omit_empty_base_classes = true;
-    const size_t num_child_indexes =  ClangASTContext::GetIndexOfChildMemberWithName (clang_ast,
-                                                                                      clang_type,
-                                                                                      name.GetCString(),
-                                                                                      omit_empty_base_classes,
-                                                                                      child_indexes);
     ValueObjectSP child_sp;
-    if (num_child_indexes > 0)
-    {
-        std::vector<uint32_t>::const_iterator pos = child_indexes.begin ();
-        std::vector<uint32_t>::const_iterator end = child_indexes.end ();
 
-        child_sp = GetChildAtIndex(*pos, can_create);
-        for (++pos; pos != end; ++pos)
+    if (UpdateValueIfNeeded())
+    {
+        std::vector<uint32_t> child_indexes;
+        clang::ASTContext *clang_ast = GetClangAST();
+        void *clang_type = GetClangType();
+        bool omit_empty_base_classes = true;
+        const size_t num_child_indexes =  ClangASTContext::GetIndexOfChildMemberWithName (clang_ast,
+                                                                                          clang_type,
+                                                                                          name.GetCString(),
+                                                                                          omit_empty_base_classes,
+                                                                                          child_indexes);
+        if (num_child_indexes > 0)
         {
-            if (child_sp)
-            {
-                ValueObjectSP new_child_sp(child_sp->GetChildAtIndex (*pos, can_create));
-                child_sp = new_child_sp;
-            }
-            else
+            std::vector<uint32_t>::const_iterator pos = child_indexes.begin ();
+            std::vector<uint32_t>::const_iterator end = child_indexes.end ();
+
+            child_sp = GetChildAtIndex(*pos, can_create);
+            for (++pos; pos != end; ++pos)
             {
-                child_sp.reset();
-            }
+                if (child_sp)
+                {
+                    ValueObjectSP new_child_sp(child_sp->GetChildAtIndex (*pos, can_create));
+                    child_sp = new_child_sp;
+                }
+                else
+                {
+                    child_sp.reset();
+                }
 
+            }
         }
     }
     return child_sp;
@@ -378,55 +381,60 @@
 ValueObject::CreateChildAtIndex (uint32_t idx, bool synthetic_array_member, int32_t synthetic_index)
 {
     ValueObjectSP valobj_sp;
-    bool omit_empty_base_classes = true;
+    
+    if (UpdateValueIfNeeded())
+    {
+        bool omit_empty_base_classes = true;
+
+        std::string child_name_str;
+        uint32_t child_byte_size = 0;
+        int32_t child_byte_offset = 0;
+        uint32_t child_bitfield_bit_size = 0;
+        uint32_t child_bitfield_bit_offset = 0;
+        bool child_is_base_class = false;
+        bool child_is_deref_of_parent = false;
+
+        const bool transparent_pointers = synthetic_array_member == false;
+        clang::ASTContext *clang_ast = GetClangAST();
+        clang_type_t clang_type = GetClangType();
+        clang_type_t child_clang_type;
+        child_clang_type = ClangASTContext::GetChildClangTypeAtIndex (clang_ast,
+                                                                      GetName().GetCString(),
+                                                                      clang_type,
+                                                                      idx,
+                                                                      transparent_pointers,
+                                                                      omit_empty_base_classes,
+                                                                      child_name_str,
+                                                                      child_byte_size,
+                                                                      child_byte_offset,
+                                                                      child_bitfield_bit_size,
+                                                                      child_bitfield_bit_offset,
+                                                                      child_is_base_class,
+                                                                      child_is_deref_of_parent);
+        if (child_clang_type && child_byte_size)
+        {
+            if (synthetic_index)
+                child_byte_offset += child_byte_size * synthetic_index;
+
+            ConstString child_name;
+            if (!child_name_str.empty())
+                child_name.SetCString (child_name_str.c_str());
 
-    std::string child_name_str;
-    uint32_t child_byte_size = 0;
-    int32_t child_byte_offset = 0;
-    uint32_t child_bitfield_bit_size = 0;
-    uint32_t child_bitfield_bit_offset = 0;
-    bool child_is_base_class = false;
-    bool child_is_deref_of_parent = false;
-
-    const bool transparent_pointers = synthetic_array_member == false;
-    clang::ASTContext *clang_ast = GetClangAST();
-    clang_type_t clang_type = GetClangType();
-    clang_type_t child_clang_type;
-    child_clang_type = ClangASTContext::GetChildClangTypeAtIndex (clang_ast,
-                                                                  GetName().GetCString(),
-                                                                  clang_type,
-                                                                  idx,
-                                                                  transparent_pointers,
-                                                                  omit_empty_base_classes,
-                                                                  child_name_str,
-                                                                  child_byte_size,
-                                                                  child_byte_offset,
-                                                                  child_bitfield_bit_size,
-                                                                  child_bitfield_bit_offset,
-                                                                  child_is_base_class,
-                                                                  child_is_deref_of_parent);
-    if (child_clang_type && child_byte_size)
-    {
-        if (synthetic_index)
-            child_byte_offset += child_byte_size * synthetic_index;
-
-        ConstString child_name;
-        if (!child_name_str.empty())
-            child_name.SetCString (child_name_str.c_str());
-
-        valobj_sp.reset (new ValueObjectChild (*this,
-                                               clang_ast,
-                                               child_clang_type,
-                                               child_name,
-                                               child_byte_size,
-                                               child_byte_offset,
-                                               child_bitfield_bit_size,
-                                               child_bitfield_bit_offset,
-                                               child_is_base_class,
-                                               child_is_deref_of_parent));
-        if (m_pointers_point_to_load_addrs)
-            valobj_sp->SetPointersPointToLoadAddrs (m_pointers_point_to_load_addrs);
+            valobj_sp.reset (new ValueObjectChild (*this,
+                                                   clang_ast,
+                                                   child_clang_type,
+                                                   child_name,
+                                                   child_byte_size,
+                                                   child_byte_offset,
+                                                   child_bitfield_bit_size,
+                                                   child_bitfield_bit_offset,
+                                                   child_is_base_class,
+                                                   child_is_deref_of_parent));
+            if (m_pointers_point_to_load_addrs)
+                valobj_sp->SetPointersPointToLoadAddrs (m_pointers_point_to_load_addrs);
+        }
     }
+    
     return valobj_sp;
 }
 
@@ -710,6 +718,9 @@
 addr_t
 ValueObject::GetAddressOf (AddressType &address_type, bool scalar_is_load_address)
 {
+    if (!UpdateValueIfNeeded())
+        return LLDB_INVALID_ADDRESS;
+        
     switch (m_value.GetValueType())
     {
     case Value::eValueTypeScalar:
@@ -738,6 +749,10 @@
 {
     lldb::addr_t address = LLDB_INVALID_ADDRESS;
     address_type = eAddressTypeInvalid;
+    
+    if (!UpdateValueIfNeeded())
+        return address;
+        
     switch (m_value.GetValueType())
     {
     case Value::eValueTypeScalar:
@@ -957,16 +972,66 @@
     return synthetic_child_sp;
 }
 
-bool
-ValueObject::SetDynamicValue ()
+void
+ValueObject::CalculateDynamicValue ()
 {
-    if (!IsPointerOrReferenceType())
-        return false;
+    if (!m_dynamic_value_sp && !IsDynamic())
+    {
+        Process *process = m_update_point.GetProcess();
+        bool worth_having_dynamic_value = false;
         
-    // Check that the runtime class is correct for determining the most specific class.
-    // If it is a C++ class, see if it is dynamic:
-    
-    return true;
+        
+        // FIXME: Process should have some kind of "map over Runtimes" so we don't have to
+        // hard code this everywhere.
+        lldb::LanguageType known_type = GetObjectRuntimeLanguage();
+        if (known_type != lldb::eLanguageTypeUnknown && known_type != lldb::eLanguageTypeC)
+        {
+            LanguageRuntime *runtime = process->GetLanguageRuntime (known_type);
+            if (runtime)
+                worth_having_dynamic_value = runtime->CouldHaveDynamicValue(*this);
+        }
+        else
+        {
+            LanguageRuntime *cpp_runtime = process->GetLanguageRuntime (lldb::eLanguageTypeC_plus_plus);
+            if (cpp_runtime)
+                worth_having_dynamic_value = cpp_runtime->CouldHaveDynamicValue(*this);
+            
+            if (!worth_having_dynamic_value)
+            {
+                LanguageRuntime *objc_runtime = process->GetLanguageRuntime (lldb::eLanguageTypeObjC);
+                if (objc_runtime)
+                    worth_having_dynamic_value = cpp_runtime->CouldHaveDynamicValue(*this);
+            }
+        }
+        
+        if (worth_having_dynamic_value)
+            m_dynamic_value_sp.reset (new ValueObjectDynamicValue (*this));
+    }
+}
+
+lldb::ValueObjectSP
+ValueObject::GetDynamicValue (bool can_create)
+{
+    if (!IsDynamic() && m_dynamic_value_sp == NULL && can_create)
+    {
+        CalculateDynamicValue();
+    }
+    return m_dynamic_value_sp;
+}
+
+lldb::ValueObjectSP
+ValueObject::GetDynamicValue (bool can_create, lldb::ValueObjectSP &owning_valobj_sp)
+{
+    if (!IsDynamic() && m_dynamic_value_sp == NULL && can_create)
+    {
+        CalculateDynamicValue();
+        if (m_dynamic_value_sp)
+        {
+            ValueObjectDynamicValue *as_dynamic_value = static_cast<ValueObjectDynamicValue *>(m_dynamic_value_sp.get());
+            as_dynamic_value->SetOwningSP (owning_valobj_sp);
+        }
+    }
+    return m_dynamic_value_sp;
 }
 
 bool
@@ -974,7 +1039,7 @@
 {
     if (IsBaseClass())
     {
-        bool parent_had_base_class = m_parent && m_parent->GetBaseClassPath (s);
+        bool parent_had_base_class = GetParent() && GetParent()->GetBaseClassPath (s);
         clang_type_t clang_type = GetClangType();
         std::string cxx_class_name;
         bool this_had_base_class = ClangASTContext::GetCXXClassName (clang_type, cxx_class_name);
@@ -993,12 +1058,12 @@
 ValueObject *
 ValueObject::GetNonBaseClassParent()
 {
-    if (m_parent)
+    if (GetParent())
     {
-        if (m_parent->IsBaseClass())
-            return m_parent->GetNonBaseClassParent();
+        if (GetParent()->IsBaseClass())
+            return GetParent()->GetNonBaseClassParent();
         else
-            return m_parent;
+            return GetParent();
     }
     return NULL;
 }
@@ -1011,8 +1076,8 @@
     if (is_deref_of_parent)
         s.PutCString("*(");
 
-    if (m_parent)
-        m_parent->GetExpressionPath (s, qualify_cxx_base_classes);
+    if (GetParent())
+        GetParent()->GetExpressionPath (s, qualify_cxx_base_classes);
     
     if (!IsBaseClass())
     {
@@ -1067,12 +1132,20 @@
     bool show_types,
     bool show_location,
     bool use_objc,
+    bool use_dynamic,
     bool scope_already_checked,
     bool flat_output
 )
 {
     if (valobj  && valobj->UpdateValueIfNeeded ())
     {
+        if (use_dynamic)
+        {
+            ValueObject *dynamic_value = valobj->GetDynamicValue(true).get();
+            if (dynamic_value)
+                valobj = dynamic_value;
+        }
+        
         clang_type_t clang_type = valobj->GetClangType();
 
         const Flags type_flags (ClangASTContext::GetTypeInfo (clang_type, NULL, NULL));
@@ -1216,6 +1289,7 @@
                                                  show_types,
                                                  show_location,
                                                  false,
+                                                 use_dynamic,
                                                  true,
                                                  flat_output);
                             }
@@ -1296,7 +1370,9 @@
 lldb::ValueObjectSP
 ValueObject::Dereference (Error &error)
 {
-    lldb::ValueObjectSP valobj_sp;
+    if (m_deref_valobj_sp)
+        return m_deref_valobj_sp;
+        
     const bool is_pointer_type = IsPointerType();
     if (is_pointer_type)
     {
@@ -1332,20 +1408,20 @@
             if (!child_name_str.empty())
                 child_name.SetCString (child_name_str.c_str());
 
-            valobj_sp.reset (new ValueObjectChild (*this,
-                                                   clang_ast,
-                                                   child_clang_type,
-                                                   child_name,
-                                                   child_byte_size,
-                                                   child_byte_offset,
-                                                   child_bitfield_bit_size,
-                                                   child_bitfield_bit_offset,
-                                                   child_is_base_class,
-                                                   child_is_deref_of_parent));
+            m_deref_valobj_sp.reset (new ValueObjectChild (*this,
+                                                           clang_ast,
+                                                           child_clang_type,
+                                                           child_name,
+                                                           child_byte_size,
+                                                           child_byte_offset,
+                                                           child_bitfield_bit_size,
+                                                           child_bitfield_bit_offset,
+                                                           child_is_base_class,
+                                                           child_is_deref_of_parent));
         }
     }
 
-    if (valobj_sp)
+    if (m_deref_valobj_sp)
     {
         error.Clear();
     }
@@ -1360,13 +1436,15 @@
             error.SetErrorStringWithFormat("not a pointer type: (%s) %s", GetTypeName().AsCString("<invalid type>"), strm.GetString().c_str());
     }
 
-    return valobj_sp;
+    return m_deref_valobj_sp;
 }
 
-    lldb::ValueObjectSP
+lldb::ValueObjectSP
 ValueObject::AddressOf (Error &error)
 {
-    lldb::ValueObjectSP valobj_sp;
+    if (m_addr_of_valobj_sp)
+        return m_addr_of_valobj_sp;
+        
     AddressType address_type = eAddressTypeInvalid;
     const bool scalar_is_load_address = false;
     lldb::addr_t addr = GetAddressOf (address_type, scalar_is_load_address);
@@ -1394,19 +1472,19 @@
                 {
                     std::string name (1, '&');
                     name.append (m_name.AsCString(""));
-                    valobj_sp.reset (new ValueObjectConstResult (GetExecutionContextScope(),
-                                                                 ast, 
-                                                                 ClangASTContext::CreatePointerType (ast, clang_type),
-                                                                 ConstString (name.c_str()),
-                                                                 addr, 
-                                                                 eAddressTypeInvalid,
-                                                                 m_data.GetAddressByteSize()));
+                    m_addr_of_valobj_sp.reset (new ValueObjectConstResult (GetExecutionContextScope(),
+                                                                           ast, 
+                                                                           ClangASTContext::CreatePointerType (ast, clang_type),
+                                                                           ConstString (name.c_str()),
+                                                                           addr, 
+                                                                           eAddressTypeInvalid,
+                                                                           m_data.GetAddressByteSize()));
                 }
             }
             break;
         }
     }
-    return valobj_sp;
+    return m_addr_of_valobj_sp;
 }
 
 ValueObject::EvaluationPoint::EvaluationPoint () :
@@ -1523,10 +1601,16 @@
         return false;
         
     // If our stop id is the current stop ID, nothing has changed:
-    if (m_stop_id == m_process_sp->GetStopID())
+    uint32_t cur_stop_id = m_process_sp->GetStopID();
+    if (m_stop_id == cur_stop_id)
         return false;
     
-    m_stop_id = m_process_sp->GetStopID();
+    // If the current stop id is 0, either we haven't run yet, or the process state has been cleared.
+    // In either case, we aren't going to be able to sync with the process state.
+    if (cur_stop_id == 0)
+        return false;
+        
+    m_stop_id = cur_stop_id;
     m_needs_update = true;
     m_exe_scope = m_process_sp.get();
     

Modified: lldb/trunk/source/Core/ValueObjectChild.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ValueObjectChild.cpp?rev=129623&r1=129622&r2=129623&view=diff
==============================================================================
--- lldb/trunk/source/Core/ValueObjectChild.cpp (original)
+++ lldb/trunk/source/Core/ValueObjectChild.cpp Fri Apr 15 19:01:13 2011
@@ -97,7 +97,7 @@
     ValueObject* parent = m_parent;
     if (parent)
     {
-        if (parent->UpdateValue())
+        if (parent->UpdateValueIfNeeded())
         {
             m_value.SetContext(Value::eContextTypeClangType, m_clang_type);
 

Added: lldb/trunk/source/Core/ValueObjectDynamicValue.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ValueObjectDynamicValue.cpp?rev=129623&view=auto
==============================================================================
--- lldb/trunk/source/Core/ValueObjectDynamicValue.cpp (added)
+++ lldb/trunk/source/Core/ValueObjectDynamicValue.cpp Fri Apr 15 19:01:13 2011
@@ -0,0 +1,254 @@
+//===-- ValueObjectDynamicValue.cpp ---------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+
+#include "lldb/Core/ValueObjectDynamicValue.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Module.h"
+#include "lldb/Core/ValueObjectList.h"
+#include "lldb/Core/Value.h"
+#include "lldb/Core/ValueObject.h"
+
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Symbol/Type.h"
+#include "lldb/Symbol/Variable.h"
+
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/LanguageRuntime.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+
+
+using namespace lldb_private;
+
+ValueObjectDynamicValue::ValueObjectDynamicValue (ValueObject &parent) :
+    ValueObject(parent),
+    m_address (),
+    m_type_sp()
+{
+    // THINK ABOUT: It looks ugly to doctor up the name like this.  But if
+    // people find it confusing to tell the difference, we may want to do something...
+    
+//    std::string dynamic_name ("<dynamic value for \"");
+//    dynamic_name.append(parent.GetName().AsCString());
+//    dynamic_name.append("\">");
+//    
+//    SetName (dynamic_name.c_str()); 
+    SetName (parent.GetName().AsCString());
+}
+
+ValueObjectDynamicValue::~ValueObjectDynamicValue()
+{
+    m_owning_valobj_sp.reset();
+}
+
+lldb::clang_type_t
+ValueObjectDynamicValue::GetClangType ()
+{
+    if (m_type_sp)
+        return m_value.GetClangType();
+    else
+        return m_parent->GetClangType();
+}
+
+ConstString
+ValueObjectDynamicValue::GetTypeName()
+{
+    // FIXME: Maybe cache the name, but have to clear it out if the type changes...
+    if (!UpdateValueIfNeeded())
+        return ConstString("<unknown type>");
+        
+    if (m_type_sp)
+        return ClangASTType::GetClangTypeName (GetClangType());
+    else
+        return m_parent->GetTypeName();
+}
+
+uint32_t
+ValueObjectDynamicValue::CalculateNumChildren()
+{
+    if (!UpdateValueIfNeeded())
+        return 0;
+        
+    if (m_type_sp)
+        return ClangASTContext::GetNumChildren (GetClangAST (), GetClangType(), true);
+    else
+        return m_parent->GetNumChildren();
+}
+
+clang::ASTContext *
+ValueObjectDynamicValue::GetClangAST ()
+{
+    if (!UpdateValueIfNeeded())
+        return NULL;
+        
+    if (m_type_sp)
+        return m_type_sp->GetClangAST();
+    else
+        return m_parent->GetClangAST ();
+}
+
+size_t
+ValueObjectDynamicValue::GetByteSize()
+{
+    if (!UpdateValueIfNeeded())
+        return 0;
+        
+    if (m_type_sp)
+        return m_value.GetValueByteSize(GetClangAST(), NULL);
+    else
+        return m_parent->GetByteSize();
+}
+
+lldb::ValueType
+ValueObjectDynamicValue::GetValueType() const
+{
+    return m_parent->GetValueType();
+}
+
+bool
+ValueObjectDynamicValue::UpdateValue ()
+{
+    SetValueIsValid (false);
+    m_error.Clear();
+
+    if (!m_parent->UpdateValueIfNeeded())
+    {
+        return false;
+    }
+    
+    ExecutionContext exe_ctx (GetExecutionContextScope());
+    
+    if (exe_ctx.target)
+    {
+        m_data.SetByteOrder(exe_ctx.target->GetArchitecture().GetByteOrder());
+        m_data.SetAddressByteSize(exe_ctx.target->GetArchitecture().GetAddressByteSize());
+    }
+    
+    // First make sure our Type and/or Address haven't changed:
+    Process *process = m_update_point.GetProcess();
+    if (!process)
+        return false;
+    
+    lldb::TypeSP dynamic_type_sp;
+    Address dynamic_address;
+    bool found_dynamic_type = false;
+    
+    lldb::LanguageType known_type = m_parent->GetObjectRuntimeLanguage();
+    if (known_type != lldb::eLanguageTypeUnknown && known_type != lldb::eLanguageTypeC)
+    {
+        LanguageRuntime *runtime = process->GetLanguageRuntime (known_type);
+        if (runtime)
+            found_dynamic_type = runtime->GetDynamicValue(*m_parent, dynamic_type_sp, dynamic_address);
+    }
+    else
+    {
+        LanguageRuntime *cpp_runtime = process->GetLanguageRuntime (lldb::eLanguageTypeC_plus_plus);
+        if (cpp_runtime)
+            found_dynamic_type = cpp_runtime->GetDynamicValue(*m_parent, dynamic_type_sp, dynamic_address);
+        
+        if (!found_dynamic_type)
+        {
+            LanguageRuntime *objc_runtime = process->GetLanguageRuntime (lldb::eLanguageTypeObjC);
+            if (objc_runtime)
+                found_dynamic_type = cpp_runtime->GetDynamicValue(*m_parent, dynamic_type_sp, dynamic_address);
+        }
+    }
+    
+    // If we don't have a dynamic type, then make ourselves just a echo of our parent.
+    // Or we could return false, and make ourselves an echo of our parent?
+    if (!found_dynamic_type)
+    {
+        if (m_type_sp)
+            SetValueDidChange(true);
+        m_value = m_parent->GetValue();
+        m_error = m_value.GetValueAsData (&exe_ctx, GetClangAST(), m_data, 0);
+        return m_error.Success();
+    }
+    
+    Value old_value(m_value);
+
+    if (!m_type_sp)
+    {
+        m_type_sp = dynamic_type_sp;
+    }
+    else if (dynamic_type_sp != m_type_sp)
+    {
+        // We are another type, we need to tear down our children...
+        m_type_sp = dynamic_type_sp;
+        SetValueDidChange (true);
+    }
+    
+    if (!m_address.IsValid() || m_address != dynamic_address)
+    {
+        if (m_address.IsValid())
+            SetValueDidChange (true);
+            
+        // We've moved, so we should be fine...
+        m_address = dynamic_address;
+        lldb::addr_t load_address = m_address.GetLoadAddress(m_update_point.GetTarget());
+        m_value.GetScalar() = load_address;
+    }
+    
+    // The type will always be the type of the dynamic object.  If our parent's type was a pointer,
+    // then our type should be a pointer to the type of the dynamic object.  If a reference, then the original type
+    // should be okay...
+    lldb::clang_type_t orig_type = m_type_sp->GetClangForwardType();
+    lldb::clang_type_t corrected_type = orig_type;
+    if (m_parent->IsPointerType())
+        corrected_type = ClangASTContext::CreatePointerType (m_type_sp->GetClangAST(), orig_type);
+    else if (m_parent->IsPointerOrReferenceType())
+        corrected_type = ClangASTContext::CreateLValueReferenceType (m_type_sp->GetClangAST(), orig_type);
+        
+    m_value.SetContext (Value::eContextTypeClangType, corrected_type);
+    
+    // Our address is the location of the dynamic type stored in memory.  It isn't a load address,
+    // because we aren't pointing to the LOCATION that stores the pointer to us, we're pointing to us...
+    m_value.SetValueType(Value::eValueTypeScalar);
+
+    if (m_address.IsValid() && m_type_sp)
+    {
+        // The variable value is in the Scalar value inside the m_value.
+        // We can point our m_data right to it.
+        m_error = m_value.GetValueAsData (&exe_ctx, GetClangAST(), m_data, 0);
+        if (m_error.Success())
+        {
+            if (ClangASTContext::IsAggregateType (GetClangType()))
+            {
+                // this value object represents an aggregate type whose
+                // children have values, but this object does not. So we
+                // say we are changed if our location has changed.
+                SetValueDidChange (m_value.GetValueType() != old_value.GetValueType() || m_value.GetScalar() != old_value.GetScalar());
+            }
+
+            SetValueIsValid (true);
+            return true;
+        }
+    }
+    
+    // We get here if we've failed above...
+    SetValueIsValid (false);
+    return false;
+}
+
+
+
+bool
+ValueObjectDynamicValue::IsInScope ()
+{
+    return m_parent->IsInScope();
+}
+

Added: lldb/trunk/source/Core/ValueObjectMemory.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ValueObjectMemory.cpp?rev=129623&view=auto
==============================================================================
--- lldb/trunk/source/Core/ValueObjectMemory.cpp (added)
+++ lldb/trunk/source/Core/ValueObjectMemory.cpp Fri Apr 15 19:01:13 2011
@@ -0,0 +1,196 @@
+//===-- ValueObjectMemory.cpp ---------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+
+#include "lldb/Core/ValueObjectMemory.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Module.h"
+#include "lldb/Core/ValueObjectList.h"
+#include "lldb/Core/Value.h"
+#include "lldb/Core/ValueObject.h"
+
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Symbol/Type.h"
+#include "lldb/Symbol/Variable.h"
+
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+
+
+using namespace lldb_private;
+
+ValueObjectMemory::ValueObjectMemory (ExecutionContextScope *exe_scope,
+                                      const char *name, 
+                                      const Address &address,
+                                      lldb::TypeSP &type_sp) :
+    ValueObject(exe_scope),
+    m_address (address),
+    m_type_sp(type_sp)
+{
+    // Do not attempt to construct one of these objects with no variable!
+    assert (m_type_sp.get() != NULL);
+    SetName (name);
+    m_value.SetContext(Value::eContextTypeLLDBType, m_type_sp.get());
+    lldb::addr_t load_address = m_address.GetLoadAddress(m_update_point.GetTarget());
+    if (load_address != LLDB_INVALID_ADDRESS)
+    {
+        m_value.SetValueType(Value::eValueTypeLoadAddress);
+        m_value.GetScalar() = load_address;
+    }
+    else
+    {
+        lldb::addr_t file_address = m_address.GetFileAddress();
+        if (file_address != LLDB_INVALID_ADDRESS)
+        {
+            m_value.SetValueType(Value::eValueTypeFileAddress);
+            m_value.GetScalar() = file_address;
+        }
+        else
+        {
+            m_value.GetScalar() = m_address.GetOffset();
+            m_value.SetValueType (Value::eValueTypeScalar);
+        }
+    }
+}
+
+ValueObjectMemory::~ValueObjectMemory()
+{
+}
+
+lldb::clang_type_t
+ValueObjectMemory::GetClangType ()
+{
+    return m_type_sp->GetClangForwardType();
+}
+
+ConstString
+ValueObjectMemory::GetTypeName()
+{
+    return m_type_sp->GetName();
+}
+
+uint32_t
+ValueObjectMemory::CalculateNumChildren()
+{
+    return m_type_sp->GetNumChildren(true);
+}
+
+clang::ASTContext *
+ValueObjectMemory::GetClangAST ()
+{
+    return m_type_sp->GetClangAST();
+}
+
+size_t
+ValueObjectMemory::GetByteSize()
+{
+    return m_type_sp->GetByteSize();
+}
+
+lldb::ValueType
+ValueObjectMemory::GetValueType() const
+{
+    // RETHINK: Should this be inherited from somewhere?
+    return lldb::eValueTypeVariableGlobal;
+}
+
+bool
+ValueObjectMemory::UpdateValue ()
+{
+    SetValueIsValid (false);
+    m_error.Clear();
+
+    ExecutionContext exe_ctx (GetExecutionContextScope());
+    
+    if (exe_ctx.target)
+    {
+        m_data.SetByteOrder(exe_ctx.target->GetArchitecture().GetByteOrder());
+        m_data.SetAddressByteSize(exe_ctx.target->GetArchitecture().GetAddressByteSize());
+    }
+
+    Value old_value(m_value);
+    if (m_address.IsValid())
+    {
+        Value::ValueType value_type = m_value.GetValueType();
+
+        switch (value_type)
+        {
+        default:
+            assert(!"Unhandled expression result value kind...");
+            break;
+
+        case Value::eValueTypeScalar:
+            // The variable value is in the Scalar value inside the m_value.
+            // We can point our m_data right to it.
+            m_error = m_value.GetValueAsData (&exe_ctx, GetClangAST(), m_data, 0);
+            break;
+
+        case Value::eValueTypeFileAddress:
+        case Value::eValueTypeLoadAddress:
+        case Value::eValueTypeHostAddress:
+            // The DWARF expression result was an address in the inferior
+            // process. If this variable is an aggregate type, we just need
+            // the address as the main value as all child variable objects
+            // will rely upon this location and add an offset and then read
+            // their own values as needed. If this variable is a simple
+            // type, we read all data for it into m_data.
+            // Make sure this type has a value before we try and read it
+
+            // If we have a file address, convert it to a load address if we can.
+            if (value_type == Value::eValueTypeFileAddress && exe_ctx.process)
+            {
+                lldb::addr_t load_addr = m_address.GetLoadAddress(exe_ctx.target);
+                if (load_addr != LLDB_INVALID_ADDRESS)
+                {
+                    m_value.SetValueType(Value::eValueTypeLoadAddress);
+                    m_value.GetScalar() = load_addr;
+                }
+            }
+
+            if (ClangASTContext::IsAggregateType (GetClangType()))
+            {
+                // this value object represents an aggregate type whose
+                // children have values, but this object does not. So we
+                // say we are changed if our location has changed.
+                SetValueDidChange (value_type != old_value.GetValueType() || m_value.GetScalar() != old_value.GetScalar());
+            }
+            else
+            {
+                // Copy the Value and set the context to use our Variable
+                // so it can extract read its value into m_data appropriately
+                Value value(m_value);
+                value.SetContext(Value::eContextTypeLLDBType, m_type_sp.get());
+                m_error = value.GetValueAsData(&exe_ctx, GetClangAST(), m_data, 0);
+            }
+            break;
+        }
+
+        SetValueIsValid (m_error.Success());
+    }
+    return m_error.Success();
+}
+
+
+
+bool
+ValueObjectMemory::IsInScope ()
+{
+    // FIXME: Maybe try to read the memory address, and if that works, then
+    // we are in scope?
+    return true;
+}
+

Modified: lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp?rev=129623&r1=129622&r2=129623&view=diff
==============================================================================
--- lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp (original)
+++ lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp Fri Apr 15 19:01:13 2011
@@ -848,7 +848,6 @@
             // with with a '$' character...
             if (member_sp->GetName().AsCString ("!")[0] == '$' && persistent_vars.ContainsVariable(member_sp))
             {
-                bool keep_this_in_memory = false;
                 
                 if (member_sp->GetName() == m_struct_vars->m_result_name)
                 {
@@ -858,7 +857,6 @@
                     if (result_sp_ptr)
                         *result_sp_ptr = member_sp;
                     
-                    keep_this_in_memory = m_keep_result_in_memory;
                 }
 
                 if (!DoMaterializeOnePersistentVariable (dematerialize, 

Modified: lldb/trunk/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp?rev=129623&r1=129622&r2=129623&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp (original)
+++ lldb/trunk/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp Fri Apr 15 19:01:13 2011
@@ -15,6 +15,8 @@
 #include "lldb/Core/Module.h"
 #include "lldb/Core/PluginManager.h"
 #include "lldb/Core/Scalar.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/Core/ValueObjectMemory.h"
 #include "lldb/Symbol/ClangASTContext.h"
 #include "lldb/Target/Process.h"
 #include "lldb/Target/RegisterContext.h"
@@ -30,12 +32,134 @@
 static const char *pluginName = "ItaniumABILanguageRuntime";
 static const char *pluginDesc = "Itanium ABI for the C++ language";
 static const char *pluginShort = "language.itanium";
+static const char *vtable_demangled_prefix = "vtable for ";
 
-lldb::ValueObjectSP
-ItaniumABILanguageRuntime::GetDynamicValue (ValueObjectSP in_value)
+bool
+ItaniumABILanguageRuntime::CouldHaveDynamicValue (ValueObject &in_value)
+{
+    return in_value.IsPointerOrReferenceType();
+}
+
+bool
+ItaniumABILanguageRuntime::GetDynamicValue (ValueObject &in_value, lldb::TypeSP &dynamic_type_sp, Address &dynamic_address)
 {
-    ValueObjectSP ret_sp;
-    return ret_sp;
+    // For Itanium, if the type has a vtable pointer in the object, it will be at offset 0
+    // in the object.  That will point to the "address point" within the vtable (not the beginning of the
+    // vtable.)  We can then look up the symbol containing this "address point" and that symbol's name 
+    // demangled will contain the full class name.
+    // The second pointer above the "address point" is the "offset_to_top".  We'll use that to get the
+    // start of the value object which holds the dynamic type.
+    //
+    
+    // Only a pointer or reference type can have a different dynamic and static type:
+    if (CouldHaveDynamicValue (in_value))
+    {
+        // FIXME: Can we get the Clang Type and ask it if the thing is really virtual?  That would avoid false positives,
+        // at the cost of not looking for the dynamic type of objects if DWARF->Clang gets it wrong.
+        
+        // First job, pull out the address at 0 offset from the object.
+        AddressType address_type;
+        lldb::addr_t original_ptr = in_value.GetPointerValue(address_type, true);
+        if (original_ptr == LLDB_INVALID_ADDRESS)
+            return false;
+            
+        Target *target = in_value.GetUpdatePoint().GetTarget();
+        Process *process = in_value.GetUpdatePoint().GetProcess();
+
+        char memory_buffer[16];
+        DataExtractor data(memory_buffer, sizeof(memory_buffer), 
+                           process->GetByteOrder(), 
+                           process->GetAddressByteSize());
+        size_t address_byte_size = process->GetAddressByteSize();
+        Error error;
+        size_t bytes_read = process->ReadMemory (original_ptr, 
+                                                 memory_buffer, 
+                                                 address_byte_size, 
+                                                 error);
+        if (!error.Success() || (bytes_read != address_byte_size))
+        {
+            return false;
+        }
+        
+        uint32_t offset_ptr = 0;
+        lldb::addr_t vtable_address_point = data.GetAddress (&offset_ptr);
+            
+        if (offset_ptr == 0)
+            return false;
+        
+        // Now find the symbol that contains this address:
+        
+        SymbolContext sc;
+        Address address_point_address;
+        if (target && !target->GetSectionLoadList().IsEmpty())
+        {
+            if (target->GetSectionLoadList().ResolveLoadAddress (vtable_address_point, address_point_address))
+            {
+                target->GetImages().ResolveSymbolContextForAddress (address_point_address, eSymbolContextSymbol, sc);
+                Symbol *symbol = sc.symbol;
+                if (symbol != NULL)
+                {
+                    const char *name = symbol->GetMangled().GetDemangledName().AsCString();
+                    if (strstr(name, vtable_demangled_prefix) == name)
+                    {
+                         // We are a C++ class, that's good.  Get the class name and look it up:
+                        const char *class_name = name + strlen(vtable_demangled_prefix);
+                        TypeList class_types;
+                        uint32_t num_matches = target->GetImages().FindTypes (sc, 
+                                                                              ConstString(class_name),
+                                                                              true,
+                                                                              UINT32_MAX,
+                                                                              class_types);
+                        if (num_matches == 1)
+                        {
+                            dynamic_type_sp = class_types.GetTypeAtIndex(0);
+                        }
+                        else if (num_matches > 1)
+                        {
+                            // How to sort out which of the type matches to pick?
+                        }
+                        
+                        if (!dynamic_type_sp)
+                            return false;
+                            
+                        // The offset_to_top is two pointers above the address.
+                        Address offset_to_top_address = address_point_address;
+                        int64_t slide = -2 * ((int64_t) target->GetArchitecture().GetAddressByteSize());
+                        offset_to_top_address.Slide (slide);
+                        
+                        Error error;
+                        lldb::addr_t offset_to_top_location = offset_to_top_address.GetLoadAddress(target);
+                        
+                        size_t bytes_read = process->ReadMemory (offset_to_top_location, 
+                                                                 memory_buffer, 
+                                                                 address_byte_size, 
+                                                                 error);
+                                                                 
+                        if (!error.Success() || (bytes_read != address_byte_size))
+                        {
+                            return false;
+                        }
+                        
+                        offset_ptr = 0;
+                        int64_t offset_to_top = data.GetMaxS64(&offset_ptr, process->GetAddressByteSize());
+                        
+                        // So the dynamic type is a value that starts at offset_to_top
+                        // above the original address.
+                        lldb::addr_t dynamic_addr = original_ptr + offset_to_top;
+                        if (!target->GetSectionLoadList().ResolveLoadAddress (dynamic_addr, dynamic_address))
+                        {
+                            dynamic_address.SetOffset(dynamic_addr);
+                            dynamic_address.SetSection(NULL);
+                        }
+                        return true;
+                    }
+                }
+            }
+        }
+        
+    }
+    
+    return false;
 }
 
 bool

Modified: lldb/trunk/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h?rev=129623&r1=129622&r2=129623&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h (original)
+++ lldb/trunk/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h Fri Apr 15 19:01:13 2011
@@ -30,9 +30,12 @@
         virtual bool
         IsVTableName (const char *name);
         
-        virtual lldb::ValueObjectSP
-        GetDynamicValue (lldb::ValueObjectSP in_value);
-
+        virtual bool
+        GetDynamicValue (ValueObject &in_value, lldb::TypeSP &type_sp, Address &address);
+        
+        virtual bool
+        CouldHaveDynamicValue (ValueObject &in_value);
+        
         //------------------------------------------------------------------
         // Static Functions
         //------------------------------------------------------------------

Modified: lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp?rev=129623&r1=129622&r2=129623&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp (original)
+++ lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp Fri Apr 15 19:01:13 2011
@@ -191,11 +191,16 @@
     return m_PrintForDebugger_addr.get();
 }
 
-lldb::ValueObjectSP
-AppleObjCRuntime::GetDynamicValue (lldb::ValueObjectSP in_value)
+bool
+AppleObjCRuntime::CouldHaveDynamicValue (ValueObject &in_value)
+{
+    return in_value.IsPointerType();
+}
+
+bool
+AppleObjCRuntime::GetDynamicValue (ValueObject &in_value, lldb::TypeSP &type_sp, Address &address)
 {
-    lldb::ValueObjectSP ret_sp;
-    return ret_sp;
+    return false;
 }
 
 bool

Modified: lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h?rev=129623&r1=129622&r2=129623&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h (original)
+++ lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h Fri Apr 15 19:01:13 2011
@@ -37,8 +37,11 @@
     virtual bool
     GetObjectDescription (Stream &str, ValueObject &object);
     
-    virtual lldb::ValueObjectSP
-    GetDynamicValue (lldb::ValueObjectSP in_value);
+    virtual bool
+    CouldHaveDynamicValue (ValueObject &in_value);
+    
+    virtual bool
+    GetDynamicValue (ValueObject &in_value, lldb::TypeSP &type_sp, Address &address);
 
     // These are the ObjC specific functions.
     

Modified: lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp?rev=129623&r1=129622&r2=129623&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp (original)
+++ lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp Fri Apr 15 19:01:13 2011
@@ -40,11 +40,10 @@
 static const char *pluginDesc = "Apple Objective C Language Runtime - Version 1";
 static const char *pluginShort = "language.apple.objc.v1";
 
-lldb::ValueObjectSP
-AppleObjCRuntimeV1::GetDynamicValue (lldb::ValueObjectSP in_value)
+bool
+AppleObjCRuntimeV1::GetDynamicValue (ValueObject &in_value, lldb::TypeSP &type_sp, Address &address)
 {
-    lldb::ValueObjectSP ret_sp;
-    return ret_sp;
+    return false;
 }
 
 //------------------------------------------------------------------

Modified: lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h?rev=129623&r1=129622&r2=129623&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h (original)
+++ lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h Fri Apr 15 19:01:13 2011
@@ -31,8 +31,8 @@
     ~AppleObjCRuntimeV1() { }
     
     // These are generic runtime functions:
-    virtual lldb::ValueObjectSP
-    GetDynamicValue (lldb::ValueObjectSP in_value);
+    virtual bool
+    GetDynamicValue (ValueObject &in_value, lldb::TypeSP &type_sp, Address &address);
 
     virtual ClangUtilityFunction *
     CreateObjectChecker (const char *);

Modified: lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp?rev=129623&r1=129622&r2=129623&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp (original)
+++ lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp Fri Apr 15 19:01:13 2011
@@ -46,11 +46,10 @@
     m_has_object_getClass = (objc_module_sp->FindFirstSymbolWithNameAndType(ConstString("gdb_object_getClass")) != NULL);
 }
 
-lldb::ValueObjectSP
-AppleObjCRuntimeV2::GetDynamicValue (lldb::ValueObjectSP in_value)
+bool
+AppleObjCRuntimeV2::GetDynamicValue (ValueObject &in_value, lldb::TypeSP &type_sp, Address &address)
 {
-    lldb::ValueObjectSP ret_sp;
-    return ret_sp;
+    return false;
 }
 
 //------------------------------------------------------------------

Modified: lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h?rev=129623&r1=129622&r2=129623&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h (original)
+++ lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h Fri Apr 15 19:01:13 2011
@@ -31,8 +31,8 @@
     ~AppleObjCRuntimeV2() { }
     
     // These are generic runtime functions:
-    virtual lldb::ValueObjectSP
-    GetDynamicValue (lldb::ValueObjectSP in_value);
+    virtual bool
+    GetDynamicValue (ValueObject &in_value, lldb::TypeSP &type_sp, Address &address);
     
     virtual ClangUtilityFunction *
     CreateObjectChecker (const char *);

Modified: lldb/trunk/source/Target/Process.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Process.cpp?rev=129623&r1=129622&r2=129623&view=diff
==============================================================================
--- lldb/trunk/source/Target/Process.cpp (original)
+++ lldb/trunk/source/Target/Process.cpp Fri Apr 15 19:01:13 2011
@@ -1902,6 +1902,12 @@
 
     if (buf == NULL || size == 0)
         return 0;
+
+    // Need to bump the stop ID after writing so that ValueObjects will know to re-read themselves.
+    // FUTURE: Doing this should be okay, but if anybody else gets upset about the stop_id changing when
+    // the target hasn't run, then we will need to add a "memory generation" as well as a stop_id...
+    m_stop_id++;
+
     // We need to write any data that would go where any current software traps
     // (enabled software breakpoints) any software traps (breakpoints) that we
     // may have placed in our tasks memory.
@@ -1962,7 +1968,7 @@
                                              ubuf + bytes_written, 
                                              size - bytes_written, 
                                              error);
-    
+                                             
     return bytes_written;
 }
 

Modified: lldb/trunk/source/Target/StackFrame.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/StackFrame.cpp?rev=129623&r1=129622&r2=129623&view=diff
==============================================================================
--- lldb/trunk/source/Target/StackFrame.cpp (original)
+++ lldb/trunk/source/Target/StackFrame.cpp Fri Apr 15 19:01:13 2011
@@ -493,6 +493,7 @@
     {
         const bool check_ptr_vs_member = (options & eExpressionPathOptionCheckPtrVsMember) != 0;
         const bool no_fragile_ivar = (options & eExpressionPathOptionsNoFragileObjcIvar) != 0;
+        const bool dynamic_value = (options & eExpressionPathOptionsDynamicValue) != 0;
         error.Clear();
         bool deref = false;
         bool address_of = false;
@@ -528,8 +529,10 @@
             VariableSP var_sp (variable_list->FindVariable(name_const_string));
             if (var_sp)
             {
-                valobj_sp = GetValueObjectForFrameVariable (var_sp);
-
+                valobj_sp = GetValueObjectForFrameVariable (var_sp, dynamic_value);
+                if (!valobj_sp)
+                    return valobj_sp;
+                    
                 var_path.erase (0, name_const_string.GetLength ());
                 // We are dumping at least one child
                 while (separator_idx != std::string::npos)
@@ -600,7 +603,6 @@
                                     return ValueObjectSP();
                                 }
                             }
-
                             child_valobj_sp = valobj_sp->GetChildMemberWithName (child_name, true);
                             if (!child_valobj_sp)
                             {
@@ -624,6 +626,12 @@
                             }
                             // Remove the child name from the path
                             var_path.erase(0, child_name.GetLength());
+                            if (dynamic_value)
+                            {
+                                ValueObjectSP dynamic_value_sp(child_valobj_sp->GetDynamicValue(true, child_valobj_sp));
+                                if (dynamic_value_sp)
+                                    child_valobj_sp = dynamic_value_sp;
+                            }
                         }
                         break;
 
@@ -650,6 +658,8 @@
                                 }
                                 else if (ClangASTContext::IsArrayType (valobj_sp->GetClangType(), NULL, NULL))
                                 {
+                                    // Pass false to dynamic_value here so we can tell the difference between
+                                    // no dynamic value and no member of this type...
                                     child_valobj_sp = valobj_sp->GetChildAtIndex (child_index, true);
                                     if (!child_valobj_sp)
                                     {
@@ -678,7 +688,12 @@
                                 // %i is the array index
                                 var_path.erase(0, (end - var_path.c_str()) + 1);
                                 separator_idx = var_path.find_first_of(".-[");
-
+                                if (dynamic_value)
+                                {
+                                    ValueObjectSP dynamic_value_sp(child_valobj_sp->GetDynamicValue(true, child_valobj_sp));
+                                    if (dynamic_value_sp)
+                                        child_valobj_sp = dynamic_value_sp;
+                                }
                                 // Break out early from the switch since we were 
                                 // able to find the child member
                                 break;
@@ -794,7 +809,7 @@
 
 
 ValueObjectSP
-StackFrame::GetValueObjectForFrameVariable (const VariableSP &variable_sp)
+StackFrame::GetValueObjectForFrameVariable (const VariableSP &variable_sp, bool use_dynamic)
 {
     ValueObjectSP valobj_sp;
     VariableList *var_list = GetVariableList (true);
@@ -815,14 +830,20 @@
             }
         }
     }
+    if (use_dynamic && valobj_sp)
+    {
+        ValueObjectSP dynamic_sp = valobj_sp->GetDynamicValue (true, valobj_sp);
+        if (dynamic_sp)
+            return dynamic_sp;
+    }
     return valobj_sp;
 }
 
 ValueObjectSP
-StackFrame::TrackGlobalVariable (const VariableSP &variable_sp)
+StackFrame::TrackGlobalVariable (const VariableSP &variable_sp, bool use_dynamic)
 {
     // Check to make sure we aren't already tracking this variable?
-    ValueObjectSP valobj_sp (GetValueObjectForFrameVariable (variable_sp));
+    ValueObjectSP valobj_sp (GetValueObjectForFrameVariable (variable_sp, use_dynamic));
     if (!valobj_sp)
     {
         // We aren't already tracking this global
@@ -835,7 +856,7 @@
         m_variable_list_sp->AddVariable (variable_sp);
 
         // Now make a value object for it so we can track its changes
-        valobj_sp = GetValueObjectForFrameVariable (variable_sp);
+        valobj_sp = GetValueObjectForFrameVariable (variable_sp, use_dynamic);
     }
     return valobj_sp;
 }

Modified: lldb/trunk/source/Target/Target.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Target.cpp?rev=129623&r1=129622&r2=129623&view=diff
==============================================================================
--- lldb/trunk/source/Target/Target.cpp (original)
+++ lldb/trunk/source/Target/Target.cpp Fri Apr 15 19:01:13 2011
@@ -887,6 +887,7 @@
     StackFrame *frame,
     bool unwind_on_error,
     bool keep_in_memory,
+    bool fetch_dynamic_value,
     lldb::ValueObjectSP &result_valobj_sp
 )
 {
@@ -927,7 +928,16 @@
             const_valobj_sp->SetName (persistent_variable_name);
         }
         else
+        {
+            if (fetch_dynamic_value)
+            {
+                ValueObjectSP dynamic_sp = result_valobj_sp->GetDynamicValue(true, result_valobj_sp);
+                if (dynamic_sp)
+                    result_valobj_sp = dynamic_sp;
+            }
+
             const_valobj_sp = result_valobj_sp->CreateConstantValue (persistent_variable_name);
+        }
 
         lldb::ValueObjectSP live_valobj_sp = result_valobj_sp;
         
@@ -1277,11 +1287,12 @@
 }
 
 
-#define TSC_DEFAULT_ARCH    "default-arch"
-#define TSC_EXPR_PREFIX     "expr-prefix"
-#define TSC_EXEC_LEVEL      "execution-level"
-#define TSC_EXEC_MODE       "execution-mode"
-#define TSC_EXEC_OS_TYPE    "execution-os-type"
+#define TSC_DEFAULT_ARCH      "default-arch"
+#define TSC_EXPR_PREFIX       "expr-prefix"
+#define TSC_EXEC_LEVEL        "execution-level"
+#define TSC_EXEC_MODE         "execution-mode"
+#define TSC_EXEC_OS_TYPE      "execution-os-type"
+#define TSC_PREFER_DYNAMIC    "prefer-dynamic-value"
 
 
 static const ConstString &
@@ -1320,6 +1331,13 @@
     return g_const_string;
 }
 
+static const ConstString &
+GetSettingNameForPreferDynamicValue ()
+{
+    static ConstString g_const_string (TSC_PREFER_DYNAMIC);
+    return g_const_string;
+}
+
 
 bool
 Target::SettingsController::SetGlobalVariable (const ConstString &var_name,
@@ -1369,7 +1387,8 @@
 ) :
     InstanceSettings (owner, name ? name : InstanceSettings::InvalidName().AsCString(), live_instance),
     m_expr_prefix_path (),
-    m_expr_prefix_contents ()
+    m_expr_prefix_contents (),
+    m_prefer_dynamic_value (true)
 {
     // CopyInstanceSettings is a pure virtual function in InstanceSettings; it therefore cannot be called
     // until the vtables for TargetInstanceSettings are properly set up, i.e. AFTER all the initializers.
@@ -1467,6 +1486,39 @@
             return;
         }
     }
+    else if (var_name == GetSettingNameForPreferDynamicValue())
+    {
+        switch (op)
+        {
+        default:
+            err.SetErrorToGenericError ();
+            err.SetErrorString ("Unrecognized operation. Cannot update value.\n");
+            return;
+        case eVarSetOperationAssign:
+            {
+                bool success;
+                bool result = Args::StringToBoolean(value, false, &success);
+
+                if (success)
+                {
+                    m_prefer_dynamic_value = result;
+                }
+                else
+                {
+                    err.SetErrorStringWithFormat ("Bad value \"%s\" for %s, should be Boolean.", 
+                                                  value, 
+                                                  GetSettingNameForPreferDynamicValue().AsCString());
+                }
+                return;
+            }
+        case eVarSetOperationClear:
+           m_prefer_dynamic_value = true;
+        case eVarSetOperationAppend:
+            err.SetErrorToGenericError ();
+            err.SetErrorString ("Cannot append to a bool.\n");
+            return;
+        }
+    }
 }
 
 void
@@ -1479,6 +1531,7 @@
     
     m_expr_prefix_path      = new_settings_ptr->m_expr_prefix_path;
     m_expr_prefix_contents  = new_settings_ptr->m_expr_prefix_contents;
+    m_prefer_dynamic_value  = new_settings_ptr->m_prefer_dynamic_value;
 }
 
 bool
@@ -1491,6 +1544,13 @@
     {
         value.AppendString (m_expr_prefix_path.c_str(), m_expr_prefix_path.size());
     }
+    else if (var_name == GetSettingNameForPreferDynamicValue())
+    {
+        if (m_prefer_dynamic_value)
+            value.AppendString ("true");
+        else
+            value.AppendString ("false");
+    }
     else 
     {
         if (err)
@@ -1533,5 +1593,6 @@
     // var-name           var-type           default      enum  init'd hidden help-text
     // =================  ================== ===========  ====  ====== ====== =========================================================================
     { TSC_EXPR_PREFIX   , eSetVarTypeString , NULL      , NULL, false, false, "Path to a file containing expressions to be prepended to all expressions." },
+    { TSC_PREFER_DYNAMIC, eSetVarTypeBoolean ,"true"    , NULL, false, false, "Should printed values be shown as their dynamic value." },
     { NULL              , eSetVarTypeNone   , NULL      , NULL, false, false, NULL }
 };

Modified: lldb/trunk/source/Target/ThreadPlanTestCondition.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/ThreadPlanTestCondition.cpp?rev=129623&r1=129622&r2=129623&view=diff
==============================================================================
--- lldb/trunk/source/Target/ThreadPlanTestCondition.cpp (original)
+++ lldb/trunk/source/Target/ThreadPlanTestCondition.cpp Fri Apr 15 19:01:13 2011
@@ -84,8 +84,8 @@
         if (result_sp)
         {
             // FIXME: This is not the right answer, we should have a "GetValueAsBoolean..."
-            Scalar scalar_value = result_sp->GetValue().ResolveValue (&m_exe_ctx, result_sp->GetClangAST());
-            if (scalar_value.IsValid())
+            Scalar scalar_value;
+            if (result_sp->ResolveValue (scalar_value))
             {
                 if (scalar_value.ULongLong(1) == 0)
                     m_did_stop = false;

Added: lldb/trunk/test/cpp/dynamic-value/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/cpp/dynamic-value/Makefile?rev=129623&view=auto
==============================================================================
--- lldb/trunk/test/cpp/dynamic-value/Makefile (added)
+++ lldb/trunk/test/cpp/dynamic-value/Makefile Fri Apr 15 19:01:13 2011
@@ -0,0 +1,5 @@
+LEVEL = ../../make
+
+CXX_SOURCES := pass-to-base.cpp
+
+include $(LEVEL)/Makefile.rules

Added: lldb/trunk/test/cpp/dynamic-value/TestDynamicValue.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/cpp/dynamic-value/TestDynamicValue.py?rev=129623&view=auto
==============================================================================
--- lldb/trunk/test/cpp/dynamic-value/TestDynamicValue.py (added)
+++ lldb/trunk/test/cpp/dynamic-value/TestDynamicValue.py Fri Apr 15 19:01:13 2011
@@ -0,0 +1,226 @@
+"""
+Use lldb Python API to test dynamic values in C++
+"""
+
+import os, time
+import re
+import unittest2
+import lldb, lldbutil
+from lldbtest import *
+
+class DynamicValueTestCase(TestBase):
+
+    mydir = os.path.join("cpp", "dynamic-value")
+
+    @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
+    @python_api_test
+    def test_get_dynamic_vals_with_dsym(self):
+        """Test fetching C++ dynamic values from pointers & references."""
+        self.buildDsym()
+        self.do_get_dynamic_vals()
+
+    @python_api_test
+    def test_get_dynamic_vals_with_dwarf(self):
+        """Test fetching C++ dynamic values from pointers & references."""
+        self.buildDwarf()
+        self.do_get_dynamic_vals()
+
+    def setUp(self):
+        # Call super's setUp().                                                                                                           
+        TestBase.setUp(self)
+
+        # Find the line number to break for main.c.                                                                                       
+
+        self.do_something_line = line_number('pass-to-base.cpp', '// Break here in doSomething.')
+        self.main_first_call_line = line_number('pass-to-base.cpp',
+                                                 '// Break here and get real addresses of myB and otherB.')
+        self.main_second_call_line = line_number('pass-to-base.cpp',
+                                                       '// Break here and get real address of reallyA.')
+
+    def examine_value_object_of_this_ptr (self, this_static, this_dynamic, dynamic_location):
+
+        # Get "this" as its static value
+        
+        self.assertTrue (this_static.IsValid())
+        this_static_loc = int (this_static.GetValue(), 16)
+        
+        # Get "this" as its dynamic value
+        
+        self.assertTrue (this_dynamic.IsValid())
+        this_dynamic_typename = this_dynamic.GetTypeName()
+        self.assertTrue (this_dynamic_typename.find('B') != -1)
+        this_dynamic_loc = int (this_dynamic.GetValue(), 16)
+        
+        # Make sure we got the right address for "this"
+        
+        self.assertTrue (this_dynamic_loc == dynamic_location)
+
+        # And that the static address is greater than the dynamic one
+
+        self.assertTrue (this_static_loc > this_dynamic_loc)
+        
+        # Now read m_b_value which is only in the dynamic value:
+
+        this_dynamic_m_b_value = this_dynamic.GetChildMemberWithName('m_b_value', True)
+        self.assertTrue (this_dynamic_m_b_value.IsValid())
+        
+        m_b_value = int (this_dynamic_m_b_value.GetValue(), 0)
+        self.assertTrue (m_b_value == 10)
+        
+        # Make sure it is not in the static version
+
+        this_static_m_b_value = this_static.GetChildMemberWithName('m_b_value', False)
+        self.assertTrue (this_static_m_b_value.IsValid() == False)
+
+        # Okay, now let's make sure that we can get the dynamic type of a child element:
+
+        contained_auto_ptr = this_dynamic.GetChildMemberWithName ('m_client_A', True)
+        self.assertTrue (contained_auto_ptr.IsValid())
+        contained_b = contained_auto_ptr.GetChildMemberWithName ('_M_ptr', True)
+        self.assertTrue (contained_b.IsValid())
+        
+        contained_b_static = contained_auto_ptr.GetChildMemberWithName ('_M_ptr', False)
+        self.assertTrue (contained_b_static.IsValid())
+        
+        contained_b_addr = int (contained_b.GetValue(), 16)
+        contained_b_static_addr = int (contained_b_static.GetValue(), 16)
+        
+        self.assertTrue (contained_b_addr < contained_b_static_addr)
+        
+    def do_get_dynamic_vals(self):
+        """Get argument vals for the call stack when stopped on a breakpoint."""
+        exe = os.path.join(os.getcwd(), "a.out")
+
+        # Create a target from the debugger.
+
+        target = self.dbg.CreateTargetWithFileAndArch (exe, lldb.LLDB_ARCH_DEFAULT)
+        self.assertTrue(target.IsValid(), VALID_TARGET)
+
+        # Set up our breakpoints:
+
+        do_something_bpt = target.BreakpointCreateByLocation('pass-to-base.cpp', self.do_something_line)
+        self.assertTrue(do_something_bpt.IsValid() and
+                        do_something_bpt.GetNumLocations() == 1,
+                        VALID_BREAKPOINT)
+
+        first_call_bpt = target.BreakpointCreateByLocation('pass-to-base.cpp', self.main_first_call_line)
+        self.assertTrue(first_call_bpt.IsValid() and
+                        first_call_bpt.GetNumLocations() == 1,
+                        VALID_BREAKPOINT)
+
+        second_call_bpt = target.BreakpointCreateByLocation('pass-to-base.cpp', self.main_second_call_line)
+        self.assertTrue(second_call_bpt.IsValid() and
+                        second_call_bpt.GetNumLocations() == 1,
+                        VALID_BREAKPOINT)
+
+        # Now launch the process, and do not stop at the entry point.
+
+        error = lldb.SBError()
+        self.process = target.Launch (self.dbg.GetListener(), None, None, os.ctermid(), os.ctermid(), os.ctermid(), None, 0, False, error)
+
+        self.assertTrue(self.process.GetState() == lldb.eStateStopped,
+                        PROCESS_STOPPED)
+
+        threads = lldbutil.GetThreadsStoppedAtBreakpoint (self.process, first_call_bpt)
+        self.assertTrue (len(threads) == 1)
+        thread = threads[0]
+
+        frame = thread.GetFrameAtIndex(0)
+
+        # Now find the dynamic addresses of myB and otherB so we can compare them
+        # with the dynamic values we get in doSomething:
+
+        noDynamic = False
+        useDynamic = True
+
+        myB = frame.FindVariable ('myB', noDynamic);
+        self.assertTrue (myB.IsValid())
+        myB_loc = int (myB.GetLocation(), 16)
+
+        otherB = frame.FindVariable('otherB', noDynamic)
+        self.assertTrue (otherB.IsValid())
+        otherB_loc = int (otherB.GetLocation(), 16)
+
+        # Okay now run to doSomething:
+
+        threads = lldbutil.ContinueToBreakpoint (self.process, do_something_bpt)
+        self.assertTrue (len(threads) == 1)
+        thread = threads[0]
+
+        frame = thread.GetFrameAtIndex(0)
+
+        # Get "this" using FindVariable:
+
+        this_static = frame.FindVariable ('this', noDynamic)
+        this_dynamic = frame.FindVariable ('this', useDynamic)
+        self.examine_value_object_of_this_ptr (this_static, this_dynamic, myB_loc)
+        
+        # Get "this" using FindValue, make sure that works too:
+        this_static = frame.FindValue ('this', lldb.eValueTypeVariableArgument, noDynamic)
+        this_dynamic = frame.FindValue ('this', lldb.eValueTypeVariableArgument, useDynamic)
+        self.examine_value_object_of_this_ptr (this_static, this_dynamic, myB_loc)
+
+        # Get "this" using the EvaluateExpression:
+        # These tests fail for now because EvaluateExpression doesn't currently support dynamic typing...
+        #this_static = frame.EvaluateExpression ('this', False)
+        #this_dynamic = frame.EvaluateExpression ('this', True)
+        #self.examine_value_object_of_this_ptr (this_static, this_dynamic, myB_loc)
+        
+        # The "frame var" code uses another path to get into children, so let's
+        # make sure that works as well:
+
+        self.expect('frame var -d 1 anotherA.m_client_A._M_ptr', 'frame var finds its way into a child member',
+            patterns = ['\(.* B \*\)'])
+
+        # Now make sure we also get it right for a reference as well:
+
+        anotherA_static = frame.FindVariable ('anotherA', False)
+        self.assertTrue (anotherA_static.IsValid())
+        anotherA_static_addr = int (anotherA_static.GetValue(), 16)
+
+        anotherA_dynamic = frame.FindVariable ('anotherA', True)
+        self.assertTrue (anotherA_dynamic.IsValid())
+        anotherA_dynamic_addr = int (anotherA_dynamic.GetValue(), 16)
+        anotherA_dynamic_typename = anotherA_dynamic.GetTypeName()
+        self.assertTrue (anotherA_dynamic_typename.find('B') != -1)
+
+        self.assertTrue(anotherA_dynamic_addr < anotherA_static_addr)
+
+        anotherA_m_b_value_dynamic = anotherA_dynamic.GetChildMemberWithName('m_b_value', True)
+        self.assertTrue (anotherA_m_b_value_dynamic.IsValid())
+        anotherA_m_b_val = int (anotherA_m_b_value_dynamic.GetValue(), 10)
+        self.assertTrue (anotherA_m_b_val == 300)
+
+        anotherA_m_b_value_static = anotherA_static.GetChildMemberWithName('m_b_value', True)
+        self.assertTrue (anotherA_m_b_value_static.IsValid() == False)
+
+        # Okay, now continue again, and when we hit the second breakpoint in main
+
+        threads = lldbutil.ContinueToBreakpoint (self.process, second_call_bpt)
+        self.assertTrue (len(threads) == 1)
+        thread = threads[0]
+
+        frame = thread.GetFrameAtIndex(0)
+        reallyA_value = frame.FindVariable ('reallyA', False)
+        self.assertTrue(reallyA_value.IsValid())
+        reallyA_loc = int (reallyA_value.GetLocation(), 16)
+        
+        # Finally continue to doSomething again, and make sure we get the right value for anotherA,
+        # which this time around is just an "A".
+
+        threads = lldbutil.ContinueToBreakpoint (self.process, do_something_bpt)
+        self.assertTrue(len(threads) == 1)
+        thread = threads[0]
+
+        frame = thread.GetFrameAtIndex(0)
+        anotherA_value = frame.FindVariable ('anotherA', True)
+        self.assertTrue(anotherA_value.IsValid())
+        anotherA_loc = int (anotherA_value.GetValue(), 16)
+        self.assertTrue (anotherA_loc == reallyA_loc)
+        self.assertTrue (anotherA_value.GetTypeName().find ('B') == -1)
+
+if __name__ == '__main__':
+    import atexit
+    lldb.SBDebugger.Initialize()
+    atexit.register(lambda: lldb.SBDebugger.Terminate())
+    unittest2.main()

Added: lldb/trunk/test/cpp/dynamic-value/pass-to-base.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/cpp/dynamic-value/pass-to-base.cpp?rev=129623&view=auto
==============================================================================
--- lldb/trunk/test/cpp/dynamic-value/pass-to-base.cpp (added)
+++ lldb/trunk/test/cpp/dynamic-value/pass-to-base.cpp Fri Apr 15 19:01:13 2011
@@ -0,0 +1,62 @@
+#include <stdio.h>
+#include <memory>
+
+class Extra
+{
+public:
+  Extra (int in_one, int in_two) : m_extra_one(in_one), m_extra_two(in_two) {}
+
+private:
+  int m_extra_one;
+  int m_extra_two;
+};
+
+class A
+{
+public:
+  A(int value) : m_a_value (value) {}
+  A(int value, A* client_A) : m_a_value (value), m_client_A (client_A) {}
+
+  virtual void
+  doSomething (A &anotherA)
+  {
+    printf ("In A %p doing something with %d.\n", this, m_a_value);
+    printf ("Also have another A at %p: %d.\n", &anotherA, anotherA.Value()); // Break here in doSomething.
+  }
+
+  int 
+  Value()
+  {
+    return m_a_value;
+  }
+
+private:
+  int m_a_value;
+  std::auto_ptr<A> m_client_A;
+};
+
+class B : public Extra, public virtual A
+{
+public:
+  B (int b_value, int a_value) : Extra(b_value, a_value), A(a_value), m_b_value(b_value) {}
+  B (int b_value, int a_value, A *client_A) : Extra(b_value, a_value), A(a_value, client_A), m_b_value(b_value) {}
+private:
+  int m_b_value;
+};
+
+static A* my_global_A_ptr;
+
+int
+main (int argc, char **argv)
+{
+  my_global_A_ptr = new B (100, 200);
+  B myB (10, 20, my_global_A_ptr);
+  B otherB (300, 400, my_global_A_ptr);
+
+  myB.doSomething(otherB); // Break here and get real addresses of myB and otherB.
+
+  A reallyA (500);
+  myB.doSomething (reallyA);  // Break here and get real address of reallyA.
+
+  return 0;
+}

Modified: lldb/trunk/test/lldbutil.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lldbutil.py?rev=129623&r1=129622&r2=129623&view=diff
==============================================================================
--- lldb/trunk/test/lldbutil.py (original)
+++ lldb/trunk/test/lldbutil.py Fri Apr 15 19:01:13 2011
@@ -383,3 +383,30 @@
 
     if string_buffer:
         return output.getvalue()
+
+def GetThreadsStoppedAtBreakpoint (process, bkpt):
+    """ For a stopped process returns the thread stopped at the breakpoint passed in in bkpt"""
+    stopped_threads = []
+    threads = []
+
+    stopped_threads = get_stopped_threads (process, lldb.eStopReasonBreakpoint)
+
+    if len(stopped_threads) == 0:
+        return threads
+    
+    for thread in stopped_threads:
+    # Make sure we've hit our breakpoint...
+        break_id = thread.GetStopReasonDataAtIndex (0)
+        if break_id == bkpt.GetID():
+            threads.append(thread)
+
+    return threads
+
+def ContinueToBreakpoint (process, bkpt):
+    """ Continues the process, when it stops, if there is a thread stopped at bkpt, returns that thread"""
+    process.Continue()
+    if process.GetState() != lldb.eStateStopped:
+        return None
+    else:
+        return GetThreadsStoppedAtBreakpoint (process, bkpt)
+

Modified: lldb/trunk/test/python_api/process/TestProcessAPI.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/python_api/process/TestProcessAPI.py?rev=129623&r1=129622&r2=129623&view=diff
==============================================================================
--- lldb/trunk/test/python_api/process/TestProcessAPI.py (original)
+++ lldb/trunk/test/python_api/process/TestProcessAPI.py Fri Apr 15 19:01:13 2011
@@ -209,7 +209,13 @@
         if not error.Success() or result != byteSize:
             self.fail("SBProcess.WriteMemory() failed")
 
-        # Get the SBValue for the global variable 'my_int' again, with its updated value.
+        # Make sure that the val we got originally updates itself to notice the change:
+        self.expect(val.GetValue(frame),
+                    "SBProcess.ReadMemory() successfully writes (int)256 to the memory location for 'my_int'",
+                    exe=False,
+            startstr = '256')
+
+        # And for grins, get the SBValue for the global variable 'my_int' again, to make sure that also tracks the new value:
         val = frame.FindValue("my_int", lldb.eValueTypeVariableGlobal)
         self.expect(val.GetValue(frame),
                     "SBProcess.ReadMemory() successfully writes (int)256 to the memory location for 'my_int'",

Modified: lldb/trunk/tools/debugserver/debugserver.xcodeproj/project.pbxproj
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/debugserver.xcodeproj/project.pbxproj?rev=129623&r1=129622&r2=129623&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/debugserver.xcodeproj/project.pbxproj (original)
+++ lldb/trunk/tools/debugserver/debugserver.xcodeproj/project.pbxproj Fri Apr 15 19:01:13 2011
@@ -551,7 +551,6 @@
 					"-llockdown",
 				);
 				OTHER_MIGFLAGS = "-I$(DERIVED_FILE_DIR)";
-				PREBINDING = NO;
 				PRODUCT_NAME = debugserver;
 				STRIP_INSTALLED_PRODUCT = YES;
 				USER_HEADER_SEARCH_PATHS = "./source ../../source $(DERIVED_SOURCES_DIR)";
@@ -592,7 +591,6 @@
 					"-llockdown",
 				);
 				OTHER_MIGFLAGS = "-I$(DERIVED_FILE_DIR)";
-				PREBINDING = NO;
 				PRODUCT_NAME = debugserver;
 				"PROVISIONING_PROFILE[sdk=macosx*]" = "";
 				USER_HEADER_SEARCH_PATHS = "./source ../../source $(DERIVED_SOURCES_DIR)";
@@ -633,7 +631,6 @@
 					"-llockdown",
 				);
 				OTHER_MIGFLAGS = "-I$(DERIVED_FILE_DIR)";
-				PREBINDING = NO;
 				PRODUCT_NAME = debugserver;
 				"PROVISIONING_PROFILE[sdk=macosx*]" = "";
 				USER_HEADER_SEARCH_PATHS = "./source ../../source $(DERIVED_SOURCES_DIR)";





More information about the lldb-commits mailing list