diff --git a/clang/include/clang/Lex/Preprocessor.h b/clang/include/clang/Lex/Preprocessor.h index 328a18a59dd6..6d6cd0d05c41 100644 --- a/clang/include/clang/Lex/Preprocessor.h +++ b/clang/include/clang/Lex/Preprocessor.h @@ -826,8 +826,9 @@ public: /// CreateString - Plop the specified string into a scratch buffer and set the /// specified token's location and length to it. If specified, the source /// location provides a location of the expansion point of the token. - void CreateString(const char *Buf, unsigned Len, - Token &Tok, SourceLocation SourceLoc = SourceLocation()); + void CreateString(const char *Buf, unsigned Len, Token &Tok, + SourceLocation ExpansionLocStart = SourceLocation(), + SourceLocation ExpansionLocEnd = SourceLocation()); /// \brief Computes the source location just past the end of the /// token at this source location. diff --git a/clang/lib/Lex/Lexer.cpp b/clang/lib/Lex/Lexer.cpp index 563248877e48..6b69e57074d5 100644 --- a/clang/lib/Lex/Lexer.cpp +++ b/clang/lib/Lex/Lexer.cpp @@ -1776,7 +1776,7 @@ bool Lexer::SaveBCPLComment(Token &Result, const char *CurPtr) { Result.setKind(tok::comment); PP->CreateString(&Spelling[0], Spelling.size(), Result, - Result.getLocation()); + Result.getLocation(), Result.getLocation()); return true; } diff --git a/clang/lib/Lex/MacroArgs.cpp b/clang/lib/Lex/MacroArgs.cpp index a2d9651470f0..1846d1c05e30 100644 --- a/clang/lib/Lex/MacroArgs.cpp +++ b/clang/lib/Lex/MacroArgs.cpp @@ -189,7 +189,8 @@ MacroArgs::getPreExpArgument(unsigned Arg, const MacroInfo *MI, /// Token MacroArgs::StringifyArgument(const Token *ArgToks, Preprocessor &PP, bool Charify, - SourceLocation hashInstLoc) { + SourceLocation ExpansionLocStart, + SourceLocation ExpansionLocEnd) { Token Tok; Tok.startToken(); Tok.setKind(Charify ? tok::char_constant : tok::string_literal); @@ -285,7 +286,8 @@ Token MacroArgs::StringifyArgument(const Token *ArgToks, } } - PP.CreateString(&Result[0], Result.size(), Tok, hashInstLoc); + PP.CreateString(&Result[0], Result.size(), Tok, + ExpansionLocStart, ExpansionLocEnd); return Tok; } @@ -293,7 +295,8 @@ Token MacroArgs::StringifyArgument(const Token *ArgToks, /// that has been 'stringified' as required by the # operator. const Token &MacroArgs::getStringifiedArgument(unsigned ArgNo, Preprocessor &PP, - SourceLocation hashInstLoc) { + SourceLocation ExpansionLocStart, + SourceLocation ExpansionLocEnd) { assert(ArgNo < NumUnexpArgTokens && "Invalid argument number!"); if (StringifiedArgs.empty()) { StringifiedArgs.resize(getNumArguments()); @@ -302,6 +305,8 @@ const Token &MacroArgs::getStringifiedArgument(unsigned ArgNo, } if (StringifiedArgs[ArgNo].isNot(tok::string_literal)) StringifiedArgs[ArgNo] = StringifyArgument(getUnexpArgument(ArgNo), PP, - /*Charify=*/false, hashInstLoc); + /*Charify=*/false, + ExpansionLocStart, + ExpansionLocEnd); return StringifiedArgs[ArgNo]; } diff --git a/clang/lib/Lex/MacroArgs.h b/clang/lib/Lex/MacroArgs.h index c45778e3d1bb..cf86d710adb7 100644 --- a/clang/lib/Lex/MacroArgs.h +++ b/clang/lib/Lex/MacroArgs.h @@ -89,7 +89,8 @@ public: /// getStringifiedArgument - Compute, cache, and return the specified argument /// that has been 'stringified' as required by the # operator. const Token &getStringifiedArgument(unsigned ArgNo, Preprocessor &PP, - SourceLocation hashInstLoc); + SourceLocation ExpansionLocStart, + SourceLocation ExpansionLocEnd); /// getNumArguments - Return the number of arguments passed into this macro /// invocation. @@ -110,7 +111,8 @@ public: /// static Token StringifyArgument(const Token *ArgToks, Preprocessor &PP, bool Charify, - SourceLocation hashInstLoc); + SourceLocation ExpansionLocStart, + SourceLocation ExpansionLocEnd); /// deallocate - This should only be called by the Preprocessor when managing diff --git a/clang/lib/Lex/PPMacroExpansion.cpp b/clang/lib/Lex/PPMacroExpansion.cpp index 5a603b639242..5bdebf93b36d 100644 --- a/clang/lib/Lex/PPMacroExpansion.cpp +++ b/clang/lib/Lex/PPMacroExpansion.cpp @@ -1019,7 +1019,8 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) { } else { llvm_unreachable("Unknown identifier!"); } - CreateString(OS.str().data(), OS.str().size(), Tok, Tok.getLocation()); + CreateString(OS.str().data(), OS.str().size(), Tok, + Tok.getLocation(), Tok.getLocation()); } void Preprocessor::markMacroAsUsed(MacroInfo *MI) { diff --git a/clang/lib/Lex/Preprocessor.cpp b/clang/lib/Lex/Preprocessor.cpp index eeb4be1250cb..dee98eac402d 100644 --- a/clang/lib/Lex/Preprocessor.cpp +++ b/clang/lib/Lex/Preprocessor.cpp @@ -353,14 +353,16 @@ StringRef Preprocessor::getSpelling(const Token &Tok, /// location for it. If specified, the source location provides a source /// location for the token. void Preprocessor::CreateString(const char *Buf, unsigned Len, Token &Tok, - SourceLocation ExpansionLoc) { + SourceLocation ExpansionLocStart, + SourceLocation ExpansionLocEnd) { Tok.setLength(Len); const char *DestPtr; SourceLocation Loc = ScratchBuf->getToken(Buf, Len, DestPtr); - if (ExpansionLoc.isValid()) - Loc = SourceMgr.createExpansionLoc(Loc, ExpansionLoc, ExpansionLoc, Len); + if (ExpansionLocStart.isValid()) + Loc = SourceMgr.createExpansionLoc(Loc, ExpansionLocStart, + ExpansionLocEnd, Len); Tok.setLocation(Loc); // If this is a raw identifier or a literal token, set the pointer data. diff --git a/clang/lib/Lex/TokenLexer.cpp b/clang/lib/Lex/TokenLexer.cpp index 9618711d6cb8..a58054490fcd 100644 --- a/clang/lib/Lex/TokenLexer.cpp +++ b/clang/lib/Lex/TokenLexer.cpp @@ -143,16 +143,22 @@ void TokenLexer::ExpandFunctionArguments() { int ArgNo = Macro->getArgumentNum(Tokens[i+1].getIdentifierInfo()); assert(ArgNo != -1 && "Token following # is not an argument?"); - SourceLocation hashInstLoc = + SourceLocation ExpansionLocStart = getExpansionLocForMacroDefLoc(CurTok.getLocation()); + SourceLocation ExpansionLocEnd = + getExpansionLocForMacroDefLoc(Tokens[i+1].getLocation()); Token Res; if (CurTok.is(tok::hash)) // Stringify - Res = ActualArgs->getStringifiedArgument(ArgNo, PP, hashInstLoc); + Res = ActualArgs->getStringifiedArgument(ArgNo, PP, + ExpansionLocStart, + ExpansionLocEnd); else { // 'charify': don't bother caching these. Res = MacroArgs::StringifyArgument(ActualArgs->getUnexpArgument(ArgNo), - PP, true, hashInstLoc); + PP, true, + ExpansionLocStart, + ExpansionLocEnd); } // The stringified/charified string leading space flag gets set to match @@ -446,6 +452,7 @@ void TokenLexer::Lex(Token &Tok) { bool TokenLexer::PasteTokens(Token &Tok) { llvm::SmallString<128> Buffer; const char *ResultTokStrPtr = 0; + SourceLocation StartLoc = Tok.getLocation(); SourceLocation PasteOpLoc; do { // Consume the ## operator. @@ -580,16 +587,19 @@ bool TokenLexer::PasteTokens(Token &Tok) { Tok = Result; } while (!isAtEnd() && Tokens[CurToken].is(tok::hashhash)); + SourceLocation EndLoc = Tokens[CurToken - 1].getLocation(); + // The token's current location indicate where the token was lexed from. We // need this information to compute the spelling of the token, but any // diagnostics for the expanded token should appear as if the token was - // expanded from the (##) operator. Pull this information together into + // expanded from the full ## expression. Pull this information together into // a new SourceLocation that captures all of this. SourceManager &SM = PP.getSourceManager(); - SourceLocation pasteLocInst = getExpansionLocForMacroDefLoc(PasteOpLoc); - Tok.setLocation(SM.createExpansionLoc(Tok.getLocation(), - pasteLocInst, - pasteLocInst, + if (StartLoc.isFileID()) + StartLoc = getExpansionLocForMacroDefLoc(StartLoc); + if (EndLoc.isFileID()) + EndLoc = getExpansionLocForMacroDefLoc(EndLoc); + Tok.setLocation(SM.createExpansionLoc(Tok.getLocation(), StartLoc, EndLoc, Tok.getLength())); // Now that we got the result token, it will be subject to expansion. Since diff --git a/clang/test/Misc/caret-diags-macros.c b/clang/test/Misc/caret-diags-macros.c index ac83ecc69525..3d2e576d6414 100644 --- a/clang/test/Misc/caret-diags-macros.c +++ b/clang/test/Misc/caret-diags-macros.c @@ -113,11 +113,8 @@ void test3() { // CHECK: {{.*}}:102:41: note: expanded from: variadic_pasting_args3a(1, 2, 3, 4); - // FIXME: It'd be really nice to retain the start location of the first token - // involved in the token paste instead of falling back on the full macro - // location in the first two locations here. - // CHECK: {{.*}}:115:3: warning: expression result unused - // CHECK: {{.*}}:106:44: note: expanded from: - // CHECK: {{.*}}:104:72: note: expanded from: + // CHECK: {{.*}}:115:30: warning: expression result unused + // CHECK: {{.*}}:106:71: note: expanded from: + // CHECK: {{.*}}:104:70: note: expanded from: // CHECK: {{.*}}:102:41: note: expanded from: }