[cfe-commits] r97607 - in /cfe/trunk: include/clang/AST/ASTContext.h lib/AST/ASTContext.cpp lib/AST/DeclCXX.cpp
Douglas Gregor
dgregor at apple.com
Tue Mar 2 15:58:15 PST 2010
Author: dgregor
Date: Tue Mar 2 17:58:15 2010
New Revision: 97607
URL: http://llvm.org/viewvc/llvm-project?rev=97607&view=rev
Log:
Eliminate the static map of overridden C++ methods, which was going to
come back to bite us at some point.
Modified:
cfe/trunk/include/clang/AST/ASTContext.h
cfe/trunk/lib/AST/ASTContext.cpp
cfe/trunk/lib/AST/DeclCXX.cpp
Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=97607&r1=97606&r2=97607&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Tue Mar 2 17:58:15 2010
@@ -67,6 +67,26 @@
namespace Builtin { class Context; }
+/// \brief A vector of C++ member functions that is optimized for
+/// storing a single method.
+class CXXMethodVector {
+ /// \brief Storage for the vector.
+ ///
+ /// When the low bit is zero, this is a const CXXMethodDecl *. When the
+ /// low bit is one, this is a std::vector<const CXXMethodDecl *> *.
+ mutable uintptr_t Storage;
+
+ typedef std::vector<const CXXMethodDecl *> vector_type;
+
+public:
+ typedef const CXXMethodDecl **iterator;
+ iterator begin() const;
+ iterator end() const;
+
+ void push_back(const CXXMethodDecl *Method);
+ void Destroy();
+};
+
/// ASTContext - This class holds long-lived AST nodes (such as types and
/// decls) that can be referred to throughout the semantic analysis of a file.
class ASTContext {
@@ -219,6 +239,14 @@
llvm::DenseMap<FieldDecl *, FieldDecl *> InstantiatedFromUnnamedFieldDecl;
+ /// \brief Mapping that stores the methods overridden by a given C++
+ /// member function.
+ ///
+ /// Since most C++ member functions aren't virtual and therefore
+ /// don't override anything, we store the overridden functions in
+ /// this map on the side rather than within the CXXMethodDecl structure.
+ llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector> OverriddenMethods;
+
TranslationUnitDecl *TUDecl;
/// SourceMgr - The associated SourceManager object.
@@ -310,6 +338,19 @@
void setInstantiatedFromUnnamedFieldDecl(FieldDecl *Inst, FieldDecl *Tmpl);
+ // Access to the set of methods overridden by the given C++ method.
+ typedef CXXMethodVector::iterator overridden_cxx_method_iterator;
+ overridden_cxx_method_iterator
+ overridden_methods_begin(const CXXMethodDecl *Method) const;
+
+ overridden_cxx_method_iterator
+ overridden_methods_end(const CXXMethodDecl *Method) const;
+
+ /// \brief Note that the given C++ \p Method overrides the given \p
+ /// Overridden method.
+ void addOverriddenMethod(const CXXMethodDecl *Method,
+ const CXXMethodDecl *Overridden);
+
TranslationUnitDecl *getTranslationUnitDecl() const { return TUDecl; }
Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=97607&r1=97606&r2=97607&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Tue Mar 2 17:58:15 2010
@@ -59,6 +59,12 @@
// Release the DenseMaps associated with DeclContext objects.
// FIXME: Is this the ideal solution?
ReleaseDeclContextMaps();
+
+ // Release all of the memory associated with overridden C++ methods.
+ for (llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector>::iterator
+ OM = OverriddenMethods.begin(), OMEnd = OverriddenMethods.end();
+ OM != OMEnd; ++OM)
+ OM->second.Destroy();
if (FreeMemory) {
// Deallocate all the types.
@@ -319,6 +325,80 @@
InstantiatedFromUnnamedFieldDecl[Inst] = Tmpl;
}
+CXXMethodVector::iterator CXXMethodVector::begin() const {
+ if ((Storage & 0x01) == 0)
+ return reinterpret_cast<iterator>(&Storage);
+
+ vector_type *Vec = reinterpret_cast<vector_type *>(Storage & ~0x01);
+ return &Vec->front();
+}
+
+CXXMethodVector::iterator CXXMethodVector::end() const {
+ if ((Storage & 0x01) == 0) {
+ if (Storage == 0)
+ return reinterpret_cast<iterator>(&Storage);
+
+ return reinterpret_cast<iterator>(&Storage) + 1;
+ }
+
+ vector_type *Vec = reinterpret_cast<vector_type *>(Storage & ~0x01);
+ return &Vec->front() + Vec->size();
+}
+
+void CXXMethodVector::push_back(const CXXMethodDecl *Method) {
+ if (Storage == 0) {
+ // 0 -> 1 element.
+ Storage = reinterpret_cast<uintptr_t>(Method);
+ return;
+ }
+
+ vector_type *Vec;
+ if ((Storage & 0x01) == 0) {
+ // 1 -> 2 elements. Allocate a new vector and push the element into that
+ // vector.
+ Vec = new vector_type;
+ Vec->push_back(reinterpret_cast<const CXXMethodDecl *>(Storage));
+ Storage = reinterpret_cast<uintptr_t>(Vec) | 0x01;
+ } else
+ Vec = reinterpret_cast<vector_type *>(Storage & ~0x01);
+
+ // Add the new method to the vector.
+ Vec->push_back(Method);
+}
+
+void CXXMethodVector::Destroy() {
+ if (Storage & 0x01)
+ delete reinterpret_cast<vector_type *>(Storage & ~0x01);
+
+ Storage = 0;
+}
+
+
+ASTContext::overridden_cxx_method_iterator
+ASTContext::overridden_methods_begin(const CXXMethodDecl *Method) const {
+ llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector>::const_iterator Pos
+ = OverriddenMethods.find(Method);
+ if (Pos == OverriddenMethods.end())
+ return 0;
+
+ return Pos->second.begin();
+}
+
+ASTContext::overridden_cxx_method_iterator
+ASTContext::overridden_methods_end(const CXXMethodDecl *Method) const {
+ llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector>::const_iterator Pos
+ = OverriddenMethods.find(Method);
+ if (Pos == OverriddenMethods.end())
+ return 0;
+
+ return Pos->second.end();
+}
+
+void ASTContext::addOverriddenMethod(const CXXMethodDecl *Method,
+ const CXXMethodDecl *Overridden) {
+ OverriddenMethods[Method].push_back(Overridden);
+}
+
namespace {
class BeforeInTranslationUnit
: std::binary_function<SourceRange, SourceRange, bool> {
Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=97607&r1=97606&r2=97607&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Tue Mar 2 17:58:15 2010
@@ -611,51 +611,20 @@
return true;
}
-typedef llvm::DenseMap<const CXXMethodDecl*,
- std::vector<const CXXMethodDecl *> *>
- OverriddenMethodsMapTy;
-
-// FIXME: We hate static data. This doesn't survive PCH saving/loading, and
-// the vtable building code uses it at CG time.
-static OverriddenMethodsMapTy *OverriddenMethods = 0;
-
void CXXMethodDecl::addOverriddenMethod(const CXXMethodDecl *MD) {
assert(MD->isCanonicalDecl() && "Method is not canonical!");
assert(!MD->getParent()->isDependentContext() &&
"Can't add an overridden method to a class template!");
- // FIXME: The CXXMethodDecl dtor needs to remove and free the entry.
-
- if (!OverriddenMethods)
- OverriddenMethods = new OverriddenMethodsMapTy();
-
- std::vector<const CXXMethodDecl *> *&Methods = (*OverriddenMethods)[this];
- if (!Methods)
- Methods = new std::vector<const CXXMethodDecl *>;
-
- Methods->push_back(MD);
+ getASTContext().addOverriddenMethod(this, MD);
}
CXXMethodDecl::method_iterator CXXMethodDecl::begin_overridden_methods() const {
- if (!OverriddenMethods)
- return 0;
-
- OverriddenMethodsMapTy::iterator it = OverriddenMethods->find(this);
- if (it == OverriddenMethods->end() || it->second->empty())
- return 0;
-
- return &(*it->second)[0];
+ return getASTContext().overridden_methods_begin(this);
}
CXXMethodDecl::method_iterator CXXMethodDecl::end_overridden_methods() const {
- if (!OverriddenMethods)
- return 0;
-
- OverriddenMethodsMapTy::iterator it = OverriddenMethods->find(this);
- if (it == OverriddenMethods->end() || it->second->empty())
- return 0;
-
- return &(*it->second)[0] + it->second->size();
+ return getASTContext().overridden_methods_end(this);
}
QualType CXXMethodDecl::getThisType(ASTContext &C) const {
More information about the cfe-commits
mailing list