clang-tools  8.0.0
DurationComparisonCheck.cpp
Go to the documentation of this file.
1 //===--- DurationComparisonCheck.cpp - clang-tidy -------------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
11 #include "DurationRewriter.h"
12 #include "clang/AST/ASTContext.h"
13 #include "clang/ASTMatchers/ASTMatchFinder.h"
14 #include "clang/Tooling/FixIt.h"
15 
16 using namespace clang::ast_matchers;
17 
18 namespace clang {
19 namespace tidy {
20 namespace abseil {
21 
22 /// Return `true` if `E` is a either: not a macro at all; or an argument to
23 /// one. In the latter case, we should still transform it.
24 static bool IsValidMacro(const MatchFinder::MatchResult &Result,
25  const Expr *E) {
26  if (!E->getBeginLoc().isMacroID())
27  return true;
28 
29  SourceLocation Loc = E->getBeginLoc();
30  // We want to get closer towards the initial macro typed into the source only
31  // if the location is being expanded as a macro argument.
32  while (Result.SourceManager->isMacroArgExpansion(Loc)) {
33  // We are calling getImmediateMacroCallerLoc, but note it is essentially
34  // equivalent to calling getImmediateSpellingLoc in this context according
35  // to Clang implementation. We are not calling getImmediateSpellingLoc
36  // because Clang comment says it "should not generally be used by clients."
37  Loc = Result.SourceManager->getImmediateMacroCallerLoc(Loc);
38  }
39  return !Loc.isMacroID();
40 }
41 
42 void DurationComparisonCheck::registerMatchers(MatchFinder *Finder) {
43  auto Matcher =
44  binaryOperator(anyOf(hasOperatorName(">"), hasOperatorName(">="),
45  hasOperatorName("=="), hasOperatorName("<="),
46  hasOperatorName("<")),
47  hasEitherOperand(ignoringImpCasts(callExpr(
48  callee(functionDecl(DurationConversionFunction())
49  .bind("function_decl"))))))
50  .bind("binop");
51 
52  Finder->addMatcher(Matcher, this);
53 }
54 
55 void DurationComparisonCheck::check(const MatchFinder::MatchResult &Result) {
56  const auto *Binop = Result.Nodes.getNodeAs<BinaryOperator>("binop");
57 
58  llvm::Optional<DurationScale> Scale = getScaleForInverse(
59  Result.Nodes.getNodeAs<FunctionDecl>("function_decl")->getName());
60  if (!Scale)
61  return;
62 
63  // In most cases, we'll only need to rewrite one of the sides, but we also
64  // want to handle the case of rewriting both sides. This is much simpler if
65  // we unconditionally try and rewrite both, and let the rewriter determine
66  // if nothing needs to be done.
67  if (!IsValidMacro(Result, Binop->getLHS()) ||
68  !IsValidMacro(Result, Binop->getRHS()))
69  return;
70  std::string LhsReplacement =
71  rewriteExprFromNumberToDuration(Result, *Scale, Binop->getLHS());
72  std::string RhsReplacement =
73  rewriteExprFromNumberToDuration(Result, *Scale, Binop->getRHS());
74 
75  diag(Binop->getBeginLoc(), "perform comparison in the duration domain")
76  << FixItHint::CreateReplacement(Binop->getSourceRange(),
77  (llvm::Twine(LhsReplacement) + " " +
78  Binop->getOpcodeStr() + " " +
79  RhsReplacement)
80  .str());
81 }
82 
83 } // namespace abseil
84 } // namespace tidy
85 } // namespace clang
SourceLocation Loc
&#39;#&#39; location in the include directive
std::string rewriteExprFromNumberToDuration(const ast_matchers::MatchFinder::MatchResult &Result, DurationScale Scale, const Expr *Node)
Assuming Node has type double or int representing a time interval of Scale, return the expression to ...
llvm::Optional< llvm::Expected< tooling::AtomicChanges > > Result
llvm::Optional< DurationScale > getScaleForInverse(llvm::StringRef Name)
Given the name of an inverse Duration function (e.g., ToDoubleSeconds), return its DurationScale...
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
static bool IsValidMacro(const MatchFinder::MatchResult &Result, const Expr *E)
Return true if E is a either: not a macro at all; or an argument to one.