xref: /llvm-project/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp (revision 3c6f91e5b671321c95259dabecdbdfe4a6d69ce1)
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, ResultObjectLocationPropagatesThroughConditionalOperator) {
3186   std::string Code = R"(
3187     struct A {
3188       A(int);
3189     };
3190 
3191     void target(bool b) {
3192       A a = b ? A(0) : A(1);
3193       (void)0; // [[p]]
3194     }
3195   )";
3196   using ast_matchers::cxxConstructExpr;
3197   using ast_matchers::equals;
3198   using ast_matchers::hasArgument;
3199   using ast_matchers::integerLiteral;
3200   using ast_matchers::match;
3201   using ast_matchers::selectFirst;
3202   using ast_matchers::traverse;
3203   runDataflow(
3204       Code,
3205       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3206          ASTContext &ASTCtx) {
3207         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3208 
3209         auto *ConstructExpr0 = selectFirst<CXXConstructExpr>(
3210             "construct",
3211             match(cxxConstructExpr(hasArgument(0, integerLiteral(equals(0))))
3212                       .bind("construct"),
3213                   ASTCtx));
3214         auto *ConstructExpr1 = selectFirst<CXXConstructExpr>(
3215             "construct",
3216             match(cxxConstructExpr(hasArgument(0, integerLiteral(equals(1))))
3217                       .bind("construct"),
3218                   ASTCtx));
3219 
3220         auto &ALoc = getLocForDecl<StorageLocation>(ASTCtx, Env, "a");
3221         EXPECT_EQ(&Env.getResultObjectLocation(*ConstructExpr0), &ALoc);
3222         EXPECT_EQ(&Env.getResultObjectLocation(*ConstructExpr1), &ALoc);
3223       });
3224 }
3225 
3226 TEST(TransferTest, StaticCast) {
3227   std::string Code = R"(
3228     void target(int Foo) {
3229       int Bar = static_cast<int>(Foo);
3230       // [[p]]
3231     }
3232   )";
3233   runDataflow(
3234       Code,
3235       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3236          ASTContext &ASTCtx) {
3237         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3238         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3239 
3240         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3241         ASSERT_THAT(FooDecl, NotNull());
3242 
3243         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3244         ASSERT_THAT(BarDecl, NotNull());
3245 
3246         const auto *FooVal = Env.getValue(*FooDecl);
3247         const auto *BarVal = Env.getValue(*BarDecl);
3248         EXPECT_TRUE(isa<IntegerValue>(FooVal));
3249         EXPECT_TRUE(isa<IntegerValue>(BarVal));
3250         EXPECT_EQ(FooVal, BarVal);
3251       });
3252 }
3253 
3254 TEST(TransferTest, IntegralCast) {
3255   std::string Code = R"(
3256     void target(int Foo) {
3257       long Bar = Foo;
3258       // [[p]]
3259     }
3260   )";
3261   runDataflow(
3262       Code,
3263       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3264          ASTContext &ASTCtx) {
3265         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3266         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3267 
3268         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3269         ASSERT_THAT(FooDecl, NotNull());
3270 
3271         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3272         ASSERT_THAT(BarDecl, NotNull());
3273 
3274         const auto *FooVal = Env.getValue(*FooDecl);
3275         const auto *BarVal = Env.getValue(*BarDecl);
3276         EXPECT_TRUE(isa<IntegerValue>(FooVal));
3277         EXPECT_TRUE(isa<IntegerValue>(BarVal));
3278         EXPECT_EQ(FooVal, BarVal);
3279       });
3280 }
3281 
3282 TEST(TransferTest, IntegraltoBooleanCast) {
3283   std::string Code = R"(
3284     void target(int Foo) {
3285       bool Bar = Foo;
3286       // [[p]]
3287     }
3288   )";
3289   runDataflow(
3290       Code,
3291       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3292          ASTContext &ASTCtx) {
3293         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3294         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3295 
3296         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3297         ASSERT_THAT(FooDecl, NotNull());
3298 
3299         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3300         ASSERT_THAT(BarDecl, NotNull());
3301 
3302         const auto *FooVal = Env.getValue(*FooDecl);
3303         const auto *BarVal = Env.getValue(*BarDecl);
3304         EXPECT_TRUE(isa<IntegerValue>(FooVal));
3305         EXPECT_TRUE(isa<BoolValue>(BarVal));
3306       });
3307 }
3308 
3309 TEST(TransferTest, IntegralToBooleanCastFromBool) {
3310   std::string Code = R"(
3311     void target(bool Foo) {
3312       int Zab = Foo;
3313       bool Bar = Zab;
3314       // [[p]]
3315     }
3316   )";
3317   runDataflow(
3318       Code,
3319       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3320          ASTContext &ASTCtx) {
3321         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3322         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3323 
3324         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3325         ASSERT_THAT(FooDecl, NotNull());
3326 
3327         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3328         ASSERT_THAT(BarDecl, NotNull());
3329 
3330         const auto *FooVal = Env.getValue(*FooDecl);
3331         const auto *BarVal = Env.getValue(*BarDecl);
3332         EXPECT_TRUE(isa<BoolValue>(FooVal));
3333         EXPECT_TRUE(isa<BoolValue>(BarVal));
3334         EXPECT_EQ(FooVal, BarVal);
3335       });
3336 }
3337 
3338 TEST(TransferTest, NullToPointerCast) {
3339   std::string Code = R"(
3340     using my_nullptr_t = decltype(nullptr);
3341     struct Baz {};
3342     void target() {
3343       int *FooX = nullptr;
3344       int *FooY = nullptr;
3345       bool **Bar = nullptr;
3346       Baz *Baz = nullptr;
3347       my_nullptr_t Null = 0;
3348       // [[p]]
3349     }
3350   )";
3351   runDataflow(
3352       Code,
3353       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3354          ASTContext &ASTCtx) {
3355         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3356         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3357 
3358         const ValueDecl *FooXDecl = findValueDecl(ASTCtx, "FooX");
3359         ASSERT_THAT(FooXDecl, NotNull());
3360 
3361         const ValueDecl *FooYDecl = findValueDecl(ASTCtx, "FooY");
3362         ASSERT_THAT(FooYDecl, NotNull());
3363 
3364         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3365         ASSERT_THAT(BarDecl, NotNull());
3366 
3367         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3368         ASSERT_THAT(BazDecl, NotNull());
3369 
3370         const ValueDecl *NullDecl = findValueDecl(ASTCtx, "Null");
3371         ASSERT_THAT(NullDecl, NotNull());
3372 
3373         const auto *FooXVal = cast<PointerValue>(Env.getValue(*FooXDecl));
3374         const auto *FooYVal = cast<PointerValue>(Env.getValue(*FooYDecl));
3375         const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl));
3376         const auto *BazVal = cast<PointerValue>(Env.getValue(*BazDecl));
3377         const auto *NullVal = cast<PointerValue>(Env.getValue(*NullDecl));
3378 
3379         EXPECT_EQ(FooXVal, FooYVal);
3380         EXPECT_NE(FooXVal, BarVal);
3381         EXPECT_NE(FooXVal, BazVal);
3382         EXPECT_NE(BarVal, BazVal);
3383 
3384         const StorageLocation &FooPointeeLoc = FooXVal->getPointeeLoc();
3385         EXPECT_TRUE(isa<ScalarStorageLocation>(FooPointeeLoc));
3386         EXPECT_THAT(Env.getValue(FooPointeeLoc), IsNull());
3387 
3388         const StorageLocation &BarPointeeLoc = BarVal->getPointeeLoc();
3389         EXPECT_TRUE(isa<ScalarStorageLocation>(BarPointeeLoc));
3390         EXPECT_THAT(Env.getValue(BarPointeeLoc), IsNull());
3391 
3392         const StorageLocation &BazPointeeLoc = BazVal->getPointeeLoc();
3393         EXPECT_TRUE(isa<RecordStorageLocation>(BazPointeeLoc));
3394         EXPECT_THAT(Env.getValue(BazPointeeLoc), IsNull());
3395 
3396         const StorageLocation &NullPointeeLoc = NullVal->getPointeeLoc();
3397         EXPECT_TRUE(isa<ScalarStorageLocation>(NullPointeeLoc));
3398         EXPECT_THAT(Env.getValue(NullPointeeLoc), IsNull());
3399       });
3400 }
3401 
3402 TEST(TransferTest, PointerToMemberVariable) {
3403   std::string Code = R"(
3404     struct S {
3405       int i;
3406     };
3407     void target() {
3408       int S::*MemberPointer = &S::i;
3409       // [[p]]
3410     }
3411   )";
3412   runDataflow(
3413       Code,
3414       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3415          ASTContext &ASTCtx) {
3416         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3417 
3418         const ValueDecl *MemberPointerDecl =
3419             findValueDecl(ASTCtx, "MemberPointer");
3420         ASSERT_THAT(MemberPointerDecl, NotNull());
3421         ASSERT_THAT(Env.getValue(*MemberPointerDecl), IsNull());
3422       });
3423 }
3424 
3425 TEST(TransferTest, PointerToMemberFunction) {
3426   std::string Code = R"(
3427     struct S {
3428       void Method();
3429     };
3430     void target() {
3431       void (S::*MemberPointer)() = &S::Method;
3432       // [[p]]
3433     }
3434   )";
3435   runDataflow(
3436       Code,
3437       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3438          ASTContext &ASTCtx) {
3439         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3440 
3441         const ValueDecl *MemberPointerDecl =
3442             findValueDecl(ASTCtx, "MemberPointer");
3443         ASSERT_THAT(MemberPointerDecl, NotNull());
3444         ASSERT_THAT(Env.getValue(*MemberPointerDecl), IsNull());
3445       });
3446 }
3447 
3448 TEST(TransferTest, NullToMemberPointerCast) {
3449   std::string Code = R"(
3450     struct Foo {};
3451     void target() {
3452       int Foo::*MemberPointer = nullptr;
3453       // [[p]]
3454     }
3455   )";
3456   runDataflow(
3457       Code,
3458       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3459          ASTContext &ASTCtx) {
3460         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3461         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3462 
3463         const ValueDecl *MemberPointerDecl =
3464             findValueDecl(ASTCtx, "MemberPointer");
3465         ASSERT_THAT(MemberPointerDecl, NotNull());
3466         ASSERT_THAT(Env.getValue(*MemberPointerDecl), IsNull());
3467       });
3468 }
3469 
3470 TEST(TransferTest, AddrOfValue) {
3471   std::string Code = R"(
3472     void target() {
3473       int Foo;
3474       int *Bar = &Foo;
3475       // [[p]]
3476     }
3477   )";
3478   runDataflow(
3479       Code,
3480       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3481          ASTContext &ASTCtx) {
3482         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3483         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3484 
3485         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3486         ASSERT_THAT(FooDecl, NotNull());
3487 
3488         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3489         ASSERT_THAT(BarDecl, NotNull());
3490 
3491         const auto *FooLoc =
3492             cast<ScalarStorageLocation>(Env.getStorageLocation(*FooDecl));
3493         const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl));
3494         EXPECT_EQ(&BarVal->getPointeeLoc(), FooLoc);
3495       });
3496 }
3497 
3498 TEST(TransferTest, AddrOfReference) {
3499   std::string Code = R"(
3500     void target(int *Foo) {
3501       int *Bar = &(*Foo);
3502       // [[p]]
3503     }
3504   )";
3505   runDataflow(
3506       Code,
3507       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3508          ASTContext &ASTCtx) {
3509         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3510         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3511 
3512         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3513         ASSERT_THAT(FooDecl, NotNull());
3514 
3515         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3516         ASSERT_THAT(BarDecl, NotNull());
3517 
3518         const auto *FooVal = cast<PointerValue>(Env.getValue(*FooDecl));
3519         const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl));
3520         EXPECT_EQ(&BarVal->getPointeeLoc(), &FooVal->getPointeeLoc());
3521       });
3522 }
3523 
3524 TEST(TransferTest, CannotAnalyzeFunctionTemplate) {
3525   std::string Code = R"(
3526     template <typename T>
3527     void target() {}
3528   )";
3529   ASSERT_THAT_ERROR(
3530       checkDataflowWithNoopAnalysis(Code),
3531       llvm::FailedWithMessage("Cannot analyze templated declarations"));
3532 }
3533 
3534 TEST(TransferTest, CannotAnalyzeMethodOfClassTemplate) {
3535   std::string Code = R"(
3536     template <typename T>
3537     struct A {
3538       void target() {}
3539     };
3540   )";
3541   ASSERT_THAT_ERROR(
3542       checkDataflowWithNoopAnalysis(Code),
3543       llvm::FailedWithMessage("Cannot analyze templated declarations"));
3544 }
3545 
3546 TEST(TransferTest, VarDeclInitAssignConditionalOperator) {
3547   std::string Code = R"(
3548     struct A {};
3549 
3550     void target(A Foo, A Bar, bool Cond) {
3551       A Baz = Cond ?  Foo : Bar;
3552       /*[[p]]*/
3553     }
3554   )";
3555   runDataflow(
3556       Code,
3557       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3558          ASTContext &ASTCtx) {
3559         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3560         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3561 
3562         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3563         ASSERT_THAT(FooDecl, NotNull());
3564 
3565         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3566         ASSERT_THAT(BarDecl, NotNull());
3567 
3568         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3569         ASSERT_THAT(BazDecl, NotNull());
3570 
3571         const auto *FooVal = cast<RecordValue>(Env.getValue(*FooDecl));
3572         const auto *BarVal = cast<RecordValue>(Env.getValue(*BarDecl));
3573 
3574         const auto *BazVal = dyn_cast<RecordValue>(Env.getValue(*BazDecl));
3575         ASSERT_THAT(BazVal, NotNull());
3576 
3577         EXPECT_NE(BazVal, FooVal);
3578         EXPECT_NE(BazVal, BarVal);
3579       });
3580 }
3581 
3582 TEST(TransferTest, VarDeclInDoWhile) {
3583   std::string Code = R"(
3584     void target(int *Foo) {
3585       do {
3586         int Bar = *Foo;
3587         // [[in_loop]]
3588       } while (false);
3589       (void)0;
3590       // [[after_loop]]
3591     }
3592   )";
3593   runDataflow(
3594       Code,
3595       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3596          ASTContext &ASTCtx) {
3597         const Environment &EnvInLoop =
3598             getEnvironmentAtAnnotation(Results, "in_loop");
3599         const Environment &EnvAfterLoop =
3600             getEnvironmentAtAnnotation(Results, "after_loop");
3601 
3602         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3603         ASSERT_THAT(FooDecl, NotNull());
3604 
3605         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3606         ASSERT_THAT(BarDecl, NotNull());
3607 
3608         const auto *FooVal =
3609             cast<PointerValue>(EnvAfterLoop.getValue(*FooDecl));
3610         const auto *FooPointeeVal =
3611             cast<IntegerValue>(EnvAfterLoop.getValue(FooVal->getPointeeLoc()));
3612 
3613         const auto *BarVal = cast<IntegerValue>(EnvInLoop.getValue(*BarDecl));
3614         EXPECT_EQ(BarVal, FooPointeeVal);
3615 
3616         ASSERT_THAT(EnvAfterLoop.getValue(*BarDecl), IsNull());
3617       });
3618 }
3619 
3620 TEST(TransferTest, UnreachableAfterWhileTrue) {
3621   std::string Code = R"(
3622     void target() {
3623       while (true) {}
3624       (void)0;
3625       /*[[p]]*/
3626     }
3627   )";
3628   runDataflow(
3629       Code,
3630       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3631          ASTContext &ASTCtx) {
3632         // The node after the while-true is pruned because it is trivially
3633         // known to be unreachable.
3634         ASSERT_TRUE(Results.empty());
3635       });
3636 }
3637 
3638 TEST(TransferTest, AggregateInitialization) {
3639   std::string BracesCode = R"(
3640     struct A {
3641       int Foo;
3642     };
3643 
3644     struct B {
3645       int Bar;
3646       A Baz;
3647       int Qux;
3648     };
3649 
3650     void target(int BarArg, int FooArg, int QuxArg) {
3651       B Quux{BarArg, {FooArg}, QuxArg};
3652       B OtherB;
3653       /*[[p]]*/
3654     }
3655   )";
3656   std::string BraceElisionCode = R"(
3657     struct A {
3658       int Foo;
3659     };
3660 
3661     struct B {
3662       int Bar;
3663       A Baz;
3664       int Qux;
3665     };
3666 
3667     void target(int BarArg, int FooArg, int QuxArg) {
3668       B Quux = {BarArg, FooArg, QuxArg};
3669       B OtherB;
3670       /*[[p]]*/
3671     }
3672   )";
3673   for (const std::string &Code : {BracesCode, BraceElisionCode}) {
3674     runDataflow(
3675         Code,
3676         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3677            ASTContext &ASTCtx) {
3678           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3679           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3680 
3681           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3682           ASSERT_THAT(FooDecl, NotNull());
3683 
3684           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3685           ASSERT_THAT(BarDecl, NotNull());
3686 
3687           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3688           ASSERT_THAT(BazDecl, NotNull());
3689 
3690           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
3691           ASSERT_THAT(QuxDecl, NotNull());
3692 
3693           const ValueDecl *FooArgDecl = findValueDecl(ASTCtx, "FooArg");
3694           ASSERT_THAT(FooArgDecl, NotNull());
3695 
3696           const ValueDecl *BarArgDecl = findValueDecl(ASTCtx, "BarArg");
3697           ASSERT_THAT(BarArgDecl, NotNull());
3698 
3699           const ValueDecl *QuxArgDecl = findValueDecl(ASTCtx, "QuxArg");
3700           ASSERT_THAT(QuxArgDecl, NotNull());
3701 
3702           const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux");
3703           ASSERT_THAT(QuuxDecl, NotNull());
3704 
3705           const auto *FooArgVal = cast<IntegerValue>(Env.getValue(*FooArgDecl));
3706           const auto *BarArgVal = cast<IntegerValue>(Env.getValue(*BarArgDecl));
3707           const auto *QuxArgVal = cast<IntegerValue>(Env.getValue(*QuxArgDecl));
3708 
3709           const auto &QuuxLoc =
3710               *cast<RecordStorageLocation>(Env.getStorageLocation(*QuuxDecl));
3711           const auto &BazLoc =
3712               *cast<RecordStorageLocation>(QuuxLoc.getChild(*BazDecl));
3713 
3714           EXPECT_EQ(getFieldValue(&QuuxLoc, *BarDecl, Env), BarArgVal);
3715           EXPECT_EQ(getFieldValue(&BazLoc, *FooDecl, Env), FooArgVal);
3716           EXPECT_EQ(getFieldValue(&QuuxLoc, *QuxDecl, Env), QuxArgVal);
3717 
3718           // Check that fields initialized in an initializer list are always
3719           // modeled in other instances of the same type.
3720           const auto &OtherBLoc =
3721               getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "OtherB");
3722           EXPECT_THAT(OtherBLoc.getChild(*BarDecl), NotNull());
3723           EXPECT_THAT(OtherBLoc.getChild(*BazDecl), NotNull());
3724           EXPECT_THAT(OtherBLoc.getChild(*QuxDecl), NotNull());
3725         });
3726   }
3727 }
3728 
3729 TEST(TransferTest, AggregateInitializationReferenceField) {
3730   std::string Code = R"(
3731     struct S {
3732       int &RefField;
3733     };
3734 
3735     void target(int i) {
3736       S s = { i };
3737       /*[[p]]*/
3738     }
3739   )";
3740   runDataflow(
3741       Code,
3742       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3743          ASTContext &ASTCtx) {
3744         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3745 
3746         const ValueDecl *RefFieldDecl = findValueDecl(ASTCtx, "RefField");
3747 
3748         auto &ILoc = getLocForDecl<StorageLocation>(ASTCtx, Env, "i");
3749         auto &SLoc = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "s");
3750 
3751         EXPECT_EQ(SLoc.getChild(*RefFieldDecl), &ILoc);
3752       });
3753 }
3754 
3755 TEST(TransferTest, AggregateInitialization_NotExplicitlyInitializedField) {
3756   std::string Code = R"(
3757     struct S {
3758       int i1;
3759       int i2;
3760     };
3761 
3762     void target(int i) {
3763       S s = { i };
3764       /*[[p]]*/
3765     }
3766   )";
3767   runDataflow(
3768       Code,
3769       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3770          ASTContext &ASTCtx) {
3771         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3772 
3773         const ValueDecl *I1FieldDecl = findValueDecl(ASTCtx, "i1");
3774         const ValueDecl *I2FieldDecl = findValueDecl(ASTCtx, "i2");
3775 
3776         auto &SLoc = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "s");
3777 
3778         auto &IValue = getValueForDecl<IntegerValue>(ASTCtx, Env, "i");
3779         auto &I1Value =
3780             *cast<IntegerValue>(getFieldValue(&SLoc, *I1FieldDecl, Env));
3781         EXPECT_EQ(&I1Value, &IValue);
3782         auto &I2Value =
3783             *cast<IntegerValue>(getFieldValue(&SLoc, *I2FieldDecl, Env));
3784         EXPECT_NE(&I2Value, &IValue);
3785       });
3786 }
3787 
3788 TEST(TransferTest, AggregateInitializationFunctionPointer) {
3789   // This is a repro for an assertion failure.
3790   // nullptr takes on the type of a const function pointer, but its type was
3791   // asserted to be equal to the *unqualified* type of Field, which no longer
3792   // included the const.
3793   std::string Code = R"(
3794     struct S {
3795       void (*const Field)();
3796     };
3797 
3798     void target() {
3799       S s{nullptr};
3800     }
3801   )";
3802   runDataflow(
3803       Code,
3804       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3805          ASTContext &ASTCtx) {});
3806 }
3807 
3808 TEST(TransferTest, AssignToUnionMember) {
3809   std::string Code = R"(
3810     union A {
3811       int Foo;
3812     };
3813 
3814     void target(int Bar) {
3815       A Baz;
3816       Baz.Foo = Bar;
3817       // [[p]]
3818     }
3819   )";
3820   runDataflow(
3821       Code,
3822       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3823          ASTContext &ASTCtx) {
3824         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3825         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3826 
3827         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3828         ASSERT_THAT(BazDecl, NotNull());
3829         ASSERT_TRUE(BazDecl->getType()->isUnionType());
3830 
3831         auto BazFields = BazDecl->getType()->getAsRecordDecl()->fields();
3832         FieldDecl *FooDecl = nullptr;
3833         for (FieldDecl *Field : BazFields) {
3834           if (Field->getNameAsString() == "Foo") {
3835             FooDecl = Field;
3836           } else {
3837             FAIL() << "Unexpected field: " << Field->getNameAsString();
3838           }
3839         }
3840         ASSERT_THAT(FooDecl, NotNull());
3841 
3842         const auto *BazLoc = dyn_cast_or_null<RecordStorageLocation>(
3843             Env.getStorageLocation(*BazDecl));
3844         ASSERT_THAT(BazLoc, NotNull());
3845         ASSERT_THAT(Env.getValue(*BazLoc), NotNull());
3846 
3847         const auto *FooVal =
3848             cast<IntegerValue>(getFieldValue(BazLoc, *FooDecl, Env));
3849 
3850         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3851         ASSERT_THAT(BarDecl, NotNull());
3852         const auto *BarLoc = Env.getStorageLocation(*BarDecl);
3853         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
3854 
3855         EXPECT_EQ(Env.getValue(*BarLoc), FooVal);
3856       });
3857 }
3858 
3859 TEST(TransferTest, AssignFromBoolLiteral) {
3860   std::string Code = R"(
3861     void target() {
3862       bool Foo = true;
3863       bool Bar = false;
3864       // [[p]]
3865     }
3866   )";
3867   runDataflow(
3868       Code,
3869       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3870          ASTContext &ASTCtx) {
3871         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3872         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3873 
3874         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3875         ASSERT_THAT(FooDecl, NotNull());
3876 
3877         const auto *FooVal =
3878             dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
3879         ASSERT_THAT(FooVal, NotNull());
3880 
3881         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3882         ASSERT_THAT(BarDecl, NotNull());
3883 
3884         const auto *BarVal =
3885             dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
3886         ASSERT_THAT(BarVal, NotNull());
3887 
3888         EXPECT_EQ(FooVal, &Env.getBoolLiteralValue(true));
3889         EXPECT_EQ(BarVal, &Env.getBoolLiteralValue(false));
3890       });
3891 }
3892 
3893 TEST(TransferTest, AssignFromCompositeBoolExpression) {
3894   {
3895     std::string Code = R"(
3896     void target(bool Foo, bool Bar, bool Qux) {
3897       bool Baz = (Foo) && (Bar || Qux);
3898       // [[p]]
3899     }
3900   )";
3901     runDataflow(
3902         Code,
3903         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3904            ASTContext &ASTCtx) {
3905           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3906           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3907 
3908           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3909           ASSERT_THAT(FooDecl, NotNull());
3910 
3911           const auto *FooVal =
3912               dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
3913           ASSERT_THAT(FooVal, NotNull());
3914 
3915           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3916           ASSERT_THAT(BarDecl, NotNull());
3917 
3918           const auto *BarVal =
3919               dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
3920           ASSERT_THAT(BarVal, NotNull());
3921 
3922           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
3923           ASSERT_THAT(QuxDecl, NotNull());
3924 
3925           const auto *QuxVal =
3926               dyn_cast_or_null<BoolValue>(Env.getValue(*QuxDecl));
3927           ASSERT_THAT(QuxVal, NotNull());
3928 
3929           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3930           ASSERT_THAT(BazDecl, NotNull());
3931 
3932           const auto *BazVal =
3933               dyn_cast_or_null<BoolValue>(Env.getValue(*BazDecl));
3934           ASSERT_THAT(BazVal, NotNull());
3935           auto &A = Env.arena();
3936           EXPECT_EQ(&BazVal->formula(),
3937                     &A.makeAnd(FooVal->formula(),
3938                                A.makeOr(BarVal->formula(), QuxVal->formula())));
3939         });
3940   }
3941 
3942   {
3943     std::string Code = R"(
3944     void target(bool Foo, bool Bar, bool Qux) {
3945       bool Baz = (Foo && Qux) || (Bar);
3946       // [[p]]
3947     }
3948   )";
3949     runDataflow(
3950         Code,
3951         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3952            ASTContext &ASTCtx) {
3953           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3954           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3955 
3956           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3957           ASSERT_THAT(FooDecl, NotNull());
3958 
3959           const auto *FooVal =
3960               dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
3961           ASSERT_THAT(FooVal, NotNull());
3962 
3963           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3964           ASSERT_THAT(BarDecl, NotNull());
3965 
3966           const auto *BarVal =
3967               dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
3968           ASSERT_THAT(BarVal, NotNull());
3969 
3970           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
3971           ASSERT_THAT(QuxDecl, NotNull());
3972 
3973           const auto *QuxVal =
3974               dyn_cast_or_null<BoolValue>(Env.getValue(*QuxDecl));
3975           ASSERT_THAT(QuxVal, NotNull());
3976 
3977           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3978           ASSERT_THAT(BazDecl, NotNull());
3979 
3980           const auto *BazVal =
3981               dyn_cast_or_null<BoolValue>(Env.getValue(*BazDecl));
3982           ASSERT_THAT(BazVal, NotNull());
3983           auto &A = Env.arena();
3984           EXPECT_EQ(&BazVal->formula(),
3985                     &A.makeOr(A.makeAnd(FooVal->formula(), QuxVal->formula()),
3986                               BarVal->formula()));
3987         });
3988   }
3989 
3990   {
3991     std::string Code = R"(
3992       void target(bool A, bool B, bool C, bool D) {
3993         bool Foo = ((A && B) && C) && D;
3994         // [[p]]
3995       }
3996     )";
3997     runDataflow(
3998         Code,
3999         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4000            ASTContext &ASTCtx) {
4001           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4002           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4003 
4004           const ValueDecl *ADecl = findValueDecl(ASTCtx, "A");
4005           ASSERT_THAT(ADecl, NotNull());
4006 
4007           const auto *AVal = dyn_cast_or_null<BoolValue>(Env.getValue(*ADecl));
4008           ASSERT_THAT(AVal, NotNull());
4009 
4010           const ValueDecl *BDecl = findValueDecl(ASTCtx, "B");
4011           ASSERT_THAT(BDecl, NotNull());
4012 
4013           const auto *BVal = dyn_cast_or_null<BoolValue>(Env.getValue(*BDecl));
4014           ASSERT_THAT(BVal, NotNull());
4015 
4016           const ValueDecl *CDecl = findValueDecl(ASTCtx, "C");
4017           ASSERT_THAT(CDecl, NotNull());
4018 
4019           const auto *CVal = dyn_cast_or_null<BoolValue>(Env.getValue(*CDecl));
4020           ASSERT_THAT(CVal, NotNull());
4021 
4022           const ValueDecl *DDecl = findValueDecl(ASTCtx, "D");
4023           ASSERT_THAT(DDecl, NotNull());
4024 
4025           const auto *DVal = dyn_cast_or_null<BoolValue>(Env.getValue(*DDecl));
4026           ASSERT_THAT(DVal, NotNull());
4027 
4028           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4029           ASSERT_THAT(FooDecl, NotNull());
4030 
4031           const auto *FooVal =
4032               dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
4033           ASSERT_THAT(FooVal, NotNull());
4034           auto &A = Env.arena();
4035           EXPECT_EQ(
4036               &FooVal->formula(),
4037               &A.makeAnd(A.makeAnd(A.makeAnd(AVal->formula(), BVal->formula()),
4038                                    CVal->formula()),
4039                          DVal->formula()));
4040         });
4041   }
4042 }
4043 
4044 TEST(TransferTest, AssignFromBoolNegation) {
4045   std::string Code = R"(
4046     void target() {
4047       bool Foo = true;
4048       bool Bar = !(Foo);
4049       // [[p]]
4050     }
4051   )";
4052   runDataflow(
4053       Code,
4054       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4055          ASTContext &ASTCtx) {
4056         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4057         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4058 
4059         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4060         ASSERT_THAT(FooDecl, NotNull());
4061 
4062         const auto *FooVal =
4063             dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
4064         ASSERT_THAT(FooVal, NotNull());
4065 
4066         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4067         ASSERT_THAT(BarDecl, NotNull());
4068 
4069         const auto *BarVal =
4070             dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
4071         ASSERT_THAT(BarVal, NotNull());
4072         auto &A = Env.arena();
4073         EXPECT_EQ(&BarVal->formula(), &A.makeNot(FooVal->formula()));
4074       });
4075 }
4076 
4077 TEST(TransferTest, BuiltinExpect) {
4078   std::string Code = R"(
4079     void target(long Foo) {
4080       long Bar = __builtin_expect(Foo, true);
4081       /*[[p]]*/
4082     }
4083   )";
4084   runDataflow(
4085       Code,
4086       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4087          ASTContext &ASTCtx) {
4088         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4089         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4090 
4091         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4092         ASSERT_THAT(FooDecl, NotNull());
4093 
4094         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4095         ASSERT_THAT(BarDecl, NotNull());
4096 
4097         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
4098       });
4099 }
4100 
4101 // `__builtin_expect` takes and returns a `long` argument, so other types
4102 // involve casts. This verifies that we identify the input and output in that
4103 // case.
4104 TEST(TransferTest, BuiltinExpectBoolArg) {
4105   std::string Code = R"(
4106     void target(bool Foo) {
4107       bool Bar = __builtin_expect(Foo, true);
4108       /*[[p]]*/
4109     }
4110   )";
4111   runDataflow(
4112       Code,
4113       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4114          ASTContext &ASTCtx) {
4115         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4116         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4117 
4118         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4119         ASSERT_THAT(FooDecl, NotNull());
4120 
4121         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4122         ASSERT_THAT(BarDecl, NotNull());
4123 
4124         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
4125       });
4126 }
4127 
4128 TEST(TransferTest, BuiltinUnreachable) {
4129   std::string Code = R"(
4130     void target(bool Foo) {
4131       bool Bar = false;
4132       if (Foo)
4133         Bar = Foo;
4134       else
4135         __builtin_unreachable();
4136       (void)0;
4137       /*[[p]]*/
4138     }
4139   )";
4140   runDataflow(
4141       Code,
4142       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4143          ASTContext &ASTCtx) {
4144         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4145         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4146 
4147         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4148         ASSERT_THAT(FooDecl, NotNull());
4149 
4150         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4151         ASSERT_THAT(BarDecl, NotNull());
4152 
4153         // `__builtin_unreachable` promises that the code is
4154         // unreachable, so the compiler treats the "then" branch as the
4155         // only possible predecessor of this statement.
4156         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
4157       });
4158 }
4159 
4160 TEST(TransferTest, BuiltinTrap) {
4161   std::string Code = R"(
4162     void target(bool Foo) {
4163       bool Bar = false;
4164       if (Foo)
4165         Bar = Foo;
4166       else
4167         __builtin_trap();
4168       (void)0;
4169       /*[[p]]*/
4170     }
4171   )";
4172   runDataflow(
4173       Code,
4174       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4175          ASTContext &ASTCtx) {
4176         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4177         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4178 
4179         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4180         ASSERT_THAT(FooDecl, NotNull());
4181 
4182         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4183         ASSERT_THAT(BarDecl, NotNull());
4184 
4185         // `__builtin_trap` ensures program termination, so only the
4186         // "then" branch is a predecessor of this statement.
4187         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
4188       });
4189 }
4190 
4191 TEST(TransferTest, BuiltinDebugTrap) {
4192   std::string Code = R"(
4193     void target(bool Foo) {
4194       bool Bar = false;
4195       if (Foo)
4196         Bar = Foo;
4197       else
4198         __builtin_debugtrap();
4199       (void)0;
4200       /*[[p]]*/
4201     }
4202   )";
4203   runDataflow(
4204       Code,
4205       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4206          ASTContext &ASTCtx) {
4207         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4208         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4209 
4210         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4211         ASSERT_THAT(FooDecl, NotNull());
4212 
4213         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4214         ASSERT_THAT(BarDecl, NotNull());
4215 
4216         // `__builtin_debugtrap` doesn't ensure program termination.
4217         EXPECT_NE(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
4218       });
4219 }
4220 
4221 TEST(TransferTest, StaticIntSingleVarDecl) {
4222   std::string Code = R"(
4223     void target() {
4224       static int Foo;
4225       // [[p]]
4226     }
4227   )";
4228   runDataflow(
4229       Code,
4230       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4231          ASTContext &ASTCtx) {
4232         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4233         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4234 
4235         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4236         ASSERT_THAT(FooDecl, NotNull());
4237 
4238         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
4239         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
4240 
4241         const Value *FooVal = Env.getValue(*FooLoc);
4242         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
4243       });
4244 }
4245 
4246 TEST(TransferTest, StaticIntGroupVarDecl) {
4247   std::string Code = R"(
4248     void target() {
4249       static int Foo, Bar;
4250       (void)0;
4251       // [[p]]
4252     }
4253   )";
4254   runDataflow(
4255       Code,
4256       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4257          ASTContext &ASTCtx) {
4258         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4259         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4260 
4261         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4262         ASSERT_THAT(FooDecl, NotNull());
4263 
4264         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4265         ASSERT_THAT(BarDecl, NotNull());
4266 
4267         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
4268         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
4269 
4270         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
4271         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
4272 
4273         const Value *FooVal = Env.getValue(*FooLoc);
4274         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
4275 
4276         const Value *BarVal = Env.getValue(*BarLoc);
4277         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
4278 
4279         EXPECT_NE(FooVal, BarVal);
4280       });
4281 }
4282 
4283 TEST(TransferTest, GlobalIntVarDecl) {
4284   std::string Code = R"(
4285     static int Foo;
4286 
4287     void target() {
4288       int Bar = Foo;
4289       int Baz = Foo;
4290       // [[p]]
4291     }
4292   )";
4293   runDataflow(
4294       Code,
4295       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4296          ASTContext &ASTCtx) {
4297         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4298         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4299 
4300         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4301         ASSERT_THAT(BarDecl, NotNull());
4302 
4303         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4304         ASSERT_THAT(BazDecl, NotNull());
4305 
4306         const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
4307         const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl));
4308         EXPECT_EQ(BarVal, BazVal);
4309       });
4310 }
4311 
4312 TEST(TransferTest, StaticMemberIntVarDecl) {
4313   std::string Code = R"(
4314     struct A {
4315       static int Foo;
4316     };
4317 
4318     void target(A a) {
4319       int Bar = a.Foo;
4320       int Baz = a.Foo;
4321       // [[p]]
4322     }
4323   )";
4324   runDataflow(
4325       Code,
4326       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4327          ASTContext &ASTCtx) {
4328         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4329         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4330 
4331         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4332         ASSERT_THAT(BarDecl, NotNull());
4333 
4334         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4335         ASSERT_THAT(BazDecl, NotNull());
4336 
4337         const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
4338         const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl));
4339         EXPECT_EQ(BarVal, BazVal);
4340       });
4341 }
4342 
4343 TEST(TransferTest, StaticMemberRefVarDecl) {
4344   std::string Code = R"(
4345     struct A {
4346       static int &Foo;
4347     };
4348 
4349     void target(A a) {
4350       int Bar = a.Foo;
4351       int Baz = a.Foo;
4352       // [[p]]
4353     }
4354   )";
4355   runDataflow(
4356       Code,
4357       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4358          ASTContext &ASTCtx) {
4359         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4360         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4361 
4362         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4363         ASSERT_THAT(BarDecl, NotNull());
4364 
4365         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4366         ASSERT_THAT(BazDecl, NotNull());
4367 
4368         const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
4369         const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl));
4370         EXPECT_EQ(BarVal, BazVal);
4371       });
4372 }
4373 
4374 TEST(TransferTest, AssignMemberBeforeCopy) {
4375   std::string Code = R"(
4376     struct A {
4377       int Foo;
4378     };
4379 
4380     void target() {
4381       A A1;
4382       A A2;
4383       int Bar;
4384       A1.Foo = Bar;
4385       A2 = A1;
4386       // [[p]]
4387     }
4388   )";
4389   runDataflow(
4390       Code,
4391       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4392          ASTContext &ASTCtx) {
4393         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4394         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4395 
4396         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4397         ASSERT_THAT(FooDecl, NotNull());
4398 
4399         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4400         ASSERT_THAT(BarDecl, NotNull());
4401 
4402         const ValueDecl *A1Decl = findValueDecl(ASTCtx, "A1");
4403         ASSERT_THAT(A1Decl, NotNull());
4404 
4405         const ValueDecl *A2Decl = findValueDecl(ASTCtx, "A2");
4406         ASSERT_THAT(A2Decl, NotNull());
4407 
4408         const auto *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
4409 
4410         const auto &A2Loc =
4411             *cast<RecordStorageLocation>(Env.getStorageLocation(*A2Decl));
4412         EXPECT_EQ(getFieldValue(&A2Loc, *FooDecl, Env), BarVal);
4413       });
4414 }
4415 
4416 TEST(TransferTest, BooleanEquality) {
4417   std::string Code = R"(
4418     void target(bool Bar) {
4419       bool Foo = true;
4420       if (Bar == Foo) {
4421         (void)0;
4422         /*[[p-then]]*/
4423       } else {
4424         (void)0;
4425         /*[[p-else]]*/
4426       }
4427     }
4428   )";
4429   runDataflow(
4430       Code,
4431       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4432          ASTContext &ASTCtx) {
4433         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-then", "p-else"));
4434         const Environment &EnvThen =
4435             getEnvironmentAtAnnotation(Results, "p-then");
4436         const Environment &EnvElse =
4437             getEnvironmentAtAnnotation(Results, "p-else");
4438 
4439         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4440         ASSERT_THAT(BarDecl, NotNull());
4441 
4442         auto &BarValThen = getFormula(*BarDecl, EnvThen);
4443         EXPECT_TRUE(EnvThen.proves(BarValThen));
4444 
4445         auto &BarValElse = getFormula(*BarDecl, EnvElse);
4446         EXPECT_TRUE(EnvElse.proves(EnvElse.arena().makeNot(BarValElse)));
4447       });
4448 }
4449 
4450 TEST(TransferTest, BooleanInequality) {
4451   std::string Code = R"(
4452     void target(bool Bar) {
4453       bool Foo = true;
4454       if (Bar != Foo) {
4455         (void)0;
4456         /*[[p-then]]*/
4457       } else {
4458         (void)0;
4459         /*[[p-else]]*/
4460       }
4461     }
4462   )";
4463   runDataflow(
4464       Code,
4465       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4466          ASTContext &ASTCtx) {
4467         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-then", "p-else"));
4468         const Environment &EnvThen =
4469             getEnvironmentAtAnnotation(Results, "p-then");
4470         const Environment &EnvElse =
4471             getEnvironmentAtAnnotation(Results, "p-else");
4472 
4473         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4474         ASSERT_THAT(BarDecl, NotNull());
4475 
4476         auto &BarValThen = getFormula(*BarDecl, EnvThen);
4477         EXPECT_TRUE(EnvThen.proves(EnvThen.arena().makeNot(BarValThen)));
4478 
4479         auto &BarValElse = getFormula(*BarDecl, EnvElse);
4480         EXPECT_TRUE(EnvElse.proves(BarValElse));
4481       });
4482 }
4483 
4484 TEST(TransferTest, IntegerLiteralEquality) {
4485   std::string Code = R"(
4486     void target() {
4487       bool equal = (42 == 42);
4488       // [[p]]
4489     }
4490   )";
4491   runDataflow(
4492       Code,
4493       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4494          ASTContext &ASTCtx) {
4495         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4496 
4497         auto &Equal =
4498             getValueForDecl<BoolValue>(ASTCtx, Env, "equal").formula();
4499         EXPECT_TRUE(Env.proves(Equal));
4500       });
4501 }
4502 
4503 TEST(TransferTest, CorrelatedBranches) {
4504   std::string Code = R"(
4505     void target(bool B, bool C) {
4506       if (B) {
4507         return;
4508       }
4509       (void)0;
4510       /*[[p0]]*/
4511       if (C) {
4512         B = true;
4513         /*[[p1]]*/
4514       }
4515       if (B) {
4516         (void)0;
4517         /*[[p2]]*/
4518       }
4519     }
4520   )";
4521   runDataflow(
4522       Code,
4523       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4524          ASTContext &ASTCtx) {
4525         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p0", "p1", "p2"));
4526 
4527         const ValueDecl *CDecl = findValueDecl(ASTCtx, "C");
4528         ASSERT_THAT(CDecl, NotNull());
4529 
4530         {
4531           const Environment &Env = getEnvironmentAtAnnotation(Results, "p0");
4532           const ValueDecl *BDecl = findValueDecl(ASTCtx, "B");
4533           ASSERT_THAT(BDecl, NotNull());
4534           auto &BVal = getFormula(*BDecl, Env);
4535 
4536           EXPECT_TRUE(Env.proves(Env.arena().makeNot(BVal)));
4537         }
4538 
4539         {
4540           const Environment &Env = getEnvironmentAtAnnotation(Results, "p1");
4541           auto &CVal = getFormula(*CDecl, Env);
4542           EXPECT_TRUE(Env.proves(CVal));
4543         }
4544 
4545         {
4546           const Environment &Env = getEnvironmentAtAnnotation(Results, "p2");
4547           auto &CVal = getFormula(*CDecl, Env);
4548           EXPECT_TRUE(Env.proves(CVal));
4549         }
4550       });
4551 }
4552 
4553 TEST(TransferTest, LoopWithAssignmentConverges) {
4554   std::string Code = R"(
4555     bool foo();
4556 
4557     void target() {
4558        do {
4559         bool Bar = foo();
4560         if (Bar) break;
4561         (void)Bar;
4562         /*[[p]]*/
4563       } while (true);
4564     }
4565   )";
4566   // The key property that we are verifying is implicit in `runDataflow` --
4567   // namely, that the analysis succeeds, rather than hitting the maximum number
4568   // of iterations.
4569   runDataflow(
4570       Code,
4571       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4572          ASTContext &ASTCtx) {
4573         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4574         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4575 
4576         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4577         ASSERT_THAT(BarDecl, NotNull());
4578 
4579         auto &BarVal = getFormula(*BarDecl, Env);
4580         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BarVal)));
4581       });
4582 }
4583 
4584 TEST(TransferTest, LoopWithStagedAssignments) {
4585   std::string Code = R"(
4586     bool foo();
4587 
4588     void target() {
4589       bool Bar = false;
4590       bool Err = false;
4591       while (foo()) {
4592         if (Bar)
4593           Err = true;
4594         Bar = true;
4595         /*[[p]]*/
4596       }
4597     }
4598   )";
4599   runDataflow(
4600       Code,
4601       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4602          ASTContext &ASTCtx) {
4603         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4604         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4605 
4606         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4607         ASSERT_THAT(BarDecl, NotNull());
4608         const ValueDecl *ErrDecl = findValueDecl(ASTCtx, "Err");
4609         ASSERT_THAT(ErrDecl, NotNull());
4610 
4611         auto &BarVal = getFormula(*BarDecl, Env);
4612         auto &ErrVal = getFormula(*ErrDecl, Env);
4613         EXPECT_TRUE(Env.proves(BarVal));
4614         // An unsound analysis, for example only evaluating the loop once, can
4615         // conclude that `Err` is false. So, we test that this conclusion is not
4616         // reached.
4617         EXPECT_FALSE(Env.proves(Env.arena().makeNot(ErrVal)));
4618       });
4619 }
4620 
4621 TEST(TransferTest, LoopWithReferenceAssignmentConverges) {
4622   std::string Code = R"(
4623     bool &foo();
4624 
4625     void target() {
4626        do {
4627         bool& Bar = foo();
4628         if (Bar) break;
4629         (void)Bar;
4630         /*[[p]]*/
4631       } while (true);
4632     }
4633   )";
4634   // The key property that we are verifying is that the analysis succeeds,
4635   // rather than hitting the maximum number of iterations.
4636   runDataflow(
4637       Code,
4638       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4639          ASTContext &ASTCtx) {
4640         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4641         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4642 
4643         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4644         ASSERT_THAT(BarDecl, NotNull());
4645 
4646         auto &BarVal = getFormula(*BarDecl, Env);
4647         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BarVal)));
4648       });
4649 }
4650 
4651 TEST(TransferTest, LoopWithStructReferenceAssignmentConverges) {
4652   std::string Code = R"(
4653     struct Lookup {
4654       int x;
4655     };
4656 
4657     void target(Lookup val, bool b) {
4658       const Lookup* l = nullptr;
4659       while (b) {
4660         l = &val;
4661         /*[[p-inner]]*/
4662       }
4663       (void)0;
4664       /*[[p-outer]]*/
4665     }
4666   )";
4667   // The key property that we are verifying is implicit in `runDataflow` --
4668   // namely, that the analysis succeeds, rather than hitting the maximum number
4669   // of iterations.
4670   runDataflow(
4671       Code,
4672       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4673          ASTContext &ASTCtx) {
4674         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-inner", "p-outer"));
4675         const Environment &InnerEnv =
4676             getEnvironmentAtAnnotation(Results, "p-inner");
4677         const Environment &OuterEnv =
4678             getEnvironmentAtAnnotation(Results, "p-outer");
4679 
4680         const ValueDecl *ValDecl = findValueDecl(ASTCtx, "val");
4681         ASSERT_THAT(ValDecl, NotNull());
4682 
4683         const ValueDecl *LDecl = findValueDecl(ASTCtx, "l");
4684         ASSERT_THAT(LDecl, NotNull());
4685 
4686         // Inner.
4687         auto *LVal = dyn_cast<PointerValue>(InnerEnv.getValue(*LDecl));
4688         ASSERT_THAT(LVal, NotNull());
4689 
4690         EXPECT_EQ(&LVal->getPointeeLoc(),
4691                   InnerEnv.getStorageLocation(*ValDecl));
4692 
4693         // Outer.
4694         LVal = dyn_cast<PointerValue>(OuterEnv.getValue(*LDecl));
4695         ASSERT_THAT(LVal, NotNull());
4696 
4697         // The loop body may not have been executed, so we should not conclude
4698         // that `l` points to `val`.
4699         EXPECT_NE(&LVal->getPointeeLoc(),
4700                   OuterEnv.getStorageLocation(*ValDecl));
4701       });
4702 }
4703 
4704 TEST(TransferTest, LoopDereferencingChangingPointerConverges) {
4705   std::string Code = R"cc(
4706     bool some_condition();
4707 
4708     void target(int i1, int i2) {
4709       int *p = &i1;
4710       while (true) {
4711         (void)*p;
4712         if (some_condition())
4713           p = &i1;
4714         else
4715           p = &i2;
4716       }
4717     }
4718   )cc";
4719   ASSERT_THAT_ERROR(checkDataflowWithNoopAnalysis(Code), llvm::Succeeded());
4720 }
4721 
4722 TEST(TransferTest, LoopDereferencingChangingRecordPointerConverges) {
4723   std::string Code = R"cc(
4724     struct Lookup {
4725       int x;
4726     };
4727 
4728     bool some_condition();
4729 
4730     void target(Lookup l1, Lookup l2) {
4731       Lookup *l = &l1;
4732       while (true) {
4733         (void)l->x;
4734         if (some_condition())
4735           l = &l1;
4736         else
4737           l = &l2;
4738       }
4739     }
4740   )cc";
4741   ASSERT_THAT_ERROR(checkDataflowWithNoopAnalysis(Code), llvm::Succeeded());
4742 }
4743 
4744 TEST(TransferTest, LoopWithShortCircuitedConditionConverges) {
4745   std::string Code = R"cc(
4746     bool foo();
4747 
4748     void target() {
4749       bool c = false;
4750       while (foo() || foo()) {
4751         c = true;
4752       }
4753     }
4754   )cc";
4755   ASSERT_THAT_ERROR(checkDataflowWithNoopAnalysis(Code), llvm::Succeeded());
4756 }
4757 
4758 TEST(TransferTest, LoopCanProveInvariantForBoolean) {
4759   // Check that we can prove `b` is always false in the loop.
4760   // This test exercises the logic in `widenDistinctValues()` that preserves
4761   // information if the boolean can be proved to be either true or false in both
4762   // the previous and current iteration.
4763   std::string Code = R"cc(
4764     int return_int();
4765     void target() {
4766       bool b = return_int() == 0;
4767       if (b) return;
4768       while (true) {
4769         b;
4770         // [[p]]
4771         b = return_int() == 0;
4772         if (b) return;
4773       }
4774     }
4775   )cc";
4776   runDataflow(
4777       Code,
4778       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4779          ASTContext &ASTCtx) {
4780         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4781         auto &BVal = getValueForDecl<BoolValue>(ASTCtx, Env, "b");
4782         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BVal.formula())));
4783       });
4784 }
4785 
4786 TEST(TransferTest, DoesNotCrashOnUnionThisExpr) {
4787   std::string Code = R"cc(
4788     union Union {
4789       int A;
4790       float B;
4791     };
4792 
4793     void foo() {
4794       Union A;
4795       Union B;
4796       A = B;
4797     }
4798   )cc";
4799   // This is a crash regression test when calling the transfer function on a
4800   // `CXXThisExpr` that refers to a union.
4801   runDataflow(
4802       Code,
4803       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &,
4804          ASTContext &) {},
4805       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator=");
4806 }
4807 
4808 TEST(TransferTest, DoesNotCrashOnNullChildren) {
4809   std::string Code = (CoroutineLibrary + R"cc(
4810     task target() noexcept {
4811       co_return;
4812     }
4813   )cc")
4814                          .str();
4815   // This is a crash regression test when calling `AdornedCFG::build` on a
4816   // statement (in this case, the `CoroutineBodyStmt`) with null children.
4817   runDataflow(
4818       Code,
4819       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &,
4820          ASTContext &) {},
4821       LangStandard::lang_cxx20, /*ApplyBuiltinTransfer=*/true);
4822 }
4823 
4824 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToRefs) {
4825   std::string Code = R"(
4826     struct A {
4827       int Foo;
4828       int Bar;
4829     };
4830 
4831     void target() {
4832       int Qux;
4833       A Baz;
4834       Baz.Foo = Qux;
4835       auto &FooRef = Baz.Foo;
4836       auto &BarRef = Baz.Bar;
4837       auto &[BoundFooRef, BoundBarRef] = Baz;
4838       // [[p]]
4839     }
4840   )";
4841   runDataflow(
4842       Code,
4843       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4844          ASTContext &ASTCtx) {
4845         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4846         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4847 
4848         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
4849         ASSERT_THAT(FooRefDecl, NotNull());
4850 
4851         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
4852         ASSERT_THAT(BarRefDecl, NotNull());
4853 
4854         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
4855         ASSERT_THAT(QuxDecl, NotNull());
4856 
4857         const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef");
4858         ASSERT_THAT(BoundFooRefDecl, NotNull());
4859 
4860         const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef");
4861         ASSERT_THAT(BoundBarRefDecl, NotNull());
4862 
4863         const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl);
4864         ASSERT_THAT(FooRefLoc, NotNull());
4865 
4866         const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl);
4867         ASSERT_THAT(BarRefLoc, NotNull());
4868 
4869         const Value *QuxVal = Env.getValue(*QuxDecl);
4870         ASSERT_THAT(QuxVal, NotNull());
4871 
4872         const StorageLocation *BoundFooRefLoc =
4873             Env.getStorageLocation(*BoundFooRefDecl);
4874         EXPECT_EQ(BoundFooRefLoc, FooRefLoc);
4875 
4876         const StorageLocation *BoundBarRefLoc =
4877             Env.getStorageLocation(*BoundBarRefDecl);
4878         EXPECT_EQ(BoundBarRefLoc, BarRefLoc);
4879 
4880         EXPECT_EQ(Env.getValue(*BoundFooRefDecl), QuxVal);
4881       });
4882 }
4883 
4884 TEST(TransferTest, StructuredBindingAssignFromStructRefMembersToRefs) {
4885   std::string Code = R"(
4886     struct A {
4887       int &Foo;
4888       int &Bar;
4889     };
4890 
4891     void target(A Baz) {
4892       int Qux;
4893       Baz.Foo = Qux;
4894       auto &FooRef = Baz.Foo;
4895       auto &BarRef = Baz.Bar;
4896       auto &[BoundFooRef, BoundBarRef] = Baz;
4897       // [[p]]
4898     }
4899   )";
4900   runDataflow(
4901       Code,
4902       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4903          ASTContext &ASTCtx) {
4904         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4905         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4906 
4907         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
4908         ASSERT_THAT(FooRefDecl, NotNull());
4909 
4910         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
4911         ASSERT_THAT(BarRefDecl, NotNull());
4912 
4913         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
4914         ASSERT_THAT(QuxDecl, NotNull());
4915 
4916         const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef");
4917         ASSERT_THAT(BoundFooRefDecl, NotNull());
4918 
4919         const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef");
4920         ASSERT_THAT(BoundBarRefDecl, NotNull());
4921 
4922         const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl);
4923         ASSERT_THAT(FooRefLoc, NotNull());
4924 
4925         const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl);
4926         ASSERT_THAT(BarRefLoc, NotNull());
4927 
4928         const Value *QuxVal = Env.getValue(*QuxDecl);
4929         ASSERT_THAT(QuxVal, NotNull());
4930 
4931         const StorageLocation *BoundFooRefLoc =
4932             Env.getStorageLocation(*BoundFooRefDecl);
4933         EXPECT_EQ(BoundFooRefLoc, FooRefLoc);
4934 
4935         const StorageLocation *BoundBarRefLoc =
4936             Env.getStorageLocation(*BoundBarRefDecl);
4937         EXPECT_EQ(BoundBarRefLoc, BarRefLoc);
4938 
4939         EXPECT_EQ(Env.getValue(*BoundFooRefDecl), QuxVal);
4940       });
4941 }
4942 
4943 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToInts) {
4944   std::string Code = R"(
4945     struct A {
4946       int Foo;
4947       int Bar;
4948     };
4949 
4950     void target() {
4951       int Qux;
4952       A Baz;
4953       Baz.Foo = Qux;
4954       auto &FooRef = Baz.Foo;
4955       auto &BarRef = Baz.Bar;
4956       auto [BoundFoo, BoundBar] = Baz;
4957       // [[p]]
4958     }
4959   )";
4960   runDataflow(
4961       Code,
4962       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4963          ASTContext &ASTCtx) {
4964         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4965         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4966 
4967         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
4968         ASSERT_THAT(FooRefDecl, NotNull());
4969 
4970         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
4971         ASSERT_THAT(BarRefDecl, NotNull());
4972 
4973         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
4974         ASSERT_THAT(BoundFooDecl, NotNull());
4975 
4976         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
4977         ASSERT_THAT(BoundBarDecl, NotNull());
4978 
4979         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
4980         ASSERT_THAT(QuxDecl, NotNull());
4981 
4982         const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl);
4983         ASSERT_THAT(FooRefLoc, NotNull());
4984 
4985         const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl);
4986         ASSERT_THAT(BarRefLoc, NotNull());
4987 
4988         const Value *QuxVal = Env.getValue(*QuxDecl);
4989         ASSERT_THAT(QuxVal, NotNull());
4990 
4991         const StorageLocation *BoundFooLoc =
4992             Env.getStorageLocation(*BoundFooDecl);
4993         EXPECT_NE(BoundFooLoc, FooRefLoc);
4994 
4995         const StorageLocation *BoundBarLoc =
4996             Env.getStorageLocation(*BoundBarDecl);
4997         EXPECT_NE(BoundBarLoc, BarRefLoc);
4998 
4999         EXPECT_EQ(Env.getValue(*BoundFooDecl), QuxVal);
5000       });
5001 }
5002 
5003 TEST(TransferTest, StructuredBindingAssignFromTupleLikeType) {
5004   std::string Code = R"(
5005     namespace std {
5006     using size_t = int;
5007     template <class> struct tuple_size;
5008     template <std::size_t, class> struct tuple_element;
5009     template <class...> class tuple;
5010 
5011     namespace {
5012     template <class T, T v>
5013     struct size_helper { static const T value = v; };
5014     } // namespace
5015 
5016     template <class... T>
5017     struct tuple_size<tuple<T...>> : size_helper<std::size_t, sizeof...(T)> {};
5018 
5019     template <std::size_t I, class... T>
5020     struct tuple_element<I, tuple<T...>> {
5021       using type =  __type_pack_element<I, T...>;
5022     };
5023 
5024     template <class...> class tuple {};
5025 
5026     template <std::size_t I, class... T>
5027     typename tuple_element<I, tuple<T...>>::type get(tuple<T...>);
5028     } // namespace std
5029 
5030     std::tuple<bool, int> makeTuple();
5031 
5032     void target(bool B) {
5033       auto [BoundFoo, BoundBar] = makeTuple();
5034       bool Baz;
5035       // Include if-then-else to test interaction of `BindingDecl` with join.
5036       if (B) {
5037         Baz = BoundFoo;
5038         (void)BoundBar;
5039         // [[p1]]
5040       } else {
5041         Baz = BoundFoo;
5042       }
5043       (void)0;
5044       // [[p2]]
5045     }
5046   )";
5047   runDataflow(
5048       Code,
5049       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5050          ASTContext &ASTCtx) {
5051         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
5052         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
5053 
5054         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
5055         ASSERT_THAT(BoundFooDecl, NotNull());
5056 
5057         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
5058         ASSERT_THAT(BoundBarDecl, NotNull());
5059 
5060         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
5061         ASSERT_THAT(BazDecl, NotNull());
5062 
5063         // BindingDecls always map to references -- either lvalue or rvalue, so
5064         // we still need to skip here.
5065         const Value *BoundFooValue = Env1.getValue(*BoundFooDecl);
5066         ASSERT_THAT(BoundFooValue, NotNull());
5067         EXPECT_TRUE(isa<BoolValue>(BoundFooValue));
5068 
5069         const Value *BoundBarValue = Env1.getValue(*BoundBarDecl);
5070         ASSERT_THAT(BoundBarValue, NotNull());
5071         EXPECT_TRUE(isa<IntegerValue>(BoundBarValue));
5072 
5073         // Test that a `DeclRefExpr` to a `BindingDecl` works as expected.
5074         EXPECT_EQ(Env1.getValue(*BazDecl), BoundFooValue);
5075 
5076         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
5077 
5078         // Test that `BoundFooDecl` retains the value we expect, after the join.
5079         BoundFooValue = Env2.getValue(*BoundFooDecl);
5080         EXPECT_EQ(Env2.getValue(*BazDecl), BoundFooValue);
5081       });
5082 }
5083 
5084 TEST(TransferTest, StructuredBindingAssignRefFromTupleLikeType) {
5085   std::string Code = R"(
5086     namespace std {
5087     using size_t = int;
5088     template <class> struct tuple_size;
5089     template <std::size_t, class> struct tuple_element;
5090     template <class...> class tuple;
5091 
5092     namespace {
5093     template <class T, T v>
5094     struct size_helper { static const T value = v; };
5095     } // namespace
5096 
5097     template <class... T>
5098     struct tuple_size<tuple<T...>> : size_helper<std::size_t, sizeof...(T)> {};
5099 
5100     template <std::size_t I, class... T>
5101     struct tuple_element<I, tuple<T...>> {
5102       using type =  __type_pack_element<I, T...>;
5103     };
5104 
5105     template <class...> class tuple {};
5106 
5107     template <std::size_t I, class... T>
5108     typename tuple_element<I, tuple<T...>>::type get(tuple<T...>);
5109     } // namespace std
5110 
5111     std::tuple<bool, int> &getTuple();
5112 
5113     void target(bool B) {
5114       auto &[BoundFoo, BoundBar] = getTuple();
5115       bool Baz;
5116       // Include if-then-else to test interaction of `BindingDecl` with join.
5117       if (B) {
5118         Baz = BoundFoo;
5119         (void)BoundBar;
5120         // [[p1]]
5121       } else {
5122         Baz = BoundFoo;
5123       }
5124       (void)0;
5125       // [[p2]]
5126     }
5127   )";
5128   runDataflow(
5129       Code,
5130       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5131          ASTContext &ASTCtx) {
5132         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
5133         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
5134 
5135         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
5136         ASSERT_THAT(BoundFooDecl, NotNull());
5137 
5138         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
5139         ASSERT_THAT(BoundBarDecl, NotNull());
5140 
5141         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
5142         ASSERT_THAT(BazDecl, NotNull());
5143 
5144         const Value *BoundFooValue = Env1.getValue(*BoundFooDecl);
5145         ASSERT_THAT(BoundFooValue, NotNull());
5146         EXPECT_TRUE(isa<BoolValue>(BoundFooValue));
5147 
5148         const Value *BoundBarValue = Env1.getValue(*BoundBarDecl);
5149         ASSERT_THAT(BoundBarValue, NotNull());
5150         EXPECT_TRUE(isa<IntegerValue>(BoundBarValue));
5151 
5152         // Test that a `DeclRefExpr` to a `BindingDecl` (with reference type)
5153         // works as expected. We don't test aliasing properties of the
5154         // reference, because we don't model `std::get` and so have no way to
5155         // equate separate references into the tuple.
5156         EXPECT_EQ(Env1.getValue(*BazDecl), BoundFooValue);
5157 
5158         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
5159 
5160         // Test that `BoundFooDecl` retains the value we expect, after the join.
5161         BoundFooValue = Env2.getValue(*BoundFooDecl);
5162         EXPECT_EQ(Env2.getValue(*BazDecl), BoundFooValue);
5163       });
5164 }
5165 
5166 TEST(TransferTest, BinaryOperatorComma) {
5167   std::string Code = R"(
5168     void target(int Foo, int Bar) {
5169       int &Baz = (Foo, Bar);
5170       // [[p]]
5171     }
5172   )";
5173   runDataflow(
5174       Code,
5175       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5176          ASTContext &ASTCtx) {
5177         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5178         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5179 
5180         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
5181         ASSERT_THAT(BarDecl, NotNull());
5182 
5183         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
5184         ASSERT_THAT(BazDecl, NotNull());
5185 
5186         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
5187         ASSERT_THAT(BarLoc, NotNull());
5188 
5189         const StorageLocation *BazLoc = Env.getStorageLocation(*BazDecl);
5190         EXPECT_EQ(BazLoc, BarLoc);
5191       });
5192 }
5193 
5194 TEST(TransferTest, IfStmtBranchExtendsFlowCondition) {
5195   std::string Code = R"(
5196     void target(bool Foo) {
5197       if (Foo) {
5198         (void)0;
5199         // [[if_then]]
5200       } else {
5201         (void)0;
5202         // [[if_else]]
5203       }
5204     }
5205   )";
5206   runDataflow(
5207       Code,
5208       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5209          ASTContext &ASTCtx) {
5210         ASSERT_THAT(Results.keys(), UnorderedElementsAre("if_then", "if_else"));
5211         const Environment &ThenEnv =
5212             getEnvironmentAtAnnotation(Results, "if_then");
5213         const Environment &ElseEnv =
5214             getEnvironmentAtAnnotation(Results, "if_else");
5215 
5216         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5217         ASSERT_THAT(FooDecl, NotNull());
5218 
5219         auto &ThenFooVal= getFormula(*FooDecl, ThenEnv);
5220         EXPECT_TRUE(ThenEnv.proves(ThenFooVal));
5221 
5222         auto &ElseFooVal = getFormula(*FooDecl, ElseEnv);
5223         EXPECT_TRUE(ElseEnv.proves(ElseEnv.arena().makeNot(ElseFooVal)));
5224       });
5225 }
5226 
5227 TEST(TransferTest, WhileStmtBranchExtendsFlowCondition) {
5228   std::string Code = R"(
5229     void target(bool Foo) {
5230       while (Foo) {
5231         (void)0;
5232         // [[loop_body]]
5233       }
5234       (void)0;
5235       // [[after_loop]]
5236     }
5237   )";
5238   runDataflow(
5239       Code,
5240       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5241          ASTContext &ASTCtx) {
5242         ASSERT_THAT(Results.keys(),
5243                     UnorderedElementsAre("loop_body", "after_loop"));
5244         const Environment &LoopBodyEnv =
5245             getEnvironmentAtAnnotation(Results, "loop_body");
5246         const Environment &AfterLoopEnv =
5247             getEnvironmentAtAnnotation(Results, "after_loop");
5248 
5249         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5250         ASSERT_THAT(FooDecl, NotNull());
5251 
5252         auto &LoopBodyFooVal = getFormula(*FooDecl, LoopBodyEnv);
5253         EXPECT_TRUE(LoopBodyEnv.proves(LoopBodyFooVal));
5254 
5255         auto &AfterLoopFooVal = getFormula(*FooDecl, AfterLoopEnv);
5256         EXPECT_TRUE(
5257             AfterLoopEnv.proves(AfterLoopEnv.arena().makeNot(AfterLoopFooVal)));
5258       });
5259 }
5260 
5261 TEST(TransferTest, DoWhileStmtBranchExtendsFlowCondition) {
5262   std::string Code = R"(
5263     void target(bool Foo) {
5264       bool Bar = true;
5265       do {
5266         (void)0;
5267         // [[loop_body]]
5268         Bar = false;
5269       } while (Foo);
5270       (void)0;
5271       // [[after_loop]]
5272     }
5273   )";
5274   runDataflow(
5275       Code,
5276       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5277          ASTContext &ASTCtx) {
5278         ASSERT_THAT(Results.keys(),
5279                     UnorderedElementsAre("loop_body", "after_loop"));
5280         const Environment &LoopBodyEnv =
5281             getEnvironmentAtAnnotation(Results, "loop_body");
5282         const Environment &AfterLoopEnv =
5283             getEnvironmentAtAnnotation(Results, "after_loop");
5284         auto &A = AfterLoopEnv.arena();
5285 
5286         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5287         ASSERT_THAT(FooDecl, NotNull());
5288 
5289         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
5290         ASSERT_THAT(BarDecl, NotNull());
5291 
5292         auto &LoopBodyFooVal= getFormula(*FooDecl, LoopBodyEnv);
5293         auto &LoopBodyBarVal = getFormula(*BarDecl, LoopBodyEnv);
5294         EXPECT_TRUE(
5295             LoopBodyEnv.proves(A.makeOr(LoopBodyBarVal, LoopBodyFooVal)));
5296 
5297         auto &AfterLoopFooVal = getFormula(*FooDecl, AfterLoopEnv);
5298         auto &AfterLoopBarVal = getFormula(*BarDecl, AfterLoopEnv);
5299         EXPECT_TRUE(AfterLoopEnv.proves(A.makeNot(AfterLoopFooVal)));
5300         EXPECT_TRUE(AfterLoopEnv.proves(A.makeNot(AfterLoopBarVal)));
5301       });
5302 }
5303 
5304 TEST(TransferTest, ForStmtBranchExtendsFlowCondition) {
5305   std::string Code = R"(
5306     void target(bool Foo) {
5307       for (; Foo;) {
5308         (void)0;
5309         // [[loop_body]]
5310       }
5311       (void)0;
5312       // [[after_loop]]
5313     }
5314   )";
5315   runDataflow(
5316       Code,
5317       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5318          ASTContext &ASTCtx) {
5319         ASSERT_THAT(Results.keys(),
5320                     UnorderedElementsAre("loop_body", "after_loop"));
5321         const Environment &LoopBodyEnv =
5322             getEnvironmentAtAnnotation(Results, "loop_body");
5323         const Environment &AfterLoopEnv =
5324             getEnvironmentAtAnnotation(Results, "after_loop");
5325 
5326         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5327         ASSERT_THAT(FooDecl, NotNull());
5328 
5329         auto &LoopBodyFooVal= getFormula(*FooDecl, LoopBodyEnv);
5330         EXPECT_TRUE(LoopBodyEnv.proves(LoopBodyFooVal));
5331 
5332         auto &AfterLoopFooVal = getFormula(*FooDecl, AfterLoopEnv);
5333         EXPECT_TRUE(
5334             AfterLoopEnv.proves(AfterLoopEnv.arena().makeNot(AfterLoopFooVal)));
5335       });
5336 }
5337 
5338 TEST(TransferTest, ForStmtBranchWithoutConditionDoesNotExtendFlowCondition) {
5339   std::string Code = R"(
5340     void target(bool Foo) {
5341       for (;;) {
5342         (void)0;
5343         // [[loop_body]]
5344       }
5345     }
5346   )";
5347   runDataflow(
5348       Code,
5349       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5350          ASTContext &ASTCtx) {
5351         ASSERT_THAT(Results.keys(), UnorderedElementsAre("loop_body"));
5352         const Environment &LoopBodyEnv =
5353             getEnvironmentAtAnnotation(Results, "loop_body");
5354 
5355         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5356         ASSERT_THAT(FooDecl, NotNull());
5357 
5358         auto &LoopBodyFooVal= getFormula(*FooDecl, LoopBodyEnv);
5359         EXPECT_FALSE(LoopBodyEnv.proves(LoopBodyFooVal));
5360       });
5361 }
5362 
5363 TEST(TransferTest, ContextSensitiveOptionDisabled) {
5364   std::string Code = R"(
5365     bool GiveBool();
5366     void SetBool(bool &Var) { Var = true; }
5367 
5368     void target() {
5369       bool Foo = GiveBool();
5370       SetBool(Foo);
5371       // [[p]]
5372     }
5373   )";
5374   runDataflow(
5375       Code,
5376       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5377          ASTContext &ASTCtx) {
5378         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5379         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5380 
5381         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5382         ASSERT_THAT(FooDecl, NotNull());
5383 
5384         auto &FooVal = getFormula(*FooDecl, Env);
5385         EXPECT_FALSE(Env.proves(FooVal));
5386         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
5387       },
5388       {BuiltinOptions{/*.ContextSensitiveOpts=*/std::nullopt}});
5389 }
5390 
5391 TEST(TransferTest, ContextSensitiveReturnReference) {
5392   std::string Code = R"(
5393     class S {};
5394     S& target(bool b, S &s) {
5395       return s;
5396       // [[p]]
5397     }
5398   )";
5399   runDataflow(
5400       Code,
5401       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5402          ASTContext &ASTCtx) {
5403         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5404 
5405         const ValueDecl *SDecl = findValueDecl(ASTCtx, "s");
5406         ASSERT_THAT(SDecl, NotNull());
5407 
5408         auto *SLoc = Env.getStorageLocation(*SDecl);
5409         ASSERT_THAT(SLoc, NotNull());
5410 
5411         ASSERT_THAT(Env.getReturnStorageLocation(), Eq(SLoc));
5412       },
5413       {BuiltinOptions{ContextSensitiveOptions{}}});
5414 }
5415 
5416 // This test is a regression test, based on a real crash.
5417 TEST(TransferTest, ContextSensitiveReturnReferenceWithConditionalOperator) {
5418   std::string Code = R"(
5419     class S {};
5420     S& target(bool b, S &s) {
5421       return b ? s : s;
5422       // [[p]]
5423     }
5424   )";
5425   runDataflow(
5426       Code,
5427       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5428          ASTContext &ASTCtx) {
5429         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5430         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5431 
5432         const ValueDecl *SDecl = findValueDecl(ASTCtx, "s");
5433         ASSERT_THAT(SDecl, NotNull());
5434 
5435         auto *SLoc = Env.getStorageLocation(*SDecl);
5436         ASSERT_THAT(SLoc, NotNull());
5437         EXPECT_THAT(Env.getValue(*SLoc), NotNull());
5438 
5439         auto *Loc = Env.getReturnStorageLocation();
5440         ASSERT_THAT(Loc, NotNull());
5441         EXPECT_THAT(Env.getValue(*Loc), NotNull());
5442 
5443         // TODO: We would really like to make this stronger assertion, but that
5444         // doesn't work because we don't propagate values correctly through
5445         // the conditional operator yet.
5446         // ASSERT_THAT(Loc, Eq(SLoc));
5447       },
5448       {BuiltinOptions{ContextSensitiveOptions{}}});
5449 }
5450 
5451 TEST(TransferTest, ContextSensitiveReturnOneOfTwoReferences) {
5452   std::string Code = R"(
5453     class S {};
5454     S &callee(bool b, S &s1_parm, S &s2_parm) {
5455       if (b)
5456         return s1_parm;
5457       else
5458         return s2_parm;
5459     }
5460     void target(bool b) {
5461       S s1;
5462       S s2;
5463       S &return_s1 = s1;
5464       S &return_s2 = s2;
5465       S &return_dont_know = callee(b, s1, s2);
5466       // [[p]]
5467     }
5468   )";
5469   runDataflow(
5470       Code,
5471       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5472          ASTContext &ASTCtx) {
5473         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5474 
5475         const ValueDecl *S1 = findValueDecl(ASTCtx, "s1");
5476         ASSERT_THAT(S1, NotNull());
5477         const ValueDecl *S2 = findValueDecl(ASTCtx, "s2");
5478         ASSERT_THAT(S2, NotNull());
5479         const ValueDecl *ReturnS1 = findValueDecl(ASTCtx, "return_s1");
5480         ASSERT_THAT(ReturnS1, NotNull());
5481         const ValueDecl *ReturnS2 = findValueDecl(ASTCtx, "return_s2");
5482         ASSERT_THAT(ReturnS2, NotNull());
5483         const ValueDecl *ReturnDontKnow =
5484             findValueDecl(ASTCtx, "return_dont_know");
5485         ASSERT_THAT(ReturnDontKnow, NotNull());
5486 
5487         StorageLocation *S1Loc = Env.getStorageLocation(*S1);
5488         StorageLocation *S2Loc = Env.getStorageLocation(*S2);
5489 
5490         EXPECT_THAT(Env.getStorageLocation(*ReturnS1), Eq(S1Loc));
5491         EXPECT_THAT(Env.getStorageLocation(*ReturnS2), Eq(S2Loc));
5492 
5493         // In the case where we don't have a consistent storage location for
5494         // the return value, the framework creates a new storage location, which
5495         // should be different from the storage locations of `s1` and `s2`.
5496         EXPECT_THAT(Env.getStorageLocation(*ReturnDontKnow), Ne(S1Loc));
5497         EXPECT_THAT(Env.getStorageLocation(*ReturnDontKnow), Ne(S2Loc));
5498       },
5499       {BuiltinOptions{ContextSensitiveOptions{}}});
5500 }
5501 
5502 TEST(TransferTest, ContextSensitiveDepthZero) {
5503   std::string Code = R"(
5504     bool GiveBool();
5505     void SetBool(bool &Var) { Var = true; }
5506 
5507     void target() {
5508       bool Foo = GiveBool();
5509       SetBool(Foo);
5510       // [[p]]
5511     }
5512   )";
5513   runDataflow(
5514       Code,
5515       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5516          ASTContext &ASTCtx) {
5517         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5518         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5519 
5520         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5521         ASSERT_THAT(FooDecl, NotNull());
5522 
5523         auto &FooVal = getFormula(*FooDecl, Env);
5524         EXPECT_FALSE(Env.proves(FooVal));
5525         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
5526       },
5527       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/0}}});
5528 }
5529 
5530 TEST(TransferTest, ContextSensitiveSetTrue) {
5531   std::string Code = R"(
5532     bool GiveBool();
5533     void SetBool(bool &Var) { Var = true; }
5534 
5535     void target() {
5536       bool Foo = GiveBool();
5537       SetBool(Foo);
5538       // [[p]]
5539     }
5540   )";
5541   runDataflow(
5542       Code,
5543       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5544          ASTContext &ASTCtx) {
5545         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5546         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5547 
5548         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5549         ASSERT_THAT(FooDecl, NotNull());
5550 
5551         auto &FooVal = getFormula(*FooDecl, Env);
5552         EXPECT_TRUE(Env.proves(FooVal));
5553       },
5554       {BuiltinOptions{ContextSensitiveOptions{}}});
5555 }
5556 
5557 TEST(TransferTest, ContextSensitiveSetFalse) {
5558   std::string Code = R"(
5559     bool GiveBool();
5560     void SetBool(bool &Var) { Var = false; }
5561 
5562     void target() {
5563       bool Foo = GiveBool();
5564       SetBool(Foo);
5565       // [[p]]
5566     }
5567   )";
5568   runDataflow(
5569       Code,
5570       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5571          ASTContext &ASTCtx) {
5572         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5573         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5574 
5575         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5576         ASSERT_THAT(FooDecl, NotNull());
5577 
5578         auto &FooVal = getFormula(*FooDecl, Env);
5579         EXPECT_TRUE(Env.proves(Env.arena().makeNot(FooVal)));
5580       },
5581       {BuiltinOptions{ContextSensitiveOptions{}}});
5582 }
5583 
5584 TEST(TransferTest, ContextSensitiveSetBothTrueAndFalse) {
5585   std::string Code = R"(
5586     bool GiveBool();
5587     void SetBool(bool &Var, bool Val) { Var = Val; }
5588 
5589     void target() {
5590       bool Foo = GiveBool();
5591       bool Bar = GiveBool();
5592       SetBool(Foo, true);
5593       SetBool(Bar, false);
5594       // [[p]]
5595     }
5596   )";
5597   runDataflow(
5598       Code,
5599       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5600          ASTContext &ASTCtx) {
5601         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5602         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5603         auto &A = Env.arena();
5604 
5605         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5606         ASSERT_THAT(FooDecl, NotNull());
5607 
5608         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
5609         ASSERT_THAT(BarDecl, NotNull());
5610 
5611         auto &FooVal = getFormula(*FooDecl, Env);
5612         EXPECT_TRUE(Env.proves(FooVal));
5613         EXPECT_FALSE(Env.proves(A.makeNot(FooVal)));
5614 
5615         auto &BarVal = getFormula(*BarDecl, Env);
5616         EXPECT_FALSE(Env.proves(BarVal));
5617         EXPECT_TRUE(Env.proves(A.makeNot(BarVal)));
5618       },
5619       {BuiltinOptions{ContextSensitiveOptions{}}});
5620 }
5621 
5622 TEST(TransferTest, ContextSensitiveSetTwoLayersDepthOne) {
5623   std::string Code = R"(
5624     bool GiveBool();
5625     void SetBool1(bool &Var) { Var = true; }
5626     void SetBool2(bool &Var) { SetBool1(Var); }
5627 
5628     void target() {
5629       bool Foo = GiveBool();
5630       SetBool2(Foo);
5631       // [[p]]
5632     }
5633   )";
5634   runDataflow(
5635       Code,
5636       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5637          ASTContext &ASTCtx) {
5638         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5639         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5640 
5641         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5642         ASSERT_THAT(FooDecl, NotNull());
5643 
5644         auto &FooVal = getFormula(*FooDecl, Env);
5645         EXPECT_FALSE(Env.proves(FooVal));
5646         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
5647       },
5648       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/1}}});
5649 }
5650 
5651 TEST(TransferTest, ContextSensitiveSetTwoLayersDepthTwo) {
5652   std::string Code = R"(
5653     bool GiveBool();
5654     void SetBool1(bool &Var) { Var = true; }
5655     void SetBool2(bool &Var) { SetBool1(Var); }
5656 
5657     void target() {
5658       bool Foo = GiveBool();
5659       SetBool2(Foo);
5660       // [[p]]
5661     }
5662   )";
5663   runDataflow(
5664       Code,
5665       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5666          ASTContext &ASTCtx) {
5667         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5668         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5669 
5670         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5671         ASSERT_THAT(FooDecl, NotNull());
5672 
5673         auto &FooVal = getFormula(*FooDecl, Env);
5674         EXPECT_TRUE(Env.proves(FooVal));
5675       },
5676       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/2}}});
5677 }
5678 
5679 TEST(TransferTest, ContextSensitiveSetThreeLayersDepthTwo) {
5680   std::string Code = R"(
5681     bool GiveBool();
5682     void SetBool1(bool &Var) { Var = true; }
5683     void SetBool2(bool &Var) { SetBool1(Var); }
5684     void SetBool3(bool &Var) { SetBool2(Var); }
5685 
5686     void target() {
5687       bool Foo = GiveBool();
5688       SetBool3(Foo);
5689       // [[p]]
5690     }
5691   )";
5692   runDataflow(
5693       Code,
5694       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5695          ASTContext &ASTCtx) {
5696         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5697         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5698 
5699         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5700         ASSERT_THAT(FooDecl, NotNull());
5701 
5702         auto &FooVal = getFormula(*FooDecl, Env);
5703         EXPECT_FALSE(Env.proves(FooVal));
5704         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
5705       },
5706       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/2}}});
5707 }
5708 
5709 TEST(TransferTest, ContextSensitiveSetThreeLayersDepthThree) {
5710   std::string Code = R"(
5711     bool GiveBool();
5712     void SetBool1(bool &Var) { Var = true; }
5713     void SetBool2(bool &Var) { SetBool1(Var); }
5714     void SetBool3(bool &Var) { SetBool2(Var); }
5715 
5716     void target() {
5717       bool Foo = GiveBool();
5718       SetBool3(Foo);
5719       // [[p]]
5720     }
5721   )";
5722   runDataflow(
5723       Code,
5724       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5725          ASTContext &ASTCtx) {
5726         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5727         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5728 
5729         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5730         ASSERT_THAT(FooDecl, NotNull());
5731 
5732         auto &FooVal = getFormula(*FooDecl, Env);
5733         EXPECT_TRUE(Env.proves(FooVal));
5734       },
5735       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/3}}});
5736 }
5737 
5738 TEST(TransferTest, ContextSensitiveMutualRecursion) {
5739   std::string Code = R"(
5740     bool Pong(bool X, bool Y);
5741 
5742     bool Ping(bool X, bool Y) {
5743       if (X) {
5744         return Y;
5745       } else {
5746         return Pong(!X, Y);
5747       }
5748     }
5749 
5750     bool Pong(bool X, bool Y) {
5751       if (Y) {
5752         return X;
5753       } else {
5754         return Ping(X, !Y);
5755       }
5756     }
5757 
5758     void target() {
5759       bool Foo = Ping(false, false);
5760       // [[p]]
5761     }
5762   )";
5763   runDataflow(
5764       Code,
5765       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5766          ASTContext &ASTCtx) {
5767         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5768         // The analysis doesn't crash...
5769         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5770 
5771         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5772         ASSERT_THAT(FooDecl, NotNull());
5773 
5774         auto &FooVal = getFormula(*FooDecl, Env);
5775         // ... but it also can't prove anything here.
5776         EXPECT_FALSE(Env.proves(FooVal));
5777         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
5778       },
5779       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/4}}});
5780 }
5781 
5782 TEST(TransferTest, ContextSensitiveSetMultipleLines) {
5783   std::string Code = R"(
5784     void SetBools(bool &Var1, bool &Var2) {
5785       Var1 = true;
5786       Var2 = false;
5787     }
5788 
5789     void target() {
5790       bool Foo = false;
5791       bool Bar = true;
5792       SetBools(Foo, Bar);
5793       // [[p]]
5794     }
5795   )";
5796   runDataflow(
5797       Code,
5798       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5799          ASTContext &ASTCtx) {
5800         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5801         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5802 
5803         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5804         ASSERT_THAT(FooDecl, NotNull());
5805 
5806         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
5807         ASSERT_THAT(BarDecl, NotNull());
5808 
5809         auto &FooVal = getFormula(*FooDecl, Env);
5810         EXPECT_TRUE(Env.proves(FooVal));
5811         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
5812 
5813         auto &BarVal = getFormula(*BarDecl, Env);
5814         EXPECT_FALSE(Env.proves(BarVal));
5815         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BarVal)));
5816       },
5817       {BuiltinOptions{ContextSensitiveOptions{}}});
5818 }
5819 
5820 TEST(TransferTest, ContextSensitiveSetMultipleBlocks) {
5821   std::string Code = R"(
5822     void IfCond(bool Cond, bool &Then, bool &Else) {
5823       if (Cond) {
5824         Then = true;
5825       } else {
5826         Else = true;
5827       }
5828     }
5829 
5830     void target() {
5831       bool Foo = false;
5832       bool Bar = false;
5833       bool Baz = false;
5834       IfCond(Foo, Bar, Baz);
5835       // [[p]]
5836     }
5837   )";
5838   runDataflow(
5839       Code,
5840       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5841          ASTContext &ASTCtx) {
5842         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5843         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5844 
5845         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
5846         ASSERT_THAT(BarDecl, NotNull());
5847 
5848         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
5849         ASSERT_THAT(BazDecl, NotNull());
5850 
5851         auto &BarVal = getFormula(*BarDecl, Env);
5852         EXPECT_FALSE(Env.proves(BarVal));
5853         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BarVal)));
5854 
5855         auto &BazVal = getFormula(*BazDecl, Env);
5856         EXPECT_TRUE(Env.proves(BazVal));
5857         EXPECT_FALSE(Env.proves(Env.arena().makeNot(BazVal)));
5858       },
5859       {BuiltinOptions{ContextSensitiveOptions{}}});
5860 }
5861 
5862 TEST(TransferTest, ContextSensitiveReturnVoid) {
5863   std::string Code = R"(
5864     void Noop() { return; }
5865 
5866     void target() {
5867       Noop();
5868       // [[p]]
5869     }
5870   )";
5871   runDataflow(
5872       Code,
5873       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5874          ASTContext &ASTCtx) {
5875         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5876         // This just tests that the analysis doesn't crash.
5877       },
5878       {BuiltinOptions{ContextSensitiveOptions{}}});
5879 }
5880 
5881 TEST(TransferTest, ContextSensitiveReturnTrue) {
5882   std::string Code = R"(
5883     bool GiveBool() { return true; }
5884 
5885     void target() {
5886       bool Foo = GiveBool();
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 *FooDecl = findValueDecl(ASTCtx, "Foo");
5898         ASSERT_THAT(FooDecl, NotNull());
5899 
5900         auto &FooVal = getFormula(*FooDecl, Env);
5901         EXPECT_TRUE(Env.proves(FooVal));
5902       },
5903       {BuiltinOptions{ContextSensitiveOptions{}}});
5904 }
5905 
5906 TEST(TransferTest, ContextSensitiveReturnFalse) {
5907   std::string Code = R"(
5908     bool GiveBool() { return false; }
5909 
5910     void target() {
5911       bool Foo = GiveBool();
5912       // [[p]]
5913     }
5914   )";
5915   runDataflow(
5916       Code,
5917       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5918          ASTContext &ASTCtx) {
5919         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5920         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5921 
5922         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5923         ASSERT_THAT(FooDecl, NotNull());
5924 
5925         auto &FooVal = getFormula(*FooDecl, Env);
5926         EXPECT_TRUE(Env.proves(Env.arena().makeNot(FooVal)));
5927       },
5928       {BuiltinOptions{ContextSensitiveOptions{}}});
5929 }
5930 
5931 TEST(TransferTest, ContextSensitiveReturnArg) {
5932   std::string Code = R"(
5933     bool GiveBool();
5934     bool GiveBack(bool Arg) { return Arg; }
5935 
5936     void target() {
5937       bool Foo = GiveBool();
5938       bool Bar = GiveBack(Foo);
5939       bool Baz = Foo == Bar;
5940       // [[p]]
5941     }
5942   )";
5943   runDataflow(
5944       Code,
5945       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5946          ASTContext &ASTCtx) {
5947         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5948         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5949 
5950         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
5951         ASSERT_THAT(BazDecl, NotNull());
5952 
5953         auto &BazVal = getFormula(*BazDecl, Env);
5954         EXPECT_TRUE(Env.proves(BazVal));
5955       },
5956       {BuiltinOptions{ContextSensitiveOptions{}}});
5957 }
5958 
5959 TEST(TransferTest, ContextSensitiveReturnInt) {
5960   std::string Code = R"(
5961     int identity(int x) { return x; }
5962 
5963     void target() {
5964       int y = identity(42);
5965       // [[p]]
5966     }
5967   )";
5968   runDataflow(
5969       Code,
5970       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5971          ASTContext &ASTCtx) {
5972         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5973         // This just tests that the analysis doesn't crash.
5974       },
5975       {BuiltinOptions{ContextSensitiveOptions{}}});
5976 }
5977 
5978 TEST(TransferTest, ContextSensitiveReturnRecord) {
5979   std::string Code = R"(
5980     struct S {
5981       bool B;
5982     };
5983 
5984     S makeS(bool BVal) { return {BVal}; }
5985 
5986     void target() {
5987       S FalseS = makeS(false);
5988       S TrueS = makeS(true);
5989       // [[p]]
5990     }
5991   )";
5992   runDataflow(
5993       Code,
5994       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5995          ASTContext &ASTCtx) {
5996         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5997 
5998         auto &FalseSLoc =
5999             getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "FalseS");
6000         auto &TrueSLoc =
6001             getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "TrueS");
6002 
6003         EXPECT_EQ(getFieldValue(&FalseSLoc, "B", ASTCtx, Env),
6004                   &Env.getBoolLiteralValue(false));
6005         EXPECT_EQ(getFieldValue(&TrueSLoc, "B", ASTCtx, Env),
6006                   &Env.getBoolLiteralValue(true));
6007       },
6008       {BuiltinOptions{ContextSensitiveOptions{}}});
6009 }
6010 
6011 TEST(TransferTest, ContextSensitiveReturnSelfReferentialRecord) {
6012   std::string Code = R"(
6013     struct S {
6014       S() { self = this; }
6015       S *self;
6016     };
6017 
6018     S makeS() {
6019       // RVO guarantees that this will be constructed directly into `MyS`.
6020       return S();
6021     }
6022 
6023     void target() {
6024       S MyS = makeS();
6025       // [[p]]
6026     }
6027   )";
6028   runDataflow(
6029       Code,
6030       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6031          ASTContext &ASTCtx) {
6032         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6033 
6034         auto &MySLoc = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "MyS");
6035 
6036         auto *SelfVal =
6037             cast<PointerValue>(getFieldValue(&MySLoc, "self", ASTCtx, Env));
6038         EXPECT_EQ(&SelfVal->getPointeeLoc(), &MySLoc);
6039       },
6040       {BuiltinOptions{ContextSensitiveOptions{}}});
6041 }
6042 
6043 TEST(TransferTest, ContextSensitiveMethodLiteral) {
6044   std::string Code = R"(
6045     class MyClass {
6046     public:
6047       bool giveBool() { return true; }
6048     };
6049 
6050     void target() {
6051       MyClass MyObj;
6052       bool Foo = MyObj.giveBool();
6053       // [[p]]
6054     }
6055   )";
6056   runDataflow(
6057       Code,
6058       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6059          ASTContext &ASTCtx) {
6060         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6061         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6062 
6063         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6064         ASSERT_THAT(FooDecl, NotNull());
6065 
6066         auto &FooVal = getFormula(*FooDecl, Env);
6067         EXPECT_TRUE(Env.proves(FooVal));
6068       },
6069       {BuiltinOptions{ContextSensitiveOptions{}}});
6070 }
6071 
6072 TEST(TransferTest, ContextSensitiveMethodGetter) {
6073   std::string Code = R"(
6074     class MyClass {
6075     public:
6076       bool getField() { return Field; }
6077 
6078       bool Field;
6079     };
6080 
6081     void target() {
6082       MyClass MyObj;
6083       MyObj.Field = true;
6084       bool Foo = MyObj.getField();
6085       // [[p]]
6086     }
6087   )";
6088   runDataflow(
6089       Code,
6090       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6091          ASTContext &ASTCtx) {
6092         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6093         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6094 
6095         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6096         ASSERT_THAT(FooDecl, NotNull());
6097 
6098         auto &FooVal = getFormula(*FooDecl, Env);
6099         EXPECT_TRUE(Env.proves(FooVal));
6100       },
6101       {BuiltinOptions{ContextSensitiveOptions{}}});
6102 }
6103 
6104 TEST(TransferTest, ContextSensitiveMethodSetter) {
6105   std::string Code = R"(
6106     class MyClass {
6107     public:
6108       void setField(bool Val) { Field = Val; }
6109 
6110       bool Field;
6111     };
6112 
6113     void target() {
6114       MyClass MyObj;
6115       MyObj.setField(true);
6116       bool Foo = MyObj.Field;
6117       // [[p]]
6118     }
6119   )";
6120   runDataflow(
6121       Code,
6122       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6123          ASTContext &ASTCtx) {
6124         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6125         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6126 
6127         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6128         ASSERT_THAT(FooDecl, NotNull());
6129 
6130         auto &FooVal = getFormula(*FooDecl, Env);
6131         EXPECT_TRUE(Env.proves(FooVal));
6132       },
6133       {BuiltinOptions{ContextSensitiveOptions{}}});
6134 }
6135 
6136 TEST(TransferTest, ContextSensitiveMethodGetterAndSetter) {
6137   std::string Code = R"(
6138     class MyClass {
6139     public:
6140       bool getField() { return Field; }
6141       void setField(bool Val) { Field = Val; }
6142 
6143     private:
6144       bool Field;
6145     };
6146 
6147     void target() {
6148       MyClass MyObj;
6149       MyObj.setField(true);
6150       bool Foo = MyObj.getField();
6151       // [[p]]
6152     }
6153   )";
6154   runDataflow(
6155       Code,
6156       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6157          ASTContext &ASTCtx) {
6158         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6159         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6160 
6161         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6162         ASSERT_THAT(FooDecl, NotNull());
6163 
6164         auto &FooVal = getFormula(*FooDecl, Env);
6165         EXPECT_TRUE(Env.proves(FooVal));
6166       },
6167       {BuiltinOptions{ContextSensitiveOptions{}}});
6168 }
6169 
6170 
6171 TEST(TransferTest, ContextSensitiveMethodTwoLayersVoid) {
6172   std::string Code = R"(
6173     class MyClass {
6174     public:
6175       void Inner() { MyField = true; }
6176       void Outer() { Inner(); }
6177 
6178       bool MyField;
6179     };
6180 
6181     void target() {
6182       MyClass MyObj;
6183       MyObj.Outer();
6184       bool Foo = MyObj.MyField;
6185       // [[p]]
6186     }
6187   )";
6188   runDataflow(
6189       Code,
6190       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6191          ASTContext &ASTCtx) {
6192         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6193         ;
6194         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6195 
6196         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6197         ASSERT_THAT(FooDecl, NotNull());
6198 
6199         auto &FooVal = getFormula(*FooDecl, Env);
6200         EXPECT_TRUE(Env.proves(FooVal));
6201       },
6202       {BuiltinOptions{ContextSensitiveOptions{}}});
6203 }
6204 
6205 TEST(TransferTest, ContextSensitiveMethodTwoLayersReturn) {
6206   std::string Code = R"(
6207     class MyClass {
6208     public:
6209       bool Inner() { return MyField; }
6210       bool Outer() { return Inner(); }
6211 
6212       bool MyField;
6213     };
6214 
6215     void target() {
6216       MyClass MyObj;
6217       MyObj.MyField = true;
6218       bool Foo = MyObj.Outer();
6219       // [[p]]
6220     }
6221   )";
6222   runDataflow(
6223       Code,
6224       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6225          ASTContext &ASTCtx) {
6226         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6227         ;
6228         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6229 
6230         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6231         ASSERT_THAT(FooDecl, NotNull());
6232 
6233         auto &FooVal = getFormula(*FooDecl, Env);
6234         EXPECT_TRUE(Env.proves(FooVal));
6235       },
6236       {BuiltinOptions{ContextSensitiveOptions{}}});
6237 }
6238 
6239 TEST(TransferTest, ContextSensitiveConstructorBody) {
6240   std::string Code = R"(
6241     class MyClass {
6242     public:
6243       MyClass() { MyField = true; }
6244 
6245       bool MyField;
6246     };
6247 
6248     void target() {
6249       MyClass MyObj;
6250       bool Foo = MyObj.MyField;
6251       // [[p]]
6252     }
6253   )";
6254   runDataflow(
6255       Code,
6256       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6257          ASTContext &ASTCtx) {
6258         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6259         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6260 
6261         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6262         ASSERT_THAT(FooDecl, NotNull());
6263 
6264         auto &FooVal = getFormula(*FooDecl, Env);
6265         EXPECT_TRUE(Env.proves(FooVal));
6266       },
6267       {BuiltinOptions{ContextSensitiveOptions{}}});
6268 }
6269 
6270 TEST(TransferTest, ContextSensitiveConstructorInitializer) {
6271   std::string Code = R"(
6272     class MyClass {
6273     public:
6274       MyClass() : MyField(true) {}
6275 
6276       bool MyField;
6277     };
6278 
6279     void target() {
6280       MyClass MyObj;
6281       bool Foo = MyObj.MyField;
6282       // [[p]]
6283     }
6284   )";
6285   runDataflow(
6286       Code,
6287       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6288          ASTContext &ASTCtx) {
6289         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6290         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6291 
6292         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6293         ASSERT_THAT(FooDecl, NotNull());
6294 
6295         auto &FooVal = getFormula(*FooDecl, Env);
6296         EXPECT_TRUE(Env.proves(FooVal));
6297       },
6298       {BuiltinOptions{ContextSensitiveOptions{}}});
6299 }
6300 
6301 TEST(TransferTest, ContextSensitiveConstructorDefault) {
6302   std::string Code = R"(
6303     class MyClass {
6304     public:
6305       MyClass() = default;
6306 
6307       bool MyField = true;
6308     };
6309 
6310     void target() {
6311       MyClass MyObj;
6312       bool Foo = MyObj.MyField;
6313       // [[p]]
6314     }
6315   )";
6316   runDataflow(
6317       Code,
6318       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6319          ASTContext &ASTCtx) {
6320         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6321         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6322 
6323         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6324         ASSERT_THAT(FooDecl, NotNull());
6325 
6326         auto &FooVal = getFormula(*FooDecl, Env);
6327         EXPECT_TRUE(Env.proves(FooVal));
6328       },
6329       {BuiltinOptions{ContextSensitiveOptions{}}});
6330 }
6331 
6332 TEST(TransferTest, ContextSensitiveSelfReferentialClass) {
6333   // Test that the `this` pointer seen in the constructor has the same value
6334   // as the address of the variable the object is constructed into.
6335   std::string Code = R"(
6336     class MyClass {
6337     public:
6338       MyClass() : Self(this) {}
6339       MyClass *Self;
6340     };
6341 
6342     void target() {
6343       MyClass MyObj;
6344       MyClass *SelfPtr = MyObj.Self;
6345       // [[p]]
6346     }
6347   )";
6348   runDataflow(
6349       Code,
6350       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6351          ASTContext &ASTCtx) {
6352         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6353 
6354         const ValueDecl *MyObjDecl = findValueDecl(ASTCtx, "MyObj");
6355         ASSERT_THAT(MyObjDecl, NotNull());
6356 
6357         const ValueDecl *SelfDecl = findValueDecl(ASTCtx, "SelfPtr");
6358         ASSERT_THAT(SelfDecl, NotNull());
6359 
6360         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6361         auto &SelfVal = *cast<PointerValue>(Env.getValue(*SelfDecl));
6362         EXPECT_EQ(Env.getStorageLocation(*MyObjDecl), &SelfVal.getPointeeLoc());
6363       },
6364       {BuiltinOptions{ContextSensitiveOptions{}}});
6365 }
6366 
6367 TEST(TransferTest, UnnamedBitfieldInitializer) {
6368   std::string Code = R"(
6369     struct B {};
6370     struct A {
6371       unsigned a;
6372       unsigned : 4;
6373       unsigned c;
6374       B b;
6375     };
6376     void target() {
6377       A a = {};
6378       A test = a;
6379       (void)test.c;
6380     }
6381   )";
6382   runDataflow(
6383       Code,
6384       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6385          ASTContext &ASTCtx) {
6386         // This doesn't need a body because this test was crashing the framework
6387         // before handling correctly Unnamed bitfields in `InitListExpr`.
6388       });
6389 }
6390 
6391 // Repro for a crash that used to occur with chained short-circuiting logical
6392 // operators.
6393 TEST(TransferTest, ChainedLogicalOps) {
6394   std::string Code = R"(
6395     bool target() {
6396       bool b = true || false || false || false;
6397       // [[p]]
6398       return b;
6399     }
6400   )";
6401   runDataflow(
6402       Code,
6403       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6404          ASTContext &ASTCtx) {
6405         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6406         auto &B = getValueForDecl<BoolValue>(ASTCtx, Env, "b").formula();
6407         EXPECT_TRUE(Env.proves(B));
6408       });
6409 }
6410 
6411 // Repro for a crash that used to occur when we call a `noreturn` function
6412 // within one of the operands of a `&&` or `||` operator.
6413 TEST(TransferTest, NoReturnFunctionInsideShortCircuitedBooleanOp) {
6414   std::string Code = R"(
6415     __attribute__((noreturn)) int doesnt_return();
6416     bool some_condition();
6417     void target(bool b1, bool b2) {
6418       // Neither of these should crash. In addition, if we don't terminate the
6419       // program, we know that the operators need to trigger the short-circuit
6420       // logic, so `NoreturnOnRhsOfAnd` will be false and `NoreturnOnRhsOfOr`
6421       // will be true.
6422       bool NoreturnOnRhsOfAnd = b1 && doesnt_return() > 0;
6423       bool NoreturnOnRhsOfOr = b2 || doesnt_return() > 0;
6424 
6425       // Calling a `noreturn` function on the LHS of an `&&` or `||` makes the
6426       // entire expression unreachable. So we know that in both of the following
6427       // cases, if `target()` terminates, the `else` branch was taken.
6428       bool NoreturnOnLhsMakesAndUnreachable = false;
6429       if (some_condition())
6430          doesnt_return() > 0 && some_condition();
6431       else
6432          NoreturnOnLhsMakesAndUnreachable = true;
6433 
6434       bool NoreturnOnLhsMakesOrUnreachable = false;
6435       if (some_condition())
6436          doesnt_return() > 0 || some_condition();
6437       else
6438          NoreturnOnLhsMakesOrUnreachable = true;
6439 
6440       // [[p]]
6441     }
6442   )";
6443   runDataflow(
6444       Code,
6445       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6446          ASTContext &ASTCtx) {
6447         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6448         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6449         auto &A = Env.arena();
6450 
6451         // Check that [[p]] is reachable with a non-false flow condition.
6452         EXPECT_FALSE(Env.proves(A.makeLiteral(false)));
6453 
6454         auto &B1 = getValueForDecl<BoolValue>(ASTCtx, Env, "b1").formula();
6455         EXPECT_TRUE(Env.proves(A.makeNot(B1)));
6456 
6457         auto &NoreturnOnRhsOfAnd =
6458             getValueForDecl<BoolValue>(ASTCtx, Env, "NoreturnOnRhsOfAnd").formula();
6459         EXPECT_TRUE(Env.proves(A.makeNot(NoreturnOnRhsOfAnd)));
6460 
6461         auto &B2 = getValueForDecl<BoolValue>(ASTCtx, Env, "b2").formula();
6462         EXPECT_TRUE(Env.proves(B2));
6463 
6464         auto &NoreturnOnRhsOfOr =
6465             getValueForDecl<BoolValue>(ASTCtx, Env, "NoreturnOnRhsOfOr")
6466                 .formula();
6467         EXPECT_TRUE(Env.proves(NoreturnOnRhsOfOr));
6468 
6469         auto &NoreturnOnLhsMakesAndUnreachable = getValueForDecl<BoolValue>(
6470             ASTCtx, Env, "NoreturnOnLhsMakesAndUnreachable").formula();
6471         EXPECT_TRUE(Env.proves(NoreturnOnLhsMakesAndUnreachable));
6472 
6473         auto &NoreturnOnLhsMakesOrUnreachable = getValueForDecl<BoolValue>(
6474             ASTCtx, Env, "NoreturnOnLhsMakesOrUnreachable").formula();
6475         EXPECT_TRUE(Env.proves(NoreturnOnLhsMakesOrUnreachable));
6476       });
6477 }
6478 
6479 TEST(TransferTest, NewExpressions) {
6480   std::string Code = R"(
6481     void target() {
6482       int *p = new int(42);
6483       // [[after_new]]
6484     }
6485   )";
6486   runDataflow(
6487       Code,
6488       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6489          ASTContext &ASTCtx) {
6490         const Environment &Env =
6491             getEnvironmentAtAnnotation(Results, "after_new");
6492 
6493         auto &P = getValueForDecl<PointerValue>(ASTCtx, Env, "p");
6494 
6495         EXPECT_THAT(Env.getValue(P.getPointeeLoc()), NotNull());
6496       });
6497 }
6498 
6499 TEST(TransferTest, NewExpressions_Structs) {
6500   std::string Code = R"(
6501     struct Inner {
6502       int InnerField;
6503     };
6504 
6505     struct Outer {
6506       Inner OuterField;
6507     };
6508 
6509     void target() {
6510       Outer *p = new Outer;
6511       // Access the fields to make sure the analysis actually generates children
6512       // for them in the `RecordStorageLocation` and `RecordValue`.
6513       p->OuterField.InnerField;
6514       // [[after_new]]
6515     }
6516   )";
6517   runDataflow(
6518       Code,
6519       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6520          ASTContext &ASTCtx) {
6521         const Environment &Env =
6522             getEnvironmentAtAnnotation(Results, "after_new");
6523 
6524         const ValueDecl *OuterField = findValueDecl(ASTCtx, "OuterField");
6525         const ValueDecl *InnerField = findValueDecl(ASTCtx, "InnerField");
6526 
6527         auto &P = getValueForDecl<PointerValue>(ASTCtx, Env, "p");
6528 
6529         auto &OuterLoc = cast<RecordStorageLocation>(P.getPointeeLoc());
6530         auto &OuterFieldLoc =
6531             *cast<RecordStorageLocation>(OuterLoc.getChild(*OuterField));
6532         auto &InnerFieldLoc = *OuterFieldLoc.getChild(*InnerField);
6533 
6534         // Values for the struct and all fields exist after the new.
6535         EXPECT_THAT(Env.getValue(OuterLoc), NotNull());
6536         EXPECT_THAT(Env.getValue(OuterFieldLoc), NotNull());
6537         EXPECT_THAT(Env.getValue(InnerFieldLoc), NotNull());
6538       });
6539 }
6540 
6541 TEST(TransferTest, FunctionToPointerDecayHasValue) {
6542   std::string Code = R"(
6543     struct A { static void static_member_func(); };
6544     void target() {
6545       // To check that we're treating function-to-pointer decay correctly,
6546       // create two pointers, then verify they refer to the same storage
6547       // location.
6548       // We need to do the test this way because even if an initializer (in this
6549       // case, the function-to-pointer decay) does not create a value, we still
6550       // create a value for the variable.
6551       void (*non_member_p1)() = target;
6552       void (*non_member_p2)() = target;
6553 
6554       // Do the same thing but for a static member function.
6555       void (*member_p1)() = A::static_member_func;
6556       void (*member_p2)() = A::static_member_func;
6557       // [[p]]
6558     }
6559   )";
6560   runDataflow(
6561       Code,
6562       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6563          ASTContext &ASTCtx) {
6564         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6565 
6566         auto &NonMemberP1 =
6567             getValueForDecl<PointerValue>(ASTCtx, Env, "non_member_p1");
6568         auto &NonMemberP2 =
6569             getValueForDecl<PointerValue>(ASTCtx, Env, "non_member_p2");
6570         EXPECT_EQ(&NonMemberP1.getPointeeLoc(), &NonMemberP2.getPointeeLoc());
6571 
6572         auto &MemberP1 =
6573             getValueForDecl<PointerValue>(ASTCtx, Env, "member_p1");
6574         auto &MemberP2 =
6575             getValueForDecl<PointerValue>(ASTCtx, Env, "member_p2");
6576         EXPECT_EQ(&MemberP1.getPointeeLoc(), &MemberP2.getPointeeLoc());
6577       });
6578 }
6579 
6580 // Check that a builtin function is not associated with a value. (It's only
6581 // possible to call builtin functions directly, not take their address.)
6582 TEST(TransferTest, BuiltinFunctionModeled) {
6583   std::string Code = R"(
6584     void target() {
6585       __builtin_expect(0, 0);
6586       // [[p]]
6587     }
6588   )";
6589   runDataflow(
6590       Code,
6591       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6592          ASTContext &ASTCtx) {
6593         using ast_matchers::selectFirst;
6594         using ast_matchers::match;
6595         using ast_matchers::traverse;
6596         using ast_matchers::implicitCastExpr;
6597         using ast_matchers::hasCastKind;
6598 
6599         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6600 
6601         auto *ImplicitCast = selectFirst<ImplicitCastExpr>(
6602             "implicit_cast",
6603             match(traverse(TK_AsIs,
6604                            implicitCastExpr(hasCastKind(CK_BuiltinFnToFnPtr))
6605                                .bind("implicit_cast")),
6606                   ASTCtx));
6607 
6608         ASSERT_THAT(ImplicitCast, NotNull());
6609         EXPECT_THAT(Env.getValue(*ImplicitCast), IsNull());
6610       });
6611 }
6612 
6613 // Check that a callee of a member operator call is modeled as a `PointerValue`.
6614 // Member operator calls are unusual in that their callee is a pointer that
6615 // stems from a `FunctionToPointerDecay`. In calls to non-operator non-static
6616 // member functions, the callee is a `MemberExpr` (which does not have pointer
6617 // type).
6618 // We want to make sure that we produce a pointer value for the callee in this
6619 // specific scenario and that its storage location is durable (for convergence).
6620 TEST(TransferTest, MemberOperatorCallModelsPointerForCallee) {
6621   std::string Code = R"(
6622     struct S {
6623       bool operator!=(S s);
6624     };
6625     void target() {
6626       S s;
6627       (void)(s != s);
6628       (void)(s != s);
6629       // [[p]]
6630     }
6631   )";
6632   runDataflow(
6633       Code,
6634       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6635          ASTContext &ASTCtx) {
6636         using ast_matchers::selectFirst;
6637         using ast_matchers::match;
6638         using ast_matchers::traverse;
6639         using ast_matchers::cxxOperatorCallExpr;
6640 
6641         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6642 
6643         auto Matches = match(
6644             traverse(TK_AsIs, cxxOperatorCallExpr().bind("call")), ASTCtx);
6645 
6646         ASSERT_EQ(Matches.size(), 2UL);
6647 
6648         auto *Call1 = Matches[0].getNodeAs<CXXOperatorCallExpr>("call");
6649         auto *Call2 = Matches[1].getNodeAs<CXXOperatorCallExpr>("call");
6650 
6651         ASSERT_THAT(Call1, NotNull());
6652         ASSERT_THAT(Call2, NotNull());
6653 
6654         EXPECT_EQ(cast<ImplicitCastExpr>(Call1->getCallee())->getCastKind(),
6655                   CK_FunctionToPointerDecay);
6656         EXPECT_EQ(cast<ImplicitCastExpr>(Call2->getCallee())->getCastKind(),
6657                   CK_FunctionToPointerDecay);
6658 
6659         auto *Ptr1 = cast<PointerValue>(Env.getValue(*Call1->getCallee()));
6660         auto *Ptr2 = cast<PointerValue>(Env.getValue(*Call2->getCallee()));
6661 
6662         ASSERT_EQ(&Ptr1->getPointeeLoc(), &Ptr2->getPointeeLoc());
6663       });
6664 }
6665 
6666 // Check that fields of anonymous records are modeled.
6667 TEST(TransferTest, AnonymousStruct) {
6668   std::string Code = R"(
6669     struct S {
6670       struct {
6671         bool b;
6672       };
6673     };
6674     void target() {
6675       S s;
6676       s.b = true;
6677       // [[p]]
6678     }
6679   )";
6680   runDataflow(
6681       Code,
6682       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6683          ASTContext &ASTCtx) {
6684         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6685         const ValueDecl *SDecl = findValueDecl(ASTCtx, "s");
6686         const ValueDecl *BDecl = findValueDecl(ASTCtx, "b");
6687         const IndirectFieldDecl *IndirectField =
6688             findIndirectFieldDecl(ASTCtx, "b");
6689 
6690         auto *S = cast<RecordStorageLocation>(Env.getStorageLocation(*SDecl));
6691         auto &AnonStruct = *cast<RecordStorageLocation>(
6692             S->getChild(*cast<ValueDecl>(IndirectField->chain().front())));
6693 
6694         auto *B = cast<BoolValue>(getFieldValue(&AnonStruct, *BDecl, Env));
6695         ASSERT_TRUE(Env.proves(B->formula()));
6696       });
6697 }
6698 
6699 TEST(TransferTest, AnonymousStructWithInitializer) {
6700   std::string Code = R"(
6701     struct target {
6702       target() {
6703         (void)0;
6704         // [[p]]
6705       }
6706       struct {
6707         bool b = true;
6708       };
6709     };
6710   )";
6711   runDataflow(
6712       Code,
6713       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6714          ASTContext &ASTCtx) {
6715         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6716         const ValueDecl *BDecl = findValueDecl(ASTCtx, "b");
6717         const IndirectFieldDecl *IndirectField =
6718             findIndirectFieldDecl(ASTCtx, "b");
6719 
6720         auto *ThisLoc =
6721             cast<RecordStorageLocation>(Env.getThisPointeeStorageLocation());
6722         auto &AnonStruct = *cast<RecordStorageLocation>(ThisLoc->getChild(
6723             *cast<ValueDecl>(IndirectField->chain().front())));
6724 
6725         auto *B = cast<BoolValue>(getFieldValue(&AnonStruct, *BDecl, Env));
6726         ASSERT_TRUE(Env.proves(B->formula()));
6727       });
6728 }
6729 
6730 TEST(TransferTest, AnonymousStructWithReferenceField) {
6731   std::string Code = R"(
6732     int global_i = 0;
6733     struct target {
6734       target() {
6735         (void)0;
6736         // [[p]]
6737       }
6738       struct {
6739         int &i = global_i;
6740       };
6741     };
6742   )";
6743   runDataflow(
6744       Code,
6745       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6746          ASTContext &ASTCtx) {
6747         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6748         const ValueDecl *GlobalIDecl = findValueDecl(ASTCtx, "global_i");
6749         const ValueDecl *IDecl = findValueDecl(ASTCtx, "i");
6750         const IndirectFieldDecl *IndirectField =
6751             findIndirectFieldDecl(ASTCtx, "i");
6752 
6753         auto *ThisLoc =
6754             cast<RecordStorageLocation>(Env.getThisPointeeStorageLocation());
6755         auto &AnonStruct = *cast<RecordStorageLocation>(ThisLoc->getChild(
6756             *cast<ValueDecl>(IndirectField->chain().front())));
6757 
6758         ASSERT_EQ(AnonStruct.getChild(*IDecl),
6759                   Env.getStorageLocation(*GlobalIDecl));
6760       });
6761 }
6762 
6763 TEST(TransferTest, EvaluateBlockWithUnreachablePreds) {
6764   // This is a crash repro.
6765   // `false` block may not have been processed when we try to evaluate the `||`
6766   // after visiting `true`, because it is not necessary (and therefore the edge
6767   // is marked unreachable). Trying to get the analysis state via
6768   // `getEnvironment` for the subexpression still should not crash.
6769   std::string Code = R"(
6770     int target(int i) {
6771       if ((i < 0 && true) || false) {
6772         return 0;
6773       }
6774       return 0;
6775     }
6776   )";
6777   runDataflow(
6778       Code,
6779       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6780          ASTContext &ASTCtx) {});
6781 }
6782 
6783 TEST(TransferTest, LambdaCaptureByCopy) {
6784   std::string Code = R"(
6785     void target(int Foo, int Bar) {
6786       [Foo]() {
6787         (void)0;
6788         // [[p]]
6789       }();
6790     }
6791   )";
6792   runDataflowOnLambda(
6793       Code,
6794       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6795          ASTContext &ASTCtx) {
6796         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6797         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6798 
6799         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6800         ASSERT_THAT(FooDecl, NotNull());
6801 
6802         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
6803         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
6804 
6805         const Value *FooVal = Env.getValue(*FooLoc);
6806         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
6807 
6808         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
6809         ASSERT_THAT(BarDecl, NotNull());
6810 
6811         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
6812         EXPECT_THAT(BarLoc, IsNull());
6813       });
6814 }
6815 
6816 TEST(TransferTest, LambdaCaptureByReference) {
6817   std::string Code = R"(
6818     void target(int Foo, int Bar) {
6819       [&Foo]() {
6820         (void)0;
6821         // [[p]]
6822       }();
6823     }
6824   )";
6825   runDataflowOnLambda(
6826       Code,
6827       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6828          ASTContext &ASTCtx) {
6829         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6830         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6831 
6832         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6833         ASSERT_THAT(FooDecl, NotNull());
6834 
6835         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
6836         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
6837 
6838         const Value *FooVal = Env.getValue(*FooLoc);
6839         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
6840 
6841         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
6842         ASSERT_THAT(BarDecl, NotNull());
6843 
6844         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
6845         EXPECT_THAT(BarLoc, IsNull());
6846       });
6847 }
6848 
6849 TEST(TransferTest, LambdaCaptureWithInitializer) {
6850   std::string Code = R"(
6851     void target(int Bar) {
6852       [Foo=Bar]() {
6853         (void)0;
6854         // [[p]]
6855       }();
6856     }
6857   )";
6858   runDataflowOnLambda(
6859       Code,
6860       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6861          ASTContext &ASTCtx) {
6862         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6863         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6864 
6865         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6866         ASSERT_THAT(FooDecl, NotNull());
6867 
6868         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
6869         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
6870 
6871         const Value *FooVal = Env.getValue(*FooLoc);
6872         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
6873 
6874         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
6875         ASSERT_THAT(BarDecl, NotNull());
6876 
6877         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
6878         EXPECT_THAT(BarLoc, IsNull());
6879       });
6880 }
6881 
6882 TEST(TransferTest, LambdaCaptureByCopyImplicit) {
6883   std::string Code = R"(
6884     void target(int Foo, int Bar) {
6885       [=]() {
6886         Foo;
6887         // [[p]]
6888       }();
6889     }
6890   )";
6891   runDataflowOnLambda(
6892       Code,
6893       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6894          ASTContext &ASTCtx) {
6895         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6896         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6897 
6898         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6899         ASSERT_THAT(FooDecl, NotNull());
6900 
6901         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
6902         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
6903 
6904         const Value *FooVal = Env.getValue(*FooLoc);
6905         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
6906 
6907         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
6908         ASSERT_THAT(BarDecl, NotNull());
6909 
6910         // There is no storage location for `Bar` because it isn't used in the
6911         // body of the lambda.
6912         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
6913         EXPECT_THAT(BarLoc, IsNull());
6914       });
6915 }
6916 
6917 TEST(TransferTest, LambdaCaptureByReferenceImplicit) {
6918   std::string Code = R"(
6919     void target(int Foo, int Bar) {
6920       [&]() {
6921         Foo;
6922         // [[p]]
6923       }();
6924     }
6925   )";
6926   runDataflowOnLambda(
6927       Code,
6928       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6929          ASTContext &ASTCtx) {
6930         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6931         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6932 
6933         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6934         ASSERT_THAT(FooDecl, NotNull());
6935 
6936         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
6937         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
6938 
6939         const Value *FooVal = Env.getValue(*FooLoc);
6940         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
6941 
6942         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
6943         ASSERT_THAT(BarDecl, NotNull());
6944 
6945         // There is no storage location for `Bar` because it isn't used in the
6946         // body of the lambda.
6947         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
6948         EXPECT_THAT(BarLoc, IsNull());
6949       });
6950 }
6951 
6952 TEST(TransferTest, LambdaCaptureThis) {
6953   std::string Code = R"(
6954     struct Bar {
6955       int Foo;
6956 
6957       void target() {
6958         [this]() {
6959           Foo;
6960           // [[p]]
6961         }();
6962       }
6963     };
6964   )";
6965   runDataflowOnLambda(
6966       Code,
6967       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6968          ASTContext &ASTCtx) {
6969         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6970         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6971 
6972         const RecordStorageLocation *ThisPointeeLoc =
6973             Env.getThisPointeeStorageLocation();
6974         ASSERT_THAT(ThisPointeeLoc, NotNull());
6975 
6976         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6977         ASSERT_THAT(FooDecl, NotNull());
6978 
6979         const StorageLocation *FooLoc = ThisPointeeLoc->getChild(*FooDecl);
6980         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
6981 
6982         const Value *FooVal = Env.getValue(*FooLoc);
6983         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
6984       });
6985 }
6986 
6987 // This test verifies correct modeling of a relational dependency that goes
6988 // through unmodeled functions (the simple `cond()` in this case).
6989 TEST(TransferTest, ConditionalRelation) {
6990   std::string Code = R"(
6991     bool cond();
6992     void target() {
6993        bool a = true;
6994        bool b = true;
6995        if (cond()) {
6996          a = false;
6997          if (cond()) {
6998            b = false;
6999          }
7000        }
7001        (void)0;
7002        // [[p]]
7003     }
7004  )";
7005   runDataflow(
7006       Code,
7007       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
7008          ASTContext &ASTCtx) {
7009         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
7010         auto &A = Env.arena();
7011         auto &VarA = getValueForDecl<BoolValue>(ASTCtx, Env, "a").formula();
7012         auto &VarB = getValueForDecl<BoolValue>(ASTCtx, Env, "b").formula();
7013 
7014         EXPECT_FALSE(Env.allows(A.makeAnd(VarA, A.makeNot(VarB))));
7015       });
7016 }
7017 
7018 } // namespace
7019