Index: test/SemaCXX/new-delete.cpp
===================================================================
--- test/SemaCXX/new-delete.cpp	(revision 59868)
+++ test/SemaCXX/new-delete.cpp	(working copy)
@@ -14,7 +14,7 @@
   pi = new int('c');
   const int *pci = new const int();
   S *ps = new S(1, 2, 3.4);
-  ps = new (pf) S(1, 2, 3.4);
+  ps = new (pf) (S)(1, 2, 3.4);
   S *(*paps)[2] = new S*[*pi][2];
   ps = new (S[3])(1, 2, 3.4);
   typedef int ia4[4];
Index: include/clang/Basic/DiagnosticKinds.def
===================================================================
--- include/clang/Basic/DiagnosticKinds.def	(revision 59871)
+++ include/clang/Basic/DiagnosticKinds.def	(working copy)
@@ -1187,6 +1187,10 @@
 // Other C++ expressions
 DIAG(err_need_header_before_typeid, ERROR,
      "you need to include <typeinfo> before using the 'typeid' operator")
+DIAG(err_static_illegal_in_new, ERROR,
+     "the 'static' modifier for the array size is not legal in new expressions")
+DIAG(err_array_new_needs_size, ERROR,
+     "array size must be specified in new expressions")
 DIAG(err_new_function, ERROR,
      "cannot allocate function type '%0' with new")
 DIAG(err_new_incomplete, ERROR,
Index: include/clang/AST/ExprCXX.h
===================================================================
--- include/clang/AST/ExprCXX.h	(revision 59868)
+++ include/clang/AST/ExprCXX.h	(working copy)
@@ -445,13 +445,16 @@
   // Is there an initializer? If not, built-ins are uninitialized, else they're
   // value-initialized.
   bool Initializer : 1;
+  // Do we allocate an array? If so, the first SubExpr is the size expression.
+  bool Array : 1;
   // The number of placement new arguments.
   unsigned NumPlacementArgs : 14;
   // The number of constructor arguments. This may be 1 even for non-class
   // types; use the pseudo copy constructor.
-  unsigned NumConstructorArgs : 15;
-  // Contains any number of optional placement arguments, and any number of
-  // optional constructor arguments, in that order.
+  unsigned NumConstructorArgs : 14;
+  // Contains an optional array 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.
   FunctionDecl *OperatorNew;
@@ -461,29 +464,25 @@
   // it would still point at the default constructor (even an implicit one).
   // Must be null for all other types.
   CXXConstructorDecl *Constructor;
-  // The type to be allocated. Is either *ty or a VLA of that type.
-  QualType AllocType;
 
   SourceLocation StartLoc;
   SourceLocation EndLoc;
 
   // Deserialization constructor
-  CXXNewExpr(QualType ty, QualType alloc, bool globalNew, bool parenTypeId,
-             bool initializer, unsigned numPlacementArgs,
-             unsigned numConstructorArgs, Stmt **subExprs,
-             FunctionDecl *operatorNew, FunctionDecl *operatorDelete,
-             CXXConstructorDecl *constructor, SourceLocation startLoc,
-             SourceLocation endLoc)
+  CXXNewExpr(QualType ty, bool globalNew, bool parenTypeId, bool initializer,
+             bool array, unsigned numPlaceArgs, unsigned numConsArgs,
+             Stmt **subExprs, FunctionDecl *operatorNew,
+             FunctionDecl *operatorDelete, CXXConstructorDecl *constructor,
+             SourceLocation startLoc, SourceLocation endLoc)
     : Expr(CXXNewExprClass, ty), GlobalNew(globalNew), ParenTypeId(parenTypeId),
-      Initializer(initializer), NumPlacementArgs(numPlacementArgs),
-      NumConstructorArgs(numConstructorArgs), SubExprs(subExprs),
+      Initializer(initializer), Array(array), NumPlacementArgs(numPlaceArgs),
+      NumConstructorArgs(numConsArgs), SubExprs(subExprs),
       OperatorNew(operatorNew), OperatorDelete(operatorDelete),
-      Constructor(constructor), AllocType(alloc),
-      StartLoc(startLoc), EndLoc(endLoc)
+      Constructor(constructor), StartLoc(startLoc), EndLoc(endLoc)
   { }
 public:
   CXXNewExpr(bool globalNew, FunctionDecl *operatorNew, Expr **placementArgs,
-             unsigned numPlaceArgs, bool ParenTypeId, QualType alloc,
+             unsigned numPlaceArgs, bool ParenTypeId, Expr *arraySize,
              CXXConstructorDecl *constructor, bool initializer,
              Expr **constructorArgs, unsigned numConsArgs,
              FunctionDecl *operatorDelete, QualType ty,
@@ -492,20 +491,31 @@
     delete[] SubExprs;
   }
 
-  QualType getAllocatedType() const { return AllocType; }
+  QualType getAllocatedType() const {
+    assert(getType()->isPointerType());
+    return getType()->getAsPointerType()->getPointeeType();
+  }
 
   FunctionDecl *getOperatorNew() const { return OperatorNew; }
   FunctionDecl *getOperatorDelete() const { return OperatorDelete; }
   CXXConstructorDecl *getConstructor() const { return Constructor; }
 
+  bool isArray() const { return Array; }
+  Expr *getArraySize() {
+    return Array ? cast<Expr>(SubExprs[0]) : 0;
+  }
+  const Expr *getArraySize() const {
+    return Array ? 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[i]);
+    return cast<Expr>(SubExprs[Array + i]);
   }
   const Expr *getPlacementArg(unsigned i) const {
     assert(i < NumPlacementArgs && "Index out of range");
-    return cast<Expr>(SubExprs[i]);
+    return cast<Expr>(SubExprs[Array + i]);
   }
 
   bool isGlobalNew() const { return GlobalNew; }
@@ -515,40 +525,40 @@
   unsigned getNumConstructorArgs() const { return NumConstructorArgs; }
   Expr *getConstructorArg(unsigned i) {
     assert(i < NumConstructorArgs && "Index out of range");
-    return cast<Expr>(SubExprs[NumPlacementArgs + i]);
+    return cast<Expr>(SubExprs[Array + NumPlacementArgs + i]);
   }
   const Expr *getConstructorArg(unsigned i) const {
     assert(i < NumConstructorArgs && "Index out of range");
-    return cast<Expr>(SubExprs[NumPlacementArgs + i]);
+    return cast<Expr>(SubExprs[Array + NumPlacementArgs + i]);
   }
 
   typedef ExprIterator arg_iterator;
   typedef ConstExprIterator const_arg_iterator;
 
   arg_iterator placement_arg_begin() {
-    return SubExprs;
+    return SubExprs + Array;
   }
   arg_iterator placement_arg_end() {
-    return SubExprs + getNumPlacementArgs();
+    return SubExprs + Array + getNumPlacementArgs();
   }
   const_arg_iterator placement_arg_begin() const {
-    return SubExprs;
+    return SubExprs + Array;
   }
   const_arg_iterator placement_arg_end() const {
-    return SubExprs + getNumPlacementArgs();
+    return SubExprs + Array + getNumPlacementArgs();
   }
 
   arg_iterator constructor_arg_begin() {
-    return SubExprs + getNumPlacementArgs();
+    return SubExprs + Array + getNumPlacementArgs();
   }
   arg_iterator constructor_arg_end() {
-    return SubExprs + getNumPlacementArgs() + getNumConstructorArgs();
+    return SubExprs + Array + getNumPlacementArgs() + getNumConstructorArgs();
   }
   const_arg_iterator constructor_arg_begin() const {
-    return SubExprs + getNumPlacementArgs();
+    return SubExprs + Array + getNumPlacementArgs();
   }
   const_arg_iterator constructor_arg_end() const {
-    return SubExprs + getNumPlacementArgs() + getNumConstructorArgs();
+    return SubExprs + Array + getNumPlacementArgs() + getNumConstructorArgs();
   }
 
   virtual SourceRange getSourceRange() const {
Index: include/clang/Parse/Parser.h
===================================================================
--- include/clang/Parse/Parser.h	(revision 59868)
+++ include/clang/Parse/Parser.h	(working copy)
@@ -511,8 +511,7 @@
   //===--------------------------------------------------------------------===//
   // C++ 5.3.4 and 5.3.5: C++ new and delete
   ExprResult ParseCXXNewExpression();
-  TypeTy *ParseNewTypeId();
-  bool ParseExpressionListOrTypeId(ExprListTy &Exprs, TypeTy *&Ty);
+  bool ParseExpressionListOrTypeId(ExprListTy &Exprs, Declarator &D);
   void ParseDirectNewDeclarator(Declarator &D);
   ExprResult ParseCXXDeleteExpression();
 
@@ -738,7 +737,7 @@
   TPResult TryParseBracketDeclarator();
 
 
-  TypeTy *ParseTypeName(bool CXXNewMode = false);
+  TypeTy *ParseTypeName();
   AttributeList *ParseAttributes();
   void ParseTypeofSpecifier(DeclSpec &DS);
 
Index: include/clang/Parse/Action.h
===================================================================
--- include/clang/Parse/Action.h	(revision 59868)
+++ include/clang/Parse/Action.h	(working copy)
@@ -258,10 +258,7 @@
   //===--------------------------------------------------------------------===//
 
   /// ActOnTypeName - A type-name (type-id in C++) was parsed.
-  /// CXXNewMode is a flag passed by the parser of C++ new-expressions. It
-  /// specifies that the outermost array (if any) must be treated as a VLA.
-  virtual TypeResult ActOnTypeName(Scope *S, Declarator &D,
-                                   bool CXXNewMode = false) {
+  virtual TypeResult ActOnTypeName(Scope *S, Declarator &D) {
     return 0;
   }
   
@@ -754,18 +751,12 @@
   /// 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, Ty will
-  /// be a variable-length array type, with the outermost dimension to be
-  /// allocated dynamically.
-  /// Example:
-  /// @code new int*[rand()][3] @endcode
-  /// Here, Ty will be a VLA with size "rand()" and element type "int*[3]".
+  /// expressions in ConstructorArgs. The type is passed as a declarator.
   virtual ExprResult ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal,
                                  SourceLocation PlacementLParen,
                                  ExprTy **PlacementArgs, unsigned NumPlaceArgs,
                                  SourceLocation PlacementRParen,
-                                 bool ParenTypeId, SourceLocation TyStart,
-                                 TypeTy *Ty, SourceLocation TyEnd,
+                                 bool ParenTypeId, Declarator &D,
                                  SourceLocation ConstructorLParen,
                                  ExprTy **ConstructorArgs, unsigned NumConsArgs,
                                  SourceLocation ConstructorRParen) {
Index: Driver/PrintParserCallbacks.cpp
===================================================================
--- Driver/PrintParserCallbacks.cpp	(revision 59868)
+++ Driver/PrintParserCallbacks.cpp	(working copy)
@@ -168,7 +168,7 @@
     // Type Parsing Callbacks.
     //===--------------------------------------------------------------------===//
   
-    virtual TypeResult ActOnTypeName(Scope *S, Declarator &D, bool CXXNewMode) {
+    virtual TypeResult ActOnTypeName(Scope *S, Declarator &D) {
       llvm::cout << __FUNCTION__ << "\n";
       return 0;
     }
Index: lib/Sema/SemaExprCXX.cpp
===================================================================
--- lib/Sema/SemaExprCXX.cpp	(revision 59868)
+++ lib/Sema/SemaExprCXX.cpp	(working copy)
@@ -180,31 +180,41 @@
                   SourceLocation PlacementLParen,
                   ExprTy **PlacementArgs, unsigned NumPlaceArgs,
                   SourceLocation PlacementRParen, bool ParenTypeId,
-                  SourceLocation TyStart, TypeTy *Ty, SourceLocation TyEnd,
-                  SourceLocation ConstructorLParen,
+                  Declarator &D, SourceLocation ConstructorLParen,
                   ExprTy **ConstructorArgs, unsigned NumConsArgs,
                   SourceLocation ConstructorRParen)
 {
-  QualType AllocType = QualType::getFromOpaquePtr(Ty);
-  QualType CheckType = AllocType;
-  // To leverage the existing parser as much as possible, array types are
-  // parsed as VLAs. Unwrap for checking.
-  if (const VariableArrayType *VLA = Context.getAsVariableArrayType(AllocType)){
-    CheckType = VLA->getElementType();
+  // FIXME: Throughout this function, we have rather bad location information.
+  // Implementing Declarator::getSourceRange() would go a long way toward
+  // fixing that.
+
+  Expr *ArraySize = 0;
+  unsigned Skip = 0;
+  // If the specified type is an array, unwrap it and save the expression.
+  if (D.getNumTypeObjects() > 0 &&
+      D.getTypeObject(0).Kind == DeclaratorChunk::Array) {
+    DeclaratorChunk &Chunk = D.getTypeObject(0);
+    if (Chunk.Arr.hasStatic)
+      return Diag(Chunk.Loc, diag::err_static_illegal_in_new);
+    if (!Chunk.Arr.NumElts)
+      return Diag(Chunk.Loc, diag::err_array_new_needs_size);
+    ArraySize = static_cast<Expr*>(Chunk.Arr.NumElts);
+    Skip = 1;
   }
+  QualType AllocType = GetTypeForDeclarator(D, /*Scope=*/0, Skip);
+  if (D.getInvalidType())
+    return true;
 
-  // Validate the type, and unwrap an array if any.
-  if (CheckAllocatedType(CheckType, StartLoc, SourceRange(TyStart, TyEnd)))
+  if (CheckAllocatedType(AllocType, D))
     return true;
 
-  QualType ResultType = Context.getPointerType(CheckType);
+  QualType ResultType = Context.getPointerType(AllocType);
 
   // That every array dimension except the first is constant was already
   // checked by the type check above.
+
   // C++ 5.3.4p6: "The expression in a direct-new-declarator shall have integral
   //   or enumeration type with a non-negative value."
-  // This was checked by ActOnTypeName, since C99 has the same restriction on
-  // VLA expressions.
 
   // --- Choosing an allocation function ---
   // C++ 5.3.4p8 - 14 & 18
@@ -240,30 +250,32 @@
   // 2) Otherwise, the object is direct-initialized.
   CXXConstructorDecl *Constructor = 0;
   Expr **ConsArgs = (Expr**)ConstructorArgs;
-  if (CheckType->isRecordType()) {
+  if (AllocType->isRecordType()) {
     // FIXME: This is incorrect for when there is an empty initializer and
     // no user-defined constructor. Must zero-initialize, not default-construct.
     Constructor = PerformInitializationByConstructor(
-                      CheckType, ConsArgs, NumConsArgs,
-                      TyStart, SourceRange(TyStart, ConstructorRParen),
-                      CheckType.getAsString(),
+                      AllocType, ConsArgs, NumConsArgs,
+                      D.getDeclSpec().getSourceRange().getBegin(),
+                      SourceRange(D.getDeclSpec().getSourceRange().getBegin(),
+                                  ConstructorRParen),
+                      AllocType.getAsString(),
                       NumConsArgs != 0 ? IK_Direct : IK_Default);
     if (!Constructor)
       return true;
   } else {
     if (!Init) {
       // FIXME: Check that no subpart is const.
-      if (CheckType.isConstQualified()) {
+      if (AllocType.isConstQualified()) {
         Diag(StartLoc, diag::err_new_uninitialized_const)
-          << SourceRange(StartLoc, TyEnd);
+          << D.getSourceRange();
         return true;
       }
     } else if (NumConsArgs == 0) {
       // Object is value-initialized. Do nothing.
     } else if (NumConsArgs == 1) {
       // Object is direct-initialized.
-      if (CheckInitializerTypes(ConsArgs[0], CheckType, StartLoc,
-                                CheckType.getAsString()))
+      if (CheckInitializerTypes(ConsArgs[0], AllocType, StartLoc,
+                                AllocType.getAsString()))
         return true;
     } else {
       Diag(StartLoc, diag::err_builtin_direct_init_more_than_one_arg)
@@ -274,16 +286,15 @@
   // FIXME: Also check that the destructor is accessible. (C++ 5.3.4p16)
 
   return new CXXNewExpr(UseGlobal, OperatorNew, PlaceArgs, NumPlaceArgs,
-                        ParenTypeId, AllocType, Constructor, Init,
+                        ParenTypeId, ArraySize, Constructor, Init,
                         ConsArgs, NumConsArgs, OperatorDelete, ResultType,
-                        StartLoc, Init ? ConstructorRParen : TyEnd);
+                        StartLoc, Init ? ConstructorRParen : SourceLocation());
 }
 
 /// CheckAllocatedType - Checks that a type is suitable as the allocated type
 /// in a new-expression.
 /// dimension off and stores the size expression in ArraySize.
-bool Sema::CheckAllocatedType(QualType AllocType, SourceLocation StartLoc,
-                              const SourceRange &TyR)
+bool Sema::CheckAllocatedType(QualType AllocType, const Declarator &D)
 {
   // C++ 5.3.4p1: "[The] type shall be a complete object type, but not an
   //   abstract class type or array thereof.
@@ -302,18 +313,24 @@
       assert(false && "Unexpected type class");
       return true;
     }
-    Diag(StartLoc, msg) << AllocType.getAsString() << TyR;
+    SourceRange TyR = D.getDeclSpec().getSourceRange();
+    // FIXME: This is very much a guess and won't work for, e.g., pointers.
+    if (D.getNumTypeObjects() > 0)
+      TyR.setEnd(D.getTypeObject(0).Loc);
+    Diag(TyR.getBegin(), msg) << AllocType.getAsString() << TyR;
     return true;
   }
 
-  // Every dimension beyond the first shall be of constant size.
+  // Every dimension shall be of constant size.
+  unsigned i = 1;
   while (const ArrayType *Array = Context.getAsArrayType(AllocType)) {
     if (!Array->isConstantArrayType()) {
-      // FIXME: Might be nice to get a better source range from somewhere.
-      Diag(StartLoc, diag::err_new_array_nonconst) << TyR;
+      Diag(D.getTypeObject(i).Loc, diag::err_new_array_nonconst)
+        << static_cast<Expr*>(D.getTypeObject(i).Arr.NumElts)->getSourceRange();
       return true;
     }
     AllocType = Array->getElementType();
+    ++i;
   }
 
   return false;
Index: lib/Sema/SemaType.cpp
===================================================================
--- lib/Sema/SemaType.cpp	(revision 59868)
+++ lib/Sema/SemaType.cpp	(working copy)
@@ -249,8 +249,8 @@
 }
 
 /// GetTypeForDeclarator - Convert the type for the specified declarator to Type
-/// instances.
-QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, bool CXXNewMode) {
+/// instances. Skip the outermost Skip type objects.
+QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, unsigned Skip) {
   // long long is a C99 feature.
   if (!getLangOptions().C99 && !getLangOptions().CPlusPlus0x &&
       D.getDeclSpec().getTypeSpecWidth() == DeclSpec::TSW_longlong)
@@ -260,8 +260,8 @@
 
   // Walk the DeclTypeInfo, building the recursive type as we go.  DeclTypeInfos
   // are ordered from the identifier out, which is opposite of what we want :).
-  for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
-    DeclaratorChunk &DeclType = D.getTypeObject(e-i-1);
+  for (unsigned i = Skip, e = D.getNumTypeObjects(); i != e; ++i) {
+    DeclaratorChunk &DeclType = D.getTypeObject(e-i-1+Skip);
     switch (DeclType.Kind) {
     default: assert(0 && "Unknown decltype!");
     case DeclaratorChunk::BlockPointer:
@@ -340,8 +340,6 @@
       break;
     }
     case DeclaratorChunk::Array: {
-      // Only the outermost dimension gets special treatment.
-      bool UseCXXNewMode = CXXNewMode && i == e-1;
       DeclaratorChunk::ArrayTypeInfo &ATI = DeclType.Arr;
       Expr *ArraySize = static_cast<Expr*>(ATI.NumElts);
       ArrayType::ArraySizeModifier ASM;
@@ -396,11 +394,9 @@
       if (!ArraySize) {
         T = Context.getIncompleteArrayType(T, ASM, ATI.TypeQuals);
       } else if (!ArraySize->isIntegerConstantExpr(ConstVal, Context) ||
-                 !T->isConstantSizeType() || UseCXXNewMode) {
+                 !T->isConstantSizeType()) {
         // Per C99, a variable array is an array with either a non-constant
         // size or an element type that has a non-constant-size
-        // We also force this for parsing C++ new-expressions, since the
-        // outermost dimension is always treated as variable.
         T = Context.getVariableArrayType(T, ArraySize, ASM, ATI.TypeQuals);
       } else {
         // C99 6.7.5.2p1: If the expression is a constant expression, it shall
@@ -420,9 +416,7 @@
         T = Context.getConstantArrayType(T, ConstVal, ASM, ATI.TypeQuals);
       }
       // If this is not C99, extwarn about VLA's and C99 array size modifiers.
-      // Unless we're in C++ new mode. ActOnCXXNew will complain about them
-      // there, and they're hard errors.
-      if (!getLangOptions().C99 && !CXXNewMode &&
+      if (!getLangOptions().C99 &&
           (ASM != ArrayType::Normal ||
            (ArraySize && !ArraySize->isIntegerConstantExpr(Context))))
         Diag(D.getIdentifierLoc(), diag::ext_vla);
@@ -620,12 +614,12 @@
   return false;
 }
 
-Sema::TypeResult Sema::ActOnTypeName(Scope *S, Declarator &D, bool CXXNewMode) {
+Sema::TypeResult Sema::ActOnTypeName(Scope *S, Declarator &D) {
   // C99 6.7.6: Type names have no identifier.  This is already validated by
   // the parser.
   assert(D.getIdentifier() == 0 && "Type name should have no identifier!");
   
-  QualType T = GetTypeForDeclarator(D, S, CXXNewMode);
+  QualType T = GetTypeForDeclarator(D, S);
 
   assert(!T.isNull() && "GetTypeForDeclarator() returned null type");
   
Index: lib/Sema/Sema.h
===================================================================
--- lib/Sema/Sema.h	(revision 59868)
+++ lib/Sema/Sema.h	(working copy)
@@ -245,16 +245,14 @@
   //
   QualType ConvertDeclSpecToType(const DeclSpec &DS);
   void ProcessTypeAttributeList(QualType &Result, const AttributeList *AL);
-  QualType GetTypeForDeclarator(Declarator &D, Scope *S,
-                                bool CXXNewMode = false);
+  QualType GetTypeForDeclarator(Declarator &D, Scope *S, unsigned Skip = 0);
   DeclarationName GetNameForDeclarator(Declarator &D);
 
   QualType ObjCGetTypeForMethodDefinition(DeclTy *D);
 
   bool UnwrapSimilarPointerTypes(QualType& T1, QualType& T2);
 
-  virtual TypeResult ActOnTypeName(Scope *S, Declarator &D,
-                                   bool CXXNewMode = false);
+  virtual TypeResult ActOnTypeName(Scope *S, Declarator &D);
 
   //===--------------------------------------------------------------------===//
   // Symbol table / Decl tracking callbacks: SemaDecl.cpp.
@@ -819,13 +817,11 @@
                                  SourceLocation PlacementLParen,
                                  ExprTy **PlacementArgs, unsigned NumPlaceArgs,
                                  SourceLocation PlacementRParen,
-                                 bool ParenTypeId, SourceLocation TyStart,
-                                 TypeTy *Ty, SourceLocation TyEnd,
+                                 bool ParenTypeId, Declarator &D,
                                  SourceLocation ConstructorLParen,
                                  ExprTy **ConstructorArgs, unsigned NumConsArgs,
                                  SourceLocation ConstructorRParen);
-  bool CheckAllocatedType(QualType AllocType, SourceLocation StartLoc,
-                          const SourceRange &TyR);
+  bool CheckAllocatedType(QualType AllocType, const Declarator &D);
 
   /// ActOnCXXDelete - Parsed a C++ 'delete' expression
   virtual ExprResult ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
Index: lib/AST/ExprCXX.cpp
===================================================================
--- lib/AST/ExprCXX.cpp	(revision 59868)
+++ lib/AST/ExprCXX.cpp	(working copy)
@@ -80,30 +80,32 @@
 // CXXNewExpr
 CXXNewExpr::CXXNewExpr(bool globalNew, FunctionDecl *operatorNew,
                        Expr **placementArgs, unsigned numPlaceArgs,
-                       bool parenTypeId, QualType alloc,
+                       bool parenTypeId, Expr *arraySize,
                        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),
+    Initializer(initializer), Array(arraySize), NumPlacementArgs(numPlaceArgs),
     NumConstructorArgs(numConsArgs), OperatorNew(operatorNew),
-    OperatorDelete(operatorDelete), Constructor(constructor), AllocType(alloc),
+    OperatorDelete(operatorDelete), Constructor(constructor),
     StartLoc(startLoc), EndLoc(endLoc)
 {
-  unsigned TotalSize = NumPlacementArgs + NumConstructorArgs;
+  unsigned TotalSize = Array + NumPlacementArgs + NumConstructorArgs;
   SubExprs = new Stmt*[TotalSize];
   unsigned i = 0;
-  for(unsigned j = 0; j < NumPlacementArgs; ++j)
+  if (Array)
+    SubExprs[i++] = arraySize;
+  for (unsigned j = 0; j < NumPlacementArgs; ++j)
     SubExprs[i++] = placementArgs[j];
-  for(unsigned j = 0; j < NumConstructorArgs; ++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();
+  return &SubExprs[0] + Array + getNumPlacementArgs() + getNumConstructorArgs();
 }
 
 // CXXDeleteExpr
Index: lib/AST/StmtSerialization.cpp
===================================================================
--- lib/AST/StmtSerialization.cpp	(revision 59868)
+++ lib/AST/StmtSerialization.cpp	(working copy)
@@ -1423,7 +1423,10 @@
 
 void CXXNewExpr::EmitImpl(Serializer& S) const {
   S.Emit(getType());
+  S.Emit(GlobalNew);
+  S.Emit(ParenTypeId);
   S.Emit(Initializer);
+  S.Emit(Array);
   S.Emit(NumPlacementArgs);
   S.Emit(NumConstructorArgs);
   S.BatchEmitOwnedPtrs(NumPlacementArgs + NumConstructorArgs, SubExprs);
@@ -1434,7 +1437,6 @@
   S.EmitPtr(OperatorNew);
   S.EmitPtr(OperatorDelete);
   S.EmitPtr(Constructor);
-  S.Emit(AllocType);
   S.Emit(StartLoc);
   S.Emit(EndLoc);
 }
@@ -1445,19 +1447,19 @@
   bool GlobalNew = D.ReadBool();
   bool ParenTypeId = D.ReadBool();
   bool Initializer = D.ReadBool();
+  bool Array = D.ReadBool();
   unsigned NumPlacementArgs = D.ReadInt();
   unsigned NumConstructorArgs = D.ReadInt();
-  unsigned TotalExprs = NumPlacementArgs + NumConstructorArgs;
+  unsigned TotalExprs = Array + 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,
+  return new CXXNewExpr(T, GlobalNew, ParenTypeId, Initializer, Array,
                         NumPlacementArgs, NumConstructorArgs, SubExprs,
                         OperatorNew, OperatorDelete, Constructor, StartLoc,
                         EndLoc);
Index: lib/AST/StmtPrinter.cpp
===================================================================
--- lib/AST/StmtPrinter.cpp	(revision 59868)
+++ lib/AST/StmtPrinter.cpp	(working copy)
@@ -941,6 +941,9 @@
   }
   if (E->isParenTypeId())
     OS << "(";
+  // FIXME: This doesn't print the dynamic array size. We'd have to split up
+  // the allocated type to correctly emit that, but without an ASTContext,
+  // that's not possible.
   OS << E->getAllocatedType().getAsString();
   if (E->isParenTypeId())
     OS << ")";
Index: lib/Parse/ParseDecl.cpp
===================================================================
--- lib/Parse/ParseDecl.cpp	(revision 59868)
+++ lib/Parse/ParseDecl.cpp	(working copy)
@@ -27,9 +27,7 @@
 ///         specifier-qualifier-list abstract-declarator[opt]
 ///
 /// Called type-id in C++.
-/// CXXNewMode is a special flag used by the parser of C++ new-expressions. It
-/// is simply passed on to ActOnTypeName.
-Parser::TypeTy *Parser::ParseTypeName(bool CXXNewMode) {
+Parser::TypeTy *Parser::ParseTypeName() {
   // Parse the common declaration-specifiers piece.
   DeclSpec DS;
   ParseSpecifierQualifierList(DS);
@@ -38,7 +36,7 @@
   Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
   ParseDeclarator(DeclaratorInfo);
   
-  return Actions.ActOnTypeName(CurScope, DeclaratorInfo, CXXNewMode).Val;
+  return Actions.ActOnTypeName(CurScope, DeclaratorInfo).Val;
 }
 
 /// ParseAttributes - Parse a non-empty attributes list.
Index: lib/Parse/ParseExprCXX.cpp
===================================================================
--- lib/Parse/ParseExprCXX.cpp	(revision 59868)
+++ lib/Parse/ParseExprCXX.cpp	(working copy)
@@ -636,6 +636,13 @@
 ///        new-placement:
 ///                   '(' expression-list ')'
 ///
+///        new-type-id:
+///                   type-specifier-seq new-declarator[opt]
+///
+///        new-declarator:
+///                   ptr-operator new-declarator[opt]
+///                   direct-new-declarator
+///
 ///        new-initializer:
 ///                   '(' expression-list[opt] ')'
 /// [C++0x]           braced-init-list                                   [TODO]
@@ -662,49 +669,46 @@
   ExprListTy PlacementArgs;
   SourceLocation PlacementLParen, PlacementRParen;
 
-  TypeTy *Ty = 0;
-  SourceLocation TyStart, TyEnd;
   bool ParenTypeId;
+  DeclSpec DS;
+  Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
   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))
+    if (ParseExpressionListOrTypeId(PlacementArgs, DeclaratorInfo))
       return true;
-    TyEnd = Tok.getLocation();
 
     PlacementRParen = MatchRHSPunctuation(tok::r_paren, PlacementLParen);
     if (PlacementRParen.isInvalid())
       return true;
 
-    if (Ty) {
+    if (PlacementArgs.empty()) {
       // Reset the placement locations. There was no placement.
       PlacementLParen = PlacementRParen = SourceLocation();
       ParenTypeId = true;
     } else {
       // We still need the type.
       if (Tok.is(tok::l_paren)) {
-        ConsumeParen();
-        TyStart = Tok.getLocation();
-        Ty = ParseTypeName(/*CXXNewMode=*/true);
+        SourceLocation LParen = ConsumeParen();
+        ParseDeclarator(DeclaratorInfo);
+        MatchRHSPunctuation(tok::r_paren, LParen);
         ParenTypeId = true;
       } else {
-        TyStart = Tok.getLocation();
-        Ty = ParseNewTypeId();
+        ParseCXXTypeSpecifierSeq(DS);
+        ParseDeclaratorInternal(DeclaratorInfo,
+                                &Parser::ParseDirectNewDeclarator);
         ParenTypeId = false;
       }
-      if (!Ty)
-        return true;
-      TyEnd = Tok.getLocation();
     }
   } else {
-    TyStart = Tok.getLocation();
-    Ty = ParseNewTypeId();
-    if (!Ty)
-      return true;
-    TyEnd = Tok.getLocation();
+    // A new-type-id is a simplified type-id, where essentially the
+    // direct-declarator is replaced by a direct-new-declarator.
+    ParseCXXTypeSpecifierSeq(DS);
+    ParseDeclaratorInternal(DeclaratorInfo, &Parser::ParseDirectNewDeclarator);
     ParenTypeId = false;
   }
+  if (DeclaratorInfo.getInvalidType())
+    return true;
 
   ExprListTy ConstructorArgs;
   SourceLocation ConstructorLParen, ConstructorRParen;
@@ -723,41 +727,11 @@
 
   return Actions.ActOnCXXNew(Start, UseGlobal, PlacementLParen,
                              &PlacementArgs[0], PlacementArgs.size(),
-                             PlacementRParen, ParenTypeId, TyStart, Ty, TyEnd,
+                             PlacementRParen, ParenTypeId, DeclaratorInfo,
                              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
-///
-Parser::TypeTy * Parser::ParseNewTypeId()
-{
-  DeclSpec DS;
-  if (ParseCXXTypeSpecifierSeq(DS))
-    return 0;
-
-  // A new-declarator is a simplified version of a declarator. We use
-  // ParseDeclaratorInternal, but pass our own direct declarator parser,
-  // one that parses a direct-new-declarator.
-  Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
-  ParseDeclaratorInternal(DeclaratorInfo, &Parser::ParseDirectNewDeclarator);
-
-  TypeTy *Ty = Actions.ActOnTypeName(CurScope, DeclaratorInfo,
-                                     /*CXXNewMode=*/true).Val;
-  return DeclaratorInfo.getInvalidType() ? 0 : Ty;
-}
-
 /// ParseDirectNewDeclarator - Parses a direct-new-declarator. Intended to be
 /// passed to ParseDeclaratorInternal.
 ///
@@ -797,12 +771,14 @@
 ///        new-placement:
 ///                   '(' expression-list ')'
 ///
-bool Parser::ParseExpressionListOrTypeId(ExprListTy &PlacementArgs, TypeTy *&Ty)
+bool Parser::ParseExpressionListOrTypeId(ExprListTy &PlacementArgs,
+                                         Declarator &D)
 {
   // The '(' was already consumed.
   if (isTypeIdInParens()) {
-    Ty = ParseTypeName(/*CXXNewMode=*/true);
-    return Ty == 0;
+    ParseSpecifierQualifierList(D.getMutableDeclSpec());
+    ParseDeclarator(D);
+    return D.getInvalidType();
   }
 
   // It's not a type, it has to be an expression list.
