[Lldb-commits] [lldb] r121841 - in /lldb/trunk: include/lldb/Core/ValueObject.h include/lldb/Symbol/ClangASTContext.h include/lldb/Target/StackFrame.h lldb.xcodeproj/project.pbxproj source/API/SBTarget.cpp source/Commands/CommandObjectFrame.cpp source/Core/ValueObject.cpp source/Symbol/ClangASTContext.cpp source/Target/StackFrame.cpp source/Target/Target.cpp test/forward/TestForwardDeclaration.py test/foundation/TestObjCMethods.py

Greg Clayton gclayton at apple.com
Tue Dec 14 21:08:08 PST 2010


Author: gclayton
Date: Tue Dec 14 23:08:08 2010
New Revision: 121841

URL: http://llvm.org/viewvc/llvm-project?rev=121841&view=rev
Log:
Fixed the "expression" command object to use the StackFrame::GetValueForExpressionPath()
function and also hooked up better error reporting for when things fail.

Fixed issues with trying to display children of pointers when none are
supposed to be shown (no children for function pointers, and more like this).
This was causing child value objects to be made that were correctly firing
an assertion.


Modified:
    lldb/trunk/include/lldb/Core/ValueObject.h
    lldb/trunk/include/lldb/Symbol/ClangASTContext.h
    lldb/trunk/include/lldb/Target/StackFrame.h
    lldb/trunk/lldb.xcodeproj/project.pbxproj
    lldb/trunk/source/API/SBTarget.cpp
    lldb/trunk/source/Commands/CommandObjectFrame.cpp
    lldb/trunk/source/Core/ValueObject.cpp
    lldb/trunk/source/Symbol/ClangASTContext.cpp
    lldb/trunk/source/Target/StackFrame.cpp
    lldb/trunk/source/Target/Target.cpp
    lldb/trunk/test/forward/TestForwardDeclaration.py
    lldb/trunk/test/foundation/TestObjCMethods.py

Modified: lldb/trunk/include/lldb/Core/ValueObject.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/ValueObject.h?rev=121841&r1=121840&r2=121841&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/ValueObject.h (original)
+++ lldb/trunk/include/lldb/Core/ValueObject.h Tue Dec 14 23:08:08 2010
@@ -207,10 +207,10 @@
     CreateConstantValue (ExecutionContextScope *exe_scope, const ConstString &name);
 
     virtual lldb::ValueObjectSP
-    Dereference (ExecutionContextScope *exe_scope, Error *error_ptr);
+    Dereference (ExecutionContextScope *exe_scope, Error &error);
     
     virtual lldb::ValueObjectSP
-    AddressOf ();
+    AddressOf (Error &error);
 
     // The backing bits of this value object were updated, clear any value
     // values, summaries or descriptions so we refetch them.

Modified: lldb/trunk/include/lldb/Symbol/ClangASTContext.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/ClangASTContext.h?rev=121841&r1=121840&r2=121841&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/ClangASTContext.h (original)
+++ lldb/trunk/include/lldb/Symbol/ClangASTContext.h Tue Dec 14 23:08:08 2010
@@ -348,6 +348,9 @@
     GetNumChildren (lldb::clang_type_t clang_type,
                     bool omit_empty_base_classes);
 
+    static uint32_t
+    GetNumPointeeChildren (lldb::clang_type_t clang_type);
+
     lldb::clang_type_t
     GetChildClangTypeAtIndex (const char *parent_name,
                               lldb::clang_type_t  parent_clang_type,

Modified: lldb/trunk/include/lldb/Target/StackFrame.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/StackFrame.h?rev=121841&r1=121840&r2=121841&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/StackFrame.h (original)
+++ lldb/trunk/include/lldb/Target/StackFrame.h Tue Dec 14 23:08:08 2010
@@ -97,7 +97,7 @@
     GetVariableList (bool get_file_globals);
 
     lldb::ValueObjectSP
-    GetValueForVariableExpressionPath (const char *var_expr);
+    GetValueForVariableExpressionPath (const char *var_expr, bool check_ptr_vs_member, Error &error);
 
     bool
     HasDebugInformation ();

Modified: lldb/trunk/lldb.xcodeproj/project.pbxproj
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lldb.xcodeproj/project.pbxproj?rev=121841&r1=121840&r2=121841&view=diff
==============================================================================
--- lldb/trunk/lldb.xcodeproj/project.pbxproj (original)
+++ lldb/trunk/lldb.xcodeproj/project.pbxproj Tue Dec 14 23:08:08 2010
@@ -2455,6 +2455,7 @@
 			isa = PBXProject;
 			buildConfigurationList = 1DEB91EF08733DB70010E9CD /* Build configuration list for PBXProject "lldb" */;
 			compatibilityVersion = "Xcode 3.1";
+			developmentRegion = English;
 			hasScannedForEncodings = 1;
 			knownRegions = (
 				en,

Modified: lldb/trunk/source/API/SBTarget.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBTarget.cpp?rev=121841&r1=121840&r2=121841&view=diff
==============================================================================
--- lldb/trunk/source/API/SBTarget.cpp (original)
+++ lldb/trunk/source/API/SBTarget.cpp Tue Dec 14 23:08:08 2010
@@ -50,7 +50,8 @@
 //----------------------------------------------------------------------
 // SBTarget constructor
 //----------------------------------------------------------------------
-SBTarget::SBTarget ()
+SBTarget::SBTarget () :
+    m_opaque_sp ()
 {
 }
 

Modified: lldb/trunk/source/Commands/CommandObjectFrame.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectFrame.cpp?rev=121841&r1=121840&r2=121841&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectFrame.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectFrame.cpp Tue Dec 14 23:08:08 2010
@@ -586,175 +586,36 @@
                         }
                         else
                         {
-                            bool address_of = false;
-                            // If first character is a '*', then show pointer contents
-                            if (name_cstr[0] == '*')
+                            Error error;
+                            const bool check_ptr_vs_member = true;
+                            valobj_sp = exe_ctx.frame->GetValueForVariableExpressionPath (name_cstr, check_ptr_vs_member, error);
+                            if (valobj_sp)
                             {
-                                ++ptr_depth;
-                                name_cstr++; // Skip the '*'
-                            }
-                            else if (name_cstr[0] == '&')
-                            {
-                                address_of = true;
-                                name_cstr++; // Skip the '&'
-                            }
-
-                            std::string var_path (name_cstr);
-                            size_t separator_idx = var_path.find_first_of(".-[");
-
-                            ConstString name_const_string;
-                            if (separator_idx == std::string::npos)
-                                name_const_string.SetCString (var_path.c_str());
-                            else
-                                name_const_string.SetCStringWithLength (var_path.c_str(), separator_idx);
-
-                            var_sp = variable_list->FindVariable(name_const_string);
-                            if (var_sp)
-                            {
-                                valobj_sp = exe_ctx.frame->GetValueObjectForFrameVariable (var_sp);
-
-                                var_path.erase (0, name_const_string.GetLength ());
-                                // We are dumping at least one child
-                                while (separator_idx != std::string::npos)
+                                if (m_options.show_decl && var_sp->GetDeclaration ().GetFile())
                                 {
-                                    // Calculate the next separator index ahead of time
-                                    ValueObjectSP child_valobj_sp;
-                                    const char separator_type = var_path[0];
-                                    switch (separator_type)
-                                    {
-
-                                    case '-':
-                                        if (var_path.size() >= 2 && var_path[1] != '>')
-                                        {
-                                            result.GetErrorStream().Printf ("error: invalid character in variable path starting at '%s'\n",
-                                                                            var_path.c_str());
-                                            var_path.clear();
-                                            valobj_sp.reset();
-                                            break;
-                                        }
-                                        var_path.erase (0, 1); // Remove the '-'
-                                        // Fall through
-                                    case '.':
-                                        {
-                                            var_path.erase (0, 1); // Remove the '.' or '>'
-                                            separator_idx = var_path.find_first_of(".-[");
-                                            ConstString child_name;
-                                            if (separator_idx == std::string::npos)
-                                                child_name.SetCString (var_path.c_str());
-                                            else
-                                                child_name.SetCStringWithLength(var_path.c_str(), separator_idx);
-
-                                            child_valobj_sp = valobj_sp->GetChildMemberWithName (child_name, true);
-                                            if (!child_valobj_sp)
-                                            {
-                                                result.GetErrorStream().Printf ("error: can't find child of '%s' named '%s'\n",
-                                                                                valobj_sp->GetName().AsCString(),
-                                                                                child_name.GetCString());
-                                                var_path.clear();
-                                                valobj_sp.reset();
-                                                break;
-                                            }
-                                            // Remove the child name from the path
-                                            var_path.erase(0, child_name.GetLength());
-                                        }
-                                        break;
-
-                                    case '[':
-                                        // Array member access, or treating pointer as an array
-                                        if (var_path.size() > 2) // Need at least two brackets and a number
-                                        {
-                                            char *end = NULL;
-                                            int32_t child_index = ::strtol (&var_path[1], &end, 0);
-                                            if (end && *end == ']')
-                                            {
-
-                                                if (valobj_sp->IsPointerType ())
-                                                {
-                                                    child_valobj_sp = valobj_sp->GetSyntheticArrayMemberFromPointer (child_index, true);
-                                                }
-                                                else
-                                                {
-                                                    child_valobj_sp = valobj_sp->GetChildAtIndex (child_index, true);
-                                                }
-
-                                                if (!child_valobj_sp)
-                                                {
-                                                    result.GetErrorStream().Printf ("error: invalid array index %u in '%s'\n",
-                                                                                    child_index,
-                                                                                    valobj_sp->GetName().AsCString());
-                                                    var_path.clear();
-                                                    valobj_sp.reset();
-                                                    break;
-                                                }
-
-                                                // Erase the array member specification '[%i]' where %i is the array index
-                                                var_path.erase(0, (end - var_path.c_str()) + 1);
-                                                separator_idx = var_path.find_first_of(".-[");
-
-                                                // Break out early from the switch since we were able to find the child member
-                                                break;
-                                            }
-                                        }
-                                        result.GetErrorStream().Printf ("error: invalid array member specification for '%s' starting at '%s'\n",
-                                                                        valobj_sp->GetName().AsCString(),
-                                                                        var_path.c_str());
-                                        var_path.clear();
-                                        valobj_sp.reset();
-                                        break;
-
-                                        break;
-
-                                    default:
-                                        result.GetErrorStream().Printf ("error: invalid character in variable path starting at '%s'\n",
-                                                                            var_path.c_str());
-                                        var_path.clear();
-                                        valobj_sp.reset();
-                                        separator_idx = std::string::npos;
-                                        break;
-                                    }
-
-                                    if (child_valobj_sp)
-                                        valobj_sp = child_valobj_sp;
-
-                                    if (var_path.empty())
-                                        break;
-
-                                }
-
-                                if (valobj_sp)
-                                {
-                                    if (m_options.show_decl && var_sp->GetDeclaration ().GetFile())
-                                    {
-                                        var_sp->GetDeclaration ().DumpStopContext (&s, false);
-                                        s.PutCString (": ");
-                                    }
-
-
-                                    if (address_of)
-                                    {
-                                        s.Printf("&%s = %s\n", name_cstr, valobj_sp->GetLocationAsCString (exe_ctx.frame));
-                                    }
-                                    else
-                                    {
-                                        ValueObject::DumpValueObject (result.GetOutputStream(), 
-                                                                      exe_ctx.frame, 
-                                                                      valobj_sp.get(), 
-                                                                      valobj_sp->GetParent() ? name_cstr : NULL, 
-                                                                      ptr_depth, 
-                                                                      0, 
-                                                                      m_options.max_depth, 
-                                                                      m_options.show_types,
-                                                                      m_options.show_location,
-                                                                      m_options.use_objc, 
-                                                                      false,
-                                                                      m_options.flat_output);
-                                    }
+                                    var_sp->GetDeclaration ().DumpStopContext (&s, false);
+                                    s.PutCString (": ");
                                 }
+                                ValueObject::DumpValueObject (result.GetOutputStream(), 
+                                                              exe_ctx.frame, 
+                                                              valobj_sp.get(), 
+                                                              valobj_sp->GetParent() ? name_cstr : NULL, 
+                                                              ptr_depth, 
+                                                              0, 
+                                                              m_options.max_depth, 
+                                                              m_options.show_types,
+                                                              m_options.show_location,
+                                                              m_options.use_objc, 
+                                                              false,
+                                                              m_options.flat_output);
                             }
                             else
                             {
-                                result.GetErrorStream().Printf ("error: unable to find any variables named '%s'\n", name_cstr);
-                                var_path.clear();
+                                const char *error_cstr = error.AsCString(NULL);
+                                if (error_cstr)
+                                    result.GetErrorStream().Printf("error: %s\n", error_cstr);
+                                else
+                                    result.GetErrorStream().Printf ("error: unable to find any variable expression path that matches '%s'\n", name_cstr);
                             }
                         }
                     }

Modified: lldb/trunk/source/Core/ValueObject.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ValueObject.cpp?rev=121841&r1=121840&r2=121841&view=diff
==============================================================================
--- lldb/trunk/source/Core/ValueObject.cpp (original)
+++ lldb/trunk/source/Core/ValueObject.cpp Tue Dec 14 23:08:08 2010
@@ -1203,10 +1203,11 @@
 }
 
 lldb::ValueObjectSP
-ValueObject::Dereference (ExecutionContextScope *exe_scope, Error *error_ptr)
+ValueObject::Dereference (ExecutionContextScope *exe_scope, Error &error)
 {
     lldb::ValueObjectSP valobj_sp;
-    if (IsPointerType())
+    const bool is_pointer_type = IsPointerType();
+    if (is_pointer_type)
     {
         bool omit_empty_base_classes = true;
 
@@ -1249,98 +1250,46 @@
                                                    child_is_base_class));
         }
     }
+
+    if (valobj_sp)
+    {
+        error.Clear();
+    }
     else
     {
-        if (error_ptr)
-            error_ptr->SetErrorString("can't dereference a non-pointer value");
+        StreamString strm;
+        GetExpressionPath(strm);
+
+        if (is_pointer_type)
+            error.SetErrorStringWithFormat("dereference failed: (%s) %s", GetTypeName().AsCString("<invalid type>"), strm.GetString().c_str());
+        else
+            error.SetErrorStringWithFormat("not a pointer type: (%s) %s", GetTypeName().AsCString("<invalid type>"), strm.GetString().c_str());
     }
 
     return valobj_sp;
 }
 
-    
-
-//lldb::ValueObjectSP
-//ValueObject::Dereference (ExecutionContextScope *exe_scope, Error *error_ptr)
-//{
-//    lldb::ValueObjectSP valobj_sp;
-//    if (IsPointerType())
-//    {
-//        UpdateValueIfNeeded(exe_scope);
-//        if (m_error.Success())
-//        {
-//            lldb::AddressType address_type = eAddressTypeInvalid;
-//            const bool scalar_is_load_address = true;
-//            lldb::addr_t addr = GetPointerValue (address_type, scalar_is_load_address);
-//            if (addr != LLDB_INVALID_ADDRESS)
-//            {
-//                switch (address_type)
-//                {
-//                    case eAddressTypeInvalid:
-//                        if (error_ptr)
-//                            error_ptr->SetErrorString("value is not in memory");
-//                        break;
-//                    case eAddressTypeFile:
-//                    case eAddressTypeLoad:
-//                    case eAddressTypeHost:
-//                    {
-//                        clang::ASTContext *ast = GetClangAST();
-//                        clang_type_t clang_type = ClangASTType::GetPointeeType (GetClangType());
-//                        if (ast && clang_type)
-//                        {
-//                            std::string name (1, '*');
-//                            name.append (m_name.AsCString(""));
-//                            valobj_sp.reset (new ValueObjectConstResult (ast, 
-//                                                                         ClangASTContext::CreatePointerType (ast, clang_type),
-//                                                                         ConstString (name.c_str()),
-//                                                                         addr, 
-//                                                                         address_type,
-//                                                                         m_data.GetAddressByteSize()));
-//                        }
-//                        else
-//                        {
-//                            if (error_ptr)
-//                                error_ptr->SetErrorString("invalid clang type info");
-//                        }
-//                    }
-//                    break;
-//                }
-//            }
-//            else
-//            {
-//                if (error_ptr)
-//                    error_ptr->SetErrorString("failed to extract pointer value");
-//            }
-//        }
-//        else
-//        {
-//            if (error_ptr)
-//                *error_ptr = m_error;
-//        }
-//    }
-//    else
-//    {
-//        if (error_ptr)
-//            error_ptr->SetErrorString("can't dereference a non-pointer value");
-//    }
-//
-//    return valobj_sp;
-//}
-    
-lldb::ValueObjectSP
-ValueObject::AddressOf ()
+    lldb::ValueObjectSP
+ValueObject::AddressOf (Error &error)
 {
     lldb::ValueObjectSP valobj_sp;
-
     lldb::AddressType address_type = eAddressTypeInvalid;
     const bool scalar_is_load_address = false;
     lldb::addr_t addr = GetAddressOf (address_type, scalar_is_load_address);
+    error.Clear();
     if (addr != LLDB_INVALID_ADDRESS)
     {
         switch (address_type)
         {
+        default:
         case eAddressTypeInvalid:
+            {
+                StreamString expr_path_strm;
+                GetExpressionPath(expr_path_strm);
+                error.SetErrorStringWithFormat("'%s' is not in memory", expr_path_strm.GetString().c_str());
+            }
             break;
+
         case eAddressTypeFile:
         case eAddressTypeLoad:
         case eAddressTypeHost:

Modified: lldb/trunk/source/Symbol/ClangASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/ClangASTContext.cpp?rev=121841&r1=121840&r2=121841&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/ClangASTContext.cpp (original)
+++ lldb/trunk/source/Symbol/ClangASTContext.cpp Tue Dec 14 23:08:08 2010
@@ -1901,7 +1901,10 @@
             break;
         }
         break;
-        
+
+    case clang::Type::Complex:
+        return 2;
+
     case clang::Type::Record:
         if (ClangASTType::IsDefined (clang_qual_type))
         {
@@ -1995,12 +1998,15 @@
     case clang::Type::Pointer:
         {
             PointerType *pointer_type = cast<PointerType>(qual_type.getTypePtr());
-            QualType pointee_type = pointer_type->getPointeeType();
+            QualType pointee_type (pointer_type->getPointeeType());
             uint32_t num_pointee_children = ClangASTContext::GetNumChildren (pointee_type.getAsOpaquePtr(), 
                                                                              omit_empty_base_classes);
-            // If this type points to a simple type, then it has 1 child
             if (num_pointee_children == 0)
-                num_children = 1;
+            {
+                // We have a pointer to a pointee type that claims it has no children.
+                // We will want to look at
+                num_children = ClangASTContext::GetNumPointeeChildren (pointee_type.getAsOpaquePtr());
+            }
             else
                 num_children = num_pointee_children;
         }
@@ -2032,6 +2038,60 @@
     return num_children;
 }
 
+// If a pointer to a pointee type (the clang_type arg) says that it has no 
+// children, then we either need to trust it, or override it and return a 
+// different result. For example, an "int *" has one child that is an integer, 
+// but a function pointer doesn't have any children. Likewise if a Record type
+// claims it has no children, then there really is nothing to show.
+uint32_t
+ClangASTContext::GetNumPointeeChildren (clang_type_t clang_type)
+{
+    if (clang_type == NULL)
+        return 0;
+
+    QualType qual_type(QualType::getFromOpaquePtr(clang_type));
+    const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+    switch (type_class)
+    {
+    case clang::Type::Builtin:                  return 1;
+    case clang::Type::Complex:                  return 2;
+    case clang::Type::Pointer:                  return 1;
+    case clang::Type::BlockPointer:             return 0;   // If block pointers don't have debug info, then no children for them
+    case clang::Type::LValueReference:          return 1;
+    case clang::Type::RValueReference:          return 1;
+    case clang::Type::MemberPointer:            return 0;
+    case clang::Type::ConstantArray:            return 0;
+    case clang::Type::IncompleteArray:          return 0;
+    case clang::Type::VariableArray:            return 0;
+    case clang::Type::DependentSizedArray:      return 0;
+    case clang::Type::DependentSizedExtVector:  return 0;
+    case clang::Type::Vector:                   return 0;
+    case clang::Type::ExtVector:                return 0;
+    case clang::Type::FunctionProto:            return 0;   // When we function pointers, they have no children...
+    case clang::Type::FunctionNoProto:          return 0;   // When we function pointers, they have no children...
+    case clang::Type::UnresolvedUsing:          return 0;
+    case clang::Type::Paren:                    return 0;
+    case clang::Type::Typedef:                  return ClangASTContext::GetNumPointeeChildren (cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr());
+    case clang::Type::TypeOfExpr:               return 0;
+    case clang::Type::TypeOf:                   return 0;
+    case clang::Type::Decltype:                 return 0;
+    case clang::Type::Record:                   return 0;
+    case clang::Type::Enum:                     return 1;
+    case clang::Type::Elaborated:               return 1;
+    case clang::Type::TemplateTypeParm:         return 1;
+    case clang::Type::SubstTemplateTypeParm:    return 1;
+    case clang::Type::TemplateSpecialization:   return 1;
+    case clang::Type::InjectedClassName:        return 0;
+    case clang::Type::DependentName:            return 1;
+    case clang::Type::DependentTemplateSpecialization:  return 1;
+    case clang::Type::ObjCObject:               return 0;
+    case clang::Type::ObjCInterface:            return 0;
+    case clang::Type::ObjCObjectPointer:        return 1;
+    default: 
+        break;
+    }
+    return 0;
+}
 
 clang_type_t
 ClangASTContext::GetChildClangTypeAtIndex

Modified: lldb/trunk/source/Target/StackFrame.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/StackFrame.cpp?rev=121841&r1=121840&r2=121841&view=diff
==============================================================================
--- lldb/trunk/source/Target/StackFrame.cpp (original)
+++ lldb/trunk/source/Target/StackFrame.cpp Tue Dec 14 23:08:08 2010
@@ -18,6 +18,7 @@
 #include "lldb/Core/Disassembler.h"
 #include "lldb/Core/Value.h"
 #include "lldb/Core/ValueObjectVariable.h"
+#include "lldb/Core/ValueObjectConstResult.h"
 #include "lldb/Symbol/Function.h"
 #include "lldb/Symbol/VariableList.h"
 #include "lldb/Target/ExecutionContext.h"
@@ -479,156 +480,235 @@
 }
 
 ValueObjectSP
-StackFrame::GetValueForVariableExpressionPath (const char *var_expr)
+StackFrame::GetValueForVariableExpressionPath (const char *var_expr_cstr, bool check_ptr_vs_member, Error &error)
 {
-    bool deref = false;
-    bool address_of = false;
-    ValueObjectSP valobj_sp;
-    const bool get_file_globals = true;
-    VariableList *variable_list = GetVariableList (get_file_globals);
-    
-    if (variable_list)
+
+    if (var_expr_cstr && var_expr_cstr[0])
     {
-        // If first character is a '*', then show pointer contents
-        if (var_expr[0] == '*')
-        {
-            deref = true;
-            var_expr++; // Skip the '*'
-        }
-        else if (var_expr[0] == '&')
+        error.Clear();
+        bool deref = false;
+        bool address_of = false;
+        ValueObjectSP valobj_sp;
+        const bool get_file_globals = true;
+        VariableList *variable_list = GetVariableList (get_file_globals);
+        
+        if (variable_list)
         {
-            address_of = true;
-            var_expr++; // Skip the '&'
-        }
-
-        std::string var_path (var_expr);
-        size_t separator_idx = var_path.find_first_of(".-[");
+            // If first character is a '*', then show pointer contents
+            const char *var_expr = var_expr_cstr;
+            if (var_expr[0] == '*')
+            {
+                deref = true;
+                var_expr++; // Skip the '*'
+            }
+            else if (var_expr[0] == '&')
+            {
+                address_of = true;
+                var_expr++; // Skip the '&'
+            }
 
-        ConstString name_const_string;
-        if (separator_idx == std::string::npos)
-            name_const_string.SetCString (var_path.c_str());
-        else
-            name_const_string.SetCStringWithLength (var_path.c_str(), separator_idx);
+            std::string var_path (var_expr);
+            size_t separator_idx = var_path.find_first_of(".-[=+~|&^%#@!/?,<>{}");
+            StreamString var_expr_path_strm;
 
-        VariableSP var_sp (variable_list->FindVariable(name_const_string));
-        if (var_sp)
-        {
-            valobj_sp = GetValueObjectForFrameVariable (var_sp);
+            ConstString name_const_string;
+            if (separator_idx == std::string::npos)
+                name_const_string.SetCString (var_path.c_str());
+            else
+                name_const_string.SetCStringWithLength (var_path.c_str(), separator_idx);
 
-            var_path.erase (0, name_const_string.GetLength ());
-            // We are dumping at least one child
-            while (separator_idx != std::string::npos)
+            VariableSP var_sp (variable_list->FindVariable(name_const_string));
+            if (var_sp)
             {
-                // Calculate the next separator index ahead of time
-                ValueObjectSP child_valobj_sp;
-                const char separator_type = var_path[0];
-                switch (separator_type)
-                {
-
-                case '-':
-                    if (var_path.size() >= 2 && var_path[1] != '>')
-                        return ValueObjectSP();
+                valobj_sp = GetValueObjectForFrameVariable (var_sp);
 
-                    var_path.erase (0, 1); // Remove the '-'
-                    // Fall through
-                case '.':
+                var_path.erase (0, name_const_string.GetLength ());
+                // We are dumping at least one child
+                while (separator_idx != std::string::npos)
+                {
+                    // Calculate the next separator index ahead of time
+                    ValueObjectSP child_valobj_sp;
+                    const char separator_type = var_path[0];
+                    switch (separator_type)
                     {
-                        // We either have a pointer type and need to verify 
-                        // valobj_sp is a pointer, or we have a member of a 
-                        // class/union/struct being accessed with the . syntax 
-                        // and need to verify we don't have a pointer.
-                        const bool is_ptr = var_path[0] == '>';
-                        
-                        if (valobj_sp->IsPointerType () != is_ptr)
-                        {
-                            // Incorrect use of "." with a pointer, or "->" with
-                            // a class/union/struct instance or reference.
-                            return ValueObjectSP();
-                        }
 
-                        var_path.erase (0, 1); // Remove the '.' or '>'
-                        separator_idx = var_path.find_first_of(".-[");
-                        ConstString child_name;
-                        if (separator_idx == std::string::npos)
-                            child_name.SetCString (var_path.c_str());
-                        else
-                            child_name.SetCStringWithLength(var_path.c_str(), separator_idx);
-
-                        child_valobj_sp = valobj_sp->GetChildMemberWithName (child_name, true);
-                        if (!child_valobj_sp)
-                        {
-                            // No child member with name "child_name"
+                    case '-':
+                        if (var_path.size() >= 2 && var_path[1] != '>')
                             return ValueObjectSP();
-                        }
-                        // Remove the child name from the path
-                        var_path.erase(0, child_name.GetLength());
-                    }
-                    break;
 
-                case '[':
-                    // Array member access, or treating pointer as an array
-                    if (var_path.size() > 2) // Need at least two brackets and a number
-                    {
-                        char *end = NULL;
-                        int32_t child_index = ::strtol (&var_path[1], &end, 0);
-                        if (end && *end == ']')
+                        var_path.erase (0, 1); // Remove the '-'
+                        // Fall through
+                    case '.':
                         {
+                            const bool expr_is_ptr = var_path[0] == '>';
 
-                            if (valobj_sp->IsPointerType ())
-                            {
-                                child_valobj_sp = valobj_sp->GetSyntheticArrayMemberFromPointer (child_index, true);
-                            }
+                            var_path.erase (0, 1); // Remove the '.' or '>'
+                            separator_idx = var_path.find_first_of(".-[");
+                            ConstString child_name;
+                            if (separator_idx == std::string::npos)
+                                child_name.SetCString (var_path.c_str());
                             else
+                                child_name.SetCStringWithLength(var_path.c_str(), separator_idx);
+
+                            if (check_ptr_vs_member)
                             {
-                                child_valobj_sp = valobj_sp->GetChildAtIndex (child_index, true);
+                                // We either have a pointer type and need to verify 
+                                // valobj_sp is a pointer, or we have a member of a 
+                                // class/union/struct being accessed with the . syntax 
+                                // and need to verify we don't have a pointer.
+                                const bool actual_is_ptr = valobj_sp->IsPointerType ();
+                                
+                                if (actual_is_ptr != expr_is_ptr)
+                                {
+                                    // Incorrect use of "." with a pointer, or "->" with
+                                    // a class/union/struct instance or reference.
+                                    valobj_sp->GetExpressionPath (var_expr_path_strm);
+                                    if (actual_is_ptr)
+                                        error.SetErrorStringWithFormat ("\"%s\" is a pointer and . was used to attempt to access \"%s\". Did you mean \"%s->%s\"?", 
+                                                                        var_expr_path_strm.GetString().c_str(), 
+                                                                        child_name.GetCString(),
+                                                                        var_expr_path_strm.GetString().c_str(), 
+                                                                        var_path.c_str());
+                                    else
+                                        error.SetErrorStringWithFormat ("\"%s\" is not a pointer and -> was used to attempt to access \"%s\". Did you mean \"%s.%s\"?", 
+                                                                        var_expr_path_strm.GetString().c_str(), 
+                                                                        child_name.GetCString(),
+                                                                        var_expr_path_strm.GetString().c_str(), 
+                                                                        var_path.c_str());
+                                    return ValueObjectSP();
+                                }
                             }
 
+                            child_valobj_sp = valobj_sp->GetChildMemberWithName (child_name, true);
                             if (!child_valobj_sp)
                             {
-                                // Invalid array index...
+                                // No child member with name "child_name"
+                                valobj_sp->GetExpressionPath (var_expr_path_strm);
+                                if (child_name)
+                                {
+                                    error.SetErrorStringWithFormat ("\"%s\" is not a member of \"(%s) %s\"", 
+                                                                    child_name.GetCString(), 
+                                                                    valobj_sp->GetTypeName().AsCString("<invalid type>"),
+                                                                    var_expr_path_strm.GetString().c_str());
+                                }
+                                else
+                                {
+                                    error.SetErrorStringWithFormat ("incomplete expression path after \"%s\" in \"%s\"",
+                                                                    var_expr_path_strm.GetString().c_str(),
+                                                                    var_expr_cstr);
+                                }
+
                                 return ValueObjectSP();
                             }
+                            // Remove the child name from the path
+                            var_path.erase(0, child_name.GetLength());
+                        }
+                        break;
 
-                            // Erase the array member specification '[%i]' where 
-                            // %i is the array index
-                            var_path.erase(0, (end - var_path.c_str()) + 1);
-                            separator_idx = var_path.find_first_of(".-[");
+                    case '[':
+                        // Array member access, or treating pointer as an array
+                        if (var_path.size() > 2) // Need at least two brackets and a number
+                        {
+                            char *end = NULL;
+                            int32_t child_index = ::strtol (&var_path[1], &end, 0);
+                            if (end && *end == ']')
+                            {
 
-                            // Break out early from the switch since we were 
-                            // able to find the child member
-                            break;
+                                if (valobj_sp->IsPointerType ())
+                                {
+                                    child_valobj_sp = valobj_sp->GetSyntheticArrayMemberFromPointer (child_index, true);
+                                    if (!child_valobj_sp)
+                                    {
+                                        valobj_sp->GetExpressionPath (var_expr_path_strm);
+                                        error.SetErrorStringWithFormat ("failed to use pointer as array for index %i for \"(%s) %s\"", 
+                                                                        child_index, 
+                                                                        valobj_sp->GetTypeName().AsCString("<invalid type>"),
+                                                                        var_expr_path_strm.GetString().c_str());
+                                    }
+                                }
+                                else if (ClangASTContext::IsArrayType (valobj_sp->GetClangType(), NULL, NULL))
+                                {
+                                    child_valobj_sp = valobj_sp->GetChildAtIndex (child_index, true);
+                                    if (!child_valobj_sp)
+                                    {
+                                        valobj_sp->GetExpressionPath (var_expr_path_strm);
+                                        error.SetErrorStringWithFormat ("array index %i is not valid for \"(%s) %s\"", 
+                                                                        child_index, 
+                                                                        valobj_sp->GetTypeName().AsCString("<invalid type>"),
+                                                                        var_expr_path_strm.GetString().c_str());
+                                    }
+                                }
+                                else
+                                {
+                                    valobj_sp->GetExpressionPath (var_expr_path_strm);
+                                    error.SetErrorStringWithFormat ("\"(%s) %s\" is not an array type", 
+                                                                    valobj_sp->GetTypeName().AsCString("<invalid type>"),
+                                                                    var_expr_path_strm.GetString().c_str());
+                                }
+
+                                if (!child_valobj_sp)
+                                {
+                                    // Invalid array index...
+                                    return ValueObjectSP();
+                                }
+
+                                // Erase the array member specification '[%i]' where 
+                                // %i is the array index
+                                var_path.erase(0, (end - var_path.c_str()) + 1);
+                                separator_idx = var_path.find_first_of(".-[");
+
+                                // Break out early from the switch since we were 
+                                // able to find the child member
+                                break;
+                            }
                         }
-                    }
-                    return ValueObjectSP();
+                        return ValueObjectSP();
 
-                default:
-                    // Failure...
-                    return ValueObjectSP();
-                }
+                    default:
+                        // Failure...
+                        {
+                            valobj_sp->GetExpressionPath (var_expr_path_strm);
+                            error.SetErrorStringWithFormat ("unexpected char '%c' encountered after \"%s\" in \"%s\"", 
+                                                            separator_type,
+                                                            var_expr_path_strm.GetString().c_str(),
+                                                            var_path.c_str());
 
-                if (child_valobj_sp)
-                    valobj_sp = child_valobj_sp;
+                            return ValueObjectSP();
+                        }
+                    }
 
-                if (var_path.empty())
-                    break;
+                    if (child_valobj_sp)
+                        valobj_sp = child_valobj_sp;
+
+                    if (var_path.empty())
+                        break;
 
-            }
-            if (valobj_sp)
-            {
-                if (deref)
-                {
-                    ValueObjectSP deref_valobj_sp (valobj_sp->Dereference(this, NULL));
-                    valobj_sp = deref_valobj_sp;
                 }
-                else if (address_of)
+                if (valobj_sp)
                 {
-                    ValueObjectSP address_of_valobj_sp (valobj_sp->AddressOf());
-                    valobj_sp = address_of_valobj_sp;
+                    if (deref)
+                    {
+                        ValueObjectSP deref_valobj_sp (valobj_sp->Dereference(this, error));
+                        valobj_sp = deref_valobj_sp;
+                    }
+                    else if (address_of)
+                    {
+                        ValueObjectSP address_of_valobj_sp (valobj_sp->AddressOf(error));
+                        valobj_sp = address_of_valobj_sp;
+                    }
                 }
+                return valobj_sp;
+            }
+            else
+            {
+                error.SetErrorStringWithFormat("no variable named '%s' found in this frame", name_const_string.GetCString());
             }
-            return valobj_sp;
         }
     }
+    else
+    {
+        error.SetErrorStringWithFormat("invalid variable path '%s'", var_expr_cstr);
+    }
     return ValueObjectSP();
 }
 

Modified: lldb/trunk/source/Target/Target.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Target.cpp?rev=121841&r1=121840&r2=121841&view=diff
==============================================================================
--- lldb/trunk/source/Target/Target.cpp (original)
+++ lldb/trunk/source/Target/Target.cpp Tue Dec 14 23:08:08 2010
@@ -886,7 +886,9 @@
     if (frame)
     {
         frame->CalculateExecutionContext(exe_ctx);
-        result_valobj_sp = frame->GetValueForVariableExpressionPath (expr_cstr);
+        Error error;
+        const bool check_ptr_vs_member = true;
+        result_valobj_sp = frame->GetValueForVariableExpressionPath (expr_cstr, check_ptr_vs_member, error);
     }
     else if (m_process_sp)
     {

Modified: lldb/trunk/test/forward/TestForwardDeclaration.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/forward/TestForwardDeclaration.py?rev=121841&r1=121840&r2=121841&view=diff
==============================================================================
--- lldb/trunk/test/forward/TestForwardDeclaration.py (original)
+++ lldb/trunk/test/forward/TestForwardDeclaration.py Tue Dec 14 23:08:08 2010
@@ -47,7 +47,7 @@
         # This should display correctly.
         # Note that the member fields of a = 1 and b = 2 is by design.
         self.expect("frame variable -t *bar_ptr", VARIABLES_DISPLAYED_CORRECTLY,
-            substrs = ['(struct bar *) bar_ptr = ',
+            substrs = ['(struct bar) *bar_ptr = ',
                        '(int) a = 1',
                        '(int) b = 2'])
 

Modified: lldb/trunk/test/foundation/TestObjCMethods.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/foundation/TestObjCMethods.py?rev=121841&r1=121840&r2=121841&view=diff
==============================================================================
--- lldb/trunk/test/foundation/TestObjCMethods.py (original)
+++ lldb/trunk/test/foundation/TestObjCMethods.py Tue Dec 14 23:08:08 2010
@@ -151,7 +151,7 @@
 
         # This should display the str and date member fields as well.
         self.expect("frame variable -t *self", VARIABLES_DISPLAYED_CORRECTLY,
-            substrs = ["(MyString *) self",
+            substrs = ["(MyString) *self",
                        "(NSString *) str",
                        "(NSDate *) date"])
 





More information about the lldb-commits mailing list