Handle new by passing the Declaration to the Action, not a processed type.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@60413 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp
index c0f2985..1bf07c4 100644
--- a/lib/AST/ExprCXX.cpp
+++ b/lib/AST/ExprCXX.cpp
@@ -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
diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index b6f0707..445e3e4 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -953,6 +953,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 << ")";
diff --git a/lib/AST/StmtSerialization.cpp b/lib/AST/StmtSerialization.cpp
index 40f5b3f..a860224 100644
--- a/lib/AST/StmtSerialization.cpp
+++ b/lib/AST/StmtSerialization.cpp
@@ -1444,7 +1444,10 @@
 
 void CXXNewExpr::EmitImpl(Serializer& S) const {
   S.Emit(getType());
-  S.Emit(Initializer);
+  S.EmitBool(GlobalNew);
+  S.EmitBool(ParenTypeId);
+  S.EmitBool(Initializer);
+  S.EmitBool(Array);
   S.EmitInt(NumPlacementArgs);
   S.EmitInt(NumConstructorArgs);
   S.BatchEmitOwnedPtrs(NumPlacementArgs + NumConstructorArgs, SubExprs);
@@ -1455,7 +1458,6 @@
   S.EmitPtr(OperatorNew);
   S.EmitPtr(OperatorDelete);
   S.EmitPtr(Constructor);
-  S.Emit(AllocType);
   S.Emit(StartLoc);
   S.Emit(EndLoc);
 }
@@ -1466,19 +1468,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);
@@ -1486,8 +1488,8 @@
 
 void CXXDeleteExpr::EmitImpl(Serializer& S) const {
   S.Emit(getType());
-  S.Emit(GlobalDelete);
-  S.Emit(ArrayForm);
+  S.EmitBool(GlobalDelete);
+  S.EmitBool(ArrayForm);
   S.EmitPtr(OperatorDelete);
   S.EmitOwnedPtr(Argument);
   S.Emit(Loc);
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 192c70a..c3bbb52 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -28,9 +28,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);
@@ -39,7 +37,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.
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index 09aea03..d995b88 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -645,6 +645,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]
@@ -671,49 +678,58 @@
   ExprVector PlacementArgs(Actions);
   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)) {
+      SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
       return true;
-    TyEnd = Tok.getLocation();
+    }
 
     PlacementRParen = MatchRHSPunctuation(tok::r_paren, PlacementLParen);
-    if (PlacementRParen.isInvalid())
+    if (PlacementRParen.isInvalid()) {
+      SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
       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();
+        ParseSpecifierQualifierList(DS);
+        ParseDeclarator(DeclaratorInfo);
+        MatchRHSPunctuation(tok::r_paren, LParen);
         ParenTypeId = true;
       } else {
-        TyStart = Tok.getLocation();
-        Ty = ParseNewTypeId();
+        if (ParseCXXTypeSpecifierSeq(DS))
+          DeclaratorInfo.setInvalidType(true);
+        else
+          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.
+    if (ParseCXXTypeSpecifierSeq(DS))
+      DeclaratorInfo.setInvalidType(true);
+    else
+      ParseDeclaratorInternal(DeclaratorInfo,
+                              &Parser::ParseDirectNewDeclarator);
     ParenTypeId = false;
   }
+  if (DeclaratorInfo.getInvalidType()) {
+    SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
+    return true;
+  }
 
   ExprVector ConstructorArgs(Actions);
   SourceLocation ConstructorLParen, ConstructorRParen;
@@ -722,51 +738,25 @@
     ConstructorLParen = ConsumeParen();
     if (Tok.isNot(tok::r_paren)) {
       CommaLocsTy CommaLocs;
-      if (ParseExpressionList(ConstructorArgs, CommaLocs))
+      if (ParseExpressionList(ConstructorArgs, CommaLocs)) {
+        SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
         return true;
+      }
     }
     ConstructorRParen = MatchRHSPunctuation(tok::r_paren, ConstructorLParen);
-    if (ConstructorRParen.isInvalid())
+    if (ConstructorRParen.isInvalid()) {
+      SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
       return true;
+    }
   }
 
   return Actions.ActOnCXXNew(Start, UseGlobal, PlacementLParen,
                              PlacementArgs.take(), PlacementArgs.size(),
-                             PlacementRParen, ParenTypeId, TyStart, Ty, TyEnd,
+                             PlacementRParen, ParenTypeId, DeclaratorInfo,
                              ConstructorLParen, ConstructorArgs.take(),
                              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.
 ///
@@ -806,12 +796,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.
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 6f1cf88..7f3d0f4 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -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.
@@ -828,13 +826,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,
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 3633da8..bfc367d 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -180,30 +180,60 @@
                   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.
 
-  // Validate the type, and unwrap an array if any.
-  if (CheckAllocatedType(CheckType, StartLoc, SourceRange(TyStart, TyEnd)))
+  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;
 
-  QualType ResultType = Context.getPointerType(CheckType);
+  if (CheckAllocatedType(AllocType, D))
+    return true;
+
+  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.
+  if (ArraySize) {
+    QualType SizeType = ArraySize->getType();
+    if (!SizeType->isIntegralType() && !SizeType->isEnumeralType())
+      return Diag(ArraySize->getSourceRange().getBegin(),
+                  diag::err_array_size_not_integral)
+        << SizeType << ArraySize->getSourceRange();
+    // Let's see if this is a constant < 0. If so, we reject it out of hand.
+    // We don't care about special rules, so we tell the machinery it's not
+    // evaluated - it gives us a result in more cases.
+    llvm::APSInt Value;
+    if (ArraySize->isIntegerConstantExpr(Value, Context, 0, false)) {
+      if (Value < llvm::APSInt(
+                      llvm::APInt::getNullValue(Value.getBitWidth()), false))
+        return Diag(ArraySize->getSourceRange().getBegin(),
+                    diag::err_typecheck_negative_array_size)
+          << ArraySize->getSourceRange();
+    }
+  }
 
   // --- Choosing an allocation function ---
   // C++ 5.3.4p8 - 14 & 18
@@ -239,12 +269,14 @@
   // 2) Otherwise, the object is direct-initialized.
   CXXConstructorDecl *Constructor = 0;
   Expr **ConsArgs = (Expr**)ConstructorArgs;
-  if (const RecordType *RT = CheckType->getAsRecordType()) {
+  if (const RecordType *RT = AllocType->getAsRecordType()) {
     // 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),
+                      AllocType, ConsArgs, NumConsArgs,
+                      D.getDeclSpec().getSourceRange().getBegin(),
+                      SourceRange(D.getDeclSpec().getSourceRange().getBegin(),
+                                  ConstructorRParen),
                       RT->getDecl()->getDeclName(),
                       NumConsArgs != 0 ? IK_Direct : IK_Default);
     if (!Constructor)
@@ -252,9 +284,9 @@
   } 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) {
@@ -262,8 +294,8 @@
     } else if (NumConsArgs == 1) {
       // Object is direct-initialized.
       // FIXME: WHAT DeclarationName do we pass in here?
-      if (CheckInitializerTypes(ConsArgs[0], CheckType, StartLoc,
-                                DeclarationName() /*CheckType.getAsString()*/))
+      if (CheckInitializerTypes(ConsArgs[0], AllocType, StartLoc,
+                                DeclarationName() /*AllocType.getAsString()*/))
         return true;
     } else {
       Diag(StartLoc, diag::err_builtin_direct_init_more_than_one_arg)
@@ -274,16 +306,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.
@@ -291,29 +322,34 @@
   // FIXME: Under C++ semantics, an incomplete object type is still an object
   // type. This code assumes the C semantics, where it's not.
   if (!AllocType->isObjectType()) {
-    diag::kind msg;
+    unsigned type; // For the select in the message.
     if (AllocType->isFunctionType()) {
-      msg = diag::err_new_function;
+      type = 0;
     } else if(AllocType->isIncompleteType()) {
-      msg = diag::err_new_incomplete;
-    } else if(AllocType->isReferenceType()) {
-      msg = diag::err_new_reference;
+      type = 1;
     } else {
-      assert(false && "Unexpected type class");
-      return true;
+      assert(AllocType->isReferenceType() && "What else could it be?");
+      type = 2;
     }
-    Diag(StartLoc, msg) << AllocType << 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(), diag::err_bad_new_type)
+      << AllocType.getAsString() << type << 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;
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index d878e46..4487c1e 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -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;
@@ -394,11 +392,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
@@ -418,9 +414,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);
@@ -617,12 +611,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");