Skip to content

Commit 0474a92

Browse files
authored
[clang][dataflow] Convert SpecialBoolAnalysis to synthetic fields. (#74706)
We're working towards eliminating `RecordValue`; this eliminates one more blocker on that path.
1 parent 2a988a3 commit 0474a92

File tree

1 file changed

+20
-58
lines changed

1 file changed

+20
-58
lines changed

clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp

Lines changed: 20 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -514,8 +514,17 @@ TEST_F(NoreturnDestructorTest, ConditionalOperatorNestedBranchReturns) {
514514
class SpecialBoolAnalysis final
515515
: public DataflowAnalysis<SpecialBoolAnalysis, NoopLattice> {
516516
public:
517-
explicit SpecialBoolAnalysis(ASTContext &Context)
518-
: DataflowAnalysis<SpecialBoolAnalysis, NoopLattice>(Context) {}
517+
explicit SpecialBoolAnalysis(ASTContext &Context, Environment &Env)
518+
: DataflowAnalysis<SpecialBoolAnalysis, NoopLattice>(Context) {
519+
Env.getDataflowAnalysisContext().setSyntheticFieldCallback(
520+
[](QualType Ty) -> llvm::StringMap<QualType> {
521+
RecordDecl *RD = Ty->getAsRecordDecl();
522+
if (RD == nullptr || RD->getIdentifier() == nullptr ||
523+
RD->getName() != "SpecialBool")
524+
return {};
525+
return {{"is_set", RD->getASTContext().BoolTy}};
526+
});
527+
}
519528

520529
static NoopLattice initialElement() { return {}; }
521530

@@ -530,67 +539,18 @@ class SpecialBoolAnalysis final
530539
if (const auto *E = selectFirst<CXXConstructExpr>(
531540
"call", match(cxxConstructExpr(HasSpecialBoolType).bind("call"), *S,
532541
getASTContext()))) {
533-
cast<RecordValue>(Env.getValue(*E))
534-
->setProperty("is_set", Env.getBoolLiteralValue(false));
542+
Env.setValue(Env.getResultObjectLocation(*E).getSyntheticField("is_set"),
543+
Env.getBoolLiteralValue(false));
535544
} else if (const auto *E = selectFirst<CXXMemberCallExpr>(
536545
"call", match(cxxMemberCallExpr(callee(cxxMethodDecl(ofClass(
537546
SpecialBoolRecordDecl))))
538547
.bind("call"),
539548
*S, getASTContext()))) {
540-
auto &ObjectLoc =
541-
*cast<RecordStorageLocation>(getImplicitObjectLocation(*E, Env));
542-
543-
refreshRecordValue(ObjectLoc, Env)
544-
.setProperty("is_set", Env.getBoolLiteralValue(true));
549+
if (RecordStorageLocation *ObjectLoc = getImplicitObjectLocation(*E, Env))
550+
Env.setValue(ObjectLoc->getSyntheticField("is_set"),
551+
Env.getBoolLiteralValue(true));
545552
}
546553
}
547-
548-
ComparisonResult compare(QualType Type, const Value &Val1,
549-
const Environment &Env1, const Value &Val2,
550-
const Environment &Env2) override {
551-
const auto *Decl = Type->getAsCXXRecordDecl();
552-
if (Decl == nullptr || Decl->getIdentifier() == nullptr ||
553-
Decl->getName() != "SpecialBool")
554-
return ComparisonResult::Unknown;
555-
556-
auto *IsSet1 = cast_or_null<BoolValue>(Val1.getProperty("is_set"));
557-
auto *IsSet2 = cast_or_null<BoolValue>(Val2.getProperty("is_set"));
558-
if (IsSet1 == nullptr)
559-
return IsSet2 == nullptr ? ComparisonResult::Same
560-
: ComparisonResult::Different;
561-
562-
if (IsSet2 == nullptr)
563-
return ComparisonResult::Different;
564-
565-
return Env1.proves(IsSet1->formula()) == Env2.proves(IsSet2->formula())
566-
? ComparisonResult::Same
567-
: ComparisonResult::Different;
568-
}
569-
570-
// Always returns `true` to accept the `MergedVal`.
571-
bool merge(QualType Type, const Value &Val1, const Environment &Env1,
572-
const Value &Val2, const Environment &Env2, Value &MergedVal,
573-
Environment &MergedEnv) override {
574-
const auto *Decl = Type->getAsCXXRecordDecl();
575-
if (Decl == nullptr || Decl->getIdentifier() == nullptr ||
576-
Decl->getName() != "SpecialBool")
577-
return true;
578-
579-
auto *IsSet1 = cast_or_null<BoolValue>(Val1.getProperty("is_set"));
580-
if (IsSet1 == nullptr)
581-
return true;
582-
583-
auto *IsSet2 = cast_or_null<BoolValue>(Val2.getProperty("is_set"));
584-
if (IsSet2 == nullptr)
585-
return true;
586-
587-
auto &IsSet = MergedEnv.makeAtomicBoolValue();
588-
MergedVal.setProperty("is_set", IsSet);
589-
if (Env1.proves(IsSet1->formula()) && Env2.proves(IsSet2->formula()))
590-
MergedEnv.assume(IsSet.formula());
591-
592-
return true;
593-
}
594554
};
595555

596556
class JoinFlowConditionsTest : public Test {
@@ -602,7 +562,7 @@ class JoinFlowConditionsTest : public Test {
602562
AnalysisInputs<SpecialBoolAnalysis>(
603563
Code, ast_matchers::hasName("target"),
604564
[](ASTContext &Context, Environment &Env) {
605-
return SpecialBoolAnalysis(Context);
565+
return SpecialBoolAnalysis(Context, Env);
606566
})
607567
.withASTBuildArgs({"-fsyntax-only", "-std=c++17"}),
608568
/*VerifyResults=*/[&Match](const llvm::StringMap<
@@ -650,7 +610,9 @@ TEST_F(JoinFlowConditionsTest, JoinDistinctButProvablyEquivalentValues) {
650610
ASSERT_THAT(FooDecl, NotNull());
651611

652612
auto GetFoo = [FooDecl](const Environment &Env) -> const Formula & {
653-
return cast<BoolValue>(Env.getValue(*FooDecl)->getProperty("is_set"))
613+
auto *Loc =
614+
cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
615+
return cast<BoolValue>(Env.getValue(Loc->getSyntheticField("is_set")))
654616
->formula();
655617
};
656618

0 commit comments

Comments
 (0)