PR10359: Template declarations which define classes are not permitted to also contain declarators. Previously we would accept code like this:
template<typename T> struct S { } f() { return 0; }
This case now produces a missing ';' diagnostic, since that seems like a much more likely error than an attempt to declare a function or variable in addition to the class template.
Treat this
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@135195 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index d78f372..172049c 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -1291,6 +1291,11 @@
break;
}
+ // C++ [temp]p3 In a template-declaration which defines a class, no
+ // declarator is permitted.
+ if (TemplateInfo.Kind)
+ ExpectedSemi = true;
+
if (ExpectedSemi) {
ExpectAndConsume(tok::semi, diag::err_expected_semi_after_tagdecl,
TagType == DeclSpec::TST_class ? "class"
diff --git a/test/CXX/temp/p3.cpp b/test/CXX/temp/p3.cpp
new file mode 100644
index 0000000..16ebb38
--- /dev/null
+++ b/test/CXX/temp/p3.cpp
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -verify %s
+
+template<typename T> struct S {
+ static int a, b;
+};
+
+template<typename T> int S<T>::a, S<T>::b; // expected-error {{can only declare a single entity}}
+
+// FIXME: the last two diagnostics here are terrible.
+template<typename T> struct A { static A a; } A<T>::a; // expected-error {{expected ';' after struct}} \
+ expected-error {{use of undeclared identifier 'T'}} \
+ expected-error {{cannot name the global scope}} \
+ expected-error {{no member named 'a' in the global namespace}}
+
+template<typename T> struct B { } f(); // expected-error {{expected ';' after struct}} \
+ expected-error {{requires a type specifier}}
+
+template<typename T> struct C { } // expected-error {{expected ';' after struct}}
+
+A<int> c;
diff --git a/test/CXX/temp/temp.res/temp.local/p3.cpp b/test/CXX/temp/temp.res/temp.local/p3.cpp
index 88f8963..54da885 100644
--- a/test/CXX/temp/temp.res/temp.local/p3.cpp
+++ b/test/CXX/temp/temp.res/temp.local/p3.cpp
@@ -22,11 +22,11 @@
namespace PR6717 {
template <typename T>
class WebVector {
- }
+ } // expected-error {{expected ';' after class}}
- WebVector(const WebVector<T>& other) { }
+ WebVector(const WebVector<T>& other) { } // expected-error{{undeclared identifier 'T'}} \
+ expected-error{{requires a type specifier}}
template <typename C>
- WebVector<T>& operator=(const C& other) { } // expected-error{{unknown type name 'WebVector'}} \
- // expected-error{{unqualified-id}}
+ WebVector<T>& operator=(const C& other) { } // expected-error{{undeclared identifier 'T'}}
}
diff --git a/test/SemaCXX/PR9459.cpp b/test/SemaCXX/PR9459.cpp
index dfb242d..2b96f34 100644
--- a/test/SemaCXX/PR9459.cpp
+++ b/test/SemaCXX/PR9459.cpp
@@ -3,5 +3,5 @@
// Don't crash.
template<typename>struct ae_same;
-template<typename>struct ts{}ap()
+template<typename>struct ts{}ap() // expected-error {{expected ';' after struct}} expected-error {{requires a type specifier}}
{ts<a>::ap<ae_same<int>::&ae_same<>>::p(a); }; // expected-error {{use of undeclared identifier 'a'}}
diff --git a/test/SemaTemplate/class-template-decl.cpp b/test/SemaTemplate/class-template-decl.cpp
index e772212..2e84e93 100644
--- a/test/SemaTemplate/class-template-decl.cpp
+++ b/test/SemaTemplate/class-template-decl.cpp
@@ -50,7 +50,7 @@
template<typename T> class X; // expected-error{{expression}}
}
-template<typename T> class X1 { } var; // expected-error{{declared as a template}}
+template<typename T> class X1 var; // expected-error{{declared as a template}}
namespace M {
}