diff --git a/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp b/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp --- a/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp +++ b/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp @@ -2508,12 +2508,6 @@ 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(); @@ -2527,6 +2521,12 @@ ClassMembersMap = EMFactory.add(ClassMembersMap, *this, ClsMembers); State = State->set(ClassMembersMap); + // Remove `Old`'s Sym->Class relation. + ClassMapTy Classes = State->get(); + ClassMapTy::Factory &CMF = State->get_context(); + Classes = CMF.remove(Classes, Old); + State = State->set(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 --- /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}} +}