Fix parsing of type-specifier-seq's. Types are syntactically allowed to be
defined here, but not semantically, so

  new struct S {};

is always ill-formed, even if there is a struct S in scope.

We also had a couple of bugs in ParseOptionalTypeSpecifier caused by it being
under-loved (due to it only being used in a few places) so merge it into
ParseDeclarationSpecifiers with a new DeclSpecContext. To avoid regressing, this
required improving ParseDeclarationSpecifiers' diagnostics in some cases. This
also required teaching ParseSpecifierQualifierList about constexpr... which
incidentally fixes an issue where we'd allow the constexpr specifier in other
bad places.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@152549 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.type/p3-0x.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.type/p3-0x.cpp
index 979da29..0b518bb 100644
--- a/test/CXX/dcl.dcl/dcl.spec/dcl.type/p3-0x.cpp
+++ b/test/CXX/dcl.dcl/dcl.spec/dcl.type/p3-0x.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s -fcxx-exceptions
 
 using X = struct { // ok
 };
@@ -7,21 +7,21 @@
 
 class K {
   virtual ~K();
-  // FIXME: Diagnostic could use some work
-  operator struct S {} (); // expected-error{{'operator S' cannot be the name of a variable or data member}} \
-  // expected-error{{expected ';' at end of declaration list}}
+  operator struct S {} (); // expected-error{{'K::S' can not be defined in a type specifier}}
 };
 
+struct A {};
+
 void f() {
   int arr[3] = {1,2,3};
 
   for (struct S { S(int) {} } s : arr) { // expected-error {{types may not be defined in a for range declaration}}
   }
 
-  new struct T {}; // expected-error {{allocation of incomplete type}} expected-note {{forward declaration}}
+  new struct T {}; // expected-error {{'T' can not be defined in a type specifier}}
+  new struct A {}; // expected-error {{'A' can not be defined in a type specifier}}
 
-  // FIXME: the diagnostic here isn't very good
-  try {} catch (struct U {}); // expected-error 3{{}} expected-note 2{{}}
+  try {} catch (struct U {}) {} // expected-error {{'U' can not be defined in a type specifier}}
 
   (void)(struct V { V(int); })0; // expected-error {{'V' can not be defined in a type specifier}}
 
diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p2-0x.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p2-0x.cpp
index 7993489..b06eb01 100644
--- a/test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p2-0x.cpp
+++ b/test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p2-0x.cpp
@@ -17,9 +17,10 @@
   using E = void(int n) throw(); // expected-error {{exception specifications are not allowed in type aliases}}
   using F = void(*)(int n) &&; // expected-error {{pointer to function type cannot have '&&' qualifier}}
   using G = __thread void(int n); // expected-error {{type name does not allow storage class to be specified}}
+  using H = constexpr int; // expected-error {{type name does not allow constexpr specifier}}
 
-  using H = void(int n); // ok
-  using I = void(int n) &&; // ok
+  using Y = void(int n); // ok
+  using Z = void(int n) &&; // ok
 }
 
 namespace IllegalSyntax {
@@ -123,9 +124,8 @@
 }
 
 namespace CWG1044 {
-  // FIXME: this is terrible. one error is plenty.
+  // FIXME: this diagnostic isn't ideal. one diagnostic is enough.
   using T = T; // expected-error {{type name requires a specifier}} \
-                  expected-error {{C++ requires a type specifier}} \
                   expected-error {{expected ';' after alias declaration}}
 }
 
diff --git a/test/CXX/dcl.decl/dcl.name/p1.cpp b/test/CXX/dcl.decl/dcl.name/p1.cpp
index 7586007..9838b4f 100644
--- a/test/CXX/dcl.decl/dcl.name/p1.cpp
+++ b/test/CXX/dcl.decl/dcl.name/p1.cpp
@@ -2,15 +2,19 @@
 
 namespace pr6200 {
   struct v {};
+  enum E { e };
   struct s {
     int i;
     operator struct v() { return v(); };
+    operator enum E() { return e; }
   };
 
   void f()
   {
-    // Neither of these is a declaration.
+    // None of these is a declaration.
     (void)new struct s;
+    (void)new enum E;
     (void)&s::operator struct v;
+    (void)&s::operator enum E;
   }
 }
diff --git a/test/Parser/cxx11-type-specifier.cpp b/test/Parser/cxx11-type-specifier.cpp
new file mode 100644
index 0000000..2e629f3
--- /dev/null
+++ b/test/Parser/cxx11-type-specifier.cpp
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -verify %s -std=c++11 -fcxx-exceptions
+
+// Tests for parsing of type-specifier-seq
+
+struct S {
+  operator constexpr int(); // expected-error{{type name does not allow constexpr}}
+};
+enum E { e };
+
+void f() {
+  try {
+    (void) new constexpr int; // expected-error{{type name does not allow constexpr}}
+  } catch (constexpr int) { // expected-error{{type name does not allow constexpr}}
+  }
+
+  // These parse as type definitions, not as type references with braced
+  // initializers. Sad but true...
+  (void) new struct S {}; // expected-error{{'S' can not be defined in a type specifier}}
+  (void) new enum E { e }; // expected-error{{'E' can not be defined in a type specifier}}
+}
diff --git a/test/Sema/invalid-struct-init.c b/test/Sema/invalid-struct-init.c
index a598d57..000d3ab 100644
--- a/test/Sema/invalid-struct-init.c
+++ b/test/Sema/invalid-struct-init.c
@@ -3,8 +3,6 @@
 typedef struct _zend_module_entry zend_module_entry;
 struct _zend_module_entry {
   _efree((p)); // expected-error{{type name requires a specifier or qualifier}} \
-                  expected-error{{field '_efree' declared as a function}} \
-                  expected-warning {{type specifier missing, defaults to 'int'}} \
                   expected-warning {{type specifier missing, defaults to 'int'}}
   
 };
diff --git a/test/SemaCXX/alias-template.cpp b/test/SemaCXX/alias-template.cpp
index 8911328..484dd33 100644
--- a/test/SemaCXX/alias-template.cpp
+++ b/test/SemaCXX/alias-template.cpp
@@ -14,9 +14,10 @@
   template<typename U> using E = void(int n) throw(); // expected-error {{exception specifications are not allowed in type aliases}}
   template<typename U> using F = void(*)(int n) &&; // expected-error {{pointer to function type cannot have '&&' qualifier}}
   template<typename U> using G = __thread void(int n); // expected-error {{type name does not allow storage class to be specified}}
+  template<typename U> using H = constexpr int; // expected-error {{type name does not allow constexpr specifier}}
 
-  template<typename U> using H = void(int n); // ok
-  template<typename U> using I = void(int n) &&; // ok
+  template<typename U> using Y = void(int n); // ok
+  template<typename U> using Z = void(int n) &&; // ok
 }
 
 namespace IllegalSyntax {
diff --git a/test/SemaCXX/invalid-member-expr.cpp b/test/SemaCXX/invalid-member-expr.cpp
index 37025d9..287d9af 100644
--- a/test/SemaCXX/invalid-member-expr.cpp
+++ b/test/SemaCXX/invalid-member-expr.cpp
@@ -8,7 +8,7 @@
   x.int; // expected-error{{expected unqualified-id}}
   x.~int(); // expected-error{{expected a class name}}
   x.operator; // expected-error{{expected a type}}
-  x.operator typedef; // expected-error{{expected a type}}
+  x.operator typedef; // expected-error{{expected a type}} expected-error{{type name does not allow storage class}}
 }
 
 void test2() {
@@ -17,7 +17,7 @@
   x->int; // expected-error{{expected unqualified-id}}
   x->~int(); // expected-error{{expected a class name}}
   x->operator; // expected-error{{expected a type}}
-  x->operator typedef; // expected-error{{expected a type}}
+  x->operator typedef; // expected-error{{expected a type}} expected-error{{type name does not allow storage class}}
 }
 
 // PR6327
diff --git a/test/SemaCXX/missing-namespace-qualifier-typo-corrections.cpp b/test/SemaCXX/missing-namespace-qualifier-typo-corrections.cpp
index 0351db1..83f8395 100644
--- a/test/SemaCXX/missing-namespace-qualifier-typo-corrections.cpp
+++ b/test/SemaCXX/missing-namespace-qualifier-typo-corrections.cpp
@@ -4,7 +4,7 @@
                                       // expected-note {{'Foobar' declared here}}
 Foobar *my_bar  // expected-error{{unknown type name 'Foobar'; did you mean 'fizbin::Foobar'?}}
     = new Foobar; // expected-error{{unknown type name 'Foobar'; did you mean 'fizbin::Foobar'?}}
-fizbin::Foobar *my_foo = new fizbin::FooBar; // expected-error{{unknown type name 'FooBar'; did you mean 'Foobar'?}}
+fizbin::Foobar *my_foo = new fizbin::FooBar; // expected-error{{no type named 'FooBar' in namespace 'fizbin'; did you mean 'Foobar'?}}
 
 namespace barstool { int toFoobar() { return 1; } } // expected-note 3 {{'barstool::toFoobar' declared here}}
 int Double(int x) { return x + x; }
@@ -64,14 +64,13 @@
 
 // Test case from http://llvm.org/bugs/show_bug.cgi?id=10318
 namespace llvm {
- template <typename T> class GraphWriter {}; // expected-note {{'llvm::GraphWriter' declared here}} \
-                                             // expected-note {{'GraphWriter' declared here}}
+ template <typename T> class GraphWriter {}; // expected-note 3{{declared here}}
 }
 
 struct S {};
 void bar() {
  GraphWriter<S> x; //expected-error{{no template named 'GraphWriter'; did you mean 'llvm::GraphWriter'?}}
- (void)new llvm::GraphWriter; // expected-error {{expected a type}}
+ (void)new llvm::GraphWriter; // expected-error {{use of class template llvm::GraphWriter requires template arguments}}
  (void)new llvm::Graphwriter<S>; // expected-error {{no template named 'Graphwriter' in namespace 'llvm'; did you mean 'GraphWriter'?}}
 }
 
diff --git a/test/SemaCXX/new-delete.cpp b/test/SemaCXX/new-delete.cpp
index 579ec33..88d85ca 100644
--- a/test/SemaCXX/new-delete.cpp
+++ b/test/SemaCXX/new-delete.cpp
@@ -387,7 +387,7 @@
 
 namespace PR7702 {
   void test1() {
-    new DoesNotExist; // expected-error {{expected a type}}
+    new DoesNotExist; // expected-error {{unknown type name 'DoesNotExist'}}
   }
 }
 
diff --git a/test/SemaObjC/property-9.m b/test/SemaObjC/property-9.m
index 60c8fd1..a7668da 100644
--- a/test/SemaObjC/property-9.m
+++ b/test/SemaObjC/property-9.m
@@ -44,8 +44,7 @@
 }
 
 @property (readonly) int; // expected-warning {{declaration does not declare anything}}
-@property (readonly) ; // expected-error {{type name requires a specifier or qualifier}} \
-                          expected-warning {{declaration does not declare anything}}
+@property (readonly) ; // expected-error {{type name requires a specifier or qualifier}}
 @property (readonly) int : 4; // expected-error {{property requires fields to be named}}
 
 
diff --git a/test/SemaTemplate/deduction-crash.cpp b/test/SemaTemplate/deduction-crash.cpp
index fb23eda..cf3899f 100644
--- a/test/SemaTemplate/deduction-crash.cpp
+++ b/test/SemaTemplate/deduction-crash.cpp
@@ -2,7 +2,7 @@
 
 // Note that the error count below doesn't matter. We just want to
 // make sure that the parser doesn't crash.
-// CHECK: 14 errors
+// CHECK: 13 errors
 
 // PR7511
 template<a>