[clang] 7157956 - [dataflow] use true/false literals in formulas, rather than variables
Sam McCall via cfe-commits
cfe-commits at lists.llvm.org
Wed Jul 5 05:06:55 PDT 2023
Author: Sam McCall
Date: 2023-07-05T14:06:48+02:00
New Revision: 71579569f4399d3cf6bc618dcd449b5388d749cc
URL: https://github.com/llvm/llvm-project/commit/71579569f4399d3cf6bc618dcd449b5388d749cc
DIFF: https://github.com/llvm/llvm-project/commit/71579569f4399d3cf6bc618dcd449b5388d749cc.diff
LOG: [dataflow] use true/false literals in formulas, rather than variables
And simplify formulas containing true/false
It's unclear to me how useful this is, it does make formulas more
conveniently self-contained now (we can usefully print them without
carrying around the "true/false" labels)
(while here, simplify !!X to X, too)
Differential Revision: https://reviews.llvm.org/D153485
Added:
Modified:
clang/include/clang/Analysis/FlowSensitive/Arena.h
clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
clang/include/clang/Analysis/FlowSensitive/Formula.h
clang/lib/Analysis/FlowSensitive/Arena.cpp
clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
clang/lib/Analysis/FlowSensitive/Formula.cpp
clang/lib/Analysis/FlowSensitive/WatchedLiteralsSolver.cpp
clang/unittests/Analysis/FlowSensitive/ArenaTest.cpp
clang/unittests/Analysis/FlowSensitive/DebugSupportTest.cpp
clang/unittests/Analysis/FlowSensitive/TestingSupport.h
clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/Analysis/FlowSensitive/Arena.h b/clang/include/clang/Analysis/FlowSensitive/Arena.h
index 373697dc7379c5..8437caefeeda8f 100644
--- a/clang/include/clang/Analysis/FlowSensitive/Arena.h
+++ b/clang/include/clang/Analysis/FlowSensitive/Arena.h
@@ -19,7 +19,9 @@ namespace clang::dataflow {
/// For example, `Value`, `StorageLocation`, `Atom`, and `Formula`.
class Arena {
public:
- Arena() : True(makeAtom()), False(makeAtom()) {}
+ Arena()
+ : True(Formula::create(Alloc, Formula::Literal, {}, 1)),
+ False(Formula::create(Alloc, Formula::Literal, {}, 0)) {}
Arena(const Arena &) = delete;
Arena &operator=(const Arena &) = delete;
@@ -105,9 +107,7 @@ class Arena {
const Formula &makeAtomRef(Atom A);
/// Returns a formula for a literal true/false.
- const Formula &makeLiteral(bool Value) {
- return makeAtomRef(Value ? True : False);
- }
+ const Formula &makeLiteral(bool Value) { return Value ? True : False; }
/// Returns a new atomic boolean variable, distinct from any other.
Atom makeAtom() { return static_cast<Atom>(NextAtom++); };
@@ -139,7 +139,7 @@ class Arena {
llvm::DenseMap<const Formula *, BoolValue *> FormulaValues;
unsigned NextAtom = 0;
- Atom True, False;
+ const Formula &True, &False;
};
} // namespace clang::dataflow
diff --git a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
index 116373dce15c81..b94485c99c9bad 100644
--- a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
+++ b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
@@ -467,9 +467,8 @@ class Environment {
/// Returns a symbolic boolean value that models a boolean literal equal to
/// `Value`
- AtomicBoolValue &getBoolLiteralValue(bool Value) const {
- return cast<AtomicBoolValue>(
- arena().makeBoolValue(arena().makeLiteral(Value)));
+ BoolValue &getBoolLiteralValue(bool Value) const {
+ return arena().makeBoolValue(arena().makeLiteral(Value));
}
/// Returns an atomic boolean value.
diff --git a/clang/include/clang/Analysis/FlowSensitive/Formula.h b/clang/include/clang/Analysis/FlowSensitive/Formula.h
index 0c7b1ecd02b17c..1d8cb6b3a8b1e6 100644
--- a/clang/include/clang/Analysis/FlowSensitive/Formula.h
+++ b/clang/include/clang/Analysis/FlowSensitive/Formula.h
@@ -54,7 +54,8 @@ class alignas(const Formula *) Formula {
/// A reference to an atomic boolean variable.
/// We name these e.g. "V3", where 3 == atom identity == Value.
AtomRef,
- // FIXME: add const true/false rather than modeling them as variables
+ /// Constant true or false.
+ Literal,
Not, /// True if its only operand is false
@@ -71,6 +72,11 @@ class alignas(const Formula *) Formula {
return static_cast<Atom>(Value);
}
+ bool literal() const {
+ assert(kind() == Literal);
+ return static_cast<bool>(Value);
+ }
+
ArrayRef<const Formula *> operands() const {
return ArrayRef(reinterpret_cast<Formula *const *>(this + 1),
numOperands(kind()));
@@ -83,9 +89,9 @@ class alignas(const Formula *) Formula {
void print(llvm::raw_ostream &OS, const AtomNames * = nullptr) const;
// Allocate Formulas using Arena rather than calling this function directly.
- static Formula &create(llvm::BumpPtrAllocator &Alloc, Kind K,
- ArrayRef<const Formula *> Operands,
- unsigned Value = 0);
+ static const Formula &create(llvm::BumpPtrAllocator &Alloc, Kind K,
+ ArrayRef<const Formula *> Operands,
+ unsigned Value = 0);
private:
Formula() = default;
@@ -95,6 +101,7 @@ class alignas(const Formula *) Formula {
static unsigned numOperands(Kind K) {
switch (K) {
case AtomRef:
+ case Literal:
return 0;
case Not:
return 1;
diff --git a/clang/lib/Analysis/FlowSensitive/Arena.cpp b/clang/lib/Analysis/FlowSensitive/Arena.cpp
index a12da2d9b555eb..a61887a3500522 100644
--- a/clang/lib/Analysis/FlowSensitive/Arena.cpp
+++ b/clang/lib/Analysis/FlowSensitive/Arena.cpp
@@ -19,63 +19,83 @@ canonicalFormulaPair(const Formula &LHS, const Formula &RHS) {
return Res;
}
-const Formula &Arena::makeAtomRef(Atom A) {
- auto [It, Inserted] = AtomRefs.try_emplace(A);
+template <class Key, class ComputeFunc>
+const Formula &cached(llvm::DenseMap<Key, const Formula *> &Cache, Key K,
+ ComputeFunc &&Compute) {
+ auto [It, Inserted] = Cache.try_emplace(std::forward<Key>(K));
if (Inserted)
- It->second =
- &Formula::create(Alloc, Formula::AtomRef, {}, static_cast<unsigned>(A));
+ It->second = Compute();
return *It->second;
}
-const Formula &Arena::makeAnd(const Formula &LHS, const Formula &RHS) {
- if (&LHS == &RHS)
- return LHS;
+const Formula &Arena::makeAtomRef(Atom A) {
+ return cached(AtomRefs, A, [&] {
+ return &Formula::create(Alloc, Formula::AtomRef, {},
+ static_cast<unsigned>(A));
+ });
+}
- auto [It, Inserted] =
- Ands.try_emplace(canonicalFormulaPair(LHS, RHS), nullptr);
- if (Inserted)
- It->second = &Formula::create(Alloc, Formula::And, {&LHS, &RHS});
- return *It->second;
+const Formula &Arena::makeAnd(const Formula &LHS, const Formula &RHS) {
+ return cached(Ands, canonicalFormulaPair(LHS, RHS), [&] {
+ if (&LHS == &RHS)
+ return &LHS;
+ if (LHS.kind() == Formula::Literal)
+ return LHS.literal() ? &RHS : &LHS;
+ if (RHS.kind() == Formula::Literal)
+ return RHS.literal() ? &LHS : &RHS;
+
+ return &Formula::create(Alloc, Formula::And, {&LHS, &RHS});
+ });
}
const Formula &Arena::makeOr(const Formula &LHS, const Formula &RHS) {
- if (&LHS == &RHS)
- return LHS;
-
- auto [It, Inserted] =
- Ors.try_emplace(canonicalFormulaPair(LHS, RHS), nullptr);
- if (Inserted)
- It->second = &Formula::create(Alloc, Formula::Or, {&LHS, &RHS});
- return *It->second;
+ return cached(Ors, canonicalFormulaPair(LHS, RHS), [&] {
+ if (&LHS == &RHS)
+ return &LHS;
+ if (LHS.kind() == Formula::Literal)
+ return LHS.literal() ? &LHS : &RHS;
+ if (RHS.kind() == Formula::Literal)
+ return RHS.literal() ? &RHS : &LHS;
+
+ return &Formula::create(Alloc, Formula::Or, {&LHS, &RHS});
+ });
}
const Formula &Arena::makeNot(const Formula &Val) {
- auto [It, Inserted] = Nots.try_emplace(&Val, nullptr);
- if (Inserted)
- It->second = &Formula::create(Alloc, Formula::Not, {&Val});
- return *It->second;
+ return cached(Nots, &Val, [&] {
+ if (Val.kind() == Formula::Not)
+ return Val.operands()[0];
+ if (Val.kind() == Formula::Literal)
+ return &makeLiteral(!Val.literal());
+
+ return &Formula::create(Alloc, Formula::Not, {&Val});
+ });
}
const Formula &Arena::makeImplies(const Formula &LHS, const Formula &RHS) {
- if (&LHS == &RHS)
- return makeLiteral(true);
-
- auto [It, Inserted] =
- Implies.try_emplace(std::make_pair(&LHS, &RHS), nullptr);
- if (Inserted)
- It->second = &Formula::create(Alloc, Formula::Implies, {&LHS, &RHS});
- return *It->second;
+ return cached(Implies, std::make_pair(&LHS, &RHS), [&] {
+ if (&LHS == &RHS)
+ return &makeLiteral(true);
+ if (LHS.kind() == Formula::Literal)
+ return LHS.literal() ? &RHS : &makeLiteral(true);
+ if (RHS.kind() == Formula::Literal)
+ return RHS.literal() ? &RHS : &makeNot(LHS);
+
+ return &Formula::create(Alloc, Formula::Implies, {&LHS, &RHS});
+ });
}
const Formula &Arena::makeEquals(const Formula &LHS, const Formula &RHS) {
- if (&LHS == &RHS)
- return makeLiteral(true);
-
- auto [It, Inserted] =
- Equals.try_emplace(canonicalFormulaPair(LHS, RHS), nullptr);
- if (Inserted)
- It->second = &Formula::create(Alloc, Formula::Equal, {&LHS, &RHS});
- return *It->second;
+ return cached(Equals, canonicalFormulaPair(LHS, RHS), [&] {
+ if (&LHS == &RHS)
+ return &makeLiteral(true);
+ if (LHS.kind() == Formula::Literal)
+ return LHS.literal() ? &RHS : &makeNot(RHS);
+ if (RHS.kind() == Formula::Literal)
+ return RHS.literal() ? &LHS : &makeNot(LHS);
+
+ return &Formula::create(Alloc, Formula::Equal, {&LHS, &RHS});
+ });
}
IntegerValue &Arena::makeIntLiteral(llvm::APInt Value) {
diff --git a/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp b/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
index a807ef8209be85..2971df6f11de2b 100644
--- a/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
+++ b/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
@@ -131,8 +131,6 @@ DataflowAnalysisContext::joinFlowConditions(Atom FirstToken,
Solver::Result DataflowAnalysisContext::querySolver(
llvm::SetVector<const Formula *> Constraints) {
- Constraints.insert(&arena().makeLiteral(true));
- Constraints.insert(&arena().makeNot(arena().makeLiteral(false)));
return S->solve(Constraints.getArrayRef());
}
@@ -201,13 +199,8 @@ void DataflowAnalysisContext::dumpFlowCondition(Atom Token,
llvm::DenseSet<Atom> VisitedTokens;
addTransitiveFlowConditionConstraints(Token, Constraints, VisitedTokens);
- // TODO: have formulas know about true/false directly instead
- Atom True = arena().makeLiteral(true).getAtom();
- Atom False = arena().makeLiteral(false).getAtom();
- Formula::AtomNames Names = {{False, "false"}, {True, "true"}};
-
for (const auto *Constraint : Constraints) {
- Constraint->print(OS, &Names);
+ Constraint->print(OS);
OS << "\n";
}
}
diff --git a/clang/lib/Analysis/FlowSensitive/Formula.cpp b/clang/lib/Analysis/FlowSensitive/Formula.cpp
index 504ad2fb7938af..12f4e25097d7d8 100644
--- a/clang/lib/Analysis/FlowSensitive/Formula.cpp
+++ b/clang/lib/Analysis/FlowSensitive/Formula.cpp
@@ -16,8 +16,9 @@
namespace clang::dataflow {
-Formula &Formula::create(llvm::BumpPtrAllocator &Alloc, Kind K,
- ArrayRef<const Formula *> Operands, unsigned Value) {
+const Formula &Formula::create(llvm::BumpPtrAllocator &Alloc, Kind K,
+ ArrayRef<const Formula *> Operands,
+ unsigned Value) {
assert(Operands.size() == numOperands(K));
if (Value != 0) // Currently, formulas have values or operands, not both.
assert(numOperands(K) == 0);
@@ -37,6 +38,7 @@ Formula &Formula::create(llvm::BumpPtrAllocator &Alloc, Kind K,
static llvm::StringLiteral sigil(Formula::Kind K) {
switch (K) {
case Formula::AtomRef:
+ case Formula::Literal:
return "";
case Formula::Not:
return "!";
@@ -61,7 +63,16 @@ void Formula::print(llvm::raw_ostream &OS, const AtomNames *Names) const {
switch (numOperands(kind())) {
case 0:
- OS << getAtom();
+ switch (kind()) {
+ case AtomRef:
+ OS << getAtom();
+ break;
+ case Literal:
+ OS << (literal() ? "true" : "false");
+ break;
+ default:
+ llvm_unreachable("unhandled formula kind");
+ }
break;
case 1:
OS << sigil(kind());
diff --git a/clang/lib/Analysis/FlowSensitive/WatchedLiteralsSolver.cpp b/clang/lib/Analysis/FlowSensitive/WatchedLiteralsSolver.cpp
index 037886d09c4f7d..bf48a1fbda5940 100644
--- a/clang/lib/Analysis/FlowSensitive/WatchedLiteralsSolver.cpp
+++ b/clang/lib/Analysis/FlowSensitive/WatchedLiteralsSolver.cpp
@@ -241,6 +241,9 @@ CNFFormula buildCNF(const llvm::ArrayRef<const Formula *> &Vals) {
switch (Val->kind()) {
case Formula::AtomRef:
break;
+ case Formula::Literal:
+ CNF.addClause(Val->literal() ? posLit(Var) : negLit(Var));
+ break;
case Formula::And: {
const Variable LHS = GetVar(Val->operands()[0]);
const Variable RHS = GetVar(Val->operands()[1]);
diff --git a/clang/unittests/Analysis/FlowSensitive/ArenaTest.cpp b/clang/unittests/Analysis/FlowSensitive/ArenaTest.cpp
index 0f8552a58787cb..98c9cc44273cff 100644
--- a/clang/unittests/Analysis/FlowSensitive/ArenaTest.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/ArenaTest.cpp
@@ -31,12 +31,6 @@ TEST_F(ArenaTest, CreateTopBoolValueReturnsDistinctValues) {
EXPECT_NE(&X, &Y);
}
-TEST_F(ArenaTest, GetOrCreateConjunctionReturnsSameExprGivenSameArgs) {
- auto &X = A.makeAtomRef(A.makeAtom());
- auto &XAndX = A.makeAnd(X, X);
- EXPECT_EQ(&XAndX, &X);
-}
-
TEST_F(ArenaTest, GetOrCreateConjunctionReturnsSameExprOnSubsequentCalls) {
auto &X = A.makeAtomRef(A.makeAtom());
auto &Y = A.makeAtomRef(A.makeAtom());
@@ -52,12 +46,6 @@ TEST_F(ArenaTest, GetOrCreateConjunctionReturnsSameExprOnSubsequentCalls) {
EXPECT_NE(&XAndY1, &XAndZ);
}
-TEST_F(ArenaTest, GetOrCreateDisjunctionReturnsSameExprGivenSameArgs) {
- auto &X = A.makeAtomRef(A.makeAtom());
- auto &XOrX = A.makeOr(X, X);
- EXPECT_EQ(&XOrX, &X);
-}
-
TEST_F(ArenaTest, GetOrCreateDisjunctionReturnsSameExprOnSubsequentCalls) {
auto &X = A.makeAtomRef(A.makeAtom());
auto &Y = A.makeAtomRef(A.makeAtom());
@@ -83,12 +71,6 @@ TEST_F(ArenaTest, GetOrCreateNegationReturnsSameExprOnSubsequentCalls) {
EXPECT_NE(&NotX1, &NotY);
}
-TEST_F(ArenaTest, GetOrCreateImplicationReturnsTrueGivenSameArgs) {
- auto &X = A.makeAtomRef(A.makeAtom());
- auto &XImpliesX = A.makeImplies(X, X);
- EXPECT_EQ(&XImpliesX, &A.makeLiteral(true));
-}
-
TEST_F(ArenaTest, GetOrCreateImplicationReturnsSameExprOnSubsequentCalls) {
auto &X = A.makeAtomRef(A.makeAtom());
auto &Y = A.makeAtomRef(A.makeAtom());
@@ -104,12 +86,6 @@ TEST_F(ArenaTest, GetOrCreateImplicationReturnsSameExprOnSubsequentCalls) {
EXPECT_NE(&XImpliesY1, &XImpliesZ);
}
-TEST_F(ArenaTest, GetOrCreateIffReturnsTrueGivenSameArgs) {
- auto &X = A.makeAtomRef(A.makeAtom());
- auto &XIffX = A.makeEquals(X, X);
- EXPECT_EQ(&XIffX, &A.makeLiteral(true));
-}
-
TEST_F(ArenaTest, GetOrCreateIffReturnsSameExprOnSubsequentCalls) {
auto &X = A.makeAtomRef(A.makeAtom());
auto &Y = A.makeAtomRef(A.makeAtom());
@@ -137,5 +113,36 @@ TEST_F(ArenaTest, Interning) {
EXPECT_EQ(&B1.formula(), &F1);
}
+TEST_F(ArenaTest, IdentitySimplification) {
+ auto &X = A.makeAtomRef(A.makeAtom());
+
+ EXPECT_EQ(&X, &A.makeAnd(X, X));
+ EXPECT_EQ(&X, &A.makeOr(X, X));
+ EXPECT_EQ(&A.makeLiteral(true), &A.makeImplies(X, X));
+ EXPECT_EQ(&A.makeLiteral(true), &A.makeEquals(X, X));
+ EXPECT_EQ(&X, &A.makeNot(A.makeNot(X)));
+}
+
+TEST_F(ArenaTest, LiteralSimplification) {
+ auto &X = A.makeAtomRef(A.makeAtom());
+
+ EXPECT_EQ(&X, &A.makeAnd(X, A.makeLiteral(true)));
+ EXPECT_EQ(&A.makeLiteral(false), &A.makeAnd(X, A.makeLiteral(false)));
+
+ EXPECT_EQ(&A.makeLiteral(true), &A.makeOr(X, A.makeLiteral(true)));
+ EXPECT_EQ(&X, &A.makeOr(X, A.makeLiteral(false)));
+
+ EXPECT_EQ(&A.makeLiteral(true), &A.makeImplies(X, A.makeLiteral(true)));
+ EXPECT_EQ(&A.makeNot(X), &A.makeImplies(X, A.makeLiteral(false)));
+ EXPECT_EQ(&X, &A.makeImplies(A.makeLiteral(true), X));
+ EXPECT_EQ(&A.makeLiteral(true), &A.makeImplies(A.makeLiteral(false), X));
+
+ EXPECT_EQ(&X, &A.makeEquals(X, A.makeLiteral(true)));
+ EXPECT_EQ(&A.makeNot(X), &A.makeEquals(X, A.makeLiteral(false)));
+
+ EXPECT_EQ(&A.makeLiteral(false), &A.makeNot(A.makeLiteral(true)));
+ EXPECT_EQ(&A.makeLiteral(true), &A.makeNot(A.makeLiteral(false)));
+}
+
} // namespace
} // namespace clang::dataflow
diff --git a/clang/unittests/Analysis/FlowSensitive/DebugSupportTest.cpp b/clang/unittests/Analysis/FlowSensitive/DebugSupportTest.cpp
index 22bf8cadd1116f..cf266f4c3a832d 100644
--- a/clang/unittests/Analysis/FlowSensitive/DebugSupportTest.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/DebugSupportTest.cpp
@@ -30,6 +30,12 @@ TEST(BoolValueDebugStringTest, AtomicBoolean) {
EXPECT_THAT(llvm::to_string(*B), StrEq(Expected));
}
+TEST(BoolValueDebugStringTest, Literal) {
+ ConstraintContext Ctx;
+ EXPECT_EQ("true", llvm::to_string(*Ctx.literal(true)));
+ EXPECT_EQ("false", llvm::to_string(*Ctx.literal(false)));
+}
+
TEST(BoolValueDebugStringTest, Negation) {
ConstraintContext Ctx;
auto B = Ctx.neg(Ctx.atom());
@@ -91,16 +97,14 @@ TEST(BoolValueDebugStringTest, NestedBoolean) {
TEST(BoolValueDebugStringTest, ComplexBooleanWithSomeNames) {
ConstraintContext Ctx;
- auto True = Ctx.atom();
- auto False = Ctx.atom();
- auto V2 = Ctx.atom();
- auto V3 = Ctx.atom();
+ auto X = Ctx.atom();
+ auto Y = Ctx.atom();
Formula::AtomNames Names;
- Names[True->getAtom()] = "true";
- Names[False->getAtom()] = "false";
- auto B = Ctx.disj(Ctx.conj(False, V2), Ctx.disj(True, V3));
+ Names[X->getAtom()] = "X";
+ Names[Y->getAtom()] = "Y";
+ auto B = Ctx.disj(Ctx.conj(Y, Ctx.atom()), Ctx.disj(X, Ctx.atom()));
- auto Expected = R"(((false & V2) | (true | V3)))";
+ auto Expected = R"(((Y & V2) | (X | V3)))";
std::string Actual;
llvm::raw_string_ostream OS(Actual);
B->print(OS, &Names);
diff --git a/clang/unittests/Analysis/FlowSensitive/TestingSupport.h b/clang/unittests/Analysis/FlowSensitive/TestingSupport.h
index 93991d87d77f20..2eaa783d8ea1cf 100644
--- a/clang/unittests/Analysis/FlowSensitive/TestingSupport.h
+++ b/clang/unittests/Analysis/FlowSensitive/TestingSupport.h
@@ -457,6 +457,11 @@ class ConstraintContext {
return &Formula::create(A, Formula::AtomRef, {}, NextAtom++);
}
+ // Returns a reference to a literal boolean value.
+ const Formula *literal(bool B) {
+ return &Formula::create(A, Formula::Literal, {}, B);
+ }
+
// Creates a boolean conjunction.
const Formula *conj(const Formula *LHS, const Formula *RHS) {
return make(Formula::And, {LHS, RHS});
diff --git a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
index 667e42f7f063b7..4da598745cfdd2 100644
--- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -2963,14 +2963,14 @@ TEST(TransferTest, AssignFromBoolLiteral) {
ASSERT_THAT(FooDecl, NotNull());
const auto *FooVal =
- dyn_cast_or_null<AtomicBoolValue>(Env.getValue(*FooDecl));
+ dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
ASSERT_THAT(FooVal, NotNull());
const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
ASSERT_THAT(BarDecl, NotNull());
const auto *BarVal =
- dyn_cast_or_null<AtomicBoolValue>(Env.getValue(*BarDecl));
+ dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
ASSERT_THAT(BarVal, NotNull());
EXPECT_EQ(FooVal, &Env.getBoolLiteralValue(true));
@@ -3148,7 +3148,7 @@ TEST(TransferTest, AssignFromBoolNegation) {
ASSERT_THAT(FooDecl, NotNull());
const auto *FooVal =
- dyn_cast_or_null<AtomicBoolValue>(Env.getValue(*FooDecl));
+ dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
ASSERT_THAT(FooVal, NotNull());
const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
More information about the cfe-commits
mailing list