Index: test/Parser/cxx-typeid.cpp
===================================================================
--- test/Parser/cxx-typeid.cpp	(revision 0)
+++ test/Parser/cxx-typeid.cpp	(revision 0)
@@ -0,0 +1,13 @@
+// RUN: clang -fsyntax-only -verify %s
+
+// FIXME: This should really include <typeinfo>, but we don't have that yet.
+namespace std {
+  class type_info;
+}
+
+void f()
+{
+  (void)typeid(int);
+  (void)typeid(0);
+  (void)typeid 1; // expected-error {{error: expected '(' after 'typeid'}}
+}
Index: test/SemaCXX/typeid.cpp
===================================================================
--- test/SemaCXX/typeid.cpp	(revision 0)
+++ test/SemaCXX/typeid.cpp	(revision 0)
@@ -0,0 +1,16 @@
+// RUN: clang -fsyntax-only -verify %s
+
+void f()
+{
+  (void)typeid(int); // expected-error {{error: you need to include <typeinfo> before using the 'typeid' operator}}
+}
+
+// FIXME: This should really include <typeinfo>, but we don't have that yet.
+namespace std {
+  class type_info;
+}
+
+void g()
+{
+  (void)typeid(int);
+}
Index: include/clang/Basic/DiagnosticKinds.def
===================================================================
--- include/clang/Basic/DiagnosticKinds.def	(revision 59005)
+++ include/clang/Basic/DiagnosticKinds.def	(working copy)
@@ -1157,6 +1157,10 @@
 DIAG(err_static_downcast_via_virtual, ERROR,
      "cannot cast '%0' to '%1' via virtual base '%2'")
 
+// Other C++ expressions
+DIAG(err_need_header_before_typeid, ERROR,
+     "you need to include <typeinfo> before using the 'typeid' operator")
+
 DIAG(err_invalid_use_of_function_type, ERROR,
      "a function type is not allowed here")
 DIAG(err_invalid_use_of_array_type, ERROR,
Index: include/clang/AST/ExprCXX.h
===================================================================
--- include/clang/AST/ExprCXX.h	(revision 59005)
+++ include/clang/AST/ExprCXX.h	(working copy)
@@ -154,6 +154,47 @@
   virtual child_iterator child_end();
 };
 
+/// CXXTypeidExpr - A C++ @c typeid expression (C++ [expr.typeid]), which gets
+/// the type_info that corresponds to the supplied type, or the (possibly
+/// dynamic) type of the supplied expression.
+///
+/// This represents code like @c typeid(int) or @c typeid(*objPtr)
+class CXXTypeidExpr : public Expr {
+private:
+  bool isTypeOp : 1;
+  void *Operand;
+  SourceRange Range;
+
+public:
+  CXXTypeidExpr(bool isTypeOp, void *op, QualType Ty, const SourceRange r) :
+    Expr(CXXTypeidExprClass, Ty), isTypeOp(isTypeOp), Operand(op), Range(r) {}
+
+  bool isTypeOperand() const { return isTypeOp; }
+  QualType getTypeOperand() const {
+    assert(isTypeOperand() && "Cannot call getTypeOperand for typeid(expr)");
+    return QualType::getFromOpaquePtr(Operand);
+  }
+  Expr* getExprOperand() const {
+    assert(!isTypeOperand() && "Cannot call getExprOperand for typeid(type)");
+    return static_cast<Expr*>(Operand);
+  }
+
+  virtual SourceRange getSourceRange() const {
+    return Range;
+  }
+  static bool classof(const Stmt *T) {
+    return T->getStmtClass() == CXXTypeidExprClass;
+  }
+  static bool classof(const CXXTypeidExpr *) { return true; }
+
+  // Iterators
+  virtual child_iterator child_begin();
+  virtual child_iterator child_end();
+
+  virtual void EmitImpl(llvm::Serializer& S) const;
+  static CXXTypeidExpr* CreateImpl(llvm::Deserializer& D, ASTContext& C);
+};
+
 /// CXXThisExpr - Represents the "this" expression in C++, which is a
 /// pointer to the object on which the current member function is
 /// executing (C++ [expr.prim]p3). Example:
Index: include/clang/AST/StmtNodes.def
===================================================================
--- include/clang/AST/StmtNodes.def	(revision 59005)
+++ include/clang/AST/StmtNodes.def	(working copy)
@@ -96,12 +96,13 @@
 STMT(63, CXXReinterpretCastExpr , CXXNamedCastExpr)
 STMT(64, CXXConstCastExpr       , CXXNamedCastExpr)
 STMT(65, CXXFunctionalCastExpr  , Expr)
-STMT(66, CXXBoolLiteralExpr     , Expr)
-STMT(67, CXXThisExpr            , Expr)
-STMT(68, CXXThrowExpr           , Expr)
-STMT(69, CXXDefaultArgExpr      , Expr)
-STMT(70, CXXZeroInitValueExpr   , Expr)
-STMT(71, CXXConditionDeclExpr   , DeclRefExpr)
+STMT(66, CXXTypeidExpr          , Expr)
+STMT(67, CXXBoolLiteralExpr     , Expr)
+STMT(68, CXXThisExpr            , Expr)
+STMT(69, CXXThrowExpr           , Expr)
+STMT(70, CXXDefaultArgExpr      , Expr)
+STMT(71, CXXZeroInitValueExpr   , Expr)
+STMT(72, CXXConditionDeclExpr   , DeclRefExpr)
 
 // Obj-C Expressions.
 STMT(80, ObjCStringLiteral    , Expr)
Index: include/clang/Parse/Parser.h
===================================================================
--- include/clang/Parse/Parser.h	(revision 59005)
+++ include/clang/Parse/Parser.h	(working copy)
@@ -505,6 +505,10 @@
   ExprResult ParseCXXCasts();
 
   //===--------------------------------------------------------------------===//
+  // C++ 5.2p1: C++ Type Identification
+  ExprResult ParseCXXTypeid();
+
+  //===--------------------------------------------------------------------===//
   // C++ 9.3.2: C++ 'this' pointer
   ExprResult ParseCXXThis();
 
Index: include/clang/Parse/Action.h
===================================================================
--- include/clang/Parse/Action.h	(revision 59005)
+++ include/clang/Parse/Action.h	(working copy)
@@ -676,6 +676,13 @@
     return 0;
   }
 
+  /// ActOnCXXTypeidOfType - Parse typeid( type-id ).
+  virtual ExprResult ActOnCXXTypeid(SourceLocation OpLoc,
+                                    SourceLocation LParenLoc, bool isType,
+                                    void *TyOrExpr, SourceLocation RParenLoc) {
+    return 0;
+  }
+
   /// ActOnCXXThis - Parse the C++ 'this' pointer.
   virtual ExprResult ActOnCXXThis(SourceLocation ThisLoc) {
     return 0;
Index: www/cxx_status.html
===================================================================
--- www/cxx_status.html	(revision 59005)
+++ www/cxx_status.html	(working copy)
@@ -466,11 +466,11 @@
 </tr>
 <tr>
   <td>&nbsp;&nbsp;&nbsp;&nbsp;5.2.8 [expr.typeid]</td>
+  <td class="complete" align="center">&#x2713;</td>  
+  <td class="complete" align="center">&#x2713;</td>  
+  <td class="complete" align="center">&#x2713;</td>  
   <td></td>
   <td></td>
-  <td></td>
-  <td></td>
-  <td></td>
 </tr>
 <tr>
   <td>&nbsp;&nbsp;&nbsp;&nbsp;5.2.9 [expr.static.cast]</td>
Index: lib/Sema/IdentifierResolver.cpp
===================================================================
--- lib/Sema/IdentifierResolver.cpp	(revision 59005)
+++ lib/Sema/IdentifierResolver.cpp	(working copy)
@@ -243,7 +243,7 @@
 /// declaration context 'Ctx'. If 'LookInParentCtx' is true, it will walk the
 /// decls of parent declaration contexts too.
 IdentifierResolver::iterator
-IdentifierResolver::begin(const IdentifierInfo *II, DeclContext *Ctx,
+IdentifierResolver::begin(const IdentifierInfo *II, const DeclContext *Ctx,
                           bool LookInParentCtx) {
   assert(Ctx && "null param passed");
 
Index: lib/Sema/SemaExprCXX.cpp
===================================================================
--- lib/Sema/SemaExprCXX.cpp	(revision 59005)
+++ lib/Sema/SemaExprCXX.cpp	(working copy)
@@ -19,6 +19,34 @@
 #include "clang/Basic/Diagnostic.h"
 using namespace clang;
 
+
+/// ActOnCXXTypeidOfType - Parse typeid( type-id ).
+Action::ExprResult
+Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc,
+                     bool isType, void *TyOrExpr, SourceLocation RParenLoc) {
+  const NamespaceDecl *StdNs = GetStdNamespace();
+  if (!StdNs) {
+    Diag(OpLoc, diag::err_need_header_before_typeid);
+    return ExprResult(true);
+  }
+  if (!Ident_TypeInfo) {
+    Ident_TypeInfo = &PP.getIdentifierTable().get("type_info");
+  }
+  Decl *TypeInfoDecl = LookupDecl(Ident_TypeInfo,
+                                  Decl::IDNS_Tag | Decl::IDNS_Ordinary,
+                                  0, StdNs, /*createBuiltins=*/false);
+  RecordDecl *TypeInfoRecordDecl = dyn_cast_or_null<RecordDecl>(TypeInfoDecl);
+  if (!TypeInfoRecordDecl) {
+    Diag(OpLoc, diag::err_need_header_before_typeid);
+    return ExprResult(true);
+  }
+
+  QualType TypeInfoType = Context.getTypeDeclType(TypeInfoRecordDecl);
+
+  return new CXXTypeidExpr(isType, TyOrExpr, TypeInfoType.withConst(),
+                           SourceRange(OpLoc, RParenLoc));
+}
+
 /// ActOnCXXBoolLiteral - Parse {true,false} literals.
 Action::ExprResult
 Sema::ActOnCXXBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind) {
Index: lib/Sema/IdentifierResolver.h
===================================================================
--- lib/Sema/IdentifierResolver.h	(revision 59005)
+++ lib/Sema/IdentifierResolver.h	(working copy)
@@ -31,7 +31,7 @@
   /// ScopedDecls, LookupContext can be used with all decls (assumes
   /// translation unit context for non ScopedDecls).
   class LookupContext {
-    DeclContext *Ctx;
+    const DeclContext *Ctx;
 
     /// TUCtx - Provides a common value for translation unit context for all
     /// decls.
@@ -49,7 +49,7 @@
     LookupContext(Decl *D) {
       Ctx = getContext(D);
     }
-    LookupContext(DeclContext *DC) {
+    LookupContext(const DeclContext *DC) {
       if (!DC || isa<TranslationUnitDecl>(DC))
         Ctx = TUCtx();
       else
@@ -196,7 +196,7 @@
   /// declaration context 'Ctx'. If 'LookInParentCtx' is true, it will walk the
   /// decls of parent declaration contexts too.
   /// Default for 'LookInParentCtx is true.
-  static iterator begin(const IdentifierInfo *II, DeclContext *Ctx,
+  static iterator begin(const IdentifierInfo *II, const DeclContext *Ctx,
                         bool LookInParentCtx = true);
 
   /// end - Returns an iterator that has 'finished'.
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp	(revision 59005)
+++ lib/Sema/SemaDecl.cpp	(working copy)
@@ -193,7 +193,8 @@
 /// LookupDecl - Look up the inner-most declaration in the specified
 /// namespace.
 Decl *Sema::LookupDecl(const IdentifierInfo *II, unsigned NSI, Scope *S,
-                       DeclContext *LookupCtx, bool enableLazyBuiltinCreation) {
+                       const DeclContext *LookupCtx,
+                       bool enableLazyBuiltinCreation) {
   if (II == 0) return 0;
   unsigned NS = NSI;
   if (getLangOptions().CPlusPlus && (NS & Decl::IDNS_Ordinary))
@@ -278,6 +279,18 @@
   return New;
 }
 
+/// GetStdNamespace - This method gets the C++ "std" namespace. This is where
+/// everything from the standard library is defined.
+NamespaceDecl *Sema::GetStdNamespace() {
+  if (!StdNamespace) {
+    DeclContext *Global = Context.getTranslationUnitDecl();
+    Decl *Std = LookupDecl(Ident_StdNs, Decl::IDNS_Tag | Decl::IDNS_Ordinary,
+                           0, Global, /*enableLazyBuiltinCreation=*/false);
+    StdNamespace = dyn_cast_or_null<NamespaceDecl>(Std);
+  }
+  return StdNamespace;
+}
+
 /// MergeTypeDefDecl - We just parsed a typedef 'New' which has the same name
 /// and scope as a previous declaration 'Old'.  Figure out how to resolve this
 /// situation, merging decls or emitting diagnostics as appropriate.
Index: lib/Sema/Sema.cpp
===================================================================
--- lib/Sema/Sema.cpp	(revision 59005)
+++ lib/Sema/Sema.cpp	(working copy)
@@ -113,6 +113,10 @@
   Ident_SEL = &IT.get("SEL");
   Ident_Protocol = &IT.get("Protocol");
 
+  Ident_StdNs = &IT.get("std");
+  Ident_TypeInfo = 0;
+  StdNamespace = 0;
+
   TUScope = 0;
   if (getLangOptions().CPlusPlus)
     FieldCollector.reset(new CXXFieldCollector());
Index: lib/Sema/Sema.h
===================================================================
--- lib/Sema/Sema.h	(revision 59005)
+++ lib/Sema/Sema.h	(working copy)
@@ -199,10 +199,18 @@
   IdentifierInfo *Ident_id, *Ident_Class;     // "id", "Class"
   IdentifierInfo *Ident_SEL, *Ident_Protocol; // "SEL", "Protocol"
 
+  /// Identifiers used by the C++ language
+  IdentifierInfo *Ident_StdNs; // "std"
+  IdentifierInfo *Ident_TypeInfo; // "type_info" - lazily created
+
   /// Translation Unit Scope - useful to Objective-C actions that need
   /// to lookup file scope declarations in the "ordinary" C decl namespace.
   /// For example, user-defined classes, built-in "id" type, etc.
   Scope *TUScope;
+
+  /// The C++ "std" namespace, where the standard library resides. Cached here
+  /// by GetStdNamespace
+  NamespaceDecl *StdNamespace;
   
   /// ObjCMethodList - a linked list of methods with different signatures.
   struct ObjCMethodList {
@@ -450,7 +458,7 @@
 
   /// More parsing and symbol table subroutines...
   Decl *LookupDecl(const IdentifierInfo *II, unsigned NSI, Scope *S,
-                   DeclContext *LookupCtx = 0,
+                   const DeclContext *LookupCtx = 0,
                    bool enableLazyBuiltinCreation = true);
   ObjCInterfaceDecl *getObjCInterfaceDecl(IdentifierInfo *Id);
   ScopedDecl *LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID, 
@@ -463,6 +471,8 @@
 
   void WarnUndefinedMethod(SourceLocation ImpLoc, ObjCMethodDecl *method,
                            bool &IncompleteImpl);
+
+  NamespaceDecl *GetStdNamespace();
                            
   /// CheckProtocolMethodDefs - This routine checks unimpletented
   /// methods declared in protocol, and those referenced by it.
@@ -751,6 +761,11 @@
                                        SourceLocation LParenLoc, ExprTy *E,
                                        SourceLocation RParenLoc);
 
+  /// ActOnCXXTypeidOfType - Parse typeid( type-id ).
+  virtual ExprResult ActOnCXXTypeid(SourceLocation OpLoc,
+                                    SourceLocation LParenLoc, bool isType,
+                                    void *TyOrExpr, SourceLocation RParenLoc);
+
   //// ActOnCXXThis -  Parse 'this' pointer.
   virtual ExprResult ActOnCXXThis(SourceLocation ThisLoc);
 
Index: lib/AST/ExprCXX.cpp
===================================================================
--- lib/AST/ExprCXX.cpp	(revision 59005)
+++ lib/AST/ExprCXX.cpp	(working copy)
@@ -24,6 +24,13 @@
 //  Child Iterators for iterating over subexpressions/substatements
 //===----------------------------------------------------------------------===//
 
+// CXXTypeidExpr - has child iterators if the operand is an expression
+Stmt::child_iterator CXXTypeidExpr::child_begin() {
+  return isTypeOperand() ? child_iterator() : (Stmt**)&Operand;
+}
+Stmt::child_iterator CXXTypeidExpr::child_end() {
+  return isTypeOperand() ? child_iterator() : (Stmt**)&Operand+1;
+}
 
 // CXXBoolLiteralExpr
 Stmt::child_iterator CXXBoolLiteralExpr::child_begin() { 
Index: lib/AST/Expr.cpp
===================================================================
--- lib/AST/Expr.cpp	(revision 59005)
+++ lib/AST/Expr.cpp	(working copy)
@@ -437,6 +437,9 @@
     if (cast<ExplicitCastExpr>(this)->getTypeAsWritten()->isReferenceType())
       return LV_Valid;
     break;
+  case CXXTypeidExprClass:
+    // C++ 5.2.8p1: The result of a typeid expression is an lvalue of ...
+    return LV_Valid;
   case CXXThisExprClass:
     return LV_InvalidExpression;
   default:
Index: lib/AST/StmtSerialization.cpp
===================================================================
--- lib/AST/StmtSerialization.cpp	(revision 59005)
+++ lib/AST/StmtSerialization.cpp	(working copy)
@@ -216,6 +216,9 @@
     case CXXConstCastExprClass:
       return CXXConstCastExpr::CreateImpl(D, C, SC);
 
+    case CXXTypeidExprClass:
+      return CXXTypeidExpr::CreateImpl(D, C);
+
     case CXXThisExprClass:
       return CXXThisExpr::CreateImpl(D, C);
 
@@ -1346,6 +1349,31 @@
   }
 }
 
+void CXXTypeidExpr::EmitImpl(llvm::Serializer& S) const {
+  S.Emit(getType());
+  S.Emit(isTypeOperand());
+  if (isTypeOperand()) {
+    S.Emit(getTypeOperand());
+  } else {
+    S.EmitOwnedPtr(getExprOperand());
+  }
+  S.Emit(Range);
+}
+
+CXXTypeidExpr*
+CXXTypeidExpr::CreateImpl(llvm::Deserializer& D, ASTContext& C) {
+  QualType Ty = QualType::ReadVal(D);
+  bool isTypeOp = D.ReadBool();
+  void *Operand;
+  if (isTypeOp) {
+    Operand = QualType::ReadVal(D).getAsOpaquePtr();
+  } else {
+    Operand = D.ReadOwnedPtr<Expr>(C);
+  }
+  SourceRange Range = SourceRange::ReadVal(D);
+  return new CXXTypeidExpr(isTypeOp, Operand, Ty, Range);
+}
+
 void CXXThisExpr::EmitImpl(llvm::Serializer& S) const {
   S.Emit(getType());
   S.Emit(Loc);
Index: lib/AST/StmtPrinter.cpp
===================================================================
--- lib/AST/StmtPrinter.cpp	(revision 59005)
+++ lib/AST/StmtPrinter.cpp	(working copy)
@@ -832,6 +832,16 @@
   VisitCXXNamedCastExpr(Node);
 }
 
+void StmtPrinter::VisitCXXTypeidExpr(CXXTypeidExpr *Node) {
+  OS << "typeid(";
+  if (Node->isTypeOperand()) {
+    OS << Node->getTypeOperand().getAsString();
+  } else {
+    PrintExpr(Node->getExprOperand());
+  }
+  OS << ")";
+}
+
 void StmtPrinter::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *Node) {
   OS << (Node->getValue() ? "true" : "false");
 }
Index: lib/Parse/ParseExpr.cpp
===================================================================
--- lib/Parse/ParseExpr.cpp	(revision 59005)
+++ lib/Parse/ParseExpr.cpp	(working copy)
@@ -357,7 +357,7 @@
 ///
 ///       primary-expression: [C99 6.5.1]
 /// [C99]   identifier
-//  [C++]   id-expression
+/// [C++]   id-expression
 ///         constant
 ///         string-literal
 /// [C++]   boolean-literal  [C++ 2.13.5]
@@ -382,6 +382,8 @@
 /// [C++]   'dynamic_cast' '<' type-name '>' '(' expression ')'     [C++ 5.2p1]
 /// [C++]   'reinterpret_cast' '<' type-name '>' '(' expression ')' [C++ 5.2p1]
 /// [C++]   'static_cast' '<' type-name '>' '(' expression ')'      [C++ 5.2p1]
+/// [C++]   'typeid' '(' expression ')'                             [C++ 5.2p1]
+/// [C++]   'typeid' '(' type-id ')'                                [C++ 5.2p1]
 /// [C++]   'this'          [C++ 9.3.2]
 /// [clang] '^' block-literal
 ///
@@ -567,6 +569,10 @@
     Res = ParseCXXCasts();
     // These can be followed by postfix-expr pieces.
     return ParsePostfixExpressionSuffix(Res);
+  case tok::kw_typeid:
+    Res = ParseCXXTypeid();
+    // This can be followed by postfix-expr pieces.
+    return ParsePostfixExpressionSuffix(Res);
   case tok::kw_this:
     Res = ParseCXXThis();
     // This can be followed by postfix-expr pieces.
Index: lib/Parse/ParseExprCXX.cpp
===================================================================
--- lib/Parse/ParseExprCXX.cpp	(revision 59005)
+++ lib/Parse/ParseExprCXX.cpp	(working copy)
@@ -216,6 +216,54 @@
   return Result;
 }
 
+/// ParseCXXTypeid - This handles the C++ typeid expression.
+///
+///       postfix-expression: [C++ 5.2p1]
+///         'typeid' '(' expression ')'
+///         'typeid' '(' type-id ')'
+///
+Parser::ExprResult Parser::ParseCXXTypeid() {
+  assert(Tok.is(tok::kw_typeid) && "Not 'typeid'!");
+
+  SourceLocation OpLoc = ConsumeToken();
+  SourceLocation LParenLoc = Tok.getLocation();
+  SourceLocation RParenLoc;
+
+  // typeid expressions are always parenthesized.
+  if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
+      "typeid"))
+    return ExprResult(true);
+
+  Parser::ExprResult Result;
+
+  if (isTypeIdInParens()) {
+    TypeTy *Ty = ParseTypeName();
+
+    // Match the ')'.
+    MatchRHSPunctuation(tok::r_paren, LParenLoc);
+
+    if (!Ty)
+      return ExprResult(true);
+
+    Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/true,
+                                    Ty, RParenLoc);
+  } else {
+    Result = ParseExpression();
+
+    // Match the ')'.
+    if (Result.isInvalid)
+      SkipUntil(tok::r_paren);
+    else {
+      MatchRHSPunctuation(tok::r_paren, LParenLoc);
+
+      Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/false,
+                                      Result.Val, RParenLoc);
+    }
+  }
+
+  return Result;
+}
+
 /// ParseCXXBoolLiteral - This handles the C++ Boolean literals.
 ///
 ///       boolean-literal: [C++ 2.13.5]
