Skip to content

Commit 6272226

Browse files
committed
[dataflow] Remove deprecated BoolValue flow condition accessors
Use the Formula versions instead, now. Differential Revision: https://reviews.llvm.org/D155152
1 parent 474e37c commit 6272226

File tree

10 files changed

+269
-253
lines changed

10 files changed

+269
-253
lines changed

clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -544,15 +544,11 @@ class Environment {
544544

545545
/// Record a fact that must be true if this point in the program is reached.
546546
void addToFlowCondition(const Formula &);
547-
/// Deprecated: Use Formula version instead.
548-
void addToFlowCondition(BoolValue &Val);
549547

550548
/// Returns true if the formula is always true when this point is reached.
551549
/// Returns false if the formula may be false, or if the flow condition isn't
552550
/// sufficiently precise to prove that it is true.
553551
bool flowConditionImplies(const Formula &) const;
554-
/// Deprecated: Use Formula version instead.
555-
bool flowConditionImplies(BoolValue &Val) const;
556552

557553
/// Returns the `DeclContext` of the block being analysed, if any. Otherwise,
558554
/// returns null.

clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -894,16 +894,10 @@ const StorageLocation &Environment::skip(const StorageLocation &Loc,
894894
void Environment::addToFlowCondition(const Formula &Val) {
895895
DACtx->addFlowConditionConstraint(FlowConditionToken, Val);
896896
}
897-
void Environment::addToFlowCondition(BoolValue &Val) {
898-
addToFlowCondition(Val.formula());
899-
}
900897

901898
bool Environment::flowConditionImplies(const Formula &Val) const {
902899
return DACtx->flowConditionImplies(FlowConditionToken, Val);
903900
}
904-
bool Environment::flowConditionImplies(BoolValue &Val) const {
905-
return flowConditionImplies(Val.formula());
906-
}
907901

908902
void Environment::dump(raw_ostream &OS) const {
909903
// FIXME: add printing for remaining fields and allow caller to decide what

clang/lib/Analysis/FlowSensitive/Models/ChromiumCheckModel.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ bool ChromiumCheckModel::transfer(const CFGElement &Element, Environment &Env) {
5959
if (const auto *M = dyn_cast<CXXMethodDecl>(Call->getDirectCallee())) {
6060
if (isCheckLikeMethod(CheckDecls, *M)) {
6161
// Mark this branch as unreachable.
62-
Env.addToFlowCondition(Env.getBoolLiteralValue(false));
62+
Env.addToFlowCondition(Env.arena().makeLiteral(false));
6363
return true;
6464
}
6565
}

clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp

Lines changed: 42 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "clang/Analysis/CFG.h"
2323
#include "clang/Analysis/FlowSensitive/CFGMatchSwitch.h"
2424
#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
25+
#include "clang/Analysis/FlowSensitive/Formula.h"
2526
#include "clang/Analysis/FlowSensitive/NoopLattice.h"
2627
#include "clang/Analysis/FlowSensitive/StorageLocation.h"
2728
#include "clang/Analysis/FlowSensitive/Value.h"
@@ -234,17 +235,17 @@ auto isComparisonOperatorCall(L lhs_arg_matcher, R rhs_arg_matcher) {
234235
hasArgument(1, rhs_arg_matcher));
235236
}
236237

237-
/// Ensures that `Expr` is mapped to a `BoolValue` and returns it.
238-
BoolValue &forceBoolValue(Environment &Env, const Expr &Expr) {
238+
/// Ensures that `Expr` is mapped to a `BoolValue` and returns its formula.
239+
const Formula &forceBoolValue(Environment &Env, const Expr &Expr) {
239240
auto *Value = cast_or_null<BoolValue>(Env.getValue(Expr, SkipPast::None));
240241
if (Value != nullptr)
241-
return *Value;
242+
return Value->formula();
242243

243244
auto &Loc = Env.createStorageLocation(Expr);
244245
Value = &Env.makeAtomicBoolValue();
245246
Env.setValue(Loc, *Value);
246247
Env.setStorageLocation(Expr, Loc);
247-
return *Value;
248+
return Value->formula();
248249
}
249250

250251
/// Sets `HasValueVal` as the symbolic value that represents the "has_value"
@@ -421,15 +422,16 @@ bool isEmptyOptional(const Value &OptionalVal, const Environment &Env) {
421422
auto *HasValueVal =
422423
cast_or_null<BoolValue>(OptionalVal.getProperty("has_value"));
423424
return HasValueVal != nullptr &&
424-
Env.flowConditionImplies(Env.makeNot(*HasValueVal));
425+
Env.flowConditionImplies(Env.arena().makeNot(HasValueVal->formula()));
425426
}
426427

427428
/// Returns true if and only if `OptionalVal` is initialized and known to be
428429
/// non-empty in `Env`.
429430
bool isNonEmptyOptional(const Value &OptionalVal, const Environment &Env) {
430431
auto *HasValueVal =
431432
cast_or_null<BoolValue>(OptionalVal.getProperty("has_value"));
432-
return HasValueVal != nullptr && Env.flowConditionImplies(*HasValueVal);
433+
return HasValueVal != nullptr &&
434+
Env.flowConditionImplies(HasValueVal->formula());
433435
}
434436

435437
Value *getValueBehindPossiblePointer(const Expr &E, const Environment &Env) {
@@ -485,12 +487,11 @@ void transferOptionalHasValueCall(const CXXMemberCallExpr *CallExpr,
485487

486488
/// `ModelPred` builds a logical formula relating the predicate in
487489
/// `ValueOrPredExpr` to the optional's `has_value` property.
488-
void transferValueOrImpl(const clang::Expr *ValueOrPredExpr,
489-
const MatchFinder::MatchResult &Result,
490-
LatticeTransferState &State,
491-
BoolValue &(*ModelPred)(Environment &Env,
492-
BoolValue &ExprVal,
493-
BoolValue &HasValueVal)) {
490+
void transferValueOrImpl(
491+
const clang::Expr *ValueOrPredExpr, const MatchFinder::MatchResult &Result,
492+
LatticeTransferState &State,
493+
const Formula &(*ModelPred)(Environment &Env, const Formula &ExprVal,
494+
const Formula &HasValueVal)) {
494495
auto &Env = State.Env;
495496

496497
const auto *ObjectArgumentExpr =
@@ -502,37 +503,39 @@ void transferValueOrImpl(const clang::Expr *ValueOrPredExpr,
502503
if (HasValueVal == nullptr)
503504
return;
504505

505-
Env.addToFlowCondition(
506-
ModelPred(Env, forceBoolValue(Env, *ValueOrPredExpr), *HasValueVal));
506+
Env.addToFlowCondition(ModelPred(Env, forceBoolValue(Env, *ValueOrPredExpr),
507+
HasValueVal->formula()));
507508
}
508509

509510
void transferValueOrStringEmptyCall(const clang::Expr *ComparisonExpr,
510511
const MatchFinder::MatchResult &Result,
511512
LatticeTransferState &State) {
512513
return transferValueOrImpl(ComparisonExpr, Result, State,
513-
[](Environment &Env, BoolValue &ExprVal,
514-
BoolValue &HasValueVal) -> BoolValue & {
514+
[](Environment &Env, const Formula &ExprVal,
515+
const Formula &HasValueVal) -> const Formula & {
516+
auto &A = Env.arena();
515517
// If the result is *not* empty, then we know the
516518
// optional must have been holding a value. If
517519
// `ExprVal` is true, though, we don't learn
518520
// anything definite about `has_value`, so we
519521
// don't add any corresponding implications to
520522
// the flow condition.
521-
return Env.makeImplication(Env.makeNot(ExprVal),
522-
HasValueVal);
523+
return A.makeImplies(A.makeNot(ExprVal),
524+
HasValueVal);
523525
});
524526
}
525527

526528
void transferValueOrNotEqX(const Expr *ComparisonExpr,
527529
const MatchFinder::MatchResult &Result,
528530
LatticeTransferState &State) {
529531
transferValueOrImpl(ComparisonExpr, Result, State,
530-
[](Environment &Env, BoolValue &ExprVal,
531-
BoolValue &HasValueVal) -> BoolValue & {
532+
[](Environment &Env, const Formula &ExprVal,
533+
const Formula &HasValueVal) -> const Formula & {
534+
auto &A = Env.arena();
532535
// We know that if `(opt.value_or(X) != X)` then
533536
// `opt.hasValue()`, even without knowing further
534537
// details about the contents of `opt`.
535-
return Env.makeImplication(ExprVal, HasValueVal);
538+
return A.makeImplies(ExprVal, HasValueVal);
536539
});
537540
}
538541

@@ -701,8 +704,8 @@ void transferStdForwardCall(const CallExpr *E, const MatchFinder::MatchResult &,
701704
State.Env.setValue(*LocRet, *ValArg);
702705
}
703706

704-
BoolValue &evaluateEquality(Environment &Env, BoolValue &EqVal, BoolValue &LHS,
705-
BoolValue &RHS) {
707+
const Formula &evaluateEquality(Arena &A, const Formula &EqVal,
708+
const Formula &LHS, const Formula &RHS) {
706709
// Logically, an optional<T> object is composed of two values - a `has_value`
707710
// bit and a value of type T. Equality of optional objects compares both
708711
// values. Therefore, merely comparing the `has_value` bits isn't sufficient:
@@ -717,37 +720,38 @@ BoolValue &evaluateEquality(Environment &Env, BoolValue &EqVal, BoolValue &LHS,
717720
// b) (!LHS & !RHS) => EqVal
718721
// If neither is set, then they are equal.
719722
// We rewrite b) as !EqVal => (LHS v RHS), for a more compact formula.
720-
return Env.makeAnd(
721-
Env.makeImplication(
722-
EqVal, Env.makeOr(Env.makeAnd(LHS, RHS),
723-
Env.makeAnd(Env.makeNot(LHS), Env.makeNot(RHS)))),
724-
Env.makeImplication(Env.makeNot(EqVal), Env.makeOr(LHS, RHS)));
723+
return A.makeAnd(
724+
A.makeImplies(EqVal, A.makeOr(A.makeAnd(LHS, RHS),
725+
A.makeAnd(A.makeNot(LHS), A.makeNot(RHS)))),
726+
A.makeImplies(A.makeNot(EqVal), A.makeOr(LHS, RHS)));
725727
}
726728

727729
void transferOptionalAndOptionalCmp(const clang::CXXOperatorCallExpr *CmpExpr,
728730
const MatchFinder::MatchResult &,
729731
LatticeTransferState &State) {
730732
Environment &Env = State.Env;
733+
auto &A = Env.arena();
731734
auto *CmpValue = &forceBoolValue(Env, *CmpExpr);
732735
if (auto *LHasVal = getHasValue(
733736
Env, Env.getValue(*CmpExpr->getArg(0), SkipPast::Reference)))
734737
if (auto *RHasVal = getHasValue(
735738
Env, Env.getValue(*CmpExpr->getArg(1), SkipPast::Reference))) {
736739
if (CmpExpr->getOperator() == clang::OO_ExclaimEqual)
737-
CmpValue = &State.Env.makeNot(*CmpValue);
738-
Env.addToFlowCondition(
739-
evaluateEquality(Env, *CmpValue, *LHasVal, *RHasVal));
740+
CmpValue = &A.makeNot(*CmpValue);
741+
Env.addToFlowCondition(evaluateEquality(A, *CmpValue, LHasVal->formula(),
742+
RHasVal->formula()));
740743
}
741744
}
742745

743746
void transferOptionalAndValueCmp(const clang::CXXOperatorCallExpr *CmpExpr,
744747
const clang::Expr *E, Environment &Env) {
748+
auto &A = Env.arena();
745749
auto *CmpValue = &forceBoolValue(Env, *CmpExpr);
746750
if (auto *HasVal = getHasValue(Env, Env.getValue(*E, SkipPast::Reference))) {
747751
if (CmpExpr->getOperator() == clang::OO_ExclaimEqual)
748-
CmpValue = &Env.makeNot(*CmpValue);
749-
Env.addToFlowCondition(evaluateEquality(Env, *CmpValue, *HasVal,
750-
Env.getBoolLiteralValue(true)));
752+
CmpValue = &A.makeNot(*CmpValue);
753+
Env.addToFlowCondition(
754+
evaluateEquality(A, *CmpValue, HasVal->formula(), A.makeLiteral(true)));
751755
}
752756
}
753757

@@ -929,7 +933,7 @@ std::vector<SourceLocation> diagnoseUnwrapCall(const Expr *ObjectExpr,
929933
if (auto *OptionalVal = getValueBehindPossiblePointer(*ObjectExpr, Env)) {
930934
auto *Prop = OptionalVal->getProperty("has_value");
931935
if (auto *HasValueVal = cast_or_null<BoolValue>(Prop)) {
932-
if (Env.flowConditionImplies(*HasValueVal))
936+
if (Env.flowConditionImplies(HasValueVal->formula()))
933937
return {};
934938
}
935939
}
@@ -1015,13 +1019,14 @@ bool UncheckedOptionalAccessModel::merge(QualType Type, const Value &Val1,
10151019
bool MustNonEmpty1 = isNonEmptyOptional(Val1, Env1);
10161020
bool MustNonEmpty2 = isNonEmptyOptional(Val2, Env2);
10171021
if (MustNonEmpty1 && MustNonEmpty2)
1018-
MergedEnv.addToFlowCondition(HasValueVal);
1022+
MergedEnv.addToFlowCondition(HasValueVal.formula());
10191023
else if (
10201024
// Only make the costly calls to `isEmptyOptional` if we got "unknown"
10211025
// (false) for both calls to `isNonEmptyOptional`.
10221026
!MustNonEmpty1 && !MustNonEmpty2 && isEmptyOptional(Val1, Env1) &&
10231027
isEmptyOptional(Val2, Env2))
1024-
MergedEnv.addToFlowCondition(MergedEnv.makeNot(HasValueVal));
1028+
MergedEnv.addToFlowCondition(
1029+
MergedEnv.arena().makeNot(HasValueVal.formula()));
10251030
setHasValue(MergedVal, HasValueVal);
10261031
return true;
10271032
}

clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ class TerminatorVisitor
145145
ConditionValue = false;
146146
}
147147

148-
Env.addToFlowCondition(*Val);
148+
Env.addToFlowCondition(Val->formula());
149149
return {&Cond, ConditionValue};
150150
}
151151

clang/unittests/Analysis/FlowSensitive/ChromiumCheckModelTest.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ TEST(ChromiumCheckModelTest, CheckSuccessImpliesConditionHolds) {
160160

161161
auto *FooVal = cast<BoolValue>(Env.getValue(*FooDecl));
162162

163-
EXPECT_TRUE(Env.flowConditionImplies(*FooVal));
163+
EXPECT_TRUE(Env.flowConditionImplies(FooVal->formula()));
164164
};
165165

166166
std::string Code = R"(
@@ -191,7 +191,7 @@ TEST(ChromiumCheckModelTest, UnrelatedCheckIgnored) {
191191

192192
auto *FooVal = cast<BoolValue>(Env.getValue(*FooDecl));
193193

194-
EXPECT_FALSE(Env.flowConditionImplies(*FooVal));
194+
EXPECT_FALSE(Env.flowConditionImplies(FooVal->formula()));
195195
};
196196

197197
std::string Code = R"(

clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,7 @@ namespace {
2525
using namespace clang;
2626
using namespace dataflow;
2727
using ::clang::dataflow::test::getFieldValue;
28-
using ::testing::ElementsAre;
2928
using ::testing::NotNull;
30-
using ::testing::Pair;
3129

3230
class EnvironmentTest : public ::testing::Test {
3331
protected:
@@ -38,17 +36,18 @@ class EnvironmentTest : public ::testing::Test {
3836

3937
TEST_F(EnvironmentTest, FlowCondition) {
4038
Environment Env(DAContext);
39+
auto &A = Env.arena();
4140

42-
EXPECT_TRUE(Env.flowConditionImplies(Env.getBoolLiteralValue(true)));
43-
EXPECT_FALSE(Env.flowConditionImplies(Env.getBoolLiteralValue(false)));
41+
EXPECT_TRUE(Env.flowConditionImplies(A.makeLiteral(true)));
42+
EXPECT_FALSE(Env.flowConditionImplies(A.makeLiteral(false)));
4443

45-
auto &X = Env.makeAtomicBoolValue();
44+
auto &X = A.makeAtomRef(A.makeAtom());
4645
EXPECT_FALSE(Env.flowConditionImplies(X));
4746

4847
Env.addToFlowCondition(X);
4948
EXPECT_TRUE(Env.flowConditionImplies(X));
5049

51-
auto &NotX = Env.makeNot(X);
50+
auto &NotX = A.makeNot(X);
5251
EXPECT_FALSE(Env.flowConditionImplies(NotX));
5352
}
5453

0 commit comments

Comments
 (0)