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