From 57fb591a54eab7db65d73e77c632f047bca22c54 Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Thu, 4 Aug 2011 22:40:57 +0000 Subject: [PATCH] Fix assertion failure in -Wuninitialized involving no-op casts. Fixes PR 10577. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@136939 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Analysis/UninitializedValues.cpp | 24 +++++++++++++++++++----- test/SemaCXX/uninit-variables.cpp | 11 +++++++++++ 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/lib/Analysis/UninitializedValues.cpp b/lib/Analysis/UninitializedValues.cpp index 7df2dc27b8..009922ae92 100644 --- a/lib/Analysis/UninitializedValues.cpp +++ b/lib/Analysis/UninitializedValues.cpp @@ -352,13 +352,19 @@ class TransferFunctions : public StmtVisitor { /// possible to either silence the warning in some cases, or we /// propagate the uninitialized value. CastExpr *lastLoad; + + /// For some expressions, we want to ignore any post-processing after + /// visitation. + bool skipProcessUses; + public: TransferFunctions(CFGBlockValues &vals, const CFG &cfg, AnalysisContext &ac, UninitVariablesHandler *handler, bool flagBlockUses) : vals(vals), cfg(cfg), ac(ac), handler(handler), - flagBlockUses(flagBlockUses), lastDR(0), lastLoad(0) {} + flagBlockUses(flagBlockUses), lastDR(0), lastLoad(0), + skipProcessUses(false) {} const CFG &getCFG() { return cfg; } void reportUninit(const DeclRefExpr *ex, const VarDecl *vd, @@ -464,8 +470,9 @@ void TransferFunctions::VisitDeclStmt(DeclStmt *ds) { // appropriately, but we need to continue to analyze subsequent uses // of the variable. if (init == lastLoad) { - DeclRefExpr *DR = - cast(lastLoad->getSubExpr()->IgnoreParens()); + DeclRefExpr *DR + = cast(lastLoad-> + getSubExpr()->IgnoreParenNoopCasts(ac.getASTContext())); if (DR->getDecl() == vd) { // int x = x; // Propagate uninitialized value, but don't immediately report @@ -537,6 +544,9 @@ void TransferFunctions::VisitCastExpr(clang::CastExpr *ce) { } } } + else if (ce->getCastKind() == CK_NoOp) { + skipProcessUses = true; + } else if (CStyleCastExpr *cse = dyn_cast(ce)) { if (cse->getType()->isVoidType()) { // e.g. (void) x; @@ -551,8 +561,10 @@ void TransferFunctions::VisitCastExpr(clang::CastExpr *ce) { } void TransferFunctions::Visit(clang::Stmt *s) { + skipProcessUses = false; StmtVisitor::Visit(s); - ProcessUses(s); + if (!skipProcessUses) + ProcessUses(s); } void TransferFunctions::ProcessUses(Stmt *s) { @@ -568,7 +580,9 @@ void TransferFunctions::ProcessUses(Stmt *s) { // If we reach here, we have seen a load of an uninitialized value // and it hasn't been casted to void or otherwise handled. In this // situation, report the incident. - DeclRefExpr *DR = cast(lastLoad->getSubExpr()->IgnoreParens()); + DeclRefExpr *DR = + cast(lastLoad->getSubExpr()-> + IgnoreParenNoopCasts(ac.getASTContext())); VarDecl *VD = cast(DR->getDecl()); reportUninit(DR, VD, isAlwaysUninit(vals[VD])); lastLoad = 0; diff --git a/test/SemaCXX/uninit-variables.cpp b/test/SemaCXX/uninit-variables.cpp index a850a2f92f..6c5d0068a4 100644 --- a/test/SemaCXX/uninit-variables.cpp +++ b/test/SemaCXX/uninit-variables.cpp @@ -118,4 +118,15 @@ void RDar9251392() { } } +// Test handling of "no-op" casts. +void test_noop_cast() +{ + int x = 1; + int y = (int&)x; // no-warning +} + +void test_noop_cast2() { + int x; // expected-note {{declared here}} expected-note {{add initialization}} + int y = (int&)x; // expected-warning {{uninitialized when used here}} +}