Skip to content

Commit 8ff6434

Browse files
authored
Revert "[clang][dataflow] Model conditional operator correctly." (#89577)
Reverts #89213 This is causing buildbot failures.
1 parent abb958f commit 8ff6434

File tree

7 files changed

+46
-149
lines changed

7 files changed

+46
-149
lines changed

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

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -244,21 +244,6 @@ class Environment {
244244
Environment::ValueModel &Model,
245245
ExprJoinBehavior ExprBehavior);
246246

247-
/// Returns a value that approximates both `Val1` and `Val2`, or null if no
248-
/// such value can be produced.
249-
///
250-
/// `Env1` and `Env2` can be used to query child values and path condition
251-
/// implications of `Val1` and `Val2` respectively. The joined value will be
252-
/// produced in `JoinedEnv`.
253-
///
254-
/// Requirements:
255-
///
256-
/// `Val1` and `Val2` must model values of type `Type`.
257-
static Value *joinValues(QualType Ty, Value *Val1, const Environment &Env1,
258-
Value *Val2, const Environment &Env2,
259-
Environment &JoinedEnv,
260-
Environment::ValueModel &Model);
261-
262247
/// Widens the environment point-wise, using `PrevEnv` as needed to inform the
263248
/// approximation.
264249
///

clang/include/clang/Analysis/FlowSensitive/Transfer.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,7 @@ class StmtToEnvMap {
5353
/// Requirements:
5454
///
5555
/// `S` must not be `ParenExpr` or `ExprWithCleanups`.
56-
void transfer(const StmtToEnvMap &StmtToEnv, const Stmt &S, Environment &Env,
57-
Environment::ValueModel &Model);
56+
void transfer(const StmtToEnvMap &StmtToEnv, const Stmt &S, Environment &Env);
5857

5958
} // namespace dataflow
6059
} // namespace clang

clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp

Lines changed: 22 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -237,8 +237,13 @@ joinLocToVal(const llvm::MapVector<const StorageLocation *, Value *> &LocToVal,
237237
continue;
238238
assert(It->second != nullptr);
239239

240-
if (Value *JoinedVal = Environment::joinValues(
241-
Loc->getType(), Val, Env1, It->second, Env2, JoinedEnv, Model)) {
240+
if (areEquivalentValues(*Val, *It->second)) {
241+
Result.insert({Loc, Val});
242+
continue;
243+
}
244+
245+
if (Value *JoinedVal = joinDistinctValues(
246+
Loc->getType(), *Val, Env1, *It->second, Env2, JoinedEnv, Model)) {
242247
Result.insert({Loc, JoinedVal});
243248
}
244249
}
@@ -770,16 +775,27 @@ Environment Environment::join(const Environment &EnvA, const Environment &EnvB,
770775
JoinedEnv.LocForRecordReturnVal = EnvA.LocForRecordReturnVal;
771776
JoinedEnv.ThisPointeeLoc = EnvA.ThisPointeeLoc;
772777

773-
if (EnvA.CallStack.empty()) {
778+
if (EnvA.ReturnVal == nullptr || EnvB.ReturnVal == nullptr) {
779+
// `ReturnVal` might not always get set -- for example if we have a return
780+
// statement of the form `return some_other_func()` and we decide not to
781+
// analyze `some_other_func()`.
782+
// In this case, we can't say anything about the joined return value -- we
783+
// don't simply want to propagate the return value that we do have, because
784+
// it might not be the correct one.
785+
// This occurs for example in the test `ContextSensitiveMutualRecursion`.
774786
JoinedEnv.ReturnVal = nullptr;
787+
} else if (areEquivalentValues(*EnvA.ReturnVal, *EnvB.ReturnVal)) {
788+
JoinedEnv.ReturnVal = EnvA.ReturnVal;
775789
} else {
790+
assert(!EnvA.CallStack.empty());
776791
// FIXME: Make `CallStack` a vector of `FunctionDecl` so we don't need this
777792
// cast.
778793
auto *Func = dyn_cast<FunctionDecl>(EnvA.CallStack.back());
779794
assert(Func != nullptr);
780-
JoinedEnv.ReturnVal =
781-
joinValues(Func->getReturnType(), EnvA.ReturnVal, EnvA, EnvB.ReturnVal,
782-
EnvB, JoinedEnv, Model);
795+
if (Value *JoinedVal =
796+
joinDistinctValues(Func->getReturnType(), *EnvA.ReturnVal, EnvA,
797+
*EnvB.ReturnVal, EnvB, JoinedEnv, Model))
798+
JoinedEnv.ReturnVal = JoinedVal;
783799
}
784800

785801
if (EnvA.ReturnLoc == EnvB.ReturnLoc)
@@ -805,24 +821,6 @@ Environment Environment::join(const Environment &EnvA, const Environment &EnvB,
805821
return JoinedEnv;
806822
}
807823

808-
Value *Environment::joinValues(QualType Ty, Value *Val1,
809-
const Environment &Env1, Value *Val2,
810-
const Environment &Env2, Environment &JoinedEnv,
811-
Environment::ValueModel &Model) {
812-
if (Val1 == nullptr || Val2 == nullptr)
813-
// We can't say anything about the joined value -- even if one of the values
814-
// is non-null, we don't want to simply propagate it, because it would be
815-
// too specific: Because the other value is null, that means we have no
816-
// information at all about the value (i.e. the value is unconstrained).
817-
return nullptr;
818-
819-
if (areEquivalentValues(*Val1, *Val2))
820-
// Arbitrarily return one of the two values.
821-
return Val1;
822-
823-
return joinDistinctValues(Ty, *Val1, Env1, *Val2, Env2, JoinedEnv, Model);
824-
}
825-
826824
StorageLocation &Environment::createStorageLocation(QualType Type) {
827825
return DACtx->createStorageLocation(Type);
828826
}

clang/lib/Analysis/FlowSensitive/Transfer.cpp

Lines changed: 15 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -124,9 +124,8 @@ namespace {
124124

125125
class TransferVisitor : public ConstStmtVisitor<TransferVisitor> {
126126
public:
127-
TransferVisitor(const StmtToEnvMap &StmtToEnv, Environment &Env,
128-
Environment::ValueModel &Model)
129-
: StmtToEnv(StmtToEnv), Env(Env), Model(Model) {}
127+
TransferVisitor(const StmtToEnvMap &StmtToEnv, Environment &Env)
128+
: StmtToEnv(StmtToEnv), Env(Env) {}
130129

131130
void VisitBinaryOperator(const BinaryOperator *S) {
132131
const Expr *LHS = S->getLHS();
@@ -642,41 +641,17 @@ class TransferVisitor : public ConstStmtVisitor<TransferVisitor> {
642641
}
643642

644643
void VisitConditionalOperator(const ConditionalOperator *S) {
645-
const Environment *TrueEnv = StmtToEnv.getEnvironment(*S->getTrueExpr());
646-
const Environment *FalseEnv = StmtToEnv.getEnvironment(*S->getFalseExpr());
647-
648-
if (TrueEnv == nullptr || FalseEnv == nullptr) {
649-
// We should always have an environment as we should visit the true /
650-
// false branches before the conditional operator.
651-
assert(false);
652-
return;
653-
}
654-
655-
if (S->isGLValue()) {
656-
StorageLocation *TrueLoc = TrueEnv->getStorageLocation(*S->getTrueExpr());
657-
StorageLocation *FalseLoc =
658-
FalseEnv->getStorageLocation(*S->getFalseExpr());
659-
if (TrueLoc == FalseLoc && TrueLoc != nullptr)
660-
Env.setStorageLocation(*S, *TrueLoc);
661-
} else if (!S->getType()->isRecordType()) {
662-
// The conditional operator can evaluate to either of the values of the
663-
// two branches. To model this, join these two values together to yield
664-
// the result of the conditional operator.
665-
// Note: Most joins happen in `computeBlockInputState()`, but this case is
666-
// different:
667-
// - `computeBlockInputState()` (which in turn calls `Environment::join()`
668-
// joins values associated with the _same_ expression or storage
669-
// location, then associates the joined value with that expression or
670-
// storage location. This join has nothing to do with transfer --
671-
// instead, it joins together the results of performing transfer on two
672-
// different blocks.
673-
// - Here, we join values associated with _different_ expressions (the
674-
// true and false branch), then associate the joined value with a third
675-
// expression (the conditional operator itself). This join is what it
676-
// means to perform transfer on the conditional operator.
677-
if (Value *Val = Environment::joinValues(
678-
S->getType(), TrueEnv->getValue(*S->getTrueExpr()), *TrueEnv,
679-
FalseEnv->getValue(*S->getFalseExpr()), *FalseEnv, Env, Model))
644+
// FIXME: Revisit this once flow conditions are added to the framework. For
645+
// `a = b ? c : d` we can add `b => a == c && !b => a == d` to the flow
646+
// condition.
647+
// When we do this, we will need to retrieve the values of the operands from
648+
// the environments for the basic blocks they are computed in, in a similar
649+
// way to how this is done for short-circuited logical operators in
650+
// `getLogicOperatorSubExprValue()`.
651+
if (S->isGLValue())
652+
Env.setStorageLocation(*S, Env.createObject(S->getType()));
653+
else if (!S->getType()->isRecordType()) {
654+
if (Value *Val = Env.createValue(S->getType()))
680655
Env.setValue(*S, *Val);
681656
}
682657
}
@@ -835,14 +810,12 @@ class TransferVisitor : public ConstStmtVisitor<TransferVisitor> {
835810

836811
const StmtToEnvMap &StmtToEnv;
837812
Environment &Env;
838-
Environment::ValueModel &Model;
839813
};
840814

841815
} // namespace
842816

843-
void transfer(const StmtToEnvMap &StmtToEnv, const Stmt &S, Environment &Env,
844-
Environment::ValueModel &Model) {
845-
TransferVisitor(StmtToEnv, Env, Model).Visit(&S);
817+
void transfer(const StmtToEnvMap &StmtToEnv, const Stmt &S, Environment &Env) {
818+
TransferVisitor(StmtToEnv, Env).Visit(&S);
846819
}
847820

848821
} // namespace dataflow

clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,7 @@ builtinTransferStatement(unsigned CurBlockID, const CFGStmt &Elt,
316316
const Stmt *S = Elt.getStmt();
317317
assert(S != nullptr);
318318
transfer(StmtToEnvMap(AC.ACFG, AC.BlockStates, CurBlockID, InputState), *S,
319-
InputState.Env, AC.Analysis);
319+
InputState.Env);
320320
}
321321

322322
/// Built-in transfer function for `CFGInitializer`.
@@ -452,7 +452,7 @@ transferCFGBlock(const CFGBlock &Block, AnalysisContext &AC,
452452
// terminator condition, but not as a `CFGElement`. The condition of an if
453453
// statement is one such example.
454454
transfer(StmtToEnvMap(AC.ACFG, AC.BlockStates, Block.getBlockID(), State),
455-
*TerminatorCond, State.Env, AC.Analysis);
455+
*TerminatorCond, State.Env);
456456

457457
// If the transfer function didn't produce a value, create an atom so that
458458
// we have *some* value for the condition expression. This ensures that

clang/unittests/Analysis/FlowSensitive/TestingSupport.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -456,7 +456,7 @@ const IndirectFieldDecl *findIndirectFieldDecl(ASTContext &ASTCtx,
456456
/// Requirements:
457457
///
458458
/// `Name` must be unique in `ASTCtx`.
459-
template <class LocT = StorageLocation>
459+
template <class LocT>
460460
LocT &getLocForDecl(ASTContext &ASTCtx, const Environment &Env,
461461
llvm::StringRef Name) {
462462
const ValueDecl *VD = findValueDecl(ASTCtx, Name);
@@ -470,7 +470,7 @@ LocT &getLocForDecl(ASTContext &ASTCtx, const Environment &Env,
470470
/// Requirements:
471471
///
472472
/// `Name` must be unique in `ASTCtx`.
473-
template <class ValueT = Value>
473+
template <class ValueT>
474474
ValueT &getValueForDecl(ASTContext &ASTCtx, const Environment &Env,
475475
llvm::StringRef Name) {
476476
const ValueDecl *VD = findValueDecl(ASTCtx, Name);

clang/unittests/Analysis/FlowSensitive/TransferTest.cpp

Lines changed: 4 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -5275,67 +5275,6 @@ TEST(TransferTest, BinaryOperatorComma) {
52755275
});
52765276
}
52775277

5278-
TEST(TransferTest, ConditionalOperatorValue) {
5279-
std::string Code = R"(
5280-
void target(bool Cond, bool B1, bool B2) {
5281-
bool JoinSame = Cond ? B1 : B1;
5282-
bool JoinDifferent = Cond ? B1 : B2;
5283-
// [[p]]
5284-
}
5285-
)";
5286-
runDataflow(
5287-
Code,
5288-
[](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5289-
ASTContext &ASTCtx) {
5290-
Environment Env = getEnvironmentAtAnnotation(Results, "p").fork();
5291-
5292-
auto &B1 = getValueForDecl<BoolValue>(ASTCtx, Env, "B1");
5293-
auto &B2 = getValueForDecl<BoolValue>(ASTCtx, Env, "B2");
5294-
auto &JoinSame = getValueForDecl<BoolValue>(ASTCtx, Env, "JoinSame");
5295-
auto &JoinDifferent =
5296-
getValueForDecl<BoolValue>(ASTCtx, Env, "JoinDifferent");
5297-
5298-
EXPECT_EQ(&JoinSame, &B1);
5299-
5300-
const Formula &JoinDifferentEqB1 =
5301-
Env.arena().makeEquals(JoinDifferent.formula(), B1.formula());
5302-
EXPECT_TRUE(Env.allows(JoinDifferentEqB1));
5303-
EXPECT_FALSE(Env.proves(JoinDifferentEqB1));
5304-
5305-
const Formula &JoinDifferentEqB2 =
5306-
Env.arena().makeEquals(JoinDifferent.formula(), B2.formula());
5307-
EXPECT_TRUE(Env.allows(JoinDifferentEqB2));
5308-
EXPECT_FALSE(Env.proves(JoinDifferentEqB1));
5309-
});
5310-
}
5311-
5312-
TEST(TransferTest, ConditionalOperatorLocation) {
5313-
std::string Code = R"(
5314-
void target(bool Cond, int I1, int I2) {
5315-
int &JoinSame = Cond ? I1 : I1;
5316-
int &JoinDifferent = Cond ? I1 : I2;
5317-
// [[p]]
5318-
}
5319-
)";
5320-
runDataflow(
5321-
Code,
5322-
[](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5323-
ASTContext &ASTCtx) {
5324-
Environment Env = getEnvironmentAtAnnotation(Results, "p").fork();
5325-
5326-
StorageLocation &I1 = getLocForDecl(ASTCtx, Env, "I1");
5327-
StorageLocation &I2 = getLocForDecl(ASTCtx, Env, "I2");
5328-
StorageLocation &JoinSame = getLocForDecl(ASTCtx, Env, "JoinSame");
5329-
StorageLocation &JoinDifferent =
5330-
getLocForDecl(ASTCtx, Env, "JoinDifferent");
5331-
5332-
EXPECT_EQ(&JoinSame, &I1);
5333-
5334-
EXPECT_NE(&JoinDifferent, &I1);
5335-
EXPECT_NE(&JoinDifferent, &I2);
5336-
});
5337-
}
5338-
53395278
TEST(TransferTest, IfStmtBranchExtendsFlowCondition) {
53405279
std::string Code = R"(
53415280
void target(bool Foo) {
@@ -5583,7 +5522,10 @@ TEST(TransferTest, ContextSensitiveReturnReferenceWithConditionalOperator) {
55835522
auto *Loc = Env.getReturnStorageLocation();
55845523
EXPECT_THAT(Loc, NotNull());
55855524

5586-
EXPECT_EQ(Loc, SLoc);
5525+
// TODO: We would really like to make this stronger assertion, but that
5526+
// doesn't work because we don't propagate values correctly through
5527+
// the conditional operator yet.
5528+
// EXPECT_EQ(Loc, SLoc);
55875529
},
55885530
{BuiltinOptions{ContextSensitiveOptions{}}});
55895531
}

0 commit comments

Comments
 (0)