diff options
-rw-r--r-- | lib/Parse/ParseDeclCXX.cpp | 21 | ||||
-rw-r--r-- | test/Parser/cxx-class.cpp | 17 |
2 files changed, 33 insertions, 5 deletions
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 51cdf6b64e..decb7f9ec5 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -2135,12 +2135,23 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, // Current token is a C++ access specifier. CurAS = AS; SourceLocation ASLoc = Tok.getLocation(); + unsigned TokLength = Tok.getLength(); ConsumeToken(); - if (Tok.is(tok::colon)) - Actions.ActOnAccessSpecifier(AS, ASLoc, Tok.getLocation()); - else - Diag(Tok, diag::err_expected_colon); - ConsumeToken(); + SourceLocation EndLoc; + if (Tok.is(tok::colon)) { + EndLoc = Tok.getLocation(); + ConsumeToken(); + } else if (Tok.is(tok::semi)) { + EndLoc = Tok.getLocation(); + ConsumeToken(); + Diag(EndLoc, diag::err_expected_colon) + << FixItHint::CreateReplacement(EndLoc, ":"); + } else { + EndLoc = ASLoc.getLocWithOffset(TokLength); + Diag(EndLoc, diag::err_expected_colon) + << FixItHint::CreateInsertion(EndLoc, ":"); + } + Actions.ActOnAccessSpecifier(AS, ASLoc, EndLoc); continue; } diff --git a/test/Parser/cxx-class.cpp b/test/Parser/cxx-class.cpp index f863bd198e..1c0d862b30 100644 --- a/test/Parser/cxx-class.cpp +++ b/test/Parser/cxx-class.cpp @@ -40,3 +40,20 @@ typedef union { } y; } bug3177; +// check that we don't consume the token after the access specifier +// when it's not a colon +class D { +public // expected-error{{expected ':'}} + int i; +}; + +// consume the token after the access specifier if it's a semicolon +// that was meant to be a colon +class E { +public; // expected-error{{expected ':'}} + int i; +}; + +// PR11109 must appear at the end of the source file +class pr11109r3 { // expected-note{{to match this '{'}} + public // expected-error{{expected ':'}} expected-error{{expected '}'}} expected-error{{expected ';' after class}} |