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