xref: /llvm-project/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp (revision 2730a5c68c6986bc8f01d047f8f31bcfd9316333)
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, InitListExprAsXValue) {
2353   // This is a crash repro.
2354   std::string Code = R"(
2355     void target() {
2356       bool&& Foo{false};
2357       // [[p]]
2358     }
2359   )";
2360   runDataflow(
2361       Code,
2362       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2363          ASTContext &ASTCtx) {
2364         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2365         const auto &FooVal = getValueForDecl<BoolValue>(ASTCtx, Env, "Foo");
2366         ASSERT_TRUE(FooVal.formula().isLiteral(false));
2367       });
2368 }
2369 
2370 TEST(TransferTest, ArrayInitListExprOneRecordElement) {
2371   // This is a crash repro.
2372   std::string Code = R"cc(
2373     struct S {};
2374 
2375     void target() { S foo[] = {S()}; }
2376   )cc";
2377   runDataflow(
2378       Code,
2379       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2380          ASTContext &ASTCtx) {
2381         // Just verify that it doesn't crash.
2382       });
2383 }
2384 
2385 TEST(TransferTest, InitListExprAsUnion) {
2386   // This is a crash repro.
2387   std::string Code = R"cc(
2388     class target {
2389       union {
2390         int *a;
2391         bool *b;
2392       } F;
2393 
2394      public:
2395       constexpr target() : F{nullptr} {}
2396     };
2397   )cc";
2398   runDataflow(
2399       Code,
2400       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2401          ASTContext &ASTCtx) {
2402         // Just verify that it doesn't crash.
2403       });
2404 }
2405 
2406 TEST(TransferTest, CopyConstructor) {
2407   std::string Code = R"(
2408     struct A {
2409       int Baz;
2410     };
2411 
2412     void target() {
2413       A Foo = { 1 };
2414       A Bar = Foo;
2415       // [[after_copy]]
2416       Foo.Baz = 2;
2417       // [[after_update]]
2418     }
2419   )";
2420   runDataflow(
2421       Code,
2422       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2423          ASTContext &ASTCtx) {
2424         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2425         ASSERT_THAT(FooDecl, NotNull());
2426 
2427         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2428         ASSERT_THAT(BarDecl, NotNull());
2429 
2430         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2431         ASSERT_THAT(BazDecl, NotNull());
2432 
2433         // after_copy
2434         {
2435           const Environment &Env =
2436               getEnvironmentAtAnnotation(Results, "after_copy");
2437 
2438           const auto *FooLoc =
2439               cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
2440           const auto *BarLoc =
2441               cast<RecordStorageLocation>(Env.getStorageLocation(*BarDecl));
2442 
2443           // `Foo` and `Bar` have different `RecordValue`s associated with them.
2444           const auto *FooVal = cast<RecordValue>(Env.getValue(*FooLoc));
2445           const auto *BarVal = cast<RecordValue>(Env.getValue(*BarLoc));
2446           EXPECT_NE(FooVal, BarVal);
2447 
2448           // But the records compare equal.
2449           EXPECT_TRUE(recordsEqual(*FooLoc, *BarLoc, Env));
2450 
2451           // In particular, the value of `Baz` in both records is the same.
2452           const auto *FooBazVal =
2453               cast<IntegerValue>(getFieldValue(FooLoc, *BazDecl, Env));
2454           const auto *BarBazVal =
2455               cast<IntegerValue>(getFieldValue(BarLoc, *BazDecl, Env));
2456           EXPECT_EQ(FooBazVal, BarBazVal);
2457         }
2458 
2459         // after_update
2460         {
2461           const Environment &Env =
2462               getEnvironmentAtAnnotation(Results, "after_update");
2463 
2464           const auto *FooLoc =
2465               cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
2466           const auto *BarLoc =
2467               cast<RecordStorageLocation>(Env.getStorageLocation(*BarDecl));
2468 
2469           EXPECT_FALSE(recordsEqual(*FooLoc, *BarLoc, Env));
2470 
2471           const auto *FooBazVal =
2472               cast<IntegerValue>(getFieldValue(FooLoc, *BazDecl, Env));
2473           const auto *BarBazVal =
2474               cast<IntegerValue>(getFieldValue(BarLoc, *BazDecl, Env));
2475           EXPECT_NE(FooBazVal, BarBazVal);
2476         }
2477       });
2478 }
2479 
2480 TEST(TransferTest, CopyConstructorWithDefaultArgument) {
2481   std::string Code = R"(
2482     struct A {
2483       int Baz;
2484       A() = default;
2485       A(const A& a, bool def = true) { Baz = a.Baz; }
2486     };
2487 
2488     void target() {
2489       A Foo;
2490       (void)Foo.Baz;
2491       A Bar = Foo;
2492       // [[p]]
2493     }
2494   )";
2495   runDataflow(
2496       Code,
2497       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2498          ASTContext &ASTCtx) {
2499         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2500         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2501 
2502         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2503         ASSERT_THAT(FooDecl, NotNull());
2504 
2505         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2506         ASSERT_THAT(BarDecl, NotNull());
2507 
2508         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2509         ASSERT_THAT(BazDecl, NotNull());
2510 
2511         const auto *FooLoc =
2512             cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
2513         const auto *BarLoc =
2514             cast<RecordStorageLocation>(Env.getStorageLocation(*BarDecl));
2515         EXPECT_TRUE(recordsEqual(*FooLoc, *BarLoc, Env));
2516 
2517         const auto *FooBazVal =
2518             cast<IntegerValue>(getFieldValue(FooLoc, *BazDecl, Env));
2519         const auto *BarBazVal =
2520             cast<IntegerValue>(getFieldValue(BarLoc, *BazDecl, Env));
2521         EXPECT_EQ(FooBazVal, BarBazVal);
2522       });
2523 }
2524 
2525 TEST(TransferTest, CopyConstructorWithParens) {
2526   std::string Code = R"(
2527     struct A {
2528       int Baz;
2529     };
2530 
2531     void target() {
2532       A Foo;
2533       (void)Foo.Baz;
2534       A Bar((A(Foo)));
2535       // [[p]]
2536     }
2537   )";
2538   runDataflow(
2539       Code,
2540       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2541          ASTContext &ASTCtx) {
2542         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2543         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2544 
2545         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2546         ASSERT_THAT(FooDecl, NotNull());
2547 
2548         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2549         ASSERT_THAT(BarDecl, NotNull());
2550 
2551         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2552         ASSERT_THAT(BazDecl, NotNull());
2553 
2554         const auto *FooLoc =
2555             cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
2556         const auto *BarLoc =
2557             cast<RecordStorageLocation>(Env.getStorageLocation(*BarDecl));
2558         EXPECT_TRUE(recordsEqual(*FooLoc, *BarLoc, Env));
2559 
2560         const auto *FooBazVal =
2561             cast<IntegerValue>(getFieldValue(FooLoc, *BazDecl, Env));
2562         const auto *BarBazVal =
2563             cast<IntegerValue>(getFieldValue(BarLoc, *BazDecl, Env));
2564         EXPECT_EQ(FooBazVal, BarBazVal);
2565       });
2566 }
2567 
2568 TEST(TransferTest, CopyConstructorWithInitializerListAsSyntacticSugar) {
2569   std::string Code = R"(
2570   struct A {
2571     int Baz;
2572   };
2573   void target() {
2574     A Foo = {3};
2575     (void)Foo.Baz;
2576     A Bar = {A(Foo)};
2577     // [[p]]
2578   }
2579   )";
2580   runDataflow(
2581       Code,
2582       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2583          ASTContext &ASTCtx) {
2584         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2585 
2586         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2587 
2588         const auto &FooLoc =
2589             getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "Foo");
2590         const auto &BarLoc =
2591             getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "Bar");
2592 
2593         const auto *FooBazVal =
2594             cast<IntegerValue>(getFieldValue(&FooLoc, *BazDecl, Env));
2595         const auto *BarBazVal =
2596             cast<IntegerValue>(getFieldValue(&BarLoc, *BazDecl, Env));
2597         EXPECT_EQ(FooBazVal, BarBazVal);
2598       });
2599 }
2600 
2601 TEST(TransferTest, CopyConstructorArgIsRefReturnedByFunction) {
2602   // This is a crash repro.
2603   std::string Code = R"(
2604     struct S {};
2605     const S &returnsSRef();
2606     void target() {
2607       S s(returnsSRef());
2608     }
2609   )";
2610   runDataflow(
2611       Code,
2612       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2613          ASTContext &ASTCtx) {});
2614 }
2615 
2616 TEST(TransferTest, MoveConstructor) {
2617   std::string Code = R"(
2618     namespace std {
2619 
2620     template <typename T> struct remove_reference      { using type = T; };
2621     template <typename T> struct remove_reference<T&>  { using type = T; };
2622     template <typename T> struct remove_reference<T&&> { using type = T; };
2623 
2624     template <typename T>
2625     using remove_reference_t = typename remove_reference<T>::type;
2626 
2627     template <typename T>
2628     std::remove_reference_t<T>&& move(T&& x);
2629 
2630     } // namespace std
2631 
2632     struct A {
2633       int Baz;
2634     };
2635 
2636     void target() {
2637       A Foo;
2638       A Bar;
2639       (void)Foo.Baz;
2640       // [[p1]]
2641       Foo = std::move(Bar);
2642       // [[p2]]
2643     }
2644   )";
2645   runDataflow(
2646       Code,
2647       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2648          ASTContext &ASTCtx) {
2649         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
2650         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
2651         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
2652 
2653         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2654         ASSERT_THAT(FooDecl, NotNull());
2655 
2656         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2657         ASSERT_THAT(BarDecl, NotNull());
2658 
2659         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2660         ASSERT_THAT(BazDecl, NotNull());
2661 
2662         const auto *FooLoc1 =
2663             cast<RecordStorageLocation>(Env1.getStorageLocation(*FooDecl));
2664         const auto *BarLoc1 =
2665             cast<RecordStorageLocation>(Env1.getStorageLocation(*BarDecl));
2666 
2667         EXPECT_FALSE(recordsEqual(*FooLoc1, *BarLoc1, Env1));
2668 
2669         const auto *FooVal1 = cast<RecordValue>(Env1.getValue(*FooLoc1));
2670         const auto *BarVal1 = cast<RecordValue>(Env1.getValue(*BarLoc1));
2671         EXPECT_NE(FooVal1, BarVal1);
2672 
2673         const auto *FooBazVal1 =
2674             cast<IntegerValue>(getFieldValue(FooLoc1, *BazDecl, Env1));
2675         const auto *BarBazVal1 =
2676             cast<IntegerValue>(getFieldValue(BarLoc1, *BazDecl, Env1));
2677         EXPECT_NE(FooBazVal1, BarBazVal1);
2678 
2679         const auto *FooLoc2 =
2680             cast<RecordStorageLocation>(Env2.getStorageLocation(*FooDecl));
2681         const auto *FooVal2 = cast<RecordValue>(Env2.getValue(*FooLoc2));
2682         EXPECT_NE(FooVal2, BarVal1);
2683         EXPECT_TRUE(recordsEqual(*FooLoc2, Env2, *BarLoc1, Env1));
2684 
2685         const auto *FooBazVal2 =
2686             cast<IntegerValue>(getFieldValue(FooLoc1, *BazDecl, Env2));
2687         EXPECT_EQ(FooBazVal2, BarBazVal1);
2688       });
2689 }
2690 
2691 TEST(TransferTest, BindTemporary) {
2692   std::string Code = R"(
2693     struct A {
2694       virtual ~A() = default;
2695 
2696       int Baz;
2697     };
2698 
2699     void target(A Foo) {
2700       int Bar = A(Foo).Baz;
2701       // [[p]]
2702     }
2703   )";
2704   runDataflow(
2705       Code,
2706       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2707          ASTContext &ASTCtx) {
2708         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2709         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2710 
2711         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2712         ASSERT_THAT(FooDecl, NotNull());
2713 
2714         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2715         ASSERT_THAT(BarDecl, NotNull());
2716 
2717         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2718         ASSERT_THAT(BazDecl, NotNull());
2719 
2720         const auto &FooLoc =
2721             *cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
2722         const auto *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
2723         EXPECT_EQ(BarVal, getFieldValue(&FooLoc, *BazDecl, Env));
2724       });
2725 }
2726 
2727 TEST(TransferTest, ResultObjectLocation) {
2728   std::string Code = R"(
2729     struct A {
2730       virtual ~A() = default;
2731     };
2732 
2733     void target() {
2734       0, A();
2735       (void)0; // [[p]]
2736     }
2737   )";
2738   using ast_matchers::binaryOperator;
2739   using ast_matchers::cxxBindTemporaryExpr;
2740   using ast_matchers::cxxTemporaryObjectExpr;
2741   using ast_matchers::exprWithCleanups;
2742   using ast_matchers::has;
2743   using ast_matchers::hasOperatorName;
2744   using ast_matchers::hasRHS;
2745   using ast_matchers::match;
2746   using ast_matchers::selectFirst;
2747   using ast_matchers::traverse;
2748   runDataflow(
2749       Code,
2750       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2751          ASTContext &ASTCtx) {
2752         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2753 
2754         // The expression `0, A()` in the code above produces the following
2755         // structure, consisting of four prvalues of record type.
2756         // `Env.getResultObjectLocation()` should return the same location for
2757         // all of these.
2758         auto MatchResult = match(
2759             traverse(TK_AsIs,
2760                      exprWithCleanups(
2761                          has(binaryOperator(
2762                                  hasOperatorName(","),
2763                                  hasRHS(cxxBindTemporaryExpr(
2764                                             has(cxxTemporaryObjectExpr().bind(
2765                                                 "toe")))
2766                                             .bind("bte")))
2767                                  .bind("comma")))
2768                          .bind("ewc")),
2769             ASTCtx);
2770         auto *TOE = selectFirst<CXXTemporaryObjectExpr>("toe", MatchResult);
2771         ASSERT_NE(TOE, nullptr);
2772         auto *Comma = selectFirst<BinaryOperator>("comma", MatchResult);
2773         ASSERT_NE(Comma, nullptr);
2774         auto *EWC = selectFirst<ExprWithCleanups>("ewc", MatchResult);
2775         ASSERT_NE(EWC, nullptr);
2776         auto *BTE = selectFirst<CXXBindTemporaryExpr>("bte", MatchResult);
2777         ASSERT_NE(BTE, nullptr);
2778 
2779         RecordStorageLocation &Loc = Env.getResultObjectLocation(*TOE);
2780         EXPECT_EQ(&Loc, &Env.getResultObjectLocation(*Comma));
2781         EXPECT_EQ(&Loc, &Env.getResultObjectLocation(*EWC));
2782         EXPECT_EQ(&Loc, &Env.getResultObjectLocation(*BTE));
2783       });
2784 }
2785 
2786 TEST(TransferTest, ResultObjectLocationForDefaultInitExpr) {
2787   std::string Code = R"(
2788     struct S {};
2789     struct target {
2790       target () {
2791         (void)0;
2792         // [[p]]
2793       }
2794       S s = {};
2795     };
2796   )";
2797 
2798   using ast_matchers::cxxCtorInitializer;
2799   using ast_matchers::match;
2800   using ast_matchers::selectFirst;
2801   runDataflow(
2802       Code,
2803       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2804          ASTContext &ASTCtx) {
2805         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2806 
2807         const ValueDecl *SField = findValueDecl(ASTCtx, "s");
2808 
2809         auto *CtorInit = selectFirst<CXXCtorInitializer>(
2810             "ctor_initializer",
2811             match(cxxCtorInitializer().bind("ctor_initializer"), ASTCtx));
2812         ASSERT_NE(CtorInit, nullptr);
2813 
2814         auto *DefaultInit = cast<CXXDefaultInitExpr>(CtorInit->getInit());
2815 
2816         RecordStorageLocation &Loc = Env.getResultObjectLocation(*DefaultInit);
2817 
2818         // FIXME: The result object location for the `CXXDefaultInitExpr` should
2819         // be the location of the member variable being initialized, but we
2820         // don't do this correctly yet; see also comments in
2821         // `builtinTransferInitializer()`.
2822         // For the time being, we just document the current erroneous behavior
2823         // here (this should be `EXPECT_EQ` when the behavior is fixed).
2824         EXPECT_NE(&Loc, Env.getThisPointeeStorageLocation()->getChild(*SField));
2825       });
2826 }
2827 
2828 // This test ensures that CXXOperatorCallExpr returning prvalues are correctly
2829 // handled by the transfer functions, especially that `getResultObjectLocation`
2830 // correctly returns a storage location for those.
2831 TEST(TransferTest, ResultObjectLocationForCXXOperatorCallExpr) {
2832   std::string Code = R"(
2833     struct A {
2834       A operator+(int);
2835     };
2836 
2837     void target() {
2838       A a;
2839       a + 3;
2840       (void)0; // [[p]]
2841     }
2842   )";
2843   using ast_matchers::cxxOperatorCallExpr;
2844   using ast_matchers::match;
2845   using ast_matchers::selectFirst;
2846   using ast_matchers::traverse;
2847   runDataflow(
2848       Code,
2849       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2850          ASTContext &ASTCtx) {
2851         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2852 
2853         auto *CallExpr = selectFirst<CXXOperatorCallExpr>(
2854             "call_expr",
2855             match(cxxOperatorCallExpr().bind("call_expr"), ASTCtx));
2856 
2857         EXPECT_NE(&Env.getResultObjectLocation(*CallExpr), nullptr);
2858       });
2859 }
2860 
2861 TEST(TransferTest, StaticCast) {
2862   std::string Code = R"(
2863     void target(int Foo) {
2864       int Bar = static_cast<int>(Foo);
2865       // [[p]]
2866     }
2867   )";
2868   runDataflow(
2869       Code,
2870       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2871          ASTContext &ASTCtx) {
2872         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2873         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2874 
2875         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2876         ASSERT_THAT(FooDecl, NotNull());
2877 
2878         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2879         ASSERT_THAT(BarDecl, NotNull());
2880 
2881         const auto *FooVal = Env.getValue(*FooDecl);
2882         const auto *BarVal = Env.getValue(*BarDecl);
2883         EXPECT_TRUE(isa<IntegerValue>(FooVal));
2884         EXPECT_TRUE(isa<IntegerValue>(BarVal));
2885         EXPECT_EQ(FooVal, BarVal);
2886       });
2887 }
2888 
2889 TEST(TransferTest, IntegralCast) {
2890   std::string Code = R"(
2891     void target(int Foo) {
2892       long Bar = Foo;
2893       // [[p]]
2894     }
2895   )";
2896   runDataflow(
2897       Code,
2898       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2899          ASTContext &ASTCtx) {
2900         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2901         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2902 
2903         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2904         ASSERT_THAT(FooDecl, NotNull());
2905 
2906         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2907         ASSERT_THAT(BarDecl, NotNull());
2908 
2909         const auto *FooVal = Env.getValue(*FooDecl);
2910         const auto *BarVal = Env.getValue(*BarDecl);
2911         EXPECT_TRUE(isa<IntegerValue>(FooVal));
2912         EXPECT_TRUE(isa<IntegerValue>(BarVal));
2913         EXPECT_EQ(FooVal, BarVal);
2914       });
2915 }
2916 
2917 TEST(TransferTest, IntegraltoBooleanCast) {
2918   std::string Code = R"(
2919     void target(int Foo) {
2920       bool Bar = Foo;
2921       // [[p]]
2922     }
2923   )";
2924   runDataflow(
2925       Code,
2926       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2927          ASTContext &ASTCtx) {
2928         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2929         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2930 
2931         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2932         ASSERT_THAT(FooDecl, NotNull());
2933 
2934         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2935         ASSERT_THAT(BarDecl, NotNull());
2936 
2937         const auto *FooVal = Env.getValue(*FooDecl);
2938         const auto *BarVal = Env.getValue(*BarDecl);
2939         EXPECT_TRUE(isa<IntegerValue>(FooVal));
2940         EXPECT_TRUE(isa<BoolValue>(BarVal));
2941       });
2942 }
2943 
2944 TEST(TransferTest, IntegralToBooleanCastFromBool) {
2945   std::string Code = R"(
2946     void target(bool Foo) {
2947       int Zab = Foo;
2948       bool Bar = Zab;
2949       // [[p]]
2950     }
2951   )";
2952   runDataflow(
2953       Code,
2954       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2955          ASTContext &ASTCtx) {
2956         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2957         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2958 
2959         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2960         ASSERT_THAT(FooDecl, NotNull());
2961 
2962         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2963         ASSERT_THAT(BarDecl, NotNull());
2964 
2965         const auto *FooVal = Env.getValue(*FooDecl);
2966         const auto *BarVal = Env.getValue(*BarDecl);
2967         EXPECT_TRUE(isa<BoolValue>(FooVal));
2968         EXPECT_TRUE(isa<BoolValue>(BarVal));
2969         EXPECT_EQ(FooVal, BarVal);
2970       });
2971 }
2972 
2973 TEST(TransferTest, NullToPointerCast) {
2974   std::string Code = R"(
2975     using my_nullptr_t = decltype(nullptr);
2976     struct Baz {};
2977     void target() {
2978       int *FooX = nullptr;
2979       int *FooY = nullptr;
2980       bool **Bar = nullptr;
2981       Baz *Baz = nullptr;
2982       my_nullptr_t Null = 0;
2983       // [[p]]
2984     }
2985   )";
2986   runDataflow(
2987       Code,
2988       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2989          ASTContext &ASTCtx) {
2990         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2991         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2992 
2993         const ValueDecl *FooXDecl = findValueDecl(ASTCtx, "FooX");
2994         ASSERT_THAT(FooXDecl, NotNull());
2995 
2996         const ValueDecl *FooYDecl = findValueDecl(ASTCtx, "FooY");
2997         ASSERT_THAT(FooYDecl, NotNull());
2998 
2999         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3000         ASSERT_THAT(BarDecl, NotNull());
3001 
3002         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3003         ASSERT_THAT(BazDecl, NotNull());
3004 
3005         const ValueDecl *NullDecl = findValueDecl(ASTCtx, "Null");
3006         ASSERT_THAT(NullDecl, NotNull());
3007 
3008         const auto *FooXVal = cast<PointerValue>(Env.getValue(*FooXDecl));
3009         const auto *FooYVal = cast<PointerValue>(Env.getValue(*FooYDecl));
3010         const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl));
3011         const auto *BazVal = cast<PointerValue>(Env.getValue(*BazDecl));
3012         const auto *NullVal = cast<PointerValue>(Env.getValue(*NullDecl));
3013 
3014         EXPECT_EQ(FooXVal, FooYVal);
3015         EXPECT_NE(FooXVal, BarVal);
3016         EXPECT_NE(FooXVal, BazVal);
3017         EXPECT_NE(BarVal, BazVal);
3018 
3019         const StorageLocation &FooPointeeLoc = FooXVal->getPointeeLoc();
3020         EXPECT_TRUE(isa<ScalarStorageLocation>(FooPointeeLoc));
3021         EXPECT_THAT(Env.getValue(FooPointeeLoc), IsNull());
3022 
3023         const StorageLocation &BarPointeeLoc = BarVal->getPointeeLoc();
3024         EXPECT_TRUE(isa<ScalarStorageLocation>(BarPointeeLoc));
3025         EXPECT_THAT(Env.getValue(BarPointeeLoc), IsNull());
3026 
3027         const StorageLocation &BazPointeeLoc = BazVal->getPointeeLoc();
3028         EXPECT_TRUE(isa<RecordStorageLocation>(BazPointeeLoc));
3029         EXPECT_THAT(Env.getValue(BazPointeeLoc), IsNull());
3030 
3031         const StorageLocation &NullPointeeLoc = NullVal->getPointeeLoc();
3032         EXPECT_TRUE(isa<ScalarStorageLocation>(NullPointeeLoc));
3033         EXPECT_THAT(Env.getValue(NullPointeeLoc), IsNull());
3034       });
3035 }
3036 
3037 TEST(TransferTest, PointerToMemberVariable) {
3038   std::string Code = R"(
3039     struct S {
3040       int i;
3041     };
3042     void target() {
3043       int S::*MemberPointer = &S::i;
3044       // [[p]]
3045     }
3046   )";
3047   runDataflow(
3048       Code,
3049       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3050          ASTContext &ASTCtx) {
3051         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3052 
3053         const ValueDecl *MemberPointerDecl =
3054             findValueDecl(ASTCtx, "MemberPointer");
3055         ASSERT_THAT(MemberPointerDecl, NotNull());
3056         ASSERT_THAT(Env.getValue(*MemberPointerDecl), IsNull());
3057       });
3058 }
3059 
3060 TEST(TransferTest, PointerToMemberFunction) {
3061   std::string Code = R"(
3062     struct S {
3063       void Method();
3064     };
3065     void target() {
3066       void (S::*MemberPointer)() = &S::Method;
3067       // [[p]]
3068     }
3069   )";
3070   runDataflow(
3071       Code,
3072       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3073          ASTContext &ASTCtx) {
3074         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3075 
3076         const ValueDecl *MemberPointerDecl =
3077             findValueDecl(ASTCtx, "MemberPointer");
3078         ASSERT_THAT(MemberPointerDecl, NotNull());
3079         ASSERT_THAT(Env.getValue(*MemberPointerDecl), IsNull());
3080       });
3081 }
3082 
3083 TEST(TransferTest, NullToMemberPointerCast) {
3084   std::string Code = R"(
3085     struct Foo {};
3086     void target() {
3087       int Foo::*MemberPointer = nullptr;
3088       // [[p]]
3089     }
3090   )";
3091   runDataflow(
3092       Code,
3093       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3094          ASTContext &ASTCtx) {
3095         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3096         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3097 
3098         const ValueDecl *MemberPointerDecl =
3099             findValueDecl(ASTCtx, "MemberPointer");
3100         ASSERT_THAT(MemberPointerDecl, NotNull());
3101         ASSERT_THAT(Env.getValue(*MemberPointerDecl), IsNull());
3102       });
3103 }
3104 
3105 TEST(TransferTest, AddrOfValue) {
3106   std::string Code = R"(
3107     void target() {
3108       int Foo;
3109       int *Bar = &Foo;
3110       // [[p]]
3111     }
3112   )";
3113   runDataflow(
3114       Code,
3115       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3116          ASTContext &ASTCtx) {
3117         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3118         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3119 
3120         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3121         ASSERT_THAT(FooDecl, NotNull());
3122 
3123         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3124         ASSERT_THAT(BarDecl, NotNull());
3125 
3126         const auto *FooLoc =
3127             cast<ScalarStorageLocation>(Env.getStorageLocation(*FooDecl));
3128         const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl));
3129         EXPECT_EQ(&BarVal->getPointeeLoc(), FooLoc);
3130       });
3131 }
3132 
3133 TEST(TransferTest, AddrOfReference) {
3134   std::string Code = R"(
3135     void target(int *Foo) {
3136       int *Bar = &(*Foo);
3137       // [[p]]
3138     }
3139   )";
3140   runDataflow(
3141       Code,
3142       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3143          ASTContext &ASTCtx) {
3144         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3145         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3146 
3147         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3148         ASSERT_THAT(FooDecl, NotNull());
3149 
3150         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3151         ASSERT_THAT(BarDecl, NotNull());
3152 
3153         const auto *FooVal = cast<PointerValue>(Env.getValue(*FooDecl));
3154         const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl));
3155         EXPECT_EQ(&BarVal->getPointeeLoc(), &FooVal->getPointeeLoc());
3156       });
3157 }
3158 
3159 TEST(TransferTest, CannotAnalyzeFunctionTemplate) {
3160   std::string Code = R"(
3161     template <typename T>
3162     void target() {}
3163   )";
3164   ASSERT_THAT_ERROR(
3165       checkDataflowWithNoopAnalysis(Code),
3166       llvm::FailedWithMessage("Cannot analyze templated declarations"));
3167 }
3168 
3169 TEST(TransferTest, CannotAnalyzeMethodOfClassTemplate) {
3170   std::string Code = R"(
3171     template <typename T>
3172     struct A {
3173       void target() {}
3174     };
3175   )";
3176   ASSERT_THAT_ERROR(
3177       checkDataflowWithNoopAnalysis(Code),
3178       llvm::FailedWithMessage("Cannot analyze templated declarations"));
3179 }
3180 
3181 TEST(TransferTest, VarDeclInitAssignConditionalOperator) {
3182   std::string Code = R"(
3183     struct A {};
3184 
3185     void target(A Foo, A Bar, bool Cond) {
3186       A Baz = Cond ?  Foo : Bar;
3187       /*[[p]]*/
3188     }
3189   )";
3190   runDataflow(
3191       Code,
3192       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3193          ASTContext &ASTCtx) {
3194         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3195         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3196 
3197         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3198         ASSERT_THAT(FooDecl, NotNull());
3199 
3200         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3201         ASSERT_THAT(BarDecl, NotNull());
3202 
3203         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3204         ASSERT_THAT(BazDecl, NotNull());
3205 
3206         const auto *FooVal = cast<RecordValue>(Env.getValue(*FooDecl));
3207         const auto *BarVal = cast<RecordValue>(Env.getValue(*BarDecl));
3208 
3209         const auto *BazVal = dyn_cast<RecordValue>(Env.getValue(*BazDecl));
3210         ASSERT_THAT(BazVal, NotNull());
3211 
3212         EXPECT_NE(BazVal, FooVal);
3213         EXPECT_NE(BazVal, BarVal);
3214       });
3215 }
3216 
3217 TEST(TransferTest, VarDeclInDoWhile) {
3218   std::string Code = R"(
3219     void target(int *Foo) {
3220       do {
3221         int Bar = *Foo;
3222         // [[in_loop]]
3223       } while (false);
3224       (void)0;
3225       // [[after_loop]]
3226     }
3227   )";
3228   runDataflow(
3229       Code,
3230       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3231          ASTContext &ASTCtx) {
3232         const Environment &EnvInLoop =
3233             getEnvironmentAtAnnotation(Results, "in_loop");
3234         const Environment &EnvAfterLoop =
3235             getEnvironmentAtAnnotation(Results, "after_loop");
3236 
3237         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3238         ASSERT_THAT(FooDecl, NotNull());
3239 
3240         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3241         ASSERT_THAT(BarDecl, NotNull());
3242 
3243         const auto *FooVal =
3244             cast<PointerValue>(EnvAfterLoop.getValue(*FooDecl));
3245         const auto *FooPointeeVal =
3246             cast<IntegerValue>(EnvAfterLoop.getValue(FooVal->getPointeeLoc()));
3247 
3248         const auto *BarVal = cast<IntegerValue>(EnvInLoop.getValue(*BarDecl));
3249         EXPECT_EQ(BarVal, FooPointeeVal);
3250 
3251         ASSERT_THAT(EnvAfterLoop.getValue(*BarDecl), IsNull());
3252       });
3253 }
3254 
3255 TEST(TransferTest, UnreachableAfterWhileTrue) {
3256   std::string Code = R"(
3257     void target() {
3258       while (true) {}
3259       (void)0;
3260       /*[[p]]*/
3261     }
3262   )";
3263   runDataflow(
3264       Code,
3265       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3266          ASTContext &ASTCtx) {
3267         // The node after the while-true is pruned because it is trivially
3268         // known to be unreachable.
3269         ASSERT_TRUE(Results.empty());
3270       });
3271 }
3272 
3273 TEST(TransferTest, AggregateInitialization) {
3274   std::string BracesCode = R"(
3275     struct A {
3276       int Foo;
3277     };
3278 
3279     struct B {
3280       int Bar;
3281       A Baz;
3282       int Qux;
3283     };
3284 
3285     void target(int BarArg, int FooArg, int QuxArg) {
3286       B Quux{BarArg, {FooArg}, QuxArg};
3287       B OtherB;
3288       /*[[p]]*/
3289     }
3290   )";
3291   std::string BraceElisionCode = R"(
3292     struct A {
3293       int Foo;
3294     };
3295 
3296     struct B {
3297       int Bar;
3298       A Baz;
3299       int Qux;
3300     };
3301 
3302     void target(int BarArg, int FooArg, int QuxArg) {
3303       B Quux = {BarArg, FooArg, QuxArg};
3304       B OtherB;
3305       /*[[p]]*/
3306     }
3307   )";
3308   for (const std::string &Code : {BracesCode, BraceElisionCode}) {
3309     runDataflow(
3310         Code,
3311         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3312            ASTContext &ASTCtx) {
3313           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3314           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3315 
3316           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3317           ASSERT_THAT(FooDecl, NotNull());
3318 
3319           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3320           ASSERT_THAT(BarDecl, NotNull());
3321 
3322           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3323           ASSERT_THAT(BazDecl, NotNull());
3324 
3325           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
3326           ASSERT_THAT(QuxDecl, NotNull());
3327 
3328           const ValueDecl *FooArgDecl = findValueDecl(ASTCtx, "FooArg");
3329           ASSERT_THAT(FooArgDecl, NotNull());
3330 
3331           const ValueDecl *BarArgDecl = findValueDecl(ASTCtx, "BarArg");
3332           ASSERT_THAT(BarArgDecl, NotNull());
3333 
3334           const ValueDecl *QuxArgDecl = findValueDecl(ASTCtx, "QuxArg");
3335           ASSERT_THAT(QuxArgDecl, NotNull());
3336 
3337           const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux");
3338           ASSERT_THAT(QuuxDecl, NotNull());
3339 
3340           const auto *FooArgVal = cast<IntegerValue>(Env.getValue(*FooArgDecl));
3341           const auto *BarArgVal = cast<IntegerValue>(Env.getValue(*BarArgDecl));
3342           const auto *QuxArgVal = cast<IntegerValue>(Env.getValue(*QuxArgDecl));
3343 
3344           const auto &QuuxLoc =
3345               *cast<RecordStorageLocation>(Env.getStorageLocation(*QuuxDecl));
3346           const auto &BazLoc =
3347               *cast<RecordStorageLocation>(QuuxLoc.getChild(*BazDecl));
3348 
3349           EXPECT_EQ(getFieldValue(&QuuxLoc, *BarDecl, Env), BarArgVal);
3350           EXPECT_EQ(getFieldValue(&BazLoc, *FooDecl, Env), FooArgVal);
3351           EXPECT_EQ(getFieldValue(&QuuxLoc, *QuxDecl, Env), QuxArgVal);
3352 
3353           // Check that fields initialized in an initializer list are always
3354           // modeled in other instances of the same type.
3355           const auto &OtherBLoc =
3356               getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "OtherB");
3357           EXPECT_THAT(OtherBLoc.getChild(*BarDecl), NotNull());
3358           EXPECT_THAT(OtherBLoc.getChild(*BazDecl), NotNull());
3359           EXPECT_THAT(OtherBLoc.getChild(*QuxDecl), NotNull());
3360         });
3361   }
3362 }
3363 
3364 TEST(TransferTest, AggregateInitializationReferenceField) {
3365   std::string Code = R"(
3366     struct S {
3367       int &RefField;
3368     };
3369 
3370     void target(int i) {
3371       S s = { i };
3372       /*[[p]]*/
3373     }
3374   )";
3375   runDataflow(
3376       Code,
3377       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3378          ASTContext &ASTCtx) {
3379         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3380 
3381         const ValueDecl *RefFieldDecl = findValueDecl(ASTCtx, "RefField");
3382 
3383         auto &ILoc = getLocForDecl<StorageLocation>(ASTCtx, Env, "i");
3384         auto &SLoc = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "s");
3385 
3386         EXPECT_EQ(SLoc.getChild(*RefFieldDecl), &ILoc);
3387       });
3388 }
3389 
3390 TEST(TransferTest, AggregateInitialization_NotExplicitlyInitializedField) {
3391   std::string Code = R"(
3392     struct S {
3393       int i1;
3394       int i2;
3395     };
3396 
3397     void target(int i) {
3398       S s = { i };
3399       /*[[p]]*/
3400     }
3401   )";
3402   runDataflow(
3403       Code,
3404       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3405          ASTContext &ASTCtx) {
3406         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3407 
3408         const ValueDecl *I1FieldDecl = findValueDecl(ASTCtx, "i1");
3409         const ValueDecl *I2FieldDecl = findValueDecl(ASTCtx, "i2");
3410 
3411         auto &SLoc = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "s");
3412 
3413         auto &IValue = getValueForDecl<IntegerValue>(ASTCtx, Env, "i");
3414         auto &I1Value =
3415             *cast<IntegerValue>(getFieldValue(&SLoc, *I1FieldDecl, Env));
3416         EXPECT_EQ(&I1Value, &IValue);
3417         auto &I2Value =
3418             *cast<IntegerValue>(getFieldValue(&SLoc, *I2FieldDecl, Env));
3419         EXPECT_NE(&I2Value, &IValue);
3420       });
3421 }
3422 
3423 TEST(TransferTest, AggregateInitializationFunctionPointer) {
3424   // This is a repro for an assertion failure.
3425   // nullptr takes on the type of a const function pointer, but its type was
3426   // asserted to be equal to the *unqualified* type of Field, which no longer
3427   // included the const.
3428   std::string Code = R"(
3429     struct S {
3430       void (*const Field)();
3431     };
3432 
3433     void target() {
3434       S s{nullptr};
3435     }
3436   )";
3437   runDataflow(
3438       Code,
3439       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3440          ASTContext &ASTCtx) {});
3441 }
3442 
3443 TEST(TransferTest, AssignToUnionMember) {
3444   std::string Code = R"(
3445     union A {
3446       int Foo;
3447     };
3448 
3449     void target(int Bar) {
3450       A Baz;
3451       Baz.Foo = Bar;
3452       // [[p]]
3453     }
3454   )";
3455   runDataflow(
3456       Code,
3457       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3458          ASTContext &ASTCtx) {
3459         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3460         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3461 
3462         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3463         ASSERT_THAT(BazDecl, NotNull());
3464         ASSERT_TRUE(BazDecl->getType()->isUnionType());
3465 
3466         auto BazFields = BazDecl->getType()->getAsRecordDecl()->fields();
3467         FieldDecl *FooDecl = nullptr;
3468         for (FieldDecl *Field : BazFields) {
3469           if (Field->getNameAsString() == "Foo") {
3470             FooDecl = Field;
3471           } else {
3472             FAIL() << "Unexpected field: " << Field->getNameAsString();
3473           }
3474         }
3475         ASSERT_THAT(FooDecl, NotNull());
3476 
3477         const auto *BazLoc = dyn_cast_or_null<RecordStorageLocation>(
3478             Env.getStorageLocation(*BazDecl));
3479         ASSERT_THAT(BazLoc, NotNull());
3480         ASSERT_THAT(Env.getValue(*BazLoc), NotNull());
3481 
3482         const auto *FooVal =
3483             cast<IntegerValue>(getFieldValue(BazLoc, *FooDecl, Env));
3484 
3485         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3486         ASSERT_THAT(BarDecl, NotNull());
3487         const auto *BarLoc = Env.getStorageLocation(*BarDecl);
3488         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
3489 
3490         EXPECT_EQ(Env.getValue(*BarLoc), FooVal);
3491       });
3492 }
3493 
3494 TEST(TransferTest, AssignFromBoolLiteral) {
3495   std::string Code = R"(
3496     void target() {
3497       bool Foo = true;
3498       bool Bar = false;
3499       // [[p]]
3500     }
3501   )";
3502   runDataflow(
3503       Code,
3504       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3505          ASTContext &ASTCtx) {
3506         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3507         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3508 
3509         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3510         ASSERT_THAT(FooDecl, NotNull());
3511 
3512         const auto *FooVal =
3513             dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
3514         ASSERT_THAT(FooVal, NotNull());
3515 
3516         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3517         ASSERT_THAT(BarDecl, NotNull());
3518 
3519         const auto *BarVal =
3520             dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
3521         ASSERT_THAT(BarVal, NotNull());
3522 
3523         EXPECT_EQ(FooVal, &Env.getBoolLiteralValue(true));
3524         EXPECT_EQ(BarVal, &Env.getBoolLiteralValue(false));
3525       });
3526 }
3527 
3528 TEST(TransferTest, AssignFromCompositeBoolExpression) {
3529   {
3530     std::string Code = R"(
3531     void target(bool Foo, bool Bar, bool Qux) {
3532       bool Baz = (Foo) && (Bar || Qux);
3533       // [[p]]
3534     }
3535   )";
3536     runDataflow(
3537         Code,
3538         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3539            ASTContext &ASTCtx) {
3540           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3541           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3542 
3543           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3544           ASSERT_THAT(FooDecl, NotNull());
3545 
3546           const auto *FooVal =
3547               dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
3548           ASSERT_THAT(FooVal, NotNull());
3549 
3550           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3551           ASSERT_THAT(BarDecl, NotNull());
3552 
3553           const auto *BarVal =
3554               dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
3555           ASSERT_THAT(BarVal, NotNull());
3556 
3557           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
3558           ASSERT_THAT(QuxDecl, NotNull());
3559 
3560           const auto *QuxVal =
3561               dyn_cast_or_null<BoolValue>(Env.getValue(*QuxDecl));
3562           ASSERT_THAT(QuxVal, NotNull());
3563 
3564           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3565           ASSERT_THAT(BazDecl, NotNull());
3566 
3567           const auto *BazVal =
3568               dyn_cast_or_null<BoolValue>(Env.getValue(*BazDecl));
3569           ASSERT_THAT(BazVal, NotNull());
3570           auto &A = Env.arena();
3571           EXPECT_EQ(&BazVal->formula(),
3572                     &A.makeAnd(FooVal->formula(),
3573                                A.makeOr(BarVal->formula(), QuxVal->formula())));
3574         });
3575   }
3576 
3577   {
3578     std::string Code = R"(
3579     void target(bool Foo, bool Bar, bool Qux) {
3580       bool Baz = (Foo && Qux) || (Bar);
3581       // [[p]]
3582     }
3583   )";
3584     runDataflow(
3585         Code,
3586         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3587            ASTContext &ASTCtx) {
3588           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3589           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3590 
3591           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3592           ASSERT_THAT(FooDecl, NotNull());
3593 
3594           const auto *FooVal =
3595               dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
3596           ASSERT_THAT(FooVal, NotNull());
3597 
3598           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3599           ASSERT_THAT(BarDecl, NotNull());
3600 
3601           const auto *BarVal =
3602               dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
3603           ASSERT_THAT(BarVal, NotNull());
3604 
3605           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
3606           ASSERT_THAT(QuxDecl, NotNull());
3607 
3608           const auto *QuxVal =
3609               dyn_cast_or_null<BoolValue>(Env.getValue(*QuxDecl));
3610           ASSERT_THAT(QuxVal, NotNull());
3611 
3612           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3613           ASSERT_THAT(BazDecl, NotNull());
3614 
3615           const auto *BazVal =
3616               dyn_cast_or_null<BoolValue>(Env.getValue(*BazDecl));
3617           ASSERT_THAT(BazVal, NotNull());
3618           auto &A = Env.arena();
3619           EXPECT_EQ(&BazVal->formula(),
3620                     &A.makeOr(A.makeAnd(FooVal->formula(), QuxVal->formula()),
3621                               BarVal->formula()));
3622         });
3623   }
3624 
3625   {
3626     std::string Code = R"(
3627       void target(bool A, bool B, bool C, bool D) {
3628         bool Foo = ((A && B) && C) && D;
3629         // [[p]]
3630       }
3631     )";
3632     runDataflow(
3633         Code,
3634         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3635            ASTContext &ASTCtx) {
3636           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3637           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3638 
3639           const ValueDecl *ADecl = findValueDecl(ASTCtx, "A");
3640           ASSERT_THAT(ADecl, NotNull());
3641 
3642           const auto *AVal = dyn_cast_or_null<BoolValue>(Env.getValue(*ADecl));
3643           ASSERT_THAT(AVal, NotNull());
3644 
3645           const ValueDecl *BDecl = findValueDecl(ASTCtx, "B");
3646           ASSERT_THAT(BDecl, NotNull());
3647 
3648           const auto *BVal = dyn_cast_or_null<BoolValue>(Env.getValue(*BDecl));
3649           ASSERT_THAT(BVal, NotNull());
3650 
3651           const ValueDecl *CDecl = findValueDecl(ASTCtx, "C");
3652           ASSERT_THAT(CDecl, NotNull());
3653 
3654           const auto *CVal = dyn_cast_or_null<BoolValue>(Env.getValue(*CDecl));
3655           ASSERT_THAT(CVal, NotNull());
3656 
3657           const ValueDecl *DDecl = findValueDecl(ASTCtx, "D");
3658           ASSERT_THAT(DDecl, NotNull());
3659 
3660           const auto *DVal = dyn_cast_or_null<BoolValue>(Env.getValue(*DDecl));
3661           ASSERT_THAT(DVal, NotNull());
3662 
3663           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3664           ASSERT_THAT(FooDecl, NotNull());
3665 
3666           const auto *FooVal =
3667               dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
3668           ASSERT_THAT(FooVal, NotNull());
3669           auto &A = Env.arena();
3670           EXPECT_EQ(
3671               &FooVal->formula(),
3672               &A.makeAnd(A.makeAnd(A.makeAnd(AVal->formula(), BVal->formula()),
3673                                    CVal->formula()),
3674                          DVal->formula()));
3675         });
3676   }
3677 }
3678 
3679 TEST(TransferTest, AssignFromBoolNegation) {
3680   std::string Code = R"(
3681     void target() {
3682       bool Foo = true;
3683       bool Bar = !(Foo);
3684       // [[p]]
3685     }
3686   )";
3687   runDataflow(
3688       Code,
3689       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3690          ASTContext &ASTCtx) {
3691         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3692         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3693 
3694         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3695         ASSERT_THAT(FooDecl, NotNull());
3696 
3697         const auto *FooVal =
3698             dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
3699         ASSERT_THAT(FooVal, NotNull());
3700 
3701         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3702         ASSERT_THAT(BarDecl, NotNull());
3703 
3704         const auto *BarVal =
3705             dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
3706         ASSERT_THAT(BarVal, NotNull());
3707         auto &A = Env.arena();
3708         EXPECT_EQ(&BarVal->formula(), &A.makeNot(FooVal->formula()));
3709       });
3710 }
3711 
3712 TEST(TransferTest, BuiltinExpect) {
3713   std::string Code = R"(
3714     void target(long Foo) {
3715       long Bar = __builtin_expect(Foo, true);
3716       /*[[p]]*/
3717     }
3718   )";
3719   runDataflow(
3720       Code,
3721       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3722          ASTContext &ASTCtx) {
3723         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3724         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3725 
3726         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3727         ASSERT_THAT(FooDecl, NotNull());
3728 
3729         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3730         ASSERT_THAT(BarDecl, NotNull());
3731 
3732         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
3733       });
3734 }
3735 
3736 // `__builtin_expect` takes and returns a `long` argument, so other types
3737 // involve casts. This verifies that we identify the input and output in that
3738 // case.
3739 TEST(TransferTest, BuiltinExpectBoolArg) {
3740   std::string Code = R"(
3741     void target(bool Foo) {
3742       bool Bar = __builtin_expect(Foo, true);
3743       /*[[p]]*/
3744     }
3745   )";
3746   runDataflow(
3747       Code,
3748       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3749          ASTContext &ASTCtx) {
3750         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3751         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3752 
3753         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3754         ASSERT_THAT(FooDecl, NotNull());
3755 
3756         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3757         ASSERT_THAT(BarDecl, NotNull());
3758 
3759         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
3760       });
3761 }
3762 
3763 TEST(TransferTest, BuiltinUnreachable) {
3764   std::string Code = R"(
3765     void target(bool Foo) {
3766       bool Bar = false;
3767       if (Foo)
3768         Bar = Foo;
3769       else
3770         __builtin_unreachable();
3771       (void)0;
3772       /*[[p]]*/
3773     }
3774   )";
3775   runDataflow(
3776       Code,
3777       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3778          ASTContext &ASTCtx) {
3779         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3780         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3781 
3782         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3783         ASSERT_THAT(FooDecl, NotNull());
3784 
3785         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3786         ASSERT_THAT(BarDecl, NotNull());
3787 
3788         // `__builtin_unreachable` promises that the code is
3789         // unreachable, so the compiler treats the "then" branch as the
3790         // only possible predecessor of this statement.
3791         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
3792       });
3793 }
3794 
3795 TEST(TransferTest, BuiltinTrap) {
3796   std::string Code = R"(
3797     void target(bool Foo) {
3798       bool Bar = false;
3799       if (Foo)
3800         Bar = Foo;
3801       else
3802         __builtin_trap();
3803       (void)0;
3804       /*[[p]]*/
3805     }
3806   )";
3807   runDataflow(
3808       Code,
3809       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3810          ASTContext &ASTCtx) {
3811         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3812         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3813 
3814         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3815         ASSERT_THAT(FooDecl, NotNull());
3816 
3817         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3818         ASSERT_THAT(BarDecl, NotNull());
3819 
3820         // `__builtin_trap` ensures program termination, so only the
3821         // "then" branch is a predecessor of this statement.
3822         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
3823       });
3824 }
3825 
3826 TEST(TransferTest, BuiltinDebugTrap) {
3827   std::string Code = R"(
3828     void target(bool Foo) {
3829       bool Bar = false;
3830       if (Foo)
3831         Bar = Foo;
3832       else
3833         __builtin_debugtrap();
3834       (void)0;
3835       /*[[p]]*/
3836     }
3837   )";
3838   runDataflow(
3839       Code,
3840       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3841          ASTContext &ASTCtx) {
3842         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3843         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3844 
3845         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3846         ASSERT_THAT(FooDecl, NotNull());
3847 
3848         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3849         ASSERT_THAT(BarDecl, NotNull());
3850 
3851         // `__builtin_debugtrap` doesn't ensure program termination.
3852         EXPECT_NE(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
3853       });
3854 }
3855 
3856 TEST(TransferTest, StaticIntSingleVarDecl) {
3857   std::string Code = R"(
3858     void target() {
3859       static int Foo;
3860       // [[p]]
3861     }
3862   )";
3863   runDataflow(
3864       Code,
3865       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3866          ASTContext &ASTCtx) {
3867         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3868         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3869 
3870         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3871         ASSERT_THAT(FooDecl, NotNull());
3872 
3873         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
3874         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
3875 
3876         const Value *FooVal = Env.getValue(*FooLoc);
3877         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
3878       });
3879 }
3880 
3881 TEST(TransferTest, StaticIntGroupVarDecl) {
3882   std::string Code = R"(
3883     void target() {
3884       static int Foo, Bar;
3885       (void)0;
3886       // [[p]]
3887     }
3888   )";
3889   runDataflow(
3890       Code,
3891       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3892          ASTContext &ASTCtx) {
3893         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3894         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3895 
3896         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3897         ASSERT_THAT(FooDecl, NotNull());
3898 
3899         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3900         ASSERT_THAT(BarDecl, NotNull());
3901 
3902         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
3903         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
3904 
3905         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
3906         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
3907 
3908         const Value *FooVal = Env.getValue(*FooLoc);
3909         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
3910 
3911         const Value *BarVal = Env.getValue(*BarLoc);
3912         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
3913 
3914         EXPECT_NE(FooVal, BarVal);
3915       });
3916 }
3917 
3918 TEST(TransferTest, GlobalIntVarDecl) {
3919   std::string Code = R"(
3920     static int Foo;
3921 
3922     void target() {
3923       int Bar = Foo;
3924       int Baz = Foo;
3925       // [[p]]
3926     }
3927   )";
3928   runDataflow(
3929       Code,
3930       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3931          ASTContext &ASTCtx) {
3932         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3933         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3934 
3935         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3936         ASSERT_THAT(BarDecl, NotNull());
3937 
3938         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3939         ASSERT_THAT(BazDecl, NotNull());
3940 
3941         const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
3942         const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl));
3943         EXPECT_EQ(BarVal, BazVal);
3944       });
3945 }
3946 
3947 TEST(TransferTest, StaticMemberIntVarDecl) {
3948   std::string Code = R"(
3949     struct A {
3950       static int Foo;
3951     };
3952 
3953     void target(A a) {
3954       int Bar = a.Foo;
3955       int Baz = a.Foo;
3956       // [[p]]
3957     }
3958   )";
3959   runDataflow(
3960       Code,
3961       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3962          ASTContext &ASTCtx) {
3963         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3964         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3965 
3966         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3967         ASSERT_THAT(BarDecl, NotNull());
3968 
3969         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3970         ASSERT_THAT(BazDecl, NotNull());
3971 
3972         const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
3973         const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl));
3974         EXPECT_EQ(BarVal, BazVal);
3975       });
3976 }
3977 
3978 TEST(TransferTest, StaticMemberRefVarDecl) {
3979   std::string Code = R"(
3980     struct A {
3981       static int &Foo;
3982     };
3983 
3984     void target(A a) {
3985       int Bar = a.Foo;
3986       int Baz = a.Foo;
3987       // [[p]]
3988     }
3989   )";
3990   runDataflow(
3991       Code,
3992       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3993          ASTContext &ASTCtx) {
3994         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3995         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3996 
3997         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3998         ASSERT_THAT(BarDecl, NotNull());
3999 
4000         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4001         ASSERT_THAT(BazDecl, NotNull());
4002 
4003         const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
4004         const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl));
4005         EXPECT_EQ(BarVal, BazVal);
4006       });
4007 }
4008 
4009 TEST(TransferTest, AssignMemberBeforeCopy) {
4010   std::string Code = R"(
4011     struct A {
4012       int Foo;
4013     };
4014 
4015     void target() {
4016       A A1;
4017       A A2;
4018       int Bar;
4019       A1.Foo = Bar;
4020       A2 = A1;
4021       // [[p]]
4022     }
4023   )";
4024   runDataflow(
4025       Code,
4026       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4027          ASTContext &ASTCtx) {
4028         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4029         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4030 
4031         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4032         ASSERT_THAT(FooDecl, NotNull());
4033 
4034         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4035         ASSERT_THAT(BarDecl, NotNull());
4036 
4037         const ValueDecl *A1Decl = findValueDecl(ASTCtx, "A1");
4038         ASSERT_THAT(A1Decl, NotNull());
4039 
4040         const ValueDecl *A2Decl = findValueDecl(ASTCtx, "A2");
4041         ASSERT_THAT(A2Decl, NotNull());
4042 
4043         const auto *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
4044 
4045         const auto &A2Loc =
4046             *cast<RecordStorageLocation>(Env.getStorageLocation(*A2Decl));
4047         EXPECT_EQ(getFieldValue(&A2Loc, *FooDecl, Env), BarVal);
4048       });
4049 }
4050 
4051 TEST(TransferTest, BooleanEquality) {
4052   std::string Code = R"(
4053     void target(bool Bar) {
4054       bool Foo = true;
4055       if (Bar == Foo) {
4056         (void)0;
4057         /*[[p-then]]*/
4058       } else {
4059         (void)0;
4060         /*[[p-else]]*/
4061       }
4062     }
4063   )";
4064   runDataflow(
4065       Code,
4066       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4067          ASTContext &ASTCtx) {
4068         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-then", "p-else"));
4069         const Environment &EnvThen =
4070             getEnvironmentAtAnnotation(Results, "p-then");
4071         const Environment &EnvElse =
4072             getEnvironmentAtAnnotation(Results, "p-else");
4073 
4074         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4075         ASSERT_THAT(BarDecl, NotNull());
4076 
4077         auto &BarValThen = getFormula(*BarDecl, EnvThen);
4078         EXPECT_TRUE(EnvThen.proves(BarValThen));
4079 
4080         auto &BarValElse = getFormula(*BarDecl, EnvElse);
4081         EXPECT_TRUE(EnvElse.proves(EnvElse.arena().makeNot(BarValElse)));
4082       });
4083 }
4084 
4085 TEST(TransferTest, BooleanInequality) {
4086   std::string Code = R"(
4087     void target(bool Bar) {
4088       bool Foo = true;
4089       if (Bar != Foo) {
4090         (void)0;
4091         /*[[p-then]]*/
4092       } else {
4093         (void)0;
4094         /*[[p-else]]*/
4095       }
4096     }
4097   )";
4098   runDataflow(
4099       Code,
4100       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4101          ASTContext &ASTCtx) {
4102         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-then", "p-else"));
4103         const Environment &EnvThen =
4104             getEnvironmentAtAnnotation(Results, "p-then");
4105         const Environment &EnvElse =
4106             getEnvironmentAtAnnotation(Results, "p-else");
4107 
4108         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4109         ASSERT_THAT(BarDecl, NotNull());
4110 
4111         auto &BarValThen = getFormula(*BarDecl, EnvThen);
4112         EXPECT_TRUE(EnvThen.proves(EnvThen.arena().makeNot(BarValThen)));
4113 
4114         auto &BarValElse = getFormula(*BarDecl, EnvElse);
4115         EXPECT_TRUE(EnvElse.proves(BarValElse));
4116       });
4117 }
4118 
4119 TEST(TransferTest, IntegerLiteralEquality) {
4120   std::string Code = R"(
4121     void target() {
4122       bool equal = (42 == 42);
4123       // [[p]]
4124     }
4125   )";
4126   runDataflow(
4127       Code,
4128       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4129          ASTContext &ASTCtx) {
4130         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4131 
4132         auto &Equal =
4133             getValueForDecl<BoolValue>(ASTCtx, Env, "equal").formula();
4134         EXPECT_TRUE(Env.proves(Equal));
4135       });
4136 }
4137 
4138 TEST(TransferTest, CorrelatedBranches) {
4139   std::string Code = R"(
4140     void target(bool B, bool C) {
4141       if (B) {
4142         return;
4143       }
4144       (void)0;
4145       /*[[p0]]*/
4146       if (C) {
4147         B = true;
4148         /*[[p1]]*/
4149       }
4150       if (B) {
4151         (void)0;
4152         /*[[p2]]*/
4153       }
4154     }
4155   )";
4156   runDataflow(
4157       Code,
4158       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4159          ASTContext &ASTCtx) {
4160         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p0", "p1", "p2"));
4161 
4162         const ValueDecl *CDecl = findValueDecl(ASTCtx, "C");
4163         ASSERT_THAT(CDecl, NotNull());
4164 
4165         {
4166           const Environment &Env = getEnvironmentAtAnnotation(Results, "p0");
4167           const ValueDecl *BDecl = findValueDecl(ASTCtx, "B");
4168           ASSERT_THAT(BDecl, NotNull());
4169           auto &BVal = getFormula(*BDecl, Env);
4170 
4171           EXPECT_TRUE(Env.proves(Env.arena().makeNot(BVal)));
4172         }
4173 
4174         {
4175           const Environment &Env = getEnvironmentAtAnnotation(Results, "p1");
4176           auto &CVal = getFormula(*CDecl, Env);
4177           EXPECT_TRUE(Env.proves(CVal));
4178         }
4179 
4180         {
4181           const Environment &Env = getEnvironmentAtAnnotation(Results, "p2");
4182           auto &CVal = getFormula(*CDecl, Env);
4183           EXPECT_TRUE(Env.proves(CVal));
4184         }
4185       });
4186 }
4187 
4188 TEST(TransferTest, LoopWithAssignmentConverges) {
4189   std::string Code = R"(
4190     bool foo();
4191 
4192     void target() {
4193        do {
4194         bool Bar = foo();
4195         if (Bar) break;
4196         (void)Bar;
4197         /*[[p]]*/
4198       } while (true);
4199     }
4200   )";
4201   // The key property that we are verifying is implicit in `runDataflow` --
4202   // namely, that the analysis succeeds, rather than hitting the maximum number
4203   // of iterations.
4204   runDataflow(
4205       Code,
4206       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4207          ASTContext &ASTCtx) {
4208         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4209         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4210 
4211         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4212         ASSERT_THAT(BarDecl, NotNull());
4213 
4214         auto &BarVal = getFormula(*BarDecl, Env);
4215         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BarVal)));
4216       });
4217 }
4218 
4219 TEST(TransferTest, LoopWithStagedAssignments) {
4220   std::string Code = R"(
4221     bool foo();
4222 
4223     void target() {
4224       bool Bar = false;
4225       bool Err = false;
4226       while (foo()) {
4227         if (Bar)
4228           Err = true;
4229         Bar = true;
4230         /*[[p]]*/
4231       }
4232     }
4233   )";
4234   runDataflow(
4235       Code,
4236       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4237          ASTContext &ASTCtx) {
4238         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4239         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4240 
4241         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4242         ASSERT_THAT(BarDecl, NotNull());
4243         const ValueDecl *ErrDecl = findValueDecl(ASTCtx, "Err");
4244         ASSERT_THAT(ErrDecl, NotNull());
4245 
4246         auto &BarVal = getFormula(*BarDecl, Env);
4247         auto &ErrVal = getFormula(*ErrDecl, Env);
4248         EXPECT_TRUE(Env.proves(BarVal));
4249         // An unsound analysis, for example only evaluating the loop once, can
4250         // conclude that `Err` is false. So, we test that this conclusion is not
4251         // reached.
4252         EXPECT_FALSE(Env.proves(Env.arena().makeNot(ErrVal)));
4253       });
4254 }
4255 
4256 TEST(TransferTest, LoopWithReferenceAssignmentConverges) {
4257   std::string Code = R"(
4258     bool &foo();
4259 
4260     void target() {
4261        do {
4262         bool& Bar = foo();
4263         if (Bar) break;
4264         (void)Bar;
4265         /*[[p]]*/
4266       } while (true);
4267     }
4268   )";
4269   // The key property that we are verifying is that the analysis succeeds,
4270   // rather than hitting the maximum number of iterations.
4271   runDataflow(
4272       Code,
4273       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4274          ASTContext &ASTCtx) {
4275         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4276         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4277 
4278         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4279         ASSERT_THAT(BarDecl, NotNull());
4280 
4281         auto &BarVal = getFormula(*BarDecl, Env);
4282         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BarVal)));
4283       });
4284 }
4285 
4286 TEST(TransferTest, LoopWithStructReferenceAssignmentConverges) {
4287   std::string Code = R"(
4288     struct Lookup {
4289       int x;
4290     };
4291 
4292     void target(Lookup val, bool b) {
4293       const Lookup* l = nullptr;
4294       while (b) {
4295         l = &val;
4296         /*[[p-inner]]*/
4297       }
4298       (void)0;
4299       /*[[p-outer]]*/
4300     }
4301   )";
4302   // The key property that we are verifying is implicit in `runDataflow` --
4303   // namely, that the analysis succeeds, rather than hitting the maximum number
4304   // of iterations.
4305   runDataflow(
4306       Code,
4307       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4308          ASTContext &ASTCtx) {
4309         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-inner", "p-outer"));
4310         const Environment &InnerEnv =
4311             getEnvironmentAtAnnotation(Results, "p-inner");
4312         const Environment &OuterEnv =
4313             getEnvironmentAtAnnotation(Results, "p-outer");
4314 
4315         const ValueDecl *ValDecl = findValueDecl(ASTCtx, "val");
4316         ASSERT_THAT(ValDecl, NotNull());
4317 
4318         const ValueDecl *LDecl = findValueDecl(ASTCtx, "l");
4319         ASSERT_THAT(LDecl, NotNull());
4320 
4321         // Inner.
4322         auto *LVal = dyn_cast<PointerValue>(InnerEnv.getValue(*LDecl));
4323         ASSERT_THAT(LVal, NotNull());
4324 
4325         EXPECT_EQ(&LVal->getPointeeLoc(),
4326                   InnerEnv.getStorageLocation(*ValDecl));
4327 
4328         // Outer.
4329         LVal = dyn_cast<PointerValue>(OuterEnv.getValue(*LDecl));
4330         ASSERT_THAT(LVal, NotNull());
4331 
4332         // The loop body may not have been executed, so we should not conclude
4333         // that `l` points to `val`.
4334         EXPECT_NE(&LVal->getPointeeLoc(),
4335                   OuterEnv.getStorageLocation(*ValDecl));
4336       });
4337 }
4338 
4339 TEST(TransferTest, LoopDereferencingChangingPointerConverges) {
4340   std::string Code = R"cc(
4341     bool some_condition();
4342 
4343     void target(int i1, int i2) {
4344       int *p = &i1;
4345       while (true) {
4346         (void)*p;
4347         if (some_condition())
4348           p = &i1;
4349         else
4350           p = &i2;
4351       }
4352     }
4353   )cc";
4354   ASSERT_THAT_ERROR(checkDataflowWithNoopAnalysis(Code), llvm::Succeeded());
4355 }
4356 
4357 TEST(TransferTest, LoopDereferencingChangingRecordPointerConverges) {
4358   std::string Code = R"cc(
4359     struct Lookup {
4360       int x;
4361     };
4362 
4363     bool some_condition();
4364 
4365     void target(Lookup l1, Lookup l2) {
4366       Lookup *l = &l1;
4367       while (true) {
4368         (void)l->x;
4369         if (some_condition())
4370           l = &l1;
4371         else
4372           l = &l2;
4373       }
4374     }
4375   )cc";
4376   ASSERT_THAT_ERROR(checkDataflowWithNoopAnalysis(Code), llvm::Succeeded());
4377 }
4378 
4379 TEST(TransferTest, LoopWithShortCircuitedConditionConverges) {
4380   std::string Code = R"cc(
4381     bool foo();
4382 
4383     void target() {
4384       bool c = false;
4385       while (foo() || foo()) {
4386         c = true;
4387       }
4388     }
4389   )cc";
4390   ASSERT_THAT_ERROR(checkDataflowWithNoopAnalysis(Code), llvm::Succeeded());
4391 }
4392 
4393 TEST(TransferTest, LoopCanProveInvariantForBoolean) {
4394   // Check that we can prove `b` is always false in the loop.
4395   // This test exercises the logic in `widenDistinctValues()` that preserves
4396   // information if the boolean can be proved to be either true or false in both
4397   // the previous and current iteration.
4398   std::string Code = R"cc(
4399     int return_int();
4400     void target() {
4401       bool b = return_int() == 0;
4402       if (b) return;
4403       while (true) {
4404         b;
4405         // [[p]]
4406         b = return_int() == 0;
4407         if (b) return;
4408       }
4409     }
4410   )cc";
4411   runDataflow(
4412       Code,
4413       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4414          ASTContext &ASTCtx) {
4415         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4416         auto &BVal = getValueForDecl<BoolValue>(ASTCtx, Env, "b");
4417         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BVal.formula())));
4418       });
4419 }
4420 
4421 TEST(TransferTest, DoesNotCrashOnUnionThisExpr) {
4422   std::string Code = R"(
4423     union Union {
4424       int A;
4425       float B;
4426     };
4427 
4428     void foo() {
4429       Union A;
4430       Union B;
4431       A = B;
4432     }
4433   )";
4434   // This is a crash regression test when calling the transfer function on a
4435   // `CXXThisExpr` that refers to a union.
4436   runDataflow(
4437       Code,
4438       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &,
4439          ASTContext &) {},
4440       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator=");
4441 }
4442 
4443 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToRefs) {
4444   std::string Code = R"(
4445     struct A {
4446       int Foo;
4447       int Bar;
4448     };
4449 
4450     void target() {
4451       int Qux;
4452       A Baz;
4453       Baz.Foo = Qux;
4454       auto &FooRef = Baz.Foo;
4455       auto &BarRef = Baz.Bar;
4456       auto &[BoundFooRef, BoundBarRef] = Baz;
4457       // [[p]]
4458     }
4459   )";
4460   runDataflow(
4461       Code,
4462       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4463          ASTContext &ASTCtx) {
4464         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4465         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4466 
4467         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
4468         ASSERT_THAT(FooRefDecl, NotNull());
4469 
4470         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
4471         ASSERT_THAT(BarRefDecl, NotNull());
4472 
4473         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
4474         ASSERT_THAT(QuxDecl, NotNull());
4475 
4476         const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef");
4477         ASSERT_THAT(BoundFooRefDecl, NotNull());
4478 
4479         const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef");
4480         ASSERT_THAT(BoundBarRefDecl, NotNull());
4481 
4482         const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl);
4483         ASSERT_THAT(FooRefLoc, NotNull());
4484 
4485         const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl);
4486         ASSERT_THAT(BarRefLoc, NotNull());
4487 
4488         const Value *QuxVal = Env.getValue(*QuxDecl);
4489         ASSERT_THAT(QuxVal, NotNull());
4490 
4491         const StorageLocation *BoundFooRefLoc =
4492             Env.getStorageLocation(*BoundFooRefDecl);
4493         EXPECT_EQ(BoundFooRefLoc, FooRefLoc);
4494 
4495         const StorageLocation *BoundBarRefLoc =
4496             Env.getStorageLocation(*BoundBarRefDecl);
4497         EXPECT_EQ(BoundBarRefLoc, BarRefLoc);
4498 
4499         EXPECT_EQ(Env.getValue(*BoundFooRefDecl), QuxVal);
4500       });
4501 }
4502 
4503 TEST(TransferTest, StructuredBindingAssignFromStructRefMembersToRefs) {
4504   std::string Code = R"(
4505     struct A {
4506       int &Foo;
4507       int &Bar;
4508     };
4509 
4510     void target(A Baz) {
4511       int Qux;
4512       Baz.Foo = Qux;
4513       auto &FooRef = Baz.Foo;
4514       auto &BarRef = Baz.Bar;
4515       auto &[BoundFooRef, BoundBarRef] = Baz;
4516       // [[p]]
4517     }
4518   )";
4519   runDataflow(
4520       Code,
4521       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4522          ASTContext &ASTCtx) {
4523         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4524         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4525 
4526         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
4527         ASSERT_THAT(FooRefDecl, NotNull());
4528 
4529         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
4530         ASSERT_THAT(BarRefDecl, NotNull());
4531 
4532         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
4533         ASSERT_THAT(QuxDecl, NotNull());
4534 
4535         const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef");
4536         ASSERT_THAT(BoundFooRefDecl, NotNull());
4537 
4538         const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef");
4539         ASSERT_THAT(BoundBarRefDecl, NotNull());
4540 
4541         const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl);
4542         ASSERT_THAT(FooRefLoc, NotNull());
4543 
4544         const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl);
4545         ASSERT_THAT(BarRefLoc, NotNull());
4546 
4547         const Value *QuxVal = Env.getValue(*QuxDecl);
4548         ASSERT_THAT(QuxVal, NotNull());
4549 
4550         const StorageLocation *BoundFooRefLoc =
4551             Env.getStorageLocation(*BoundFooRefDecl);
4552         EXPECT_EQ(BoundFooRefLoc, FooRefLoc);
4553 
4554         const StorageLocation *BoundBarRefLoc =
4555             Env.getStorageLocation(*BoundBarRefDecl);
4556         EXPECT_EQ(BoundBarRefLoc, BarRefLoc);
4557 
4558         EXPECT_EQ(Env.getValue(*BoundFooRefDecl), QuxVal);
4559       });
4560 }
4561 
4562 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToInts) {
4563   std::string Code = R"(
4564     struct A {
4565       int Foo;
4566       int Bar;
4567     };
4568 
4569     void target() {
4570       int Qux;
4571       A Baz;
4572       Baz.Foo = Qux;
4573       auto &FooRef = Baz.Foo;
4574       auto &BarRef = Baz.Bar;
4575       auto [BoundFoo, BoundBar] = Baz;
4576       // [[p]]
4577     }
4578   )";
4579   runDataflow(
4580       Code,
4581       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4582          ASTContext &ASTCtx) {
4583         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4584         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4585 
4586         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
4587         ASSERT_THAT(FooRefDecl, NotNull());
4588 
4589         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
4590         ASSERT_THAT(BarRefDecl, NotNull());
4591 
4592         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
4593         ASSERT_THAT(BoundFooDecl, NotNull());
4594 
4595         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
4596         ASSERT_THAT(BoundBarDecl, NotNull());
4597 
4598         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
4599         ASSERT_THAT(QuxDecl, NotNull());
4600 
4601         const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl);
4602         ASSERT_THAT(FooRefLoc, NotNull());
4603 
4604         const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl);
4605         ASSERT_THAT(BarRefLoc, NotNull());
4606 
4607         const Value *QuxVal = Env.getValue(*QuxDecl);
4608         ASSERT_THAT(QuxVal, NotNull());
4609 
4610         const StorageLocation *BoundFooLoc =
4611             Env.getStorageLocation(*BoundFooDecl);
4612         EXPECT_NE(BoundFooLoc, FooRefLoc);
4613 
4614         const StorageLocation *BoundBarLoc =
4615             Env.getStorageLocation(*BoundBarDecl);
4616         EXPECT_NE(BoundBarLoc, BarRefLoc);
4617 
4618         EXPECT_EQ(Env.getValue(*BoundFooDecl), QuxVal);
4619       });
4620 }
4621 
4622 TEST(TransferTest, StructuredBindingAssignFromTupleLikeType) {
4623   std::string Code = R"(
4624     namespace std {
4625     using size_t = int;
4626     template <class> struct tuple_size;
4627     template <std::size_t, class> struct tuple_element;
4628     template <class...> class tuple;
4629 
4630     namespace {
4631     template <class T, T v>
4632     struct size_helper { static const T value = v; };
4633     } // namespace
4634 
4635     template <class... T>
4636     struct tuple_size<tuple<T...>> : size_helper<std::size_t, sizeof...(T)> {};
4637 
4638     template <std::size_t I, class... T>
4639     struct tuple_element<I, tuple<T...>> {
4640       using type =  __type_pack_element<I, T...>;
4641     };
4642 
4643     template <class...> class tuple {};
4644 
4645     template <std::size_t I, class... T>
4646     typename tuple_element<I, tuple<T...>>::type get(tuple<T...>);
4647     } // namespace std
4648 
4649     std::tuple<bool, int> makeTuple();
4650 
4651     void target(bool B) {
4652       auto [BoundFoo, BoundBar] = makeTuple();
4653       bool Baz;
4654       // Include if-then-else to test interaction of `BindingDecl` with join.
4655       if (B) {
4656         Baz = BoundFoo;
4657         (void)BoundBar;
4658         // [[p1]]
4659       } else {
4660         Baz = BoundFoo;
4661       }
4662       (void)0;
4663       // [[p2]]
4664     }
4665   )";
4666   runDataflow(
4667       Code,
4668       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4669          ASTContext &ASTCtx) {
4670         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
4671         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
4672 
4673         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
4674         ASSERT_THAT(BoundFooDecl, NotNull());
4675 
4676         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
4677         ASSERT_THAT(BoundBarDecl, NotNull());
4678 
4679         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4680         ASSERT_THAT(BazDecl, NotNull());
4681 
4682         // BindingDecls always map to references -- either lvalue or rvalue, so
4683         // we still need to skip here.
4684         const Value *BoundFooValue = Env1.getValue(*BoundFooDecl);
4685         ASSERT_THAT(BoundFooValue, NotNull());
4686         EXPECT_TRUE(isa<BoolValue>(BoundFooValue));
4687 
4688         const Value *BoundBarValue = Env1.getValue(*BoundBarDecl);
4689         ASSERT_THAT(BoundBarValue, NotNull());
4690         EXPECT_TRUE(isa<IntegerValue>(BoundBarValue));
4691 
4692         // Test that a `DeclRefExpr` to a `BindingDecl` works as expected.
4693         EXPECT_EQ(Env1.getValue(*BazDecl), BoundFooValue);
4694 
4695         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
4696 
4697         // Test that `BoundFooDecl` retains the value we expect, after the join.
4698         BoundFooValue = Env2.getValue(*BoundFooDecl);
4699         EXPECT_EQ(Env2.getValue(*BazDecl), BoundFooValue);
4700       });
4701 }
4702 
4703 TEST(TransferTest, StructuredBindingAssignRefFromTupleLikeType) {
4704   std::string Code = R"(
4705     namespace std {
4706     using size_t = int;
4707     template <class> struct tuple_size;
4708     template <std::size_t, class> struct tuple_element;
4709     template <class...> class tuple;
4710 
4711     namespace {
4712     template <class T, T v>
4713     struct size_helper { static const T value = v; };
4714     } // namespace
4715 
4716     template <class... T>
4717     struct tuple_size<tuple<T...>> : size_helper<std::size_t, sizeof...(T)> {};
4718 
4719     template <std::size_t I, class... T>
4720     struct tuple_element<I, tuple<T...>> {
4721       using type =  __type_pack_element<I, T...>;
4722     };
4723 
4724     template <class...> class tuple {};
4725 
4726     template <std::size_t I, class... T>
4727     typename tuple_element<I, tuple<T...>>::type get(tuple<T...>);
4728     } // namespace std
4729 
4730     std::tuple<bool, int> &getTuple();
4731 
4732     void target(bool B) {
4733       auto &[BoundFoo, BoundBar] = getTuple();
4734       bool Baz;
4735       // Include if-then-else to test interaction of `BindingDecl` with join.
4736       if (B) {
4737         Baz = BoundFoo;
4738         (void)BoundBar;
4739         // [[p1]]
4740       } else {
4741         Baz = BoundFoo;
4742       }
4743       (void)0;
4744       // [[p2]]
4745     }
4746   )";
4747   runDataflow(
4748       Code,
4749       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4750          ASTContext &ASTCtx) {
4751         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
4752         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
4753 
4754         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
4755         ASSERT_THAT(BoundFooDecl, NotNull());
4756 
4757         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
4758         ASSERT_THAT(BoundBarDecl, NotNull());
4759 
4760         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4761         ASSERT_THAT(BazDecl, NotNull());
4762 
4763         const Value *BoundFooValue = Env1.getValue(*BoundFooDecl);
4764         ASSERT_THAT(BoundFooValue, NotNull());
4765         EXPECT_TRUE(isa<BoolValue>(BoundFooValue));
4766 
4767         const Value *BoundBarValue = Env1.getValue(*BoundBarDecl);
4768         ASSERT_THAT(BoundBarValue, NotNull());
4769         EXPECT_TRUE(isa<IntegerValue>(BoundBarValue));
4770 
4771         // Test that a `DeclRefExpr` to a `BindingDecl` (with reference type)
4772         // works as expected. We don't test aliasing properties of the
4773         // reference, because we don't model `std::get` and so have no way to
4774         // equate separate references into the tuple.
4775         EXPECT_EQ(Env1.getValue(*BazDecl), BoundFooValue);
4776 
4777         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
4778 
4779         // Test that `BoundFooDecl` retains the value we expect, after the join.
4780         BoundFooValue = Env2.getValue(*BoundFooDecl);
4781         EXPECT_EQ(Env2.getValue(*BazDecl), BoundFooValue);
4782       });
4783 }
4784 
4785 TEST(TransferTest, BinaryOperatorComma) {
4786   std::string Code = R"(
4787     void target(int Foo, int Bar) {
4788       int &Baz = (Foo, Bar);
4789       // [[p]]
4790     }
4791   )";
4792   runDataflow(
4793       Code,
4794       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4795          ASTContext &ASTCtx) {
4796         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4797         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4798 
4799         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4800         ASSERT_THAT(BarDecl, NotNull());
4801 
4802         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4803         ASSERT_THAT(BazDecl, NotNull());
4804 
4805         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
4806         ASSERT_THAT(BarLoc, NotNull());
4807 
4808         const StorageLocation *BazLoc = Env.getStorageLocation(*BazDecl);
4809         EXPECT_EQ(BazLoc, BarLoc);
4810       });
4811 }
4812 
4813 TEST(TransferTest, IfStmtBranchExtendsFlowCondition) {
4814   std::string Code = R"(
4815     void target(bool Foo) {
4816       if (Foo) {
4817         (void)0;
4818         // [[if_then]]
4819       } else {
4820         (void)0;
4821         // [[if_else]]
4822       }
4823     }
4824   )";
4825   runDataflow(
4826       Code,
4827       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4828          ASTContext &ASTCtx) {
4829         ASSERT_THAT(Results.keys(), UnorderedElementsAre("if_then", "if_else"));
4830         const Environment &ThenEnv =
4831             getEnvironmentAtAnnotation(Results, "if_then");
4832         const Environment &ElseEnv =
4833             getEnvironmentAtAnnotation(Results, "if_else");
4834 
4835         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4836         ASSERT_THAT(FooDecl, NotNull());
4837 
4838         auto &ThenFooVal= getFormula(*FooDecl, ThenEnv);
4839         EXPECT_TRUE(ThenEnv.proves(ThenFooVal));
4840 
4841         auto &ElseFooVal = getFormula(*FooDecl, ElseEnv);
4842         EXPECT_TRUE(ElseEnv.proves(ElseEnv.arena().makeNot(ElseFooVal)));
4843       });
4844 }
4845 
4846 TEST(TransferTest, WhileStmtBranchExtendsFlowCondition) {
4847   std::string Code = R"(
4848     void target(bool Foo) {
4849       while (Foo) {
4850         (void)0;
4851         // [[loop_body]]
4852       }
4853       (void)0;
4854       // [[after_loop]]
4855     }
4856   )";
4857   runDataflow(
4858       Code,
4859       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4860          ASTContext &ASTCtx) {
4861         ASSERT_THAT(Results.keys(),
4862                     UnorderedElementsAre("loop_body", "after_loop"));
4863         const Environment &LoopBodyEnv =
4864             getEnvironmentAtAnnotation(Results, "loop_body");
4865         const Environment &AfterLoopEnv =
4866             getEnvironmentAtAnnotation(Results, "after_loop");
4867 
4868         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4869         ASSERT_THAT(FooDecl, NotNull());
4870 
4871         auto &LoopBodyFooVal = getFormula(*FooDecl, LoopBodyEnv);
4872         EXPECT_TRUE(LoopBodyEnv.proves(LoopBodyFooVal));
4873 
4874         auto &AfterLoopFooVal = getFormula(*FooDecl, AfterLoopEnv);
4875         EXPECT_TRUE(
4876             AfterLoopEnv.proves(AfterLoopEnv.arena().makeNot(AfterLoopFooVal)));
4877       });
4878 }
4879 
4880 TEST(TransferTest, DoWhileStmtBranchExtendsFlowCondition) {
4881   std::string Code = R"(
4882     void target(bool Foo) {
4883       bool Bar = true;
4884       do {
4885         (void)0;
4886         // [[loop_body]]
4887         Bar = false;
4888       } while (Foo);
4889       (void)0;
4890       // [[after_loop]]
4891     }
4892   )";
4893   runDataflow(
4894       Code,
4895       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4896          ASTContext &ASTCtx) {
4897         ASSERT_THAT(Results.keys(),
4898                     UnorderedElementsAre("loop_body", "after_loop"));
4899         const Environment &LoopBodyEnv =
4900             getEnvironmentAtAnnotation(Results, "loop_body");
4901         const Environment &AfterLoopEnv =
4902             getEnvironmentAtAnnotation(Results, "after_loop");
4903         auto &A = AfterLoopEnv.arena();
4904 
4905         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4906         ASSERT_THAT(FooDecl, NotNull());
4907 
4908         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4909         ASSERT_THAT(BarDecl, NotNull());
4910 
4911         auto &LoopBodyFooVal= getFormula(*FooDecl, LoopBodyEnv);
4912         auto &LoopBodyBarVal = getFormula(*BarDecl, LoopBodyEnv);
4913         EXPECT_TRUE(
4914             LoopBodyEnv.proves(A.makeOr(LoopBodyBarVal, LoopBodyFooVal)));
4915 
4916         auto &AfterLoopFooVal = getFormula(*FooDecl, AfterLoopEnv);
4917         auto &AfterLoopBarVal = getFormula(*BarDecl, AfterLoopEnv);
4918         EXPECT_TRUE(AfterLoopEnv.proves(A.makeNot(AfterLoopFooVal)));
4919         EXPECT_TRUE(AfterLoopEnv.proves(A.makeNot(AfterLoopBarVal)));
4920       });
4921 }
4922 
4923 TEST(TransferTest, ForStmtBranchExtendsFlowCondition) {
4924   std::string Code = R"(
4925     void target(bool Foo) {
4926       for (; Foo;) {
4927         (void)0;
4928         // [[loop_body]]
4929       }
4930       (void)0;
4931       // [[after_loop]]
4932     }
4933   )";
4934   runDataflow(
4935       Code,
4936       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4937          ASTContext &ASTCtx) {
4938         ASSERT_THAT(Results.keys(),
4939                     UnorderedElementsAre("loop_body", "after_loop"));
4940         const Environment &LoopBodyEnv =
4941             getEnvironmentAtAnnotation(Results, "loop_body");
4942         const Environment &AfterLoopEnv =
4943             getEnvironmentAtAnnotation(Results, "after_loop");
4944 
4945         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4946         ASSERT_THAT(FooDecl, NotNull());
4947 
4948         auto &LoopBodyFooVal= getFormula(*FooDecl, LoopBodyEnv);
4949         EXPECT_TRUE(LoopBodyEnv.proves(LoopBodyFooVal));
4950 
4951         auto &AfterLoopFooVal = getFormula(*FooDecl, AfterLoopEnv);
4952         EXPECT_TRUE(
4953             AfterLoopEnv.proves(AfterLoopEnv.arena().makeNot(AfterLoopFooVal)));
4954       });
4955 }
4956 
4957 TEST(TransferTest, ForStmtBranchWithoutConditionDoesNotExtendFlowCondition) {
4958   std::string Code = R"(
4959     void target(bool Foo) {
4960       for (;;) {
4961         (void)0;
4962         // [[loop_body]]
4963       }
4964     }
4965   )";
4966   runDataflow(
4967       Code,
4968       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4969          ASTContext &ASTCtx) {
4970         ASSERT_THAT(Results.keys(), UnorderedElementsAre("loop_body"));
4971         const Environment &LoopBodyEnv =
4972             getEnvironmentAtAnnotation(Results, "loop_body");
4973 
4974         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4975         ASSERT_THAT(FooDecl, NotNull());
4976 
4977         auto &LoopBodyFooVal= getFormula(*FooDecl, LoopBodyEnv);
4978         EXPECT_FALSE(LoopBodyEnv.proves(LoopBodyFooVal));
4979       });
4980 }
4981 
4982 TEST(TransferTest, ContextSensitiveOptionDisabled) {
4983   std::string Code = R"(
4984     bool GiveBool();
4985     void SetBool(bool &Var) { Var = true; }
4986 
4987     void target() {
4988       bool Foo = GiveBool();
4989       SetBool(Foo);
4990       // [[p]]
4991     }
4992   )";
4993   runDataflow(
4994       Code,
4995       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4996          ASTContext &ASTCtx) {
4997         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4998         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4999 
5000         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5001         ASSERT_THAT(FooDecl, NotNull());
5002 
5003         auto &FooVal = getFormula(*FooDecl, Env);
5004         EXPECT_FALSE(Env.proves(FooVal));
5005         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
5006       },
5007       {BuiltinOptions{/*.ContextSensitiveOpts=*/std::nullopt}});
5008 }
5009 
5010 TEST(TransferTest, ContextSensitiveReturnReference) {
5011   std::string Code = R"(
5012     class S {};
5013     S& target(bool b, S &s) {
5014       return s;
5015       // [[p]]
5016     }
5017   )";
5018   runDataflow(
5019       Code,
5020       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5021          ASTContext &ASTCtx) {
5022         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5023 
5024         const ValueDecl *SDecl = findValueDecl(ASTCtx, "s");
5025         ASSERT_THAT(SDecl, NotNull());
5026 
5027         auto *SLoc = Env.getStorageLocation(*SDecl);
5028         ASSERT_THAT(SLoc, NotNull());
5029 
5030         ASSERT_THAT(Env.getReturnStorageLocation(), Eq(SLoc));
5031       },
5032       {BuiltinOptions{ContextSensitiveOptions{}}});
5033 }
5034 
5035 // This test is a regression test, based on a real crash.
5036 TEST(TransferTest, ContextSensitiveReturnReferenceWithConditionalOperator) {
5037   std::string Code = R"(
5038     class S {};
5039     S& target(bool b, S &s) {
5040       return b ? s : s;
5041       // [[p]]
5042     }
5043   )";
5044   runDataflow(
5045       Code,
5046       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5047          ASTContext &ASTCtx) {
5048         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5049         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5050 
5051         const ValueDecl *SDecl = findValueDecl(ASTCtx, "s");
5052         ASSERT_THAT(SDecl, NotNull());
5053 
5054         auto *SLoc = Env.getStorageLocation(*SDecl);
5055         ASSERT_THAT(SLoc, NotNull());
5056         EXPECT_THAT(Env.getValue(*SLoc), NotNull());
5057 
5058         auto *Loc = Env.getReturnStorageLocation();
5059         ASSERT_THAT(Loc, NotNull());
5060         EXPECT_THAT(Env.getValue(*Loc), NotNull());
5061 
5062         // TODO: We would really like to make this stronger assertion, but that
5063         // doesn't work because we don't propagate values correctly through
5064         // the conditional operator yet.
5065         // ASSERT_THAT(Loc, Eq(SLoc));
5066       },
5067       {BuiltinOptions{ContextSensitiveOptions{}}});
5068 }
5069 
5070 TEST(TransferTest, ContextSensitiveReturnOneOfTwoReferences) {
5071   std::string Code = R"(
5072     class S {};
5073     S &callee(bool b, S &s1_parm, S &s2_parm) {
5074       if (b)
5075         return s1_parm;
5076       else
5077         return s2_parm;
5078     }
5079     void target(bool b) {
5080       S s1;
5081       S s2;
5082       S &return_s1 = s1;
5083       S &return_s2 = s2;
5084       S &return_dont_know = callee(b, s1, s2);
5085       // [[p]]
5086     }
5087   )";
5088   runDataflow(
5089       Code,
5090       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5091          ASTContext &ASTCtx) {
5092         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5093 
5094         const ValueDecl *S1 = findValueDecl(ASTCtx, "s1");
5095         ASSERT_THAT(S1, NotNull());
5096         const ValueDecl *S2 = findValueDecl(ASTCtx, "s2");
5097         ASSERT_THAT(S2, NotNull());
5098         const ValueDecl *ReturnS1 = findValueDecl(ASTCtx, "return_s1");
5099         ASSERT_THAT(ReturnS1, NotNull());
5100         const ValueDecl *ReturnS2 = findValueDecl(ASTCtx, "return_s2");
5101         ASSERT_THAT(ReturnS2, NotNull());
5102         const ValueDecl *ReturnDontKnow =
5103             findValueDecl(ASTCtx, "return_dont_know");
5104         ASSERT_THAT(ReturnDontKnow, NotNull());
5105 
5106         StorageLocation *S1Loc = Env.getStorageLocation(*S1);
5107         StorageLocation *S2Loc = Env.getStorageLocation(*S2);
5108 
5109         EXPECT_THAT(Env.getStorageLocation(*ReturnS1), Eq(S1Loc));
5110         EXPECT_THAT(Env.getStorageLocation(*ReturnS2), Eq(S2Loc));
5111 
5112         // In the case where we don't have a consistent storage location for
5113         // the return value, the framework creates a new storage location, which
5114         // should be different from the storage locations of `s1` and `s2`.
5115         EXPECT_THAT(Env.getStorageLocation(*ReturnDontKnow), Ne(S1Loc));
5116         EXPECT_THAT(Env.getStorageLocation(*ReturnDontKnow), Ne(S2Loc));
5117       },
5118       {BuiltinOptions{ContextSensitiveOptions{}}});
5119 }
5120 
5121 TEST(TransferTest, ContextSensitiveDepthZero) {
5122   std::string Code = R"(
5123     bool GiveBool();
5124     void SetBool(bool &Var) { Var = true; }
5125 
5126     void target() {
5127       bool Foo = GiveBool();
5128       SetBool(Foo);
5129       // [[p]]
5130     }
5131   )";
5132   runDataflow(
5133       Code,
5134       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5135          ASTContext &ASTCtx) {
5136         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5137         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5138 
5139         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5140         ASSERT_THAT(FooDecl, NotNull());
5141 
5142         auto &FooVal = getFormula(*FooDecl, Env);
5143         EXPECT_FALSE(Env.proves(FooVal));
5144         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
5145       },
5146       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/0}}});
5147 }
5148 
5149 TEST(TransferTest, ContextSensitiveSetTrue) {
5150   std::string Code = R"(
5151     bool GiveBool();
5152     void SetBool(bool &Var) { Var = true; }
5153 
5154     void target() {
5155       bool Foo = GiveBool();
5156       SetBool(Foo);
5157       // [[p]]
5158     }
5159   )";
5160   runDataflow(
5161       Code,
5162       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5163          ASTContext &ASTCtx) {
5164         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5165         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5166 
5167         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5168         ASSERT_THAT(FooDecl, NotNull());
5169 
5170         auto &FooVal = getFormula(*FooDecl, Env);
5171         EXPECT_TRUE(Env.proves(FooVal));
5172       },
5173       {BuiltinOptions{ContextSensitiveOptions{}}});
5174 }
5175 
5176 TEST(TransferTest, ContextSensitiveSetFalse) {
5177   std::string Code = R"(
5178     bool GiveBool();
5179     void SetBool(bool &Var) { Var = false; }
5180 
5181     void target() {
5182       bool Foo = GiveBool();
5183       SetBool(Foo);
5184       // [[p]]
5185     }
5186   )";
5187   runDataflow(
5188       Code,
5189       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5190          ASTContext &ASTCtx) {
5191         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5192         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5193 
5194         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5195         ASSERT_THAT(FooDecl, NotNull());
5196 
5197         auto &FooVal = getFormula(*FooDecl, Env);
5198         EXPECT_TRUE(Env.proves(Env.arena().makeNot(FooVal)));
5199       },
5200       {BuiltinOptions{ContextSensitiveOptions{}}});
5201 }
5202 
5203 TEST(TransferTest, ContextSensitiveSetBothTrueAndFalse) {
5204   std::string Code = R"(
5205     bool GiveBool();
5206     void SetBool(bool &Var, bool Val) { Var = Val; }
5207 
5208     void target() {
5209       bool Foo = GiveBool();
5210       bool Bar = GiveBool();
5211       SetBool(Foo, true);
5212       SetBool(Bar, false);
5213       // [[p]]
5214     }
5215   )";
5216   runDataflow(
5217       Code,
5218       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5219          ASTContext &ASTCtx) {
5220         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5221         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5222         auto &A = Env.arena();
5223 
5224         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5225         ASSERT_THAT(FooDecl, NotNull());
5226 
5227         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
5228         ASSERT_THAT(BarDecl, NotNull());
5229 
5230         auto &FooVal = getFormula(*FooDecl, Env);
5231         EXPECT_TRUE(Env.proves(FooVal));
5232         EXPECT_FALSE(Env.proves(A.makeNot(FooVal)));
5233 
5234         auto &BarVal = getFormula(*BarDecl, Env);
5235         EXPECT_FALSE(Env.proves(BarVal));
5236         EXPECT_TRUE(Env.proves(A.makeNot(BarVal)));
5237       },
5238       {BuiltinOptions{ContextSensitiveOptions{}}});
5239 }
5240 
5241 TEST(TransferTest, ContextSensitiveSetTwoLayersDepthOne) {
5242   std::string Code = R"(
5243     bool GiveBool();
5244     void SetBool1(bool &Var) { Var = true; }
5245     void SetBool2(bool &Var) { SetBool1(Var); }
5246 
5247     void target() {
5248       bool Foo = GiveBool();
5249       SetBool2(Foo);
5250       // [[p]]
5251     }
5252   )";
5253   runDataflow(
5254       Code,
5255       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5256          ASTContext &ASTCtx) {
5257         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5258         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5259 
5260         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5261         ASSERT_THAT(FooDecl, NotNull());
5262 
5263         auto &FooVal = getFormula(*FooDecl, Env);
5264         EXPECT_FALSE(Env.proves(FooVal));
5265         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
5266       },
5267       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/1}}});
5268 }
5269 
5270 TEST(TransferTest, ContextSensitiveSetTwoLayersDepthTwo) {
5271   std::string Code = R"(
5272     bool GiveBool();
5273     void SetBool1(bool &Var) { Var = true; }
5274     void SetBool2(bool &Var) { SetBool1(Var); }
5275 
5276     void target() {
5277       bool Foo = GiveBool();
5278       SetBool2(Foo);
5279       // [[p]]
5280     }
5281   )";
5282   runDataflow(
5283       Code,
5284       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5285          ASTContext &ASTCtx) {
5286         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5287         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5288 
5289         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5290         ASSERT_THAT(FooDecl, NotNull());
5291 
5292         auto &FooVal = getFormula(*FooDecl, Env);
5293         EXPECT_TRUE(Env.proves(FooVal));
5294       },
5295       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/2}}});
5296 }
5297 
5298 TEST(TransferTest, ContextSensitiveSetThreeLayersDepthTwo) {
5299   std::string Code = R"(
5300     bool GiveBool();
5301     void SetBool1(bool &Var) { Var = true; }
5302     void SetBool2(bool &Var) { SetBool1(Var); }
5303     void SetBool3(bool &Var) { SetBool2(Var); }
5304 
5305     void target() {
5306       bool Foo = GiveBool();
5307       SetBool3(Foo);
5308       // [[p]]
5309     }
5310   )";
5311   runDataflow(
5312       Code,
5313       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5314          ASTContext &ASTCtx) {
5315         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5316         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5317 
5318         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5319         ASSERT_THAT(FooDecl, NotNull());
5320 
5321         auto &FooVal = getFormula(*FooDecl, Env);
5322         EXPECT_FALSE(Env.proves(FooVal));
5323         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
5324       },
5325       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/2}}});
5326 }
5327 
5328 TEST(TransferTest, ContextSensitiveSetThreeLayersDepthThree) {
5329   std::string Code = R"(
5330     bool GiveBool();
5331     void SetBool1(bool &Var) { Var = true; }
5332     void SetBool2(bool &Var) { SetBool1(Var); }
5333     void SetBool3(bool &Var) { SetBool2(Var); }
5334 
5335     void target() {
5336       bool Foo = GiveBool();
5337       SetBool3(Foo);
5338       // [[p]]
5339     }
5340   )";
5341   runDataflow(
5342       Code,
5343       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5344          ASTContext &ASTCtx) {
5345         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5346         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5347 
5348         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5349         ASSERT_THAT(FooDecl, NotNull());
5350 
5351         auto &FooVal = getFormula(*FooDecl, Env);
5352         EXPECT_TRUE(Env.proves(FooVal));
5353       },
5354       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/3}}});
5355 }
5356 
5357 TEST(TransferTest, ContextSensitiveMutualRecursion) {
5358   std::string Code = R"(
5359     bool Pong(bool X, bool Y);
5360 
5361     bool Ping(bool X, bool Y) {
5362       if (X) {
5363         return Y;
5364       } else {
5365         return Pong(!X, Y);
5366       }
5367     }
5368 
5369     bool Pong(bool X, bool Y) {
5370       if (Y) {
5371         return X;
5372       } else {
5373         return Ping(X, !Y);
5374       }
5375     }
5376 
5377     void target() {
5378       bool Foo = Ping(false, false);
5379       // [[p]]
5380     }
5381   )";
5382   runDataflow(
5383       Code,
5384       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5385          ASTContext &ASTCtx) {
5386         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5387         // The analysis doesn't crash...
5388         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5389 
5390         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5391         ASSERT_THAT(FooDecl, NotNull());
5392 
5393         auto &FooVal = getFormula(*FooDecl, Env);
5394         // ... but it also can't prove anything here.
5395         EXPECT_FALSE(Env.proves(FooVal));
5396         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
5397       },
5398       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/4}}});
5399 }
5400 
5401 TEST(TransferTest, ContextSensitiveSetMultipleLines) {
5402   std::string Code = R"(
5403     void SetBools(bool &Var1, bool &Var2) {
5404       Var1 = true;
5405       Var2 = false;
5406     }
5407 
5408     void target() {
5409       bool Foo = false;
5410       bool Bar = true;
5411       SetBools(Foo, Bar);
5412       // [[p]]
5413     }
5414   )";
5415   runDataflow(
5416       Code,
5417       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5418          ASTContext &ASTCtx) {
5419         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5420         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5421 
5422         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5423         ASSERT_THAT(FooDecl, NotNull());
5424 
5425         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
5426         ASSERT_THAT(BarDecl, NotNull());
5427 
5428         auto &FooVal = getFormula(*FooDecl, Env);
5429         EXPECT_TRUE(Env.proves(FooVal));
5430         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
5431 
5432         auto &BarVal = getFormula(*BarDecl, Env);
5433         EXPECT_FALSE(Env.proves(BarVal));
5434         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BarVal)));
5435       },
5436       {BuiltinOptions{ContextSensitiveOptions{}}});
5437 }
5438 
5439 TEST(TransferTest, ContextSensitiveSetMultipleBlocks) {
5440   std::string Code = R"(
5441     void IfCond(bool Cond, bool &Then, bool &Else) {
5442       if (Cond) {
5443         Then = true;
5444       } else {
5445         Else = true;
5446       }
5447     }
5448 
5449     void target() {
5450       bool Foo = false;
5451       bool Bar = false;
5452       bool Baz = false;
5453       IfCond(Foo, Bar, Baz);
5454       // [[p]]
5455     }
5456   )";
5457   runDataflow(
5458       Code,
5459       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5460          ASTContext &ASTCtx) {
5461         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5462         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5463 
5464         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
5465         ASSERT_THAT(BarDecl, NotNull());
5466 
5467         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
5468         ASSERT_THAT(BazDecl, NotNull());
5469 
5470         auto &BarVal = getFormula(*BarDecl, Env);
5471         EXPECT_FALSE(Env.proves(BarVal));
5472         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BarVal)));
5473 
5474         auto &BazVal = getFormula(*BazDecl, Env);
5475         EXPECT_TRUE(Env.proves(BazVal));
5476         EXPECT_FALSE(Env.proves(Env.arena().makeNot(BazVal)));
5477       },
5478       {BuiltinOptions{ContextSensitiveOptions{}}});
5479 }
5480 
5481 TEST(TransferTest, ContextSensitiveReturnVoid) {
5482   std::string Code = R"(
5483     void Noop() { return; }
5484 
5485     void target() {
5486       Noop();
5487       // [[p]]
5488     }
5489   )";
5490   runDataflow(
5491       Code,
5492       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5493          ASTContext &ASTCtx) {
5494         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5495         // This just tests that the analysis doesn't crash.
5496       },
5497       {BuiltinOptions{ContextSensitiveOptions{}}});
5498 }
5499 
5500 TEST(TransferTest, ContextSensitiveReturnTrue) {
5501   std::string Code = R"(
5502     bool GiveBool() { return true; }
5503 
5504     void target() {
5505       bool Foo = GiveBool();
5506       // [[p]]
5507     }
5508   )";
5509   runDataflow(
5510       Code,
5511       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5512          ASTContext &ASTCtx) {
5513         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5514         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5515 
5516         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5517         ASSERT_THAT(FooDecl, NotNull());
5518 
5519         auto &FooVal = getFormula(*FooDecl, Env);
5520         EXPECT_TRUE(Env.proves(FooVal));
5521       },
5522       {BuiltinOptions{ContextSensitiveOptions{}}});
5523 }
5524 
5525 TEST(TransferTest, ContextSensitiveReturnFalse) {
5526   std::string Code = R"(
5527     bool GiveBool() { return false; }
5528 
5529     void target() {
5530       bool Foo = GiveBool();
5531       // [[p]]
5532     }
5533   )";
5534   runDataflow(
5535       Code,
5536       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5537          ASTContext &ASTCtx) {
5538         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5539         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5540 
5541         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5542         ASSERT_THAT(FooDecl, NotNull());
5543 
5544         auto &FooVal = getFormula(*FooDecl, Env);
5545         EXPECT_TRUE(Env.proves(Env.arena().makeNot(FooVal)));
5546       },
5547       {BuiltinOptions{ContextSensitiveOptions{}}});
5548 }
5549 
5550 TEST(TransferTest, ContextSensitiveReturnArg) {
5551   std::string Code = R"(
5552     bool GiveBool();
5553     bool GiveBack(bool Arg) { return Arg; }
5554 
5555     void target() {
5556       bool Foo = GiveBool();
5557       bool Bar = GiveBack(Foo);
5558       bool Baz = Foo == Bar;
5559       // [[p]]
5560     }
5561   )";
5562   runDataflow(
5563       Code,
5564       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5565          ASTContext &ASTCtx) {
5566         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5567         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5568 
5569         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
5570         ASSERT_THAT(BazDecl, NotNull());
5571 
5572         auto &BazVal = getFormula(*BazDecl, Env);
5573         EXPECT_TRUE(Env.proves(BazVal));
5574       },
5575       {BuiltinOptions{ContextSensitiveOptions{}}});
5576 }
5577 
5578 TEST(TransferTest, ContextSensitiveReturnInt) {
5579   std::string Code = R"(
5580     int identity(int x) { return x; }
5581 
5582     void target() {
5583       int y = identity(42);
5584       // [[p]]
5585     }
5586   )";
5587   runDataflow(
5588       Code,
5589       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5590          ASTContext &ASTCtx) {
5591         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5592         // This just tests that the analysis doesn't crash.
5593       },
5594       {BuiltinOptions{ContextSensitiveOptions{}}});
5595 }
5596 
5597 TEST(TransferTest, ContextSensitiveMethodLiteral) {
5598   std::string Code = R"(
5599     class MyClass {
5600     public:
5601       bool giveBool() { return true; }
5602     };
5603 
5604     void target() {
5605       MyClass MyObj;
5606       bool Foo = MyObj.giveBool();
5607       // [[p]]
5608     }
5609   )";
5610   runDataflow(
5611       Code,
5612       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5613          ASTContext &ASTCtx) {
5614         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5615         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5616 
5617         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5618         ASSERT_THAT(FooDecl, NotNull());
5619 
5620         auto &FooVal = getFormula(*FooDecl, Env);
5621         EXPECT_TRUE(Env.proves(FooVal));
5622       },
5623       {BuiltinOptions{ContextSensitiveOptions{}}});
5624 }
5625 
5626 TEST(TransferTest, ContextSensitiveMethodGetter) {
5627   std::string Code = R"(
5628     class MyClass {
5629     public:
5630       bool getField() { return Field; }
5631 
5632       bool Field;
5633     };
5634 
5635     void target() {
5636       MyClass MyObj;
5637       MyObj.Field = true;
5638       bool Foo = MyObj.getField();
5639       // [[p]]
5640     }
5641   )";
5642   runDataflow(
5643       Code,
5644       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5645          ASTContext &ASTCtx) {
5646         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5647         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5648 
5649         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5650         ASSERT_THAT(FooDecl, NotNull());
5651 
5652         auto &FooVal = getFormula(*FooDecl, Env);
5653         EXPECT_TRUE(Env.proves(FooVal));
5654       },
5655       {BuiltinOptions{ContextSensitiveOptions{}}});
5656 }
5657 
5658 TEST(TransferTest, ContextSensitiveMethodSetter) {
5659   std::string Code = R"(
5660     class MyClass {
5661     public:
5662       void setField(bool Val) { Field = Val; }
5663 
5664       bool Field;
5665     };
5666 
5667     void target() {
5668       MyClass MyObj;
5669       MyObj.setField(true);
5670       bool Foo = MyObj.Field;
5671       // [[p]]
5672     }
5673   )";
5674   runDataflow(
5675       Code,
5676       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5677          ASTContext &ASTCtx) {
5678         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5679         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5680 
5681         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5682         ASSERT_THAT(FooDecl, NotNull());
5683 
5684         auto &FooVal = getFormula(*FooDecl, Env);
5685         EXPECT_TRUE(Env.proves(FooVal));
5686       },
5687       {BuiltinOptions{ContextSensitiveOptions{}}});
5688 }
5689 
5690 TEST(TransferTest, ContextSensitiveMethodGetterAndSetter) {
5691   std::string Code = R"(
5692     class MyClass {
5693     public:
5694       bool getField() { return Field; }
5695       void setField(bool Val) { Field = Val; }
5696 
5697     private:
5698       bool Field;
5699     };
5700 
5701     void target() {
5702       MyClass MyObj;
5703       MyObj.setField(true);
5704       bool Foo = MyObj.getField();
5705       // [[p]]
5706     }
5707   )";
5708   runDataflow(
5709       Code,
5710       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5711          ASTContext &ASTCtx) {
5712         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5713         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5714 
5715         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5716         ASSERT_THAT(FooDecl, NotNull());
5717 
5718         auto &FooVal = getFormula(*FooDecl, Env);
5719         EXPECT_TRUE(Env.proves(FooVal));
5720       },
5721       {BuiltinOptions{ContextSensitiveOptions{}}});
5722 }
5723 
5724 
5725 TEST(TransferTest, ContextSensitiveMethodTwoLayersVoid) {
5726   std::string Code = R"(
5727     class MyClass {
5728     public:
5729       void Inner() { MyField = true; }
5730       void Outer() { Inner(); }
5731 
5732       bool MyField;
5733     };
5734 
5735     void target() {
5736       MyClass MyObj;
5737       MyObj.Outer();
5738       bool Foo = MyObj.MyField;
5739       // [[p]]
5740     }
5741   )";
5742   runDataflow(
5743       Code,
5744       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5745          ASTContext &ASTCtx) {
5746         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5747         ;
5748         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5749 
5750         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5751         ASSERT_THAT(FooDecl, NotNull());
5752 
5753         auto &FooVal = getFormula(*FooDecl, Env);
5754         EXPECT_TRUE(Env.proves(FooVal));
5755       },
5756       {BuiltinOptions{ContextSensitiveOptions{}}});
5757 }
5758 
5759 TEST(TransferTest, ContextSensitiveMethodTwoLayersReturn) {
5760   std::string Code = R"(
5761     class MyClass {
5762     public:
5763       bool Inner() { return MyField; }
5764       bool Outer() { return Inner(); }
5765 
5766       bool MyField;
5767     };
5768 
5769     void target() {
5770       MyClass MyObj;
5771       MyObj.MyField = true;
5772       bool Foo = MyObj.Outer();
5773       // [[p]]
5774     }
5775   )";
5776   runDataflow(
5777       Code,
5778       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5779          ASTContext &ASTCtx) {
5780         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5781         ;
5782         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5783 
5784         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5785         ASSERT_THAT(FooDecl, NotNull());
5786 
5787         auto &FooVal = getFormula(*FooDecl, Env);
5788         EXPECT_TRUE(Env.proves(FooVal));
5789       },
5790       {BuiltinOptions{ContextSensitiveOptions{}}});
5791 }
5792 
5793 TEST(TransferTest, ContextSensitiveConstructorBody) {
5794   std::string Code = R"(
5795     class MyClass {
5796     public:
5797       MyClass() { MyField = true; }
5798 
5799       bool MyField;
5800     };
5801 
5802     void target() {
5803       MyClass MyObj;
5804       bool Foo = MyObj.MyField;
5805       // [[p]]
5806     }
5807   )";
5808   runDataflow(
5809       Code,
5810       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5811          ASTContext &ASTCtx) {
5812         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5813         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5814 
5815         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5816         ASSERT_THAT(FooDecl, NotNull());
5817 
5818         auto &FooVal = getFormula(*FooDecl, Env);
5819         EXPECT_TRUE(Env.proves(FooVal));
5820       },
5821       {BuiltinOptions{ContextSensitiveOptions{}}});
5822 }
5823 
5824 TEST(TransferTest, ContextSensitiveConstructorInitializer) {
5825   std::string Code = R"(
5826     class MyClass {
5827     public:
5828       MyClass() : MyField(true) {}
5829 
5830       bool MyField;
5831     };
5832 
5833     void target() {
5834       MyClass MyObj;
5835       bool Foo = MyObj.MyField;
5836       // [[p]]
5837     }
5838   )";
5839   runDataflow(
5840       Code,
5841       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5842          ASTContext &ASTCtx) {
5843         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5844         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5845 
5846         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5847         ASSERT_THAT(FooDecl, NotNull());
5848 
5849         auto &FooVal = getFormula(*FooDecl, Env);
5850         EXPECT_TRUE(Env.proves(FooVal));
5851       },
5852       {BuiltinOptions{ContextSensitiveOptions{}}});
5853 }
5854 
5855 TEST(TransferTest, ContextSensitiveConstructorDefault) {
5856   std::string Code = R"(
5857     class MyClass {
5858     public:
5859       MyClass() = default;
5860 
5861       bool MyField = true;
5862     };
5863 
5864     void target() {
5865       MyClass MyObj;
5866       bool Foo = MyObj.MyField;
5867       // [[p]]
5868     }
5869   )";
5870   runDataflow(
5871       Code,
5872       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5873          ASTContext &ASTCtx) {
5874         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5875         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5876 
5877         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5878         ASSERT_THAT(FooDecl, NotNull());
5879 
5880         auto &FooVal = getFormula(*FooDecl, Env);
5881         EXPECT_TRUE(Env.proves(FooVal));
5882       },
5883       {BuiltinOptions{ContextSensitiveOptions{}}});
5884 }
5885 
5886 TEST(TransferTest, ContextSensitiveSelfReferentialClass) {
5887   // Test that the `this` pointer seen in the constructor has the same value
5888   // as the address of the variable the object is constructed into.
5889   std::string Code = R"(
5890     class MyClass {
5891     public:
5892       MyClass() : Self(this) {}
5893       MyClass *Self;
5894     };
5895 
5896     void target() {
5897       MyClass MyObj;
5898       MyClass *SelfPtr = MyObj.Self;
5899       // [[p]]
5900     }
5901   )";
5902   runDataflow(
5903       Code,
5904       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5905          ASTContext &ASTCtx) {
5906         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5907 
5908         const ValueDecl *MyObjDecl = findValueDecl(ASTCtx, "MyObj");
5909         ASSERT_THAT(MyObjDecl, NotNull());
5910 
5911         const ValueDecl *SelfDecl = findValueDecl(ASTCtx, "SelfPtr");
5912         ASSERT_THAT(SelfDecl, NotNull());
5913 
5914         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5915         auto &SelfVal = *cast<PointerValue>(Env.getValue(*SelfDecl));
5916         EXPECT_EQ(Env.getStorageLocation(*MyObjDecl), &SelfVal.getPointeeLoc());
5917       },
5918       {BuiltinOptions{ContextSensitiveOptions{}}});
5919 }
5920 
5921 TEST(TransferTest, UnnamedBitfieldInitializer) {
5922   std::string Code = R"(
5923     struct B {};
5924     struct A {
5925       unsigned a;
5926       unsigned : 4;
5927       unsigned c;
5928       B b;
5929     };
5930     void target() {
5931       A a = {};
5932       A test = a;
5933       (void)test.c;
5934     }
5935   )";
5936   runDataflow(
5937       Code,
5938       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5939          ASTContext &ASTCtx) {
5940         // This doesn't need a body because this test was crashing the framework
5941         // before handling correctly Unnamed bitfields in `InitListExpr`.
5942       });
5943 }
5944 
5945 // Repro for a crash that used to occur with chained short-circuiting logical
5946 // operators.
5947 TEST(TransferTest, ChainedLogicalOps) {
5948   std::string Code = R"(
5949     bool target() {
5950       bool b = true || false || false || false;
5951       // [[p]]
5952       return b;
5953     }
5954   )";
5955   runDataflow(
5956       Code,
5957       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5958          ASTContext &ASTCtx) {
5959         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5960         auto &B = getValueForDecl<BoolValue>(ASTCtx, Env, "b").formula();
5961         EXPECT_TRUE(Env.proves(B));
5962       });
5963 }
5964 
5965 // Repro for a crash that used to occur when we call a `noreturn` function
5966 // within one of the operands of a `&&` or `||` operator.
5967 TEST(TransferTest, NoReturnFunctionInsideShortCircuitedBooleanOp) {
5968   std::string Code = R"(
5969     __attribute__((noreturn)) int doesnt_return();
5970     bool some_condition();
5971     void target(bool b1, bool b2) {
5972       // Neither of these should crash. In addition, if we don't terminate the
5973       // program, we know that the operators need to trigger the short-circuit
5974       // logic, so `NoreturnOnRhsOfAnd` will be false and `NoreturnOnRhsOfOr`
5975       // will be true.
5976       bool NoreturnOnRhsOfAnd = b1 && doesnt_return() > 0;
5977       bool NoreturnOnRhsOfOr = b2 || doesnt_return() > 0;
5978 
5979       // Calling a `noreturn` function on the LHS of an `&&` or `||` makes the
5980       // entire expression unreachable. So we know that in both of the following
5981       // cases, if `target()` terminates, the `else` branch was taken.
5982       bool NoreturnOnLhsMakesAndUnreachable = false;
5983       if (some_condition())
5984          doesnt_return() > 0 && some_condition();
5985       else
5986          NoreturnOnLhsMakesAndUnreachable = true;
5987 
5988       bool NoreturnOnLhsMakesOrUnreachable = false;
5989       if (some_condition())
5990          doesnt_return() > 0 || some_condition();
5991       else
5992          NoreturnOnLhsMakesOrUnreachable = true;
5993 
5994       // [[p]]
5995     }
5996   )";
5997   runDataflow(
5998       Code,
5999       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6000          ASTContext &ASTCtx) {
6001         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6002         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6003         auto &A = Env.arena();
6004 
6005         // Check that [[p]] is reachable with a non-false flow condition.
6006         EXPECT_FALSE(Env.proves(A.makeLiteral(false)));
6007 
6008         auto &B1 = getValueForDecl<BoolValue>(ASTCtx, Env, "b1").formula();
6009         EXPECT_TRUE(Env.proves(A.makeNot(B1)));
6010 
6011         auto &NoreturnOnRhsOfAnd =
6012             getValueForDecl<BoolValue>(ASTCtx, Env, "NoreturnOnRhsOfAnd").formula();
6013         EXPECT_TRUE(Env.proves(A.makeNot(NoreturnOnRhsOfAnd)));
6014 
6015         auto &B2 = getValueForDecl<BoolValue>(ASTCtx, Env, "b2").formula();
6016         EXPECT_TRUE(Env.proves(B2));
6017 
6018         auto &NoreturnOnRhsOfOr =
6019             getValueForDecl<BoolValue>(ASTCtx, Env, "NoreturnOnRhsOfOr")
6020                 .formula();
6021         EXPECT_TRUE(Env.proves(NoreturnOnRhsOfOr));
6022 
6023         auto &NoreturnOnLhsMakesAndUnreachable = getValueForDecl<BoolValue>(
6024             ASTCtx, Env, "NoreturnOnLhsMakesAndUnreachable").formula();
6025         EXPECT_TRUE(Env.proves(NoreturnOnLhsMakesAndUnreachable));
6026 
6027         auto &NoreturnOnLhsMakesOrUnreachable = getValueForDecl<BoolValue>(
6028             ASTCtx, Env, "NoreturnOnLhsMakesOrUnreachable").formula();
6029         EXPECT_TRUE(Env.proves(NoreturnOnLhsMakesOrUnreachable));
6030       });
6031 }
6032 
6033 TEST(TransferTest, NewExpressions) {
6034   std::string Code = R"(
6035     void target() {
6036       int *p = new int(42);
6037       // [[after_new]]
6038     }
6039   )";
6040   runDataflow(
6041       Code,
6042       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6043          ASTContext &ASTCtx) {
6044         const Environment &Env =
6045             getEnvironmentAtAnnotation(Results, "after_new");
6046 
6047         auto &P = getValueForDecl<PointerValue>(ASTCtx, Env, "p");
6048 
6049         EXPECT_THAT(Env.getValue(P.getPointeeLoc()), NotNull());
6050       });
6051 }
6052 
6053 TEST(TransferTest, NewExpressions_Structs) {
6054   std::string Code = R"(
6055     struct Inner {
6056       int InnerField;
6057     };
6058 
6059     struct Outer {
6060       Inner OuterField;
6061     };
6062 
6063     void target() {
6064       Outer *p = new Outer;
6065       // Access the fields to make sure the analysis actually generates children
6066       // for them in the `RecordStorageLocation` and `RecordValue`.
6067       p->OuterField.InnerField;
6068       // [[after_new]]
6069     }
6070   )";
6071   runDataflow(
6072       Code,
6073       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6074          ASTContext &ASTCtx) {
6075         const Environment &Env =
6076             getEnvironmentAtAnnotation(Results, "after_new");
6077 
6078         const ValueDecl *OuterField = findValueDecl(ASTCtx, "OuterField");
6079         const ValueDecl *InnerField = findValueDecl(ASTCtx, "InnerField");
6080 
6081         auto &P = getValueForDecl<PointerValue>(ASTCtx, Env, "p");
6082 
6083         auto &OuterLoc = cast<RecordStorageLocation>(P.getPointeeLoc());
6084         auto &OuterFieldLoc =
6085             *cast<RecordStorageLocation>(OuterLoc.getChild(*OuterField));
6086         auto &InnerFieldLoc = *OuterFieldLoc.getChild(*InnerField);
6087 
6088         // Values for the struct and all fields exist after the new.
6089         EXPECT_THAT(Env.getValue(OuterLoc), NotNull());
6090         EXPECT_THAT(Env.getValue(OuterFieldLoc), NotNull());
6091         EXPECT_THAT(Env.getValue(InnerFieldLoc), NotNull());
6092       });
6093 }
6094 
6095 TEST(TransferTest, FunctionToPointerDecayHasValue) {
6096   std::string Code = R"(
6097     struct A { static void static_member_func(); };
6098     void target() {
6099       // To check that we're treating function-to-pointer decay correctly,
6100       // create two pointers, then verify they refer to the same storage
6101       // location.
6102       // We need to do the test this way because even if an initializer (in this
6103       // case, the function-to-pointer decay) does not create a value, we still
6104       // create a value for the variable.
6105       void (*non_member_p1)() = target;
6106       void (*non_member_p2)() = target;
6107 
6108       // Do the same thing but for a static member function.
6109       void (*member_p1)() = A::static_member_func;
6110       void (*member_p2)() = A::static_member_func;
6111       // [[p]]
6112     }
6113   )";
6114   runDataflow(
6115       Code,
6116       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6117          ASTContext &ASTCtx) {
6118         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6119 
6120         auto &NonMemberP1 =
6121             getValueForDecl<PointerValue>(ASTCtx, Env, "non_member_p1");
6122         auto &NonMemberP2 =
6123             getValueForDecl<PointerValue>(ASTCtx, Env, "non_member_p2");
6124         EXPECT_EQ(&NonMemberP1.getPointeeLoc(), &NonMemberP2.getPointeeLoc());
6125 
6126         auto &MemberP1 =
6127             getValueForDecl<PointerValue>(ASTCtx, Env, "member_p1");
6128         auto &MemberP2 =
6129             getValueForDecl<PointerValue>(ASTCtx, Env, "member_p2");
6130         EXPECT_EQ(&MemberP1.getPointeeLoc(), &MemberP2.getPointeeLoc());
6131       });
6132 }
6133 
6134 // Check that a builtin function is not associated with a value. (It's only
6135 // possible to call builtin functions directly, not take their address.)
6136 TEST(TransferTest, BuiltinFunctionModeled) {
6137   std::string Code = R"(
6138     void target() {
6139       __builtin_expect(0, 0);
6140       // [[p]]
6141     }
6142   )";
6143   runDataflow(
6144       Code,
6145       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6146          ASTContext &ASTCtx) {
6147         using ast_matchers::selectFirst;
6148         using ast_matchers::match;
6149         using ast_matchers::traverse;
6150         using ast_matchers::implicitCastExpr;
6151         using ast_matchers::hasCastKind;
6152 
6153         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6154 
6155         auto *ImplicitCast = selectFirst<ImplicitCastExpr>(
6156             "implicit_cast",
6157             match(traverse(TK_AsIs,
6158                            implicitCastExpr(hasCastKind(CK_BuiltinFnToFnPtr))
6159                                .bind("implicit_cast")),
6160                   ASTCtx));
6161 
6162         ASSERT_THAT(ImplicitCast, NotNull());
6163         EXPECT_THAT(Env.getValue(*ImplicitCast), IsNull());
6164       });
6165 }
6166 
6167 // Check that a callee of a member operator call is modeled as a `PointerValue`.
6168 // Member operator calls are unusual in that their callee is a pointer that
6169 // stems from a `FunctionToPointerDecay`. In calls to non-operator non-static
6170 // member functions, the callee is a `MemberExpr` (which does not have pointer
6171 // type).
6172 // We want to make sure that we produce a pointer value for the callee in this
6173 // specific scenario and that its storage location is durable (for convergence).
6174 TEST(TransferTest, MemberOperatorCallModelsPointerForCallee) {
6175   std::string Code = R"(
6176     struct S {
6177       bool operator!=(S s);
6178     };
6179     void target() {
6180       S s;
6181       (void)(s != s);
6182       (void)(s != s);
6183       // [[p]]
6184     }
6185   )";
6186   runDataflow(
6187       Code,
6188       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6189          ASTContext &ASTCtx) {
6190         using ast_matchers::selectFirst;
6191         using ast_matchers::match;
6192         using ast_matchers::traverse;
6193         using ast_matchers::cxxOperatorCallExpr;
6194 
6195         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6196 
6197         auto Matches = match(
6198             traverse(TK_AsIs, cxxOperatorCallExpr().bind("call")), ASTCtx);
6199 
6200         ASSERT_EQ(Matches.size(), 2UL);
6201 
6202         auto *Call1 = Matches[0].getNodeAs<CXXOperatorCallExpr>("call");
6203         auto *Call2 = Matches[1].getNodeAs<CXXOperatorCallExpr>("call");
6204 
6205         ASSERT_THAT(Call1, NotNull());
6206         ASSERT_THAT(Call2, NotNull());
6207 
6208         EXPECT_EQ(cast<ImplicitCastExpr>(Call1->getCallee())->getCastKind(),
6209                   CK_FunctionToPointerDecay);
6210         EXPECT_EQ(cast<ImplicitCastExpr>(Call2->getCallee())->getCastKind(),
6211                   CK_FunctionToPointerDecay);
6212 
6213         auto *Ptr1 = cast<PointerValue>(Env.getValue(*Call1->getCallee()));
6214         auto *Ptr2 = cast<PointerValue>(Env.getValue(*Call2->getCallee()));
6215 
6216         ASSERT_EQ(&Ptr1->getPointeeLoc(), &Ptr2->getPointeeLoc());
6217       });
6218 }
6219 
6220 // Check that fields of anonymous records are modeled.
6221 TEST(TransferTest, AnonymousStruct) {
6222   std::string Code = R"(
6223     struct S {
6224       struct {
6225         bool b;
6226       };
6227     };
6228     void target() {
6229       S s;
6230       s.b = true;
6231       // [[p]]
6232     }
6233   )";
6234   runDataflow(
6235       Code,
6236       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6237          ASTContext &ASTCtx) {
6238         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6239         const ValueDecl *SDecl = findValueDecl(ASTCtx, "s");
6240         const ValueDecl *BDecl = findValueDecl(ASTCtx, "b");
6241         const IndirectFieldDecl *IndirectField =
6242             findIndirectFieldDecl(ASTCtx, "b");
6243 
6244         auto *S = cast<RecordStorageLocation>(Env.getStorageLocation(*SDecl));
6245         auto &AnonStruct = *cast<RecordStorageLocation>(
6246             S->getChild(*cast<ValueDecl>(IndirectField->chain().front())));
6247 
6248         auto *B = cast<BoolValue>(getFieldValue(&AnonStruct, *BDecl, Env));
6249         ASSERT_TRUE(Env.proves(B->formula()));
6250       });
6251 }
6252 
6253 TEST(TransferTest, AnonymousStructWithInitializer) {
6254   std::string Code = R"(
6255     struct target {
6256       target() {
6257         (void)0;
6258         // [[p]]
6259       }
6260       struct {
6261         bool b = true;
6262       };
6263     };
6264   )";
6265   runDataflow(
6266       Code,
6267       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6268          ASTContext &ASTCtx) {
6269         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6270         const ValueDecl *BDecl = findValueDecl(ASTCtx, "b");
6271         const IndirectFieldDecl *IndirectField =
6272             findIndirectFieldDecl(ASTCtx, "b");
6273 
6274         auto *ThisLoc =
6275             cast<RecordStorageLocation>(Env.getThisPointeeStorageLocation());
6276         auto &AnonStruct = *cast<RecordStorageLocation>(ThisLoc->getChild(
6277             *cast<ValueDecl>(IndirectField->chain().front())));
6278 
6279         auto *B = cast<BoolValue>(getFieldValue(&AnonStruct, *BDecl, Env));
6280         ASSERT_TRUE(Env.proves(B->formula()));
6281       });
6282 }
6283 
6284 TEST(TransferTest, AnonymousStructWithReferenceField) {
6285   std::string Code = R"(
6286     int global_i = 0;
6287     struct target {
6288       target() {
6289         (void)0;
6290         // [[p]]
6291       }
6292       struct {
6293         int &i = global_i;
6294       };
6295     };
6296   )";
6297   runDataflow(
6298       Code,
6299       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6300          ASTContext &ASTCtx) {
6301         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6302         const ValueDecl *GlobalIDecl = findValueDecl(ASTCtx, "global_i");
6303         const ValueDecl *IDecl = findValueDecl(ASTCtx, "i");
6304         const IndirectFieldDecl *IndirectField =
6305             findIndirectFieldDecl(ASTCtx, "i");
6306 
6307         auto *ThisLoc =
6308             cast<RecordStorageLocation>(Env.getThisPointeeStorageLocation());
6309         auto &AnonStruct = *cast<RecordStorageLocation>(ThisLoc->getChild(
6310             *cast<ValueDecl>(IndirectField->chain().front())));
6311 
6312         ASSERT_EQ(AnonStruct.getChild(*IDecl),
6313                   Env.getStorageLocation(*GlobalIDecl));
6314       });
6315 }
6316 
6317 TEST(TransferTest, EvaluateBlockWithUnreachablePreds) {
6318   // This is a crash repro.
6319   // `false` block may not have been processed when we try to evaluate the `||`
6320   // after visiting `true`, because it is not necessary (and therefore the edge
6321   // is marked unreachable). Trying to get the analysis state via
6322   // `getEnvironment` for the subexpression still should not crash.
6323   std::string Code = R"(
6324     int target(int i) {
6325       if ((i < 0 && true) || false) {
6326         return 0;
6327       }
6328       return 0;
6329     }
6330   )";
6331   runDataflow(
6332       Code,
6333       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6334          ASTContext &ASTCtx) {});
6335 }
6336 
6337 TEST(TransferTest, LambdaCaptureByCopy) {
6338   std::string Code = R"(
6339     void target(int Foo, int Bar) {
6340       [Foo]() {
6341         (void)0;
6342         // [[p]]
6343       }();
6344     }
6345   )";
6346   runDataflowOnLambda(
6347       Code,
6348       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6349          ASTContext &ASTCtx) {
6350         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6351         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6352 
6353         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6354         ASSERT_THAT(FooDecl, NotNull());
6355 
6356         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
6357         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
6358 
6359         const Value *FooVal = Env.getValue(*FooLoc);
6360         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
6361 
6362         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
6363         ASSERT_THAT(BarDecl, NotNull());
6364 
6365         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
6366         EXPECT_THAT(BarLoc, IsNull());
6367       });
6368 }
6369 
6370 TEST(TransferTest, LambdaCaptureByReference) {
6371   std::string Code = R"(
6372     void target(int Foo, int Bar) {
6373       [&Foo]() {
6374         (void)0;
6375         // [[p]]
6376       }();
6377     }
6378   )";
6379   runDataflowOnLambda(
6380       Code,
6381       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6382          ASTContext &ASTCtx) {
6383         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6384         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6385 
6386         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6387         ASSERT_THAT(FooDecl, NotNull());
6388 
6389         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
6390         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
6391 
6392         const Value *FooVal = Env.getValue(*FooLoc);
6393         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
6394 
6395         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
6396         ASSERT_THAT(BarDecl, NotNull());
6397 
6398         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
6399         EXPECT_THAT(BarLoc, IsNull());
6400       });
6401 }
6402 
6403 TEST(TransferTest, LambdaCaptureWithInitializer) {
6404   std::string Code = R"(
6405     void target(int Bar) {
6406       [Foo=Bar]() {
6407         (void)0;
6408         // [[p]]
6409       }();
6410     }
6411   )";
6412   runDataflowOnLambda(
6413       Code,
6414       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6415          ASTContext &ASTCtx) {
6416         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6417         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6418 
6419         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6420         ASSERT_THAT(FooDecl, NotNull());
6421 
6422         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
6423         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
6424 
6425         const Value *FooVal = Env.getValue(*FooLoc);
6426         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
6427 
6428         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
6429         ASSERT_THAT(BarDecl, NotNull());
6430 
6431         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
6432         EXPECT_THAT(BarLoc, IsNull());
6433       });
6434 }
6435 
6436 TEST(TransferTest, LambdaCaptureByCopyImplicit) {
6437   std::string Code = R"(
6438     void target(int Foo, int Bar) {
6439       [=]() {
6440         Foo;
6441         // [[p]]
6442       }();
6443     }
6444   )";
6445   runDataflowOnLambda(
6446       Code,
6447       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6448          ASTContext &ASTCtx) {
6449         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6450         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6451 
6452         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6453         ASSERT_THAT(FooDecl, NotNull());
6454 
6455         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
6456         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
6457 
6458         const Value *FooVal = Env.getValue(*FooLoc);
6459         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
6460 
6461         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
6462         ASSERT_THAT(BarDecl, NotNull());
6463 
6464         // There is no storage location for `Bar` because it isn't used in the
6465         // body of the lambda.
6466         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
6467         EXPECT_THAT(BarLoc, IsNull());
6468       });
6469 }
6470 
6471 TEST(TransferTest, LambdaCaptureByReferenceImplicit) {
6472   std::string Code = R"(
6473     void target(int Foo, int Bar) {
6474       [&]() {
6475         Foo;
6476         // [[p]]
6477       }();
6478     }
6479   )";
6480   runDataflowOnLambda(
6481       Code,
6482       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6483          ASTContext &ASTCtx) {
6484         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6485         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6486 
6487         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6488         ASSERT_THAT(FooDecl, NotNull());
6489 
6490         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
6491         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
6492 
6493         const Value *FooVal = Env.getValue(*FooLoc);
6494         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
6495 
6496         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
6497         ASSERT_THAT(BarDecl, NotNull());
6498 
6499         // There is no storage location for `Bar` because it isn't used in the
6500         // body of the lambda.
6501         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
6502         EXPECT_THAT(BarLoc, IsNull());
6503       });
6504 }
6505 
6506 TEST(TransferTest, LambdaCaptureThis) {
6507   std::string Code = R"(
6508     struct Bar {
6509       int Foo;
6510 
6511       void target() {
6512         [this]() {
6513           Foo;
6514           // [[p]]
6515         }();
6516       }
6517     };
6518   )";
6519   runDataflowOnLambda(
6520       Code,
6521       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6522          ASTContext &ASTCtx) {
6523         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6524         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6525 
6526         const RecordStorageLocation *ThisPointeeLoc =
6527             Env.getThisPointeeStorageLocation();
6528         ASSERT_THAT(ThisPointeeLoc, NotNull());
6529 
6530         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6531         ASSERT_THAT(FooDecl, NotNull());
6532 
6533         const StorageLocation *FooLoc = ThisPointeeLoc->getChild(*FooDecl);
6534         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
6535 
6536         const Value *FooVal = Env.getValue(*FooLoc);
6537         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
6538       });
6539 }
6540 
6541 TEST(TransferTest, DifferentReferenceLocInJoin) {
6542   // This test triggers a case where the storage location for a reference-type
6543   // variable is different for two states being joined. We used to believe this
6544   // could not happen and therefore had an assertion disallowing this; this test
6545   // exists to demonstrate that we can handle this condition without a failing
6546   // assertion. See also the discussion here:
6547   // https://discourse.llvm.org/t/70086/6
6548   std::string Code = R"(
6549     namespace std {
6550       template <class T> struct initializer_list {
6551         const T* begin();
6552         const T* end();
6553       };
6554     }
6555 
6556     void target(char* p, char* end) {
6557       while (p != end) {
6558         if (*p == ' ') {
6559           p++;
6560           continue;
6561         }
6562 
6563         auto && range = {1, 2};
6564         for (auto b = range.begin(), e = range.end(); b != e; ++b) {
6565         }
6566         (void)0;
6567         // [[p]]
6568       }
6569     }
6570   )";
6571   runDataflow(
6572       Code,
6573       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6574          ASTContext &ASTCtx) {
6575         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6576 
6577         // Joining environments with different storage locations for the same
6578         // declaration results in the declaration being removed from the joined
6579         // environment.
6580         const ValueDecl *VD = findValueDecl(ASTCtx, "range");
6581         ASSERT_EQ(Env.getStorageLocation(*VD), nullptr);
6582       });
6583 }
6584 
6585 // This test verifies correct modeling of a relational dependency that goes
6586 // through unmodeled functions (the simple `cond()` in this case).
6587 TEST(TransferTest, ConditionalRelation) {
6588   std::string Code = R"(
6589     bool cond();
6590     void target() {
6591        bool a = true;
6592        bool b = true;
6593        if (cond()) {
6594          a = false;
6595          if (cond()) {
6596            b = false;
6597          }
6598        }
6599        (void)0;
6600        // [[p]]
6601     }
6602  )";
6603   runDataflow(
6604       Code,
6605       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6606          ASTContext &ASTCtx) {
6607         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6608         auto &A = Env.arena();
6609         auto &VarA = getValueForDecl<BoolValue>(ASTCtx, Env, "a").formula();
6610         auto &VarB = getValueForDecl<BoolValue>(ASTCtx, Env, "b").formula();
6611 
6612         EXPECT_FALSE(Env.allows(A.makeAnd(VarA, A.makeNot(VarB))));
6613       });
6614 }
6615 
6616 } // namespace
6617