2010-08-27 01:01:44 +00:00
//===-- ClangUserExpression.cpp -------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// C Includes
# include <stdio.h>
# if HAVE_SYS_TYPES_H
# include <sys / types.h>
# endif
// C++ Includes
# include <cstdlib>
# include <string>
# include <map>
# include "lldb/Core/ConstString.h"
# include "lldb/Core/Log.h"
# include "lldb/Core/StreamString.h"
2010-10-05 03:13:51 +00:00
# include "lldb/Core/ValueObjectConstResult.h"
2010-08-27 01:01:44 +00:00
# include "lldb/Expression/ClangExpressionDeclMap.h"
# include "lldb/Expression/ClangExpressionParser.h"
# include "lldb/Expression/ClangFunction.h"
# include "lldb/Expression/ASTResultSynthesizer.h"
# include "lldb/Expression/ClangUserExpression.h"
# include "lldb/Host/Host.h"
2010-09-21 00:44:12 +00:00
# include "lldb/Symbol/VariableList.h"
2010-08-27 01:01:44 +00:00
# include "lldb/Target/ExecutionContext.h"
2010-11-04 01:54:29 +00:00
# include "lldb/Target/Process.h"
2010-09-21 00:44:12 +00:00
# include "lldb/Target/StackFrame.h"
2010-08-27 01:01:44 +00:00
# include "lldb/Target/Target.h"
2010-11-30 02:22:11 +00:00
# include "lldb/Target/ThreadPlan.h"
# include "lldb/Target/ThreadPlanCallUserExpression.h"
2010-08-27 01:01:44 +00:00
using namespace lldb_private ;
2010-10-29 00:29:03 +00:00
ClangUserExpression : : ClangUserExpression ( const char * expr ,
const char * expr_prefix ) :
2010-08-27 01:01:44 +00:00
m_expr_text ( expr ) ,
2010-10-29 20:19:44 +00:00
m_expr_prefix ( expr_prefix ? expr_prefix : " " ) ,
2010-09-21 00:44:12 +00:00
m_transformed_text ( ) ,
m_jit_addr ( LLDB_INVALID_ADDRESS ) ,
m_cplusplus ( false ) ,
m_objectivec ( false ) ,
2010-11-19 02:52:21 +00:00
m_needs_object_ptr ( false ) ,
2010-12-01 21:35:54 +00:00
m_const_object ( false ) ,
2010-11-19 02:52:21 +00:00
m_desired_type ( NULL , NULL )
2010-08-27 01:01:44 +00:00
{
}
2010-08-27 23:31:21 +00:00
ClangUserExpression : : ~ ClangUserExpression ( )
{
}
2010-08-27 01:01:44 +00:00
clang : : ASTConsumer *
ClangUserExpression : : ASTTransformer ( clang : : ASTConsumer * passthrough )
{
2010-11-19 02:52:21 +00:00
return new ASTResultSynthesizer ( passthrough ,
m_desired_type ) ;
2010-08-27 01:01:44 +00:00
}
2010-09-21 00:44:12 +00:00
void
ClangUserExpression : : ScanContext ( ExecutionContext & exe_ctx )
{
if ( ! exe_ctx . frame )
return ;
VariableList * vars = exe_ctx . frame - > GetVariableList ( false ) ;
if ( ! vars )
return ;
2010-12-01 21:35:54 +00:00
lldb : : VariableSP this_var ( vars - > FindVariable ( ConstString ( " this " ) ) ) ;
lldb : : VariableSP self_var ( vars - > FindVariable ( ConstString ( " self " ) ) ) ;
if ( this_var . get ( ) )
{
Type * this_type = this_var - > GetType ( ) ;
lldb : : clang_type_t pointer_target_type ;
if ( ClangASTContext : : IsPointerType ( this_type - > GetClangType ( ) ,
& pointer_target_type ) )
{
TypeFromUser target_ast_type ( pointer_target_type , this_type - > GetClangAST ( ) ) ;
if ( target_ast_type . IsDefined ( ) )
m_cplusplus = true ;
if ( target_ast_type . IsConst ( ) )
m_const_object = true ;
}
}
else if ( self_var . get ( ) )
{
2010-09-21 00:44:12 +00:00
m_objectivec = true ;
2010-12-01 21:35:54 +00:00
}
2010-09-21 00:44:12 +00:00
}
2010-10-22 23:25:16 +00:00
// This is a really nasty hack, meant to fix Objective-C expressions of the form
// (int)[myArray count]. Right now, because the type information for count is
// not available, [myArray count] returns id, which can't be directly cast to
// int without causing a clang error.
static void
ApplyObjcCastHack ( std : : string & expr )
{
# define OBJC_CAST_HACK_FROM "(int)["
# define OBJC_CAST_HACK_TO "(int)(long long)["
size_t from_offset ;
while ( ( from_offset = expr . find ( OBJC_CAST_HACK_FROM ) ) ! = expr . npos )
expr . replace ( from_offset , sizeof ( OBJC_CAST_HACK_FROM ) - 1 , OBJC_CAST_HACK_TO ) ;
# undef OBJC_CAST_HACK_TO
# undef OBJC_CAST_HACK_FROM
}
2010-10-24 20:45:49 +00:00
// Another hack, meant to allow use of unichar despite it not being available in
// the type information. Although we could special-case it in type lookup,
// hopefully we'll figure out a way to #include the same environment as is
// present in the original source file rather than try to hack specific type
// definitions in as needed.
static void
ApplyUnicharHack ( std : : string & expr )
{
# define UNICHAR_HACK_FROM "unichar"
# define UNICHAR_HACK_TO "unsigned short"
size_t from_offset ;
while ( ( from_offset = expr . find ( UNICHAR_HACK_FROM ) ) ! = expr . npos )
expr . replace ( from_offset , sizeof ( UNICHAR_HACK_FROM ) - 1 , UNICHAR_HACK_TO ) ;
# undef UNICHAR_HACK_TO
# undef UNICHAR_HACK_FROM
}
2010-10-22 23:25:16 +00:00
bool
2010-11-19 02:52:21 +00:00
ClangUserExpression : : Parse ( Stream & error_stream ,
ExecutionContext & exe_ctx ,
TypeFromUser desired_type )
2010-08-27 01:01:44 +00:00
{
2010-11-06 01:53:30 +00:00
lldb : : LogSP log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2010-08-27 01:01:44 +00:00
2010-09-21 00:44:12 +00:00
ScanContext ( exe_ctx ) ;
StreamString m_transformed_stream ;
////////////////////////////////////
// Generate the expression
//
2010-10-22 23:25:16 +00:00
ApplyObjcCastHack ( m_expr_text ) ;
2010-10-27 03:32:59 +00:00
//ApplyUnicharHack(m_expr_text);
2010-09-21 00:44:12 +00:00
if ( m_cplusplus )
{
2010-10-29 00:29:03 +00:00
m_transformed_stream . Printf ( " %s \n "
" typedef unsigned short unichar; \n "
2010-10-27 03:32:59 +00:00
" void \n "
2010-12-01 21:35:54 +00:00
" $__lldb_class::%s(void *$__lldb_arg) %s \n "
2010-09-21 00:44:12 +00:00
" { \n "
" %s; \n "
" } \n " ,
2010-10-29 00:29:03 +00:00
m_expr_prefix . c_str ( ) ,
2010-09-21 00:44:12 +00:00
FunctionName ( ) ,
2010-12-01 21:35:54 +00:00
( m_const_object ? " const " : " " ) ,
2010-09-21 00:44:12 +00:00
m_expr_text . c_str ( ) ) ;
m_needs_object_ptr = true ;
}
else
{
2010-10-29 00:29:03 +00:00
m_transformed_stream . Printf ( " %s \n "
" typedef unsigned short unichar; \n "
2010-10-27 03:32:59 +00:00
" void \n "
2010-10-22 23:25:16 +00:00
" %s(void *$__lldb_arg) \n "
2010-09-21 00:44:12 +00:00
" { \n "
" %s; \n "
" } \n " ,
2010-10-29 00:29:03 +00:00
m_expr_prefix . c_str ( ) ,
2010-09-21 00:44:12 +00:00
FunctionName ( ) ,
m_expr_text . c_str ( ) ) ;
}
m_transformed_text = m_transformed_stream . GetData ( ) ;
if ( log )
log - > Printf ( " Parsing the following code: \n %s " , m_transformed_text . c_str ( ) ) ;
2010-08-27 01:01:44 +00:00
////////////////////////////////////
// Set up the target and compiler
//
Target * target = exe_ctx . target ;
if ( ! target )
{
error_stream . PutCString ( " error: invalid target \n " ) ;
return false ;
}
ConstString target_triple ;
target - > GetTargetTriple ( target_triple ) ;
if ( ! target_triple )
target_triple = Host : : GetTargetTriple ( ) ;
if ( ! target_triple )
{
error_stream . PutCString ( " error: invalid target triple \n " ) ;
return false ;
}
//////////////////////////
// Parse the expression
//
2010-11-19 02:52:21 +00:00
m_desired_type = desired_type ;
2010-12-03 01:38:59 +00:00
m_expr_decl_map . reset ( new ClangExpressionDeclMap ( ) ) ;
m_expr_decl_map - > WillParse ( exe_ctx ) ;
2010-08-27 01:01:44 +00:00
ClangExpressionParser parser ( target_triple . GetCString ( ) , * this ) ;
unsigned num_errors = parser . Parse ( error_stream ) ;
if ( num_errors )
{
error_stream . Printf ( " error: %d errors parsing expression \n " , num_errors ) ;
2010-12-03 01:38:59 +00:00
m_expr_decl_map - > DidParse ( ) ;
2010-08-27 01:01:44 +00:00
return false ;
}
///////////////////////////////////////////////
// Convert the output of the parser to DWARF
//
m_dwarf_opcodes . reset ( new StreamString ) ;
m_dwarf_opcodes - > SetByteOrder ( lldb : : eByteOrderHost ) ;
m_dwarf_opcodes - > GetFlags ( ) . Set ( Stream : : eBinary ) ;
m_local_variables . reset ( new ClangExpressionVariableStore ( ) ) ;
Error dwarf_error = parser . MakeDWARF ( ) ;
if ( dwarf_error . Success ( ) )
{
if ( log )
log - > Printf ( " Code can be interpreted. " ) ;
2010-12-03 01:38:59 +00:00
m_expr_decl_map - > DidParse ( ) ;
2010-08-27 01:01:44 +00:00
return true ;
}
//////////////////////////////////
// JIT the output of the parser
//
m_dwarf_opcodes . reset ( ) ;
2010-08-27 23:31:21 +00:00
lldb : : addr_t jit_end ;
Error jit_error = parser . MakeJIT ( m_jit_addr , jit_end , exe_ctx ) ;
2010-08-27 01:01:44 +00:00
2010-12-03 01:38:59 +00:00
m_expr_decl_map - > DidParse ( ) ;
2010-08-27 01:01:44 +00:00
if ( jit_error . Success ( ) )
{
return true ;
}
else
{
error_stream . Printf ( " error: expression can't be interpreted or run \n " , num_errors ) ;
return false ;
}
}
bool
2010-10-14 23:45:03 +00:00
ClangUserExpression : : PrepareToExecuteJITExpression ( Stream & error_stream ,
2010-10-19 23:57:21 +00:00
ExecutionContext & exe_ctx ,
lldb : : addr_t & struct_address ,
lldb : : addr_t & object_ptr )
2010-08-27 01:01:44 +00:00
{
2010-11-06 01:53:30 +00:00
lldb : : LogSP log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2010-08-27 01:01:44 +00:00
2010-10-14 23:45:03 +00:00
if ( m_jit_addr ! = LLDB_INVALID_ADDRESS )
2010-08-27 01:01:44 +00:00
{
Error materialize_error ;
2010-09-21 00:44:12 +00:00
2010-12-03 01:38:59 +00:00
if ( m_needs_object_ptr & & ! ( m_expr_decl_map - > GetObjectPointer ( object_ptr , exe_ctx , materialize_error ) ) )
2010-09-21 00:44:12 +00:00
{
error_stream . Printf ( " Couldn't get required object pointer: %s \n " , materialize_error . AsCString ( ) ) ;
return false ;
}
2010-12-03 01:38:59 +00:00
if ( ! m_expr_decl_map - > Materialize ( exe_ctx , struct_address , materialize_error ) )
2010-08-27 01:01:44 +00:00
{
2010-09-21 00:44:12 +00:00
error_stream . Printf ( " Couldn't materialize struct: %s \n " , materialize_error . AsCString ( ) ) ;
2010-08-27 01:01:44 +00:00
return false ;
}
if ( log )
{
2010-12-07 22:55:01 +00:00
log - > Printf ( " -- [ClangUserExpression::PrepareToExecuteJITExpression] Materializing for execution -- " ) ;
2010-12-07 10:00:20 +00:00
log - > Printf ( " Function address : 0x%llx " , ( uint64_t ) m_jit_addr ) ;
2010-09-21 00:44:12 +00:00
if ( m_needs_object_ptr )
2010-12-07 10:00:20 +00:00
log - > Printf ( " Object pointer : 0x%llx " , ( uint64_t ) object_ptr ) ;
2010-09-21 00:44:12 +00:00
2010-12-07 10:00:20 +00:00
log - > Printf ( " Structure address : 0x%llx " , ( uint64_t ) struct_address ) ;
2010-08-27 01:01:44 +00:00
StreamString args ;
Error dump_error ;
2010-09-13 21:34:21 +00:00
if ( struct_address )
2010-08-27 01:01:44 +00:00
{
2010-12-03 01:38:59 +00:00
if ( ! m_expr_decl_map - > DumpMaterializedStruct ( exe_ctx , args , dump_error ) )
2010-09-13 21:34:21 +00:00
{
2010-12-07 10:00:20 +00:00
log - > Printf ( " Couldn't extract variable values : %s " , dump_error . AsCString ( " unknown error " ) ) ;
2010-09-13 21:34:21 +00:00
}
else
{
2010-12-07 10:00:20 +00:00
log - > Printf ( " Structure contents: \n %s " , args . GetData ( ) ) ;
2010-09-13 21:34:21 +00:00
}
2010-08-27 01:01:44 +00:00
}
}
2010-10-14 23:45:03 +00:00
}
return true ;
}
ThreadPlan *
ClangUserExpression : : GetThreadPlanToExecuteJITExpression ( Stream & error_stream ,
ExecutionContext & exe_ctx )
{
lldb : : addr_t struct_address ;
lldb : : addr_t object_ptr = NULL ;
PrepareToExecuteJITExpression ( error_stream , exe_ctx , struct_address , object_ptr ) ;
2010-11-30 02:22:11 +00:00
// FIXME: This should really return a ThreadPlanCallUserExpression, in order to make sure that we don't release the
// ClangUserExpression resources before the thread plan finishes execution in the target. But because we are
// forcing unwind_on_error to be true here, in practical terms that can't happen.
2010-10-14 23:45:03 +00:00
return ClangFunction : : GetThreadPlanToCallFunction ( exe_ctx ,
2010-12-01 01:28:23 +00:00
m_jit_addr ,
struct_address ,
error_stream ,
true ,
true ,
( m_needs_object_ptr ? & object_ptr : NULL ) ) ;
2010-10-14 23:45:03 +00:00
}
bool
ClangUserExpression : : FinalizeJITExecution ( Stream & error_stream ,
ExecutionContext & exe_ctx ,
ClangExpressionVariable * & result )
{
Error expr_error ;
2010-12-07 10:00:20 +00:00
lldb : : LogSP log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
if ( log )
{
2010-12-07 22:55:01 +00:00
log - > Printf ( " -- [ClangUserExpression::FinalizeJITExecution] Dematerializing after execution -- " ) ;
2010-12-07 10:00:20 +00:00
StreamString args ;
Error dump_error ;
if ( ! m_expr_decl_map - > DumpMaterializedStruct ( exe_ctx , args , dump_error ) )
{
log - > Printf ( " Couldn't extract variable values : %s " , dump_error . AsCString ( " unknown error " ) ) ;
}
else
{
log - > Printf ( " Structure contents: \n %s " , args . GetData ( ) ) ;
}
}
2010-12-03 01:38:59 +00:00
if ( ! m_expr_decl_map - > Dematerialize ( exe_ctx , result , expr_error ) )
2010-10-14 23:45:03 +00:00
{
error_stream . Printf ( " Couldn't dematerialize struct : %s \n " , expr_error . AsCString ( " unknown error " ) ) ;
return false ;
}
return true ;
}
2010-11-30 02:22:11 +00:00
Process : : ExecutionResults
2010-10-14 23:45:03 +00:00
ClangUserExpression : : Execute ( Stream & error_stream ,
ExecutionContext & exe_ctx ,
2010-11-05 19:25:48 +00:00
bool discard_on_error ,
2010-11-30 02:22:11 +00:00
ClangUserExpression : : ClangUserExpressionSP & shared_ptr_to_me ,
2010-10-14 23:45:03 +00:00
ClangExpressionVariable * & result )
{
2010-12-07 10:00:20 +00:00
lldb : : LogSP log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2010-10-14 23:45:03 +00:00
if ( m_dwarf_opcodes . get ( ) )
{
// TODO execute the JITted opcodes
error_stream . Printf ( " We don't currently support executing DWARF expressions " ) ;
2010-11-30 02:22:11 +00:00
return Process : : eExecutionSetupError ;
2010-10-14 23:45:03 +00:00
}
else if ( m_jit_addr ! = LLDB_INVALID_ADDRESS )
{
lldb : : addr_t struct_address ;
lldb : : addr_t object_ptr = NULL ;
PrepareToExecuteJITExpression ( error_stream , exe_ctx , struct_address , object_ptr ) ;
2010-08-27 01:01:44 +00:00
2010-11-05 19:25:48 +00:00
const bool stop_others = true ;
const bool try_all_threads = true ;
2010-08-27 01:01:44 +00:00
2010-11-30 02:22:11 +00:00
Address wrapper_address ( NULL , m_jit_addr ) ;
lldb : : ThreadPlanSP call_plan_sp ( new ThreadPlanCallUserExpression ( * ( exe_ctx . thread ) , wrapper_address , struct_address ,
stop_others , discard_on_error ,
( m_needs_object_ptr ? & object_ptr : NULL ) ,
shared_ptr_to_me ) ) ;
if ( call_plan_sp = = NULL | | ! call_plan_sp - > ValidatePlan ( NULL ) )
return Process : : eExecutionSetupError ;
call_plan_sp - > SetPrivate ( true ) ;
uint32_t single_thread_timeout_usec = 10000000 ;
2010-12-07 10:00:20 +00:00
if ( log )
2010-12-07 22:55:01 +00:00
log - > Printf ( " -- [ClangUserExpression::Execute] Execution of expression begins -- " ) ;
2010-12-07 10:00:20 +00:00
2010-11-30 02:22:11 +00:00
Process : : ExecutionResults execution_result =
exe_ctx . process - > RunThreadPlan ( exe_ctx , call_plan_sp , stop_others , try_all_threads , discard_on_error ,
single_thread_timeout_usec , error_stream ) ;
2010-12-07 10:00:20 +00:00
if ( log )
2010-12-07 22:55:01 +00:00
log - > Printf ( " -- [ClangUserExpression::Execute] Execution of expression completed -- " ) ;
2010-11-30 02:22:11 +00:00
if ( execution_result = = Process : : eExecutionInterrupted )
2010-08-27 01:01:44 +00:00
{
2010-11-30 02:22:11 +00:00
if ( discard_on_error )
error_stream . Printf ( " Expression execution was interrupted. The process has been returned to the state before execution. " ) ;
else
error_stream . Printf ( " Expression execution was interrupted. The process has been left at the point where it was interrupted. " ) ;
return execution_result ;
}
else if ( execution_result ! = Process : : eExecutionCompleted )
{
error_stream . Printf ( " Couldn't execute function; result was %s \n " , Process : : ExecutionResultAsCString ( execution_result ) ) ;
return execution_result ;
2010-08-27 01:01:44 +00:00
}
2010-11-30 02:22:11 +00:00
if ( FinalizeJITExecution ( error_stream , exe_ctx , result ) )
return Process : : eExecutionCompleted ;
else
return Process : : eExecutionSetupError ;
2010-08-27 01:01:44 +00:00
}
else
{
2010-11-10 19:02:11 +00:00
error_stream . Printf ( " Expression can't be run; neither DWARF nor a JIT compiled function is present " ) ;
2010-11-30 02:22:11 +00:00
return Process : : eExecutionSetupError ;
2010-08-27 01:01:44 +00:00
}
}
StreamString &
ClangUserExpression : : DwarfOpcodeStream ( )
{
if ( ! m_dwarf_opcodes . get ( ) )
m_dwarf_opcodes . reset ( new StreamString ( ) ) ;
return * m_dwarf_opcodes . get ( ) ;
}
2010-10-05 00:31:29 +00:00
2010-11-30 02:22:11 +00:00
Process : : ExecutionResults
2010-10-29 00:29:03 +00:00
ClangUserExpression : : Evaluate ( ExecutionContext & exe_ctx ,
2010-11-05 19:25:48 +00:00
bool discard_on_error ,
2010-10-29 00:29:03 +00:00
const char * expr_cstr ,
2010-11-30 02:22:11 +00:00
const char * expr_prefix ,
lldb : : ValueObjectSP & result_valobj_sp )
2010-10-05 00:31:29 +00:00
{
2010-12-07 22:55:01 +00:00
lldb : : LogSP log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2010-10-05 00:31:29 +00:00
Error error ;
2010-11-30 02:22:11 +00:00
Process : : ExecutionResults execution_results = Process : : eExecutionSetupError ;
2010-11-04 01:54:29 +00:00
if ( exe_ctx . process = = NULL )
2010-11-30 02:22:11 +00:00
{
error . SetErrorString ( " Must have a process to evaluate expressions. " ) ;
result_valobj_sp . reset ( new ValueObjectConstResult ( error ) ) ;
return Process : : eExecutionSetupError ;
}
2010-11-04 01:54:29 +00:00
if ( ! exe_ctx . process - > GetDynamicCheckers ( ) )
{
2010-12-07 22:55:01 +00:00
if ( log )
log - > Printf ( " == [ClangUserExpression::Evaluate] Installing dynamic checkers == " ) ;
2010-11-04 01:54:29 +00:00
DynamicCheckerFunctions * dynamic_checkers = new DynamicCheckerFunctions ( ) ;
StreamString install_errors ;
if ( ! dynamic_checkers - > Install ( install_errors , exe_ctx ) )
2010-11-05 00:57:06 +00:00
{
if ( install_errors . GetString ( ) . empty ( ) )
error . SetErrorString ( " couldn't install checkers, unknown error " ) ;
else
error . SetErrorString ( install_errors . GetString ( ) . c_str ( ) ) ;
result_valobj_sp . reset ( new ValueObjectConstResult ( error ) ) ;
2010-11-30 02:22:11 +00:00
return Process : : eExecutionSetupError ;
2010-11-05 00:57:06 +00:00
}
2010-11-04 01:54:29 +00:00
exe_ctx . process - > SetDynamicCheckers ( dynamic_checkers ) ;
2010-12-07 22:55:01 +00:00
if ( log )
log - > Printf ( " == [ClangUserExpression::Evaluate] Finished installing dynamic checkers == " ) ;
2010-11-04 01:54:29 +00:00
}
2010-11-30 02:22:11 +00:00
ClangUserExpressionSP user_expression_sp ( new ClangUserExpression ( expr_cstr , expr_prefix ) ) ;
2010-10-05 00:31:29 +00:00
StreamString error_stream ;
2010-12-07 22:55:01 +00:00
if ( log )
log - > Printf ( " == [ClangUserExpression::Evaluate] Parsing expression %s == " , expr_cstr ) ;
2010-11-30 02:22:11 +00:00
if ( ! user_expression_sp - > Parse ( error_stream , exe_ctx , TypeFromUser ( NULL , NULL ) ) )
2010-10-05 00:31:29 +00:00
{
if ( error_stream . GetString ( ) . empty ( ) )
error . SetErrorString ( " expression failed to parse, unknown error " ) ;
else
error . SetErrorString ( error_stream . GetString ( ) . c_str ( ) ) ;
}
else
{
ClangExpressionVariable * expr_result = NULL ;
error_stream . GetString ( ) . clear ( ) ;
2010-12-07 22:55:01 +00:00
if ( log )
log - > Printf ( " == [ClangUserExpression::Evaluate] Executing expression == " ) ;
2010-10-05 00:31:29 +00:00
2010-11-30 02:22:11 +00:00
execution_results = user_expression_sp - > Execute ( error_stream ,
exe_ctx ,
discard_on_error ,
user_expression_sp ,
expr_result ) ;
if ( execution_results ! = Process : : eExecutionCompleted )
2010-10-05 00:31:29 +00:00
{
2010-12-07 22:55:01 +00:00
if ( log )
log - > Printf ( " == [ClangUserExpression::Evaluate] Execution completed abnormally == " ) ;
2010-10-05 00:31:29 +00:00
if ( error_stream . GetString ( ) . empty ( ) )
error . SetErrorString ( " expression failed to execute, unknown error " ) ;
else
error . SetErrorString ( error_stream . GetString ( ) . c_str ( ) ) ;
}
else
{
// TODO: seems weird to get a pointer to a result object back from
// a function. Do we own it? Feels like we do, but from looking at the
// code we don't. Might be best to make this a reference and state
// explicitly that we don't own it when we get a reference back from
// the execute?
if ( expr_result )
{
result_valobj_sp = expr_result - > GetExpressionResult ( & exe_ctx ) ;
2010-12-07 22:55:01 +00:00
if ( log )
log - > Printf ( " == [ClangUserExpression::Evaluate] Execution completed normally with result %s == " , result_valobj_sp - > GetValueAsCString ( exe_ctx . GetBestExecutionContextScope ( ) ) ) ;
2010-10-05 00:31:29 +00:00
}
else
{
2010-12-07 22:55:01 +00:00
if ( log )
log - > Printf ( " == [ClangUserExpression::Evaluate] Execution completed normally with no result == " ) ;
2010-10-19 20:15:00 +00:00
error . SetErrorString ( " Expression did not return a result " ) ;
2010-10-05 00:31:29 +00:00
}
}
}
2010-10-19 20:15:00 +00:00
2010-10-05 03:13:51 +00:00
if ( result_valobj_sp . get ( ) = = NULL )
result_valobj_sp . reset ( new ValueObjectConstResult ( error ) ) ;
2010-11-30 02:22:11 +00:00
return execution_results ;
2010-10-29 20:19:44 +00:00
}