From c5d194fcd3ea30bf3162bdea61e6d0ca67da8cb8 Mon Sep 17 00:00:00 2001 From: Alp Toker Date: Sat, 31 May 2014 03:38:17 +0000 Subject: [PATCH] Preprocessor: recover gracefully when C++ operator names are used as macro identifiers This failure mode shows up occasionally when users try to include C headers in C++ projects or when porting from Windows. We might as well recover in the way the user expected, thus avoiding confusing diagnostic messages at point of use. llvm-svn: 209963 --- clang/include/clang/Basic/DiagnosticLexKinds.td | 2 +- clang/lib/Lex/PPDirectives.cpp | 7 ++++--- clang/test/Preprocessor/cxx_oper_keyword.cpp | 13 +++++++++++-- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticLexKinds.td b/clang/include/clang/Basic/DiagnosticLexKinds.td index 2d584f1..01f5608 100644 --- a/clang/include/clang/Basic/DiagnosticLexKinds.td +++ b/clang/include/clang/Basic/DiagnosticLexKinds.td @@ -500,7 +500,7 @@ def ext_pp_bad_paste_ms : ExtWarn< "pasting formed '%0', an invalid preprocessing token">, DefaultError, InGroup>; def err_pp_operator_used_as_macro_name : Error< - "C++ operator %0 (aka %1) cannot be used as a macro name">; + "C++ operator %0 (aka %1) used as a macro name">; def err_pp_illegal_floating_literal : Error< "floating point literal in preprocessor expression">; def err_pp_line_requires_integer : Error< diff --git a/clang/lib/Lex/PPDirectives.cpp b/clang/lib/Lex/PPDirectives.cpp index 78b84e2..46e8f07 100644 --- a/clang/lib/Lex/PPDirectives.cpp +++ b/clang/lib/Lex/PPDirectives.cpp @@ -148,10 +148,11 @@ bool Preprocessor::CheckMacroName(Token &MacroNameTok, char isDefineUndef) { if (!getLangOpts().MSVCCompat) // C++ 2.5p2: Alternative tokens behave the same as its primary token // except for their spellings. - return Diag(MacroNameTok, diag::err_pp_operator_used_as_macro_name) - << II << MacroNameTok.getKind(); + Diag(MacroNameTok, diag::err_pp_operator_used_as_macro_name) + << II << MacroNameTok.getKind(); - // Allow #defining |and| and friends for Microsoft compatibility. + // Allow #defining |and| and friends for Microsoft compatibility or + // recovery when legacy C headers are included in C++. MacroNameTok.setIdentifierInfo(II); } diff --git a/clang/test/Preprocessor/cxx_oper_keyword.cpp b/clang/test/Preprocessor/cxx_oper_keyword.cpp index 03e2a66..89a094d 100644 --- a/clang/test/Preprocessor/cxx_oper_keyword.cpp +++ b/clang/test/Preprocessor/cxx_oper_keyword.cpp @@ -11,12 +11,21 @@ // Not valid in C++ unless -fno-operator-names is passed: #ifdef OPERATOR_NAMES -//expected-error@+2 {{C++ operator 'and' (aka '&&') cannot be used as a macro name}} +//expected-error@+2 {{C++ operator 'and' (aka '&&') used as a macro name}} #endif #define and foo #ifdef OPERATOR_NAMES -//expected-error@+2 {{C++ operator 'xor' (aka '^') cannot be used as a macro name}} +//expected-error@+2 {{C++ operator 'xor' (aka '^') used as a macro name}} #endif #if defined xor #endif + +// For error recovery we continue as though the identifier was a macro name regardless of -fno-operator-names. +#ifdef OPERATOR_NAMES +//expected-error@+3 {{C++ operator 'and' (aka '&&') used as a macro name}} +#endif +//expected-warning@+2 {{and is defined}} +#ifdef and +#warning and is defined +#endif -- 2.7.4