|  | //===--- DurationDivisionCheck.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 "DurationDivisionCheck.h" | 
|  | #include "clang/AST/ASTContext.h" | 
|  | #include "clang/ASTMatchers/ASTMatchFinder.h" | 
|  | #include "clang/Lex/Lexer.h" | 
|  |  | 
|  | namespace clang::tidy::abseil { | 
|  |  | 
|  | using namespace clang::ast_matchers; | 
|  |  | 
|  | void DurationDivisionCheck::registerMatchers(MatchFinder *Finder) { | 
|  | const auto DurationExpr = | 
|  | expr(hasType(cxxRecordDecl(hasName("::absl::Duration")))); | 
|  | Finder->addMatcher( | 
|  | traverse(TK_AsIs, | 
|  | implicitCastExpr( | 
|  | hasSourceExpression(ignoringParenCasts( | 
|  | cxxOperatorCallExpr(hasOverloadedOperatorName("/"), | 
|  | hasArgument(0, DurationExpr), | 
|  | hasArgument(1, DurationExpr)) | 
|  | .bind("OpCall"))), | 
|  | hasImplicitDestinationType(qualType(unless(isInteger()))), | 
|  | unless(hasParent(cxxStaticCastExpr())), | 
|  | unless(hasParent(cStyleCastExpr())), | 
|  | unless(isInTemplateInstantiation()))), | 
|  | this); | 
|  | } | 
|  |  | 
|  | void DurationDivisionCheck::check(const MatchFinder::MatchResult &Result) { | 
|  | const auto *OpCall = Result.Nodes.getNodeAs<CXXOperatorCallExpr>("OpCall"); | 
|  | diag(OpCall->getOperatorLoc(), | 
|  | "operator/ on absl::Duration objects performs integer division; " | 
|  | "did you mean to use FDivDuration()?") | 
|  | << FixItHint::CreateInsertion(OpCall->getBeginLoc(), | 
|  | "absl::FDivDuration(") | 
|  | << FixItHint::CreateReplacement( | 
|  | SourceRange(OpCall->getOperatorLoc(), OpCall->getOperatorLoc()), | 
|  | ", ") | 
|  | << FixItHint::CreateInsertion( | 
|  | Lexer::getLocForEndOfToken( | 
|  | Result.SourceManager->getSpellingLoc(OpCall->getEndLoc()), 0, | 
|  | *Result.SourceManager, Result.Context->getLangOpts()), | 
|  | ")"); | 
|  | } | 
|  |  | 
|  | } // namespace clang::tidy::abseil |