Implementation of new and delete parsing and sema.
This version uses VLAs to represent arrays. I'll try an alternative way next, but I want this safe first.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@59835 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 2e13352..e6a7b41 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -329,7 +329,13 @@
 
   case CXXDefaultArgExprClass:
     return cast<CXXDefaultArgExpr>(this)->getExpr()->hasLocalSideEffect();
-  }     
+
+  case CXXNewExprClass:
+    // FIXME: In theory, there might be new expressions that don't have side
+    // effects (e.g. a placement new with an uninitialized POD).
+  case CXXDeleteExprClass:
+    return true;
+  }
 }
 
 /// DeclCanBeLvalue - Determine whether the given declaration can be
@@ -481,8 +487,6 @@
   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:
     break;
   }
diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp
index 1155a4b..c0f2985 100644
--- a/lib/AST/ExprCXX.cpp
+++ b/lib/AST/ExprCXX.cpp
@@ -77,6 +77,39 @@
   return child_iterator();
 }
 
+// CXXNewExpr
+CXXNewExpr::CXXNewExpr(bool globalNew, FunctionDecl *operatorNew,
+                       Expr **placementArgs, unsigned numPlaceArgs,
+                       bool parenTypeId, QualType alloc,
+                       CXXConstructorDecl *constructor, bool initializer,
+                       Expr **constructorArgs, unsigned numConsArgs,
+                       FunctionDecl *operatorDelete, QualType ty,
+                       SourceLocation startLoc, SourceLocation endLoc)
+  : Expr(CXXNewExprClass, ty), GlobalNew(globalNew), ParenTypeId(parenTypeId),
+    Initializer(initializer), NumPlacementArgs(numPlaceArgs),
+    NumConstructorArgs(numConsArgs), OperatorNew(operatorNew),
+    OperatorDelete(operatorDelete), Constructor(constructor), AllocType(alloc),
+    StartLoc(startLoc), EndLoc(endLoc)
+{
+  unsigned TotalSize = NumPlacementArgs + NumConstructorArgs;
+  SubExprs = new Stmt*[TotalSize];
+  unsigned i = 0;
+  for(unsigned j = 0; j < NumPlacementArgs; ++j)
+    SubExprs[i++] = placementArgs[j];
+  for(unsigned j = 0; j < NumConstructorArgs; ++j)
+    SubExprs[i++] = constructorArgs[j];
+  assert(i == TotalSize);
+}
+
+Stmt::child_iterator CXXNewExpr::child_begin() { return &SubExprs[0]; }
+Stmt::child_iterator CXXNewExpr::child_end() {
+  return &SubExprs[0] + getNumPlacementArgs() + getNumConstructorArgs();
+}
+
+// CXXDeleteExpr
+Stmt::child_iterator CXXDeleteExpr::child_begin() { return &Argument; }
+Stmt::child_iterator CXXDeleteExpr::child_end() { return &Argument+1; }
+
 OverloadedOperatorKind CXXOperatorCallExpr::getOperator() const {
   // All simple function calls (e.g. func()) are implicitly cast to pointer to
   // function. As a result, we try and obtain the DeclRefExpr from the 
diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index cf6d4c0..cb5c44f 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -925,6 +925,49 @@
   PrintRawDecl(E->getVarDecl());
 }
 
+void StmtPrinter::VisitCXXNewExpr(CXXNewExpr *E) {
+  if (E->isGlobalNew())
+    OS << "::";
+  OS << "new ";
+  unsigned NumPlace = E->getNumPlacementArgs();
+  if (NumPlace > 0) {
+    OS << "(";
+    PrintExpr(E->getPlacementArg(0));
+    for (unsigned i = 1; i < NumPlace; ++i) {
+      OS << ", ";
+      PrintExpr(E->getPlacementArg(i));
+    }
+    OS << ") ";
+  }
+  if (E->isParenTypeId())
+    OS << "(";
+  OS << E->getAllocatedType().getAsString();
+  if (E->isParenTypeId())
+    OS << ")";
+
+  if (E->hasInitializer()) {
+    OS << "(";
+    unsigned NumCons = E->getNumConstructorArgs();
+    if (NumCons > 0) {
+      PrintExpr(E->getConstructorArg(0));
+      for (unsigned i = 1; i < NumCons; ++i) {
+        OS << ", ";
+        PrintExpr(E->getConstructorArg(i));
+      }
+    }
+    OS << ")";
+  }
+}
+
+void StmtPrinter::VisitCXXDeleteExpr(CXXDeleteExpr *E) {
+  if (E->isGlobalDelete())
+    OS << "::";
+  OS << "delete ";
+  if (E->isArrayForm())
+    OS << "[] ";
+  PrintExpr(E->getArgument());
+}
+
 // Obj-C 
 
 void StmtPrinter::VisitObjCStringLiteral(ObjCStringLiteral *Node) {
diff --git a/lib/AST/StmtSerialization.cpp b/lib/AST/StmtSerialization.cpp
index 268922e..8faef8b 100644
--- a/lib/AST/StmtSerialization.cpp
+++ b/lib/AST/StmtSerialization.cpp
@@ -227,6 +227,12 @@
 
     case CXXZeroInitValueExprClass:
       return CXXZeroInitValueExpr::CreateImpl(D, C);
+
+    case CXXNewExprClass:
+      return CXXNewExpr::CreateImpl(D, C);
+
+    case CXXDeleteExprClass:
+      return CXXDeleteExpr::CreateImpl(D, C);
   }
 }
 
@@ -1414,3 +1420,66 @@
   SourceLocation RParenLoc = SourceLocation::ReadVal(D);
   return new CXXZeroInitValueExpr(Ty, TyBeginLoc, RParenLoc);
 }
+
+void CXXNewExpr::EmitImpl(Serializer& S) const {
+  S.Emit(getType());
+  S.Emit(Initializer);
+  S.Emit(NumPlacementArgs);
+  S.Emit(NumConstructorArgs);
+  S.BatchEmitOwnedPtrs(NumPlacementArgs + NumConstructorArgs, SubExprs);
+  assert((OperatorNew == 0 || S.isRegistered(OperatorNew)) &&
+         (OperatorDelete == 0 || S.isRegistered(OperatorDelete)) &&
+         (Constructor == 0 || S.isRegistered(Constructor)) &&
+         "CXXNewExpr cannot own declarations");
+  S.EmitPtr(OperatorNew);
+  S.EmitPtr(OperatorDelete);
+  S.EmitPtr(Constructor);
+  S.Emit(AllocType);
+  S.Emit(StartLoc);
+  S.Emit(EndLoc);
+}
+
+CXXNewExpr *
+CXXNewExpr::CreateImpl(Deserializer& D, ASTContext& C) {
+  QualType T = QualType::ReadVal(D);
+  bool GlobalNew = D.ReadBool();
+  bool ParenTypeId = D.ReadBool();
+  bool Initializer = D.ReadBool();
+  unsigned NumPlacementArgs = D.ReadInt();
+  unsigned NumConstructorArgs = D.ReadInt();
+  unsigned TotalExprs = NumPlacementArgs + NumConstructorArgs;
+  Stmt** SubExprs = new Stmt*[TotalExprs];
+  D.BatchReadOwnedPtrs(TotalExprs, SubExprs, C);
+  FunctionDecl *OperatorNew = D.ReadPtr<FunctionDecl>();
+  FunctionDecl *OperatorDelete = D.ReadPtr<FunctionDecl>();
+  CXXConstructorDecl *Constructor = D.ReadPtr<CXXConstructorDecl>();
+  QualType AllocType = QualType::ReadVal(D);
+  SourceLocation StartLoc = SourceLocation::ReadVal(D);
+  SourceLocation EndLoc = SourceLocation::ReadVal(D);
+
+  return new CXXNewExpr(T, AllocType, GlobalNew, ParenTypeId, Initializer,
+                        NumPlacementArgs, NumConstructorArgs, SubExprs,
+                        OperatorNew, OperatorDelete, Constructor, StartLoc,
+                        EndLoc);
+}
+
+void CXXDeleteExpr::EmitImpl(Serializer& S) const {
+  S.Emit(getType());
+  S.Emit(GlobalDelete);
+  S.Emit(ArrayForm);
+  S.EmitPtr(OperatorDelete);
+  S.EmitOwnedPtr(Argument);
+  S.Emit(Loc);
+}
+
+CXXDeleteExpr *
+CXXDeleteExpr::CreateImpl(Deserializer& D, ASTContext& C) {
+  QualType Ty = QualType::ReadVal(D);
+  bool GlobalDelete = D.ReadBool();
+  bool ArrayForm = D.ReadBool();
+  FunctionDecl *OperatorDelete = D.ReadPtr<FunctionDecl>();
+  Stmt *Argument = D.ReadOwnedPtr<Stmt>(C);
+  SourceLocation Loc = SourceLocation::ReadVal(D);
+  return new CXXDeleteExpr(Ty, GlobalDelete, ArrayForm, OperatorDelete,
+                           cast<Expr>(Argument), Loc);
+}