diff --git a/clang/Lex/Preprocessor.cpp b/clang/Lex/Preprocessor.cpp index 8facc3cce08d..e99f34e0c761 100644 --- a/clang/Lex/Preprocessor.cpp +++ b/clang/Lex/Preprocessor.cpp @@ -1067,6 +1067,13 @@ void Preprocessor::DiscardUntilEndOfDirective() { } while (Tmp.getKind() != tok::eom); } +/// isCXXNamedOperator - Returns "true" if the token is a named operator in C++. +static bool isCXXNamedOperator(const std::string &Spelling) { + return Spelling == "and" || Spelling == "bitand" || Spelling == "bitor" || + Spelling == "compl" || Spelling == "not" || Spelling == "not_eq" || + Spelling == "or" || Spelling == "xor"; +} + /// ReadMacroName - Lex and validate a macro name, which occurs after a /// #define or #undef. This sets the token kind to eom and discards the rest /// of the macro line if the macro name is invalid. isDefineUndef is 1 if @@ -1082,11 +1089,14 @@ void Preprocessor::ReadMacroName(LexerToken &MacroNameTok, char isDefineUndef) { IdentifierInfo *II = MacroNameTok.getIdentifierInfo(); if (II == 0) { - Diag(MacroNameTok, diag::err_pp_macro_not_identifier); + std::string Spelling = getSpelling(MacroNameTok); + if (isCXXNamedOperator(Spelling)) + // C++ 2.5p2: Alternative tokens behave the same as its primary token + // except for their spellings. + Diag(MacroNameTok, diag::err_pp_operator_used_as_macro_name, Spelling); + else + Diag(MacroNameTok, diag::err_pp_macro_not_identifier); // Fall through on error. - } else if (0) { - // FIXME: C++. Error if defining a C++ named operator. - } else if (isDefineUndef && II->getPPKeywordID() == tok::pp_defined) { // Error if defining "defined": C99 6.10.8.4. Diag(MacroNameTok, diag::err_defined_macro_name); diff --git a/clang/include/clang/Basic/DiagnosticKinds.def b/clang/include/clang/Basic/DiagnosticKinds.def index 1e44c90dd5ec..1dae508eaeb9 100644 --- a/clang/include/clang/Basic/DiagnosticKinds.def +++ b/clang/include/clang/Basic/DiagnosticKinds.def @@ -232,6 +232,8 @@ DIAG(err_too_few_args_in_macro_invoc, ERROR, "too few arguments provided to function-like macro invocation") DIAG(err_pp_bad_paste, ERROR, "pasting formed \"%s\", an invalid preprocessing token") +DIAG(err_pp_operator_used_as_macro_name, ERROR, + "C++ operator \"%s\" cannot be used as a macro name") // Should be a sorry? DIAG(err_pp_I_dash_not_supported, ERROR,