12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182 |
- //===--- DurationConversionCastCheck.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 "DurationConversionCastCheck.h"
- #include "DurationRewriter.h"
- #include "clang/AST/ASTContext.h"
- #include "clang/ASTMatchers/ASTMatchFinder.h"
- #include "clang/Tooling/FixIt.h"
- #include <optional>
- using namespace clang::ast_matchers;
- namespace clang::tidy::abseil {
- void DurationConversionCastCheck::registerMatchers(MatchFinder *Finder) {
- auto CallMatcher = ignoringImpCasts(callExpr(
- callee(functionDecl(DurationConversionFunction()).bind("func_decl")),
- hasArgument(0, expr().bind("arg"))));
- Finder->addMatcher(
- expr(anyOf(
- cxxStaticCastExpr(hasSourceExpression(CallMatcher)).bind("cast_expr"),
- cStyleCastExpr(hasSourceExpression(CallMatcher)).bind("cast_expr"),
- cxxFunctionalCastExpr(hasSourceExpression(CallMatcher))
- .bind("cast_expr"))),
- this);
- }
- void DurationConversionCastCheck::check(
- const MatchFinder::MatchResult &Result) {
- const auto *MatchedCast =
- Result.Nodes.getNodeAs<ExplicitCastExpr>("cast_expr");
- if (isInMacro(Result, MatchedCast))
- return;
- const auto *FuncDecl = Result.Nodes.getNodeAs<FunctionDecl>("func_decl");
- const auto *Arg = Result.Nodes.getNodeAs<Expr>("arg");
- StringRef ConversionFuncName = FuncDecl->getName();
- std::optional<DurationScale> Scale =
- getScaleForDurationInverse(ConversionFuncName);
- if (!Scale)
- return;
- // Casting a double to an integer.
- if (MatchedCast->getTypeAsWritten()->isIntegerType() &&
- ConversionFuncName.contains("Double")) {
- llvm::StringRef NewFuncName = getDurationInverseForScale(*Scale).second;
- diag(MatchedCast->getBeginLoc(),
- "duration should be converted directly to an integer rather than "
- "through a type cast")
- << FixItHint::CreateReplacement(
- MatchedCast->getSourceRange(),
- (llvm::Twine(NewFuncName.substr(2)) + "(" +
- tooling::fixit::getText(*Arg, *Result.Context) + ")")
- .str());
- }
- // Casting an integer to a double.
- if (MatchedCast->getTypeAsWritten()->isRealFloatingType() &&
- ConversionFuncName.contains("Int64")) {
- llvm::StringRef NewFuncName = getDurationInverseForScale(*Scale).first;
- diag(MatchedCast->getBeginLoc(), "duration should be converted directly to "
- "a floating-point number rather than "
- "through a type cast")
- << FixItHint::CreateReplacement(
- MatchedCast->getSourceRange(),
- (llvm::Twine(NewFuncName.substr(2)) + "(" +
- tooling::fixit::getText(*Arg, *Result.Context) + ")")
- .str());
- }
- }
- } // namespace clang::tidy::abseil
|