aboutsummaryrefslogtreecommitdiff
path: root/lib/Parse/ParseDeclCXX.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2013-01-19 03:48:05 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2013-01-19 03:48:05 +0000
commitba65f505b7cc2551571b299d05d767e0a892aaae (patch)
tree509827e5964e85dc82200ac60a909ccf77cccb92 /lib/Parse/ParseDeclCXX.cpp
parentdc1088f6201c3fb8f3f97f54c343f7d163fbec06 (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.cpp15
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;
}