Index: include/clang/AST/Decl.h
===================================================================
--- include/clang/AST/Decl.h	(revision 48749)
+++ include/clang/AST/Decl.h	(working copy)
@@ -25,6 +25,7 @@
 }
 
 namespace clang {
+class Scope;
 class Expr;
 class Stmt;
 class StringLiteral;
@@ -52,6 +53,7 @@
            PropertyDecl,
     //     ScopedDecl
              CompatibleAlias,
+             Namespace,
     //       TypeDecl
                ObjCInterface,
                Typedef,
@@ -88,11 +90,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 +172,8 @@
     case Class:
     case Enum:
       return IDNS_Tag;
+    case Namespace:
+      return IDNS_CXXNamespace;
     }
   }
   // global temp stats (until we have a per-module visitor)
@@ -232,13 +238,21 @@
   ///
   ScopedDecl *Next;
 
+  /// The Scope where the ScopedDecl is declared. If it's in a namespace,
+  /// the namespace name can be retrieved from this.
+  Scope *ParentScope;
+
 protected:
   ScopedDecl(Kind DK, SourceLocation L, IdentifierInfo *Id,ScopedDecl *PrevDecl)
-    : NamedDecl(DK, L, Id), NextDeclarator(PrevDecl), Next(0) {}
+    : NamedDecl(DK, L, Id), NextDeclarator(PrevDecl), Next(0), ParentScope(0) {}
   
 public:
   ScopedDecl *getNext() const { return Next; }
   void setNext(ScopedDecl *N) { Next = N; }
+
+  Scope *getParentScope() { return ParentScope; }
+  void setParentScope(Scope *S) { ParentScope = S; }
+
   
   /// getNextDeclarator - If this decl was part of a multi-declarator
   /// declaration, such as "int X, Y, *Z;" this returns the decl for the next
@@ -287,6 +301,70 @@
   void ReadInRec(llvm::Deserializer& D);
 };
 
+/// NamespaceDecl - Represent a C++ namespace.
+class NamespaceDecl : public ScopedDecl {
+  llvm::SmallVector<ScopedDecl *, 16> Decls;
+  SourceLocation LBracLoc, RBracLoc;
+
+  // The Scope that is associated with this namespace
+  Scope *NSScope;
+
+  NamespaceDecl(SourceLocation L, IdentifierInfo *Id)
+    : ScopedDecl(Namespace, L, Id, 0), NSScope(0) {}
+public:
+  static NamespaceDecl *Create(ASTContext &C, SourceLocation L,
+                               IdentifierInfo *Id);
+  ~NamespaceDecl();
+
+  Scope *getNamespaceScope() { return NSScope; }
+  /// This transfers ownership of the Scope to the decl.
+  void setNamespaceScope(Scope *NSS);
+
+  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 48749)
+++ include/clang/Basic/DiagnosticKinds.def	(working copy)
@@ -347,6 +347,10 @@
      "expected method body")
 DIAG(err_expected_after_declarator, ERROR,
      "expected '=', ',', ';', 'asm', or '__attribute__' after declarator")
+DIAG(err_expected_after_coloncolon, ERROR,
+	 "expected unqualified-id after '::' token")
+DIAG(err_non_class_or_namespace, ERROR,
+     "'%0' is not a class or namespace")
 DIAG(err_expected_statement, ERROR,
      "expected statement")
 DIAG(err_expected_lparen_after, ERROR,
@@ -624,6 +628,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 48749)
+++ 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,27 @@
     return Group;
   }
 
+  /// ActOnEnterNamespace - This is called at the start of a namespace
+  /// declaration. If the namespace has been already declared, NamespcScope will
+  /// be set to the Scope of the previous declaration.
+  virtual DeclTy *ActOnEnterNamespace(Scope *S, SourceLocation IdentLoc,
+                                        IdentifierInfo *Ident,
+                                        SourceLocation LBrace,
+                                        Scope *& NamespcScope) {
+    return 0;
+  }
+
+  virtual void ActOnParsedDeclarationForNamespace(DeclTy *Dcl,
+                                                  DeclTy* Namespc) {
+    return;
+  }
+
+  /// ActOnExitNamespace - This callback is called immediately before the
+  /// specified namespace is exited.
+  virtual void ActOnExitNamespace(Scope *S, 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 +751,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 48749)
+++ include/clang/Parse/Parser.h	(working copy)
@@ -16,6 +16,7 @@
 
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Parse/Action.h"
+#include <stack>
 
 namespace clang {
   class DeclSpec;
@@ -49,6 +50,7 @@
   enum { ScopeCacheSize = 16 };
   unsigned NumCachedScopes;
   Scope *ScopeCache[ScopeCacheSize];
+  std::stack<Scope*> ScopeStack;
 public:
   Parser(Preprocessor &PP, Action &Actions);
   ~Parser();
@@ -228,7 +230,11 @@
   // Scope manipulation
   
   /// EnterScope - Start a new scope.
-  void EnterScope(unsigned ScopeFlags);
+  void EnterScope(unsigned ScopeFlags, DeclTy *NamedScopeDecl = 0);
+  void EnterScope(Scope *S) {
+    CurScope = S;
+    ScopeStack.push(S);
+  }
   
   /// ExitScope - Pop a scope off the scope stack.
   void ExitScope();
Index: include/clang/Parse/Scope.h
===================================================================
--- include/clang/Parse/Scope.h	(revision 48749)
+++ include/clang/Parse/Scope.h	(working copy)
@@ -42,7 +42,11 @@
     
     /// 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,
+
+    /// NamedScope - This is a scope that can be associated to a NamedDecl.
+    /// Used for C++ namespaces.
+    NamedScope = 0x10
   };
 private:
   /// The parent scope for this scope.  This is null for the translation-unit
@@ -65,6 +69,9 @@
   /// preceeding BreakParent/ContinueParent if this scope is not one, or null if
   /// there is no containing break/continue scope.
   Scope *BreakParent, *ContinueParent;
+
+  Scope *NamedParent;
+  Action::DeclTy *NamedDecl;
   
   /// 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,10 +81,11 @@
   /// implement these semantics.
   typedef llvm::SmallPtrSet<Action::DeclTy*, 32> DeclSetTy;
   DeclSetTy DeclsInScope;
-  
+
 public:
-  Scope(Scope *Parent, unsigned ScopeFlags) {
-    Init(Parent, ScopeFlags);
+  Scope(Scope *Parent, unsigned ScopeFlags,
+        Action::DeclTy *NamedScopeDecl = 0) {
+    Init(Parent, ScopeFlags, NamedScopeDecl);
   }
 
   /// getFlags - Return the flags for this scope.
@@ -103,8 +111,16 @@
   /// would be affected by.
   const Scope *getBreakParent() const { return BreakParent; }
   Scope *getBreakParent() { return BreakParent; }
-  
- 
+
+  const Scope *getNamedParent() const { return NamedParent; }
+  Scope *getNamedParent() { return NamedParent; }
+
+  Action::DeclTy *getNamedDecl() const { return NamedDecl; }
+
+  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(); }
@@ -122,7 +138,12 @@
   
   /// Init - This is used by the parser to implement scope caching.
   ///
-  void Init(Scope *Parent, unsigned ScopeFlags) {
+  void Init(Scope *Parent, unsigned ScopeFlags,
+            Action::DeclTy *NamedScopeDecl = 0) {
+    assert((ScopeFlags & NamedScope) || NamedScopeDecl == 0 &&
+                "Passed NamedDecl for non NamedScope");
+    assert(!(ScopeFlags & NamedScope) || NamedScopeDecl != 0 &&
+                "NamedScope with a null NamedDecl");
     AnyParent = Parent;
     Depth = AnyParent ? AnyParent->Depth+1 : 0;
     Flags = ScopeFlags;
@@ -131,16 +152,21 @@
       FnParent       = AnyParent->FnParent;
       BreakParent    = AnyParent->BreakParent;
       ContinueParent = AnyParent->ContinueParent;
+      NamedParent    = AnyParent->NamedParent;
     } else {
       FnParent = BreakParent = ContinueParent = 0;
+      NamedParent = 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 & NamedScope)    NamedParent = this;
     
     DeclsInScope.clear();
+
+    NamedDecl = NamedScopeDecl;
   }      
 };
     
Index: lib/AST/Decl.cpp
===================================================================
--- lib/AST/Decl.cpp	(revision 48749)
+++ lib/AST/Decl.cpp	(working copy)
@@ -14,6 +14,7 @@
 #include "clang/AST/Decl.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/Attr.h"
+#include "clang/Parse/Scope.h"
 #include "clang/Basic/IdentifierTable.h"
 #include "llvm/ADT/DenseMap.h"
 using namespace clang;
@@ -31,6 +32,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 +177,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 +207,12 @@
 // 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) {
@@ -325,6 +334,22 @@
   return "";
 }
 
+void NamespaceDecl::setNamespaceScope(Scope *NSS) {
+  assert(NSS->getFlags() & Scope::NamedScope &&
+    "Non NamedScope assigned to namespace");
+  NSScope = NSS;
+}
+
+NamespaceDecl::~NamespaceDecl() {
+  if (NSScope) {
+    if (NSScope->getNamedDecl() == this) {
+      // This decl is the owner of the scope. Destroy it.
+      delete NSScope;
+    }
+  }
+}
+
+
 FunctionDecl::~FunctionDecl() {
   delete[] ParamInfo;
 }
Index: lib/Parse/MinimalAction.cpp
===================================================================
--- lib/Parse/MinimalAction.cpp	(revision 48749)
+++ 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 48749)
+++ 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.
-    
+    // NamespcScope will receive the Scope of the namescope if it has been
+    // declared before.
+    Scope *NamespcScope;
+    DeclTy *NamespcDecl =
+      Actions.ActOnEnterNamespace(CurScope, IdentLoc, Ident,
+                                  LBrace, NamespcScope);
+    if (NamespcScope) {
+      // A scope is already created for the namespace during a previous
+      // declaration. Push it on the stack.
+      EnterScope(NamespcScope);
+    }
+    else
+      EnterScope(Scope::NamedScope | Scope::DeclScope, NamespcDecl);
+
     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.ActOnExitNamespace(CurScope, 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/ParseInit.cpp
===================================================================
--- lib/Parse/ParseInit.cpp	(revision 48749)
+++ lib/Parse/ParseInit.cpp	(working copy)
@@ -225,3 +225,4 @@
   return ExprResult(true); // an error occurred.
 }
 
+
Index: lib/Parse/Parser.cpp
===================================================================
--- lib/Parse/Parser.cpp	(revision 48749)
+++ lib/Parse/Parser.cpp	(working copy)
@@ -174,19 +174,30 @@
 //===----------------------------------------------------------------------===//
 
 /// EnterScope - Start a new scope.
-void Parser::EnterScope(unsigned ScopeFlags) {
-  if (NumCachedScopes) {
-    Scope *N = ScopeCache[--NumCachedScopes];
-    N->Init(CurScope, ScopeFlags);
-    CurScope = N;
+void Parser::EnterScope(unsigned ScopeFlags, DeclTy *NamedScopeDecl) {
+  Scope *S;
+  if (ScopeFlags & Scope::NamedScope) {
+    // A NamedDecl will be associated with this scope and will gain ownership.
+    S = new Scope(CurScope, ScopeFlags, NamedScopeDecl);
   } else {
-    CurScope = new Scope(CurScope, ScopeFlags);
+    assert(NamedScopeDecl == 0 && "decl passed for non NamedScope");
+      
+    if (NumCachedScopes) {
+      Scope *N = ScopeCache[--NumCachedScopes];
+      N->Init(CurScope, ScopeFlags);
+      S = N;
+    } else {
+      S = new Scope(CurScope, ScopeFlags);
+    }
   }
+
+  EnterScope(S);
 }
 
 /// ExitScope - Pop a scope off the scope stack.
 void Parser::ExitScope() {
   assert(CurScope && "Scope imbalance!");
+  assert(ScopeStack.size() > 0 && "ScopeStack invalid.");
 
   // Inform the actions module that this scope is going away if there are any
   // decls in it.
@@ -194,12 +205,21 @@
     Actions.ActOnPopScope(Tok.getLocation(), CurScope);
   
   Scope *OldScope = CurScope;
-  CurScope = OldScope->getParent();
-  
-  if (NumCachedScopes == ScopeCacheSize)
-    delete OldScope;
+  ScopeStack.pop();
+  if (ScopeStack.size() == 0)
+    CurScope = 0;
   else
-    ScopeCache[NumCachedScopes++] = OldScope;
+    CurScope = ScopeStack.top();
+
+  if (OldScope->getFlags() & Scope::NamedScope) {
+    // A NamedDecl was associated with this scope and gained ownership.
+    // Don't delete it here.
+  } else {
+    if (NumCachedScopes == ScopeCacheSize)
+      delete OldScope;
+    else
+      ScopeCache[NumCachedScopes++] = OldScope;
+  }
 }
 
 
@@ -644,4 +664,3 @@
   
   return Result;
 }
-
Index: lib/Sema/Sema.cpp
===================================================================
--- lib/Sema/Sema.cpp	(revision 48749)
+++ 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);
 }
 
@@ -129,6 +124,12 @@
   TUScope = 0;
 }
 
+Sema::~Sema() {
+  for (llvm::SmallVector<IdentifierTag*,128>::iterator it = IdentTags.begin();
+       it != IdentTags.end(); ++it)
+    delete *it;
+}
+
 /// ImpCastExprToType - If Expr is not of type 'Type', insert an implicit cast. 
 /// If there is already an implicit cast, merge into the existing one.
 void Sema::ImpCastExprToType(Expr *&Expr, QualType Type) {
Index: lib/Sema/Sema.h
===================================================================
--- lib/Sema/Sema.h	(revision 48749)
+++ lib/Sema/Sema.h	(working copy)
@@ -36,6 +36,7 @@
   class Expr;
   class InitListExpr;
   class CallExpr;
+  class NamespaceDecl;
   class VarDecl;
   class ParmVarDecl;
   class TypedefDecl;
@@ -92,7 +93,28 @@
   /// 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*> ScopedDecls;
+
+    /// Decls - Associate each ScopedDecl that uses the particular identifier
+    /// with the Scope that it was created in. This is used for fast name lookup
+    ScopedDecls Decls;
+
+    /// LocalDecl - When in a local scope, this holds the current declaration
+    /// 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 Decls.
+    ScopedDecl *LocalDecl;
+
+    IdentifierTag()
+      : Decls(ScopedDecls(4)), LocalDecl(0) {}
+  };
+
+  llvm::SmallVector<IdentifierTag*, 128> IdentTags;
+
   // Enum values used by KnownFunctionIDs (see below).
   enum {
     id_printf,
@@ -141,6 +163,7 @@
   llvm::DenseMap<Selector, ObjCMethodList> FactoryMethodPool;
 public:
   Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer);
+  ~Sema();
   
   const LangOptions &getLangOptions() const;
   
@@ -188,7 +211,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);
@@ -239,8 +262,11 @@
   /// More parsing and symbol table subroutines...
   ParmVarDecl *ActOnParamDeclarator(struct DeclaratorChunk::ParamInfo &PI, 
                                     Scope *FnBodyScope);  
+  bool IsDeclInScope(ScopedDecl *D, Scope *S);
   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 +536,15 @@
                                 ExprTy *expr, TypeTy *type,
                                 SourceLocation RPLoc);
   
+  // Act on C++ namespaces
+  virtual DeclTy *ActOnEnterNamespace(Scope *S, SourceLocation IdentLoc,
+                                        IdentifierInfo *Ident,
+                                        SourceLocation LBrace,
+                                        Scope *& NamespcScope);
+  virtual void ActOnExitNamespace(Scope *S, 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 48749)
+++ 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,51 @@
 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!");
+
+  // When not in a local scope (i.e. in a C++ namespace) the scope is cached for
+  // each identifier of its decls using IdentifierTag, so we can find it later
+  // on a name lookup. Unlink the identifiers only on local scope.
+  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 +104,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))
@@ -117,24 +120,57 @@
   return cast_or_null<ObjCInterfaceDecl>(IdDecl);
 }
 
+
+bool Sema::IsDeclInScope(ScopedDecl *D, Scope *S)
+{
+  assert(S && "null Scope passed");
+  if (D)
+    return D->getParentScope() == S;
+  else
+    return false;
+}
+
 /// 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)
+  IdentifierTag &ITag = getIdentifierTag(II);
+
+  // 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 named scope, like
+  // a C++ namespace or in the translation unit scope.
+  Scope *NS = S->getNamedParent();
+  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::ScopedDecls::iterator it = 
+        ITag.Decls.find(NS);
+    if (it != ITag.Decls.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 +178,38 @@
   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");
+
+  // Associate the scope with the identifier of the declaration.
+  IdentifierTag &ITag = getIdentifierTag(II);
+  ScopedDecl *&PrevDecl =
+    (S->isLocalScope()) ?
+      ITag.LocalDecl
+    :
+      ITag.Decls.FindAndConstruct(S).second;
+  D->setNext(PrevDecl);
+  PrevDecl = D;
+
+  S->AddDecl(D);
+  D->setParentScope(S);
+}
+
+Sema::IdentifierTag &Sema::getIdentifierTag(IdentifierInfo *II) {
+  assert(II && "null parameter passed");
+  IdentifierTag *ITag = II->getFETokenInfo<IdentifierTag>();
+  if (!ITag) {
+    ITag = new IdentifierTag();
+    // Store it in IdentTags so it can be deleted when Sema is destroyed.
+    IdentTags.push_back(ITag);
+    II->setFETokenInfo(ITag);
+  }
+  return *ITag;
+}
+
 void Sema::InitBuiltinVaListType()
 {
   if (!Context.getBuiltinVaListType().isNull())
@@ -169,23 +237,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;
 }
 
@@ -723,12 +775,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 && IsDeclInScope(PrevDecl, S)) {
       NewTD = MergeTypeDefDecl(NewTD, PrevDecl);
       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()) {
@@ -786,7 +838,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) {
@@ -819,7 +871,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 && IsDeclInScope(PrevDecl, S)) {
       NewVD = MergeVarDecl(NewVD, PrevDecl);
       if (NewVD == 0) return 0;
     }
@@ -827,11 +879,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();
@@ -1024,11 +1073,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;
@@ -1219,43 +1265,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 || IsDeclInScope(PrevDecl, S)) {
+        // 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
@@ -1291,9 +1350,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);
@@ -1546,7 +1603,7 @@
   // scope.
   if (ScopedDecl *PrevDecl = LookupScopedDecl(Id, Decl::IDNS_Ordinary, 
                                               IdLoc, S)) {
-    if (S->isDeclScope(PrevDecl)) {
+    if (IsDeclInScope(PrevDecl, S)) {
       if (isa<EnumConstantDecl>(PrevDecl))
         Diag(IdLoc, diag::err_redefinition_of_enumerator, Id->getName());
       else
@@ -1598,9 +1655,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,78 @@
+//===--- 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"
+using namespace clang;
+
+
+/// ActOnEnterNamespace - This is called at the start of a namespace
+/// declaration. If the namespace has been already declared, NamespcScope will
+/// be set to the Scope of the previous declaration.
+Sema::DeclTy *Sema::ActOnEnterNamespace(Scope *S, SourceLocation IdentLoc,
+                                        IdentifierInfo *II,
+                                        SourceLocation LBrace,
+                                        Scope *& NamespcScope) {
+  NamespaceDecl *Namespc = NamespaceDecl::Create(Context, IdentLoc, II);
+  Namespc->setLBracLoc(LBrace);
+  NamespcScope = 0;
+
+  if (II) {
+    // See if this is a namespace block that adds declarations to a previous
+    // declared namespace or an invalid redefinition of the symbol.
+    ScopedDecl *PrevDecl = LookupScopedDecl(II, Decl::IDNS_CXXNamespace,
+                                            IdentLoc, S);
+
+    if (IsDeclInScope(PrevDecl, S)) {
+      if (NamespaceDecl *PrevNS = dyn_cast<NamespaceDecl>(PrevDecl)) {
+        NamespcScope = PrevNS->getNamespaceScope();
+        // 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
+  }
+
+  return Namespc;
+}
+
+/// ActOnExitNamespace - This callback is called immediately before the
+/// specified namespace is exited.
+void Sema::ActOnExitNamespace(Scope *S, 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);
+  // This transfers ownership of the scope to the namespace decl.
+  Namespc->setNamespaceScope(S);
+}
+
+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 48749)
+++ 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 48749)
+++ 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;
+      }
+    }
+  }
+}
