From cf6b0a20c697ba8daf2dff3a4cce2a028b33cb48 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Thu, 14 Jul 2011 21:35:26 +0000 Subject: [PATCH] PR10359: Template declarations which define classes are not permitted to also contain declarators. Previously we would accept code like this: template 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 --- lib/Parse/ParseDeclCXX.cpp | 5 +++++ test/CXX/temp/p3.cpp | 20 ++++++++++++++++++++ test/CXX/temp/temp.res/temp.local/p3.cpp | 8 ++++---- test/SemaCXX/PR9459.cpp | 2 +- test/SemaTemplate/class-template-decl.cpp | 2 +- 5 files changed, 31 insertions(+), 6 deletions(-) create mode 100644 test/CXX/temp/p3.cpp diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index d78f3728e1..172049c340 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/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/test/CXX/temp/p3.cpp b/test/CXX/temp/p3.cpp new file mode 100644 index 0000000000..16ebb381fd --- /dev/null +++ b/test/CXX/temp/p3.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -verify %s + +template struct S { + static int a, b; +}; + +template int S::a, S::b; // expected-error {{can only declare a single entity}} + +// FIXME: the last two diagnostics here are terrible. +template struct A { static A a; } A::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 struct B { } f(); // expected-error {{expected ';' after struct}} \ + expected-error {{requires a type specifier}} + +template struct C { } // expected-error {{expected ';' after struct}} + +A c; diff --git a/test/CXX/temp/temp.res/temp.local/p3.cpp b/test/CXX/temp/temp.res/temp.local/p3.cpp index 88f8963e6b..54da8856fe 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 @@ template struct Derived: Base, Base { namespace PR6717 { template class WebVector { - } + } // expected-error {{expected ';' after class}} - WebVector(const WebVector& other) { } + WebVector(const WebVector& other) { } // expected-error{{undeclared identifier 'T'}} \ + expected-error{{requires a type specifier}} template - WebVector& operator=(const C& other) { } // expected-error{{unknown type name 'WebVector'}} \ - // expected-error{{unqualified-id}} + WebVector& operator=(const C& other) { } // expected-error{{undeclared identifier 'T'}} } diff --git a/test/SemaCXX/PR9459.cpp b/test/SemaCXX/PR9459.cpp index dfb242dc59..2b96f34e8a 100644 --- a/test/SemaCXX/PR9459.cpp +++ b/test/SemaCXX/PR9459.cpp @@ -3,5 +3,5 @@ // Don't crash. templatestruct ae_same; -templatestruct ts{}ap() +templatestruct ts{}ap() // expected-error {{expected ';' after struct}} expected-error {{requires a type specifier}} {ts::ap::&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 e7722123f9..2e84e93ead 100644 --- a/test/SemaTemplate/class-template-decl.cpp +++ b/test/SemaTemplate/class-template-decl.cpp @@ -50,7 +50,7 @@ void f() { template class X; // expected-error{{expression}} } -template class X1 { } var; // expected-error{{declared as a template}} +template class X1 var; // expected-error{{declared as a template}} namespace M { } -- 2.50.1