aboutsummaryrefslogtreecommitdiff
path: root/clang-tidy/utils
diff options
context:
space:
mode:
authorAaron Ballman <aaron@aaronballman.com>2018-10-31 19:11:38 +0000
committerAaron Ballman <aaron@aaronballman.com>2018-10-31 19:11:38 +0000
commita1e6c8120333420e029d41b72716b15617518034 (patch)
tree1bdb94bc1040748cc0150e739175b2538c5495e4 /clang-tidy/utils
parent764c358561448cb2b87636432b9e14b9904d012c (diff)
Implement the readability-const-return-type check.
This check flags function top-level const-qualified return types and suggests removing the mostly-superfluous const qualifier where possible. Patch by Yitzhak Mandelbaum. git-svn-id: https://llvm.org/svn/llvm-project/clang-tools-extra/trunk@345764 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'clang-tidy/utils')
-rw-r--r--clang-tidy/utils/LexerUtils.cpp28
-rw-r--r--clang-tidy/utils/LexerUtils.h8
2 files changed, 36 insertions, 0 deletions
diff --git a/clang-tidy/utils/LexerUtils.cpp b/clang-tidy/utils/LexerUtils.cpp
index 82097978..edd4cd62 100644
--- a/clang-tidy/utils/LexerUtils.cpp
+++ b/clang-tidy/utils/LexerUtils.cpp
@@ -92,6 +92,34 @@ bool rangeContainsExpansionsOrDirectives(SourceRange Range,
return false;
}
+
+llvm::Optional<Token> getConstQualifyingToken(CharSourceRange Range,
+ const ASTContext &Context,
+ const SourceManager &SM) {
+ std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Range.getBegin());
+ StringRef File = SM.getBufferData(LocInfo.first);
+ Lexer RawLexer(SM.getLocForStartOfFile(LocInfo.first), Context.getLangOpts(),
+ File.begin(), File.data() + LocInfo.second, File.end());
+ llvm::Optional<Token> FirstConstTok;
+ Token LastTokInRange;
+ Token Tok;
+ while (!RawLexer.LexFromRawLexer(Tok) &&
+ Range.getEnd() != Tok.getLocation() &&
+ !SM.isBeforeInTranslationUnit(Range.getEnd(), Tok.getLocation())) {
+ if (Tok.is(tok::raw_identifier)) {
+ IdentifierInfo &Info = Context.Idents.get(
+ StringRef(SM.getCharacterData(Tok.getLocation()), Tok.getLength()));
+ Tok.setIdentifierInfo(&Info);
+ Tok.setKind(Info.getTokenID());
+ }
+ if (Tok.is(tok::kw_const) && !FirstConstTok)
+ FirstConstTok = Tok;
+ LastTokInRange = Tok;
+ }
+ // If the last token in the range is a `const`, then it const qualifies the
+ // type. Otherwise, the first `const` token, if any, is the qualifier.
+ return LastTokInRange.is(tok::kw_const) ? LastTokInRange : FirstConstTok;
+}
} // namespace lexer
} // namespace utils
} // namespace tidy
diff --git a/clang-tidy/utils/LexerUtils.h b/clang-tidy/utils/LexerUtils.h
index f81fdae4..55a8b85c 100644
--- a/clang-tidy/utils/LexerUtils.h
+++ b/clang-tidy/utils/LexerUtils.h
@@ -82,6 +82,14 @@ bool rangeContainsExpansionsOrDirectives(SourceRange Range,
const SourceManager &SM,
const LangOptions &LangOpts);
+/// Assuming that ``Range`` spans a const-qualified type, returns the ``const``
+/// token in ``Range`` that is responsible for const qualification. ``Range``
+/// must be valid with respect to ``SM``. Returns ``None`` if no ``const``
+/// tokens are found.
+llvm::Optional<Token> getConstQualifyingToken(CharSourceRange Range,
+ const ASTContext &Context,
+ const SourceManager &SM);
+
} // namespace lexer
} // namespace utils
} // namespace tidy