summaryrefslogtreecommitdiffstats
path: root/clang-tools-extra/clang-tidy/abseil/DurationRewriter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang-tools-extra/clang-tidy/abseil/DurationRewriter.cpp')
-rw-r--r--clang-tools-extra/clang-tidy/abseil/DurationRewriter.cpp109
1 files changed, 109 insertions, 0 deletions
diff --git a/clang-tools-extra/clang-tidy/abseil/DurationRewriter.cpp b/clang-tools-extra/clang-tidy/abseil/DurationRewriter.cpp
new file mode 100644
index 00000000000..b8a0f535f34
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/abseil/DurationRewriter.cpp
@@ -0,0 +1,109 @@
+//===--- DurationRewriter.cpp - clang-tidy --------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DurationRewriter.h"
+#include "clang/Tooling/FixIt.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace abseil {
+
+/// Returns an integer if the fractional part of a `FloatingLiteral` is `0`.
+static llvm::Optional<llvm::APSInt>
+truncateIfIntegral(const FloatingLiteral &FloatLiteral) {
+ double Value = FloatLiteral.getValueAsApproximateDouble();
+ if (std::fmod(Value, 1) == 0) {
+ if (Value >= static_cast<double>(1u << 31))
+ return llvm::None;
+
+ return llvm::APSInt::get(static_cast<int64_t>(Value));
+ }
+ return llvm::None;
+}
+
+/// Returns the factory function name for a given `Scale`.
+llvm::StringRef getFactoryForScale(DurationScale Scale) {
+ switch (Scale) {
+ case DurationScale::Hours:
+ return "absl::Hours";
+ case DurationScale::Minutes:
+ return "absl::Minutes";
+ case DurationScale::Seconds:
+ return "absl::Seconds";
+ case DurationScale::Milliseconds:
+ return "absl::Milliseconds";
+ case DurationScale::Microseconds:
+ return "absl::Microseconds";
+ case DurationScale::Nanoseconds:
+ return "absl::Nanoseconds";
+ }
+ llvm_unreachable("unknown scaling factor");
+}
+
+/// Returns `true` if `Node` is a value which evaluates to a literal `0`.
+bool IsLiteralZero(const MatchFinder::MatchResult &Result, const Expr &Node) {
+ return selectFirst<const clang::Expr>(
+ "val",
+ match(expr(ignoringImpCasts(anyOf(integerLiteral(equals(0)),
+ floatLiteral(equals(0.0)))))
+ .bind("val"),
+ Node, *Result.Context)) != nullptr;
+}
+
+llvm::Optional<std::string>
+stripFloatCast(const ast_matchers::MatchFinder::MatchResult &Result,
+ const Expr &Node) {
+ if (const Expr *MaybeCastArg = selectFirst<const Expr>(
+ "cast_arg",
+ match(expr(anyOf(cxxStaticCastExpr(
+ hasDestinationType(realFloatingPointType()),
+ hasSourceExpression(expr().bind("cast_arg"))),
+ cStyleCastExpr(
+ hasDestinationType(realFloatingPointType()),
+ hasSourceExpression(expr().bind("cast_arg"))),
+ cxxFunctionalCastExpr(
+ hasDestinationType(realFloatingPointType()),
+ hasSourceExpression(expr().bind("cast_arg"))))),
+ Node, *Result.Context)))
+ return tooling::fixit::getText(*MaybeCastArg, *Result.Context).str();
+
+ return llvm::None;
+}
+
+llvm::Optional<std::string>
+stripFloatLiteralFraction(const MatchFinder::MatchResult &Result,
+ const Expr &Node) {
+ if (const auto *LitFloat = llvm::dyn_cast<FloatingLiteral>(&Node))
+ // Attempt to simplify a `Duration` factory call with a literal argument.
+ if (llvm::Optional<llvm::APSInt> IntValue = truncateIfIntegral(*LitFloat))
+ return IntValue->toString(/*radix=*/10);
+
+ return llvm::None;
+}
+
+std::string simplifyDurationFactoryArg(const MatchFinder::MatchResult &Result,
+ const Expr &Node) {
+ // Check for an explicit cast to `float` or `double`.
+ if (llvm::Optional<std::string> MaybeArg = stripFloatCast(Result, Node))
+ return *MaybeArg;
+
+ // Check for floats without fractional components.
+ if (llvm::Optional<std::string> MaybeArg =
+ stripFloatLiteralFraction(Result, Node))
+ return *MaybeArg;
+
+ // We couldn't simplify any further, so return the argument text.
+ return tooling::fixit::getText(Node, *Result.Context).str();
+}
+
+} // namespace abseil
+} // namespace tidy
+} // namespace clang
OpenPOWER on IntegriCloud