Enhance the diagnostic for negative array sizes to include the
declaration name of the array when present. This ensures that
a poor-man's C++03 static_assert will include the user error message
often embedded in the name.

Update all the tests to reflect the new wording, and add a test for the
name behavior.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@122802 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index ffef242..bf28070 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2167,6 +2167,8 @@
   "objective-c message has incomplete result type %0">;
 def err_illegal_decl_array_of_references : Error<
   "'%0' declared as array of references of type %1">;
+def err_decl_negative_array_size : Error<
+  "'%0' declared as an array with a negative size">;
 def err_array_star_outside_prototype : Error<
   "star modifier used outside of function prototype">;
 def err_illegal_decl_pointer_to_reference : Error<
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index c70d5be..453531d 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -711,9 +711,12 @@
     // C99 6.7.5.2p1: If the expression is a constant expression, it shall
     // have a value greater than zero.
     if (ConstVal.isSigned() && ConstVal.isNegative()) {
-      Diag(ArraySize->getLocStart(),
-           diag::err_typecheck_negative_array_size)
-        << ArraySize->getSourceRange();
+      if (Entity)
+        Diag(ArraySize->getLocStart(), diag::err_decl_negative_array_size)
+          << getPrintableNameForEntity(Entity) << ArraySize->getSourceRange();
+      else
+        Diag(ArraySize->getLocStart(), diag::err_typecheck_negative_array_size)
+          << ArraySize->getSourceRange();
       return QualType();
     }
     if (ConstVal == 0) {
diff --git a/test/CXX/dcl.decl/dcl.meaning/dcl.array/p1.cpp b/test/CXX/dcl.decl/dcl.meaning/dcl.array/p1.cpp
index f032bf9..bb4a48e 100644
--- a/test/CXX/dcl.decl/dcl.meaning/dcl.array/p1.cpp
+++ b/test/CXX/dcl.decl/dcl.meaning/dcl.array/p1.cpp
@@ -16,7 +16,7 @@
 Abstract ar5[10]; // expected-error {{abstract class}}
 
 // If we have a size, it must be greater than zero.
-int ar6[-1]; // expected-error {{array size is negative}}
+int ar6[-1]; // expected-error {{array with a negative size}}
 int ar7[0u]; // expected-warning {{zero size arrays are an extension}}
 
 // An array with unknown bound is incomplete.
@@ -42,3 +42,13 @@
   typename T::type x; // expected-error {{has no members}}
 };
 S<int> ar10[10]; // expected-note {{requested here}}
+
+// Ensure that negative array size errors include the name of the declared
+// array as this is often used to simulate static_assert with template
+// instantiations, placing the 'error message' in the declarator name.
+int
+user_error_message
+[-1]; // expected-error {{user_error_message}}
+typedef int
+another_user_error_message
+[-1]; // expected-error {{another_user_error_message}}
diff --git a/test/Sema/array-constraint.c b/test/Sema/array-constraint.c
index fe7fdc7..bee33c0 100644
--- a/test/Sema/array-constraint.c
+++ b/test/Sema/array-constraint.c
@@ -36,7 +36,7 @@
 void check_size() {
   float f;
   int size_not_int[f]; // expected-error {{size of array has non-integer type 'float'}}
-  int negative_size[1-2]; // expected-error{{array size is negative}}
+  int negative_size[1-2]; // expected-error{{array with a negative size}}
   int zero_size[0]; // expected-warning{{zero size arrays are an extension}}
 }
 
diff --git a/test/SemaCXX/virtual-override.cpp b/test/SemaCXX/virtual-override.cpp
index ba2b80d..4ea77a3 100644
--- a/test/SemaCXX/virtual-override.cpp
+++ b/test/SemaCXX/virtual-override.cpp
@@ -121,7 +121,7 @@
   struct a { };
   
   template<typename T> struct b : a {
-    int a[sizeof(T) ? -1 : -1]; // expected-error {{array size is negative}}
+    int a[sizeof(T) ? -1 : -1]; // expected-error {{array with a negative size}}
   };
   
   class A {
diff --git a/test/SemaTemplate/attributes.cpp b/test/SemaTemplate/attributes.cpp
index f4c1887..e208bd2 100644
--- a/test/SemaTemplate/attributes.cpp
+++ b/test/SemaTemplate/attributes.cpp
@@ -7,7 +7,7 @@
   };
 
   template <bool X> struct check {
-    int check_failed[X ? 1 : -1]; // expected-error {{array size is negative}}
+    int check_failed[X ? 1 : -1]; // expected-error {{array with a negative size}}
   };
 
   template <int N> struct check_alignment {
diff --git a/test/SemaTemplate/default-expr-arguments.cpp b/test/SemaTemplate/default-expr-arguments.cpp
index 8d54926..5d301be 100644
--- a/test/SemaTemplate/default-expr-arguments.cpp
+++ b/test/SemaTemplate/default-expr-arguments.cpp
@@ -151,7 +151,7 @@
 namespace PR5810 {
   template<typename T>
   struct allocator {
-    allocator() { int a[sizeof(T) ? -1 : -1]; } // expected-error2 {{array size is negative}}
+    allocator() { int a[sizeof(T) ? -1 : -1]; } // expected-error2 {{array with a negative size}}
   };
   
   template<typename T>
diff --git a/test/SemaTemplate/friend-template.cpp b/test/SemaTemplate/friend-template.cpp
index 419ae93..703daea 100644
--- a/test/SemaTemplate/friend-template.cpp
+++ b/test/SemaTemplate/friend-template.cpp
@@ -93,7 +93,7 @@
   };
 
   template<typename T> void f(const A<T>&) {
-    int a[sizeof(T) ? -1 : -1]; // expected-error {{array size is negative}}
+    int a[sizeof(T) ? -1 : -1]; // expected-error {{array with a negative size}}
   }
 
   void f() {
diff --git a/test/SemaTemplate/instantiate-default-assignment-operator.cpp b/test/SemaTemplate/instantiate-default-assignment-operator.cpp
index 8b97f59..31cdef5 100644
--- a/test/SemaTemplate/instantiate-default-assignment-operator.cpp
+++ b/test/SemaTemplate/instantiate-default-assignment-operator.cpp
@@ -1,7 +1,7 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s
 template<typename> struct PassRefPtr { };
 template<typename T> struct RefPtr {
-  RefPtr& operator=(const RefPtr&) { int a[sizeof(T) ? -1 : -1];} // expected-error 2 {{array size is negative}}
+  RefPtr& operator=(const RefPtr&) { int a[sizeof(T) ? -1 : -1];} // expected-error 2 {{array with a negative size}}
   RefPtr& operator=(const PassRefPtr<T>&);
 };
 
diff --git a/test/SemaTemplate/instantiate-expr-4.cpp b/test/SemaTemplate/instantiate-expr-4.cpp
index 11efe5b..d923f2b 100644
--- a/test/SemaTemplate/instantiate-expr-4.cpp
+++ b/test/SemaTemplate/instantiate-expr-4.cpp
@@ -46,8 +46,8 @@
 // Ensure that both the constructor and the destructor are instantiated by
 // checking for parse errors from each.
 template<int N> struct BadX {
-  BadX() { int a[-N]; } // expected-error {{array size is negative}}
-  ~BadX() { int a[-N]; } // expected-error {{array size is negative}}
+  BadX() { int a[-N]; } // expected-error {{array with a negative size}}
+  ~BadX() { int a[-N]; } // expected-error {{array with a negative size}}
 };
 
 template<int N>
diff --git a/test/SemaTemplate/instantiate-member-expr.cpp b/test/SemaTemplate/instantiate-member-expr.cpp
index 6c0e91b..a31569a 100644
--- a/test/SemaTemplate/instantiate-member-expr.cpp
+++ b/test/SemaTemplate/instantiate-member-expr.cpp
@@ -6,7 +6,7 @@
 
 template<typename T>
 struct vector {
-  void push_back(const T&) { int a[sizeof(T) ? -1: -1]; } // expected-error {{array size is negative}}
+  void push_back(const T&) { int a[sizeof(T) ? -1: -1]; } // expected-error {{array with a negative size}}
 };
 
 class ExprEngine {
diff --git a/test/SemaTemplate/instantiate-member-pointers.cpp b/test/SemaTemplate/instantiate-member-pointers.cpp
index dca0f62..0db90e3 100644
--- a/test/SemaTemplate/instantiate-member-pointers.cpp
+++ b/test/SemaTemplate/instantiate-member-pointers.cpp
@@ -61,7 +61,7 @@
     typedef instantiate_function<&S::instantiate> x; // expected-note{{instantiation}}
   };
   template <typename T> void S<T>::instantiate() {
-    int a[(int)sizeof(T)-42]; // expected-error{{array size is negative}}
+    int a[(int)sizeof(T)-42]; // expected-error{{array with a negative size}}
   }
   S<int> s; 
 }