11 #include "clang/AST/ASTContext.h" 21 void MultiwayPathsCoveredCheck::storeOptions(
23 Options.store(Opts,
"WarnOnMissingElse", WarnOnMissingElse);
26 void MultiwayPathsCoveredCheck::registerMatchers(MatchFinder *Finder) {
33 anyOf(ignoringImpCasts(memberExpr(hasDeclaration(
34 fieldDecl(isBitField()).bind(
"bitfield")))),
35 ignoringImpCasts(declRefExpr().bind(
"non-enum-condition"))),
39 unless(ignoringImpCasts(
40 declRefExpr(hasType(enumType())).bind(
"enum-condition"))))))
45 if (WarnOnMissingElse) {
47 ifStmt(allOf(hasParent(ifStmt()), unless(hasElse(anything()))))
54 std::size_t CaseCount = 0;
55 bool HasDefault =
false;
57 const SwitchCase *CurrentCase = Switch->getSwitchCaseList();
60 if (isa<DefaultStmt>(CurrentCase))
63 CurrentCase = CurrentCase->getNextSwitchCase();
66 return std::make_pair(CaseCount, HasDefault);
71 static std::size_t
twoPow(std::size_t Bits) {
72 return Bits >= std::numeric_limits<std::size_t>::digits
73 ? std::numeric_limits<std::size_t>::max()
74 :
static_cast<size_t>(1) << Bits;
83 const ASTContext &Context) {
86 if (T->isBooleanType())
88 else if (T->isIntegralType(Context))
89 return twoPow(Context.getTypeSize(T));
94 void MultiwayPathsCoveredCheck::check(
const MatchFinder::MatchResult &Result) {
95 if (
const auto *ElseIfWithoutElse =
96 Result.Nodes.getNodeAs<IfStmt>(
"else-if")) {
97 diag(ElseIfWithoutElse->getLocStart(),
98 "potentially uncovered codepath; add an ending else statement");
101 const auto *Switch = Result.Nodes.getNodeAs<SwitchStmt>(
"switch");
102 std::size_t SwitchCaseCount;
103 bool SwitchHasDefault;
108 if (SwitchHasDefault) {
109 handleSwitchWithDefault(Switch, SwitchCaseCount);
114 if (!SwitchHasDefault && SwitchCaseCount > 0) {
115 handleSwitchWithoutDefault(Switch, SwitchCaseCount, Result);
122 if (!SwitchHasDefault && SwitchCaseCount == 0) {
123 diag(Switch->getLocStart(),
124 "switch statement without labels has no effect");
127 llvm_unreachable(
"matched a case, that was not explicitly handled");
130 void MultiwayPathsCoveredCheck::handleSwitchWithDefault(
131 const SwitchStmt *Switch, std::size_t CaseCount) {
132 assert(CaseCount > 0 &&
"Switch statement with supposedly one default " 133 "branch did not contain any case labels");
134 if (CaseCount == 1 || CaseCount == 2)
135 diag(Switch->getLocStart(),
137 ?
"degenerated switch with default label only" 138 :
"switch could be better written as an if/else statement");
141 void MultiwayPathsCoveredCheck::handleSwitchWithoutDefault(
142 const SwitchStmt *Switch, std::size_t CaseCount,
143 const MatchFinder::MatchResult &Result) {
147 assert(!Result.Nodes.getNodeAs<DeclRefExpr>(
"enum-condition") &&
148 "switch over enum is handled by warnings already, explicitly ignoring " 156 assert(CaseCount > 0 &&
"Switch statement without any case found. This case " 157 "should be excluded by the matcher and is handled " 159 std::size_t MaxPathsPossible = [&]() {
160 if (
const auto *GeneralCondition =
161 Result.Nodes.getNodeAs<DeclRefExpr>(
"non-enum-condition")) {
165 if (
const auto *BitfieldDecl =
166 Result.Nodes.getNodeAs<FieldDecl>(
"bitfield")) {
167 return twoPow(BitfieldDecl->getBitWidthValue(*Result.Context));
170 return static_cast<std::size_t
>(0);
174 if (CaseCount < MaxPathsPossible)
175 diag(Switch->getLocStart(),
176 CaseCount == 1 ?
"switch with only one case; use an if statement" 177 :
"potential uncovered code path; add a default label");
static std::pair< std::size_t, bool > countCaseLabels(const SwitchStmt *Switch)
std::map< std::string, std::string > OptionMap
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
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.
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...