[cfe-commits] r162028 - in /cfe/trunk: include/clang/StaticAnalyzer/Core/ include/clang/StaticAnalyzer/Core/BugReporter/ include/clang/StaticAnalyzer/Core/PathSensitive/ lib/StaticAnalyzer/Core/ lib/StaticAnalyzer/Frontend/ test/Analysis/

Ted Kremenek kremenek at apple.com
Thu Aug 16 10:45:23 PDT 2012


Author: kremenek
Date: Thu Aug 16 12:45:23 2012
New Revision: 162028

URL: http://llvm.org/viewvc/llvm-project?rev=162028&view=rev
Log:
Allow multiple PathDiagnosticConsumers to be used with a BugReporter at the same time.

This fixes several issues:

- removes egregious hack where PlistDiagnosticConsumer would forward to HTMLDiagnosticConsumer,
but diagnostics wouldn't be generated consistently in the same way if PlistDiagnosticConsumer
was used by itself.

- emitting diagnostics to the terminal (using clang's diagnostic machinery) is no longer a special
case, just another PathDiagnosticConsumer.  This also magically resolved some duplicate warnings,
as we now use PathDiagnosticConsumer's diagnostic pruning, which has scope for the entire translation
unit, not just the scope of a BugReporter (which is limited to a particular ExprEngine).

As an interesting side-effect, diagnostics emitted to the terminal also have their trailing "." stripped,
just like with diagnostics emitted to plists and HTML.  This required some tests to be updated, but now
the tests have higher fidelity with what users will see.

There are some inefficiencies in this patch.  We currently generate the report graph (from the ExplodedGraph)
once per PathDiagnosticConsumer, which is a bit wasteful, but that could be pulled up higher in the
logic stack.  There is some intended duplication, however, as we now generate different PathDiagnostics (for the same issue)
for different PathDiagnosticConsumers.  This is necessary to produce the diagnostics that a particular
consumer expects.

Modified:
    cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
    cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
    cfe/trunk/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h
    cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h
    cfe/trunk/lib/StaticAnalyzer/Core/AnalysisManager.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/TextPathDiagnostics.cpp
    cfe/trunk/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
    cfe/trunk/test/Analysis/CFNumber.c
    cfe/trunk/test/Analysis/CheckNSError.m
    cfe/trunk/test/Analysis/array-struct.c
    cfe/trunk/test/Analysis/keychainAPI.m
    cfe/trunk/test/Analysis/malloc-annotations.c
    cfe/trunk/test/Analysis/malloc.c
    cfe/trunk/test/Analysis/misc-ps-region-store.m
    cfe/trunk/test/Analysis/nil-receiver-undefined-larger-than-voidptr-ret.m
    cfe/trunk/test/Analysis/ptr-arith.c
    cfe/trunk/test/Analysis/security-syntax-checks.m
    cfe/trunk/test/Analysis/sizeofpointer.c
    cfe/trunk/test/Analysis/stream.c
    cfe/trunk/test/Analysis/variadic-method-types.m

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h?rev=162028&r1=162027&r2=162028&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h Thu Aug 16 12:45:23 2012
@@ -81,15 +81,19 @@
   typedef llvm::DenseSet<SymbolRef> Symbols;
   typedef llvm::DenseSet<const MemRegion *> Regions;
 
-  /// A set of symbols that are registered with this report as being
-  /// "interesting", and thus used to help decide which diagnostics
-  /// to include when constructing the final path diagnostic.
-  Symbols interestingSymbols;
+  /// A (stack of) a set of symbols that are registered with this
+  /// report as being "interesting", and thus used to help decide which
+  /// diagnostics to include when constructing the final path diagnostic.
+  /// The stack is largely used by BugReporter when generating PathDiagnostics
+  /// for multiple PathDiagnosticConsumers.
+  llvm::SmallVector<Symbols *, 2> interestingSymbols;
 
-  /// A set of regions that are registered with this report as being
+  /// A (stack of) set of regions that are registered with this report as being
   /// "interesting", and thus used to help decide which diagnostics
   /// to include when constructing the final path diagnostic.
-  Regions interestingRegions;
+  /// The stack is largely used by BugReporter when generating PathDiagnostics
+  /// for multiple PathDiagnosticConsumers.
+  llvm::SmallVector<Regions *, 2> interestingRegions;
 
   /// A set of custom visitors which generate "event" diagnostics at
   /// interesting points in the path.
@@ -107,6 +111,15 @@
   /// when reporting an issue.
   bool DoNotPrunePath;
 
+private:
+  // Used internally by BugReporter.
+  Symbols &getInterestingSymbols();
+  Regions &getInterestingRegions();
+
+  void lazyInitializeInterestingSets();
+  void pushInterestingSymbolsAndRegions();
+  void popInterestingSymbolsAndRegions();
+
 public:
   BugReport(BugType& bt, StringRef desc, const ExplodedNode *errornode)
     : BT(bt), DeclWithIssue(0), Description(desc), ErrorNode(errornode),
@@ -160,9 +173,9 @@
   void markInteresting(const MemRegion *R);
   void markInteresting(SVal V);
   
-  bool isInteresting(SymbolRef sym) const;
-  bool isInteresting(const MemRegion *R) const;
-  bool isInteresting(SVal V) const;
+  bool isInteresting(SymbolRef sym);
+  bool isInteresting(const MemRegion *R);
+  bool isInteresting(SVal V);
 
   unsigned getConfigurationChangeToken() const {
     return ConfigurationChangeToken;
@@ -295,7 +308,7 @@
 public:
   virtual ~BugReporterData();
   virtual DiagnosticsEngine& getDiagnostic() = 0;
-  virtual PathDiagnosticConsumer* getPathDiagnosticConsumer() = 0;
+  virtual ArrayRef<PathDiagnosticConsumer*> getPathDiagnosticConsumers() = 0;
   virtual ASTContext &getASTContext() = 0;
   virtual SourceManager& getSourceManager() = 0;
 };
@@ -318,6 +331,12 @@
   /// Generate and flush the diagnostics for the given bug report.
   void FlushReport(BugReportEquivClass& EQ);
 
+  /// Generate and flush the diagnostics for the given bug report
+  /// and PathDiagnosticConsumer.
+  void FlushReport(BugReport *exampleReport,
+                   PathDiagnosticConsumer &PD,
+                   ArrayRef<BugReport*> BugReports);
+
   /// The set of bug reports tracked by the BugReporter.
   llvm::FoldingSet<BugReportEquivClass> EQClasses;
   /// A vector of BugReports for tracking the allocated pointers and cleanup.
@@ -341,8 +360,8 @@
     return D.getDiagnostic();
   }
 
-  PathDiagnosticConsumer* getPathDiagnosticConsumer() {
-    return D.getPathDiagnosticConsumer();
+  ArrayRef<PathDiagnosticConsumer*> getPathDiagnosticConsumers() {
+    return D.getPathDiagnosticConsumers();
   }
 
   /// \brief Iterator over the set of BugTypes tracked by the BugReporter.
@@ -360,7 +379,8 @@
   SourceManager& getSourceManager() { return D.getSourceManager(); }
 
   virtual void GeneratePathDiagnostic(PathDiagnostic& pathDiagnostic,
-        SmallVectorImpl<BugReport *> &bugReports) {}
+                                      PathDiagnosticConsumer &PC,
+                                      ArrayRef<BugReport *> &bugReports) {}
 
   void Register(BugType *BT);
 
@@ -421,7 +441,8 @@
   ProgramStateManager &getStateManager();
 
   virtual void GeneratePathDiagnostic(PathDiagnostic &pathDiagnostic,
-                     SmallVectorImpl<BugReport*> &bugReports);
+                                      PathDiagnosticConsumer &PC,
+                                      ArrayRef<BugReport*> &bugReports);
 
   /// classof - Used by isa<>, cast<>, and dyn_cast<>.
   static bool classof(const BugReporter* R) {

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h?rev=162028&r1=162027&r2=162028&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h Thu Aug 16 12:45:23 2012
@@ -51,22 +51,25 @@
 class PathDiagnostic;
 
 class PathDiagnosticConsumer {
+public:
+  typedef std::vector<std::pair<StringRef, std::string> > FilesMade;
+
+private:
   virtual void anchor();
 public:
   PathDiagnosticConsumer() : flushed(false) {}
   virtual ~PathDiagnosticConsumer();
 
-  void FlushDiagnostics(SmallVectorImpl<std::string> *FilesMade);
+  void FlushDiagnostics(FilesMade *FilesMade);
 
   virtual void FlushDiagnosticsImpl(std::vector<const PathDiagnostic *> &Diags,
-                                    SmallVectorImpl<std::string> *FilesMade)
-                                    = 0;
+                                    FilesMade *filesMade) = 0;
 
   virtual StringRef getName() const = 0;
   
   void HandlePathDiagnostic(PathDiagnostic *D);
 
-  enum PathGenerationScheme { Minimal, Extensive };
+  enum PathGenerationScheme { None, Minimal, Extensive };
   virtual PathGenerationScheme getGenerationScheme() const { return Minimal; }
   virtual bool supportsLogicalOpControlFlow() const { return false; }
   virtual bool supportsAllBlockEdges() const { return false; }
@@ -334,6 +337,8 @@
 
   typedef const SourceRange* range_iterator;
 
+  ArrayRef<SourceRange> getRanges() const { return ranges; }
+
   range_iterator ranges_begin() const {
     return ranges.empty() ? NULL : &ranges[0];
   }

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h?rev=162028&r1=162027&r2=162028&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h Thu Aug 16 12:45:23 2012
@@ -15,6 +15,7 @@
 #define LLVM_CLANG_GR_PATH_DIAGNOSTIC_CLIENTS_H
 
 #include <string>
+#include <vector>
 
 namespace clang {
 
@@ -23,24 +24,25 @@
 namespace ento {
 
 class PathDiagnosticConsumer;
+typedef std::vector<PathDiagnosticConsumer*> PathDiagnosticConsumers;
 
-PathDiagnosticConsumer*
-createHTMLDiagnosticConsumer(const std::string& prefix, const Preprocessor &PP);
+void createHTMLDiagnosticConsumer(PathDiagnosticConsumers &C,
+                                  const std::string& prefix,
+                                  const Preprocessor &PP);
+
+void createPlistDiagnosticConsumer(PathDiagnosticConsumers &C,
+                                   const std::string& prefix,
+                                   const Preprocessor &PP);
+
+void createPlistMultiFileDiagnosticConsumer(PathDiagnosticConsumers &C,
+                                            const std::string& prefix,
+                                            const Preprocessor &PP);
+
+void createTextPathDiagnosticConsumer(PathDiagnosticConsumers &C,
+                                      const std::string& prefix,
+                                      const Preprocessor &PP);
 
-PathDiagnosticConsumer*
-createPlistDiagnosticConsumer(const std::string& prefix, const Preprocessor &PP,
-                              PathDiagnosticConsumer *SubPD = 0);
-
-PathDiagnosticConsumer*
-createPlistMultiFileDiagnosticConsumer(const std::string& prefix,
-                                       const Preprocessor &PP);
-
-PathDiagnosticConsumer*
-createTextPathDiagnosticConsumer(const std::string& prefix,
-                                 const Preprocessor &PP);
-
-} // end GR namespace
-
-} // end clang namespace
+} // end 'ento' namespace
+} // end 'clang' namespace
 
 #endif

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h?rev=162028&r1=162027&r2=162028&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h Thu Aug 16 12:45:23 2012
@@ -19,6 +19,7 @@
 #include "clang/Frontend/AnalyzerOptions.h"
 #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
 #include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
+#include "clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h"
 
 namespace clang {
 
@@ -32,8 +33,7 @@
   ASTContext &Ctx;
   DiagnosticsEngine &Diags;
   const LangOptions &LangOpts;
-
-  OwningPtr<PathDiagnosticConsumer> PD;
+  PathDiagnosticConsumers PathConsumers;
 
   // Configurable components creators.
   StoreManagerCreator CreateStoreMgr;
@@ -82,8 +82,9 @@
   bool NoRetryExhausted;
 
 public:
-  AnalysisManager(ASTContext &ctx, DiagnosticsEngine &diags, 
-                  const LangOptions &lang, PathDiagnosticConsumer *pd,
+  AnalysisManager(ASTContext &ctx,DiagnosticsEngine &diags,
+                  const LangOptions &lang,
+                  const PathDiagnosticConsumers &Consumers,
                   StoreManagerCreator storemgr,
                   ConstraintManagerCreator constraintmgr, 
                   CheckerManager *checkerMgr,
@@ -99,12 +100,7 @@
                   AnalysisInliningMode inliningMode,
                   bool NoRetry);
 
-  /// Construct a clone of the given AnalysisManager with the given ASTContext
-  /// and DiagnosticsEngine.
-  AnalysisManager(ASTContext &ctx, DiagnosticsEngine &diags,
-                  AnalysisManager &ParentAM);
-
-  ~AnalysisManager() { FlushDiagnostics(); }
+  ~AnalysisManager();
   
   void ClearContexts() {
     AnaCtxMgr.clear();
@@ -140,15 +136,12 @@
     return LangOpts;
   }
 
-  virtual PathDiagnosticConsumer *getPathDiagnosticConsumer() {
-    return PD.get();
-  }
-  
-  void FlushDiagnostics() {
-    if (PD.get())
-      PD->FlushDiagnostics(0);
+  ArrayRef<PathDiagnosticConsumer*> getPathDiagnosticConsumers()  {
+    return PathConsumers;
   }
 
+  void FlushDiagnostics();
+
   unsigned getMaxNodes() const { return MaxNodes; }
 
   unsigned getMaxVisit() const { return MaxVisit; }

Modified: cfe/trunk/lib/StaticAnalyzer/Core/AnalysisManager.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/AnalysisManager.cpp?rev=162028&r1=162027&r2=162028&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/AnalysisManager.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/AnalysisManager.cpp Thu Aug 16 12:45:23 2012
@@ -16,7 +16,7 @@
 
 AnalysisManager::AnalysisManager(ASTContext &ctx, DiagnosticsEngine &diags,
                                  const LangOptions &lang,
-                                 PathDiagnosticConsumer *pd,
+                                 const PathDiagnosticConsumers &PDC,
                                  StoreManagerCreator storemgr,
                                  ConstraintManagerCreator constraintmgr, 
                                  CheckerManager *checkerMgr,
@@ -33,7 +33,8 @@
                                  AnalysisInliningMode IMode,
                                  bool NoRetry)
   : AnaCtxMgr(useUnoptimizedCFG, addImplicitDtors, /*addInitializers=*/true),
-    Ctx(ctx), Diags(diags), LangOpts(lang), PD(pd),
+    Ctx(ctx), Diags(diags), LangOpts(lang),
+    PathConsumers(PDC),
     CreateStoreMgr(storemgr), CreateConstraintMgr(constraintmgr),
     CheckerMgr(checkerMgr), 
     MaxNodes(maxnodes), MaxVisit(maxvisit),
@@ -49,29 +50,19 @@
   AnaCtxMgr.getCFGBuildOptions().setAllAlwaysAdd();
 }
 
-AnalysisManager::AnalysisManager(ASTContext &ctx, DiagnosticsEngine &diags,
-                                 AnalysisManager &ParentAM)
-  : AnaCtxMgr(ParentAM.AnaCtxMgr.getUseUnoptimizedCFG(),
-              ParentAM.AnaCtxMgr.getCFGBuildOptions().AddImplicitDtors,
-              ParentAM.AnaCtxMgr.getCFGBuildOptions().AddInitializers),
-    Ctx(ctx), Diags(diags),
-    LangOpts(ParentAM.LangOpts), PD(ParentAM.getPathDiagnosticConsumer()),
-    CreateStoreMgr(ParentAM.CreateStoreMgr),
-    CreateConstraintMgr(ParentAM.CreateConstraintMgr),
-    CheckerMgr(ParentAM.CheckerMgr),
-    MaxNodes(ParentAM.MaxNodes),
-    MaxVisit(ParentAM.MaxVisit),
-    VisualizeEGDot(ParentAM.VisualizeEGDot),
-    VisualizeEGUbi(ParentAM.VisualizeEGUbi),
-    PurgeDead(ParentAM.PurgeDead),
-    EagerlyAssume(ParentAM.EagerlyAssume),
-    TrimGraph(ParentAM.TrimGraph),
-    EagerlyTrimEGraph(ParentAM.EagerlyTrimEGraph),
-    IPAMode(ParentAM.IPAMode),
-    InlineMaxStackDepth(ParentAM.InlineMaxStackDepth),
-    InlineMaxFunctionSize(ParentAM.InlineMaxFunctionSize),
-    InliningMode(ParentAM.InliningMode),
-    NoRetryExhausted(ParentAM.NoRetryExhausted)
-{
-  AnaCtxMgr.getCFGBuildOptions().setAllAlwaysAdd();
+AnalysisManager::~AnalysisManager() {
+  FlushDiagnostics();
+  for (PathDiagnosticConsumers::iterator I = PathConsumers.begin(),
+       E = PathConsumers.end(); I != E; ++I) {
+    delete *I;
+  }
+}
+
+void AnalysisManager::FlushDiagnostics() {
+  PathDiagnosticConsumer::FilesMade filesMade;
+  for (PathDiagnosticConsumers::iterator I = PathConsumers.begin(),
+       E = PathConsumers.end();
+       I != E; ++I) {
+    (*I)->FlushDiagnostics(&filesMade);
+  }
 }

Modified: cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp?rev=162028&r1=162027&r2=162028&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp Thu Aug 16 12:45:23 2012
@@ -1345,6 +1345,9 @@
   for (visitor_iterator I = visitor_begin(), E = visitor_end(); I != E; ++I) {
     delete *I;
   }
+  while (!interestingSymbols.empty()) {
+    popInterestingSymbolsAndRegions();
+  }
 }
 
 const Decl *BugReport::getDeclWithIssue() const {
@@ -1386,11 +1389,11 @@
     return;
 
   // If the symbol wasn't already in our set, note a configuration change.
-  if (interestingSymbols.insert(sym).second)
+  if (getInterestingSymbols().insert(sym).second)
     ++ConfigurationChangeToken;
 
   if (const SymbolMetadata *meta = dyn_cast<SymbolMetadata>(sym))
-    interestingRegions.insert(meta->getRegion());
+    getInterestingRegions().insert(meta->getRegion());
 }
 
 void BugReport::markInteresting(const MemRegion *R) {
@@ -1399,11 +1402,11 @@
 
   // If the base region wasn't already in our set, note a configuration change.
   R = R->getBaseRegion();
-  if (interestingRegions.insert(R).second)
+  if (getInterestingRegions().insert(R).second)
     ++ConfigurationChangeToken;
 
   if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R))
-    interestingSymbols.insert(SR->getSymbol());
+    getInterestingSymbols().insert(SR->getSymbol());
 }
 
 void BugReport::markInteresting(SVal V) {
@@ -1411,30 +1414,58 @@
   markInteresting(V.getAsSymbol());
 }
 
-bool BugReport::isInteresting(SVal V) const {
+bool BugReport::isInteresting(SVal V) {
   return isInteresting(V.getAsRegion()) || isInteresting(V.getAsSymbol());
 }
 
-bool BugReport::isInteresting(SymbolRef sym) const {
+bool BugReport::isInteresting(SymbolRef sym) {
   if (!sym)
     return false;
   // We don't currently consider metadata symbols to be interesting
   // even if we know their region is interesting. Is that correct behavior?
-  return interestingSymbols.count(sym);
+  return getInterestingSymbols().count(sym);
 }
 
-bool BugReport::isInteresting(const MemRegion *R) const {
+bool BugReport::isInteresting(const MemRegion *R) {
   if (!R)
     return false;
   R = R->getBaseRegion();
-  bool b = interestingRegions.count(R);
+  bool b = getInterestingRegions().count(R);
   if (b)
     return true;
   if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R))
-    return interestingSymbols.count(SR->getSymbol());
+    return getInterestingSymbols().count(SR->getSymbol());
   return false;
 }
-  
+
+void BugReport::lazyInitializeInterestingSets() {
+  if (interestingSymbols.empty()) {
+    interestingSymbols.push_back(new Symbols());
+    interestingRegions.push_back(new Regions());
+  }
+}
+
+BugReport::Symbols &BugReport::getInterestingSymbols() {
+  lazyInitializeInterestingSets();
+  return *interestingSymbols.back();
+}
+
+BugReport::Regions &BugReport::getInterestingRegions() {
+  lazyInitializeInterestingSets();
+  return *interestingRegions.back();
+}
+
+void BugReport::pushInterestingSymbolsAndRegions() {
+  interestingSymbols.push_back(new Symbols(getInterestingSymbols()));
+  interestingRegions.push_back(new Regions(getInterestingRegions()));
+}
+
+void BugReport::popInterestingSymbolsAndRegions() {
+  delete interestingSymbols.back();
+  interestingSymbols.pop_back();
+  delete interestingRegions.back();
+  interestingRegions.pop_back();
+}
 
 const Stmt *BugReport::getStmt() const {
   if (!ErrorNode)
@@ -1793,12 +1824,13 @@
 }
 
 void GRBugReporter::GeneratePathDiagnostic(PathDiagnostic& PD,
-                        SmallVectorImpl<BugReport *> &bugReports) {
+                                           PathDiagnosticConsumer &PC,
+                                           ArrayRef<BugReport *> &bugReports) {
 
   assert(!bugReports.empty());
   SmallVector<const ExplodedNode *, 10> errorNodes;
-  for (SmallVectorImpl<BugReport*>::iterator I = bugReports.begin(),
-    E = bugReports.end(); I != E; ++I) {
+  for (ArrayRef<BugReport*>::iterator I = bugReports.begin(),
+                                      E = bugReports.end(); I != E; ++I) {
       errorNodes.push_back((*I)->getErrorNode());
   }
 
@@ -1818,8 +1850,7 @@
   const ExplodedNode *N = GPair.second.first;
 
   // Start building the path diagnostic...
-  PathDiagnosticBuilder PDB(*this, R, BackMap.get(),
-                            getPathDiagnosticConsumer());
+  PathDiagnosticBuilder PDB(*this, R, BackMap.get(), &PC);
 
   // Register additional node visitors.
   R->addVisitor(new NilReceiverBRVisitor());
@@ -1867,6 +1898,8 @@
     case PathDiagnosticConsumer::Minimal:
       GenerateMinimalPathDiagnostic(PD, PDB, N, visitors);
       break;
+    case PathDiagnosticConsumer::None:
+      llvm_unreachable("PathDiagnosticConsumer::None should never appear here");
     }
 
     // Clean up the visitors we used.
@@ -2022,53 +2055,21 @@
   return exampleReport;
 }
 
-//===----------------------------------------------------------------------===//
-// DiagnosticCache.  This is a hack to cache analyzer diagnostics.  It
-// uses global state, which eventually should go elsewhere.
-//===----------------------------------------------------------------------===//
-namespace {
-class DiagCacheItem : public llvm::FoldingSetNode {
-  llvm::FoldingSetNodeID ID;
-public:
-  DiagCacheItem(BugReport *R, PathDiagnostic *PD) {
-    R->Profile(ID);
-    PD->Profile(ID);
-  }
-  
-  void Profile(llvm::FoldingSetNodeID &id) {
-    id = ID;
-  }
-  
-  llvm::FoldingSetNodeID &getID() { return ID; }
-};
-}
-
-static bool IsCachedDiagnostic(BugReport *R, PathDiagnostic *PD) {
-  // FIXME: Eventually this diagnostic cache should reside in something
-  // like AnalysisManager instead of being a static variable.  This is
-  // really unsafe in the long term.
-  typedef llvm::FoldingSet<DiagCacheItem> DiagnosticCache;
-  static DiagnosticCache DC;
-  
-  void *InsertPos;
-  DiagCacheItem *Item = new DiagCacheItem(R, PD);
-  
-  if (DC.FindNodeOrInsertPos(Item->getID(), InsertPos)) {
-    delete Item;
-    return true;
-  }
-  
-  DC.InsertNode(Item, InsertPos);
-  return false;
-}
-
 void BugReporter::FlushReport(BugReportEquivClass& EQ) {
   SmallVector<BugReport*, 10> bugReports;
   BugReport *exampleReport = FindReportInEquivalenceClass(EQ, bugReports);
-  if (!exampleReport)
-    return;
-  
-  PathDiagnosticConsumer* PD = getPathDiagnosticConsumer();
+  if (exampleReport) {
+    const PathDiagnosticConsumers &C = getPathDiagnosticConsumers();
+    for (PathDiagnosticConsumers::const_iterator I=C.begin(),
+                                                 E=C.end(); I != E; ++I) {
+      FlushReport(exampleReport, **I, bugReports);
+    }
+  }
+}
+
+void BugReporter::FlushReport(BugReport *exampleReport,
+                              PathDiagnosticConsumer &PD,
+                              ArrayRef<BugReport*> bugReports) {
 
   // FIXME: Make sure we use the 'R' for the path that was actually used.
   // Probably doesn't make a difference in practice.
@@ -2077,65 +2078,39 @@
   OwningPtr<PathDiagnostic>
     D(new PathDiagnostic(exampleReport->getDeclWithIssue(),
                          exampleReport->getBugType().getName(),
-                         !PD || PD->useVerboseDescription()
+                         PD.useVerboseDescription()
                          ? exampleReport->getDescription() 
                          : exampleReport->getShortDescription(),
                          BT.getCategory()));
 
-  if (!bugReports.empty())
-    GeneratePathDiagnostic(*D.get(), bugReports);
-  
-  // Get the meta data.
-  const BugReport::ExtraTextList &Meta =
-                                  exampleReport->getExtraText();
-  for (BugReport::ExtraTextList::const_iterator i = Meta.begin(),
-                                                e = Meta.end(); i != e; ++i) {
-    D->addMeta(*i);
+  // Generate the full path diagnostic, using the generation scheme
+  // specified by the PathDiagnosticConsumer.
+  if (PD.getGenerationScheme() != PathDiagnosticConsumer::None) {
+    if (!bugReports.empty())
+      GeneratePathDiagnostic(*D.get(), PD, bugReports);
   }
 
-  // Emit a summary diagnostic to the regular Diagnostics engine.
-  BugReport::ranges_iterator Beg, End;
-  llvm::tie(Beg, End) = exampleReport->getRanges();
-  DiagnosticsEngine &Diag = getDiagnostic();
-  
-  if (!IsCachedDiagnostic(exampleReport, D.get())) {
-    // Search the description for '%', as that will be interpretted as a
-    // format character by FormatDiagnostics.
-    StringRef desc = exampleReport->getShortDescription();
-
-    SmallString<512> TmpStr;
-    llvm::raw_svector_ostream Out(TmpStr);
-    for (StringRef::iterator I=desc.begin(), E=desc.end(); I!=E; ++I) {
-      if (*I == '%')
-        Out << "%%";
-      else
-        Out << *I;
-    }
-    
-    Out.flush();
-    unsigned ErrorDiag = Diag.getCustomDiagID(DiagnosticsEngine::Warning, TmpStr);
-
-    DiagnosticBuilder diagBuilder = Diag.Report(
-      exampleReport->getLocation(getSourceManager()).asLocation(), ErrorDiag);
-    for (BugReport::ranges_iterator I = Beg; I != End; ++I)
-      diagBuilder << *I;
-  }
-
-  // Emit a full diagnostic for the path if we have a PathDiagnosticConsumer.
-  if (!PD)
-    return;
-
+  // If the path is empty, generate a single step path with the location
+  // of the issue.
   if (D->path.empty()) {
-    PathDiagnosticPiece *piece = new PathDiagnosticEventPiece(
-                                 exampleReport->getLocation(getSourceManager()),
-                                 exampleReport->getDescription());
+    PathDiagnosticLocation L = exampleReport->getLocation(getSourceManager());
+    PathDiagnosticPiece *piece =
+      new PathDiagnosticEventPiece(L, exampleReport->getDescription());
+    BugReport::ranges_iterator Beg, End;
+    llvm::tie(Beg, End) = exampleReport->getRanges();
     for ( ; Beg != End; ++Beg)
       piece->addRange(*Beg);
-
     D->getActivePath().push_back(piece);
   }
 
-  PD->HandlePathDiagnostic(D.take());
+  // Get the meta data.
+  const BugReport::ExtraTextList &Meta = exampleReport->getExtraText();
+  for (BugReport::ExtraTextList::const_iterator i = Meta.begin(),
+                                                e = Meta.end(); i != e; ++i) {
+    D->addMeta(*i);
+  }
+
+  PD.HandlePathDiagnostic(D.take());
 }
 
 void BugReporter::EmitBasicReport(const Decl *DeclWithIssue,

Modified: cfe/trunk/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp?rev=162028&r1=162027&r2=162028&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp Thu Aug 16 12:45:23 2012
@@ -45,7 +45,7 @@
   virtual ~HTMLDiagnostics() { FlushDiagnostics(NULL); }
 
   virtual void FlushDiagnosticsImpl(std::vector<const PathDiagnostic *> &Diags,
-                                    SmallVectorImpl<std::string> *FilesMade);
+                                    FilesMade *filesMade);
 
   virtual StringRef getName() const {
     return "HTMLDiagnostics";
@@ -63,7 +63,7 @@
                       const char *HighlightEnd = "</span>");
 
   void ReportDiag(const PathDiagnostic& D,
-                  SmallVectorImpl<std::string> *FilesMade);
+                  FilesMade *filesMade);
 };
 
 } // end anonymous namespace
@@ -76,10 +76,10 @@
   FilePrefix.appendComponent("report");
 }
 
-PathDiagnosticConsumer*
-ento::createHTMLDiagnosticConsumer(const std::string& prefix,
-                                 const Preprocessor &PP) {
-  return new HTMLDiagnostics(prefix, PP);
+void ento::createHTMLDiagnosticConsumer(PathDiagnosticConsumers &C,
+                                        const std::string& prefix,
+                                        const Preprocessor &PP) {
+  C.push_back(new HTMLDiagnostics(prefix, PP));
 }
 
 //===----------------------------------------------------------------------===//
@@ -88,15 +88,15 @@
 
 void HTMLDiagnostics::FlushDiagnosticsImpl(
   std::vector<const PathDiagnostic *> &Diags,
-  SmallVectorImpl<std::string> *FilesMade) {
+  FilesMade *filesMade) {
   for (std::vector<const PathDiagnostic *>::iterator it = Diags.begin(),
        et = Diags.end(); it != et; ++it) {
-    ReportDiag(**it, FilesMade);
+    ReportDiag(**it, filesMade);
   }
 }
 
 void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D,
-                                 SmallVectorImpl<std::string> *FilesMade) {
+                                 FilesMade *filesMade) {
     
   // Create the HTML directory if it is missing.
   if (!createdDir) {
@@ -266,8 +266,10 @@
     return;
   }
 
-  if (FilesMade)
-    FilesMade->push_back(llvm::sys::path::filename(H.str()));
+  if (filesMade) {
+    filesMade->push_back(std::make_pair(StringRef(getName()),
+                                        llvm::sys::path::filename(H.str())));
+  }
 
   // Emit the HTML to disk.
   for (RewriteBuffer::iterator I = Buf->begin(), E = Buf->end(); I!=E; ++I)

Modified: cfe/trunk/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/PathDiagnostic.cpp?rev=162028&r1=162027&r2=162028&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/PathDiagnostic.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/PathDiagnostic.cpp Thu Aug 16 12:45:23 2012
@@ -240,8 +240,8 @@
 };  
 }
 
-void
-PathDiagnosticConsumer::FlushDiagnostics(SmallVectorImpl<std::string> *Files) {
+void PathDiagnosticConsumer::FlushDiagnostics(
+                                     PathDiagnosticConsumer::FilesMade *Files) {
   if (flushed)
     return;
   

Modified: cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp?rev=162028&r1=162027&r2=162028&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp Thu Aug 16 12:45:23 2012
@@ -30,23 +30,21 @@
   class PlistDiagnostics : public PathDiagnosticConsumer {
     const std::string OutputFile;
     const LangOptions &LangOpts;
-    OwningPtr<PathDiagnosticConsumer> SubPD;
     const bool SupportsCrossFileDiagnostics;
   public:
     PlistDiagnostics(const std::string& prefix, const LangOptions &LangOpts,
-                     bool supportsMultipleFiles,
-                     PathDiagnosticConsumer *subPD);
+                     bool supportsMultipleFiles);
 
     virtual ~PlistDiagnostics() {}
 
     void FlushDiagnosticsImpl(std::vector<const PathDiagnostic *> &Diags,
-                              SmallVectorImpl<std::string> *FilesMade);
+                              FilesMade *filesMade);
     
     virtual StringRef getName() const {
       return "PlistDiagnostics";
     }
 
-    PathGenerationScheme getGenerationScheme() const;
+    PathGenerationScheme getGenerationScheme() const { return Extensive; }
     bool supportsLogicalOpControlFlow() const { return true; }
     bool supportsAllBlockEdges() const { return true; }
     virtual bool useVerboseDescription() const { return false; }
@@ -58,29 +56,20 @@
 
 PlistDiagnostics::PlistDiagnostics(const std::string& output,
                                    const LangOptions &LO,
-                                   bool supportsMultipleFiles,
-                                   PathDiagnosticConsumer *subPD)
-  : OutputFile(output), LangOpts(LO), SubPD(subPD),
+                                   bool supportsMultipleFiles)
+  : OutputFile(output), LangOpts(LO),
     SupportsCrossFileDiagnostics(supportsMultipleFiles) {}
 
-PathDiagnosticConsumer*
-ento::createPlistDiagnosticConsumer(const std::string& s, const Preprocessor &PP,
-                                  PathDiagnosticConsumer *subPD) {
-  return new PlistDiagnostics(s, PP.getLangOpts(), false, subPD);
+void ento::createPlistDiagnosticConsumer(PathDiagnosticConsumers &C,
+                                         const std::string& s,
+                                         const Preprocessor &PP) {
+  C.push_back(new PlistDiagnostics(s, PP.getLangOpts(), false));
 }
 
-PathDiagnosticConsumer*
-ento::createPlistMultiFileDiagnosticConsumer(const std::string &s,
-                                              const Preprocessor &PP) {
-  return new PlistDiagnostics(s, PP.getLangOpts(), true, 0);
-}
-
-PathDiagnosticConsumer::PathGenerationScheme
-PlistDiagnostics::getGenerationScheme() const {
-  if (const PathDiagnosticConsumer *PD = SubPD.get())
-    return PD->getGenerationScheme();
-
-  return Extensive;
+void ento::createPlistMultiFileDiagnosticConsumer(PathDiagnosticConsumers &C,
+                                                  const std::string &s,
+                                                  const Preprocessor &PP) {
+  C.push_back(new PlistDiagnostics(s, PP.getLangOpts(), true));
 }
 
 static void AddFID(FIDMap &FIDs, SmallVectorImpl<FileID> &V,
@@ -353,7 +342,7 @@
 
 void PlistDiagnostics::FlushDiagnosticsImpl(
                                     std::vector<const PathDiagnostic *> &Diags,
-                                    SmallVectorImpl<std::string> *FilesMade) {
+                                    FilesMade *filesMade) {
   // Build up a set of FIDs that we use by scanning the locations and
   // ranges of the diagnostics.
   FIDMap FM;
@@ -507,19 +496,21 @@
     EmitLocation(o, *SM, LangOpts, D->getLocation(), FM, 2);
 
     // Output the diagnostic to the sub-diagnostic client, if any.
-    if (SubPD) {
-      std::vector<const PathDiagnostic *> SubDiags;
-      SubDiags.push_back(D);
-      SmallVector<std::string, 1> SubFilesMade;
-      SubPD->FlushDiagnosticsImpl(SubDiags, &SubFilesMade);
-
-      if (!SubFilesMade.empty()) {
-        o << "  <key>" << SubPD->getName() << "_files</key>\n";
-        o << "  <array>\n";
-        for (size_t i = 0, n = SubFilesMade.size(); i < n ; ++i)
-          o << "   <string>" << SubFilesMade[i] << "</string>\n";
-        o << "  </array>\n";
+    if (!filesMade->empty()) {
+      StringRef lastName;
+      for (FilesMade::iterator I = filesMade->begin(), E = filesMade->end();
+           I != E; ++I) {
+        StringRef newName = I->first;
+        if (newName != lastName) {
+          if (!lastName.empty())
+            o << "  </array>\n";
+          lastName = newName;
+          o <<  "  <key>" << lastName << "_files</key>\n";
+          o << "  <array>\n";
+        }
+        o << "   <string>" << I->second << "</string>\n";
       }
+      o << "  </array>\n";
     }
 
     // Close up the entry.
@@ -531,6 +522,8 @@
   // Finish.
   o << "</dict>\n</plist>";
   
-  if (FilesMade)
-    FilesMade->push_back(OutputFile);
+  if (filesMade) {
+    StringRef Name(getName());
+    filesMade->push_back(std::make_pair(Name, OutputFile));
+  }
 }

Modified: cfe/trunk/lib/StaticAnalyzer/Core/TextPathDiagnostics.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/TextPathDiagnostics.cpp?rev=162028&r1=162027&r2=162028&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/TextPathDiagnostics.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/TextPathDiagnostics.cpp Thu Aug 16 12:45:23 2012
@@ -32,7 +32,7 @@
     : OutputFile(output), Diag(diag) {}
 
   void FlushDiagnosticsImpl(std::vector<const PathDiagnostic *> &Diags,
-                            SmallVectorImpl<std::string> *FilesMade);
+                            FilesMade *filesMade);
   
   virtual StringRef getName() const {
     return "TextPathDiagnostics";
@@ -47,15 +47,15 @@
 
 } // end anonymous namespace
 
-PathDiagnosticConsumer*
-ento::createTextPathDiagnosticConsumer(const std::string& out,
-                                     const Preprocessor &PP) {
-  return new TextPathDiagnostics(out, PP.getDiagnostics());
+void ento::createTextPathDiagnosticConsumer(PathDiagnosticConsumers &C,
+                                            const std::string& out,
+                                            const Preprocessor &PP) {
+  C.push_back(new TextPathDiagnostics(out, PP.getDiagnostics()));
 }
 
 void TextPathDiagnostics::FlushDiagnosticsImpl(
                               std::vector<const PathDiagnostic *> &Diags,
-                              SmallVectorImpl<std::string> *FilesMade) {
+                              FilesMade *) {
   for (std::vector<const PathDiagnostic *>::iterator it = Diags.begin(),
        et = Diags.end(); it != et; ++it) {
     const PathDiagnostic *D = *it;

Modified: cfe/trunk/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp?rev=162028&r1=162027&r2=162028&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp Thu Aug 16 12:45:23 2012
@@ -64,14 +64,55 @@
 // Special PathDiagnosticConsumers.
 //===----------------------------------------------------------------------===//
 
-static PathDiagnosticConsumer*
-createPlistHTMLDiagnosticConsumer(const std::string& prefix,
-                                const Preprocessor &PP) {
-  PathDiagnosticConsumer *PD =
-    createHTMLDiagnosticConsumer(llvm::sys::path::parent_path(prefix), PP);
-  return createPlistDiagnosticConsumer(prefix, PP, PD);
+static void createPlistHTMLDiagnosticConsumer(PathDiagnosticConsumers &C,
+                                              const std::string &prefix,
+                                              const Preprocessor &PP) {
+  createHTMLDiagnosticConsumer(C, llvm::sys::path::parent_path(prefix), PP);
+  createPlistDiagnosticConsumer(C, prefix, PP);
 }
 
+namespace {
+class ClangDiagPathDiagConsumer : public PathDiagnosticConsumer {
+  DiagnosticsEngine &Diag;
+public:
+  ClangDiagPathDiagConsumer(DiagnosticsEngine &Diag) : Diag(Diag) {}
+  virtual ~ClangDiagPathDiagConsumer() {}
+  virtual StringRef getName() const { return "ClangDiags"; }
+  virtual bool useVerboseDescription() const { return false; }
+  virtual PathGenerationScheme getGenerationScheme() const { return None; }
+
+  void FlushDiagnosticsImpl(std::vector<const PathDiagnostic *> &Diags,
+                            FilesMade *filesMade) {
+    for (std::vector<const PathDiagnostic*>::iterator I = Diags.begin(),
+         E = Diags.end(); I != E; ++I) {
+      const PathDiagnostic *PD = *I;
+      StringRef desc = PD->getDescription();
+      SmallString<512> TmpStr;
+      llvm::raw_svector_ostream Out(TmpStr);
+      for (StringRef::iterator I=desc.begin(), E=desc.end(); I!=E; ++I) {
+        if (*I == '%')
+          Out << "%%";
+        else
+          Out << *I;
+      }
+      Out.flush();
+      unsigned ErrorDiag = Diag.getCustomDiagID(DiagnosticsEngine::Warning,
+                                                TmpStr);
+      SourceLocation L = PD->getLocation().asLocation();
+      DiagnosticBuilder diagBuilder = Diag.Report(L, ErrorDiag);
+
+      // Get the ranges from the last point in the path.
+      ArrayRef<SourceRange> Ranges = PD->path.back()->getRanges();
+
+      for (ArrayRef<SourceRange>::iterator I = Ranges.begin(),
+                                           E = Ranges.end(); I != E; ++I) {
+        diagBuilder << *I;
+      }
+    }
+  }
+};
+} // end anonymous namespace
+
 //===----------------------------------------------------------------------===//
 // AnalysisConsumer declaration.
 //===----------------------------------------------------------------------===//
@@ -105,8 +146,8 @@
   /// working with a PCH file.
   SetOfDecls LocalTUDecls;
                            
-  // PD is owned by AnalysisManager.
-  PathDiagnosticConsumer *PD;
+  // Set of PathDiagnosticConsumers.  Owned by AnalysisManager.
+  PathDiagnosticConsumers PathConsumers;
 
   StoreManagerCreator CreateStoreMgr;
   ConstraintManagerCreator CreateConstraintMgr;
@@ -126,7 +167,7 @@
                    const AnalyzerOptions& opts,
                    ArrayRef<std::string> plugins)
     : RecVisitorMode(ANALYSIS_ALL), RecVisitorBR(0),
-      Ctx(0), PP(pp), OutDir(outdir), Opts(opts), Plugins(plugins), PD(0) {
+      Ctx(0), PP(pp), OutDir(outdir), Opts(opts), Plugins(plugins) {
     DigestAnalyzerOptions();
     if (Opts.PrintStats) {
       llvm::EnableStatistics();
@@ -141,17 +182,19 @@
 
   void DigestAnalyzerOptions() {
     // Create the PathDiagnosticConsumer.
+    PathConsumers.push_back(new ClangDiagPathDiagConsumer(PP.getDiagnostics()));
+
     if (!OutDir.empty()) {
       switch (Opts.AnalysisDiagOpt) {
       default:
 #define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN, AUTOCREATE) \
-        case PD_##NAME: PD = CREATEFN(OutDir, PP); break;
+        case PD_##NAME: CREATEFN(PathConsumers, OutDir, PP); break;
 #include "clang/Frontend/Analyses.def"
       }
     } else if (Opts.AnalysisDiagOpt == PD_TEXT) {
       // Create the text client even without a specified output file since
       // it just uses diagnostic notes.
-      PD = createTextPathDiagnosticConsumer("", PP);
+      createTextPathDiagnosticConsumer(PathConsumers, "", PP);
     }
 
     // Create the analyzer component creators.
@@ -205,9 +248,12 @@
     Ctx = &Context;
     checkerMgr.reset(createCheckerManager(Opts, PP.getLangOpts(), Plugins,
                                           PP.getDiagnostics()));
-    Mgr.reset(new AnalysisManager(*Ctx, PP.getDiagnostics(),
-                                  PP.getLangOpts(), PD,
-                                  CreateStoreMgr, CreateConstraintMgr,
+    Mgr.reset(new AnalysisManager(*Ctx,
+                                  PP.getDiagnostics(),
+                                  PP.getLangOpts(),
+                                  PathConsumers,
+                                  CreateStoreMgr,
+                                  CreateConstraintMgr,
                                   checkerMgr.get(),
                                   Opts.MaxNodes, Opts.MaxLoop,
                                   Opts.VisualizeEGDot, Opts.VisualizeEGUbi,

Modified: cfe/trunk/test/Analysis/CFNumber.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/CFNumber.c?rev=162028&r1=162027&r2=162028&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/CFNumber.c (original)
+++ cfe/trunk/test/Analysis/CFNumber.c Thu Aug 16 12:45:23 2012
@@ -17,11 +17,11 @@
 extern CFNumberRef CFNumberCreate(CFAllocatorRef allocator, CFNumberType theType, const void *valuePtr);
 
 CFNumberRef f1(unsigned char x) {
-  return CFNumberCreate(0, kCFNumberSInt16Type, &x);  // expected-warning{{An 8 bit integer is used to initialize a CFNumber object that represents a 16 bit integer. 8 bits of the CFNumber value will be garbage.}}
+  return CFNumberCreate(0, kCFNumberSInt16Type, &x);  // expected-warning{{An 8 bit integer is used to initialize a CFNumber object that represents a 16 bit integer. 8 bits of the CFNumber value will be garbage}}
 }
 
 __attribute__((cf_returns_retained)) CFNumberRef f2(unsigned short x) {
-  return CFNumberCreate(0, kCFNumberSInt8Type, &x); // expected-warning{{A 16 bit integer is used to initialize a CFNumber object that represents an 8 bit integer. 8 bits of the input integer will be lost.}}
+  return CFNumberCreate(0, kCFNumberSInt8Type, &x); // expected-warning{{A 16 bit integer is used to initialize a CFNumber object that represents an 8 bit integer. 8 bits of the input integer will be lost}}
 }
 
 // test that the attribute overrides the naming convention.
@@ -30,5 +30,5 @@
 }
 
 CFNumberRef f3(unsigned i) {
-  return CFNumberCreate(0, kCFNumberLongType, &i); // expected-warning{{A 32 bit integer is used to initialize a CFNumber object that represents a 64 bit integer.}}
+  return CFNumberCreate(0, kCFNumberLongType, &i); // expected-warning{{A 32 bit integer is used to initialize a CFNumber object that represents a 64 bit integer}}
 }

Modified: cfe/trunk/test/Analysis/CheckNSError.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/CheckNSError.m?rev=162028&r1=162027&r2=162028&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/CheckNSError.m (original)
+++ cfe/trunk/test/Analysis/CheckNSError.m Thu Aug 16 12:45:23 2012
@@ -23,7 +23,7 @@
 
 @implementation A
 - (void)myMethodWhichMayFail:(NSError **)error {   // expected-warning {{Method accepting NSError** should have a non-void return value to indicate whether or not an error occurred}}
-  *error = [NSError errorWithDomain:@"domain" code:1 userInfo:0]; // expected-warning {{Potential null dereference.}}
+  *error = [NSError errorWithDomain:@"domain" code:1 userInfo:0]; // expected-warning {{Potential null dereference}}
 }
 
 - (BOOL)myMethodWhichMayFail2:(NSError **)error {  // no-warning
@@ -36,7 +36,7 @@
 typedef struct __CFError* CFErrorRef;
 
 void foo(CFErrorRef* error) { // expected-warning {{Function accepting CFErrorRef* should have a non-void return value to indicate whether or not an error occurred}}
-  *error = 0;  // expected-warning {{Potential null dereference.}}
+  *error = 0;  // expected-warning {{Potential null dereference}}
 }
 
 int f1(CFErrorRef* error) {

Modified: cfe/trunk/test/Analysis/array-struct.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/array-struct.c?rev=162028&r1=162027&r2=162028&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/array-struct.c (original)
+++ cfe/trunk/test/Analysis/array-struct.c Thu Aug 16 12:45:23 2012
@@ -151,7 +151,7 @@
 // an ElementRegion of type 'char'. Then load a nonloc::SymbolVal from it and
 // assigns to 'a'. 
 void f16(struct s3 *p) {
-  struct s3 a = *((struct s3*) ((char*) &p[0])); // expected-warning{{Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption.}}
+  struct s3 a = *((struct s3*) ((char*) &p[0])); // expected-warning{{Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption}}
 }
 
 void inv(struct s1 *);

Modified: cfe/trunk/test/Analysis/keychainAPI.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/keychainAPI.m?rev=162028&r1=162027&r2=162028&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/keychainAPI.m (original)
+++ cfe/trunk/test/Analysis/keychainAPI.m Thu Aug 16 12:45:23 2012
@@ -76,7 +76,7 @@
   UInt32 length;
   void *outData;
   st = SecKeychainItemCopyContent(2, ptr, ptr, &length, &outData);
-  if (st == GenericError) // expected-warning{{Allocated data is not released: missing a call to 'SecKeychainItemFreeContent'.}}
+  if (st == GenericError) // expected-warning{{Allocated data is not released: missing a call to 'SecKeychainItemFreeContent'}}
     SecKeychainItemFreeContent(ptr, outData); // expected-warning{{Only call free if a valid (non-NULL) buffer was returned}}
 }
 
@@ -220,7 +220,7 @@
     if (st == noErr)
       SecKeychainItemFreeContent(ptr, outData[3]);
   }
-  if (length) { // expected-warning{{Allocated data is not released: missing a call to 'SecKeychainItemFreeContent'.}}
+  if (length) { // expected-warning{{Allocated data is not released: missing a call to 'SecKeychainItemFreeContent'}}
     length++;
   }
   return 0;
@@ -318,7 +318,7 @@
   UInt32 pwdLen = 0;
   void*  pwdBytes = 0;
   OSStatus rc = SecKeychainFindGenericPassword(0, 3, "foo", 3, "bar", &pwdLen, &pwdBytes, 0);
-  SecKeychainItemFreeContent(0, pwdBytes); // expected-warning {{Only call free if a valid (non-NULL) buffer was returned.}}
+  SecKeychainItemFreeContent(0, pwdBytes); // expected-warning {{Only call free if a valid (non-NULL) buffer was returned}}
 }
 
 //Example from bug 10797.

Modified: cfe/trunk/test/Analysis/malloc-annotations.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/malloc-annotations.c?rev=162028&r1=162027&r2=162028&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/malloc-annotations.c (original)
+++ cfe/trunk/test/Analysis/malloc-annotations.c Thu Aug 16 12:45:23 2012
@@ -208,11 +208,11 @@
 }
 
 void PR6123() {
-  int *x = malloc(11); // expected-warning{{Cast a region whose size is not a multiple of the destination type size.}}
+  int *x = malloc(11); // expected-warning{{Cast a region whose size is not a multiple of the destination type size}}
 }
 
 void PR7217() {
-  int *buf = malloc(2); // expected-warning{{Cast a region whose size is not a multiple of the destination type size.}}
+  int *buf = malloc(2); // expected-warning{{Cast a region whose size is not a multiple of the destination type size}}
   buf[1] = 'c'; // not crash
 }
 

Modified: cfe/trunk/test/Analysis/malloc.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/malloc.c?rev=162028&r1=162027&r2=162028&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/malloc.c (original)
+++ cfe/trunk/test/Analysis/malloc.c Thu Aug 16 12:45:23 2012
@@ -260,11 +260,11 @@
 }
 
 void PR6123() {
-  int *x = malloc(11); // expected-warning{{Cast a region whose size is not a multiple of the destination type size.}}
+  int *x = malloc(11); // expected-warning{{Cast a region whose size is not a multiple of the destination type size}}
 }
 
 void PR7217() {
-  int *buf = malloc(2); // expected-warning{{Cast a region whose size is not a multiple of the destination type size.}}
+  int *buf = malloc(2); // expected-warning{{Cast a region whose size is not a multiple of the destination type size}}
   buf[1] = 'c'; // not crash
 }
 
@@ -389,7 +389,7 @@
 
 void mallocMalloc() {
   int *p = malloc(12);
-  p = malloc(12); // expected-warning 2 {{Memory is never released; potential leak}}
+  p = malloc(12); // expected-warning {{Memory is never released; potential leak}}
 }
 
 void mallocFreeMalloc() {

Modified: cfe/trunk/test/Analysis/misc-ps-region-store.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/misc-ps-region-store.m?rev=162028&r1=162027&r2=162028&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/misc-ps-region-store.m (original)
+++ cfe/trunk/test/Analysis/misc-ps-region-store.m Thu Aug 16 12:45:23 2012
@@ -299,7 +299,7 @@
 int test_handle_array_wrapper() {
   struct ArrayWrapper x;
   test_handle_array_wrapper_helper(&x);
-  struct WrappedStruct *p = (struct WrappedStruct*) x.y; // expected-warning{{Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption.}}
+  struct WrappedStruct *p = (struct WrappedStruct*) x.y; // expected-warning{{Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption}}
   return p->z;  // no-warning
 }
 

Modified: cfe/trunk/test/Analysis/nil-receiver-undefined-larger-than-voidptr-ret.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/nil-receiver-undefined-larger-than-voidptr-ret.m?rev=162028&r1=162027&r2=162028&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/nil-receiver-undefined-larger-than-voidptr-ret.m (original)
+++ cfe/trunk/test/Analysis/nil-receiver-undefined-larger-than-voidptr-ret.m Thu Aug 16 12:45:23 2012
@@ -80,11 +80,11 @@
 int marker(void) { // control reaches end of non-void function
 }
 
+// CHECK-darwin8: warning: The receiver of message 'longDoubleM' is nil and returns a value of type 'long double' that will be garbage
 // CHECK-darwin8: warning: The receiver of message 'longlongM' is nil and returns a value of type 'long long' that will be garbage
-// CHECK-darwin8: warning: The receiver of message 'unsignedLongLongM' is nil and returns a value of type 'unsigned long long' that will be garbage
 // CHECK-darwin8: warning: The receiver of message 'doubleM' is nil and returns a value of type 'double' that will be garbage
+// CHECK-darwin8: warning: The receiver of message 'unsignedLongLongM' is nil and returns a value of type 'unsigned long long' that will be garbage
 // CHECK-darwin8: warning: The receiver of message 'longlongM' is nil and returns a value of type 'long long' that will be garbage
-// CHECK-darwin8: warning: The receiver of message 'longDoubleM' is nil and returns a value of type 'long double' that will be garbage
 
 // CHECK-darwin9-NOT: warning: The receiver of message 'longlongM' is nil and returns a value of type 'long long' that will be garbage
 // CHECK-darwin9-NOT: warning: The receiver of message 'unsignedLongLongM' is nil and returns a value of type 'unsigned long long' that will be garbage

Modified: cfe/trunk/test/Analysis/ptr-arith.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/ptr-arith.c?rev=162028&r1=162027&r2=162028&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/ptr-arith.c (original)
+++ cfe/trunk/test/Analysis/ptr-arith.c Thu Aug 16 12:45:23 2012
@@ -36,7 +36,7 @@
 
 void f3() {
   int x, y;
-  int d = &y - &x; // expected-warning{{Subtraction of two pointers that do not point to the same memory chunk may cause incorrect result.}}
+  int d = &y - &x; // expected-warning{{Subtraction of two pointers that do not point to the same memory chunk may cause incorrect result}}
 
   int a[10];
   int *p = &a[2];
@@ -46,13 +46,13 @@
 
 void f4() {
   int *p;
-  p = (int*) 0x10000; // expected-warning{{Using a fixed address is not portable because that address will probably not be valid in all environments or platforms.}}
+  p = (int*) 0x10000; // expected-warning{{Using a fixed address is not portable because that address will probably not be valid in all environments or platforms}}
 }
 
 void f5() {
   int x, y;
   int *p;
-  p = &x + 1;  // expected-warning{{Pointer arithmetic done on non-array variables means reliance on memory layout, which is dangerous.}}
+  p = &x + 1;  // expected-warning{{Pointer arithmetic done on non-array variables means reliance on memory layout, which is dangerous}}
 
   int a[10];
   p = a + 1; // no-warning

Modified: cfe/trunk/test/Analysis/security-syntax-checks.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/security-syntax-checks.m?rev=162028&r1=162027&r2=162028&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/security-syntax-checks.m (original)
+++ cfe/trunk/test/Analysis/security-syntax-checks.m Thu Aug 16 12:45:23 2012
@@ -46,7 +46,7 @@
 
 void test_getpw() {
   char buff[1024];
-  getpw(2, buff); // expected-warning{{The getpw() function is dangerous as it may overflow the provided buffer. It is obsoleted by getpwuid().}}
+  getpw(2, buff); // expected-warning{{The getpw() function is dangerous as it may overflow the provided buffer. It is obsoleted by getpwuid()}}
 }
 
 // <rdar://problem/6337132> CWE-273: Failure to Check Whether Privileges Were
@@ -138,7 +138,7 @@
   char x[4];
   char *y;
 
-  strcpy(x, y); //expected-warning{{Call to function 'strcpy' is insecure as it does not provide bounding of the memory buffer. Replace unbounded copy functions with analogous functions that support length arguments such as 'strlcpy'. CWE-119.}}
+  strcpy(x, y); //expected-warning{{Call to function 'strcpy' is insecure as it does not provide bounding of the memory buffer. Replace unbounded copy functions with analogous functions that support length arguments such as 'strlcpy'. CWE-119}}
 }
 
 //===----------------------------------------------------------------------===
@@ -162,7 +162,7 @@
   char x[4];
   char *y;
 
-  strcat(x, y); //expected-warning{{Call to function 'strcat' is insecure as it does not provide bounding of the memory buffer. Replace unbounded copy functions with analogous functions that support length arguments such as 'strlcat'. CWE-119.}}
+  strcat(x, y); //expected-warning{{Call to function 'strcat' is insecure as it does not provide bounding of the memory buffer. Replace unbounded copy functions with analogous functions that support length arguments such as 'strlcat'. CWE-119}}
 }
 
 //===----------------------------------------------------------------------===
@@ -173,7 +173,7 @@
 pid_t vfork(void);
 
 void test_vfork() {
-  vfork(); //expected-warning{{Call to function 'vfork' is insecure as it can lead to denial of service situations in the parent process.}}
+  vfork(); //expected-warning{{Call to function 'vfork' is insecure as it can lead to denial of service situations in the parent process}}
 }
 
 //===----------------------------------------------------------------------===

Modified: cfe/trunk/test/Analysis/sizeofpointer.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/sizeofpointer.c?rev=162028&r1=162027&r2=162028&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/sizeofpointer.c (original)
+++ cfe/trunk/test/Analysis/sizeofpointer.c Thu Aug 16 12:45:23 2012
@@ -4,5 +4,5 @@
 };
 
 int f(struct s *p) {
-  return sizeof(p); // expected-warning{{The code calls sizeof() on a pointer type. This can produce an unexpected result.}}
+  return sizeof(p); // expected-warning{{The code calls sizeof() on a pointer type. This can produce an unexpected result}}
 }

Modified: cfe/trunk/test/Analysis/stream.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/stream.c?rev=162028&r1=162027&r2=162028&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/stream.c (original)
+++ cfe/trunk/test/Analysis/stream.c Thu Aug 16 12:45:23 2012
@@ -16,25 +16,25 @@
 void f1(void) {
   FILE *p = fopen("foo", "r");
   char buf[1024];
-  fread(buf, 1, 1, p); // expected-warning {{Stream pointer might be NULL.}}
+  fread(buf, 1, 1, p); // expected-warning {{Stream pointer might be NULL}}
   fclose(p);
 }
 
 void f2(void) {
   FILE *p = fopen("foo", "r");
-  fseek(p, 1, SEEK_SET); // expected-warning {{Stream pointer might be NULL.}}
+  fseek(p, 1, SEEK_SET); // expected-warning {{Stream pointer might be NULL}}
   fclose(p);
 }
 
 void f3(void) {
   FILE *p = fopen("foo", "r");
-  ftell(p); // expected-warning {{Stream pointer might be NULL.}}
+  ftell(p); // expected-warning {{Stream pointer might be NULL}}
   fclose(p);
 }
 
 void f4(void) {
   FILE *p = fopen("foo", "r");
-  rewind(p); // expected-warning {{Stream pointer might be NULL.}}
+  rewind(p); // expected-warning {{Stream pointer might be NULL}}
   fclose(p);
 }
 
@@ -43,26 +43,26 @@
   if (!p)
     return;
   fseek(p, 1, SEEK_SET); // no-warning
-  fseek(p, 1, 3); // expected-warning {{The whence argument to fseek() should be SEEK_SET, SEEK_END, or SEEK_CUR.}}
+  fseek(p, 1, 3); // expected-warning {{The whence argument to fseek() should be SEEK_SET, SEEK_END, or SEEK_CUR}}
   fclose(p);
 }
 
 void f6(void) {
   FILE *p = fopen("foo", "r");
   fclose(p); 
-  fclose(p); // expected-warning {{Try to close a file Descriptor already closed. Cause undefined behaviour.}}
+  fclose(p); // expected-warning {{Try to close a file Descriptor already closed. Cause undefined behaviour}}
 }
 
 void f7(void) {
   FILE *p = tmpfile();
-  ftell(p); // expected-warning {{Stream pointer might be NULL.}}
+  ftell(p); // expected-warning {{Stream pointer might be NULL}}
   fclose(p);
 }
 
 void f8(int c) {
   FILE *p = fopen("foo.c", "r");
   if(c)
-    return; // expected-warning {{Opened File never closed. Potential Resource leak.}}
+    return; // expected-warning {{Opened File never closed. Potential Resource leak}}
   fclose(p);
 }
 

Modified: cfe/trunk/test/Analysis/variadic-method-types.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/variadic-method-types.m?rev=162028&r1=162027&r2=162028&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/variadic-method-types.m (original)
+++ cfe/trunk/test/Analysis/variadic-method-types.m Thu Aug 16 12:45:23 2012
@@ -74,7 +74,7 @@
   [NSArray arrayWithObjects:@"Hello", a, b, c, d, nil];
   [NSArray arrayWithObjects:@"Foo", ^{}, nil];
 
-  [NSArray arrayWithObjects:@"Foo", "Bar", "Baz", nil]; // expected-warning 2 {{Argument to 'NSArray' method 'arrayWithObjects:' should be an Objective-C pointer type, not 'char *'}}
+  [NSArray arrayWithObjects:@"Foo", "Bar", "Baz", nil]; // expected-warning {{Argument to 'NSArray' method 'arrayWithObjects:' should be an Objective-C pointer type, not 'char *'}}
   [NSDictionary dictionaryWithObjectsAndKeys:@"Foo", "Bar", nil]; // expected-warning {{Argument to 'NSDictionary' method 'dictionaryWithObjectsAndKeys:' should be an Objective-C pointer type, not 'char *'}}
   [NSSet setWithObjects:@"Foo", "Bar", nil]; // expected-warning {{Argument to 'NSSet' method 'setWithObjects:' should be an Objective-C pointer type, not 'char *'}}
   [NSOrderedSet orderedSetWithObjects:@"Foo", "Bar", nil]; // expected-warning {{Argument to 'NSOrderedSet' method 'orderedSetWithObjects:' should be an Objective-C pointer type, not 'char *'}}





More information about the cfe-commits mailing list