[Lldb-commits] [lldb] r134458 - in /lldb/trunk: include/lldb/Core/ include/lldb/Symbol/ lldb.xcodeproj/ source/Core/ source/Symbol/ source/Target/ test/functionalities/data-formatter/data-formatter-advanced/ test/functionalities/data-formatter/data-formatter-cpp/
Enrico Granata
granata.enrico at gmail.com
Tue Jul 5 19:13:41 PDT 2011
Author: enrico
Date: Tue Jul 5 21:13:41 2011
New Revision: 134458
URL: http://llvm.org/viewvc/llvm-project?rev=134458&view=rev
Log:
new syntax for summary strings:
- ${*expr} now simply means to dereference expr before actually using it
- bitfields, array ranges and pointer ranges now work in a (hopefully) more natural and language-compliant way
a new class TypeHierarchyNavigator replicates the behavior of the FormatManager in going through type hierarchies
when one-lining summary strings, children's summaries can be used as well as values
Added:
lldb/trunk/include/lldb/Symbol/TypeHierarchyNavigator.h
lldb/trunk/source/Symbol/TypeHierarchyNavigator.cpp
Modified:
lldb/trunk/include/lldb/Core/FormatManager.h
lldb/trunk/include/lldb/Core/ValueObject.h
lldb/trunk/include/lldb/Symbol/ClangASTContext.h
lldb/trunk/lldb.xcodeproj/project.pbxproj
lldb/trunk/source/Core/DataExtractor.cpp
lldb/trunk/source/Core/Debugger.cpp
lldb/trunk/source/Core/ValueObject.cpp
lldb/trunk/source/Symbol/ClangASTContext.cpp
lldb/trunk/source/Target/StackFrame.cpp
lldb/trunk/test/functionalities/data-formatter/data-formatter-advanced/TestDataFormatterAdv.py
lldb/trunk/test/functionalities/data-formatter/data-formatter-advanced/main.cpp
lldb/trunk/test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py
Modified: lldb/trunk/include/lldb/Core/FormatManager.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/FormatManager.h?rev=134458&r1=134457&r2=134458&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/FormatManager.h (original)
+++ lldb/trunk/include/lldb/Core/FormatManager.h Tue Jul 5 21:13:41 2011
@@ -260,6 +260,13 @@
if (!typePtr)
return false;
ConstString name(ClangASTType::GetTypeNameForQualType(type).c_str());
+ if(vobj.GetBitfieldBitSize() > 0)
+ {
+ // for bitfields, append size to the typename so one can custom format them
+ StreamString sstring;
+ sstring.Printf("%s:%d",name.AsCString(),vobj.GetBitfieldBitSize());
+ name = ConstString(sstring.GetData());
+ }
//printf("trying to get format for VO name %s of type %s\n",vobj.GetName().AsCString(),name.AsCString());
if (Get(name.GetCString(), entry))
return true;
@@ -357,8 +364,7 @@
template<>
bool
FormatNavigator<std::map<lldb::RegularExpressionSP, SummaryFormat::SharedPointer>, SummaryFormat::RegexSummaryCallback>::Get(const char* key,
- SummaryFormat::SharedPointer& value);
-
+ SummaryFormat::SharedPointer& value);
template<>
bool
FormatNavigator<std::map<lldb::RegularExpressionSP, SummaryFormat::SharedPointer>, SummaryFormat::RegexSummaryCallback>::Delete(const char* type);
Modified: lldb/trunk/include/lldb/Core/ValueObject.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/ValueObject.h?rev=134458&r1=134457&r2=134458&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/ValueObject.h (original)
+++ lldb/trunk/include/lldb/Core/ValueObject.h Tue Jul 5 21:13:41 2011
@@ -246,6 +246,9 @@
virtual bool
IsPointerType ();
+
+ virtual bool
+ IsScalarType ();
virtual bool
IsPointerOrReferenceType ();
@@ -302,6 +305,12 @@
}
virtual bool
+ IsArrayItemForPointer()
+ {
+ return m_is_array_item_for_pointer;
+ }
+
+ virtual bool
SetClangAST (clang::ASTContext *ast)
{
return false;
@@ -357,6 +366,10 @@
lldb::Format custom_format = lldb::eFormatInvalid);
bool
+ DumpPrintableRepresentation(Stream& s,
+ ValueObjectRepresentationStyle val_obj_display = eDisplaySummary,
+ lldb::Format custom_format = lldb::eFormatInvalid);
+ bool
GetValueIsValid () const;
bool
@@ -392,6 +405,9 @@
GetSyntheticArrayMemberFromPointer (int32_t index, bool can_create);
lldb::ValueObjectSP
+ GetSyntheticBitFieldChild (uint32_t from, uint32_t to, bool can_create);
+
+ lldb::ValueObjectSP
GetDynamicValue (lldb::DynamicValueType valueType);
virtual lldb::ValueObjectSP
@@ -537,7 +553,8 @@
m_old_value_valid:1,
m_pointers_point_to_load_addrs:1,
m_is_deref_of_parent:1,
- m_is_array_item_for_pointer:1;
+ m_is_array_item_for_pointer:1,
+ m_is_bitfield_for_scalar:1;
friend class ClangExpressionDeclMap; // For GetValue
friend class ClangExpressionVariable; // For SetName
Modified: lldb/trunk/include/lldb/Symbol/ClangASTContext.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/ClangASTContext.h?rev=134458&r1=134457&r2=134458&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/ClangASTContext.h (original)
+++ lldb/trunk/include/lldb/Symbol/ClangASTContext.h Tue Jul 5 21:13:41 2011
@@ -661,8 +661,19 @@
//------------------------------------------------------------------
static bool
IsFloatingPointType (lldb::clang_type_t clang_type, uint32_t &count, bool &is_complex);
+
+ // true iff this is one of the types that can "fit"
+ // in a Scalar object
+ static bool
+ IsScalarType (lldb::clang_type_t clang_type);
+
+ static bool
+ IsPointerToScalarType (lldb::clang_type_t clang_type);
static bool
+ IsArrayOfScalarType (lldb::clang_type_t clang_type);
+
+ static bool
GetCXXClassName (lldb::clang_type_t clang_type,
std::string &class_name);
Added: lldb/trunk/include/lldb/Symbol/TypeHierarchyNavigator.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/TypeHierarchyNavigator.h?rev=134458&view=auto
==============================================================================
--- lldb/trunk/include/lldb/Symbol/TypeHierarchyNavigator.h (added)
+++ lldb/trunk/include/lldb/Symbol/TypeHierarchyNavigator.h Tue Jul 5 21:13:41 2011
@@ -0,0 +1,75 @@
+//===-- TypeHierarchyNavigator.h ------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef lldb_TypeHierarchyNavigator_h_
+#define lldb_TypeHierarchyNavigator_h_
+
+// C Includes
+// C++ Includes
+
+// Other libraries and framework includes
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/DeclObjC.h"
+
+// Project includes
+#include "lldb/lldb-public.h"
+#include "lldb/lldb-enumerations.h"
+
+namespace lldb_private {
+
+class TypeHierarchyNavigator {
+
+public:
+
+ enum RelationshipToCurrentType
+ {
+ eRootType,
+ eCXXBaseClass,
+ eCXXVBaseClass,
+ eObjCBaseClass,
+ eStrippedPointer,
+ eStrippedReference,
+ eStrippedTypedef
+ };
+
+ typedef bool (*TypeHierarchyNavigatorCallback)(const clang::QualType& qual_type,
+ RelationshipToCurrentType reason_why_here,
+ void* callback_baton);
+
+ TypeHierarchyNavigator(const clang::QualType& qual_type,
+ ValueObject& val_obj,
+ void* callback_baton = NULL) :
+ m_root_type(qual_type),
+ m_value_object(val_obj),
+ m_default_callback_baton(callback_baton)
+ {
+ }
+
+ bool
+ LoopThrough(TypeHierarchyNavigatorCallback callback,
+ void* callback_baton = NULL);
+
+private:
+
+ bool
+ LoopThrough(const clang::QualType& qual_type,
+ TypeHierarchyNavigatorCallback callback,
+ RelationshipToCurrentType reason_why_here,
+ void* callback_baton);
+
+ const clang::QualType& m_root_type;
+ ValueObject& m_value_object;
+ void* m_default_callback_baton;
+
+};
+
+} // namespace lldb_private
+
+#endif // lldb_TypeHierarchyNavigator_h_
Modified: lldb/trunk/lldb.xcodeproj/project.pbxproj
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lldb.xcodeproj/project.pbxproj?rev=134458&r1=134457&r2=134458&view=diff
==============================================================================
--- lldb/trunk/lldb.xcodeproj/project.pbxproj (original)
+++ lldb/trunk/lldb.xcodeproj/project.pbxproj Tue Jul 5 21:13:41 2011
@@ -402,6 +402,7 @@
4CD0BD0F134BFADF00CB44D4 /* ValueObjectDynamicValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CD0BD0E134BFADF00CB44D4 /* ValueObjectDynamicValue.cpp */; };
9415F61813B2C0EF00A52B36 /* FormatManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9415F61713B2C0EF00A52B36 /* FormatManager.cpp */; };
9463D4CD13B1798800C230D4 /* CommandObjectType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9463D4CC13B1798800C230D4 /* CommandObjectType.cpp */; };
+ 9467E65213C3D97600B3B6F3 /* TypeHierarchyNavigator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9467E65113C3D97600B3B6F3 /* TypeHierarchyNavigator.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 */; };
9A22A161135E30370024DDC3 /* EmulateInstructionARM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A22A15D135E30370024DDC3 /* EmulateInstructionARM.cpp */; };
@@ -1165,6 +1166,8 @@
9415F61713B2C0EF00A52B36 /* FormatManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FormatManager.cpp; path = source/Core/FormatManager.cpp; sourceTree = "<group>"; };
9463D4CC13B1798800C230D4 /* CommandObjectType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandObjectType.cpp; path = source/Commands/CommandObjectType.cpp; sourceTree = "<group>"; };
9463D4CE13B179A500C230D4 /* CommandObjectType.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CommandObjectType.h; path = source/Commands/CommandObjectType.h; sourceTree = "<group>"; };
+ 9467E65113C3D97600B3B6F3 /* TypeHierarchyNavigator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TypeHierarchyNavigator.cpp; path = source/Symbol/TypeHierarchyNavigator.cpp; sourceTree = "<group>"; };
+ 9467E65413C3D98900B3B6F3 /* TypeHierarchyNavigator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = TypeHierarchyNavigator.h; path = include/lldb/Symbol/TypeHierarchyNavigator.h; sourceTree = "<group>"; };
961FABB81235DE1600F93A47 /* FuncUnwinders.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FuncUnwinders.cpp; path = source/Symbol/FuncUnwinders.cpp; sourceTree = "<group>"; };
961FABB91235DE1600F93A47 /* UnwindPlan.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = UnwindPlan.cpp; path = source/Symbol/UnwindPlan.cpp; sourceTree = "<group>"; };
961FABBA1235DE1600F93A47 /* UnwindTable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = UnwindTable.cpp; path = source/Symbol/UnwindTable.cpp; sourceTree = "<group>"; };
@@ -2043,6 +2046,8 @@
49BB309511F79450001A4197 /* TaggedASTType.h */,
26BC7C6510F1B6E900F91463 /* Type.h */,
26BC7F2010F1B8EC00F91463 /* Type.cpp */,
+ 9467E65413C3D98900B3B6F3 /* TypeHierarchyNavigator.h */,
+ 9467E65113C3D97600B3B6F3 /* TypeHierarchyNavigator.cpp */,
26BC7C6610F1B6E900F91463 /* TypeList.h */,
26BC7F2110F1B8EC00F91463 /* TypeList.cpp */,
269FF07F12494F8E00225026 /* UnwindPlan.h */,
@@ -3239,6 +3244,7 @@
9463D4CD13B1798800C230D4 /* CommandObjectType.cpp in Sources */,
9415F61813B2C0EF00A52B36 /* FormatManager.cpp in Sources */,
49D8FB3913B5598F00411094 /* ClangASTImporter.cpp in Sources */,
+ 9467E65213C3D97600B3B6F3 /* TypeHierarchyNavigator.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Modified: lldb/trunk/source/Core/DataExtractor.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/DataExtractor.cpp?rev=134458&r1=134457&r2=134458&view=diff
==============================================================================
--- lldb/trunk/source/Core/DataExtractor.cpp (original)
+++ lldb/trunk/source/Core/DataExtractor.cpp Tue Jul 5 21:13:41 2011
@@ -753,7 +753,9 @@
{
if (bitfield_bit_offset > 0)
uval64 >>= bitfield_bit_offset;
- uint64_t bitfield_mask = ((1 << bitfield_bit_size) - 1);
+ uint64_t bitfield_mask = ((1ul << bitfield_bit_size) - 1);
+ if(!bitfield_mask && bitfield_bit_offset == 0 && bitfield_bit_size == 64)
+ return uval64;
uval64 &= bitfield_mask;
}
return uval64;
Modified: lldb/trunk/source/Core/Debugger.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Debugger.cpp?rev=134458&r1=134457&r2=134458&view=diff
==============================================================================
--- lldb/trunk/source/Core/Debugger.cpp (original)
+++ lldb/trunk/source/Core/Debugger.cpp Tue Jul 5 21:13:41 2011
@@ -694,6 +694,176 @@
}
}
+// #define VERBOSE_FORMATPROMPT_OUTPUT
+#ifdef VERBOSE_FORMATPROMPT_OUTPUT
+#define IFERROR_PRINT_IT if (error.Fail()) \
+{ \
+ printf("ERROR: %s\n",error.AsCString("unknown")); \
+ break; \
+}
+#else // IFERROR_PRINT_IT
+#define IFERROR_PRINT_IT if (error.Fail()) \
+break;
+#endif // IFERROR_PRINT_IT
+
+static bool
+ScanFormatDescriptor(const char* var_name_begin,
+ const char* var_name_end,
+ const char** var_name_final,
+ const char** percent_position,
+ lldb::Format* custom_format,
+ ValueObject::ValueObjectRepresentationStyle* val_obj_display)
+{
+ *percent_position = ::strchr(var_name_begin,'%');
+ if(!*percent_position || *percent_position > var_name_end)
+ *var_name_final = var_name_end;
+ else
+ {
+ *var_name_final = *percent_position;
+ char* format_name = new char[var_name_end-*var_name_final]; format_name[var_name_end-*var_name_final-1] = '\0';
+ memcpy(format_name, *var_name_final+1, var_name_end-*var_name_final-1);
+ if ( !FormatManager::GetFormatFromCString(format_name,
+ true,
+ *custom_format) )
+ {
+ // if this is an @ sign, print ObjC description
+ if(*format_name == '@')
+ *val_obj_display = ValueObject::eDisplayLanguageSpecific;
+ // if this is a V, print the value using the default format
+ if(*format_name == 'V')
+ *val_obj_display = ValueObject::eDisplayValue;
+ }
+ // a good custom format tells us to print the value using it
+ else
+ *val_obj_display = ValueObject::eDisplayValue;
+ delete format_name;
+ }
+ return true;
+}
+
+static bool
+ScanBracketedRange(const char* var_name_begin,
+ const char* var_name_end,
+ const char* var_name_final,
+ const char** open_bracket_position,
+ const char** separator_position,
+ const char** close_bracket_position,
+ const char** var_name_final_if_array_range,
+ int64_t* index_lower,
+ int64_t* index_higher)
+{
+ *open_bracket_position = ::strchr(var_name_begin,'[');
+ if(*open_bracket_position && *open_bracket_position < var_name_final)
+ {
+ *separator_position = ::strchr(*open_bracket_position,'-'); // might be NULL if this is a simple var[N] bitfield
+ *close_bracket_position = ::strchr(*open_bracket_position,']');
+ // as usual, we assume that [] will come before %
+ //printf("trying to expand a []\n");
+ *var_name_final_if_array_range = *open_bracket_position;
+ if(*close_bracket_position - *open_bracket_position == 1)
+ {
+ *index_lower = 0;
+ }
+ else if (*separator_position == NULL || *separator_position > var_name_end)
+ {
+ char *end = NULL;
+ *index_lower = ::strtoul (*open_bracket_position+1, &end, 0);
+ *index_higher = *index_lower;
+ //printf("got to read low=%d high same\n",bitfield_lower);
+ }
+ else if(*close_bracket_position && *close_bracket_position < var_name_end)
+ {
+ char *end = NULL;
+ *index_lower = ::strtoul (*open_bracket_position+1, &end, 0);
+ *index_higher = ::strtoul (*separator_position+1, &end, 0);
+ //printf("got to read low=%d high=%d\n",bitfield_lower,bitfield_higher);
+ }
+ else
+ return false;
+ if (*index_lower > *index_higher && *index_higher > 0)
+ {
+ int temp = *index_lower;
+ *index_lower = *index_higher;
+ *index_higher = temp;
+ }
+ }
+ return true;
+}
+
+
+static ValueObjectSP
+ExpandExpressionPath(ValueObject* vobj,
+ StackFrame* frame,
+ bool* do_deref_pointer,
+ const char* var_name_begin,
+ const char* var_name_final,
+ Error& error)
+{
+
+ StreamString sstring;
+ VariableSP var_sp;
+
+ if(*do_deref_pointer)
+ sstring.PutChar('*');
+ else if(vobj->IsDereferenceOfParent() && ClangASTContext::IsPointerType(vobj->GetParent()->GetClangType()) && !vobj->IsArrayItemForPointer())
+ {
+ sstring.PutChar('*');
+ *do_deref_pointer = true;
+ }
+
+ vobj->GetExpressionPath(sstring, true, ValueObject::eHonorPointers);
+#ifdef VERBOSE_FORMATPROMPT_OUTPUT
+ printf("name to expand in phase 0: %s\n",sstring.GetData());
+#endif //VERBOSE_FORMATPROMPT_OUTPUT
+ sstring.PutRawBytes(var_name_begin+3, var_name_final-var_name_begin-3);
+#ifdef VERBOSE_FORMATPROMPT_OUTPUT
+ printf("name to expand in phase 1: %s\n",sstring.GetData());
+#endif //VERBOSE_FORMATPROMPT_OUTPUT
+ std::string name = std::string(sstring.GetData());
+ ValueObjectSP target = frame->GetValueForVariableExpressionPath (name.c_str(),
+ eNoDynamicValues,
+ 0,
+ var_sp,
+ error);
+ return target;
+}
+
+static ValueObjectSP
+ExpandIndexedExpression(ValueObject* vobj,
+ uint32_t index,
+ StackFrame* frame,
+ Error error)
+{
+ ValueObjectSP item;
+ bool is_array = ClangASTContext::IsArrayType(vobj->GetClangType());
+
+ if(is_array)
+ return vobj->GetChildAtIndex(index, true);
+ else
+ {
+ const char* ptr_deref_format = "%s[%d]";
+ char* ptr_deref_buffer = new char[1024];
+ StreamString expr_path_string;
+ vobj->GetExpressionPath(expr_path_string, true, ValueObject::eHonorPointers);
+ const char* expr_path = expr_path_string.GetData();
+#ifdef VERBOSE_FORMATPROMPT_OUTPUT
+ printf("name to deref in phase 0: %s\n",expr_path);
+#endif //VERBOSE_FORMATPROMPT_OUTPUT
+ ::sprintf(ptr_deref_buffer, ptr_deref_format, expr_path, index);
+#ifdef VERBOSE_FORMATPROMPT_OUTPUT
+ printf("name to deref in phase 1: %s\n",ptr_deref_buffer);
+#endif //VERBOSE_FORMATPROMPT_OUTPUT
+ lldb::VariableSP var_sp;
+ item = frame->GetValueForVariableExpressionPath (ptr_deref_buffer,
+ eNoDynamicValues,
+ 0,
+ var_sp,
+ error);
+ delete ptr_deref_buffer;
+ }
+ return item;
+}
+
bool
Debugger::FormatPrompt
(
@@ -783,6 +953,7 @@
FileSpec format_file_spec;
const RegisterInfo *reg_info = NULL;
RegisterContext *reg_ctx = NULL;
+ bool do_deref_pointer = false;
// Each variable must set success to true below...
bool var_success = false;
@@ -791,270 +962,19 @@
case '*':
{
if (!vobj) break;
- lldb::clang_type_t pointer_clang_type = vobj->GetClangType();
- clang_type_t elem_or_pointee_clang_type;
- const Flags type_flags (ClangASTContext::GetTypeInfo (pointer_clang_type,
- vobj->GetClangAST(),
- &elem_or_pointee_clang_type));
- bool is_pointer = type_flags.Test (ClangASTContext::eTypeIsPointer),
- is_array = type_flags.Test (ClangASTContext::eTypeIsArray);
- if ( is_array ||
- ( is_pointer && ::strchr(var_name_begin,'[') && ::strchr(var_name_begin,'[') < var_name_end )
- )
- {
- const char* var_name_final;
- const char* close_bracket_position = NULL;
- const char* percent_position = NULL;
- const char* targetvalue;
- lldb::Format custom_format = eFormatInvalid;
- int index_lower = -1;
- int index_higher = -1;
- ValueObject::ValueObjectRepresentationStyle val_obj_display = ValueObject::eDisplaySummary;
- {
- percent_position = ::strchr(var_name_begin,'%');
- if(!percent_position || percent_position > var_name_end)
- var_name_final = var_name_end;
- else
- {
- var_name_final = percent_position;
- char* format_name = new char[var_name_end-var_name_final]; format_name[var_name_end-var_name_final-1] = '\0';
- memcpy(format_name, var_name_final+1, var_name_end-var_name_final-1);
- if ( !FormatManager::GetFormatFromCString(format_name,
- true,
- custom_format) )
- {
- // if this is an @ sign, print ObjC description
- if(*format_name == '@')
- val_obj_display = ValueObject::eDisplayLanguageSpecific;
- // if this is a V, print the value using the default format
- if(*format_name == 'V')
- val_obj_display = ValueObject::eDisplayValue;
- }
- // a good custom format tells us to print the value using it
- else
- val_obj_display = ValueObject::eDisplayValue;
- }
- }
-
- {
- const char* open_bracket_position = ::strchr(var_name_begin,'[');
- if(open_bracket_position && open_bracket_position < var_name_final)
- {
- // TODO: pick a way to say "all entries". this will make more sense once
- // regex typenames are in place. now, you need to be size-aware anyways
- const char* separator_position = ::strchr(open_bracket_position,'-'); // might be NULL if this is a simple var[N] bitfield
- close_bracket_position = ::strchr(open_bracket_position,']');
- // as usual, we assume that [] will come before %
- //printf("trying to expand a []\n");
- var_name_final = open_bracket_position;
- if(close_bracket_position - open_bracket_position == 1)
- {
- if(is_array)
- {
- index_lower = 0;
- index_higher = vobj->GetNumChildren() - 1;
- }
- else
- break; // cannot auto-determine size for pointers
- }
- else if (separator_position == NULL || separator_position > var_name_end)
- {
- char *end = NULL;
- index_lower = ::strtoul (open_bracket_position+1, &end, 0);
- index_higher = index_lower;
- //printf("got to read low=%d high same\n",bitfield_lower);
- }
- else if(close_bracket_position && close_bracket_position < var_name_end)
- {
- char *end = NULL;
- index_lower = ::strtoul (open_bracket_position+1, &end, 0);
- index_higher = ::strtoul (separator_position+1, &end, 0);
- //printf("got to read low=%d high=%d\n",bitfield_lower,bitfield_higher);
- }
- else
- break;
- if (index_lower > index_higher)
- {
- int temp = index_lower;
- index_lower = index_higher;
- index_higher = temp;
- }
- //*((char*)open_bracket_position) = '\0';
- //printf("variable name is %s\n",var_name_begin);
- //*((char*)open_bracket_position) = '[';
- }
- }
-
- // if you just type a range, lldb will do the "right thing" in picking
- // a reasonable display for the array entries. you can override this by
- // giving other input (e.g. ${*var[1-3].member1%uint8_t[]}) and they
- // will be honored
- char* special_directions = NULL;
- if (close_bracket_position && (var_name_end-close_bracket_position > 1))
- {
- int base_len = var_name_end-close_bracket_position;
- special_directions = new char[8+base_len];
- special_directions[0] = '$';
- special_directions[1] = '{';
- special_directions[2] = 'v';
- special_directions[3] = 'a';
- special_directions[4] = 'r';
- memcpy(special_directions+5, close_bracket_position+1, base_len);
- special_directions[base_len+7] = '\0';
- printf("%s\n",special_directions);
- }
-
- // let us display items index_lower thru index_higher of this array
- s.PutChar('[');
- var_success = true;
- const char* expr_path = NULL;
- const char* ptr_deref_format = "%s[%d]";
- char* ptr_deref_buffer = new char[1024];
- StreamString expr_path_string;
-
- if(is_pointer)
- {
- vobj->GetExpressionPath(expr_path_string, true, ValueObject::eHonorPointers);
- expr_path = expr_path_string.GetData();
- }
-
- for(;index_lower<=index_higher;index_lower++)
- {
- ValueObject* item;
-
- if(is_array)
- item = vobj->GetChildAtIndex(index_lower, true).get();
- else
- {
-#ifdef VERBOSE_FORMATPROMPT_OUTPUT
- printf("name to deref in phase 0: %s\n",expr_path);
-#endif //VERBOSE_FORMATPROMPT_OUTPUT
- ::sprintf(ptr_deref_buffer, ptr_deref_format, expr_path, index_lower);
-#ifdef VERBOSE_FORMATPROMPT_OUTPUT
- printf("name to deref in phase 1: %s\n",ptr_deref_buffer);
-#endif //VERBOSE_FORMATPROMPT_OUTPUT
- lldb::VariableSP var_sp;
- Error error;
- item = exe_ctx->frame->GetValueForVariableExpressionPath (ptr_deref_buffer,
- eNoDynamicValues,
- 0,
- var_sp,
- error).get();
- if (error.Fail())
- {
-#ifdef VERBOSE_FORMATPROMPT_OUTPUT
- printf("ERROR: %s\n",error.AsCString("unknown"));
-#endif //VERBOSE_FORMATPROMPT_OUTPUT
- break;
- }
- }
-
- if (!special_directions)
- {
- targetvalue = item->GetPrintableRepresentation(val_obj_display, custom_format);
- if(targetvalue)
- s.PutCString(targetvalue);
- var_success &= (targetvalue != NULL);
- if(custom_format != eFormatInvalid)
- item->SetFormat(eFormatDefault);
- }
- else
- {
- var_success &= FormatPrompt(special_directions, sc, exe_ctx, addr, s, NULL, item);
- }
-
- if(index_lower < index_higher)
- s.PutChar(',');
- }
- s.PutChar(']');
- break;
-
- }
- else if (is_pointer)
- {
- var_name_begin++;
- uint32_t offset = 0;
- DataExtractor read_for_null = vobj->GetDataExtractor();
- if (read_for_null.GetPointer(&offset) == 0)
- break;
- if (ClangASTContext::IsAggregateType (elem_or_pointee_clang_type) )
- {
- Error error;
- realvobj = vobj;
- vobj = vobj->Dereference(error).get();
- if(!vobj || error.Fail())
- break;
- }
- else if (ClangASTContext::IsCharType (elem_or_pointee_clang_type))
- {
- StreamString sstr;
- ExecutionContextScope *exe_scope = vobj->GetExecutionContextScope();
- Process *process = exe_scope->CalculateProcess();
- if(!process) break;
- lldb::addr_t cstr_address = LLDB_INVALID_ADDRESS;
- AddressType cstr_address_type = eAddressTypeInvalid;
- DataExtractor data;
- size_t bytes_read = 0;
- std::vector<char> data_buffer;
- Error error;
- cstr_address = vobj->GetPointerValue (cstr_address_type, true);
- {
- const size_t k_max_buf_size = 256;
- data_buffer.resize (k_max_buf_size + 1);
- // NULL terminate in case we don't get the entire C string
- data_buffer.back() = '\0';
-
- sstr << '"';
-
- data.SetData (&data_buffer.front(), data_buffer.size(), endian::InlHostByteOrder());
- while ((bytes_read = process->ReadMemory (cstr_address, &data_buffer.front(), k_max_buf_size, error)) > 0)
- {
- size_t len = strlen(&data_buffer.front());
- if (len == 0)
- break;
- if (len > bytes_read)
- len = bytes_read;
-
- data.Dump (&sstr,
- 0, // Start offset in "data"
- eFormatCharArray, // Print as characters
- 1, // Size of item (1 byte for a char!)
- len, // How many bytes to print?
- UINT32_MAX, // num per line
- LLDB_INVALID_ADDRESS,// base address
- 0, // bitfield bit size
- 0); // bitfield bit offset
-
- if (len < k_max_buf_size)
- break;
- cstr_address += k_max_buf_size;
- }
- sstr << '"';
- s.PutCString(sstr.GetData());
- var_success = true;
- break;
- }
- }
- else /*some other pointer type*/
- {
- Error error;
- realvobj = vobj;
- vobj = vobj->Dereference(error).get();
- if(!vobj || error.Fail())
- break;
- }
- }
- else
- break;
+ do_deref_pointer = true;
+ var_name_begin++;
}
case 'v':
{
- const char* targetvalue;
ValueObject::ValueObjectRepresentationStyle val_obj_display = ValueObject::eDisplaySummary;
ValueObject* target;
lldb::Format custom_format = eFormatInvalid;
- int bitfield_lower = -1;
- int bitfield_higher = -1;
+ const char* var_name_final;
+ const char* var_name_final_if_array_range = NULL;
+ const char* close_bracket_position;
+ int64_t index_lower = -1, index_higher = -1;
+ bool is_array_range = false;
if (!vobj) break;
// simplest case ${var}, just print vobj's value
if (::strncmp (var_name_begin, "var}", strlen("var}")) == 0)
@@ -1065,217 +985,140 @@
else if (::strncmp(var_name_begin,"var%",strlen("var%")) == 0)
{
// this is a variable with some custom format applied to it
- const char* var_name_final;
+ const char* percent_position;
target = vobj;
val_obj_display = ValueObject::eDisplayValue;
- {
- const char* percent_position = ::strchr(var_name_begin,'%'); // TODO: make this a constant
- //if(!percent_position || percent_position > var_name_end)
- // var_name_final = var_name_end;
- //else
- //{
- var_name_final = percent_position;
- char* format_name = new char[var_name_end-var_name_final]; format_name[var_name_end-var_name_final-1] = '\0';
- memcpy(format_name, var_name_final+1, var_name_end-var_name_final-1);
- if ( !FormatManager::GetFormatFromCString(format_name,
- true,
- custom_format) )
- {
- // if this is an @ sign, print ObjC description
- if(*format_name == '@')
- val_obj_display = ValueObject::eDisplayLanguageSpecific;
- }
- delete format_name;
- //}
- }
- }
- else if (::strncmp(var_name_begin,"var[",strlen("var[")) == 0)
- {
- // this is a bitfield variable
- const char *var_name_final;
- target = vobj;
- val_obj_display = ValueObject::eDisplayValue;
- {
- const char* percent_position = ::strchr(var_name_begin,'%');
- if(!percent_position || percent_position > var_name_end)
- var_name_final = var_name_end;
- else
- {
- var_name_final = percent_position;
- char* format_name = new char[var_name_end-var_name_final]; format_name[var_name_end-var_name_final-1] = '\0';
- memcpy(format_name, var_name_final+1, var_name_end-var_name_final-1);
- if ( !FormatManager::GetFormatFromCString(format_name,
- true,
- custom_format) )
- {
- delete format_name;
- break;
- }
- else
- delete format_name;
- }
- }
-
- {
- // code here might be simpler than in the case below
- const char* open_bracket_position = ::strchr(var_name_begin,'[');
- if(open_bracket_position && open_bracket_position < var_name_final)
- {
- const char* separator_position = ::strchr(open_bracket_position,'-'); // might be NULL if this is a simple var[N] bitfield
- const char* close_bracket_position = ::strchr(open_bracket_position,']');
- // as usual, we assume that [] will come before %
- //printf("trying to expand a []\n");
- var_name_final = open_bracket_position;
- if (separator_position == NULL || separator_position > var_name_end)
- {
- char *end = NULL;
- bitfield_lower = ::strtoul (open_bracket_position+1, &end, 0);
- bitfield_higher = bitfield_lower;
- //printf("got to read low=%d high same\n",bitfield_lower);
- }
- else if(close_bracket_position && close_bracket_position < var_name_end)
- {
- char *end = NULL;
- bitfield_lower = ::strtoul (open_bracket_position+1, &end, 0);
- bitfield_higher = ::strtoul (separator_position+1, &end, 0);
- //printf("got to read low=%d high=%d\n",bitfield_lower,bitfield_higher);
- }
- else
- break;
- if(bitfield_lower > bitfield_higher)
- {
- int temp = bitfield_lower;
- bitfield_lower = bitfield_higher;
- bitfield_higher = temp;
- }
- }
- }
+ ScanFormatDescriptor(var_name_begin,
+ var_name_end,
+ &var_name_final,
+ &percent_position,
+ &custom_format,
+ &val_obj_display);
}
// this is ${var.something} or multiple .something nested
else if (::strncmp (var_name_begin, "var", strlen("var")) == 0)
{
- // check for custom format string
-
- // we need this because we might have ${var.something%format}. in this case var_name_end
- // still points to the closing }, but we must extract the variable name only up to
- // before the %. var_name_final will point to that % sign position
- const char* var_name_final;
-
- {
- const char* percent_position = ::strchr(var_name_begin,'%');
- if(!percent_position || percent_position > var_name_end)
- var_name_final = var_name_end;
- else
- {
- var_name_final = percent_position;
- char* format_name = new char[var_name_end-var_name_final]; format_name[var_name_end-var_name_final-1] = '\0';
- memcpy(format_name, var_name_final+1, var_name_end-var_name_final-1);
- if ( !FormatManager::GetFormatFromCString(format_name,
- true,
- custom_format) )
- {
- // if this is an @ sign, print ObjC description
- if(*format_name == '@')
- val_obj_display = ValueObject::eDisplayLanguageSpecific;
- // if this is a V, print the value using the default format
- if(*format_name == 'V')
- val_obj_display = ValueObject::eDisplayValue;
- }
- // a good custom format tells us to print the value using it
- else
- val_obj_display = ValueObject::eDisplayValue;
- }
- }
-
- {
- const char* open_bracket_position = ::strchr(var_name_begin,'[');
- if(open_bracket_position && open_bracket_position < var_name_final)
- {
- const char* separator_position = ::strchr(open_bracket_position,'-'); // might be NULL if this is a simple var[N] bitfield
- const char* close_bracket_position = ::strchr(open_bracket_position,']');
- // as usual, we assume that [] will come before %
- //printf("trying to expand a []\n");
- var_name_final = open_bracket_position;
- if (separator_position == NULL || separator_position > var_name_end)
- {
- char *end = NULL;
- bitfield_lower = ::strtoul (open_bracket_position+1, &end, 0);
- bitfield_higher = bitfield_lower;
- //printf("got to read low=%d high same\n",bitfield_lower);
- }
- else if(close_bracket_position && close_bracket_position < var_name_end)
- {
- char *end = NULL;
- bitfield_lower = ::strtoul (open_bracket_position+1, &end, 0);
- bitfield_higher = ::strtoul (separator_position+1, &end, 0);
- //printf("got to read low=%d high=%d\n",bitfield_lower,bitfield_higher);
- }
- else
- break;
- if(bitfield_lower > bitfield_higher)
- {
- int temp = bitfield_lower;
- bitfield_lower = bitfield_higher;
- bitfield_higher = temp;
- }
- //*((char*)open_bracket_position) = '\0';
- //printf("variable name is %s\n",var_name_begin);
- //*((char*)open_bracket_position) = '[';
- }
- }
+ const char* percent_position;
+ ScanFormatDescriptor(var_name_begin,
+ var_name_end,
+ &var_name_final,
+ &percent_position,
+ &custom_format,
+ &val_obj_display);
+
+ const char* open_bracket_position;
+ const char* separator_position;
+ ScanBracketedRange(var_name_begin,
+ var_name_end,
+ var_name_final,
+ &open_bracket_position,
+ &separator_position,
+ &close_bracket_position,
+ &var_name_final_if_array_range,
+ &index_lower,
+ &index_higher);
+
Error error;
- lldb::VariableSP var_sp;
- StreamString sstring;
- vobj->GetExpressionPath(sstring, true, ValueObject::eHonorPointers);
-#ifdef VERBOSE_FORMATPROMPT_OUTPUT
- printf("name to expand in phase 0: %s\n",sstring.GetData());
-#endif //VERBOSE_FORMATPROMPT_OUTPUT
- sstring.PutRawBytes(var_name_begin+3, var_name_final-var_name_begin-3);
-#ifdef VERBOSE_FORMATPROMPT_OUTPUT
- printf("name to expand in phase 1: %s\n",sstring.GetData());
-#endif //VERBOSE_FORMATPROMPT_OUTPUT
- std::string name = std::string(sstring.GetData());
- target = exe_ctx->frame->GetValueForVariableExpressionPath (name.c_str(),
- eNoDynamicValues,
- 0,
- var_sp,
- error).get();
- if (error.Fail())
+ target = ExpandExpressionPath(vobj,
+ exe_ctx->frame,
+ &do_deref_pointer,
+ var_name_begin,
+ var_name_final,
+ error).get();
+
+ if (error.Fail() || !target)
{
#ifdef VERBOSE_FORMATPROMPT_OUTPUT
printf("ERROR: %s\n",error.AsCString("unknown"));
#endif //VERBOSE_FORMATPROMPT_OUTPUT
- break;
+ if (var_name_final_if_array_range)
+ {
+ target = ExpandExpressionPath(vobj,
+ exe_ctx->frame,
+ &do_deref_pointer,
+ var_name_begin,
+ var_name_final_if_array_range,
+ error).get();
+ }
+
+ IFERROR_PRINT_IT
+ else
+ is_array_range = true;
}
+
+ do_deref_pointer = false; // I have honored the request to deref
+
}
else
break;
- if (bitfield_lower >= 0)
+
+ if(do_deref_pointer)
{
- //printf("trying to print a []\n");
- // format this as a bitfield
- DataExtractor extractor = target->GetDataExtractor();
- uint32_t item_byte_size = ClangASTType::GetTypeByteSize(target->GetClangAST(), target->GetClangType());
- if(custom_format == eFormatInvalid)
- custom_format = eFormatHex;
- var_success =
- extractor.Dump(&s, 0, custom_format, item_byte_size, 1, 1, LLDB_INVALID_ADDRESS, bitfield_higher-bitfield_lower+1, bitfield_lower) > 0;
- //printf("var_success = %s\n",var_success ? "true" : "false");
+ // I have not deref-ed yet, let's do it
+ // this happens when we are not going through GetValueForVariableExpressionPath
+ // to get to the target ValueObject
+ Error error;
+ target = target->Dereference(error).get();
+ IFERROR_PRINT_IT
+ do_deref_pointer = false;
}
+
+ if(!is_array_range)
+ var_success = target->DumpPrintableRepresentation(s,val_obj_display, custom_format);
else
{
- // format this as usual
- targetvalue = target->GetPrintableRepresentation(val_obj_display, custom_format);
- if(targetvalue)
- s.PutCString(targetvalue);
- var_success = targetvalue;
- //printf("here I come 4 : %s\n",var_success ? "good" : "bad");
- if(custom_format != eFormatInvalid)
- target->SetFormat(eFormatDefault);
- //printf("here I come 5\n");
+ bool is_array = ClangASTContext::IsArrayType(vobj->GetClangType());
+ bool is_pointer = ClangASTContext::IsPointerType(vobj->GetClangType());
+
+ if(!is_array && !is_pointer)
+ break;
+
+ char* special_directions = NULL;
+ if (close_bracket_position && (var_name_end-close_bracket_position > 1))
+ {
+ int base_len = var_name_end-close_bracket_position;
+ special_directions = new char[8+base_len];
+ special_directions[0] = '$';
+ special_directions[1] = '{';
+ special_directions[2] = 'v';
+ special_directions[3] = 'a';
+ special_directions[4] = 'r';
+ memcpy(special_directions+5, close_bracket_position+1, base_len);
+ special_directions[base_len+7] = '\0';
+#ifdef VERBOSE_FORMATPROMPT_OUTPUT
+ printf("%s\n",special_directions);
+#endif //VERBOSE_FORMATPROMPT_OUTPUT
+ }
+
+ // let us display items index_lower thru index_higher of this array
+ s.PutChar('[');
+ var_success = true;
+
+ if(index_higher < 0)
+ index_higher = vobj->GetNumChildren() - 1;
+
+ for(;index_lower<=index_higher;index_lower++)
+ {
+ Error error;
+ ValueObject* item = ExpandIndexedExpression(vobj,
+ index_lower,
+ exe_ctx->frame,
+ error).get();
+
+
+ IFERROR_PRINT_IT
+ if (!special_directions)
+ var_success &= item->DumpPrintableRepresentation(s,val_obj_display, custom_format);
+ else
+ var_success &= FormatPrompt(special_directions, sc, exe_ctx, addr, s, NULL, item);
+
+ if(index_lower < index_higher)
+ s.PutChar(',');
+ }
+ s.PutChar(']');
}
- break;
+ break;
}
case 'a':
if (::strncmp (var_name_begin, "addr}", strlen("addr}")) == 0)
Modified: lldb/trunk/source/Core/ValueObject.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ValueObject.cpp?rev=134458&r1=134457&r2=134458&view=diff
==============================================================================
--- lldb/trunk/source/Core/ValueObject.cpp (original)
+++ lldb/trunk/source/Core/ValueObject.cpp Tue Jul 5 21:13:41 2011
@@ -74,6 +74,7 @@
m_pointers_point_to_load_addrs (false),
m_is_deref_of_parent (false),
m_is_array_item_for_pointer(false),
+ m_is_bitfield_for_scalar(false),
m_last_format_mgr_revision(0),
m_last_summary_format(),
m_last_value_format()
@@ -110,6 +111,7 @@
m_pointers_point_to_load_addrs (false),
m_is_deref_of_parent (false),
m_is_array_item_for_pointer(false),
+ m_is_bitfield_for_scalar(false),
m_last_format_mgr_revision(0),
m_last_summary_format(),
m_last_value_format()
@@ -515,7 +517,7 @@
s.PutCString(", ");
s.PutCString(child_sp.get()->GetName().AsCString());
s.PutChar('=');
- s.PutCString(child_sp.get()->GetValueAsCString());
+ s.PutCString(child_sp.get()->GetPrintableRepresentation());
}
}
@@ -768,7 +770,9 @@
if (m_last_value_format)
format = m_last_value_format->m_format;
else
- format = ClangASTType::GetFormat(clang_type);
+ // force the system into using unsigned integers for bitfields
+ format = (m_is_bitfield_for_scalar ? eFormatUnsigned :
+ ClangASTType::GetFormat(clang_type));
}
if (ClangASTType::DumpTypeValue (GetClangAST(), // The clang AST
@@ -844,15 +848,35 @@
break;
}
+ if (!return_value)
+ {
+ // try to pick the other choice
+ if (val_obj_display == eDisplayValue)
+ return_value = GetSummaryAsCString();
+ else if (val_obj_display == eDisplaySummary)
+ return_value = GetValueAsCString();
+ else
+ return_value = "";
+ }
- // try to use the value if the user's choice failed
- if(!return_value && val_obj_display != eDisplayValue)
- return_value = GetValueAsCString();
-
- return return_value;
+ return (return_value ? return_value : "");
}
+bool
+ValueObject::DumpPrintableRepresentation(Stream& s,
+ ValueObjectRepresentationStyle val_obj_display,
+ lldb::Format custom_format)
+{
+ const char *targetvalue = GetPrintableRepresentation(val_obj_display, custom_format);
+ if(targetvalue)
+ s.PutCString(targetvalue);
+ bool var_success = (targetvalue != NULL);
+ if(custom_format != eFormatInvalid)
+ SetFormat(eFormatDefault);
+ return var_success;
+}
+
addr_t
ValueObject::GetAddressOf (AddressType &address_type, bool scalar_is_load_address)
{
@@ -1073,6 +1097,12 @@
}
bool
+ValueObject::IsScalarType ()
+{
+ return ClangASTContext::IsScalarType (GetClangType());
+}
+
+bool
ValueObject::IsIntegerType (bool &is_signed)
{
return ClangASTContext::IsIntegerType (GetClangType(), is_signed);
@@ -1128,6 +1158,47 @@
return synthetic_child_sp;
}
+ValueObjectSP
+ValueObject::GetSyntheticBitFieldChild (uint32_t from, uint32_t to, bool can_create)
+{
+ ValueObjectSP synthetic_child_sp;
+ if (IsScalarType ())
+ {
+ char index_str[64];
+ snprintf(index_str, sizeof(index_str), "[%i-%i]", from, to);
+ ConstString index_const_str(index_str);
+ // Check if we have already created a synthetic array member in this
+ // valid object. If we have we will re-use it.
+ synthetic_child_sp = GetSyntheticChild (index_const_str);
+ if (!synthetic_child_sp)
+ {
+ ValueObjectChild *synthetic_child;
+ // We haven't made a synthetic array member for INDEX yet, so
+ // lets make one and cache it for any future reference.
+ synthetic_child = new ValueObjectChild(*this,
+ GetClangAST(),
+ GetClangType(),
+ index_const_str,
+ GetByteSize(),
+ 0,
+ to-from+1,
+ from,
+ false,
+ false);
+
+ // Cache the value if we got one back...
+ if (synthetic_child)
+ {
+ AddSyntheticChild(index_const_str, synthetic_child);
+ synthetic_child_sp = synthetic_child->GetSP();
+ synthetic_child_sp->SetName(index_str);
+ synthetic_child_sp->m_is_bitfield_for_scalar = true;
+ }
+ }
+ }
+ return synthetic_child_sp;
+}
+
void
ValueObject::CalculateDynamicValue (lldb::DynamicValueType use_dynamic)
{
Modified: lldb/trunk/source/Symbol/ClangASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/ClangASTContext.cpp?rev=134458&r1=134457&r2=134458&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/ClangASTContext.cpp (original)
+++ lldb/trunk/source/Symbol/ClangASTContext.cpp Tue Jul 5 21:13:41 2011
@@ -4464,6 +4464,40 @@
return false;
}
+bool
+ClangASTContext::IsScalarType (lldb::clang_type_t clang_type)
+{
+ bool is_signed;
+ if (ClangASTContext::IsIntegerType(clang_type, is_signed))
+ return true;
+
+ uint32_t count;
+ bool is_complex;
+ return ClangASTContext::IsFloatingPointType(clang_type, count, is_complex) && !is_complex;
+}
+
+bool
+ClangASTContext::IsPointerToScalarType (lldb::clang_type_t clang_type)
+{
+ if (!IsPointerType(clang_type))
+ return false;
+
+ QualType qual_type (QualType::getFromOpaquePtr(clang_type));
+ lldb::clang_type_t pointee_type = qual_type.getTypePtr()->getPointeeType().getAsOpaquePtr();
+ return IsScalarType(pointee_type);
+}
+
+bool
+ClangASTContext::IsArrayOfScalarType (lldb::clang_type_t clang_type)
+{
+ if (!IsArrayType(clang_type))
+ return false;
+
+ QualType qual_type (QualType::getFromOpaquePtr(clang_type));
+ lldb::clang_type_t item_type = cast<ArrayType>(qual_type.getTypePtr())->getElementType().getAsOpaquePtr();
+ return IsScalarType(item_type);
+}
+
bool
ClangASTContext::GetCXXClassName (clang_type_t clang_type, std::string &class_name)
Added: lldb/trunk/source/Symbol/TypeHierarchyNavigator.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/TypeHierarchyNavigator.cpp?rev=134458&view=auto
==============================================================================
--- lldb/trunk/source/Symbol/TypeHierarchyNavigator.cpp (added)
+++ lldb/trunk/source/Symbol/TypeHierarchyNavigator.cpp Tue Jul 5 21:13:41 2011
@@ -0,0 +1,121 @@
+//===-- TypeHierarchyNavigator.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/Error.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/TypeHierarchyNavigator.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+bool
+TypeHierarchyNavigator::LoopThrough(TypeHierarchyNavigatorCallback callback,
+ void* callback_baton)
+{
+ return LoopThrough(m_root_type,
+ callback,
+ eRootType,
+ (callback_baton ? callback_baton : m_default_callback_baton));
+}
+
+bool
+TypeHierarchyNavigator::LoopThrough(const clang::QualType& qual_type,
+ TypeHierarchyNavigatorCallback callback,
+ RelationshipToCurrentType reason_why_here,
+ void* callback_baton)
+{
+ if (qual_type.isNull())
+ return true;
+ clang::QualType type = qual_type.getUnqualifiedType();
+ type.removeLocalConst(); type.removeLocalVolatile(); type.removeLocalRestrict();
+ const clang::Type* typePtr = type.getTypePtrOrNull();
+ if (!typePtr)
+ return true;
+ if (!callback(type, reason_why_here, callback_baton))
+ return false;
+ // look for a "base type", whatever that means
+ if (typePtr->isReferenceType())
+ {
+ if (LoopThrough(type.getNonReferenceType(), callback, eStrippedReference, callback_baton) == false)
+ return false;
+ }
+ if (typePtr->isPointerType())
+ {
+ if (LoopThrough(typePtr->getPointeeType(), callback, eStrippedPointer, callback_baton) == false)
+ return false;
+ }
+ if (typePtr->isObjCObjectPointerType())
+ {
+ /*
+ for some reason, C++ can quite easily obtain the type hierarchy for a ValueObject
+ even if the VO represent a pointer-to-class, as long as the typePtr is right
+ Objective-C on the other hand cannot really complete an @interface when
+ the VO refers to a pointer-to- at interface
+ */
+ Error error;
+ ValueObject* target = m_value_object.Dereference(error).get();
+ if(error.Fail() || !target)
+ return true;
+ if (LoopThrough(typePtr->getPointeeType(), callback, eStrippedPointer, callback_baton) == false)
+ return false;
+ }
+ const clang::ObjCObjectType *objc_class_type = typePtr->getAs<clang::ObjCObjectType>();
+ if (objc_class_type)
+ {
+ clang::ASTContext *ast = m_value_object.GetClangAST();
+ if (ClangASTContext::GetCompleteType(ast, m_value_object.GetClangType()) && !objc_class_type->isObjCId())
+ {
+ clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
+ if(class_interface_decl)
+ {
+ clang::ObjCInterfaceDecl *superclass_interface_decl = class_interface_decl->getSuperClass();
+ if(superclass_interface_decl)
+ {
+ clang::QualType ivar_qual_type(ast->getObjCInterfaceType(superclass_interface_decl));
+ return LoopThrough(ivar_qual_type, callback, eObjCBaseClass, callback_baton);
+ }
+ }
+ }
+ }
+ // for C++ classes, navigate up the hierarchy
+ if (typePtr->isRecordType())
+ {
+ clang::CXXRecordDecl* record = typePtr->getAsCXXRecordDecl();
+ if (record)
+ {
+ if (!record->hasDefinition())
+ ClangASTContext::GetCompleteType(m_value_object.GetClangAST(), m_value_object.GetClangType());
+ if (record->hasDefinition())
+ {
+ clang::CXXRecordDecl::base_class_iterator pos,end;
+ if( record->getNumBases() > 0)
+ {
+ end = record->bases_end();
+ for (pos = record->bases_begin(); pos != end; pos++)
+ if (LoopThrough(pos->getType(), callback, eCXXBaseClass, callback_baton) == false)
+ return false;
+ }
+ if (record->getNumVBases() > 0)
+ {
+ end = record->vbases_end();
+ for (pos = record->vbases_begin(); pos != end; pos++)
+ if (LoopThrough(pos->getType(), callback, eCXXVBaseClass, callback_baton) == false)
+ return false;
+ }
+ }
+ }
+ }
+ // try to strip typedef chains
+ const clang::TypedefType* type_tdef = type->getAs<clang::TypedefType>();
+ if (type_tdef)
+ return LoopThrough(type_tdef->getDecl()->getUnderlyingType(), callback, eStrippedTypedef, callback_baton);
+ else
+ return true;
+}
Modified: lldb/trunk/source/Target/StackFrame.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/StackFrame.cpp?rev=134458&r1=134457&r2=134458&view=diff
==============================================================================
--- lldb/trunk/source/Target/StackFrame.cpp (original)
+++ lldb/trunk/source/Target/StackFrame.cpp Tue Jul 5 21:13:41 2011
@@ -645,9 +645,47 @@
{
char *end = NULL;
long child_index = ::strtol (&var_path[1], &end, 0);
- if (end && *end == ']')
+ if (end && *end == ']'
+ && *(end-1) != '[') // this code forces an error in the case of arr[]. as bitfield[] is not a good syntax we're good to go
{
-
+ if (ClangASTContext::IsPointerToScalarType(valobj_sp->GetClangType()) && deref)
+ {
+ // what we have is *ptr[low]. the most similar C++ syntax is to deref ptr
+ // and extract bit low out of it. reading array item low
+ // would be done by saying ptr[low], without a deref * sign
+ Error error;
+ ValueObjectSP temp(valobj_sp->Dereference(error));
+ if (error.Fail())
+ {
+ valobj_sp->GetExpressionPath (var_expr_path_strm, false);
+ error.SetErrorStringWithFormat ("could not dereference \"(%s) %s\"",
+ valobj_sp->GetTypeName().AsCString("<invalid type>"),
+ var_expr_path_strm.GetString().c_str());
+ return ValueObjectSP();
+ }
+ valobj_sp = temp;
+ deref = false;
+ }
+ else if (ClangASTContext::IsArrayOfScalarType(valobj_sp->GetClangType()) && deref)
+ {
+ // what we have is *arr[low]. the most similar C++ syntax is to get arr[0]
+ // (an operation that is equivalent to deref-ing arr)
+ // and extract bit low out of it. reading array item low
+ // would be done by saying arr[low], without a deref * sign
+ Error error;
+ ValueObjectSP temp(valobj_sp->GetChildAtIndex (0, true));
+ if (error.Fail())
+ {
+ valobj_sp->GetExpressionPath (var_expr_path_strm, false);
+ error.SetErrorStringWithFormat ("could not get item 0 for \"(%s) %s\"",
+ valobj_sp->GetTypeName().AsCString("<invalid type>"),
+ var_expr_path_strm.GetString().c_str());
+ return ValueObjectSP();
+ }
+ valobj_sp = temp;
+ deref = false;
+ }
+
if (valobj_sp->IsPointerType ())
{
child_valobj_sp = valobj_sp->GetSyntheticArrayMemberFromPointer (child_index, true);
@@ -674,6 +712,19 @@
var_expr_path_strm.GetString().c_str());
}
}
+ else if (ClangASTContext::IsScalarType(valobj_sp->GetClangType()))
+ {
+ // this is a bitfield asking to display just one bit
+ child_valobj_sp = valobj_sp->GetSyntheticBitFieldChild(child_index, child_index, true);
+ if (!child_valobj_sp)
+ {
+ valobj_sp->GetExpressionPath (var_expr_path_strm, false);
+ error.SetErrorStringWithFormat ("bitfield range %i-%i is not valid for \"(%s) %s\"",
+ child_index, child_index,
+ valobj_sp->GetTypeName().AsCString("<invalid type>"),
+ var_expr_path_strm.GetString().c_str());
+ }
+ }
else
{
valobj_sp->GetExpressionPath (var_expr_path_strm, false);
@@ -702,6 +753,97 @@
// able to find the child member
break;
}
+ else if(end && *end == '-')
+ {
+ // this is most probably a BitField, let's take a look
+ char *real_end = NULL;
+ long final_index = ::strtol (end+1, &real_end, 0);
+ if(real_end && *real_end == ']')
+ {
+ // if the format given is [high-low], swap range
+ if(child_index > final_index)
+ {
+ long temp = child_index;
+ child_index = final_index;
+ final_index = temp;
+ }
+
+ if (ClangASTContext::IsPointerToScalarType(valobj_sp->GetClangType()) && deref)
+ {
+ // what we have is *ptr[low-high]. the most similar C++ syntax is to deref ptr
+ // and extract bits low thru high out of it. reading array items low thru high
+ // would be done by saying ptr[low-high], without a deref * sign
+ Error error;
+ ValueObjectSP temp(valobj_sp->Dereference(error));
+ if (error.Fail())
+ {
+ valobj_sp->GetExpressionPath (var_expr_path_strm, false);
+ error.SetErrorStringWithFormat ("could not dereference \"(%s) %s\"",
+ valobj_sp->GetTypeName().AsCString("<invalid type>"),
+ var_expr_path_strm.GetString().c_str());
+ return ValueObjectSP();
+ }
+ valobj_sp = temp;
+ deref = false;
+ }
+ else if (ClangASTContext::IsArrayOfScalarType(valobj_sp->GetClangType()) && deref)
+ {
+ // what we have is *arr[low-high]. the most similar C++ syntax is to get arr[0]
+ // (an operation that is equivalent to deref-ing arr)
+ // and extract bits low thru high out of it. reading array items low thru high
+ // would be done by saying arr[low-high], without a deref * sign
+ Error error;
+ ValueObjectSP temp(valobj_sp->GetChildAtIndex (0, true));
+ if (error.Fail())
+ {
+ valobj_sp->GetExpressionPath (var_expr_path_strm, false);
+ error.SetErrorStringWithFormat ("could not get item 0 for \"(%s) %s\"",
+ valobj_sp->GetTypeName().AsCString("<invalid type>"),
+ var_expr_path_strm.GetString().c_str());
+ return ValueObjectSP();
+ }
+ valobj_sp = temp;
+ deref = false;
+ }
+
+ child_valobj_sp = valobj_sp->GetSyntheticBitFieldChild(child_index, final_index, true);
+ if (!child_valobj_sp)
+ {
+ valobj_sp->GetExpressionPath (var_expr_path_strm, false);
+ error.SetErrorStringWithFormat ("bitfield range %i-%i is not valid for \"(%s) %s\"",
+ child_index, final_index,
+ valobj_sp->GetTypeName().AsCString("<invalid type>"),
+ var_expr_path_strm.GetString().c_str());
+ }
+ }
+
+ if (!child_valobj_sp)
+ {
+ // Invalid bitfield range...
+ return ValueObjectSP();
+ }
+
+ // Erase the bitfield member specification '[%i-%i]' where
+ // %i is the index
+ var_path.erase(0, (real_end - var_path.c_str()) + 1);
+ separator_idx = var_path.find_first_of(".-[");
+ if (use_dynamic != lldb::eNoDynamicValues)
+ {
+ ValueObjectSP dynamic_value_sp(child_valobj_sp->GetDynamicValue(use_dynamic));
+ 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;
+
+ }
+ }
+ else
+ {
+ error.SetErrorStringWithFormat("invalid square bracket encountered after \"%s\" in \"%s\"",
+ var_expr_path_strm.GetString().c_str(),
+ var_path.c_str());
}
return ValueObjectSP();
Modified: lldb/trunk/test/functionalities/data-formatter/data-formatter-advanced/TestDataFormatterAdv.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-advanced/TestDataFormatterAdv.py?rev=134458&r1=134457&r2=134458&view=diff
==============================================================================
--- lldb/trunk/test/functionalities/data-formatter/data-formatter-advanced/TestDataFormatterAdv.py (original)
+++ lldb/trunk/test/functionalities/data-formatter/data-formatter-advanced/TestDataFormatterAdv.py Tue Jul 5 21:13:41 2011
@@ -53,13 +53,6 @@
# Execute the cleanup function during test case tear down.
self.addTearDownHook(cleanup)
- self.runCmd("type summary add -f \"pippo\" -x \"IUseCharStar\"")
-
- self.expect("frame variable iEncapsulateCharStar",
- substrs = ['pippo'])
-
- self.runCmd("type summary clear")
-
self.runCmd("type summary add -f \"pippo\" \"i_am_cool\"")
self.runCmd("type summary add -f \"pluto\" -x \"i_am_cool[a-z]*\"")
@@ -77,12 +70,12 @@
self.runCmd("type summary clear")
- self.runCmd("type summary add -f \"${*var[]}\" -x \"int \\[[0-9]\\]")
+ self.runCmd("type summary add -f \"${var[]}\" -x \"int \\[[0-9]\\]")
self.expect("frame variable int_array",
substrs = ['1,2,3,4,5'])
- self.runCmd("type summary add -f \"${*var[].integer}\" -x \"i_am_cool \\[[0-9]\\]")
+ self.runCmd("type summary add -f \"${var[].integer}\" -x \"i_am_cool \\[[0-9]\\]")
self.expect("frame variable cool_array",
substrs = ['1,1,1,1,6'])
@@ -93,17 +86,79 @@
self.expect("frame variable iAmInt",
substrs = ['01'])
-
- self.runCmd("type summary add -f \"${*var[0-1]%x}\" \"int\"")
-
- self.expect("frame variable iAmInt", matching=False,
- substrs = ['01'])
-
+
self.runCmd("type summary add -f \"${var[0-1]%x}\" \"int\"")
self.expect("frame variable iAmInt",
substrs = ['01'])
+ self.runCmd("type summary clear")
+
+ self.runCmd("type summary add -f \"${var[0-1]%x}\" int")
+ self.runCmd("type summary add -f \"${var[0-31]%x}\" float")
+
+ self.expect("frame variable *pointer",
+ substrs = ['0x',
+ '2'])
+
+ self.expect("frame variable cool_array[3].floating",
+ substrs = ['0x'])
+
+ self.runCmd("type summary add -f \"low bits are ${*var[0-1]} tgt is ${*var}\" \"int *\"")
+
+ self.expect("frame variable pointer",
+ substrs = ['low bits are',
+ 'tgt is 6'])
+
+ self.runCmd("type summary add -f \"${*var[0-1]}\" -x \"int \[[0-9]\]\"")
+
+ self.expect("frame variable int_array",
+ substrs = ['3'])
+
+ self.runCmd("type summary clear")
+
+ self.runCmd("type summary add -f \"${var[0-1]}\" -x \"int \[[0-9]\]\"")
+
+ self.expect("frame variable int_array",
+ substrs = ['1,2'])
+
+ self.runCmd("type summary clear")
+
+ self.runCmd("type summary add -c -x \"i_am_cool \[[0-9]\]\"")
+ self.runCmd("type summary add -c i_am_cool")
+
+ self.expect("frame variable cool_array",
+ substrs = ['[0]',
+ '[1]',
+ '[2]',
+ '[3]',
+ '[4]',
+ 'integer',
+ 'character',
+ 'floating'])
+
+ self.runCmd("type summary add -f \"int = ${*var.int_pointer}, float = ${*var.float_pointer}\" IWrapPointers")
+
+ self.expect("frame variable wrapper",
+ substrs = ['int = 4',
+ 'float = 1.1'])
+
+ self.runCmd("type summary add -f \"low bits = ${*var.int_pointer[2]}\" IWrapPointers -p")
+
+ self.expect("frame variable wrapper",
+ substrs = ['low bits = 1'])
+
+ self.expect("frame variable *wrap_pointer",
+ substrs = ['low bits = 1'])
+
+ self.runCmd("type summary clear")
+
+ self.runCmd("type summary add -f \"${var[0][0-2]%hex}\" -x \"int \[[0-9]\]\"")
+
+ self.expect("frame variable int_array",
+ substrs = ['0x',
+ '7'])
+
if __name__ == '__main__':
import atexit
Modified: lldb/trunk/test/functionalities/data-formatter/data-formatter-advanced/main.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-advanced/main.cpp?rev=134458&r1=134457&r2=134458&view=diff
==============================================================================
--- lldb/trunk/test/functionalities/data-formatter/data-formatter-advanced/main.cpp (original)
+++ lldb/trunk/test/functionalities/data-formatter/data-formatter-advanced/main.cpp Tue Jul 5 21:13:41 2011
@@ -34,10 +34,11 @@
floating((F1 + F2)/2) {}
};
-struct IUseCharStar
+struct IWrapPointers
{
- const char* pointer;
- IUseCharStar() : pointer("Hello world") {}
+ int* int_pointer;
+ float* float_pointer;
+ IWrapPointers() : int_pointer(new int(4)), float_pointer(new float(1.111)) {}
};
int main (int argc, const char * argv[])
@@ -58,7 +59,13 @@
int int_array[] = {1,2,3,4,5};
- IUseCharStar iEncapsulateCharStar;
+ IWrapPointers wrapper;
+
+ *int_array = -1;
+
+ int* pointer = &cool_array[4].integer;
+
+ IWrapPointers *wrap_pointer = &wrapper;
return 0; // Set break point at this line.
}
\ No newline at end of file
Modified: lldb/trunk/test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py?rev=134458&r1=134457&r2=134458&view=diff
==============================================================================
--- lldb/trunk/test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py (original)
+++ lldb/trunk/test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py Tue Jul 5 21:13:41 2011
@@ -129,7 +129,7 @@
substrs = ['a test'],
matching = False)
- self.runCmd("type summary add -f \"${*var[1-3]}\" \"int [5]\"")
+ self.runCmd("type summary add -f \"${var[1-3]}\" \"int [5]\"")
self.expect("frame variable int_array",
substrs = ['2',
@@ -138,8 +138,8 @@
self.runCmd("type summary clear")
- self.runCmd("type summary add -f \"${*var[0-2].integer}\" \"i_am_cool *\"")
- self.runCmd("type summary add -f \"${*var[2-4].integer}\" \"i_am_cool [5]\"")
+ self.runCmd("type summary add -f \"${var[0-2].integer}\" \"i_am_cool *\"")
+ self.runCmd("type summary add -f \"${var[2-4].integer}\" \"i_am_cool [5]\"")
self.expect("frame variable cool_array",
substrs = ['1,1,6'])
More information about the lldb-commits
mailing list