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.

llvm-svn: 258778
This commit is contained in:
Richard Trieu 2016-01-26 02:51:55 +00:00
parent f1c00a22be
commit 3a5c958182
5 changed files with 77 additions and 45 deletions

View File

@ -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,

View File

@ -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

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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{{}}
}
}