forked from OSchip/llvm-project
[analyzer] INT50-CPP. Do not cast to an out-of-range enumeration checker
This checker implements a solution to the "INT50-CPP. Do not cast to an out-of-range enumeration value" rule [1]. It lands in alpha for now, and a number of followup patches are planned in order to enable it by default. [1] https://www.securecoding.cert.org/confluence/display/cplusplus/INT50-CPP.+Do+not+cast+to+an+out-of-range+enumeration+value Patch by: Endre Fülöp and Alexander Zaitsev! Differential Revision: https://reviews.llvm.org/D33672 llvm-svn: 347513
This commit is contained in:
parent
1af8dd6a1e
commit
e0466f570e
|
@ -290,6 +290,9 @@ def DeleteWithNonVirtualDtorChecker : Checker<"DeleteWithNonVirtualDtor">,
|
|||
HelpText<"Reports destructions of polymorphic objects with a non-virtual "
|
||||
"destructor in their base class">;
|
||||
|
||||
def EnumCastOutOfRangeChecker : Checker<"EnumCastOutOfRange">,
|
||||
HelpText<"Check integer to enumeration casts for out of range values">;
|
||||
|
||||
def InvalidatedIteratorChecker : Checker<"InvalidatedIterator">,
|
||||
HelpText<"Check for use of invalidated iterators">;
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@ add_clang_library(clangStaticAnalyzerCheckers
|
|||
DivZeroChecker.cpp
|
||||
DynamicTypePropagation.cpp
|
||||
DynamicTypeChecker.cpp
|
||||
EnumCastOutOfRangeChecker.cpp
|
||||
ExprInspectionChecker.cpp
|
||||
FixedAddressChecker.cpp
|
||||
GCDAntipatternChecker.cpp
|
||||
|
|
|
@ -0,0 +1,128 @@
|
|||
//===- EnumCastOutOfRangeChecker.cpp ---------------------------*- C++ -*--===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The EnumCastOutOfRangeChecker is responsible for checking integer to
|
||||
// enumeration casts that could result in undefined values. This could happen
|
||||
// if the value that we cast from is out of the value range of the enumeration.
|
||||
// Reference:
|
||||
// [ISO/IEC 14882-2014] ISO/IEC 14882-2014.
|
||||
// Programming Languages — C++, Fourth Edition. 2014.
|
||||
// C++ Standard, [dcl.enum], in paragraph 8, which defines the range of an enum
|
||||
// C++ Standard, [expr.static.cast], paragraph 10, which defines the behaviour
|
||||
// of casting an integer value that is out of range
|
||||
// SEI CERT C++ Coding Standard, INT50-CPP. Do not cast to an out-of-range
|
||||
// enumeration value
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "ClangSACheckers.h"
|
||||
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
|
||||
|
||||
using namespace clang;
|
||||
using namespace ento;
|
||||
|
||||
namespace {
|
||||
// This evaluator checks two SVals for equality. The first SVal is provided via
|
||||
// the constructor, the second is the parameter of the overloaded () operator.
|
||||
// It uses the in-built ConstraintManager to resolve the equlity to possible or
|
||||
// not possible ProgramStates.
|
||||
class ConstraintBasedEQEvaluator {
|
||||
const DefinedOrUnknownSVal CompareValue;
|
||||
const ProgramStateRef PS;
|
||||
SValBuilder &SVB;
|
||||
|
||||
public:
|
||||
ConstraintBasedEQEvaluator(CheckerContext &C,
|
||||
const DefinedOrUnknownSVal CompareValue)
|
||||
: CompareValue(CompareValue), PS(C.getState()), SVB(C.getSValBuilder()) {}
|
||||
|
||||
bool operator()(const llvm::APSInt &EnumDeclInitValue) {
|
||||
DefinedOrUnknownSVal EnumDeclValue = SVB.makeIntVal(EnumDeclInitValue);
|
||||
DefinedOrUnknownSVal ElemEqualsValueToCast =
|
||||
SVB.evalEQ(PS, EnumDeclValue, CompareValue);
|
||||
|
||||
return static_cast<bool>(PS->assume(ElemEqualsValueToCast, true));
|
||||
}
|
||||
};
|
||||
|
||||
// This checker checks CastExpr statements.
|
||||
// If the value provided to the cast is one of the values the enumeration can
|
||||
// represent, the said value matches the enumeration. If the checker can
|
||||
// establish the impossibility of matching it gives a warning.
|
||||
// Being conservative, it does not warn if there is slight possibility the
|
||||
// value can be matching.
|
||||
class EnumCastOutOfRangeChecker : public Checker<check::PreStmt<CastExpr>> {
|
||||
mutable std::unique_ptr<BuiltinBug> EnumValueCastOutOfRange;
|
||||
void reportWarning(CheckerContext &C) const;
|
||||
|
||||
public:
|
||||
void checkPreStmt(const CastExpr *CE, CheckerContext &C) const;
|
||||
};
|
||||
|
||||
using EnumValueVector = llvm::SmallVector<llvm::APSInt, 6>;
|
||||
|
||||
// Collects all of the values an enum can represent (as SVals).
|
||||
EnumValueVector getDeclValuesForEnum(const EnumDecl *ED) {
|
||||
EnumValueVector DeclValues(
|
||||
std::distance(ED->enumerator_begin(), ED->enumerator_end()));
|
||||
llvm::transform(ED->enumerators(), DeclValues.begin(),
|
||||
[](const EnumConstantDecl *D) { return D->getInitVal(); });
|
||||
return DeclValues;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void EnumCastOutOfRangeChecker::reportWarning(CheckerContext &C) const {
|
||||
if (const ExplodedNode *N = C.generateNonFatalErrorNode()) {
|
||||
if (!EnumValueCastOutOfRange)
|
||||
EnumValueCastOutOfRange.reset(
|
||||
new BuiltinBug(this, "Enum cast out of range",
|
||||
"The value provided to the cast expression is not in "
|
||||
"the valid range of values for the enum"));
|
||||
C.emitReport(llvm::make_unique<BugReport>(
|
||||
*EnumValueCastOutOfRange, EnumValueCastOutOfRange->getDescription(),
|
||||
N));
|
||||
}
|
||||
}
|
||||
|
||||
void EnumCastOutOfRangeChecker::checkPreStmt(const CastExpr *CE,
|
||||
CheckerContext &C) const {
|
||||
// Get the value of the expression to cast.
|
||||
const llvm::Optional<DefinedOrUnknownSVal> ValueToCast =
|
||||
C.getSVal(CE->getSubExpr()).getAs<DefinedOrUnknownSVal>();
|
||||
|
||||
// If the value cannot be reasoned about (not even a DefinedOrUnknownSVal),
|
||||
// don't analyze further.
|
||||
if (!ValueToCast)
|
||||
return;
|
||||
|
||||
const QualType T = CE->getType();
|
||||
// Check whether the cast type is an enum.
|
||||
if (!T->isEnumeralType())
|
||||
return;
|
||||
|
||||
// If the cast is an enum, get its declaration.
|
||||
// If the isEnumeralType() returned true, then the declaration must exist
|
||||
// even if it is a stub declaration. It is up to the getDeclValuesForEnum()
|
||||
// function to handle this.
|
||||
const EnumDecl *ED = T->castAs<EnumType>()->getDecl();
|
||||
|
||||
EnumValueVector DeclValues = getDeclValuesForEnum(ED);
|
||||
// Check if any of the enum values possibly match.
|
||||
bool PossibleValueMatch = llvm::any_of(
|
||||
DeclValues, ConstraintBasedEQEvaluator(C, *ValueToCast));
|
||||
|
||||
// If there is no value that can possibly match any of the enum values, then
|
||||
// warn.
|
||||
if (!PossibleValueMatch)
|
||||
reportWarning(C);
|
||||
}
|
||||
|
||||
void ento::registerEnumCastOutOfRangeChecker(CheckerManager &mgr) {
|
||||
mgr.registerChecker<EnumCastOutOfRangeChecker>();
|
||||
}
|
|
@ -0,0 +1,192 @@
|
|||
// RUN: %clang_analyze_cc1 \
|
||||
// RUN: -analyzer-checker=core,alpha.cplusplus.EnumCastOutOfRange \
|
||||
// RUN: -std=c++11 -verify %s
|
||||
|
||||
enum unscoped_unspecified_t {
|
||||
unscoped_unspecified_0 = -4,
|
||||
unscoped_unspecified_1,
|
||||
unscoped_unspecified_2 = 1,
|
||||
unscoped_unspecified_3,
|
||||
unscoped_unspecified_4 = 4
|
||||
};
|
||||
|
||||
enum unscoped_specified_t : int {
|
||||
unscoped_specified_0 = -4,
|
||||
unscoped_specified_1,
|
||||
unscoped_specified_2 = 1,
|
||||
unscoped_specified_3,
|
||||
unscoped_specified_4 = 4
|
||||
};
|
||||
|
||||
enum class scoped_unspecified_t {
|
||||
scoped_unspecified_0 = -4,
|
||||
scoped_unspecified_1,
|
||||
scoped_unspecified_2 = 1,
|
||||
scoped_unspecified_3,
|
||||
scoped_unspecified_4 = 4
|
||||
};
|
||||
|
||||
enum class scoped_specified_t : int {
|
||||
scoped_specified_0 = -4,
|
||||
scoped_specified_1,
|
||||
scoped_specified_2 = 1,
|
||||
scoped_specified_3,
|
||||
scoped_specified_4 = 4
|
||||
};
|
||||
|
||||
struct S {
|
||||
unscoped_unspecified_t E : 5;
|
||||
};
|
||||
|
||||
void unscopedUnspecified() {
|
||||
unscoped_unspecified_t InvalidBeforeRangeBegin = static_cast<unscoped_unspecified_t>(-5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
|
||||
unscoped_unspecified_t ValidNegativeValue1 = static_cast<unscoped_unspecified_t>(-4); // OK.
|
||||
unscoped_unspecified_t ValidNegativeValue2 = static_cast<unscoped_unspecified_t>(-3); // OK.
|
||||
unscoped_unspecified_t InvalidInsideRange1 = static_cast<unscoped_unspecified_t>(-2); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
|
||||
unscoped_unspecified_t InvalidInsideRange2 = static_cast<unscoped_unspecified_t>(-1); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
|
||||
unscoped_unspecified_t InvalidInsideRange3 = static_cast<unscoped_unspecified_t>(0); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
|
||||
unscoped_unspecified_t ValidPositiveValue1 = static_cast<unscoped_unspecified_t>(1); // OK.
|
||||
unscoped_unspecified_t ValidPositiveValue2 = static_cast<unscoped_unspecified_t>(2); // OK.
|
||||
unscoped_unspecified_t InvalidInsideRange4 = static_cast<unscoped_unspecified_t>(3); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
|
||||
unscoped_unspecified_t ValidPositiveValue3 = static_cast<unscoped_unspecified_t>(4); // OK.
|
||||
unscoped_unspecified_t InvalidAfterRangeEnd = static_cast<unscoped_unspecified_t>(5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
|
||||
}
|
||||
|
||||
void unscopedSpecified() {
|
||||
unscoped_specified_t InvalidBeforeRangeBegin = static_cast<unscoped_specified_t>(-5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
|
||||
unscoped_specified_t ValidNegativeValue1 = static_cast<unscoped_specified_t>(-4); // OK.
|
||||
unscoped_specified_t ValidNegativeValue2 = static_cast<unscoped_specified_t>(-3); // OK.
|
||||
unscoped_specified_t InvalidInsideRange1 = static_cast<unscoped_specified_t>(-2); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
|
||||
unscoped_specified_t InvalidInsideRange2 = static_cast<unscoped_specified_t>(-1); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
|
||||
unscoped_specified_t InvalidInsideRange3 = static_cast<unscoped_specified_t>(0); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
|
||||
unscoped_specified_t ValidPositiveValue1 = static_cast<unscoped_specified_t>(1); // OK.
|
||||
unscoped_specified_t ValidPositiveValue2 = static_cast<unscoped_specified_t>(2); // OK.
|
||||
unscoped_specified_t InvalidInsideRange4 = static_cast<unscoped_specified_t>(3); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
|
||||
unscoped_specified_t ValidPositiveValue3 = static_cast<unscoped_specified_t>(4); // OK.
|
||||
unscoped_specified_t InvalidAfterRangeEnd = static_cast<unscoped_specified_t>(5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
|
||||
}
|
||||
|
||||
void scopedUnspecified() {
|
||||
scoped_unspecified_t InvalidBeforeRangeBegin = static_cast<scoped_unspecified_t>(-5); // expected-warning{{The value provided to the cast expression is not in the valid range of values for the enum}}
|
||||
scoped_unspecified_t ValidNegativeValue1 = static_cast<scoped_unspecified_t>(-4); // OK.
|
||||
scoped_unspecified_t ValidNegativeValue2 = static_cast<scoped_unspecified_t>(-3); // OK.
|
||||
scoped_unspecified_t InvalidInsideRange1 = static_cast<scoped_unspecified_t>(-2); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
|
||||
scoped_unspecified_t InvalidInsideRange2 = static_cast<scoped_unspecified_t>(-1); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
|
||||
scoped_unspecified_t InvalidInsideRange3 = static_cast<scoped_unspecified_t>(0); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
|
||||
scoped_unspecified_t ValidPositiveValue1 = static_cast<scoped_unspecified_t>(1); // OK.
|
||||
scoped_unspecified_t ValidPositiveValue2 = static_cast<scoped_unspecified_t>(2); // OK.
|
||||
scoped_unspecified_t InvalidInsideRange4 = static_cast<scoped_unspecified_t>(3); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
|
||||
scoped_unspecified_t ValidPositiveValue3 = static_cast<scoped_unspecified_t>(4); // OK.
|
||||
scoped_unspecified_t InvalidAfterRangeEnd = static_cast<scoped_unspecified_t>(5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
|
||||
}
|
||||
|
||||
void scopedSpecified() {
|
||||
scoped_specified_t InvalidBeforeRangeBegin = static_cast<scoped_specified_t>(-5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
|
||||
scoped_specified_t ValidNegativeValue1 = static_cast<scoped_specified_t>(-4); // OK.
|
||||
scoped_specified_t ValidNegativeValue2 = static_cast<scoped_specified_t>(-3); // OK.
|
||||
scoped_specified_t InvalidInsideRange1 = static_cast<scoped_specified_t>(-2); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
|
||||
scoped_specified_t InvalidInsideRange2 = static_cast<scoped_specified_t>(-1); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
|
||||
scoped_specified_t InvalidInsideRange3 = static_cast<scoped_specified_t>(0); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
|
||||
scoped_specified_t ValidPositiveValue1 = static_cast<scoped_specified_t>(1); // OK.
|
||||
scoped_specified_t ValidPositiveValue2 = static_cast<scoped_specified_t>(2); // OK.
|
||||
scoped_specified_t InvalidInsideRange4 = static_cast<scoped_specified_t>(3); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
|
||||
scoped_specified_t ValidPositiveValue3 = static_cast<scoped_specified_t>(4); // OK.
|
||||
scoped_specified_t InvalidAfterRangeEnd = static_cast<scoped_specified_t>(5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
|
||||
}
|
||||
|
||||
void unscopedUnspecifiedCStyle() {
|
||||
unscoped_unspecified_t InvalidBeforeRangeBegin = (unscoped_unspecified_t)(-5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
|
||||
unscoped_unspecified_t ValidNegativeValue1 = (unscoped_unspecified_t)(-4); // OK.
|
||||
unscoped_unspecified_t ValidNegativeValue2 = (unscoped_unspecified_t)(-3); // OK.
|
||||
unscoped_unspecified_t InvalidInsideRange1 = (unscoped_unspecified_t)(-2); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
|
||||
unscoped_unspecified_t InvalidInsideRange2 = (unscoped_unspecified_t)(-1); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
|
||||
unscoped_unspecified_t InvalidInsideRange3 = (unscoped_unspecified_t)(0); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
|
||||
unscoped_unspecified_t ValidPositiveValue1 = (unscoped_unspecified_t)(1); // OK.
|
||||
unscoped_unspecified_t ValidPositiveValue2 = (unscoped_unspecified_t)(2); // OK.
|
||||
unscoped_unspecified_t InvalidInsideRange4 = (unscoped_unspecified_t)(3); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
|
||||
unscoped_unspecified_t ValidPositiveValue3 = (unscoped_unspecified_t)(4); // OK.
|
||||
unscoped_unspecified_t InvalidAfterRangeEnd = (unscoped_unspecified_t)(5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
|
||||
}
|
||||
|
||||
void unscopedSpecifiedCStyle() {
|
||||
unscoped_specified_t InvalidBeforeRangeBegin = (unscoped_specified_t)(-5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
|
||||
unscoped_specified_t ValidNegativeValue1 = (unscoped_specified_t)(-4); // OK.
|
||||
unscoped_specified_t ValidNegativeValue2 = (unscoped_specified_t)(-3); // OK.
|
||||
unscoped_specified_t InvalidInsideRange1 = (unscoped_specified_t)(-2); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
|
||||
unscoped_specified_t InvalidInsideRange2 = (unscoped_specified_t)(-1); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
|
||||
unscoped_specified_t InvalidInsideRange3 = (unscoped_specified_t)(0); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
|
||||
unscoped_specified_t ValidPositiveValue1 = (unscoped_specified_t)(1); // OK.
|
||||
unscoped_specified_t ValidPositiveValue2 = (unscoped_specified_t)(2); // OK.
|
||||
unscoped_specified_t InvalidInsideRange4 = (unscoped_specified_t)(3); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
|
||||
unscoped_specified_t ValidPositiveValue3 = (unscoped_specified_t)(4); // OK.
|
||||
unscoped_specified_t InvalidAfterRangeEnd = (unscoped_specified_t)(5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
|
||||
}
|
||||
|
||||
void scopedUnspecifiedCStyle() {
|
||||
scoped_unspecified_t InvalidBeforeRangeBegin = (scoped_unspecified_t)(-5); // expected-warning{{The value provided to the cast expression is not in the valid range of values for the enum}}
|
||||
scoped_unspecified_t ValidNegativeValue1 = (scoped_unspecified_t)(-4); // OK.
|
||||
scoped_unspecified_t ValidNegativeValue2 = (scoped_unspecified_t)(-3); // OK.
|
||||
scoped_unspecified_t InvalidInsideRange1 = (scoped_unspecified_t)(-2); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
|
||||
scoped_unspecified_t InvalidInsideRange2 = (scoped_unspecified_t)(-1); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
|
||||
scoped_unspecified_t InvalidInsideRange3 = (scoped_unspecified_t)(0); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
|
||||
scoped_unspecified_t ValidPositiveValue1 = (scoped_unspecified_t)(1); // OK.
|
||||
scoped_unspecified_t ValidPositiveValue2 = (scoped_unspecified_t)(2); // OK.
|
||||
scoped_unspecified_t InvalidInsideRange4 = (scoped_unspecified_t)(3); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
|
||||
scoped_unspecified_t ValidPositiveValue3 = (scoped_unspecified_t)(4); // OK.
|
||||
scoped_unspecified_t InvalidAfterRangeEnd = (scoped_unspecified_t)(5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
|
||||
}
|
||||
|
||||
void scopedSpecifiedCStyle() {
|
||||
scoped_specified_t InvalidBeforeRangeBegin = (scoped_specified_t)(-5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
|
||||
scoped_specified_t ValidNegativeValue1 = (scoped_specified_t)(-4); // OK.
|
||||
scoped_specified_t ValidNegativeValue2 = (scoped_specified_t)(-3); // OK.
|
||||
scoped_specified_t InvalidInsideRange1 = (scoped_specified_t)(-2); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
|
||||
scoped_specified_t InvalidInsideRange2 = (scoped_specified_t)(-1); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
|
||||
scoped_specified_t InvalidInsideRange3 = (scoped_specified_t)(0); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
|
||||
scoped_specified_t ValidPositiveValue1 = (scoped_specified_t)(1); // OK.
|
||||
scoped_specified_t ValidPositiveValue2 = (scoped_specified_t)(2); // OK.
|
||||
scoped_specified_t InvalidInsideRange4 = (scoped_specified_t)(3); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
|
||||
scoped_specified_t ValidPositiveValue3 = (scoped_specified_t)(4); // OK.
|
||||
scoped_specified_t InvalidAfterRangeEnd = (scoped_specified_t)(5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
|
||||
}
|
||||
|
||||
void rangeContstrained1(int input) {
|
||||
if (input > -5 && input < 5)
|
||||
auto value = static_cast<scoped_specified_t>(input); // OK. Being conservative, this is a possibly good value.
|
||||
}
|
||||
|
||||
void rangeConstrained2(int input) {
|
||||
if (input < -5)
|
||||
auto value = static_cast<scoped_specified_t>(input); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
|
||||
}
|
||||
|
||||
void rangeConstrained3(int input) {
|
||||
if (input >= -2 && input <= -1)
|
||||
auto value = static_cast<scoped_specified_t>(input); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
|
||||
}
|
||||
|
||||
void rangeConstrained4(int input) {
|
||||
if (input >= -2 && input <= 1)
|
||||
auto value = static_cast<scoped_specified_t>(input); // OK. Possibly 1.
|
||||
}
|
||||
|
||||
void rangeConstrained5(int input) {
|
||||
if (input >= 1 && input <= 2)
|
||||
auto value = static_cast<scoped_specified_t>(input); // OK. Strict inner matching.
|
||||
}
|
||||
|
||||
void rangeConstrained6(int input) {
|
||||
if (input >= 2 && input <= 4)
|
||||
auto value = static_cast<scoped_specified_t>(input); // OK. The value is possibly 2 or 4, dont warn.
|
||||
}
|
||||
|
||||
void rangeConstrained7(int input) {
|
||||
if (input >= 3 && input <= 3)
|
||||
auto value = static_cast<scoped_specified_t>(input); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
|
||||
}
|
||||
|
||||
void enumBitFieldAssignment() {
|
||||
S s;
|
||||
s.E = static_cast<unscoped_unspecified_t>(4); // OK.
|
||||
s.E = static_cast<unscoped_unspecified_t>(5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
|
||||
}
|
|
@ -349,6 +349,24 @@ void sink(NonVirtual *x) {
|
|||
}
|
||||
</pre></div></div></td></tr>
|
||||
|
||||
<tr><td><div class="namedescr expandable"><span class="name">
|
||||
alpha.cplusplus.EnumCastOutOfRange</span><span class="lang">
|
||||
(C++)</span><div class="descr">
|
||||
Check for integer to enumeration casts that could result in undefined values.
|
||||
</div></div></td>
|
||||
<td><div class="exampleContainer expandable">
|
||||
<div class="example"><pre>
|
||||
enum TestEnum {
|
||||
A = 0
|
||||
};
|
||||
|
||||
void foo() {
|
||||
TestEnum t = static_cast<TestEnum>(-1);
|
||||
// warn: the value provided to the cast expression is not in
|
||||
the valid range of values for the enum
|
||||
}
|
||||
</pre></div></div></td></tr>
|
||||
|
||||
|
||||
<tr><td><div class="namedescr expandable"><span class="name">
|
||||
alpha.cplusplus.InvalidatedIterator</span><span class="lang">
|
||||
|
|
Loading…
Reference in New Issue