Index: test/SemaCXX/new-delete.cpp
===================================================================
--- test/SemaCXX/new-delete.cpp	(revision 0)
+++ test/SemaCXX/new-delete.cpp	(revision 0)
@@ -0,0 +1,40 @@
+struct S
+{
+  S(int, int, double);
+};
+struct T;
+
+void good_news()
+{
+  int *pi = new int;
+  float *pf = new (pi) float();
+  (void)new int(1);
+  (void)new S(1, 2, 3.4);
+  (void)new (pf) S(1, 2, 3.4);
+  (void)new S*[*pi][2];
+  (void)new (S[3])(1, 2, 3.4);
+}
+
+void bad_news()
+{
+  new; // expected-error {{missing type specifier}} This could be better
+  new 4; // expected-error {{missing type specifier}}
+  new int[1.1]; // expected-error {{array size expression needs to}}
+  // Lots of lacking cases due to lack of sema support.
+}
+
+void good_deletes()
+{
+  delete (int*)0;
+  delete [](int*)0;
+  delete (S*)0;
+}
+
+void bad_deletes()
+{
+  delete 0; // expected-error {{cannot delete expression of type 'int'}}
+  delete [0] (int*)0; // expected-error {{expected ']'}} \
+                      // expected-error {{to match this '['}}
+  delete (void*)0; // expected-error {{cannot delete expression}}
+  delete (T*)0; // expected-warning {{deleting pointer to incomplete type}}
+}
Index: include/clang/Basic/DiagnosticKinds.def
===================================================================
--- include/clang/Basic/DiagnosticKinds.def	(revision 59319)
+++ include/clang/Basic/DiagnosticKinds.def	(working copy)
@@ -1164,6 +1164,18 @@
 // Other C++ expressions
 DIAG(err_need_header_before_typeid, ERROR,
      "you need to include <typeinfo> before using the 'typeid' operator")
+DIAG(err_new_function, ERROR,
+     "cannot allocate function type '%0' with new")
+DIAG(err_new_incomplete, ERROR,
+     "cannot allocate incomplete type '%0' with new")
+DIAG(err_new_reference, ERROR,
+     "cannot allocate reference type '%0' with new")
+DIAG(err_new_size_not_integral, ERROR,
+     "array size expression needs to be of integral or enum type, is '%0'")
+DIAG(err_delete_operand, ERROR,
+     "cannot delete expression of type '%0'")
+DIAG(warn_delete_incomplete, WARNING,
+     "deleting pointer to incomplete type '%0' may cause undefined behaviour")
 
 DIAG(err_invalid_use_of_function_type, ERROR,
      "a function type is not allowed here")
Index: include/clang/AST/ExprCXX.h
===================================================================
--- include/clang/AST/ExprCXX.h	(revision 59319)
+++ include/clang/AST/ExprCXX.h	(working copy)
@@ -433,6 +433,180 @@
   //    CreateImpl(llvm::Deserializer& D, ASTContext& C);
 };
 
+/// CXXNewExpr - A new expression for memory allocation and constructor calls,
+/// e.g: "new CXXNewExpr(foo)".
+class CXXNewExpr : public Expr {
+  // Does SubExprs contain an array size specifier? If yes, it's the first
+  // element in SubExprs.
+  bool ArraySize : 1;
+  // Is there an initializer? If not, built-ins are uninitialized, else they're
+  // value-initialized.
+  bool Initializer : 1;
+  // The number of placement new arguments.
+  unsigned NumPlacementArgs : 15;
+  // The number of constructor arguments. This may be 1 even for non-class
+  // types; use the pseudo copy constructor.
+  unsigned NumConstructorArgs : 15;
+  // Contains an optional size expression, any number of optional placement
+  // arguments, and any number of optional constructor arguments, in that order.
+  Stmt **SubExprs;
+  // Points to the allocation function used.
+  Decl *OperatorNew;
+  // Points to the deallocation function used in case of error. May be null.
+  Decl *OperatorDelete;
+  // Points to the constructor used. Cannot be null if AllocType is a record;
+  // it would still point at the default constructor (even an implicit one).
+  // Must be null for all other types.
+  Decl *Constructor;
+
+  SourceLocation StartLoc;
+  SourceLocation EndLoc;
+
+  // Deserialization constructor
+  CXXNewExpr(QualType ty, bool arraySize, bool initializer,
+             unsigned numPlacementArgs, unsigned numConstructorArgs,
+             Stmt **subExprs, Decl *operatorNew, Decl *operatorDelete,
+             Decl *constructor, SourceLocation startLoc, SourceLocation endLoc)
+    : Expr(CXXNewExprClass, ty), ArraySize(arraySize), Initializer(initializer),
+      NumPlacementArgs(numPlacementArgs),
+      NumConstructorArgs(numConstructorArgs), SubExprs(subExprs),
+      OperatorNew(operatorNew), OperatorDelete(operatorDelete),
+      Constructor(constructor), StartLoc(startLoc), EndLoc(endLoc)
+  { }
+public:
+  CXXNewExpr(Decl *operatorNew, Expr **placementArgs, unsigned numPlaceArgs,
+             Decl *constructor, bool initializer, Expr **constructorArgs,
+             unsigned numConsArgs, Expr *arraySize, Decl *operatorDelete,
+             QualType ty, SourceLocation startLoc, SourceLocation endLoc);
+  ~CXXNewExpr() {
+    delete[] SubExprs;
+  }
+
+  QualType getAllocatedType() const {
+    return getType()->getAsPointerType()->getPointeeType();
+  }
+
+  Decl *getOperatorNew() const { return OperatorNew; }
+  Decl *getOperatorDelete() const { return OperatorDelete; }
+  Decl *getConstructor() const { return Constructor; }
+
+  Expr *getArraySize() {
+    return ArraySize ? cast<Expr>(SubExprs[0]) : 0;
+  }
+  const Expr *getArraySize() const {
+    return ArraySize ? cast<Expr>(SubExprs[0]) : 0;
+  }
+
+  unsigned getNumPlacementArgs() const { return NumPlacementArgs; }
+  Expr *getPlacementArg(unsigned i) {
+    assert(i < NumPlacementArgs && "Index out of range");
+    return cast<Expr>(SubExprs[ArraySize + i]);
+  }
+  const Expr *getPlacementArg(unsigned i) const {
+    assert(i < NumPlacementArgs && "Index out of range");
+    return cast<Expr>(SubExprs[ArraySize + i]);
+  }
+
+  bool hasInitializer() const { return Initializer; }
+
+  unsigned getNumConstructorArgs() const { return NumConstructorArgs; }
+  Expr *getConstructorArg(unsigned i) {
+    assert(i < NumConstructorArgs && "Index out of range");
+    return cast<Expr>(SubExprs[ArraySize + NumPlacementArgs + i]);
+  }
+  const Expr *getConstructorArg(unsigned i) const {
+    assert(i < NumConstructorArgs && "Index out of range");
+    return cast<Expr>(SubExprs[ArraySize + NumPlacementArgs + i]);
+  }
+
+  typedef ExprIterator arg_iterator;
+  typedef ConstExprIterator const_arg_iterator;
+
+  arg_iterator placement_arg_begin() {
+    return SubExprs + ArraySize;
+  }
+  arg_iterator placement_arg_end() {
+    return SubExprs + ArraySize + getNumPlacementArgs();
+  }
+  const_arg_iterator placement_arg_begin() const {
+    return SubExprs + ArraySize;
+  }
+  const_arg_iterator placement_arg_end() const {
+    return SubExprs + ArraySize + getNumPlacementArgs();
+  }
+
+  arg_iterator constructor_arg_begin() {
+    return SubExprs + ArraySize + getNumPlacementArgs() +
+           getNumConstructorArgs();
+  }
+  arg_iterator constructor_arg_end() {
+    return SubExprs + ArraySize + getNumPlacementArgs();
+  }
+  const_arg_iterator constructor_arg_begin() const {
+    return SubExprs + ArraySize + getNumPlacementArgs() +
+           getNumConstructorArgs();
+  }
+  const_arg_iterator constructor_arg_end() const {
+    return SubExprs + ArraySize + getNumPlacementArgs();
+  }
+
+  virtual SourceRange getSourceRange() const {
+    return SourceRange(StartLoc, EndLoc);
+  }
+
+  static bool classof(const Stmt *T) {
+    return T->getStmtClass() == CXXNewExprClass;
+  }
+  static bool classof(const CXXNewExpr *) { return true; }
+
+  // Iterators
+  virtual child_iterator child_begin();
+  virtual child_iterator child_end();
+  
+  virtual void EmitImpl(llvm::Serializer& S) const;
+  static CXXNewExpr* CreateImpl(llvm::Deserializer& D, ASTContext& C);
+};
+
+/// CXXDeleteExpr - A delete expression for memory deallocation and destructor
+/// calls, e.g. "delete[] pArray".
+class CXXDeleteExpr : public Expr {
+  // Is this the array form of delete, i.e. "delete[]"?
+  bool ArrayForm : 1;
+  // Points to the operator delete overload that is used. Could be a member.
+  Decl *OperatorDelete;
+  // The pointer expression to be deleted.
+  Stmt *Argument;
+  // Location of the expression.
+  SourceLocation Loc;
+public:
+  CXXDeleteExpr(QualType ty, bool arrayForm, Expr *arg, SourceLocation loc)
+    : Expr(CXXDeleteExprClass, ty), ArrayForm(arrayForm), Argument(arg),
+      Loc(loc) { }
+
+  bool isArrayForm() const { return ArrayForm; }
+
+  Decl *getOperatorDelete() const { return OperatorDelete; }
+
+  Expr *getArgument() { return cast<Expr>(Argument); }
+  const Expr *getArgument() const { return cast<Expr>(Argument); }
+
+  virtual SourceRange getSourceRange() const {
+    return SourceRange(Loc, Argument->getLocEnd());
+  }
+
+  static bool classof(const Stmt *T) {
+    return T->getStmtClass() == CXXDeleteExprClass;
+  }
+  static bool classof(const CXXDeleteExpr *) { return true; }
+
+  // Iterators
+  virtual child_iterator child_begin();
+  virtual child_iterator child_end();
+
+  virtual void EmitImpl(llvm::Serializer& S) const;
+  static CXXDeleteExpr * CreateImpl(llvm::Deserializer& D, ASTContext& C);
+};
+
 }  // end namespace clang
 
 #endif
Index: include/clang/AST/StmtNodes.def
===================================================================
--- include/clang/AST/StmtNodes.def	(revision 59319)
+++ include/clang/AST/StmtNodes.def	(working copy)
@@ -104,6 +104,8 @@
 STMT(CXXDefaultArgExpr      , Expr)
 STMT(CXXZeroInitValueExpr   , Expr)
 STMT(CXXConditionDeclExpr   , DeclRefExpr)
+STMT(CXXNewExpr             , Expr)
+STMT(CXXDeleteExpr          , Expr)
 
 // Obj-C Expressions.
 STMT(ObjCStringLiteral    , Expr)
Index: include/clang/Parse/Parser.h
===================================================================
--- include/clang/Parse/Parser.h	(revision 59319)
+++ include/clang/Parse/Parser.h	(working copy)
@@ -532,6 +532,13 @@
   bool ParseCXXTypeSpecifierSeq(DeclSpec &DS);
 
   //===--------------------------------------------------------------------===//
+  // C++ 5.3.4 and 5.3.5: C++ new and delete
+  ExprResult ParseCXXNewExpression();
+  TypeTy *ParseNewTypeId(ExprTy *&ArraySize);
+  bool ParseExpressionListOrTypeId(ExprListTy &Exprs, TypeTy *&Ty);
+  ExprResult ParseCXXDeleteExpression();
+
+  //===--------------------------------------------------------------------===//
   // C++ if/switch/while/for condition expression.
   ExprResult ParseCXXCondition();
 
Index: include/clang/Parse/Action.h
===================================================================
--- include/clang/Parse/Action.h	(revision 59319)
+++ include/clang/Parse/Action.h	(working copy)
@@ -716,6 +716,39 @@
     return 0;
   }
 
+  /// ActOnCXXNew - Parsed a C++ 'new' expression. UseGlobal is true if the
+  /// new was qualified (::new). In a full new like
+  /// @code new (p1, p2) type(c1, c2) @endcode
+  /// the p1 and p2 expressions will be in PlacementArgs and the c1 and c2
+  /// expressions in ConstructorArgs. If the type is a dynamic array, the Ty
+  /// will be the type of the dynamic array dimension and ArraySize will be the
+  /// final size expression.
+  /// Example:
+  /// @code new int*[rand()][3] @endcode
+  /// Here, Ty will be "int*[3]", and ArraySize will be "rand()". This is
+  /// consistent with the fact that the type of the new result should be
+  /// a pointer to Ty, i.e. "int* (*)[3]" (a pointer to an array of 3 pointers
+  /// to int) above.
+  virtual ExprResult ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal,
+                                 SourceLocation PlacementLParen,
+                                 ExprTy **PlacementArgs, unsigned NumPlaceArgs,
+                                 SourceLocation PlacementRParen,
+                                 SourceLocation TyStart, TypeTy *Ty,
+                                 ExprTy *ArraySize, SourceLocation TyEnd,
+                                 SourceLocation ConstructorLParen,
+                                 ExprTy **ConstructorArgs, unsigned NumConsArgs,
+                                 SourceLocation ConstructorRParen) {
+    return 0;
+  }
+
+  /// ActOnCXXDelete - Parsed a C++ 'delete' expression. UseGlobal is true if
+  /// the delete was qualified (::delete). ArrayForm is true if the array form
+  /// was used (delete[]).
+  virtual ExprResult ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
+                                    bool ArrayForm, ExprTy *Operand) {
+    return 0;
+  }
+
   //===---------------------------- C++ Classes ---------------------------===//
   /// ActOnBaseSpecifier - Parsed a base specifier
   virtual BaseResult ActOnBaseSpecifier(DeclTy *classdecl, 
Index: lib/Sema/SemaExprCXX.cpp
===================================================================
--- lib/Sema/SemaExprCXX.cpp	(revision 59319)
+++ lib/Sema/SemaExprCXX.cpp	(working copy)
@@ -145,6 +145,162 @@
 }
 
 
+/// ActOnCXXNew - Parsed a C++ 'new' expression (C++ 5.3.4), as in e.g.:
+/// @code new (memory) int[size][4] @endcode
+/// or
+/// @code ::new Foo(23, "hello") @endcode
+/// For the interpretation of this heap of arguments, consult the base version.
+Action::ExprResult
+Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal,
+                  SourceLocation PlacementLParen,
+                  ExprTy **PlacementArgs, unsigned NumPlaceArgs,
+                  SourceLocation PlacementRParen,
+                  SourceLocation TyStart, TypeTy *Ty,
+                  ExprTy *ArraySize, SourceLocation TyEnd,
+                  SourceLocation ConstructorLParen,
+                  ExprTy **ConstructorArgs, unsigned NumConsArgs,
+                  SourceLocation ConstructorRParen)
+{
+  QualType AllocType = QualType::getFromOpaquePtr(Ty);
+
+  // If the type given is an array, and ArraySize is null, we face something
+  // like "new (int[10])". We must unwrap the array and use the inner type
+  // instead.
+  Expr *SizeExpr = (Expr *)ArraySize;
+  if (!SizeExpr) {
+    if (const ConstantArrayType *CAT =
+        Context.getAsConstantArrayType(AllocType)) {
+      // We've lost the expression that led to the size.
+      // FIXME: Perhaps we can adjust the parser, although it means
+      // reimplementing a lot of stuff. Better to modify ConstantSizedArray to
+      // remember the source expression. Is that even possible?
+      // Best method may be to give the existing parser function a special
+      // mode for new, where it forces a VLA on the first array dimension.
+      // As a workaround, pretend that the size was a literal.
+      // The source location is pretty much invented, too.
+      SizeExpr = new IntegerLiteral(CAT->getSize(), Context.getSizeType(),
+                                    TyEnd);
+      AllocType = CAT->getElementType();
+    }
+  }
+
+  // C++ 5.3.4p1: "[The] type shall be a complete object type, but not an
+  //   abstract class type or array thereof.
+  // FIXME: We don't have abstract types yet.
+  if (!AllocType->isObjectType()) {
+    diag::kind msg;
+    if (AllocType->isFunctionType()) {
+      msg = diag::err_new_function;
+    } else if(AllocType->isIncompleteType()) {
+      msg = diag::err_new_incomplete;
+    } else if(AllocType->isReferenceType()) {
+      msg = diag::err_new_reference;
+    } else {
+      assert(false && "Unexpected type class");
+      return true;
+    }
+    Diag(StartLoc, msg, AllocType.getAsString(), SourceRange(TyStart, TyEnd));
+    return true;
+  }
+
+  QualType ResultType = Context.getPointerType(AllocType);
+
+  // That every array dimension except the first is constant was already
+  // checked by the type creation function.
+  // C++ 5.3.4p6: "The expression in a direct-new-declarator shall have integral
+  //   or enumeration type with a non-negative value."
+  // Since the value is a runtime thing, we only need to check the type.
+  if (SizeExpr) {
+    QualType SizeType = SizeExpr->getType();
+    if (!SizeType->isIntegralType() && !SizeType->isEnumeralType()) {
+      Diag(StartLoc, diag::err_new_size_not_integral, SizeType.getAsString(),
+        SizeExpr->getSourceRange());
+      return true;
+    }
+  }
+
+  // --- Choosing an allocation function ---
+  // C++ 5.3.4p8 - 14 & 18
+  // 1) If UseGlobal is true, only look in the global scope. Else, also look
+  //   in the scope of the allocated class.
+  // 2) If an array size is given, look for operator new[], else look for
+  //   operator new.
+  // 3) The first argument is always size_t. Append the arguments from the
+  //   placement form.
+  // FIXME: Find the correct overload of operator new.
+  // FIXME: Also find the corresponding overload of operator delete.
+  Decl *OperatorNew = 0;
+  Decl *OperatorDelete = 0;
+  Expr **PlaceArgs = (Expr**)PlacementArgs;
+
+  bool Init = ConstructorLParen.isValid();
+  // --- Choosing a constructor ---
+  // C++ 5.3.4p15
+  // 1) If T is a POD and there's no initializer (ConstructorLParen is invalid)
+  //   the object is default-initialized, i.e. not at all. If the object, or any
+  //   part of it, is const-qualified, it's an error.
+  // 2) If T is a POD and there's an empty initializer, the object is value-
+  //   initialized.
+  // 3) If T is a POD and there's one initializer argument, the object is copy-
+  //   constructed.
+  // 4) If T is a POD and there's more initializer arguments, it's an error.
+  // 5) If T is not a POD, the initializer arguments are used as constructor
+  //   arguments.
+  // FIXME: Find the correct constructor.
+  Decl *Constructor = 0;
+  Expr **ConsArgs = (Expr**)ConstructorArgs;
+
+  // FIXME: Also check that the destructor is accessible. (C++ 5.3.4p16)
+
+  return new CXXNewExpr(OperatorNew, PlaceArgs, NumPlaceArgs, Constructor,
+                        Init, ConsArgs, NumConsArgs, SizeExpr, OperatorDelete,
+                        ResultType, StartLoc, Init ? ConstructorRParen : TyEnd);
+}
+
+/// ActOnCXXDelete - Parsed a C++ 'delete' expression (C++ 5.3.5), as in:
+/// @code ::delete ptr; @endcode
+/// or
+/// @code delete [] ptr; @endcode
+Action::ExprResult
+Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
+                     bool ArrayForm, ExprTy *Operand)
+{
+  // C++ 5.3.5p1: "The operand shall have a pointer type, or a class type
+  //   having a single conversion function to a pointer type. The result has
+  //   type void."
+  // DR599 amends "pointer type" to "pointer to object type" in both cases.
+
+  Expr *Ex = (Expr *)Operand;
+  QualType Type = Ex->getType();
+
+  if (Type->isRecordType()) {
+    // FIXME: Find that one conversion function and amend the type.
+  }
+
+  if (!Type->isPointerType()) {
+    Diag(StartLoc, diag::err_delete_operand, Type.getAsString(),
+         Ex->getSourceRange());
+    return true;
+  }
+
+  QualType Pointee = Type->getAsPointerType()->getPointeeType();
+  if (Pointee->isIncompleteType() && !Pointee->isVoidType())
+    Diag(StartLoc, diag::warn_delete_incomplete,
+         Pointee.getAsString(), Ex->getSourceRange());
+  else if (!Pointee->isObjectType()) {
+    Diag(StartLoc, diag::err_delete_operand, Type.getAsString(),
+         Ex->getSourceRange());
+    return true;
+  }
+
+  // FIXME: Look up the correct operator delete overload and pass a pointer
+  // along.
+  // FIXME: Check access and ambiguity of operator delete and destructor.
+
+  return new CXXDeleteExpr(Context.VoidTy, ArrayForm, Ex, StartLoc);
+}
+
+
 /// ActOnCXXConditionDeclarationExpr - Parsed a condition declaration of a
 /// C++ if/switch/while/for statement.
 /// e.g: "if (int x = f()) {...}"
Index: lib/Sema/Sema.h
===================================================================
--- lib/Sema/Sema.h	(revision 59319)
+++ lib/Sema/Sema.h	(working copy)
@@ -796,6 +796,21 @@
                                                SourceLocation *CommaLocs,
                                                SourceLocation RParenLoc);
 
+  /// ActOnCXXNew - Parsed a C++ 'new' expression.
+  virtual ExprResult ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal,
+                                 SourceLocation PlacementLParen,
+                                 ExprTy **PlacementArgs, unsigned NumPlaceArgs,
+                                 SourceLocation PlacementRParen,
+                                 SourceLocation TyStart, TypeTy *Ty,
+                                 ExprTy *ArraySize, SourceLocation TyEnd,
+                                 SourceLocation ConstructorLParen,
+                                 ExprTy **ConstructorArgs, unsigned NumConsArgs,
+                                 SourceLocation ConstructorRParen);
+
+  /// ActOnCXXDelete - Parsed a C++ 'delete' expression
+  virtual ExprResult ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
+                                    bool ArrayForm, ExprTy *Operand);
+
   /// ActOnCXXConditionDeclarationExpr - Parsed a condition declaration of a
   /// C++ if/switch/while/for statement.
   /// e.g: "if (int x = f()) {...}"
Index: lib/AST/ExprCXX.cpp
===================================================================
--- lib/AST/ExprCXX.cpp	(revision 59319)
+++ lib/AST/ExprCXX.cpp	(working copy)
@@ -77,6 +77,40 @@
   return child_iterator();
 }
 
+// CXXNewExpr
+CXXNewExpr::CXXNewExpr(Decl *operatorNew, Expr **placementArgs,
+                       unsigned numPlaceArgs, Decl *constructor,
+                       bool initializer, Expr **constructorArgs,
+                       unsigned numConsArgs, Expr *arraySize,
+                       Decl *operatorDelete, QualType ty,
+                       SourceLocation startLoc, SourceLocation endLoc)
+  : Expr(CXXNewExprClass, ty), ArraySize(arraySize), Initializer(initializer),
+    NumPlacementArgs(numPlaceArgs), NumConstructorArgs(numConsArgs),
+    OperatorNew(operatorNew), OperatorDelete(operatorDelete),
+    Constructor(constructor), StartLoc(startLoc), EndLoc(endLoc)
+{
+  unsigned TotalSize = ArraySize + NumPlacementArgs + NumConstructorArgs;
+  SubExprs = new Stmt*[TotalSize];
+  unsigned i = 0;
+  if(ArraySize)
+    SubExprs[i++] = arraySize;
+  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] + ArraySize + 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 
Index: lib/AST/Expr.cpp
===================================================================
--- lib/AST/Expr.cpp	(revision 59319)
+++ lib/AST/Expr.cpp	(working copy)
@@ -326,7 +326,13 @@
 
   case CXXDefaultArgExprClass:
     return cast<CXXDefaultArgExpr>(this)->getExpr()->hasLocalSideEffect();
-  }     
+
+  case CXXNewExprClass:
+    // In theory, there might be new expressions that don't have side effects
+    // (e.g. a placement new with an uninitialized POD), but those are obscure.
+  case CXXDeleteExprClass:
+    return true;
+  }
 }
 
 /// DeclCanBeLvalue - Determine whether the given declaration can be
@@ -468,8 +474,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;
   }
Index: lib/AST/StmtSerialization.cpp
===================================================================
--- lib/AST/StmtSerialization.cpp	(revision 59319)
+++ lib/AST/StmtSerialization.cpp	(working copy)
@@ -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,61 @@
   SourceLocation RParenLoc = SourceLocation::ReadVal(D);
   return new CXXZeroInitValueExpr(Ty, TyBeginLoc, RParenLoc);
 }
+
+void CXXNewExpr::EmitImpl(Serializer& S) const {
+  S.Emit(getType());
+  S.Emit(ArraySize);
+  S.Emit(Initializer);
+  S.Emit(NumPlacementArgs);
+  S.Emit(NumConstructorArgs);
+  S.BatchEmitOwnedPtrs(ArraySize + NumPlacementArgs + NumConstructorArgs,
+                       SubExprs);
+  // FIXME: What about the default allocation functions? We don't want to
+  // own them to avoid the mess DeclRefExpr is in, but who would?
+  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(StartLoc);
+  S.Emit(EndLoc);
+}
+
+CXXNewExpr *
+CXXNewExpr::CreateImpl(Deserializer& D, ASTContext& C) {
+  QualType T = QualType::ReadVal(D);
+  bool ArraySize = D.ReadBool();
+  bool Initializer = D.ReadBool();
+  unsigned NumPlacementArgs = D.ReadInt();
+  unsigned NumConstructorArgs = D.ReadInt();
+  unsigned TotalExprs = ArraySize + NumPlacementArgs + NumConstructorArgs;
+  Stmt** SubExprs = new Stmt*[TotalExprs];
+  D.BatchReadOwnedPtrs(TotalExprs, SubExprs, C);
+  Decl *OperatorNew = D.ReadPtr<Decl>();
+  Decl *OperatorDelete = D.ReadPtr<Decl>();
+  Decl *Constructor = D.ReadPtr<Decl>();
+  SourceLocation StartLoc = SourceLocation::ReadVal(D);
+  SourceLocation EndLoc = SourceLocation::ReadVal(D);
+
+  return new CXXNewExpr(T, ArraySize, Initializer, NumPlacementArgs,
+                        NumConstructorArgs, SubExprs, OperatorNew,
+                        OperatorDelete, Constructor, StartLoc, EndLoc);
+}
+
+void CXXDeleteExpr::EmitImpl(Serializer& S) const {
+  S.Emit(getType());
+  S.Emit(ArrayForm);
+  S.EmitOwnedPtr(Argument);
+  S.Emit(Loc);
+}
+
+CXXDeleteExpr *
+CXXDeleteExpr::CreateImpl(Deserializer& D, ASTContext& C) {
+  QualType Ty = QualType::ReadVal(D);
+  bool ArrayForm = D.ReadBool();
+  Stmt *Argument = D.ReadOwnedPtr<Stmt>(C);
+  SourceLocation Loc = SourceLocation::ReadVal(D);
+  return new CXXDeleteExpr(Ty, ArrayForm, cast<Expr>(Argument), Loc);
+}
Index: lib/AST/StmtPrinter.cpp
===================================================================
--- lib/AST/StmtPrinter.cpp	(revision 59319)
+++ lib/AST/StmtPrinter.cpp	(working copy)
@@ -925,6 +925,53 @@
   PrintRawDecl(E->getVarDecl());
 }
 
+void StmtPrinter::VisitCXXNewExpr(CXXNewExpr *E) {
+  // FIXME: How to recover the '::'?
+  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 << ") ";
+  }
+  Expr *Ar = E->getArraySize();
+  if (!Ar) {
+    // We can just print the allocated type.
+    // FIXME: We lose the info about whether it was a new-type-id or a (type-id)
+    // Depending on the situation, this can lead to invalid code.
+    OS << E->getAllocatedType().getAsString();
+  } else {
+    // Would have to unwrap the array - but without an ASTContext, we can't!
+    // FIXME: There's got to be a way around this.
+    OS << "<array new>";
+  }
+
+  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) {
+  // FIXME: How to recover the '::'?
+  OS << "delete ";
+  if (E->isArrayForm())
+    OS << "[] ";
+  PrintExpr(E->getArgument());
+}
+
 // Obj-C 
 
 void StmtPrinter::VisitObjCStringLiteral(ObjCStringLiteral *Node) {
Index: lib/Parse/ParseDecl.cpp
===================================================================
--- lib/Parse/ParseDecl.cpp	(revision 59319)
+++ lib/Parse/ParseDecl.cpp	(working copy)
@@ -25,6 +25,8 @@
 /// ParseTypeName
 ///       type-name: [C99 6.7.6]
 ///         specifier-qualifier-list abstract-declarator[opt]
+///
+/// Called type-id in C++
 Parser::TypeTy *Parser::ParseTypeName() {
   // Parse the common declaration-specifiers piece.
   DeclSpec DS;
@@ -1373,7 +1375,7 @@
         Diag(InnerChunk.Loc, diag::err_illegal_decl_reference_to_reference,
              D.getIdentifier() ? D.getIdentifier()->getName() : "type name");
 
-        // Once we've complained about the reference-to-referwnce, we
+        // Once we've complained about the reference-to-reference, we
         // can go ahead and build the (technically ill-formed)
         // declarator: reference collapsing will take care of it.
       }
Index: lib/Parse/ParseExpr.cpp
===================================================================
--- lib/Parse/ParseExpr.cpp	(revision 59319)
+++ lib/Parse/ParseExpr.cpp	(working copy)
@@ -350,6 +350,8 @@
 /// [GNU]   '__alignof' '(' type-name ')'
 /// [C++0x] 'alignof' '(' type-id ')'
 /// [GNU]   '&&' identifier
+/// [C++]   new-expression
+/// [C++]   delete-expression
 ///
 ///       unary-operator: one of
 ///         '&'  '*'  '+'  '-'  '~'  '!'
@@ -404,6 +406,16 @@
 ///                   '~' class-name         [TODO]
 ///                   template-id            [TODO]
 ///
+///       new-expression: [C++ 5.3.4]
+///                   '::'[opt] 'new' new-placement[opt] new-type-id
+///                                     new-initializer[opt]
+///                   '::'[opt] 'new' new-placement[opt] '(' type-id ')'
+///                                     new-initializer[opt]
+///
+///       delete-expression: [C++ 5.3.5]
+///                   '::'[opt] 'delete' cast-expression
+///                   '::'[opt] 'delete' '[' ']' cast-expression
+///
 Parser::ExprResult Parser::ParseCastExpression(bool isUnaryExpression) {
   if (getLang().CPlusPlus) {
     // Annotate typenames and C++ scope specifiers.
@@ -613,6 +625,13 @@
     Res = ParseCXXIdExpression();
     return ParsePostfixExpressionSuffix(Res);
 
+  case tok::kw_new: // [C++] new-expression
+    // FIXME: ParseCXXIdExpression currently steals :: tokens.
+    return ParseCXXNewExpression();
+
+  case tok::kw_delete: // [C++] delete-expression
+    return ParseCXXDeleteExpression();
+
   case tok::at: {
     SourceLocation AtLoc = ConsumeToken();
     return ParseObjCAtExpression(AtLoc);
Index: lib/Parse/ParseExprCXX.cpp
===================================================================
--- lib/Parse/ParseExprCXX.cpp	(revision 59319)
+++ lib/Parse/ParseExprCXX.cpp	(working copy)
@@ -627,3 +627,231 @@
   else
     return Result.Val;
 }
+
+/// ParseCXXNewExpression - Parse a C++ new-expression. New is used to allocate
+/// memory in a typesafe manner and call constructors.
+///
+///        new-expression:
+///                   '::'[opt] 'new' new-placement[opt] new-type-id
+///                                     new-initializer[opt]
+///                   '::'[opt] 'new' new-placement[opt] '(' type-id ')'
+///                                     new-initializer[opt]
+///
+///        new-placement:
+///                   '(' expression-list ')'
+///
+///        new-initializer:
+///                   '(' expression-list[opt] ')'
+///
+Parser::ExprResult Parser::ParseCXXNewExpression()
+{
+  assert((Tok.is(tok::coloncolon) || Tok.is(tok::kw_new)) &&
+         "Expected :: or 'new' keyword");
+
+  SourceLocation Start = Tok.getLocation();
+  bool UseGlobal = false;
+  if (Tok.is(tok::coloncolon)) {
+    UseGlobal = true;
+    ConsumeToken();
+  }
+
+  assert(Tok.is(tok::kw_new) && "Lookahead should have ensured 'new'");
+  // Consume 'new'
+  ConsumeToken();
+
+  // A '(' now can be a new-placement or the '(' wrapping the type-id in the
+  // second form of new-expression. It can't be a new-type-id.
+
+  ExprListTy PlacementArgs;
+  SourceLocation PlacementLParen, PlacementRParen;
+
+  TypeTy *Ty = 0;
+  ExprTy *ArraySize = 0;
+  SourceLocation TyStart, TyEnd;
+  if (Tok.is(tok::l_paren)) {
+    // If it turns out to be a placement, we change the type location.
+    PlacementLParen = ConsumeParen();
+    TyStart = Tok.getLocation();
+    if (ParseExpressionListOrTypeId(PlacementArgs, Ty))
+      return true;
+    TyEnd = Tok.getLocation();
+
+    PlacementRParen = MatchRHSPunctuation(tok::r_paren, PlacementLParen);
+    if (PlacementRParen.isInvalid())
+      return true;
+
+    if (Ty) {
+      // Reset the placement locations. There was no placement.
+      PlacementLParen = PlacementRParen = SourceLocation();
+    } else {
+      // We still need the type.
+      if (Tok.is(tok::l_paren)) {
+        ConsumeParen();
+        TyStart = Tok.getLocation();
+        Ty = ParseTypeName();
+      } else {
+        TyStart = Tok.getLocation();
+        Ty = ParseNewTypeId(ArraySize);
+      }
+      if (!Ty)
+        return true;
+      TyEnd = Tok.getLocation();
+    }
+  } else {
+    TyStart = Tok.getLocation();
+    Ty = ParseNewTypeId(ArraySize);
+    if (!Ty)
+      return true;
+    TyEnd = Tok.getLocation();
+  }
+
+  ExprListTy ConstructorArgs;
+  SourceLocation ConstructorLParen, ConstructorRParen;
+
+  if (Tok.is(tok::l_paren)) {
+    ConstructorLParen = ConsumeParen();
+    if (Tok.isNot(tok::r_paren)) {
+      CommaLocsTy CommaLocs;
+      if (ParseExpressionList(ConstructorArgs, CommaLocs))
+        return true;
+    }
+    ConstructorRParen = MatchRHSPunctuation(tok::r_paren, ConstructorLParen);
+    if (ConstructorRParen.isInvalid())
+      return true;
+  }
+
+  return Actions.ActOnCXXNew(Start, UseGlobal, PlacementLParen,
+                             &PlacementArgs[0], PlacementArgs.size(),
+                             PlacementRParen, TyStart, Ty, ArraySize, TyEnd,
+                             ConstructorLParen, &ConstructorArgs[0],
+                             ConstructorArgs.size(), ConstructorRParen);
+}
+
+/// ParseNewTypeId - Parses a type ID as it appears in a new expression.
+/// The most interesting part of this is the new-declarator, which can be a
+/// multi-dimensional array, of which the first has a non-constant expression as
+/// the size, e.g.
+/// @code new int[runtimeSize()][2][2] @endcode
+///
+///        new-type-id:
+///                   type-specifier-seq new-declarator[opt]
+///
+///        new-declarator:
+///                   ptr-operator new-declarator[opt]
+///                   direct-new-declarator
+///
+///        direct-new-declarator:
+///                   '[' expression ']'
+///                   direct-new-declarator '[' constant-expression ']'
+///
+Parser::TypeTy * Parser::ParseNewTypeId(ExprTy *&ArraySize)
+{
+  DeclSpec DS;
+  if (ParseCXXTypeSpecifierSeq(DS))
+    return 0;
+
+  // A new-declarator is a simplified version of a declarator. We use
+  // ParseDeclaratorInternal in PtrOperator mode to get the pointer operators
+  // out of the way.
+  Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
+  ParseDeclaratorInternal(DeclaratorInfo, true);
+
+  // Parse the array dimensions. The first can have a variable size and does
+  // not become part of the type. The others are dutifully added to the
+  // declarator.
+  if (Tok.is(tok::l_square)) {
+    SourceLocation LLoc = ConsumeBracket();
+    ExprResult Size = ParseExpression();
+    if (Size.isInvalid) {
+      // Recover
+      SkipUntil(tok::r_square);
+      return 0;
+    }
+    ArraySize = Size.Val;
+
+    if (MatchRHSPunctuation(tok::r_square, LLoc).isInvalid())
+      return 0;
+
+    while (Tok.is(tok::l_square)) {
+      LLoc = ConsumeBracket();
+      Size = ParseConstantExpression();
+      if (Size.isInvalid) {
+        // Recover
+        SkipUntil(tok::r_square);
+        return 0;
+      }
+
+      DeclaratorInfo.AddTypeInfo(
+        DeclaratorChunk::getArray(0, /*static=*/false, /*star=*/false,
+                                  Size.Val, LLoc));
+
+      if (MatchRHSPunctuation(tok::r_square, LLoc).isInvalid())
+        return 0;
+    }
+  }
+
+  return Actions.ActOnTypeName(CurScope, DeclaratorInfo).Val;
+}
+
+/// ParseExpressionListOrTypeId - Parse either an expression-list or a type-id.
+/// This ambiguity appears in the syntax of the C++ new operator.
+///
+///        new-expression:
+///                   '::'[opt] 'new' new-placement[opt] '(' type-id ')'
+///                                     new-initializer[opt]
+///
+///        new-placement:
+///                   '(' expression-list ')'
+///
+bool Parser::ParseExpressionListOrTypeId(ExprListTy &PlacementArgs, TypeTy *&Ty)
+{
+  // The '(' was alrady consumed.
+  if (isTypeIdInParens()) {
+    Ty = ParseTypeName();
+    return false;
+  }
+
+  // It's not a type, it has to be an expression list.
+  // Discard the comma locations - ActOnCXXNew has enough parameters.
+  CommaLocsTy CommaLocs;
+  return ParseExpressionList(PlacementArgs, CommaLocs);
+}
+
+/// ParseCXXDeleteExpression - Parse a C++ delete-expression. Delete is used
+/// to free memory allocated by new.
+///
+///        delete-expression:
+///                   '::'[opt] 'delete' cast-expression
+///                   '::'[opt] 'delete' '[' ']' cast-expression
+Parser::ExprResult Parser::ParseCXXDeleteExpression()
+{
+  assert((Tok.is(tok::coloncolon) || Tok.is(tok::kw_delete)) &&
+         "Expected :: or 'delete' keyword");
+
+  SourceLocation Start = Tok.getLocation();
+  bool UseGlobal = false;
+  if (Tok.is(tok::coloncolon)) {
+    UseGlobal = true;
+    ConsumeToken();
+  }
+
+  assert(Tok.is(tok::kw_delete) && "Lookahead should have ensured 'delete'");
+  // Consume 'delete'
+  ConsumeToken();
+
+  // Array delete?
+  bool ArrayDelete = false;
+  if (Tok.is(tok::l_square)) {
+    ArrayDelete = true;
+    SourceLocation LHS = ConsumeBracket();
+    SourceLocation RHS = MatchRHSPunctuation(tok::r_square, LHS);
+    if (RHS.isInvalid())
+      return true;
+  }
+
+  ExprResult Operand = ParseCastExpression(false);
+  if (Operand.isInvalid)
+    return Operand;
+
+  return Actions.ActOnCXXDelete(Start, UseGlobal, ArrayDelete, Operand.Val);
+}
