[PATCH] D128658: [clang][dataflow] Ensure atomic boolean values representing true and false are not replaced in `buildAndSubstituteFlowCondition`

weiyi via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Mon Jun 27 08:54:21 PDT 2022


wyt created this revision.
Herald added subscribers: martong, tschuett, xazax.hun.
Herald added a project: All.
wyt requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D128658

Files:
  clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
  clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
  clang/unittests/Analysis/FlowSensitive/DataflowAnalysisContextTest.cpp


Index: clang/unittests/Analysis/FlowSensitive/DataflowAnalysisContextTest.cpp
===================================================================
--- clang/unittests/Analysis/FlowSensitive/DataflowAnalysisContextTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/DataflowAnalysisContextTest.cpp
@@ -276,6 +276,38 @@
       Context.getOrCreateConjunction(X, Context.getOrCreateConjunction(Y, Z))));
 }
 
+TEST_F(DataflowAnalysisContextTest, SubstituteFlowConditionsTrueUnchanged) {
+  auto &True = Context.getBoolLiteralValue(true);
+  auto &Other = Context.createAtomicBoolValue();
+
+  // FC = True
+  auto &FC = Context.makeFlowConditionToken();
+  Context.addFlowConditionConstraint(FC, True);
+
+  // `True` should never be substituted
+  auto &FCNoSubstitution = Context.buildAndSubstituteFlowCondition(FC, {{}});
+  auto &FCTrySubstituteTrue =
+      Context.buildAndSubstituteFlowCondition(FC, {{&True, &Other}});
+  EXPECT_TRUE(
+      Context.equivalentBoolValues(FCNoSubstitution, FCTrySubstituteTrue));
+}
+
+TEST_F(DataflowAnalysisContextTest, SubstituteFlowConditionsFalseUnchanged) {
+  auto &False = Context.getBoolLiteralValue(false);
+  auto &Other = Context.createAtomicBoolValue();
+
+  // FC = False
+  auto &FC = Context.makeFlowConditionToken();
+  Context.addFlowConditionConstraint(FC, False);
+
+  // `False` should never be substituted
+  auto &FCNoSubstitution = Context.buildAndSubstituteFlowCondition(FC, {{}});
+  auto &FCTrySubstituteFalse =
+      Context.buildAndSubstituteFlowCondition(FC, {{&False, &Other}});
+  EXPECT_TRUE(
+      Context.equivalentBoolValues(FCNoSubstitution, FCTrySubstituteFalse));
+}
+
 TEST_F(DataflowAnalysisContextTest, SubstituteFlowConditionsAtomicFC) {
   auto &X = Context.createAtomicBoolValue();
   auto &True = Context.getBoolLiteralValue(true);
Index: clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
===================================================================
--- clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
+++ clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
@@ -172,10 +172,20 @@
 BoolValue &DataflowAnalysisContext::substituteBoolValue(
     BoolValue &Val,
     llvm::DenseMap<BoolValue *, BoolValue *> &SubstitutionsCache) {
+  if (&Val == &getBoolLiteralValue(true) ||
+      &Val == &getBoolLiteralValue(false)) {
+    // Don't substitute boolean values representing true / false.
+    return Val;
+  }
+
   auto IT = SubstitutionsCache.find(&Val);
   if (IT != SubstitutionsCache.end()) {
+    // Return memoized result of substituting this boolean value.
     return *IT->second;
   }
+
+  // Handle substitution on the boolean value (and its subvalues), saving the
+  // result into `SubstitutionsCache`.
   BoolValue *Result;
   switch (Val.getKind()) {
   case Value::Kind::AtomicBool: {
Index: clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
===================================================================
--- clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
+++ clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
@@ -205,13 +205,14 @@
   //
   /// Builds and returns the logical formula defining the flow condition
   /// identified by `Token`. If a value in the formula is present as a key in
-  /// `Substitutions`, it will be substituted with the value it maps to.
+  /// `Substitutions`, and it is not a True/False boolean literal, it will be
+  /// substituted with the value it maps to.
   /// As an example, say we have flow condition tokens FC1, FC2, FC3 and
   /// FlowConditionConstraints: { FC1: C1,
-  ///                             FC2: C2,
+  ///                             FC2: C2 ^ True,
   ///                             FC3: (FC1 v FC2) ^ C3 }
-  /// buildAndSubstituteFlowCondition(FC3, {{C1 -> C1'}}) will return a value
-  /// corresponding to (C1' v C2) ^ C3.
+  /// buildAndSubstituteFlowCondition(FC3, {{C1 -> C1', True -> _ }}) will
+  /// return a value corresponding to (C1' v (C2 ^ True)) ^ C3.
   BoolValue &buildAndSubstituteFlowCondition(
       AtomicBoolValue &Token,
       llvm::DenseMap<AtomicBoolValue *, BoolValue *> Substitutions);


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D128658.440252.patch
Type: text/x-patch
Size: 4172 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20220627/db1fd0e0/attachment-0001.bin>


More information about the cfe-commits mailing list