From 13a5ecc6ff941c3056f2cf6c86aa2b07c6164d89 Mon Sep 17 00:00:00 2001
From: Chris Lattner <sabre@nondot.org>
Date: Sun, 9 May 2010 06:03:39 +0000
Subject: [PATCH] pch'ify typeid.

llvm-svn: 103374
---
 clang/include/clang/AST/ExprCXX.h          | 23 +++++++++++++++++-----
 clang/include/clang/Frontend/PCHBitCodes.h |  5 +++--
 clang/lib/Frontend/PCHReaderStmt.cpp       | 20 +++++++++++++++++++
 clang/lib/Frontend/PCHWriterStmt.cpp       | 13 ++++++++++++
 clang/test/Makefile                        |  4 ++--
 clang/test/PCH/cxx_exprs.cpp               |  4 ++++
 clang/test/PCH/cxx_exprs.h                 | 13 +++++++++++-
 7 files changed, 72 insertions(+), 10 deletions(-)

diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h
index c11f55b95bd6..e6bc39419eb3 100644
--- a/clang/include/clang/AST/ExprCXX.h
+++ b/clang/include/clang/AST/ExprCXX.h
@@ -321,6 +321,14 @@ public:
         Operand->isTypeDependent() || Operand->isValueDependent()),
       Operand(Operand), Range(R) { }
 
+  CXXTypeidExpr(EmptyShell Empty, bool isExpr)
+    : Expr(CXXTypeidExprClass, Empty) {
+    if (isExpr)
+      Operand = (Expr*)0;
+    else
+      Operand = (TypeSourceInfo*)0;
+  }
+  
   bool isTypeOperand() const { return Operand.is<TypeSourceInfo *>(); }
   
   /// \brief Retrieves the type operand of this typeid() expression after
@@ -332,15 +340,20 @@ public:
     assert(isTypeOperand() && "Cannot call getTypeOperand for typeid(expr)");
     return Operand.get<TypeSourceInfo *>();
   }
+
+  void setTypeOperandSourceInfo(TypeSourceInfo *TSI) {
+    assert(isTypeOperand() && "Cannot call getTypeOperand for typeid(expr)");
+    Operand = TSI;
+  }
   
-  Expr* getExprOperand() const {
+  Expr *getExprOperand() const {
     assert(!isTypeOperand() && "Cannot call getExprOperand for typeid(type)");
     return static_cast<Expr*>(Operand.get<Stmt *>());
   }
-
-  virtual SourceRange getSourceRange() const {
-    return Range;
-  }
+  
+  virtual SourceRange getSourceRange() const { return Range; }
+  void setSourceRange(SourceRange R) { Range = R; }
+  
   static bool classof(const Stmt *T) {
     return T->getStmtClass() == CXXTypeidExprClass;
   }
diff --git a/clang/include/clang/Frontend/PCHBitCodes.h b/clang/include/clang/Frontend/PCHBitCodes.h
index 5d9b02788fd1..575881ad5968 100644
--- a/clang/include/clang/Frontend/PCHBitCodes.h
+++ b/clang/include/clang/Frontend/PCHBitCodes.h
@@ -746,8 +746,9 @@ namespace clang {
       EXPR_CXX_FUNCTIONAL_CAST,
       // \brief A CXXBoolLiteralExpr record.
       EXPR_CXX_BOOL_LITERAL,
-      // \brief A CXXNullPtrLiteralExpr record.
-      EXPR_CXX_NULL_PTR_LITERAL
+      EXPR_CXX_NULL_PTR_LITERAL,  // CXXNullPtrLiteralExpr
+      EXPR_CXX_TYPEID_EXPR,       // CXXTypeidExpr (of expr).
+      EXPR_CXX_TYPEID_TYPE        // CXXTypeidExpr (of type).
     };
 
     /// \brief The kinds of designators that can occur in a
diff --git a/clang/lib/Frontend/PCHReaderStmt.cpp b/clang/lib/Frontend/PCHReaderStmt.cpp
index 394a894e4e4c..cce2e262deee 100644
--- a/clang/lib/Frontend/PCHReaderStmt.cpp
+++ b/clang/lib/Frontend/PCHReaderStmt.cpp
@@ -126,6 +126,7 @@ namespace {
     unsigned VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E);
     unsigned VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E);
     unsigned VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E);
+    unsigned VisitCXXTypeidExpr(CXXTypeidExpr *E);
   };
 }
 
@@ -992,6 +993,19 @@ unsigned PCHStmtReader::VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E) {
   return 0;
 }
 
+unsigned PCHStmtReader::VisitCXXTypeidExpr(CXXTypeidExpr *E) {
+  VisitExpr(E);
+  E->setSourceRange(Reader.ReadSourceRange(Record, Idx));
+  if (E->isTypeOperand()) { // typeid(int)
+    E->setTypeOperandSourceInfo(Reader.GetTypeSourceInfo(Record, Idx));
+    return 0;
+  }
+  
+  // typeid(42+2)
+  return 1;
+}
+
+
 // Within the bitstream, expressions are stored in Reverse Polish
 // Notation, with each of the subexpressions preceding the
 // expression they are stored in. To evaluate expressions, we
@@ -1341,6 +1355,12 @@ Stmt *PCHReader::ReadStmt(llvm::BitstreamCursor &Cursor) {
     case pch::EXPR_CXX_NULL_PTR_LITERAL:
       S = new (Context) CXXNullPtrLiteralExpr(Empty);
       break;
+    case pch::EXPR_CXX_TYPEID_EXPR:
+      S = new (Context) CXXTypeidExpr(Empty, true);
+      break;
+    case pch::EXPR_CXX_TYPEID_TYPE:
+      S = new (Context) CXXTypeidExpr(Empty, false);
+      break;
     }
 
     // We hit a STMT_STOP, so we're done with this expression.
diff --git a/clang/lib/Frontend/PCHWriterStmt.cpp b/clang/lib/Frontend/PCHWriterStmt.cpp
index 3c2022ea9983..1e272c3c66f4 100644
--- a/clang/lib/Frontend/PCHWriterStmt.cpp
+++ b/clang/lib/Frontend/PCHWriterStmt.cpp
@@ -122,6 +122,7 @@ namespace {
     void VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E);
     void VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E);
     void VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E);
+    void VisitCXXTypeidExpr(CXXTypeidExpr *E);
   };
 }
 
@@ -911,6 +912,18 @@ void PCHStmtWriter::VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E) {
   Code = pch::EXPR_CXX_NULL_PTR_LITERAL;
 }
 
+void PCHStmtWriter::VisitCXXTypeidExpr(CXXTypeidExpr *E) {
+  VisitExpr(E);
+  Writer.AddSourceRange(E->getSourceRange(), Record);
+  if (E->isTypeOperand()) {
+    Writer.AddTypeSourceInfo(E->getTypeOperandSourceInfo(), Record);
+    Code = pch::EXPR_CXX_TYPEID_TYPE;
+  } else {
+    Writer.WriteSubStmt(E->getExprOperand());
+    Code = pch::EXPR_CXX_TYPEID_EXPR;
+  }
+}
+
 //===----------------------------------------------------------------------===//
 // PCHWriter Implementation
 //===----------------------------------------------------------------------===//
diff --git a/clang/test/Makefile b/clang/test/Makefile
index e9d89454b898..40170e42ff9f 100644
--- a/clang/test/Makefile
+++ b/clang/test/Makefile
@@ -16,9 +16,9 @@ TESTDIRS += $(EXTRA_TESTDIRS)
 
 ifndef TESTARGS
 ifdef VERBOSE
-TESTARGS = -v
+TESTARGS = -v -j16
 else
-TESTARGS = -s -v
+TESTARGS = -s -v -j16
 endif
 endif
 
diff --git a/clang/test/PCH/cxx_exprs.cpp b/clang/test/PCH/cxx_exprs.cpp
index 0f0fe88dc54a..ec7041b9843a 100644
--- a/clang/test/PCH/cxx_exprs.cpp
+++ b/clang/test/PCH/cxx_exprs.cpp
@@ -33,3 +33,7 @@ static_assert(!false_value, "false_value is false");
 
 // CXXNullPtrLiteralExpr
 cxx_null_ptr_result null_ptr = nullptr;
+
+// CXXTypeidExpr
+typeid_result1 typeid_1 = 0;
+typeid_result2 typeid_2 = 0;
\ No newline at end of file
diff --git a/clang/test/PCH/cxx_exprs.h b/clang/test/PCH/cxx_exprs.h
index 6766842f0a2d..4f01b3aff630 100644
--- a/clang/test/PCH/cxx_exprs.h
+++ b/clang/test/PCH/cxx_exprs.h
@@ -1,5 +1,6 @@
 // Header for PCH test cxx_exprs.cpp
 
+
 // CXXStaticCastExpr
 typedef __typeof__(static_cast<void *>(0)) static_cast_result;
 
@@ -31,4 +32,14 @@ typedef __typeof__(nullptr) cxx_null_ptr_result;
 void foo(Derived *P) {
   // CXXMemberCallExpr
   P->f();
-}
\ No newline at end of file
+}
+
+
+// FIXME: This is a hack until <typeinfo> works completely.
+namespace std {
+  class type_info {};
+}
+
+// CXXTypeidExpr - Both expr and type forms.
+typedef __typeof__(typeid(int))* typeid_result1;
+typedef __typeof__(typeid(2))*   typeid_result2;