diff --git a/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp b/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp index ee1723dcd8cc85..8a5d5ca386afeb 100644 --- a/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp +++ b/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp @@ -257,6 +257,11 @@ static void transferCFGInitializer(const CFGInitializer &CfgInit, const CXXCtorInitializer *Initializer = CfgInit.getInitializer(); assert(Initializer != nullptr); + const FieldDecl *Member = Initializer->getMember(); + if (Member == nullptr) + // Not a field initializer. + return; + auto *InitStmt = Initializer->getInit(); assert(InitStmt != nullptr); @@ -269,9 +274,6 @@ static void transferCFGInitializer(const CFGInitializer &CfgInit, if (InitStmtVal == nullptr) return; - const FieldDecl *Member = Initializer->getMember(); - assert(Member != nullptr); - if (Member->getType()->isReferenceType()) { auto &MemberLoc = ThisLoc.getChild(*Member); State.Env.setValue(MemberLoc, diff --git a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp index dbf59bf695560c..efea7797b45fbc 100644 --- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp @@ -1296,6 +1296,49 @@ TEST_F(TransferTest, ClassMember) { }); } +TEST_F(TransferTest, BaseClassInitializer) { + using ast_matchers::cxxConstructorDecl; + using ast_matchers::hasName; + using ast_matchers::ofClass; + + std::string Code = R"( + class A { + public: + A(int I) : Bar(I) {} + int Bar; + }; + + class B : public A { + public: + B(int I) : A(I) { + (void)0; + // [[p]] + } + }; + )"; + ASSERT_THAT_ERROR( + test::checkDataflow( + Code, cxxConstructorDecl(ofClass(hasName("B"))), + [](ASTContext &C, Environment &) { + return NoopAnalysis(C, /*ApplyBuiltinTransfer=*/true); + }, + [](llvm::ArrayRef< + std::pair>> + Results, + ASTContext &ASTCtx) { + // Regression test to verify that base-class initializers do not + // trigger an assertion. If we add support for such initializers in + // the future, we can expand this test to check more specific + // properties. + EXPECT_THAT(Results, ElementsAre(Pair("p", _))); + }, + {"-fsyntax-only", "-fno-delayed-template-parsing", + "-std=" + std::string(LangStandard::getLangStandardForKind( + LangStandard::lang_cxx17) + .getName())}), + llvm::Succeeded()); +} + TEST_F(TransferTest, ReferenceMember) { std::string Code = R"( struct A {