]> granicus.if.org Git - clang/commitdiff
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.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@209482 91177308-0d34-0410-b5e6-96231b3b80d8

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

index 4b268d4af0586ac75523cd056a66a1aed0e432ad..01af64a755b33f4c9e09a68d6606227faac150d9 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 fc15bdee01006b8df1bbb59a776b2c68ebc18548..a783364c677f1972e18246c620a36f1398c798b2 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 1c4162827599790aa5eb12ae21e7e2870e5abee0..0ac8b73e306ea63b6fd63d5a1825a8da1b368468 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 d900f71c464f8e40297c3a4cf5eb412243a10af7..0c6d858bf5475640e4d661b75bd4dd757acd55a5 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;