summaryrefslogtreecommitdiffstats
path: root/clang-tidy/abseil/DurationRewriter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang-tidy/abseil/DurationRewriter.cpp')
-rw-r--r--clang-tidy/abseil/DurationRewriter.cpp121
1 files changed, 112 insertions, 9 deletions
diff --git a/clang-tidy/abseil/DurationRewriter.cpp b/clang-tidy/abseil/DurationRewriter.cpp
index ed648897..3466cdbb 100644
--- a/clang-tidy/abseil/DurationRewriter.cpp
+++ b/clang-tidy/abseil/DurationRewriter.cpp
@@ -1,9 +1,8 @@
//===--- 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.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -38,7 +37,7 @@ truncateIfIntegral(const FloatingLiteral &FloatLiteral) {
}
const std::pair<llvm::StringRef, llvm::StringRef> &
-getInverseForScale(DurationScale Scale) {
+getDurationInverseForScale(DurationScale Scale) {
static const llvm::IndexedMap<std::pair<llvm::StringRef, llvm::StringRef>,
DurationScale2IndexFunctor>
InverseMap = []() {
@@ -72,7 +71,7 @@ static llvm::Optional<std::string>
rewriteInverseDurationCall(const MatchFinder::MatchResult &Result,
DurationScale Scale, const Expr &Node) {
const std::pair<llvm::StringRef, llvm::StringRef> &InverseFunctions =
- getInverseForScale(Scale);
+ getDurationInverseForScale(Scale);
if (const auto *MaybeCallArg = selectFirst<const Expr>(
"e",
match(callExpr(callee(functionDecl(hasAnyName(
@@ -85,8 +84,24 @@ rewriteInverseDurationCall(const MatchFinder::MatchResult &Result,
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 getFactoryForScale(DurationScale Scale) {
+llvm::StringRef getDurationFactoryForScale(DurationScale Scale) {
switch (Scale) {
case DurationScale::Hours:
return "absl::Hours";
@@ -104,6 +119,43 @@ llvm::StringRef getFactoryForScale(DurationScale Scale) {
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) {
+ 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");
+}
+
/// Returns `true` if `Node` is a value which evaluates to a literal `0`.
bool IsLiteralZero(const MatchFinder::MatchResult &Result, const Expr &Node) {
auto ZeroMatcher =
@@ -176,7 +228,7 @@ std::string simplifyDurationFactoryArg(const MatchFinder::MatchResult &Result,
return tooling::fixit::getText(Node, *Result.Context).str();
}
-llvm::Optional<DurationScale> getScaleForInverse(llvm::StringRef Name) {
+llvm::Optional<DurationScale> getScaleForDurationInverse(llvm::StringRef Name) {
static const llvm::StringMap<DurationScale> ScaleMap(
{{"ToDoubleHours", DurationScale::Hours},
{"ToInt64Hours", DurationScale::Hours},
@@ -198,6 +250,22 @@ llvm::Optional<DurationScale> getScaleForInverse(llvm::StringRef Name) {
return ScaleIter->second;
}
+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;
+}
+
std::string rewriteExprFromNumberToDuration(
const ast_matchers::MatchFinder::MatchResult &Result, DurationScale Scale,
const Expr *Node) {
@@ -211,11 +279,46 @@ std::string rewriteExprFromNumberToDuration(
if (IsLiteralZero(Result, RootNode))
return std::string("absl::ZeroDuration()");
- return (llvm::Twine(getFactoryForScale(Scale)) + "(" +
+ return (llvm::Twine(getDurationFactoryForScale(Scale)) + "(" +
simplifyDurationFactoryArg(Result, RootNode) + ")")
.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 isInMacro(const MatchFinder::MatchResult &Result, const Expr *E) {
+ if (!E->getBeginLoc().isMacroID())
+ return false;
+
+ 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);
+ }
+ return Loc.isMacroID();
+}
+
} // namespace abseil
} // namespace tidy
} // namespace clang