[Clang] Fix memory leak due to TemplateArgumentListInfo used in AST node.

It looks like the leak is rooted at the allocation here:
1a155ee7de/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp (L3857)

The VarTemplateSpecializationDecl is allocated using placement new which uses the AST structure for ownership: 1a155ee7de/clang/lib/AST/DeclBase.cpp (L99)

The problem is the TemplateArgumentListInfo inside 1a155ee7de/clang/include/clang/AST/DeclTemplate.h (L2721)
This object contains a vector which does not use placement new: 1a155ee7de/clang/include/clang/AST/TemplateBase.h (L564)

Apparently ASTTemplateArgumentListInfo should be used instead 1a155ee7de/clang/include/clang/AST/TemplateBase.h (L575)

https://reviews.llvm.org/D125802#3551305

Reviewed By: aaron.ballman

Differential Revision: https://reviews.llvm.org/D126944
This commit is contained in:
Andrew Browne 2022-06-02 17:42:54 -07:00
parent 0392d425bb
commit c7689fd552
8 changed files with 69 additions and 18 deletions

View File

@ -53,8 +53,10 @@ getTemplateSpecializationArgLocs(const NamedDecl &ND) {
llvm::dyn_cast<VarTemplatePartialSpecializationDecl>(&ND)) { llvm::dyn_cast<VarTemplatePartialSpecializationDecl>(&ND)) {
if (auto *Args = Var->getTemplateArgsAsWritten()) if (auto *Args = Var->getTemplateArgsAsWritten())
return Args->arguments(); return Args->arguments();
} else if (auto *Var = llvm::dyn_cast<VarTemplateSpecializationDecl>(&ND)) } else if (auto *Var = llvm::dyn_cast<VarTemplateSpecializationDecl>(&ND)) {
return Var->getTemplateArgsInfo().arguments(); if (auto *Args = Var->getTemplateArgsInfo())
return Args->arguments();
}
// We return None for ClassTemplateSpecializationDecls because it does not // We return None for ClassTemplateSpecializationDecls because it does not
// contain TemplateArgumentLoc information. // contain TemplateArgumentLoc information.
return llvm::None; return llvm::None;

View File

@ -168,6 +168,8 @@ Bug Fixes
`Issue 55562 <https://github.com/llvm/llvm-project/issues/55562>`_. `Issue 55562 <https://github.com/llvm/llvm-project/issues/55562>`_.
- Clang will allow calling a ``consteval`` function in a default argument. This - Clang will allow calling a ``consteval`` function in a default argument. This
fixes `Issue 48230 <https://github.com/llvm/llvm-project/issues/48230>`_. fixes `Issue 48230 <https://github.com/llvm/llvm-project/issues/48230>`_.
- Fixed memory leak due to ``VarTemplateSpecializationDecl`` using
``TemplateArgumentListInfo`` instead of ``ASTTemplateArgumentListInfo``.
Improvements to Clang's diagnostics Improvements to Clang's diagnostics
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -2718,7 +2718,7 @@ class VarTemplateSpecializationDecl : public VarDecl,
/// The template arguments used to describe this specialization. /// The template arguments used to describe this specialization.
const TemplateArgumentList *TemplateArgs; const TemplateArgumentList *TemplateArgs;
TemplateArgumentListInfo TemplateArgsInfo; const ASTTemplateArgumentListInfo *TemplateArgsInfo = nullptr;
/// The point where this template was instantiated (if any). /// The point where this template was instantiated (if any).
SourceLocation PointOfInstantiation; SourceLocation PointOfInstantiation;
@ -2773,8 +2773,9 @@ public:
// TODO: Always set this when creating the new specialization? // TODO: Always set this when creating the new specialization?
void setTemplateArgsInfo(const TemplateArgumentListInfo &ArgsInfo); void setTemplateArgsInfo(const TemplateArgumentListInfo &ArgsInfo);
void setTemplateArgsInfo(const ASTTemplateArgumentListInfo *ArgsInfo);
const TemplateArgumentListInfo &getTemplateArgsInfo() const { const ASTTemplateArgumentListInfo *getTemplateArgsInfo() const {
return TemplateArgsInfo; return TemplateArgsInfo;
} }

View File

@ -618,6 +618,9 @@ private:
ASTTemplateArgumentListInfo(const TemplateArgumentListInfo &List); ASTTemplateArgumentListInfo(const TemplateArgumentListInfo &List);
// FIXME: Is it ever necessary to copy to another context?
ASTTemplateArgumentListInfo(const ASTTemplateArgumentListInfo *List);
public: public:
/// The source location of the left angle bracket ('<'). /// The source location of the left angle bracket ('<').
SourceLocation LAngleLoc; SourceLocation LAngleLoc;
@ -647,6 +650,10 @@ public:
static const ASTTemplateArgumentListInfo * static const ASTTemplateArgumentListInfo *
Create(const ASTContext &C, const TemplateArgumentListInfo &List); Create(const ASTContext &C, const TemplateArgumentListInfo &List);
// FIXME: Is it ever necessary to copy to another context?
static const ASTTemplateArgumentListInfo *
Create(const ASTContext &C, const ASTTemplateArgumentListInfo *List);
}; };
/// Represents an explicit template argument list in C++, e.g., /// Represents an explicit template argument list in C++, e.g.,

View File

@ -6018,9 +6018,10 @@ ExpectedDecl ASTNodeImporter::VisitVarTemplateSpecializationDecl(
return TInfoOrErr.takeError(); return TInfoOrErr.takeError();
TemplateArgumentListInfo ToTAInfo; TemplateArgumentListInfo ToTAInfo;
if (Error Err = ImportTemplateArgumentListInfo( if (const ASTTemplateArgumentListInfo *Args = D->getTemplateArgsInfo()) {
D->getTemplateArgsInfo(), ToTAInfo)) if (Error Err = ImportTemplateArgumentListInfo(*Args, ToTAInfo))
return std::move(Err); return std::move(Err);
}
using PartVarSpecDecl = VarTemplatePartialSpecializationDecl; using PartVarSpecDecl = VarTemplatePartialSpecializationDecl;
// Create a new specialization. // Create a new specialization.

View File

@ -1335,10 +1335,14 @@ VarTemplateDecl *VarTemplateSpecializationDecl::getSpecializedTemplate() const {
void VarTemplateSpecializationDecl::setTemplateArgsInfo( void VarTemplateSpecializationDecl::setTemplateArgsInfo(
const TemplateArgumentListInfo &ArgsInfo) { const TemplateArgumentListInfo &ArgsInfo) {
TemplateArgsInfo.setLAngleLoc(ArgsInfo.getLAngleLoc()); TemplateArgsInfo =
TemplateArgsInfo.setRAngleLoc(ArgsInfo.getRAngleLoc()); ASTTemplateArgumentListInfo::Create(getASTContext(), ArgsInfo);
for (const TemplateArgumentLoc &Loc : ArgsInfo.arguments()) }
TemplateArgsInfo.addArgument(Loc);
void VarTemplateSpecializationDecl::setTemplateArgsInfo(
const ASTTemplateArgumentListInfo *ArgsInfo) {
TemplateArgsInfo =
ASTTemplateArgumentListInfo::Create(getASTContext(), ArgsInfo);
} }
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//

View File

@ -617,6 +617,17 @@ ASTTemplateArgumentListInfo::Create(const ASTContext &C,
return new (Mem) ASTTemplateArgumentListInfo(List); return new (Mem) ASTTemplateArgumentListInfo(List);
} }
const ASTTemplateArgumentListInfo *
ASTTemplateArgumentListInfo::Create(const ASTContext &C,
const ASTTemplateArgumentListInfo *List) {
if (!List)
return nullptr;
std::size_t size =
totalSizeToAlloc<TemplateArgumentLoc>(List->getNumTemplateArgs());
void *Mem = C.Allocate(size, alignof(ASTTemplateArgumentListInfo));
return new (Mem) ASTTemplateArgumentListInfo(List);
}
ASTTemplateArgumentListInfo::ASTTemplateArgumentListInfo( ASTTemplateArgumentListInfo::ASTTemplateArgumentListInfo(
const TemplateArgumentListInfo &Info) { const TemplateArgumentListInfo &Info) {
LAngleLoc = Info.getLAngleLoc(); LAngleLoc = Info.getLAngleLoc();
@ -628,6 +639,17 @@ ASTTemplateArgumentListInfo::ASTTemplateArgumentListInfo(
new (&ArgBuffer[i]) TemplateArgumentLoc(Info[i]); new (&ArgBuffer[i]) TemplateArgumentLoc(Info[i]);
} }
ASTTemplateArgumentListInfo::ASTTemplateArgumentListInfo(
const ASTTemplateArgumentListInfo *Info) {
LAngleLoc = Info->getLAngleLoc();
RAngleLoc = Info->getRAngleLoc();
NumTemplateArgs = Info->getNumTemplateArgs();
TemplateArgumentLoc *ArgBuffer = getTrailingObjects<TemplateArgumentLoc>();
for (unsigned i = 0; i != NumTemplateArgs; ++i)
new (&ArgBuffer[i]) TemplateArgumentLoc((*Info)[i]);
}
void ASTTemplateKWAndArgsInfo::initializeFrom( void ASTTemplateKWAndArgsInfo::initializeFrom(
SourceLocation TemplateKWLoc, const TemplateArgumentListInfo &Info, SourceLocation TemplateKWLoc, const TemplateArgumentListInfo &Info,
TemplateArgumentLoc *OutArgArray) { TemplateArgumentLoc *OutArgArray) {

View File

@ -3801,13 +3801,15 @@ Decl *TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl(
return nullptr; return nullptr;
// Substitute the current template arguments. // Substitute the current template arguments.
const TemplateArgumentListInfo &TemplateArgsInfo = D->getTemplateArgsInfo(); if (const ASTTemplateArgumentListInfo *TemplateArgsInfo =
VarTemplateArgsInfo.setLAngleLoc(TemplateArgsInfo.getLAngleLoc()); D->getTemplateArgsInfo()) {
VarTemplateArgsInfo.setRAngleLoc(TemplateArgsInfo.getRAngleLoc()); VarTemplateArgsInfo.setLAngleLoc(TemplateArgsInfo->getLAngleLoc());
VarTemplateArgsInfo.setRAngleLoc(TemplateArgsInfo->getRAngleLoc());
if (SemaRef.SubstTemplateArguments(TemplateArgsInfo.arguments(), TemplateArgs, if (SemaRef.SubstTemplateArguments(TemplateArgsInfo->arguments(),
VarTemplateArgsInfo)) TemplateArgs, VarTemplateArgsInfo))
return nullptr; return nullptr;
}
// Check that the template argument list is well-formed for this template. // Check that the template argument list is well-formed for this template.
SmallVector<TemplateArgument, 4> Converted; SmallVector<TemplateArgument, 4> Converted;
@ -5554,8 +5556,18 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
// declaration of the definition. // declaration of the definition.
TemplateDeclInstantiator Instantiator(*this, Var->getDeclContext(), TemplateDeclInstantiator Instantiator(*this, Var->getDeclContext(),
TemplateArgs); TemplateArgs);
TemplateArgumentListInfo TemplateArgInfo;
if (const ASTTemplateArgumentListInfo *ArgInfo =
VarSpec->getTemplateArgsInfo()) {
TemplateArgInfo.setLAngleLoc(ArgInfo->getLAngleLoc());
TemplateArgInfo.setRAngleLoc(ArgInfo->getRAngleLoc());
for (const TemplateArgumentLoc &Arg : ArgInfo->arguments())
TemplateArgInfo.addArgument(Arg);
}
Var = cast_or_null<VarDecl>(Instantiator.VisitVarTemplateSpecializationDecl( Var = cast_or_null<VarDecl>(Instantiator.VisitVarTemplateSpecializationDecl(
VarSpec->getSpecializedTemplate(), Def, VarSpec->getTemplateArgsInfo(), VarSpec->getSpecializedTemplate(), Def, TemplateArgInfo,
VarSpec->getTemplateArgs().asArray(), VarSpec)); VarSpec->getTemplateArgs().asArray(), VarSpec));
if (Var) { if (Var) {
llvm::PointerUnion<VarTemplateDecl *, llvm::PointerUnion<VarTemplateDecl *,