From: Argyrios Kyrtzidis Date: Thu, 22 Sep 2011 20:07:09 +0000 (+0000) Subject: Don't use TemplateArgumentListInfo inside AST nodes because it may leak. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=71a7605977113c795edd44fcbd2302ad49506653;p=clang Don't use TemplateArgumentListInfo inside AST nodes because it may leak. Use ASTTemplateArgumentListInfo instead. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@140331 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index ab4f21eec9..c28242d118 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -33,6 +33,7 @@ class StringLiteral; class NestedNameSpecifier; class TemplateParameterList; class TemplateArgumentList; +struct ASTTemplateArgumentListInfo; class MemberSpecializationInfo; class FunctionTemplateSpecializationInfo; class DependentFunctionTemplateSpecializationInfo; @@ -1918,7 +1919,7 @@ public: /// or if it had no explicit template argument list, returns NULL. /// Note that it an explicit template argument list may be written empty, /// e.g., template<> void foo<>(char* s); - const TemplateArgumentListInfo* + const ASTTemplateArgumentListInfo* getTemplateSpecializationArgsAsWritten() const; /// \brief Specify that this function declaration is actually a function diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h index 0fa4a765c2..04c6674426 100644 --- a/include/clang/AST/DeclTemplate.h +++ b/include/clang/AST/DeclTemplate.h @@ -264,7 +264,7 @@ class FunctionTemplateSpecializationInfo : public llvm::FoldingSetNode { FunctionTemplateDecl *Template, TemplateSpecializationKind TSK, const TemplateArgumentList *TemplateArgs, - const TemplateArgumentListInfo *TemplateArgsAsWritten, + const ASTTemplateArgumentListInfo *TemplateArgsAsWritten, SourceLocation POI) : Function(FD), Template(Template, TSK - 1), @@ -278,12 +278,7 @@ public: TemplateSpecializationKind TSK, const TemplateArgumentList *TemplateArgs, const TemplateArgumentListInfo *TemplateArgsAsWritten, - SourceLocation POI) { - return new (C) FunctionTemplateSpecializationInfo(FD, Template, TSK, - TemplateArgs, - TemplateArgsAsWritten, - POI); - } + SourceLocation POI); /// \brief The function template specialization that this structure /// describes. @@ -300,7 +295,7 @@ public: const TemplateArgumentList *TemplateArguments; /// \brief The template arguments as written in the sources, if provided. - const TemplateArgumentListInfo *TemplateArgumentsAsWritten; + const ASTTemplateArgumentListInfo *TemplateArgumentsAsWritten; /// \brief The point at which this function template specialization was /// first instantiated. diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 0c891519b3..694dd5c6ff 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -20,6 +20,7 @@ #include "clang/AST/DeclAccessPair.h" #include "clang/AST/OperationKinds.h" #include "clang/AST/ASTVector.h" +#include "clang/AST/TemplateBase.h" #include "clang/AST/UsuallyTinyPtrVector.h" #include "clang/Basic/TypeTraits.h" #include "llvm/ADT/APSInt.h" @@ -41,8 +42,6 @@ namespace clang { class CXXOperatorCallExpr; class CXXMemberCallExpr; class ObjCPropertyRefExpr; - class TemplateArgumentLoc; - class TemplateArgumentListInfo; class OpaqueValueExpr; /// \brief A simple array of base specifiers. @@ -688,41 +687,6 @@ public: static bool classof(const OpaqueValueExpr *) { return true; } }; -/// \brief Represents an explicit template argument list in C++, e.g., -/// the "" in "sort". -/// This is safe to be used inside an AST node, in contrast with -/// TemplateArgumentListInfo. -struct ASTTemplateArgumentListInfo { - /// \brief The source location of the left angle bracket ('<'); - SourceLocation LAngleLoc; - - /// \brief The source location of the right angle bracket ('>'); - SourceLocation RAngleLoc; - - /// \brief The number of template arguments in TemplateArgs. - /// The actual template arguments (if any) are stored after the - /// ExplicitTemplateArgumentList structure. - unsigned NumTemplateArgs; - - /// \brief Retrieve the template arguments - TemplateArgumentLoc *getTemplateArgs() { - return reinterpret_cast (this + 1); - } - - /// \brief Retrieve the template arguments - const TemplateArgumentLoc *getTemplateArgs() const { - return reinterpret_cast (this + 1); - } - - void initializeFrom(const TemplateArgumentListInfo &List); - void initializeFrom(const TemplateArgumentListInfo &List, - bool &Dependent, bool &InstantiationDependent, - bool &ContainsUnexpandedParameterPack); - void copyInto(TemplateArgumentListInfo &List) const; - static std::size_t sizeFor(unsigned NumTemplateArgs); - static std::size_t sizeFor(const TemplateArgumentListInfo &List); -}; - /// \brief A reference to a declared variable, function, enum, etc. /// [C99 6.5.1p2] /// diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index 473ba66f38..f4c8bae7d1 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -1552,10 +1552,10 @@ bool RecursiveASTVisitor::TraverseFunctionHelper(FunctionDecl *D) { FTSI->getTemplateSpecializationKind() != TSK_ImplicitInstantiation) { // A specialization might not have explicit template arguments if it has // a templated return type and concrete arguments. - if (const TemplateArgumentListInfo *TALI = + if (const ASTTemplateArgumentListInfo *TALI = FTSI->TemplateArgumentsAsWritten) { - TRY_TO(TraverseTemplateArgumentLocsHelper(TALI->getArgumentArray(), - TALI->size())); + TRY_TO(TraverseTemplateArgumentLocsHelper(TALI->getTemplateArgs(), + TALI->NumTemplateArgs)); } } } diff --git a/include/clang/AST/TemplateBase.h b/include/clang/AST/TemplateBase.h index 26021e4d7e..371c27a0d2 100644 --- a/include/clang/AST/TemplateBase.h +++ b/include/clang/AST/TemplateBase.h @@ -518,6 +518,10 @@ class TemplateArgumentListInfo { SourceLocation LAngleLoc; SourceLocation RAngleLoc; + // This can leak if used in an AST node, use ASTTemplateArgumentListInfo + // instead. + void* operator new(size_t bytes, ASTContext& C); + public: TemplateArgumentListInfo() {} @@ -546,6 +550,48 @@ public: } }; +/// \brief Represents an explicit template argument list in C++, e.g., +/// the "" in "sort". +/// This is safe to be used inside an AST node, in contrast with +/// TemplateArgumentListInfo. +struct ASTTemplateArgumentListInfo { + /// \brief The source location of the left angle bracket ('<'); + SourceLocation LAngleLoc; + + /// \brief The source location of the right angle bracket ('>'); + SourceLocation RAngleLoc; + + /// \brief The number of template arguments in TemplateArgs. + /// The actual template arguments (if any) are stored after the + /// ExplicitTemplateArgumentList structure. + unsigned NumTemplateArgs; + + /// \brief Retrieve the template arguments + TemplateArgumentLoc *getTemplateArgs() { + return reinterpret_cast (this + 1); + } + + /// \brief Retrieve the template arguments + const TemplateArgumentLoc *getTemplateArgs() const { + return reinterpret_cast (this + 1); + } + + const TemplateArgumentLoc &operator[](unsigned I) const { + return getTemplateArgs()[I]; + } + + static const ASTTemplateArgumentListInfo *Create(ASTContext &C, + const TemplateArgumentListInfo &List); + + void initializeFrom(const TemplateArgumentListInfo &List); + void initializeFrom(const TemplateArgumentListInfo &List, + bool &Dependent, bool &InstantiationDependent, + bool &ContainsUnexpandedParameterPack); + void copyInto(TemplateArgumentListInfo &List) const; + static std::size_t sizeFor(unsigned NumTemplateArgs); + static std::size_t sizeFor(const TemplateArgumentListInfo &List); +}; + const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, const TemplateArgument &Arg); diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 3a2d532f18..57f9995fce 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -1999,7 +1999,7 @@ FunctionDecl::getTemplateSpecializationArgs() const { return 0; } -const TemplateArgumentListInfo * +const ASTTemplateArgumentListInfo * FunctionDecl::getTemplateSpecializationArgsAsWritten() const { if (FunctionTemplateSpecializationInfo *Info = TemplateOrSpecialization diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp index 7ed2ce851b..078869cec4 100644 --- a/lib/AST/DeclTemplate.cpp +++ b/lib/AST/DeclTemplate.cpp @@ -563,6 +563,24 @@ TemplateArgumentList::CreateCopy(ASTContext &Context, return new (Mem) TemplateArgumentList(StoredArgs, NumArgs, true); } +FunctionTemplateSpecializationInfo * +FunctionTemplateSpecializationInfo::Create(ASTContext &C, FunctionDecl *FD, + FunctionTemplateDecl *Template, + TemplateSpecializationKind TSK, + const TemplateArgumentList *TemplateArgs, + const TemplateArgumentListInfo *TemplateArgsAsWritten, + SourceLocation POI) { + const ASTTemplateArgumentListInfo *ArgsAsWritten = 0; + if (TemplateArgsAsWritten) + ArgsAsWritten = ASTTemplateArgumentListInfo::Create(C, + *TemplateArgsAsWritten); + + return new (C) FunctionTemplateSpecializationInfo(FD, Template, TSK, + TemplateArgs, + ArgsAsWritten, + POI); +} + //===----------------------------------------------------------------------===// // ClassTemplateSpecializationDecl Implementation //===----------------------------------------------------------------------===// diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 5196bf1ae3..374c1a03a7 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -130,57 +130,6 @@ SourceLocation Expr::getExprLoc() const { // Primary Expressions. //===----------------------------------------------------------------------===// -void ASTTemplateArgumentListInfo::initializeFrom( - const TemplateArgumentListInfo &Info) { - LAngleLoc = Info.getLAngleLoc(); - RAngleLoc = Info.getRAngleLoc(); - NumTemplateArgs = Info.size(); - - TemplateArgumentLoc *ArgBuffer = getTemplateArgs(); - for (unsigned i = 0; i != NumTemplateArgs; ++i) - new (&ArgBuffer[i]) TemplateArgumentLoc(Info[i]); -} - -void ASTTemplateArgumentListInfo::initializeFrom( - const TemplateArgumentListInfo &Info, - bool &Dependent, - bool &InstantiationDependent, - bool &ContainsUnexpandedParameterPack) { - LAngleLoc = Info.getLAngleLoc(); - RAngleLoc = Info.getRAngleLoc(); - NumTemplateArgs = Info.size(); - - TemplateArgumentLoc *ArgBuffer = getTemplateArgs(); - for (unsigned i = 0; i != NumTemplateArgs; ++i) { - Dependent = Dependent || Info[i].getArgument().isDependent(); - InstantiationDependent = InstantiationDependent || - Info[i].getArgument().isInstantiationDependent(); - ContainsUnexpandedParameterPack - = ContainsUnexpandedParameterPack || - Info[i].getArgument().containsUnexpandedParameterPack(); - - new (&ArgBuffer[i]) TemplateArgumentLoc(Info[i]); - } -} - -void ASTTemplateArgumentListInfo::copyInto( - TemplateArgumentListInfo &Info) const { - Info.setLAngleLoc(LAngleLoc); - Info.setRAngleLoc(RAngleLoc); - for (unsigned I = 0; I != NumTemplateArgs; ++I) - Info.addArgument(getTemplateArgs()[I]); -} - -std::size_t ASTTemplateArgumentListInfo::sizeFor(unsigned NumTemplateArgs) { - return sizeof(ASTTemplateArgumentListInfo) + - sizeof(TemplateArgumentLoc) * NumTemplateArgs; -} - -std::size_t ASTTemplateArgumentListInfo::sizeFor( - const TemplateArgumentListInfo &Info) { - return sizeFor(Info.size()); -} - /// \brief Compute the type-, value-, and instantiation-dependence of a /// declaration reference /// based on the declaration being referenced. diff --git a/lib/AST/TemplateBase.cpp b/lib/AST/TemplateBase.cpp index d565a47733..b963cec42c 100644 --- a/lib/AST/TemplateBase.cpp +++ b/lib/AST/TemplateBase.cpp @@ -530,3 +530,65 @@ const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB, return DB; } + +const ASTTemplateArgumentListInfo * +ASTTemplateArgumentListInfo::Create(ASTContext &C, + const TemplateArgumentListInfo &List) { + std::size_t size = sizeof(CXXDependentScopeMemberExpr) + + ASTTemplateArgumentListInfo::sizeFor(List); + void *Mem = C.Allocate(size, llvm::alignOf()); + ASTTemplateArgumentListInfo *TAI = new (Mem) ASTTemplateArgumentListInfo(); + TAI->initializeFrom(List); + return TAI; +} + +void ASTTemplateArgumentListInfo::initializeFrom( + const TemplateArgumentListInfo &Info) { + LAngleLoc = Info.getLAngleLoc(); + RAngleLoc = Info.getRAngleLoc(); + NumTemplateArgs = Info.size(); + + TemplateArgumentLoc *ArgBuffer = getTemplateArgs(); + for (unsigned i = 0; i != NumTemplateArgs; ++i) + new (&ArgBuffer[i]) TemplateArgumentLoc(Info[i]); +} + +void ASTTemplateArgumentListInfo::initializeFrom( + const TemplateArgumentListInfo &Info, + bool &Dependent, + bool &InstantiationDependent, + bool &ContainsUnexpandedParameterPack) { + LAngleLoc = Info.getLAngleLoc(); + RAngleLoc = Info.getRAngleLoc(); + NumTemplateArgs = Info.size(); + + TemplateArgumentLoc *ArgBuffer = getTemplateArgs(); + for (unsigned i = 0; i != NumTemplateArgs; ++i) { + Dependent = Dependent || Info[i].getArgument().isDependent(); + InstantiationDependent = InstantiationDependent || + Info[i].getArgument().isInstantiationDependent(); + ContainsUnexpandedParameterPack + = ContainsUnexpandedParameterPack || + Info[i].getArgument().containsUnexpandedParameterPack(); + + new (&ArgBuffer[i]) TemplateArgumentLoc(Info[i]); + } +} + +void ASTTemplateArgumentListInfo::copyInto( + TemplateArgumentListInfo &Info) const { + Info.setLAngleLoc(LAngleLoc); + Info.setRAngleLoc(RAngleLoc); + for (unsigned I = 0; I != NumTemplateArgs; ++I) + Info.addArgument(getTemplateArgs()[I]); +} + +std::size_t ASTTemplateArgumentListInfo::sizeFor(unsigned NumTemplateArgs) { + return sizeof(ASTTemplateArgumentListInfo) + + sizeof(TemplateArgumentLoc) * NumTemplateArgs; +} + +std::size_t ASTTemplateArgumentListInfo::sizeFor( + const TemplateArgumentListInfo &Info) { + return sizeFor(Info.size()); +} diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 341cf4de94..43fdcb6d4a 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -5522,12 +5522,10 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD, // Take copies of (semantic and syntactic) template argument lists. const TemplateArgumentList* TemplArgs = new (Context) TemplateArgumentList(Specialization->getTemplateSpecializationArgs()); - const TemplateArgumentListInfo* TemplArgsAsWritten = ExplicitTemplateArgs - ? new (Context) TemplateArgumentListInfo(*ExplicitTemplateArgs) : 0; FD->setFunctionTemplateSpecialization(Specialization->getPrimaryTemplate(), TemplArgs, /*InsertPos=*/0, SpecInfo->getTemplateSpecializationKind(), - TemplArgsAsWritten); + ExplicitTemplateArgs); FD->setStorageClass(Specialization->getStorageClass()); // The "previous declaration" for this function template specialization is diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index 77b05fd5a3..01b635ef97 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -373,7 +373,8 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) { // Template args as written. SmallVector TemplArgLocs; SourceLocation LAngleLoc, RAngleLoc; - if (Record[Idx++]) { // TemplateArgumentsAsWritten != 0 + bool HasTemplateArgumentsAsWritten = Record[Idx++]; + if (HasTemplateArgumentsAsWritten) { unsigned NumTemplateArgLocs = Record[Idx++]; TemplArgLocs.reserve(NumTemplateArgLocs); for (unsigned i=0; i != NumTemplateArgLocs; ++i) @@ -389,14 +390,14 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) { ASTContext &C = Reader.getContext(); TemplateArgumentList *TemplArgList = TemplateArgumentList::CreateCopy(C, TemplArgs.data(), TemplArgs.size()); - TemplateArgumentListInfo *TemplArgsInfo - = new (C) TemplateArgumentListInfo(LAngleLoc, RAngleLoc); + TemplateArgumentListInfo TemplArgsInfo(LAngleLoc, RAngleLoc); for (unsigned i=0, e = TemplArgLocs.size(); i != e; ++i) - TemplArgsInfo->addArgument(TemplArgLocs[i]); + TemplArgsInfo.addArgument(TemplArgLocs[i]); FunctionTemplateSpecializationInfo *FTInfo = FunctionTemplateSpecializationInfo::Create(C, FD, Template, TSK, TemplArgList, - TemplArgsInfo, POI); + HasTemplateArgumentsAsWritten ? &TemplArgsInfo : 0, + POI); FD->TemplateOrSpecialization = FTInfo; if (FD->isCanonicalDecl()) { // if canonical add to template's set. diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp index 80685ad674..a7468a77a3 100644 --- a/lib/Serialization/ASTWriterDecl.cpp +++ b/lib/Serialization/ASTWriterDecl.cpp @@ -321,13 +321,14 @@ void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) { // Template args as written. Record.push_back(FTSInfo->TemplateArgumentsAsWritten != 0); if (FTSInfo->TemplateArgumentsAsWritten) { - Record.push_back(FTSInfo->TemplateArgumentsAsWritten->size()); - for (int i=0, e = FTSInfo->TemplateArgumentsAsWritten->size(); i!=e; ++i) + Record.push_back(FTSInfo->TemplateArgumentsAsWritten->NumTemplateArgs); + for (int i=0, e = FTSInfo->TemplateArgumentsAsWritten->NumTemplateArgs; + i!=e; ++i) Writer.AddTemplateArgumentLoc((*FTSInfo->TemplateArgumentsAsWritten)[i], Record); - Writer.AddSourceLocation(FTSInfo->TemplateArgumentsAsWritten->getLAngleLoc(), + Writer.AddSourceLocation(FTSInfo->TemplateArgumentsAsWritten->LAngleLoc, Record); - Writer.AddSourceLocation(FTSInfo->TemplateArgumentsAsWritten->getRAngleLoc(), + Writer.AddSourceLocation(FTSInfo->TemplateArgumentsAsWritten->RAngleLoc, Record); }