ddcc added a comment.

As an aside, I think it'd be good to land https://reviews.llvm.org/D28954 and 
https://reviews.llvm.org/D28955 first, since they affect accuracy and precision 
of various analyzer parts that this depends on.

> Here are some examples that should all be UNKNOWN (right?) but are not in the 
> current patch, assuming a and b hold unconstrained symbols of floating-point 
> type:

Yeah, those should definitely be fixed. In general, I tried to avoid performing 
simplifications on anything not of floating-point type, particularly in 
SimpleSValBuilder, but there are probably cases that I've missed.

In your example `clang_analyzer_eval(a < 4.0 || a >= 4.0)` (and likewise for 
the rest), the following is happening:

1. At ExprEngineC.cpp:VisitLogicalExpr(), we hit this logical expression for 
the first time, the introspection fails, and we generate the SVal `(((double) 
(reg_$0<float a>)) >= 4.0E+0) != 0` that is bound to `a < 4.0 || a >= 4.0`.
2. The next time around, the introspection succeeds, and we generate the SVal 
`1 S32b` that is bound to `a < 4.0 || a >= 4.0`.
3. Now, when we hit ExprInspectionChecker.cpp:getArgumentValueString(), we 
retrieve the SVal `1 S32b`, and attempt to assert it.
4. Then, we hit SimpleConstraintManager.cpp:assumeAux(), and fall into the 
`nonloc::ConcreteIntKind` case. When `Assumption` is `true`, we are fine and 
return the original `State`, but then when `Assumption` is `false`, we return 
`nullptr`.
5. Back in ExprInspectionChecker.cpp:getArgumentValueString(), we see `StTrue 
!= nullptr` and `StFalse == nullptr`, and we print `TRUE` instead of `UNKNOWN`.

I'm not familiar with `VisitLogicalExpr()` and why integer constants are being 
bound to the logical expressions. Wouldn't we simply want to assume that the 
logical expression, when expressed as a symbolic constraint, is either 
true/false in each respective child state?



================
Comment at: include/clang/StaticAnalyzer/Checkers/Checkers.td:150
 
+def FloatingPointMathChecker : Checker<"FPMath">,
+  HelpText<"Check for domain errors in floating-point math functions">,
----------------
dcoughlin wrote:
> It is fine to have this in alpha now. What package to do envision this in 
> after it is ready? Is this something that should always be on, or should be 
> opted into on a per-project basis?
This checker is a bit of a toy, in that (last I checked) Clang doesn't support 
the floating-point environment, which is typically used to install global 
floating-point exception handlers (for e.g. NaN, etc). As a result, there are 
probably going to lots of false-positives on real codebases.

Additionally, it requires the z3 solver, which probably isn't being built by 
default in most Linux distributions (and I doubt we're at the point of asking 
package maintainers to add a dependency for clang on libz3, even for those that 
do build that package).

So I think it should definitely be optional.


================
Comment at: lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp:80
+    DefinedOrUnknownSVal isPInf = SVB.evalEQ(state, V, SPInf);
+    if (isPInf.isConstant(1)) {
+      C.addTransition(state->BindExpr(CE, LCtx, isPInf));
----------------
dcoughlin wrote:
> Is there a reason you're not using assumeDual() here?
I'm not sure how `assumeDual` helps here?  The explicit checks `isPInf` and 
`isNInf` implement the short-circuit effect of logical or, whereas omitting 
them and binding directly to `isInf` miss the short-circuit effect.


================
Comment at: lib/StaticAnalyzer/Core/BasicValueFactory.cpp:118
+const llvm::APFloat &BasicValueFactory::getValue(const llvm::APFloat& X) {
+  llvm::FoldingSetNodeID ID;
+  void *InsertPos;
----------------
dcoughlin wrote:
> This logic is nearly identical to that in getValue(const llvm::APSInt& X). 
> Can the logic be factored out in some sort of zero-costish abstraction? 
> (Perhaps templatized over the value type?)
The tricky part is that there are associate class member variables for each 
function (`APSIntSet` and `APFloatSet`). I can factor out `getValue` to a 
template, but then I'd need to introduce a templated helper function with two 
specializations to retrieve the class member variable for the input template 
type. I'm not sure if that'd be zero-cost?


================
Comment at: lib/StaticAnalyzer/Core/BasicValueFactory.cpp:331
+    case BO_Div:
+      // Divide by zero
+      if (V1.isFinite() && V2.isInfinity())
----------------
dcoughlin wrote:
> Is this comment correct? Is this really a divide by zero?
> 
> I'm also a bit surprised APFloat::divide() doesn't handle this case.
I don't recall why I wrote this...


================
Comment at: lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp:1092
 
+  assert(!V.isFloat());
+
----------------
dcoughlin wrote:
> I'm wondering whether we should rename this method to "getKnownIntValue()" 
> and then just return nullptr here. What are the merits of trapping vs. 
> returning nullptr here? 
The trapping should be for debugging purposes only, since it is easy to 
accidentally call the wrong `getKnown*Value` function without disambiguating on 
the input type, and this wasn't previously necessary.


================
Comment at: lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp:1334
+      const llvm::APSInt *Int = getSymVal(State, CastSym);
+      assert(CastTy->isRealFloatingType());
+      llvm::APFloat Float(Ctx.getFloatTypeSemantics(CastTy));
----------------
dcoughlin wrote:
> I'm wondering whether this assert is too strong. Should it be the 
> responsibility of callers of this method to guarantee that it doesn't fire? 
> If so, can we document the implied precondition for the method?
Would you prefer returning nullptr instead?

I guess the question is if calling `getSymFloatVal` on a non floating-point 
type implies that the result should be converted to a floating-point type, and 
if so, whether that should trigger an assertion failure or return a null 
pointer on failure?


https://reviews.llvm.org/D28954



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

Reply via email to