forked from OSchip/llvm-project
A ':' after an enum-specifier at class scope is a bitfield, not a typo for a ';'.
llvm-svn: 159549
This commit is contained in:
parent
21cca97d95
commit
200f47c65d
|
@ -1949,7 +1949,7 @@ private:
|
|||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// C++ 9: classes [class] and C structs/unions.
|
||||
bool isValidAfterTypeSpecifier();
|
||||
bool isValidAfterTypeSpecifier(bool CouldBeBitfield);
|
||||
void ParseClassSpecifier(tok::TokenKind TagTokKind, SourceLocation TagLoc,
|
||||
DeclSpec &DS, const ParsedTemplateInfo &TemplateInfo,
|
||||
AccessSpecifier AS, bool EnteringContext,
|
||||
|
|
|
@ -3067,9 +3067,10 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
|
|||
TypeResult BaseType;
|
||||
|
||||
// Parse the fixed underlying type.
|
||||
bool CanBeBitfield = getCurScope()->getFlags() & Scope::ClassScope;
|
||||
if (AllowFixedUnderlyingType && Tok.is(tok::colon)) {
|
||||
bool PossibleBitfield = false;
|
||||
if (getCurScope()->getFlags() & Scope::ClassScope) {
|
||||
if (CanBeBitfield) {
|
||||
// If we're in class scope, this can either be an enum declaration with
|
||||
// an underlying type, or a declaration of a bitfield member. We try to
|
||||
// use a simple disambiguation scheme first to catch the common cases
|
||||
|
@ -3158,7 +3159,8 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
|
|||
}
|
||||
} else if (DSC != DSC_type_specifier &&
|
||||
(Tok.is(tok::semi) ||
|
||||
(Tok.isAtStartOfLine() && !isValidAfterTypeSpecifier()))) {
|
||||
(Tok.isAtStartOfLine() &&
|
||||
!isValidAfterTypeSpecifier(CanBeBitfield)))) {
|
||||
TUK = DS.isFriendSpecified() ? Sema::TUK_Friend : Sema::TUK_Declaration;
|
||||
if (Tok.isNot(tok::semi)) {
|
||||
// A semicolon was missing after this declaration. Diagnose and recover.
|
||||
|
@ -3366,7 +3368,8 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) {
|
|||
|
||||
// The next token must be valid after an enum definition. If not, a ';'
|
||||
// was probably forgotten.
|
||||
if (!isValidAfterTypeSpecifier()) {
|
||||
bool CanBeBitfield = getCurScope()->getFlags() & Scope::ClassScope;
|
||||
if (!isValidAfterTypeSpecifier(CanBeBitfield)) {
|
||||
ExpectAndConsume(tok::semi, diag::err_expected_semi_after_tagdecl, "enum");
|
||||
// Push this token back into the preprocessor and change our current token
|
||||
// to ';' so that the rest of the code recovers as though there were an
|
||||
|
|
|
@ -929,7 +929,7 @@ void Parser::ParseMicrosoftInheritanceClassAttributes(ParsedAttributes &attrs) {
|
|||
/// Determine whether the following tokens are valid after a type-specifier
|
||||
/// which could be a standalone declaration. This will conservatively return
|
||||
/// true if there's any doubt, and is appropriate for insert-';' fixits.
|
||||
bool Parser::isValidAfterTypeSpecifier() {
|
||||
bool Parser::isValidAfterTypeSpecifier(bool CouldBeBitfield) {
|
||||
// This switch enumerates the valid "follow" set for type-specifiers.
|
||||
switch (Tok.getKind()) {
|
||||
default: break;
|
||||
|
@ -944,6 +944,8 @@ bool Parser::isValidAfterTypeSpecifier() {
|
|||
case tok::l_paren: // struct foo {...} ( x);
|
||||
case tok::comma: // __builtin_offsetof(struct foo{...} ,
|
||||
return true;
|
||||
case tok::colon:
|
||||
return CouldBeBitfield; // enum E { ... } : 2;
|
||||
// Type qualifiers
|
||||
case tok::kw_const: // struct foo {...} const x;
|
||||
case tok::kw_volatile: // struct foo {...} volatile x;
|
||||
|
@ -1236,7 +1238,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
|
|||
}
|
||||
} else if (DSC != DSC_type_specifier &&
|
||||
(Tok.is(tok::semi) ||
|
||||
(Tok.isAtStartOfLine() && !isValidAfterTypeSpecifier()))) {
|
||||
(Tok.isAtStartOfLine() && !isValidAfterTypeSpecifier(false)))) {
|
||||
TUK = DS.isFriendSpecified() ? Sema::TUK_Friend : Sema::TUK_Declaration;
|
||||
if (Tok.isNot(tok::semi)) {
|
||||
// A semicolon was missing after this declaration. Diagnose and recover.
|
||||
|
@ -1466,7 +1468,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
|
|||
// In a template-declaration which defines a class, no declarator
|
||||
// is permitted.
|
||||
if (TUK == Sema::TUK_Definition &&
|
||||
(TemplateInfo.Kind || !isValidAfterTypeSpecifier())) {
|
||||
(TemplateInfo.Kind || !isValidAfterTypeSpecifier(false))) {
|
||||
ExpectAndConsume(tok::semi, diag::err_expected_semi_after_tagdecl,
|
||||
TagType == DeclSpec::TST_class ? "class" :
|
||||
TagType == DeclSpec::TST_struct ? "struct" : "union");
|
||||
|
|
|
@ -107,3 +107,8 @@ void test18() {
|
|||
int x = 4+(5-12)); // expected-error {{extraneous ')' before ';'}}
|
||||
}
|
||||
|
||||
enum E1 { e1 }: // expected-error {{expected ';'}}
|
||||
struct EnumBitfield {
|
||||
enum E2 { e2 } : 4; // ok
|
||||
struct S { int n; }: // expected-error {{expected ';'}}
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue