xref: /llvm-project/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp (revision a8fb0dcc41bf355a3bff9ad7165715a8b6012059)
1 //===- unittests/Analysis/FlowSensitive/TransferTest.cpp ------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "TestingSupport.h"
10 #include "clang/AST/ASTContext.h"
11 #include "clang/AST/Decl.h"
12 #include "clang/ASTMatchers/ASTMatchers.h"
13 #include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h"
14 #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
15 #include "clang/Analysis/FlowSensitive/NoopAnalysis.h"
16 #include "clang/Analysis/FlowSensitive/RecordOps.h"
17 #include "clang/Analysis/FlowSensitive/StorageLocation.h"
18 #include "clang/Analysis/FlowSensitive/Value.h"
19 #include "clang/Basic/LangStandard.h"
20 #include "llvm/ADT/SmallVector.h"
21 #include "llvm/ADT/StringRef.h"
22 #include "llvm/Testing/Support/Error.h"
23 #include "gmock/gmock.h"
24 #include "gtest/gtest.h"
25 #include <optional>
26 #include <string>
27 #include <utility>
28 
29 namespace {
30 
31 using namespace clang;
32 using namespace dataflow;
33 using namespace test;
34 using ::testing::Eq;
35 using ::testing::IsNull;
36 using ::testing::Ne;
37 using ::testing::NotNull;
38 using ::testing::UnorderedElementsAre;
39 
40 void runDataflow(
41     llvm::StringRef Code,
42     std::function<
43         void(const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &,
44              ASTContext &)>
45         VerifyResults,
46     DataflowAnalysisOptions Options,
47     LangStandard::Kind Std = LangStandard::lang_cxx17,
48     llvm::StringRef TargetFun = "target") {
49   ASSERT_THAT_ERROR(checkDataflowWithNoopAnalysis(Code, VerifyResults, Options,
50                                                   Std, TargetFun),
51                     llvm::Succeeded());
52 }
53 
54 void runDataflow(
55     llvm::StringRef Code,
56     std::function<
57         void(const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &,
58              ASTContext &)>
59         VerifyResults,
60     LangStandard::Kind Std = LangStandard::lang_cxx17,
61     bool ApplyBuiltinTransfer = true, llvm::StringRef TargetFun = "target") {
62   runDataflow(Code, std::move(VerifyResults),
63               {ApplyBuiltinTransfer ? BuiltinOptions{}
64                                     : std::optional<BuiltinOptions>()},
65               Std, TargetFun);
66 }
67 
68 void runDataflowOnLambda(
69     llvm::StringRef Code,
70     std::function<
71         void(const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &,
72              ASTContext &)>
73         VerifyResults,
74     DataflowAnalysisOptions Options,
75     LangStandard::Kind Std = LangStandard::lang_cxx17) {
76   ASSERT_THAT_ERROR(
77       checkDataflowWithNoopAnalysis(
78           Code,
79           ast_matchers::hasDeclContext(
80               ast_matchers::cxxRecordDecl(ast_matchers::isLambda())),
81           VerifyResults, Options, Std),
82       llvm::Succeeded());
83 }
84 
85 void runDataflowOnLambda(
86     llvm::StringRef Code,
87     std::function<
88         void(const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &,
89              ASTContext &)>
90         VerifyResults,
91     LangStandard::Kind Std = LangStandard::lang_cxx17,
92     bool ApplyBuiltinTransfer = true) {
93   runDataflowOnLambda(Code, std::move(VerifyResults),
94                       {ApplyBuiltinTransfer ? BuiltinOptions{}
95                                             : std::optional<BuiltinOptions>()},
96                       Std);
97 }
98 
99 const Formula &getFormula(const ValueDecl &D, const Environment &Env) {
100   return cast<BoolValue>(Env.getValue(D))->formula();
101 }
102 
103 TEST(TransferTest, CNotSupported) {
104   std::string Code = R"(
105     void target() {}
106   )";
107   ASSERT_THAT_ERROR(checkDataflowWithNoopAnalysis(
108                         Code, [](const auto &, auto &) {}, {BuiltinOptions{}},
109                         LangStandard::lang_c89),
110                     llvm::FailedWithMessage("Can only analyze C++"));
111 }
112 
113 TEST(TransferTest, IntVarDeclNotTrackedWhenTransferDisabled) {
114   std::string Code = R"(
115     void target() {
116       int Foo;
117       // [[p]]
118     }
119   )";
120   runDataflow(
121       Code,
122       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
123          ASTContext &ASTCtx) {
124         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
125         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
126 
127         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
128         ASSERT_THAT(FooDecl, NotNull());
129 
130         EXPECT_EQ(Env.getStorageLocation(*FooDecl), nullptr);
131       },
132       LangStandard::lang_cxx17,
133       /*ApplyBuiltinTransfer=*/false);
134 }
135 
136 TEST(TransferTest, BoolVarDecl) {
137   std::string Code = R"(
138     void target() {
139       bool Foo;
140       // [[p]]
141     }
142   )";
143   runDataflow(
144       Code,
145       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
146          ASTContext &ASTCtx) {
147         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
148         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
149 
150         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
151         ASSERT_THAT(FooDecl, NotNull());
152 
153         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
154         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
155 
156         const Value *FooVal = Env.getValue(*FooLoc);
157         EXPECT_TRUE(isa_and_nonnull<BoolValue>(FooVal));
158       });
159 }
160 
161 TEST(TransferTest, IntVarDecl) {
162   std::string Code = R"(
163     void target() {
164       int Foo;
165       // [[p]]
166     }
167   )";
168   runDataflow(
169       Code,
170       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
171          ASTContext &ASTCtx) {
172         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
173         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
174 
175         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
176         ASSERT_THAT(FooDecl, NotNull());
177 
178         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
179         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
180 
181         const Value *FooVal = Env.getValue(*FooLoc);
182         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
183       });
184 }
185 
186 TEST(TransferTest, StructIncomplete) {
187   std::string Code = R"(
188     struct A;
189 
190     void target() {
191       A* Foo;
192       // [[p]]
193     }
194   )";
195   runDataflow(
196       Code,
197       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
198          ASTContext &ASTCtx) {
199         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
200         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
201 
202         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
203         ASSERT_THAT(FooDecl, NotNull());
204         auto *FooValue = dyn_cast_or_null<PointerValue>(Env.getValue(*FooDecl));
205         ASSERT_THAT(FooValue, NotNull());
206 
207         EXPECT_TRUE(isa<RecordStorageLocation>(FooValue->getPointeeLoc()));
208         auto *FooPointeeValue = Env.getValue(FooValue->getPointeeLoc());
209         ASSERT_THAT(FooPointeeValue, NotNull());
210         EXPECT_TRUE(isa<RecordValue>(FooPointeeValue));
211       });
212 }
213 
214 // As a memory optimization, we prevent modeling fields nested below a certain
215 // level (currently, depth 3). This test verifies this lack of modeling. We also
216 // include a regression test for the case that the unmodeled field is a
217 // reference to a struct; previously, we crashed when accessing such a field.
218 TEST(TransferTest, StructFieldUnmodeled) {
219   std::string Code = R"(
220     struct S { int X; };
221     S GlobalS;
222     struct A { S &Unmodeled = GlobalS; };
223     struct B { A F3; };
224     struct C { B F2; };
225     struct D { C F1; };
226 
227     void target() {
228       D Bar;
229       A &Foo = Bar.F1.F2.F3;
230       int Zab = Foo.Unmodeled.X;
231       // [[p]]
232     }
233   )";
234   runDataflow(
235       Code,
236       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
237          ASTContext &ASTCtx) {
238         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
239         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
240 
241         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
242         ASSERT_THAT(FooDecl, NotNull());
243         QualType FooReferentType = FooDecl->getType()->getPointeeType();
244         ASSERT_TRUE(FooReferentType->isStructureType());
245         auto FooFields = FooReferentType->getAsRecordDecl()->fields();
246 
247         FieldDecl *UnmodeledDecl = nullptr;
248         for (FieldDecl *Field : FooFields) {
249           if (Field->getNameAsString() == "Unmodeled") {
250             UnmodeledDecl = Field;
251           } else {
252             FAIL() << "Unexpected field: " << Field->getNameAsString();
253           }
254         }
255         ASSERT_THAT(UnmodeledDecl, NotNull());
256 
257         const auto *FooLoc =
258             cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
259         const auto *UnmodeledLoc = FooLoc->getChild(*UnmodeledDecl);
260         ASSERT_TRUE(isa<RecordStorageLocation>(UnmodeledLoc));
261         EXPECT_THAT(Env.getValue(*UnmodeledLoc), IsNull());
262 
263         const ValueDecl *ZabDecl = findValueDecl(ASTCtx, "Zab");
264         ASSERT_THAT(ZabDecl, NotNull());
265         EXPECT_THAT(Env.getValue(*ZabDecl), NotNull());
266       });
267 }
268 
269 TEST(TransferTest, StructVarDecl) {
270   std::string Code = R"(
271     struct A {
272       int Bar;
273     };
274 
275     void target() {
276       A Foo;
277       (void)Foo.Bar;
278       // [[p]]
279     }
280   )";
281   runDataflow(
282       Code,
283       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
284          ASTContext &ASTCtx) {
285         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
286         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
287 
288         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
289         ASSERT_THAT(FooDecl, NotNull());
290 
291         ASSERT_TRUE(FooDecl->getType()->isStructureType());
292         auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields();
293 
294         FieldDecl *BarDecl = nullptr;
295         for (FieldDecl *Field : FooFields) {
296           if (Field->getNameAsString() == "Bar") {
297             BarDecl = Field;
298           } else {
299             FAIL() << "Unexpected field: " << Field->getNameAsString();
300           }
301         }
302         ASSERT_THAT(BarDecl, NotNull());
303 
304         const auto *FooLoc =
305             cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
306         EXPECT_TRUE(isa<IntegerValue>(getFieldValue(FooLoc, *BarDecl, Env)));
307       });
308 }
309 
310 TEST(TransferTest, StructVarDeclWithInit) {
311   std::string Code = R"(
312     struct A {
313       int Bar;
314     };
315 
316     A Gen();
317 
318     void target() {
319       A Foo = Gen();
320       (void)Foo.Bar;
321       // [[p]]
322     }
323   )";
324   runDataflow(
325       Code,
326       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
327          ASTContext &ASTCtx) {
328         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
329         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
330 
331         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
332         ASSERT_THAT(FooDecl, NotNull());
333 
334         ASSERT_TRUE(FooDecl->getType()->isStructureType());
335         auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields();
336 
337         FieldDecl *BarDecl = nullptr;
338         for (FieldDecl *Field : FooFields) {
339           if (Field->getNameAsString() == "Bar") {
340             BarDecl = Field;
341           } else {
342             FAIL() << "Unexpected field: " << Field->getNameAsString();
343           }
344         }
345         ASSERT_THAT(BarDecl, NotNull());
346 
347         const auto *FooLoc =
348             cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
349         EXPECT_TRUE(isa<IntegerValue>(getFieldValue(FooLoc, *BarDecl, Env)));
350       });
351 }
352 
353 TEST(TransferTest, StructArrayVarDecl) {
354   std::string Code = R"(
355     struct A {};
356 
357     void target() {
358       A Array[2];
359       // [[p]]
360     }
361   )";
362   runDataflow(
363       Code,
364       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
365          ASTContext &ASTCtx) {
366         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
367 
368         const ValueDecl *ArrayDecl = findValueDecl(ASTCtx, "Array");
369 
370         // We currently don't create values for arrays.
371         ASSERT_THAT(Env.getValue(*ArrayDecl), IsNull());
372       });
373 }
374 
375 TEST(TransferTest, ClassVarDecl) {
376   std::string Code = R"(
377     class A {
378      public:
379       int Bar;
380     };
381 
382     void target() {
383       A Foo;
384       (void)Foo.Bar;
385       // [[p]]
386     }
387   )";
388   runDataflow(
389       Code,
390       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
391          ASTContext &ASTCtx) {
392         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
393         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
394 
395         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
396         ASSERT_THAT(FooDecl, NotNull());
397 
398         ASSERT_TRUE(FooDecl->getType()->isClassType());
399         auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields();
400 
401         FieldDecl *BarDecl = nullptr;
402         for (FieldDecl *Field : FooFields) {
403           if (Field->getNameAsString() == "Bar") {
404             BarDecl = Field;
405           } else {
406             FAIL() << "Unexpected field: " << Field->getNameAsString();
407           }
408         }
409         ASSERT_THAT(BarDecl, NotNull());
410 
411         const auto *FooLoc =
412             cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
413         EXPECT_TRUE(isa<IntegerValue>(getFieldValue(FooLoc, *BarDecl, Env)));
414       });
415 }
416 
417 TEST(TransferTest, ReferenceVarDecl) {
418   std::string Code = R"(
419     struct A {};
420 
421     A &getA();
422 
423     void target() {
424       A &Foo = getA();
425       // [[p]]
426     }
427   )";
428   runDataflow(
429       Code,
430       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
431          ASTContext &ASTCtx) {
432         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
433         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
434 
435         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
436         ASSERT_THAT(FooDecl, NotNull());
437 
438         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
439         ASSERT_TRUE(isa_and_nonnull<RecordStorageLocation>(FooLoc));
440 
441         const Value *FooReferentVal = Env.getValue(*FooLoc);
442         EXPECT_TRUE(isa_and_nonnull<RecordValue>(FooReferentVal));
443       });
444 }
445 
446 TEST(TransferTest, SelfReferentialReferenceVarDecl) {
447   std::string Code = R"(
448     struct A;
449 
450     struct B {};
451 
452     struct C {
453       A &FooRef;
454       A *FooPtr;
455       B &BazRef;
456       B *BazPtr;
457     };
458 
459     struct A {
460       C &Bar;
461     };
462 
463     A &getA();
464 
465     void target() {
466       A &Foo = getA();
467       (void)Foo.Bar.FooRef;
468       (void)Foo.Bar.FooPtr;
469       (void)Foo.Bar.BazRef;
470       (void)Foo.Bar.BazPtr;
471       // [[p]]
472     }
473   )";
474   runDataflow(Code, [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>>
475                            &Results,
476                        ASTContext &ASTCtx) {
477     ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
478     const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
479 
480     const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
481     ASSERT_THAT(FooDecl, NotNull());
482 
483     ASSERT_TRUE(FooDecl->getType()->isReferenceType());
484     ASSERT_TRUE(FooDecl->getType().getNonReferenceType()->isStructureType());
485     const auto FooFields =
486         FooDecl->getType().getNonReferenceType()->getAsRecordDecl()->fields();
487 
488     FieldDecl *BarDecl = nullptr;
489     for (FieldDecl *Field : FooFields) {
490       if (Field->getNameAsString() == "Bar") {
491         BarDecl = Field;
492       } else {
493         FAIL() << "Unexpected field: " << Field->getNameAsString();
494       }
495     }
496     ASSERT_THAT(BarDecl, NotNull());
497 
498     ASSERT_TRUE(BarDecl->getType()->isReferenceType());
499     ASSERT_TRUE(BarDecl->getType().getNonReferenceType()->isStructureType());
500     const auto BarFields =
501         BarDecl->getType().getNonReferenceType()->getAsRecordDecl()->fields();
502 
503     FieldDecl *FooRefDecl = nullptr;
504     FieldDecl *FooPtrDecl = nullptr;
505     FieldDecl *BazRefDecl = nullptr;
506     FieldDecl *BazPtrDecl = nullptr;
507     for (FieldDecl *Field : BarFields) {
508       if (Field->getNameAsString() == "FooRef") {
509         FooRefDecl = Field;
510       } else if (Field->getNameAsString() == "FooPtr") {
511         FooPtrDecl = Field;
512       } else if (Field->getNameAsString() == "BazRef") {
513         BazRefDecl = Field;
514       } else if (Field->getNameAsString() == "BazPtr") {
515         BazPtrDecl = Field;
516       } else {
517         FAIL() << "Unexpected field: " << Field->getNameAsString();
518       }
519     }
520     ASSERT_THAT(FooRefDecl, NotNull());
521     ASSERT_THAT(FooPtrDecl, NotNull());
522     ASSERT_THAT(BazRefDecl, NotNull());
523     ASSERT_THAT(BazPtrDecl, NotNull());
524 
525     const auto &FooLoc =
526         *cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
527 
528     const auto &BarLoc =
529         *cast<RecordStorageLocation>(FooLoc.getChild(*BarDecl));
530 
531     const auto &FooReferentLoc =
532         *cast<RecordStorageLocation>(BarLoc.getChild(*FooRefDecl));
533     EXPECT_THAT(Env.getValue(FooReferentLoc), NotNull());
534     EXPECT_THAT(getFieldValue(&FooReferentLoc, *BarDecl, Env), IsNull());
535 
536     const auto &FooPtrVal =
537         *cast<PointerValue>(getFieldValue(&BarLoc, *FooPtrDecl, Env));
538     const auto &FooPtrPointeeLoc =
539         cast<RecordStorageLocation>(FooPtrVal.getPointeeLoc());
540     EXPECT_THAT(Env.getValue(FooPtrPointeeLoc), NotNull());
541     EXPECT_THAT(getFieldValue(&FooPtrPointeeLoc, *BarDecl, Env), IsNull());
542 
543     EXPECT_THAT(getFieldValue(&BarLoc, *BazRefDecl, Env), NotNull());
544 
545     const auto &BazPtrVal =
546         *cast<PointerValue>(getFieldValue(&BarLoc, *BazPtrDecl, Env));
547     const StorageLocation &BazPtrPointeeLoc = BazPtrVal.getPointeeLoc();
548     EXPECT_THAT(Env.getValue(BazPtrPointeeLoc), NotNull());
549   });
550 }
551 
552 TEST(TransferTest, PointerVarDecl) {
553   std::string Code = R"(
554     struct A {};
555 
556     A *getA();
557 
558     void target() {
559       A *Foo = getA();
560       // [[p]]
561     }
562   )";
563   runDataflow(
564       Code,
565       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
566          ASTContext &ASTCtx) {
567         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
568         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
569 
570         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
571         ASSERT_THAT(FooDecl, NotNull());
572 
573         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
574         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
575 
576         const PointerValue *FooVal = cast<PointerValue>(Env.getValue(*FooLoc));
577         const StorageLocation &FooPointeeLoc = FooVal->getPointeeLoc();
578         EXPECT_TRUE(isa<RecordStorageLocation>(&FooPointeeLoc));
579 
580         const Value *FooPointeeVal = Env.getValue(FooPointeeLoc);
581         EXPECT_TRUE(isa_and_nonnull<RecordValue>(FooPointeeVal));
582       });
583 }
584 
585 TEST(TransferTest, SelfReferentialPointerVarDecl) {
586   std::string Code = R"(
587     struct A;
588 
589     struct B {};
590 
591     struct C {
592       A &FooRef;
593       A *FooPtr;
594       B &BazRef;
595       B *BazPtr;
596     };
597 
598     struct A {
599       C *Bar;
600     };
601 
602     A *getA();
603 
604     void target() {
605       A *Foo = getA();
606       (void)Foo->Bar->FooRef;
607       (void)Foo->Bar->FooPtr;
608       (void)Foo->Bar->BazRef;
609       (void)Foo->Bar->BazPtr;
610       // [[p]]
611     }
612   )";
613   runDataflow(
614       Code,
615       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
616          ASTContext &ASTCtx) {
617         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
618         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
619 
620         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
621         ASSERT_THAT(FooDecl, NotNull());
622 
623         ASSERT_TRUE(FooDecl->getType()->isPointerType());
624         ASSERT_TRUE(FooDecl->getType()
625                         ->getAs<PointerType>()
626                         ->getPointeeType()
627                         ->isStructureType());
628         const auto FooFields = FooDecl->getType()
629                                    ->getAs<PointerType>()
630                                    ->getPointeeType()
631                                    ->getAsRecordDecl()
632                                    ->fields();
633 
634         FieldDecl *BarDecl = nullptr;
635         for (FieldDecl *Field : FooFields) {
636           if (Field->getNameAsString() == "Bar") {
637             BarDecl = Field;
638           } else {
639             FAIL() << "Unexpected field: " << Field->getNameAsString();
640           }
641         }
642         ASSERT_THAT(BarDecl, NotNull());
643 
644         ASSERT_TRUE(BarDecl->getType()->isPointerType());
645         ASSERT_TRUE(BarDecl->getType()
646                         ->getAs<PointerType>()
647                         ->getPointeeType()
648                         ->isStructureType());
649         const auto BarFields = BarDecl->getType()
650                                    ->getAs<PointerType>()
651                                    ->getPointeeType()
652                                    ->getAsRecordDecl()
653                                    ->fields();
654 
655         FieldDecl *FooRefDecl = nullptr;
656         FieldDecl *FooPtrDecl = nullptr;
657         FieldDecl *BazRefDecl = nullptr;
658         FieldDecl *BazPtrDecl = nullptr;
659         for (FieldDecl *Field : BarFields) {
660           if (Field->getNameAsString() == "FooRef") {
661             FooRefDecl = Field;
662           } else if (Field->getNameAsString() == "FooPtr") {
663             FooPtrDecl = Field;
664           } else if (Field->getNameAsString() == "BazRef") {
665             BazRefDecl = Field;
666           } else if (Field->getNameAsString() == "BazPtr") {
667             BazPtrDecl = Field;
668           } else {
669             FAIL() << "Unexpected field: " << Field->getNameAsString();
670           }
671         }
672         ASSERT_THAT(FooRefDecl, NotNull());
673         ASSERT_THAT(FooPtrDecl, NotNull());
674         ASSERT_THAT(BazRefDecl, NotNull());
675         ASSERT_THAT(BazPtrDecl, NotNull());
676 
677         const auto &FooLoc =
678             *cast<ScalarStorageLocation>(Env.getStorageLocation(*FooDecl));
679         const auto &FooVal = *cast<PointerValue>(Env.getValue(FooLoc));
680         const auto &FooPointeeLoc =
681             cast<RecordStorageLocation>(FooVal.getPointeeLoc());
682 
683         const auto &BarVal =
684             *cast<PointerValue>(getFieldValue(&FooPointeeLoc, *BarDecl, Env));
685         const auto &BarPointeeLoc =
686             cast<RecordStorageLocation>(BarVal.getPointeeLoc());
687 
688         EXPECT_THAT(getFieldValue(&BarPointeeLoc, *FooRefDecl, Env), NotNull());
689 
690         const auto &FooPtrVal = *cast<PointerValue>(
691             getFieldValue(&BarPointeeLoc, *FooPtrDecl, Env));
692         const auto &FooPtrPointeeLoc =
693             cast<RecordStorageLocation>(FooPtrVal.getPointeeLoc());
694         EXPECT_THAT(Env.getValue(FooPtrPointeeLoc), IsNull());
695 
696         EXPECT_THAT(getFieldValue(&BarPointeeLoc, *BazRefDecl, Env), NotNull());
697 
698         const auto &BazPtrVal = *cast<PointerValue>(
699             getFieldValue(&BarPointeeLoc, *BazPtrDecl, Env));
700         const StorageLocation &BazPtrPointeeLoc = BazPtrVal.getPointeeLoc();
701         EXPECT_THAT(Env.getValue(BazPtrPointeeLoc), NotNull());
702       });
703 }
704 
705 TEST(TransferTest, DirectlySelfReferentialReference) {
706   std::string Code = R"(
707     struct target {
708       target() {
709         (void)0;
710         // [[p]]
711       }
712       target &self = *this;
713     };
714   )";
715   runDataflow(
716       Code,
717       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
718          ASTContext &ASTCtx) {
719         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
720         const ValueDecl *SelfDecl = findValueDecl(ASTCtx, "self");
721 
722         auto *ThisLoc = Env.getThisPointeeStorageLocation();
723         ASSERT_EQ(ThisLoc->getChild(*SelfDecl), ThisLoc);
724       });
725 }
726 
727 TEST(TransferTest, MultipleVarsDecl) {
728   std::string Code = R"(
729     void target() {
730       int Foo, Bar;
731       (void)0;
732       // [[p]]
733     }
734   )";
735   runDataflow(
736       Code,
737       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
738          ASTContext &ASTCtx) {
739         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
740         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
741 
742         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
743         ASSERT_THAT(FooDecl, NotNull());
744 
745         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
746         ASSERT_THAT(BarDecl, NotNull());
747 
748         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
749         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
750 
751         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
752         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
753 
754         const Value *FooVal = Env.getValue(*FooLoc);
755         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
756 
757         const Value *BarVal = Env.getValue(*BarLoc);
758         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
759       });
760 }
761 
762 TEST(TransferTest, JoinVarDecl) {
763   std::string Code = R"(
764     void target(bool B) {
765       int Foo;
766       // [[p1]]
767       if (B) {
768         int Bar;
769         // [[p2]]
770       } else {
771         int Baz;
772         // [[p3]]
773       }
774       (void)0;
775       // [[p4]]
776     }
777   )";
778   runDataflow(Code, [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>>
779                            &Results,
780                        ASTContext &ASTCtx) {
781     ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2", "p3", "p4"));
782 
783     const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
784     ASSERT_THAT(FooDecl, NotNull());
785 
786     const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
787     ASSERT_THAT(BarDecl, NotNull());
788 
789     const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
790     ASSERT_THAT(BazDecl, NotNull());
791 
792     const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
793 
794     const StorageLocation *FooLoc = Env1.getStorageLocation(*FooDecl);
795     EXPECT_THAT(FooLoc, NotNull());
796     EXPECT_THAT(Env1.getStorageLocation(*BarDecl), IsNull());
797     EXPECT_THAT(Env1.getStorageLocation(*BazDecl), IsNull());
798 
799     const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
800     EXPECT_EQ(Env2.getStorageLocation(*FooDecl), FooLoc);
801     EXPECT_THAT(Env2.getStorageLocation(*BarDecl), NotNull());
802     EXPECT_THAT(Env2.getStorageLocation(*BazDecl), IsNull());
803 
804     const Environment &Env3 = getEnvironmentAtAnnotation(Results, "p3");
805     EXPECT_EQ(Env3.getStorageLocation(*FooDecl), FooLoc);
806     EXPECT_THAT(Env3.getStorageLocation(*BarDecl), IsNull());
807     EXPECT_THAT(Env3.getStorageLocation(*BazDecl), NotNull());
808 
809     const Environment &Env4 = getEnvironmentAtAnnotation(Results, "p4");
810     EXPECT_EQ(Env4.getStorageLocation(*FooDecl), FooLoc);
811     EXPECT_THAT(Env4.getStorageLocation(*BarDecl), IsNull());
812     EXPECT_THAT(Env4.getStorageLocation(*BazDecl), IsNull());
813   });
814 }
815 
816 TEST(TransferTest, BinaryOperatorAssign) {
817   std::string Code = R"(
818     void target() {
819       int Foo;
820       int Bar;
821       (Bar) = (Foo);
822       // [[p]]
823     }
824   )";
825   runDataflow(
826       Code,
827       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
828          ASTContext &ASTCtx) {
829         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
830         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
831 
832         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
833         ASSERT_THAT(FooDecl, NotNull());
834 
835         const Value *FooVal = Env.getValue(*FooDecl);
836         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
837 
838         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
839         ASSERT_THAT(BarDecl, NotNull());
840 
841         EXPECT_EQ(Env.getValue(*BarDecl), FooVal);
842       });
843 }
844 
845 TEST(TransferTest, BinaryOperatorAssignIntegerLiteral) {
846   std::string Code = R"(
847     void target() {
848       int Foo = 1;
849       // [[before]]
850       Foo = 2;
851       // [[after]]
852     }
853   )";
854   runDataflow(
855       Code,
856       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
857          ASTContext &ASTCtx) {
858         const Environment &Before =
859             getEnvironmentAtAnnotation(Results, "before");
860         const Environment &After = getEnvironmentAtAnnotation(Results, "after");
861 
862         const auto &ValBefore =
863             getValueForDecl<IntegerValue>(ASTCtx, Before, "Foo");
864         const auto &ValAfter =
865             getValueForDecl<IntegerValue>(ASTCtx, After, "Foo");
866         EXPECT_NE(&ValBefore, &ValAfter);
867       });
868 }
869 
870 TEST(TransferTest, VarDeclInitAssign) {
871   std::string Code = R"(
872     void target() {
873       int Foo;
874       int Bar = Foo;
875       // [[p]]
876     }
877   )";
878   runDataflow(
879       Code,
880       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
881          ASTContext &ASTCtx) {
882         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
883         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
884 
885         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
886         ASSERT_THAT(FooDecl, NotNull());
887 
888         const Value *FooVal = Env.getValue(*FooDecl);
889         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
890 
891         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
892         ASSERT_THAT(BarDecl, NotNull());
893 
894         EXPECT_EQ(Env.getValue(*BarDecl), FooVal);
895       });
896 }
897 
898 TEST(TransferTest, VarDeclInitAssignChained) {
899   std::string Code = R"(
900     void target() {
901       int Foo;
902       int Bar;
903       int Baz = (Bar = Foo);
904       // [[p]]
905     }
906   )";
907   runDataflow(
908       Code,
909       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
910          ASTContext &ASTCtx) {
911         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
912         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
913 
914         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
915         ASSERT_THAT(FooDecl, NotNull());
916 
917         const Value *FooVal = Env.getValue(*FooDecl);
918         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
919 
920         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
921         ASSERT_THAT(BarDecl, NotNull());
922 
923         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
924         ASSERT_THAT(BazDecl, NotNull());
925 
926         EXPECT_EQ(Env.getValue(*BarDecl), FooVal);
927         EXPECT_EQ(Env.getValue(*BazDecl), FooVal);
928       });
929 }
930 
931 TEST(TransferTest, VarDeclInitAssignPtrDeref) {
932   std::string Code = R"(
933     void target() {
934       int Foo;
935       int *Bar;
936       *(Bar) = Foo;
937       int Baz = *(Bar);
938       // [[p]]
939     }
940   )";
941   runDataflow(
942       Code,
943       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
944          ASTContext &ASTCtx) {
945         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
946         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
947 
948         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
949         ASSERT_THAT(FooDecl, NotNull());
950 
951         const Value *FooVal = Env.getValue(*FooDecl);
952         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
953 
954         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
955         ASSERT_THAT(BarDecl, NotNull());
956 
957         const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl));
958         EXPECT_EQ(Env.getValue(BarVal->getPointeeLoc()), FooVal);
959 
960         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
961         ASSERT_THAT(BazDecl, NotNull());
962 
963         EXPECT_EQ(Env.getValue(*BazDecl), FooVal);
964       });
965 }
966 
967 TEST(TransferTest, AssignToAndFromReference) {
968   std::string Code = R"(
969     void target() {
970       int Foo;
971       int Bar;
972       int &Baz = Foo;
973       // [[p1]]
974       Baz = Bar;
975       int Qux = Baz;
976       int &Quux = Baz;
977       // [[p2]]
978     }
979   )";
980   runDataflow(
981       Code,
982       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
983          ASTContext &ASTCtx) {
984         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
985         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
986         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
987 
988         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
989         ASSERT_THAT(FooDecl, NotNull());
990 
991         const Value *FooVal = Env1.getValue(*FooDecl);
992         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
993 
994         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
995         ASSERT_THAT(BarDecl, NotNull());
996 
997         const Value *BarVal = Env1.getValue(*BarDecl);
998         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
999 
1000         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
1001         ASSERT_THAT(BazDecl, NotNull());
1002 
1003         EXPECT_EQ(Env1.getValue(*BazDecl), FooVal);
1004 
1005         EXPECT_EQ(Env2.getValue(*BazDecl), BarVal);
1006         EXPECT_EQ(Env2.getValue(*FooDecl), BarVal);
1007 
1008         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
1009         ASSERT_THAT(QuxDecl, NotNull());
1010         EXPECT_EQ(Env2.getValue(*QuxDecl), BarVal);
1011 
1012         const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux");
1013         ASSERT_THAT(QuuxDecl, NotNull());
1014         EXPECT_EQ(Env2.getValue(*QuuxDecl), BarVal);
1015       });
1016 }
1017 
1018 TEST(TransferTest, MultipleParamDecls) {
1019   std::string Code = R"(
1020     void target(int Foo, int Bar) {
1021       (void)0;
1022       // [[p]]
1023     }
1024   )";
1025   runDataflow(
1026       Code,
1027       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1028          ASTContext &ASTCtx) {
1029         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1030         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1031 
1032         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1033         ASSERT_THAT(FooDecl, NotNull());
1034 
1035         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
1036         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
1037 
1038         const Value *FooVal = Env.getValue(*FooLoc);
1039         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
1040 
1041         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1042         ASSERT_THAT(BarDecl, NotNull());
1043 
1044         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
1045         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
1046 
1047         const Value *BarVal = Env.getValue(*BarLoc);
1048         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
1049       });
1050 }
1051 
1052 TEST(TransferTest, StructParamDecl) {
1053   std::string Code = R"(
1054     struct A {
1055       int Bar;
1056     };
1057 
1058     void target(A Foo) {
1059       (void)Foo.Bar;
1060       // [[p]]
1061     }
1062   )";
1063   runDataflow(
1064       Code,
1065       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1066          ASTContext &ASTCtx) {
1067         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1068         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1069 
1070         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1071         ASSERT_THAT(FooDecl, NotNull());
1072 
1073         ASSERT_TRUE(FooDecl->getType()->isStructureType());
1074         auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields();
1075 
1076         FieldDecl *BarDecl = nullptr;
1077         for (FieldDecl *Field : FooFields) {
1078           if (Field->getNameAsString() == "Bar") {
1079             BarDecl = Field;
1080           } else {
1081             FAIL() << "Unexpected field: " << Field->getNameAsString();
1082           }
1083         }
1084         ASSERT_THAT(BarDecl, NotNull());
1085 
1086         const auto *FooLoc =
1087             cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
1088         EXPECT_TRUE(isa<IntegerValue>(getFieldValue(FooLoc, *BarDecl, Env)));
1089       });
1090 }
1091 
1092 TEST(TransferTest, ReferenceParamDecl) {
1093   std::string Code = R"(
1094     struct A {};
1095 
1096     void target(A &Foo) {
1097       (void)0;
1098       // [[p]]
1099     }
1100   )";
1101   runDataflow(
1102       Code,
1103       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1104          ASTContext &ASTCtx) {
1105         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1106         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1107 
1108         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1109         ASSERT_THAT(FooDecl, NotNull());
1110 
1111         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
1112         ASSERT_TRUE(isa_and_nonnull<RecordStorageLocation>(FooLoc));
1113 
1114         const Value *FooReferentVal = Env.getValue(*FooLoc);
1115         EXPECT_TRUE(isa_and_nonnull<RecordValue>(FooReferentVal));
1116       });
1117 }
1118 
1119 TEST(TransferTest, PointerParamDecl) {
1120   std::string Code = R"(
1121     struct A {};
1122 
1123     void target(A *Foo) {
1124       (void)0;
1125       // [[p]]
1126     }
1127   )";
1128   runDataflow(
1129       Code,
1130       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1131          ASTContext &ASTCtx) {
1132         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1133         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1134 
1135         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1136         ASSERT_THAT(FooDecl, NotNull());
1137 
1138         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
1139         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
1140 
1141         const PointerValue *FooVal = cast<PointerValue>(Env.getValue(*FooLoc));
1142         const StorageLocation &FooPointeeLoc = FooVal->getPointeeLoc();
1143         EXPECT_TRUE(isa<RecordStorageLocation>(&FooPointeeLoc));
1144 
1145         const Value *FooPointeeVal = Env.getValue(FooPointeeLoc);
1146         EXPECT_TRUE(isa_and_nonnull<RecordValue>(FooPointeeVal));
1147       });
1148 }
1149 
1150 TEST(TransferTest, StructMember) {
1151   std::string Code = R"(
1152     struct A {
1153       int Bar;
1154     };
1155 
1156     void target(A Foo) {
1157       int Baz = Foo.Bar;
1158       // [[p]]
1159     }
1160   )";
1161   runDataflow(
1162       Code,
1163       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1164          ASTContext &ASTCtx) {
1165         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1166         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1167 
1168         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1169         ASSERT_THAT(FooDecl, NotNull());
1170 
1171         ASSERT_TRUE(FooDecl->getType()->isStructureType());
1172         auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields();
1173 
1174         FieldDecl *BarDecl = nullptr;
1175         for (FieldDecl *Field : FooFields) {
1176           if (Field->getNameAsString() == "Bar") {
1177             BarDecl = Field;
1178           } else {
1179             FAIL() << "Unexpected field: " << Field->getNameAsString();
1180           }
1181         }
1182         ASSERT_THAT(BarDecl, NotNull());
1183 
1184         const auto *FooLoc =
1185             cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
1186         const auto *BarVal =
1187             cast<IntegerValue>(getFieldValue(FooLoc, *BarDecl, Env));
1188 
1189         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
1190         ASSERT_THAT(BazDecl, NotNull());
1191 
1192         EXPECT_EQ(Env.getValue(*BazDecl), BarVal);
1193       });
1194 }
1195 
1196 TEST(TransferTest, StructMemberEnum) {
1197   std::string Code = R"(
1198     struct A {
1199       int Bar;
1200       enum E { ONE, TWO };
1201     };
1202 
1203     void target(A Foo) {
1204       A::E Baz = Foo.ONE;
1205       // [[p]]
1206     }
1207   )";
1208   // Minimal expectations -- we're just testing that it doesn't crash, since
1209   // enums aren't interpreted.
1210   runDataflow(
1211       Code,
1212       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1213          ASTContext &ASTCtx) {
1214         EXPECT_THAT(Results.keys(), UnorderedElementsAre("p"));
1215       });
1216 }
1217 
1218 TEST(TransferTest, DerivedBaseMemberClass) {
1219   std::string Code = R"(
1220     class A {
1221       int ADefault;
1222     protected:
1223       int AProtected;
1224     private:
1225       int APrivate;
1226     public:
1227       int APublic;
1228 
1229     private:
1230       friend void target();
1231     };
1232 
1233     class B : public A {
1234       int BDefault;
1235     protected:
1236       int BProtected;
1237     private:
1238       int BPrivate;
1239 
1240     private:
1241       friend void target();
1242     };
1243 
1244     void target() {
1245       B Foo;
1246       (void)Foo.ADefault;
1247       (void)Foo.AProtected;
1248       (void)Foo.APrivate;
1249       (void)Foo.APublic;
1250       (void)Foo.BDefault;
1251       (void)Foo.BProtected;
1252       (void)Foo.BPrivate;
1253       // [[p]]
1254     }
1255   )";
1256   runDataflow(
1257       Code,
1258       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1259          ASTContext &ASTCtx) {
1260         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1261         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1262 
1263         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1264         ASSERT_THAT(FooDecl, NotNull());
1265         ASSERT_TRUE(FooDecl->getType()->isRecordType());
1266 
1267         // Derived-class fields.
1268         const FieldDecl *BDefaultDecl = nullptr;
1269         const FieldDecl *BProtectedDecl = nullptr;
1270         const FieldDecl *BPrivateDecl = nullptr;
1271         for (const FieldDecl *Field :
1272              FooDecl->getType()->getAsRecordDecl()->fields()) {
1273           if (Field->getNameAsString() == "BDefault") {
1274             BDefaultDecl = Field;
1275           } else if (Field->getNameAsString() == "BProtected") {
1276             BProtectedDecl = Field;
1277           } else if (Field->getNameAsString() == "BPrivate") {
1278             BPrivateDecl = Field;
1279           } else {
1280             FAIL() << "Unexpected field: " << Field->getNameAsString();
1281           }
1282         }
1283         ASSERT_THAT(BDefaultDecl, NotNull());
1284         ASSERT_THAT(BProtectedDecl, NotNull());
1285         ASSERT_THAT(BPrivateDecl, NotNull());
1286 
1287         // Base-class fields.
1288         const FieldDecl *ADefaultDecl = nullptr;
1289         const FieldDecl *APrivateDecl = nullptr;
1290         const FieldDecl *AProtectedDecl = nullptr;
1291         const FieldDecl *APublicDecl = nullptr;
1292         for (const clang::CXXBaseSpecifier &Base :
1293              FooDecl->getType()->getAsCXXRecordDecl()->bases()) {
1294           QualType BaseType = Base.getType();
1295           ASSERT_TRUE(BaseType->isRecordType());
1296           for (const FieldDecl *Field : BaseType->getAsRecordDecl()->fields()) {
1297             if (Field->getNameAsString() == "ADefault") {
1298               ADefaultDecl = Field;
1299             } else if (Field->getNameAsString() == "AProtected") {
1300               AProtectedDecl = Field;
1301             } else if (Field->getNameAsString() == "APrivate") {
1302               APrivateDecl = Field;
1303             } else if (Field->getNameAsString() == "APublic") {
1304               APublicDecl = Field;
1305             } else {
1306               FAIL() << "Unexpected field: " << Field->getNameAsString();
1307             }
1308           }
1309         }
1310         ASSERT_THAT(ADefaultDecl, NotNull());
1311         ASSERT_THAT(AProtectedDecl, NotNull());
1312         ASSERT_THAT(APrivateDecl, NotNull());
1313         ASSERT_THAT(APublicDecl, NotNull());
1314 
1315         ASSERT_TRUE(
1316             isa<RecordStorageLocation>(Env.getStorageLocation(*FooDecl)));
1317       });
1318 }
1319 
1320 static void derivedBaseMemberExpectations(
1321     const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1322     ASTContext &ASTCtx) {
1323   ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1324   const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1325 
1326   const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1327   ASSERT_THAT(FooDecl, NotNull());
1328 
1329   ASSERT_TRUE(FooDecl->getType()->isRecordType());
1330   const FieldDecl *BarDecl = nullptr;
1331   for (const clang::CXXBaseSpecifier &Base :
1332        FooDecl->getType()->getAsCXXRecordDecl()->bases()) {
1333     QualType BaseType = Base.getType();
1334     ASSERT_TRUE(BaseType->isStructureType());
1335 
1336     for (const FieldDecl *Field : BaseType->getAsRecordDecl()->fields()) {
1337       if (Field->getNameAsString() == "Bar") {
1338         BarDecl = Field;
1339       } else {
1340         FAIL() << "Unexpected field: " << Field->getNameAsString();
1341       }
1342     }
1343   }
1344   ASSERT_THAT(BarDecl, NotNull());
1345 
1346   const auto &FooLoc =
1347       *cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
1348   const auto &FooVal = *cast<RecordValue>(Env.getValue(FooLoc));
1349   EXPECT_EQ(&FooVal.getLoc(), &FooLoc);
1350 }
1351 
1352 TEST(TransferTest, DerivedBaseMemberStructDefault) {
1353   std::string Code = R"(
1354     struct A {
1355       int Bar;
1356     };
1357     struct B : public A {
1358     };
1359 
1360     void target() {
1361       B Foo;
1362       (void)Foo.Bar;
1363       // [[p]]
1364     }
1365   )";
1366   runDataflow(Code, derivedBaseMemberExpectations);
1367 }
1368 
1369 TEST(TransferTest, DerivedBaseMemberPrivateFriend) {
1370   // Include an access to `Foo.Bar` to verify the analysis doesn't crash on that
1371   // access.
1372   std::string Code = R"(
1373     struct A {
1374     private:
1375       friend void target();
1376       int Bar;
1377     };
1378     struct B : public A {
1379     };
1380 
1381     void target() {
1382       B Foo;
1383       (void)Foo.Bar;
1384       // [[p]]
1385     }
1386   )";
1387   runDataflow(Code, derivedBaseMemberExpectations);
1388 }
1389 
1390 TEST(TransferTest, ClassMember) {
1391   std::string Code = R"(
1392     class A {
1393     public:
1394       int Bar;
1395     };
1396 
1397     void target(A Foo) {
1398       int Baz = Foo.Bar;
1399       // [[p]]
1400     }
1401   )";
1402   runDataflow(
1403       Code,
1404       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1405          ASTContext &ASTCtx) {
1406         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1407         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1408 
1409         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1410         ASSERT_THAT(FooDecl, NotNull());
1411 
1412         ASSERT_TRUE(FooDecl->getType()->isClassType());
1413         auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields();
1414 
1415         FieldDecl *BarDecl = nullptr;
1416         for (FieldDecl *Field : FooFields) {
1417           if (Field->getNameAsString() == "Bar") {
1418             BarDecl = Field;
1419           } else {
1420             FAIL() << "Unexpected field: " << Field->getNameAsString();
1421           }
1422         }
1423         ASSERT_THAT(BarDecl, NotNull());
1424 
1425         const auto *FooLoc =
1426             cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
1427         const auto *BarVal =
1428             cast<IntegerValue>(getFieldValue(FooLoc, *BarDecl, Env));
1429 
1430         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
1431         ASSERT_THAT(BazDecl, NotNull());
1432 
1433         EXPECT_EQ(Env.getValue(*BazDecl), BarVal);
1434       });
1435 }
1436 
1437 TEST(TransferTest, BaseClassInitializer) {
1438   using ast_matchers::cxxConstructorDecl;
1439   using ast_matchers::hasName;
1440   using ast_matchers::ofClass;
1441 
1442   std::string Code = R"(
1443     class A {
1444     public:
1445       A(int I) : Bar(I) {}
1446       int Bar;
1447     };
1448 
1449     class B : public A {
1450     public:
1451       B(int I) : A(I) {
1452         (void)0;
1453         // [[p]]
1454       }
1455     };
1456   )";
1457   ASSERT_THAT_ERROR(
1458       checkDataflow<NoopAnalysis>(
1459           AnalysisInputs<NoopAnalysis>(
1460               Code, cxxConstructorDecl(ofClass(hasName("B"))),
1461               [](ASTContext &C, Environment &) { return NoopAnalysis(C); })
1462               .withASTBuildArgs(
1463                   {"-fsyntax-only", "-fno-delayed-template-parsing",
1464                    "-std=" + std::string(LangStandard::getLangStandardForKind(
1465                                              LangStandard::lang_cxx17)
1466                                              .getName())}),
1467           /*VerifyResults=*/
1468           [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1469              const AnalysisOutputs &) {
1470             // Regression test to verify that base-class initializers do not
1471             // trigger an assertion. If we add support for such initializers in
1472             // the future, we can expand this test to check more specific
1473             // properties.
1474             EXPECT_THAT(Results.keys(), UnorderedElementsAre("p"));
1475           }),
1476       llvm::Succeeded());
1477 }
1478 
1479 TEST(TransferTest, StructModeledFieldsWithAccessor) {
1480   std::string Code = R"(
1481     class S {
1482       int *Ptr;
1483       int *PtrNonConst;
1484       int Int;
1485       int IntWithInc;
1486       int IntNotAccessed;
1487       int IntRef;
1488     public:
1489       int *getPtr() const { return Ptr; }
1490       int *getPtrNonConst() { return PtrNonConst; }
1491       int getInt(int i) const { return Int; }
1492       int getWithInc(int i) { IntWithInc += i; return IntWithInc; }
1493       int getIntNotAccessed() const { return IntNotAccessed; }
1494       int getIntNoDefinition() const;
1495       int &getIntRef() { return IntRef; }
1496       void returnVoid() const { return; }
1497     };
1498 
1499     void target() {
1500       S s;
1501       int *p1 = s.getPtr();
1502       int *p2 = s.getPtrNonConst();
1503       int i1 = s.getInt(1);
1504       int i2 = s.getWithInc(1);
1505       int i3 = s.getIntNoDefinition();
1506       int &iref = s.getIntRef();
1507 
1508       // Regression test: Don't crash on an indirect call (which doesn't have
1509       // an associated `CXXMethodDecl`).
1510       auto ptr_to_member_fn = &S::getPtr;
1511       p1 = (s.*ptr_to_member_fn)();
1512 
1513       // Regression test: Don't crash on a return statement without a value.
1514       s.returnVoid();
1515       // [[p]]
1516     }
1517   )";
1518   runDataflow(
1519       Code,
1520       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1521          ASTContext &ASTCtx) {
1522         const Environment &Env =
1523               getEnvironmentAtAnnotation(Results, "p");
1524         auto &SLoc = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "s");
1525         std::vector<const ValueDecl*> Fields;
1526         for (auto [Field, _] : SLoc.children())
1527           Fields.push_back(Field);
1528         // Only the fields that have simple accessor methods (that have a
1529         // single statement body that returns the member variable) should be
1530         // modeled.
1531         ASSERT_THAT(Fields, UnorderedElementsAre(
1532             findValueDecl(ASTCtx, "Ptr"), findValueDecl(ASTCtx, "PtrNonConst"),
1533             findValueDecl(ASTCtx, "Int"), findValueDecl(ASTCtx, "IntRef")));
1534       });
1535 }
1536 
1537 TEST(TransferTest, StructModeledFieldsWithComplicatedInheritance) {
1538   std::string Code = R"(
1539     struct Base1 {
1540       int base1_1;
1541       int base1_2;
1542     };
1543     struct Intermediate : Base1 {
1544       int intermediate_1;
1545       int intermediate_2;
1546     };
1547     struct Base2 {
1548       int base2_1;
1549       int base2_2;
1550     };
1551     struct MostDerived : public Intermediate, Base2 {
1552       int most_derived_1;
1553       int most_derived_2;
1554     };
1555 
1556     void target() {
1557       MostDerived MD;
1558       MD.base1_2 = 1;
1559       MD.intermediate_2 = 1;
1560       MD.base2_2 = 1;
1561       MD.most_derived_2 = 1;
1562       // [[p]]
1563     }
1564   )";
1565   runDataflow(
1566       Code,
1567       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1568          ASTContext &ASTCtx) {
1569         const Environment &Env =
1570               getEnvironmentAtAnnotation(Results, "p");
1571 
1572         // Only the accessed fields should exist in the model.
1573         auto &MDLoc = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "MD");
1574         std::vector<const ValueDecl*> Fields;
1575         for (auto [Field, _] : MDLoc.children())
1576           Fields.push_back(Field);
1577         ASSERT_THAT(Fields, UnorderedElementsAre(
1578             findValueDecl(ASTCtx, "base1_2"),
1579             findValueDecl(ASTCtx, "intermediate_2"),
1580             findValueDecl(ASTCtx, "base2_2"),
1581             findValueDecl(ASTCtx, "most_derived_2")));
1582       });
1583 }
1584 
1585 TEST(TransferTest, StructInitializerListWithComplicatedInheritance) {
1586   std::string Code = R"(
1587     struct Base1 {
1588       int base1;
1589     };
1590     struct Intermediate : Base1 {
1591       int intermediate;
1592     };
1593     struct Base2 {
1594       int base2;
1595     };
1596     struct MostDerived : public Intermediate, Base2 {
1597       int most_derived;
1598     };
1599 
1600     void target() {
1601       MostDerived MD = {};
1602       // [[p]]
1603     }
1604   )";
1605   runDataflow(
1606       Code,
1607       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1608          ASTContext &ASTCtx) {
1609         const Environment &Env =
1610               getEnvironmentAtAnnotation(Results, "p");
1611 
1612         // When a struct is initialized with a initializer list, all the
1613         // fields are considered "accessed", and therefore do exist.
1614         auto &MD = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "MD");
1615         ASSERT_THAT(cast<IntegerValue>(
1616             getFieldValue(&MD, *findValueDecl(ASTCtx, "base1"), Env)),
1617             NotNull());
1618         ASSERT_THAT(cast<IntegerValue>(
1619             getFieldValue(&MD, *findValueDecl(ASTCtx, "intermediate"), Env)),
1620             NotNull());
1621         ASSERT_THAT(cast<IntegerValue>(
1622             getFieldValue(&MD, *findValueDecl(ASTCtx, "base2"), Env)),
1623             NotNull());
1624         ASSERT_THAT(cast<IntegerValue>(
1625             getFieldValue(&MD, *findValueDecl(ASTCtx, "most_derived"), Env)),
1626             NotNull());
1627       });
1628 }
1629 
1630 TEST(TransferTest, ReferenceMember) {
1631   std::string Code = R"(
1632     struct A {
1633       int &Bar;
1634     };
1635 
1636     void target(A Foo) {
1637       int Baz = Foo.Bar;
1638       // [[p]]
1639     }
1640   )";
1641   runDataflow(
1642       Code,
1643       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1644          ASTContext &ASTCtx) {
1645         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1646         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1647 
1648         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1649         ASSERT_THAT(FooDecl, NotNull());
1650 
1651         ASSERT_TRUE(FooDecl->getType()->isStructureType());
1652         auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields();
1653 
1654         FieldDecl *BarDecl = nullptr;
1655         for (FieldDecl *Field : FooFields) {
1656           if (Field->getNameAsString() == "Bar") {
1657             BarDecl = Field;
1658           } else {
1659             FAIL() << "Unexpected field: " << Field->getNameAsString();
1660           }
1661         }
1662         ASSERT_THAT(BarDecl, NotNull());
1663 
1664         const auto *FooLoc =
1665             cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
1666         const auto *BarReferentVal =
1667             cast<IntegerValue>(getFieldValue(FooLoc, *BarDecl, Env));
1668 
1669         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
1670         ASSERT_THAT(BazDecl, NotNull());
1671 
1672         EXPECT_EQ(Env.getValue(*BazDecl), BarReferentVal);
1673       });
1674 }
1675 
1676 TEST(TransferTest, StructThisMember) {
1677   std::string Code = R"(
1678     struct A {
1679       int Bar;
1680 
1681       struct B {
1682         int Baz;
1683       };
1684 
1685       B Qux;
1686 
1687       void target() {
1688         int Foo = Bar;
1689         int Quux = Qux.Baz;
1690         // [[p]]
1691       }
1692     };
1693   )";
1694   runDataflow(
1695       Code,
1696       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1697          ASTContext &ASTCtx) {
1698         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1699         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1700 
1701         const auto *ThisLoc = Env.getThisPointeeStorageLocation();
1702         ASSERT_THAT(ThisLoc, NotNull());
1703 
1704         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1705         ASSERT_THAT(BarDecl, NotNull());
1706 
1707         const auto *BarLoc =
1708             cast<ScalarStorageLocation>(ThisLoc->getChild(*BarDecl));
1709         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
1710 
1711         const Value *BarVal = Env.getValue(*BarLoc);
1712         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
1713 
1714         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1715         ASSERT_THAT(FooDecl, NotNull());
1716         EXPECT_EQ(Env.getValue(*FooDecl), BarVal);
1717 
1718         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
1719         ASSERT_THAT(QuxDecl, NotNull());
1720 
1721         ASSERT_TRUE(QuxDecl->getType()->isStructureType());
1722         auto QuxFields = QuxDecl->getType()->getAsRecordDecl()->fields();
1723 
1724         FieldDecl *BazDecl = nullptr;
1725         for (FieldDecl *Field : QuxFields) {
1726           if (Field->getNameAsString() == "Baz") {
1727             BazDecl = Field;
1728           } else {
1729             FAIL() << "Unexpected field: " << Field->getNameAsString();
1730           }
1731         }
1732         ASSERT_THAT(BazDecl, NotNull());
1733 
1734         const auto *QuxLoc =
1735             cast<RecordStorageLocation>(ThisLoc->getChild(*QuxDecl));
1736         EXPECT_THAT(dyn_cast<RecordValue>(Env.getValue(*QuxLoc)), NotNull());
1737 
1738         const auto *BazVal =
1739             cast<IntegerValue>(getFieldValue(QuxLoc, *BazDecl, Env));
1740 
1741         const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux");
1742         ASSERT_THAT(QuuxDecl, NotNull());
1743         EXPECT_EQ(Env.getValue(*QuuxDecl), BazVal);
1744       });
1745 }
1746 
1747 TEST(TransferTest, ClassThisMember) {
1748   std::string Code = R"(
1749     class A {
1750       int Bar;
1751 
1752       class B {
1753       public:
1754         int Baz;
1755       };
1756 
1757       B Qux;
1758 
1759       void target() {
1760         int Foo = Bar;
1761         int Quux = Qux.Baz;
1762         // [[p]]
1763       }
1764     };
1765   )";
1766   runDataflow(
1767       Code,
1768       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1769          ASTContext &ASTCtx) {
1770         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1771         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1772 
1773         const auto *ThisLoc = Env.getThisPointeeStorageLocation();
1774 
1775         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1776         ASSERT_THAT(BarDecl, NotNull());
1777 
1778         const auto *BarLoc =
1779             cast<ScalarStorageLocation>(ThisLoc->getChild(*BarDecl));
1780         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
1781 
1782         const Value *BarVal = Env.getValue(*BarLoc);
1783         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
1784 
1785         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1786         ASSERT_THAT(FooDecl, NotNull());
1787         EXPECT_EQ(Env.getValue(*FooDecl), BarVal);
1788 
1789         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
1790         ASSERT_THAT(QuxDecl, NotNull());
1791 
1792         ASSERT_TRUE(QuxDecl->getType()->isClassType());
1793         auto QuxFields = QuxDecl->getType()->getAsRecordDecl()->fields();
1794 
1795         FieldDecl *BazDecl = nullptr;
1796         for (FieldDecl *Field : QuxFields) {
1797           if (Field->getNameAsString() == "Baz") {
1798             BazDecl = Field;
1799           } else {
1800             FAIL() << "Unexpected field: " << Field->getNameAsString();
1801           }
1802         }
1803         ASSERT_THAT(BazDecl, NotNull());
1804 
1805         const auto *QuxLoc =
1806             cast<RecordStorageLocation>(ThisLoc->getChild(*QuxDecl));
1807         EXPECT_THAT(dyn_cast<RecordValue>(Env.getValue(*QuxLoc)), NotNull());
1808 
1809         const auto *BazVal =
1810             cast<IntegerValue>(getFieldValue(QuxLoc, *BazDecl, Env));
1811 
1812         const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux");
1813         ASSERT_THAT(QuuxDecl, NotNull());
1814         EXPECT_EQ(Env.getValue(*QuuxDecl), BazVal);
1815       });
1816 }
1817 
1818 TEST(TransferTest, UnionThisMember) {
1819   std::string Code = R"(
1820     union A {
1821       int Foo;
1822       int Bar;
1823 
1824       void target() {
1825         A a;
1826         // Mention the fields to ensure they're included in the analysis.
1827         (void)a.Foo;
1828         (void)a.Bar;
1829         // [[p]]
1830       }
1831     };
1832   )";
1833   runDataflow(
1834       Code,
1835       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1836          ASTContext &ASTCtx) {
1837         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1838         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1839 
1840         const auto *ThisLoc = Env.getThisPointeeStorageLocation();
1841         ASSERT_THAT(ThisLoc, NotNull());
1842 
1843         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1844         ASSERT_THAT(FooDecl, NotNull());
1845 
1846         const auto *FooLoc =
1847             cast<ScalarStorageLocation>(ThisLoc->getChild(*FooDecl));
1848         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
1849 
1850         const Value *FooVal = Env.getValue(*FooLoc);
1851         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
1852 
1853         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1854         ASSERT_THAT(BarDecl, NotNull());
1855 
1856         const auto *BarLoc =
1857             cast<ScalarStorageLocation>(ThisLoc->getChild(*BarDecl));
1858         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
1859 
1860         const Value *BarVal = Env.getValue(*BarLoc);
1861         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
1862       });
1863 }
1864 
1865 TEST(TransferTest, StructThisInLambda) {
1866   std::string ThisCaptureCode = R"(
1867     struct A {
1868       void frob() {
1869         [this]() {
1870           int Foo = Bar;
1871           // [[p1]]
1872         }();
1873       }
1874 
1875       int Bar;
1876     };
1877   )";
1878   runDataflow(
1879       ThisCaptureCode,
1880       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1881          ASTContext &ASTCtx) {
1882         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1"));
1883         const Environment &Env = getEnvironmentAtAnnotation(Results, "p1");
1884 
1885         const auto *ThisLoc = Env.getThisPointeeStorageLocation();
1886         ASSERT_THAT(ThisLoc, NotNull());
1887 
1888         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1889         ASSERT_THAT(BarDecl, NotNull());
1890 
1891         const auto *BarLoc =
1892             cast<ScalarStorageLocation>(ThisLoc->getChild(*BarDecl));
1893         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
1894 
1895         const Value *BarVal = Env.getValue(*BarLoc);
1896         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
1897 
1898         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1899         ASSERT_THAT(FooDecl, NotNull());
1900         EXPECT_EQ(Env.getValue(*FooDecl), BarVal);
1901       },
1902       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator()");
1903 
1904   std::string RefCaptureDefaultCode = R"(
1905     struct A {
1906       void frob() {
1907         [&]() {
1908           int Foo = Bar;
1909           // [[p2]]
1910         }();
1911       }
1912 
1913       int Bar;
1914     };
1915   )";
1916   runDataflow(
1917       RefCaptureDefaultCode,
1918       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1919          ASTContext &ASTCtx) {
1920         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p2"));
1921         const Environment &Env = getEnvironmentAtAnnotation(Results, "p2");
1922 
1923         const auto *ThisLoc = Env.getThisPointeeStorageLocation();
1924         ASSERT_THAT(ThisLoc, NotNull());
1925 
1926         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1927         ASSERT_THAT(BarDecl, NotNull());
1928 
1929         const auto *BarLoc =
1930             cast<ScalarStorageLocation>(ThisLoc->getChild(*BarDecl));
1931         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
1932 
1933         const Value *BarVal = Env.getValue(*BarLoc);
1934         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
1935 
1936         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1937         ASSERT_THAT(FooDecl, NotNull());
1938         EXPECT_EQ(Env.getValue(*FooDecl), BarVal);
1939       },
1940       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator()");
1941 
1942   std::string FreeFunctionLambdaCode = R"(
1943     void foo() {
1944       int Bar;
1945       [&]() {
1946         int Foo = Bar;
1947         // [[p3]]
1948       }();
1949     }
1950   )";
1951   runDataflow(
1952       FreeFunctionLambdaCode,
1953       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1954          ASTContext &ASTCtx) {
1955         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p3"));
1956         const Environment &Env = getEnvironmentAtAnnotation(Results, "p3");
1957 
1958         EXPECT_THAT(Env.getThisPointeeStorageLocation(), IsNull());
1959       },
1960       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator()");
1961 }
1962 
1963 TEST(TransferTest, ConstructorInitializer) {
1964   std::string Code = R"(
1965     struct target {
1966       int Bar;
1967 
1968       target(int Foo) : Bar(Foo) {
1969         int Qux = Bar;
1970         // [[p]]
1971       }
1972     };
1973   )";
1974   runDataflow(
1975       Code,
1976       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1977          ASTContext &ASTCtx) {
1978         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1979         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1980 
1981         const auto *ThisLoc = Env.getThisPointeeStorageLocation();
1982         ASSERT_THAT(ThisLoc, NotNull());
1983 
1984         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1985         ASSERT_THAT(FooDecl, NotNull());
1986 
1987         const auto *FooVal = cast<IntegerValue>(Env.getValue(*FooDecl));
1988 
1989         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
1990         ASSERT_THAT(QuxDecl, NotNull());
1991         EXPECT_EQ(Env.getValue(*QuxDecl), FooVal);
1992       });
1993 }
1994 
1995 TEST(TransferTest, DefaultInitializer) {
1996   std::string Code = R"(
1997     struct target {
1998       int Bar;
1999       int Baz = Bar;
2000 
2001       target(int Foo) : Bar(Foo) {
2002         int Qux = Baz;
2003         // [[p]]
2004       }
2005     };
2006   )";
2007   runDataflow(
2008       Code,
2009       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2010          ASTContext &ASTCtx) {
2011         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2012         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2013 
2014         const auto *ThisLoc = Env.getThisPointeeStorageLocation();
2015         ASSERT_THAT(ThisLoc, NotNull());
2016 
2017         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2018         ASSERT_THAT(FooDecl, NotNull());
2019 
2020         const auto *FooVal = cast<IntegerValue>(Env.getValue(*FooDecl));
2021 
2022         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
2023         ASSERT_THAT(QuxDecl, NotNull());
2024         EXPECT_EQ(Env.getValue(*QuxDecl), FooVal);
2025       });
2026 }
2027 
2028 TEST(TransferTest, DefaultInitializerReference) {
2029   std::string Code = R"(
2030     struct target {
2031       int &Bar;
2032       int &Baz = Bar;
2033 
2034       target(int &Foo) : Bar(Foo) {
2035         int &Qux = Baz;
2036         // [[p]]
2037       }
2038     };
2039   )";
2040   runDataflow(
2041       Code,
2042       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2043          ASTContext &ASTCtx) {
2044         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2045         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2046 
2047         const auto *ThisLoc = Env.getThisPointeeStorageLocation();
2048         ASSERT_THAT(ThisLoc, NotNull());
2049 
2050         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2051         ASSERT_THAT(FooDecl, NotNull());
2052 
2053         const auto *FooLoc = Env.getStorageLocation(*FooDecl);
2054 
2055         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
2056         ASSERT_THAT(QuxDecl, NotNull());
2057 
2058         const auto *QuxLoc = Env.getStorageLocation(*QuxDecl);
2059         EXPECT_EQ(QuxLoc, FooLoc);
2060       });
2061 }
2062 
2063 TEST(TransferTest, TemporaryObject) {
2064   std::string Code = R"(
2065     struct A {
2066       int Bar;
2067     };
2068 
2069     void target() {
2070       A Foo = A();
2071       (void)Foo.Bar;
2072       // [[p]]
2073     }
2074   )";
2075   runDataflow(
2076       Code,
2077       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2078          ASTContext &ASTCtx) {
2079         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2080         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2081 
2082         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2083         ASSERT_THAT(FooDecl, NotNull());
2084 
2085         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2086         ASSERT_THAT(BarDecl, NotNull());
2087 
2088         const auto *FooLoc =
2089             cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
2090         EXPECT_TRUE(isa<IntegerValue>(getFieldValue(FooLoc, *BarDecl, Env)));
2091       });
2092 }
2093 
2094 TEST(TransferTest, ElidableConstructor) {
2095   // This test is effectively the same as TransferTest.TemporaryObject, but
2096   // the code is compiled as C++14.
2097   std::string Code = R"(
2098     struct A {
2099       int Bar;
2100     };
2101 
2102     void target() {
2103       A Foo = A();
2104       (void)Foo.Bar;
2105       // [[p]]
2106     }
2107   )";
2108   runDataflow(
2109       Code,
2110       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2111          ASTContext &ASTCtx) {
2112         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2113         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2114 
2115         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2116         ASSERT_THAT(FooDecl, NotNull());
2117 
2118         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2119         ASSERT_THAT(BarDecl, NotNull());
2120 
2121         const auto *FooLoc =
2122             cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
2123         EXPECT_TRUE(isa<IntegerValue>(getFieldValue(FooLoc, *BarDecl, Env)));
2124       },
2125       LangStandard::lang_cxx14);
2126 }
2127 
2128 TEST(TransferTest, AssignmentOperator) {
2129   std::string Code = R"(
2130     struct A {
2131       int Baz;
2132     };
2133 
2134     void target() {
2135       A Foo = { 1 };
2136       A Bar = { 2 };
2137       // [[p1]]
2138       Foo = Bar;
2139       // [[p2]]
2140       Foo.Baz = 3;
2141       // [[p3]]
2142     }
2143   )";
2144   runDataflow(
2145       Code,
2146       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2147          ASTContext &ASTCtx) {
2148         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2149         ASSERT_THAT(FooDecl, NotNull());
2150 
2151         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2152         ASSERT_THAT(BarDecl, NotNull());
2153 
2154         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2155         ASSERT_THAT(BazDecl, NotNull());
2156 
2157         // Before copy assignment.
2158         {
2159           const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
2160 
2161           const auto *FooLoc1 =
2162               cast<RecordStorageLocation>(Env1.getStorageLocation(*FooDecl));
2163           const auto *BarLoc1 =
2164               cast<RecordStorageLocation>(Env1.getStorageLocation(*BarDecl));
2165           EXPECT_FALSE(recordsEqual(*FooLoc1, *BarLoc1, Env1));
2166 
2167           const auto *FooBazVal1 =
2168               cast<IntegerValue>(getFieldValue(FooLoc1, *BazDecl, Env1));
2169           const auto *BarBazVal1 =
2170               cast<IntegerValue>(getFieldValue(BarLoc1, *BazDecl, Env1));
2171           EXPECT_NE(FooBazVal1, BarBazVal1);
2172         }
2173 
2174         // After copy assignment.
2175         {
2176           const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
2177 
2178           const auto *FooLoc2 =
2179               cast<RecordStorageLocation>(Env2.getStorageLocation(*FooDecl));
2180           const auto *BarLoc2 =
2181               cast<RecordStorageLocation>(Env2.getStorageLocation(*BarDecl));
2182 
2183           const auto *FooVal2 = cast<RecordValue>(Env2.getValue(*FooLoc2));
2184           const auto *BarVal2 = cast<RecordValue>(Env2.getValue(*BarLoc2));
2185           EXPECT_NE(FooVal2, BarVal2);
2186 
2187           EXPECT_TRUE(recordsEqual(*FooLoc2, *BarLoc2, Env2));
2188 
2189           const auto *FooBazVal2 =
2190               cast<IntegerValue>(getFieldValue(FooLoc2, *BazDecl, Env2));
2191           const auto *BarBazVal2 =
2192               cast<IntegerValue>(getFieldValue(BarLoc2, *BazDecl, Env2));
2193           EXPECT_EQ(FooBazVal2, BarBazVal2);
2194         }
2195 
2196         // After value update.
2197         {
2198           const Environment &Env3 = getEnvironmentAtAnnotation(Results, "p3");
2199 
2200           const auto *FooLoc3 =
2201               cast<RecordStorageLocation>(Env3.getStorageLocation(*FooDecl));
2202           const auto *BarLoc3 =
2203               cast<RecordStorageLocation>(Env3.getStorageLocation(*BarDecl));
2204           EXPECT_FALSE(recordsEqual(*FooLoc3, *BarLoc3, Env3));
2205 
2206           const auto *FooBazVal3 =
2207               cast<IntegerValue>(getFieldValue(FooLoc3, *BazDecl, Env3));
2208           const auto *BarBazVal3 =
2209               cast<IntegerValue>(getFieldValue(BarLoc3, *BazDecl, Env3));
2210           EXPECT_NE(FooBazVal3, BarBazVal3);
2211         }
2212       });
2213 }
2214 
2215 // It's legal for the assignment operator to take its source parameter by value.
2216 // Check that we handle this correctly. (This is a repro -- we used to
2217 // assert-fail on this.)
2218 TEST(TransferTest, AssignmentOperator_ArgByValue) {
2219   std::string Code = R"(
2220     struct A {
2221       int Baz;
2222       A &operator=(A);
2223     };
2224 
2225     void target() {
2226       A Foo = { 1 };
2227       A Bar = { 2 };
2228       Foo = Bar;
2229       // [[p]]
2230     }
2231   )";
2232   runDataflow(
2233       Code,
2234       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2235          ASTContext &ASTCtx) {
2236         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2237         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2238 
2239         const auto &FooLoc =
2240             getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "Foo");
2241         const auto &BarLoc =
2242             getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "Bar");
2243 
2244         const auto *FooBazVal =
2245             cast<IntegerValue>(getFieldValue(&FooLoc, *BazDecl, Env));
2246         const auto *BarBazVal =
2247             cast<IntegerValue>(getFieldValue(&BarLoc, *BazDecl, Env));
2248         EXPECT_EQ(FooBazVal, BarBazVal);
2249       });
2250 }
2251 
2252 TEST(TransferTest, AssignmentOperatorFromBase) {
2253   // This is a crash repro. We don't model the copy this case, so no
2254   // expectations on the copied field of the base class are checked.
2255   std::string Code = R"(
2256     struct Base {
2257       int base;
2258     };
2259     struct Derived : public Base {
2260       using Base::operator=;
2261       int derived;
2262     };
2263     void target(Base B, Derived D) {
2264       D.base = 1;
2265       D.derived = 1;
2266       D = B;
2267       // [[p]]
2268     }
2269   )";
2270   runDataflow(
2271       Code,
2272       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2273          ASTContext &ASTCtx) {});
2274 }
2275 
2276 TEST(TransferTest, AssignmentOperatorFromCallResult) {
2277   std::string Code = R"(
2278     struct A {};
2279     A ReturnA();
2280 
2281     void target() {
2282       A MyA;
2283       MyA = ReturnA();
2284     }
2285   )";
2286   runDataflow(
2287       Code,
2288       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2289          ASTContext &ASTCtx) {
2290         // As of this writing, we don't produce a `Value` for the call
2291         // `ReturnA()`. The only condition we're testing for is that the
2292         // analysis should not crash in this case.
2293       });
2294 }
2295 
2296 TEST(TransferTest, AssignmentOperatorWithInitAndInheritance) {
2297   // This is a crash repro.
2298   std::string Code = R"(
2299     struct B { int Foo; };
2300     struct S : public B {};
2301     void target() {
2302       S S1 = { 1 };
2303       S S2;
2304       S S3;
2305       S1 = S2;  // Only Dst has InitListExpr.
2306       S3 = S1;  // Only Src has InitListExpr.
2307       // [[p]]
2308     }
2309   )";
2310   runDataflow(
2311       Code,
2312       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2313          ASTContext &ASTCtx) {});
2314 }
2315 
2316 TEST(TransferTest, AssignmentOperatorReturnsVoid) {
2317   // This is a crash repro.
2318   std::string Code = R"(
2319     struct S {
2320       void operator=(S&& other);
2321     };
2322     void target() {
2323       S s;
2324       s = S();
2325       // [[p]]
2326     }
2327   )";
2328   runDataflow(
2329       Code,
2330       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2331          ASTContext &ASTCtx) {});
2332 }
2333 
2334 TEST(TransferTest, AssignmentOperatorReturnsByValue) {
2335   // This is a crash repro.
2336   std::string Code = R"(
2337     struct S {
2338       S operator=(S&& other);
2339     };
2340     void target() {
2341       S s;
2342       s = S();
2343       // [[p]]
2344     }
2345   )";
2346   runDataflow(
2347       Code,
2348       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2349          ASTContext &ASTCtx) {});
2350 }
2351 
2352 TEST(TransferTest, CopyConstructor) {
2353   std::string Code = R"(
2354     struct A {
2355       int Baz;
2356     };
2357 
2358     void target() {
2359       A Foo = { 1 };
2360       A Bar = Foo;
2361       // [[after_copy]]
2362       Foo.Baz = 2;
2363       // [[after_update]]
2364     }
2365   )";
2366   runDataflow(
2367       Code,
2368       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2369          ASTContext &ASTCtx) {
2370         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2371         ASSERT_THAT(FooDecl, NotNull());
2372 
2373         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2374         ASSERT_THAT(BarDecl, NotNull());
2375 
2376         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2377         ASSERT_THAT(BazDecl, NotNull());
2378 
2379         // after_copy
2380         {
2381           const Environment &Env =
2382               getEnvironmentAtAnnotation(Results, "after_copy");
2383 
2384           const auto *FooLoc =
2385               cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
2386           const auto *BarLoc =
2387               cast<RecordStorageLocation>(Env.getStorageLocation(*BarDecl));
2388 
2389           // `Foo` and `Bar` have different `RecordValue`s associated with them.
2390           const auto *FooVal = cast<RecordValue>(Env.getValue(*FooLoc));
2391           const auto *BarVal = cast<RecordValue>(Env.getValue(*BarLoc));
2392           EXPECT_NE(FooVal, BarVal);
2393 
2394           // But the records compare equal.
2395           EXPECT_TRUE(recordsEqual(*FooLoc, *BarLoc, Env));
2396 
2397           // In particular, the value of `Baz` in both records is the same.
2398           const auto *FooBazVal =
2399               cast<IntegerValue>(getFieldValue(FooLoc, *BazDecl, Env));
2400           const auto *BarBazVal =
2401               cast<IntegerValue>(getFieldValue(BarLoc, *BazDecl, Env));
2402           EXPECT_EQ(FooBazVal, BarBazVal);
2403         }
2404 
2405         // after_update
2406         {
2407           const Environment &Env =
2408               getEnvironmentAtAnnotation(Results, "after_update");
2409 
2410           const auto *FooLoc =
2411               cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
2412           const auto *BarLoc =
2413               cast<RecordStorageLocation>(Env.getStorageLocation(*BarDecl));
2414 
2415           EXPECT_FALSE(recordsEqual(*FooLoc, *BarLoc, Env));
2416 
2417           const auto *FooBazVal =
2418               cast<IntegerValue>(getFieldValue(FooLoc, *BazDecl, Env));
2419           const auto *BarBazVal =
2420               cast<IntegerValue>(getFieldValue(BarLoc, *BazDecl, Env));
2421           EXPECT_NE(FooBazVal, BarBazVal);
2422         }
2423       });
2424 }
2425 
2426 TEST(TransferTest, CopyConstructorWithDefaultArgument) {
2427   std::string Code = R"(
2428     struct A {
2429       int Baz;
2430       A() = default;
2431       A(const A& a, bool def = true) { Baz = a.Baz; }
2432     };
2433 
2434     void target() {
2435       A Foo;
2436       (void)Foo.Baz;
2437       A Bar = Foo;
2438       // [[p]]
2439     }
2440   )";
2441   runDataflow(
2442       Code,
2443       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2444          ASTContext &ASTCtx) {
2445         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2446         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2447 
2448         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2449         ASSERT_THAT(FooDecl, NotNull());
2450 
2451         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2452         ASSERT_THAT(BarDecl, NotNull());
2453 
2454         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2455         ASSERT_THAT(BazDecl, NotNull());
2456 
2457         const auto *FooLoc =
2458             cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
2459         const auto *BarLoc =
2460             cast<RecordStorageLocation>(Env.getStorageLocation(*BarDecl));
2461         EXPECT_TRUE(recordsEqual(*FooLoc, *BarLoc, Env));
2462 
2463         const auto *FooBazVal =
2464             cast<IntegerValue>(getFieldValue(FooLoc, *BazDecl, Env));
2465         const auto *BarBazVal =
2466             cast<IntegerValue>(getFieldValue(BarLoc, *BazDecl, Env));
2467         EXPECT_EQ(FooBazVal, BarBazVal);
2468       });
2469 }
2470 
2471 TEST(TransferTest, CopyConstructorWithParens) {
2472   std::string Code = R"(
2473     struct A {
2474       int Baz;
2475     };
2476 
2477     void target() {
2478       A Foo;
2479       (void)Foo.Baz;
2480       A Bar((A(Foo)));
2481       // [[p]]
2482     }
2483   )";
2484   runDataflow(
2485       Code,
2486       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2487          ASTContext &ASTCtx) {
2488         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2489         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2490 
2491         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2492         ASSERT_THAT(FooDecl, NotNull());
2493 
2494         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2495         ASSERT_THAT(BarDecl, NotNull());
2496 
2497         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2498         ASSERT_THAT(BazDecl, NotNull());
2499 
2500         const auto *FooLoc =
2501             cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
2502         const auto *BarLoc =
2503             cast<RecordStorageLocation>(Env.getStorageLocation(*BarDecl));
2504         EXPECT_TRUE(recordsEqual(*FooLoc, *BarLoc, Env));
2505 
2506         const auto *FooBazVal =
2507             cast<IntegerValue>(getFieldValue(FooLoc, *BazDecl, Env));
2508         const auto *BarBazVal =
2509             cast<IntegerValue>(getFieldValue(BarLoc, *BazDecl, Env));
2510         EXPECT_EQ(FooBazVal, BarBazVal);
2511       });
2512 }
2513 
2514 TEST(TransferTest, CopyConstructorWithInitializerListAsSyntacticSugar) {
2515   std::string Code = R"(
2516   struct A {
2517     int Baz;
2518   };
2519   void target() {
2520     A Foo = {3};
2521     (void)Foo.Baz;
2522     A Bar = {A(Foo)};
2523     // [[p]]
2524   }
2525   )";
2526   runDataflow(
2527       Code,
2528       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2529          ASTContext &ASTCtx) {
2530         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2531 
2532         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2533 
2534         const auto &FooLoc =
2535             getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "Foo");
2536         const auto &BarLoc =
2537             getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "Bar");
2538 
2539         const auto *FooBazVal =
2540             cast<IntegerValue>(getFieldValue(&FooLoc, *BazDecl, Env));
2541         const auto *BarBazVal =
2542             cast<IntegerValue>(getFieldValue(&BarLoc, *BazDecl, Env));
2543         EXPECT_EQ(FooBazVal, BarBazVal);
2544       });
2545 }
2546 
2547 TEST(TransferTest, CopyConstructorArgIsRefReturnedByFunction) {
2548   // This is a crash repro.
2549   std::string Code = R"(
2550     struct S {};
2551     const S &returnsSRef();
2552     void target() {
2553       S s(returnsSRef());
2554     }
2555   )";
2556   runDataflow(
2557       Code,
2558       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2559          ASTContext &ASTCtx) {});
2560 }
2561 
2562 TEST(TransferTest, MoveConstructor) {
2563   std::string Code = R"(
2564     namespace std {
2565 
2566     template <typename T> struct remove_reference      { using type = T; };
2567     template <typename T> struct remove_reference<T&>  { using type = T; };
2568     template <typename T> struct remove_reference<T&&> { using type = T; };
2569 
2570     template <typename T>
2571     using remove_reference_t = typename remove_reference<T>::type;
2572 
2573     template <typename T>
2574     std::remove_reference_t<T>&& move(T&& x);
2575 
2576     } // namespace std
2577 
2578     struct A {
2579       int Baz;
2580     };
2581 
2582     void target() {
2583       A Foo;
2584       A Bar;
2585       (void)Foo.Baz;
2586       // [[p1]]
2587       Foo = std::move(Bar);
2588       // [[p2]]
2589     }
2590   )";
2591   runDataflow(
2592       Code,
2593       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2594          ASTContext &ASTCtx) {
2595         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
2596         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
2597         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
2598 
2599         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2600         ASSERT_THAT(FooDecl, NotNull());
2601 
2602         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2603         ASSERT_THAT(BarDecl, NotNull());
2604 
2605         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2606         ASSERT_THAT(BazDecl, NotNull());
2607 
2608         const auto *FooLoc1 =
2609             cast<RecordStorageLocation>(Env1.getStorageLocation(*FooDecl));
2610         const auto *BarLoc1 =
2611             cast<RecordStorageLocation>(Env1.getStorageLocation(*BarDecl));
2612 
2613         EXPECT_FALSE(recordsEqual(*FooLoc1, *BarLoc1, Env1));
2614 
2615         const auto *FooVal1 = cast<RecordValue>(Env1.getValue(*FooLoc1));
2616         const auto *BarVal1 = cast<RecordValue>(Env1.getValue(*BarLoc1));
2617         EXPECT_NE(FooVal1, BarVal1);
2618 
2619         const auto *FooBazVal1 =
2620             cast<IntegerValue>(getFieldValue(FooLoc1, *BazDecl, Env1));
2621         const auto *BarBazVal1 =
2622             cast<IntegerValue>(getFieldValue(BarLoc1, *BazDecl, Env1));
2623         EXPECT_NE(FooBazVal1, BarBazVal1);
2624 
2625         const auto *FooLoc2 =
2626             cast<RecordStorageLocation>(Env2.getStorageLocation(*FooDecl));
2627         const auto *FooVal2 = cast<RecordValue>(Env2.getValue(*FooLoc2));
2628         EXPECT_NE(FooVal2, BarVal1);
2629         EXPECT_TRUE(recordsEqual(*FooLoc2, Env2, *BarLoc1, Env1));
2630 
2631         const auto *FooBazVal2 =
2632             cast<IntegerValue>(getFieldValue(FooLoc1, *BazDecl, Env2));
2633         EXPECT_EQ(FooBazVal2, BarBazVal1);
2634       });
2635 }
2636 
2637 TEST(TransferTest, BindTemporary) {
2638   std::string Code = R"(
2639     struct A {
2640       virtual ~A() = default;
2641 
2642       int Baz;
2643     };
2644 
2645     void target(A Foo) {
2646       int Bar = A(Foo).Baz;
2647       // [[p]]
2648     }
2649   )";
2650   runDataflow(
2651       Code,
2652       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2653          ASTContext &ASTCtx) {
2654         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2655         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2656 
2657         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2658         ASSERT_THAT(FooDecl, NotNull());
2659 
2660         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2661         ASSERT_THAT(BarDecl, NotNull());
2662 
2663         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2664         ASSERT_THAT(BazDecl, NotNull());
2665 
2666         const auto &FooLoc =
2667             *cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
2668         const auto *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
2669         EXPECT_EQ(BarVal, getFieldValue(&FooLoc, *BazDecl, Env));
2670       });
2671 }
2672 
2673 TEST(TransferTest, ResultObjectLocation) {
2674   std::string Code = R"(
2675     struct A {
2676       virtual ~A() = default;
2677     };
2678 
2679     void target() {
2680       0, A();
2681       (void)0; // [[p]]
2682     }
2683   )";
2684   using ast_matchers::binaryOperator;
2685   using ast_matchers::cxxBindTemporaryExpr;
2686   using ast_matchers::cxxTemporaryObjectExpr;
2687   using ast_matchers::exprWithCleanups;
2688   using ast_matchers::has;
2689   using ast_matchers::hasOperatorName;
2690   using ast_matchers::hasRHS;
2691   using ast_matchers::match;
2692   using ast_matchers::selectFirst;
2693   using ast_matchers::traverse;
2694   runDataflow(
2695       Code,
2696       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2697          ASTContext &ASTCtx) {
2698         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2699 
2700         // The expression `0, A()` in the code above produces the following
2701         // structure, consisting of four prvalues of record type.
2702         // `Env.getResultObjectLocation()` should return the same location for
2703         // all of these.
2704         auto MatchResult = match(
2705             traverse(TK_AsIs,
2706                      exprWithCleanups(
2707                          has(binaryOperator(
2708                                  hasOperatorName(","),
2709                                  hasRHS(cxxBindTemporaryExpr(
2710                                             has(cxxTemporaryObjectExpr().bind(
2711                                                 "toe")))
2712                                             .bind("bte")))
2713                                  .bind("comma")))
2714                          .bind("ewc")),
2715             ASTCtx);
2716         auto *TOE = selectFirst<CXXTemporaryObjectExpr>("toe", MatchResult);
2717         ASSERT_NE(TOE, nullptr);
2718         auto *Comma = selectFirst<BinaryOperator>("comma", MatchResult);
2719         ASSERT_NE(Comma, nullptr);
2720         auto *EWC = selectFirst<ExprWithCleanups>("ewc", MatchResult);
2721         ASSERT_NE(EWC, nullptr);
2722         auto *BTE = selectFirst<CXXBindTemporaryExpr>("bte", MatchResult);
2723         ASSERT_NE(BTE, nullptr);
2724 
2725         RecordStorageLocation &Loc = Env.getResultObjectLocation(*TOE);
2726         EXPECT_EQ(&Loc, &Env.getResultObjectLocation(*Comma));
2727         EXPECT_EQ(&Loc, &Env.getResultObjectLocation(*EWC));
2728         EXPECT_EQ(&Loc, &Env.getResultObjectLocation(*BTE));
2729       });
2730 }
2731 
2732 TEST(TransferTest, ResultObjectLocationForDefaultInitExpr) {
2733   std::string Code = R"(
2734     struct S {};
2735     struct target {
2736       target () {
2737         (void)0;
2738         // [[p]]
2739       }
2740       S s = {};
2741     };
2742   )";
2743 
2744   using ast_matchers::cxxCtorInitializer;
2745   using ast_matchers::match;
2746   using ast_matchers::selectFirst;
2747   runDataflow(
2748       Code,
2749       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2750          ASTContext &ASTCtx) {
2751         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2752 
2753         const ValueDecl *SField = findValueDecl(ASTCtx, "s");
2754 
2755         auto *CtorInit = selectFirst<CXXCtorInitializer>(
2756             "ctor_initializer",
2757             match(cxxCtorInitializer().bind("ctor_initializer"), ASTCtx));
2758         ASSERT_NE(CtorInit, nullptr);
2759 
2760         auto *DefaultInit = cast<CXXDefaultInitExpr>(CtorInit->getInit());
2761 
2762         RecordStorageLocation &Loc = Env.getResultObjectLocation(*DefaultInit);
2763 
2764         // FIXME: The result object location for the `CXXDefaultInitExpr` should
2765         // be the location of the member variable being initialized, but we
2766         // don't do this correctly yet; see also comments in
2767         // `builtinTransferInitializer()`.
2768         // For the time being, we just document the current erroneous behavior
2769         // here (this should be `EXPECT_EQ` when the behavior is fixed).
2770         EXPECT_NE(&Loc, Env.getThisPointeeStorageLocation()->getChild(*SField));
2771       });
2772 }
2773 
2774 // This test ensures that CXXOperatorCallExpr returning prvalues are correctly
2775 // handled by the transfer functions, especially that `getResultObjectLocation`
2776 // correctly returns a storage location for those.
2777 TEST(TransferTest, ResultObjectLocationForCXXOperatorCallExpr) {
2778   std::string Code = R"(
2779     struct A {
2780       A operator+(int);
2781     };
2782 
2783     void target() {
2784       A a;
2785       a + 3;
2786       (void)0; // [[p]]
2787     }
2788   )";
2789   using ast_matchers::cxxOperatorCallExpr;
2790   using ast_matchers::match;
2791   using ast_matchers::selectFirst;
2792   using ast_matchers::traverse;
2793   runDataflow(
2794       Code,
2795       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2796          ASTContext &ASTCtx) {
2797         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2798 
2799         auto *CallExpr = selectFirst<CXXOperatorCallExpr>(
2800             "call_expr",
2801             match(cxxOperatorCallExpr().bind("call_expr"), ASTCtx));
2802 
2803         EXPECT_NE(&Env.getResultObjectLocation(*CallExpr), nullptr);
2804       });
2805 }
2806 
2807 TEST(TransferTest, StaticCast) {
2808   std::string Code = R"(
2809     void target(int Foo) {
2810       int Bar = static_cast<int>(Foo);
2811       // [[p]]
2812     }
2813   )";
2814   runDataflow(
2815       Code,
2816       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2817          ASTContext &ASTCtx) {
2818         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2819         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2820 
2821         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2822         ASSERT_THAT(FooDecl, NotNull());
2823 
2824         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2825         ASSERT_THAT(BarDecl, NotNull());
2826 
2827         const auto *FooVal = Env.getValue(*FooDecl);
2828         const auto *BarVal = Env.getValue(*BarDecl);
2829         EXPECT_TRUE(isa<IntegerValue>(FooVal));
2830         EXPECT_TRUE(isa<IntegerValue>(BarVal));
2831         EXPECT_EQ(FooVal, BarVal);
2832       });
2833 }
2834 
2835 TEST(TransferTest, IntegralCast) {
2836   std::string Code = R"(
2837     void target(int Foo) {
2838       long Bar = Foo;
2839       // [[p]]
2840     }
2841   )";
2842   runDataflow(
2843       Code,
2844       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2845          ASTContext &ASTCtx) {
2846         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2847         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2848 
2849         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2850         ASSERT_THAT(FooDecl, NotNull());
2851 
2852         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2853         ASSERT_THAT(BarDecl, NotNull());
2854 
2855         const auto *FooVal = Env.getValue(*FooDecl);
2856         const auto *BarVal = Env.getValue(*BarDecl);
2857         EXPECT_TRUE(isa<IntegerValue>(FooVal));
2858         EXPECT_TRUE(isa<IntegerValue>(BarVal));
2859         EXPECT_EQ(FooVal, BarVal);
2860       });
2861 }
2862 
2863 TEST(TransferTest, IntegraltoBooleanCast) {
2864   std::string Code = R"(
2865     void target(int Foo) {
2866       bool Bar = Foo;
2867       // [[p]]
2868     }
2869   )";
2870   runDataflow(
2871       Code,
2872       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2873          ASTContext &ASTCtx) {
2874         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2875         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2876 
2877         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2878         ASSERT_THAT(FooDecl, NotNull());
2879 
2880         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2881         ASSERT_THAT(BarDecl, NotNull());
2882 
2883         const auto *FooVal = Env.getValue(*FooDecl);
2884         const auto *BarVal = Env.getValue(*BarDecl);
2885         EXPECT_TRUE(isa<IntegerValue>(FooVal));
2886         EXPECT_TRUE(isa<BoolValue>(BarVal));
2887       });
2888 }
2889 
2890 TEST(TransferTest, IntegralToBooleanCastFromBool) {
2891   std::string Code = R"(
2892     void target(bool Foo) {
2893       int Zab = Foo;
2894       bool Bar = Zab;
2895       // [[p]]
2896     }
2897   )";
2898   runDataflow(
2899       Code,
2900       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2901          ASTContext &ASTCtx) {
2902         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2903         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2904 
2905         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2906         ASSERT_THAT(FooDecl, NotNull());
2907 
2908         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2909         ASSERT_THAT(BarDecl, NotNull());
2910 
2911         const auto *FooVal = Env.getValue(*FooDecl);
2912         const auto *BarVal = Env.getValue(*BarDecl);
2913         EXPECT_TRUE(isa<BoolValue>(FooVal));
2914         EXPECT_TRUE(isa<BoolValue>(BarVal));
2915         EXPECT_EQ(FooVal, BarVal);
2916       });
2917 }
2918 
2919 TEST(TransferTest, NullToPointerCast) {
2920   std::string Code = R"(
2921     using my_nullptr_t = decltype(nullptr);
2922     struct Baz {};
2923     void target() {
2924       int *FooX = nullptr;
2925       int *FooY = nullptr;
2926       bool **Bar = nullptr;
2927       Baz *Baz = nullptr;
2928       my_nullptr_t Null = 0;
2929       // [[p]]
2930     }
2931   )";
2932   runDataflow(
2933       Code,
2934       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2935          ASTContext &ASTCtx) {
2936         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2937         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2938 
2939         const ValueDecl *FooXDecl = findValueDecl(ASTCtx, "FooX");
2940         ASSERT_THAT(FooXDecl, NotNull());
2941 
2942         const ValueDecl *FooYDecl = findValueDecl(ASTCtx, "FooY");
2943         ASSERT_THAT(FooYDecl, NotNull());
2944 
2945         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2946         ASSERT_THAT(BarDecl, NotNull());
2947 
2948         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2949         ASSERT_THAT(BazDecl, NotNull());
2950 
2951         const ValueDecl *NullDecl = findValueDecl(ASTCtx, "Null");
2952         ASSERT_THAT(NullDecl, NotNull());
2953 
2954         const auto *FooXVal = cast<PointerValue>(Env.getValue(*FooXDecl));
2955         const auto *FooYVal = cast<PointerValue>(Env.getValue(*FooYDecl));
2956         const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl));
2957         const auto *BazVal = cast<PointerValue>(Env.getValue(*BazDecl));
2958         const auto *NullVal = cast<PointerValue>(Env.getValue(*NullDecl));
2959 
2960         EXPECT_EQ(FooXVal, FooYVal);
2961         EXPECT_NE(FooXVal, BarVal);
2962         EXPECT_NE(FooXVal, BazVal);
2963         EXPECT_NE(BarVal, BazVal);
2964 
2965         const StorageLocation &FooPointeeLoc = FooXVal->getPointeeLoc();
2966         EXPECT_TRUE(isa<ScalarStorageLocation>(FooPointeeLoc));
2967         EXPECT_THAT(Env.getValue(FooPointeeLoc), IsNull());
2968 
2969         const StorageLocation &BarPointeeLoc = BarVal->getPointeeLoc();
2970         EXPECT_TRUE(isa<ScalarStorageLocation>(BarPointeeLoc));
2971         EXPECT_THAT(Env.getValue(BarPointeeLoc), IsNull());
2972 
2973         const StorageLocation &BazPointeeLoc = BazVal->getPointeeLoc();
2974         EXPECT_TRUE(isa<RecordStorageLocation>(BazPointeeLoc));
2975         EXPECT_THAT(Env.getValue(BazPointeeLoc), IsNull());
2976 
2977         const StorageLocation &NullPointeeLoc = NullVal->getPointeeLoc();
2978         EXPECT_TRUE(isa<ScalarStorageLocation>(NullPointeeLoc));
2979         EXPECT_THAT(Env.getValue(NullPointeeLoc), IsNull());
2980       });
2981 }
2982 
2983 TEST(TransferTest, PointerToMemberVariable) {
2984   std::string Code = R"(
2985     struct S {
2986       int i;
2987     };
2988     void target() {
2989       int S::*MemberPointer = &S::i;
2990       // [[p]]
2991     }
2992   )";
2993   runDataflow(
2994       Code,
2995       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2996          ASTContext &ASTCtx) {
2997         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2998 
2999         const ValueDecl *MemberPointerDecl =
3000             findValueDecl(ASTCtx, "MemberPointer");
3001         ASSERT_THAT(MemberPointerDecl, NotNull());
3002         ASSERT_THAT(Env.getValue(*MemberPointerDecl), IsNull());
3003       });
3004 }
3005 
3006 TEST(TransferTest, PointerToMemberFunction) {
3007   std::string Code = R"(
3008     struct S {
3009       void Method();
3010     };
3011     void target() {
3012       void (S::*MemberPointer)() = &S::Method;
3013       // [[p]]
3014     }
3015   )";
3016   runDataflow(
3017       Code,
3018       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3019          ASTContext &ASTCtx) {
3020         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3021 
3022         const ValueDecl *MemberPointerDecl =
3023             findValueDecl(ASTCtx, "MemberPointer");
3024         ASSERT_THAT(MemberPointerDecl, NotNull());
3025         ASSERT_THAT(Env.getValue(*MemberPointerDecl), IsNull());
3026       });
3027 }
3028 
3029 TEST(TransferTest, NullToMemberPointerCast) {
3030   std::string Code = R"(
3031     struct Foo {};
3032     void target() {
3033       int Foo::*MemberPointer = nullptr;
3034       // [[p]]
3035     }
3036   )";
3037   runDataflow(
3038       Code,
3039       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3040          ASTContext &ASTCtx) {
3041         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3042         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3043 
3044         const ValueDecl *MemberPointerDecl =
3045             findValueDecl(ASTCtx, "MemberPointer");
3046         ASSERT_THAT(MemberPointerDecl, NotNull());
3047         ASSERT_THAT(Env.getValue(*MemberPointerDecl), IsNull());
3048       });
3049 }
3050 
3051 TEST(TransferTest, AddrOfValue) {
3052   std::string Code = R"(
3053     void target() {
3054       int Foo;
3055       int *Bar = &Foo;
3056       // [[p]]
3057     }
3058   )";
3059   runDataflow(
3060       Code,
3061       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3062          ASTContext &ASTCtx) {
3063         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3064         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3065 
3066         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3067         ASSERT_THAT(FooDecl, NotNull());
3068 
3069         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3070         ASSERT_THAT(BarDecl, NotNull());
3071 
3072         const auto *FooLoc =
3073             cast<ScalarStorageLocation>(Env.getStorageLocation(*FooDecl));
3074         const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl));
3075         EXPECT_EQ(&BarVal->getPointeeLoc(), FooLoc);
3076       });
3077 }
3078 
3079 TEST(TransferTest, AddrOfReference) {
3080   std::string Code = R"(
3081     void target(int *Foo) {
3082       int *Bar = &(*Foo);
3083       // [[p]]
3084     }
3085   )";
3086   runDataflow(
3087       Code,
3088       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3089          ASTContext &ASTCtx) {
3090         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3091         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3092 
3093         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3094         ASSERT_THAT(FooDecl, NotNull());
3095 
3096         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3097         ASSERT_THAT(BarDecl, NotNull());
3098 
3099         const auto *FooVal = cast<PointerValue>(Env.getValue(*FooDecl));
3100         const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl));
3101         EXPECT_EQ(&BarVal->getPointeeLoc(), &FooVal->getPointeeLoc());
3102       });
3103 }
3104 
3105 TEST(TransferTest, CannotAnalyzeFunctionTemplate) {
3106   std::string Code = R"(
3107     template <typename T>
3108     void target() {}
3109   )";
3110   ASSERT_THAT_ERROR(
3111       checkDataflowWithNoopAnalysis(Code),
3112       llvm::FailedWithMessage("Cannot analyze templated declarations"));
3113 }
3114 
3115 TEST(TransferTest, CannotAnalyzeMethodOfClassTemplate) {
3116   std::string Code = R"(
3117     template <typename T>
3118     struct A {
3119       void target() {}
3120     };
3121   )";
3122   ASSERT_THAT_ERROR(
3123       checkDataflowWithNoopAnalysis(Code),
3124       llvm::FailedWithMessage("Cannot analyze templated declarations"));
3125 }
3126 
3127 TEST(TransferTest, VarDeclInitAssignConditionalOperator) {
3128   std::string Code = R"(
3129     struct A {};
3130 
3131     void target(A Foo, A Bar, bool Cond) {
3132       A Baz = Cond ?  Foo : Bar;
3133       /*[[p]]*/
3134     }
3135   )";
3136   runDataflow(
3137       Code,
3138       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3139          ASTContext &ASTCtx) {
3140         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3141         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3142 
3143         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3144         ASSERT_THAT(FooDecl, NotNull());
3145 
3146         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3147         ASSERT_THAT(BarDecl, NotNull());
3148 
3149         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3150         ASSERT_THAT(BazDecl, NotNull());
3151 
3152         const auto *FooVal = cast<RecordValue>(Env.getValue(*FooDecl));
3153         const auto *BarVal = cast<RecordValue>(Env.getValue(*BarDecl));
3154 
3155         const auto *BazVal = dyn_cast<RecordValue>(Env.getValue(*BazDecl));
3156         ASSERT_THAT(BazVal, NotNull());
3157 
3158         EXPECT_NE(BazVal, FooVal);
3159         EXPECT_NE(BazVal, BarVal);
3160       });
3161 }
3162 
3163 TEST(TransferTest, VarDeclInDoWhile) {
3164   std::string Code = R"(
3165     void target(int *Foo) {
3166       do {
3167         int Bar = *Foo;
3168         // [[in_loop]]
3169       } while (false);
3170       (void)0;
3171       // [[after_loop]]
3172     }
3173   )";
3174   runDataflow(
3175       Code,
3176       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3177          ASTContext &ASTCtx) {
3178         const Environment &EnvInLoop =
3179             getEnvironmentAtAnnotation(Results, "in_loop");
3180         const Environment &EnvAfterLoop =
3181             getEnvironmentAtAnnotation(Results, "after_loop");
3182 
3183         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3184         ASSERT_THAT(FooDecl, NotNull());
3185 
3186         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3187         ASSERT_THAT(BarDecl, NotNull());
3188 
3189         const auto *FooVal =
3190             cast<PointerValue>(EnvAfterLoop.getValue(*FooDecl));
3191         const auto *FooPointeeVal =
3192             cast<IntegerValue>(EnvAfterLoop.getValue(FooVal->getPointeeLoc()));
3193 
3194         const auto *BarVal = cast<IntegerValue>(EnvInLoop.getValue(*BarDecl));
3195         EXPECT_EQ(BarVal, FooPointeeVal);
3196 
3197         ASSERT_THAT(EnvAfterLoop.getValue(*BarDecl), IsNull());
3198       });
3199 }
3200 
3201 TEST(TransferTest, UnreachableAfterWhileTrue) {
3202   std::string Code = R"(
3203     void target() {
3204       while (true) {}
3205       (void)0;
3206       /*[[p]]*/
3207     }
3208   )";
3209   runDataflow(
3210       Code,
3211       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3212          ASTContext &ASTCtx) {
3213         // The node after the while-true is pruned because it is trivially
3214         // known to be unreachable.
3215         ASSERT_TRUE(Results.empty());
3216       });
3217 }
3218 
3219 TEST(TransferTest, AggregateInitialization) {
3220   std::string BracesCode = R"(
3221     struct A {
3222       int Foo;
3223     };
3224 
3225     struct B {
3226       int Bar;
3227       A Baz;
3228       int Qux;
3229     };
3230 
3231     void target(int BarArg, int FooArg, int QuxArg) {
3232       B Quux{BarArg, {FooArg}, QuxArg};
3233       B OtherB;
3234       /*[[p]]*/
3235     }
3236   )";
3237   std::string BraceElisionCode = R"(
3238     struct A {
3239       int Foo;
3240     };
3241 
3242     struct B {
3243       int Bar;
3244       A Baz;
3245       int Qux;
3246     };
3247 
3248     void target(int BarArg, int FooArg, int QuxArg) {
3249       B Quux = {BarArg, FooArg, QuxArg};
3250       B OtherB;
3251       /*[[p]]*/
3252     }
3253   )";
3254   for (const std::string &Code : {BracesCode, BraceElisionCode}) {
3255     runDataflow(
3256         Code,
3257         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3258            ASTContext &ASTCtx) {
3259           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3260           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3261 
3262           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3263           ASSERT_THAT(FooDecl, NotNull());
3264 
3265           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3266           ASSERT_THAT(BarDecl, NotNull());
3267 
3268           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3269           ASSERT_THAT(BazDecl, NotNull());
3270 
3271           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
3272           ASSERT_THAT(QuxDecl, NotNull());
3273 
3274           const ValueDecl *FooArgDecl = findValueDecl(ASTCtx, "FooArg");
3275           ASSERT_THAT(FooArgDecl, NotNull());
3276 
3277           const ValueDecl *BarArgDecl = findValueDecl(ASTCtx, "BarArg");
3278           ASSERT_THAT(BarArgDecl, NotNull());
3279 
3280           const ValueDecl *QuxArgDecl = findValueDecl(ASTCtx, "QuxArg");
3281           ASSERT_THAT(QuxArgDecl, NotNull());
3282 
3283           const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux");
3284           ASSERT_THAT(QuuxDecl, NotNull());
3285 
3286           const auto *FooArgVal = cast<IntegerValue>(Env.getValue(*FooArgDecl));
3287           const auto *BarArgVal = cast<IntegerValue>(Env.getValue(*BarArgDecl));
3288           const auto *QuxArgVal = cast<IntegerValue>(Env.getValue(*QuxArgDecl));
3289 
3290           const auto &QuuxLoc =
3291               *cast<RecordStorageLocation>(Env.getStorageLocation(*QuuxDecl));
3292           const auto &BazLoc =
3293               *cast<RecordStorageLocation>(QuuxLoc.getChild(*BazDecl));
3294 
3295           EXPECT_EQ(getFieldValue(&QuuxLoc, *BarDecl, Env), BarArgVal);
3296           EXPECT_EQ(getFieldValue(&BazLoc, *FooDecl, Env), FooArgVal);
3297           EXPECT_EQ(getFieldValue(&QuuxLoc, *QuxDecl, Env), QuxArgVal);
3298 
3299           // Check that fields initialized in an initializer list are always
3300           // modeled in other instances of the same type.
3301           const auto &OtherBLoc =
3302               getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "OtherB");
3303           EXPECT_THAT(OtherBLoc.getChild(*BarDecl), NotNull());
3304           EXPECT_THAT(OtherBLoc.getChild(*BazDecl), NotNull());
3305           EXPECT_THAT(OtherBLoc.getChild(*QuxDecl), NotNull());
3306         });
3307   }
3308 }
3309 
3310 TEST(TransferTest, AggregateInitializationReferenceField) {
3311   std::string Code = R"(
3312     struct S {
3313       int &RefField;
3314     };
3315 
3316     void target(int i) {
3317       S s = { i };
3318       /*[[p]]*/
3319     }
3320   )";
3321   runDataflow(
3322       Code,
3323       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3324          ASTContext &ASTCtx) {
3325         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3326 
3327         const ValueDecl *RefFieldDecl = findValueDecl(ASTCtx, "RefField");
3328 
3329         auto &ILoc = getLocForDecl<StorageLocation>(ASTCtx, Env, "i");
3330         auto &SLoc = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "s");
3331 
3332         EXPECT_EQ(SLoc.getChild(*RefFieldDecl), &ILoc);
3333       });
3334 }
3335 
3336 TEST(TransferTest, AggregateInitialization_NotExplicitlyInitializedField) {
3337   std::string Code = R"(
3338     struct S {
3339       int i1;
3340       int i2;
3341     };
3342 
3343     void target(int i) {
3344       S s = { i };
3345       /*[[p]]*/
3346     }
3347   )";
3348   runDataflow(
3349       Code,
3350       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3351          ASTContext &ASTCtx) {
3352         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3353 
3354         const ValueDecl *I1FieldDecl = findValueDecl(ASTCtx, "i1");
3355         const ValueDecl *I2FieldDecl = findValueDecl(ASTCtx, "i2");
3356 
3357         auto &SLoc = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "s");
3358 
3359         auto &IValue = getValueForDecl<IntegerValue>(ASTCtx, Env, "i");
3360         auto &I1Value =
3361             *cast<IntegerValue>(getFieldValue(&SLoc, *I1FieldDecl, Env));
3362         EXPECT_EQ(&I1Value, &IValue);
3363         auto &I2Value =
3364             *cast<IntegerValue>(getFieldValue(&SLoc, *I2FieldDecl, Env));
3365         EXPECT_NE(&I2Value, &IValue);
3366       });
3367 }
3368 
3369 TEST(TransferTest, AggregateInitializationFunctionPointer) {
3370   // This is a repro for an assertion failure.
3371   // nullptr takes on the type of a const function pointer, but its type was
3372   // asserted to be equal to the *unqualified* type of Field, which no longer
3373   // included the const.
3374   std::string Code = R"(
3375     struct S {
3376       void (*const Field)();
3377     };
3378 
3379     void target() {
3380       S s{nullptr};
3381     }
3382   )";
3383   runDataflow(
3384       Code,
3385       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3386          ASTContext &ASTCtx) {});
3387 }
3388 
3389 TEST(TransferTest, AssignToUnionMember) {
3390   std::string Code = R"(
3391     union A {
3392       int Foo;
3393     };
3394 
3395     void target(int Bar) {
3396       A Baz;
3397       Baz.Foo = Bar;
3398       // [[p]]
3399     }
3400   )";
3401   runDataflow(
3402       Code,
3403       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3404          ASTContext &ASTCtx) {
3405         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3406         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3407 
3408         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3409         ASSERT_THAT(BazDecl, NotNull());
3410         ASSERT_TRUE(BazDecl->getType()->isUnionType());
3411 
3412         auto BazFields = BazDecl->getType()->getAsRecordDecl()->fields();
3413         FieldDecl *FooDecl = nullptr;
3414         for (FieldDecl *Field : BazFields) {
3415           if (Field->getNameAsString() == "Foo") {
3416             FooDecl = Field;
3417           } else {
3418             FAIL() << "Unexpected field: " << Field->getNameAsString();
3419           }
3420         }
3421         ASSERT_THAT(FooDecl, NotNull());
3422 
3423         const auto *BazLoc = dyn_cast_or_null<RecordStorageLocation>(
3424             Env.getStorageLocation(*BazDecl));
3425         ASSERT_THAT(BazLoc, NotNull());
3426         ASSERT_THAT(Env.getValue(*BazLoc), NotNull());
3427 
3428         const auto *FooVal =
3429             cast<IntegerValue>(getFieldValue(BazLoc, *FooDecl, Env));
3430 
3431         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3432         ASSERT_THAT(BarDecl, NotNull());
3433         const auto *BarLoc = Env.getStorageLocation(*BarDecl);
3434         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
3435 
3436         EXPECT_EQ(Env.getValue(*BarLoc), FooVal);
3437       });
3438 }
3439 
3440 TEST(TransferTest, AssignFromBoolLiteral) {
3441   std::string Code = R"(
3442     void target() {
3443       bool Foo = true;
3444       bool Bar = false;
3445       // [[p]]
3446     }
3447   )";
3448   runDataflow(
3449       Code,
3450       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3451          ASTContext &ASTCtx) {
3452         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3453         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3454 
3455         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3456         ASSERT_THAT(FooDecl, NotNull());
3457 
3458         const auto *FooVal =
3459             dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
3460         ASSERT_THAT(FooVal, NotNull());
3461 
3462         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3463         ASSERT_THAT(BarDecl, NotNull());
3464 
3465         const auto *BarVal =
3466             dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
3467         ASSERT_THAT(BarVal, NotNull());
3468 
3469         EXPECT_EQ(FooVal, &Env.getBoolLiteralValue(true));
3470         EXPECT_EQ(BarVal, &Env.getBoolLiteralValue(false));
3471       });
3472 }
3473 
3474 TEST(TransferTest, AssignFromCompositeBoolExpression) {
3475   {
3476     std::string Code = R"(
3477     void target(bool Foo, bool Bar, bool Qux) {
3478       bool Baz = (Foo) && (Bar || Qux);
3479       // [[p]]
3480     }
3481   )";
3482     runDataflow(
3483         Code,
3484         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3485            ASTContext &ASTCtx) {
3486           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3487           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3488 
3489           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3490           ASSERT_THAT(FooDecl, NotNull());
3491 
3492           const auto *FooVal =
3493               dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
3494           ASSERT_THAT(FooVal, NotNull());
3495 
3496           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3497           ASSERT_THAT(BarDecl, NotNull());
3498 
3499           const auto *BarVal =
3500               dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
3501           ASSERT_THAT(BarVal, NotNull());
3502 
3503           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
3504           ASSERT_THAT(QuxDecl, NotNull());
3505 
3506           const auto *QuxVal =
3507               dyn_cast_or_null<BoolValue>(Env.getValue(*QuxDecl));
3508           ASSERT_THAT(QuxVal, NotNull());
3509 
3510           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3511           ASSERT_THAT(BazDecl, NotNull());
3512 
3513           const auto *BazVal =
3514               dyn_cast_or_null<BoolValue>(Env.getValue(*BazDecl));
3515           ASSERT_THAT(BazVal, NotNull());
3516           auto &A = Env.arena();
3517           EXPECT_EQ(&BazVal->formula(),
3518                     &A.makeAnd(FooVal->formula(),
3519                                A.makeOr(BarVal->formula(), QuxVal->formula())));
3520         });
3521   }
3522 
3523   {
3524     std::string Code = R"(
3525     void target(bool Foo, bool Bar, bool Qux) {
3526       bool Baz = (Foo && Qux) || (Bar);
3527       // [[p]]
3528     }
3529   )";
3530     runDataflow(
3531         Code,
3532         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3533            ASTContext &ASTCtx) {
3534           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3535           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3536 
3537           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3538           ASSERT_THAT(FooDecl, NotNull());
3539 
3540           const auto *FooVal =
3541               dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
3542           ASSERT_THAT(FooVal, NotNull());
3543 
3544           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3545           ASSERT_THAT(BarDecl, NotNull());
3546 
3547           const auto *BarVal =
3548               dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
3549           ASSERT_THAT(BarVal, NotNull());
3550 
3551           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
3552           ASSERT_THAT(QuxDecl, NotNull());
3553 
3554           const auto *QuxVal =
3555               dyn_cast_or_null<BoolValue>(Env.getValue(*QuxDecl));
3556           ASSERT_THAT(QuxVal, NotNull());
3557 
3558           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3559           ASSERT_THAT(BazDecl, NotNull());
3560 
3561           const auto *BazVal =
3562               dyn_cast_or_null<BoolValue>(Env.getValue(*BazDecl));
3563           ASSERT_THAT(BazVal, NotNull());
3564           auto &A = Env.arena();
3565           EXPECT_EQ(&BazVal->formula(),
3566                     &A.makeOr(A.makeAnd(FooVal->formula(), QuxVal->formula()),
3567                               BarVal->formula()));
3568         });
3569   }
3570 
3571   {
3572     std::string Code = R"(
3573       void target(bool A, bool B, bool C, bool D) {
3574         bool Foo = ((A && B) && C) && D;
3575         // [[p]]
3576       }
3577     )";
3578     runDataflow(
3579         Code,
3580         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3581            ASTContext &ASTCtx) {
3582           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3583           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3584 
3585           const ValueDecl *ADecl = findValueDecl(ASTCtx, "A");
3586           ASSERT_THAT(ADecl, NotNull());
3587 
3588           const auto *AVal = dyn_cast_or_null<BoolValue>(Env.getValue(*ADecl));
3589           ASSERT_THAT(AVal, NotNull());
3590 
3591           const ValueDecl *BDecl = findValueDecl(ASTCtx, "B");
3592           ASSERT_THAT(BDecl, NotNull());
3593 
3594           const auto *BVal = dyn_cast_or_null<BoolValue>(Env.getValue(*BDecl));
3595           ASSERT_THAT(BVal, NotNull());
3596 
3597           const ValueDecl *CDecl = findValueDecl(ASTCtx, "C");
3598           ASSERT_THAT(CDecl, NotNull());
3599 
3600           const auto *CVal = dyn_cast_or_null<BoolValue>(Env.getValue(*CDecl));
3601           ASSERT_THAT(CVal, NotNull());
3602 
3603           const ValueDecl *DDecl = findValueDecl(ASTCtx, "D");
3604           ASSERT_THAT(DDecl, NotNull());
3605 
3606           const auto *DVal = dyn_cast_or_null<BoolValue>(Env.getValue(*DDecl));
3607           ASSERT_THAT(DVal, NotNull());
3608 
3609           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3610           ASSERT_THAT(FooDecl, NotNull());
3611 
3612           const auto *FooVal =
3613               dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
3614           ASSERT_THAT(FooVal, NotNull());
3615           auto &A = Env.arena();
3616           EXPECT_EQ(
3617               &FooVal->formula(),
3618               &A.makeAnd(A.makeAnd(A.makeAnd(AVal->formula(), BVal->formula()),
3619                                    CVal->formula()),
3620                          DVal->formula()));
3621         });
3622   }
3623 }
3624 
3625 TEST(TransferTest, AssignFromBoolNegation) {
3626   std::string Code = R"(
3627     void target() {
3628       bool Foo = true;
3629       bool Bar = !(Foo);
3630       // [[p]]
3631     }
3632   )";
3633   runDataflow(
3634       Code,
3635       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3636          ASTContext &ASTCtx) {
3637         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3638         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3639 
3640         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3641         ASSERT_THAT(FooDecl, NotNull());
3642 
3643         const auto *FooVal =
3644             dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
3645         ASSERT_THAT(FooVal, NotNull());
3646 
3647         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3648         ASSERT_THAT(BarDecl, NotNull());
3649 
3650         const auto *BarVal =
3651             dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
3652         ASSERT_THAT(BarVal, NotNull());
3653         auto &A = Env.arena();
3654         EXPECT_EQ(&BarVal->formula(), &A.makeNot(FooVal->formula()));
3655       });
3656 }
3657 
3658 TEST(TransferTest, BuiltinExpect) {
3659   std::string Code = R"(
3660     void target(long Foo) {
3661       long Bar = __builtin_expect(Foo, true);
3662       /*[[p]]*/
3663     }
3664   )";
3665   runDataflow(
3666       Code,
3667       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3668          ASTContext &ASTCtx) {
3669         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3670         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3671 
3672         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3673         ASSERT_THAT(FooDecl, NotNull());
3674 
3675         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3676         ASSERT_THAT(BarDecl, NotNull());
3677 
3678         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
3679       });
3680 }
3681 
3682 // `__builtin_expect` takes and returns a `long` argument, so other types
3683 // involve casts. This verifies that we identify the input and output in that
3684 // case.
3685 TEST(TransferTest, BuiltinExpectBoolArg) {
3686   std::string Code = R"(
3687     void target(bool Foo) {
3688       bool Bar = __builtin_expect(Foo, true);
3689       /*[[p]]*/
3690     }
3691   )";
3692   runDataflow(
3693       Code,
3694       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3695          ASTContext &ASTCtx) {
3696         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3697         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3698 
3699         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3700         ASSERT_THAT(FooDecl, NotNull());
3701 
3702         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3703         ASSERT_THAT(BarDecl, NotNull());
3704 
3705         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
3706       });
3707 }
3708 
3709 TEST(TransferTest, BuiltinUnreachable) {
3710   std::string Code = R"(
3711     void target(bool Foo) {
3712       bool Bar = false;
3713       if (Foo)
3714         Bar = Foo;
3715       else
3716         __builtin_unreachable();
3717       (void)0;
3718       /*[[p]]*/
3719     }
3720   )";
3721   runDataflow(
3722       Code,
3723       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3724          ASTContext &ASTCtx) {
3725         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3726         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3727 
3728         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3729         ASSERT_THAT(FooDecl, NotNull());
3730 
3731         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3732         ASSERT_THAT(BarDecl, NotNull());
3733 
3734         // `__builtin_unreachable` promises that the code is
3735         // unreachable, so the compiler treats the "then" branch as the
3736         // only possible predecessor of this statement.
3737         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
3738       });
3739 }
3740 
3741 TEST(TransferTest, BuiltinTrap) {
3742   std::string Code = R"(
3743     void target(bool Foo) {
3744       bool Bar = false;
3745       if (Foo)
3746         Bar = Foo;
3747       else
3748         __builtin_trap();
3749       (void)0;
3750       /*[[p]]*/
3751     }
3752   )";
3753   runDataflow(
3754       Code,
3755       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3756          ASTContext &ASTCtx) {
3757         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3758         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3759 
3760         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3761         ASSERT_THAT(FooDecl, NotNull());
3762 
3763         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3764         ASSERT_THAT(BarDecl, NotNull());
3765 
3766         // `__builtin_trap` ensures program termination, so only the
3767         // "then" branch is a predecessor of this statement.
3768         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
3769       });
3770 }
3771 
3772 TEST(TransferTest, BuiltinDebugTrap) {
3773   std::string Code = R"(
3774     void target(bool Foo) {
3775       bool Bar = false;
3776       if (Foo)
3777         Bar = Foo;
3778       else
3779         __builtin_debugtrap();
3780       (void)0;
3781       /*[[p]]*/
3782     }
3783   )";
3784   runDataflow(
3785       Code,
3786       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3787          ASTContext &ASTCtx) {
3788         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3789         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3790 
3791         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3792         ASSERT_THAT(FooDecl, NotNull());
3793 
3794         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3795         ASSERT_THAT(BarDecl, NotNull());
3796 
3797         // `__builtin_debugtrap` doesn't ensure program termination.
3798         EXPECT_NE(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
3799       });
3800 }
3801 
3802 TEST(TransferTest, StaticIntSingleVarDecl) {
3803   std::string Code = R"(
3804     void target() {
3805       static int Foo;
3806       // [[p]]
3807     }
3808   )";
3809   runDataflow(
3810       Code,
3811       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3812          ASTContext &ASTCtx) {
3813         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3814         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3815 
3816         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3817         ASSERT_THAT(FooDecl, NotNull());
3818 
3819         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
3820         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
3821 
3822         const Value *FooVal = Env.getValue(*FooLoc);
3823         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
3824       });
3825 }
3826 
3827 TEST(TransferTest, StaticIntGroupVarDecl) {
3828   std::string Code = R"(
3829     void target() {
3830       static int Foo, Bar;
3831       (void)0;
3832       // [[p]]
3833     }
3834   )";
3835   runDataflow(
3836       Code,
3837       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3838          ASTContext &ASTCtx) {
3839         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3840         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3841 
3842         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3843         ASSERT_THAT(FooDecl, NotNull());
3844 
3845         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3846         ASSERT_THAT(BarDecl, NotNull());
3847 
3848         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
3849         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
3850 
3851         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
3852         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
3853 
3854         const Value *FooVal = Env.getValue(*FooLoc);
3855         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
3856 
3857         const Value *BarVal = Env.getValue(*BarLoc);
3858         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
3859 
3860         EXPECT_NE(FooVal, BarVal);
3861       });
3862 }
3863 
3864 TEST(TransferTest, GlobalIntVarDecl) {
3865   std::string Code = R"(
3866     static int Foo;
3867 
3868     void target() {
3869       int Bar = Foo;
3870       int Baz = Foo;
3871       // [[p]]
3872     }
3873   )";
3874   runDataflow(
3875       Code,
3876       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3877          ASTContext &ASTCtx) {
3878         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3879         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3880 
3881         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3882         ASSERT_THAT(BarDecl, NotNull());
3883 
3884         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3885         ASSERT_THAT(BazDecl, NotNull());
3886 
3887         const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
3888         const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl));
3889         EXPECT_EQ(BarVal, BazVal);
3890       });
3891 }
3892 
3893 TEST(TransferTest, StaticMemberIntVarDecl) {
3894   std::string Code = R"(
3895     struct A {
3896       static int Foo;
3897     };
3898 
3899     void target(A a) {
3900       int Bar = a.Foo;
3901       int Baz = a.Foo;
3902       // [[p]]
3903     }
3904   )";
3905   runDataflow(
3906       Code,
3907       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3908          ASTContext &ASTCtx) {
3909         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3910         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3911 
3912         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3913         ASSERT_THAT(BarDecl, NotNull());
3914 
3915         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3916         ASSERT_THAT(BazDecl, NotNull());
3917 
3918         const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
3919         const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl));
3920         EXPECT_EQ(BarVal, BazVal);
3921       });
3922 }
3923 
3924 TEST(TransferTest, StaticMemberRefVarDecl) {
3925   std::string Code = R"(
3926     struct A {
3927       static int &Foo;
3928     };
3929 
3930     void target(A a) {
3931       int Bar = a.Foo;
3932       int Baz = a.Foo;
3933       // [[p]]
3934     }
3935   )";
3936   runDataflow(
3937       Code,
3938       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3939          ASTContext &ASTCtx) {
3940         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3941         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3942 
3943         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3944         ASSERT_THAT(BarDecl, NotNull());
3945 
3946         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3947         ASSERT_THAT(BazDecl, NotNull());
3948 
3949         const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
3950         const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl));
3951         EXPECT_EQ(BarVal, BazVal);
3952       });
3953 }
3954 
3955 TEST(TransferTest, AssignMemberBeforeCopy) {
3956   std::string Code = R"(
3957     struct A {
3958       int Foo;
3959     };
3960 
3961     void target() {
3962       A A1;
3963       A A2;
3964       int Bar;
3965       A1.Foo = Bar;
3966       A2 = A1;
3967       // [[p]]
3968     }
3969   )";
3970   runDataflow(
3971       Code,
3972       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3973          ASTContext &ASTCtx) {
3974         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3975         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3976 
3977         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3978         ASSERT_THAT(FooDecl, NotNull());
3979 
3980         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3981         ASSERT_THAT(BarDecl, NotNull());
3982 
3983         const ValueDecl *A1Decl = findValueDecl(ASTCtx, "A1");
3984         ASSERT_THAT(A1Decl, NotNull());
3985 
3986         const ValueDecl *A2Decl = findValueDecl(ASTCtx, "A2");
3987         ASSERT_THAT(A2Decl, NotNull());
3988 
3989         const auto *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
3990 
3991         const auto &A2Loc =
3992             *cast<RecordStorageLocation>(Env.getStorageLocation(*A2Decl));
3993         EXPECT_EQ(getFieldValue(&A2Loc, *FooDecl, Env), BarVal);
3994       });
3995 }
3996 
3997 TEST(TransferTest, BooleanEquality) {
3998   std::string Code = R"(
3999     void target(bool Bar) {
4000       bool Foo = true;
4001       if (Bar == Foo) {
4002         (void)0;
4003         /*[[p-then]]*/
4004       } else {
4005         (void)0;
4006         /*[[p-else]]*/
4007       }
4008     }
4009   )";
4010   runDataflow(
4011       Code,
4012       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4013          ASTContext &ASTCtx) {
4014         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-then", "p-else"));
4015         const Environment &EnvThen =
4016             getEnvironmentAtAnnotation(Results, "p-then");
4017         const Environment &EnvElse =
4018             getEnvironmentAtAnnotation(Results, "p-else");
4019 
4020         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4021         ASSERT_THAT(BarDecl, NotNull());
4022 
4023         auto &BarValThen = getFormula(*BarDecl, EnvThen);
4024         EXPECT_TRUE(EnvThen.proves(BarValThen));
4025 
4026         auto &BarValElse = getFormula(*BarDecl, EnvElse);
4027         EXPECT_TRUE(EnvElse.proves(EnvElse.arena().makeNot(BarValElse)));
4028       });
4029 }
4030 
4031 TEST(TransferTest, BooleanInequality) {
4032   std::string Code = R"(
4033     void target(bool Bar) {
4034       bool Foo = true;
4035       if (Bar != Foo) {
4036         (void)0;
4037         /*[[p-then]]*/
4038       } else {
4039         (void)0;
4040         /*[[p-else]]*/
4041       }
4042     }
4043   )";
4044   runDataflow(
4045       Code,
4046       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4047          ASTContext &ASTCtx) {
4048         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-then", "p-else"));
4049         const Environment &EnvThen =
4050             getEnvironmentAtAnnotation(Results, "p-then");
4051         const Environment &EnvElse =
4052             getEnvironmentAtAnnotation(Results, "p-else");
4053 
4054         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4055         ASSERT_THAT(BarDecl, NotNull());
4056 
4057         auto &BarValThen = getFormula(*BarDecl, EnvThen);
4058         EXPECT_TRUE(EnvThen.proves(EnvThen.arena().makeNot(BarValThen)));
4059 
4060         auto &BarValElse = getFormula(*BarDecl, EnvElse);
4061         EXPECT_TRUE(EnvElse.proves(BarValElse));
4062       });
4063 }
4064 
4065 TEST(TransferTest, IntegerLiteralEquality) {
4066   std::string Code = R"(
4067     void target() {
4068       bool equal = (42 == 42);
4069       // [[p]]
4070     }
4071   )";
4072   runDataflow(
4073       Code,
4074       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4075          ASTContext &ASTCtx) {
4076         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4077 
4078         auto &Equal =
4079             getValueForDecl<BoolValue>(ASTCtx, Env, "equal").formula();
4080         EXPECT_TRUE(Env.proves(Equal));
4081       });
4082 }
4083 
4084 TEST(TransferTest, CorrelatedBranches) {
4085   std::string Code = R"(
4086     void target(bool B, bool C) {
4087       if (B) {
4088         return;
4089       }
4090       (void)0;
4091       /*[[p0]]*/
4092       if (C) {
4093         B = true;
4094         /*[[p1]]*/
4095       }
4096       if (B) {
4097         (void)0;
4098         /*[[p2]]*/
4099       }
4100     }
4101   )";
4102   runDataflow(
4103       Code,
4104       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4105          ASTContext &ASTCtx) {
4106         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p0", "p1", "p2"));
4107 
4108         const ValueDecl *CDecl = findValueDecl(ASTCtx, "C");
4109         ASSERT_THAT(CDecl, NotNull());
4110 
4111         {
4112           const Environment &Env = getEnvironmentAtAnnotation(Results, "p0");
4113           const ValueDecl *BDecl = findValueDecl(ASTCtx, "B");
4114           ASSERT_THAT(BDecl, NotNull());
4115           auto &BVal = getFormula(*BDecl, Env);
4116 
4117           EXPECT_TRUE(Env.proves(Env.arena().makeNot(BVal)));
4118         }
4119 
4120         {
4121           const Environment &Env = getEnvironmentAtAnnotation(Results, "p1");
4122           auto &CVal = getFormula(*CDecl, Env);
4123           EXPECT_TRUE(Env.proves(CVal));
4124         }
4125 
4126         {
4127           const Environment &Env = getEnvironmentAtAnnotation(Results, "p2");
4128           auto &CVal = getFormula(*CDecl, Env);
4129           EXPECT_TRUE(Env.proves(CVal));
4130         }
4131       });
4132 }
4133 
4134 TEST(TransferTest, LoopWithAssignmentConverges) {
4135   std::string Code = R"(
4136     bool foo();
4137 
4138     void target() {
4139        do {
4140         bool Bar = foo();
4141         if (Bar) break;
4142         (void)Bar;
4143         /*[[p]]*/
4144       } while (true);
4145     }
4146   )";
4147   // The key property that we are verifying is implicit in `runDataflow` --
4148   // namely, that the analysis succeeds, rather than hitting the maximum number
4149   // of iterations.
4150   runDataflow(
4151       Code,
4152       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4153          ASTContext &ASTCtx) {
4154         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4155         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4156 
4157         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4158         ASSERT_THAT(BarDecl, NotNull());
4159 
4160         auto &BarVal = getFormula(*BarDecl, Env);
4161         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BarVal)));
4162       });
4163 }
4164 
4165 TEST(TransferTest, LoopWithStagedAssignments) {
4166   std::string Code = R"(
4167     bool foo();
4168 
4169     void target() {
4170       bool Bar = false;
4171       bool Err = false;
4172       while (foo()) {
4173         if (Bar)
4174           Err = true;
4175         Bar = true;
4176         /*[[p]]*/
4177       }
4178     }
4179   )";
4180   runDataflow(
4181       Code,
4182       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4183          ASTContext &ASTCtx) {
4184         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4185         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4186 
4187         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4188         ASSERT_THAT(BarDecl, NotNull());
4189         const ValueDecl *ErrDecl = findValueDecl(ASTCtx, "Err");
4190         ASSERT_THAT(ErrDecl, NotNull());
4191 
4192         auto &BarVal = getFormula(*BarDecl, Env);
4193         auto &ErrVal = getFormula(*ErrDecl, Env);
4194         EXPECT_TRUE(Env.proves(BarVal));
4195         // An unsound analysis, for example only evaluating the loop once, can
4196         // conclude that `Err` is false. So, we test that this conclusion is not
4197         // reached.
4198         EXPECT_FALSE(Env.proves(Env.arena().makeNot(ErrVal)));
4199       });
4200 }
4201 
4202 TEST(TransferTest, LoopWithReferenceAssignmentConverges) {
4203   std::string Code = R"(
4204     bool &foo();
4205 
4206     void target() {
4207        do {
4208         bool& Bar = foo();
4209         if (Bar) break;
4210         (void)Bar;
4211         /*[[p]]*/
4212       } while (true);
4213     }
4214   )";
4215   // The key property that we are verifying is that the analysis succeeds,
4216   // rather than hitting the maximum number of iterations.
4217   runDataflow(
4218       Code,
4219       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4220          ASTContext &ASTCtx) {
4221         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4222         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4223 
4224         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4225         ASSERT_THAT(BarDecl, NotNull());
4226 
4227         auto &BarVal = getFormula(*BarDecl, Env);
4228         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BarVal)));
4229       });
4230 }
4231 
4232 TEST(TransferTest, LoopWithStructReferenceAssignmentConverges) {
4233   std::string Code = R"(
4234     struct Lookup {
4235       int x;
4236     };
4237 
4238     void target(Lookup val, bool b) {
4239       const Lookup* l = nullptr;
4240       while (b) {
4241         l = &val;
4242         /*[[p-inner]]*/
4243       }
4244       (void)0;
4245       /*[[p-outer]]*/
4246     }
4247   )";
4248   // The key property that we are verifying is implicit in `runDataflow` --
4249   // namely, that the analysis succeeds, rather than hitting the maximum number
4250   // of iterations.
4251   runDataflow(
4252       Code,
4253       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4254          ASTContext &ASTCtx) {
4255         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-inner", "p-outer"));
4256         const Environment &InnerEnv =
4257             getEnvironmentAtAnnotation(Results, "p-inner");
4258         const Environment &OuterEnv =
4259             getEnvironmentAtAnnotation(Results, "p-outer");
4260 
4261         const ValueDecl *ValDecl = findValueDecl(ASTCtx, "val");
4262         ASSERT_THAT(ValDecl, NotNull());
4263 
4264         const ValueDecl *LDecl = findValueDecl(ASTCtx, "l");
4265         ASSERT_THAT(LDecl, NotNull());
4266 
4267         // Inner.
4268         auto *LVal = dyn_cast<PointerValue>(InnerEnv.getValue(*LDecl));
4269         ASSERT_THAT(LVal, NotNull());
4270 
4271         EXPECT_EQ(&LVal->getPointeeLoc(),
4272                   InnerEnv.getStorageLocation(*ValDecl));
4273 
4274         // Outer.
4275         LVal = dyn_cast<PointerValue>(OuterEnv.getValue(*LDecl));
4276         ASSERT_THAT(LVal, NotNull());
4277 
4278         // The loop body may not have been executed, so we should not conclude
4279         // that `l` points to `val`.
4280         EXPECT_NE(&LVal->getPointeeLoc(),
4281                   OuterEnv.getStorageLocation(*ValDecl));
4282       });
4283 }
4284 
4285 TEST(TransferTest, LoopDereferencingChangingPointerConverges) {
4286   std::string Code = R"cc(
4287     bool some_condition();
4288 
4289     void target(int i1, int i2) {
4290       int *p = &i1;
4291       while (true) {
4292         (void)*p;
4293         if (some_condition())
4294           p = &i1;
4295         else
4296           p = &i2;
4297       }
4298     }
4299   )cc";
4300   ASSERT_THAT_ERROR(checkDataflowWithNoopAnalysis(Code), llvm::Succeeded());
4301 }
4302 
4303 TEST(TransferTest, LoopDereferencingChangingRecordPointerConverges) {
4304   std::string Code = R"cc(
4305     struct Lookup {
4306       int x;
4307     };
4308 
4309     bool some_condition();
4310 
4311     void target(Lookup l1, Lookup l2) {
4312       Lookup *l = &l1;
4313       while (true) {
4314         (void)l->x;
4315         if (some_condition())
4316           l = &l1;
4317         else
4318           l = &l2;
4319       }
4320     }
4321   )cc";
4322   ASSERT_THAT_ERROR(checkDataflowWithNoopAnalysis(Code), llvm::Succeeded());
4323 }
4324 
4325 TEST(TransferTest, LoopWithShortCircuitedConditionConverges) {
4326   std::string Code = R"cc(
4327     bool foo();
4328 
4329     void target() {
4330       bool c = false;
4331       while (foo() || foo()) {
4332         c = true;
4333       }
4334     }
4335   )cc";
4336   ASSERT_THAT_ERROR(checkDataflowWithNoopAnalysis(Code), llvm::Succeeded());
4337 }
4338 
4339 TEST(TransferTest, LoopCanProveInvariantForBoolean) {
4340   // Check that we can prove `b` is always false in the loop.
4341   // This test exercises the logic in `widenDistinctValues()` that preserves
4342   // information if the boolean can be proved to be either true or false in both
4343   // the previous and current iteration.
4344   std::string Code = R"cc(
4345     int return_int();
4346     void target() {
4347       bool b = return_int() == 0;
4348       if (b) return;
4349       while (true) {
4350         b;
4351         // [[p]]
4352         b = return_int() == 0;
4353         if (b) return;
4354       }
4355     }
4356   )cc";
4357   runDataflow(
4358       Code,
4359       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4360          ASTContext &ASTCtx) {
4361         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4362         auto &BVal = getValueForDecl<BoolValue>(ASTCtx, Env, "b");
4363         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BVal.formula())));
4364       });
4365 }
4366 
4367 TEST(TransferTest, DoesNotCrashOnUnionThisExpr) {
4368   std::string Code = R"(
4369     union Union {
4370       int A;
4371       float B;
4372     };
4373 
4374     void foo() {
4375       Union A;
4376       Union B;
4377       A = B;
4378     }
4379   )";
4380   // This is a crash regression test when calling the transfer function on a
4381   // `CXXThisExpr` that refers to a union.
4382   runDataflow(
4383       Code,
4384       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &,
4385          ASTContext &) {},
4386       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator=");
4387 }
4388 
4389 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToRefs) {
4390   std::string Code = R"(
4391     struct A {
4392       int Foo;
4393       int Bar;
4394     };
4395 
4396     void target() {
4397       int Qux;
4398       A Baz;
4399       Baz.Foo = Qux;
4400       auto &FooRef = Baz.Foo;
4401       auto &BarRef = Baz.Bar;
4402       auto &[BoundFooRef, BoundBarRef] = Baz;
4403       // [[p]]
4404     }
4405   )";
4406   runDataflow(
4407       Code,
4408       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4409          ASTContext &ASTCtx) {
4410         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4411         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4412 
4413         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
4414         ASSERT_THAT(FooRefDecl, NotNull());
4415 
4416         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
4417         ASSERT_THAT(BarRefDecl, NotNull());
4418 
4419         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
4420         ASSERT_THAT(QuxDecl, NotNull());
4421 
4422         const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef");
4423         ASSERT_THAT(BoundFooRefDecl, NotNull());
4424 
4425         const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef");
4426         ASSERT_THAT(BoundBarRefDecl, NotNull());
4427 
4428         const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl);
4429         ASSERT_THAT(FooRefLoc, NotNull());
4430 
4431         const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl);
4432         ASSERT_THAT(BarRefLoc, NotNull());
4433 
4434         const Value *QuxVal = Env.getValue(*QuxDecl);
4435         ASSERT_THAT(QuxVal, NotNull());
4436 
4437         const StorageLocation *BoundFooRefLoc =
4438             Env.getStorageLocation(*BoundFooRefDecl);
4439         EXPECT_EQ(BoundFooRefLoc, FooRefLoc);
4440 
4441         const StorageLocation *BoundBarRefLoc =
4442             Env.getStorageLocation(*BoundBarRefDecl);
4443         EXPECT_EQ(BoundBarRefLoc, BarRefLoc);
4444 
4445         EXPECT_EQ(Env.getValue(*BoundFooRefDecl), QuxVal);
4446       });
4447 }
4448 
4449 TEST(TransferTest, StructuredBindingAssignFromStructRefMembersToRefs) {
4450   std::string Code = R"(
4451     struct A {
4452       int &Foo;
4453       int &Bar;
4454     };
4455 
4456     void target(A Baz) {
4457       int Qux;
4458       Baz.Foo = Qux;
4459       auto &FooRef = Baz.Foo;
4460       auto &BarRef = Baz.Bar;
4461       auto &[BoundFooRef, BoundBarRef] = Baz;
4462       // [[p]]
4463     }
4464   )";
4465   runDataflow(
4466       Code,
4467       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4468          ASTContext &ASTCtx) {
4469         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4470         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4471 
4472         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
4473         ASSERT_THAT(FooRefDecl, NotNull());
4474 
4475         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
4476         ASSERT_THAT(BarRefDecl, NotNull());
4477 
4478         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
4479         ASSERT_THAT(QuxDecl, NotNull());
4480 
4481         const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef");
4482         ASSERT_THAT(BoundFooRefDecl, NotNull());
4483 
4484         const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef");
4485         ASSERT_THAT(BoundBarRefDecl, NotNull());
4486 
4487         const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl);
4488         ASSERT_THAT(FooRefLoc, NotNull());
4489 
4490         const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl);
4491         ASSERT_THAT(BarRefLoc, NotNull());
4492 
4493         const Value *QuxVal = Env.getValue(*QuxDecl);
4494         ASSERT_THAT(QuxVal, NotNull());
4495 
4496         const StorageLocation *BoundFooRefLoc =
4497             Env.getStorageLocation(*BoundFooRefDecl);
4498         EXPECT_EQ(BoundFooRefLoc, FooRefLoc);
4499 
4500         const StorageLocation *BoundBarRefLoc =
4501             Env.getStorageLocation(*BoundBarRefDecl);
4502         EXPECT_EQ(BoundBarRefLoc, BarRefLoc);
4503 
4504         EXPECT_EQ(Env.getValue(*BoundFooRefDecl), QuxVal);
4505       });
4506 }
4507 
4508 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToInts) {
4509   std::string Code = R"(
4510     struct A {
4511       int Foo;
4512       int Bar;
4513     };
4514 
4515     void target() {
4516       int Qux;
4517       A Baz;
4518       Baz.Foo = Qux;
4519       auto &FooRef = Baz.Foo;
4520       auto &BarRef = Baz.Bar;
4521       auto [BoundFoo, BoundBar] = Baz;
4522       // [[p]]
4523     }
4524   )";
4525   runDataflow(
4526       Code,
4527       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4528          ASTContext &ASTCtx) {
4529         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4530         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4531 
4532         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
4533         ASSERT_THAT(FooRefDecl, NotNull());
4534 
4535         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
4536         ASSERT_THAT(BarRefDecl, NotNull());
4537 
4538         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
4539         ASSERT_THAT(BoundFooDecl, NotNull());
4540 
4541         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
4542         ASSERT_THAT(BoundBarDecl, NotNull());
4543 
4544         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
4545         ASSERT_THAT(QuxDecl, NotNull());
4546 
4547         const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl);
4548         ASSERT_THAT(FooRefLoc, NotNull());
4549 
4550         const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl);
4551         ASSERT_THAT(BarRefLoc, NotNull());
4552 
4553         const Value *QuxVal = Env.getValue(*QuxDecl);
4554         ASSERT_THAT(QuxVal, NotNull());
4555 
4556         const StorageLocation *BoundFooLoc =
4557             Env.getStorageLocation(*BoundFooDecl);
4558         EXPECT_NE(BoundFooLoc, FooRefLoc);
4559 
4560         const StorageLocation *BoundBarLoc =
4561             Env.getStorageLocation(*BoundBarDecl);
4562         EXPECT_NE(BoundBarLoc, BarRefLoc);
4563 
4564         EXPECT_EQ(Env.getValue(*BoundFooDecl), QuxVal);
4565       });
4566 }
4567 
4568 TEST(TransferTest, StructuredBindingAssignFromTupleLikeType) {
4569   std::string Code = R"(
4570     namespace std {
4571     using size_t = int;
4572     template <class> struct tuple_size;
4573     template <std::size_t, class> struct tuple_element;
4574     template <class...> class tuple;
4575 
4576     namespace {
4577     template <class T, T v>
4578     struct size_helper { static const T value = v; };
4579     } // namespace
4580 
4581     template <class... T>
4582     struct tuple_size<tuple<T...>> : size_helper<std::size_t, sizeof...(T)> {};
4583 
4584     template <std::size_t I, class... T>
4585     struct tuple_element<I, tuple<T...>> {
4586       using type =  __type_pack_element<I, T...>;
4587     };
4588 
4589     template <class...> class tuple {};
4590 
4591     template <std::size_t I, class... T>
4592     typename tuple_element<I, tuple<T...>>::type get(tuple<T...>);
4593     } // namespace std
4594 
4595     std::tuple<bool, int> makeTuple();
4596 
4597     void target(bool B) {
4598       auto [BoundFoo, BoundBar] = makeTuple();
4599       bool Baz;
4600       // Include if-then-else to test interaction of `BindingDecl` with join.
4601       if (B) {
4602         Baz = BoundFoo;
4603         (void)BoundBar;
4604         // [[p1]]
4605       } else {
4606         Baz = BoundFoo;
4607       }
4608       (void)0;
4609       // [[p2]]
4610     }
4611   )";
4612   runDataflow(
4613       Code,
4614       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4615          ASTContext &ASTCtx) {
4616         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
4617         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
4618 
4619         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
4620         ASSERT_THAT(BoundFooDecl, NotNull());
4621 
4622         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
4623         ASSERT_THAT(BoundBarDecl, NotNull());
4624 
4625         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4626         ASSERT_THAT(BazDecl, NotNull());
4627 
4628         // BindingDecls always map to references -- either lvalue or rvalue, so
4629         // we still need to skip here.
4630         const Value *BoundFooValue = Env1.getValue(*BoundFooDecl);
4631         ASSERT_THAT(BoundFooValue, NotNull());
4632         EXPECT_TRUE(isa<BoolValue>(BoundFooValue));
4633 
4634         const Value *BoundBarValue = Env1.getValue(*BoundBarDecl);
4635         ASSERT_THAT(BoundBarValue, NotNull());
4636         EXPECT_TRUE(isa<IntegerValue>(BoundBarValue));
4637 
4638         // Test that a `DeclRefExpr` to a `BindingDecl` works as expected.
4639         EXPECT_EQ(Env1.getValue(*BazDecl), BoundFooValue);
4640 
4641         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
4642 
4643         // Test that `BoundFooDecl` retains the value we expect, after the join.
4644         BoundFooValue = Env2.getValue(*BoundFooDecl);
4645         EXPECT_EQ(Env2.getValue(*BazDecl), BoundFooValue);
4646       });
4647 }
4648 
4649 TEST(TransferTest, StructuredBindingAssignRefFromTupleLikeType) {
4650   std::string Code = R"(
4651     namespace std {
4652     using size_t = int;
4653     template <class> struct tuple_size;
4654     template <std::size_t, class> struct tuple_element;
4655     template <class...> class tuple;
4656 
4657     namespace {
4658     template <class T, T v>
4659     struct size_helper { static const T value = v; };
4660     } // namespace
4661 
4662     template <class... T>
4663     struct tuple_size<tuple<T...>> : size_helper<std::size_t, sizeof...(T)> {};
4664 
4665     template <std::size_t I, class... T>
4666     struct tuple_element<I, tuple<T...>> {
4667       using type =  __type_pack_element<I, T...>;
4668     };
4669 
4670     template <class...> class tuple {};
4671 
4672     template <std::size_t I, class... T>
4673     typename tuple_element<I, tuple<T...>>::type get(tuple<T...>);
4674     } // namespace std
4675 
4676     std::tuple<bool, int> &getTuple();
4677 
4678     void target(bool B) {
4679       auto &[BoundFoo, BoundBar] = getTuple();
4680       bool Baz;
4681       // Include if-then-else to test interaction of `BindingDecl` with join.
4682       if (B) {
4683         Baz = BoundFoo;
4684         (void)BoundBar;
4685         // [[p1]]
4686       } else {
4687         Baz = BoundFoo;
4688       }
4689       (void)0;
4690       // [[p2]]
4691     }
4692   )";
4693   runDataflow(
4694       Code,
4695       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4696          ASTContext &ASTCtx) {
4697         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
4698         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
4699 
4700         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
4701         ASSERT_THAT(BoundFooDecl, NotNull());
4702 
4703         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
4704         ASSERT_THAT(BoundBarDecl, NotNull());
4705 
4706         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4707         ASSERT_THAT(BazDecl, NotNull());
4708 
4709         const Value *BoundFooValue = Env1.getValue(*BoundFooDecl);
4710         ASSERT_THAT(BoundFooValue, NotNull());
4711         EXPECT_TRUE(isa<BoolValue>(BoundFooValue));
4712 
4713         const Value *BoundBarValue = Env1.getValue(*BoundBarDecl);
4714         ASSERT_THAT(BoundBarValue, NotNull());
4715         EXPECT_TRUE(isa<IntegerValue>(BoundBarValue));
4716 
4717         // Test that a `DeclRefExpr` to a `BindingDecl` (with reference type)
4718         // works as expected. We don't test aliasing properties of the
4719         // reference, because we don't model `std::get` and so have no way to
4720         // equate separate references into the tuple.
4721         EXPECT_EQ(Env1.getValue(*BazDecl), BoundFooValue);
4722 
4723         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
4724 
4725         // Test that `BoundFooDecl` retains the value we expect, after the join.
4726         BoundFooValue = Env2.getValue(*BoundFooDecl);
4727         EXPECT_EQ(Env2.getValue(*BazDecl), BoundFooValue);
4728       });
4729 }
4730 
4731 TEST(TransferTest, BinaryOperatorComma) {
4732   std::string Code = R"(
4733     void target(int Foo, int Bar) {
4734       int &Baz = (Foo, Bar);
4735       // [[p]]
4736     }
4737   )";
4738   runDataflow(
4739       Code,
4740       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4741          ASTContext &ASTCtx) {
4742         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4743         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4744 
4745         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4746         ASSERT_THAT(BarDecl, NotNull());
4747 
4748         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4749         ASSERT_THAT(BazDecl, NotNull());
4750 
4751         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
4752         ASSERT_THAT(BarLoc, NotNull());
4753 
4754         const StorageLocation *BazLoc = Env.getStorageLocation(*BazDecl);
4755         EXPECT_EQ(BazLoc, BarLoc);
4756       });
4757 }
4758 
4759 TEST(TransferTest, IfStmtBranchExtendsFlowCondition) {
4760   std::string Code = R"(
4761     void target(bool Foo) {
4762       if (Foo) {
4763         (void)0;
4764         // [[if_then]]
4765       } else {
4766         (void)0;
4767         // [[if_else]]
4768       }
4769     }
4770   )";
4771   runDataflow(
4772       Code,
4773       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4774          ASTContext &ASTCtx) {
4775         ASSERT_THAT(Results.keys(), UnorderedElementsAre("if_then", "if_else"));
4776         const Environment &ThenEnv =
4777             getEnvironmentAtAnnotation(Results, "if_then");
4778         const Environment &ElseEnv =
4779             getEnvironmentAtAnnotation(Results, "if_else");
4780 
4781         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4782         ASSERT_THAT(FooDecl, NotNull());
4783 
4784         auto &ThenFooVal= getFormula(*FooDecl, ThenEnv);
4785         EXPECT_TRUE(ThenEnv.proves(ThenFooVal));
4786 
4787         auto &ElseFooVal = getFormula(*FooDecl, ElseEnv);
4788         EXPECT_TRUE(ElseEnv.proves(ElseEnv.arena().makeNot(ElseFooVal)));
4789       });
4790 }
4791 
4792 TEST(TransferTest, WhileStmtBranchExtendsFlowCondition) {
4793   std::string Code = R"(
4794     void target(bool Foo) {
4795       while (Foo) {
4796         (void)0;
4797         // [[loop_body]]
4798       }
4799       (void)0;
4800       // [[after_loop]]
4801     }
4802   )";
4803   runDataflow(
4804       Code,
4805       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4806          ASTContext &ASTCtx) {
4807         ASSERT_THAT(Results.keys(),
4808                     UnorderedElementsAre("loop_body", "after_loop"));
4809         const Environment &LoopBodyEnv =
4810             getEnvironmentAtAnnotation(Results, "loop_body");
4811         const Environment &AfterLoopEnv =
4812             getEnvironmentAtAnnotation(Results, "after_loop");
4813 
4814         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4815         ASSERT_THAT(FooDecl, NotNull());
4816 
4817         auto &LoopBodyFooVal = getFormula(*FooDecl, LoopBodyEnv);
4818         EXPECT_TRUE(LoopBodyEnv.proves(LoopBodyFooVal));
4819 
4820         auto &AfterLoopFooVal = getFormula(*FooDecl, AfterLoopEnv);
4821         EXPECT_TRUE(
4822             AfterLoopEnv.proves(AfterLoopEnv.arena().makeNot(AfterLoopFooVal)));
4823       });
4824 }
4825 
4826 TEST(TransferTest, DoWhileStmtBranchExtendsFlowCondition) {
4827   std::string Code = R"(
4828     void target(bool Foo) {
4829       bool Bar = true;
4830       do {
4831         (void)0;
4832         // [[loop_body]]
4833         Bar = false;
4834       } while (Foo);
4835       (void)0;
4836       // [[after_loop]]
4837     }
4838   )";
4839   runDataflow(
4840       Code,
4841       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4842          ASTContext &ASTCtx) {
4843         ASSERT_THAT(Results.keys(),
4844                     UnorderedElementsAre("loop_body", "after_loop"));
4845         const Environment &LoopBodyEnv =
4846             getEnvironmentAtAnnotation(Results, "loop_body");
4847         const Environment &AfterLoopEnv =
4848             getEnvironmentAtAnnotation(Results, "after_loop");
4849         auto &A = AfterLoopEnv.arena();
4850 
4851         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4852         ASSERT_THAT(FooDecl, NotNull());
4853 
4854         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4855         ASSERT_THAT(BarDecl, NotNull());
4856 
4857         auto &LoopBodyFooVal= getFormula(*FooDecl, LoopBodyEnv);
4858         auto &LoopBodyBarVal = getFormula(*BarDecl, LoopBodyEnv);
4859         EXPECT_TRUE(
4860             LoopBodyEnv.proves(A.makeOr(LoopBodyBarVal, LoopBodyFooVal)));
4861 
4862         auto &AfterLoopFooVal = getFormula(*FooDecl, AfterLoopEnv);
4863         auto &AfterLoopBarVal = getFormula(*BarDecl, AfterLoopEnv);
4864         EXPECT_TRUE(AfterLoopEnv.proves(A.makeNot(AfterLoopFooVal)));
4865         EXPECT_TRUE(AfterLoopEnv.proves(A.makeNot(AfterLoopBarVal)));
4866       });
4867 }
4868 
4869 TEST(TransferTest, ForStmtBranchExtendsFlowCondition) {
4870   std::string Code = R"(
4871     void target(bool Foo) {
4872       for (; Foo;) {
4873         (void)0;
4874         // [[loop_body]]
4875       }
4876       (void)0;
4877       // [[after_loop]]
4878     }
4879   )";
4880   runDataflow(
4881       Code,
4882       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4883          ASTContext &ASTCtx) {
4884         ASSERT_THAT(Results.keys(),
4885                     UnorderedElementsAre("loop_body", "after_loop"));
4886         const Environment &LoopBodyEnv =
4887             getEnvironmentAtAnnotation(Results, "loop_body");
4888         const Environment &AfterLoopEnv =
4889             getEnvironmentAtAnnotation(Results, "after_loop");
4890 
4891         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4892         ASSERT_THAT(FooDecl, NotNull());
4893 
4894         auto &LoopBodyFooVal= getFormula(*FooDecl, LoopBodyEnv);
4895         EXPECT_TRUE(LoopBodyEnv.proves(LoopBodyFooVal));
4896 
4897         auto &AfterLoopFooVal = getFormula(*FooDecl, AfterLoopEnv);
4898         EXPECT_TRUE(
4899             AfterLoopEnv.proves(AfterLoopEnv.arena().makeNot(AfterLoopFooVal)));
4900       });
4901 }
4902 
4903 TEST(TransferTest, ForStmtBranchWithoutConditionDoesNotExtendFlowCondition) {
4904   std::string Code = R"(
4905     void target(bool Foo) {
4906       for (;;) {
4907         (void)0;
4908         // [[loop_body]]
4909       }
4910     }
4911   )";
4912   runDataflow(
4913       Code,
4914       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4915          ASTContext &ASTCtx) {
4916         ASSERT_THAT(Results.keys(), UnorderedElementsAre("loop_body"));
4917         const Environment &LoopBodyEnv =
4918             getEnvironmentAtAnnotation(Results, "loop_body");
4919 
4920         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4921         ASSERT_THAT(FooDecl, NotNull());
4922 
4923         auto &LoopBodyFooVal= getFormula(*FooDecl, LoopBodyEnv);
4924         EXPECT_FALSE(LoopBodyEnv.proves(LoopBodyFooVal));
4925       });
4926 }
4927 
4928 TEST(TransferTest, ContextSensitiveOptionDisabled) {
4929   std::string Code = R"(
4930     bool GiveBool();
4931     void SetBool(bool &Var) { Var = true; }
4932 
4933     void target() {
4934       bool Foo = GiveBool();
4935       SetBool(Foo);
4936       // [[p]]
4937     }
4938   )";
4939   runDataflow(
4940       Code,
4941       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4942          ASTContext &ASTCtx) {
4943         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4944         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4945 
4946         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4947         ASSERT_THAT(FooDecl, NotNull());
4948 
4949         auto &FooVal = getFormula(*FooDecl, Env);
4950         EXPECT_FALSE(Env.proves(FooVal));
4951         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
4952       },
4953       {BuiltinOptions{/*.ContextSensitiveOpts=*/std::nullopt}});
4954 }
4955 
4956 TEST(TransferTest, ContextSensitiveReturnReference) {
4957   std::string Code = R"(
4958     class S {};
4959     S& target(bool b, S &s) {
4960       return s;
4961       // [[p]]
4962     }
4963   )";
4964   runDataflow(
4965       Code,
4966       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4967          ASTContext &ASTCtx) {
4968         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4969 
4970         const ValueDecl *SDecl = findValueDecl(ASTCtx, "s");
4971         ASSERT_THAT(SDecl, NotNull());
4972 
4973         auto *SLoc = Env.getStorageLocation(*SDecl);
4974         ASSERT_THAT(SLoc, NotNull());
4975 
4976         ASSERT_THAT(Env.getReturnStorageLocation(), Eq(SLoc));
4977       },
4978       {BuiltinOptions{ContextSensitiveOptions{}}});
4979 }
4980 
4981 // This test is a regression test, based on a real crash.
4982 TEST(TransferTest, ContextSensitiveReturnReferenceWithConditionalOperator) {
4983   std::string Code = R"(
4984     class S {};
4985     S& target(bool b, S &s) {
4986       return b ? s : s;
4987       // [[p]]
4988     }
4989   )";
4990   runDataflow(
4991       Code,
4992       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4993          ASTContext &ASTCtx) {
4994         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4995         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4996 
4997         const ValueDecl *SDecl = findValueDecl(ASTCtx, "s");
4998         ASSERT_THAT(SDecl, NotNull());
4999 
5000         auto *SLoc = Env.getStorageLocation(*SDecl);
5001         ASSERT_THAT(SLoc, NotNull());
5002         EXPECT_THAT(Env.getValue(*SLoc), NotNull());
5003 
5004         auto *Loc = Env.getReturnStorageLocation();
5005         ASSERT_THAT(Loc, NotNull());
5006         EXPECT_THAT(Env.getValue(*Loc), NotNull());
5007 
5008         // TODO: We would really like to make this stronger assertion, but that
5009         // doesn't work because we don't propagate values correctly through
5010         // the conditional operator yet.
5011         // ASSERT_THAT(Loc, Eq(SLoc));
5012       },
5013       {BuiltinOptions{ContextSensitiveOptions{}}});
5014 }
5015 
5016 TEST(TransferTest, ContextSensitiveReturnOneOfTwoReferences) {
5017   std::string Code = R"(
5018     class S {};
5019     S &callee(bool b, S &s1_parm, S &s2_parm) {
5020       if (b)
5021         return s1_parm;
5022       else
5023         return s2_parm;
5024     }
5025     void target(bool b) {
5026       S s1;
5027       S s2;
5028       S &return_s1 = s1;
5029       S &return_s2 = s2;
5030       S &return_dont_know = callee(b, s1, s2);
5031       // [[p]]
5032     }
5033   )";
5034   runDataflow(
5035       Code,
5036       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5037          ASTContext &ASTCtx) {
5038         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5039 
5040         const ValueDecl *S1 = findValueDecl(ASTCtx, "s1");
5041         ASSERT_THAT(S1, NotNull());
5042         const ValueDecl *S2 = findValueDecl(ASTCtx, "s2");
5043         ASSERT_THAT(S2, NotNull());
5044         const ValueDecl *ReturnS1 = findValueDecl(ASTCtx, "return_s1");
5045         ASSERT_THAT(ReturnS1, NotNull());
5046         const ValueDecl *ReturnS2 = findValueDecl(ASTCtx, "return_s2");
5047         ASSERT_THAT(ReturnS2, NotNull());
5048         const ValueDecl *ReturnDontKnow =
5049             findValueDecl(ASTCtx, "return_dont_know");
5050         ASSERT_THAT(ReturnDontKnow, NotNull());
5051 
5052         StorageLocation *S1Loc = Env.getStorageLocation(*S1);
5053         StorageLocation *S2Loc = Env.getStorageLocation(*S2);
5054 
5055         EXPECT_THAT(Env.getStorageLocation(*ReturnS1), Eq(S1Loc));
5056         EXPECT_THAT(Env.getStorageLocation(*ReturnS2), Eq(S2Loc));
5057 
5058         // In the case where we don't have a consistent storage location for
5059         // the return value, the framework creates a new storage location, which
5060         // should be different from the storage locations of `s1` and `s2`.
5061         EXPECT_THAT(Env.getStorageLocation(*ReturnDontKnow), Ne(S1Loc));
5062         EXPECT_THAT(Env.getStorageLocation(*ReturnDontKnow), Ne(S2Loc));
5063       },
5064       {BuiltinOptions{ContextSensitiveOptions{}}});
5065 }
5066 
5067 TEST(TransferTest, ContextSensitiveDepthZero) {
5068   std::string Code = R"(
5069     bool GiveBool();
5070     void SetBool(bool &Var) { Var = true; }
5071 
5072     void target() {
5073       bool Foo = GiveBool();
5074       SetBool(Foo);
5075       // [[p]]
5076     }
5077   )";
5078   runDataflow(
5079       Code,
5080       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5081          ASTContext &ASTCtx) {
5082         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5083         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5084 
5085         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5086         ASSERT_THAT(FooDecl, NotNull());
5087 
5088         auto &FooVal = getFormula(*FooDecl, Env);
5089         EXPECT_FALSE(Env.proves(FooVal));
5090         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
5091       },
5092       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/0}}});
5093 }
5094 
5095 TEST(TransferTest, ContextSensitiveSetTrue) {
5096   std::string Code = R"(
5097     bool GiveBool();
5098     void SetBool(bool &Var) { Var = true; }
5099 
5100     void target() {
5101       bool Foo = GiveBool();
5102       SetBool(Foo);
5103       // [[p]]
5104     }
5105   )";
5106   runDataflow(
5107       Code,
5108       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5109          ASTContext &ASTCtx) {
5110         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5111         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5112 
5113         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5114         ASSERT_THAT(FooDecl, NotNull());
5115 
5116         auto &FooVal = getFormula(*FooDecl, Env);
5117         EXPECT_TRUE(Env.proves(FooVal));
5118       },
5119       {BuiltinOptions{ContextSensitiveOptions{}}});
5120 }
5121 
5122 TEST(TransferTest, ContextSensitiveSetFalse) {
5123   std::string Code = R"(
5124     bool GiveBool();
5125     void SetBool(bool &Var) { Var = false; }
5126 
5127     void target() {
5128       bool Foo = GiveBool();
5129       SetBool(Foo);
5130       // [[p]]
5131     }
5132   )";
5133   runDataflow(
5134       Code,
5135       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5136          ASTContext &ASTCtx) {
5137         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5138         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5139 
5140         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5141         ASSERT_THAT(FooDecl, NotNull());
5142 
5143         auto &FooVal = getFormula(*FooDecl, Env);
5144         EXPECT_TRUE(Env.proves(Env.arena().makeNot(FooVal)));
5145       },
5146       {BuiltinOptions{ContextSensitiveOptions{}}});
5147 }
5148 
5149 TEST(TransferTest, ContextSensitiveSetBothTrueAndFalse) {
5150   std::string Code = R"(
5151     bool GiveBool();
5152     void SetBool(bool &Var, bool Val) { Var = Val; }
5153 
5154     void target() {
5155       bool Foo = GiveBool();
5156       bool Bar = GiveBool();
5157       SetBool(Foo, true);
5158       SetBool(Bar, false);
5159       // [[p]]
5160     }
5161   )";
5162   runDataflow(
5163       Code,
5164       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5165          ASTContext &ASTCtx) {
5166         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5167         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5168         auto &A = Env.arena();
5169 
5170         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5171         ASSERT_THAT(FooDecl, NotNull());
5172 
5173         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
5174         ASSERT_THAT(BarDecl, NotNull());
5175 
5176         auto &FooVal = getFormula(*FooDecl, Env);
5177         EXPECT_TRUE(Env.proves(FooVal));
5178         EXPECT_FALSE(Env.proves(A.makeNot(FooVal)));
5179 
5180         auto &BarVal = getFormula(*BarDecl, Env);
5181         EXPECT_FALSE(Env.proves(BarVal));
5182         EXPECT_TRUE(Env.proves(A.makeNot(BarVal)));
5183       },
5184       {BuiltinOptions{ContextSensitiveOptions{}}});
5185 }
5186 
5187 TEST(TransferTest, ContextSensitiveSetTwoLayersDepthOne) {
5188   std::string Code = R"(
5189     bool GiveBool();
5190     void SetBool1(bool &Var) { Var = true; }
5191     void SetBool2(bool &Var) { SetBool1(Var); }
5192 
5193     void target() {
5194       bool Foo = GiveBool();
5195       SetBool2(Foo);
5196       // [[p]]
5197     }
5198   )";
5199   runDataflow(
5200       Code,
5201       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5202          ASTContext &ASTCtx) {
5203         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5204         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5205 
5206         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5207         ASSERT_THAT(FooDecl, NotNull());
5208 
5209         auto &FooVal = getFormula(*FooDecl, Env);
5210         EXPECT_FALSE(Env.proves(FooVal));
5211         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
5212       },
5213       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/1}}});
5214 }
5215 
5216 TEST(TransferTest, ContextSensitiveSetTwoLayersDepthTwo) {
5217   std::string Code = R"(
5218     bool GiveBool();
5219     void SetBool1(bool &Var) { Var = true; }
5220     void SetBool2(bool &Var) { SetBool1(Var); }
5221 
5222     void target() {
5223       bool Foo = GiveBool();
5224       SetBool2(Foo);
5225       // [[p]]
5226     }
5227   )";
5228   runDataflow(
5229       Code,
5230       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5231          ASTContext &ASTCtx) {
5232         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5233         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5234 
5235         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5236         ASSERT_THAT(FooDecl, NotNull());
5237 
5238         auto &FooVal = getFormula(*FooDecl, Env);
5239         EXPECT_TRUE(Env.proves(FooVal));
5240       },
5241       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/2}}});
5242 }
5243 
5244 TEST(TransferTest, ContextSensitiveSetThreeLayersDepthTwo) {
5245   std::string Code = R"(
5246     bool GiveBool();
5247     void SetBool1(bool &Var) { Var = true; }
5248     void SetBool2(bool &Var) { SetBool1(Var); }
5249     void SetBool3(bool &Var) { SetBool2(Var); }
5250 
5251     void target() {
5252       bool Foo = GiveBool();
5253       SetBool3(Foo);
5254       // [[p]]
5255     }
5256   )";
5257   runDataflow(
5258       Code,
5259       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5260          ASTContext &ASTCtx) {
5261         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5262         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5263 
5264         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5265         ASSERT_THAT(FooDecl, NotNull());
5266 
5267         auto &FooVal = getFormula(*FooDecl, Env);
5268         EXPECT_FALSE(Env.proves(FooVal));
5269         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
5270       },
5271       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/2}}});
5272 }
5273 
5274 TEST(TransferTest, ContextSensitiveSetThreeLayersDepthThree) {
5275   std::string Code = R"(
5276     bool GiveBool();
5277     void SetBool1(bool &Var) { Var = true; }
5278     void SetBool2(bool &Var) { SetBool1(Var); }
5279     void SetBool3(bool &Var) { SetBool2(Var); }
5280 
5281     void target() {
5282       bool Foo = GiveBool();
5283       SetBool3(Foo);
5284       // [[p]]
5285     }
5286   )";
5287   runDataflow(
5288       Code,
5289       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5290          ASTContext &ASTCtx) {
5291         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5292         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5293 
5294         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5295         ASSERT_THAT(FooDecl, NotNull());
5296 
5297         auto &FooVal = getFormula(*FooDecl, Env);
5298         EXPECT_TRUE(Env.proves(FooVal));
5299       },
5300       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/3}}});
5301 }
5302 
5303 TEST(TransferTest, ContextSensitiveMutualRecursion) {
5304   std::string Code = R"(
5305     bool Pong(bool X, bool Y);
5306 
5307     bool Ping(bool X, bool Y) {
5308       if (X) {
5309         return Y;
5310       } else {
5311         return Pong(!X, Y);
5312       }
5313     }
5314 
5315     bool Pong(bool X, bool Y) {
5316       if (Y) {
5317         return X;
5318       } else {
5319         return Ping(X, !Y);
5320       }
5321     }
5322 
5323     void target() {
5324       bool Foo = Ping(false, false);
5325       // [[p]]
5326     }
5327   )";
5328   runDataflow(
5329       Code,
5330       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5331          ASTContext &ASTCtx) {
5332         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5333         // The analysis doesn't crash...
5334         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5335 
5336         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5337         ASSERT_THAT(FooDecl, NotNull());
5338 
5339         auto &FooVal = getFormula(*FooDecl, Env);
5340         // ... but it also can't prove anything here.
5341         EXPECT_FALSE(Env.proves(FooVal));
5342         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
5343       },
5344       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/4}}});
5345 }
5346 
5347 TEST(TransferTest, ContextSensitiveSetMultipleLines) {
5348   std::string Code = R"(
5349     void SetBools(bool &Var1, bool &Var2) {
5350       Var1 = true;
5351       Var2 = false;
5352     }
5353 
5354     void target() {
5355       bool Foo = false;
5356       bool Bar = true;
5357       SetBools(Foo, Bar);
5358       // [[p]]
5359     }
5360   )";
5361   runDataflow(
5362       Code,
5363       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5364          ASTContext &ASTCtx) {
5365         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5366         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5367 
5368         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5369         ASSERT_THAT(FooDecl, NotNull());
5370 
5371         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
5372         ASSERT_THAT(BarDecl, NotNull());
5373 
5374         auto &FooVal = getFormula(*FooDecl, Env);
5375         EXPECT_TRUE(Env.proves(FooVal));
5376         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
5377 
5378         auto &BarVal = getFormula(*BarDecl, Env);
5379         EXPECT_FALSE(Env.proves(BarVal));
5380         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BarVal)));
5381       },
5382       {BuiltinOptions{ContextSensitiveOptions{}}});
5383 }
5384 
5385 TEST(TransferTest, ContextSensitiveSetMultipleBlocks) {
5386   std::string Code = R"(
5387     void IfCond(bool Cond, bool &Then, bool &Else) {
5388       if (Cond) {
5389         Then = true;
5390       } else {
5391         Else = true;
5392       }
5393     }
5394 
5395     void target() {
5396       bool Foo = false;
5397       bool Bar = false;
5398       bool Baz = false;
5399       IfCond(Foo, Bar, Baz);
5400       // [[p]]
5401     }
5402   )";
5403   runDataflow(
5404       Code,
5405       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5406          ASTContext &ASTCtx) {
5407         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5408         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5409 
5410         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
5411         ASSERT_THAT(BarDecl, NotNull());
5412 
5413         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
5414         ASSERT_THAT(BazDecl, NotNull());
5415 
5416         auto &BarVal = getFormula(*BarDecl, Env);
5417         EXPECT_FALSE(Env.proves(BarVal));
5418         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BarVal)));
5419 
5420         auto &BazVal = getFormula(*BazDecl, Env);
5421         EXPECT_TRUE(Env.proves(BazVal));
5422         EXPECT_FALSE(Env.proves(Env.arena().makeNot(BazVal)));
5423       },
5424       {BuiltinOptions{ContextSensitiveOptions{}}});
5425 }
5426 
5427 TEST(TransferTest, ContextSensitiveReturnVoid) {
5428   std::string Code = R"(
5429     void Noop() { return; }
5430 
5431     void target() {
5432       Noop();
5433       // [[p]]
5434     }
5435   )";
5436   runDataflow(
5437       Code,
5438       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5439          ASTContext &ASTCtx) {
5440         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5441         // This just tests that the analysis doesn't crash.
5442       },
5443       {BuiltinOptions{ContextSensitiveOptions{}}});
5444 }
5445 
5446 TEST(TransferTest, ContextSensitiveReturnTrue) {
5447   std::string Code = R"(
5448     bool GiveBool() { return true; }
5449 
5450     void target() {
5451       bool Foo = GiveBool();
5452       // [[p]]
5453     }
5454   )";
5455   runDataflow(
5456       Code,
5457       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5458          ASTContext &ASTCtx) {
5459         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5460         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5461 
5462         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5463         ASSERT_THAT(FooDecl, NotNull());
5464 
5465         auto &FooVal = getFormula(*FooDecl, Env);
5466         EXPECT_TRUE(Env.proves(FooVal));
5467       },
5468       {BuiltinOptions{ContextSensitiveOptions{}}});
5469 }
5470 
5471 TEST(TransferTest, ContextSensitiveReturnFalse) {
5472   std::string Code = R"(
5473     bool GiveBool() { return false; }
5474 
5475     void target() {
5476       bool Foo = GiveBool();
5477       // [[p]]
5478     }
5479   )";
5480   runDataflow(
5481       Code,
5482       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5483          ASTContext &ASTCtx) {
5484         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5485         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5486 
5487         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5488         ASSERT_THAT(FooDecl, NotNull());
5489 
5490         auto &FooVal = getFormula(*FooDecl, Env);
5491         EXPECT_TRUE(Env.proves(Env.arena().makeNot(FooVal)));
5492       },
5493       {BuiltinOptions{ContextSensitiveOptions{}}});
5494 }
5495 
5496 TEST(TransferTest, ContextSensitiveReturnArg) {
5497   std::string Code = R"(
5498     bool GiveBool();
5499     bool GiveBack(bool Arg) { return Arg; }
5500 
5501     void target() {
5502       bool Foo = GiveBool();
5503       bool Bar = GiveBack(Foo);
5504       bool Baz = Foo == Bar;
5505       // [[p]]
5506     }
5507   )";
5508   runDataflow(
5509       Code,
5510       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5511          ASTContext &ASTCtx) {
5512         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5513         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5514 
5515         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
5516         ASSERT_THAT(BazDecl, NotNull());
5517 
5518         auto &BazVal = getFormula(*BazDecl, Env);
5519         EXPECT_TRUE(Env.proves(BazVal));
5520       },
5521       {BuiltinOptions{ContextSensitiveOptions{}}});
5522 }
5523 
5524 TEST(TransferTest, ContextSensitiveReturnInt) {
5525   std::string Code = R"(
5526     int identity(int x) { return x; }
5527 
5528     void target() {
5529       int y = identity(42);
5530       // [[p]]
5531     }
5532   )";
5533   runDataflow(
5534       Code,
5535       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5536          ASTContext &ASTCtx) {
5537         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5538         // This just tests that the analysis doesn't crash.
5539       },
5540       {BuiltinOptions{ContextSensitiveOptions{}}});
5541 }
5542 
5543 TEST(TransferTest, ContextSensitiveMethodLiteral) {
5544   std::string Code = R"(
5545     class MyClass {
5546     public:
5547       bool giveBool() { return true; }
5548     };
5549 
5550     void target() {
5551       MyClass MyObj;
5552       bool Foo = MyObj.giveBool();
5553       // [[p]]
5554     }
5555   )";
5556   runDataflow(
5557       Code,
5558       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5559          ASTContext &ASTCtx) {
5560         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5561         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5562 
5563         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5564         ASSERT_THAT(FooDecl, NotNull());
5565 
5566         auto &FooVal = getFormula(*FooDecl, Env);
5567         EXPECT_TRUE(Env.proves(FooVal));
5568       },
5569       {BuiltinOptions{ContextSensitiveOptions{}}});
5570 }
5571 
5572 TEST(TransferTest, ContextSensitiveMethodGetter) {
5573   std::string Code = R"(
5574     class MyClass {
5575     public:
5576       bool getField() { return Field; }
5577 
5578       bool Field;
5579     };
5580 
5581     void target() {
5582       MyClass MyObj;
5583       MyObj.Field = true;
5584       bool Foo = MyObj.getField();
5585       // [[p]]
5586     }
5587   )";
5588   runDataflow(
5589       Code,
5590       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5591          ASTContext &ASTCtx) {
5592         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5593         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5594 
5595         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5596         ASSERT_THAT(FooDecl, NotNull());
5597 
5598         auto &FooVal = getFormula(*FooDecl, Env);
5599         EXPECT_TRUE(Env.proves(FooVal));
5600       },
5601       {BuiltinOptions{ContextSensitiveOptions{}}});
5602 }
5603 
5604 TEST(TransferTest, ContextSensitiveMethodSetter) {
5605   std::string Code = R"(
5606     class MyClass {
5607     public:
5608       void setField(bool Val) { Field = Val; }
5609 
5610       bool Field;
5611     };
5612 
5613     void target() {
5614       MyClass MyObj;
5615       MyObj.setField(true);
5616       bool Foo = MyObj.Field;
5617       // [[p]]
5618     }
5619   )";
5620   runDataflow(
5621       Code,
5622       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5623          ASTContext &ASTCtx) {
5624         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5625         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5626 
5627         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5628         ASSERT_THAT(FooDecl, NotNull());
5629 
5630         auto &FooVal = getFormula(*FooDecl, Env);
5631         EXPECT_TRUE(Env.proves(FooVal));
5632       },
5633       {BuiltinOptions{ContextSensitiveOptions{}}});
5634 }
5635 
5636 TEST(TransferTest, ContextSensitiveMethodGetterAndSetter) {
5637   std::string Code = R"(
5638     class MyClass {
5639     public:
5640       bool getField() { return Field; }
5641       void setField(bool Val) { Field = Val; }
5642 
5643     private:
5644       bool Field;
5645     };
5646 
5647     void target() {
5648       MyClass MyObj;
5649       MyObj.setField(true);
5650       bool Foo = MyObj.getField();
5651       // [[p]]
5652     }
5653   )";
5654   runDataflow(
5655       Code,
5656       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5657          ASTContext &ASTCtx) {
5658         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5659         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5660 
5661         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5662         ASSERT_THAT(FooDecl, NotNull());
5663 
5664         auto &FooVal = getFormula(*FooDecl, Env);
5665         EXPECT_TRUE(Env.proves(FooVal));
5666       },
5667       {BuiltinOptions{ContextSensitiveOptions{}}});
5668 }
5669 
5670 
5671 TEST(TransferTest, ContextSensitiveMethodTwoLayersVoid) {
5672   std::string Code = R"(
5673     class MyClass {
5674     public:
5675       void Inner() { MyField = true; }
5676       void Outer() { Inner(); }
5677 
5678       bool MyField;
5679     };
5680 
5681     void target() {
5682       MyClass MyObj;
5683       MyObj.Outer();
5684       bool Foo = MyObj.MyField;
5685       // [[p]]
5686     }
5687   )";
5688   runDataflow(
5689       Code,
5690       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5691          ASTContext &ASTCtx) {
5692         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5693         ;
5694         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5695 
5696         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5697         ASSERT_THAT(FooDecl, NotNull());
5698 
5699         auto &FooVal = getFormula(*FooDecl, Env);
5700         EXPECT_TRUE(Env.proves(FooVal));
5701       },
5702       {BuiltinOptions{ContextSensitiveOptions{}}});
5703 }
5704 
5705 TEST(TransferTest, ContextSensitiveMethodTwoLayersReturn) {
5706   std::string Code = R"(
5707     class MyClass {
5708     public:
5709       bool Inner() { return MyField; }
5710       bool Outer() { return Inner(); }
5711 
5712       bool MyField;
5713     };
5714 
5715     void target() {
5716       MyClass MyObj;
5717       MyObj.MyField = true;
5718       bool Foo = MyObj.Outer();
5719       // [[p]]
5720     }
5721   )";
5722   runDataflow(
5723       Code,
5724       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5725          ASTContext &ASTCtx) {
5726         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5727         ;
5728         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5729 
5730         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5731         ASSERT_THAT(FooDecl, NotNull());
5732 
5733         auto &FooVal = getFormula(*FooDecl, Env);
5734         EXPECT_TRUE(Env.proves(FooVal));
5735       },
5736       {BuiltinOptions{ContextSensitiveOptions{}}});
5737 }
5738 
5739 TEST(TransferTest, ContextSensitiveConstructorBody) {
5740   std::string Code = R"(
5741     class MyClass {
5742     public:
5743       MyClass() { MyField = true; }
5744 
5745       bool MyField;
5746     };
5747 
5748     void target() {
5749       MyClass MyObj;
5750       bool Foo = MyObj.MyField;
5751       // [[p]]
5752     }
5753   )";
5754   runDataflow(
5755       Code,
5756       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5757          ASTContext &ASTCtx) {
5758         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5759         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5760 
5761         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5762         ASSERT_THAT(FooDecl, NotNull());
5763 
5764         auto &FooVal = getFormula(*FooDecl, Env);
5765         EXPECT_TRUE(Env.proves(FooVal));
5766       },
5767       {BuiltinOptions{ContextSensitiveOptions{}}});
5768 }
5769 
5770 TEST(TransferTest, ContextSensitiveConstructorInitializer) {
5771   std::string Code = R"(
5772     class MyClass {
5773     public:
5774       MyClass() : MyField(true) {}
5775 
5776       bool MyField;
5777     };
5778 
5779     void target() {
5780       MyClass MyObj;
5781       bool Foo = MyObj.MyField;
5782       // [[p]]
5783     }
5784   )";
5785   runDataflow(
5786       Code,
5787       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5788          ASTContext &ASTCtx) {
5789         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5790         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5791 
5792         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5793         ASSERT_THAT(FooDecl, NotNull());
5794 
5795         auto &FooVal = getFormula(*FooDecl, Env);
5796         EXPECT_TRUE(Env.proves(FooVal));
5797       },
5798       {BuiltinOptions{ContextSensitiveOptions{}}});
5799 }
5800 
5801 TEST(TransferTest, ContextSensitiveConstructorDefault) {
5802   std::string Code = R"(
5803     class MyClass {
5804     public:
5805       MyClass() = default;
5806 
5807       bool MyField = true;
5808     };
5809 
5810     void target() {
5811       MyClass MyObj;
5812       bool Foo = MyObj.MyField;
5813       // [[p]]
5814     }
5815   )";
5816   runDataflow(
5817       Code,
5818       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5819          ASTContext &ASTCtx) {
5820         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5821         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5822 
5823         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5824         ASSERT_THAT(FooDecl, NotNull());
5825 
5826         auto &FooVal = getFormula(*FooDecl, Env);
5827         EXPECT_TRUE(Env.proves(FooVal));
5828       },
5829       {BuiltinOptions{ContextSensitiveOptions{}}});
5830 }
5831 
5832 TEST(TransferTest, ContextSensitiveSelfReferentialClass) {
5833   // Test that the `this` pointer seen in the constructor has the same value
5834   // as the address of the variable the object is constructed into.
5835   std::string Code = R"(
5836     class MyClass {
5837     public:
5838       MyClass() : Self(this) {}
5839       MyClass *Self;
5840     };
5841 
5842     void target() {
5843       MyClass MyObj;
5844       MyClass *SelfPtr = MyObj.Self;
5845       // [[p]]
5846     }
5847   )";
5848   runDataflow(
5849       Code,
5850       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5851          ASTContext &ASTCtx) {
5852         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5853 
5854         const ValueDecl *MyObjDecl = findValueDecl(ASTCtx, "MyObj");
5855         ASSERT_THAT(MyObjDecl, NotNull());
5856 
5857         const ValueDecl *SelfDecl = findValueDecl(ASTCtx, "SelfPtr");
5858         ASSERT_THAT(SelfDecl, NotNull());
5859 
5860         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5861         auto &SelfVal = *cast<PointerValue>(Env.getValue(*SelfDecl));
5862         EXPECT_EQ(Env.getStorageLocation(*MyObjDecl), &SelfVal.getPointeeLoc());
5863       },
5864       {BuiltinOptions{ContextSensitiveOptions{}}});
5865 }
5866 
5867 TEST(TransferTest, UnnamedBitfieldInitializer) {
5868   std::string Code = R"(
5869     struct B {};
5870     struct A {
5871       unsigned a;
5872       unsigned : 4;
5873       unsigned c;
5874       B b;
5875     };
5876     void target() {
5877       A a = {};
5878       A test = a;
5879       (void)test.c;
5880     }
5881   )";
5882   runDataflow(
5883       Code,
5884       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5885          ASTContext &ASTCtx) {
5886         // This doesn't need a body because this test was crashing the framework
5887         // before handling correctly Unnamed bitfields in `InitListExpr`.
5888       });
5889 }
5890 
5891 // Repro for a crash that used to occur with chained short-circuiting logical
5892 // operators.
5893 TEST(TransferTest, ChainedLogicalOps) {
5894   std::string Code = R"(
5895     bool target() {
5896       bool b = true || false || false || false;
5897       // [[p]]
5898       return b;
5899     }
5900   )";
5901   runDataflow(
5902       Code,
5903       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5904          ASTContext &ASTCtx) {
5905         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5906         auto &B = getValueForDecl<BoolValue>(ASTCtx, Env, "b").formula();
5907         EXPECT_TRUE(Env.proves(B));
5908       });
5909 }
5910 
5911 // Repro for a crash that used to occur when we call a `noreturn` function
5912 // within one of the operands of a `&&` or `||` operator.
5913 TEST(TransferTest, NoReturnFunctionInsideShortCircuitedBooleanOp) {
5914   std::string Code = R"(
5915     __attribute__((noreturn)) int doesnt_return();
5916     bool some_condition();
5917     void target(bool b1, bool b2) {
5918       // Neither of these should crash. In addition, if we don't terminate the
5919       // program, we know that the operators need to trigger the short-circuit
5920       // logic, so `NoreturnOnRhsOfAnd` will be false and `NoreturnOnRhsOfOr`
5921       // will be true.
5922       bool NoreturnOnRhsOfAnd = b1 && doesnt_return() > 0;
5923       bool NoreturnOnRhsOfOr = b2 || doesnt_return() > 0;
5924 
5925       // Calling a `noreturn` function on the LHS of an `&&` or `||` makes the
5926       // entire expression unreachable. So we know that in both of the following
5927       // cases, if `target()` terminates, the `else` branch was taken.
5928       bool NoreturnOnLhsMakesAndUnreachable = false;
5929       if (some_condition())
5930          doesnt_return() > 0 && some_condition();
5931       else
5932          NoreturnOnLhsMakesAndUnreachable = true;
5933 
5934       bool NoreturnOnLhsMakesOrUnreachable = false;
5935       if (some_condition())
5936          doesnt_return() > 0 || some_condition();
5937       else
5938          NoreturnOnLhsMakesOrUnreachable = true;
5939 
5940       // [[p]]
5941     }
5942   )";
5943   runDataflow(
5944       Code,
5945       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5946          ASTContext &ASTCtx) {
5947         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5948         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5949         auto &A = Env.arena();
5950 
5951         // Check that [[p]] is reachable with a non-false flow condition.
5952         EXPECT_FALSE(Env.proves(A.makeLiteral(false)));
5953 
5954         auto &B1 = getValueForDecl<BoolValue>(ASTCtx, Env, "b1").formula();
5955         EXPECT_TRUE(Env.proves(A.makeNot(B1)));
5956 
5957         auto &NoreturnOnRhsOfAnd =
5958             getValueForDecl<BoolValue>(ASTCtx, Env, "NoreturnOnRhsOfAnd").formula();
5959         EXPECT_TRUE(Env.proves(A.makeNot(NoreturnOnRhsOfAnd)));
5960 
5961         auto &B2 = getValueForDecl<BoolValue>(ASTCtx, Env, "b2").formula();
5962         EXPECT_TRUE(Env.proves(B2));
5963 
5964         auto &NoreturnOnRhsOfOr =
5965             getValueForDecl<BoolValue>(ASTCtx, Env, "NoreturnOnRhsOfOr")
5966                 .formula();
5967         EXPECT_TRUE(Env.proves(NoreturnOnRhsOfOr));
5968 
5969         auto &NoreturnOnLhsMakesAndUnreachable = getValueForDecl<BoolValue>(
5970             ASTCtx, Env, "NoreturnOnLhsMakesAndUnreachable").formula();
5971         EXPECT_TRUE(Env.proves(NoreturnOnLhsMakesAndUnreachable));
5972 
5973         auto &NoreturnOnLhsMakesOrUnreachable = getValueForDecl<BoolValue>(
5974             ASTCtx, Env, "NoreturnOnLhsMakesOrUnreachable").formula();
5975         EXPECT_TRUE(Env.proves(NoreturnOnLhsMakesOrUnreachable));
5976       });
5977 }
5978 
5979 TEST(TransferTest, NewExpressions) {
5980   std::string Code = R"(
5981     void target() {
5982       int *p = new int(42);
5983       // [[after_new]]
5984     }
5985   )";
5986   runDataflow(
5987       Code,
5988       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5989          ASTContext &ASTCtx) {
5990         const Environment &Env =
5991             getEnvironmentAtAnnotation(Results, "after_new");
5992 
5993         auto &P = getValueForDecl<PointerValue>(ASTCtx, Env, "p");
5994 
5995         EXPECT_THAT(Env.getValue(P.getPointeeLoc()), NotNull());
5996       });
5997 }
5998 
5999 TEST(TransferTest, NewExpressions_Structs) {
6000   std::string Code = R"(
6001     struct Inner {
6002       int InnerField;
6003     };
6004 
6005     struct Outer {
6006       Inner OuterField;
6007     };
6008 
6009     void target() {
6010       Outer *p = new Outer;
6011       // Access the fields to make sure the analysis actually generates children
6012       // for them in the `RecordStorageLocation` and `RecordValue`.
6013       p->OuterField.InnerField;
6014       // [[after_new]]
6015     }
6016   )";
6017   runDataflow(
6018       Code,
6019       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6020          ASTContext &ASTCtx) {
6021         const Environment &Env =
6022             getEnvironmentAtAnnotation(Results, "after_new");
6023 
6024         const ValueDecl *OuterField = findValueDecl(ASTCtx, "OuterField");
6025         const ValueDecl *InnerField = findValueDecl(ASTCtx, "InnerField");
6026 
6027         auto &P = getValueForDecl<PointerValue>(ASTCtx, Env, "p");
6028 
6029         auto &OuterLoc = cast<RecordStorageLocation>(P.getPointeeLoc());
6030         auto &OuterFieldLoc =
6031             *cast<RecordStorageLocation>(OuterLoc.getChild(*OuterField));
6032         auto &InnerFieldLoc = *OuterFieldLoc.getChild(*InnerField);
6033 
6034         // Values for the struct and all fields exist after the new.
6035         EXPECT_THAT(Env.getValue(OuterLoc), NotNull());
6036         EXPECT_THAT(Env.getValue(OuterFieldLoc), NotNull());
6037         EXPECT_THAT(Env.getValue(InnerFieldLoc), NotNull());
6038       });
6039 }
6040 
6041 TEST(TransferTest, FunctionToPointerDecayHasValue) {
6042   std::string Code = R"(
6043     struct A { static void static_member_func(); };
6044     void target() {
6045       // To check that we're treating function-to-pointer decay correctly,
6046       // create two pointers, then verify they refer to the same storage
6047       // location.
6048       // We need to do the test this way because even if an initializer (in this
6049       // case, the function-to-pointer decay) does not create a value, we still
6050       // create a value for the variable.
6051       void (*non_member_p1)() = target;
6052       void (*non_member_p2)() = target;
6053 
6054       // Do the same thing but for a static member function.
6055       void (*member_p1)() = A::static_member_func;
6056       void (*member_p2)() = A::static_member_func;
6057       // [[p]]
6058     }
6059   )";
6060   runDataflow(
6061       Code,
6062       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6063          ASTContext &ASTCtx) {
6064         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6065 
6066         auto &NonMemberP1 =
6067             getValueForDecl<PointerValue>(ASTCtx, Env, "non_member_p1");
6068         auto &NonMemberP2 =
6069             getValueForDecl<PointerValue>(ASTCtx, Env, "non_member_p2");
6070         EXPECT_EQ(&NonMemberP1.getPointeeLoc(), &NonMemberP2.getPointeeLoc());
6071 
6072         auto &MemberP1 =
6073             getValueForDecl<PointerValue>(ASTCtx, Env, "member_p1");
6074         auto &MemberP2 =
6075             getValueForDecl<PointerValue>(ASTCtx, Env, "member_p2");
6076         EXPECT_EQ(&MemberP1.getPointeeLoc(), &MemberP2.getPointeeLoc());
6077       });
6078 }
6079 
6080 // Check that a builtin function is not associated with a value. (It's only
6081 // possible to call builtin functions directly, not take their address.)
6082 TEST(TransferTest, BuiltinFunctionModeled) {
6083   std::string Code = R"(
6084     void target() {
6085       __builtin_expect(0, 0);
6086       // [[p]]
6087     }
6088   )";
6089   runDataflow(
6090       Code,
6091       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6092          ASTContext &ASTCtx) {
6093         using ast_matchers::selectFirst;
6094         using ast_matchers::match;
6095         using ast_matchers::traverse;
6096         using ast_matchers::implicitCastExpr;
6097         using ast_matchers::hasCastKind;
6098 
6099         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6100 
6101         auto *ImplicitCast = selectFirst<ImplicitCastExpr>(
6102             "implicit_cast",
6103             match(traverse(TK_AsIs,
6104                            implicitCastExpr(hasCastKind(CK_BuiltinFnToFnPtr))
6105                                .bind("implicit_cast")),
6106                   ASTCtx));
6107 
6108         ASSERT_THAT(ImplicitCast, NotNull());
6109         EXPECT_THAT(Env.getValue(*ImplicitCast), IsNull());
6110       });
6111 }
6112 
6113 // Check that a callee of a member operator call is modeled as a `PointerValue`.
6114 // Member operator calls are unusual in that their callee is a pointer that
6115 // stems from a `FunctionToPointerDecay`. In calls to non-operator non-static
6116 // member functions, the callee is a `MemberExpr` (which does not have pointer
6117 // type).
6118 // We want to make sure that we produce a pointer value for the callee in this
6119 // specific scenario and that its storage location is durable (for convergence).
6120 TEST(TransferTest, MemberOperatorCallModelsPointerForCallee) {
6121   std::string Code = R"(
6122     struct S {
6123       bool operator!=(S s);
6124     };
6125     void target() {
6126       S s;
6127       (void)(s != s);
6128       (void)(s != s);
6129       // [[p]]
6130     }
6131   )";
6132   runDataflow(
6133       Code,
6134       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6135          ASTContext &ASTCtx) {
6136         using ast_matchers::selectFirst;
6137         using ast_matchers::match;
6138         using ast_matchers::traverse;
6139         using ast_matchers::cxxOperatorCallExpr;
6140 
6141         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6142 
6143         auto Matches = match(
6144             traverse(TK_AsIs, cxxOperatorCallExpr().bind("call")), ASTCtx);
6145 
6146         ASSERT_EQ(Matches.size(), 2UL);
6147 
6148         auto *Call1 = Matches[0].getNodeAs<CXXOperatorCallExpr>("call");
6149         auto *Call2 = Matches[1].getNodeAs<CXXOperatorCallExpr>("call");
6150 
6151         ASSERT_THAT(Call1, NotNull());
6152         ASSERT_THAT(Call2, NotNull());
6153 
6154         EXPECT_EQ(cast<ImplicitCastExpr>(Call1->getCallee())->getCastKind(),
6155                   CK_FunctionToPointerDecay);
6156         EXPECT_EQ(cast<ImplicitCastExpr>(Call2->getCallee())->getCastKind(),
6157                   CK_FunctionToPointerDecay);
6158 
6159         auto *Ptr1 = cast<PointerValue>(Env.getValue(*Call1->getCallee()));
6160         auto *Ptr2 = cast<PointerValue>(Env.getValue(*Call2->getCallee()));
6161 
6162         ASSERT_EQ(&Ptr1->getPointeeLoc(), &Ptr2->getPointeeLoc());
6163       });
6164 }
6165 
6166 // Check that fields of anonymous records are modeled.
6167 TEST(TransferTest, AnonymousStruct) {
6168   std::string Code = R"(
6169     struct S {
6170       struct {
6171         bool b;
6172       };
6173     };
6174     void target() {
6175       S s;
6176       s.b = true;
6177       // [[p]]
6178     }
6179   )";
6180   runDataflow(
6181       Code,
6182       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6183          ASTContext &ASTCtx) {
6184         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6185         const ValueDecl *SDecl = findValueDecl(ASTCtx, "s");
6186         const ValueDecl *BDecl = findValueDecl(ASTCtx, "b");
6187         const IndirectFieldDecl *IndirectField =
6188             findIndirectFieldDecl(ASTCtx, "b");
6189 
6190         auto *S = cast<RecordStorageLocation>(Env.getStorageLocation(*SDecl));
6191         auto &AnonStruct = *cast<RecordStorageLocation>(
6192             S->getChild(*cast<ValueDecl>(IndirectField->chain().front())));
6193 
6194         auto *B = cast<BoolValue>(getFieldValue(&AnonStruct, *BDecl, Env));
6195         ASSERT_TRUE(Env.proves(B->formula()));
6196       });
6197 }
6198 
6199 TEST(TransferTest, AnonymousStructWithInitializer) {
6200   std::string Code = R"(
6201     struct target {
6202       target() {
6203         (void)0;
6204         // [[p]]
6205       }
6206       struct {
6207         bool b = true;
6208       };
6209     };
6210   )";
6211   runDataflow(
6212       Code,
6213       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6214          ASTContext &ASTCtx) {
6215         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6216         const ValueDecl *BDecl = findValueDecl(ASTCtx, "b");
6217         const IndirectFieldDecl *IndirectField =
6218             findIndirectFieldDecl(ASTCtx, "b");
6219 
6220         auto *ThisLoc =
6221             cast<RecordStorageLocation>(Env.getThisPointeeStorageLocation());
6222         auto &AnonStruct = *cast<RecordStorageLocation>(ThisLoc->getChild(
6223             *cast<ValueDecl>(IndirectField->chain().front())));
6224 
6225         auto *B = cast<BoolValue>(getFieldValue(&AnonStruct, *BDecl, Env));
6226         ASSERT_TRUE(Env.proves(B->formula()));
6227       });
6228 }
6229 
6230 TEST(TransferTest, AnonymousStructWithReferenceField) {
6231   std::string Code = R"(
6232     int global_i = 0;
6233     struct target {
6234       target() {
6235         (void)0;
6236         // [[p]]
6237       }
6238       struct {
6239         int &i = global_i;
6240       };
6241     };
6242   )";
6243   runDataflow(
6244       Code,
6245       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6246          ASTContext &ASTCtx) {
6247         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6248         const ValueDecl *GlobalIDecl = findValueDecl(ASTCtx, "global_i");
6249         const ValueDecl *IDecl = findValueDecl(ASTCtx, "i");
6250         const IndirectFieldDecl *IndirectField =
6251             findIndirectFieldDecl(ASTCtx, "i");
6252 
6253         auto *ThisLoc =
6254             cast<RecordStorageLocation>(Env.getThisPointeeStorageLocation());
6255         auto &AnonStruct = *cast<RecordStorageLocation>(ThisLoc->getChild(
6256             *cast<ValueDecl>(IndirectField->chain().front())));
6257 
6258         ASSERT_EQ(AnonStruct.getChild(*IDecl),
6259                   Env.getStorageLocation(*GlobalIDecl));
6260       });
6261 }
6262 
6263 TEST(TransferTest, EvaluateBlockWithUnreachablePreds) {
6264   // This is a crash repro.
6265   // `false` block may not have been processed when we try to evaluate the `||`
6266   // after visiting `true`, because it is not necessary (and therefore the edge
6267   // is marked unreachable). Trying to get the analysis state via
6268   // `getEnvironment` for the subexpression still should not crash.
6269   std::string Code = R"(
6270     int target(int i) {
6271       if ((i < 0 && true) || false) {
6272         return 0;
6273       }
6274       return 0;
6275     }
6276   )";
6277   runDataflow(
6278       Code,
6279       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6280          ASTContext &ASTCtx) {});
6281 }
6282 
6283 TEST(TransferTest, LambdaCaptureByCopy) {
6284   std::string Code = R"(
6285     void target(int Foo, int Bar) {
6286       [Foo]() {
6287         (void)0;
6288         // [[p]]
6289       }();
6290     }
6291   )";
6292   runDataflowOnLambda(
6293       Code,
6294       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6295          ASTContext &ASTCtx) {
6296         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6297         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6298 
6299         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6300         ASSERT_THAT(FooDecl, NotNull());
6301 
6302         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
6303         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
6304 
6305         const Value *FooVal = Env.getValue(*FooLoc);
6306         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
6307 
6308         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
6309         ASSERT_THAT(BarDecl, NotNull());
6310 
6311         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
6312         EXPECT_THAT(BarLoc, IsNull());
6313       });
6314 }
6315 
6316 TEST(TransferTest, LambdaCaptureByReference) {
6317   std::string Code = R"(
6318     void target(int Foo, int Bar) {
6319       [&Foo]() {
6320         (void)0;
6321         // [[p]]
6322       }();
6323     }
6324   )";
6325   runDataflowOnLambda(
6326       Code,
6327       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6328          ASTContext &ASTCtx) {
6329         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6330         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6331 
6332         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6333         ASSERT_THAT(FooDecl, NotNull());
6334 
6335         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
6336         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
6337 
6338         const Value *FooVal = Env.getValue(*FooLoc);
6339         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
6340 
6341         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
6342         ASSERT_THAT(BarDecl, NotNull());
6343 
6344         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
6345         EXPECT_THAT(BarLoc, IsNull());
6346       });
6347 }
6348 
6349 TEST(TransferTest, LambdaCaptureWithInitializer) {
6350   std::string Code = R"(
6351     void target(int Bar) {
6352       [Foo=Bar]() {
6353         (void)0;
6354         // [[p]]
6355       }();
6356     }
6357   )";
6358   runDataflowOnLambda(
6359       Code,
6360       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6361          ASTContext &ASTCtx) {
6362         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6363         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6364 
6365         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6366         ASSERT_THAT(FooDecl, NotNull());
6367 
6368         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
6369         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
6370 
6371         const Value *FooVal = Env.getValue(*FooLoc);
6372         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
6373 
6374         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
6375         ASSERT_THAT(BarDecl, NotNull());
6376 
6377         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
6378         EXPECT_THAT(BarLoc, IsNull());
6379       });
6380 }
6381 
6382 TEST(TransferTest, LambdaCaptureByCopyImplicit) {
6383   std::string Code = R"(
6384     void target(int Foo, int Bar) {
6385       [=]() {
6386         Foo;
6387         // [[p]]
6388       }();
6389     }
6390   )";
6391   runDataflowOnLambda(
6392       Code,
6393       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6394          ASTContext &ASTCtx) {
6395         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6396         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6397 
6398         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6399         ASSERT_THAT(FooDecl, NotNull());
6400 
6401         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
6402         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
6403 
6404         const Value *FooVal = Env.getValue(*FooLoc);
6405         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
6406 
6407         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
6408         ASSERT_THAT(BarDecl, NotNull());
6409 
6410         // There is no storage location for `Bar` because it isn't used in the
6411         // body of the lambda.
6412         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
6413         EXPECT_THAT(BarLoc, IsNull());
6414       });
6415 }
6416 
6417 TEST(TransferTest, LambdaCaptureByReferenceImplicit) {
6418   std::string Code = R"(
6419     void target(int Foo, int Bar) {
6420       [&]() {
6421         Foo;
6422         // [[p]]
6423       }();
6424     }
6425   )";
6426   runDataflowOnLambda(
6427       Code,
6428       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6429          ASTContext &ASTCtx) {
6430         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6431         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6432 
6433         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6434         ASSERT_THAT(FooDecl, NotNull());
6435 
6436         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
6437         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
6438 
6439         const Value *FooVal = Env.getValue(*FooLoc);
6440         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
6441 
6442         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
6443         ASSERT_THAT(BarDecl, NotNull());
6444 
6445         // There is no storage location for `Bar` because it isn't used in the
6446         // body of the lambda.
6447         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
6448         EXPECT_THAT(BarLoc, IsNull());
6449       });
6450 }
6451 
6452 TEST(TransferTest, LambdaCaptureThis) {
6453   std::string Code = R"(
6454     struct Bar {
6455       int Foo;
6456 
6457       void target() {
6458         [this]() {
6459           Foo;
6460           // [[p]]
6461         }();
6462       }
6463     };
6464   )";
6465   runDataflowOnLambda(
6466       Code,
6467       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6468          ASTContext &ASTCtx) {
6469         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6470         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6471 
6472         const RecordStorageLocation *ThisPointeeLoc =
6473             Env.getThisPointeeStorageLocation();
6474         ASSERT_THAT(ThisPointeeLoc, NotNull());
6475 
6476         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6477         ASSERT_THAT(FooDecl, NotNull());
6478 
6479         const StorageLocation *FooLoc = ThisPointeeLoc->getChild(*FooDecl);
6480         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
6481 
6482         const Value *FooVal = Env.getValue(*FooLoc);
6483         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
6484       });
6485 }
6486 
6487 TEST(TransferTest, DifferentReferenceLocInJoin) {
6488   // This test triggers a case where the storage location for a reference-type
6489   // variable is different for two states being joined. We used to believe this
6490   // could not happen and therefore had an assertion disallowing this; this test
6491   // exists to demonstrate that we can handle this condition without a failing
6492   // assertion. See also the discussion here:
6493   // https://discourse.llvm.org/t/70086/6
6494   std::string Code = R"(
6495     namespace std {
6496       template <class T> struct initializer_list {
6497         const T* begin();
6498         const T* end();
6499       };
6500     }
6501 
6502     void target(char* p, char* end) {
6503       while (p != end) {
6504         if (*p == ' ') {
6505           p++;
6506           continue;
6507         }
6508 
6509         auto && range = {1, 2};
6510         for (auto b = range.begin(), e = range.end(); b != e; ++b) {
6511         }
6512         (void)0;
6513         // [[p]]
6514       }
6515     }
6516   )";
6517   runDataflow(
6518       Code,
6519       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6520          ASTContext &ASTCtx) {
6521         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6522 
6523         // Joining environments with different storage locations for the same
6524         // declaration results in the declaration being removed from the joined
6525         // environment.
6526         const ValueDecl *VD = findValueDecl(ASTCtx, "range");
6527         ASSERT_EQ(Env.getStorageLocation(*VD), nullptr);
6528       });
6529 }
6530 
6531 // This test verifies correct modeling of a relational dependency that goes
6532 // through unmodeled functions (the simple `cond()` in this case).
6533 TEST(TransferTest, ConditionalRelation) {
6534   std::string Code = R"(
6535     bool cond();
6536     void target() {
6537        bool a = true;
6538        bool b = true;
6539        if (cond()) {
6540          a = false;
6541          if (cond()) {
6542            b = false;
6543          }
6544        }
6545        (void)0;
6546        // [[p]]
6547     }
6548  )";
6549   runDataflow(
6550       Code,
6551       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6552          ASTContext &ASTCtx) {
6553         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6554         auto &A = Env.arena();
6555         auto &VarA = getValueForDecl<BoolValue>(ASTCtx, Env, "a").formula();
6556         auto &VarB = getValueForDecl<BoolValue>(ASTCtx, Env, "b").formula();
6557 
6558         EXPECT_FALSE(Env.allows(A.makeAnd(VarA, A.makeNot(VarB))));
6559       });
6560 }
6561 
6562 } // namespace
6563