@@ -878,4 +878,119 @@ TEST_F(FlowConditionTest, Join) {
878
878
});
879
879
}
880
880
881
+ // Verifies that flow conditions are properly constructed even when the
882
+ // condition is not meaningfully interpreted.
883
+ //
884
+ // Note: currently, arbitrary function calls are uninterpreted, so the test
885
+ // exercises this case. If and when we change that, this test will not add to
886
+ // coverage (although it may still test a valuable case).
887
+ TEST_F (FlowConditionTest, OpaqueFlowConditionMergesToOpaqueBool) {
888
+ std::string Code = R"(
889
+ bool foo();
890
+
891
+ void target() {
892
+ bool Bar = true;
893
+ if (foo())
894
+ Bar = false;
895
+ (void)0;
896
+ /*[[p]]*/
897
+ }
898
+ )" ;
899
+ runDataflow (
900
+ Code, [](llvm::ArrayRef<
901
+ std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
902
+ Results,
903
+ ASTContext &ASTCtx) {
904
+ ASSERT_THAT (Results, ElementsAre (Pair (" p" , _)));
905
+ const Environment &Env = Results[0 ].second .Env ;
906
+
907
+ const ValueDecl *BarDecl = findValueDecl (ASTCtx, " Bar" );
908
+ ASSERT_THAT (BarDecl, NotNull ());
909
+
910
+ auto &BarVal =
911
+ *cast<BoolValue>(Env.getValue (*BarDecl, SkipPast::Reference));
912
+
913
+ EXPECT_FALSE (Env.flowConditionImplies (BarVal));
914
+ });
915
+ }
916
+
917
+ // Verifies that flow conditions are properly constructed even when the
918
+ // condition is not meaningfully interpreted.
919
+ //
920
+ // Note: currently, fields with recursive type calls are uninterpreted (beneath
921
+ // the first instance), so the test exercises this case. If and when we change
922
+ // that, this test will not add to coverage (although it may still test a
923
+ // valuable case).
924
+ TEST_F (FlowConditionTest, OpaqueFieldFlowConditionMergesToOpaqueBool) {
925
+ std::string Code = R"(
926
+ struct Rec {
927
+ Rec* Next;
928
+ };
929
+
930
+ struct Foo {
931
+ Rec* X;
932
+ };
933
+
934
+ void target(Foo F) {
935
+ bool Bar = true;
936
+ if (F.X->Next)
937
+ Bar = false;
938
+ (void)0;
939
+ /*[[p]]*/
940
+ }
941
+ )" ;
942
+ runDataflow (
943
+ Code, [](llvm::ArrayRef<
944
+ std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
945
+ Results,
946
+ ASTContext &ASTCtx) {
947
+ ASSERT_THAT (Results, ElementsAre (Pair (" p" , _)));
948
+ const Environment &Env = Results[0 ].second .Env ;
949
+
950
+ const ValueDecl *BarDecl = findValueDecl (ASTCtx, " Bar" );
951
+ ASSERT_THAT (BarDecl, NotNull ());
952
+
953
+ auto &BarVal =
954
+ *cast<BoolValue>(Env.getValue (*BarDecl, SkipPast::Reference));
955
+
956
+ EXPECT_FALSE (Env.flowConditionImplies (BarVal));
957
+ });
958
+ }
959
+
960
+ // Verifies that flow conditions are properly constructed even when the
961
+ // condition is not meaningfully interpreted. Adds to above by nesting the
962
+ // interestnig case inside a normal branch. This protects against degenerate
963
+ // solutions which only test for empty flow conditions, for example.
964
+ TEST_F (FlowConditionTest, OpaqueFlowConditionInsideBranchMergesToOpaqueBool) {
965
+ std::string Code = R"(
966
+ bool foo();
967
+
968
+ void target(bool Cond) {
969
+ bool Bar = true;
970
+ if (Cond) {
971
+ if (foo())
972
+ Bar = false;
973
+ (void)0;
974
+ /*[[p]]*/
975
+ }
976
+ }
977
+ )" ;
978
+ runDataflow (
979
+ Code, [](llvm::ArrayRef<
980
+ std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
981
+ Results,
982
+ ASTContext &ASTCtx) {
983
+ ASSERT_THAT (Results, ElementsAre (Pair (" p" , _)));
984
+ const Environment &Env = Results[0 ].second .Env ;
985
+
986
+ const ValueDecl *BarDecl = findValueDecl (ASTCtx, " Bar" );
987
+ ASSERT_THAT (BarDecl, NotNull ());
988
+
989
+ auto &BarVal =
990
+ *cast<BoolValue>(Env.getValue (*BarDecl, SkipPast::Reference));
991
+
992
+ EXPECT_FALSE (Env.flowConditionImplies (BarVal));
993
+ });
994
+ }
995
+
881
996
} // namespace
0 commit comments