]> granicus.if.org Git - clang/commitdiff
Preprocessor: recover gracefully when C++ operator names are used as macro identifiers
authorAlp Toker <alp@nuanti.com>
Sat, 31 May 2014 03:38:17 +0000 (03:38 +0000)
committerAlp Toker <alp@nuanti.com>
Sat, 31 May 2014 03:38:17 +0000 (03:38 +0000)
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.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@209963 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticLexKinds.td
lib/Lex/PPDirectives.cpp
test/Preprocessor/cxx_oper_keyword.cpp

index 2d584f1c340415f268521b5574d705ce12b5464c..01f56089d9491149fa5e3e3b45a86eb7357d0c50 100644 (file)
@@ -500,7 +500,7 @@ def ext_pp_bad_paste_ms : ExtWarn<
   "pasting formed '%0', an invalid preprocessing token">, DefaultError,
   InGroup<DiagGroup<"invalid-token-paste">>;
 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<
index 78b84e2d469a1eeae858430b3b8f41daac7788d6..46e8f07c510a77f367c94900f490b9ed83375732 100644 (file)
@@ -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);
   }
 
index 03e2a661b972c3f2a844e0da24a898c87270bb33..89a094d073ca1db4b6c756450c7678e63d84a3a3 100644 (file)
 // 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