This is an archive of the discontinued LLVM Phabricator instance.

[analyzer][solver] Handle simplification to ConcreteInt
ClosedPublic

Authored by martong on Oct 1 2021, 2:42 AM.

Details

Summary

The solver's symbol simplification mechanism was not able to handle cases
when a symbol is simplified to a concrete integer. This patch adds the
capability.

E.g., in the attached lit test case, the original symbol is c + 1 and
it has a [0, 0] range associated with it. Then, a new condition c == 0
is assumed, so a new range constraint [0, 0] comes in for c and
simplification kicks in. c + 1 becomes 0 + 1, but the associated
range is [0, 0], so now we are able to realize the contradiction.

Diff Detail

Event Timeline

martong created this revision.Oct 1 2021, 2:42 AM
martong requested review of this revision.Oct 1 2021, 2:42 AM
Herald added a project: Restricted Project. · View Herald TranscriptOct 1 2021, 2:42 AM
Herald added a subscriber: cfe-commits. · View Herald Transcript

The patch seems reasonable, but I will need slightly more time to digest it.
I'll get back to this.

clang/include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h
391–400

I'm confused about which comment corresponds to which function.
You should also signify the difference between the two APIs.

Shouldn't be one of them an implementation detail? If so, why do we have the same visibility?

clang/test/Analysis/solver-sym-simplification-concreteint.c
23

Could we have an eval(c == -1) // TRUE?
Also, please disable eager bifurcation to prevent state-splits in the eval arguments.

martong updated this revision to Diff 377495.Oct 6 2021, 4:01 AM
martong marked 2 inline comments as done.
  • Add better comments to simplify functions
  • Add a new check and explanation to the test file
clang/include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h
391–400

Shouldn't be one of them an implementation detail? If so, why do we have the same visibility?

No, we use both of them. simplify that always returns a symbol is used e.g. in RangedConstraintManager::assumeSym.

And we use simplifyToSVal directly in EquivalenceClass::simplify.

clang/test/Analysis/solver-sym-simplification-concreteint.c
23

Actually, it is eval(c == -1) // FALSE that holds.

This is because after the simplification with b==1 we have a constraint c+1==0 but we do not reorder this equality to c==-1. Besides we have another constraint that we inherited from a previous State, this is c: [0, 1]. Now, when you query c==-1 then the latter constraint is found, thus resulting in an infeasible state, so you'll receive FALSE in the warning. Actually, these are the constraints after line 19:

"constraints": [
  { "symbol": "(reg_$1<int c>) + (reg_$0<int b>)", "range": "{ [0, 0] }" },
  { "symbol": "(reg_$1<int c>) + 1", "range": "{ [0, 0] }" },
  { "symbol": "reg_$0<int b>", "range": "{ [1, 1] }" },
  { "symbol": "reg_$1<int c>", "range": "{ [0, 1] }" }
],

I am considering to create a follow-up patch, where the reordering of c+1==0 to c==-1 is done (perhaps by reusing RangedConstraintManager::assumeSymRel).

ASDenysPetrov added inline comments.Oct 8 2021, 5:26 AM
clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
2114

We usually use R or RS. It gets readability better IMO.

2117–2119

What prevents you to not put this stuff inside ento::simplify. I think it should perfectly fit in there.

ASDenysPetrov added inline comments.Oct 8 2021, 5:30 AM
clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
2109–2123

UPD. I mean all this new snippet.

martong marked 2 inline comments as done.Oct 12 2021, 5:58 AM
martong added inline comments.
clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
2114

There are many other cases in this file where we spell out ClassConstraint, e.g. in mergeImpl we have NewClassConstraint. Also, I think the name ClassConstraint is telling way more than RS, so I'd like to keep this name.

2117–2119

ento::simplify is at a different abstraction level, it works on a SymbolRef and the SVal associated to it; and it uses the SValBuilder to achieve the desired constant folding. We have absolutely no knowledge about the equivalence classes there.

martong updated this revision to Diff 378994.Oct 12 2021, 5:59 AM
martong marked an inline comment as done.
  • Make the test case way simpler (and independent from other solver patches)
martong added inline comments.Oct 12 2021, 6:01 AM
clang/test/Analysis/solver-sym-simplification-concreteint.c
23

I've just updated the test case to be way more direct and simple.

Looks good to me. I very much like this.
Check my nits inline. Given those are fixed I'm gonna accept this.

clang/include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h
392–400

Okay, I like it!
However, it's still not entirely clear to me *when* to use which.
Could you clarify that aspect too?
Sorry for being picky but I'm not an expert on this part of the code and if it's not clear to me, it probably won't be clear to newcomers either.

clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
2110

By initializing it here, it will be much cleaner:

  1. It's not mutated, thus it can be const
  2. We can spare the else branch.

Also consider marking the rest of the variables const, so that the lack of constness would actually suggest mutability.

2112

I think a comment would be appreciated describing that we only look for infeasibility here, nothing else.
Thus, the fallthrough in the feasible case is intentional.

clang/test/Analysis/solver-sym-simplification-concreteint.c
18

Consider following the convention and using the // no-warning comment instead.
I'm also requesting an additional test case, exercising the fallthrough behavior I stated in an earlier comment.

martong updated this revision to Diff 379434.Oct 13 2021, 9:22 AM
martong marked 5 inline comments as done.
  • Use getAsSymbol to initialize the simplified member symbol
  • Add some more explanation to ento::simplify
  • Add a comment about checking only feasiblity
  • Add a new test case for the "fallthrough"
clang/include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h
392–400

Okay, I've added the following comment (though this feels a bit too mouthful for me):

/// ... We use this function in the family of assumeSymNE/EQ/LT/../GE
/// functions where we can work only with symbols. Use the other function
/// (simplifyToSVal) if you are interested in a simplification that may yield
/// a concrete constant value.
clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
2110

Good point! I've made the suggested change.

2112

Ok, I've added a comment for that.

clang/test/Analysis/solver-sym-simplification-concreteint.c
18

Okay, makes sense. I've added a new test case.

steakhal accepted this revision.Oct 14 2021, 6:19 AM

I love this! The coverage is great and looks good.

This revision is now accepted and ready to land.Oct 14 2021, 6:19 AM
This revision was automatically updated to reflect the committed changes.