summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/lib/Parse/ParseDeclCXX.cpp11
-rw-r--r--clang/test/Parser/atomic.c3
-rw-r--r--clang/test/Parser/cxx0x-decl.cpp5
-rw-r--r--clang/test/Parser/declarators.c2
4 files changed, 17 insertions, 4 deletions
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index d7ed2fa54b4..380b6d77940 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -1066,6 +1066,8 @@ bool Parser::isValidAfterTypeSpecifier(bool CouldBeBitfield) {
case tok::comma: // __builtin_offsetof(struct foo{...} ,
case tok::kw_operator: // struct foo operator ++() {...}
case tok::kw___declspec: // struct foo {...} __declspec(...)
+ case tok::l_square: // void f(struct f [ 3])
+ case tok::ellipsis: // void f(struct f ... [Ns])
return true;
case tok::colon:
return CouldBeBitfield; // enum E { ... } : 2;
@@ -1073,6 +1075,7 @@ 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__Atomic: // struct foo {...} _Atomic x;
// 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.
@@ -1111,10 +1114,6 @@ 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);
case tok::greater:
// template<class T = class X>
return getLangOpts().CPlusPlus;
@@ -1669,7 +1668,11 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
// Also enforce C++ [temp]p3:
// In a template-declaration which defines a class, no declarator
// is permitted.
+ //
+ // After a type-specifier, we don't expect a semicolon. This only happens in
+ // C, since definitions are not permitted in this context in C++.
if (TUK == Sema::TUK_Definition &&
+ (getLangOpts().CPlusPlus || !isTypeSpecifier(DSC)) &&
(TemplateInfo.Kind || !isValidAfterTypeSpecifier(false))) {
if (Tok.isNot(tok::semi)) {
const PrintingPolicy &PPol = Actions.getASTContext().getPrintingPolicy();
diff --git a/clang/test/Parser/atomic.c b/clang/test/Parser/atomic.c
index 432deeb59c1..07a83dddcd3 100644
--- a/clang/test/Parser/atomic.c
+++ b/clang/test/Parser/atomic.c
@@ -33,3 +33,6 @@ typedef _Atomic(int) __attribute__((address_space(1))) atomic_addr_space_int;
typedef _Atomic int __attribute__((vector_size(16))) atomic_vector_int;
typedef _Atomic(int __attribute__((vector_size(16)))) atomic_vector_int;
+
+struct S
+_Atomic atomic_s_no_missing_semicolon;
diff --git a/clang/test/Parser/cxx0x-decl.cpp b/clang/test/Parser/cxx0x-decl.cpp
index a0334cdde29..2cd68252133 100644
--- a/clang/test/Parser/cxx0x-decl.cpp
+++ b/clang/test/Parser/cxx0x-decl.cpp
@@ -122,3 +122,8 @@ struct MemberComponentOrder : Base {
void g() __attribute__(( )) override;
void h() __attribute__(( )) override {}
};
+
+void NoMissingSemicolonHere(struct S
+ [3]);
+template<int ...N> void NoMissingSemicolonHereEither(struct S
+ ... [N]);
diff --git a/clang/test/Parser/declarators.c b/clang/test/Parser/declarators.c
index e3024206e4f..48936d59226 100644
--- a/clang/test/Parser/declarators.c
+++ b/clang/test/Parser/declarators.c
@@ -150,3 +150,5 @@ enum E16 {
A6; // expected-error{{expected '= constant-expression' or end of enumerator definition}}
A6a
};
+
+int PR20634 = sizeof(struct { int n; } [5]);
OpenPOWER on IntegriCloud