From: Douglas Gregor Date: Mon, 30 Aug 2010 16:49:28 +0000 (+0000) Subject: Heap-allocate the attribute vectors in X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6320064d0c60fa8683f5623881c9394fd4aa7689;p=clang Heap-allocate the attribute vectors in ASTContext::DeclAttrs. Otherwise, iterators will go stale when the DenseMap reallocates, which can cause crashes when, e.g., looping over the attributes in a template to instantiate them and add the results to the instantiation of that template. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@112488 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 20c8d1f41d..ae4ee946fe 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -198,7 +198,7 @@ class ASTContext { /// /// Since so few decls have attrs, we keep them in a hash map instead of /// wasting space in the Decl class. - llvm::DenseMap DeclAttrs; + llvm::DenseMap DeclAttrs; /// \brief Keeps track of the static data member templates from which /// static data members of class template specializations were instantiated. @@ -321,10 +321,10 @@ public: } /// \brief Retrieve the attributes for the given declaration. - AttrVec& getDeclAttrs(const Decl *D) { return DeclAttrs[D]; } + AttrVec& getDeclAttrs(const Decl *D); /// \brief Erase the attributes corresponding to the given declaration. - void eraseDeclAttrs(const Decl *D) { DeclAttrs.erase(D); } + void eraseDeclAttrs(const Decl *D); /// \brief If this variable is an instantiated static data member of a /// class template specialization, returns the templated static data member diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 749c9db6d6..8c61b5c750 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -206,7 +206,12 @@ ASTContext::~ASTContext() { if (ASTRecordLayout *R = const_cast((I++)->second)) R->Destroy(*this); } - } + + for (llvm::DenseMap::iterator A = DeclAttrs.begin(), + AEnd = DeclAttrs.end(); + A != AEnd; ++A) + A->second->~AttrVec(); +} void ASTContext::AddDeallocation(void (*Callback)(void*), void *Data) { Deallocations.push_back(std::make_pair(Callback, Data)); @@ -364,6 +369,26 @@ void ASTContext::InitBuiltinTypes() { InitBuiltinType(NullPtrTy, BuiltinType::NullPtr); } +AttrVec& ASTContext::getDeclAttrs(const Decl *D) { + AttrVec *&Result = DeclAttrs[D]; + if (!Result) { + void *Mem = Allocate(sizeof(AttrVec)); + Result = new (Mem) AttrVec; + } + + return *Result; +} + +/// \brief Erase the attributes corresponding to the given declaration. +void ASTContext::eraseDeclAttrs(const Decl *D) { + llvm::DenseMap::iterator Pos = DeclAttrs.find(D); + if (Pos != DeclAttrs.end()) { + Pos->second->~AttrVec(); + DeclAttrs.erase(Pos); + } +} + + MemberSpecializationInfo * ASTContext::getInstantiatedFromStaticDataMember(const VarDecl *Var) { assert(Var->isStaticDataMember() && "Not a static data member");