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