diff --git a/clang/lib/Analysis/FlowSensitive/RecordOps.cpp b/clang/lib/Analysis/FlowSensitive/RecordOps.cpp --- a/clang/lib/Analysis/FlowSensitive/RecordOps.cpp +++ b/clang/lib/Analysis/FlowSensitive/RecordOps.cpp @@ -35,8 +35,8 @@ }); assert(compatibleTypes); - for (auto [Field, DstFieldLoc] : Dst.children()) { - StorageLocation *SrcFieldLoc = Src.getChild(*Field); + for (auto [Field, SrcFieldLoc] : Src.children()) { + StorageLocation *DstFieldLoc = Dst.getChild(*Field); assert(Field->getType()->isReferenceType() || (SrcFieldLoc != nullptr && DstFieldLoc != nullptr)); diff --git a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp --- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp @@ -16,10 +16,8 @@ #include "clang/Analysis/FlowSensitive/StorageLocation.h" #include "clang/Analysis/FlowSensitive/Value.h" #include "clang/Basic/LangStandard.h" -#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" -#include "llvm/Support/Casting.h" #include "llvm/Testing/Support/Error.h" #include "gmock/gmock.h" #include "gtest/gtest.h" @@ -2253,6 +2251,49 @@ ASTContext &ASTCtx) {}); } +TEST(TransferTest, CopyConstructorWithInheritance) { + // This is a crash repro. + std::string Code = R"( + struct B { int Foo; }; + struct S : public B {}; + void target() { + S S1 = { 1 }; + S S2(S1); + // [p1] + S2.Foo = 2; + // [p2] + } + )"; + runDataflow( + Code, + [](const llvm::StringMap> &Results, + ASTContext &ASTCtx) { + // FIXME: Add tests to check if `Foo` exists both in S1 and S2 once + // initialization with inheritance is fixed. + }); +} + +TEST(TransferTest, CopyConstructorWithBaseInitAndInheritance) { + // This is a crash repro. + std::string Code = R"( + struct Foo { int Bar; }; + struct B { Foo F = { 1 }; }; + struct S : public B {}; + void target() { + S S1 = {}; + S S2(S1); + // [p] + } + )"; + runDataflow( + Code, + [](const llvm::StringMap> &Results, + ASTContext &ASTCtx) { + // FIXME: Add tests to check if `Bar` exists both in S1 and S2 once + // initialization with inheritance is fixed. + }); +} + TEST(TransferTest, MoveConstructor) { std::string Code = R"( namespace std { @@ -2328,6 +2369,22 @@ }); } +TEST(TransferTest, ReturnStructWithInheritance) { + // This is a crash repro. + std::string Code = R"( + struct B { int Foo; }; + struct S : public B { }; + S target() { + S S1 = { 1 }; + return S1; + } + )"; + runDataflow( + Code, + [](const llvm::StringMap> &Results, + ASTContext &ASTCtx) {}); +} + TEST(TransferTest, BindTemporary) { std::string Code = R"( struct A {