14aee81c4SRaphael Isemann //===-- ClangExpressionDeclMapTest.cpp ------------------------------------===//
24aee81c4SRaphael Isemann //
34aee81c4SRaphael Isemann // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44aee81c4SRaphael Isemann // See https://llvm.org/LICENSE.txt for license information.
54aee81c4SRaphael Isemann // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
64aee81c4SRaphael Isemann //
74aee81c4SRaphael Isemann //===----------------------------------------------------------------------===//
84aee81c4SRaphael Isemann
94aee81c4SRaphael Isemann #include "Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h"
108be30215SAlex Langford #include "Plugins/ExpressionParser/Clang/ClangUtil.h"
118be30215SAlex Langford #include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
125dca0596SRaphael Isemann #include "TestingSupport/SubsystemRAII.h"
13aaa34bc0SRaphael Isemann #include "TestingSupport/Symbol/ClangTestUtils.h"
144aee81c4SRaphael Isemann #include "lldb/Host/FileSystem.h"
154aee81c4SRaphael Isemann #include "lldb/Host/HostInfo.h"
164aee81c4SRaphael Isemann #include "lldb/lldb-defines.h"
174aee81c4SRaphael Isemann #include "gtest/gtest.h"
184aee81c4SRaphael Isemann
194aee81c4SRaphael Isemann using namespace lldb_private;
204aee81c4SRaphael Isemann using namespace lldb;
214aee81c4SRaphael Isemann
22d8a31949SRaphael Isemann namespace {
23d8a31949SRaphael Isemann struct FakeClangExpressionDeclMap : public ClangExpressionDeclMap {
FakeClangExpressionDeclMap__anonf62ad2c90111::FakeClangExpressionDeclMap247c9ebdd3SAlex Langford FakeClangExpressionDeclMap(const std::shared_ptr<ClangASTImporter> &importer)
25d8a31949SRaphael Isemann : ClangExpressionDeclMap(false, nullptr, lldb::TargetSP(), importer,
26d8a31949SRaphael Isemann nullptr) {
276be76f49SRaphael Isemann m_scratch_context = clang_utils::createAST();
28d8a31949SRaphael Isemann }
296e3b0cc2SRaphael Isemann std::unique_ptr<TypeSystemClang> m_scratch_context;
30d8a31949SRaphael Isemann /// Adds a persistent decl that can be found by the ClangExpressionDeclMap
31d8a31949SRaphael Isemann /// via GetPersistentDecl.
AddPersistentDeclForTest__anonf62ad2c90111::FakeClangExpressionDeclMap32d8a31949SRaphael Isemann void AddPersistentDeclForTest(clang::NamedDecl *d) {
33d8a31949SRaphael Isemann // The declaration needs to have '$' prefix in its name like every
34d8a31949SRaphael Isemann // persistent declaration and must be inside the scratch AST context.
35d8a31949SRaphael Isemann assert(d);
36d8a31949SRaphael Isemann assert(d->getName().startswith("$"));
37f9f49d35SRaphael Isemann assert(&d->getASTContext() == &m_scratch_context->getASTContext());
38d8a31949SRaphael Isemann m_persistent_decls[d->getName()] = d;
39d8a31949SRaphael Isemann }
40d8a31949SRaphael Isemann
41d8a31949SRaphael Isemann protected:
42d8a31949SRaphael Isemann // ClangExpressionDeclMap hooks.
43d8a31949SRaphael Isemann
GetPersistentDecl__anonf62ad2c90111::FakeClangExpressionDeclMap44d8a31949SRaphael Isemann clang::NamedDecl *GetPersistentDecl(ConstString name) override {
45d8a31949SRaphael Isemann // ClangExpressionDeclMap wants to know if there is a persistent decl
46d8a31949SRaphael Isemann // with the given name. Check the
47d8a31949SRaphael Isemann return m_persistent_decls.lookup(name.GetStringRef());
48d8a31949SRaphael Isemann }
49d8a31949SRaphael Isemann
50d8a31949SRaphael Isemann private:
51d8a31949SRaphael Isemann /// The persistent decls in this test with their names as keys.
52d8a31949SRaphael Isemann llvm::DenseMap<llvm::StringRef, clang::NamedDecl *> m_persistent_decls;
53d8a31949SRaphael Isemann };
54d8a31949SRaphael Isemann } // namespace
55d8a31949SRaphael Isemann
564aee81c4SRaphael Isemann namespace {
574aee81c4SRaphael Isemann struct ClangExpressionDeclMapTest : public testing::Test {
585dca0596SRaphael Isemann SubsystemRAII<FileSystem, HostInfo> subsystems;
594aee81c4SRaphael Isemann
60d8a31949SRaphael Isemann /// The ClangASTImporter used during the test.
617c9ebdd3SAlex Langford std::shared_ptr<ClangASTImporter> importer;
62d8a31949SRaphael Isemann /// The ExpressionDeclMap for the current test case.
63d8a31949SRaphael Isemann std::unique_ptr<FakeClangExpressionDeclMap> decl_map;
64d8a31949SRaphael Isemann
65d8a31949SRaphael Isemann /// The target AST that lookup results should be imported to.
666e3b0cc2SRaphael Isemann std::unique_ptr<TypeSystemClang> target_ast;
67d8a31949SRaphael Isemann
SetUp__anonf62ad2c90211::ClangExpressionDeclMapTest68d8a31949SRaphael Isemann void SetUp() override {
69d8a31949SRaphael Isemann importer = std::make_shared<ClangASTImporter>();
70d8a31949SRaphael Isemann decl_map = std::make_unique<FakeClangExpressionDeclMap>(importer);
71aaa34bc0SRaphael Isemann target_ast = clang_utils::createAST();
7249b206f9SRaphael Isemann decl_map->InstallASTContext(*target_ast);
73d8a31949SRaphael Isemann }
74d8a31949SRaphael Isemann
TearDown__anonf62ad2c90211::ClangExpressionDeclMapTest75d8a31949SRaphael Isemann void TearDown() override {
76d8a31949SRaphael Isemann importer.reset();
77d8a31949SRaphael Isemann decl_map.reset();
78d8a31949SRaphael Isemann target_ast.reset();
794aee81c4SRaphael Isemann }
804aee81c4SRaphael Isemann };
814aee81c4SRaphael Isemann } // namespace
824aee81c4SRaphael Isemann
TEST_F(ClangExpressionDeclMapTest,TestUnknownIdentifierLookup)83d8a31949SRaphael Isemann TEST_F(ClangExpressionDeclMapTest, TestUnknownIdentifierLookup) {
84d8a31949SRaphael Isemann // Tests looking up an identifier that can't be found anywhere.
854aee81c4SRaphael Isemann
86d8a31949SRaphael Isemann // Setup a NameSearchContext for 'foo'.
874aee81c4SRaphael Isemann llvm::SmallVector<clang::NamedDecl *, 16> decls;
88aaa34bc0SRaphael Isemann clang::DeclarationName name =
89aaa34bc0SRaphael Isemann clang_utils::getDeclarationName(*target_ast, "foo");
90d8a31949SRaphael Isemann const clang::DeclContext *dc = target_ast->GetTranslationUnitDecl();
91*defd0e24SRaphael Isemann NameSearchContext search(*target_ast, decls, name, dc);
924aee81c4SRaphael Isemann
93d8a31949SRaphael Isemann decl_map->FindExternalVisibleDecls(search);
944aee81c4SRaphael Isemann
95d8a31949SRaphael Isemann // This shouldn't exist so we should get no lookups.
964aee81c4SRaphael Isemann EXPECT_EQ(0U, decls.size());
974aee81c4SRaphael Isemann }
98d8a31949SRaphael Isemann
TEST_F(ClangExpressionDeclMapTest,TestPersistentDeclLookup)99d8a31949SRaphael Isemann TEST_F(ClangExpressionDeclMapTest, TestPersistentDeclLookup) {
100d8a31949SRaphael Isemann // Tests looking up a persistent decl from the scratch AST context.
101d8a31949SRaphael Isemann
102d8a31949SRaphael Isemann // Create a '$persistent_class' record and add it as a persistent variable
103d8a31949SRaphael Isemann // to the scratch AST context.
104d8a31949SRaphael Isemann llvm::StringRef decl_name = "$persistent_class";
105d8a31949SRaphael Isemann CompilerType persistent_type =
106aaa34bc0SRaphael Isemann clang_utils::createRecord(*decl_map->m_scratch_context, decl_name);
107d8a31949SRaphael Isemann decl_map->AddPersistentDeclForTest(ClangUtil::GetAsTagDecl(persistent_type));
108d8a31949SRaphael Isemann
109d8a31949SRaphael Isemann // Setup a NameSearchContext for $persistent_class;
110d8a31949SRaphael Isemann llvm::SmallVector<clang::NamedDecl *, 16> decls;
111aaa34bc0SRaphael Isemann clang::DeclarationName name =
112aaa34bc0SRaphael Isemann clang_utils::getDeclarationName(*target_ast, decl_name);
113d8a31949SRaphael Isemann const clang::DeclContext *dc = target_ast->GetTranslationUnitDecl();
114*defd0e24SRaphael Isemann NameSearchContext search(*target_ast, decls, name, dc);
115d8a31949SRaphael Isemann
116d8a31949SRaphael Isemann // Search and check that we found $persistent_class.
117d8a31949SRaphael Isemann decl_map->FindExternalVisibleDecls(search);
118d8a31949SRaphael Isemann EXPECT_EQ(1U, decls.size());
119d8a31949SRaphael Isemann EXPECT_EQ(decl_name, decls.front()->getQualifiedNameAsString());
120d8a31949SRaphael Isemann auto *record = llvm::cast<clang::RecordDecl>(decls.front());
121d8a31949SRaphael Isemann // The class was minimally imported from the scratch AST context.
122d8a31949SRaphael Isemann EXPECT_TRUE(record->hasExternalLexicalStorage());
123d8a31949SRaphael Isemann }
124