summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlp Toker <alp@nuanti.com>2014-05-31 03:38:17 +0000
committerAlp Toker <alp@nuanti.com>2014-05-31 03:38:17 +0000
commit2c59df7b3ddf27b6ebbfc8a68f3831045e882c04 (patch)
tree8a0384dcf70961c9d966059d81ab0acde48bef37
parent96dd0dfe842893651cdc6b377502685731183163 (diff)
downloadclang-2c59df7b3ddf27b6ebbfc8a68f3831045e882c04.tar.gz
clang-2c59df7b3ddf27b6ebbfc8a68f3831045e882c04.tar.bz2
clang-2c59df7b3ddf27b6ebbfc8a68f3831045e882c04.tar.xz
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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@209963 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Basic/DiagnosticLexKinds.td2
-rw-r--r--lib/Lex/PPDirectives.cpp7
-rw-r--r--test/Preprocessor/cxx_oper_keyword.cpp13
3 files changed, 16 insertions, 6 deletions
diff --git a/include/clang/Basic/DiagnosticLexKinds.td b/include/clang/Basic/DiagnosticLexKinds.td
index 2d584f1c34..01f56089d9 100644
--- a/include/clang/Basic/DiagnosticLexKinds.td
+++ b/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<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<
diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp
index 78b84e2d46..46e8f07c51 100644
--- a/lib/Lex/PPDirectives.cpp
+++ b/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/test/Preprocessor/cxx_oper_keyword.cpp b/test/Preprocessor/cxx_oper_keyword.cpp
index 03e2a661b9..89a094d073 100644
--- a/test/Preprocessor/cxx_oper_keyword.cpp
+++ b/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