Author: Yitzhak Mandelbaum Date: 2022-05-27T13:54:11Z New Revision: 3682e22ef404e1314ee1eab9daf6de99dc9ea8ee
URL: https://github.com/llvm/llvm-project/commit/3682e22ef404e1314ee1eab9daf6de99dc9ea8ee DIFF: https://github.com/llvm/llvm-project/commit/3682e22ef404e1314ee1eab9daf6de99dc9ea8ee.diff LOG: [clang][dataflow] Improve handling of constructor initializers. Currently, we assert that `CXXCtorInitializer`s are field initializers. Replace the assertion with an early return. Otherwise, we crash every time we process a constructor with a non-field (e.g. base class) initializer. Differential Revision: https://reviews.llvm.org/D126419 Added: Modified: clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp clang/unittests/Analysis/FlowSensitive/TransferTest.cpp Removed: ################################################################################ diff --git a/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp b/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp index ee1723dcd8cc..8a5d5ca386af 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 dbf59bf69556..efea7797b45f 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<NoopAnalysis>( + Code, cxxConstructorDecl(ofClass(hasName("B"))), + [](ASTContext &C, Environment &) { + return NoopAnalysis(C, /*ApplyBuiltinTransfer=*/true); + }, + [](llvm::ArrayRef< + std::pair<std::string, DataflowAnalysisState<NoopLattice>>> + 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 { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits