]> granicus.if.org Git - clang/commitdiff
Replace DeclContext's vector of ScopedDecl pointers with a linked list
authorDouglas Gregor <dgregor@apple.com>
Fri, 9 Jan 2009 19:42:16 +0000 (19:42 +0000)
committerDouglas Gregor <dgregor@apple.com>
Fri, 9 Jan 2009 19:42:16 +0000 (19:42 +0000)
of ScopedDecls (using the new ScopedDecl::NextDeclInScope
pointer). Performance-wise:

  - It's a net win in memory utilization, since DeclContext is now one
    pointer smaller than it used to be (std::vectors are typically 3
    pointers; we now use 2 pointers) and
  - Parsing Cocoa.h with -fsyntax-only (with a Release-Asserts Clang)
    is about 1.9% faster than before, most likely because we no longer
    have the memory allocations and copying associated with the
    std::vector.

I'll re-enable serialization of DeclContexts once I've sorted out the
NextDeclarator/NextDeclInScope question.

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

include/clang/AST/Decl.h
include/clang/AST/DeclBase.h
include/clang/Basic/DiagnosticKinds.def
lib/AST/DeclBase.cpp
lib/AST/DeclSerialization.cpp
lib/Sema/SemaDecl.cpp
lib/Sema/SemaDeclObjC.cpp
test/Sema/typedef-redef.c

index 96bd8842b399e2b1420d99332684d458f58131af..7392af6ca54ccb2bef9ec31d19ceb1c0d7163af9 100644 (file)
@@ -115,6 +115,17 @@ class ScopedDecl : public NamedDecl {
   /// such as "int X, Y, *Z;" this indicates Decl for the next declarator.
   ScopedDecl *NextDeclarator;
   
+  /// NextDeclInScope - The next declaration within the same lexical
+  /// DeclContext. These pointers form the linked list that is
+  /// traversed via DeclContext's decls_begin()/decls_end().
+  /// FIXME: If NextDeclarator is non-NULL, will it always be the same
+  /// as NextDeclInScope? If so, we can use a
+  /// PointerIntPair<ScopedDecl*, 1> to make ScopedDecl smaller.
+  ScopedDecl *NextDeclInScope;
+
+  friend class DeclContext;
+  friend class DeclContext::decl_iterator;
+
   /// DeclCtx - Holds either a DeclContext* or a MultipleDC*.
   /// For declarations that don't contain C++ scope specifiers, it contains
   /// the DeclContext where the ScopedDecl was declared.
@@ -144,7 +155,7 @@ class ScopedDecl : public NamedDecl {
 protected:
   ScopedDecl(Kind DK, DeclContext *DC, SourceLocation L,
              DeclarationName N, ScopedDecl *PrevDecl = 0)
-    : NamedDecl(DK, L, N), NextDeclarator(PrevDecl), 
+    : NamedDecl(DK, L, N), NextDeclarator(PrevDecl), NextDeclInScope(0),
       DeclCtx(reinterpret_cast<uintptr_t>(DC)) {}
 
   virtual ~ScopedDecl();
@@ -1215,6 +1226,11 @@ protected:
   friend Decl* Decl::Create(llvm::Deserializer& D, ASTContext& C);
 };
 
+inline DeclContext::decl_iterator& DeclContext::decl_iterator::operator++() {
+  Current = Current->NextDeclInScope;
+  return *this;
+}
+
 }  // end namespace clang
 
 #endif
index c6a18a23caa70bae8ed37765767bde933ab9f8fa..f96909bb912c1cd1b2cf29123298133e6cc9fa2a 100644 (file)
@@ -18,7 +18,6 @@
 #include "clang/AST/Type.h"
 #include "clang/Basic/SourceLocation.h"
 #include "llvm/ADT/PointerIntPair.h"
-#include <vector>
 
 namespace clang {
 class DeclContext;
@@ -307,9 +306,15 @@ class DeclContext {
   /// FIXME: We need a better data structure for this.
   llvm::PointerIntPair<void*, 3> LookupPtr;
 
-  /// Decls - Contains all of the declarations that are defined inside
-  /// this declaration context. 
-  std::vector<ScopedDecl*> Decls;
+  /// FirstDecl - The first declaration stored within this declaration
+  /// context.
+  ScopedDecl *FirstDecl;
+
+  /// LastDecl - The last declaration stored within this declaration
+  /// context. FIXME: We could probably cache this value somewhere
+  /// outside of the DeclContext, to reduce the size of DeclContext by
+  /// another pointer.
+  ScopedDecl *LastDecl;
 
   // Used in the CastTo template to get the DeclKind
   // from a Decl or a DeclContext. DeclContext doesn't have a getKind() method
@@ -363,8 +368,8 @@ class DeclContext {
   bool isLookupMap() const { return LookupPtr.getInt() == LookupIsMap; }
 
 protected:
-  DeclContext(Decl::Kind K) : DeclKind(K), LookupPtr() {
-  }
+   DeclContext(Decl::Kind K) 
+     : DeclKind(K), LookupPtr(), FirstDecl(0), LastDecl(0) { }
 
   void DestroyDecls(ASTContext &C);
 
@@ -483,12 +488,43 @@ public:
 
   /// decl_iterator - Iterates through the declarations stored
   /// within this context.
-  typedef std::vector<ScopedDecl*>::const_iterator decl_iterator;
+  class decl_iterator {
+    /// Current - The current declaration.
+    ScopedDecl *Current;
+
+  public:
+    typedef ScopedDecl*               value_type;
+    typedef ScopedDecl*               reference;
+    typedef ScopedDecl*               pointer;
+    typedef std::forward_iterator_tag iterator_category;
+    typedef std::ptrdiff_t            difference_type;
+
+    decl_iterator() : Current(0) { }
+    explicit decl_iterator(ScopedDecl *C) : Current(C) { }
+
+    reference operator*() const { return Current; }
+    pointer operator->() const { return Current; }
+
+    decl_iterator& operator++();
+
+    decl_iterator operator++(int) {
+      decl_iterator tmp(*this);
+      ++(*this);
+      return tmp;
+    }
+
+    friend bool operator==(decl_iterator x, decl_iterator y) { 
+      return x.Current == y.Current;
+    }
+    friend bool operator!=(decl_iterator x, decl_iterator y) { 
+      return x.Current != y.Current;
+    }
+  };
 
   /// decls_begin/decls_end - Iterate over the declarations stored in
   /// this context. 
-  decl_iterator decls_begin() const { return Decls.begin(); }
-  decl_iterator decls_end()   const { return Decls.end(); }
+  decl_iterator decls_begin() const { return decl_iterator(FirstDecl); }
+  decl_iterator decls_end()   const { return decl_iterator(); }
 
   /// specific_decl_iterator - Iterates over a subrange of
   /// declarations stored in a DeclContext, providing only those that
@@ -548,8 +584,8 @@ public:
       SkipToNextDecl();
     }
 
-    reference operator*() { return cast<SpecificDecl>(*Current); }
-    pointer operator->() { return cast<SpecificDecl>(*Current); }
+    reference operator*() const { return cast<SpecificDecl>(*Current); }
+    pointer operator->() const { return cast<SpecificDecl>(*Current); }
 
     specific_decl_iterator& operator++() {
       ++Current;
index 2577e65d3b603f319a758668cffb38d52d2946c2..af721a6128116b306665e5b51871600fdaaeac0e 100644 (file)
@@ -1003,6 +1003,8 @@ DIAG(err_static_non_static, ERROR,
      "static declaration of %0 follows non-static declaration")
 DIAG(err_non_static_static, ERROR,
      "non-static declaration of %0 follows static declaration")
+DIAG(err_redefinition_different_type, ERROR,
+     "redefinition of %0 with a different type")
 DIAG(err_redefinition_different_kind, ERROR,
      "redefinition of %0 as different kind of symbol")
 DIAG(err_redefinition_different_typedef, ERROR,
index d9765ac4b45e3edb79a06e90aad85bf69c233b07..cafe5358d618616d3920f52f265af5ecda410bca 100644 (file)
@@ -401,7 +401,8 @@ DeclContext::~DeclContext() {
 }
 
 void DeclContext::DestroyDecls(ASTContext &C) {
-  for (decl_iterator D = Decls.begin(); D != Decls.end(); ++D) {
+  for (decl_iterator D = decls_begin(); D != decls_end(); ++D) {
+    // FIXME: assert that this condition holds.
     if ((*D)->getLexicalDeclContext() == this)
       (*D)->Destroy(C);
   }
@@ -515,7 +516,15 @@ DeclContext *DeclContext::getNextContext() {
 
 void DeclContext::addDecl(ASTContext &Context, ScopedDecl *D, bool AllowLookup) {
   assert(D->getLexicalDeclContext() == this && "Decl inserted into wrong lexical context");
-  Decls.push_back(D);
+  assert(!D->NextDeclInScope && D != LastDecl && 
+         "Decl already inserted into a DeclContext");
+
+  if (FirstDecl) {
+    LastDecl->NextDeclInScope = D;
+    LastDecl = D;
+  } else {
+    FirstDecl = LastDecl = D;
+  }
   if (AllowLookup)
     D->getDeclContext()->insert(Context, D);
 }
index 38af4620918a143d2b684c3c54df625807ff53ca..11577cd6dc298f7970672c977eda89a8ec95f8b9 100644 (file)
@@ -124,6 +124,9 @@ void Decl::ReadInRec(Deserializer& D, ASTContext& C) {
 //===----------------------------------------------------------------------===//
 
 void DeclContext::EmitOutRec(Serializer& S) const {
+#if 0
+  // FIXME: it would be far easier to just serialize FirstDecl and let
+  // ScopedDecl do the work of serializing NextDeclInScope.
   S.EmitInt(Decls.size());
   for (decl_iterator D = decls_begin(); D != decls_end(); ++D) {
     bool Owned = ((*D)->getLexicalDeclContext() == this &&
@@ -135,9 +138,12 @@ void DeclContext::EmitOutRec(Serializer& S) const {
     else
       S.EmitPtr(*D);
   }
+#endif
 }
 
 void DeclContext::ReadOutRec(Deserializer& D, ASTContext& C) {
+#if 0
+  // FIXME: See comment in DeclContext::EmitOutRec
   unsigned NumDecls = D.ReadInt();
   Decls.resize(NumDecls);
   for (unsigned Idx = 0; Idx < NumDecls; ++Idx) {
@@ -147,6 +153,7 @@ void DeclContext::ReadOutRec(Deserializer& D, ASTContext& C) {
     else
       D.ReadPtr<ScopedDecl>(Decls[Idx]);
   }
+#endif
 }
 
 //===----------------------------------------------------------------------===//
index ecf6de9d96f5ea93458c677566906ce10231c0d3..ee72a98295c3d80acdb7408580f4b6bb0b615340 100644 (file)
@@ -515,7 +515,7 @@ TypedefDecl *Sema::MergeTypeDefDecl(TypedefDecl *New, Decl *OldD) {
     Diag(New->getLocation(), diag::err_redefinition_different_typedef)
       << New->getUnderlyingType() << Old->getUnderlyingType();
     Diag(Old->getLocation(), diag::note_previous_definition);
-    return Old;
+    return New;
   }
   
   if (getLangOptions().Microsoft) return New;
@@ -768,7 +768,8 @@ VarDecl *Sema::MergeVarDecl(VarDecl *New, Decl *OldD) {
   QualType OldCType = Context.getCanonicalType(Old->getType());
   QualType NewCType = Context.getCanonicalType(New->getType());
   if (OldCType != NewCType && !Context.typesAreCompatible(OldCType, NewCType)) {
-    Diag(New->getLocation(), diag::err_redefinition) << New->getDeclName();
+    Diag(New->getLocation(), diag::err_redefinition_different_type) 
+      << New->getDeclName();
     Diag(Old->getLocation(), diag::note_previous_definition);
     return New;
   }
index f39b84c270123866cfa950fc2cfba893df8aef3c..49a8c835c5c058455a3da9592e971244f9ac4558 100644 (file)
@@ -1078,6 +1078,7 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property,
                               ObjCPropertyDecl::Optional) ? 
                              ObjCMethodDecl::Optional : 
                              ObjCMethodDecl::Required);
+    CD->addDecl(Context, GetterMethod);
   } else
     // A user declared getter will be synthesize when @synthesize of
     // the property with the same name is seen in the @implementation
@@ -1108,6 +1109,7 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property,
                                                   VarDecl::None,
                                                   0, 0);
       SetterMethod->setMethodParams(&Argument, 1);
+      CD->addDecl(Context, SetterMethod);
     } else
       // A user declared setter will be synthesize when @synthesize of
       // the property with the same name is seen in the @implementation
@@ -1126,14 +1128,10 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property,
   //   double bar = [foo bar];
   // }
   //
-  if (GetterMethod) {
-    CD->addDecl(Context, GetterMethod);
+  if (GetterMethod)
     AddInstanceMethodToGlobalPool(GetterMethod);  
-  }
-  if (SetterMethod) {
-    CD->addDecl(Context, SetterMethod);
+  if (SetterMethod)
     AddInstanceMethodToGlobalPool(SetterMethod);     
-  }
 }
 
 // Note: For class/category implemenations, allMethods/allProperties is
index 76b8a3cddef77dc98beb82a7c081036c9e48e7cf..d6962f1cd1709928b7f550ccd438843f6a0c70cf 100644 (file)
@@ -7,7 +7,7 @@ typedef __SIZE_TYPE__ size_t;
 
 
 typedef const int x; // expected-note {{previous definition is here}}
-extern x a;
+extern x a; // expected-note {{previous definition is here}}
 typedef int x;  // expected-error {{typedef redefinition with different types}}
-extern x a;
+extern x a; // expected-error{{redefinition of 'a' with a different type}}