xref: /llvm-project/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp (revision 834cb919b3107f9db3efe80483908d31cb84ee7a)
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         ASSERT_THAT(EnvAfterLoop.getValue(*BarDecl), IsNull());
2961       });
2962 }
2963 
2964 TEST(TransferTest, UnreachableAfterWhileTrue) {
2965   std::string Code = R"(
2966     void target() {
2967       while (true) {}
2968       (void)0;
2969       /*[[p]]*/
2970     }
2971   )";
2972   runDataflow(
2973       Code,
2974       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2975          ASTContext &ASTCtx) {
2976         // The node after the while-true is pruned because it is trivially
2977         // known to be unreachable.
2978         ASSERT_TRUE(Results.empty());
2979       });
2980 }
2981 
2982 TEST(TransferTest, AggregateInitialization) {
2983   std::string BracesCode = R"(
2984     struct A {
2985       int Foo;
2986     };
2987 
2988     struct B {
2989       int Bar;
2990       A Baz;
2991       int Qux;
2992     };
2993 
2994     void target(int BarArg, int FooArg, int QuxArg) {
2995       B Quux{BarArg, {FooArg}, QuxArg};
2996       B OtherB;
2997       /*[[p]]*/
2998     }
2999   )";
3000   std::string BraceElisionCode = R"(
3001     struct A {
3002       int Foo;
3003     };
3004 
3005     struct B {
3006       int Bar;
3007       A Baz;
3008       int Qux;
3009     };
3010 
3011     void target(int BarArg, int FooArg, int QuxArg) {
3012       B Quux = {BarArg, FooArg, QuxArg};
3013       B OtherB;
3014       /*[[p]]*/
3015     }
3016   )";
3017   for (const std::string &Code : {BracesCode, BraceElisionCode}) {
3018     runDataflow(
3019         Code,
3020         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3021            ASTContext &ASTCtx) {
3022           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3023           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3024 
3025           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3026           ASSERT_THAT(FooDecl, NotNull());
3027 
3028           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3029           ASSERT_THAT(BarDecl, NotNull());
3030 
3031           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3032           ASSERT_THAT(BazDecl, NotNull());
3033 
3034           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
3035           ASSERT_THAT(QuxDecl, NotNull());
3036 
3037           const ValueDecl *FooArgDecl = findValueDecl(ASTCtx, "FooArg");
3038           ASSERT_THAT(FooArgDecl, NotNull());
3039 
3040           const ValueDecl *BarArgDecl = findValueDecl(ASTCtx, "BarArg");
3041           ASSERT_THAT(BarArgDecl, NotNull());
3042 
3043           const ValueDecl *QuxArgDecl = findValueDecl(ASTCtx, "QuxArg");
3044           ASSERT_THAT(QuxArgDecl, NotNull());
3045 
3046           const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux");
3047           ASSERT_THAT(QuuxDecl, NotNull());
3048 
3049           const auto *FooArgVal = cast<IntegerValue>(Env.getValue(*FooArgDecl));
3050           const auto *BarArgVal = cast<IntegerValue>(Env.getValue(*BarArgDecl));
3051           const auto *QuxArgVal = cast<IntegerValue>(Env.getValue(*QuxArgDecl));
3052 
3053           const auto &QuuxLoc =
3054               *cast<RecordStorageLocation>(Env.getStorageLocation(*QuuxDecl));
3055           const auto &BazLoc =
3056               *cast<RecordStorageLocation>(QuuxLoc.getChild(*BazDecl));
3057 
3058           EXPECT_EQ(getFieldValue(&QuuxLoc, *BarDecl, Env), BarArgVal);
3059           EXPECT_EQ(getFieldValue(&BazLoc, *FooDecl, Env), FooArgVal);
3060           EXPECT_EQ(getFieldValue(&QuuxLoc, *QuxDecl, Env), QuxArgVal);
3061 
3062           // Check that fields initialized in an initializer list are always
3063           // modeled in other instances of the same type.
3064           const auto &OtherBLoc =
3065               getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "OtherB");
3066           EXPECT_THAT(OtherBLoc.getChild(*BarDecl), NotNull());
3067           EXPECT_THAT(OtherBLoc.getChild(*BazDecl), NotNull());
3068           EXPECT_THAT(OtherBLoc.getChild(*QuxDecl), NotNull());
3069         });
3070   }
3071 }
3072 
3073 TEST(TransferTest, AggregateInitializationReferenceField) {
3074   std::string Code = R"(
3075     struct S {
3076       int &RefField;
3077     };
3078 
3079     void target(int i) {
3080       S s = { i };
3081       /*[[p]]*/
3082     }
3083   )";
3084   runDataflow(
3085       Code,
3086       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3087          ASTContext &ASTCtx) {
3088         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3089 
3090         const ValueDecl *RefFieldDecl = findValueDecl(ASTCtx, "RefField");
3091 
3092         auto &ILoc = getLocForDecl<StorageLocation>(ASTCtx, Env, "i");
3093         auto &SLoc = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "s");
3094 
3095         EXPECT_EQ(SLoc.getChild(*RefFieldDecl), &ILoc);
3096       });
3097 }
3098 
3099 TEST(TransferTest, AggregateInitialization_NotExplicitlyInitializedField) {
3100   std::string Code = R"(
3101     struct S {
3102       int i1;
3103       int i2;
3104     };
3105 
3106     void target(int i) {
3107       S s = { i };
3108       /*[[p]]*/
3109     }
3110   )";
3111   runDataflow(
3112       Code,
3113       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3114          ASTContext &ASTCtx) {
3115         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3116 
3117         const ValueDecl *I1FieldDecl = findValueDecl(ASTCtx, "i1");
3118         const ValueDecl *I2FieldDecl = findValueDecl(ASTCtx, "i2");
3119 
3120         auto &SLoc = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "s");
3121 
3122         auto &IValue = getValueForDecl<IntegerValue>(ASTCtx, Env, "i");
3123         auto &I1Value =
3124             *cast<IntegerValue>(getFieldValue(&SLoc, *I1FieldDecl, Env));
3125         EXPECT_EQ(&I1Value, &IValue);
3126         auto &I2Value =
3127             *cast<IntegerValue>(getFieldValue(&SLoc, *I2FieldDecl, Env));
3128         EXPECT_NE(&I2Value, &IValue);
3129       });
3130 }
3131 
3132 TEST(TransferTest, AssignToUnionMember) {
3133   std::string Code = R"(
3134     union A {
3135       int Foo;
3136     };
3137 
3138     void target(int Bar) {
3139       A Baz;
3140       Baz.Foo = Bar;
3141       // [[p]]
3142     }
3143   )";
3144   runDataflow(
3145       Code,
3146       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3147          ASTContext &ASTCtx) {
3148         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3149         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3150 
3151         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3152         ASSERT_THAT(BazDecl, NotNull());
3153         ASSERT_TRUE(BazDecl->getType()->isUnionType());
3154 
3155         auto BazFields = BazDecl->getType()->getAsRecordDecl()->fields();
3156         FieldDecl *FooDecl = nullptr;
3157         for (FieldDecl *Field : BazFields) {
3158           if (Field->getNameAsString() == "Foo") {
3159             FooDecl = Field;
3160           } else {
3161             FAIL() << "Unexpected field: " << Field->getNameAsString();
3162           }
3163         }
3164         ASSERT_THAT(FooDecl, NotNull());
3165 
3166         const auto *BazLoc = dyn_cast_or_null<RecordStorageLocation>(
3167             Env.getStorageLocation(*BazDecl));
3168         ASSERT_THAT(BazLoc, NotNull());
3169         ASSERT_THAT(Env.getValue(*BazLoc), NotNull());
3170 
3171         const auto *FooVal =
3172             cast<IntegerValue>(getFieldValue(BazLoc, *FooDecl, Env));
3173 
3174         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3175         ASSERT_THAT(BarDecl, NotNull());
3176         const auto *BarLoc = Env.getStorageLocation(*BarDecl);
3177         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
3178 
3179         EXPECT_EQ(Env.getValue(*BarLoc), FooVal);
3180       });
3181 }
3182 
3183 TEST(TransferTest, AssignFromBoolLiteral) {
3184   std::string Code = R"(
3185     void target() {
3186       bool Foo = true;
3187       bool Bar = false;
3188       // [[p]]
3189     }
3190   )";
3191   runDataflow(
3192       Code,
3193       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3194          ASTContext &ASTCtx) {
3195         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3196         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3197 
3198         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3199         ASSERT_THAT(FooDecl, NotNull());
3200 
3201         const auto *FooVal =
3202             dyn_cast_or_null<AtomicBoolValue>(Env.getValue(*FooDecl));
3203         ASSERT_THAT(FooVal, NotNull());
3204 
3205         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3206         ASSERT_THAT(BarDecl, NotNull());
3207 
3208         const auto *BarVal =
3209             dyn_cast_or_null<AtomicBoolValue>(Env.getValue(*BarDecl));
3210         ASSERT_THAT(BarVal, NotNull());
3211 
3212         EXPECT_EQ(FooVal, &Env.getBoolLiteralValue(true));
3213         EXPECT_EQ(BarVal, &Env.getBoolLiteralValue(false));
3214       });
3215 }
3216 
3217 TEST(TransferTest, AssignFromCompositeBoolExpression) {
3218   {
3219     std::string Code = R"(
3220     void target(bool Foo, bool Bar, bool Qux) {
3221       bool Baz = (Foo) && (Bar || Qux);
3222       // [[p]]
3223     }
3224   )";
3225     runDataflow(
3226         Code,
3227         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3228            ASTContext &ASTCtx) {
3229           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3230           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3231 
3232           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3233           ASSERT_THAT(FooDecl, NotNull());
3234 
3235           const auto *FooVal =
3236               dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
3237           ASSERT_THAT(FooVal, NotNull());
3238 
3239           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3240           ASSERT_THAT(BarDecl, NotNull());
3241 
3242           const auto *BarVal =
3243               dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
3244           ASSERT_THAT(BarVal, NotNull());
3245 
3246           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
3247           ASSERT_THAT(QuxDecl, NotNull());
3248 
3249           const auto *QuxVal =
3250               dyn_cast_or_null<BoolValue>(Env.getValue(*QuxDecl));
3251           ASSERT_THAT(QuxVal, NotNull());
3252 
3253           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3254           ASSERT_THAT(BazDecl, NotNull());
3255 
3256           const auto *BazVal =
3257               dyn_cast_or_null<BoolValue>(Env.getValue(*BazDecl));
3258           ASSERT_THAT(BazVal, NotNull());
3259           auto &A = Env.arena();
3260           EXPECT_EQ(&BazVal->formula(),
3261                     &A.makeAnd(FooVal->formula(),
3262                                A.makeOr(BarVal->formula(), QuxVal->formula())));
3263         });
3264   }
3265 
3266   {
3267     std::string Code = R"(
3268     void target(bool Foo, bool Bar, bool Qux) {
3269       bool Baz = (Foo && Qux) || (Bar);
3270       // [[p]]
3271     }
3272   )";
3273     runDataflow(
3274         Code,
3275         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3276            ASTContext &ASTCtx) {
3277           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3278           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3279 
3280           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3281           ASSERT_THAT(FooDecl, NotNull());
3282 
3283           const auto *FooVal =
3284               dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
3285           ASSERT_THAT(FooVal, NotNull());
3286 
3287           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3288           ASSERT_THAT(BarDecl, NotNull());
3289 
3290           const auto *BarVal =
3291               dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
3292           ASSERT_THAT(BarVal, NotNull());
3293 
3294           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
3295           ASSERT_THAT(QuxDecl, NotNull());
3296 
3297           const auto *QuxVal =
3298               dyn_cast_or_null<BoolValue>(Env.getValue(*QuxDecl));
3299           ASSERT_THAT(QuxVal, NotNull());
3300 
3301           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3302           ASSERT_THAT(BazDecl, NotNull());
3303 
3304           const auto *BazVal =
3305               dyn_cast_or_null<BoolValue>(Env.getValue(*BazDecl));
3306           ASSERT_THAT(BazVal, NotNull());
3307           auto &A = Env.arena();
3308           EXPECT_EQ(&BazVal->formula(),
3309                     &A.makeOr(A.makeAnd(FooVal->formula(), QuxVal->formula()),
3310                               BarVal->formula()));
3311         });
3312   }
3313 
3314   {
3315     std::string Code = R"(
3316       void target(bool A, bool B, bool C, bool D) {
3317         bool Foo = ((A && B) && C) && D;
3318         // [[p]]
3319       }
3320     )";
3321     runDataflow(
3322         Code,
3323         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3324            ASTContext &ASTCtx) {
3325           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3326           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3327 
3328           const ValueDecl *ADecl = findValueDecl(ASTCtx, "A");
3329           ASSERT_THAT(ADecl, NotNull());
3330 
3331           const auto *AVal = dyn_cast_or_null<BoolValue>(Env.getValue(*ADecl));
3332           ASSERT_THAT(AVal, NotNull());
3333 
3334           const ValueDecl *BDecl = findValueDecl(ASTCtx, "B");
3335           ASSERT_THAT(BDecl, NotNull());
3336 
3337           const auto *BVal = dyn_cast_or_null<BoolValue>(Env.getValue(*BDecl));
3338           ASSERT_THAT(BVal, NotNull());
3339 
3340           const ValueDecl *CDecl = findValueDecl(ASTCtx, "C");
3341           ASSERT_THAT(CDecl, NotNull());
3342 
3343           const auto *CVal = dyn_cast_or_null<BoolValue>(Env.getValue(*CDecl));
3344           ASSERT_THAT(CVal, NotNull());
3345 
3346           const ValueDecl *DDecl = findValueDecl(ASTCtx, "D");
3347           ASSERT_THAT(DDecl, NotNull());
3348 
3349           const auto *DVal = dyn_cast_or_null<BoolValue>(Env.getValue(*DDecl));
3350           ASSERT_THAT(DVal, NotNull());
3351 
3352           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3353           ASSERT_THAT(FooDecl, NotNull());
3354 
3355           const auto *FooVal =
3356               dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
3357           ASSERT_THAT(FooVal, NotNull());
3358           auto &A = Env.arena();
3359           EXPECT_EQ(
3360               &FooVal->formula(),
3361               &A.makeAnd(A.makeAnd(A.makeAnd(AVal->formula(), BVal->formula()),
3362                                    CVal->formula()),
3363                          DVal->formula()));
3364         });
3365   }
3366 }
3367 
3368 TEST(TransferTest, AssignFromBoolNegation) {
3369   std::string Code = R"(
3370     void target() {
3371       bool Foo = true;
3372       bool Bar = !(Foo);
3373       // [[p]]
3374     }
3375   )";
3376   runDataflow(
3377       Code,
3378       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3379          ASTContext &ASTCtx) {
3380         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3381         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3382 
3383         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3384         ASSERT_THAT(FooDecl, NotNull());
3385 
3386         const auto *FooVal =
3387             dyn_cast_or_null<AtomicBoolValue>(Env.getValue(*FooDecl));
3388         ASSERT_THAT(FooVal, NotNull());
3389 
3390         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3391         ASSERT_THAT(BarDecl, NotNull());
3392 
3393         const auto *BarVal =
3394             dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
3395         ASSERT_THAT(BarVal, NotNull());
3396         auto &A = Env.arena();
3397         EXPECT_EQ(&BarVal->formula(), &A.makeNot(FooVal->formula()));
3398       });
3399 }
3400 
3401 TEST(TransferTest, BuiltinExpect) {
3402   std::string Code = R"(
3403     void target(long Foo) {
3404       long Bar = __builtin_expect(Foo, true);
3405       /*[[p]]*/
3406     }
3407   )";
3408   runDataflow(
3409       Code,
3410       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3411          ASTContext &ASTCtx) {
3412         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3413         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3414 
3415         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3416         ASSERT_THAT(FooDecl, NotNull());
3417 
3418         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3419         ASSERT_THAT(BarDecl, NotNull());
3420 
3421         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
3422       });
3423 }
3424 
3425 // `__builtin_expect` takes and returns a `long` argument, so other types
3426 // involve casts. This verifies that we identify the input and output in that
3427 // case.
3428 TEST(TransferTest, BuiltinExpectBoolArg) {
3429   std::string Code = R"(
3430     void target(bool Foo) {
3431       bool Bar = __builtin_expect(Foo, true);
3432       /*[[p]]*/
3433     }
3434   )";
3435   runDataflow(
3436       Code,
3437       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3438          ASTContext &ASTCtx) {
3439         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3440         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3441 
3442         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3443         ASSERT_THAT(FooDecl, NotNull());
3444 
3445         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3446         ASSERT_THAT(BarDecl, NotNull());
3447 
3448         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
3449       });
3450 }
3451 
3452 TEST(TransferTest, BuiltinUnreachable) {
3453   std::string Code = R"(
3454     void target(bool Foo) {
3455       bool Bar = false;
3456       if (Foo)
3457         Bar = Foo;
3458       else
3459         __builtin_unreachable();
3460       (void)0;
3461       /*[[p]]*/
3462     }
3463   )";
3464   runDataflow(
3465       Code,
3466       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3467          ASTContext &ASTCtx) {
3468         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3469         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3470 
3471         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3472         ASSERT_THAT(FooDecl, NotNull());
3473 
3474         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3475         ASSERT_THAT(BarDecl, NotNull());
3476 
3477         // `__builtin_unreachable` promises that the code is
3478         // unreachable, so the compiler treats the "then" branch as the
3479         // only possible predecessor of this statement.
3480         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
3481       });
3482 }
3483 
3484 TEST(TransferTest, BuiltinTrap) {
3485   std::string Code = R"(
3486     void target(bool Foo) {
3487       bool Bar = false;
3488       if (Foo)
3489         Bar = Foo;
3490       else
3491         __builtin_trap();
3492       (void)0;
3493       /*[[p]]*/
3494     }
3495   )";
3496   runDataflow(
3497       Code,
3498       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3499          ASTContext &ASTCtx) {
3500         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3501         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3502 
3503         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3504         ASSERT_THAT(FooDecl, NotNull());
3505 
3506         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3507         ASSERT_THAT(BarDecl, NotNull());
3508 
3509         // `__builtin_trap` ensures program termination, so only the
3510         // "then" branch is a predecessor of this statement.
3511         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
3512       });
3513 }
3514 
3515 TEST(TransferTest, BuiltinDebugTrap) {
3516   std::string Code = R"(
3517     void target(bool Foo) {
3518       bool Bar = false;
3519       if (Foo)
3520         Bar = Foo;
3521       else
3522         __builtin_debugtrap();
3523       (void)0;
3524       /*[[p]]*/
3525     }
3526   )";
3527   runDataflow(
3528       Code,
3529       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3530          ASTContext &ASTCtx) {
3531         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3532         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3533 
3534         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3535         ASSERT_THAT(FooDecl, NotNull());
3536 
3537         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3538         ASSERT_THAT(BarDecl, NotNull());
3539 
3540         // `__builtin_debugtrap` doesn't ensure program termination.
3541         EXPECT_NE(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
3542       });
3543 }
3544 
3545 TEST(TransferTest, StaticIntSingleVarDecl) {
3546   std::string Code = R"(
3547     void target() {
3548       static int Foo;
3549       // [[p]]
3550     }
3551   )";
3552   runDataflow(
3553       Code,
3554       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3555          ASTContext &ASTCtx) {
3556         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3557         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3558 
3559         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3560         ASSERT_THAT(FooDecl, NotNull());
3561 
3562         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
3563         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
3564 
3565         const Value *FooVal = Env.getValue(*FooLoc);
3566         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
3567       });
3568 }
3569 
3570 TEST(TransferTest, StaticIntGroupVarDecl) {
3571   std::string Code = R"(
3572     void target() {
3573       static int Foo, Bar;
3574       (void)0;
3575       // [[p]]
3576     }
3577   )";
3578   runDataflow(
3579       Code,
3580       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3581          ASTContext &ASTCtx) {
3582         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3583         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3584 
3585         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3586         ASSERT_THAT(FooDecl, NotNull());
3587 
3588         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3589         ASSERT_THAT(BarDecl, NotNull());
3590 
3591         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
3592         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
3593 
3594         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
3595         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
3596 
3597         const Value *FooVal = Env.getValue(*FooLoc);
3598         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
3599 
3600         const Value *BarVal = Env.getValue(*BarLoc);
3601         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
3602 
3603         EXPECT_NE(FooVal, BarVal);
3604       });
3605 }
3606 
3607 TEST(TransferTest, GlobalIntVarDecl) {
3608   std::string Code = R"(
3609     static int Foo;
3610 
3611     void target() {
3612       int Bar = Foo;
3613       int Baz = Foo;
3614       // [[p]]
3615     }
3616   )";
3617   runDataflow(
3618       Code,
3619       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3620          ASTContext &ASTCtx) {
3621         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3622         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3623 
3624         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3625         ASSERT_THAT(BarDecl, NotNull());
3626 
3627         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3628         ASSERT_THAT(BazDecl, NotNull());
3629 
3630         const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
3631         const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl));
3632         EXPECT_EQ(BarVal, BazVal);
3633       });
3634 }
3635 
3636 TEST(TransferTest, StaticMemberIntVarDecl) {
3637   std::string Code = R"(
3638     struct A {
3639       static int Foo;
3640     };
3641 
3642     void target(A a) {
3643       int Bar = a.Foo;
3644       int Baz = a.Foo;
3645       // [[p]]
3646     }
3647   )";
3648   runDataflow(
3649       Code,
3650       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3651          ASTContext &ASTCtx) {
3652         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3653         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3654 
3655         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3656         ASSERT_THAT(BarDecl, NotNull());
3657 
3658         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3659         ASSERT_THAT(BazDecl, NotNull());
3660 
3661         const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
3662         const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl));
3663         EXPECT_EQ(BarVal, BazVal);
3664       });
3665 }
3666 
3667 TEST(TransferTest, StaticMemberRefVarDecl) {
3668   std::string Code = R"(
3669     struct A {
3670       static int &Foo;
3671     };
3672 
3673     void target(A a) {
3674       int Bar = a.Foo;
3675       int Baz = a.Foo;
3676       // [[p]]
3677     }
3678   )";
3679   runDataflow(
3680       Code,
3681       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3682          ASTContext &ASTCtx) {
3683         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3684         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3685 
3686         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3687         ASSERT_THAT(BarDecl, NotNull());
3688 
3689         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3690         ASSERT_THAT(BazDecl, NotNull());
3691 
3692         const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
3693         const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl));
3694         EXPECT_EQ(BarVal, BazVal);
3695       });
3696 }
3697 
3698 TEST(TransferTest, AssignMemberBeforeCopy) {
3699   std::string Code = R"(
3700     struct A {
3701       int Foo;
3702     };
3703 
3704     void target() {
3705       A A1;
3706       A A2;
3707       int Bar;
3708       A1.Foo = Bar;
3709       A2 = A1;
3710       // [[p]]
3711     }
3712   )";
3713   runDataflow(
3714       Code,
3715       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3716          ASTContext &ASTCtx) {
3717         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3718         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3719 
3720         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3721         ASSERT_THAT(FooDecl, NotNull());
3722 
3723         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3724         ASSERT_THAT(BarDecl, NotNull());
3725 
3726         const ValueDecl *A1Decl = findValueDecl(ASTCtx, "A1");
3727         ASSERT_THAT(A1Decl, NotNull());
3728 
3729         const ValueDecl *A2Decl = findValueDecl(ASTCtx, "A2");
3730         ASSERT_THAT(A2Decl, NotNull());
3731 
3732         const auto *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
3733 
3734         const auto &A2Loc =
3735             *cast<RecordStorageLocation>(Env.getStorageLocation(*A2Decl));
3736         EXPECT_EQ(getFieldValue(&A2Loc, *FooDecl, Env), BarVal);
3737       });
3738 }
3739 
3740 TEST(TransferTest, BooleanEquality) {
3741   std::string Code = R"(
3742     void target(bool Bar) {
3743       bool Foo = true;
3744       if (Bar == Foo) {
3745         (void)0;
3746         /*[[p-then]]*/
3747       } else {
3748         (void)0;
3749         /*[[p-else]]*/
3750       }
3751     }
3752   )";
3753   runDataflow(
3754       Code,
3755       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3756          ASTContext &ASTCtx) {
3757         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-then", "p-else"));
3758         const Environment &EnvThen =
3759             getEnvironmentAtAnnotation(Results, "p-then");
3760         const Environment &EnvElse =
3761             getEnvironmentAtAnnotation(Results, "p-else");
3762 
3763         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3764         ASSERT_THAT(BarDecl, NotNull());
3765 
3766         auto &BarValThen = getFormula(*BarDecl, EnvThen);
3767         EXPECT_TRUE(EnvThen.flowConditionImplies(BarValThen));
3768 
3769         auto &BarValElse = getFormula(*BarDecl, EnvElse);
3770         EXPECT_TRUE(
3771             EnvElse.flowConditionImplies(EnvElse.arena().makeNot(BarValElse)));
3772       });
3773 }
3774 
3775 TEST(TransferTest, BooleanInequality) {
3776   std::string Code = R"(
3777     void target(bool Bar) {
3778       bool Foo = true;
3779       if (Bar != Foo) {
3780         (void)0;
3781         /*[[p-then]]*/
3782       } else {
3783         (void)0;
3784         /*[[p-else]]*/
3785       }
3786     }
3787   )";
3788   runDataflow(
3789       Code,
3790       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3791          ASTContext &ASTCtx) {
3792         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-then", "p-else"));
3793         const Environment &EnvThen =
3794             getEnvironmentAtAnnotation(Results, "p-then");
3795         const Environment &EnvElse =
3796             getEnvironmentAtAnnotation(Results, "p-else");
3797 
3798         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3799         ASSERT_THAT(BarDecl, NotNull());
3800 
3801         auto &BarValThen = getFormula(*BarDecl, EnvThen);
3802         EXPECT_TRUE(
3803             EnvThen.flowConditionImplies(EnvThen.arena().makeNot(BarValThen)));
3804 
3805         auto &BarValElse = getFormula(*BarDecl, EnvElse);
3806         EXPECT_TRUE(EnvElse.flowConditionImplies(BarValElse));
3807       });
3808 }
3809 
3810 TEST(TransferTest, IntegerLiteralEquality) {
3811   std::string Code = R"(
3812     void target() {
3813       bool equal = (42 == 42);
3814       // [[p]]
3815     }
3816   )";
3817   runDataflow(
3818       Code,
3819       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3820          ASTContext &ASTCtx) {
3821         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3822 
3823         auto &Equal =
3824             getValueForDecl<BoolValue>(ASTCtx, Env, "equal").formula();
3825         EXPECT_TRUE(Env.flowConditionImplies(Equal));
3826       });
3827 }
3828 
3829 TEST(TransferTest, CorrelatedBranches) {
3830   std::string Code = R"(
3831     void target(bool B, bool C) {
3832       if (B) {
3833         return;
3834       }
3835       (void)0;
3836       /*[[p0]]*/
3837       if (C) {
3838         B = true;
3839         /*[[p1]]*/
3840       }
3841       if (B) {
3842         (void)0;
3843         /*[[p2]]*/
3844       }
3845     }
3846   )";
3847   runDataflow(
3848       Code,
3849       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3850          ASTContext &ASTCtx) {
3851         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p0", "p1", "p2"));
3852 
3853         const ValueDecl *CDecl = findValueDecl(ASTCtx, "C");
3854         ASSERT_THAT(CDecl, NotNull());
3855 
3856         {
3857           const Environment &Env = getEnvironmentAtAnnotation(Results, "p0");
3858           const ValueDecl *BDecl = findValueDecl(ASTCtx, "B");
3859           ASSERT_THAT(BDecl, NotNull());
3860           auto &BVal = getFormula(*BDecl, Env);
3861 
3862           EXPECT_TRUE(Env.flowConditionImplies(Env.arena().makeNot(BVal)));
3863         }
3864 
3865         {
3866           const Environment &Env = getEnvironmentAtAnnotation(Results, "p1");
3867           auto &CVal = getFormula(*CDecl, Env);
3868           EXPECT_TRUE(Env.flowConditionImplies(CVal));
3869         }
3870 
3871         {
3872           const Environment &Env = getEnvironmentAtAnnotation(Results, "p2");
3873           auto &CVal = getFormula(*CDecl, Env);
3874           EXPECT_TRUE(Env.flowConditionImplies(CVal));
3875         }
3876       });
3877 }
3878 
3879 TEST(TransferTest, LoopWithAssignmentConverges) {
3880   std::string Code = R"(
3881     bool foo();
3882 
3883     void target() {
3884        do {
3885         bool Bar = foo();
3886         if (Bar) break;
3887         (void)Bar;
3888         /*[[p]]*/
3889       } while (true);
3890     }
3891   )";
3892   // The key property that we are verifying is implicit in `runDataflow` --
3893   // namely, that the analysis succeeds, rather than hitting the maximum number
3894   // of iterations.
3895   runDataflow(
3896       Code,
3897       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3898          ASTContext &ASTCtx) {
3899         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3900         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3901 
3902         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3903         ASSERT_THAT(BarDecl, NotNull());
3904 
3905         auto &BarVal = getFormula(*BarDecl, Env);
3906         EXPECT_TRUE(Env.flowConditionImplies(Env.arena().makeNot(BarVal)));
3907       });
3908 }
3909 
3910 TEST(TransferTest, LoopWithStagedAssignments) {
3911   std::string Code = R"(
3912     bool foo();
3913 
3914     void target() {
3915       bool Bar = false;
3916       bool Err = false;
3917       while (foo()) {
3918         if (Bar)
3919           Err = true;
3920         Bar = true;
3921         /*[[p]]*/
3922       }
3923     }
3924   )";
3925   runDataflow(
3926       Code,
3927       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3928          ASTContext &ASTCtx) {
3929         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3930         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3931 
3932         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3933         ASSERT_THAT(BarDecl, NotNull());
3934         const ValueDecl *ErrDecl = findValueDecl(ASTCtx, "Err");
3935         ASSERT_THAT(ErrDecl, NotNull());
3936 
3937         auto &BarVal = getFormula(*BarDecl, Env);
3938         auto &ErrVal = getFormula(*ErrDecl, Env);
3939         EXPECT_TRUE(Env.flowConditionImplies(BarVal));
3940         // An unsound analysis, for example only evaluating the loop once, can
3941         // conclude that `Err` is false. So, we test that this conclusion is not
3942         // reached.
3943         EXPECT_FALSE(
3944             Env.flowConditionImplies(Env.arena().makeNot(ErrVal)));
3945       });
3946 }
3947 
3948 TEST(TransferTest, LoopWithReferenceAssignmentConverges) {
3949   std::string Code = R"(
3950     bool &foo();
3951 
3952     void target() {
3953        do {
3954         bool& Bar = foo();
3955         if (Bar) break;
3956         (void)Bar;
3957         /*[[p]]*/
3958       } while (true);
3959     }
3960   )";
3961   // The key property that we are verifying is that the analysis succeeds,
3962   // rather than hitting the maximum number of iterations.
3963   runDataflow(
3964       Code,
3965       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3966          ASTContext &ASTCtx) {
3967         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3968         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3969 
3970         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3971         ASSERT_THAT(BarDecl, NotNull());
3972 
3973         auto &BarVal = getFormula(*BarDecl, Env);
3974         EXPECT_TRUE(Env.flowConditionImplies(Env.arena().makeNot(BarVal)));
3975       });
3976 }
3977 
3978 TEST(TransferTest, LoopWithStructReferenceAssignmentConverges) {
3979   std::string Code = R"(
3980     struct Lookup {
3981       int x;
3982     };
3983 
3984     void target(Lookup val, bool b) {
3985       const Lookup* l = nullptr;
3986       while (b) {
3987         l = &val;
3988         /*[[p-inner]]*/
3989       }
3990       (void)0;
3991       /*[[p-outer]]*/
3992     }
3993   )";
3994   // The key property that we are verifying is implicit in `runDataflow` --
3995   // namely, that the analysis succeeds, rather than hitting the maximum number
3996   // of iterations.
3997   runDataflow(
3998       Code,
3999       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4000          ASTContext &ASTCtx) {
4001         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-inner", "p-outer"));
4002         const Environment &InnerEnv =
4003             getEnvironmentAtAnnotation(Results, "p-inner");
4004         const Environment &OuterEnv =
4005             getEnvironmentAtAnnotation(Results, "p-outer");
4006 
4007         const ValueDecl *ValDecl = findValueDecl(ASTCtx, "val");
4008         ASSERT_THAT(ValDecl, NotNull());
4009 
4010         const ValueDecl *LDecl = findValueDecl(ASTCtx, "l");
4011         ASSERT_THAT(LDecl, NotNull());
4012 
4013         // Inner.
4014         auto *LVal = dyn_cast<PointerValue>(InnerEnv.getValue(*LDecl));
4015         ASSERT_THAT(LVal, NotNull());
4016 
4017         EXPECT_EQ(&LVal->getPointeeLoc(),
4018                   InnerEnv.getStorageLocation(*ValDecl));
4019 
4020         // Outer.
4021         LVal = dyn_cast<PointerValue>(OuterEnv.getValue(*LDecl));
4022         ASSERT_THAT(LVal, NotNull());
4023 
4024         // The loop body may not have been executed, so we should not conclude
4025         // that `l` points to `val`.
4026         EXPECT_NE(&LVal->getPointeeLoc(),
4027                   OuterEnv.getStorageLocation(*ValDecl));
4028       });
4029 }
4030 
4031 TEST(TransferTest, LoopDereferencingChangingPointerConverges) {
4032   std::string Code = R"cc(
4033     bool some_condition();
4034 
4035     void target(int i1, int i2) {
4036       int *p = &i1;
4037       while (true) {
4038         (void)*p;
4039         if (some_condition())
4040           p = &i1;
4041         else
4042           p = &i2;
4043       }
4044     }
4045   )cc";
4046   ASSERT_THAT_ERROR(checkDataflowWithNoopAnalysis(Code), llvm::Succeeded());
4047 }
4048 
4049 TEST(TransferTest, LoopDereferencingChangingRecordPointerConverges) {
4050   std::string Code = R"cc(
4051     struct Lookup {
4052       int x;
4053     };
4054 
4055     bool some_condition();
4056 
4057     void target(Lookup l1, Lookup l2) {
4058       Lookup *l = &l1;
4059       while (true) {
4060         (void)l->x;
4061         if (some_condition())
4062           l = &l1;
4063         else
4064           l = &l2;
4065       }
4066     }
4067   )cc";
4068   ASSERT_THAT_ERROR(checkDataflowWithNoopAnalysis(Code), llvm::Succeeded());
4069 }
4070 
4071 TEST(TransferTest, DoesNotCrashOnUnionThisExpr) {
4072   std::string Code = R"(
4073     union Union {
4074       int A;
4075       float B;
4076     };
4077 
4078     void foo() {
4079       Union A;
4080       Union B;
4081       A = B;
4082     }
4083   )";
4084   // This is a crash regression test when calling the transfer function on a
4085   // `CXXThisExpr` that refers to a union.
4086   runDataflow(
4087       Code,
4088       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &,
4089          ASTContext &) {},
4090       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator=");
4091 }
4092 
4093 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToRefs) {
4094   std::string Code = R"(
4095     struct A {
4096       int Foo;
4097       int Bar;
4098     };
4099 
4100     void target() {
4101       int Qux;
4102       A Baz;
4103       Baz.Foo = Qux;
4104       auto &FooRef = Baz.Foo;
4105       auto &BarRef = Baz.Bar;
4106       auto &[BoundFooRef, BoundBarRef] = Baz;
4107       // [[p]]
4108     }
4109   )";
4110   runDataflow(
4111       Code,
4112       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4113          ASTContext &ASTCtx) {
4114         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4115         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4116 
4117         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
4118         ASSERT_THAT(FooRefDecl, NotNull());
4119 
4120         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
4121         ASSERT_THAT(BarRefDecl, NotNull());
4122 
4123         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
4124         ASSERT_THAT(QuxDecl, NotNull());
4125 
4126         const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef");
4127         ASSERT_THAT(BoundFooRefDecl, NotNull());
4128 
4129         const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef");
4130         ASSERT_THAT(BoundBarRefDecl, NotNull());
4131 
4132         const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl);
4133         ASSERT_THAT(FooRefLoc, NotNull());
4134 
4135         const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl);
4136         ASSERT_THAT(BarRefLoc, NotNull());
4137 
4138         const Value *QuxVal = Env.getValue(*QuxDecl);
4139         ASSERT_THAT(QuxVal, NotNull());
4140 
4141         const StorageLocation *BoundFooRefLoc =
4142             Env.getStorageLocation(*BoundFooRefDecl);
4143         EXPECT_EQ(BoundFooRefLoc, FooRefLoc);
4144 
4145         const StorageLocation *BoundBarRefLoc =
4146             Env.getStorageLocation(*BoundBarRefDecl);
4147         EXPECT_EQ(BoundBarRefLoc, BarRefLoc);
4148 
4149         EXPECT_EQ(Env.getValue(*BoundFooRefDecl), QuxVal);
4150       });
4151 }
4152 
4153 TEST(TransferTest, StructuredBindingAssignFromStructRefMembersToRefs) {
4154   std::string Code = R"(
4155     struct A {
4156       int &Foo;
4157       int &Bar;
4158     };
4159 
4160     void target(A Baz) {
4161       int Qux;
4162       Baz.Foo = Qux;
4163       auto &FooRef = Baz.Foo;
4164       auto &BarRef = Baz.Bar;
4165       auto &[BoundFooRef, BoundBarRef] = Baz;
4166       // [[p]]
4167     }
4168   )";
4169   runDataflow(
4170       Code,
4171       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4172          ASTContext &ASTCtx) {
4173         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4174         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4175 
4176         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
4177         ASSERT_THAT(FooRefDecl, NotNull());
4178 
4179         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
4180         ASSERT_THAT(BarRefDecl, NotNull());
4181 
4182         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
4183         ASSERT_THAT(QuxDecl, NotNull());
4184 
4185         const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef");
4186         ASSERT_THAT(BoundFooRefDecl, NotNull());
4187 
4188         const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef");
4189         ASSERT_THAT(BoundBarRefDecl, NotNull());
4190 
4191         const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl);
4192         ASSERT_THAT(FooRefLoc, NotNull());
4193 
4194         const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl);
4195         ASSERT_THAT(BarRefLoc, NotNull());
4196 
4197         const Value *QuxVal = Env.getValue(*QuxDecl);
4198         ASSERT_THAT(QuxVal, NotNull());
4199 
4200         const StorageLocation *BoundFooRefLoc =
4201             Env.getStorageLocation(*BoundFooRefDecl);
4202         EXPECT_EQ(BoundFooRefLoc, FooRefLoc);
4203 
4204         const StorageLocation *BoundBarRefLoc =
4205             Env.getStorageLocation(*BoundBarRefDecl);
4206         EXPECT_EQ(BoundBarRefLoc, BarRefLoc);
4207 
4208         EXPECT_EQ(Env.getValue(*BoundFooRefDecl), QuxVal);
4209       });
4210 }
4211 
4212 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToInts) {
4213   std::string Code = R"(
4214     struct A {
4215       int Foo;
4216       int Bar;
4217     };
4218 
4219     void target() {
4220       int Qux;
4221       A Baz;
4222       Baz.Foo = Qux;
4223       auto &FooRef = Baz.Foo;
4224       auto &BarRef = Baz.Bar;
4225       auto [BoundFoo, BoundBar] = Baz;
4226       // [[p]]
4227     }
4228   )";
4229   runDataflow(
4230       Code,
4231       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4232          ASTContext &ASTCtx) {
4233         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4234         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4235 
4236         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
4237         ASSERT_THAT(FooRefDecl, NotNull());
4238 
4239         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
4240         ASSERT_THAT(BarRefDecl, NotNull());
4241 
4242         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
4243         ASSERT_THAT(BoundFooDecl, NotNull());
4244 
4245         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
4246         ASSERT_THAT(BoundBarDecl, NotNull());
4247 
4248         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
4249         ASSERT_THAT(QuxDecl, NotNull());
4250 
4251         const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl);
4252         ASSERT_THAT(FooRefLoc, NotNull());
4253 
4254         const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl);
4255         ASSERT_THAT(BarRefLoc, NotNull());
4256 
4257         const Value *QuxVal = Env.getValue(*QuxDecl);
4258         ASSERT_THAT(QuxVal, NotNull());
4259 
4260         const StorageLocation *BoundFooLoc =
4261             Env.getStorageLocation(*BoundFooDecl);
4262         EXPECT_NE(BoundFooLoc, FooRefLoc);
4263 
4264         const StorageLocation *BoundBarLoc =
4265             Env.getStorageLocation(*BoundBarDecl);
4266         EXPECT_NE(BoundBarLoc, BarRefLoc);
4267 
4268         EXPECT_EQ(Env.getValue(*BoundFooDecl), QuxVal);
4269       });
4270 }
4271 
4272 TEST(TransferTest, StructuredBindingAssignFromTupleLikeType) {
4273   std::string Code = R"(
4274     namespace std {
4275     using size_t = int;
4276     template <class> struct tuple_size;
4277     template <std::size_t, class> struct tuple_element;
4278     template <class...> class tuple;
4279 
4280     namespace {
4281     template <class T, T v>
4282     struct size_helper { static const T value = v; };
4283     } // namespace
4284 
4285     template <class... T>
4286     struct tuple_size<tuple<T...>> : size_helper<std::size_t, sizeof...(T)> {};
4287 
4288     template <std::size_t I, class... T>
4289     struct tuple_element<I, tuple<T...>> {
4290       using type =  __type_pack_element<I, T...>;
4291     };
4292 
4293     template <class...> class tuple {};
4294 
4295     template <std::size_t I, class... T>
4296     typename tuple_element<I, tuple<T...>>::type get(tuple<T...>);
4297     } // namespace std
4298 
4299     std::tuple<bool, int> makeTuple();
4300 
4301     void target(bool B) {
4302       auto [BoundFoo, BoundBar] = makeTuple();
4303       bool Baz;
4304       // Include if-then-else to test interaction of `BindingDecl` with join.
4305       if (B) {
4306         Baz = BoundFoo;
4307         (void)BoundBar;
4308         // [[p1]]
4309       } else {
4310         Baz = BoundFoo;
4311       }
4312       (void)0;
4313       // [[p2]]
4314     }
4315   )";
4316   runDataflow(
4317       Code,
4318       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4319          ASTContext &ASTCtx) {
4320         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
4321         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
4322 
4323         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
4324         ASSERT_THAT(BoundFooDecl, NotNull());
4325 
4326         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
4327         ASSERT_THAT(BoundBarDecl, NotNull());
4328 
4329         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4330         ASSERT_THAT(BazDecl, NotNull());
4331 
4332         // BindingDecls always map to references -- either lvalue or rvalue, so
4333         // we still need to skip here.
4334         const Value *BoundFooValue = Env1.getValue(*BoundFooDecl);
4335         ASSERT_THAT(BoundFooValue, NotNull());
4336         EXPECT_TRUE(isa<BoolValue>(BoundFooValue));
4337 
4338         const Value *BoundBarValue = Env1.getValue(*BoundBarDecl);
4339         ASSERT_THAT(BoundBarValue, NotNull());
4340         EXPECT_TRUE(isa<IntegerValue>(BoundBarValue));
4341 
4342         // Test that a `DeclRefExpr` to a `BindingDecl` works as expected.
4343         EXPECT_EQ(Env1.getValue(*BazDecl), BoundFooValue);
4344 
4345         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
4346 
4347         // Test that `BoundFooDecl` retains the value we expect, after the join.
4348         BoundFooValue = Env2.getValue(*BoundFooDecl);
4349         EXPECT_EQ(Env2.getValue(*BazDecl), BoundFooValue);
4350       });
4351 }
4352 
4353 TEST(TransferTest, StructuredBindingAssignRefFromTupleLikeType) {
4354   std::string Code = R"(
4355     namespace std {
4356     using size_t = int;
4357     template <class> struct tuple_size;
4358     template <std::size_t, class> struct tuple_element;
4359     template <class...> class tuple;
4360 
4361     namespace {
4362     template <class T, T v>
4363     struct size_helper { static const T value = v; };
4364     } // namespace
4365 
4366     template <class... T>
4367     struct tuple_size<tuple<T...>> : size_helper<std::size_t, sizeof...(T)> {};
4368 
4369     template <std::size_t I, class... T>
4370     struct tuple_element<I, tuple<T...>> {
4371       using type =  __type_pack_element<I, T...>;
4372     };
4373 
4374     template <class...> class tuple {};
4375 
4376     template <std::size_t I, class... T>
4377     typename tuple_element<I, tuple<T...>>::type get(tuple<T...>);
4378     } // namespace std
4379 
4380     std::tuple<bool, int> &getTuple();
4381 
4382     void target(bool B) {
4383       auto &[BoundFoo, BoundBar] = getTuple();
4384       bool Baz;
4385       // Include if-then-else to test interaction of `BindingDecl` with join.
4386       if (B) {
4387         Baz = BoundFoo;
4388         (void)BoundBar;
4389         // [[p1]]
4390       } else {
4391         Baz = BoundFoo;
4392       }
4393       (void)0;
4394       // [[p2]]
4395     }
4396   )";
4397   runDataflow(
4398       Code,
4399       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4400          ASTContext &ASTCtx) {
4401         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
4402         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
4403 
4404         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
4405         ASSERT_THAT(BoundFooDecl, NotNull());
4406 
4407         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
4408         ASSERT_THAT(BoundBarDecl, NotNull());
4409 
4410         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4411         ASSERT_THAT(BazDecl, NotNull());
4412 
4413         const Value *BoundFooValue = Env1.getValue(*BoundFooDecl);
4414         ASSERT_THAT(BoundFooValue, NotNull());
4415         EXPECT_TRUE(isa<BoolValue>(BoundFooValue));
4416 
4417         const Value *BoundBarValue = Env1.getValue(*BoundBarDecl);
4418         ASSERT_THAT(BoundBarValue, NotNull());
4419         EXPECT_TRUE(isa<IntegerValue>(BoundBarValue));
4420 
4421         // Test that a `DeclRefExpr` to a `BindingDecl` (with reference type)
4422         // works as expected. We don't test aliasing properties of the
4423         // reference, because we don't model `std::get` and so have no way to
4424         // equate separate references into the tuple.
4425         EXPECT_EQ(Env1.getValue(*BazDecl), BoundFooValue);
4426 
4427         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
4428 
4429         // Test that `BoundFooDecl` retains the value we expect, after the join.
4430         BoundFooValue = Env2.getValue(*BoundFooDecl);
4431         EXPECT_EQ(Env2.getValue(*BazDecl), BoundFooValue);
4432       });
4433 }
4434 
4435 TEST(TransferTest, BinaryOperatorComma) {
4436   std::string Code = R"(
4437     void target(int Foo, int Bar) {
4438       int &Baz = (Foo, Bar);
4439       // [[p]]
4440     }
4441   )";
4442   runDataflow(
4443       Code,
4444       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4445          ASTContext &ASTCtx) {
4446         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4447         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4448 
4449         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4450         ASSERT_THAT(BarDecl, NotNull());
4451 
4452         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4453         ASSERT_THAT(BazDecl, NotNull());
4454 
4455         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
4456         ASSERT_THAT(BarLoc, NotNull());
4457 
4458         const StorageLocation *BazLoc = Env.getStorageLocation(*BazDecl);
4459         EXPECT_EQ(BazLoc, BarLoc);
4460       });
4461 }
4462 
4463 TEST(TransferTest, IfStmtBranchExtendsFlowCondition) {
4464   std::string Code = R"(
4465     void target(bool Foo) {
4466       if (Foo) {
4467         (void)0;
4468         // [[if_then]]
4469       } else {
4470         (void)0;
4471         // [[if_else]]
4472       }
4473     }
4474   )";
4475   runDataflow(
4476       Code,
4477       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4478          ASTContext &ASTCtx) {
4479         ASSERT_THAT(Results.keys(), UnorderedElementsAre("if_then", "if_else"));
4480         const Environment &ThenEnv =
4481             getEnvironmentAtAnnotation(Results, "if_then");
4482         const Environment &ElseEnv =
4483             getEnvironmentAtAnnotation(Results, "if_else");
4484 
4485         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4486         ASSERT_THAT(FooDecl, NotNull());
4487 
4488         auto &ThenFooVal= getFormula(*FooDecl, ThenEnv);
4489         EXPECT_TRUE(ThenEnv.flowConditionImplies(ThenFooVal));
4490 
4491         auto &ElseFooVal = getFormula(*FooDecl, ElseEnv);
4492         EXPECT_TRUE(
4493             ElseEnv.flowConditionImplies(ElseEnv.arena().makeNot(ElseFooVal)));
4494       });
4495 }
4496 
4497 TEST(TransferTest, WhileStmtBranchExtendsFlowCondition) {
4498   std::string Code = R"(
4499     void target(bool Foo) {
4500       while (Foo) {
4501         (void)0;
4502         // [[loop_body]]
4503       }
4504       (void)0;
4505       // [[after_loop]]
4506     }
4507   )";
4508   runDataflow(
4509       Code,
4510       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4511          ASTContext &ASTCtx) {
4512         ASSERT_THAT(Results.keys(),
4513                     UnorderedElementsAre("loop_body", "after_loop"));
4514         const Environment &LoopBodyEnv =
4515             getEnvironmentAtAnnotation(Results, "loop_body");
4516         const Environment &AfterLoopEnv =
4517             getEnvironmentAtAnnotation(Results, "after_loop");
4518 
4519         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4520         ASSERT_THAT(FooDecl, NotNull());
4521 
4522         auto &LoopBodyFooVal = getFormula(*FooDecl, LoopBodyEnv);
4523         EXPECT_TRUE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal));
4524 
4525         auto &AfterLoopFooVal = getFormula(*FooDecl, AfterLoopEnv);
4526         EXPECT_TRUE(AfterLoopEnv.flowConditionImplies(
4527             AfterLoopEnv.arena().makeNot(AfterLoopFooVal)));
4528       });
4529 }
4530 
4531 TEST(TransferTest, DoWhileStmtBranchExtendsFlowCondition) {
4532   std::string Code = R"(
4533     void target(bool Foo) {
4534       bool Bar = true;
4535       do {
4536         (void)0;
4537         // [[loop_body]]
4538         Bar = false;
4539       } while (Foo);
4540       (void)0;
4541       // [[after_loop]]
4542     }
4543   )";
4544   runDataflow(
4545       Code,
4546       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4547          ASTContext &ASTCtx) {
4548         ASSERT_THAT(Results.keys(),
4549                     UnorderedElementsAre("loop_body", "after_loop"));
4550         const Environment &LoopBodyEnv =
4551             getEnvironmentAtAnnotation(Results, "loop_body");
4552         const Environment &AfterLoopEnv =
4553             getEnvironmentAtAnnotation(Results, "after_loop");
4554         auto &A = AfterLoopEnv.arena();
4555 
4556         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4557         ASSERT_THAT(FooDecl, NotNull());
4558 
4559         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4560         ASSERT_THAT(BarDecl, NotNull());
4561 
4562         auto &LoopBodyFooVal= getFormula(*FooDecl, LoopBodyEnv);
4563         auto &LoopBodyBarVal = getFormula(*BarDecl, LoopBodyEnv);
4564         EXPECT_TRUE(LoopBodyEnv.flowConditionImplies(
4565             A.makeOr(LoopBodyBarVal, LoopBodyFooVal)));
4566 
4567         auto &AfterLoopFooVal = getFormula(*FooDecl, AfterLoopEnv);
4568         auto &AfterLoopBarVal = getFormula(*BarDecl, AfterLoopEnv);
4569         EXPECT_TRUE(
4570             AfterLoopEnv.flowConditionImplies(A.makeNot(AfterLoopFooVal)));
4571         EXPECT_TRUE(
4572             AfterLoopEnv.flowConditionImplies(A.makeNot(AfterLoopBarVal)));
4573       });
4574 }
4575 
4576 TEST(TransferTest, ForStmtBranchExtendsFlowCondition) {
4577   std::string Code = R"(
4578     void target(bool Foo) {
4579       for (; Foo;) {
4580         (void)0;
4581         // [[loop_body]]
4582       }
4583       (void)0;
4584       // [[after_loop]]
4585     }
4586   )";
4587   runDataflow(
4588       Code,
4589       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4590          ASTContext &ASTCtx) {
4591         ASSERT_THAT(Results.keys(),
4592                     UnorderedElementsAre("loop_body", "after_loop"));
4593         const Environment &LoopBodyEnv =
4594             getEnvironmentAtAnnotation(Results, "loop_body");
4595         const Environment &AfterLoopEnv =
4596             getEnvironmentAtAnnotation(Results, "after_loop");
4597 
4598         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4599         ASSERT_THAT(FooDecl, NotNull());
4600 
4601         auto &LoopBodyFooVal= getFormula(*FooDecl, LoopBodyEnv);
4602         EXPECT_TRUE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal));
4603 
4604         auto &AfterLoopFooVal = getFormula(*FooDecl, AfterLoopEnv);
4605         EXPECT_TRUE(AfterLoopEnv.flowConditionImplies(
4606             AfterLoopEnv.arena().makeNot(AfterLoopFooVal)));
4607       });
4608 }
4609 
4610 TEST(TransferTest, ForStmtBranchWithoutConditionDoesNotExtendFlowCondition) {
4611   std::string Code = R"(
4612     void target(bool Foo) {
4613       for (;;) {
4614         (void)0;
4615         // [[loop_body]]
4616       }
4617     }
4618   )";
4619   runDataflow(
4620       Code,
4621       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4622          ASTContext &ASTCtx) {
4623         ASSERT_THAT(Results.keys(), UnorderedElementsAre("loop_body"));
4624         const Environment &LoopBodyEnv =
4625             getEnvironmentAtAnnotation(Results, "loop_body");
4626 
4627         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4628         ASSERT_THAT(FooDecl, NotNull());
4629 
4630         auto &LoopBodyFooVal= getFormula(*FooDecl, LoopBodyEnv);
4631         EXPECT_FALSE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal));
4632       });
4633 }
4634 
4635 TEST(TransferTest, ContextSensitiveOptionDisabled) {
4636   std::string Code = R"(
4637     bool GiveBool();
4638     void SetBool(bool &Var) { Var = true; }
4639 
4640     void target() {
4641       bool Foo = GiveBool();
4642       SetBool(Foo);
4643       // [[p]]
4644     }
4645   )";
4646   runDataflow(
4647       Code,
4648       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4649          ASTContext &ASTCtx) {
4650         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4651         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4652 
4653         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4654         ASSERT_THAT(FooDecl, NotNull());
4655 
4656         auto &FooVal = getFormula(*FooDecl, Env);
4657         EXPECT_FALSE(Env.flowConditionImplies(FooVal));
4658         EXPECT_FALSE(Env.flowConditionImplies(Env.arena().makeNot(FooVal)));
4659       },
4660       {BuiltinOptions{/*.ContextSensitiveOpts=*/std::nullopt}});
4661 }
4662 
4663 TEST(TransferTest, ContextSensitiveReturnReference) {
4664   std::string Code = R"(
4665     class S {};
4666     S& target(bool b, S &s) {
4667       return s;
4668       // [[p]]
4669     }
4670   )";
4671   runDataflow(
4672       Code,
4673       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4674          ASTContext &ASTCtx) {
4675         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4676 
4677         const ValueDecl *SDecl = findValueDecl(ASTCtx, "s");
4678         ASSERT_THAT(SDecl, NotNull());
4679 
4680         auto *SLoc = Env.getStorageLocation(*SDecl);
4681         ASSERT_THAT(SLoc, NotNull());
4682 
4683         ASSERT_THAT(Env.getReturnStorageLocation(), Eq(SLoc));
4684       },
4685       {BuiltinOptions{ContextSensitiveOptions{}}});
4686 }
4687 
4688 // This test is a regression test, based on a real crash.
4689 TEST(TransferTest, ContextSensitiveReturnReferenceWithConditionalOperator) {
4690   std::string Code = R"(
4691     class S {};
4692     S& target(bool b, S &s) {
4693       return b ? s : s;
4694       // [[p]]
4695     }
4696   )";
4697   runDataflow(
4698       Code,
4699       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4700          ASTContext &ASTCtx) {
4701         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4702         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4703 
4704         const ValueDecl *SDecl = findValueDecl(ASTCtx, "s");
4705         ASSERT_THAT(SDecl, NotNull());
4706 
4707         auto *SLoc = Env.getStorageLocation(*SDecl);
4708         ASSERT_THAT(SLoc, NotNull());
4709         EXPECT_THAT(Env.getValue(*SLoc), NotNull());
4710 
4711         auto *Loc = Env.getReturnStorageLocation();
4712         ASSERT_THAT(Loc, NotNull());
4713         EXPECT_THAT(Env.getValue(*Loc), NotNull());
4714 
4715         // TODO: We would really like to make this stronger assertion, but that
4716         // doesn't work because we don't propagate values correctly through
4717         // the conditional operator yet.
4718         // ASSERT_THAT(Loc, Eq(SLoc));
4719       },
4720       {BuiltinOptions{ContextSensitiveOptions{}}});
4721 }
4722 
4723 TEST(TransferTest, ContextSensitiveReturnOneOfTwoReferences) {
4724   std::string Code = R"(
4725     class S {};
4726     S &callee(bool b, S &s1_parm, S &s2_parm) {
4727       if (b)
4728         return s1_parm;
4729       else
4730         return s2_parm;
4731     }
4732     void target(bool b) {
4733       S s1;
4734       S s2;
4735       S &return_s1 = s1;
4736       S &return_s2 = s2;
4737       S &return_dont_know = callee(b, s1, s2);
4738       // [[p]]
4739     }
4740   )";
4741   runDataflow(
4742       Code,
4743       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4744          ASTContext &ASTCtx) {
4745         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4746 
4747         const ValueDecl *S1 = findValueDecl(ASTCtx, "s1");
4748         ASSERT_THAT(S1, NotNull());
4749         const ValueDecl *S2 = findValueDecl(ASTCtx, "s2");
4750         ASSERT_THAT(S2, NotNull());
4751         const ValueDecl *ReturnS1 = findValueDecl(ASTCtx, "return_s1");
4752         ASSERT_THAT(ReturnS1, NotNull());
4753         const ValueDecl *ReturnS2 = findValueDecl(ASTCtx, "return_s2");
4754         ASSERT_THAT(ReturnS2, NotNull());
4755         const ValueDecl *ReturnDontKnow =
4756             findValueDecl(ASTCtx, "return_dont_know");
4757         ASSERT_THAT(ReturnDontKnow, NotNull());
4758 
4759         StorageLocation *S1Loc = Env.getStorageLocation(*S1);
4760         StorageLocation *S2Loc = Env.getStorageLocation(*S2);
4761 
4762         EXPECT_THAT(Env.getStorageLocation(*ReturnS1), Eq(S1Loc));
4763         EXPECT_THAT(Env.getStorageLocation(*ReturnS2), Eq(S2Loc));
4764 
4765         // In the case where we don't have a consistent storage location for
4766         // the return value, the framework creates a new storage location, which
4767         // should be different from the storage locations of `s1` and `s2`.
4768         EXPECT_THAT(Env.getStorageLocation(*ReturnDontKnow), Ne(S1Loc));
4769         EXPECT_THAT(Env.getStorageLocation(*ReturnDontKnow), Ne(S2Loc));
4770       },
4771       {BuiltinOptions{ContextSensitiveOptions{}}});
4772 }
4773 
4774 TEST(TransferTest, ContextSensitiveDepthZero) {
4775   std::string Code = R"(
4776     bool GiveBool();
4777     void SetBool(bool &Var) { Var = true; }
4778 
4779     void target() {
4780       bool Foo = GiveBool();
4781       SetBool(Foo);
4782       // [[p]]
4783     }
4784   )";
4785   runDataflow(
4786       Code,
4787       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4788          ASTContext &ASTCtx) {
4789         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4790         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4791 
4792         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4793         ASSERT_THAT(FooDecl, NotNull());
4794 
4795         auto &FooVal = getFormula(*FooDecl, Env);
4796         EXPECT_FALSE(Env.flowConditionImplies(FooVal));
4797         EXPECT_FALSE(Env.flowConditionImplies(Env.arena().makeNot(FooVal)));
4798       },
4799       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/0}}});
4800 }
4801 
4802 TEST(TransferTest, ContextSensitiveSetTrue) {
4803   std::string Code = R"(
4804     bool GiveBool();
4805     void SetBool(bool &Var) { Var = true; }
4806 
4807     void target() {
4808       bool Foo = GiveBool();
4809       SetBool(Foo);
4810       // [[p]]
4811     }
4812   )";
4813   runDataflow(
4814       Code,
4815       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4816          ASTContext &ASTCtx) {
4817         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4818         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4819 
4820         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4821         ASSERT_THAT(FooDecl, NotNull());
4822 
4823         auto &FooVal = getFormula(*FooDecl, Env);
4824         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4825       },
4826       {BuiltinOptions{ContextSensitiveOptions{}}});
4827 }
4828 
4829 TEST(TransferTest, ContextSensitiveSetFalse) {
4830   std::string Code = R"(
4831     bool GiveBool();
4832     void SetBool(bool &Var) { Var = false; }
4833 
4834     void target() {
4835       bool Foo = GiveBool();
4836       SetBool(Foo);
4837       // [[p]]
4838     }
4839   )";
4840   runDataflow(
4841       Code,
4842       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4843          ASTContext &ASTCtx) {
4844         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4845         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4846 
4847         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4848         ASSERT_THAT(FooDecl, NotNull());
4849 
4850         auto &FooVal = getFormula(*FooDecl, Env);
4851         EXPECT_TRUE(Env.flowConditionImplies(Env.arena().makeNot(FooVal)));
4852       },
4853       {BuiltinOptions{ContextSensitiveOptions{}}});
4854 }
4855 
4856 TEST(TransferTest, ContextSensitiveSetBothTrueAndFalse) {
4857   std::string Code = R"(
4858     bool GiveBool();
4859     void SetBool(bool &Var, bool Val) { Var = Val; }
4860 
4861     void target() {
4862       bool Foo = GiveBool();
4863       bool Bar = GiveBool();
4864       SetBool(Foo, true);
4865       SetBool(Bar, false);
4866       // [[p]]
4867     }
4868   )";
4869   runDataflow(
4870       Code,
4871       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4872          ASTContext &ASTCtx) {
4873         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4874         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4875         auto &A = Env.arena();
4876 
4877         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4878         ASSERT_THAT(FooDecl, NotNull());
4879 
4880         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4881         ASSERT_THAT(BarDecl, NotNull());
4882 
4883         auto &FooVal = getFormula(*FooDecl, Env);
4884         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4885         EXPECT_FALSE(Env.flowConditionImplies(A.makeNot(FooVal)));
4886 
4887         auto &BarVal = getFormula(*BarDecl, Env);
4888         EXPECT_FALSE(Env.flowConditionImplies(BarVal));
4889         EXPECT_TRUE(Env.flowConditionImplies(A.makeNot(BarVal)));
4890       },
4891       {BuiltinOptions{ContextSensitiveOptions{}}});
4892 }
4893 
4894 TEST(TransferTest, ContextSensitiveSetTwoLayersDepthOne) {
4895   std::string Code = R"(
4896     bool GiveBool();
4897     void SetBool1(bool &Var) { Var = true; }
4898     void SetBool2(bool &Var) { SetBool1(Var); }
4899 
4900     void target() {
4901       bool Foo = GiveBool();
4902       SetBool2(Foo);
4903       // [[p]]
4904     }
4905   )";
4906   runDataflow(
4907       Code,
4908       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4909          ASTContext &ASTCtx) {
4910         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4911         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4912 
4913         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4914         ASSERT_THAT(FooDecl, NotNull());
4915 
4916         auto &FooVal = getFormula(*FooDecl, Env);
4917         EXPECT_FALSE(Env.flowConditionImplies(FooVal));
4918         EXPECT_FALSE(Env.flowConditionImplies(Env.arena().makeNot(FooVal)));
4919       },
4920       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/1}}});
4921 }
4922 
4923 TEST(TransferTest, ContextSensitiveSetTwoLayersDepthTwo) {
4924   std::string Code = R"(
4925     bool GiveBool();
4926     void SetBool1(bool &Var) { Var = true; }
4927     void SetBool2(bool &Var) { SetBool1(Var); }
4928 
4929     void target() {
4930       bool Foo = GiveBool();
4931       SetBool2(Foo);
4932       // [[p]]
4933     }
4934   )";
4935   runDataflow(
4936       Code,
4937       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4938          ASTContext &ASTCtx) {
4939         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4940         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4941 
4942         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4943         ASSERT_THAT(FooDecl, NotNull());
4944 
4945         auto &FooVal = getFormula(*FooDecl, Env);
4946         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4947       },
4948       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/2}}});
4949 }
4950 
4951 TEST(TransferTest, ContextSensitiveSetThreeLayersDepthTwo) {
4952   std::string Code = R"(
4953     bool GiveBool();
4954     void SetBool1(bool &Var) { Var = true; }
4955     void SetBool2(bool &Var) { SetBool1(Var); }
4956     void SetBool3(bool &Var) { SetBool2(Var); }
4957 
4958     void target() {
4959       bool Foo = GiveBool();
4960       SetBool3(Foo);
4961       // [[p]]
4962     }
4963   )";
4964   runDataflow(
4965       Code,
4966       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4967          ASTContext &ASTCtx) {
4968         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4969         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4970 
4971         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4972         ASSERT_THAT(FooDecl, NotNull());
4973 
4974         auto &FooVal = getFormula(*FooDecl, Env);
4975         EXPECT_FALSE(Env.flowConditionImplies(FooVal));
4976         EXPECT_FALSE(Env.flowConditionImplies(Env.arena().makeNot(FooVal)));
4977       },
4978       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/2}}});
4979 }
4980 
4981 TEST(TransferTest, ContextSensitiveSetThreeLayersDepthThree) {
4982   std::string Code = R"(
4983     bool GiveBool();
4984     void SetBool1(bool &Var) { Var = true; }
4985     void SetBool2(bool &Var) { SetBool1(Var); }
4986     void SetBool3(bool &Var) { SetBool2(Var); }
4987 
4988     void target() {
4989       bool Foo = GiveBool();
4990       SetBool3(Foo);
4991       // [[p]]
4992     }
4993   )";
4994   runDataflow(
4995       Code,
4996       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4997          ASTContext &ASTCtx) {
4998         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4999         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5000 
5001         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5002         ASSERT_THAT(FooDecl, NotNull());
5003 
5004         auto &FooVal = getFormula(*FooDecl, Env);
5005         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
5006       },
5007       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/3}}});
5008 }
5009 
5010 TEST(TransferTest, ContextSensitiveMutualRecursion) {
5011   std::string Code = R"(
5012     bool Pong(bool X, bool Y);
5013 
5014     bool Ping(bool X, bool Y) {
5015       if (X) {
5016         return Y;
5017       } else {
5018         return Pong(!X, Y);
5019       }
5020     }
5021 
5022     bool Pong(bool X, bool Y) {
5023       if (Y) {
5024         return X;
5025       } else {
5026         return Ping(X, !Y);
5027       }
5028     }
5029 
5030     void target() {
5031       bool Foo = Ping(false, false);
5032       // [[p]]
5033     }
5034   )";
5035   runDataflow(
5036       Code,
5037       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5038          ASTContext &ASTCtx) {
5039         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5040         // The analysis doesn't crash...
5041         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5042 
5043         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5044         ASSERT_THAT(FooDecl, NotNull());
5045 
5046         auto &FooVal = getFormula(*FooDecl, Env);
5047         // ... but it also can't prove anything here.
5048         EXPECT_FALSE(Env.flowConditionImplies(FooVal));
5049         EXPECT_FALSE(Env.flowConditionImplies(Env.arena().makeNot(FooVal)));
5050       },
5051       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/4}}});
5052 }
5053 
5054 TEST(TransferTest, ContextSensitiveSetMultipleLines) {
5055   std::string Code = R"(
5056     void SetBools(bool &Var1, bool &Var2) {
5057       Var1 = true;
5058       Var2 = false;
5059     }
5060 
5061     void target() {
5062       bool Foo = false;
5063       bool Bar = true;
5064       SetBools(Foo, Bar);
5065       // [[p]]
5066     }
5067   )";
5068   runDataflow(
5069       Code,
5070       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5071          ASTContext &ASTCtx) {
5072         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5073         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5074 
5075         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5076         ASSERT_THAT(FooDecl, NotNull());
5077 
5078         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
5079         ASSERT_THAT(BarDecl, NotNull());
5080 
5081         auto &FooVal = getFormula(*FooDecl, Env);
5082         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
5083         EXPECT_FALSE(Env.flowConditionImplies(Env.arena().makeNot(FooVal)));
5084 
5085         auto &BarVal = getFormula(*BarDecl, Env);
5086         EXPECT_FALSE(Env.flowConditionImplies(BarVal));
5087         EXPECT_TRUE(Env.flowConditionImplies(Env.arena().makeNot(BarVal)));
5088       },
5089       {BuiltinOptions{ContextSensitiveOptions{}}});
5090 }
5091 
5092 TEST(TransferTest, ContextSensitiveSetMultipleBlocks) {
5093   std::string Code = R"(
5094     void IfCond(bool Cond, bool &Then, bool &Else) {
5095       if (Cond) {
5096         Then = true;
5097       } else {
5098         Else = true;
5099       }
5100     }
5101 
5102     void target() {
5103       bool Foo = false;
5104       bool Bar = false;
5105       bool Baz = false;
5106       IfCond(Foo, Bar, Baz);
5107       // [[p]]
5108     }
5109   )";
5110   runDataflow(
5111       Code,
5112       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5113          ASTContext &ASTCtx) {
5114         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5115         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5116 
5117         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
5118         ASSERT_THAT(BarDecl, NotNull());
5119 
5120         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
5121         ASSERT_THAT(BazDecl, NotNull());
5122 
5123         auto &BarVal = getFormula(*BarDecl, Env);
5124         EXPECT_FALSE(Env.flowConditionImplies(BarVal));
5125         EXPECT_TRUE(Env.flowConditionImplies(Env.arena().makeNot(BarVal)));
5126 
5127         auto &BazVal = getFormula(*BazDecl, Env);
5128         EXPECT_TRUE(Env.flowConditionImplies(BazVal));
5129         EXPECT_FALSE(Env.flowConditionImplies(Env.arena().makeNot(BazVal)));
5130       },
5131       {BuiltinOptions{ContextSensitiveOptions{}}});
5132 }
5133 
5134 TEST(TransferTest, ContextSensitiveReturnVoid) {
5135   std::string Code = R"(
5136     void Noop() { return; }
5137 
5138     void target() {
5139       Noop();
5140       // [[p]]
5141     }
5142   )";
5143   runDataflow(
5144       Code,
5145       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5146          ASTContext &ASTCtx) {
5147         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5148         // This just tests that the analysis doesn't crash.
5149       },
5150       {BuiltinOptions{ContextSensitiveOptions{}}});
5151 }
5152 
5153 TEST(TransferTest, ContextSensitiveReturnTrue) {
5154   std::string Code = R"(
5155     bool GiveBool() { return true; }
5156 
5157     void target() {
5158       bool Foo = GiveBool();
5159       // [[p]]
5160     }
5161   )";
5162   runDataflow(
5163       Code,
5164       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5165          ASTContext &ASTCtx) {
5166         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5167         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5168 
5169         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5170         ASSERT_THAT(FooDecl, NotNull());
5171 
5172         auto &FooVal = getFormula(*FooDecl, Env);
5173         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
5174       },
5175       {BuiltinOptions{ContextSensitiveOptions{}}});
5176 }
5177 
5178 TEST(TransferTest, ContextSensitiveReturnFalse) {
5179   std::string Code = R"(
5180     bool GiveBool() { return false; }
5181 
5182     void target() {
5183       bool Foo = GiveBool();
5184       // [[p]]
5185     }
5186   )";
5187   runDataflow(
5188       Code,
5189       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5190          ASTContext &ASTCtx) {
5191         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5192         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5193 
5194         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5195         ASSERT_THAT(FooDecl, NotNull());
5196 
5197         auto &FooVal = getFormula(*FooDecl, Env);
5198         EXPECT_TRUE(Env.flowConditionImplies(Env.arena().makeNot(FooVal)));
5199       },
5200       {BuiltinOptions{ContextSensitiveOptions{}}});
5201 }
5202 
5203 TEST(TransferTest, ContextSensitiveReturnArg) {
5204   std::string Code = R"(
5205     bool GiveBool();
5206     bool GiveBack(bool Arg) { return Arg; }
5207 
5208     void target() {
5209       bool Foo = GiveBool();
5210       bool Bar = GiveBack(Foo);
5211       bool Baz = Foo == Bar;
5212       // [[p]]
5213     }
5214   )";
5215   runDataflow(
5216       Code,
5217       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5218          ASTContext &ASTCtx) {
5219         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5220         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5221 
5222         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
5223         ASSERT_THAT(BazDecl, NotNull());
5224 
5225         auto &BazVal = getFormula(*BazDecl, Env);
5226         EXPECT_TRUE(Env.flowConditionImplies(BazVal));
5227       },
5228       {BuiltinOptions{ContextSensitiveOptions{}}});
5229 }
5230 
5231 TEST(TransferTest, ContextSensitiveReturnInt) {
5232   std::string Code = R"(
5233     int identity(int x) { return x; }
5234 
5235     void target() {
5236       int y = identity(42);
5237       // [[p]]
5238     }
5239   )";
5240   runDataflow(
5241       Code,
5242       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5243          ASTContext &ASTCtx) {
5244         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5245         // This just tests that the analysis doesn't crash.
5246       },
5247       {BuiltinOptions{ContextSensitiveOptions{}}});
5248 }
5249 
5250 TEST(TransferTest, ContextSensitiveMethodLiteral) {
5251   std::string Code = R"(
5252     class MyClass {
5253     public:
5254       bool giveBool() { return true; }
5255     };
5256 
5257     void target() {
5258       MyClass MyObj;
5259       bool Foo = MyObj.giveBool();
5260       // [[p]]
5261     }
5262   )";
5263   runDataflow(
5264       Code,
5265       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5266          ASTContext &ASTCtx) {
5267         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5268         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5269 
5270         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5271         ASSERT_THAT(FooDecl, NotNull());
5272 
5273         auto &FooVal = getFormula(*FooDecl, Env);
5274         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
5275       },
5276       {BuiltinOptions{ContextSensitiveOptions{}}});
5277 }
5278 
5279 TEST(TransferTest, ContextSensitiveMethodGetter) {
5280   std::string Code = R"(
5281     class MyClass {
5282     public:
5283       bool getField() { return Field; }
5284 
5285       bool Field;
5286     };
5287 
5288     void target() {
5289       MyClass MyObj;
5290       MyObj.Field = true;
5291       bool Foo = MyObj.getField();
5292       // [[p]]
5293     }
5294   )";
5295   runDataflow(
5296       Code,
5297       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5298          ASTContext &ASTCtx) {
5299         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5300         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5301 
5302         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5303         ASSERT_THAT(FooDecl, NotNull());
5304 
5305         auto &FooVal = getFormula(*FooDecl, Env);
5306         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
5307       },
5308       {BuiltinOptions{ContextSensitiveOptions{}}});
5309 }
5310 
5311 TEST(TransferTest, ContextSensitiveMethodSetter) {
5312   std::string Code = R"(
5313     class MyClass {
5314     public:
5315       void setField(bool Val) { Field = Val; }
5316 
5317       bool Field;
5318     };
5319 
5320     void target() {
5321       MyClass MyObj;
5322       MyObj.setField(true);
5323       bool Foo = MyObj.Field;
5324       // [[p]]
5325     }
5326   )";
5327   runDataflow(
5328       Code,
5329       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5330          ASTContext &ASTCtx) {
5331         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5332         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5333 
5334         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5335         ASSERT_THAT(FooDecl, NotNull());
5336 
5337         auto &FooVal = getFormula(*FooDecl, Env);
5338         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
5339       },
5340       {BuiltinOptions{ContextSensitiveOptions{}}});
5341 }
5342 
5343 TEST(TransferTest, ContextSensitiveMethodGetterAndSetter) {
5344   std::string Code = R"(
5345     class MyClass {
5346     public:
5347       bool getField() { return Field; }
5348       void setField(bool Val) { Field = Val; }
5349 
5350     private:
5351       bool Field;
5352     };
5353 
5354     void target() {
5355       MyClass MyObj;
5356       MyObj.setField(true);
5357       bool Foo = MyObj.getField();
5358       // [[p]]
5359     }
5360   )";
5361   runDataflow(
5362       Code,
5363       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5364          ASTContext &ASTCtx) {
5365         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5366         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5367 
5368         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5369         ASSERT_THAT(FooDecl, NotNull());
5370 
5371         auto &FooVal = getFormula(*FooDecl, Env);
5372         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
5373       },
5374       {BuiltinOptions{ContextSensitiveOptions{}}});
5375 }
5376 
5377 
5378 TEST(TransferTest, ContextSensitiveMethodTwoLayersVoid) {
5379   std::string Code = R"(
5380     class MyClass {
5381     public:
5382       void Inner() { MyField = true; }
5383       void Outer() { Inner(); }
5384 
5385       bool MyField;
5386     };
5387 
5388     void target() {
5389       MyClass MyObj;
5390       MyObj.Outer();
5391       bool Foo = MyObj.MyField;
5392       // [[p]]
5393     }
5394   )";
5395   runDataflow(
5396       Code,
5397       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5398          ASTContext &ASTCtx) {
5399         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5400         ;
5401         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5402 
5403         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5404         ASSERT_THAT(FooDecl, NotNull());
5405 
5406         auto &FooVal = getFormula(*FooDecl, Env);
5407         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
5408       },
5409       {BuiltinOptions{ContextSensitiveOptions{}}});
5410 }
5411 
5412 TEST(TransferTest, ContextSensitiveMethodTwoLayersReturn) {
5413   std::string Code = R"(
5414     class MyClass {
5415     public:
5416       bool Inner() { return MyField; }
5417       bool Outer() { return Inner(); }
5418 
5419       bool MyField;
5420     };
5421 
5422     void target() {
5423       MyClass MyObj;
5424       MyObj.MyField = true;
5425       bool Foo = MyObj.Outer();
5426       // [[p]]
5427     }
5428   )";
5429   runDataflow(
5430       Code,
5431       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5432          ASTContext &ASTCtx) {
5433         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5434         ;
5435         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5436 
5437         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5438         ASSERT_THAT(FooDecl, NotNull());
5439 
5440         auto &FooVal = getFormula(*FooDecl, Env);
5441         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
5442       },
5443       {BuiltinOptions{ContextSensitiveOptions{}}});
5444 }
5445 
5446 TEST(TransferTest, ContextSensitiveConstructorBody) {
5447   std::string Code = R"(
5448     class MyClass {
5449     public:
5450       MyClass() { MyField = true; }
5451 
5452       bool MyField;
5453     };
5454 
5455     void target() {
5456       MyClass MyObj;
5457       bool Foo = MyObj.MyField;
5458       // [[p]]
5459     }
5460   )";
5461   runDataflow(
5462       Code,
5463       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5464          ASTContext &ASTCtx) {
5465         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5466         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5467 
5468         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5469         ASSERT_THAT(FooDecl, NotNull());
5470 
5471         auto &FooVal = getFormula(*FooDecl, Env);
5472         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
5473       },
5474       {BuiltinOptions{ContextSensitiveOptions{}}});
5475 }
5476 
5477 TEST(TransferTest, ContextSensitiveConstructorInitializer) {
5478   std::string Code = R"(
5479     class MyClass {
5480     public:
5481       MyClass() : MyField(true) {}
5482 
5483       bool MyField;
5484     };
5485 
5486     void target() {
5487       MyClass MyObj;
5488       bool Foo = MyObj.MyField;
5489       // [[p]]
5490     }
5491   )";
5492   runDataflow(
5493       Code,
5494       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5495          ASTContext &ASTCtx) {
5496         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5497         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5498 
5499         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5500         ASSERT_THAT(FooDecl, NotNull());
5501 
5502         auto &FooVal = getFormula(*FooDecl, Env);
5503         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
5504       },
5505       {BuiltinOptions{ContextSensitiveOptions{}}});
5506 }
5507 
5508 TEST(TransferTest, ContextSensitiveConstructorDefault) {
5509   std::string Code = R"(
5510     class MyClass {
5511     public:
5512       MyClass() = default;
5513 
5514       bool MyField = true;
5515     };
5516 
5517     void target() {
5518       MyClass MyObj;
5519       bool Foo = MyObj.MyField;
5520       // [[p]]
5521     }
5522   )";
5523   runDataflow(
5524       Code,
5525       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5526          ASTContext &ASTCtx) {
5527         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5528         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5529 
5530         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5531         ASSERT_THAT(FooDecl, NotNull());
5532 
5533         auto &FooVal = getFormula(*FooDecl, Env);
5534         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
5535       },
5536       {BuiltinOptions{ContextSensitiveOptions{}}});
5537 }
5538 
5539 TEST(TransferTest, ContextSensitiveSelfReferentialClass) {
5540   // Test that the `this` pointer seen in the constructor has the same value
5541   // as the address of the variable the object is constructed into.
5542   std::string Code = R"(
5543     class MyClass {
5544     public:
5545       MyClass() : Self(this) {}
5546       MyClass *Self;
5547     };
5548 
5549     void target() {
5550       MyClass MyObj;
5551       MyClass *SelfPtr = MyObj.Self;
5552       // [[p]]
5553     }
5554   )";
5555   runDataflow(
5556       Code,
5557       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5558          ASTContext &ASTCtx) {
5559         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5560 
5561         const ValueDecl *MyObjDecl = findValueDecl(ASTCtx, "MyObj");
5562         ASSERT_THAT(MyObjDecl, NotNull());
5563 
5564         const ValueDecl *SelfDecl = findValueDecl(ASTCtx, "SelfPtr");
5565         ASSERT_THAT(SelfDecl, NotNull());
5566 
5567         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5568         auto &SelfVal = *cast<PointerValue>(Env.getValue(*SelfDecl));
5569         EXPECT_EQ(Env.getStorageLocation(*MyObjDecl), &SelfVal.getPointeeLoc());
5570       },
5571       {BuiltinOptions{ContextSensitiveOptions{}}});
5572 }
5573 
5574 TEST(TransferTest, UnnamedBitfieldInitializer) {
5575   std::string Code = R"(
5576     struct B {};
5577     struct A {
5578       unsigned a;
5579       unsigned : 4;
5580       unsigned c;
5581       B b;
5582     };
5583     void target() {
5584       A a = {};
5585       A test = a;
5586       (void)test.c;
5587     }
5588   )";
5589   runDataflow(
5590       Code,
5591       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5592          ASTContext &ASTCtx) {
5593         // This doesn't need a body because this test was crashing the framework
5594         // before handling correctly Unnamed bitfields in `InitListExpr`.
5595       });
5596 }
5597 
5598 // Repro for a crash that used to occur with chained short-circuiting logical
5599 // operators.
5600 TEST(TransferTest, ChainedLogicalOps) {
5601   std::string Code = R"(
5602     bool target() {
5603       bool b = true || false || false || false;
5604       // [[p]]
5605       return b;
5606     }
5607   )";
5608   runDataflow(
5609       Code,
5610       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5611          ASTContext &ASTCtx) {
5612         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5613         auto &B = getValueForDecl<BoolValue>(ASTCtx, Env, "b").formula();
5614         EXPECT_TRUE(Env.flowConditionImplies(B));
5615       });
5616 }
5617 
5618 // Repro for a crash that used to occur when we call a `noreturn` function
5619 // within one of the operands of a `&&` or `||` operator.
5620 TEST(TransferTest, NoReturnFunctionInsideShortCircuitedBooleanOp) {
5621   std::string Code = R"(
5622     __attribute__((noreturn)) int doesnt_return();
5623     bool some_condition();
5624     void target(bool b1, bool b2) {
5625       // Neither of these should crash. In addition, if we don't terminate the
5626       // program, we know that the operators need to trigger the short-circuit
5627       // logic, so `NoreturnOnRhsOfAnd` will be false and `NoreturnOnRhsOfOr`
5628       // will be true.
5629       bool NoreturnOnRhsOfAnd = b1 && doesnt_return() > 0;
5630       bool NoreturnOnRhsOfOr = b2 || doesnt_return() > 0;
5631 
5632       // Calling a `noreturn` function on the LHS of an `&&` or `||` makes the
5633       // entire expression unreachable. So we know that in both of the following
5634       // cases, if `target()` terminates, the `else` branch was taken.
5635       bool NoreturnOnLhsMakesAndUnreachable = false;
5636       if (some_condition())
5637          doesnt_return() > 0 && some_condition();
5638       else
5639          NoreturnOnLhsMakesAndUnreachable = true;
5640 
5641       bool NoreturnOnLhsMakesOrUnreachable = false;
5642       if (some_condition())
5643          doesnt_return() > 0 || some_condition();
5644       else
5645          NoreturnOnLhsMakesOrUnreachable = true;
5646 
5647       // [[p]]
5648     }
5649   )";
5650   runDataflow(
5651       Code,
5652       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5653          ASTContext &ASTCtx) {
5654         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5655         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5656         auto &A = Env.arena();
5657 
5658         // Check that [[p]] is reachable with a non-false flow condition.
5659         EXPECT_FALSE(Env.flowConditionImplies(A.makeLiteral(false)));
5660 
5661         auto &B1 = getValueForDecl<BoolValue>(ASTCtx, Env, "b1").formula();
5662         EXPECT_TRUE(Env.flowConditionImplies(A.makeNot(B1)));
5663 
5664         auto &NoreturnOnRhsOfAnd =
5665             getValueForDecl<BoolValue>(ASTCtx, Env, "NoreturnOnRhsOfAnd").formula();
5666         EXPECT_TRUE(Env.flowConditionImplies(A.makeNot(NoreturnOnRhsOfAnd)));
5667 
5668         auto &B2 = getValueForDecl<BoolValue>(ASTCtx, Env, "b2").formula();
5669         EXPECT_TRUE(Env.flowConditionImplies(B2));
5670 
5671         auto &NoreturnOnRhsOfOr =
5672             getValueForDecl<BoolValue>(ASTCtx, Env, "NoreturnOnRhsOfOr")
5673                 .formula();
5674         EXPECT_TRUE(Env.flowConditionImplies(NoreturnOnRhsOfOr));
5675 
5676         auto &NoreturnOnLhsMakesAndUnreachable = getValueForDecl<BoolValue>(
5677             ASTCtx, Env, "NoreturnOnLhsMakesAndUnreachable").formula();
5678         EXPECT_TRUE(Env.flowConditionImplies(NoreturnOnLhsMakesAndUnreachable));
5679 
5680         auto &NoreturnOnLhsMakesOrUnreachable = getValueForDecl<BoolValue>(
5681             ASTCtx, Env, "NoreturnOnLhsMakesOrUnreachable").formula();
5682         EXPECT_TRUE(Env.flowConditionImplies(NoreturnOnLhsMakesOrUnreachable));
5683       });
5684 }
5685 
5686 TEST(TransferTest, NewExpressions) {
5687   std::string Code = R"(
5688     void target() {
5689       int *p = new int(42);
5690       // [[after_new]]
5691     }
5692   )";
5693   runDataflow(
5694       Code,
5695       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5696          ASTContext &ASTCtx) {
5697         const Environment &Env =
5698             getEnvironmentAtAnnotation(Results, "after_new");
5699 
5700         auto &P = getValueForDecl<PointerValue>(ASTCtx, Env, "p");
5701 
5702         EXPECT_THAT(Env.getValue(P.getPointeeLoc()), NotNull());
5703       });
5704 }
5705 
5706 TEST(TransferTest, NewExpressions_Structs) {
5707   std::string Code = R"(
5708     struct Inner {
5709       int InnerField;
5710     };
5711 
5712     struct Outer {
5713       Inner OuterField;
5714     };
5715 
5716     void target() {
5717       Outer *p = new Outer;
5718       // Access the fields to make sure the analysis actually generates children
5719       // for them in the `RecordStorageLocation` and `RecordValue`.
5720       p->OuterField.InnerField;
5721       // [[after_new]]
5722     }
5723   )";
5724   runDataflow(
5725       Code,
5726       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5727          ASTContext &ASTCtx) {
5728         const Environment &Env =
5729             getEnvironmentAtAnnotation(Results, "after_new");
5730 
5731         const ValueDecl *OuterField = findValueDecl(ASTCtx, "OuterField");
5732         const ValueDecl *InnerField = findValueDecl(ASTCtx, "InnerField");
5733 
5734         auto &P = getValueForDecl<PointerValue>(ASTCtx, Env, "p");
5735 
5736         auto &OuterLoc = cast<RecordStorageLocation>(P.getPointeeLoc());
5737         auto &OuterFieldLoc =
5738             *cast<RecordStorageLocation>(OuterLoc.getChild(*OuterField));
5739         auto &InnerFieldLoc = *OuterFieldLoc.getChild(*InnerField);
5740 
5741         // Values for the struct and all fields exist after the new.
5742         EXPECT_THAT(Env.getValue(OuterLoc), NotNull());
5743         EXPECT_THAT(Env.getValue(OuterFieldLoc), NotNull());
5744         EXPECT_THAT(Env.getValue(InnerFieldLoc), NotNull());
5745       });
5746 }
5747 
5748 TEST(TransferTest, FunctionToPointerDecayHasValue) {
5749   std::string Code = R"(
5750     struct A { static void static_member_func(); };
5751     void target() {
5752       // To check that we're treating function-to-pointer decay correctly,
5753       // create two pointers, then verify they refer to the same storage
5754       // location.
5755       // We need to do the test this way because even if an initializer (in this
5756       // case, the function-to-pointer decay) does not create a value, we still
5757       // create a value for the variable.
5758       void (*non_member_p1)() = target;
5759       void (*non_member_p2)() = target;
5760 
5761       // Do the same thing but for a static member function.
5762       void (*member_p1)() = A::static_member_func;
5763       void (*member_p2)() = A::static_member_func;
5764       // [[p]]
5765     }
5766   )";
5767   runDataflow(
5768       Code,
5769       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5770          ASTContext &ASTCtx) {
5771         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5772 
5773         auto &NonMemberP1 =
5774             getValueForDecl<PointerValue>(ASTCtx, Env, "non_member_p1");
5775         auto &NonMemberP2 =
5776             getValueForDecl<PointerValue>(ASTCtx, Env, "non_member_p2");
5777         EXPECT_EQ(&NonMemberP1.getPointeeLoc(), &NonMemberP2.getPointeeLoc());
5778 
5779         auto &MemberP1 =
5780             getValueForDecl<PointerValue>(ASTCtx, Env, "member_p1");
5781         auto &MemberP2 =
5782             getValueForDecl<PointerValue>(ASTCtx, Env, "member_p2");
5783         EXPECT_EQ(&MemberP1.getPointeeLoc(), &MemberP2.getPointeeLoc());
5784       });
5785 }
5786 
5787 // Check that a builtin function is not associated with a value. (It's only
5788 // possible to call builtin functions directly, not take their address.)
5789 TEST(TransferTest, BuiltinFunctionModeled) {
5790   std::string Code = R"(
5791     void target() {
5792       __builtin_expect(0, 0);
5793       // [[p]]
5794     }
5795   )";
5796   runDataflow(
5797       Code,
5798       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5799          ASTContext &ASTCtx) {
5800         using ast_matchers::selectFirst;
5801         using ast_matchers::match;
5802         using ast_matchers::traverse;
5803         using ast_matchers::implicitCastExpr;
5804         using ast_matchers::hasCastKind;
5805 
5806         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5807 
5808         auto *ImplicitCast = selectFirst<ImplicitCastExpr>(
5809             "implicit_cast",
5810             match(traverse(TK_AsIs,
5811                            implicitCastExpr(hasCastKind(CK_BuiltinFnToFnPtr))
5812                                .bind("implicit_cast")),
5813                   ASTCtx));
5814 
5815         ASSERT_THAT(ImplicitCast, NotNull());
5816         EXPECT_THAT(Env.getValue(*ImplicitCast), IsNull());
5817       });
5818 }
5819 
5820 // Check that a callee of a member operator call is modeled as a `PointerValue`.
5821 // Member operator calls are unusual in that their callee is a pointer that
5822 // stems from a `FunctionToPointerDecay`. In calls to non-operator non-static
5823 // member functions, the callee is a `MemberExpr` (which does not have pointer
5824 // type).
5825 // We want to make sure that we produce a pointer value for the callee in this
5826 // specific scenario and that its storage location is durable (for convergence).
5827 TEST(TransferTest, MemberOperatorCallModelsPointerForCallee) {
5828   std::string Code = R"(
5829     struct S {
5830       bool operator!=(S s);
5831     };
5832     void target() {
5833       S s;
5834       (void)(s != s);
5835       (void)(s != s);
5836       // [[p]]
5837     }
5838   )";
5839   runDataflow(
5840       Code,
5841       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5842          ASTContext &ASTCtx) {
5843         using ast_matchers::selectFirst;
5844         using ast_matchers::match;
5845         using ast_matchers::traverse;
5846         using ast_matchers::cxxOperatorCallExpr;
5847 
5848         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5849 
5850         auto Matches = match(
5851             traverse(TK_AsIs, cxxOperatorCallExpr().bind("call")), ASTCtx);
5852 
5853         ASSERT_EQ(Matches.size(), 2UL);
5854 
5855         auto *Call1 = Matches[0].getNodeAs<CXXOperatorCallExpr>("call");
5856         auto *Call2 = Matches[1].getNodeAs<CXXOperatorCallExpr>("call");
5857 
5858         ASSERT_THAT(Call1, NotNull());
5859         ASSERT_THAT(Call2, NotNull());
5860 
5861         EXPECT_EQ(cast<ImplicitCastExpr>(Call1->getCallee())->getCastKind(),
5862                   CK_FunctionToPointerDecay);
5863         EXPECT_EQ(cast<ImplicitCastExpr>(Call2->getCallee())->getCastKind(),
5864                   CK_FunctionToPointerDecay);
5865 
5866         auto *Ptr1 = cast<PointerValue>(Env.getValue(*Call1->getCallee()));
5867         auto *Ptr2 = cast<PointerValue>(Env.getValue(*Call2->getCallee()));
5868 
5869         ASSERT_EQ(&Ptr1->getPointeeLoc(), &Ptr2->getPointeeLoc());
5870       });
5871 }
5872 
5873 // Check that fields of anonymous records are modeled.
5874 TEST(TransferTest, AnonymousStruct) {
5875   std::string Code = R"(
5876     struct S {
5877       struct {
5878         bool b;
5879       };
5880     };
5881     void target() {
5882       S s;
5883       s.b = true;
5884       // [[p]]
5885     }
5886   )";
5887   runDataflow(
5888       Code,
5889       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5890          ASTContext &ASTCtx) {
5891         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5892         const ValueDecl *SDecl = findValueDecl(ASTCtx, "s");
5893         const ValueDecl *BDecl = findValueDecl(ASTCtx, "b");
5894         const IndirectFieldDecl *IndirectField =
5895             findIndirectFieldDecl(ASTCtx, "b");
5896 
5897         auto *S = cast<RecordStorageLocation>(Env.getStorageLocation(*SDecl));
5898         auto &AnonStruct = *cast<RecordStorageLocation>(
5899             S->getChild(*cast<ValueDecl>(IndirectField->chain().front())));
5900 
5901         auto *B = cast<BoolValue>(getFieldValue(&AnonStruct, *BDecl, Env));
5902         ASSERT_TRUE(Env.flowConditionImplies(B->formula()));
5903       });
5904 }
5905 
5906 TEST(TransferTest, AnonymousStructWithInitializer) {
5907   std::string Code = R"(
5908     struct target {
5909       target() {
5910         (void)0;
5911         // [[p]]
5912       }
5913       struct {
5914         bool b = true;
5915       };
5916     };
5917   )";
5918   runDataflow(
5919       Code,
5920       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5921          ASTContext &ASTCtx) {
5922         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5923         const ValueDecl *BDecl = findValueDecl(ASTCtx, "b");
5924         const IndirectFieldDecl *IndirectField =
5925             findIndirectFieldDecl(ASTCtx, "b");
5926 
5927         auto *ThisLoc =
5928             cast<RecordStorageLocation>(Env.getThisPointeeStorageLocation());
5929         auto &AnonStruct = *cast<RecordStorageLocation>(ThisLoc->getChild(
5930             *cast<ValueDecl>(IndirectField->chain().front())));
5931 
5932         auto *B = cast<BoolValue>(getFieldValue(&AnonStruct, *BDecl, Env));
5933         ASSERT_TRUE(Env.flowConditionImplies(B->formula()));
5934       });
5935 }
5936 
5937 TEST(TransferTest, AnonymousStructWithReferenceField) {
5938   std::string Code = R"(
5939     int global_i = 0;
5940     struct target {
5941       target() {
5942         (void)0;
5943         // [[p]]
5944       }
5945       struct {
5946         int &i = global_i;
5947       };
5948     };
5949   )";
5950   runDataflow(
5951       Code,
5952       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5953          ASTContext &ASTCtx) {
5954         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5955         const ValueDecl *GlobalIDecl = findValueDecl(ASTCtx, "global_i");
5956         const ValueDecl *IDecl = findValueDecl(ASTCtx, "i");
5957         const IndirectFieldDecl *IndirectField =
5958             findIndirectFieldDecl(ASTCtx, "i");
5959 
5960         auto *ThisLoc =
5961             cast<RecordStorageLocation>(Env.getThisPointeeStorageLocation());
5962         auto &AnonStruct = *cast<RecordStorageLocation>(ThisLoc->getChild(
5963             *cast<ValueDecl>(IndirectField->chain().front())));
5964 
5965         ASSERT_EQ(AnonStruct.getChild(*IDecl),
5966                   Env.getStorageLocation(*GlobalIDecl));
5967       });
5968 }
5969 
5970 TEST(TransferTest, EvaluateBlockWithUnreachablePreds) {
5971   // This is a crash repro.
5972   // `false` block may not have been processed when we try to evaluate the `||`
5973   // after visiting `true`, because it is not necessary (and therefore the edge
5974   // is marked unreachable). Trying to get the analysis state via
5975   // `getEnvironment` for the subexpression still should not crash.
5976   std::string Code = R"(
5977     int target(int i) {
5978       if ((i < 0 && true) || false) {
5979         return 0;
5980       }
5981       return 0;
5982     }
5983   )";
5984   runDataflow(
5985       Code,
5986       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5987          ASTContext &ASTCtx) {});
5988 }
5989 
5990 } // namespace
5991