From 3eb0f55c2626d98b95cee1c8f7574718d8d0f0cd Mon Sep 17 00:00:00 2001
From: Richard Trieu <rtrieu@google.com>
Date: Tue, 26 Jan 2016 02:51:55 +0000
Subject: [PATCH] Fix -Wnull-conversion for long macros.

Move the function to get a macro name from DiagnosticRenderer.cpp to Lexer.cpp
so that other files can use it.  Lexer now has two functions to get the
immediate macro name, the newly added one is better for diagnostic purposes.
Make -Wnull-conversion use this function for better NULL macro detection.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@258778 91177308-0d34-0410-b5e6-96231b3b80d8
---
 include/clang/Lex/Lexer.h           | 20 +++++++++++++
 lib/Frontend/DiagnosticRenderer.cpp | 45 ++---------------------------
 lib/Lex/Lexer.cpp                   | 25 ++++++++++++++++
 lib/Sema/SemaChecking.cpp           |  4 +--
 test/SemaCXX/conversion.cpp         | 28 ++++++++++++++++++
 5 files changed, 77 insertions(+), 45 deletions(-)

diff --git a/include/clang/Lex/Lexer.h b/include/clang/Lex/Lexer.h
index 12565d0b14b..830c25a2e4d 100644
--- a/include/clang/Lex/Lexer.h
+++ b/include/clang/Lex/Lexer.h
@@ -410,6 +410,26 @@ public:
                                          const SourceManager &SM,
                                          const LangOptions &LangOpts);
 
+  /// \brief Retrieve the name of the immediate macro expansion.
+  ///
+  /// This routine starts from a source location, and finds the name of the
+  /// macro responsible for its immediate expansion. It looks through any
+  /// intervening macro argument expansions to compute this. It returns a
+  /// StringRef which refers to the SourceManager-owned buffer of the source
+  /// where that macro name is spelled. Thus, the result shouldn't out-live
+  /// that SourceManager.
+  ///
+  /// This differs from Lexer::getImmediateMacroName in that any macro argument
+  /// location will result in the topmost function macro that accepted it.
+  /// e.g.
+  /// \code
+  ///   MAC1( MAC2(foo) )
+  /// \endcode
+  /// for location of 'foo' token, this function will return "MAC1" while
+  /// Lexer::getImmediateMacroName will return "MAC2".
+  static StringRef getImmediateMacroNameForDiagnostics(
+      SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts);
+
   /// \brief Compute the preamble of the given file.
   ///
   /// The preamble of a file contains the initial comments, include directives,
diff --git a/lib/Frontend/DiagnosticRenderer.cpp b/lib/Frontend/DiagnosticRenderer.cpp
index caf1f0dce99..302067a2fb0 100644
--- a/lib/Frontend/DiagnosticRenderer.cpp
+++ b/lib/Frontend/DiagnosticRenderer.cpp
@@ -23,48 +23,6 @@
 #include <algorithm>
 using namespace clang;
 
-/// \brief Retrieve the name of the immediate macro expansion.
-///
-/// This routine starts from a source location, and finds the name of the macro
-/// responsible for its immediate expansion. It looks through any intervening
-/// macro argument expansions to compute this. It returns a StringRef which
-/// refers to the SourceManager-owned buffer of the source where that macro
-/// name is spelled. Thus, the result shouldn't out-live that SourceManager.
-///
-/// This differs from Lexer::getImmediateMacroName in that any macro argument
-/// location will result in the topmost function macro that accepted it.
-/// e.g.
-/// \code
-///   MAC1( MAC2(foo) )
-/// \endcode
-/// for location of 'foo' token, this function will return "MAC1" while
-/// Lexer::getImmediateMacroName will return "MAC2".
-static StringRef getImmediateMacroName(SourceLocation Loc,
-                                       const SourceManager &SM,
-                                       const LangOptions &LangOpts) {
-   assert(Loc.isMacroID() && "Only reasonble to call this on macros");
-   // Walk past macro argument expanions.
-   while (SM.isMacroArgExpansion(Loc))
-     Loc = SM.getImmediateExpansionRange(Loc).first;
-
-   // If the macro's spelling has no FileID, then it's actually a token paste
-   // or stringization (or similar) and not a macro at all.
-   if (!SM.getFileEntryForID(SM.getFileID(SM.getSpellingLoc(Loc))))
-     return StringRef();
-
-   // Find the spelling location of the start of the non-argument expansion
-   // range. This is where the macro name was spelled in order to begin
-   // expanding this macro.
-   Loc = SM.getSpellingLoc(SM.getImmediateExpansionRange(Loc).first);
-
-   // Dig out the buffer where the macro name was spelled and the extents of the
-   // name so that we can render it into the expansion note.
-   std::pair<FileID, unsigned> ExpansionInfo = SM.getDecomposedLoc(Loc);
-   unsigned MacroTokenLength = Lexer::MeasureTokenLength(Loc, SM, LangOpts);
-   StringRef ExpansionBuffer = SM.getBufferData(ExpansionInfo.first);
-   return ExpansionBuffer.substr(ExpansionInfo.second, MacroTokenLength);
-}
-
 DiagnosticRenderer::DiagnosticRenderer(const LangOptions &LangOpts,
                                        DiagnosticOptions *DiagOpts)
   : LangOpts(LangOpts), DiagOpts(DiagOpts), LastLevel() {}
@@ -474,7 +432,8 @@ void DiagnosticRenderer::emitSingleMacroExpansion(
 
   SmallString<100> MessageStorage;
   llvm::raw_svector_ostream Message(MessageStorage);
-  StringRef MacroName = getImmediateMacroName(Loc, SM, LangOpts);
+  StringRef MacroName =
+      Lexer::getImmediateMacroNameForDiagnostics(Loc, SM, LangOpts);
   if (MacroName.empty())
     Message << "expanded from here";
   else
diff --git a/lib/Lex/Lexer.cpp b/lib/Lex/Lexer.cpp
index 27b0feb4827..88e7b247806 100644
--- a/lib/Lex/Lexer.cpp
+++ b/lib/Lex/Lexer.cpp
@@ -1000,6 +1000,31 @@ StringRef Lexer::getImmediateMacroName(SourceLocation Loc,
   return ExpansionBuffer.substr(ExpansionInfo.second, MacroTokenLength);
 }
 
+StringRef Lexer::getImmediateMacroNameForDiagnostics(
+    SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts) {
+  assert(Loc.isMacroID() && "Only reasonble to call this on macros");
+  // Walk past macro argument expanions.
+  while (SM.isMacroArgExpansion(Loc))
+    Loc = SM.getImmediateExpansionRange(Loc).first;
+
+  // If the macro's spelling has no FileID, then it's actually a token paste
+  // or stringization (or similar) and not a macro at all.
+  if (!SM.getFileEntryForID(SM.getFileID(SM.getSpellingLoc(Loc))))
+    return StringRef();
+
+  // Find the spelling location of the start of the non-argument expansion
+  // range. This is where the macro name was spelled in order to begin
+  // expanding this macro.
+  Loc = SM.getSpellingLoc(SM.getImmediateExpansionRange(Loc).first);
+
+  // Dig out the buffer where the macro name was spelled and the extents of the
+  // name so that we can render it into the expansion note.
+  std::pair<FileID, unsigned> ExpansionInfo = SM.getDecomposedLoc(Loc);
+  unsigned MacroTokenLength = Lexer::MeasureTokenLength(Loc, SM, LangOpts);
+  StringRef ExpansionBuffer = SM.getBufferData(ExpansionInfo.first);
+  return ExpansionBuffer.substr(ExpansionInfo.second, MacroTokenLength);
+}
+
 bool Lexer::isIdentifierBodyChar(char c, const LangOptions &LangOpts) {
   return isIdentifierBody(c, LangOpts.DollarIdents);
 }
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp
index c8c4d3331b1..58ae3acf498 100644
--- a/lib/Sema/SemaChecking.cpp
+++ b/lib/Sema/SemaChecking.cpp
@@ -7068,8 +7068,8 @@ static void DiagnoseNullConversion(Sema &S, Expr *E, QualType T,
   // __null is usually wrapped in a macro.  Go up a macro if that is the case.
   if (NullKind == Expr::NPCK_GNUNull) {
     if (Loc.isMacroID()) {
-      StringRef MacroName =
-          Lexer::getImmediateMacroName(Loc, S.SourceMgr, S.getLangOpts());
+      StringRef MacroName = Lexer::getImmediateMacroNameForDiagnostics(
+          Loc, S.SourceMgr, S.getLangOpts());
       if (MacroName == "NULL")
         Loc = S.SourceMgr.getImmediateExpansionRange(Loc).first;
     }
diff --git a/test/SemaCXX/conversion.cpp b/test/SemaCXX/conversion.cpp
index 4c4089c6aae..eea8ac2af8a 100644
--- a/test/SemaCXX/conversion.cpp
+++ b/test/SemaCXX/conversion.cpp
@@ -228,3 +228,31 @@ namespace test10 {
     assert(test2(x));
   }
 }
+
+namespace test11 {
+
+#define assert11(expr) ((expr) ? 0 : 0)
+
+// The whitespace in macro run1 are important to trigger the macro being split
+// over multiple SLocEntry's.
+#define run1() (dostuff() ? \
+    NULL                                   : NULL)
+#define run2() (dostuff() ? NULL : NULL)
+int dostuff ();
+
+void test(const char * content_type) {
+  assert11(run1());
+  assert11(run2());
+}
+
+}
+
+namespace test12 {
+
+#define x return NULL;
+
+bool run() {
+  x  // expected-warning{{}}
+}
+
+}
-- 
GitLab