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