[clang] f75bc5b - [analyzer] Fix symbol simplification assertion failure

Gabor Marton via cfe-commits cfe-commits at lists.llvm.org
Wed May 25 02:02:48 PDT 2022


Author: Gabor Marton
Date: 2022-05-25T10:55:50+02:00
New Revision: f75bc5bfc8f898de10e14163998c63eeb2b9f705

URL: https://github.com/llvm/llvm-project/commit/f75bc5bfc8f898de10e14163998c63eeb2b9f705
DIFF: https://github.com/llvm/llvm-project/commit/f75bc5bfc8f898de10e14163998c63eeb2b9f705.diff

LOG: [analyzer] Fix symbol simplification assertion failure

Fixes https://github.com/llvm/llvm-project/issues/55546

The assertion mentioned in the issue is triggered because an
inconsistency is formed in the Sym->Class and Class->Sym relations. A
simpler but similar inconsistency is demonstrated here:
https://reviews.llvm.org/D114887 .

Previously in `removeMember`, we didn't remove the old symbol's
Sym->Class relation. Back then, we explained it with the following two
bullet points:
> 1) This way constraints for the old symbol can still be found via it's
> equivalence class that it used to be the member of.
> 2) Performance and resource reasons. We can spare one removal and thus one
> additional tree in the forest of `ClassMap`.

This patch do remove the old symbol's Sym->Class relation in order to
keep the Sym->Class relation consistent with the Class->Sym relations.
Point 2) above has negligible performance impact, empirical measurements
do not show any noticeable difference in the run-time. Point 1) above
seems to be a not well justified statement. This is because we cannot
create a new symbol that would be equal to the old symbol after the
simplification had happened. The reason for this is that the SValBuilder
uses the available constant constraints for each sub-symbol.

Differential Revision: https://reviews.llvm.org/D126281

Added: 
    clang/test/Analysis/symbol-simplification-assertion.c

Modified: 
    clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp b/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
index 1c17d48844ea3..e0ceac51d14f3 100644
--- a/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
+++ b/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
@@ -2508,12 +2508,6 @@ EquivalenceClass::removeMember(ProgramStateRef State, const SymbolRef Old) {
   SymbolSet ClsMembers = getClassMembers(State);
   assert(ClsMembers.contains(Old));
 
-  // We don't remove `Old`'s Sym->Class relation for two reasons:
-  // 1) This way constraints for the old symbol can still be found via it's
-  // equivalence class that it used to be the member of.
-  // 2) Performance and resource reasons. We can spare one removal and thus one
-  // additional tree in the forest of `ClassMap`.
-
   // Remove `Old`'s Class->Sym relation.
   SymbolSet::Factory &F = getMembersFactory(State);
   ClassMembersTy::Factory &EMFactory = State->get_context<ClassMembers>();
@@ -2527,6 +2521,12 @@ EquivalenceClass::removeMember(ProgramStateRef State, const SymbolRef Old) {
   ClassMembersMap = EMFactory.add(ClassMembersMap, *this, ClsMembers);
   State = State->set<ClassMembers>(ClassMembersMap);
 
+  // Remove `Old`'s Sym->Class relation.
+  ClassMapTy Classes = State->get<ClassMap>();
+  ClassMapTy::Factory &CMF = State->get_context<ClassMap>();
+  Classes = CMF.remove(Classes, Old);
+  State = State->set<ClassMap>(Classes);
+
   return State;
 }
 

diff  --git a/clang/test/Analysis/symbol-simplification-assertion.c b/clang/test/Analysis/symbol-simplification-assertion.c
new file mode 100644
index 0000000000000..e17f5a619158a
--- /dev/null
+++ b/clang/test/Analysis/symbol-simplification-assertion.c
@@ -0,0 +1,25 @@
+// RUN: %clang_analyze_cc1 %s \
+// RUN:   -analyzer-checker=core \
+// RUN:   -analyzer-checker=debug.ExprInspection \
+// RUN:   -analyzer-config eagerly-assume=true \
+// RUN:   -verify
+
+// Here we test that no assertion is fired during symbol simplification.
+// Related issue: https://github.com/llvm/llvm-project/issues/55546
+
+extern void abort() __attribute__((__noreturn__));
+#define assert(expr) ((expr) ? (void)(0) : abort())
+
+void clang_analyzer_warnIfReached();
+
+int a, b, c;
+long L, L1;
+void test() {
+  assert(a + L + 1 + b != c);
+  assert(L == a);
+  assert(c == 0);
+  L1 = 0;
+  assert(a + L1 + 1 + b != c);
+  assert(a == 0); // no-assertion
+  clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
+}


        


More information about the cfe-commits mailing list