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