[clang][AST] Add support for SubstTemplateTypeParmPackType to ASTImporter

Thank you @martong for acquiring a suitable test case!

Reviewed By: shafik, martong

Differential Revision: https://reviews.llvm.org/D109237
This commit is contained in:
Balazs Benics 2021-09-04 10:19:57 +02:00
parent b97a96400a
commit d6ca91ea42
2 changed files with 69 additions and 0 deletions

View File

@ -383,6 +383,8 @@ namespace clang {
ExpectedType VisitTemplateTypeParmType(const TemplateTypeParmType *T);
ExpectedType VisitSubstTemplateTypeParmType(
const SubstTemplateTypeParmType *T);
ExpectedType
VisitSubstTemplateTypeParmPackType(const SubstTemplateTypeParmPackType *T);
ExpectedType VisitTemplateSpecializationType(
const TemplateSpecializationType *T);
ExpectedType VisitElaboratedType(const ElaboratedType *T);
@ -1486,6 +1488,22 @@ ExpectedType ASTNodeImporter::VisitSubstTemplateTypeParmType(
Replaced, (*ToReplacementTypeOrErr).getCanonicalType());
}
ExpectedType ASTNodeImporter::VisitSubstTemplateTypeParmPackType(
const SubstTemplateTypeParmPackType *T) {
ExpectedType ReplacedOrErr = import(QualType(T->getReplacedParameter(), 0));
if (!ReplacedOrErr)
return ReplacedOrErr.takeError();
const TemplateTypeParmType *Replaced =
cast<TemplateTypeParmType>(ReplacedOrErr->getTypePtr());
Expected<TemplateArgument> ToArgumentPack = import(T->getArgumentPack());
if (!ToArgumentPack)
return ToArgumentPack.takeError();
return Importer.getToContext().getSubstTemplateTypeParmPackType(
Replaced, *ToArgumentPack);
}
ExpectedType ASTNodeImporter::VisitTemplateSpecializationType(
const TemplateSpecializationType *T) {
auto ToTemplateOrErr = import(T->getTemplateName());

View File

@ -4693,6 +4693,57 @@ TEST_P(ASTImporterOptionSpecificTestBase,
ToD2->getDeclContext(), ToD2->getTemplateParameters()->getParam(0)));
}
const AstTypeMatcher<SubstTemplateTypeParmPackType>
substTemplateTypeParmPackType;
TEST_P(ASTImporterOptionSpecificTestBase, ImportSubstTemplateTypeParmPackType) {
constexpr auto Code = R"(
template<typename ...T> struct D {
template<typename... U> using B = int(int (*...p)(T, U));
template<typename U1, typename U2> D(B<U1, U2>*);
};
int f(int(int, int), int(int, int));
using asd = D<float, double, float>::B<int, long, int>;
)";
Decl *FromTU = getTuDecl(Code, Lang_CXX11, "input.cpp");
auto *FromClass = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
FromTU, classTemplateSpecializationDecl());
{
ASTContext &FromCtx = FromTU->getASTContext();
const auto *FromSubstPack = selectFirst<SubstTemplateTypeParmPackType>(
"pack", match(substTemplateTypeParmPackType().bind("pack"), FromCtx));
ASSERT_TRUE(FromSubstPack);
ASSERT_EQ(FromSubstPack->getIdentifier()->getName(), "T");
ArrayRef<TemplateArgument> FromArgPack =
FromSubstPack->getArgumentPack().pack_elements();
ASSERT_EQ(FromArgPack.size(), 3u);
ASSERT_EQ(FromArgPack[0].getAsType(), FromCtx.FloatTy);
ASSERT_EQ(FromArgPack[1].getAsType(), FromCtx.DoubleTy);
ASSERT_EQ(FromArgPack[2].getAsType(), FromCtx.FloatTy);
}
{
// Let's do the import.
ClassTemplateSpecializationDecl *ToClass = Import(FromClass, Lang_CXX11);
ASTContext &ToCtx = ToClass->getASTContext();
const auto *ToSubstPack = selectFirst<SubstTemplateTypeParmPackType>(
"pack", match(substTemplateTypeParmPackType().bind("pack"), ToCtx));
// Check if it meets the requirements.
ASSERT_TRUE(ToSubstPack);
ASSERT_EQ(ToSubstPack->getIdentifier()->getName(), "T");
ArrayRef<TemplateArgument> ToArgPack =
ToSubstPack->getArgumentPack().pack_elements();
ASSERT_EQ(ToArgPack.size(), 3u);
ASSERT_EQ(ToArgPack[0].getAsType(), ToCtx.FloatTy);
ASSERT_EQ(ToArgPack[1].getAsType(), ToCtx.DoubleTy);
ASSERT_EQ(ToArgPack[2].getAsType(), ToCtx.FloatTy);
}
}
struct ASTImporterLookupTableTest : ASTImporterOptionSpecificTestBase {};
TEST_P(ASTImporterLookupTableTest, OneDecl) {