diff options
Diffstat (limited to 'clang-tools-extra/clang-tidy/utils')
-rw-r--r-- | clang-tools-extra/clang-tidy/utils/LexerUtils.cpp | 61 | ||||
-rw-r--r-- | clang-tools-extra/clang-tidy/utils/LexerUtils.h | 60 |
2 files changed, 121 insertions, 0 deletions
diff --git a/clang-tools-extra/clang-tidy/utils/LexerUtils.cpp b/clang-tools-extra/clang-tidy/utils/LexerUtils.cpp index 1b52347e45d..82097978129 100644 --- a/clang-tools-extra/clang-tidy/utils/LexerUtils.cpp +++ b/clang-tools-extra/clang-tidy/utils/LexerUtils.cpp @@ -31,6 +31,67 @@ Token getPreviousToken(SourceLocation Location, const SourceManager &SM, return Token; } +SourceLocation findPreviousTokenStart(SourceLocation Start, + const SourceManager &SM, + const LangOptions &LangOpts) { + if (Start.isInvalid() || Start.isMacroID()) + return SourceLocation(); + + SourceLocation BeforeStart = Start.getLocWithOffset(-1); + if (BeforeStart.isInvalid() || BeforeStart.isMacroID()) + return SourceLocation(); + + return Lexer::GetBeginningOfToken(BeforeStart, SM, LangOpts); +} + +SourceLocation findPreviousTokenKind(SourceLocation Start, + const SourceManager &SM, + const LangOptions &LangOpts, + tok::TokenKind TK) { + while (true) { + SourceLocation L = findPreviousTokenStart(Start, SM, LangOpts); + if (L.isInvalid() || L.isMacroID()) + return SourceLocation(); + + Token T; + if (Lexer::getRawToken(L, T, SM, LangOpts, /*IgnoreWhiteSpace=*/true)) + return SourceLocation(); + + if (T.is(TK)) + return T.getLocation(); + + Start = L; + } +} + +SourceLocation findNextTerminator(SourceLocation Start, const SourceManager &SM, + const LangOptions &LangOpts) { + return findNextAnyTokenKind(Start, SM, LangOpts, tok::comma, tok::semi); +} + +bool rangeContainsExpansionsOrDirectives(SourceRange Range, + const SourceManager &SM, + const LangOptions &LangOpts) { + assert(Range.isValid() && "Invalid Range for relexing provided"); + SourceLocation Loc = Range.getBegin(); + + while (Loc < Range.getEnd()) { + if (Loc.isMacroID()) + return true; + + llvm::Optional<Token> Tok = Lexer::findNextToken(Loc, SM, LangOpts); + + if (!Tok) + return true; + + if (Tok->is(tok::hash)) + return true; + + Loc = Lexer::getLocForEndOfToken(Loc, 0, SM, LangOpts).getLocWithOffset(1); + } + + return false; +} } // namespace lexer } // namespace utils } // namespace tidy diff --git a/clang-tools-extra/clang-tidy/utils/LexerUtils.h b/clang-tools-extra/clang-tidy/utils/LexerUtils.h index 0eb5e56ef64..f81fdae4b52 100644 --- a/clang-tools-extra/clang-tidy/utils/LexerUtils.h +++ b/clang-tools-extra/clang-tidy/utils/LexerUtils.h @@ -22,6 +22,66 @@ namespace lexer { Token getPreviousToken(SourceLocation Location, const SourceManager &SM, const LangOptions &LangOpts, bool SkipComments = true); +SourceLocation findPreviousTokenStart(SourceLocation Start, + const SourceManager &SM, + const LangOptions &LangOpts); + +SourceLocation findPreviousTokenKind(SourceLocation Start, + const SourceManager &SM, + const LangOptions &LangOpts, + tok::TokenKind TK); + +SourceLocation findNextTerminator(SourceLocation Start, const SourceManager &SM, + const LangOptions &LangOpts); + +template <typename TokenKind, typename... TokenKinds> +SourceLocation findPreviousAnyTokenKind(SourceLocation Start, + const SourceManager &SM, + const LangOptions &LangOpts, + TokenKind TK, TokenKinds... TKs) { + while (true) { + SourceLocation L = findPreviousTokenStart(Start, SM, LangOpts); + if (L.isInvalid() || L.isMacroID()) + return SourceLocation(); + + Token T; + // Returning 'true' is used to signal failure to retrieve the token. + if (Lexer::getRawToken(L, T, SM, LangOpts)) + return SourceLocation(); + + if (T.isOneOf(TK, TKs...)) + return T.getLocation(); + + Start = L; + } +} + +template <typename TokenKind, typename... TokenKinds> +SourceLocation findNextAnyTokenKind(SourceLocation Start, + const SourceManager &SM, + const LangOptions &LangOpts, TokenKind TK, + TokenKinds... TKs) { + while (true) { + Optional<Token> CurrentToken = Lexer::findNextToken(Start, SM, LangOpts); + + if (!CurrentToken) + return SourceLocation(); + + Token PotentialMatch = *CurrentToken; + if (PotentialMatch.isOneOf(TK, TKs...)) + return PotentialMatch.getLocation(); + + Start = PotentialMatch.getLastLoc(); + } +} + +/// Re-lex the provide \p Range and return \c false if either a macro spans +/// multiple tokens, a pre-processor directive or failure to retrieve the +/// next token is found, otherwise \c true. +bool rangeContainsExpansionsOrDirectives(SourceRange Range, + const SourceManager &SM, + const LangOptions &LangOpts); + } // namespace lexer } // namespace utils } // namespace tidy |