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 | 85e7671b71a49beba14db59ebb87fc16b5a7fcb7 (patch) | |
tree | 2f8636bd9be40176283b484ce0fe9e40ea92633c /clang/lib/Lex/Lexer.cpp | |
parent | 528f56c93fc6a80f1827da2c4128c497d1dcbe37 (diff) | |
download | bcm5719-llvm-85e7671b71a49beba14db59ebb87fc16b5a7fcb7.tar.gz bcm5719-llvm-85e7671b71a49beba14db59ebb87fc16b5a7fcb7.zip |
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.
llvm-svn: 148551
Diffstat (limited to 'clang/lib/Lex/Lexer.cpp')
-rw-r--r-- | clang/lib/Lex/Lexer.cpp | 72 |
1 files changed, 61 insertions, 11 deletions
diff --git a/clang/lib/Lex/Lexer.cpp b/clang/lib/Lex/Lexer.cpp index 12cb76722bf..967359f2616 100644 --- a/clang/lib/Lex/Lexer.cpp +++ b/clang/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, |