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