diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2018-04-30 05:25:48 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2018-04-30 05:25:48 +0000 |
commit | ef91bd38cd94e34b4b0a30e225e507f5c10087d3 (patch) | |
tree | a32eb01379c5c7f1f1bcd6a2528cabeedda12c80 /lib/Basic/SourceManager.cpp | |
parent | 9ab08c3357404e43c970e2e7438c796dd33f4593 (diff) | |
download | clang-ef91bd38cd94e34b4b0a30e225e507f5c10087d3.tar.gz |
PR37189 Fix incorrect end source location and spelling for a split '>>' token.
When a '>>' token is split into two '>' tokens (in C++11 onwards), or (as an
extension) when we do the same for other tokens starting with a '>', we can't
just use a location pointing to the first '>' as the location of the split
token, because that would result in our miscomputing the length and spelling
for the token. As a consequence, for example, a refactoring replacing 'A<X>'
with something else would sometimes replace one character too many, and
similarly diagnostics highlighting a template-id source range would highlight
one character too many.
Fix this by creating an expansion range covering the first character of the
'>>' token, whose spelling is '>'. For this to work, we generalize the
expansion range of a macro FileID to be either a token range (the common case)
or a character range (used in this new case).
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@331155 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Basic/SourceManager.cpp')
-rw-r--r-- | lib/Basic/SourceManager.cpp | 39 |
1 files changed, 26 insertions, 13 deletions
diff --git a/lib/Basic/SourceManager.cpp b/lib/Basic/SourceManager.cpp index 3df2015bfe..d5e71e9363 100644 --- a/lib/Basic/SourceManager.cpp +++ b/lib/Basic/SourceManager.cpp @@ -579,13 +579,24 @@ SourceManager::createExpansionLoc(SourceLocation SpellingLoc, SourceLocation ExpansionLocStart, SourceLocation ExpansionLocEnd, unsigned TokLength, + bool ExpansionIsTokenRange, int LoadedID, unsigned LoadedOffset) { - ExpansionInfo Info = ExpansionInfo::create(SpellingLoc, ExpansionLocStart, - ExpansionLocEnd); + ExpansionInfo Info = ExpansionInfo::create( + SpellingLoc, ExpansionLocStart, ExpansionLocEnd, ExpansionIsTokenRange); return createExpansionLocImpl(Info, TokLength, LoadedID, LoadedOffset); } +SourceLocation SourceManager::createTokenSplitLoc(SourceLocation Spelling, + SourceLocation TokenStart, + SourceLocation TokenEnd) { + assert(getFileID(TokenStart) == getFileID(TokenEnd) && + "token spans multiple files"); + return createExpansionLocImpl( + ExpansionInfo::createForTokenSplit(Spelling, TokenStart, TokenEnd), + TokenEnd.getOffset() - TokenStart.getOffset()); +} + SourceLocation SourceManager::createExpansionLocImpl(const ExpansionInfo &Info, unsigned TokLength, @@ -895,7 +906,7 @@ SourceLocation SourceManager::getFileLocSlowCase(SourceLocation Loc) const { if (isMacroArgExpansion(Loc)) Loc = getImmediateSpellingLoc(Loc); else - Loc = getImmediateExpansionRange(Loc).first; + Loc = getImmediateExpansionRange(Loc).getBegin(); } while (!Loc.isFileID()); return Loc; } @@ -950,7 +961,7 @@ SourceLocation SourceManager::getImmediateSpellingLoc(SourceLocation Loc) const{ /// getImmediateExpansionRange - Loc is required to be an expansion location. /// Return the start/end of the expansion information. -std::pair<SourceLocation,SourceLocation> +CharSourceRange SourceManager::getImmediateExpansionRange(SourceLocation Loc) const { assert(Loc.isMacroID() && "Not a macro expansion loc!"); const ExpansionInfo &Expansion = getSLocEntry(getFileID(Loc)).getExpansion(); @@ -965,19 +976,21 @@ SourceLocation SourceManager::getTopMacroCallerLoc(SourceLocation Loc) const { /// getExpansionRange - Given a SourceLocation object, return the range of /// tokens covered by the expansion in the ultimate file. -std::pair<SourceLocation,SourceLocation> -SourceManager::getExpansionRange(SourceLocation Loc) const { - if (Loc.isFileID()) return std::make_pair(Loc, Loc); +CharSourceRange SourceManager::getExpansionRange(SourceLocation Loc) const { + if (Loc.isFileID()) + return CharSourceRange(SourceRange(Loc, Loc), true); - std::pair<SourceLocation,SourceLocation> Res = - getImmediateExpansionRange(Loc); + CharSourceRange Res = getImmediateExpansionRange(Loc); // Fully resolve the start and end locations to their ultimate expansion // points. - while (!Res.first.isFileID()) - Res.first = getImmediateExpansionRange(Res.first).first; - while (!Res.second.isFileID()) - Res.second = getImmediateExpansionRange(Res.second).second; + while (!Res.getBegin().isFileID()) + Res.setBegin(getImmediateExpansionRange(Res.getBegin()).getBegin()); + while (!Res.getEnd().isFileID()) { + CharSourceRange EndRange = getImmediateExpansionRange(Res.getEnd()); + Res.setEnd(EndRange.getEnd()); + Res.setTokenRange(EndRange.isTokenRange()); + } return Res; } |