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