aboutsummaryrefslogtreecommitdiff
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
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
-rw-r--r--lib/Parse/ParseDeclCXX.cpp15
-rw-r--r--test/Parser/cxx-decl.cpp14
-rw-r--r--test/Parser/cxx0x-decl.cpp25
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<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;
}
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;
+
+}