https://github.com/jimmy2683 created https://github.com/llvm/llvm-project/pull/166932
## 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 ## Problem Clang does not warn about uninitialized array access while GCC does: ```cpp int main() { int arr[5]; int x = arr[0]; // GCC warns: 'arr' may be used uninitialized // Clang: no warning return x; } ``` ## Root Cause Analysis The issue was in `clang/lib/Analysis/UninitializedValues.cpp`: 1. **Array Tracking**: Arrays were included in `isTrackedVar()` but not properly classified 2. **Classification Issue**: Array subscript expressions like `arr[0]` were defaulting to "Init" instead of "Use" 3. **Missing Logic**: No specific handling for `ArraySubscriptExpr` in classification ## Solution ### Key Changes Made 1. **Enhanced `isTrackedVar()`** (line ~69): ```cpp bool isArray = ty->isArrayType(); bool result = ty->isScalarType() || ty->isVectorType() || ty->isRVVSizelessBuiltinType() || isArray; return result; ``` 2. **Fixed `ClassifyRefs::get()`** (line ~298): ```cpp // Default to Use instead of Init for arrays - CRITICAL FIX if (VD->getType()->isArrayType()) { return Use; } ``` 3. **Added Array Subscript Handling in `classify()`** (line ~332): ```cpp // 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 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; } } } // ... rest of processing } ``` 4. **Improved Binary Operator Handling** (line ~383): ```cpp // 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()); ``` ## Test Results ### Before Fix: ```bash $ clang -Wuninitialized problem.cpp # No warnings ``` ### After Fix: ```bash $ clang -Wuninitialized problem.cpp problem.cpp:5:12: warning: variable 'c' is uninitialized when used here [-Wuninitialized] 5 | b[d] = c[d]; | ^ problem.cpp:3:3: note: variable 'c' is declared here 3 | int c[24]; | ^ 1 warning generated. ``` >From b838084c0c8cfdc534bf18efd799f43f21590e94 Mon Sep 17 00:00:00 2001 From: jimmy2683 <[email protected]> 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 <[email protected]> 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) { _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
