diff --git a/include/clang/Basic/SourceManager.h b/include/clang/Basic/SourceManager.h index 77ad2b2086e6aed4971a545eaba4cd2bd0b41a97..d5845baa31a06ae4ec9d268eb9c22754fd5669c5 100644 --- a/include/clang/Basic/SourceManager.h +++ b/include/clang/Basic/SourceManager.h @@ -177,23 +177,43 @@ namespace SrcMgr { /// location - where the token was ultimately instantiated, and the /// SpellingLoc - where the actual character data for the token came from. class InstantiationInfo { - unsigned InstantiationLoc, SpellingLoc; // Really these are SourceLocations. + // Really these are all SourceLocations. + + /// SpellingLoc - Where the spelling for the token can be found. + unsigned SpellingLoc; + + /// InstantiationLocStart/InstantiationLocEnd - In a macro expansion, these + /// indicate the start and end of the instantiation. In object-line macros, + /// these will be the same. In a function-like macro instantiation, the + /// start will be the identifier and the end will be the ')'. + unsigned InstantiationLocStart, InstantiationLocEnd; public: - SourceLocation getInstantiationLoc() const { - return SourceLocation::getFromRawEncoding(InstantiationLoc); - } SourceLocation getSpellingLoc() const { return SourceLocation::getFromRawEncoding(SpellingLoc); } + SourceLocation getInstantiationLocStart() const { + return SourceLocation::getFromRawEncoding(InstantiationLocStart); + } + SourceLocation getInstantiationLocEnd() const { + return SourceLocation::getFromRawEncoding(InstantiationLocEnd); + } + + std::pair<SourceLocation,SourceLocation> getInstantiationLocRange() const { + return std::make_pair(getInstantiationLocStart(), + getInstantiationLocEnd()); + } - /// get - Return a InstantiationInfo for an expansion. VL specifies + /// get - Return a InstantiationInfo for an expansion. IL specifies /// the instantiation location (where the macro is expanded), and SL /// specifies the spelling location (where the characters from the token - /// come from). Both VL and PL refer to normal File SLocs. - static InstantiationInfo get(SourceLocation IL, SourceLocation SL) { + /// come from). IL and PL can both refer to normal File SLocs or + /// instantiation locations. + static InstantiationInfo get(SourceLocation ILStart, SourceLocation ILEnd, + SourceLocation SL) { InstantiationInfo X; - X.InstantiationLoc = IL.getRawEncoding(); X.SpellingLoc = SL.getRawEncoding(); + X.InstantiationLocStart = ILStart.getRawEncoding(); + X.InstantiationLocEnd = ILEnd.getRawEncoding(); return X; } }; @@ -354,7 +374,8 @@ public: /// that a token at Loc should actually be referenced from InstantiationLoc. /// TokLength is the length of the token being instantiated. SourceLocation createInstantiationLoc(SourceLocation Loc, - SourceLocation InstantiationLoc, + SourceLocation InstantiationLocStart, + SourceLocation InstantiationLocEnd, unsigned TokLength); //===--------------------------------------------------------------------===// @@ -413,6 +434,11 @@ public: return getInstantiationLocSlowCase(Loc); } + /// getImmediateInstantiationRange - Loc is required to be an instantiation + /// location. Return the start/end of the instantiation information. + std::pair<SourceLocation,SourceLocation> + getImmediateInstantiationRange(SourceLocation Loc) const; + /// getSpellingLoc - Given a SourceLocation object, return the spelling /// location referenced by the ID. This is the place where the characters /// that make up the lexed token can be found. diff --git a/include/clang/Lex/Lexer.h b/include/clang/Lex/Lexer.h index 296fca11151c65d23f60dc8398d7ce7241909e7d..3950e17705ddcb1767d4a987fa283ed8a2bc00b3 100644 --- a/include/clang/Lex/Lexer.h +++ b/include/clang/Lex/Lexer.h @@ -94,7 +94,8 @@ public: /// _Pragma expansion. This has a variety of magic semantics that this method /// sets up. It returns a new'd Lexer that must be delete'd when done. static Lexer *Create_PragmaLexer(SourceLocation SpellingLoc, - SourceLocation InstantiationLoc, + SourceLocation InstantiationLocStart, + SourceLocation InstantiationLocEnd, unsigned TokLen, Preprocessor &PP); diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h index 5200725ba135135c172e815328984066e3aaec5b..1608466fe2ef6edce11e02691efc7212d23840dd 100644 --- a/include/clang/Lex/Preprocessor.h +++ b/include/clang/Lex/Preprocessor.h @@ -298,7 +298,10 @@ public: /// EnterMacro - Add a Macro to the top of the include stack and start lexing /// tokens from it instead of the current buffer. Args specifies the /// tokens input to a function-like macro. - void EnterMacro(Token &Identifier, MacroArgs *Args); + /// + /// ILEnd specifies the location of the ')' for a function-like macro or the + /// identifier for an object-like macro. + void EnterMacro(Token &Identifier, SourceLocation ILEnd, MacroArgs *Args); /// EnterTokenStream - Add a "macro" context to the top of the include stack, /// which will cause the lexer to start returning the specified tokens. @@ -637,7 +640,8 @@ private: /// ReadFunctionLikeMacroArgs - After reading "MACRO(", this method is /// invoked to read all of the formal arguments specified for the macro /// invocation. This returns null on error. - MacroArgs *ReadFunctionLikeMacroArgs(Token &MacroName, MacroInfo *MI); + MacroArgs *ReadFunctionLikeMacroArgs(Token &MacroName, MacroInfo *MI, + SourceLocation &InstantiationEnd); /// ExpandBuiltinMacro - If an identifier token is read that is to be expanded /// as a builtin macro, handle it and return the next token as 'Tok'. diff --git a/include/clang/Lex/TokenLexer.h b/include/clang/Lex/TokenLexer.h index 47b7c213d7589b468ed78018d528b1d1d302159b..a3004b1c04b6632f80b3bf86c7bc6bbe79b58416 100644 --- a/include/clang/Lex/TokenLexer.h +++ b/include/clang/Lex/TokenLexer.h @@ -53,9 +53,9 @@ class TokenLexer { /// unsigned CurToken; - /// InstantiateLoc - The source location where this macro was instantiated. - /// - SourceLocation InstantiateLoc; + /// InstantiateLocStart/End - The source location range where this macro was + /// instantiated. + SourceLocation InstantiateLocStart, InstantiateLocEnd; /// Lexical information about the expansion point of the macro: the identifier /// that the macro expanded from had these properties. @@ -77,15 +77,19 @@ class TokenLexer { public: /// Create a TokenLexer for the specified macro with the specified actual /// arguments. Note that this ctor takes ownership of the ActualArgs pointer. - TokenLexer(Token &Tok, MacroArgs *ActualArgs, Preprocessor &pp) + /// ILEnd specifies the location of the ')' for a function-like macro or the + /// identifier for an object-like macro. + TokenLexer(Token &Tok, SourceLocation ILEnd, MacroArgs *ActualArgs, + Preprocessor &pp) : Macro(0), ActualArgs(0), PP(pp), OwnsTokens(false) { - Init(Tok, ActualArgs); + Init(Tok, ILEnd, ActualArgs); } /// Init - Initialize this TokenLexer to expand from the specified macro /// with the specified argument information. Note that this ctor takes - /// ownership of the ActualArgs pointer. - void Init(Token &Tok, MacroArgs *ActualArgs); + /// ownership of the ActualArgs pointer. ILEnd specifies the location of the + /// ')' for a function-like macro or the identifier for an object-like macro. + void Init(Token &Tok, SourceLocation ILEnd, MacroArgs *ActualArgs); /// Create a TokenLexer for the specified token stream. If 'OwnsTokens' is /// specified, this takes ownership of the tokens and delete[]'s them when diff --git a/lib/Basic/SourceManager.cpp b/lib/Basic/SourceManager.cpp index e023a91f2f164d9d4be79a0b5094b7f194b71fbc..71bda5b255fe631c64541af452d198b5d1f2198c 100644 --- a/lib/Basic/SourceManager.cpp +++ b/lib/Basic/SourceManager.cpp @@ -352,7 +352,7 @@ void SourceManager::clearIDTables() { // Use up FileID #0 as an invalid instantiation. NextOffset = 0; - createInstantiationLoc(SourceLocation(), SourceLocation(), 1); + createInstantiationLoc(SourceLocation(),SourceLocation(),SourceLocation(), 1); } /// getOrCreateContentCache - Create or return a cached ContentCache for the @@ -418,11 +418,11 @@ FileID SourceManager::createFileID(const ContentCache *File, /// that a token from SpellingLoc should actually be referenced from /// InstantiationLoc. SourceLocation SourceManager::createInstantiationLoc(SourceLocation SpellingLoc, - SourceLocation InstantLoc, + SourceLocation ILocStart, + SourceLocation ILocEnd, unsigned TokLength) { - SLocEntryTable.push_back(SLocEntry::get(NextOffset, - InstantiationInfo::get(InstantLoc, - SpellingLoc))); + InstantiationInfo II = InstantiationInfo::get(ILocStart,ILocEnd, SpellingLoc); + SLocEntryTable.push_back(SLocEntry::get(NextOffset, II)); assert(NextOffset+TokLength+1 > NextOffset && "Ran out of source locations!"); NextOffset += TokLength+1; return SourceLocation::getMacroLoc(NextOffset-(TokLength+1)); @@ -543,7 +543,8 @@ SourceLocation SourceManager:: getInstantiationLocSlowCase(SourceLocation Loc) const { do { std::pair<FileID, unsigned> LocInfo = getDecomposedLoc(Loc); - Loc =getSLocEntry(LocInfo.first).getInstantiation().getInstantiationLoc(); + Loc = getSLocEntry(LocInfo.first).getInstantiation() + .getInstantiationLocStart(); Loc = Loc.getFileLocWithOffset(LocInfo.second); } while (!Loc.isFileID()); @@ -568,7 +569,7 @@ SourceManager::getDecomposedInstantiationLocSlowCase(const SrcMgr::SLocEntry *E, FileID FID; SourceLocation Loc; do { - Loc = E->getInstantiation().getInstantiationLoc(); + Loc = E->getInstantiation().getInstantiationLocStart(); FID = getFileID(Loc); E = &getSLocEntry(FID); @@ -596,6 +597,16 @@ SourceManager::getDecomposedSpellingLocSlowCase(const SrcMgr::SLocEntry *E, return std::make_pair(FID, Offset); } +/// getImmediateInstantiationRange - Loc is required to be an instantiation +/// location. Return the start/end of the instantiation information. +std::pair<SourceLocation,SourceLocation> +SourceManager::getImmediateInstantiationRange(SourceLocation Loc) const { + assert(Loc.isMacroID() && "Not an instantiation loc!"); + const InstantiationInfo &II = getSLocEntry(getFileID(Loc)).getInstantiation(); + return II.getInstantiationLocRange(); +} + + //===----------------------------------------------------------------------===// // Queries about the code at a SourceLocation. diff --git a/lib/Lex/Lexer.cpp b/lib/Lex/Lexer.cpp index 72715c9eedaaf629677d4727be3dc50f06d06f45..5f325220206af6a043429d5714ba496776e532a1 100644 --- a/lib/Lex/Lexer.cpp +++ b/lib/Lex/Lexer.cpp @@ -151,7 +151,8 @@ Lexer::Lexer(FileID FID, const SourceManager &SM, const LangOptions &features) /// out of the critical path of the lexer! /// Lexer *Lexer::Create_PragmaLexer(SourceLocation SpellingLoc, - SourceLocation InstantiationLoc, + SourceLocation InstantiationLocStart, + SourceLocation InstantiationLocEnd, unsigned TokLen, Preprocessor &PP) { SourceManager &SM = PP.getSourceManager(); @@ -170,7 +171,8 @@ Lexer *Lexer::Create_PragmaLexer(SourceLocation SpellingLoc, // Set the SourceLocation with the remapping information. This ensures that // GetMappedTokenLoc will remap the tokens as they are lexed. L->FileLoc = SM.createInstantiationLoc(SM.getLocForStartOfFile(SpellingFID), - InstantiationLoc, TokLen); + InstantiationLocStart, + InstantiationLocEnd, TokLen); // Ensure that the lexer thinks it is inside a directive, so that end \n will // return an EOM token. @@ -315,16 +317,24 @@ static SourceLocation GetMappedTokenLoc(Preprocessor &PP, static SourceLocation GetMappedTokenLoc(Preprocessor &PP, SourceLocation FileLoc, unsigned CharNo, unsigned TokLen) { + assert(FileLoc.isMacroID() && "Must be an instantiation"); + // Otherwise, we're lexing "mapped tokens". This is used for things like // _Pragma handling. Combine the instantiation location of FileLoc with the // spelling location. - SourceManager &SourceMgr = PP.getSourceManager(); + SourceManager &SM = PP.getSourceManager(); // Create a new SLoc which is expanded from Instantiation(FileLoc) but whose // characters come from spelling(FileLoc)+Offset. - SourceLocation SpellingLoc = SourceMgr.getSpellingLoc(FileLoc); + SourceLocation SpellingLoc = SM.getSpellingLoc(FileLoc); SpellingLoc = SpellingLoc.getFileLocWithOffset(CharNo); - return SourceMgr.createInstantiationLoc(SpellingLoc, FileLoc, TokLen); + + // Figure out the expansion loc range, which is the range covered by the + // original _Pragma(...) sequence. + std::pair<SourceLocation,SourceLocation> II = + SM.getImmediateInstantiationRange(FileLoc); + + return SM.createInstantiationLoc(SpellingLoc, II.first, II.second, TokLen); } /// getSourceLocation - Return a source location identifier for the specified diff --git a/lib/Lex/PPLexerChange.cpp b/lib/Lex/PPLexerChange.cpp index ec3447a5af993d78b358643722d2b54a72377665..13e6126899d6b52e0e0029431cce513874e19027 100644 --- a/lib/Lex/PPLexerChange.cpp +++ b/lib/Lex/PPLexerChange.cpp @@ -127,15 +127,16 @@ void Preprocessor::EnterSourceFileWithPTH(PTHLexer *PL, /// EnterMacro - Add a Macro to the top of the include stack and start lexing /// tokens from it instead of the current buffer. -void Preprocessor::EnterMacro(Token &Tok, MacroArgs *Args) { +void Preprocessor::EnterMacro(Token &Tok, SourceLocation ILEnd, + MacroArgs *Args) { PushIncludeMacroStack(); CurDirLookup = 0; if (NumCachedTokenLexers == 0) { - CurTokenLexer.reset(new TokenLexer(Tok, Args, *this)); + CurTokenLexer.reset(new TokenLexer(Tok, ILEnd, Args, *this)); } else { CurTokenLexer.reset(TokenLexerCache[--NumCachedTokenLexers]); - CurTokenLexer->Init(Tok, Args); + CurTokenLexer->Init(Tok, ILEnd, Args); } } diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp index 776754372d3d06f92542b4fd1fdb4cf45867043b..ae686527f55f1065a36a501a31631d60ecf17ed0 100644 --- a/lib/Lex/PPMacroExpansion.cpp +++ b/lib/Lex/PPMacroExpansion.cpp @@ -165,6 +165,10 @@ bool Preprocessor::HandleMacroExpandedIdentifier(Token &Identifier, /// invocation. MacroArgs *Args = 0; + // Remember where the end of the instantiation occurred. For an object-like + // macro, this is the identifier. For a function-like macro, this is the ')'. + SourceLocation InstantiationEnd = Identifier.getLocation(); + // If this is a function-like macro, read the arguments. if (MI->isFunctionLike()) { // C99 6.10.3p10: If the preprocessing token immediately after the the macro @@ -177,7 +181,7 @@ bool Preprocessor::HandleMacroExpandedIdentifier(Token &Identifier, // Preprocessor directives used inside macro arguments are not portable, and // this enables the warning. InMacroArgs = true; - Args = ReadFunctionLikeMacroArgs(Identifier, MI); + Args = ReadFunctionLikeMacroArgs(Identifier, MI, InstantiationEnd); // Finished parsing args. InMacroArgs = false; @@ -248,7 +252,7 @@ bool Preprocessor::HandleMacroExpandedIdentifier(Token &Identifier, // locations. SourceLocation Loc = SourceMgr.createInstantiationLoc(Identifier.getLocation(), InstantiateLoc, - Identifier.getLength()); + InstantiationEnd,Identifier.getLength()); Identifier.setLocation(Loc); // If this is #define X X, we must mark the result as unexpandible. @@ -263,7 +267,7 @@ bool Preprocessor::HandleMacroExpandedIdentifier(Token &Identifier, } // Start expanding the macro. - EnterMacro(Identifier, Args); + EnterMacro(Identifier, InstantiationEnd, Args); // Now that the macro is at the top of the include stack, ask the // preprocessor to read the next token from it. @@ -275,7 +279,8 @@ bool Preprocessor::HandleMacroExpandedIdentifier(Token &Identifier, /// invoked to read all of the actual arguments specified for the macro /// invocation. This returns null on error. MacroArgs *Preprocessor::ReadFunctionLikeMacroArgs(Token &MacroName, - MacroInfo *MI) { + MacroInfo *MI, + SourceLocation &MacroEnd) { // The number of fixed arguments to parse. unsigned NumFixedArgsLeft = MI->getNumArgs(); bool isVariadic = MI->isVariadic(); @@ -308,8 +313,10 @@ MacroArgs *Preprocessor::ReadFunctionLikeMacroArgs(Token &MacroName, return 0; } else if (Tok.is(tok::r_paren)) { // If we found the ) token, the macro arg list is done. - if (NumParens-- == 0) + if (NumParens-- == 0) { + MacroEnd = Tok.getLocation(); break; + } } else if (Tok.is(tok::l_paren)) { ++NumParens; } else if (Tok.is(tok::comma) && NumParens == 0) { @@ -357,7 +364,7 @@ MacroArgs *Preprocessor::ReadFunctionLikeMacroArgs(Token &MacroName, ArgTokens.push_back(EOFTok); ++NumActuals; --NumFixedArgsLeft; - }; + } // Okay, we either found the r_paren. Check to see if we parsed too few // arguments. @@ -494,6 +501,7 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) { Tok.setKind(tok::string_literal); Tok.setLength(strlen("\"Mmm dd yyyy\"")); Tok.setLocation(SourceMgr.createInstantiationLoc(DATELoc, Tok.getLocation(), + Tok.getLocation(), Tok.getLength())); } else if (II == Ident__TIME__) { if (!TIMELoc.isValid()) @@ -501,6 +509,7 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) { Tok.setKind(tok::string_literal); Tok.setLength(strlen("\"hh:mm:ss\"")); Tok.setLocation(SourceMgr.createInstantiationLoc(TIMELoc, Tok.getLocation(), + Tok.getLocation(), Tok.getLength())); } else if (II == Ident__INCLUDE_LEVEL__) { Diag(Tok, diag::ext_pp_include_level); diff --git a/lib/Lex/Pragma.cpp b/lib/Lex/Pragma.cpp index 87410f9ff4ab907071983067cdc916af342f8ad2..73d36414ba92ce38e23488357053626c6d3ac147 100644 --- a/lib/Lex/Pragma.cpp +++ b/lib/Lex/Pragma.cpp @@ -117,7 +117,6 @@ void Preprocessor::Handle_Pragma(Token &Tok) { // Remember the string. std::string StrVal = getSpelling(Tok); - SourceLocation StrLoc = Tok.getLocation(); // Read the ')'. Lex(Tok); @@ -126,6 +125,8 @@ void Preprocessor::Handle_Pragma(Token &Tok) { return; } + SourceLocation RParenLoc = Tok.getLocation(); + // The _Pragma is lexically sound. Destringize according to C99 6.10.9.1: // "The string literal is destringized by deleting the L prefix, if present, // deleting the leading and trailing double-quotes, replacing each escape @@ -163,7 +164,7 @@ void Preprocessor::Handle_Pragma(Token &Tok) { // Make and enter a lexer object so that we lex and expand the tokens just // like any others. - Lexer *TL = Lexer::Create_PragmaLexer(TokLoc, StrLoc, + Lexer *TL = Lexer::Create_PragmaLexer(TokLoc, PragmaLoc, RParenLoc, // do not include the null in the count. StrVal.size()-1, *this); diff --git a/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp index d769720634dde026fe20f9608ac893b5c290a47a..cf7306a41cc9b612396d3288cde8a6cd15975aed 100644 --- a/lib/Lex/Preprocessor.cpp +++ b/lib/Lex/Preprocessor.cpp @@ -277,7 +277,8 @@ void Preprocessor::CreateString(const char *Buf, unsigned Len, Token &Tok, SourceLocation Loc = ScratchBuf->getToken(Buf, Len, DestPtr); if (InstantiationLoc.isValid()) - Loc = SourceMgr.createInstantiationLoc(Loc, InstantiationLoc, Len); + Loc = SourceMgr.createInstantiationLoc(Loc, InstantiationLoc, + InstantiationLoc, Len); Tok.setLocation(Loc); // If this is a literal token, set the pointer data. diff --git a/lib/Lex/TokenLexer.cpp b/lib/Lex/TokenLexer.cpp index 3ca0fcfa05de96c88ad0c9ec39c8f31bb06032cb..f0e2fbdfa627e4b413b9dc9574b3b5cb525dbb4e 100644 --- a/lib/Lex/TokenLexer.cpp +++ b/lib/Lex/TokenLexer.cpp @@ -23,7 +23,7 @@ using namespace clang; /// Create a TokenLexer for the specified macro with the specified actual /// arguments. Note that this ctor takes ownership of the ActualArgs pointer. -void TokenLexer::Init(Token &Tok, MacroArgs *Actuals) { +void TokenLexer::Init(Token &Tok, SourceLocation ILEnd, MacroArgs *Actuals) { // If the client is reusing a TokenLexer, make sure to free any memory // associated with it. destroy(); @@ -32,7 +32,8 @@ void TokenLexer::Init(Token &Tok, MacroArgs *Actuals) { ActualArgs = Actuals; CurToken = 0; - InstantiateLoc = Tok.getLocation(); + InstantiateLocStart = Tok.getLocation(); + InstantiateLocEnd = ILEnd; AtStartOfLine = Tok.isAtStartOfLine(); HasLeadingSpace = Tok.hasLeadingSpace(); Tokens = &*Macro->tokens_begin(); @@ -68,7 +69,7 @@ void TokenLexer::Init(const Token *TokArray, unsigned NumToks, DisableMacroExpansion = disableMacroExpansion; NumTokens = NumToks; CurToken = 0; - InstantiateLoc = SourceLocation(); + InstantiateLocStart = InstantiateLocEnd = SourceLocation(); AtStartOfLine = false; HasLeadingSpace = false; @@ -313,11 +314,12 @@ void TokenLexer::Lex(Token &Tok) { // diagnostics for the expanded token should appear as if they came from // InstantiationLoc. Pull this information together into a new SourceLocation // that captures all of this. - if (InstantiateLoc.isValid()) { // Don't do this for token streams. - SourceManager &SrcMgr = PP.getSourceManager(); - Tok.setLocation(SrcMgr.createInstantiationLoc(Tok.getLocation(), - InstantiateLoc, - Tok.getLength())); + if (InstantiateLocStart.isValid()) { // Don't do this for token streams. + SourceManager &SM = PP.getSourceManager(); + Tok.setLocation(SM.createInstantiationLoc(Tok.getLocation(), + InstantiateLocStart, + InstantiateLocEnd, + Tok.getLength())); } // If this is the first token, set the lexical properties of the token to diff --git a/test/Preprocessor/_Pragma-dependency.c b/test/Preprocessor/_Pragma-dependency.c index f7d7efe41b02ae7e3f7e5de0ab813c1c9bbc4182..837f31d07c9599d60752fab0335c20e4141da529 100644 --- a/test/Preprocessor/_Pragma-dependency.c +++ b/test/Preprocessor/_Pragma-dependency.c @@ -1,7 +1,7 @@ // RUN: clang %s -E 2>&1 | grep 'DO_PRAGMA (STR' && -// RUN: clang %s -E 2>&1 | grep '7:12' +// RUN: clang %s -E 2>&1 | grep '7:3' #define DO_PRAGMA _Pragma #define STR "GCC dependency \"parse.y\"") -// Test that this line is printed by caret diagnostics. -DO_PRAGMA (STR + // Test that this line is printed by caret diagnostics. + DO_PRAGMA (STR