forked from OSchip/llvm-project
[ASTImporter] Adding some friend function related unittests.
Reviewers: a.sidorin, a_sidorin Reviewed By: a_sidorin Subscribers: a_sidorin, martong, cfe-commits Differential Revision: https://reviews.llvm.org/D49798 llvm-svn: 340277
This commit is contained in:
parent
6bb09a4291
commit
89632b84f5
|
@ -2274,6 +2274,211 @@ TEST_P(ImportFriendFunctions, ImportFriendFunctionFromMultipleTU) {
|
|||
EXPECT_EQ(ImportedD1->getPreviousDecl(), ImportedD);
|
||||
}
|
||||
|
||||
TEST_P(ImportFriendFunctions, Lookup) {
|
||||
auto FunctionPattern = functionDecl(hasName("f"));
|
||||
auto ClassPattern = cxxRecordDecl(hasName("X"));
|
||||
|
||||
TranslationUnitDecl *FromTU =
|
||||
getTuDecl("struct X { friend void f(); };", Lang_CXX, "input0.cc");
|
||||
auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
|
||||
ASSERT_TRUE(FromD->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
|
||||
ASSERT_FALSE(FromD->isInIdentifierNamespace(Decl::IDNS_Ordinary));
|
||||
{
|
||||
auto FromName = FromD->getDeclName();
|
||||
auto *Class = FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
|
||||
auto LookupRes = Class->noload_lookup(FromName);
|
||||
ASSERT_EQ(LookupRes.size(), 0u);
|
||||
LookupRes = FromTU->noload_lookup(FromName);
|
||||
ASSERT_EQ(LookupRes.size(), 1u);
|
||||
}
|
||||
|
||||
auto *ToD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
|
||||
auto ToName = ToD->getDeclName();
|
||||
|
||||
TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
|
||||
auto *Class = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
|
||||
auto LookupRes = Class->noload_lookup(ToName);
|
||||
EXPECT_EQ(LookupRes.size(), 0u);
|
||||
LookupRes = ToTU->noload_lookup(ToName);
|
||||
EXPECT_EQ(LookupRes.size(), 1u);
|
||||
|
||||
EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 1u);
|
||||
auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
|
||||
EXPECT_TRUE(To0->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
|
||||
EXPECT_FALSE(To0->isInIdentifierNamespace(Decl::IDNS_Ordinary));
|
||||
}
|
||||
|
||||
TEST_P(ImportFriendFunctions, DISABLED_LookupWithProtoAfter) {
|
||||
auto FunctionPattern = functionDecl(hasName("f"));
|
||||
auto ClassPattern = cxxRecordDecl(hasName("X"));
|
||||
|
||||
TranslationUnitDecl *FromTU = getTuDecl(
|
||||
"struct X { friend void f(); };"
|
||||
// This proto decl makes f available to normal
|
||||
// lookup, otherwise it is hidden.
|
||||
// Normal C++ lookup (implemented in
|
||||
// `clang::Sema::CppLookupName()` and in `LookupDirect()`)
|
||||
// returns the found `NamedDecl` only if the set IDNS is matched
|
||||
"void f();",
|
||||
Lang_CXX, "input0.cc");
|
||||
auto *FromFriend =
|
||||
FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
|
||||
auto *FromNormal =
|
||||
LastDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
|
||||
ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
|
||||
ASSERT_FALSE(FromFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
|
||||
ASSERT_FALSE(FromNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
|
||||
ASSERT_TRUE(FromNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
|
||||
|
||||
auto FromName = FromFriend->getDeclName();
|
||||
auto *FromClass =
|
||||
FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
|
||||
auto LookupRes = FromClass->noload_lookup(FromName);
|
||||
ASSERT_EQ(LookupRes.size(), 0u);
|
||||
LookupRes = FromTU->noload_lookup(FromName);
|
||||
ASSERT_EQ(LookupRes.size(), 1u);
|
||||
|
||||
auto *ToFriend = cast<FunctionDecl>(Import(FromFriend, Lang_CXX));
|
||||
auto ToName = ToFriend->getDeclName();
|
||||
|
||||
TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
|
||||
auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
|
||||
LookupRes = ToClass->noload_lookup(ToName);
|
||||
EXPECT_EQ(LookupRes.size(), 0u);
|
||||
LookupRes = ToTU->noload_lookup(ToName);
|
||||
// Test is disabled because this result is 2.
|
||||
EXPECT_EQ(LookupRes.size(), 1u);
|
||||
|
||||
ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 2u);
|
||||
ToFriend = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
|
||||
auto *ToNormal = LastDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
|
||||
EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
|
||||
EXPECT_FALSE(ToFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
|
||||
EXPECT_FALSE(ToNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
|
||||
EXPECT_TRUE(ToNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
|
||||
}
|
||||
|
||||
TEST_P(ImportFriendFunctions, LookupWithProtoBefore) {
|
||||
auto FunctionPattern = functionDecl(hasName("f"));
|
||||
auto ClassPattern = cxxRecordDecl(hasName("X"));
|
||||
|
||||
TranslationUnitDecl *FromTU = getTuDecl(
|
||||
"void f();"
|
||||
"struct X { friend void f(); };",
|
||||
Lang_CXX, "input0.cc");
|
||||
auto *FromNormal =
|
||||
FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
|
||||
auto *FromFriend =
|
||||
LastDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
|
||||
ASSERT_FALSE(FromNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
|
||||
ASSERT_TRUE(FromNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
|
||||
ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
|
||||
ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
|
||||
|
||||
auto FromName = FromNormal->getDeclName();
|
||||
auto *FromClass =
|
||||
FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
|
||||
auto LookupRes = FromClass->noload_lookup(FromName);
|
||||
ASSERT_EQ(LookupRes.size(), 0u);
|
||||
LookupRes = FromTU->noload_lookup(FromName);
|
||||
ASSERT_EQ(LookupRes.size(), 1u);
|
||||
|
||||
auto *ToNormal = cast<FunctionDecl>(Import(FromNormal, Lang_CXX));
|
||||
auto ToName = ToNormal->getDeclName();
|
||||
TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
|
||||
|
||||
auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
|
||||
LookupRes = ToClass->noload_lookup(ToName);
|
||||
EXPECT_EQ(LookupRes.size(), 0u);
|
||||
LookupRes = ToTU->noload_lookup(ToName);
|
||||
EXPECT_EQ(LookupRes.size(), 1u);
|
||||
|
||||
EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 2u);
|
||||
ToNormal = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
|
||||
auto *ToFriend = LastDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
|
||||
EXPECT_FALSE(ToNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
|
||||
EXPECT_TRUE(ToNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
|
||||
EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
|
||||
EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
|
||||
}
|
||||
|
||||
TEST_P(ImportFriendFunctions, ImportFriendChangesLookup) {
|
||||
auto Pattern = functionDecl(hasName("f"));
|
||||
|
||||
TranslationUnitDecl *FromNormalTU =
|
||||
getTuDecl("void f();", Lang_CXX, "input0.cc");
|
||||
auto *FromNormalF =
|
||||
FirstDeclMatcher<FunctionDecl>().match(FromNormalTU, Pattern);
|
||||
TranslationUnitDecl *FromFriendTU =
|
||||
getTuDecl("class X { friend void f(); };", Lang_CXX, "input1.cc");
|
||||
auto *FromFriendF =
|
||||
FirstDeclMatcher<FunctionDecl>().match(FromFriendTU, Pattern);
|
||||
auto FromNormalName = FromNormalF->getDeclName();
|
||||
auto FromFriendName = FromFriendF->getDeclName();
|
||||
|
||||
ASSERT_TRUE(FromNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
|
||||
ASSERT_FALSE(FromNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
|
||||
ASSERT_FALSE(FromFriendF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
|
||||
ASSERT_TRUE(FromFriendF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
|
||||
auto LookupRes = FromNormalTU->noload_lookup(FromNormalName);
|
||||
ASSERT_EQ(LookupRes.size(), 1u);
|
||||
LookupRes = FromFriendTU->noload_lookup(FromFriendName);
|
||||
ASSERT_EQ(LookupRes.size(), 1u);
|
||||
|
||||
auto *ToNormalF = cast<FunctionDecl>(Import(FromNormalF, Lang_CXX));
|
||||
TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
|
||||
auto ToName = ToNormalF->getDeclName();
|
||||
EXPECT_TRUE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
|
||||
EXPECT_FALSE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
|
||||
LookupRes = ToTU->noload_lookup(ToName);
|
||||
EXPECT_EQ(LookupRes.size(), 1u);
|
||||
EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
|
||||
|
||||
auto *ToFriendF = cast<FunctionDecl>(Import(FromFriendF, Lang_CXX));
|
||||
LookupRes = ToTU->noload_lookup(ToName);
|
||||
EXPECT_EQ(LookupRes.size(), 1u);
|
||||
EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
|
||||
|
||||
EXPECT_TRUE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
|
||||
EXPECT_FALSE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
|
||||
|
||||
EXPECT_TRUE(ToFriendF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
|
||||
EXPECT_TRUE(ToFriendF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
|
||||
}
|
||||
|
||||
TEST_P(ImportFriendFunctions, ImportFriendList) {
|
||||
TranslationUnitDecl *FromTU = getTuDecl(
|
||||
"struct X { friend void f(); };"
|
||||
"void f();",
|
||||
Lang_CXX, "input0.cc");
|
||||
auto *FromFriendF = FirstDeclMatcher<FunctionDecl>().match(
|
||||
FromTU, functionDecl(hasName("f")));
|
||||
|
||||
auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
|
||||
FromTU, cxxRecordDecl(hasName("X")));
|
||||
auto *FromFriend = FirstDeclMatcher<FriendDecl>().match(FromTU, friendDecl());
|
||||
auto FromFriends = FromClass->friends();
|
||||
unsigned int FrN = 0;
|
||||
for (auto Fr : FromFriends) {
|
||||
ASSERT_EQ(Fr, FromFriend);
|
||||
++FrN;
|
||||
}
|
||||
ASSERT_EQ(FrN, 1u);
|
||||
|
||||
Import(FromFriendF, Lang_CXX);
|
||||
TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
|
||||
auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(
|
||||
ToTU, cxxRecordDecl(hasName("X")));
|
||||
auto *ToFriend = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
|
||||
auto ToFriends = ToClass->friends();
|
||||
FrN = 0;
|
||||
for (auto Fr : ToFriends) {
|
||||
EXPECT_EQ(Fr, ToFriend);
|
||||
++FrN;
|
||||
}
|
||||
EXPECT_EQ(FrN, 1u);
|
||||
}
|
||||
|
||||
AST_MATCHER_P(TagDecl, hasTypedefForAnonDecl, Matcher<TypedefNameDecl>,
|
||||
InnerMatcher) {
|
||||
if (auto *Typedef = Node.getTypedefNameForAnonDecl())
|
||||
|
|
Loading…
Reference in New Issue