[clang] Fix: Issue #165239 — resolve -Wuninitialized warnings (PR #166991)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Nov 7 10:45:12 PST 2025
https://github.com/jimmy2683 created https://github.com/llvm/llvm-project/pull/166991
## c is uninitialized and used in the main function.
#### **Options:** -Wall -Wextra -Wuninitialized -Wconditional-uninitialized -O2
#### **Link:** https://godbolt.org/z/1aMWdEfjr
#### **Code:**
```cpp
int b[24] = {0};
int main() {
int c[24];
for (int d = 0; d < 24; ++d)
b[d] = c[d];
__builtin_printf("%d\n", b[0]);
return 0;
}
```
This might be related to #66448
This patch now handles the uninitialized variable analysis to handle arrays
by handling ArraySubscriptExpr bases as proper variable uses. The fix
ensures warnings are emitted for cases such as:
int arr[5];
int x = arr[0]; // now diagnosed
>From 593fc1b368be26538fe65f650d0074139a683a85 Mon Sep 17 00:00:00 2001
From: jimmy2683 <karangupta0805 at gmail.com>
Date: Fri, 7 Nov 2025 23:58:13 +0530
Subject: [PATCH] =?UTF-8?q?Fix:=20Issue=20#165239=20=E2=80=94=20resolve=20?=
=?UTF-8?q?-Wuninitialized=20warnings?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
clang/docs/ReleaseNotes.rst | 7 ++
clang/lib/Analysis/UninitializedValues.cpp | 75 ++++++++++++++++++++--
clang/test/Sema/uninit-arrays.c | 17 +++++
3 files changed, 94 insertions(+), 5 deletions(-)
create mode 100644 clang/test/Sema/uninit-arrays.c
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 3a4e1fce2511e..931d01ef97ebc 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -414,6 +414,13 @@ Improvements to Clang's diagnostics
- Clang now emits a diagnostic in case `vector_size` or `ext_vector_type`
attributes are used with a negative size (#GH165463).
+- Fixed: ``-Wuninitialized`` now emits a warning for uninitialized fixed-size local arrays. For example:
+
+ .. code-block:: c
+
+ int arr[4];
+ int x = arr[2]; // warning: variable 'arr' is uninitialized when used here (#GH165239)
+
Improvements to Clang's time-trace
----------------------------------
diff --git a/clang/lib/Analysis/UninitializedValues.cpp b/clang/lib/Analysis/UninitializedValues.cpp
index f6b1c67ab20c3..1d14a64e48ef5 100644
--- a/clang/lib/Analysis/UninitializedValues.cpp
+++ b/clang/lib/Analysis/UninitializedValues.cpp
@@ -61,8 +61,8 @@ static bool isTrackedVar(const VarDecl *vd, const DeclContext *dc) {
vd->getDeclContext() == dc) {
QualType ty = vd->getType();
if (const auto *RD = ty->getAsRecordDecl())
- return recordIsNotEmpty(RD);
- return ty->isScalarType() || ty->isVectorType() || ty->isRVVSizelessBuiltinType();
+ return recordIsNotEmpty(RD);
+ return ty->isScalarType() || ty->isVectorType() || ty->isRVVSizelessBuiltinType() || ty->isArrayType();
}
return false;
}
@@ -291,6 +291,7 @@ class ClassifyRefs : public StmtVisitor<ClassifyRefs> {
public:
ClassifyRefs(AnalysisDeclContext &AC) : DC(cast<DeclContext>(AC.getDecl())) {}
+ void VisitArraySubscriptExpr(ArraySubscriptExpr *ASE);
void VisitDeclStmt(DeclStmt *DS);
void VisitUnaryOperator(UnaryOperator *UO);
void VisitBinaryOperator(BinaryOperator *BO);
@@ -310,6 +311,10 @@ class ClassifyRefs : public StmtVisitor<ClassifyRefs> {
if (!VD || !isTrackedVar(VD))
return Ignore;
+ // Default to Use instead of Init for arrays - CRITICAL FIX
+ if (VD->getType()->isArrayType())
+ return Use;
+
return Init;
}
};
@@ -331,6 +336,26 @@ static const DeclRefExpr *getSelfInitExpr(VarDecl *VD) {
void ClassifyRefs::classify(const Expr *E, Class C) {
// The result of a ?: could also be an lvalue.
E = E->IgnoreParens();
+
+ // Handle array subscripts - THE KEY FIX
+ if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(E)) {
+ // For ANY array subscript expression, the base array is being USED
+ // This is the critical fix - don't check C, just mark as Use
+ FindVarResult Var = findVar(ASE->getBase(), DC);
+ if (const VarDecl *VD = Var.getDecl()) {
+ if (VD->getType()->isArrayType()) {
+ // Directly mark the array DeclRefExpr as Use
+ if (const DeclRefExpr *DRE = Var.getDeclRefExpr())
+ Classification[DRE] = Use;
+ }
+ }
+
+ // Process base and index normally
+ classify(ASE->getBase(), C);
+ Visit(const_cast<Expr*>(ASE->getIdx()));
+ return;
+ }
+
if (const auto *CO = dyn_cast<ConditionalOperator>(E)) {
classify(CO->getTrueExpr(), C);
classify(CO->getFalseExpr(), C);
@@ -376,6 +401,13 @@ void ClassifyRefs::classify(const Expr *E, Class C) {
}
}
+void ClassifyRefs::VisitArraySubscriptExpr(ArraySubscriptExpr *ASE) {
+ // For array subscript expressions, classify the base as a use
+ classify(ASE->getBase(), Use);
+ // Also visit the index expression
+ Visit(ASE->getIdx());
+}
+
void ClassifyRefs::VisitDeclStmt(DeclStmt *DS) {
for (auto *DI : DS->decls()) {
auto *VD = dyn_cast<VarDecl>(DI);
@@ -393,10 +425,27 @@ void ClassifyRefs::VisitBinaryOperator(BinaryOperator *BO) {
// use.
if (BO->isCompoundAssignmentOp())
classify(BO->getLHS(), Use);
- else if (BO->getOpcode() == BO_Assign || BO->getOpcode() == BO_Comma)
- classify(BO->getLHS(), Ignore);
+ else if (BO->getOpcode() == BO_Assign || BO->getOpcode() == BO_Comma) {
+ // For array subscript expressions on LHS of assignment, don't classify as use
+ if (isa<ArraySubscriptExpr>(BO->getLHS())) {
+ // Don't classify array base as use when it's being assigned to
+ // But we still need to visit the index expression
+ if (auto *ASE = dyn_cast<ArraySubscriptExpr>(BO->getLHS())) {
+ Visit(ASE->getIdx());
+ }
+ } else {
+ classify(BO->getLHS(), Ignore);
+ }
+ // ALWAYS visit the right-hand side - this is crucial for array subscripts
+ Visit(BO->getRHS());
+ } else {
+ // For all other binary operators, visit both operands normally
+ Visit(BO->getLHS());
+ Visit(BO->getRHS());
+ }
}
+
void ClassifyRefs::VisitUnaryOperator(UnaryOperator *UO) {
// Increment and decrement are uses despite there being no lvalue-to-rvalue
// conversion.
@@ -491,6 +540,7 @@ class TransferFunctions : public StmtVisitor<TransferFunctions> {
void reportConstRefUse(const Expr *ex, const VarDecl *vd);
void reportConstPtrUse(const Expr *ex, const VarDecl *vd);
+ void VisitArraySubscriptExpr(ArraySubscriptExpr *ASE);
void VisitBinaryOperator(BinaryOperator *bo);
void VisitBlockExpr(BlockExpr *be);
void VisitCallExpr(CallExpr *ce);
@@ -661,8 +711,23 @@ class TransferFunctions : public StmtVisitor<TransferFunctions> {
} // namespace
-void TransferFunctions::reportUse(const Expr *ex, const VarDecl *vd) {
+void TransferFunctions::VisitArraySubscriptExpr(ArraySubscriptExpr *ASE) {
+ // Handle array subscript expressions like arr[i]
+ // Check if the base array variable is uninitialized
+ FindVarResult Var = findVar(ASE->getBase());
+
+ if (const VarDecl *VD = Var.getDecl()) {
+ if (VD->getType()->isArrayType())
+ reportUse(ASE, VD);
+ }
+
+ // Also visit index expression
+ Visit(ASE->getIdx());
+}
+
+void TransferFunctions::reportUse(const Expr *ex, const VarDecl *vd) {
Value v = vals[vd];
+
if (isUninitialized(v))
handler.handleUseOfUninitVariable(vd, getUninitUse(ex, vd, v));
}
diff --git a/clang/test/Sema/uninit-arrays.c b/clang/test/Sema/uninit-arrays.c
new file mode 100644
index 0000000000000..fb3a31c225a5b
--- /dev/null
+++ b/clang/test/Sema/uninit-arrays.c
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -Wall -Wextra -Wuninitialized -fsyntax-only %s 2>&1 | FileCheck %s
+
+void test1() {
+ int arr[5];
+ int x = arr[0]; // expected-warning{{variable 'arr' is uninitialized when used here}}
+}
+
+void test2() {
+ int a[3][3];
+ int y = a[1][1]; // expected-warning{{variable 'a' is uninitialized when used here}}
+}
+
+void test3() {
+ int n;
+ int vla[n]; // expected-note{{declared here}}
+ int z = vla[2]; // expected-warning{{variable 'vla' is uninitialized when used here}}
+}
More information about the cfe-commits
mailing list