10 #include "clang/AST/ASTContext.h" 11 #include "clang/ASTMatchers/ASTMatchFinder.h" 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(anyOf(hasOperatorName(
"^"), hasOperatorName(
"|"),
52 hasOperatorName(
"&"), hasOperatorName(
"^="),
53 hasOperatorName(
"|="), hasOperatorName(
"&=")),
55 unless(allOf(hasLHS(IsStdBitmask), hasRHS(IsStdBitmask))),
57 hasEitherOperand(SignedIntegerOperand),
58 hasLHS(hasType(isInteger())), hasRHS(hasType(isInteger())))
59 .bind(
"binary-no-sign-interference"),
65 binaryOperator(anyOf(hasOperatorName(
"<<"), hasOperatorName(
">>"),
66 hasOperatorName(
"<<="), hasOperatorName(
">>=")),
67 hasEitherOperand(SignedIntegerOperand),
68 hasLHS(hasType(isInteger())), hasRHS(hasType(isInteger())))
69 .bind(
"binary-sign-interference"),
74 unaryOperator(hasOperatorName(
"~"), hasUnaryOperand(SignedIntegerOperand))
75 .bind(
"unary-signed"),
80 const ast_matchers::BoundNodes &N = Result.Nodes;
81 const auto *SignedOperand = N.getNodeAs<Expr>(
"signed-operand");
82 assert(SignedOperand &&
83 "No signed operand found in problematic bitwise operations");
88 if (
const auto *UnaryOp = N.getNodeAs<UnaryOperator>(
"unary-signed")) {
90 Location = UnaryOp->getBeginLoc();
92 if (
const auto *BinaryOp =
93 N.getNodeAs<BinaryOperator>(
"binary-no-sign-interference"))
94 Location = BinaryOp->getBeginLoc();
95 else if (
const auto *BinaryOp =
96 N.getNodeAs<BinaryOperator>(
"binary-sign-interference"))
97 Location = BinaryOp->getBeginLoc();
99 llvm_unreachable(
"unexpected matcher result");
101 diag(Location,
"use of a signed integer operand with a " 102 "%select{binary|unary}0 bitwise operator")
103 << IsUnary << SignedOperand->getSourceRange();
Base class for all clang-tidy checks.
void store(ClangTidyOptions::OptionMap &Options, StringRef LocalName, StringRef Value) const
Stores an option with the check-local name LocalName with string value Value to Options.
static constexpr llvm::StringLiteral Name
std::map< std::string, std::string > OptionMap
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.
void registerMatchers(ast_matchers::MatchFinder *Finder) override
Override this to register AST matchers with Finder.
void storeOptions(ClangTidyOptions::OptionMap &Options) override
Should store all options supported by this check with their current values or default values for opti...
DiagnosticBuilder diag(SourceLocation Loc, StringRef Description, DiagnosticIDs::Level Level=DiagnosticIDs::Warning)
Add a diagnostic with the check's name.
void check(const ast_matchers::MatchFinder::MatchResult &Result) override
ClangTidyChecks that register ASTMatchers should do the actual work in here.