[clang] [SSAF][PointerFlowExtractor] Handle empty initializer lists for scalars and unions (PR #201968)

Ziqing Luo via cfe-commits cfe-commits at lists.llvm.org
Fri Jun 5 16:50:12 PDT 2026


https://github.com/ziqingluo-90 updated https://github.com/llvm/llvm-project/pull/201968

>From 53e1c96fb472bf7243e960ab4e6a9a79cb4e2b71 Mon Sep 17 00:00:00 2001
From: Ziqing Luo <ziqing_luo at apple.com>
Date: Fri, 5 Jun 2026 16:35:10 -0700
Subject: [PATCH 1/2] [SSAF][PointerFlowExtractor] Handle empty initializer
 lists for scalars and unions

Empty initializer lists for scalars and unions are corner cases that
were previously missed by the PointerFlowExtractor. This commit adds
support for these cases. Because the initializing values are
implicitly constant 0 (or nullptr), they do not bridge entity pointer
levels.

rdar://178856689
---
 .../PointerFlow/PointerFlowExtractor.cpp      |  9 ++++--
 .../Analyses/PointerFlow/PointerFlowTest.cpp  | 32 +++++++++++++++++++
 2 files changed, 38 insertions(+), 3 deletions(-)

diff --git a/clang/lib/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowExtractor.cpp b/clang/lib/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowExtractor.cpp
index e1130a2c52e4c..822022864ed49 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowExtractor.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowExtractor.cpp
@@ -222,9 +222,8 @@ llvm::Error matchInitializerListForRecordDecl(PointerFlowMatcher &Matcher,
   if (RecordTy->isUnion()) {
     auto *InitField = ILE->getInitializedFieldInUnion();
 
-    if (!InitField)
+    if (!InitField || ILE->inits().empty())
       return llvm::Error::success();
-    assert(!ILE->inits().empty());
     return Matcher.matchesInitializerList(InitField, ILE->getInit(0));
   }
   // Handle struct/class:
@@ -299,7 +298,11 @@ PointerFlowMatcher::matchesInitializerList(const ValueDecl *Base,
   if (Type->isArrayType())
     return matchInitializerListForArray(*this, Base, ILE,
                                         ArrayElementIndirectLevel);
-  // Must be the case of using a initializer-list for a scalar:
+
+  // Must be the case of using a initializer-list for a scalar.
+  // The initializer-list can be either singleton or empty:
+  if (ILE->getNumInits() == 0)
+    return llvm::Error::success();
   return matchesInitializerList(Base, ILE->getInit(0));
 }
 
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowTest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowTest.cpp
index 9f7a508ea35fd..404730d4c2861 100644
--- a/clang/unittests/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowTest.cpp
+++ b/clang/unittests/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowTest.cpp
@@ -967,6 +967,38 @@ TEST_F(PointerFlowTest, ArrayOfStructInitList) {
                                       }));
 }
 
+TEST_F(PointerFlowTest, EmptyInitsScalarInt) {
+  ASSERT_EQ(setUpTest(R"cpp(
+    void foo() {
+      int x{};
+      int y = {};
+      int *p{};
+      int *q = {};
+    }
+  )cpp"),
+            true);
+
+  auto *Sum = getEntitySummary("foo");
+
+  // No pointer-flow edge for 0-initialized scalar.
+  ASSERT_EQ(Sum, nullptr);
+}
+
+TEST_F(PointerFlowTest, EmptyInitsUnion) {
+  ASSERT_EQ(setUpTest(R"cpp(
+    union U { int x; int *p; };
+    void foo() {
+      U u{};
+      U uu = {};
+    }
+  )cpp"),
+            true);
+
+  auto *Sum = getEntitySummary("foo");
+
+  ASSERT_EQ(Sum, nullptr);
+}
+
 //////////////////////////////////////////////////////////////
 //              Return Tests.                               //
 //////////////////////////////////////////////////////////////

>From 8abc7f5ef8ff5dbe9e5c00dd4159161f1ba4980a Mon Sep 17 00:00:00 2001
From: Ziqing Luo <ziqing_luo at apple.com>
Date: Fri, 5 Jun 2026 16:49:40 -0700
Subject: [PATCH 2/2] add test for brace-init scalar pointer

---
 .../Analyses/PointerFlow/PointerFlowTest.cpp      | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/clang/unittests/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowTest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowTest.cpp
index 404730d4c2861..fde1f3201f9b4 100644
--- a/clang/unittests/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowTest.cpp
+++ b/clang/unittests/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowTest.cpp
@@ -967,6 +967,21 @@ TEST_F(PointerFlowTest, ArrayOfStructInitList) {
                                       }));
 }
 
+TEST_F(PointerFlowTest, ScalarPointerBraceInit) {
+  ASSERT_EQ(setUpTest(R"cpp(
+    int *q;
+    void foo() {
+      int *p{q};
+    }
+  )cpp"),
+            true);
+
+  auto *Sum = getEntitySummary("foo");
+
+  ASSERT_NE(Sum, nullptr);
+  EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"p", 1U}, {"q", 1U}}}));
+}
+
 TEST_F(PointerFlowTest, EmptyInitsScalarInt) {
   ASSERT_EQ(setUpTest(R"cpp(
     void foo() {



More information about the cfe-commits mailing list