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