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