diff options
| author | Richard Smith <richard-llvm@metafoo.co.uk> | 2011-07-14 21:35:26 +0000 |
|---|---|---|
| committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2011-07-14 21:35:26 +0000 |
| commit | 7b8c3c91f4c3781f09113c82fcca835d71eaae15 (patch) | |
| tree | 1d49fa833b90ad340d2c5fc8dacd58716ac5111f /clang | |
| parent | 4036b587df876032248bbe03fcae21d63a6697fe (diff) | |
| download | bcm5719-llvm-7b8c3c91f4c3781f09113c82fcca835d71eaae15.tar.gz bcm5719-llvm-7b8c3c91f4c3781f09113c82fcca835d71eaae15.zip | |
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
llvm-svn: 135195
Diffstat (limited to 'clang')
| -rw-r--r-- | clang/lib/Parse/ParseDeclCXX.cpp | 5 | ||||
| -rw-r--r-- | clang/test/CXX/temp/p3.cpp | 20 | ||||
| -rw-r--r-- | clang/test/CXX/temp/temp.res/temp.local/p3.cpp | 8 | ||||
| -rw-r--r-- | clang/test/SemaCXX/PR9459.cpp | 2 | ||||
| -rw-r--r-- | clang/test/SemaTemplate/class-template-decl.cpp | 2 |
5 files changed, 31 insertions, 6 deletions
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index d78f3728e1b..172049c3405 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -1291,6 +1291,11 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, 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/clang/test/CXX/temp/p3.cpp b/clang/test/CXX/temp/p3.cpp new file mode 100644 index 00000000000..16ebb381fd1 --- /dev/null +++ b/clang/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/clang/test/CXX/temp/temp.res/temp.local/p3.cpp b/clang/test/CXX/temp/temp.res/temp.local/p3.cpp index 88f8963e6b6..54da8856fe4 100644 --- a/clang/test/CXX/temp/temp.res/temp.local/p3.cpp +++ b/clang/test/CXX/temp/temp.res/temp.local/p3.cpp @@ -22,11 +22,11 @@ template <class T> struct Derived: Base<int>, Base<char> { 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/clang/test/SemaCXX/PR9459.cpp b/clang/test/SemaCXX/PR9459.cpp index dfb242dc595..2b96f34e8a7 100644 --- a/clang/test/SemaCXX/PR9459.cpp +++ b/clang/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/clang/test/SemaTemplate/class-template-decl.cpp b/clang/test/SemaTemplate/class-template-decl.cpp index e7722123f9c..2e84e93ead9 100644 --- a/clang/test/SemaTemplate/class-template-decl.cpp +++ b/clang/test/SemaTemplate/class-template-decl.cpp @@ -50,7 +50,7 @@ void f() { 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 { } |

