aboutsummaryrefslogtreecommitdiffstats
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.cpp189
1 files changed, 107 insertions, 82 deletions
diff --git a/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp b/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
index 2dae5b7022f3..da1ca785635c 100644
--- a/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
+++ b/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
@@ -6,6 +6,8 @@
//
//===----------------------------------------------------------------------===//
+#include "lldb/Host/Config.h"
+
#include <stdio.h>
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
@@ -21,9 +23,9 @@
#include "ClangDiagnostic.h"
#include "ClangExpressionDeclMap.h"
#include "ClangExpressionParser.h"
-#include "ClangExpressionSourceCode.h"
#include "ClangModulesDeclVendor.h"
#include "ClangPersistentVariables.h"
+#include "CppModuleConfiguration.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Module.h"
@@ -90,21 +92,18 @@ ClangUserExpression::~ClangUserExpression() {}
void ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Status &err) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
- if (log)
- log->Printf("ClangUserExpression::ScanContext()");
+ LLDB_LOGF(log, "ClangUserExpression::ScanContext()");
m_target = exe_ctx.GetTargetPtr();
if (!(m_allow_cxx || m_allow_objc)) {
- if (log)
- log->Printf(" [CUE::SC] Settings inhibit C++ and Objective-C");
+ LLDB_LOGF(log, " [CUE::SC] Settings inhibit C++ and Objective-C");
return;
}
StackFrame *frame = exe_ctx.GetFramePtr();
if (frame == nullptr) {
- if (log)
- log->Printf(" [CUE::SC] Null stack frame");
+ LLDB_LOGF(log, " [CUE::SC] Null stack frame");
return;
}
@@ -112,8 +111,7 @@ void ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Status &err) {
lldb::eSymbolContextBlock);
if (!sym_ctx.function) {
- if (log)
- log->Printf(" [CUE::SC] Null function");
+ LLDB_LOGF(log, " [CUE::SC] Null function");
return;
}
@@ -121,16 +119,14 @@ void ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Status &err) {
Block *function_block = sym_ctx.GetFunctionBlock();
if (!function_block) {
- if (log)
- log->Printf(" [CUE::SC] Null function block");
+ LLDB_LOGF(log, " [CUE::SC] Null function block");
return;
}
CompilerDeclContext decl_context = function_block->GetDeclContext();
if (!decl_context) {
- if (log)
- log->Printf(" [CUE::SC] Null decl context");
+ LLDB_LOGF(log, " [CUE::SC] Null decl context");
return;
}
@@ -317,17 +313,13 @@ void ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Status &err) {
// count is not available, [myArray count] returns id, which can't be directly
// cast to int without causing a clang error.
static void ApplyObjcCastHack(std::string &expr) {
-#define OBJC_CAST_HACK_FROM "(int)["
-#define OBJC_CAST_HACK_TO "(int)(long long)["
-
- size_t from_offset;
+ const std::string from = "(int)[";
+ const std::string to = "(int)(long long)[";
- while ((from_offset = expr.find(OBJC_CAST_HACK_FROM)) != expr.npos)
- expr.replace(from_offset, sizeof(OBJC_CAST_HACK_FROM) - 1,
- OBJC_CAST_HACK_TO);
+ size_t offset;
-#undef OBJC_CAST_HACK_TO
-#undef OBJC_CAST_HACK_FROM
+ while ((offset = expr.find(from)) != expr.npos)
+ expr.replace(offset, from.size(), to);
}
bool ClangUserExpression::SetupPersistentState(DiagnosticManager &diagnostic_manager,
@@ -336,6 +328,7 @@ bool ClangUserExpression::SetupPersistentState(DiagnosticManager &diagnostic_man
if (PersistentExpressionState *persistent_state =
target->GetPersistentExpressionStateForLanguage(
lldb::eLanguageTypeC)) {
+ m_clang_state = llvm::cast<ClangPersistentVariables>(persistent_state);
m_result_delegate.RegisterPersistentState(persistent_state);
} else {
diagnostic_manager.PutString(
@@ -384,30 +377,34 @@ static void SetupDeclVendor(ExecutionContext &exe_ctx, Target *target) {
}
}
-void ClangUserExpression::UpdateLanguageForExpr(
+void ClangUserExpression::UpdateLanguageForExpr() {
+ m_expr_lang = lldb::LanguageType::eLanguageTypeUnknown;
+ if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel)
+ return;
+ if (m_in_cplusplus_method)
+ m_expr_lang = lldb::eLanguageTypeC_plus_plus;
+ else if (m_in_objectivec_method)
+ m_expr_lang = lldb::eLanguageTypeObjC;
+ else
+ m_expr_lang = lldb::eLanguageTypeC;
+}
+
+void ClangUserExpression::CreateSourceCode(
DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx,
std::vector<std::string> modules_to_import, bool for_completion) {
- m_expr_lang = lldb::LanguageType::eLanguageTypeUnknown;
+ m_filename = m_clang_state->GetNextExprFileName();
std::string prefix = m_expr_prefix;
if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel) {
m_transformed_text = m_expr_text;
} else {
- std::unique_ptr<ClangExpressionSourceCode> source_code(
- ClangExpressionSourceCode::CreateWrapped(prefix.c_str(),
- m_expr_text.c_str()));
-
- if (m_in_cplusplus_method)
- m_expr_lang = lldb::eLanguageTypeC_plus_plus;
- else if (m_in_objectivec_method)
- m_expr_lang = lldb::eLanguageTypeObjC;
- else
- m_expr_lang = lldb::eLanguageTypeC;
-
- if (!source_code->GetText(m_transformed_text, m_expr_lang,
- m_in_static_method, exe_ctx, !m_ctx_obj,
- for_completion, modules_to_import)) {
+ m_source_code.reset(ClangExpressionSourceCode::CreateWrapped(
+ m_filename, prefix.c_str(), m_expr_text.c_str()));
+
+ if (!m_source_code->GetText(m_transformed_text, m_expr_lang,
+ m_in_static_method, exe_ctx, !m_ctx_obj,
+ for_completion, modules_to_import)) {
diagnostic_manager.PutString(eDiagnosticSeverityError,
"couldn't construct expression body");
return;
@@ -417,7 +414,7 @@ void ClangUserExpression::UpdateLanguageForExpr(
// transformed code. We need this later for the code completion.
std::size_t original_start;
std::size_t original_end;
- bool found_bounds = source_code->GetOriginalBodyBounds(
+ bool found_bounds = m_source_code->GetOriginalBodyBounds(
m_transformed_text, m_expr_lang, original_start, original_end);
if (found_bounds)
m_user_expression_start_pos = original_start;
@@ -437,48 +434,70 @@ static bool SupportsCxxModuleImport(lldb::LanguageType language) {
}
}
-std::vector<std::string>
-ClangUserExpression::GetModulesToImport(ExecutionContext &exe_ctx) {
+/// Utility method that puts a message into the expression log and
+/// returns an invalid module configuration.
+static CppModuleConfiguration LogConfigError(const std::string &msg) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
+ LLDB_LOG(log, "[C++ module config] {0}", msg);
+ return CppModuleConfiguration();
+}
- if (!SupportsCxxModuleImport(Language()))
- return {};
+CppModuleConfiguration GetModuleConfig(lldb::LanguageType language,
+ ExecutionContext &exe_ctx) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
+
+ // Don't do anything if this is not a C++ module configuration.
+ if (!SupportsCxxModuleImport(language))
+ return LogConfigError("Language doesn't support C++ modules");
Target *target = exe_ctx.GetTargetPtr();
- if (!target || !target->GetEnableImportStdModule())
- return {};
+ if (!target)
+ return LogConfigError("No target");
+
+ if (!target->GetEnableImportStdModule())
+ return LogConfigError("Importing std module not enabled in settings");
StackFrame *frame = exe_ctx.GetFramePtr();
if (!frame)
- return {};
+ return LogConfigError("No frame");
Block *block = frame->GetFrameBlock();
if (!block)
- return {};
+ return LogConfigError("No block");
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);
+ return LogConfigError("Couldn't calculate symbol context");
+
+ // Build a list of files we need to analyze to build the configuration.
+ FileSpecList files;
+ for (const FileSpec &f : sc.comp_unit->GetSupportFiles())
+ files.AppendIfUnique(f);
+ // We also need to look at external modules in the case of -gmodules as they
+ // contain the support files for libc++ and the C library.
+ sc.comp_unit->ForEachExternalModule([&files](lldb::ModuleSP module) {
+ for (std::size_t i = 0; i < module->GetNumCompileUnits(); ++i) {
+ const FileSpecList &support_files =
+ module->GetCompileUnitAtIndex(i)->GetSupportFiles();
+ for (const FileSpec &f : support_files) {
+ files.AppendIfUnique(f);
+ }
}
+ });
+
+ LLDB_LOG(log, "[C++ module config] Found {0} support files to analyze",
+ files.GetSize());
+ if (log && log->GetVerbose()) {
+ for (const FileSpec &f : files)
+ LLDB_LOGV(log, "[C++ module config] Analyzing support file: {0}",
+ f.GetPath());
}
- 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 {};
+ // Try to create a configuration from the files. If there is no valid
+ // configuration possible with the files, this just returns an invalid
+ // configuration.
+ return CppModuleConfiguration(files);
}
bool ClangUserExpression::PrepareForParsing(
@@ -506,14 +525,21 @@ bool ClangUserExpression::PrepareForParsing(
SetupDeclVendor(exe_ctx, m_target);
- std::vector<std::string> used_modules = GetModulesToImport(exe_ctx);
- m_imported_cpp_modules = !used_modules.empty();
+ CppModuleConfiguration module_config = GetModuleConfig(m_language, exe_ctx);
+ llvm::ArrayRef<std::string> imported_modules =
+ module_config.GetImportedModules();
+ m_imported_cpp_modules = !imported_modules.empty();
+ m_include_directories = module_config.GetIncludeDirs();
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);
+ llvm::make_range(imported_modules.begin(), imported_modules.end()));
+ LLDB_LOG(log, "List of include directories gathered for modules: {0}",
+ llvm::make_range(m_include_directories.begin(),
+ m_include_directories.end()));
+
+ UpdateLanguageForExpr();
+ CreateSourceCode(diagnostic_manager, exe_ctx, imported_modules,
+ for_completion);
return true;
}
@@ -527,8 +553,7 @@ bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager,
if (!PrepareForParsing(diagnostic_manager, exe_ctx, /*for_completion*/ false))
return false;
- if (log)
- log->Printf("Parsing the following code:\n%s", m_transformed_text.c_str());
+ LLDB_LOGF(log, "Parsing the following code:\n%s", m_transformed_text.c_str());
////////////////////////////////////
// Set up the target and compiler
@@ -573,7 +598,7 @@ bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager,
// parser_sp will never be empty.
ClangExpressionParser parser(exe_scope, *this, generate_debug_info,
- m_include_directories);
+ m_include_directories, m_filename);
unsigned num_errors = parser.Parse(diagnostic_manager);
@@ -586,8 +611,11 @@ bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager,
size_t fixed_end;
const std::string &fixed_expression =
diagnostic_manager.GetFixedExpression();
- if (ClangExpressionSourceCode::GetOriginalBodyBounds(
- fixed_expression, m_expr_lang, fixed_start, fixed_end))
+ // Retrieve the original expression in case we don't have a top level
+ // expression (which has no surrounding source code).
+ if (m_source_code &&
+ m_source_code->GetOriginalBodyBounds(fixed_expression, m_expr_lang,
+ fixed_start, fixed_end))
m_fixed_text =
fixed_expression.substr(fixed_start, fixed_end - fixed_start);
}
@@ -648,12 +676,10 @@ bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager,
register_execution_unit = true;
}
- if (register_execution_unit) {
- llvm::cast<PersistentExpressionState>(
- exe_ctx.GetTargetPtr()->GetPersistentExpressionStateForLanguage(
- m_language))
+ if (register_execution_unit)
+ exe_ctx.GetTargetPtr()
+ ->GetPersistentExpressionStateForLanguage(m_language)
->RegisterExecutionUnit(m_execution_unit_sp);
- }
}
if (generate_debug_info) {
@@ -726,8 +752,7 @@ bool ClangUserExpression::Complete(ExecutionContext &exe_ctx,
if (!PrepareForParsing(diagnostic_manager, exe_ctx, /*for_completion*/ true))
return false;
- if (log)
- log->Printf("Parsing the following code:\n%s", m_transformed_text.c_str());
+ LLDB_LOGF(log, "Parsing the following code:\n%s", m_transformed_text.c_str());
//////////////////////////
// Parse the expression