[clang] [clang] Add support for uninitialized array access warnings #165239 (PR #166932)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Nov 7 07:27:12 PST 2025
https://github.com/jimmy2683 updated https://github.com/llvm/llvm-project/pull/166932
>From b838084c0c8cfdc534bf18efd799f43f21590e94 Mon Sep 17 00:00:00 2001
From: jimmy2683 <karangupta0805 at gmail.com>
Date: Fri, 7 Nov 2025 11:19:29 +0530
Subject: [PATCH 1/2] Fixing
---
clang/lib/Analysis/UninitializedValues.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/lib/Analysis/UninitializedValues.cpp b/clang/lib/Analysis/UninitializedValues.cpp
index f6b1c67ab20c3..c4c517f8b7644 100644
--- a/clang/lib/Analysis/UninitializedValues.cpp
+++ b/clang/lib/Analysis/UninitializedValues.cpp
@@ -967,4 +967,4 @@ void clang::runUninitializedVariablesAnalysis(
}
}
-UninitVariablesHandler::~UninitVariablesHandler() = default;
+UninitVariablesHandler::~UninitVariablesHandler() = default;
\ No newline at end of file
>From 56bc0ba73a86da93a530993cac66ac7c260b1e20 Mon Sep 17 00:00:00 2001
From: jimmy2683 <karangupta0805 at gmail.com>
Date: Fri, 7 Nov 2025 17:43:33 +0530
Subject: [PATCH 2/2] =?UTF-8?q?Fix:=20Issue=20#165239=20=E2=80=94=20resolv?=
=?UTF-8?q?e=20-Wuninitialized=20warnings?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
clang/lib/Analysis/UninitializedValues.cpp | 127 +++++++++++++++++++--
1 file changed, 120 insertions(+), 7 deletions(-)
diff --git a/clang/lib/Analysis/UninitializedValues.cpp b/clang/lib/Analysis/UninitializedValues.cpp
index c4c517f8b7644..7a3decc927a91 100644
--- a/clang/lib/Analysis/UninitializedValues.cpp
+++ b/clang/lib/Analysis/UninitializedValues.cpp
@@ -62,7 +62,18 @@ static bool isTrackedVar(const VarDecl *vd, const DeclContext *dc) {
QualType ty = vd->getType();
if (const auto *RD = ty->getAsRecordDecl())
return recordIsNotEmpty(RD);
- return ty->isScalarType() || ty->isVectorType() || ty->isRVVSizelessBuiltinType();
+
+ bool isArray = ty->isArrayType();
+ bool result = ty->isScalarType() || ty->isVectorType() || ty->isRVVSizelessBuiltinType() || isArray;
+
+ // Debug output
+ #if DEBUG_LOGGING
+ llvm::errs() << "DEBUG isTrackedVar: " << vd->getNameAsString()
+ << " isArray=" << isArray
+ << " result=" << result << "\n";
+ #endif
+
+ return result;
}
return false;
}
@@ -187,8 +198,8 @@ void CFGBlockValues::computeSetOfDeclarations(const DeclContext &dc) {
static void printVector(const CFGBlock *block, ValueVector &bv,
unsigned num) {
llvm::errs() << block->getBlockID() << " :";
- for (const auto &i : bv)
- llvm::errs() << ' ' << i;
+ for (unsigned i = 0, e = bv.size(); i != e; ++i)
+ llvm::errs() << ' ' << bv[i];
llvm::errs() << " : " << num << '\n';
}
#endif
@@ -291,6 +302,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);
@@ -303,13 +315,19 @@ class ClassifyRefs : public StmtVisitor<ClassifyRefs> {
Class get(const DeclRefExpr *DRE) const {
llvm::DenseMap<const DeclRefExpr*, Class>::const_iterator I
= Classification.find(DRE);
- if (I != Classification.end())
+ if (I != Classification.end()) {
return I->second;
+ }
const auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
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 +349,27 @@ 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 +415,18 @@ void ClassifyRefs::classify(const Expr *E, Class C) {
}
}
+void ClassifyRefs::VisitArraySubscriptExpr(ArraySubscriptExpr *ASE) {
+ // Debug output
+ #if DEBUG_LOGGING
+ llvm::errs() << "DEBUG ClassifyRefs::VisitArraySubscriptExpr called\n";
+ #endif
+
+ // 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 +444,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 +559,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,10 +730,54 @@ class TransferFunctions : public StmtVisitor<TransferFunctions> {
} // namespace
+void TransferFunctions::VisitArraySubscriptExpr(ArraySubscriptExpr *ASE) {
+ // Debug output
+ #if DEBUG_LOGGING
+ llvm::errs() << "DEBUG TransferFunctions::VisitArraySubscriptExpr called\n";
+ #endif
+
+ // Handle array subscript expressions like arr[i]
+ // Check if the base array variable is uninitialized
+ FindVarResult Var = findVar(ASE->getBase());
+
+ #if DEBUG_LOGGING
+ llvm::errs() << "DEBUG: FindVar result: " << (Var.getDecl() ? "found" : "not found") << "\n";
+ if (Var.getDecl()) {
+ llvm::errs() << "DEBUG: Variable name: " << Var.getDecl()->getNameAsString() << "\n";
+ llvm::errs() << "DEBUG: Is array type: " << Var.getDecl()->getType()->isArrayType() << "\n";
+ }
+ #endif
+
+ if (const VarDecl *VD = Var.getDecl()) {
+ if (VD->getType()->isArrayType()) {
+ #if DEBUG_LOGGING
+ llvm::errs() << "DEBUG: Reporting array use for " << VD->getNameAsString() << "\n";
+ #endif
+ reportUse(ASE, VD);
+ }
+ }
+
+ // Also visit index expression
+ Visit(ASE->getIdx());
+}
+
void TransferFunctions::reportUse(const Expr *ex, const VarDecl *vd) {
+ #if DEBUG_LOGGING
+ llvm::errs() << "DEBUG TransferFunctions::reportUse for " << vd->getNameAsString() << "\n";
+ #endif
+
Value v = vals[vd];
- if (isUninitialized(v))
+
+ #if DEBUG_LOGGING
+ llvm::errs() << "DEBUG: Variable " << vd->getNameAsString() << " has value " << v << "\n";
+ #endif
+
+ if (isUninitialized(v)) {
+ #if DEBUG_LOGGING
+ llvm::errs() << "DEBUG: Reporting uninitialized use of " << vd->getNameAsString() << "\n";
+ #endif
handler.handleUseOfUninitVariable(vd, getUninitUse(ex, vd, v));
+ }
}
void TransferFunctions::reportConstRefUse(const Expr *ex, const VarDecl *vd) {
More information about the cfe-commits
mailing list