summaryrefslogtreecommitdiffstats
path: root/clang-tools-extra/clang-tidy/utils
diff options
context:
space:
mode:
authorJonas Toth <jonas.toth@gmail.com>2018-10-31 16:50:44 +0000
committerJonas Toth <jonas.toth@gmail.com>2018-10-31 16:50:44 +0000
commit0ea5af7acb33c8b455edea3a02ee2ffcbbcad3f8 (patch)
tree8cece7013e098f165ee66914058a38aa6038c432 /clang-tools-extra/clang-tidy/utils
parent1c254c6716cd01a228c5c35a225a45e6d8ee51ad (diff)
downloadbcm5719-llvm-0ea5af7acb33c8b455edea3a02ee2ffcbbcad3f8.tar.gz
bcm5719-llvm-0ea5af7acb33c8b455edea3a02ee2ffcbbcad3f8.zip
[clang-tidy] new check 'readability-isolate-declaration'
Summary: This patch introduces a new clang-tidy check that matches on all `declStmt` that declare more then one variable and transform them into one statement per declaration if possible. It currently only focusses on variable declarations but should be extended to cover more kinds of declarations in the future. It is related to https://reviews.llvm.org/D27621 and does use it's extensive test-suite. Thank you to firolino for his work! Reviewers: rsmith, aaron.ballman, alexfh, hokein, kbobyrev Reviewed By: aaron.ballman Subscribers: ZaMaZaN4iK, mgehre, nemanjai, kbarton, lebedev.ri, Eugene.Zelenko, mgorny, xazax.hun, cfe-commits Tags: #clang-tools-extra Differential Revision: https://reviews.llvm.org/D51949 llvm-svn: 345735
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