diff --git a/include/clang/Lex/Lexer.h b/include/clang/Lex/Lexer.h index 12565d0b14b6384f0356ac82694b583c8f626844..830c25a2e4d29fc6fcead442fe7b9e35ace03f3e 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 caf1f0dce99ffce4a719c537f2e1d185e476cd6f..302067a2fb05d29a74eb256d7a6481e0ebdcdfad 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 27b0feb4827054f0c0de3402b2f43f03875de446..88e7b247806c70d9f3b76aadbb3d1554306271b1 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 c8c4d3331b1e55e2bd93359dd06bad97cfee787c..58ae3acf49876e374710df511eddbfa76c32db11 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 4c4089c6aae773840122e33d755fabe0c5331246..eea8ac2af8a5bc8aa8a4a41bb568b24697593e63 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{{}} +} + +}