ClangUserExpression.cpp revision daa6efe771f5f068e29328a774fa5bf2358ce14a
1//===-- ClangUserExpression.cpp ---------------------------------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10// C Includes
11#include <stdio.h>
12#if HAVE_SYS_TYPES_H
13#  include <sys/types.h>
14#endif
15
16// C++ Includes
17#include <cstdlib>
18#include <string>
19#include <map>
20
21#include "lldb/Core/ConstString.h"
22#include "lldb/Core/Log.h"
23#include "lldb/Core/StreamFile.h"
24#include "lldb/Core/StreamString.h"
25#include "lldb/Core/ValueObjectConstResult.h"
26#include "lldb/Expression/ASTResultSynthesizer.h"
27#include "lldb/Expression/ClangExpressionDeclMap.h"
28#include "lldb/Expression/ClangExpressionParser.h"
29#include "lldb/Expression/ClangFunction.h"
30#include "lldb/Expression/ClangUserExpression.h"
31#include "lldb/Expression/ExpressionSourceCode.h"
32#include "lldb/Host/Host.h"
33#include "lldb/Symbol/VariableList.h"
34#include "lldb/Target/ExecutionContext.h"
35#include "lldb/Target/Process.h"
36#include "lldb/Target/StackFrame.h"
37#include "lldb/Target/Target.h"
38#include "lldb/Target/ThreadPlan.h"
39#include "lldb/Target/ThreadPlanCallUserExpression.h"
40
41#include "clang/AST/DeclCXX.h"
42#include "clang/AST/DeclObjC.h"
43
44using namespace lldb_private;
45
46ClangUserExpression::ClangUserExpression (const char *expr,
47                                          const char *expr_prefix,
48                                          lldb::LanguageType language,
49                                          ResultType desired_type) :
50    ClangExpression (),
51    m_expr_text (expr),
52    m_expr_prefix (expr_prefix ? expr_prefix : ""),
53    m_language (language),
54    m_transformed_text (),
55    m_desired_type (desired_type),
56    m_cplusplus (false),
57    m_objectivec (false),
58    m_needs_object_ptr (false),
59    m_const_object (false),
60    m_static_method(false),
61    m_target (NULL),
62    m_evaluated_statically (false),
63    m_const_result (),
64    m_enforce_valid_object (false)
65{
66    switch (m_language)
67    {
68    case lldb::eLanguageTypeC_plus_plus:
69        m_allow_cxx = true;
70        break;
71    case lldb::eLanguageTypeObjC:
72        m_allow_objc = true;
73        break;
74    case lldb::eLanguageTypeObjC_plus_plus:
75    default:
76        m_allow_cxx = true;
77        m_allow_objc = true;
78        break;
79    }
80}
81
82ClangUserExpression::~ClangUserExpression ()
83{
84}
85
86clang::ASTConsumer *
87ClangUserExpression::ASTTransformer (clang::ASTConsumer *passthrough)
88{
89    ClangASTContext *clang_ast_context = m_target->GetScratchClangASTContext();
90
91    if (!clang_ast_context)
92        return NULL;
93
94    if (!m_result_synthesizer.get())
95        m_result_synthesizer.reset(new ASTResultSynthesizer(passthrough,
96                                                            *m_target));
97
98    return m_result_synthesizer.get();
99}
100
101void
102ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Error &err)
103{
104    m_target = exe_ctx.GetTargetPtr();
105
106    if (!(m_allow_cxx || m_allow_objc))
107        return;
108
109    StackFrame *frame = exe_ctx.GetFramePtr();
110    if (frame == NULL)
111        return;
112
113    SymbolContext sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction);
114
115    if (!sym_ctx.function)
116        return;
117
118    clang::DeclContext *decl_context;
119
120    if (sym_ctx.block && sym_ctx.block->GetInlinedFunctionInfo())
121        decl_context = sym_ctx.block->GetClangDeclContextForInlinedFunction();
122    else
123        decl_context = sym_ctx.function->GetClangDeclContext();
124
125    if (!decl_context)
126        return;
127
128    if (clang::CXXMethodDecl *method_decl = llvm::dyn_cast<clang::CXXMethodDecl>(decl_context))
129    {
130        if (m_allow_cxx && method_decl->isInstance())
131        {
132            if (m_enforce_valid_object)
133            {
134                VariableList *vars = frame->GetVariableList(false);
135
136                const char *thisErrorString = "Stopped in a C++ method, but 'this' isn't available; pretending we are in a generic context";
137
138                if (!vars)
139                {
140                    err.SetErrorToGenericError();
141                    err.SetErrorString(thisErrorString);
142                    return;
143                }
144
145                lldb::VariableSP this_var = vars->FindVariable(ConstString("this"));
146
147                if (!this_var ||
148                    !this_var->IsInScope(frame) ||
149                    !this_var->LocationIsValidForFrame (frame))
150                {
151                    err.SetErrorToGenericError();
152                    err.SetErrorString(thisErrorString);
153                    return;
154                }
155            }
156
157            m_cplusplus = true;
158            m_needs_object_ptr = true;
159
160            do {
161                clang::QualType this_type = method_decl->getThisType(decl_context->getParentASTContext());
162
163                const clang::PointerType *this_pointer_type = this_type->getAs<clang::PointerType>();
164
165                if (!this_pointer_type)
166                    break;
167
168                clang::QualType this_pointee_type = this_pointer_type->getPointeeType();
169            } while (0);
170        }
171    }
172    else if (clang::ObjCMethodDecl *method_decl = llvm::dyn_cast<clang::ObjCMethodDecl>(decl_context))
173    {
174        if (m_allow_objc)
175        {
176            if (m_enforce_valid_object)
177            {
178                VariableList *vars = frame->GetVariableList(false);
179
180                const char *selfErrorString = "Stopped in an Objective-C method, but 'self' isn't available; pretending we are in a generic context";
181
182                if (!vars)
183                {
184                    err.SetErrorToGenericError();
185                    err.SetErrorString(selfErrorString);
186                    return;
187                }
188
189                lldb::VariableSP self_var = vars->FindVariable(ConstString("self"));
190
191                if (!self_var ||
192                    !self_var->IsInScope(frame) ||
193                    !self_var->LocationIsValidForFrame (frame))
194                {
195                    err.SetErrorToGenericError();
196                    err.SetErrorString(selfErrorString);
197                    return;
198                }
199            }
200
201            m_objectivec = true;
202            m_needs_object_ptr = true;
203
204            if (!method_decl->isInstanceMethod())
205                m_static_method = true;
206        }
207    }
208}
209
210// This is a really nasty hack, meant to fix Objective-C expressions of the form
211// (int)[myArray count].  Right now, because the type information for count is
212// not available, [myArray count] returns id, which can't be directly cast to
213// int without causing a clang error.
214static void
215ApplyObjcCastHack(std::string &expr)
216{
217#define OBJC_CAST_HACK_FROM "(int)["
218#define OBJC_CAST_HACK_TO   "(int)(long long)["
219
220    size_t from_offset;
221
222    while ((from_offset = expr.find(OBJC_CAST_HACK_FROM)) != expr.npos)
223        expr.replace(from_offset, sizeof(OBJC_CAST_HACK_FROM) - 1, OBJC_CAST_HACK_TO);
224
225#undef OBJC_CAST_HACK_TO
226#undef OBJC_CAST_HACK_FROM
227}
228
229// Another hack, meant to allow use of unichar despite it not being available in
230// the type information.  Although we could special-case it in type lookup,
231// hopefully we'll figure out a way to #include the same environment as is
232// present in the original source file rather than try to hack specific type
233// definitions in as needed.
234static void
235ApplyUnicharHack(std::string &expr)
236{
237#define UNICHAR_HACK_FROM "unichar"
238#define UNICHAR_HACK_TO   "unsigned short"
239
240    size_t from_offset;
241
242    while ((from_offset = expr.find(UNICHAR_HACK_FROM)) != expr.npos)
243        expr.replace(from_offset, sizeof(UNICHAR_HACK_FROM) - 1, UNICHAR_HACK_TO);
244
245#undef UNICHAR_HACK_TO
246#undef UNICHAR_HACK_FROM
247}
248
249bool
250ClangUserExpression::Parse (Stream &error_stream,
251                            ExecutionContext &exe_ctx,
252                            lldb_private::ExecutionPolicy execution_policy,
253                            bool keep_result_in_memory)
254{
255    lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
256
257    Error err;
258
259    ScanContext(exe_ctx, err);
260
261    if (!err.Success())
262    {
263        error_stream.Printf("warning: %s\n", err.AsCString());
264    }
265
266    StreamString m_transformed_stream;
267
268    ////////////////////////////////////
269    // Generate the expression
270    //
271
272    ApplyObjcCastHack(m_expr_text);
273    //ApplyUnicharHack(m_expr_text);
274
275    std::auto_ptr <ExpressionSourceCode> source_code (ExpressionSourceCode::CreateWrapped(m_expr_prefix.c_str(), m_expr_text.c_str()));
276
277    lldb::LanguageType lang_type;
278
279    if (m_cplusplus)
280        lang_type = lldb::eLanguageTypeC_plus_plus;
281    else if(m_objectivec)
282        lang_type = lldb::eLanguageTypeObjC;
283    else
284        lang_type = lldb::eLanguageTypeC;
285
286    if (!source_code->GetText(m_transformed_text, lang_type, m_const_object, m_static_method))
287    {
288        error_stream.PutCString ("error: couldn't construct expression body");
289        return false;
290    }
291
292    if (log)
293        log->Printf("Parsing the following code:\n%s", m_transformed_text.c_str());
294
295    ////////////////////////////////////
296    // Set up the target and compiler
297    //
298
299    Target *target = exe_ctx.GetTargetPtr();
300
301    if (!target)
302    {
303        error_stream.PutCString ("error: invalid target\n");
304        return false;
305    }
306
307    //////////////////////////
308    // Parse the expression
309    //
310
311    m_expr_decl_map.reset(new ClangExpressionDeclMap(keep_result_in_memory, exe_ctx));
312
313    if (!m_expr_decl_map->WillParse(exe_ctx))
314    {
315        error_stream.PutCString ("error: current process state is unsuitable for expression parsing\n");
316        return false;
317    }
318
319    Process *process = exe_ctx.GetProcessPtr();
320    ClangExpressionParser parser(process, *this);
321
322    unsigned num_errors = parser.Parse (error_stream);
323
324    if (num_errors)
325    {
326        error_stream.Printf ("error: %d errors parsing expression\n", num_errors);
327
328        m_expr_decl_map->DidParse();
329
330        return false;
331    }
332
333    //////////////////////////////////////////////////////////////////////////////////////////
334    // Prepare the output of the parser for execution, evaluating it statically if possible
335    //
336
337    if (execution_policy != eExecutionPolicyNever && process)
338        m_data_allocator.reset(new ProcessDataAllocator(*process));
339
340    Error jit_error = parser.PrepareForExecution (m_jit_alloc,
341                                                  m_jit_start_addr,
342                                                  m_jit_end_addr,
343                                                  exe_ctx,
344                                                  m_data_allocator.get(),
345                                                  m_evaluated_statically,
346                                                  m_const_result,
347                                                  execution_policy);
348
349    if (log && m_data_allocator.get())
350    {
351        StreamString dump_string;
352        m_data_allocator->Dump(dump_string);
353
354        log->Printf("Data buffer contents:\n%s", dump_string.GetString().c_str());
355    }
356
357    if (jit_error.Success())
358    {
359        if (process && m_jit_alloc != LLDB_INVALID_ADDRESS)
360            m_jit_process_sp = process->GetSP();
361        return true;
362    }
363    else
364    {
365        const char *error_cstr = jit_error.AsCString();
366        if (error_cstr && error_cstr[0])
367            error_stream.Printf ("error: %s\n", error_cstr);
368        else
369            error_stream.Printf ("error: expression can't be interpreted or run\n");
370        return false;
371    }
372}
373
374bool
375ClangUserExpression::PrepareToExecuteJITExpression (Stream &error_stream,
376                                                    ExecutionContext &exe_ctx,
377                                                    lldb::addr_t &struct_address,
378                                                    lldb::addr_t &object_ptr,
379                                                    lldb::addr_t &cmd_ptr)
380{
381    lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
382
383    if (m_jit_start_addr != LLDB_INVALID_ADDRESS)
384    {
385        Error materialize_error;
386
387        if (m_needs_object_ptr)
388        {
389            ConstString object_name;
390
391            if (m_cplusplus)
392            {
393                object_name.SetCString("this");
394            }
395            else if (m_objectivec)
396            {
397                object_name.SetCString("self");
398            }
399            else
400            {
401                error_stream.Printf("Need object pointer but don't know the language\n");
402                return false;
403            }
404
405            if (!(m_expr_decl_map->GetObjectPointer(object_ptr, object_name, exe_ctx, materialize_error)))
406            {
407                error_stream.Printf("warning: couldn't get required object pointer (substituting NULL): %s\n", materialize_error.AsCString());
408                object_ptr = 0;
409            }
410
411            if (m_objectivec)
412            {
413                ConstString cmd_name("_cmd");
414
415                if (!(m_expr_decl_map->GetObjectPointer(cmd_ptr, cmd_name, exe_ctx, materialize_error, true)))
416                {
417                    error_stream.Printf("warning: couldn't get object pointer (substituting NULL): %s\n", materialize_error.AsCString());
418                    cmd_ptr = 0;
419                }
420            }
421        }
422
423        if (!m_expr_decl_map->Materialize(exe_ctx, struct_address, materialize_error))
424        {
425            error_stream.Printf("Couldn't materialize struct: %s\n", materialize_error.AsCString());
426            return false;
427        }
428
429#if 0
430		// jingham: look here
431        StreamFile logfile ("/tmp/exprs.txt", "a");
432        logfile.Printf("0x%16.16llx: thread = 0x%4.4x, expr = '%s'\n", m_jit_start_addr, exe_ctx.thread ? exe_ctx.thread->GetID() : -1, m_expr_text.c_str());
433#endif
434
435        if (log)
436        {
437            log->Printf("-- [ClangUserExpression::PrepareToExecuteJITExpression] Materializing for execution --");
438
439            log->Printf("  Function address  : 0x%llx", (uint64_t)m_jit_start_addr);
440
441            if (m_needs_object_ptr)
442                log->Printf("  Object pointer    : 0x%llx", (uint64_t)object_ptr);
443
444            log->Printf("  Structure address : 0x%llx", (uint64_t)struct_address);
445
446            StreamString args;
447
448            Error dump_error;
449
450            if (struct_address)
451            {
452                if (!m_expr_decl_map->DumpMaterializedStruct(exe_ctx, args, dump_error))
453                {
454                    log->Printf("  Couldn't extract variable values : %s", dump_error.AsCString("unknown error"));
455                }
456                else
457                {
458                    log->Printf("  Structure contents:\n%s", args.GetData());
459                }
460            }
461        }
462    }
463    return true;
464}
465
466ThreadPlan *
467ClangUserExpression::GetThreadPlanToExecuteJITExpression (Stream &error_stream,
468                                                          ExecutionContext &exe_ctx)
469{
470    lldb::addr_t struct_address;
471
472    lldb::addr_t object_ptr = 0;
473    lldb::addr_t cmd_ptr = 0;
474
475    PrepareToExecuteJITExpression (error_stream, exe_ctx, struct_address, object_ptr, cmd_ptr);
476
477    // FIXME: This should really return a ThreadPlanCallUserExpression, in order to make sure that we don't release the
478    // ClangUserExpression resources before the thread plan finishes execution in the target.  But because we are
479    // forcing unwind_on_error to be true here, in practical terms that can't happen.
480
481    return ClangFunction::GetThreadPlanToCallFunction (exe_ctx,
482                                                       m_jit_start_addr,
483                                                       struct_address,
484                                                       error_stream,
485                                                       true,
486                                                       true,
487                                                       (m_needs_object_ptr ? &object_ptr : NULL),
488                                                       (m_needs_object_ptr && m_objectivec) ? &cmd_ptr : NULL);
489}
490
491bool
492ClangUserExpression::FinalizeJITExecution (Stream &error_stream,
493                                           ExecutionContext &exe_ctx,
494                                           lldb::ClangExpressionVariableSP &result,
495                                           lldb::addr_t function_stack_pointer)
496{
497    Error expr_error;
498
499    lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
500
501    if (log)
502    {
503        log->Printf("-- [ClangUserExpression::FinalizeJITExecution] Dematerializing after execution --");
504
505        StreamString args;
506
507        Error dump_error;
508
509        if (!m_expr_decl_map->DumpMaterializedStruct(exe_ctx, args, dump_error))
510        {
511            log->Printf("  Couldn't extract variable values : %s", dump_error.AsCString("unknown error"));
512        }
513        else
514        {
515            log->Printf("  Structure contents:\n%s", args.GetData());
516        }
517    }
518
519    lldb::addr_t function_stack_bottom = function_stack_pointer - Host::GetPageSize();
520
521
522    if (!m_expr_decl_map->Dematerialize(exe_ctx, result, function_stack_pointer, function_stack_bottom, expr_error))
523    {
524        error_stream.Printf ("Couldn't dematerialize struct : %s\n", expr_error.AsCString("unknown error"));
525        return false;
526    }
527
528    return true;
529}
530
531ExecutionResults
532ClangUserExpression::Execute (Stream &error_stream,
533                              ExecutionContext &exe_ctx,
534                              bool discard_on_error,
535                              ClangUserExpression::ClangUserExpressionSP &shared_ptr_to_me,
536                              lldb::ClangExpressionVariableSP &result)
537{
538    // The expression log is quite verbose, and if you're just tracking the execution of the
539    // expression, it's quite convenient to have these logs come out with the STEP log as well.
540    lldb::LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
541
542    if (m_jit_start_addr != LLDB_INVALID_ADDRESS)
543    {
544        lldb::addr_t struct_address;
545
546        lldb::addr_t object_ptr = 0;
547        lldb::addr_t cmd_ptr = 0;
548
549        if (!PrepareToExecuteJITExpression (error_stream, exe_ctx, struct_address, object_ptr, cmd_ptr))
550            return eExecutionSetupError;
551
552        const bool stop_others = true;
553        const bool try_all_threads = true;
554
555        Address wrapper_address (NULL, m_jit_start_addr);
556        lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallUserExpression (exe_ctx.GetThreadRef(),
557                                                                          wrapper_address,
558                                                                          struct_address,
559                                                                          stop_others,
560                                                                          discard_on_error,
561                                                                          (m_needs_object_ptr ? &object_ptr : NULL),
562                                                                          ((m_needs_object_ptr && m_objectivec) ? &cmd_ptr : NULL),
563                                                                          shared_ptr_to_me));
564
565        if (call_plan_sp == NULL || !call_plan_sp->ValidatePlan (NULL))
566            return eExecutionSetupError;
567
568        lldb::addr_t function_stack_pointer = static_cast<ThreadPlanCallFunction *>(call_plan_sp.get())->GetFunctionStackPointer();
569
570        call_plan_sp->SetPrivate(true);
571
572        uint32_t single_thread_timeout_usec = 500000;
573
574        if (log)
575            log->Printf("-- [ClangUserExpression::Execute] Execution of expression begins --");
576
577        if (exe_ctx.GetProcessPtr())
578            exe_ctx.GetProcessPtr()->SetRunningUserExpression(true);
579
580        ExecutionResults execution_result = exe_ctx.GetProcessRef().RunThreadPlan (exe_ctx,
581                                                                                   call_plan_sp,
582                                                                                   stop_others,
583                                                                                   try_all_threads,
584                                                                                   discard_on_error,
585                                                                                   single_thread_timeout_usec,
586                                                                                   error_stream);
587
588        if (exe_ctx.GetProcessPtr())
589            exe_ctx.GetProcessPtr()->SetRunningUserExpression(false);
590
591        if (log)
592            log->Printf("-- [ClangUserExpression::Execute] Execution of expression completed --");
593
594        if (execution_result == eExecutionInterrupted)
595        {
596            const char *error_desc = NULL;
597
598            if (call_plan_sp)
599            {
600                lldb::StopInfoSP real_stop_info_sp = call_plan_sp->GetRealStopInfo();
601                if (real_stop_info_sp)
602                    error_desc = real_stop_info_sp->GetDescription();
603            }
604            if (error_desc)
605                error_stream.Printf ("Execution was interrupted, reason: %s.", error_desc);
606            else
607                error_stream.Printf ("Execution was interrupted.");
608
609            if (discard_on_error)
610                error_stream.Printf ("\nThe process has been returned to the state before execution.");
611            else
612                error_stream.Printf ("\nThe process has been left at the point where it was interrupted.");
613
614            return execution_result;
615        }
616        else if (execution_result != eExecutionCompleted)
617        {
618            error_stream.Printf ("Couldn't execute function; result was %s\n", Process::ExecutionResultAsCString (execution_result));
619            return execution_result;
620        }
621
622        if  (FinalizeJITExecution (error_stream, exe_ctx, result, function_stack_pointer))
623            return eExecutionCompleted;
624        else
625            return eExecutionSetupError;
626    }
627    else
628    {
629        error_stream.Printf("Expression can't be run, because there is no JIT compiled function");
630        return eExecutionSetupError;
631    }
632}
633
634ExecutionResults
635ClangUserExpression::Evaluate (ExecutionContext &exe_ctx,
636                               lldb_private::ExecutionPolicy execution_policy,
637                               lldb::LanguageType language,
638                               ResultType desired_type,
639                               bool discard_on_error,
640                               const char *expr_cstr,
641                               const char *expr_prefix,
642                               lldb::ValueObjectSP &result_valobj_sp)
643{
644    Error error;
645    return EvaluateWithError (exe_ctx, execution_policy, language, desired_type, discard_on_error, expr_cstr, expr_prefix, result_valobj_sp, error);
646}
647
648ExecutionResults
649ClangUserExpression::EvaluateWithError (ExecutionContext &exe_ctx,
650                                        lldb_private::ExecutionPolicy execution_policy,
651                                        lldb::LanguageType language,
652                                        ResultType desired_type,
653                                        bool discard_on_error,
654                                        const char *expr_cstr,
655                                        const char *expr_prefix,
656                                        lldb::ValueObjectSP &result_valobj_sp,
657                                        Error &error)
658{
659    lldb::LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
660
661    ExecutionResults execution_results = eExecutionSetupError;
662
663    Process *process = exe_ctx.GetProcessPtr();
664
665    if (process == NULL || process->GetState() != lldb::eStateStopped)
666    {
667        if (execution_policy == eExecutionPolicyAlways)
668        {
669            if (log)
670                log->Printf("== [ClangUserExpression::Evaluate] Expression may not run, but is not constant ==");
671
672            error.SetErrorString ("expression needed to run but couldn't");
673
674            return execution_results;
675        }
676    }
677
678    if (process == NULL || !process->CanJIT())
679        execution_policy = eExecutionPolicyNever;
680
681    ClangUserExpressionSP user_expression_sp (new ClangUserExpression (expr_cstr, expr_prefix, language, desired_type));
682
683    StreamString error_stream;
684
685    if (log)
686        log->Printf("== [ClangUserExpression::Evaluate] Parsing expression %s ==", expr_cstr);
687
688    const bool keep_expression_in_memory = true;
689
690    if (!user_expression_sp->Parse (error_stream, exe_ctx, execution_policy, keep_expression_in_memory))
691    {
692        if (error_stream.GetString().empty())
693            error.SetErrorString ("expression failed to parse, unknown error");
694        else
695            error.SetErrorString (error_stream.GetString().c_str());
696    }
697    else
698    {
699        lldb::ClangExpressionVariableSP expr_result;
700
701        if (user_expression_sp->EvaluatedStatically())
702        {
703            if (log)
704                log->Printf("== [ClangUserExpression::Evaluate] Expression evaluated as a constant ==");
705
706            if (user_expression_sp->m_const_result)
707                result_valobj_sp = user_expression_sp->m_const_result->GetValueObject();
708            else
709                error.SetError(ClangUserExpression::kNoResult, lldb::eErrorTypeGeneric);
710
711            execution_results = eExecutionCompleted;
712        }
713        else if (execution_policy == eExecutionPolicyNever)
714        {
715            if (log)
716                log->Printf("== [ClangUserExpression::Evaluate] Expression may not run, but is not constant ==");
717
718            if (error_stream.GetString().empty())
719                error.SetErrorString ("expression needed to run but couldn't");
720        }
721        else
722        {
723            error_stream.GetString().clear();
724
725            if (log)
726                log->Printf("== [ClangUserExpression::Evaluate] Executing expression ==");
727
728            execution_results = user_expression_sp->Execute (error_stream,
729                                                             exe_ctx,
730                                                             discard_on_error,
731                                                             user_expression_sp,
732                                                             expr_result);
733
734            if (execution_results != eExecutionCompleted)
735            {
736                if (log)
737                    log->Printf("== [ClangUserExpression::Evaluate] Execution completed abnormally ==");
738
739                if (error_stream.GetString().empty())
740                    error.SetErrorString ("expression failed to execute, unknown error");
741                else
742                    error.SetErrorString (error_stream.GetString().c_str());
743            }
744            else
745            {
746                if (expr_result)
747                {
748                    result_valobj_sp = expr_result->GetValueObject();
749
750                    if (log)
751                        log->Printf("== [ClangUserExpression::Evaluate] Execution completed normally with result %s ==", result_valobj_sp->GetValueAsCString());
752                }
753                else
754                {
755                    if (log)
756                        log->Printf("== [ClangUserExpression::Evaluate] Execution completed normally with no result ==");
757
758                    error.SetError(ClangUserExpression::kNoResult, lldb::eErrorTypeGeneric);
759                }
760            }
761        }
762    }
763
764    if (result_valobj_sp.get() == NULL)
765        result_valobj_sp = ValueObjectConstResult::Create (NULL, error);
766
767    return execution_results;
768}
769