diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp index f0de3f534562..5267ef0ecccb 100644 --- a/clang/lib/Parse/ParseStmt.cpp +++ b/clang/lib/Parse/ParseStmt.cpp @@ -279,6 +279,11 @@ Parser::OwningStmtResult Parser::ParseCaseStatement(AttributeList *Attr) { ConsumeToken(); } + /// We don't want to treat 'case x : y' as a potential typo for 'case x::y'. + /// Disable this form of error recovery while we're parsing the case + /// expression. + ColonProtectionRAIIObject ColonProtection(*this); + OwningExprResult LHS(ParseConstantExpression()); if (LHS.isInvalid()) { SkipUntil(tok::colon); @@ -298,6 +303,8 @@ Parser::OwningStmtResult Parser::ParseCaseStatement(AttributeList *Attr) { return StmtError(); } } + + ColonProtection.restore(); if (Tok.isNot(tok::colon)) { Diag(Tok, diag::err_expected_colon_after) << "'case'"; diff --git a/clang/lib/Parse/RAIIObjectsForParser.h b/clang/lib/Parse/RAIIObjectsForParser.h index d18d2f802633..bacdf29c8ae3 100644 --- a/clang/lib/Parse/RAIIObjectsForParser.h +++ b/clang/lib/Parse/RAIIObjectsForParser.h @@ -50,9 +50,15 @@ namespace clang { P.ColonIsSacred = true; } - ~ColonProtectionRAIIObject() { + /// restore - This can be used to restore the state early, before the dtor + /// is run. + void restore() { P.ColonIsSacred = OldVal; } + + ~ColonProtectionRAIIObject() { + restore(); + } }; } // end namespace clang diff --git a/clang/test/Parser/cxx-stmt.cpp b/clang/test/Parser/cxx-stmt.cpp index 535f40d78057..cc35ba153f6b 100644 --- a/clang/test/Parser/cxx-stmt.cpp +++ b/clang/test/Parser/cxx-stmt.cpp @@ -1,6 +1,6 @@ // RUN: clang-cc -fsyntax-only -verify %s -void f() +void f1() { try { ; @@ -10,7 +10,7 @@ void f() } } -void g() +void f2() { try; // expected-error {{expected '{'}} @@ -24,7 +24,7 @@ void g() catch {} // expected-error {{expected '('}} } -void h() try { +void f3() try { } catch(...) { } @@ -39,3 +39,16 @@ struct A { A::A(char) : i(0) try {} // expected-error {{expected '{' or ','}} A::A(int j) try : i(j) {} catch(...) {} + + + +// PR5740 +struct Type { }; + +enum { Type } Kind; +void f4() { + int i = 0; + switch (Kind) { + case Type: i = 7; break; // no error. + } +} \ No newline at end of file