diff options
Diffstat (limited to 'clang/lib/Parse')
| -rw-r--r-- | clang/lib/Parse/ParseDecl.cpp | 17 | ||||
| -rw-r--r-- | clang/lib/Parse/ParseDeclCXX.cpp | 21 | 
2 files changed, 31 insertions, 7 deletions
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 16321491ee8..5c4e898bf62 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -994,9 +994,15 @@ bool Parser::MightBeDeclarator(unsigned Context) {    case tok::amp:    case tok::ampamp: -  case tok::colon: // Might be a typo for '::'.      return getLang().CPlusPlus; +  case tok::l_square: // Might be an attribute on an unnamed bit-field. +    return Context == Declarator::MemberContext && getLang().CPlusPlus0x && +           NextToken().is(tok::l_square); + +  case tok::colon: // Might be a typo for '::' or an unnamed bit-field. +    return Context == Declarator::MemberContext || getLang().CPlusPlus; +    case tok::identifier:      switch (NextToken().getKind()) {      case tok::code_completion: @@ -1019,8 +1025,13 @@ bool Parser::MightBeDeclarator(unsigned Context) {      case tok::colon:        // At namespace scope, 'identifier:' is probably a typo for 'identifier::' -      // and in block scope it's probably a label. -      return getLang().CPlusPlus && Context == Declarator::FileContext; +      // and in block scope it's probably a label. Inside a class definition, +      // this is a bit-field. +      return Context == Declarator::MemberContext || +             (getLang().CPlusPlus && Context == Declarator::FileContext); + +    case tok::identifier: // Possible virt-specifier. +      return getLang().CPlusPlus0x && isCXX0XVirtSpecifier(NextToken());      default:        return false; diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 5bae0e4d2c9..05a346353bf 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -1548,13 +1548,13 @@ void Parser::HandleMemberFunctionDefaultArgs(Declarator& DeclaratorInfo,    }  } -/// isCXX0XVirtSpecifier - Determine whether the next token is a C++0x +/// isCXX0XVirtSpecifier - Determine whether the given token is a C++0x  /// virt-specifier.  ///  ///       virt-specifier:  ///         override  ///         final -VirtSpecifiers::Specifier Parser::isCXX0XVirtSpecifier() const { +VirtSpecifiers::Specifier Parser::isCXX0XVirtSpecifier(const Token &Tok) const {    if (!getLang().CPlusPlus)      return VirtSpecifiers::VS_None; @@ -1896,6 +1896,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,    SmallVector<Decl *, 8> DeclsInGroup;    ExprResult BitfieldSize; +  bool ExpectSemi = true;    while (1) {      // member-declarator: @@ -2023,7 +2024,18 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,        break;      // Consume the comma. -    ConsumeToken(); +    SourceLocation CommaLoc = ConsumeToken(); + +    if (Tok.isAtStartOfLine() && +        !MightBeDeclarator(Declarator::MemberContext)) { +      // This comma was followed by a line-break and something which can't be +      // the start of a declarator. The comma was probably a typo for a +      // semicolon. +      Diag(CommaLoc, diag::err_expected_semi_declaration) +        << FixItHint::CreateReplacement(CommaLoc, ";"); +      ExpectSemi = false; +      break; +    }      // Parse the next declarator.      DeclaratorInfo.clear(); @@ -2039,7 +2051,8 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,        ParseDeclarator(DeclaratorInfo);    } -  if (ExpectAndConsume(tok::semi, diag::err_expected_semi_decl_list)) { +  if (ExpectSemi && +      ExpectAndConsume(tok::semi, diag::err_expected_semi_decl_list)) {      // Skip to end of block or statement.      SkipUntil(tok::r_brace, true, true);      // If we stopped at a ';', eat it.  | 

