The ClangExpressionDeclMap should be testable from a unit test. This is currently
impossible as they have both dependencies on Target/ExecutionContext from their
constructor. This patch allows constructing these classes without an active Target
and adds the missing tests for running without a target that we can do at least
a basic lookup test without crashing.
};
}
-ClangASTSource::ClangASTSource(const lldb::TargetSP &target)
+ClangASTSource::ClangASTSource(const lldb::TargetSP &target,
+ const lldb::ClangASTImporterSP &importer)
: m_import_in_progress(false), m_lookups_enabled(false), m_target(target),
m_ast_context(nullptr), m_active_lexical_decls(), m_active_lookups() {
- m_ast_importer_sp = m_target->GetClangASTImporter();
+ m_ast_importer_sp = importer;
}
void ClangASTSource::InstallASTContext(ClangASTContext &clang_ast_context,
}
ClangASTSource::~ClangASTSource() {
- if (m_ast_importer_sp)
- m_ast_importer_sp->ForgetDestination(m_ast_context);
+ if (!m_ast_importer_sp)
+ return;
+
+ m_ast_importer_sp->ForgetDestination(m_ast_context);
+ if (!m_target)
+ return;
// We are in the process of destruction, don't create clang ast context on
// demand by passing false to
// Target::GetScratchClangASTContext(create_on_demand).
if (IgnoreName(name, true))
return;
+ if (!m_target)
+ return;
+
if (module_sp && namespace_decl) {
CompilerDeclContext found_namespace_decl;
///
/// \param[in] target
/// A reference to the target containing debug information to use.
- ClangASTSource(const lldb::TargetSP &target);
+ ///
+ /// \param[in] importer
+ /// The ClangASTImporter to use.
+ ClangASTSource(const lldb::TargetSP &target,
+ const lldb::ClangASTImporterSP &importer);
/// Destructor
~ClangASTSource() override;
ClangExpressionDeclMap::ClangExpressionDeclMap(
bool keep_result_in_memory,
Materializer::PersistentVariableDelegate *result_delegate,
- ExecutionContext &exe_ctx, ValueObject *ctx_obj)
- : ClangASTSource(exe_ctx.GetTargetSP()), m_found_entities(),
- m_struct_members(), m_keep_result_in_memory(keep_result_in_memory),
+ const lldb::TargetSP &target, const lldb::ClangASTImporterSP &importer,
+ ValueObject *ctx_obj)
+ : ClangASTSource(target, importer), m_found_entities(), m_struct_members(),
+ m_keep_result_in_memory(keep_result_in_memory),
m_result_delegate(result_delegate), m_ctx_obj(ctx_obj), m_parser_vars(),
m_struct_vars() {
EnableStructVars();
const ConstString name,
unsigned int current_id) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
+ if (!m_parser_vars)
+ return;
Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr();
if (!target)
return;
NameSearchContext &context, ConstString name, unsigned current_id) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
+ if (!m_target)
+ return;
+
auto *modules_decl_vendor = m_target->GetClangModulesDeclVendor();
if (!modules_decl_vendor)
return;
ConstString name,
CompilerDeclContext &namespace_decl,
unsigned current_id) {
+ if (!m_parser_vars)
+ return;
Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr();
// Only look for functions by name out in our symbols if the function doesn't
// start with our phony prefix of '$'
- Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr();
- StackFrame *frame = m_parser_vars->m_exe_ctx.GetFramePtr();
+
+ Target *target = nullptr;
+ StackFrame *frame = nullptr;
SymbolContext sym_ctx;
+ if (m_parser_vars) {
+ target = m_parser_vars->m_exe_ctx.GetTargetPtr();
+ frame = m_parser_vars->m_exe_ctx.GetFramePtr();
+ }
if (frame != nullptr)
sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction |
lldb::eSymbolContextBlock);
/// If non-NULL, use this delegate to report result values. This
/// allows the client ClangUserExpression to report a result.
///
- /// \param[in] exe_ctx
- /// The execution context to use when parsing.
+ /// \param[in] target
+ /// The target to use when parsing.
+ ///
+ /// \param[in] importer
+ /// The ClangASTImporter to use when parsing.
///
/// \param[in] ctx_obj
/// If not empty, then expression is evaluated in context of this object.
ClangExpressionDeclMap(
bool keep_result_in_memory,
Materializer::PersistentVariableDelegate *result_delegate,
- ExecutionContext &exe_ctx,
+ const lldb::TargetSP &target, const lldb::ClangASTImporterSP &importer,
ValueObject *ctx_obj);
/// Destructor
Materializer::PersistentVariableDelegate &delegate,
bool keep_result_in_memory,
ValueObject *ctx_obj) {
- m_expr_decl_map_up.reset(
- new ClangExpressionDeclMap(keep_result_in_memory, &delegate, exe_ctx,
- ctx_obj));
+ m_expr_decl_map_up.reset(new ClangExpressionDeclMap(
+ keep_result_in_memory, &delegate, exe_ctx.GetTargetSP(),
+ exe_ctx.GetTargetRef().GetClangASTImporter(), ctx_obj));
}
clang::ASTConsumer *
void ClangUtilityFunction::ClangUtilityFunctionHelper::ResetDeclMap(
ExecutionContext &exe_ctx, bool keep_result_in_memory) {
- m_expr_decl_map_up.reset(
- new ClangExpressionDeclMap(keep_result_in_memory, nullptr, exe_ctx,
- nullptr));
+ m_expr_decl_map_up.reset(new ClangExpressionDeclMap(
+ keep_result_in_memory, nullptr, exe_ctx.GetTargetSP(),
+ exe_ctx.GetTargetRef().GetClangASTImporter(), nullptr));
}
} else if (target && target->IsValid()) {
std::shared_ptr<ClangASTContextForExpressions> ast_sp(
new ClangASTContextForExpressions(*target, fixed_arch));
- ast_sp->m_scratch_ast_source_up.reset(
- new ClangASTSource(target->shared_from_this()));
+ ast_sp->m_scratch_ast_source_up.reset(new ClangASTSource(
+ target->shared_from_this(), target->GetClangASTImporter()));
lldbassert(ast_sp->getFileManager());
ast_sp->m_scratch_ast_source_up->InstallASTContext(
*ast_sp, *ast_sp->getFileManager(), true);
add_lldb_unittest(ExpressionTests
ClangParserTest.cpp
+ ClangExpressionDeclMapTest.cpp
DiagnosticManagerTest.cpp
DWARFExpressionTest.cpp
CppModuleConfigurationTest.cpp
--- /dev/null
+//===-- ClangExpressionDeclMapTest.cpp ------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h"
+#include "TestingSupport/TestUtilities.h"
+#include "lldb/Host/FileSystem.h"
+#include "lldb/Host/HostInfo.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/lldb-defines.h"
+#include "gtest/gtest.h"
+
+using namespace lldb_private;
+using namespace lldb;
+
+namespace {
+struct ClangExpressionDeclMapTest : public testing::Test {
+ static void SetUpTestCase() {
+ FileSystem::Initialize();
+ HostInfo::Initialize();
+ }
+ static void TearDownTestCase() {
+ HostInfo::Terminate();
+ FileSystem::Terminate();
+ }
+
+ std::unique_ptr<ClangASTContext> createAST() {
+ return std::make_unique<ClangASTContext>(HostInfo::GetTargetTriple());
+ }
+
+ clang::DeclarationName getDeclarationName(ClangASTContext &ast,
+ llvm::StringRef name) {
+ clang::IdentifierInfo &II = ast.getIdentifierTable()->get(name);
+ return ast.getASTContext()->DeclarationNames.getIdentifier(&II);
+ }
+};
+} // namespace
+
+TEST_F(ClangExpressionDeclMapTest, TestIdentifierLookupInEmptyTU) {
+ ClangASTImporterSP importer = std::make_shared<ClangASTImporter>();
+ ClangExpressionDeclMap map(false, nullptr, lldb::TargetSP(), importer,
+ nullptr);
+
+ std::unique_ptr<ClangASTContext> ast = createAST();
+ map.InstallASTContext(*ast, *ast->getFileManager());
+
+ llvm::SmallVector<clang::NamedDecl *, 16> decls;
+ clang::DeclarationName name = getDeclarationName(*ast, "does_no_exist");
+ const clang::DeclContext *dc = ast->GetTranslationUnitDecl();
+
+ NameSearchContext search(map, decls, name, dc);
+ map.FindExternalVisibleDecls(search);
+
+ EXPECT_EQ(0U, decls.size());
+}