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