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
10 #include "DurationComparisonCheck.h"
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
DurationRewriter.h
Loc
SourceLocation Loc
&#39;#&#39; location in the include directive
Definition: IncludeOrderCheck.cpp:37
clang::ast_matchers
Definition: AbseilMatcher.h:15
DurationComparisonCheck.h
clang::tidy::abseil::rewriteExprFromNumberToDuration
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 ...
Definition: DurationRewriter.cpp:201
Result
llvm::Optional< llvm::Expected< tooling::AtomicChanges > > Result
Definition: ClangdServer.cpp:60
clang::tidy::abseil::getScaleForInverse
llvm::Optional< DurationScale > getScaleForInverse(llvm::StringRef Name)
Given the name of an inverse Duration function (e.g., ToDoubleSeconds), return its DurationScale...
Definition: DurationRewriter.cpp:179
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ChangeNamespace.cpp:18
clang::tidy::abseil::IsValidMacro
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.
Definition: DurationComparisonCheck.cpp:24