llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Jimmy2683 (jimmy2683) <details> <summary>Changes</summary> ## 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 --- Full diff: https://github.com/llvm/llvm-project/pull/166991.diff 3 Files Affected: - (modified) clang/docs/ReleaseNotes.rst (+7) - (modified) clang/lib/Analysis/UninitializedValues.cpp (+70-5) - (added) clang/test/Sema/uninit-arrays.c (+17) ``````````diff 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}} +} `````````` </details> https://github.com/llvm/llvm-project/pull/166991 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
