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