[clang] [analyzer] Fix uninitialized base class with initializer list when ctor is not declared in the base class (#70464) (PR #70792)

Ella Ma via cfe-commits cfe-commits at lists.llvm.org
Tue Oct 31 09:10:10 PDT 2023


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 <alansnape3058 at 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



More information about the cfe-commits mailing list