[PATCH] D33672: [analyzer] INT50-CPP. Do not cast to an out-of-range enumeration checker

Aaron Ballman via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Tue Jul 25 06:44:59 PDT 2017


aaron.ballman added a comment.

In https://reviews.llvm.org/D33672#819683, @xazax.hun wrote:

> Aaron, could you comment on the applicability of this check to C? Thanks in advance.


C has different rules for their enumerations in that the enumerators are all ints, but the enumeration type is either `char`, a signed integer type, or an unsigned integer type depending on the values of the enumerators. So this problem exists:

  enum E {
    one = 1
  };
  
  void f(int i) {
    enum E e = (enum E)i;
  }
  
  int main(void) {
    f(1024);
  }

If `enum E` is represented by a `char`, then the cast causes a loss of precision. However, this isn't undefined behavior in C like it is in C++.



================
Comment at: lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp:29
+namespace {
+// This evaluator checks 2 SVals for equality. The first SVal is provided via
+// the constructor, the second is the parameter of the overloaded () operator.
----------------
s/2/two


================
Comment at: lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp:34
+class ConstraintBasedEQEvaluator {
+private:
+  const DefinedOrUnknownSVal CompareValue;
----------------
No need for the access specifier; it defaults to `private`.


================
Comment at: lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp:47
+    DefinedOrUnknownSVal EnumDeclValue = SVB.makeIntVal(EnumDeclInitValue);
+    const auto ElemEqualsValueToCast =
+        SVB.evalEQ(PS, EnumDeclValue, CompareValue);
----------------
Please do not use `auto` here as the type is not spelled out in the initialization. Also, you can drop the `const` qualifier if it's not a pointer or reference type.


================
Comment at: lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp:74-75
+  EnumValueVector DeclValues;
+  for (const auto *D : ED->decls()) {
+    const auto ECD = dyn_cast<EnumConstantDecl>(D);
+    DeclValues.push_back(ECD->getInitVal());
----------------
Instead of enumerating over `decls()` and then casting, just enumerate over `enumerators()` and  the cast isn't needed. Or, even better:
```
EnumValueVector DeclValues(ED->enumerator_end() - ED->enumerator_begin());
std::transform(ED->enumerator_begin(), ED->enumerator_end(), DeclValues.begin(),
                       [](const EnumConstantDecl *D) { return D->getInitVal(); });
```


================
Comment at: lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp:84
+void EnumCastOutOfRangeChecker::reportWarning(CheckerContext &C) const {
+  if (auto N = C.generateNonFatalErrorNode(C.getState())) {
+    if (!EnumValueCastOutOfRange)
----------------
NoQ wrote:
> `C.getState()` is the default value (if you see how `generateNonFatalErrorNode()` calls `addTransition()` which in turns substitutes nullptr with `getState()`), so it can be omitted.
Don't use `auto` here.


================
Comment at: lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp:87-89
+          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."));
----------------
Also, diagnostics should not be full sentences or grammatically correct, so drop the capitalization and full stop.


================
Comment at: lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp:116
+  // function to handle this.
+  const EnumDecl *ED = T->getAs<EnumType>()->getDecl();
+
----------------
You can use `castAs<>()` because you've already determined it's an enumeral type.


================
Comment at: lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp:121
+  bool PossibleValueMatch =
+      std::any_of(DeclValues.begin(), DeclValues.end(),
+                  ConstraintBasedEQEvaluator(C, *ValueToCastOptional));
----------------
You can use `llvm::any_of()` and pass in the container.


https://reviews.llvm.org/D33672





More information about the cfe-commits mailing list