From 47187c6ad22b5498459b3a0562443feeed260887 Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Wed, 29 Apr 2009 21:58:13 +0000 Subject: [PATCH] BugReporter/PathDiagnostics: - Add an (optional) short description for BugReports for clients that want to distinguish between long and short descriptions for bugs - Make the bug report for VLA less obscene for Plist diagnostics by using the short description llvm-svn: 70415 --- clang/include/clang/Analysis/PathDiagnostic.h | 1 + .../clang/Analysis/PathSensitive/BugReporter.h | 14 ++++++++++++++ clang/lib/Analysis/BugReporter.cpp | 11 +++++++---- clang/lib/Analysis/GRExprEngineInternalChecks.cpp | 15 +++++++++++++-- clang/lib/Frontend/PlistDiagnostics.cpp | 1 + 5 files changed, 36 insertions(+), 6 deletions(-) diff --git a/clang/include/clang/Analysis/PathDiagnostic.h b/clang/include/clang/Analysis/PathDiagnostic.h index 84fe8d92c60d..16b9b06f7b13 100644 --- a/clang/include/clang/Analysis/PathDiagnostic.h +++ b/clang/include/clang/Analysis/PathDiagnostic.h @@ -50,6 +50,7 @@ public: virtual PathGenerationScheme getGenerationScheme() const { return Minimal; } virtual bool supportsLogicalOpControlFlow() const { return false; } virtual bool supportsAllBlockEdges() const { return false; } + virtual bool useVerboseDescription() const { return true; } }; //===----------------------------------------------------------------------===// diff --git a/clang/include/clang/Analysis/PathSensitive/BugReporter.h b/clang/include/clang/Analysis/PathSensitive/BugReporter.h index 85430e366ef1..f941a7a57087 100644 --- a/clang/include/clang/Analysis/PathSensitive/BugReporter.h +++ b/clang/include/clang/Analysis/PathSensitive/BugReporter.h @@ -48,6 +48,7 @@ class ParentMap; class BugReport { protected: BugType& BT; + std::string ShortDescription; std::string Description; const ExplodedNode *EndNode; SourceRange R; @@ -70,6 +71,11 @@ public: BugReport(BugType& bt, const char* desc, const ExplodedNode *n) : BT(bt), Description(desc), EndNode(n) {} + + BugReport(BugType& bt, const char* shortDesc, const char* desc, + const ExplodedNode *n) + : BT(bt), ShortDescription(shortDesc), Description(desc), EndNode(n) {} + virtual ~BugReport(); @@ -84,6 +90,10 @@ public: Stmt* getStmt(BugReporter& BR) const; const std::string& getDescription() const { return Description; } + + const std::string& getShortDescription() const { + return ShortDescription.empty() ? Description : ShortDescription; + } // FIXME: Is this needed? virtual std::pair getExtraDescriptiveText() { @@ -197,6 +207,10 @@ public: RangedBugReport(BugType& D, const char* description, ExplodedNode *n) : BugReport(D, description, n) {} + RangedBugReport(BugType& D, const char *shortDescription, + const char *description, ExplodedNode *n) + : BugReport(D, shortDescription, description, n) {} + ~RangedBugReport(); // FIXME: Move this out of line. diff --git a/clang/lib/Analysis/BugReporter.cpp b/clang/lib/Analysis/BugReporter.cpp index 3c814dbb67bd..4e88baab5748 100644 --- a/clang/lib/Analysis/BugReporter.cpp +++ b/clang/lib/Analysis/BugReporter.cpp @@ -1667,14 +1667,18 @@ void BugReporter::EmitReport(BugReport* R) { void BugReporter::FlushReport(BugReportEquivClass& EQ) { assert(!EQ.Reports.empty()); BugReport &R = **EQ.begin(); + PathDiagnosticClient* PD = getPathDiagnosticClient(); // FIXME: Make sure we use the 'R' for the path that was actually used. // Probably doesn't make a difference in practice. BugType& BT = R.getBugType(); - llvm::OwningPtr D(new PathDiagnostic(R.getBugType().getName(), - R.getDescription(), - BT.getCategory())); + llvm::OwningPtr + D(new PathDiagnostic(R.getBugType().getName(), + PD->useVerboseDescription() + ? R.getDescription() : R.getShortDescription(), + BT.getCategory())); + GeneratePathDiagnostic(*D.get(), EQ); // Get the meta data. @@ -1682,7 +1686,6 @@ void BugReporter::FlushReport(BugReportEquivClass& EQ) { for (const char** s = Meta.first; s != Meta.second; ++s) D->addMeta(*s); // Emit a summary diagnostic to the regular Diagnostics engine. - PathDiagnosticClient* PD = getPathDiagnosticClient(); const SourceRange *Beg = 0, *End = 0; R.getRanges(*this, Beg, End); Diagnostic& Diag = getDiagnostic(); diff --git a/clang/lib/Analysis/GRExprEngineInternalChecks.cpp b/clang/lib/Analysis/GRExprEngineInternalChecks.cpp index 1b0314920418..a40eff8fc42c 100644 --- a/clang/lib/Analysis/GRExprEngineInternalChecks.cpp +++ b/clang/lib/Analysis/GRExprEngineInternalChecks.cpp @@ -405,12 +405,23 @@ public: "variable-length array (VLA) '" << VD->getNameAsString() << "' evaluates to "; - if (Eng.getStateManager().GetSVal(N->getState(), SizeExpr).isUndef()) + bool isUndefined = Eng.getStateManager().GetSVal(N->getState(), + SizeExpr).isUndef(); + + if (isUndefined) os << "an undefined or garbage value."; else os << "0. VLAs with no elements have undefined behavior."; + + std::string shortBuf; + llvm::raw_string_ostream os_short(shortBuf); + os_short << "Variable-length array '" << VD->getNameAsString() << "' " + << (isUndefined ? " garbage value for array size" + : " has zero elements (undefined behavior)"); - RangedBugReport *report = new RangedBugReport(*this, os.str().c_str(), N); + RangedBugReport *report = new RangedBugReport(*this, + os_short.str().c_str(), + os.str().c_str(), N); report->addRange(SizeExpr->getSourceRange()); BR.EmitReport(report); } diff --git a/clang/lib/Frontend/PlistDiagnostics.cpp b/clang/lib/Frontend/PlistDiagnostics.cpp index 7ad900e8741c..387ed45a9c71 100644 --- a/clang/lib/Frontend/PlistDiagnostics.cpp +++ b/clang/lib/Frontend/PlistDiagnostics.cpp @@ -45,6 +45,7 @@ namespace { PathGenerationScheme getGenerationScheme() const { return Extensive; } bool supportsLogicalOpControlFlow() const { return true; } bool supportsAllBlockEdges() const { return true; } + virtual bool useVerboseDescription() const { return false; } }; } // end anonymous namespace