When the type-id or new-type-id of a C++ "new" expression is a typedef
of an array type, use the outermost array bound as the number of
elements to allocate. Fixes PR7147.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@103908 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 48daf84..01da9c1 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -680,10 +680,19 @@
   if (CheckAllocatedType(AllocType, TypeLoc, TypeRange))
     return ExprError();
 
-  QualType ResultType = Context.getPointerType(AllocType);
+  // Per C++0x [expr.new]p5, the type being constructed may be a
+  // typedef of an array type.
+  if (!ArraySizeE.get()) {
+    if (const ConstantArrayType *Array
+                              = Context.getAsConstantArrayType(AllocType)) {
+      ArraySizeE = Owned(new (Context) IntegerLiteral(Array->getSize(),
+                                                      Context.getSizeType(),
+                                                      TypeRange.getEnd()));
+      AllocType = Array->getElementType();
+    }
+  }
 
-  // That every array dimension except the first is constant was already
-  // checked by the type check above.
+  QualType ResultType = Context.getPointerType(AllocType);
 
   // C++ 5.3.4p6: "The expression in a direct-new-declarator shall have integral
   //   or enumeration type with a non-negative value."
diff --git a/test/SemaCXX/new-delete.cpp b/test/SemaCXX/new-delete.cpp
index 763ed2c..7b9b9d4 100644
--- a/test/SemaCXX/new-delete.cpp
+++ b/test/SemaCXX/new-delete.cpp
@@ -24,6 +24,8 @@
 void* operator new(size_t, float*); // expected-note 3 {{candidate}}
 void* operator new(size_t, S); // expected-note 2 {{candidate}}
 
+struct foo { };
+
 void good_news()
 {
   int *pi = new int;
@@ -43,6 +45,14 @@
   pi = new (S(1.0f, 2)) int;
   
   (void)new int[true];
+
+  // PR7147
+  typedef int a[2];
+  foo* f1 = new foo;
+  foo* f2 = new foo[2];
+  typedef foo x[2];
+  typedef foo y[2][2];
+  x* f3 = new y;
 }
 
 struct abstract {