Avoid allocating extra memory to handle the lazy definition data pointer for
authorRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 22 May 2014 23:19:02 +0000 (23:19 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 22 May 2014 23:19:02 +0000 (23:19 +0000)
CXXRecordDecls when modules is enabled.

llvm-svn: 209482

clang/include/clang/AST/DeclCXX.h
clang/lib/AST/Decl.cpp
clang/lib/AST/DeclCXX.cpp
clang/lib/Serialization/ASTReaderDecl.cpp

index 4b268d4..01af64a 100644 (file)
@@ -257,10 +257,31 @@ public:
   TypeSourceInfo *getTypeSourceInfo() const { return BaseTypeInfo; }
 };
 
+/// \brief A lazy pointer to the definition data for a declaration.
+/// FIXME: This is a little CXXRecordDecl-specific that the moment.
+template<typename Decl, typename T> class LazyDefinitionDataPtr {
+  llvm::PointerUnion<T *, Decl *> DataOrCanonicalDecl;
+
+  LazyDefinitionDataPtr update() {
+    if (Decl *Canon = DataOrCanonicalDecl.template dyn_cast<Decl*>()) {
+      if (Canon->isCanonicalDecl())
+        Canon->getMostRecentDecl();
+      else
+        // Declaration isn't canonical any more;
+        // update it and perform path compression.
+        *this = Canon->getPreviousDecl()->DefinitionData.update();
+    }
+    return *this;
+  }
+
+public:
+  LazyDefinitionDataPtr(Decl *Canon) : DataOrCanonicalDecl(Canon) {}
+  LazyDefinitionDataPtr(T *Data) : DataOrCanonicalDecl(Data) {}
+  T *getNotUpdated() { return DataOrCanonicalDecl.template dyn_cast<T*>(); }
+  T *get() { return update().getNotUpdated(); }
+};
+
 /// \brief Represents a C++ struct/union/class.
-///
-/// FIXME: This class will disappear once we've properly taught RecordDecl
-/// to deal with C++-specific things.
 class CXXRecordDecl : public RecordDecl {
 
   friend void TagDecl::startDefinition();
@@ -496,9 +517,9 @@ class CXXRecordDecl : public RecordDecl {
     CXXBaseSpecifier *getVBasesSlowCase() const;
   };
 
-  typedef LazyGenerationalUpdatePtr<const Decl*, struct DefinitionData*,
-                                    &ExternalASTSource::CompleteRedeclChain>
+  typedef LazyDefinitionDataPtr<CXXRecordDecl, struct DefinitionData>
       DefinitionDataPtr;
+  friend class LazyDefinitionDataPtr<CXXRecordDecl, struct DefinitionData>;
 
   mutable DefinitionDataPtr DefinitionData;
 
@@ -558,7 +579,7 @@ class CXXRecordDecl : public RecordDecl {
   };
 
   struct DefinitionData &data() const {
-    auto *DD = DefinitionData.get(this);
+    auto *DD = DefinitionData.get();
     assert(DD && "queried property of class with no definition");
     return *DD;
   }
@@ -643,11 +664,11 @@ public:
   }
 
   CXXRecordDecl *getDefinition() const {
-    auto *DD = DefinitionData.get(this);
+    auto *DD = DefinitionData.get();
     return DD ? DD->Definition : nullptr;
   }
 
-  bool hasDefinition() const { return DefinitionData.get(this); }
+  bool hasDefinition() const { return DefinitionData.get(); }
 
   static CXXRecordDecl *Create(const ASTContext &C, TagKind TK, DeclContext *DC,
                                SourceLocation StartLoc, SourceLocation IdLoc,
index fc15bde..a783364 100644 (file)
@@ -3240,7 +3240,7 @@ void TagDecl::startDefinition() {
     struct CXXRecordDecl::DefinitionData *Data =
       new (getASTContext()) struct CXXRecordDecl::DefinitionData(D);
     for (auto I : redecls())
-      cast<CXXRecordDecl>(I)->DefinitionData.setNotUpdated(Data);
+      cast<CXXRecordDecl>(I)->DefinitionData = Data;
   }
 }
 
index 1c41628..0ac8b73 100644 (file)
@@ -88,7 +88,7 @@ CXXRecordDecl::CXXRecordDecl(Kind K, TagKind TK, const ASTContext &C,
                              CXXRecordDecl *PrevDecl)
     : RecordDecl(K, TK, C, DC, StartLoc, IdLoc, Id, PrevDecl),
       DefinitionData(PrevDecl ? PrevDecl->DefinitionData
-                              : DefinitionDataPtr(C)),
+                              : DefinitionDataPtr(this)),
       TemplateOrInstantiation() {}
 
 CXXRecordDecl *CXXRecordDecl::Create(const ASTContext &C, TagKind TK,
@@ -115,9 +115,9 @@ CXXRecordDecl::CreateLambda(const ASTContext &C, DeclContext *DC,
       new (C, DC) CXXRecordDecl(CXXRecord, TTK_Class, C, DC, Loc, Loc,
                                 nullptr, nullptr);
   R->IsBeingDefined = true;
-  R->DefinitionData.setNotUpdated(
+  R->DefinitionData =
       new (C) struct LambdaDefinitionData(R, Info, Dependent, IsGeneric,
-                                          CaptureDefault));
+                                          CaptureDefault);
   R->MayHaveOutOfDateDef = false;
   R->setImplicit(true);
   C.getTypeDeclType(R, /*PrevDecl=*/nullptr);
index d900f71..0c6d858 100644 (file)
@@ -1405,7 +1405,7 @@ void ASTDeclReader::ReadCXXRecordDefinition(CXXRecordDecl *D) {
   // that all other deserialized declarations will see it.
   CXXRecordDecl *Canon = D->getCanonicalDecl();
   if (Canon == D) {
-    D->DefinitionData.setNotUpdated(DD);
+    D->DefinitionData = DD;
     D->IsCompleteDefinition = true;
   } else if (auto *CanonDD = Canon->DefinitionData.getNotUpdated()) {
     // We have already deserialized a definition of this record. This
@@ -1417,7 +1417,7 @@ void ASTDeclReader::ReadCXXRecordDefinition(CXXRecordDecl *D) {
     D->IsCompleteDefinition = false;
     MergeDefinitionData(D, *DD);
   } else {
-    Canon->DefinitionData.setNotUpdated(DD);
+    Canon->DefinitionData = DD;
     D->DefinitionData = Canon->DefinitionData;
     D->IsCompleteDefinition = true;