[clang] [clang][dataflow] Fix bug in `Value` comparison. (PR #76746)

Yitzhak Mandelbaum via cfe-commits cfe-commits at lists.llvm.org
Wed Jan 10 11:54:58 PST 2024


https://github.com/ymand updated https://github.com/llvm/llvm-project/pull/76746

>From 3524e2bc42aa6f83a8ecb3ad892d4a7a33f31f03 Mon Sep 17 00:00:00 2001
From: Yitzhak Mandelbaum <yitzhakm at google.com>
Date: Tue, 2 Jan 2024 19:27:21 +0000
Subject: [PATCH 1/4] [clang][dataflow] Fix bug in `Value` comparison.

Makes value equivalence require that the values have no properties, except in
the case of equivalence by pointer equality (if the pointers are equal, nothing
else is checked).

Fixes issue #76459.
---
 clang/lib/Analysis/FlowSensitive/Value.cpp           | 10 +++++++---
 clang/unittests/Analysis/FlowSensitive/ValueTest.cpp |  4 ++--
 2 files changed, 9 insertions(+), 5 deletions(-)

diff --git a/clang/lib/Analysis/FlowSensitive/Value.cpp b/clang/lib/Analysis/FlowSensitive/Value.cpp
index 349f873f1e6c4d..a22156e79ec801 100644
--- a/clang/lib/Analysis/FlowSensitive/Value.cpp
+++ b/clang/lib/Analysis/FlowSensitive/Value.cpp
@@ -27,9 +27,13 @@ static bool areEquivalentIndirectionValues(const Value &Val1,
 }
 
 bool areEquivalentValues(const Value &Val1, const Value &Val2) {
-  return &Val1 == &Val2 || (Val1.getKind() == Val2.getKind() &&
-                            (isa<TopBoolValue>(&Val1) ||
-                             areEquivalentIndirectionValues(Val1, Val2)));
+  // If values are distinct and have properties, we don't consider them equal,
+  // leaving equality up to the user model.
+  return &Val1 == &Val2 ||
+         (Val1.getKind() == Val2.getKind() &&
+          (Val1.properties().empty() && Val2.properties().empty()) &&
+          (isa<TopBoolValue>(&Val1) ||
+           areEquivalentIndirectionValues(Val1, Val2)));
 }
 
 raw_ostream &operator<<(raw_ostream &OS, const Value &Val) {
diff --git a/clang/unittests/Analysis/FlowSensitive/ValueTest.cpp b/clang/unittests/Analysis/FlowSensitive/ValueTest.cpp
index c5d18ba74c3ed6..2060b7eb264f74 100644
--- a/clang/unittests/Analysis/FlowSensitive/ValueTest.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/ValueTest.cpp
@@ -53,8 +53,8 @@ TEST(ValueTest, EquivalentValuesWithDifferentPropsEquivalent) {
   TopBoolValue V2(A.makeAtomRef(Atom(3)));
   V1.setProperty("foo", Prop1);
   V2.setProperty("bar", Prop2);
-  EXPECT_TRUE(areEquivalentValues(V1, V2));
-  EXPECT_TRUE(areEquivalentValues(V2, V1));
+  EXPECT_FALSE(areEquivalentValues(V1, V2));
+  EXPECT_FALSE(areEquivalentValues(V2, V1));
 }
 
 TEST(ValueTest, DifferentKindsNotEquivalent) {

>From b2a6821ea88f6ed3b38c6dca1e5c7aaeef4159a2 Mon Sep 17 00:00:00 2001
From: Yitzhak Mandelbaum <ymand at users.noreply.github.com>
Date: Wed, 10 Jan 2024 13:30:38 -0500
Subject: [PATCH 2/4] Update clang/lib/Analysis/FlowSensitive/Value.cpp

Co-authored-by: martinboehme <mboehme at google.com>
---
 clang/lib/Analysis/FlowSensitive/Value.cpp | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/clang/lib/Analysis/FlowSensitive/Value.cpp b/clang/lib/Analysis/FlowSensitive/Value.cpp
index a22156e79ec801..fa86874af3f836 100644
--- a/clang/lib/Analysis/FlowSensitive/Value.cpp
+++ b/clang/lib/Analysis/FlowSensitive/Value.cpp
@@ -27,13 +27,13 @@ static bool areEquivalentIndirectionValues(const Value &Val1,
 }
 
 bool areEquivalentValues(const Value &Val1, const Value &Val2) {
+  if (&Val1 == &Val2) return true;
+  if (Val1.getKind() != Val2.getKind()) return false;
   // If values are distinct and have properties, we don't consider them equal,
   // leaving equality up to the user model.
-  return &Val1 == &Val2 ||
-         (Val1.getKind() == Val2.getKind() &&
-          (Val1.properties().empty() && Val2.properties().empty()) &&
-          (isa<TopBoolValue>(&Val1) ||
-           areEquivalentIndirectionValues(Val1, Val2)));
+  if (!Val1.properties().empty() || !Val2.properties().empty()) return false;
+  if (isa<TopBoolValue>(&Val1)) return true;
+  return areEquivalentIndirectionValues(Val1, Val2);
 }
 
 raw_ostream &operator<<(raw_ostream &OS, const Value &Val) {

>From d08fdac30f842f4dea5fbee55c37843f9bf15da0 Mon Sep 17 00:00:00 2001
From: Yitzhak Mandelbaum <yitzhakm at google.com>
Date: Wed, 10 Jan 2024 19:51:23 +0000
Subject: [PATCH 3/4] fixup! Update clang/lib/Analysis/FlowSensitive/Value.cpp

add tests
---
 .../Analysis/FlowSensitive/ValueTest.cpp      | 26 ++++++++++++++++++-
 1 file changed, 25 insertions(+), 1 deletion(-)

diff --git a/clang/unittests/Analysis/FlowSensitive/ValueTest.cpp b/clang/unittests/Analysis/FlowSensitive/ValueTest.cpp
index 2060b7eb264f74..b07328d2a56215 100644
--- a/clang/unittests/Analysis/FlowSensitive/ValueTest.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/ValueTest.cpp
@@ -45,7 +45,20 @@ TEST(ValueTest, TopsEquivalent) {
   EXPECT_TRUE(areEquivalentValues(V2, V1));
 }
 
-TEST(ValueTest, EquivalentValuesWithDifferentPropsEquivalent) {
+// The framework does not (currently) consider equivalence for values with
+// properties, leaving such to individual analyses.
+TEST(ValueTest, ValuesWithSamePropsDifferent) {
+  Arena A;
+  TopBoolValue Prop(A.makeAtomRef(Atom(0)));
+  TopBoolValue V1(A.makeAtomRef(Atom(2)));
+  TopBoolValue V2(A.makeAtomRef(Atom(3)));
+  V1.setProperty("foo", Prop);
+  V2.setProperty("foo", Prop);
+  EXPECT_FALSE(areEquivalentValues(V1, V2));
+  EXPECT_FALSE(areEquivalentValues(V2, V1));
+}
+
+TEST(ValueTest, ValuesWithDifferentPropsDifferent) {
   Arena A;
   TopBoolValue Prop1(A.makeAtomRef(Atom(0)));
   TopBoolValue Prop2(A.makeAtomRef(Atom(1)));
@@ -57,6 +70,17 @@ TEST(ValueTest, EquivalentValuesWithDifferentPropsEquivalent) {
   EXPECT_FALSE(areEquivalentValues(V2, V1));
 }
 
+TEST(ValueTest, ValuesWithDifferentNumberPropsDifferent) {
+  Arena A;
+  TopBoolValue Prop(A.makeAtomRef(Atom(0)));
+  TopBoolValue V1(A.makeAtomRef(Atom(2)));
+  TopBoolValue V2(A.makeAtomRef(Atom(3)));
+  // Only set a property on `V1`.
+  V1.setProperty("foo", Prop);
+  EXPECT_FALSE(areEquivalentValues(V1, V2));
+  EXPECT_FALSE(areEquivalentValues(V2, V1));
+}
+
 TEST(ValueTest, DifferentKindsNotEquivalent) {
   Arena A;
   auto L = ScalarStorageLocation(QualType());

>From ac3c298c71d73b18918f191e84fcf618548f91f6 Mon Sep 17 00:00:00 2001
From: Yitzhak Mandelbaum <yitzhakm at google.com>
Date: Wed, 10 Jan 2024 19:54:45 +0000
Subject: [PATCH 4/4] fixup! fixup! Update
 clang/lib/Analysis/FlowSensitive/Value.cpp

clang format
---
 clang/lib/Analysis/FlowSensitive/Value.cpp | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/clang/lib/Analysis/FlowSensitive/Value.cpp b/clang/lib/Analysis/FlowSensitive/Value.cpp
index fa86874af3f836..7fad6deb0e918f 100644
--- a/clang/lib/Analysis/FlowSensitive/Value.cpp
+++ b/clang/lib/Analysis/FlowSensitive/Value.cpp
@@ -27,12 +27,16 @@ static bool areEquivalentIndirectionValues(const Value &Val1,
 }
 
 bool areEquivalentValues(const Value &Val1, const Value &Val2) {
-  if (&Val1 == &Val2) return true;
-  if (Val1.getKind() != Val2.getKind()) return false;
+  if (&Val1 == &Val2)
+    return true;
+  if (Val1.getKind() != Val2.getKind())
+    return false;
   // If values are distinct and have properties, we don't consider them equal,
   // leaving equality up to the user model.
-  if (!Val1.properties().empty() || !Val2.properties().empty()) return false;
-  if (isa<TopBoolValue>(&Val1)) return true;
+  if (!Val1.properties().empty() || !Val2.properties().empty())
+    return false;
+  if (isa<TopBoolValue>(&Val1))
+    return true;
   return areEquivalentIndirectionValues(Val1, Val2);
 }
 



More information about the cfe-commits mailing list