// Get the source range of the specified Stmt, ensuring that a semicolon is // included, if necessary - since the clang ranges do not guarantee this. SrcRange getStmtRangeWithSemicolon(const clang::Stmt *S, const clang::SourceManager& sm, const clang::LangOptions& options) { clang::SourceLocation SLoc = sm.getExpansionLoc(S->getLocStart()); clang::SourceLocation ELoc = sm.getExpansionLoc(S->getLocEnd()); unsigned start = sm.getFileOffset(SLoc); unsigned end = sm.getFileOffset(ELoc); // Below code copied from clang::Lexer::MeasureTokenLength(): clang::SourceLocation Loc = sm.getExpansionLoc(ELoc); std::pair<clang::FileID, unsigned> LocInfo = sm.getDecomposedLoc(Loc); llvm::StringRef Buffer = sm.getBufferData(LocInfo.first); const char *StrData = Buffer.data()+LocInfo.second; clang::Lexer TheLexer(Loc, options, Buffer.begin(), StrData, Buffer.end()); clang::Token TheTok; TheLexer.LexFromRawLexer(TheTok); // End copied code. end += TheTok.getLength(); // Check if we the source range did include the semicolon. if (TheTok.isNot(clang::tok::semi) && TheTok.isNot(clang::tok::r_brace)) { TheLexer.LexFromRawLexer(TheTok); if (TheTok.is(clang::tok::semi)) { end += TheTok.getLength(); } } return SrcRange(start, end); }
// Get the source range of the macro definition excluding the #define. SrcRange getMacroRange(const clang::MacroInfo *MI, const clang::SourceManager& sm, const clang::LangOptions& options) { clang::SourceLocation SLoc = sm.getExpansionLoc(MI->getDefinitionLoc()); clang::SourceLocation ELoc = sm.getExpansionLoc(MI->getDefinitionEndLoc()); return constructSrcRange(sm, options, SLoc, ELoc); }
// Get the source range of the specified Stmt. SrcRange getStmtRange(const clang::Stmt *S, const clang::SourceManager& sm, const clang::LangOptions& options) { clang::SourceLocation SLoc = sm.getExpansionLoc(S->getLocStart()); clang::SourceLocation ELoc = sm.getExpansionLoc(S->getLocEnd()); // This is necessary to get the correct range of function-like macros. if (SLoc == ELoc && S->getLocEnd().isMacroID()) ELoc = sm.getExpansionRange(S->getLocEnd()).second; return constructSrcRange(sm, options, SLoc, ELoc); }
clang::SourceLocation getExpansionLoc(const clang::SourceManager& sm, clang::SourceLocation loc) { if(sm.isMacroArgExpansion(loc)) { loc = sm.getExpansionLoc(loc); } return loc; }