xref: /openbsd-src/gnu/llvm/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp (revision dda2819751e49c83612958492e38917049128b41)
1*dda28197Spatrick //===-- ClangUserExpression.cpp -------------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick 
9061da546Spatrick #include "lldb/Host/Config.h"
10061da546Spatrick 
11061da546Spatrick #include <stdio.h>
12061da546Spatrick #if HAVE_SYS_TYPES_H
13061da546Spatrick #include <sys/types.h>
14061da546Spatrick #endif
15061da546Spatrick 
16061da546Spatrick #include <cstdlib>
17061da546Spatrick #include <map>
18061da546Spatrick #include <string>
19061da546Spatrick 
20061da546Spatrick #include "ClangUserExpression.h"
21061da546Spatrick 
22061da546Spatrick #include "ASTResultSynthesizer.h"
23*dda28197Spatrick #include "ClangASTMetadata.h"
24061da546Spatrick #include "ClangDiagnostic.h"
25061da546Spatrick #include "ClangExpressionDeclMap.h"
26061da546Spatrick #include "ClangExpressionParser.h"
27061da546Spatrick #include "ClangModulesDeclVendor.h"
28061da546Spatrick #include "ClangPersistentVariables.h"
29061da546Spatrick #include "CppModuleConfiguration.h"
30061da546Spatrick 
31*dda28197Spatrick #include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
32061da546Spatrick #include "lldb/Core/Debugger.h"
33061da546Spatrick #include "lldb/Core/Module.h"
34061da546Spatrick #include "lldb/Core/StreamFile.h"
35061da546Spatrick #include "lldb/Core/ValueObjectConstResult.h"
36061da546Spatrick #include "lldb/Expression/ExpressionSourceCode.h"
37061da546Spatrick #include "lldb/Expression/IRExecutionUnit.h"
38061da546Spatrick #include "lldb/Expression/IRInterpreter.h"
39061da546Spatrick #include "lldb/Expression/Materializer.h"
40061da546Spatrick #include "lldb/Host/HostInfo.h"
41061da546Spatrick #include "lldb/Symbol/Block.h"
42061da546Spatrick #include "lldb/Symbol/CompileUnit.h"
43061da546Spatrick #include "lldb/Symbol/Function.h"
44061da546Spatrick #include "lldb/Symbol/ObjectFile.h"
45061da546Spatrick #include "lldb/Symbol/SymbolFile.h"
46061da546Spatrick #include "lldb/Symbol/SymbolVendor.h"
47061da546Spatrick #include "lldb/Symbol/Type.h"
48061da546Spatrick #include "lldb/Symbol/VariableList.h"
49061da546Spatrick #include "lldb/Target/ExecutionContext.h"
50061da546Spatrick #include "lldb/Target/Process.h"
51061da546Spatrick #include "lldb/Target/StackFrame.h"
52061da546Spatrick #include "lldb/Target/Target.h"
53061da546Spatrick #include "lldb/Target/ThreadPlan.h"
54061da546Spatrick #include "lldb/Target/ThreadPlanCallUserExpression.h"
55061da546Spatrick #include "lldb/Utility/ConstString.h"
56061da546Spatrick #include "lldb/Utility/Log.h"
57061da546Spatrick #include "lldb/Utility/StreamString.h"
58061da546Spatrick 
59061da546Spatrick #include "clang/AST/DeclCXX.h"
60061da546Spatrick #include "clang/AST/DeclObjC.h"
61061da546Spatrick 
62061da546Spatrick #include "llvm/ADT/ScopeExit.h"
63061da546Spatrick 
64061da546Spatrick using namespace lldb_private;
65061da546Spatrick 
66061da546Spatrick char ClangUserExpression::ID;
67061da546Spatrick 
68061da546Spatrick ClangUserExpression::ClangUserExpression(
69061da546Spatrick     ExecutionContextScope &exe_scope, llvm::StringRef expr,
70061da546Spatrick     llvm::StringRef prefix, lldb::LanguageType language,
71061da546Spatrick     ResultType desired_type, const EvaluateExpressionOptions &options,
72061da546Spatrick     ValueObject *ctx_obj)
73061da546Spatrick     : LLVMUserExpression(exe_scope, expr, prefix, language, desired_type,
74061da546Spatrick                          options),
75061da546Spatrick       m_type_system_helper(*m_target_wp.lock(), options.GetExecutionPolicy() ==
76061da546Spatrick                                                     eExecutionPolicyTopLevel),
77061da546Spatrick       m_result_delegate(exe_scope.CalculateTarget()), m_ctx_obj(ctx_obj) {
78061da546Spatrick   switch (m_language) {
79061da546Spatrick   case lldb::eLanguageTypeC_plus_plus:
80061da546Spatrick     m_allow_cxx = true;
81061da546Spatrick     break;
82061da546Spatrick   case lldb::eLanguageTypeObjC:
83061da546Spatrick     m_allow_objc = true;
84061da546Spatrick     break;
85061da546Spatrick   case lldb::eLanguageTypeObjC_plus_plus:
86061da546Spatrick   default:
87061da546Spatrick     m_allow_cxx = true;
88061da546Spatrick     m_allow_objc = true;
89061da546Spatrick     break;
90061da546Spatrick   }
91061da546Spatrick }
92061da546Spatrick 
93061da546Spatrick ClangUserExpression::~ClangUserExpression() {}
94061da546Spatrick 
95061da546Spatrick void ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Status &err) {
96061da546Spatrick   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
97061da546Spatrick 
98061da546Spatrick   LLDB_LOGF(log, "ClangUserExpression::ScanContext()");
99061da546Spatrick 
100061da546Spatrick   m_target = exe_ctx.GetTargetPtr();
101061da546Spatrick 
102061da546Spatrick   if (!(m_allow_cxx || m_allow_objc)) {
103061da546Spatrick     LLDB_LOGF(log, "  [CUE::SC] Settings inhibit C++ and Objective-C");
104061da546Spatrick     return;
105061da546Spatrick   }
106061da546Spatrick 
107061da546Spatrick   StackFrame *frame = exe_ctx.GetFramePtr();
108061da546Spatrick   if (frame == nullptr) {
109061da546Spatrick     LLDB_LOGF(log, "  [CUE::SC] Null stack frame");
110061da546Spatrick     return;
111061da546Spatrick   }
112061da546Spatrick 
113061da546Spatrick   SymbolContext sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction |
114061da546Spatrick                                                   lldb::eSymbolContextBlock);
115061da546Spatrick 
116061da546Spatrick   if (!sym_ctx.function) {
117061da546Spatrick     LLDB_LOGF(log, "  [CUE::SC] Null function");
118061da546Spatrick     return;
119061da546Spatrick   }
120061da546Spatrick 
121061da546Spatrick   // Find the block that defines the function represented by "sym_ctx"
122061da546Spatrick   Block *function_block = sym_ctx.GetFunctionBlock();
123061da546Spatrick 
124061da546Spatrick   if (!function_block) {
125061da546Spatrick     LLDB_LOGF(log, "  [CUE::SC] Null function block");
126061da546Spatrick     return;
127061da546Spatrick   }
128061da546Spatrick 
129061da546Spatrick   CompilerDeclContext decl_context = function_block->GetDeclContext();
130061da546Spatrick 
131061da546Spatrick   if (!decl_context) {
132061da546Spatrick     LLDB_LOGF(log, "  [CUE::SC] Null decl context");
133061da546Spatrick     return;
134061da546Spatrick   }
135061da546Spatrick 
136061da546Spatrick   if (m_ctx_obj) {
137061da546Spatrick     switch (m_ctx_obj->GetObjectRuntimeLanguage()) {
138061da546Spatrick     case lldb::eLanguageTypeC:
139061da546Spatrick     case lldb::eLanguageTypeC89:
140061da546Spatrick     case lldb::eLanguageTypeC99:
141061da546Spatrick     case lldb::eLanguageTypeC11:
142061da546Spatrick     case lldb::eLanguageTypeC_plus_plus:
143061da546Spatrick     case lldb::eLanguageTypeC_plus_plus_03:
144061da546Spatrick     case lldb::eLanguageTypeC_plus_plus_11:
145061da546Spatrick     case lldb::eLanguageTypeC_plus_plus_14:
146061da546Spatrick       m_in_cplusplus_method = true;
147061da546Spatrick       break;
148061da546Spatrick     case lldb::eLanguageTypeObjC:
149061da546Spatrick     case lldb::eLanguageTypeObjC_plus_plus:
150061da546Spatrick       m_in_objectivec_method = true;
151061da546Spatrick       break;
152061da546Spatrick     default:
153061da546Spatrick       break;
154061da546Spatrick     }
155061da546Spatrick     m_needs_object_ptr = true;
156061da546Spatrick   } else if (clang::CXXMethodDecl *method_decl =
157*dda28197Spatrick           TypeSystemClang::DeclContextGetAsCXXMethodDecl(decl_context)) {
158061da546Spatrick     if (m_allow_cxx && method_decl->isInstance()) {
159061da546Spatrick       if (m_enforce_valid_object) {
160061da546Spatrick         lldb::VariableListSP variable_list_sp(
161061da546Spatrick             function_block->GetBlockVariableList(true));
162061da546Spatrick 
163061da546Spatrick         const char *thisErrorString = "Stopped in a C++ method, but 'this' "
164061da546Spatrick                                       "isn't available; pretending we are in a "
165061da546Spatrick                                       "generic context";
166061da546Spatrick 
167061da546Spatrick         if (!variable_list_sp) {
168061da546Spatrick           err.SetErrorString(thisErrorString);
169061da546Spatrick           return;
170061da546Spatrick         }
171061da546Spatrick 
172061da546Spatrick         lldb::VariableSP this_var_sp(
173061da546Spatrick             variable_list_sp->FindVariable(ConstString("this")));
174061da546Spatrick 
175061da546Spatrick         if (!this_var_sp || !this_var_sp->IsInScope(frame) ||
176061da546Spatrick             !this_var_sp->LocationIsValidForFrame(frame)) {
177061da546Spatrick           err.SetErrorString(thisErrorString);
178061da546Spatrick           return;
179061da546Spatrick         }
180061da546Spatrick       }
181061da546Spatrick 
182061da546Spatrick       m_in_cplusplus_method = true;
183061da546Spatrick       m_needs_object_ptr = true;
184061da546Spatrick     }
185061da546Spatrick   } else if (clang::ObjCMethodDecl *method_decl =
186*dda28197Spatrick                  TypeSystemClang::DeclContextGetAsObjCMethodDecl(
187061da546Spatrick                      decl_context)) {
188061da546Spatrick     if (m_allow_objc) {
189061da546Spatrick       if (m_enforce_valid_object) {
190061da546Spatrick         lldb::VariableListSP variable_list_sp(
191061da546Spatrick             function_block->GetBlockVariableList(true));
192061da546Spatrick 
193061da546Spatrick         const char *selfErrorString = "Stopped in an Objective-C method, but "
194061da546Spatrick                                       "'self' isn't available; pretending we "
195061da546Spatrick                                       "are in a generic context";
196061da546Spatrick 
197061da546Spatrick         if (!variable_list_sp) {
198061da546Spatrick           err.SetErrorString(selfErrorString);
199061da546Spatrick           return;
200061da546Spatrick         }
201061da546Spatrick 
202061da546Spatrick         lldb::VariableSP self_variable_sp =
203061da546Spatrick             variable_list_sp->FindVariable(ConstString("self"));
204061da546Spatrick 
205061da546Spatrick         if (!self_variable_sp || !self_variable_sp->IsInScope(frame) ||
206061da546Spatrick             !self_variable_sp->LocationIsValidForFrame(frame)) {
207061da546Spatrick           err.SetErrorString(selfErrorString);
208061da546Spatrick           return;
209061da546Spatrick         }
210061da546Spatrick       }
211061da546Spatrick 
212061da546Spatrick       m_in_objectivec_method = true;
213061da546Spatrick       m_needs_object_ptr = true;
214061da546Spatrick 
215061da546Spatrick       if (!method_decl->isInstanceMethod())
216061da546Spatrick         m_in_static_method = true;
217061da546Spatrick     }
218061da546Spatrick   } else if (clang::FunctionDecl *function_decl =
219*dda28197Spatrick                  TypeSystemClang::DeclContextGetAsFunctionDecl(decl_context)) {
220061da546Spatrick     // We might also have a function that said in the debug information that it
221061da546Spatrick     // captured an object pointer.  The best way to deal with getting to the
222061da546Spatrick     // ivars at present is by pretending that this is a method of a class in
223061da546Spatrick     // whatever runtime the debug info says the object pointer belongs to.  Do
224061da546Spatrick     // that here.
225061da546Spatrick 
226061da546Spatrick     ClangASTMetadata *metadata =
227*dda28197Spatrick         TypeSystemClang::DeclContextGetMetaData(decl_context, function_decl);
228061da546Spatrick     if (metadata && metadata->HasObjectPtr()) {
229061da546Spatrick       lldb::LanguageType language = metadata->GetObjectPtrLanguage();
230061da546Spatrick       if (language == lldb::eLanguageTypeC_plus_plus) {
231061da546Spatrick         if (m_enforce_valid_object) {
232061da546Spatrick           lldb::VariableListSP variable_list_sp(
233061da546Spatrick               function_block->GetBlockVariableList(true));
234061da546Spatrick 
235061da546Spatrick           const char *thisErrorString = "Stopped in a context claiming to "
236061da546Spatrick                                         "capture a C++ object pointer, but "
237061da546Spatrick                                         "'this' isn't available; pretending we "
238061da546Spatrick                                         "are in a generic context";
239061da546Spatrick 
240061da546Spatrick           if (!variable_list_sp) {
241061da546Spatrick             err.SetErrorString(thisErrorString);
242061da546Spatrick             return;
243061da546Spatrick           }
244061da546Spatrick 
245061da546Spatrick           lldb::VariableSP this_var_sp(
246061da546Spatrick               variable_list_sp->FindVariable(ConstString("this")));
247061da546Spatrick 
248061da546Spatrick           if (!this_var_sp || !this_var_sp->IsInScope(frame) ||
249061da546Spatrick               !this_var_sp->LocationIsValidForFrame(frame)) {
250061da546Spatrick             err.SetErrorString(thisErrorString);
251061da546Spatrick             return;
252061da546Spatrick           }
253061da546Spatrick         }
254061da546Spatrick 
255061da546Spatrick         m_in_cplusplus_method = true;
256061da546Spatrick         m_needs_object_ptr = true;
257061da546Spatrick       } else if (language == lldb::eLanguageTypeObjC) {
258061da546Spatrick         if (m_enforce_valid_object) {
259061da546Spatrick           lldb::VariableListSP variable_list_sp(
260061da546Spatrick               function_block->GetBlockVariableList(true));
261061da546Spatrick 
262061da546Spatrick           const char *selfErrorString =
263061da546Spatrick               "Stopped in a context claiming to capture an Objective-C object "
264061da546Spatrick               "pointer, but 'self' isn't available; pretending we are in a "
265061da546Spatrick               "generic context";
266061da546Spatrick 
267061da546Spatrick           if (!variable_list_sp) {
268061da546Spatrick             err.SetErrorString(selfErrorString);
269061da546Spatrick             return;
270061da546Spatrick           }
271061da546Spatrick 
272061da546Spatrick           lldb::VariableSP self_variable_sp =
273061da546Spatrick               variable_list_sp->FindVariable(ConstString("self"));
274061da546Spatrick 
275061da546Spatrick           if (!self_variable_sp || !self_variable_sp->IsInScope(frame) ||
276061da546Spatrick               !self_variable_sp->LocationIsValidForFrame(frame)) {
277061da546Spatrick             err.SetErrorString(selfErrorString);
278061da546Spatrick             return;
279061da546Spatrick           }
280061da546Spatrick 
281061da546Spatrick           Type *self_type = self_variable_sp->GetType();
282061da546Spatrick 
283061da546Spatrick           if (!self_type) {
284061da546Spatrick             err.SetErrorString(selfErrorString);
285061da546Spatrick             return;
286061da546Spatrick           }
287061da546Spatrick 
288061da546Spatrick           CompilerType self_clang_type = self_type->GetForwardCompilerType();
289061da546Spatrick 
290061da546Spatrick           if (!self_clang_type) {
291061da546Spatrick             err.SetErrorString(selfErrorString);
292061da546Spatrick             return;
293061da546Spatrick           }
294061da546Spatrick 
295*dda28197Spatrick           if (TypeSystemClang::IsObjCClassType(self_clang_type)) {
296061da546Spatrick             return;
297*dda28197Spatrick           } else if (TypeSystemClang::IsObjCObjectPointerType(
298061da546Spatrick                          self_clang_type)) {
299061da546Spatrick             m_in_objectivec_method = true;
300061da546Spatrick             m_needs_object_ptr = true;
301061da546Spatrick           } else {
302061da546Spatrick             err.SetErrorString(selfErrorString);
303061da546Spatrick             return;
304061da546Spatrick           }
305061da546Spatrick         } else {
306061da546Spatrick           m_in_objectivec_method = true;
307061da546Spatrick           m_needs_object_ptr = true;
308061da546Spatrick         }
309061da546Spatrick       }
310061da546Spatrick     }
311061da546Spatrick   }
312061da546Spatrick }
313061da546Spatrick 
314061da546Spatrick // This is a really nasty hack, meant to fix Objective-C expressions of the
315061da546Spatrick // form (int)[myArray count].  Right now, because the type information for
316061da546Spatrick // count is not available, [myArray count] returns id, which can't be directly
317061da546Spatrick // cast to int without causing a clang error.
318061da546Spatrick static void ApplyObjcCastHack(std::string &expr) {
319061da546Spatrick   const std::string from = "(int)[";
320061da546Spatrick   const std::string to = "(int)(long long)[";
321061da546Spatrick 
322061da546Spatrick   size_t offset;
323061da546Spatrick 
324061da546Spatrick   while ((offset = expr.find(from)) != expr.npos)
325061da546Spatrick     expr.replace(offset, from.size(), to);
326061da546Spatrick }
327061da546Spatrick 
328061da546Spatrick bool ClangUserExpression::SetupPersistentState(DiagnosticManager &diagnostic_manager,
329061da546Spatrick                                  ExecutionContext &exe_ctx) {
330061da546Spatrick   if (Target *target = exe_ctx.GetTargetPtr()) {
331061da546Spatrick     if (PersistentExpressionState *persistent_state =
332061da546Spatrick             target->GetPersistentExpressionStateForLanguage(
333061da546Spatrick                 lldb::eLanguageTypeC)) {
334061da546Spatrick       m_clang_state = llvm::cast<ClangPersistentVariables>(persistent_state);
335061da546Spatrick       m_result_delegate.RegisterPersistentState(persistent_state);
336061da546Spatrick     } else {
337061da546Spatrick       diagnostic_manager.PutString(
338061da546Spatrick           eDiagnosticSeverityError,
339061da546Spatrick           "couldn't start parsing (no persistent data)");
340061da546Spatrick       return false;
341061da546Spatrick     }
342061da546Spatrick   } else {
343061da546Spatrick     diagnostic_manager.PutString(eDiagnosticSeverityError,
344061da546Spatrick                                  "error: couldn't start parsing (no target)");
345061da546Spatrick     return false;
346061da546Spatrick   }
347061da546Spatrick   return true;
348061da546Spatrick }
349061da546Spatrick 
350*dda28197Spatrick static void SetupDeclVendor(ExecutionContext &exe_ctx, Target *target,
351*dda28197Spatrick                             DiagnosticManager &diagnostic_manager) {
352*dda28197Spatrick   ClangModulesDeclVendor *decl_vendor = target->GetClangModulesDeclVendor();
353*dda28197Spatrick   if (!decl_vendor)
354*dda28197Spatrick     return;
355*dda28197Spatrick 
356*dda28197Spatrick   if (!target->GetEnableAutoImportClangModules())
357*dda28197Spatrick     return;
358*dda28197Spatrick 
359061da546Spatrick   auto *persistent_state = llvm::cast<ClangPersistentVariables>(
360061da546Spatrick       target->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC));
361061da546Spatrick   if (!persistent_state)
362061da546Spatrick     return;
363061da546Spatrick 
364*dda28197Spatrick   StackFrame *frame = exe_ctx.GetFramePtr();
365*dda28197Spatrick   if (!frame)
366*dda28197Spatrick     return;
367061da546Spatrick 
368*dda28197Spatrick   Block *block = frame->GetFrameBlock();
369*dda28197Spatrick   if (!block)
370*dda28197Spatrick     return;
371061da546Spatrick   SymbolContext sc;
372061da546Spatrick 
373061da546Spatrick   block->CalculateSymbolContext(&sc);
374061da546Spatrick 
375*dda28197Spatrick   if (!sc.comp_unit)
376*dda28197Spatrick     return;
377061da546Spatrick   StreamString error_stream;
378061da546Spatrick 
379*dda28197Spatrick   ClangModulesDeclVendor::ModuleVector modules_for_macros =
380*dda28197Spatrick       persistent_state->GetHandLoadedClangModules();
381*dda28197Spatrick   if (decl_vendor->AddModulesForCompileUnit(*sc.comp_unit, modules_for_macros,
382*dda28197Spatrick                                             error_stream))
383*dda28197Spatrick     return;
384*dda28197Spatrick 
385*dda28197Spatrick   // Failed to load some modules, so emit the error stream as a diagnostic.
386*dda28197Spatrick   if (!error_stream.Empty()) {
387*dda28197Spatrick     // The error stream already contains several Clang diagnostics that might
388*dda28197Spatrick     // be either errors or warnings, so just print them all as one remark
389*dda28197Spatrick     // diagnostic to prevent that the message starts with "error: error:".
390*dda28197Spatrick     diagnostic_manager.PutString(eDiagnosticSeverityRemark,
391*dda28197Spatrick                                  error_stream.GetString());
392*dda28197Spatrick     return;
393061da546Spatrick   }
394061da546Spatrick 
395*dda28197Spatrick   diagnostic_manager.PutString(eDiagnosticSeverityError,
396*dda28197Spatrick                                "Unknown error while loading modules needed for "
397*dda28197Spatrick                                "current compilation unit.");
398*dda28197Spatrick }
399*dda28197Spatrick 
400*dda28197Spatrick ClangExpressionSourceCode::WrapKind ClangUserExpression::GetWrapKind() const {
401*dda28197Spatrick   assert(m_options.GetExecutionPolicy() != eExecutionPolicyTopLevel &&
402*dda28197Spatrick          "Top level expressions aren't wrapped.");
403*dda28197Spatrick   using Kind = ClangExpressionSourceCode::WrapKind;
404061da546Spatrick   if (m_in_cplusplus_method)
405*dda28197Spatrick     return Kind::CppMemberFunction;
406*dda28197Spatrick   else if (m_in_objectivec_method) {
407*dda28197Spatrick     if (m_in_static_method)
408*dda28197Spatrick       return Kind::ObjCStaticMethod;
409*dda28197Spatrick     return Kind::ObjCInstanceMethod;
410*dda28197Spatrick   }
411*dda28197Spatrick   // Not in any kind of 'special' function, so just wrap it in a normal C
412*dda28197Spatrick   // function.
413*dda28197Spatrick   return Kind::Function;
414061da546Spatrick }
415061da546Spatrick 
416061da546Spatrick void ClangUserExpression::CreateSourceCode(
417061da546Spatrick     DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx,
418061da546Spatrick     std::vector<std::string> modules_to_import, bool for_completion) {
419061da546Spatrick 
420061da546Spatrick   m_filename = m_clang_state->GetNextExprFileName();
421061da546Spatrick   std::string prefix = m_expr_prefix;
422061da546Spatrick 
423061da546Spatrick   if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel) {
424061da546Spatrick     m_transformed_text = m_expr_text;
425061da546Spatrick   } else {
426061da546Spatrick     m_source_code.reset(ClangExpressionSourceCode::CreateWrapped(
427*dda28197Spatrick         m_filename, prefix, m_expr_text, GetWrapKind()));
428061da546Spatrick 
429*dda28197Spatrick     if (!m_source_code->GetText(m_transformed_text, exe_ctx, !m_ctx_obj,
430061da546Spatrick                                 for_completion, modules_to_import)) {
431061da546Spatrick       diagnostic_manager.PutString(eDiagnosticSeverityError,
432061da546Spatrick                                    "couldn't construct expression body");
433061da546Spatrick       return;
434061da546Spatrick     }
435061da546Spatrick 
436061da546Spatrick     // Find and store the start position of the original code inside the
437061da546Spatrick     // transformed code. We need this later for the code completion.
438061da546Spatrick     std::size_t original_start;
439061da546Spatrick     std::size_t original_end;
440061da546Spatrick     bool found_bounds = m_source_code->GetOriginalBodyBounds(
441*dda28197Spatrick         m_transformed_text, original_start, original_end);
442061da546Spatrick     if (found_bounds)
443061da546Spatrick       m_user_expression_start_pos = original_start;
444061da546Spatrick   }
445061da546Spatrick }
446061da546Spatrick 
447061da546Spatrick static bool SupportsCxxModuleImport(lldb::LanguageType language) {
448061da546Spatrick   switch (language) {
449061da546Spatrick   case lldb::eLanguageTypeC_plus_plus:
450061da546Spatrick   case lldb::eLanguageTypeC_plus_plus_03:
451061da546Spatrick   case lldb::eLanguageTypeC_plus_plus_11:
452061da546Spatrick   case lldb::eLanguageTypeC_plus_plus_14:
453061da546Spatrick   case lldb::eLanguageTypeObjC_plus_plus:
454061da546Spatrick     return true;
455061da546Spatrick   default:
456061da546Spatrick     return false;
457061da546Spatrick   }
458061da546Spatrick }
459061da546Spatrick 
460061da546Spatrick /// Utility method that puts a message into the expression log and
461061da546Spatrick /// returns an invalid module configuration.
462061da546Spatrick static CppModuleConfiguration LogConfigError(const std::string &msg) {
463061da546Spatrick   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
464061da546Spatrick   LLDB_LOG(log, "[C++ module config] {0}", msg);
465061da546Spatrick   return CppModuleConfiguration();
466061da546Spatrick }
467061da546Spatrick 
468061da546Spatrick CppModuleConfiguration GetModuleConfig(lldb::LanguageType language,
469061da546Spatrick                                        ExecutionContext &exe_ctx) {
470061da546Spatrick   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
471061da546Spatrick 
472061da546Spatrick   // Don't do anything if this is not a C++ module configuration.
473061da546Spatrick   if (!SupportsCxxModuleImport(language))
474061da546Spatrick     return LogConfigError("Language doesn't support C++ modules");
475061da546Spatrick 
476061da546Spatrick   Target *target = exe_ctx.GetTargetPtr();
477061da546Spatrick   if (!target)
478061da546Spatrick     return LogConfigError("No target");
479061da546Spatrick 
480061da546Spatrick   if (!target->GetEnableImportStdModule())
481061da546Spatrick     return LogConfigError("Importing std module not enabled in settings");
482061da546Spatrick 
483061da546Spatrick   StackFrame *frame = exe_ctx.GetFramePtr();
484061da546Spatrick   if (!frame)
485061da546Spatrick     return LogConfigError("No frame");
486061da546Spatrick 
487061da546Spatrick   Block *block = frame->GetFrameBlock();
488061da546Spatrick   if (!block)
489061da546Spatrick     return LogConfigError("No block");
490061da546Spatrick 
491061da546Spatrick   SymbolContext sc;
492061da546Spatrick   block->CalculateSymbolContext(&sc);
493061da546Spatrick   if (!sc.comp_unit)
494061da546Spatrick     return LogConfigError("Couldn't calculate symbol context");
495061da546Spatrick 
496061da546Spatrick   // Build a list of files we need to analyze to build the configuration.
497061da546Spatrick   FileSpecList files;
498061da546Spatrick   for (const FileSpec &f : sc.comp_unit->GetSupportFiles())
499061da546Spatrick     files.AppendIfUnique(f);
500061da546Spatrick   // We also need to look at external modules in the case of -gmodules as they
501061da546Spatrick   // contain the support files for libc++ and the C library.
502061da546Spatrick   llvm::DenseSet<SymbolFile *> visited_symbol_files;
503061da546Spatrick   sc.comp_unit->ForEachExternalModule(
504061da546Spatrick       visited_symbol_files, [&files](Module &module) {
505061da546Spatrick         for (std::size_t i = 0; i < module.GetNumCompileUnits(); ++i) {
506061da546Spatrick           const FileSpecList &support_files =
507061da546Spatrick               module.GetCompileUnitAtIndex(i)->GetSupportFiles();
508061da546Spatrick           for (const FileSpec &f : support_files) {
509061da546Spatrick             files.AppendIfUnique(f);
510061da546Spatrick           }
511061da546Spatrick         }
512061da546Spatrick         return false;
513061da546Spatrick       });
514061da546Spatrick 
515061da546Spatrick   LLDB_LOG(log, "[C++ module config] Found {0} support files to analyze",
516061da546Spatrick            files.GetSize());
517061da546Spatrick   if (log && log->GetVerbose()) {
518061da546Spatrick     for (const FileSpec &f : files)
519061da546Spatrick       LLDB_LOGV(log, "[C++ module config] Analyzing support file: {0}",
520061da546Spatrick                 f.GetPath());
521061da546Spatrick   }
522061da546Spatrick 
523061da546Spatrick   // Try to create a configuration from the files. If there is no valid
524061da546Spatrick   // configuration possible with the files, this just returns an invalid
525061da546Spatrick   // configuration.
526061da546Spatrick   return CppModuleConfiguration(files);
527061da546Spatrick }
528061da546Spatrick 
529061da546Spatrick bool ClangUserExpression::PrepareForParsing(
530061da546Spatrick     DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx,
531061da546Spatrick     bool for_completion) {
532061da546Spatrick   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
533061da546Spatrick 
534061da546Spatrick   InstallContext(exe_ctx);
535061da546Spatrick 
536061da546Spatrick   if (!SetupPersistentState(diagnostic_manager, exe_ctx))
537061da546Spatrick     return false;
538061da546Spatrick 
539061da546Spatrick   Status err;
540061da546Spatrick   ScanContext(exe_ctx, err);
541061da546Spatrick 
542061da546Spatrick   if (!err.Success()) {
543061da546Spatrick     diagnostic_manager.PutString(eDiagnosticSeverityWarning, err.AsCString());
544061da546Spatrick   }
545061da546Spatrick 
546061da546Spatrick   ////////////////////////////////////
547061da546Spatrick   // Generate the expression
548061da546Spatrick   //
549061da546Spatrick 
550061da546Spatrick   ApplyObjcCastHack(m_expr_text);
551061da546Spatrick 
552*dda28197Spatrick   SetupDeclVendor(exe_ctx, m_target, diagnostic_manager);
553061da546Spatrick 
554061da546Spatrick   CppModuleConfiguration module_config = GetModuleConfig(m_language, exe_ctx);
555061da546Spatrick   llvm::ArrayRef<std::string> imported_modules =
556061da546Spatrick       module_config.GetImportedModules();
557061da546Spatrick   m_imported_cpp_modules = !imported_modules.empty();
558061da546Spatrick   m_include_directories = module_config.GetIncludeDirs();
559061da546Spatrick 
560061da546Spatrick   LLDB_LOG(log, "List of imported modules in expression: {0}",
561061da546Spatrick            llvm::make_range(imported_modules.begin(), imported_modules.end()));
562061da546Spatrick   LLDB_LOG(log, "List of include directories gathered for modules: {0}",
563061da546Spatrick            llvm::make_range(m_include_directories.begin(),
564061da546Spatrick                             m_include_directories.end()));
565061da546Spatrick 
566061da546Spatrick   CreateSourceCode(diagnostic_manager, exe_ctx, imported_modules,
567061da546Spatrick                    for_completion);
568061da546Spatrick   return true;
569061da546Spatrick }
570061da546Spatrick 
571061da546Spatrick bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager,
572061da546Spatrick                                 ExecutionContext &exe_ctx,
573061da546Spatrick                                 lldb_private::ExecutionPolicy execution_policy,
574061da546Spatrick                                 bool keep_result_in_memory,
575061da546Spatrick                                 bool generate_debug_info) {
576061da546Spatrick   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
577061da546Spatrick 
578061da546Spatrick   if (!PrepareForParsing(diagnostic_manager, exe_ctx, /*for_completion*/ false))
579061da546Spatrick     return false;
580061da546Spatrick 
581061da546Spatrick   LLDB_LOGF(log, "Parsing the following code:\n%s", m_transformed_text.c_str());
582061da546Spatrick 
583061da546Spatrick   ////////////////////////////////////
584061da546Spatrick   // Set up the target and compiler
585061da546Spatrick   //
586061da546Spatrick 
587061da546Spatrick   Target *target = exe_ctx.GetTargetPtr();
588061da546Spatrick 
589061da546Spatrick   if (!target) {
590061da546Spatrick     diagnostic_manager.PutString(eDiagnosticSeverityError, "invalid target");
591061da546Spatrick     return false;
592061da546Spatrick   }
593061da546Spatrick 
594061da546Spatrick   //////////////////////////
595061da546Spatrick   // Parse the expression
596061da546Spatrick   //
597061da546Spatrick 
598*dda28197Spatrick   m_materializer_up = std::make_unique<Materializer>();
599061da546Spatrick 
600061da546Spatrick   ResetDeclMap(exe_ctx, m_result_delegate, keep_result_in_memory);
601061da546Spatrick 
602061da546Spatrick   auto on_exit = llvm::make_scope_exit([this]() { ResetDeclMap(); });
603061da546Spatrick 
604061da546Spatrick   if (!DeclMap()->WillParse(exe_ctx, GetMaterializer())) {
605061da546Spatrick     diagnostic_manager.PutString(
606061da546Spatrick         eDiagnosticSeverityError,
607061da546Spatrick         "current process state is unsuitable for expression parsing");
608061da546Spatrick     return false;
609061da546Spatrick   }
610061da546Spatrick 
611061da546Spatrick   if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel) {
612061da546Spatrick     DeclMap()->SetLookupsEnabled(true);
613061da546Spatrick   }
614061da546Spatrick 
615061da546Spatrick   Process *process = exe_ctx.GetProcessPtr();
616061da546Spatrick   ExecutionContextScope *exe_scope = process;
617061da546Spatrick 
618061da546Spatrick   if (!exe_scope)
619061da546Spatrick     exe_scope = exe_ctx.GetTargetPtr();
620061da546Spatrick 
621061da546Spatrick   // We use a shared pointer here so we can use the original parser - if it
622061da546Spatrick   // succeeds or the rewrite parser we might make if it fails.  But the
623061da546Spatrick   // parser_sp will never be empty.
624061da546Spatrick 
625061da546Spatrick   ClangExpressionParser parser(exe_scope, *this, generate_debug_info,
626061da546Spatrick                                m_include_directories, m_filename);
627061da546Spatrick 
628061da546Spatrick   unsigned num_errors = parser.Parse(diagnostic_manager);
629061da546Spatrick 
630061da546Spatrick   // Check here for FixItHints.  If there are any try to apply the fixits and
631061da546Spatrick   // set the fixed text in m_fixed_text before returning an error.
632061da546Spatrick   if (num_errors) {
633061da546Spatrick     if (diagnostic_manager.HasFixIts()) {
634061da546Spatrick       if (parser.RewriteExpression(diagnostic_manager)) {
635061da546Spatrick         size_t fixed_start;
636061da546Spatrick         size_t fixed_end;
637*dda28197Spatrick         m_fixed_text = diagnostic_manager.GetFixedExpression();
638061da546Spatrick         // Retrieve the original expression in case we don't have a top level
639061da546Spatrick         // expression (which has no surrounding source code).
640*dda28197Spatrick         if (m_source_code && m_source_code->GetOriginalBodyBounds(
641*dda28197Spatrick                                  m_fixed_text, fixed_start, fixed_end))
642061da546Spatrick           m_fixed_text =
643*dda28197Spatrick               m_fixed_text.substr(fixed_start, fixed_end - fixed_start);
644061da546Spatrick       }
645061da546Spatrick     }
646061da546Spatrick     return false;
647061da546Spatrick   }
648061da546Spatrick 
649061da546Spatrick   //////////////////////////////////////////////////////////////////////////////
650061da546Spatrick   // Prepare the output of the parser for execution, evaluating it statically
651061da546Spatrick   // if possible
652061da546Spatrick   //
653061da546Spatrick 
654061da546Spatrick   {
655061da546Spatrick     Status jit_error = parser.PrepareForExecution(
656061da546Spatrick         m_jit_start_addr, m_jit_end_addr, m_execution_unit_sp, exe_ctx,
657061da546Spatrick         m_can_interpret, execution_policy);
658061da546Spatrick 
659061da546Spatrick     if (!jit_error.Success()) {
660061da546Spatrick       const char *error_cstr = jit_error.AsCString();
661061da546Spatrick       if (error_cstr && error_cstr[0])
662061da546Spatrick         diagnostic_manager.PutString(eDiagnosticSeverityError, error_cstr);
663061da546Spatrick       else
664061da546Spatrick         diagnostic_manager.PutString(eDiagnosticSeverityError,
665061da546Spatrick                                      "expression can't be interpreted or run");
666061da546Spatrick       return false;
667061da546Spatrick     }
668061da546Spatrick   }
669061da546Spatrick 
670061da546Spatrick   if (exe_ctx.GetProcessPtr() && execution_policy == eExecutionPolicyTopLevel) {
671061da546Spatrick     Status static_init_error =
672061da546Spatrick         parser.RunStaticInitializers(m_execution_unit_sp, exe_ctx);
673061da546Spatrick 
674061da546Spatrick     if (!static_init_error.Success()) {
675061da546Spatrick       const char *error_cstr = static_init_error.AsCString();
676061da546Spatrick       if (error_cstr && error_cstr[0])
677061da546Spatrick         diagnostic_manager.Printf(eDiagnosticSeverityError,
678*dda28197Spatrick                                   "%s\n",
679061da546Spatrick                                   error_cstr);
680061da546Spatrick       else
681061da546Spatrick         diagnostic_manager.PutString(eDiagnosticSeverityError,
682061da546Spatrick                                      "couldn't run static initializers\n");
683061da546Spatrick       return false;
684061da546Spatrick     }
685061da546Spatrick   }
686061da546Spatrick 
687061da546Spatrick   if (m_execution_unit_sp) {
688061da546Spatrick     bool register_execution_unit = false;
689061da546Spatrick 
690061da546Spatrick     if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel) {
691061da546Spatrick       register_execution_unit = true;
692061da546Spatrick     }
693061da546Spatrick 
694061da546Spatrick     // If there is more than one external function in the execution unit, it
695061da546Spatrick     // needs to keep living even if it's not top level, because the result
696061da546Spatrick     // could refer to that function.
697061da546Spatrick 
698061da546Spatrick     if (m_execution_unit_sp->GetJittedFunctions().size() > 1) {
699061da546Spatrick       register_execution_unit = true;
700061da546Spatrick     }
701061da546Spatrick 
702061da546Spatrick     if (register_execution_unit) {
703061da546Spatrick       if (auto *persistent_state =
704061da546Spatrick               exe_ctx.GetTargetPtr()->GetPersistentExpressionStateForLanguage(
705061da546Spatrick                   m_language))
706061da546Spatrick         persistent_state->RegisterExecutionUnit(m_execution_unit_sp);
707061da546Spatrick     }
708061da546Spatrick   }
709061da546Spatrick 
710061da546Spatrick   if (generate_debug_info) {
711061da546Spatrick     lldb::ModuleSP jit_module_sp(m_execution_unit_sp->GetJITModule());
712061da546Spatrick 
713061da546Spatrick     if (jit_module_sp) {
714061da546Spatrick       ConstString const_func_name(FunctionName());
715061da546Spatrick       FileSpec jit_file;
716061da546Spatrick       jit_file.GetFilename() = const_func_name;
717061da546Spatrick       jit_module_sp->SetFileSpecAndObjectName(jit_file, ConstString());
718061da546Spatrick       m_jit_module_wp = jit_module_sp;
719061da546Spatrick       target->GetImages().Append(jit_module_sp);
720061da546Spatrick     }
721061da546Spatrick   }
722061da546Spatrick 
723061da546Spatrick   if (process && m_jit_start_addr != LLDB_INVALID_ADDRESS)
724061da546Spatrick     m_jit_process_wp = lldb::ProcessWP(process->shared_from_this());
725061da546Spatrick   return true;
726061da546Spatrick }
727061da546Spatrick 
728061da546Spatrick /// Converts an absolute position inside a given code string into
729061da546Spatrick /// a column/line pair.
730061da546Spatrick ///
731061da546Spatrick /// \param[in] abs_pos
732061da546Spatrick ///     A absolute position in the code string that we want to convert
733061da546Spatrick ///     to a column/line pair.
734061da546Spatrick ///
735061da546Spatrick /// \param[in] code
736061da546Spatrick ///     A multi-line string usually representing source code.
737061da546Spatrick ///
738061da546Spatrick /// \param[out] line
739061da546Spatrick ///     The line in the code that contains the given absolute position.
740061da546Spatrick ///     The first line in the string is indexed as 1.
741061da546Spatrick ///
742061da546Spatrick /// \param[out] column
743061da546Spatrick ///     The column in the line that contains the absolute position.
744061da546Spatrick ///     The first character in a line is indexed as 0.
745061da546Spatrick static void AbsPosToLineColumnPos(size_t abs_pos, llvm::StringRef code,
746061da546Spatrick                                   unsigned &line, unsigned &column) {
747061da546Spatrick   // Reset to code position to beginning of the file.
748061da546Spatrick   line = 0;
749061da546Spatrick   column = 0;
750061da546Spatrick 
751061da546Spatrick   assert(abs_pos <= code.size() && "Absolute position outside code string?");
752061da546Spatrick 
753061da546Spatrick   // We have to walk up to the position and count lines/columns.
754061da546Spatrick   for (std::size_t i = 0; i < abs_pos; ++i) {
755061da546Spatrick     // If we hit a line break, we go back to column 0 and enter a new line.
756061da546Spatrick     // We only handle \n because that's what we internally use to make new
757061da546Spatrick     // lines for our temporary code strings.
758061da546Spatrick     if (code[i] == '\n') {
759061da546Spatrick       ++line;
760061da546Spatrick       column = 0;
761061da546Spatrick       continue;
762061da546Spatrick     }
763061da546Spatrick     ++column;
764061da546Spatrick   }
765061da546Spatrick }
766061da546Spatrick 
767061da546Spatrick bool ClangUserExpression::Complete(ExecutionContext &exe_ctx,
768061da546Spatrick                                    CompletionRequest &request,
769061da546Spatrick                                    unsigned complete_pos) {
770061da546Spatrick   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
771061da546Spatrick 
772061da546Spatrick   // We don't want any visible feedback when completing an expression. Mostly
773061da546Spatrick   // because the results we get from an incomplete invocation are probably not
774061da546Spatrick   // correct.
775061da546Spatrick   DiagnosticManager diagnostic_manager;
776061da546Spatrick 
777061da546Spatrick   if (!PrepareForParsing(diagnostic_manager, exe_ctx, /*for_completion*/ true))
778061da546Spatrick     return false;
779061da546Spatrick 
780061da546Spatrick   LLDB_LOGF(log, "Parsing the following code:\n%s", m_transformed_text.c_str());
781061da546Spatrick 
782061da546Spatrick   //////////////////////////
783061da546Spatrick   // Parse the expression
784061da546Spatrick   //
785061da546Spatrick 
786*dda28197Spatrick   m_materializer_up = std::make_unique<Materializer>();
787061da546Spatrick 
788061da546Spatrick   ResetDeclMap(exe_ctx, m_result_delegate, /*keep result in memory*/ true);
789061da546Spatrick 
790061da546Spatrick   auto on_exit = llvm::make_scope_exit([this]() { ResetDeclMap(); });
791061da546Spatrick 
792061da546Spatrick   if (!DeclMap()->WillParse(exe_ctx, GetMaterializer())) {
793061da546Spatrick     diagnostic_manager.PutString(
794061da546Spatrick         eDiagnosticSeverityError,
795061da546Spatrick         "current process state is unsuitable for expression parsing");
796061da546Spatrick 
797061da546Spatrick     return false;
798061da546Spatrick   }
799061da546Spatrick 
800061da546Spatrick   if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel) {
801061da546Spatrick     DeclMap()->SetLookupsEnabled(true);
802061da546Spatrick   }
803061da546Spatrick 
804061da546Spatrick   Process *process = exe_ctx.GetProcessPtr();
805061da546Spatrick   ExecutionContextScope *exe_scope = process;
806061da546Spatrick 
807061da546Spatrick   if (!exe_scope)
808061da546Spatrick     exe_scope = exe_ctx.GetTargetPtr();
809061da546Spatrick 
810061da546Spatrick   ClangExpressionParser parser(exe_scope, *this, false);
811061da546Spatrick 
812061da546Spatrick   // We have to find the source code location where the user text is inside
813061da546Spatrick   // the transformed expression code. When creating the transformed text, we
814061da546Spatrick   // already stored the absolute position in the m_transformed_text string. The
815061da546Spatrick   // only thing left to do is to transform it into the line:column format that
816061da546Spatrick   // Clang expects.
817061da546Spatrick 
818061da546Spatrick   // The line and column of the user expression inside the transformed source
819061da546Spatrick   // code.
820061da546Spatrick   unsigned user_expr_line, user_expr_column;
821061da546Spatrick   if (m_user_expression_start_pos.hasValue())
822061da546Spatrick     AbsPosToLineColumnPos(*m_user_expression_start_pos, m_transformed_text,
823061da546Spatrick                           user_expr_line, user_expr_column);
824061da546Spatrick   else
825061da546Spatrick     return false;
826061da546Spatrick 
827061da546Spatrick   // The actual column where we have to complete is the start column of the
828061da546Spatrick   // user expression + the offset inside the user code that we were given.
829061da546Spatrick   const unsigned completion_column = user_expr_column + complete_pos;
830061da546Spatrick   parser.Complete(request, user_expr_line, completion_column, complete_pos);
831061da546Spatrick 
832061da546Spatrick   return true;
833061da546Spatrick }
834061da546Spatrick 
835061da546Spatrick bool ClangUserExpression::AddArguments(ExecutionContext &exe_ctx,
836061da546Spatrick                                        std::vector<lldb::addr_t> &args,
837061da546Spatrick                                        lldb::addr_t struct_address,
838061da546Spatrick                                        DiagnosticManager &diagnostic_manager) {
839061da546Spatrick   lldb::addr_t object_ptr = LLDB_INVALID_ADDRESS;
840061da546Spatrick   lldb::addr_t cmd_ptr = LLDB_INVALID_ADDRESS;
841061da546Spatrick 
842061da546Spatrick   if (m_needs_object_ptr) {
843061da546Spatrick     lldb::StackFrameSP frame_sp = exe_ctx.GetFrameSP();
844061da546Spatrick     if (!frame_sp)
845061da546Spatrick       return true;
846061da546Spatrick 
847061da546Spatrick     ConstString object_name;
848061da546Spatrick 
849061da546Spatrick     if (m_in_cplusplus_method) {
850061da546Spatrick       object_name.SetCString("this");
851061da546Spatrick     } else if (m_in_objectivec_method) {
852061da546Spatrick       object_name.SetCString("self");
853061da546Spatrick     } else {
854061da546Spatrick       diagnostic_manager.PutString(
855061da546Spatrick           eDiagnosticSeverityError,
856061da546Spatrick           "need object pointer but don't know the language");
857061da546Spatrick       return false;
858061da546Spatrick     }
859061da546Spatrick 
860061da546Spatrick     Status object_ptr_error;
861061da546Spatrick 
862061da546Spatrick     if (m_ctx_obj) {
863061da546Spatrick       AddressType address_type;
864061da546Spatrick       object_ptr = m_ctx_obj->GetAddressOf(false, &address_type);
865061da546Spatrick       if (object_ptr == LLDB_INVALID_ADDRESS ||
866061da546Spatrick           address_type != eAddressTypeLoad)
867061da546Spatrick         object_ptr_error.SetErrorString("Can't get context object's "
868061da546Spatrick                                         "debuggee address");
869061da546Spatrick     } else
870061da546Spatrick       object_ptr = GetObjectPointer(frame_sp, object_name, object_ptr_error);
871061da546Spatrick 
872061da546Spatrick     if (!object_ptr_error.Success()) {
873061da546Spatrick       exe_ctx.GetTargetRef().GetDebugger().GetAsyncOutputStream()->Printf(
874061da546Spatrick           "warning: `%s' is not accessible (substituting 0)\n",
875061da546Spatrick           object_name.AsCString());
876061da546Spatrick       object_ptr = 0;
877061da546Spatrick     }
878061da546Spatrick 
879061da546Spatrick     if (m_in_objectivec_method) {
880061da546Spatrick       ConstString cmd_name("_cmd");
881061da546Spatrick 
882061da546Spatrick       cmd_ptr = GetObjectPointer(frame_sp, cmd_name, object_ptr_error);
883061da546Spatrick 
884061da546Spatrick       if (!object_ptr_error.Success()) {
885061da546Spatrick         diagnostic_manager.Printf(
886061da546Spatrick             eDiagnosticSeverityWarning,
887061da546Spatrick             "couldn't get cmd pointer (substituting NULL): %s",
888061da546Spatrick             object_ptr_error.AsCString());
889061da546Spatrick         cmd_ptr = 0;
890061da546Spatrick       }
891061da546Spatrick     }
892061da546Spatrick 
893061da546Spatrick     args.push_back(object_ptr);
894061da546Spatrick 
895061da546Spatrick     if (m_in_objectivec_method)
896061da546Spatrick       args.push_back(cmd_ptr);
897061da546Spatrick 
898061da546Spatrick     args.push_back(struct_address);
899061da546Spatrick   } else {
900061da546Spatrick     args.push_back(struct_address);
901061da546Spatrick   }
902061da546Spatrick   return true;
903061da546Spatrick }
904061da546Spatrick 
905061da546Spatrick lldb::ExpressionVariableSP ClangUserExpression::GetResultAfterDematerialization(
906061da546Spatrick     ExecutionContextScope *exe_scope) {
907061da546Spatrick   return m_result_delegate.GetVariable();
908061da546Spatrick }
909061da546Spatrick 
910061da546Spatrick void ClangUserExpression::ClangUserExpressionHelper::ResetDeclMap(
911061da546Spatrick     ExecutionContext &exe_ctx,
912061da546Spatrick     Materializer::PersistentVariableDelegate &delegate,
913061da546Spatrick     bool keep_result_in_memory,
914061da546Spatrick     ValueObject *ctx_obj) {
915*dda28197Spatrick   std::shared_ptr<ClangASTImporter> ast_importer;
916*dda28197Spatrick   auto *state = exe_ctx.GetTargetSP()->GetPersistentExpressionStateForLanguage(
917*dda28197Spatrick       lldb::eLanguageTypeC);
918*dda28197Spatrick   if (state) {
919*dda28197Spatrick     auto *persistent_vars = llvm::cast<ClangPersistentVariables>(state);
920*dda28197Spatrick     ast_importer = persistent_vars->GetClangASTImporter();
921*dda28197Spatrick   }
922*dda28197Spatrick   m_expr_decl_map_up = std::make_unique<ClangExpressionDeclMap>(
923*dda28197Spatrick       keep_result_in_memory, &delegate, exe_ctx.GetTargetSP(), ast_importer,
924*dda28197Spatrick       ctx_obj);
925061da546Spatrick }
926061da546Spatrick 
927061da546Spatrick clang::ASTConsumer *
928061da546Spatrick ClangUserExpression::ClangUserExpressionHelper::ASTTransformer(
929061da546Spatrick     clang::ASTConsumer *passthrough) {
930*dda28197Spatrick   m_result_synthesizer_up = std::make_unique<ASTResultSynthesizer>(
931*dda28197Spatrick       passthrough, m_top_level, m_target);
932061da546Spatrick 
933061da546Spatrick   return m_result_synthesizer_up.get();
934061da546Spatrick }
935061da546Spatrick 
936061da546Spatrick void ClangUserExpression::ClangUserExpressionHelper::CommitPersistentDecls() {
937061da546Spatrick   if (m_result_synthesizer_up) {
938061da546Spatrick     m_result_synthesizer_up->CommitPersistentDecls();
939061da546Spatrick   }
940061da546Spatrick }
941061da546Spatrick 
942061da546Spatrick ConstString ClangUserExpression::ResultDelegate::GetName() {
943*dda28197Spatrick   return m_persistent_state->GetNextPersistentVariableName(false);
944061da546Spatrick }
945061da546Spatrick 
946061da546Spatrick void ClangUserExpression::ResultDelegate::DidDematerialize(
947061da546Spatrick     lldb::ExpressionVariableSP &variable) {
948061da546Spatrick   m_variable = variable;
949061da546Spatrick }
950061da546Spatrick 
951061da546Spatrick void ClangUserExpression::ResultDelegate::RegisterPersistentState(
952061da546Spatrick     PersistentExpressionState *persistent_state) {
953061da546Spatrick   m_persistent_state = persistent_state;
954061da546Spatrick }
955061da546Spatrick 
956061da546Spatrick lldb::ExpressionVariableSP &ClangUserExpression::ResultDelegate::GetVariable() {
957061da546Spatrick   return m_variable;
958061da546Spatrick }
959