diff --git a/clang/lib/Analysis/UninitializedValues.cpp b/clang/lib/Analysis/UninitializedValues.cpp index f6b1c67ab20c3..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 { public: ClassifyRefs(AnalysisDeclContext &AC) : DC(cast(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 { Class get(const DeclRefExpr *DRE) const { llvm::DenseMap::const_iterator I = Classification.find(DRE); - if (I != Classification.end()) + if (I != Classification.end()) { return I->second; + } const auto *VD = dyn_cast(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(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(ASE->getIdx())); + return; + } + if (const auto *CO = dyn_cast(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(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(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(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 { 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 { } // 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) { @@ -967,4 +1080,4 @@ void clang::runUninitializedVariablesAnalysis( } } -UninitVariablesHandler::~UninitVariablesHandler() = default; +UninitVariablesHandler::~UninitVariablesHandler() = default; \ No newline at end of file