[PATCH] D114887: [Analyzer][solver] Simplification: Do a fixpoint iteration before the eq class merge

Gabor Marton via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Wed Dec 1 09:12:57 PST 2021


martong created this revision.
martong added a reviewer: steakhal.
Herald added subscribers: manas, ASDenysPetrov, gamesh411, dkrupp, donat.nagy, Szelethus, mikhail.ramalho, a.sidorin, rnkovacs, szepet, baloghadamsoftware, xazax.hun.
Herald added a reviewer: Szelethus.
martong requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

This reverts commit f02c5f3478318075d1a469203900e452ba651421 <https://reviews.llvm.org/rGf02c5f3478318075d1a469203900e452ba651421> and
addresses the issue mentioned in D114619 <https://reviews.llvm.org/D114619> differently.

Repeating the issue here:
Currently, during symbol simplification we remove the original member
symbol from the equivalence class (`ClassMembers` trait). However, we
keep the reverse link (`ClassMap` trait), in order to be able the query
the related constraints even for the old member. This asymmetry can lead
to a problem when we merge equivalence classes:

  ClassA: [a, b]   // ClassMembers trait,
  a->a, b->a       // ClassMap trait, a is the representative symbol

Now let,s delete `a`:

  ClassA: [b]
  a->a, b->a

Let's merge ClassA into the trivial class `c`:

  ClassA: [c, b]
  c->c, b->c, a->a

Now, after the merge operation, `c` and `a` are actually in different
equivalence classes, which is inconsistent.

This issue manifests in a test case (added in D103317 <https://reviews.llvm.org/D103317>):

  void recurring_symbol(int b) {
    if (b * b != b)
      if ((b * b) * b * b != (b * b) * b)
        if (b * b == 1)
  }

Before the simplification we have these equivalence classes:

  trivial EQ1: [b * b != b]
  trivial EQ2: [(b * b) * b * b != (b * b) * b]

During the simplification with `b * b == 1`, EQ1 is merged with `1 != b`
`EQ1: [b * b != b, 1 != b]` and we remove the complex symbol, so
`EQ1: [1 != b]`
Then we start to simplify the only symbol in EQ2:
`(b * b) * b * b != (b * b) * b --> 1 * b * b != 1 * b --> b * b != b`
But `b * b != b` is such a symbol that had been removed previously from
EQ1, thus we reach the above mentioned inconsistency.

This patch addresses the issue by making it impossible to synthesise a
symbol that had been simplified before. We achieve this by simplifying
the given symbol to the absolute simplest form.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D114887

Files:
  clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
  clang/test/Analysis/expr-inspection-printState-eq-classes.c
  clang/test/Analysis/symbol-simplification-disequality-info.cpp
  clang/test/Analysis/symbol-simplification-fixpoint-one-iteration.cpp
  clang/test/Analysis/symbol-simplification-fixpoint-two-iterations.cpp

-------------- next part --------------
A non-text attachment was scrubbed...
Name: D114887.391057.patch
Type: text/x-patch
Size: 14673 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20211201/82d76e25/attachment-0001.bin>


More information about the cfe-commits mailing list