10 #include "clang/AST/ASTContext.h"
11 #include "clang/ASTMatchers/ASTMatchFinder.h"
14 using namespace clang::ast_matchers::internal;
20 SignedBitwiseCheck::SignedBitwiseCheck(StringRef
Name,
23 IgnorePositiveIntegerLiterals(
24 Options.get(
"IgnorePositiveIntegerLiterals", false)) {}
28 IgnorePositiveIntegerLiterals);
32 const auto SignedIntegerOperand =
33 (IgnorePositiveIntegerLiterals
34 ? expr(ignoringImpCasts(hasType(isSignedInteger())),
35 unless(integerLiteral()))
36 : expr(ignoringImpCasts(hasType(isSignedInteger()))))
37 .bind(
"signed-operand");
43 const auto BitmaskType = namedDecl(
44 hasAnyName(
"::std::locale::category",
"::std::ctype_base::mask",
45 "::std::ios_base::fmtflags",
"::std::ios_base::iostate",
46 "::std::ios_base::openmode"));
47 const auto IsStdBitmask = ignoringImpCasts(declRefExpr(hasType(BitmaskType)));
51 binaryOperator(hasAnyOperatorName(
"^",
"|",
"&",
"^=",
"|=",
"&="),
53 unless(allOf(hasLHS(IsStdBitmask), hasRHS(IsStdBitmask))),
55 hasEitherOperand(SignedIntegerOperand),
56 hasLHS(hasType(isInteger())), hasRHS(hasType(isInteger())))
57 .bind(
"binary-no-sign-interference"),
63 binaryOperator(hasAnyOperatorName(
"<<",
">>",
"<<=",
">>="),
64 hasEitherOperand(SignedIntegerOperand),
65 hasLHS(hasType(isInteger())), hasRHS(hasType(isInteger())))
66 .bind(
"binary-sign-interference"),
71 unaryOperator(hasOperatorName(
"~"), hasUnaryOperand(SignedIntegerOperand))
72 .bind(
"unary-signed"),
77 const ast_matchers::BoundNodes &N = Result.Nodes;
78 const auto *SignedOperand = N.getNodeAs<Expr>(
"signed-operand");
79 assert(SignedOperand &&
80 "No signed operand found in problematic bitwise operations");
85 if (
const auto *UnaryOp = N.getNodeAs<UnaryOperator>(
"unary-signed")) {
89 if (
const auto *BinaryOp =
90 N.getNodeAs<BinaryOperator>(
"binary-no-sign-interference"))
92 else if (
const auto *BinaryOp =
93 N.getNodeAs<BinaryOperator>(
"binary-sign-interference"))
96 llvm_unreachable(
"unexpected matcher result");
99 "%select{binary|unary}0 bitwise operator")
100 << IsUnary << SignedOperand->getSourceRange();