xref: /llvm-project/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp (revision bd9b57de4ff7c65be0d69179232ba2d5fe832195)
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, AggregateInitializationReferenceField) {
2916   std::string Code = R"(
2917     struct S {
2918       int &RefField;
2919     };
2920 
2921     void target(int i) {
2922       S s = { i };
2923       /*[[p]]*/
2924     }
2925   )";
2926   runDataflow(
2927       Code,
2928       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2929          ASTContext &ASTCtx) {
2930         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2931 
2932         const ValueDecl *RefFieldDecl = findValueDecl(ASTCtx, "RefField");
2933 
2934         auto &ILoc = getLocForDecl<StorageLocation>(ASTCtx, Env, "i");
2935         auto &SLoc = getLocForDecl<AggregateStorageLocation>(ASTCtx, Env, "s");
2936 
2937         auto &RefValue =
2938             *cast<ReferenceValue>(getFieldValue(&SLoc, *RefFieldDecl, Env));
2939         EXPECT_EQ(&RefValue.getReferentLoc(), &ILoc);
2940       });
2941 }
2942 
2943 TEST(TransferTest, AssignToUnionMember) {
2944   std::string Code = R"(
2945     union A {
2946       int Foo;
2947     };
2948 
2949     void target(int Bar) {
2950       A Baz;
2951       Baz.Foo = Bar;
2952       // [[p]]
2953     }
2954   )";
2955   runDataflow(
2956       Code,
2957       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2958          ASTContext &ASTCtx) {
2959         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2960         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2961 
2962         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2963         ASSERT_THAT(BazDecl, NotNull());
2964         ASSERT_TRUE(BazDecl->getType()->isUnionType());
2965 
2966         auto BazFields = BazDecl->getType()->getAsRecordDecl()->fields();
2967         FieldDecl *FooDecl = nullptr;
2968         for (FieldDecl *Field : BazFields) {
2969           if (Field->getNameAsString() == "Foo") {
2970             FooDecl = Field;
2971           } else {
2972             FAIL() << "Unexpected field: " << Field->getNameAsString();
2973           }
2974         }
2975         ASSERT_THAT(FooDecl, NotNull());
2976 
2977         const auto *BazLoc = dyn_cast_or_null<AggregateStorageLocation>(
2978             Env.getStorageLocation(*BazDecl));
2979         ASSERT_THAT(BazLoc, NotNull());
2980         ASSERT_THAT(Env.getValue(*BazLoc), NotNull());
2981 
2982         const auto *BazVal = cast<StructValue>(Env.getValue(*BazLoc));
2983         const auto *FooValFromBazVal =
2984             cast<IntegerValue>(getFieldValue(BazVal, *FooDecl, Env));
2985         const auto *FooValFromBazLoc =
2986             cast<IntegerValue>(getFieldValue(BazLoc, *FooDecl, Env));
2987         EXPECT_EQ(FooValFromBazLoc, FooValFromBazVal);
2988 
2989         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2990         ASSERT_THAT(BarDecl, NotNull());
2991         const auto *BarLoc = Env.getStorageLocation(*BarDecl);
2992         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
2993 
2994         EXPECT_EQ(Env.getValue(*BarLoc), FooValFromBazVal);
2995         EXPECT_EQ(Env.getValue(*BarLoc), FooValFromBazLoc);
2996       });
2997 }
2998 
2999 TEST(TransferTest, AssignFromBoolLiteral) {
3000   std::string Code = R"(
3001     void target() {
3002       bool Foo = true;
3003       bool Bar = false;
3004       // [[p]]
3005     }
3006   )";
3007   runDataflow(
3008       Code,
3009       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3010          ASTContext &ASTCtx) {
3011         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3012         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3013 
3014         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3015         ASSERT_THAT(FooDecl, NotNull());
3016 
3017         const auto *FooVal =
3018             dyn_cast_or_null<AtomicBoolValue>(Env.getValue(*FooDecl));
3019         ASSERT_THAT(FooVal, NotNull());
3020 
3021         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3022         ASSERT_THAT(BarDecl, NotNull());
3023 
3024         const auto *BarVal =
3025             dyn_cast_or_null<AtomicBoolValue>(Env.getValue(*BarDecl));
3026         ASSERT_THAT(BarVal, NotNull());
3027 
3028         EXPECT_EQ(FooVal, &Env.getBoolLiteralValue(true));
3029         EXPECT_EQ(BarVal, &Env.getBoolLiteralValue(false));
3030       });
3031 }
3032 
3033 TEST(TransferTest, AssignFromCompositeBoolExpression) {
3034   {
3035     std::string Code = R"(
3036     void target(bool Foo, bool Bar, bool Qux) {
3037       bool Baz = (Foo) && (Bar || Qux);
3038       // [[p]]
3039     }
3040   )";
3041     runDataflow(
3042         Code,
3043         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3044            ASTContext &ASTCtx) {
3045           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3046           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3047 
3048           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3049           ASSERT_THAT(FooDecl, NotNull());
3050 
3051           const auto *FooVal =
3052               dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
3053           ASSERT_THAT(FooVal, NotNull());
3054 
3055           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3056           ASSERT_THAT(BarDecl, NotNull());
3057 
3058           const auto *BarVal =
3059               dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
3060           ASSERT_THAT(BarVal, NotNull());
3061 
3062           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
3063           ASSERT_THAT(QuxDecl, NotNull());
3064 
3065           const auto *QuxVal =
3066               dyn_cast_or_null<BoolValue>(Env.getValue(*QuxDecl));
3067           ASSERT_THAT(QuxVal, NotNull());
3068 
3069           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3070           ASSERT_THAT(BazDecl, NotNull());
3071 
3072           const auto *BazVal =
3073               dyn_cast_or_null<BoolValue>(Env.getValue(*BazDecl));
3074           ASSERT_THAT(BazVal, NotNull());
3075           auto &A = Env.arena();
3076           EXPECT_EQ(&BazVal->formula(),
3077                     &A.makeAnd(FooVal->formula(),
3078                                A.makeOr(BarVal->formula(), QuxVal->formula())));
3079         });
3080   }
3081 
3082   {
3083     std::string Code = R"(
3084     void target(bool Foo, bool Bar, bool Qux) {
3085       bool Baz = (Foo && Qux) || (Bar);
3086       // [[p]]
3087     }
3088   )";
3089     runDataflow(
3090         Code,
3091         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3092            ASTContext &ASTCtx) {
3093           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3094           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3095 
3096           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3097           ASSERT_THAT(FooDecl, NotNull());
3098 
3099           const auto *FooVal =
3100               dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
3101           ASSERT_THAT(FooVal, NotNull());
3102 
3103           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3104           ASSERT_THAT(BarDecl, NotNull());
3105 
3106           const auto *BarVal =
3107               dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
3108           ASSERT_THAT(BarVal, NotNull());
3109 
3110           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
3111           ASSERT_THAT(QuxDecl, NotNull());
3112 
3113           const auto *QuxVal =
3114               dyn_cast_or_null<BoolValue>(Env.getValue(*QuxDecl));
3115           ASSERT_THAT(QuxVal, NotNull());
3116 
3117           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3118           ASSERT_THAT(BazDecl, NotNull());
3119 
3120           const auto *BazVal =
3121               dyn_cast_or_null<BoolValue>(Env.getValue(*BazDecl));
3122           ASSERT_THAT(BazVal, NotNull());
3123           auto &A = Env.arena();
3124           EXPECT_EQ(&BazVal->formula(),
3125                     &A.makeOr(A.makeAnd(FooVal->formula(), QuxVal->formula()),
3126                               BarVal->formula()));
3127         });
3128   }
3129 
3130   {
3131     std::string Code = R"(
3132       void target(bool A, bool B, bool C, bool D) {
3133         bool Foo = ((A && B) && C) && D;
3134         // [[p]]
3135       }
3136     )";
3137     runDataflow(
3138         Code,
3139         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3140            ASTContext &ASTCtx) {
3141           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3142           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3143 
3144           const ValueDecl *ADecl = findValueDecl(ASTCtx, "A");
3145           ASSERT_THAT(ADecl, NotNull());
3146 
3147           const auto *AVal = dyn_cast_or_null<BoolValue>(Env.getValue(*ADecl));
3148           ASSERT_THAT(AVal, NotNull());
3149 
3150           const ValueDecl *BDecl = findValueDecl(ASTCtx, "B");
3151           ASSERT_THAT(BDecl, NotNull());
3152 
3153           const auto *BVal = dyn_cast_or_null<BoolValue>(Env.getValue(*BDecl));
3154           ASSERT_THAT(BVal, NotNull());
3155 
3156           const ValueDecl *CDecl = findValueDecl(ASTCtx, "C");
3157           ASSERT_THAT(CDecl, NotNull());
3158 
3159           const auto *CVal = dyn_cast_or_null<BoolValue>(Env.getValue(*CDecl));
3160           ASSERT_THAT(CVal, NotNull());
3161 
3162           const ValueDecl *DDecl = findValueDecl(ASTCtx, "D");
3163           ASSERT_THAT(DDecl, NotNull());
3164 
3165           const auto *DVal = dyn_cast_or_null<BoolValue>(Env.getValue(*DDecl));
3166           ASSERT_THAT(DVal, NotNull());
3167 
3168           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3169           ASSERT_THAT(FooDecl, NotNull());
3170 
3171           const auto *FooVal =
3172               dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
3173           ASSERT_THAT(FooVal, NotNull());
3174           auto &A = Env.arena();
3175           EXPECT_EQ(
3176               &FooVal->formula(),
3177               &A.makeAnd(A.makeAnd(A.makeAnd(AVal->formula(), BVal->formula()),
3178                                    CVal->formula()),
3179                          DVal->formula()));
3180         });
3181   }
3182 }
3183 
3184 TEST(TransferTest, AssignFromBoolNegation) {
3185   std::string Code = R"(
3186     void target() {
3187       bool Foo = true;
3188       bool Bar = !(Foo);
3189       // [[p]]
3190     }
3191   )";
3192   runDataflow(
3193       Code,
3194       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3195          ASTContext &ASTCtx) {
3196         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3197         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3198 
3199         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3200         ASSERT_THAT(FooDecl, NotNull());
3201 
3202         const auto *FooVal =
3203             dyn_cast_or_null<AtomicBoolValue>(Env.getValue(*FooDecl));
3204         ASSERT_THAT(FooVal, NotNull());
3205 
3206         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3207         ASSERT_THAT(BarDecl, NotNull());
3208 
3209         const auto *BarVal =
3210             dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
3211         ASSERT_THAT(BarVal, NotNull());
3212         auto &A = Env.arena();
3213         EXPECT_EQ(&BarVal->formula(), &A.makeNot(FooVal->formula()));
3214       });
3215 }
3216 
3217 TEST(TransferTest, BuiltinExpect) {
3218   std::string Code = R"(
3219     void target(long Foo) {
3220       long Bar = __builtin_expect(Foo, true);
3221       /*[[p]]*/
3222     }
3223   )";
3224   runDataflow(
3225       Code,
3226       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3227          ASTContext &ASTCtx) {
3228         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3229         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3230 
3231         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3232         ASSERT_THAT(FooDecl, NotNull());
3233 
3234         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3235         ASSERT_THAT(BarDecl, NotNull());
3236 
3237         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
3238       });
3239 }
3240 
3241 // `__builtin_expect` takes and returns a `long` argument, so other types
3242 // involve casts. This verifies that we identify the input and output in that
3243 // case.
3244 TEST(TransferTest, BuiltinExpectBoolArg) {
3245   std::string Code = R"(
3246     void target(bool Foo) {
3247       bool Bar = __builtin_expect(Foo, true);
3248       /*[[p]]*/
3249     }
3250   )";
3251   runDataflow(
3252       Code,
3253       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3254          ASTContext &ASTCtx) {
3255         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3256         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3257 
3258         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3259         ASSERT_THAT(FooDecl, NotNull());
3260 
3261         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3262         ASSERT_THAT(BarDecl, NotNull());
3263 
3264         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
3265       });
3266 }
3267 
3268 TEST(TransferTest, BuiltinUnreachable) {
3269   std::string Code = R"(
3270     void target(bool Foo) {
3271       bool Bar = false;
3272       if (Foo)
3273         Bar = Foo;
3274       else
3275         __builtin_unreachable();
3276       (void)0;
3277       /*[[p]]*/
3278     }
3279   )";
3280   runDataflow(
3281       Code,
3282       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3283          ASTContext &ASTCtx) {
3284         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3285         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3286 
3287         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3288         ASSERT_THAT(FooDecl, NotNull());
3289 
3290         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3291         ASSERT_THAT(BarDecl, NotNull());
3292 
3293         // `__builtin_unreachable` promises that the code is
3294         // unreachable, so the compiler treats the "then" branch as the
3295         // only possible predecessor of this statement.
3296         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
3297       });
3298 }
3299 
3300 TEST(TransferTest, BuiltinTrap) {
3301   std::string Code = R"(
3302     void target(bool Foo) {
3303       bool Bar = false;
3304       if (Foo)
3305         Bar = Foo;
3306       else
3307         __builtin_trap();
3308       (void)0;
3309       /*[[p]]*/
3310     }
3311   )";
3312   runDataflow(
3313       Code,
3314       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3315          ASTContext &ASTCtx) {
3316         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3317         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3318 
3319         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3320         ASSERT_THAT(FooDecl, NotNull());
3321 
3322         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3323         ASSERT_THAT(BarDecl, NotNull());
3324 
3325         // `__builtin_trap` ensures program termination, so only the
3326         // "then" branch is a predecessor of this statement.
3327         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
3328       });
3329 }
3330 
3331 TEST(TransferTest, BuiltinDebugTrap) {
3332   std::string Code = R"(
3333     void target(bool Foo) {
3334       bool Bar = false;
3335       if (Foo)
3336         Bar = Foo;
3337       else
3338         __builtin_debugtrap();
3339       (void)0;
3340       /*[[p]]*/
3341     }
3342   )";
3343   runDataflow(
3344       Code,
3345       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3346          ASTContext &ASTCtx) {
3347         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3348         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3349 
3350         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3351         ASSERT_THAT(FooDecl, NotNull());
3352 
3353         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3354         ASSERT_THAT(BarDecl, NotNull());
3355 
3356         // `__builtin_debugtrap` doesn't ensure program termination.
3357         EXPECT_NE(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
3358       });
3359 }
3360 
3361 TEST(TransferTest, StaticIntSingleVarDecl) {
3362   std::string Code = R"(
3363     void target() {
3364       static int Foo;
3365       // [[p]]
3366     }
3367   )";
3368   runDataflow(
3369       Code,
3370       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3371          ASTContext &ASTCtx) {
3372         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3373         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3374 
3375         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3376         ASSERT_THAT(FooDecl, NotNull());
3377 
3378         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
3379         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
3380 
3381         const Value *FooVal = Env.getValue(*FooLoc);
3382         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
3383       });
3384 }
3385 
3386 TEST(TransferTest, StaticIntGroupVarDecl) {
3387   std::string Code = R"(
3388     void target() {
3389       static int Foo, Bar;
3390       (void)0;
3391       // [[p]]
3392     }
3393   )";
3394   runDataflow(
3395       Code,
3396       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3397          ASTContext &ASTCtx) {
3398         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3399         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3400 
3401         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3402         ASSERT_THAT(FooDecl, NotNull());
3403 
3404         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3405         ASSERT_THAT(BarDecl, NotNull());
3406 
3407         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
3408         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
3409 
3410         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
3411         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
3412 
3413         const Value *FooVal = Env.getValue(*FooLoc);
3414         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
3415 
3416         const Value *BarVal = Env.getValue(*BarLoc);
3417         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
3418 
3419         EXPECT_NE(FooVal, BarVal);
3420       });
3421 }
3422 
3423 TEST(TransferTest, GlobalIntVarDecl) {
3424   std::string Code = R"(
3425     static int Foo;
3426 
3427     void target() {
3428       int Bar = Foo;
3429       int Baz = Foo;
3430       // [[p]]
3431     }
3432   )";
3433   runDataflow(
3434       Code,
3435       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3436          ASTContext &ASTCtx) {
3437         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3438         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3439 
3440         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3441         ASSERT_THAT(BarDecl, NotNull());
3442 
3443         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3444         ASSERT_THAT(BazDecl, NotNull());
3445 
3446         const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
3447         const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl));
3448         EXPECT_EQ(BarVal, BazVal);
3449       });
3450 }
3451 
3452 TEST(TransferTest, StaticMemberIntVarDecl) {
3453   std::string Code = R"(
3454     struct A {
3455       static int Foo;
3456     };
3457 
3458     void target(A a) {
3459       int Bar = a.Foo;
3460       int Baz = a.Foo;
3461       // [[p]]
3462     }
3463   )";
3464   runDataflow(
3465       Code,
3466       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3467          ASTContext &ASTCtx) {
3468         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3469         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3470 
3471         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3472         ASSERT_THAT(BarDecl, NotNull());
3473 
3474         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3475         ASSERT_THAT(BazDecl, NotNull());
3476 
3477         const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
3478         const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl));
3479         EXPECT_EQ(BarVal, BazVal);
3480       });
3481 }
3482 
3483 TEST(TransferTest, StaticMemberRefVarDecl) {
3484   std::string Code = R"(
3485     struct A {
3486       static int &Foo;
3487     };
3488 
3489     void target(A a) {
3490       int Bar = a.Foo;
3491       int Baz = a.Foo;
3492       // [[p]]
3493     }
3494   )";
3495   runDataflow(
3496       Code,
3497       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3498          ASTContext &ASTCtx) {
3499         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3500         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3501 
3502         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3503         ASSERT_THAT(BarDecl, NotNull());
3504 
3505         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3506         ASSERT_THAT(BazDecl, NotNull());
3507 
3508         const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
3509         const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl));
3510         EXPECT_EQ(BarVal, BazVal);
3511       });
3512 }
3513 
3514 TEST(TransferTest, AssignMemberBeforeCopy) {
3515   std::string Code = R"(
3516     struct A {
3517       int Foo;
3518     };
3519 
3520     void target() {
3521       A A1;
3522       A A2;
3523       int Bar;
3524       A1.Foo = Bar;
3525       A2 = A1;
3526       // [[p]]
3527     }
3528   )";
3529   runDataflow(
3530       Code,
3531       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3532          ASTContext &ASTCtx) {
3533         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3534         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3535 
3536         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3537         ASSERT_THAT(FooDecl, NotNull());
3538 
3539         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3540         ASSERT_THAT(BarDecl, NotNull());
3541 
3542         const ValueDecl *A1Decl = findValueDecl(ASTCtx, "A1");
3543         ASSERT_THAT(A1Decl, NotNull());
3544 
3545         const ValueDecl *A2Decl = findValueDecl(ASTCtx, "A2");
3546         ASSERT_THAT(A2Decl, NotNull());
3547 
3548         const auto *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
3549 
3550         const auto *A2Val = cast<StructValue>(Env.getValue(*A2Decl));
3551         EXPECT_EQ(getFieldValue(A2Val, *FooDecl, Env), BarVal);
3552       });
3553 }
3554 
3555 TEST(TransferTest, BooleanEquality) {
3556   std::string Code = R"(
3557     void target(bool Bar) {
3558       bool Foo = true;
3559       if (Bar == Foo) {
3560         (void)0;
3561         /*[[p-then]]*/
3562       } else {
3563         (void)0;
3564         /*[[p-else]]*/
3565       }
3566     }
3567   )";
3568   runDataflow(
3569       Code,
3570       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3571          ASTContext &ASTCtx) {
3572         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-then", "p-else"));
3573         const Environment &EnvThen =
3574             getEnvironmentAtAnnotation(Results, "p-then");
3575         const Environment &EnvElse =
3576             getEnvironmentAtAnnotation(Results, "p-else");
3577 
3578         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3579         ASSERT_THAT(BarDecl, NotNull());
3580 
3581         auto &BarValThen = *cast<BoolValue>(EnvThen.getValue(*BarDecl));
3582         EXPECT_TRUE(EnvThen.flowConditionImplies(BarValThen));
3583 
3584         auto &BarValElse = *cast<BoolValue>(EnvElse.getValue(*BarDecl));
3585         EXPECT_FALSE(EnvElse.flowConditionImplies(BarValElse));
3586       });
3587 }
3588 
3589 TEST(TransferTest, BooleanInequality) {
3590   std::string Code = R"(
3591     void target(bool Bar) {
3592       bool Foo = true;
3593       if (Bar != Foo) {
3594         (void)0;
3595         /*[[p-then]]*/
3596       } else {
3597         (void)0;
3598         /*[[p-else]]*/
3599       }
3600     }
3601   )";
3602   runDataflow(
3603       Code,
3604       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3605          ASTContext &ASTCtx) {
3606         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-then", "p-else"));
3607         const Environment &EnvThen =
3608             getEnvironmentAtAnnotation(Results, "p-then");
3609         const Environment &EnvElse =
3610             getEnvironmentAtAnnotation(Results, "p-else");
3611 
3612         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3613         ASSERT_THAT(BarDecl, NotNull());
3614 
3615         auto &BarValThen = *cast<BoolValue>(EnvThen.getValue(*BarDecl));
3616         EXPECT_FALSE(EnvThen.flowConditionImplies(BarValThen));
3617 
3618         auto &BarValElse = *cast<BoolValue>(EnvElse.getValue(*BarDecl));
3619         EXPECT_TRUE(EnvElse.flowConditionImplies(BarValElse));
3620       });
3621 }
3622 
3623 TEST(TransferTest, IntegerLiteralEquality) {
3624   std::string Code = R"(
3625     void target() {
3626       bool equal = (42 == 42);
3627       // [[p]]
3628     }
3629   )";
3630   runDataflow(
3631       Code,
3632       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3633          ASTContext &ASTCtx) {
3634         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3635 
3636         auto &Equal = getValueForDecl<BoolValue>(ASTCtx, Env, "equal");
3637         EXPECT_TRUE(Env.flowConditionImplies(Equal));
3638       });
3639 }
3640 
3641 TEST(TransferTest, CorrelatedBranches) {
3642   std::string Code = R"(
3643     void target(bool B, bool C) {
3644       if (B) {
3645         return;
3646       }
3647       (void)0;
3648       /*[[p0]]*/
3649       if (C) {
3650         B = true;
3651         /*[[p1]]*/
3652       }
3653       if (B) {
3654         (void)0;
3655         /*[[p2]]*/
3656       }
3657     }
3658   )";
3659   runDataflow(
3660       Code,
3661       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3662          ASTContext &ASTCtx) {
3663         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p0", "p1", "p2"));
3664 
3665         const ValueDecl *CDecl = findValueDecl(ASTCtx, "C");
3666         ASSERT_THAT(CDecl, NotNull());
3667 
3668         {
3669           const Environment &Env = getEnvironmentAtAnnotation(Results, "p0");
3670           const ValueDecl *BDecl = findValueDecl(ASTCtx, "B");
3671           ASSERT_THAT(BDecl, NotNull());
3672           auto &BVal = *cast<BoolValue>(Env.getValue(*BDecl));
3673 
3674           EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BVal)));
3675         }
3676 
3677         {
3678           const Environment &Env = getEnvironmentAtAnnotation(Results, "p1");
3679           auto &CVal = *cast<BoolValue>(Env.getValue(*CDecl));
3680           EXPECT_TRUE(Env.flowConditionImplies(CVal));
3681         }
3682 
3683         {
3684           const Environment &Env = getEnvironmentAtAnnotation(Results, "p2");
3685           auto &CVal = *cast<BoolValue>(Env.getValue(*CDecl));
3686           EXPECT_TRUE(Env.flowConditionImplies(CVal));
3687         }
3688       });
3689 }
3690 
3691 TEST(TransferTest, LoopWithAssignmentConverges) {
3692   std::string Code = R"(
3693     bool foo();
3694 
3695     void target() {
3696        do {
3697         bool Bar = foo();
3698         if (Bar) break;
3699         (void)Bar;
3700         /*[[p]]*/
3701       } while (true);
3702     }
3703   )";
3704   // The key property that we are verifying is implicit in `runDataflow` --
3705   // namely, that the analysis succeeds, rather than hitting the maximum number
3706   // of iterations.
3707   runDataflow(
3708       Code,
3709       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3710          ASTContext &ASTCtx) {
3711         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3712         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3713 
3714         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3715         ASSERT_THAT(BarDecl, NotNull());
3716 
3717         auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl));
3718         EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal)));
3719       });
3720 }
3721 
3722 TEST(TransferTest, LoopWithStagedAssignments) {
3723   std::string Code = R"(
3724     bool foo();
3725 
3726     void target() {
3727       bool Bar = false;
3728       bool Err = false;
3729       while (foo()) {
3730         if (Bar)
3731           Err = true;
3732         Bar = true;
3733         /*[[p]]*/
3734       }
3735     }
3736   )";
3737   runDataflow(
3738       Code,
3739       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3740          ASTContext &ASTCtx) {
3741         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3742         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3743 
3744         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3745         ASSERT_THAT(BarDecl, NotNull());
3746         const ValueDecl *ErrDecl = findValueDecl(ASTCtx, "Err");
3747         ASSERT_THAT(ErrDecl, NotNull());
3748 
3749         auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl));
3750         auto &ErrVal = *cast<BoolValue>(Env.getValue(*ErrDecl));
3751         EXPECT_TRUE(Env.flowConditionImplies(BarVal));
3752         // An unsound analysis, for example only evaluating the loop once, can
3753         // conclude that `Err` is false. So, we test that this conclusion is not
3754         // reached.
3755         EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(ErrVal)));
3756       });
3757 }
3758 
3759 TEST(TransferTest, LoopWithReferenceAssignmentConverges) {
3760   std::string Code = R"(
3761     bool &foo();
3762 
3763     void target() {
3764        do {
3765         bool& Bar = foo();
3766         if (Bar) break;
3767         (void)Bar;
3768         /*[[p]]*/
3769       } while (true);
3770     }
3771   )";
3772   // The key property that we are verifying is that the analysis succeeds,
3773   // rather than hitting the maximum number of iterations.
3774   runDataflow(
3775       Code,
3776       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3777          ASTContext &ASTCtx) {
3778         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3779         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3780 
3781         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3782         ASSERT_THAT(BarDecl, NotNull());
3783 
3784         auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl));
3785         EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal)));
3786       });
3787 }
3788 
3789 TEST(TransferTest, LoopWithStructReferenceAssignmentConverges) {
3790   std::string Code = R"(
3791     struct Lookup {
3792       int x;
3793     };
3794 
3795     void target(Lookup val, bool b) {
3796       const Lookup* l = nullptr;
3797       while (b) {
3798         l = &val;
3799         /*[[p-inner]]*/
3800       }
3801       (void)0;
3802       /*[[p-outer]]*/
3803     }
3804   )";
3805   // The key property that we are verifying is implicit in `runDataflow` --
3806   // namely, that the analysis succeeds, rather than hitting the maximum number
3807   // of iterations.
3808   runDataflow(
3809       Code,
3810       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3811          ASTContext &ASTCtx) {
3812         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-inner", "p-outer"));
3813         const Environment &InnerEnv =
3814             getEnvironmentAtAnnotation(Results, "p-inner");
3815         const Environment &OuterEnv =
3816             getEnvironmentAtAnnotation(Results, "p-outer");
3817 
3818         const ValueDecl *ValDecl = findValueDecl(ASTCtx, "val");
3819         ASSERT_THAT(ValDecl, NotNull());
3820 
3821         const ValueDecl *LDecl = findValueDecl(ASTCtx, "l");
3822         ASSERT_THAT(LDecl, NotNull());
3823 
3824         // Inner.
3825         auto *LVal = dyn_cast<PointerValue>(InnerEnv.getValue(*LDecl));
3826         ASSERT_THAT(LVal, NotNull());
3827 
3828         EXPECT_EQ(&LVal->getPointeeLoc(),
3829                   InnerEnv.getStorageLocation(*ValDecl));
3830 
3831         // Outer.
3832         LVal = dyn_cast<PointerValue>(OuterEnv.getValue(*LDecl));
3833         ASSERT_THAT(LVal, NotNull());
3834 
3835         // The loop body may not have been executed, so we should not conclude
3836         // that `l` points to `val`.
3837         EXPECT_NE(&LVal->getPointeeLoc(),
3838                   OuterEnv.getStorageLocation(*ValDecl));
3839       });
3840 }
3841 
3842 TEST(TransferTest, DoesNotCrashOnUnionThisExpr) {
3843   std::string Code = R"(
3844     union Union {
3845       int A;
3846       float B;
3847     };
3848 
3849     void foo() {
3850       Union A;
3851       Union B;
3852       A = B;
3853     }
3854   )";
3855   // This is a crash regression test when calling the transfer function on a
3856   // `CXXThisExpr` that refers to a union.
3857   runDataflow(
3858       Code,
3859       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &,
3860          ASTContext &) {},
3861       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator=");
3862 }
3863 
3864 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToRefs) {
3865   std::string Code = R"(
3866     struct A {
3867       int Foo;
3868       int Bar;
3869     };
3870 
3871     void target() {
3872       int Qux;
3873       A Baz;
3874       Baz.Foo = Qux;
3875       auto &FooRef = Baz.Foo;
3876       auto &BarRef = Baz.Bar;
3877       auto &[BoundFooRef, BoundBarRef] = Baz;
3878       // [[p]]
3879     }
3880   )";
3881   runDataflow(
3882       Code,
3883       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3884          ASTContext &ASTCtx) {
3885         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3886         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3887 
3888         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
3889         ASSERT_THAT(FooRefDecl, NotNull());
3890 
3891         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
3892         ASSERT_THAT(BarRefDecl, NotNull());
3893 
3894         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
3895         ASSERT_THAT(QuxDecl, NotNull());
3896 
3897         const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef");
3898         ASSERT_THAT(BoundFooRefDecl, NotNull());
3899 
3900         const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef");
3901         ASSERT_THAT(BoundBarRefDecl, NotNull());
3902 
3903         const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl);
3904         ASSERT_THAT(FooRefLoc, NotNull());
3905 
3906         const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl);
3907         ASSERT_THAT(BarRefLoc, NotNull());
3908 
3909         const Value *QuxVal = Env.getValue(*QuxDecl);
3910         ASSERT_THAT(QuxVal, NotNull());
3911 
3912         const StorageLocation *BoundFooRefLoc =
3913             Env.getStorageLocation(*BoundFooRefDecl);
3914         EXPECT_EQ(BoundFooRefLoc, FooRefLoc);
3915 
3916         const StorageLocation *BoundBarRefLoc =
3917             Env.getStorageLocation(*BoundBarRefDecl);
3918         EXPECT_EQ(BoundBarRefLoc, BarRefLoc);
3919 
3920         EXPECT_EQ(Env.getValue(*BoundFooRefDecl), QuxVal);
3921       });
3922 }
3923 
3924 TEST(TransferTest, StructuredBindingAssignFromStructRefMembersToRefs) {
3925   std::string Code = R"(
3926     struct A {
3927       int &Foo;
3928       int &Bar;
3929     };
3930 
3931     void target(A Baz) {
3932       int Qux;
3933       Baz.Foo = Qux;
3934       auto &FooRef = Baz.Foo;
3935       auto &BarRef = Baz.Bar;
3936       auto &[BoundFooRef, BoundBarRef] = Baz;
3937       // [[p]]
3938     }
3939   )";
3940   runDataflow(
3941       Code,
3942       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3943          ASTContext &ASTCtx) {
3944         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3945         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3946 
3947         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
3948         ASSERT_THAT(FooRefDecl, NotNull());
3949 
3950         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
3951         ASSERT_THAT(BarRefDecl, NotNull());
3952 
3953         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
3954         ASSERT_THAT(QuxDecl, NotNull());
3955 
3956         const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef");
3957         ASSERT_THAT(BoundFooRefDecl, NotNull());
3958 
3959         const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef");
3960         ASSERT_THAT(BoundBarRefDecl, NotNull());
3961 
3962         const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl);
3963         ASSERT_THAT(FooRefLoc, NotNull());
3964 
3965         const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl);
3966         ASSERT_THAT(BarRefLoc, NotNull());
3967 
3968         const Value *QuxVal = Env.getValue(*QuxDecl);
3969         ASSERT_THAT(QuxVal, NotNull());
3970 
3971         const StorageLocation *BoundFooRefLoc =
3972             Env.getStorageLocation(*BoundFooRefDecl);
3973         EXPECT_EQ(BoundFooRefLoc, FooRefLoc);
3974 
3975         const StorageLocation *BoundBarRefLoc =
3976             Env.getStorageLocation(*BoundBarRefDecl);
3977         EXPECT_EQ(BoundBarRefLoc, BarRefLoc);
3978 
3979         EXPECT_EQ(Env.getValue(*BoundFooRefDecl), QuxVal);
3980       });
3981 }
3982 
3983 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToInts) {
3984   std::string Code = R"(
3985     struct A {
3986       int Foo;
3987       int Bar;
3988     };
3989 
3990     void target() {
3991       int Qux;
3992       A Baz;
3993       Baz.Foo = Qux;
3994       auto &FooRef = Baz.Foo;
3995       auto &BarRef = Baz.Bar;
3996       auto [BoundFoo, BoundBar] = Baz;
3997       // [[p]]
3998     }
3999   )";
4000   runDataflow(
4001       Code,
4002       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4003          ASTContext &ASTCtx) {
4004         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4005         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4006 
4007         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
4008         ASSERT_THAT(FooRefDecl, NotNull());
4009 
4010         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
4011         ASSERT_THAT(BarRefDecl, NotNull());
4012 
4013         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
4014         ASSERT_THAT(BoundFooDecl, NotNull());
4015 
4016         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
4017         ASSERT_THAT(BoundBarDecl, NotNull());
4018 
4019         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
4020         ASSERT_THAT(QuxDecl, NotNull());
4021 
4022         const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl);
4023         ASSERT_THAT(FooRefLoc, NotNull());
4024 
4025         const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl);
4026         ASSERT_THAT(BarRefLoc, NotNull());
4027 
4028         const Value *QuxVal = Env.getValue(*QuxDecl);
4029         ASSERT_THAT(QuxVal, NotNull());
4030 
4031         const StorageLocation *BoundFooLoc =
4032             Env.getStorageLocation(*BoundFooDecl);
4033         EXPECT_NE(BoundFooLoc, FooRefLoc);
4034 
4035         const StorageLocation *BoundBarLoc =
4036             Env.getStorageLocation(*BoundBarDecl);
4037         EXPECT_NE(BoundBarLoc, BarRefLoc);
4038 
4039         EXPECT_EQ(Env.getValue(*BoundFooDecl), QuxVal);
4040       });
4041 }
4042 
4043 TEST(TransferTest, StructuredBindingAssignFromTupleLikeType) {
4044   std::string Code = R"(
4045     namespace std {
4046     using size_t = int;
4047     template <class> struct tuple_size;
4048     template <std::size_t, class> struct tuple_element;
4049     template <class...> class tuple;
4050 
4051     namespace {
4052     template <class T, T v>
4053     struct size_helper { static const T value = v; };
4054     } // namespace
4055 
4056     template <class... T>
4057     struct tuple_size<tuple<T...>> : size_helper<std::size_t, sizeof...(T)> {};
4058 
4059     template <std::size_t I, class... T>
4060     struct tuple_element<I, tuple<T...>> {
4061       using type =  __type_pack_element<I, T...>;
4062     };
4063 
4064     template <class...> class tuple {};
4065 
4066     template <std::size_t I, class... T>
4067     typename tuple_element<I, tuple<T...>>::type get(tuple<T...>);
4068     } // namespace std
4069 
4070     std::tuple<bool, int> makeTuple();
4071 
4072     void target(bool B) {
4073       auto [BoundFoo, BoundBar] = makeTuple();
4074       bool Baz;
4075       // Include if-then-else to test interaction of `BindingDecl` with join.
4076       if (B) {
4077         Baz = BoundFoo;
4078         (void)BoundBar;
4079         // [[p1]]
4080       } else {
4081         Baz = BoundFoo;
4082       }
4083       (void)0;
4084       // [[p2]]
4085     }
4086   )";
4087   runDataflow(
4088       Code,
4089       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4090          ASTContext &ASTCtx) {
4091         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
4092         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
4093 
4094         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
4095         ASSERT_THAT(BoundFooDecl, NotNull());
4096 
4097         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
4098         ASSERT_THAT(BoundBarDecl, NotNull());
4099 
4100         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4101         ASSERT_THAT(BazDecl, NotNull());
4102 
4103         // BindingDecls always map to references -- either lvalue or rvalue, so
4104         // we still need to skip here.
4105         const Value *BoundFooValue = Env1.getValue(*BoundFooDecl);
4106         ASSERT_THAT(BoundFooValue, NotNull());
4107         EXPECT_TRUE(isa<BoolValue>(BoundFooValue));
4108 
4109         const Value *BoundBarValue = Env1.getValue(*BoundBarDecl);
4110         ASSERT_THAT(BoundBarValue, NotNull());
4111         EXPECT_TRUE(isa<IntegerValue>(BoundBarValue));
4112 
4113         // Test that a `DeclRefExpr` to a `BindingDecl` works as expected.
4114         EXPECT_EQ(Env1.getValue(*BazDecl), BoundFooValue);
4115 
4116         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
4117 
4118         // Test that `BoundFooDecl` retains the value we expect, after the join.
4119         BoundFooValue = Env2.getValue(*BoundFooDecl);
4120         EXPECT_EQ(Env2.getValue(*BazDecl), BoundFooValue);
4121       });
4122 }
4123 
4124 TEST(TransferTest, StructuredBindingAssignRefFromTupleLikeType) {
4125   std::string Code = R"(
4126     namespace std {
4127     using size_t = int;
4128     template <class> struct tuple_size;
4129     template <std::size_t, class> struct tuple_element;
4130     template <class...> class tuple;
4131 
4132     namespace {
4133     template <class T, T v>
4134     struct size_helper { static const T value = v; };
4135     } // namespace
4136 
4137     template <class... T>
4138     struct tuple_size<tuple<T...>> : size_helper<std::size_t, sizeof...(T)> {};
4139 
4140     template <std::size_t I, class... T>
4141     struct tuple_element<I, tuple<T...>> {
4142       using type =  __type_pack_element<I, T...>;
4143     };
4144 
4145     template <class...> class tuple {};
4146 
4147     template <std::size_t I, class... T>
4148     typename tuple_element<I, tuple<T...>>::type get(tuple<T...>);
4149     } // namespace std
4150 
4151     std::tuple<bool, int> &getTuple();
4152 
4153     void target(bool B) {
4154       auto &[BoundFoo, BoundBar] = getTuple();
4155       bool Baz;
4156       // Include if-then-else to test interaction of `BindingDecl` with join.
4157       if (B) {
4158         Baz = BoundFoo;
4159         (void)BoundBar;
4160         // [[p1]]
4161       } else {
4162         Baz = BoundFoo;
4163       }
4164       (void)0;
4165       // [[p2]]
4166     }
4167   )";
4168   runDataflow(
4169       Code,
4170       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4171          ASTContext &ASTCtx) {
4172         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
4173         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
4174 
4175         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
4176         ASSERT_THAT(BoundFooDecl, NotNull());
4177 
4178         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
4179         ASSERT_THAT(BoundBarDecl, NotNull());
4180 
4181         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4182         ASSERT_THAT(BazDecl, NotNull());
4183 
4184         const Value *BoundFooValue = Env1.getValue(*BoundFooDecl);
4185         ASSERT_THAT(BoundFooValue, NotNull());
4186         EXPECT_TRUE(isa<BoolValue>(BoundFooValue));
4187 
4188         const Value *BoundBarValue = Env1.getValue(*BoundBarDecl);
4189         ASSERT_THAT(BoundBarValue, NotNull());
4190         EXPECT_TRUE(isa<IntegerValue>(BoundBarValue));
4191 
4192         // Test that a `DeclRefExpr` to a `BindingDecl` (with reference type)
4193         // works as expected. We don't test aliasing properties of the
4194         // reference, because we don't model `std::get` and so have no way to
4195         // equate separate references into the tuple.
4196         EXPECT_EQ(Env1.getValue(*BazDecl), BoundFooValue);
4197 
4198         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
4199 
4200         // Test that `BoundFooDecl` retains the value we expect, after the join.
4201         BoundFooValue = Env2.getValue(*BoundFooDecl);
4202         EXPECT_EQ(Env2.getValue(*BazDecl), BoundFooValue);
4203       });
4204 }
4205 
4206 TEST(TransferTest, BinaryOperatorComma) {
4207   std::string Code = R"(
4208     void target(int Foo, int Bar) {
4209       int &Baz = (Foo, Bar);
4210       // [[p]]
4211     }
4212   )";
4213   runDataflow(
4214       Code,
4215       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4216          ASTContext &ASTCtx) {
4217         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4218         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4219 
4220         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4221         ASSERT_THAT(BarDecl, NotNull());
4222 
4223         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4224         ASSERT_THAT(BazDecl, NotNull());
4225 
4226         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
4227         ASSERT_THAT(BarLoc, NotNull());
4228 
4229         const StorageLocation *BazLoc = Env.getStorageLocation(*BazDecl);
4230         EXPECT_EQ(BazLoc, BarLoc);
4231       });
4232 }
4233 
4234 TEST(TransferTest, IfStmtBranchExtendsFlowCondition) {
4235   std::string Code = R"(
4236     void target(bool Foo) {
4237       if (Foo) {
4238         (void)0;
4239         // [[if_then]]
4240       } else {
4241         (void)0;
4242         // [[if_else]]
4243       }
4244     }
4245   )";
4246   runDataflow(
4247       Code,
4248       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4249          ASTContext &ASTCtx) {
4250         ASSERT_THAT(Results.keys(), UnorderedElementsAre("if_then", "if_else"));
4251         const Environment &ThenEnv =
4252             getEnvironmentAtAnnotation(Results, "if_then");
4253         const Environment &ElseEnv =
4254             getEnvironmentAtAnnotation(Results, "if_else");
4255 
4256         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4257         ASSERT_THAT(FooDecl, NotNull());
4258 
4259         BoolValue &ThenFooVal = *cast<BoolValue>(ThenEnv.getValue(*FooDecl));
4260         EXPECT_TRUE(ThenEnv.flowConditionImplies(ThenFooVal));
4261 
4262         BoolValue &ElseFooVal = *cast<BoolValue>(ElseEnv.getValue(*FooDecl));
4263         EXPECT_TRUE(ElseEnv.flowConditionImplies(ElseEnv.makeNot(ElseFooVal)));
4264       });
4265 }
4266 
4267 TEST(TransferTest, WhileStmtBranchExtendsFlowCondition) {
4268   std::string Code = R"(
4269     void target(bool Foo) {
4270       while (Foo) {
4271         (void)0;
4272         // [[loop_body]]
4273       }
4274       (void)0;
4275       // [[after_loop]]
4276     }
4277   )";
4278   runDataflow(
4279       Code,
4280       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4281          ASTContext &ASTCtx) {
4282         ASSERT_THAT(Results.keys(),
4283                     UnorderedElementsAre("loop_body", "after_loop"));
4284         const Environment &LoopBodyEnv =
4285             getEnvironmentAtAnnotation(Results, "loop_body");
4286         const Environment &AfterLoopEnv =
4287             getEnvironmentAtAnnotation(Results, "after_loop");
4288 
4289         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4290         ASSERT_THAT(FooDecl, NotNull());
4291 
4292         BoolValue &LoopBodyFooVal =
4293             *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl));
4294         EXPECT_TRUE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal));
4295 
4296         BoolValue &AfterLoopFooVal =
4297             *cast<BoolValue>(AfterLoopEnv.getValue(*FooDecl));
4298         EXPECT_TRUE(AfterLoopEnv.flowConditionImplies(
4299             AfterLoopEnv.makeNot(AfterLoopFooVal)));
4300       });
4301 }
4302 
4303 TEST(TransferTest, DoWhileStmtBranchExtendsFlowCondition) {
4304   std::string Code = R"(
4305     void target(bool Foo) {
4306       bool Bar = true;
4307       do {
4308         (void)0;
4309         // [[loop_body]]
4310         Bar = false;
4311       } while (Foo);
4312       (void)0;
4313       // [[after_loop]]
4314     }
4315   )";
4316   runDataflow(
4317       Code,
4318       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4319          ASTContext &ASTCtx) {
4320         ASSERT_THAT(Results.keys(),
4321                     UnorderedElementsAre("loop_body", "after_loop"));
4322         const Environment &LoopBodyEnv =
4323             getEnvironmentAtAnnotation(Results, "loop_body");
4324         const Environment &AfterLoopEnv =
4325             getEnvironmentAtAnnotation(Results, "after_loop");
4326 
4327         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4328         ASSERT_THAT(FooDecl, NotNull());
4329 
4330         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4331         ASSERT_THAT(BarDecl, NotNull());
4332 
4333         BoolValue &LoopBodyFooVal =
4334             *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl));
4335         BoolValue &LoopBodyBarVal =
4336             *cast<BoolValue>(LoopBodyEnv.getValue(*BarDecl));
4337         EXPECT_TRUE(LoopBodyEnv.flowConditionImplies(
4338             LoopBodyEnv.makeOr(LoopBodyBarVal, LoopBodyFooVal)));
4339 
4340         BoolValue &AfterLoopFooVal =
4341             *cast<BoolValue>(AfterLoopEnv.getValue(*FooDecl));
4342         BoolValue &AfterLoopBarVal =
4343             *cast<BoolValue>(AfterLoopEnv.getValue(*BarDecl));
4344         EXPECT_TRUE(AfterLoopEnv.flowConditionImplies(
4345             AfterLoopEnv.makeNot(AfterLoopFooVal)));
4346         EXPECT_TRUE(AfterLoopEnv.flowConditionImplies(
4347             AfterLoopEnv.makeNot(AfterLoopBarVal)));
4348       });
4349 }
4350 
4351 TEST(TransferTest, ForStmtBranchExtendsFlowCondition) {
4352   std::string Code = R"(
4353     void target(bool Foo) {
4354       for (; Foo;) {
4355         (void)0;
4356         // [[loop_body]]
4357       }
4358       (void)0;
4359       // [[after_loop]]
4360     }
4361   )";
4362   runDataflow(
4363       Code,
4364       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4365          ASTContext &ASTCtx) {
4366         ASSERT_THAT(Results.keys(),
4367                     UnorderedElementsAre("loop_body", "after_loop"));
4368         const Environment &LoopBodyEnv =
4369             getEnvironmentAtAnnotation(Results, "loop_body");
4370         const Environment &AfterLoopEnv =
4371             getEnvironmentAtAnnotation(Results, "after_loop");
4372 
4373         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4374         ASSERT_THAT(FooDecl, NotNull());
4375 
4376         BoolValue &LoopBodyFooVal =
4377             *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl));
4378         EXPECT_TRUE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal));
4379 
4380         BoolValue &AfterLoopFooVal =
4381             *cast<BoolValue>(AfterLoopEnv.getValue(*FooDecl));
4382         EXPECT_TRUE(AfterLoopEnv.flowConditionImplies(
4383             AfterLoopEnv.makeNot(AfterLoopFooVal)));
4384       });
4385 }
4386 
4387 TEST(TransferTest, ForStmtBranchWithoutConditionDoesNotExtendFlowCondition) {
4388   std::string Code = R"(
4389     void target(bool Foo) {
4390       for (;;) {
4391         (void)0;
4392         // [[loop_body]]
4393       }
4394     }
4395   )";
4396   runDataflow(
4397       Code,
4398       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4399          ASTContext &ASTCtx) {
4400         ASSERT_THAT(Results.keys(), UnorderedElementsAre("loop_body"));
4401         const Environment &LoopBodyEnv =
4402             getEnvironmentAtAnnotation(Results, "loop_body");
4403 
4404         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4405         ASSERT_THAT(FooDecl, NotNull());
4406 
4407         BoolValue &LoopBodyFooVal =
4408             *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl));
4409         EXPECT_FALSE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal));
4410       });
4411 }
4412 
4413 TEST(TransferTest, ContextSensitiveOptionDisabled) {
4414   std::string Code = R"(
4415     bool GiveBool();
4416     void SetBool(bool &Var) { Var = true; }
4417 
4418     void target() {
4419       bool Foo = GiveBool();
4420       SetBool(Foo);
4421       // [[p]]
4422     }
4423   )";
4424   runDataflow(
4425       Code,
4426       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4427          ASTContext &ASTCtx) {
4428         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4429         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4430 
4431         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4432         ASSERT_THAT(FooDecl, NotNull());
4433 
4434         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
4435         EXPECT_FALSE(Env.flowConditionImplies(FooVal));
4436         EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
4437       },
4438       {BuiltinOptions{/*.ContextSensitiveOpts=*/std::nullopt}});
4439 }
4440 
4441 TEST(TransferTest, ContextSensitiveReturnReference) {
4442   std::string Code = R"(
4443     class S {};
4444     S& target(bool b, S &s) {
4445       return s;
4446       // [[p]]
4447     }
4448   )";
4449   runDataflow(
4450       Code,
4451       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4452          ASTContext &ASTCtx) {
4453         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4454 
4455         const ValueDecl *SDecl = findValueDecl(ASTCtx, "s");
4456         ASSERT_THAT(SDecl, NotNull());
4457 
4458         auto *SLoc = Env.getStorageLocation(*SDecl);
4459         ASSERT_THAT(SLoc, NotNull());
4460 
4461         ASSERT_THAT(Env.getReturnStorageLocation(), Eq(SLoc));
4462       },
4463       {BuiltinOptions{ContextSensitiveOptions{}}});
4464 }
4465 
4466 // This test is a regression test, based on a real crash.
4467 TEST(TransferTest, ContextSensitiveReturnReferenceWithConditionalOperator) {
4468   std::string Code = R"(
4469     class S {};
4470     S& target(bool b, S &s) {
4471       return b ? s : s;
4472       // [[p]]
4473     }
4474   )";
4475   runDataflow(
4476       Code,
4477       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4478          ASTContext &ASTCtx) {
4479         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4480         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4481 
4482         const ValueDecl *SDecl = findValueDecl(ASTCtx, "s");
4483         ASSERT_THAT(SDecl, NotNull());
4484 
4485         auto *SLoc = Env.getStorageLocation(*SDecl);
4486         ASSERT_THAT(SLoc, NotNull());
4487         EXPECT_THAT(Env.getValue(*SLoc), NotNull());
4488 
4489         auto *Loc = Env.getReturnStorageLocation();
4490         ASSERT_THAT(Loc, NotNull());
4491         EXPECT_THAT(Env.getValue(*Loc), NotNull());
4492 
4493         // TODO: We would really like to make this stronger assertion, but that
4494         // doesn't work because we don't propagate values correctly through
4495         // the conditional operator yet.
4496         // ASSERT_THAT(Loc, Eq(SLoc));
4497       },
4498       {BuiltinOptions{ContextSensitiveOptions{}}});
4499 }
4500 
4501 TEST(TransferTest, ContextSensitiveReturnOneOfTwoReferences) {
4502   std::string Code = R"(
4503     class S {};
4504     S &callee(bool b, S &s1_parm, S &s2_parm) {
4505       if (b)
4506         return s1_parm;
4507       else
4508         return s2_parm;
4509     }
4510     void target(bool b) {
4511       S s1;
4512       S s2;
4513       S &return_s1 = s1;
4514       S &return_s2 = s2;
4515       S &return_dont_know = callee(b, s1, s2);
4516       // [[p]]
4517     }
4518   )";
4519   runDataflow(
4520       Code,
4521       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4522          ASTContext &ASTCtx) {
4523         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4524 
4525         const ValueDecl *S1 = findValueDecl(ASTCtx, "s1");
4526         ASSERT_THAT(S1, NotNull());
4527         const ValueDecl *S2 = findValueDecl(ASTCtx, "s2");
4528         ASSERT_THAT(S2, NotNull());
4529         const ValueDecl *ReturnS1 = findValueDecl(ASTCtx, "return_s1");
4530         ASSERT_THAT(ReturnS1, NotNull());
4531         const ValueDecl *ReturnS2 = findValueDecl(ASTCtx, "return_s2");
4532         ASSERT_THAT(ReturnS2, NotNull());
4533         const ValueDecl *ReturnDontKnow =
4534             findValueDecl(ASTCtx, "return_dont_know");
4535         ASSERT_THAT(ReturnDontKnow, NotNull());
4536 
4537         StorageLocation *S1Loc = Env.getStorageLocation(*S1);
4538         StorageLocation *S2Loc = Env.getStorageLocation(*S2);
4539 
4540         EXPECT_THAT(Env.getStorageLocation(*ReturnS1), Eq(S1Loc));
4541         EXPECT_THAT(Env.getStorageLocation(*ReturnS2), Eq(S2Loc));
4542 
4543         // In the case where we don't have a consistent storage location for
4544         // the return value, the framework creates a new storage location, which
4545         // should be different from the storage locations of `s1` and `s2`.
4546         EXPECT_THAT(Env.getStorageLocation(*ReturnDontKnow), Ne(S1Loc));
4547         EXPECT_THAT(Env.getStorageLocation(*ReturnDontKnow), Ne(S2Loc));
4548       },
4549       {BuiltinOptions{ContextSensitiveOptions{}}});
4550 }
4551 
4552 TEST(TransferTest, ContextSensitiveDepthZero) {
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_FALSE(Env.flowConditionImplies(FooVal));
4575         EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
4576       },
4577       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/0}}});
4578 }
4579 
4580 TEST(TransferTest, ContextSensitiveSetTrue) {
4581   std::string Code = R"(
4582     bool GiveBool();
4583     void SetBool(bool &Var) { Var = true; }
4584 
4585     void target() {
4586       bool Foo = GiveBool();
4587       SetBool(Foo);
4588       // [[p]]
4589     }
4590   )";
4591   runDataflow(
4592       Code,
4593       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4594          ASTContext &ASTCtx) {
4595         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4596         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4597 
4598         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4599         ASSERT_THAT(FooDecl, NotNull());
4600 
4601         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
4602         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4603       },
4604       {BuiltinOptions{ContextSensitiveOptions{}}});
4605 }
4606 
4607 TEST(TransferTest, ContextSensitiveSetFalse) {
4608   std::string Code = R"(
4609     bool GiveBool();
4610     void SetBool(bool &Var) { Var = false; }
4611 
4612     void target() {
4613       bool Foo = GiveBool();
4614       SetBool(Foo);
4615       // [[p]]
4616     }
4617   )";
4618   runDataflow(
4619       Code,
4620       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4621          ASTContext &ASTCtx) {
4622         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4623         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4624 
4625         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4626         ASSERT_THAT(FooDecl, NotNull());
4627 
4628         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
4629         EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(FooVal)));
4630       },
4631       {BuiltinOptions{ContextSensitiveOptions{}}});
4632 }
4633 
4634 TEST(TransferTest, ContextSensitiveSetBothTrueAndFalse) {
4635   std::string Code = R"(
4636     bool GiveBool();
4637     void SetBool(bool &Var, bool Val) { Var = Val; }
4638 
4639     void target() {
4640       bool Foo = GiveBool();
4641       bool Bar = GiveBool();
4642       SetBool(Foo, true);
4643       SetBool(Bar, false);
4644       // [[p]]
4645     }
4646   )";
4647   runDataflow(
4648       Code,
4649       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4650          ASTContext &ASTCtx) {
4651         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4652         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4653 
4654         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4655         ASSERT_THAT(FooDecl, NotNull());
4656 
4657         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4658         ASSERT_THAT(BarDecl, NotNull());
4659 
4660         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
4661         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4662         EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
4663 
4664         auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl));
4665         EXPECT_FALSE(Env.flowConditionImplies(BarVal));
4666         EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal)));
4667       },
4668       {BuiltinOptions{ContextSensitiveOptions{}}});
4669 }
4670 
4671 TEST(TransferTest, ContextSensitiveSetTwoLayersDepthOne) {
4672   std::string Code = R"(
4673     bool GiveBool();
4674     void SetBool1(bool &Var) { Var = true; }
4675     void SetBool2(bool &Var) { SetBool1(Var); }
4676 
4677     void target() {
4678       bool Foo = GiveBool();
4679       SetBool2(Foo);
4680       // [[p]]
4681     }
4682   )";
4683   runDataflow(
4684       Code,
4685       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4686          ASTContext &ASTCtx) {
4687         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4688         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4689 
4690         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4691         ASSERT_THAT(FooDecl, NotNull());
4692 
4693         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
4694         EXPECT_FALSE(Env.flowConditionImplies(FooVal));
4695         EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
4696       },
4697       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/1}}});
4698 }
4699 
4700 TEST(TransferTest, ContextSensitiveSetTwoLayersDepthTwo) {
4701   std::string Code = R"(
4702     bool GiveBool();
4703     void SetBool1(bool &Var) { Var = true; }
4704     void SetBool2(bool &Var) { SetBool1(Var); }
4705 
4706     void target() {
4707       bool Foo = GiveBool();
4708       SetBool2(Foo);
4709       // [[p]]
4710     }
4711   )";
4712   runDataflow(
4713       Code,
4714       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4715          ASTContext &ASTCtx) {
4716         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4717         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4718 
4719         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4720         ASSERT_THAT(FooDecl, NotNull());
4721 
4722         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
4723         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4724       },
4725       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/2}}});
4726 }
4727 
4728 TEST(TransferTest, ContextSensitiveSetThreeLayersDepthTwo) {
4729   std::string Code = R"(
4730     bool GiveBool();
4731     void SetBool1(bool &Var) { Var = true; }
4732     void SetBool2(bool &Var) { SetBool1(Var); }
4733     void SetBool3(bool &Var) { SetBool2(Var); }
4734 
4735     void target() {
4736       bool Foo = GiveBool();
4737       SetBool3(Foo);
4738       // [[p]]
4739     }
4740   )";
4741   runDataflow(
4742       Code,
4743       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4744          ASTContext &ASTCtx) {
4745         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4746         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4747 
4748         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4749         ASSERT_THAT(FooDecl, NotNull());
4750 
4751         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
4752         EXPECT_FALSE(Env.flowConditionImplies(FooVal));
4753         EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
4754       },
4755       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/2}}});
4756 }
4757 
4758 TEST(TransferTest, ContextSensitiveSetThreeLayersDepthThree) {
4759   std::string Code = R"(
4760     bool GiveBool();
4761     void SetBool1(bool &Var) { Var = true; }
4762     void SetBool2(bool &Var) { SetBool1(Var); }
4763     void SetBool3(bool &Var) { SetBool2(Var); }
4764 
4765     void target() {
4766       bool Foo = GiveBool();
4767       SetBool3(Foo);
4768       // [[p]]
4769     }
4770   )";
4771   runDataflow(
4772       Code,
4773       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4774          ASTContext &ASTCtx) {
4775         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4776         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4777 
4778         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4779         ASSERT_THAT(FooDecl, NotNull());
4780 
4781         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
4782         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4783       },
4784       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/3}}});
4785 }
4786 
4787 TEST(TransferTest, ContextSensitiveMutualRecursion) {
4788   std::string Code = R"(
4789     bool Pong(bool X, bool Y);
4790 
4791     bool Ping(bool X, bool Y) {
4792       if (X) {
4793         return Y;
4794       } else {
4795         return Pong(!X, Y);
4796       }
4797     }
4798 
4799     bool Pong(bool X, bool Y) {
4800       if (Y) {
4801         return X;
4802       } else {
4803         return Ping(X, !Y);
4804       }
4805     }
4806 
4807     void target() {
4808       bool Foo = Ping(false, false);
4809       // [[p]]
4810     }
4811   )";
4812   runDataflow(
4813       Code,
4814       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4815          ASTContext &ASTCtx) {
4816         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4817         // The analysis doesn't crash...
4818         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4819 
4820         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4821         ASSERT_THAT(FooDecl, NotNull());
4822 
4823         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
4824         // ... but it also can't prove anything here.
4825         EXPECT_FALSE(Env.flowConditionImplies(FooVal));
4826         EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
4827       },
4828       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/4}}});
4829 }
4830 
4831 TEST(TransferTest, ContextSensitiveSetMultipleLines) {
4832   std::string Code = R"(
4833     void SetBools(bool &Var1, bool &Var2) {
4834       Var1 = true;
4835       Var2 = false;
4836     }
4837 
4838     void target() {
4839       bool Foo = false;
4840       bool Bar = true;
4841       SetBools(Foo, Bar);
4842       // [[p]]
4843     }
4844   )";
4845   runDataflow(
4846       Code,
4847       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4848          ASTContext &ASTCtx) {
4849         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4850         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4851 
4852         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4853         ASSERT_THAT(FooDecl, NotNull());
4854 
4855         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4856         ASSERT_THAT(BarDecl, NotNull());
4857 
4858         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
4859         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4860         EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
4861 
4862         auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl));
4863         EXPECT_FALSE(Env.flowConditionImplies(BarVal));
4864         EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal)));
4865       },
4866       {BuiltinOptions{ContextSensitiveOptions{}}});
4867 }
4868 
4869 TEST(TransferTest, ContextSensitiveSetMultipleBlocks) {
4870   std::string Code = R"(
4871     void IfCond(bool Cond, bool &Then, bool &Else) {
4872       if (Cond) {
4873         Then = true;
4874       } else {
4875         Else = true;
4876       }
4877     }
4878 
4879     void target() {
4880       bool Foo = false;
4881       bool Bar = false;
4882       bool Baz = false;
4883       IfCond(Foo, Bar, Baz);
4884       // [[p]]
4885     }
4886   )";
4887   runDataflow(
4888       Code,
4889       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4890          ASTContext &ASTCtx) {
4891         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4892         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4893 
4894         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4895         ASSERT_THAT(BarDecl, NotNull());
4896 
4897         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4898         ASSERT_THAT(BazDecl, NotNull());
4899 
4900         auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl));
4901         EXPECT_FALSE(Env.flowConditionImplies(BarVal));
4902         EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal)));
4903 
4904         auto &BazVal = *cast<BoolValue>(Env.getValue(*BazDecl));
4905         EXPECT_TRUE(Env.flowConditionImplies(BazVal));
4906         EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(BazVal)));
4907       },
4908       {BuiltinOptions{ContextSensitiveOptions{}}});
4909 }
4910 
4911 TEST(TransferTest, ContextSensitiveReturnVoid) {
4912   std::string Code = R"(
4913     void Noop() { return; }
4914 
4915     void target() {
4916       Noop();
4917       // [[p]]
4918     }
4919   )";
4920   runDataflow(
4921       Code,
4922       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4923          ASTContext &ASTCtx) {
4924         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4925         // This just tests that the analysis doesn't crash.
4926       },
4927       {BuiltinOptions{ContextSensitiveOptions{}}});
4928 }
4929 
4930 TEST(TransferTest, ContextSensitiveReturnTrue) {
4931   std::string Code = R"(
4932     bool GiveBool() { return true; }
4933 
4934     void target() {
4935       bool Foo = GiveBool();
4936       // [[p]]
4937     }
4938   )";
4939   runDataflow(
4940       Code,
4941       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4942          ASTContext &ASTCtx) {
4943         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4944         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4945 
4946         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4947         ASSERT_THAT(FooDecl, NotNull());
4948 
4949         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
4950         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4951       },
4952       {BuiltinOptions{ContextSensitiveOptions{}}});
4953 }
4954 
4955 TEST(TransferTest, ContextSensitiveReturnFalse) {
4956   std::string Code = R"(
4957     bool GiveBool() { return false; }
4958 
4959     void target() {
4960       bool Foo = GiveBool();
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 *FooDecl = findValueDecl(ASTCtx, "Foo");
4972         ASSERT_THAT(FooDecl, NotNull());
4973 
4974         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
4975         EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(FooVal)));
4976       },
4977       {BuiltinOptions{ContextSensitiveOptions{}}});
4978 }
4979 
4980 TEST(TransferTest, ContextSensitiveReturnArg) {
4981   std::string Code = R"(
4982     bool GiveBool();
4983     bool GiveBack(bool Arg) { return Arg; }
4984 
4985     void target() {
4986       bool Foo = GiveBool();
4987       bool Bar = GiveBack(Foo);
4988       bool Baz = Foo == Bar;
4989       // [[p]]
4990     }
4991   )";
4992   runDataflow(
4993       Code,
4994       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4995          ASTContext &ASTCtx) {
4996         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4997         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4998 
4999         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
5000         ASSERT_THAT(BazDecl, NotNull());
5001 
5002         auto &BazVal = *cast<BoolValue>(Env.getValue(*BazDecl));
5003         EXPECT_TRUE(Env.flowConditionImplies(BazVal));
5004       },
5005       {BuiltinOptions{ContextSensitiveOptions{}}});
5006 }
5007 
5008 TEST(TransferTest, ContextSensitiveReturnInt) {
5009   std::string Code = R"(
5010     int identity(int x) { return x; }
5011 
5012     void target() {
5013       int y = identity(42);
5014       // [[p]]
5015     }
5016   )";
5017   runDataflow(
5018       Code,
5019       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5020          ASTContext &ASTCtx) {
5021         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5022         // This just tests that the analysis doesn't crash.
5023       },
5024       {BuiltinOptions{ContextSensitiveOptions{}}});
5025 }
5026 
5027 TEST(TransferTest, ContextSensitiveMethodLiteral) {
5028   std::string Code = R"(
5029     class MyClass {
5030     public:
5031       bool giveBool() { return true; }
5032     };
5033 
5034     void target() {
5035       MyClass MyObj;
5036       bool Foo = MyObj.giveBool();
5037       // [[p]]
5038     }
5039   )";
5040   runDataflow(
5041       Code,
5042       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5043          ASTContext &ASTCtx) {
5044         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5045         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5046 
5047         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5048         ASSERT_THAT(FooDecl, NotNull());
5049 
5050         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
5051         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
5052       },
5053       {BuiltinOptions{ContextSensitiveOptions{}}});
5054 }
5055 
5056 TEST(TransferTest, ContextSensitiveMethodGetter) {
5057   std::string Code = R"(
5058     class MyClass {
5059     public:
5060       bool getField() { return Field; }
5061 
5062       bool Field;
5063     };
5064 
5065     void target() {
5066       MyClass MyObj;
5067       MyObj.Field = true;
5068       bool Foo = MyObj.getField();
5069       // [[p]]
5070     }
5071   )";
5072   runDataflow(
5073       Code,
5074       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5075          ASTContext &ASTCtx) {
5076         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5077         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5078 
5079         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5080         ASSERT_THAT(FooDecl, NotNull());
5081 
5082         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
5083         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
5084       },
5085       {BuiltinOptions{ContextSensitiveOptions{}}});
5086 }
5087 
5088 TEST(TransferTest, ContextSensitiveMethodSetter) {
5089   std::string Code = R"(
5090     class MyClass {
5091     public:
5092       void setField(bool Val) { Field = Val; }
5093 
5094       bool Field;
5095     };
5096 
5097     void target() {
5098       MyClass MyObj;
5099       MyObj.setField(true);
5100       bool Foo = MyObj.Field;
5101       // [[p]]
5102     }
5103   )";
5104   runDataflow(
5105       Code,
5106       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5107          ASTContext &ASTCtx) {
5108         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5109         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5110 
5111         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5112         ASSERT_THAT(FooDecl, NotNull());
5113 
5114         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
5115         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
5116       },
5117       {BuiltinOptions{ContextSensitiveOptions{}}});
5118 }
5119 
5120 TEST(TransferTest, ContextSensitiveMethodGetterAndSetter) {
5121   std::string Code = R"(
5122     class MyClass {
5123     public:
5124       bool getField() { return Field; }
5125       void setField(bool Val) { Field = Val; }
5126 
5127     private:
5128       bool Field;
5129     };
5130 
5131     void target() {
5132       MyClass MyObj;
5133       MyObj.setField(true);
5134       bool Foo = MyObj.getField();
5135       // [[p]]
5136     }
5137   )";
5138   runDataflow(
5139       Code,
5140       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5141          ASTContext &ASTCtx) {
5142         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5143         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5144 
5145         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5146         ASSERT_THAT(FooDecl, NotNull());
5147 
5148         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
5149         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
5150       },
5151       {BuiltinOptions{ContextSensitiveOptions{}}});
5152 }
5153 
5154 
5155 TEST(TransferTest, ContextSensitiveMethodTwoLayersVoid) {
5156   std::string Code = R"(
5157     class MyClass {
5158     public:
5159       void Inner() { MyField = true; }
5160       void Outer() { Inner(); }
5161 
5162       bool MyField;
5163     };
5164 
5165     void target() {
5166       MyClass MyObj;
5167       MyObj.Outer();
5168       bool Foo = MyObj.MyField;
5169       // [[p]]
5170     }
5171   )";
5172   runDataflow(
5173       Code,
5174       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5175          ASTContext &ASTCtx) {
5176         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5177         ;
5178         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5179 
5180         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5181         ASSERT_THAT(FooDecl, NotNull());
5182 
5183         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
5184         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
5185       },
5186       {BuiltinOptions{ContextSensitiveOptions{}}});
5187 }
5188 
5189 TEST(TransferTest, ContextSensitiveMethodTwoLayersReturn) {
5190   std::string Code = R"(
5191     class MyClass {
5192     public:
5193       bool Inner() { return MyField; }
5194       bool Outer() { return Inner(); }
5195 
5196       bool MyField;
5197     };
5198 
5199     void target() {
5200       MyClass MyObj;
5201       MyObj.MyField = true;
5202       bool Foo = MyObj.Outer();
5203       // [[p]]
5204     }
5205   )";
5206   runDataflow(
5207       Code,
5208       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5209          ASTContext &ASTCtx) {
5210         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5211         ;
5212         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5213 
5214         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5215         ASSERT_THAT(FooDecl, NotNull());
5216 
5217         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
5218         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
5219       },
5220       {BuiltinOptions{ContextSensitiveOptions{}}});
5221 }
5222 
5223 TEST(TransferTest, ContextSensitiveConstructorBody) {
5224   std::string Code = R"(
5225     class MyClass {
5226     public:
5227       MyClass() { MyField = true; }
5228 
5229       bool MyField;
5230     };
5231 
5232     void target() {
5233       MyClass MyObj;
5234       bool Foo = MyObj.MyField;
5235       // [[p]]
5236     }
5237   )";
5238   runDataflow(
5239       Code,
5240       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5241          ASTContext &ASTCtx) {
5242         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5243         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5244 
5245         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5246         ASSERT_THAT(FooDecl, NotNull());
5247 
5248         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
5249         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
5250       },
5251       {BuiltinOptions{ContextSensitiveOptions{}}});
5252 }
5253 
5254 TEST(TransferTest, ContextSensitiveConstructorInitializer) {
5255   std::string Code = R"(
5256     class MyClass {
5257     public:
5258       MyClass() : MyField(true) {}
5259 
5260       bool MyField;
5261     };
5262 
5263     void target() {
5264       MyClass MyObj;
5265       bool Foo = MyObj.MyField;
5266       // [[p]]
5267     }
5268   )";
5269   runDataflow(
5270       Code,
5271       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5272          ASTContext &ASTCtx) {
5273         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5274         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5275 
5276         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5277         ASSERT_THAT(FooDecl, NotNull());
5278 
5279         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
5280         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
5281       },
5282       {BuiltinOptions{ContextSensitiveOptions{}}});
5283 }
5284 
5285 TEST(TransferTest, ContextSensitiveConstructorDefault) {
5286   std::string Code = R"(
5287     class MyClass {
5288     public:
5289       MyClass() = default;
5290 
5291       bool MyField = true;
5292     };
5293 
5294     void target() {
5295       MyClass MyObj;
5296       bool Foo = MyObj.MyField;
5297       // [[p]]
5298     }
5299   )";
5300   runDataflow(
5301       Code,
5302       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5303          ASTContext &ASTCtx) {
5304         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5305         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5306 
5307         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5308         ASSERT_THAT(FooDecl, NotNull());
5309 
5310         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
5311         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
5312       },
5313       {BuiltinOptions{ContextSensitiveOptions{}}});
5314 }
5315 
5316 TEST(TransferTest, UnnamedBitfieldInitializer) {
5317   std::string Code = R"(
5318     struct B {};
5319     struct A {
5320       unsigned a;
5321       unsigned : 4;
5322       unsigned c;
5323       B b;
5324     };
5325     void target() {
5326       A a = {};
5327       A test = a;
5328       (void)test.c;
5329     }
5330   )";
5331   runDataflow(
5332       Code,
5333       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5334          ASTContext &ASTCtx) {
5335         // This doesn't need a body because this test was crashing the framework
5336         // before handling correctly Unnamed bitfields in `InitListExpr`.
5337       });
5338 }
5339 
5340 // Repro for a crash that used to occur with chained short-circuiting logical
5341 // operators.
5342 TEST(TransferTest, ChainedLogicalOps) {
5343   std::string Code = R"(
5344     bool target() {
5345       bool b = true || false || false || false;
5346       // [[p]]
5347       return b;
5348     }
5349   )";
5350   runDataflow(
5351       Code,
5352       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5353          ASTContext &ASTCtx) {
5354         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5355         auto &B = getValueForDecl<BoolValue>(ASTCtx, Env, "b");
5356         EXPECT_TRUE(Env.flowConditionImplies(B));
5357       });
5358 }
5359 
5360 // Repro for a crash that used to occur when we call a `noreturn` function
5361 // within one of the operands of a `&&` or `||` operator.
5362 TEST(TransferTest, NoReturnFunctionInsideShortCircuitedBooleanOp) {
5363   std::string Code = R"(
5364     __attribute__((noreturn)) int doesnt_return();
5365     bool some_condition();
5366     void target(bool b1, bool b2) {
5367       // Neither of these should crash. In addition, if we don't terminate the
5368       // program, we know that the operators need to trigger the short-circuit
5369       // logic, so `NoreturnOnRhsOfAnd` will be false and `NoreturnOnRhsOfOr`
5370       // will be true.
5371       bool NoreturnOnRhsOfAnd = b1 && doesnt_return() > 0;
5372       bool NoreturnOnRhsOfOr = b2 || doesnt_return() > 0;
5373 
5374       // Calling a `noreturn` function on the LHS of an `&&` or `||` makes the
5375       // entire expression unreachable. So we know that in both of the following
5376       // cases, if `target()` terminates, the `else` branch was taken.
5377       bool NoreturnOnLhsMakesAndUnreachable = false;
5378       if (some_condition())
5379          doesnt_return() > 0 && some_condition();
5380       else
5381          NoreturnOnLhsMakesAndUnreachable = true;
5382 
5383       bool NoreturnOnLhsMakesOrUnreachable = false;
5384       if (some_condition())
5385          doesnt_return() > 0 || some_condition();
5386       else
5387          NoreturnOnLhsMakesOrUnreachable = true;
5388 
5389       // [[p]]
5390     }
5391   )";
5392   runDataflow(
5393       Code,
5394       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5395          ASTContext &ASTCtx) {
5396         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5397         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5398 
5399         // Check that [[p]] is reachable with a non-false flow condition.
5400         EXPECT_FALSE(Env.flowConditionImplies(Env.getBoolLiteralValue(false)));
5401 
5402         auto &B1 = getValueForDecl<BoolValue>(ASTCtx, Env, "b1");
5403         EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(B1)));
5404 
5405         auto &NoreturnOnRhsOfAnd =
5406             getValueForDecl<BoolValue>(ASTCtx, Env, "NoreturnOnRhsOfAnd");
5407         EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(NoreturnOnRhsOfAnd)));
5408 
5409         auto &B2 = getValueForDecl<BoolValue>(ASTCtx, Env, "b2");
5410         EXPECT_TRUE(Env.flowConditionImplies(B2));
5411 
5412         auto &NoreturnOnRhsOfOr =
5413             getValueForDecl<BoolValue>(ASTCtx, Env, "NoreturnOnRhsOfOr");
5414         EXPECT_TRUE(Env.flowConditionImplies(NoreturnOnRhsOfOr));
5415 
5416         auto &NoreturnOnLhsMakesAndUnreachable = getValueForDecl<BoolValue>(
5417             ASTCtx, Env, "NoreturnOnLhsMakesAndUnreachable");
5418         EXPECT_TRUE(Env.flowConditionImplies(NoreturnOnLhsMakesAndUnreachable));
5419 
5420         auto &NoreturnOnLhsMakesOrUnreachable = getValueForDecl<BoolValue>(
5421             ASTCtx, Env, "NoreturnOnLhsMakesOrUnreachable");
5422         EXPECT_TRUE(Env.flowConditionImplies(NoreturnOnLhsMakesOrUnreachable));
5423       });
5424 }
5425 
5426 TEST(TransferTest, NewExpressions) {
5427   std::string Code = R"(
5428     void target() {
5429       int *p = new int(42);
5430       // [[after_new]]
5431     }
5432   )";
5433   runDataflow(
5434       Code,
5435       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5436          ASTContext &ASTCtx) {
5437         const Environment &Env =
5438             getEnvironmentAtAnnotation(Results, "after_new");
5439 
5440         auto &P = getValueForDecl<PointerValue>(ASTCtx, Env, "p");
5441 
5442         EXPECT_THAT(Env.getValue(P.getPointeeLoc()), NotNull());
5443       });
5444 }
5445 
5446 TEST(TransferTest, NewExpressions_Structs) {
5447   std::string Code = R"(
5448     struct Inner {
5449       int InnerField;
5450     };
5451 
5452     struct Outer {
5453       Inner OuterField;
5454     };
5455 
5456     void target() {
5457       Outer *p = new Outer;
5458       // Access the fields to make sure the analysis actually generates children
5459       // for them in the `AggregateStorageLoc` and `StructValue`.
5460       p->OuterField.InnerField;
5461       // [[after_new]]
5462     }
5463   )";
5464   runDataflow(
5465       Code,
5466       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5467          ASTContext &ASTCtx) {
5468         const Environment &Env =
5469             getEnvironmentAtAnnotation(Results, "after_new");
5470 
5471         const ValueDecl *OuterField = findValueDecl(ASTCtx, "OuterField");
5472         const ValueDecl *InnerField = findValueDecl(ASTCtx, "InnerField");
5473 
5474         auto &P = getValueForDecl<PointerValue>(ASTCtx, Env, "p");
5475 
5476         auto &OuterLoc = cast<AggregateStorageLocation>(P.getPointeeLoc());
5477         auto &OuterFieldLoc =
5478             cast<AggregateStorageLocation>(OuterLoc.getChild(*OuterField));
5479         auto &InnerFieldLoc = OuterFieldLoc.getChild(*InnerField);
5480 
5481         // Values for the struct and all fields exist after the new.
5482         EXPECT_THAT(Env.getValue(OuterLoc), NotNull());
5483         EXPECT_THAT(Env.getValue(OuterFieldLoc), NotNull());
5484         EXPECT_THAT(Env.getValue(InnerFieldLoc), NotNull());
5485       });
5486 }
5487 
5488 TEST(TransferTest, FunctionToPointerDecayHasValue) {
5489   std::string Code = R"(
5490     struct A { static void static_member_func(); };
5491     void target() {
5492       // To check that we're treating function-to-pointer decay correctly,
5493       // create two pointers, then verify they refer to the same storage
5494       // location.
5495       // We need to do the test this way because even if an initializer (in this
5496       // case, the function-to-pointer decay) does not create a value, we still
5497       // create a value for the variable.
5498       void (*non_member_p1)() = target;
5499       void (*non_member_p2)() = target;
5500 
5501       // Do the same thing but for a static member function.
5502       void (*member_p1)() = A::static_member_func;
5503       void (*member_p2)() = A::static_member_func;
5504       // [[p]]
5505     }
5506   )";
5507   runDataflow(
5508       Code,
5509       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5510          ASTContext &ASTCtx) {
5511         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5512 
5513         auto &NonMemberP1 =
5514             getValueForDecl<PointerValue>(ASTCtx, Env, "non_member_p1");
5515         auto &NonMemberP2 =
5516             getValueForDecl<PointerValue>(ASTCtx, Env, "non_member_p2");
5517         EXPECT_EQ(&NonMemberP1.getPointeeLoc(), &NonMemberP2.getPointeeLoc());
5518 
5519         auto &MemberP1 =
5520             getValueForDecl<PointerValue>(ASTCtx, Env, "member_p1");
5521         auto &MemberP2 =
5522             getValueForDecl<PointerValue>(ASTCtx, Env, "member_p2");
5523         EXPECT_EQ(&MemberP1.getPointeeLoc(), &MemberP2.getPointeeLoc());
5524       });
5525 }
5526 
5527 // Check that a builtin function is not associated with a value. (It's only
5528 // possible to call builtin functions directly, not take their address.)
5529 TEST(TransferTest, BuiltinFunctionModeled) {
5530   std::string Code = R"(
5531     void target() {
5532       __builtin_expect(0, 0);
5533       // [[p]]
5534     }
5535   )";
5536   runDataflow(
5537       Code,
5538       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5539          ASTContext &ASTCtx) {
5540         using ast_matchers::selectFirst;
5541         using ast_matchers::match;
5542         using ast_matchers::traverse;
5543         using ast_matchers::implicitCastExpr;
5544         using ast_matchers::hasCastKind;
5545 
5546         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5547 
5548         auto *ImplicitCast = selectFirst<ImplicitCastExpr>(
5549             "implicit_cast",
5550             match(traverse(TK_AsIs,
5551                            implicitCastExpr(hasCastKind(CK_BuiltinFnToFnPtr))
5552                                .bind("implicit_cast")),
5553                   ASTCtx));
5554 
5555         ASSERT_THAT(ImplicitCast, NotNull());
5556         EXPECT_THAT(Env.getValueStrict(*ImplicitCast), IsNull());
5557       });
5558 }
5559 
5560 // Check that fields of anonymous records are modeled.
5561 TEST(TransferTest, AnonymousStruct) {
5562   std::string Code = R"(
5563     struct S {
5564       struct {
5565         bool b;
5566       };
5567     };
5568     void target() {
5569       S s;
5570       s.b = true;
5571       // [[p]]
5572     }
5573   )";
5574   runDataflow(
5575       Code,
5576       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5577          ASTContext &ASTCtx) {
5578         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5579         const ValueDecl *SDecl = findValueDecl(ASTCtx, "s");
5580         const ValueDecl *BDecl = findValueDecl(ASTCtx, "b");
5581         const IndirectFieldDecl *IndirectField =
5582             findIndirectFieldDecl(ASTCtx, "b");
5583 
5584         auto *S =
5585             cast<AggregateStorageLocation>(Env.getStorageLocation(*SDecl));
5586         auto &AnonStruct = cast<AggregateStorageLocation>(
5587             S->getChild(*cast<ValueDecl>(IndirectField->chain().front())));
5588 
5589         auto *B = cast<BoolValue>(getFieldValue(&AnonStruct, *BDecl, Env));
5590         ASSERT_TRUE(Env.flowConditionImplies(*B));
5591       });
5592 }
5593 
5594 TEST(TransferTest, AnonymousStructWithInitializer) {
5595   std::string Code = R"(
5596     struct target {
5597       target() {
5598         (void)0;
5599         // [[p]]
5600       }
5601       struct {
5602         bool b = true;
5603       };
5604     };
5605   )";
5606   runDataflow(
5607       Code,
5608       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5609          ASTContext &ASTCtx) {
5610         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5611         const ValueDecl *BDecl = findValueDecl(ASTCtx, "b");
5612         const IndirectFieldDecl *IndirectField =
5613             findIndirectFieldDecl(ASTCtx, "b");
5614 
5615         auto *ThisLoc =
5616             cast<AggregateStorageLocation>(Env.getThisPointeeStorageLocation());
5617         auto &AnonStruct = cast<AggregateStorageLocation>(ThisLoc->getChild(
5618             *cast<ValueDecl>(IndirectField->chain().front())));
5619 
5620         auto *B = cast<BoolValue>(getFieldValue(&AnonStruct, *BDecl, Env));
5621         ASSERT_TRUE(Env.flowConditionImplies(*B));
5622       });
5623 }
5624 
5625 TEST(TransferTest, AnonymousStructWithReferenceField) {
5626   std::string Code = R"(
5627     int global_i = 0;
5628     struct target {
5629       target() {
5630         (void)0;
5631         // [[p]]
5632       }
5633       struct {
5634         int &i = global_i;
5635       };
5636     };
5637   )";
5638   runDataflow(
5639       Code,
5640       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5641          ASTContext &ASTCtx) {
5642         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5643         const ValueDecl *GlobalIDecl = findValueDecl(ASTCtx, "global_i");
5644         const ValueDecl *IDecl = findValueDecl(ASTCtx, "i");
5645         const IndirectFieldDecl *IndirectField =
5646             findIndirectFieldDecl(ASTCtx, "i");
5647 
5648         auto *ThisLoc =
5649             cast<AggregateStorageLocation>(Env.getThisPointeeStorageLocation());
5650         auto &AnonStruct = cast<AggregateStorageLocation>(ThisLoc->getChild(
5651             *cast<ValueDecl>(IndirectField->chain().front())));
5652 
5653         auto *RefVal =
5654             cast<ReferenceValue>(Env.getValue(AnonStruct.getChild(*IDecl)));
5655 
5656         ASSERT_EQ(&RefVal->getReferentLoc(),
5657                   Env.getStorageLocation(*GlobalIDecl));
5658       });
5659 }
5660 
5661 } // namespace
5662