ASDenysPetrov added inline comments.

================
Comment at: 
clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h:293-296
+    SymbolRef Sym = Operand;
+    while (isa<SymbolCast>(Sym))
+      Sym = cast<SymbolCast>(Sym)->Operand;
+    return Sym;
----------------
vsavchenko wrote:
> ASDenysPetrov wrote:
> > vsavchenko wrote:
> > > 
> > Do you think the recursive call is better than the loop? But, I guess, I 
> > see your point. You option could be safer if we had another implementation 
> > of the virtual method. Or you think such alike cast symbol is possible in 
> > the future? Well, for now `ignoreCasts` doesn't make sense to any other 
> > `Expr` successors.
> Oh, wait, why is it even virtual?  I don't think that it should be virtual.
> Are similar functions in `Expr` virtual?
> And I think that this implementation should live in `SymExpr` directly.  Then 
> it would look like:
> ```
> if (const SymbolCast *ThisAsCast = dyn_cast<SymbolCast>(this)) {
>   return ThisAsCast->ignoreCasts();
> }
> return this;
> ```
Yes, `SymExpr` is an abstract class. And because of limitations and dependency 
of inheritance we are not able to know the implementaion of `SymbolCast`. 
Unfortunately, this is not a CRTP.


================
Comment at: clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp:1203
+    if (!Opts.ShouldSupportSymbolicIntegerCasts)
+      return VisitSymExpr(Sym);
+
----------------
vsavchenko wrote:
> ASDenysPetrov wrote:
> > vsavchenko wrote:
> > > Why do you use `VisitSymExpr` here?  You want to interrupt all `Visits 
> > > or... I'm not sure I fully understand.
> > Here we want to delegate the reasoning to another handler as we don't 
> > support non-integral cast yet.
> You are not delegating it here.  `Visit` includes a runtime dispatch that 
> calls a correct `VisitTYPE` method.  Here you call `VisitSymExpr` directly, 
> which is one of the `VisitTYPE` methods.  No dispatch will happen, and since 
> we use `VisitSymExpr` as the last resort (it's the most base class, if we got 
> there, we don't actually support the expression), you interrupt the `Visit` 
> and go directly to "the last resort".
> 
> See the problem now?
OK. I reject this idea before. If we call `Visit` inside `VisitSymbolCast`, we 
will go into recursive loop, because it will return us back to 
`VisitSymbolCast` as we have passed `Sym` as is. (This is theoretically, I 
didn't check in practice.) Or I'm missing smth?
I choosed `VisitSymExpr` here because all kinds of `SymbolCast` were previously 
handled here. So I decided to pass all unsupproted forms of casts there.


================
Comment at: clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp:1241
+      // Find the first constraint and exit the loop.
+      RSPtr = getConstraint(State, S);
+    }
----------------
vsavchenko wrote:
> ASDenysPetrov wrote:
> > vsavchenko wrote:
> > > Why do you get associated constraint directly without consulting with 
> > > what `SymbolRangeInferrer` can tell you about it?
> > What do you mean? I didn't get. Could you give an example?
> `getConstraint` returns whatever constraint we have stored directly in the 
> constraint map.  That's the main source of information for ranges, but not 
> the only one.
> 
> Here is the  of things that you skip, when you do `getConstraint` here:
>   * we can understand that something is equality/disequality check and find 
> the corresponding info in Equivalence Classes data structure
>   * we can see that the expression has the form `A - B` and we can find 
> constraint for `B - A`
>   * we can see that the expression is comparison `A op B` and check what 
> other comparison info we have on `A` and `B` (your own change)
>   * we can see that the expression is of form `A op B` and check if we know 
> something about `A` and `B`, and produce a reasonable constraint out of this 
> information
> 
> In order to use the right information, you should use `infer` that will 
> actually do all other things as well.  That's how `SymbolRangeInferrer` is 
> designed, to be **recursive**.
> 
> Speaking of **recursiveness**.  All these loops and manually checking for 
> types of the cast's operand is against this pattern.  Recursive visitors 
> should call `Visit` for children nodes (like `RecursiveASTVisitor`).  In 
> other words, if `f(x)` is a visit function, it should be defined like this:
> ```
> f(x) = g(f(x->operand_1), f(x->operand_2), ... , f(x->operand_N))
> ```
> or if we talk about your case specifically:
> ```
> f(x: SymbolCast) = h(f(x->Operand))
> ```
> and the `h` function should transform the range set returned by 
> `f(x->Operand)` into a range set appropriate for `x`.
> 
> NOTE: `h` can also intersect different ranges
Thank you for useful notes!  I'll take them into account.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D103096/new/

https://reviews.llvm.org/D103096

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

Reply via email to