From: Argyrios Kyrtzidis Date: Fri, 19 Aug 2011 22:34:17 +0000 (+0000) Subject: For assigning SourceLocations to macro arg tokens, reserve a single SLocEntry X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d60a34a4e514ec0dfddd05ef2744be104e111f45;p=clang For assigning SourceLocations to macro arg tokens, reserve a single SLocEntry for tokens that are lexed consecutively from the same FileID, instead of creating a SLocEntry for each token. e.g for assert(foo == bar); there will be a single SLocEntry for the "foo == bar" chunk and locations for the 'foo', '==', 'bar' tokens will point inside that chunk. For parsing SemaExpr.cpp, this reduced the number of SLocEntries by 25%. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@138129 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/SourceManager.h b/include/clang/Basic/SourceManager.h index 9a1fff7919..beff66e675 100644 --- a/include/clang/Basic/SourceManager.h +++ b/include/clang/Basic/SourceManager.h @@ -933,6 +933,14 @@ public: return NextOffset - Entry.getOffset() - 1; } + /// \brief Given a specific FileID, returns true if \arg Loc is inside that + /// FileID chunk and sets relative offset (offset of \arg Loc from beginning + /// of FileID) to \arg relativeOffset. + bool isInFileID(SourceLocation Loc, FileID FID, + unsigned *RelativeOffset = 0) const { + return isInFileID(Loc, FID, 0, getFileIDSize(FID), RelativeOffset); + } + /// \brief Given a specific chunk of a FileID (FileID with offset+length), /// returns true if \arg Loc is inside that chunk and sets relative offset /// (offset of \arg Loc from beginning of chunk) to \arg relativeOffset. diff --git a/include/clang/Lex/TokenLexer.h b/include/clang/Lex/TokenLexer.h index 24aed76db4..c2f1c3a781 100644 --- a/include/clang/Lex/TokenLexer.h +++ b/include/clang/Lex/TokenLexer.h @@ -170,6 +170,14 @@ private: /// definition, returns the appropriate source location pointing at the /// macro expansion source location entry. SourceLocation getExpansionLocForMacroDefLoc(SourceLocation loc) const; + + /// \brief Creates SLocEntries and updates the locations of macro argument + /// tokens to their new expanded locations. + /// + /// \param ArgIdSpellLoc the location of the macro argument id inside the + /// macro definition. + void updateLocForMacroArgTokens(SourceLocation ArgIdSpellLoc, + Token *begin_tokens, Token *end_tokens); }; } // end namespace clang diff --git a/lib/Lex/TokenLexer.cpp b/lib/Lex/TokenLexer.cpp index befd12af39..cda7975ef1 100644 --- a/lib/Lex/TokenLexer.cpp +++ b/lib/Lex/TokenLexer.cpp @@ -121,7 +121,6 @@ void TokenLexer::destroy() { /// Expand the arguments of a function-like macro so that we can quickly /// return preexpanded tokens from Tokens. void TokenLexer::ExpandFunctionArguments() { - SourceManager &SM = PP.getSourceManager(); SmallVector ResultToks; @@ -225,16 +224,9 @@ void TokenLexer::ExpandFunctionArguments() { } if(ExpandLocStart.isValid()) { - SourceLocation curInst = - getExpansionLocForMacroDefLoc(CurTok.getLocation()); - assert(curInst.isValid() && - "Expected arg identifier to come from definition"); - for (unsigned i = FirstResult, e = ResultToks.size(); i != e; ++i) { - Token &Tok = ResultToks[i]; - Tok.setLocation(SM.createMacroArgExpansionLoc(Tok.getLocation(), - curInst, - Tok.getLength())); - } + updateLocForMacroArgTokens(CurTok.getLocation(), + ResultToks.begin()+FirstResult, + ResultToks.end()); } // If any tokens were substituted from the argument, the whitespace @@ -282,17 +274,8 @@ void TokenLexer::ExpandFunctionArguments() { } if (ExpandLocStart.isValid()) { - SourceLocation curInst = - getExpansionLocForMacroDefLoc(CurTok.getLocation()); - assert(curInst.isValid() && - "Expected arg identifier to come from definition"); - for (unsigned i = ResultToks.size() - NumToks, e = ResultToks.size(); - i != e; ++i) { - Token &Tok = ResultToks[i]; - Tok.setLocation(SM.createMacroArgExpansionLoc(Tok.getLocation(), - curInst, - Tok.getLength())); - } + updateLocForMacroArgTokens(CurTok.getLocation(), + ResultToks.end()-NumToks, ResultToks.end()); } // If this token (the macro argument) was supposed to get leading @@ -686,3 +669,67 @@ TokenLexer::getExpansionLocForMacroDefLoc(SourceLocation loc) const { return SourceLocation(); } + +/// \brief Finds the tokens that are consecutive (from the same FileID) +/// creates a single SLocEntry, and assigns SourceLocations to each token that +/// point to that SLocEntry. e.g for +/// assert(foo == bar); +/// There will be a single SLocEntry for the "foo == bar" chunk and locations +/// for the 'foo', '==', 'bar' tokens will point inside that chunk. +/// +/// \arg begin_tokens will be updated to a position past all the found +/// consecutive tokens. +static void updateConsecutiveMacroArgTokens(SourceManager &SM, + SourceLocation InstLoc, + Token *&begin_tokens, + Token * end_tokens) { + assert(begin_tokens < end_tokens); + Token &FirstTok = *begin_tokens; + FileID SpellFID = SM.getFileID(FirstTok.getLocation()); + + // Look for the first token that is not from the same FileID. + Token *NextFIDTok = begin_tokens + 1; + for (; NextFIDTok < end_tokens; ++NextFIDTok) + if (!SM.isInFileID(NextFIDTok->getLocation(), SpellFID)) + break; + + // For the consecutive tokens, find the length of the SLocEntry to contain + // all of them. + unsigned FirstOffs, LastOffs; + SM.isInFileID(FirstTok.getLocation(), SpellFID, &FirstOffs); + SM.isInFileID((NextFIDTok-1)->getLocation(), SpellFID, &LastOffs); + unsigned FullLength = (LastOffs - FirstOffs) + (NextFIDTok-1)->getLength(); + + // Create a macro expansion SLocEntry that will "contain" all of the tokens. + SourceLocation Expansion = + SM.createMacroArgExpansionLoc(FirstTok.getLocation(), InstLoc,FullLength); + + // Change the location of the tokens from the spelling location to the new + // expanded location. + for (; begin_tokens < NextFIDTok; ++begin_tokens) { + Token &Tok = *begin_tokens; + unsigned Offs; + SM.isInFileID(Tok.getLocation(), SpellFID, &Offs); + Tok.setLocation(Expansion.getFileLocWithOffset(Offs - FirstOffs)); + } +} + +/// \brief Creates SLocEntries and updates the locations of macro argument +/// tokens to their new expanded locations. +/// +/// \param ArgIdDefLoc the location of the macro argument id inside the macro +/// definition. +/// \param Tokens the macro argument tokens to update. +void TokenLexer::updateLocForMacroArgTokens(SourceLocation ArgIdSpellLoc, + Token *begin_tokens, + Token *end_tokens) { + SourceManager &SM = PP.getSourceManager(); + + SourceLocation curInst = + getExpansionLocForMacroDefLoc(ArgIdSpellLoc); + assert(curInst.isValid() && + "Expected arg identifier to come from definition"); + + while (begin_tokens < end_tokens) + updateConsecutiveMacroArgTokens(SM, curInst, begin_tokens, end_tokens); +}