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



_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to