Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 121 additions & 8 deletions clang/lib/Analysis/UninitializedValues.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand All @@ -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;
}
};
Expand All @@ -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);
Expand Down Expand Up @@ -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);
Expand All @@ -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.
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -967,4 +1080,4 @@ void clang::runUninitializedVariablesAnalysis(
}
}

UninitVariablesHandler::~UninitVariablesHandler() = default;
UninitVariablesHandler::~UninitVariablesHandler() = default;