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