// 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); }
SourceLocation Utils::locForNextToken(SourceLocation loc, const clang::SourceManager &sm, const clang::LangOptions &lo) { std::pair<FileID, unsigned> locInfo = sm.getDecomposedLoc(loc); bool InvalidTemp = false; StringRef File = sm.getBufferData(locInfo.first, &InvalidTemp); if (InvalidTemp) { llvm::errs() << "Failed to get buffer data\n"; return {}; } const char *TokenBegin = File.data() + locInfo.second; Lexer lexer(sm.getLocForStartOfFile(locInfo.first), lo, File.begin(), TokenBegin, File.end()); Token Tok; lexer.LexFromRawLexer(Tok); SourceLocation TokenLoc = Tok.getLocation(); // Calculate how much whitespace needs to be skipped if any. unsigned NumWhitespaceChars = 0; const char *TokenEnd = sm.getCharacterData(TokenLoc) + Tok.getLength(); unsigned char C = *TokenEnd; while (isHorizontalWhitespace(C)) { C = *(++TokenEnd); NumWhitespaceChars++; } // Skip \r, \n, \r\n, or \n\r if (C == '\n' || C == '\r') { char PrevC = C; C = *(++TokenEnd); NumWhitespaceChars++; if ((C == '\n' || C == '\r') && C != PrevC) NumWhitespaceChars++; } return loc.getLocWithOffset(Tok.getLength() + NumWhitespaceChars); }