2010-06-08 16:52:24 +00:00
//===-- ValueObject.cpp -----------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
2012-12-05 00:20:57 +00:00
# include "lldb/lldb-python.h"
2010-06-08 16:52:24 +00:00
# include "lldb/Core/ValueObject.h"
// C Includes
2010-09-14 23:36:40 +00:00
# include <stdlib.h>
2010-06-08 16:52:24 +00:00
// C++ Includes
// Other libraries and framework includes
# include "llvm/Support/raw_ostream.h"
2010-09-28 01:25:32 +00:00
# include "clang/AST/Type.h"
2010-06-08 16:52:24 +00:00
// Project includes
# include "lldb/Core/DataBufferHeap.h"
2011-08-22 22:03:47 +00:00
# include "lldb/Core/DataVisualization.h"
2011-06-29 22:27:15 +00:00
# include "lldb/Core/Debugger.h"
2011-07-29 19:53:35 +00:00
# include "lldb/Core/Log.h"
2012-08-29 21:13:06 +00:00
# include "lldb/Core/Module.h"
2010-06-08 16:52:24 +00:00
# include "lldb/Core/StreamString.h"
2012-10-27 02:05:48 +00:00
# include "lldb/Core/ValueObjectCast.h"
2010-06-08 16:52:24 +00:00
# include "lldb/Core/ValueObjectChild.h"
2010-12-14 02:59:59 +00:00
# include "lldb/Core/ValueObjectConstResult.h"
2011-04-16 00:01:13 +00:00
# include "lldb/Core/ValueObjectDynamicValue.h"
2010-06-08 16:52:24 +00:00
# include "lldb/Core/ValueObjectList.h"
2011-05-05 23:32:56 +00:00
# include "lldb/Core/ValueObjectMemory.h"
2011-07-22 00:16:08 +00:00
# include "lldb/Core/ValueObjectSyntheticFilter.h"
2010-06-08 16:52:24 +00:00
2011-02-01 01:31:41 +00:00
# include "lldb/Host/Endian.h"
2011-08-12 16:42:31 +00:00
# include "lldb/Interpreter/CommandInterpreter.h"
2011-07-15 02:26:42 +00:00
# include "lldb/Interpreter/ScriptInterpreterPython.h"
2010-07-21 22:12:05 +00:00
# include "lldb/Symbol/ClangASTType.h"
2010-06-08 16:52:24 +00:00
# include "lldb/Symbol/ClangASTContext.h"
# include "lldb/Symbol/Type.h"
2010-09-10 23:12:17 +00:00
# include "lldb/Target/ExecutionContext.h"
2010-09-28 01:25:32 +00:00
# include "lldb/Target/LanguageRuntime.h"
2011-08-02 17:27:39 +00:00
# include "lldb/Target/ObjCLanguageRuntime.h"
2010-06-08 16:52:24 +00:00
# include "lldb/Target/Process.h"
# include "lldb/Target/RegisterContext.h"
2010-09-14 23:36:40 +00:00
# include "lldb/Target/Target.h"
2010-06-08 16:52:24 +00:00
# include "lldb/Target/Thread.h"
2011-07-12 22:56:10 +00:00
# include "lldb/Utility/RefCounter.h"
2010-06-08 16:52:24 +00:00
using namespace lldb ;
using namespace lldb_private ;
2011-07-12 22:56:10 +00:00
using namespace lldb_utility ;
2010-06-08 16:52:24 +00:00
2011-09-02 01:15:17 +00:00
static user_id_t g_value_obj_uid = 0 ;
2010-06-08 16:52:24 +00:00
//----------------------------------------------------------------------
// ValueObject constructor
//----------------------------------------------------------------------
2011-03-31 00:19:25 +00:00
ValueObject : : ValueObject ( ValueObject & parent ) :
2010-06-08 16:52:24 +00:00
UserID ( + + g_value_obj_uid ) , // Unique identifier for every value object
2011-03-31 00:19:25 +00:00
m_parent ( & parent ) ,
2011-04-11 19:41:40 +00:00
m_update_point ( parent . GetUpdatePoint ( ) ) ,
2010-06-08 16:52:24 +00:00
m_name ( ) ,
m_data ( ) ,
m_value ( ) ,
m_error ( ) ,
2010-09-02 02:59:18 +00:00
m_value_str ( ) ,
m_old_value_str ( ) ,
m_location_str ( ) ,
m_summary_str ( ) ,
2010-09-10 23:12:17 +00:00
m_object_desc_str ( ) ,
2011-04-22 23:53:53 +00:00
m_manager ( parent . GetManager ( ) ) ,
2010-09-02 02:59:18 +00:00
m_children ( ) ,
m_synthetic_children ( ) ,
2011-04-22 23:53:53 +00:00
m_dynamic_value ( NULL ) ,
2011-07-22 00:16:08 +00:00
m_synthetic_value ( NULL ) ,
2011-04-22 23:53:53 +00:00
m_deref_valobj ( NULL ) ,
2010-10-06 03:09:11 +00:00
m_format ( eFormatDefault ) ,
2011-07-19 20:57:44 +00:00
m_last_format_mgr_revision ( 0 ) ,
2011-08-02 23:12:24 +00:00
m_last_format_mgr_dynamic ( parent . m_last_format_mgr_dynamic ) ,
2012-03-01 04:24:26 +00:00
m_type_summary_sp ( ) ,
m_type_format_sp ( ) ,
m_synthetic_children_sp ( ) ,
2011-08-09 02:12:22 +00:00
m_user_id_of_forced_summary ( ) ,
2011-10-31 22:50:49 +00:00
m_address_type_of_ptr_or_ref_children ( eAddressTypeInvalid ) ,
2010-09-02 02:59:18 +00:00
m_value_is_valid ( false ) ,
m_value_did_change ( false ) ,
m_children_count_valid ( false ) ,
2010-12-14 02:59:59 +00:00
m_old_value_valid ( false ) ,
2011-06-29 22:27:15 +00:00
m_is_deref_of_parent ( false ) ,
2011-07-02 00:25:22 +00:00
m_is_array_item_for_pointer ( false ) ,
2011-07-06 02:13:41 +00:00
m_is_bitfield_for_scalar ( false ) ,
2011-07-22 00:16:08 +00:00
m_is_expression_path_child ( false ) ,
2011-07-29 19:53:35 +00:00
m_is_child_at_offset ( false ) ,
2012-02-22 23:57:45 +00:00
m_is_getting_summary ( false ) ,
m_did_calculate_complete_objc_class_type ( false )
2011-03-31 00:19:25 +00:00
{
2011-04-22 23:53:53 +00:00
m_manager - > ManageObject ( this ) ;
2011-03-31 00:19:25 +00:00
}
//----------------------------------------------------------------------
// ValueObject constructor
//----------------------------------------------------------------------
2011-09-06 19:20:51 +00:00
ValueObject : : ValueObject ( ExecutionContextScope * exe_scope ,
AddressType child_ptr_or_ref_addr_type ) :
2011-03-31 00:19:25 +00:00
UserID ( + + g_value_obj_uid ) , // Unique identifier for every value object
m_parent ( NULL ) ,
2011-04-11 19:41:40 +00:00
m_update_point ( exe_scope ) ,
2011-03-31 00:19:25 +00:00
m_name ( ) ,
m_data ( ) ,
m_value ( ) ,
m_error ( ) ,
m_value_str ( ) ,
m_old_value_str ( ) ,
m_location_str ( ) ,
m_summary_str ( ) ,
m_object_desc_str ( ) ,
2011-04-22 23:53:53 +00:00
m_manager ( ) ,
2011-03-31 00:19:25 +00:00
m_children ( ) ,
m_synthetic_children ( ) ,
2011-04-22 23:53:53 +00:00
m_dynamic_value ( NULL ) ,
2011-07-22 00:16:08 +00:00
m_synthetic_value ( NULL ) ,
2011-04-22 23:53:53 +00:00
m_deref_valobj ( NULL ) ,
2011-03-31 00:19:25 +00:00
m_format ( eFormatDefault ) ,
2011-07-19 20:57:44 +00:00
m_last_format_mgr_revision ( 0 ) ,
2011-09-02 01:15:17 +00:00
m_last_format_mgr_dynamic ( eNoDynamicValues ) ,
2012-03-01 04:24:26 +00:00
m_type_summary_sp ( ) ,
m_type_format_sp ( ) ,
m_synthetic_children_sp ( ) ,
2011-08-09 02:12:22 +00:00
m_user_id_of_forced_summary ( ) ,
2011-10-31 22:50:49 +00:00
m_address_type_of_ptr_or_ref_children ( child_ptr_or_ref_addr_type ) ,
2011-03-31 00:19:25 +00:00
m_value_is_valid ( false ) ,
m_value_did_change ( false ) ,
m_children_count_valid ( false ) ,
m_old_value_valid ( false ) ,
2011-06-29 22:27:15 +00:00
m_is_deref_of_parent ( false ) ,
2011-07-02 00:25:22 +00:00
m_is_array_item_for_pointer ( false ) ,
2011-07-06 02:13:41 +00:00
m_is_bitfield_for_scalar ( false ) ,
2011-07-22 00:16:08 +00:00
m_is_expression_path_child ( false ) ,
2011-07-29 19:53:35 +00:00
m_is_child_at_offset ( false ) ,
2012-02-22 23:57:45 +00:00
m_is_getting_summary ( false ) ,
m_did_calculate_complete_objc_class_type ( false )
2010-06-08 16:52:24 +00:00
{
2011-04-22 23:53:53 +00:00
m_manager = new ValueObjectManager ( ) ;
m_manager - > ManageObject ( this ) ;
2010-06-08 16:52:24 +00:00
}
//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
ValueObject : : ~ ValueObject ( )
{
}
bool
2011-07-02 00:25:22 +00:00
ValueObject : : UpdateValueIfNeeded ( bool update_format )
2011-08-02 17:27:39 +00:00
{
return UpdateValueIfNeeded ( m_last_format_mgr_dynamic , update_format ) ;
}
bool
2011-09-02 01:15:17 +00:00
ValueObject : : UpdateValueIfNeeded ( DynamicValueType use_dynamic , bool update_format )
2010-06-08 16:52:24 +00:00
{
2011-06-29 22:27:15 +00:00
2011-09-06 19:20:51 +00:00
bool did_change_formats = false ;
2011-07-02 00:25:22 +00:00
if ( update_format )
2011-09-06 19:20:51 +00:00
did_change_formats = UpdateFormatsIfNeeded ( use_dynamic ) ;
2011-06-29 22:27:15 +00:00
2010-10-05 03:13:51 +00:00
// If this is a constant value, then our success is predicated on whether
// we have an error or not
if ( GetIsConstant ( ) )
2011-09-06 19:20:51 +00:00
{
// if you were asked to update your formatters, but did not get a chance to do it
// clear your own values (this serves the purpose of faking a stop-id for frozen
// objects (which are regarded as constant, but could have changes behind their backs
// because of the frozen-pointer depth limit)
// TODO: decouple summary from value and then remove this code and only force-clear the summary
if ( update_format & & ! did_change_formats )
2012-03-19 22:58:49 +00:00
ClearUserVisibleData ( eClearUserVisibleDataItemsSummary ) ;
2010-10-05 03:13:51 +00:00
return m_error . Success ( ) ;
2011-09-06 19:20:51 +00:00
}
2010-10-05 03:13:51 +00:00
2011-03-31 00:19:25 +00:00
bool first_update = m_update_point . IsFirstEvaluation ( ) ;
if ( m_update_point . NeedsUpdating ( ) )
2010-06-08 16:52:24 +00:00
{
2011-03-31 00:19:25 +00:00
m_update_point . SetUpdated ( ) ;
// Save the old value using swap to avoid a string copy which
// also will clear our m_value_str
if ( m_value_str . empty ( ) )
2010-06-08 16:52:24 +00:00
{
2011-03-31 00:19:25 +00:00
m_old_value_valid = false ;
}
else
{
m_old_value_valid = true ;
m_old_value_str . swap ( m_value_str ) ;
2012-03-19 22:58:49 +00:00
ClearUserVisibleData ( eClearUserVisibleDataItemsValue ) ;
2011-03-31 00:19:25 +00:00
}
2010-06-08 16:52:24 +00:00
2011-07-15 02:26:42 +00:00
ClearUserVisibleData ( ) ;
2012-03-09 04:23:44 +00:00
if ( IsInScope ( ) )
2011-03-31 00:19:25 +00:00
{
2012-03-09 04:23:44 +00:00
const bool value_was_valid = GetValueIsValid ( ) ;
SetValueDidChange ( false ) ;
m_error . Clear ( ) ;
// Call the pure virtual function to update the value
bool success = UpdateValue ( ) ;
SetValueIsValid ( success ) ;
if ( first_update )
SetValueDidChange ( false ) ;
else if ( ! m_value_did_change & & success = = false )
{
// The value wasn't gotten successfully, so we mark this
// as changed if the value used to be valid and now isn't
SetValueDidChange ( value_was_valid ) ;
}
}
else
{
m_error . SetErrorString ( " out of scope " ) ;
2010-06-08 16:52:24 +00:00
}
}
return m_error . Success ( ) ;
}
2011-09-06 19:20:51 +00:00
bool
2011-09-02 01:15:17 +00:00
ValueObject : : UpdateFormatsIfNeeded ( DynamicValueType use_dynamic )
2011-06-29 22:27:15 +00:00
{
2011-07-29 19:53:35 +00:00
LogSP log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_TYPES ) ) ;
if ( log )
2012-10-17 22:23:56 +00:00
log - > Printf ( " [%s %p] checking for FormatManager revisions. ValueObject rev: %d - Global rev: %d " ,
2011-07-29 19:53:35 +00:00
GetName ( ) . GetCString ( ) ,
2012-10-17 22:23:56 +00:00
this ,
2011-06-29 22:27:15 +00:00
m_last_format_mgr_revision ,
2011-08-18 16:38:26 +00:00
DataVisualization : : GetCurrentRevision ( ) ) ;
2011-09-06 19:20:51 +00:00
bool any_change = false ;
2011-08-18 16:38:26 +00:00
if ( ( m_last_format_mgr_revision ! = DataVisualization : : GetCurrentRevision ( ) ) | |
2011-08-02 17:27:39 +00:00
m_last_format_mgr_dynamic ! = use_dynamic )
2011-06-29 22:27:15 +00:00
{
2011-09-09 23:33:14 +00:00
SetValueFormat ( DataVisualization : : ValueFormats : : GetFormat ( * this , eNoDynamicValues ) ) ;
SetSummaryFormat ( DataVisualization : : GetSummaryFormat ( * this , use_dynamic ) ) ;
2012-05-16 00:38:08 +00:00
# ifndef LLDB_DISABLE_PYTHON
2011-09-09 23:33:14 +00:00
SetSyntheticChildren ( DataVisualization : : GetSyntheticChildren ( * this , use_dynamic ) ) ;
2012-05-16 00:38:08 +00:00
# endif
2011-07-19 02:34:21 +00:00
2011-08-18 16:38:26 +00:00
m_last_format_mgr_revision = DataVisualization : : GetCurrentRevision ( ) ;
2011-08-02 17:27:39 +00:00
m_last_format_mgr_dynamic = use_dynamic ;
2011-09-06 22:59:55 +00:00
any_change = true ;
2011-06-29 22:27:15 +00:00
}
2011-09-06 19:20:51 +00:00
return any_change ;
2011-06-29 22:27:15 +00:00
}
2011-08-12 23:34:31 +00:00
void
ValueObject : : SetNeedsUpdate ( )
{
m_update_point . SetNeedsUpdate ( ) ;
// We have to clear the value string here so ConstResult children will notice if their values are
// changed by hand (i.e. with SetValueAsCString).
2012-03-19 22:58:49 +00:00
ClearUserVisibleData ( eClearUserVisibleDataItemsValue ) ;
2011-08-12 23:34:31 +00:00
}
2012-10-17 19:03:34 +00:00
void
2012-10-22 18:18:36 +00:00
ValueObject : : ClearDynamicTypeInformation ( )
2012-10-17 19:03:34 +00:00
{
m_did_calculate_complete_objc_class_type = false ;
2012-10-22 18:18:36 +00:00
m_last_format_mgr_revision = 0 ;
2012-10-17 19:03:34 +00:00
m_override_type = ClangASTType ( ) ;
2012-10-22 18:18:36 +00:00
SetValueFormat ( lldb : : TypeFormatImplSP ( ) ) ;
SetSummaryFormat ( lldb : : TypeSummaryImplSP ( ) ) ;
SetSyntheticChildren ( lldb : : SyntheticChildrenSP ( ) ) ;
2012-10-17 19:03:34 +00:00
}
2012-02-22 23:57:45 +00:00
ClangASTType
ValueObject : : MaybeCalculateCompleteType ( )
{
ClangASTType ret ( GetClangASTImpl ( ) , GetClangTypeImpl ( ) ) ;
2012-03-30 02:04:38 +00:00
2012-02-22 23:57:45 +00:00
if ( m_did_calculate_complete_objc_class_type )
{
if ( m_override_type . IsValid ( ) )
return m_override_type ;
else
return ret ;
}
clang_type_t ast_type ( GetClangTypeImpl ( ) ) ;
clang_type_t class_type ;
bool is_pointer_type ;
if ( ClangASTContext : : IsObjCObjectPointerType ( ast_type , & class_type ) )
{
is_pointer_type = true ;
}
else if ( ClangASTContext : : IsObjCClassType ( ast_type ) )
{
is_pointer_type = false ;
class_type = ast_type ;
}
else
{
return ret ;
}
m_did_calculate_complete_objc_class_type = true ;
if ( ! class_type )
return ret ;
std : : string class_name ;
if ( ! ClangASTContext : : GetObjCClassName ( class_type , class_name ) )
return ret ;
ProcessSP process_sp ( GetUpdatePoint ( ) . GetExecutionContextRef ( ) . GetProcessSP ( ) ) ;
if ( ! process_sp )
return ret ;
ObjCLanguageRuntime * objc_language_runtime ( process_sp - > GetObjCLanguageRuntime ( ) ) ;
if ( ! objc_language_runtime )
return ret ;
ConstString class_name_cs ( class_name . c_str ( ) ) ;
TypeSP complete_objc_class_type_sp = objc_language_runtime - > LookupInCompleteClassCache ( class_name_cs ) ;
if ( ! complete_objc_class_type_sp )
return ret ;
ClangASTType complete_class ( complete_objc_class_type_sp - > GetClangAST ( ) ,
complete_objc_class_type_sp - > GetClangFullType ( ) ) ;
if ( ! ClangASTContext : : GetCompleteType ( complete_class . GetASTContext ( ) ,
complete_class . GetOpaqueQualType ( ) ) )
return ret ;
if ( is_pointer_type )
{
clang_type_t pointer_type = ClangASTContext : : CreatePointerType ( complete_class . GetASTContext ( ) ,
complete_class . GetOpaqueQualType ( ) ) ;
m_override_type = ClangASTType ( complete_class . GetASTContext ( ) ,
pointer_type ) ;
}
else
{
m_override_type = complete_class ;
}
2012-03-30 02:04:38 +00:00
if ( m_override_type . IsValid ( ) )
return m_override_type ;
else
return ret ;
2012-02-22 23:57:45 +00:00
}
clang : : ASTContext *
ValueObject : : GetClangAST ( )
{
ClangASTType type = MaybeCalculateCompleteType ( ) ;
return type . GetASTContext ( ) ;
}
lldb : : clang_type_t
ValueObject : : GetClangType ( )
{
ClangASTType type = MaybeCalculateCompleteType ( ) ;
return type . GetOpaqueQualType ( ) ;
}
2010-06-08 16:52:24 +00:00
DataExtractor &
ValueObject : : GetDataExtractor ( )
{
2011-08-02 17:27:39 +00:00
UpdateValueIfNeeded ( false ) ;
2010-06-08 16:52:24 +00:00
return m_data ;
}
const Error &
2011-07-06 16:49:27 +00:00
ValueObject : : GetError ( )
2010-06-08 16:52:24 +00:00
{
2011-08-02 17:27:39 +00:00
UpdateValueIfNeeded ( false ) ;
2010-06-08 16:52:24 +00:00
return m_error ;
}
const ConstString &
ValueObject : : GetName ( ) const
{
return m_name ;
}
const char *
2011-03-31 00:19:25 +00:00
ValueObject : : GetLocationAsCString ( )
2010-06-08 16:52:24 +00:00
{
2011-08-02 17:27:39 +00:00
if ( UpdateValueIfNeeded ( false ) )
2010-06-08 16:52:24 +00:00
{
if ( m_location_str . empty ( ) )
{
StreamString sstr ;
switch ( m_value . GetValueType ( ) )
{
case Value : : eValueTypeScalar :
2012-10-30 18:18:43 +00:00
case Value : : eValueTypeVector :
2010-11-13 03:52:47 +00:00
if ( m_value . GetContextType ( ) = = Value : : eContextTypeRegisterInfo )
2010-06-08 16:52:24 +00:00
{
RegisterInfo * reg_info = m_value . GetRegisterInfo ( ) ;
if ( reg_info )
{
if ( reg_info - > name )
m_location_str = reg_info - > name ;
else if ( reg_info - > alt_name )
m_location_str = reg_info - > alt_name ;
2012-10-30 18:18:43 +00:00
m_location_str = ( reg_info - > encoding = = lldb : : eEncodingVector ) ? " vector " : " scalar " ;
2010-06-08 16:52:24 +00:00
}
}
break ;
case Value : : eValueTypeLoadAddress :
case Value : : eValueTypeFileAddress :
case Value : : eValueTypeHostAddress :
{
uint32_t addr_nibble_size = m_data . GetAddressByteSize ( ) * 2 ;
sstr . Printf ( " 0x%*.*llx " , addr_nibble_size , addr_nibble_size , m_value . GetScalar ( ) . ULongLong ( LLDB_INVALID_ADDRESS ) ) ;
m_location_str . swap ( sstr . GetString ( ) ) ;
}
break ;
}
}
}
return m_location_str . c_str ( ) ;
}
Value &
ValueObject : : GetValue ( )
{
return m_value ;
}
const Value &
ValueObject : : GetValue ( ) const
{
return m_value ;
}
2010-11-04 01:54:29 +00:00
bool
2011-03-31 00:19:25 +00:00
ValueObject : : ResolveValue ( Scalar & scalar )
2010-11-04 01:54:29 +00:00
{
2011-08-04 01:41:02 +00:00
if ( UpdateValueIfNeeded ( false ) ) // make sure that you are up to date before returning anything
{
2012-02-17 07:49:44 +00:00
ExecutionContext exe_ctx ( GetExecutionContextRef ( ) ) ;
2011-08-12 23:34:31 +00:00
Value tmp_value ( m_value ) ;
scalar = tmp_value . ResolveValue ( & exe_ctx , GetClangAST ( ) ) ;
2011-12-29 01:26:56 +00:00
if ( scalar . IsValid ( ) )
{
const uint32_t bitfield_bit_size = GetBitfieldBitSize ( ) ;
if ( bitfield_bit_size )
return scalar . ExtractBitfield ( bitfield_bit_size , GetBitfieldBitOffset ( ) ) ;
return true ;
}
2011-08-04 01:41:02 +00:00
}
2011-12-29 01:26:56 +00:00
return false ;
2010-11-04 01:54:29 +00:00
}
2010-06-08 16:52:24 +00:00
bool
2010-09-02 02:59:18 +00:00
ValueObject : : GetValueIsValid ( ) const
2010-06-08 16:52:24 +00:00
{
2010-09-02 02:59:18 +00:00
return m_value_is_valid ;
2010-06-08 16:52:24 +00:00
}
void
ValueObject : : SetValueIsValid ( bool b )
{
2010-09-02 02:59:18 +00:00
m_value_is_valid = b ;
2010-06-08 16:52:24 +00:00
}
bool
2011-03-31 00:19:25 +00:00
ValueObject : : GetValueDidChange ( )
2010-06-08 16:52:24 +00:00
{
2011-03-31 00:19:25 +00:00
GetValueAsCString ( ) ;
2010-09-02 02:59:18 +00:00
return m_value_did_change ;
2010-06-08 16:52:24 +00:00
}
void
ValueObject : : SetValueDidChange ( bool value_changed )
{
2010-09-02 02:59:18 +00:00
m_value_did_change = value_changed ;
2010-06-08 16:52:24 +00:00
}
ValueObjectSP
ValueObject : : GetChildAtIndex ( uint32_t idx , bool can_create )
{
ValueObjectSP child_sp ;
2011-06-29 22:09:02 +00:00
// We may need to update our value if we are dynamic
if ( IsPossibleDynamicType ( ) )
2011-08-02 17:27:39 +00:00
UpdateValueIfNeeded ( false ) ;
2011-06-29 22:09:02 +00:00
if ( idx < GetNumChildren ( ) )
2010-06-08 16:52:24 +00:00
{
2011-06-29 22:09:02 +00:00
// Check if we have already made the child value object?
2012-03-09 03:09:58 +00:00
if ( can_create & & ! m_children . HasChildAtIndex ( idx ) )
2010-06-08 16:52:24 +00:00
{
2011-06-29 22:09:02 +00:00
// No we haven't created the child at this index, so lets have our
// subclass do it and cache the result for quick future access.
2012-03-09 03:09:58 +00:00
m_children . SetChildAtIndex ( idx , CreateChildAtIndex ( idx , false , 0 ) ) ;
2011-04-16 00:01:13 +00:00
}
2011-06-29 22:09:02 +00:00
2012-03-09 03:09:58 +00:00
ValueObject * child = m_children . GetChildAtIndex ( idx ) ;
if ( child ! = NULL )
return child - > GetSP ( ) ;
2010-06-08 16:52:24 +00:00
}
return child_sp ;
}
uint32_t
ValueObject : : GetIndexOfChildWithName ( const ConstString & name )
{
bool omit_empty_base_classes = true ;
return ClangASTContext : : GetIndexOfChildWithName ( GetClangAST ( ) ,
2010-09-29 01:12:09 +00:00
GetClangType ( ) ,
2010-12-14 02:59:59 +00:00
name . GetCString ( ) ,
2010-06-08 16:52:24 +00:00
omit_empty_base_classes ) ;
}
ValueObjectSP
ValueObject : : GetChildMemberWithName ( const ConstString & name , bool can_create )
{
2011-01-08 20:28:42 +00:00
// when getting a child by name, it could be buried inside some base
2010-06-08 16:52:24 +00:00
// classes (which really aren't part of the expression path), so we
// need a vector of indexes that can get us down to the correct child
ValueObjectSP child_sp ;
2011-04-16 00:01:13 +00:00
2011-06-29 22:09:02 +00:00
// We may need to update our value if we are dynamic
if ( IsPossibleDynamicType ( ) )
2011-08-02 17:27:39 +00:00
UpdateValueIfNeeded ( false ) ;
2011-06-29 22:09:02 +00:00
std : : vector < uint32_t > child_indexes ;
clang : : ASTContext * clang_ast = GetClangAST ( ) ;
void * clang_type = GetClangType ( ) ;
bool omit_empty_base_classes = true ;
const size_t num_child_indexes = ClangASTContext : : GetIndexOfChildMemberWithName ( clang_ast ,
clang_type ,
name . GetCString ( ) ,
omit_empty_base_classes ,
child_indexes ) ;
if ( num_child_indexes > 0 )
2010-06-08 16:52:24 +00:00
{
2011-06-29 22:09:02 +00:00
std : : vector < uint32_t > : : const_iterator pos = child_indexes . begin ( ) ;
std : : vector < uint32_t > : : const_iterator end = child_indexes . end ( ) ;
child_sp = GetChildAtIndex ( * pos , can_create ) ;
for ( + + pos ; pos ! = end ; + + pos )
2010-06-08 16:52:24 +00:00
{
2011-06-29 22:09:02 +00:00
if ( child_sp )
2011-04-16 00:01:13 +00:00
{
2011-06-29 22:09:02 +00:00
ValueObjectSP new_child_sp ( child_sp - > GetChildAtIndex ( * pos , can_create ) ) ;
child_sp = new_child_sp ;
2011-04-16 00:01:13 +00:00
}
2011-06-29 22:09:02 +00:00
else
{
child_sp . reset ( ) ;
}
2010-06-08 16:52:24 +00:00
}
}
return child_sp ;
}
uint32_t
ValueObject : : GetNumChildren ( )
{
2012-03-27 02:35:13 +00:00
UpdateValueIfNeeded ( ) ;
2010-09-02 02:59:18 +00:00
if ( ! m_children_count_valid )
2010-06-08 16:52:24 +00:00
{
SetNumChildren ( CalculateNumChildren ( ) ) ;
}
2012-03-09 03:09:58 +00:00
return m_children . GetChildrenCount ( ) ;
2010-06-08 16:52:24 +00:00
}
2012-10-23 01:50:10 +00:00
bool
ValueObject : : MightHaveChildren ( )
{
2012-10-23 02:07:54 +00:00
bool has_children = false ;
2012-10-23 01:50:10 +00:00
clang_type_t clang_type = GetClangType ( ) ;
if ( clang_type )
{
const uint32_t type_info = ClangASTContext : : GetTypeInfo ( clang_type ,
GetClangAST ( ) ,
NULL ) ;
if ( type_info & ( ClangASTContext : : eTypeHasChildren |
ClangASTContext : : eTypeIsPointer |
ClangASTContext : : eTypeIsReference ) )
has_children = true ;
}
else
{
has_children = GetNumChildren ( ) > 0 ;
}
return has_children ;
}
// Should only be called by ValueObject::GetNumChildren()
2010-06-08 16:52:24 +00:00
void
ValueObject : : SetNumChildren ( uint32_t num_children )
{
2010-09-02 02:59:18 +00:00
m_children_count_valid = true ;
2012-03-09 03:09:58 +00:00
m_children . SetChildrenCount ( num_children ) ;
2010-06-08 16:52:24 +00:00
}
void
ValueObject : : SetName ( const ConstString & name )
{
m_name = name ;
}
2011-04-22 23:53:53 +00:00
ValueObject *
2010-06-08 16:52:24 +00:00
ValueObject : : CreateChildAtIndex ( uint32_t idx , bool synthetic_array_member , int32_t synthetic_index )
{
2011-05-07 00:10:58 +00:00
ValueObject * valobj = NULL ;
2011-04-16 00:01:13 +00:00
2011-06-29 22:09:02 +00:00
bool omit_empty_base_classes = true ;
2011-07-09 20:12:33 +00:00
bool ignore_array_bounds = synthetic_array_member ;
2011-06-29 22:09:02 +00:00
std : : string child_name_str ;
uint32_t child_byte_size = 0 ;
int32_t child_byte_offset = 0 ;
uint32_t child_bitfield_bit_size = 0 ;
uint32_t child_bitfield_bit_offset = 0 ;
bool child_is_base_class = false ;
bool child_is_deref_of_parent = false ;
const bool transparent_pointers = synthetic_array_member = = false ;
clang : : ASTContext * clang_ast = GetClangAST ( ) ;
clang_type_t clang_type = GetClangType ( ) ;
clang_type_t child_clang_type ;
2012-02-17 07:49:44 +00:00
ExecutionContext exe_ctx ( GetExecutionContextRef ( ) ) ;
2011-06-29 22:09:02 +00:00
child_clang_type = ClangASTContext : : GetChildClangTypeAtIndex ( & exe_ctx ,
clang_ast ,
GetName ( ) . GetCString ( ) ,
clang_type ,
idx ,
transparent_pointers ,
omit_empty_base_classes ,
2011-07-09 20:12:33 +00:00
ignore_array_bounds ,
2011-06-29 22:09:02 +00:00
child_name_str ,
child_byte_size ,
child_byte_offset ,
child_bitfield_bit_size ,
child_bitfield_bit_offset ,
child_is_base_class ,
child_is_deref_of_parent ) ;
2012-12-06 02:33:54 +00:00
if ( child_clang_type )
2010-06-08 16:52:24 +00:00
{
2011-06-29 22:09:02 +00:00
if ( synthetic_index )
child_byte_offset + = child_byte_size * synthetic_index ;
2010-06-08 16:52:24 +00:00
2011-06-29 22:09:02 +00:00
ConstString child_name ;
if ( ! child_name_str . empty ( ) )
child_name . SetCString ( child_name_str . c_str ( ) ) ;
2010-06-08 16:52:24 +00:00
2011-06-29 22:09:02 +00:00
valobj = new ValueObjectChild ( * this ,
clang_ast ,
child_clang_type ,
child_name ,
child_byte_size ,
child_byte_offset ,
child_bitfield_bit_size ,
child_bitfield_bit_offset ,
child_is_base_class ,
2011-09-06 19:20:51 +00:00
child_is_deref_of_parent ,
eAddressTypeInvalid ) ;
//if (valobj)
// valobj->SetAddressTypeOfChildren(eAddressTypeInvalid);
}
2011-04-16 00:01:13 +00:00
2011-04-22 23:53:53 +00:00
return valobj ;
2010-06-08 16:52:24 +00:00
}
2012-03-01 04:24:26 +00:00
bool
ValueObject : : GetSummaryAsCString ( TypeSummaryImpl * summary_ptr ,
std : : string & destination )
2010-06-08 16:52:24 +00:00
{
2012-03-01 04:24:26 +00:00
destination . clear ( ) ;
// ideally we would like to bail out if passing NULL, but if we do so
// we end up not providing the summary for function pointers anymore
if ( /*summary_ptr == NULL ||*/ m_is_getting_summary )
return false ;
2012-01-07 20:58:07 +00:00
m_is_getting_summary = true ;
2012-04-04 17:34:10 +00:00
// this is a hot path in code and we prefer to avoid setting this string all too often also clearing out other
// information that we might care to see in a crash log. might be useful in very specific situations though.
/*Host::SetCrashDescriptionWithFormat("Trying to fetch a summary for %s %s. Summary provider's description is %s",
GetTypeName().GetCString(),
GetName().GetCString(),
summary_ptr->GetDescription().c_str());*/
2012-03-01 04:24:26 +00:00
if ( UpdateValueIfNeeded ( false ) )
{
if ( summary_ptr )
2010-06-08 16:52:24 +00:00
{
2012-03-19 22:58:49 +00:00
if ( HasSyntheticValue ( ) )
m_synthetic_value - > UpdateValueIfNeeded ( ) ; // the summary might depend on the synthetic children being up-to-date (e.g. ${svar%#})
summary_ptr - > FormatObject ( this , destination ) ;
2012-03-01 04:24:26 +00:00
}
else
{
clang_type_t clang_type = GetClangType ( ) ;
// Do some default printout for function pointers
if ( clang_type )
2011-06-29 22:27:15 +00:00
{
2012-03-01 04:24:26 +00:00
StreamString sstr ;
clang_type_t elem_or_pointee_clang_type ;
const Flags type_flags ( ClangASTContext : : GetTypeInfo ( clang_type ,
GetClangAST ( ) ,
& elem_or_pointee_clang_type ) ) ;
if ( ClangASTContext : : IsFunctionPointerType ( clang_type ) )
2010-06-08 16:52:24 +00:00
{
2012-03-01 04:24:26 +00:00
AddressType func_ptr_address_type = eAddressTypeInvalid ;
addr_t func_ptr_address = GetPointerValue ( & func_ptr_address_type ) ;
if ( func_ptr_address ! = 0 & & func_ptr_address ! = LLDB_INVALID_ADDRESS )
2011-07-15 02:26:42 +00:00
{
2012-03-01 04:24:26 +00:00
switch ( func_ptr_address_type )
2011-03-31 00:19:25 +00:00
{
2012-02-17 07:49:44 +00:00
case eAddressTypeInvalid :
case eAddressTypeFile :
break ;
2012-03-01 04:24:26 +00:00
2012-02-17 07:49:44 +00:00
case eAddressTypeLoad :
2012-03-01 04:24:26 +00:00
{
ExecutionContext exe_ctx ( GetExecutionContextRef ( ) ) ;
Address so_addr ;
Target * target = exe_ctx . GetTargetPtr ( ) ;
if ( target & & target - > GetSectionLoadList ( ) . IsEmpty ( ) = = false )
2012-02-17 07:49:44 +00:00
{
2012-03-01 04:24:26 +00:00
if ( target - > GetSectionLoadList ( ) . ResolveLoadAddress ( func_ptr_address , so_addr ) )
2011-07-15 02:26:42 +00:00
{
2012-03-01 04:24:26 +00:00
so_addr . Dump ( & sstr ,
exe_ctx . GetBestExecutionContextScope ( ) ,
Address : : DumpStyleResolvedDescription ,
Address : : DumpStyleSectionNameOffset ) ;
2011-07-15 02:26:42 +00:00
}
}
2012-03-01 04:24:26 +00:00
}
2012-02-17 07:49:44 +00:00
break ;
2012-03-01 04:24:26 +00:00
2012-02-17 07:49:44 +00:00
case eAddressTypeHost :
break ;
2011-03-31 00:19:25 +00:00
}
2010-06-08 16:52:24 +00:00
}
2012-03-01 04:24:26 +00:00
if ( sstr . GetSize ( ) > 0 )
{
destination . assign ( 1 , ' ( ' ) ;
destination . append ( sstr . GetData ( ) , sstr . GetSize ( ) ) ;
destination . append ( 1 , ' ) ' ) ;
}
2010-06-08 16:52:24 +00:00
}
}
}
}
2012-01-07 20:58:07 +00:00
m_is_getting_summary = false ;
2012-03-01 04:24:26 +00:00
return ! destination . empty ( ) ;
}
const char *
ValueObject : : GetSummaryAsCString ( )
{
if ( UpdateValueIfNeeded ( true ) & & m_summary_str . empty ( ) )
{
GetSummaryAsCString ( GetSummaryFormat ( ) . get ( ) ,
m_summary_str ) ;
}
2010-06-08 16:52:24 +00:00
if ( m_summary_str . empty ( ) )
return NULL ;
return m_summary_str . c_str ( ) ;
}
2011-07-12 00:18:11 +00:00
bool
ValueObject : : IsCStringContainer ( bool check_pointer )
{
clang_type_t elem_or_pointee_clang_type ;
const Flags type_flags ( ClangASTContext : : GetTypeInfo ( GetClangType ( ) ,
GetClangAST ( ) ,
& elem_or_pointee_clang_type ) ) ;
bool is_char_arr_ptr ( type_flags . AnySet ( ClangASTContext : : eTypeIsArray | ClangASTContext : : eTypeIsPointer ) & &
ClangASTContext : : IsCharType ( elem_or_pointee_clang_type ) ) ;
if ( ! is_char_arr_ptr )
return false ;
if ( ! check_pointer )
return true ;
if ( type_flags . Test ( ClangASTContext : : eTypeIsArray ) )
return true ;
2011-09-02 01:15:17 +00:00
addr_t cstr_address = LLDB_INVALID_ADDRESS ;
2011-07-12 00:18:11 +00:00
AddressType cstr_address_type = eAddressTypeInvalid ;
2011-09-06 19:20:51 +00:00
cstr_address = GetAddressOf ( true , & cstr_address_type ) ;
2011-07-12 00:18:11 +00:00
return ( cstr_address ! = LLDB_INVALID_ADDRESS ) ;
}
2011-09-06 19:20:51 +00:00
size_t
ValueObject : : GetPointeeData ( DataExtractor & data ,
uint32_t item_idx ,
uint32_t item_count )
{
if ( ! IsPointerType ( ) & & ! IsArrayType ( ) )
return 0 ;
if ( item_count = = 0 )
return 0 ;
uint32_t stride = 0 ;
ClangASTType type ( GetClangAST ( ) ,
GetClangType ( ) ) ;
const uint64_t item_type_size = ( IsPointerType ( ) ? ClangASTType : : GetTypeByteSize ( GetClangAST ( ) , type . GetPointeeType ( ) ) :
ClangASTType : : GetTypeByteSize ( GetClangAST ( ) , type . GetArrayElementType ( stride ) ) ) ;
const uint64_t bytes = item_count * item_type_size ;
const uint64_t offset = item_idx * item_type_size ;
if ( item_idx = = 0 & & item_count = = 1 ) // simply a deref
{
if ( IsPointerType ( ) )
{
Error error ;
ValueObjectSP pointee_sp = Dereference ( error ) ;
if ( error . Fail ( ) | | pointee_sp . get ( ) = = NULL )
return 0 ;
return pointee_sp - > GetDataExtractor ( ) . Copy ( data ) ;
}
else
{
ValueObjectSP child_sp = GetChildAtIndex ( 0 , true ) ;
if ( child_sp . get ( ) = = NULL )
return 0 ;
return child_sp - > GetDataExtractor ( ) . Copy ( data ) ;
}
return true ;
}
else /* (items > 1) */
{
Error error ;
lldb_private : : DataBufferHeap * heap_buf_ptr = NULL ;
lldb : : DataBufferSP data_sp ( heap_buf_ptr = new lldb_private : : DataBufferHeap ( ) ) ;
AddressType addr_type ;
lldb : : addr_t addr = IsPointerType ( ) ? GetPointerValue ( & addr_type ) : GetAddressOf ( true , & addr_type ) ;
switch ( addr_type )
{
case eAddressTypeFile :
{
2012-02-24 01:59:29 +00:00
ModuleSP module_sp ( GetModule ( ) ) ;
if ( module_sp )
2011-09-06 19:20:51 +00:00
{
2012-08-07 01:49:34 +00:00
addr = addr + offset ;
2011-09-06 19:20:51 +00:00
Address so_addr ;
2012-02-24 01:59:29 +00:00
module_sp - > ResolveFileAddress ( addr , so_addr ) ;
2012-02-17 07:49:44 +00:00
ExecutionContext exe_ctx ( GetExecutionContextRef ( ) ) ;
Target * target = exe_ctx . GetTargetPtr ( ) ;
if ( target )
2011-09-06 19:20:51 +00:00
{
2012-02-17 07:49:44 +00:00
heap_buf_ptr - > SetByteSize ( bytes ) ;
size_t bytes_read = target - > ReadMemory ( so_addr , false , heap_buf_ptr - > GetBytes ( ) , bytes , error ) ;
if ( error . Success ( ) )
2011-09-06 19:20:51 +00:00
{
2012-02-17 07:49:44 +00:00
data . SetData ( data_sp ) ;
return bytes_read ;
2011-09-06 19:20:51 +00:00
}
}
}
}
break ;
case eAddressTypeLoad :
{
2012-02-17 07:49:44 +00:00
ExecutionContext exe_ctx ( GetExecutionContextRef ( ) ) ;
Process * process = exe_ctx . GetProcessPtr ( ) ;
2011-09-06 19:20:51 +00:00
if ( process )
{
heap_buf_ptr - > SetByteSize ( bytes ) ;
size_t bytes_read = process - > ReadMemory ( addr + offset , heap_buf_ptr - > GetBytes ( ) , bytes , error ) ;
if ( error . Success ( ) )
{
data . SetData ( data_sp ) ;
return bytes_read ;
}
}
}
break ;
case eAddressTypeHost :
{
heap_buf_ptr - > CopyData ( ( uint8_t * ) ( addr + offset ) , bytes ) ;
data . SetData ( data_sp ) ;
return bytes ;
}
break ;
case eAddressTypeInvalid :
break ;
}
}
return 0 ;
}
size_t
ValueObject : : GetData ( DataExtractor & data )
{
UpdateValueIfNeeded ( false ) ;
2012-02-17 07:49:44 +00:00
ExecutionContext exe_ctx ( GetExecutionContextRef ( ) ) ;
2012-02-24 01:59:29 +00:00
Error error = m_value . GetValueAsData ( & exe_ctx , GetClangAST ( ) , data , 0 , GetModule ( ) . get ( ) ) ;
2011-09-06 19:20:51 +00:00
if ( error . Fail ( ) )
return 0 ;
data . SetAddressByteSize ( m_data . GetAddressByteSize ( ) ) ;
data . SetByteOrder ( m_data . GetByteOrder ( ) ) ;
return data . GetByteSize ( ) ;
}
// will compute strlen(str), but without consuming more than
// maxlen bytes out of str (this serves the purpose of reading
// chunks of a string without having to worry about
// missing NULL terminators in the chunk)
// of course, if strlen(str) > maxlen, the function will return
// maxlen_value (which should be != maxlen, because that allows you
// to know whether strlen(str) == maxlen or strlen(str) > maxlen)
static uint32_t
strlen_or_inf ( const char * str ,
uint32_t maxlen ,
uint32_t maxlen_value )
{
uint32_t len = 0 ;
2011-10-05 22:19:51 +00:00
if ( str )
2011-09-06 19:20:51 +00:00
{
2011-10-05 22:19:51 +00:00
while ( * str )
{
len + + ; str + + ;
if ( len > maxlen )
return maxlen_value ;
}
2011-09-06 19:20:51 +00:00
}
return len ;
}
2011-07-12 00:18:11 +00:00
void
2012-02-17 07:49:44 +00:00
ValueObject : : ReadPointedString ( Stream & s ,
Error & error ,
uint32_t max_length ,
bool honor_array ,
Format item_format )
2011-07-12 00:18:11 +00:00
{
2012-02-17 07:49:44 +00:00
ExecutionContext exe_ctx ( GetExecutionContextRef ( ) ) ;
Target * target = exe_ctx . GetTargetPtr ( ) ;
if ( target & & max_length = = 0 )
max_length = target - > GetMaximumSizeOfStringSummary ( ) ;
2011-07-12 00:18:11 +00:00
clang_type_t clang_type = GetClangType ( ) ;
clang_type_t elem_or_pointee_clang_type ;
const Flags type_flags ( ClangASTContext : : GetTypeInfo ( clang_type ,
GetClangAST ( ) ,
& elem_or_pointee_clang_type ) ) ;
if ( type_flags . AnySet ( ClangASTContext : : eTypeIsArray | ClangASTContext : : eTypeIsPointer ) & &
ClangASTContext : : IsCharType ( elem_or_pointee_clang_type ) )
{
2012-02-17 07:49:44 +00:00
if ( target = = NULL )
{
s < < " <no target to read from> " ;
}
else
{
addr_t cstr_address = LLDB_INVALID_ADDRESS ;
AddressType cstr_address_type = eAddressTypeInvalid ;
size_t cstr_len = 0 ;
bool capped_data = false ;
if ( type_flags . Test ( ClangASTContext : : eTypeIsArray ) )
2011-07-12 00:18:11 +00:00
{
2012-02-17 07:49:44 +00:00
// We have an array
cstr_len = ClangASTContext : : GetArraySize ( clang_type ) ;
if ( cstr_len > max_length )
2011-07-29 19:53:35 +00:00
{
2012-02-17 07:49:44 +00:00
capped_data = true ;
cstr_len = max_length ;
}
cstr_address = GetAddressOf ( true , & cstr_address_type ) ;
}
else
{
// We have a pointer
cstr_address = GetPointerValue ( & cstr_address_type ) ;
}
if ( cstr_address ! = 0 & & cstr_address ! = LLDB_INVALID_ADDRESS )
{
2012-02-24 01:59:29 +00:00
Address cstr_so_addr ( cstr_address ) ;
2012-02-17 07:49:44 +00:00
DataExtractor data ;
size_t bytes_read = 0 ;
if ( cstr_len > 0 & & honor_array )
{
// I am using GetPointeeData() here to abstract the fact that some ValueObjects are actually frozen pointers in the host
// but the pointed-to data lives in the debuggee, and GetPointeeData() automatically takes care of this
GetPointeeData ( data , 0 , cstr_len ) ;
if ( ( bytes_read = data . GetByteSize ( ) ) > 0 )
{
s < < ' " ' ;
data . Dump ( & s ,
0 , // Start offset in "data"
item_format ,
1 , // Size of item (1 byte for a char!)
bytes_read , // How many bytes to print?
UINT32_MAX , // num per line
LLDB_INVALID_ADDRESS , // base address
0 , // bitfield bit size
0 ) ; // bitfield bit offset
if ( capped_data )
s < < " ... " ;
s < < ' " ' ;
}
2011-07-29 19:53:35 +00:00
}
else
2011-07-12 00:18:11 +00:00
{
2012-02-17 07:49:44 +00:00
cstr_len = max_length ;
const size_t k_max_buf_size = 64 ;
size_t offset = 0 ;
2011-07-12 00:18:11 +00:00
2012-02-17 07:49:44 +00:00
int cstr_len_displayed = - 1 ;
bool capped_cstr = false ;
// I am using GetPointeeData() here to abstract the fact that some ValueObjects are actually frozen pointers in the host
// but the pointed-to data lives in the debuggee, and GetPointeeData() automatically takes care of this
while ( ( bytes_read = GetPointeeData ( data , offset , k_max_buf_size ) ) > 0 )
2011-07-12 00:18:11 +00:00
{
2012-02-17 07:49:44 +00:00
const char * cstr = data . PeekCStr ( 0 ) ;
size_t len = strlen_or_inf ( cstr , k_max_buf_size , k_max_buf_size + 1 ) ;
if ( len > k_max_buf_size )
len = k_max_buf_size ;
if ( cstr & & cstr_len_displayed < 0 )
s < < ' " ' ;
if ( cstr_len_displayed < 0 )
cstr_len_displayed = len ;
if ( len = = 0 )
break ;
cstr_len_displayed + = len ;
if ( len > bytes_read )
len = bytes_read ;
if ( len > cstr_len )
len = cstr_len ;
data . Dump ( & s ,
0 , // Start offset in "data"
item_format ,
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 ;
if ( len > = cstr_len )
2011-07-12 00:18:11 +00:00
{
2012-02-17 07:49:44 +00:00
capped_cstr = true ;
break ;
2011-07-12 00:18:11 +00:00
}
2012-02-17 07:49:44 +00:00
cstr_len - = len ;
offset + = len ;
2011-07-12 00:18:11 +00:00
}
2012-02-17 07:49:44 +00:00
if ( cstr_len_displayed > = 0 )
2011-07-12 00:18:11 +00:00
{
2012-02-17 07:49:44 +00:00
s < < ' " ' ;
if ( capped_cstr )
s < < " ... " ;
2011-07-12 00:18:11 +00:00
}
}
}
2012-02-17 07:49:44 +00:00
}
2011-07-12 00:18:11 +00:00
}
else
{
error . SetErrorString ( " impossible to read a string from this object " ) ;
2011-07-29 19:53:35 +00:00
s < < " <not a string object> " ;
2011-07-12 00:18:11 +00:00
}
}
2010-09-10 23:12:17 +00:00
const char *
2011-03-31 00:19:25 +00:00
ValueObject : : GetObjectDescription ( )
2010-09-10 23:12:17 +00:00
{
2011-07-02 00:25:22 +00:00
2011-08-02 23:12:24 +00:00
if ( ! UpdateValueIfNeeded ( true ) )
2010-09-10 23:12:17 +00:00
return NULL ;
2011-07-02 00:25:22 +00:00
if ( ! m_object_desc_str . empty ( ) )
return m_object_desc_str . c_str ( ) ;
2012-02-17 07:49:44 +00:00
ExecutionContext exe_ctx ( GetExecutionContextRef ( ) ) ;
Process * process = exe_ctx . GetProcessPtr ( ) ;
2010-09-28 01:25:32 +00:00
if ( process = = NULL )
2010-09-10 23:12:17 +00:00
return NULL ;
2010-09-28 01:25:32 +00:00
2010-09-10 23:12:17 +00:00
StreamString s ;
2010-09-28 01:25:32 +00:00
2011-09-02 01:15:17 +00:00
LanguageType language = GetObjectRuntimeLanguage ( ) ;
2010-09-28 01:25:32 +00:00
LanguageRuntime * runtime = process - > GetLanguageRuntime ( language ) ;
2010-12-23 02:29:54 +00:00
if ( runtime = = NULL )
{
2011-03-18 00:05:18 +00:00
// Aw, hell, if the things a pointer, or even just an integer, let's try ObjC anyway...
2010-12-23 02:29:54 +00:00
clang_type_t opaque_qual_type = GetClangType ( ) ;
if ( opaque_qual_type ! = NULL )
{
2011-03-18 00:05:18 +00:00
bool is_signed ;
if ( ClangASTContext : : IsIntegerType ( opaque_qual_type , is_signed )
| | ClangASTContext : : IsPointerType ( opaque_qual_type ) )
{
2011-09-02 01:15:17 +00:00
runtime = process - > GetLanguageRuntime ( eLanguageTypeObjC ) ;
2011-03-18 00:05:18 +00:00
}
2010-12-23 02:29:54 +00:00
}
}
2011-03-31 23:01:21 +00:00
if ( runtime & & runtime - > GetObjectDescription ( s , * this ) )
2010-09-10 23:12:17 +00:00
{
m_object_desc_str . append ( s . GetData ( ) ) ;
}
2010-10-23 00:18:49 +00:00
if ( m_object_desc_str . empty ( ) )
return NULL ;
else
return m_object_desc_str . c_str ( ) ;
2010-09-10 23:12:17 +00:00
}
2010-06-08 16:52:24 +00:00
2012-03-01 04:24:26 +00:00
bool
ValueObject : : GetValueAsCString ( lldb : : Format format ,
std : : string & destination )
{
if ( ClangASTContext : : IsAggregateType ( GetClangType ( ) ) = = false & &
UpdateValueIfNeeded ( false ) )
{
const Value : : ContextType context_type = m_value . GetContextType ( ) ;
switch ( context_type )
{
case Value : : eContextTypeClangType :
case Value : : eContextTypeLLDBType :
case Value : : eContextTypeVariable :
{
clang_type_t clang_type = GetClangType ( ) ;
if ( clang_type )
{
StreamString sstr ;
ExecutionContext exe_ctx ( GetExecutionContextRef ( ) ) ;
ClangASTType : : DumpTypeValue ( GetClangAST ( ) , // The clang AST
clang_type , // The clang type to display
& sstr ,
format , // Format to display this type with
m_data , // Data to extract from
0 , // Byte offset into "m_data"
GetByteSize ( ) , // Byte size of item in "m_data"
GetBitfieldBitSize ( ) , // Bitfield bit size
GetBitfieldBitOffset ( ) , // Bitfield bit offset
exe_ctx . GetBestExecutionContextScope ( ) ) ;
// Don't set the m_error to anything here otherwise
// we won't be able to re-format as anything else. The
// code for ClangASTType::DumpTypeValue() should always
// return something, even if that something contains
// an error messsage. "m_error" is used to detect errors
// when reading the valid object, not for formatting errors.
if ( sstr . GetString ( ) . empty ( ) )
destination . clear ( ) ;
else
destination . swap ( sstr . GetString ( ) ) ;
}
}
break ;
case Value : : eContextTypeRegisterInfo :
{
const RegisterInfo * reg_info = m_value . GetRegisterInfo ( ) ;
if ( reg_info )
{
ExecutionContext exe_ctx ( GetExecutionContextRef ( ) ) ;
StreamString reg_sstr ;
m_data . Dump ( & reg_sstr ,
0 ,
format ,
reg_info - > byte_size ,
1 ,
UINT32_MAX ,
LLDB_INVALID_ADDRESS ,
0 ,
0 ,
exe_ctx . GetBestExecutionContextScope ( ) ) ;
destination . swap ( reg_sstr . GetString ( ) ) ;
}
}
break ;
default :
break ;
}
return ! destination . empty ( ) ;
}
else
return false ;
}
2010-06-08 16:52:24 +00:00
const char *
2011-03-31 00:19:25 +00:00
ValueObject : : GetValueAsCString ( )
2010-06-08 16:52:24 +00:00
{
2012-03-01 04:24:26 +00:00
if ( UpdateValueIfNeeded ( true ) & & m_value_str . empty ( ) )
2010-06-08 16:52:24 +00:00
{
2012-03-01 04:24:26 +00:00
lldb : : Format my_format = GetFormat ( ) ;
2012-12-11 02:17:22 +00:00
if ( my_format = = lldb : : eFormatDefault )
2010-06-08 16:52:24 +00:00
{
2012-03-01 04:24:26 +00:00
if ( m_type_format_sp )
my_format = m_type_format_sp - > GetFormat ( ) ;
else
2010-06-08 16:52:24 +00:00
{
2012-03-01 04:24:26 +00:00
if ( m_is_bitfield_for_scalar )
my_format = eFormatUnsigned ;
else
2010-06-08 16:52:24 +00:00
{
2012-03-01 04:24:26 +00:00
if ( m_value . GetContextType ( ) = = Value : : eContextTypeRegisterInfo )
2010-06-08 16:52:24 +00:00
{
const RegisterInfo * reg_info = m_value . GetRegisterInfo ( ) ;
if ( reg_info )
2012-03-01 04:24:26 +00:00
my_format = reg_info - > format ;
}
else
{
clang_type_t clang_type = GetClangType ( ) ;
my_format = ClangASTType : : GetFormat ( clang_type ) ;
2010-06-08 16:52:24 +00:00
}
}
}
}
2012-03-06 23:21:16 +00:00
if ( GetValueAsCString ( my_format , m_value_str ) )
{
if ( ! m_value_did_change & & m_old_value_valid )
{
// The value was gotten successfully, so we consider the
// value as changed if the value string differs
SetValueDidChange ( m_old_value_str ! = m_value_str ) ;
}
}
2010-06-08 16:52:24 +00:00
}
if ( m_value_str . empty ( ) )
return NULL ;
return m_value_str . c_str ( ) ;
}
2011-08-02 17:27:39 +00:00
// if > 8bytes, 0 is returned. this method should mostly be used
// to read address values out of pointers
2011-08-22 02:49:39 +00:00
uint64_t
2012-06-05 19:37:43 +00:00
ValueObject : : GetValueAsUnsigned ( uint64_t fail_value , bool * success )
2011-08-02 17:27:39 +00:00
{
// If our byte size is zero this is an aggregate type that has children
if ( ClangASTContext : : IsAggregateType ( GetClangType ( ) ) = = false )
{
2011-08-22 02:49:39 +00:00
Scalar scalar ;
if ( ResolveValue ( scalar ) )
2012-06-05 19:37:43 +00:00
{
if ( success )
* success = true ;
2012-10-24 20:24:39 +00:00
return scalar . ULongLong ( fail_value ) ;
2012-06-05 19:37:43 +00:00
}
// fallthrough, otherwise...
2011-08-02 17:27:39 +00:00
}
2012-06-05 19:37:43 +00:00
if ( success )
* success = false ;
2011-08-22 02:49:39 +00:00
return fail_value ;
2011-08-02 17:27:39 +00:00
}
2011-08-19 21:13:46 +00:00
// if any more "special cases" are added to ValueObject::DumpPrintableRepresentation() please keep
// this call up to date by returning true for your new special cases. We will eventually move
// to checking this call result before trying to display special cases
bool
2012-03-19 22:58:49 +00:00
ValueObject : : HasSpecialPrintableRepresentation ( ValueObjectRepresentationStyle val_obj_display ,
Format custom_format )
2011-08-19 21:13:46 +00:00
{
clang_type_t elem_or_pointee_type ;
Flags flags ( ClangASTContext : : GetTypeInfo ( GetClangType ( ) , GetClangAST ( ) , & elem_or_pointee_type ) ) ;
if ( flags . AnySet ( ClangASTContext : : eTypeIsArray | ClangASTContext : : eTypeIsPointer )
2012-03-19 22:58:49 +00:00
& & val_obj_display = = ValueObject : : eValueObjectRepresentationStyleValue )
2011-08-19 21:13:46 +00:00
{
if ( IsCStringContainer ( true ) & &
2011-09-02 01:15:17 +00:00
( custom_format = = eFormatCString | |
custom_format = = eFormatCharArray | |
custom_format = = eFormatChar | |
custom_format = = eFormatVectorOfChar ) )
2011-08-19 21:13:46 +00:00
return true ;
if ( flags . Test ( ClangASTContext : : eTypeIsArray ) )
{
2011-09-02 01:15:17 +00:00
if ( ( custom_format = = eFormatBytes ) | |
( custom_format = = eFormatBytesWithASCII ) )
2011-08-19 21:13:46 +00:00
return true ;
2011-09-02 01:15:17 +00:00
if ( ( custom_format = = eFormatVectorOfChar ) | |
( custom_format = = eFormatVectorOfFloat32 ) | |
( custom_format = = eFormatVectorOfFloat64 ) | |
( custom_format = = eFormatVectorOfSInt16 ) | |
( custom_format = = eFormatVectorOfSInt32 ) | |
( custom_format = = eFormatVectorOfSInt64 ) | |
( custom_format = = eFormatVectorOfSInt8 ) | |
( custom_format = = eFormatVectorOfUInt128 ) | |
( custom_format = = eFormatVectorOfUInt16 ) | |
( custom_format = = eFormatVectorOfUInt32 ) | |
( custom_format = = eFormatVectorOfUInt64 ) | |
( custom_format = = eFormatVectorOfUInt8 ) )
2011-08-19 21:13:46 +00:00
return true ;
}
}
return false ;
}
2011-07-06 02:13:41 +00:00
bool
ValueObject : : DumpPrintableRepresentation ( Stream & s ,
ValueObjectRepresentationStyle val_obj_display ,
2011-09-02 01:15:17 +00:00
Format custom_format ,
2012-03-19 22:58:49 +00:00
PrintableRepresentationSpecialCases special )
2011-07-06 02:13:41 +00:00
{
2011-07-12 22:56:10 +00:00
clang_type_t elem_or_pointee_type ;
Flags flags ( ClangASTContext : : GetTypeInfo ( GetClangType ( ) , GetClangAST ( ) , & elem_or_pointee_type ) ) ;
2011-07-12 00:18:11 +00:00
2012-03-19 22:58:49 +00:00
bool allow_special = ( ( special & ePrintableRepresentationSpecialCasesAllow ) = = ePrintableRepresentationSpecialCasesAllow ) ;
bool only_special = ( ( special & ePrintableRepresentationSpecialCasesOnly ) = = ePrintableRepresentationSpecialCasesOnly ) ;
if ( allow_special )
2011-07-12 00:18:11 +00:00
{
2012-03-19 22:58:49 +00:00
if ( flags . AnySet ( ClangASTContext : : eTypeIsArray | ClangASTContext : : eTypeIsPointer )
& & val_obj_display = = ValueObject : : eValueObjectRepresentationStyleValue )
2011-07-12 22:56:10 +00:00
{
2012-03-19 22:58:49 +00:00
// when being asked to get a printable display an array or pointer type directly,
// try to "do the right thing"
if ( IsCStringContainer ( true ) & &
( custom_format = = eFormatCString | |
custom_format = = eFormatCharArray | |
custom_format = = eFormatChar | |
custom_format = = eFormatVectorOfChar ) ) // print char[] & char* directly
2011-07-12 22:56:10 +00:00
{
2012-03-19 22:58:49 +00:00
Error error ;
ReadPointedString ( s ,
error ,
0 ,
( custom_format = = eFormatVectorOfChar ) | |
( custom_format = = eFormatCharArray ) ) ;
return ! error . Fail ( ) ;
2011-07-12 22:56:10 +00:00
}
2012-03-19 22:58:49 +00:00
if ( custom_format = = eFormatEnum )
return false ;
// this only works for arrays, because I have no way to know when
// the pointed memory ends, and no special \0 end of data marker
if ( flags . Test ( ClangASTContext : : eTypeIsArray ) )
2011-07-12 22:56:10 +00:00
{
2012-03-19 22:58:49 +00:00
if ( ( custom_format = = eFormatBytes ) | |
( custom_format = = eFormatBytesWithASCII ) )
2011-07-12 22:56:10 +00:00
{
2012-03-19 22:58:49 +00:00
uint32_t count = GetNumChildren ( ) ;
s < < ' [ ' ;
for ( uint32_t low = 0 ; low < count ; low + + )
2011-07-12 22:56:10 +00:00
{
2012-03-19 22:58:49 +00:00
if ( low )
s < < ' , ' ;
ValueObjectSP child = GetChildAtIndex ( low , true ) ;
if ( ! child . get ( ) )
{
s < < " <invalid child> " ;
continue ;
}
child - > DumpPrintableRepresentation ( s , ValueObject : : eValueObjectRepresentationStyleValue , custom_format ) ;
}
s < < ' ] ' ;
return true ;
}
2011-07-12 22:56:10 +00:00
2012-03-19 22:58:49 +00:00
if ( ( custom_format = = eFormatVectorOfChar ) | |
( custom_format = = eFormatVectorOfFloat32 ) | |
( custom_format = = eFormatVectorOfFloat64 ) | |
( custom_format = = eFormatVectorOfSInt16 ) | |
( custom_format = = eFormatVectorOfSInt32 ) | |
( custom_format = = eFormatVectorOfSInt64 ) | |
( custom_format = = eFormatVectorOfSInt8 ) | |
( custom_format = = eFormatVectorOfUInt128 ) | |
( custom_format = = eFormatVectorOfUInt16 ) | |
( custom_format = = eFormatVectorOfUInt32 ) | |
( custom_format = = eFormatVectorOfUInt64 ) | |
( custom_format = = eFormatVectorOfUInt8 ) ) // arrays of bytes, bytes with ASCII or any vector format should be printed directly
{
uint32_t count = GetNumChildren ( ) ;
Format format = FormatManager : : GetSingleItemFormat ( custom_format ) ;
s < < ' [ ' ;
for ( uint32_t low = 0 ; low < count ; low + + )
{
if ( low )
s < < ' , ' ;
ValueObjectSP child = GetChildAtIndex ( low , true ) ;
if ( ! child . get ( ) )
{
s < < " <invalid child> " ;
continue ;
}
child - > DumpPrintableRepresentation ( s , ValueObject : : eValueObjectRepresentationStyleValue , format ) ;
}
s < < ' ] ' ;
return true ;
}
2011-07-12 22:56:10 +00:00
}
2012-03-19 22:58:49 +00:00
if ( ( custom_format = = eFormatBoolean ) | |
( custom_format = = eFormatBinary ) | |
( custom_format = = eFormatChar ) | |
( custom_format = = eFormatCharPrintable ) | |
( custom_format = = eFormatComplexFloat ) | |
( custom_format = = eFormatDecimal ) | |
( custom_format = = eFormatHex ) | |
2012-08-09 19:33:34 +00:00
( custom_format = = eFormatHexUppercase ) | |
2012-03-19 22:58:49 +00:00
( custom_format = = eFormatFloat ) | |
( custom_format = = eFormatOctal ) | |
( custom_format = = eFormatOSType ) | |
( custom_format = = eFormatUnicode16 ) | |
( custom_format = = eFormatUnicode32 ) | |
( custom_format = = eFormatUnsigned ) | |
( custom_format = = eFormatPointer ) | |
( custom_format = = eFormatComplexInteger ) | |
( custom_format = = eFormatComplex ) | |
( custom_format = = eFormatDefault ) ) // use the [] operator
return false ;
2011-07-12 22:56:10 +00:00
}
2011-07-12 00:18:11 +00:00
}
2011-08-18 16:38:26 +00:00
if ( only_special )
return false ;
2012-03-19 22:58:49 +00:00
bool var_success = false ;
{
const char * return_value ;
std : : string alloc_mem ;
if ( custom_format ! = eFormatInvalid )
SetFormat ( custom_format ) ;
switch ( val_obj_display )
{
case eValueObjectRepresentationStyleValue :
return_value = GetValueAsCString ( ) ;
break ;
case eValueObjectRepresentationStyleSummary :
return_value = GetSummaryAsCString ( ) ;
break ;
case eValueObjectRepresentationStyleLanguageSpecific :
return_value = GetObjectDescription ( ) ;
break ;
case eValueObjectRepresentationStyleLocation :
return_value = GetLocationAsCString ( ) ;
break ;
case eValueObjectRepresentationStyleChildrenCount :
{
alloc_mem . resize ( 512 ) ;
return_value = & alloc_mem [ 0 ] ;
int count = GetNumChildren ( ) ;
snprintf ( ( char * ) return_value , 512 , " %d " , count ) ;
}
break ;
case eValueObjectRepresentationStyleType :
return_value = GetTypeName ( ) . AsCString ( ) ;
break ;
}
if ( ! return_value )
{
if ( val_obj_display = = eValueObjectRepresentationStyleValue )
return_value = GetSummaryAsCString ( ) ;
else if ( val_obj_display = = eValueObjectRepresentationStyleSummary )
{
if ( ClangASTContext : : IsAggregateType ( GetClangType ( ) ) = = true )
{
// this thing has no value, and it seems to have no summary
// some combination of unitialized data and other factors can also
// raise this condition, so let's print a nice generic description
{
alloc_mem . resize ( 684 ) ;
return_value = & alloc_mem [ 0 ] ;
snprintf ( ( char * ) return_value , 684 , " %s @ %s " , GetTypeName ( ) . AsCString ( ) , GetLocationAsCString ( ) ) ;
}
}
else
return_value = GetValueAsCString ( ) ;
}
}
if ( return_value )
s . PutCString ( return_value ) ;
else
{
if ( m_error . Fail ( ) )
s . Printf ( " <%s> " , m_error . AsCString ( ) ) ;
else if ( val_obj_display = = eValueObjectRepresentationStyleSummary )
s . PutCString ( " <no summary available> " ) ;
else if ( val_obj_display = = eValueObjectRepresentationStyleValue )
s . PutCString ( " <no value available> " ) ;
else if ( val_obj_display = = eValueObjectRepresentationStyleLanguageSpecific )
s . PutCString ( " <not a valid Objective-C object> " ) ; // edit this if we have other runtimes that support a description
else
s . PutCString ( " <no printable representation> " ) ;
}
// we should only return false here if we could not do *anything*
// even if we have an error message as output, that's a success
// from our callers' perspective, so return true
var_success = true ;
if ( custom_format ! = eFormatInvalid )
SetFormat ( eFormatDefault ) ;
}
2011-07-12 22:56:10 +00:00
return var_success ;
2011-07-06 02:13:41 +00:00
}
2010-10-27 03:32:59 +00:00
addr_t
2011-09-06 19:20:51 +00:00
ValueObject : : GetAddressOf ( bool scalar_is_load_address , AddressType * address_type )
2010-10-27 03:32:59 +00:00
{
2011-08-02 17:27:39 +00:00
if ( ! UpdateValueIfNeeded ( false ) )
2011-04-16 00:01:13 +00:00
return LLDB_INVALID_ADDRESS ;
2010-10-27 03:32:59 +00:00
switch ( m_value . GetValueType ( ) )
{
case Value : : eValueTypeScalar :
2012-10-30 18:18:43 +00:00
case Value : : eValueTypeVector :
2010-10-27 03:32:59 +00:00
if ( scalar_is_load_address )
{
2011-09-06 19:20:51 +00:00
if ( address_type )
* address_type = eAddressTypeLoad ;
2010-10-27 03:32:59 +00:00
return m_value . GetScalar ( ) . ULongLong ( LLDB_INVALID_ADDRESS ) ;
}
break ;
case Value : : eValueTypeLoadAddress :
case Value : : eValueTypeFileAddress :
case Value : : eValueTypeHostAddress :
{
2011-09-06 19:20:51 +00:00
if ( address_type )
* address_type = m_value . GetValueAddressType ( ) ;
2010-10-27 03:32:59 +00:00
return m_value . GetScalar ( ) . ULongLong ( LLDB_INVALID_ADDRESS ) ;
}
break ;
}
2011-09-06 19:20:51 +00:00
if ( address_type )
* address_type = eAddressTypeInvalid ;
2010-10-27 03:32:59 +00:00
return LLDB_INVALID_ADDRESS ;
}
2010-09-13 03:32:57 +00:00
addr_t
2011-09-06 19:20:51 +00:00
ValueObject : : GetPointerValue ( AddressType * address_type )
2010-09-13 03:32:57 +00:00
{
2011-09-02 01:15:17 +00:00
addr_t address = LLDB_INVALID_ADDRESS ;
2011-09-06 19:20:51 +00:00
if ( address_type )
* address_type = eAddressTypeInvalid ;
2011-04-16 00:01:13 +00:00
2011-08-02 17:27:39 +00:00
if ( ! UpdateValueIfNeeded ( false ) )
2011-04-16 00:01:13 +00:00
return address ;
2010-10-27 03:32:59 +00:00
switch ( m_value . GetValueType ( ) )
2010-09-13 03:32:57 +00:00
{
case Value : : eValueTypeScalar :
2012-10-30 18:18:43 +00:00
case Value : : eValueTypeVector :
2011-09-06 19:20:51 +00:00
address = m_value . GetScalar ( ) . ULongLong ( LLDB_INVALID_ADDRESS ) ;
2010-09-13 03:32:57 +00:00
break ;
2011-09-06 19:20:51 +00:00
case Value : : eValueTypeHostAddress :
2010-09-13 03:32:57 +00:00
case Value : : eValueTypeLoadAddress :
case Value : : eValueTypeFileAddress :
{
uint32_t data_offset = 0 ;
address = m_data . GetPointer ( & data_offset ) ;
}
break ;
}
2010-12-14 02:59:59 +00:00
2011-09-06 19:20:51 +00:00
if ( address_type )
* address_type = GetAddressTypeOfChildren ( ) ;
2010-12-14 02:59:59 +00:00
2010-09-13 03:32:57 +00:00
return address ;
}
2010-06-08 16:52:24 +00:00
bool
2012-05-08 21:25:06 +00:00
ValueObject : : SetValueFromCString ( const char * value_str , Error & error )
2010-06-08 16:52:24 +00:00
{
2012-05-08 21:25:06 +00:00
error . Clear ( ) ;
2010-06-08 16:52:24 +00:00
// Make sure our value is up to date first so that our location and location
// type is valid.
2011-08-02 17:27:39 +00:00
if ( ! UpdateValueIfNeeded ( false ) )
2012-05-08 21:25:06 +00:00
{
error . SetErrorString ( " unable to read value " ) ;
2010-06-08 16:52:24 +00:00
return false ;
2012-05-08 21:25:06 +00:00
}
2010-06-08 16:52:24 +00:00
uint32_t count = 0 ;
2011-09-02 01:15:17 +00:00
Encoding encoding = ClangASTType : : GetEncoding ( GetClangType ( ) , count ) ;
2010-06-08 16:52:24 +00:00
2010-07-14 00:18:15 +00:00
const size_t byte_size = GetByteSize ( ) ;
2010-06-08 16:52:24 +00:00
2011-08-12 23:34:31 +00:00
Value : : ValueType value_type = m_value . GetValueType ( ) ;
if ( value_type = = Value : : eValueTypeScalar )
{
// If the value is already a scalar, then let the scalar change itself:
m_value . GetScalar ( ) . SetValueFromCString ( value_str , encoding , byte_size ) ;
}
else if ( byte_size < = Scalar : : GetMaxByteSize ( ) )
{
// If the value fits in a scalar, then make a new scalar and again let the
// scalar code do the conversion, then figure out where to put the new value.
Scalar new_scalar ;
error = new_scalar . SetValueFromCString ( value_str , encoding , byte_size ) ;
if ( error . Success ( ) )
2010-06-08 16:52:24 +00:00
{
2011-08-09 02:12:22 +00:00
switch ( value_type )
{
2012-02-17 07:49:44 +00:00
case Value : : eValueTypeLoadAddress :
2011-08-12 23:34:31 +00:00
{
// If it is a load address, then the scalar value is the storage location
// of the data, and we have to shove this value down to that load location.
2012-02-17 07:49:44 +00:00
ExecutionContext exe_ctx ( GetExecutionContextRef ( ) ) ;
Process * process = exe_ctx . GetProcessPtr ( ) ;
if ( process )
2011-08-12 23:34:31 +00:00
{
2012-10-24 20:24:39 +00:00
addr_t target_addr = m_value . GetScalar ( ) . ULongLong ( LLDB_INVALID_ADDRESS ) ;
2012-02-17 07:49:44 +00:00
size_t bytes_written = process - > WriteScalarToMemory ( target_addr ,
new_scalar ,
byte_size ,
error ) ;
2012-05-08 21:25:06 +00:00
if ( ! error . Success ( ) )
return false ;
if ( bytes_written ! = byte_size )
{
error . SetErrorString ( " unable to write value to memory " ) ;
return false ;
}
2011-08-12 23:34:31 +00:00
}
}
2011-08-09 02:12:22 +00:00
break ;
2012-02-17 07:49:44 +00:00
case Value : : eValueTypeHostAddress :
2011-08-12 23:34:31 +00:00
{
// If it is a host address, then we stuff the scalar as a DataBuffer into the Value's data.
DataExtractor new_data ;
new_data . SetByteOrder ( m_data . GetByteOrder ( ) ) ;
DataBufferSP buffer_sp ( new DataBufferHeap ( byte_size , 0 ) ) ;
m_data . SetData ( buffer_sp , 0 ) ;
bool success = new_scalar . GetData ( new_data ) ;
if ( success )
{
2012-02-17 07:49:44 +00:00
new_data . CopyByteOrderedData ( 0 ,
byte_size ,
const_cast < uint8_t * > ( m_data . GetDataStart ( ) ) ,
byte_size ,
m_data . GetByteOrder ( ) ) ;
2011-08-12 23:34:31 +00:00
}
m_value . GetScalar ( ) = ( uintptr_t ) m_data . GetDataStart ( ) ;
}
2011-08-09 02:12:22 +00:00
break ;
2012-02-17 07:49:44 +00:00
case Value : : eValueTypeFileAddress :
case Value : : eValueTypeScalar :
2012-10-30 18:18:43 +00:00
case Value : : eValueTypeVector :
break ;
2011-08-09 02:12:22 +00:00
}
2010-06-08 16:52:24 +00:00
}
else
{
2011-08-12 23:34:31 +00:00
return false ;
2010-06-08 16:52:24 +00:00
}
2011-08-12 23:34:31 +00:00
}
else
{
// We don't support setting things bigger than a scalar at present.
2012-05-08 21:25:06 +00:00
error . SetErrorString ( " unable to write aggregate data type " ) ;
2010-06-08 16:52:24 +00:00
return false ;
}
2011-08-12 23:34:31 +00:00
// If we have reached this point, then we have successfully changed the value.
SetNeedsUpdate ( ) ;
return true ;
2010-06-08 16:52:24 +00:00
}
2012-02-04 02:27:34 +00:00
bool
ValueObject : : GetDeclaration ( Declaration & decl )
{
decl . Clear ( ) ;
return false ;
}
2012-03-26 23:03:23 +00:00
ConstString
ValueObject : : GetTypeName ( )
{
return ClangASTType : : GetConstTypeName ( GetClangAST ( ) , GetClangType ( ) ) ;
}
ConstString
ValueObject : : GetQualifiedTypeName ( )
{
return ClangASTType : : GetConstQualifiedTypeName ( GetClangAST ( ) , GetClangType ( ) ) ;
}
2011-09-02 01:15:17 +00:00
LanguageType
2010-09-28 01:25:32 +00:00
ValueObject : : GetObjectRuntimeLanguage ( )
{
2011-08-02 17:27:39 +00:00
return ClangASTType : : GetMinimumLanguage ( GetClangAST ( ) ,
GetClangType ( ) ) ;
2010-09-28 01:25:32 +00:00
}
2010-06-08 16:52:24 +00:00
void
2011-04-22 23:53:53 +00:00
ValueObject : : AddSyntheticChild ( const ConstString & key , ValueObject * valobj )
2010-06-08 16:52:24 +00:00
{
2011-04-22 23:53:53 +00:00
m_synthetic_children [ key ] = valobj ;
2010-06-08 16:52:24 +00:00
}
ValueObjectSP
ValueObject : : GetSyntheticChild ( const ConstString & key ) const
{
ValueObjectSP synthetic_child_sp ;
2011-04-22 23:53:53 +00:00
std : : map < ConstString , ValueObject * > : : const_iterator pos = m_synthetic_children . find ( key ) ;
2010-06-08 16:52:24 +00:00
if ( pos ! = m_synthetic_children . end ( ) )
2011-04-22 23:53:53 +00:00
synthetic_child_sp = pos - > second - > GetSP ( ) ;
2010-06-08 16:52:24 +00:00
return synthetic_child_sp ;
}
bool
ValueObject : : IsPointerType ( )
{
2010-09-29 01:12:09 +00:00
return ClangASTContext : : IsPointerType ( GetClangType ( ) ) ;
2010-06-08 16:52:24 +00:00
}
2011-07-09 20:12:33 +00:00
bool
ValueObject : : IsArrayType ( )
{
2012-12-06 02:33:54 +00:00
return ClangASTContext : : IsArrayType ( GetClangType ( ) , NULL , NULL , NULL ) ;
2011-07-09 20:12:33 +00:00
}
2011-07-06 02:13:41 +00:00
bool
ValueObject : : IsScalarType ( )
{
return ClangASTContext : : IsScalarType ( GetClangType ( ) ) ;
}
2011-03-18 00:05:18 +00:00
bool
ValueObject : : IsIntegerType ( bool & is_signed )
{
return ClangASTContext : : IsIntegerType ( GetClangType ( ) , is_signed ) ;
}
2010-10-27 03:32:59 +00:00
2010-06-08 16:52:24 +00:00
bool
ValueObject : : IsPointerOrReferenceType ( )
{
2011-05-30 00:49:24 +00:00
return ClangASTContext : : IsPointerOrReferenceType ( GetClangType ( ) ) ;
}
2011-06-29 22:09:02 +00:00
bool
ValueObject : : IsPossibleDynamicType ( )
{
2012-05-21 16:51:35 +00:00
ExecutionContext exe_ctx ( GetExecutionContextRef ( ) ) ;
Process * process = exe_ctx . GetProcessPtr ( ) ;
if ( process )
return process - > IsPossibleDynamicValue ( * this ) ;
else
2012-08-31 18:56:24 +00:00
return ClangASTContext : : IsPossibleDynamicType ( GetClangAST ( ) , GetClangType ( ) , NULL , true , true ) ;
2011-06-29 22:09:02 +00:00
}
2012-12-13 23:50:33 +00:00
bool
ValueObject : : IsObjCNil ( )
{
bool isObjCpointer = ClangASTContext : : IsObjCObjectPointerType ( GetClangType ( ) , NULL ) ;
bool canReadValue = true ;
bool isZero = GetValueAsUnsigned ( 0 , & canReadValue ) = = 0 ;
return canReadValue & & isZero & & isObjCpointer ;
}
2011-09-02 01:15:17 +00:00
ValueObjectSP
2011-08-19 21:13:46 +00:00
ValueObject : : GetSyntheticArrayMember ( int32_t index , bool can_create )
{
if ( IsArrayType ( ) )
return GetSyntheticArrayMemberFromArray ( index , can_create ) ;
if ( IsPointerType ( ) )
return GetSyntheticArrayMemberFromPointer ( index , can_create ) ;
return ValueObjectSP ( ) ;
}
2010-06-08 16:52:24 +00:00
ValueObjectSP
ValueObject : : GetSyntheticArrayMemberFromPointer ( int32_t index , bool can_create )
{
ValueObjectSP synthetic_child_sp ;
if ( IsPointerType ( ) )
{
char index_str [ 64 ] ;
snprintf ( index_str , sizeof ( index_str ) , " [%i] " , index ) ;
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 )
{
2011-04-22 23:53:53 +00:00
ValueObject * synthetic_child ;
2010-06-08 16:52:24 +00:00
// We haven't made a synthetic array member for INDEX yet, so
// lets make one and cache it for any future reference.
2011-04-22 23:53:53 +00:00
synthetic_child = CreateChildAtIndex ( 0 , true , index ) ;
2010-06-08 16:52:24 +00:00
// Cache the value if we got one back...
2011-04-22 23:53:53 +00:00
if ( synthetic_child )
{
AddSyntheticChild ( index_const_str , synthetic_child ) ;
synthetic_child_sp = synthetic_child - > GetSP ( ) ;
2011-07-29 19:53:35 +00:00
synthetic_child_sp - > SetName ( ConstString ( index_str ) ) ;
2011-07-02 00:25:22 +00:00
synthetic_child_sp - > m_is_array_item_for_pointer = true ;
2011-04-22 23:53:53 +00:00
}
2010-06-08 16:52:24 +00:00
}
}
return synthetic_child_sp ;
}
2010-09-23 02:01:19 +00:00
2011-07-09 20:12:33 +00:00
// This allows you to create an array member using and index
// that doesn't not fall in the normal bounds of the array.
// Many times structure can be defined as:
// struct Collection
// {
// uint32_t item_count;
// Item item_array[0];
// };
// The size of the "item_array" is 1, but many times in practice
// there are more items in "item_array".
ValueObjectSP
ValueObject : : GetSyntheticArrayMemberFromArray ( int32_t index , bool can_create )
{
ValueObjectSP synthetic_child_sp ;
if ( IsArrayType ( ) )
{
char index_str [ 64 ] ;
snprintf ( index_str , sizeof ( index_str ) , " [%i] " , index ) ;
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 )
{
ValueObject * 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 = CreateChildAtIndex ( 0 , true , index ) ;
// Cache the value if we got one back...
if ( synthetic_child )
{
AddSyntheticChild ( index_const_str , synthetic_child ) ;
synthetic_child_sp = synthetic_child - > GetSP ( ) ;
2011-07-29 19:53:35 +00:00
synthetic_child_sp - > SetName ( ConstString ( index_str ) ) ;
2011-07-09 20:12:33 +00:00
synthetic_child_sp - > m_is_array_item_for_pointer = true ;
}
}
}
return synthetic_child_sp ;
}
2011-07-06 02:13:41 +00:00
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 ,
2011-09-06 19:20:51 +00:00
false ,
eAddressTypeInvalid ) ;
2011-07-06 02:13:41 +00:00
// Cache the value if we got one back...
if ( synthetic_child )
{
AddSyntheticChild ( index_const_str , synthetic_child ) ;
synthetic_child_sp = synthetic_child - > GetSP ( ) ;
2011-07-29 19:53:35 +00:00
synthetic_child_sp - > SetName ( ConstString ( index_str ) ) ;
2011-07-06 02:13:41 +00:00
synthetic_child_sp - > m_is_bitfield_for_scalar = true ;
}
}
}
return synthetic_child_sp ;
2011-08-19 21:13:46 +00:00
}
2011-09-02 01:15:17 +00:00
ValueObjectSP
2011-08-19 21:13:46 +00:00
ValueObject : : GetSyntheticArrayRangeChild ( uint32_t from , uint32_t to , bool can_create )
{
ValueObjectSP synthetic_child_sp ;
if ( IsArrayType ( ) | | IsPointerType ( ) )
{
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 )
{
ValueObjectSynthetic * synthetic_child ;
// We haven't made a synthetic array member for INDEX yet, so
// lets make one and cache it for any future reference.
2012-02-15 02:34:21 +00:00
SyntheticArrayView * view = new SyntheticArrayView ( SyntheticChildren : : Flags ( ) ) ;
2011-08-19 21:13:46 +00:00
view - > AddRange ( from , to ) ;
SyntheticChildrenSP view_sp ( view ) ;
synthetic_child = new ValueObjectSynthetic ( * this , view_sp ) ;
// 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 ( ConstString ( index_str ) ) ;
synthetic_child_sp - > m_is_bitfield_for_scalar = true ;
}
}
}
return synthetic_child_sp ;
2011-07-06 02:13:41 +00:00
}
2011-09-02 01:15:17 +00:00
ValueObjectSP
2011-07-29 19:53:35 +00:00
ValueObject : : GetSyntheticChildAtOffset ( uint32_t offset , const ClangASTType & type , bool can_create )
{
ValueObjectSP synthetic_child_sp ;
char name_str [ 64 ] ;
snprintf ( name_str , sizeof ( name_str ) , " @%i " , offset ) ;
ConstString name_const_str ( name_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 ( name_const_str ) ;
if ( synthetic_child_sp . get ( ) )
return synthetic_child_sp ;
if ( ! can_create )
2011-09-02 01:15:17 +00:00
return ValueObjectSP ( ) ;
2011-07-29 19:53:35 +00:00
ValueObjectChild * synthetic_child = new ValueObjectChild ( * this ,
type . GetASTContext ( ) ,
type . GetOpaqueQualType ( ) ,
name_const_str ,
type . GetTypeByteSize ( ) ,
offset ,
0 ,
0 ,
false ,
2011-09-06 19:20:51 +00:00
false ,
eAddressTypeInvalid ) ;
2011-07-29 19:53:35 +00:00
if ( synthetic_child )
{
AddSyntheticChild ( name_const_str , synthetic_child ) ;
synthetic_child_sp = synthetic_child - > GetSP ( ) ;
synthetic_child_sp - > SetName ( name_const_str ) ;
synthetic_child_sp - > m_is_child_at_offset = true ;
}
return synthetic_child_sp ;
}
2011-07-22 00:16:08 +00:00
// your expression path needs to have a leading . or ->
// (unless it somehow "looks like" an array, in which case it has
// a leading [ symbol). while the [ is meaningful and should be shown
// to the user, . and -> are just parser design, but by no means
// added information for the user.. strip them off
static const char *
SkipLeadingExpressionPathSeparators ( const char * expression )
{
if ( ! expression | | ! expression [ 0 ] )
return expression ;
if ( expression [ 0 ] = = ' . ' )
return expression + 1 ;
if ( expression [ 0 ] = = ' - ' & & expression [ 1 ] = = ' > ' )
return expression + 2 ;
return expression ;
}
2011-09-02 01:15:17 +00:00
ValueObjectSP
2011-07-22 00:16:08 +00:00
ValueObject : : GetSyntheticExpressionPathChild ( const char * expression , bool can_create )
{
ValueObjectSP synthetic_child_sp ;
ConstString name_const_string ( expression ) ;
// 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 ( name_const_string ) ;
if ( ! synthetic_child_sp )
{
// We haven't made a synthetic array member for expression yet, so
// lets make one and cache it for any future reference.
2012-08-02 17:34:05 +00:00
synthetic_child_sp = GetValueForExpressionPath ( expression ,
NULL , NULL , NULL ,
GetValueForExpressionPathOptions ( ) . DontAllowSyntheticChildren ( ) ) ;
2011-07-22 00:16:08 +00:00
// Cache the value if we got one back...
if ( synthetic_child_sp . get ( ) )
{
AddSyntheticChild ( name_const_string , synthetic_child_sp . get ( ) ) ;
2011-07-29 19:53:35 +00:00
synthetic_child_sp - > SetName ( ConstString ( SkipLeadingExpressionPathSeparators ( expression ) ) ) ;
2011-07-22 00:16:08 +00:00
synthetic_child_sp - > m_is_expression_path_child = true ;
}
}
return synthetic_child_sp ;
}
void
2012-03-19 22:58:49 +00:00
ValueObject : : CalculateSyntheticValue ( bool use_synthetic )
2011-07-22 00:16:08 +00:00
{
2012-03-19 22:58:49 +00:00
if ( use_synthetic = = false )
2011-07-22 00:16:08 +00:00
return ;
2012-03-27 02:35:13 +00:00
TargetSP target_sp ( GetTargetSP ( ) ) ;
if ( target_sp & & ( target_sp - > GetEnableSyntheticValue ( ) = = false | | target_sp - > GetSuppressSyntheticValue ( ) = = true ) )
{
m_synthetic_value = NULL ;
return ;
}
2012-10-22 18:18:36 +00:00
lldb : : SyntheticChildrenSP current_synth_sp ( m_synthetic_children_sp ) ;
2012-03-19 22:58:49 +00:00
if ( ! UpdateFormatsIfNeeded ( m_last_format_mgr_dynamic ) & & m_synthetic_value )
return ;
2011-07-22 00:16:08 +00:00
2012-03-01 04:24:26 +00:00
if ( m_synthetic_children_sp . get ( ) = = NULL )
2011-07-22 00:16:08 +00:00
return ;
2012-10-22 18:18:36 +00:00
if ( current_synth_sp = = m_synthetic_children_sp & & m_synthetic_value )
return ;
2012-03-19 22:58:49 +00:00
m_synthetic_value = new ValueObjectSynthetic ( * this , m_synthetic_children_sp ) ;
2011-07-22 00:16:08 +00:00
}
2011-04-16 00:01:13 +00:00
void
2011-09-02 01:15:17 +00:00
ValueObject : : CalculateDynamicValue ( DynamicValueType use_dynamic )
2010-09-23 02:01:19 +00:00
{
2011-09-02 01:15:17 +00:00
if ( use_dynamic = = eNoDynamicValues )
2011-05-04 03:43:18 +00:00
return ;
2011-04-22 23:53:53 +00:00
if ( ! m_dynamic_value & & ! IsDynamic ( ) )
2011-04-16 00:01:13 +00:00
{
2012-02-17 07:49:44 +00:00
ExecutionContext exe_ctx ( GetExecutionContextRef ( ) ) ;
Process * process = exe_ctx . GetProcessPtr ( ) ;
2012-05-21 16:51:35 +00:00
if ( process & & process - > IsPossibleDynamicValue ( * this ) )
2012-10-22 18:18:36 +00:00
{
ClearDynamicTypeInformation ( ) ;
2012-05-21 16:51:35 +00:00
m_dynamic_value = new ValueObjectDynamicValue ( * this , use_dynamic ) ;
2012-10-22 18:18:36 +00:00
}
2011-04-16 00:01:13 +00:00
}
}
2011-04-22 23:53:53 +00:00
ValueObjectSP
2011-05-04 03:43:18 +00:00
ValueObject : : GetDynamicValue ( DynamicValueType use_dynamic )
2011-04-16 00:01:13 +00:00
{
2011-09-02 01:15:17 +00:00
if ( use_dynamic = = eNoDynamicValues )
2011-05-04 03:43:18 +00:00
return ValueObjectSP ( ) ;
if ( ! IsDynamic ( ) & & m_dynamic_value = = NULL )
2011-04-16 00:01:13 +00:00
{
2011-05-04 03:43:18 +00:00
CalculateDynamicValue ( use_dynamic ) ;
2011-04-16 00:01:13 +00:00
}
2011-04-22 23:53:53 +00:00
if ( m_dynamic_value )
return m_dynamic_value - > GetSP ( ) ;
else
return ValueObjectSP ( ) ;
2010-09-23 02:01:19 +00:00
}
2010-10-05 00:00:42 +00:00
2011-12-08 19:44:08 +00:00
ValueObjectSP
ValueObject : : GetStaticValue ( )
{
return GetSP ( ) ;
}
2012-05-08 18:47:08 +00:00
lldb : : ValueObjectSP
ValueObject : : GetNonSyntheticValue ( )
{
return GetSP ( ) ;
}
2011-07-22 00:16:08 +00:00
ValueObjectSP
2012-03-19 22:58:49 +00:00
ValueObject : : GetSyntheticValue ( bool use_synthetic )
2011-07-22 00:16:08 +00:00
{
2012-03-19 22:58:49 +00:00
if ( use_synthetic = = false )
return ValueObjectSP ( ) ;
2011-07-22 00:16:08 +00:00
CalculateSyntheticValue ( use_synthetic ) ;
if ( m_synthetic_value )
return m_synthetic_value - > GetSP ( ) ;
else
2012-03-19 22:58:49 +00:00
return ValueObjectSP ( ) ;
2011-07-22 00:16:08 +00:00
}
2011-08-09 01:04:56 +00:00
bool
ValueObject : : HasSyntheticValue ( )
{
UpdateFormatsIfNeeded ( m_last_format_mgr_dynamic ) ;
2012-03-01 04:24:26 +00:00
if ( m_synthetic_children_sp . get ( ) = = NULL )
2011-08-09 01:04:56 +00:00
return false ;
2012-03-19 22:58:49 +00:00
CalculateSyntheticValue ( true ) ;
2011-08-09 01:04:56 +00:00
if ( m_synthetic_value )
return true ;
else
return false ;
}
2011-01-21 01:59:00 +00:00
bool
ValueObject : : GetBaseClassPath ( Stream & s )
{
if ( IsBaseClass ( ) )
{
2011-04-16 00:01:13 +00:00
bool parent_had_base_class = GetParent ( ) & & GetParent ( ) - > GetBaseClassPath ( s ) ;
2011-01-21 01:59:00 +00:00
clang_type_t clang_type = GetClangType ( ) ;
std : : string cxx_class_name ;
bool this_had_base_class = ClangASTContext : : GetCXXClassName ( clang_type , cxx_class_name ) ;
if ( this_had_base_class )
{
if ( parent_had_base_class )
s . PutCString ( " :: " ) ;
s . PutCString ( cxx_class_name . c_str ( ) ) ;
}
return parent_had_base_class | | this_had_base_class ;
}
return false ;
}
ValueObject *
ValueObject : : GetNonBaseClassParent ( )
{
2011-04-16 00:01:13 +00:00
if ( GetParent ( ) )
2011-01-21 01:59:00 +00:00
{
2011-04-16 00:01:13 +00:00
if ( GetParent ( ) - > IsBaseClass ( ) )
return GetParent ( ) - > GetNonBaseClassParent ( ) ;
2011-01-21 01:59:00 +00:00
else
2011-04-16 00:01:13 +00:00
return GetParent ( ) ;
2011-01-21 01:59:00 +00:00
}
return NULL ;
}
2010-10-05 00:00:42 +00:00
2010-10-14 22:52:14 +00:00
void
2011-06-29 22:27:15 +00:00
ValueObject : : GetExpressionPath ( Stream & s , bool qualify_cxx_base_classes , GetExpressionPathFormat epformat )
2010-10-14 22:52:14 +00:00
{
2011-01-21 01:59:00 +00:00
const bool is_deref_of_parent = IsDereferenceOfParent ( ) ;
2012-03-19 22:58:49 +00:00
if ( is_deref_of_parent & & epformat = = eGetExpressionPathFormatDereferencePointers )
2011-08-18 16:38:26 +00:00
{
2011-06-29 22:27:15 +00:00
// this is the original format of GetExpressionPath() producing code like *(a_ptr).memberName, which is entirely
// fine, until you put this into StackFrame::GetValueForVariableExpressionPath() which prefers to see a_ptr->memberName.
// the eHonorPointers mode is meant to produce strings in this latter format
s . PutCString ( " *( " ) ;
}
2011-01-21 01:59:00 +00:00
2011-06-29 22:27:15 +00:00
ValueObject * parent = GetParent ( ) ;
if ( parent )
parent - > GetExpressionPath ( s , qualify_cxx_base_classes , epformat ) ;
2011-07-02 00:25:22 +00:00
// if we are a deref_of_parent just because we are synthetic array
// members made up to allow ptr[%d] syntax to work in variable
// printing, then add our name ([%d]) to the expression path
2012-03-19 22:58:49 +00:00
if ( m_is_array_item_for_pointer & & epformat = = eGetExpressionPathFormatHonorPointers )
2011-07-02 00:25:22 +00:00
s . PutCString ( m_name . AsCString ( ) ) ;
2011-06-29 22:27:15 +00:00
2011-01-21 01:59:00 +00:00
if ( ! IsBaseClass ( ) )
{
if ( ! is_deref_of_parent )
2010-10-14 22:52:14 +00:00
{
2011-01-21 01:59:00 +00:00
ValueObject * non_base_class_parent = GetNonBaseClassParent ( ) ;
if ( non_base_class_parent )
2010-10-14 22:52:14 +00:00
{
2011-01-21 01:59:00 +00:00
clang_type_t non_base_class_parent_clang_type = non_base_class_parent - > GetClangType ( ) ;
if ( non_base_class_parent_clang_type )
{
const uint32_t non_base_class_parent_type_info = ClangASTContext : : GetTypeInfo ( non_base_class_parent_clang_type , NULL , NULL ) ;
2012-03-19 22:58:49 +00:00
if ( parent & & parent - > IsDereferenceOfParent ( ) & & epformat = = eGetExpressionPathFormatHonorPointers )
2011-01-21 01:59:00 +00:00
{
s . PutCString ( " -> " ) ;
}
2011-06-29 22:27:15 +00:00
else
{
if ( non_base_class_parent_type_info & ClangASTContext : : eTypeIsPointer )
{
s . PutCString ( " -> " ) ;
}
else if ( ( non_base_class_parent_type_info & ClangASTContext : : eTypeHasChildren ) & &
! ( non_base_class_parent_type_info & ClangASTContext : : eTypeIsArray ) )
{
s . PutChar ( ' . ' ) ;
}
2011-01-21 01:59:00 +00:00
}
}
2010-10-14 22:52:14 +00:00
}
2011-01-21 01:59:00 +00:00
const char * name = GetName ( ) . GetCString ( ) ;
if ( name )
2010-10-14 22:52:14 +00:00
{
2011-01-21 01:59:00 +00:00
if ( qualify_cxx_base_classes )
{
if ( GetBaseClassPath ( s ) )
s . PutCString ( " :: " ) ;
}
s . PutCString ( name ) ;
2010-10-14 22:52:14 +00:00
}
}
}
2012-03-19 22:58:49 +00:00
if ( is_deref_of_parent & & epformat = = eGetExpressionPathFormatDereferencePointers )
2011-08-18 16:38:26 +00:00
{
2011-01-21 01:59:00 +00:00
s . PutChar ( ' ) ' ) ;
2011-06-29 22:27:15 +00:00
}
2010-10-14 22:52:14 +00:00
}
2011-09-02 01:15:17 +00:00
ValueObjectSP
2011-07-08 02:51:01 +00:00
ValueObject : : GetValueForExpressionPath ( const char * expression ,
const char * * first_unparsed ,
ExpressionPathScanEndReason * reason_to_stop ,
ExpressionPathEndResultType * final_value_type ,
const GetValueForExpressionPathOptions & options ,
ExpressionPathAftermath * final_task_on_target )
{
const char * dummy_first_unparsed ;
ExpressionPathScanEndReason dummy_reason_to_stop ;
ExpressionPathEndResultType dummy_final_value_type ;
2012-03-19 22:58:49 +00:00
ExpressionPathAftermath dummy_final_task_on_target = ValueObject : : eExpressionPathAftermathNothing ;
2011-07-08 02:51:01 +00:00
ValueObjectSP ret_val = GetValueForExpressionPath_Impl ( expression ,
first_unparsed ? first_unparsed : & dummy_first_unparsed ,
reason_to_stop ? reason_to_stop : & dummy_reason_to_stop ,
final_value_type ? final_value_type : & dummy_final_value_type ,
options ,
final_task_on_target ? final_task_on_target : & dummy_final_task_on_target ) ;
2012-03-19 22:58:49 +00:00
if ( ! final_task_on_target | | * final_task_on_target = = ValueObject : : eExpressionPathAftermathNothing )
2011-07-08 02:51:01 +00:00
return ret_val ;
2012-03-03 00:45:57 +00:00
2012-03-19 22:58:49 +00:00
if ( ret_val . get ( ) & & ( ( final_value_type ? * final_value_type : dummy_final_value_type ) = = eExpressionPathEndResultTypePlain ) ) // I can only deref and takeaddress of plain objects
2011-07-08 02:51:01 +00:00
{
2012-03-19 22:58:49 +00:00
if ( ( final_task_on_target ? * final_task_on_target : dummy_final_task_on_target ) = = ValueObject : : eExpressionPathAftermathDereference )
2011-07-08 02:51:01 +00:00
{
Error error ;
ValueObjectSP final_value = ret_val - > Dereference ( error ) ;
if ( error . Fail ( ) | | ! final_value . get ( ) )
{
2012-03-03 00:45:57 +00:00
if ( reason_to_stop )
2012-03-19 22:58:49 +00:00
* reason_to_stop = ValueObject : : eExpressionPathScanEndReasonDereferencingFailed ;
2012-03-03 00:45:57 +00:00
if ( final_value_type )
2012-03-19 22:58:49 +00:00
* final_value_type = ValueObject : : eExpressionPathEndResultTypeInvalid ;
2011-07-08 02:51:01 +00:00
return ValueObjectSP ( ) ;
}
else
{
2012-03-03 00:45:57 +00:00
if ( final_task_on_target )
2012-03-19 22:58:49 +00:00
* final_task_on_target = ValueObject : : eExpressionPathAftermathNothing ;
2011-07-08 02:51:01 +00:00
return final_value ;
}
}
2012-03-19 22:58:49 +00:00
if ( * final_task_on_target = = ValueObject : : eExpressionPathAftermathTakeAddress )
2011-07-08 02:51:01 +00:00
{
Error error ;
ValueObjectSP final_value = ret_val - > AddressOf ( error ) ;
if ( error . Fail ( ) | | ! final_value . get ( ) )
{
2012-03-03 00:45:57 +00:00
if ( reason_to_stop )
2012-03-19 22:58:49 +00:00
* reason_to_stop = ValueObject : : eExpressionPathScanEndReasonTakingAddressFailed ;
2012-03-03 00:45:57 +00:00
if ( final_value_type )
2012-03-19 22:58:49 +00:00
* final_value_type = ValueObject : : eExpressionPathEndResultTypeInvalid ;
2011-07-08 02:51:01 +00:00
return ValueObjectSP ( ) ;
}
else
{
2012-03-03 00:45:57 +00:00
if ( final_task_on_target )
2012-03-19 22:58:49 +00:00
* final_task_on_target = ValueObject : : eExpressionPathAftermathNothing ;
2011-07-08 02:51:01 +00:00
return final_value ;
}
}
}
return ret_val ; // final_task_on_target will still have its original value, so you know I did not do it
}
2011-07-12 00:18:11 +00:00
int
ValueObject : : GetValuesForExpressionPath ( const char * expression ,
2011-09-02 01:15:17 +00:00
ValueObjectListSP & list ,
2011-07-12 00:18:11 +00:00
const char * * first_unparsed ,
ExpressionPathScanEndReason * reason_to_stop ,
ExpressionPathEndResultType * final_value_type ,
const GetValueForExpressionPathOptions & options ,
ExpressionPathAftermath * final_task_on_target )
{
const char * dummy_first_unparsed ;
ExpressionPathScanEndReason dummy_reason_to_stop ;
ExpressionPathEndResultType dummy_final_value_type ;
2012-03-19 22:58:49 +00:00
ExpressionPathAftermath dummy_final_task_on_target = ValueObject : : eExpressionPathAftermathNothing ;
2011-07-12 00:18:11 +00:00
ValueObjectSP ret_val = GetValueForExpressionPath_Impl ( expression ,
first_unparsed ? first_unparsed : & dummy_first_unparsed ,
reason_to_stop ? reason_to_stop : & dummy_reason_to_stop ,
final_value_type ? final_value_type : & dummy_final_value_type ,
options ,
final_task_on_target ? final_task_on_target : & dummy_final_task_on_target ) ;
if ( ! ret_val . get ( ) ) // if there are errors, I add nothing to the list
return 0 ;
2012-03-29 01:34:34 +00:00
if ( ( reason_to_stop ? * reason_to_stop : dummy_reason_to_stop ) ! = eExpressionPathScanEndReasonArrayRangeOperatorMet )
2011-07-12 00:18:11 +00:00
{
// I need not expand a range, just post-process the final value and return
2012-03-19 22:58:49 +00:00
if ( ! final_task_on_target | | * final_task_on_target = = ValueObject : : eExpressionPathAftermathNothing )
2011-07-12 00:18:11 +00:00
{
list - > Append ( ret_val ) ;
return 1 ;
}
2012-03-29 01:34:34 +00:00
if ( ret_val . get ( ) & & ( final_value_type ? * final_value_type : dummy_final_value_type ) = = eExpressionPathEndResultTypePlain ) // I can only deref and takeaddress of plain objects
2011-07-12 00:18:11 +00:00
{
2012-03-19 22:58:49 +00:00
if ( * final_task_on_target = = ValueObject : : eExpressionPathAftermathDereference )
2011-07-12 00:18:11 +00:00
{
Error error ;
ValueObjectSP final_value = ret_val - > Dereference ( error ) ;
if ( error . Fail ( ) | | ! final_value . get ( ) )
{
2012-07-17 03:23:13 +00:00
if ( reason_to_stop )
* reason_to_stop = ValueObject : : eExpressionPathScanEndReasonDereferencingFailed ;
if ( final_value_type )
* final_value_type = ValueObject : : eExpressionPathEndResultTypeInvalid ;
2011-07-12 00:18:11 +00:00
return 0 ;
}
else
{
2012-03-19 22:58:49 +00:00
* final_task_on_target = ValueObject : : eExpressionPathAftermathNothing ;
2011-07-12 00:18:11 +00:00
list - > Append ( final_value ) ;
return 1 ;
}
}
2012-03-19 22:58:49 +00:00
if ( * final_task_on_target = = ValueObject : : eExpressionPathAftermathTakeAddress )
2011-07-12 00:18:11 +00:00
{
Error error ;
ValueObjectSP final_value = ret_val - > AddressOf ( error ) ;
if ( error . Fail ( ) | | ! final_value . get ( ) )
{
2012-07-17 03:23:13 +00:00
if ( reason_to_stop )
* reason_to_stop = ValueObject : : eExpressionPathScanEndReasonTakingAddressFailed ;
if ( final_value_type )
* final_value_type = ValueObject : : eExpressionPathEndResultTypeInvalid ;
2011-07-12 00:18:11 +00:00
return 0 ;
}
else
{
2012-03-19 22:58:49 +00:00
* final_task_on_target = ValueObject : : eExpressionPathAftermathNothing ;
2011-07-12 00:18:11 +00:00
list - > Append ( final_value ) ;
return 1 ;
}
}
}
}
else
{
return ExpandArraySliceExpression ( first_unparsed ? * first_unparsed : dummy_first_unparsed ,
first_unparsed ? first_unparsed : & dummy_first_unparsed ,
ret_val ,
list ,
reason_to_stop ? reason_to_stop : & dummy_reason_to_stop ,
final_value_type ? final_value_type : & dummy_final_value_type ,
options ,
final_task_on_target ? final_task_on_target : & dummy_final_task_on_target ) ;
}
// in any non-covered case, just do the obviously right thing
list - > Append ( ret_val ) ;
return 1 ;
}
2011-09-02 01:15:17 +00:00
ValueObjectSP
2011-07-08 02:51:01 +00:00
ValueObject : : GetValueForExpressionPath_Impl ( const char * expression_cstr ,
const char * * first_unparsed ,
ExpressionPathScanEndReason * reason_to_stop ,
ExpressionPathEndResultType * final_result ,
const GetValueForExpressionPathOptions & options ,
ExpressionPathAftermath * what_next )
{
ValueObjectSP root = GetSP ( ) ;
if ( ! root . get ( ) )
return ValueObjectSP ( ) ;
* first_unparsed = expression_cstr ;
while ( true )
{
const char * expression_cstr = * first_unparsed ; // hide the top level expression_cstr
2011-09-02 01:15:17 +00:00
clang_type_t root_clang_type = root - > GetClangType ( ) ;
clang_type_t pointee_clang_type ;
2011-07-12 00:18:11 +00:00
Flags root_clang_type_info , pointee_clang_type_info ;
root_clang_type_info = Flags ( ClangASTContext : : GetTypeInfo ( root_clang_type , GetClangAST ( ) , & pointee_clang_type ) ) ;
if ( pointee_clang_type )
pointee_clang_type_info = Flags ( ClangASTContext : : GetTypeInfo ( pointee_clang_type , GetClangAST ( ) , NULL ) ) ;
2011-07-08 02:51:01 +00:00
if ( ! expression_cstr | | * expression_cstr = = ' \0 ' )
{
2012-03-19 22:58:49 +00:00
* reason_to_stop = ValueObject : : eExpressionPathScanEndReasonEndOfString ;
2011-07-08 02:51:01 +00:00
return root ;
}
switch ( * expression_cstr )
{
case ' - ' :
{
if ( options . m_check_dot_vs_arrow_syntax & &
2011-07-12 00:18:11 +00:00
root_clang_type_info . Test ( ClangASTContext : : eTypeIsPointer ) ) // if you are trying to use -> on a non-pointer and I must catch the error
2011-07-08 02:51:01 +00:00
{
* first_unparsed = expression_cstr ;
2012-03-19 22:58:49 +00:00
* reason_to_stop = ValueObject : : eExpressionPathScanEndReasonArrowInsteadOfDot ;
* final_result = ValueObject : : eExpressionPathEndResultTypeInvalid ;
2011-07-08 02:51:01 +00:00
return ValueObjectSP ( ) ;
}
2011-07-12 00:18:11 +00:00
if ( root_clang_type_info . Test ( ClangASTContext : : eTypeIsObjC ) & & // if yo are trying to extract an ObjC IVar when this is forbidden
root_clang_type_info . Test ( ClangASTContext : : eTypeIsPointer ) & &
2011-07-08 02:51:01 +00:00
options . m_no_fragile_ivar )
{
* first_unparsed = expression_cstr ;
2012-03-19 22:58:49 +00:00
* reason_to_stop = ValueObject : : eExpressionPathScanEndReasonFragileIVarNotAllowed ;
* final_result = ValueObject : : eExpressionPathEndResultTypeInvalid ;
2011-07-08 02:51:01 +00:00
return ValueObjectSP ( ) ;
}
if ( expression_cstr [ 1 ] ! = ' > ' )
{
* first_unparsed = expression_cstr ;
2012-03-19 22:58:49 +00:00
* reason_to_stop = ValueObject : : eExpressionPathScanEndReasonUnexpectedSymbol ;
* final_result = ValueObject : : eExpressionPathEndResultTypeInvalid ;
2011-07-08 02:51:01 +00:00
return ValueObjectSP ( ) ;
}
expression_cstr + + ; // skip the -
}
case ' . ' : // or fallthrough from ->
{
if ( options . m_check_dot_vs_arrow_syntax & & * expression_cstr = = ' . ' & &
2011-07-12 00:18:11 +00:00
root_clang_type_info . Test ( ClangASTContext : : eTypeIsPointer ) ) // if you are trying to use . on a pointer and I must catch the error
2011-07-08 02:51:01 +00:00
{
* first_unparsed = expression_cstr ;
2012-03-19 22:58:49 +00:00
* reason_to_stop = ValueObject : : eExpressionPathScanEndReasonDotInsteadOfArrow ;
* final_result = ValueObject : : eExpressionPathEndResultTypeInvalid ;
2011-07-08 02:51:01 +00:00
return ValueObjectSP ( ) ;
}
expression_cstr + + ; // skip .
const char * next_separator = strpbrk ( expression_cstr + 1 , " -.[ " ) ;
ConstString child_name ;
if ( ! next_separator ) // if no other separator just expand this last layer
{
child_name . SetCString ( expression_cstr ) ;
2011-08-11 17:08:01 +00:00
ValueObjectSP child_valobj_sp = root - > GetChildMemberWithName ( child_name , true ) ;
if ( child_valobj_sp . get ( ) ) // we know we are done, so just return
2011-07-08 02:51:01 +00:00
{
2012-12-07 22:21:08 +00:00
* first_unparsed = " " ;
2012-03-19 22:58:49 +00:00
* reason_to_stop = ValueObject : : eExpressionPathScanEndReasonEndOfString ;
* final_result = ValueObject : : eExpressionPathEndResultTypePlain ;
2011-08-11 17:08:01 +00:00
return child_valobj_sp ;
}
else if ( options . m_no_synthetic_children = = false ) // let's try with synthetic children
{
2012-03-19 22:58:49 +00:00
if ( root - > IsSynthetic ( ) )
2012-08-02 17:34:05 +00:00
{
* first_unparsed = expression_cstr ;
* reason_to_stop = ValueObject : : eExpressionPathScanEndReasonNoSuchChild ;
* final_result = ValueObject : : eExpressionPathEndResultTypeInvalid ;
return ValueObjectSP ( ) ;
}
child_valobj_sp = root - > GetSyntheticValue ( ) ;
2012-03-19 22:58:49 +00:00
if ( child_valobj_sp . get ( ) )
child_valobj_sp = child_valobj_sp - > GetChildMemberWithName ( child_name , true ) ;
2011-08-11 17:08:01 +00:00
}
// if we are here and options.m_no_synthetic_children is true, child_valobj_sp is going to be a NULL SP,
// so we hit the "else" branch, and return an error
if ( child_valobj_sp . get ( ) ) // if it worked, just return
{
2012-12-07 22:21:08 +00:00
* first_unparsed = " " ;
2012-03-19 22:58:49 +00:00
* reason_to_stop = ValueObject : : eExpressionPathScanEndReasonEndOfString ;
* final_result = ValueObject : : eExpressionPathEndResultTypePlain ;
2011-08-11 17:08:01 +00:00
return child_valobj_sp ;
2011-07-08 02:51:01 +00:00
}
else
{
* first_unparsed = expression_cstr ;
2012-03-19 22:58:49 +00:00
* reason_to_stop = ValueObject : : eExpressionPathScanEndReasonNoSuchChild ;
* final_result = ValueObject : : eExpressionPathEndResultTypeInvalid ;
2011-07-08 02:51:01 +00:00
return ValueObjectSP ( ) ;
}
}
else // other layers do expand
{
child_name . SetCStringWithLength ( expression_cstr , next_separator - expression_cstr ) ;
2011-08-11 17:08:01 +00:00
ValueObjectSP child_valobj_sp = root - > GetChildMemberWithName ( child_name , true ) ;
if ( child_valobj_sp . get ( ) ) // store the new root and move on
2011-07-08 02:51:01 +00:00
{
2011-08-11 17:08:01 +00:00
root = child_valobj_sp ;
* first_unparsed = next_separator ;
2012-03-19 22:58:49 +00:00
* final_result = ValueObject : : eExpressionPathEndResultTypePlain ;
2011-08-11 17:08:01 +00:00
continue ;
}
else if ( options . m_no_synthetic_children = = false ) // let's try with synthetic children
{
2012-08-02 17:34:05 +00:00
if ( root - > IsSynthetic ( ) )
{
* first_unparsed = expression_cstr ;
* reason_to_stop = ValueObject : : eExpressionPathScanEndReasonNoSuchChild ;
* final_result = ValueObject : : eExpressionPathEndResultTypeInvalid ;
return ValueObjectSP ( ) ;
}
2012-03-19 22:58:49 +00:00
child_valobj_sp = root - > GetSyntheticValue ( true ) ;
if ( child_valobj_sp )
child_valobj_sp = child_valobj_sp - > GetChildMemberWithName ( child_name , true ) ;
2011-08-11 17:08:01 +00:00
}
// if we are here and options.m_no_synthetic_children is true, child_valobj_sp is going to be a NULL SP,
// so we hit the "else" branch, and return an error
if ( child_valobj_sp . get ( ) ) // if it worked, move on
{
root = child_valobj_sp ;
2011-07-08 02:51:01 +00:00
* first_unparsed = next_separator ;
2012-03-19 22:58:49 +00:00
* final_result = ValueObject : : eExpressionPathEndResultTypePlain ;
2011-07-08 02:51:01 +00:00
continue ;
}
else
{
* first_unparsed = expression_cstr ;
2012-03-19 22:58:49 +00:00
* reason_to_stop = ValueObject : : eExpressionPathScanEndReasonNoSuchChild ;
* final_result = ValueObject : : eExpressionPathEndResultTypeInvalid ;
2011-07-08 02:51:01 +00:00
return ValueObjectSP ( ) ;
}
}
break ;
}
case ' [ ' :
{
2011-07-12 00:18:11 +00:00
if ( ! root_clang_type_info . Test ( ClangASTContext : : eTypeIsArray ) & & ! root_clang_type_info . Test ( ClangASTContext : : eTypeIsPointer ) ) // if this is not a T[] nor a T*
2011-07-08 02:51:01 +00:00
{
2011-08-09 01:04:56 +00:00
if ( ! root_clang_type_info . Test ( ClangASTContext : : eTypeIsScalar ) ) // if this is not even a scalar...
2011-07-08 02:51:01 +00:00
{
2011-08-09 01:04:56 +00:00
if ( options . m_no_synthetic_children ) // ...only chance left is synthetic
{
* first_unparsed = expression_cstr ;
2012-03-19 22:58:49 +00:00
* reason_to_stop = ValueObject : : eExpressionPathScanEndReasonRangeOperatorInvalid ;
* final_result = ValueObject : : eExpressionPathEndResultTypeInvalid ;
2011-08-09 01:04:56 +00:00
return ValueObjectSP ( ) ;
}
2011-07-08 02:51:01 +00:00
}
else if ( ! options . m_allow_bitfields_syntax ) // if this is a scalar, check that we can expand bitfields
{
* first_unparsed = expression_cstr ;
2012-03-19 22:58:49 +00:00
* reason_to_stop = ValueObject : : eExpressionPathScanEndReasonRangeOperatorNotAllowed ;
* final_result = ValueObject : : eExpressionPathEndResultTypeInvalid ;
2011-07-08 02:51:01 +00:00
return ValueObjectSP ( ) ;
}
}
if ( * ( expression_cstr + 1 ) = = ' ] ' ) // if this is an unbounded range it only works for arrays
{
2011-07-12 00:18:11 +00:00
if ( ! root_clang_type_info . Test ( ClangASTContext : : eTypeIsArray ) )
2011-07-08 02:51:01 +00:00
{
* first_unparsed = expression_cstr ;
2012-03-19 22:58:49 +00:00
* reason_to_stop = ValueObject : : eExpressionPathScanEndReasonEmptyRangeNotAllowed ;
* final_result = ValueObject : : eExpressionPathEndResultTypeInvalid ;
2011-07-08 02:51:01 +00:00
return ValueObjectSP ( ) ;
}
else // even if something follows, we cannot expand unbounded ranges, just let the caller do it
{
* first_unparsed = expression_cstr + 2 ;
2012-03-19 22:58:49 +00:00
* reason_to_stop = ValueObject : : eExpressionPathScanEndReasonArrayRangeOperatorMet ;
* final_result = ValueObject : : eExpressionPathEndResultTypeUnboundedRange ;
2011-07-08 02:51:01 +00:00
return root ;
}
}
const char * separator_position = : : strchr ( expression_cstr + 1 , ' - ' ) ;
const char * close_bracket_position = : : strchr ( expression_cstr + 1 , ' ] ' ) ;
if ( ! close_bracket_position ) // if there is no ], this is a syntax error
{
* first_unparsed = expression_cstr ;
2012-03-19 22:58:49 +00:00
* reason_to_stop = ValueObject : : eExpressionPathScanEndReasonUnexpectedSymbol ;
* final_result = ValueObject : : eExpressionPathEndResultTypeInvalid ;
2011-07-08 02:51:01 +00:00
return ValueObjectSP ( ) ;
}
if ( ! separator_position | | separator_position > close_bracket_position ) // if no separator, this is either [] or [N]
{
char * end = NULL ;
unsigned long index = : : strtoul ( expression_cstr + 1 , & end , 0 ) ;
if ( ! end | | end ! = close_bracket_position ) // if something weird is in our way return an error
{
* first_unparsed = expression_cstr ;
2012-03-19 22:58:49 +00:00
* reason_to_stop = ValueObject : : eExpressionPathScanEndReasonUnexpectedSymbol ;
* final_result = ValueObject : : eExpressionPathEndResultTypeInvalid ;
2011-07-08 02:51:01 +00:00
return ValueObjectSP ( ) ;
}
if ( end - expression_cstr = = 1 ) // if this is [], only return a valid value for arrays
{
2011-07-12 00:18:11 +00:00
if ( root_clang_type_info . Test ( ClangASTContext : : eTypeIsArray ) )
2011-07-08 02:51:01 +00:00
{
* first_unparsed = expression_cstr + 2 ;
2012-03-19 22:58:49 +00:00
* reason_to_stop = ValueObject : : eExpressionPathScanEndReasonArrayRangeOperatorMet ;
* final_result = ValueObject : : eExpressionPathEndResultTypeUnboundedRange ;
2011-07-08 02:51:01 +00:00
return root ;
}
else
{
* first_unparsed = expression_cstr ;
2012-03-19 22:58:49 +00:00
* reason_to_stop = ValueObject : : eExpressionPathScanEndReasonEmptyRangeNotAllowed ;
* final_result = ValueObject : : eExpressionPathEndResultTypeInvalid ;
2011-07-08 02:51:01 +00:00
return ValueObjectSP ( ) ;
}
}
// from here on we do have a valid index
2011-07-12 00:18:11 +00:00
if ( root_clang_type_info . Test ( ClangASTContext : : eTypeIsArray ) )
2011-07-08 02:51:01 +00:00
{
2011-07-09 20:12:33 +00:00
ValueObjectSP child_valobj_sp = root - > GetChildAtIndex ( index , true ) ;
if ( ! child_valobj_sp )
child_valobj_sp = root - > GetSyntheticArrayMemberFromArray ( index , true ) ;
2011-08-09 01:04:56 +00:00
if ( ! child_valobj_sp )
2012-03-19 22:58:49 +00:00
if ( root - > HasSyntheticValue ( ) & & root - > GetSyntheticValue ( ) - > GetNumChildren ( ) > index )
child_valobj_sp = root - > GetSyntheticValue ( ) - > GetChildAtIndex ( index , true ) ;
2011-07-09 20:12:33 +00:00
if ( child_valobj_sp )
{
root = child_valobj_sp ;
* first_unparsed = end + 1 ; // skip ]
2012-03-19 22:58:49 +00:00
* final_result = ValueObject : : eExpressionPathEndResultTypePlain ;
2011-07-09 20:12:33 +00:00
continue ;
}
else
2011-07-08 02:51:01 +00:00
{
* first_unparsed = expression_cstr ;
2012-03-19 22:58:49 +00:00
* reason_to_stop = ValueObject : : eExpressionPathScanEndReasonNoSuchChild ;
* final_result = ValueObject : : eExpressionPathEndResultTypeInvalid ;
2011-07-08 02:51:01 +00:00
return ValueObjectSP ( ) ;
}
}
2011-07-12 00:18:11 +00:00
else if ( root_clang_type_info . Test ( ClangASTContext : : eTypeIsPointer ) )
2011-07-08 02:51:01 +00:00
{
2012-03-19 22:58:49 +00:00
if ( * what_next = = ValueObject : : eExpressionPathAftermathDereference & & // if this is a ptr-to-scalar, I am accessing it by index and I would have deref'ed anyway, then do it now and use this as a bitfield
2011-07-12 00:18:11 +00:00
pointee_clang_type_info . Test ( ClangASTContext : : eTypeIsScalar ) )
2011-07-08 02:51:01 +00:00
{
Error error ;
root = root - > Dereference ( error ) ;
if ( error . Fail ( ) | | ! root . get ( ) )
{
* first_unparsed = expression_cstr ;
2012-03-19 22:58:49 +00:00
* reason_to_stop = ValueObject : : eExpressionPathScanEndReasonDereferencingFailed ;
* final_result = ValueObject : : eExpressionPathEndResultTypeInvalid ;
2011-07-08 02:51:01 +00:00
return ValueObjectSP ( ) ;
}
else
{
2012-03-19 22:58:49 +00:00
* what_next = eExpressionPathAftermathNothing ;
2011-07-08 02:51:01 +00:00
continue ;
}
}
else
{
2011-08-09 01:04:56 +00:00
if ( ClangASTType : : GetMinimumLanguage ( root - > GetClangAST ( ) ,
2012-03-26 23:03:23 +00:00
root - > GetClangType ( ) ) = = eLanguageTypeObjC
& & ClangASTContext : : IsPointerType ( ClangASTType : : GetPointeeType ( root - > GetClangType ( ) ) ) = = false
& & root - > HasSyntheticValue ( )
& & options . m_no_synthetic_children = = false )
2011-08-09 01:04:56 +00:00
{
2012-03-19 22:58:49 +00:00
root = root - > GetSyntheticValue ( ) - > GetChildAtIndex ( index , true ) ;
2011-08-09 01:04:56 +00:00
}
else
root = root - > GetSyntheticArrayMemberFromPointer ( index , true ) ;
2011-07-08 02:51:01 +00:00
if ( ! root . get ( ) )
{
* first_unparsed = expression_cstr ;
2012-03-19 22:58:49 +00:00
* reason_to_stop = ValueObject : : eExpressionPathScanEndReasonNoSuchChild ;
* final_result = ValueObject : : eExpressionPathEndResultTypeInvalid ;
2011-07-08 02:51:01 +00:00
return ValueObjectSP ( ) ;
}
else
{
* first_unparsed = end + 1 ; // skip ]
2012-03-19 22:58:49 +00:00
* final_result = ValueObject : : eExpressionPathEndResultTypePlain ;
2011-07-08 02:51:01 +00:00
continue ;
}
}
}
2011-08-09 01:04:56 +00:00
else if ( ClangASTContext : : IsScalarType ( root_clang_type ) )
2011-07-08 02:51:01 +00:00
{
root = root - > GetSyntheticBitFieldChild ( index , index , true ) ;
if ( ! root . get ( ) )
{
* first_unparsed = expression_cstr ;
2012-03-19 22:58:49 +00:00
* reason_to_stop = ValueObject : : eExpressionPathScanEndReasonNoSuchChild ;
* final_result = ValueObject : : eExpressionPathEndResultTypeInvalid ;
2011-07-08 02:51:01 +00:00
return ValueObjectSP ( ) ;
}
else // we do not know how to expand members of bitfields, so we just return and let the caller do any further processing
{
* first_unparsed = end + 1 ; // skip ]
2012-03-19 22:58:49 +00:00
* reason_to_stop = ValueObject : : eExpressionPathScanEndReasonBitfieldRangeOperatorMet ;
* final_result = ValueObject : : eExpressionPathEndResultTypeBitfield ;
2011-07-08 02:51:01 +00:00
return root ;
}
}
2012-03-19 22:58:49 +00:00
else if ( options . m_no_synthetic_children = = false )
2011-08-09 01:04:56 +00:00
{
2012-03-19 22:58:49 +00:00
if ( root - > HasSyntheticValue ( ) )
root = root - > GetSyntheticValue ( ) ;
else if ( ! root - > IsSynthetic ( ) )
{
* first_unparsed = expression_cstr ;
* reason_to_stop = ValueObject : : eExpressionPathScanEndReasonSyntheticValueMissing ;
* final_result = ValueObject : : eExpressionPathEndResultTypeInvalid ;
return ValueObjectSP ( ) ;
}
// if we are here, then root itself is a synthetic VO.. should be good to go
2011-08-09 01:04:56 +00:00
if ( ! root . get ( ) )
{
* first_unparsed = expression_cstr ;
2012-03-19 22:58:49 +00:00
* reason_to_stop = ValueObject : : eExpressionPathScanEndReasonSyntheticValueMissing ;
* final_result = ValueObject : : eExpressionPathEndResultTypeInvalid ;
return ValueObjectSP ( ) ;
}
root = root - > GetChildAtIndex ( index , true ) ;
if ( ! root . get ( ) )
{
* first_unparsed = expression_cstr ;
* reason_to_stop = ValueObject : : eExpressionPathScanEndReasonNoSuchChild ;
* final_result = ValueObject : : eExpressionPathEndResultTypeInvalid ;
2011-08-09 01:04:56 +00:00
return ValueObjectSP ( ) ;
}
2011-08-11 17:08:01 +00:00
else
{
* first_unparsed = end + 1 ; // skip ]
2012-03-19 22:58:49 +00:00
* final_result = ValueObject : : eExpressionPathEndResultTypePlain ;
2011-08-11 17:08:01 +00:00
continue ;
}
2011-08-09 01:04:56 +00:00
}
else
{
* first_unparsed = expression_cstr ;
2012-03-19 22:58:49 +00:00
* reason_to_stop = ValueObject : : eExpressionPathScanEndReasonNoSuchChild ;
* final_result = ValueObject : : eExpressionPathEndResultTypeInvalid ;
2011-08-09 01:04:56 +00:00
return ValueObjectSP ( ) ;
}
2011-07-08 02:51:01 +00:00
}
else // we have a low and a high index
{
char * end = NULL ;
unsigned long index_lower = : : strtoul ( expression_cstr + 1 , & end , 0 ) ;
if ( ! end | | end ! = separator_position ) // if something weird is in our way return an error
{
* first_unparsed = expression_cstr ;
2012-03-19 22:58:49 +00:00
* reason_to_stop = ValueObject : : eExpressionPathScanEndReasonUnexpectedSymbol ;
* final_result = ValueObject : : eExpressionPathEndResultTypeInvalid ;
2011-07-08 02:51:01 +00:00
return ValueObjectSP ( ) ;
}
unsigned long index_higher = : : strtoul ( separator_position + 1 , & end , 0 ) ;
if ( ! end | | end ! = close_bracket_position ) // if something weird is in our way return an error
{
* first_unparsed = expression_cstr ;
2012-03-19 22:58:49 +00:00
* reason_to_stop = ValueObject : : eExpressionPathScanEndReasonUnexpectedSymbol ;
* final_result = ValueObject : : eExpressionPathEndResultTypeInvalid ;
2011-07-08 02:51:01 +00:00
return ValueObjectSP ( ) ;
}
if ( index_lower > index_higher ) // swap indices if required
{
unsigned long temp = index_lower ;
index_lower = index_higher ;
index_higher = temp ;
}
2011-07-12 00:18:11 +00:00
if ( root_clang_type_info . Test ( ClangASTContext : : eTypeIsScalar ) ) // expansion only works for scalars
2011-07-08 02:51:01 +00:00
{
root = root - > GetSyntheticBitFieldChild ( index_lower , index_higher , true ) ;
if ( ! root . get ( ) )
{
* first_unparsed = expression_cstr ;
2012-03-19 22:58:49 +00:00
* reason_to_stop = ValueObject : : eExpressionPathScanEndReasonNoSuchChild ;
* final_result = ValueObject : : eExpressionPathEndResultTypeInvalid ;
2011-07-08 02:51:01 +00:00
return ValueObjectSP ( ) ;
}
else
{
* first_unparsed = end + 1 ; // skip ]
2012-03-19 22:58:49 +00:00
* reason_to_stop = ValueObject : : eExpressionPathScanEndReasonBitfieldRangeOperatorMet ;
* final_result = ValueObject : : eExpressionPathEndResultTypeBitfield ;
2011-07-08 02:51:01 +00:00
return root ;
}
}
2011-07-12 00:18:11 +00:00
else if ( root_clang_type_info . Test ( ClangASTContext : : eTypeIsPointer ) & & // if this is a ptr-to-scalar, I am accessing it by index and I would have deref'ed anyway, then do it now and use this as a bitfield
2012-03-19 22:58:49 +00:00
* what_next = = ValueObject : : eExpressionPathAftermathDereference & &
2011-07-12 00:18:11 +00:00
pointee_clang_type_info . Test ( ClangASTContext : : eTypeIsScalar ) )
2011-07-08 02:51:01 +00:00
{
Error error ;
root = root - > Dereference ( error ) ;
if ( error . Fail ( ) | | ! root . get ( ) )
{
* first_unparsed = expression_cstr ;
2012-03-19 22:58:49 +00:00
* reason_to_stop = ValueObject : : eExpressionPathScanEndReasonDereferencingFailed ;
* final_result = ValueObject : : eExpressionPathEndResultTypeInvalid ;
2011-07-08 02:51:01 +00:00
return ValueObjectSP ( ) ;
}
else
{
2012-03-19 22:58:49 +00:00
* what_next = ValueObject : : eExpressionPathAftermathNothing ;
2011-07-08 02:51:01 +00:00
continue ;
}
}
else
{
* first_unparsed = expression_cstr ;
2012-03-19 22:58:49 +00:00
* reason_to_stop = ValueObject : : eExpressionPathScanEndReasonArrayRangeOperatorMet ;
* final_result = ValueObject : : eExpressionPathEndResultTypeBoundedRange ;
2011-07-08 02:51:01 +00:00
return root ;
}
}
break ;
}
default : // some non-separator is in the way
{
* first_unparsed = expression_cstr ;
2012-03-19 22:58:49 +00:00
* reason_to_stop = ValueObject : : eExpressionPathScanEndReasonUnexpectedSymbol ;
* final_result = ValueObject : : eExpressionPathEndResultTypeInvalid ;
2011-07-08 02:51:01 +00:00
return ValueObjectSP ( ) ;
break ;
}
}
}
}
2011-07-12 00:18:11 +00:00
int
ValueObject : : ExpandArraySliceExpression ( const char * expression_cstr ,
const char * * first_unparsed ,
2011-09-02 01:15:17 +00:00
ValueObjectSP root ,
ValueObjectListSP & list ,
2011-07-12 00:18:11 +00:00
ExpressionPathScanEndReason * reason_to_stop ,
ExpressionPathEndResultType * final_result ,
const GetValueForExpressionPathOptions & options ,
ExpressionPathAftermath * what_next )
{
if ( ! root . get ( ) )
return 0 ;
* first_unparsed = expression_cstr ;
while ( true )
{
const char * expression_cstr = * first_unparsed ; // hide the top level expression_cstr
2011-09-02 01:15:17 +00:00
clang_type_t root_clang_type = root - > GetClangType ( ) ;
clang_type_t pointee_clang_type ;
2011-07-12 00:18:11 +00:00
Flags root_clang_type_info , pointee_clang_type_info ;
root_clang_type_info = Flags ( ClangASTContext : : GetTypeInfo ( root_clang_type , GetClangAST ( ) , & pointee_clang_type ) ) ;
if ( pointee_clang_type )
pointee_clang_type_info = Flags ( ClangASTContext : : GetTypeInfo ( pointee_clang_type , GetClangAST ( ) , NULL ) ) ;
if ( ! expression_cstr | | * expression_cstr = = ' \0 ' )
{
2012-03-19 22:58:49 +00:00
* reason_to_stop = ValueObject : : eExpressionPathScanEndReasonEndOfString ;
2011-07-12 00:18:11 +00:00
list - > Append ( root ) ;
return 1 ;
}
switch ( * expression_cstr )
{
case ' [ ' :
{
if ( ! root_clang_type_info . Test ( ClangASTContext : : eTypeIsArray ) & & ! root_clang_type_info . Test ( ClangASTContext : : eTypeIsPointer ) ) // if this is not a T[] nor a T*
{
if ( ! root_clang_type_info . Test ( ClangASTContext : : eTypeIsScalar ) ) // if this is not even a scalar, this syntax is just plain wrong!
{
* first_unparsed = expression_cstr ;
2012-03-19 22:58:49 +00:00
* reason_to_stop = ValueObject : : eExpressionPathScanEndReasonRangeOperatorInvalid ;
* final_result = ValueObject : : eExpressionPathEndResultTypeInvalid ;
2011-07-12 00:18:11 +00:00
return 0 ;
}
else if ( ! options . m_allow_bitfields_syntax ) // if this is a scalar, check that we can expand bitfields
{
* first_unparsed = expression_cstr ;
2012-03-19 22:58:49 +00:00
* reason_to_stop = ValueObject : : eExpressionPathScanEndReasonRangeOperatorNotAllowed ;
* final_result = ValueObject : : eExpressionPathEndResultTypeInvalid ;
2011-07-12 00:18:11 +00:00
return 0 ;
}
}
if ( * ( expression_cstr + 1 ) = = ' ] ' ) // if this is an unbounded range it only works for arrays
{
if ( ! root_clang_type_info . Test ( ClangASTContext : : eTypeIsArray ) )
{
* first_unparsed = expression_cstr ;
2012-03-19 22:58:49 +00:00
* reason_to_stop = ValueObject : : eExpressionPathScanEndReasonEmptyRangeNotAllowed ;
* final_result = ValueObject : : eExpressionPathEndResultTypeInvalid ;
2011-07-12 00:18:11 +00:00
return 0 ;
}
else // expand this into list
{
int max_index = root - > GetNumChildren ( ) - 1 ;
for ( int index = 0 ; index < max_index ; index + + )
{
ValueObjectSP child =
root - > GetChildAtIndex ( index , true ) ;
list - > Append ( child ) ;
}
* first_unparsed = expression_cstr + 2 ;
2012-03-19 22:58:49 +00:00
* reason_to_stop = ValueObject : : eExpressionPathScanEndReasonRangeOperatorExpanded ;
* final_result = ValueObject : : eExpressionPathEndResultTypeValueObjectList ;
2011-07-12 00:18:11 +00:00
return max_index ; // tell me number of items I added to the VOList
}
}
const char * separator_position = : : strchr ( expression_cstr + 1 , ' - ' ) ;
const char * close_bracket_position = : : strchr ( expression_cstr + 1 , ' ] ' ) ;
if ( ! close_bracket_position ) // if there is no ], this is a syntax error
{
* first_unparsed = expression_cstr ;
2012-03-19 22:58:49 +00:00
* reason_to_stop = ValueObject : : eExpressionPathScanEndReasonUnexpectedSymbol ;
* final_result = ValueObject : : eExpressionPathEndResultTypeInvalid ;
2011-07-12 00:18:11 +00:00
return 0 ;
}
if ( ! separator_position | | separator_position > close_bracket_position ) // if no separator, this is either [] or [N]
{
char * end = NULL ;
unsigned long index = : : strtoul ( expression_cstr + 1 , & end , 0 ) ;
if ( ! end | | end ! = close_bracket_position ) // if something weird is in our way return an error
{
* first_unparsed = expression_cstr ;
2012-03-19 22:58:49 +00:00
* reason_to_stop = ValueObject : : eExpressionPathScanEndReasonUnexpectedSymbol ;
* final_result = ValueObject : : eExpressionPathEndResultTypeInvalid ;
2011-07-12 00:18:11 +00:00
return 0 ;
}
if ( end - expression_cstr = = 1 ) // if this is [], only return a valid value for arrays
{
if ( root_clang_type_info . Test ( ClangASTContext : : eTypeIsArray ) )
{
int max_index = root - > GetNumChildren ( ) - 1 ;
for ( int index = 0 ; index < max_index ; index + + )
{
ValueObjectSP child =
root - > GetChildAtIndex ( index , true ) ;
list - > Append ( child ) ;
}
* first_unparsed = expression_cstr + 2 ;
2012-03-19 22:58:49 +00:00
* reason_to_stop = ValueObject : : eExpressionPathScanEndReasonRangeOperatorExpanded ;
* final_result = ValueObject : : eExpressionPathEndResultTypeValueObjectList ;
2011-07-12 00:18:11 +00:00
return max_index ; // tell me number of items I added to the VOList
}
else
{
* first_unparsed = expression_cstr ;
2012-03-19 22:58:49 +00:00
* reason_to_stop = ValueObject : : eExpressionPathScanEndReasonEmptyRangeNotAllowed ;
* final_result = ValueObject : : eExpressionPathEndResultTypeInvalid ;
2011-07-12 00:18:11 +00:00
return 0 ;
}
}
// from here on we do have a valid index
if ( root_clang_type_info . Test ( ClangASTContext : : eTypeIsArray ) )
{
root = root - > GetChildAtIndex ( index , true ) ;
if ( ! root . get ( ) )
{
* first_unparsed = expression_cstr ;
2012-03-19 22:58:49 +00:00
* reason_to_stop = ValueObject : : eExpressionPathScanEndReasonNoSuchChild ;
* final_result = ValueObject : : eExpressionPathEndResultTypeInvalid ;
2011-07-12 00:18:11 +00:00
return 0 ;
}
else
{
list - > Append ( root ) ;
* first_unparsed = end + 1 ; // skip ]
2012-03-19 22:58:49 +00:00
* reason_to_stop = ValueObject : : eExpressionPathScanEndReasonRangeOperatorExpanded ;
* final_result = ValueObject : : eExpressionPathEndResultTypeValueObjectList ;
2011-07-12 00:18:11 +00:00
return 1 ;
}
}
else if ( root_clang_type_info . Test ( ClangASTContext : : eTypeIsPointer ) )
{
2012-03-19 22:58:49 +00:00
if ( * what_next = = ValueObject : : eExpressionPathAftermathDereference & & // if this is a ptr-to-scalar, I am accessing it by index and I would have deref'ed anyway, then do it now and use this as a bitfield
2011-07-12 00:18:11 +00:00
pointee_clang_type_info . Test ( ClangASTContext : : eTypeIsScalar ) )
{
Error error ;
root = root - > Dereference ( error ) ;
if ( error . Fail ( ) | | ! root . get ( ) )
{
* first_unparsed = expression_cstr ;
2012-03-19 22:58:49 +00:00
* reason_to_stop = ValueObject : : eExpressionPathScanEndReasonDereferencingFailed ;
* final_result = ValueObject : : eExpressionPathEndResultTypeInvalid ;
2011-07-12 00:18:11 +00:00
return 0 ;
}
else
{
2012-03-19 22:58:49 +00:00
* what_next = eExpressionPathAftermathNothing ;
2011-07-12 00:18:11 +00:00
continue ;
}
}
else
{
root = root - > GetSyntheticArrayMemberFromPointer ( index , true ) ;
if ( ! root . get ( ) )
{
* first_unparsed = expression_cstr ;
2012-03-19 22:58:49 +00:00
* reason_to_stop = ValueObject : : eExpressionPathScanEndReasonNoSuchChild ;
* final_result = ValueObject : : eExpressionPathEndResultTypeInvalid ;
2011-07-12 00:18:11 +00:00
return 0 ;
}
else
{
list - > Append ( root ) ;
* first_unparsed = end + 1 ; // skip ]
2012-03-19 22:58:49 +00:00
* reason_to_stop = ValueObject : : eExpressionPathScanEndReasonRangeOperatorExpanded ;
* final_result = ValueObject : : eExpressionPathEndResultTypeValueObjectList ;
2011-07-12 00:18:11 +00:00
return 1 ;
}
}
}
else /*if (ClangASTContext::IsScalarType(root_clang_type))*/
{
root = root - > GetSyntheticBitFieldChild ( index , index , true ) ;
if ( ! root . get ( ) )
{
* first_unparsed = expression_cstr ;
2012-03-19 22:58:49 +00:00
* reason_to_stop = ValueObject : : eExpressionPathScanEndReasonNoSuchChild ;
* final_result = ValueObject : : eExpressionPathEndResultTypeInvalid ;
2011-07-12 00:18:11 +00:00
return 0 ;
}
else // we do not know how to expand members of bitfields, so we just return and let the caller do any further processing
{
list - > Append ( root ) ;
* first_unparsed = end + 1 ; // skip ]
2012-03-19 22:58:49 +00:00
* reason_to_stop = ValueObject : : eExpressionPathScanEndReasonRangeOperatorExpanded ;
* final_result = ValueObject : : eExpressionPathEndResultTypeValueObjectList ;
2011-07-12 00:18:11 +00:00
return 1 ;
}
}
}
else // we have a low and a high index
{
char * end = NULL ;
unsigned long index_lower = : : strtoul ( expression_cstr + 1 , & end , 0 ) ;
if ( ! end | | end ! = separator_position ) // if something weird is in our way return an error
{
* first_unparsed = expression_cstr ;
2012-03-19 22:58:49 +00:00
* reason_to_stop = ValueObject : : eExpressionPathScanEndReasonUnexpectedSymbol ;
* final_result = ValueObject : : eExpressionPathEndResultTypeInvalid ;
2011-07-12 00:18:11 +00:00
return 0 ;
}
unsigned long index_higher = : : strtoul ( separator_position + 1 , & end , 0 ) ;
if ( ! end | | end ! = close_bracket_position ) // if something weird is in our way return an error
{
* first_unparsed = expression_cstr ;
2012-03-19 22:58:49 +00:00
* reason_to_stop = ValueObject : : eExpressionPathScanEndReasonUnexpectedSymbol ;
* final_result = ValueObject : : eExpressionPathEndResultTypeInvalid ;
2011-07-12 00:18:11 +00:00
return 0 ;
}
if ( index_lower > index_higher ) // swap indices if required
{
unsigned long temp = index_lower ;
index_lower = index_higher ;
index_higher = temp ;
}
if ( root_clang_type_info . Test ( ClangASTContext : : eTypeIsScalar ) ) // expansion only works for scalars
{
root = root - > GetSyntheticBitFieldChild ( index_lower , index_higher , true ) ;
if ( ! root . get ( ) )
{
* first_unparsed = expression_cstr ;
2012-03-19 22:58:49 +00:00
* reason_to_stop = ValueObject : : eExpressionPathScanEndReasonNoSuchChild ;
* final_result = ValueObject : : eExpressionPathEndResultTypeInvalid ;
2011-07-12 00:18:11 +00:00
return 0 ;
}
else
{
list - > Append ( root ) ;
* first_unparsed = end + 1 ; // skip ]
2012-03-19 22:58:49 +00:00
* reason_to_stop = ValueObject : : eExpressionPathScanEndReasonRangeOperatorExpanded ;
* final_result = ValueObject : : eExpressionPathEndResultTypeValueObjectList ;
2011-07-12 00:18:11 +00:00
return 1 ;
}
}
else if ( root_clang_type_info . Test ( ClangASTContext : : eTypeIsPointer ) & & // if this is a ptr-to-scalar, I am accessing it by index and I would have deref'ed anyway, then do it now and use this as a bitfield
2012-03-19 22:58:49 +00:00
* what_next = = ValueObject : : eExpressionPathAftermathDereference & &
2011-07-12 00:18:11 +00:00
pointee_clang_type_info . Test ( ClangASTContext : : eTypeIsScalar ) )
{
Error error ;
root = root - > Dereference ( error ) ;
if ( error . Fail ( ) | | ! root . get ( ) )
{
* first_unparsed = expression_cstr ;
2012-03-19 22:58:49 +00:00
* reason_to_stop = ValueObject : : eExpressionPathScanEndReasonDereferencingFailed ;
* final_result = ValueObject : : eExpressionPathEndResultTypeInvalid ;
2011-07-12 00:18:11 +00:00
return 0 ;
}
else
{
2012-03-19 22:58:49 +00:00
* what_next = ValueObject : : eExpressionPathAftermathNothing ;
2011-07-12 00:18:11 +00:00
continue ;
}
}
else
{
2011-07-19 19:48:13 +00:00
for ( unsigned long index = index_lower ;
2011-07-12 00:18:11 +00:00
index < = index_higher ; index + + )
{
ValueObjectSP child =
root - > GetChildAtIndex ( index , true ) ;
list - > Append ( child ) ;
}
* first_unparsed = end + 1 ;
2012-03-19 22:58:49 +00:00
* reason_to_stop = ValueObject : : eExpressionPathScanEndReasonRangeOperatorExpanded ;
* final_result = ValueObject : : eExpressionPathEndResultTypeValueObjectList ;
2011-07-12 00:18:11 +00:00
return index_higher - index_lower + 1 ; // tell me number of items I added to the VOList
}
}
break ;
}
default : // some non-[ separator, or something entirely wrong, is in the way
{
* first_unparsed = expression_cstr ;
2012-03-19 22:58:49 +00:00
* reason_to_stop = ValueObject : : eExpressionPathScanEndReasonUnexpectedSymbol ;
* final_result = ValueObject : : eExpressionPathEndResultTypeInvalid ;
2011-07-12 00:18:11 +00:00
return 0 ;
break ;
}
}
}
}
2012-03-01 04:24:26 +00:00
static void
DumpValueObject_Impl ( Stream & s ,
ValueObject * valobj ,
const ValueObject : : DumpValueObjectOptions & options ,
uint32_t ptr_depth ,
uint32_t curr_depth )
2010-10-05 00:00:42 +00:00
{
2011-05-30 00:49:24 +00:00
if ( valobj )
2010-10-05 00:00:42 +00:00
{
2012-03-01 04:24:26 +00:00
bool update_success = valobj - > UpdateValueIfNeeded ( options . m_use_dynamic , true ) ;
2011-05-30 00:49:24 +00:00
2012-03-01 04:24:26 +00:00
const char * root_valobj_name =
options . m_root_valobj_name . empty ( ) ?
valobj - > GetName ( ) . AsCString ( ) :
options . m_root_valobj_name . c_str ( ) ;
if ( update_success & & options . m_use_dynamic ! = eNoDynamicValues )
2011-04-16 00:01:13 +00:00
{
2012-03-01 04:24:26 +00:00
ValueObject * dynamic_value = valobj - > GetDynamicValue ( options . m_use_dynamic ) . get ( ) ;
2011-04-16 00:01:13 +00:00
if ( dynamic_value )
valobj = dynamic_value ;
}
2010-10-14 22:52:14 +00:00
clang_type_t clang_type = valobj - > GetClangType ( ) ;
2010-10-27 03:32:59 +00:00
const Flags type_flags ( ClangASTContext : : GetTypeInfo ( clang_type , NULL , NULL ) ) ;
2010-10-14 22:52:14 +00:00
const char * err_cstr = NULL ;
2010-10-27 03:32:59 +00:00
const bool has_children = type_flags . Test ( ClangASTContext : : eTypeHasChildren ) ;
const bool has_value = type_flags . Test ( ClangASTContext : : eTypeHasValue ) ;
2010-10-14 22:52:14 +00:00
2012-03-01 04:24:26 +00:00
const bool print_valobj = options . m_flat_output = = false | | has_value ;
2010-10-14 22:52:14 +00:00
if ( print_valobj )
2010-10-05 00:00:42 +00:00
{
2012-03-01 04:24:26 +00:00
if ( options . m_show_location )
2010-10-14 22:52:14 +00:00
{
2011-03-31 00:19:25 +00:00
s . Printf ( " %s: " , valobj - > GetLocationAsCString ( ) ) ;
2010-10-14 22:52:14 +00:00
}
2010-10-05 00:00:42 +00:00
2010-10-14 22:52:14 +00:00
s . Indent ( ) ;
2012-08-09 16:51:25 +00:00
bool show_type = true ;
// if we are at the root-level and been asked to hide the root's type, then hide it
if ( curr_depth = = 0 & & options . m_hide_root_type )
show_type = false ;
else
// otherwise decide according to the usual rules (asked to show types - always at the root level)
show_type = options . m_show_types | | ( curr_depth = = 0 & & ! options . m_flat_output ) ;
if ( show_type )
2011-08-02 17:27:39 +00:00
{
2012-03-26 23:03:23 +00:00
const char * typeName = valobj - > GetQualifiedTypeName ( ) . AsCString ( " <invalid type> " ) ;
//const char* typeName = valobj->GetTypeName().AsCString("<invalid type>");
2011-08-03 02:18:51 +00:00
s . Printf ( " (%s " , typeName ) ;
// only show dynamic types if the user really wants to see types
2012-03-01 04:24:26 +00:00
if ( options . m_show_types & & options . m_use_dynamic ! = eNoDynamicValues & &
2011-08-03 02:18:51 +00:00
( /*strstr(typeName, "id") == typeName ||*/
2011-09-02 01:15:17 +00:00
ClangASTType : : GetMinimumLanguage ( valobj - > GetClangAST ( ) , valobj - > GetClangType ( ) ) = = eLanguageTypeObjC ) )
2011-08-02 17:27:39 +00:00
{
2012-02-17 07:49:44 +00:00
ExecutionContext exe_ctx ( valobj - > GetExecutionContextRef ( ) ) ;
Process * process = exe_ctx . GetProcessPtr ( ) ;
2011-08-02 17:27:39 +00:00
if ( process = = NULL )
2011-08-03 02:18:51 +00:00
s . Printf ( " , dynamic type: unknown) " ) ;
2011-08-02 17:27:39 +00:00
else
{
ObjCLanguageRuntime * runtime = process - > GetObjCLanguageRuntime ( ) ;
if ( runtime = = NULL )
2011-08-03 02:18:51 +00:00
s . Printf ( " , dynamic type: unknown) " ) ;
2011-08-02 17:27:39 +00:00
else
{
2012-10-11 18:07:21 +00:00
ObjCLanguageRuntime : : ClassDescriptorSP objc_class_sp ( runtime - > GetNonKVOClassDescriptor ( * valobj ) ) ;
if ( objc_class_sp )
s . Printf ( " , dynamic type: %s) " , objc_class_sp - > GetClassName ( ) . GetCString ( ) ) ;
2011-08-02 17:27:39 +00:00
else
2012-10-11 18:07:21 +00:00
s . Printf ( " , dynamic type: unknown) " ) ;
2011-08-02 17:27:39 +00:00
}
}
}
else
s . Printf ( " ) " ) ;
}
2010-10-05 00:00:42 +00:00
2012-03-01 04:24:26 +00:00
if ( options . m_flat_output )
2010-10-14 22:52:14 +00:00
{
2011-01-17 03:46:26 +00:00
// If we are showing types, also qualify the C++ base classes
2012-03-01 04:24:26 +00:00
const bool qualify_cxx_base_classes = options . m_show_types ;
2011-01-17 03:46:26 +00:00
valobj - > GetExpressionPath ( s , qualify_cxx_base_classes ) ;
2010-10-14 22:52:14 +00:00
s . PutCString ( " = " ) ;
}
else
{
const char * name_cstr = root_valobj_name ? root_valobj_name : valobj - > GetName ( ) . AsCString ( " " ) ;
s . Printf ( " %s = " , name_cstr ) ;
}
2012-03-01 04:24:26 +00:00
if ( ! options . m_scope_already_checked & & ! valobj - > IsInScope ( ) )
2010-10-14 22:52:14 +00:00
{
2011-05-30 00:49:24 +00:00
err_cstr = " out of scope " ;
2010-10-14 22:52:14 +00:00
}
2010-10-05 00:00:42 +00:00
}
2012-03-01 04:24:26 +00:00
std : : string summary_str ;
2012-01-26 21:08:30 +00:00
std : : string value_str ;
2010-10-14 22:52:14 +00:00
const char * val_cstr = NULL ;
2011-06-29 22:27:15 +00:00
const char * sum_cstr = NULL ;
2012-03-01 04:24:26 +00:00
TypeSummaryImpl * entry = options . m_summary_sp ? options . m_summary_sp . get ( ) : valobj - > GetSummaryFormat ( ) . get ( ) ;
2010-10-14 22:52:14 +00:00
2012-03-01 04:24:26 +00:00
if ( options . m_omit_summary_depth > 0 )
2011-07-16 01:22:04 +00:00
entry = NULL ;
2012-12-13 23:50:33 +00:00
bool is_nil = valobj - > IsObjCNil ( ) ;
2010-10-14 22:52:14 +00:00
if ( err_cstr = = NULL )
{
2012-03-01 04:24:26 +00:00
if ( options . m_format ! = eFormatDefault & & options . m_format ! = valobj - > GetFormat ( ) )
2012-01-26 21:08:30 +00:00
{
2012-03-01 04:24:26 +00:00
valobj - > GetValueAsCString ( options . m_format ,
value_str ) ;
2012-01-26 21:08:30 +00:00
}
2012-03-01 04:24:26 +00:00
else
2012-01-26 21:08:30 +00:00
{
2012-03-01 04:24:26 +00:00
val_cstr = valobj - > GetValueAsCString ( ) ;
if ( val_cstr )
value_str = val_cstr ;
2012-01-26 21:08:30 +00:00
}
2010-10-14 22:52:14 +00:00
err_cstr = valobj - > GetError ( ) . AsCString ( ) ;
}
2010-10-05 00:00:42 +00:00
if ( err_cstr )
{
2011-05-30 00:49:24 +00:00
s . Printf ( " <%s> \n " , err_cstr ) ;
2010-10-05 00:00:42 +00:00
}
else
{
2010-10-27 03:32:59 +00:00
const bool is_ref = type_flags . Test ( ClangASTContext : : eTypeIsReference ) ;
2010-10-14 22:52:14 +00:00
if ( print_valobj )
2010-10-05 00:00:42 +00:00
{
2012-12-13 23:50:33 +00:00
if ( is_nil )
sum_cstr = " nil " ;
else if ( options . m_omit_summary_depth = = 0 )
2012-03-01 04:24:26 +00:00
{
if ( options . m_summary_sp )
{
valobj - > GetSummaryAsCString ( entry , summary_str ) ;
sum_cstr = summary_str . c_str ( ) ;
}
else
sum_cstr = valobj - > GetSummaryAsCString ( ) ;
}
2010-10-05 00:00:42 +00:00
2012-01-26 21:08:30 +00:00
// Make sure we have a value and make sure the summary didn't
2012-12-13 23:50:33 +00:00
// specify that the value should not be printed - and do not print
// the value if this thing is nil
if ( ! is_nil & & ! value_str . empty ( ) & & ( entry = = NULL | | entry - > DoesPrintValue ( ) | | sum_cstr = = NULL ) )
2012-01-26 21:08:30 +00:00
s . Printf ( " %s " , value_str . c_str ( ) ) ;
2010-10-14 22:52:14 +00:00
2011-07-15 23:30:15 +00:00
if ( sum_cstr )
2012-03-01 04:24:26 +00:00
s . Printf ( " %s " , sum_cstr ) ;
2010-10-14 22:52:14 +00:00
2012-12-13 23:50:33 +00:00
// let's avoid the overly verbose no description error for a nil thing
if ( options . m_use_objc & & ! is_nil )
2010-10-14 22:52:14 +00:00
{
2011-03-31 00:19:25 +00:00
const char * object_desc = valobj - > GetObjectDescription ( ) ;
2010-10-14 22:52:14 +00:00
if ( object_desc )
s . Printf ( " %s \n " , object_desc ) ;
else
2010-10-23 00:18:49 +00:00
s . Printf ( " [no Objective-C description available] \n " ) ;
2010-10-14 22:52:14 +00:00
return ;
2011-07-02 00:25:22 +00:00
}
2010-10-14 22:52:14 +00:00
}
2010-10-05 00:00:42 +00:00
2012-03-01 04:24:26 +00:00
if ( curr_depth < options . m_max_depth )
2010-10-05 00:00:42 +00:00
{
2010-10-27 03:32:59 +00:00
// We will show children for all concrete types. We won't show
// pointer contents unless a pointer depth has been specified.
// We won't reference contents unless the reference is the
// root object (depth of zero).
bool print_children = true ;
// Use a new temporary pointer depth in case we override the
// current pointer depth below...
uint32_t curr_ptr_depth = ptr_depth ;
const bool is_ptr = type_flags . Test ( ClangASTContext : : eTypeIsPointer ) ;
if ( is_ptr | | is_ref )
{
// We have a pointer or reference whose value is an address.
// Make sure that address is not NULL
2011-03-24 21:19:54 +00:00
AddressType ptr_address_type ;
2011-09-06 19:20:51 +00:00
if ( valobj - > GetPointerValue ( & ptr_address_type ) = = 0 )
2010-10-27 03:32:59 +00:00
print_children = false ;
else if ( is_ref & & curr_depth = = 0 )
{
// If this is the root object (depth is zero) that we are showing
// and it is a reference, and no pointer depth has been supplied
// print out what it references. Don't do this at deeper depths
// otherwise we can end up with infinite recursion...
curr_ptr_depth = 1 ;
}
if ( curr_ptr_depth = = 0 )
print_children = false ;
}
2010-10-05 00:00:42 +00:00
2011-07-02 00:25:22 +00:00
if ( print_children & & ( ! entry | | entry - > DoesPrintChildren ( ) | | ! sum_cstr ) )
2010-10-05 00:00:42 +00:00
{
2012-03-19 22:58:49 +00:00
ValueObject * synth_valobj ;
ValueObjectSP synth_valobj_sp = valobj - > GetSyntheticValue ( options . m_use_synthetic ) ;
synth_valobj = ( synth_valobj_sp ? synth_valobj_sp . get ( ) : valobj ) ;
2012-03-27 02:35:13 +00:00
2011-08-17 22:13:59 +00:00
uint32_t num_children = synth_valobj - > GetNumChildren ( ) ;
2011-08-12 02:00:06 +00:00
bool print_dotdotdot = false ;
2010-10-14 22:52:14 +00:00
if ( num_children )
2010-10-05 00:00:42 +00:00
{
2012-03-01 04:24:26 +00:00
if ( options . m_flat_output )
2010-10-05 00:00:42 +00:00
{
2010-10-14 22:52:14 +00:00
if ( print_valobj )
s . EOL ( ) ;
}
else
{
if ( print_valobj )
2010-10-29 04:59:35 +00:00
s . PutCString ( is_ref ? " : { \n " : " { \n " ) ;
2010-10-14 22:52:14 +00:00
s . IndentMore ( ) ;
}
2011-08-12 02:00:06 +00:00
2012-02-17 07:49:44 +00:00
uint32_t max_num_children = valobj - > GetTargetSP ( ) - > GetMaximumNumberOfChildrenToDisplay ( ) ;
2011-08-12 02:00:06 +00:00
2012-03-01 04:24:26 +00:00
if ( num_children > max_num_children & & ! options . m_ignore_cap )
2011-08-12 02:00:06 +00:00
{
num_children = max_num_children ;
print_dotdotdot = true ;
}
2010-10-14 22:52:14 +00:00
2012-03-01 04:24:26 +00:00
ValueObject : : DumpValueObjectOptions child_options ( options ) ;
2012-12-11 02:17:22 +00:00
child_options . SetFormat ( options . m_format ) . SetSummary ( ) . SetRootValueObjectName ( ) ;
2012-03-01 04:24:26 +00:00
child_options . SetScopeChecked ( true )
. SetOmitSummaryDepth ( child_options . m_omit_summary_depth > 1 ? child_options . m_omit_summary_depth - 1 : 0 ) ;
2010-10-14 22:52:14 +00:00
for ( uint32_t idx = 0 ; idx < num_children ; + + idx )
{
2011-08-17 22:13:59 +00:00
ValueObjectSP child_sp ( synth_valobj - > GetChildAtIndex ( idx , true ) ) ;
2010-10-14 22:52:14 +00:00
if ( child_sp . get ( ) )
{
2012-03-01 04:24:26 +00:00
DumpValueObject_Impl ( s ,
child_sp . get ( ) ,
child_options ,
( is_ptr | | is_ref ) ? curr_ptr_depth - 1 : curr_ptr_depth ,
curr_depth + 1 ) ;
2010-10-14 22:52:14 +00:00
}
}
2012-03-01 04:24:26 +00:00
if ( ! options . m_flat_output )
2010-10-14 22:52:14 +00:00
{
2011-08-12 02:00:06 +00:00
if ( print_dotdotdot )
2011-08-12 16:42:31 +00:00
{
2012-02-17 07:49:44 +00:00
ExecutionContext exe_ctx ( valobj - > GetExecutionContextRef ( ) ) ;
Target * target = exe_ctx . GetTargetPtr ( ) ;
if ( target )
target - > GetDebugger ( ) . GetCommandInterpreter ( ) . ChildrenTruncated ( ) ;
2011-08-12 02:00:06 +00:00
s . Indent ( " ... \n " ) ;
2011-08-12 16:42:31 +00:00
}
2010-10-14 22:52:14 +00:00
s . IndentLess ( ) ;
s . Indent ( " } \n " ) ;
2010-10-05 00:00:42 +00:00
}
}
2010-10-14 22:52:14 +00:00
else if ( has_children )
{
// Aggregate, no children...
if ( print_valobj )
2010-10-27 03:32:59 +00:00
s . PutCString ( " {} \n " ) ;
2010-10-14 22:52:14 +00:00
}
else
{
if ( print_valobj )
s . EOL ( ) ;
}
2010-10-05 00:00:42 +00:00
}
2010-10-14 22:52:14 +00:00
else
{
2010-10-05 00:00:42 +00:00
s . EOL ( ) ;
}
}
else
{
2010-10-14 22:52:14 +00:00
if ( has_children & & print_valobj )
2010-10-05 00:00:42 +00:00
{
2010-10-14 22:52:14 +00:00
s . PutCString ( " {...} \n " ) ;
2010-10-05 00:00:42 +00:00
}
}
}
}
}
2012-03-22 18:15:37 +00:00
void
ValueObject : : LogValueObject ( Log * log ,
ValueObject * valobj )
{
if ( log & & valobj )
return LogValueObject ( log , valobj , DumpValueObjectOptions : : DefaultOptions ( ) ) ;
}
void
ValueObject : : LogValueObject ( Log * log ,
ValueObject * valobj ,
const DumpValueObjectOptions & options )
{
if ( log & & valobj )
{
StreamString s ;
ValueObject : : DumpValueObject ( s , valobj , options ) ;
if ( s . GetSize ( ) )
log - > PutCString ( s . GetData ( ) ) ;
}
}
2012-03-01 04:24:26 +00:00
void
ValueObject : : DumpValueObject ( Stream & s ,
ValueObject * valobj )
{
if ( ! valobj )
return ;
DumpValueObject_Impl ( s ,
valobj ,
DumpValueObjectOptions : : DefaultOptions ( ) ,
0 ,
0 ) ;
}
void
ValueObject : : DumpValueObject ( Stream & s ,
ValueObject * valobj ,
const DumpValueObjectOptions & options )
{
DumpValueObject_Impl ( s ,
valobj ,
options ,
options . m_max_ptr_depth , // max pointer depth allowed, we will go down from here
0 // current object depth is 0 since we are just starting
) ;
}
2010-12-14 02:59:59 +00:00
ValueObjectSP
2011-03-31 00:19:25 +00:00
ValueObject : : CreateConstantValue ( const ConstString & name )
2010-12-14 02:59:59 +00:00
{
ValueObjectSP valobj_sp ;
2011-08-02 17:27:39 +00:00
if ( UpdateValueIfNeeded ( false ) & & m_error . Success ( ) )
2010-12-14 02:59:59 +00:00
{
2012-02-17 07:49:44 +00:00
ExecutionContext exe_ctx ( GetExecutionContextRef ( ) ) ;
clang : : ASTContext * ast = GetClangAST ( ) ;
DataExtractor data ;
data . SetByteOrder ( m_data . GetByteOrder ( ) ) ;
data . SetAddressByteSize ( m_data . GetAddressByteSize ( ) ) ;
2012-04-24 22:15:37 +00:00
if ( IsBitfield ( ) )
{
Value v ( Scalar ( GetValueAsUnsigned ( UINT64_MAX ) ) ) ;
m_error = v . GetValueAsData ( & exe_ctx , ast , data , 0 , GetModule ( ) . get ( ) ) ;
}
else
m_error = m_value . GetValueAsData ( & exe_ctx , ast , data , 0 , GetModule ( ) . get ( ) ) ;
2012-02-17 07:49:44 +00:00
valobj_sp = ValueObjectConstResult : : Create ( exe_ctx . GetBestExecutionContextScope ( ) ,
ast ,
GetClangType ( ) ,
name ,
data ,
GetAddressOf ( ) ) ;
2010-12-14 02:59:59 +00:00
}
2011-03-31 00:19:25 +00:00
if ( ! valobj_sp )
2010-12-14 02:59:59 +00:00
{
2011-04-22 23:53:53 +00:00
valobj_sp = ValueObjectConstResult : : Create ( NULL , m_error ) ;
2010-12-14 02:59:59 +00:00
}
return valobj_sp ;
}
2011-09-02 01:15:17 +00:00
ValueObjectSP
2010-12-20 20:49:23 +00:00
ValueObject : : Dereference ( Error & error )
2010-12-14 02:59:59 +00:00
{
2011-04-22 23:53:53 +00:00
if ( m_deref_valobj )
return m_deref_valobj - > GetSP ( ) ;
2011-04-16 00:01:13 +00:00
2010-12-15 05:08:08 +00:00
const bool is_pointer_type = IsPointerType ( ) ;
if ( is_pointer_type )
2010-12-14 02:59:59 +00:00
{
bool omit_empty_base_classes = true ;
2011-07-09 20:12:33 +00:00
bool ignore_array_bounds = false ;
2010-12-14 02:59:59 +00:00
std : : string child_name_str ;
uint32_t child_byte_size = 0 ;
int32_t child_byte_offset = 0 ;
uint32_t child_bitfield_bit_size = 0 ;
uint32_t child_bitfield_bit_offset = 0 ;
bool child_is_base_class = false ;
2011-01-21 01:59:00 +00:00
bool child_is_deref_of_parent = false ;
2010-12-14 02:59:59 +00:00
const bool transparent_pointers = false ;
clang : : ASTContext * clang_ast = GetClangAST ( ) ;
clang_type_t clang_type = GetClangType ( ) ;
clang_type_t child_clang_type ;
2011-06-24 22:03:24 +00:00
2012-02-17 07:49:44 +00:00
ExecutionContext exe_ctx ( GetExecutionContextRef ( ) ) ;
2011-06-24 22:03:24 +00:00
child_clang_type = ClangASTContext : : GetChildClangTypeAtIndex ( & exe_ctx ,
clang_ast ,
2010-12-14 02:59:59 +00:00
GetName ( ) . GetCString ( ) ,
clang_type ,
0 ,
transparent_pointers ,
omit_empty_base_classes ,
2011-07-09 20:12:33 +00:00
ignore_array_bounds ,
2010-12-14 02:59:59 +00:00
child_name_str ,
child_byte_size ,
child_byte_offset ,
child_bitfield_bit_size ,
child_bitfield_bit_offset ,
2011-01-21 01:59:00 +00:00
child_is_base_class ,
child_is_deref_of_parent ) ;
2011-01-09 21:07:35 +00:00
if ( child_clang_type & & child_byte_size )
2010-12-14 02:59:59 +00:00
{
ConstString child_name ;
if ( ! child_name_str . empty ( ) )
child_name . SetCString ( child_name_str . c_str ( ) ) ;
2011-04-22 23:53:53 +00:00
m_deref_valobj = new ValueObjectChild ( * this ,
clang_ast ,
child_clang_type ,
child_name ,
child_byte_size ,
child_byte_offset ,
child_bitfield_bit_size ,
child_bitfield_bit_offset ,
child_is_base_class ,
2011-09-06 19:20:51 +00:00
child_is_deref_of_parent ,
eAddressTypeInvalid ) ;
2010-12-14 02:59:59 +00:00
}
}
2010-12-15 05:08:08 +00:00
2011-04-22 23:53:53 +00:00
if ( m_deref_valobj )
2010-12-15 05:08:08 +00:00
{
error . Clear ( ) ;
2011-04-22 23:53:53 +00:00
return m_deref_valobj - > GetSP ( ) ;
2010-12-15 05:08:08 +00:00
}
2010-12-14 02:59:59 +00:00
else
{
2010-12-15 05:08:08 +00:00
StreamString strm ;
2011-01-17 03:46:26 +00:00
GetExpressionPath ( strm , true ) ;
2010-12-15 05:08:08 +00:00
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 ( ) ) ;
2011-04-22 23:53:53 +00:00
return ValueObjectSP ( ) ;
2010-12-14 02:59:59 +00:00
}
}
2011-09-02 01:15:17 +00:00
ValueObjectSP
2010-12-15 05:08:08 +00:00
ValueObject : : AddressOf ( Error & error )
2010-12-14 02:59:59 +00:00
{
2011-04-16 00:01:13 +00:00
if ( m_addr_of_valobj_sp )
return m_addr_of_valobj_sp ;
2011-03-24 21:19:54 +00:00
AddressType address_type = eAddressTypeInvalid ;
2010-12-14 02:59:59 +00:00
const bool scalar_is_load_address = false ;
2011-09-06 19:20:51 +00:00
addr_t addr = GetAddressOf ( scalar_is_load_address , & address_type ) ;
2010-12-15 05:08:08 +00:00
error . Clear ( ) ;
2010-12-14 02:59:59 +00:00
if ( addr ! = LLDB_INVALID_ADDRESS )
{
switch ( address_type )
{
case eAddressTypeInvalid :
2010-12-15 05:08:08 +00:00
{
StreamString expr_path_strm ;
2011-01-17 03:46:26 +00:00
GetExpressionPath ( expr_path_strm , true ) ;
2010-12-15 05:08:08 +00:00
error . SetErrorStringWithFormat ( " '%s' is not in memory " , expr_path_strm . GetString ( ) . c_str ( ) ) ;
}
2010-12-14 02:59:59 +00:00
break ;
2010-12-15 05:08:08 +00:00
2010-12-14 02:59:59 +00:00
case eAddressTypeFile :
case eAddressTypeLoad :
case eAddressTypeHost :
{
clang : : ASTContext * ast = GetClangAST ( ) ;
clang_type_t clang_type = GetClangType ( ) ;
if ( ast & & clang_type )
{
std : : string name ( 1 , ' & ' ) ;
name . append ( m_name . AsCString ( " " ) ) ;
2012-02-17 07:49:44 +00:00
ExecutionContext exe_ctx ( GetExecutionContextRef ( ) ) ;
m_addr_of_valobj_sp = ValueObjectConstResult : : Create ( exe_ctx . GetBestExecutionContextScope ( ) ,
2011-04-22 23:53:53 +00:00
ast ,
ClangASTContext : : CreatePointerType ( ast , clang_type ) ,
ConstString ( name . c_str ( ) ) ,
addr ,
eAddressTypeInvalid ,
m_data . GetAddressByteSize ( ) ) ;
2010-12-14 02:59:59 +00:00
}
}
break ;
}
}
2011-04-16 00:01:13 +00:00
return m_addr_of_valobj_sp ;
2010-12-14 02:59:59 +00:00
}
2012-02-03 05:34:10 +00:00
ValueObjectSP
ValueObject : : Cast ( const ClangASTType & clang_ast_type )
{
2012-02-04 02:27:34 +00:00
return ValueObjectCast : : Create ( * this , GetName ( ) , clang_ast_type ) ;
2012-02-03 05:34:10 +00:00
}
2011-05-05 23:32:56 +00:00
2011-09-02 01:15:17 +00:00
ValueObjectSP
2011-05-05 23:32:56 +00:00
ValueObject : : CastPointerType ( const char * name , ClangASTType & clang_ast_type )
{
2011-09-02 01:15:17 +00:00
ValueObjectSP valobj_sp ;
2011-05-05 23:32:56 +00:00
AddressType address_type ;
2011-09-06 19:20:51 +00:00
addr_t ptr_value = GetPointerValue ( & address_type ) ;
2011-05-05 23:32:56 +00:00
if ( ptr_value ! = LLDB_INVALID_ADDRESS )
{
2012-02-24 01:59:29 +00:00
Address ptr_addr ( ptr_value ) ;
2012-02-17 07:49:44 +00:00
ExecutionContext exe_ctx ( GetExecutionContextRef ( ) ) ;
valobj_sp = ValueObjectMemory : : Create ( exe_ctx . GetBestExecutionContextScope ( ) ,
2011-05-05 23:32:56 +00:00
name ,
ptr_addr ,
clang_ast_type ) ;
}
return valobj_sp ;
}
2011-09-02 01:15:17 +00:00
ValueObjectSP
2011-05-05 23:32:56 +00:00
ValueObject : : CastPointerType ( const char * name , TypeSP & type_sp )
{
2011-09-02 01:15:17 +00:00
ValueObjectSP valobj_sp ;
2011-05-05 23:32:56 +00:00
AddressType address_type ;
2011-09-06 19:20:51 +00:00
addr_t ptr_value = GetPointerValue ( & address_type ) ;
2011-05-05 23:32:56 +00:00
if ( ptr_value ! = LLDB_INVALID_ADDRESS )
{
2012-02-24 01:59:29 +00:00
Address ptr_addr ( ptr_value ) ;
2012-02-17 07:49:44 +00:00
ExecutionContext exe_ctx ( GetExecutionContextRef ( ) ) ;
valobj_sp = ValueObjectMemory : : Create ( exe_ctx . GetBestExecutionContextScope ( ) ,
2011-05-05 23:32:56 +00:00
name ,
ptr_addr ,
type_sp ) ;
}
return valobj_sp ;
}
2011-03-31 00:19:25 +00:00
ValueObject : : EvaluationPoint : : EvaluationPoint ( ) :
2012-02-17 07:49:44 +00:00
m_mod_id ( ) ,
m_exe_ctx_ref ( ) ,
m_needs_update ( true ) ,
m_first_update ( true )
2011-03-31 00:19:25 +00:00
{
}
ValueObject : : EvaluationPoint : : EvaluationPoint ( ExecutionContextScope * exe_scope , bool use_selected ) :
2012-02-17 07:49:44 +00:00
m_mod_id ( ) ,
m_exe_ctx_ref ( ) ,
2011-03-31 00:19:25 +00:00
m_needs_update ( true ) ,
2012-02-17 07:49:44 +00:00
m_first_update ( true )
2011-03-31 00:19:25 +00:00
{
2012-02-17 07:49:44 +00:00
ExecutionContext exe_ctx ( exe_scope ) ;
TargetSP target_sp ( exe_ctx . GetTargetSP ( ) ) ;
if ( target_sp )
2011-03-31 00:19:25 +00:00
{
2012-02-17 07:49:44 +00:00
m_exe_ctx_ref . SetTargetSP ( target_sp ) ;
ProcessSP process_sp ( exe_ctx . GetProcessSP ( ) ) ;
if ( ! process_sp )
process_sp = target_sp - > GetProcessSP ( ) ;
2011-03-31 00:19:25 +00:00
2012-02-17 07:49:44 +00:00
if ( process_sp )
2011-03-31 00:19:25 +00:00
{
2012-02-17 07:49:44 +00:00
m_mod_id = process_sp - > GetModID ( ) ;
m_exe_ctx_ref . SetProcessSP ( process_sp ) ;
2011-08-09 02:12:22 +00:00
2012-02-17 07:49:44 +00:00
ThreadSP thread_sp ( exe_ctx . GetThreadSP ( ) ) ;
2011-03-31 00:19:25 +00:00
2012-02-17 07:49:44 +00:00
if ( ! thread_sp )
2011-03-31 00:19:25 +00:00
{
if ( use_selected )
2012-02-17 07:49:44 +00:00
thread_sp = process_sp - > GetThreadList ( ) . GetSelectedThread ( ) ;
2011-03-31 00:19:25 +00:00
}
2012-02-17 07:49:44 +00:00
if ( thread_sp )
2011-03-31 00:19:25 +00:00
{
2012-02-17 07:49:44 +00:00
m_exe_ctx_ref . SetThreadSP ( thread_sp ) ;
2011-09-22 04:58:26 +00:00
2012-02-17 07:49:44 +00:00
StackFrameSP frame_sp ( exe_ctx . GetFrameSP ( ) ) ;
if ( ! frame_sp )
2011-03-31 00:19:25 +00:00
{
if ( use_selected )
2012-02-17 07:49:44 +00:00
frame_sp = thread_sp - > GetSelectedFrame ( ) ;
2011-03-31 00:19:25 +00:00
}
2012-02-17 07:49:44 +00:00
if ( frame_sp )
m_exe_ctx_ref . SetFrameSP ( frame_sp ) ;
2011-03-31 00:19:25 +00:00
}
}
}
}
ValueObject : : EvaluationPoint : : EvaluationPoint ( const ValueObject : : EvaluationPoint & rhs ) :
2012-02-17 07:49:44 +00:00
m_mod_id ( ) ,
m_exe_ctx_ref ( rhs . m_exe_ctx_ref ) ,
m_needs_update ( true ) ,
m_first_update ( true )
2011-03-31 00:19:25 +00:00
{
}
ValueObject : : EvaluationPoint : : ~ EvaluationPoint ( )
{
}
// This function checks the EvaluationPoint against the current process state. If the current
// state matches the evaluation point, or the evaluation point is already invalid, then we return
// false, meaning "no change". If the current state is different, we update our state, and return
// true meaning "yes, change". If we did see a change, we also set m_needs_update to true, so
// future calls to NeedsUpdate will return true.
2011-12-10 01:49:43 +00:00
// exe_scope will be set to the current execution context scope.
2011-03-31 00:19:25 +00:00
bool
2012-02-17 07:49:44 +00:00
ValueObject : : EvaluationPoint : : SyncWithProcessState ( )
2011-03-31 00:19:25 +00:00
{
2011-12-17 01:35:57 +00:00
// Start with the target, if it is NULL, then we're obviously not going to get any further:
2012-02-17 07:49:44 +00:00
ExecutionContext exe_ctx ( m_exe_ctx_ref . Lock ( ) ) ;
2011-12-17 01:35:57 +00:00
2012-02-17 07:49:44 +00:00
if ( exe_ctx . GetTargetPtr ( ) = = NULL )
2011-12-17 01:35:57 +00:00
return false ;
2011-03-31 00:19:25 +00:00
// If we don't have a process nothing can change.
2012-02-17 07:49:44 +00:00
Process * process = exe_ctx . GetProcessPtr ( ) ;
if ( process = = NULL )
2011-03-31 00:19:25 +00:00
return false ;
2011-12-17 01:35:57 +00:00
2011-03-31 00:19:25 +00:00
// If our stop id is the current stop ID, nothing has changed:
2012-02-17 07:49:44 +00:00
ProcessModID current_mod_id = process - > GetModID ( ) ;
2011-08-09 02:12:22 +00:00
2011-04-16 00:01:13 +00:00
// If the current stop id is 0, either we haven't run yet, or the process state has been cleared.
// In either case, we aren't going to be able to sync with the process state.
2011-08-09 02:12:22 +00:00
if ( current_mod_id . GetStopID ( ) = = 0 )
2011-04-16 00:01:13 +00:00
return false ;
2011-12-10 01:49:43 +00:00
2012-07-17 03:23:13 +00:00
bool changed = false ;
const bool was_valid = m_mod_id . IsValid ( ) ;
if ( was_valid )
2011-08-12 21:40:01 +00:00
{
if ( m_mod_id = = current_mod_id )
{
2012-01-12 22:42:34 +00:00
// Everything is already up to date in this object, no need to
2011-08-12 21:40:01 +00:00
// update the execution context scope.
2011-12-10 01:49:43 +00:00
changed = false ;
2011-08-12 21:40:01 +00:00
}
2011-12-10 01:49:43 +00:00
else
{
m_mod_id = current_mod_id ;
m_needs_update = true ;
changed = true ;
}
2011-08-12 21:40:01 +00:00
}
2011-03-31 00:19:25 +00:00
2011-12-17 01:35:57 +00:00
// Now re-look up the thread and frame in case the underlying objects have gone away & been recreated.
// That way we'll be sure to return a valid exe_scope.
// If we used to have a thread or a frame but can't find it anymore, then mark ourselves as invalid.
2011-03-31 00:19:25 +00:00
2012-02-17 07:49:44 +00:00
if ( m_exe_ctx_ref . HasThreadRef ( ) )
2011-03-31 00:19:25 +00:00
{
2012-02-17 07:49:44 +00:00
ThreadSP thread_sp ( m_exe_ctx_ref . GetThreadSP ( ) ) ;
if ( thread_sp )
2011-07-06 16:49:27 +00:00
{
2012-02-17 07:49:44 +00:00
if ( m_exe_ctx_ref . HasFrameRef ( ) )
{
StackFrameSP frame_sp ( m_exe_ctx_ref . GetFrameSP ( ) ) ;
if ( ! frame_sp )
{
// We used to have a frame, but now it is gone
SetInvalid ( ) ;
2012-07-17 03:23:13 +00:00
changed = was_valid ;
2012-02-17 07:49:44 +00:00
}
}
2011-07-06 16:49:27 +00:00
}
2011-03-31 00:19:25 +00:00
else
{
2012-02-17 07:49:44 +00:00
// We used to have a thread, but now it is gone
SetInvalid ( ) ;
2012-07-17 03:23:13 +00:00
changed = was_valid ;
2011-03-31 00:19:25 +00:00
}
2012-02-17 07:49:44 +00:00
2011-03-31 00:19:25 +00:00
}
2011-12-10 01:49:43 +00:00
return changed ;
2011-03-31 00:19:25 +00:00
}
2011-05-02 18:13:59 +00:00
void
ValueObject : : EvaluationPoint : : SetUpdated ( )
{
2012-02-17 07:49:44 +00:00
ProcessSP process_sp ( m_exe_ctx_ref . GetProcessSP ( ) ) ;
if ( process_sp )
m_mod_id = process_sp - > GetModID ( ) ;
2011-05-02 18:13:59 +00:00
m_first_update = false ;
m_needs_update = false ;
}
2012-02-17 07:49:44 +00:00
//bool
//ValueObject::EvaluationPoint::SetContext (ExecutionContextScope *exe_scope)
//{
// if (!IsValid())
// return false;
//
// bool needs_update = false;
//
// // The target has to be non-null, and the
// Target *target = exe_scope->CalculateTarget();
// if (target != NULL)
// {
// Target *old_target = m_target_sp.get();
// assert (target == old_target);
// Process *process = exe_scope->CalculateProcess();
// if (process != NULL)
// {
// // FOR NOW - assume you can't update variable objects across process boundaries.
// Process *old_process = m_process_sp.get();
// assert (process == old_process);
// ProcessModID current_mod_id = process->GetModID();
// if (m_mod_id != current_mod_id)
// {
// needs_update = true;
// m_mod_id = current_mod_id;
// }
// // See if we're switching the thread or stack context. If no thread is given, this is
// // being evaluated in a global context.
// Thread *thread = exe_scope->CalculateThread();
// if (thread != NULL)
// {
// user_id_t new_thread_index = thread->GetIndexID();
// if (new_thread_index != m_thread_id)
// {
// needs_update = true;
// m_thread_id = new_thread_index;
// m_stack_id.Clear();
// }
//
// StackFrame *new_frame = exe_scope->CalculateStackFrame();
// if (new_frame != NULL)
// {
// if (new_frame->GetStackID() != m_stack_id)
// {
// needs_update = true;
// m_stack_id = new_frame->GetStackID();
// }
// }
// else
// {
// m_stack_id.Clear();
// needs_update = true;
// }
// }
// else
// {
// // If this had been given a thread, and now there is none, we should update.
// // Otherwise we don't have to do anything.
// if (m_thread_id != LLDB_INVALID_UID)
// {
// m_thread_id = LLDB_INVALID_UID;
// m_stack_id.Clear();
// needs_update = true;
// }
// }
// }
// else
// {
// // If there is no process, then we don't need to update anything.
// // But if we're switching from having a process to not, we should try to update.
// if (m_process_sp.get() != NULL)
// {
// needs_update = true;
// m_process_sp.reset();
// m_thread_id = LLDB_INVALID_UID;
// m_stack_id.Clear();
// }
// }
// }
// else
// {
// // If there's no target, nothing can change so we don't need to update anything.
// // But if we're switching from having a target to not, we should try to update.
// if (m_target_sp.get() != NULL)
// {
// needs_update = true;
// m_target_sp.reset();
// m_process_sp.reset();
// m_thread_id = LLDB_INVALID_UID;
// m_stack_id.Clear();
// }
// }
// if (!m_needs_update)
// m_needs_update = needs_update;
//
// return needs_update;
//}
2011-07-15 02:26:42 +00:00
void
2012-03-19 22:58:49 +00:00
ValueObject : : ClearUserVisibleData ( uint32_t clear_mask )
2011-07-15 02:26:42 +00:00
{
2012-03-19 22:58:49 +00:00
if ( ( clear_mask & eClearUserVisibleDataItemsValue ) = = eClearUserVisibleDataItemsValue )
m_value_str . clear ( ) ;
if ( ( clear_mask & eClearUserVisibleDataItemsLocation ) = = eClearUserVisibleDataItemsLocation )
m_location_str . clear ( ) ;
if ( ( clear_mask & eClearUserVisibleDataItemsSummary ) = = eClearUserVisibleDataItemsSummary )
{
m_summary_str . clear ( ) ;
}
if ( ( clear_mask & eClearUserVisibleDataItemsDescription ) = = eClearUserVisibleDataItemsDescription )
m_object_desc_str . clear ( ) ;
if ( ( clear_mask & eClearUserVisibleDataItemsSyntheticChildren ) = = eClearUserVisibleDataItemsSyntheticChildren )
{
if ( m_synthetic_value )
m_synthetic_value = NULL ;
}
2011-07-19 19:48:13 +00:00
}
2011-09-06 19:20:51 +00:00
SymbolContextScope *
ValueObject : : GetSymbolContextScope ( )
{
if ( m_parent )
{
if ( ! m_parent - > IsPointerOrReferenceType ( ) )
return m_parent - > GetSymbolContextScope ( ) ;
}
return NULL ;
}
2012-09-13 18:27:09 +00:00
lldb : : ValueObjectSP
ValueObject : : CreateValueObjectFromExpression ( const char * name ,
const char * expression ,
const ExecutionContext & exe_ctx )
{
lldb : : ValueObjectSP retval_sp ;
lldb : : TargetSP target_sp ( exe_ctx . GetTargetSP ( ) ) ;
if ( ! target_sp )
return retval_sp ;
if ( ! expression | | ! * expression )
return retval_sp ;
target_sp - > EvaluateExpression ( expression ,
exe_ctx . GetFrameSP ( ) . get ( ) ,
retval_sp ) ;
if ( retval_sp & & name & & * name )
retval_sp - > SetName ( ConstString ( name ) ) ;
return retval_sp ;
}
lldb : : ValueObjectSP
ValueObject : : CreateValueObjectFromAddress ( const char * name ,
uint64_t address ,
const ExecutionContext & exe_ctx ,
ClangASTType type )
{
ClangASTType pointer_type ( type . GetASTContext ( ) , type . GetPointerType ( ) ) ;
lldb : : DataBufferSP buffer ( new lldb_private : : DataBufferHeap ( & address , sizeof ( lldb : : addr_t ) ) ) ;
lldb : : ValueObjectSP ptr_result_valobj_sp ( ValueObjectConstResult : : Create ( exe_ctx . GetBestExecutionContextScope ( ) ,
pointer_type . GetASTContext ( ) ,
pointer_type . GetOpaqueQualType ( ) ,
ConstString ( name ) ,
buffer ,
lldb : : endian : : InlHostByteOrder ( ) ,
exe_ctx . GetAddressByteSize ( ) ) ) ;
if ( ptr_result_valobj_sp )
{
ptr_result_valobj_sp - > GetValue ( ) . SetValueType ( Value : : eValueTypeLoadAddress ) ;
Error err ;
ptr_result_valobj_sp = ptr_result_valobj_sp - > Dereference ( err ) ;
if ( ptr_result_valobj_sp & & name & & * name )
ptr_result_valobj_sp - > SetName ( ConstString ( name ) ) ;
}
return ptr_result_valobj_sp ;
}
lldb : : ValueObjectSP
ValueObject : : CreateValueObjectFromData ( const char * name ,
DataExtractor & data ,
const ExecutionContext & exe_ctx ,
ClangASTType type )
{
lldb : : ValueObjectSP new_value_sp ;
new_value_sp = ValueObjectConstResult : : Create ( exe_ctx . GetBestExecutionContextScope ( ) ,
type . GetASTContext ( ) ,
type . GetOpaqueQualType ( ) ,
ConstString ( name ) ,
data ,
LLDB_INVALID_ADDRESS ) ;
new_value_sp - > SetAddressTypeOfChildren ( eAddressTypeLoad ) ;
if ( new_value_sp & & name & & * name )
new_value_sp - > SetName ( ConstString ( name ) ) ;
return new_value_sp ;
}