[clang-tidy] Recommit: Add the abseil-duration-comparison check
Summary:
This check finds instances where Duration values are being converted to a numeric value in a comparison expression, and suggests that the conversion happen on the other side of the expression to a Duration. See documentation for examples.
This also shuffles some code around so that the new check may perform in sone step simplifications also caught by other checks.
Compilation is unbroken, because the hash-function is now directly
specified for std::unordered_map, as 'enum class' does not compile as
key (seamingly only on some compilers).
Patch by hwright.
Reviewers: aaron.ballman, JonasToth, alexfh, hokein
Reviewed By: JonasToth
Subscribers: sammccall, Eugene.Zelenko, xazax.hun, cfe-commits, mgorny
Tags: #clang-tools-extra
Differential Revision: https://reviews.llvm.org/D54737
llvm-svn: 348169
2018-12-04 03:22:08 +08:00
|
|
|
//===--- DurationRewriter.cpp - clang-tidy --------------------------------===//
|
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// 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
|
[clang-tidy] Recommit: Add the abseil-duration-comparison check
Summary:
This check finds instances where Duration values are being converted to a numeric value in a comparison expression, and suggests that the conversion happen on the other side of the expression to a Duration. See documentation for examples.
This also shuffles some code around so that the new check may perform in sone step simplifications also caught by other checks.
Compilation is unbroken, because the hash-function is now directly
specified for std::unordered_map, as 'enum class' does not compile as
key (seamingly only on some compilers).
Patch by hwright.
Reviewers: aaron.ballman, JonasToth, alexfh, hokein
Reviewed By: JonasToth
Subscribers: sammccall, Eugene.Zelenko, xazax.hun, cfe-commits, mgorny
Tags: #clang-tools-extra
Differential Revision: https://reviews.llvm.org/D54737
llvm-svn: 348169
2018-12-04 03:22:08 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "DurationRewriter.h"
|
|
|
|
#include "clang/Tooling/FixIt.h"
|
2018-12-14 03:23:52 +08:00
|
|
|
#include "llvm/ADT/IndexedMap.h"
|
[clang-tidy] Recommit: Add the abseil-duration-comparison check
Summary:
This check finds instances where Duration values are being converted to a numeric value in a comparison expression, and suggests that the conversion happen on the other side of the expression to a Duration. See documentation for examples.
This also shuffles some code around so that the new check may perform in sone step simplifications also caught by other checks.
Compilation is unbroken, because the hash-function is now directly
specified for std::unordered_map, as 'enum class' does not compile as
key (seamingly only on some compilers).
Patch by hwright.
Reviewers: aaron.ballman, JonasToth, alexfh, hokein
Reviewed By: JonasToth
Subscribers: sammccall, Eugene.Zelenko, xazax.hun, cfe-commits, mgorny
Tags: #clang-tools-extra
Differential Revision: https://reviews.llvm.org/D54737
llvm-svn: 348169
2018-12-04 03:22:08 +08:00
|
|
|
|
|
|
|
using namespace clang::ast_matchers;
|
|
|
|
|
|
|
|
namespace clang {
|
|
|
|
namespace tidy {
|
|
|
|
namespace abseil {
|
|
|
|
|
2018-12-14 03:23:52 +08:00
|
|
|
struct DurationScale2IndexFunctor {
|
|
|
|
using argument_type = DurationScale;
|
|
|
|
unsigned operator()(DurationScale Scale) const {
|
|
|
|
return static_cast<unsigned>(Scale);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
[clang-tidy] Recommit: Add the abseil-duration-comparison check
Summary:
This check finds instances where Duration values are being converted to a numeric value in a comparison expression, and suggests that the conversion happen on the other side of the expression to a Duration. See documentation for examples.
This also shuffles some code around so that the new check may perform in sone step simplifications also caught by other checks.
Compilation is unbroken, because the hash-function is now directly
specified for std::unordered_map, as 'enum class' does not compile as
key (seamingly only on some compilers).
Patch by hwright.
Reviewers: aaron.ballman, JonasToth, alexfh, hokein
Reviewed By: JonasToth
Subscribers: sammccall, Eugene.Zelenko, xazax.hun, cfe-commits, mgorny
Tags: #clang-tools-extra
Differential Revision: https://reviews.llvm.org/D54737
llvm-svn: 348169
2018-12-04 03:22:08 +08:00
|
|
|
/// 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;
|
|
|
|
}
|
|
|
|
|
2018-12-29 03:04:21 +08:00
|
|
|
const std::pair<llvm::StringRef, llvm::StringRef> &
|
2019-01-25 03:23:50 +08:00
|
|
|
getDurationInverseForScale(DurationScale Scale) {
|
2018-12-14 03:23:52 +08:00
|
|
|
static const llvm::IndexedMap<std::pair<llvm::StringRef, llvm::StringRef>,
|
|
|
|
DurationScale2IndexFunctor>
|
|
|
|
InverseMap = []() {
|
2020-04-05 14:28:11 +08:00
|
|
|
// TODO: Revisit the immediately invoked lambda technique when
|
2018-12-14 03:23:52 +08:00
|
|
|
// IndexedMap gets an initializer list constructor.
|
|
|
|
llvm::IndexedMap<std::pair<llvm::StringRef, llvm::StringRef>,
|
|
|
|
DurationScale2IndexFunctor>
|
|
|
|
InverseMap;
|
|
|
|
InverseMap.resize(6);
|
|
|
|
InverseMap[DurationScale::Hours] =
|
|
|
|
std::make_pair("::absl::ToDoubleHours", "::absl::ToInt64Hours");
|
|
|
|
InverseMap[DurationScale::Minutes] =
|
|
|
|
std::make_pair("::absl::ToDoubleMinutes", "::absl::ToInt64Minutes");
|
|
|
|
InverseMap[DurationScale::Seconds] =
|
|
|
|
std::make_pair("::absl::ToDoubleSeconds", "::absl::ToInt64Seconds");
|
|
|
|
InverseMap[DurationScale::Milliseconds] = std::make_pair(
|
|
|
|
"::absl::ToDoubleMilliseconds", "::absl::ToInt64Milliseconds");
|
|
|
|
InverseMap[DurationScale::Microseconds] = std::make_pair(
|
|
|
|
"::absl::ToDoubleMicroseconds", "::absl::ToInt64Microseconds");
|
|
|
|
InverseMap[DurationScale::Nanoseconds] = std::make_pair(
|
|
|
|
"::absl::ToDoubleNanoseconds", "::absl::ToInt64Nanoseconds");
|
|
|
|
return InverseMap;
|
|
|
|
}();
|
|
|
|
|
|
|
|
return InverseMap[Scale];
|
|
|
|
}
|
|
|
|
|
|
|
|
/// If `Node` is a call to the inverse of `Scale`, return that inverse's
|
|
|
|
/// argument, otherwise None.
|
|
|
|
static llvm::Optional<std::string>
|
|
|
|
rewriteInverseDurationCall(const MatchFinder::MatchResult &Result,
|
|
|
|
DurationScale Scale, const Expr &Node) {
|
|
|
|
const std::pair<llvm::StringRef, llvm::StringRef> &InverseFunctions =
|
2019-01-25 03:23:50 +08:00
|
|
|
getDurationInverseForScale(Scale);
|
2018-12-14 03:23:52 +08:00
|
|
|
if (const auto *MaybeCallArg = selectFirst<const Expr>(
|
|
|
|
"e",
|
|
|
|
match(callExpr(callee(functionDecl(hasAnyName(
|
|
|
|
InverseFunctions.first, InverseFunctions.second))),
|
|
|
|
hasArgument(0, expr().bind("e"))),
|
|
|
|
Node, *Result.Context))) {
|
|
|
|
return tooling::fixit::getText(*MaybeCallArg, *Result.Context).str();
|
|
|
|
}
|
|
|
|
|
|
|
|
return llvm::None;
|
|
|
|
}
|
|
|
|
|
2019-02-28 04:08:50 +08:00
|
|
|
/// 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>(
|
2020-01-29 17:52:25 +08:00
|
|
|
"e", match(callExpr(callee(functionDecl(hasName(InverseFunction))),
|
2019-02-28 04:08:50 +08:00
|
|
|
hasArgument(0, expr().bind("e"))),
|
|
|
|
Node, *Result.Context))) {
|
|
|
|
return tooling::fixit::getText(*MaybeCallArg, *Result.Context).str();
|
|
|
|
}
|
|
|
|
|
|
|
|
return llvm::None;
|
|
|
|
}
|
|
|
|
|
[clang-tidy] Recommit: Add the abseil-duration-comparison check
Summary:
This check finds instances where Duration values are being converted to a numeric value in a comparison expression, and suggests that the conversion happen on the other side of the expression to a Duration. See documentation for examples.
This also shuffles some code around so that the new check may perform in sone step simplifications also caught by other checks.
Compilation is unbroken, because the hash-function is now directly
specified for std::unordered_map, as 'enum class' does not compile as
key (seamingly only on some compilers).
Patch by hwright.
Reviewers: aaron.ballman, JonasToth, alexfh, hokein
Reviewed By: JonasToth
Subscribers: sammccall, Eugene.Zelenko, xazax.hun, cfe-commits, mgorny
Tags: #clang-tools-extra
Differential Revision: https://reviews.llvm.org/D54737
llvm-svn: 348169
2018-12-04 03:22:08 +08:00
|
|
|
/// Returns the factory function name for a given `Scale`.
|
2019-01-25 03:23:50 +08:00
|
|
|
llvm::StringRef getDurationFactoryForScale(DurationScale Scale) {
|
[clang-tidy] Recommit: Add the abseil-duration-comparison check
Summary:
This check finds instances where Duration values are being converted to a numeric value in a comparison expression, and suggests that the conversion happen on the other side of the expression to a Duration. See documentation for examples.
This also shuffles some code around so that the new check may perform in sone step simplifications also caught by other checks.
Compilation is unbroken, because the hash-function is now directly
specified for std::unordered_map, as 'enum class' does not compile as
key (seamingly only on some compilers).
Patch by hwright.
Reviewers: aaron.ballman, JonasToth, alexfh, hokein
Reviewed By: JonasToth
Subscribers: sammccall, Eugene.Zelenko, xazax.hun, cfe-commits, mgorny
Tags: #clang-tools-extra
Differential Revision: https://reviews.llvm.org/D54737
llvm-svn: 348169
2018-12-04 03:22:08 +08:00
|
|
|
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");
|
|
|
|
}
|
|
|
|
|
2019-02-28 04:08:50 +08:00
|
|
|
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");
|
|
|
|
}
|
|
|
|
|
2019-01-28 22:03:09 +08:00
|
|
|
/// Returns the Time factory function name for a given `Scale`.
|
2021-01-29 07:49:53 +08:00
|
|
|
llvm::StringRef getTimeInverseForScale(DurationScale Scale) {
|
|
|
|
switch (Scale) {
|
2019-01-28 22:03:09 +08:00
|
|
|
case DurationScale::Hours:
|
|
|
|
return "absl::ToUnixHours";
|
|
|
|
case DurationScale::Minutes:
|
|
|
|
return "absl::ToUnixMinutes";
|
|
|
|
case DurationScale::Seconds:
|
|
|
|
return "absl::ToUnixSeconds";
|
|
|
|
case DurationScale::Milliseconds:
|
|
|
|
return "absl::ToUnixMillis";
|
|
|
|
case DurationScale::Microseconds:
|
|
|
|
return "absl::ToUnixMicros";
|
|
|
|
case DurationScale::Nanoseconds:
|
|
|
|
return "absl::ToUnixNanos";
|
|
|
|
}
|
|
|
|
llvm_unreachable("unknown scaling factor");
|
|
|
|
}
|
|
|
|
|
[clang-tidy] Recommit: Add the abseil-duration-comparison check
Summary:
This check finds instances where Duration values are being converted to a numeric value in a comparison expression, and suggests that the conversion happen on the other side of the expression to a Duration. See documentation for examples.
This also shuffles some code around so that the new check may perform in sone step simplifications also caught by other checks.
Compilation is unbroken, because the hash-function is now directly
specified for std::unordered_map, as 'enum class' does not compile as
key (seamingly only on some compilers).
Patch by hwright.
Reviewers: aaron.ballman, JonasToth, alexfh, hokein
Reviewed By: JonasToth
Subscribers: sammccall, Eugene.Zelenko, xazax.hun, cfe-commits, mgorny
Tags: #clang-tools-extra
Differential Revision: https://reviews.llvm.org/D54737
llvm-svn: 348169
2018-12-04 03:22:08 +08:00
|
|
|
/// Returns `true` if `Node` is a value which evaluates to a literal `0`.
|
|
|
|
bool IsLiteralZero(const MatchFinder::MatchResult &Result, const Expr &Node) {
|
2018-12-22 05:07:11 +08:00
|
|
|
auto ZeroMatcher =
|
|
|
|
anyOf(integerLiteral(equals(0)), floatLiteral(equals(0.0)));
|
|
|
|
|
|
|
|
// Check to see if we're using a zero directly.
|
|
|
|
if (selectFirst<const clang::Expr>(
|
|
|
|
"val", match(expr(ignoringImpCasts(ZeroMatcher)).bind("val"), Node,
|
|
|
|
*Result.Context)) != nullptr)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// Now check to see if we're using a functional cast with a scalar
|
|
|
|
// initializer expression, e.g. `int{0}`.
|
|
|
|
if (selectFirst<const clang::Expr>(
|
2019-01-07 22:36:47 +08:00
|
|
|
"val", match(cxxFunctionalCastExpr(
|
|
|
|
hasDestinationType(
|
|
|
|
anyOf(isInteger(), realFloatingPointType())),
|
|
|
|
hasSourceExpression(initListExpr(
|
|
|
|
hasInit(0, ignoringParenImpCasts(ZeroMatcher)))))
|
|
|
|
.bind("val"),
|
|
|
|
Node, *Result.Context)) != nullptr)
|
2018-12-22 05:07:11 +08:00
|
|
|
return true;
|
|
|
|
|
|
|
|
return false;
|
[clang-tidy] Recommit: Add the abseil-duration-comparison check
Summary:
This check finds instances where Duration values are being converted to a numeric value in a comparison expression, and suggests that the conversion happen on the other side of the expression to a Duration. See documentation for examples.
This also shuffles some code around so that the new check may perform in sone step simplifications also caught by other checks.
Compilation is unbroken, because the hash-function is now directly
specified for std::unordered_map, as 'enum class' does not compile as
key (seamingly only on some compilers).
Patch by hwright.
Reviewers: aaron.ballman, JonasToth, alexfh, hokein
Reviewed By: JonasToth
Subscribers: sammccall, Eugene.Zelenko, xazax.hun, cfe-commits, mgorny
Tags: #clang-tools-extra
Differential Revision: https://reviews.llvm.org/D54737
llvm-svn: 348169
2018-12-04 03:22:08 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
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))
|
2021-06-11 20:19:00 +08:00
|
|
|
return toString(*IntValue, /*radix=*/10);
|
[clang-tidy] Recommit: Add the abseil-duration-comparison check
Summary:
This check finds instances where Duration values are being converted to a numeric value in a comparison expression, and suggests that the conversion happen on the other side of the expression to a Duration. See documentation for examples.
This also shuffles some code around so that the new check may perform in sone step simplifications also caught by other checks.
Compilation is unbroken, because the hash-function is now directly
specified for std::unordered_map, as 'enum class' does not compile as
key (seamingly only on some compilers).
Patch by hwright.
Reviewers: aaron.ballman, JonasToth, alexfh, hokein
Reviewed By: JonasToth
Subscribers: sammccall, Eugene.Zelenko, xazax.hun, cfe-commits, mgorny
Tags: #clang-tools-extra
Differential Revision: https://reviews.llvm.org/D54737
llvm-svn: 348169
2018-12-04 03:22:08 +08:00
|
|
|
|
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
2019-01-25 03:23:50 +08:00
|
|
|
llvm::Optional<DurationScale> getScaleForDurationInverse(llvm::StringRef Name) {
|
2018-12-14 03:23:52 +08:00
|
|
|
static const llvm::StringMap<DurationScale> ScaleMap(
|
|
|
|
{{"ToDoubleHours", DurationScale::Hours},
|
|
|
|
{"ToInt64Hours", DurationScale::Hours},
|
|
|
|
{"ToDoubleMinutes", DurationScale::Minutes},
|
|
|
|
{"ToInt64Minutes", DurationScale::Minutes},
|
|
|
|
{"ToDoubleSeconds", DurationScale::Seconds},
|
|
|
|
{"ToInt64Seconds", DurationScale::Seconds},
|
|
|
|
{"ToDoubleMilliseconds", DurationScale::Milliseconds},
|
|
|
|
{"ToInt64Milliseconds", DurationScale::Milliseconds},
|
|
|
|
{"ToDoubleMicroseconds", DurationScale::Microseconds},
|
|
|
|
{"ToInt64Microseconds", DurationScale::Microseconds},
|
|
|
|
{"ToDoubleNanoseconds", DurationScale::Nanoseconds},
|
|
|
|
{"ToInt64Nanoseconds", DurationScale::Nanoseconds}});
|
|
|
|
|
|
|
|
auto ScaleIter = ScaleMap.find(std::string(Name));
|
|
|
|
if (ScaleIter == ScaleMap.end())
|
|
|
|
return llvm::None;
|
|
|
|
|
|
|
|
return ScaleIter->second;
|
|
|
|
}
|
|
|
|
|
2019-01-28 22:03:09 +08:00
|
|
|
llvm::Optional<DurationScale> getScaleForTimeInverse(llvm::StringRef Name) {
|
|
|
|
static const llvm::StringMap<DurationScale> ScaleMap(
|
|
|
|
{{"ToUnixHours", DurationScale::Hours},
|
|
|
|
{"ToUnixMinutes", DurationScale::Minutes},
|
|
|
|
{"ToUnixSeconds", DurationScale::Seconds},
|
|
|
|
{"ToUnixMillis", DurationScale::Milliseconds},
|
|
|
|
{"ToUnixMicros", DurationScale::Microseconds},
|
|
|
|
{"ToUnixNanos", DurationScale::Nanoseconds}});
|
|
|
|
|
|
|
|
auto ScaleIter = ScaleMap.find(std::string(Name));
|
|
|
|
if (ScaleIter == ScaleMap.end())
|
|
|
|
return llvm::None;
|
|
|
|
|
|
|
|
return ScaleIter->second;
|
|
|
|
}
|
|
|
|
|
2018-12-20 00:03:34 +08:00
|
|
|
std::string rewriteExprFromNumberToDuration(
|
2018-12-14 03:23:52 +08:00
|
|
|
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 =
|
|
|
|
rewriteInverseDurationCall(Result, Scale, RootNode))
|
|
|
|
return *MaybeRewrite;
|
|
|
|
|
|
|
|
if (IsLiteralZero(Result, RootNode))
|
|
|
|
return std::string("absl::ZeroDuration()");
|
|
|
|
|
2019-01-25 03:23:50 +08:00
|
|
|
return (llvm::Twine(getDurationFactoryForScale(Scale)) + "(" +
|
2018-12-14 03:23:52 +08:00
|
|
|
simplifyDurationFactoryArg(Result, RootNode) + ")")
|
|
|
|
.str();
|
|
|
|
}
|
|
|
|
|
2019-02-28 04:08:50 +08:00
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
2019-03-08 23:37:15 +08:00
|
|
|
bool isInMacro(const MatchFinder::MatchResult &Result, const Expr *E) {
|
2019-01-16 22:49:32 +08:00
|
|
|
if (!E->getBeginLoc().isMacroID())
|
2019-03-08 23:37:15 +08:00
|
|
|
return false;
|
2019-01-16 22:49:32 +08:00
|
|
|
|
|
|
|
SourceLocation Loc = E->getBeginLoc();
|
|
|
|
// We want to get closer towards the initial macro typed into the source only
|
|
|
|
// if the location is being expanded as a macro argument.
|
|
|
|
while (Result.SourceManager->isMacroArgExpansion(Loc)) {
|
|
|
|
// We are calling getImmediateMacroCallerLoc, but note it is essentially
|
|
|
|
// equivalent to calling getImmediateSpellingLoc in this context according
|
|
|
|
// to Clang implementation. We are not calling getImmediateSpellingLoc
|
|
|
|
// because Clang comment says it "should not generally be used by clients."
|
|
|
|
Loc = Result.SourceManager->getImmediateMacroCallerLoc(Loc);
|
|
|
|
}
|
2019-03-08 23:37:15 +08:00
|
|
|
return Loc.isMacroID();
|
2019-01-16 22:49:32 +08:00
|
|
|
}
|
|
|
|
|
[clang-tidy] Recommit: Add the abseil-duration-comparison check
Summary:
This check finds instances where Duration values are being converted to a numeric value in a comparison expression, and suggests that the conversion happen on the other side of the expression to a Duration. See documentation for examples.
This also shuffles some code around so that the new check may perform in sone step simplifications also caught by other checks.
Compilation is unbroken, because the hash-function is now directly
specified for std::unordered_map, as 'enum class' does not compile as
key (seamingly only on some compilers).
Patch by hwright.
Reviewers: aaron.ballman, JonasToth, alexfh, hokein
Reviewed By: JonasToth
Subscribers: sammccall, Eugene.Zelenko, xazax.hun, cfe-commits, mgorny
Tags: #clang-tools-extra
Differential Revision: https://reviews.llvm.org/D54737
llvm-svn: 348169
2018-12-04 03:22:08 +08:00
|
|
|
} // namespace abseil
|
|
|
|
} // namespace tidy
|
|
|
|
} // namespace clang
|