diff options
author | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2012-01-20 16:52:43 +0000 |
---|---|---|
committer | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2012-01-20 16:52:43 +0000 |
commit | d9806c912ae3e870a733acfd83c26e8a1f6a5ffc (patch) | |
tree | 2c88ac00c99f519f46538c980b2168cf1c1034c3 /lib/Lex/Lexer.cpp | |
parent | 74fe66181db91d45d48f57abe325ea487e32ddbc (diff) |
Enhance Lexer::makeFileCharRange to check for ranges inside a macro argument
expansion, in which case it returns a file range in the location where the
argument was spelled.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@148551 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Lex/Lexer.cpp')
-rw-r--r-- | lib/Lex/Lexer.cpp | 72 |
1 files changed, 61 insertions, 11 deletions
diff --git a/lib/Lex/Lexer.cpp b/lib/Lex/Lexer.cpp index 12cb76722b..967359f261 100644 --- a/lib/Lex/Lexer.cpp +++ b/lib/Lex/Lexer.cpp @@ -30,6 +30,7 @@ #include "clang/Lex/CodeCompletionHandler.h" #include "clang/Basic/SourceManager.h" #include "llvm/ADT/StringSwitch.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/MemoryBuffer.h" #include <cstring> @@ -792,6 +793,30 @@ bool Lexer::isAtEndOfMacroExpansion(SourceLocation loc, return isAtEndOfMacroExpansion(expansionLoc, SM, LangOpts, MacroEnd); } +static CharSourceRange makeRangeFromFileLocs(SourceLocation Begin, + SourceLocation End, + const SourceManager &SM, + const LangOptions &LangOpts) { + assert(Begin.isFileID() && End.isFileID()); + End = Lexer::getLocForEndOfToken(End, 0, SM,LangOpts); + if (End.isInvalid()) + return CharSourceRange(); + + // Break down the source locations. + FileID FID; + unsigned BeginOffs; + llvm::tie(FID, BeginOffs) = SM.getDecomposedLoc(Begin); + if (FID.isInvalid()) + return CharSourceRange(); + + unsigned EndOffs; + if (!SM.isInFileID(End, FID, &EndOffs) || + BeginOffs > EndOffs) + return CharSourceRange(); + + return CharSourceRange::getCharRange(Begin, End); +} + /// \brief Accepts a token source range and returns a character range with /// file locations. /// Returns a null range if a part of the range resides inside a macro @@ -800,28 +825,53 @@ CharSourceRange Lexer::makeFileCharRange(SourceRange TokenRange, const SourceManager &SM, const LangOptions &LangOpts) { SourceLocation Begin = TokenRange.getBegin(); - if (Begin.isInvalid()) + SourceLocation End = TokenRange.getEnd(); + if (Begin.isInvalid() || End.isInvalid()) return CharSourceRange(); - if (Begin.isMacroID()) + if (Begin.isFileID() && End.isFileID()) + return makeRangeFromFileLocs(Begin, End, SM, LangOpts); + + if (Begin.isMacroID() && End.isFileID()) { if (!isAtStartOfMacroExpansion(Begin, SM, LangOpts, &Begin)) return CharSourceRange(); + return makeRangeFromFileLocs(Begin, End, SM, LangOpts); + } - SourceLocation End = getLocForEndOfToken(TokenRange.getEnd(), 0, SM,LangOpts); - if (End.isInvalid()) - return CharSourceRange(); + if (Begin.isFileID() && End.isMacroID()) { + if (!isAtEndOfMacroExpansion(End, SM, LangOpts, &End)) + return CharSourceRange(); + return makeRangeFromFileLocs(Begin, End, SM, LangOpts); + } - // Break down the source locations. - std::pair<FileID, unsigned> beginInfo = SM.getDecomposedLoc(Begin); - if (beginInfo.first.isInvalid()) + assert(Begin.isMacroID() && End.isMacroID()); + SourceLocation MacroBegin, MacroEnd; + if (isAtStartOfMacroExpansion(Begin, SM, LangOpts, &MacroBegin) && + isAtEndOfMacroExpansion(End, SM, LangOpts, &MacroEnd)) + return makeRangeFromFileLocs(MacroBegin, MacroEnd, SM, LangOpts); + + FileID FID; + unsigned BeginOffs; + llvm::tie(FID, BeginOffs) = SM.getDecomposedLoc(Begin); + if (FID.isInvalid()) return CharSourceRange(); unsigned EndOffs; - if (!SM.isInFileID(End, beginInfo.first, &EndOffs) || - beginInfo.second > EndOffs) + if (!SM.isInFileID(End, FID, &EndOffs) || + BeginOffs > EndOffs) return CharSourceRange(); - return CharSourceRange::getCharRange(Begin, End); + const SrcMgr::SLocEntry *E = &SM.getSLocEntry(FID); + const SrcMgr::ExpansionInfo &Expansion = E->getExpansion(); + if (Expansion.isMacroArgExpansion() && + Expansion.getSpellingLoc().isFileID()) { + SourceLocation SpellLoc = Expansion.getSpellingLoc(); + return makeRangeFromFileLocs(SpellLoc.getLocWithOffset(BeginOffs), + SpellLoc.getLocWithOffset(EndOffs), + SM, LangOpts); + } + + return CharSourceRange(); } StringRef Lexer::getSourceText(CharSourceRange Range, |