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 #include <stdio.h>
11 #if HAVE_SYS_TYPES_H
12 #  include <sys/types.h>
13 #endif
14 
15 #include <cstdlib>
16 #include <string>
17 #include <map>
18 
19 #include "ClangUserExpression.h"
20 
21 #include "ASTResultSynthesizer.h"
22 #include "ClangExpressionDeclMap.h"
23 #include "ClangExpressionParser.h"
24 #include "ClangModulesDeclVendor.h"
25 #include "ClangPersistentVariables.h"
26 #include "ClangDiagnostic.h"
27 
28 #include "lldb/Core/ConstString.h"
29 #include "lldb/Core/Log.h"
30 #include "lldb/Core/Module.h"
31 #include "lldb/Core/StreamFile.h"
32 #include "lldb/Core/StreamString.h"
33 #include "lldb/Core/ValueObjectConstResult.h"
34 #include "lldb/Expression/ExpressionSourceCode.h"
35 #include "lldb/Expression/IRExecutionUnit.h"
36 #include "lldb/Expression/IRInterpreter.h"
37 #include "lldb/Expression/Materializer.h"
38 #include "lldb/Host/HostInfo.h"
39 #include "lldb/Symbol/Block.h"
40 #include "lldb/Symbol/ClangASTContext.h"
41 #include "lldb/Symbol/Function.h"
42 #include "lldb/Symbol/ObjectFile.h"
43 #include "lldb/Symbol/SymbolVendor.h"
44 #include "lldb/Symbol/Type.h"
45 #include "lldb/Symbol/ClangExternalASTSourceCommon.h"
46 #include "lldb/Symbol/VariableList.h"
47 #include "lldb/Target/ExecutionContext.h"
48 #include "lldb/Target/Process.h"
49 #include "lldb/Target/StackFrame.h"
50 #include "lldb/Target/Target.h"
51 #include "lldb/Target/ThreadPlan.h"
52 #include "lldb/Target/ThreadPlanCallUserExpression.h"
53 
54 #include "clang/AST/DeclCXX.h"
55 #include "clang/AST/DeclObjC.h"
56 
57 using namespace lldb_private;
58 
59 ClangUserExpression::ClangUserExpression(ExecutionContextScope &exe_scope, const char *expr, const char *expr_prefix,
60                                          lldb::LanguageType language, ResultType desired_type,
61                                          const EvaluateExpressionOptions &options)
62     : LLVMUserExpression(exe_scope, expr, expr_prefix, language, desired_type, options),
63       m_type_system_helper(*m_target_wp.lock().get(), options.GetExecutionPolicy() == eExecutionPolicyTopLevel)
64 {
65     switch (m_language)
66     {
67         case lldb::eLanguageTypeC_plus_plus:
68             m_allow_cxx = true;
69             break;
70         case lldb::eLanguageTypeObjC:
71             m_allow_objc = true;
72             break;
73         case lldb::eLanguageTypeObjC_plus_plus:
74         default:
75             m_allow_cxx = true;
76             m_allow_objc = true;
77             break;
78     }
79 }
80 
81 ClangUserExpression::~ClangUserExpression ()
82 {
83 }
84 
85 void
86 ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Error &err)
87 {
88     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
89 
90     if (log)
91         log->Printf("ClangUserExpression::ScanContext()");
92 
93     m_target = exe_ctx.GetTargetPtr();
94 
95     if (!(m_allow_cxx || m_allow_objc))
96     {
97         if (log)
98             log->Printf("  [CUE::SC] Settings inhibit C++ and Objective-C");
99         return;
100     }
101 
102     StackFrame *frame = exe_ctx.GetFramePtr();
103     if (frame == NULL)
104     {
105         if (log)
106             log->Printf("  [CUE::SC] Null stack frame");
107         return;
108     }
109 
110     SymbolContext sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction | lldb::eSymbolContextBlock);
111 
112     if (!sym_ctx.function)
113     {
114         if (log)
115             log->Printf("  [CUE::SC] Null function");
116         return;
117     }
118 
119     // Find the block that defines the function represented by "sym_ctx"
120     Block *function_block = sym_ctx.GetFunctionBlock();
121 
122     if (!function_block)
123     {
124         if (log)
125             log->Printf("  [CUE::SC] Null function block");
126         return;
127     }
128 
129     CompilerDeclContext decl_context = function_block->GetDeclContext();
130 
131     if (!decl_context)
132     {
133         if (log)
134             log->Printf("  [CUE::SC] Null decl context");
135         return;
136     }
137 
138     if (clang::CXXMethodDecl *method_decl = ClangASTContext::DeclContextGetAsCXXMethodDecl(decl_context))
139     {
140         if (m_allow_cxx && method_decl->isInstance())
141         {
142             if (m_enforce_valid_object)
143             {
144                 lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true));
145 
146                 const char *thisErrorString = "Stopped in a C++ method, but 'this' isn't available; pretending we are in a generic context";
147 
148                 if (!variable_list_sp)
149                 {
150                     err.SetErrorString(thisErrorString);
151                     return;
152                 }
153 
154                 lldb::VariableSP this_var_sp (variable_list_sp->FindVariable(ConstString("this")));
155 
156                 if (!this_var_sp ||
157                     !this_var_sp->IsInScope(frame) ||
158                     !this_var_sp->LocationIsValidForFrame (frame))
159                 {
160                     err.SetErrorString(thisErrorString);
161                     return;
162                 }
163             }
164 
165             m_in_cplusplus_method = true;
166             m_needs_object_ptr = true;
167         }
168     }
169     else if (clang::ObjCMethodDecl *method_decl = ClangASTContext::DeclContextGetAsObjCMethodDecl(decl_context))
170     {
171         if (m_allow_objc)
172         {
173             if (m_enforce_valid_object)
174             {
175                 lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true));
176 
177                 const char *selfErrorString = "Stopped in an Objective-C method, but 'self' isn't available; pretending we are in a generic context";
178 
179                 if (!variable_list_sp)
180                 {
181                     err.SetErrorString(selfErrorString);
182                     return;
183                 }
184 
185                 lldb::VariableSP self_variable_sp = variable_list_sp->FindVariable(ConstString("self"));
186 
187                 if (!self_variable_sp ||
188                     !self_variable_sp->IsInScope(frame) ||
189                     !self_variable_sp->LocationIsValidForFrame (frame))
190                 {
191                     err.SetErrorString(selfErrorString);
192                     return;
193                 }
194             }
195 
196             m_in_objectivec_method = true;
197             m_needs_object_ptr = true;
198 
199             if (!method_decl->isInstanceMethod())
200                 m_in_static_method = true;
201         }
202     }
203     else if (clang::FunctionDecl *function_decl = ClangASTContext::DeclContextGetAsFunctionDecl(decl_context))
204     {
205         // We might also have a function that said in the debug information that it captured an
206         // object pointer.  The best way to deal with getting to the ivars at present is by pretending
207         // that this is a method of a class in whatever runtime the debug info says the object pointer
208         // belongs to.  Do that here.
209 
210         ClangASTMetadata *metadata = ClangASTContext::DeclContextGetMetaData (decl_context, function_decl);
211         if (metadata && metadata->HasObjectPtr())
212         {
213             lldb::LanguageType language = metadata->GetObjectPtrLanguage();
214             if (language == lldb::eLanguageTypeC_plus_plus)
215             {
216                 if (m_enforce_valid_object)
217                 {
218                     lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true));
219 
220                     const char *thisErrorString = "Stopped in a context claiming to capture a C++ object pointer, but 'this' isn't available; pretending we are in a generic context";
221 
222                     if (!variable_list_sp)
223                     {
224                         err.SetErrorString(thisErrorString);
225                         return;
226                     }
227 
228                     lldb::VariableSP this_var_sp (variable_list_sp->FindVariable(ConstString("this")));
229 
230                     if (!this_var_sp ||
231                         !this_var_sp->IsInScope(frame) ||
232                         !this_var_sp->LocationIsValidForFrame (frame))
233                     {
234                         err.SetErrorString(thisErrorString);
235                         return;
236                     }
237                 }
238 
239                 m_in_cplusplus_method = true;
240                 m_needs_object_ptr = true;
241             }
242             else if (language == lldb::eLanguageTypeObjC)
243             {
244                 if (m_enforce_valid_object)
245                 {
246                     lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true));
247 
248                     const char *selfErrorString = "Stopped in a context claiming to capture an Objective-C object pointer, but 'self' isn't available; pretending we are in a generic context";
249 
250                     if (!variable_list_sp)
251                     {
252                         err.SetErrorString(selfErrorString);
253                         return;
254                     }
255 
256                     lldb::VariableSP self_variable_sp = variable_list_sp->FindVariable(ConstString("self"));
257 
258                     if (!self_variable_sp ||
259                         !self_variable_sp->IsInScope(frame) ||
260                         !self_variable_sp->LocationIsValidForFrame (frame))
261                     {
262                         err.SetErrorString(selfErrorString);
263                         return;
264                     }
265 
266                     Type *self_type = self_variable_sp->GetType();
267 
268                     if (!self_type)
269                     {
270                         err.SetErrorString(selfErrorString);
271                         return;
272                     }
273 
274                     CompilerType self_clang_type = self_type->GetForwardCompilerType ();
275 
276                     if (!self_clang_type)
277                     {
278                         err.SetErrorString(selfErrorString);
279                         return;
280                     }
281 
282                     if (ClangASTContext::IsObjCClassType(self_clang_type))
283                     {
284                         return;
285                     }
286                     else if (ClangASTContext::IsObjCObjectPointerType(self_clang_type))
287                     {
288                         m_in_objectivec_method = true;
289                         m_needs_object_ptr = true;
290                     }
291                     else
292                     {
293                         err.SetErrorString(selfErrorString);
294                         return;
295                     }
296                 }
297                 else
298                 {
299                     m_in_objectivec_method = true;
300                     m_needs_object_ptr = true;
301                 }
302             }
303         }
304     }
305 }
306 
307 // This is a really nasty hack, meant to fix Objective-C expressions of the form
308 // (int)[myArray count].  Right now, because the type information for count is
309 // not available, [myArray count] returns id, which can't be directly cast to
310 // int without causing a clang error.
311 static void
312 ApplyObjcCastHack(std::string &expr)
313 {
314 #define OBJC_CAST_HACK_FROM "(int)["
315 #define OBJC_CAST_HACK_TO   "(int)(long long)["
316 
317     size_t from_offset;
318 
319     while ((from_offset = expr.find(OBJC_CAST_HACK_FROM)) != expr.npos)
320         expr.replace(from_offset, sizeof(OBJC_CAST_HACK_FROM) - 1, OBJC_CAST_HACK_TO);
321 
322 #undef OBJC_CAST_HACK_TO
323 #undef OBJC_CAST_HACK_FROM
324 }
325 
326 bool
327 ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx,
328                            lldb_private::ExecutionPolicy execution_policy, bool keep_result_in_memory,
329                            bool generate_debug_info)
330 {
331     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
332 
333     Error err;
334 
335     InstallContext(exe_ctx);
336 
337     if (Target *target = exe_ctx.GetTargetPtr())
338     {
339         if (PersistentExpressionState *persistent_state = target->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC))
340         {
341             m_result_delegate.RegisterPersistentState(persistent_state);
342         }
343         else
344         {
345             diagnostic_manager.PutCString(eDiagnosticSeverityError, "couldn't start parsing (no persistent data)");
346             return false;
347         }
348     }
349     else
350     {
351         diagnostic_manager.PutCString(eDiagnosticSeverityError, "error: couldn't start parsing (no target)");
352         return false;
353     }
354 
355     ScanContext(exe_ctx, err);
356 
357     if (!err.Success())
358     {
359         diagnostic_manager.PutCString(eDiagnosticSeverityWarning, err.AsCString());
360     }
361 
362     ////////////////////////////////////
363     // Generate the expression
364     //
365 
366     ApplyObjcCastHack(m_expr_text);
367     //ApplyUnicharHack(m_expr_text);
368 
369     std::string prefix = m_expr_prefix;
370 
371     if (ClangModulesDeclVendor *decl_vendor = m_target->GetClangModulesDeclVendor())
372     {
373         const ClangModulesDeclVendor::ModuleVector &hand_imported_modules = llvm::cast<ClangPersistentVariables>(m_target->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC))->GetHandLoadedClangModules();
374         ClangModulesDeclVendor::ModuleVector modules_for_macros;
375 
376         for (ClangModulesDeclVendor::ModuleID module : hand_imported_modules)
377         {
378             modules_for_macros.push_back(module);
379         }
380 
381         if (m_target->GetEnableAutoImportClangModules())
382         {
383             if (StackFrame *frame = exe_ctx.GetFramePtr())
384             {
385                 if (Block *block = frame->GetFrameBlock())
386                 {
387                     SymbolContext sc;
388 
389                     block->CalculateSymbolContext(&sc);
390 
391                     if (sc.comp_unit)
392                     {
393                         StreamString error_stream;
394 
395                         decl_vendor->AddModulesForCompileUnit(*sc.comp_unit, modules_for_macros, error_stream);
396                     }
397                 }
398             }
399         }
400     }
401 
402     if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel)
403     {
404         m_transformed_text = m_expr_text;
405     }
406     else
407     {
408         std::unique_ptr<ExpressionSourceCode> source_code(
409             ExpressionSourceCode::CreateWrapped(prefix.c_str(), m_expr_text.c_str()));
410 
411         lldb::LanguageType lang_type;
412 
413         if (m_in_cplusplus_method)
414             lang_type = lldb::eLanguageTypeC_plus_plus;
415         else if (m_in_objectivec_method)
416             lang_type = lldb::eLanguageTypeObjC;
417         else
418             lang_type = lldb::eLanguageTypeC;
419 
420         if (!source_code->GetText(m_transformed_text, lang_type, m_const_object, m_in_static_method, exe_ctx))
421         {
422             diagnostic_manager.PutCString(eDiagnosticSeverityError, "couldn't construct expression body");
423             return false;
424         }
425     }
426 
427     if (log)
428         log->Printf("Parsing the following code:\n%s", m_transformed_text.c_str());
429 
430     ////////////////////////////////////
431     // Set up the target and compiler
432     //
433 
434     Target *target = exe_ctx.GetTargetPtr();
435 
436     if (!target)
437     {
438         diagnostic_manager.PutCString(eDiagnosticSeverityError, "invalid target");
439         return false;
440     }
441 
442     //////////////////////////
443     // Parse the expression
444     //
445 
446     m_materializer_ap.reset(new Materializer());
447 
448     ResetDeclMap(exe_ctx, m_result_delegate, keep_result_in_memory);
449 
450     class OnExit
451     {
452     public:
453         typedef std::function <void (void)> Callback;
454 
455         OnExit (Callback const &callback) :
456             m_callback(callback)
457         {
458         }
459 
460         ~OnExit ()
461         {
462             m_callback();
463         }
464     private:
465         Callback m_callback;
466     };
467 
468     OnExit on_exit([this]() { ResetDeclMap(); });
469 
470     if (!DeclMap()->WillParse(exe_ctx, m_materializer_ap.get()))
471     {
472         diagnostic_manager.PutCString(eDiagnosticSeverityError,
473                                       "current process state is unsuitable for expression parsing");
474 
475         ResetDeclMap(); // We are being careful here in the case of breakpoint conditions.
476 
477         return false;
478     }
479 
480     if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel)
481     {
482         DeclMap()->SetLookupsEnabled(true);
483     }
484 
485     Process *process = exe_ctx.GetProcessPtr();
486     ExecutionContextScope *exe_scope = process;
487 
488     if (!exe_scope)
489         exe_scope = exe_ctx.GetTargetPtr();
490 
491     // We use a shared pointer here so we can use the original parser - if it succeeds
492     // or the rewrite parser we might make if it fails.  But the parser_sp will never be empty.
493 
494     std::shared_ptr<ClangExpressionParser> parser_sp(new ClangExpressionParser(exe_scope, *this, generate_debug_info));
495 
496     unsigned num_errors = parser_sp->Parse(diagnostic_manager);
497 
498     // Check here for FixItHints.  If there are any try fixing the source and re-parsing...
499     if (num_errors && diagnostic_manager.HasFixIts() && diagnostic_manager.ShouldAutoApplyFixIts())
500     {
501         if (parser_sp->RewriteExpression(diagnostic_manager))
502         {
503             std::string backup_source = std::move(m_transformed_text);
504             m_transformed_text = diagnostic_manager.GetFixedExpression();
505             // Make a new diagnostic manager and parser, and try again with the rewritten expression:
506             // FIXME: It would be nice to reuse the parser we have but that doesn't seem to be possible.
507             DiagnosticManager rewrite_manager;
508             std::shared_ptr<ClangExpressionParser> rewrite_parser_sp(new ClangExpressionParser(exe_scope, *this, generate_debug_info));
509             unsigned rewrite_errors = rewrite_parser_sp->Parse(rewrite_manager);
510             if (rewrite_errors == 0)
511             {
512                 diagnostic_manager.Clear();
513                 parser_sp = rewrite_parser_sp;
514                 num_errors = 0;
515             }
516             else
517             {
518                 m_transformed_text = std::move(backup_source);
519             }
520         }
521     }
522 
523     if (num_errors)
524     {
525         diagnostic_manager.Printf(eDiagnosticSeverityError, "%u error%s parsing expression", num_errors,
526                                   num_errors == 1 ? "" : "s");
527 
528         ResetDeclMap(); // We are being careful here in the case of breakpoint conditions.
529 
530         return false;
531     }
532 
533     //////////////////////////////////////////////////////////////////////////////////////////
534     // Prepare the output of the parser for execution, evaluating it statically if possible
535     //
536 
537     {
538         Error jit_error = parser_sp->PrepareForExecution(m_jit_start_addr,
539                                                          m_jit_end_addr,
540                                                          m_execution_unit_sp,
541                                                          exe_ctx,
542                                                          m_can_interpret,
543                                                          execution_policy);
544 
545         if (!jit_error.Success())
546         {
547             const char *error_cstr = jit_error.AsCString();
548             if (error_cstr && error_cstr[0])
549                 diagnostic_manager.PutCString(eDiagnosticSeverityError, error_cstr);
550             else
551                 diagnostic_manager.PutCString(eDiagnosticSeverityError, "expression can't be interpreted or run");
552             return false;
553         }
554     }
555 
556     if (exe_ctx.GetProcessPtr() && execution_policy == eExecutionPolicyTopLevel)
557     {
558         Error static_init_error = parser_sp->RunStaticInitializers(m_execution_unit_sp, exe_ctx);
559 
560         if (!static_init_error.Success())
561         {
562             const char *error_cstr = static_init_error.AsCString();
563             if (error_cstr && error_cstr[0])
564                 diagnostic_manager.Printf(eDiagnosticSeverityError, "couldn't run static initializers: %s\n",
565                                           error_cstr);
566             else
567                 diagnostic_manager.PutCString(eDiagnosticSeverityError, "couldn't run static initializers\n");
568             return false;
569         }
570     }
571 
572     if (m_execution_unit_sp)
573     {
574         bool register_execution_unit = false;
575 
576         if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel)
577         {
578             register_execution_unit = true;
579         }
580 
581         // If there is more than one external function in the execution
582         // unit, it needs to keep living even if it's not top level, because
583         // the result could refer to that function.
584 
585         if (m_execution_unit_sp->GetJittedFunctions().size() > 1)
586         {
587             register_execution_unit = true;
588         }
589 
590         if (register_execution_unit)
591         {
592             llvm::cast<PersistentExpressionState>(
593                 exe_ctx.GetTargetPtr()->GetPersistentExpressionStateForLanguage(m_language))
594                 ->RegisterExecutionUnit(m_execution_unit_sp);
595         }
596     }
597 
598     if (generate_debug_info)
599     {
600         lldb::ModuleSP jit_module_sp(m_execution_unit_sp->GetJITModule());
601 
602         if (jit_module_sp)
603         {
604             ConstString const_func_name(FunctionName());
605             FileSpec jit_file;
606             jit_file.GetFilename() = const_func_name;
607             jit_module_sp->SetFileSpecAndObjectName (jit_file, ConstString());
608             m_jit_module_wp = jit_module_sp;
609             target->GetImages().Append(jit_module_sp);
610         }
611     }
612 
613     ResetDeclMap(); // Make this go away since we don't need any of its state after parsing.  This also gets rid of any
614                     // ClangASTImporter::Minions.
615 
616     if (process && m_jit_start_addr != LLDB_INVALID_ADDRESS)
617         m_jit_process_wp = lldb::ProcessWP(process->shared_from_this());
618     return true;
619 }
620 
621 bool
622 ClangUserExpression::AddArguments(ExecutionContext &exe_ctx, std::vector<lldb::addr_t> &args,
623                                   lldb::addr_t struct_address, DiagnosticManager &diagnostic_manager)
624 {
625     lldb::addr_t object_ptr = LLDB_INVALID_ADDRESS;
626     lldb::addr_t cmd_ptr = LLDB_INVALID_ADDRESS;
627 
628     if (m_needs_object_ptr)
629     {
630         lldb::StackFrameSP frame_sp = exe_ctx.GetFrameSP();
631         if (!frame_sp)
632             return true;
633 
634         ConstString object_name;
635 
636         if (m_in_cplusplus_method)
637         {
638             object_name.SetCString("this");
639         }
640         else if (m_in_objectivec_method)
641         {
642             object_name.SetCString("self");
643         }
644         else
645         {
646             diagnostic_manager.PutCString(eDiagnosticSeverityError, "need object pointer but don't know the language");
647             return false;
648         }
649 
650         Error object_ptr_error;
651 
652         object_ptr = GetObjectPointer(frame_sp, object_name, object_ptr_error);
653 
654         if (!object_ptr_error.Success())
655         {
656             diagnostic_manager.Printf(eDiagnosticSeverityWarning,
657                                       "couldn't get required object pointer (substituting NULL): %s",
658                                       object_ptr_error.AsCString());
659             object_ptr = 0;
660         }
661 
662         if (m_in_objectivec_method)
663         {
664             ConstString cmd_name("_cmd");
665 
666             cmd_ptr = GetObjectPointer(frame_sp, cmd_name, object_ptr_error);
667 
668             if (!object_ptr_error.Success())
669             {
670                 diagnostic_manager.Printf(eDiagnosticSeverityWarning,
671                                           "couldn't get cmd pointer (substituting NULL): %s",
672                                           object_ptr_error.AsCString());
673                 cmd_ptr = 0;
674             }
675         }
676         if (object_ptr)
677             args.push_back(object_ptr);
678 
679         if (m_in_objectivec_method)
680             args.push_back(cmd_ptr);
681 
682         args.push_back(struct_address);
683     }
684     else
685     {
686         args.push_back(struct_address);
687     }
688     return true;
689 }
690 
691 lldb::ExpressionVariableSP
692 ClangUserExpression::GetResultAfterDematerialization(ExecutionContextScope *exe_scope)
693 {
694     return m_result_delegate.GetVariable();
695 }
696 
697 void
698 ClangUserExpression::ClangUserExpressionHelper::ResetDeclMap(ExecutionContext &exe_ctx, Materializer::PersistentVariableDelegate &delegate, bool keep_result_in_memory)
699 {
700     m_expr_decl_map_up.reset(new ClangExpressionDeclMap(keep_result_in_memory, &delegate, exe_ctx));
701 }
702 
703 clang::ASTConsumer *
704 ClangUserExpression::ClangUserExpressionHelper::ASTTransformer(clang::ASTConsumer *passthrough)
705 {
706     m_result_synthesizer_up.reset(new ASTResultSynthesizer(passthrough, m_top_level, m_target));
707 
708     return m_result_synthesizer_up.get();
709 }
710 
711 void
712 ClangUserExpression::ClangUserExpressionHelper::CommitPersistentDecls()
713 {
714     if (m_result_synthesizer_up.get())
715     {
716         m_result_synthesizer_up->CommitPersistentDecls();
717     }
718 }
719 
720 ClangUserExpression::ResultDelegate::ResultDelegate()
721 {
722 }
723 
724 ConstString
725 ClangUserExpression::ResultDelegate::GetName()
726 {
727     return m_persistent_state->GetNextPersistentVariableName();
728 }
729 
730 void
731 ClangUserExpression::ResultDelegate::DidDematerialize(lldb::ExpressionVariableSP &variable)
732 {
733     m_variable = variable;
734 }
735 
736 void
737 ClangUserExpression::ResultDelegate::RegisterPersistentState(PersistentExpressionState *persistent_state)
738 {
739     m_persistent_state = persistent_state;
740 }
741 
742 lldb::ExpressionVariableSP &
743 ClangUserExpression::ResultDelegate::GetVariable()
744 {
745     return m_variable;
746 }
747 
748