diff options
| author | Aleksei Sidorin <a.sidorin@samsung.com> | 2018-05-15 11:09:07 +0000 |
|---|---|---|
| committer | Aleksei Sidorin <a.sidorin@samsung.com> | 2018-05-15 11:09:07 +0000 |
| commit | 761c2247b44a4128e715fe71a1faeadd28d4028a (patch) | |
| tree | 0b98371935c335cec69a943375268335d626639d | |
| parent | 904684cf5c02f9c781ee0310d1daaef0d1193c74 (diff) | |
| download | bcm5719-llvm-761c2247b44a4128e715fe71a1faeadd28d4028a.tar.gz bcm5719-llvm-761c2247b44a4128e715fe71a1faeadd28d4028a.zip | |
[ASTImporter] Extend lookup logic in class templates
During import of a class template, lookup may find a forward
declaration and structural match falsely reports equivalency
between a forward decl and a definition. The result is that
some definitions are not imported if we had imported a forward
decl previously. This patch gives a fix.
Patch by Gabor Marton!
Differential Revision: https://reviews.llvm.org/D46353
llvm-svn: 332338
| -rw-r--r-- | clang/lib/AST/ASTImporter.cpp | 10 | ||||
| -rw-r--r-- | clang/unittests/AST/ASTImporterTest.cpp | 33 |
2 files changed, 41 insertions, 2 deletions
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 57d4585e07d..d8c2259e1c2 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -4108,8 +4108,14 @@ Decl *ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) { if (auto *FoundTemplate = dyn_cast<ClassTemplateDecl>(Found)) { if (IsStructuralMatch(D, FoundTemplate)) { // The class templates structurally match; call it the same template. - // FIXME: We may be filling in a forward declaration here. Handle - // this case! + + // We found a forward declaration but the class to be imported has a + // definition. + // FIXME Add this forward declaration to the redeclaration chain. + if (D->isThisDeclarationADefinition() && + !FoundTemplate->isThisDeclarationADefinition()) + continue; + Importer.Imported(D->getTemplatedDecl(), FoundTemplate->getTemplatedDecl()); return Importer.Imported(D, FoundTemplate); diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp index debcfe67d96..9eec1d20bac 100644 --- a/clang/unittests/AST/ASTImporterTest.cpp +++ b/clang/unittests/AST/ASTImporterTest.cpp @@ -1431,6 +1431,39 @@ TEST_P(ASTImporterTestBase, MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern)); } +TEST_P(ASTImporterTestBase, ImportDefinitionOfClassTemplateAfterFwdDecl) { + { + Decl *FromTU = getTuDecl( + R"( + template <typename T> + struct B; + )", + Lang_CXX, "input0.cc"); + auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match( + FromTU, classTemplateDecl(hasName("B"))); + + Import(FromD, Lang_CXX); + } + + { + Decl *FromTU = getTuDecl( + R"( + template <typename T> + struct B { + void f(); + }; + )", + Lang_CXX, "input1.cc"); + FunctionDecl *FromD = FirstDeclMatcher<FunctionDecl>().match( + FromTU, functionDecl(hasName("f"))); + Import(FromD, Lang_CXX); + auto *FromCTD = FirstDeclMatcher<ClassTemplateDecl>().match( + FromTU, classTemplateDecl(hasName("B"))); + auto *ToCTD = cast<ClassTemplateDecl>(Import(FromCTD, Lang_CXX)); + EXPECT_TRUE(ToCTD->isThisDeclarationADefinition()); + } +} + INSTANTIATE_TEST_CASE_P( ParameterizedTests, ASTImporterTestBase, ::testing::Values(ArgVector(), ArgVector{"-fdelayed-template-parsing"}),); |

