From 2a82ca255b0f99f6201a75ed52b91fc024f6e9cf Mon Sep 17 00:00:00 2001 From: Argyrios Kyrtzidis Date: Wed, 28 Nov 2012 03:56:16 +0000 Subject: [PATCH] Introduce ASTUnresolvedSet, an UnresolvedSet-like class, whose contents are allocated using the allocator associated with an ASTContext. Use this inside CXXRecordDecl::DefinitionData instead of an UnresolvedSet to avoid a potential memory leak. rdar://12761275 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@168771 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/ASTUnresolvedSet.h | 86 +++++++++++++++++++++++++ include/clang/AST/ASTVector.h | 4 +- include/clang/AST/DeclCXX.h | 6 +- include/clang/AST/Expr.h | 4 +- include/clang/AST/UnresolvedSet.h | 5 +- include/clang/Serialization/ASTReader.h | 3 +- include/clang/Serialization/ASTWriter.h | 3 +- lib/AST/DeclCXX.cpp | 20 +++--- lib/Serialization/ASTReader.cpp | 5 +- lib/Serialization/ASTReaderStmt.cpp | 2 +- lib/Serialization/ASTWriter.cpp | 4 +- 11 files changed, 117 insertions(+), 25 deletions(-) create mode 100644 include/clang/AST/ASTUnresolvedSet.h diff --git a/include/clang/AST/ASTUnresolvedSet.h b/include/clang/AST/ASTUnresolvedSet.h new file mode 100644 index 0000000000..26c5406802 --- /dev/null +++ b/include/clang/AST/ASTUnresolvedSet.h @@ -0,0 +1,86 @@ +//===-- ASTUnresolvedSet.h - Unresolved sets of declarations ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides an UnresolvedSet-like class, whose contents are +// allocated using the allocator associated with an ASTContext. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_ASTUNRESOLVEDSET_H +#define LLVM_CLANG_AST_ASTUNRESOLVEDSET_H + +#include "clang/AST/UnresolvedSet.h" +#include "clang/AST/ASTVector.h" + +namespace clang { + +/// \brief An UnresolvedSet-like class which uses the ASTContext's allocator. +class ASTUnresolvedSet { + typedef ASTVector DeclsTy; + DeclsTy Decls; + + ASTUnresolvedSet(const ASTUnresolvedSet &) LLVM_DELETED_FUNCTION; + void operator=(const ASTUnresolvedSet &) LLVM_DELETED_FUNCTION; + +public: + ASTUnresolvedSet() {} + ASTUnresolvedSet(ASTContext &C, unsigned N) : Decls(C, N) {} + + typedef UnresolvedSetIterator iterator; + typedef UnresolvedSetIterator const_iterator; + + iterator begin() { return iterator(Decls.begin()); } + iterator end() { return iterator(Decls.end()); } + + const_iterator begin() const { return const_iterator(Decls.begin()); } + const_iterator end() const { return const_iterator(Decls.end()); } + + void addDecl(ASTContext &C, NamedDecl *D) { + addDecl(C, D, AS_none); + } + + void addDecl(ASTContext &C, NamedDecl *D, AccessSpecifier AS) { + Decls.push_back(DeclAccessPair::make(D, AS), C); + } + + /// Replaces the given declaration with the new one, once. + /// + /// \return true if the set changed + bool replace(const NamedDecl* Old, NamedDecl *New) { + for (DeclsTy::iterator I = Decls.begin(), E = Decls.end(); I != E; ++I) + if (I->getDecl() == Old) + return (I->setDecl(New), true); + return false; + } + + void erase(unsigned I) { + Decls[I] = Decls.back(); + Decls.pop_back(); + } + + void clear() { Decls.clear(); } + + bool empty() const { return Decls.empty(); } + unsigned size() const { return Decls.size(); } + + void reserve(ASTContext &C, unsigned N) { + Decls.reserve(C, N); + } + + void append(ASTContext &C, iterator I, iterator E) { + Decls.append(C, I.ir, E.ir); + } + + DeclAccessPair &operator[](unsigned I) { return Decls[I]; } + const DeclAccessPair &operator[](unsigned I) const { return Decls[I]; } +}; + +} // namespace clang + +#endif diff --git a/include/clang/AST/ASTVector.h b/include/clang/AST/ASTVector.h index 4ff5ea37b8..91966520d8 100644 --- a/include/clang/AST/ASTVector.h +++ b/include/clang/AST/ASTVector.h @@ -59,7 +59,9 @@ class ASTVector { public: // Default ctor - Initialize to empty. - explicit ASTVector(ASTContext &C, unsigned N = 0) + ASTVector() : Begin(NULL), End(NULL), Capacity(NULL) { } + + ASTVector(ASTContext &C, unsigned N) : Begin(NULL), End(NULL), Capacity(NULL) { reserve(C, N); } diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index 6abc82d7be..7e89e1e21a 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -19,7 +19,7 @@ #include "clang/AST/ExprCXX.h" #include "clang/AST/Decl.h" #include "clang/AST/TypeLoc.h" -#include "clang/AST/UnresolvedSet.h" +#include "clang/AST/ASTUnresolvedSet.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/SmallPtrSet.h" @@ -522,14 +522,14 @@ class CXXRecordDecl : public RecordDecl { /// of this C++ class (but not its inherited conversion /// functions). Each of the entries in this overload set is a /// CXXConversionDecl. - UnresolvedSet<4> Conversions; + ASTUnresolvedSet Conversions; /// VisibleConversions - Overload set containing the conversion /// functions of this C++ class and all those inherited conversion /// functions that are visible in this class. Each of the entries /// in this overload set is a CXXConversionDecl or a /// FunctionTemplateDecl. - UnresolvedSet<4> VisibleConversions; + ASTUnresolvedSet VisibleConversions; /// Definition - The declaration which defines this record. CXXRecordDecl *Definition; diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index dc83654bd9..ac35bf8bd6 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -3580,8 +3580,8 @@ public: ArrayRef initExprs, SourceLocation rbraceloc); /// \brief Build an empty initializer list. - explicit InitListExpr(ASTContext &C, EmptyShell Empty) - : Expr(InitListExprClass, Empty), InitExprs(C) { } + explicit InitListExpr(EmptyShell Empty) + : Expr(InitListExprClass, Empty) { } unsigned getNumInits() const { return InitExprs.size(); } diff --git a/include/clang/AST/UnresolvedSet.h b/include/clang/AST/UnresolvedSet.h index 9f11ee5fe3..de96601323 100644 --- a/include/clang/AST/UnresolvedSet.h +++ b/include/clang/AST/UnresolvedSet.h @@ -25,12 +25,13 @@ namespace clang { /// non-const iterator. class UnresolvedSetIterator { private: - typedef SmallVectorImpl DeclsTy; + typedef llvm::MutableArrayRef DeclsTy; typedef DeclsTy::iterator IteratorTy; IteratorTy ir; friend class UnresolvedSetImpl; + friend class ASTUnresolvedSet; friend class OverloadExpr; explicit UnresolvedSetIterator(DeclsTy::iterator ir) : ir(ir) {} explicit UnresolvedSetIterator(DeclsTy::const_iterator ir) : @@ -87,7 +88,7 @@ public: /// UnresolvedSet - A set of unresolved declarations. class UnresolvedSetImpl { - typedef UnresolvedSetIterator::DeclsTy DeclsTy; + typedef SmallVectorImpl DeclsTy; // Don't allow direct construction, and only permit subclassing by // UnresolvedSet. diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h index 14550baf8d..6b3c4f107f 100644 --- a/include/clang/Serialization/ASTReader.h +++ b/include/clang/Serialization/ASTReader.h @@ -85,6 +85,7 @@ class TypeLocReader; struct HeaderFileInfo; class VersionTuple; class TargetOptions; +class ASTUnresolvedSet; /// \brief Abstract interface for callback invocations by the ASTReader. /// @@ -1612,7 +1613,7 @@ public: unsigned &Idx); /// \brief Read a UnresolvedSet structure. - void ReadUnresolvedSet(ModuleFile &F, UnresolvedSetImpl &Set, + void ReadUnresolvedSet(ModuleFile &F, ASTUnresolvedSet &Set, const RecordData &Record, unsigned &Idx); /// \brief Read a C++ base specifier. diff --git a/include/clang/Serialization/ASTWriter.h b/include/clang/Serialization/ASTWriter.h index ac81e2164c..19636bfbd9 100644 --- a/include/clang/Serialization/ASTWriter.h +++ b/include/clang/Serialization/ASTWriter.h @@ -63,6 +63,7 @@ class SourceManager; class SwitchCase; class TargetInfo; class VersionTuple; +class ASTUnresolvedSet; namespace SrcMgr { class SLocEntry; } @@ -603,7 +604,7 @@ public: RecordDataImpl &Record); /// \brief Emit a UnresolvedSet structure. - void AddUnresolvedSet(const UnresolvedSetImpl &Set, RecordDataImpl &Record); + void AddUnresolvedSet(const ASTUnresolvedSet &Set, RecordDataImpl &Record); /// \brief Emit a C++ base specifier. void AddCXXBaseSpecifier(const CXXBaseSpecifier &Base, diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index bf6107f052..d661aa04af 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -709,13 +709,13 @@ NotASpecialMember:; data().Conversions.replace(FunTmpl->getPreviousDecl(), FunTmpl); else - data().Conversions.addDecl(FunTmpl); + data().Conversions.addDecl(getASTContext(), FunTmpl); } else { if (Conversion->getPreviousDecl()) data().Conversions.replace(Conversion->getPreviousDecl(), Conversion); else - data().Conversions.addDecl(Conversion); + data().Conversions.addDecl(getASTContext(), Conversion); } } @@ -935,7 +935,7 @@ NotASpecialMember:; if (UsingShadowDecl *Shadow = dyn_cast(D)) if (Shadow->getDeclName().getNameKind() == DeclarationName::CXXConversionFunctionName) - data().Conversions.addDecl(Shadow, Shadow->getAccess()); + data().Conversions.addDecl(getASTContext(), Shadow, Shadow->getAccess()); } bool CXXRecordDecl::isCLike() const { @@ -996,7 +996,7 @@ static void CollectVisibleConversions(ASTContext &Context, bool InVirtual, AccessSpecifier Access, const llvm::SmallPtrSet &ParentHiddenTypes, - UnresolvedSetImpl &Output, + ASTUnresolvedSet &Output, UnresolvedSetImpl &VOutput, llvm::SmallPtrSet &HiddenVBaseCs) { // The set of types which have conversions in this class or its @@ -1032,7 +1032,7 @@ static void CollectVisibleConversions(ASTContext &Context, if (InVirtual) VOutput.addDecl(I.getDecl(), IAccess); else - Output.addDecl(I.getDecl(), IAccess); + Output.addDecl(Context, I.getDecl(), IAccess); } } } @@ -1059,7 +1059,7 @@ static void CollectVisibleConversions(ASTContext &Context, /// bases. It might be worth special-casing that, really. static void CollectVisibleConversions(ASTContext &Context, CXXRecordDecl *Record, - UnresolvedSetImpl &Output) { + ASTUnresolvedSet &Output) { // The collection of all conversions in virtual bases that we've // found. These will be added to the output as long as they don't // appear in the hidden-conversions set. @@ -1076,7 +1076,7 @@ static void CollectVisibleConversions(ASTContext &Context, // hidden-types set. CXXRecordDecl::conversion_iterator ConvI = Record->conversion_begin(); CXXRecordDecl::conversion_iterator ConvE = Record->conversion_end(); - Output.append(ConvI, ConvE); + Output.append(Context, ConvI, ConvE); for (; ConvI != ConvE; ++ConvI) HiddenTypes.insert(GetConversionType(Context, ConvI.getDecl())); @@ -1095,7 +1095,7 @@ static void CollectVisibleConversions(ASTContext &Context, for (UnresolvedSetIterator I = VBaseCs.begin(), E = VBaseCs.end(); I != E; ++I) { if (!HiddenVBaseCs.count(cast(I.getDecl()->getCanonicalDecl()))) - Output.addDecl(I.getDecl(), I.getAccess()); + Output.addDecl(Context, I.getDecl(), I.getAccess()); } } @@ -1127,7 +1127,7 @@ void CXXRecordDecl::removeConversion(const NamedDecl *ConvDecl) { // with sufficiently large numbers of directly-declared conversions // that asymptotic behavior matters. - UnresolvedSetImpl &Convs = data().Conversions; + ASTUnresolvedSet &Convs = data().Conversions; for (unsigned I = 0, E = Convs.size(); I != E; ++I) { if (Convs[I].getDecl() == ConvDecl) { Convs.erase(I); @@ -1266,7 +1266,7 @@ void CXXRecordDecl::completeDefinition(CXXFinalOverriderMap *FinalOverriders) { for (UnresolvedSetIterator I = data().Conversions.begin(), E = data().Conversions.end(); I != E; ++I) - data().Conversions.setAccess(I, (*I)->getAccess()); + I.setAccess((*I)->getAccess()); } bool CXXRecordDecl::mayBeAbstract() const { diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index 6e82cd9c76..ffed8356c9 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -6448,13 +6448,14 @@ ReadTemplateArgumentList(SmallVector &TemplArgs, } /// \brief Read a UnresolvedSet structure. -void ASTReader::ReadUnresolvedSet(ModuleFile &F, UnresolvedSetImpl &Set, +void ASTReader::ReadUnresolvedSet(ModuleFile &F, ASTUnresolvedSet &Set, const RecordData &Record, unsigned &Idx) { unsigned NumDecls = Record[Idx++]; + Set.reserve(Context, NumDecls); while (NumDecls--) { NamedDecl *D = ReadDeclAs(F, Record, Idx); AccessSpecifier AS = (AccessSpecifier)Record[Idx++]; - Set.addDecl(D, AS); + Set.addDecl(Context, D, AS); } } diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp index 367f75f55e..529cfea433 100644 --- a/lib/Serialization/ASTReaderStmt.cpp +++ b/lib/Serialization/ASTReaderStmt.cpp @@ -1868,7 +1868,7 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { break; case EXPR_INIT_LIST: - S = new (Context) InitListExpr(getContext(), Empty); + S = new (Context) InitListExpr(Empty); break; case EXPR_DESIGNATED_INIT: diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index 744ae9fd81..41665d8969 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -4480,9 +4480,9 @@ ASTWriter::AddTemplateArgumentList(const TemplateArgumentList *TemplateArgs, void -ASTWriter::AddUnresolvedSet(const UnresolvedSetImpl &Set, RecordDataImpl &Record) { +ASTWriter::AddUnresolvedSet(const ASTUnresolvedSet &Set, RecordDataImpl &Record) { Record.push_back(Set.size()); - for (UnresolvedSetImpl::const_iterator + for (ASTUnresolvedSet::const_iterator I = Set.begin(), E = Set.end(); I != E; ++I) { AddDeclRef(I.getDecl(), Record); Record.push_back(I.getAccess()); -- 2.40.0