зеркало из https://github.com/microsoft/clang.git
Unify the code path for the Dead Stores checker to always use the BugReporter interface.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@53054 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
01006786e3
Коммит
e207558e9d
|
@ -108,7 +108,6 @@ namespace {
|
|||
llvm::OwningPtr<CFG> cfg;
|
||||
llvm::OwningPtr<LiveVariables> liveness;
|
||||
llvm::OwningPtr<ParentMap> PM;
|
||||
llvm::OwningPtr<PathDiagnosticClient> PD;
|
||||
|
||||
public:
|
||||
AnalysisManager(AnalysisConsumer& c, Decl* d, Stmt* b)
|
||||
|
@ -124,7 +123,8 @@ namespace {
|
|||
}
|
||||
|
||||
virtual ParentMap& getParentMap() {
|
||||
if (!PM) PM.reset(new ParentMap(getBody()));
|
||||
if (!PM)
|
||||
PM.reset(new ParentMap(getBody()));
|
||||
return *PM.get();
|
||||
}
|
||||
|
||||
|
@ -145,10 +145,10 @@ namespace {
|
|||
}
|
||||
|
||||
virtual PathDiagnosticClient* getPathDiagnosticClient() {
|
||||
if (PD.get() == 0 && !C.HTMLDir.empty())
|
||||
PD.reset(CreateHTMLDiagnosticClient(C.HTMLDir, C.PP, C.PPF));
|
||||
if (C.PD.get() == 0 && !C.HTMLDir.empty())
|
||||
C.PD.reset(CreateHTMLDiagnosticClient(C.HTMLDir, C.PP, C.PPF));
|
||||
|
||||
return PD.get();
|
||||
return C.PD.get();
|
||||
}
|
||||
|
||||
virtual LiveVariables& getLiveVariables() {
|
||||
|
@ -267,9 +267,8 @@ void AnalysisConsumer::HandleCode(Decl* D, Stmt* Body, Actions actions) {
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
static void ActionDeadStores(AnalysisManager& mgr) {
|
||||
CheckDeadStores(mgr.getCFG(), mgr.getContext(),
|
||||
mgr.getLiveVariables(), mgr.getParentMap(),
|
||||
mgr.getDiagnostic());
|
||||
BugReporter BR(mgr);
|
||||
CheckDeadStores(mgr.getLiveVariables(), BR);
|
||||
}
|
||||
|
||||
static void ActionUninitVals(AnalysisManager& mgr) {
|
||||
|
|
|
@ -27,12 +27,9 @@ class BugType;
|
|||
class LangOptions;
|
||||
class ParentMap;
|
||||
class LiveVariables;
|
||||
class BugReporter;
|
||||
|
||||
void CheckDeadStores(CFG& cfg, ASTContext &Ctx, ParentMap& Parents,
|
||||
Diagnostic &Diags);
|
||||
|
||||
void CheckDeadStores(CFG& cfg, ASTContext &Ctx, LiveVariables& L,
|
||||
ParentMap& Parents, Diagnostic &Diags);
|
||||
void CheckDeadStores(LiveVariables& L, BugReporter& BR);
|
||||
|
||||
void CheckUninitializedValues(CFG& cfg, ASTContext& Ctx, Diagnostic& Diags,
|
||||
bool FullUninitTaint=false);
|
||||
|
@ -41,7 +38,6 @@ GRTransferFuncs* MakeGRSimpleValsTF();
|
|||
GRTransferFuncs* MakeCFRefCountTF(ASTContext& Ctx, bool GCEnabled,
|
||||
bool StandardWarnings,
|
||||
const LangOptions& lopts);
|
||||
BugType* MakeDeadStoresChecker();
|
||||
|
||||
} // end namespace clang
|
||||
|
||||
|
|
|
@ -15,12 +15,15 @@
|
|||
#ifndef LLVM_CLANG_ANALYSIS_BUGREPORTER
|
||||
#define LLVM_CLANG_ANALYSIS_BUGREPORTER
|
||||
|
||||
#include "clang/Basic/Diagnostic.h"
|
||||
#include "clang/Basic/SourceLocation.h"
|
||||
#include "clang/Analysis/PathSensitive/ValueState.h"
|
||||
#include "clang/Analysis/PathSensitive/ExplodedGraph.h"
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/ADT/SmallSet.h"
|
||||
#include <vector>
|
||||
#include <list>
|
||||
|
||||
|
||||
namespace clang {
|
||||
|
||||
|
@ -168,7 +171,7 @@ public:
|
|||
}
|
||||
|
||||
SourceManager& getSourceManager() {
|
||||
return getContext().getSourceManager();
|
||||
return D.getSourceManager();
|
||||
}
|
||||
|
||||
CFG& getCFG() {
|
||||
|
@ -223,6 +226,66 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
class DiagBugReport : public RangedBugReport {
|
||||
std::list<std::string> Strs;
|
||||
FullSourceLoc L;
|
||||
const char* description;
|
||||
public:
|
||||
DiagBugReport(const char* desc, BugType& D, FullSourceLoc l) :
|
||||
RangedBugReport(D, NULL), L(l), description(desc) {}
|
||||
|
||||
virtual ~DiagBugReport() {}
|
||||
virtual FullSourceLoc getLocation(SourceManager&) { return L; }
|
||||
|
||||
virtual const char* getDescription() const {
|
||||
return description;
|
||||
}
|
||||
|
||||
void addString(const std::string& s) { Strs.push_back(s); }
|
||||
|
||||
typedef std::list<std::string>::const_iterator str_iterator;
|
||||
str_iterator str_begin() const { return Strs.begin(); }
|
||||
str_iterator str_end() const { return Strs.end(); }
|
||||
};
|
||||
|
||||
class DiagCollector : public DiagnosticClient {
|
||||
std::list<DiagBugReport> Reports;
|
||||
BugType& D;
|
||||
public:
|
||||
DiagCollector(BugType& d) : D(d) {}
|
||||
|
||||
virtual ~DiagCollector() {}
|
||||
|
||||
virtual void HandleDiagnostic(Diagnostic &Diags,
|
||||
Diagnostic::Level DiagLevel,
|
||||
FullSourceLoc Pos,
|
||||
diag::kind ID,
|
||||
const std::string *Strs,
|
||||
unsigned NumStrs,
|
||||
const SourceRange *Ranges,
|
||||
unsigned NumRanges) {
|
||||
|
||||
// FIXME: Use a map from diag::kind to BugType, instead of having just
|
||||
// one BugType.
|
||||
|
||||
Reports.push_back(DiagBugReport(Diags.getDescription(ID), D, Pos));
|
||||
DiagBugReport& R = Reports.back();
|
||||
|
||||
for ( ; NumRanges ; --NumRanges, ++Ranges)
|
||||
R.addRange(*Ranges);
|
||||
|
||||
for ( ; NumStrs ; --NumStrs, ++Strs)
|
||||
R.addString(*Strs);
|
||||
}
|
||||
|
||||
// Iterators.
|
||||
|
||||
typedef std::list<DiagBugReport>::iterator iterator;
|
||||
iterator begin() { return Reports.begin(); }
|
||||
iterator end() { return Reports.end(); }
|
||||
};
|
||||
|
||||
} // end clang namespace
|
||||
|
||||
#endif
|
||||
|
|
|
@ -44,8 +44,8 @@ public:
|
|||
|
||||
std::string msg = inEnclosing
|
||||
? "Although the value stored to '" + name +
|
||||
"' is used in the enclosing expression, the value is never actually read"
|
||||
" from '" + name + "'"
|
||||
"' is used in the enclosing expression, the value is never actually"
|
||||
" read from '" + name + "'"
|
||||
: "Value stored to '" + name + "' is never read";
|
||||
|
||||
return Diags.getCustomDiagID(Diagnostic::Warning, msg.c_str());
|
||||
|
@ -143,116 +143,38 @@ public:
|
|||
|
||||
} // end anonymous namespace
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Driver function to invoke the Dead-Stores checker on a CFG.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
void clang::CheckDeadStores(CFG& cfg, ASTContext &Ctx,
|
||||
ParentMap& Parents, Diagnostic &Diags) {
|
||||
LiveVariables L(cfg);
|
||||
L.runOnCFG(cfg);
|
||||
CheckDeadStores(cfg, Ctx, L, Parents, Diags);
|
||||
}
|
||||
|
||||
void clang::CheckDeadStores(CFG& cfg, ASTContext &Ctx, LiveVariables& L,
|
||||
ParentMap& Parents, Diagnostic &Diags) {
|
||||
|
||||
DeadStoreObs A(Ctx, Diags, Diags.getClient(), Parents);
|
||||
L.runOnAllBlocks(cfg, &A);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// BugReporter-based invocation of the Dead-Stores checker.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
namespace {
|
||||
|
||||
class VISIBILITY_HIDDEN DiagBugReport : public RangedBugReport {
|
||||
std::list<std::string> Strs;
|
||||
FullSourceLoc L;
|
||||
const char* description;
|
||||
class SimpleBugType : public BugTypeCacheLocation {
|
||||
const char* name;
|
||||
public:
|
||||
DiagBugReport(const char* desc, BugType& D, FullSourceLoc l) :
|
||||
RangedBugReport(D, NULL), L(l), description(desc) {}
|
||||
SimpleBugType(const char* n) : name(n) {}
|
||||
|
||||
virtual ~DiagBugReport() {}
|
||||
virtual FullSourceLoc getLocation(SourceManager&) { return L; }
|
||||
|
||||
virtual const char* getDescription() const {
|
||||
return description;
|
||||
}
|
||||
|
||||
void addString(const std::string& s) { Strs.push_back(s); }
|
||||
|
||||
typedef std::list<std::string>::const_iterator str_iterator;
|
||||
str_iterator str_begin() const { return Strs.begin(); }
|
||||
str_iterator str_end() const { return Strs.end(); }
|
||||
};
|
||||
|
||||
class VISIBILITY_HIDDEN DiagCollector : public DiagnosticClient {
|
||||
std::list<DiagBugReport> Reports;
|
||||
BugType& D;
|
||||
public:
|
||||
DiagCollector(BugType& d) : D(d) {}
|
||||
|
||||
virtual ~DiagCollector() {}
|
||||
|
||||
virtual void HandleDiagnostic(Diagnostic &Diags,
|
||||
Diagnostic::Level DiagLevel,
|
||||
FullSourceLoc Pos,
|
||||
diag::kind ID,
|
||||
const std::string *Strs,
|
||||
unsigned NumStrs,
|
||||
const SourceRange *Ranges,
|
||||
unsigned NumRanges) {
|
||||
|
||||
// FIXME: Use a map from diag::kind to BugType, instead of having just
|
||||
// one BugType.
|
||||
|
||||
Reports.push_back(DiagBugReport(Diags.getDescription(ID), D, Pos));
|
||||
DiagBugReport& R = Reports.back();
|
||||
|
||||
for ( ; NumRanges ; --NumRanges, ++Ranges)
|
||||
R.addRange(*Ranges);
|
||||
|
||||
for ( ; NumStrs ; --NumStrs, ++Strs)
|
||||
R.addString(*Strs);
|
||||
}
|
||||
|
||||
// Iterators.
|
||||
|
||||
typedef std::list<DiagBugReport>::iterator iterator;
|
||||
iterator begin() { return Reports.begin(); }
|
||||
iterator end() { return Reports.end(); }
|
||||
};
|
||||
|
||||
class VISIBILITY_HIDDEN DeadStoresChecker : public BugTypeCacheLocation {
|
||||
public:
|
||||
virtual const char* getName() const {
|
||||
return "dead store";
|
||||
return name;
|
||||
}
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
virtual const char* getDescription() const {
|
||||
return "Value stored to variable is never subsequently read.";
|
||||
}
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Driver function to invoke the Dead-Stores checker on a CFG.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
virtual void EmitWarnings(BugReporter& BR) {
|
||||
void clang::CheckDeadStores(LiveVariables& L, BugReporter& BR) {
|
||||
|
||||
SimpleBugType BT("dead store");
|
||||
DiagCollector C(BT);
|
||||
|
||||
// Run the dead store checker and collect the diagnostics.
|
||||
DiagCollector C(*this);
|
||||
DeadStoreObs A(BR.getContext(), BR.getDiagnostic(), C, BR.getParentMap());
|
||||
|
||||
|
||||
BR.getLiveVariables().runOnAllBlocks(BR.getCFG(), &A);
|
||||
L.runOnAllBlocks(BR.getCFG(), &A);
|
||||
|
||||
// Emit the bug reports.
|
||||
|
||||
for (DiagCollector::iterator I = C.begin(), E = C.end(); I != E; ++I)
|
||||
BR.EmitWarning(*I);
|
||||
}
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
BugType* clang::MakeDeadStoresChecker() {
|
||||
return new DeadStoresChecker();
|
||||
}
|
||||
|
||||
|
|
|
@ -350,9 +350,6 @@ void GRSimpleVals::RegisterChecks(GRExprEngine& Eng) {
|
|||
Eng.Register(new BadMsgExprArg());
|
||||
Eng.Register(new BadReceiver());
|
||||
|
||||
// Flow-sensitive checks.
|
||||
Eng.Register(MakeDeadStoresChecker());
|
||||
|
||||
// Add extra checkers.
|
||||
ASTContext& Ctx = Eng.getContext();
|
||||
ValueStateManager* VMgr = &Eng.getStateManager();
|
||||
|
|
Загрузка…
Ссылка в новой задаче