10#include "clang/AST/ASTContext.h"
19 Options.store(Opts,
"WarnOnMissingElse", WarnOnMissingElse);
29 anyOf(ignoringImpCasts(memberExpr(hasDeclaration(
30 fieldDecl(isBitField()).bind(
"bitfield")))),
31 ignoringImpCasts(declRefExpr().bind(
"non-enum-condition"))),
35 unless(ignoringImpCasts(
36 declRefExpr(hasType(hasCanonicalType(enumType())))
37 .bind(
"enum-condition"))))))
42 if (WarnOnMissingElse) {
43 Finder->addMatcher(ifStmt(hasParent(ifStmt()), unless(hasElse(anything())))
50 std::size_t CaseCount = 0;
51 bool HasDefault =
false;
53 const SwitchCase *CurrentCase = Switch->getSwitchCaseList();
56 if (isa<DefaultStmt>(CurrentCase))
59 CurrentCase = CurrentCase->getNextSwitchCase();
62 return {CaseCount, HasDefault};
67static std::size_t
twoPow(std::size_t Bits) {
68 return Bits >= std::numeric_limits<std::size_t>::digits
69 ? std::numeric_limits<std::size_t>::max()
70 :
static_cast<size_t>(1) << Bits;
79 const ASTContext &Context) {
82 if (T->isBooleanType())
84 if (T->isIntegralType(Context))
85 return twoPow(Context.getTypeSize(T));
90 if (
const auto *ElseIfWithoutElse =
91 Result.Nodes.getNodeAs<IfStmt>(
"else-if")) {
92 diag(ElseIfWithoutElse->getBeginLoc(),
93 "potentially uncovered codepath; add an ending else statement");
96 const auto *Switch = Result.Nodes.getNodeAs<SwitchStmt>(
"switch");
97 std::size_t SwitchCaseCount = 0;
98 bool SwitchHasDefault =
false;
101 if (SwitchHasDefault || SwitchCaseCount <= 1)
104 handleSwitchWithoutDefault(Switch, SwitchCaseCount, Result);
107void UnhandledCodePathsCheck::handleSwitchWithoutDefault(
108 const SwitchStmt *Switch, std::size_t CaseCount,
109 const MatchFinder::MatchResult &Result) {
113 assert(!Result.Nodes.getNodeAs<DeclRefExpr>(
"enum-condition") &&
114 "switch over enum is handled by warnings already, explicitly ignoring "
120 assert(CaseCount > 1 &&
"Switch statement with fewer than two cases found.");
121 const std::size_t MaxPathsPossible = [&]() {
122 if (
const auto *GeneralCondition =
123 Result.Nodes.getNodeAs<DeclRefExpr>(
"non-enum-condition")) {
127 if (
const auto *BitfieldDecl =
128 Result.Nodes.getNodeAs<FieldDecl>(
"bitfield")) {
129 return twoPow(BitfieldDecl->getBitWidthValue());
132 return static_cast<std::size_t
>(0);
135 if (CaseCount < MaxPathsPossible)
136 diag(Switch->getBeginLoc(),
137 "potential uncovered code path; add a default label");
void check(const ast_matchers::MatchFinder::MatchResult &Result) override
void storeOptions(ClangTidyOptions::OptionMap &Opts) override
void registerMatchers(ast_matchers::MatchFinder *Finder) override
static std::pair< std::size_t, bool > countCaseLabels(const SwitchStmt *Switch)
static std::size_t twoPow(std::size_t Bits)
This function calculate 2 ** Bits and returns numeric_limits<std::size_t>::max() if an overflow occur...
static std::size_t getNumberOfPossibleValues(QualType T, const ASTContext &Context)
Get the number of possible values that can be switched on for the type T.
llvm::StringMap< ClangTidyValue > OptionMap