180814287SRaphael Isemann //===-- ClangUserExpression.cpp -------------------------------------------===//
24dbb271fSSean Callanan //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
64dbb271fSSean Callanan //
74dbb271fSSean Callanan //===----------------------------------------------------------------------===//
84dbb271fSSean Callanan
976e47d48SRaphael Isemann #include <cstdio>
104dbb271fSSean Callanan #include <sys/types.h>
114dbb271fSSean Callanan
124dbb271fSSean Callanan #include <cstdlib>
134dbb271fSSean Callanan #include <map>
14b9c1b51eSKate Stone #include <string>
154dbb271fSSean Callanan
164dbb271fSSean Callanan #include "ClangUserExpression.h"
174dbb271fSSean Callanan
184dbb271fSSean Callanan #include "ASTResultSynthesizer.h"
198be30215SAlex Langford #include "ClangASTMetadata.h"
20b9c1b51eSKate Stone #include "ClangDiagnostic.h"
214dbb271fSSean Callanan #include "ClangExpressionDeclMap.h"
224dbb271fSSean Callanan #include "ClangExpressionParser.h"
234dbb271fSSean Callanan #include "ClangModulesDeclVendor.h"
244dbb271fSSean Callanan #include "ClangPersistentVariables.h"
259379d19fSRaphael Isemann #include "CppModuleConfiguration.h"
264dbb271fSSean Callanan
278be30215SAlex Langford #include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
28bda7ef84SSean Callanan #include "lldb/Core/Debugger.h"
294dbb271fSSean Callanan #include "lldb/Core/Module.h"
304dbb271fSSean Callanan #include "lldb/Core/StreamFile.h"
314dbb271fSSean Callanan #include "lldb/Core/ValueObjectConstResult.h"
324dbb271fSSean Callanan #include "lldb/Expression/ExpressionSourceCode.h"
334dbb271fSSean Callanan #include "lldb/Expression/IRExecutionUnit.h"
344dbb271fSSean Callanan #include "lldb/Expression/IRInterpreter.h"
354dbb271fSSean Callanan #include "lldb/Expression/Materializer.h"
364dbb271fSSean Callanan #include "lldb/Host/HostInfo.h"
374dbb271fSSean Callanan #include "lldb/Symbol/Block.h"
386c0bbfc0SRaphael Isemann #include "lldb/Symbol/CompileUnit.h"
394dbb271fSSean Callanan #include "lldb/Symbol/Function.h"
404dbb271fSSean Callanan #include "lldb/Symbol/ObjectFile.h"
410e45e60cSAdrian Prantl #include "lldb/Symbol/SymbolFile.h"
424dbb271fSSean Callanan #include "lldb/Symbol/SymbolVendor.h"
434dbb271fSSean Callanan #include "lldb/Symbol/Type.h"
444dbb271fSSean Callanan #include "lldb/Symbol/VariableList.h"
454dbb271fSSean Callanan #include "lldb/Target/ExecutionContext.h"
464dbb271fSSean Callanan #include "lldb/Target/Process.h"
474dbb271fSSean Callanan #include "lldb/Target/StackFrame.h"
484dbb271fSSean Callanan #include "lldb/Target/Target.h"
494dbb271fSSean Callanan #include "lldb/Target/ThreadPlan.h"
504dbb271fSSean Callanan #include "lldb/Target/ThreadPlanCallUserExpression.h"
51bf9a7730SZachary Turner #include "lldb/Utility/ConstString.h"
52c34698a8SPavel Labath #include "lldb/Utility/LLDBLog.h"
536f9e6901SZachary Turner #include "lldb/Utility/Log.h"
54bf9a7730SZachary Turner #include "lldb/Utility/StreamString.h"
554dbb271fSSean Callanan
564dbb271fSSean Callanan #include "clang/AST/DeclCXX.h"
574dbb271fSSean Callanan #include "clang/AST/DeclObjC.h"
584dbb271fSSean Callanan
59edebf12aSTatyana Krasnukha #include "llvm/ADT/ScopeExit.h"
60edebf12aSTatyana Krasnukha
614dbb271fSSean Callanan using namespace lldb_private;
624dbb271fSSean Callanan
6352f3a2faSRaphael Isemann char ClangUserExpression::ID;
6452f3a2faSRaphael Isemann
ClangUserExpression(ExecutionContextScope & exe_scope,llvm::StringRef expr,llvm::StringRef prefix,lldb::LanguageType language,ResultType desired_type,const EvaluateExpressionOptions & options,ValueObject * ctx_obj)65b9c1b51eSKate Stone ClangUserExpression::ClangUserExpression(
66c5d7df90SZachary Turner ExecutionContextScope &exe_scope, llvm::StringRef expr,
67c5d7df90SZachary Turner llvm::StringRef prefix, lldb::LanguageType language,
6840624a08SAleksandr Urakov ResultType desired_type, const EvaluateExpressionOptions &options,
6940624a08SAleksandr Urakov ValueObject *ctx_obj)
70c5d7df90SZachary Turner : LLVMUserExpression(exe_scope, expr, prefix, language, desired_type,
7152f3a2faSRaphael Isemann options),
7270355aceSJonas Devlieghere m_type_system_helper(*m_target_wp.lock(), options.GetExecutionPolicy() ==
735435f780SAdrian Prantl eExecutionPolicyTopLevel),
7470355aceSJonas Devlieghere m_result_delegate(exe_scope.CalculateTarget()), m_ctx_obj(ctx_obj) {
75b9c1b51eSKate Stone switch (m_language) {
764dbb271fSSean Callanan case lldb::eLanguageTypeC_plus_plus:
774dbb271fSSean Callanan m_allow_cxx = true;
784dbb271fSSean Callanan break;
794dbb271fSSean Callanan case lldb::eLanguageTypeObjC:
804dbb271fSSean Callanan m_allow_objc = true;
814dbb271fSSean Callanan break;
824dbb271fSSean Callanan case lldb::eLanguageTypeObjC_plus_plus:
834dbb271fSSean Callanan default:
844dbb271fSSean Callanan m_allow_cxx = true;
854dbb271fSSean Callanan m_allow_objc = true;
864dbb271fSSean Callanan break;
874dbb271fSSean Callanan }
884dbb271fSSean Callanan }
894dbb271fSSean Callanan
90fd2433e1SJonas Devlieghere ClangUserExpression::~ClangUserExpression() = default;
914dbb271fSSean Callanan
ScanContext(ExecutionContext & exe_ctx,Status & err)9297206d57SZachary Turner void ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Status &err) {
93a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Expressions);
944dbb271fSSean Callanan
9563e5fb76SJonas Devlieghere LLDB_LOGF(log, "ClangUserExpression::ScanContext()");
964dbb271fSSean Callanan
974dbb271fSSean Callanan m_target = exe_ctx.GetTargetPtr();
984dbb271fSSean Callanan
99b9c1b51eSKate Stone if (!(m_allow_cxx || m_allow_objc)) {
10063e5fb76SJonas Devlieghere LLDB_LOGF(log, " [CUE::SC] Settings inhibit C++ and Objective-C");
1014dbb271fSSean Callanan return;
1024dbb271fSSean Callanan }
1034dbb271fSSean Callanan
1044dbb271fSSean Callanan StackFrame *frame = exe_ctx.GetFramePtr();
105248a1305SKonrad Kleine if (frame == nullptr) {
10663e5fb76SJonas Devlieghere LLDB_LOGF(log, " [CUE::SC] Null stack frame");
1074dbb271fSSean Callanan return;
1084dbb271fSSean Callanan }
1094dbb271fSSean Callanan
110b9c1b51eSKate Stone SymbolContext sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction |
111b9c1b51eSKate Stone lldb::eSymbolContextBlock);
1124dbb271fSSean Callanan
113b9c1b51eSKate Stone if (!sym_ctx.function) {
11463e5fb76SJonas Devlieghere LLDB_LOGF(log, " [CUE::SC] Null function");
1154dbb271fSSean Callanan return;
1164dbb271fSSean Callanan }
1174dbb271fSSean Callanan
1184dbb271fSSean Callanan // Find the block that defines the function represented by "sym_ctx"
1194dbb271fSSean Callanan Block *function_block = sym_ctx.GetFunctionBlock();
1204dbb271fSSean Callanan
121b9c1b51eSKate Stone if (!function_block) {
12263e5fb76SJonas Devlieghere LLDB_LOGF(log, " [CUE::SC] Null function block");
1234dbb271fSSean Callanan return;
1244dbb271fSSean Callanan }
1254dbb271fSSean Callanan
1264dbb271fSSean Callanan CompilerDeclContext decl_context = function_block->GetDeclContext();
1274dbb271fSSean Callanan
128b9c1b51eSKate Stone if (!decl_context) {
12963e5fb76SJonas Devlieghere LLDB_LOGF(log, " [CUE::SC] Null decl context");
1304dbb271fSSean Callanan return;
1314dbb271fSSean Callanan }
1324dbb271fSSean Callanan
13340624a08SAleksandr Urakov if (m_ctx_obj) {
13440624a08SAleksandr Urakov switch (m_ctx_obj->GetObjectRuntimeLanguage()) {
13540624a08SAleksandr Urakov case lldb::eLanguageTypeC:
13640624a08SAleksandr Urakov case lldb::eLanguageTypeC89:
13740624a08SAleksandr Urakov case lldb::eLanguageTypeC99:
13840624a08SAleksandr Urakov case lldb::eLanguageTypeC11:
13940624a08SAleksandr Urakov case lldb::eLanguageTypeC_plus_plus:
14040624a08SAleksandr Urakov case lldb::eLanguageTypeC_plus_plus_03:
14140624a08SAleksandr Urakov case lldb::eLanguageTypeC_plus_plus_11:
14240624a08SAleksandr Urakov case lldb::eLanguageTypeC_plus_plus_14:
14340624a08SAleksandr Urakov m_in_cplusplus_method = true;
14440624a08SAleksandr Urakov break;
14540624a08SAleksandr Urakov case lldb::eLanguageTypeObjC:
14640624a08SAleksandr Urakov case lldb::eLanguageTypeObjC_plus_plus:
14740624a08SAleksandr Urakov m_in_objectivec_method = true;
14840624a08SAleksandr Urakov break;
14940624a08SAleksandr Urakov default:
15040624a08SAleksandr Urakov break;
15140624a08SAleksandr Urakov }
15240624a08SAleksandr Urakov m_needs_object_ptr = true;
15340624a08SAleksandr Urakov } else if (clang::CXXMethodDecl *method_decl =
1546e3b0cc2SRaphael Isemann TypeSystemClang::DeclContextGetAsCXXMethodDecl(decl_context)) {
1554125b462SRaphael Isemann if (m_allow_cxx && method_decl->isInstance()) {
156b9c1b51eSKate Stone if (m_enforce_valid_object) {
157b9c1b51eSKate Stone lldb::VariableListSP variable_list_sp(
158b9c1b51eSKate Stone function_block->GetBlockVariableList(true));
1594dbb271fSSean Callanan
1604125b462SRaphael Isemann const char *thisErrorString = "Stopped in a C++ method, but 'this' "
161b9c1b51eSKate Stone "isn't available; pretending we are in a "
162b9c1b51eSKate Stone "generic context";
1634dbb271fSSean Callanan
164b9c1b51eSKate Stone if (!variable_list_sp) {
1654dbb271fSSean Callanan err.SetErrorString(thisErrorString);
1664dbb271fSSean Callanan return;
1674dbb271fSSean Callanan }
1684dbb271fSSean Callanan
169b9c1b51eSKate Stone lldb::VariableSP this_var_sp(
170b9c1b51eSKate Stone variable_list_sp->FindVariable(ConstString("this")));
1714dbb271fSSean Callanan
172b9c1b51eSKate Stone if (!this_var_sp || !this_var_sp->IsInScope(frame) ||
173b9c1b51eSKate Stone !this_var_sp->LocationIsValidForFrame(frame)) {
1744dbb271fSSean Callanan err.SetErrorString(thisErrorString);
1754dbb271fSSean Callanan return;
1764dbb271fSSean Callanan }
1774dbb271fSSean Callanan }
1784125b462SRaphael Isemann
17900764c36SRaphael Isemann m_in_cplusplus_method = true;
1804125b462SRaphael Isemann m_needs_object_ptr = true;
18100764c36SRaphael Isemann }
182b9c1b51eSKate Stone } else if (clang::ObjCMethodDecl *method_decl =
1836e3b0cc2SRaphael Isemann TypeSystemClang::DeclContextGetAsObjCMethodDecl(
184b9c1b51eSKate Stone decl_context)) {
185b9c1b51eSKate Stone if (m_allow_objc) {
186b9c1b51eSKate Stone if (m_enforce_valid_object) {
187b9c1b51eSKate Stone lldb::VariableListSP variable_list_sp(
188b9c1b51eSKate Stone function_block->GetBlockVariableList(true));
1894dbb271fSSean Callanan
190b9c1b51eSKate Stone const char *selfErrorString = "Stopped in an Objective-C method, but "
191b9c1b51eSKate Stone "'self' isn't available; pretending we "
192b9c1b51eSKate Stone "are in a generic context";
1934dbb271fSSean Callanan
194b9c1b51eSKate Stone if (!variable_list_sp) {
1954dbb271fSSean Callanan err.SetErrorString(selfErrorString);
1964dbb271fSSean Callanan return;
1974dbb271fSSean Callanan }
1984dbb271fSSean Callanan
199b9c1b51eSKate Stone lldb::VariableSP self_variable_sp =
200b9c1b51eSKate Stone variable_list_sp->FindVariable(ConstString("self"));
2014dbb271fSSean Callanan
202b9c1b51eSKate Stone if (!self_variable_sp || !self_variable_sp->IsInScope(frame) ||
203b9c1b51eSKate Stone !self_variable_sp->LocationIsValidForFrame(frame)) {
2044dbb271fSSean Callanan err.SetErrorString(selfErrorString);
2054dbb271fSSean Callanan return;
2064dbb271fSSean Callanan }
2074dbb271fSSean Callanan }
2084dbb271fSSean Callanan
2094dbb271fSSean Callanan m_in_objectivec_method = true;
2104dbb271fSSean Callanan m_needs_object_ptr = true;
2114dbb271fSSean Callanan
2124dbb271fSSean Callanan if (!method_decl->isInstanceMethod())
2134dbb271fSSean Callanan m_in_static_method = true;
2144dbb271fSSean Callanan }
215b9c1b51eSKate Stone } else if (clang::FunctionDecl *function_decl =
2166e3b0cc2SRaphael Isemann TypeSystemClang::DeclContextGetAsFunctionDecl(decl_context)) {
217b9c1b51eSKate Stone // We might also have a function that said in the debug information that it
21805097246SAdrian Prantl // captured an object pointer. The best way to deal with getting to the
21905097246SAdrian Prantl // ivars at present is by pretending that this is a method of a class in
22005097246SAdrian Prantl // whatever runtime the debug info says the object pointer belongs to. Do
22105097246SAdrian Prantl // that here.
2224dbb271fSSean Callanan
223b9c1b51eSKate Stone ClangASTMetadata *metadata =
2246e3b0cc2SRaphael Isemann TypeSystemClang::DeclContextGetMetaData(decl_context, function_decl);
225b9c1b51eSKate Stone if (metadata && metadata->HasObjectPtr()) {
2264dbb271fSSean Callanan lldb::LanguageType language = metadata->GetObjectPtrLanguage();
227b9c1b51eSKate Stone if (language == lldb::eLanguageTypeC_plus_plus) {
228b9c1b51eSKate Stone if (m_enforce_valid_object) {
229b9c1b51eSKate Stone lldb::VariableListSP variable_list_sp(
230b9c1b51eSKate Stone function_block->GetBlockVariableList(true));
2314dbb271fSSean Callanan
232b9c1b51eSKate Stone const char *thisErrorString = "Stopped in a context claiming to "
233b9c1b51eSKate Stone "capture a C++ object pointer, but "
234b9c1b51eSKate Stone "'this' isn't available; pretending we "
235b9c1b51eSKate Stone "are in a generic context";
2364dbb271fSSean Callanan
237b9c1b51eSKate Stone if (!variable_list_sp) {
2384dbb271fSSean Callanan err.SetErrorString(thisErrorString);
2394dbb271fSSean Callanan return;
2404dbb271fSSean Callanan }
2414dbb271fSSean Callanan
242b9c1b51eSKate Stone lldb::VariableSP this_var_sp(
243b9c1b51eSKate Stone variable_list_sp->FindVariable(ConstString("this")));
2444dbb271fSSean Callanan
245b9c1b51eSKate Stone if (!this_var_sp || !this_var_sp->IsInScope(frame) ||
246b9c1b51eSKate Stone !this_var_sp->LocationIsValidForFrame(frame)) {
2474dbb271fSSean Callanan err.SetErrorString(thisErrorString);
2484dbb271fSSean Callanan return;
2494dbb271fSSean Callanan }
2504dbb271fSSean Callanan }
2514dbb271fSSean Callanan
2524dbb271fSSean Callanan m_in_cplusplus_method = true;
2534dbb271fSSean Callanan m_needs_object_ptr = true;
254b9c1b51eSKate Stone } else if (language == lldb::eLanguageTypeObjC) {
255b9c1b51eSKate Stone if (m_enforce_valid_object) {
256b9c1b51eSKate Stone lldb::VariableListSP variable_list_sp(
257b9c1b51eSKate Stone function_block->GetBlockVariableList(true));
2584dbb271fSSean Callanan
259b9c1b51eSKate Stone const char *selfErrorString =
260b9c1b51eSKate Stone "Stopped in a context claiming to capture an Objective-C object "
261b9c1b51eSKate Stone "pointer, but 'self' isn't available; pretending we are in a "
262b9c1b51eSKate Stone "generic context";
2634dbb271fSSean Callanan
264b9c1b51eSKate Stone if (!variable_list_sp) {
2654dbb271fSSean Callanan err.SetErrorString(selfErrorString);
2664dbb271fSSean Callanan return;
2674dbb271fSSean Callanan }
2684dbb271fSSean Callanan
269b9c1b51eSKate Stone lldb::VariableSP self_variable_sp =
270b9c1b51eSKate Stone variable_list_sp->FindVariable(ConstString("self"));
2714dbb271fSSean Callanan
272b9c1b51eSKate Stone if (!self_variable_sp || !self_variable_sp->IsInScope(frame) ||
273b9c1b51eSKate Stone !self_variable_sp->LocationIsValidForFrame(frame)) {
2744dbb271fSSean Callanan err.SetErrorString(selfErrorString);
2754dbb271fSSean Callanan return;
2764dbb271fSSean Callanan }
2774dbb271fSSean Callanan
2784dbb271fSSean Callanan Type *self_type = self_variable_sp->GetType();
2794dbb271fSSean Callanan
280b9c1b51eSKate Stone if (!self_type) {
2814dbb271fSSean Callanan err.SetErrorString(selfErrorString);
2824dbb271fSSean Callanan return;
2834dbb271fSSean Callanan }
2844dbb271fSSean Callanan
2854dbb271fSSean Callanan CompilerType self_clang_type = self_type->GetForwardCompilerType();
2864dbb271fSSean Callanan
287b9c1b51eSKate Stone if (!self_clang_type) {
2884dbb271fSSean Callanan err.SetErrorString(selfErrorString);
2894dbb271fSSean Callanan return;
2904dbb271fSSean Callanan }
2914dbb271fSSean Callanan
2926e3b0cc2SRaphael Isemann if (TypeSystemClang::IsObjCClassType(self_clang_type)) {
2934dbb271fSSean Callanan return;
2946e3b0cc2SRaphael Isemann } else if (TypeSystemClang::IsObjCObjectPointerType(
295b9c1b51eSKate Stone self_clang_type)) {
2964dbb271fSSean Callanan m_in_objectivec_method = true;
2974dbb271fSSean Callanan m_needs_object_ptr = true;
298b9c1b51eSKate Stone } else {
2994dbb271fSSean Callanan err.SetErrorString(selfErrorString);
3004dbb271fSSean Callanan return;
3014dbb271fSSean Callanan }
302b9c1b51eSKate Stone } else {
3034dbb271fSSean Callanan m_in_objectivec_method = true;
3044dbb271fSSean Callanan m_needs_object_ptr = true;
3054dbb271fSSean Callanan }
3064dbb271fSSean Callanan }
3074dbb271fSSean Callanan }
3084dbb271fSSean Callanan }
3094dbb271fSSean Callanan }
3104dbb271fSSean Callanan
31105097246SAdrian Prantl // This is a really nasty hack, meant to fix Objective-C expressions of the
31205097246SAdrian Prantl // form (int)[myArray count]. Right now, because the type information for
31305097246SAdrian Prantl // count is not available, [myArray count] returns id, which can't be directly
31405097246SAdrian Prantl // cast to int without causing a clang error.
ApplyObjcCastHack(std::string & expr)315b9c1b51eSKate Stone static void ApplyObjcCastHack(std::string &expr) {
3163ee98a14SRaphael Isemann const std::string from = "(int)[";
3173ee98a14SRaphael Isemann const std::string to = "(int)(long long)[";
3184dbb271fSSean Callanan
3193ee98a14SRaphael Isemann size_t offset;
3204dbb271fSSean Callanan
3213ee98a14SRaphael Isemann while ((offset = expr.find(from)) != expr.npos)
3223ee98a14SRaphael Isemann expr.replace(offset, from.size(), to);
3234dbb271fSSean Callanan }
3244dbb271fSSean Callanan
SetupPersistentState(DiagnosticManager & diagnostic_manager,ExecutionContext & exe_ctx)325ba800e7dSRaphael Isemann bool ClangUserExpression::SetupPersistentState(DiagnosticManager &diagnostic_manager,
326ba800e7dSRaphael Isemann ExecutionContext &exe_ctx) {
327b9c1b51eSKate Stone if (Target *target = exe_ctx.GetTargetPtr()) {
328b9c1b51eSKate Stone if (PersistentExpressionState *persistent_state =
329b9c1b51eSKate Stone target->GetPersistentExpressionStateForLanguage(
330b9c1b51eSKate Stone lldb::eLanguageTypeC)) {
3311442efeaSRaphael Isemann m_clang_state = llvm::cast<ClangPersistentVariables>(persistent_state);
3329fda9d21SSean Callanan m_result_delegate.RegisterPersistentState(persistent_state);
333b9c1b51eSKate Stone } else {
334e2411fabSZachary Turner diagnostic_manager.PutString(
335b9c1b51eSKate Stone eDiagnosticSeverityError,
336b9c1b51eSKate Stone "couldn't start parsing (no persistent data)");
3379fda9d21SSean Callanan return false;
3389fda9d21SSean Callanan }
339b9c1b51eSKate Stone } else {
340e2411fabSZachary Turner diagnostic_manager.PutString(eDiagnosticSeverityError,
341b9c1b51eSKate Stone "error: couldn't start parsing (no target)");
3429fda9d21SSean Callanan return false;
3439fda9d21SSean Callanan }
344ba800e7dSRaphael Isemann return true;
3454dbb271fSSean Callanan }
3464dbb271fSSean Callanan
SetupDeclVendor(ExecutionContext & exe_ctx,Target * target,DiagnosticManager & diagnostic_manager)347d48ef7caSRaphael Isemann static void SetupDeclVendor(ExecutionContext &exe_ctx, Target *target,
348d48ef7caSRaphael Isemann DiagnosticManager &diagnostic_manager) {
3495f7a5e3bSRaphael Isemann if (!target->GetEnableAutoImportClangModules())
3505f7a5e3bSRaphael Isemann return;
3515f7a5e3bSRaphael Isemann
352e9331a56SAdrian Prantl auto *persistent_state = llvm::cast<ClangPersistentVariables>(
353e9331a56SAdrian Prantl target->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC));
354e9331a56SAdrian Prantl if (!persistent_state)
355e9331a56SAdrian Prantl return;
3564dbb271fSSean Callanan
3574c0b0de9SAlex Langford std::shared_ptr<ClangModulesDeclVendor> decl_vendor =
3584c0b0de9SAlex Langford persistent_state->GetClangModulesDeclVendor();
3594c0b0de9SAlex Langford if (!decl_vendor)
3604c0b0de9SAlex Langford return;
3614c0b0de9SAlex Langford
3625f7a5e3bSRaphael Isemann StackFrame *frame = exe_ctx.GetFramePtr();
3635f7a5e3bSRaphael Isemann if (!frame)
3645f7a5e3bSRaphael Isemann return;
3654dbb271fSSean Callanan
3665f7a5e3bSRaphael Isemann Block *block = frame->GetFrameBlock();
3675f7a5e3bSRaphael Isemann if (!block)
3685f7a5e3bSRaphael Isemann return;
3694dbb271fSSean Callanan SymbolContext sc;
3704dbb271fSSean Callanan
3714dbb271fSSean Callanan block->CalculateSymbolContext(&sc);
3724dbb271fSSean Callanan
3735f7a5e3bSRaphael Isemann if (!sc.comp_unit)
3745f7a5e3bSRaphael Isemann return;
3754dbb271fSSean Callanan StreamString error_stream;
3764dbb271fSSean Callanan
3775f7a5e3bSRaphael Isemann ClangModulesDeclVendor::ModuleVector modules_for_macros =
3785f7a5e3bSRaphael Isemann persistent_state->GetHandLoadedClangModules();
379d48ef7caSRaphael Isemann if (decl_vendor->AddModulesForCompileUnit(*sc.comp_unit, modules_for_macros,
380d48ef7caSRaphael Isemann error_stream))
381d48ef7caSRaphael Isemann return;
382d48ef7caSRaphael Isemann
383d48ef7caSRaphael Isemann // Failed to load some modules, so emit the error stream as a diagnostic.
384d48ef7caSRaphael Isemann if (!error_stream.Empty()) {
385d48ef7caSRaphael Isemann // The error stream already contains several Clang diagnostics that might
386d48ef7caSRaphael Isemann // be either errors or warnings, so just print them all as one remark
387d48ef7caSRaphael Isemann // diagnostic to prevent that the message starts with "error: error:".
388d48ef7caSRaphael Isemann diagnostic_manager.PutString(eDiagnosticSeverityRemark,
389d48ef7caSRaphael Isemann error_stream.GetString());
390d48ef7caSRaphael Isemann return;
391d48ef7caSRaphael Isemann }
392d48ef7caSRaphael Isemann
393d48ef7caSRaphael Isemann diagnostic_manager.PutString(eDiagnosticSeverityError,
394d48ef7caSRaphael Isemann "Unknown error while loading modules needed for "
395d48ef7caSRaphael Isemann "current compilation unit.");
396ba800e7dSRaphael Isemann }
3974dbb271fSSean Callanan
GetWrapKind() const3982b37c5b5SRaphael Isemann ClangExpressionSourceCode::WrapKind ClangUserExpression::GetWrapKind() const {
3992b37c5b5SRaphael Isemann assert(m_options.GetExecutionPolicy() != eExecutionPolicyTopLevel &&
4002b37c5b5SRaphael Isemann "Top level expressions aren't wrapped.");
4012b37c5b5SRaphael Isemann using Kind = ClangExpressionSourceCode::WrapKind;
4024125b462SRaphael Isemann if (m_in_cplusplus_method)
4032b37c5b5SRaphael Isemann return Kind::CppMemberFunction;
4044125b462SRaphael Isemann else if (m_in_objectivec_method) {
4052b37c5b5SRaphael Isemann if (m_in_static_method)
4062b37c5b5SRaphael Isemann return Kind::ObjCStaticMethod;
4072b37c5b5SRaphael Isemann return Kind::ObjCInstanceMethod;
4082b37c5b5SRaphael Isemann }
4092b37c5b5SRaphael Isemann // Not in any kind of 'special' function, so just wrap it in a normal C
4102b37c5b5SRaphael Isemann // function.
4112b37c5b5SRaphael Isemann return Kind::Function;
4125eb87cf3SRaphael Isemann }
4135eb87cf3SRaphael Isemann
CreateSourceCode(DiagnosticManager & diagnostic_manager,ExecutionContext & exe_ctx,std::vector<std::string> modules_to_import,bool for_completion)4145eb87cf3SRaphael Isemann void ClangUserExpression::CreateSourceCode(
4156c0bbfc0SRaphael Isemann DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx,
41671569d0dSRaphael Isemann std::vector<std::string> modules_to_import, bool for_completion) {
417ba800e7dSRaphael Isemann
418ba800e7dSRaphael Isemann std::string prefix = m_expr_prefix;
419e5ee6f04SJim Ingham
420b9c1b51eSKate Stone if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel) {
42100294b34SSean Callanan m_transformed_text = m_expr_text;
422b9c1b51eSKate Stone } else {
4231442efeaSRaphael Isemann m_source_code.reset(ClangExpressionSourceCode::CreateWrapped(
4242b37c5b5SRaphael Isemann m_filename, prefix, m_expr_text, GetWrapKind()));
4254dbb271fSSean Callanan
4262b37c5b5SRaphael Isemann if (!m_source_code->GetText(m_transformed_text, exe_ctx, !m_ctx_obj,
42771569d0dSRaphael Isemann for_completion, modules_to_import)) {
428e2411fabSZachary Turner diagnostic_manager.PutString(eDiagnosticSeverityError,
429b9c1b51eSKate Stone "couldn't construct expression body");
430dababf70SRaphael Isemann return;
4314dbb271fSSean Callanan }
43274829734SRaphael Isemann
43374829734SRaphael Isemann // Find and store the start position of the original code inside the
43474829734SRaphael Isemann // transformed code. We need this later for the code completion.
43574829734SRaphael Isemann std::size_t original_start;
43674829734SRaphael Isemann std::size_t original_end;
4371442efeaSRaphael Isemann bool found_bounds = m_source_code->GetOriginalBodyBounds(
4382b37c5b5SRaphael Isemann m_transformed_text, original_start, original_end);
439d59c8d30SRaphael Isemann if (found_bounds)
44074829734SRaphael Isemann m_user_expression_start_pos = original_start;
44174829734SRaphael Isemann }
44200294b34SSean Callanan }
443ba800e7dSRaphael Isemann
SupportsCxxModuleImport(lldb::LanguageType language)4446c0bbfc0SRaphael Isemann static bool SupportsCxxModuleImport(lldb::LanguageType language) {
4456c0bbfc0SRaphael Isemann switch (language) {
4466c0bbfc0SRaphael Isemann case lldb::eLanguageTypeC_plus_plus:
4476c0bbfc0SRaphael Isemann case lldb::eLanguageTypeC_plus_plus_03:
4486c0bbfc0SRaphael Isemann case lldb::eLanguageTypeC_plus_plus_11:
4496c0bbfc0SRaphael Isemann case lldb::eLanguageTypeC_plus_plus_14:
4506c0bbfc0SRaphael Isemann case lldb::eLanguageTypeObjC_plus_plus:
4516c0bbfc0SRaphael Isemann return true;
4526c0bbfc0SRaphael Isemann default:
4536c0bbfc0SRaphael Isemann return false;
4546c0bbfc0SRaphael Isemann }
4556c0bbfc0SRaphael Isemann }
4566c0bbfc0SRaphael Isemann
4579379d19fSRaphael Isemann /// Utility method that puts a message into the expression log and
4589379d19fSRaphael Isemann /// returns an invalid module configuration.
LogConfigError(const std::string & msg)4599379d19fSRaphael Isemann static CppModuleConfiguration LogConfigError(const std::string &msg) {
460a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Expressions);
4619379d19fSRaphael Isemann LLDB_LOG(log, "[C++ module config] {0}", msg);
4629379d19fSRaphael Isemann return CppModuleConfiguration();
4639379d19fSRaphael Isemann }
4646c0bbfc0SRaphael Isemann
GetModuleConfig(lldb::LanguageType language,ExecutionContext & exe_ctx)4659379d19fSRaphael Isemann CppModuleConfiguration GetModuleConfig(lldb::LanguageType language,
4669379d19fSRaphael Isemann ExecutionContext &exe_ctx) {
467a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Expressions);
468ccd54a13SRaphael Isemann
4699379d19fSRaphael Isemann // Don't do anything if this is not a C++ module configuration.
4709379d19fSRaphael Isemann if (!SupportsCxxModuleImport(language))
4719379d19fSRaphael Isemann return LogConfigError("Language doesn't support C++ modules");
4726c0bbfc0SRaphael Isemann
4736c0bbfc0SRaphael Isemann Target *target = exe_ctx.GetTargetPtr();
4749379d19fSRaphael Isemann if (!target)
4759379d19fSRaphael Isemann return LogConfigError("No target");
4769379d19fSRaphael Isemann
4776c0bbfc0SRaphael Isemann StackFrame *frame = exe_ctx.GetFramePtr();
4786c0bbfc0SRaphael Isemann if (!frame)
4799379d19fSRaphael Isemann return LogConfigError("No frame");
4806c0bbfc0SRaphael Isemann
4816c0bbfc0SRaphael Isemann Block *block = frame->GetFrameBlock();
4826c0bbfc0SRaphael Isemann if (!block)
4839379d19fSRaphael Isemann return LogConfigError("No block");
4846c0bbfc0SRaphael Isemann
4856c0bbfc0SRaphael Isemann SymbolContext sc;
4866c0bbfc0SRaphael Isemann block->CalculateSymbolContext(&sc);
4876c0bbfc0SRaphael Isemann if (!sc.comp_unit)
4889379d19fSRaphael Isemann return LogConfigError("Couldn't calculate symbol context");
4896c0bbfc0SRaphael Isemann
4909379d19fSRaphael Isemann // Build a list of files we need to analyze to build the configuration.
4919379d19fSRaphael Isemann FileSpecList files;
4929379d19fSRaphael Isemann for (const FileSpec &f : sc.comp_unit->GetSupportFiles())
4939379d19fSRaphael Isemann files.AppendIfUnique(f);
4949379d19fSRaphael Isemann // We also need to look at external modules in the case of -gmodules as they
4959379d19fSRaphael Isemann // contain the support files for libc++ and the C library.
4960e45e60cSAdrian Prantl llvm::DenseSet<SymbolFile *> visited_symbol_files;
4970e45e60cSAdrian Prantl sc.comp_unit->ForEachExternalModule(
4980e45e60cSAdrian Prantl visited_symbol_files, [&files](Module &module) {
4990e45e60cSAdrian Prantl for (std::size_t i = 0; i < module.GetNumCompileUnits(); ++i) {
5009379d19fSRaphael Isemann const FileSpecList &support_files =
5010e45e60cSAdrian Prantl module.GetCompileUnitAtIndex(i)->GetSupportFiles();
5029379d19fSRaphael Isemann for (const FileSpec &f : support_files) {
5039379d19fSRaphael Isemann files.AppendIfUnique(f);
5046c0bbfc0SRaphael Isemann }
5056c0bbfc0SRaphael Isemann }
5060e45e60cSAdrian Prantl return false;
5079379d19fSRaphael Isemann });
508ccd54a13SRaphael Isemann
509ccd54a13SRaphael Isemann LLDB_LOG(log, "[C++ module config] Found {0} support files to analyze",
510ccd54a13SRaphael Isemann files.GetSize());
511ccd54a13SRaphael Isemann if (log && log->GetVerbose()) {
512ccd54a13SRaphael Isemann for (const FileSpec &f : files)
513ccd54a13SRaphael Isemann LLDB_LOGV(log, "[C++ module config] Analyzing support file: {0}",
514ccd54a13SRaphael Isemann f.GetPath());
515ccd54a13SRaphael Isemann }
516ccd54a13SRaphael Isemann
5179379d19fSRaphael Isemann // Try to create a configuration from the files. If there is no valid
5189379d19fSRaphael Isemann // configuration possible with the files, this just returns an invalid
5199379d19fSRaphael Isemann // configuration.
5201aab5e65SPavel Kosov return CppModuleConfiguration(files, target->GetArchitecture().GetTriple());
5216c0bbfc0SRaphael Isemann }
5226c0bbfc0SRaphael Isemann
PrepareForParsing(DiagnosticManager & diagnostic_manager,ExecutionContext & exe_ctx,bool for_completion)523ba800e7dSRaphael Isemann bool ClangUserExpression::PrepareForParsing(
52471569d0dSRaphael Isemann DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx,
52571569d0dSRaphael Isemann bool for_completion) {
526ba800e7dSRaphael Isemann InstallContext(exe_ctx);
527ba800e7dSRaphael Isemann
528ba800e7dSRaphael Isemann if (!SetupPersistentState(diagnostic_manager, exe_ctx))
529ba800e7dSRaphael Isemann return false;
530ba800e7dSRaphael Isemann
531ba800e7dSRaphael Isemann Status err;
532ba800e7dSRaphael Isemann ScanContext(exe_ctx, err);
533ba800e7dSRaphael Isemann
534ba800e7dSRaphael Isemann if (!err.Success()) {
535ba800e7dSRaphael Isemann diagnostic_manager.PutString(eDiagnosticSeverityWarning, err.AsCString());
536ba800e7dSRaphael Isemann }
537ba800e7dSRaphael Isemann
538ba800e7dSRaphael Isemann ////////////////////////////////////
539ba800e7dSRaphael Isemann // Generate the expression
540ba800e7dSRaphael Isemann //
541ba800e7dSRaphael Isemann
542ba800e7dSRaphael Isemann ApplyObjcCastHack(m_expr_text);
543ba800e7dSRaphael Isemann
544d48ef7caSRaphael Isemann SetupDeclVendor(exe_ctx, m_target, diagnostic_manager);
545dababf70SRaphael Isemann
54695860828SRaphael Isemann m_filename = m_clang_state->GetNextExprFileName();
54795860828SRaphael Isemann
54895860828SRaphael Isemann if (m_target->GetImportStdModule() == eImportStdModuleTrue)
54995860828SRaphael Isemann SetupCppModuleImports(exe_ctx);
55095860828SRaphael Isemann
55195860828SRaphael Isemann CreateSourceCode(diagnostic_manager, exe_ctx, m_imported_cpp_modules,
55295860828SRaphael Isemann for_completion);
55395860828SRaphael Isemann return true;
55495860828SRaphael Isemann }
55595860828SRaphael Isemann
TryParse(DiagnosticManager & diagnostic_manager,ExecutionContextScope * exe_scope,ExecutionContext & exe_ctx,lldb_private::ExecutionPolicy execution_policy,bool keep_result_in_memory,bool generate_debug_info)55695860828SRaphael Isemann bool ClangUserExpression::TryParse(
55795860828SRaphael Isemann DiagnosticManager &diagnostic_manager, ExecutionContextScope *exe_scope,
55895860828SRaphael Isemann ExecutionContext &exe_ctx, lldb_private::ExecutionPolicy execution_policy,
55995860828SRaphael Isemann bool keep_result_in_memory, bool generate_debug_info) {
56095860828SRaphael Isemann m_materializer_up = std::make_unique<Materializer>();
56195860828SRaphael Isemann
56295860828SRaphael Isemann ResetDeclMap(exe_ctx, m_result_delegate, keep_result_in_memory);
56395860828SRaphael Isemann
56495860828SRaphael Isemann auto on_exit = llvm::make_scope_exit([this]() { ResetDeclMap(); });
56595860828SRaphael Isemann
56695860828SRaphael Isemann if (!DeclMap()->WillParse(exe_ctx, GetMaterializer())) {
56795860828SRaphael Isemann diagnostic_manager.PutString(
56895860828SRaphael Isemann eDiagnosticSeverityError,
56995860828SRaphael Isemann "current process state is unsuitable for expression parsing");
57095860828SRaphael Isemann return false;
57195860828SRaphael Isemann }
57295860828SRaphael Isemann
57395860828SRaphael Isemann if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel) {
57495860828SRaphael Isemann DeclMap()->SetLookupsEnabled(true);
57595860828SRaphael Isemann }
57695860828SRaphael Isemann
57795860828SRaphael Isemann m_parser = std::make_unique<ClangExpressionParser>(
57895860828SRaphael Isemann exe_scope, *this, generate_debug_info, m_include_directories, m_filename);
57995860828SRaphael Isemann
58095860828SRaphael Isemann unsigned num_errors = m_parser->Parse(diagnostic_manager);
58195860828SRaphael Isemann
58295860828SRaphael Isemann // Check here for FixItHints. If there are any try to apply the fixits and
58395860828SRaphael Isemann // set the fixed text in m_fixed_text before returning an error.
58495860828SRaphael Isemann if (num_errors) {
58595860828SRaphael Isemann if (diagnostic_manager.HasFixIts()) {
58695860828SRaphael Isemann if (m_parser->RewriteExpression(diagnostic_manager)) {
58795860828SRaphael Isemann size_t fixed_start;
58895860828SRaphael Isemann size_t fixed_end;
58995860828SRaphael Isemann m_fixed_text = diagnostic_manager.GetFixedExpression();
59095860828SRaphael Isemann // Retrieve the original expression in case we don't have a top level
59195860828SRaphael Isemann // expression (which has no surrounding source code).
59295860828SRaphael Isemann if (m_source_code && m_source_code->GetOriginalBodyBounds(
59395860828SRaphael Isemann m_fixed_text, fixed_start, fixed_end))
59495860828SRaphael Isemann m_fixed_text =
59595860828SRaphael Isemann m_fixed_text.substr(fixed_start, fixed_end - fixed_start);
59695860828SRaphael Isemann }
59795860828SRaphael Isemann }
59895860828SRaphael Isemann return false;
59995860828SRaphael Isemann }
60095860828SRaphael Isemann
60195860828SRaphael Isemann //////////////////////////////////////////////////////////////////////////////
60295860828SRaphael Isemann // Prepare the output of the parser for execution, evaluating it statically
60395860828SRaphael Isemann // if possible
60495860828SRaphael Isemann //
60595860828SRaphael Isemann
60695860828SRaphael Isemann {
60795860828SRaphael Isemann Status jit_error = m_parser->PrepareForExecution(
60895860828SRaphael Isemann m_jit_start_addr, m_jit_end_addr, m_execution_unit_sp, exe_ctx,
60995860828SRaphael Isemann m_can_interpret, execution_policy);
61095860828SRaphael Isemann
61195860828SRaphael Isemann if (!jit_error.Success()) {
61295860828SRaphael Isemann const char *error_cstr = jit_error.AsCString();
61395860828SRaphael Isemann if (error_cstr && error_cstr[0])
61495860828SRaphael Isemann diagnostic_manager.PutString(eDiagnosticSeverityError, error_cstr);
61595860828SRaphael Isemann else
61695860828SRaphael Isemann diagnostic_manager.PutString(eDiagnosticSeverityError,
61795860828SRaphael Isemann "expression can't be interpreted or run");
61895860828SRaphael Isemann return false;
61995860828SRaphael Isemann }
62095860828SRaphael Isemann }
62195860828SRaphael Isemann return true;
62295860828SRaphael Isemann }
62395860828SRaphael Isemann
SetupCppModuleImports(ExecutionContext & exe_ctx)62495860828SRaphael Isemann void ClangUserExpression::SetupCppModuleImports(ExecutionContext &exe_ctx) {
625a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Expressions);
62695860828SRaphael Isemann
6279379d19fSRaphael Isemann CppModuleConfiguration module_config = GetModuleConfig(m_language, exe_ctx);
62895860828SRaphael Isemann m_imported_cpp_modules = module_config.GetImportedModules();
6299379d19fSRaphael Isemann m_include_directories = module_config.GetIncludeDirs();
6306c0bbfc0SRaphael Isemann
6316c0bbfc0SRaphael Isemann LLDB_LOG(log, "List of imported modules in expression: {0}",
63295860828SRaphael Isemann llvm::make_range(m_imported_cpp_modules.begin(),
63395860828SRaphael Isemann m_imported_cpp_modules.end()));
6349379d19fSRaphael Isemann LLDB_LOG(log, "List of include directories gathered for modules: {0}",
6359379d19fSRaphael Isemann llvm::make_range(m_include_directories.begin(),
6369379d19fSRaphael Isemann m_include_directories.end()));
63795860828SRaphael Isemann }
6386c0bbfc0SRaphael Isemann
shouldRetryWithCppModule(Target & target,ExecutionPolicy exe_policy)63995860828SRaphael Isemann static bool shouldRetryWithCppModule(Target &target, ExecutionPolicy exe_policy) {
64095860828SRaphael Isemann // Top-level expression don't yet support importing C++ modules.
64195860828SRaphael Isemann if (exe_policy == ExecutionPolicy::eExecutionPolicyTopLevel)
64295860828SRaphael Isemann return false;
64395860828SRaphael Isemann return target.GetImportStdModule() == eImportStdModuleFallback;
644ba800e7dSRaphael Isemann }
645ba800e7dSRaphael Isemann
Parse(DiagnosticManager & diagnostic_manager,ExecutionContext & exe_ctx,lldb_private::ExecutionPolicy execution_policy,bool keep_result_in_memory,bool generate_debug_info)646ba800e7dSRaphael Isemann bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager,
647ba800e7dSRaphael Isemann ExecutionContext &exe_ctx,
648ba800e7dSRaphael Isemann lldb_private::ExecutionPolicy execution_policy,
649ba800e7dSRaphael Isemann bool keep_result_in_memory,
650ba800e7dSRaphael Isemann bool generate_debug_info) {
651a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Expressions);
652ba800e7dSRaphael Isemann
65371569d0dSRaphael Isemann if (!PrepareForParsing(diagnostic_manager, exe_ctx, /*for_completion*/ false))
654ba800e7dSRaphael Isemann return false;
655ba800e7dSRaphael Isemann
65663e5fb76SJonas Devlieghere LLDB_LOGF(log, "Parsing the following code:\n%s", m_transformed_text.c_str());
6574dbb271fSSean Callanan
6584dbb271fSSean Callanan ////////////////////////////////////
6594dbb271fSSean Callanan // Set up the target and compiler
6604dbb271fSSean Callanan //
6614dbb271fSSean Callanan
6624dbb271fSSean Callanan Target *target = exe_ctx.GetTargetPtr();
6634dbb271fSSean Callanan
664b9c1b51eSKate Stone if (!target) {
665e2411fabSZachary Turner diagnostic_manager.PutString(eDiagnosticSeverityError, "invalid target");
6664dbb271fSSean Callanan return false;
6674dbb271fSSean Callanan }
6684dbb271fSSean Callanan
6694dbb271fSSean Callanan //////////////////////////
6704dbb271fSSean Callanan // Parse the expression
6714dbb271fSSean Callanan //
6724dbb271fSSean Callanan
6734dbb271fSSean Callanan Process *process = exe_ctx.GetProcessPtr();
6744dbb271fSSean Callanan ExecutionContextScope *exe_scope = process;
6754dbb271fSSean Callanan
6764dbb271fSSean Callanan if (!exe_scope)
6774dbb271fSSean Callanan exe_scope = exe_ctx.GetTargetPtr();
6784dbb271fSSean Callanan
67995860828SRaphael Isemann bool parse_success = TryParse(diagnostic_manager, exe_scope, exe_ctx,
68095860828SRaphael Isemann execution_policy, keep_result_in_memory,
68195860828SRaphael Isemann generate_debug_info);
68295860828SRaphael Isemann // If the expression failed to parse, check if retrying parsing with a loaded
68395860828SRaphael Isemann // C++ module is possible.
68495860828SRaphael Isemann if (!parse_success && shouldRetryWithCppModule(*target, execution_policy)) {
68595860828SRaphael Isemann // Load the loaded C++ modules.
68695860828SRaphael Isemann SetupCppModuleImports(exe_ctx);
68795860828SRaphael Isemann // If we did load any modules, then retry parsing.
68895860828SRaphael Isemann if (!m_imported_cpp_modules.empty()) {
6896fcb8577SRaphael Isemann // Create a dedicated diagnostic manager for the second parse attempt.
6906fcb8577SRaphael Isemann // These diagnostics are only returned to the caller if using the fallback
6916fcb8577SRaphael Isemann // actually succeeded in getting the expression to parse. This prevents
6926fcb8577SRaphael Isemann // that module-specific issues regress diagnostic quality with the
6936fcb8577SRaphael Isemann // fallback mode.
6946fcb8577SRaphael Isemann DiagnosticManager retry_manager;
69595860828SRaphael Isemann // The module imports are injected into the source code wrapper,
69695860828SRaphael Isemann // so recreate those.
6976fcb8577SRaphael Isemann CreateSourceCode(retry_manager, exe_ctx, m_imported_cpp_modules,
69895860828SRaphael Isemann /*for_completion*/ false);
6996fcb8577SRaphael Isemann parse_success = TryParse(retry_manager, exe_scope, exe_ctx,
70095860828SRaphael Isemann execution_policy, keep_result_in_memory,
70195860828SRaphael Isemann generate_debug_info);
7026fcb8577SRaphael Isemann // Return the parse diagnostics if we were successful.
7036fcb8577SRaphael Isemann if (parse_success)
7046fcb8577SRaphael Isemann diagnostic_manager = std::move(retry_manager);
705e5ee6f04SJim Ingham }
706e5ee6f04SJim Ingham }
70795860828SRaphael Isemann if (!parse_success)
7084dbb271fSSean Callanan return false;
70900294b34SSean Callanan
710b9c1b51eSKate Stone if (exe_ctx.GetProcessPtr() && execution_policy == eExecutionPolicyTopLevel) {
71197206d57SZachary Turner Status static_init_error =
71295860828SRaphael Isemann m_parser->RunStaticInitializers(m_execution_unit_sp, exe_ctx);
71300294b34SSean Callanan
714b9c1b51eSKate Stone if (!static_init_error.Success()) {
71500294b34SSean Callanan const char *error_cstr = static_init_error.AsCString();
71600294b34SSean Callanan if (error_cstr && error_cstr[0])
717b9c1b51eSKate Stone diagnostic_manager.Printf(eDiagnosticSeverityError,
7180082f1e0SRaphael Isemann "%s\n",
71900294b34SSean Callanan error_cstr);
72000294b34SSean Callanan else
721e2411fabSZachary Turner diagnostic_manager.PutString(eDiagnosticSeverityError,
722b9c1b51eSKate Stone "couldn't run static initializers\n");
72300294b34SSean Callanan return false;
72400294b34SSean Callanan }
72500294b34SSean Callanan }
72600294b34SSean Callanan
727b9c1b51eSKate Stone if (m_execution_unit_sp) {
72800294b34SSean Callanan bool register_execution_unit = false;
72900294b34SSean Callanan
730b9c1b51eSKate Stone if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel) {
73100294b34SSean Callanan register_execution_unit = true;
73200294b34SSean Callanan }
73300294b34SSean Callanan
73405097246SAdrian Prantl // If there is more than one external function in the execution unit, it
73505097246SAdrian Prantl // needs to keep living even if it's not top level, because the result
73605097246SAdrian Prantl // could refer to that function.
73747cca78eSSean Callanan
738b9c1b51eSKate Stone if (m_execution_unit_sp->GetJittedFunctions().size() > 1) {
73947cca78eSSean Callanan register_execution_unit = true;
74047cca78eSSean Callanan }
74147cca78eSSean Callanan
742e9331a56SAdrian Prantl if (register_execution_unit) {
743e9331a56SAdrian Prantl if (auto *persistent_state =
744e9331a56SAdrian Prantl exe_ctx.GetTargetPtr()->GetPersistentExpressionStateForLanguage(
745e9331a56SAdrian Prantl m_language))
746e9331a56SAdrian Prantl persistent_state->RegisterExecutionUnit(m_execution_unit_sp);
747e9331a56SAdrian Prantl }
74800294b34SSean Callanan }
7494dbb271fSSean Callanan
750b9c1b51eSKate Stone if (generate_debug_info) {
7514dbb271fSSean Callanan lldb::ModuleSP jit_module_sp(m_execution_unit_sp->GetJITModule());
7524dbb271fSSean Callanan
753b9c1b51eSKate Stone if (jit_module_sp) {
7544dbb271fSSean Callanan ConstString const_func_name(FunctionName());
7554dbb271fSSean Callanan FileSpec jit_file;
756*1b4b12a3SNico Weber jit_file.GetFilename() = const_func_name;
7574dbb271fSSean Callanan jit_module_sp->SetFileSpecAndObjectName(jit_file, ConstString());
7584dbb271fSSean Callanan m_jit_module_wp = jit_module_sp;
7594dbb271fSSean Callanan target->GetImages().Append(jit_module_sp);
7604dbb271fSSean Callanan }
7614dbb271fSSean Callanan }
7624dbb271fSSean Callanan
7634dbb271fSSean Callanan if (process && m_jit_start_addr != LLDB_INVALID_ADDRESS)
7644dbb271fSSean Callanan m_jit_process_wp = lldb::ProcessWP(process->shared_from_this());
7654dbb271fSSean Callanan return true;
7664dbb271fSSean Callanan }
7674dbb271fSSean Callanan
76874829734SRaphael Isemann /// Converts an absolute position inside a given code string into
76974829734SRaphael Isemann /// a column/line pair.
77074829734SRaphael Isemann ///
771f05b42e9SAdrian Prantl /// \param[in] abs_pos
77274829734SRaphael Isemann /// A absolute position in the code string that we want to convert
77374829734SRaphael Isemann /// to a column/line pair.
77474829734SRaphael Isemann ///
775f05b42e9SAdrian Prantl /// \param[in] code
77674829734SRaphael Isemann /// A multi-line string usually representing source code.
77774829734SRaphael Isemann ///
778f05b42e9SAdrian Prantl /// \param[out] line
77974829734SRaphael Isemann /// The line in the code that contains the given absolute position.
78074829734SRaphael Isemann /// The first line in the string is indexed as 1.
78174829734SRaphael Isemann ///
782f05b42e9SAdrian Prantl /// \param[out] column
78374829734SRaphael Isemann /// The column in the line that contains the absolute position.
78474829734SRaphael Isemann /// The first character in a line is indexed as 0.
AbsPosToLineColumnPos(size_t abs_pos,llvm::StringRef code,unsigned & line,unsigned & column)785bfc5ef6cSRaphael Isemann static void AbsPosToLineColumnPos(size_t abs_pos, llvm::StringRef code,
78674829734SRaphael Isemann unsigned &line, unsigned &column) {
78774829734SRaphael Isemann // Reset to code position to beginning of the file.
78874829734SRaphael Isemann line = 0;
78974829734SRaphael Isemann column = 0;
79074829734SRaphael Isemann
79174829734SRaphael Isemann assert(abs_pos <= code.size() && "Absolute position outside code string?");
79274829734SRaphael Isemann
79374829734SRaphael Isemann // We have to walk up to the position and count lines/columns.
79474829734SRaphael Isemann for (std::size_t i = 0; i < abs_pos; ++i) {
79574829734SRaphael Isemann // If we hit a line break, we go back to column 0 and enter a new line.
79674829734SRaphael Isemann // We only handle \n because that's what we internally use to make new
79774829734SRaphael Isemann // lines for our temporary code strings.
79874829734SRaphael Isemann if (code[i] == '\n') {
79974829734SRaphael Isemann ++line;
80074829734SRaphael Isemann column = 0;
80174829734SRaphael Isemann continue;
80274829734SRaphael Isemann }
80374829734SRaphael Isemann ++column;
80474829734SRaphael Isemann }
80574829734SRaphael Isemann }
80674829734SRaphael Isemann
Complete(ExecutionContext & exe_ctx,CompletionRequest & request,unsigned complete_pos)80774829734SRaphael Isemann bool ClangUserExpression::Complete(ExecutionContext &exe_ctx,
808c11a780eSRaphael Isemann CompletionRequest &request,
809c11a780eSRaphael Isemann unsigned complete_pos) {
810a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Expressions);
81174829734SRaphael Isemann
81274829734SRaphael Isemann // We don't want any visible feedback when completing an expression. Mostly
81374829734SRaphael Isemann // because the results we get from an incomplete invocation are probably not
81474829734SRaphael Isemann // correct.
81574829734SRaphael Isemann DiagnosticManager diagnostic_manager;
81674829734SRaphael Isemann
81771569d0dSRaphael Isemann if (!PrepareForParsing(diagnostic_manager, exe_ctx, /*for_completion*/ true))
81874829734SRaphael Isemann return false;
81974829734SRaphael Isemann
82063e5fb76SJonas Devlieghere LLDB_LOGF(log, "Parsing the following code:\n%s", m_transformed_text.c_str());
82174829734SRaphael Isemann
82274829734SRaphael Isemann //////////////////////////
82374829734SRaphael Isemann // Parse the expression
82474829734SRaphael Isemann //
82574829734SRaphael Isemann
82606412daeSJonas Devlieghere m_materializer_up = std::make_unique<Materializer>();
82774829734SRaphael Isemann
82874829734SRaphael Isemann ResetDeclMap(exe_ctx, m_result_delegate, /*keep result in memory*/ true);
82974829734SRaphael Isemann
830edebf12aSTatyana Krasnukha auto on_exit = llvm::make_scope_exit([this]() { ResetDeclMap(); });
83174829734SRaphael Isemann
832ae10661aSRaphael Isemann if (!DeclMap()->WillParse(exe_ctx, GetMaterializer())) {
83374829734SRaphael Isemann diagnostic_manager.PutString(
83474829734SRaphael Isemann eDiagnosticSeverityError,
83574829734SRaphael Isemann "current process state is unsuitable for expression parsing");
83674829734SRaphael Isemann
83774829734SRaphael Isemann return false;
83874829734SRaphael Isemann }
83974829734SRaphael Isemann
84074829734SRaphael Isemann if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel) {
84174829734SRaphael Isemann DeclMap()->SetLookupsEnabled(true);
84274829734SRaphael Isemann }
84374829734SRaphael Isemann
84474829734SRaphael Isemann Process *process = exe_ctx.GetProcessPtr();
84574829734SRaphael Isemann ExecutionContextScope *exe_scope = process;
84674829734SRaphael Isemann
84774829734SRaphael Isemann if (!exe_scope)
84874829734SRaphael Isemann exe_scope = exe_ctx.GetTargetPtr();
84974829734SRaphael Isemann
85074829734SRaphael Isemann ClangExpressionParser parser(exe_scope, *this, false);
85174829734SRaphael Isemann
85274829734SRaphael Isemann // We have to find the source code location where the user text is inside
85374829734SRaphael Isemann // the transformed expression code. When creating the transformed text, we
85474829734SRaphael Isemann // already stored the absolute position in the m_transformed_text string. The
85574829734SRaphael Isemann // only thing left to do is to transform it into the line:column format that
85674829734SRaphael Isemann // Clang expects.
85774829734SRaphael Isemann
85874829734SRaphael Isemann // The line and column of the user expression inside the transformed source
85974829734SRaphael Isemann // code.
86074829734SRaphael Isemann unsigned user_expr_line, user_expr_column;
8615413bf1bSKazu Hirata if (m_user_expression_start_pos)
86274829734SRaphael Isemann AbsPosToLineColumnPos(*m_user_expression_start_pos, m_transformed_text,
86374829734SRaphael Isemann user_expr_line, user_expr_column);
86474829734SRaphael Isemann else
86574829734SRaphael Isemann return false;
86674829734SRaphael Isemann
86774829734SRaphael Isemann // The actual column where we have to complete is the start column of the
86874829734SRaphael Isemann // user expression + the offset inside the user code that we were given.
86974829734SRaphael Isemann const unsigned completion_column = user_expr_column + complete_pos;
870c11a780eSRaphael Isemann parser.Complete(request, user_expr_line, completion_column, complete_pos);
87174829734SRaphael Isemann
87274829734SRaphael Isemann return true;
87374829734SRaphael Isemann }
87474829734SRaphael Isemann
GetCppObjectPointer(lldb::StackFrameSP frame_sp,ConstString & object_name,Status & err)8758184b252SMichael Buch lldb::addr_t ClangUserExpression::GetCppObjectPointer(
8768184b252SMichael Buch lldb::StackFrameSP frame_sp, ConstString &object_name, Status &err) {
8778184b252SMichael Buch auto valobj_sp =
8788184b252SMichael Buch GetObjectPointerValueObject(std::move(frame_sp), object_name, err);
8798184b252SMichael Buch
8808184b252SMichael Buch // We're inside a C++ class method. This could potentially be an unnamed
8818184b252SMichael Buch // lambda structure. If the lambda captured a "this", that should be
8828184b252SMichael Buch // the object pointer.
8838184b252SMichael Buch if (auto thisChildSP =
8848184b252SMichael Buch valobj_sp->GetChildMemberWithName(ConstString("this"), true)) {
8858184b252SMichael Buch valobj_sp = thisChildSP;
8868184b252SMichael Buch }
8878184b252SMichael Buch
8888184b252SMichael Buch if (!err.Success() || !valobj_sp.get())
8898184b252SMichael Buch return LLDB_INVALID_ADDRESS;
8908184b252SMichael Buch
8918184b252SMichael Buch lldb::addr_t ret = valobj_sp->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
8928184b252SMichael Buch
8938184b252SMichael Buch if (ret == LLDB_INVALID_ADDRESS) {
8948184b252SMichael Buch err.SetErrorStringWithFormat(
8958184b252SMichael Buch "Couldn't load '%s' because its value couldn't be evaluated",
8968184b252SMichael Buch object_name.AsCString());
8978184b252SMichael Buch return LLDB_INVALID_ADDRESS;
8988184b252SMichael Buch }
8998184b252SMichael Buch
9008184b252SMichael Buch return ret;
9018184b252SMichael Buch }
9028184b252SMichael Buch
AddArguments(ExecutionContext & exe_ctx,std::vector<lldb::addr_t> & args,lldb::addr_t struct_address,DiagnosticManager & diagnostic_manager)903b9c1b51eSKate Stone bool ClangUserExpression::AddArguments(ExecutionContext &exe_ctx,
904b9c1b51eSKate Stone std::vector<lldb::addr_t> &args,
905b9c1b51eSKate Stone lldb::addr_t struct_address,
906b9c1b51eSKate Stone DiagnosticManager &diagnostic_manager) {
9074dbb271fSSean Callanan lldb::addr_t object_ptr = LLDB_INVALID_ADDRESS;
9084dbb271fSSean Callanan lldb::addr_t cmd_ptr = LLDB_INVALID_ADDRESS;
9094dbb271fSSean Callanan
910b9c1b51eSKate Stone if (m_needs_object_ptr) {
9114dbb271fSSean Callanan lldb::StackFrameSP frame_sp = exe_ctx.GetFrameSP();
9124dbb271fSSean Callanan if (!frame_sp)
9134dbb271fSSean Callanan return true;
9144dbb271fSSean Callanan
9154dbb271fSSean Callanan ConstString object_name;
9164dbb271fSSean Callanan
917b9c1b51eSKate Stone if (m_in_cplusplus_method) {
9184dbb271fSSean Callanan object_name.SetCString("this");
919b9c1b51eSKate Stone } else if (m_in_objectivec_method) {
9204dbb271fSSean Callanan object_name.SetCString("self");
921b9c1b51eSKate Stone } else {
922e2411fabSZachary Turner diagnostic_manager.PutString(
923b9c1b51eSKate Stone eDiagnosticSeverityError,
924b9c1b51eSKate Stone "need object pointer but don't know the language");
9254dbb271fSSean Callanan return false;
9264dbb271fSSean Callanan }
9274dbb271fSSean Callanan
92897206d57SZachary Turner Status object_ptr_error;
9294dbb271fSSean Callanan
93040624a08SAleksandr Urakov if (m_ctx_obj) {
93140624a08SAleksandr Urakov AddressType address_type;
93240624a08SAleksandr Urakov object_ptr = m_ctx_obj->GetAddressOf(false, &address_type);
93340624a08SAleksandr Urakov if (object_ptr == LLDB_INVALID_ADDRESS ||
93440624a08SAleksandr Urakov address_type != eAddressTypeLoad)
93540624a08SAleksandr Urakov object_ptr_error.SetErrorString("Can't get context object's "
93640624a08SAleksandr Urakov "debuggee address");
9378184b252SMichael Buch } else {
9388184b252SMichael Buch if (m_in_cplusplus_method) {
9398184b252SMichael Buch object_ptr =
9408184b252SMichael Buch GetCppObjectPointer(frame_sp, object_name, object_ptr_error);
9418184b252SMichael Buch } else {
9424dbb271fSSean Callanan object_ptr = GetObjectPointer(frame_sp, object_name, object_ptr_error);
9438184b252SMichael Buch }
9448184b252SMichael Buch }
9454dbb271fSSean Callanan
946b9c1b51eSKate Stone if (!object_ptr_error.Success()) {
947b9c1b51eSKate Stone exe_ctx.GetTargetRef().GetDebugger().GetAsyncOutputStream()->Printf(
948f98df8a3SRaphael Isemann "warning: `%s' is not accessible (substituting 0). %s\n",
949f98df8a3SRaphael Isemann object_name.AsCString(), object_ptr_error.AsCString());
9504dbb271fSSean Callanan object_ptr = 0;
9514dbb271fSSean Callanan }
9524dbb271fSSean Callanan
953b9c1b51eSKate Stone if (m_in_objectivec_method) {
9544dbb271fSSean Callanan ConstString cmd_name("_cmd");
9554dbb271fSSean Callanan
9564dbb271fSSean Callanan cmd_ptr = GetObjectPointer(frame_sp, cmd_name, object_ptr_error);
9574dbb271fSSean Callanan
958b9c1b51eSKate Stone if (!object_ptr_error.Success()) {
959b9c1b51eSKate Stone diagnostic_manager.Printf(
960b9c1b51eSKate Stone eDiagnosticSeverityWarning,
961579e70c9SSean Callanan "couldn't get cmd pointer (substituting NULL): %s",
962579e70c9SSean Callanan object_ptr_error.AsCString());
9634dbb271fSSean Callanan cmd_ptr = 0;
9644dbb271fSSean Callanan }
9654dbb271fSSean Callanan }
966bda7ef84SSean Callanan
9674dbb271fSSean Callanan args.push_back(object_ptr);
9684dbb271fSSean Callanan
9694dbb271fSSean Callanan if (m_in_objectivec_method)
9704dbb271fSSean Callanan args.push_back(cmd_ptr);
9714dbb271fSSean Callanan
97251148e9fSJim Ingham args.push_back(struct_address);
973b9c1b51eSKate Stone } else {
97451148e9fSJim Ingham args.push_back(struct_address);
9754dbb271fSSean Callanan }
9764dbb271fSSean Callanan return true;
9774dbb271fSSean Callanan }
9784dbb271fSSean Callanan
GetResultAfterDematerialization(ExecutionContextScope * exe_scope)979b9c1b51eSKate Stone lldb::ExpressionVariableSP ClangUserExpression::GetResultAfterDematerialization(
980b9c1b51eSKate Stone ExecutionContextScope *exe_scope) {
9819fda9d21SSean Callanan return m_result_delegate.GetVariable();
9829fda9d21SSean Callanan }
9839fda9d21SSean Callanan
ResetDeclMap(ExecutionContext & exe_ctx,Materializer::PersistentVariableDelegate & delegate,bool keep_result_in_memory,ValueObject * ctx_obj)984b9c1b51eSKate Stone void ClangUserExpression::ClangUserExpressionHelper::ResetDeclMap(
985b9c1b51eSKate Stone ExecutionContext &exe_ctx,
986b9c1b51eSKate Stone Materializer::PersistentVariableDelegate &delegate,
98740624a08SAleksandr Urakov bool keep_result_in_memory,
98840624a08SAleksandr Urakov ValueObject *ctx_obj) {
9897c9ebdd3SAlex Langford std::shared_ptr<ClangASTImporter> ast_importer;
990c4f6fbe9SAlex Langford auto *state = exe_ctx.GetTargetSP()->GetPersistentExpressionStateForLanguage(
991c4f6fbe9SAlex Langford lldb::eLanguageTypeC);
992c4f6fbe9SAlex Langford if (state) {
993c4f6fbe9SAlex Langford auto *persistent_vars = llvm::cast<ClangPersistentVariables>(state);
994c4f6fbe9SAlex Langford ast_importer = persistent_vars->GetClangASTImporter();
995c4f6fbe9SAlex Langford }
99606412daeSJonas Devlieghere m_expr_decl_map_up = std::make_unique<ClangExpressionDeclMap>(
99706412daeSJonas Devlieghere keep_result_in_memory, &delegate, exe_ctx.GetTargetSP(), ast_importer,
99806412daeSJonas Devlieghere ctx_obj);
9994dbb271fSSean Callanan }
10004dbb271fSSean Callanan
10014dbb271fSSean Callanan clang::ASTConsumer *
ASTTransformer(clang::ASTConsumer * passthrough)1002b9c1b51eSKate Stone ClangUserExpression::ClangUserExpressionHelper::ASTTransformer(
1003b9c1b51eSKate Stone clang::ASTConsumer *passthrough) {
100406412daeSJonas Devlieghere m_result_synthesizer_up = std::make_unique<ASTResultSynthesizer>(
100506412daeSJonas Devlieghere passthrough, m_top_level, m_target);
10064dbb271fSSean Callanan
10074dbb271fSSean Callanan return m_result_synthesizer_up.get();
10084dbb271fSSean Callanan }
10094dbb271fSSean Callanan
CommitPersistentDecls()1010b9c1b51eSKate Stone void ClangUserExpression::ClangUserExpressionHelper::CommitPersistentDecls() {
101170355aceSJonas Devlieghere if (m_result_synthesizer_up) {
101200294b34SSean Callanan m_result_synthesizer_up->CommitPersistentDecls();
101300294b34SSean Callanan }
101400294b34SSean Callanan }
101500294b34SSean Callanan
GetName()1016b9c1b51eSKate Stone ConstString ClangUserExpression::ResultDelegate::GetName() {
101767d67ebeSJim Ingham return m_persistent_state->GetNextPersistentVariableName(false);
10189fda9d21SSean Callanan }
10199fda9d21SSean Callanan
DidDematerialize(lldb::ExpressionVariableSP & variable)1020b9c1b51eSKate Stone void ClangUserExpression::ResultDelegate::DidDematerialize(
1021b9c1b51eSKate Stone lldb::ExpressionVariableSP &variable) {
10229fda9d21SSean Callanan m_variable = variable;
10239fda9d21SSean Callanan }
10249fda9d21SSean Callanan
RegisterPersistentState(PersistentExpressionState * persistent_state)1025b9c1b51eSKate Stone void ClangUserExpression::ResultDelegate::RegisterPersistentState(
1026b9c1b51eSKate Stone PersistentExpressionState *persistent_state) {
10279fda9d21SSean Callanan m_persistent_state = persistent_state;
10289fda9d21SSean Callanan }
10299fda9d21SSean Callanan
GetVariable()1030b9c1b51eSKate Stone lldb::ExpressionVariableSP &ClangUserExpression::ResultDelegate::GetVariable() {
10319fda9d21SSean Callanan return m_variable;
10329fda9d21SSean Callanan }
1033