diff options
-rw-r--r-- | Driver/ASTConsumers.cpp | 8 | ||||
-rw-r--r-- | Driver/HTMLDiagnostics.cpp | 13 | ||||
-rw-r--r-- | include/clang/Analysis/LocalCheckers.h | 6 | ||||
-rw-r--r-- | include/clang/Analysis/PathDiagnostic.h | 8 | ||||
-rw-r--r-- | include/clang/Analysis/PathSensitive/BugReporter.h | 8 | ||||
-rw-r--r-- | lib/Analysis/BugReporter.cpp | 7 | ||||
-rw-r--r-- | lib/Analysis/CFRefCount.cpp | 58 |
7 files changed, 93 insertions, 15 deletions
diff --git a/Driver/ASTConsumers.cpp b/Driver/ASTConsumers.cpp index c01e4edb0d..59e477ab65 100644 --- a/Driver/ASTConsumers.cpp +++ b/Driver/ASTConsumers.cpp @@ -813,16 +813,16 @@ public: virtual void getTransferFunctions(std::vector<GRTransferFuncs*>& TFs) { switch (LangOpts.getGCMode()) { case LangOptions::NonGC: - TFs.push_back(MakeCFRefCountTF(*Ctx, false)); + TFs.push_back(MakeCFRefCountTF(*Ctx, false, LangOpts)); break; case LangOptions::GCOnly: - TFs.push_back(MakeCFRefCountTF(*Ctx, true)); + TFs.push_back(MakeCFRefCountTF(*Ctx, true, LangOpts)); break; case LangOptions::HybridGC: - TFs.push_back(MakeCFRefCountTF(*Ctx, false)); - TFs.push_back(MakeCFRefCountTF(*Ctx, true)); + TFs.push_back(MakeCFRefCountTF(*Ctx, false, LangOpts)); + TFs.push_back(MakeCFRefCountTF(*Ctx, true, LangOpts)); break; } } diff --git a/Driver/HTMLDiagnostics.cpp b/Driver/HTMLDiagnostics.cpp index 3e3571c512..cb333b978c 100644 --- a/Driver/HTMLDiagnostics.cpp +++ b/Driver/HTMLDiagnostics.cpp @@ -187,9 +187,16 @@ void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D) { << (*D.rbegin()).getLocation().getLogicalColumnNumber() << "</a></td></tr>\n" "<tr><td class=\"rowname\">Description:</td><td>" - << D.getDescription() - << "</td></tr>\n</table>\n" - "<h3>Annotated Source Code</h3>\n"; + << D.getDescription() << "</td></tr>\n"; + + // Output any other meta data. + + for (PathDiagnostic::meta_iterator I=D.meta_begin(), E=D.meta_end(); + I!=E; ++I) { + os << "<tr><td></td><td>" << html::EscapeText(*I) << "</td></tr>\n"; + } + + os << "</table>\n<h3>Annotated Source Code</h3>\n"; R.InsertStrBefore(SourceLocation::getFileLoc(FileID, 0), os.str()); } diff --git a/include/clang/Analysis/LocalCheckers.h b/include/clang/Analysis/LocalCheckers.h index bf4f30a337..64dc4dd90f 100644 --- a/include/clang/Analysis/LocalCheckers.h +++ b/include/clang/Analysis/LocalCheckers.h @@ -24,14 +24,16 @@ class ASTContext; class PathDiagnosticClient; class GRTransferFuncs; class BugType; - +class LangOptions; + void CheckDeadStores(CFG& cfg, ASTContext &Ctx, Diagnostic &Diags); void CheckUninitializedValues(CFG& cfg, ASTContext& Ctx, Diagnostic& Diags, bool FullUninitTaint=false); GRTransferFuncs* MakeGRSimpleValsTF(); -GRTransferFuncs* MakeCFRefCountTF(ASTContext& Ctx, bool GCEnabled); +GRTransferFuncs* MakeCFRefCountTF(ASTContext& Ctx, bool GCEnabled, + const LangOptions& lopts); BugType* MakeDeadStoresChecker(); } // end namespace clang diff --git a/include/clang/Analysis/PathDiagnostic.h b/include/clang/Analysis/PathDiagnostic.h index f9bd0fd106..77234e7c4a 100644 --- a/include/clang/Analysis/PathDiagnostic.h +++ b/include/clang/Analysis/PathDiagnostic.h @@ -65,6 +65,7 @@ class PathDiagnostic { std::list<PathDiagnosticPiece*> path; unsigned Size; std::string Desc; + std::vector<std::string> OtherDesc; public: PathDiagnostic() : Size(0) {} @@ -75,6 +76,13 @@ public: const std::string& getDescription() const { return Desc; } + typedef std::vector<std::string>::const_iterator meta_iterator; + meta_iterator meta_begin() const { return OtherDesc.begin(); } + meta_iterator meta_end() const { return OtherDesc.end(); } + void addMeta(const std::string& s) { OtherDesc.push_back(s); } + void addMeta(const char* s) { OtherDesc.push_back(s); } + + void push_front(PathDiagnosticPiece* piece) { path.push_front(piece); ++Size; diff --git a/include/clang/Analysis/PathSensitive/BugReporter.h b/include/clang/Analysis/PathSensitive/BugReporter.h index 325e1a750f..5a8606f071 100644 --- a/include/clang/Analysis/PathSensitive/BugReporter.h +++ b/include/clang/Analysis/PathSensitive/BugReporter.h @@ -41,6 +41,10 @@ public: virtual const char* getName() const = 0; virtual const char* getDescription() const { return getName(); } + + virtual std::pair<const char**,const char**> getExtraDescriptiveText() { + return std::pair<const char**, const char**>(0, 0); + } virtual void EmitWarnings(BugReporter& BR) {} virtual void GetErrorNodes(std::vector<ExplodedNode<ValueState>*>& Nodes) {} @@ -78,6 +82,10 @@ public: return getBugType().getDescription(); } + virtual std::pair<const char**,const char**> getExtraDescriptiveText() { + return getBugType().getExtraDescriptiveText(); + } + virtual PathDiagnosticPiece* getEndPath(BugReporter& BR, ExplodedNode<ValueState>* N) const; diff --git a/lib/Analysis/BugReporter.cpp b/lib/Analysis/BugReporter.cpp index d00d329e95..465acf03f3 100644 --- a/lib/Analysis/BugReporter.cpp +++ b/lib/Analysis/BugReporter.cpp @@ -448,6 +448,13 @@ void BugReporter::EmitWarning(BugReport& R) { llvm::OwningPtr<PathDiagnostic> D(new PathDiagnostic(R.getName())); GeneratePathDiagnostic(*D.get(), R); + + // Get the meta data. + + std::pair<const char**, const char**> Meta = R.getExtraDescriptiveText(); + + for (const char** s = Meta.first; s != Meta.second; ++s) + D->addMeta(*s); // Emit a full diagnostic for the path if we have a PathDiagnosticClient. diff --git a/lib/Analysis/CFRefCount.cpp b/lib/Analysis/CFRefCount.cpp index 9ed4f1db29..c5f582fdbe 100644 --- a/lib/Analysis/CFRefCount.cpp +++ b/lib/Analysis/CFRefCount.cpp @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// #include "GRSimpleVals.h" +#include "clang/Basic/LangOptions.h" #include "clang/Analysis/PathSensitive/ValueState.h" #include "clang/Analysis/PathDiagnostic.h" #include "clang/Analysis/LocalCheckers.h" @@ -624,7 +625,8 @@ private: // Instance variables. CFRefSummaryManager Summaries; - const bool GCEnabled; + const bool GCEnabled; + const LangOptions& LOpts; RefBFactoryTy RefBFactory; UseAfterReleasesTy UseAfterReleases; @@ -670,9 +672,10 @@ private: public: - CFRefCount(ASTContext& Ctx, bool gcenabled) + CFRefCount(ASTContext& Ctx, bool gcenabled, const LangOptions& lopts) : Summaries(Ctx, gcenabled), GCEnabled(gcenabled), + LOpts(lopts), RetainSelector(GetUnarySelector("retain", Ctx)), ReleaseSelector(GetUnarySelector("release", Ctx)) {} @@ -687,6 +690,9 @@ public: return &Printer; } + bool isGCEnabled() const { return GCEnabled; } + const LangOptions& getLangOptions() const { return LOpts; } + // Calls. virtual void EvalCall(ExplodedNodeSet<ValueState>& Dst, @@ -1375,6 +1381,8 @@ namespace { public: CFRefBug(CFRefCount& tf) : TF(tf) {} + + CFRefCount& getTF() { return TF; } }; class VISIBILITY_HIDDEN UseAfterRelease : public CFRefBug { @@ -1390,7 +1398,6 @@ namespace { } virtual void EmitWarnings(BugReporter& BR); - }; class VISIBILITY_HIDDEN BadRelease : public CFRefBug { @@ -1432,11 +1439,12 @@ namespace { class VISIBILITY_HIDDEN CFRefReport : public RangedBugReport { SymbolID Sym; public: - CFRefReport(BugType& D, ExplodedNode<ValueState> *n, SymbolID sym) + CFRefReport(CFRefBug& D, ExplodedNode<ValueState> *n, SymbolID sym) : RangedBugReport(D, n), Sym(sym) {} virtual ~CFRefReport() {} + virtual std::pair<const char**,const char**> getExtraDescriptiveText(); virtual PathDiagnosticPiece* VisitNode(ExplodedNode<ValueState>* N, ExplodedNode<ValueState>* PrevN, @@ -1454,6 +1462,43 @@ void CFRefCount::RegisterChecks(GRExprEngine& Eng) { Eng.Register(new Leak(*this)); } + +static const char* Msgs[] = { + "Code is compiled in garbage collection only mode" // GC only + " (the bug occurs with garbage collection enabled).", + + "Code is compiled without garbage collection.", // No GC. + + "Code is compiled for use with and without garbage collection (GC)." + " The bug occurs with GC enabled.", // Hybrid, with GC. + + "Code is compiled for use with and without garbage collection (GC)." + " The bug occurs in non-GC mode." // Hyrbird, without GC/ +}; + +std::pair<const char**,const char**> CFRefReport::getExtraDescriptiveText() { + CFRefCount& TF = static_cast<CFRefBug&>(getBugType()).getTF(); + + switch (TF.getLangOptions().getGCMode()) { + default: + assert(false); + + case LangOptions::NonGC: + assert (!TF.isGCEnabled()); + return std::make_pair(&Msgs[0], &Msgs[0]+1); + + case LangOptions::GCOnly: + assert (TF.isGCEnabled()); + return std::make_pair(&Msgs[1], &Msgs[1]+1); + + case LangOptions::HybridGC: + if (TF.isGCEnabled()) + return std::make_pair(&Msgs[2], &Msgs[2]+1); + else + return std::make_pair(&Msgs[3], &Msgs[3]+1); + } +} + PathDiagnosticPiece* CFRefReport::VisitNode(ExplodedNode<ValueState>* N, ExplodedNode<ValueState>* PrevN, ExplodedGraph<ValueState>& G, @@ -1618,6 +1663,7 @@ void Leak::GetErrorNodes(std::vector<ExplodedNode<ValueState>*>& Nodes) { // Transfer function creation for external clients. //===----------------------------------------------------------------------===// -GRTransferFuncs* clang::MakeCFRefCountTF(ASTContext& Ctx, bool GCEnabled) { - return new CFRefCount(Ctx, GCEnabled); +GRTransferFuncs* clang::MakeCFRefCountTF(ASTContext& Ctx, bool GCEnabled, + const LangOptions& lopts) { + return new CFRefCount(Ctx, GCEnabled, lopts); } |