xref: /llvm-project/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp (revision dfe80a73223edff5c53f8be7925d302883cb40bc)
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/NoopAnalysis.h"
16 #include "clang/Analysis/FlowSensitive/RecordOps.h"
17 #include "clang/Analysis/FlowSensitive/StorageLocation.h"
18 #include "clang/Analysis/FlowSensitive/Value.h"
19 #include "clang/Basic/LangStandard.h"
20 #include "clang/Testing/TestAST.h"
21 #include "llvm/ADT/SmallVector.h"
22 #include "llvm/ADT/StringRef.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 clang {
31 namespace dataflow {
32 namespace {
33 AST_MATCHER(FunctionDecl, isTemplated) { return Node.isTemplated(); }
34 } // namespace
35 } // namespace dataflow
36 } // namespace clang
37 
38 namespace {
39 
40 using namespace clang;
41 using namespace dataflow;
42 using namespace test;
43 using ::testing::Eq;
44 using ::testing::IsNull;
45 using ::testing::Ne;
46 using ::testing::NotNull;
47 using ::testing::UnorderedElementsAre;
48 
49 // Declares a minimal coroutine library.
50 constexpr llvm::StringRef CoroutineLibrary = R"cc(
51 struct promise;
52 struct task;
53 
54 namespace std {
55 template <class, class...>
56 struct coroutine_traits {};
57 template <>
58 struct coroutine_traits<task> {
59     using promise_type = promise;
60 };
61 
62 template <class Promise = void>
63 struct coroutine_handle {
64     static constexpr coroutine_handle from_address(void *addr) { return {}; }
65 };
66 }  // namespace std
67 
68 struct awaitable {
69     bool await_ready() const noexcept;
70     void await_suspend(std::coroutine_handle<promise>) const noexcept;
71     void await_resume() const noexcept;
72 };
73 struct task {};
74 struct promise {
75     task get_return_object();
76     awaitable initial_suspend();
77     awaitable final_suspend() noexcept;
78     void unhandled_exception();
79     void return_void();
80 };
81 )cc";
82 
83 void runDataflow(
84     llvm::StringRef Code,
85     std::function<
86         void(const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &,
87              ASTContext &)>
88         VerifyResults,
89     DataflowAnalysisOptions Options,
90     LangStandard::Kind Std = LangStandard::lang_cxx17,
91     llvm::StringRef TargetFun = "target") {
92   ASSERT_THAT_ERROR(checkDataflowWithNoopAnalysis(Code, VerifyResults, Options,
93                                                   Std, TargetFun),
94                     llvm::Succeeded());
95 }
96 
97 void runDataflow(
98     llvm::StringRef Code,
99     std::function<
100         void(const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &,
101              ASTContext &)>
102         VerifyResults,
103     LangStandard::Kind Std = LangStandard::lang_cxx17,
104     bool ApplyBuiltinTransfer = true, llvm::StringRef TargetFun = "target") {
105   runDataflow(Code, std::move(VerifyResults),
106               {ApplyBuiltinTransfer ? BuiltinOptions{}
107                                     : std::optional<BuiltinOptions>()},
108               Std, TargetFun);
109 }
110 
111 void runDataflowOnLambda(
112     llvm::StringRef Code,
113     std::function<
114         void(const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &,
115              ASTContext &)>
116         VerifyResults,
117     DataflowAnalysisOptions Options,
118     LangStandard::Kind Std = LangStandard::lang_cxx17) {
119   ASSERT_THAT_ERROR(
120       checkDataflowWithNoopAnalysis(
121           Code,
122           ast_matchers::hasDeclContext(
123               ast_matchers::cxxRecordDecl(ast_matchers::isLambda())),
124           VerifyResults, Options, Std),
125       llvm::Succeeded());
126 }
127 
128 void runDataflowOnLambda(
129     llvm::StringRef Code,
130     std::function<
131         void(const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &,
132              ASTContext &)>
133         VerifyResults,
134     LangStandard::Kind Std = LangStandard::lang_cxx17,
135     bool ApplyBuiltinTransfer = true) {
136   runDataflowOnLambda(Code, std::move(VerifyResults),
137                       {ApplyBuiltinTransfer ? BuiltinOptions{}
138                                             : std::optional<BuiltinOptions>()},
139                       Std);
140 }
141 
142 const Formula &getFormula(const ValueDecl &D, const Environment &Env) {
143   return cast<BoolValue>(Env.getValue(D))->formula();
144 }
145 
146 TEST(TransferTest, CNotSupported) {
147   TestInputs Inputs("void target() {}");
148   Inputs.Language = TestLanguage::Lang_C89;
149   clang::TestAST AST(Inputs);
150   const auto *Target =
151       cast<FunctionDecl>(test::findValueDecl(AST.context(), "target"));
152   ASSERT_THAT_ERROR(AdornedCFG::build(*Target).takeError(),
153                     llvm::FailedWithMessage("Can only analyze C++"));
154 }
155 
156 TEST(TransferTest, ObjectiveCNotSupported) {
157   TestInputs Inputs("void target() {}");
158   Inputs.Language = TestLanguage::Lang_OBJC;
159   clang::TestAST AST(Inputs);
160   const auto *Target =
161       cast<FunctionDecl>(test::findValueDecl(AST.context(), "target"));
162   ASSERT_THAT_ERROR(AdornedCFG::build(*Target).takeError(),
163                     llvm::FailedWithMessage("Can only analyze C++"));
164 }
165 
166 TEST(TransferTest, ObjectiveCXXNotSupported) {
167   TestInputs Inputs("void target() {}");
168   Inputs.Language = TestLanguage::Lang_OBJCXX;
169   clang::TestAST AST(Inputs);
170   const auto *Target =
171       cast<FunctionDecl>(test::findValueDecl(AST.context(), "target"));
172   ASSERT_THAT_ERROR(AdornedCFG::build(*Target).takeError(),
173                     llvm::FailedWithMessage("Can only analyze C++"));
174 }
175 
176 TEST(TransferTest, IntVarDeclNotTrackedWhenTransferDisabled) {
177   std::string Code = R"(
178     void target() {
179       int Foo;
180       // [[p]]
181     }
182   )";
183   runDataflow(
184       Code,
185       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
186          ASTContext &ASTCtx) {
187         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
188         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
189 
190         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
191         ASSERT_THAT(FooDecl, NotNull());
192 
193         EXPECT_EQ(Env.getStorageLocation(*FooDecl), nullptr);
194       },
195       LangStandard::lang_cxx17,
196       /*ApplyBuiltinTransfer=*/false);
197 }
198 
199 TEST(TransferTest, BoolVarDecl) {
200   std::string Code = R"(
201     void target() {
202       bool Foo;
203       // [[p]]
204     }
205   )";
206   runDataflow(
207       Code,
208       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
209          ASTContext &ASTCtx) {
210         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
211         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
212 
213         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
214         ASSERT_THAT(FooDecl, NotNull());
215 
216         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
217         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
218 
219         const Value *FooVal = Env.getValue(*FooLoc);
220         EXPECT_TRUE(isa_and_nonnull<BoolValue>(FooVal));
221       });
222 }
223 
224 TEST(TransferTest, IntVarDecl) {
225   std::string Code = R"(
226     void target() {
227       int Foo;
228       // [[p]]
229     }
230   )";
231   runDataflow(
232       Code,
233       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
234          ASTContext &ASTCtx) {
235         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
236         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
237 
238         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
239         ASSERT_THAT(FooDecl, NotNull());
240 
241         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
242         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
243 
244         const Value *FooVal = Env.getValue(*FooLoc);
245         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
246       });
247 }
248 
249 TEST(TransferTest, StructIncomplete) {
250   std::string Code = R"(
251     struct A;
252 
253     void target() {
254       A* Foo;
255       // [[p]]
256     }
257   )";
258   runDataflow(
259       Code,
260       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
261          ASTContext &ASTCtx) {
262         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
263         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
264 
265         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
266         ASSERT_THAT(FooDecl, NotNull());
267         auto *FooValue = dyn_cast_or_null<PointerValue>(Env.getValue(*FooDecl));
268         ASSERT_THAT(FooValue, NotNull());
269 
270         EXPECT_TRUE(isa<RecordStorageLocation>(FooValue->getPointeeLoc()));
271       });
272 }
273 
274 // As a memory optimization, we prevent modeling fields nested below a certain
275 // level (currently, depth 3). This test verifies this lack of modeling. We also
276 // include a regression test for the case that the unmodeled field is a
277 // reference to a struct; previously, we crashed when accessing such a field.
278 TEST(TransferTest, StructFieldUnmodeled) {
279   std::string Code = R"(
280     struct S { int X; };
281     S GlobalS;
282     struct A { S &Unmodeled = GlobalS; };
283     struct B { A F3; };
284     struct C { B F2; };
285     struct D { C F1; };
286 
287     void target() {
288       D Bar;
289       A &Foo = Bar.F1.F2.F3;
290       int Zab = Foo.Unmodeled.X;
291       // [[p]]
292     }
293   )";
294   runDataflow(
295       Code,
296       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
297          ASTContext &ASTCtx) {
298         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
299         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
300 
301         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
302         ASSERT_THAT(FooDecl, NotNull());
303         QualType FooReferentType = FooDecl->getType()->getPointeeType();
304         ASSERT_TRUE(FooReferentType->isStructureType());
305         auto FooFields = FooReferentType->getAsRecordDecl()->fields();
306 
307         FieldDecl *UnmodeledDecl = nullptr;
308         for (FieldDecl *Field : FooFields) {
309           if (Field->getNameAsString() == "Unmodeled") {
310             UnmodeledDecl = Field;
311           } else {
312             FAIL() << "Unexpected field: " << Field->getNameAsString();
313           }
314         }
315         ASSERT_THAT(UnmodeledDecl, NotNull());
316 
317         const auto *FooLoc =
318             cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
319         const auto &UnmodeledLoc =
320             *cast<RecordStorageLocation>(FooLoc->getChild(*UnmodeledDecl));
321         StorageLocation &UnmodeledXLoc = getFieldLoc(UnmodeledLoc, "X", ASTCtx);
322         EXPECT_EQ(Env.getValue(UnmodeledXLoc), nullptr);
323 
324         const ValueDecl *ZabDecl = findValueDecl(ASTCtx, "Zab");
325         ASSERT_THAT(ZabDecl, NotNull());
326         EXPECT_THAT(Env.getValue(*ZabDecl), NotNull());
327       });
328 }
329 
330 TEST(TransferTest, StructVarDecl) {
331   std::string Code = R"(
332     struct A {
333       int Bar;
334     };
335 
336     void target() {
337       A Foo;
338       (void)Foo.Bar;
339       // [[p]]
340     }
341   )";
342   runDataflow(
343       Code,
344       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
345          ASTContext &ASTCtx) {
346         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
347         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
348 
349         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
350         ASSERT_THAT(FooDecl, NotNull());
351 
352         ASSERT_TRUE(FooDecl->getType()->isStructureType());
353         auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields();
354 
355         FieldDecl *BarDecl = nullptr;
356         for (FieldDecl *Field : FooFields) {
357           if (Field->getNameAsString() == "Bar") {
358             BarDecl = Field;
359           } else {
360             FAIL() << "Unexpected field: " << Field->getNameAsString();
361           }
362         }
363         ASSERT_THAT(BarDecl, NotNull());
364 
365         const auto *FooLoc =
366             cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
367         EXPECT_TRUE(isa<IntegerValue>(getFieldValue(FooLoc, *BarDecl, Env)));
368       });
369 }
370 
371 TEST(TransferTest, StructVarDeclWithInit) {
372   std::string Code = R"(
373     struct A {
374       int Bar;
375     };
376 
377     A Gen();
378 
379     void target() {
380       A Foo = Gen();
381       (void)Foo.Bar;
382       // [[p]]
383     }
384   )";
385   runDataflow(
386       Code,
387       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
388          ASTContext &ASTCtx) {
389         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
390         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
391 
392         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
393         ASSERT_THAT(FooDecl, NotNull());
394 
395         ASSERT_TRUE(FooDecl->getType()->isStructureType());
396         auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields();
397 
398         FieldDecl *BarDecl = nullptr;
399         for (FieldDecl *Field : FooFields) {
400           if (Field->getNameAsString() == "Bar") {
401             BarDecl = Field;
402           } else {
403             FAIL() << "Unexpected field: " << Field->getNameAsString();
404           }
405         }
406         ASSERT_THAT(BarDecl, NotNull());
407 
408         const auto *FooLoc =
409             cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
410         EXPECT_TRUE(isa<IntegerValue>(getFieldValue(FooLoc, *BarDecl, Env)));
411       });
412 }
413 
414 TEST(TransferTest, StructArrayVarDecl) {
415   std::string Code = R"(
416     struct A {};
417 
418     void target() {
419       A Array[2];
420       // [[p]]
421     }
422   )";
423   runDataflow(
424       Code,
425       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
426          ASTContext &ASTCtx) {
427         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
428 
429         const ValueDecl *ArrayDecl = findValueDecl(ASTCtx, "Array");
430 
431         // We currently don't create values for arrays.
432         ASSERT_THAT(Env.getValue(*ArrayDecl), IsNull());
433       });
434 }
435 
436 TEST(TransferTest, ClassVarDecl) {
437   std::string Code = R"(
438     class A {
439      public:
440       int Bar;
441     };
442 
443     void target() {
444       A Foo;
445       (void)Foo.Bar;
446       // [[p]]
447     }
448   )";
449   runDataflow(
450       Code,
451       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
452          ASTContext &ASTCtx) {
453         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
454         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
455 
456         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
457         ASSERT_THAT(FooDecl, NotNull());
458 
459         ASSERT_TRUE(FooDecl->getType()->isClassType());
460         auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields();
461 
462         FieldDecl *BarDecl = nullptr;
463         for (FieldDecl *Field : FooFields) {
464           if (Field->getNameAsString() == "Bar") {
465             BarDecl = Field;
466           } else {
467             FAIL() << "Unexpected field: " << Field->getNameAsString();
468           }
469         }
470         ASSERT_THAT(BarDecl, NotNull());
471 
472         const auto *FooLoc =
473             cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
474         EXPECT_TRUE(isa<IntegerValue>(getFieldValue(FooLoc, *BarDecl, Env)));
475       });
476 }
477 
478 TEST(TransferTest, ReferenceVarDecl) {
479   std::string Code = R"(
480     struct A {};
481 
482     A &getA();
483 
484     void target() {
485       A &Foo = getA();
486       // [[p]]
487     }
488   )";
489   runDataflow(
490       Code,
491       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
492          ASTContext &ASTCtx) {
493         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
494         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
495 
496         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
497         ASSERT_THAT(FooDecl, NotNull());
498 
499         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
500         ASSERT_TRUE(isa_and_nonnull<RecordStorageLocation>(FooLoc));
501       });
502 }
503 
504 TEST(TransferTest, SelfReferentialReferenceVarDecl) {
505   std::string Code = R"(
506     struct A;
507 
508     struct B {};
509 
510     struct C {
511       A &FooRef;
512       A *FooPtr;
513       B &BazRef;
514       B *BazPtr;
515     };
516 
517     struct A {
518       C &Bar;
519     };
520 
521     A &getA();
522 
523     void target() {
524       A &Foo = getA();
525       (void)Foo.Bar.FooRef;
526       (void)Foo.Bar.FooPtr;
527       (void)Foo.Bar.BazRef;
528       (void)Foo.Bar.BazPtr;
529       // [[p]]
530     }
531   )";
532   runDataflow(Code, [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>>
533                            &Results,
534                        ASTContext &ASTCtx) {
535     ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
536     const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
537 
538     const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
539     ASSERT_THAT(FooDecl, NotNull());
540 
541     ASSERT_TRUE(FooDecl->getType()->isReferenceType());
542     ASSERT_TRUE(FooDecl->getType().getNonReferenceType()->isStructureType());
543     const auto FooFields =
544         FooDecl->getType().getNonReferenceType()->getAsRecordDecl()->fields();
545 
546     FieldDecl *BarDecl = nullptr;
547     for (FieldDecl *Field : FooFields) {
548       if (Field->getNameAsString() == "Bar") {
549         BarDecl = Field;
550       } else {
551         FAIL() << "Unexpected field: " << Field->getNameAsString();
552       }
553     }
554     ASSERT_THAT(BarDecl, NotNull());
555 
556     ASSERT_TRUE(BarDecl->getType()->isReferenceType());
557     ASSERT_TRUE(BarDecl->getType().getNonReferenceType()->isStructureType());
558     const auto BarFields =
559         BarDecl->getType().getNonReferenceType()->getAsRecordDecl()->fields();
560 
561     FieldDecl *FooRefDecl = nullptr;
562     FieldDecl *FooPtrDecl = nullptr;
563     FieldDecl *BazRefDecl = nullptr;
564     FieldDecl *BazPtrDecl = nullptr;
565     for (FieldDecl *Field : BarFields) {
566       if (Field->getNameAsString() == "FooRef") {
567         FooRefDecl = Field;
568       } else if (Field->getNameAsString() == "FooPtr") {
569         FooPtrDecl = Field;
570       } else if (Field->getNameAsString() == "BazRef") {
571         BazRefDecl = Field;
572       } else if (Field->getNameAsString() == "BazPtr") {
573         BazPtrDecl = Field;
574       } else {
575         FAIL() << "Unexpected field: " << Field->getNameAsString();
576       }
577     }
578     ASSERT_THAT(FooRefDecl, NotNull());
579     ASSERT_THAT(FooPtrDecl, NotNull());
580     ASSERT_THAT(BazRefDecl, NotNull());
581     ASSERT_THAT(BazPtrDecl, NotNull());
582 
583     const auto &FooLoc =
584         *cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
585 
586     const auto &BarLoc =
587         *cast<RecordStorageLocation>(FooLoc.getChild(*BarDecl));
588 
589     const auto &FooReferentLoc =
590         *cast<RecordStorageLocation>(BarLoc.getChild(*FooRefDecl));
591     EXPECT_EQ(Env.getValue(*cast<RecordStorageLocation>(
592                                 FooReferentLoc.getChild(*BarDecl))
593                                 ->getChild(*FooPtrDecl)),
594               nullptr);
595 
596     const auto &FooPtrVal =
597         *cast<PointerValue>(getFieldValue(&BarLoc, *FooPtrDecl, Env));
598     const auto &FooPtrPointeeLoc =
599         cast<RecordStorageLocation>(FooPtrVal.getPointeeLoc());
600     EXPECT_EQ(Env.getValue(*cast<RecordStorageLocation>(
601                                 FooPtrPointeeLoc.getChild(*BarDecl))
602                                 ->getChild(*FooPtrDecl)),
603               nullptr);
604 
605     EXPECT_TRUE(isa<PointerValue>(getFieldValue(&BarLoc, *BazPtrDecl, Env)));
606   });
607 }
608 
609 TEST(TransferTest, PointerVarDecl) {
610   std::string Code = R"(
611     struct A {};
612 
613     A *getA();
614 
615     void target() {
616       A *Foo = getA();
617       // [[p]]
618     }
619   )";
620   runDataflow(
621       Code,
622       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
623          ASTContext &ASTCtx) {
624         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
625         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
626 
627         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
628         ASSERT_THAT(FooDecl, NotNull());
629 
630         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
631         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
632 
633         const PointerValue *FooVal = cast<PointerValue>(Env.getValue(*FooLoc));
634         const StorageLocation &FooPointeeLoc = FooVal->getPointeeLoc();
635         EXPECT_TRUE(isa<RecordStorageLocation>(&FooPointeeLoc));
636       });
637 }
638 
639 TEST(TransferTest, SelfReferentialPointerVarDecl) {
640   std::string Code = R"(
641     struct A;
642 
643     struct B {};
644 
645     struct C {
646       A &FooRef;
647       A *FooPtr;
648       B &BazRef;
649       B *BazPtr;
650     };
651 
652     struct A {
653       C *Bar;
654     };
655 
656     A *getA();
657 
658     void target() {
659       A *Foo = getA();
660       (void)Foo->Bar->FooRef;
661       (void)Foo->Bar->FooPtr;
662       (void)Foo->Bar->BazRef;
663       (void)Foo->Bar->BazPtr;
664       // [[p]]
665     }
666   )";
667   runDataflow(
668       Code,
669       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
670          ASTContext &ASTCtx) {
671         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
672         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
673 
674         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
675         ASSERT_THAT(FooDecl, NotNull());
676 
677         ASSERT_TRUE(FooDecl->getType()->isPointerType());
678         ASSERT_TRUE(FooDecl->getType()
679                         ->getAs<PointerType>()
680                         ->getPointeeType()
681                         ->isStructureType());
682         const auto FooFields = FooDecl->getType()
683                                    ->getAs<PointerType>()
684                                    ->getPointeeType()
685                                    ->getAsRecordDecl()
686                                    ->fields();
687 
688         FieldDecl *BarDecl = nullptr;
689         for (FieldDecl *Field : FooFields) {
690           if (Field->getNameAsString() == "Bar") {
691             BarDecl = Field;
692           } else {
693             FAIL() << "Unexpected field: " << Field->getNameAsString();
694           }
695         }
696         ASSERT_THAT(BarDecl, NotNull());
697 
698         ASSERT_TRUE(BarDecl->getType()->isPointerType());
699         ASSERT_TRUE(BarDecl->getType()
700                         ->getAs<PointerType>()
701                         ->getPointeeType()
702                         ->isStructureType());
703         const auto BarFields = BarDecl->getType()
704                                    ->getAs<PointerType>()
705                                    ->getPointeeType()
706                                    ->getAsRecordDecl()
707                                    ->fields();
708 
709         FieldDecl *FooRefDecl = nullptr;
710         FieldDecl *FooPtrDecl = nullptr;
711         FieldDecl *BazRefDecl = nullptr;
712         FieldDecl *BazPtrDecl = nullptr;
713         for (FieldDecl *Field : BarFields) {
714           if (Field->getNameAsString() == "FooRef") {
715             FooRefDecl = Field;
716           } else if (Field->getNameAsString() == "FooPtr") {
717             FooPtrDecl = Field;
718           } else if (Field->getNameAsString() == "BazRef") {
719             BazRefDecl = Field;
720           } else if (Field->getNameAsString() == "BazPtr") {
721             BazPtrDecl = Field;
722           } else {
723             FAIL() << "Unexpected field: " << Field->getNameAsString();
724           }
725         }
726         ASSERT_THAT(FooRefDecl, NotNull());
727         ASSERT_THAT(FooPtrDecl, NotNull());
728         ASSERT_THAT(BazRefDecl, NotNull());
729         ASSERT_THAT(BazPtrDecl, NotNull());
730 
731         const auto &FooLoc =
732             *cast<ScalarStorageLocation>(Env.getStorageLocation(*FooDecl));
733         const auto &FooVal = *cast<PointerValue>(Env.getValue(FooLoc));
734         const auto &FooPointeeLoc =
735             cast<RecordStorageLocation>(FooVal.getPointeeLoc());
736 
737         const auto &BarVal =
738             *cast<PointerValue>(getFieldValue(&FooPointeeLoc, *BarDecl, Env));
739         const auto &BarPointeeLoc =
740             cast<RecordStorageLocation>(BarVal.getPointeeLoc());
741 
742         const auto &FooPtrVal = *cast<PointerValue>(
743             getFieldValue(&BarPointeeLoc, *FooPtrDecl, Env));
744         const auto &FooPtrPointeeLoc =
745             cast<RecordStorageLocation>(FooPtrVal.getPointeeLoc());
746         EXPECT_EQ(Env.getValue(*FooPtrPointeeLoc.getChild(*BarDecl)), nullptr);
747 
748         EXPECT_TRUE(
749             isa<PointerValue>(getFieldValue(&BarPointeeLoc, *BazPtrDecl, Env)));
750       });
751 }
752 
753 TEST(TransferTest, DirectlySelfReferentialReference) {
754   std::string Code = R"(
755     struct target {
756       target() {
757         (void)0;
758         // [[p]]
759       }
760       target &self = *this;
761     };
762   )";
763   runDataflow(
764       Code,
765       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
766          ASTContext &ASTCtx) {
767         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
768         const ValueDecl *SelfDecl = findValueDecl(ASTCtx, "self");
769 
770         auto *ThisLoc = Env.getThisPointeeStorageLocation();
771         ASSERT_EQ(ThisLoc->getChild(*SelfDecl), ThisLoc);
772       });
773 }
774 
775 TEST(TransferTest, MultipleVarsDecl) {
776   std::string Code = R"(
777     void target() {
778       int Foo, Bar;
779       (void)0;
780       // [[p]]
781     }
782   )";
783   runDataflow(
784       Code,
785       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
786          ASTContext &ASTCtx) {
787         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
788         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
789 
790         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
791         ASSERT_THAT(FooDecl, NotNull());
792 
793         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
794         ASSERT_THAT(BarDecl, NotNull());
795 
796         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
797         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
798 
799         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
800         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
801 
802         const Value *FooVal = Env.getValue(*FooLoc);
803         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
804 
805         const Value *BarVal = Env.getValue(*BarLoc);
806         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
807       });
808 }
809 
810 TEST(TransferTest, JoinVarDecl) {
811   std::string Code = R"(
812     void target(bool B) {
813       int Foo;
814       // [[p1]]
815       if (B) {
816         int Bar;
817         // [[p2]]
818       } else {
819         int Baz;
820         // [[p3]]
821       }
822       (void)0;
823       // [[p4]]
824     }
825   )";
826   runDataflow(Code, [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>>
827                            &Results,
828                        ASTContext &ASTCtx) {
829     ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2", "p3", "p4"));
830 
831     const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
832     ASSERT_THAT(FooDecl, NotNull());
833 
834     const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
835     ASSERT_THAT(BarDecl, NotNull());
836 
837     const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
838     ASSERT_THAT(BazDecl, NotNull());
839 
840     const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
841 
842     const StorageLocation *FooLoc = Env1.getStorageLocation(*FooDecl);
843     EXPECT_THAT(FooLoc, NotNull());
844     EXPECT_THAT(Env1.getStorageLocation(*BarDecl), IsNull());
845     EXPECT_THAT(Env1.getStorageLocation(*BazDecl), IsNull());
846 
847     const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
848     EXPECT_EQ(Env2.getStorageLocation(*FooDecl), FooLoc);
849     EXPECT_THAT(Env2.getStorageLocation(*BarDecl), NotNull());
850     EXPECT_THAT(Env2.getStorageLocation(*BazDecl), IsNull());
851 
852     const Environment &Env3 = getEnvironmentAtAnnotation(Results, "p3");
853     EXPECT_EQ(Env3.getStorageLocation(*FooDecl), FooLoc);
854     EXPECT_THAT(Env3.getStorageLocation(*BarDecl), IsNull());
855     EXPECT_THAT(Env3.getStorageLocation(*BazDecl), NotNull());
856 
857     const Environment &Env4 = getEnvironmentAtAnnotation(Results, "p4");
858     EXPECT_EQ(Env4.getStorageLocation(*FooDecl), FooLoc);
859     EXPECT_THAT(Env4.getStorageLocation(*BarDecl), IsNull());
860     EXPECT_THAT(Env4.getStorageLocation(*BazDecl), IsNull());
861   });
862 }
863 
864 TEST(TransferTest, BinaryOperatorAssign) {
865   std::string Code = R"(
866     void target() {
867       int Foo;
868       int Bar;
869       (Bar) = (Foo);
870       // [[p]]
871     }
872   )";
873   runDataflow(
874       Code,
875       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
876          ASTContext &ASTCtx) {
877         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
878         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
879 
880         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
881         ASSERT_THAT(FooDecl, NotNull());
882 
883         const Value *FooVal = Env.getValue(*FooDecl);
884         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
885 
886         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
887         ASSERT_THAT(BarDecl, NotNull());
888 
889         EXPECT_EQ(Env.getValue(*BarDecl), FooVal);
890       });
891 }
892 
893 TEST(TransferTest, BinaryOperatorAssignIntegerLiteral) {
894   std::string Code = R"(
895     void target() {
896       int Foo = 1;
897       // [[before]]
898       Foo = 2;
899       // [[after]]
900     }
901   )";
902   runDataflow(
903       Code,
904       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
905          ASTContext &ASTCtx) {
906         const Environment &Before =
907             getEnvironmentAtAnnotation(Results, "before");
908         const Environment &After = getEnvironmentAtAnnotation(Results, "after");
909 
910         const auto &ValBefore =
911             getValueForDecl<IntegerValue>(ASTCtx, Before, "Foo");
912         const auto &ValAfter =
913             getValueForDecl<IntegerValue>(ASTCtx, After, "Foo");
914         EXPECT_NE(&ValBefore, &ValAfter);
915       });
916 }
917 
918 TEST(TransferTest, VarDeclInitAssign) {
919   std::string Code = R"(
920     void target() {
921       int Foo;
922       int Bar = Foo;
923       // [[p]]
924     }
925   )";
926   runDataflow(
927       Code,
928       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
929          ASTContext &ASTCtx) {
930         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
931         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
932 
933         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
934         ASSERT_THAT(FooDecl, NotNull());
935 
936         const Value *FooVal = Env.getValue(*FooDecl);
937         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
938 
939         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
940         ASSERT_THAT(BarDecl, NotNull());
941 
942         EXPECT_EQ(Env.getValue(*BarDecl), FooVal);
943       });
944 }
945 
946 TEST(TransferTest, VarDeclInitAssignChained) {
947   std::string Code = R"(
948     void target() {
949       int Foo;
950       int Bar;
951       int Baz = (Bar = Foo);
952       // [[p]]
953     }
954   )";
955   runDataflow(
956       Code,
957       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
958          ASTContext &ASTCtx) {
959         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
960         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
961 
962         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
963         ASSERT_THAT(FooDecl, NotNull());
964 
965         const Value *FooVal = Env.getValue(*FooDecl);
966         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
967 
968         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
969         ASSERT_THAT(BarDecl, NotNull());
970 
971         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
972         ASSERT_THAT(BazDecl, NotNull());
973 
974         EXPECT_EQ(Env.getValue(*BarDecl), FooVal);
975         EXPECT_EQ(Env.getValue(*BazDecl), FooVal);
976       });
977 }
978 
979 TEST(TransferTest, VarDeclInitAssignPtrDeref) {
980   std::string Code = R"(
981     void target() {
982       int Foo;
983       int *Bar;
984       *(Bar) = Foo;
985       int Baz = *(Bar);
986       // [[p]]
987     }
988   )";
989   runDataflow(
990       Code,
991       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
992          ASTContext &ASTCtx) {
993         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
994         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
995 
996         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
997         ASSERT_THAT(FooDecl, NotNull());
998 
999         const Value *FooVal = Env.getValue(*FooDecl);
1000         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
1001 
1002         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1003         ASSERT_THAT(BarDecl, NotNull());
1004 
1005         const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl));
1006         EXPECT_EQ(Env.getValue(BarVal->getPointeeLoc()), FooVal);
1007 
1008         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
1009         ASSERT_THAT(BazDecl, NotNull());
1010 
1011         EXPECT_EQ(Env.getValue(*BazDecl), FooVal);
1012       });
1013 }
1014 
1015 TEST(TransferTest, AssignToAndFromReference) {
1016   std::string Code = R"(
1017     void target() {
1018       int Foo;
1019       int Bar;
1020       int &Baz = Foo;
1021       // [[p1]]
1022       Baz = Bar;
1023       int Qux = Baz;
1024       int &Quux = Baz;
1025       // [[p2]]
1026     }
1027   )";
1028   runDataflow(
1029       Code,
1030       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1031          ASTContext &ASTCtx) {
1032         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
1033         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
1034         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
1035 
1036         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1037         ASSERT_THAT(FooDecl, NotNull());
1038 
1039         const Value *FooVal = Env1.getValue(*FooDecl);
1040         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
1041 
1042         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1043         ASSERT_THAT(BarDecl, NotNull());
1044 
1045         const Value *BarVal = Env1.getValue(*BarDecl);
1046         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
1047 
1048         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
1049         ASSERT_THAT(BazDecl, NotNull());
1050 
1051         EXPECT_EQ(Env1.getValue(*BazDecl), FooVal);
1052 
1053         EXPECT_EQ(Env2.getValue(*BazDecl), BarVal);
1054         EXPECT_EQ(Env2.getValue(*FooDecl), BarVal);
1055 
1056         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
1057         ASSERT_THAT(QuxDecl, NotNull());
1058         EXPECT_EQ(Env2.getValue(*QuxDecl), BarVal);
1059 
1060         const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux");
1061         ASSERT_THAT(QuuxDecl, NotNull());
1062         EXPECT_EQ(Env2.getValue(*QuuxDecl), BarVal);
1063       });
1064 }
1065 
1066 TEST(TransferTest, MultipleParamDecls) {
1067   std::string Code = R"(
1068     void target(int Foo, int Bar) {
1069       (void)0;
1070       // [[p]]
1071     }
1072   )";
1073   runDataflow(
1074       Code,
1075       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1076          ASTContext &ASTCtx) {
1077         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1078         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1079 
1080         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1081         ASSERT_THAT(FooDecl, NotNull());
1082 
1083         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
1084         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
1085 
1086         const Value *FooVal = Env.getValue(*FooLoc);
1087         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
1088 
1089         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1090         ASSERT_THAT(BarDecl, NotNull());
1091 
1092         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
1093         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
1094 
1095         const Value *BarVal = Env.getValue(*BarLoc);
1096         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
1097       });
1098 }
1099 
1100 TEST(TransferTest, StructParamDecl) {
1101   std::string Code = R"(
1102     struct A {
1103       int Bar;
1104     };
1105 
1106     void target(A Foo) {
1107       (void)Foo.Bar;
1108       // [[p]]
1109     }
1110   )";
1111   runDataflow(
1112       Code,
1113       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1114          ASTContext &ASTCtx) {
1115         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1116         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1117 
1118         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1119         ASSERT_THAT(FooDecl, NotNull());
1120 
1121         ASSERT_TRUE(FooDecl->getType()->isStructureType());
1122         auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields();
1123 
1124         FieldDecl *BarDecl = nullptr;
1125         for (FieldDecl *Field : FooFields) {
1126           if (Field->getNameAsString() == "Bar") {
1127             BarDecl = Field;
1128           } else {
1129             FAIL() << "Unexpected field: " << Field->getNameAsString();
1130           }
1131         }
1132         ASSERT_THAT(BarDecl, NotNull());
1133 
1134         const auto *FooLoc =
1135             cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
1136         EXPECT_TRUE(isa<IntegerValue>(getFieldValue(FooLoc, *BarDecl, Env)));
1137       });
1138 }
1139 
1140 TEST(TransferTest, ReferenceParamDecl) {
1141   std::string Code = R"(
1142     struct A {};
1143 
1144     void target(A &Foo) {
1145       (void)0;
1146       // [[p]]
1147     }
1148   )";
1149   runDataflow(
1150       Code,
1151       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1152          ASTContext &ASTCtx) {
1153         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1154         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1155 
1156         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1157         ASSERT_THAT(FooDecl, NotNull());
1158 
1159         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
1160         ASSERT_TRUE(isa_and_nonnull<RecordStorageLocation>(FooLoc));
1161       });
1162 }
1163 
1164 TEST(TransferTest, PointerParamDecl) {
1165   std::string Code = R"(
1166     struct A {};
1167 
1168     void target(A *Foo) {
1169       (void)0;
1170       // [[p]]
1171     }
1172   )";
1173   runDataflow(
1174       Code,
1175       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1176          ASTContext &ASTCtx) {
1177         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1178         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1179 
1180         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1181         ASSERT_THAT(FooDecl, NotNull());
1182 
1183         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
1184         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
1185 
1186         const PointerValue *FooVal = cast<PointerValue>(Env.getValue(*FooLoc));
1187         const StorageLocation &FooPointeeLoc = FooVal->getPointeeLoc();
1188         EXPECT_TRUE(isa<RecordStorageLocation>(&FooPointeeLoc));
1189       });
1190 }
1191 
1192 TEST(TransferTest, StructMember) {
1193   std::string Code = R"(
1194     struct A {
1195       int Bar;
1196     };
1197 
1198     void target(A Foo) {
1199       int Baz = Foo.Bar;
1200       // [[p]]
1201     }
1202   )";
1203   runDataflow(
1204       Code,
1205       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1206          ASTContext &ASTCtx) {
1207         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1208         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1209 
1210         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1211         ASSERT_THAT(FooDecl, NotNull());
1212 
1213         ASSERT_TRUE(FooDecl->getType()->isStructureType());
1214         auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields();
1215 
1216         FieldDecl *BarDecl = nullptr;
1217         for (FieldDecl *Field : FooFields) {
1218           if (Field->getNameAsString() == "Bar") {
1219             BarDecl = Field;
1220           } else {
1221             FAIL() << "Unexpected field: " << Field->getNameAsString();
1222           }
1223         }
1224         ASSERT_THAT(BarDecl, NotNull());
1225 
1226         const auto *FooLoc =
1227             cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
1228         const auto *BarVal =
1229             cast<IntegerValue>(getFieldValue(FooLoc, *BarDecl, Env));
1230 
1231         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
1232         ASSERT_THAT(BazDecl, NotNull());
1233 
1234         EXPECT_EQ(Env.getValue(*BazDecl), BarVal);
1235       });
1236 }
1237 
1238 TEST(TransferTest, StructMemberEnum) {
1239   std::string Code = R"(
1240     struct A {
1241       int Bar;
1242       enum E { ONE, TWO };
1243     };
1244 
1245     void target(A Foo) {
1246       A::E Baz = Foo.ONE;
1247       // [[p]]
1248     }
1249   )";
1250   // Minimal expectations -- we're just testing that it doesn't crash, since
1251   // enums aren't interpreted.
1252   runDataflow(
1253       Code,
1254       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1255          ASTContext &ASTCtx) {
1256         EXPECT_THAT(Results.keys(), UnorderedElementsAre("p"));
1257       });
1258 }
1259 
1260 TEST(TransferTest, DerivedBaseMemberClass) {
1261   std::string Code = R"(
1262     class A {
1263       int ADefault;
1264     protected:
1265       int AProtected;
1266     private:
1267       int APrivate;
1268     public:
1269       int APublic;
1270 
1271     private:
1272       friend void target();
1273     };
1274 
1275     class B : public A {
1276       int BDefault;
1277     protected:
1278       int BProtected;
1279     private:
1280       int BPrivate;
1281 
1282     private:
1283       friend void target();
1284     };
1285 
1286     void target() {
1287       B Foo;
1288       (void)Foo.ADefault;
1289       (void)Foo.AProtected;
1290       (void)Foo.APrivate;
1291       (void)Foo.APublic;
1292       (void)Foo.BDefault;
1293       (void)Foo.BProtected;
1294       (void)Foo.BPrivate;
1295       // [[p]]
1296     }
1297   )";
1298   runDataflow(
1299       Code,
1300       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1301          ASTContext &ASTCtx) {
1302         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1303         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1304 
1305         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1306         ASSERT_THAT(FooDecl, NotNull());
1307         ASSERT_TRUE(FooDecl->getType()->isRecordType());
1308 
1309         // Derived-class fields.
1310         const FieldDecl *BDefaultDecl = nullptr;
1311         const FieldDecl *BProtectedDecl = nullptr;
1312         const FieldDecl *BPrivateDecl = nullptr;
1313         for (const FieldDecl *Field :
1314              FooDecl->getType()->getAsRecordDecl()->fields()) {
1315           if (Field->getNameAsString() == "BDefault") {
1316             BDefaultDecl = Field;
1317           } else if (Field->getNameAsString() == "BProtected") {
1318             BProtectedDecl = Field;
1319           } else if (Field->getNameAsString() == "BPrivate") {
1320             BPrivateDecl = Field;
1321           } else {
1322             FAIL() << "Unexpected field: " << Field->getNameAsString();
1323           }
1324         }
1325         ASSERT_THAT(BDefaultDecl, NotNull());
1326         ASSERT_THAT(BProtectedDecl, NotNull());
1327         ASSERT_THAT(BPrivateDecl, NotNull());
1328 
1329         // Base-class fields.
1330         const FieldDecl *ADefaultDecl = nullptr;
1331         const FieldDecl *APrivateDecl = nullptr;
1332         const FieldDecl *AProtectedDecl = nullptr;
1333         const FieldDecl *APublicDecl = nullptr;
1334         for (const clang::CXXBaseSpecifier &Base :
1335              FooDecl->getType()->getAsCXXRecordDecl()->bases()) {
1336           QualType BaseType = Base.getType();
1337           ASSERT_TRUE(BaseType->isRecordType());
1338           for (const FieldDecl *Field : BaseType->getAsRecordDecl()->fields()) {
1339             if (Field->getNameAsString() == "ADefault") {
1340               ADefaultDecl = Field;
1341             } else if (Field->getNameAsString() == "AProtected") {
1342               AProtectedDecl = Field;
1343             } else if (Field->getNameAsString() == "APrivate") {
1344               APrivateDecl = Field;
1345             } else if (Field->getNameAsString() == "APublic") {
1346               APublicDecl = Field;
1347             } else {
1348               FAIL() << "Unexpected field: " << Field->getNameAsString();
1349             }
1350           }
1351         }
1352         ASSERT_THAT(ADefaultDecl, NotNull());
1353         ASSERT_THAT(AProtectedDecl, NotNull());
1354         ASSERT_THAT(APrivateDecl, NotNull());
1355         ASSERT_THAT(APublicDecl, NotNull());
1356 
1357         ASSERT_TRUE(
1358             isa<RecordStorageLocation>(Env.getStorageLocation(*FooDecl)));
1359       });
1360 }
1361 
1362 static void derivedBaseMemberExpectations(
1363     const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1364     ASTContext &ASTCtx) {
1365   ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1366   const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1367 
1368   const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1369   ASSERT_THAT(FooDecl, NotNull());
1370 
1371   ASSERT_TRUE(FooDecl->getType()->isRecordType());
1372   const FieldDecl *BarDecl = nullptr;
1373   for (const clang::CXXBaseSpecifier &Base :
1374        FooDecl->getType()->getAsCXXRecordDecl()->bases()) {
1375     QualType BaseType = Base.getType();
1376     ASSERT_TRUE(BaseType->isStructureType());
1377 
1378     for (const FieldDecl *Field : BaseType->getAsRecordDecl()->fields()) {
1379       if (Field->getNameAsString() == "Bar") {
1380         BarDecl = Field;
1381       } else {
1382         FAIL() << "Unexpected field: " << Field->getNameAsString();
1383       }
1384     }
1385   }
1386   ASSERT_THAT(BarDecl, NotNull());
1387 
1388   const auto &FooLoc =
1389       *cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
1390   EXPECT_NE(Env.getValue(*FooLoc.getChild(*BarDecl)), nullptr);
1391 }
1392 
1393 TEST(TransferTest, DerivedBaseMemberStructDefault) {
1394   std::string Code = R"(
1395     struct A {
1396       int Bar;
1397     };
1398     struct B : public A {
1399     };
1400 
1401     void target() {
1402       B Foo;
1403       (void)Foo.Bar;
1404       // [[p]]
1405     }
1406   )";
1407   runDataflow(Code, derivedBaseMemberExpectations);
1408 }
1409 
1410 TEST(TransferTest, DerivedBaseMemberPrivateFriend) {
1411   // Include an access to `Foo.Bar` to verify the analysis doesn't crash on that
1412   // access.
1413   std::string Code = R"(
1414     struct A {
1415     private:
1416       friend void target();
1417       int Bar;
1418     };
1419     struct B : public A {
1420     };
1421 
1422     void target() {
1423       B Foo;
1424       (void)Foo.Bar;
1425       // [[p]]
1426     }
1427   )";
1428   runDataflow(Code, derivedBaseMemberExpectations);
1429 }
1430 
1431 TEST(TransferTest, ClassMember) {
1432   std::string Code = R"(
1433     class A {
1434     public:
1435       int Bar;
1436     };
1437 
1438     void target(A Foo) {
1439       int Baz = Foo.Bar;
1440       // [[p]]
1441     }
1442   )";
1443   runDataflow(
1444       Code,
1445       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1446          ASTContext &ASTCtx) {
1447         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1448         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1449 
1450         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1451         ASSERT_THAT(FooDecl, NotNull());
1452 
1453         ASSERT_TRUE(FooDecl->getType()->isClassType());
1454         auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields();
1455 
1456         FieldDecl *BarDecl = nullptr;
1457         for (FieldDecl *Field : FooFields) {
1458           if (Field->getNameAsString() == "Bar") {
1459             BarDecl = Field;
1460           } else {
1461             FAIL() << "Unexpected field: " << Field->getNameAsString();
1462           }
1463         }
1464         ASSERT_THAT(BarDecl, NotNull());
1465 
1466         const auto *FooLoc =
1467             cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
1468         const auto *BarVal =
1469             cast<IntegerValue>(getFieldValue(FooLoc, *BarDecl, Env));
1470 
1471         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
1472         ASSERT_THAT(BazDecl, NotNull());
1473 
1474         EXPECT_EQ(Env.getValue(*BazDecl), BarVal);
1475       });
1476 }
1477 
1478 TEST(TransferTest, BaseClassInitializer) {
1479   using ast_matchers::cxxConstructorDecl;
1480   using ast_matchers::hasName;
1481   using ast_matchers::ofClass;
1482 
1483   std::string Code = R"(
1484     class A {
1485     public:
1486       A(int I) : Bar(I) {}
1487       int Bar;
1488     };
1489 
1490     class B : public A {
1491     public:
1492       B(int I) : A(I) {
1493         (void)0;
1494         // [[p]]
1495       }
1496     };
1497   )";
1498   ASSERT_THAT_ERROR(
1499       checkDataflow<NoopAnalysis>(
1500           AnalysisInputs<NoopAnalysis>(
1501               Code, cxxConstructorDecl(ofClass(hasName("B"))),
1502               [](ASTContext &C, Environment &) { return NoopAnalysis(C); })
1503               .withASTBuildArgs(
1504                   {"-fsyntax-only", "-fno-delayed-template-parsing",
1505                    "-std=" + std::string(LangStandard::getLangStandardForKind(
1506                                              LangStandard::lang_cxx17)
1507                                              .getName())}),
1508           /*VerifyResults=*/
1509           [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1510              const AnalysisOutputs &) {
1511             // Regression test to verify that base-class initializers do not
1512             // trigger an assertion. If we add support for such initializers in
1513             // the future, we can expand this test to check more specific
1514             // properties.
1515             EXPECT_THAT(Results.keys(), UnorderedElementsAre("p"));
1516           }),
1517       llvm::Succeeded());
1518 }
1519 
1520 TEST(TransferTest, FieldsDontHaveValuesInConstructor) {
1521   // In a constructor, unlike in regular member functions, we don't want fields
1522   // to be pre-initialized with values, because doing so is the job of the
1523   // constructor.
1524   std::string Code = R"(
1525     struct target {
1526       target() {
1527         0;
1528         // [[p]]
1529         // Mention the field so it is modeled;
1530         Val;
1531       }
1532 
1533       int Val;
1534     };
1535  )";
1536   runDataflow(
1537       Code,
1538       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1539          ASTContext &ASTCtx) {
1540         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1541         EXPECT_EQ(getFieldValue(Env.getThisPointeeStorageLocation(), "Val",
1542                                 ASTCtx, Env),
1543                   nullptr);
1544       });
1545 }
1546 
1547 TEST(TransferTest, FieldsDontHaveValuesInConstructorWithBaseClass) {
1548   // See above, but for a class with a base class.
1549   std::string Code = R"(
1550     struct Base {
1551         int BaseVal;
1552     };
1553 
1554     struct target  : public Base {
1555       target() {
1556         0;
1557         // [[p]]
1558         // Mention the fields so they are modeled.
1559         BaseVal;
1560         Val;
1561       }
1562 
1563       int Val;
1564     };
1565  )";
1566   runDataflow(
1567       Code,
1568       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1569          ASTContext &ASTCtx) {
1570         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1571         // The field of the base class should already have been initialized with
1572         // a value by the base constructor.
1573         EXPECT_NE(getFieldValue(Env.getThisPointeeStorageLocation(), "BaseVal",
1574                                 ASTCtx, Env),
1575                   nullptr);
1576         EXPECT_EQ(getFieldValue(Env.getThisPointeeStorageLocation(), "Val",
1577                                 ASTCtx, Env),
1578                   nullptr);
1579       });
1580 }
1581 
1582 TEST(TransferTest, StructModeledFieldsWithAccessor) {
1583   std::string Code = R"(
1584     class S {
1585       int *Ptr;
1586       int *PtrNonConst;
1587       int Int;
1588       int IntWithInc;
1589       int IntNotAccessed;
1590       int IntRef;
1591     public:
1592       int *getPtr() const { return Ptr; }
1593       int *getPtrNonConst() { return PtrNonConst; }
1594       int getInt(int i) const { return Int; }
1595       int getWithInc(int i) { IntWithInc += i; return IntWithInc; }
1596       int getIntNotAccessed() const { return IntNotAccessed; }
1597       int getIntNoDefinition() const;
1598       int &getIntRef() { return IntRef; }
1599       void returnVoid() const { return; }
1600     };
1601 
1602     void target() {
1603       S s;
1604       int *p1 = s.getPtr();
1605       int *p2 = s.getPtrNonConst();
1606       int i1 = s.getInt(1);
1607       int i2 = s.getWithInc(1);
1608       int i3 = s.getIntNoDefinition();
1609       int &iref = s.getIntRef();
1610 
1611       // Regression test: Don't crash on an indirect call (which doesn't have
1612       // an associated `CXXMethodDecl`).
1613       auto ptr_to_member_fn = &S::getPtr;
1614       p1 = (s.*ptr_to_member_fn)();
1615 
1616       // Regression test: Don't crash on a return statement without a value.
1617       s.returnVoid();
1618       // [[p]]
1619     }
1620   )";
1621   runDataflow(
1622       Code,
1623       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1624          ASTContext &ASTCtx) {
1625         const Environment &Env =
1626               getEnvironmentAtAnnotation(Results, "p");
1627         auto &SLoc = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "s");
1628         std::vector<const ValueDecl*> Fields;
1629         for (auto [Field, _] : SLoc.children())
1630           Fields.push_back(Field);
1631         // Only the fields that have simple accessor methods (that have a
1632         // single statement body that returns the member variable) should be
1633         // modeled.
1634         ASSERT_THAT(Fields, UnorderedElementsAre(
1635             findValueDecl(ASTCtx, "Ptr"), findValueDecl(ASTCtx, "PtrNonConst"),
1636             findValueDecl(ASTCtx, "Int"), findValueDecl(ASTCtx, "IntRef")));
1637       });
1638 }
1639 
1640 TEST(TransferTest, StructModeledFieldsInTypeid) {
1641   // Test that we model fields mentioned inside a `typeid()` expression only if
1642   // that expression is potentially evaluated -- i.e. if the expression inside
1643   // `typeid()` is a glvalue of polymorphic type (see
1644   // `CXXTypeidExpr::isPotentiallyEvaluated()` and [expr.typeid]p3).
1645   std::string Code = R"(
1646     // Definitions needed for `typeid`.
1647     namespace std {
1648       class type_info {};
1649       class bad_typeid {};
1650     }  // namespace std
1651 
1652     struct NonPolymorphic {};
1653 
1654     struct Polymorphic {
1655       virtual ~Polymorphic() = default;
1656     };
1657 
1658     struct S {
1659       NonPolymorphic *NonPoly;
1660       Polymorphic *Poly;
1661     };
1662 
1663     void target(S &s) {
1664       typeid(*s.NonPoly);
1665       typeid(*s.Poly);
1666       // [[p]]
1667     }
1668   )";
1669   runDataflow(
1670       Code,
1671       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1672          ASTContext &ASTCtx) {
1673         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1674         auto &SLoc = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "s");
1675         std::vector<const ValueDecl *> Fields;
1676         for (auto [Field, _] : SLoc.children())
1677           Fields.push_back(Field);
1678         EXPECT_THAT(Fields,
1679                     UnorderedElementsAre(findValueDecl(ASTCtx, "Poly")));
1680       });
1681 }
1682 
1683 TEST(TransferTest, StructModeledFieldsWithComplicatedInheritance) {
1684   std::string Code = R"(
1685     struct Base1 {
1686       int base1_1;
1687       int base1_2;
1688     };
1689     struct Intermediate : Base1 {
1690       int intermediate_1;
1691       int intermediate_2;
1692     };
1693     struct Base2 {
1694       int base2_1;
1695       int base2_2;
1696     };
1697     struct MostDerived : public Intermediate, Base2 {
1698       int most_derived_1;
1699       int most_derived_2;
1700     };
1701 
1702     void target() {
1703       MostDerived MD;
1704       MD.base1_2 = 1;
1705       MD.intermediate_2 = 1;
1706       MD.base2_2 = 1;
1707       MD.most_derived_2 = 1;
1708       // [[p]]
1709     }
1710   )";
1711   runDataflow(
1712       Code,
1713       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1714          ASTContext &ASTCtx) {
1715         const Environment &Env =
1716               getEnvironmentAtAnnotation(Results, "p");
1717 
1718         // Only the accessed fields should exist in the model.
1719         auto &MDLoc = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "MD");
1720         std::vector<const ValueDecl*> Fields;
1721         for (auto [Field, _] : MDLoc.children())
1722           Fields.push_back(Field);
1723         ASSERT_THAT(Fields, UnorderedElementsAre(
1724             findValueDecl(ASTCtx, "base1_2"),
1725             findValueDecl(ASTCtx, "intermediate_2"),
1726             findValueDecl(ASTCtx, "base2_2"),
1727             findValueDecl(ASTCtx, "most_derived_2")));
1728       });
1729 }
1730 
1731 TEST(TransferTest, StructInitializerListWithComplicatedInheritance) {
1732   std::string Code = R"(
1733     struct Base1 {
1734       int base1;
1735     };
1736     struct Intermediate : Base1 {
1737       int intermediate;
1738     };
1739     struct Base2 {
1740       int base2;
1741     };
1742     struct MostDerived : public Intermediate, Base2 {
1743       int most_derived;
1744     };
1745 
1746     void target() {
1747       MostDerived MD = {};
1748       // [[p]]
1749     }
1750   )";
1751   runDataflow(
1752       Code,
1753       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1754          ASTContext &ASTCtx) {
1755         const Environment &Env =
1756               getEnvironmentAtAnnotation(Results, "p");
1757 
1758         // When a struct is initialized with a initializer list, all the
1759         // fields are considered "accessed", and therefore do exist.
1760         auto &MD = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "MD");
1761         ASSERT_THAT(cast<IntegerValue>(
1762             getFieldValue(&MD, *findValueDecl(ASTCtx, "base1"), Env)),
1763             NotNull());
1764         ASSERT_THAT(cast<IntegerValue>(
1765             getFieldValue(&MD, *findValueDecl(ASTCtx, "intermediate"), Env)),
1766             NotNull());
1767         ASSERT_THAT(cast<IntegerValue>(
1768             getFieldValue(&MD, *findValueDecl(ASTCtx, "base2"), Env)),
1769             NotNull());
1770         ASSERT_THAT(cast<IntegerValue>(
1771             getFieldValue(&MD, *findValueDecl(ASTCtx, "most_derived"), Env)),
1772             NotNull());
1773       });
1774 }
1775 
1776 TEST(TransferTest, ReferenceMember) {
1777   std::string Code = R"(
1778     struct A {
1779       int &Bar;
1780     };
1781 
1782     void target(A Foo) {
1783       int Baz = Foo.Bar;
1784       // [[p]]
1785     }
1786   )";
1787   runDataflow(
1788       Code,
1789       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1790          ASTContext &ASTCtx) {
1791         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1792         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1793 
1794         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1795         ASSERT_THAT(FooDecl, NotNull());
1796 
1797         ASSERT_TRUE(FooDecl->getType()->isStructureType());
1798         auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields();
1799 
1800         FieldDecl *BarDecl = nullptr;
1801         for (FieldDecl *Field : FooFields) {
1802           if (Field->getNameAsString() == "Bar") {
1803             BarDecl = Field;
1804           } else {
1805             FAIL() << "Unexpected field: " << Field->getNameAsString();
1806           }
1807         }
1808         ASSERT_THAT(BarDecl, NotNull());
1809 
1810         const auto *FooLoc =
1811             cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
1812         const auto *BarReferentVal =
1813             cast<IntegerValue>(getFieldValue(FooLoc, *BarDecl, Env));
1814 
1815         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
1816         ASSERT_THAT(BazDecl, NotNull());
1817 
1818         EXPECT_EQ(Env.getValue(*BazDecl), BarReferentVal);
1819       });
1820 }
1821 
1822 TEST(TransferTest, StructThisMember) {
1823   std::string Code = R"(
1824     struct A {
1825       int Bar;
1826 
1827       struct B {
1828         int Baz;
1829       };
1830 
1831       B Qux;
1832 
1833       void target() {
1834         int Foo = Bar;
1835         int Quux = Qux.Baz;
1836         // [[p]]
1837       }
1838     };
1839   )";
1840   runDataflow(
1841       Code,
1842       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1843          ASTContext &ASTCtx) {
1844         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1845         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1846 
1847         const auto *ThisLoc = Env.getThisPointeeStorageLocation();
1848         ASSERT_THAT(ThisLoc, NotNull());
1849 
1850         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1851         ASSERT_THAT(BarDecl, NotNull());
1852 
1853         const auto *BarLoc =
1854             cast<ScalarStorageLocation>(ThisLoc->getChild(*BarDecl));
1855         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
1856 
1857         const Value *BarVal = Env.getValue(*BarLoc);
1858         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
1859 
1860         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1861         ASSERT_THAT(FooDecl, NotNull());
1862         EXPECT_EQ(Env.getValue(*FooDecl), BarVal);
1863 
1864         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
1865         ASSERT_THAT(QuxDecl, NotNull());
1866 
1867         ASSERT_TRUE(QuxDecl->getType()->isStructureType());
1868         auto QuxFields = QuxDecl->getType()->getAsRecordDecl()->fields();
1869 
1870         FieldDecl *BazDecl = nullptr;
1871         for (FieldDecl *Field : QuxFields) {
1872           if (Field->getNameAsString() == "Baz") {
1873             BazDecl = Field;
1874           } else {
1875             FAIL() << "Unexpected field: " << Field->getNameAsString();
1876           }
1877         }
1878         ASSERT_THAT(BazDecl, NotNull());
1879 
1880         const auto *QuxLoc =
1881             cast<RecordStorageLocation>(ThisLoc->getChild(*QuxDecl));
1882 
1883         const auto *BazVal =
1884             cast<IntegerValue>(getFieldValue(QuxLoc, *BazDecl, Env));
1885 
1886         const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux");
1887         ASSERT_THAT(QuuxDecl, NotNull());
1888         EXPECT_EQ(Env.getValue(*QuuxDecl), BazVal);
1889       });
1890 }
1891 
1892 TEST(TransferTest, ClassThisMember) {
1893   std::string Code = R"(
1894     class A {
1895       int Bar;
1896 
1897       class B {
1898       public:
1899         int Baz;
1900       };
1901 
1902       B Qux;
1903 
1904       void target() {
1905         int Foo = Bar;
1906         int Quux = Qux.Baz;
1907         // [[p]]
1908       }
1909     };
1910   )";
1911   runDataflow(
1912       Code,
1913       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1914          ASTContext &ASTCtx) {
1915         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1916         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1917 
1918         const auto *ThisLoc = Env.getThisPointeeStorageLocation();
1919 
1920         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1921         ASSERT_THAT(BarDecl, NotNull());
1922 
1923         const auto *BarLoc =
1924             cast<ScalarStorageLocation>(ThisLoc->getChild(*BarDecl));
1925         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
1926 
1927         const Value *BarVal = Env.getValue(*BarLoc);
1928         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
1929 
1930         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1931         ASSERT_THAT(FooDecl, NotNull());
1932         EXPECT_EQ(Env.getValue(*FooDecl), BarVal);
1933 
1934         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
1935         ASSERT_THAT(QuxDecl, NotNull());
1936 
1937         ASSERT_TRUE(QuxDecl->getType()->isClassType());
1938         auto QuxFields = QuxDecl->getType()->getAsRecordDecl()->fields();
1939 
1940         FieldDecl *BazDecl = nullptr;
1941         for (FieldDecl *Field : QuxFields) {
1942           if (Field->getNameAsString() == "Baz") {
1943             BazDecl = Field;
1944           } else {
1945             FAIL() << "Unexpected field: " << Field->getNameAsString();
1946           }
1947         }
1948         ASSERT_THAT(BazDecl, NotNull());
1949 
1950         const auto *QuxLoc =
1951             cast<RecordStorageLocation>(ThisLoc->getChild(*QuxDecl));
1952 
1953         const auto *BazVal =
1954             cast<IntegerValue>(getFieldValue(QuxLoc, *BazDecl, Env));
1955 
1956         const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux");
1957         ASSERT_THAT(QuuxDecl, NotNull());
1958         EXPECT_EQ(Env.getValue(*QuuxDecl), BazVal);
1959       });
1960 }
1961 
1962 TEST(TransferTest, UnionThisMember) {
1963   std::string Code = R"(
1964     union A {
1965       int Foo;
1966       int Bar;
1967 
1968       void target() {
1969         A a;
1970         // Mention the fields to ensure they're included in the analysis.
1971         (void)a.Foo;
1972         (void)a.Bar;
1973         // [[p]]
1974       }
1975     };
1976   )";
1977   runDataflow(
1978       Code,
1979       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1980          ASTContext &ASTCtx) {
1981         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1982         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1983 
1984         const auto *ThisLoc = Env.getThisPointeeStorageLocation();
1985         ASSERT_THAT(ThisLoc, NotNull());
1986 
1987         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1988         ASSERT_THAT(FooDecl, NotNull());
1989 
1990         const auto *FooLoc =
1991             cast<ScalarStorageLocation>(ThisLoc->getChild(*FooDecl));
1992         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
1993 
1994         const Value *FooVal = Env.getValue(*FooLoc);
1995         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
1996 
1997         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1998         ASSERT_THAT(BarDecl, NotNull());
1999 
2000         const auto *BarLoc =
2001             cast<ScalarStorageLocation>(ThisLoc->getChild(*BarDecl));
2002         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
2003 
2004         const Value *BarVal = Env.getValue(*BarLoc);
2005         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
2006       });
2007 }
2008 
2009 TEST(TransferTest, StructThisInLambda) {
2010   std::string ThisCaptureCode = R"(
2011     struct A {
2012       void frob() {
2013         [this]() {
2014           int Foo = Bar;
2015           // [[p1]]
2016         }();
2017       }
2018 
2019       int Bar;
2020     };
2021   )";
2022   runDataflow(
2023       ThisCaptureCode,
2024       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2025          ASTContext &ASTCtx) {
2026         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1"));
2027         const Environment &Env = getEnvironmentAtAnnotation(Results, "p1");
2028 
2029         const auto *ThisLoc = Env.getThisPointeeStorageLocation();
2030         ASSERT_THAT(ThisLoc, NotNull());
2031 
2032         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2033         ASSERT_THAT(BarDecl, NotNull());
2034 
2035         const auto *BarLoc =
2036             cast<ScalarStorageLocation>(ThisLoc->getChild(*BarDecl));
2037         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
2038 
2039         const Value *BarVal = Env.getValue(*BarLoc);
2040         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
2041 
2042         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2043         ASSERT_THAT(FooDecl, NotNull());
2044         EXPECT_EQ(Env.getValue(*FooDecl), BarVal);
2045       },
2046       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator()");
2047 
2048   std::string RefCaptureDefaultCode = R"(
2049     struct A {
2050       void frob() {
2051         [&]() {
2052           int Foo = Bar;
2053           // [[p2]]
2054         }();
2055       }
2056 
2057       int Bar;
2058     };
2059   )";
2060   runDataflow(
2061       RefCaptureDefaultCode,
2062       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2063          ASTContext &ASTCtx) {
2064         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p2"));
2065         const Environment &Env = getEnvironmentAtAnnotation(Results, "p2");
2066 
2067         const auto *ThisLoc = Env.getThisPointeeStorageLocation();
2068         ASSERT_THAT(ThisLoc, NotNull());
2069 
2070         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2071         ASSERT_THAT(BarDecl, NotNull());
2072 
2073         const auto *BarLoc =
2074             cast<ScalarStorageLocation>(ThisLoc->getChild(*BarDecl));
2075         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
2076 
2077         const Value *BarVal = Env.getValue(*BarLoc);
2078         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
2079 
2080         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2081         ASSERT_THAT(FooDecl, NotNull());
2082         EXPECT_EQ(Env.getValue(*FooDecl), BarVal);
2083       },
2084       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator()");
2085 
2086   std::string FreeFunctionLambdaCode = R"(
2087     void foo() {
2088       int Bar;
2089       [&]() {
2090         int Foo = Bar;
2091         // [[p3]]
2092       }();
2093     }
2094   )";
2095   runDataflow(
2096       FreeFunctionLambdaCode,
2097       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2098          ASTContext &ASTCtx) {
2099         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p3"));
2100         const Environment &Env = getEnvironmentAtAnnotation(Results, "p3");
2101 
2102         EXPECT_THAT(Env.getThisPointeeStorageLocation(), IsNull());
2103       },
2104       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator()");
2105 }
2106 
2107 TEST(TransferTest, ConstructorInitializer) {
2108   std::string Code = R"(
2109     struct target {
2110       int Bar;
2111 
2112       target(int Foo) : Bar(Foo) {
2113         int Qux = Bar;
2114         // [[p]]
2115       }
2116     };
2117   )";
2118   runDataflow(
2119       Code,
2120       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2121          ASTContext &ASTCtx) {
2122         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2123         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2124 
2125         const auto *ThisLoc = Env.getThisPointeeStorageLocation();
2126         ASSERT_THAT(ThisLoc, NotNull());
2127 
2128         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2129         ASSERT_THAT(FooDecl, NotNull());
2130 
2131         const auto *FooVal = cast<IntegerValue>(Env.getValue(*FooDecl));
2132 
2133         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
2134         ASSERT_THAT(QuxDecl, NotNull());
2135         EXPECT_EQ(Env.getValue(*QuxDecl), FooVal);
2136       });
2137 }
2138 
2139 TEST(TransferTest, DefaultInitializer) {
2140   std::string Code = R"(
2141     struct target {
2142       int Bar;
2143       int Baz = Bar;
2144 
2145       target(int Foo) : Bar(Foo) {
2146         int Qux = Baz;
2147         // [[p]]
2148       }
2149     };
2150   )";
2151   runDataflow(
2152       Code,
2153       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2154          ASTContext &ASTCtx) {
2155         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2156         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2157 
2158         const auto *ThisLoc = Env.getThisPointeeStorageLocation();
2159         ASSERT_THAT(ThisLoc, NotNull());
2160 
2161         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2162         ASSERT_THAT(FooDecl, NotNull());
2163 
2164         const auto *FooVal = cast<IntegerValue>(Env.getValue(*FooDecl));
2165 
2166         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
2167         ASSERT_THAT(QuxDecl, NotNull());
2168         EXPECT_EQ(Env.getValue(*QuxDecl), FooVal);
2169       });
2170 }
2171 
2172 TEST(TransferTest, DefaultInitializerReference) {
2173   std::string Code = R"(
2174     struct target {
2175       int &Bar;
2176       int &Baz = Bar;
2177 
2178       target(int &Foo) : Bar(Foo) {
2179         int &Qux = Baz;
2180         // [[p]]
2181       }
2182     };
2183   )";
2184   runDataflow(
2185       Code,
2186       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2187          ASTContext &ASTCtx) {
2188         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2189         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2190 
2191         const auto *ThisLoc = Env.getThisPointeeStorageLocation();
2192         ASSERT_THAT(ThisLoc, NotNull());
2193 
2194         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2195         ASSERT_THAT(FooDecl, NotNull());
2196 
2197         const auto *FooLoc = Env.getStorageLocation(*FooDecl);
2198 
2199         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
2200         ASSERT_THAT(QuxDecl, NotNull());
2201 
2202         const auto *QuxLoc = Env.getStorageLocation(*QuxDecl);
2203         EXPECT_EQ(QuxLoc, FooLoc);
2204       });
2205 }
2206 
2207 TEST(TransferTest, TemporaryObject) {
2208   std::string Code = R"(
2209     struct A {
2210       int Bar;
2211     };
2212 
2213     void target() {
2214       A Foo = A();
2215       (void)Foo.Bar;
2216       // [[p]]
2217     }
2218   )";
2219   runDataflow(
2220       Code,
2221       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2222          ASTContext &ASTCtx) {
2223         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2224         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2225 
2226         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2227         ASSERT_THAT(FooDecl, NotNull());
2228 
2229         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2230         ASSERT_THAT(BarDecl, NotNull());
2231 
2232         const auto *FooLoc =
2233             cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
2234         EXPECT_TRUE(isa<IntegerValue>(getFieldValue(FooLoc, *BarDecl, Env)));
2235       });
2236 }
2237 
2238 TEST(TransferTest, ElidableConstructor) {
2239   // This test is effectively the same as TransferTest.TemporaryObject, but
2240   // the code is compiled as C++14.
2241   std::string Code = R"(
2242     struct A {
2243       int Bar;
2244     };
2245 
2246     void target() {
2247       A Foo = A();
2248       (void)Foo.Bar;
2249       // [[p]]
2250     }
2251   )";
2252   runDataflow(
2253       Code,
2254       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2255          ASTContext &ASTCtx) {
2256         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2257         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2258 
2259         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2260         ASSERT_THAT(FooDecl, NotNull());
2261 
2262         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2263         ASSERT_THAT(BarDecl, NotNull());
2264 
2265         const auto *FooLoc =
2266             cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
2267         EXPECT_TRUE(isa<IntegerValue>(getFieldValue(FooLoc, *BarDecl, Env)));
2268       },
2269       LangStandard::lang_cxx14);
2270 }
2271 
2272 TEST(TransferTest, AssignmentOperator) {
2273   std::string Code = R"(
2274     struct A {
2275       int Baz;
2276     };
2277 
2278     void target() {
2279       A Foo = { 1 };
2280       A Bar = { 2 };
2281       // [[p1]]
2282       A &Rval = (Foo = Bar);
2283       // [[p2]]
2284       Foo.Baz = 3;
2285       // [[p3]]
2286     }
2287   )";
2288   runDataflow(
2289       Code,
2290       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2291          ASTContext &ASTCtx) {
2292         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2293         ASSERT_THAT(FooDecl, NotNull());
2294 
2295         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2296         ASSERT_THAT(BarDecl, NotNull());
2297 
2298         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2299         ASSERT_THAT(BazDecl, NotNull());
2300 
2301         // Before copy assignment.
2302         {
2303           const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
2304 
2305           const auto *FooLoc1 =
2306               cast<RecordStorageLocation>(Env1.getStorageLocation(*FooDecl));
2307           const auto *BarLoc1 =
2308               cast<RecordStorageLocation>(Env1.getStorageLocation(*BarDecl));
2309           EXPECT_FALSE(recordsEqual(*FooLoc1, *BarLoc1, Env1));
2310 
2311           const auto *FooBazVal1 =
2312               cast<IntegerValue>(getFieldValue(FooLoc1, *BazDecl, Env1));
2313           const auto *BarBazVal1 =
2314               cast<IntegerValue>(getFieldValue(BarLoc1, *BazDecl, Env1));
2315           EXPECT_NE(FooBazVal1, BarBazVal1);
2316         }
2317 
2318         // After copy assignment.
2319         {
2320           const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
2321 
2322           const auto *FooLoc2 =
2323               cast<RecordStorageLocation>(Env2.getStorageLocation(*FooDecl));
2324           const auto *BarLoc2 =
2325               cast<RecordStorageLocation>(Env2.getStorageLocation(*BarDecl));
2326 
2327           EXPECT_TRUE(recordsEqual(*FooLoc2, *BarLoc2, Env2));
2328           EXPECT_EQ(&getLocForDecl(ASTCtx, Env2, "Rval"), FooLoc2);
2329 
2330           const auto *FooBazVal2 =
2331               cast<IntegerValue>(getFieldValue(FooLoc2, *BazDecl, Env2));
2332           const auto *BarBazVal2 =
2333               cast<IntegerValue>(getFieldValue(BarLoc2, *BazDecl, Env2));
2334           EXPECT_EQ(FooBazVal2, BarBazVal2);
2335         }
2336 
2337         // After value update.
2338         {
2339           const Environment &Env3 = getEnvironmentAtAnnotation(Results, "p3");
2340 
2341           const auto *FooLoc3 =
2342               cast<RecordStorageLocation>(Env3.getStorageLocation(*FooDecl));
2343           const auto *BarLoc3 =
2344               cast<RecordStorageLocation>(Env3.getStorageLocation(*BarDecl));
2345           EXPECT_FALSE(recordsEqual(*FooLoc3, *BarLoc3, Env3));
2346 
2347           const auto *FooBazVal3 =
2348               cast<IntegerValue>(getFieldValue(FooLoc3, *BazDecl, Env3));
2349           const auto *BarBazVal3 =
2350               cast<IntegerValue>(getFieldValue(BarLoc3, *BazDecl, Env3));
2351           EXPECT_NE(FooBazVal3, BarBazVal3);
2352         }
2353       });
2354 }
2355 
2356 // It's legal for the assignment operator to take its source parameter by value.
2357 // Check that we handle this correctly. (This is a repro -- we used to
2358 // assert-fail on this.)
2359 TEST(TransferTest, AssignmentOperator_ArgByValue) {
2360   std::string Code = R"(
2361     struct A {
2362       int Baz;
2363       A &operator=(A);
2364     };
2365 
2366     void target() {
2367       A Foo = { 1 };
2368       A Bar = { 2 };
2369       Foo = Bar;
2370       // [[p]]
2371     }
2372   )";
2373   runDataflow(
2374       Code,
2375       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2376          ASTContext &ASTCtx) {
2377         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2378         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2379 
2380         const auto &FooLoc =
2381             getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "Foo");
2382         const auto &BarLoc =
2383             getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "Bar");
2384 
2385         const auto *FooBazVal =
2386             cast<IntegerValue>(getFieldValue(&FooLoc, *BazDecl, Env));
2387         const auto *BarBazVal =
2388             cast<IntegerValue>(getFieldValue(&BarLoc, *BazDecl, Env));
2389         EXPECT_EQ(FooBazVal, BarBazVal);
2390       });
2391 }
2392 
2393 TEST(TransferTest, AssignmentOperatorFromBase) {
2394   std::string Code = R"(
2395     struct Base {
2396       int base;
2397     };
2398     struct Derived : public Base {
2399       using Base::operator=;
2400       int derived;
2401     };
2402     void target(Base B, Derived D) {
2403       D.base = 1;
2404       D.derived = 1;
2405       // [[before]]
2406       D = B;
2407       // [[after]]
2408     }
2409   )";
2410   runDataflow(
2411       Code,
2412       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2413          ASTContext &ASTCtx) {
2414         const Environment &EnvBefore =
2415             getEnvironmentAtAnnotation(Results, "before");
2416         const Environment &EnvAfter =
2417             getEnvironmentAtAnnotation(Results, "after");
2418 
2419         auto &BLoc =
2420             getLocForDecl<RecordStorageLocation>(ASTCtx, EnvBefore, "B");
2421         auto &DLoc =
2422             getLocForDecl<RecordStorageLocation>(ASTCtx, EnvBefore, "D");
2423 
2424         EXPECT_NE(getFieldValue(&BLoc, "base", ASTCtx, EnvBefore),
2425                   getFieldValue(&DLoc, "base", ASTCtx, EnvBefore));
2426         EXPECT_EQ(getFieldValue(&BLoc, "base", ASTCtx, EnvAfter),
2427                   getFieldValue(&DLoc, "base", ASTCtx, EnvAfter));
2428 
2429         EXPECT_EQ(getFieldValue(&DLoc, "derived", ASTCtx, EnvBefore),
2430                   getFieldValue(&DLoc, "derived", ASTCtx, EnvAfter));
2431       });
2432 }
2433 
2434 TEST(TransferTest, AssignmentOperatorFromCallResult) {
2435   std::string Code = R"(
2436     struct A {};
2437     A ReturnA();
2438 
2439     void target() {
2440       A MyA;
2441       MyA = ReturnA();
2442     }
2443   )";
2444   runDataflow(
2445       Code,
2446       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2447          ASTContext &ASTCtx) {
2448         // As of this writing, we don't produce a `Value` for the call
2449         // `ReturnA()`. The only condition we're testing for is that the
2450         // analysis should not crash in this case.
2451       });
2452 }
2453 
2454 TEST(TransferTest, AssignmentOperatorWithInitAndInheritance) {
2455   // This is a crash repro.
2456   std::string Code = R"(
2457     struct B { int Foo; };
2458     struct S : public B {};
2459     void target() {
2460       S S1 = { 1 };
2461       S S2;
2462       S S3;
2463       S1 = S2;  // Only Dst has InitListExpr.
2464       S3 = S1;  // Only Src has InitListExpr.
2465       // [[p]]
2466     }
2467   )";
2468   runDataflow(
2469       Code,
2470       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2471          ASTContext &ASTCtx) {});
2472 }
2473 
2474 TEST(TransferTest, AssignmentOperatorReturnsVoid) {
2475   // This is a crash repro.
2476   std::string Code = R"(
2477     struct S {
2478       void operator=(S&& other);
2479     };
2480     void target() {
2481       S s;
2482       s = S();
2483       // [[p]]
2484     }
2485   )";
2486   runDataflow(
2487       Code,
2488       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2489          ASTContext &ASTCtx) {});
2490 }
2491 
2492 TEST(TransferTest, AssignmentOperatorReturnsByValue) {
2493   // This is a crash repro.
2494   std::string Code = R"(
2495     struct S {
2496       S operator=(const S&);
2497       int i;
2498     };
2499     void target() {
2500       S S1 = { 1 };
2501       S S2 = { 2 };
2502       S S3 = { 3 };
2503       // [[before]]
2504       // Test that the returned value is modeled by assigning to another value.
2505       S1 = (S2 = S3);
2506       (void)0;
2507       // [[after]]
2508     }
2509   )";
2510   runDataflow(
2511       Code,
2512       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2513          ASTContext &ASTCtx) {
2514         const ValueDecl *S1Decl = findValueDecl(ASTCtx, "S1");
2515         const ValueDecl *S2Decl = findValueDecl(ASTCtx, "S2");
2516         const ValueDecl *S3Decl = findValueDecl(ASTCtx, "S3");
2517 
2518         const Environment &EnvBefore =
2519             getEnvironmentAtAnnotation(Results, "before");
2520 
2521         EXPECT_FALSE(recordsEqual(
2522             *EnvBefore.get<RecordStorageLocation>(*S1Decl),
2523             *EnvBefore.get<RecordStorageLocation>(*S2Decl), EnvBefore));
2524         EXPECT_FALSE(recordsEqual(
2525             *EnvBefore.get<RecordStorageLocation>(*S2Decl),
2526             *EnvBefore.get<RecordStorageLocation>(*S3Decl), EnvBefore));
2527 
2528         const Environment &EnvAfter =
2529             getEnvironmentAtAnnotation(Results, "after");
2530 
2531         EXPECT_TRUE(recordsEqual(*EnvAfter.get<RecordStorageLocation>(*S1Decl),
2532                                  *EnvAfter.get<RecordStorageLocation>(*S2Decl),
2533                                  EnvAfter));
2534         EXPECT_TRUE(recordsEqual(*EnvAfter.get<RecordStorageLocation>(*S2Decl),
2535                                  *EnvAfter.get<RecordStorageLocation>(*S3Decl),
2536                                  EnvAfter));
2537       });
2538 }
2539 
2540 TEST(TransferTest, AssignmentOperatorReturnsDifferentTypeByRef) {
2541   // This is a crash repro.
2542   std::string Code = R"(
2543     struct DifferentType {};
2544     struct S {
2545       DifferentType& operator=(const S&);
2546     };
2547     void target() {
2548       S s;
2549       s = S();
2550       // [[p]]
2551     }
2552   )";
2553   runDataflow(
2554       Code,
2555       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2556          ASTContext &ASTCtx) {});
2557 }
2558 
2559 TEST(TransferTest, AssignmentOperatorReturnsDifferentTypeByValue) {
2560   // This is a crash repro.
2561   std::string Code = R"(
2562     struct DifferentType {};
2563     struct S {
2564       DifferentType operator=(const S&);
2565     };
2566     void target() {
2567       S s;
2568       s = S();
2569       // [[p]]
2570     }
2571   )";
2572   runDataflow(
2573       Code,
2574       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2575          ASTContext &ASTCtx) {});
2576 }
2577 
2578 TEST(TransferTest, InitListExprAsXValue) {
2579   // This is a crash repro.
2580   std::string Code = R"(
2581     void target() {
2582       bool&& Foo{false};
2583       // [[p]]
2584     }
2585   )";
2586   runDataflow(
2587       Code,
2588       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2589          ASTContext &ASTCtx) {
2590         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2591         const auto &FooVal = getValueForDecl<BoolValue>(ASTCtx, Env, "Foo");
2592         ASSERT_TRUE(FooVal.formula().isLiteral(false));
2593       });
2594 }
2595 
2596 TEST(TransferTest, ArrayInitListExprOneRecordElement) {
2597   // This is a crash repro.
2598   std::string Code = R"cc(
2599     struct S {};
2600 
2601     void target() { S foo[] = {S()}; }
2602   )cc";
2603   runDataflow(
2604       Code,
2605       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2606          ASTContext &ASTCtx) {
2607         // Just verify that it doesn't crash.
2608       });
2609 }
2610 
2611 TEST(TransferTest, InitListExprAsUnion) {
2612   // This is a crash repro.
2613   std::string Code = R"cc(
2614     class target {
2615       union {
2616         int *a;
2617         bool *b;
2618       } F;
2619 
2620      public:
2621       constexpr target() : F{nullptr} {
2622         int *null = nullptr;
2623         F.b;  // Make sure we reference 'b' so it is modeled.
2624         // [[p]]
2625       }
2626     };
2627   )cc";
2628   runDataflow(
2629       Code,
2630       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2631          ASTContext &ASTCtx) {
2632         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2633 
2634         auto &FLoc = getFieldLoc<RecordStorageLocation>(
2635             *Env.getThisPointeeStorageLocation(), "F", ASTCtx);
2636         auto *AVal = cast<PointerValue>(getFieldValue(&FLoc, "a", ASTCtx, Env));
2637         EXPECT_EQ(AVal, &getValueForDecl<PointerValue>(ASTCtx, Env, "null"));
2638         EXPECT_EQ(getFieldValue(&FLoc, "b", ASTCtx, Env), nullptr);
2639       });
2640 }
2641 
2642 TEST(TransferTest, EmptyInitListExprForUnion) {
2643   // This is a crash repro.
2644   std::string Code = R"cc(
2645     class target {
2646       union {
2647         int *a;
2648         bool *b;
2649       } F;
2650 
2651      public:
2652       // Empty initializer list means that `F` is aggregate-initialized.
2653       // For a union, this has the effect that the first member of the union
2654       // is copy-initialized from an empty initializer list; in this specific
2655       // case, this has the effect of initializing `a` with null.
2656       constexpr target() : F{} {
2657         int *null = nullptr;
2658         F.b;  // Make sure we reference 'b' so it is modeled.
2659         // [[p]]
2660       }
2661     };
2662   )cc";
2663   runDataflow(
2664       Code,
2665       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2666          ASTContext &ASTCtx) {
2667         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2668 
2669         auto &FLoc = getFieldLoc<RecordStorageLocation>(
2670             *Env.getThisPointeeStorageLocation(), "F", ASTCtx);
2671         auto *AVal = cast<PointerValue>(getFieldValue(&FLoc, "a", ASTCtx, Env));
2672         EXPECT_EQ(AVal, &getValueForDecl<PointerValue>(ASTCtx, Env, "null"));
2673         EXPECT_EQ(getFieldValue(&FLoc, "b", ASTCtx, Env), nullptr);
2674       });
2675 }
2676 
2677 TEST(TransferTest, EmptyInitListExprForStruct) {
2678   std::string Code = R"cc(
2679     class target {
2680       struct {
2681         int *a;
2682         bool *b;
2683       } F;
2684 
2685      public:
2686       constexpr target() : F{} {
2687         int *NullIntPtr = nullptr;
2688         bool *NullBoolPtr = nullptr;
2689         // [[p]]
2690       }
2691     };
2692   )cc";
2693   runDataflow(
2694       Code,
2695       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2696          ASTContext &ASTCtx) {
2697         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2698 
2699         auto &FLoc = getFieldLoc<RecordStorageLocation>(
2700             *Env.getThisPointeeStorageLocation(), "F", ASTCtx);
2701         auto *AVal = cast<PointerValue>(getFieldValue(&FLoc, "a", ASTCtx, Env));
2702         EXPECT_EQ(AVal,
2703                   &getValueForDecl<PointerValue>(ASTCtx, Env, "NullIntPtr"));
2704         auto *BVal = cast<PointerValue>(getFieldValue(&FLoc, "b", ASTCtx, Env));
2705         EXPECT_EQ(BVal,
2706                   &getValueForDecl<PointerValue>(ASTCtx, Env, "NullBoolPtr"));
2707       });
2708 }
2709 
2710 TEST(TransferTest, CopyConstructor) {
2711   std::string Code = R"(
2712     struct A {
2713       int Baz;
2714     };
2715 
2716     void target() {
2717       A Foo = { 1 };
2718       A Bar = Foo;
2719       // [[after_copy]]
2720       Foo.Baz = 2;
2721       // [[after_update]]
2722     }
2723   )";
2724   runDataflow(
2725       Code,
2726       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2727          ASTContext &ASTCtx) {
2728         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2729         ASSERT_THAT(FooDecl, NotNull());
2730 
2731         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2732         ASSERT_THAT(BarDecl, NotNull());
2733 
2734         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2735         ASSERT_THAT(BazDecl, NotNull());
2736 
2737         // after_copy
2738         {
2739           const Environment &Env =
2740               getEnvironmentAtAnnotation(Results, "after_copy");
2741 
2742           const auto *FooLoc =
2743               cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
2744           const auto *BarLoc =
2745               cast<RecordStorageLocation>(Env.getStorageLocation(*BarDecl));
2746 
2747           // The records compare equal.
2748           EXPECT_TRUE(recordsEqual(*FooLoc, *BarLoc, Env));
2749 
2750           // In particular, the value of `Baz` in both records is the same.
2751           const auto *FooBazVal =
2752               cast<IntegerValue>(getFieldValue(FooLoc, *BazDecl, Env));
2753           const auto *BarBazVal =
2754               cast<IntegerValue>(getFieldValue(BarLoc, *BazDecl, Env));
2755           EXPECT_EQ(FooBazVal, BarBazVal);
2756         }
2757 
2758         // after_update
2759         {
2760           const Environment &Env =
2761               getEnvironmentAtAnnotation(Results, "after_update");
2762 
2763           const auto *FooLoc =
2764               cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
2765           const auto *BarLoc =
2766               cast<RecordStorageLocation>(Env.getStorageLocation(*BarDecl));
2767 
2768           EXPECT_FALSE(recordsEqual(*FooLoc, *BarLoc, Env));
2769 
2770           const auto *FooBazVal =
2771               cast<IntegerValue>(getFieldValue(FooLoc, *BazDecl, Env));
2772           const auto *BarBazVal =
2773               cast<IntegerValue>(getFieldValue(BarLoc, *BazDecl, Env));
2774           EXPECT_NE(FooBazVal, BarBazVal);
2775         }
2776       });
2777 }
2778 
2779 TEST(TransferTest, CopyConstructorWithDefaultArgument) {
2780   std::string Code = R"(
2781     struct A {
2782       int Baz;
2783       A() = default;
2784       A(const A& a, bool def = true) { Baz = a.Baz; }
2785     };
2786 
2787     void target() {
2788       A Foo;
2789       (void)Foo.Baz;
2790       A Bar = Foo;
2791       // [[p]]
2792     }
2793   )";
2794   runDataflow(
2795       Code,
2796       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2797          ASTContext &ASTCtx) {
2798         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2799         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2800 
2801         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2802         ASSERT_THAT(FooDecl, NotNull());
2803 
2804         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2805         ASSERT_THAT(BarDecl, NotNull());
2806 
2807         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2808         ASSERT_THAT(BazDecl, NotNull());
2809 
2810         const auto *FooLoc =
2811             cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
2812         const auto *BarLoc =
2813             cast<RecordStorageLocation>(Env.getStorageLocation(*BarDecl));
2814         EXPECT_TRUE(recordsEqual(*FooLoc, *BarLoc, Env));
2815 
2816         const auto *FooBazVal =
2817             cast<IntegerValue>(getFieldValue(FooLoc, *BazDecl, Env));
2818         const auto *BarBazVal =
2819             cast<IntegerValue>(getFieldValue(BarLoc, *BazDecl, Env));
2820         EXPECT_EQ(FooBazVal, BarBazVal);
2821       });
2822 }
2823 
2824 TEST(TransferTest, CopyConstructorWithParens) {
2825   std::string Code = R"(
2826     struct A {
2827       int Baz;
2828     };
2829 
2830     void target() {
2831       A Foo;
2832       (void)Foo.Baz;
2833       A Bar((A(Foo)));
2834       // [[p]]
2835     }
2836   )";
2837   runDataflow(
2838       Code,
2839       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2840          ASTContext &ASTCtx) {
2841         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2842         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2843 
2844         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2845         ASSERT_THAT(FooDecl, NotNull());
2846 
2847         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2848         ASSERT_THAT(BarDecl, NotNull());
2849 
2850         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2851         ASSERT_THAT(BazDecl, NotNull());
2852 
2853         const auto *FooLoc =
2854             cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
2855         const auto *BarLoc =
2856             cast<RecordStorageLocation>(Env.getStorageLocation(*BarDecl));
2857         EXPECT_TRUE(recordsEqual(*FooLoc, *BarLoc, Env));
2858 
2859         const auto *FooBazVal =
2860             cast<IntegerValue>(getFieldValue(FooLoc, *BazDecl, Env));
2861         const auto *BarBazVal =
2862             cast<IntegerValue>(getFieldValue(BarLoc, *BazDecl, Env));
2863         EXPECT_EQ(FooBazVal, BarBazVal);
2864       });
2865 }
2866 
2867 TEST(TransferTest, CopyConstructorWithInitializerListAsSyntacticSugar) {
2868   std::string Code = R"(
2869   struct A {
2870     int Baz;
2871   };
2872   void target() {
2873     A Foo = {3};
2874     (void)Foo.Baz;
2875     A Bar = {A(Foo)};
2876     // [[p]]
2877   }
2878   )";
2879   runDataflow(
2880       Code,
2881       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2882          ASTContext &ASTCtx) {
2883         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2884 
2885         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2886 
2887         const auto &FooLoc =
2888             getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "Foo");
2889         const auto &BarLoc =
2890             getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "Bar");
2891 
2892         const auto *FooBazVal =
2893             cast<IntegerValue>(getFieldValue(&FooLoc, *BazDecl, Env));
2894         const auto *BarBazVal =
2895             cast<IntegerValue>(getFieldValue(&BarLoc, *BazDecl, Env));
2896         EXPECT_EQ(FooBazVal, BarBazVal);
2897       });
2898 }
2899 
2900 TEST(TransferTest, CopyConstructorArgIsRefReturnedByFunction) {
2901   // This is a crash repro.
2902   std::string Code = R"(
2903     struct S {};
2904     const S &returnsSRef();
2905     void target() {
2906       S s(returnsSRef());
2907     }
2908   )";
2909   runDataflow(
2910       Code,
2911       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2912          ASTContext &ASTCtx) {});
2913 }
2914 
2915 TEST(TransferTest, MoveConstructor) {
2916   std::string Code = R"(
2917     namespace std {
2918 
2919     template <typename T> struct remove_reference      { using type = T; };
2920     template <typename T> struct remove_reference<T&>  { using type = T; };
2921     template <typename T> struct remove_reference<T&&> { using type = T; };
2922 
2923     template <typename T>
2924     using remove_reference_t = typename remove_reference<T>::type;
2925 
2926     template <typename T>
2927     std::remove_reference_t<T>&& move(T&& x);
2928 
2929     } // namespace std
2930 
2931     struct A {
2932       int Baz;
2933     };
2934 
2935     void target() {
2936       A Foo;
2937       A Bar;
2938       (void)Foo.Baz;
2939       // [[p1]]
2940       Foo = std::move(Bar);
2941       // [[p2]]
2942     }
2943   )";
2944   runDataflow(
2945       Code,
2946       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2947          ASTContext &ASTCtx) {
2948         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
2949         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
2950         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
2951 
2952         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2953         ASSERT_THAT(FooDecl, NotNull());
2954 
2955         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2956         ASSERT_THAT(BarDecl, NotNull());
2957 
2958         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2959         ASSERT_THAT(BazDecl, NotNull());
2960 
2961         const auto *FooLoc1 =
2962             cast<RecordStorageLocation>(Env1.getStorageLocation(*FooDecl));
2963         const auto *BarLoc1 =
2964             cast<RecordStorageLocation>(Env1.getStorageLocation(*BarDecl));
2965 
2966         EXPECT_FALSE(recordsEqual(*FooLoc1, *BarLoc1, Env1));
2967 
2968         const auto *FooBazVal1 =
2969             cast<IntegerValue>(getFieldValue(FooLoc1, *BazDecl, Env1));
2970         const auto *BarBazVal1 =
2971             cast<IntegerValue>(getFieldValue(BarLoc1, *BazDecl, Env1));
2972         EXPECT_NE(FooBazVal1, BarBazVal1);
2973 
2974         const auto *FooLoc2 =
2975             cast<RecordStorageLocation>(Env2.getStorageLocation(*FooDecl));
2976         EXPECT_TRUE(recordsEqual(*FooLoc2, Env2, *BarLoc1, Env1));
2977 
2978         const auto *FooBazVal2 =
2979             cast<IntegerValue>(getFieldValue(FooLoc1, *BazDecl, Env2));
2980         EXPECT_EQ(FooBazVal2, BarBazVal1);
2981       });
2982 }
2983 
2984 TEST(TransferTest, BindTemporary) {
2985   std::string Code = R"(
2986     struct A {
2987       virtual ~A() = default;
2988 
2989       int Baz;
2990     };
2991 
2992     void target(A Foo) {
2993       int Bar = A(Foo).Baz;
2994       // [[p]]
2995     }
2996   )";
2997   runDataflow(
2998       Code,
2999       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3000          ASTContext &ASTCtx) {
3001         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3002         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3003 
3004         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3005         ASSERT_THAT(FooDecl, NotNull());
3006 
3007         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3008         ASSERT_THAT(BarDecl, NotNull());
3009 
3010         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3011         ASSERT_THAT(BazDecl, NotNull());
3012 
3013         const auto &FooLoc =
3014             *cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
3015         const auto *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
3016         EXPECT_EQ(BarVal, getFieldValue(&FooLoc, *BazDecl, Env));
3017       });
3018 }
3019 
3020 TEST(TransferTest, ResultObjectLocation) {
3021   std::string Code = R"(
3022     struct A {
3023       virtual ~A() = default;
3024     };
3025 
3026     void target() {
3027       0, A();
3028       (void)0; // [[p]]
3029     }
3030   )";
3031   using ast_matchers::binaryOperator;
3032   using ast_matchers::cxxBindTemporaryExpr;
3033   using ast_matchers::cxxTemporaryObjectExpr;
3034   using ast_matchers::exprWithCleanups;
3035   using ast_matchers::has;
3036   using ast_matchers::hasOperatorName;
3037   using ast_matchers::hasRHS;
3038   using ast_matchers::match;
3039   using ast_matchers::selectFirst;
3040   using ast_matchers::traverse;
3041   runDataflow(
3042       Code,
3043       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3044          ASTContext &ASTCtx) {
3045         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3046 
3047         // The expression `0, A()` in the code above produces the following
3048         // structure, consisting of four prvalues of record type.
3049         // `Env.getResultObjectLocation()` should return the same location for
3050         // all of these.
3051         auto MatchResult = match(
3052             traverse(TK_AsIs,
3053                      exprWithCleanups(
3054                          has(binaryOperator(
3055                                  hasOperatorName(","),
3056                                  hasRHS(cxxBindTemporaryExpr(
3057                                             has(cxxTemporaryObjectExpr().bind(
3058                                                 "toe")))
3059                                             .bind("bte")))
3060                                  .bind("comma")))
3061                          .bind("ewc")),
3062             ASTCtx);
3063         auto *TOE = selectFirst<CXXTemporaryObjectExpr>("toe", MatchResult);
3064         ASSERT_NE(TOE, nullptr);
3065         auto *Comma = selectFirst<BinaryOperator>("comma", MatchResult);
3066         ASSERT_NE(Comma, nullptr);
3067         auto *EWC = selectFirst<ExprWithCleanups>("ewc", MatchResult);
3068         ASSERT_NE(EWC, nullptr);
3069         auto *BTE = selectFirst<CXXBindTemporaryExpr>("bte", MatchResult);
3070         ASSERT_NE(BTE, nullptr);
3071 
3072         RecordStorageLocation &Loc = Env.getResultObjectLocation(*TOE);
3073         EXPECT_EQ(&Loc, &Env.getResultObjectLocation(*Comma));
3074         EXPECT_EQ(&Loc, &Env.getResultObjectLocation(*EWC));
3075         EXPECT_EQ(&Loc, &Env.getResultObjectLocation(*BTE));
3076       });
3077 }
3078 
3079 TEST(TransferTest, ResultObjectLocationForDefaultArgExpr) {
3080   std::string Code = R"(
3081     struct Inner {};
3082     struct Outer {
3083         Inner I = {};
3084     };
3085 
3086     void funcWithDefaultArg(Outer O = {});
3087     void target() {
3088       funcWithDefaultArg();
3089       // [[p]]
3090     }
3091   )";
3092 
3093   using ast_matchers::cxxDefaultArgExpr;
3094   using ast_matchers::match;
3095   using ast_matchers::selectFirst;
3096   runDataflow(
3097       Code,
3098       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3099          ASTContext &ASTCtx) {
3100         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3101 
3102         auto *DefaultArg = selectFirst<CXXDefaultArgExpr>(
3103             "default_arg",
3104             match(cxxDefaultArgExpr().bind("default_arg"), ASTCtx));
3105         ASSERT_NE(DefaultArg, nullptr);
3106 
3107         // The values for default arguments aren't modeled; we merely verify
3108         // that we can get a result object location for a default arg.
3109         Env.getResultObjectLocation(*DefaultArg);
3110       });
3111 }
3112 
3113 TEST(TransferTest, ResultObjectLocationForDefaultInitExpr) {
3114   std::string Code = R"(
3115     struct S {};
3116     struct target {
3117       target () {
3118         (void)0;
3119         // [[p]]
3120       }
3121       S s = {};
3122     };
3123   )";
3124 
3125   using ast_matchers::cxxCtorInitializer;
3126   using ast_matchers::match;
3127   using ast_matchers::selectFirst;
3128   runDataflow(
3129       Code,
3130       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3131          ASTContext &ASTCtx) {
3132         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3133 
3134         const ValueDecl *SField = findValueDecl(ASTCtx, "s");
3135 
3136         auto *CtorInit = selectFirst<CXXCtorInitializer>(
3137             "ctor_initializer",
3138             match(cxxCtorInitializer().bind("ctor_initializer"), ASTCtx));
3139         ASSERT_NE(CtorInit, nullptr);
3140 
3141         auto *DefaultInit = cast<CXXDefaultInitExpr>(CtorInit->getInit());
3142 
3143         RecordStorageLocation &Loc = Env.getResultObjectLocation(*DefaultInit);
3144 
3145         EXPECT_EQ(&Loc, Env.getThisPointeeStorageLocation()->getChild(*SField));
3146       });
3147 }
3148 
3149 // This test ensures that CXXOperatorCallExpr returning prvalues are correctly
3150 // handled by the transfer functions, especially that `getResultObjectLocation`
3151 // correctly returns a storage location for those.
3152 TEST(TransferTest, ResultObjectLocationForCXXOperatorCallExpr) {
3153   std::string Code = R"(
3154     struct A {
3155       A operator+(int);
3156     };
3157 
3158     void target() {
3159       A a;
3160       a + 3;
3161       (void)0; // [[p]]
3162     }
3163   )";
3164   using ast_matchers::cxxOperatorCallExpr;
3165   using ast_matchers::match;
3166   using ast_matchers::selectFirst;
3167   using ast_matchers::traverse;
3168   runDataflow(
3169       Code,
3170       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3171          ASTContext &ASTCtx) {
3172         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3173 
3174         auto *CallExpr = selectFirst<CXXOperatorCallExpr>(
3175             "call_expr",
3176             match(cxxOperatorCallExpr().bind("call_expr"), ASTCtx));
3177 
3178         EXPECT_NE(&Env.getResultObjectLocation(*CallExpr), nullptr);
3179       });
3180 }
3181 
3182 TEST(TransferTest, ResultObjectLocationForInitListExpr) {
3183   std::string Code = R"cc(
3184     struct Inner {};
3185 
3186     struct Outer { Inner I; };
3187 
3188     void target() {
3189       Outer O = { Inner() };
3190       // [[p]]
3191     }
3192   )cc";
3193   using ast_matchers::asString;
3194   using ast_matchers::cxxConstructExpr;
3195   using ast_matchers::hasType;
3196   using ast_matchers::match;
3197   using ast_matchers::selectFirst;
3198   using ast_matchers::traverse;
3199   runDataflow(
3200       Code,
3201       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3202          ASTContext &ASTCtx) {
3203         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3204 
3205         auto *Construct = selectFirst<CXXConstructExpr>(
3206             "construct",
3207             match(
3208                 cxxConstructExpr(hasType(asString("Inner"))).bind("construct"),
3209                 ASTCtx));
3210 
3211         EXPECT_EQ(
3212             &Env.getResultObjectLocation(*Construct),
3213             &getFieldLoc(getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "O"),
3214                          "I", ASTCtx));
3215       });
3216 }
3217 
3218 TEST(TransferTest, ResultObjectLocationForParenInitListExpr) {
3219   std::string Code = R"cc(
3220     struct Inner {};
3221 
3222     struct Outer { Inner I; };
3223 
3224     void target() {
3225       Outer O((Inner()));
3226       // [[p]]
3227     }
3228   )cc";
3229   using ast_matchers::asString;
3230   using ast_matchers::cxxConstructExpr;
3231   using ast_matchers::hasType;
3232   using ast_matchers::match;
3233   using ast_matchers::selectFirst;
3234   using ast_matchers::traverse;
3235   runDataflow(
3236       Code,
3237       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3238          ASTContext &ASTCtx) {
3239         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3240 
3241         auto *Construct = selectFirst<CXXConstructExpr>(
3242             "construct",
3243             match(
3244                 cxxConstructExpr(hasType(asString("Inner"))).bind("construct"),
3245                 ASTCtx));
3246 
3247         EXPECT_EQ(
3248             &Env.getResultObjectLocation(*Construct),
3249             &getFieldLoc(getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "O"),
3250                          "I", ASTCtx));
3251       },
3252       LangStandard::lang_cxx20);
3253 }
3254 
3255 // Check that the `std::strong_ordering` object returned by builtin `<=>` has a
3256 // correctly modeled result object location.
3257 TEST(TransferTest, ResultObjectLocationForBuiltinSpaceshipOperator) {
3258   std::string Code = R"(
3259     namespace std {
3260       // This is the minimal definition required to get
3261       // `Sema::CheckComparisonCategoryType()` to accept this fake.
3262       struct strong_ordering {
3263         enum class ordering { less, equal, greater };
3264         ordering o;
3265         static const strong_ordering less;
3266         static const strong_ordering equivalent;
3267         static const strong_ordering equal;
3268         static const strong_ordering greater;
3269       };
3270 
3271       inline constexpr strong_ordering strong_ordering::less =
3272         { strong_ordering::ordering::less };
3273       inline constexpr strong_ordering strong_ordering::equal =
3274         { strong_ordering::ordering::equal };
3275       inline constexpr strong_ordering strong_ordering::equivalent =
3276         { strong_ordering::ordering::equal };
3277       inline constexpr strong_ordering strong_ordering::greater =
3278         { strong_ordering::ordering::greater };
3279     }
3280     void target(int i, int j) {
3281       auto ordering = i <=> j;
3282       // [[p]]
3283     }
3284   )";
3285   using ast_matchers::binaryOperator;
3286   using ast_matchers::hasOperatorName;
3287   using ast_matchers::match;
3288   using ast_matchers::selectFirst;
3289   using ast_matchers::traverse;
3290   runDataflow(
3291       Code,
3292       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3293          ASTContext &ASTCtx) {
3294         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3295 
3296         auto *Spaceship = selectFirst<BinaryOperator>(
3297             "op",
3298             match(binaryOperator(hasOperatorName("<=>")).bind("op"), ASTCtx));
3299 
3300         EXPECT_EQ(
3301             &Env.getResultObjectLocation(*Spaceship),
3302             &getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "ordering"));
3303       },
3304       LangStandard::lang_cxx20);
3305 }
3306 
3307 TEST(TransferTest, ResultObjectLocationForStdInitializerListExpr) {
3308   std::string Code = R"(
3309     namespace std {
3310     template <typename T>
3311     struct initializer_list { const T *a, *b; };
3312     } // namespace std
3313 
3314     void target() {
3315       std::initializer_list<int> list = {1};
3316       // [[p]]
3317     }
3318   )";
3319 
3320   using ast_matchers::cxxStdInitializerListExpr;
3321   using ast_matchers::match;
3322   using ast_matchers::selectFirst;
3323   runDataflow(
3324       Code,
3325       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3326          ASTContext &ASTCtx) {
3327         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3328 
3329         auto *StdInitList = selectFirst<CXXStdInitializerListExpr>(
3330             "std_init_list",
3331             match(cxxStdInitializerListExpr().bind("std_init_list"), ASTCtx));
3332         ASSERT_NE(StdInitList, nullptr);
3333 
3334         EXPECT_EQ(&Env.getResultObjectLocation(*StdInitList),
3335                   &getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "list"));
3336       });
3337 }
3338 
3339 TEST(TransferTest, ResultObjectLocationForStmtExpr) {
3340   std::string Code = R"(
3341     struct S {};
3342     void target() {
3343       S s = ({ S(); });
3344       // [[p]]
3345     }
3346   )";
3347   using ast_matchers::cxxConstructExpr;
3348   using ast_matchers::match;
3349   using ast_matchers::selectFirst;
3350   using ast_matchers::traverse;
3351   runDataflow(
3352       Code,
3353       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3354          ASTContext &ASTCtx) {
3355         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3356 
3357         auto *Construct = selectFirst<CXXConstructExpr>(
3358             "construct", match(cxxConstructExpr().bind("construct"), ASTCtx));
3359 
3360         EXPECT_EQ(&Env.getResultObjectLocation(*Construct),
3361                   &getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "s"));
3362       });
3363 }
3364 
3365 TEST(TransferTest, ResultObjectLocationForBuiltinBitCastExpr) {
3366   std::string Code = R"(
3367     struct S { int i; };
3368     void target(int i) {
3369       S s = __builtin_bit_cast(S, i);
3370       // [[p]]
3371     }
3372   )";
3373   using ast_matchers::explicitCastExpr;
3374   using ast_matchers::match;
3375   using ast_matchers::selectFirst;
3376   using ast_matchers::traverse;
3377   runDataflow(
3378       Code,
3379       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3380          ASTContext &ASTCtx) {
3381         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3382 
3383         auto *BuiltinBitCast = selectFirst<BuiltinBitCastExpr>(
3384             "cast", match(explicitCastExpr().bind("cast"), ASTCtx));
3385 
3386         EXPECT_EQ(&Env.getResultObjectLocation(*BuiltinBitCast),
3387                   &getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "s"));
3388       });
3389 }
3390 
3391 TEST(TransferTest, ResultObjectLocationForAtomicExpr) {
3392   std::string Code = R"(
3393     struct S {};
3394     void target(_Atomic(S) *ptr) {
3395       S s = __c11_atomic_load(ptr, __ATOMIC_SEQ_CST);
3396       // [[p]]
3397     }
3398   )";
3399   using ast_matchers::atomicExpr;
3400   using ast_matchers::match;
3401   using ast_matchers::selectFirst;
3402   using ast_matchers::traverse;
3403   runDataflow(
3404       Code,
3405       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3406          ASTContext &ASTCtx) {
3407         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3408 
3409         auto *Atomic = selectFirst<AtomicExpr>(
3410             "atomic", match(atomicExpr().bind("atomic"), ASTCtx));
3411 
3412         EXPECT_EQ(&Env.getResultObjectLocation(*Atomic),
3413                   &getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "s"));
3414       });
3415 }
3416 
3417 TEST(TransferTest, ResultObjectLocationPropagatesThroughConditionalOperator) {
3418   std::string Code = R"(
3419     struct A {
3420       A(int);
3421     };
3422 
3423     void target(bool b) {
3424       A a = b ? A(0) : A(1);
3425       (void)0; // [[p]]
3426     }
3427   )";
3428   using ast_matchers::cxxConstructExpr;
3429   using ast_matchers::equals;
3430   using ast_matchers::hasArgument;
3431   using ast_matchers::integerLiteral;
3432   using ast_matchers::match;
3433   using ast_matchers::selectFirst;
3434   using ast_matchers::traverse;
3435   runDataflow(
3436       Code,
3437       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3438          ASTContext &ASTCtx) {
3439         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3440 
3441         auto *ConstructExpr0 = selectFirst<CXXConstructExpr>(
3442             "construct",
3443             match(cxxConstructExpr(hasArgument(0, integerLiteral(equals(0))))
3444                       .bind("construct"),
3445                   ASTCtx));
3446         auto *ConstructExpr1 = selectFirst<CXXConstructExpr>(
3447             "construct",
3448             match(cxxConstructExpr(hasArgument(0, integerLiteral(equals(1))))
3449                       .bind("construct"),
3450                   ASTCtx));
3451 
3452         auto &ALoc = getLocForDecl<StorageLocation>(ASTCtx, Env, "a");
3453         EXPECT_EQ(&Env.getResultObjectLocation(*ConstructExpr0), &ALoc);
3454         EXPECT_EQ(&Env.getResultObjectLocation(*ConstructExpr1), &ALoc);
3455       });
3456 }
3457 
3458 TEST(TransferTest, ResultObjectLocationDontVisitNestedRecordDecl) {
3459   // This is a crash repro.
3460   // We used to crash because when propagating result objects, we would visit
3461   // nested record and function declarations, but we don't model fields used
3462   // only in these.
3463   std::string Code = R"(
3464     struct S1 {};
3465     struct S2 { S1 s1; };
3466     void target() {
3467       struct Nested {
3468         void f() {
3469           S2 s2 = { S1() };
3470         }
3471       };
3472     }
3473   )";
3474   runDataflow(
3475       Code,
3476       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3477          ASTContext &ASTCtx) {});
3478 }
3479 
3480 TEST(TransferTest, ResultObjectLocationDontVisitUnevaluatedContexts) {
3481   // This is a crash repro.
3482   // We used to crash because when propagating result objects, we would visit
3483   // unevaluated contexts, but we don't model fields used only in these.
3484 
3485   auto testFunction = [](llvm::StringRef Code, llvm::StringRef TargetFun) {
3486     runDataflow(
3487         Code,
3488         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3489            ASTContext &ASTCtx) {},
3490         LangStandard::lang_gnucxx17,
3491         /* ApplyBuiltinTransfer= */ true, TargetFun);
3492   };
3493 
3494   std::string Code = R"cc(
3495     // Definitions needed for `typeid`.
3496     namespace std {
3497       class type_info {};
3498       class bad_typeid {};
3499     }  // namespace std
3500 
3501     struct S1 {};
3502     struct S2 { S1 s1; };
3503 
3504     // We test each type of unevaluated context from a different target
3505     // function. Some types of unevaluated contexts may actually cause the
3506     // field `s1` to be modeled, and we don't want this to "pollute" the tests
3507     // for the other unevaluated contexts.
3508     void decltypeTarget() {
3509         decltype(S2{}) Dummy;
3510     }
3511     void typeofTarget() {
3512         typeof(S2{}) Dummy;
3513     }
3514     void typeidTarget() {
3515 #if __has_feature(cxx_rtti)
3516         typeid(S2{});
3517 #endif
3518     }
3519     void sizeofTarget() {
3520         sizeof(S2{});
3521     }
3522     void noexceptTarget() {
3523         noexcept(S2{});
3524     }
3525   )cc";
3526 
3527   testFunction(Code, "decltypeTarget");
3528   testFunction(Code, "typeofTarget");
3529   testFunction(Code, "typeidTarget");
3530   testFunction(Code, "sizeofTarget");
3531   testFunction(Code, "noexceptTarget");
3532 }
3533 
3534 TEST(TransferTest, StaticCast) {
3535   std::string Code = R"(
3536     void target(int Foo) {
3537       int Bar = static_cast<int>(Foo);
3538       // [[p]]
3539     }
3540   )";
3541   runDataflow(
3542       Code,
3543       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3544          ASTContext &ASTCtx) {
3545         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3546         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3547 
3548         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3549         ASSERT_THAT(FooDecl, NotNull());
3550 
3551         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3552         ASSERT_THAT(BarDecl, NotNull());
3553 
3554         const auto *FooVal = Env.getValue(*FooDecl);
3555         const auto *BarVal = Env.getValue(*BarDecl);
3556         EXPECT_TRUE(isa<IntegerValue>(FooVal));
3557         EXPECT_TRUE(isa<IntegerValue>(BarVal));
3558         EXPECT_EQ(FooVal, BarVal);
3559       });
3560 }
3561 
3562 TEST(TransferTest, IntegralCast) {
3563   std::string Code = R"(
3564     void target(int Foo) {
3565       long Bar = Foo;
3566       // [[p]]
3567     }
3568   )";
3569   runDataflow(
3570       Code,
3571       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3572          ASTContext &ASTCtx) {
3573         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3574 
3575         const auto &FooVal = getValueForDecl<IntegerValue>(ASTCtx, Env, "Foo");
3576         const auto &BarVal = getValueForDecl<IntegerValue>(ASTCtx, Env, "Bar");
3577         EXPECT_EQ(&FooVal, &BarVal);
3578       });
3579 }
3580 
3581 TEST(TransferTest, IntegraltoBooleanCast) {
3582   std::string Code = R"(
3583     void target(int Foo) {
3584       bool Bar = Foo;
3585       // [[p]]
3586     }
3587   )";
3588   runDataflow(
3589       Code,
3590       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3591          ASTContext &ASTCtx) {
3592         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3593 
3594         const auto &FooVal = getValueForDecl(ASTCtx, Env, "Foo");
3595         const auto &BarVal = getValueForDecl(ASTCtx, Env, "Bar");
3596         EXPECT_TRUE(isa<IntegerValue>(FooVal));
3597         EXPECT_TRUE(isa<BoolValue>(BarVal));
3598       });
3599 }
3600 
3601 TEST(TransferTest, IntegralToBooleanCastFromBool) {
3602   std::string Code = R"(
3603     void target(bool Foo) {
3604       int Zab = Foo;
3605       bool Bar = Zab;
3606       // [[p]]
3607     }
3608   )";
3609   runDataflow(
3610       Code,
3611       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3612          ASTContext &ASTCtx) {
3613         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3614 
3615         const auto &FooVal = getValueForDecl<BoolValue>(ASTCtx, Env, "Foo");
3616         const auto &BarVal = getValueForDecl<BoolValue>(ASTCtx, Env, "Bar");
3617         EXPECT_EQ(&FooVal, &BarVal);
3618       });
3619 }
3620 
3621 TEST(TransferTest, WidenBoolValueInIntegerVariable) {
3622   // This is a crash repro.
3623   // This test sets up a case where we perform widening on an integer variable
3624   // that contains a `BoolValue` for the previous iteration and an
3625   // `IntegerValue` for the current iteration. We used to crash on this because
3626   // `widenDistinctValues()` assumed that if the previous iteration had a
3627   // `BoolValue`, the current iteration would too.
3628   // FIXME: The real fix here is to make sure we never store `BoolValue`s in
3629   // integer variables; see also the comment in `widenDistinctValues()`.
3630   std::string Code = R"cc(
3631     struct S {
3632       int i;
3633       S *next;
3634     };
3635     void target(S *s) {
3636       for (; s; s = s->next)
3637         s->i = false;
3638     }
3639   )cc";
3640   runDataflow(Code,
3641               [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &,
3642                  ASTContext &) {});
3643 }
3644 
3645 TEST(TransferTest, NullToPointerCast) {
3646   std::string Code = R"(
3647     using my_nullptr_t = decltype(nullptr);
3648     struct Baz {};
3649     void target() {
3650       int *FooX = nullptr;
3651       int *FooY = nullptr;
3652       bool **Bar = nullptr;
3653       Baz *Baz = nullptr;
3654       my_nullptr_t Null = 0;
3655       // [[p]]
3656     }
3657   )";
3658   runDataflow(
3659       Code,
3660       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3661          ASTContext &ASTCtx) {
3662         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3663         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3664 
3665         const ValueDecl *FooXDecl = findValueDecl(ASTCtx, "FooX");
3666         ASSERT_THAT(FooXDecl, NotNull());
3667 
3668         const ValueDecl *FooYDecl = findValueDecl(ASTCtx, "FooY");
3669         ASSERT_THAT(FooYDecl, NotNull());
3670 
3671         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3672         ASSERT_THAT(BarDecl, NotNull());
3673 
3674         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3675         ASSERT_THAT(BazDecl, NotNull());
3676 
3677         const ValueDecl *NullDecl = findValueDecl(ASTCtx, "Null");
3678         ASSERT_THAT(NullDecl, NotNull());
3679 
3680         const auto *FooXVal = cast<PointerValue>(Env.getValue(*FooXDecl));
3681         const auto *FooYVal = cast<PointerValue>(Env.getValue(*FooYDecl));
3682         const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl));
3683         const auto *BazVal = cast<PointerValue>(Env.getValue(*BazDecl));
3684         const auto *NullVal = cast<PointerValue>(Env.getValue(*NullDecl));
3685 
3686         EXPECT_EQ(FooXVal, FooYVal);
3687         EXPECT_NE(FooXVal, BarVal);
3688         EXPECT_NE(FooXVal, BazVal);
3689         EXPECT_NE(BarVal, BazVal);
3690 
3691         const StorageLocation &FooPointeeLoc = FooXVal->getPointeeLoc();
3692         EXPECT_TRUE(isa<ScalarStorageLocation>(FooPointeeLoc));
3693         EXPECT_THAT(Env.getValue(FooPointeeLoc), IsNull());
3694 
3695         const StorageLocation &BarPointeeLoc = BarVal->getPointeeLoc();
3696         EXPECT_TRUE(isa<ScalarStorageLocation>(BarPointeeLoc));
3697         EXPECT_THAT(Env.getValue(BarPointeeLoc), IsNull());
3698 
3699         const StorageLocation &BazPointeeLoc = BazVal->getPointeeLoc();
3700         EXPECT_TRUE(isa<RecordStorageLocation>(BazPointeeLoc));
3701         EXPECT_EQ(BazVal, &Env.fork().getOrCreateNullPointerValue(
3702                               BazPointeeLoc.getType()));
3703 
3704         const StorageLocation &NullPointeeLoc = NullVal->getPointeeLoc();
3705         EXPECT_TRUE(isa<ScalarStorageLocation>(NullPointeeLoc));
3706         EXPECT_THAT(Env.getValue(NullPointeeLoc), IsNull());
3707       });
3708 }
3709 
3710 TEST(TransferTest, PointerToMemberVariable) {
3711   std::string Code = R"(
3712     struct S {
3713       int i;
3714     };
3715     void target() {
3716       int S::*MemberPointer = &S::i;
3717       // [[p]]
3718     }
3719   )";
3720   runDataflow(
3721       Code,
3722       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3723          ASTContext &ASTCtx) {
3724         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3725 
3726         const ValueDecl *MemberPointerDecl =
3727             findValueDecl(ASTCtx, "MemberPointer");
3728         ASSERT_THAT(MemberPointerDecl, NotNull());
3729         ASSERT_THAT(Env.getValue(*MemberPointerDecl), IsNull());
3730       });
3731 }
3732 
3733 TEST(TransferTest, PointerToMemberFunction) {
3734   std::string Code = R"(
3735     struct S {
3736       void Method();
3737     };
3738     void target() {
3739       void (S::*MemberPointer)() = &S::Method;
3740       // [[p]]
3741     }
3742   )";
3743   runDataflow(
3744       Code,
3745       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3746          ASTContext &ASTCtx) {
3747         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3748 
3749         const ValueDecl *MemberPointerDecl =
3750             findValueDecl(ASTCtx, "MemberPointer");
3751         ASSERT_THAT(MemberPointerDecl, NotNull());
3752         ASSERT_THAT(Env.getValue(*MemberPointerDecl), IsNull());
3753       });
3754 }
3755 
3756 TEST(TransferTest, NullToMemberPointerCast) {
3757   std::string Code = R"(
3758     struct Foo {};
3759     void target() {
3760       int Foo::*MemberPointer = nullptr;
3761       // [[p]]
3762     }
3763   )";
3764   runDataflow(
3765       Code,
3766       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3767          ASTContext &ASTCtx) {
3768         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3769         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3770 
3771         const ValueDecl *MemberPointerDecl =
3772             findValueDecl(ASTCtx, "MemberPointer");
3773         ASSERT_THAT(MemberPointerDecl, NotNull());
3774         ASSERT_THAT(Env.getValue(*MemberPointerDecl), IsNull());
3775       });
3776 }
3777 
3778 TEST(TransferTest, AddrOfValue) {
3779   std::string Code = R"(
3780     void target() {
3781       int Foo;
3782       int *Bar = &Foo;
3783       // [[p]]
3784     }
3785   )";
3786   runDataflow(
3787       Code,
3788       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3789          ASTContext &ASTCtx) {
3790         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3791         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3792 
3793         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3794         ASSERT_THAT(FooDecl, NotNull());
3795 
3796         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3797         ASSERT_THAT(BarDecl, NotNull());
3798 
3799         const auto *FooLoc =
3800             cast<ScalarStorageLocation>(Env.getStorageLocation(*FooDecl));
3801         const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl));
3802         EXPECT_EQ(&BarVal->getPointeeLoc(), FooLoc);
3803       });
3804 }
3805 
3806 TEST(TransferTest, AddrOfReference) {
3807   std::string Code = R"(
3808     void target(int *Foo) {
3809       int *Bar = &(*Foo);
3810       // [[p]]
3811     }
3812   )";
3813   runDataflow(
3814       Code,
3815       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3816          ASTContext &ASTCtx) {
3817         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3818         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3819 
3820         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3821         ASSERT_THAT(FooDecl, NotNull());
3822 
3823         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3824         ASSERT_THAT(BarDecl, NotNull());
3825 
3826         const auto *FooVal = cast<PointerValue>(Env.getValue(*FooDecl));
3827         const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl));
3828         EXPECT_EQ(&BarVal->getPointeeLoc(), &FooVal->getPointeeLoc());
3829       });
3830 }
3831 
3832 TEST(TransferTest, Preincrement) {
3833   std::string Code = R"(
3834     void target(int I) {
3835       int &IRef = ++I;
3836       // [[p]]
3837     }
3838   )";
3839   runDataflow(
3840       Code,
3841       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3842          ASTContext &ASTCtx) {
3843         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3844 
3845         EXPECT_EQ(&getLocForDecl(ASTCtx, Env, "IRef"),
3846                   &getLocForDecl(ASTCtx, Env, "I"));
3847       });
3848 }
3849 
3850 TEST(TransferTest, Postincrement) {
3851   std::string Code = R"(
3852     void target(int I) {
3853       int OldVal = I++;
3854       // [[p]]
3855     }
3856   )";
3857   runDataflow(
3858       Code,
3859       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3860          ASTContext &ASTCtx) {
3861         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3862 
3863         EXPECT_EQ(&getValueForDecl(ASTCtx, Env, "OldVal"),
3864                   &getValueForDecl(ASTCtx, Env, "I"));
3865       });
3866 }
3867 
3868 // We test just one of the compound assignment operators because we know the
3869 // code for propagating the storage location is shared among all of them.
3870 TEST(TransferTest, AddAssign) {
3871   std::string Code = R"(
3872     void target(int I) {
3873       int &IRef = (I += 1);
3874       // [[p]]
3875     }
3876   )";
3877   runDataflow(
3878       Code,
3879       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3880          ASTContext &ASTCtx) {
3881         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3882 
3883         EXPECT_EQ(&getLocForDecl(ASTCtx, Env, "IRef"),
3884                   &getLocForDecl(ASTCtx, Env, "I"));
3885       });
3886 }
3887 
3888 TEST(TransferTest, CannotAnalyzeFunctionTemplate) {
3889   std::string Code = R"(
3890     template <typename T>
3891     void target() {}
3892   )";
3893   ASSERT_THAT_ERROR(
3894       checkDataflowWithNoopAnalysis(Code),
3895       llvm::FailedWithMessage("Cannot analyze templated declarations"));
3896 }
3897 
3898 TEST(TransferTest, CannotAnalyzeMethodOfClassTemplate) {
3899   std::string Code = R"(
3900     template <typename T>
3901     struct A {
3902       void target() {}
3903     };
3904   )";
3905   ASSERT_THAT_ERROR(
3906       checkDataflowWithNoopAnalysis(Code),
3907       llvm::FailedWithMessage("Cannot analyze templated declarations"));
3908 }
3909 
3910 TEST(TransferTest, VarDeclInitAssignConditionalOperator) {
3911   std::string Code = R"(
3912     struct A {
3913       int i;
3914     };
3915 
3916     void target(A Foo, A Bar, bool Cond) {
3917       A Baz = Cond ?  A(Foo) : A(Bar);
3918       // Make sure A::i is modeled.
3919       Baz.i;
3920       /*[[p]]*/
3921     }
3922   )";
3923   runDataflow(
3924       Code,
3925       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3926          ASTContext &ASTCtx) {
3927         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3928 
3929         auto *FooIVal = cast<IntegerValue>(getFieldValue(
3930             &getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "Foo"), "i",
3931             ASTCtx, Env));
3932         auto *BarIVal = cast<IntegerValue>(getFieldValue(
3933             &getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "Bar"), "i",
3934             ASTCtx, Env));
3935         auto *BazIVal = cast<IntegerValue>(getFieldValue(
3936             &getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "Baz"), "i",
3937             ASTCtx, Env));
3938 
3939         EXPECT_NE(BazIVal, FooIVal);
3940         EXPECT_NE(BazIVal, BarIVal);
3941       });
3942 }
3943 
3944 TEST(TransferTest, VarDeclInDoWhile) {
3945   std::string Code = R"(
3946     void target(int *Foo) {
3947       do {
3948         int Bar = *Foo;
3949         // [[in_loop]]
3950       } while (false);
3951       (void)0;
3952       // [[after_loop]]
3953     }
3954   )";
3955   runDataflow(
3956       Code,
3957       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3958          ASTContext &ASTCtx) {
3959         const Environment &EnvInLoop =
3960             getEnvironmentAtAnnotation(Results, "in_loop");
3961         const Environment &EnvAfterLoop =
3962             getEnvironmentAtAnnotation(Results, "after_loop");
3963 
3964         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3965         ASSERT_THAT(FooDecl, NotNull());
3966 
3967         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3968         ASSERT_THAT(BarDecl, NotNull());
3969 
3970         const auto *FooVal =
3971             cast<PointerValue>(EnvAfterLoop.getValue(*FooDecl));
3972         const auto *FooPointeeVal =
3973             cast<IntegerValue>(EnvAfterLoop.getValue(FooVal->getPointeeLoc()));
3974 
3975         const auto *BarVal = cast<IntegerValue>(EnvInLoop.getValue(*BarDecl));
3976         EXPECT_EQ(BarVal, FooPointeeVal);
3977 
3978         ASSERT_THAT(EnvAfterLoop.getValue(*BarDecl), IsNull());
3979       });
3980 }
3981 
3982 TEST(TransferTest, UnreachableAfterWhileTrue) {
3983   std::string Code = R"(
3984     void target() {
3985       while (true) {}
3986       (void)0;
3987       /*[[p]]*/
3988     }
3989   )";
3990   runDataflow(
3991       Code,
3992       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3993          ASTContext &ASTCtx) {
3994         // The node after the while-true is pruned because it is trivially
3995         // known to be unreachable.
3996         ASSERT_TRUE(Results.empty());
3997       });
3998 }
3999 
4000 TEST(TransferTest, AggregateInitialization) {
4001   std::string BracesCode = R"(
4002     struct A {
4003       int Foo;
4004     };
4005 
4006     struct B {
4007       int Bar;
4008       A Baz;
4009       int Qux;
4010     };
4011 
4012     void target(int BarArg, int FooArg, int QuxArg) {
4013       B Quux{BarArg, {FooArg}, QuxArg};
4014       B OtherB;
4015       /*[[p]]*/
4016     }
4017   )";
4018   std::string BraceElisionCode = R"(
4019     struct A {
4020       int Foo;
4021     };
4022 
4023     struct B {
4024       int Bar;
4025       A Baz;
4026       int Qux;
4027     };
4028 
4029     void target(int BarArg, int FooArg, int QuxArg) {
4030       B Quux = {BarArg, FooArg, QuxArg};
4031       B OtherB;
4032       /*[[p]]*/
4033     }
4034   )";
4035   for (const std::string &Code : {BracesCode, BraceElisionCode}) {
4036     runDataflow(
4037         Code,
4038         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4039            ASTContext &ASTCtx) {
4040           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4041           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4042 
4043           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4044           ASSERT_THAT(FooDecl, NotNull());
4045 
4046           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4047           ASSERT_THAT(BarDecl, NotNull());
4048 
4049           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4050           ASSERT_THAT(BazDecl, NotNull());
4051 
4052           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
4053           ASSERT_THAT(QuxDecl, NotNull());
4054 
4055           const ValueDecl *FooArgDecl = findValueDecl(ASTCtx, "FooArg");
4056           ASSERT_THAT(FooArgDecl, NotNull());
4057 
4058           const ValueDecl *BarArgDecl = findValueDecl(ASTCtx, "BarArg");
4059           ASSERT_THAT(BarArgDecl, NotNull());
4060 
4061           const ValueDecl *QuxArgDecl = findValueDecl(ASTCtx, "QuxArg");
4062           ASSERT_THAT(QuxArgDecl, NotNull());
4063 
4064           const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux");
4065           ASSERT_THAT(QuuxDecl, NotNull());
4066 
4067           const auto *FooArgVal = cast<IntegerValue>(Env.getValue(*FooArgDecl));
4068           const auto *BarArgVal = cast<IntegerValue>(Env.getValue(*BarArgDecl));
4069           const auto *QuxArgVal = cast<IntegerValue>(Env.getValue(*QuxArgDecl));
4070 
4071           const auto &QuuxLoc =
4072               *cast<RecordStorageLocation>(Env.getStorageLocation(*QuuxDecl));
4073           const auto &BazLoc =
4074               *cast<RecordStorageLocation>(QuuxLoc.getChild(*BazDecl));
4075 
4076           EXPECT_EQ(getFieldValue(&QuuxLoc, *BarDecl, Env), BarArgVal);
4077           EXPECT_EQ(getFieldValue(&BazLoc, *FooDecl, Env), FooArgVal);
4078           EXPECT_EQ(getFieldValue(&QuuxLoc, *QuxDecl, Env), QuxArgVal);
4079 
4080           // Check that fields initialized in an initializer list are always
4081           // modeled in other instances of the same type.
4082           const auto &OtherBLoc =
4083               getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "OtherB");
4084           EXPECT_THAT(OtherBLoc.getChild(*BarDecl), NotNull());
4085           EXPECT_THAT(OtherBLoc.getChild(*BazDecl), NotNull());
4086           EXPECT_THAT(OtherBLoc.getChild(*QuxDecl), NotNull());
4087         });
4088   }
4089 }
4090 
4091 TEST(TransferTest, AggregateInitializationReferenceField) {
4092   std::string Code = R"(
4093     struct S {
4094       int &RefField;
4095     };
4096 
4097     void target(int i) {
4098       S s = { i };
4099       /*[[p]]*/
4100     }
4101   )";
4102   runDataflow(
4103       Code,
4104       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4105          ASTContext &ASTCtx) {
4106         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4107 
4108         const ValueDecl *RefFieldDecl = findValueDecl(ASTCtx, "RefField");
4109 
4110         auto &ILoc = getLocForDecl<StorageLocation>(ASTCtx, Env, "i");
4111         auto &SLoc = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "s");
4112 
4113         EXPECT_EQ(SLoc.getChild(*RefFieldDecl), &ILoc);
4114       });
4115 }
4116 
4117 TEST(TransferTest, AggregateInitialization_NotExplicitlyInitializedField) {
4118   std::string Code = R"(
4119     struct S {
4120       int i1;
4121       int i2;
4122     };
4123 
4124     void target(int i) {
4125       S s = { i };
4126       /*[[p]]*/
4127     }
4128   )";
4129   runDataflow(
4130       Code,
4131       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4132          ASTContext &ASTCtx) {
4133         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4134 
4135         const ValueDecl *I1FieldDecl = findValueDecl(ASTCtx, "i1");
4136         const ValueDecl *I2FieldDecl = findValueDecl(ASTCtx, "i2");
4137 
4138         auto &SLoc = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "s");
4139 
4140         auto &IValue = getValueForDecl<IntegerValue>(ASTCtx, Env, "i");
4141         auto &I1Value =
4142             *cast<IntegerValue>(getFieldValue(&SLoc, *I1FieldDecl, Env));
4143         EXPECT_EQ(&I1Value, &IValue);
4144         auto &I2Value =
4145             *cast<IntegerValue>(getFieldValue(&SLoc, *I2FieldDecl, Env));
4146         EXPECT_NE(&I2Value, &IValue);
4147       });
4148 }
4149 
4150 TEST(TransferTest, AggregateInitializationFunctionPointer) {
4151   // This is a repro for an assertion failure.
4152   // nullptr takes on the type of a const function pointer, but its type was
4153   // asserted to be equal to the *unqualified* type of Field, which no longer
4154   // included the const.
4155   std::string Code = R"(
4156     struct S {
4157       void (*const Field)();
4158     };
4159 
4160     void target() {
4161       S s{nullptr};
4162     }
4163   )";
4164   runDataflow(
4165       Code,
4166       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4167          ASTContext &ASTCtx) {});
4168 }
4169 
4170 TEST(TransferTest, AssignToUnionMember) {
4171   std::string Code = R"(
4172     union A {
4173       int Foo;
4174     };
4175 
4176     void target(int Bar) {
4177       A Baz;
4178       Baz.Foo = Bar;
4179       // [[p]]
4180     }
4181   )";
4182   runDataflow(
4183       Code,
4184       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4185          ASTContext &ASTCtx) {
4186         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4187         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4188 
4189         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4190         ASSERT_THAT(BazDecl, NotNull());
4191         ASSERT_TRUE(BazDecl->getType()->isUnionType());
4192 
4193         auto BazFields = BazDecl->getType()->getAsRecordDecl()->fields();
4194         FieldDecl *FooDecl = nullptr;
4195         for (FieldDecl *Field : BazFields) {
4196           if (Field->getNameAsString() == "Foo") {
4197             FooDecl = Field;
4198           } else {
4199             FAIL() << "Unexpected field: " << Field->getNameAsString();
4200           }
4201         }
4202         ASSERT_THAT(FooDecl, NotNull());
4203 
4204         const auto *BazLoc = dyn_cast_or_null<RecordStorageLocation>(
4205             Env.getStorageLocation(*BazDecl));
4206         ASSERT_THAT(BazLoc, NotNull());
4207 
4208         const auto *FooVal =
4209             cast<IntegerValue>(getFieldValue(BazLoc, *FooDecl, Env));
4210 
4211         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4212         ASSERT_THAT(BarDecl, NotNull());
4213         const auto *BarLoc = Env.getStorageLocation(*BarDecl);
4214         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
4215 
4216         EXPECT_EQ(Env.getValue(*BarLoc), FooVal);
4217       });
4218 }
4219 
4220 TEST(TransferTest, AssignFromBoolLiteral) {
4221   std::string Code = R"(
4222     void target() {
4223       bool Foo = true;
4224       bool Bar = false;
4225       // [[p]]
4226     }
4227   )";
4228   runDataflow(
4229       Code,
4230       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4231          ASTContext &ASTCtx) {
4232         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4233         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4234 
4235         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4236         ASSERT_THAT(FooDecl, NotNull());
4237 
4238         const auto *FooVal =
4239             dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
4240         ASSERT_THAT(FooVal, NotNull());
4241 
4242         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4243         ASSERT_THAT(BarDecl, NotNull());
4244 
4245         const auto *BarVal =
4246             dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
4247         ASSERT_THAT(BarVal, NotNull());
4248 
4249         EXPECT_EQ(FooVal, &Env.getBoolLiteralValue(true));
4250         EXPECT_EQ(BarVal, &Env.getBoolLiteralValue(false));
4251       });
4252 }
4253 
4254 TEST(TransferTest, AssignFromCompositeBoolExpression) {
4255   {
4256     std::string Code = R"(
4257     void target(bool Foo, bool Bar, bool Qux) {
4258       bool Baz = (Foo) && (Bar || Qux);
4259       // [[p]]
4260     }
4261   )";
4262     runDataflow(
4263         Code,
4264         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4265            ASTContext &ASTCtx) {
4266           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4267           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4268 
4269           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4270           ASSERT_THAT(FooDecl, NotNull());
4271 
4272           const auto *FooVal =
4273               dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
4274           ASSERT_THAT(FooVal, NotNull());
4275 
4276           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4277           ASSERT_THAT(BarDecl, NotNull());
4278 
4279           const auto *BarVal =
4280               dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
4281           ASSERT_THAT(BarVal, NotNull());
4282 
4283           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
4284           ASSERT_THAT(QuxDecl, NotNull());
4285 
4286           const auto *QuxVal =
4287               dyn_cast_or_null<BoolValue>(Env.getValue(*QuxDecl));
4288           ASSERT_THAT(QuxVal, NotNull());
4289 
4290           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4291           ASSERT_THAT(BazDecl, NotNull());
4292 
4293           const auto *BazVal =
4294               dyn_cast_or_null<BoolValue>(Env.getValue(*BazDecl));
4295           ASSERT_THAT(BazVal, NotNull());
4296           auto &A = Env.arena();
4297           EXPECT_EQ(&BazVal->formula(),
4298                     &A.makeAnd(FooVal->formula(),
4299                                A.makeOr(BarVal->formula(), QuxVal->formula())));
4300         });
4301   }
4302 
4303   {
4304     std::string Code = R"(
4305     void target(bool Foo, bool Bar, bool Qux) {
4306       bool Baz = (Foo && Qux) || (Bar);
4307       // [[p]]
4308     }
4309   )";
4310     runDataflow(
4311         Code,
4312         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4313            ASTContext &ASTCtx) {
4314           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4315           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4316 
4317           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4318           ASSERT_THAT(FooDecl, NotNull());
4319 
4320           const auto *FooVal =
4321               dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
4322           ASSERT_THAT(FooVal, NotNull());
4323 
4324           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4325           ASSERT_THAT(BarDecl, NotNull());
4326 
4327           const auto *BarVal =
4328               dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
4329           ASSERT_THAT(BarVal, NotNull());
4330 
4331           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
4332           ASSERT_THAT(QuxDecl, NotNull());
4333 
4334           const auto *QuxVal =
4335               dyn_cast_or_null<BoolValue>(Env.getValue(*QuxDecl));
4336           ASSERT_THAT(QuxVal, NotNull());
4337 
4338           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4339           ASSERT_THAT(BazDecl, NotNull());
4340 
4341           const auto *BazVal =
4342               dyn_cast_or_null<BoolValue>(Env.getValue(*BazDecl));
4343           ASSERT_THAT(BazVal, NotNull());
4344           auto &A = Env.arena();
4345           EXPECT_EQ(&BazVal->formula(),
4346                     &A.makeOr(A.makeAnd(FooVal->formula(), QuxVal->formula()),
4347                               BarVal->formula()));
4348         });
4349   }
4350 
4351   {
4352     std::string Code = R"(
4353       void target(bool A, bool B, bool C, bool D) {
4354         bool Foo = ((A && B) && C) && D;
4355         // [[p]]
4356       }
4357     )";
4358     runDataflow(
4359         Code,
4360         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4361            ASTContext &ASTCtx) {
4362           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4363           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4364 
4365           const ValueDecl *ADecl = findValueDecl(ASTCtx, "A");
4366           ASSERT_THAT(ADecl, NotNull());
4367 
4368           const auto *AVal = dyn_cast_or_null<BoolValue>(Env.getValue(*ADecl));
4369           ASSERT_THAT(AVal, NotNull());
4370 
4371           const ValueDecl *BDecl = findValueDecl(ASTCtx, "B");
4372           ASSERT_THAT(BDecl, NotNull());
4373 
4374           const auto *BVal = dyn_cast_or_null<BoolValue>(Env.getValue(*BDecl));
4375           ASSERT_THAT(BVal, NotNull());
4376 
4377           const ValueDecl *CDecl = findValueDecl(ASTCtx, "C");
4378           ASSERT_THAT(CDecl, NotNull());
4379 
4380           const auto *CVal = dyn_cast_or_null<BoolValue>(Env.getValue(*CDecl));
4381           ASSERT_THAT(CVal, NotNull());
4382 
4383           const ValueDecl *DDecl = findValueDecl(ASTCtx, "D");
4384           ASSERT_THAT(DDecl, NotNull());
4385 
4386           const auto *DVal = dyn_cast_or_null<BoolValue>(Env.getValue(*DDecl));
4387           ASSERT_THAT(DVal, NotNull());
4388 
4389           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4390           ASSERT_THAT(FooDecl, NotNull());
4391 
4392           const auto *FooVal =
4393               dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
4394           ASSERT_THAT(FooVal, NotNull());
4395           auto &A = Env.arena();
4396           EXPECT_EQ(
4397               &FooVal->formula(),
4398               &A.makeAnd(A.makeAnd(A.makeAnd(AVal->formula(), BVal->formula()),
4399                                    CVal->formula()),
4400                          DVal->formula()));
4401         });
4402   }
4403 }
4404 
4405 TEST(TransferTest, AssignFromBoolNegation) {
4406   std::string Code = R"(
4407     void target() {
4408       bool Foo = true;
4409       bool Bar = !(Foo);
4410       // [[p]]
4411     }
4412   )";
4413   runDataflow(
4414       Code,
4415       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4416          ASTContext &ASTCtx) {
4417         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4418         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4419 
4420         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4421         ASSERT_THAT(FooDecl, NotNull());
4422 
4423         const auto *FooVal =
4424             dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
4425         ASSERT_THAT(FooVal, NotNull());
4426 
4427         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4428         ASSERT_THAT(BarDecl, NotNull());
4429 
4430         const auto *BarVal =
4431             dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
4432         ASSERT_THAT(BarVal, NotNull());
4433         auto &A = Env.arena();
4434         EXPECT_EQ(&BarVal->formula(), &A.makeNot(FooVal->formula()));
4435       });
4436 }
4437 
4438 TEST(TransferTest, BuiltinExpect) {
4439   std::string Code = R"(
4440     void target(long Foo) {
4441       long Bar = __builtin_expect(Foo, true);
4442       /*[[p]]*/
4443     }
4444   )";
4445   runDataflow(
4446       Code,
4447       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4448          ASTContext &ASTCtx) {
4449         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4450         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4451 
4452         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4453         ASSERT_THAT(FooDecl, NotNull());
4454 
4455         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4456         ASSERT_THAT(BarDecl, NotNull());
4457 
4458         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
4459       });
4460 }
4461 
4462 // `__builtin_expect` takes and returns a `long` argument, so other types
4463 // involve casts. This verifies that we identify the input and output in that
4464 // case.
4465 TEST(TransferTest, BuiltinExpectBoolArg) {
4466   std::string Code = R"(
4467     void target(bool Foo) {
4468       bool Bar = __builtin_expect(Foo, true);
4469       /*[[p]]*/
4470     }
4471   )";
4472   runDataflow(
4473       Code,
4474       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4475          ASTContext &ASTCtx) {
4476         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4477         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4478 
4479         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4480         ASSERT_THAT(FooDecl, NotNull());
4481 
4482         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4483         ASSERT_THAT(BarDecl, NotNull());
4484 
4485         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
4486       });
4487 }
4488 
4489 TEST(TransferTest, BuiltinUnreachable) {
4490   std::string Code = R"(
4491     void target(bool Foo) {
4492       bool Bar = false;
4493       if (Foo)
4494         Bar = Foo;
4495       else
4496         __builtin_unreachable();
4497       (void)0;
4498       /*[[p]]*/
4499     }
4500   )";
4501   runDataflow(
4502       Code,
4503       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4504          ASTContext &ASTCtx) {
4505         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4506         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4507 
4508         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4509         ASSERT_THAT(FooDecl, NotNull());
4510 
4511         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4512         ASSERT_THAT(BarDecl, NotNull());
4513 
4514         // `__builtin_unreachable` promises that the code is
4515         // unreachable, so the compiler treats the "then" branch as the
4516         // only possible predecessor of this statement.
4517         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
4518       });
4519 }
4520 
4521 TEST(TransferTest, BuiltinTrap) {
4522   std::string Code = R"(
4523     void target(bool Foo) {
4524       bool Bar = false;
4525       if (Foo)
4526         Bar = Foo;
4527       else
4528         __builtin_trap();
4529       (void)0;
4530       /*[[p]]*/
4531     }
4532   )";
4533   runDataflow(
4534       Code,
4535       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4536          ASTContext &ASTCtx) {
4537         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4538         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4539 
4540         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4541         ASSERT_THAT(FooDecl, NotNull());
4542 
4543         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4544         ASSERT_THAT(BarDecl, NotNull());
4545 
4546         // `__builtin_trap` ensures program termination, so only the
4547         // "then" branch is a predecessor of this statement.
4548         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
4549       });
4550 }
4551 
4552 TEST(TransferTest, BuiltinDebugTrap) {
4553   std::string Code = R"(
4554     void target(bool Foo) {
4555       bool Bar = false;
4556       if (Foo)
4557         Bar = Foo;
4558       else
4559         __builtin_debugtrap();
4560       (void)0;
4561       /*[[p]]*/
4562     }
4563   )";
4564   runDataflow(
4565       Code,
4566       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4567          ASTContext &ASTCtx) {
4568         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4569         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4570 
4571         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4572         ASSERT_THAT(FooDecl, NotNull());
4573 
4574         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4575         ASSERT_THAT(BarDecl, NotNull());
4576 
4577         // `__builtin_debugtrap` doesn't ensure program termination.
4578         EXPECT_NE(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
4579       });
4580 }
4581 
4582 TEST(TransferTest, StaticIntSingleVarDecl) {
4583   std::string Code = R"(
4584     void target() {
4585       static int Foo;
4586       // [[p]]
4587     }
4588   )";
4589   runDataflow(
4590       Code,
4591       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4592          ASTContext &ASTCtx) {
4593         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4594         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4595 
4596         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4597         ASSERT_THAT(FooDecl, NotNull());
4598 
4599         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
4600         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
4601 
4602         const Value *FooVal = Env.getValue(*FooLoc);
4603         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
4604       });
4605 }
4606 
4607 TEST(TransferTest, StaticIntGroupVarDecl) {
4608   std::string Code = R"(
4609     void target() {
4610       static int Foo, Bar;
4611       (void)0;
4612       // [[p]]
4613     }
4614   )";
4615   runDataflow(
4616       Code,
4617       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4618          ASTContext &ASTCtx) {
4619         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4620         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4621 
4622         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4623         ASSERT_THAT(FooDecl, NotNull());
4624 
4625         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4626         ASSERT_THAT(BarDecl, NotNull());
4627 
4628         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
4629         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
4630 
4631         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
4632         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
4633 
4634         const Value *FooVal = Env.getValue(*FooLoc);
4635         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
4636 
4637         const Value *BarVal = Env.getValue(*BarLoc);
4638         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
4639 
4640         EXPECT_NE(FooVal, BarVal);
4641       });
4642 }
4643 
4644 TEST(TransferTest, GlobalIntVarDecl) {
4645   std::string Code = R"(
4646     static int Foo;
4647 
4648     void target() {
4649       int Bar = Foo;
4650       int Baz = Foo;
4651       // [[p]]
4652     }
4653   )";
4654   runDataflow(
4655       Code,
4656       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4657          ASTContext &ASTCtx) {
4658         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4659         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4660 
4661         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4662         ASSERT_THAT(BarDecl, NotNull());
4663 
4664         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4665         ASSERT_THAT(BazDecl, NotNull());
4666 
4667         const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
4668         const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl));
4669         EXPECT_EQ(BarVal, BazVal);
4670       });
4671 }
4672 
4673 TEST(TransferTest, StaticMemberIntVarDecl) {
4674   std::string Code = R"(
4675     struct A {
4676       static int Foo;
4677     };
4678 
4679     void target(A a) {
4680       int Bar = a.Foo;
4681       int Baz = a.Foo;
4682       // [[p]]
4683     }
4684   )";
4685   runDataflow(
4686       Code,
4687       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4688          ASTContext &ASTCtx) {
4689         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4690         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4691 
4692         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4693         ASSERT_THAT(BarDecl, NotNull());
4694 
4695         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4696         ASSERT_THAT(BazDecl, NotNull());
4697 
4698         const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
4699         const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl));
4700         EXPECT_EQ(BarVal, BazVal);
4701       });
4702 }
4703 
4704 TEST(TransferTest, StaticMemberRefVarDecl) {
4705   std::string Code = R"(
4706     struct A {
4707       static int &Foo;
4708     };
4709 
4710     void target(A a) {
4711       int Bar = a.Foo;
4712       int Baz = a.Foo;
4713       // [[p]]
4714     }
4715   )";
4716   runDataflow(
4717       Code,
4718       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4719          ASTContext &ASTCtx) {
4720         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4721         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4722 
4723         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4724         ASSERT_THAT(BarDecl, NotNull());
4725 
4726         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4727         ASSERT_THAT(BazDecl, NotNull());
4728 
4729         const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
4730         const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl));
4731         EXPECT_EQ(BarVal, BazVal);
4732       });
4733 }
4734 
4735 TEST(TransferTest, AssignMemberBeforeCopy) {
4736   std::string Code = R"(
4737     struct A {
4738       int Foo;
4739     };
4740 
4741     void target() {
4742       A A1;
4743       A A2;
4744       int Bar;
4745       A1.Foo = Bar;
4746       A2 = A1;
4747       // [[p]]
4748     }
4749   )";
4750   runDataflow(
4751       Code,
4752       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4753          ASTContext &ASTCtx) {
4754         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4755         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4756 
4757         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4758         ASSERT_THAT(FooDecl, NotNull());
4759 
4760         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4761         ASSERT_THAT(BarDecl, NotNull());
4762 
4763         const ValueDecl *A1Decl = findValueDecl(ASTCtx, "A1");
4764         ASSERT_THAT(A1Decl, NotNull());
4765 
4766         const ValueDecl *A2Decl = findValueDecl(ASTCtx, "A2");
4767         ASSERT_THAT(A2Decl, NotNull());
4768 
4769         const auto *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
4770 
4771         const auto &A2Loc =
4772             *cast<RecordStorageLocation>(Env.getStorageLocation(*A2Decl));
4773         EXPECT_EQ(getFieldValue(&A2Loc, *FooDecl, Env), BarVal);
4774       });
4775 }
4776 
4777 TEST(TransferTest, BooleanEquality) {
4778   std::string Code = R"(
4779     void target(bool Bar) {
4780       bool Foo = true;
4781       if (Bar == Foo) {
4782         (void)0;
4783         /*[[p-then]]*/
4784       } else {
4785         (void)0;
4786         /*[[p-else]]*/
4787       }
4788     }
4789   )";
4790   runDataflow(
4791       Code,
4792       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4793          ASTContext &ASTCtx) {
4794         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-then", "p-else"));
4795         const Environment &EnvThen =
4796             getEnvironmentAtAnnotation(Results, "p-then");
4797         const Environment &EnvElse =
4798             getEnvironmentAtAnnotation(Results, "p-else");
4799 
4800         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4801         ASSERT_THAT(BarDecl, NotNull());
4802 
4803         auto &BarValThen = getFormula(*BarDecl, EnvThen);
4804         EXPECT_TRUE(EnvThen.proves(BarValThen));
4805 
4806         auto &BarValElse = getFormula(*BarDecl, EnvElse);
4807         EXPECT_TRUE(EnvElse.proves(EnvElse.arena().makeNot(BarValElse)));
4808       });
4809 }
4810 
4811 TEST(TransferTest, BooleanInequality) {
4812   std::string Code = R"(
4813     void target(bool Bar) {
4814       bool Foo = true;
4815       if (Bar != Foo) {
4816         (void)0;
4817         /*[[p-then]]*/
4818       } else {
4819         (void)0;
4820         /*[[p-else]]*/
4821       }
4822     }
4823   )";
4824   runDataflow(
4825       Code,
4826       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4827          ASTContext &ASTCtx) {
4828         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-then", "p-else"));
4829         const Environment &EnvThen =
4830             getEnvironmentAtAnnotation(Results, "p-then");
4831         const Environment &EnvElse =
4832             getEnvironmentAtAnnotation(Results, "p-else");
4833 
4834         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4835         ASSERT_THAT(BarDecl, NotNull());
4836 
4837         auto &BarValThen = getFormula(*BarDecl, EnvThen);
4838         EXPECT_TRUE(EnvThen.proves(EnvThen.arena().makeNot(BarValThen)));
4839 
4840         auto &BarValElse = getFormula(*BarDecl, EnvElse);
4841         EXPECT_TRUE(EnvElse.proves(BarValElse));
4842       });
4843 }
4844 
4845 TEST(TransferTest, PointerEquality) {
4846   std::string Code = R"cc(
4847     void target() {
4848       int i = 0;
4849       int i_other = 0;
4850       int *p1 = &i;
4851       int *p2 = &i;
4852       int *p_other = &i_other;
4853       int *null = nullptr;
4854 
4855       bool p1_eq_p1 = (p1 == p1);
4856       bool p1_eq_p2 = (p1 == p2);
4857       bool p1_eq_p_other = (p1 == p_other);
4858 
4859       bool p1_eq_null = (p1 == null);
4860       bool p1_eq_nullptr = (p1 == nullptr);
4861       bool null_eq_nullptr = (null == nullptr);
4862       bool nullptr_eq_nullptr = (nullptr == nullptr);
4863 
4864       // We won't duplicate all of the tests above with `!=`, as we know that
4865       // the implementation simply negates the result of the `==` comparison.
4866       // Instaed, just spot-check one case.
4867       bool p1_ne_p1 = (p1 != p1);
4868 
4869       (void)0; // [[p]]
4870     }
4871   )cc";
4872   runDataflow(
4873       Code,
4874       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4875          ASTContext &ASTCtx) {
4876         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4877 
4878         // Check the we have indeed set things up so that `p1` and `p2` have
4879         // different pointer values.
4880         EXPECT_NE(&getValueForDecl<PointerValue>(ASTCtx, Env, "p1"),
4881                   &getValueForDecl<PointerValue>(ASTCtx, Env, "p2"));
4882 
4883         EXPECT_EQ(&getValueForDecl<BoolValue>(ASTCtx, Env, "p1_eq_p1"),
4884                   &Env.getBoolLiteralValue(true));
4885         EXPECT_EQ(&getValueForDecl<BoolValue>(ASTCtx, Env, "p1_eq_p2"),
4886                   &Env.getBoolLiteralValue(true));
4887         EXPECT_TRUE(isa<AtomicBoolValue>(
4888             getValueForDecl<BoolValue>(ASTCtx, Env, "p1_eq_p_other")));
4889 
4890         EXPECT_TRUE(isa<AtomicBoolValue>(
4891             getValueForDecl<BoolValue>(ASTCtx, Env, "p1_eq_null")));
4892         EXPECT_TRUE(isa<AtomicBoolValue>(
4893             getValueForDecl<BoolValue>(ASTCtx, Env, "p1_eq_nullptr")));
4894         EXPECT_EQ(&getValueForDecl<BoolValue>(ASTCtx, Env, "null_eq_nullptr"),
4895                   &Env.getBoolLiteralValue(true));
4896         EXPECT_EQ(
4897             &getValueForDecl<BoolValue>(ASTCtx, Env, "nullptr_eq_nullptr"),
4898             &Env.getBoolLiteralValue(true));
4899 
4900         EXPECT_EQ(&getValueForDecl<BoolValue>(ASTCtx, Env, "p1_ne_p1"),
4901                   &Env.getBoolLiteralValue(false));
4902       });
4903 }
4904 
4905 TEST(TransferTest, PointerEqualityUnionMembers) {
4906   std::string Code = R"cc(
4907     union U {
4908       int i1;
4909       int i2;
4910     };
4911     void target() {
4912       U u;
4913       bool i1_eq_i2 = (&u.i1 == &u.i2);
4914 
4915       (void)0; // [[p]]
4916     }
4917   )cc";
4918   runDataflow(
4919       Code,
4920       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4921          ASTContext &ASTCtx) {
4922         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4923 
4924         // FIXME: By the standard, `u.i1` and `u.i2` should have the same
4925         // address, but we don't yet model this property of union members
4926         // correctly. The result is therefore weaker than it could be (just an
4927         // atom rather than a true literal), though not wrong.
4928         EXPECT_TRUE(isa<AtomicBoolValue>(
4929             getValueForDecl<BoolValue>(ASTCtx, Env, "i1_eq_i2")));
4930       });
4931 }
4932 
4933 TEST(TransferTest, IntegerLiteralEquality) {
4934   std::string Code = R"(
4935     void target() {
4936       bool equal = (42 == 42);
4937       // [[p]]
4938     }
4939   )";
4940   runDataflow(
4941       Code,
4942       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4943          ASTContext &ASTCtx) {
4944         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4945 
4946         auto &Equal =
4947             getValueForDecl<BoolValue>(ASTCtx, Env, "equal").formula();
4948         EXPECT_TRUE(Env.proves(Equal));
4949       });
4950 }
4951 
4952 TEST(TransferTest, CorrelatedBranches) {
4953   std::string Code = R"(
4954     void target(bool B, bool C) {
4955       if (B) {
4956         return;
4957       }
4958       (void)0;
4959       /*[[p0]]*/
4960       if (C) {
4961         B = true;
4962         /*[[p1]]*/
4963       }
4964       if (B) {
4965         (void)0;
4966         /*[[p2]]*/
4967       }
4968     }
4969   )";
4970   runDataflow(
4971       Code,
4972       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4973          ASTContext &ASTCtx) {
4974         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p0", "p1", "p2"));
4975 
4976         const ValueDecl *CDecl = findValueDecl(ASTCtx, "C");
4977         ASSERT_THAT(CDecl, NotNull());
4978 
4979         {
4980           const Environment &Env = getEnvironmentAtAnnotation(Results, "p0");
4981           const ValueDecl *BDecl = findValueDecl(ASTCtx, "B");
4982           ASSERT_THAT(BDecl, NotNull());
4983           auto &BVal = getFormula(*BDecl, Env);
4984 
4985           EXPECT_TRUE(Env.proves(Env.arena().makeNot(BVal)));
4986         }
4987 
4988         {
4989           const Environment &Env = getEnvironmentAtAnnotation(Results, "p1");
4990           auto &CVal = getFormula(*CDecl, Env);
4991           EXPECT_TRUE(Env.proves(CVal));
4992         }
4993 
4994         {
4995           const Environment &Env = getEnvironmentAtAnnotation(Results, "p2");
4996           auto &CVal = getFormula(*CDecl, Env);
4997           EXPECT_TRUE(Env.proves(CVal));
4998         }
4999       });
5000 }
5001 
5002 TEST(TransferTest, LoopWithAssignmentConverges) {
5003   std::string Code = R"(
5004     bool foo();
5005 
5006     void target() {
5007        do {
5008         bool Bar = foo();
5009         if (Bar) break;
5010         (void)Bar;
5011         /*[[p]]*/
5012       } while (true);
5013     }
5014   )";
5015   // The key property that we are verifying is implicit in `runDataflow` --
5016   // namely, that the analysis succeeds, rather than hitting the maximum number
5017   // of iterations.
5018   runDataflow(
5019       Code,
5020       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5021          ASTContext &ASTCtx) {
5022         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5023         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5024 
5025         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
5026         ASSERT_THAT(BarDecl, NotNull());
5027 
5028         auto &BarVal = getFormula(*BarDecl, Env);
5029         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BarVal)));
5030       });
5031 }
5032 
5033 TEST(TransferTest, LoopWithStagedAssignments) {
5034   std::string Code = R"(
5035     bool foo();
5036 
5037     void target() {
5038       bool Bar = false;
5039       bool Err = false;
5040       while (foo()) {
5041         if (Bar)
5042           Err = true;
5043         Bar = true;
5044         /*[[p]]*/
5045       }
5046     }
5047   )";
5048   runDataflow(
5049       Code,
5050       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5051          ASTContext &ASTCtx) {
5052         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5053         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5054 
5055         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
5056         ASSERT_THAT(BarDecl, NotNull());
5057         const ValueDecl *ErrDecl = findValueDecl(ASTCtx, "Err");
5058         ASSERT_THAT(ErrDecl, NotNull());
5059 
5060         auto &BarVal = getFormula(*BarDecl, Env);
5061         auto &ErrVal = getFormula(*ErrDecl, Env);
5062         EXPECT_TRUE(Env.proves(BarVal));
5063         // An unsound analysis, for example only evaluating the loop once, can
5064         // conclude that `Err` is false. So, we test that this conclusion is not
5065         // reached.
5066         EXPECT_FALSE(Env.proves(Env.arena().makeNot(ErrVal)));
5067       });
5068 }
5069 
5070 TEST(TransferTest, LoopWithReferenceAssignmentConverges) {
5071   std::string Code = R"(
5072     bool &foo();
5073 
5074     void target() {
5075        do {
5076         bool& Bar = foo();
5077         if (Bar) break;
5078         (void)Bar;
5079         /*[[p]]*/
5080       } while (true);
5081     }
5082   )";
5083   // The key property that we are verifying is that the analysis succeeds,
5084   // rather than hitting the maximum number of iterations.
5085   runDataflow(
5086       Code,
5087       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5088          ASTContext &ASTCtx) {
5089         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5090         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5091 
5092         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
5093         ASSERT_THAT(BarDecl, NotNull());
5094 
5095         auto &BarVal = getFormula(*BarDecl, Env);
5096         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BarVal)));
5097       });
5098 }
5099 
5100 TEST(TransferTest, LoopWithStructReferenceAssignmentConverges) {
5101   std::string Code = R"(
5102     struct Lookup {
5103       int x;
5104     };
5105 
5106     void target(Lookup val, bool b) {
5107       const Lookup* l = nullptr;
5108       while (b) {
5109         l = &val;
5110         /*[[p-inner]]*/
5111       }
5112       (void)0;
5113       /*[[p-outer]]*/
5114     }
5115   )";
5116   // The key property that we are verifying is implicit in `runDataflow` --
5117   // namely, that the analysis succeeds, rather than hitting the maximum number
5118   // of iterations.
5119   runDataflow(
5120       Code,
5121       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5122          ASTContext &ASTCtx) {
5123         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-inner", "p-outer"));
5124         const Environment &InnerEnv =
5125             getEnvironmentAtAnnotation(Results, "p-inner");
5126         const Environment &OuterEnv =
5127             getEnvironmentAtAnnotation(Results, "p-outer");
5128 
5129         const ValueDecl *ValDecl = findValueDecl(ASTCtx, "val");
5130         ASSERT_THAT(ValDecl, NotNull());
5131 
5132         const ValueDecl *LDecl = findValueDecl(ASTCtx, "l");
5133         ASSERT_THAT(LDecl, NotNull());
5134 
5135         // Inner.
5136         auto *LVal = dyn_cast<PointerValue>(InnerEnv.getValue(*LDecl));
5137         ASSERT_THAT(LVal, NotNull());
5138 
5139         EXPECT_EQ(&LVal->getPointeeLoc(),
5140                   InnerEnv.getStorageLocation(*ValDecl));
5141 
5142         // Outer.
5143         LVal = dyn_cast<PointerValue>(OuterEnv.getValue(*LDecl));
5144         ASSERT_THAT(LVal, NotNull());
5145 
5146         // The loop body may not have been executed, so we should not conclude
5147         // that `l` points to `val`.
5148         EXPECT_NE(&LVal->getPointeeLoc(),
5149                   OuterEnv.getStorageLocation(*ValDecl));
5150       });
5151 }
5152 
5153 TEST(TransferTest, LoopDereferencingChangingPointerConverges) {
5154   std::string Code = R"cc(
5155     bool some_condition();
5156 
5157     void target(int i1, int i2) {
5158       int *p = &i1;
5159       while (true) {
5160         (void)*p;
5161         if (some_condition())
5162           p = &i1;
5163         else
5164           p = &i2;
5165       }
5166     }
5167   )cc";
5168   ASSERT_THAT_ERROR(checkDataflowWithNoopAnalysis(Code), llvm::Succeeded());
5169 }
5170 
5171 TEST(TransferTest, LoopDereferencingChangingRecordPointerConverges) {
5172   std::string Code = R"cc(
5173     struct Lookup {
5174       int x;
5175     };
5176 
5177     bool some_condition();
5178 
5179     void target(Lookup l1, Lookup l2) {
5180       Lookup *l = &l1;
5181       while (true) {
5182         (void)l->x;
5183         if (some_condition())
5184           l = &l1;
5185         else
5186           l = &l2;
5187       }
5188     }
5189   )cc";
5190   ASSERT_THAT_ERROR(checkDataflowWithNoopAnalysis(Code), llvm::Succeeded());
5191 }
5192 
5193 TEST(TransferTest, LoopWithShortCircuitedConditionConverges) {
5194   std::string Code = R"cc(
5195     bool foo();
5196 
5197     void target() {
5198       bool c = false;
5199       while (foo() || foo()) {
5200         c = true;
5201       }
5202     }
5203   )cc";
5204   ASSERT_THAT_ERROR(checkDataflowWithNoopAnalysis(Code), llvm::Succeeded());
5205 }
5206 
5207 TEST(TransferTest, LoopCanProveInvariantForBoolean) {
5208   // Check that we can prove `b` is always false in the loop.
5209   // This test exercises the logic in `widenDistinctValues()` that preserves
5210   // information if the boolean can be proved to be either true or false in both
5211   // the previous and current iteration.
5212   std::string Code = R"cc(
5213     int return_int();
5214     void target() {
5215       bool b = return_int() == 0;
5216       if (b) return;
5217       while (true) {
5218         b;
5219         // [[p]]
5220         b = return_int() == 0;
5221         if (b) return;
5222       }
5223     }
5224   )cc";
5225   runDataflow(
5226       Code,
5227       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5228          ASTContext &ASTCtx) {
5229         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5230         auto &BVal = getValueForDecl<BoolValue>(ASTCtx, Env, "b");
5231         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BVal.formula())));
5232       });
5233 }
5234 
5235 TEST(TransferTest, DoesNotCrashOnUnionThisExpr) {
5236   std::string Code = R"cc(
5237     union Union {
5238       int A;
5239       float B;
5240     };
5241 
5242     void foo() {
5243       Union A;
5244       Union B;
5245       A = B;
5246     }
5247   )cc";
5248   // This is a crash regression test when calling the transfer function on a
5249   // `CXXThisExpr` that refers to a union.
5250   runDataflow(
5251       Code,
5252       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &,
5253          ASTContext &) {},
5254       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator=");
5255 }
5256 
5257 TEST(TransferTest, DoesNotCrashOnNullChildren) {
5258   std::string Code = (CoroutineLibrary + R"cc(
5259     task target() noexcept {
5260       co_return;
5261     }
5262   )cc")
5263                          .str();
5264   // This is a crash regression test when calling `AdornedCFG::build` on a
5265   // statement (in this case, the `CoroutineBodyStmt`) with null children.
5266   runDataflow(
5267       Code,
5268       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &,
5269          ASTContext &) {},
5270       LangStandard::lang_cxx20, /*ApplyBuiltinTransfer=*/true);
5271 }
5272 
5273 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToRefs) {
5274   std::string Code = R"(
5275     struct A {
5276       int Foo;
5277       int Bar;
5278     };
5279 
5280     void target() {
5281       int Qux;
5282       A Baz;
5283       Baz.Foo = Qux;
5284       auto &FooRef = Baz.Foo;
5285       auto &BarRef = Baz.Bar;
5286       auto &[BoundFooRef, BoundBarRef] = Baz;
5287       // [[p]]
5288     }
5289   )";
5290   runDataflow(
5291       Code,
5292       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5293          ASTContext &ASTCtx) {
5294         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5295         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5296 
5297         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
5298         ASSERT_THAT(FooRefDecl, NotNull());
5299 
5300         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
5301         ASSERT_THAT(BarRefDecl, NotNull());
5302 
5303         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
5304         ASSERT_THAT(QuxDecl, NotNull());
5305 
5306         const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef");
5307         ASSERT_THAT(BoundFooRefDecl, NotNull());
5308 
5309         const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef");
5310         ASSERT_THAT(BoundBarRefDecl, NotNull());
5311 
5312         const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl);
5313         ASSERT_THAT(FooRefLoc, NotNull());
5314 
5315         const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl);
5316         ASSERT_THAT(BarRefLoc, NotNull());
5317 
5318         const Value *QuxVal = Env.getValue(*QuxDecl);
5319         ASSERT_THAT(QuxVal, NotNull());
5320 
5321         const StorageLocation *BoundFooRefLoc =
5322             Env.getStorageLocation(*BoundFooRefDecl);
5323         EXPECT_EQ(BoundFooRefLoc, FooRefLoc);
5324 
5325         const StorageLocation *BoundBarRefLoc =
5326             Env.getStorageLocation(*BoundBarRefDecl);
5327         EXPECT_EQ(BoundBarRefLoc, BarRefLoc);
5328 
5329         EXPECT_EQ(Env.getValue(*BoundFooRefDecl), QuxVal);
5330       });
5331 }
5332 
5333 TEST(TransferTest, StructuredBindingAssignFromStructRefMembersToRefs) {
5334   std::string Code = R"(
5335     struct A {
5336       int &Foo;
5337       int &Bar;
5338     };
5339 
5340     void target(A Baz) {
5341       int Qux;
5342       Baz.Foo = Qux;
5343       auto &FooRef = Baz.Foo;
5344       auto &BarRef = Baz.Bar;
5345       auto &[BoundFooRef, BoundBarRef] = Baz;
5346       // [[p]]
5347     }
5348   )";
5349   runDataflow(
5350       Code,
5351       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5352          ASTContext &ASTCtx) {
5353         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5354         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5355 
5356         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
5357         ASSERT_THAT(FooRefDecl, NotNull());
5358 
5359         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
5360         ASSERT_THAT(BarRefDecl, NotNull());
5361 
5362         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
5363         ASSERT_THAT(QuxDecl, NotNull());
5364 
5365         const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef");
5366         ASSERT_THAT(BoundFooRefDecl, NotNull());
5367 
5368         const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef");
5369         ASSERT_THAT(BoundBarRefDecl, NotNull());
5370 
5371         const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl);
5372         ASSERT_THAT(FooRefLoc, NotNull());
5373 
5374         const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl);
5375         ASSERT_THAT(BarRefLoc, NotNull());
5376 
5377         const Value *QuxVal = Env.getValue(*QuxDecl);
5378         ASSERT_THAT(QuxVal, NotNull());
5379 
5380         const StorageLocation *BoundFooRefLoc =
5381             Env.getStorageLocation(*BoundFooRefDecl);
5382         EXPECT_EQ(BoundFooRefLoc, FooRefLoc);
5383 
5384         const StorageLocation *BoundBarRefLoc =
5385             Env.getStorageLocation(*BoundBarRefDecl);
5386         EXPECT_EQ(BoundBarRefLoc, BarRefLoc);
5387 
5388         EXPECT_EQ(Env.getValue(*BoundFooRefDecl), QuxVal);
5389       });
5390 }
5391 
5392 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToInts) {
5393   std::string Code = R"(
5394     struct A {
5395       int Foo;
5396       int Bar;
5397     };
5398 
5399     void target() {
5400       int Qux;
5401       A Baz;
5402       Baz.Foo = Qux;
5403       auto &FooRef = Baz.Foo;
5404       auto &BarRef = Baz.Bar;
5405       auto [BoundFoo, BoundBar] = Baz;
5406       // [[p]]
5407     }
5408   )";
5409   runDataflow(
5410       Code,
5411       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5412          ASTContext &ASTCtx) {
5413         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5414         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5415 
5416         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
5417         ASSERT_THAT(FooRefDecl, NotNull());
5418 
5419         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
5420         ASSERT_THAT(BarRefDecl, NotNull());
5421 
5422         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
5423         ASSERT_THAT(BoundFooDecl, NotNull());
5424 
5425         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
5426         ASSERT_THAT(BoundBarDecl, NotNull());
5427 
5428         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
5429         ASSERT_THAT(QuxDecl, NotNull());
5430 
5431         const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl);
5432         ASSERT_THAT(FooRefLoc, NotNull());
5433 
5434         const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl);
5435         ASSERT_THAT(BarRefLoc, NotNull());
5436 
5437         const Value *QuxVal = Env.getValue(*QuxDecl);
5438         ASSERT_THAT(QuxVal, NotNull());
5439 
5440         const StorageLocation *BoundFooLoc =
5441             Env.getStorageLocation(*BoundFooDecl);
5442         EXPECT_NE(BoundFooLoc, FooRefLoc);
5443 
5444         const StorageLocation *BoundBarLoc =
5445             Env.getStorageLocation(*BoundBarDecl);
5446         EXPECT_NE(BoundBarLoc, BarRefLoc);
5447 
5448         EXPECT_EQ(Env.getValue(*BoundFooDecl), QuxVal);
5449       });
5450 }
5451 
5452 TEST(TransferTest, StructuredBindingAssignFromTupleLikeType) {
5453   std::string Code = R"(
5454     namespace std {
5455     using size_t = int;
5456     template <class> struct tuple_size;
5457     template <std::size_t, class> struct tuple_element;
5458     template <class...> class tuple;
5459 
5460     namespace {
5461     template <class T, T v>
5462     struct size_helper { static const T value = v; };
5463     } // namespace
5464 
5465     template <class... T>
5466     struct tuple_size<tuple<T...>> : size_helper<std::size_t, sizeof...(T)> {};
5467 
5468     template <std::size_t I, class... T>
5469     struct tuple_element<I, tuple<T...>> {
5470       using type =  __type_pack_element<I, T...>;
5471     };
5472 
5473     template <class...> class tuple {};
5474 
5475     template <std::size_t I, class... T>
5476     typename tuple_element<I, tuple<T...>>::type get(tuple<T...>);
5477     } // namespace std
5478 
5479     std::tuple<bool, int> makeTuple();
5480 
5481     void target(bool B) {
5482       auto [BoundFoo, BoundBar] = makeTuple();
5483       bool Baz;
5484       // Include if-then-else to test interaction of `BindingDecl` with join.
5485       if (B) {
5486         Baz = BoundFoo;
5487         (void)BoundBar;
5488         // [[p1]]
5489       } else {
5490         Baz = BoundFoo;
5491       }
5492       (void)0;
5493       // [[p2]]
5494     }
5495   )";
5496   runDataflow(
5497       Code,
5498       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5499          ASTContext &ASTCtx) {
5500         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
5501         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
5502 
5503         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
5504         ASSERT_THAT(BoundFooDecl, NotNull());
5505 
5506         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
5507         ASSERT_THAT(BoundBarDecl, NotNull());
5508 
5509         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
5510         ASSERT_THAT(BazDecl, NotNull());
5511 
5512         // BindingDecls always map to references -- either lvalue or rvalue, so
5513         // we still need to skip here.
5514         const Value *BoundFooValue = Env1.getValue(*BoundFooDecl);
5515         ASSERT_THAT(BoundFooValue, NotNull());
5516         EXPECT_TRUE(isa<BoolValue>(BoundFooValue));
5517 
5518         const Value *BoundBarValue = Env1.getValue(*BoundBarDecl);
5519         ASSERT_THAT(BoundBarValue, NotNull());
5520         EXPECT_TRUE(isa<IntegerValue>(BoundBarValue));
5521 
5522         // Test that a `DeclRefExpr` to a `BindingDecl` works as expected.
5523         EXPECT_EQ(Env1.getValue(*BazDecl), BoundFooValue);
5524 
5525         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
5526 
5527         // Test that `BoundFooDecl` retains the value we expect, after the join.
5528         BoundFooValue = Env2.getValue(*BoundFooDecl);
5529         EXPECT_EQ(Env2.getValue(*BazDecl), BoundFooValue);
5530       });
5531 }
5532 
5533 TEST(TransferTest, StructuredBindingAssignRefFromTupleLikeType) {
5534   std::string Code = R"(
5535     namespace std {
5536     using size_t = int;
5537     template <class> struct tuple_size;
5538     template <std::size_t, class> struct tuple_element;
5539     template <class...> class tuple;
5540 
5541     namespace {
5542     template <class T, T v>
5543     struct size_helper { static const T value = v; };
5544     } // namespace
5545 
5546     template <class... T>
5547     struct tuple_size<tuple<T...>> : size_helper<std::size_t, sizeof...(T)> {};
5548 
5549     template <std::size_t I, class... T>
5550     struct tuple_element<I, tuple<T...>> {
5551       using type =  __type_pack_element<I, T...>;
5552     };
5553 
5554     template <class...> class tuple {};
5555 
5556     template <std::size_t I, class... T>
5557     typename tuple_element<I, tuple<T...>>::type get(tuple<T...>);
5558     } // namespace std
5559 
5560     std::tuple<bool, int> &getTuple();
5561 
5562     void target(bool B) {
5563       auto &[BoundFoo, BoundBar] = getTuple();
5564       bool Baz;
5565       // Include if-then-else to test interaction of `BindingDecl` with join.
5566       if (B) {
5567         Baz = BoundFoo;
5568         (void)BoundBar;
5569         // [[p1]]
5570       } else {
5571         Baz = BoundFoo;
5572       }
5573       (void)0;
5574       // [[p2]]
5575     }
5576   )";
5577   runDataflow(
5578       Code,
5579       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5580          ASTContext &ASTCtx) {
5581         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
5582         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
5583 
5584         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
5585         ASSERT_THAT(BoundFooDecl, NotNull());
5586 
5587         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
5588         ASSERT_THAT(BoundBarDecl, NotNull());
5589 
5590         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
5591         ASSERT_THAT(BazDecl, NotNull());
5592 
5593         const Value *BoundFooValue = Env1.getValue(*BoundFooDecl);
5594         ASSERT_THAT(BoundFooValue, NotNull());
5595         EXPECT_TRUE(isa<BoolValue>(BoundFooValue));
5596 
5597         const Value *BoundBarValue = Env1.getValue(*BoundBarDecl);
5598         ASSERT_THAT(BoundBarValue, NotNull());
5599         EXPECT_TRUE(isa<IntegerValue>(BoundBarValue));
5600 
5601         // Test that a `DeclRefExpr` to a `BindingDecl` (with reference type)
5602         // works as expected. We don't test aliasing properties of the
5603         // reference, because we don't model `std::get` and so have no way to
5604         // equate separate references into the tuple.
5605         EXPECT_EQ(Env1.getValue(*BazDecl), BoundFooValue);
5606 
5607         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
5608 
5609         // Test that `BoundFooDecl` retains the value we expect, after the join.
5610         BoundFooValue = Env2.getValue(*BoundFooDecl);
5611         EXPECT_EQ(Env2.getValue(*BazDecl), BoundFooValue);
5612       });
5613 }
5614 
5615 TEST(TransferTest, BinaryOperatorComma) {
5616   std::string Code = R"(
5617     void target(int Foo, int Bar) {
5618       int &Baz = (Foo, Bar);
5619       // [[p]]
5620     }
5621   )";
5622   runDataflow(
5623       Code,
5624       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5625          ASTContext &ASTCtx) {
5626         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5627         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5628 
5629         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
5630         ASSERT_THAT(BarDecl, NotNull());
5631 
5632         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
5633         ASSERT_THAT(BazDecl, NotNull());
5634 
5635         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
5636         ASSERT_THAT(BarLoc, NotNull());
5637 
5638         const StorageLocation *BazLoc = Env.getStorageLocation(*BazDecl);
5639         EXPECT_EQ(BazLoc, BarLoc);
5640       });
5641 }
5642 
5643 TEST(TransferTest, ConditionalOperatorValue) {
5644   std::string Code = R"(
5645     void target(bool Cond, bool B1, bool B2) {
5646       bool JoinSame = Cond ? B1 : B1;
5647       bool JoinDifferent = Cond ? B1 : B2;
5648       // [[p]]
5649     }
5650   )";
5651   runDataflow(
5652       Code,
5653       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5654          ASTContext &ASTCtx) {
5655         Environment Env = getEnvironmentAtAnnotation(Results, "p").fork();
5656 
5657         auto &B1 = getValueForDecl<BoolValue>(ASTCtx, Env, "B1");
5658         auto &B2 = getValueForDecl<BoolValue>(ASTCtx, Env, "B2");
5659         auto &JoinSame = getValueForDecl<BoolValue>(ASTCtx, Env, "JoinSame");
5660         auto &JoinDifferent =
5661             getValueForDecl<BoolValue>(ASTCtx, Env, "JoinDifferent");
5662 
5663         EXPECT_EQ(&JoinSame, &B1);
5664 
5665         const Formula &JoinDifferentEqB1 =
5666             Env.arena().makeEquals(JoinDifferent.formula(), B1.formula());
5667         EXPECT_TRUE(Env.allows(JoinDifferentEqB1));
5668         EXPECT_FALSE(Env.proves(JoinDifferentEqB1));
5669 
5670         const Formula &JoinDifferentEqB2 =
5671             Env.arena().makeEquals(JoinDifferent.formula(), B2.formula());
5672         EXPECT_TRUE(Env.allows(JoinDifferentEqB2));
5673         EXPECT_FALSE(Env.proves(JoinDifferentEqB1));
5674       });
5675 }
5676 
5677 TEST(TransferTest, ConditionalOperatorLocation) {
5678   std::string Code = R"(
5679     void target(bool Cond, int I1, int I2) {
5680       int &JoinSame = Cond ? I1 : I1;
5681       int &JoinDifferent = Cond ? I1 : I2;
5682       // [[p]]
5683     }
5684   )";
5685   runDataflow(
5686       Code,
5687       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5688          ASTContext &ASTCtx) {
5689         Environment Env = getEnvironmentAtAnnotation(Results, "p").fork();
5690 
5691         StorageLocation &I1 = getLocForDecl(ASTCtx, Env, "I1");
5692         StorageLocation &I2 = getLocForDecl(ASTCtx, Env, "I2");
5693         StorageLocation &JoinSame = getLocForDecl(ASTCtx, Env, "JoinSame");
5694         StorageLocation &JoinDifferent =
5695             getLocForDecl(ASTCtx, Env, "JoinDifferent");
5696 
5697         EXPECT_EQ(&JoinSame, &I1);
5698 
5699         EXPECT_NE(&JoinDifferent, &I1);
5700         EXPECT_NE(&JoinDifferent, &I2);
5701       });
5702 }
5703 
5704 TEST(TransferTest, ConditionalOperatorOnConstantExpr) {
5705   // This is a regression test: We used to crash when a `ConstantExpr` was used
5706   // in the branches of a conditional operator.
5707   std::string Code = R"cc(
5708     consteval bool identity(bool B) { return B; }
5709     void target(bool Cond) {
5710       bool JoinTrueTrue = Cond ? identity(true) : identity(true);
5711       bool JoinTrueFalse = Cond ? identity(true) : identity(false);
5712       // [[p]]
5713     }
5714   )cc";
5715   runDataflow(
5716       Code,
5717       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5718          ASTContext &ASTCtx) {
5719         Environment Env = getEnvironmentAtAnnotation(Results, "p").fork();
5720 
5721         auto &JoinTrueTrue =
5722             getValueForDecl<BoolValue>(ASTCtx, Env, "JoinTrueTrue");
5723         // FIXME: This test documents the current behavior, namely that we
5724         // don't actually use the constant result of the `ConstantExpr` and
5725         // instead treat it like a normal function call.
5726         EXPECT_EQ(JoinTrueTrue.formula().kind(), Formula::Kind::AtomRef);
5727         // EXPECT_TRUE(JoinTrueTrue.formula().literal());
5728 
5729         auto &JoinTrueFalse =
5730             getValueForDecl<BoolValue>(ASTCtx, Env, "JoinTrueFalse");
5731         EXPECT_EQ(JoinTrueFalse.formula().kind(), Formula::Kind::AtomRef);
5732       },
5733       LangStandard::lang_cxx20);
5734 }
5735 
5736 TEST(TransferTest, IfStmtBranchExtendsFlowCondition) {
5737   std::string Code = R"(
5738     void target(bool Foo) {
5739       if (Foo) {
5740         (void)0;
5741         // [[if_then]]
5742       } else {
5743         (void)0;
5744         // [[if_else]]
5745       }
5746     }
5747   )";
5748   runDataflow(
5749       Code,
5750       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5751          ASTContext &ASTCtx) {
5752         ASSERT_THAT(Results.keys(), UnorderedElementsAre("if_then", "if_else"));
5753         const Environment &ThenEnv =
5754             getEnvironmentAtAnnotation(Results, "if_then");
5755         const Environment &ElseEnv =
5756             getEnvironmentAtAnnotation(Results, "if_else");
5757 
5758         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5759         ASSERT_THAT(FooDecl, NotNull());
5760 
5761         auto &ThenFooVal= getFormula(*FooDecl, ThenEnv);
5762         EXPECT_TRUE(ThenEnv.proves(ThenFooVal));
5763 
5764         auto &ElseFooVal = getFormula(*FooDecl, ElseEnv);
5765         EXPECT_TRUE(ElseEnv.proves(ElseEnv.arena().makeNot(ElseFooVal)));
5766       });
5767 }
5768 
5769 TEST(TransferTest, WhileStmtBranchExtendsFlowCondition) {
5770   std::string Code = R"(
5771     void target(bool Foo) {
5772       while (Foo) {
5773         (void)0;
5774         // [[loop_body]]
5775       }
5776       (void)0;
5777       // [[after_loop]]
5778     }
5779   )";
5780   runDataflow(
5781       Code,
5782       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5783          ASTContext &ASTCtx) {
5784         ASSERT_THAT(Results.keys(),
5785                     UnorderedElementsAre("loop_body", "after_loop"));
5786         const Environment &LoopBodyEnv =
5787             getEnvironmentAtAnnotation(Results, "loop_body");
5788         const Environment &AfterLoopEnv =
5789             getEnvironmentAtAnnotation(Results, "after_loop");
5790 
5791         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5792         ASSERT_THAT(FooDecl, NotNull());
5793 
5794         auto &LoopBodyFooVal = getFormula(*FooDecl, LoopBodyEnv);
5795         EXPECT_TRUE(LoopBodyEnv.proves(LoopBodyFooVal));
5796 
5797         auto &AfterLoopFooVal = getFormula(*FooDecl, AfterLoopEnv);
5798         EXPECT_TRUE(
5799             AfterLoopEnv.proves(AfterLoopEnv.arena().makeNot(AfterLoopFooVal)));
5800       });
5801 }
5802 
5803 TEST(TransferTest, DoWhileStmtBranchExtendsFlowCondition) {
5804   std::string Code = R"(
5805     void target(bool Foo) {
5806       bool Bar = true;
5807       do {
5808         (void)0;
5809         // [[loop_body]]
5810         Bar = false;
5811       } while (Foo);
5812       (void)0;
5813       // [[after_loop]]
5814     }
5815   )";
5816   runDataflow(
5817       Code,
5818       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5819          ASTContext &ASTCtx) {
5820         ASSERT_THAT(Results.keys(),
5821                     UnorderedElementsAre("loop_body", "after_loop"));
5822         const Environment &LoopBodyEnv =
5823             getEnvironmentAtAnnotation(Results, "loop_body");
5824         const Environment &AfterLoopEnv =
5825             getEnvironmentAtAnnotation(Results, "after_loop");
5826         auto &A = AfterLoopEnv.arena();
5827 
5828         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5829         ASSERT_THAT(FooDecl, NotNull());
5830 
5831         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
5832         ASSERT_THAT(BarDecl, NotNull());
5833 
5834         auto &LoopBodyFooVal= getFormula(*FooDecl, LoopBodyEnv);
5835         auto &LoopBodyBarVal = getFormula(*BarDecl, LoopBodyEnv);
5836         EXPECT_TRUE(
5837             LoopBodyEnv.proves(A.makeOr(LoopBodyBarVal, LoopBodyFooVal)));
5838 
5839         auto &AfterLoopFooVal = getFormula(*FooDecl, AfterLoopEnv);
5840         auto &AfterLoopBarVal = getFormula(*BarDecl, AfterLoopEnv);
5841         EXPECT_TRUE(AfterLoopEnv.proves(A.makeNot(AfterLoopFooVal)));
5842         EXPECT_TRUE(AfterLoopEnv.proves(A.makeNot(AfterLoopBarVal)));
5843       });
5844 }
5845 
5846 TEST(TransferTest, ForStmtBranchExtendsFlowCondition) {
5847   std::string Code = R"(
5848     void target(bool Foo) {
5849       for (; Foo;) {
5850         (void)0;
5851         // [[loop_body]]
5852       }
5853       (void)0;
5854       // [[after_loop]]
5855     }
5856   )";
5857   runDataflow(
5858       Code,
5859       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5860          ASTContext &ASTCtx) {
5861         ASSERT_THAT(Results.keys(),
5862                     UnorderedElementsAre("loop_body", "after_loop"));
5863         const Environment &LoopBodyEnv =
5864             getEnvironmentAtAnnotation(Results, "loop_body");
5865         const Environment &AfterLoopEnv =
5866             getEnvironmentAtAnnotation(Results, "after_loop");
5867 
5868         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5869         ASSERT_THAT(FooDecl, NotNull());
5870 
5871         auto &LoopBodyFooVal= getFormula(*FooDecl, LoopBodyEnv);
5872         EXPECT_TRUE(LoopBodyEnv.proves(LoopBodyFooVal));
5873 
5874         auto &AfterLoopFooVal = getFormula(*FooDecl, AfterLoopEnv);
5875         EXPECT_TRUE(
5876             AfterLoopEnv.proves(AfterLoopEnv.arena().makeNot(AfterLoopFooVal)));
5877       });
5878 }
5879 
5880 TEST(TransferTest, ForStmtBranchWithoutConditionDoesNotExtendFlowCondition) {
5881   std::string Code = R"(
5882     void target(bool Foo) {
5883       for (;;) {
5884         (void)0;
5885         // [[loop_body]]
5886       }
5887     }
5888   )";
5889   runDataflow(
5890       Code,
5891       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5892          ASTContext &ASTCtx) {
5893         ASSERT_THAT(Results.keys(), UnorderedElementsAre("loop_body"));
5894         const Environment &LoopBodyEnv =
5895             getEnvironmentAtAnnotation(Results, "loop_body");
5896 
5897         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5898         ASSERT_THAT(FooDecl, NotNull());
5899 
5900         auto &LoopBodyFooVal= getFormula(*FooDecl, LoopBodyEnv);
5901         EXPECT_FALSE(LoopBodyEnv.proves(LoopBodyFooVal));
5902       });
5903 }
5904 
5905 TEST(TransferTest, ContextSensitiveOptionDisabled) {
5906   std::string Code = R"(
5907     bool GiveBool();
5908     void SetBool(bool &Var) { Var = true; }
5909 
5910     void target() {
5911       bool Foo = GiveBool();
5912       SetBool(Foo);
5913       // [[p]]
5914     }
5915   )";
5916   runDataflow(
5917       Code,
5918       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5919          ASTContext &ASTCtx) {
5920         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5921         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5922 
5923         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5924         ASSERT_THAT(FooDecl, NotNull());
5925 
5926         auto &FooVal = getFormula(*FooDecl, Env);
5927         EXPECT_FALSE(Env.proves(FooVal));
5928         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
5929       },
5930       {BuiltinOptions{/*.ContextSensitiveOpts=*/std::nullopt}});
5931 }
5932 
5933 TEST(TransferTest, ContextSensitiveReturnReference) {
5934   std::string Code = R"(
5935     class S {};
5936     S& target(bool b, S &s) {
5937       return s;
5938       // [[p]]
5939     }
5940   )";
5941   runDataflow(
5942       Code,
5943       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5944          ASTContext &ASTCtx) {
5945         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5946 
5947         const ValueDecl *SDecl = findValueDecl(ASTCtx, "s");
5948         ASSERT_THAT(SDecl, NotNull());
5949 
5950         auto *SLoc = Env.getStorageLocation(*SDecl);
5951         ASSERT_THAT(SLoc, NotNull());
5952 
5953         ASSERT_THAT(Env.getReturnStorageLocation(), Eq(SLoc));
5954       },
5955       {BuiltinOptions{ContextSensitiveOptions{}}});
5956 }
5957 
5958 // This test is a regression test, based on a real crash.
5959 TEST(TransferTest, ContextSensitiveReturnReferenceWithConditionalOperator) {
5960   std::string Code = R"(
5961     class S {};
5962     S& target(bool b, S &s) {
5963       return b ? s : s;
5964       // [[p]]
5965     }
5966   )";
5967   runDataflow(
5968       Code,
5969       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5970          ASTContext &ASTCtx) {
5971         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5972         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5973 
5974         const ValueDecl *SDecl = findValueDecl(ASTCtx, "s");
5975         ASSERT_THAT(SDecl, NotNull());
5976 
5977         auto *SLoc = Env.getStorageLocation(*SDecl);
5978         EXPECT_THAT(SLoc, NotNull());
5979 
5980         auto *Loc = Env.getReturnStorageLocation();
5981         EXPECT_THAT(Loc, NotNull());
5982 
5983         EXPECT_EQ(Loc, SLoc);
5984       },
5985       {BuiltinOptions{ContextSensitiveOptions{}}});
5986 }
5987 
5988 TEST(TransferTest, ContextSensitiveReturnOneOfTwoReferences) {
5989   std::string Code = R"(
5990     class S {};
5991     S &callee(bool b, S &s1_parm, S &s2_parm) {
5992       if (b)
5993         return s1_parm;
5994       else
5995         return s2_parm;
5996     }
5997     void target(bool b) {
5998       S s1;
5999       S s2;
6000       S &return_s1 = s1;
6001       S &return_s2 = s2;
6002       S &return_dont_know = callee(b, s1, s2);
6003       // [[p]]
6004     }
6005   )";
6006   runDataflow(
6007       Code,
6008       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6009          ASTContext &ASTCtx) {
6010         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6011 
6012         const ValueDecl *S1 = findValueDecl(ASTCtx, "s1");
6013         ASSERT_THAT(S1, NotNull());
6014         const ValueDecl *S2 = findValueDecl(ASTCtx, "s2");
6015         ASSERT_THAT(S2, NotNull());
6016         const ValueDecl *ReturnS1 = findValueDecl(ASTCtx, "return_s1");
6017         ASSERT_THAT(ReturnS1, NotNull());
6018         const ValueDecl *ReturnS2 = findValueDecl(ASTCtx, "return_s2");
6019         ASSERT_THAT(ReturnS2, NotNull());
6020         const ValueDecl *ReturnDontKnow =
6021             findValueDecl(ASTCtx, "return_dont_know");
6022         ASSERT_THAT(ReturnDontKnow, NotNull());
6023 
6024         StorageLocation *S1Loc = Env.getStorageLocation(*S1);
6025         StorageLocation *S2Loc = Env.getStorageLocation(*S2);
6026 
6027         EXPECT_THAT(Env.getStorageLocation(*ReturnS1), Eq(S1Loc));
6028         EXPECT_THAT(Env.getStorageLocation(*ReturnS2), Eq(S2Loc));
6029 
6030         // In the case where we don't have a consistent storage location for
6031         // the return value, the framework creates a new storage location, which
6032         // should be different from the storage locations of `s1` and `s2`.
6033         EXPECT_THAT(Env.getStorageLocation(*ReturnDontKnow), Ne(S1Loc));
6034         EXPECT_THAT(Env.getStorageLocation(*ReturnDontKnow), Ne(S2Loc));
6035       },
6036       {BuiltinOptions{ContextSensitiveOptions{}}});
6037 }
6038 
6039 TEST(TransferTest, ContextSensitiveDepthZero) {
6040   std::string Code = R"(
6041     bool GiveBool();
6042     void SetBool(bool &Var) { Var = true; }
6043 
6044     void target() {
6045       bool Foo = GiveBool();
6046       SetBool(Foo);
6047       // [[p]]
6048     }
6049   )";
6050   runDataflow(
6051       Code,
6052       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6053          ASTContext &ASTCtx) {
6054         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6055         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6056 
6057         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6058         ASSERT_THAT(FooDecl, NotNull());
6059 
6060         auto &FooVal = getFormula(*FooDecl, Env);
6061         EXPECT_FALSE(Env.proves(FooVal));
6062         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
6063       },
6064       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/0}}});
6065 }
6066 
6067 TEST(TransferTest, ContextSensitiveSetTrue) {
6068   std::string Code = R"(
6069     bool GiveBool();
6070     void SetBool(bool &Var) { Var = true; }
6071 
6072     void target() {
6073       bool Foo = GiveBool();
6074       SetBool(Foo);
6075       // [[p]]
6076     }
6077   )";
6078   runDataflow(
6079       Code,
6080       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6081          ASTContext &ASTCtx) {
6082         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6083         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6084 
6085         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6086         ASSERT_THAT(FooDecl, NotNull());
6087 
6088         auto &FooVal = getFormula(*FooDecl, Env);
6089         EXPECT_TRUE(Env.proves(FooVal));
6090       },
6091       {BuiltinOptions{ContextSensitiveOptions{}}});
6092 }
6093 
6094 TEST(TransferTest, ContextSensitiveSetFalse) {
6095   std::string Code = R"(
6096     bool GiveBool();
6097     void SetBool(bool &Var) { Var = false; }
6098 
6099     void target() {
6100       bool Foo = GiveBool();
6101       SetBool(Foo);
6102       // [[p]]
6103     }
6104   )";
6105   runDataflow(
6106       Code,
6107       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6108          ASTContext &ASTCtx) {
6109         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6110         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6111 
6112         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6113         ASSERT_THAT(FooDecl, NotNull());
6114 
6115         auto &FooVal = getFormula(*FooDecl, Env);
6116         EXPECT_TRUE(Env.proves(Env.arena().makeNot(FooVal)));
6117       },
6118       {BuiltinOptions{ContextSensitiveOptions{}}});
6119 }
6120 
6121 TEST(TransferTest, ContextSensitiveSetBothTrueAndFalse) {
6122   std::string Code = R"(
6123     bool GiveBool();
6124     void SetBool(bool &Var, bool Val) { Var = Val; }
6125 
6126     void target() {
6127       bool Foo = GiveBool();
6128       bool Bar = GiveBool();
6129       SetBool(Foo, true);
6130       SetBool(Bar, false);
6131       // [[p]]
6132     }
6133   )";
6134   runDataflow(
6135       Code,
6136       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6137          ASTContext &ASTCtx) {
6138         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6139         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6140         auto &A = Env.arena();
6141 
6142         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6143         ASSERT_THAT(FooDecl, NotNull());
6144 
6145         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
6146         ASSERT_THAT(BarDecl, NotNull());
6147 
6148         auto &FooVal = getFormula(*FooDecl, Env);
6149         EXPECT_TRUE(Env.proves(FooVal));
6150         EXPECT_FALSE(Env.proves(A.makeNot(FooVal)));
6151 
6152         auto &BarVal = getFormula(*BarDecl, Env);
6153         EXPECT_FALSE(Env.proves(BarVal));
6154         EXPECT_TRUE(Env.proves(A.makeNot(BarVal)));
6155       },
6156       {BuiltinOptions{ContextSensitiveOptions{}}});
6157 }
6158 
6159 TEST(TransferTest, ContextSensitiveSetTwoLayersDepthOne) {
6160   std::string Code = R"(
6161     bool GiveBool();
6162     void SetBool1(bool &Var) { Var = true; }
6163     void SetBool2(bool &Var) { SetBool1(Var); }
6164 
6165     void target() {
6166       bool Foo = GiveBool();
6167       SetBool2(Foo);
6168       // [[p]]
6169     }
6170   )";
6171   runDataflow(
6172       Code,
6173       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6174          ASTContext &ASTCtx) {
6175         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6176         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6177 
6178         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6179         ASSERT_THAT(FooDecl, NotNull());
6180 
6181         auto &FooVal = getFormula(*FooDecl, Env);
6182         EXPECT_FALSE(Env.proves(FooVal));
6183         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
6184       },
6185       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/1}}});
6186 }
6187 
6188 TEST(TransferTest, ContextSensitiveSetTwoLayersDepthTwo) {
6189   std::string Code = R"(
6190     bool GiveBool();
6191     void SetBool1(bool &Var) { Var = true; }
6192     void SetBool2(bool &Var) { SetBool1(Var); }
6193 
6194     void target() {
6195       bool Foo = GiveBool();
6196       SetBool2(Foo);
6197       // [[p]]
6198     }
6199   )";
6200   runDataflow(
6201       Code,
6202       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6203          ASTContext &ASTCtx) {
6204         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6205         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6206 
6207         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6208         ASSERT_THAT(FooDecl, NotNull());
6209 
6210         auto &FooVal = getFormula(*FooDecl, Env);
6211         EXPECT_TRUE(Env.proves(FooVal));
6212       },
6213       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/2}}});
6214 }
6215 
6216 TEST(TransferTest, ContextSensitiveSetThreeLayersDepthTwo) {
6217   std::string Code = R"(
6218     bool GiveBool();
6219     void SetBool1(bool &Var) { Var = true; }
6220     void SetBool2(bool &Var) { SetBool1(Var); }
6221     void SetBool3(bool &Var) { SetBool2(Var); }
6222 
6223     void target() {
6224       bool Foo = GiveBool();
6225       SetBool3(Foo);
6226       // [[p]]
6227     }
6228   )";
6229   runDataflow(
6230       Code,
6231       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6232          ASTContext &ASTCtx) {
6233         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6234         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6235 
6236         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6237         ASSERT_THAT(FooDecl, NotNull());
6238 
6239         auto &FooVal = getFormula(*FooDecl, Env);
6240         EXPECT_FALSE(Env.proves(FooVal));
6241         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
6242       },
6243       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/2}}});
6244 }
6245 
6246 TEST(TransferTest, ContextSensitiveSetThreeLayersDepthThree) {
6247   std::string Code = R"(
6248     bool GiveBool();
6249     void SetBool1(bool &Var) { Var = true; }
6250     void SetBool2(bool &Var) { SetBool1(Var); }
6251     void SetBool3(bool &Var) { SetBool2(Var); }
6252 
6253     void target() {
6254       bool Foo = GiveBool();
6255       SetBool3(Foo);
6256       // [[p]]
6257     }
6258   )";
6259   runDataflow(
6260       Code,
6261       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6262          ASTContext &ASTCtx) {
6263         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6264         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6265 
6266         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6267         ASSERT_THAT(FooDecl, NotNull());
6268 
6269         auto &FooVal = getFormula(*FooDecl, Env);
6270         EXPECT_TRUE(Env.proves(FooVal));
6271       },
6272       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/3}}});
6273 }
6274 
6275 TEST(TransferTest, ContextSensitiveMutualRecursion) {
6276   std::string Code = R"(
6277     bool Pong(bool X, bool Y);
6278 
6279     bool Ping(bool X, bool Y) {
6280       if (X) {
6281         return Y;
6282       } else {
6283         return Pong(!X, Y);
6284       }
6285     }
6286 
6287     bool Pong(bool X, bool Y) {
6288       if (Y) {
6289         return X;
6290       } else {
6291         return Ping(X, !Y);
6292       }
6293     }
6294 
6295     void target() {
6296       bool Foo = Ping(false, false);
6297       // [[p]]
6298     }
6299   )";
6300   runDataflow(
6301       Code,
6302       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6303          ASTContext &ASTCtx) {
6304         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6305         // The analysis doesn't crash...
6306         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6307 
6308         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6309         ASSERT_THAT(FooDecl, NotNull());
6310 
6311         auto &FooVal = getFormula(*FooDecl, Env);
6312         // ... but it also can't prove anything here.
6313         EXPECT_FALSE(Env.proves(FooVal));
6314         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
6315       },
6316       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/4}}});
6317 }
6318 
6319 TEST(TransferTest, ContextSensitiveSetMultipleLines) {
6320   std::string Code = R"(
6321     void SetBools(bool &Var1, bool &Var2) {
6322       Var1 = true;
6323       Var2 = false;
6324     }
6325 
6326     void target() {
6327       bool Foo = false;
6328       bool Bar = true;
6329       SetBools(Foo, Bar);
6330       // [[p]]
6331     }
6332   )";
6333   runDataflow(
6334       Code,
6335       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6336          ASTContext &ASTCtx) {
6337         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6338         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6339 
6340         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6341         ASSERT_THAT(FooDecl, NotNull());
6342 
6343         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
6344         ASSERT_THAT(BarDecl, NotNull());
6345 
6346         auto &FooVal = getFormula(*FooDecl, Env);
6347         EXPECT_TRUE(Env.proves(FooVal));
6348         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
6349 
6350         auto &BarVal = getFormula(*BarDecl, Env);
6351         EXPECT_FALSE(Env.proves(BarVal));
6352         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BarVal)));
6353       },
6354       {BuiltinOptions{ContextSensitiveOptions{}}});
6355 }
6356 
6357 TEST(TransferTest, ContextSensitiveSetMultipleBlocks) {
6358   std::string Code = R"(
6359     void IfCond(bool Cond, bool &Then, bool &Else) {
6360       if (Cond) {
6361         Then = true;
6362       } else {
6363         Else = true;
6364       }
6365     }
6366 
6367     void target() {
6368       bool Foo = false;
6369       bool Bar = false;
6370       bool Baz = false;
6371       IfCond(Foo, Bar, Baz);
6372       // [[p]]
6373     }
6374   )";
6375   runDataflow(
6376       Code,
6377       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6378          ASTContext &ASTCtx) {
6379         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6380         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6381 
6382         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
6383         ASSERT_THAT(BarDecl, NotNull());
6384 
6385         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
6386         ASSERT_THAT(BazDecl, NotNull());
6387 
6388         auto &BarVal = getFormula(*BarDecl, Env);
6389         EXPECT_FALSE(Env.proves(BarVal));
6390         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BarVal)));
6391 
6392         auto &BazVal = getFormula(*BazDecl, Env);
6393         EXPECT_TRUE(Env.proves(BazVal));
6394         EXPECT_FALSE(Env.proves(Env.arena().makeNot(BazVal)));
6395       },
6396       {BuiltinOptions{ContextSensitiveOptions{}}});
6397 }
6398 
6399 TEST(TransferTest, ContextSensitiveReturnVoid) {
6400   std::string Code = R"(
6401     void Noop() { return; }
6402 
6403     void target() {
6404       Noop();
6405       // [[p]]
6406     }
6407   )";
6408   runDataflow(
6409       Code,
6410       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6411          ASTContext &ASTCtx) {
6412         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6413         // This just tests that the analysis doesn't crash.
6414       },
6415       {BuiltinOptions{ContextSensitiveOptions{}}});
6416 }
6417 
6418 TEST(TransferTest, ContextSensitiveReturnTrue) {
6419   std::string Code = R"(
6420     bool GiveBool() { return true; }
6421 
6422     void target() {
6423       bool Foo = GiveBool();
6424       // [[p]]
6425     }
6426   )";
6427   runDataflow(
6428       Code,
6429       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6430          ASTContext &ASTCtx) {
6431         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6432         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6433 
6434         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6435         ASSERT_THAT(FooDecl, NotNull());
6436 
6437         auto &FooVal = getFormula(*FooDecl, Env);
6438         EXPECT_TRUE(Env.proves(FooVal));
6439       },
6440       {BuiltinOptions{ContextSensitiveOptions{}}});
6441 }
6442 
6443 TEST(TransferTest, ContextSensitiveReturnFalse) {
6444   std::string Code = R"(
6445     bool GiveBool() { return false; }
6446 
6447     void target() {
6448       bool Foo = GiveBool();
6449       // [[p]]
6450     }
6451   )";
6452   runDataflow(
6453       Code,
6454       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6455          ASTContext &ASTCtx) {
6456         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6457         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6458 
6459         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6460         ASSERT_THAT(FooDecl, NotNull());
6461 
6462         auto &FooVal = getFormula(*FooDecl, Env);
6463         EXPECT_TRUE(Env.proves(Env.arena().makeNot(FooVal)));
6464       },
6465       {BuiltinOptions{ContextSensitiveOptions{}}});
6466 }
6467 
6468 TEST(TransferTest, ContextSensitiveReturnArg) {
6469   std::string Code = R"(
6470     bool GiveBool();
6471     bool GiveBack(bool Arg) { return Arg; }
6472 
6473     void target() {
6474       bool Foo = GiveBool();
6475       bool Bar = GiveBack(Foo);
6476       bool Baz = Foo == Bar;
6477       // [[p]]
6478     }
6479   )";
6480   runDataflow(
6481       Code,
6482       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6483          ASTContext &ASTCtx) {
6484         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6485         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6486 
6487         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
6488         ASSERT_THAT(BazDecl, NotNull());
6489 
6490         auto &BazVal = getFormula(*BazDecl, Env);
6491         EXPECT_TRUE(Env.proves(BazVal));
6492       },
6493       {BuiltinOptions{ContextSensitiveOptions{}}});
6494 }
6495 
6496 TEST(TransferTest, ContextSensitiveReturnInt) {
6497   std::string Code = R"(
6498     int identity(int x) { return x; }
6499 
6500     void target() {
6501       int y = identity(42);
6502       // [[p]]
6503     }
6504   )";
6505   runDataflow(
6506       Code,
6507       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6508          ASTContext &ASTCtx) {
6509         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6510         // This just tests that the analysis doesn't crash.
6511       },
6512       {BuiltinOptions{ContextSensitiveOptions{}}});
6513 }
6514 
6515 TEST(TransferTest, ContextSensitiveReturnRecord) {
6516   std::string Code = R"(
6517     struct S {
6518       bool B;
6519     };
6520 
6521     S makeS(bool BVal) { return {BVal}; }
6522 
6523     void target() {
6524       S FalseS = makeS(false);
6525       S TrueS = makeS(true);
6526       // [[p]]
6527     }
6528   )";
6529   runDataflow(
6530       Code,
6531       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6532          ASTContext &ASTCtx) {
6533         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6534 
6535         auto &FalseSLoc =
6536             getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "FalseS");
6537         auto &TrueSLoc =
6538             getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "TrueS");
6539 
6540         EXPECT_EQ(getFieldValue(&FalseSLoc, "B", ASTCtx, Env),
6541                   &Env.getBoolLiteralValue(false));
6542         EXPECT_EQ(getFieldValue(&TrueSLoc, "B", ASTCtx, Env),
6543                   &Env.getBoolLiteralValue(true));
6544       },
6545       {BuiltinOptions{ContextSensitiveOptions{}}});
6546 }
6547 
6548 TEST(TransferTest, ContextSensitiveReturnSelfReferentialRecord) {
6549   std::string Code = R"(
6550     struct S {
6551       S() { self = this; }
6552       S *self;
6553     };
6554 
6555     S makeS() {
6556       // RVO guarantees that this will be constructed directly into `MyS`.
6557       return S();
6558     }
6559 
6560     void target() {
6561       S MyS = makeS();
6562       // [[p]]
6563     }
6564   )";
6565   runDataflow(
6566       Code,
6567       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6568          ASTContext &ASTCtx) {
6569         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6570 
6571         auto &MySLoc = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "MyS");
6572 
6573         auto *SelfVal =
6574             cast<PointerValue>(getFieldValue(&MySLoc, "self", ASTCtx, Env));
6575         EXPECT_EQ(&SelfVal->getPointeeLoc(), &MySLoc);
6576       },
6577       {BuiltinOptions{ContextSensitiveOptions{}}});
6578 }
6579 
6580 TEST(TransferTest, ContextSensitiveMethodLiteral) {
6581   std::string Code = R"(
6582     class MyClass {
6583     public:
6584       bool giveBool() { return true; }
6585     };
6586 
6587     void target() {
6588       MyClass MyObj;
6589       bool Foo = MyObj.giveBool();
6590       // [[p]]
6591     }
6592   )";
6593   runDataflow(
6594       Code,
6595       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6596          ASTContext &ASTCtx) {
6597         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6598         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6599 
6600         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6601         ASSERT_THAT(FooDecl, NotNull());
6602 
6603         auto &FooVal = getFormula(*FooDecl, Env);
6604         EXPECT_TRUE(Env.proves(FooVal));
6605       },
6606       {BuiltinOptions{ContextSensitiveOptions{}}});
6607 }
6608 
6609 TEST(TransferTest, ContextSensitiveMethodGetter) {
6610   std::string Code = R"(
6611     class MyClass {
6612     public:
6613       bool getField() { return Field; }
6614 
6615       bool Field;
6616     };
6617 
6618     void target() {
6619       MyClass MyObj;
6620       MyObj.Field = true;
6621       bool Foo = MyObj.getField();
6622       // [[p]]
6623     }
6624   )";
6625   runDataflow(
6626       Code,
6627       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6628          ASTContext &ASTCtx) {
6629         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6630         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6631 
6632         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6633         ASSERT_THAT(FooDecl, NotNull());
6634 
6635         auto &FooVal = getFormula(*FooDecl, Env);
6636         EXPECT_TRUE(Env.proves(FooVal));
6637       },
6638       {BuiltinOptions{ContextSensitiveOptions{}}});
6639 }
6640 
6641 TEST(TransferTest, ContextSensitiveMethodSetter) {
6642   std::string Code = R"(
6643     class MyClass {
6644     public:
6645       void setField(bool Val) { Field = Val; }
6646 
6647       bool Field;
6648     };
6649 
6650     void target() {
6651       MyClass MyObj;
6652       MyObj.setField(true);
6653       bool Foo = MyObj.Field;
6654       // [[p]]
6655     }
6656   )";
6657   runDataflow(
6658       Code,
6659       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6660          ASTContext &ASTCtx) {
6661         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6662         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6663 
6664         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6665         ASSERT_THAT(FooDecl, NotNull());
6666 
6667         auto &FooVal = getFormula(*FooDecl, Env);
6668         EXPECT_TRUE(Env.proves(FooVal));
6669       },
6670       {BuiltinOptions{ContextSensitiveOptions{}}});
6671 }
6672 
6673 TEST(TransferTest, ContextSensitiveMethodGetterAndSetter) {
6674   std::string Code = R"(
6675     class MyClass {
6676     public:
6677       bool getField() { return Field; }
6678       void setField(bool Val) { Field = Val; }
6679 
6680     private:
6681       bool Field;
6682     };
6683 
6684     void target() {
6685       MyClass MyObj;
6686       MyObj.setField(true);
6687       bool Foo = MyObj.getField();
6688       // [[p]]
6689     }
6690   )";
6691   runDataflow(
6692       Code,
6693       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6694          ASTContext &ASTCtx) {
6695         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6696         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6697 
6698         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6699         ASSERT_THAT(FooDecl, NotNull());
6700 
6701         auto &FooVal = getFormula(*FooDecl, Env);
6702         EXPECT_TRUE(Env.proves(FooVal));
6703       },
6704       {BuiltinOptions{ContextSensitiveOptions{}}});
6705 }
6706 
6707 
6708 TEST(TransferTest, ContextSensitiveMethodTwoLayersVoid) {
6709   std::string Code = R"(
6710     class MyClass {
6711     public:
6712       void Inner() { MyField = true; }
6713       void Outer() { Inner(); }
6714 
6715       bool MyField;
6716     };
6717 
6718     void target() {
6719       MyClass MyObj;
6720       MyObj.Outer();
6721       bool Foo = MyObj.MyField;
6722       // [[p]]
6723     }
6724   )";
6725   runDataflow(
6726       Code,
6727       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6728          ASTContext &ASTCtx) {
6729         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6730         ;
6731         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6732 
6733         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6734         ASSERT_THAT(FooDecl, NotNull());
6735 
6736         auto &FooVal = getFormula(*FooDecl, Env);
6737         EXPECT_TRUE(Env.proves(FooVal));
6738       },
6739       {BuiltinOptions{ContextSensitiveOptions{}}});
6740 }
6741 
6742 TEST(TransferTest, ContextSensitiveMethodTwoLayersReturn) {
6743   std::string Code = R"(
6744     class MyClass {
6745     public:
6746       bool Inner() { return MyField; }
6747       bool Outer() { return Inner(); }
6748 
6749       bool MyField;
6750     };
6751 
6752     void target() {
6753       MyClass MyObj;
6754       MyObj.MyField = true;
6755       bool Foo = MyObj.Outer();
6756       // [[p]]
6757     }
6758   )";
6759   runDataflow(
6760       Code,
6761       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6762          ASTContext &ASTCtx) {
6763         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6764         ;
6765         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6766 
6767         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6768         ASSERT_THAT(FooDecl, NotNull());
6769 
6770         auto &FooVal = getFormula(*FooDecl, Env);
6771         EXPECT_TRUE(Env.proves(FooVal));
6772       },
6773       {BuiltinOptions{ContextSensitiveOptions{}}});
6774 }
6775 
6776 TEST(TransferTest, ContextSensitiveConstructorBody) {
6777   std::string Code = R"(
6778     class MyClass {
6779     public:
6780       MyClass() { MyField = true; }
6781 
6782       bool MyField;
6783     };
6784 
6785     void target() {
6786       MyClass MyObj;
6787       bool Foo = MyObj.MyField;
6788       // [[p]]
6789     }
6790   )";
6791   runDataflow(
6792       Code,
6793       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6794          ASTContext &ASTCtx) {
6795         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6796         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6797 
6798         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6799         ASSERT_THAT(FooDecl, NotNull());
6800 
6801         auto &FooVal = getFormula(*FooDecl, Env);
6802         EXPECT_TRUE(Env.proves(FooVal));
6803       },
6804       {BuiltinOptions{ContextSensitiveOptions{}}});
6805 }
6806 
6807 TEST(TransferTest, ContextSensitiveConstructorInitializer) {
6808   std::string Code = R"(
6809     class MyClass {
6810     public:
6811       MyClass() : MyField(true) {}
6812 
6813       bool MyField;
6814     };
6815 
6816     void target() {
6817       MyClass MyObj;
6818       bool Foo = MyObj.MyField;
6819       // [[p]]
6820     }
6821   )";
6822   runDataflow(
6823       Code,
6824       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6825          ASTContext &ASTCtx) {
6826         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6827         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6828 
6829         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6830         ASSERT_THAT(FooDecl, NotNull());
6831 
6832         auto &FooVal = getFormula(*FooDecl, Env);
6833         EXPECT_TRUE(Env.proves(FooVal));
6834       },
6835       {BuiltinOptions{ContextSensitiveOptions{}}});
6836 }
6837 
6838 TEST(TransferTest, ContextSensitiveConstructorDefault) {
6839   std::string Code = R"(
6840     class MyClass {
6841     public:
6842       MyClass() = default;
6843 
6844       bool MyField = true;
6845     };
6846 
6847     void target() {
6848       MyClass MyObj;
6849       bool Foo = MyObj.MyField;
6850       // [[p]]
6851     }
6852   )";
6853   runDataflow(
6854       Code,
6855       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6856          ASTContext &ASTCtx) {
6857         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6858         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6859 
6860         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6861         ASSERT_THAT(FooDecl, NotNull());
6862 
6863         auto &FooVal = getFormula(*FooDecl, Env);
6864         EXPECT_TRUE(Env.proves(FooVal));
6865       },
6866       {BuiltinOptions{ContextSensitiveOptions{}}});
6867 }
6868 
6869 TEST(TransferTest, ContextSensitiveSelfReferentialClass) {
6870   // Test that the `this` pointer seen in the constructor has the same value
6871   // as the address of the variable the object is constructed into.
6872   std::string Code = R"(
6873     class MyClass {
6874     public:
6875       MyClass() : Self(this) {}
6876       MyClass *Self;
6877     };
6878 
6879     void target() {
6880       MyClass MyObj;
6881       MyClass *SelfPtr = MyObj.Self;
6882       // [[p]]
6883     }
6884   )";
6885   runDataflow(
6886       Code,
6887       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6888          ASTContext &ASTCtx) {
6889         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6890 
6891         const ValueDecl *MyObjDecl = findValueDecl(ASTCtx, "MyObj");
6892         ASSERT_THAT(MyObjDecl, NotNull());
6893 
6894         const ValueDecl *SelfDecl = findValueDecl(ASTCtx, "SelfPtr");
6895         ASSERT_THAT(SelfDecl, NotNull());
6896 
6897         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6898         auto &SelfVal = *cast<PointerValue>(Env.getValue(*SelfDecl));
6899         EXPECT_EQ(Env.getStorageLocation(*MyObjDecl), &SelfVal.getPointeeLoc());
6900       },
6901       {BuiltinOptions{ContextSensitiveOptions{}}});
6902 }
6903 
6904 TEST(TransferTest, UnnamedBitfieldInitializer) {
6905   std::string Code = R"(
6906     struct B {};
6907     struct A {
6908       unsigned a;
6909       unsigned : 4;
6910       unsigned c;
6911       B b;
6912     };
6913     void target() {
6914       A a = {};
6915       A test = a;
6916       (void)test.c;
6917     }
6918   )";
6919   runDataflow(
6920       Code,
6921       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6922          ASTContext &ASTCtx) {
6923         // This doesn't need a body because this test was crashing the framework
6924         // before handling correctly Unnamed bitfields in `InitListExpr`.
6925       });
6926 }
6927 
6928 // Repro for a crash that used to occur with chained short-circuiting logical
6929 // operators.
6930 TEST(TransferTest, ChainedLogicalOps) {
6931   std::string Code = R"(
6932     bool target() {
6933       bool b = true || false || false || false;
6934       // [[p]]
6935       return b;
6936     }
6937   )";
6938   runDataflow(
6939       Code,
6940       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6941          ASTContext &ASTCtx) {
6942         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6943         auto &B = getValueForDecl<BoolValue>(ASTCtx, Env, "b").formula();
6944         EXPECT_TRUE(Env.proves(B));
6945       });
6946 }
6947 
6948 // Repro for a crash that used to occur when we call a `noreturn` function
6949 // within one of the operands of a `&&` or `||` operator.
6950 TEST(TransferTest, NoReturnFunctionInsideShortCircuitedBooleanOp) {
6951   std::string Code = R"(
6952     __attribute__((noreturn)) int doesnt_return();
6953     bool some_condition();
6954     void target(bool b1, bool b2) {
6955       // Neither of these should crash. In addition, if we don't terminate the
6956       // program, we know that the operators need to trigger the short-circuit
6957       // logic, so `NoreturnOnRhsOfAnd` will be false and `NoreturnOnRhsOfOr`
6958       // will be true.
6959       bool NoreturnOnRhsOfAnd = b1 && doesnt_return() > 0;
6960       bool NoreturnOnRhsOfOr = b2 || doesnt_return() > 0;
6961 
6962       // Calling a `noreturn` function on the LHS of an `&&` or `||` makes the
6963       // entire expression unreachable. So we know that in both of the following
6964       // cases, if `target()` terminates, the `else` branch was taken.
6965       bool NoreturnOnLhsMakesAndUnreachable = false;
6966       if (some_condition())
6967          doesnt_return() > 0 && some_condition();
6968       else
6969          NoreturnOnLhsMakesAndUnreachable = true;
6970 
6971       bool NoreturnOnLhsMakesOrUnreachable = false;
6972       if (some_condition())
6973          doesnt_return() > 0 || some_condition();
6974       else
6975          NoreturnOnLhsMakesOrUnreachable = true;
6976 
6977       // [[p]]
6978     }
6979   )";
6980   runDataflow(
6981       Code,
6982       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6983          ASTContext &ASTCtx) {
6984         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6985         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6986         auto &A = Env.arena();
6987 
6988         // Check that [[p]] is reachable with a non-false flow condition.
6989         EXPECT_FALSE(Env.proves(A.makeLiteral(false)));
6990 
6991         auto &B1 = getValueForDecl<BoolValue>(ASTCtx, Env, "b1").formula();
6992         EXPECT_TRUE(Env.proves(A.makeNot(B1)));
6993 
6994         auto &NoreturnOnRhsOfAnd =
6995             getValueForDecl<BoolValue>(ASTCtx, Env, "NoreturnOnRhsOfAnd").formula();
6996         EXPECT_TRUE(Env.proves(A.makeNot(NoreturnOnRhsOfAnd)));
6997 
6998         auto &B2 = getValueForDecl<BoolValue>(ASTCtx, Env, "b2").formula();
6999         EXPECT_TRUE(Env.proves(B2));
7000 
7001         auto &NoreturnOnRhsOfOr =
7002             getValueForDecl<BoolValue>(ASTCtx, Env, "NoreturnOnRhsOfOr")
7003                 .formula();
7004         EXPECT_TRUE(Env.proves(NoreturnOnRhsOfOr));
7005 
7006         auto &NoreturnOnLhsMakesAndUnreachable = getValueForDecl<BoolValue>(
7007             ASTCtx, Env, "NoreturnOnLhsMakesAndUnreachable").formula();
7008         EXPECT_TRUE(Env.proves(NoreturnOnLhsMakesAndUnreachable));
7009 
7010         auto &NoreturnOnLhsMakesOrUnreachable = getValueForDecl<BoolValue>(
7011             ASTCtx, Env, "NoreturnOnLhsMakesOrUnreachable").formula();
7012         EXPECT_TRUE(Env.proves(NoreturnOnLhsMakesOrUnreachable));
7013       });
7014 }
7015 
7016 TEST(TransferTest, NewExpressions) {
7017   std::string Code = R"(
7018     void target() {
7019       int *p = new int(42);
7020       // [[after_new]]
7021     }
7022   )";
7023   runDataflow(
7024       Code,
7025       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
7026          ASTContext &ASTCtx) {
7027         const Environment &Env =
7028             getEnvironmentAtAnnotation(Results, "after_new");
7029 
7030         auto &P = getValueForDecl<PointerValue>(ASTCtx, Env, "p");
7031 
7032         EXPECT_THAT(Env.getValue(P.getPointeeLoc()), NotNull());
7033       });
7034 }
7035 
7036 TEST(TransferTest, NewExpressions_Structs) {
7037   std::string Code = R"(
7038     struct Inner {
7039       int InnerField;
7040     };
7041 
7042     struct Outer {
7043       Inner OuterField;
7044     };
7045 
7046     void target() {
7047       Outer *p = new Outer;
7048       // Access the fields to make sure the analysis actually generates children
7049       // for them in the `RecordStorageLocation`.
7050       p->OuterField.InnerField;
7051       // [[after_new]]
7052     }
7053   )";
7054   runDataflow(
7055       Code,
7056       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
7057          ASTContext &ASTCtx) {
7058         const Environment &Env =
7059             getEnvironmentAtAnnotation(Results, "after_new");
7060 
7061         const ValueDecl *OuterField = findValueDecl(ASTCtx, "OuterField");
7062         const ValueDecl *InnerField = findValueDecl(ASTCtx, "InnerField");
7063 
7064         auto &P = getValueForDecl<PointerValue>(ASTCtx, Env, "p");
7065 
7066         auto &OuterLoc = cast<RecordStorageLocation>(P.getPointeeLoc());
7067         auto &OuterFieldLoc =
7068             *cast<RecordStorageLocation>(OuterLoc.getChild(*OuterField));
7069         auto &InnerFieldLoc = *OuterFieldLoc.getChild(*InnerField);
7070 
7071         EXPECT_THAT(Env.getValue(InnerFieldLoc), NotNull());
7072       });
7073 }
7074 
7075 TEST(TransferTest, FunctionToPointerDecayHasValue) {
7076   std::string Code = R"(
7077     struct A { static void static_member_func(); };
7078     void target() {
7079       // To check that we're treating function-to-pointer decay correctly,
7080       // create two pointers, then verify they refer to the same storage
7081       // location.
7082       // We need to do the test this way because even if an initializer (in this
7083       // case, the function-to-pointer decay) does not create a value, we still
7084       // create a value for the variable.
7085       void (*non_member_p1)() = target;
7086       void (*non_member_p2)() = target;
7087 
7088       // Do the same thing but for a static member function.
7089       void (*member_p1)() = A::static_member_func;
7090       void (*member_p2)() = A::static_member_func;
7091       // [[p]]
7092     }
7093   )";
7094   runDataflow(
7095       Code,
7096       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
7097          ASTContext &ASTCtx) {
7098         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
7099 
7100         auto &NonMemberP1 =
7101             getValueForDecl<PointerValue>(ASTCtx, Env, "non_member_p1");
7102         auto &NonMemberP2 =
7103             getValueForDecl<PointerValue>(ASTCtx, Env, "non_member_p2");
7104         EXPECT_EQ(&NonMemberP1.getPointeeLoc(), &NonMemberP2.getPointeeLoc());
7105 
7106         auto &MemberP1 =
7107             getValueForDecl<PointerValue>(ASTCtx, Env, "member_p1");
7108         auto &MemberP2 =
7109             getValueForDecl<PointerValue>(ASTCtx, Env, "member_p2");
7110         EXPECT_EQ(&MemberP1.getPointeeLoc(), &MemberP2.getPointeeLoc());
7111       });
7112 }
7113 
7114 // Check that a builtin function is not associated with a value. (It's only
7115 // possible to call builtin functions directly, not take their address.)
7116 TEST(TransferTest, BuiltinFunctionModeled) {
7117   std::string Code = R"(
7118     void target() {
7119       __builtin_expect(0, 0);
7120       // [[p]]
7121     }
7122   )";
7123   runDataflow(
7124       Code,
7125       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
7126          ASTContext &ASTCtx) {
7127         using ast_matchers::selectFirst;
7128         using ast_matchers::match;
7129         using ast_matchers::traverse;
7130         using ast_matchers::implicitCastExpr;
7131         using ast_matchers::hasCastKind;
7132 
7133         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
7134 
7135         auto *ImplicitCast = selectFirst<ImplicitCastExpr>(
7136             "implicit_cast",
7137             match(traverse(TK_AsIs,
7138                            implicitCastExpr(hasCastKind(CK_BuiltinFnToFnPtr))
7139                                .bind("implicit_cast")),
7140                   ASTCtx));
7141 
7142         ASSERT_THAT(ImplicitCast, NotNull());
7143         EXPECT_THAT(Env.getValue(*ImplicitCast), IsNull());
7144       });
7145 }
7146 
7147 // Check that a callee of a member operator call is modeled as a `PointerValue`.
7148 // Member operator calls are unusual in that their callee is a pointer that
7149 // stems from a `FunctionToPointerDecay`. In calls to non-operator non-static
7150 // member functions, the callee is a `MemberExpr` (which does not have pointer
7151 // type).
7152 // We want to make sure that we produce a pointer value for the callee in this
7153 // specific scenario and that its storage location is durable (for convergence).
7154 TEST(TransferTest, MemberOperatorCallModelsPointerForCallee) {
7155   std::string Code = R"(
7156     struct S {
7157       bool operator!=(S s);
7158     };
7159     void target() {
7160       S s;
7161       (void)(s != s);
7162       (void)(s != s);
7163       // [[p]]
7164     }
7165   )";
7166   runDataflow(
7167       Code,
7168       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
7169          ASTContext &ASTCtx) {
7170         using ast_matchers::selectFirst;
7171         using ast_matchers::match;
7172         using ast_matchers::traverse;
7173         using ast_matchers::cxxOperatorCallExpr;
7174 
7175         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
7176 
7177         auto Matches = match(
7178             traverse(TK_AsIs, cxxOperatorCallExpr().bind("call")), ASTCtx);
7179 
7180         ASSERT_EQ(Matches.size(), 2UL);
7181 
7182         auto *Call1 = Matches[0].getNodeAs<CXXOperatorCallExpr>("call");
7183         auto *Call2 = Matches[1].getNodeAs<CXXOperatorCallExpr>("call");
7184 
7185         ASSERT_THAT(Call1, NotNull());
7186         ASSERT_THAT(Call2, NotNull());
7187 
7188         EXPECT_EQ(cast<ImplicitCastExpr>(Call1->getCallee())->getCastKind(),
7189                   CK_FunctionToPointerDecay);
7190         EXPECT_EQ(cast<ImplicitCastExpr>(Call2->getCallee())->getCastKind(),
7191                   CK_FunctionToPointerDecay);
7192 
7193         auto *Ptr1 = cast<PointerValue>(Env.getValue(*Call1->getCallee()));
7194         auto *Ptr2 = cast<PointerValue>(Env.getValue(*Call2->getCallee()));
7195 
7196         ASSERT_EQ(&Ptr1->getPointeeLoc(), &Ptr2->getPointeeLoc());
7197       });
7198 }
7199 
7200 // Check that fields of anonymous records are modeled.
7201 TEST(TransferTest, AnonymousStruct) {
7202   std::string Code = R"(
7203     struct S {
7204       struct {
7205         bool b;
7206       };
7207     };
7208     void target() {
7209       S s;
7210       s.b = true;
7211       // [[p]]
7212     }
7213   )";
7214   runDataflow(
7215       Code,
7216       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
7217          ASTContext &ASTCtx) {
7218         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
7219         const ValueDecl *SDecl = findValueDecl(ASTCtx, "s");
7220         const ValueDecl *BDecl = findValueDecl(ASTCtx, "b");
7221         const IndirectFieldDecl *IndirectField =
7222             findIndirectFieldDecl(ASTCtx, "b");
7223 
7224         auto *S = cast<RecordStorageLocation>(Env.getStorageLocation(*SDecl));
7225         auto &AnonStruct = *cast<RecordStorageLocation>(
7226             S->getChild(*cast<ValueDecl>(IndirectField->chain().front())));
7227 
7228         auto *B = cast<BoolValue>(getFieldValue(&AnonStruct, *BDecl, Env));
7229         ASSERT_TRUE(Env.proves(B->formula()));
7230       });
7231 }
7232 
7233 TEST(TransferTest, AnonymousStructWithInitializer) {
7234   std::string Code = R"(
7235     struct target {
7236       target() {
7237         (void)0;
7238         // [[p]]
7239       }
7240       struct {
7241         bool b = true;
7242       };
7243     };
7244   )";
7245   runDataflow(
7246       Code,
7247       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
7248          ASTContext &ASTCtx) {
7249         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
7250         const ValueDecl *BDecl = findValueDecl(ASTCtx, "b");
7251         const IndirectFieldDecl *IndirectField =
7252             findIndirectFieldDecl(ASTCtx, "b");
7253 
7254         auto *ThisLoc =
7255             cast<RecordStorageLocation>(Env.getThisPointeeStorageLocation());
7256         auto &AnonStruct = *cast<RecordStorageLocation>(ThisLoc->getChild(
7257             *cast<ValueDecl>(IndirectField->chain().front())));
7258 
7259         auto *B = cast<BoolValue>(getFieldValue(&AnonStruct, *BDecl, Env));
7260         ASSERT_TRUE(Env.proves(B->formula()));
7261       });
7262 }
7263 
7264 TEST(TransferTest, AnonymousStructWithReferenceField) {
7265   std::string Code = R"(
7266     int global_i = 0;
7267     struct target {
7268       target() {
7269         (void)0;
7270         // [[p]]
7271       }
7272       struct {
7273         int &i = global_i;
7274       };
7275     };
7276   )";
7277   runDataflow(
7278       Code,
7279       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
7280          ASTContext &ASTCtx) {
7281         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
7282         const ValueDecl *GlobalIDecl = findValueDecl(ASTCtx, "global_i");
7283         const ValueDecl *IDecl = findValueDecl(ASTCtx, "i");
7284         const IndirectFieldDecl *IndirectField =
7285             findIndirectFieldDecl(ASTCtx, "i");
7286 
7287         auto *ThisLoc =
7288             cast<RecordStorageLocation>(Env.getThisPointeeStorageLocation());
7289         auto &AnonStruct = *cast<RecordStorageLocation>(ThisLoc->getChild(
7290             *cast<ValueDecl>(IndirectField->chain().front())));
7291 
7292         ASSERT_EQ(AnonStruct.getChild(*IDecl),
7293                   Env.getStorageLocation(*GlobalIDecl));
7294       });
7295 }
7296 
7297 TEST(TransferTest, EvaluateBlockWithUnreachablePreds) {
7298   // This is a crash repro.
7299   // `false` block may not have been processed when we try to evaluate the `||`
7300   // after visiting `true`, because it is not necessary (and therefore the edge
7301   // is marked unreachable). Trying to get the analysis state via
7302   // `getEnvironment` for the subexpression still should not crash.
7303   std::string Code = R"(
7304     int target(int i) {
7305       if ((i < 0 && true) || false) {
7306         return 0;
7307       }
7308       return 0;
7309     }
7310   )";
7311   runDataflow(
7312       Code,
7313       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
7314          ASTContext &ASTCtx) {});
7315 }
7316 
7317 TEST(TransferTest, LambdaCaptureByCopy) {
7318   std::string Code = R"(
7319     void target(int Foo, int Bar) {
7320       [Foo]() {
7321         (void)0;
7322         // [[p]]
7323       }();
7324     }
7325   )";
7326   runDataflowOnLambda(
7327       Code,
7328       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
7329          ASTContext &ASTCtx) {
7330         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
7331         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
7332 
7333         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
7334         ASSERT_THAT(FooDecl, NotNull());
7335 
7336         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
7337         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
7338 
7339         const Value *FooVal = Env.getValue(*FooLoc);
7340         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
7341 
7342         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
7343         ASSERT_THAT(BarDecl, NotNull());
7344 
7345         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
7346         EXPECT_THAT(BarLoc, IsNull());
7347       });
7348 }
7349 
7350 TEST(TransferTest, LambdaCaptureByReference) {
7351   std::string Code = R"(
7352     void target(int Foo, int Bar) {
7353       [&Foo]() {
7354         (void)0;
7355         // [[p]]
7356       }();
7357     }
7358   )";
7359   runDataflowOnLambda(
7360       Code,
7361       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
7362          ASTContext &ASTCtx) {
7363         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
7364         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
7365 
7366         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
7367         ASSERT_THAT(FooDecl, NotNull());
7368 
7369         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
7370         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
7371 
7372         const Value *FooVal = Env.getValue(*FooLoc);
7373         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
7374 
7375         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
7376         ASSERT_THAT(BarDecl, NotNull());
7377 
7378         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
7379         EXPECT_THAT(BarLoc, IsNull());
7380       });
7381 }
7382 
7383 TEST(TransferTest, LambdaCaptureWithInitializer) {
7384   std::string Code = R"(
7385     void target(int Bar) {
7386       [Foo=Bar]() {
7387         (void)0;
7388         // [[p]]
7389       }();
7390     }
7391   )";
7392   runDataflowOnLambda(
7393       Code,
7394       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
7395          ASTContext &ASTCtx) {
7396         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
7397         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
7398 
7399         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
7400         ASSERT_THAT(FooDecl, NotNull());
7401 
7402         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
7403         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
7404 
7405         const Value *FooVal = Env.getValue(*FooLoc);
7406         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
7407 
7408         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
7409         ASSERT_THAT(BarDecl, NotNull());
7410 
7411         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
7412         EXPECT_THAT(BarLoc, IsNull());
7413       });
7414 }
7415 
7416 TEST(TransferTest, LambdaCaptureByCopyImplicit) {
7417   std::string Code = R"(
7418     void target(int Foo, int Bar) {
7419       [=]() {
7420         Foo;
7421         // [[p]]
7422       }();
7423     }
7424   )";
7425   runDataflowOnLambda(
7426       Code,
7427       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
7428          ASTContext &ASTCtx) {
7429         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
7430         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
7431 
7432         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
7433         ASSERT_THAT(FooDecl, NotNull());
7434 
7435         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
7436         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
7437 
7438         const Value *FooVal = Env.getValue(*FooLoc);
7439         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
7440 
7441         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
7442         ASSERT_THAT(BarDecl, NotNull());
7443 
7444         // There is no storage location for `Bar` because it isn't used in the
7445         // body of the lambda.
7446         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
7447         EXPECT_THAT(BarLoc, IsNull());
7448       });
7449 }
7450 
7451 TEST(TransferTest, LambdaCaptureByReferenceImplicit) {
7452   std::string Code = R"(
7453     void target(int Foo, int Bar) {
7454       [&]() {
7455         Foo;
7456         // [[p]]
7457       }();
7458     }
7459   )";
7460   runDataflowOnLambda(
7461       Code,
7462       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
7463          ASTContext &ASTCtx) {
7464         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
7465         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
7466 
7467         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
7468         ASSERT_THAT(FooDecl, NotNull());
7469 
7470         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
7471         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
7472 
7473         const Value *FooVal = Env.getValue(*FooLoc);
7474         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
7475 
7476         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
7477         ASSERT_THAT(BarDecl, NotNull());
7478 
7479         // There is no storage location for `Bar` because it isn't used in the
7480         // body of the lambda.
7481         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
7482         EXPECT_THAT(BarLoc, IsNull());
7483       });
7484 }
7485 
7486 TEST(TransferTest, LambdaCaptureThis) {
7487   std::string Code = R"(
7488     struct Bar {
7489       int Foo;
7490 
7491       void target() {
7492         [this]() {
7493           Foo;
7494           // [[p]]
7495         }();
7496       }
7497     };
7498   )";
7499   runDataflowOnLambda(
7500       Code,
7501       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
7502          ASTContext &ASTCtx) {
7503         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
7504         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
7505 
7506         const RecordStorageLocation *ThisPointeeLoc =
7507             Env.getThisPointeeStorageLocation();
7508         ASSERT_THAT(ThisPointeeLoc, NotNull());
7509 
7510         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
7511         ASSERT_THAT(FooDecl, NotNull());
7512 
7513         const StorageLocation *FooLoc = ThisPointeeLoc->getChild(*FooDecl);
7514         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
7515 
7516         const Value *FooVal = Env.getValue(*FooLoc);
7517         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
7518       });
7519 }
7520 
7521 // This test verifies correct modeling of a relational dependency that goes
7522 // through unmodeled functions (the simple `cond()` in this case).
7523 TEST(TransferTest, ConditionalRelation) {
7524   std::string Code = R"(
7525     bool cond();
7526     void target() {
7527        bool a = true;
7528        bool b = true;
7529        if (cond()) {
7530          a = false;
7531          if (cond()) {
7532            b = false;
7533          }
7534        }
7535        (void)0;
7536        // [[p]]
7537     }
7538  )";
7539   runDataflow(
7540       Code,
7541       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
7542          ASTContext &ASTCtx) {
7543         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
7544         auto &A = Env.arena();
7545         auto &VarA = getValueForDecl<BoolValue>(ASTCtx, Env, "a").formula();
7546         auto &VarB = getValueForDecl<BoolValue>(ASTCtx, Env, "b").formula();
7547 
7548         EXPECT_FALSE(Env.allows(A.makeAnd(VarA, A.makeNot(VarB))));
7549       });
7550 }
7551 
7552 // This is a crash repro.
7553 // We used to crash while transferring `S().i` because Clang contained a bug
7554 // causing the AST to be malformed.
7555 TEST(TransferTest, AnonymousUnionMemberExprInTemplate) {
7556   using ast_matchers::functionDecl;
7557   using ast_matchers::hasName;
7558   using ast_matchers::unless;
7559 
7560   std::string Code = R"cc(
7561     struct S {
7562       struct {
7563         int i;
7564       };
7565     };
7566 
7567     template <class>
7568     void target() {
7569         S().i;
7570     }
7571 
7572     template void target<int>();
7573   )cc";
7574   auto Matcher = functionDecl(hasName("target"), unless(isTemplated()));
7575   ASSERT_THAT_ERROR(checkDataflowWithNoopAnalysis(Code, Matcher),
7576                     llvm::Succeeded());
7577 }
7578 
7579 } // namespace
7580