Skip to content

Commit

Permalink
[clang][ASTImporter] New fix for default template parameter values. (l…
Browse files Browse the repository at this point in the history
…lvm#101836)

Commit e4440b8 added a change that introduced new crash in an
incorrectly handled case. This is fixed here. Default argument
definition or inheritance is preserved in the "To" AST compared to
the "From". If the default argument is defined already in the "To"
AST it can be duplicated at the import.
  • Loading branch information
balazske authored Sep 6, 2024
1 parent ddf40e0 commit 9c72a30
Show file tree
Hide file tree
Showing 2 changed files with 309 additions and 143 deletions.
118 changes: 43 additions & 75 deletions clang/lib/AST/ASTImporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -360,51 +360,42 @@ namespace clang {
}

template <typename TemplateParmDeclT>
void tryUpdateTemplateParmDeclInheritedFrom(NamedDecl *RecentParm,
NamedDecl *NewParm) {
if (auto *ParmT = dyn_cast<TemplateParmDeclT>(RecentParm)) {
if (ParmT->hasDefaultArgument()) {
auto *P = cast<TemplateParmDeclT>(NewParm);
P->removeDefaultArgument();
P->setInheritedDefaultArgument(Importer.ToContext, ParmT);
Error importTemplateParameterDefaultArgument(const TemplateParmDeclT *D,
TemplateParmDeclT *ToD) {
Error Err = Error::success();
if (D->hasDefaultArgument()) {
if (D->defaultArgumentWasInherited()) {
auto *ToInheritedFrom = const_cast<TemplateParmDeclT *>(
importChecked(Err, D->getDefaultArgStorage().getInheritedFrom()));
if (Err)
return std::move(Err);
if (!ToInheritedFrom->hasDefaultArgument()) {
// Resolve possible circular dependency between default value of the
// template argument and the template declaration.
const auto ToInheritedDefaultArg =
importChecked(Err, D->getDefaultArgStorage()
.getInheritedFrom()
->getDefaultArgument());
if (Err)
return std::move(Err);
ToInheritedFrom->setDefaultArgument(Importer.getToContext(),
ToInheritedDefaultArg);
}
ToD->setInheritedDefaultArgument(ToD->getASTContext(),
ToInheritedFrom);
} else {
Expected<TemplateArgumentLoc> ToDefaultArgOrErr =
import(D->getDefaultArgument());
if (!ToDefaultArgOrErr)
return ToDefaultArgOrErr.takeError();
// Default argument could have been set in the
// '!ToInheritedFrom->hasDefaultArgument()' branch above.
if (!ToD->hasDefaultArgument())
ToD->setDefaultArgument(Importer.getToContext(),
*ToDefaultArgOrErr);
}
}
}

// Update the parameter list `NewParams` of a template declaration
// by "inheriting" default argument values from `RecentParams`,
// which is the parameter list of an earlier declaration of the
// same template. (Note that "inheriting" default argument values
// is not related to object-oriented inheritance.)
//
// In the clang AST template parameters (NonTypeTemplateParmDec,
// TemplateTypeParmDecl, TemplateTemplateParmDecl) have a reference to the
// default value, if one is specified at the first declaration. The default
// value can be specified only once. The template parameters of the
// following declarations have a reference to the original default value
// through the "inherited" value. This value should be set for all imported
// template parameters that have a previous declaration (also a previous
// template declaration).
//
// In the `Visit*ParmDecl` functions the default value of these template
// arguments is always imported. At that location the previous declaration
// is not easily accessible, it is not possible to call
// `setInheritedDefaultArgument` at that place.
// `updateTemplateParametersInheritedFrom` is called later when the already
// imported default value is erased and changed to "inherited".
// It is important to change the mode to "inherited" otherwise false
// structural in-equivalences could be detected.
void updateTemplateParametersInheritedFrom(
const TemplateParameterList &RecentParams,
TemplateParameterList &NewParams) {
for (auto [Idx, Param] : enumerate(RecentParams)) {
tryUpdateTemplateParmDeclInheritedFrom<NonTypeTemplateParmDecl>(
Param, NewParams.getParam(Idx));
tryUpdateTemplateParmDeclInheritedFrom<TemplateTypeParmDecl>(
Param, NewParams.getParam(Idx));
tryUpdateTemplateParmDeclInheritedFrom<TemplateTemplateParmDecl>(
Param, NewParams.getParam(Idx));
}
return Err;
}

public:
Expand Down Expand Up @@ -5955,8 +5946,8 @@ ASTNodeImporter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) {
ExpectedDecl
ASTNodeImporter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
// For template arguments, we adopt the translation unit as our declaration
// context. This context will be fixed when the actual template declaration
// is created.
// context. This context will be fixed when (during) the actual template
// declaration is created.

ExpectedSLoc BeginLocOrErr = import(D->getBeginLoc());
if (!BeginLocOrErr)
Expand Down Expand Up @@ -5988,13 +5979,8 @@ ASTNodeImporter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
ToD->setTypeConstraint(ToConceptRef, ToIDC);
}

if (D->hasDefaultArgument()) {
Expected<TemplateArgumentLoc> ToDefaultArgOrErr =
import(D->getDefaultArgument());
if (!ToDefaultArgOrErr)
return ToDefaultArgOrErr.takeError();
ToD->setDefaultArgument(ToD->getASTContext(), *ToDefaultArgOrErr);
}
if (Error Err = importTemplateParameterDefaultArgument(D, ToD))
return Err;

return ToD;
}
Expand All @@ -6020,13 +6006,9 @@ ASTNodeImporter::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
D->isParameterPack(), ToTypeSourceInfo))
return ToD;

if (D->hasDefaultArgument()) {
Expected<TemplateArgumentLoc> ToDefaultArgOrErr =
import(D->getDefaultArgument());
if (!ToDefaultArgOrErr)
return ToDefaultArgOrErr.takeError();
ToD->setDefaultArgument(Importer.getToContext(), *ToDefaultArgOrErr);
}
Err = importTemplateParameterDefaultArgument(D, ToD);
if (Err)
return Err;

return ToD;
}
Expand Down Expand Up @@ -6057,13 +6039,8 @@ ASTNodeImporter::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
*TemplateParamsOrErr))
return ToD;

if (D->hasDefaultArgument()) {
Expected<TemplateArgumentLoc> ToDefaultArgOrErr =
import(D->getDefaultArgument());
if (!ToDefaultArgOrErr)
return ToDefaultArgOrErr.takeError();
ToD->setDefaultArgument(Importer.getToContext(), *ToDefaultArgOrErr);
}
if (Error Err = importTemplateParameterDefaultArgument(D, ToD))
return Err;

return ToD;
}
Expand Down Expand Up @@ -6201,9 +6178,6 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
}

D2->setPreviousDecl(Recent);

updateTemplateParametersInheritedFrom(*(Recent->getTemplateParameters()),
**TemplateParamsOrErr);
}

return D2;
Expand Down Expand Up @@ -6518,9 +6492,6 @@ ExpectedDecl ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) {
ToTemplated->setPreviousDecl(PrevTemplated);
}
ToVarTD->setPreviousDecl(Recent);

updateTemplateParametersInheritedFrom(*(Recent->getTemplateParameters()),
**TemplateParamsOrErr);
}

return ToVarTD;
Expand Down Expand Up @@ -6793,9 +6764,6 @@ ASTNodeImporter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
TemplatedFD->setPreviousDecl(PrevTemplated);
}
ToFunc->setPreviousDecl(Recent);

updateTemplateParametersInheritedFrom(*(Recent->getTemplateParameters()),
*Params);
}

return ToFunc;
Expand Down
Loading

0 comments on commit 9c72a30

Please sign in to comment.