//===- EnumCastOutOfRangeChecker.cpp ---------------------------*- C++ -*--===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // 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 "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "llvm/Support/FormatVariadic.h" #include <optional> usingnamespaceclang; usingnamespaceento; formatv; 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 { … }; // 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>> { … }; EnumValueVector; // Collects all of the values an enum can represent (as SVals). EnumValueVector getDeclValuesForEnum(const EnumDecl *ED) { … } } // namespace void EnumCastOutOfRangeChecker::reportWarning(CheckerContext &C, const CastExpr *CE, const EnumDecl *E) const { … } void EnumCastOutOfRangeChecker::checkPreStmt(const CastExpr *CE, CheckerContext &C) const { … } void ento::registerEnumCastOutOfRangeChecker(CheckerManager &mgr) { … } bool ento::shouldRegisterEnumCastOutOfRangeChecker(const CheckerManager &mgr) { … }