Sebastian Redl wrote:
Sebastian Redl wrote:
I really like the idea of simply passing a Declarator to ActOnCXXNew, though. Ideally, I'd kill the outermost array there and keep its expression, then pass it on to ActOnTypeName to create the type for me. However, for that I'd have to make the chunks removable in Declarator, which they aren't now.
Did it without making the thing mutable. I just taught GetTypeForDeclarator to skip a bit.

So, here's the new patch. There are downsides to this approach, too - for example, statement printing doesn't work quite right if I do it this way.

Next up, I'll go hunting for leaking Exprs throughout Sema. That's a cleanup that's long overdue, I think.
Forgot attachment.
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.
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to