|
22 | 22 | #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
|
23 | 23 | #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
|
24 | 24 | #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
|
| 25 | +#include "llvm/Support/FormatVariadic.h" |
25 | 26 | #include <optional>
|
26 | 27 |
|
27 | 28 | using namespace clang;
|
28 | 29 | using namespace ento;
|
| 30 | +using llvm::formatv; |
29 | 31 |
|
30 | 32 | namespace {
|
31 | 33 | // This evaluator checks two SVals for equality. The first SVal is provided via
|
@@ -87,17 +89,22 @@ void EnumCastOutOfRangeChecker::reportWarning(CheckerContext &C,
|
87 | 89 | EnumValueCastOutOfRange.reset(
|
88 | 90 | new BugType(this, "Enum cast out of range"));
|
89 | 91 |
|
90 |
| - llvm::SmallString<128> Msg{"The value provided to the cast expression is " |
91 |
| - "not in the valid range of values for "}; |
92 |
| - StringRef EnumName{E->getName()}; |
93 |
| - if (EnumName.empty()) { |
94 |
| - Msg += "the enum"; |
95 |
| - } else { |
96 |
| - Msg += '\''; |
97 |
| - Msg += EnumName; |
98 |
| - Msg += '\''; |
| 92 | + std::string ValueStr = "", NameStr = "the enum"; |
| 93 | + |
| 94 | + // Try to add details to the message: |
| 95 | + const auto ConcreteValue = |
| 96 | + C.getSVal(CE->getSubExpr()).getAs<nonloc::ConcreteInt>(); |
| 97 | + if (ConcreteValue) { |
| 98 | + ValueStr = formatv(" '{0}'", ConcreteValue->getValue()); |
| 99 | + } |
| 100 | + if (StringRef EnumName{E->getName()}; !EnumName.empty()) { |
| 101 | + NameStr = formatv("'{0}'", EnumName); |
99 | 102 | }
|
100 | 103 |
|
| 104 | + std::string Msg = formatv("The value{0} provided to the cast expression is " |
| 105 | + "not in the valid range of values for {1}", |
| 106 | + ValueStr, NameStr); |
| 107 | + |
101 | 108 | auto BR = std::make_unique<PathSensitiveBugReport>(*EnumValueCastOutOfRange,
|
102 | 109 | Msg, N);
|
103 | 110 | bugreporter::trackExpressionValue(N, CE->getSubExpr(), *BR);
|
|
0 commit comments