From: Ted Kremenek Date: Mon, 4 Apr 2011 20:56:00 +0000 (+0000) Subject: -Wuninitialized: use "self-init" warning when issue uninitialized values warnings... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6f41715df2c6a31c0c3ab3088b8cd18a3c8321b8;p=clang -Wuninitialized: use "self-init" warning when issue uninitialized values warnings from the dataflow analysis that include within the initializer of a variable. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@128843 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/AnalysisBasedWarnings.cpp b/lib/Sema/AnalysisBasedWarnings.cpp index 75e2c5b8ac..3467dae4ba 100644 --- a/lib/Sema/AnalysisBasedWarnings.cpp +++ b/lib/Sema/AnalysisBasedWarnings.cpp @@ -24,6 +24,7 @@ #include "clang/AST/ExprCXX.h" #include "clang/AST/StmtObjC.h" #include "clang/AST/StmtCXX.h" +#include "clang/AST/EvaluatedExprVisitor.h" #include "clang/Analysis/AnalysisContext.h" #include "clang/Analysis/CFG.h" #include "clang/Analysis/Analyses/ReachableCode.h" @@ -377,6 +378,45 @@ static void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body, // -Wuninitialized //===----------------------------------------------------------------------===// +namespace { +class ContainsReference : public EvaluatedExprVisitor { + bool containsReference; + const DeclRefExpr *dr; +public: + ContainsReference(ASTContext &context, + const DeclRefExpr *dr) : + EvaluatedExprVisitor(context), + containsReference(false), dr(dr) {} + + void VisitExpr(Expr *e) { + // Stop evaluating if we already have a reference. + if (containsReference) + return; + + EvaluatedExprVisitor::VisitExpr(e); + } + + void VisitDeclRefExpr(DeclRefExpr *e) { + if (e == dr) + containsReference = true; + else + EvaluatedExprVisitor::VisitDeclRefExpr(e); + } + + bool doesContainReference() const { return containsReference; } +}; +} + +static bool isSelfInit(ASTContext &context, + const VarDecl *vd, const DeclRefExpr *dr) { + if (const Expr *exp = vd->getInit()) { + ContainsReference contains(context, dr); + contains.Visit(const_cast(exp)); + return contains.doesContainReference(); + } + return false; +} + typedef std::pair UninitUse; namespace { @@ -432,8 +472,11 @@ public: const bool isAlwaysUninit = vi->second; if (const DeclRefExpr *dr = dyn_cast(vi->first)) { S.Diag(dr->getLocStart(), - isAlwaysUninit ? diag::warn_uninit_var - : diag::warn_maybe_uninit_var) + isAlwaysUninit ? + (isSelfInit(S.Context, vd, dr) + ? diag::warn_uninit_self_reference_in_init + : diag::warn_uninit_var) + : diag::warn_maybe_uninit_var) << vd->getDeclName() << dr->getSourceRange(); } else { diff --git a/test/Sema/uninit-variables.c b/test/Sema/uninit-variables.c index 3ddd097c8f..e0558ccc78 100644 --- a/test/Sema/uninit-variables.c +++ b/test/Sema/uninit-variables.c @@ -92,7 +92,7 @@ void test14() { } void test15() { - int x = x; // expected-warning{{variable 'x' is possibly uninitialized when used here}} expected-note{{variable 'x' is declared here}} + int x = x; // expected-warning{{variable 'x' is uninitialized when used within its own initialization}} expected-note{{variable 'x' is declared here}} } // Don't warn in the following example; shows dataflow confluence.