clang-tools  4.0.0
BoolPointerImplicitConversionCheck.cpp
Go to the documentation of this file.
1 //===--- BoolPointerImplicitConversionCheck.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 
12 using namespace clang::ast_matchers;
13 
14 namespace clang {
15 namespace tidy {
16 namespace misc {
17 
18 void BoolPointerImplicitConversionCheck::registerMatchers(MatchFinder *Finder) {
19  // Look for ifs that have an implicit bool* to bool conversion in the
20  // condition. Filter negations.
21  Finder->addMatcher(
22  ifStmt(hasCondition(findAll(implicitCastExpr(
23  allOf(unless(hasParent(unaryOperator(hasOperatorName("!")))),
24  hasSourceExpression(expr(
25  hasType(pointerType(pointee(booleanType()))),
26  ignoringParenImpCasts(declRefExpr().bind("expr")))),
27  hasCastKind(CK_PointerToBoolean))))),
28  unless(isInTemplateInstantiation()))
29  .bind("if"),
30  this);
31 }
32 
33 void BoolPointerImplicitConversionCheck::check(
34  const MatchFinder::MatchResult &Result) {
35  auto *If = Result.Nodes.getNodeAs<IfStmt>("if");
36  auto *Var = Result.Nodes.getNodeAs<DeclRefExpr>("expr");
37 
38  // Ignore macros.
39  if (Var->getLocStart().isMacroID())
40  return;
41 
42  // Only allow variable accesses for now, no function calls or member exprs.
43  // Check that we don't dereference the variable anywhere within the if. This
44  // avoids false positives for checks of the pointer for nullptr before it is
45  // dereferenced. If there is a dereferencing operator on this variable don't
46  // emit a diagnostic. Also ignore array subscripts.
47  const Decl *D = Var->getDecl();
48  auto DeclRef = ignoringParenImpCasts(declRefExpr(to(equalsNode(D))));
49  if (!match(findAll(
50  unaryOperator(hasOperatorName("*"), hasUnaryOperand(DeclRef))),
51  *If, *Result.Context)
52  .empty() ||
53  !match(findAll(arraySubscriptExpr(hasBase(DeclRef))), *If,
54  *Result.Context)
55  .empty() ||
56  // FIXME: We should still warn if the paremater is implicitly converted to
57  // bool.
58  !match(findAll(callExpr(hasAnyArgument(ignoringParenImpCasts(DeclRef)))),
59  *If, *Result.Context)
60  .empty() ||
61  !match(findAll(cxxDeleteExpr(has(ignoringParenImpCasts(expr(DeclRef))))),
62  *If, *Result.Context)
63  .empty())
64  return;
65 
66  diag(Var->getLocStart(), "dubious check of 'bool *' against 'nullptr', did "
67  "you mean to dereference it?")
68  << FixItHint::CreateInsertion(Var->getLocStart(), "*");
69 }
70 
71 } // namespace misc
72 } // namespace tidy
73 } // namespace clang
std::unique_ptr< ast_matchers::MatchFinder > Finder
Definition: ClangTidy.cpp:262
const DeclRefExpr * DeclRef
const NamedDecl * Result
Definition: USRFinder.cpp:162