summaryrefslogtreecommitdiff
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.cpp195
1 files changed, 140 insertions, 55 deletions
diff --git a/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp b/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
index f42955df07aa..2dae5b7022f3 100644
--- a/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
+++ b/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
@@ -1,9 +1,8 @@
//===-- ClangUserExpression.cpp ---------------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
@@ -22,6 +21,7 @@
#include "ClangDiagnostic.h"
#include "ClangExpressionDeclMap.h"
#include "ClangExpressionParser.h"
+#include "ClangExpressionSourceCode.h"
#include "ClangModulesDeclVendor.h"
#include "ClangPersistentVariables.h"
@@ -37,6 +37,7 @@
#include "lldb/Symbol/Block.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/ClangExternalASTSourceCommon.h"
+#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/SymbolVendor.h"
@@ -55,18 +56,20 @@
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
+#include "llvm/ADT/ScopeExit.h"
+
using namespace lldb_private;
ClangUserExpression::ClangUserExpression(
ExecutionContextScope &exe_scope, llvm::StringRef expr,
llvm::StringRef prefix, lldb::LanguageType language,
- ResultType desired_type, const EvaluateExpressionOptions &options)
+ ResultType desired_type, const EvaluateExpressionOptions &options,
+ ValueObject *ctx_obj)
: LLVMUserExpression(exe_scope, expr, prefix, language, desired_type,
- options),
- m_type_system_helper(*m_target_wp.lock().get(),
- options.GetExecutionPolicy() ==
- eExecutionPolicyTopLevel),
- m_result_delegate(exe_scope.CalculateTarget()) {
+ options, eKindClangUserExpression),
+ m_type_system_helper(*m_target_wp.lock(), options.GetExecutionPolicy() ==
+ eExecutionPolicyTopLevel),
+ m_result_delegate(exe_scope.CalculateTarget()), m_ctx_obj(ctx_obj) {
switch (m_language) {
case lldb::eLanguageTypeC_plus_plus:
m_allow_cxx = true;
@@ -99,7 +102,7 @@ void ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Status &err) {
}
StackFrame *frame = exe_ctx.GetFramePtr();
- if (frame == NULL) {
+ if (frame == nullptr) {
if (log)
log->Printf(" [CUE::SC] Null stack frame");
return;
@@ -131,7 +134,27 @@ void ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Status &err) {
return;
}
- if (clang::CXXMethodDecl *method_decl =
+ if (m_ctx_obj) {
+ switch (m_ctx_obj->GetObjectRuntimeLanguage()) {
+ case lldb::eLanguageTypeC:
+ case lldb::eLanguageTypeC89:
+ case lldb::eLanguageTypeC99:
+ case lldb::eLanguageTypeC11:
+ case lldb::eLanguageTypeC_plus_plus:
+ case lldb::eLanguageTypeC_plus_plus_03:
+ case lldb::eLanguageTypeC_plus_plus_11:
+ case lldb::eLanguageTypeC_plus_plus_14:
+ m_in_cplusplus_method = true;
+ break;
+ case lldb::eLanguageTypeObjC:
+ case lldb::eLanguageTypeObjC_plus_plus:
+ m_in_objectivec_method = true;
+ break;
+ default:
+ break;
+ }
+ m_needs_object_ptr = true;
+ } else if (clang::CXXMethodDecl *method_decl =
ClangASTContext::DeclContextGetAsCXXMethodDecl(decl_context)) {
if (m_allow_cxx && method_decl->isInstance()) {
if (m_enforce_valid_object) {
@@ -307,21 +330,6 @@ static void ApplyObjcCastHack(std::string &expr) {
#undef OBJC_CAST_HACK_FROM
}
-namespace {
-// Utility guard that calls a callback when going out of scope.
-class OnExit {
-public:
- typedef std::function<void(void)> Callback;
-
- OnExit(Callback const &callback) : m_callback(callback) {}
-
- ~OnExit() { m_callback(); }
-
-private:
- Callback m_callback;
-};
-} // namespace
-
bool ClangUserExpression::SetupPersistentState(DiagnosticManager &diagnostic_manager,
ExecutionContext &exe_ctx) {
if (Target *target = exe_ctx.GetTargetPtr()) {
@@ -377,7 +385,8 @@ static void SetupDeclVendor(ExecutionContext &exe_ctx, Target *target) {
}
void ClangUserExpression::UpdateLanguageForExpr(
- DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx) {
+ DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx,
+ std::vector<std::string> modules_to_import, bool for_completion) {
m_expr_lang = lldb::LanguageType::eLanguageTypeUnknown;
std::string prefix = m_expr_prefix;
@@ -385,8 +394,8 @@ void ClangUserExpression::UpdateLanguageForExpr(
if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel) {
m_transformed_text = m_expr_text;
} else {
- std::unique_ptr<ExpressionSourceCode> source_code(
- ExpressionSourceCode::CreateWrapped(prefix.c_str(),
+ std::unique_ptr<ClangExpressionSourceCode> source_code(
+ ClangExpressionSourceCode::CreateWrapped(prefix.c_str(),
m_expr_text.c_str()));
if (m_in_cplusplus_method)
@@ -397,7 +406,8 @@ void ClangUserExpression::UpdateLanguageForExpr(
m_expr_lang = lldb::eLanguageTypeC;
if (!source_code->GetText(m_transformed_text, m_expr_lang,
- m_in_static_method, exe_ctx)) {
+ m_in_static_method, exe_ctx, !m_ctx_obj,
+ for_completion, modules_to_import)) {
diagnostic_manager.PutString(eDiagnosticSeverityError,
"couldn't construct expression body");
return;
@@ -409,14 +419,73 @@ void ClangUserExpression::UpdateLanguageForExpr(
std::size_t original_end;
bool found_bounds = source_code->GetOriginalBodyBounds(
m_transformed_text, m_expr_lang, original_start, original_end);
- if (found_bounds) {
+ if (found_bounds)
m_user_expression_start_pos = original_start;
+ }
+}
+
+static bool SupportsCxxModuleImport(lldb::LanguageType language) {
+ switch (language) {
+ case lldb::eLanguageTypeC_plus_plus:
+ case lldb::eLanguageTypeC_plus_plus_03:
+ case lldb::eLanguageTypeC_plus_plus_11:
+ case lldb::eLanguageTypeC_plus_plus_14:
+ case lldb::eLanguageTypeObjC_plus_plus:
+ return true;
+ default:
+ return false;
+ }
+}
+
+std::vector<std::string>
+ClangUserExpression::GetModulesToImport(ExecutionContext &exe_ctx) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
+
+ if (!SupportsCxxModuleImport(Language()))
+ return {};
+
+ Target *target = exe_ctx.GetTargetPtr();
+ if (!target || !target->GetEnableImportStdModule())
+ return {};
+
+ StackFrame *frame = exe_ctx.GetFramePtr();
+ if (!frame)
+ return {};
+
+ Block *block = frame->GetFrameBlock();
+ if (!block)
+ return {};
+
+ SymbolContext sc;
+ block->CalculateSymbolContext(&sc);
+ if (!sc.comp_unit)
+ return {};
+
+ if (log) {
+ for (const SourceModule &m : sc.comp_unit->GetImportedModules()) {
+ LLDB_LOG(log, "Found module in compile unit: {0:$[.]} - include dir: {1}",
+ llvm::make_range(m.path.begin(), m.path.end()), m.search_path);
}
}
+
+ for (const SourceModule &m : sc.comp_unit->GetImportedModules())
+ m_include_directories.push_back(m.search_path);
+
+ // Check if we imported 'std' or any of its submodules.
+ // We currently don't support importing any other modules in the expression
+ // parser.
+ for (const SourceModule &m : sc.comp_unit->GetImportedModules())
+ if (!m.path.empty() && m.path.front() == "std")
+ return {"std"};
+
+ return {};
}
bool ClangUserExpression::PrepareForParsing(
- DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx) {
+ DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx,
+ bool for_completion) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
+
InstallContext(exe_ctx);
if (!SetupPersistentState(diagnostic_manager, exe_ctx))
@@ -437,7 +506,14 @@ bool ClangUserExpression::PrepareForParsing(
SetupDeclVendor(exe_ctx, m_target);
- UpdateLanguageForExpr(diagnostic_manager, exe_ctx);
+ std::vector<std::string> used_modules = GetModulesToImport(exe_ctx);
+ m_imported_cpp_modules = !used_modules.empty();
+
+ LLDB_LOG(log, "List of imported modules in expression: {0}",
+ llvm::make_range(used_modules.begin(), used_modules.end()));
+
+ UpdateLanguageForExpr(diagnostic_manager, exe_ctx, used_modules,
+ for_completion);
return true;
}
@@ -448,7 +524,7 @@ bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager,
bool generate_debug_info) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
- if (!PrepareForParsing(diagnostic_manager, exe_ctx))
+ if (!PrepareForParsing(diagnostic_manager, exe_ctx, /*for_completion*/ false))
return false;
if (log)
@@ -469,13 +545,13 @@ bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager,
// Parse the expression
//
- m_materializer_ap.reset(new Materializer());
+ m_materializer_up.reset(new Materializer());
ResetDeclMap(exe_ctx, m_result_delegate, keep_result_in_memory);
- OnExit on_exit([this]() { ResetDeclMap(); });
+ auto on_exit = llvm::make_scope_exit([this]() { ResetDeclMap(); });
- if (!DeclMap()->WillParse(exe_ctx, m_materializer_ap.get())) {
+ if (!DeclMap()->WillParse(exe_ctx, m_materializer_up.get())) {
diagnostic_manager.PutString(
eDiagnosticSeverityError,
"current process state is unsuitable for expression parsing");
@@ -496,7 +572,8 @@ bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager,
// 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);
+ ClangExpressionParser parser(exe_scope, *this, generate_debug_info,
+ m_include_directories);
unsigned num_errors = parser.Parse(diagnostic_manager);
@@ -509,7 +586,7 @@ bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager,
size_t fixed_end;
const std::string &fixed_expression =
diagnostic_manager.GetFixedExpression();
- if (ExpressionSourceCode::GetOriginalBodyBounds(
+ if (ClangExpressionSourceCode::GetOriginalBodyBounds(
fixed_expression, m_expr_lang, fixed_start, fixed_end))
m_fixed_text =
fixed_expression.substr(fixed_start, fixed_end - fixed_start);
@@ -518,7 +595,7 @@ bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager,
return false;
}
- //////////////////////////////////////////////////////////////////////////////////////////
+ //////////////////////////////////////////////////////////////////////////////
// Prepare the output of the parser for execution, evaluating it statically
// if possible
//
@@ -597,25 +674,23 @@ bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager,
return true;
}
-//------------------------------------------------------------------
/// Converts an absolute position inside a given code string into
/// a column/line pair.
///
-/// @param[in] abs_pos
+/// \param[in] abs_pos
/// A absolute position in the code string that we want to convert
/// to a column/line pair.
///
-/// @param[in] code
+/// \param[in] code
/// A multi-line string usually representing source code.
///
-/// @param[out] line
+/// \param[out] line
/// The line in the code that contains the given absolute position.
/// The first line in the string is indexed as 1.
///
-/// @param[out] column
+/// \param[out] column
/// The column in the line that contains the absolute position.
/// The first character in a line is indexed as 0.
-//------------------------------------------------------------------
static void AbsPosToLineColumnPos(size_t abs_pos, llvm::StringRef code,
unsigned &line, unsigned &column) {
// Reset to code position to beginning of the file.
@@ -648,7 +723,7 @@ bool ClangUserExpression::Complete(ExecutionContext &exe_ctx,
// correct.
DiagnosticManager diagnostic_manager;
- if (!PrepareForParsing(diagnostic_manager, exe_ctx))
+ if (!PrepareForParsing(diagnostic_manager, exe_ctx, /*for_completion*/ true))
return false;
if (log)
@@ -658,13 +733,13 @@ bool ClangUserExpression::Complete(ExecutionContext &exe_ctx,
// Parse the expression
//
- m_materializer_ap.reset(new Materializer());
+ m_materializer_up.reset(new Materializer());
ResetDeclMap(exe_ctx, m_result_delegate, /*keep result in memory*/ true);
- OnExit on_exit([this]() { ResetDeclMap(); });
+ auto on_exit = llvm::make_scope_exit([this]() { ResetDeclMap(); });
- if (!DeclMap()->WillParse(exe_ctx, m_materializer_ap.get())) {
+ if (!DeclMap()->WillParse(exe_ctx, m_materializer_up.get())) {
diagnostic_manager.PutString(
eDiagnosticSeverityError,
"current process state is unsuitable for expression parsing");
@@ -734,7 +809,15 @@ bool ClangUserExpression::AddArguments(ExecutionContext &exe_ctx,
Status object_ptr_error;
- object_ptr = GetObjectPointer(frame_sp, object_name, object_ptr_error);
+ if (m_ctx_obj) {
+ AddressType address_type;
+ object_ptr = m_ctx_obj->GetAddressOf(false, &address_type);
+ if (object_ptr == LLDB_INVALID_ADDRESS ||
+ address_type != eAddressTypeLoad)
+ object_ptr_error.SetErrorString("Can't get context object's "
+ "debuggee address");
+ } else
+ object_ptr = GetObjectPointer(frame_sp, object_name, object_ptr_error);
if (!object_ptr_error.Success()) {
exe_ctx.GetTargetRef().GetDebugger().GetAsyncOutputStream()->Printf(
@@ -777,9 +860,11 @@ lldb::ExpressionVariableSP ClangUserExpression::GetResultAfterDematerialization(
void ClangUserExpression::ClangUserExpressionHelper::ResetDeclMap(
ExecutionContext &exe_ctx,
Materializer::PersistentVariableDelegate &delegate,
- bool keep_result_in_memory) {
+ bool keep_result_in_memory,
+ ValueObject *ctx_obj) {
m_expr_decl_map_up.reset(
- new ClangExpressionDeclMap(keep_result_in_memory, &delegate, exe_ctx));
+ new ClangExpressionDeclMap(keep_result_in_memory, &delegate, exe_ctx,
+ ctx_obj));
}
clang::ASTConsumer *
@@ -792,7 +877,7 @@ ClangUserExpression::ClangUserExpressionHelper::ASTTransformer(
}
void ClangUserExpression::ClangUserExpressionHelper::CommitPersistentDecls() {
- if (m_result_synthesizer_up.get()) {
+ if (m_result_synthesizer_up) {
m_result_synthesizer_up->CommitPersistentDecls();
}
}