[lldb][NFC] Move utility functions from ClangASTImporter and ClangExpressionDeclMap to own header

This commit is contained in:
Raphael Isemann 2019-12-20 15:09:40 +01:00
parent 77e906ac78
commit aaa34bc0bd
4 changed files with 129 additions and 84 deletions

View File

@ -7,7 +7,7 @@
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h" #include "Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h"
#include "TestingSupport/TestUtilities.h" #include "TestingSupport/Symbol/ClangTestUtils.h"
#include "lldb/Host/FileSystem.h" #include "lldb/Host/FileSystem.h"
#include "lldb/Host/HostInfo.h" #include "lldb/Host/HostInfo.h"
#include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/ClangASTContext.h"
@ -78,7 +78,7 @@ struct ClangExpressionDeclMapTest : public testing::Test {
void SetUp() override { void SetUp() override {
importer = std::make_shared<ClangASTImporter>(); importer = std::make_shared<ClangASTImporter>();
decl_map = std::make_unique<FakeClangExpressionDeclMap>(importer); decl_map = std::make_unique<FakeClangExpressionDeclMap>(importer);
target_ast = createAST(); target_ast = clang_utils::createAST();
decl_map->InstallASTContext(*target_ast, *target_ast->getFileManager()); decl_map->InstallASTContext(*target_ast, *target_ast->getFileManager());
} }
@ -87,21 +87,6 @@ struct ClangExpressionDeclMapTest : public testing::Test {
decl_map.reset(); decl_map.reset();
target_ast.reset(); target_ast.reset();
} }
clang::DeclarationName getDeclarationName(ClangASTContext &ast,
llvm::StringRef name) {
clang::IdentifierInfo &II = ast.getIdentifierTable()->get(name);
return ast.getASTContext()->DeclarationNames.getIdentifier(&II);
}
CompilerType createRecord(ClangASTContext &ast, llvm::StringRef name) {
CompilerType t = ast.CreateRecordType(ast.getASTContext()->getTranslationUnitDecl(),
lldb::AccessType::eAccessPublic, name, 0,
lldb::LanguageType::eLanguageTypeC);
ClangASTContext::StartTagDeclarationDefinition(t);
ClangASTContext::CompleteTagDeclarationDefinition(t);
return t;
}
}; };
} // namespace } // namespace
@ -110,7 +95,8 @@ TEST_F(ClangExpressionDeclMapTest, TestUnknownIdentifierLookup) {
// Setup a NameSearchContext for 'foo'. // Setup a NameSearchContext for 'foo'.
llvm::SmallVector<clang::NamedDecl *, 16> decls; llvm::SmallVector<clang::NamedDecl *, 16> decls;
clang::DeclarationName name = getDeclarationName(*target_ast, "foo"); clang::DeclarationName name =
clang_utils::getDeclarationName(*target_ast, "foo");
const clang::DeclContext *dc = target_ast->GetTranslationUnitDecl(); const clang::DeclContext *dc = target_ast->GetTranslationUnitDecl();
NameSearchContext search(*decl_map, decls, name, dc); NameSearchContext search(*decl_map, decls, name, dc);
@ -127,12 +113,13 @@ TEST_F(ClangExpressionDeclMapTest, TestPersistentDeclLookup) {
// to the scratch AST context. // to the scratch AST context.
llvm::StringRef decl_name = "$persistent_class"; llvm::StringRef decl_name = "$persistent_class";
CompilerType persistent_type = CompilerType persistent_type =
createRecord(*decl_map->m_scratch_context, decl_name); clang_utils::createRecord(*decl_map->m_scratch_context, decl_name);
decl_map->AddPersistentDeclForTest(ClangUtil::GetAsTagDecl(persistent_type)); decl_map->AddPersistentDeclForTest(ClangUtil::GetAsTagDecl(persistent_type));
// Setup a NameSearchContext for $persistent_class; // Setup a NameSearchContext for $persistent_class;
llvm::SmallVector<clang::NamedDecl *, 16> decls; llvm::SmallVector<clang::NamedDecl *, 16> decls;
clang::DeclarationName name = getDeclarationName(*target_ast, decl_name); clang::DeclarationName name =
clang_utils::getDeclarationName(*target_ast, decl_name);
const clang::DeclContext *dc = target_ast->GetTranslationUnitDecl(); const clang::DeclContext *dc = target_ast->GetTranslationUnitDecl();
NameSearchContext search(*decl_map, decls, name, dc); NameSearchContext search(*decl_map, decls, name, dc);

View File

@ -8,6 +8,7 @@
#include "gtest/gtest.h" #include "gtest/gtest.h"
#include "TestingSupport/Symbol/ClangTestUtils.h"
#include "lldb/Host/FileSystem.h" #include "lldb/Host/FileSystem.h"
#include "lldb/Host/HostInfo.h" #include "lldb/Host/HostInfo.h"
#include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/ClangASTContext.h"
@ -73,22 +74,19 @@ TEST_F(TestClangASTImporter, ImportInvalidType) {
TEST_F(TestClangASTImporter, CopyDeclTagDecl) { TEST_F(TestClangASTImporter, CopyDeclTagDecl) {
// Tests that the ClangASTImporter::CopyDecl can copy TagDecls. // Tests that the ClangASTImporter::CopyDecl can copy TagDecls.
std::unique_ptr<ClangASTContext> source_ast = createAST(); clang_utils::SourceASTWithRecord source;
CompilerType source_type = createRecordWithField(
*source_ast, "Source",
source_ast->GetBasicType(lldb::BasicType::eBasicTypeChar), "a_field");
clang::TagDecl *source = ClangUtil::GetAsTagDecl(source_type);
std::unique_ptr<ClangASTContext> target_ast = createAST(); std::unique_ptr<ClangASTContext> target_ast = createAST();
ClangASTImporter importer; ClangASTImporter importer;
clang::Decl *imported = importer.CopyDecl( clang::Decl *imported =
target_ast->getASTContext(), source_ast->getASTContext(), source); importer.CopyDecl(target_ast->getASTContext(),
source.ast->getASTContext(), source.record_decl);
ASSERT_NE(nullptr, imported); ASSERT_NE(nullptr, imported);
// Check that we got the correct decl by just comparing their qualified name. // Check that we got the correct decl by just comparing their qualified name.
clang::TagDecl *imported_tag_decl = llvm::cast<clang::TagDecl>(imported); clang::TagDecl *imported_tag_decl = llvm::cast<clang::TagDecl>(imported);
EXPECT_EQ(source->getQualifiedNameAsString(), EXPECT_EQ(source.record_decl->getQualifiedNameAsString(),
imported_tag_decl->getQualifiedNameAsString()); imported_tag_decl->getQualifiedNameAsString());
// We did a minimal import of the tag decl. // We did a minimal import of the tag decl.
EXPECT_TRUE(imported_tag_decl->hasExternalLexicalStorage()); EXPECT_TRUE(imported_tag_decl->hasExternalLexicalStorage());
@ -96,27 +94,23 @@ TEST_F(TestClangASTImporter, CopyDeclTagDecl) {
// Check that origin was set for the imported declaration. // Check that origin was set for the imported declaration.
ClangASTImporter::DeclOrigin origin = importer.GetDeclOrigin(imported); ClangASTImporter::DeclOrigin origin = importer.GetDeclOrigin(imported);
EXPECT_TRUE(origin.Valid()); EXPECT_TRUE(origin.Valid());
EXPECT_EQ(origin.ctx, source_ast->getASTContext()); EXPECT_EQ(origin.ctx, source.ast->getASTContext());
EXPECT_EQ(origin.decl, source); EXPECT_EQ(origin.decl, source.record_decl);
} }
TEST_F(TestClangASTImporter, CopyTypeTagDecl) { TEST_F(TestClangASTImporter, CopyTypeTagDecl) {
// Tests that the ClangASTImporter::CopyType can copy TagDecls types. // Tests that the ClangASTImporter::CopyType can copy TagDecls types.
std::unique_ptr<ClangASTContext> source_ast = createAST(); clang_utils::SourceASTWithRecord source;
CompilerType source_type = createRecordWithField(
*source_ast, "Source",
source_ast->GetBasicType(lldb::BasicType::eBasicTypeChar), "a_field");
clang::TagDecl *source = ClangUtil::GetAsTagDecl(source_type);
std::unique_ptr<ClangASTContext> target_ast = createAST(); std::unique_ptr<ClangASTContext> target_ast = createAST();
ClangASTImporter importer; ClangASTImporter importer;
CompilerType imported = importer.CopyType(*target_ast, source_type); CompilerType imported = importer.CopyType(*target_ast, source.record_type);
ASSERT_TRUE(imported.IsValid()); ASSERT_TRUE(imported.IsValid());
// Check that we got the correct decl by just comparing their qualified name. // Check that we got the correct decl by just comparing their qualified name.
clang::TagDecl *imported_tag_decl = ClangUtil::GetAsTagDecl(imported); clang::TagDecl *imported_tag_decl = ClangUtil::GetAsTagDecl(imported);
EXPECT_EQ(source->getQualifiedNameAsString(), EXPECT_EQ(source.record_decl->getQualifiedNameAsString(),
imported_tag_decl->getQualifiedNameAsString()); imported_tag_decl->getQualifiedNameAsString());
// We did a minimal import of the tag decl. // We did a minimal import of the tag decl.
EXPECT_TRUE(imported_tag_decl->hasExternalLexicalStorage()); EXPECT_TRUE(imported_tag_decl->hasExternalLexicalStorage());
@ -125,28 +119,25 @@ TEST_F(TestClangASTImporter, CopyTypeTagDecl) {
ClangASTImporter::DeclOrigin origin = ClangASTImporter::DeclOrigin origin =
importer.GetDeclOrigin(imported_tag_decl); importer.GetDeclOrigin(imported_tag_decl);
EXPECT_TRUE(origin.Valid()); EXPECT_TRUE(origin.Valid());
EXPECT_EQ(origin.ctx, source_ast->getASTContext()); EXPECT_EQ(origin.ctx, source.ast->getASTContext());
EXPECT_EQ(origin.decl, source); EXPECT_EQ(origin.decl, source.record_decl);
} }
TEST_F(TestClangASTImporter, DeportDeclTagDecl) { TEST_F(TestClangASTImporter, DeportDeclTagDecl) {
// Tests that the ClangASTImporter::DeportDecl completely copies TagDecls. // Tests that the ClangASTImporter::DeportDecl completely copies TagDecls.
std::unique_ptr<ClangASTContext> source_ast = createAST(); clang_utils::SourceASTWithRecord source;
CompilerType source_type = createRecordWithField(
*source_ast, "Source",
source_ast->GetBasicType(lldb::BasicType::eBasicTypeChar), "a_field");
clang::TagDecl *source = ClangUtil::GetAsTagDecl(source_type);
std::unique_ptr<ClangASTContext> target_ast = createAST(); std::unique_ptr<ClangASTContext> target_ast = createAST();
ClangASTImporter importer; ClangASTImporter importer;
clang::Decl *imported = importer.DeportDecl( clang::Decl *imported =
target_ast->getASTContext(), source_ast->getASTContext(), source); importer.DeportDecl(target_ast->getASTContext(),
source.ast->getASTContext(), source.record_decl);
ASSERT_NE(nullptr, imported); ASSERT_NE(nullptr, imported);
// Check that we got the correct decl by just comparing their qualified name. // Check that we got the correct decl by just comparing their qualified name.
clang::TagDecl *imported_tag_decl = llvm::cast<clang::TagDecl>(imported); clang::TagDecl *imported_tag_decl = llvm::cast<clang::TagDecl>(imported);
EXPECT_EQ(source->getQualifiedNameAsString(), EXPECT_EQ(source.record_decl->getQualifiedNameAsString(),
imported_tag_decl->getQualifiedNameAsString()); imported_tag_decl->getQualifiedNameAsString());
// The record should be completed as we deported it. // The record should be completed as we deported it.
EXPECT_FALSE(imported_tag_decl->hasExternalLexicalStorage()); EXPECT_FALSE(imported_tag_decl->hasExternalLexicalStorage());
@ -157,21 +148,17 @@ TEST_F(TestClangASTImporter, DeportDeclTagDecl) {
TEST_F(TestClangASTImporter, DeportTypeTagDecl) { TEST_F(TestClangASTImporter, DeportTypeTagDecl) {
// Tests that the ClangASTImporter::CopyType can deport TagDecl types. // Tests that the ClangASTImporter::CopyType can deport TagDecl types.
std::unique_ptr<ClangASTContext> source_ast = createAST(); clang_utils::SourceASTWithRecord source;
CompilerType source_type = createRecordWithField(
*source_ast, "Source",
source_ast->GetBasicType(lldb::BasicType::eBasicTypeChar), "a_field");
clang::TagDecl *source = ClangUtil::GetAsTagDecl(source_type);
std::unique_ptr<ClangASTContext> target_ast = createAST(); std::unique_ptr<ClangASTContext> target_ast = createAST();
ClangASTImporter importer; ClangASTImporter importer;
CompilerType imported = importer.DeportType(*target_ast, source_type); CompilerType imported = importer.DeportType(*target_ast, source.record_type);
ASSERT_TRUE(imported.IsValid()); ASSERT_TRUE(imported.IsValid());
// Check that we got the correct decl by just comparing their qualified name. // Check that we got the correct decl by just comparing their qualified name.
clang::TagDecl *imported_tag_decl = ClangUtil::GetAsTagDecl(imported); clang::TagDecl *imported_tag_decl = ClangUtil::GetAsTagDecl(imported);
EXPECT_EQ(source->getQualifiedNameAsString(), EXPECT_EQ(source.record_decl->getQualifiedNameAsString(),
imported_tag_decl->getQualifiedNameAsString()); imported_tag_decl->getQualifiedNameAsString());
// The record should be completed as we deported it. // The record should be completed as we deported it.
EXPECT_FALSE(imported_tag_decl->hasExternalLexicalStorage()); EXPECT_FALSE(imported_tag_decl->hasExternalLexicalStorage());
@ -183,17 +170,17 @@ TEST_F(TestClangASTImporter, DeportTypeTagDecl) {
TEST_F(TestClangASTImporter, MetadataPropagation) { TEST_F(TestClangASTImporter, MetadataPropagation) {
// Tests that AST metadata is propagated when copying declarations. // Tests that AST metadata is propagated when copying declarations.
std::unique_ptr<ClangASTContext> source_ast = createAST(); clang_utils::SourceASTWithRecord source;
CompilerType source_type = createRecord(*source_ast, "Source");
clang::TagDecl *source = ClangUtil::GetAsTagDecl(source_type);
const lldb::user_id_t metadata = 123456; const lldb::user_id_t metadata = 123456;
source_ast->SetMetadataAsUserID(source, metadata); source.ast->SetMetadataAsUserID(source.record_decl, metadata);
std::unique_ptr<ClangASTContext> target_ast = createAST(); std::unique_ptr<ClangASTContext> target_ast = createAST();
ClangASTImporter importer; ClangASTImporter importer;
clang::Decl *imported = importer.CopyDecl( clang::Decl *imported =
target_ast->getASTContext(), source_ast->getASTContext(), source); importer.CopyDecl(target_ast->getASTContext(),
source.ast->getASTContext(), source.record_decl);
ASSERT_NE(nullptr, imported); ASSERT_NE(nullptr, imported);
// Check that we got the same Metadata. // Check that we got the same Metadata.
@ -206,17 +193,17 @@ TEST_F(TestClangASTImporter, MetadataPropagationIndirectImport) {
// importing one declaration into a temporary context and then to the // importing one declaration into a temporary context and then to the
// actual destination context. // actual destination context.
std::unique_ptr<ClangASTContext> source_ast = createAST(); clang_utils::SourceASTWithRecord source;
CompilerType source_type = createRecord(*source_ast, "Source");
clang::TagDecl *source = ClangUtil::GetAsTagDecl(source_type);
const lldb::user_id_t metadata = 123456; const lldb::user_id_t metadata = 123456;
source_ast->SetMetadataAsUserID(source, metadata); source.ast->SetMetadataAsUserID(source.record_decl, metadata);
std::unique_ptr<ClangASTContext> temporary_ast = createAST(); std::unique_ptr<ClangASTContext> temporary_ast = createAST();
ClangASTImporter importer; ClangASTImporter importer;
clang::Decl *temporary_imported = importer.CopyDecl( clang::Decl *temporary_imported =
temporary_ast->getASTContext(), source_ast->getASTContext(), source); importer.CopyDecl(temporary_ast->getASTContext(),
source.ast->getASTContext(), source.record_decl);
ASSERT_NE(nullptr, temporary_imported); ASSERT_NE(nullptr, temporary_imported);
std::unique_ptr<ClangASTContext> target_ast = createAST(); std::unique_ptr<ClangASTContext> target_ast = createAST();
@ -234,21 +221,20 @@ TEST_F(TestClangASTImporter, MetadataPropagationAfterCopying) {
// Tests that AST metadata is propagated when copying declarations even // Tests that AST metadata is propagated when copying declarations even
// when the metadata was set after the declaration has already been copied. // when the metadata was set after the declaration has already been copied.
std::unique_ptr<ClangASTContext> source_ast = createAST(); clang_utils::SourceASTWithRecord source;
CompilerType source_type = createRecord(*source_ast, "Source");
clang::TagDecl *source = ClangUtil::GetAsTagDecl(source_type);
const lldb::user_id_t metadata = 123456; const lldb::user_id_t metadata = 123456;
std::unique_ptr<ClangASTContext> target_ast = createAST(); std::unique_ptr<ClangASTContext> target_ast = createAST();
ClangASTImporter importer; ClangASTImporter importer;
clang::Decl *imported = importer.CopyDecl( clang::Decl *imported =
target_ast->getASTContext(), source_ast->getASTContext(), source); importer.CopyDecl(target_ast->getASTContext(),
source.ast->getASTContext(), source.record_decl);
ASSERT_NE(nullptr, imported); ASSERT_NE(nullptr, imported);
// The TagDecl has been imported. Now set the metadata of the source and // The TagDecl has been imported. Now set the metadata of the source and
// make sure the imported one will directly see it. // make sure the imported one will directly see it.
source_ast->SetMetadataAsUserID(source, metadata); source.ast->SetMetadataAsUserID(source.record_decl, metadata);
// Check that we got the same Metadata. // Check that we got the same Metadata.
ASSERT_NE(nullptr, importer.GetDeclMetadata(imported)); ASSERT_NE(nullptr, importer.GetDeclMetadata(imported));
@ -259,33 +245,27 @@ TEST_F(TestClangASTImporter, RecordLayout) {
// Test that it is possible to register RecordDecl layouts and then later // Test that it is possible to register RecordDecl layouts and then later
// correctly retrieve them. // correctly retrieve them.
std::unique_ptr<ClangASTContext> source_ast = createAST(); clang_utils::SourceASTWithRecord source;
CompilerType source_type = createRecordWithField(
*source_ast, "Source",
source_ast->GetBasicType(lldb::BasicType::eBasicTypeChar), "a_field");
clang::TagDecl *source_tag = ClangUtil::GetAsTagDecl(source_type);
clang::RecordDecl *source_record = llvm::cast<clang::RecordDecl>(source_tag);
ClangASTImporter importer; ClangASTImporter importer;
ClangASTImporter::LayoutInfo layout_info; ClangASTImporter::LayoutInfo layout_info;
layout_info.bit_size = 15; layout_info.bit_size = 15;
layout_info.alignment = 2; layout_info.alignment = 2;
layout_info.field_offsets[*source_record->fields().begin()] = 1; layout_info.field_offsets[source.field_decl] = 1;
importer.SetRecordLayout(source_record, layout_info); importer.SetRecordLayout(source.record_decl, layout_info);
uint64_t bit_size; uint64_t bit_size;
uint64_t alignment; uint64_t alignment;
llvm::DenseMap<const clang::FieldDecl *, uint64_t> field_offsets; llvm::DenseMap<const clang::FieldDecl *, uint64_t> field_offsets;
llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> base_offsets; llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> base_offsets;
llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> vbase_offsets; llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> vbase_offsets;
importer.LayoutRecordType(source_record, bit_size, alignment, field_offsets, importer.LayoutRecordType(source.record_decl, bit_size, alignment,
base_offsets, vbase_offsets); field_offsets, base_offsets, vbase_offsets);
EXPECT_EQ(15U, bit_size); EXPECT_EQ(15U, bit_size);
EXPECT_EQ(2U, alignment); EXPECT_EQ(2U, alignment);
EXPECT_EQ(1U, field_offsets.size()); EXPECT_EQ(1U, field_offsets.size());
EXPECT_EQ(1U, field_offsets[*source_record->fields().begin()]); EXPECT_EQ(1U, field_offsets[source.field_decl]);
EXPECT_EQ(0U, base_offsets.size()); EXPECT_EQ(0U, base_offsets.size());
EXPECT_EQ(0U, vbase_offsets.size()); EXPECT_EQ(0U, vbase_offsets.size());
} }

View File

@ -0,0 +1,73 @@
//===- ClangTestUtils.h -----------------------------------------*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//
#ifndef LLDB_UNITTESTS_TESTINGSUPPORT_SYMBOL_CLANGTESTUTILS_H
#define LLDB_UNITTESTS_TESTINGSUPPORT_SYMBOL_CLANGTESTUTILS_H
#include "lldb/Host/HostInfo.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/ClangUtil.h"
namespace lldb_private {
namespace clang_utils {
inline clang::DeclarationName getDeclarationName(ClangASTContext &ast,
llvm::StringRef name) {
clang::IdentifierInfo &II = ast.getIdentifierTable()->get(name);
return ast.getASTContext()->DeclarationNames.getIdentifier(&II);
}
inline std::unique_ptr<ClangASTContext> createAST() {
return std::make_unique<ClangASTContext>(HostInfo::GetTargetTriple());
}
inline CompilerType createRecord(ClangASTContext &ast, llvm::StringRef name) {
return ast.CreateRecordType(ast.getASTContext()->getTranslationUnitDecl(),
lldb::AccessType::eAccessPublic, name, 0,
lldb::LanguageType::eLanguageTypeC);
}
/// Create a record with the given name and a field with the given type
/// and name.
inline CompilerType createRecordWithField(ClangASTContext &ast,
llvm::StringRef record_name,
CompilerType field_type,
llvm::StringRef field_name) {
CompilerType t = createRecord(ast, record_name);
ClangASTContext::StartTagDeclarationDefinition(t);
ast.AddFieldToRecordType(t, field_name, field_type,
lldb::AccessType::eAccessPublic, 7);
ClangASTContext::CompleteTagDeclarationDefinition(t);
return t;
}
/// Constructs a ClangASTContext that contains a single RecordDecl that contains
/// a single FieldDecl. Utility class as this setup is a common starting point
/// for unit test that exercise the ASTImporter.
struct SourceASTWithRecord {
std::unique_ptr<ClangASTContext> ast;
CompilerType record_type;
clang::RecordDecl *record_decl = nullptr;
clang::FieldDecl *field_decl = nullptr;
SourceASTWithRecord() {
ast = createAST();
record_type = createRecordWithField(
*ast, "Source", ast->GetBasicType(lldb::BasicType::eBasicTypeChar),
"a_field");
record_decl =
llvm::cast<clang::RecordDecl>(ClangUtil::GetAsTagDecl(record_type));
field_decl = *record_decl->fields().begin();
assert(field_decl);
}
};
} // namespace clang_utils
} // namespace lldb_private
#endif

View File

@ -9,3 +9,8 @@ module lldb_TestingSupport_Host {
requires cplusplus requires cplusplus
module NativeProcessTestUtils { header "Host/NativeProcessTestUtils.h" export * } module NativeProcessTestUtils { header "Host/NativeProcessTestUtils.h" export * }
} }
module lldb_TestingSupport_Symbol {
requires cplusplus
module ClangTestUtils { header "Symbol/ClangTestUtils.h" export * }
}