[clang-tools-extra] r355024 - [clang-tidy] Add the abseil-time-subtraction check
Hyrum Wright via cfe-commits
cfe-commits at lists.llvm.org
Wed Feb 27 12:08:50 PST 2019
Author: hwright
Date: Wed Feb 27 12:08:50 2019
New Revision: 355024
URL: http://llvm.org/viewvc/llvm-project?rev=355024&view=rev
Log:
[clang-tidy] Add the abseil-time-subtraction check
Differential Revision: https://reviews.llvm.org/D58137
Added:
clang-tools-extra/trunk/clang-tidy/abseil/TimeSubtractionCheck.cpp
clang-tools-extra/trunk/clang-tidy/abseil/TimeSubtractionCheck.h
clang-tools-extra/trunk/docs/clang-tidy/checks/abseil-time-subtraction.rst
clang-tools-extra/trunk/test/clang-tidy/abseil-time-subtraction.cpp
Modified:
clang-tools-extra/trunk/clang-tidy/abseil/AbseilTidyModule.cpp
clang-tools-extra/trunk/clang-tidy/abseil/CMakeLists.txt
clang-tools-extra/trunk/clang-tidy/abseil/DurationRewriter.cpp
clang-tools-extra/trunk/clang-tidy/abseil/DurationRewriter.h
clang-tools-extra/trunk/docs/ReleaseNotes.rst
clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst
clang-tools-extra/trunk/test/clang-tidy/Inputs/absl/time/time.h
Modified: clang-tools-extra/trunk/clang-tidy/abseil/AbseilTidyModule.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/abseil/AbseilTidyModule.cpp?rev=355024&r1=355023&r2=355024&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/abseil/AbseilTidyModule.cpp (original)
+++ clang-tools-extra/trunk/clang-tidy/abseil/AbseilTidyModule.cpp Wed Feb 27 12:08:50 2019
@@ -23,6 +23,7 @@
#include "RedundantStrcatCallsCheck.h"
#include "StringFindStartswithCheck.h"
#include "StrCatAppendCheck.h"
+#include "TimeSubtractionCheck.h"
#include "UpgradeDurationConversionsCheck.h"
namespace clang {
@@ -59,6 +60,8 @@ public:
"abseil-str-cat-append");
CheckFactories.registerCheck<StringFindStartswithCheck>(
"abseil-string-find-startswith");
+ CheckFactories.registerCheck<TimeSubtractionCheck>(
+ "abseil-time-subtraction");
CheckFactories.registerCheck<UpgradeDurationConversionsCheck>(
"abseil-upgrade-duration-conversions");
}
Modified: clang-tools-extra/trunk/clang-tidy/abseil/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/abseil/CMakeLists.txt?rev=355024&r1=355023&r2=355024&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/abseil/CMakeLists.txt (original)
+++ clang-tools-extra/trunk/clang-tidy/abseil/CMakeLists.txt Wed Feb 27 12:08:50 2019
@@ -17,6 +17,7 @@ add_clang_library(clangTidyAbseilModule
RedundantStrcatCallsCheck.cpp
StrCatAppendCheck.cpp
StringFindStartswithCheck.cpp
+ TimeSubtractionCheck.cpp
UpgradeDurationConversionsCheck.cpp
LINK_LIBS
Modified: clang-tools-extra/trunk/clang-tidy/abseil/DurationRewriter.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/abseil/DurationRewriter.cpp?rev=355024&r1=355023&r2=355024&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/abseil/DurationRewriter.cpp (original)
+++ clang-tools-extra/trunk/clang-tidy/abseil/DurationRewriter.cpp Wed Feb 27 12:08:50 2019
@@ -84,6 +84,22 @@ rewriteInverseDurationCall(const MatchFi
return llvm::None;
}
+/// If `Node` is a call to the inverse of `Scale`, return that inverse's
+/// argument, otherwise None.
+static llvm::Optional<std::string>
+rewriteInverseTimeCall(const MatchFinder::MatchResult &Result,
+ DurationScale Scale, const Expr &Node) {
+ llvm::StringRef InverseFunction = getTimeInverseForScale(Scale);
+ if (const auto *MaybeCallArg = selectFirst<const Expr>(
+ "e", match(callExpr(callee(functionDecl(hasName(InverseFunction))),
+ hasArgument(0, expr().bind("e"))),
+ Node, *Result.Context))) {
+ return tooling::fixit::getText(*MaybeCallArg, *Result.Context).str();
+ }
+
+ return llvm::None;
+}
+
/// Returns the factory function name for a given `Scale`.
llvm::StringRef getDurationFactoryForScale(DurationScale Scale) {
switch (Scale) {
@@ -103,6 +119,24 @@ llvm::StringRef getDurationFactoryForSca
llvm_unreachable("unknown scaling factor");
}
+llvm::StringRef getTimeFactoryForScale(DurationScale Scale) {
+ switch (Scale) {
+ case DurationScale::Hours:
+ return "absl::FromUnixHours";
+ case DurationScale::Minutes:
+ return "absl::FromUnixMinutes";
+ case DurationScale::Seconds:
+ return "absl::FromUnixSeconds";
+ case DurationScale::Milliseconds:
+ return "absl::FromUnixMillis";
+ case DurationScale::Microseconds:
+ return "absl::FromUnixMicros";
+ case DurationScale::Nanoseconds:
+ return "absl::FromUnixNanos";
+ }
+ llvm_unreachable("unknown scaling factor");
+}
+
/// Returns the Time factory function name for a given `Scale`.
llvm::StringRef getTimeInverseForScale(DurationScale scale) {
switch (scale) {
@@ -250,6 +284,24 @@ std::string rewriteExprFromNumberToDurat
.str();
}
+std::string rewriteExprFromNumberToTime(
+ const ast_matchers::MatchFinder::MatchResult &Result, DurationScale Scale,
+ const Expr *Node) {
+ const Expr &RootNode = *Node->IgnoreParenImpCasts();
+
+ // First check to see if we can undo a complimentary function call.
+ if (llvm::Optional<std::string> MaybeRewrite =
+ rewriteInverseTimeCall(Result, Scale, RootNode))
+ return *MaybeRewrite;
+
+ if (IsLiteralZero(Result, RootNode))
+ return std::string("absl::UnixEpoch()");
+
+ return (llvm::Twine(getTimeFactoryForScale(Scale)) + "(" +
+ tooling::fixit::getText(RootNode, *Result.Context) + ")")
+ .str();
+}
+
bool isNotInMacro(const MatchFinder::MatchResult &Result, const Expr *E) {
if (!E->getBeginLoc().isMacroID())
return true;
Modified: clang-tools-extra/trunk/clang-tidy/abseil/DurationRewriter.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/abseil/DurationRewriter.h?rev=355024&r1=355023&r2=355024&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/abseil/DurationRewriter.h (original)
+++ clang-tools-extra/trunk/clang-tidy/abseil/DurationRewriter.h Wed Feb 27 12:08:50 2019
@@ -31,6 +31,10 @@ enum class DurationScale : std::uint8_t
/// constructing a `Duration` for that scale.
llvm::StringRef getDurationFactoryForScale(DurationScale Scale);
+/// Given a 'Scale', return the appropriate factory function call for
+/// constructing a `Time` for that scale.
+llvm::StringRef getTimeFactoryForScale(DurationScale scale);
+
// Determine if `Node` represents a literal floating point or integral zero.
bool IsLiteralZero(const ast_matchers::MatchFinder::MatchResult &Result,
const Expr &Node);
@@ -81,6 +85,12 @@ std::string rewriteExprFromNumberToDurat
const ast_matchers::MatchFinder::MatchResult &Result, DurationScale Scale,
const Expr *Node);
+/// Assuming `Node` has a type `int` representing a time instant of `Scale`
+/// since The Epoch, return the expression to make it a suitable `Time`.
+std::string rewriteExprFromNumberToTime(
+ const ast_matchers::MatchFinder::MatchResult &Result, DurationScale Scale,
+ const Expr *Node);
+
/// Return `true` if `E` is a either: not a macro at all; or an argument to
/// one. In the both cases, we often want to do the transformation.
bool isNotInMacro(const ast_matchers::MatchFinder::MatchResult &Result,
Added: clang-tools-extra/trunk/clang-tidy/abseil/TimeSubtractionCheck.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/abseil/TimeSubtractionCheck.cpp?rev=355024&view=auto
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/abseil/TimeSubtractionCheck.cpp (added)
+++ clang-tools-extra/trunk/clang-tidy/abseil/TimeSubtractionCheck.cpp Wed Feb 27 12:08:50 2019
@@ -0,0 +1,181 @@
+//===--- TimeSubtractionCheck.cpp - clang-tidy ----------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "TimeSubtractionCheck.h"
+#include "DurationRewriter.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Tooling/FixIt.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace abseil {
+
+// Returns `true` if `Range` is inside a macro definition.
+static bool InsideMacroDefinition(const MatchFinder::MatchResult &Result,
+ SourceRange Range) {
+ return !clang::Lexer::makeFileCharRange(
+ clang::CharSourceRange::getCharRange(Range),
+ *Result.SourceManager, Result.Context->getLangOpts())
+ .isValid();
+}
+
+static bool isConstructorAssignment(const MatchFinder::MatchResult &Result,
+ const Expr *Node) {
+ return selectFirst<const Expr>(
+ "e", match(expr(hasParent(materializeTemporaryExpr(hasParent(
+ cxxConstructExpr(hasParent(exprWithCleanups(
+ hasParent(varDecl()))))))))
+ .bind("e"),
+ *Node, *Result.Context)) != nullptr;
+}
+
+static bool isArgument(const MatchFinder::MatchResult &Result,
+ const Expr *Node) {
+ return selectFirst<const Expr>(
+ "e",
+ match(expr(hasParent(
+ materializeTemporaryExpr(hasParent(cxxConstructExpr(
+ hasParent(callExpr()),
+ unless(hasParent(cxxOperatorCallExpr())))))))
+ .bind("e"),
+ *Node, *Result.Context)) != nullptr;
+}
+
+static bool isReturn(const MatchFinder::MatchResult &Result, const Expr *Node) {
+ return selectFirst<const Expr>(
+ "e", match(expr(hasParent(materializeTemporaryExpr(hasParent(
+ cxxConstructExpr(hasParent(exprWithCleanups(
+ hasParent(returnStmt()))))))))
+ .bind("e"),
+ *Node, *Result.Context)) != nullptr;
+}
+
+static bool parensRequired(const MatchFinder::MatchResult &Result,
+ const Expr *Node) {
+ // TODO: Figure out any more contexts in which we can omit the surrounding
+ // parentheses.
+ return !(isConstructorAssignment(Result, Node) || isArgument(Result, Node) ||
+ isReturn(Result, Node));
+}
+
+void TimeSubtractionCheck::emitDiagnostic(const Expr *Node,
+ llvm::StringRef Replacement) {
+ diag(Node->getBeginLoc(), "perform subtraction in the time domain")
+ << FixItHint::CreateReplacement(Node->getSourceRange(), Replacement);
+}
+
+void TimeSubtractionCheck::registerMatchers(MatchFinder *Finder) {
+ for (auto ScaleName :
+ {"Hours", "Minutes", "Seconds", "Millis", "Micros", "Nanos"}) {
+ std::string TimeInverse = (llvm::Twine("ToUnix") + ScaleName).str();
+ llvm::Optional<DurationScale> Scale = getScaleForTimeInverse(TimeInverse);
+ assert(Scale && "Unknow scale encountered");
+
+ auto TimeInverseMatcher = callExpr(callee(
+ functionDecl(hasName((llvm::Twine("::absl::") + TimeInverse).str()))
+ .bind("func_decl")));
+
+ // Match the cases where we know that the result is a 'Duration' and the
+ // first argument is a 'Time'. Just knowing the type of the first operand
+ // is not sufficient, since the second operand could be either a 'Time' or
+ // a 'Duration'. If we know the result is a 'Duration', we can then infer
+ // that the second operand must be a 'Time'.
+ auto CallMatcher =
+ callExpr(
+ callee(functionDecl(hasName(getDurationFactoryForScale(*Scale)))),
+ hasArgument(0, binaryOperator(hasOperatorName("-"),
+ hasLHS(TimeInverseMatcher))
+ .bind("binop")))
+ .bind("outer_call");
+ Finder->addMatcher(CallMatcher, this);
+
+ // Match cases where we know the second operand is a 'Time'. Since
+ // subtracting a 'Time' from a 'Duration' is not defined, in these cases,
+ // we always know the first operand is a 'Time' if the second is a 'Time'.
+ auto OperandMatcher =
+ binaryOperator(hasOperatorName("-"), hasRHS(TimeInverseMatcher))
+ .bind("binop");
+ Finder->addMatcher(OperandMatcher, this);
+ }
+}
+
+void TimeSubtractionCheck::check(const MatchFinder::MatchResult &Result) {
+ const auto *BinOp = Result.Nodes.getNodeAs<BinaryOperator>("binop");
+ std::string InverseName =
+ Result.Nodes.getNodeAs<FunctionDecl>("func_decl")->getNameAsString();
+ if (InsideMacroDefinition(Result, BinOp->getSourceRange()))
+ return;
+
+ llvm::Optional<DurationScale> Scale = getScaleForTimeInverse(InverseName);
+ if (!Scale)
+ return;
+
+ const auto *OuterCall = Result.Nodes.getNodeAs<CallExpr>("outer_call");
+ if (OuterCall) {
+ if (InsideMacroDefinition(Result, OuterCall->getSourceRange()))
+ return;
+
+ // We're working with the first case of matcher, and need to replace the
+ // entire 'Duration' factory call. (Which also means being careful about
+ // our order-of-operations and optionally putting in some parenthesis.
+ bool NeedParens = parensRequired(Result, OuterCall);
+
+ emitDiagnostic(
+ OuterCall,
+ (llvm::Twine(NeedParens ? "(" : "") +
+ rewriteExprFromNumberToTime(Result, *Scale, BinOp->getLHS()) + " - " +
+ rewriteExprFromNumberToTime(Result, *Scale, BinOp->getRHS()) +
+ (NeedParens ? ")" : ""))
+ .str());
+ } else {
+ // We're working with the second case of matcher, and either just need to
+ // change the arguments, or perhaps remove an outer function call. In the
+ // latter case (addressed first), we also need to worry about parenthesis.
+ const auto *MaybeCallArg = selectFirst<const CallExpr>(
+ "arg", match(expr(hasAncestor(
+ callExpr(callee(functionDecl(hasName(
+ getDurationFactoryForScale(*Scale)))))
+ .bind("arg"))),
+ *BinOp, *Result.Context));
+ if (MaybeCallArg && MaybeCallArg->getArg(0)->IgnoreImpCasts() == BinOp &&
+ !InsideMacroDefinition(Result, MaybeCallArg->getSourceRange())) {
+ // Handle the case where the matched expression is inside a call which
+ // converts it from the inverse to a Duration. In this case, we replace
+ // the outer with just the subtraction expresison, which gives the right
+ // type and scale, taking care again about parenthesis.
+ bool NeedParens = parensRequired(Result, MaybeCallArg);
+
+ emitDiagnostic(
+ MaybeCallArg,
+ (llvm::Twine(NeedParens ? "(" : "") +
+ rewriteExprFromNumberToTime(Result, *Scale, BinOp->getLHS()) +
+ " - " +
+ rewriteExprFromNumberToTime(Result, *Scale, BinOp->getRHS()) +
+ (NeedParens ? ")" : ""))
+ .str());
+ } else {
+ // In the last case, just convert the arguments and wrap the result in
+ // the correct inverse function.
+ emitDiagnostic(
+ BinOp,
+ (llvm::Twine(
+ getDurationInverseForScale(*Scale).second.str().substr(2)) +
+ "(" + rewriteExprFromNumberToTime(Result, *Scale, BinOp->getLHS()) +
+ " - " +
+ rewriteExprFromNumberToTime(Result, *Scale, BinOp->getRHS()) + ")")
+ .str());
+ }
+ }
+}
+
+} // namespace abseil
+} // namespace tidy
+} // namespace clang
Added: clang-tools-extra/trunk/clang-tidy/abseil/TimeSubtractionCheck.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/abseil/TimeSubtractionCheck.h?rev=355024&view=auto
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/abseil/TimeSubtractionCheck.h (added)
+++ clang-tools-extra/trunk/clang-tidy/abseil/TimeSubtractionCheck.h Wed Feb 27 12:08:50 2019
@@ -0,0 +1,38 @@
+//===--- TimeSubtractionCheck.h - clang-tidy --------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ABSEIL_TIMESUBTRACTIONCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ABSEIL_TIMESUBTRACTIONCHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace abseil {
+
+/// Finds and fixes `absl::Time` subtraction expressions to do subtraction
+/// in the time domain instead of the numeric domain.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/abseil-time-subtraction.html
+class TimeSubtractionCheck : public ClangTidyCheck {
+public:
+ TimeSubtractionCheck(StringRef Name, ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context) {}
+ void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+ void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+ void emitDiagnostic(const Expr* Node, llvm::StringRef Replacement);
+};
+
+} // namespace abseil
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ABSEIL_TIMESUBTRACTIONCHECK_H
Modified: clang-tools-extra/trunk/docs/ReleaseNotes.rst
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/ReleaseNotes.rst?rev=355024&r1=355023&r2=355024&view=diff
==============================================================================
--- clang-tools-extra/trunk/docs/ReleaseNotes.rst (original)
+++ clang-tools-extra/trunk/docs/ReleaseNotes.rst Wed Feb 27 12:08:50 2019
@@ -85,6 +85,12 @@ Improvements to clang-tidy
Finds and fixes cases where ``absl::Duration`` values are being converted to
numeric types and back again.
+- New :doc:`abseil-time-subtraction
+ <clang-tidy/checks/abseil-time-subtraction>` check.
+
+ Finds and fixes ``absl::Time`` subtraction expressions to do subtraction
+ in the Time domain instead of the numeric domain.
+
- New :doc:`google-readability-avoid-underscore-in-googletest-name
<clang-tidy/checks/google-readability-avoid-underscore-in-googletest-name>`
check.
Added: clang-tools-extra/trunk/docs/clang-tidy/checks/abseil-time-subtraction.rst
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/clang-tidy/checks/abseil-time-subtraction.rst?rev=355024&view=auto
==============================================================================
--- clang-tools-extra/trunk/docs/clang-tidy/checks/abseil-time-subtraction.rst (added)
+++ clang-tools-extra/trunk/docs/clang-tidy/checks/abseil-time-subtraction.rst Wed Feb 27 12:08:50 2019
@@ -0,0 +1,37 @@
+.. title:: clang-tidy - abseil-time-subtraction
+
+abseil-time-subtraction
+=======================
+
+Finds and fixes ``absl::Time`` subtraction expressions to do subtraction
+in the Time domain instead of the numeric domain.
+
+There are two cases of Time subtraction in which deduce additional type
+information:
+ - When the result is an ``absl::Duration`` and the first argument is an
+ ``absl::Time``.
+ - When the second argument is a ``absl::Time``.
+
+In the first case, we must know the result of the operation, since without that
+the second operand could be either an ``absl::Time`` or an ``absl::Duration``.
+In the second case, the first operand *must* be an ``absl::Time``, because
+subtracting an ``absl::Time`` from an ``absl::Duration`` is not defined.
+
+Examples:
+
+.. code-block:: c++
+ int x;
+ absl::Time t;
+
+ // Original - absl::Duration result and first operand is a absl::Time.
+ absl::Duration d = absl::Seconds(absl::ToUnixSeconds(t) - x);
+
+ // Suggestion - Perform subtraction in the Time domain instead.
+ absl::Duration d = t - absl::FromUnixSeconds(x);
+
+
+ // Original - Second operand is an absl::Time.
+ int i = x - absl::ToUnixSeconds(t);
+
+ // Suggestion - Perform subtraction in the Time domain instead.
+ int i = absl::ToInt64Seconds(absl::FromUnixSeconds(x) - t);
Modified: clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst?rev=355024&r1=355023&r2=355024&view=diff
==============================================================================
--- clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst (original)
+++ clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst Wed Feb 27 12:08:50 2019
@@ -18,6 +18,7 @@ Clang-Tidy Checks
abseil-redundant-strcat-calls
abseil-str-cat-append
abseil-string-find-startswith
+ abseil-time-subtraction
abseil-upgrade-duration-conversions
android-cloexec-accept
android-cloexec-accept4
Modified: clang-tools-extra/trunk/test/clang-tidy/Inputs/absl/time/time.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/Inputs/absl/time/time.h?rev=355024&r1=355023&r2=355024&view=diff
==============================================================================
--- clang-tools-extra/trunk/test/clang-tidy/Inputs/absl/time/time.h (original)
+++ clang-tools-extra/trunk/test/clang-tidy/Inputs/absl/time/time.h Wed Feb 27 12:08:50 2019
@@ -70,6 +70,8 @@ Time FromUnixMillis(int64_t);
Time FromUnixMicros(int64_t);
Time FromUnixNanos(int64_t);
+Time Now();
+
// Relational Operators
constexpr bool operator<(Duration lhs, Duration rhs);
constexpr bool operator>(Duration lhs, Duration rhs);
Added: clang-tools-extra/trunk/test/clang-tidy/abseil-time-subtraction.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/abseil-time-subtraction.cpp?rev=355024&view=auto
==============================================================================
--- clang-tools-extra/trunk/test/clang-tidy/abseil-time-subtraction.cpp (added)
+++ clang-tools-extra/trunk/test/clang-tidy/abseil-time-subtraction.cpp Wed Feb 27 12:08:50 2019
@@ -0,0 +1,117 @@
+// RUN: %check_clang_tidy %s abseil-time-subtraction %t -- -- -I%S/Inputs
+
+#include "absl/time/time.h"
+
+void g(absl::Duration d);
+
+void f() {
+ absl::Time t;
+ int x, y;
+ absl::Duration d;
+
+ d = absl::Hours(absl::ToUnixHours(t) - x);
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+ // CHECK-FIXES: d = (t - absl::FromUnixHours(x));
+ d = absl::Minutes(absl::ToUnixMinutes(t) - x);
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+ // CHECK-FIXES: d = (t - absl::FromUnixMinutes(x));
+ d = absl::Seconds(absl::ToUnixSeconds(t) - x);
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+ // CHECK-FIXES: d = (t - absl::FromUnixSeconds(x));
+ d = absl::Milliseconds(absl::ToUnixMillis(t) - x);
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+ // CHECK-FIXES: d = (t - absl::FromUnixMillis(x));
+ d = absl::Microseconds(absl::ToUnixMicros(t) - x);
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+ // CHECK-FIXES: d = (t - absl::FromUnixMicros(x));
+ d = absl::Nanoseconds(absl::ToUnixNanos(t) - x);
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+ // CHECK-FIXES: d = (t - absl::FromUnixNanos(x));
+
+ y = x - absl::ToUnixHours(t);
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+ // CHECK-FIXES: y = absl::ToInt64Hours(absl::FromUnixHours(x) - t);
+ y = x - absl::ToUnixMinutes(t);
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+ // CHECK-FIXES: y = absl::ToInt64Minutes(absl::FromUnixMinutes(x) - t);
+ y = x - absl::ToUnixSeconds(t);
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+ // CHECK-FIXES: y = absl::ToInt64Seconds(absl::FromUnixSeconds(x) - t);
+ y = x - absl::ToUnixMillis(t);
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+ // CHECK-FIXES: y = absl::ToInt64Milliseconds(absl::FromUnixMillis(x) - t);
+ y = x - absl::ToUnixMicros(t);
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+ // CHECK-FIXES: y = absl::ToInt64Microseconds(absl::FromUnixMicros(x) - t);
+ y = x - absl::ToUnixNanos(t);
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+ // CHECK-FIXES: y = absl::ToInt64Nanoseconds(absl::FromUnixNanos(x) - t);
+
+ // Check parenthesis placement
+ d = 5 * absl::Seconds(absl::ToUnixSeconds(t) - x);
+ // CHECK-MESSAGES: [[@LINE-1]]:11: warning: perform subtraction in the time domain [abseil-time-subtraction]
+ // CHECK-FIXES: d = 5 * (t - absl::FromUnixSeconds(x));
+ d = absl::Seconds(absl::ToUnixSeconds(t) - x) / 5;
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+ // CHECK-FIXES: d = (t - absl::FromUnixSeconds(x)) / 5;
+
+ // No extra parens around arguments
+ g(absl::Seconds(absl::ToUnixSeconds(t) - x));
+ // CHECK-MESSAGES: [[@LINE-1]]:5: warning: perform subtraction in the time domain [abseil-time-subtraction]
+ // CHECK-FIXES: g(t - absl::FromUnixSeconds(x));
+ g(absl::Seconds(x - absl::ToUnixSeconds(t)));
+ // CHECK-MESSAGES: [[@LINE-1]]:5: warning: perform subtraction in the time domain [abseil-time-subtraction]
+ // CHECK-FIXES: g(absl::FromUnixSeconds(x) - t);
+
+ // More complex subexpressions
+ d = absl::Hours(absl::ToUnixHours(t) - 5 * x);
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: perform subtraction in the time domain [abseil-time-subtraction]
+ // CHECK-FIXES: d = (t - absl::FromUnixHours(5 * x));
+
+ // These should not trigger; they are likely bugs
+ d = absl::Milliseconds(absl::ToUnixSeconds(t) - x);
+ d = absl::Seconds(absl::ToUnixMicros(t) - x);
+
+ // Various macro scenarios
+#define SUB(z, t1) z - absl::ToUnixSeconds(t1)
+ y = SUB(x, t);
+#undef SUB
+
+#define MILLIS(t1) absl::ToUnixMillis(t1)
+ y = x - MILLIS(t);
+#undef MILLIS
+
+#define HOURS(z) absl::Hours(z)
+ d = HOURS(absl::ToUnixHours(t) - x);
+#undef HOURS
+
+ // This should match the expression inside the macro invocation.
+#define SECONDS(z) absl::Seconds(z)
+ d = SECONDS(x - absl::ToUnixSeconds(t));
+ // CHECK-MESSAGES: [[@LINE-1]]:15: warning: perform subtraction in the time domain [abseil-time-subtraction]
+ // CHECK-FIXES: SECONDS(absl::ToInt64Seconds(absl::FromUnixSeconds(x) - t))
+#undef SECONDS
+}
+
+template<typename T>
+void func(absl::Time t, T x) {
+ absl::Duration d = absl::Seconds(absl::ToUnixSeconds(t) - x);
+ // CHECK-MESSAGES: [[@LINE-1]]:22: warning: perform subtraction in the time domain [abseil-time-subtraction]
+ // CHECK-FIXES: absl::Duration d = t - absl::FromUnixSeconds(x);
+}
+
+void g() {
+ func(absl::Now(), 5);
+}
+
+absl::Duration parens_in_return() {
+ absl::Time t;
+ int x;
+
+ return absl::Seconds(absl::ToUnixSeconds(t) - x);
+ // CHECK-MESSAGES: [[@LINE-1]]:10: warning: perform subtraction in the time domain [abseil-time-subtraction]
+ // CHECK-FIXES: return t - absl::FromUnixSeconds(x);
+ return absl::Seconds(x - absl::ToUnixSeconds(t));
+ // CHECK-MESSAGES: [[@LINE-1]]:10: warning: perform subtraction in the time domain [abseil-time-subtraction]
+ // CHECK-FIXES: return absl::FromUnixSeconds(x) - t;
+}
More information about the cfe-commits
mailing list