Implement C++0x nullptr.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@71405 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 4aed59f..133e8c2 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -276,6 +276,9 @@
   
   // void * type
   VoidPtrTy = getPointerType(VoidTy);
+
+  // nullptr type (C++0x 2.14.7)
+  InitBuiltinType(NullPtrTy,           BuiltinType::NullPtr);
 }
 
 //===----------------------------------------------------------------------===//
@@ -431,6 +434,9 @@
       Width = Target.getLongDoubleWidth();
       Align = Target.getLongDoubleAlign();
       break;
+    case BuiltinType::NullPtr:
+      Width = Target.getPointerWidth(0); // C++ 3.9.1p11: sizeof(nullptr_t)
+      Align = Target.getPointerAlign(0); //   == sizeof(void*)
     }
     break;
   case Type::FixedWidthInt:
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 77a25f6..0d38dd2 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -1377,6 +1377,10 @@
     return true;
   }
 
+  // C++0x nullptr_t is always a null pointer constant.
+  if (getType()->isNullPtrType())
+    return true;
+
   // This expression must be an integer type.
   if (!getType()->isIntegerType())
     return false;
diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp
index b05bf7d..8176db5 100644
--- a/lib/AST/ExprCXX.cpp
+++ b/lib/AST/ExprCXX.cpp
@@ -44,6 +44,14 @@
   return child_iterator();
 }
 
+// CXXNullPtrLiteralExpr
+Stmt::child_iterator CXXNullPtrLiteralExpr::child_begin() { 
+  return child_iterator();
+}
+Stmt::child_iterator CXXNullPtrLiteralExpr::child_end() {
+  return child_iterator();
+}
+
 // CXXThisExpr
 Stmt::child_iterator CXXThisExpr::child_begin() { return child_iterator(); }
 Stmt::child_iterator CXXThisExpr::child_end() { return child_iterator(); }
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index aa4920f..34b0187 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -299,7 +299,9 @@
       { return APValue((Expr*)0, 0); }
   APValue VisitConditionalOperator(ConditionalOperator *E);
   APValue VisitChooseExpr(ChooseExpr *E)
-    { return Visit(E->getChosenSubExpr(Info.Ctx)); }
+      { return Visit(E->getChosenSubExpr(Info.Ctx)); }
+  APValue VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E)
+      { return APValue((Expr*)0, 0); }
   // FIXME: Missing: @protocol, @selector
 };
 } // end anonymous namespace
diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index 0f8284a..cf1a255 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -996,6 +996,10 @@
   OS << (Node->getValue() ? "true" : "false");
 }
 
+void StmtPrinter::VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *Node) {
+  OS << "nullptr";
+}
+
 void StmtPrinter::VisitCXXThisExpr(CXXThisExpr *Node) {
   OS << "this";
 }
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index d6cf4bd..b5a8840 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -889,6 +889,12 @@
   return false;
 }
 
+bool Type::isNullPtrType() const {
+  if (const BuiltinType *BT = getAsBuiltinType())
+    return BT->getKind() == BuiltinType::NullPtr;
+  return false;
+}
+
 const char *BuiltinType::getName() const {
   switch (getKind()) {
   default: assert(0 && "Unknown builtin type!");
@@ -912,6 +918,7 @@
   case Double:            return "double";
   case LongDouble:        return "long double";
   case WChar:             return "wchar_t";
+  case NullPtr:           return "nullptr_t";
   case Overload:          return "<overloaded function type>";
   case Dependent:         return "<dependent type>";
   }