brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.0 KiB · ef06a9e Raw
85 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "DurationConversionCastCheck.h"10#include "DurationRewriter.h"11#include "clang/AST/ASTContext.h"12#include "clang/ASTMatchers/ASTMatchFinder.h"13#include "clang/Tooling/FixIt.h"14#include <optional>15 16using namespace clang::ast_matchers;17 18namespace clang::tidy::abseil {19 20void DurationConversionCastCheck::registerMatchers(MatchFinder *Finder) {21  auto CallMatcher = ignoringImpCasts(callExpr(22      callee(functionDecl(durationConversionFunction()).bind("func_decl")),23      hasArgument(0, expr().bind("arg"))));24 25  Finder->addMatcher(26      expr(anyOf(27          cxxStaticCastExpr(hasSourceExpression(CallMatcher)).bind("cast_expr"),28          cStyleCastExpr(hasSourceExpression(CallMatcher)).bind("cast_expr"),29          cxxFunctionalCastExpr(hasSourceExpression(CallMatcher))30              .bind("cast_expr"))),31      this);32}33 34void DurationConversionCastCheck::check(35    const MatchFinder::MatchResult &Result) {36  const auto *MatchedCast =37      Result.Nodes.getNodeAs<ExplicitCastExpr>("cast_expr");38 39  if (isInMacro(Result, MatchedCast))40    return;41 42  const auto *FuncDecl = Result.Nodes.getNodeAs<FunctionDecl>("func_decl");43  const auto *Arg = Result.Nodes.getNodeAs<Expr>("arg");44  const StringRef ConversionFuncName = FuncDecl->getName();45 46  std::optional<DurationScale> Scale =47      getScaleForDurationInverse(ConversionFuncName);48  if (!Scale)49    return;50 51  // Casting a double to an integer.52  if (MatchedCast->getTypeAsWritten()->isIntegerType() &&53      ConversionFuncName.contains("Double")) {54    const llvm::StringRef NewFuncName =55        getDurationInverseForScale(*Scale).second;56 57    diag(MatchedCast->getBeginLoc(),58         "duration should be converted directly to an integer rather than "59         "through a type cast")60        << FixItHint::CreateReplacement(61               MatchedCast->getSourceRange(),62               (llvm::Twine(NewFuncName.substr(2)) + "(" +63                tooling::fixit::getText(*Arg, *Result.Context) + ")")64                   .str());65  }66 67  // Casting an integer to a double.68  if (MatchedCast->getTypeAsWritten()->isRealFloatingType() &&69      ConversionFuncName.contains("Int64")) {70    const llvm::StringRef NewFuncName =71        getDurationInverseForScale(*Scale).first;72 73    diag(MatchedCast->getBeginLoc(), "duration should be converted directly to "74                                     "a floating-point number rather than "75                                     "through a type cast")76        << FixItHint::CreateReplacement(77               MatchedCast->getSourceRange(),78               (llvm::Twine(NewFuncName.substr(2)) + "(" +79                tooling::fixit::getText(*Arg, *Result.Context) + ")")80                   .str());81  }82}83 84} // namespace clang::tidy::abseil85