https://github.com/Snape3058 updated https://github.com/llvm/llvm-project/pull/70792
>From fa7f1d1a862d584d42e9f4a44660f6f61501b150 Mon Sep 17 00:00:00 2001 From: Ella Ma <alansnape3...@gmail.com> Date: Tue, 31 Oct 2023 18:41:14 +0800 Subject: [PATCH] [analyzer] Fix uninitialized base class with initializer list when ctor is not declared in the base class Fixes #70464 When ctor is not declared in the base class, initializing the base class with the initializer list will not trigger a proper assignment of the base region, as a CXXConstructExpr doing that is not available in the AST. This patch checks whether the init expr is an InitListExpr under a base initializer, and adds a binding if so. --- clang/lib/StaticAnalyzer/Core/ExprEngine.cpp | 8 +++ clang/test/Analysis/issue-70464.cpp | 68 ++++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 clang/test/Analysis/issue-70464.cpp diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp index 2e67fb953e45611..24e91a22fd6884f 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -1222,6 +1222,14 @@ void ExprEngine::ProcessInitializer(const CFGInitializer CFGInit, PostInitializer PP(BMI, FieldLoc.getAsRegion(), stackFrame); evalBind(Tmp, Init, Pred, FieldLoc, InitVal, /*isInit=*/true, &PP); } + } else if (BMI->isBaseInitializer() && isa<InitListExpr>(Init)) { + // When the base class is initialized with an initialization list and the + // base class does not have a ctor, there will not be a CXXConstructExpr to + // initialize the base region. Hence, we need to make the bind for it. + SVal BaseLoc = getStoreManager().evalDerivedToBase( + thisVal, QualType(BMI->getBaseClass(), 0), BMI->isBaseVirtual()); + SVal InitVal = State->getSVal(Init, stackFrame); + evalBind(Tmp, Init, Pred, BaseLoc, InitVal, /*isInit=*/true); } else { assert(BMI->isBaseInitializer() || BMI->isDelegatingInitializer()); Tmp.insert(Pred); diff --git a/clang/test/Analysis/issue-70464.cpp b/clang/test/Analysis/issue-70464.cpp new file mode 100644 index 000000000000000..f3b3072eb919823 --- /dev/null +++ b/clang/test/Analysis/issue-70464.cpp @@ -0,0 +1,68 @@ +// RUN: %clang_analyze_cc1 %s -verify -analyzer-checker=core,debug.ExprInspection + +// Refer to https://github.com/llvm/llvm-project/issues/70464 for more details. +// +// When the base class does not have a declared constructor, the base +// initializer in the constructor of the derived class should use the given +// initializer list to finish the initialization of the base class. +// +// Also testing base constructor and delegate constructor to make sure this +// change will not break these two cases when a CXXConstructExpr is available. + +void clang_analyzer_dump(int); + +namespace init_list { + +struct Base { + int foox; +}; + +class Derived : public Base { +public: + Derived() : Base{42} { + // The dereference to this->foox below should be initialized properly. + clang_analyzer_dump(this->foox); // expected-warning{{42 S32b}} + clang_analyzer_dump(foox); // expected-warning{{42 S32b}} + } +}; + +void entry() { Derived test; } + +} // namespace init_list + +namespace base_ctor_call { + +struct Base { + int foox; + Base(int x) : foox(x) {} +}; + +class Derived : public Base { +public: + Derived() : Base{42} { + clang_analyzer_dump(this->foox); // expected-warning{{42 S32b}} + clang_analyzer_dump(foox); // expected-warning{{42 S32b}} + } +}; + +void entry() { Derived test; } + +} // namespace base_ctor_call + +namespace delegate_ctor_call { + +struct Base { + int foox; +}; + +struct Derived : Base { + Derived(int parx) { this->foox = parx; } + Derived() : Derived{42} { + clang_analyzer_dump(this->foox); // expected-warning{{42 S32b}} + clang_analyzer_dump(foox); // expected-warning{{42 S32b}} + } +}; + +void entry() { Derived test; } + +} // namespace delegate_ctor_call _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits