From aaa34bc0bd1aeb7271ba0ce2c4f3dfba5dbae8e2 Mon Sep 17 00:00:00 2001 From: Raphael Isemann Date: Fri, 20 Dec 2019 15:09:40 +0100 Subject: [PATCH] [lldb][NFC] Move utility functions from ClangASTImporter and ClangExpressionDeclMap to own header --- .../Expression/ClangExpressionDeclMapTest.cpp | 27 ++--- .../unittests/Symbol/TestClangASTImporter.cpp | 108 +++++++----------- .../TestingSupport/Symbol/ClangTestUtils.h | 73 ++++++++++++ .../unittests/TestingSupport/module.modulemap | 5 + 4 files changed, 129 insertions(+), 84 deletions(-) create mode 100644 lldb/unittests/TestingSupport/Symbol/ClangTestUtils.h diff --git a/lldb/unittests/Expression/ClangExpressionDeclMapTest.cpp b/lldb/unittests/Expression/ClangExpressionDeclMapTest.cpp index 6fac168462b3..36d45fe5a58f 100644 --- a/lldb/unittests/Expression/ClangExpressionDeclMapTest.cpp +++ b/lldb/unittests/Expression/ClangExpressionDeclMapTest.cpp @@ -7,7 +7,7 @@ //===----------------------------------------------------------------------===// #include "Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h" -#include "TestingSupport/TestUtilities.h" +#include "TestingSupport/Symbol/ClangTestUtils.h" #include "lldb/Host/FileSystem.h" #include "lldb/Host/HostInfo.h" #include "lldb/Symbol/ClangASTContext.h" @@ -78,7 +78,7 @@ struct ClangExpressionDeclMapTest : public testing::Test { void SetUp() override { importer = std::make_shared(); decl_map = std::make_unique(importer); - target_ast = createAST(); + target_ast = clang_utils::createAST(); decl_map->InstallASTContext(*target_ast, *target_ast->getFileManager()); } @@ -87,21 +87,6 @@ struct ClangExpressionDeclMapTest : public testing::Test { decl_map.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 @@ -110,7 +95,8 @@ TEST_F(ClangExpressionDeclMapTest, TestUnknownIdentifierLookup) { // Setup a NameSearchContext for 'foo'. llvm::SmallVector decls; - clang::DeclarationName name = getDeclarationName(*target_ast, "foo"); + clang::DeclarationName name = + clang_utils::getDeclarationName(*target_ast, "foo"); const clang::DeclContext *dc = target_ast->GetTranslationUnitDecl(); NameSearchContext search(*decl_map, decls, name, dc); @@ -127,12 +113,13 @@ TEST_F(ClangExpressionDeclMapTest, TestPersistentDeclLookup) { // to the scratch AST context. llvm::StringRef decl_name = "$persistent_class"; 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)); // Setup a NameSearchContext for $persistent_class; llvm::SmallVector 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(); NameSearchContext search(*decl_map, decls, name, dc); diff --git a/lldb/unittests/Symbol/TestClangASTImporter.cpp b/lldb/unittests/Symbol/TestClangASTImporter.cpp index 11749a4189c3..126484e8d047 100644 --- a/lldb/unittests/Symbol/TestClangASTImporter.cpp +++ b/lldb/unittests/Symbol/TestClangASTImporter.cpp @@ -8,6 +8,7 @@ #include "gtest/gtest.h" +#include "TestingSupport/Symbol/ClangTestUtils.h" #include "lldb/Host/FileSystem.h" #include "lldb/Host/HostInfo.h" #include "lldb/Symbol/ClangASTContext.h" @@ -73,22 +74,19 @@ TEST_F(TestClangASTImporter, ImportInvalidType) { TEST_F(TestClangASTImporter, CopyDeclTagDecl) { // Tests that the ClangASTImporter::CopyDecl can copy TagDecls. - std::unique_ptr source_ast = createAST(); - CompilerType source_type = createRecordWithField( - *source_ast, "Source", - source_ast->GetBasicType(lldb::BasicType::eBasicTypeChar), "a_field"); - clang::TagDecl *source = ClangUtil::GetAsTagDecl(source_type); + clang_utils::SourceASTWithRecord source; std::unique_ptr target_ast = createAST(); ClangASTImporter importer; - clang::Decl *imported = importer.CopyDecl( - target_ast->getASTContext(), source_ast->getASTContext(), source); + clang::Decl *imported = + importer.CopyDecl(target_ast->getASTContext(), + source.ast->getASTContext(), source.record_decl); ASSERT_NE(nullptr, imported); // Check that we got the correct decl by just comparing their qualified name. clang::TagDecl *imported_tag_decl = llvm::cast(imported); - EXPECT_EQ(source->getQualifiedNameAsString(), + EXPECT_EQ(source.record_decl->getQualifiedNameAsString(), imported_tag_decl->getQualifiedNameAsString()); // We did a minimal import of the tag decl. EXPECT_TRUE(imported_tag_decl->hasExternalLexicalStorage()); @@ -96,27 +94,23 @@ TEST_F(TestClangASTImporter, CopyDeclTagDecl) { // Check that origin was set for the imported declaration. ClangASTImporter::DeclOrigin origin = importer.GetDeclOrigin(imported); EXPECT_TRUE(origin.Valid()); - EXPECT_EQ(origin.ctx, source_ast->getASTContext()); - EXPECT_EQ(origin.decl, source); + EXPECT_EQ(origin.ctx, source.ast->getASTContext()); + EXPECT_EQ(origin.decl, source.record_decl); } TEST_F(TestClangASTImporter, CopyTypeTagDecl) { // Tests that the ClangASTImporter::CopyType can copy TagDecls types. - std::unique_ptr source_ast = createAST(); - CompilerType source_type = createRecordWithField( - *source_ast, "Source", - source_ast->GetBasicType(lldb::BasicType::eBasicTypeChar), "a_field"); - clang::TagDecl *source = ClangUtil::GetAsTagDecl(source_type); + clang_utils::SourceASTWithRecord source; std::unique_ptr target_ast = createAST(); ClangASTImporter importer; - CompilerType imported = importer.CopyType(*target_ast, source_type); + CompilerType imported = importer.CopyType(*target_ast, source.record_type); ASSERT_TRUE(imported.IsValid()); // Check that we got the correct decl by just comparing their qualified name. clang::TagDecl *imported_tag_decl = ClangUtil::GetAsTagDecl(imported); - EXPECT_EQ(source->getQualifiedNameAsString(), + EXPECT_EQ(source.record_decl->getQualifiedNameAsString(), imported_tag_decl->getQualifiedNameAsString()); // We did a minimal import of the tag decl. EXPECT_TRUE(imported_tag_decl->hasExternalLexicalStorage()); @@ -125,28 +119,25 @@ TEST_F(TestClangASTImporter, CopyTypeTagDecl) { ClangASTImporter::DeclOrigin origin = importer.GetDeclOrigin(imported_tag_decl); EXPECT_TRUE(origin.Valid()); - EXPECT_EQ(origin.ctx, source_ast->getASTContext()); - EXPECT_EQ(origin.decl, source); + EXPECT_EQ(origin.ctx, source.ast->getASTContext()); + EXPECT_EQ(origin.decl, source.record_decl); } TEST_F(TestClangASTImporter, DeportDeclTagDecl) { // Tests that the ClangASTImporter::DeportDecl completely copies TagDecls. - std::unique_ptr source_ast = createAST(); - CompilerType source_type = createRecordWithField( - *source_ast, "Source", - source_ast->GetBasicType(lldb::BasicType::eBasicTypeChar), "a_field"); - clang::TagDecl *source = ClangUtil::GetAsTagDecl(source_type); + clang_utils::SourceASTWithRecord source; std::unique_ptr target_ast = createAST(); ClangASTImporter importer; - clang::Decl *imported = importer.DeportDecl( - target_ast->getASTContext(), source_ast->getASTContext(), source); + clang::Decl *imported = + importer.DeportDecl(target_ast->getASTContext(), + source.ast->getASTContext(), source.record_decl); ASSERT_NE(nullptr, imported); // Check that we got the correct decl by just comparing their qualified name. clang::TagDecl *imported_tag_decl = llvm::cast(imported); - EXPECT_EQ(source->getQualifiedNameAsString(), + EXPECT_EQ(source.record_decl->getQualifiedNameAsString(), imported_tag_decl->getQualifiedNameAsString()); // The record should be completed as we deported it. EXPECT_FALSE(imported_tag_decl->hasExternalLexicalStorage()); @@ -157,21 +148,17 @@ TEST_F(TestClangASTImporter, DeportDeclTagDecl) { TEST_F(TestClangASTImporter, DeportTypeTagDecl) { // Tests that the ClangASTImporter::CopyType can deport TagDecl types. - std::unique_ptr source_ast = createAST(); - CompilerType source_type = createRecordWithField( - *source_ast, "Source", - source_ast->GetBasicType(lldb::BasicType::eBasicTypeChar), "a_field"); - clang::TagDecl *source = ClangUtil::GetAsTagDecl(source_type); + clang_utils::SourceASTWithRecord source; std::unique_ptr target_ast = createAST(); ClangASTImporter importer; - CompilerType imported = importer.DeportType(*target_ast, source_type); + CompilerType imported = importer.DeportType(*target_ast, source.record_type); ASSERT_TRUE(imported.IsValid()); // Check that we got the correct decl by just comparing their qualified name. clang::TagDecl *imported_tag_decl = ClangUtil::GetAsTagDecl(imported); - EXPECT_EQ(source->getQualifiedNameAsString(), + EXPECT_EQ(source.record_decl->getQualifiedNameAsString(), imported_tag_decl->getQualifiedNameAsString()); // The record should be completed as we deported it. EXPECT_FALSE(imported_tag_decl->hasExternalLexicalStorage()); @@ -183,17 +170,17 @@ TEST_F(TestClangASTImporter, DeportTypeTagDecl) { TEST_F(TestClangASTImporter, MetadataPropagation) { // Tests that AST metadata is propagated when copying declarations. - std::unique_ptr source_ast = createAST(); - CompilerType source_type = createRecord(*source_ast, "Source"); - clang::TagDecl *source = ClangUtil::GetAsTagDecl(source_type); + clang_utils::SourceASTWithRecord source; + const lldb::user_id_t metadata = 123456; - source_ast->SetMetadataAsUserID(source, metadata); + source.ast->SetMetadataAsUserID(source.record_decl, metadata); std::unique_ptr target_ast = createAST(); ClangASTImporter importer; - clang::Decl *imported = importer.CopyDecl( - target_ast->getASTContext(), source_ast->getASTContext(), source); + clang::Decl *imported = + importer.CopyDecl(target_ast->getASTContext(), + source.ast->getASTContext(), source.record_decl); ASSERT_NE(nullptr, imported); // 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 // actual destination context. - std::unique_ptr source_ast = createAST(); - CompilerType source_type = createRecord(*source_ast, "Source"); - clang::TagDecl *source = ClangUtil::GetAsTagDecl(source_type); + clang_utils::SourceASTWithRecord source; + const lldb::user_id_t metadata = 123456; - source_ast->SetMetadataAsUserID(source, metadata); + source.ast->SetMetadataAsUserID(source.record_decl, metadata); std::unique_ptr temporary_ast = createAST(); ClangASTImporter importer; - clang::Decl *temporary_imported = importer.CopyDecl( - temporary_ast->getASTContext(), source_ast->getASTContext(), source); + clang::Decl *temporary_imported = + importer.CopyDecl(temporary_ast->getASTContext(), + source.ast->getASTContext(), source.record_decl); ASSERT_NE(nullptr, temporary_imported); std::unique_ptr target_ast = createAST(); @@ -234,21 +221,20 @@ TEST_F(TestClangASTImporter, MetadataPropagationAfterCopying) { // Tests that AST metadata is propagated when copying declarations even // when the metadata was set after the declaration has already been copied. - std::unique_ptr source_ast = createAST(); - CompilerType source_type = createRecord(*source_ast, "Source"); - clang::TagDecl *source = ClangUtil::GetAsTagDecl(source_type); + clang_utils::SourceASTWithRecord source; const lldb::user_id_t metadata = 123456; std::unique_ptr target_ast = createAST(); ClangASTImporter importer; - clang::Decl *imported = importer.CopyDecl( - target_ast->getASTContext(), source_ast->getASTContext(), source); + clang::Decl *imported = + importer.CopyDecl(target_ast->getASTContext(), + source.ast->getASTContext(), source.record_decl); ASSERT_NE(nullptr, imported); // The TagDecl has been imported. Now set the metadata of the source and // 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. 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 // correctly retrieve them. - std::unique_ptr source_ast = createAST(); - 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(source_tag); + clang_utils::SourceASTWithRecord source; ClangASTImporter importer; ClangASTImporter::LayoutInfo layout_info; layout_info.bit_size = 15; layout_info.alignment = 2; - layout_info.field_offsets[*source_record->fields().begin()] = 1; - importer.SetRecordLayout(source_record, layout_info); + layout_info.field_offsets[source.field_decl] = 1; + importer.SetRecordLayout(source.record_decl, layout_info); uint64_t bit_size; uint64_t alignment; llvm::DenseMap field_offsets; llvm::DenseMap base_offsets; llvm::DenseMap vbase_offsets; - importer.LayoutRecordType(source_record, bit_size, alignment, field_offsets, - base_offsets, vbase_offsets); + importer.LayoutRecordType(source.record_decl, bit_size, alignment, + field_offsets, base_offsets, vbase_offsets); EXPECT_EQ(15U, bit_size); EXPECT_EQ(2U, alignment); 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, vbase_offsets.size()); } diff --git a/lldb/unittests/TestingSupport/Symbol/ClangTestUtils.h b/lldb/unittests/TestingSupport/Symbol/ClangTestUtils.h new file mode 100644 index 000000000000..b1b1f30e2f6d --- /dev/null +++ b/lldb/unittests/TestingSupport/Symbol/ClangTestUtils.h @@ -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 createAST() { + return std::make_unique(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 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(ClangUtil::GetAsTagDecl(record_type)); + field_decl = *record_decl->fields().begin(); + assert(field_decl); + } +}; + +} // namespace clang_utils +} // namespace lldb_private + +#endif diff --git a/lldb/unittests/TestingSupport/module.modulemap b/lldb/unittests/TestingSupport/module.modulemap index 542c0b11c78f..b73ac2793278 100644 --- a/lldb/unittests/TestingSupport/module.modulemap +++ b/lldb/unittests/TestingSupport/module.modulemap @@ -9,3 +9,8 @@ module lldb_TestingSupport_Host { requires cplusplus module NativeProcessTestUtils { header "Host/NativeProcessTestUtils.h" export * } } + +module lldb_TestingSupport_Symbol { + requires cplusplus + module ClangTestUtils { header "Symbol/ClangTestUtils.h" export * } +}