Implement C++ 'typeid' parsing and sema.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@59042 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index e8758e1..df55bf7 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -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.
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index a1fd565..692e35d 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -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]