[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)) {
if (auto *Args = Var->getTemplateArgsAsWritten())
return Args->arguments();
} else if (auto *Var = llvm::dyn_cast<VarTemplateSpecializationDecl>(&ND))
return Var->getTemplateArgsInfo().arguments();
} else if (auto *Var = llvm::dyn_cast<VarTemplateSpecializationDecl>(&ND)) {
if (auto *Args = Var->getTemplateArgsInfo())
return Args->arguments();
}
// We return None for ClassTemplateSpecializationDecls because it does not
// contain TemplateArgumentLoc information.
return llvm::None;

View File

@ -168,6 +168,8 @@ Bug Fixes
`Issue 55562 <https://github.com/llvm/llvm-project/issues/55562>`_.
- Clang will allow calling a ``consteval`` function in a default argument. This
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
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

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

View File

@ -618,6 +618,9 @@ private:
ASTTemplateArgumentListInfo(const TemplateArgumentListInfo &List);
// FIXME: Is it ever necessary to copy to another context?
ASTTemplateArgumentListInfo(const ASTTemplateArgumentListInfo *List);
public:
/// The source location of the left angle bracket ('<').
SourceLocation LAngleLoc;
@ -647,6 +650,10 @@ public:
static const ASTTemplateArgumentListInfo *
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.,

View File

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

View File

@ -1335,10 +1335,14 @@ VarTemplateDecl *VarTemplateSpecializationDecl::getSpecializedTemplate() const {
void VarTemplateSpecializationDecl::setTemplateArgsInfo(
const TemplateArgumentListInfo &ArgsInfo) {
TemplateArgsInfo.setLAngleLoc(ArgsInfo.getLAngleLoc());
TemplateArgsInfo.setRAngleLoc(ArgsInfo.getRAngleLoc());
for (const TemplateArgumentLoc &Loc : ArgsInfo.arguments())
TemplateArgsInfo.addArgument(Loc);
TemplateArgsInfo =
ASTTemplateArgumentListInfo::Create(getASTContext(), ArgsInfo);
}
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);
}
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(
const TemplateArgumentListInfo &Info) {
LAngleLoc = Info.getLAngleLoc();
@ -628,6 +639,17 @@ ASTTemplateArgumentListInfo::ASTTemplateArgumentListInfo(
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(
SourceLocation TemplateKWLoc, const TemplateArgumentListInfo &Info,
TemplateArgumentLoc *OutArgArray) {

View File

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