Skip to content

Commit e4440b8

Browse files
committed
[clang][ASTImporter] Fix import of template parameter default values.
Default values of template parameters (non-type, type, template) were not correctly handled in the "inherited" case. This occurs if the first declaration contains the default value but a next one not. The default value is "inherited" from the first. In ASTImporter it was only possible to set the inherited status after the template object was created with the template parameters that were imported without handling the inherited case. The import function of the template parameter contains not enough information (previous declaration) to set the inherited-from status. After the template was created, default value of the parameters that should be inherited is reset to inherited mode.
1 parent 96d4121 commit e4440b8

File tree

2 files changed

+159
-0
lines changed

2 files changed

+159
-0
lines changed

clang/lib/AST/ASTImporter.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,31 @@ namespace clang {
359359
Params, Importer.getToContext().getTranslationUnitDecl());
360360
}
361361

362+
template <typename TemplateParmDeclT>
363+
void tryUpdateTemplateParmDeclInheritedFrom(NamedDecl *RecentParm,
364+
NamedDecl *NewParm) {
365+
if (auto *ParmT = dyn_cast<TemplateParmDeclT>(RecentParm)) {
366+
if (ParmT->hasDefaultArgument()) {
367+
auto *P = cast<TemplateParmDeclT>(NewParm);
368+
P->removeDefaultArgument();
369+
P->setInheritedDefaultArgument(Importer.ToContext, ParmT);
370+
}
371+
}
372+
}
373+
374+
void updateTemplateParametersInheritedFrom(
375+
const TemplateParameterList &RecentParams,
376+
TemplateParameterList &NewParams) {
377+
for (auto [Idx, Param] : enumerate(RecentParams)) {
378+
tryUpdateTemplateParmDeclInheritedFrom<NonTypeTemplateParmDecl>(
379+
Param, NewParams.getParam(Idx));
380+
tryUpdateTemplateParmDeclInheritedFrom<TemplateTypeParmDecl>(
381+
Param, NewParams.getParam(Idx));
382+
tryUpdateTemplateParmDeclInheritedFrom<TemplateTemplateParmDecl>(
383+
Param, NewParams.getParam(Idx));
384+
}
385+
}
386+
362387
public:
363388
explicit ASTNodeImporter(ASTImporter &Importer) : Importer(Importer) {}
364389

@@ -6138,6 +6163,9 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
61386163
}
61396164

61406165
D2->setPreviousDecl(Recent);
6166+
6167+
updateTemplateParametersInheritedFrom(*(Recent->getTemplateParameters()),
6168+
**TemplateParamsOrErr);
61416169
}
61426170

61436171
return D2;
@@ -6452,6 +6480,9 @@ ExpectedDecl ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) {
64526480
ToTemplated->setPreviousDecl(PrevTemplated);
64536481
}
64546482
ToVarTD->setPreviousDecl(Recent);
6483+
6484+
updateTemplateParametersInheritedFrom(*(Recent->getTemplateParameters()),
6485+
**TemplateParamsOrErr);
64556486
}
64566487

64576488
return ToVarTD;
@@ -6724,6 +6755,9 @@ ASTNodeImporter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
67246755
TemplatedFD->setPreviousDecl(PrevTemplated);
67256756
}
67266757
ToFunc->setPreviousDecl(Recent);
6758+
6759+
updateTemplateParametersInheritedFrom(*(Recent->getTemplateParameters()),
6760+
*Params);
67276761
}
67286762

67296763
return ToFunc;

clang/unittests/AST/ASTImporterTest.cpp

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9783,6 +9783,128 @@ TEST_P(ASTImporterOptionSpecificTestBase, ImportExistingEmptyAnonymousEnums) {
97839783
EXPECT_EQ(ImportedE2, ToE1);
97849784
}
97859785

9786+
struct ImportTemplateParmDeclDefaultValue
9787+
: public ASTImporterOptionSpecificTestBase {
9788+
protected:
9789+
void checkTemplateParams(RedeclarableTemplateDecl *D) {
9790+
auto *CanD = cast<RedeclarableTemplateDecl>(D->getCanonicalDecl());
9791+
auto *CanNonTypeP = cast<NonTypeTemplateParmDecl>(
9792+
CanD->getTemplateParameters()->getParam(0));
9793+
auto *CanTypeP =
9794+
cast<TemplateTypeParmDecl>(CanD->getTemplateParameters()->getParam(1));
9795+
auto *CanTemplateP = cast<TemplateTemplateParmDecl>(
9796+
CanD->getTemplateParameters()->getParam(2));
9797+
EXPECT_FALSE(CanNonTypeP->getDefaultArgStorage().isInherited());
9798+
EXPECT_FALSE(CanTypeP->getDefaultArgStorage().isInherited());
9799+
EXPECT_FALSE(CanTemplateP->getDefaultArgStorage().isInherited());
9800+
for (Decl *Redecl : D->redecls()) {
9801+
auto *ReD = cast<RedeclarableTemplateDecl>(Redecl);
9802+
if (ReD != CanD) {
9803+
auto *NonTypeP = cast<NonTypeTemplateParmDecl>(
9804+
ReD->getTemplateParameters()->getParam(0));
9805+
auto *TypeP = cast<TemplateTypeParmDecl>(
9806+
ReD->getTemplateParameters()->getParam(1));
9807+
auto *TemplateP = cast<TemplateTemplateParmDecl>(
9808+
ReD->getTemplateParameters()->getParam(2));
9809+
EXPECT_TRUE(NonTypeP->getDefaultArgStorage().isInherited());
9810+
EXPECT_TRUE(TypeP->getDefaultArgStorage().isInherited());
9811+
EXPECT_TRUE(TemplateP->getDefaultArgStorage().isInherited());
9812+
EXPECT_EQ(NonTypeP->getDefaultArgStorage().getInheritedFrom(),
9813+
CanNonTypeP);
9814+
EXPECT_EQ(TypeP->getDefaultArgStorage().getInheritedFrom(), CanTypeP);
9815+
EXPECT_EQ(TemplateP->getDefaultArgStorage().getInheritedFrom(),
9816+
CanTemplateP);
9817+
}
9818+
}
9819+
}
9820+
9821+
void testImport(RedeclarableTemplateDecl *FromD) {
9822+
RedeclarableTemplateDecl *ToD = Import(FromD, Lang_CXX14);
9823+
checkTemplateParams(ToD);
9824+
}
9825+
9826+
const char *CodeFunction =
9827+
R"(
9828+
template <class> struct X;
9829+
9830+
template <int A = 2, typename B = int, template<class> class C = X>
9831+
void f();
9832+
template <int A, typename B, template<class> class C>
9833+
void f();
9834+
template <int A, typename B, template<class> class C>
9835+
void f() {}
9836+
)";
9837+
9838+
const char *CodeClass =
9839+
R"(
9840+
template <class> struct X;
9841+
9842+
template <int A = 2, typename B = int, template<class> class C = X>
9843+
struct S;
9844+
template <int A, typename B, template<class> class C>
9845+
struct S;
9846+
template <int A, typename B, template<class> class C>
9847+
struct S {};
9848+
)";
9849+
9850+
const char *CodeVar =
9851+
R"(
9852+
template <class> struct X;
9853+
9854+
template <int A = 2, typename B = int, template<class> class C = X>
9855+
extern int V;
9856+
template <int A, typename B, template<class> class C>
9857+
extern int V;
9858+
template <int A, typename B, template<class> class C>
9859+
int V = A;
9860+
)";
9861+
};
9862+
9863+
TEST_P(ImportTemplateParmDeclDefaultValue, ImportFunctionTemplate) {
9864+
Decl *FromTU = getTuDecl(CodeFunction, Lang_CXX14);
9865+
auto *FromLastD = LastDeclMatcher<FunctionTemplateDecl>().match(
9866+
FromTU, functionTemplateDecl(hasName("f")));
9867+
testImport(FromLastD);
9868+
}
9869+
9870+
TEST_P(ImportTemplateParmDeclDefaultValue, ImportExistingFunctionTemplate) {
9871+
getToTuDecl(CodeFunction, Lang_CXX14);
9872+
Decl *FromTU = getTuDecl(CodeFunction, Lang_CXX14);
9873+
auto *FromLastD = LastDeclMatcher<FunctionTemplateDecl>().match(
9874+
FromTU, functionTemplateDecl(hasName("f")));
9875+
testImport(FromLastD);
9876+
}
9877+
9878+
TEST_P(ImportTemplateParmDeclDefaultValue, ImportClassTemplate) {
9879+
Decl *FromTU = getTuDecl(CodeClass, Lang_CXX14);
9880+
auto *FromLastD = LastDeclMatcher<ClassTemplateDecl>().match(
9881+
FromTU, classTemplateDecl(hasName("S")));
9882+
testImport(FromLastD);
9883+
}
9884+
9885+
TEST_P(ImportTemplateParmDeclDefaultValue, ImportExistingClassTemplate) {
9886+
getToTuDecl(CodeClass, Lang_CXX14);
9887+
Decl *FromTU = getTuDecl(CodeClass, Lang_CXX14);
9888+
auto *FromLastD = LastDeclMatcher<ClassTemplateDecl>().match(
9889+
FromTU, classTemplateDecl(hasName("S")));
9890+
testImport(FromLastD);
9891+
}
9892+
9893+
TEST_P(ImportTemplateParmDeclDefaultValue, ImportVarTemplate) {
9894+
Decl *FromTU = getTuDecl(CodeVar, Lang_CXX14);
9895+
auto *FromLastD = LastDeclMatcher<VarTemplateDecl>().match(
9896+
FromTU, varTemplateDecl(hasName("V")));
9897+
testImport(FromLastD);
9898+
}
9899+
9900+
TEST_P(ImportTemplateParmDeclDefaultValue, ImportExistingVarTemplate) {
9901+
getToTuDecl(CodeVar, Lang_CXX14);
9902+
Decl *FromTU = getTuDecl(CodeVar, Lang_CXX14);
9903+
auto *FromLastD = LastDeclMatcher<VarTemplateDecl>().match(
9904+
FromTU, varTemplateDecl(hasName("V")));
9905+
testImport(FromLastD);
9906+
}
9907+
97869908
INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ASTImporterLookupTableTest,
97879909
DefaultTestValuesForRunOptions);
97889910

@@ -9866,6 +9988,9 @@ INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportInjectedClassNameType,
98669988
INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportMatrixType,
98679989
DefaultTestValuesForRunOptions);
98689990

9991+
INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportTemplateParmDeclDefaultValue,
9992+
DefaultTestValuesForRunOptions);
9993+
98699994
// FIXME: Make ImportOpenCLPipe test work.
98709995
// INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportOpenCLPipe,
98719996
// DefaultTestValuesForRunOptions);

0 commit comments

Comments
 (0)