Index: test/Parser/cxx-typeid.cpp
===================================================================
--- test/Parser/cxx-typeid.cpp	(revision 0)
+++ test/Parser/cxx-typeid.cpp	(revision 0)
@@ -0,0 +1,8 @@
+// RUN: clang -fsyntax-only -verify %s
+
+void f()
+{
+  (void)typeid(int);
+  (void)typeid(0);
+  (void)typeid 1; // expected-error {{error: expected '(' after 'typeid'}}
+}
Index: include/clang/AST/ExprCXX.h
===================================================================
--- include/clang/AST/ExprCXX.h	(revision 58931)
+++ include/clang/AST/ExprCXX.h	(working copy)
@@ -154,6 +154,48 @@
   virtual child_iterator child_end();
 };
 
+class CXXTypeidExpr : public Expr {
+public:
+  enum OperandKind {
+    OpType,
+    OpExpr
+  };
+
+private:
+  OperandKind OpKind;
+  void *Operand;
+  SourceRange Range;
+
+public:
+  CXXTypeidExpr(OperandKind kind, void *op, QualType Ty, const SourceRange r) :
+    Expr(CXXTypeidExprClass, Ty), OpKind(kind), Operand(op), Range(r) {}
+
+  OperandKind getOperandKind() const { return OpKind; }
+  QualType getTypeOperand() const {
+    assert(OpKind == OpType && "Cannot call getTypeOperand for typeid(expr)");
+    return QualType::getFromOpaquePtr(Operand);
+  }
+  Expr* getExprOperand() const {
+    assert(OpKind == OpExpr && "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 58931)
+++ 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 58931)
+++ include/clang/Parse/Parser.h	(working copy)
@@ -504,6 +504,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 58931)
+++ 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 58932)
+++ 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="basic" align="center"></td>
+  <td class="basic" align="center"></td>
   <td></td>
-  <td></td>
-  <td></td>
-  <td></td>
-  <td></td>
+  <td>Type of typeid expression is 'const void'</td>
 </tr>
 <tr>
   <td>&nbsp;&nbsp;&nbsp;&nbsp;5.2.9 [expr.static.cast]</td>
Index: lib/Sema/SemaExprCXX.cpp
===================================================================
--- lib/Sema/SemaExprCXX.cpp	(revision 58931)
+++ lib/Sema/SemaExprCXX.cpp	(working copy)
@@ -19,6 +19,18 @@
 #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) {
+  // FIXME: Implicitly declare std::type_info if necessary, and use it.
+  return new CXXTypeidExpr(isType ? CXXTypeidExpr::OpType
+                                  : CXXTypeidExpr::OpExpr,
+                           TyOrExpr, Context.VoidTy.withConst(),
+                           SourceRange(OpLoc, RParenLoc));
+}
+
 /// ActOnCXXBoolLiteral - Parse {true,false} literals.
 Action::ExprResult
 Sema::ActOnCXXBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind) {
Index: lib/Sema/Sema.h
===================================================================
--- lib/Sema/Sema.h	(revision 58931)
+++ lib/Sema/Sema.h	(working copy)
@@ -750,6 +750,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 58931)
+++ 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 OpKind == OpExpr ? (Stmt**)&Operand : child_iterator();
+}
+Stmt::child_iterator CXXTypeidExpr::child_end() {
+  return OpKind == OpExpr ? (Stmt**)&Operand+1 : child_iterator();
+}
 
 // CXXBoolLiteralExpr
 Stmt::child_iterator CXXBoolLiteralExpr::child_begin() { 
Index: lib/AST/Expr.cpp
===================================================================
--- lib/AST/Expr.cpp	(revision 58931)
+++ 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 58931)
+++ 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(static_cast<int>(OpKind));
+  if (OpKind == OpType) {
+    S.Emit(getTypeOperand());
+  } else {
+    S.EmitOwnedPtr(getExprOperand());
+  }
+  S.Emit(Range);
+}
+
+CXXTypeidExpr*
+CXXTypeidExpr::CreateImpl(llvm::Deserializer& D, ASTContext& C) {
+  QualType Ty = QualType::ReadVal(D);
+  OperandKind OpKind = static_cast<OperandKind>(OpKind);
+  void *Operand;
+  switch (OpKind) {
+  default: assert(false && "Unknown operand kind!"); break;
+  case OpType: Operand = QualType::ReadVal(D).getAsOpaquePtr(); break;
+  case OpExpr: Operand = D.ReadOwnedPtr<Expr>(C); break;
+  }
+  SourceRange Range = SourceRange::ReadVal(D);
+  return new CXXTypeidExpr(OpKind, 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 58931)
+++ lib/AST/StmtPrinter.cpp	(working copy)
@@ -832,6 +832,16 @@
   VisitCXXNamedCastExpr(Node);
 }
 
+void StmtPrinter::VisitCXXTypeidExpr(CXXTypeidExpr *Node) {
+  OS << "typeid(";
+  if (Node->getOperandKind() == CXXTypeidExpr::OpType) {
+    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 58931)
+++ 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 58931)
+++ lib/Parse/ParseExprCXX.cpp	(working copy)
@@ -216,6 +216,60 @@
   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 ')'.
+    if (Tok.is(tok::r_paren))
+      RParenLoc = ConsumeParen();
+    else
+      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 {
+      if (Tok.is(tok::r_paren))
+        RParenLoc = ConsumeParen();
+      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]
