Index: include/clang/AST/Decl.h
===================================================================
--- include/clang/AST/Decl.h	(revision 48945)
+++ include/clang/AST/Decl.h	(working copy)
@@ -52,6 +52,7 @@
            PropertyDecl,
     //     ScopedDecl
              CompatibleAlias,
+             Namespace,
     //       TypeDecl
                ObjCInterface,
                Typedef,
@@ -88,11 +89,13 @@
 
   /// IdentifierNamespace - According to C99 6.2.3, there are four namespaces,
   /// labels, tags, members and ordinary identifiers.
+  /// C++ namespace names clash with names from Ordinary and Tag namespaces.
   enum IdentifierNamespace {
-    IDNS_Label,
-    IDNS_Tag,
-    IDNS_Member,
-    IDNS_Ordinary
+    IDNS_Ordinary     = 0x1,
+    IDNS_Tag          = 0x2,
+    IDNS_Label        = 0x4,
+    IDNS_Member       = 0x8,
+    IDNS_CXXNamespace = IDNS_Ordinary | IDNS_Tag
   };
   
   /// ObjCDeclQualifier - Qualifier used on types in method declarations
@@ -168,6 +171,8 @@
     case Class:
     case Enum:
       return IDNS_Tag;
+    case Namespace:
+      return IDNS_CXXNamespace;
     }
   }
   // global temp stats (until we have a per-module visitor)
@@ -287,6 +292,82 @@
   void ReadInRec(llvm::Deserializer& D);
 };
 
+/// NamespaceDecl - Represent a C++ namespace.
+class NamespaceDecl : public ScopedDecl {
+  llvm::SmallVector<ScopedDecl *, 16> Decls;
+  SourceLocation LBracLoc, RBracLoc;
+  
+  // For extended namespace definitions like:
+  //
+  // namespace A { int x; }
+  // namespace A { int y; }
+  //
+  // there will be one NamespaceDecl for each declaration.
+  // HeadNS points to the first NamespaceDecl,
+  // NextNS points to the next extended declaration.
+
+  NamespaceDecl *HeadNS;
+  NamespaceDecl *NextNS;
+
+  NamespaceDecl(SourceLocation L, IdentifierInfo *Id)
+    : ScopedDecl(Namespace, L, Id, 0), NextNS(0) {
+      HeadNS = this;
+  }
+public:
+  static NamespaceDecl *Create(ASTContext &C,
+                               SourceLocation L, IdentifierInfo *Id);
+
+  NamespaceDecl *getHeadNamespace() { return HeadNS; }
+  void setHeadNamespace(NamespaceDecl *ND) { HeadNS = ND; }
+
+  NamespaceDecl *getNextNamespace() { return NextNS; }
+  void setNextNamespace(NamespaceDecl *ND) { NextNS = ND; }
+
+  bool decls_empty() const { return Decls.empty(); }
+  
+  typedef llvm::SmallVector<ScopedDecl*, 16>::iterator decl_iterator;
+  decl_iterator decl_begin() { return Decls.begin(); }
+  decl_iterator decl_end() { return Decls.end(); }
+  ScopedDecl *decl_back() { return Decls.back(); }
+
+  typedef llvm::SmallVector<ScopedDecl*,16>::const_iterator const_decl_iterator;
+  const_decl_iterator decl_begin() const { return Decls.begin(); }
+  const_decl_iterator decl_end() const { return Decls.end(); }
+  const ScopedDecl *decl_back() const { return Decls.back(); }
+
+  typedef llvm::SmallVector<ScopedDecl*, 16>::reverse_iterator
+                                                          reverse_decl_iterator;
+  reverse_decl_iterator decl_rbegin() { return Decls.rbegin(); }
+  reverse_decl_iterator decl_rend() { return Decls.rend(); }
+
+  typedef llvm::SmallVector<ScopedDecl*, 16>::const_reverse_iterator 
+    const_reverse_decl_iterator;
+  const_reverse_decl_iterator decl_rbegin() const { return Decls.rbegin(); }
+  const_reverse_decl_iterator decl_rend() const { return Decls.rend(); }
+    
+  void push_back(ScopedDecl *D) { Decls.push_back(D); }
+  
+  virtual SourceRange getSourceRange() const { 
+    return SourceRange(LBracLoc, RBracLoc); 
+  }
+
+  SourceLocation getLBracLoc() const { return LBracLoc; }
+  SourceLocation getRBracLoc() const { return RBracLoc; }
+  void setLBracLoc(SourceLocation LBrace) { LBracLoc = LBrace; }
+  void setRBracLoc(SourceLocation RBrace) { RBracLoc = RBrace; }
+  
+  // Implement isa/cast/dyncast/etc.
+  static bool classof(const Decl *D) { return D->getKind() == Namespace; }
+  static bool classof(const NamespaceDecl *D) { return true; }
+  
+protected:
+  void EmitInRec(llvm::Serializer& S) const;
+  void ReadInRec(llvm::Deserializer& D);
+  
+  void EmitOutRec(llvm::Serializer& S) const;
+  void ReadOutRec(llvm::Deserializer& D);
+};
+
 /// VarDecl - An instance of this class is created to represent a variable
 /// declaration or definition.
 class VarDecl : public ValueDecl {
Index: include/clang/Basic/DiagnosticKinds.def
===================================================================
--- include/clang/Basic/DiagnosticKinds.def	(revision 48945)
+++ include/clang/Basic/DiagnosticKinds.def	(working copy)
@@ -626,6 +626,8 @@
 
 DIAG(err_unexpected_typedef, ERROR,
      "unexpected type name '%0': expected expression")
+DIAG(err_unexpected_namespace, ERROR,
+     "unexpected namespace name '%0': expected expression")
 DIAG(err_undeclared_var_use, ERROR,
      "use of undeclared identifier '%0'")
 DIAG(warn_deprecated, WARNING,
Index: include/clang/Parse/Action.h
===================================================================
--- include/clang/Parse/Action.h	(revision 48945)
+++ include/clang/Parse/Action.h	(working copy)
@@ -94,7 +94,7 @@
   
   /// isTypeName - Return non-null if the specified identifier is a typedef name
   /// in the current scope.
-  virtual DeclTy *isTypeName(const IdentifierInfo &II, Scope *S) const = 0;
+  virtual DeclTy *isTypeName(IdentifierInfo &II, Scope *S) = 0;
   
   /// ActOnDeclarator - This callback is invoked when a declarator is parsed and
   /// 'Init' specifies the initializer if any.  This is for things like:
@@ -123,6 +123,29 @@
     return Group;
   }
 
+  /// ActOnStartNamespaceDef - This is called at the start of a namespace
+  /// definition. If the namespace has been already declared, and this is an
+  /// extended namespace definition, HeadNamespc will be set to first namespace
+  /// decl. If it's declared for the first time, HeadNamespc will be the same
+  /// decl that this method returns.
+  virtual DeclTy *ActOnStartNamespaceDef(Scope *S, SourceLocation IdentLoc,
+                                        IdentifierInfo *Ident,
+                                        SourceLocation LBrace,
+                                        DeclTy *&HeadNamespc) {
+    return 0;
+  }
+
+  virtual void ActOnParsedDeclarationForNamespace(DeclTy *Dcl,
+                                                  DeclTy* Namespc) {
+    return;
+  }
+
+  /// ActOnFinishNamespaceDef - This callback is called after a namespace is
+  /// exited. Decl is the DeclTy returned by ActOnStartNamespaceDef.
+  virtual void ActOnFinishNamespaceDef(DeclTy *Dcl,SourceLocation RBrace) {
+    return;
+  }
+
   /// ActOnStartOfFunctionDef - This is called at the start of a function
   /// definition, instead of calling ActOnDeclarator.  The Declarator includes
   /// information about formal arguments that are part of this function.
@@ -730,7 +753,7 @@
   
   /// isTypeName - This looks at the IdentifierInfo::FETokenInfo field to
   /// determine whether the name is a typedef or not in this scope.
-  virtual DeclTy *isTypeName(const IdentifierInfo &II, Scope *S) const;
+  virtual DeclTy *isTypeName(IdentifierInfo &II, Scope *S);
   
   /// ActOnDeclarator - If this is a typedef declarator, we modify the
   /// IdentifierInfo::FETokenInfo field to keep track of this fact, until S is
Index: include/clang/Parse/Parser.h
===================================================================
--- include/clang/Parse/Parser.h	(revision 48945)
+++ include/clang/Parse/Parser.h	(working copy)
@@ -49,6 +49,9 @@
   enum { ScopeCacheSize = 16 };
   unsigned NumCachedScopes;
   Scope *ScopeCache[ScopeCacheSize];
+
+  typedef llvm::DenseMap<Action::DeclTy*, Scope*> NamespaceScopeMapTy;
+  NamespaceScopeMapTy NamespaceScopeMap;
 public:
   Parser(Preprocessor &PP, Action &Actions);
   ~Parser();
@@ -229,6 +232,10 @@
   
   /// EnterScope - Start a new scope.
   void EnterScope(unsigned ScopeFlags);
+
+  /// EnterNamespaceScope - This will map the namespace decl to the scope so
+  /// that it can be re-entered for an extended namespace definition.
+  void EnterNamespaceScope(DeclTy *NameSpc);
   
   /// ExitScope - Pop a scope off the scope stack.
   void ExitScope();
Index: include/clang/Parse/Scope.h
===================================================================
--- include/clang/Parse/Scope.h	(revision 48945)
+++ include/clang/Parse/Scope.h	(working copy)
@@ -42,7 +42,10 @@
     
     /// DeclScope - This is a scope that can contain a declaration.  Some scopes
     /// just contain loop constructs but don't contain decls.
-    DeclScope = 0x08
+    DeclScope = 0x08,
+
+    /// NamespaceScope - Used for C++ namespaces.
+    NamespaceScope = 0x10
   };
 private:
   /// The parent scope for this scope.  This is null for the translation-unit
@@ -65,6 +68,8 @@
   /// preceeding BreakParent/ContinueParent if this scope is not one, or null if
   /// there is no containing break/continue scope.
   Scope *BreakParent, *ContinueParent;
+
+  Scope *NamespaceParent;
   
   /// DeclsInScope - This keeps track of all declarations in this scope.  When
   /// the declaration is added to the scope, it is set as the current
@@ -74,7 +79,7 @@
   /// implement these semantics.
   typedef llvm::SmallPtrSet<Action::DeclTy*, 32> DeclSetTy;
   DeclSetTy DeclsInScope;
-  
+
 public:
   Scope(Scope *Parent, unsigned ScopeFlags) {
     Init(Parent, ScopeFlags);
@@ -103,8 +108,14 @@
   /// would be affected by.
   const Scope *getBreakParent() const { return BreakParent; }
   Scope *getBreakParent() { return BreakParent; }
-  
- 
+
+  const Scope *getNamespaceParent() const { return NamespaceParent; }
+  Scope *getNamespaceParent() { return NamespaceParent; }
+
+  bool isLocalScope() const {
+    return FnParent != 0;
+  }
+
   typedef DeclSetTy::iterator decl_iterator;
   decl_iterator decl_begin() const { return DeclsInScope.begin(); }
   decl_iterator decl_end()   const { return DeclsInScope.end(); }
@@ -131,14 +142,17 @@
       FnParent       = AnyParent->FnParent;
       BreakParent    = AnyParent->BreakParent;
       ContinueParent = AnyParent->ContinueParent;
+      NamespaceParent    = AnyParent->NamespaceParent;
     } else {
       FnParent = BreakParent = ContinueParent = 0;
+      NamespaceParent = 0;
     }
     
     // If this scope is a function or contains breaks/continues, remember it.
     if (Flags & FnScope)       FnParent = this;
     if (Flags & BreakScope)    BreakParent = this;
     if (Flags & ContinueScope) ContinueParent = this;
+    if (Flags & NamespaceScope)    NamespaceParent = this;
     
     DeclsInScope.clear();
   }      
Index: lib/AST/Decl.cpp
===================================================================
--- lib/AST/Decl.cpp	(revision 48945)
+++ lib/AST/Decl.cpp	(working copy)
@@ -31,6 +31,7 @@
 static unsigned nEnumConst = 0;
 static unsigned nEnumDecls = 0;
 static unsigned nTypedef = 0;
+static unsigned nNamespaceDecls = 0;
 static unsigned nFieldDecls = 0;
 static unsigned nInterfaceDecls = 0;
 static unsigned nClassDecls = 0;
@@ -175,6 +176,7 @@
 
 void Decl::addDeclKind(Kind k) {
   switch (k) {
+  case Namespace:           nNamespaceDecls++; break;
   case Typedef:             nTypedef++; break;
   case Function:            nFuncs++; break;
   case BlockVar:            nBlockVars++; break;
@@ -204,6 +206,11 @@
 // Decl Allocation/Deallocation Method Implementations
 //===----------------------------------------------------------------------===//
 
+NamespaceDecl *NamespaceDecl::Create(ASTContext &C, SourceLocation L, IdentifierInfo *Id) {
+  void *Mem = C.getAllocator().Allocate<NamespaceDecl>();
+  return new (Mem) NamespaceDecl(L, Id);
+}
+
 BlockVarDecl *BlockVarDecl::Create(ASTContext &C, SourceLocation L,
                                    IdentifierInfo *Id, QualType T,
                                    StorageClass S, ScopedDecl *PrevDecl) {
Index: lib/Parse/MinimalAction.cpp
===================================================================
--- lib/Parse/MinimalAction.cpp	(revision 48945)
+++ lib/Parse/MinimalAction.cpp	(working copy)
@@ -52,7 +52,7 @@
 /// determine whether the name is a type name (objc class name or typedef) or
 /// not in this scope.
 Action::DeclTy *
-MinimalAction::isTypeName(const IdentifierInfo &II, Scope *S) const {
+MinimalAction::isTypeName(IdentifierInfo &II, Scope *S) {
   if (TypeNameInfo *TI = II.getFETokenInfo<TypeNameInfo>())
     if (TI->isTypeName)
       return TI;
Index: lib/Parse/ParseDeclCXX.cpp
===================================================================
--- lib/Parse/ParseDeclCXX.cpp	(revision 48945)
+++ lib/Parse/ParseDeclCXX.cpp	(working copy)
@@ -62,16 +62,31 @@
     // FIXME: parse this.
   } else if (Tok.is(tok::l_brace)) {
     SourceLocation LBrace = ConsumeBrace();
-    // FIXME: push a scope, push a namespace decl.
-    
+    // When there are extended namespace definitions like
+    //
+    // namespace A { int x; }
+    // namespace A { int y; }
+    //
+    // HeadNamespc gets the first NamespaceDecl.
+    // If the namespace hasn't been declared before, HeadNamespc is the decl
+    // that ActOnStartNamespaceDef returns.
+    DeclTy *HeadNamespc;
+    DeclTy *NamespcDecl =
+      Actions.ActOnStartNamespaceDef(CurScope, IdentLoc, Ident,
+                                  LBrace, HeadNamespc);
+    EnterNamespaceScope(HeadNamespc);
+
     while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
-      // FIXME capture the decls.
-      ParseExternalDeclaration();
+      DeclTy *D = ParseExternalDeclaration();
+      Actions.ActOnParsedDeclarationForNamespace(D, NamespcDecl);
     }
     
     SourceLocation RBrace = MatchRHSPunctuation(tok::r_brace, LBrace);
+    Actions.ActOnFinishNamespaceDef(NamespcDecl, RBrace);
+    ExitScope();
+
+    return NamespcDecl;
     
-    // FIXME: act on this.
   } else {
     unsigned D = Ident ? diag::err_expected_lbrace : 
                          diag::err_expected_ident_lbrace;
Index: lib/Parse/Parser.cpp
===================================================================
--- lib/Parse/Parser.cpp	(revision 48945)
+++ lib/Parse/Parser.cpp	(working copy)
@@ -184,6 +184,16 @@
   }
 }
 
+void Parser::EnterNamespaceScope(DeclTy *NSD) {
+  assert(NSD && "passed null parameter");
+  Scope *& S = NamespaceScopeMap.FindAndConstruct(NSD).second;
+  if (!S)
+    S = new Scope(CurScope, Scope::NamespaceScope | Scope::DeclScope);
+
+  assert(S->getParent() == CurScope && "namespace not directly nested");
+  CurScope = S;
+}
+
 /// ExitScope - Pop a scope off the scope stack.
 void Parser::ExitScope() {
   assert(CurScope && "Scope imbalance!");
@@ -192,14 +202,20 @@
   // decls in it.
   if (!CurScope->decl_empty())
     Actions.ActOnPopScope(Tok.getLocation(), CurScope);
-  
+
   Scope *OldScope = CurScope;
   CurScope = OldScope->getParent();
-  
-  if (NumCachedScopes == ScopeCacheSize)
-    delete OldScope;
-  else
-    ScopeCache[NumCachedScopes++] = OldScope;
+
+  if (OldScope->getFlags() & Scope::NamespaceScope) {
+    // Don't delete the namespace scope, we may enter it again.
+    // It's been added to the NamespaceScopeMap and it will be deleted
+    // at Parser's destructor.
+  } else {
+    if (NumCachedScopes == ScopeCacheSize)
+      delete OldScope;
+    else
+      ScopeCache[NumCachedScopes++] = OldScope;
+  }
 }
 
 
@@ -216,6 +232,11 @@
   // Free the scope cache.
   for (unsigned i = 0, e = NumCachedScopes; i != e; ++i)
     delete ScopeCache[i];
+
+  // Delete the namespace scopes.
+  for (NamespaceScopeMapTy::iterator it = NamespaceScopeMap.begin();
+       it != NamespaceScopeMap.end(); ++it)
+    delete it->second;
 }
 
 /// Initialize - Warm up the parser.
@@ -644,4 +665,3 @@
   
   return Result;
 }
-
Index: lib/Sema/Sema.cpp
===================================================================
--- lib/Sema/Sema.cpp	(revision 48945)
+++ lib/Sema/Sema.cpp	(working copy)
@@ -48,30 +48,25 @@
   
   // Add the built-in ObjC types.
   t = cast<TypedefType>(Context.getObjCIdType().getTypePtr());
-  t->getDecl()->getIdentifier()->setFETokenInfo(t->getDecl());
-  TUScope->AddDecl(t->getDecl());
+  AddDeclInScope(t->getDecl(), TUScope);
   t = cast<TypedefType>(Context.getObjCClassType().getTypePtr());
-  t->getDecl()->getIdentifier()->setFETokenInfo(t->getDecl());
-  TUScope->AddDecl(t->getDecl());
+  AddDeclInScope(t->getDecl(), TUScope);
   ObjCInterfaceType *it = cast<ObjCInterfaceType>(Context.getObjCProtoType());
   ObjCInterfaceDecl *IDecl = it->getDecl();
-  IDecl->getIdentifier()->setFETokenInfo(IDecl);
-  TUScope->AddDecl(IDecl);
+  AddDeclInScope(IDecl, TUScope);
   
   // Synthesize "typedef struct objc_selector *SEL;"
   RecordDecl *SelTag = RecordDecl::Create(Context, Decl::Struct,
                                           SourceLocation(), 
                                           &Context.Idents.get("objc_selector"),
                                           0);
-  SelTag->getIdentifier()->setFETokenInfo(SelTag);
-  TUScope->AddDecl(SelTag);
+  AddDeclInScope(SelTag, TUScope);
   
   QualType SelT = Context.getPointerType(Context.getTagDeclType(SelTag));
   TypedefDecl *SelTypedef = TypedefDecl::Create(Context, SourceLocation(),
                                                 &Context.Idents.get("SEL"),
                                                 SelT, 0);
-  SelTypedef->getIdentifier()->setFETokenInfo(SelTypedef);
-  TUScope->AddDecl(SelTypedef);
+  AddDeclInScope(SelTypedef, TUScope);
   Context.setObjCSelType(SelTypedef);
 }
 
Index: lib/Sema/Sema.h
===================================================================
--- lib/Sema/Sema.h	(revision 48945)
+++ lib/Sema/Sema.h	(working copy)
@@ -92,7 +92,27 @@
   /// with @protocol keyword, so that we can emit errors on duplicates and
   /// find the declarations when needed.
   llvm::DenseMap<IdentifierInfo*, ObjCProtocolDecl*> ObjCProtocols;
-  
+
+  /// IdentifierTag - A instance of this class is associated with each
+  /// identifier, by the get/setFETokenInfo
+  struct IdentifierTag {
+    typedef llvm::DenseMap<Scope*, ScopedDecl*> ScopedDeclsTy;
+
+    /// ScopedDecls - Associate each ScopedDecl that uses the particular
+    /// identifier with the non-local scope that it was created in.
+    /// This is used for fast name lookup.
+    ScopedDeclsTy ScopedDecls;
+
+    /// LocalDecl - When in a local scope, this holds the local declaration
+    /// chain that is associated with the identifier. We don't need to refer to
+    /// local declarations outside of their scope, so there's no need to cache
+    /// their scope with ScopedDecls.
+    ScopedDecl *LocalDecl;
+
+    IdentifierTag()
+      : ScopedDecls(ScopedDeclsTy(4)), LocalDecl(0) {}
+  };
+
   // Enum values used by KnownFunctionIDs (see below).
   enum {
     id_printf,
@@ -118,7 +138,7 @@
   /// to lookup file scope declarations in the "ordinary" C decl namespace.
   /// For example, user-defined classes, built-in "id" type, etc.
   Scope *TUScope;
-  
+
   /// ObjCMethodList - a linked list of methods with different signatures.
   struct ObjCMethodList {
     ObjCMethodDecl *Method;
@@ -188,7 +208,7 @@
   //===--------------------------------------------------------------------===//
   // Symbol table / Decl tracking callbacks: SemaDecl.cpp.
   //
-  virtual DeclTy *isTypeName(const IdentifierInfo &II, Scope *S) const;
+  virtual DeclTy *isTypeName(IdentifierInfo &II, Scope *S);
   virtual DeclTy *ActOnDeclarator(Scope *S, Declarator &D, DeclTy *LastInGroup);
   void AddInitializerToDecl(DeclTy *dcl, ExprTy *init);
   virtual DeclTy *FinalizeDeclaratorGroup(Scope *S, DeclTy *Group);
@@ -241,6 +261,8 @@
                                     Scope *FnBodyScope);  
   ScopedDecl *LookupScopedDecl(IdentifierInfo *II, unsigned NSI, 
                                SourceLocation IdLoc, Scope *S);
+  void AddDeclInScope(ScopedDecl *D, Scope *S);
+  IdentifierTag &getIdentifierTag(IdentifierInfo *II);
   ScopedDecl *LookupInterfaceDecl(IdentifierInfo *II);
   ObjCInterfaceDecl *getObjCInterfaceDecl(IdentifierInfo *Id);
   ScopedDecl *LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID, Scope *S);
@@ -510,6 +532,15 @@
                                 ExprTy *expr, TypeTy *type,
                                 SourceLocation RPLoc);
   
+  // Act on C++ namespaces
+  virtual DeclTy *ActOnStartNamespaceDef(Scope *S, SourceLocation IdentLoc,
+                                        IdentifierInfo *Ident,
+                                        SourceLocation LBrace,
+                                        DeclTy *&HeadNamespc);
+  virtual void ActOnFinishNamespaceDef(DeclTy *Dcl, SourceLocation RBrace);
+
+  virtual void ActOnParsedDeclarationForNamespace(DeclTy *Dcl, DeclTy* Namespc);
+
   /// ActOnCXXCasts - Parse {dynamic,static,reinterpret,const}_cast's.
   virtual ExprResult ActOnCXXCasts(SourceLocation OpLoc, tok::TokenKind Kind,
                                    SourceLocation LAngleBracketLoc, TypeTy *Ty,
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp	(revision 48945)
+++ lib/Sema/SemaDecl.cpp	(working copy)
@@ -32,11 +32,9 @@
 #include "llvm/ADT/DenseSet.h"
 using namespace clang;
 
-Sema::DeclTy *Sema::isTypeName(const IdentifierInfo &II, Scope *S) const {
-  Decl *IIDecl = II.getFETokenInfo<Decl>();
+Sema::DeclTy *Sema::isTypeName(IdentifierInfo &II, Scope *S) {
   // Find first occurance of none-tagged declaration
-  while(IIDecl && IIDecl->getIdentifierNamespace() != Decl::IDNS_Ordinary)
-    IIDecl = cast<ScopedDecl>(IIDecl)->getNext();
+  Decl *IIDecl = LookupScopedDecl(&II, Decl::IDNS_Ordinary, SourceLocation(),S);
   if (!IIDecl)
     return 0;
   if (isa<TypedefDecl>(IIDecl) || isa<ObjCInterfaceDecl>(IIDecl))
@@ -50,44 +48,49 @@
 void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) {
   if (S->decl_empty()) return;
   assert((S->getFlags() & Scope::DeclScope) &&"Scope shouldn't contain decls!");
-         
-  for (Scope::decl_iterator I = S->decl_begin(), E = S->decl_end();
-       I != E; ++I) {
-    Decl *TmpD = static_cast<Decl*>(*I);
-    assert(TmpD && "This decl didn't get pushed??");
-    ScopedDecl *D = dyn_cast<ScopedDecl>(TmpD);
-    assert(D && "This decl isn't a ScopedDecl?");
-    
-    IdentifierInfo *II = D->getIdentifier();
-    if (!II) continue;
-    
-    // Unlink this decl from the identifier.  Because the scope contains decls
-    // in an unordered collection, and because we have multiple identifier
-    // namespaces (e.g. tag, normal, label),the decl may not be the first entry.
-    if (II->getFETokenInfo<Decl>() == D) {
-      // Normal case, no multiple decls in different namespaces.
-      II->setFETokenInfo(D->getNext());
-    } else {
-      // Scan ahead.  There are only three namespaces in C, so this loop can
-      // never execute more than 3 times.
-      ScopedDecl *SomeDecl = II->getFETokenInfo<ScopedDecl>();
-      while (SomeDecl->getNext() != D) {
-        SomeDecl = SomeDecl->getNext();
-        assert(SomeDecl && "Didn't find this decl on its identifier's chain!");
+
+  // Unlink the identifiers from the local decl scope chain.
+  if (S->isLocalScope()) {         
+    for (Scope::decl_iterator I = S->decl_begin(), E = S->decl_end();
+         I != E; ++I) {
+      Decl *TmpD = static_cast<Decl*>(*I);
+      assert(TmpD && "This decl didn't get pushed??");
+      ScopedDecl *D = dyn_cast<ScopedDecl>(TmpD);
+      assert(D && "This decl isn't a ScopedDecl?");
+      
+      IdentifierInfo *II = D->getIdentifier();
+      if (!II) continue;
+      
+      IdentifierTag &ITag = getIdentifierTag(II);
+
+      // Unlink this decl from the identifier.  Because the scope contains decls
+      // in an unordered collection, and because we have multiple identifier
+      // namespaces (e.g. tag,normal,label),the decl may not be the first entry.
+      if (ITag.LocalDecl == D) {
+        // Normal case, no multiple decls in different namespaces.
+        ITag.LocalDecl = D->getNext();
+      } else {
+        // Scan ahead.  There are only three namespaces in C, so this loop can
+        // never execute more than 3 times.
+        ScopedDecl *SomeDecl = ITag.LocalDecl;
+        while (SomeDecl->getNext() != D) {
+          SomeDecl = SomeDecl->getNext();
+          assert(SomeDecl &&"Didn't find this decl on its identifier's chain!");
+        }
+        SomeDecl->setNext(D->getNext());
       }
-      SomeDecl->setNext(D->getNext());
+      
+      // This will have to be revisited for C++: there we want to nest stuff in
+      // namespace decls etc.  Even for C, we might want a top-level translation
+      // unit decl or something.
+      if (!CurFunctionDecl)
+        continue;
+
+      // Chain this decl to the containing function, it now owns the memory for
+      // the decl.
+      D->setNext(CurFunctionDecl->getDeclChain());
+      CurFunctionDecl->setDeclChain(D);
     }
-    
-    // This will have to be revisited for C++: there we want to nest stuff in
-    // namespace decls etc.  Even for C, we might want a top-level translation
-    // unit decl or something.
-    if (!CurFunctionDecl)
-      continue;
-
-    // Chain this decl to the containing function, it now owns the memory for
-    // the decl.
-    D->setNext(CurFunctionDecl->getDeclChain());
-    CurFunctionDecl->setDeclChain(D);
   }
 }
 
@@ -99,10 +102,8 @@
   ScopedDecl *IDecl;
   // Scan up the scope chain looking for a decl that matches this identifier
   // that is in the appropriate namespace.
-  for (IDecl = ClassName->getFETokenInfo<ScopedDecl>(); IDecl; 
-       IDecl = IDecl->getNext())
-    if (IDecl->getIdentifierNamespace() == Decl::IDNS_Ordinary)
-      break;
+  IDecl = LookupScopedDecl(ClassName, Decl::IDNS_Ordinary,
+                           SourceLocation(), TUScope);
   
   if (ObjCCompatibleAliasDecl *ADecl =
       dyn_cast_or_null<ObjCCompatibleAliasDecl>(IDecl))
@@ -118,23 +119,47 @@
 }
 
 /// LookupScopedDecl - Look up the inner-most declaration in the specified
-/// namespace.
+/// identifier namespace.
 ScopedDecl *Sema::LookupScopedDecl(IdentifierInfo *II, unsigned NSI,
                                    SourceLocation IdLoc, Scope *S) {
   if (II == 0) return 0;
-  Decl::IdentifierNamespace NS = (Decl::IdentifierNamespace)NSI;
+  Decl::IdentifierNamespace INS = (Decl::IdentifierNamespace)NSI;
   
-  // 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.
-  for (ScopedDecl *D = II->getFETokenInfo<ScopedDecl>(); D; D = D->getNext())
-    if (D->getIdentifierNamespace() == NS)
-      return D;
-  
+  IdentifierTag &ITag = getIdentifierTag(II);
+
+  if (S->isLocalScope()) {
+    // Scan up the local 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.
+    for (ScopedDecl *D = ITag.LocalDecl; D; D = D->getNext())
+      if (D->getIdentifierNamespace() & INS)
+        return D;
+  }
+
+  // We didn't find it in a local scope. This is either in a namespace scope,
+  // or in the translation unit scope.
+  Scope *NS = S->getNamespaceParent();
+  if (!NS)
+    NS = TUScope;
+
+  // Go through the scope chain and for each scope, check if it's cached for 
+  // this identifier.
+  for (; NS; NS = NS->getParent()) {
+    IdentifierTag::ScopedDeclsTy::iterator it = 
+        ITag.ScopedDecls.find(NS);
+    if (it != ITag.ScopedDecls.end()) {
+      // Ok, there are declarations with this identifier in this scope.
+      // Go through them looking for the right identifier namespace.
+      for (ScopedDecl *D = it->second; D; D = D->getNext())
+        if (D->getIdentifierNamespace() & INS)
+          return D;
+    }
+  }  
   // 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
   // now, injecting it into translation unit scope, and return it.
-  if (NS == Decl::IDNS_Ordinary) {
+  if (INS == Decl::IDNS_Ordinary) {
     // If this is a builtin on this (or all) targets, create the decl.
     if (unsigned BuiltinID = II->getBuiltinID())
       return LazilyCreateBuiltin(II, BuiltinID, S);
@@ -142,6 +167,35 @@
   return 0;
 }
 
+void Sema::AddDeclInScope(ScopedDecl *D, Scope *S)
+{
+  assert(D && S && "passed null parameter");
+  IdentifierInfo *II = D->getIdentifier();
+  assert(II && "Decl has no name");
+  IdentifierTag &ITag = getIdentifierTag(II);
+
+  ScopedDecl *&PrevDecl =
+    (S->isLocalScope()) ?
+      ITag.LocalDecl
+    :
+      ITag.ScopedDecls.FindAndConstruct(S).second;
+  D->setNext(PrevDecl);
+  PrevDecl = D;
+
+  S->AddDecl(D);
+}
+
+Sema::IdentifierTag &Sema::getIdentifierTag(IdentifierInfo *II) {
+  assert(II && "null parameter passed");
+  IdentifierTag *ITag = II->getFETokenInfo<IdentifierTag>();
+  if (!ITag) {
+    void *Mem = Context.getAllocator().Allocate<IdentifierTag>();
+    ITag = new (Mem) IdentifierTag();
+    II->setFETokenInfo(ITag);
+  }
+  return *ITag;
+}
+
 void Sema::InitBuiltinVaListType()
 {
   if (!Context.getBuiltinVaListType().isNull())
@@ -169,23 +223,7 @@
   FunctionDecl *New = FunctionDecl::Create(Context, SourceLocation(), II, R,
                                            FunctionDecl::Extern, false, 0);
   
-  // Find translation-unit scope to insert this function into.
-  if (Scope *FnS = S->getFnParent())
-    S = FnS->getParent();   // Skip all scopes in a function at once.
-  while (S->getParent())
-    S = S->getParent();
-  S->AddDecl(New);
-  
-  // Add this decl to the end of the identifier info.
-  if (ScopedDecl *LastDecl = II->getFETokenInfo<ScopedDecl>()) {
-    // Scan until we find the last (outermost) decl in the id chain. 
-    while (LastDecl->getNext())
-      LastDecl = LastDecl->getNext();
-    // Insert before (outside) it.
-    LastDecl->setNext(New);
-  } else {
-    II->setFETokenInfo(New);
-  }    
+  AddDeclInScope(New, TUScope);
   return New;
 }
 
@@ -729,7 +767,7 @@
       if (NewTD == 0) return 0;
     }
     New = NewTD;
-    if (S->getParent() == 0) {
+    if (!S->isLocalScope()) {
       // C99 6.7.7p2: If a typedef name specifies a variably modified type
       // then it shall have block scope.
       if (NewTD->getUnderlyingType()->isVariablyModifiedType()) {
@@ -787,7 +825,7 @@
     case DeclSpec::SCS_register:       SC = VarDecl::Register; break;
     case DeclSpec::SCS_private_extern: SC = VarDecl::PrivateExtern; break;
     }    
-    if (S->getParent() == 0) {
+    if (!S->isLocalScope()) {
       // 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) {
@@ -823,11 +861,8 @@
   }
   
   // If this has an identifier, add it to the scope stack.
-  if (II) {
-    New->setNext(II->getFETokenInfo<ScopedDecl>());
-    II->setFETokenInfo(New);
-    S->AddDecl(New);
-  }
+  if (II)
+    AddDeclInScope(New,S);
   // If any semantic error occurred, mark the decl as invalid.
   if (D.getInvalidType() || InvalidDecl)
     New->setInvalidDecl();
@@ -1020,11 +1055,8 @@
     New->setInvalidDecl();
     
   // If this has an identifier, add it to the scope stack.
-  if (II) {
-    New->setNext(II->getFETokenInfo<ScopedDecl>());
-    II->setFETokenInfo(New);
-    FnScope->AddDecl(New);
-  }
+  if (II)
+    AddDeclInScope(New,FnScope);
 
   HandleDeclAttributes(New, PI.AttrList, 0);
   return New;
@@ -1215,43 +1247,56 @@
   
   // If this is a named struct, check to see if there was a previous forward
   // declaration or definition.
-  if (TagDecl *PrevDecl = 
-          dyn_cast_or_null<TagDecl>(LookupScopedDecl(Name, Decl::IDNS_Tag,
+  // Use ScopedDecl instead of TagDecl, because a NamespaceDecl may come up.
+  if (ScopedDecl *PrevDecl = 
+          dyn_cast_or_null<ScopedDecl>(LookupScopedDecl(Name, Decl::IDNS_Tag,
                                                      NameLoc, S))) {
     
-    // 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)) {
-      // Make sure that this wasn't declared as an enum and now used as a struct
-      // or something similar.
-      if (PrevDecl->getKind() != Kind) {
-        Diag(KWLoc, diag::err_use_with_wrong_tag, Name->getName());
-        Diag(PrevDecl->getLocation(), diag::err_previous_use);
-      }
-      
-      // If this is a use or a forward declaration, we're good.
-      if (TK != TK_Definition)
-        return PrevDecl;
+    assert((isa<TagDecl>(PrevDecl) || isa<NamespaceDecl>(PrevDecl)) &&
+            "unexpected Decl type");
 
-      // Diagnose attempts to redefine a tag.
-      if (PrevDecl->isDefinition()) {
-        Diag(NameLoc, diag::err_redefinition, Name->getName());
-        Diag(PrevDecl->getLocation(), diag::err_previous_definition);
-        // If this is a redefinition, recover by making this struct be
-        // anonymous, which will make any later references get the previous
-        // definition.
-        Name = 0;
-      } else {
-        // Okay, this is definition of a previously declared or referenced tag.
-        // Move the location of the decl to be the definition site.
-        PrevDecl->setLocation(NameLoc);
-        return PrevDecl;
+    TagDecl *PrevTagDecl = dyn_cast<TagDecl>(PrevDecl);
+    if (PrevTagDecl) {
+      // 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)) {
+        // Make sure that this wasn't declared as an enum and now used as a struct
+        // or something similar.
+        if (PrevDecl->getKind() != Kind) {
+          Diag(KWLoc, diag::err_use_with_wrong_tag, Name->getName());
+          Diag(PrevDecl->getLocation(), diag::err_previous_use);
+        }
+        
+        // If this is a use or a forward declaration, we're good.
+        if (TK != TK_Definition)
+          return PrevDecl;
+
+        // Diagnose attempts to redefine a tag.
+        if (PrevTagDecl->isDefinition()) {
+          Diag(NameLoc, diag::err_redefinition, Name->getName());
+          Diag(PrevDecl->getLocation(), diag::err_previous_definition);
+          // If this is a redefinition, recover by making this struct be
+          // anonymous, which will make any later references get the previous
+          // definition.
+          Name = 0;
+        } else {
+          // Okay, this is definition of a previously declared or referenced tag.
+          // Move the location of the decl to be the definition site.
+          PrevDecl->setLocation(NameLoc);
+          return PrevDecl;
+        }
       }
+      // If we get here, this is a definition of a new struct type in a nested
+      // scope, e.g. "struct foo; void bar() { struct foo; }", just create a new
+      // type.
+    } else {
+      Diag(NameLoc, diag::err_redefinition_different_kind, Name->getName());
+      Diag(PrevDecl->getLocation(), diag::err_previous_definition);
+      // The tag name clashes with a namespace name, recover by making this
+      // struct be anonymous
+      Name = 0;
     }
-    // If we get here, this is a definition of a new struct type in a nested
-    // scope, e.g. "struct foo; void bar() { struct foo; }", just create a new
-    // type.
   }
   
   // If there is an identifier, use the location of the identifier as the
@@ -1287,9 +1332,7 @@
       S = S->getParent();
     
     // Add it to the decl chain.
-    New->setNext(Name->getFETokenInfo<ScopedDecl>());
-    Name->setFETokenInfo(New);
-    S->AddDecl(New);
+    AddDeclInScope(New,S);
   }
   
   HandleDeclAttributes(New, Attr, 0);
@@ -1594,9 +1637,7 @@
                              LastEnumConst);
   
   // Register this decl in the current scope stack.
-  New->setNext(Id->getFETokenInfo<ScopedDecl>());
-  Id->setFETokenInfo(New);
-  S->AddDecl(New);
+  AddDeclInScope(New,S);
   return New;
 }
 
Index: lib/Sema/SemaDeclCXX.cpp
===================================================================
--- lib/Sema/SemaDeclCXX.cpp	(revision 0)
+++ lib/Sema/SemaDeclCXX.cpp	(revision 0)
@@ -0,0 +1,88 @@
+//===--- SemaDeclCXX.cpp - Semantic Analysis for C++ Declarations ---------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements semantic analysis for C++ declarations.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Sema.h"
+#include "clang/AST/Decl.h"
+#include "clang/Parse/Scope.h"
+using namespace clang;
+
+
+/// ActOnStartNamespaceDef - This is called at the start of a namespace
+/// definition. If the namespace has been already declared, and this is an
+/// extended namespace definition, HeadNamespc will be set to first namespace
+/// decl. If it's declared for the first time, HeadNamespc will be the same
+/// decl that this method returns.
+Sema::DeclTy *Sema::ActOnStartNamespaceDef(Scope *S, SourceLocation IdentLoc,
+                                           IdentifierInfo *II,
+                                           SourceLocation LBrace,
+                                           DeclTy *& HeadNamespc) {
+  NamespaceDecl *Namespc = NamespaceDecl::Create(Context, IdentLoc, II);
+  Namespc->setLBracLoc(LBrace);
+
+  if (II) {
+    // See if this is an extended namespace definition or an invalid
+    // redefinition of the symbol.
+    ScopedDecl *PrevDecl = LookupScopedDecl(II, Decl::IDNS_CXXNamespace,
+                                            IdentLoc, S);
+
+    if (PrevDecl && S->isDeclScope(PrevDecl)) {
+      if (NamespaceDecl *HeadNS = dyn_cast<NamespaceDecl>(PrevDecl)) {
+        // We have an extended namespace definition.
+        Namespc->setHeadNamespace(HeadNS);
+
+        // Attach this namespace decl to the chain of extended namespace
+        // definitions.
+        NamespaceDecl *NextNS = HeadNS;
+        for (; NextNS->getNextNamespace(); NextNS = NextNS->getNextNamespace())
+          ;
+        NextNS->setNextNamespace(Namespc);
+
+        // We won't add this decl to the current scope. We want the namespace
+        // name to get the first namespace declaration during a name lookup.
+      } else {
+        Diag(Namespc->getLocation(), diag::err_redefinition_different_kind,
+          Namespc->getName());
+        Diag(PrevDecl->getLocation(), diag::err_previous_definition);
+        Namespc->isInvalidDecl();
+        return Namespc;
+      }
+    } else {
+      // This namespace is declared for the first time.
+      AddDeclInScope(Namespc,S);
+    }
+  }
+  else {
+    // FIXME: Handle anonymous namespaces
+  }
+
+  HeadNamespc = Namespc->getHeadNamespace();
+  return Namespc;
+}
+
+/// ActOnFinishNamespaceDef - This callback is called after a namespace is
+/// exited. Decl is the DeclTy returned by ActOnStartNamespaceDef.
+void Sema::ActOnFinishNamespaceDef(DeclTy *D, SourceLocation RBrace) {
+  Decl *Dcl = static_cast<Decl *>(D);
+  NamespaceDecl *Namespc = dyn_cast_or_null<NamespaceDecl>(Dcl);
+  assert(Namespc && "Invalid parameter, expected NamespaceDecl");
+  Namespc->setRBracLoc(RBrace);
+}
+
+void Sema::ActOnParsedDeclarationForNamespace(DeclTy *D, DeclTy* NS) {
+  Decl *Dcl = static_cast<Decl *>(D);
+  Decl *NSDcl = static_cast<Decl *>(NS);
+  ScopedDecl *SD = dyn_cast_or_null<ScopedDecl>(Dcl);
+  NamespaceDecl *Namespc = dyn_cast_or_null<NamespaceDecl>(NSDcl);
+  assert(SD && Namespc && "Invalid parameters");
+  Namespc->push_back(SD);
+}
Index: lib/Sema/SemaDeclObjC.cpp
===================================================================
--- lib/Sema/SemaDeclObjC.cpp	(revision 48945)
+++ lib/Sema/SemaDeclObjC.cpp	(working copy)
@@ -102,11 +102,7 @@
                                       ClassName);
   
     // Chain & install the interface decl into the identifier.
-    IDecl->setNext(ClassName->getFETokenInfo<ScopedDecl>());
-    ClassName->setFETokenInfo(IDecl);
-    
-    // Remember that this needs to be removed when the scope is popped.
-    TUScope->AddDecl(IDecl);
+    AddDeclInScope(IDecl, TUScope);
   }
   
   if (SuperName) {
@@ -188,8 +184,7 @@
                                     AliasName, CDecl);
     
   // Chain & install the interface decl into the identifier.
-  AliasDecl->setNext(AliasName->getFETokenInfo<ScopedDecl>());
-  AliasName->setFETokenInfo(AliasDecl);
+  AddDeclInScope(AliasDecl, TUScope);
   return AliasDecl;
 }
 
@@ -391,13 +386,10 @@
     // Build, chain & install the interface decl into the identifier.
     IDecl = ObjCInterfaceDecl::Create(Context, AtClassImplLoc, 0, ClassName, 
                                       false, true);
-    IDecl->setNext(ClassName->getFETokenInfo<ScopedDecl>());
-    ClassName->setFETokenInfo(IDecl);
     IDecl->setSuperClass(SDecl);
     IDecl->setLocEnd(ClassLoc);
-    
-    // Remember that this needs to be removed when the scope is popped.
-    TUScope->AddDecl(IDecl);
+
+    AddDeclInScope(IDecl, TUScope);
   }
   
   ObjCImplementationDecl* IMPDecl = 
@@ -601,11 +593,7 @@
       IDecl = ObjCInterfaceDecl::Create(Context, AtClassLoc, 0, IdentList[i],
                                         true);
       // Chain & install the interface decl into the identifier.
-      IDecl->setNext(IdentList[i]->getFETokenInfo<ScopedDecl>());
-      IdentList[i]->setFETokenInfo(IDecl);
-
-      // Remember that this needs to be removed when the scope is popped.
-      TUScope->AddDecl(IDecl);
+      AddDeclInScope(IDecl, TUScope);
     }
 
     Interfaces.push_back(IDecl);
Index: lib/Sema/SemaExpr.cpp
===================================================================
--- lib/Sema/SemaExpr.cpp	(revision 48945)
+++ lib/Sema/SemaExpr.cpp	(working copy)
@@ -113,6 +113,8 @@
     return Diag(Loc, diag::err_unexpected_typedef, II.getName());
   if (isa<ObjCInterfaceDecl>(D))
     return Diag(Loc, diag::err_unexpected_interface, II.getName());
+  if (isa<NamespaceDecl>(D))
+    return Diag(Loc, diag::err_unexpected_namespace, II.getName());
 
   assert(0 && "Invalid decl");
   abort();
@@ -2284,3 +2286,4 @@
   return isInvalid;
 }
 
+
Index: test/Parser/cxx-namespace.cpp
===================================================================
--- test/Parser/cxx-namespace.cpp	(revision 0)
+++ test/Parser/cxx-namespace.cpp	(revision 0)
@@ -0,0 +1,35 @@
+// RUN: clang -fsyntax-only -pedantic-errors -verify %s
+
+namespace A {
+  int a;
+
+  namespace B {
+    void fb();
+  }
+}
+
+char *tu;
+
+namespace A {
+  namespace B {
+    void fb() {
+      a = 0;
+    }
+    namespace C {
+      void fc1() {
+        tu = a; // expected-error {{error: incompatible integer to pointer conversion assigning 'int', expected 'char *'}}
+      }
+    }
+    int tu;
+  }
+}
+
+namespace A {
+  namespace B {
+    namespace C {
+      void fc2() {
+        tu = a;
+      }
+    }
+  }
+}
