diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -591,6 +591,8 @@ def warn_empty_init_statement : Warning< "empty initialization statement of '%select{if|switch|range-based for}0' " "has no effect">, InGroup, DefaultIgnore; +def err_keyword_as_ident : Error < + "using keyword '%0' as an identifier is not permitted">; // C++ derived classes def err_dup_virtual : Error<"duplicate 'virtual' in base specifier">; diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -6869,6 +6869,13 @@ } } + // Recovery if a keyword is used as an identifier. + if (Tok.getIdentifierInfo() && + Tok.getIdentifierInfo()->isKeyword(getLangOpts())) { + Diag(Tok, diag::err_keyword_as_ident) << PP.getSpelling(Tok); + // Consume the keyword. + ConsumeToken(); + } ParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII, ParmDeclarator.getIdentifierLoc(), Param, std::move(DefArgToks))); diff --git a/clang/test/Parser/cxx-keyword-identifiers.cpp b/clang/test/Parser/cxx-keyword-identifiers.cpp new file mode 100644 --- /dev/null +++ b/clang/test/Parser/cxx-keyword-identifiers.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + + +int foo(int case, int throw, int y) { // expected-error {{using keyword 'case' as an identifier is not permitted}} \ + expected-error {{using keyword 'throw' as}} + // Trailing parameters should be recovered. + y = 1; +} + +void test() { + // FIXME: we shoud improve the dianostics for the following cases. + int case; // expected-error {{expected unqualified-id}} + struct X { + int case; // expected-error {{expected member name or ';'}} + }; +}