[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
This commit is contained in:
Aleksei Sidorin 2018-05-15 11:09:07 +00:00
parent 904684cf5c
commit 761c2247b4
2 changed files with 41 additions and 2 deletions

View File

@ -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);

View File

@ -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"}),);