diff options
author | Balazs Keri <1.int32@gmail.com> | 2018-08-13 13:08:37 +0000 |
---|---|---|
committer | Balazs Keri <1.int32@gmail.com> | 2018-08-13 13:08:37 +0000 |
commit | 0c23dc59fcf55491063e94b2f474e55112876c8e (patch) | |
tree | 4397d8486b03f030126a84e0ecad4f05cfa49b89 /clang/unittests/AST/ASTImporterTest.cpp | |
parent | 706005486f37405a847a546634a52d42076e18e1 (diff) | |
download | bcm5719-llvm-0c23dc59fcf55491063e94b2f474e55112876c8e.tar.gz bcm5719-llvm-0c23dc59fcf55491063e94b2f474e55112876c8e.zip |
[ASTImporter] Improved import of friend templates.
Summary:
When importing a friend class template declaration,
this declaration should not be merged with any other existing declaration
for the same type. Otherwise the getFriendDecl of the FriendDecl can point
to an other already referenced declaration, this case causes problems.
Additionally the previous decl of class templates is set at import.
Reviewers: a.sidorin, a_sidorin
Reviewed By: a_sidorin
Subscribers: a_sidorin, martong, cfe-commits
Differential Revision: https://reviews.llvm.org/D50516
llvm-svn: 339560
Diffstat (limited to 'clang/unittests/AST/ASTImporterTest.cpp')
-rw-r--r-- | clang/unittests/AST/ASTImporterTest.cpp | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp index 7d61e98be1a..4e13f295aa3 100644 --- a/clang/unittests/AST/ASTImporterTest.cpp +++ b/clang/unittests/AST/ASTImporterTest.cpp @@ -2677,6 +2677,93 @@ TEST_P(ASTImporterTestBase, ImportUnnamedFieldsInCorrectOrder) { EXPECT_EQ(FromIndex, 3u); } +TEST_P( + ASTImporterTestBase, + ImportOfFriendRecordDoesNotMergeDefinition) { + Decl *FromTU = getTuDecl( + R"( + class A { + template <int I> class F {}; + class X { + template <int I> friend class F; + }; + }; + )", + Lang_CXX, "input0.cc"); + + auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match( + FromTU, cxxRecordDecl(hasName("F"), isDefinition())); + auto *FromFriendClass = LastDeclMatcher<CXXRecordDecl>().match( + FromTU, cxxRecordDecl(hasName("F"))); + + ASSERT_TRUE(FromClass); + ASSERT_TRUE(FromFriendClass); + ASSERT_NE(FromClass, FromFriendClass); + ASSERT_EQ(FromFriendClass->getDefinition(), FromClass); + ASSERT_EQ(FromFriendClass->getPreviousDecl(), FromClass); + ASSERT_EQ( + FromFriendClass->getDescribedClassTemplate()->getPreviousDecl(), + FromClass->getDescribedClassTemplate()); + + auto *ToClass = cast<CXXRecordDecl>(Import(FromClass, Lang_CXX)); + auto *ToFriendClass = cast<CXXRecordDecl>(Import(FromFriendClass, Lang_CXX)); + + EXPECT_TRUE(ToClass); + EXPECT_TRUE(ToFriendClass); + EXPECT_NE(ToClass, ToFriendClass); + EXPECT_EQ(ToFriendClass->getDefinition(), ToClass); + EXPECT_EQ(ToFriendClass->getPreviousDecl(), ToClass); + EXPECT_EQ( + ToFriendClass->getDescribedClassTemplate()->getPreviousDecl(), + ToClass->getDescribedClassTemplate()); +} + +TEST_P( + ASTImporterTestBase, + ImportOfRecursiveFriendClass) { + Decl *FromTu = getTuDecl( + R"( + class declToImport { + friend class declToImport; + }; + )", + Lang_CXX, "input.cc"); + + auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match( + FromTu, cxxRecordDecl(hasName("declToImport"))); + auto *ToD = Import(FromD, Lang_CXX); + auto Pattern = cxxRecordDecl(hasName("declToImport"), has(friendDecl())); + ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromD, Pattern)); + EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToD, Pattern)); +} + +TEST_P( + ASTImporterTestBase, + ImportOfRecursiveFriendClassTemplate) { + Decl *FromTu = getTuDecl( + R"( + template <class A> class declToImport { + template <class A1> friend class declToImport; + }; + )", + Lang_CXX, "input.cc"); + + auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match( + FromTu, classTemplateDecl(hasName("declToImport"))); + auto *ToD = Import(FromD, Lang_CXX); + + auto Pattern = classTemplateDecl( + has(cxxRecordDecl(has(friendDecl(has(classTemplateDecl())))))); + ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromD, Pattern)); + EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToD, Pattern)); + + auto *Class = + FirstDeclMatcher<ClassTemplateDecl>().match(ToD, classTemplateDecl()); + auto *Friend = FirstDeclMatcher<FriendDecl>().match(ToD, friendDecl()); + EXPECT_NE(Friend->getFriendDecl(), Class); + EXPECT_EQ(Friend->getFriendDecl()->getPreviousDecl(), Class); +} + struct DeclContextTest : ASTImporterTestBase {}; TEST_P(DeclContextTest, removeDeclOfClassTemplateSpecialization) { |