diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2013-01-19 03:48:05 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2013-01-19 03:48:05 +0000 |
commit | ba65f505b7cc2551571b299d05d767e0a892aaae (patch) | |
tree | 509827e5964e85dc82200ac60a909ccf77cccb92 /lib/Parse/ParseDeclCXX.cpp | |
parent | dc1088f6201c3fb8f3f97f54c343f7d163fbec06 (diff) |
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
Diffstat (limited to 'lib/Parse/ParseDeclCXX.cpp')
-rw-r--r-- | lib/Parse/ParseDeclCXX.cpp | 15 |
1 files changed, 13 insertions, 2 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<int> ::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; } |