[cfe-commits] r50923 - in /cfe/trunk: lib/Parse/ParseDecl.cpp lib/Sema/IdentifierResolver.cpp lib/Sema/IdentifierResolver.h lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclCXX.cpp test/Sema/cxx-namespace.cpp

Argiris Kirtzidis akyrtzi at gmail.com
Fri May 9 16:39:43 PDT 2008


Author: akirtzidis
Date: Fri May  9 18:39:43 2008
New Revision: 50923

URL: http://llvm.org/viewvc/llvm-project?rev=50923&view=rev
Log:
-Implement proper name lookup for namespaces.
-identifierResolver exposes an iterator interface to get all decls through the scope chain.
-The semantic staff (checking IdentifierNamespace and Doug's checking for shadowed tags were moved out of IdentifierResolver and back into Sema. IdentifierResolver just gives an iterator for all reachable decls of an identifier.

Modified:
    cfe/trunk/lib/Parse/ParseDecl.cpp
    cfe/trunk/lib/Sema/IdentifierResolver.cpp
    cfe/trunk/lib/Sema/IdentifierResolver.h
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/test/Sema/cxx-namespace.cpp

Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=50923&r1=50922&r2=50923&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Fri May  9 18:39:43 2008
@@ -1251,7 +1251,7 @@
 
   // Enter function-declaration scope, limiting any declarators to the
   // function prototype scope, including parameter declarators.
-  EnterScope(Scope::DeclScope);
+  EnterScope(Scope::FnScope|Scope::DeclScope);
   
   bool IsVariadic = false;
   while (1) {
@@ -1526,3 +1526,4 @@
   }
 }
 
+

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

==============================================================================
--- cfe/trunk/lib/Sema/IdentifierResolver.cpp (original)
+++ cfe/trunk/lib/Sema/IdentifierResolver.cpp Fri May  9 18:39:43 2008
@@ -13,67 +13,16 @@
 //===----------------------------------------------------------------------===//
 
 #include "IdentifierResolver.h"
-#include "clang/Basic/IdentifierTable.h"
-#include "clang/AST/Decl.h"
-#include "clang/Parse/Scope.h"
 #include <list>
 #include <vector>
 
 using namespace clang;
 
-namespace {
-
-class IdDeclInfo;
-
-/// Identifier's FETokenInfo contains a Decl pointer if lower bit == 0.
-static inline bool isDeclPtr(void *Ptr) {
-  return (reinterpret_cast<uintptr_t>(Ptr) & 0x1) == 0;
-}
-
-/// Identifier's FETokenInfo contains a IdDeclInfo pointer if lower bit == 1.
-static inline IdDeclInfo *toIdDeclInfo(void *Ptr) {
-  return reinterpret_cast<IdDeclInfo*>(
-                  reinterpret_cast<uintptr_t>(Ptr) & ~0x1
-                                                          );
-}
-
-
-/// IdDeclInfo - Keeps track of information about decls associated to a
-/// particular identifier. IdDeclInfos are lazily constructed and assigned
-/// to an identifier the first time a decl with that identifier is shadowed
-/// in some scope.
-class IdDeclInfo {
-  typedef llvm::SmallVector<NamedDecl *, 2> ShadowedTy;
-  ShadowedTy ShadowedDecls;
-
-public:
-  typedef ShadowedTy::iterator ShadowedIter;
-
-  inline ShadowedIter shadowed_begin() { return ShadowedDecls.begin(); }
-  inline ShadowedIter shadowed_end() { return ShadowedDecls.end(); }
-
-  /// Add a decl in the scope chain.
-  void PushShadowed(NamedDecl *D) {
-    assert(D && "Decl null");
-    ShadowedDecls.push_back(D);
-  }
-
-  /// Add the decl at the top of scope chain.
-  void PushGlobalShadowed(NamedDecl *D) {
-    assert(D && "Decl null");
-    ShadowedDecls.insert(ShadowedDecls.begin(), D);
-  }
-
-  /// RemoveShadowed - Remove the decl from the scope chain.
-  /// The decl must already be part of the decl chain.
-  void RemoveShadowed(NamedDecl *D);
-};
-
 
 /// IdDeclInfoMap - Associates IdDeclInfos with Identifiers.
 /// Allocates 'pools' (vectors of IdDeclInfos) to avoid allocating each
 /// individual IdDeclInfo to heap.
-class IdDeclInfoMap {
+class IdentifierResolver::IdDeclInfoMap {
   static const unsigned int VECTOR_SIZE = 512;
   // Holds vectors of IdDeclInfos that serve as 'pools'.
   // New vectors are added when the current one is full.
@@ -88,17 +37,14 @@
   IdDeclInfo &operator[](IdentifierInfo *II);
 };
 
-} // end anonymous namespace
-
 
 IdentifierResolver::IdentifierResolver() : IdDeclInfos(new IdDeclInfoMap) {}
 IdentifierResolver::~IdentifierResolver() {
-  delete static_cast<IdDeclInfoMap*>(IdDeclInfos);
+  delete IdDeclInfos;
 }
 
 /// AddDecl - Link the decl to its shadowed decl chain.
-void IdentifierResolver::AddDecl(NamedDecl *D, Scope *S) {
-  assert(D && S && "null param passed");
+void IdentifierResolver::AddDecl(NamedDecl *D) {
   IdentifierInfo *II = D->getIdentifier();
   void *Ptr = II->getFETokenInfo<void>();
 
@@ -111,56 +57,40 @@
 
   if (isDeclPtr(Ptr)) {
     II->setFETokenInfo(NULL);
-    IdDeclInfoMap &Map = *static_cast<IdDeclInfoMap*>(IdDeclInfos);
-    IDI = &Map[II];
-    IDI->PushShadowed(static_cast<NamedDecl*>(Ptr));
+    IDI = &(*IdDeclInfos)[II];
+    NamedDecl *PrevD = static_cast<NamedDecl*>(Ptr);
+    IDI->AddDecl(PrevD);
   } else
     IDI = toIdDeclInfo(Ptr);
 
-  // C++ [basic.scope]p4:
-  //   -- exactly one declaration shall declare a class name or
-  //   enumeration name that is not a typedef name and the other
-  //   declarations shall all refer to the same object or
-  //   enumerator, or all refer to functions and function templates;
-  //   in this case the class name or enumeration name is hidden.
-  if (isa<TagDecl>(D) && IDI->shadowed_end() != IDI->shadowed_begin()) {
-    // We are pushing the name of a tag (enum or class).
-    IdDeclInfo::ShadowedIter TopIter = IDI->shadowed_end() - 1;
-    if (S->isDeclScope(*TopIter)) {
-      // There is already a declaration with the same name in the same
-      // scope. It must be found before we find the new declaration,
-      // so swap the order on the shadowed declaration stack.
-      NamedDecl *Temp = *TopIter;
-      *TopIter = D;
-      D = Temp;
-    }
-  }
-
-  IDI->PushShadowed(D);
+  IDI->AddDecl(D);
 }
 
-/// AddGlobalDecl - Link the decl at the top of the shadowed decl chain.
-void IdentifierResolver::AddGlobalDecl(NamedDecl *D) {
-  assert(D && "null param passed");
+/// AddShadowedDecl - Link the decl to its shadowed decl chain putting it
+/// after the decl that the iterator points to, thus the 'CIT' decl will be
+/// encountered before the 'D' decl.
+void IdentifierResolver::AddShadowedDecl(NamedDecl *D, NamedDecl *Shadow) {
+  assert(D->getIdentifier() == Shadow->getIdentifier() && "Different ids!");
+  assert(LookupContext(D) == LookupContext(Shadow) && "Different context!");
+
   IdentifierInfo *II = D->getIdentifier();
   void *Ptr = II->getFETokenInfo<void>();
-
-  if (!Ptr) {
-    II->setFETokenInfo(D);
-    return;
-  }
+  assert(Ptr && "No decl from Ptr ?");
 
   IdDeclInfo *IDI;
 
   if (isDeclPtr(Ptr)) {
     II->setFETokenInfo(NULL);
-    IdDeclInfoMap &Map = *static_cast<IdDeclInfoMap*>(IdDeclInfos);
-    IDI = &Map[II];
-    IDI->PushShadowed(static_cast<NamedDecl*>(Ptr));
-  } else
-    IDI = toIdDeclInfo(Ptr);
+    IDI = &(*IdDeclInfos)[II];
+    NamedDecl *PrevD = static_cast<NamedDecl*>(Ptr);
+    assert(PrevD == Shadow && "Invalid shadow decl ?");
+    IDI->AddDecl(D);
+    IDI->AddDecl(PrevD);
+    return;
+  }
 
-  IDI->PushGlobalShadowed(D);
+  IDI = toIdDeclInfo(Ptr);
+  IDI->AddShadowed(D, Shadow);
 }
 
 /// RemoveDecl - Unlink the decl from its shadowed decl chain.
@@ -178,71 +108,72 @@
     return;
   }
   
-  return toIdDeclInfo(Ptr)->RemoveShadowed(D);
+  return toIdDeclInfo(Ptr)->RemoveDecl(D);
 }
 
-/// Lookup - Find the non-shadowed decl that belongs to a particular
-/// Decl::IdentifierNamespace.
-NamedDecl *IdentifierResolver::Lookup(const IdentifierInfo *II, unsigned NS) {
-  assert(II && "null param passed");
+/// begin - Returns an iterator for all decls, starting at the given
+/// declaration context.
+IdentifierResolver::iterator
+IdentifierResolver::begin(const IdentifierInfo *II, DeclContext *Ctx) {
+  assert(Ctx && "null param passed");
+
   void *Ptr = II->getFETokenInfo<void>();
+  if (!Ptr) return end(II);
 
-  if (!Ptr) return NULL;
+  LookupContext LC(Ctx);
 
   if (isDeclPtr(Ptr)) {
     NamedDecl *D = static_cast<NamedDecl*>(Ptr);
-    return (D->getIdentifierNamespace() & NS) ? D : NULL;
-  }
 
-  IdDeclInfo *IDI = toIdDeclInfo(Ptr);
+    if (LC.isEqOrContainedBy(LookupContext(D)))
+      return iterator(D);
+    else
+      return end(II);
 
-  // ShadowedDecls are ordered from most shadowed to less shadowed.
-  // So we do a reverse iteration from end to begin.
-  for (IdDeclInfo::ShadowedIter SI = IDI->shadowed_end();
-       SI != IDI->shadowed_begin(); --SI) {
-    NamedDecl *D = *(SI-1);
-    if (D->getIdentifierNamespace() & NS)
-      return D;
   }
-
-  // we didn't find the decl.
-  return NULL;
+  
+  IdDeclInfo *IDI = toIdDeclInfo(Ptr);
+  return iterator(IDI->FindContext(LC));
 }
 
-/// RemoveShadowed - Remove the decl from the scope chain.
-/// The decl must already be part of the decl chain.
-void IdDeclInfo::RemoveShadowed(NamedDecl *D) {
-  assert(D && "null decl passed");
-  assert(!ShadowedDecls.empty() &&
-         "Didn't find this decl on its identifier's chain!");
-
-  // common case
-  if (D == ShadowedDecls.back()) {
-    ShadowedDecls.pop_back();
-    return;
-  }
+/// ctx_begin - Returns an iterator for only decls that belong to the given
+/// declaration context.
+IdentifierResolver::ctx_iterator
+IdentifierResolver::ctx_begin(const IdentifierInfo *II, DeclContext *Ctx) {
+  assert(Ctx && "null param passed");
+
+  void *Ptr = II->getFETokenInfo<void>();
+  if (!Ptr) return ctx_end(II);
+
+  LookupContext LC(Ctx);
+
+  if (isDeclPtr(Ptr)) {
+    NamedDecl *D = static_cast<NamedDecl*>(Ptr);
+
+    if (LC == LookupContext(D))
+      return ctx_iterator(D);
+    else
+      return ctx_end(II);
 
-  for (ShadowedIter SI = ShadowedDecls.end()-1;
-       SI != ShadowedDecls.begin(); --SI) {
-    if (*(SI-1) == D) {
-      ShadowedDecls.erase(SI-1);
-      return;
-    }
   }
+  
+  IdDeclInfo *IDI = toIdDeclInfo(Ptr);
+  IdDeclInfo::DeclsTy::iterator I = IDI->FindContext(LookupContext(Ctx));
+  if (I != IDI->decls_begin() && LC != LookupContext(*(I-1)))
+    I = IDI->decls_begin();
 
-  assert(false && "Didn't find this decl on its identifier's chain!");
+  return ctx_iterator(I);
 }
 
+
 /// Returns the IdDeclInfo associated to the IdentifierInfo.
 /// It creates a new IdDeclInfo if one was not created before for this id.
-IdDeclInfo &IdDeclInfoMap::operator[](IdentifierInfo *II) {
+IdentifierResolver::IdDeclInfo &
+IdentifierResolver::IdDeclInfoMap::operator[](IdentifierInfo *II) {
   assert (II && "null IdentifierInfo passed");
   void *Ptr = II->getFETokenInfo<void>();
 
-  if (Ptr) {
-    assert(!isDeclPtr(Ptr) && "didn't clear decl for FEToken");
-    return *toIdDeclInfo(Ptr);
-  }
+  if (Ptr) return *toIdDeclInfo(Ptr);
 
   if (CurIndex == VECTOR_SIZE) {
     // Add a IdDeclInfo vector 'pool'

Modified: cfe/trunk/lib/Sema/IdentifierResolver.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/IdentifierResolver.h?rev=50923&r1=50922&r2=50923&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/IdentifierResolver.h (original)
+++ cfe/trunk/lib/Sema/IdentifierResolver.h Fri May  9 18:39:43 2008
@@ -15,37 +15,354 @@
 #ifndef LLVM_CLANG_AST_SEMA_IDENTIFIERRESOLVER_H
 #define LLVM_CLANG_AST_SEMA_IDENTIFIERRESOLVER_H
 
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Parse/Scope.h"
+#include "clang/AST/Decl.h"
+
 namespace clang {
-  class IdentifierInfo;
-  class NamedDecl;
-  class Scope;
 
 /// IdentifierResolver - Keeps track of shadowed decls on enclosing scopes.
 /// It manages the shadowing chains of identifiers and implements efficent decl
 /// lookup based on an identifier.
 class IdentifierResolver {
+
+  /// LookupContext - A wrapper for DeclContext. DeclContext is only part of
+  /// ScopedDecls, LookupContext can be used with all decls (assumes
+  /// translation unit context for non ScopedDecls).
+  class LookupContext {
+    DeclContext *Ctx;
+
+    /// TUCtx - Provides a common value for translation unit context for all
+    /// decls.
+    /// FIXME: When (if ?) all decls can point to their translation unit context
+    /// remove this hack.
+    static inline DeclContext *TUCtx() {
+      return reinterpret_cast<DeclContext*>(-1);
+    }
+
+    /// getContext - Returns translation unit context for non ScopedDecls and
+    /// for EnumConstantDecls returns the parent context of their EnumDecl.
+    static DeclContext *getContext(Decl *D) {
+      DeclContext *Ctx;
+
+      if (EnumConstantDecl *EnumD = dyn_cast<EnumConstantDecl>(D)) {
+        Ctx = EnumD->getDeclContext()->getParent();
+      } else if (ScopedDecl *SD = dyn_cast<ScopedDecl>(D))
+        Ctx = SD->getDeclContext();
+      else
+        return TUCtx();
+
+      if (isa<TranslationUnitDecl>(Ctx))
+        return TUCtx();
+
+      return Ctx;
+    }
+
+  public:
+    LookupContext(Decl *D) {
+      Ctx = getContext(D);
+    }
+    LookupContext(DeclContext *DC) {
+      if (!DC || isa<TranslationUnitDecl>(DC))
+        Ctx = TUCtx();
+      else
+        Ctx = DC;
+    }
+
+    bool isTU() const {
+      return (Ctx == TUCtx());
+    }
+
+    /// getParent - Returns the parent context. This should not be called for
+    /// a translation unit context.
+    LookupContext getParent() const {
+      assert(!isTU() && "TU has no parent!");
+      return LookupContext(Ctx->getParent());
+    }
+
+    /// isEqOrContainedBy - Returns true of the given context is the same or a
+    /// parent of this one.
+    bool isEqOrContainedBy(const LookupContext &PC) const {
+      if (PC.isTU()) return true;
+
+      for (LookupContext Next = *this; !Next.isTU();  Next = Next.getParent())
+        if (Next.Ctx == PC.Ctx) return true;
+
+      return false;
+    }
+
+    bool operator==(const LookupContext &RHS) const {
+      return Ctx == RHS.Ctx;
+    }
+    bool operator!=(const LookupContext &RHS) const {
+      return Ctx != RHS.Ctx;
+    }
+  };
+
+  /// IdDeclInfo - Keeps track of information about decls associated to a
+  /// particular identifier. IdDeclInfos are lazily constructed and assigned
+  /// to an identifier the first time a decl with that identifier is shadowed
+  /// in some scope.
+  class IdDeclInfo {
+  public:
+    typedef llvm::SmallVector<NamedDecl*, 2> DeclsTy;
+
+    inline DeclsTy::iterator decls_begin() { return Decls.begin(); }
+    inline DeclsTy::iterator decls_end() { return Decls.end(); }
+
+    /// FindContext - Returns an iterator pointing just after the decl that is
+    /// in the given context or in a parent of it. The search is in reverse
+    /// order, from end to begin.
+    DeclsTy::iterator FindContext(const LookupContext &Ctx) {
+      return FindContext(Ctx, Decls.end());
+    }
+
+    /// FindContext - Returns an iterator pointing just after the decl that is
+    /// in the given context or in a parent of it. The search is in reverse
+    /// order, from end to begin.
+    DeclsTy::iterator FindContext(const LookupContext &Ctx,
+                                  const DeclsTy::iterator &Start) {
+      for (DeclsTy::iterator I = Start; I != Decls.begin(); --I) {
+        if (Ctx.isEqOrContainedBy(LookupContext(*(I-1))))
+          return I;
+      }
+
+      return Decls.begin();
+    }
+
+    /// iterator - Iterate over the decls by walking their parent contexts too.
+    class iterator {
+    public:
+      typedef DeclsTy::iterator BaseIter;
+
+      iterator(const BaseIter &DeclIt) : DI(DeclIt) {}
+      const BaseIter &getBase() { return DI; }
+
+      NamedDecl *&operator*() const {
+        return *(DI-1);
+      }
+      
+      bool operator==(const iterator &RHS) const {
+        return DI == RHS.DI;
+      }
+      bool operator!=(const iterator &RHS) const {
+        return DI != RHS.DI;
+      }
+      
+      // Preincrement.
+      iterator& operator++() {
+        NamedDecl *D = **this;
+        void *Ptr = D->getIdentifier()->getFETokenInfo<void>();
+        assert(!isDeclPtr(Ptr) && "Decl with wrong id ?");
+        DI = toIdDeclInfo(Ptr)->FindContext(LookupContext(D), DI-1);
+        return *this;
+      }
+
+    private:
+      BaseIter DI;
+    };
+
+    /// ctx_iterator - Iterator over the decls of a specific context only.
+    class ctx_iterator {
+    public:
+      typedef DeclsTy::iterator BaseIter;
+
+      ctx_iterator(const BaseIter &DeclIt) : DI(DeclIt) {}
+      const BaseIter &getBase() { return DI; }
+
+      NamedDecl *&operator*() const {
+        return *(DI-1);
+      }
+      
+      bool operator==(const ctx_iterator &RHS) const {
+        return DI == RHS.DI;
+      }
+      bool operator!=(const ctx_iterator &RHS) const {
+        return DI != RHS.DI;
+      }
+      
+      // Preincrement.
+      ctx_iterator& operator++() {
+        NamedDecl *D = **this;
+        void *Ptr = D->getIdentifier()->getFETokenInfo<void>();
+        assert(!isDeclPtr(Ptr) && "Decl with wrong id ?");
+        IdDeclInfo *Info = toIdDeclInfo(Ptr);
+        
+        --DI;
+        if (DI != Info->Decls.begin() &&
+            LookupContext(D) != LookupContext(**this))
+          DI = Info->Decls.begin();
+        return *this;
+      }
+
+    private:
+      BaseIter DI;
+    };
+
+    void AddDecl(NamedDecl *D) {
+      Decls.insert(FindContext(LookupContext(D)), D);
+    }
+
+    /// AddShadowed - Add a decl by putting it directly above the 'Shadow' decl.
+    /// Later lookups will find the 'Shadow' decl first. The 'Shadow' decl must
+    /// be already added to the scope chain and must be in the same context as
+    /// the decl that we want to add.
+    void AddShadowed(NamedDecl *D, NamedDecl *Shadow) {
+      assert(LookupContext(D) == LookupContext(Shadow) &&
+             "Decl and Shadow not in same context!");
+
+      for (DeclsTy::iterator I = Decls.end(); I != Decls.begin(); --I) {
+        if (Shadow == *(I-1)) {
+          Decls.insert(I-1, D);
+          return;
+        }
+      }
+
+      assert(0 && "Shadow wasn't in scope chain!");
+    }
+
+    /// RemoveDecl - Remove the decl from the scope chain.
+    /// The decl must already be part of the decl chain.
+    void RemoveDecl(NamedDecl *D) {
+      for (DeclsTy::iterator I = Decls.end(); I != Decls.begin(); --I) {
+        if (D == *(I-1)) {
+          Decls.erase(I-1);
+          return;
+        }
+      }
+
+      assert(0 && "Didn't find this decl on its identifier's chain!");
+    }
+
+  private:
+    DeclsTy Decls;
+  };
+
+  /// SwizzledIterator - Can be instantiated either with a single NamedDecl*
+  /// (the common case where only one decl is associated with an identifier) or
+  /// with an 'Iter' iterator, when there are more than one decls to lookup.
+  template<typename Iter>
+  class SwizzledIterator {
+    uintptr_t Ptr;
+
+    SwizzledIterator() : Ptr(0) {}
+    SwizzledIterator(NamedDecl *D) {
+      Ptr = reinterpret_cast<uintptr_t>(D);
+    }
+    SwizzledIterator(Iter I) {
+      Ptr = reinterpret_cast<uintptr_t>(I.getBase()) | 0x1;
+    }
+
+    bool isIterator() const { return (Ptr & 0x1); }
+
+    Iter getIterator() const {
+      assert(isIterator() && "Ptr not an iterator.");
+      return reinterpret_cast<typename Iter::BaseIter>(Ptr & ~0x1);
+    }
+
+    friend class IdentifierResolver;
+  public:
+    NamedDecl *operator*() const {
+      if (isIterator())
+        return *getIterator();
+      else
+        return reinterpret_cast<NamedDecl*>(Ptr);
+    }
+    
+    bool operator==(const SwizzledIterator &RHS) const {
+      return Ptr == RHS.Ptr;
+    }
+    bool operator!=(const SwizzledIterator &RHS) const {
+      return Ptr != RHS.Ptr;
+    }
+
+    // Preincrement.
+    SwizzledIterator& operator++() {
+      if (isIterator()) {
+        Iter I = getIterator();
+        ++I;
+        Ptr = reinterpret_cast<uintptr_t>(I.getBase()) | 0x1;
+      }
+      else  // This is a single NamedDecl*.
+        Ptr = 0;
+
+      return *this;
+    }
+  };
+
 public:
-  IdentifierResolver();
-  ~IdentifierResolver();
+
+  typedef SwizzledIterator<IdDeclInfo::iterator> iterator;
+  typedef SwizzledIterator<IdDeclInfo::ctx_iterator> ctx_iterator;
+
+  /// begin - Returns an iterator for all decls, starting at the given
+  /// declaration context.
+  static iterator begin(const IdentifierInfo *II, DeclContext *Ctx);
+
+  static iterator end(const IdentifierInfo *II) {
+    void *Ptr = II->getFETokenInfo<void>();
+    if (!Ptr || isDeclPtr(Ptr))
+      return iterator();
+
+    IdDeclInfo *IDI = toIdDeclInfo(Ptr);
+    return iterator(IDI->decls_begin());
+  }
+
+  /// ctx_begin - Returns an iterator for only decls that belong to the given
+  /// declaration context.
+  static ctx_iterator ctx_begin(const IdentifierInfo *II, DeclContext *Ctx);
+
+  static ctx_iterator ctx_end(const IdentifierInfo *II) {
+    void *Ptr = II->getFETokenInfo<void>();
+    if (!Ptr || isDeclPtr(Ptr))
+      return ctx_iterator();
+
+    IdDeclInfo *IDI = toIdDeclInfo(Ptr);
+    return ctx_iterator(IDI->decls_begin());
+  }
+
+  /// isDeclInScope - If 'Ctx' is a function/method, isDeclInScope returns true
+  /// if 'D' is in Scope 'S', otherwise 'S' is ignored and isDeclInScope returns
+  /// true if 'D' belongs to the given declaration context.
+  static bool isDeclInScope(Decl *D, DeclContext *Ctx, Scope *S = 0) {
+    if (Ctx->isFunctionOrMethod())
+      return S->isDeclScope(D);
+
+    return LookupContext(D) == LookupContext(Ctx);
+  }
 
   /// AddDecl - Link the decl to its shadowed decl chain.
-  void AddDecl(NamedDecl *D, Scope *S);
+  void AddDecl(NamedDecl *D);
 
-  /// AddGlobalDecl - Link the decl at the top of the shadowed decl chain.
-  void AddGlobalDecl(NamedDecl *D);
+  /// AddShadowedDecl - Link the decl to its shadowed decl chain putting it
+  /// after the decl that the iterator points to, thus the 'CIT' decl will be
+  /// encountered before the 'D' decl.
+  void AddShadowedDecl(NamedDecl *D, NamedDecl *Shadow);
 
   /// RemoveDecl - Unlink the decl from its shadowed decl chain.
   /// The decl must already be part of the decl chain.
   void RemoveDecl(NamedDecl *D);
 
-  /// Lookup - Find the non-shadowed decl that belongs to one or more
-  /// of the specified Decl::IdentifierNamespaces.
-  NamedDecl *Lookup(const IdentifierInfo *II, unsigned NSI);
+  IdentifierResolver();
+  ~IdentifierResolver();
 
 private:
-  // An instance of IdDeclInfoMap class, that's hidden away in the
-  // implementation file.
-  void *IdDeclInfos;
+  class IdDeclInfoMap;
+  IdDeclInfoMap *IdDeclInfos;
+
+  /// Identifier's FETokenInfo contains a Decl pointer if lower bit == 0.
+  static inline bool isDeclPtr(void *Ptr) {
+    return (reinterpret_cast<uintptr_t>(Ptr) & 0x1) == 0;
+  }
+
+  /// Identifier's FETokenInfo contains a IdDeclInfo pointer if lower bit == 1.
+  static inline IdDeclInfo *toIdDeclInfo(void *Ptr) {
+    assert((reinterpret_cast<uintptr_t>(Ptr) & 0x1) == 1
+          && "Ptr not a IdDeclInfo* !");
+    return reinterpret_cast<IdDeclInfo*>(
+                    reinterpret_cast<uintptr_t>(Ptr) & ~0x1
+                                                            );
+  }
 };
 
 } // end namespace clang

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Fri May  9 18:39:43 2008
@@ -59,13 +59,40 @@
 
 /// Add this decl to the scope shadowed decl chains.
 void Sema::PushOnScopeChains(NamedDecl *D, Scope *S) {
-  IdResolver.AddDecl(D, S);
   S->AddDecl(D);
+
+  // C++ [basic.scope]p4:
+  //   -- exactly one declaration shall declare a class name or
+  //   enumeration name that is not a typedef name and the other
+  //   declarations shall all refer to the same object or
+  //   enumerator, or all refer to functions and function templates;
+  //   in this case the class name or enumeration name is hidden.
+  if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
+    // We are pushing the name of a tag (enum or class).
+    IdentifierResolver::ctx_iterator
+      CIT = IdResolver.ctx_begin(TD->getIdentifier(), TD->getDeclContext());
+    if (CIT != IdResolver.ctx_end(TD->getIdentifier()) &&
+        IdResolver.isDeclInScope(*CIT, TD->getDeclContext(), S)) {
+      // There is already a declaration with the same name in the same
+      // scope. It must be found before we find the new declaration,
+      // so swap the order on the shadowed declaration chain.
+
+      IdResolver.AddShadowedDecl(TD, *CIT);
+      return;
+    }
+  }
+
+  IdResolver.AddDecl(D);
 }
 
 void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) {
   if (S->decl_empty()) return;
   assert((S->getFlags() & Scope::DeclScope) &&"Scope shouldn't contain decls!");
+
+  // We only want to remove the decls from the identifier decl chains for local
+  // scopes, when inside a function/method.
+  if (S->getFnParent() == 0)
+    return;
          
   for (Scope::decl_iterator I = S->decl_begin(), E = S->decl_end();
        I != E; ++I) {
@@ -115,8 +142,10 @@
   // Scan up the scope chain looking for a decl that matches this identifier
   // that is in the appropriate namespace.  This search should not take long, as
   // shadowing of names is uncommon, and deep shadowing is extremely uncommon.
-  NamedDecl *ND = IdResolver.Lookup(II, NS);
-  if (ND) return ND;
+  for (IdentifierResolver::iterator
+       I = IdResolver.begin(II, CurContext), E = IdResolver.end(II); I != E; ++I)
+    if ((*I)->getIdentifierNamespace() & NS)
+      return *I;
 
   // If we didn't find a use of this identifier, and if the identifier
   // corresponds to a compiler builtin, create the decl object for the builtin
@@ -184,11 +213,7 @@
   
   
   // TUScope is the translation-unit scope to insert this function into.
-  TUScope->AddDecl(New);
-  
-  // Add this decl to the end of the identifier info.
-  IdResolver.AddGlobalDecl(New);
-
+  PushOnScopeChains(New, TUScope);
   return New;
 }
 
@@ -797,12 +822,12 @@
                          D.getAttributes());
     // Merge the decl with the existing one if appropriate. If the decl is
     // in an outer scope, it isn't the same thing.
-    if (PrevDecl && S->isDeclScope(PrevDecl)) {
+    if (PrevDecl && IdResolver.isDeclInScope(PrevDecl, CurContext, S)) {
       NewTD = MergeTypeDefDecl(NewTD, PrevDecl);
       if (NewTD == 0) return 0;
     }
     New = NewTD;
-    if (S->getParent() == 0) {
+    if (S->getFnParent() == 0) {
       // C99 6.7.7p2: If a typedef name specifies a variably modified type
       // then it shall have block scope.
       if (NewTD->getUnderlyingType()->isVariablyModifiedType()) {
@@ -873,7 +898,9 @@
 
     // Merge the decl with the existing one if appropriate. Since C functions
     // are in a flat namespace, make sure we consider decls in outer scopes.
-    if (PrevDecl) {
+    if (PrevDecl &&
+        (!getLangOptions().CPlusPlus ||
+         IdResolver.isDeclInScope(PrevDecl, CurContext, S)) ) {
       bool Redeclaration = false;
       NewFD = MergeFunctionDecl(NewFD, PrevDecl, Redeclaration);
       if (NewFD == 0) return 0;
@@ -914,7 +941,7 @@
     case DeclSpec::SCS_register:       SC = VarDecl::Register; break;
     case DeclSpec::SCS_private_extern: SC = VarDecl::PrivateExtern; break;
     }    
-    if (S->getParent() == 0) {
+    if (S->getFnParent() == 0) {
       // C99 6.9p2: The storage-class specifiers auto and register shall not
       // appear in the declaration specifiers in an external declaration.
       if (SC == VarDecl::Auto || SC == VarDecl::Register) {
@@ -942,7 +969,7 @@
     }
     // Merge the decl with the existing one if appropriate. If the decl is
     // in an outer scope, it isn't the same thing.
-    if (PrevDecl && S->isDeclScope(PrevDecl)) {
+    if (PrevDecl && IdResolver.isDeclInScope(PrevDecl, CurContext, S)) {
       NewVD = MergeVarDecl(NewVD, PrevDecl);
       if (NewVD == 0) return 0;
     }
@@ -1221,12 +1248,14 @@
   // See if this is a redefinition.
   Decl *PrevDcl = LookupDecl(D.getIdentifier(), Decl::IDNS_Ordinary,
                              GlobalScope);
-  if (FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(PrevDcl)) {
-    const FunctionDecl *Definition;
-    if (FD->getBody(Definition)) {
-      Diag(D.getIdentifierLoc(), diag::err_redefinition, 
-           D.getIdentifier()->getName());
-      Diag(Definition->getLocation(), diag::err_previous_definition);
+  if (PrevDcl && IdResolver.isDeclInScope(PrevDcl, CurContext)) {
+    if (FunctionDecl *FD = dyn_cast<FunctionDecl>(PrevDcl)) {
+      const FunctionDecl *Definition;
+      if (FD->getBody(Definition)) {
+        Diag(D.getIdentifierLoc(), diag::err_redefinition, 
+             D.getIdentifier()->getName());
+        Diag(Definition->getLocation(), diag::err_previous_definition);
+      }
     }
   }
   Decl *decl = static_cast<Decl*>(ActOnDeclarator(GlobalScope, D, 0));
@@ -1375,7 +1404,8 @@
       // If this is a use of a previous tag, or if the tag is already declared in
       // the same scope (so that the definition/declaration completes or
       // rementions the tag), reuse the decl.
-      if (TK == TK_Reference || S->isDeclScope(PrevDecl)) {
+      if (TK == TK_Reference ||
+          IdResolver.isDeclInScope(PrevDecl, CurContext, S)) {
         // Make sure that this wasn't declared as an enum and now used as a struct
         // or something similar.
         if (PrevDecl->getKind() != Kind) {
@@ -1733,7 +1763,7 @@
   // Verify that there isn't already something declared with this name in this
   // scope.
   if (Decl *PrevDecl = LookupDecl(Id, Decl::IDNS_Ordinary, S)) {
-    if (S->isDeclScope(PrevDecl)) {
+    if (IdResolver.isDeclInScope(PrevDecl, CurContext, S)) {
       if (isa<EnumConstantDecl>(PrevDecl))
         Diag(IdLoc, diag::err_redefinition_of_enumerator, Id->getName());
       else

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Fri May  9 18:39:43 2008
@@ -335,7 +335,8 @@
         LookupDecl(II, Decl::IDNS_Tag | Decl::IDNS_Ordinary, DeclRegionScope,
                    /*enableLazyBuiltinCreation=*/false);
 
-    if (PrevDecl && DeclRegionScope->isDeclScope(PrevDecl)) {
+    if (PrevDecl &&
+        IdResolver.isDeclInScope(PrevDecl, CurContext, DeclRegionScope)) {
       if (NamespaceDecl *OrigNS = dyn_cast<NamespaceDecl>(PrevDecl)) {
         // This is an extended namespace definition.
         // Attach this namespace decl to the chain of extended namespace

Modified: cfe/trunk/test/Sema/cxx-namespace.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/cxx-namespace.cpp?rev=50923&r1=50922&r2=50923&view=diff

==============================================================================
--- cfe/trunk/test/Sema/cxx-namespace.cpp (original)
+++ cfe/trunk/test/Sema/cxx-namespace.cpp Fri May  9 18:39:43 2008
@@ -8,8 +8,46 @@
 int A; // expected-error {{error: redefinition of 'A' as different kind of symbol}}
 class A; // expected-error {{error: redefinition of 'A' as different kind of symbol}}
 
-class B; // expected-error {{error: previous definition is here}}
+class B {}; // expected-error {{error: previous definition is here}}
 namespace B {} // expected-error {{error: redefinition of 'B' as different kind of symbol}}
 
 void C(); // expected-error {{error: previous definition is here}}
 namespace C {} // expected-error {{error: redefinition of 'C' as different kind of symbol}}
+
+namespace S1 {
+  int x;
+
+  namespace S2 {
+
+    namespace S3 {
+      B x;
+    }
+  }
+}
+
+namespace S1 {
+  void f() {
+    x = 0;
+  }
+
+  namespace S2 {
+    
+    namespace S3 {
+      void f() {
+        x = 0; // expected-error {{error: incompatible type assigning 'int', expected 'class B'}}
+      }
+    }
+
+    int y;
+  }
+}
+
+namespace S1 {
+  namespace S2 {
+    namespace S3 {
+      void f3() {
+        y = 0;
+      }
+    }
+  }
+}





More information about the cfe-commits mailing list