[clang] [analyzer] Extend EnumCastOutOfRange diagnostics (PR #68191)
Endre Fülöp via cfe-commits
cfe-commits at lists.llvm.org
Fri Oct 27 03:33:09 PDT 2023
https://github.com/gamesh411 updated https://github.com/llvm/llvm-project/pull/68191
>From a08f51109bd93f88271f0548719c52c75afc96e3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Endre=20F=C3=BCl=C3=B6p?= <endre.fulop at sigmatechnology.se>
Date: Wed, 4 Oct 2023 10:38:00 +0200
Subject: [PATCH 1/4] [analyzer] Extend EnumCastOutOfRange diagnostics
EnumCastOutOfRange checker now reports the name of the enum in the
warning message. Additionally, a note-tag is placed to highlight the
location of the declaration.
---
.../Checkers/EnumCastOutOfRangeChecker.cpp | 33 ++++--
clang/test/Analysis/enum-cast-out-of-range.c | 13 ++-
.../test/Analysis/enum-cast-out-of-range.cpp | 108 +++++++++---------
3 files changed, 87 insertions(+), 67 deletions(-)
diff --git a/clang/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp
index 89be6a47250a245..6163f7a23804091 100644
--- a/clang/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp
@@ -59,7 +59,7 @@ class ConstraintBasedEQEvaluator {
// value can be matching.
class EnumCastOutOfRangeChecker : public Checker<check::PreStmt<CastExpr>> {
mutable std::unique_ptr<BugType> EnumValueCastOutOfRange;
- void reportWarning(CheckerContext &C) const;
+ void reportWarning(CheckerContext &C, const EnumDecl *E) const;
public:
void checkPreStmt(const CastExpr *CE, CheckerContext &C) const;
@@ -72,21 +72,36 @@ 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(); });
+ [](const EnumConstantDecl *D) { return D->getInitVal(); });
return DeclValues;
}
} // namespace
-void EnumCastOutOfRangeChecker::reportWarning(CheckerContext &C) const {
+void EnumCastOutOfRangeChecker::reportWarning(CheckerContext &C,
+ const EnumDecl *E) const {
+ assert(E && "valid EnumDecl* is expected");
if (const ExplodedNode *N = C.generateNonFatalErrorNode()) {
if (!EnumValueCastOutOfRange)
EnumValueCastOutOfRange.reset(
new BugType(this, "Enum cast out of range"));
- constexpr llvm::StringLiteral Msg =
- "The value provided to the cast expression is not in the valid range"
- " of values for the enum";
- C.emitReport(std::make_unique<PathSensitiveBugReport>(
- *EnumValueCastOutOfRange, Msg, N));
+
+ llvm::SmallString<128> Msg{"The value provided to the cast expression is "
+ "not in the valid range of values for "};
+ StringRef EnumName{E->getName()};
+ if (EnumName.empty()) {
+ Msg += "the enum";
+ } else {
+ Msg += '\'';
+ Msg += EnumName;
+ Msg += '\'';
+ }
+
+ auto BR = std::make_unique<PathSensitiveBugReport>(*EnumValueCastOutOfRange,
+ Msg, N);
+ BR->addNote("enum declared here",
+ PathDiagnosticLocation::create(E, C.getSourceManager()),
+ {E->getSourceRange()});
+ C.emitReport(std::move(BR));
}
}
@@ -144,7 +159,7 @@ void EnumCastOutOfRangeChecker::checkPreStmt(const CastExpr *CE,
// If there is no value that can possibly match any of the enum values, then
// warn.
if (!PossibleValueMatch)
- reportWarning(C);
+ reportWarning(C, ED);
}
void ento::registerEnumCastOutOfRangeChecker(CheckerManager &mgr) {
diff --git a/clang/test/Analysis/enum-cast-out-of-range.c b/clang/test/Analysis/enum-cast-out-of-range.c
index 3282cba653d7125..6d3afa3fcf9885f 100644
--- a/clang/test/Analysis/enum-cast-out-of-range.c
+++ b/clang/test/Analysis/enum-cast-out-of-range.c
@@ -2,6 +2,7 @@
// RUN: -analyzer-checker=core,alpha.cplusplus.EnumCastOutOfRange \
// RUN: -verify %s
+// expected-note at +1 6 {{enum declared here}}
enum En_t {
En_0 = -4,
En_1,
@@ -11,17 +12,17 @@ enum En_t {
};
void unscopedUnspecifiedCStyle(void) {
- enum En_t Below = (enum En_t)(-5); // expected-warning {{not in the valid range}}
+ enum En_t Below = (enum En_t)(-5); // expected-warning {{not in the valid range of values for 'En_t'}}
enum En_t NegVal1 = (enum En_t)(-4); // OK.
enum En_t NegVal2 = (enum En_t)(-3); // OK.
- enum En_t InRange1 = (enum En_t)(-2); // expected-warning {{not in the valid range}}
- enum En_t InRange2 = (enum En_t)(-1); // expected-warning {{not in the valid range}}
- enum En_t InRange3 = (enum En_t)(0); // expected-warning {{not in the valid range}}
+ enum En_t InRange1 = (enum En_t)(-2); // expected-warning {{not in the valid range of values for 'En_t'}}
+ enum En_t InRange2 = (enum En_t)(-1); // expected-warning {{not in the valid range of values for 'En_t'}}
+ enum En_t InRange3 = (enum En_t)(0); // expected-warning {{not in the valid range of values for 'En_t'}}
enum En_t PosVal1 = (enum En_t)(1); // OK.
enum En_t PosVal2 = (enum En_t)(2); // OK.
- enum En_t InRange4 = (enum En_t)(3); // expected-warning {{not in the valid range}}
+ enum En_t InRange4 = (enum En_t)(3); // expected-warning {{not in the valid range of values for 'En_t'}}
enum En_t PosVal3 = (enum En_t)(4); // OK.
- enum En_t Above = (enum En_t)(5); // expected-warning {{not in the valid range}}
+ enum En_t Above = (enum En_t)(5); // expected-warning {{not in the valid range of values for 'En_t'}}
}
enum En_t unused;
diff --git a/clang/test/Analysis/enum-cast-out-of-range.cpp b/clang/test/Analysis/enum-cast-out-of-range.cpp
index abc1431e5be140f..0eb740664ecdc7c 100644
--- a/clang/test/Analysis/enum-cast-out-of-range.cpp
+++ b/clang/test/Analysis/enum-cast-out-of-range.cpp
@@ -2,6 +2,7 @@
// RUN: -analyzer-checker=core,alpha.cplusplus.EnumCastOutOfRange \
// RUN: -std=c++11 -verify %s
+// expected-note at +1 + {{enum declared here}}
enum unscoped_unspecified_t {
unscoped_unspecified_0 = -4,
unscoped_unspecified_1,
@@ -10,6 +11,7 @@ enum unscoped_unspecified_t {
unscoped_unspecified_4 = 4
};
+// expected-note at +1 + {{enum declared here}}
enum unscoped_specified_t : int {
unscoped_specified_0 = -4,
unscoped_specified_1,
@@ -18,6 +20,7 @@ enum unscoped_specified_t : int {
unscoped_specified_4 = 4
};
+// expected-note at +1 + {{enum declared here}}
enum class scoped_unspecified_t {
scoped_unspecified_0 = -4,
scoped_unspecified_1,
@@ -26,6 +29,7 @@ enum class scoped_unspecified_t {
scoped_unspecified_4 = 4
};
+// expected-note at +1 + {{enum declared here}}
enum class scoped_specified_t : int {
scoped_specified_0 = -4,
scoped_specified_1,
@@ -39,115 +43,115 @@ struct S {
};
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 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 'unscoped_unspecified_t'}}
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 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 'unscoped_unspecified_t'}}
+ 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 'unscoped_unspecified_t'}}
+ 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 'unscoped_unspecified_t'}}
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 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 'unscoped_unspecified_t'}}
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}}
+ 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 'unscoped_unspecified_t'}}
}
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 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 'unscoped_specified_t'}}
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 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 'unscoped_specified_t'}}
+ 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 'unscoped_specified_t'}}
+ 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 'unscoped_specified_t'}}
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 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 'unscoped_specified_t'}}
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}}
+ 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 'unscoped_specified_t'}}
}
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 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 'scoped_unspecified_t'}}
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 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 'scoped_unspecified_t'}}
+ 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 'scoped_unspecified_t'}}
+ 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 'scoped_unspecified_t'}}
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 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 'scoped_unspecified_t'}}
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}}
+ 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 'scoped_unspecified_t'}}
}
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 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 'scoped_specified_t'}}
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 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 'scoped_specified_t'}}
+ 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 'scoped_specified_t'}}
+ 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 'scoped_specified_t'}}
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 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 'scoped_specified_t'}}
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}}
+ 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 'scoped_specified_t'}}
}
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 InvalidBeforeRangeBegin = (unscoped_unspecified_t)(-5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for 'unscoped_unspecified_t'}}
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 InvalidInsideRange1 = (unscoped_unspecified_t)(-2); // expected-warning {{The value provided to the cast expression is not in the valid range of values for 'unscoped_unspecified_t'}}
+ 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 'unscoped_unspecified_t'}}
+ 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 'unscoped_unspecified_t'}}
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 InvalidInsideRange4 = (unscoped_unspecified_t)(3); // expected-warning {{The value provided to the cast expression is not in the valid range of values for 'unscoped_unspecified_t'}}
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}}
+ 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 'unscoped_unspecified_t'}}
}
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 InvalidBeforeRangeBegin = (unscoped_specified_t)(-5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for 'unscoped_specified_t'}}
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 InvalidInsideRange1 = (unscoped_specified_t)(-2); // expected-warning {{The value provided to the cast expression is not in the valid range of values for 'unscoped_specified_t'}}
+ 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 'unscoped_specified_t'}}
+ 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 'unscoped_specified_t'}}
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 InvalidInsideRange4 = (unscoped_specified_t)(3); // expected-warning {{The value provided to the cast expression is not in the valid range of values for 'unscoped_specified_t'}}
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}}
+ 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 'unscoped_specified_t'}}
}
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 InvalidBeforeRangeBegin = (scoped_unspecified_t)(-5); // expected-warning{{The value provided to the cast expression is not in the valid range of values for 'scoped_unspecified_t'}}
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 InvalidInsideRange1 = (scoped_unspecified_t)(-2); // expected-warning {{The value provided to the cast expression is not in the valid range of values for 'scoped_unspecified_t'}}
+ 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 'scoped_unspecified_t'}}
+ 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 'scoped_unspecified_t'}}
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 InvalidInsideRange4 = (scoped_unspecified_t)(3); // expected-warning {{The value provided to the cast expression is not in the valid range of values for 'scoped_unspecified_t'}}
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}}
+ 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 'scoped_unspecified_t'}}
}
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 InvalidBeforeRangeBegin = (scoped_specified_t)(-5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for 'scoped_specified_t'}}
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 InvalidInsideRange1 = (scoped_specified_t)(-2); // expected-warning {{The value provided to the cast expression is not in the valid range of values for 'scoped_specified_t'}}
+ 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 'scoped_specified_t'}}
+ 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 'scoped_specified_t'}}
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 InvalidInsideRange4 = (scoped_specified_t)(3); // expected-warning {{The value provided to the cast expression is not in the valid range of values for 'scoped_specified_t'}}
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}}
+ 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 'scoped_specified_t'}}
}
unscoped_unspecified_t unused;
@@ -165,12 +169,12 @@ void rangeConstrained1(int input) {
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}}
+ 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 'scoped_specified_t'}}
}
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}}
+ 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 'scoped_specified_t'}}
}
void rangeConstrained4(int input) {
@@ -190,13 +194,13 @@ void rangeConstrained6(int input) {
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}}
+ 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 'scoped_specified_t'}}
}
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}}
+ 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 'unscoped_unspecified_t'}}
}
>From b9807ec48b36c143eaa0d6a63d24a5bb1f62c589 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Endre=20F=C3=BCl=C3=B6p?= <endre.fulop at sigmatechnology.se>
Date: Wed, 4 Oct 2023 13:52:48 +0200
Subject: [PATCH 2/4] Track expression value of the CastExpr
---
.../Checkers/EnumCastOutOfRangeChecker.cpp | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/clang/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp
index 6163f7a23804091..5afb62d2a5f5c79 100644
--- a/clang/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp
@@ -59,7 +59,8 @@ class ConstraintBasedEQEvaluator {
// value can be matching.
class EnumCastOutOfRangeChecker : public Checker<check::PreStmt<CastExpr>> {
mutable std::unique_ptr<BugType> EnumValueCastOutOfRange;
- void reportWarning(CheckerContext &C, const EnumDecl *E) const;
+ void reportWarning(CheckerContext &C, const CastExpr *CE,
+ const EnumDecl *E) const;
public:
void checkPreStmt(const CastExpr *CE, CheckerContext &C) const;
@@ -78,6 +79,7 @@ EnumValueVector getDeclValuesForEnum(const EnumDecl *ED) {
} // namespace
void EnumCastOutOfRangeChecker::reportWarning(CheckerContext &C,
+ const CastExpr *CE,
const EnumDecl *E) const {
assert(E && "valid EnumDecl* is expected");
if (const ExplodedNode *N = C.generateNonFatalErrorNode()) {
@@ -98,6 +100,7 @@ void EnumCastOutOfRangeChecker::reportWarning(CheckerContext &C,
auto BR = std::make_unique<PathSensitiveBugReport>(*EnumValueCastOutOfRange,
Msg, N);
+ bugreporter::trackExpressionValue(N, CE, *BR);
BR->addNote("enum declared here",
PathDiagnosticLocation::create(E, C.getSourceManager()),
{E->getSourceRange()});
@@ -153,13 +156,13 @@ void EnumCastOutOfRangeChecker::checkPreStmt(const CastExpr *CE,
return;
// Check if any of the enum values possibly match.
- bool PossibleValueMatch = llvm::any_of(
- DeclValues, ConstraintBasedEQEvaluator(C, *ValueToCast));
+ 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, ED);
+ reportWarning(C, CE, ED);
}
void ento::registerEnumCastOutOfRangeChecker(CheckerManager &mgr) {
>From 4d1293953d2b965467db6de1afe51008c6ed3e7f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Endre=20F=C3=BCl=C3=B6p?= <endre.fulop at sigmatechnology.se>
Date: Tue, 24 Oct 2023 16:41:26 +0200
Subject: [PATCH 3/4] add trackexpression test track subexpression instead of
the whole cast
---
.../Checkers/EnumCastOutOfRangeChecker.cpp | 2 +-
clang/test/Analysis/enum-cast-out-of-range.c | 23 ++++++++++++++++++-
2 files changed, 23 insertions(+), 2 deletions(-)
diff --git a/clang/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp
index 5afb62d2a5f5c79..5844f4399100183 100644
--- a/clang/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp
@@ -100,7 +100,7 @@ void EnumCastOutOfRangeChecker::reportWarning(CheckerContext &C,
auto BR = std::make_unique<PathSensitiveBugReport>(*EnumValueCastOutOfRange,
Msg, N);
- bugreporter::trackExpressionValue(N, CE, *BR);
+ bugreporter::trackExpressionValue(N, CE->getSubExpr(), *BR);
BR->addNote("enum declared here",
PathDiagnosticLocation::create(E, C.getSourceManager()),
{E->getSourceRange()});
diff --git a/clang/test/Analysis/enum-cast-out-of-range.c b/clang/test/Analysis/enum-cast-out-of-range.c
index 6d3afa3fcf9885f..490af6fcc75528b 100644
--- a/clang/test/Analysis/enum-cast-out-of-range.c
+++ b/clang/test/Analysis/enum-cast-out-of-range.c
@@ -1,8 +1,9 @@
// RUN: %clang_analyze_cc1 \
// RUN: -analyzer-checker=core,alpha.cplusplus.EnumCastOutOfRange \
+// RUN: -analyzer-output text \
// RUN: -verify %s
-// expected-note at +1 6 {{enum declared here}}
+// expected-note at +1 + {{enum declared here}}
enum En_t {
En_0 = -4,
En_1,
@@ -13,16 +14,22 @@ enum En_t {
void unscopedUnspecifiedCStyle(void) {
enum En_t Below = (enum En_t)(-5); // expected-warning {{not in the valid range of values for 'En_t'}}
+ // expected-note at -1 {{not in the valid range of values for 'En_t'}}
enum En_t NegVal1 = (enum En_t)(-4); // OK.
enum En_t NegVal2 = (enum En_t)(-3); // OK.
enum En_t InRange1 = (enum En_t)(-2); // expected-warning {{not in the valid range of values for 'En_t'}}
+ // expected-note at -1 {{not in the valid range of values for 'En_t'}}
enum En_t InRange2 = (enum En_t)(-1); // expected-warning {{not in the valid range of values for 'En_t'}}
+ // expected-note at -1 {{not in the valid range of values for 'En_t'}}
enum En_t InRange3 = (enum En_t)(0); // expected-warning {{not in the valid range of values for 'En_t'}}
+ // expected-note at -1 {{not in the valid range of values for 'En_t'}}
enum En_t PosVal1 = (enum En_t)(1); // OK.
enum En_t PosVal2 = (enum En_t)(2); // OK.
enum En_t InRange4 = (enum En_t)(3); // expected-warning {{not in the valid range of values for 'En_t'}}
+ // expected-note at -1 {{not in the valid range of values for 'En_t'}}
enum En_t PosVal3 = (enum En_t)(4); // OK.
enum En_t Above = (enum En_t)(5); // expected-warning {{not in the valid range of values for 'En_t'}}
+ // expected-note at -1 {{not in the valid range of values for 'En_t'}}
}
enum En_t unused;
@@ -33,3 +40,17 @@ void unusedExpr(void) {
// generate a warning having nothing to do with this checker.
unused; // expected-warning {{expression result unused}}
}
+
+// Test expression tracking
+void set(int* p, int v) {
+ *p = v; // expected-note {{The value -1 is assigned to 'i'}}
+}
+
+
+void testTrackExpression(int i) {
+ set(&i, -1); // expected-note {{Passing the value -1 via 2nd parameter 'v'}}
+ // expected-note at -1 {{Calling 'set'}}
+ // expected-note at -2 {{Returning from 'set'}}
+ (void)(enum En_t)(i); // expected-warning {{not in the valid range of values for 'En_t'}}
+ // expected-note at -1 {{not in the valid range of values for 'En_t'}}
+}
>From af9baa208cd1b61af0ce1212fe132cf466bd653a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Endre=20F=C3=BCl=C3=B6p?= <endre.fulop at sigmatechnology.se>
Date: Fri, 27 Oct 2023 12:29:19 +0200
Subject: [PATCH 4/4] Add test cases for anonymous enums
---
clang/test/Analysis/enum-cast-out-of-range.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/clang/test/Analysis/enum-cast-out-of-range.c b/clang/test/Analysis/enum-cast-out-of-range.c
index 490af6fcc75528b..4e5c9bb9ffdec41 100644
--- a/clang/test/Analysis/enum-cast-out-of-range.c
+++ b/clang/test/Analysis/enum-cast-out-of-range.c
@@ -41,6 +41,16 @@ void unusedExpr(void) {
unused; // expected-warning {{expression result unused}}
}
+// Test typedef-ed anonymous enums
+typedef enum { // expected-note {{enum declared here}}
+ TD_0 = 0,
+} TD_t;
+
+void testTypeDefEnum(void) {
+ (void)(TD_t)(-1); // expected-warning {{not in the valid range of values for the enum}}
+ // expected-note at -1 {{not in the valid range of values for the enum}}
+}
+
// Test expression tracking
void set(int* p, int v) {
*p = v; // expected-note {{The value -1 is assigned to 'i'}}
More information about the cfe-commits
mailing list