xref: /openbsd-src/gnu/llvm/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
1dda28197Spatrick //===-- 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 
9be691f3bSpatrick #include <cstdio>
10061da546Spatrick #include <sys/types.h>
11061da546Spatrick 
12061da546Spatrick #include <cstdlib>
13061da546Spatrick #include <map>
14061da546Spatrick #include <string>
15061da546Spatrick 
16061da546Spatrick #include "ClangUserExpression.h"
17061da546Spatrick 
18061da546Spatrick #include "ASTResultSynthesizer.h"
19dda28197Spatrick #include "ClangASTMetadata.h"
20061da546Spatrick #include "ClangDiagnostic.h"
21061da546Spatrick #include "ClangExpressionDeclMap.h"
22061da546Spatrick #include "ClangExpressionParser.h"
23061da546Spatrick #include "ClangModulesDeclVendor.h"
24061da546Spatrick #include "ClangPersistentVariables.h"
25061da546Spatrick #include "CppModuleConfiguration.h"
26061da546Spatrick 
27dda28197Spatrick #include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
28061da546Spatrick #include "lldb/Core/Debugger.h"
29061da546Spatrick #include "lldb/Core/Module.h"
30061da546Spatrick #include "lldb/Core/StreamFile.h"
31061da546Spatrick #include "lldb/Core/ValueObjectConstResult.h"
32061da546Spatrick #include "lldb/Expression/ExpressionSourceCode.h"
33061da546Spatrick #include "lldb/Expression/IRExecutionUnit.h"
34061da546Spatrick #include "lldb/Expression/IRInterpreter.h"
35061da546Spatrick #include "lldb/Expression/Materializer.h"
36061da546Spatrick #include "lldb/Host/HostInfo.h"
37061da546Spatrick #include "lldb/Symbol/Block.h"
38061da546Spatrick #include "lldb/Symbol/CompileUnit.h"
39061da546Spatrick #include "lldb/Symbol/Function.h"
40061da546Spatrick #include "lldb/Symbol/ObjectFile.h"
41061da546Spatrick #include "lldb/Symbol/SymbolFile.h"
42061da546Spatrick #include "lldb/Symbol/SymbolVendor.h"
43061da546Spatrick #include "lldb/Symbol/Type.h"
44061da546Spatrick #include "lldb/Symbol/VariableList.h"
45061da546Spatrick #include "lldb/Target/ExecutionContext.h"
46061da546Spatrick #include "lldb/Target/Process.h"
47061da546Spatrick #include "lldb/Target/StackFrame.h"
48061da546Spatrick #include "lldb/Target/Target.h"
49061da546Spatrick #include "lldb/Target/ThreadPlan.h"
50061da546Spatrick #include "lldb/Target/ThreadPlanCallUserExpression.h"
51061da546Spatrick #include "lldb/Utility/ConstString.h"
52*f6aab3d8Srobert #include "lldb/Utility/LLDBLog.h"
53061da546Spatrick #include "lldb/Utility/Log.h"
54061da546Spatrick #include "lldb/Utility/StreamString.h"
55061da546Spatrick 
56061da546Spatrick #include "clang/AST/DeclCXX.h"
57061da546Spatrick #include "clang/AST/DeclObjC.h"
58061da546Spatrick 
59061da546Spatrick #include "llvm/ADT/ScopeExit.h"
60061da546Spatrick 
61061da546Spatrick using namespace lldb_private;
62061da546Spatrick 
63061da546Spatrick char ClangUserExpression::ID;
64061da546Spatrick 
ClangUserExpression(ExecutionContextScope & exe_scope,llvm::StringRef expr,llvm::StringRef prefix,lldb::LanguageType language,ResultType desired_type,const EvaluateExpressionOptions & options,ValueObject * ctx_obj)65061da546Spatrick ClangUserExpression::ClangUserExpression(
66061da546Spatrick     ExecutionContextScope &exe_scope, llvm::StringRef expr,
67061da546Spatrick     llvm::StringRef prefix, lldb::LanguageType language,
68061da546Spatrick     ResultType desired_type, const EvaluateExpressionOptions &options,
69061da546Spatrick     ValueObject *ctx_obj)
70061da546Spatrick     : LLVMUserExpression(exe_scope, expr, prefix, language, desired_type,
71061da546Spatrick                          options),
72061da546Spatrick       m_type_system_helper(*m_target_wp.lock(), options.GetExecutionPolicy() ==
73061da546Spatrick                                                     eExecutionPolicyTopLevel),
74061da546Spatrick       m_result_delegate(exe_scope.CalculateTarget()), m_ctx_obj(ctx_obj) {
75061da546Spatrick   switch (m_language) {
76061da546Spatrick   case lldb::eLanguageTypeC_plus_plus:
77061da546Spatrick     m_allow_cxx = true;
78061da546Spatrick     break;
79061da546Spatrick   case lldb::eLanguageTypeObjC:
80061da546Spatrick     m_allow_objc = true;
81061da546Spatrick     break;
82061da546Spatrick   case lldb::eLanguageTypeObjC_plus_plus:
83061da546Spatrick   default:
84061da546Spatrick     m_allow_cxx = true;
85061da546Spatrick     m_allow_objc = true;
86061da546Spatrick     break;
87061da546Spatrick   }
88061da546Spatrick }
89061da546Spatrick 
90be691f3bSpatrick ClangUserExpression::~ClangUserExpression() = default;
91061da546Spatrick 
ScanContext(ExecutionContext & exe_ctx,Status & err)92061da546Spatrick void ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Status &err) {
93*f6aab3d8Srobert   Log *log = GetLog(LLDBLog::Expressions);
94061da546Spatrick 
95061da546Spatrick   LLDB_LOGF(log, "ClangUserExpression::ScanContext()");
96061da546Spatrick 
97061da546Spatrick   m_target = exe_ctx.GetTargetPtr();
98061da546Spatrick 
99061da546Spatrick   if (!(m_allow_cxx || m_allow_objc)) {
100061da546Spatrick     LLDB_LOGF(log, "  [CUE::SC] Settings inhibit C++ and Objective-C");
101061da546Spatrick     return;
102061da546Spatrick   }
103061da546Spatrick 
104061da546Spatrick   StackFrame *frame = exe_ctx.GetFramePtr();
105061da546Spatrick   if (frame == nullptr) {
106061da546Spatrick     LLDB_LOGF(log, "  [CUE::SC] Null stack frame");
107061da546Spatrick     return;
108061da546Spatrick   }
109061da546Spatrick 
110061da546Spatrick   SymbolContext sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction |
111061da546Spatrick                                                   lldb::eSymbolContextBlock);
112061da546Spatrick 
113061da546Spatrick   if (!sym_ctx.function) {
114061da546Spatrick     LLDB_LOGF(log, "  [CUE::SC] Null function");
115061da546Spatrick     return;
116061da546Spatrick   }
117061da546Spatrick 
118061da546Spatrick   // Find the block that defines the function represented by "sym_ctx"
119061da546Spatrick   Block *function_block = sym_ctx.GetFunctionBlock();
120061da546Spatrick 
121061da546Spatrick   if (!function_block) {
122061da546Spatrick     LLDB_LOGF(log, "  [CUE::SC] Null function block");
123061da546Spatrick     return;
124061da546Spatrick   }
125061da546Spatrick 
126061da546Spatrick   CompilerDeclContext decl_context = function_block->GetDeclContext();
127061da546Spatrick 
128061da546Spatrick   if (!decl_context) {
129061da546Spatrick     LLDB_LOGF(log, "  [CUE::SC] Null decl context");
130061da546Spatrick     return;
131061da546Spatrick   }
132061da546Spatrick 
133061da546Spatrick   if (m_ctx_obj) {
134061da546Spatrick     switch (m_ctx_obj->GetObjectRuntimeLanguage()) {
135061da546Spatrick     case lldb::eLanguageTypeC:
136061da546Spatrick     case lldb::eLanguageTypeC89:
137061da546Spatrick     case lldb::eLanguageTypeC99:
138061da546Spatrick     case lldb::eLanguageTypeC11:
139061da546Spatrick     case lldb::eLanguageTypeC_plus_plus:
140061da546Spatrick     case lldb::eLanguageTypeC_plus_plus_03:
141061da546Spatrick     case lldb::eLanguageTypeC_plus_plus_11:
142061da546Spatrick     case lldb::eLanguageTypeC_plus_plus_14:
143061da546Spatrick       m_in_cplusplus_method = true;
144061da546Spatrick       break;
145061da546Spatrick     case lldb::eLanguageTypeObjC:
146061da546Spatrick     case lldb::eLanguageTypeObjC_plus_plus:
147061da546Spatrick       m_in_objectivec_method = true;
148061da546Spatrick       break;
149061da546Spatrick     default:
150061da546Spatrick       break;
151061da546Spatrick     }
152061da546Spatrick     m_needs_object_ptr = true;
153061da546Spatrick   } else if (clang::CXXMethodDecl *method_decl =
154dda28197Spatrick           TypeSystemClang::DeclContextGetAsCXXMethodDecl(decl_context)) {
155061da546Spatrick     if (m_allow_cxx && method_decl->isInstance()) {
156061da546Spatrick       if (m_enforce_valid_object) {
157061da546Spatrick         lldb::VariableListSP variable_list_sp(
158061da546Spatrick             function_block->GetBlockVariableList(true));
159061da546Spatrick 
160061da546Spatrick         const char *thisErrorString = "Stopped in a C++ method, but 'this' "
161061da546Spatrick                                       "isn't available; pretending we are in a "
162061da546Spatrick                                       "generic context";
163061da546Spatrick 
164061da546Spatrick         if (!variable_list_sp) {
165061da546Spatrick           err.SetErrorString(thisErrorString);
166061da546Spatrick           return;
167061da546Spatrick         }
168061da546Spatrick 
169061da546Spatrick         lldb::VariableSP this_var_sp(
170061da546Spatrick             variable_list_sp->FindVariable(ConstString("this")));
171061da546Spatrick 
172061da546Spatrick         if (!this_var_sp || !this_var_sp->IsInScope(frame) ||
173061da546Spatrick             !this_var_sp->LocationIsValidForFrame(frame)) {
174061da546Spatrick           err.SetErrorString(thisErrorString);
175061da546Spatrick           return;
176061da546Spatrick         }
177061da546Spatrick       }
178061da546Spatrick 
179061da546Spatrick       m_in_cplusplus_method = true;
180061da546Spatrick       m_needs_object_ptr = true;
181061da546Spatrick     }
182061da546Spatrick   } else if (clang::ObjCMethodDecl *method_decl =
183dda28197Spatrick                  TypeSystemClang::DeclContextGetAsObjCMethodDecl(
184061da546Spatrick                      decl_context)) {
185061da546Spatrick     if (m_allow_objc) {
186061da546Spatrick       if (m_enforce_valid_object) {
187061da546Spatrick         lldb::VariableListSP variable_list_sp(
188061da546Spatrick             function_block->GetBlockVariableList(true));
189061da546Spatrick 
190061da546Spatrick         const char *selfErrorString = "Stopped in an Objective-C method, but "
191061da546Spatrick                                       "'self' isn't available; pretending we "
192061da546Spatrick                                       "are in a generic context";
193061da546Spatrick 
194061da546Spatrick         if (!variable_list_sp) {
195061da546Spatrick           err.SetErrorString(selfErrorString);
196061da546Spatrick           return;
197061da546Spatrick         }
198061da546Spatrick 
199061da546Spatrick         lldb::VariableSP self_variable_sp =
200061da546Spatrick             variable_list_sp->FindVariable(ConstString("self"));
201061da546Spatrick 
202061da546Spatrick         if (!self_variable_sp || !self_variable_sp->IsInScope(frame) ||
203061da546Spatrick             !self_variable_sp->LocationIsValidForFrame(frame)) {
204061da546Spatrick           err.SetErrorString(selfErrorString);
205061da546Spatrick           return;
206061da546Spatrick         }
207061da546Spatrick       }
208061da546Spatrick 
209061da546Spatrick       m_in_objectivec_method = true;
210061da546Spatrick       m_needs_object_ptr = true;
211061da546Spatrick 
212061da546Spatrick       if (!method_decl->isInstanceMethod())
213061da546Spatrick         m_in_static_method = true;
214061da546Spatrick     }
215061da546Spatrick   } else if (clang::FunctionDecl *function_decl =
216dda28197Spatrick                  TypeSystemClang::DeclContextGetAsFunctionDecl(decl_context)) {
217061da546Spatrick     // We might also have a function that said in the debug information that it
218061da546Spatrick     // captured an object pointer.  The best way to deal with getting to the
219061da546Spatrick     // ivars at present is by pretending that this is a method of a class in
220061da546Spatrick     // whatever runtime the debug info says the object pointer belongs to.  Do
221061da546Spatrick     // that here.
222061da546Spatrick 
223061da546Spatrick     ClangASTMetadata *metadata =
224dda28197Spatrick         TypeSystemClang::DeclContextGetMetaData(decl_context, function_decl);
225061da546Spatrick     if (metadata && metadata->HasObjectPtr()) {
226061da546Spatrick       lldb::LanguageType language = metadata->GetObjectPtrLanguage();
227061da546Spatrick       if (language == lldb::eLanguageTypeC_plus_plus) {
228061da546Spatrick         if (m_enforce_valid_object) {
229061da546Spatrick           lldb::VariableListSP variable_list_sp(
230061da546Spatrick               function_block->GetBlockVariableList(true));
231061da546Spatrick 
232061da546Spatrick           const char *thisErrorString = "Stopped in a context claiming to "
233061da546Spatrick                                         "capture a C++ object pointer, but "
234061da546Spatrick                                         "'this' isn't available; pretending we "
235061da546Spatrick                                         "are in a generic context";
236061da546Spatrick 
237061da546Spatrick           if (!variable_list_sp) {
238061da546Spatrick             err.SetErrorString(thisErrorString);
239061da546Spatrick             return;
240061da546Spatrick           }
241061da546Spatrick 
242061da546Spatrick           lldb::VariableSP this_var_sp(
243061da546Spatrick               variable_list_sp->FindVariable(ConstString("this")));
244061da546Spatrick 
245061da546Spatrick           if (!this_var_sp || !this_var_sp->IsInScope(frame) ||
246061da546Spatrick               !this_var_sp->LocationIsValidForFrame(frame)) {
247061da546Spatrick             err.SetErrorString(thisErrorString);
248061da546Spatrick             return;
249061da546Spatrick           }
250061da546Spatrick         }
251061da546Spatrick 
252061da546Spatrick         m_in_cplusplus_method = true;
253061da546Spatrick         m_needs_object_ptr = true;
254061da546Spatrick       } else if (language == lldb::eLanguageTypeObjC) {
255061da546Spatrick         if (m_enforce_valid_object) {
256061da546Spatrick           lldb::VariableListSP variable_list_sp(
257061da546Spatrick               function_block->GetBlockVariableList(true));
258061da546Spatrick 
259061da546Spatrick           const char *selfErrorString =
260061da546Spatrick               "Stopped in a context claiming to capture an Objective-C object "
261061da546Spatrick               "pointer, but 'self' isn't available; pretending we are in a "
262061da546Spatrick               "generic context";
263061da546Spatrick 
264061da546Spatrick           if (!variable_list_sp) {
265061da546Spatrick             err.SetErrorString(selfErrorString);
266061da546Spatrick             return;
267061da546Spatrick           }
268061da546Spatrick 
269061da546Spatrick           lldb::VariableSP self_variable_sp =
270061da546Spatrick               variable_list_sp->FindVariable(ConstString("self"));
271061da546Spatrick 
272061da546Spatrick           if (!self_variable_sp || !self_variable_sp->IsInScope(frame) ||
273061da546Spatrick               !self_variable_sp->LocationIsValidForFrame(frame)) {
274061da546Spatrick             err.SetErrorString(selfErrorString);
275061da546Spatrick             return;
276061da546Spatrick           }
277061da546Spatrick 
278061da546Spatrick           Type *self_type = self_variable_sp->GetType();
279061da546Spatrick 
280061da546Spatrick           if (!self_type) {
281061da546Spatrick             err.SetErrorString(selfErrorString);
282061da546Spatrick             return;
283061da546Spatrick           }
284061da546Spatrick 
285061da546Spatrick           CompilerType self_clang_type = self_type->GetForwardCompilerType();
286061da546Spatrick 
287061da546Spatrick           if (!self_clang_type) {
288061da546Spatrick             err.SetErrorString(selfErrorString);
289061da546Spatrick             return;
290061da546Spatrick           }
291061da546Spatrick 
292dda28197Spatrick           if (TypeSystemClang::IsObjCClassType(self_clang_type)) {
293061da546Spatrick             return;
294dda28197Spatrick           } else if (TypeSystemClang::IsObjCObjectPointerType(
295061da546Spatrick                          self_clang_type)) {
296061da546Spatrick             m_in_objectivec_method = true;
297061da546Spatrick             m_needs_object_ptr = true;
298061da546Spatrick           } else {
299061da546Spatrick             err.SetErrorString(selfErrorString);
300061da546Spatrick             return;
301061da546Spatrick           }
302061da546Spatrick         } else {
303061da546Spatrick           m_in_objectivec_method = true;
304061da546Spatrick           m_needs_object_ptr = true;
305061da546Spatrick         }
306061da546Spatrick       }
307061da546Spatrick     }
308061da546Spatrick   }
309061da546Spatrick }
310061da546Spatrick 
311061da546Spatrick // This is a really nasty hack, meant to fix Objective-C expressions of the
312061da546Spatrick // form (int)[myArray count].  Right now, because the type information for
313061da546Spatrick // count is not available, [myArray count] returns id, which can't be directly
314061da546Spatrick // cast to int without causing a clang error.
ApplyObjcCastHack(std::string & expr)315061da546Spatrick static void ApplyObjcCastHack(std::string &expr) {
316061da546Spatrick   const std::string from = "(int)[";
317061da546Spatrick   const std::string to = "(int)(long long)[";
318061da546Spatrick 
319061da546Spatrick   size_t offset;
320061da546Spatrick 
321061da546Spatrick   while ((offset = expr.find(from)) != expr.npos)
322061da546Spatrick     expr.replace(offset, from.size(), to);
323061da546Spatrick }
324061da546Spatrick 
SetupPersistentState(DiagnosticManager & diagnostic_manager,ExecutionContext & exe_ctx)325061da546Spatrick bool ClangUserExpression::SetupPersistentState(DiagnosticManager &diagnostic_manager,
326061da546Spatrick                                  ExecutionContext &exe_ctx) {
327061da546Spatrick   if (Target *target = exe_ctx.GetTargetPtr()) {
328061da546Spatrick     if (PersistentExpressionState *persistent_state =
329061da546Spatrick             target->GetPersistentExpressionStateForLanguage(
330061da546Spatrick                 lldb::eLanguageTypeC)) {
331061da546Spatrick       m_clang_state = llvm::cast<ClangPersistentVariables>(persistent_state);
332061da546Spatrick       m_result_delegate.RegisterPersistentState(persistent_state);
333061da546Spatrick     } else {
334061da546Spatrick       diagnostic_manager.PutString(
335061da546Spatrick           eDiagnosticSeverityError,
336061da546Spatrick           "couldn't start parsing (no persistent data)");
337061da546Spatrick       return false;
338061da546Spatrick     }
339061da546Spatrick   } else {
340061da546Spatrick     diagnostic_manager.PutString(eDiagnosticSeverityError,
341061da546Spatrick                                  "error: couldn't start parsing (no target)");
342061da546Spatrick     return false;
343061da546Spatrick   }
344061da546Spatrick   return true;
345061da546Spatrick }
346061da546Spatrick 
SetupDeclVendor(ExecutionContext & exe_ctx,Target * target,DiagnosticManager & diagnostic_manager)347dda28197Spatrick static void SetupDeclVendor(ExecutionContext &exe_ctx, Target *target,
348dda28197Spatrick                             DiagnosticManager &diagnostic_manager) {
349dda28197Spatrick   if (!target->GetEnableAutoImportClangModules())
350dda28197Spatrick     return;
351dda28197Spatrick 
352061da546Spatrick   auto *persistent_state = llvm::cast<ClangPersistentVariables>(
353061da546Spatrick       target->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC));
354061da546Spatrick   if (!persistent_state)
355061da546Spatrick     return;
356061da546Spatrick 
357be691f3bSpatrick   std::shared_ptr<ClangModulesDeclVendor> decl_vendor =
358be691f3bSpatrick       persistent_state->GetClangModulesDeclVendor();
359be691f3bSpatrick   if (!decl_vendor)
360be691f3bSpatrick     return;
361be691f3bSpatrick 
362dda28197Spatrick   StackFrame *frame = exe_ctx.GetFramePtr();
363dda28197Spatrick   if (!frame)
364dda28197Spatrick     return;
365061da546Spatrick 
366dda28197Spatrick   Block *block = frame->GetFrameBlock();
367dda28197Spatrick   if (!block)
368dda28197Spatrick     return;
369061da546Spatrick   SymbolContext sc;
370061da546Spatrick 
371061da546Spatrick   block->CalculateSymbolContext(&sc);
372061da546Spatrick 
373dda28197Spatrick   if (!sc.comp_unit)
374dda28197Spatrick     return;
375061da546Spatrick   StreamString error_stream;
376061da546Spatrick 
377dda28197Spatrick   ClangModulesDeclVendor::ModuleVector modules_for_macros =
378dda28197Spatrick       persistent_state->GetHandLoadedClangModules();
379dda28197Spatrick   if (decl_vendor->AddModulesForCompileUnit(*sc.comp_unit, modules_for_macros,
380dda28197Spatrick                                             error_stream))
381dda28197Spatrick     return;
382dda28197Spatrick 
383dda28197Spatrick   // Failed to load some modules, so emit the error stream as a diagnostic.
384dda28197Spatrick   if (!error_stream.Empty()) {
385dda28197Spatrick     // The error stream already contains several Clang diagnostics that might
386dda28197Spatrick     // be either errors or warnings, so just print them all as one remark
387dda28197Spatrick     // diagnostic to prevent that the message starts with "error: error:".
388dda28197Spatrick     diagnostic_manager.PutString(eDiagnosticSeverityRemark,
389dda28197Spatrick                                  error_stream.GetString());
390dda28197Spatrick     return;
391061da546Spatrick   }
392061da546Spatrick 
393dda28197Spatrick   diagnostic_manager.PutString(eDiagnosticSeverityError,
394dda28197Spatrick                                "Unknown error while loading modules needed for "
395dda28197Spatrick                                "current compilation unit.");
396dda28197Spatrick }
397dda28197Spatrick 
GetWrapKind() const398dda28197Spatrick ClangExpressionSourceCode::WrapKind ClangUserExpression::GetWrapKind() const {
399dda28197Spatrick   assert(m_options.GetExecutionPolicy() != eExecutionPolicyTopLevel &&
400dda28197Spatrick          "Top level expressions aren't wrapped.");
401dda28197Spatrick   using Kind = ClangExpressionSourceCode::WrapKind;
402061da546Spatrick   if (m_in_cplusplus_method)
403dda28197Spatrick     return Kind::CppMemberFunction;
404dda28197Spatrick   else if (m_in_objectivec_method) {
405dda28197Spatrick     if (m_in_static_method)
406dda28197Spatrick       return Kind::ObjCStaticMethod;
407dda28197Spatrick     return Kind::ObjCInstanceMethod;
408dda28197Spatrick   }
409dda28197Spatrick   // Not in any kind of 'special' function, so just wrap it in a normal C
410dda28197Spatrick   // function.
411dda28197Spatrick   return Kind::Function;
412061da546Spatrick }
413061da546Spatrick 
CreateSourceCode(DiagnosticManager & diagnostic_manager,ExecutionContext & exe_ctx,std::vector<std::string> modules_to_import,bool for_completion)414061da546Spatrick void ClangUserExpression::CreateSourceCode(
415061da546Spatrick     DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx,
416061da546Spatrick     std::vector<std::string> modules_to_import, bool for_completion) {
417061da546Spatrick 
418061da546Spatrick   std::string prefix = m_expr_prefix;
419061da546Spatrick 
420061da546Spatrick   if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel) {
421061da546Spatrick     m_transformed_text = m_expr_text;
422061da546Spatrick   } else {
423061da546Spatrick     m_source_code.reset(ClangExpressionSourceCode::CreateWrapped(
424dda28197Spatrick         m_filename, prefix, m_expr_text, GetWrapKind()));
425061da546Spatrick 
426dda28197Spatrick     if (!m_source_code->GetText(m_transformed_text, exe_ctx, !m_ctx_obj,
427061da546Spatrick                                 for_completion, modules_to_import)) {
428061da546Spatrick       diagnostic_manager.PutString(eDiagnosticSeverityError,
429061da546Spatrick                                    "couldn't construct expression body");
430061da546Spatrick       return;
431061da546Spatrick     }
432061da546Spatrick 
433061da546Spatrick     // Find and store the start position of the original code inside the
434061da546Spatrick     // transformed code. We need this later for the code completion.
435061da546Spatrick     std::size_t original_start;
436061da546Spatrick     std::size_t original_end;
437061da546Spatrick     bool found_bounds = m_source_code->GetOriginalBodyBounds(
438dda28197Spatrick         m_transformed_text, original_start, original_end);
439061da546Spatrick     if (found_bounds)
440061da546Spatrick       m_user_expression_start_pos = original_start;
441061da546Spatrick   }
442061da546Spatrick }
443061da546Spatrick 
SupportsCxxModuleImport(lldb::LanguageType language)444061da546Spatrick static bool SupportsCxxModuleImport(lldb::LanguageType language) {
445061da546Spatrick   switch (language) {
446061da546Spatrick   case lldb::eLanguageTypeC_plus_plus:
447061da546Spatrick   case lldb::eLanguageTypeC_plus_plus_03:
448061da546Spatrick   case lldb::eLanguageTypeC_plus_plus_11:
449061da546Spatrick   case lldb::eLanguageTypeC_plus_plus_14:
450061da546Spatrick   case lldb::eLanguageTypeObjC_plus_plus:
451061da546Spatrick     return true;
452061da546Spatrick   default:
453061da546Spatrick     return false;
454061da546Spatrick   }
455061da546Spatrick }
456061da546Spatrick 
457061da546Spatrick /// Utility method that puts a message into the expression log and
458061da546Spatrick /// returns an invalid module configuration.
LogConfigError(const std::string & msg)459061da546Spatrick static CppModuleConfiguration LogConfigError(const std::string &msg) {
460*f6aab3d8Srobert   Log *log = GetLog(LLDBLog::Expressions);
461061da546Spatrick   LLDB_LOG(log, "[C++ module config] {0}", msg);
462061da546Spatrick   return CppModuleConfiguration();
463061da546Spatrick }
464061da546Spatrick 
GetModuleConfig(lldb::LanguageType language,ExecutionContext & exe_ctx)465061da546Spatrick CppModuleConfiguration GetModuleConfig(lldb::LanguageType language,
466061da546Spatrick                                        ExecutionContext &exe_ctx) {
467*f6aab3d8Srobert   Log *log = GetLog(LLDBLog::Expressions);
468061da546Spatrick 
469061da546Spatrick   // Don't do anything if this is not a C++ module configuration.
470061da546Spatrick   if (!SupportsCxxModuleImport(language))
471061da546Spatrick     return LogConfigError("Language doesn't support C++ modules");
472061da546Spatrick 
473061da546Spatrick   Target *target = exe_ctx.GetTargetPtr();
474061da546Spatrick   if (!target)
475061da546Spatrick     return LogConfigError("No target");
476061da546Spatrick 
477061da546Spatrick   StackFrame *frame = exe_ctx.GetFramePtr();
478061da546Spatrick   if (!frame)
479061da546Spatrick     return LogConfigError("No frame");
480061da546Spatrick 
481061da546Spatrick   Block *block = frame->GetFrameBlock();
482061da546Spatrick   if (!block)
483061da546Spatrick     return LogConfigError("No block");
484061da546Spatrick 
485061da546Spatrick   SymbolContext sc;
486061da546Spatrick   block->CalculateSymbolContext(&sc);
487061da546Spatrick   if (!sc.comp_unit)
488061da546Spatrick     return LogConfigError("Couldn't calculate symbol context");
489061da546Spatrick 
490061da546Spatrick   // Build a list of files we need to analyze to build the configuration.
491061da546Spatrick   FileSpecList files;
492061da546Spatrick   for (const FileSpec &f : sc.comp_unit->GetSupportFiles())
493061da546Spatrick     files.AppendIfUnique(f);
494061da546Spatrick   // We also need to look at external modules in the case of -gmodules as they
495061da546Spatrick   // contain the support files for libc++ and the C library.
496061da546Spatrick   llvm::DenseSet<SymbolFile *> visited_symbol_files;
497061da546Spatrick   sc.comp_unit->ForEachExternalModule(
498061da546Spatrick       visited_symbol_files, [&files](Module &module) {
499061da546Spatrick         for (std::size_t i = 0; i < module.GetNumCompileUnits(); ++i) {
500061da546Spatrick           const FileSpecList &support_files =
501061da546Spatrick               module.GetCompileUnitAtIndex(i)->GetSupportFiles();
502061da546Spatrick           for (const FileSpec &f : support_files) {
503061da546Spatrick             files.AppendIfUnique(f);
504061da546Spatrick           }
505061da546Spatrick         }
506061da546Spatrick         return false;
507061da546Spatrick       });
508061da546Spatrick 
509061da546Spatrick   LLDB_LOG(log, "[C++ module config] Found {0} support files to analyze",
510061da546Spatrick            files.GetSize());
511061da546Spatrick   if (log && log->GetVerbose()) {
512061da546Spatrick     for (const FileSpec &f : files)
513061da546Spatrick       LLDB_LOGV(log, "[C++ module config] Analyzing support file: {0}",
514061da546Spatrick                 f.GetPath());
515061da546Spatrick   }
516061da546Spatrick 
517061da546Spatrick   // Try to create a configuration from the files. If there is no valid
518061da546Spatrick   // configuration possible with the files, this just returns an invalid
519061da546Spatrick   // configuration.
520*f6aab3d8Srobert   return CppModuleConfiguration(files, target->GetArchitecture().GetTriple());
521061da546Spatrick }
522061da546Spatrick 
PrepareForParsing(DiagnosticManager & diagnostic_manager,ExecutionContext & exe_ctx,bool for_completion)523061da546Spatrick bool ClangUserExpression::PrepareForParsing(
524061da546Spatrick     DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx,
525061da546Spatrick     bool for_completion) {
526061da546Spatrick   InstallContext(exe_ctx);
527061da546Spatrick 
528061da546Spatrick   if (!SetupPersistentState(diagnostic_manager, exe_ctx))
529061da546Spatrick     return false;
530061da546Spatrick 
531061da546Spatrick   Status err;
532061da546Spatrick   ScanContext(exe_ctx, err);
533061da546Spatrick 
534061da546Spatrick   if (!err.Success()) {
535061da546Spatrick     diagnostic_manager.PutString(eDiagnosticSeverityWarning, err.AsCString());
536061da546Spatrick   }
537061da546Spatrick 
538061da546Spatrick   ////////////////////////////////////
539061da546Spatrick   // Generate the expression
540061da546Spatrick   //
541061da546Spatrick 
542061da546Spatrick   ApplyObjcCastHack(m_expr_text);
543061da546Spatrick 
544dda28197Spatrick   SetupDeclVendor(exe_ctx, m_target, diagnostic_manager);
545061da546Spatrick 
546be691f3bSpatrick   m_filename = m_clang_state->GetNextExprFileName();
547be691f3bSpatrick 
548be691f3bSpatrick   if (m_target->GetImportStdModule() == eImportStdModuleTrue)
549be691f3bSpatrick     SetupCppModuleImports(exe_ctx);
550be691f3bSpatrick 
551be691f3bSpatrick   CreateSourceCode(diagnostic_manager, exe_ctx, m_imported_cpp_modules,
552be691f3bSpatrick                    for_completion);
553be691f3bSpatrick   return true;
554be691f3bSpatrick }
555be691f3bSpatrick 
TryParse(DiagnosticManager & diagnostic_manager,ExecutionContextScope * exe_scope,ExecutionContext & exe_ctx,lldb_private::ExecutionPolicy execution_policy,bool keep_result_in_memory,bool generate_debug_info)556be691f3bSpatrick bool ClangUserExpression::TryParse(
557be691f3bSpatrick     DiagnosticManager &diagnostic_manager, ExecutionContextScope *exe_scope,
558be691f3bSpatrick     ExecutionContext &exe_ctx, lldb_private::ExecutionPolicy execution_policy,
559be691f3bSpatrick     bool keep_result_in_memory, bool generate_debug_info) {
560be691f3bSpatrick   m_materializer_up = std::make_unique<Materializer>();
561be691f3bSpatrick 
562be691f3bSpatrick   ResetDeclMap(exe_ctx, m_result_delegate, keep_result_in_memory);
563be691f3bSpatrick 
564be691f3bSpatrick   auto on_exit = llvm::make_scope_exit([this]() { ResetDeclMap(); });
565be691f3bSpatrick 
566be691f3bSpatrick   if (!DeclMap()->WillParse(exe_ctx, GetMaterializer())) {
567be691f3bSpatrick     diagnostic_manager.PutString(
568be691f3bSpatrick         eDiagnosticSeverityError,
569be691f3bSpatrick         "current process state is unsuitable for expression parsing");
570be691f3bSpatrick     return false;
571be691f3bSpatrick   }
572be691f3bSpatrick 
573be691f3bSpatrick   if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel) {
574be691f3bSpatrick     DeclMap()->SetLookupsEnabled(true);
575be691f3bSpatrick   }
576be691f3bSpatrick 
577be691f3bSpatrick   m_parser = std::make_unique<ClangExpressionParser>(
578be691f3bSpatrick       exe_scope, *this, generate_debug_info, m_include_directories, m_filename);
579be691f3bSpatrick 
580be691f3bSpatrick   unsigned num_errors = m_parser->Parse(diagnostic_manager);
581be691f3bSpatrick 
582be691f3bSpatrick   // Check here for FixItHints.  If there are any try to apply the fixits and
583be691f3bSpatrick   // set the fixed text in m_fixed_text before returning an error.
584be691f3bSpatrick   if (num_errors) {
585be691f3bSpatrick     if (diagnostic_manager.HasFixIts()) {
586be691f3bSpatrick       if (m_parser->RewriteExpression(diagnostic_manager)) {
587be691f3bSpatrick         size_t fixed_start;
588be691f3bSpatrick         size_t fixed_end;
589be691f3bSpatrick         m_fixed_text = diagnostic_manager.GetFixedExpression();
590be691f3bSpatrick         // Retrieve the original expression in case we don't have a top level
591be691f3bSpatrick         // expression (which has no surrounding source code).
592be691f3bSpatrick         if (m_source_code && m_source_code->GetOriginalBodyBounds(
593be691f3bSpatrick                                  m_fixed_text, fixed_start, fixed_end))
594be691f3bSpatrick           m_fixed_text =
595be691f3bSpatrick               m_fixed_text.substr(fixed_start, fixed_end - fixed_start);
596be691f3bSpatrick       }
597be691f3bSpatrick     }
598be691f3bSpatrick     return false;
599be691f3bSpatrick   }
600be691f3bSpatrick 
601be691f3bSpatrick   //////////////////////////////////////////////////////////////////////////////
602be691f3bSpatrick   // Prepare the output of the parser for execution, evaluating it statically
603be691f3bSpatrick   // if possible
604be691f3bSpatrick   //
605be691f3bSpatrick 
606be691f3bSpatrick   {
607be691f3bSpatrick     Status jit_error = m_parser->PrepareForExecution(
608be691f3bSpatrick         m_jit_start_addr, m_jit_end_addr, m_execution_unit_sp, exe_ctx,
609be691f3bSpatrick         m_can_interpret, execution_policy);
610be691f3bSpatrick 
611be691f3bSpatrick     if (!jit_error.Success()) {
612be691f3bSpatrick       const char *error_cstr = jit_error.AsCString();
613be691f3bSpatrick       if (error_cstr && error_cstr[0])
614be691f3bSpatrick         diagnostic_manager.PutString(eDiagnosticSeverityError, error_cstr);
615be691f3bSpatrick       else
616be691f3bSpatrick         diagnostic_manager.PutString(eDiagnosticSeverityError,
617be691f3bSpatrick                                      "expression can't be interpreted or run");
618be691f3bSpatrick       return false;
619be691f3bSpatrick     }
620be691f3bSpatrick   }
621be691f3bSpatrick   return true;
622be691f3bSpatrick }
623be691f3bSpatrick 
SetupCppModuleImports(ExecutionContext & exe_ctx)624be691f3bSpatrick void ClangUserExpression::SetupCppModuleImports(ExecutionContext &exe_ctx) {
625*f6aab3d8Srobert   Log *log = GetLog(LLDBLog::Expressions);
626be691f3bSpatrick 
627061da546Spatrick   CppModuleConfiguration module_config = GetModuleConfig(m_language, exe_ctx);
628be691f3bSpatrick   m_imported_cpp_modules = module_config.GetImportedModules();
629061da546Spatrick   m_include_directories = module_config.GetIncludeDirs();
630061da546Spatrick 
631061da546Spatrick   LLDB_LOG(log, "List of imported modules in expression: {0}",
632be691f3bSpatrick            llvm::make_range(m_imported_cpp_modules.begin(),
633be691f3bSpatrick                             m_imported_cpp_modules.end()));
634061da546Spatrick   LLDB_LOG(log, "List of include directories gathered for modules: {0}",
635061da546Spatrick            llvm::make_range(m_include_directories.begin(),
636061da546Spatrick                             m_include_directories.end()));
637be691f3bSpatrick }
638061da546Spatrick 
shouldRetryWithCppModule(Target & target,ExecutionPolicy exe_policy)639be691f3bSpatrick static bool shouldRetryWithCppModule(Target &target, ExecutionPolicy exe_policy) {
640be691f3bSpatrick   // Top-level expression don't yet support importing C++ modules.
641be691f3bSpatrick   if (exe_policy == ExecutionPolicy::eExecutionPolicyTopLevel)
642be691f3bSpatrick     return false;
643be691f3bSpatrick   return target.GetImportStdModule() == eImportStdModuleFallback;
644061da546Spatrick }
645061da546Spatrick 
Parse(DiagnosticManager & diagnostic_manager,ExecutionContext & exe_ctx,lldb_private::ExecutionPolicy execution_policy,bool keep_result_in_memory,bool generate_debug_info)646061da546Spatrick bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager,
647061da546Spatrick                                 ExecutionContext &exe_ctx,
648061da546Spatrick                                 lldb_private::ExecutionPolicy execution_policy,
649061da546Spatrick                                 bool keep_result_in_memory,
650061da546Spatrick                                 bool generate_debug_info) {
651*f6aab3d8Srobert   Log *log = GetLog(LLDBLog::Expressions);
652061da546Spatrick 
653061da546Spatrick   if (!PrepareForParsing(diagnostic_manager, exe_ctx, /*for_completion*/ false))
654061da546Spatrick     return false;
655061da546Spatrick 
656061da546Spatrick   LLDB_LOGF(log, "Parsing the following code:\n%s", m_transformed_text.c_str());
657061da546Spatrick 
658061da546Spatrick   ////////////////////////////////////
659061da546Spatrick   // Set up the target and compiler
660061da546Spatrick   //
661061da546Spatrick 
662061da546Spatrick   Target *target = exe_ctx.GetTargetPtr();
663061da546Spatrick 
664061da546Spatrick   if (!target) {
665061da546Spatrick     diagnostic_manager.PutString(eDiagnosticSeverityError, "invalid target");
666061da546Spatrick     return false;
667061da546Spatrick   }
668061da546Spatrick 
669061da546Spatrick   //////////////////////////
670061da546Spatrick   // Parse the expression
671061da546Spatrick   //
672061da546Spatrick 
673061da546Spatrick   Process *process = exe_ctx.GetProcessPtr();
674061da546Spatrick   ExecutionContextScope *exe_scope = process;
675061da546Spatrick 
676061da546Spatrick   if (!exe_scope)
677061da546Spatrick     exe_scope = exe_ctx.GetTargetPtr();
678061da546Spatrick 
679be691f3bSpatrick   bool parse_success = TryParse(diagnostic_manager, exe_scope, exe_ctx,
680be691f3bSpatrick                                 execution_policy, keep_result_in_memory,
681be691f3bSpatrick                                 generate_debug_info);
682be691f3bSpatrick   // If the expression failed to parse, check if retrying parsing with a loaded
683be691f3bSpatrick   // C++ module is possible.
684be691f3bSpatrick   if (!parse_success && shouldRetryWithCppModule(*target, execution_policy)) {
685be691f3bSpatrick     // Load the loaded C++ modules.
686be691f3bSpatrick     SetupCppModuleImports(exe_ctx);
687be691f3bSpatrick     // If we did load any modules, then retry parsing.
688be691f3bSpatrick     if (!m_imported_cpp_modules.empty()) {
689*f6aab3d8Srobert       // Create a dedicated diagnostic manager for the second parse attempt.
690*f6aab3d8Srobert       // These diagnostics are only returned to the caller if using the fallback
691*f6aab3d8Srobert       // actually succeeded in getting the expression to parse. This prevents
692*f6aab3d8Srobert       // that module-specific issues regress diagnostic quality with the
693*f6aab3d8Srobert       // fallback mode.
694*f6aab3d8Srobert       DiagnosticManager retry_manager;
695be691f3bSpatrick       // The module imports are injected into the source code wrapper,
696be691f3bSpatrick       // so recreate those.
697*f6aab3d8Srobert       CreateSourceCode(retry_manager, exe_ctx, m_imported_cpp_modules,
698be691f3bSpatrick                        /*for_completion*/ false);
699*f6aab3d8Srobert       parse_success = TryParse(retry_manager, exe_scope, exe_ctx,
700be691f3bSpatrick                                execution_policy, keep_result_in_memory,
701be691f3bSpatrick                                generate_debug_info);
702*f6aab3d8Srobert       // Return the parse diagnostics if we were successful.
703*f6aab3d8Srobert       if (parse_success)
704*f6aab3d8Srobert         diagnostic_manager = std::move(retry_manager);
705061da546Spatrick     }
706061da546Spatrick   }
707be691f3bSpatrick   if (!parse_success)
708061da546Spatrick     return false;
709061da546Spatrick 
710061da546Spatrick   if (exe_ctx.GetProcessPtr() && execution_policy == eExecutionPolicyTopLevel) {
711061da546Spatrick     Status static_init_error =
712be691f3bSpatrick         m_parser->RunStaticInitializers(m_execution_unit_sp, exe_ctx);
713061da546Spatrick 
714061da546Spatrick     if (!static_init_error.Success()) {
715061da546Spatrick       const char *error_cstr = static_init_error.AsCString();
716061da546Spatrick       if (error_cstr && error_cstr[0])
717061da546Spatrick         diagnostic_manager.Printf(eDiagnosticSeverityError,
718dda28197Spatrick                                   "%s\n",
719061da546Spatrick                                   error_cstr);
720061da546Spatrick       else
721061da546Spatrick         diagnostic_manager.PutString(eDiagnosticSeverityError,
722061da546Spatrick                                      "couldn't run static initializers\n");
723061da546Spatrick       return false;
724061da546Spatrick     }
725061da546Spatrick   }
726061da546Spatrick 
727061da546Spatrick   if (m_execution_unit_sp) {
728061da546Spatrick     bool register_execution_unit = false;
729061da546Spatrick 
730061da546Spatrick     if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel) {
731061da546Spatrick       register_execution_unit = true;
732061da546Spatrick     }
733061da546Spatrick 
734061da546Spatrick     // If there is more than one external function in the execution unit, it
735061da546Spatrick     // needs to keep living even if it's not top level, because the result
736061da546Spatrick     // could refer to that function.
737061da546Spatrick 
738061da546Spatrick     if (m_execution_unit_sp->GetJittedFunctions().size() > 1) {
739061da546Spatrick       register_execution_unit = true;
740061da546Spatrick     }
741061da546Spatrick 
742061da546Spatrick     if (register_execution_unit) {
743061da546Spatrick       if (auto *persistent_state =
744061da546Spatrick               exe_ctx.GetTargetPtr()->GetPersistentExpressionStateForLanguage(
745061da546Spatrick                   m_language))
746061da546Spatrick         persistent_state->RegisterExecutionUnit(m_execution_unit_sp);
747061da546Spatrick     }
748061da546Spatrick   }
749061da546Spatrick 
750061da546Spatrick   if (generate_debug_info) {
751061da546Spatrick     lldb::ModuleSP jit_module_sp(m_execution_unit_sp->GetJITModule());
752061da546Spatrick 
753061da546Spatrick     if (jit_module_sp) {
754061da546Spatrick       ConstString const_func_name(FunctionName());
755061da546Spatrick       FileSpec jit_file;
756*f6aab3d8Srobert       jit_file.SetFilename(const_func_name);
757061da546Spatrick       jit_module_sp->SetFileSpecAndObjectName(jit_file, ConstString());
758061da546Spatrick       m_jit_module_wp = jit_module_sp;
759061da546Spatrick       target->GetImages().Append(jit_module_sp);
760061da546Spatrick     }
761061da546Spatrick   }
762061da546Spatrick 
763061da546Spatrick   if (process && m_jit_start_addr != LLDB_INVALID_ADDRESS)
764061da546Spatrick     m_jit_process_wp = lldb::ProcessWP(process->shared_from_this());
765061da546Spatrick   return true;
766061da546Spatrick }
767061da546Spatrick 
768061da546Spatrick /// Converts an absolute position inside a given code string into
769061da546Spatrick /// a column/line pair.
770061da546Spatrick ///
771061da546Spatrick /// \param[in] abs_pos
772061da546Spatrick ///     A absolute position in the code string that we want to convert
773061da546Spatrick ///     to a column/line pair.
774061da546Spatrick ///
775061da546Spatrick /// \param[in] code
776061da546Spatrick ///     A multi-line string usually representing source code.
777061da546Spatrick ///
778061da546Spatrick /// \param[out] line
779061da546Spatrick ///     The line in the code that contains the given absolute position.
780061da546Spatrick ///     The first line in the string is indexed as 1.
781061da546Spatrick ///
782061da546Spatrick /// \param[out] column
783061da546Spatrick ///     The column in the line that contains the absolute position.
784061da546Spatrick ///     The first character in a line is indexed as 0.
AbsPosToLineColumnPos(size_t abs_pos,llvm::StringRef code,unsigned & line,unsigned & column)785061da546Spatrick static void AbsPosToLineColumnPos(size_t abs_pos, llvm::StringRef code,
786061da546Spatrick                                   unsigned &line, unsigned &column) {
787061da546Spatrick   // Reset to code position to beginning of the file.
788061da546Spatrick   line = 0;
789061da546Spatrick   column = 0;
790061da546Spatrick 
791061da546Spatrick   assert(abs_pos <= code.size() && "Absolute position outside code string?");
792061da546Spatrick 
793061da546Spatrick   // We have to walk up to the position and count lines/columns.
794061da546Spatrick   for (std::size_t i = 0; i < abs_pos; ++i) {
795061da546Spatrick     // If we hit a line break, we go back to column 0 and enter a new line.
796061da546Spatrick     // We only handle \n because that's what we internally use to make new
797061da546Spatrick     // lines for our temporary code strings.
798061da546Spatrick     if (code[i] == '\n') {
799061da546Spatrick       ++line;
800061da546Spatrick       column = 0;
801061da546Spatrick       continue;
802061da546Spatrick     }
803061da546Spatrick     ++column;
804061da546Spatrick   }
805061da546Spatrick }
806061da546Spatrick 
Complete(ExecutionContext & exe_ctx,CompletionRequest & request,unsigned complete_pos)807061da546Spatrick bool ClangUserExpression::Complete(ExecutionContext &exe_ctx,
808061da546Spatrick                                    CompletionRequest &request,
809061da546Spatrick                                    unsigned complete_pos) {
810*f6aab3d8Srobert   Log *log = GetLog(LLDBLog::Expressions);
811061da546Spatrick 
812061da546Spatrick   // We don't want any visible feedback when completing an expression. Mostly
813061da546Spatrick   // because the results we get from an incomplete invocation are probably not
814061da546Spatrick   // correct.
815061da546Spatrick   DiagnosticManager diagnostic_manager;
816061da546Spatrick 
817061da546Spatrick   if (!PrepareForParsing(diagnostic_manager, exe_ctx, /*for_completion*/ true))
818061da546Spatrick     return false;
819061da546Spatrick 
820061da546Spatrick   LLDB_LOGF(log, "Parsing the following code:\n%s", m_transformed_text.c_str());
821061da546Spatrick 
822061da546Spatrick   //////////////////////////
823061da546Spatrick   // Parse the expression
824061da546Spatrick   //
825061da546Spatrick 
826dda28197Spatrick   m_materializer_up = std::make_unique<Materializer>();
827061da546Spatrick 
828061da546Spatrick   ResetDeclMap(exe_ctx, m_result_delegate, /*keep result in memory*/ true);
829061da546Spatrick 
830061da546Spatrick   auto on_exit = llvm::make_scope_exit([this]() { ResetDeclMap(); });
831061da546Spatrick 
832061da546Spatrick   if (!DeclMap()->WillParse(exe_ctx, GetMaterializer())) {
833061da546Spatrick     diagnostic_manager.PutString(
834061da546Spatrick         eDiagnosticSeverityError,
835061da546Spatrick         "current process state is unsuitable for expression parsing");
836061da546Spatrick 
837061da546Spatrick     return false;
838061da546Spatrick   }
839061da546Spatrick 
840061da546Spatrick   if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel) {
841061da546Spatrick     DeclMap()->SetLookupsEnabled(true);
842061da546Spatrick   }
843061da546Spatrick 
844061da546Spatrick   Process *process = exe_ctx.GetProcessPtr();
845061da546Spatrick   ExecutionContextScope *exe_scope = process;
846061da546Spatrick 
847061da546Spatrick   if (!exe_scope)
848061da546Spatrick     exe_scope = exe_ctx.GetTargetPtr();
849061da546Spatrick 
850061da546Spatrick   ClangExpressionParser parser(exe_scope, *this, false);
851061da546Spatrick 
852061da546Spatrick   // We have to find the source code location where the user text is inside
853061da546Spatrick   // the transformed expression code. When creating the transformed text, we
854061da546Spatrick   // already stored the absolute position in the m_transformed_text string. The
855061da546Spatrick   // only thing left to do is to transform it into the line:column format that
856061da546Spatrick   // Clang expects.
857061da546Spatrick 
858061da546Spatrick   // The line and column of the user expression inside the transformed source
859061da546Spatrick   // code.
860061da546Spatrick   unsigned user_expr_line, user_expr_column;
861*f6aab3d8Srobert   if (m_user_expression_start_pos)
862061da546Spatrick     AbsPosToLineColumnPos(*m_user_expression_start_pos, m_transformed_text,
863061da546Spatrick                           user_expr_line, user_expr_column);
864061da546Spatrick   else
865061da546Spatrick     return false;
866061da546Spatrick 
867061da546Spatrick   // The actual column where we have to complete is the start column of the
868061da546Spatrick   // user expression + the offset inside the user code that we were given.
869061da546Spatrick   const unsigned completion_column = user_expr_column + complete_pos;
870061da546Spatrick   parser.Complete(request, user_expr_line, completion_column, complete_pos);
871061da546Spatrick 
872061da546Spatrick   return true;
873061da546Spatrick }
874061da546Spatrick 
GetCppObjectPointer(lldb::StackFrameSP frame_sp,ConstString & object_name,Status & err)875*f6aab3d8Srobert lldb::addr_t ClangUserExpression::GetCppObjectPointer(
876*f6aab3d8Srobert     lldb::StackFrameSP frame_sp, ConstString &object_name, Status &err) {
877*f6aab3d8Srobert   auto valobj_sp =
878*f6aab3d8Srobert       GetObjectPointerValueObject(std::move(frame_sp), object_name, err);
879*f6aab3d8Srobert 
880*f6aab3d8Srobert   // We're inside a C++ class method. This could potentially be an unnamed
881*f6aab3d8Srobert   // lambda structure. If the lambda captured a "this", that should be
882*f6aab3d8Srobert   // the object pointer.
883*f6aab3d8Srobert   if (auto thisChildSP =
884*f6aab3d8Srobert           valobj_sp->GetChildMemberWithName(ConstString("this"), true)) {
885*f6aab3d8Srobert     valobj_sp = thisChildSP;
886*f6aab3d8Srobert   }
887*f6aab3d8Srobert 
888*f6aab3d8Srobert   if (!err.Success() || !valobj_sp.get())
889*f6aab3d8Srobert     return LLDB_INVALID_ADDRESS;
890*f6aab3d8Srobert 
891*f6aab3d8Srobert   lldb::addr_t ret = valobj_sp->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
892*f6aab3d8Srobert 
893*f6aab3d8Srobert   if (ret == LLDB_INVALID_ADDRESS) {
894*f6aab3d8Srobert     err.SetErrorStringWithFormat(
895*f6aab3d8Srobert         "Couldn't load '%s' because its value couldn't be evaluated",
896*f6aab3d8Srobert         object_name.AsCString());
897*f6aab3d8Srobert     return LLDB_INVALID_ADDRESS;
898*f6aab3d8Srobert   }
899*f6aab3d8Srobert 
900*f6aab3d8Srobert   return ret;
901*f6aab3d8Srobert }
902*f6aab3d8Srobert 
AddArguments(ExecutionContext & exe_ctx,std::vector<lldb::addr_t> & args,lldb::addr_t struct_address,DiagnosticManager & diagnostic_manager)903061da546Spatrick bool ClangUserExpression::AddArguments(ExecutionContext &exe_ctx,
904061da546Spatrick                                        std::vector<lldb::addr_t> &args,
905061da546Spatrick                                        lldb::addr_t struct_address,
906061da546Spatrick                                        DiagnosticManager &diagnostic_manager) {
907061da546Spatrick   lldb::addr_t object_ptr = LLDB_INVALID_ADDRESS;
908061da546Spatrick   lldb::addr_t cmd_ptr = LLDB_INVALID_ADDRESS;
909061da546Spatrick 
910061da546Spatrick   if (m_needs_object_ptr) {
911061da546Spatrick     lldb::StackFrameSP frame_sp = exe_ctx.GetFrameSP();
912061da546Spatrick     if (!frame_sp)
913061da546Spatrick       return true;
914061da546Spatrick 
915061da546Spatrick     ConstString object_name;
916061da546Spatrick 
917061da546Spatrick     if (m_in_cplusplus_method) {
918061da546Spatrick       object_name.SetCString("this");
919061da546Spatrick     } else if (m_in_objectivec_method) {
920061da546Spatrick       object_name.SetCString("self");
921061da546Spatrick     } else {
922061da546Spatrick       diagnostic_manager.PutString(
923061da546Spatrick           eDiagnosticSeverityError,
924061da546Spatrick           "need object pointer but don't know the language");
925061da546Spatrick       return false;
926061da546Spatrick     }
927061da546Spatrick 
928061da546Spatrick     Status object_ptr_error;
929061da546Spatrick 
930061da546Spatrick     if (m_ctx_obj) {
931061da546Spatrick       AddressType address_type;
932061da546Spatrick       object_ptr = m_ctx_obj->GetAddressOf(false, &address_type);
933061da546Spatrick       if (object_ptr == LLDB_INVALID_ADDRESS ||
934061da546Spatrick           address_type != eAddressTypeLoad)
935061da546Spatrick         object_ptr_error.SetErrorString("Can't get context object's "
936061da546Spatrick                                         "debuggee address");
937*f6aab3d8Srobert     } else {
938*f6aab3d8Srobert       if (m_in_cplusplus_method) {
939*f6aab3d8Srobert         object_ptr =
940*f6aab3d8Srobert             GetCppObjectPointer(frame_sp, object_name, object_ptr_error);
941*f6aab3d8Srobert       } else {
942061da546Spatrick         object_ptr = GetObjectPointer(frame_sp, object_name, object_ptr_error);
943*f6aab3d8Srobert       }
944*f6aab3d8Srobert     }
945061da546Spatrick 
946061da546Spatrick     if (!object_ptr_error.Success()) {
947061da546Spatrick       exe_ctx.GetTargetRef().GetDebugger().GetAsyncOutputStream()->Printf(
948*f6aab3d8Srobert           "warning: `%s' is not accessible (substituting 0). %s\n",
949*f6aab3d8Srobert           object_name.AsCString(), object_ptr_error.AsCString());
950061da546Spatrick       object_ptr = 0;
951061da546Spatrick     }
952061da546Spatrick 
953061da546Spatrick     if (m_in_objectivec_method) {
954061da546Spatrick       ConstString cmd_name("_cmd");
955061da546Spatrick 
956061da546Spatrick       cmd_ptr = GetObjectPointer(frame_sp, cmd_name, object_ptr_error);
957061da546Spatrick 
958061da546Spatrick       if (!object_ptr_error.Success()) {
959061da546Spatrick         diagnostic_manager.Printf(
960061da546Spatrick             eDiagnosticSeverityWarning,
961061da546Spatrick             "couldn't get cmd pointer (substituting NULL): %s",
962061da546Spatrick             object_ptr_error.AsCString());
963061da546Spatrick         cmd_ptr = 0;
964061da546Spatrick       }
965061da546Spatrick     }
966061da546Spatrick 
967061da546Spatrick     args.push_back(object_ptr);
968061da546Spatrick 
969061da546Spatrick     if (m_in_objectivec_method)
970061da546Spatrick       args.push_back(cmd_ptr);
971061da546Spatrick 
972061da546Spatrick     args.push_back(struct_address);
973061da546Spatrick   } else {
974061da546Spatrick     args.push_back(struct_address);
975061da546Spatrick   }
976061da546Spatrick   return true;
977061da546Spatrick }
978061da546Spatrick 
GetResultAfterDematerialization(ExecutionContextScope * exe_scope)979061da546Spatrick lldb::ExpressionVariableSP ClangUserExpression::GetResultAfterDematerialization(
980061da546Spatrick     ExecutionContextScope *exe_scope) {
981061da546Spatrick   return m_result_delegate.GetVariable();
982061da546Spatrick }
983061da546Spatrick 
ResetDeclMap(ExecutionContext & exe_ctx,Materializer::PersistentVariableDelegate & delegate,bool keep_result_in_memory,ValueObject * ctx_obj)984061da546Spatrick void ClangUserExpression::ClangUserExpressionHelper::ResetDeclMap(
985061da546Spatrick     ExecutionContext &exe_ctx,
986061da546Spatrick     Materializer::PersistentVariableDelegate &delegate,
987061da546Spatrick     bool keep_result_in_memory,
988061da546Spatrick     ValueObject *ctx_obj) {
989dda28197Spatrick   std::shared_ptr<ClangASTImporter> ast_importer;
990dda28197Spatrick   auto *state = exe_ctx.GetTargetSP()->GetPersistentExpressionStateForLanguage(
991dda28197Spatrick       lldb::eLanguageTypeC);
992dda28197Spatrick   if (state) {
993dda28197Spatrick     auto *persistent_vars = llvm::cast<ClangPersistentVariables>(state);
994dda28197Spatrick     ast_importer = persistent_vars->GetClangASTImporter();
995dda28197Spatrick   }
996dda28197Spatrick   m_expr_decl_map_up = std::make_unique<ClangExpressionDeclMap>(
997dda28197Spatrick       keep_result_in_memory, &delegate, exe_ctx.GetTargetSP(), ast_importer,
998dda28197Spatrick       ctx_obj);
999061da546Spatrick }
1000061da546Spatrick 
1001061da546Spatrick clang::ASTConsumer *
ASTTransformer(clang::ASTConsumer * passthrough)1002061da546Spatrick ClangUserExpression::ClangUserExpressionHelper::ASTTransformer(
1003061da546Spatrick     clang::ASTConsumer *passthrough) {
1004dda28197Spatrick   m_result_synthesizer_up = std::make_unique<ASTResultSynthesizer>(
1005dda28197Spatrick       passthrough, m_top_level, m_target);
1006061da546Spatrick 
1007061da546Spatrick   return m_result_synthesizer_up.get();
1008061da546Spatrick }
1009061da546Spatrick 
CommitPersistentDecls()1010061da546Spatrick void ClangUserExpression::ClangUserExpressionHelper::CommitPersistentDecls() {
1011061da546Spatrick   if (m_result_synthesizer_up) {
1012061da546Spatrick     m_result_synthesizer_up->CommitPersistentDecls();
1013061da546Spatrick   }
1014061da546Spatrick }
1015061da546Spatrick 
GetName()1016061da546Spatrick ConstString ClangUserExpression::ResultDelegate::GetName() {
1017dda28197Spatrick   return m_persistent_state->GetNextPersistentVariableName(false);
1018061da546Spatrick }
1019061da546Spatrick 
DidDematerialize(lldb::ExpressionVariableSP & variable)1020061da546Spatrick void ClangUserExpression::ResultDelegate::DidDematerialize(
1021061da546Spatrick     lldb::ExpressionVariableSP &variable) {
1022061da546Spatrick   m_variable = variable;
1023061da546Spatrick }
1024061da546Spatrick 
RegisterPersistentState(PersistentExpressionState * persistent_state)1025061da546Spatrick void ClangUserExpression::ResultDelegate::RegisterPersistentState(
1026061da546Spatrick     PersistentExpressionState *persistent_state) {
1027061da546Spatrick   m_persistent_state = persistent_state;
1028061da546Spatrick }
1029061da546Spatrick 
GetVariable()1030061da546Spatrick lldb::ExpressionVariableSP &ClangUserExpression::ResultDelegate::GetVariable() {
1031061da546Spatrick   return m_variable;
1032061da546Spatrick }
1033