[cfe-commits] r62001 - in /cfe/trunk: 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

Douglas Gregor dgregor at apple.com
Fri Jan 9 11:42:16 PST 2009


Author: dgregor
Date: Fri Jan  9 13:42:16 2009
New Revision: 62001

URL: http://llvm.org/viewvc/llvm-project?rev=62001&view=rev
Log:
Replace DeclContext's vector of ScopedDecl pointers with a linked list
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.


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

Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=62001&r1=62000&r2=62001&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Fri Jan  9 13:42:16 2009
@@ -115,6 +115,17 @@
   /// 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 @@
 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 @@
   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

Modified: cfe/trunk/include/clang/AST/DeclBase.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclBase.h?rev=62001&r1=62000&r2=62001&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/DeclBase.h (original)
+++ cfe/trunk/include/clang/AST/DeclBase.h Fri Jan  9 13:42:16 2009
@@ -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 @@
   /// 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 @@
   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 @@
 
   /// 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 @@
       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;

Modified: cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=62001&r1=62000&r2=62001&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticKinds.def Fri Jan  9 13:42:16 2009
@@ -1003,6 +1003,8 @@
      "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,

Modified: cfe/trunk/lib/AST/DeclBase.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclBase.cpp?rev=62001&r1=62000&r2=62001&view=diff

==============================================================================
--- cfe/trunk/lib/AST/DeclBase.cpp (original)
+++ cfe/trunk/lib/AST/DeclBase.cpp Fri Jan  9 13:42:16 2009
@@ -401,7 +401,8 @@
 }
 
 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 @@
 
 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);
 }

Modified: cfe/trunk/lib/AST/DeclSerialization.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclSerialization.cpp?rev=62001&r1=62000&r2=62001&view=diff

==============================================================================
--- cfe/trunk/lib/AST/DeclSerialization.cpp (original)
+++ cfe/trunk/lib/AST/DeclSerialization.cpp Fri Jan  9 13:42:16 2009
@@ -124,6 +124,9 @@
 //===----------------------------------------------------------------------===//
 
 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 @@
     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 @@
     else
       D.ReadPtr<ScopedDecl>(Decls[Idx]);
   }
+#endif
 }
 
 //===----------------------------------------------------------------------===//

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=62001&r1=62000&r2=62001&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Fri Jan  9 13:42:16 2009
@@ -515,7 +515,7 @@
     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 @@
   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;
   }

Modified: cfe/trunk/lib/Sema/SemaDeclObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclObjC.cpp?rev=62001&r1=62000&r2=62001&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclObjC.cpp Fri Jan  9 13:42:16 2009
@@ -1078,6 +1078,7 @@
                               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 @@
                                                   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 @@
   //   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

Modified: cfe/trunk/test/Sema/typedef-redef.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/typedef-redef.c?rev=62001&r1=62000&r2=62001&view=diff

==============================================================================
--- cfe/trunk/test/Sema/typedef-redef.c (original)
+++ cfe/trunk/test/Sema/typedef-redef.c Fri Jan  9 13:42:16 2009
@@ -7,7 +7,7 @@
 
 
 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}}
 





More information about the cfe-commits mailing list