]> granicus.if.org Git - clang/commitdiff
A ':' after an enum-specifier at class scope is a bitfield, not a typo for a ';'.
authorRichard Smith <richard-llvm@metafoo.co.uk>
Mon, 2 Jul 2012 19:14:01 +0000 (19:14 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Mon, 2 Jul 2012 19:14:01 +0000 (19:14 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@159549 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Parse/Parser.h
lib/Parse/ParseDecl.cpp
lib/Parse/ParseDeclCXX.cpp
test/Parser/declarators.c

index 895cd04fd9da5dcd0bd91eaa5dbc338ebcb22e46..8fd597e1cf02dc50dfabdff5185a04c6520be53c 100644 (file)
@@ -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,
index c6db497a53d41c0b60251a5a22471723419e102e..c61f5543a63dd059f5afa2e5f42caa200c0c3fde 100644 (file)
@@ -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
index 23855cdf291f460c16f60b4a702298425a543879..8e357f7e42dcc7935755f0c894b82aabff02c224 100644 (file)
@@ -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");
index 476a9af0fd9b7e68047d28a1de7177a24b2d2a3d..f63b59f7caa64bf0a236bacbfa1a451018a642ae 100644 (file)
@@ -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 ';'}}
+};