aboutsummaryrefslogtreecommitdiff
path: root/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp')
-rw-r--r--source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp257
1 files changed, 158 insertions, 99 deletions
diff --git a/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp b/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
index 11f7f84ff5f1..52d49aecec9a 100644
--- a/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
+++ b/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
@@ -23,8 +23,10 @@
#include "ClangExpressionParser.h"
#include "ClangModulesDeclVendor.h"
#include "ClangPersistentVariables.h"
+#include "ClangDiagnostic.h"
#include "lldb/Core/ConstString.h"
+#include "lldb/Core/Debugger.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/StreamFile.h"
@@ -55,28 +57,25 @@
using namespace lldb_private;
-ClangUserExpression::ClangUserExpression (ExecutionContextScope &exe_scope,
- const char *expr,
- const char *expr_prefix,
- lldb::LanguageType language,
- ResultType desired_type,
- const EvaluateExpressionOptions &options) :
- LLVMUserExpression (exe_scope, expr, expr_prefix, language, desired_type, options),
- m_type_system_helper(*m_target_wp.lock().get())
+ClangUserExpression::ClangUserExpression(ExecutionContextScope &exe_scope, const char *expr, const char *expr_prefix,
+ lldb::LanguageType language, ResultType desired_type,
+ const EvaluateExpressionOptions &options)
+ : LLVMUserExpression(exe_scope, expr, expr_prefix, language, desired_type, options),
+ m_type_system_helper(*m_target_wp.lock().get(), options.GetExecutionPolicy() == eExecutionPolicyTopLevel)
{
switch (m_language)
{
- case lldb::eLanguageTypeC_plus_plus:
- m_allow_cxx = true;
- break;
- case lldb::eLanguageTypeObjC:
- m_allow_objc = true;
- break;
- case lldb::eLanguageTypeObjC_plus_plus:
- default:
- m_allow_cxx = true;
- m_allow_objc = true;
- break;
+ case lldb::eLanguageTypeC_plus_plus:
+ m_allow_cxx = true;
+ break;
+ case lldb::eLanguageTypeObjC:
+ m_allow_objc = true;
+ break;
+ case lldb::eLanguageTypeObjC_plus_plus:
+ default:
+ m_allow_cxx = true;
+ m_allow_objc = true;
+ break;
}
}
@@ -326,11 +325,9 @@ ApplyObjcCastHack(std::string &expr)
}
bool
-ClangUserExpression::Parse (Stream &error_stream,
- ExecutionContext &exe_ctx,
- lldb_private::ExecutionPolicy execution_policy,
- bool keep_result_in_memory,
- bool generate_debug_info)
+ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx,
+ lldb_private::ExecutionPolicy execution_policy, bool keep_result_in_memory,
+ bool generate_debug_info)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
@@ -346,13 +343,13 @@ ClangUserExpression::Parse (Stream &error_stream,
}
else
{
- error_stream.PutCString ("error: couldn't start parsing (no persistent data)");
+ diagnostic_manager.PutCString(eDiagnosticSeverityError, "couldn't start parsing (no persistent data)");
return false;
}
}
else
{
- error_stream.PutCString ("error: couldn't start parsing (no target)");
+ diagnostic_manager.PutCString(eDiagnosticSeverityError, "error: couldn't start parsing (no target)");
return false;
}
@@ -360,11 +357,9 @@ ClangUserExpression::Parse (Stream &error_stream,
if (!err.Success())
{
- error_stream.Printf("warning: %s\n", err.AsCString());
+ diagnostic_manager.PutCString(eDiagnosticSeverityWarning, err.AsCString());
}
- StreamString m_transformed_stream;
-
////////////////////////////////////
// Generate the expression
//
@@ -404,22 +399,30 @@ ClangUserExpression::Parse (Stream &error_stream,
}
}
}
-
- std::unique_ptr<ExpressionSourceCode> source_code (ExpressionSourceCode::CreateWrapped(prefix.c_str(), m_expr_text.c_str()));
-
- lldb::LanguageType lang_type;
- if (m_in_cplusplus_method)
- lang_type = lldb::eLanguageTypeC_plus_plus;
- else if (m_in_objectivec_method)
- lang_type = lldb::eLanguageTypeObjC;
- else
- lang_type = lldb::eLanguageTypeC;
+ lldb::LanguageType lang_type = lldb::eLanguageTypeUnknown;
- if (!source_code->GetText(m_transformed_text, lang_type, m_const_object, m_in_static_method, exe_ctx))
+ if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel)
{
- error_stream.PutCString ("error: couldn't construct expression body");
- return false;
+ m_transformed_text = m_expr_text;
+ }
+ else
+ {
+ std::unique_ptr<ExpressionSourceCode> source_code(
+ ExpressionSourceCode::CreateWrapped(prefix.c_str(), m_expr_text.c_str()));
+
+ if (m_in_cplusplus_method)
+ lang_type = lldb::eLanguageTypeC_plus_plus;
+ else if (m_in_objectivec_method)
+ lang_type = lldb::eLanguageTypeObjC;
+ else
+ lang_type = lldb::eLanguageTypeC;
+
+ if (!source_code->GetText(m_transformed_text, lang_type, m_in_static_method, exe_ctx))
+ {
+ diagnostic_manager.PutCString(eDiagnosticSeverityError, "couldn't construct expression body");
+ return false;
+ }
}
if (log)
@@ -433,7 +436,7 @@ ClangUserExpression::Parse (Stream &error_stream,
if (!target)
{
- error_stream.PutCString ("error: invalid target\n");
+ diagnostic_manager.PutCString(eDiagnosticSeverityError, "invalid target");
return false;
}
@@ -467,26 +470,47 @@ ClangUserExpression::Parse (Stream &error_stream,
if (!DeclMap()->WillParse(exe_ctx, m_materializer_ap.get()))
{
- error_stream.PutCString ("error: current process state is unsuitable for expression parsing\n");
+ diagnostic_manager.PutCString(eDiagnosticSeverityError,
+ "current process state is unsuitable for expression parsing");
ResetDeclMap(); // We are being careful here in the case of breakpoint conditions.
return false;
}
+ if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel)
+ {
+ DeclMap()->SetLookupsEnabled(true);
+ }
+
Process *process = exe_ctx.GetProcessPtr();
ExecutionContextScope *exe_scope = process;
if (!exe_scope)
exe_scope = exe_ctx.GetTargetPtr();
+ // We use a shared pointer here so we can use the original parser - if it succeeds
+ // or the rewrite parser we might make if it fails. But the parser_sp will never be empty.
+
ClangExpressionParser parser(exe_scope, *this, generate_debug_info);
- unsigned num_errors = parser.Parse (error_stream);
+ unsigned num_errors = parser.Parse(diagnostic_manager);
+ // Check here for FixItHints. If there are any try to apply the fixits and set the fixed text in m_fixed_text
+ // before returning an error.
if (num_errors)
{
- error_stream.Printf ("error: %d errors parsing expression\n", num_errors);
+ if (diagnostic_manager.HasFixIts())
+ {
+ if (parser.RewriteExpression(diagnostic_manager))
+ {
+ size_t fixed_start;
+ size_t fixed_end;
+ const std::string &fixed_expression = diagnostic_manager.GetFixedExpression();
+ if (ExpressionSourceCode::GetOriginalBodyBounds(fixed_expression, lang_type, fixed_start, fixed_end))
+ m_fixed_text = fixed_expression.substr(fixed_start, fixed_end - fixed_start);
+ }
+ }
ResetDeclMap(); // We are being careful here in the case of breakpoint conditions.
@@ -497,16 +521,70 @@ ClangUserExpression::Parse (Stream &error_stream,
// Prepare the output of the parser for execution, evaluating it statically if possible
//
- Error jit_error = parser.PrepareForExecution (m_jit_start_addr,
- m_jit_end_addr,
- m_execution_unit_sp,
- exe_ctx,
- m_can_interpret,
- execution_policy);
+ {
+ Error jit_error = parser.PrepareForExecution(m_jit_start_addr,
+ m_jit_end_addr,
+ m_execution_unit_sp,
+ exe_ctx,
+ m_can_interpret,
+ execution_policy);
+
+ if (!jit_error.Success())
+ {
+ const char *error_cstr = jit_error.AsCString();
+ if (error_cstr && error_cstr[0])
+ diagnostic_manager.PutCString(eDiagnosticSeverityError, error_cstr);
+ else
+ diagnostic_manager.PutCString(eDiagnosticSeverityError, "expression can't be interpreted or run");
+ return false;
+ }
+ }
+
+ if (exe_ctx.GetProcessPtr() && execution_policy == eExecutionPolicyTopLevel)
+ {
+ Error static_init_error = parser.RunStaticInitializers(m_execution_unit_sp, exe_ctx);
+
+ if (!static_init_error.Success())
+ {
+ const char *error_cstr = static_init_error.AsCString();
+ if (error_cstr && error_cstr[0])
+ diagnostic_manager.Printf(eDiagnosticSeverityError, "couldn't run static initializers: %s\n",
+ error_cstr);
+ else
+ diagnostic_manager.PutCString(eDiagnosticSeverityError, "couldn't run static initializers\n");
+ return false;
+ }
+ }
+
+ if (m_execution_unit_sp)
+ {
+ bool register_execution_unit = false;
+
+ if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel)
+ {
+ register_execution_unit = true;
+ }
+
+ // If there is more than one external function in the execution
+ // unit, it needs to keep living even if it's not top level, because
+ // the result could refer to that function.
+
+ if (m_execution_unit_sp->GetJittedFunctions().size() > 1)
+ {
+ register_execution_unit = true;
+ }
+
+ if (register_execution_unit)
+ {
+ llvm::cast<PersistentExpressionState>(
+ exe_ctx.GetTargetPtr()->GetPersistentExpressionStateForLanguage(m_language))
+ ->RegisterExecutionUnit(m_execution_unit_sp);
+ }
+ }
if (generate_debug_info)
{
- lldb::ModuleSP jit_module_sp ( m_execution_unit_sp->GetJITModule());
+ lldb::ModuleSP jit_module_sp(m_execution_unit_sp->GetJITModule());
if (jit_module_sp)
{
@@ -517,52 +595,23 @@ ClangUserExpression::Parse (Stream &error_stream,
m_jit_module_wp = jit_module_sp;
target->GetImages().Append(jit_module_sp);
}
-// lldb_private::ObjectFile *jit_obj_file = jit_module_sp->GetObjectFile();
-// StreamFile strm (stdout, false);
-// if (jit_obj_file)
-// {
-// jit_obj_file->GetSectionList();
-// jit_obj_file->GetSymtab();
-// jit_obj_file->Dump(&strm);
-// }
-// lldb_private::SymbolVendor *jit_sym_vendor = jit_module_sp->GetSymbolVendor();
-// if (jit_sym_vendor)
-// {
-// lldb_private::SymbolContextList sc_list;
-// jit_sym_vendor->FindFunctions(const_func_name, NULL, lldb::eFunctionNameTypeFull, true, false, sc_list);
-// sc_list.Dump(&strm, target);
-// jit_sym_vendor->Dump(&strm);
-// }
}
- ResetDeclMap(); // Make this go away since we don't need any of its state after parsing. This also gets rid of any ClangASTImporter::Minions.
+ ResetDeclMap(); // Make this go away since we don't need any of its state after parsing. This also gets rid of any
+ // ClangASTImporter::Minions.
- if (jit_error.Success())
- {
- if (process && m_jit_start_addr != LLDB_INVALID_ADDRESS)
- m_jit_process_wp = lldb::ProcessWP(process->shared_from_this());
- return true;
- }
- else
- {
- const char *error_cstr = jit_error.AsCString();
- if (error_cstr && error_cstr[0])
- error_stream.Printf ("error: %s\n", error_cstr);
- else
- error_stream.Printf ("error: expression can't be interpreted or run\n");
- return false;
- }
+ if (process && m_jit_start_addr != LLDB_INVALID_ADDRESS)
+ m_jit_process_wp = lldb::ProcessWP(process->shared_from_this());
+ return true;
}
bool
-ClangUserExpression::AddArguments (ExecutionContext &exe_ctx,
- std::vector<lldb::addr_t> &args,
- lldb::addr_t struct_address,
- Stream &error_stream)
+ClangUserExpression::AddArguments(ExecutionContext &exe_ctx, std::vector<lldb::addr_t> &args,
+ lldb::addr_t struct_address, DiagnosticManager &diagnostic_manager)
{
lldb::addr_t object_ptr = LLDB_INVALID_ADDRESS;
- lldb::addr_t cmd_ptr = LLDB_INVALID_ADDRESS;
-
+ lldb::addr_t cmd_ptr = LLDB_INVALID_ADDRESS;
+
if (m_needs_object_ptr)
{
lldb::StackFrameSP frame_sp = exe_ctx.GetFrameSP();
@@ -581,7 +630,7 @@ ClangUserExpression::AddArguments (ExecutionContext &exe_ctx,
}
else
{
- error_stream.Printf("Need object pointer but don't know the language\n");
+ diagnostic_manager.PutCString(eDiagnosticSeverityError, "need object pointer but don't know the language");
return false;
}
@@ -591,7 +640,7 @@ ClangUserExpression::AddArguments (ExecutionContext &exe_ctx,
if (!object_ptr_error.Success())
{
- error_stream.Printf("warning: couldn't get required object pointer (substituting NULL): %s\n", object_ptr_error.AsCString());
+ exe_ctx.GetTargetRef().GetDebugger().GetAsyncOutputStream()->Printf("warning: `%s' is not accessible (subsituting 0)\n", object_name.AsCString());
object_ptr = 0;
}
@@ -603,12 +652,14 @@ ClangUserExpression::AddArguments (ExecutionContext &exe_ctx,
if (!object_ptr_error.Success())
{
- error_stream.Printf("warning: couldn't get cmd pointer (substituting NULL): %s\n", object_ptr_error.AsCString());
+ diagnostic_manager.Printf(eDiagnosticSeverityWarning,
+ "couldn't get cmd pointer (substituting NULL): %s",
+ object_ptr_error.AsCString());
cmd_ptr = 0;
}
}
- if (object_ptr)
- args.push_back(object_ptr);
+
+ args.push_back(object_ptr);
if (m_in_objectivec_method)
args.push_back(cmd_ptr);
@@ -635,14 +686,22 @@ ClangUserExpression::ClangUserExpressionHelper::ResetDeclMap(ExecutionContext &e
}
clang::ASTConsumer *
-ClangUserExpression::ClangUserExpressionHelper::ASTTransformer (clang::ASTConsumer *passthrough)
+ClangUserExpression::ClangUserExpressionHelper::ASTTransformer(clang::ASTConsumer *passthrough)
{
- m_result_synthesizer_up.reset(new ASTResultSynthesizer(passthrough,
- m_target));
+ m_result_synthesizer_up.reset(new ASTResultSynthesizer(passthrough, m_top_level, m_target));
return m_result_synthesizer_up.get();
}
+void
+ClangUserExpression::ClangUserExpressionHelper::CommitPersistentDecls()
+{
+ if (m_result_synthesizer_up.get())
+ {
+ m_result_synthesizer_up->CommitPersistentDecls();
+ }
+}
+
ClangUserExpression::ResultDelegate::ResultDelegate()
{
}