From ba65f505b7cc2551571b299d05d767e0a892aaae Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Sat, 19 Jan 2013 03:48:05 +0000 Subject: [PATCH] Fix five more cases of tokens which can legally follow a type specifier. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@172886 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Parse/ParseDeclCXX.cpp | 15 +++++++++++++-- test/Parser/cxx-decl.cpp | 14 +++++++++++++- test/Parser/cxx0x-decl.cpp | 25 +++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 3 deletions(-) diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 9aa3a8b2af..2c5d142fd7 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -957,6 +957,7 @@ bool Parser::isValidAfterTypeSpecifier(bool CouldBeBitfield) { case tok::semi: // struct foo {...} ; case tok::star: // struct foo {...} * P; case tok::amp: // struct foo {...} & R = ... + case tok::ampamp: // struct foo {...} && R = ... case tok::identifier: // struct foo {...} V ; case tok::r_paren: //(struct foo {...} ) {4} case tok::annot_cxxscope: // struct foo {...} a:: b; @@ -964,7 +965,7 @@ bool Parser::isValidAfterTypeSpecifier(bool CouldBeBitfield) { case tok::annot_template_id: // struct foo {...} a ::b; case tok::l_paren: // struct foo {...} ( x); case tok::comma: // __builtin_offsetof(struct foo{...} , - case tok::kw_operator: // struct foo operator++() {...} + case tok::kw_operator: // struct foo operator ++() {...} return true; case tok::colon: return CouldBeBitfield; // enum E { ... } : 2; @@ -972,7 +973,12 @@ bool Parser::isValidAfterTypeSpecifier(bool CouldBeBitfield) { case tok::kw_const: // struct foo {...} const x; case tok::kw_volatile: // struct foo {...} volatile x; case tok::kw_restrict: // struct foo {...} restrict x; - case tok::kw_inline: // struct foo {...} inline foo() {}; + // Function specifiers + // Note, no 'explicit'. An explicit function must be either a conversion + // operator or a constructor. Either way, it can't have a return type. + case tok::kw_inline: // struct foo inline f(); + case tok::kw_virtual: // struct foo virtual f(); + case tok::kw_friend: // struct foo friend f(); // Storage-class specifiers case tok::kw_static: // struct foo {...} static x; case tok::kw_extern: // struct foo {...} extern x; @@ -980,6 +986,7 @@ bool Parser::isValidAfterTypeSpecifier(bool CouldBeBitfield) { case tok::kw_register: // struct foo {...} register x; case tok::kw_auto: // struct foo {...} auto x; case tok::kw_mutable: // struct foo {...} mutable x; + case tok::kw_thread_local: // struct foo {...} thread_local x; case tok::kw_constexpr: // struct foo {...} constexpr x; // As shown above, type qualifiers and storage class specifiers absolutely // can occur after class specifiers according to the grammar. However, @@ -1004,6 +1011,10 @@ bool Parser::isValidAfterTypeSpecifier(bool CouldBeBitfield) { if (!getLangOpts().CPlusPlus) return true; break; + // C++11 attributes + case tok::l_square: // enum E [[]] x + // Note, no tok::kw_alignas here; alignas cannot appertain to a type. + return getLangOpts().CPlusPlus11 && NextToken().is(tok::l_square); } return false; } diff --git a/test/Parser/cxx-decl.cpp b/test/Parser/cxx-decl.cpp index aa775c8c76..ee292fdae0 100644 --- a/test/Parser/cxx-decl.cpp +++ b/test/Parser/cxx-decl.cpp @@ -134,7 +134,7 @@ struct S { namespace TestIsValidAfterTypeSpecifier { -struct s {}; +struct s {} v; namespace a { struct s operator++(struct s a) @@ -148,6 +148,18 @@ operator++(struct s a) { return a; } } +struct X { + struct s + friend f(); + struct s + virtual f(); +}; + +struct s +&r0 = v; +struct s +bitand r2 = v; + } // PR8380 diff --git a/test/Parser/cxx0x-decl.cpp b/test/Parser/cxx0x-decl.cpp index 1da7dd2833..b9441fd681 100644 --- a/test/Parser/cxx0x-decl.cpp +++ b/test/Parser/cxx0x-decl.cpp @@ -49,3 +49,28 @@ struct ConstexprTrailingReturn { constexpr auto f() -> decltype((n)); }; constexpr const int &ConstexprTrailingReturn::f() const { return n; } + +namespace TestIsValidAfterTypeSpecifier { +struct s {} v; + +// FIXME: We should accept this once we support thread_local. +struct s +thread_local tl; // expected-error {{expected unqualified-id}} + +struct s +&r0 = v; + +struct s +&&r1 = s(); + +struct s +bitand r2 = v; + +struct s +and r3 = s(); + +enum E {}; +enum E +[[]] e; + +} -- 2.50.1