Author: szelethus Date: Sat Nov 24 04:24:27 2018 New Revision: 347513 URL: http://llvm.org/viewvc/llvm-project?rev=347513&view=rev Log: [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 Added: cfe/trunk/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp cfe/trunk/test/Analysis/enum-cast-out-of-range.cpp Modified: cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt cfe/trunk/www/analyzer/alpha_checks.html Modified: cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td?rev=347513&r1=347512&r2=347513&view=diff ============================================================================== --- cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td (original) +++ cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td Sat Nov 24 04:24:27 2018 @@ -290,6 +290,9 @@ def DeleteWithNonVirtualDtorChecker : Ch 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">; Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt?rev=347513&r1=347512&r2=347513&view=diff ============================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt Sat Nov 24 04:24:27 2018 @@ -34,6 +34,7 @@ add_clang_library(clangStaticAnalyzerChe DivZeroChecker.cpp DynamicTypePropagation.cpp DynamicTypeChecker.cpp + EnumCastOutOfRangeChecker.cpp ExprInspectionChecker.cpp FixedAddressChecker.cpp GCDAntipatternChecker.cpp Added: cfe/trunk/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp?rev=347513&view=auto ============================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp (added) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp Sat Nov 24 04:24:27 2018 @@ -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>(); +} Added: cfe/trunk/test/Analysis/enum-cast-out-of-range.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/enum-cast-out-of-range.cpp?rev=347513&view=auto ============================================================================== --- cfe/trunk/test/Analysis/enum-cast-out-of-range.cpp (added) +++ cfe/trunk/test/Analysis/enum-cast-out-of-range.cpp Sat Nov 24 04:24:27 2018 @@ -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}} +} Modified: cfe/trunk/www/analyzer/alpha_checks.html URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/www/analyzer/alpha_checks.html?rev=347513&r1=347512&r2=347513&view=diff ============================================================================== --- cfe/trunk/www/analyzer/alpha_checks.html (original) +++ cfe/trunk/www/analyzer/alpha_checks.html Sat Nov 24 04:24:27 2018 @@ -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"> _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits