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