summaryrefslogtreecommitdiffstats
path: root/clang-tools-extra/clang-tidy/utils
diff options
context:
space:
mode:
Diffstat (limited to 'clang-tools-extra/clang-tidy/utils')
-rw-r--r--clang-tools-extra/clang-tidy/utils/LexerUtils.cpp61
-rw-r--r--clang-tools-extra/clang-tidy/utils/LexerUtils.h60
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
OpenPOWER on IntegriCloud