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