зеркало из https://github.com/microsoft/clang-1.git
Refactor the AnalysisConsumer to analyze functions after the whole
translation unit is parsed. This enables us to inline some calls when still analyzing one function at a time. Actions are classified into Function, CXXMethod, ObjCMethod, ObjCImplementation. This does not hurt performance much. The analysis time for sqlite3.c: before: real 17m52.440s user 17m49.460s sys 0m2.010s after: real 18m0.500s user 17m56.900s sys 0m2.330s DisplayProgress option is broken now. -inine-call action is removed. It will be reenabled in another form, perhaps as an indenpendant option. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@102689 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
51e2a5d45d
Коммит
ed8afacb81
|
@ -15,22 +15,21 @@
|
||||||
#define ANALYSIS(NAME, CMDFLAG, DESC, SCOPE)
|
#define ANALYSIS(NAME, CMDFLAG, DESC, SCOPE)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ANALYSIS(CFGDump, "cfg-dump",
|
ANALYSIS(CFGDump, "cfg-dump",
|
||||||
"Display Control-Flow Graphs", Code)
|
"Display Control-Flow Graphs", Code)
|
||||||
|
|
||||||
ANALYSIS(CFGView, "cfg-view",
|
ANALYSIS(CFGView, "cfg-view",
|
||||||
"View Control-Flow Graphs using GraphViz", Code)
|
"View Control-Flow Graphs using GraphViz", Code)
|
||||||
|
|
||||||
ANALYSIS(DisplayLiveVariables, "dump-live-variables",
|
ANALYSIS(DisplayLiveVariables, "dump-live-variables",
|
||||||
"Print results of live variable analysis", Code)
|
"Print results of live variable analysis", Code)
|
||||||
|
|
||||||
ANALYSIS(SecuritySyntacticChecks, "analyzer-check-security-syntactic",
|
ANALYSIS(SecuritySyntacticChecks, "analyzer-check-security-syntactic",
|
||||||
"Perform quick security checks that require no data flow",
|
"Perform quick security checks that require no data flow", Code)
|
||||||
Code)
|
|
||||||
|
|
||||||
ANALYSIS(LLVMConventionChecker, "analyzer-check-llvm-conventions",
|
ANALYSIS(LLVMConventionChecker, "analyzer-check-llvm-conventions",
|
||||||
"Check code for LLVM codebase conventions (domain-specific)",
|
"Check code for LLVM codebase conventions (domain-specific)",
|
||||||
TranslationUnit)
|
TranslationUnit)
|
||||||
|
|
||||||
ANALYSIS(WarnDeadStores, "analyzer-check-dead-stores",
|
ANALYSIS(WarnDeadStores, "analyzer-check-dead-stores",
|
||||||
"Warn about stores to dead variables", Code)
|
"Warn about stores to dead variables", Code)
|
||||||
|
@ -39,15 +38,15 @@ ANALYSIS(WarnUninitVals, "warn-uninit-values",
|
||||||
"Warn about uses of uninitialized variables", Code)
|
"Warn about uses of uninitialized variables", Code)
|
||||||
|
|
||||||
ANALYSIS(WarnObjCMethSigs, "analyzer-check-objc-methodsigs",
|
ANALYSIS(WarnObjCMethSigs, "analyzer-check-objc-methodsigs",
|
||||||
"Warn about Objective-C method signatures with type incompatibilities",
|
"Warn about Objective-C method signatures with type incompatibilities",
|
||||||
ObjCImplementation)
|
ObjCImplementation)
|
||||||
|
|
||||||
ANALYSIS(WarnObjCDealloc, "analyzer-check-objc-missing-dealloc",
|
ANALYSIS(WarnObjCDealloc, "analyzer-check-objc-missing-dealloc",
|
||||||
"Warn about Objective-C classes that lack a correct implementation of -dealloc",
|
"Warn about Objective-C classes that lack a correct implementation of -dealloc",
|
||||||
ObjCImplementation)
|
ObjCImplementation)
|
||||||
|
|
||||||
ANALYSIS(WarnObjCUnusedIvars, "analyzer-check-objc-unused-ivars",
|
ANALYSIS(WarnObjCUnusedIvars, "analyzer-check-objc-unused-ivars",
|
||||||
"Warn about private ivars that are never used", ObjCImplementation)
|
"Warn about private ivars that are never used", ObjCImplementation)
|
||||||
|
|
||||||
ANALYSIS(ObjCMemChecker, "analyzer-check-objc-mem",
|
ANALYSIS(ObjCMemChecker, "analyzer-check-objc-mem",
|
||||||
"Run the [Core] Foundation reference count checker", Code)
|
"Run the [Core] Foundation reference count checker", Code)
|
||||||
|
@ -55,10 +54,6 @@ ANALYSIS(ObjCMemChecker, "analyzer-check-objc-mem",
|
||||||
ANALYSIS(WarnSizeofPointer, "warn-sizeof-pointer",
|
ANALYSIS(WarnSizeofPointer, "warn-sizeof-pointer",
|
||||||
"Warn about unintended use of sizeof() on pointer expressions", Code)
|
"Warn about unintended use of sizeof() on pointer expressions", Code)
|
||||||
|
|
||||||
ANALYSIS(InlineCall, "inline-call",
|
|
||||||
"Experimental transfer function inling callees when its definition"
|
|
||||||
" is available.", TranslationUnit)
|
|
||||||
|
|
||||||
#ifndef ANALYSIS_STORE
|
#ifndef ANALYSIS_STORE
|
||||||
#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATFN)
|
#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATFN)
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -62,20 +62,21 @@ CreatePlistHTMLDiagnosticClient(const std::string& prefix,
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
class AnalysisConsumer : public ASTConsumer {
|
class AnalysisConsumer : public ASTConsumer {
|
||||||
public:
|
public:
|
||||||
typedef void (*CodeAction)(AnalysisConsumer &C, AnalysisManager &M, Decl *D);
|
typedef void (*CodeAction)(AnalysisConsumer &C, AnalysisManager &M, Decl *D);
|
||||||
typedef void (*TUAction)(AnalysisConsumer &C, AnalysisManager &M,
|
typedef void (*TUAction)(AnalysisConsumer &C, AnalysisManager &M,
|
||||||
TranslationUnitDecl &TU);
|
TranslationUnitDecl &TU);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef std::vector<CodeAction> Actions;
|
typedef std::vector<CodeAction> Actions;
|
||||||
typedef std::vector<TUAction> TUActions;
|
typedef std::vector<TUAction> TUActions;
|
||||||
|
|
||||||
Actions FunctionActions;
|
Actions FunctionActions;
|
||||||
Actions ObjCMethodActions;
|
Actions ObjCMethodActions;
|
||||||
Actions ObjCImplementationActions;
|
Actions ObjCImplementationActions;
|
||||||
TUActions TranslationUnitActions;
|
Actions CXXMethodActions;
|
||||||
|
TUActions TranslationUnitActions; // Remove this.
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ASTContext* Ctx;
|
ASTContext* Ctx;
|
||||||
|
@ -161,16 +162,17 @@ public:
|
||||||
void addCodeAction(CodeAction action) {
|
void addCodeAction(CodeAction action) {
|
||||||
FunctionActions.push_back(action);
|
FunctionActions.push_back(action);
|
||||||
ObjCMethodActions.push_back(action);
|
ObjCMethodActions.push_back(action);
|
||||||
}
|
CXXMethodActions.push_back(action);
|
||||||
|
|
||||||
void addObjCImplementationAction(CodeAction action) {
|
|
||||||
ObjCImplementationActions.push_back(action);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void addTranslationUnitAction(TUAction action) {
|
void addTranslationUnitAction(TUAction action) {
|
||||||
TranslationUnitActions.push_back(action);
|
TranslationUnitActions.push_back(action);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void addObjCImplementationAction(CodeAction action) {
|
||||||
|
ObjCImplementationActions.push_back(action);
|
||||||
|
}
|
||||||
|
|
||||||
virtual void Initialize(ASTContext &Context) {
|
virtual void Initialize(ASTContext &Context) {
|
||||||
Ctx = &Context;
|
Ctx = &Context;
|
||||||
Mgr.reset(new AnalysisManager(*Ctx, PP.getDiagnostics(),
|
Mgr.reset(new AnalysisManager(*Ctx, PP.getDiagnostics(),
|
||||||
|
@ -182,16 +184,8 @@ public:
|
||||||
Opts.TrimGraph));
|
Opts.TrimGraph));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void HandleTopLevelDecl(DeclGroupRef D) {
|
|
||||||
declDisplayed = false;
|
|
||||||
for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I)
|
|
||||||
HandleTopLevelSingleDecl(*I);
|
|
||||||
}
|
|
||||||
|
|
||||||
void HandleTopLevelSingleDecl(Decl *D);
|
|
||||||
virtual void HandleTranslationUnit(ASTContext &C);
|
virtual void HandleTranslationUnit(ASTContext &C);
|
||||||
|
void HandleCode(Decl *D, Stmt* Body, Actions& actions);
|
||||||
void HandleCode(Decl* D, Stmt* Body, Actions& actions);
|
|
||||||
};
|
};
|
||||||
} // end anonymous namespace
|
} // end anonymous namespace
|
||||||
|
|
||||||
|
@ -208,57 +202,69 @@ namespace llvm {
|
||||||
// AnalysisConsumer implementation.
|
// AnalysisConsumer implementation.
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
void AnalysisConsumer::HandleTopLevelSingleDecl(Decl *D) {
|
|
||||||
switch (D->getKind()) {
|
|
||||||
case Decl::CXXConstructor:
|
|
||||||
case Decl::CXXDestructor:
|
|
||||||
case Decl::CXXConversion:
|
|
||||||
case Decl::CXXMethod:
|
|
||||||
case Decl::Function: {
|
|
||||||
FunctionDecl* FD = cast<FunctionDecl>(D);
|
|
||||||
if (!Opts.AnalyzeSpecificFunction.empty() &&
|
|
||||||
FD->getDeclName().getAsString() != Opts.AnalyzeSpecificFunction)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (Stmt *Body = FD->getBody())
|
|
||||||
HandleCode(FD, Body, FunctionActions);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case Decl::ObjCMethod: {
|
|
||||||
ObjCMethodDecl* MD = cast<ObjCMethodDecl>(D);
|
|
||||||
|
|
||||||
if (!Opts.AnalyzeSpecificFunction.empty() &&
|
|
||||||
Opts.AnalyzeSpecificFunction != MD->getSelector().getAsString())
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (Stmt* Body = MD->getBody())
|
|
||||||
HandleCode(MD, Body, ObjCMethodActions);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AnalysisConsumer::HandleTranslationUnit(ASTContext &C) {
|
void AnalysisConsumer::HandleTranslationUnit(ASTContext &C) {
|
||||||
|
|
||||||
TranslationUnitDecl *TU = C.getTranslationUnitDecl();
|
TranslationUnitDecl *TU = C.getTranslationUnitDecl();
|
||||||
|
|
||||||
|
for (DeclContext::decl_iterator I = TU->decls_begin(), E = TU->decls_end();
|
||||||
|
I != E; ++I) {
|
||||||
|
Decl *D = *I;
|
||||||
|
|
||||||
|
switch (D->getKind()) {
|
||||||
|
case Decl::CXXConstructor:
|
||||||
|
case Decl::CXXDestructor:
|
||||||
|
case Decl::CXXConversion:
|
||||||
|
case Decl::CXXMethod:
|
||||||
|
case Decl::Function: {
|
||||||
|
FunctionDecl* FD = cast<FunctionDecl>(D);
|
||||||
|
|
||||||
|
if (FD->isThisDeclarationADefinition()) {
|
||||||
|
if (!Opts.AnalyzeSpecificFunction.empty() &&
|
||||||
|
FD->getDeclName().getAsString() != Opts.AnalyzeSpecificFunction)
|
||||||
|
break;
|
||||||
|
HandleCode(FD, FD->getBody(), FunctionActions);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Decl::ObjCMethod: {
|
||||||
|
ObjCMethodDecl* MD = cast<ObjCMethodDecl>(D);
|
||||||
|
|
||||||
|
if (MD->isThisDeclarationADefinition()) {
|
||||||
|
if (!Opts.AnalyzeSpecificFunction.empty() &&
|
||||||
|
Opts.AnalyzeSpecificFunction != MD->getSelector().getAsString())
|
||||||
|
break;
|
||||||
|
HandleCode(MD, MD->getBody(), ObjCMethodActions);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Decl::ObjCImplementation: {
|
||||||
|
ObjCImplementationDecl* ID = cast<ObjCImplementationDecl>(*I);
|
||||||
|
HandleCode(ID, 0, ObjCImplementationActions);
|
||||||
|
|
||||||
|
for (ObjCImplementationDecl::method_iterator MI = ID->meth_begin(),
|
||||||
|
ME = ID->meth_end(); MI != ME; ++MI) {
|
||||||
|
if ((*MI)->isThisDeclarationADefinition()) {
|
||||||
|
if (!Opts.AnalyzeSpecificFunction.empty() &&
|
||||||
|
Opts.AnalyzeSpecificFunction != (*MI)->getSelector().getAsString())
|
||||||
|
break;
|
||||||
|
HandleCode(*MI, (*MI)->getBody(), ObjCMethodActions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (TUActions::iterator I = TranslationUnitActions.begin(),
|
for (TUActions::iterator I = TranslationUnitActions.begin(),
|
||||||
E = TranslationUnitActions.end(); I != E; ++I) {
|
E = TranslationUnitActions.end(); I != E; ++I) {
|
||||||
(*I)(*this, *Mgr, *TU);
|
(*I)(*this, *Mgr, *TU);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ObjCImplementationActions.empty()) {
|
|
||||||
for (DeclContext::decl_iterator I = TU->decls_begin(),
|
|
||||||
E = TU->decls_end();
|
|
||||||
I != E; ++I)
|
|
||||||
if (ObjCImplementationDecl* ID = dyn_cast<ObjCImplementationDecl>(*I))
|
|
||||||
HandleCode(ID, 0, ObjCImplementationActions);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Explicitly destroy the PathDiagnosticClient. This will flush its output.
|
// Explicitly destroy the PathDiagnosticClient. This will flush its output.
|
||||||
// FIXME: This should be replaced with something that doesn't rely on
|
// FIXME: This should be replaced with something that doesn't rely on
|
||||||
// side-effects in PathDiagnosticClient's destructor. This is required when
|
// side-effects in PathDiagnosticClient's destructor. This is required when
|
||||||
|
@ -311,7 +317,6 @@ void AnalysisConsumer::HandleCode(Decl *D, Stmt* Body, Actions& actions) {
|
||||||
static void ActionWarnDeadStores(AnalysisConsumer &C, AnalysisManager& mgr,
|
static void ActionWarnDeadStores(AnalysisConsumer &C, AnalysisManager& mgr,
|
||||||
Decl *D) {
|
Decl *D) {
|
||||||
if (LiveVariables *L = mgr.getLiveVariables(D)) {
|
if (LiveVariables *L = mgr.getLiveVariables(D)) {
|
||||||
C.DisplayFunction(D);
|
|
||||||
BugReporter BR(mgr);
|
BugReporter BR(mgr);
|
||||||
CheckDeadStores(*mgr.getCFG(D), *L, mgr.getParentMap(D), BR);
|
CheckDeadStores(*mgr.getCFG(D), *L, mgr.getParentMap(D), BR);
|
||||||
}
|
}
|
||||||
|
@ -320,7 +325,6 @@ static void ActionWarnDeadStores(AnalysisConsumer &C, AnalysisManager& mgr,
|
||||||
static void ActionWarnUninitVals(AnalysisConsumer &C, AnalysisManager& mgr,
|
static void ActionWarnUninitVals(AnalysisConsumer &C, AnalysisManager& mgr,
|
||||||
Decl *D) {
|
Decl *D) {
|
||||||
if (CFG* c = mgr.getCFG(D)) {
|
if (CFG* c = mgr.getCFG(D)) {
|
||||||
C.DisplayFunction(D);
|
|
||||||
CheckUninitializedValues(*c, mgr.getASTContext(), mgr.getDiagnostic());
|
CheckUninitializedValues(*c, mgr.getASTContext(), mgr.getDiagnostic());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -332,15 +336,11 @@ static void ActionGRExprEngine(AnalysisConsumer &C, AnalysisManager& mgr,
|
||||||
|
|
||||||
llvm::OwningPtr<GRTransferFuncs> TF(tf);
|
llvm::OwningPtr<GRTransferFuncs> TF(tf);
|
||||||
|
|
||||||
// Display progress.
|
|
||||||
C.DisplayFunction(D);
|
|
||||||
|
|
||||||
// Construct the analysis engine. We first query for the LiveVariables
|
// Construct the analysis engine. We first query for the LiveVariables
|
||||||
// information to see if the CFG is valid.
|
// information to see if the CFG is valid.
|
||||||
// FIXME: Inter-procedural analysis will need to handle invalid CFGs.
|
// FIXME: Inter-procedural analysis will need to handle invalid CFGs.
|
||||||
if (!mgr.getLiveVariables(D))
|
if (!mgr.getLiveVariables(D))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
GRExprEngine Eng(mgr, TF.take());
|
GRExprEngine Eng(mgr, TF.take());
|
||||||
|
|
||||||
if (C.Opts.EnableExperimentalInternalChecks)
|
if (C.Opts.EnableExperimentalInternalChecks)
|
||||||
|
@ -407,28 +407,24 @@ static void ActionObjCMemChecker(AnalysisConsumer &C, AnalysisManager& mgr,
|
||||||
static void ActionDisplayLiveVariables(AnalysisConsumer &C,
|
static void ActionDisplayLiveVariables(AnalysisConsumer &C,
|
||||||
AnalysisManager& mgr, Decl *D) {
|
AnalysisManager& mgr, Decl *D) {
|
||||||
if (LiveVariables* L = mgr.getLiveVariables(D)) {
|
if (LiveVariables* L = mgr.getLiveVariables(D)) {
|
||||||
C.DisplayFunction(D);
|
|
||||||
L->dumpBlockLiveness(mgr.getSourceManager());
|
L->dumpBlockLiveness(mgr.getSourceManager());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ActionCFGDump(AnalysisConsumer &C, AnalysisManager& mgr, Decl *D) {
|
static void ActionCFGDump(AnalysisConsumer &C, AnalysisManager& mgr, Decl *D) {
|
||||||
if (CFG *cfg = mgr.getCFG(D)) {
|
if (CFG *cfg = mgr.getCFG(D)) {
|
||||||
C.DisplayFunction(D);
|
|
||||||
cfg->dump(mgr.getLangOptions());
|
cfg->dump(mgr.getLangOptions());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ActionCFGView(AnalysisConsumer &C, AnalysisManager& mgr, Decl *D) {
|
static void ActionCFGView(AnalysisConsumer &C, AnalysisManager& mgr, Decl *D) {
|
||||||
if (CFG *cfg = mgr.getCFG(D)) {
|
if (CFG *cfg = mgr.getCFG(D)) {
|
||||||
C.DisplayFunction(D);
|
|
||||||
cfg->viewCFG(mgr.getLangOptions());
|
cfg->viewCFG(mgr.getLangOptions());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ActionSecuritySyntacticChecks(AnalysisConsumer &C,
|
static void ActionSecuritySyntacticChecks(AnalysisConsumer &C,
|
||||||
AnalysisManager &mgr, Decl *D) {
|
AnalysisManager &mgr, Decl *D) {
|
||||||
C.DisplayFunction(D);
|
|
||||||
BugReporter BR(mgr);
|
BugReporter BR(mgr);
|
||||||
CheckSecuritySyntaxOnly(D, BR);
|
CheckSecuritySyntaxOnly(D, BR);
|
||||||
}
|
}
|
||||||
|
@ -444,86 +440,28 @@ static void ActionWarnObjCDealloc(AnalysisConsumer &C, AnalysisManager& mgr,
|
||||||
Decl *D) {
|
Decl *D) {
|
||||||
if (mgr.getLangOptions().getGCMode() == LangOptions::GCOnly)
|
if (mgr.getLangOptions().getGCMode() == LangOptions::GCOnly)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
C.DisplayFunction(D);
|
|
||||||
BugReporter BR(mgr);
|
BugReporter BR(mgr);
|
||||||
CheckObjCDealloc(cast<ObjCImplementationDecl>(D), mgr.getLangOptions(), BR);
|
CheckObjCDealloc(cast<ObjCImplementationDecl>(D), mgr.getLangOptions(), BR);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ActionWarnObjCUnusedIvars(AnalysisConsumer &C, AnalysisManager& mgr,
|
static void ActionWarnObjCUnusedIvars(AnalysisConsumer &C, AnalysisManager& mgr,
|
||||||
Decl *D) {
|
Decl *D) {
|
||||||
C.DisplayFunction(D);
|
|
||||||
BugReporter BR(mgr);
|
BugReporter BR(mgr);
|
||||||
CheckObjCUnusedIvar(cast<ObjCImplementationDecl>(D), BR);
|
CheckObjCUnusedIvar(cast<ObjCImplementationDecl>(D), BR);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ActionWarnObjCMethSigs(AnalysisConsumer &C, AnalysisManager& mgr,
|
static void ActionWarnObjCMethSigs(AnalysisConsumer &C, AnalysisManager& mgr,
|
||||||
Decl *D) {
|
Decl *D) {
|
||||||
C.DisplayFunction(D);
|
|
||||||
BugReporter BR(mgr);
|
BugReporter BR(mgr);
|
||||||
CheckObjCInstMethSignature(cast<ObjCImplementationDecl>(D), BR);
|
CheckObjCInstMethSignature(cast<ObjCImplementationDecl>(D), BR);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ActionWarnSizeofPointer(AnalysisConsumer &C, AnalysisManager &mgr,
|
static void ActionWarnSizeofPointer(AnalysisConsumer &C, AnalysisManager &mgr,
|
||||||
Decl *D) {
|
Decl *D) {
|
||||||
C.DisplayFunction(D);
|
|
||||||
BugReporter BR(mgr);
|
BugReporter BR(mgr);
|
||||||
CheckSizeofPointer(D, BR);
|
CheckSizeofPointer(D, BR);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ActionInlineCall(AnalysisConsumer &C, AnalysisManager &mgr,
|
|
||||||
TranslationUnitDecl &TU) {
|
|
||||||
|
|
||||||
// Find the entry function definition (if any).
|
|
||||||
FunctionDecl *D = 0;
|
|
||||||
|
|
||||||
// Must specify an entry function.
|
|
||||||
if (!C.Opts.AnalyzeSpecificFunction.empty()) {
|
|
||||||
for (DeclContext::decl_iterator I=TU.decls_begin(), E=TU.decls_end();
|
|
||||||
I != E; ++I) {
|
|
||||||
if (FunctionDecl *fd = dyn_cast<FunctionDecl>(*I))
|
|
||||||
if (fd->isThisDeclarationADefinition() &&
|
|
||||||
fd->getNameAsString() == C.Opts.AnalyzeSpecificFunction) {
|
|
||||||
D = fd;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!D)
|
|
||||||
return;
|
|
||||||
|
|
||||||
|
|
||||||
// FIXME: This is largely copy of ActionGRExprEngine. Needs cleanup.
|
|
||||||
// Display progress.
|
|
||||||
C.DisplayFunction(D);
|
|
||||||
|
|
||||||
// FIXME: Make a fake transfer function. The GRTransferFunc interface
|
|
||||||
// eventually will be removed.
|
|
||||||
GRExprEngine Eng(mgr, new GRTransferFuncs());
|
|
||||||
|
|
||||||
if (C.Opts.EnableExperimentalInternalChecks)
|
|
||||||
RegisterExperimentalInternalChecks(Eng);
|
|
||||||
|
|
||||||
RegisterAppleChecks(Eng, *D);
|
|
||||||
|
|
||||||
if (C.Opts.EnableExperimentalChecks)
|
|
||||||
RegisterExperimentalChecks(Eng);
|
|
||||||
|
|
||||||
// Register call inliner as the last checker.
|
|
||||||
RegisterCallInliner(Eng);
|
|
||||||
|
|
||||||
// Execute the worklist algorithm.
|
|
||||||
Eng.ExecuteWorkList(mgr.getStackFrame(D));
|
|
||||||
|
|
||||||
// Visualize the exploded graph.
|
|
||||||
if (mgr.shouldVisualizeGraphviz())
|
|
||||||
Eng.ViewGraph(mgr.shouldTrimGraph());
|
|
||||||
|
|
||||||
// Display warnings.
|
|
||||||
Eng.getBugReporter().FlushReports();
|
|
||||||
}
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// AnalysisConsumer creation.
|
// AnalysisConsumer creation.
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// RUN: %clang_cc1 -analyze -inline-call -analyzer-store region -analyze-function f2 -verify %s
|
// RUN: false
|
||||||
|
// XFAIL: *
|
||||||
int f1() {
|
int f1() {
|
||||||
int y = 1;
|
int y = 1;
|
||||||
y++;
|
y++;
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
// RUN: %clang_cc1 -analyze -inline-call -analyzer-store region -analyze-function f2 -verify %s
|
// RUN: false
|
||||||
|
// XFAIL: *
|
||||||
|
|
||||||
// Test parameter 'a' is registered to LiveVariables analysis data although it
|
// Test parameter 'a' is registered to LiveVariables analysis data although it
|
||||||
// is not referenced in the function body.
|
// is not referenced in the function body.
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// RUN: %clang_cc1 -analyze -inline-call -analyzer-store region -analyze-function f2 -verify %s
|
// RUN: false
|
||||||
|
// XFAIL: *
|
||||||
|
|
||||||
// Test when entering f1(), we set the right AnalysisContext to Environment.
|
// Test when entering f1(), we set the right AnalysisContext to Environment.
|
||||||
// Otherwise, block-level expr '1 && a' would not be block-level.
|
// Otherwise, block-level expr '1 && a' would not be block-level.
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// RUN: %clang_cc1 -analyze -inline-call -analyzer-store region -analyze-function f -verify %s
|
// RUN: false
|
||||||
|
// XFAIL: *
|
||||||
int g(int a) {
|
int g(int a) {
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,11 +72,11 @@ int handleVoidInComma() {
|
||||||
int marker(void) { // control reaches end of non-void function
|
int marker(void) { // control reaches end of non-void function
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CHECK-darwin8: 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 '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 'longlongM' is nil and returns a value of type '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 'doubleM' is nil and returns a value of type '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 'longlongM' is nil and returns a value of type 'long long' that will be garbage
|
||||||
// CHECK-darwin8: control reaches end of non-void function
|
|
||||||
// CHECK-darwin8: 5 warnings generated
|
// CHECK-darwin8: 5 warnings generated
|
||||||
// CHECK-darwin9: control reaches end of non-void function
|
// CHECK-darwin9: control reaches end of non-void function
|
||||||
// CHECK-darwin9: 1 warning generated
|
// CHECK-darwin9: 1 warning generated
|
||||||
|
|
Загрузка…
Ссылка в новой задаче