xref: /llvm-project/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp (revision 6e96e5ab8a0e40fba0302a5c32574be41ef57354)
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, StructModeledFieldsWithComplicatedInheritance) {
1641   std::string Code = R"(
1642     struct Base1 {
1643       int base1_1;
1644       int base1_2;
1645     };
1646     struct Intermediate : Base1 {
1647       int intermediate_1;
1648       int intermediate_2;
1649     };
1650     struct Base2 {
1651       int base2_1;
1652       int base2_2;
1653     };
1654     struct MostDerived : public Intermediate, Base2 {
1655       int most_derived_1;
1656       int most_derived_2;
1657     };
1658 
1659     void target() {
1660       MostDerived MD;
1661       MD.base1_2 = 1;
1662       MD.intermediate_2 = 1;
1663       MD.base2_2 = 1;
1664       MD.most_derived_2 = 1;
1665       // [[p]]
1666     }
1667   )";
1668   runDataflow(
1669       Code,
1670       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1671          ASTContext &ASTCtx) {
1672         const Environment &Env =
1673               getEnvironmentAtAnnotation(Results, "p");
1674 
1675         // Only the accessed fields should exist in the model.
1676         auto &MDLoc = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "MD");
1677         std::vector<const ValueDecl*> Fields;
1678         for (auto [Field, _] : MDLoc.children())
1679           Fields.push_back(Field);
1680         ASSERT_THAT(Fields, UnorderedElementsAre(
1681             findValueDecl(ASTCtx, "base1_2"),
1682             findValueDecl(ASTCtx, "intermediate_2"),
1683             findValueDecl(ASTCtx, "base2_2"),
1684             findValueDecl(ASTCtx, "most_derived_2")));
1685       });
1686 }
1687 
1688 TEST(TransferTest, StructInitializerListWithComplicatedInheritance) {
1689   std::string Code = R"(
1690     struct Base1 {
1691       int base1;
1692     };
1693     struct Intermediate : Base1 {
1694       int intermediate;
1695     };
1696     struct Base2 {
1697       int base2;
1698     };
1699     struct MostDerived : public Intermediate, Base2 {
1700       int most_derived;
1701     };
1702 
1703     void target() {
1704       MostDerived MD = {};
1705       // [[p]]
1706     }
1707   )";
1708   runDataflow(
1709       Code,
1710       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1711          ASTContext &ASTCtx) {
1712         const Environment &Env =
1713               getEnvironmentAtAnnotation(Results, "p");
1714 
1715         // When a struct is initialized with a initializer list, all the
1716         // fields are considered "accessed", and therefore do exist.
1717         auto &MD = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "MD");
1718         ASSERT_THAT(cast<IntegerValue>(
1719             getFieldValue(&MD, *findValueDecl(ASTCtx, "base1"), Env)),
1720             NotNull());
1721         ASSERT_THAT(cast<IntegerValue>(
1722             getFieldValue(&MD, *findValueDecl(ASTCtx, "intermediate"), Env)),
1723             NotNull());
1724         ASSERT_THAT(cast<IntegerValue>(
1725             getFieldValue(&MD, *findValueDecl(ASTCtx, "base2"), Env)),
1726             NotNull());
1727         ASSERT_THAT(cast<IntegerValue>(
1728             getFieldValue(&MD, *findValueDecl(ASTCtx, "most_derived"), Env)),
1729             NotNull());
1730       });
1731 }
1732 
1733 TEST(TransferTest, ReferenceMember) {
1734   std::string Code = R"(
1735     struct A {
1736       int &Bar;
1737     };
1738 
1739     void target(A Foo) {
1740       int Baz = Foo.Bar;
1741       // [[p]]
1742     }
1743   )";
1744   runDataflow(
1745       Code,
1746       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1747          ASTContext &ASTCtx) {
1748         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1749         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1750 
1751         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1752         ASSERT_THAT(FooDecl, NotNull());
1753 
1754         ASSERT_TRUE(FooDecl->getType()->isStructureType());
1755         auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields();
1756 
1757         FieldDecl *BarDecl = nullptr;
1758         for (FieldDecl *Field : FooFields) {
1759           if (Field->getNameAsString() == "Bar") {
1760             BarDecl = Field;
1761           } else {
1762             FAIL() << "Unexpected field: " << Field->getNameAsString();
1763           }
1764         }
1765         ASSERT_THAT(BarDecl, NotNull());
1766 
1767         const auto *FooLoc =
1768             cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
1769         const auto *BarReferentVal =
1770             cast<IntegerValue>(getFieldValue(FooLoc, *BarDecl, Env));
1771 
1772         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
1773         ASSERT_THAT(BazDecl, NotNull());
1774 
1775         EXPECT_EQ(Env.getValue(*BazDecl), BarReferentVal);
1776       });
1777 }
1778 
1779 TEST(TransferTest, StructThisMember) {
1780   std::string Code = R"(
1781     struct A {
1782       int Bar;
1783 
1784       struct B {
1785         int Baz;
1786       };
1787 
1788       B Qux;
1789 
1790       void target() {
1791         int Foo = Bar;
1792         int Quux = Qux.Baz;
1793         // [[p]]
1794       }
1795     };
1796   )";
1797   runDataflow(
1798       Code,
1799       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1800          ASTContext &ASTCtx) {
1801         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1802         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1803 
1804         const auto *ThisLoc = Env.getThisPointeeStorageLocation();
1805         ASSERT_THAT(ThisLoc, NotNull());
1806 
1807         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1808         ASSERT_THAT(BarDecl, NotNull());
1809 
1810         const auto *BarLoc =
1811             cast<ScalarStorageLocation>(ThisLoc->getChild(*BarDecl));
1812         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
1813 
1814         const Value *BarVal = Env.getValue(*BarLoc);
1815         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
1816 
1817         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1818         ASSERT_THAT(FooDecl, NotNull());
1819         EXPECT_EQ(Env.getValue(*FooDecl), BarVal);
1820 
1821         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
1822         ASSERT_THAT(QuxDecl, NotNull());
1823 
1824         ASSERT_TRUE(QuxDecl->getType()->isStructureType());
1825         auto QuxFields = QuxDecl->getType()->getAsRecordDecl()->fields();
1826 
1827         FieldDecl *BazDecl = nullptr;
1828         for (FieldDecl *Field : QuxFields) {
1829           if (Field->getNameAsString() == "Baz") {
1830             BazDecl = Field;
1831           } else {
1832             FAIL() << "Unexpected field: " << Field->getNameAsString();
1833           }
1834         }
1835         ASSERT_THAT(BazDecl, NotNull());
1836 
1837         const auto *QuxLoc =
1838             cast<RecordStorageLocation>(ThisLoc->getChild(*QuxDecl));
1839 
1840         const auto *BazVal =
1841             cast<IntegerValue>(getFieldValue(QuxLoc, *BazDecl, Env));
1842 
1843         const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux");
1844         ASSERT_THAT(QuuxDecl, NotNull());
1845         EXPECT_EQ(Env.getValue(*QuuxDecl), BazVal);
1846       });
1847 }
1848 
1849 TEST(TransferTest, ClassThisMember) {
1850   std::string Code = R"(
1851     class A {
1852       int Bar;
1853 
1854       class B {
1855       public:
1856         int Baz;
1857       };
1858 
1859       B Qux;
1860 
1861       void target() {
1862         int Foo = Bar;
1863         int Quux = Qux.Baz;
1864         // [[p]]
1865       }
1866     };
1867   )";
1868   runDataflow(
1869       Code,
1870       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1871          ASTContext &ASTCtx) {
1872         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1873         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1874 
1875         const auto *ThisLoc = Env.getThisPointeeStorageLocation();
1876 
1877         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1878         ASSERT_THAT(BarDecl, NotNull());
1879 
1880         const auto *BarLoc =
1881             cast<ScalarStorageLocation>(ThisLoc->getChild(*BarDecl));
1882         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
1883 
1884         const Value *BarVal = Env.getValue(*BarLoc);
1885         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
1886 
1887         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1888         ASSERT_THAT(FooDecl, NotNull());
1889         EXPECT_EQ(Env.getValue(*FooDecl), BarVal);
1890 
1891         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
1892         ASSERT_THAT(QuxDecl, NotNull());
1893 
1894         ASSERT_TRUE(QuxDecl->getType()->isClassType());
1895         auto QuxFields = QuxDecl->getType()->getAsRecordDecl()->fields();
1896 
1897         FieldDecl *BazDecl = nullptr;
1898         for (FieldDecl *Field : QuxFields) {
1899           if (Field->getNameAsString() == "Baz") {
1900             BazDecl = Field;
1901           } else {
1902             FAIL() << "Unexpected field: " << Field->getNameAsString();
1903           }
1904         }
1905         ASSERT_THAT(BazDecl, NotNull());
1906 
1907         const auto *QuxLoc =
1908             cast<RecordStorageLocation>(ThisLoc->getChild(*QuxDecl));
1909 
1910         const auto *BazVal =
1911             cast<IntegerValue>(getFieldValue(QuxLoc, *BazDecl, Env));
1912 
1913         const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux");
1914         ASSERT_THAT(QuuxDecl, NotNull());
1915         EXPECT_EQ(Env.getValue(*QuuxDecl), BazVal);
1916       });
1917 }
1918 
1919 TEST(TransferTest, UnionThisMember) {
1920   std::string Code = R"(
1921     union A {
1922       int Foo;
1923       int Bar;
1924 
1925       void target() {
1926         A a;
1927         // Mention the fields to ensure they're included in the analysis.
1928         (void)a.Foo;
1929         (void)a.Bar;
1930         // [[p]]
1931       }
1932     };
1933   )";
1934   runDataflow(
1935       Code,
1936       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1937          ASTContext &ASTCtx) {
1938         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1939         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1940 
1941         const auto *ThisLoc = Env.getThisPointeeStorageLocation();
1942         ASSERT_THAT(ThisLoc, NotNull());
1943 
1944         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1945         ASSERT_THAT(FooDecl, NotNull());
1946 
1947         const auto *FooLoc =
1948             cast<ScalarStorageLocation>(ThisLoc->getChild(*FooDecl));
1949         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
1950 
1951         const Value *FooVal = Env.getValue(*FooLoc);
1952         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
1953 
1954         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1955         ASSERT_THAT(BarDecl, NotNull());
1956 
1957         const auto *BarLoc =
1958             cast<ScalarStorageLocation>(ThisLoc->getChild(*BarDecl));
1959         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
1960 
1961         const Value *BarVal = Env.getValue(*BarLoc);
1962         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
1963       });
1964 }
1965 
1966 TEST(TransferTest, StructThisInLambda) {
1967   std::string ThisCaptureCode = R"(
1968     struct A {
1969       void frob() {
1970         [this]() {
1971           int Foo = Bar;
1972           // [[p1]]
1973         }();
1974       }
1975 
1976       int Bar;
1977     };
1978   )";
1979   runDataflow(
1980       ThisCaptureCode,
1981       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1982          ASTContext &ASTCtx) {
1983         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1"));
1984         const Environment &Env = getEnvironmentAtAnnotation(Results, "p1");
1985 
1986         const auto *ThisLoc = Env.getThisPointeeStorageLocation();
1987         ASSERT_THAT(ThisLoc, NotNull());
1988 
1989         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1990         ASSERT_THAT(BarDecl, NotNull());
1991 
1992         const auto *BarLoc =
1993             cast<ScalarStorageLocation>(ThisLoc->getChild(*BarDecl));
1994         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
1995 
1996         const Value *BarVal = Env.getValue(*BarLoc);
1997         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
1998 
1999         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2000         ASSERT_THAT(FooDecl, NotNull());
2001         EXPECT_EQ(Env.getValue(*FooDecl), BarVal);
2002       },
2003       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator()");
2004 
2005   std::string RefCaptureDefaultCode = R"(
2006     struct A {
2007       void frob() {
2008         [&]() {
2009           int Foo = Bar;
2010           // [[p2]]
2011         }();
2012       }
2013 
2014       int Bar;
2015     };
2016   )";
2017   runDataflow(
2018       RefCaptureDefaultCode,
2019       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2020          ASTContext &ASTCtx) {
2021         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p2"));
2022         const Environment &Env = getEnvironmentAtAnnotation(Results, "p2");
2023 
2024         const auto *ThisLoc = Env.getThisPointeeStorageLocation();
2025         ASSERT_THAT(ThisLoc, NotNull());
2026 
2027         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2028         ASSERT_THAT(BarDecl, NotNull());
2029 
2030         const auto *BarLoc =
2031             cast<ScalarStorageLocation>(ThisLoc->getChild(*BarDecl));
2032         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
2033 
2034         const Value *BarVal = Env.getValue(*BarLoc);
2035         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
2036 
2037         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2038         ASSERT_THAT(FooDecl, NotNull());
2039         EXPECT_EQ(Env.getValue(*FooDecl), BarVal);
2040       },
2041       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator()");
2042 
2043   std::string FreeFunctionLambdaCode = R"(
2044     void foo() {
2045       int Bar;
2046       [&]() {
2047         int Foo = Bar;
2048         // [[p3]]
2049       }();
2050     }
2051   )";
2052   runDataflow(
2053       FreeFunctionLambdaCode,
2054       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2055          ASTContext &ASTCtx) {
2056         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p3"));
2057         const Environment &Env = getEnvironmentAtAnnotation(Results, "p3");
2058 
2059         EXPECT_THAT(Env.getThisPointeeStorageLocation(), IsNull());
2060       },
2061       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator()");
2062 }
2063 
2064 TEST(TransferTest, ConstructorInitializer) {
2065   std::string Code = R"(
2066     struct target {
2067       int Bar;
2068 
2069       target(int Foo) : Bar(Foo) {
2070         int Qux = Bar;
2071         // [[p]]
2072       }
2073     };
2074   )";
2075   runDataflow(
2076       Code,
2077       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2078          ASTContext &ASTCtx) {
2079         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2080         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2081 
2082         const auto *ThisLoc = Env.getThisPointeeStorageLocation();
2083         ASSERT_THAT(ThisLoc, NotNull());
2084 
2085         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2086         ASSERT_THAT(FooDecl, NotNull());
2087 
2088         const auto *FooVal = cast<IntegerValue>(Env.getValue(*FooDecl));
2089 
2090         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
2091         ASSERT_THAT(QuxDecl, NotNull());
2092         EXPECT_EQ(Env.getValue(*QuxDecl), FooVal);
2093       });
2094 }
2095 
2096 TEST(TransferTest, DefaultInitializer) {
2097   std::string Code = R"(
2098     struct target {
2099       int Bar;
2100       int Baz = Bar;
2101 
2102       target(int Foo) : Bar(Foo) {
2103         int Qux = Baz;
2104         // [[p]]
2105       }
2106     };
2107   )";
2108   runDataflow(
2109       Code,
2110       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2111          ASTContext &ASTCtx) {
2112         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2113         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2114 
2115         const auto *ThisLoc = Env.getThisPointeeStorageLocation();
2116         ASSERT_THAT(ThisLoc, NotNull());
2117 
2118         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2119         ASSERT_THAT(FooDecl, NotNull());
2120 
2121         const auto *FooVal = cast<IntegerValue>(Env.getValue(*FooDecl));
2122 
2123         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
2124         ASSERT_THAT(QuxDecl, NotNull());
2125         EXPECT_EQ(Env.getValue(*QuxDecl), FooVal);
2126       });
2127 }
2128 
2129 TEST(TransferTest, DefaultInitializerReference) {
2130   std::string Code = R"(
2131     struct target {
2132       int &Bar;
2133       int &Baz = Bar;
2134 
2135       target(int &Foo) : Bar(Foo) {
2136         int &Qux = Baz;
2137         // [[p]]
2138       }
2139     };
2140   )";
2141   runDataflow(
2142       Code,
2143       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2144          ASTContext &ASTCtx) {
2145         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2146         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2147 
2148         const auto *ThisLoc = Env.getThisPointeeStorageLocation();
2149         ASSERT_THAT(ThisLoc, NotNull());
2150 
2151         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2152         ASSERT_THAT(FooDecl, NotNull());
2153 
2154         const auto *FooLoc = Env.getStorageLocation(*FooDecl);
2155 
2156         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
2157         ASSERT_THAT(QuxDecl, NotNull());
2158 
2159         const auto *QuxLoc = Env.getStorageLocation(*QuxDecl);
2160         EXPECT_EQ(QuxLoc, FooLoc);
2161       });
2162 }
2163 
2164 TEST(TransferTest, TemporaryObject) {
2165   std::string Code = R"(
2166     struct A {
2167       int Bar;
2168     };
2169 
2170     void target() {
2171       A Foo = A();
2172       (void)Foo.Bar;
2173       // [[p]]
2174     }
2175   )";
2176   runDataflow(
2177       Code,
2178       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2179          ASTContext &ASTCtx) {
2180         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2181         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2182 
2183         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2184         ASSERT_THAT(FooDecl, NotNull());
2185 
2186         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2187         ASSERT_THAT(BarDecl, NotNull());
2188 
2189         const auto *FooLoc =
2190             cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
2191         EXPECT_TRUE(isa<IntegerValue>(getFieldValue(FooLoc, *BarDecl, Env)));
2192       });
2193 }
2194 
2195 TEST(TransferTest, ElidableConstructor) {
2196   // This test is effectively the same as TransferTest.TemporaryObject, but
2197   // the code is compiled as C++14.
2198   std::string Code = R"(
2199     struct A {
2200       int Bar;
2201     };
2202 
2203     void target() {
2204       A Foo = A();
2205       (void)Foo.Bar;
2206       // [[p]]
2207     }
2208   )";
2209   runDataflow(
2210       Code,
2211       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2212          ASTContext &ASTCtx) {
2213         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2214         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2215 
2216         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2217         ASSERT_THAT(FooDecl, NotNull());
2218 
2219         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2220         ASSERT_THAT(BarDecl, NotNull());
2221 
2222         const auto *FooLoc =
2223             cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
2224         EXPECT_TRUE(isa<IntegerValue>(getFieldValue(FooLoc, *BarDecl, Env)));
2225       },
2226       LangStandard::lang_cxx14);
2227 }
2228 
2229 TEST(TransferTest, AssignmentOperator) {
2230   std::string Code = R"(
2231     struct A {
2232       int Baz;
2233     };
2234 
2235     void target() {
2236       A Foo = { 1 };
2237       A Bar = { 2 };
2238       // [[p1]]
2239       A &Rval = (Foo = Bar);
2240       // [[p2]]
2241       Foo.Baz = 3;
2242       // [[p3]]
2243     }
2244   )";
2245   runDataflow(
2246       Code,
2247       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2248          ASTContext &ASTCtx) {
2249         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2250         ASSERT_THAT(FooDecl, NotNull());
2251 
2252         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2253         ASSERT_THAT(BarDecl, NotNull());
2254 
2255         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2256         ASSERT_THAT(BazDecl, NotNull());
2257 
2258         // Before copy assignment.
2259         {
2260           const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
2261 
2262           const auto *FooLoc1 =
2263               cast<RecordStorageLocation>(Env1.getStorageLocation(*FooDecl));
2264           const auto *BarLoc1 =
2265               cast<RecordStorageLocation>(Env1.getStorageLocation(*BarDecl));
2266           EXPECT_FALSE(recordsEqual(*FooLoc1, *BarLoc1, Env1));
2267 
2268           const auto *FooBazVal1 =
2269               cast<IntegerValue>(getFieldValue(FooLoc1, *BazDecl, Env1));
2270           const auto *BarBazVal1 =
2271               cast<IntegerValue>(getFieldValue(BarLoc1, *BazDecl, Env1));
2272           EXPECT_NE(FooBazVal1, BarBazVal1);
2273         }
2274 
2275         // After copy assignment.
2276         {
2277           const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
2278 
2279           const auto *FooLoc2 =
2280               cast<RecordStorageLocation>(Env2.getStorageLocation(*FooDecl));
2281           const auto *BarLoc2 =
2282               cast<RecordStorageLocation>(Env2.getStorageLocation(*BarDecl));
2283 
2284           EXPECT_TRUE(recordsEqual(*FooLoc2, *BarLoc2, Env2));
2285           EXPECT_EQ(&getLocForDecl(ASTCtx, Env2, "Rval"), FooLoc2);
2286 
2287           const auto *FooBazVal2 =
2288               cast<IntegerValue>(getFieldValue(FooLoc2, *BazDecl, Env2));
2289           const auto *BarBazVal2 =
2290               cast<IntegerValue>(getFieldValue(BarLoc2, *BazDecl, Env2));
2291           EXPECT_EQ(FooBazVal2, BarBazVal2);
2292         }
2293 
2294         // After value update.
2295         {
2296           const Environment &Env3 = getEnvironmentAtAnnotation(Results, "p3");
2297 
2298           const auto *FooLoc3 =
2299               cast<RecordStorageLocation>(Env3.getStorageLocation(*FooDecl));
2300           const auto *BarLoc3 =
2301               cast<RecordStorageLocation>(Env3.getStorageLocation(*BarDecl));
2302           EXPECT_FALSE(recordsEqual(*FooLoc3, *BarLoc3, Env3));
2303 
2304           const auto *FooBazVal3 =
2305               cast<IntegerValue>(getFieldValue(FooLoc3, *BazDecl, Env3));
2306           const auto *BarBazVal3 =
2307               cast<IntegerValue>(getFieldValue(BarLoc3, *BazDecl, Env3));
2308           EXPECT_NE(FooBazVal3, BarBazVal3);
2309         }
2310       });
2311 }
2312 
2313 // It's legal for the assignment operator to take its source parameter by value.
2314 // Check that we handle this correctly. (This is a repro -- we used to
2315 // assert-fail on this.)
2316 TEST(TransferTest, AssignmentOperator_ArgByValue) {
2317   std::string Code = R"(
2318     struct A {
2319       int Baz;
2320       A &operator=(A);
2321     };
2322 
2323     void target() {
2324       A Foo = { 1 };
2325       A Bar = { 2 };
2326       Foo = Bar;
2327       // [[p]]
2328     }
2329   )";
2330   runDataflow(
2331       Code,
2332       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2333          ASTContext &ASTCtx) {
2334         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2335         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2336 
2337         const auto &FooLoc =
2338             getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "Foo");
2339         const auto &BarLoc =
2340             getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "Bar");
2341 
2342         const auto *FooBazVal =
2343             cast<IntegerValue>(getFieldValue(&FooLoc, *BazDecl, Env));
2344         const auto *BarBazVal =
2345             cast<IntegerValue>(getFieldValue(&BarLoc, *BazDecl, Env));
2346         EXPECT_EQ(FooBazVal, BarBazVal);
2347       });
2348 }
2349 
2350 TEST(TransferTest, AssignmentOperatorFromBase) {
2351   std::string Code = R"(
2352     struct Base {
2353       int base;
2354     };
2355     struct Derived : public Base {
2356       using Base::operator=;
2357       int derived;
2358     };
2359     void target(Base B, Derived D) {
2360       D.base = 1;
2361       D.derived = 1;
2362       // [[before]]
2363       D = B;
2364       // [[after]]
2365     }
2366   )";
2367   runDataflow(
2368       Code,
2369       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2370          ASTContext &ASTCtx) {
2371         const Environment &EnvBefore =
2372             getEnvironmentAtAnnotation(Results, "before");
2373         const Environment &EnvAfter =
2374             getEnvironmentAtAnnotation(Results, "after");
2375 
2376         auto &BLoc =
2377             getLocForDecl<RecordStorageLocation>(ASTCtx, EnvBefore, "B");
2378         auto &DLoc =
2379             getLocForDecl<RecordStorageLocation>(ASTCtx, EnvBefore, "D");
2380 
2381         EXPECT_NE(getFieldValue(&BLoc, "base", ASTCtx, EnvBefore),
2382                   getFieldValue(&DLoc, "base", ASTCtx, EnvBefore));
2383         EXPECT_EQ(getFieldValue(&BLoc, "base", ASTCtx, EnvAfter),
2384                   getFieldValue(&DLoc, "base", ASTCtx, EnvAfter));
2385 
2386         EXPECT_EQ(getFieldValue(&DLoc, "derived", ASTCtx, EnvBefore),
2387                   getFieldValue(&DLoc, "derived", ASTCtx, EnvAfter));
2388       });
2389 }
2390 
2391 TEST(TransferTest, AssignmentOperatorFromCallResult) {
2392   std::string Code = R"(
2393     struct A {};
2394     A ReturnA();
2395 
2396     void target() {
2397       A MyA;
2398       MyA = ReturnA();
2399     }
2400   )";
2401   runDataflow(
2402       Code,
2403       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2404          ASTContext &ASTCtx) {
2405         // As of this writing, we don't produce a `Value` for the call
2406         // `ReturnA()`. The only condition we're testing for is that the
2407         // analysis should not crash in this case.
2408       });
2409 }
2410 
2411 TEST(TransferTest, AssignmentOperatorWithInitAndInheritance) {
2412   // This is a crash repro.
2413   std::string Code = R"(
2414     struct B { int Foo; };
2415     struct S : public B {};
2416     void target() {
2417       S S1 = { 1 };
2418       S S2;
2419       S S3;
2420       S1 = S2;  // Only Dst has InitListExpr.
2421       S3 = S1;  // Only Src has InitListExpr.
2422       // [[p]]
2423     }
2424   )";
2425   runDataflow(
2426       Code,
2427       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2428          ASTContext &ASTCtx) {});
2429 }
2430 
2431 TEST(TransferTest, AssignmentOperatorReturnsVoid) {
2432   // This is a crash repro.
2433   std::string Code = R"(
2434     struct S {
2435       void operator=(S&& other);
2436     };
2437     void target() {
2438       S s;
2439       s = S();
2440       // [[p]]
2441     }
2442   )";
2443   runDataflow(
2444       Code,
2445       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2446          ASTContext &ASTCtx) {});
2447 }
2448 
2449 TEST(TransferTest, AssignmentOperatorReturnsByValue) {
2450   // This is a crash repro.
2451   std::string Code = R"(
2452     struct S {
2453       S operator=(const S&);
2454       int i;
2455     };
2456     void target() {
2457       S S1 = { 1 };
2458       S S2 = { 2 };
2459       S S3 = { 3 };
2460       // [[before]]
2461       // Test that the returned value is modeled by assigning to another value.
2462       S1 = (S2 = S3);
2463       (void)0;
2464       // [[after]]
2465     }
2466   )";
2467   runDataflow(
2468       Code,
2469       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2470          ASTContext &ASTCtx) {
2471         const ValueDecl *S1Decl = findValueDecl(ASTCtx, "S1");
2472         const ValueDecl *S2Decl = findValueDecl(ASTCtx, "S2");
2473         const ValueDecl *S3Decl = findValueDecl(ASTCtx, "S3");
2474 
2475         const Environment &EnvBefore =
2476             getEnvironmentAtAnnotation(Results, "before");
2477 
2478         EXPECT_FALSE(recordsEqual(
2479             *EnvBefore.get<RecordStorageLocation>(*S1Decl),
2480             *EnvBefore.get<RecordStorageLocation>(*S2Decl), EnvBefore));
2481         EXPECT_FALSE(recordsEqual(
2482             *EnvBefore.get<RecordStorageLocation>(*S2Decl),
2483             *EnvBefore.get<RecordStorageLocation>(*S3Decl), EnvBefore));
2484 
2485         const Environment &EnvAfter =
2486             getEnvironmentAtAnnotation(Results, "after");
2487 
2488         EXPECT_TRUE(recordsEqual(*EnvAfter.get<RecordStorageLocation>(*S1Decl),
2489                                  *EnvAfter.get<RecordStorageLocation>(*S2Decl),
2490                                  EnvAfter));
2491         EXPECT_TRUE(recordsEqual(*EnvAfter.get<RecordStorageLocation>(*S2Decl),
2492                                  *EnvAfter.get<RecordStorageLocation>(*S3Decl),
2493                                  EnvAfter));
2494       });
2495 }
2496 
2497 TEST(TransferTest, AssignmentOperatorReturnsDifferentTypeByRef) {
2498   // This is a crash repro.
2499   std::string Code = R"(
2500     struct DifferentType {};
2501     struct S {
2502       DifferentType& operator=(const S&);
2503     };
2504     void target() {
2505       S s;
2506       s = S();
2507       // [[p]]
2508     }
2509   )";
2510   runDataflow(
2511       Code,
2512       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2513          ASTContext &ASTCtx) {});
2514 }
2515 
2516 TEST(TransferTest, AssignmentOperatorReturnsDifferentTypeByValue) {
2517   // This is a crash repro.
2518   std::string Code = R"(
2519     struct DifferentType {};
2520     struct S {
2521       DifferentType operator=(const S&);
2522     };
2523     void target() {
2524       S s;
2525       s = S();
2526       // [[p]]
2527     }
2528   )";
2529   runDataflow(
2530       Code,
2531       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2532          ASTContext &ASTCtx) {});
2533 }
2534 
2535 TEST(TransferTest, InitListExprAsXValue) {
2536   // This is a crash repro.
2537   std::string Code = R"(
2538     void target() {
2539       bool&& Foo{false};
2540       // [[p]]
2541     }
2542   )";
2543   runDataflow(
2544       Code,
2545       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2546          ASTContext &ASTCtx) {
2547         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2548         const auto &FooVal = getValueForDecl<BoolValue>(ASTCtx, Env, "Foo");
2549         ASSERT_TRUE(FooVal.formula().isLiteral(false));
2550       });
2551 }
2552 
2553 TEST(TransferTest, ArrayInitListExprOneRecordElement) {
2554   // This is a crash repro.
2555   std::string Code = R"cc(
2556     struct S {};
2557 
2558     void target() { S foo[] = {S()}; }
2559   )cc";
2560   runDataflow(
2561       Code,
2562       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2563          ASTContext &ASTCtx) {
2564         // Just verify that it doesn't crash.
2565       });
2566 }
2567 
2568 TEST(TransferTest, InitListExprAsUnion) {
2569   // This is a crash repro.
2570   std::string Code = R"cc(
2571     class target {
2572       union {
2573         int *a;
2574         bool *b;
2575       } F;
2576 
2577      public:
2578       constexpr target() : F{nullptr} {
2579         int *null = nullptr;
2580         F.b;  // Make sure we reference 'b' so it is modeled.
2581         // [[p]]
2582       }
2583     };
2584   )cc";
2585   runDataflow(
2586       Code,
2587       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2588          ASTContext &ASTCtx) {
2589         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2590 
2591         auto &FLoc = getFieldLoc<RecordStorageLocation>(
2592             *Env.getThisPointeeStorageLocation(), "F", ASTCtx);
2593         auto *AVal = cast<PointerValue>(getFieldValue(&FLoc, "a", ASTCtx, Env));
2594         EXPECT_EQ(AVal, &getValueForDecl<PointerValue>(ASTCtx, Env, "null"));
2595         EXPECT_EQ(getFieldValue(&FLoc, "b", ASTCtx, Env), nullptr);
2596       });
2597 }
2598 
2599 TEST(TransferTest, EmptyInitListExprForUnion) {
2600   // This is a crash repro.
2601   std::string Code = R"cc(
2602     class target {
2603       union {
2604         int *a;
2605         bool *b;
2606       } F;
2607 
2608      public:
2609       // Empty initializer list means that `F` is aggregate-initialized.
2610       // For a union, this has the effect that the first member of the union
2611       // is copy-initialized from an empty initializer list; in this specific
2612       // case, this has the effect of initializing `a` with null.
2613       constexpr target() : F{} {
2614         int *null = nullptr;
2615         F.b;  // Make sure we reference 'b' so it is modeled.
2616         // [[p]]
2617       }
2618     };
2619   )cc";
2620   runDataflow(
2621       Code,
2622       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2623          ASTContext &ASTCtx) {
2624         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2625 
2626         auto &FLoc = getFieldLoc<RecordStorageLocation>(
2627             *Env.getThisPointeeStorageLocation(), "F", ASTCtx);
2628         auto *AVal = cast<PointerValue>(getFieldValue(&FLoc, "a", ASTCtx, Env));
2629         EXPECT_EQ(AVal, &getValueForDecl<PointerValue>(ASTCtx, Env, "null"));
2630         EXPECT_EQ(getFieldValue(&FLoc, "b", ASTCtx, Env), nullptr);
2631       });
2632 }
2633 
2634 TEST(TransferTest, EmptyInitListExprForStruct) {
2635   std::string Code = R"cc(
2636     class target {
2637       struct {
2638         int *a;
2639         bool *b;
2640       } F;
2641 
2642      public:
2643       constexpr target() : F{} {
2644         int *NullIntPtr = nullptr;
2645         bool *NullBoolPtr = nullptr;
2646         // [[p]]
2647       }
2648     };
2649   )cc";
2650   runDataflow(
2651       Code,
2652       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2653          ASTContext &ASTCtx) {
2654         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2655 
2656         auto &FLoc = getFieldLoc<RecordStorageLocation>(
2657             *Env.getThisPointeeStorageLocation(), "F", ASTCtx);
2658         auto *AVal = cast<PointerValue>(getFieldValue(&FLoc, "a", ASTCtx, Env));
2659         EXPECT_EQ(AVal,
2660                   &getValueForDecl<PointerValue>(ASTCtx, Env, "NullIntPtr"));
2661         auto *BVal = cast<PointerValue>(getFieldValue(&FLoc, "b", ASTCtx, Env));
2662         EXPECT_EQ(BVal,
2663                   &getValueForDecl<PointerValue>(ASTCtx, Env, "NullBoolPtr"));
2664       });
2665 }
2666 
2667 TEST(TransferTest, CopyConstructor) {
2668   std::string Code = R"(
2669     struct A {
2670       int Baz;
2671     };
2672 
2673     void target() {
2674       A Foo = { 1 };
2675       A Bar = Foo;
2676       // [[after_copy]]
2677       Foo.Baz = 2;
2678       // [[after_update]]
2679     }
2680   )";
2681   runDataflow(
2682       Code,
2683       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2684          ASTContext &ASTCtx) {
2685         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2686         ASSERT_THAT(FooDecl, NotNull());
2687 
2688         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2689         ASSERT_THAT(BarDecl, NotNull());
2690 
2691         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2692         ASSERT_THAT(BazDecl, NotNull());
2693 
2694         // after_copy
2695         {
2696           const Environment &Env =
2697               getEnvironmentAtAnnotation(Results, "after_copy");
2698 
2699           const auto *FooLoc =
2700               cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
2701           const auto *BarLoc =
2702               cast<RecordStorageLocation>(Env.getStorageLocation(*BarDecl));
2703 
2704           // The records compare equal.
2705           EXPECT_TRUE(recordsEqual(*FooLoc, *BarLoc, Env));
2706 
2707           // In particular, the value of `Baz` in both records is the same.
2708           const auto *FooBazVal =
2709               cast<IntegerValue>(getFieldValue(FooLoc, *BazDecl, Env));
2710           const auto *BarBazVal =
2711               cast<IntegerValue>(getFieldValue(BarLoc, *BazDecl, Env));
2712           EXPECT_EQ(FooBazVal, BarBazVal);
2713         }
2714 
2715         // after_update
2716         {
2717           const Environment &Env =
2718               getEnvironmentAtAnnotation(Results, "after_update");
2719 
2720           const auto *FooLoc =
2721               cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
2722           const auto *BarLoc =
2723               cast<RecordStorageLocation>(Env.getStorageLocation(*BarDecl));
2724 
2725           EXPECT_FALSE(recordsEqual(*FooLoc, *BarLoc, Env));
2726 
2727           const auto *FooBazVal =
2728               cast<IntegerValue>(getFieldValue(FooLoc, *BazDecl, Env));
2729           const auto *BarBazVal =
2730               cast<IntegerValue>(getFieldValue(BarLoc, *BazDecl, Env));
2731           EXPECT_NE(FooBazVal, BarBazVal);
2732         }
2733       });
2734 }
2735 
2736 TEST(TransferTest, CopyConstructorWithDefaultArgument) {
2737   std::string Code = R"(
2738     struct A {
2739       int Baz;
2740       A() = default;
2741       A(const A& a, bool def = true) { Baz = a.Baz; }
2742     };
2743 
2744     void target() {
2745       A Foo;
2746       (void)Foo.Baz;
2747       A Bar = Foo;
2748       // [[p]]
2749     }
2750   )";
2751   runDataflow(
2752       Code,
2753       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2754          ASTContext &ASTCtx) {
2755         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2756         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2757 
2758         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2759         ASSERT_THAT(FooDecl, NotNull());
2760 
2761         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2762         ASSERT_THAT(BarDecl, NotNull());
2763 
2764         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2765         ASSERT_THAT(BazDecl, NotNull());
2766 
2767         const auto *FooLoc =
2768             cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
2769         const auto *BarLoc =
2770             cast<RecordStorageLocation>(Env.getStorageLocation(*BarDecl));
2771         EXPECT_TRUE(recordsEqual(*FooLoc, *BarLoc, Env));
2772 
2773         const auto *FooBazVal =
2774             cast<IntegerValue>(getFieldValue(FooLoc, *BazDecl, Env));
2775         const auto *BarBazVal =
2776             cast<IntegerValue>(getFieldValue(BarLoc, *BazDecl, Env));
2777         EXPECT_EQ(FooBazVal, BarBazVal);
2778       });
2779 }
2780 
2781 TEST(TransferTest, CopyConstructorWithParens) {
2782   std::string Code = R"(
2783     struct A {
2784       int Baz;
2785     };
2786 
2787     void target() {
2788       A Foo;
2789       (void)Foo.Baz;
2790       A Bar((A(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, CopyConstructorWithInitializerListAsSyntacticSugar) {
2825   std::string Code = R"(
2826   struct A {
2827     int Baz;
2828   };
2829   void target() {
2830     A Foo = {3};
2831     (void)Foo.Baz;
2832     A Bar = {A(Foo)};
2833     // [[p]]
2834   }
2835   )";
2836   runDataflow(
2837       Code,
2838       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2839          ASTContext &ASTCtx) {
2840         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2841 
2842         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2843 
2844         const auto &FooLoc =
2845             getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "Foo");
2846         const auto &BarLoc =
2847             getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "Bar");
2848 
2849         const auto *FooBazVal =
2850             cast<IntegerValue>(getFieldValue(&FooLoc, *BazDecl, Env));
2851         const auto *BarBazVal =
2852             cast<IntegerValue>(getFieldValue(&BarLoc, *BazDecl, Env));
2853         EXPECT_EQ(FooBazVal, BarBazVal);
2854       });
2855 }
2856 
2857 TEST(TransferTest, CopyConstructorArgIsRefReturnedByFunction) {
2858   // This is a crash repro.
2859   std::string Code = R"(
2860     struct S {};
2861     const S &returnsSRef();
2862     void target() {
2863       S s(returnsSRef());
2864     }
2865   )";
2866   runDataflow(
2867       Code,
2868       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2869          ASTContext &ASTCtx) {});
2870 }
2871 
2872 TEST(TransferTest, MoveConstructor) {
2873   std::string Code = R"(
2874     namespace std {
2875 
2876     template <typename T> struct remove_reference      { using type = T; };
2877     template <typename T> struct remove_reference<T&>  { using type = T; };
2878     template <typename T> struct remove_reference<T&&> { using type = T; };
2879 
2880     template <typename T>
2881     using remove_reference_t = typename remove_reference<T>::type;
2882 
2883     template <typename T>
2884     std::remove_reference_t<T>&& move(T&& x);
2885 
2886     } // namespace std
2887 
2888     struct A {
2889       int Baz;
2890     };
2891 
2892     void target() {
2893       A Foo;
2894       A Bar;
2895       (void)Foo.Baz;
2896       // [[p1]]
2897       Foo = std::move(Bar);
2898       // [[p2]]
2899     }
2900   )";
2901   runDataflow(
2902       Code,
2903       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2904          ASTContext &ASTCtx) {
2905         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
2906         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
2907         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
2908 
2909         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2910         ASSERT_THAT(FooDecl, NotNull());
2911 
2912         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2913         ASSERT_THAT(BarDecl, NotNull());
2914 
2915         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2916         ASSERT_THAT(BazDecl, NotNull());
2917 
2918         const auto *FooLoc1 =
2919             cast<RecordStorageLocation>(Env1.getStorageLocation(*FooDecl));
2920         const auto *BarLoc1 =
2921             cast<RecordStorageLocation>(Env1.getStorageLocation(*BarDecl));
2922 
2923         EXPECT_FALSE(recordsEqual(*FooLoc1, *BarLoc1, Env1));
2924 
2925         const auto *FooBazVal1 =
2926             cast<IntegerValue>(getFieldValue(FooLoc1, *BazDecl, Env1));
2927         const auto *BarBazVal1 =
2928             cast<IntegerValue>(getFieldValue(BarLoc1, *BazDecl, Env1));
2929         EXPECT_NE(FooBazVal1, BarBazVal1);
2930 
2931         const auto *FooLoc2 =
2932             cast<RecordStorageLocation>(Env2.getStorageLocation(*FooDecl));
2933         EXPECT_TRUE(recordsEqual(*FooLoc2, Env2, *BarLoc1, Env1));
2934 
2935         const auto *FooBazVal2 =
2936             cast<IntegerValue>(getFieldValue(FooLoc1, *BazDecl, Env2));
2937         EXPECT_EQ(FooBazVal2, BarBazVal1);
2938       });
2939 }
2940 
2941 TEST(TransferTest, BindTemporary) {
2942   std::string Code = R"(
2943     struct A {
2944       virtual ~A() = default;
2945 
2946       int Baz;
2947     };
2948 
2949     void target(A Foo) {
2950       int Bar = A(Foo).Baz;
2951       // [[p]]
2952     }
2953   )";
2954   runDataflow(
2955       Code,
2956       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2957          ASTContext &ASTCtx) {
2958         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2959         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2960 
2961         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2962         ASSERT_THAT(FooDecl, NotNull());
2963 
2964         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2965         ASSERT_THAT(BarDecl, NotNull());
2966 
2967         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2968         ASSERT_THAT(BazDecl, NotNull());
2969 
2970         const auto &FooLoc =
2971             *cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
2972         const auto *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
2973         EXPECT_EQ(BarVal, getFieldValue(&FooLoc, *BazDecl, Env));
2974       });
2975 }
2976 
2977 TEST(TransferTest, ResultObjectLocation) {
2978   std::string Code = R"(
2979     struct A {
2980       virtual ~A() = default;
2981     };
2982 
2983     void target() {
2984       0, A();
2985       (void)0; // [[p]]
2986     }
2987   )";
2988   using ast_matchers::binaryOperator;
2989   using ast_matchers::cxxBindTemporaryExpr;
2990   using ast_matchers::cxxTemporaryObjectExpr;
2991   using ast_matchers::exprWithCleanups;
2992   using ast_matchers::has;
2993   using ast_matchers::hasOperatorName;
2994   using ast_matchers::hasRHS;
2995   using ast_matchers::match;
2996   using ast_matchers::selectFirst;
2997   using ast_matchers::traverse;
2998   runDataflow(
2999       Code,
3000       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3001          ASTContext &ASTCtx) {
3002         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3003 
3004         // The expression `0, A()` in the code above produces the following
3005         // structure, consisting of four prvalues of record type.
3006         // `Env.getResultObjectLocation()` should return the same location for
3007         // all of these.
3008         auto MatchResult = match(
3009             traverse(TK_AsIs,
3010                      exprWithCleanups(
3011                          has(binaryOperator(
3012                                  hasOperatorName(","),
3013                                  hasRHS(cxxBindTemporaryExpr(
3014                                             has(cxxTemporaryObjectExpr().bind(
3015                                                 "toe")))
3016                                             .bind("bte")))
3017                                  .bind("comma")))
3018                          .bind("ewc")),
3019             ASTCtx);
3020         auto *TOE = selectFirst<CXXTemporaryObjectExpr>("toe", MatchResult);
3021         ASSERT_NE(TOE, nullptr);
3022         auto *Comma = selectFirst<BinaryOperator>("comma", MatchResult);
3023         ASSERT_NE(Comma, nullptr);
3024         auto *EWC = selectFirst<ExprWithCleanups>("ewc", MatchResult);
3025         ASSERT_NE(EWC, nullptr);
3026         auto *BTE = selectFirst<CXXBindTemporaryExpr>("bte", MatchResult);
3027         ASSERT_NE(BTE, nullptr);
3028 
3029         RecordStorageLocation &Loc = Env.getResultObjectLocation(*TOE);
3030         EXPECT_EQ(&Loc, &Env.getResultObjectLocation(*Comma));
3031         EXPECT_EQ(&Loc, &Env.getResultObjectLocation(*EWC));
3032         EXPECT_EQ(&Loc, &Env.getResultObjectLocation(*BTE));
3033       });
3034 }
3035 
3036 TEST(TransferTest, ResultObjectLocationForDefaultArgExpr) {
3037   std::string Code = R"(
3038     struct Inner {};
3039     struct Outer {
3040         Inner I = {};
3041     };
3042 
3043     void funcWithDefaultArg(Outer O = {});
3044     void target() {
3045       funcWithDefaultArg();
3046       // [[p]]
3047     }
3048   )";
3049 
3050   using ast_matchers::cxxDefaultArgExpr;
3051   using ast_matchers::match;
3052   using ast_matchers::selectFirst;
3053   runDataflow(
3054       Code,
3055       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3056          ASTContext &ASTCtx) {
3057         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3058 
3059         auto *DefaultArg = selectFirst<CXXDefaultArgExpr>(
3060             "default_arg",
3061             match(cxxDefaultArgExpr().bind("default_arg"), ASTCtx));
3062         ASSERT_NE(DefaultArg, nullptr);
3063 
3064         // The values for default arguments aren't modeled; we merely verify
3065         // that we can get a result object location for a default arg.
3066         Env.getResultObjectLocation(*DefaultArg);
3067       });
3068 }
3069 
3070 TEST(TransferTest, ResultObjectLocationForDefaultInitExpr) {
3071   std::string Code = R"(
3072     struct S {};
3073     struct target {
3074       target () {
3075         (void)0;
3076         // [[p]]
3077       }
3078       S s = {};
3079     };
3080   )";
3081 
3082   using ast_matchers::cxxCtorInitializer;
3083   using ast_matchers::match;
3084   using ast_matchers::selectFirst;
3085   runDataflow(
3086       Code,
3087       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3088          ASTContext &ASTCtx) {
3089         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3090 
3091         const ValueDecl *SField = findValueDecl(ASTCtx, "s");
3092 
3093         auto *CtorInit = selectFirst<CXXCtorInitializer>(
3094             "ctor_initializer",
3095             match(cxxCtorInitializer().bind("ctor_initializer"), ASTCtx));
3096         ASSERT_NE(CtorInit, nullptr);
3097 
3098         auto *DefaultInit = cast<CXXDefaultInitExpr>(CtorInit->getInit());
3099 
3100         RecordStorageLocation &Loc = Env.getResultObjectLocation(*DefaultInit);
3101 
3102         EXPECT_EQ(&Loc, Env.getThisPointeeStorageLocation()->getChild(*SField));
3103       });
3104 }
3105 
3106 // This test ensures that CXXOperatorCallExpr returning prvalues are correctly
3107 // handled by the transfer functions, especially that `getResultObjectLocation`
3108 // correctly returns a storage location for those.
3109 TEST(TransferTest, ResultObjectLocationForCXXOperatorCallExpr) {
3110   std::string Code = R"(
3111     struct A {
3112       A operator+(int);
3113     };
3114 
3115     void target() {
3116       A a;
3117       a + 3;
3118       (void)0; // [[p]]
3119     }
3120   )";
3121   using ast_matchers::cxxOperatorCallExpr;
3122   using ast_matchers::match;
3123   using ast_matchers::selectFirst;
3124   using ast_matchers::traverse;
3125   runDataflow(
3126       Code,
3127       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3128          ASTContext &ASTCtx) {
3129         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3130 
3131         auto *CallExpr = selectFirst<CXXOperatorCallExpr>(
3132             "call_expr",
3133             match(cxxOperatorCallExpr().bind("call_expr"), ASTCtx));
3134 
3135         EXPECT_NE(&Env.getResultObjectLocation(*CallExpr), nullptr);
3136       });
3137 }
3138 
3139 TEST(TransferTest, ResultObjectLocationForInitListExpr) {
3140   std::string Code = R"cc(
3141     struct Inner {};
3142 
3143     struct Outer { Inner I; };
3144 
3145     void target() {
3146       Outer O = { Inner() };
3147       // [[p]]
3148     }
3149   )cc";
3150   using ast_matchers::asString;
3151   using ast_matchers::cxxConstructExpr;
3152   using ast_matchers::hasType;
3153   using ast_matchers::match;
3154   using ast_matchers::selectFirst;
3155   using ast_matchers::traverse;
3156   runDataflow(
3157       Code,
3158       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3159          ASTContext &ASTCtx) {
3160         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3161 
3162         auto *Construct = selectFirst<CXXConstructExpr>(
3163             "construct",
3164             match(
3165                 cxxConstructExpr(hasType(asString("Inner"))).bind("construct"),
3166                 ASTCtx));
3167 
3168         EXPECT_EQ(
3169             &Env.getResultObjectLocation(*Construct),
3170             &getFieldLoc(getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "O"),
3171                          "I", ASTCtx));
3172       });
3173 }
3174 
3175 TEST(TransferTest, ResultObjectLocationForParenInitListExpr) {
3176   std::string Code = R"cc(
3177     struct Inner {};
3178 
3179     struct Outer { Inner I; };
3180 
3181     void target() {
3182       Outer O((Inner()));
3183       // [[p]]
3184     }
3185   )cc";
3186   using ast_matchers::asString;
3187   using ast_matchers::cxxConstructExpr;
3188   using ast_matchers::hasType;
3189   using ast_matchers::match;
3190   using ast_matchers::selectFirst;
3191   using ast_matchers::traverse;
3192   runDataflow(
3193       Code,
3194       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3195          ASTContext &ASTCtx) {
3196         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3197 
3198         auto *Construct = selectFirst<CXXConstructExpr>(
3199             "construct",
3200             match(
3201                 cxxConstructExpr(hasType(asString("Inner"))).bind("construct"),
3202                 ASTCtx));
3203 
3204         EXPECT_EQ(
3205             &Env.getResultObjectLocation(*Construct),
3206             &getFieldLoc(getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "O"),
3207                          "I", ASTCtx));
3208       },
3209       LangStandard::lang_cxx20);
3210 }
3211 
3212 // Check that the `std::strong_ordering` object returned by builtin `<=>` has a
3213 // correctly modeled result object location.
3214 TEST(TransferTest, ResultObjectLocationForBuiltinSpaceshipOperator) {
3215   std::string Code = R"(
3216     namespace std {
3217       // This is the minimal definition required to get
3218       // `Sema::CheckComparisonCategoryType()` to accept this fake.
3219       struct strong_ordering {
3220         enum class ordering { less, equal, greater };
3221         ordering o;
3222         static const strong_ordering less;
3223         static const strong_ordering equivalent;
3224         static const strong_ordering equal;
3225         static const strong_ordering greater;
3226       };
3227 
3228       inline constexpr strong_ordering strong_ordering::less =
3229         { strong_ordering::ordering::less };
3230       inline constexpr strong_ordering strong_ordering::equal =
3231         { strong_ordering::ordering::equal };
3232       inline constexpr strong_ordering strong_ordering::equivalent =
3233         { strong_ordering::ordering::equal };
3234       inline constexpr strong_ordering strong_ordering::greater =
3235         { strong_ordering::ordering::greater };
3236     }
3237     void target(int i, int j) {
3238       auto ordering = i <=> j;
3239       // [[p]]
3240     }
3241   )";
3242   using ast_matchers::binaryOperator;
3243   using ast_matchers::hasOperatorName;
3244   using ast_matchers::match;
3245   using ast_matchers::selectFirst;
3246   using ast_matchers::traverse;
3247   runDataflow(
3248       Code,
3249       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3250          ASTContext &ASTCtx) {
3251         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3252 
3253         auto *Spaceship = selectFirst<BinaryOperator>(
3254             "op",
3255             match(binaryOperator(hasOperatorName("<=>")).bind("op"), ASTCtx));
3256 
3257         EXPECT_EQ(
3258             &Env.getResultObjectLocation(*Spaceship),
3259             &getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "ordering"));
3260       },
3261       LangStandard::lang_cxx20);
3262 }
3263 
3264 TEST(TransferTest, ResultObjectLocationForStdInitializerListExpr) {
3265   std::string Code = R"(
3266     namespace std {
3267     template <typename T>
3268     struct initializer_list { const T *a, *b; };
3269     } // namespace std
3270 
3271     void target() {
3272       std::initializer_list<int> list = {1};
3273       // [[p]]
3274     }
3275   )";
3276 
3277   using ast_matchers::cxxStdInitializerListExpr;
3278   using ast_matchers::match;
3279   using ast_matchers::selectFirst;
3280   runDataflow(
3281       Code,
3282       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3283          ASTContext &ASTCtx) {
3284         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3285 
3286         auto *StdInitList = selectFirst<CXXStdInitializerListExpr>(
3287             "std_init_list",
3288             match(cxxStdInitializerListExpr().bind("std_init_list"), ASTCtx));
3289         ASSERT_NE(StdInitList, nullptr);
3290 
3291         EXPECT_EQ(&Env.getResultObjectLocation(*StdInitList),
3292                   &getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "list"));
3293       });
3294 }
3295 
3296 TEST(TransferTest, ResultObjectLocationForStmtExpr) {
3297   std::string Code = R"(
3298     struct S {};
3299     void target() {
3300       S s = ({ S(); });
3301       // [[p]]
3302     }
3303   )";
3304   using ast_matchers::cxxConstructExpr;
3305   using ast_matchers::match;
3306   using ast_matchers::selectFirst;
3307   using ast_matchers::traverse;
3308   runDataflow(
3309       Code,
3310       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3311          ASTContext &ASTCtx) {
3312         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3313 
3314         auto *Construct = selectFirst<CXXConstructExpr>(
3315             "construct", match(cxxConstructExpr().bind("construct"), ASTCtx));
3316 
3317         EXPECT_EQ(&Env.getResultObjectLocation(*Construct),
3318                   &getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "s"));
3319       });
3320 }
3321 
3322 TEST(TransferTest, ResultObjectLocationForBuiltinBitCastExpr) {
3323   std::string Code = R"(
3324     struct S { int i; };
3325     void target(int i) {
3326       S s = __builtin_bit_cast(S, i);
3327       // [[p]]
3328     }
3329   )";
3330   using ast_matchers::explicitCastExpr;
3331   using ast_matchers::match;
3332   using ast_matchers::selectFirst;
3333   using ast_matchers::traverse;
3334   runDataflow(
3335       Code,
3336       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3337          ASTContext &ASTCtx) {
3338         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3339 
3340         auto *BuiltinBitCast = selectFirst<BuiltinBitCastExpr>(
3341             "cast", match(explicitCastExpr().bind("cast"), ASTCtx));
3342 
3343         EXPECT_EQ(&Env.getResultObjectLocation(*BuiltinBitCast),
3344                   &getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "s"));
3345       });
3346 }
3347 
3348 TEST(TransferTest, ResultObjectLocationForAtomicExpr) {
3349   std::string Code = R"(
3350     struct S {};
3351     void target(_Atomic(S) *ptr) {
3352       S s = __c11_atomic_load(ptr, __ATOMIC_SEQ_CST);
3353       // [[p]]
3354     }
3355   )";
3356   using ast_matchers::atomicExpr;
3357   using ast_matchers::match;
3358   using ast_matchers::selectFirst;
3359   using ast_matchers::traverse;
3360   runDataflow(
3361       Code,
3362       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3363          ASTContext &ASTCtx) {
3364         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3365 
3366         auto *Atomic = selectFirst<AtomicExpr>(
3367             "atomic", match(atomicExpr().bind("atomic"), ASTCtx));
3368 
3369         EXPECT_EQ(&Env.getResultObjectLocation(*Atomic),
3370                   &getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "s"));
3371       });
3372 }
3373 
3374 TEST(TransferTest, ResultObjectLocationPropagatesThroughConditionalOperator) {
3375   std::string Code = R"(
3376     struct A {
3377       A(int);
3378     };
3379 
3380     void target(bool b) {
3381       A a = b ? A(0) : A(1);
3382       (void)0; // [[p]]
3383     }
3384   )";
3385   using ast_matchers::cxxConstructExpr;
3386   using ast_matchers::equals;
3387   using ast_matchers::hasArgument;
3388   using ast_matchers::integerLiteral;
3389   using ast_matchers::match;
3390   using ast_matchers::selectFirst;
3391   using ast_matchers::traverse;
3392   runDataflow(
3393       Code,
3394       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3395          ASTContext &ASTCtx) {
3396         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3397 
3398         auto *ConstructExpr0 = selectFirst<CXXConstructExpr>(
3399             "construct",
3400             match(cxxConstructExpr(hasArgument(0, integerLiteral(equals(0))))
3401                       .bind("construct"),
3402                   ASTCtx));
3403         auto *ConstructExpr1 = selectFirst<CXXConstructExpr>(
3404             "construct",
3405             match(cxxConstructExpr(hasArgument(0, integerLiteral(equals(1))))
3406                       .bind("construct"),
3407                   ASTCtx));
3408 
3409         auto &ALoc = getLocForDecl<StorageLocation>(ASTCtx, Env, "a");
3410         EXPECT_EQ(&Env.getResultObjectLocation(*ConstructExpr0), &ALoc);
3411         EXPECT_EQ(&Env.getResultObjectLocation(*ConstructExpr1), &ALoc);
3412       });
3413 }
3414 
3415 TEST(TransferTest, ResultObjectLocationDontVisitNestedRecordDecl) {
3416   // This is a crash repro.
3417   // We used to crash because when propagating result objects, we would visit
3418   // nested record and function declarations, but we don't model fields used
3419   // only in these.
3420   std::string Code = R"(
3421     struct S1 {};
3422     struct S2 { S1 s1; };
3423     void target() {
3424       struct Nested {
3425         void f() {
3426           S2 s2 = { S1() };
3427         }
3428       };
3429     }
3430   )";
3431   runDataflow(
3432       Code,
3433       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3434          ASTContext &ASTCtx) {});
3435 }
3436 
3437 TEST(TransferTest, ResultObjectLocationDontVisitUnevaluatedContexts) {
3438   // This is a crash repro.
3439   // We used to crash because when propagating result objects, we would visit
3440   // unevaluated contexts, but we don't model fields used only in these.
3441 
3442   auto testFunction = [](llvm::StringRef Code, llvm::StringRef TargetFun) {
3443     runDataflow(
3444         Code,
3445         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3446            ASTContext &ASTCtx) {},
3447         LangStandard::lang_gnucxx17,
3448         /* ApplyBuiltinTransfer= */ true, TargetFun);
3449   };
3450 
3451   std::string Code = R"cc(
3452     // Definitions needed for `typeid`.
3453     namespace std {
3454       class type_info {};
3455       class bad_typeid {};
3456     }  // namespace std
3457 
3458     struct S1 {};
3459     struct S2 { S1 s1; };
3460 
3461     // We test each type of unevaluated context from a different target
3462     // function. Some types of unevaluated contexts may actually cause the
3463     // field `s1` to be modeled, and we don't want this to "pollute" the tests
3464     // for the other unevaluated contexts.
3465     void decltypeTarget() {
3466         decltype(S2{}) Dummy;
3467     }
3468     void typeofTarget() {
3469         typeof(S2{}) Dummy;
3470     }
3471     void typeidTarget() {
3472 #if __has_feature(cxx_rtti)
3473         typeid(S2{});
3474 #endif
3475     }
3476     void sizeofTarget() {
3477         sizeof(S2{});
3478     }
3479     void noexceptTarget() {
3480         noexcept(S2{});
3481     }
3482   )cc";
3483 
3484   testFunction(Code, "decltypeTarget");
3485   testFunction(Code, "typeofTarget");
3486   testFunction(Code, "typeidTarget");
3487   testFunction(Code, "sizeofTarget");
3488   testFunction(Code, "noexceptTarget");
3489 }
3490 
3491 TEST(TransferTest, StaticCast) {
3492   std::string Code = R"(
3493     void target(int Foo) {
3494       int Bar = static_cast<int>(Foo);
3495       // [[p]]
3496     }
3497   )";
3498   runDataflow(
3499       Code,
3500       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3501          ASTContext &ASTCtx) {
3502         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3503         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3504 
3505         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3506         ASSERT_THAT(FooDecl, NotNull());
3507 
3508         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3509         ASSERT_THAT(BarDecl, NotNull());
3510 
3511         const auto *FooVal = Env.getValue(*FooDecl);
3512         const auto *BarVal = Env.getValue(*BarDecl);
3513         EXPECT_TRUE(isa<IntegerValue>(FooVal));
3514         EXPECT_TRUE(isa<IntegerValue>(BarVal));
3515         EXPECT_EQ(FooVal, BarVal);
3516       });
3517 }
3518 
3519 TEST(TransferTest, IntegralCast) {
3520   std::string Code = R"(
3521     void target(int Foo) {
3522       long Bar = Foo;
3523       // [[p]]
3524     }
3525   )";
3526   runDataflow(
3527       Code,
3528       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3529          ASTContext &ASTCtx) {
3530         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3531 
3532         const auto &FooVal = getValueForDecl<IntegerValue>(ASTCtx, Env, "Foo");
3533         const auto &BarVal = getValueForDecl<IntegerValue>(ASTCtx, Env, "Bar");
3534         EXPECT_EQ(&FooVal, &BarVal);
3535       });
3536 }
3537 
3538 TEST(TransferTest, IntegraltoBooleanCast) {
3539   std::string Code = R"(
3540     void target(int Foo) {
3541       bool Bar = Foo;
3542       // [[p]]
3543     }
3544   )";
3545   runDataflow(
3546       Code,
3547       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3548          ASTContext &ASTCtx) {
3549         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3550 
3551         const auto &FooVal = getValueForDecl(ASTCtx, Env, "Foo");
3552         const auto &BarVal = getValueForDecl(ASTCtx, Env, "Bar");
3553         EXPECT_TRUE(isa<IntegerValue>(FooVal));
3554         EXPECT_TRUE(isa<BoolValue>(BarVal));
3555       });
3556 }
3557 
3558 TEST(TransferTest, IntegralToBooleanCastFromBool) {
3559   std::string Code = R"(
3560     void target(bool Foo) {
3561       int Zab = Foo;
3562       bool Bar = Zab;
3563       // [[p]]
3564     }
3565   )";
3566   runDataflow(
3567       Code,
3568       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3569          ASTContext &ASTCtx) {
3570         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3571 
3572         const auto &FooVal = getValueForDecl<BoolValue>(ASTCtx, Env, "Foo");
3573         const auto &BarVal = getValueForDecl<BoolValue>(ASTCtx, Env, "Bar");
3574         EXPECT_EQ(&FooVal, &BarVal);
3575       });
3576 }
3577 
3578 TEST(TransferTest, WidenBoolValueInIntegerVariable) {
3579   // This is a crash repro.
3580   // This test sets up a case where we perform widening on an integer variable
3581   // that contains a `BoolValue` for the previous iteration and an
3582   // `IntegerValue` for the current iteration. We used to crash on this because
3583   // `widenDistinctValues()` assumed that if the previous iteration had a
3584   // `BoolValue`, the current iteration would too.
3585   // FIXME: The real fix here is to make sure we never store `BoolValue`s in
3586   // integer variables; see also the comment in `widenDistinctValues()`.
3587   std::string Code = R"cc(
3588     struct S {
3589       int i;
3590       S *next;
3591     };
3592     void target(S *s) {
3593       for (; s; s = s->next)
3594         s->i = false;
3595     }
3596   )cc";
3597   runDataflow(Code,
3598               [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &,
3599                  ASTContext &) {});
3600 }
3601 
3602 TEST(TransferTest, NullToPointerCast) {
3603   std::string Code = R"(
3604     using my_nullptr_t = decltype(nullptr);
3605     struct Baz {};
3606     void target() {
3607       int *FooX = nullptr;
3608       int *FooY = nullptr;
3609       bool **Bar = nullptr;
3610       Baz *Baz = nullptr;
3611       my_nullptr_t Null = 0;
3612       // [[p]]
3613     }
3614   )";
3615   runDataflow(
3616       Code,
3617       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3618          ASTContext &ASTCtx) {
3619         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3620         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3621 
3622         const ValueDecl *FooXDecl = findValueDecl(ASTCtx, "FooX");
3623         ASSERT_THAT(FooXDecl, NotNull());
3624 
3625         const ValueDecl *FooYDecl = findValueDecl(ASTCtx, "FooY");
3626         ASSERT_THAT(FooYDecl, NotNull());
3627 
3628         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3629         ASSERT_THAT(BarDecl, NotNull());
3630 
3631         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3632         ASSERT_THAT(BazDecl, NotNull());
3633 
3634         const ValueDecl *NullDecl = findValueDecl(ASTCtx, "Null");
3635         ASSERT_THAT(NullDecl, NotNull());
3636 
3637         const auto *FooXVal = cast<PointerValue>(Env.getValue(*FooXDecl));
3638         const auto *FooYVal = cast<PointerValue>(Env.getValue(*FooYDecl));
3639         const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl));
3640         const auto *BazVal = cast<PointerValue>(Env.getValue(*BazDecl));
3641         const auto *NullVal = cast<PointerValue>(Env.getValue(*NullDecl));
3642 
3643         EXPECT_EQ(FooXVal, FooYVal);
3644         EXPECT_NE(FooXVal, BarVal);
3645         EXPECT_NE(FooXVal, BazVal);
3646         EXPECT_NE(BarVal, BazVal);
3647 
3648         const StorageLocation &FooPointeeLoc = FooXVal->getPointeeLoc();
3649         EXPECT_TRUE(isa<ScalarStorageLocation>(FooPointeeLoc));
3650         EXPECT_THAT(Env.getValue(FooPointeeLoc), IsNull());
3651 
3652         const StorageLocation &BarPointeeLoc = BarVal->getPointeeLoc();
3653         EXPECT_TRUE(isa<ScalarStorageLocation>(BarPointeeLoc));
3654         EXPECT_THAT(Env.getValue(BarPointeeLoc), IsNull());
3655 
3656         const StorageLocation &BazPointeeLoc = BazVal->getPointeeLoc();
3657         EXPECT_TRUE(isa<RecordStorageLocation>(BazPointeeLoc));
3658         EXPECT_EQ(BazVal, &Env.fork().getOrCreateNullPointerValue(
3659                               BazPointeeLoc.getType()));
3660 
3661         const StorageLocation &NullPointeeLoc = NullVal->getPointeeLoc();
3662         EXPECT_TRUE(isa<ScalarStorageLocation>(NullPointeeLoc));
3663         EXPECT_THAT(Env.getValue(NullPointeeLoc), IsNull());
3664       });
3665 }
3666 
3667 TEST(TransferTest, PointerToMemberVariable) {
3668   std::string Code = R"(
3669     struct S {
3670       int i;
3671     };
3672     void target() {
3673       int S::*MemberPointer = &S::i;
3674       // [[p]]
3675     }
3676   )";
3677   runDataflow(
3678       Code,
3679       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3680          ASTContext &ASTCtx) {
3681         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3682 
3683         const ValueDecl *MemberPointerDecl =
3684             findValueDecl(ASTCtx, "MemberPointer");
3685         ASSERT_THAT(MemberPointerDecl, NotNull());
3686         ASSERT_THAT(Env.getValue(*MemberPointerDecl), IsNull());
3687       });
3688 }
3689 
3690 TEST(TransferTest, PointerToMemberFunction) {
3691   std::string Code = R"(
3692     struct S {
3693       void Method();
3694     };
3695     void target() {
3696       void (S::*MemberPointer)() = &S::Method;
3697       // [[p]]
3698     }
3699   )";
3700   runDataflow(
3701       Code,
3702       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3703          ASTContext &ASTCtx) {
3704         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3705 
3706         const ValueDecl *MemberPointerDecl =
3707             findValueDecl(ASTCtx, "MemberPointer");
3708         ASSERT_THAT(MemberPointerDecl, NotNull());
3709         ASSERT_THAT(Env.getValue(*MemberPointerDecl), IsNull());
3710       });
3711 }
3712 
3713 TEST(TransferTest, NullToMemberPointerCast) {
3714   std::string Code = R"(
3715     struct Foo {};
3716     void target() {
3717       int Foo::*MemberPointer = nullptr;
3718       // [[p]]
3719     }
3720   )";
3721   runDataflow(
3722       Code,
3723       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3724          ASTContext &ASTCtx) {
3725         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3726         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3727 
3728         const ValueDecl *MemberPointerDecl =
3729             findValueDecl(ASTCtx, "MemberPointer");
3730         ASSERT_THAT(MemberPointerDecl, NotNull());
3731         ASSERT_THAT(Env.getValue(*MemberPointerDecl), IsNull());
3732       });
3733 }
3734 
3735 TEST(TransferTest, AddrOfValue) {
3736   std::string Code = R"(
3737     void target() {
3738       int Foo;
3739       int *Bar = &Foo;
3740       // [[p]]
3741     }
3742   )";
3743   runDataflow(
3744       Code,
3745       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3746          ASTContext &ASTCtx) {
3747         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3748         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3749 
3750         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3751         ASSERT_THAT(FooDecl, NotNull());
3752 
3753         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3754         ASSERT_THAT(BarDecl, NotNull());
3755 
3756         const auto *FooLoc =
3757             cast<ScalarStorageLocation>(Env.getStorageLocation(*FooDecl));
3758         const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl));
3759         EXPECT_EQ(&BarVal->getPointeeLoc(), FooLoc);
3760       });
3761 }
3762 
3763 TEST(TransferTest, AddrOfReference) {
3764   std::string Code = R"(
3765     void target(int *Foo) {
3766       int *Bar = &(*Foo);
3767       // [[p]]
3768     }
3769   )";
3770   runDataflow(
3771       Code,
3772       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3773          ASTContext &ASTCtx) {
3774         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3775         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3776 
3777         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3778         ASSERT_THAT(FooDecl, NotNull());
3779 
3780         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3781         ASSERT_THAT(BarDecl, NotNull());
3782 
3783         const auto *FooVal = cast<PointerValue>(Env.getValue(*FooDecl));
3784         const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl));
3785         EXPECT_EQ(&BarVal->getPointeeLoc(), &FooVal->getPointeeLoc());
3786       });
3787 }
3788 
3789 TEST(TransferTest, Preincrement) {
3790   std::string Code = R"(
3791     void target(int I) {
3792       (void)0; // [[before]]
3793       int &IRef = ++I;
3794       // [[after]]
3795     }
3796   )";
3797   runDataflow(
3798       Code,
3799       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3800          ASTContext &ASTCtx) {
3801         const Environment &EnvBefore =
3802             getEnvironmentAtAnnotation(Results, "before");
3803         const Environment &EnvAfter =
3804             getEnvironmentAtAnnotation(Results, "after");
3805 
3806         EXPECT_EQ(&getLocForDecl(ASTCtx, EnvAfter, "IRef"),
3807                   &getLocForDecl(ASTCtx, EnvBefore, "I"));
3808 
3809         const ValueDecl *IDecl = findValueDecl(ASTCtx, "I");
3810         EXPECT_NE(EnvBefore.getValue(*IDecl), nullptr);
3811         EXPECT_EQ(EnvAfter.getValue(*IDecl), nullptr);
3812       });
3813 }
3814 
3815 TEST(TransferTest, Postincrement) {
3816   std::string Code = R"(
3817     void target(int I) {
3818       (void)0; // [[before]]
3819       int OldVal = I++;
3820       // [[after]]
3821     }
3822   )";
3823   runDataflow(
3824       Code,
3825       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3826          ASTContext &ASTCtx) {
3827         const Environment &EnvBefore =
3828             getEnvironmentAtAnnotation(Results, "before");
3829         const Environment &EnvAfter =
3830             getEnvironmentAtAnnotation(Results, "after");
3831 
3832         EXPECT_EQ(&getValueForDecl(ASTCtx, EnvBefore, "I"),
3833                   &getValueForDecl(ASTCtx, EnvAfter, "OldVal"));
3834 
3835         const ValueDecl *IDecl = findValueDecl(ASTCtx, "I");
3836         EXPECT_EQ(EnvAfter.getValue(*IDecl), nullptr);
3837       });
3838 }
3839 
3840 // We test just one of the compound assignment operators because we know the
3841 // code for propagating the storage location is shared among all of them.
3842 TEST(TransferTest, AddAssign) {
3843   std::string Code = R"(
3844     void target(int I) {
3845       int &IRef = (I += 1);
3846       // [[p]]
3847     }
3848   )";
3849   runDataflow(
3850       Code,
3851       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3852          ASTContext &ASTCtx) {
3853         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3854 
3855         EXPECT_EQ(&getLocForDecl(ASTCtx, Env, "IRef"),
3856                   &getLocForDecl(ASTCtx, Env, "I"));
3857       });
3858 }
3859 
3860 TEST(TransferTest, CannotAnalyzeFunctionTemplate) {
3861   std::string Code = R"(
3862     template <typename T>
3863     void target() {}
3864   )";
3865   ASSERT_THAT_ERROR(
3866       checkDataflowWithNoopAnalysis(Code),
3867       llvm::FailedWithMessage("Cannot analyze templated declarations"));
3868 }
3869 
3870 TEST(TransferTest, CannotAnalyzeMethodOfClassTemplate) {
3871   std::string Code = R"(
3872     template <typename T>
3873     struct A {
3874       void target() {}
3875     };
3876   )";
3877   ASSERT_THAT_ERROR(
3878       checkDataflowWithNoopAnalysis(Code),
3879       llvm::FailedWithMessage("Cannot analyze templated declarations"));
3880 }
3881 
3882 TEST(TransferTest, VarDeclInitAssignConditionalOperator) {
3883   std::string Code = R"(
3884     struct A {
3885       int i;
3886     };
3887 
3888     void target(A Foo, A Bar, bool Cond) {
3889       A Baz = Cond ?  A(Foo) : A(Bar);
3890       // Make sure A::i is modeled.
3891       Baz.i;
3892       /*[[p]]*/
3893     }
3894   )";
3895   runDataflow(
3896       Code,
3897       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3898          ASTContext &ASTCtx) {
3899         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3900 
3901         auto *FooIVal = cast<IntegerValue>(getFieldValue(
3902             &getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "Foo"), "i",
3903             ASTCtx, Env));
3904         auto *BarIVal = cast<IntegerValue>(getFieldValue(
3905             &getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "Bar"), "i",
3906             ASTCtx, Env));
3907         auto *BazIVal = cast<IntegerValue>(getFieldValue(
3908             &getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "Baz"), "i",
3909             ASTCtx, Env));
3910 
3911         EXPECT_NE(BazIVal, FooIVal);
3912         EXPECT_NE(BazIVal, BarIVal);
3913       });
3914 }
3915 
3916 TEST(TransferTest, VarDeclInDoWhile) {
3917   std::string Code = R"(
3918     void target(int *Foo) {
3919       do {
3920         int Bar = *Foo;
3921         // [[in_loop]]
3922       } while (false);
3923       (void)0;
3924       // [[after_loop]]
3925     }
3926   )";
3927   runDataflow(
3928       Code,
3929       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3930          ASTContext &ASTCtx) {
3931         const Environment &EnvInLoop =
3932             getEnvironmentAtAnnotation(Results, "in_loop");
3933         const Environment &EnvAfterLoop =
3934             getEnvironmentAtAnnotation(Results, "after_loop");
3935 
3936         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3937         ASSERT_THAT(FooDecl, NotNull());
3938 
3939         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3940         ASSERT_THAT(BarDecl, NotNull());
3941 
3942         const auto *FooVal =
3943             cast<PointerValue>(EnvAfterLoop.getValue(*FooDecl));
3944         const auto *FooPointeeVal =
3945             cast<IntegerValue>(EnvAfterLoop.getValue(FooVal->getPointeeLoc()));
3946 
3947         const auto *BarVal = cast<IntegerValue>(EnvInLoop.getValue(*BarDecl));
3948         EXPECT_EQ(BarVal, FooPointeeVal);
3949 
3950         ASSERT_THAT(EnvAfterLoop.getValue(*BarDecl), IsNull());
3951       });
3952 }
3953 
3954 TEST(TransferTest, UnreachableAfterWhileTrue) {
3955   std::string Code = R"(
3956     void target() {
3957       while (true) {}
3958       (void)0;
3959       /*[[p]]*/
3960     }
3961   )";
3962   runDataflow(
3963       Code,
3964       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3965          ASTContext &ASTCtx) {
3966         // The node after the while-true is pruned because it is trivially
3967         // known to be unreachable.
3968         ASSERT_TRUE(Results.empty());
3969       });
3970 }
3971 
3972 TEST(TransferTest, AggregateInitialization) {
3973   std::string BracesCode = R"(
3974     struct A {
3975       int Foo;
3976     };
3977 
3978     struct B {
3979       int Bar;
3980       A Baz;
3981       int Qux;
3982     };
3983 
3984     void target(int BarArg, int FooArg, int QuxArg) {
3985       B Quux{BarArg, {FooArg}, QuxArg};
3986       B OtherB;
3987       /*[[p]]*/
3988     }
3989   )";
3990   std::string BraceElisionCode = R"(
3991     struct A {
3992       int Foo;
3993     };
3994 
3995     struct B {
3996       int Bar;
3997       A Baz;
3998       int Qux;
3999     };
4000 
4001     void target(int BarArg, int FooArg, int QuxArg) {
4002       B Quux = {BarArg, FooArg, QuxArg};
4003       B OtherB;
4004       /*[[p]]*/
4005     }
4006   )";
4007   for (const std::string &Code : {BracesCode, BraceElisionCode}) {
4008     runDataflow(
4009         Code,
4010         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4011            ASTContext &ASTCtx) {
4012           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4013           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4014 
4015           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4016           ASSERT_THAT(FooDecl, NotNull());
4017 
4018           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4019           ASSERT_THAT(BarDecl, NotNull());
4020 
4021           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4022           ASSERT_THAT(BazDecl, NotNull());
4023 
4024           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
4025           ASSERT_THAT(QuxDecl, NotNull());
4026 
4027           const ValueDecl *FooArgDecl = findValueDecl(ASTCtx, "FooArg");
4028           ASSERT_THAT(FooArgDecl, NotNull());
4029 
4030           const ValueDecl *BarArgDecl = findValueDecl(ASTCtx, "BarArg");
4031           ASSERT_THAT(BarArgDecl, NotNull());
4032 
4033           const ValueDecl *QuxArgDecl = findValueDecl(ASTCtx, "QuxArg");
4034           ASSERT_THAT(QuxArgDecl, NotNull());
4035 
4036           const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux");
4037           ASSERT_THAT(QuuxDecl, NotNull());
4038 
4039           const auto *FooArgVal = cast<IntegerValue>(Env.getValue(*FooArgDecl));
4040           const auto *BarArgVal = cast<IntegerValue>(Env.getValue(*BarArgDecl));
4041           const auto *QuxArgVal = cast<IntegerValue>(Env.getValue(*QuxArgDecl));
4042 
4043           const auto &QuuxLoc =
4044               *cast<RecordStorageLocation>(Env.getStorageLocation(*QuuxDecl));
4045           const auto &BazLoc =
4046               *cast<RecordStorageLocation>(QuuxLoc.getChild(*BazDecl));
4047 
4048           EXPECT_EQ(getFieldValue(&QuuxLoc, *BarDecl, Env), BarArgVal);
4049           EXPECT_EQ(getFieldValue(&BazLoc, *FooDecl, Env), FooArgVal);
4050           EXPECT_EQ(getFieldValue(&QuuxLoc, *QuxDecl, Env), QuxArgVal);
4051 
4052           // Check that fields initialized in an initializer list are always
4053           // modeled in other instances of the same type.
4054           const auto &OtherBLoc =
4055               getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "OtherB");
4056           EXPECT_THAT(OtherBLoc.getChild(*BarDecl), NotNull());
4057           EXPECT_THAT(OtherBLoc.getChild(*BazDecl), NotNull());
4058           EXPECT_THAT(OtherBLoc.getChild(*QuxDecl), NotNull());
4059         });
4060   }
4061 }
4062 
4063 TEST(TransferTest, AggregateInitializationReferenceField) {
4064   std::string Code = R"(
4065     struct S {
4066       int &RefField;
4067     };
4068 
4069     void target(int i) {
4070       S s = { i };
4071       /*[[p]]*/
4072     }
4073   )";
4074   runDataflow(
4075       Code,
4076       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4077          ASTContext &ASTCtx) {
4078         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4079 
4080         const ValueDecl *RefFieldDecl = findValueDecl(ASTCtx, "RefField");
4081 
4082         auto &ILoc = getLocForDecl<StorageLocation>(ASTCtx, Env, "i");
4083         auto &SLoc = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "s");
4084 
4085         EXPECT_EQ(SLoc.getChild(*RefFieldDecl), &ILoc);
4086       });
4087 }
4088 
4089 TEST(TransferTest, AggregateInitialization_NotExplicitlyInitializedField) {
4090   std::string Code = R"(
4091     struct S {
4092       int i1;
4093       int i2;
4094     };
4095 
4096     void target(int i) {
4097       S s = { i };
4098       /*[[p]]*/
4099     }
4100   )";
4101   runDataflow(
4102       Code,
4103       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4104          ASTContext &ASTCtx) {
4105         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4106 
4107         const ValueDecl *I1FieldDecl = findValueDecl(ASTCtx, "i1");
4108         const ValueDecl *I2FieldDecl = findValueDecl(ASTCtx, "i2");
4109 
4110         auto &SLoc = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "s");
4111 
4112         auto &IValue = getValueForDecl<IntegerValue>(ASTCtx, Env, "i");
4113         auto &I1Value =
4114             *cast<IntegerValue>(getFieldValue(&SLoc, *I1FieldDecl, Env));
4115         EXPECT_EQ(&I1Value, &IValue);
4116         auto &I2Value =
4117             *cast<IntegerValue>(getFieldValue(&SLoc, *I2FieldDecl, Env));
4118         EXPECT_NE(&I2Value, &IValue);
4119       });
4120 }
4121 
4122 TEST(TransferTest, AggregateInitializationFunctionPointer) {
4123   // This is a repro for an assertion failure.
4124   // nullptr takes on the type of a const function pointer, but its type was
4125   // asserted to be equal to the *unqualified* type of Field, which no longer
4126   // included the const.
4127   std::string Code = R"(
4128     struct S {
4129       void (*const Field)();
4130     };
4131 
4132     void target() {
4133       S s{nullptr};
4134     }
4135   )";
4136   runDataflow(
4137       Code,
4138       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4139          ASTContext &ASTCtx) {});
4140 }
4141 
4142 TEST(TransferTest, AssignToUnionMember) {
4143   std::string Code = R"(
4144     union A {
4145       int Foo;
4146     };
4147 
4148     void target(int Bar) {
4149       A Baz;
4150       Baz.Foo = Bar;
4151       // [[p]]
4152     }
4153   )";
4154   runDataflow(
4155       Code,
4156       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4157          ASTContext &ASTCtx) {
4158         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4159         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4160 
4161         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4162         ASSERT_THAT(BazDecl, NotNull());
4163         ASSERT_TRUE(BazDecl->getType()->isUnionType());
4164 
4165         auto BazFields = BazDecl->getType()->getAsRecordDecl()->fields();
4166         FieldDecl *FooDecl = nullptr;
4167         for (FieldDecl *Field : BazFields) {
4168           if (Field->getNameAsString() == "Foo") {
4169             FooDecl = Field;
4170           } else {
4171             FAIL() << "Unexpected field: " << Field->getNameAsString();
4172           }
4173         }
4174         ASSERT_THAT(FooDecl, NotNull());
4175 
4176         const auto *BazLoc = dyn_cast_or_null<RecordStorageLocation>(
4177             Env.getStorageLocation(*BazDecl));
4178         ASSERT_THAT(BazLoc, NotNull());
4179 
4180         const auto *FooVal =
4181             cast<IntegerValue>(getFieldValue(BazLoc, *FooDecl, Env));
4182 
4183         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4184         ASSERT_THAT(BarDecl, NotNull());
4185         const auto *BarLoc = Env.getStorageLocation(*BarDecl);
4186         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
4187 
4188         EXPECT_EQ(Env.getValue(*BarLoc), FooVal);
4189       });
4190 }
4191 
4192 TEST(TransferTest, AssignFromBoolLiteral) {
4193   std::string Code = R"(
4194     void target() {
4195       bool Foo = true;
4196       bool Bar = false;
4197       // [[p]]
4198     }
4199   )";
4200   runDataflow(
4201       Code,
4202       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4203          ASTContext &ASTCtx) {
4204         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4205         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4206 
4207         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4208         ASSERT_THAT(FooDecl, NotNull());
4209 
4210         const auto *FooVal =
4211             dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
4212         ASSERT_THAT(FooVal, NotNull());
4213 
4214         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4215         ASSERT_THAT(BarDecl, NotNull());
4216 
4217         const auto *BarVal =
4218             dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
4219         ASSERT_THAT(BarVal, NotNull());
4220 
4221         EXPECT_EQ(FooVal, &Env.getBoolLiteralValue(true));
4222         EXPECT_EQ(BarVal, &Env.getBoolLiteralValue(false));
4223       });
4224 }
4225 
4226 TEST(TransferTest, AssignFromCompositeBoolExpression) {
4227   {
4228     std::string Code = R"(
4229     void target(bool Foo, bool Bar, bool Qux) {
4230       bool Baz = (Foo) && (Bar || Qux);
4231       // [[p]]
4232     }
4233   )";
4234     runDataflow(
4235         Code,
4236         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4237            ASTContext &ASTCtx) {
4238           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4239           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4240 
4241           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4242           ASSERT_THAT(FooDecl, NotNull());
4243 
4244           const auto *FooVal =
4245               dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
4246           ASSERT_THAT(FooVal, NotNull());
4247 
4248           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4249           ASSERT_THAT(BarDecl, NotNull());
4250 
4251           const auto *BarVal =
4252               dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
4253           ASSERT_THAT(BarVal, NotNull());
4254 
4255           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
4256           ASSERT_THAT(QuxDecl, NotNull());
4257 
4258           const auto *QuxVal =
4259               dyn_cast_or_null<BoolValue>(Env.getValue(*QuxDecl));
4260           ASSERT_THAT(QuxVal, NotNull());
4261 
4262           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4263           ASSERT_THAT(BazDecl, NotNull());
4264 
4265           const auto *BazVal =
4266               dyn_cast_or_null<BoolValue>(Env.getValue(*BazDecl));
4267           ASSERT_THAT(BazVal, NotNull());
4268           auto &A = Env.arena();
4269           EXPECT_EQ(&BazVal->formula(),
4270                     &A.makeAnd(FooVal->formula(),
4271                                A.makeOr(BarVal->formula(), QuxVal->formula())));
4272         });
4273   }
4274 
4275   {
4276     std::string Code = R"(
4277     void target(bool Foo, bool Bar, bool Qux) {
4278       bool Baz = (Foo && Qux) || (Bar);
4279       // [[p]]
4280     }
4281   )";
4282     runDataflow(
4283         Code,
4284         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4285            ASTContext &ASTCtx) {
4286           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4287           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4288 
4289           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4290           ASSERT_THAT(FooDecl, NotNull());
4291 
4292           const auto *FooVal =
4293               dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
4294           ASSERT_THAT(FooVal, NotNull());
4295 
4296           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4297           ASSERT_THAT(BarDecl, NotNull());
4298 
4299           const auto *BarVal =
4300               dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
4301           ASSERT_THAT(BarVal, NotNull());
4302 
4303           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
4304           ASSERT_THAT(QuxDecl, NotNull());
4305 
4306           const auto *QuxVal =
4307               dyn_cast_or_null<BoolValue>(Env.getValue(*QuxDecl));
4308           ASSERT_THAT(QuxVal, NotNull());
4309 
4310           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4311           ASSERT_THAT(BazDecl, NotNull());
4312 
4313           const auto *BazVal =
4314               dyn_cast_or_null<BoolValue>(Env.getValue(*BazDecl));
4315           ASSERT_THAT(BazVal, NotNull());
4316           auto &A = Env.arena();
4317           EXPECT_EQ(&BazVal->formula(),
4318                     &A.makeOr(A.makeAnd(FooVal->formula(), QuxVal->formula()),
4319                               BarVal->formula()));
4320         });
4321   }
4322 
4323   {
4324     std::string Code = R"(
4325       void target(bool A, bool B, bool C, bool D) {
4326         bool Foo = ((A && B) && C) && D;
4327         // [[p]]
4328       }
4329     )";
4330     runDataflow(
4331         Code,
4332         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4333            ASTContext &ASTCtx) {
4334           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4335           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4336 
4337           const ValueDecl *ADecl = findValueDecl(ASTCtx, "A");
4338           ASSERT_THAT(ADecl, NotNull());
4339 
4340           const auto *AVal = dyn_cast_or_null<BoolValue>(Env.getValue(*ADecl));
4341           ASSERT_THAT(AVal, NotNull());
4342 
4343           const ValueDecl *BDecl = findValueDecl(ASTCtx, "B");
4344           ASSERT_THAT(BDecl, NotNull());
4345 
4346           const auto *BVal = dyn_cast_or_null<BoolValue>(Env.getValue(*BDecl));
4347           ASSERT_THAT(BVal, NotNull());
4348 
4349           const ValueDecl *CDecl = findValueDecl(ASTCtx, "C");
4350           ASSERT_THAT(CDecl, NotNull());
4351 
4352           const auto *CVal = dyn_cast_or_null<BoolValue>(Env.getValue(*CDecl));
4353           ASSERT_THAT(CVal, NotNull());
4354 
4355           const ValueDecl *DDecl = findValueDecl(ASTCtx, "D");
4356           ASSERT_THAT(DDecl, NotNull());
4357 
4358           const auto *DVal = dyn_cast_or_null<BoolValue>(Env.getValue(*DDecl));
4359           ASSERT_THAT(DVal, NotNull());
4360 
4361           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4362           ASSERT_THAT(FooDecl, NotNull());
4363 
4364           const auto *FooVal =
4365               dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
4366           ASSERT_THAT(FooVal, NotNull());
4367           auto &A = Env.arena();
4368           EXPECT_EQ(
4369               &FooVal->formula(),
4370               &A.makeAnd(A.makeAnd(A.makeAnd(AVal->formula(), BVal->formula()),
4371                                    CVal->formula()),
4372                          DVal->formula()));
4373         });
4374   }
4375 }
4376 
4377 TEST(TransferTest, AssignFromBoolNegation) {
4378   std::string Code = R"(
4379     void target() {
4380       bool Foo = true;
4381       bool Bar = !(Foo);
4382       // [[p]]
4383     }
4384   )";
4385   runDataflow(
4386       Code,
4387       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4388          ASTContext &ASTCtx) {
4389         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4390         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4391 
4392         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4393         ASSERT_THAT(FooDecl, NotNull());
4394 
4395         const auto *FooVal =
4396             dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
4397         ASSERT_THAT(FooVal, NotNull());
4398 
4399         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4400         ASSERT_THAT(BarDecl, NotNull());
4401 
4402         const auto *BarVal =
4403             dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
4404         ASSERT_THAT(BarVal, NotNull());
4405         auto &A = Env.arena();
4406         EXPECT_EQ(&BarVal->formula(), &A.makeNot(FooVal->formula()));
4407       });
4408 }
4409 
4410 TEST(TransferTest, BuiltinExpect) {
4411   std::string Code = R"(
4412     void target(long Foo) {
4413       long Bar = __builtin_expect(Foo, true);
4414       /*[[p]]*/
4415     }
4416   )";
4417   runDataflow(
4418       Code,
4419       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4420          ASTContext &ASTCtx) {
4421         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4422         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4423 
4424         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4425         ASSERT_THAT(FooDecl, NotNull());
4426 
4427         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4428         ASSERT_THAT(BarDecl, NotNull());
4429 
4430         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
4431       });
4432 }
4433 
4434 // `__builtin_expect` takes and returns a `long` argument, so other types
4435 // involve casts. This verifies that we identify the input and output in that
4436 // case.
4437 TEST(TransferTest, BuiltinExpectBoolArg) {
4438   std::string Code = R"(
4439     void target(bool Foo) {
4440       bool Bar = __builtin_expect(Foo, true);
4441       /*[[p]]*/
4442     }
4443   )";
4444   runDataflow(
4445       Code,
4446       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4447          ASTContext &ASTCtx) {
4448         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4449         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4450 
4451         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4452         ASSERT_THAT(FooDecl, NotNull());
4453 
4454         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4455         ASSERT_THAT(BarDecl, NotNull());
4456 
4457         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
4458       });
4459 }
4460 
4461 TEST(TransferTest, BuiltinUnreachable) {
4462   std::string Code = R"(
4463     void target(bool Foo) {
4464       bool Bar = false;
4465       if (Foo)
4466         Bar = Foo;
4467       else
4468         __builtin_unreachable();
4469       (void)0;
4470       /*[[p]]*/
4471     }
4472   )";
4473   runDataflow(
4474       Code,
4475       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4476          ASTContext &ASTCtx) {
4477         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4478         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4479 
4480         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4481         ASSERT_THAT(FooDecl, NotNull());
4482 
4483         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4484         ASSERT_THAT(BarDecl, NotNull());
4485 
4486         // `__builtin_unreachable` promises that the code is
4487         // unreachable, so the compiler treats the "then" branch as the
4488         // only possible predecessor of this statement.
4489         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
4490       });
4491 }
4492 
4493 TEST(TransferTest, BuiltinTrap) {
4494   std::string Code = R"(
4495     void target(bool Foo) {
4496       bool Bar = false;
4497       if (Foo)
4498         Bar = Foo;
4499       else
4500         __builtin_trap();
4501       (void)0;
4502       /*[[p]]*/
4503     }
4504   )";
4505   runDataflow(
4506       Code,
4507       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4508          ASTContext &ASTCtx) {
4509         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4510         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4511 
4512         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4513         ASSERT_THAT(FooDecl, NotNull());
4514 
4515         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4516         ASSERT_THAT(BarDecl, NotNull());
4517 
4518         // `__builtin_trap` ensures program termination, so only the
4519         // "then" branch is a predecessor of this statement.
4520         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
4521       });
4522 }
4523 
4524 TEST(TransferTest, BuiltinDebugTrap) {
4525   std::string Code = R"(
4526     void target(bool Foo) {
4527       bool Bar = false;
4528       if (Foo)
4529         Bar = Foo;
4530       else
4531         __builtin_debugtrap();
4532       (void)0;
4533       /*[[p]]*/
4534     }
4535   )";
4536   runDataflow(
4537       Code,
4538       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4539          ASTContext &ASTCtx) {
4540         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4541         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4542 
4543         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4544         ASSERT_THAT(FooDecl, NotNull());
4545 
4546         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4547         ASSERT_THAT(BarDecl, NotNull());
4548 
4549         // `__builtin_debugtrap` doesn't ensure program termination.
4550         EXPECT_NE(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
4551       });
4552 }
4553 
4554 TEST(TransferTest, StaticIntSingleVarDecl) {
4555   std::string Code = R"(
4556     void target() {
4557       static int Foo;
4558       // [[p]]
4559     }
4560   )";
4561   runDataflow(
4562       Code,
4563       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4564          ASTContext &ASTCtx) {
4565         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4566         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4567 
4568         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4569         ASSERT_THAT(FooDecl, NotNull());
4570 
4571         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
4572         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
4573 
4574         const Value *FooVal = Env.getValue(*FooLoc);
4575         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
4576       });
4577 }
4578 
4579 TEST(TransferTest, StaticIntGroupVarDecl) {
4580   std::string Code = R"(
4581     void target() {
4582       static int Foo, Bar;
4583       (void)0;
4584       // [[p]]
4585     }
4586   )";
4587   runDataflow(
4588       Code,
4589       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4590          ASTContext &ASTCtx) {
4591         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4592         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4593 
4594         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4595         ASSERT_THAT(FooDecl, NotNull());
4596 
4597         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4598         ASSERT_THAT(BarDecl, NotNull());
4599 
4600         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
4601         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
4602 
4603         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
4604         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
4605 
4606         const Value *FooVal = Env.getValue(*FooLoc);
4607         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
4608 
4609         const Value *BarVal = Env.getValue(*BarLoc);
4610         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
4611 
4612         EXPECT_NE(FooVal, BarVal);
4613       });
4614 }
4615 
4616 TEST(TransferTest, GlobalIntVarDecl) {
4617   std::string Code = R"(
4618     static int Foo;
4619 
4620     void target() {
4621       int Bar = Foo;
4622       int Baz = Foo;
4623       // [[p]]
4624     }
4625   )";
4626   runDataflow(
4627       Code,
4628       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4629          ASTContext &ASTCtx) {
4630         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4631         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4632 
4633         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4634         ASSERT_THAT(BarDecl, NotNull());
4635 
4636         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4637         ASSERT_THAT(BazDecl, NotNull());
4638 
4639         const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
4640         const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl));
4641         EXPECT_EQ(BarVal, BazVal);
4642       });
4643 }
4644 
4645 TEST(TransferTest, StaticMemberIntVarDecl) {
4646   std::string Code = R"(
4647     struct A {
4648       static int Foo;
4649     };
4650 
4651     void target(A a) {
4652       int Bar = a.Foo;
4653       int Baz = a.Foo;
4654       // [[p]]
4655     }
4656   )";
4657   runDataflow(
4658       Code,
4659       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4660          ASTContext &ASTCtx) {
4661         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4662         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4663 
4664         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4665         ASSERT_THAT(BarDecl, NotNull());
4666 
4667         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4668         ASSERT_THAT(BazDecl, NotNull());
4669 
4670         const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
4671         const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl));
4672         EXPECT_EQ(BarVal, BazVal);
4673       });
4674 }
4675 
4676 TEST(TransferTest, StaticMemberRefVarDecl) {
4677   std::string Code = R"(
4678     struct A {
4679       static int &Foo;
4680     };
4681 
4682     void target(A a) {
4683       int Bar = a.Foo;
4684       int Baz = a.Foo;
4685       // [[p]]
4686     }
4687   )";
4688   runDataflow(
4689       Code,
4690       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4691          ASTContext &ASTCtx) {
4692         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4693         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4694 
4695         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4696         ASSERT_THAT(BarDecl, NotNull());
4697 
4698         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4699         ASSERT_THAT(BazDecl, NotNull());
4700 
4701         const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
4702         const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl));
4703         EXPECT_EQ(BarVal, BazVal);
4704       });
4705 }
4706 
4707 TEST(TransferTest, AssignMemberBeforeCopy) {
4708   std::string Code = R"(
4709     struct A {
4710       int Foo;
4711     };
4712 
4713     void target() {
4714       A A1;
4715       A A2;
4716       int Bar;
4717       A1.Foo = Bar;
4718       A2 = A1;
4719       // [[p]]
4720     }
4721   )";
4722   runDataflow(
4723       Code,
4724       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4725          ASTContext &ASTCtx) {
4726         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4727         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4728 
4729         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4730         ASSERT_THAT(FooDecl, NotNull());
4731 
4732         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4733         ASSERT_THAT(BarDecl, NotNull());
4734 
4735         const ValueDecl *A1Decl = findValueDecl(ASTCtx, "A1");
4736         ASSERT_THAT(A1Decl, NotNull());
4737 
4738         const ValueDecl *A2Decl = findValueDecl(ASTCtx, "A2");
4739         ASSERT_THAT(A2Decl, NotNull());
4740 
4741         const auto *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
4742 
4743         const auto &A2Loc =
4744             *cast<RecordStorageLocation>(Env.getStorageLocation(*A2Decl));
4745         EXPECT_EQ(getFieldValue(&A2Loc, *FooDecl, Env), BarVal);
4746       });
4747 }
4748 
4749 TEST(TransferTest, BooleanEquality) {
4750   std::string Code = R"(
4751     void target(bool Bar) {
4752       bool Foo = true;
4753       if (Bar == Foo) {
4754         (void)0;
4755         /*[[p-then]]*/
4756       } else {
4757         (void)0;
4758         /*[[p-else]]*/
4759       }
4760     }
4761   )";
4762   runDataflow(
4763       Code,
4764       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4765          ASTContext &ASTCtx) {
4766         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-then", "p-else"));
4767         const Environment &EnvThen =
4768             getEnvironmentAtAnnotation(Results, "p-then");
4769         const Environment &EnvElse =
4770             getEnvironmentAtAnnotation(Results, "p-else");
4771 
4772         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4773         ASSERT_THAT(BarDecl, NotNull());
4774 
4775         auto &BarValThen = getFormula(*BarDecl, EnvThen);
4776         EXPECT_TRUE(EnvThen.proves(BarValThen));
4777 
4778         auto &BarValElse = getFormula(*BarDecl, EnvElse);
4779         EXPECT_TRUE(EnvElse.proves(EnvElse.arena().makeNot(BarValElse)));
4780       });
4781 }
4782 
4783 TEST(TransferTest, BooleanInequality) {
4784   std::string Code = R"(
4785     void target(bool Bar) {
4786       bool Foo = true;
4787       if (Bar != Foo) {
4788         (void)0;
4789         /*[[p-then]]*/
4790       } else {
4791         (void)0;
4792         /*[[p-else]]*/
4793       }
4794     }
4795   )";
4796   runDataflow(
4797       Code,
4798       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4799          ASTContext &ASTCtx) {
4800         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-then", "p-else"));
4801         const Environment &EnvThen =
4802             getEnvironmentAtAnnotation(Results, "p-then");
4803         const Environment &EnvElse =
4804             getEnvironmentAtAnnotation(Results, "p-else");
4805 
4806         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4807         ASSERT_THAT(BarDecl, NotNull());
4808 
4809         auto &BarValThen = getFormula(*BarDecl, EnvThen);
4810         EXPECT_TRUE(EnvThen.proves(EnvThen.arena().makeNot(BarValThen)));
4811 
4812         auto &BarValElse = getFormula(*BarDecl, EnvElse);
4813         EXPECT_TRUE(EnvElse.proves(BarValElse));
4814       });
4815 }
4816 
4817 TEST(TransferTest, PointerEquality) {
4818   std::string Code = R"cc(
4819     void target() {
4820       int i = 0;
4821       int i_other = 0;
4822       int *p1 = &i;
4823       int *p2 = &i;
4824       int *p_other = &i_other;
4825       int *null = nullptr;
4826 
4827       bool p1_eq_p1 = (p1 == p1);
4828       bool p1_eq_p2 = (p1 == p2);
4829       bool p1_eq_p_other = (p1 == p_other);
4830 
4831       bool p1_eq_null = (p1 == null);
4832       bool p1_eq_nullptr = (p1 == nullptr);
4833       bool null_eq_nullptr = (null == nullptr);
4834       bool nullptr_eq_nullptr = (nullptr == nullptr);
4835 
4836       // We won't duplicate all of the tests above with `!=`, as we know that
4837       // the implementation simply negates the result of the `==` comparison.
4838       // Instaed, just spot-check one case.
4839       bool p1_ne_p1 = (p1 != p1);
4840 
4841       (void)0; // [[p]]
4842     }
4843   )cc";
4844   runDataflow(
4845       Code,
4846       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4847          ASTContext &ASTCtx) {
4848         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4849 
4850         // Check the we have indeed set things up so that `p1` and `p2` have
4851         // different pointer values.
4852         EXPECT_NE(&getValueForDecl<PointerValue>(ASTCtx, Env, "p1"),
4853                   &getValueForDecl<PointerValue>(ASTCtx, Env, "p2"));
4854 
4855         EXPECT_EQ(&getValueForDecl<BoolValue>(ASTCtx, Env, "p1_eq_p1"),
4856                   &Env.getBoolLiteralValue(true));
4857         EXPECT_EQ(&getValueForDecl<BoolValue>(ASTCtx, Env, "p1_eq_p2"),
4858                   &Env.getBoolLiteralValue(true));
4859         EXPECT_TRUE(isa<AtomicBoolValue>(
4860             getValueForDecl<BoolValue>(ASTCtx, Env, "p1_eq_p_other")));
4861 
4862         EXPECT_TRUE(isa<AtomicBoolValue>(
4863             getValueForDecl<BoolValue>(ASTCtx, Env, "p1_eq_null")));
4864         EXPECT_TRUE(isa<AtomicBoolValue>(
4865             getValueForDecl<BoolValue>(ASTCtx, Env, "p1_eq_nullptr")));
4866         EXPECT_EQ(&getValueForDecl<BoolValue>(ASTCtx, Env, "null_eq_nullptr"),
4867                   &Env.getBoolLiteralValue(true));
4868         EXPECT_EQ(
4869             &getValueForDecl<BoolValue>(ASTCtx, Env, "nullptr_eq_nullptr"),
4870             &Env.getBoolLiteralValue(true));
4871 
4872         EXPECT_EQ(&getValueForDecl<BoolValue>(ASTCtx, Env, "p1_ne_p1"),
4873                   &Env.getBoolLiteralValue(false));
4874       });
4875 }
4876 
4877 TEST(TransferTest, PointerEqualityUnionMembers) {
4878   std::string Code = R"cc(
4879     union U {
4880       int i1;
4881       int i2;
4882     };
4883     void target() {
4884       U u;
4885       bool i1_eq_i2 = (&u.i1 == &u.i2);
4886 
4887       (void)0; // [[p]]
4888     }
4889   )cc";
4890   runDataflow(
4891       Code,
4892       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4893          ASTContext &ASTCtx) {
4894         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4895 
4896         // FIXME: By the standard, `u.i1` and `u.i2` should have the same
4897         // address, but we don't yet model this property of union members
4898         // correctly. The result is therefore weaker than it could be (just an
4899         // atom rather than a true literal), though not wrong.
4900         EXPECT_TRUE(isa<AtomicBoolValue>(
4901             getValueForDecl<BoolValue>(ASTCtx, Env, "i1_eq_i2")));
4902       });
4903 }
4904 
4905 TEST(TransferTest, IntegerLiteralEquality) {
4906   std::string Code = R"(
4907     void target() {
4908       bool equal = (42 == 42);
4909       // [[p]]
4910     }
4911   )";
4912   runDataflow(
4913       Code,
4914       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4915          ASTContext &ASTCtx) {
4916         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4917 
4918         auto &Equal =
4919             getValueForDecl<BoolValue>(ASTCtx, Env, "equal").formula();
4920         EXPECT_TRUE(Env.proves(Equal));
4921       });
4922 }
4923 
4924 TEST(TransferTest, CorrelatedBranches) {
4925   std::string Code = R"(
4926     void target(bool B, bool C) {
4927       if (B) {
4928         return;
4929       }
4930       (void)0;
4931       /*[[p0]]*/
4932       if (C) {
4933         B = true;
4934         /*[[p1]]*/
4935       }
4936       if (B) {
4937         (void)0;
4938         /*[[p2]]*/
4939       }
4940     }
4941   )";
4942   runDataflow(
4943       Code,
4944       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4945          ASTContext &ASTCtx) {
4946         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p0", "p1", "p2"));
4947 
4948         const ValueDecl *CDecl = findValueDecl(ASTCtx, "C");
4949         ASSERT_THAT(CDecl, NotNull());
4950 
4951         {
4952           const Environment &Env = getEnvironmentAtAnnotation(Results, "p0");
4953           const ValueDecl *BDecl = findValueDecl(ASTCtx, "B");
4954           ASSERT_THAT(BDecl, NotNull());
4955           auto &BVal = getFormula(*BDecl, Env);
4956 
4957           EXPECT_TRUE(Env.proves(Env.arena().makeNot(BVal)));
4958         }
4959 
4960         {
4961           const Environment &Env = getEnvironmentAtAnnotation(Results, "p1");
4962           auto &CVal = getFormula(*CDecl, Env);
4963           EXPECT_TRUE(Env.proves(CVal));
4964         }
4965 
4966         {
4967           const Environment &Env = getEnvironmentAtAnnotation(Results, "p2");
4968           auto &CVal = getFormula(*CDecl, Env);
4969           EXPECT_TRUE(Env.proves(CVal));
4970         }
4971       });
4972 }
4973 
4974 TEST(TransferTest, LoopWithAssignmentConverges) {
4975   std::string Code = R"(
4976     bool foo();
4977 
4978     void target() {
4979        do {
4980         bool Bar = foo();
4981         if (Bar) break;
4982         (void)Bar;
4983         /*[[p]]*/
4984       } while (true);
4985     }
4986   )";
4987   // The key property that we are verifying is implicit in `runDataflow` --
4988   // namely, that the analysis succeeds, rather than hitting the maximum number
4989   // of iterations.
4990   runDataflow(
4991       Code,
4992       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4993          ASTContext &ASTCtx) {
4994         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4995         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4996 
4997         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4998         ASSERT_THAT(BarDecl, NotNull());
4999 
5000         auto &BarVal = getFormula(*BarDecl, Env);
5001         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BarVal)));
5002       });
5003 }
5004 
5005 TEST(TransferTest, LoopWithStagedAssignments) {
5006   std::string Code = R"(
5007     bool foo();
5008 
5009     void target() {
5010       bool Bar = false;
5011       bool Err = false;
5012       while (foo()) {
5013         if (Bar)
5014           Err = true;
5015         Bar = true;
5016         /*[[p]]*/
5017       }
5018     }
5019   )";
5020   runDataflow(
5021       Code,
5022       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5023          ASTContext &ASTCtx) {
5024         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5025         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5026 
5027         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
5028         ASSERT_THAT(BarDecl, NotNull());
5029         const ValueDecl *ErrDecl = findValueDecl(ASTCtx, "Err");
5030         ASSERT_THAT(ErrDecl, NotNull());
5031 
5032         auto &BarVal = getFormula(*BarDecl, Env);
5033         auto &ErrVal = getFormula(*ErrDecl, Env);
5034         EXPECT_TRUE(Env.proves(BarVal));
5035         // An unsound analysis, for example only evaluating the loop once, can
5036         // conclude that `Err` is false. So, we test that this conclusion is not
5037         // reached.
5038         EXPECT_FALSE(Env.proves(Env.arena().makeNot(ErrVal)));
5039       });
5040 }
5041 
5042 TEST(TransferTest, LoopWithReferenceAssignmentConverges) {
5043   std::string Code = R"(
5044     bool &foo();
5045 
5046     void target() {
5047        do {
5048         bool& Bar = foo();
5049         if (Bar) break;
5050         (void)Bar;
5051         /*[[p]]*/
5052       } while (true);
5053     }
5054   )";
5055   // The key property that we are verifying is that the analysis succeeds,
5056   // rather than hitting the maximum number of iterations.
5057   runDataflow(
5058       Code,
5059       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5060          ASTContext &ASTCtx) {
5061         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5062         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5063 
5064         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
5065         ASSERT_THAT(BarDecl, NotNull());
5066 
5067         auto &BarVal = getFormula(*BarDecl, Env);
5068         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BarVal)));
5069       });
5070 }
5071 
5072 TEST(TransferTest, LoopWithStructReferenceAssignmentConverges) {
5073   std::string Code = R"(
5074     struct Lookup {
5075       int x;
5076     };
5077 
5078     void target(Lookup val, bool b) {
5079       const Lookup* l = nullptr;
5080       while (b) {
5081         l = &val;
5082         /*[[p-inner]]*/
5083       }
5084       (void)0;
5085       /*[[p-outer]]*/
5086     }
5087   )";
5088   // The key property that we are verifying is implicit in `runDataflow` --
5089   // namely, that the analysis succeeds, rather than hitting the maximum number
5090   // of iterations.
5091   runDataflow(
5092       Code,
5093       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5094          ASTContext &ASTCtx) {
5095         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-inner", "p-outer"));
5096         const Environment &InnerEnv =
5097             getEnvironmentAtAnnotation(Results, "p-inner");
5098         const Environment &OuterEnv =
5099             getEnvironmentAtAnnotation(Results, "p-outer");
5100 
5101         const ValueDecl *ValDecl = findValueDecl(ASTCtx, "val");
5102         ASSERT_THAT(ValDecl, NotNull());
5103 
5104         const ValueDecl *LDecl = findValueDecl(ASTCtx, "l");
5105         ASSERT_THAT(LDecl, NotNull());
5106 
5107         // Inner.
5108         auto *LVal = dyn_cast<PointerValue>(InnerEnv.getValue(*LDecl));
5109         ASSERT_THAT(LVal, NotNull());
5110 
5111         EXPECT_EQ(&LVal->getPointeeLoc(),
5112                   InnerEnv.getStorageLocation(*ValDecl));
5113 
5114         // Outer.
5115         LVal = dyn_cast<PointerValue>(OuterEnv.getValue(*LDecl));
5116         ASSERT_THAT(LVal, NotNull());
5117 
5118         // The loop body may not have been executed, so we should not conclude
5119         // that `l` points to `val`.
5120         EXPECT_NE(&LVal->getPointeeLoc(),
5121                   OuterEnv.getStorageLocation(*ValDecl));
5122       });
5123 }
5124 
5125 TEST(TransferTest, LoopDereferencingChangingPointerConverges) {
5126   std::string Code = R"cc(
5127     bool some_condition();
5128 
5129     void target(int i1, int i2) {
5130       int *p = &i1;
5131       while (true) {
5132         (void)*p;
5133         if (some_condition())
5134           p = &i1;
5135         else
5136           p = &i2;
5137       }
5138     }
5139   )cc";
5140   ASSERT_THAT_ERROR(checkDataflowWithNoopAnalysis(Code), llvm::Succeeded());
5141 }
5142 
5143 TEST(TransferTest, LoopDereferencingChangingRecordPointerConverges) {
5144   std::string Code = R"cc(
5145     struct Lookup {
5146       int x;
5147     };
5148 
5149     bool some_condition();
5150 
5151     void target(Lookup l1, Lookup l2) {
5152       Lookup *l = &l1;
5153       while (true) {
5154         (void)l->x;
5155         if (some_condition())
5156           l = &l1;
5157         else
5158           l = &l2;
5159       }
5160     }
5161   )cc";
5162   ASSERT_THAT_ERROR(checkDataflowWithNoopAnalysis(Code), llvm::Succeeded());
5163 }
5164 
5165 TEST(TransferTest, LoopWithShortCircuitedConditionConverges) {
5166   std::string Code = R"cc(
5167     bool foo();
5168 
5169     void target() {
5170       bool c = false;
5171       while (foo() || foo()) {
5172         c = true;
5173       }
5174     }
5175   )cc";
5176   ASSERT_THAT_ERROR(checkDataflowWithNoopAnalysis(Code), llvm::Succeeded());
5177 }
5178 
5179 TEST(TransferTest, LoopCanProveInvariantForBoolean) {
5180   // Check that we can prove `b` is always false in the loop.
5181   // This test exercises the logic in `widenDistinctValues()` that preserves
5182   // information if the boolean can be proved to be either true or false in both
5183   // the previous and current iteration.
5184   std::string Code = R"cc(
5185     int return_int();
5186     void target() {
5187       bool b = return_int() == 0;
5188       if (b) return;
5189       while (true) {
5190         b;
5191         // [[p]]
5192         b = return_int() == 0;
5193         if (b) return;
5194       }
5195     }
5196   )cc";
5197   runDataflow(
5198       Code,
5199       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5200          ASTContext &ASTCtx) {
5201         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5202         auto &BVal = getValueForDecl<BoolValue>(ASTCtx, Env, "b");
5203         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BVal.formula())));
5204       });
5205 }
5206 
5207 TEST(TransferTest, DoesNotCrashOnUnionThisExpr) {
5208   std::string Code = R"cc(
5209     union Union {
5210       int A;
5211       float B;
5212     };
5213 
5214     void foo() {
5215       Union A;
5216       Union B;
5217       A = B;
5218     }
5219   )cc";
5220   // This is a crash regression test when calling the transfer function on a
5221   // `CXXThisExpr` that refers to a union.
5222   runDataflow(
5223       Code,
5224       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &,
5225          ASTContext &) {},
5226       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator=");
5227 }
5228 
5229 TEST(TransferTest, DoesNotCrashOnNullChildren) {
5230   std::string Code = (CoroutineLibrary + R"cc(
5231     task target() noexcept {
5232       co_return;
5233     }
5234   )cc")
5235                          .str();
5236   // This is a crash regression test when calling `AdornedCFG::build` on a
5237   // statement (in this case, the `CoroutineBodyStmt`) with null children.
5238   runDataflow(
5239       Code,
5240       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &,
5241          ASTContext &) {},
5242       LangStandard::lang_cxx20, /*ApplyBuiltinTransfer=*/true);
5243 }
5244 
5245 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToRefs) {
5246   std::string Code = R"(
5247     struct A {
5248       int Foo;
5249       int Bar;
5250     };
5251 
5252     void target() {
5253       int Qux;
5254       A Baz;
5255       Baz.Foo = Qux;
5256       auto &FooRef = Baz.Foo;
5257       auto &BarRef = Baz.Bar;
5258       auto &[BoundFooRef, BoundBarRef] = Baz;
5259       // [[p]]
5260     }
5261   )";
5262   runDataflow(
5263       Code,
5264       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5265          ASTContext &ASTCtx) {
5266         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5267         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5268 
5269         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
5270         ASSERT_THAT(FooRefDecl, NotNull());
5271 
5272         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
5273         ASSERT_THAT(BarRefDecl, NotNull());
5274 
5275         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
5276         ASSERT_THAT(QuxDecl, NotNull());
5277 
5278         const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef");
5279         ASSERT_THAT(BoundFooRefDecl, NotNull());
5280 
5281         const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef");
5282         ASSERT_THAT(BoundBarRefDecl, NotNull());
5283 
5284         const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl);
5285         ASSERT_THAT(FooRefLoc, NotNull());
5286 
5287         const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl);
5288         ASSERT_THAT(BarRefLoc, NotNull());
5289 
5290         const Value *QuxVal = Env.getValue(*QuxDecl);
5291         ASSERT_THAT(QuxVal, NotNull());
5292 
5293         const StorageLocation *BoundFooRefLoc =
5294             Env.getStorageLocation(*BoundFooRefDecl);
5295         EXPECT_EQ(BoundFooRefLoc, FooRefLoc);
5296 
5297         const StorageLocation *BoundBarRefLoc =
5298             Env.getStorageLocation(*BoundBarRefDecl);
5299         EXPECT_EQ(BoundBarRefLoc, BarRefLoc);
5300 
5301         EXPECT_EQ(Env.getValue(*BoundFooRefDecl), QuxVal);
5302       });
5303 }
5304 
5305 TEST(TransferTest, StructuredBindingAssignFromStructRefMembersToRefs) {
5306   std::string Code = R"(
5307     struct A {
5308       int &Foo;
5309       int &Bar;
5310     };
5311 
5312     void target(A Baz) {
5313       int Qux;
5314       Baz.Foo = Qux;
5315       auto &FooRef = Baz.Foo;
5316       auto &BarRef = Baz.Bar;
5317       auto &[BoundFooRef, BoundBarRef] = Baz;
5318       // [[p]]
5319     }
5320   )";
5321   runDataflow(
5322       Code,
5323       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5324          ASTContext &ASTCtx) {
5325         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5326         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5327 
5328         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
5329         ASSERT_THAT(FooRefDecl, NotNull());
5330 
5331         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
5332         ASSERT_THAT(BarRefDecl, NotNull());
5333 
5334         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
5335         ASSERT_THAT(QuxDecl, NotNull());
5336 
5337         const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef");
5338         ASSERT_THAT(BoundFooRefDecl, NotNull());
5339 
5340         const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef");
5341         ASSERT_THAT(BoundBarRefDecl, NotNull());
5342 
5343         const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl);
5344         ASSERT_THAT(FooRefLoc, NotNull());
5345 
5346         const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl);
5347         ASSERT_THAT(BarRefLoc, NotNull());
5348 
5349         const Value *QuxVal = Env.getValue(*QuxDecl);
5350         ASSERT_THAT(QuxVal, NotNull());
5351 
5352         const StorageLocation *BoundFooRefLoc =
5353             Env.getStorageLocation(*BoundFooRefDecl);
5354         EXPECT_EQ(BoundFooRefLoc, FooRefLoc);
5355 
5356         const StorageLocation *BoundBarRefLoc =
5357             Env.getStorageLocation(*BoundBarRefDecl);
5358         EXPECT_EQ(BoundBarRefLoc, BarRefLoc);
5359 
5360         EXPECT_EQ(Env.getValue(*BoundFooRefDecl), QuxVal);
5361       });
5362 }
5363 
5364 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToInts) {
5365   std::string Code = R"(
5366     struct A {
5367       int Foo;
5368       int Bar;
5369     };
5370 
5371     void target() {
5372       int Qux;
5373       A Baz;
5374       Baz.Foo = Qux;
5375       auto &FooRef = Baz.Foo;
5376       auto &BarRef = Baz.Bar;
5377       auto [BoundFoo, BoundBar] = Baz;
5378       // [[p]]
5379     }
5380   )";
5381   runDataflow(
5382       Code,
5383       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5384          ASTContext &ASTCtx) {
5385         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5386         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5387 
5388         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
5389         ASSERT_THAT(FooRefDecl, NotNull());
5390 
5391         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
5392         ASSERT_THAT(BarRefDecl, NotNull());
5393 
5394         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
5395         ASSERT_THAT(BoundFooDecl, NotNull());
5396 
5397         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
5398         ASSERT_THAT(BoundBarDecl, NotNull());
5399 
5400         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
5401         ASSERT_THAT(QuxDecl, NotNull());
5402 
5403         const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl);
5404         ASSERT_THAT(FooRefLoc, NotNull());
5405 
5406         const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl);
5407         ASSERT_THAT(BarRefLoc, NotNull());
5408 
5409         const Value *QuxVal = Env.getValue(*QuxDecl);
5410         ASSERT_THAT(QuxVal, NotNull());
5411 
5412         const StorageLocation *BoundFooLoc =
5413             Env.getStorageLocation(*BoundFooDecl);
5414         EXPECT_NE(BoundFooLoc, FooRefLoc);
5415 
5416         const StorageLocation *BoundBarLoc =
5417             Env.getStorageLocation(*BoundBarDecl);
5418         EXPECT_NE(BoundBarLoc, BarRefLoc);
5419 
5420         EXPECT_EQ(Env.getValue(*BoundFooDecl), QuxVal);
5421       });
5422 }
5423 
5424 TEST(TransferTest, StructuredBindingAssignFromTupleLikeType) {
5425   std::string Code = R"(
5426     namespace std {
5427     using size_t = int;
5428     template <class> struct tuple_size;
5429     template <std::size_t, class> struct tuple_element;
5430     template <class...> class tuple;
5431 
5432     namespace {
5433     template <class T, T v>
5434     struct size_helper { static const T value = v; };
5435     } // namespace
5436 
5437     template <class... T>
5438     struct tuple_size<tuple<T...>> : size_helper<std::size_t, sizeof...(T)> {};
5439 
5440     template <std::size_t I, class... T>
5441     struct tuple_element<I, tuple<T...>> {
5442       using type =  __type_pack_element<I, T...>;
5443     };
5444 
5445     template <class...> class tuple {};
5446 
5447     template <std::size_t I, class... T>
5448     typename tuple_element<I, tuple<T...>>::type get(tuple<T...>);
5449     } // namespace std
5450 
5451     std::tuple<bool, int> makeTuple();
5452 
5453     void target(bool B) {
5454       auto [BoundFoo, BoundBar] = makeTuple();
5455       bool Baz;
5456       // Include if-then-else to test interaction of `BindingDecl` with join.
5457       if (B) {
5458         Baz = BoundFoo;
5459         (void)BoundBar;
5460         // [[p1]]
5461       } else {
5462         Baz = BoundFoo;
5463       }
5464       (void)0;
5465       // [[p2]]
5466     }
5467   )";
5468   runDataflow(
5469       Code,
5470       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5471          ASTContext &ASTCtx) {
5472         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
5473         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
5474 
5475         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
5476         ASSERT_THAT(BoundFooDecl, NotNull());
5477 
5478         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
5479         ASSERT_THAT(BoundBarDecl, NotNull());
5480 
5481         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
5482         ASSERT_THAT(BazDecl, NotNull());
5483 
5484         // BindingDecls always map to references -- either lvalue or rvalue, so
5485         // we still need to skip here.
5486         const Value *BoundFooValue = Env1.getValue(*BoundFooDecl);
5487         ASSERT_THAT(BoundFooValue, NotNull());
5488         EXPECT_TRUE(isa<BoolValue>(BoundFooValue));
5489 
5490         const Value *BoundBarValue = Env1.getValue(*BoundBarDecl);
5491         ASSERT_THAT(BoundBarValue, NotNull());
5492         EXPECT_TRUE(isa<IntegerValue>(BoundBarValue));
5493 
5494         // Test that a `DeclRefExpr` to a `BindingDecl` works as expected.
5495         EXPECT_EQ(Env1.getValue(*BazDecl), BoundFooValue);
5496 
5497         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
5498 
5499         // Test that `BoundFooDecl` retains the value we expect, after the join.
5500         BoundFooValue = Env2.getValue(*BoundFooDecl);
5501         EXPECT_EQ(Env2.getValue(*BazDecl), BoundFooValue);
5502       });
5503 }
5504 
5505 TEST(TransferTest, StructuredBindingAssignRefFromTupleLikeType) {
5506   std::string Code = R"(
5507     namespace std {
5508     using size_t = int;
5509     template <class> struct tuple_size;
5510     template <std::size_t, class> struct tuple_element;
5511     template <class...> class tuple;
5512 
5513     namespace {
5514     template <class T, T v>
5515     struct size_helper { static const T value = v; };
5516     } // namespace
5517 
5518     template <class... T>
5519     struct tuple_size<tuple<T...>> : size_helper<std::size_t, sizeof...(T)> {};
5520 
5521     template <std::size_t I, class... T>
5522     struct tuple_element<I, tuple<T...>> {
5523       using type =  __type_pack_element<I, T...>;
5524     };
5525 
5526     template <class...> class tuple {};
5527 
5528     template <std::size_t I, class... T>
5529     typename tuple_element<I, tuple<T...>>::type get(tuple<T...>);
5530     } // namespace std
5531 
5532     std::tuple<bool, int> &getTuple();
5533 
5534     void target(bool B) {
5535       auto &[BoundFoo, BoundBar] = getTuple();
5536       bool Baz;
5537       // Include if-then-else to test interaction of `BindingDecl` with join.
5538       if (B) {
5539         Baz = BoundFoo;
5540         (void)BoundBar;
5541         // [[p1]]
5542       } else {
5543         Baz = BoundFoo;
5544       }
5545       (void)0;
5546       // [[p2]]
5547     }
5548   )";
5549   runDataflow(
5550       Code,
5551       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5552          ASTContext &ASTCtx) {
5553         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
5554         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
5555 
5556         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
5557         ASSERT_THAT(BoundFooDecl, NotNull());
5558 
5559         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
5560         ASSERT_THAT(BoundBarDecl, NotNull());
5561 
5562         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
5563         ASSERT_THAT(BazDecl, NotNull());
5564 
5565         const Value *BoundFooValue = Env1.getValue(*BoundFooDecl);
5566         ASSERT_THAT(BoundFooValue, NotNull());
5567         EXPECT_TRUE(isa<BoolValue>(BoundFooValue));
5568 
5569         const Value *BoundBarValue = Env1.getValue(*BoundBarDecl);
5570         ASSERT_THAT(BoundBarValue, NotNull());
5571         EXPECT_TRUE(isa<IntegerValue>(BoundBarValue));
5572 
5573         // Test that a `DeclRefExpr` to a `BindingDecl` (with reference type)
5574         // works as expected. We don't test aliasing properties of the
5575         // reference, because we don't model `std::get` and so have no way to
5576         // equate separate references into the tuple.
5577         EXPECT_EQ(Env1.getValue(*BazDecl), BoundFooValue);
5578 
5579         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
5580 
5581         // Test that `BoundFooDecl` retains the value we expect, after the join.
5582         BoundFooValue = Env2.getValue(*BoundFooDecl);
5583         EXPECT_EQ(Env2.getValue(*BazDecl), BoundFooValue);
5584       });
5585 }
5586 
5587 TEST(TransferTest, BinaryOperatorComma) {
5588   std::string Code = R"(
5589     void target(int Foo, int Bar) {
5590       int &Baz = (Foo, Bar);
5591       // [[p]]
5592     }
5593   )";
5594   runDataflow(
5595       Code,
5596       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5597          ASTContext &ASTCtx) {
5598         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5599         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5600 
5601         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
5602         ASSERT_THAT(BarDecl, NotNull());
5603 
5604         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
5605         ASSERT_THAT(BazDecl, NotNull());
5606 
5607         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
5608         ASSERT_THAT(BarLoc, NotNull());
5609 
5610         const StorageLocation *BazLoc = Env.getStorageLocation(*BazDecl);
5611         EXPECT_EQ(BazLoc, BarLoc);
5612       });
5613 }
5614 
5615 TEST(TransferTest, ConditionalOperatorValue) {
5616   std::string Code = R"(
5617     void target(bool Cond, bool B1, bool B2) {
5618       bool JoinSame = Cond ? B1 : B1;
5619       bool JoinDifferent = Cond ? B1 : B2;
5620       // [[p]]
5621     }
5622   )";
5623   runDataflow(
5624       Code,
5625       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5626          ASTContext &ASTCtx) {
5627         Environment Env = getEnvironmentAtAnnotation(Results, "p").fork();
5628 
5629         auto &B1 = getValueForDecl<BoolValue>(ASTCtx, Env, "B1");
5630         auto &B2 = getValueForDecl<BoolValue>(ASTCtx, Env, "B2");
5631         auto &JoinSame = getValueForDecl<BoolValue>(ASTCtx, Env, "JoinSame");
5632         auto &JoinDifferent =
5633             getValueForDecl<BoolValue>(ASTCtx, Env, "JoinDifferent");
5634 
5635         EXPECT_EQ(&JoinSame, &B1);
5636 
5637         const Formula &JoinDifferentEqB1 =
5638             Env.arena().makeEquals(JoinDifferent.formula(), B1.formula());
5639         EXPECT_TRUE(Env.allows(JoinDifferentEqB1));
5640         EXPECT_FALSE(Env.proves(JoinDifferentEqB1));
5641 
5642         const Formula &JoinDifferentEqB2 =
5643             Env.arena().makeEquals(JoinDifferent.formula(), B2.formula());
5644         EXPECT_TRUE(Env.allows(JoinDifferentEqB2));
5645         EXPECT_FALSE(Env.proves(JoinDifferentEqB1));
5646       });
5647 }
5648 
5649 TEST(TransferTest, ConditionalOperatorLocation) {
5650   std::string Code = R"(
5651     void target(bool Cond, int I1, int I2) {
5652       int &JoinSame = Cond ? I1 : I1;
5653       int &JoinDifferent = Cond ? I1 : I2;
5654       // [[p]]
5655     }
5656   )";
5657   runDataflow(
5658       Code,
5659       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5660          ASTContext &ASTCtx) {
5661         Environment Env = getEnvironmentAtAnnotation(Results, "p").fork();
5662 
5663         StorageLocation &I1 = getLocForDecl(ASTCtx, Env, "I1");
5664         StorageLocation &I2 = getLocForDecl(ASTCtx, Env, "I2");
5665         StorageLocation &JoinSame = getLocForDecl(ASTCtx, Env, "JoinSame");
5666         StorageLocation &JoinDifferent =
5667             getLocForDecl(ASTCtx, Env, "JoinDifferent");
5668 
5669         EXPECT_EQ(&JoinSame, &I1);
5670 
5671         EXPECT_NE(&JoinDifferent, &I1);
5672         EXPECT_NE(&JoinDifferent, &I2);
5673       });
5674 }
5675 
5676 TEST(TransferTest, ConditionalOperatorOnConstantExpr) {
5677   // This is a regression test: We used to crash when a `ConstantExpr` was used
5678   // in the branches of a conditional operator.
5679   std::string Code = R"cc(
5680     consteval bool identity(bool B) { return B; }
5681     void target(bool Cond) {
5682       bool JoinTrueTrue = Cond ? identity(true) : identity(true);
5683       bool JoinTrueFalse = Cond ? identity(true) : identity(false);
5684       // [[p]]
5685     }
5686   )cc";
5687   runDataflow(
5688       Code,
5689       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5690          ASTContext &ASTCtx) {
5691         Environment Env = getEnvironmentAtAnnotation(Results, "p").fork();
5692 
5693         auto &JoinTrueTrue =
5694             getValueForDecl<BoolValue>(ASTCtx, Env, "JoinTrueTrue");
5695         // FIXME: This test documents the current behavior, namely that we
5696         // don't actually use the constant result of the `ConstantExpr` and
5697         // instead treat it like a normal function call.
5698         EXPECT_EQ(JoinTrueTrue.formula().kind(), Formula::Kind::AtomRef);
5699         // EXPECT_TRUE(JoinTrueTrue.formula().literal());
5700 
5701         auto &JoinTrueFalse =
5702             getValueForDecl<BoolValue>(ASTCtx, Env, "JoinTrueFalse");
5703         EXPECT_EQ(JoinTrueFalse.formula().kind(), Formula::Kind::AtomRef);
5704       },
5705       LangStandard::lang_cxx20);
5706 }
5707 
5708 TEST(TransferTest, IfStmtBranchExtendsFlowCondition) {
5709   std::string Code = R"(
5710     void target(bool Foo) {
5711       if (Foo) {
5712         (void)0;
5713         // [[if_then]]
5714       } else {
5715         (void)0;
5716         // [[if_else]]
5717       }
5718     }
5719   )";
5720   runDataflow(
5721       Code,
5722       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5723          ASTContext &ASTCtx) {
5724         ASSERT_THAT(Results.keys(), UnorderedElementsAre("if_then", "if_else"));
5725         const Environment &ThenEnv =
5726             getEnvironmentAtAnnotation(Results, "if_then");
5727         const Environment &ElseEnv =
5728             getEnvironmentAtAnnotation(Results, "if_else");
5729 
5730         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5731         ASSERT_THAT(FooDecl, NotNull());
5732 
5733         auto &ThenFooVal= getFormula(*FooDecl, ThenEnv);
5734         EXPECT_TRUE(ThenEnv.proves(ThenFooVal));
5735 
5736         auto &ElseFooVal = getFormula(*FooDecl, ElseEnv);
5737         EXPECT_TRUE(ElseEnv.proves(ElseEnv.arena().makeNot(ElseFooVal)));
5738       });
5739 }
5740 
5741 TEST(TransferTest, WhileStmtBranchExtendsFlowCondition) {
5742   std::string Code = R"(
5743     void target(bool Foo) {
5744       while (Foo) {
5745         (void)0;
5746         // [[loop_body]]
5747       }
5748       (void)0;
5749       // [[after_loop]]
5750     }
5751   )";
5752   runDataflow(
5753       Code,
5754       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5755          ASTContext &ASTCtx) {
5756         ASSERT_THAT(Results.keys(),
5757                     UnorderedElementsAre("loop_body", "after_loop"));
5758         const Environment &LoopBodyEnv =
5759             getEnvironmentAtAnnotation(Results, "loop_body");
5760         const Environment &AfterLoopEnv =
5761             getEnvironmentAtAnnotation(Results, "after_loop");
5762 
5763         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5764         ASSERT_THAT(FooDecl, NotNull());
5765 
5766         auto &LoopBodyFooVal = getFormula(*FooDecl, LoopBodyEnv);
5767         EXPECT_TRUE(LoopBodyEnv.proves(LoopBodyFooVal));
5768 
5769         auto &AfterLoopFooVal = getFormula(*FooDecl, AfterLoopEnv);
5770         EXPECT_TRUE(
5771             AfterLoopEnv.proves(AfterLoopEnv.arena().makeNot(AfterLoopFooVal)));
5772       });
5773 }
5774 
5775 TEST(TransferTest, DoWhileStmtBranchExtendsFlowCondition) {
5776   std::string Code = R"(
5777     void target(bool Foo) {
5778       bool Bar = true;
5779       do {
5780         (void)0;
5781         // [[loop_body]]
5782         Bar = false;
5783       } while (Foo);
5784       (void)0;
5785       // [[after_loop]]
5786     }
5787   )";
5788   runDataflow(
5789       Code,
5790       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5791          ASTContext &ASTCtx) {
5792         ASSERT_THAT(Results.keys(),
5793                     UnorderedElementsAre("loop_body", "after_loop"));
5794         const Environment &LoopBodyEnv =
5795             getEnvironmentAtAnnotation(Results, "loop_body");
5796         const Environment &AfterLoopEnv =
5797             getEnvironmentAtAnnotation(Results, "after_loop");
5798         auto &A = AfterLoopEnv.arena();
5799 
5800         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5801         ASSERT_THAT(FooDecl, NotNull());
5802 
5803         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
5804         ASSERT_THAT(BarDecl, NotNull());
5805 
5806         auto &LoopBodyFooVal= getFormula(*FooDecl, LoopBodyEnv);
5807         auto &LoopBodyBarVal = getFormula(*BarDecl, LoopBodyEnv);
5808         EXPECT_TRUE(
5809             LoopBodyEnv.proves(A.makeOr(LoopBodyBarVal, LoopBodyFooVal)));
5810 
5811         auto &AfterLoopFooVal = getFormula(*FooDecl, AfterLoopEnv);
5812         auto &AfterLoopBarVal = getFormula(*BarDecl, AfterLoopEnv);
5813         EXPECT_TRUE(AfterLoopEnv.proves(A.makeNot(AfterLoopFooVal)));
5814         EXPECT_TRUE(AfterLoopEnv.proves(A.makeNot(AfterLoopBarVal)));
5815       });
5816 }
5817 
5818 TEST(TransferTest, ForStmtBranchExtendsFlowCondition) {
5819   std::string Code = R"(
5820     void target(bool Foo) {
5821       for (; Foo;) {
5822         (void)0;
5823         // [[loop_body]]
5824       }
5825       (void)0;
5826       // [[after_loop]]
5827     }
5828   )";
5829   runDataflow(
5830       Code,
5831       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5832          ASTContext &ASTCtx) {
5833         ASSERT_THAT(Results.keys(),
5834                     UnorderedElementsAre("loop_body", "after_loop"));
5835         const Environment &LoopBodyEnv =
5836             getEnvironmentAtAnnotation(Results, "loop_body");
5837         const Environment &AfterLoopEnv =
5838             getEnvironmentAtAnnotation(Results, "after_loop");
5839 
5840         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5841         ASSERT_THAT(FooDecl, NotNull());
5842 
5843         auto &LoopBodyFooVal= getFormula(*FooDecl, LoopBodyEnv);
5844         EXPECT_TRUE(LoopBodyEnv.proves(LoopBodyFooVal));
5845 
5846         auto &AfterLoopFooVal = getFormula(*FooDecl, AfterLoopEnv);
5847         EXPECT_TRUE(
5848             AfterLoopEnv.proves(AfterLoopEnv.arena().makeNot(AfterLoopFooVal)));
5849       });
5850 }
5851 
5852 TEST(TransferTest, ForStmtBranchWithoutConditionDoesNotExtendFlowCondition) {
5853   std::string Code = R"(
5854     void target(bool Foo) {
5855       for (;;) {
5856         (void)0;
5857         // [[loop_body]]
5858       }
5859     }
5860   )";
5861   runDataflow(
5862       Code,
5863       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5864          ASTContext &ASTCtx) {
5865         ASSERT_THAT(Results.keys(), UnorderedElementsAre("loop_body"));
5866         const Environment &LoopBodyEnv =
5867             getEnvironmentAtAnnotation(Results, "loop_body");
5868 
5869         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5870         ASSERT_THAT(FooDecl, NotNull());
5871 
5872         auto &LoopBodyFooVal= getFormula(*FooDecl, LoopBodyEnv);
5873         EXPECT_FALSE(LoopBodyEnv.proves(LoopBodyFooVal));
5874       });
5875 }
5876 
5877 TEST(TransferTest, ContextSensitiveOptionDisabled) {
5878   std::string Code = R"(
5879     bool GiveBool();
5880     void SetBool(bool &Var) { Var = true; }
5881 
5882     void target() {
5883       bool Foo = GiveBool();
5884       SetBool(Foo);
5885       // [[p]]
5886     }
5887   )";
5888   runDataflow(
5889       Code,
5890       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5891          ASTContext &ASTCtx) {
5892         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5893         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5894 
5895         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5896         ASSERT_THAT(FooDecl, NotNull());
5897 
5898         auto &FooVal = getFormula(*FooDecl, Env);
5899         EXPECT_FALSE(Env.proves(FooVal));
5900         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
5901       },
5902       {BuiltinOptions{/*.ContextSensitiveOpts=*/std::nullopt}});
5903 }
5904 
5905 TEST(TransferTest, ContextSensitiveReturnReference) {
5906   std::string Code = R"(
5907     class S {};
5908     S& target(bool b, S &s) {
5909       return s;
5910       // [[p]]
5911     }
5912   )";
5913   runDataflow(
5914       Code,
5915       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5916          ASTContext &ASTCtx) {
5917         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5918 
5919         const ValueDecl *SDecl = findValueDecl(ASTCtx, "s");
5920         ASSERT_THAT(SDecl, NotNull());
5921 
5922         auto *SLoc = Env.getStorageLocation(*SDecl);
5923         ASSERT_THAT(SLoc, NotNull());
5924 
5925         ASSERT_THAT(Env.getReturnStorageLocation(), Eq(SLoc));
5926       },
5927       {BuiltinOptions{ContextSensitiveOptions{}}});
5928 }
5929 
5930 // This test is a regression test, based on a real crash.
5931 TEST(TransferTest, ContextSensitiveReturnReferenceWithConditionalOperator) {
5932   std::string Code = R"(
5933     class S {};
5934     S& target(bool b, S &s) {
5935       return b ? s : s;
5936       // [[p]]
5937     }
5938   )";
5939   runDataflow(
5940       Code,
5941       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5942          ASTContext &ASTCtx) {
5943         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5944         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5945 
5946         const ValueDecl *SDecl = findValueDecl(ASTCtx, "s");
5947         ASSERT_THAT(SDecl, NotNull());
5948 
5949         auto *SLoc = Env.getStorageLocation(*SDecl);
5950         EXPECT_THAT(SLoc, NotNull());
5951 
5952         auto *Loc = Env.getReturnStorageLocation();
5953         EXPECT_THAT(Loc, NotNull());
5954 
5955         EXPECT_EQ(Loc, SLoc);
5956       },
5957       {BuiltinOptions{ContextSensitiveOptions{}}});
5958 }
5959 
5960 TEST(TransferTest, ContextSensitiveReturnOneOfTwoReferences) {
5961   std::string Code = R"(
5962     class S {};
5963     S &callee(bool b, S &s1_parm, S &s2_parm) {
5964       if (b)
5965         return s1_parm;
5966       else
5967         return s2_parm;
5968     }
5969     void target(bool b) {
5970       S s1;
5971       S s2;
5972       S &return_s1 = s1;
5973       S &return_s2 = s2;
5974       S &return_dont_know = callee(b, s1, s2);
5975       // [[p]]
5976     }
5977   )";
5978   runDataflow(
5979       Code,
5980       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5981          ASTContext &ASTCtx) {
5982         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5983 
5984         const ValueDecl *S1 = findValueDecl(ASTCtx, "s1");
5985         ASSERT_THAT(S1, NotNull());
5986         const ValueDecl *S2 = findValueDecl(ASTCtx, "s2");
5987         ASSERT_THAT(S2, NotNull());
5988         const ValueDecl *ReturnS1 = findValueDecl(ASTCtx, "return_s1");
5989         ASSERT_THAT(ReturnS1, NotNull());
5990         const ValueDecl *ReturnS2 = findValueDecl(ASTCtx, "return_s2");
5991         ASSERT_THAT(ReturnS2, NotNull());
5992         const ValueDecl *ReturnDontKnow =
5993             findValueDecl(ASTCtx, "return_dont_know");
5994         ASSERT_THAT(ReturnDontKnow, NotNull());
5995 
5996         StorageLocation *S1Loc = Env.getStorageLocation(*S1);
5997         StorageLocation *S2Loc = Env.getStorageLocation(*S2);
5998 
5999         EXPECT_THAT(Env.getStorageLocation(*ReturnS1), Eq(S1Loc));
6000         EXPECT_THAT(Env.getStorageLocation(*ReturnS2), Eq(S2Loc));
6001 
6002         // In the case where we don't have a consistent storage location for
6003         // the return value, the framework creates a new storage location, which
6004         // should be different from the storage locations of `s1` and `s2`.
6005         EXPECT_THAT(Env.getStorageLocation(*ReturnDontKnow), Ne(S1Loc));
6006         EXPECT_THAT(Env.getStorageLocation(*ReturnDontKnow), Ne(S2Loc));
6007       },
6008       {BuiltinOptions{ContextSensitiveOptions{}}});
6009 }
6010 
6011 TEST(TransferTest, ContextSensitiveDepthZero) {
6012   std::string Code = R"(
6013     bool GiveBool();
6014     void SetBool(bool &Var) { Var = true; }
6015 
6016     void target() {
6017       bool Foo = GiveBool();
6018       SetBool(Foo);
6019       // [[p]]
6020     }
6021   )";
6022   runDataflow(
6023       Code,
6024       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6025          ASTContext &ASTCtx) {
6026         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6027         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6028 
6029         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6030         ASSERT_THAT(FooDecl, NotNull());
6031 
6032         auto &FooVal = getFormula(*FooDecl, Env);
6033         EXPECT_FALSE(Env.proves(FooVal));
6034         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
6035       },
6036       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/0}}});
6037 }
6038 
6039 TEST(TransferTest, ContextSensitiveSetTrue) {
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_TRUE(Env.proves(FooVal));
6062       },
6063       {BuiltinOptions{ContextSensitiveOptions{}}});
6064 }
6065 
6066 TEST(TransferTest, ContextSensitiveSetFalse) {
6067   std::string Code = R"(
6068     bool GiveBool();
6069     void SetBool(bool &Var) { Var = false; }
6070 
6071     void target() {
6072       bool Foo = GiveBool();
6073       SetBool(Foo);
6074       // [[p]]
6075     }
6076   )";
6077   runDataflow(
6078       Code,
6079       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6080          ASTContext &ASTCtx) {
6081         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6082         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6083 
6084         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6085         ASSERT_THAT(FooDecl, NotNull());
6086 
6087         auto &FooVal = getFormula(*FooDecl, Env);
6088         EXPECT_TRUE(Env.proves(Env.arena().makeNot(FooVal)));
6089       },
6090       {BuiltinOptions{ContextSensitiveOptions{}}});
6091 }
6092 
6093 TEST(TransferTest, ContextSensitiveSetBothTrueAndFalse) {
6094   std::string Code = R"(
6095     bool GiveBool();
6096     void SetBool(bool &Var, bool Val) { Var = Val; }
6097 
6098     void target() {
6099       bool Foo = GiveBool();
6100       bool Bar = GiveBool();
6101       SetBool(Foo, true);
6102       SetBool(Bar, false);
6103       // [[p]]
6104     }
6105   )";
6106   runDataflow(
6107       Code,
6108       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6109          ASTContext &ASTCtx) {
6110         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6111         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6112         auto &A = Env.arena();
6113 
6114         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6115         ASSERT_THAT(FooDecl, NotNull());
6116 
6117         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
6118         ASSERT_THAT(BarDecl, NotNull());
6119 
6120         auto &FooVal = getFormula(*FooDecl, Env);
6121         EXPECT_TRUE(Env.proves(FooVal));
6122         EXPECT_FALSE(Env.proves(A.makeNot(FooVal)));
6123 
6124         auto &BarVal = getFormula(*BarDecl, Env);
6125         EXPECT_FALSE(Env.proves(BarVal));
6126         EXPECT_TRUE(Env.proves(A.makeNot(BarVal)));
6127       },
6128       {BuiltinOptions{ContextSensitiveOptions{}}});
6129 }
6130 
6131 TEST(TransferTest, ContextSensitiveSetTwoLayersDepthOne) {
6132   std::string Code = R"(
6133     bool GiveBool();
6134     void SetBool1(bool &Var) { Var = true; }
6135     void SetBool2(bool &Var) { SetBool1(Var); }
6136 
6137     void target() {
6138       bool Foo = GiveBool();
6139       SetBool2(Foo);
6140       // [[p]]
6141     }
6142   )";
6143   runDataflow(
6144       Code,
6145       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6146          ASTContext &ASTCtx) {
6147         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6148         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6149 
6150         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6151         ASSERT_THAT(FooDecl, NotNull());
6152 
6153         auto &FooVal = getFormula(*FooDecl, Env);
6154         EXPECT_FALSE(Env.proves(FooVal));
6155         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
6156       },
6157       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/1}}});
6158 }
6159 
6160 TEST(TransferTest, ContextSensitiveSetTwoLayersDepthTwo) {
6161   std::string Code = R"(
6162     bool GiveBool();
6163     void SetBool1(bool &Var) { Var = true; }
6164     void SetBool2(bool &Var) { SetBool1(Var); }
6165 
6166     void target() {
6167       bool Foo = GiveBool();
6168       SetBool2(Foo);
6169       // [[p]]
6170     }
6171   )";
6172   runDataflow(
6173       Code,
6174       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6175          ASTContext &ASTCtx) {
6176         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6177         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6178 
6179         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6180         ASSERT_THAT(FooDecl, NotNull());
6181 
6182         auto &FooVal = getFormula(*FooDecl, Env);
6183         EXPECT_TRUE(Env.proves(FooVal));
6184       },
6185       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/2}}});
6186 }
6187 
6188 TEST(TransferTest, ContextSensitiveSetThreeLayersDepthTwo) {
6189   std::string Code = R"(
6190     bool GiveBool();
6191     void SetBool1(bool &Var) { Var = true; }
6192     void SetBool2(bool &Var) { SetBool1(Var); }
6193     void SetBool3(bool &Var) { SetBool2(Var); }
6194 
6195     void target() {
6196       bool Foo = GiveBool();
6197       SetBool3(Foo);
6198       // [[p]]
6199     }
6200   )";
6201   runDataflow(
6202       Code,
6203       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6204          ASTContext &ASTCtx) {
6205         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6206         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6207 
6208         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6209         ASSERT_THAT(FooDecl, NotNull());
6210 
6211         auto &FooVal = getFormula(*FooDecl, Env);
6212         EXPECT_FALSE(Env.proves(FooVal));
6213         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
6214       },
6215       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/2}}});
6216 }
6217 
6218 TEST(TransferTest, ContextSensitiveSetThreeLayersDepthThree) {
6219   std::string Code = R"(
6220     bool GiveBool();
6221     void SetBool1(bool &Var) { Var = true; }
6222     void SetBool2(bool &Var) { SetBool1(Var); }
6223     void SetBool3(bool &Var) { SetBool2(Var); }
6224 
6225     void target() {
6226       bool Foo = GiveBool();
6227       SetBool3(Foo);
6228       // [[p]]
6229     }
6230   )";
6231   runDataflow(
6232       Code,
6233       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6234          ASTContext &ASTCtx) {
6235         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6236         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6237 
6238         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6239         ASSERT_THAT(FooDecl, NotNull());
6240 
6241         auto &FooVal = getFormula(*FooDecl, Env);
6242         EXPECT_TRUE(Env.proves(FooVal));
6243       },
6244       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/3}}});
6245 }
6246 
6247 TEST(TransferTest, ContextSensitiveMutualRecursion) {
6248   std::string Code = R"(
6249     bool Pong(bool X, bool Y);
6250 
6251     bool Ping(bool X, bool Y) {
6252       if (X) {
6253         return Y;
6254       } else {
6255         return Pong(!X, Y);
6256       }
6257     }
6258 
6259     bool Pong(bool X, bool Y) {
6260       if (Y) {
6261         return X;
6262       } else {
6263         return Ping(X, !Y);
6264       }
6265     }
6266 
6267     void target() {
6268       bool Foo = Ping(false, false);
6269       // [[p]]
6270     }
6271   )";
6272   runDataflow(
6273       Code,
6274       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6275          ASTContext &ASTCtx) {
6276         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6277         // The analysis doesn't crash...
6278         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6279 
6280         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6281         ASSERT_THAT(FooDecl, NotNull());
6282 
6283         auto &FooVal = getFormula(*FooDecl, Env);
6284         // ... but it also can't prove anything here.
6285         EXPECT_FALSE(Env.proves(FooVal));
6286         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
6287       },
6288       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/4}}});
6289 }
6290 
6291 TEST(TransferTest, ContextSensitiveSetMultipleLines) {
6292   std::string Code = R"(
6293     void SetBools(bool &Var1, bool &Var2) {
6294       Var1 = true;
6295       Var2 = false;
6296     }
6297 
6298     void target() {
6299       bool Foo = false;
6300       bool Bar = true;
6301       SetBools(Foo, Bar);
6302       // [[p]]
6303     }
6304   )";
6305   runDataflow(
6306       Code,
6307       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6308          ASTContext &ASTCtx) {
6309         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6310         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6311 
6312         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6313         ASSERT_THAT(FooDecl, NotNull());
6314 
6315         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
6316         ASSERT_THAT(BarDecl, NotNull());
6317 
6318         auto &FooVal = getFormula(*FooDecl, Env);
6319         EXPECT_TRUE(Env.proves(FooVal));
6320         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
6321 
6322         auto &BarVal = getFormula(*BarDecl, Env);
6323         EXPECT_FALSE(Env.proves(BarVal));
6324         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BarVal)));
6325       },
6326       {BuiltinOptions{ContextSensitiveOptions{}}});
6327 }
6328 
6329 TEST(TransferTest, ContextSensitiveSetMultipleBlocks) {
6330   std::string Code = R"(
6331     void IfCond(bool Cond, bool &Then, bool &Else) {
6332       if (Cond) {
6333         Then = true;
6334       } else {
6335         Else = true;
6336       }
6337     }
6338 
6339     void target() {
6340       bool Foo = false;
6341       bool Bar = false;
6342       bool Baz = false;
6343       IfCond(Foo, Bar, Baz);
6344       // [[p]]
6345     }
6346   )";
6347   runDataflow(
6348       Code,
6349       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6350          ASTContext &ASTCtx) {
6351         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6352         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6353 
6354         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
6355         ASSERT_THAT(BarDecl, NotNull());
6356 
6357         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
6358         ASSERT_THAT(BazDecl, NotNull());
6359 
6360         auto &BarVal = getFormula(*BarDecl, Env);
6361         EXPECT_FALSE(Env.proves(BarVal));
6362         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BarVal)));
6363 
6364         auto &BazVal = getFormula(*BazDecl, Env);
6365         EXPECT_TRUE(Env.proves(BazVal));
6366         EXPECT_FALSE(Env.proves(Env.arena().makeNot(BazVal)));
6367       },
6368       {BuiltinOptions{ContextSensitiveOptions{}}});
6369 }
6370 
6371 TEST(TransferTest, ContextSensitiveReturnVoid) {
6372   std::string Code = R"(
6373     void Noop() { return; }
6374 
6375     void target() {
6376       Noop();
6377       // [[p]]
6378     }
6379   )";
6380   runDataflow(
6381       Code,
6382       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6383          ASTContext &ASTCtx) {
6384         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6385         // This just tests that the analysis doesn't crash.
6386       },
6387       {BuiltinOptions{ContextSensitiveOptions{}}});
6388 }
6389 
6390 TEST(TransferTest, ContextSensitiveReturnTrue) {
6391   std::string Code = R"(
6392     bool GiveBool() { return true; }
6393 
6394     void target() {
6395       bool Foo = GiveBool();
6396       // [[p]]
6397     }
6398   )";
6399   runDataflow(
6400       Code,
6401       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6402          ASTContext &ASTCtx) {
6403         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6404         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6405 
6406         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6407         ASSERT_THAT(FooDecl, NotNull());
6408 
6409         auto &FooVal = getFormula(*FooDecl, Env);
6410         EXPECT_TRUE(Env.proves(FooVal));
6411       },
6412       {BuiltinOptions{ContextSensitiveOptions{}}});
6413 }
6414 
6415 TEST(TransferTest, ContextSensitiveReturnFalse) {
6416   std::string Code = R"(
6417     bool GiveBool() { return false; }
6418 
6419     void target() {
6420       bool Foo = GiveBool();
6421       // [[p]]
6422     }
6423   )";
6424   runDataflow(
6425       Code,
6426       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6427          ASTContext &ASTCtx) {
6428         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6429         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6430 
6431         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6432         ASSERT_THAT(FooDecl, NotNull());
6433 
6434         auto &FooVal = getFormula(*FooDecl, Env);
6435         EXPECT_TRUE(Env.proves(Env.arena().makeNot(FooVal)));
6436       },
6437       {BuiltinOptions{ContextSensitiveOptions{}}});
6438 }
6439 
6440 TEST(TransferTest, ContextSensitiveReturnArg) {
6441   std::string Code = R"(
6442     bool GiveBool();
6443     bool GiveBack(bool Arg) { return Arg; }
6444 
6445     void target() {
6446       bool Foo = GiveBool();
6447       bool Bar = GiveBack(Foo);
6448       bool Baz = Foo == Bar;
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 *BazDecl = findValueDecl(ASTCtx, "Baz");
6460         ASSERT_THAT(BazDecl, NotNull());
6461 
6462         auto &BazVal = getFormula(*BazDecl, Env);
6463         EXPECT_TRUE(Env.proves(BazVal));
6464       },
6465       {BuiltinOptions{ContextSensitiveOptions{}}});
6466 }
6467 
6468 TEST(TransferTest, ContextSensitiveReturnInt) {
6469   std::string Code = R"(
6470     int identity(int x) { return x; }
6471 
6472     void target() {
6473       int y = identity(42);
6474       // [[p]]
6475     }
6476   )";
6477   runDataflow(
6478       Code,
6479       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6480          ASTContext &ASTCtx) {
6481         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6482         // This just tests that the analysis doesn't crash.
6483       },
6484       {BuiltinOptions{ContextSensitiveOptions{}}});
6485 }
6486 
6487 TEST(TransferTest, ContextSensitiveReturnRecord) {
6488   std::string Code = R"(
6489     struct S {
6490       bool B;
6491     };
6492 
6493     S makeS(bool BVal) { return {BVal}; }
6494 
6495     void target() {
6496       S FalseS = makeS(false);
6497       S TrueS = makeS(true);
6498       // [[p]]
6499     }
6500   )";
6501   runDataflow(
6502       Code,
6503       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6504          ASTContext &ASTCtx) {
6505         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6506 
6507         auto &FalseSLoc =
6508             getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "FalseS");
6509         auto &TrueSLoc =
6510             getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "TrueS");
6511 
6512         EXPECT_EQ(getFieldValue(&FalseSLoc, "B", ASTCtx, Env),
6513                   &Env.getBoolLiteralValue(false));
6514         EXPECT_EQ(getFieldValue(&TrueSLoc, "B", ASTCtx, Env),
6515                   &Env.getBoolLiteralValue(true));
6516       },
6517       {BuiltinOptions{ContextSensitiveOptions{}}});
6518 }
6519 
6520 TEST(TransferTest, ContextSensitiveReturnSelfReferentialRecord) {
6521   std::string Code = R"(
6522     struct S {
6523       S() { self = this; }
6524       S *self;
6525     };
6526 
6527     S makeS() {
6528       // RVO guarantees that this will be constructed directly into `MyS`.
6529       return S();
6530     }
6531 
6532     void target() {
6533       S MyS = makeS();
6534       // [[p]]
6535     }
6536   )";
6537   runDataflow(
6538       Code,
6539       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6540          ASTContext &ASTCtx) {
6541         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6542 
6543         auto &MySLoc = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "MyS");
6544 
6545         auto *SelfVal =
6546             cast<PointerValue>(getFieldValue(&MySLoc, "self", ASTCtx, Env));
6547         EXPECT_EQ(&SelfVal->getPointeeLoc(), &MySLoc);
6548       },
6549       {BuiltinOptions{ContextSensitiveOptions{}}});
6550 }
6551 
6552 TEST(TransferTest, ContextSensitiveMethodLiteral) {
6553   std::string Code = R"(
6554     class MyClass {
6555     public:
6556       bool giveBool() { return true; }
6557     };
6558 
6559     void target() {
6560       MyClass MyObj;
6561       bool Foo = MyObj.giveBool();
6562       // [[p]]
6563     }
6564   )";
6565   runDataflow(
6566       Code,
6567       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6568          ASTContext &ASTCtx) {
6569         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6570         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6571 
6572         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6573         ASSERT_THAT(FooDecl, NotNull());
6574 
6575         auto &FooVal = getFormula(*FooDecl, Env);
6576         EXPECT_TRUE(Env.proves(FooVal));
6577       },
6578       {BuiltinOptions{ContextSensitiveOptions{}}});
6579 }
6580 
6581 TEST(TransferTest, ContextSensitiveMethodGetter) {
6582   std::string Code = R"(
6583     class MyClass {
6584     public:
6585       bool getField() { return Field; }
6586 
6587       bool Field;
6588     };
6589 
6590     void target() {
6591       MyClass MyObj;
6592       MyObj.Field = true;
6593       bool Foo = MyObj.getField();
6594       // [[p]]
6595     }
6596   )";
6597   runDataflow(
6598       Code,
6599       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6600          ASTContext &ASTCtx) {
6601         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6602         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6603 
6604         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6605         ASSERT_THAT(FooDecl, NotNull());
6606 
6607         auto &FooVal = getFormula(*FooDecl, Env);
6608         EXPECT_TRUE(Env.proves(FooVal));
6609       },
6610       {BuiltinOptions{ContextSensitiveOptions{}}});
6611 }
6612 
6613 TEST(TransferTest, ContextSensitiveMethodSetter) {
6614   std::string Code = R"(
6615     class MyClass {
6616     public:
6617       void setField(bool Val) { Field = Val; }
6618 
6619       bool Field;
6620     };
6621 
6622     void target() {
6623       MyClass MyObj;
6624       MyObj.setField(true);
6625       bool Foo = MyObj.Field;
6626       // [[p]]
6627     }
6628   )";
6629   runDataflow(
6630       Code,
6631       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6632          ASTContext &ASTCtx) {
6633         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6634         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6635 
6636         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6637         ASSERT_THAT(FooDecl, NotNull());
6638 
6639         auto &FooVal = getFormula(*FooDecl, Env);
6640         EXPECT_TRUE(Env.proves(FooVal));
6641       },
6642       {BuiltinOptions{ContextSensitiveOptions{}}});
6643 }
6644 
6645 TEST(TransferTest, ContextSensitiveMethodGetterAndSetter) {
6646   std::string Code = R"(
6647     class MyClass {
6648     public:
6649       bool getField() { return Field; }
6650       void setField(bool Val) { Field = Val; }
6651 
6652     private:
6653       bool Field;
6654     };
6655 
6656     void target() {
6657       MyClass MyObj;
6658       MyObj.setField(true);
6659       bool Foo = MyObj.getField();
6660       // [[p]]
6661     }
6662   )";
6663   runDataflow(
6664       Code,
6665       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6666          ASTContext &ASTCtx) {
6667         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6668         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6669 
6670         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6671         ASSERT_THAT(FooDecl, NotNull());
6672 
6673         auto &FooVal = getFormula(*FooDecl, Env);
6674         EXPECT_TRUE(Env.proves(FooVal));
6675       },
6676       {BuiltinOptions{ContextSensitiveOptions{}}});
6677 }
6678 
6679 
6680 TEST(TransferTest, ContextSensitiveMethodTwoLayersVoid) {
6681   std::string Code = R"(
6682     class MyClass {
6683     public:
6684       void Inner() { MyField = true; }
6685       void Outer() { Inner(); }
6686 
6687       bool MyField;
6688     };
6689 
6690     void target() {
6691       MyClass MyObj;
6692       MyObj.Outer();
6693       bool Foo = MyObj.MyField;
6694       // [[p]]
6695     }
6696   )";
6697   runDataflow(
6698       Code,
6699       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6700          ASTContext &ASTCtx) {
6701         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6702         ;
6703         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6704 
6705         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6706         ASSERT_THAT(FooDecl, NotNull());
6707 
6708         auto &FooVal = getFormula(*FooDecl, Env);
6709         EXPECT_TRUE(Env.proves(FooVal));
6710       },
6711       {BuiltinOptions{ContextSensitiveOptions{}}});
6712 }
6713 
6714 TEST(TransferTest, ContextSensitiveMethodTwoLayersReturn) {
6715   std::string Code = R"(
6716     class MyClass {
6717     public:
6718       bool Inner() { return MyField; }
6719       bool Outer() { return Inner(); }
6720 
6721       bool MyField;
6722     };
6723 
6724     void target() {
6725       MyClass MyObj;
6726       MyObj.MyField = true;
6727       bool Foo = MyObj.Outer();
6728       // [[p]]
6729     }
6730   )";
6731   runDataflow(
6732       Code,
6733       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6734          ASTContext &ASTCtx) {
6735         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6736         ;
6737         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6738 
6739         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6740         ASSERT_THAT(FooDecl, NotNull());
6741 
6742         auto &FooVal = getFormula(*FooDecl, Env);
6743         EXPECT_TRUE(Env.proves(FooVal));
6744       },
6745       {BuiltinOptions{ContextSensitiveOptions{}}});
6746 }
6747 
6748 TEST(TransferTest, ContextSensitiveConstructorBody) {
6749   std::string Code = R"(
6750     class MyClass {
6751     public:
6752       MyClass() { MyField = true; }
6753 
6754       bool MyField;
6755     };
6756 
6757     void target() {
6758       MyClass MyObj;
6759       bool Foo = MyObj.MyField;
6760       // [[p]]
6761     }
6762   )";
6763   runDataflow(
6764       Code,
6765       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6766          ASTContext &ASTCtx) {
6767         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6768         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6769 
6770         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6771         ASSERT_THAT(FooDecl, NotNull());
6772 
6773         auto &FooVal = getFormula(*FooDecl, Env);
6774         EXPECT_TRUE(Env.proves(FooVal));
6775       },
6776       {BuiltinOptions{ContextSensitiveOptions{}}});
6777 }
6778 
6779 TEST(TransferTest, ContextSensitiveConstructorInitializer) {
6780   std::string Code = R"(
6781     class MyClass {
6782     public:
6783       MyClass() : MyField(true) {}
6784 
6785       bool MyField;
6786     };
6787 
6788     void target() {
6789       MyClass MyObj;
6790       bool Foo = MyObj.MyField;
6791       // [[p]]
6792     }
6793   )";
6794   runDataflow(
6795       Code,
6796       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6797          ASTContext &ASTCtx) {
6798         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6799         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6800 
6801         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6802         ASSERT_THAT(FooDecl, NotNull());
6803 
6804         auto &FooVal = getFormula(*FooDecl, Env);
6805         EXPECT_TRUE(Env.proves(FooVal));
6806       },
6807       {BuiltinOptions{ContextSensitiveOptions{}}});
6808 }
6809 
6810 TEST(TransferTest, ContextSensitiveConstructorDefault) {
6811   std::string Code = R"(
6812     class MyClass {
6813     public:
6814       MyClass() = default;
6815 
6816       bool MyField = true;
6817     };
6818 
6819     void target() {
6820       MyClass MyObj;
6821       bool Foo = MyObj.MyField;
6822       // [[p]]
6823     }
6824   )";
6825   runDataflow(
6826       Code,
6827       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6828          ASTContext &ASTCtx) {
6829         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6830         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6831 
6832         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6833         ASSERT_THAT(FooDecl, NotNull());
6834 
6835         auto &FooVal = getFormula(*FooDecl, Env);
6836         EXPECT_TRUE(Env.proves(FooVal));
6837       },
6838       {BuiltinOptions{ContextSensitiveOptions{}}});
6839 }
6840 
6841 TEST(TransferTest, ContextSensitiveSelfReferentialClass) {
6842   // Test that the `this` pointer seen in the constructor has the same value
6843   // as the address of the variable the object is constructed into.
6844   std::string Code = R"(
6845     class MyClass {
6846     public:
6847       MyClass() : Self(this) {}
6848       MyClass *Self;
6849     };
6850 
6851     void target() {
6852       MyClass MyObj;
6853       MyClass *SelfPtr = MyObj.Self;
6854       // [[p]]
6855     }
6856   )";
6857   runDataflow(
6858       Code,
6859       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6860          ASTContext &ASTCtx) {
6861         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6862 
6863         const ValueDecl *MyObjDecl = findValueDecl(ASTCtx, "MyObj");
6864         ASSERT_THAT(MyObjDecl, NotNull());
6865 
6866         const ValueDecl *SelfDecl = findValueDecl(ASTCtx, "SelfPtr");
6867         ASSERT_THAT(SelfDecl, NotNull());
6868 
6869         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6870         auto &SelfVal = *cast<PointerValue>(Env.getValue(*SelfDecl));
6871         EXPECT_EQ(Env.getStorageLocation(*MyObjDecl), &SelfVal.getPointeeLoc());
6872       },
6873       {BuiltinOptions{ContextSensitiveOptions{}}});
6874 }
6875 
6876 TEST(TransferTest, UnnamedBitfieldInitializer) {
6877   std::string Code = R"(
6878     struct B {};
6879     struct A {
6880       unsigned a;
6881       unsigned : 4;
6882       unsigned c;
6883       B b;
6884     };
6885     void target() {
6886       A a = {};
6887       A test = a;
6888       (void)test.c;
6889     }
6890   )";
6891   runDataflow(
6892       Code,
6893       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6894          ASTContext &ASTCtx) {
6895         // This doesn't need a body because this test was crashing the framework
6896         // before handling correctly Unnamed bitfields in `InitListExpr`.
6897       });
6898 }
6899 
6900 // Repro for a crash that used to occur with chained short-circuiting logical
6901 // operators.
6902 TEST(TransferTest, ChainedLogicalOps) {
6903   std::string Code = R"(
6904     bool target() {
6905       bool b = true || false || false || false;
6906       // [[p]]
6907       return b;
6908     }
6909   )";
6910   runDataflow(
6911       Code,
6912       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6913          ASTContext &ASTCtx) {
6914         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6915         auto &B = getValueForDecl<BoolValue>(ASTCtx, Env, "b").formula();
6916         EXPECT_TRUE(Env.proves(B));
6917       });
6918 }
6919 
6920 // Repro for a crash that used to occur when we call a `noreturn` function
6921 // within one of the operands of a `&&` or `||` operator.
6922 TEST(TransferTest, NoReturnFunctionInsideShortCircuitedBooleanOp) {
6923   std::string Code = R"(
6924     __attribute__((noreturn)) int doesnt_return();
6925     bool some_condition();
6926     void target(bool b1, bool b2) {
6927       // Neither of these should crash. In addition, if we don't terminate the
6928       // program, we know that the operators need to trigger the short-circuit
6929       // logic, so `NoreturnOnRhsOfAnd` will be false and `NoreturnOnRhsOfOr`
6930       // will be true.
6931       bool NoreturnOnRhsOfAnd = b1 && doesnt_return() > 0;
6932       bool NoreturnOnRhsOfOr = b2 || doesnt_return() > 0;
6933 
6934       // Calling a `noreturn` function on the LHS of an `&&` or `||` makes the
6935       // entire expression unreachable. So we know that in both of the following
6936       // cases, if `target()` terminates, the `else` branch was taken.
6937       bool NoreturnOnLhsMakesAndUnreachable = false;
6938       if (some_condition())
6939          doesnt_return() > 0 && some_condition();
6940       else
6941          NoreturnOnLhsMakesAndUnreachable = true;
6942 
6943       bool NoreturnOnLhsMakesOrUnreachable = false;
6944       if (some_condition())
6945          doesnt_return() > 0 || some_condition();
6946       else
6947          NoreturnOnLhsMakesOrUnreachable = true;
6948 
6949       // [[p]]
6950     }
6951   )";
6952   runDataflow(
6953       Code,
6954       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6955          ASTContext &ASTCtx) {
6956         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6957         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6958         auto &A = Env.arena();
6959 
6960         // Check that [[p]] is reachable with a non-false flow condition.
6961         EXPECT_FALSE(Env.proves(A.makeLiteral(false)));
6962 
6963         auto &B1 = getValueForDecl<BoolValue>(ASTCtx, Env, "b1").formula();
6964         EXPECT_TRUE(Env.proves(A.makeNot(B1)));
6965 
6966         auto &NoreturnOnRhsOfAnd =
6967             getValueForDecl<BoolValue>(ASTCtx, Env, "NoreturnOnRhsOfAnd").formula();
6968         EXPECT_TRUE(Env.proves(A.makeNot(NoreturnOnRhsOfAnd)));
6969 
6970         auto &B2 = getValueForDecl<BoolValue>(ASTCtx, Env, "b2").formula();
6971         EXPECT_TRUE(Env.proves(B2));
6972 
6973         auto &NoreturnOnRhsOfOr =
6974             getValueForDecl<BoolValue>(ASTCtx, Env, "NoreturnOnRhsOfOr")
6975                 .formula();
6976         EXPECT_TRUE(Env.proves(NoreturnOnRhsOfOr));
6977 
6978         auto &NoreturnOnLhsMakesAndUnreachable = getValueForDecl<BoolValue>(
6979             ASTCtx, Env, "NoreturnOnLhsMakesAndUnreachable").formula();
6980         EXPECT_TRUE(Env.proves(NoreturnOnLhsMakesAndUnreachable));
6981 
6982         auto &NoreturnOnLhsMakesOrUnreachable = getValueForDecl<BoolValue>(
6983             ASTCtx, Env, "NoreturnOnLhsMakesOrUnreachable").formula();
6984         EXPECT_TRUE(Env.proves(NoreturnOnLhsMakesOrUnreachable));
6985       });
6986 }
6987 
6988 TEST(TransferTest, NewExpressions) {
6989   std::string Code = R"(
6990     void target() {
6991       int *p = new int(42);
6992       // [[after_new]]
6993     }
6994   )";
6995   runDataflow(
6996       Code,
6997       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6998          ASTContext &ASTCtx) {
6999         const Environment &Env =
7000             getEnvironmentAtAnnotation(Results, "after_new");
7001 
7002         auto &P = getValueForDecl<PointerValue>(ASTCtx, Env, "p");
7003 
7004         EXPECT_THAT(Env.getValue(P.getPointeeLoc()), NotNull());
7005       });
7006 }
7007 
7008 TEST(TransferTest, NewExpressions_Structs) {
7009   std::string Code = R"(
7010     struct Inner {
7011       int InnerField;
7012     };
7013 
7014     struct Outer {
7015       Inner OuterField;
7016     };
7017 
7018     void target() {
7019       Outer *p = new Outer;
7020       // Access the fields to make sure the analysis actually generates children
7021       // for them in the `RecordStorageLocation`.
7022       p->OuterField.InnerField;
7023       // [[after_new]]
7024     }
7025   )";
7026   runDataflow(
7027       Code,
7028       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
7029          ASTContext &ASTCtx) {
7030         const Environment &Env =
7031             getEnvironmentAtAnnotation(Results, "after_new");
7032 
7033         const ValueDecl *OuterField = findValueDecl(ASTCtx, "OuterField");
7034         const ValueDecl *InnerField = findValueDecl(ASTCtx, "InnerField");
7035 
7036         auto &P = getValueForDecl<PointerValue>(ASTCtx, Env, "p");
7037 
7038         auto &OuterLoc = cast<RecordStorageLocation>(P.getPointeeLoc());
7039         auto &OuterFieldLoc =
7040             *cast<RecordStorageLocation>(OuterLoc.getChild(*OuterField));
7041         auto &InnerFieldLoc = *OuterFieldLoc.getChild(*InnerField);
7042 
7043         EXPECT_THAT(Env.getValue(InnerFieldLoc), NotNull());
7044       });
7045 }
7046 
7047 TEST(TransferTest, FunctionToPointerDecayHasValue) {
7048   std::string Code = R"(
7049     struct A { static void static_member_func(); };
7050     void target() {
7051       // To check that we're treating function-to-pointer decay correctly,
7052       // create two pointers, then verify they refer to the same storage
7053       // location.
7054       // We need to do the test this way because even if an initializer (in this
7055       // case, the function-to-pointer decay) does not create a value, we still
7056       // create a value for the variable.
7057       void (*non_member_p1)() = target;
7058       void (*non_member_p2)() = target;
7059 
7060       // Do the same thing but for a static member function.
7061       void (*member_p1)() = A::static_member_func;
7062       void (*member_p2)() = A::static_member_func;
7063       // [[p]]
7064     }
7065   )";
7066   runDataflow(
7067       Code,
7068       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
7069          ASTContext &ASTCtx) {
7070         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
7071 
7072         auto &NonMemberP1 =
7073             getValueForDecl<PointerValue>(ASTCtx, Env, "non_member_p1");
7074         auto &NonMemberP2 =
7075             getValueForDecl<PointerValue>(ASTCtx, Env, "non_member_p2");
7076         EXPECT_EQ(&NonMemberP1.getPointeeLoc(), &NonMemberP2.getPointeeLoc());
7077 
7078         auto &MemberP1 =
7079             getValueForDecl<PointerValue>(ASTCtx, Env, "member_p1");
7080         auto &MemberP2 =
7081             getValueForDecl<PointerValue>(ASTCtx, Env, "member_p2");
7082         EXPECT_EQ(&MemberP1.getPointeeLoc(), &MemberP2.getPointeeLoc());
7083       });
7084 }
7085 
7086 // Check that a builtin function is not associated with a value. (It's only
7087 // possible to call builtin functions directly, not take their address.)
7088 TEST(TransferTest, BuiltinFunctionModeled) {
7089   std::string Code = R"(
7090     void target() {
7091       __builtin_expect(0, 0);
7092       // [[p]]
7093     }
7094   )";
7095   runDataflow(
7096       Code,
7097       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
7098          ASTContext &ASTCtx) {
7099         using ast_matchers::selectFirst;
7100         using ast_matchers::match;
7101         using ast_matchers::traverse;
7102         using ast_matchers::implicitCastExpr;
7103         using ast_matchers::hasCastKind;
7104 
7105         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
7106 
7107         auto *ImplicitCast = selectFirst<ImplicitCastExpr>(
7108             "implicit_cast",
7109             match(traverse(TK_AsIs,
7110                            implicitCastExpr(hasCastKind(CK_BuiltinFnToFnPtr))
7111                                .bind("implicit_cast")),
7112                   ASTCtx));
7113 
7114         ASSERT_THAT(ImplicitCast, NotNull());
7115         EXPECT_THAT(Env.getValue(*ImplicitCast), IsNull());
7116       });
7117 }
7118 
7119 // Check that a callee of a member operator call is modeled as a `PointerValue`.
7120 // Member operator calls are unusual in that their callee is a pointer that
7121 // stems from a `FunctionToPointerDecay`. In calls to non-operator non-static
7122 // member functions, the callee is a `MemberExpr` (which does not have pointer
7123 // type).
7124 // We want to make sure that we produce a pointer value for the callee in this
7125 // specific scenario and that its storage location is durable (for convergence).
7126 TEST(TransferTest, MemberOperatorCallModelsPointerForCallee) {
7127   std::string Code = R"(
7128     struct S {
7129       bool operator!=(S s);
7130     };
7131     void target() {
7132       S s;
7133       (void)(s != s);
7134       (void)(s != s);
7135       // [[p]]
7136     }
7137   )";
7138   runDataflow(
7139       Code,
7140       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
7141          ASTContext &ASTCtx) {
7142         using ast_matchers::selectFirst;
7143         using ast_matchers::match;
7144         using ast_matchers::traverse;
7145         using ast_matchers::cxxOperatorCallExpr;
7146 
7147         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
7148 
7149         auto Matches = match(
7150             traverse(TK_AsIs, cxxOperatorCallExpr().bind("call")), ASTCtx);
7151 
7152         ASSERT_EQ(Matches.size(), 2UL);
7153 
7154         auto *Call1 = Matches[0].getNodeAs<CXXOperatorCallExpr>("call");
7155         auto *Call2 = Matches[1].getNodeAs<CXXOperatorCallExpr>("call");
7156 
7157         ASSERT_THAT(Call1, NotNull());
7158         ASSERT_THAT(Call2, NotNull());
7159 
7160         EXPECT_EQ(cast<ImplicitCastExpr>(Call1->getCallee())->getCastKind(),
7161                   CK_FunctionToPointerDecay);
7162         EXPECT_EQ(cast<ImplicitCastExpr>(Call2->getCallee())->getCastKind(),
7163                   CK_FunctionToPointerDecay);
7164 
7165         auto *Ptr1 = cast<PointerValue>(Env.getValue(*Call1->getCallee()));
7166         auto *Ptr2 = cast<PointerValue>(Env.getValue(*Call2->getCallee()));
7167 
7168         ASSERT_EQ(&Ptr1->getPointeeLoc(), &Ptr2->getPointeeLoc());
7169       });
7170 }
7171 
7172 // Check that fields of anonymous records are modeled.
7173 TEST(TransferTest, AnonymousStruct) {
7174   std::string Code = R"(
7175     struct S {
7176       struct {
7177         bool b;
7178       };
7179     };
7180     void target() {
7181       S s;
7182       s.b = true;
7183       // [[p]]
7184     }
7185   )";
7186   runDataflow(
7187       Code,
7188       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
7189          ASTContext &ASTCtx) {
7190         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
7191         const ValueDecl *SDecl = findValueDecl(ASTCtx, "s");
7192         const ValueDecl *BDecl = findValueDecl(ASTCtx, "b");
7193         const IndirectFieldDecl *IndirectField =
7194             findIndirectFieldDecl(ASTCtx, "b");
7195 
7196         auto *S = cast<RecordStorageLocation>(Env.getStorageLocation(*SDecl));
7197         auto &AnonStruct = *cast<RecordStorageLocation>(
7198             S->getChild(*cast<ValueDecl>(IndirectField->chain().front())));
7199 
7200         auto *B = cast<BoolValue>(getFieldValue(&AnonStruct, *BDecl, Env));
7201         ASSERT_TRUE(Env.proves(B->formula()));
7202       });
7203 }
7204 
7205 TEST(TransferTest, AnonymousStructWithInitializer) {
7206   std::string Code = R"(
7207     struct target {
7208       target() {
7209         (void)0;
7210         // [[p]]
7211       }
7212       struct {
7213         bool b = true;
7214       };
7215     };
7216   )";
7217   runDataflow(
7218       Code,
7219       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
7220          ASTContext &ASTCtx) {
7221         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
7222         const ValueDecl *BDecl = findValueDecl(ASTCtx, "b");
7223         const IndirectFieldDecl *IndirectField =
7224             findIndirectFieldDecl(ASTCtx, "b");
7225 
7226         auto *ThisLoc =
7227             cast<RecordStorageLocation>(Env.getThisPointeeStorageLocation());
7228         auto &AnonStruct = *cast<RecordStorageLocation>(ThisLoc->getChild(
7229             *cast<ValueDecl>(IndirectField->chain().front())));
7230 
7231         auto *B = cast<BoolValue>(getFieldValue(&AnonStruct, *BDecl, Env));
7232         ASSERT_TRUE(Env.proves(B->formula()));
7233       });
7234 }
7235 
7236 TEST(TransferTest, AnonymousStructWithReferenceField) {
7237   std::string Code = R"(
7238     int global_i = 0;
7239     struct target {
7240       target() {
7241         (void)0;
7242         // [[p]]
7243       }
7244       struct {
7245         int &i = global_i;
7246       };
7247     };
7248   )";
7249   runDataflow(
7250       Code,
7251       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
7252          ASTContext &ASTCtx) {
7253         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
7254         const ValueDecl *GlobalIDecl = findValueDecl(ASTCtx, "global_i");
7255         const ValueDecl *IDecl = findValueDecl(ASTCtx, "i");
7256         const IndirectFieldDecl *IndirectField =
7257             findIndirectFieldDecl(ASTCtx, "i");
7258 
7259         auto *ThisLoc =
7260             cast<RecordStorageLocation>(Env.getThisPointeeStorageLocation());
7261         auto &AnonStruct = *cast<RecordStorageLocation>(ThisLoc->getChild(
7262             *cast<ValueDecl>(IndirectField->chain().front())));
7263 
7264         ASSERT_EQ(AnonStruct.getChild(*IDecl),
7265                   Env.getStorageLocation(*GlobalIDecl));
7266       });
7267 }
7268 
7269 TEST(TransferTest, EvaluateBlockWithUnreachablePreds) {
7270   // This is a crash repro.
7271   // `false` block may not have been processed when we try to evaluate the `||`
7272   // after visiting `true`, because it is not necessary (and therefore the edge
7273   // is marked unreachable). Trying to get the analysis state via
7274   // `getEnvironment` for the subexpression still should not crash.
7275   std::string Code = R"(
7276     int target(int i) {
7277       if ((i < 0 && true) || false) {
7278         return 0;
7279       }
7280       return 0;
7281     }
7282   )";
7283   runDataflow(
7284       Code,
7285       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
7286          ASTContext &ASTCtx) {});
7287 }
7288 
7289 TEST(TransferTest, LambdaCaptureByCopy) {
7290   std::string Code = R"(
7291     void target(int Foo, int Bar) {
7292       [Foo]() {
7293         (void)0;
7294         // [[p]]
7295       }();
7296     }
7297   )";
7298   runDataflowOnLambda(
7299       Code,
7300       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
7301          ASTContext &ASTCtx) {
7302         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
7303         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
7304 
7305         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
7306         ASSERT_THAT(FooDecl, NotNull());
7307 
7308         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
7309         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
7310 
7311         const Value *FooVal = Env.getValue(*FooLoc);
7312         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
7313 
7314         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
7315         ASSERT_THAT(BarDecl, NotNull());
7316 
7317         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
7318         EXPECT_THAT(BarLoc, IsNull());
7319       });
7320 }
7321 
7322 TEST(TransferTest, LambdaCaptureByReference) {
7323   std::string Code = R"(
7324     void target(int Foo, int Bar) {
7325       [&Foo]() {
7326         (void)0;
7327         // [[p]]
7328       }();
7329     }
7330   )";
7331   runDataflowOnLambda(
7332       Code,
7333       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
7334          ASTContext &ASTCtx) {
7335         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
7336         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
7337 
7338         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
7339         ASSERT_THAT(FooDecl, NotNull());
7340 
7341         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
7342         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
7343 
7344         const Value *FooVal = Env.getValue(*FooLoc);
7345         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
7346 
7347         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
7348         ASSERT_THAT(BarDecl, NotNull());
7349 
7350         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
7351         EXPECT_THAT(BarLoc, IsNull());
7352       });
7353 }
7354 
7355 TEST(TransferTest, LambdaCaptureWithInitializer) {
7356   std::string Code = R"(
7357     void target(int Bar) {
7358       [Foo=Bar]() {
7359         (void)0;
7360         // [[p]]
7361       }();
7362     }
7363   )";
7364   runDataflowOnLambda(
7365       Code,
7366       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
7367          ASTContext &ASTCtx) {
7368         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
7369         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
7370 
7371         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
7372         ASSERT_THAT(FooDecl, NotNull());
7373 
7374         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
7375         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
7376 
7377         const Value *FooVal = Env.getValue(*FooLoc);
7378         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
7379 
7380         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
7381         ASSERT_THAT(BarDecl, NotNull());
7382 
7383         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
7384         EXPECT_THAT(BarLoc, IsNull());
7385       });
7386 }
7387 
7388 TEST(TransferTest, LambdaCaptureByCopyImplicit) {
7389   std::string Code = R"(
7390     void target(int Foo, int Bar) {
7391       [=]() {
7392         Foo;
7393         // [[p]]
7394       }();
7395     }
7396   )";
7397   runDataflowOnLambda(
7398       Code,
7399       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
7400          ASTContext &ASTCtx) {
7401         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
7402         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
7403 
7404         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
7405         ASSERT_THAT(FooDecl, NotNull());
7406 
7407         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
7408         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
7409 
7410         const Value *FooVal = Env.getValue(*FooLoc);
7411         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
7412 
7413         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
7414         ASSERT_THAT(BarDecl, NotNull());
7415 
7416         // There is no storage location for `Bar` because it isn't used in the
7417         // body of the lambda.
7418         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
7419         EXPECT_THAT(BarLoc, IsNull());
7420       });
7421 }
7422 
7423 TEST(TransferTest, LambdaCaptureByReferenceImplicit) {
7424   std::string Code = R"(
7425     void target(int Foo, int Bar) {
7426       [&]() {
7427         Foo;
7428         // [[p]]
7429       }();
7430     }
7431   )";
7432   runDataflowOnLambda(
7433       Code,
7434       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
7435          ASTContext &ASTCtx) {
7436         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
7437         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
7438 
7439         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
7440         ASSERT_THAT(FooDecl, NotNull());
7441 
7442         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
7443         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
7444 
7445         const Value *FooVal = Env.getValue(*FooLoc);
7446         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
7447 
7448         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
7449         ASSERT_THAT(BarDecl, NotNull());
7450 
7451         // There is no storage location for `Bar` because it isn't used in the
7452         // body of the lambda.
7453         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
7454         EXPECT_THAT(BarLoc, IsNull());
7455       });
7456 }
7457 
7458 TEST(TransferTest, LambdaCaptureThis) {
7459   std::string Code = R"(
7460     struct Bar {
7461       int Foo;
7462 
7463       void target() {
7464         [this]() {
7465           Foo;
7466           // [[p]]
7467         }();
7468       }
7469     };
7470   )";
7471   runDataflowOnLambda(
7472       Code,
7473       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
7474          ASTContext &ASTCtx) {
7475         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
7476         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
7477 
7478         const RecordStorageLocation *ThisPointeeLoc =
7479             Env.getThisPointeeStorageLocation();
7480         ASSERT_THAT(ThisPointeeLoc, NotNull());
7481 
7482         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
7483         ASSERT_THAT(FooDecl, NotNull());
7484 
7485         const StorageLocation *FooLoc = ThisPointeeLoc->getChild(*FooDecl);
7486         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
7487 
7488         const Value *FooVal = Env.getValue(*FooLoc);
7489         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
7490       });
7491 }
7492 
7493 // This test verifies correct modeling of a relational dependency that goes
7494 // through unmodeled functions (the simple `cond()` in this case).
7495 TEST(TransferTest, ConditionalRelation) {
7496   std::string Code = R"(
7497     bool cond();
7498     void target() {
7499        bool a = true;
7500        bool b = true;
7501        if (cond()) {
7502          a = false;
7503          if (cond()) {
7504            b = false;
7505          }
7506        }
7507        (void)0;
7508        // [[p]]
7509     }
7510  )";
7511   runDataflow(
7512       Code,
7513       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
7514          ASTContext &ASTCtx) {
7515         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
7516         auto &A = Env.arena();
7517         auto &VarA = getValueForDecl<BoolValue>(ASTCtx, Env, "a").formula();
7518         auto &VarB = getValueForDecl<BoolValue>(ASTCtx, Env, "b").formula();
7519 
7520         EXPECT_FALSE(Env.allows(A.makeAnd(VarA, A.makeNot(VarB))));
7521       });
7522 }
7523 
7524 // This is a crash repro.
7525 // We used to crash while transferring `S().i` because Clang contained a bug
7526 // causing the AST to be malformed.
7527 TEST(TransferTest, AnonymousUnionMemberExprInTemplate) {
7528   using ast_matchers::functionDecl;
7529   using ast_matchers::hasName;
7530   using ast_matchers::unless;
7531 
7532   std::string Code = R"cc(
7533     struct S {
7534       struct {
7535         int i;
7536       };
7537     };
7538 
7539     template <class>
7540     void target() {
7541         S().i;
7542     }
7543 
7544     template void target<int>();
7545   )cc";
7546   auto Matcher = functionDecl(hasName("target"), unless(isTemplated()));
7547   ASSERT_THAT_ERROR(checkDataflowWithNoopAnalysis(Code, Matcher),
7548                     llvm::Succeeded());
7549 }
7550 
7551 } // namespace
7552