[cfe-commits] r123777 - in /cfe/trunk: lib/Analysis/UninitializedValuesV2.cpp lib/Sema/AnalysisBasedWarnings.cpp test/Sema/uninit-variables.c test/SemaCXX/uninit-variables.cpp
Ted Kremenek
kremenek at apple.com
Tue Jan 18 13:18:58 PST 2011
Author: kremenek
Date: Tue Jan 18 15:18:58 2011
New Revision: 123777
URL: http://llvm.org/viewvc/llvm-project?rev=123777&view=rev
Log:
Teach UninitializedValuesV2 to implicitly reason about C++
references by monitoring whether an access to
a variable is solely to compute it's lvalue or
to do an lvalue-to-rvalue conversion (i.e., a load).
Added:
cfe/trunk/test/SemaCXX/uninit-variables.cpp
Modified:
cfe/trunk/lib/Analysis/UninitializedValuesV2.cpp
cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp
cfe/trunk/test/Sema/uninit-variables.c
Modified: cfe/trunk/lib/Analysis/UninitializedValuesV2.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/UninitializedValuesV2.cpp?rev=123777&r1=123776&r2=123777&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/UninitializedValuesV2.cpp (original)
+++ cfe/trunk/lib/Analysis/UninitializedValuesV2.cpp Tue Jan 18 15:18:58 2011
@@ -19,6 +19,7 @@
#include "clang/Analysis/CFG.h"
#include "clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h"
#include "clang/Analysis/Analyses/UninitializedValuesV2.h"
+#include "clang/Analysis/Support/SaveAndRestore.h"
using namespace clang;
@@ -218,15 +219,17 @@
CFGBlockValues &vals;
const CFG &cfg;
UninitVariablesHandler *handler;
+ const DeclRefExpr *currentDR;
public:
TransferFunctions(CFGBlockValues &vals, const CFG &cfg,
UninitVariablesHandler *handler)
- : vals(vals), cfg(cfg), handler(handler) {}
+ : vals(vals), cfg(cfg), handler(handler), currentDR(0) {}
const CFG &getCFG() { return cfg; }
void reportUninit(const DeclRefExpr *ex, const VarDecl *vd);
void VisitDeclStmt(DeclStmt *ds);
+ void VisitDeclRefExpr(DeclRefExpr *dr);
void VisitUnaryOperator(UnaryOperator *uo);
void VisitBinaryOperator(BinaryOperator *bo);
void VisitCastExpr(CastExpr *ce);
@@ -249,10 +252,28 @@
vals[vd] = Initialized;
}
}
+ else if (Stmt *init = vd->getInit()) {
+ Visit(init);
+ }
}
}
}
+void TransferFunctions::VisitDeclRefExpr(DeclRefExpr *dr) {
+ // We assume that DeclRefExprs wrapped in an lvalue-to-rvalue cast
+ // cannot be block-level expressions. Therefore, we determine if
+ // a DeclRefExpr is involved in a "load" by comparing it to the current
+ // DeclRefExpr found when analyzing the last lvalue-to-rvalue CastExpr.
+ // If a DeclRefExpr is not involved in a load, we are essentially computing
+ // its address, either for assignment to a reference or via the '&' operator.
+ // In such cases, treat the variable as being initialized, since this
+ // analysis isn't powerful enough to do alias tracking.
+ if (dr != currentDR)
+ if (const VarDecl *vd = dyn_cast<VarDecl>(dr->getDecl()))
+ if (isTrackedVar(vd))
+ vals[vd] = Initialized;
+}
+
static FindVarResult findBlockVarDecl(Expr* ex) {
if (DeclRefExpr* dr = dyn_cast<DeclRefExpr>(ex->IgnoreParenCasts()))
if (VarDecl *vd = dyn_cast<VarDecl>(dr->getDecl()))
@@ -263,55 +284,86 @@
}
void TransferFunctions::VisitBinaryOperator(clang::BinaryOperator *bo) {
- Visit(bo->getRHS());
- Visit(bo->getLHS());
if (bo->isAssignmentOp()) {
const FindVarResult &res = findBlockVarDecl(bo->getLHS());
if (const VarDecl* vd = res.getDecl()) {
+ // We assume that DeclRefExprs wrapped in a BinaryOperator "assignment"
+ // cannot be block-level expressions. Therefore, we determine if
+ // a DeclRefExpr is involved in a "load" by comparing it to the current
+ // DeclRefExpr found when analyzing the last lvalue-to-rvalue CastExpr.
+ SaveAndRestore<const DeclRefExpr*> lastDR(currentDR,
+ res.getDeclRefExpr());
+ Visit(bo->getRHS());
+ Visit(bo->getLHS());
+
llvm::BitVector::reference bit = vals[vd];
if (bit == Uninitialized) {
if (bo->getOpcode() != BO_Assign)
reportUninit(res.getDeclRefExpr(), vd);
bit = Initialized;
}
+ return;
}
}
+ Visit(bo->getRHS());
+ Visit(bo->getLHS());
}
void TransferFunctions::VisitUnaryOperator(clang::UnaryOperator *uo) {
- Visit(uo->getSubExpr());
switch (uo->getOpcode()) {
- case clang::UO_AddrOf:
- if (const VarDecl *vd = findBlockVarDecl(uo->getSubExpr()).getDecl())
- vals[vd] = Initialized;
- break;
case clang::UO_PostDec:
case clang::UO_PostInc:
case clang::UO_PreDec:
case clang::UO_PreInc: {
const FindVarResult &res = findBlockVarDecl(uo->getSubExpr());
if (const VarDecl *vd = res.getDecl()) {
+ // We assume that DeclRefExprs wrapped in a unary operator ++/--
+ // cannot be block-level expressions. Therefore, we determine if
+ // a DeclRefExpr is involved in a "load" by comparing it to the current
+ // DeclRefExpr found when analyzing the last lvalue-to-rvalue CastExpr.
+ SaveAndRestore<const DeclRefExpr*> lastDR(currentDR,
+ res.getDeclRefExpr());
+ Visit(uo->getSubExpr());
+
llvm::BitVector::reference bit = vals[vd];
if (bit == Uninitialized) {
reportUninit(res.getDeclRefExpr(), vd);
bit = Initialized;
}
+ return;
}
break;
}
default:
break;
}
+ Visit(uo->getSubExpr());
}
void TransferFunctions::VisitCastExpr(clang::CastExpr *ce) {
- Visit(ce->getSubExpr());
if (ce->getCastKind() == CK_LValueToRValue) {
const FindVarResult &res = findBlockVarDecl(ce->getSubExpr());
- if (const VarDecl *vd = res.getDecl())
- if (vals[vd] == Uninitialized)
+ if (const VarDecl *vd = res.getDecl()) {
+ // We assume that DeclRefExprs wrapped in an lvalue-to-rvalue cast
+ // cannot be block-level expressions. Therefore, we determine if
+ // a DeclRefExpr is involved in a "load" by comparing it to the current
+ // DeclRefExpr found when analyzing the last lvalue-to-rvalue CastExpr.
+ // Here we update 'currentDR' to be the one associated with this
+ // lvalue-to-rvalue cast. Then, when we analyze the DeclRefExpr, we
+ // will know that we are not computing its lvalue for other purposes
+ // than to perform a load.
+ SaveAndRestore<const DeclRefExpr*> lastDR(currentDR,
+ res.getDeclRefExpr());
+ Visit(ce->getSubExpr());
+ if (vals[vd] == Uninitialized) {
reportUninit(res.getDeclRefExpr(), vd);
- }
+ // Don't cascade warnings.
+ vals[vd] = Initialized;
+ }
+ return;
+ }
+ }
+ Visit(ce->getSubExpr());
}
//------------------------------------------------------------------------====//
Modified: cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp?rev=123777&r1=123776&r2=123777&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp (original)
+++ cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp Tue Jan 18 15:18:58 2011
@@ -442,13 +442,9 @@
if (Diags.getDiagnosticLevel(diag::warn_var_is_uninit, D->getLocStart())
!= Diagnostic::Ignored) {
- if (!S.getLangOptions().CPlusPlus) {
- CFG *cfg = AC.getCFG();
- if (cfg) {
- UninitValsDiagReporter reporter(S);
- runUninitializedVariablesAnalysis(*cast<DeclContext>(D), *cfg,
- reporter);
- }
+ if (CFG *cfg = AC.getCFG()) {
+ UninitValsDiagReporter reporter(S);
+ runUninitializedVariablesAnalysis(*cast<DeclContext>(D), *cfg, reporter);
}
}
}
Modified: cfe/trunk/test/Sema/uninit-variables.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/uninit-variables.c?rev=123777&r1=123776&r2=123777&view=diff
==============================================================================
--- cfe/trunk/test/Sema/uninit-variables.c (original)
+++ cfe/trunk/test/Sema/uninit-variables.c Tue Jan 18 15:18:58 2011
@@ -102,3 +102,12 @@
for (unsigned i = 0 ; i < 100 ; i++)
p[i] = 'a'; // no-warning
}
+
+void test17() {
+ // Don't warn multiple times about the same uninitialized variable
+ // along the same path.
+ int *x;
+ *x = 1; // expected-warning{{use of uninitialized variable 'x'}}
+ *x = 1; // no-warning
+}
+
Added: cfe/trunk/test/SemaCXX/uninit-variables.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/uninit-variables.cpp?rev=123777&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/uninit-variables.cpp (added)
+++ cfe/trunk/test/SemaCXX/uninit-variables.cpp Tue Jan 18 15:18:58 2011
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -fsyntax-only -Wuninitialized-experimental -fsyntax-only %s -verify
+
+int test1_aux(int &x);
+int test1() {
+ int x;
+ test1_aux(x);
+ return x; // no-warning
+}
+
+int test2_aux() {
+ int x;
+ int &y = x;
+ return x; // no-warning
+}
+
More information about the cfe-commits
mailing list