Enhance -Wuninitialized-experimental diagnostics
to issue the warning at an uninitialized variable's
declaration, but to issue notes at possible
uninitialized uses (which could be multiple).

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@123994 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/AnalysisBasedWarnings.cpp b/lib/Sema/AnalysisBasedWarnings.cpp
index eb8590d..67ddbf5 100644
--- a/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/lib/Sema/AnalysisBasedWarnings.cpp
@@ -364,14 +364,62 @@
 //===----------------------------------------------------------------------===//
 
 namespace {
+struct SLocSort {
+  bool operator()(const DeclRefExpr *a, const DeclRefExpr *b) {
+    SourceLocation aLoc = a->getLocStart();
+    SourceLocation bLoc = b->getLocStart();
+    return aLoc.getRawEncoding() < bLoc.getRawEncoding();
+  }
+};
+
 class UninitValsDiagReporter : public UninitVariablesHandler {
   Sema &S;
+  typedef llvm::SmallVector<const DeclRefExpr *, 2> UsesVec;
+  typedef llvm::DenseMap<const VarDecl *, UsesVec*> UsesMap;
+  UsesMap *uses;
+  
 public:
-  UninitValsDiagReporter(Sema &S) : S(S) {}
+  UninitValsDiagReporter(Sema &S) : S(S), uses(0) {}
+  ~UninitValsDiagReporter() { 
+    flushDiagnostics();
+  }
   
   void handleUseOfUninitVariable(const DeclRefExpr *dr, const VarDecl *vd) {
-    S.Diag(dr->getLocStart(), diag::warn_var_is_uninit)
-      << vd->getDeclName() << dr->getSourceRange();
+    if (!uses)
+      uses = new UsesMap();
+    
+    UsesVec *&vec = (*uses)[vd];
+    if (!vec)
+      vec = new UsesVec();
+    
+    vec->push_back(dr);    
+  }
+  
+  void flushDiagnostics() {
+    if (!uses)
+      return;
+
+    for (UsesMap::iterator i = uses->begin(), e = uses->end(); i != e; ++i) {
+      const VarDecl *vd = i->first;
+      UsesVec *vec = i->second;
+      
+      S.Diag(vd->getLocStart(), diag::warn_var_is_uninit)
+        << vd->getDeclName() << vd->getSourceRange();
+
+      // Sort the uses by their SourceLocations.  While not strictly
+      // guaranteed to produce them in line/column order, this will provide
+      // a stable ordering.
+      std::sort(vec->begin(), vec->end(), SLocSort());
+      
+      for (UsesVec::iterator vi = vec->begin(), ve = vec->end(); vi != ve; ++vi)
+      {
+        const DeclRefExpr *dr = *vi;
+        S.Diag(dr->getLocStart(), diag::note_var_is_uninit)
+          << vd->getDeclName() << dr->getSourceRange();
+      }
+      delete vec;
+    }
+    delete uses;
   }
 };
 }