r340277 - [ASTImporter] Adding some friend function related unittests.
Balazs Keri via cfe-commits
cfe-commits at lists.llvm.org
Tue Aug 21 07:32:21 PDT 2018
Author: balazske
Date: Tue Aug 21 07:32:21 2018
New Revision: 340277
URL: http://llvm.org/viewvc/llvm-project?rev=340277&view=rev
Log:
[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
Modified:
cfe/trunk/unittests/AST/ASTImporterTest.cpp
Modified: cfe/trunk/unittests/AST/ASTImporterTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/AST/ASTImporterTest.cpp?rev=340277&r1=340276&r2=340277&view=diff
==============================================================================
--- cfe/trunk/unittests/AST/ASTImporterTest.cpp (original)
+++ cfe/trunk/unittests/AST/ASTImporterTest.cpp Tue Aug 21 07:32:21 2018
@@ -2274,6 +2274,211 @@ TEST_P(ImportFriendFunctions, ImportFrie
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())
More information about the cfe-commits
mailing list