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()) _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits