clang::Token GetTokenBefore(const clang::SourceManager &sources, clang::SourceLocation loc) { clang::Token token; token.setKind(clang::tok::unknown); clang::LangOptions lang_options; loc = loc.getLocWithOffset(-1); while (loc != sources.getLocForStartOfFile(sources.getFileID(loc))) { loc = clang::Lexer::GetBeginningOfToken(loc, sources, lang_options); if (!clang::Lexer::getRawToken(loc, token, sources, lang_options)) { if (!token.is(clang::tok::comment)) { break; } } loc = loc.getLocWithOffset(-1); } return token; }
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); }