]> granicus.if.org Git - clang/commitdiff
-Wuninitialized: use "self-init" warning when issue uninitialized values warnings...
authorTed Kremenek <kremenek@apple.com>
Mon, 4 Apr 2011 20:56:00 +0000 (20:56 +0000)
committerTed Kremenek <kremenek@apple.com>
Mon, 4 Apr 2011 20:56:00 +0000 (20:56 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@128843 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/AnalysisBasedWarnings.cpp
test/Sema/uninit-variables.c

index 75e2c5b8ac1a3873218dfa96e9eb48af650a417e..3467dae4ba67424dd14a921d626813f322b238ce 100644 (file)
@@ -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<ContainsReference> {
+  bool containsReference;
+  const DeclRefExpr *dr;  
+public:
+  ContainsReference(ASTContext &context,
+                    const DeclRefExpr *dr) :
+    EvaluatedExprVisitor<ContainsReference>(context),
+    containsReference(false), dr(dr) {}
+  
+  void VisitExpr(Expr *e) {
+    // Stop evaluating if we already have a reference.
+    if (containsReference)
+      return;
+    
+    EvaluatedExprVisitor<ContainsReference>::VisitExpr(e);
+  }
+  
+  void VisitDeclRefExpr(DeclRefExpr *e) {
+    if (e == dr)
+      containsReference = true;
+    else 
+      EvaluatedExprVisitor<ContainsReference>::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<Expr*>(exp));
+    return contains.doesContainReference();
+  }
+  return false;
+}
+
 typedef std::pair<const Expr*, bool> UninitUse;
 
 namespace {
@@ -432,8 +472,11 @@ public:
         const bool isAlwaysUninit = vi->second;
         if (const DeclRefExpr *dr = dyn_cast<DeclRefExpr>(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 {
index 3ddd097c8f279226f6211a0018187eee8b5bf81d..e0558ccc78c6c5effa755bd5280be409e870f11a 100644 (file)
@@ -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.