<div class="gmail_quote">On Mon, Jan 10, 2011 at 1:23 AM, Zhongxing Xu <span dir="ltr"><<a href="mailto:xuzhongxing@gmail.com">xuzhongxing@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
Author: zhongxingxu<br>
Date: Mon Jan 10 03:23:01 2011<br>
New Revision: 123166<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=123166&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=123166&view=rev</a><br>
Log:<br>
Revert r123160. There are linking dependency problems.<br></blockquote><div><br></div><div>Please also revert dgregor's subsequent CMake fix, and reinstate with this patch when its working? We need to keep both build systems in sync.</div>
<div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<br>
Added:<br>
cfe/trunk/lib/StaticAnalyzer/Checkers/AnalysisConsumer.cpp<br>
- copied, changed from r123160, cfe/trunk/lib/StaticAnalyzer/AnalysisConsumer.cpp<br>
cfe/trunk/lib/StaticAnalyzer/Checkers/ExprEngine.cpp<br>
- copied, changed from r123160, cfe/trunk/lib/StaticAnalyzer/ExprEngine.cpp<br>
Removed:<br>
cfe/trunk/lib/StaticAnalyzer/AnalysisConsumer.cpp<br>
cfe/trunk/lib/StaticAnalyzer/ExprEngine.cpp<br>
Modified:<br>
cfe/trunk/tools/driver/Makefile<br>
<br>
Removed: cfe/trunk/lib/StaticAnalyzer/AnalysisConsumer.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/AnalysisConsumer.cpp?rev=123165&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/AnalysisConsumer.cpp?rev=123165&view=auto</a><br>
==============================================================================<br>
--- cfe/trunk/lib/StaticAnalyzer/AnalysisConsumer.cpp (original)<br>
+++ cfe/trunk/lib/StaticAnalyzer/AnalysisConsumer.cpp (removed)<br>
@@ -1,610 +0,0 @@<br>
-//===--- AnalysisConsumer.cpp - ASTConsumer for running Analyses ----------===//<br>
-//<br>
-// The LLVM Compiler Infrastructure<br>
-//<br>
-// This file is distributed under the University of Illinois Open Source<br>
-// License. See LICENSE.TXT for details.<br>
-//<br>
-//===----------------------------------------------------------------------===//<br>
-//<br>
-// "Meta" ASTConsumer for running different source analyses.<br>
-//<br>
-//===----------------------------------------------------------------------===//<br>
-<br>
-#include "clang/StaticAnalyzer/AnalysisConsumer.h"<br>
-#include "clang/AST/ASTConsumer.h"<br>
-#include "clang/AST/Decl.h"<br>
-#include "clang/AST/DeclCXX.h"<br>
-#include "clang/AST/DeclObjC.h"<br>
-#include "clang/AST/ParentMap.h"<br>
-#include "clang/Analysis/Analyses/LiveVariables.h"<br>
-#include "clang/Analysis/Analyses/UninitializedValues.h"<br>
-#include "clang/Analysis/CFG.h"<br>
-#include "clang/StaticAnalyzer/Checkers/LocalCheckers.h"<br>
-#include "clang/StaticAnalyzer/ManagerRegistry.h"<br>
-#include "clang/StaticAnalyzer/BugReporter/PathDiagnostic.h"<br>
-#include "clang/StaticAnalyzer/PathSensitive/AnalysisManager.h"<br>
-#include "clang/StaticAnalyzer/BugReporter/BugReporter.h"<br>
-#include "clang/StaticAnalyzer/PathSensitive/ExprEngine.h"<br>
-#include "clang/StaticAnalyzer/PathSensitive/TransferFuncs.h"<br>
-#include "clang/StaticAnalyzer/PathDiagnosticClients.h"<br>
-<br>
-// FIXME: Restructure checker registration.<br>
-#include "Checkers/ExprEngineExperimentalChecks.h"<br>
-#include "Checkers/ExprEngineInternalChecks.h"<br>
-<br>
-#include "clang/Basic/FileManager.h"<br>
-#include "clang/Basic/SourceManager.h"<br>
-#include "clang/Frontend/AnalyzerOptions.h"<br>
-#include "clang/Lex/Preprocessor.h"<br>
-#include "llvm/Support/raw_ostream.h"<br>
-#include "llvm/Support/Path.h"<br>
-#include "llvm/Support/Program.h"<br>
-#include "llvm/ADT/OwningPtr.h"<br>
-<br>
-using namespace clang;<br>
-using namespace ento;<br>
-<br>
-static ExplodedNode::Auditor* CreateUbiViz();<br>
-<br>
-//===----------------------------------------------------------------------===//<br>
-// Special PathDiagnosticClients.<br>
-//===----------------------------------------------------------------------===//<br>
-<br>
-static PathDiagnosticClient*<br>
-createPlistHTMLDiagnosticClient(const std::string& prefix,<br>
- const Preprocessor &PP) {<br>
- PathDiagnosticClient *PD =<br>
- createHTMLDiagnosticClient(llvm::sys::path::parent_path(prefix), PP);<br>
- return createPlistDiagnosticClient(prefix, PP, PD);<br>
-}<br>
-<br>
-//===----------------------------------------------------------------------===//<br>
-// AnalysisConsumer declaration.<br>
-//===----------------------------------------------------------------------===//<br>
-<br>
-namespace {<br>
-<br>
-class AnalysisConsumer : public ASTConsumer {<br>
-public:<br>
- typedef void (*CodeAction)(AnalysisConsumer &C, AnalysisManager &M, Decl *D);<br>
- typedef void (*TUAction)(AnalysisConsumer &C, AnalysisManager &M,<br>
- TranslationUnitDecl &TU);<br>
-<br>
-private:<br>
- typedef std::vector<CodeAction> Actions;<br>
- typedef std::vector<TUAction> TUActions;<br>
-<br>
- Actions FunctionActions;<br>
- Actions ObjCMethodActions;<br>
- Actions ObjCImplementationActions;<br>
- Actions CXXMethodActions;<br>
- TUActions TranslationUnitActions; // Remove this.<br>
-<br>
-public:<br>
- ASTContext* Ctx;<br>
- const Preprocessor &PP;<br>
- const std::string OutDir;<br>
- AnalyzerOptions Opts;<br>
-<br>
- // PD is owned by AnalysisManager.<br>
- PathDiagnosticClient *PD;<br>
-<br>
- StoreManagerCreator CreateStoreMgr;<br>
- ConstraintManagerCreator CreateConstraintMgr;<br>
-<br>
- llvm::OwningPtr<AnalysisManager> Mgr;<br>
-<br>
- AnalysisConsumer(const Preprocessor& pp,<br>
- const std::string& outdir,<br>
- const AnalyzerOptions& opts)<br>
- : Ctx(0), PP(pp), OutDir(outdir),<br>
- Opts(opts), PD(0) {<br>
- DigestAnalyzerOptions();<br>
- }<br>
-<br>
- void DigestAnalyzerOptions() {<br>
- // Create the PathDiagnosticClient.<br>
- if (!OutDir.empty()) {<br>
- switch (Opts.AnalysisDiagOpt) {<br>
- default:<br>
-#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN, AUTOCREATE) \<br>
- case PD_##NAME: PD = CREATEFN(OutDir, PP); break;<br>
-#include "clang/Frontend/Analyses.def"<br>
- }<br>
- } else if (Opts.AnalysisDiagOpt == PD_TEXT) {<br>
- // Create the text client even without a specified output file since<br>
- // it just uses diagnostic notes.<br>
- PD = createTextPathDiagnosticClient("", PP);<br>
- }<br>
-<br>
- // Create the analyzer component creators.<br>
- if (ManagerRegistry::StoreMgrCreator != 0) {<br>
- CreateStoreMgr = ManagerRegistry::StoreMgrCreator;<br>
- }<br>
- else {<br>
- switch (Opts.AnalysisStoreOpt) {<br>
- default:<br>
- assert(0 && "Unknown store manager.");<br>
-#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATEFN) \<br>
- case NAME##Model: CreateStoreMgr = CREATEFN; break;<br>
-#include "clang/Frontend/Analyses.def"<br>
- }<br>
- }<br>
-<br>
- if (ManagerRegistry::ConstraintMgrCreator != 0)<br>
- CreateConstraintMgr = ManagerRegistry::ConstraintMgrCreator;<br>
- else {<br>
- switch (Opts.AnalysisConstraintsOpt) {<br>
- default:<br>
- assert(0 && "Unknown store manager.");<br>
-#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATEFN) \<br>
- case NAME##Model: CreateConstraintMgr = CREATEFN; break;<br>
-#include "clang/Frontend/Analyses.def"<br>
- }<br>
- }<br>
- }<br>
-<br>
- void DisplayFunction(const Decl *D) {<br>
- if (!Opts.AnalyzerDisplayProgress)<br>
- return;<br>
-<br>
- SourceManager &SM = Mgr->getASTContext().getSourceManager();<br>
- PresumedLoc Loc = SM.getPresumedLoc(D->getLocation());<br>
- if (Loc.isValid()) {<br>
- llvm::errs() << "ANALYZE: " << Loc.getFilename();<br>
-<br>
- if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) {<br>
- const NamedDecl *ND = cast<NamedDecl>(D);<br>
- llvm::errs() << ' ' << ND << '\n';<br>
- }<br>
- else if (isa<BlockDecl>(D)) {<br>
- llvm::errs() << ' ' << "block(line:" << Loc.getLine() << ",col:"<br>
- << Loc.getColumn() << '\n';<br>
- }<br>
- else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {<br>
- Selector S = MD->getSelector();<br>
- llvm::errs() << ' ' << S.getAsString();<br>
- }<br>
- }<br>
- }<br>
-<br>
- void addCodeAction(CodeAction action) {<br>
- FunctionActions.push_back(action);<br>
- ObjCMethodActions.push_back(action);<br>
- CXXMethodActions.push_back(action);<br>
- }<br>
-<br>
- void addTranslationUnitAction(TUAction action) {<br>
- TranslationUnitActions.push_back(action);<br>
- }<br>
-<br>
- void addObjCImplementationAction(CodeAction action) {<br>
- ObjCImplementationActions.push_back(action);<br>
- }<br>
-<br>
- virtual void Initialize(ASTContext &Context) {<br>
- Ctx = &Context;<br>
- Mgr.reset(new AnalysisManager(*Ctx, PP.getDiagnostics(),<br>
- PP.getLangOptions(), PD,<br>
- CreateStoreMgr, CreateConstraintMgr,<br>
- /* Indexer */ 0,<br>
- Opts.MaxNodes, Opts.MaxLoop,<br>
- Opts.VisualizeEGDot, Opts.VisualizeEGUbi,<br>
- Opts.PurgeDead, Opts.EagerlyAssume,<br>
- Opts.TrimGraph, Opts.InlineCall,<br>
- Opts.UnoptimizedCFG, Opts.CFGAddImplicitDtors,<br>
- Opts.CFGAddInitializers));<br>
- }<br>
-<br>
- virtual void HandleTranslationUnit(ASTContext &C);<br>
- void HandleCode(Decl *D, Actions& actions);<br>
-};<br>
-} // end anonymous namespace<br>
-<br>
-//===----------------------------------------------------------------------===//<br>
-// AnalysisConsumer implementation.<br>
-//===----------------------------------------------------------------------===//<br>
-<br>
-void AnalysisConsumer::HandleTranslationUnit(ASTContext &C) {<br>
-<br>
- TranslationUnitDecl *TU = C.getTranslationUnitDecl();<br>
-<br>
- for (DeclContext::decl_iterator I = TU->decls_begin(), E = TU->decls_end();<br>
- I != E; ++I) {<br>
- Decl *D = *I;<br>
-<br>
- switch (D->getKind()) {<br>
- case Decl::CXXConstructor:<br>
- case Decl::CXXDestructor:<br>
- case Decl::CXXConversion:<br>
- case Decl::CXXMethod:<br>
- case Decl::Function: {<br>
- FunctionDecl* FD = cast<FunctionDecl>(D);<br>
- // We skip function template definitions, as their semantics is<br>
- // only determined when they are instantiated.<br>
- if (FD->isThisDeclarationADefinition() &&<br>
- !FD->isDependentContext()) {<br>
- if (!Opts.AnalyzeSpecificFunction.empty() &&<br>
- FD->getDeclName().getAsString() != Opts.AnalyzeSpecificFunction)<br>
- break;<br>
- DisplayFunction(FD);<br>
- HandleCode(FD, FunctionActions);<br>
- }<br>
- break;<br>
- }<br>
-<br>
- case Decl::ObjCImplementation: {<br>
- ObjCImplementationDecl* ID = cast<ObjCImplementationDecl>(*I);<br>
- HandleCode(ID, ObjCImplementationActions);<br>
-<br>
- for (ObjCImplementationDecl::method_iterator MI = ID->meth_begin(),<br>
- ME = ID->meth_end(); MI != ME; ++MI) {<br>
- if ((*MI)->isThisDeclarationADefinition()) {<br>
- if (!Opts.AnalyzeSpecificFunction.empty() &&<br>
- Opts.AnalyzeSpecificFunction != (*MI)->getSelector().getAsString())<br>
- break;<br>
- DisplayFunction(*MI);<br>
- HandleCode(*MI, ObjCMethodActions);<br>
- }<br>
- }<br>
- break;<br>
- }<br>
-<br>
- default:<br>
- break;<br>
- }<br>
- }<br>
-<br>
- for (TUActions::iterator I = TranslationUnitActions.begin(),<br>
- E = TranslationUnitActions.end(); I != E; ++I) {<br>
- (*I)(*this, *Mgr, *TU);<br>
- }<br>
-<br>
- // Explicitly destroy the PathDiagnosticClient. This will flush its output.<br>
- // FIXME: This should be replaced with something that doesn't rely on<br>
- // side-effects in PathDiagnosticClient's destructor. This is required when<br>
- // used with option -disable-free.<br>
- Mgr.reset(NULL);<br>
-}<br>
-<br>
-static void FindBlocks(DeclContext *D, llvm::SmallVectorImpl<Decl*> &WL) {<br>
- if (BlockDecl *BD = dyn_cast<BlockDecl>(D))<br>
- WL.push_back(BD);<br>
-<br>
- for (DeclContext::decl_iterator I = D->decls_begin(), E = D->decls_end();<br>
- I!=E; ++I)<br>
- if (DeclContext *DC = dyn_cast<DeclContext>(*I))<br>
- FindBlocks(DC, WL);<br>
-}<br>
-<br>
-void AnalysisConsumer::HandleCode(Decl *D, Actions& actions) {<br>
-<br>
- // Don't run the actions if an error has occured with parsing the file.<br>
- Diagnostic &Diags = PP.getDiagnostics();<br>
- if (Diags.hasErrorOccurred() || Diags.hasFatalErrorOccurred())<br>
- return;<br>
-<br>
- // Don't run the actions on declarations in header files unless<br>
- // otherwise specified.<br>
- SourceManager &SM = Ctx->getSourceManager();<br>
- SourceLocation SL = SM.getInstantiationLoc(D->getLocation());<br>
- if (!Opts.AnalyzeAll && !SM.isFromMainFile(SL))<br>
- return;<br>
-<br>
- // Clear the AnalysisManager of old AnalysisContexts.<br>
- Mgr->ClearContexts();<br>
-<br>
- // Dispatch on the actions.<br>
- llvm::SmallVector<Decl*, 10> WL;<br>
- WL.push_back(D);<br>
-<br>
- if (D->hasBody() && Opts.AnalyzeNestedBlocks)<br>
- FindBlocks(cast<DeclContext>(D), WL);<br>
-<br>
- for (Actions::iterator I = actions.begin(), E = actions.end(); I != E; ++I)<br>
- for (llvm::SmallVectorImpl<Decl*>::iterator WI=WL.begin(), WE=WL.end();<br>
- WI != WE; ++WI)<br>
- (*I)(*this, *Mgr, *WI);<br>
-}<br>
-<br>
-//===----------------------------------------------------------------------===//<br>
-// Analyses<br>
-//===----------------------------------------------------------------------===//<br>
-<br>
-static void ActionWarnDeadStores(AnalysisConsumer &C, AnalysisManager& mgr,<br>
- Decl *D) {<br>
- if (LiveVariables *L = mgr.getLiveVariables(D)) {<br>
- BugReporter BR(mgr);<br>
- CheckDeadStores(*mgr.getCFG(D), *L, mgr.getParentMap(D), BR);<br>
- }<br>
-}<br>
-<br>
-static void ActionWarnUninitVals(AnalysisConsumer &C, AnalysisManager& mgr,<br>
- Decl *D) {<br>
- if (CFG* c = mgr.getCFG(D)) {<br>
- CheckUninitializedValues(*c, mgr.getASTContext(), mgr.getDiagnostic());<br>
- }<br>
-}<br>
-<br>
-<br>
-static void ActionExprEngine(AnalysisConsumer &C, AnalysisManager& mgr,<br>
- Decl *D,<br>
- TransferFuncs* tf) {<br>
-<br>
- llvm::OwningPtr<TransferFuncs> TF(tf);<br>
-<br>
- // Construct the analysis engine. We first query for the LiveVariables<br>
- // information to see if the CFG is valid.<br>
- // FIXME: Inter-procedural analysis will need to handle invalid CFGs.<br>
- if (!mgr.getLiveVariables(D))<br>
- return;<br>
- ExprEngine Eng(mgr, TF.take());<br>
-<br>
- if (C.Opts.EnableExperimentalInternalChecks)<br>
- RegisterExperimentalInternalChecks(Eng);<br>
-<br>
- RegisterAppleChecks(Eng, *D);<br>
-<br>
- if (C.Opts.EnableExperimentalChecks)<br>
- RegisterExperimentalChecks(Eng);<br>
-<br>
- // Enable idempotent operation checking if it was explicitly turned on, or if<br>
- // we are running experimental checks (i.e. everything)<br>
- if (C.Opts.IdempotentOps || C.Opts.EnableExperimentalChecks<br>
- || C.Opts.EnableExperimentalInternalChecks)<br>
- RegisterIdempotentOperationChecker(Eng);<br>
-<br>
- if (C.Opts.BufferOverflows)<br>
- RegisterArrayBoundCheckerV2(Eng);<br>
-<br>
- // Enable AnalyzerStatsChecker if it was given as an argument<br>
- if (C.Opts.AnalyzerStats)<br>
- RegisterAnalyzerStatsChecker(Eng);<br>
-<br>
- // Set the graph auditor.<br>
- llvm::OwningPtr<ExplodedNode::Auditor> Auditor;<br>
- if (mgr.shouldVisualizeUbigraph()) {<br>
- Auditor.reset(CreateUbiViz());<br>
- ExplodedNode::SetAuditor(Auditor.get());<br>
- }<br>
-<br>
- // Execute the worklist algorithm.<br>
- Eng.ExecuteWorkList(mgr.getStackFrame(D, 0), mgr.getMaxNodes());<br>
-<br>
- // Release the auditor (if any) so that it doesn't monitor the graph<br>
- // created BugReporter.<br>
- ExplodedNode::SetAuditor(0);<br>
-<br>
- // Visualize the exploded graph.<br>
- if (mgr.shouldVisualizeGraphviz())<br>
- Eng.ViewGraph(mgr.shouldTrimGraph());<br>
-<br>
- // Display warnings.<br>
- Eng.getBugReporter().FlushReports();<br>
-}<br>
-<br>
-static void ActionObjCMemCheckerAux(AnalysisConsumer &C, AnalysisManager& mgr,<br>
- Decl *D, bool GCEnabled) {<br>
-<br>
- TransferFuncs* TF = MakeCFRefCountTF(mgr.getASTContext(),<br>
- GCEnabled,<br>
- mgr.getLangOptions());<br>
-<br>
- ActionExprEngine(C, mgr, D, TF);<br>
-}<br>
-<br>
-static void ActionObjCMemChecker(AnalysisConsumer &C, AnalysisManager& mgr,<br>
- Decl *D) {<br>
-<br>
- switch (mgr.getLangOptions().getGCMode()) {<br>
- default:<br>
- assert (false && "Invalid GC mode.");<br>
- case LangOptions::NonGC:<br>
- ActionObjCMemCheckerAux(C, mgr, D, false);<br>
- break;<br>
-<br>
- case LangOptions::GCOnly:<br>
- ActionObjCMemCheckerAux(C, mgr, D, true);<br>
- break;<br>
-<br>
- case LangOptions::HybridGC:<br>
- ActionObjCMemCheckerAux(C, mgr, D, false);<br>
- ActionObjCMemCheckerAux(C, mgr, D, true);<br>
- break;<br>
- }<br>
-}<br>
-<br>
-static void ActionDisplayLiveVariables(AnalysisConsumer &C,<br>
- AnalysisManager& mgr, Decl *D) {<br>
- if (LiveVariables* L = mgr.getLiveVariables(D)) {<br>
- L->dumpBlockLiveness(mgr.getSourceManager());<br>
- }<br>
-}<br>
-<br>
-static void ActionCFGDump(AnalysisConsumer &C, AnalysisManager& mgr, Decl *D) {<br>
- if (CFG *cfg = mgr.getCFG(D)) {<br>
- cfg->dump(mgr.getLangOptions());<br>
- }<br>
-}<br>
-<br>
-static void ActionCFGView(AnalysisConsumer &C, AnalysisManager& mgr, Decl *D) {<br>
- if (CFG *cfg = mgr.getCFG(D)) {<br>
- cfg->viewCFG(mgr.getLangOptions());<br>
- }<br>
-}<br>
-<br>
-static void ActionSecuritySyntacticChecks(AnalysisConsumer &C,<br>
- AnalysisManager &mgr, Decl *D) {<br>
- BugReporter BR(mgr);<br>
- CheckSecuritySyntaxOnly(D, BR);<br>
-}<br>
-<br>
-static void ActionLLVMConventionChecker(AnalysisConsumer &C,<br>
- AnalysisManager &mgr,<br>
- TranslationUnitDecl &TU) {<br>
- BugReporter BR(mgr);<br>
- CheckLLVMConventions(TU, BR);<br>
-}<br>
-<br>
-static void ActionWarnObjCDealloc(AnalysisConsumer &C, AnalysisManager& mgr,<br>
- Decl *D) {<br>
- if (mgr.getLangOptions().getGCMode() == LangOptions::GCOnly)<br>
- return;<br>
- BugReporter BR(mgr);<br>
- CheckObjCDealloc(cast<ObjCImplementationDecl>(D), mgr.getLangOptions(), BR);<br>
-}<br>
-<br>
-static void ActionWarnObjCUnusedIvars(AnalysisConsumer &C, AnalysisManager& mgr,<br>
- Decl *D) {<br>
- BugReporter BR(mgr);<br>
- CheckObjCUnusedIvar(cast<ObjCImplementationDecl>(D), BR);<br>
-}<br>
-<br>
-static void ActionWarnObjCMethSigs(AnalysisConsumer &C, AnalysisManager& mgr,<br>
- Decl *D) {<br>
- BugReporter BR(mgr);<br>
- CheckObjCInstMethSignature(cast<ObjCImplementationDecl>(D), BR);<br>
-}<br>
-<br>
-static void ActionWarnSizeofPointer(AnalysisConsumer &C, AnalysisManager &mgr,<br>
- Decl *D) {<br>
- BugReporter BR(mgr);<br>
- CheckSizeofPointer(D, BR);<br>
-}<br>
-<br>
-//===----------------------------------------------------------------------===//<br>
-// AnalysisConsumer creation.<br>
-//===----------------------------------------------------------------------===//<br>
-<br>
-ASTConsumer* ento::CreateAnalysisConsumer(const Preprocessor& pp,<br>
- const std::string& OutDir,<br>
- const AnalyzerOptions& Opts) {<br>
- llvm::OwningPtr<AnalysisConsumer> C(new AnalysisConsumer(pp, OutDir, Opts));<br>
-<br>
- for (unsigned i = 0; i < Opts.AnalysisList.size(); ++i)<br>
- switch (Opts.AnalysisList[i]) {<br>
-#define ANALYSIS(NAME, CMD, DESC, SCOPE)\<br>
- case NAME:\<br>
- C->add ## SCOPE ## Action(&Action ## NAME);\<br>
- break;<br>
-#include "clang/Frontend/Analyses.def"<br>
- default: break;<br>
- }<br>
-<br>
- // Last, disable the effects of '-Werror' when using the AnalysisConsumer.<br>
- pp.getDiagnostics().setWarningsAsErrors(false);<br>
-<br>
- return C.take();<br>
-}<br>
-<br>
-//===----------------------------------------------------------------------===//<br>
-// Ubigraph Visualization. FIXME: Move to separate file.<br>
-//===----------------------------------------------------------------------===//<br>
-<br>
-namespace {<br>
-<br>
-class UbigraphViz : public ExplodedNode::Auditor {<br>
- llvm::OwningPtr<llvm::raw_ostream> Out;<br>
- llvm::sys::Path Dir, Filename;<br>
- unsigned Cntr;<br>
-<br>
- typedef llvm::DenseMap<void*,unsigned> VMap;<br>
- VMap M;<br>
-<br>
-public:<br>
- UbigraphViz(llvm::raw_ostream* out, llvm::sys::Path& dir,<br>
- llvm::sys::Path& filename);<br>
-<br>
- ~UbigraphViz();<br>
-<br>
- virtual void AddEdge(ExplodedNode* Src, ExplodedNode* Dst);<br>
-};<br>
-<br>
-} // end anonymous namespace<br>
-<br>
-static ExplodedNode::Auditor* CreateUbiViz() {<br>
- std::string ErrMsg;<br>
-<br>
- llvm::sys::Path Dir = llvm::sys::Path::GetTemporaryDirectory(&ErrMsg);<br>
- if (!ErrMsg.empty())<br>
- return 0;<br>
-<br>
- llvm::sys::Path Filename = Dir;<br>
- Filename.appendComponent("llvm_ubi");<br>
- Filename.makeUnique(true,&ErrMsg);<br>
-<br>
- if (!ErrMsg.empty())<br>
- return 0;<br>
-<br>
- llvm::errs() << "Writing '" << Filename.str() << "'.\n";<br>
-<br>
- llvm::OwningPtr<llvm::raw_fd_ostream> Stream;<br>
- Stream.reset(new llvm::raw_fd_ostream(Filename.c_str(), ErrMsg));<br>
-<br>
- if (!ErrMsg.empty())<br>
- return 0;<br>
-<br>
- return new UbigraphViz(Stream.take(), Dir, Filename);<br>
-}<br>
-<br>
-void UbigraphViz::AddEdge(ExplodedNode* Src, ExplodedNode* Dst) {<br>
-<br>
- assert (Src != Dst && "Self-edges are not allowed.");<br>
-<br>
- // Lookup the Src. If it is a new node, it's a root.<br>
- VMap::iterator SrcI= M.find(Src);<br>
- unsigned SrcID;<br>
-<br>
- if (SrcI == M.end()) {<br>
- M[Src] = SrcID = Cntr++;<br>
- *Out << "('vertex', " << SrcID << ", ('color','#00ff00'))\n";<br>
- }<br>
- else<br>
- SrcID = SrcI->second;<br>
-<br>
- // Lookup the Dst.<br>
- VMap::iterator DstI= M.find(Dst);<br>
- unsigned DstID;<br>
-<br>
- if (DstI == M.end()) {<br>
- M[Dst] = DstID = Cntr++;<br>
- *Out << "('vertex', " << DstID << ")\n";<br>
- }<br>
- else {<br>
- // We have hit DstID before. Change its style to reflect a cache hit.<br>
- DstID = DstI->second;<br>
- *Out << "('change_vertex_style', " << DstID << ", 1)\n";<br>
- }<br>
-<br>
- // Add the edge.<br>
- *Out << "('edge', " << SrcID << ", " << DstID<br>
- << ", ('arrow','true'), ('oriented', 'true'))\n";<br>
-}<br>
-<br>
-UbigraphViz::UbigraphViz(llvm::raw_ostream* out, llvm::sys::Path& dir,<br>
- llvm::sys::Path& filename)<br>
- : Out(out), Dir(dir), Filename(filename), Cntr(0) {<br>
-<br>
- *Out << "('vertex_style_attribute', 0, ('shape', 'icosahedron'))\n";<br>
- *Out << "('vertex_style', 1, 0, ('shape', 'sphere'), ('color', '#ffcc66'),"<br>
- " ('size', '1.5'))\n";<br>
-}<br>
-<br>
-UbigraphViz::~UbigraphViz() {<br>
- Out.reset(0);<br>
- llvm::errs() << "Running 'ubiviz' program... ";<br>
- std::string ErrMsg;<br>
- llvm::sys::Path Ubiviz = llvm::sys::Program::FindProgramByName("ubiviz");<br>
- std::vector<const char*> args;<br>
- args.push_back(Ubiviz.c_str());<br>
- args.push_back(Filename.c_str());<br>
- args.push_back(0);<br>
-<br>
- if (llvm::sys::Program::ExecuteAndWait(Ubiviz, &args[0],0,0,0,0,&ErrMsg)) {<br>
- llvm::errs() << "Error viewing graph: " << ErrMsg << "\n";<br>
- }<br>
-<br>
- // Delete the directory.<br>
- Dir.eraseFromDisk(true);<br>
-}<br>
<br>
Copied: cfe/trunk/lib/StaticAnalyzer/Checkers/AnalysisConsumer.cpp (from r123160, cfe/trunk/lib/StaticAnalyzer/AnalysisConsumer.cpp)<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/AnalysisConsumer.cpp?p2=cfe/trunk/lib/StaticAnalyzer/Checkers/AnalysisConsumer.cpp&p1=cfe/trunk/lib/StaticAnalyzer/AnalysisConsumer.cpp&r1=123160&r2=123166&rev=123166&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/AnalysisConsumer.cpp?p2=cfe/trunk/lib/StaticAnalyzer/Checkers/AnalysisConsumer.cpp&p1=cfe/trunk/lib/StaticAnalyzer/AnalysisConsumer.cpp&r1=123160&r2=123166&rev=123166&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/StaticAnalyzer/AnalysisConsumer.cpp (original)<br>
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/AnalysisConsumer.cpp Mon Jan 10 03:23:01 2011<br>
@@ -30,8 +30,8 @@<br>
#include "clang/StaticAnalyzer/PathDiagnosticClients.h"<br>
<br>
// FIXME: Restructure checker registration.<br>
-#include "Checkers/ExprEngineExperimentalChecks.h"<br>
-#include "Checkers/ExprEngineInternalChecks.h"<br>
+#include "ExprEngineExperimentalChecks.h"<br>
+#include "ExprEngineInternalChecks.h"<br>
<br>
#include "clang/Basic/FileManager.h"<br>
#include "clang/Basic/SourceManager.h"<br>
<br>
Copied: cfe/trunk/lib/StaticAnalyzer/Checkers/ExprEngine.cpp (from r123160, cfe/trunk/lib/StaticAnalyzer/ExprEngine.cpp)<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/ExprEngine.cpp?p2=cfe/trunk/lib/StaticAnalyzer/Checkers/ExprEngine.cpp&p1=cfe/trunk/lib/StaticAnalyzer/ExprEngine.cpp&r1=123160&r2=123166&rev=123166&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/ExprEngine.cpp?p2=cfe/trunk/lib/StaticAnalyzer/Checkers/ExprEngine.cpp&p1=cfe/trunk/lib/StaticAnalyzer/ExprEngine.cpp&r1=123160&r2=123166&rev=123166&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/StaticAnalyzer/ExprEngine.cpp (original)<br>
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/ExprEngine.cpp Mon Jan 10 03:23:01 2011<br>
@@ -14,7 +14,7 @@<br>
//===----------------------------------------------------------------------===//<br>
<br>
// FIXME: Restructure checker registration.<br>
-#include "Checkers/ExprEngineInternalChecks.h"<br>
+#include "ExprEngineInternalChecks.h"<br>
<br>
#include "clang/StaticAnalyzer/BugReporter/BugType.h"<br>
#include "clang/StaticAnalyzer/PathSensitive/AnalysisManager.h"<br>
<br>
Removed: cfe/trunk/lib/StaticAnalyzer/ExprEngine.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/ExprEngine.cpp?rev=123165&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/ExprEngine.cpp?rev=123165&view=auto</a><br>
==============================================================================<br>
--- cfe/trunk/lib/StaticAnalyzer/ExprEngine.cpp (original)<br>
+++ cfe/trunk/lib/StaticAnalyzer/ExprEngine.cpp (removed)<br>
@@ -1,3521 +0,0 @@<br>
-//=-- ExprEngine.cpp - Path-Sensitive Expression-Level Dataflow ---*- C++ -*-=<br>
-//<br>
-// The LLVM Compiler Infrastructure<br>
-//<br>
-// This file is distributed under the University of Illinois Open Source<br>
-// License. See LICENSE.TXT for details.<br>
-//<br>
-//===----------------------------------------------------------------------===//<br>
-//<br>
-// This file defines a meta-engine for path-sensitive dataflow analysis that<br>
-// is built on GREngine, but provides the boilerplate to execute transfer<br>
-// functions and build the ExplodedGraph at the expression level.<br>
-//<br>
-//===----------------------------------------------------------------------===//<br>
-<br>
-// FIXME: Restructure checker registration.<br>
-#include "Checkers/ExprEngineInternalChecks.h"<br>
-<br>
-#include "clang/StaticAnalyzer/BugReporter/BugType.h"<br>
-#include "clang/StaticAnalyzer/PathSensitive/AnalysisManager.h"<br>
-#include "clang/StaticAnalyzer/PathSensitive/ExprEngine.h"<br>
-#include "clang/StaticAnalyzer/PathSensitive/ExprEngineBuilders.h"<br>
-#include "clang/StaticAnalyzer/PathSensitive/Checker.h"<br>
-#include "clang/AST/CharUnits.h"<br>
-#include "clang/AST/ParentMap.h"<br>
-#include "clang/AST/StmtObjC.h"<br>
-#include "clang/AST/DeclCXX.h"<br>
-#include "clang/Basic/Builtins.h"<br>
-#include "clang/Basic/SourceManager.h"<br>
-#include "clang/Basic/SourceManager.h"<br>
-#include "clang/Basic/PrettyStackTrace.h"<br>
-#include "llvm/Support/raw_ostream.h"<br>
-#include "llvm/ADT/ImmutableList.h"<br>
-<br>
-#ifndef NDEBUG<br>
-#include "llvm/Support/GraphWriter.h"<br>
-#endif<br>
-<br>
-using namespace clang;<br>
-using namespace ento;<br>
-using llvm::dyn_cast;<br>
-using llvm::dyn_cast_or_null;<br>
-using llvm::cast;<br>
-using llvm::APSInt;<br>
-<br>
-namespace {<br>
- // Trait class for recording returned expression in the state.<br>
- struct ReturnExpr {<br>
- static int TagInt;<br>
- typedef const Stmt *data_type;<br>
- };<br>
- int ReturnExpr::TagInt;<br>
-}<br>
-<br>
-//===----------------------------------------------------------------------===//<br>
-// Utility functions.<br>
-//===----------------------------------------------------------------------===//<br>
-<br>
-static inline Selector GetNullarySelector(const char* name, ASTContext& Ctx) {<br>
- IdentifierInfo* II = &Ctx.Idents.get(name);<br>
- return Ctx.Selectors.getSelector(0, &II);<br>
-}<br>
-<br>
-//===----------------------------------------------------------------------===//<br>
-// Checker worklist routines.<br>
-//===----------------------------------------------------------------------===//<br>
-<br>
-void ExprEngine::CheckerVisit(const Stmt *S, ExplodedNodeSet &Dst,<br>
- ExplodedNodeSet &Src, CallbackKind Kind) {<br>
-<br>
- // Determine if we already have a cached 'CheckersOrdered' vector<br>
- // specifically tailored for the provided <CallbackKind, Stmt kind>. This<br>
- // can reduce the number of checkers actually called.<br>
- CheckersOrdered *CO = &Checkers;<br>
- llvm::OwningPtr<CheckersOrdered> NewCO;<br>
-<br>
- // The cache key is made up of the and the callback kind (pre- or post-visit)<br>
- // and the statement kind.<br>
- CallbackTag K = GetCallbackTag(Kind, S->getStmtClass());<br>
-<br>
- CheckersOrdered *& CO_Ref = COCache[K];<br>
-<br>
- if (!CO_Ref) {<br>
- // If we have no previously cached CheckersOrdered vector for this<br>
- // statement kind, then create one.<br>
- NewCO.reset(new CheckersOrdered);<br>
- }<br>
- else {<br>
- // Use the already cached set.<br>
- CO = CO_Ref;<br>
- }<br>
-<br>
- if (CO->empty()) {<br>
- // If there are no checkers, return early without doing any<br>
- // more work.<br>
- Dst.insert(Src);<br>
- return;<br>
- }<br>
-<br>
- ExplodedNodeSet Tmp;<br>
- ExplodedNodeSet *PrevSet = &Src;<br>
- unsigned checkersEvaluated = 0;<br>
-<br>
- for (CheckersOrdered::iterator I=CO->begin(), E=CO->end(); I!=E; ++I) {<br>
- // If all nodes are sunk, bail out early.<br>
- if (PrevSet->empty())<br>
- break;<br>
- ExplodedNodeSet *CurrSet = 0;<br>
- if (I+1 == E)<br>
- CurrSet = &Dst;<br>
- else {<br>
- CurrSet = (PrevSet == &Tmp) ? &Src : &Tmp;<br>
- CurrSet->clear();<br>
- }<br>
- void *tag = I->first;<br>
- Checker *checker = I->second;<br>
- bool respondsToCallback = true;<br>
-<br>
- for (ExplodedNodeSet::iterator NI = PrevSet->begin(), NE = PrevSet->end();<br>
- NI != NE; ++NI) {<br>
-<br>
- checker->GR_Visit(*CurrSet, *Builder, *this, S, *NI, tag,<br>
- Kind == PreVisitStmtCallback, respondsToCallback);<br>
-<br>
- }<br>
-<br>
- PrevSet = CurrSet;<br>
-<br>
- if (NewCO.get()) {<br>
- ++checkersEvaluated;<br>
- if (respondsToCallback)<br>
- NewCO->push_back(*I);<br>
- }<br>
- }<br>
-<br>
- // If we built NewCO, check if we called all the checkers. This is important<br>
- // so that we know that we accurately determined the entire set of checkers<br>
- // that responds to this callback. Note that 'checkersEvaluated' might<br>
- // not be the same as Checkers.size() if one of the Checkers generates<br>
- // a sink node.<br>
- if (NewCO.get() && checkersEvaluated == Checkers.size())<br>
- CO_Ref = NewCO.take();<br>
-<br>
- // Don't autotransition. The CheckerContext objects should do this<br>
- // automatically.<br>
-}<br>
-<br>
-void ExprEngine::CheckerEvalNilReceiver(const ObjCMessageExpr *ME,<br>
- ExplodedNodeSet &Dst,<br>
- const GRState *state,<br>
- ExplodedNode *Pred) {<br>
- bool evaluated = false;<br>
- ExplodedNodeSet DstTmp;<br>
-<br>
- for (CheckersOrdered::iterator I=Checkers.begin(),E=Checkers.end();I!=E;++I) {<br>
- void *tag = I->first;<br>
- Checker *checker = I->second;<br>
-<br>
- if (checker->GR_evalNilReceiver(DstTmp, *Builder, *this, ME, Pred, state,<br>
- tag)) {<br>
- evaluated = true;<br>
- break;<br>
- } else<br>
- // The checker didn't evaluate the expr. Restore the Dst.<br>
- DstTmp.clear();<br>
- }<br>
-<br>
- if (evaluated)<br>
- Dst.insert(DstTmp);<br>
- else<br>
- Dst.insert(Pred);<br>
-}<br>
-<br>
-// CheckerEvalCall returns true if one of the checkers processed the node.<br>
-// This may return void when all call evaluation logic goes to some checker<br>
-// in the future.<br>
-bool ExprEngine::CheckerEvalCall(const CallExpr *CE,<br>
- ExplodedNodeSet &Dst,<br>
- ExplodedNode *Pred) {<br>
- bool evaluated = false;<br>
- ExplodedNodeSet DstTmp;<br>
-<br>
- for (CheckersOrdered::iterator I=Checkers.begin(),E=Checkers.end();I!=E;++I) {<br>
- void *tag = I->first;<br>
- Checker *checker = I->second;<br>
-<br>
- if (checker->GR_evalCallExpr(DstTmp, *Builder, *this, CE, Pred, tag)) {<br>
- evaluated = true;<br>
- break;<br>
- } else<br>
- // The checker didn't evaluate the expr. Restore the DstTmp set.<br>
- DstTmp.clear();<br>
- }<br>
-<br>
- if (evaluated)<br>
- Dst.insert(DstTmp);<br>
- else<br>
- Dst.insert(Pred);<br>
-<br>
- return evaluated;<br>
-}<br>
-<br>
-// FIXME: This is largely copy-paste from CheckerVisit(). Need to<br>
-// unify.<br>
-void ExprEngine::CheckerVisitBind(const Stmt *StoreE, ExplodedNodeSet &Dst,<br>
- ExplodedNodeSet &Src, SVal location,<br>
- SVal val, bool isPrevisit) {<br>
-<br>
- if (Checkers.empty()) {<br>
- Dst.insert(Src);<br>
- return;<br>
- }<br>
-<br>
- ExplodedNodeSet Tmp;<br>
- ExplodedNodeSet *PrevSet = &Src;<br>
-<br>
- for (CheckersOrdered::iterator I=Checkers.begin(),E=Checkers.end(); I!=E; ++I)<br>
- {<br>
- ExplodedNodeSet *CurrSet = 0;<br>
- if (I+1 == E)<br>
- CurrSet = &Dst;<br>
- else {<br>
- CurrSet = (PrevSet == &Tmp) ? &Src : &Tmp;<br>
- CurrSet->clear();<br>
- }<br>
-<br>
- void *tag = I->first;<br>
- Checker *checker = I->second;<br>
-<br>
- for (ExplodedNodeSet::iterator NI = PrevSet->begin(), NE = PrevSet->end();<br>
- NI != NE; ++NI)<br>
- checker->GR_VisitBind(*CurrSet, *Builder, *this, StoreE,<br>
- *NI, tag, location, val, isPrevisit);<br>
-<br>
- // Update which NodeSet is the current one.<br>
- PrevSet = CurrSet;<br>
- }<br>
-<br>
- // Don't autotransition. The CheckerContext objects should do this<br>
- // automatically.<br>
-}<br>
-//===----------------------------------------------------------------------===//<br>
-// Engine construction and deletion.<br>
-//===----------------------------------------------------------------------===//<br>
-<br>
-static void RegisterInternalChecks(ExprEngine &Eng) {<br>
- // Register internal "built-in" BugTypes with the BugReporter. These BugTypes<br>
- // are different than what probably many checks will do since they don't<br>
- // create BugReports on-the-fly but instead wait until ExprEngine finishes<br>
- // analyzing a function. Generation of BugReport objects is done via a call<br>
- // to 'FlushReports' from BugReporter.<br>
- // The following checks do not need to have their associated BugTypes<br>
- // explicitly registered with the BugReporter. If they issue any BugReports,<br>
- // their associated BugType will get registered with the BugReporter<br>
- // automatically. Note that the check itself is owned by the ExprEngine<br>
- // object.<br>
- RegisterAdjustedReturnValueChecker(Eng);<br>
- // CallAndMessageChecker should be registered before AttrNonNullChecker,<br>
- // where we assume arguments are not undefined.<br>
- RegisterCallAndMessageChecker(Eng);<br>
- RegisterAttrNonNullChecker(Eng);<br>
- RegisterDereferenceChecker(Eng);<br>
- RegisterVLASizeChecker(Eng);<br>
- RegisterDivZeroChecker(Eng);<br>
- RegisterReturnUndefChecker(Eng);<br>
- RegisterUndefinedArraySubscriptChecker(Eng);<br>
- RegisterUndefinedAssignmentChecker(Eng);<br>
- RegisterUndefBranchChecker(Eng);<br>
- RegisterUndefCapturedBlockVarChecker(Eng);<br>
- RegisterUndefResultChecker(Eng);<br>
- RegisterStackAddrLeakChecker(Eng);<br>
- RegisterObjCAtSyncChecker(Eng);<br>
-<br>
- // This is not a checker yet.<br>
- RegisterNoReturnFunctionChecker(Eng);<br>
- RegisterBuiltinFunctionChecker(Eng);<br>
- RegisterOSAtomicChecker(Eng);<br>
- RegisterUnixAPIChecker(Eng);<br>
- RegisterMacOSXAPIChecker(Eng);<br>
-}<br>
-<br>
-ExprEngine::ExprEngine(AnalysisManager &mgr, TransferFuncs *tf)<br>
- : AMgr(mgr),<br>
- Engine(*this),<br>
- G(Engine.getGraph()),<br>
- Builder(NULL),<br>
- StateMgr(getContext(), mgr.getStoreManagerCreator(),<br>
- mgr.getConstraintManagerCreator(), G.getAllocator(),<br>
- *this),<br>
- SymMgr(StateMgr.getSymbolManager()),<br>
- svalBuilder(StateMgr.getSValBuilder()),<br>
- EntryNode(NULL), currentStmt(NULL),<br>
- NSExceptionII(NULL), NSExceptionInstanceRaiseSelectors(NULL),<br>
- RaiseSel(GetNullarySelector("raise", getContext())),<br>
- BR(mgr, *this), TF(tf) {<br>
- // Register internal checks.<br>
- RegisterInternalChecks(*this);<br>
-<br>
- // FIXME: Eventually remove the TF object entirely.<br>
- TF->RegisterChecks(*this);<br>
- TF->RegisterPrinters(getStateManager().Printers);<br>
-}<br>
-<br>
-ExprEngine::~ExprEngine() {<br>
- BR.FlushReports();<br>
- delete [] NSExceptionInstanceRaiseSelectors;<br>
-<br>
- // Delete the set of checkers.<br>
- for (CheckersOrdered::iterator I=Checkers.begin(), E=Checkers.end(); I!=E;++I)<br>
- delete I->second;<br>
-<br>
- for (CheckersOrderedCache::iterator I=COCache.begin(), E=COCache.end();<br>
- I!=E;++I)<br>
- delete I->second;<br>
-}<br>
-<br>
-//===----------------------------------------------------------------------===//<br>
-// Utility methods.<br>
-//===----------------------------------------------------------------------===//<br>
-<br>
-const GRState* ExprEngine::getInitialState(const LocationContext *InitLoc) {<br>
- const GRState *state = StateMgr.getInitialState(InitLoc);<br>
-<br>
- // Preconditions.<br>
-<br>
- // FIXME: It would be nice if we had a more general mechanism to add<br>
- // such preconditions. Some day.<br>
- do {<br>
- const Decl *D = InitLoc->getDecl();<br>
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {<br>
- // Precondition: the first argument of 'main' is an integer guaranteed<br>
- // to be > 0.<br>
- const IdentifierInfo *II = FD->getIdentifier();<br>
- if (!II || !(II->getName() == "main" && FD->getNumParams() > 0))<br>
- break;<br>
-<br>
- const ParmVarDecl *PD = FD->getParamDecl(0);<br>
- QualType T = PD->getType();<br>
- if (!T->isIntegerType())<br>
- break;<br>
-<br>
- const MemRegion *R = state->getRegion(PD, InitLoc);<br>
- if (!R)<br>
- break;<br>
-<br>
- SVal V = state->getSVal(loc::MemRegionVal(R));<br>
- SVal Constraint_untested = evalBinOp(state, BO_GT, V,<br>
- svalBuilder.makeZeroVal(T),<br>
- getContext().IntTy);<br>
-<br>
- DefinedOrUnknownSVal *Constraint =<br>
- dyn_cast<DefinedOrUnknownSVal>(&Constraint_untested);<br>
-<br>
- if (!Constraint)<br>
- break;<br>
-<br>
- if (const GRState *newState = state->assume(*Constraint, true))<br>
- state = newState;<br>
-<br>
- break;<br>
- }<br>
-<br>
- if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {<br>
- // Precondition: 'self' is always non-null upon entry to an Objective-C<br>
- // method.<br>
- const ImplicitParamDecl *SelfD = MD->getSelfDecl();<br>
- const MemRegion *R = state->getRegion(SelfD, InitLoc);<br>
- SVal V = state->getSVal(loc::MemRegionVal(R));<br>
-<br>
- if (const Loc *LV = dyn_cast<Loc>(&V)) {<br>
- // Assume that the pointer value in 'self' is non-null.<br>
- state = state->assume(*LV, true);<br>
- assert(state && "'self' cannot be null");<br>
- }<br>
- }<br>
- } while (0);<br>
-<br>
- return state;<br>
-}<br>
-<br>
-//===----------------------------------------------------------------------===//<br>
-// Top-level transfer function logic (Dispatcher).<br>
-//===----------------------------------------------------------------------===//<br>
-<br>
-/// evalAssume - Called by ConstraintManager. Used to call checker-specific<br>
-/// logic for handling assumptions on symbolic values.<br>
-const GRState *ExprEngine::ProcessAssume(const GRState *state, SVal cond,<br>
- bool assumption) {<br>
- // Determine if we already have a cached 'CheckersOrdered' vector<br>
- // specifically tailored for processing assumptions. This<br>
- // can reduce the number of checkers actually called.<br>
- CheckersOrdered *CO = &Checkers;<br>
- llvm::OwningPtr<CheckersOrdered> NewCO;<br>
-<br>
- CallbackTag K = GetCallbackTag(ProcessAssumeCallback);<br>
- CheckersOrdered *& CO_Ref = COCache[K];<br>
-<br>
- if (!CO_Ref) {<br>
- // If we have no previously cached CheckersOrdered vector for this<br>
- // statement kind, then create one.<br>
- NewCO.reset(new CheckersOrdered);<br>
- }<br>
- else {<br>
- // Use the already cached set.<br>
- CO = CO_Ref;<br>
- }<br>
-<br>
- if (!CO->empty()) {<br>
- // Let the checkers have a crack at the assume before the transfer functions<br>
- // get their turn.<br>
- for (CheckersOrdered::iterator I = CO->begin(), E = CO->end(); I!=E; ++I) {<br>
-<br>
- // If any checker declares the state infeasible (or if it starts that<br>
- // way), bail out.<br>
- if (!state)<br>
- return NULL;<br>
-<br>
- Checker *C = I->second;<br>
- bool respondsToCallback = true;<br>
-<br>
- state = C->evalAssume(state, cond, assumption, &respondsToCallback);<br>
-<br>
- // Check if we're building the cache of checkers that care about<br>
- // assumptions.<br>
- if (NewCO.get() && respondsToCallback)<br>
- NewCO->push_back(*I);<br>
- }<br>
-<br>
- // If we got through all the checkers, and we built a list of those that<br>
- // care about assumptions, save it.<br>
- if (NewCO.get())<br>
- CO_Ref = NewCO.take();<br>
- }<br>
-<br>
- // If the state is infeasible at this point, bail out.<br>
- if (!state)<br>
- return NULL;<br>
-<br>
- return TF->evalAssume(state, cond, assumption);<br>
-}<br>
-<br>
-bool ExprEngine::WantsRegionChangeUpdate(const GRState* state) {<br>
- CallbackTag K = GetCallbackTag(EvalRegionChangesCallback);<br>
- CheckersOrdered *CO = COCache[K];<br>
-<br>
- if (!CO)<br>
- CO = &Checkers;<br>
-<br>
- for (CheckersOrdered::iterator I = CO->begin(), E = CO->end(); I != E; ++I) {<br>
- Checker *C = I->second;<br>
- if (C->WantsRegionChangeUpdate(state))<br>
- return true;<br>
- }<br>
-<br>
- return false;<br>
-}<br>
-<br>
-const GRState *<br>
-ExprEngine::ProcessRegionChanges(const GRState *state,<br>
- const MemRegion * const *Begin,<br>
- const MemRegion * const *End) {<br>
- // FIXME: Most of this method is copy-pasted from ProcessAssume.<br>
-<br>
- // Determine if we already have a cached 'CheckersOrdered' vector<br>
- // specifically tailored for processing region changes. This<br>
- // can reduce the number of checkers actually called.<br>
- CheckersOrdered *CO = &Checkers;<br>
- llvm::OwningPtr<CheckersOrdered> NewCO;<br>
-<br>
- CallbackTag K = GetCallbackTag(EvalRegionChangesCallback);<br>
- CheckersOrdered *& CO_Ref = COCache[K];<br>
-<br>
- if (!CO_Ref) {<br>
- // If we have no previously cached CheckersOrdered vector for this<br>
- // callback, then create one.<br>
- NewCO.reset(new CheckersOrdered);<br>
- }<br>
- else {<br>
- // Use the already cached set.<br>
- CO = CO_Ref;<br>
- }<br>
-<br>
- // If there are no checkers, just return the state as is.<br>
- if (CO->empty())<br>
- return state;<br>
-<br>
- for (CheckersOrdered::iterator I = CO->begin(), E = CO->end(); I != E; ++I) {<br>
- // If any checker declares the state infeasible (or if it starts that way),<br>
- // bail out.<br>
- if (!state)<br>
- return NULL;<br>
-<br>
- Checker *C = I->second;<br>
- bool respondsToCallback = true;<br>
-<br>
- state = C->EvalRegionChanges(state, Begin, End, &respondsToCallback);<br>
-<br>
- // See if we're building a cache of checkers that care about region changes.<br>
- if (NewCO.get() && respondsToCallback)<br>
- NewCO->push_back(*I);<br>
- }<br>
-<br>
- // If we got through all the checkers, and we built a list of those that<br>
- // care about region changes, save it.<br>
- if (NewCO.get())<br>
- CO_Ref = NewCO.take();<br>
-<br>
- return state;<br>
-}<br>
-<br>
-void ExprEngine::ProcessEndWorklist(bool hasWorkRemaining) {<br>
- for (CheckersOrdered::iterator I = Checkers.begin(), E = Checkers.end();<br>
- I != E; ++I) {<br>
- I->second->VisitEndAnalysis(G, BR, *this);<br>
- }<br>
-}<br>
-<br>
-void ExprEngine::ProcessElement(const CFGElement E,<br>
- StmtNodeBuilder& builder) {<br>
- switch (E.getKind()) {<br>
- case CFGElement::Statement:<br>
- ProcessStmt(E.getAs<CFGStmt>(), builder);<br>
- break;<br>
- case CFGElement::Initializer:<br>
- ProcessInitializer(E.getAs<CFGInitializer>(), builder);<br>
- break;<br>
- case CFGElement::ImplicitDtor:<br>
- ProcessImplicitDtor(E.getAs<CFGImplicitDtor>(), builder);<br>
- break;<br>
- default:<br>
- // Suppress compiler warning.<br>
- llvm_unreachable("Unexpected CFGElement kind.");<br>
- }<br>
-}<br>
-<br>
-void ExprEngine::ProcessStmt(const CFGStmt S, StmtNodeBuilder& builder) {<br>
- currentStmt = S.getStmt();<br>
- PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),<br>
- currentStmt->getLocStart(),<br>
- "Error evaluating statement");<br>
-<br>
- Builder = &builder;<br>
- EntryNode = builder.getBasePredecessor();<br>
-<br>
- // Create the cleaned state.<br>
- const LocationContext *LC = EntryNode->getLocationContext();<br>
- SymbolReaper SymReaper(LC, currentStmt, SymMgr);<br>
-<br>
- if (AMgr.shouldPurgeDead()) {<br>
- const GRState *St = EntryNode->getState();<br>
-<br>
- for (CheckersOrdered::iterator I = Checkers.begin(), E = Checkers.end();<br>
- I != E; ++I) {<br>
- Checker *checker = I->second;<br>
- checker->MarkLiveSymbols(St, SymReaper);<br>
- }<br>
-<br>
- const StackFrameContext *SFC = LC->getCurrentStackFrame();<br>
- CleanedState = StateMgr.RemoveDeadBindings(St, SFC, SymReaper);<br>
- } else {<br>
- CleanedState = EntryNode->getState();<br>
- }<br>
-<br>
- // Process any special transfer function for dead symbols.<br>
- ExplodedNodeSet Tmp;<br>
-<br>
- if (!SymReaper.hasDeadSymbols())<br>
- Tmp.Add(EntryNode);<br>
- else {<br>
- SaveAndRestore<bool> OldSink(Builder->BuildSinks);<br>
- SaveOr OldHasGen(Builder->HasGeneratedNode);<br>
-<br>
- SaveAndRestore<bool> OldPurgeDeadSymbols(Builder->PurgingDeadSymbols);<br>
- Builder->PurgingDeadSymbols = true;<br>
-<br>
- // FIXME: This should soon be removed.<br>
- ExplodedNodeSet Tmp2;<br>
- getTF().evalDeadSymbols(Tmp2, *this, *Builder, EntryNode,<br>
- CleanedState, SymReaper);<br>
-<br>
- if (Checkers.empty())<br>
- Tmp.insert(Tmp2);<br>
- else {<br>
- ExplodedNodeSet Tmp3;<br>
- ExplodedNodeSet *SrcSet = &Tmp2;<br>
- for (CheckersOrdered::iterator I = Checkers.begin(), E = Checkers.end();<br>
- I != E; ++I) {<br>
- ExplodedNodeSet *DstSet = 0;<br>
- if (I+1 == E)<br>
- DstSet = &Tmp;<br>
- else {<br>
- DstSet = (SrcSet == &Tmp2) ? &Tmp3 : &Tmp2;<br>
- DstSet->clear();<br>
- }<br>
-<br>
- void *tag = I->first;<br>
- Checker *checker = I->second;<br>
- for (ExplodedNodeSet::iterator NI = SrcSet->begin(), NE = SrcSet->end();<br>
- NI != NE; ++NI)<br>
- checker->GR_evalDeadSymbols(*DstSet, *Builder, *this, currentStmt,<br>
- *NI, SymReaper, tag);<br>
- SrcSet = DstSet;<br>
- }<br>
- }<br>
-<br>
- if (!Builder->BuildSinks && !Builder->HasGeneratedNode)<br>
- Tmp.Add(EntryNode);<br>
- }<br>
-<br>
- bool HasAutoGenerated = false;<br>
-<br>
- for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {<br>
- ExplodedNodeSet Dst;<br>
-<br>
- // Set the cleaned state.<br>
- Builder->SetCleanedState(*I == EntryNode ? CleanedState : GetState(*I));<br>
-<br>
- // Visit the statement.<br>
- Visit(currentStmt, *I, Dst);<br>
-<br>
- // Do we need to auto-generate a node? We only need to do this to generate<br>
- // a node with a "cleaned" state; CoreEngine will actually handle<br>
- // auto-transitions for other cases.<br>
- if (Dst.size() == 1 && *Dst.begin() == EntryNode<br>
- && !Builder->HasGeneratedNode && !HasAutoGenerated) {<br>
- HasAutoGenerated = true;<br>
- builder.generateNode(currentStmt, GetState(EntryNode), *I);<br>
- }<br>
- }<br>
-<br>
- // NULL out these variables to cleanup.<br>
- CleanedState = NULL;<br>
- EntryNode = NULL;<br>
-<br>
- currentStmt = 0;<br>
-<br>
- Builder = NULL;<br>
-}<br>
-<br>
-void ExprEngine::ProcessInitializer(const CFGInitializer Init,<br>
- StmtNodeBuilder &builder) {<br>
- // We don't set EntryNode and currentStmt. And we don't clean up state.<br>
- const CXXCtorInitializer *BMI = Init.getInitializer();<br>
-<br>
- ExplodedNode *Pred = builder.getBasePredecessor();<br>
- const LocationContext *LC = Pred->getLocationContext();<br>
-<br>
- if (BMI->isAnyMemberInitializer()) {<br>
- ExplodedNodeSet Dst;<br>
-<br>
- // Evaluate the initializer.<br>
- Visit(BMI->getInit(), Pred, Dst);<br>
-<br>
- for (ExplodedNodeSet::iterator I = Dst.begin(), E = Dst.end(); I != E; ++I){<br>
- ExplodedNode *Pred = *I;<br>
- const GRState *state = Pred->getState();<br>
-<br>
- const FieldDecl *FD = BMI->getAnyMember();<br>
- const RecordDecl *RD = FD->getParent();<br>
- const CXXThisRegion *ThisR = getCXXThisRegion(cast<CXXRecordDecl>(RD),<br>
- cast<StackFrameContext>(LC));<br>
-<br>
- SVal ThisV = state->getSVal(ThisR);<br>
- SVal FieldLoc = state->getLValue(FD, ThisV);<br>
- SVal InitVal = state->getSVal(BMI->getInit());<br>
- state = state->bindLoc(FieldLoc, InitVal);<br>
-<br>
- // Use a custom node building process.<br>
- PostInitializer PP(BMI, LC);<br>
- // Builder automatically add the generated node to the deferred set,<br>
- // which are processed in the builder's dtor.<br>
- builder.generateNode(PP, state, Pred);<br>
- }<br>
- }<br>
-}<br>
-<br>
-void ExprEngine::ProcessImplicitDtor(const CFGImplicitDtor D,<br>
- StmtNodeBuilder &builder) {<br>
- Builder = &builder;<br>
-<br>
- switch (D.getDtorKind()) {<br>
- case CFGElement::AutomaticObjectDtor:<br>
- ProcessAutomaticObjDtor(cast<CFGAutomaticObjDtor>(D), builder);<br>
- break;<br>
- case CFGElement::BaseDtor:<br>
- ProcessBaseDtor(cast<CFGBaseDtor>(D), builder);<br>
- break;<br>
- case CFGElement::MemberDtor:<br>
- ProcessMemberDtor(cast<CFGMemberDtor>(D), builder);<br>
- break;<br>
- case CFGElement::TemporaryDtor:<br>
- ProcessTemporaryDtor(cast<CFGTemporaryDtor>(D), builder);<br>
- break;<br>
- default:<br>
- llvm_unreachable("Unexpected dtor kind.");<br>
- }<br>
-}<br>
-<br>
-void ExprEngine::ProcessAutomaticObjDtor(const CFGAutomaticObjDtor dtor,<br>
- StmtNodeBuilder &builder) {<br>
- ExplodedNode *pred = builder.getBasePredecessor();<br>
- const GRState *state = pred->getState();<br>
- const VarDecl *varDecl = dtor.getVarDecl();<br>
-<br>
- QualType varType = varDecl->getType();<br>
-<br>
- if (const ReferenceType *refType = varType->getAs<ReferenceType>())<br>
- varType = refType->getPointeeType();<br>
-<br>
- const CXXRecordDecl *recordDecl = varType->getAsCXXRecordDecl();<br>
- assert(recordDecl && "get CXXRecordDecl fail");<br>
- const CXXDestructorDecl *dtorDecl = recordDecl->getDestructor();<br>
-<br>
- Loc dest = state->getLValue(varDecl, pred->getLocationContext());<br>
-<br>
- ExplodedNodeSet dstSet;<br>
- VisitCXXDestructor(dtorDecl, cast<loc::MemRegionVal>(dest).getRegion(),<br>
- dtor.getTriggerStmt(), pred, dstSet);<br>
-}<br>
-<br>
-void ExprEngine::ProcessBaseDtor(const CFGBaseDtor D,<br>
- StmtNodeBuilder &builder) {<br>
-}<br>
-<br>
-void ExprEngine::ProcessMemberDtor(const CFGMemberDtor D,<br>
- StmtNodeBuilder &builder) {<br>
-}<br>
-<br>
-void ExprEngine::ProcessTemporaryDtor(const CFGTemporaryDtor D,<br>
- StmtNodeBuilder &builder) {<br>
-}<br>
-<br>
-void ExprEngine::Visit(const Stmt* S, ExplodedNode* Pred,<br>
- ExplodedNodeSet& Dst) {<br>
- PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),<br>
- S->getLocStart(),<br>
- "Error evaluating statement");<br>
-<br>
- // Expressions to ignore.<br>
- if (const Expr *Ex = dyn_cast<Expr>(S))<br>
- S = Ex->IgnoreParens();<br>
-<br>
- // FIXME: add metadata to the CFG so that we can disable<br>
- // this check when we KNOW that there is no block-level subexpression.<br>
- // The motivation is that this check requires a hashtable lookup.<br>
-<br>
- if (S != currentStmt && Pred->getLocationContext()->getCFG()->isBlkExpr(S)) {<br>
- Dst.Add(Pred);<br>
- return;<br>
- }<br>
-<br>
- switch (S->getStmtClass()) {<br>
- // C++ stuff we don't support yet.<br>
- case Stmt::CXXBindTemporaryExprClass:<br>
- case Stmt::CXXCatchStmtClass:<br>
- case Stmt::CXXDefaultArgExprClass:<br>
- case Stmt::CXXDependentScopeMemberExprClass:<br>
- case Stmt::ExprWithCleanupsClass:<br>
- case Stmt::CXXNullPtrLiteralExprClass:<br>
- case Stmt::CXXPseudoDestructorExprClass:<br>
- case Stmt::CXXTemporaryObjectExprClass:<br>
- case Stmt::CXXThrowExprClass:<br>
- case Stmt::CXXTryStmtClass:<br>
- case Stmt::CXXTypeidExprClass:<br>
- case Stmt::CXXUuidofExprClass:<br>
- case Stmt::CXXUnresolvedConstructExprClass:<br>
- case Stmt::CXXScalarValueInitExprClass:<br>
- case Stmt::DependentScopeDeclRefExprClass:<br>
- case Stmt::UnaryTypeTraitExprClass:<br>
- case Stmt::BinaryTypeTraitExprClass:<br>
- case Stmt::UnresolvedLookupExprClass:<br>
- case Stmt::UnresolvedMemberExprClass:<br>
- case Stmt::CXXNoexceptExprClass:<br>
- case Stmt::PackExpansionExprClass:<br>
- {<br>
- SaveAndRestore<bool> OldSink(Builder->BuildSinks);<br>
- Builder->BuildSinks = true;<br>
- MakeNode(Dst, S, Pred, GetState(Pred));<br>
- break;<br>
- }<br>
-<br>
- case Stmt::ParenExprClass:<br>
- llvm_unreachable("ParenExprs already handled.");<br>
- // Cases that should never be evaluated simply because they shouldn't<br>
- // appear in the CFG.<br>
- case Stmt::BreakStmtClass:<br>
- case Stmt::CaseStmtClass:<br>
- case Stmt::CompoundStmtClass:<br>
- case Stmt::ContinueStmtClass:<br>
- case Stmt::DefaultStmtClass:<br>
- case Stmt::DoStmtClass:<br>
- case Stmt::GotoStmtClass:<br>
- case Stmt::IndirectGotoStmtClass:<br>
- case Stmt::LabelStmtClass:<br>
- case Stmt::NoStmtClass:<br>
- case Stmt::NullStmtClass:<br>
- case Stmt::SwitchCaseClass:<br>
- case Stmt::OpaqueValueExprClass:<br>
- llvm_unreachable("Stmt should not be in analyzer evaluation loop");<br>
- break;<br>
-<br>
- case Stmt::GNUNullExprClass: {<br>
- MakeNode(Dst, S, Pred, GetState(Pred)->BindExpr(S, svalBuilder.makeNull()));<br>
- break;<br>
- }<br>
-<br>
- case Stmt::ObjCAtSynchronizedStmtClass:<br>
- VisitObjCAtSynchronizedStmt(cast<ObjCAtSynchronizedStmt>(S), Pred, Dst);<br>
- break;<br>
-<br>
- // Cases not handled yet; but will handle some day.<br>
- case Stmt::DesignatedInitExprClass:<br>
- case Stmt::ExtVectorElementExprClass:<br>
- case Stmt::ImaginaryLiteralClass:<br>
- case Stmt::ImplicitValueInitExprClass:<br>
- case Stmt::ObjCAtCatchStmtClass:<br>
- case Stmt::ObjCAtFinallyStmtClass:<br>
- case Stmt::ObjCAtTryStmtClass:<br>
- case Stmt::ObjCEncodeExprClass:<br>
- case Stmt::ObjCIsaExprClass:<br>
- case Stmt::ObjCPropertyRefExprClass:<br>
- case Stmt::ObjCProtocolExprClass:<br>
- case Stmt::ObjCSelectorExprClass:<br>
- case Stmt::ObjCStringLiteralClass:<br>
- case Stmt::ParenListExprClass:<br>
- case Stmt::PredefinedExprClass:<br>
- case Stmt::ShuffleVectorExprClass:<br>
- case Stmt::VAArgExprClass:<br>
- // Fall through.<br>
-<br>
- // Cases we intentionally don't evaluate, since they don't need<br>
- // to be explicitly evaluated.<br>
- case Stmt::AddrLabelExprClass:<br>
- case Stmt::IntegerLiteralClass:<br>
- case Stmt::CharacterLiteralClass:<br>
- case Stmt::CXXBoolLiteralExprClass:<br>
- case Stmt::FloatingLiteralClass:<br>
- case Stmt::SizeOfPackExprClass:<br>
- Dst.Add(Pred); // No-op. Simply propagate the current state unchanged.<br>
- break;<br>
-<br>
- case Stmt::ArraySubscriptExprClass:<br>
- VisitLvalArraySubscriptExpr(cast<ArraySubscriptExpr>(S), Pred, Dst);<br>
- break;<br>
-<br>
- case Stmt::AsmStmtClass:<br>
- VisitAsmStmt(cast<AsmStmt>(S), Pred, Dst);<br>
- break;<br>
-<br>
- case Stmt::BlockDeclRefExprClass: {<br>
- const BlockDeclRefExpr *BE = cast<BlockDeclRefExpr>(S);<br>
- VisitCommonDeclRefExpr(BE, BE->getDecl(), Pred, Dst);<br>
- break;<br>
- }<br>
-<br>
- case Stmt::BlockExprClass:<br>
- VisitBlockExpr(cast<BlockExpr>(S), Pred, Dst);<br>
- break;<br>
-<br>
- case Stmt::BinaryOperatorClass: {<br>
- const BinaryOperator* B = cast<BinaryOperator>(S);<br>
- if (B->isLogicalOp()) {<br>
- VisitLogicalExpr(B, Pred, Dst);<br>
- break;<br>
- }<br>
- else if (B->getOpcode() == BO_Comma) {<br>
- const GRState* state = GetState(Pred);<br>
- MakeNode(Dst, B, Pred, state->BindExpr(B, state->getSVal(B->getRHS())));<br>
- break;<br>
- }<br>
-<br>
- if (AMgr.shouldEagerlyAssume() &&<br>
- (B->isRelationalOp() || B->isEqualityOp())) {<br>
- ExplodedNodeSet Tmp;<br>
- VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Tmp);<br>
- evalEagerlyAssume(Dst, Tmp, cast<Expr>(S));<br>
- }<br>
- else<br>
- VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst);<br>
-<br>
- break;<br>
- }<br>
-<br>
- case Stmt::CallExprClass: {<br>
- const CallExpr* C = cast<CallExpr>(S);<br>
- VisitCall(C, Pred, C->arg_begin(), C->arg_end(), Dst);<br>
- break;<br>
- }<br>
-<br>
- case Stmt::CXXConstructExprClass: {<br>
- const CXXConstructExpr *C = cast<CXXConstructExpr>(S);<br>
- // For block-level CXXConstructExpr, we don't have a destination region.<br>
- // Let VisitCXXConstructExpr() create one.<br>
- VisitCXXConstructExpr(C, 0, Pred, Dst);<br>
- break;<br>
- }<br>
-<br>
- case Stmt::CXXMemberCallExprClass: {<br>
- const CXXMemberCallExpr *MCE = cast<CXXMemberCallExpr>(S);<br>
- VisitCXXMemberCallExpr(MCE, Pred, Dst);<br>
- break;<br>
- }<br>
-<br>
- case Stmt::CXXOperatorCallExprClass: {<br>
- const CXXOperatorCallExpr *C = cast<CXXOperatorCallExpr>(S);<br>
- VisitCXXOperatorCallExpr(C, Pred, Dst);<br>
- break;<br>
- }<br>
-<br>
- case Stmt::CXXNewExprClass: {<br>
- const CXXNewExpr *NE = cast<CXXNewExpr>(S);<br>
- VisitCXXNewExpr(NE, Pred, Dst);<br>
- break;<br>
- }<br>
-<br>
- case Stmt::CXXDeleteExprClass: {<br>
- const CXXDeleteExpr *CDE = cast<CXXDeleteExpr>(S);<br>
- VisitCXXDeleteExpr(CDE, Pred, Dst);<br>
- break;<br>
- }<br>
- // FIXME: ChooseExpr is really a constant. We need to fix<br>
- // the CFG do not model them as explicit control-flow.<br>
-<br>
- case Stmt::ChooseExprClass: { // __builtin_choose_expr<br>
- const ChooseExpr* C = cast<ChooseExpr>(S);<br>
- VisitGuardedExpr(C, C->getLHS(), C->getRHS(), Pred, Dst);<br>
- break;<br>
- }<br>
-<br>
- case Stmt::CompoundAssignOperatorClass:<br>
- VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst);<br>
- break;<br>
-<br>
- case Stmt::CompoundLiteralExprClass:<br>
- VisitCompoundLiteralExpr(cast<CompoundLiteralExpr>(S), Pred, Dst);<br>
- break;<br>
-<br>
- case Stmt::ConditionalOperatorClass: { // '?' operator<br>
- const ConditionalOperator* C = cast<ConditionalOperator>(S);<br>
- VisitGuardedExpr(C, C->getLHS(), C->getRHS(), Pred, Dst);<br>
- break;<br>
- }<br>
-<br>
- case Stmt::CXXThisExprClass:<br>
- VisitCXXThisExpr(cast<CXXThisExpr>(S), Pred, Dst);<br>
- break;<br>
-<br>
- case Stmt::DeclRefExprClass: {<br>
- const DeclRefExpr *DE = cast<DeclRefExpr>(S);<br>
- VisitCommonDeclRefExpr(DE, DE->getDecl(), Pred, Dst);<br>
- break;<br>
- }<br>
-<br>
- case Stmt::DeclStmtClass:<br>
- VisitDeclStmt(cast<DeclStmt>(S), Pred, Dst);<br>
- break;<br>
-<br>
- case Stmt::ForStmtClass:<br>
- // This case isn't for branch processing, but for handling the<br>
- // initialization of a condition variable.<br>
- VisitCondInit(cast<ForStmt>(S)->getConditionVariable(), S, Pred, Dst);<br>
- break;<br>
-<br>
- case Stmt::ImplicitCastExprClass:<br>
- case Stmt::CStyleCastExprClass:<br>
- case Stmt::CXXStaticCastExprClass:<br>
- case Stmt::CXXDynamicCastExprClass:<br>
- case Stmt::CXXReinterpretCastExprClass:<br>
- case Stmt::CXXConstCastExprClass:<br>
- case Stmt::CXXFunctionalCastExprClass: {<br>
- const CastExpr* C = cast<CastExpr>(S);<br>
- VisitCast(C, C->getSubExpr(), Pred, Dst);<br>
- break;<br>
- }<br>
-<br>
- case Stmt::IfStmtClass:<br>
- // This case isn't for branch processing, but for handling the<br>
- // initialization of a condition variable.<br>
- VisitCondInit(cast<IfStmt>(S)->getConditionVariable(), S, Pred, Dst);<br>
- break;<br>
-<br>
- case Stmt::InitListExprClass:<br>
- VisitInitListExpr(cast<InitListExpr>(S), Pred, Dst);<br>
- break;<br>
-<br>
- case Stmt::MemberExprClass:<br>
- VisitMemberExpr(cast<MemberExpr>(S), Pred, Dst);<br>
- break;<br>
- case Stmt::ObjCIvarRefExprClass:<br>
- VisitLvalObjCIvarRefExpr(cast<ObjCIvarRefExpr>(S), Pred, Dst);<br>
- break;<br>
-<br>
- case Stmt::ObjCForCollectionStmtClass:<br>
- VisitObjCForCollectionStmt(cast<ObjCForCollectionStmt>(S), Pred, Dst);<br>
- break;<br>
-<br>
- case Stmt::ObjCMessageExprClass:<br>
- VisitObjCMessageExpr(cast<ObjCMessageExpr>(S), Pred, Dst);<br>
- break;<br>
-<br>
- case Stmt::ObjCAtThrowStmtClass: {<br>
- // FIXME: This is not complete. We basically treat @throw as<br>
- // an abort.<br>
- SaveAndRestore<bool> OldSink(Builder->BuildSinks);<br>
- Builder->BuildSinks = true;<br>
- MakeNode(Dst, S, Pred, GetState(Pred));<br>
- break;<br>
- }<br>
-<br>
- case Stmt::ReturnStmtClass:<br>
- VisitReturnStmt(cast<ReturnStmt>(S), Pred, Dst);<br>
- break;<br>
-<br>
- case Stmt::OffsetOfExprClass:<br>
- VisitOffsetOfExpr(cast<OffsetOfExpr>(S), Pred, Dst);<br>
- break;<br>
-<br>
- case Stmt::SizeOfAlignOfExprClass:<br>
- VisitSizeOfAlignOfExpr(cast<SizeOfAlignOfExpr>(S), Pred, Dst);<br>
- break;<br>
-<br>
- case Stmt::StmtExprClass: {<br>
- const StmtExpr* SE = cast<StmtExpr>(S);<br>
-<br>
- if (SE->getSubStmt()->body_empty()) {<br>
- // Empty statement expression.<br>
- assert(SE->getType() == getContext().VoidTy<br>
- && "Empty statement expression must have void type.");<br>
- Dst.Add(Pred);<br>
- break;<br>
- }<br>
-<br>
- if (Expr* LastExpr = dyn_cast<Expr>(*SE->getSubStmt()->body_rbegin())) {<br>
- const GRState* state = GetState(Pred);<br>
- MakeNode(Dst, SE, Pred, state->BindExpr(SE, state->getSVal(LastExpr)));<br>
- }<br>
- else<br>
- Dst.Add(Pred);<br>
-<br>
- break;<br>
- }<br>
-<br>
- case Stmt::StringLiteralClass: {<br>
- const GRState* state = GetState(Pred);<br>
- SVal V = state->getLValue(cast<StringLiteral>(S));<br>
- MakeNode(Dst, S, Pred, state->BindExpr(S, V));<br>
- return;<br>
- }<br>
-<br>
- case Stmt::SwitchStmtClass:<br>
- // This case isn't for branch processing, but for handling the<br>
- // initialization of a condition variable.<br>
- VisitCondInit(cast<SwitchStmt>(S)->getConditionVariable(), S, Pred, Dst);<br>
- break;<br>
-<br>
- case Stmt::UnaryOperatorClass: {<br>
- const UnaryOperator *U = cast<UnaryOperator>(S);<br>
- if (AMgr.shouldEagerlyAssume()&&(U->getOpcode() == UO_LNot)) {<br>
- ExplodedNodeSet Tmp;<br>
- VisitUnaryOperator(U, Pred, Tmp);<br>
- evalEagerlyAssume(Dst, Tmp, U);<br>
- }<br>
- else<br>
- VisitUnaryOperator(U, Pred, Dst);<br>
- break;<br>
- }<br>
-<br>
- case Stmt::WhileStmtClass:<br>
- // This case isn't for branch processing, but for handling the<br>
- // initialization of a condition variable.<br>
- VisitCondInit(cast<WhileStmt>(S)->getConditionVariable(), S, Pred, Dst);<br>
- break;<br>
- }<br>
-}<br>
-<br>
-//===----------------------------------------------------------------------===//<br>
-// Block entrance. (Update counters).<br>
-//===----------------------------------------------------------------------===//<br>
-<br>
-bool ExprEngine::ProcessBlockEntrance(const CFGBlock* B,<br>
- const ExplodedNode *Pred,<br>
- BlockCounter BC) {<br>
- return BC.getNumVisited(Pred->getLocationContext()->getCurrentStackFrame(),<br>
- B->getBlockID()) < AMgr.getMaxVisit();<br>
-}<br>
-<br>
-//===----------------------------------------------------------------------===//<br>
-// Generic node creation.<br>
-//===----------------------------------------------------------------------===//<br>
-<br>
-ExplodedNode* ExprEngine::MakeNode(ExplodedNodeSet& Dst, const Stmt* S,<br>
- ExplodedNode* Pred, const GRState* St,<br>
- ProgramPoint::Kind K, const void *tag) {<br>
- assert (Builder && "StmtNodeBuilder not present.");<br>
- SaveAndRestore<const void*> OldTag(Builder->Tag);<br>
- Builder->Tag = tag;<br>
- return Builder->MakeNode(Dst, S, Pred, St, K);<br>
-}<br>
-<br>
-//===----------------------------------------------------------------------===//<br>
-// Branch processing.<br>
-//===----------------------------------------------------------------------===//<br>
-<br>
-const GRState* ExprEngine::MarkBranch(const GRState* state,<br>
- const Stmt* Terminator,<br>
- bool branchTaken) {<br>
-<br>
- switch (Terminator->getStmtClass()) {<br>
- default:<br>
- return state;<br>
-<br>
- case Stmt::BinaryOperatorClass: { // '&&' and '||'<br>
-<br>
- const BinaryOperator* B = cast<BinaryOperator>(Terminator);<br>
- BinaryOperator::Opcode Op = B->getOpcode();<br>
-<br>
- assert (Op == BO_LAnd || Op == BO_LOr);<br>
-<br>
- // For &&, if we take the true branch, then the value of the whole<br>
- // expression is that of the RHS expression.<br>
- //<br>
- // For ||, if we take the false branch, then the value of the whole<br>
- // expression is that of the RHS expression.<br>
-<br>
- const Expr* Ex = (Op == BO_LAnd && branchTaken) ||<br>
- (Op == BO_LOr && !branchTaken)<br>
- ? B->getRHS() : B->getLHS();<br>
-<br>
- return state->BindExpr(B, UndefinedVal(Ex));<br>
- }<br>
-<br>
- case Stmt::ConditionalOperatorClass: { // ?:<br>
-<br>
- const ConditionalOperator* C = cast<ConditionalOperator>(Terminator);<br>
-<br>
- // For ?, if branchTaken == true then the value is either the LHS or<br>
- // the condition itself. (GNU extension).<br>
-<br>
- const Expr* Ex;<br>
-<br>
- if (branchTaken)<br>
- Ex = C->getLHS() ? C->getLHS() : C->getCond();<br>
- else<br>
- Ex = C->getRHS();<br>
-<br>
- return state->BindExpr(C, UndefinedVal(Ex));<br>
- }<br>
-<br>
- case Stmt::ChooseExprClass: { // ?:<br>
-<br>
- const ChooseExpr* C = cast<ChooseExpr>(Terminator);<br>
-<br>
- const Expr* Ex = branchTaken ? C->getLHS() : C->getRHS();<br>
- return state->BindExpr(C, UndefinedVal(Ex));<br>
- }<br>
- }<br>
-}<br>
-<br>
-/// RecoverCastedSymbol - A helper function for ProcessBranch that is used<br>
-/// to try to recover some path-sensitivity for casts of symbolic<br>
-/// integers that promote their values (which are currently not tracked well).<br>
-/// This function returns the SVal bound to Condition->IgnoreCasts if all the<br>
-// cast(s) did was sign-extend the original value.<br>
-static SVal RecoverCastedSymbol(GRStateManager& StateMgr, const GRState* state,<br>
- const Stmt* Condition, ASTContext& Ctx) {<br>
-<br>
- const Expr *Ex = dyn_cast<Expr>(Condition);<br>
- if (!Ex)<br>
- return UnknownVal();<br>
-<br>
- uint64_t bits = 0;<br>
- bool bitsInit = false;<br>
-<br>
- while (const CastExpr *CE = dyn_cast<CastExpr>(Ex)) {<br>
- QualType T = CE->getType();<br>
-<br>
- if (!T->isIntegerType())<br>
- return UnknownVal();<br>
-<br>
- uint64_t newBits = Ctx.getTypeSize(T);<br>
- if (!bitsInit || newBits < bits) {<br>
- bitsInit = true;<br>
- bits = newBits;<br>
- }<br>
-<br>
- Ex = CE->getSubExpr();<br>
- }<br>
-<br>
- // We reached a non-cast. Is it a symbolic value?<br>
- QualType T = Ex->getType();<br>
-<br>
- if (!bitsInit || !T->isIntegerType() || Ctx.getTypeSize(T) > bits)<br>
- return UnknownVal();<br>
-<br>
- return state->getSVal(Ex);<br>
-}<br>
-<br>
-void ExprEngine::ProcessBranch(const Stmt* Condition, const Stmt* Term,<br>
- BranchNodeBuilder& builder) {<br>
-<br>
- // Check for NULL conditions; e.g. "for(;;)"<br>
- if (!Condition) {<br>
- builder.markInfeasible(false);<br>
- return;<br>
- }<br>
-<br>
- PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),<br>
- Condition->getLocStart(),<br>
- "Error evaluating branch");<br>
-<br>
- for (CheckersOrdered::iterator I=Checkers.begin(),E=Checkers.end();I!=E;++I) {<br>
- void *tag = I->first;<br>
- Checker *checker = I->second;<br>
- checker->VisitBranchCondition(builder, *this, Condition, tag);<br>
- }<br>
-<br>
- // If the branch condition is undefined, return;<br>
- if (!builder.isFeasible(true) && !builder.isFeasible(false))<br>
- return;<br>
-<br>
- const GRState* PrevState = builder.getState();<br>
- SVal X = PrevState->getSVal(Condition);<br>
-<br>
- if (X.isUnknown()) {<br>
- // Give it a chance to recover from unknown.<br>
- if (const Expr *Ex = dyn_cast<Expr>(Condition)) {<br>
- if (Ex->getType()->isIntegerType()) {<br>
- // Try to recover some path-sensitivity. Right now casts of symbolic<br>
- // integers that promote their values are currently not tracked well.<br>
- // If 'Condition' is such an expression, try and recover the<br>
- // underlying value and use that instead.<br>
- SVal recovered = RecoverCastedSymbol(getStateManager(),<br>
- builder.getState(), Condition,<br>
- getContext());<br>
-<br>
- if (!recovered.isUnknown()) {<br>
- X = recovered;<br>
- }<br>
- }<br>
- }<br>
- // If the condition is still unknown, give up.<br>
- if (X.isUnknown()) {<br>
- builder.generateNode(MarkBranch(PrevState, Term, true), true);<br>
- builder.generateNode(MarkBranch(PrevState, Term, false), false);<br>
- return;<br>
- }<br>
- }<br>
-<br>
- DefinedSVal V = cast<DefinedSVal>(X);<br>
-<br>
- // Process the true branch.<br>
- if (builder.isFeasible(true)) {<br>
- if (const GRState *state = PrevState->assume(V, true))<br>
- builder.generateNode(MarkBranch(state, Term, true), true);<br>
- else<br>
- builder.markInfeasible(true);<br>
- }<br>
-<br>
- // Process the false branch.<br>
- if (builder.isFeasible(false)) {<br>
- if (const GRState *state = PrevState->assume(V, false))<br>
- builder.generateNode(MarkBranch(state, Term, false), false);<br>
- else<br>
- builder.markInfeasible(false);<br>
- }<br>
-}<br>
-<br>
-/// ProcessIndirectGoto - Called by CoreEngine. Used to generate successor<br>
-/// nodes by processing the 'effects' of a computed goto jump.<br>
-void ExprEngine::ProcessIndirectGoto(IndirectGotoNodeBuilder& builder) {<br>
-<br>
- const GRState *state = builder.getState();<br>
- SVal V = state->getSVal(builder.getTarget());<br>
-<br>
- // Three possibilities:<br>
- //<br>
- // (1) We know the computed label.<br>
- // (2) The label is NULL (or some other constant), or Undefined.<br>
- // (3) We have no clue about the label. Dispatch to all targets.<br>
- //<br>
-<br>
- typedef IndirectGotoNodeBuilder::iterator iterator;<br>
-<br>
- if (isa<loc::GotoLabel>(V)) {<br>
- const LabelStmt* L = cast<loc::GotoLabel>(V).getLabel();<br>
-<br>
- for (iterator I=builder.begin(), E=builder.end(); I != E; ++I) {<br>
- if (I.getLabel() == L) {<br>
- builder.generateNode(I, state);<br>
- return;<br>
- }<br>
- }<br>
-<br>
- assert (false && "No block with label.");<br>
- return;<br>
- }<br>
-<br>
- if (isa<loc::ConcreteInt>(V) || isa<UndefinedVal>(V)) {<br>
- // Dispatch to the first target and mark it as a sink.<br>
- //ExplodedNode* N = builder.generateNode(builder.begin(), state, true);<br>
- // FIXME: add checker visit.<br>
- // UndefBranches.insert(N);<br>
- return;<br>
- }<br>
-<br>
- // This is really a catch-all. We don't support symbolics yet.<br>
- // FIXME: Implement dispatch for symbolic pointers.<br>
-<br>
- for (iterator I=builder.begin(), E=builder.end(); I != E; ++I)<br>
- builder.generateNode(I, state);<br>
-}<br>
-<br>
-<br>
-void ExprEngine::VisitGuardedExpr(const Expr* Ex, const Expr* L,<br>
- const Expr* R,<br>
- ExplodedNode* Pred, ExplodedNodeSet& Dst) {<br>
-<br>
- assert(Ex == currentStmt &&<br>
- Pred->getLocationContext()->getCFG()->isBlkExpr(Ex));<br>
-<br>
- const GRState* state = GetState(Pred);<br>
- SVal X = state->getSVal(Ex);<br>
-<br>
- assert (X.isUndef());<br>
-<br>
- const Expr *SE = (Expr*) cast<UndefinedVal>(X).getData();<br>
- assert(SE);<br>
- X = state->getSVal(SE);<br>
-<br>
- // Make sure that we invalidate the previous binding.<br>
- MakeNode(Dst, Ex, Pred, state->BindExpr(Ex, X, true));<br>
-}<br>
-<br>
-/// ProcessEndPath - Called by CoreEngine. Used to generate end-of-path<br>
-/// nodes when the control reaches the end of a function.<br>
-void ExprEngine::ProcessEndPath(EndPathNodeBuilder& builder) {<br>
- getTF().evalEndPath(*this, builder);<br>
- StateMgr.EndPath(builder.getState());<br>
- for (CheckersOrdered::iterator I=Checkers.begin(),E=Checkers.end(); I!=E;++I){<br>
- void *tag = I->first;<br>
- Checker *checker = I->second;<br>
- checker->evalEndPath(builder, tag, *this);<br>
- }<br>
-}<br>
-<br>
-/// ProcessSwitch - Called by CoreEngine. Used to generate successor<br>
-/// nodes by processing the 'effects' of a switch statement.<br>
-void ExprEngine::ProcessSwitch(SwitchNodeBuilder& builder) {<br>
- typedef SwitchNodeBuilder::iterator iterator;<br>
- const GRState* state = builder.getState();<br>
- const Expr* CondE = builder.getCondition();<br>
- SVal CondV_untested = state->getSVal(CondE);<br>
-<br>
- if (CondV_untested.isUndef()) {<br>
- //ExplodedNode* N = builder.generateDefaultCaseNode(state, true);<br>
- // FIXME: add checker<br>
- //UndefBranches.insert(N);<br>
-<br>
- return;<br>
- }<br>
- DefinedOrUnknownSVal CondV = cast<DefinedOrUnknownSVal>(CondV_untested);<br>
-<br>
- const GRState *DefaultSt = state;<br>
-<br>
- iterator I = builder.begin(), EI = builder.end();<br>
- bool defaultIsFeasible = I == EI;<br>
-<br>
- for ( ; I != EI; ++I) {<br>
- const CaseStmt* Case = I.getCase();<br>
-<br>
- // Evaluate the LHS of the case value.<br>
- Expr::EvalResult V1;<br>
- bool b = Case->getLHS()->Evaluate(V1, getContext());<br>
-<br>
- // Sanity checks. These go away in Release builds.<br>
- assert(b && V1.Val.isInt() && !V1.HasSideEffects<br>
- && "Case condition must evaluate to an integer constant.");<br>
- (void)b; // silence unused variable warning<br>
- assert(V1.Val.getInt().getBitWidth() ==<br>
- getContext().getTypeSize(CondE->getType()));<br>
-<br>
- // Get the RHS of the case, if it exists.<br>
- Expr::EvalResult V2;<br>
-<br>
- if (const Expr* E = Case->getRHS()) {<br>
- b = E->Evaluate(V2, getContext());<br>
- assert(b && V2.Val.isInt() && !V2.HasSideEffects<br>
- && "Case condition must evaluate to an integer constant.");<br>
- (void)b; // silence unused variable warning<br>
- }<br>
- else<br>
- V2 = V1;<br>
-<br>
- // FIXME: Eventually we should replace the logic below with a range<br>
- // comparison, rather than concretize the values within the range.<br>
- // This should be easy once we have "ranges" for NonLVals.<br>
-<br>
- do {<br>
- nonloc::ConcreteInt CaseVal(getBasicVals().getValue(V1.Val.getInt()));<br>
- DefinedOrUnknownSVal Res = svalBuilder.evalEQ(DefaultSt ? DefaultSt : state,<br>
- CondV, CaseVal);<br>
-<br>
- // Now "assume" that the case matches.<br>
- if (const GRState* stateNew = state->assume(Res, true)) {<br>
- builder.generateCaseStmtNode(I, stateNew);<br>
-<br>
- // If CondV evaluates to a constant, then we know that this<br>
- // is the *only* case that we can take, so stop evaluating the<br>
- // others.<br>
- if (isa<nonloc::ConcreteInt>(CondV))<br>
- return;<br>
- }<br>
-<br>
- // Now "assume" that the case doesn't match. Add this state<br>
- // to the default state (if it is feasible).<br>
- if (DefaultSt) {<br>
- if (const GRState *stateNew = DefaultSt->assume(Res, false)) {<br>
- defaultIsFeasible = true;<br>
- DefaultSt = stateNew;<br>
- }<br>
- else {<br>
- defaultIsFeasible = false;<br>
- DefaultSt = NULL;<br>
- }<br>
- }<br>
-<br>
- // Concretize the next value in the range.<br>
- if (V1.Val.getInt() == V2.Val.getInt())<br>
- break;<br>
-<br>
- ++V1.Val.getInt();<br>
- assert (V1.Val.getInt() <= V2.Val.getInt());<br>
-<br>
- } while (true);<br>
- }<br>
-<br>
- if (!defaultIsFeasible)<br>
- return;<br>
-<br>
- // If we have switch(enum value), the default branch is not<br>
- // feasible if all of the enum constants not covered by 'case:' statements<br>
- // are not feasible values for the switch condition.<br>
- //<br>
- // Note that this isn't as accurate as it could be. Even if there isn't<br>
- // a case for a particular enum value as long as that enum value isn't<br>
- // feasible then it shouldn't be considered for making 'default:' reachable.<br>
- const SwitchStmt *SS = builder.getSwitch();<br>
- const Expr *CondExpr = SS->getCond()->IgnoreParenImpCasts();<br>
- if (CondExpr->getType()->getAs<EnumType>()) {<br>
- if (SS->isAllEnumCasesCovered())<br>
- return;<br>
- }<br>
-<br>
- builder.generateDefaultCaseNode(DefaultSt);<br>
-}<br>
-<br>
-void ExprEngine::ProcessCallEnter(CallEnterNodeBuilder &B) {<br>
- const GRState *state = B.getState()->EnterStackFrame(B.getCalleeContext());<br>
- B.generateNode(state);<br>
-}<br>
-<br>
-void ExprEngine::ProcessCallExit(CallExitNodeBuilder &B) {<br>
- const GRState *state = B.getState();<br>
- const ExplodedNode *Pred = B.getPredecessor();<br>
- const StackFrameContext *calleeCtx =<br>
- cast<StackFrameContext>(Pred->getLocationContext());<br>
- const Stmt *CE = calleeCtx->getCallSite();<br>
-<br>
- // If the callee returns an expression, bind its value to CallExpr.<br>
- const Stmt *ReturnedExpr = state->get<ReturnExpr>();<br>
- if (ReturnedExpr) {<br>
- SVal RetVal = state->getSVal(ReturnedExpr);<br>
- state = state->BindExpr(CE, RetVal);<br>
- // Clear the return expr GDM.<br>
- state = state->remove<ReturnExpr>();<br>
- }<br>
-<br>
- // Bind the constructed object value to CXXConstructExpr.<br>
- if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(CE)) {<br>
- const CXXThisRegion *ThisR =<br>
- getCXXThisRegion(CCE->getConstructor()->getParent(), calleeCtx);<br>
-<br>
- SVal ThisV = state->getSVal(ThisR);<br>
- // Always bind the region to the CXXConstructExpr.<br>
- state = state->BindExpr(CCE, ThisV);<br>
- }<br>
-<br>
- B.generateNode(state);<br>
-}<br>
-<br>
-//===----------------------------------------------------------------------===//<br>
-// Transfer functions: logical operations ('&&', '||').<br>
-//===----------------------------------------------------------------------===//<br>
-<br>
-void ExprEngine::VisitLogicalExpr(const BinaryOperator* B, ExplodedNode* Pred,<br>
- ExplodedNodeSet& Dst) {<br>
-<br>
- assert(B->getOpcode() == BO_LAnd ||<br>
- B->getOpcode() == BO_LOr);<br>
-<br>
- assert(B==currentStmt && Pred->getLocationContext()->getCFG()->isBlkExpr(B));<br>
-<br>
- const GRState* state = GetState(Pred);<br>
- SVal X = state->getSVal(B);<br>
- assert(X.isUndef());<br>
-<br>
- const Expr *Ex = (const Expr*) cast<UndefinedVal>(X).getData();<br>
- assert(Ex);<br>
-<br>
- if (Ex == B->getRHS()) {<br>
- X = state->getSVal(Ex);<br>
-<br>
- // Handle undefined values.<br>
- if (X.isUndef()) {<br>
- MakeNode(Dst, B, Pred, state->BindExpr(B, X));<br>
- return;<br>
- }<br>
-<br>
- DefinedOrUnknownSVal XD = cast<DefinedOrUnknownSVal>(X);<br>
-<br>
- // We took the RHS. Because the value of the '&&' or '||' expression must<br>
- // evaluate to 0 or 1, we must assume the value of the RHS evaluates to 0<br>
- // or 1. Alternatively, we could take a lazy approach, and calculate this<br>
- // value later when necessary. We don't have the machinery in place for<br>
- // this right now, and since most logical expressions are used for branches,<br>
- // the payoff is not likely to be large. Instead, we do eager evaluation.<br>
- if (const GRState *newState = state->assume(XD, true))<br>
- MakeNode(Dst, B, Pred,<br>
- newState->BindExpr(B, svalBuilder.makeIntVal(1U, B->getType())));<br>
-<br>
- if (const GRState *newState = state->assume(XD, false))<br>
- MakeNode(Dst, B, Pred,<br>
- newState->BindExpr(B, svalBuilder.makeIntVal(0U, B->getType())));<br>
- }<br>
- else {<br>
- // We took the LHS expression. Depending on whether we are '&&' or<br>
- // '||' we know what the value of the expression is via properties of<br>
- // the short-circuiting.<br>
- X = svalBuilder.makeIntVal(B->getOpcode() == BO_LAnd ? 0U : 1U,<br>
- B->getType());<br>
- MakeNode(Dst, B, Pred, state->BindExpr(B, X));<br>
- }<br>
-}<br>
-<br>
-//===----------------------------------------------------------------------===//<br>
-// Transfer functions: Loads and stores.<br>
-//===----------------------------------------------------------------------===//<br>
-<br>
-void ExprEngine::VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred,<br>
- ExplodedNodeSet &Dst) {<br>
-<br>
- ExplodedNodeSet Tmp;<br>
-<br>
- CanQualType T = getContext().getCanonicalType(BE->getType());<br>
- SVal V = svalBuilder.getBlockPointer(BE->getBlockDecl(), T,<br>
- Pred->getLocationContext());<br>
-<br>
- MakeNode(Tmp, BE, Pred, GetState(Pred)->BindExpr(BE, V),<br>
- ProgramPoint::PostLValueKind);<br>
-<br>
- // Post-visit the BlockExpr.<br>
- CheckerVisit(BE, Dst, Tmp, PostVisitStmtCallback);<br>
-}<br>
-<br>
-void ExprEngine::VisitCommonDeclRefExpr(const Expr *Ex, const NamedDecl *D,<br>
- ExplodedNode *Pred,<br>
- ExplodedNodeSet &Dst) {<br>
- const GRState *state = GetState(Pred);<br>
-<br>
- if (const VarDecl* VD = dyn_cast<VarDecl>(D)) {<br>
- assert(Ex->isLValue());<br>
- SVal V = state->getLValue(VD, Pred->getLocationContext());<br>
-<br>
- // For references, the 'lvalue' is the pointer address stored in the<br>
- // reference region.<br>
- if (VD->getType()->isReferenceType()) {<br>
- if (const MemRegion *R = V.getAsRegion())<br>
- V = state->getSVal(R);<br>
- else<br>
- V = UnknownVal();<br>
- }<br>
-<br>
- MakeNode(Dst, Ex, Pred, state->BindExpr(Ex, V),<br>
- ProgramPoint::PostLValueKind);<br>
- return;<br>
- }<br>
- if (const EnumConstantDecl* ED = dyn_cast<EnumConstantDecl>(D)) {<br>
- assert(!Ex->isLValue());<br>
- SVal V = svalBuilder.makeIntVal(ED->getInitVal());<br>
- MakeNode(Dst, Ex, Pred, state->BindExpr(Ex, V));<br>
- return;<br>
- }<br>
- if (const FunctionDecl* FD = dyn_cast<FunctionDecl>(D)) {<br>
- SVal V = svalBuilder.getFunctionPointer(FD);<br>
- MakeNode(Dst, Ex, Pred, state->BindExpr(Ex, V),<br>
- ProgramPoint::PostLValueKind);<br>
- return;<br>
- }<br>
- assert (false &&<br>
- "ValueDecl support for this ValueDecl not implemented.");<br>
-}<br>
-<br>
-/// VisitArraySubscriptExpr - Transfer function for array accesses<br>
-void ExprEngine::VisitLvalArraySubscriptExpr(const ArraySubscriptExpr* A,<br>
- ExplodedNode* Pred,<br>
- ExplodedNodeSet& Dst){<br>
-<br>
- const Expr* Base = A->getBase()->IgnoreParens();<br>
- const Expr* Idx = A->getIdx()->IgnoreParens();<br>
-<br>
- // Evaluate the base.<br>
- ExplodedNodeSet Tmp;<br>
- Visit(Base, Pred, Tmp);<br>
-<br>
- for (ExplodedNodeSet::iterator I1=Tmp.begin(), E1=Tmp.end(); I1!=E1; ++I1) {<br>
- ExplodedNodeSet Tmp2;<br>
- Visit(Idx, *I1, Tmp2); // Evaluate the index.<br>
- ExplodedNodeSet Tmp3;<br>
- CheckerVisit(A, Tmp3, Tmp2, PreVisitStmtCallback);<br>
-<br>
- for (ExplodedNodeSet::iterator I2=Tmp3.begin(),E2=Tmp3.end();I2!=E2; ++I2) {<br>
- const GRState* state = GetState(*I2);<br>
- SVal V = state->getLValue(A->getType(), state->getSVal(Idx),<br>
- state->getSVal(Base));<br>
- assert(A->isLValue());<br>
- MakeNode(Dst, A, *I2, state->BindExpr(A, V), ProgramPoint::PostLValueKind);<br>
- }<br>
- }<br>
-}<br>
-<br>
-/// VisitMemberExpr - Transfer function for member expressions.<br>
-void ExprEngine::VisitMemberExpr(const MemberExpr* M, ExplodedNode* Pred,<br>
- ExplodedNodeSet& Dst) {<br>
-<br>
- Expr *baseExpr = M->getBase()->IgnoreParens();<br>
- ExplodedNodeSet dstBase;<br>
- Visit(baseExpr, Pred, dstBase);<br>
-<br>
- FieldDecl *field = dyn_cast<FieldDecl>(M->getMemberDecl());<br>
- if (!field) // FIXME: skipping member expressions for non-fields<br>
- return;<br>
-<br>
- for (ExplodedNodeSet::iterator I = dstBase.begin(), E = dstBase.end();<br>
- I != E; ++I) {<br>
- const GRState* state = GetState(*I);<br>
- SVal baseExprVal = state->getSVal(baseExpr);<br>
- if (isa<nonloc::LazyCompoundVal>(baseExprVal) ||<br>
- isa<nonloc::CompoundVal>(baseExprVal)) {<br>
- MakeNode(Dst, M, *I, state->BindExpr(M, UnknownVal()));<br>
- continue;<br>
- }<br>
-<br>
- // FIXME: Should we insert some assumption logic in here to determine<br>
- // if "Base" is a valid piece of memory? Before we put this assumption<br>
- // later when using FieldOffset lvals (which we no longer have).<br>
-<br>
- // For all other cases, compute an lvalue.<br>
- SVal L = state->getLValue(field, baseExprVal);<br>
- if (M->isLValue())<br>
- MakeNode(Dst, M, *I, state->BindExpr(M, L), ProgramPoint::PostLValueKind);<br>
- else<br>
- evalLoad(Dst, M, *I, state, L);<br>
- }<br>
-}<br>
-<br>
-/// evalBind - Handle the semantics of binding a value to a specific location.<br>
-/// This method is used by evalStore and (soon) VisitDeclStmt, and others.<br>
-void ExprEngine::evalBind(ExplodedNodeSet& Dst, const Stmt* StoreE,<br>
- ExplodedNode* Pred, const GRState* state,<br>
- SVal location, SVal Val, bool atDeclInit) {<br>
-<br>
-<br>
- // Do a previsit of the bind.<br>
- ExplodedNodeSet CheckedSet, Src;<br>
- Src.Add(Pred);<br>
- CheckerVisitBind(StoreE, CheckedSet, Src, location, Val, true);<br>
-<br>
- for (ExplodedNodeSet::iterator I = CheckedSet.begin(), E = CheckedSet.end();<br>
- I!=E; ++I) {<br>
-<br>
- if (Pred != *I)<br>
- state = GetState(*I);<br>
-<br>
- const GRState* newState = 0;<br>
-<br>
- if (atDeclInit) {<br>
- const VarRegion *VR =<br>
- cast<VarRegion>(cast<loc::MemRegionVal>(location).getRegion());<br>
-<br>
- newState = state->bindDecl(VR, Val);<br>
- }<br>
- else {<br>
- if (location.isUnknown()) {<br>
- // We know that the new state will be the same as the old state since<br>
- // the location of the binding is "unknown". Consequently, there<br>
- // is no reason to just create a new node.<br>
- newState = state;<br>
- }<br>
- else {<br>
- // We are binding to a value other than 'unknown'. Perform the binding<br>
- // using the StoreManager.<br>
- newState = state->bindLoc(cast<Loc>(location), Val);<br>
- }<br>
- }<br>
-<br>
- // The next thing to do is check if the TransferFuncs object wants to<br>
- // update the state based on the new binding. If the GRTransferFunc object<br>
- // doesn't do anything, just auto-propagate the current state.<br>
-<br>
- // NOTE: We use 'AssignE' for the location of the PostStore if 'AssignE'<br>
- // is non-NULL. Checkers typically care about<br>
-<br>
- StmtNodeBuilderRef BuilderRef(Dst, *Builder, *this, *I, newState, StoreE,<br>
- true);<br>
-<br>
- getTF().evalBind(BuilderRef, location, Val);<br>
- }<br>
-}<br>
-<br>
-/// evalStore - Handle the semantics of a store via an assignment.<br>
-/// @param Dst The node set to store generated state nodes<br>
-/// @param AssignE The assignment expression if the store happens in an<br>
-/// assignment.<br>
-/// @param LocatioinE The location expression that is stored to.<br>
-/// @param state The current simulation state<br>
-/// @param location The location to store the value<br>
-/// @param Val The value to be stored<br>
-void ExprEngine::evalStore(ExplodedNodeSet& Dst, const Expr *AssignE,<br>
- const Expr* LocationE,<br>
- ExplodedNode* Pred,<br>
- const GRState* state, SVal location, SVal Val,<br>
- const void *tag) {<br>
-<br>
- assert(Builder && "StmtNodeBuilder must be defined.");<br>
-<br>
- // Evaluate the location (checks for bad dereferences).<br>
- ExplodedNodeSet Tmp;<br>
- evalLocation(Tmp, LocationE, Pred, state, location, tag, false);<br>
-<br>
- if (Tmp.empty())<br>
- return;<br>
-<br>
- assert(!location.isUndef());<br>
-<br>
- SaveAndRestore<ProgramPoint::Kind> OldSPointKind(Builder->PointKind,<br>
- ProgramPoint::PostStoreKind);<br>
- SaveAndRestore<const void*> OldTag(Builder->Tag, tag);<br>
-<br>
- // Proceed with the store. We use AssignE as the anchor for the PostStore<br>
- // ProgramPoint if it is non-NULL, and LocationE otherwise.<br>
- const Expr *StoreE = AssignE ? AssignE : LocationE;<br>
-<br>
- for (ExplodedNodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI!=NE; ++NI)<br>
- evalBind(Dst, StoreE, *NI, GetState(*NI), location, Val);<br>
-}<br>
-<br>
-void ExprEngine::evalLoad(ExplodedNodeSet& Dst, const Expr *Ex,<br>
- ExplodedNode* Pred,<br>
- const GRState* state, SVal location,<br>
- const void *tag, QualType LoadTy) {<br>
- assert(!isa<NonLoc>(location) && "location cannot be a NonLoc.");<br>
-<br>
- // Are we loading from a region? This actually results in two loads; one<br>
- // to fetch the address of the referenced value and one to fetch the<br>
- // referenced value.<br>
- if (const TypedRegion *TR =<br>
- dyn_cast_or_null<TypedRegion>(location.getAsRegion())) {<br>
-<br>
- QualType ValTy = TR->getValueType();<br>
- if (const ReferenceType *RT = ValTy->getAs<ReferenceType>()) {<br>
- static int loadReferenceTag = 0;<br>
- ExplodedNodeSet Tmp;<br>
- evalLoadCommon(Tmp, Ex, Pred, state, location, &loadReferenceTag,<br>
- getContext().getPointerType(RT->getPointeeType()));<br>
-<br>
- // Perform the load from the referenced value.<br>
- for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end() ; I!=E; ++I) {<br>
- state = GetState(*I);<br>
- location = state->getSVal(Ex);<br>
- evalLoadCommon(Dst, Ex, *I, state, location, tag, LoadTy);<br>
- }<br>
- return;<br>
- }<br>
- }<br>
-<br>
- evalLoadCommon(Dst, Ex, Pred, state, location, tag, LoadTy);<br>
-}<br>
-<br>
-void ExprEngine::evalLoadCommon(ExplodedNodeSet& Dst, const Expr *Ex,<br>
- ExplodedNode* Pred,<br>
- const GRState* state, SVal location,<br>
- const void *tag, QualType LoadTy) {<br>
-<br>
- // Evaluate the location (checks for bad dereferences).<br>
- ExplodedNodeSet Tmp;<br>
- evalLocation(Tmp, Ex, Pred, state, location, tag, true);<br>
-<br>
- if (Tmp.empty())<br>
- return;<br>
-<br>
- assert(!location.isUndef());<br>
-<br>
- SaveAndRestore<ProgramPoint::Kind> OldSPointKind(Builder->PointKind);<br>
- SaveAndRestore<const void*> OldTag(Builder->Tag);<br>
-<br>
- // Proceed with the load.<br>
- for (ExplodedNodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI!=NE; ++NI) {<br>
- state = GetState(*NI);<br>
-<br>
- if (location.isUnknown()) {<br>
- // This is important. We must nuke the old binding.<br>
- MakeNode(Dst, Ex, *NI, state->BindExpr(Ex, UnknownVal()),<br>
- ProgramPoint::PostLoadKind, tag);<br>
- }<br>
- else {<br>
- if (LoadTy.isNull())<br>
- LoadTy = Ex->getType();<br>
- SVal V = state->getSVal(cast<Loc>(location), LoadTy);<br>
- MakeNode(Dst, Ex, *NI, state->bindExprAndLocation(Ex, location, V),<br>
- ProgramPoint::PostLoadKind, tag);<br>
- }<br>
- }<br>
-}<br>
-<br>
-void ExprEngine::evalLocation(ExplodedNodeSet &Dst, const Stmt *S,<br>
- ExplodedNode* Pred,<br>
- const GRState* state, SVal location,<br>
- const void *tag, bool isLoad) {<br>
- // Early checks for performance reason.<br>
- if (location.isUnknown() || Checkers.empty()) {<br>
- Dst.Add(Pred);<br>
- return;<br>
- }<br>
-<br>
- ExplodedNodeSet Src, Tmp;<br>
- Src.Add(Pred);<br>
- ExplodedNodeSet *PrevSet = &Src;<br>
-<br>
- for (CheckersOrdered::iterator I=Checkers.begin(),E=Checkers.end(); I!=E; ++I)<br>
- {<br>
- ExplodedNodeSet *CurrSet = 0;<br>
- if (I+1 == E)<br>
- CurrSet = &Dst;<br>
- else {<br>
- CurrSet = (PrevSet == &Tmp) ? &Src : &Tmp;<br>
- CurrSet->clear();<br>
- }<br>
-<br>
- void *tag = I->first;<br>
- Checker *checker = I->second;<br>
-<br>
- for (ExplodedNodeSet::iterator NI = PrevSet->begin(), NE = PrevSet->end();<br>
- NI != NE; ++NI) {<br>
- // Use the 'state' argument only when the predecessor node is the<br>
- // same as Pred. This allows us to catch updates to the state.<br>
- checker->GR_visitLocation(*CurrSet, *Builder, *this, S, *NI,<br>
- *NI == Pred ? state : GetState(*NI),<br>
- location, tag, isLoad);<br>
- }<br>
-<br>
- // Update which NodeSet is the current one.<br>
- PrevSet = CurrSet;<br>
- }<br>
-}<br>
-<br>
-bool ExprEngine::InlineCall(ExplodedNodeSet &Dst, const CallExpr *CE,<br>
- ExplodedNode *Pred) {<br>
- const GRState *state = GetState(Pred);<br>
- const Expr *Callee = CE->getCallee();<br>
- SVal L = state->getSVal(Callee);<br>
-<br>
- const FunctionDecl *FD = L.getAsFunctionDecl();<br>
- if (!FD)<br>
- return false;<br>
-<br>
- // Check if the function definition is in the same translation unit.<br>
- if (FD->hasBody(FD)) {<br>
- const StackFrameContext *stackFrame =<br>
- AMgr.getStackFrame(AMgr.getAnalysisContext(FD),<br>
- Pred->getLocationContext(),<br>
- CE, Builder->getBlock(), Builder->getIndex());<br>
- // Now we have the definition of the callee, create a CallEnter node.<br>
- CallEnter Loc(CE, stackFrame, Pred->getLocationContext());<br>
-<br>
- ExplodedNode *N = Builder->generateNode(Loc, state, Pred);<br>
- Dst.Add(N);<br>
- return true;<br>
- }<br>
-<br>
- // Check if we can find the function definition in other translation units.<br>
- if (AMgr.hasIndexer()) {<br>
- AnalysisContext *C = AMgr.getAnalysisContextInAnotherTU(FD);<br>
- if (C == 0)<br>
- return false;<br>
- const StackFrameContext *stackFrame =<br>
- AMgr.getStackFrame(C, Pred->getLocationContext(),<br>
- CE, Builder->getBlock(), Builder->getIndex());<br>
- CallEnter Loc(CE, stackFrame, Pred->getLocationContext());<br>
- ExplodedNode *N = Builder->generateNode(Loc, state, Pred);<br>
- Dst.Add(N);<br>
- return true;<br>
- }<br>
-<br>
- return false;<br>
-}<br>
-<br>
-void ExprEngine::VisitCall(const CallExpr* CE, ExplodedNode* Pred,<br>
- CallExpr::const_arg_iterator AI,<br>
- CallExpr::const_arg_iterator AE,<br>
- ExplodedNodeSet& Dst) {<br>
-<br>
- // Determine the type of function we're calling (if available).<br>
- const FunctionProtoType *Proto = NULL;<br>
- QualType FnType = CE->getCallee()->IgnoreParens()->getType();<br>
- if (const PointerType *FnTypePtr = FnType->getAs<PointerType>())<br>
- Proto = FnTypePtr->getPointeeType()->getAs<FunctionProtoType>();<br>
-<br>
- // Evaluate the arguments.<br>
- ExplodedNodeSet ArgsEvaluated;<br>
- evalArguments(CE->arg_begin(), CE->arg_end(), Proto, Pred, ArgsEvaluated);<br>
-<br>
- // Now process the call itself.<br>
- ExplodedNodeSet DstTmp;<br>
- const Expr* Callee = CE->getCallee()->IgnoreParens();<br>
-<br>
- for (ExplodedNodeSet::iterator NI=ArgsEvaluated.begin(),<br>
- NE=ArgsEvaluated.end(); NI != NE; ++NI) {<br>
- // Evaluate the callee.<br>
- ExplodedNodeSet DstTmp2;<br>
- Visit(Callee, *NI, DstTmp2);<br>
- // Perform the previsit of the CallExpr, storing the results in DstTmp.<br>
- CheckerVisit(CE, DstTmp, DstTmp2, PreVisitStmtCallback);<br>
- }<br>
-<br>
- // Finally, evaluate the function call. We try each of the checkers<br>
- // to see if the can evaluate the function call.<br>
- ExplodedNodeSet DstTmp3;<br>
-<br>
- for (ExplodedNodeSet::iterator DI = DstTmp.begin(), DE = DstTmp.end();<br>
- DI != DE; ++DI) {<br>
-<br>
- const GRState* state = GetState(*DI);<br>
- SVal L = state->getSVal(Callee);<br>
-<br>
- // FIXME: Add support for symbolic function calls (calls involving<br>
- // function pointer values that are symbolic).<br>
- SaveAndRestore<bool> OldSink(Builder->BuildSinks);<br>
- ExplodedNodeSet DstChecker;<br>
-<br>
- // If the callee is processed by a checker, skip the rest logic.<br>
- if (CheckerEvalCall(CE, DstChecker, *DI))<br>
- DstTmp3.insert(DstChecker);<br>
- else if (AMgr.shouldInlineCall() && InlineCall(Dst, CE, *DI)) {<br>
- // Callee is inlined. We shouldn't do post call checking.<br>
- return;<br>
- }<br>
- else {<br>
- for (ExplodedNodeSet::iterator DI_Checker = DstChecker.begin(),<br>
- DE_Checker = DstChecker.end();<br>
- DI_Checker != DE_Checker; ++DI_Checker) {<br>
-<br>
- // Dispatch to the plug-in transfer function.<br>
- unsigned oldSize = DstTmp3.size();<br>
- SaveOr OldHasGen(Builder->HasGeneratedNode);<br>
- Pred = *DI_Checker;<br>
-<br>
- // Dispatch to transfer function logic to handle the call itself.<br>
- // FIXME: Allow us to chain together transfer functions.<br>
- assert(Builder && "StmtNodeBuilder must be defined.");<br>
- getTF().evalCall(DstTmp3, *this, *Builder, CE, L, Pred);<br>
-<br>
- // Handle the case where no nodes where generated. Auto-generate that<br>
- // contains the updated state if we aren't generating sinks.<br>
- if (!Builder->BuildSinks && DstTmp3.size() == oldSize &&<br>
- !Builder->HasGeneratedNode)<br>
- MakeNode(DstTmp3, CE, Pred, state);<br>
- }<br>
- }<br>
- }<br>
-<br>
- // Finally, perform the post-condition check of the CallExpr and store<br>
- // the created nodes in 'Dst'.<br>
- CheckerVisit(CE, Dst, DstTmp3, PostVisitStmtCallback);<br>
-}<br>
-<br>
-//===----------------------------------------------------------------------===//<br>
-// Transfer function: Objective-C ivar references.<br>
-//===----------------------------------------------------------------------===//<br>
-<br>
-static std::pair<const void*,const void*> EagerlyAssumeTag<br>
- = std::pair<const void*,const void*>(&EagerlyAssumeTag,static_cast<void*>(0));<br>
-<br>
-void ExprEngine::evalEagerlyAssume(ExplodedNodeSet &Dst, ExplodedNodeSet &Src,<br>
- const Expr *Ex) {<br>
- for (ExplodedNodeSet::iterator I=Src.begin(), E=Src.end(); I!=E; ++I) {<br>
- ExplodedNode *Pred = *I;<br>
-<br>
- // Test if the previous node was as the same expression. This can happen<br>
- // when the expression fails to evaluate to anything meaningful and<br>
- // (as an optimization) we don't generate a node.<br>
- ProgramPoint P = Pred->getLocation();<br>
- if (!isa<PostStmt>(P) || cast<PostStmt>(P).getStmt() != Ex) {<br>
- Dst.Add(Pred);<br>
- continue;<br>
- }<br>
-<br>
- const GRState* state = GetState(Pred);<br>
- SVal V = state->getSVal(Ex);<br>
- if (nonloc::SymExprVal *SEV = dyn_cast<nonloc::SymExprVal>(&V)) {<br>
- // First assume that the condition is true.<br>
- if (const GRState *stateTrue = state->assume(*SEV, true)) {<br>
- stateTrue = stateTrue->BindExpr(Ex,<br>
- svalBuilder.makeIntVal(1U, Ex->getType()));<br>
- Dst.Add(Builder->generateNode(PostStmtCustom(Ex,<br>
- &EagerlyAssumeTag, Pred->getLocationContext()),<br>
- stateTrue, Pred));<br>
- }<br>
-<br>
- // Next, assume that the condition is false.<br>
- if (const GRState *stateFalse = state->assume(*SEV, false)) {<br>
- stateFalse = stateFalse->BindExpr(Ex,<br>
- svalBuilder.makeIntVal(0U, Ex->getType()));<br>
- Dst.Add(Builder->generateNode(PostStmtCustom(Ex, &EagerlyAssumeTag,<br>
- Pred->getLocationContext()),<br>
- stateFalse, Pred));<br>
- }<br>
- }<br>
- else<br>
- Dst.Add(Pred);<br>
- }<br>
-}<br>
-<br>
-//===----------------------------------------------------------------------===//<br>
-// Transfer function: Objective-C @synchronized.<br>
-//===----------------------------------------------------------------------===//<br>
-<br>
-void ExprEngine::VisitObjCAtSynchronizedStmt(const ObjCAtSynchronizedStmt *S,<br>
- ExplodedNode *Pred,<br>
- ExplodedNodeSet &Dst) {<br>
-<br>
- // The mutex expression is a CFGElement, so we don't need to explicitly<br>
- // visit it since it will already be processed.<br>
-<br>
- // Pre-visit the ObjCAtSynchronizedStmt.<br>
- ExplodedNodeSet Tmp;<br>
- Tmp.Add(Pred);<br>
- CheckerVisit(S, Dst, Tmp, PreVisitStmtCallback);<br>
-}<br>
-<br>
-//===----------------------------------------------------------------------===//<br>
-// Transfer function: Objective-C ivar references.<br>
-//===----------------------------------------------------------------------===//<br>
-<br>
-void ExprEngine::VisitLvalObjCIvarRefExpr(const ObjCIvarRefExpr* Ex,<br>
- ExplodedNode* Pred,<br>
- ExplodedNodeSet& Dst) {<br>
-<br>
- // Visit the base expression, which is needed for computing the lvalue<br>
- // of the ivar.<br>
- ExplodedNodeSet dstBase;<br>
- const Expr *baseExpr = Ex->getBase();<br>
- Visit(baseExpr, Pred, dstBase);<br>
-<br>
- // Using the base, compute the lvalue of the instance variable.<br>
- for (ExplodedNodeSet::iterator I = dstBase.begin(), E = dstBase.end();<br>
- I!=E; ++I) {<br>
- ExplodedNode *nodeBase = *I;<br>
- const GRState *state = GetState(nodeBase);<br>
- SVal baseVal = state->getSVal(baseExpr);<br>
- SVal location = state->getLValue(Ex->getDecl(), baseVal);<br>
- MakeNode(Dst, Ex, *I, state->BindExpr(Ex, location));<br>
- }<br>
-}<br>
-<br>
-//===----------------------------------------------------------------------===//<br>
-// Transfer function: Objective-C fast enumeration 'for' statements.<br>
-//===----------------------------------------------------------------------===//<br>
-<br>
-void ExprEngine::VisitObjCForCollectionStmt(const ObjCForCollectionStmt* S,<br>
- ExplodedNode* Pred, ExplodedNodeSet& Dst) {<br>
-<br>
- // ObjCForCollectionStmts are processed in two places. This method<br>
- // handles the case where an ObjCForCollectionStmt* occurs as one of the<br>
- // statements within a basic block. This transfer function does two things:<br>
- //<br>
- // (1) binds the next container value to 'element'. This creates a new<br>
- // node in the ExplodedGraph.<br>
- //<br>
- // (2) binds the value 0/1 to the ObjCForCollectionStmt* itself, indicating<br>
- // whether or not the container has any more elements. This value<br>
- // will be tested in ProcessBranch. We need to explicitly bind<br>
- // this value because a container can contain nil elements.<br>
- //<br>
- // FIXME: Eventually this logic should actually do dispatches to<br>
- // 'countByEnumeratingWithState:objects:count:' (NSFastEnumeration).<br>
- // This will require simulating a temporary NSFastEnumerationState, either<br>
- // through an SVal or through the use of MemRegions. This value can<br>
- // be affixed to the ObjCForCollectionStmt* instead of 0/1; when the loop<br>
- // terminates we reclaim the temporary (it goes out of scope) and we<br>
- // we can test if the SVal is 0 or if the MemRegion is null (depending<br>
- // on what approach we take).<br>
- //<br>
- // For now: simulate (1) by assigning either a symbol or nil if the<br>
- // container is empty. Thus this transfer function will by default<br>
- // result in state splitting.<br>
-<br>
- const Stmt* elem = S->getElement();<br>
- SVal ElementV;<br>
-<br>
- if (const DeclStmt* DS = dyn_cast<DeclStmt>(elem)) {<br>
- const VarDecl* ElemD = cast<VarDecl>(DS->getSingleDecl());<br>
- assert (ElemD->getInit() == 0);<br>
- ElementV = GetState(Pred)->getLValue(ElemD, Pred->getLocationContext());<br>
- VisitObjCForCollectionStmtAux(S, Pred, Dst, ElementV);<br>
- return;<br>
- }<br>
-<br>
- ExplodedNodeSet Tmp;<br>
- Visit(cast<Expr>(elem), Pred, Tmp);<br>
- for (ExplodedNodeSet::iterator I = Tmp.begin(), E = Tmp.end(); I!=E; ++I) {<br>
- const GRState* state = GetState(*I);<br>
- VisitObjCForCollectionStmtAux(S, *I, Dst, state->getSVal(elem));<br>
- }<br>
-}<br>
-<br>
-void ExprEngine::VisitObjCForCollectionStmtAux(const ObjCForCollectionStmt* S,<br>
- ExplodedNode* Pred, ExplodedNodeSet& Dst,<br>
- SVal ElementV) {<br>
-<br>
- // Check if the location we are writing back to is a null pointer.<br>
- const Stmt* elem = S->getElement();<br>
- ExplodedNodeSet Tmp;<br>
- evalLocation(Tmp, elem, Pred, GetState(Pred), ElementV, NULL, false);<br>
-<br>
- if (Tmp.empty())<br>
- return;<br>
-<br>
- for (ExplodedNodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI!=NE; ++NI) {<br>
- Pred = *NI;<br>
- const GRState *state = GetState(Pred);<br>
-<br>
- // Handle the case where the container still has elements.<br>
- SVal TrueV = svalBuilder.makeTruthVal(1);<br>
- const GRState *hasElems = state->BindExpr(S, TrueV);<br>
-<br>
- // Handle the case where the container has no elements.<br>
- SVal FalseV = svalBuilder.makeTruthVal(0);<br>
- const GRState *noElems = state->BindExpr(S, FalseV);<br>
-<br>
- if (loc::MemRegionVal* MV = dyn_cast<loc::MemRegionVal>(&ElementV))<br>
- if (const TypedRegion* R = dyn_cast<TypedRegion>(MV->getRegion())) {<br>
- // FIXME: The proper thing to do is to really iterate over the<br>
- // container. We will do this with dispatch logic to the store.<br>
- // For now, just 'conjure' up a symbolic value.<br>
- QualType T = R->getValueType();<br>
- assert(Loc::IsLocType(T));<br>
- unsigned Count = Builder->getCurrentBlockCount();<br>
- SymbolRef Sym = SymMgr.getConjuredSymbol(elem, T, Count);<br>
- SVal V = svalBuilder.makeLoc(Sym);<br>
- hasElems = hasElems->bindLoc(ElementV, V);<br>
-<br>
- // Bind the location to 'nil' on the false branch.<br>
- SVal nilV = svalBuilder.makeIntVal(0, T);<br>
- noElems = noElems->bindLoc(ElementV, nilV);<br>
- }<br>
-<br>
- // Create the new nodes.<br>
- MakeNode(Dst, S, Pred, hasElems);<br>
- MakeNode(Dst, S, Pred, noElems);<br>
- }<br>
-}<br>
-<br>
-//===----------------------------------------------------------------------===//<br>
-// Transfer function: Objective-C message expressions.<br>
-//===----------------------------------------------------------------------===//<br>
-<br>
-namespace {<br>
-class ObjCMsgWLItem {<br>
-public:<br>
- ObjCMessageExpr::const_arg_iterator I;<br>
- ExplodedNode *N;<br>
-<br>
- ObjCMsgWLItem(const ObjCMessageExpr::const_arg_iterator &i, ExplodedNode *n)<br>
- : I(i), N(n) {}<br>
-};<br>
-} // end anonymous namespace<br>
-<br>
-void ExprEngine::VisitObjCMessageExpr(const ObjCMessageExpr* ME,<br>
- ExplodedNode* Pred,<br>
- ExplodedNodeSet& Dst){<br>
-<br>
- // Create a worklist to process both the arguments.<br>
- llvm::SmallVector<ObjCMsgWLItem, 20> WL;<br>
-<br>
- // But first evaluate the receiver (if any).<br>
- ObjCMessageExpr::const_arg_iterator AI = ME->arg_begin(), AE = ME->arg_end();<br>
- if (const Expr *Receiver = ME->getInstanceReceiver()) {<br>
- ExplodedNodeSet Tmp;<br>
- Visit(Receiver, Pred, Tmp);<br>
-<br>
- if (Tmp.empty())<br>
- return;<br>
-<br>
- for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I)<br>
- WL.push_back(ObjCMsgWLItem(AI, *I));<br>
- }<br>
- else<br>
- WL.push_back(ObjCMsgWLItem(AI, Pred));<br>
-<br>
- // Evaluate the arguments.<br>
- ExplodedNodeSet ArgsEvaluated;<br>
- while (!WL.empty()) {<br>
- ObjCMsgWLItem Item = WL.back();<br>
- WL.pop_back();<br>
-<br>
- if (Item.I == AE) {<br>
- ArgsEvaluated.insert(Item.N);<br>
- continue;<br>
- }<br>
-<br>
- // Evaluate the subexpression.<br>
- ExplodedNodeSet Tmp;<br>
-<br>
- // FIXME: [Objective-C++] handle arguments that are references<br>
- Visit(*Item.I, Item.N, Tmp);<br>
-<br>
- // Enqueue evaluating the next argument on the worklist.<br>
- ++(Item.I);<br>
- for (ExplodedNodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI!=NE; ++NI)<br>
- WL.push_back(ObjCMsgWLItem(Item.I, *NI));<br>
- }<br>
-<br>
- // Now that the arguments are processed, handle the previsits checks.<br>
- ExplodedNodeSet DstPrevisit;<br>
- CheckerVisit(ME, DstPrevisit, ArgsEvaluated, PreVisitStmtCallback);<br>
-<br>
- // Proceed with evaluate the message expression.<br>
- ExplodedNodeSet dstEval;<br>
-<br>
- for (ExplodedNodeSet::iterator DI = DstPrevisit.begin(),<br>
- DE = DstPrevisit.end(); DI != DE; ++DI) {<br>
-<br>
- Pred = *DI;<br>
- bool RaisesException = false;<br>
- unsigned oldSize = dstEval.size();<br>
- SaveAndRestore<bool> OldSink(Builder->BuildSinks);<br>
- SaveOr OldHasGen(Builder->HasGeneratedNode);<br>
-<br>
- if (const Expr *Receiver = ME->getInstanceReceiver()) {<br>
- const GRState *state = GetState(Pred);<br>
-<br>
- // Bifurcate the state into nil and non-nil ones.<br>
- DefinedOrUnknownSVal receiverVal =<br>
- cast<DefinedOrUnknownSVal>(state->getSVal(Receiver));<br>
-<br>
- const GRState *notNilState, *nilState;<br>
- llvm::tie(notNilState, nilState) = state->assume(receiverVal);<br>
-<br>
- // There are three cases: can be nil or non-nil, must be nil, must be<br>
- // non-nil. We handle must be nil, and merge the rest two into non-nil.<br>
- if (nilState && !notNilState) {<br>
- CheckerEvalNilReceiver(ME, dstEval, nilState, Pred);<br>
- continue;<br>
- }<br>
-<br>
- // Check if the "raise" message was sent.<br>
- assert(notNilState);<br>
- if (ME->getSelector() == RaiseSel)<br>
- RaisesException = true;<br>
-<br>
- // Check if we raise an exception. For now treat these as sinks.<br>
- // Eventually we will want to handle exceptions properly.<br>
- if (RaisesException)<br>
- Builder->BuildSinks = true;<br>
-<br>
- // Dispatch to plug-in transfer function.<br>
- evalObjCMessageExpr(dstEval, ME, Pred, notNilState);<br>
- }<br>
- else if (ObjCInterfaceDecl *Iface = ME->getReceiverInterface()) {<br>
- IdentifierInfo* ClsName = Iface->getIdentifier();<br>
- Selector S = ME->getSelector();<br>
-<br>
- // Check for special instance methods.<br>
- if (!NSExceptionII) {<br>
- ASTContext& Ctx = getContext();<br>
- NSExceptionII = &Ctx.Idents.get("NSException");<br>
- }<br>
-<br>
- if (ClsName == NSExceptionII) {<br>
- enum { NUM_RAISE_SELECTORS = 2 };<br>
-<br>
- // Lazily create a cache of the selectors.<br>
- if (!NSExceptionInstanceRaiseSelectors) {<br>
- ASTContext& Ctx = getContext();<br>
- NSExceptionInstanceRaiseSelectors =<br>
- new Selector[NUM_RAISE_SELECTORS];<br>
- llvm::SmallVector<IdentifierInfo*, NUM_RAISE_SELECTORS> II;<br>
- unsigned idx = 0;<br>
-<br>
- // raise:format:<br>
- II.push_back(&Ctx.Idents.get("raise"));<br>
- II.push_back(&Ctx.Idents.get("format"));<br>
- NSExceptionInstanceRaiseSelectors[idx++] =<br>
- Ctx.Selectors.getSelector(II.size(), &II[0]);<br>
-<br>
- // raise:format::arguments:<br>
- II.push_back(&Ctx.Idents.get("arguments"));<br>
- NSExceptionInstanceRaiseSelectors[idx++] =<br>
- Ctx.Selectors.getSelector(II.size(), &II[0]);<br>
- }<br>
-<br>
- for (unsigned i = 0; i < NUM_RAISE_SELECTORS; ++i)<br>
- if (S == NSExceptionInstanceRaiseSelectors[i]) {<br>
- RaisesException = true;<br>
- break;<br>
- }<br>
- }<br>
-<br>
- // Check if we raise an exception. For now treat these as sinks.<br>
- // Eventually we will want to handle exceptions properly.<br>
- if (RaisesException)<br>
- Builder->BuildSinks = true;<br>
-<br>
- // Dispatch to plug-in transfer function.<br>
- evalObjCMessageExpr(dstEval, ME, Pred, Builder->GetState(Pred));<br>
- }<br>
-<br>
- // Handle the case where no nodes where generated. Auto-generate that<br>
- // contains the updated state if we aren't generating sinks.<br>
- if (!Builder->BuildSinks && dstEval.size() == oldSize &&<br>
- !Builder->HasGeneratedNode)<br>
- MakeNode(dstEval, ME, Pred, GetState(Pred));<br>
- }<br>
-<br>
- // Finally, perform the post-condition check of the ObjCMessageExpr and store<br>
- // the created nodes in 'Dst'.<br>
- CheckerVisit(ME, Dst, dstEval, PostVisitStmtCallback);<br>
-}<br>
-<br>
-//===----------------------------------------------------------------------===//<br>
-// Transfer functions: Miscellaneous statements.<br>
-//===----------------------------------------------------------------------===//<br>
-<br>
-void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,<br>
- ExplodedNode *Pred, ExplodedNodeSet &Dst) {<br>
-<br>
- ExplodedNodeSet S1;<br>
- Visit(Ex, Pred, S1);<br>
- ExplodedNodeSet S2;<br>
- CheckerVisit(CastE, S2, S1, PreVisitStmtCallback);<br>
-<br>
- if (CastE->getCastKind() == CK_LValueToRValue) {<br>
- for (ExplodedNodeSet::iterator I = S2.begin(), E = S2.end(); I!=E; ++I) {<br>
- ExplodedNode *subExprNode = *I;<br>
- const GRState *state = GetState(subExprNode);<br>
- evalLoad(Dst, CastE, subExprNode, state, state->getSVal(Ex));<br>
- }<br>
- return;<br>
- }<br>
-<br>
- // All other casts.<br>
- QualType T = CastE->getType();<br>
- QualType ExTy = Ex->getType();<br>
-<br>
- if (const ExplicitCastExpr *ExCast=dyn_cast_or_null<ExplicitCastExpr>(CastE))<br>
- T = ExCast->getTypeAsWritten();<br>
-<br>
-#if 0<br>
- // If we are evaluating the cast in an lvalue context, we implicitly want<br>
- // the cast to evaluate to a location.<br>
- if (asLValue) {<br>
- ASTContext &Ctx = getContext();<br>
- T = Ctx.getPointerType(Ctx.getCanonicalType(T));<br>
- ExTy = Ctx.getPointerType(Ctx.getCanonicalType(ExTy));<br>
- }<br>
-#endif<br>
-<br>
- switch (CastE->getCastKind()) {<br>
- case CK_ToVoid:<br>
- for (ExplodedNodeSet::iterator I = S2.begin(), E = S2.end(); I != E; ++I)<br>
- Dst.Add(*I);<br>
- return;<br>
-<br>
- case CK_LValueToRValue:<br>
- case CK_NoOp:<br>
- case CK_FunctionToPointerDecay:<br>
- for (ExplodedNodeSet::iterator I = S2.begin(), E = S2.end(); I != E; ++I) {<br>
- // Copy the SVal of Ex to CastE.<br>
- ExplodedNode *N = *I;<br>
- const GRState *state = GetState(N);<br>
- SVal V = state->getSVal(Ex);<br>
- state = state->BindExpr(CastE, V);<br>
- MakeNode(Dst, CastE, N, state);<br>
- }<br>
- return;<br>
-<br>
- case CK_GetObjCProperty:<br>
- case CK_Dependent:<br>
- case CK_ArrayToPointerDecay:<br>
- case CK_BitCast:<br>
- case CK_LValueBitCast:<br>
- case CK_IntegralCast:<br>
- case CK_NullToPointer:<br>
- case CK_IntegralToPointer:<br>
- case CK_PointerToIntegral:<br>
- case CK_PointerToBoolean:<br>
- case CK_IntegralToBoolean:<br>
- case CK_IntegralToFloating:<br>
- case CK_FloatingToIntegral:<br>
- case CK_FloatingToBoolean:<br>
- case CK_FloatingCast:<br>
- case CK_FloatingRealToComplex:<br>
- case CK_FloatingComplexToReal:<br>
- case CK_FloatingComplexToBoolean:<br>
- case CK_FloatingComplexCast:<br>
- case CK_FloatingComplexToIntegralComplex:<br>
- case CK_IntegralRealToComplex:<br>
- case CK_IntegralComplexToReal:<br>
- case CK_IntegralComplexToBoolean:<br>
- case CK_IntegralComplexCast:<br>
- case CK_IntegralComplexToFloatingComplex:<br>
- case CK_AnyPointerToObjCPointerCast:<br>
- case CK_AnyPointerToBlockPointerCast:<br>
-<br>
- case CK_ObjCObjectLValueCast: {<br>
- // Delegate to SValBuilder to process.<br>
- for (ExplodedNodeSet::iterator I = S2.begin(), E = S2.end(); I != E; ++I) {<br>
- ExplodedNode* N = *I;<br>
- const GRState* state = GetState(N);<br>
- SVal V = state->getSVal(Ex);<br>
- V = svalBuilder.evalCast(V, T, ExTy);<br>
- state = state->BindExpr(CastE, V);<br>
- MakeNode(Dst, CastE, N, state);<br>
- }<br>
- return;<br>
- }<br>
-<br>
- case CK_DerivedToBase:<br>
- case CK_UncheckedDerivedToBase:<br>
- // For DerivedToBase cast, delegate to the store manager.<br>
- for (ExplodedNodeSet::iterator I = S2.begin(), E = S2.end(); I != E; ++I) {<br>
- ExplodedNode *node = *I;<br>
- const GRState *state = GetState(node);<br>
- SVal val = state->getSVal(Ex);<br>
- val = getStoreManager().evalDerivedToBase(val, T);<br>
- state = state->BindExpr(CastE, val);<br>
- MakeNode(Dst, CastE, node, state);<br>
- }<br>
- return;<br>
-<br>
- // Various C++ casts that are not handled yet.<br>
- case CK_Dynamic:<br>
- case CK_ToUnion:<br>
- case CK_BaseToDerived:<br>
- case CK_NullToMemberPointer:<br>
- case CK_BaseToDerivedMemberPointer:<br>
- case CK_DerivedToBaseMemberPointer:<br>
- case CK_UserDefinedConversion:<br>
- case CK_ConstructorConversion:<br>
- case CK_VectorSplat:<br>
- case CK_MemberPointerToBoolean: {<br>
- SaveAndRestore<bool> OldSink(Builder->BuildSinks);<br>
- Builder->BuildSinks = true;<br>
- MakeNode(Dst, CastE, Pred, GetState(Pred));<br>
- return;<br>
- }<br>
- }<br>
-}<br>
-<br>
-void ExprEngine::VisitCompoundLiteralExpr(const CompoundLiteralExpr* CL,<br>
- ExplodedNode* Pred,<br>
- ExplodedNodeSet& Dst) {<br>
- const InitListExpr* ILE<br>
- = cast<InitListExpr>(CL->getInitializer()->IgnoreParens());<br>
- ExplodedNodeSet Tmp;<br>
- Visit(ILE, Pred, Tmp);<br>
-<br>
- for (ExplodedNodeSet::iterator I = Tmp.begin(), EI = Tmp.end(); I!=EI; ++I) {<br>
- const GRState* state = GetState(*I);<br>
- SVal ILV = state->getSVal(ILE);<br>
- const LocationContext *LC = (*I)->getLocationContext();<br>
- state = state->bindCompoundLiteral(CL, LC, ILV);<br>
-<br>
- if (CL->isLValue()) {<br>
- MakeNode(Dst, CL, *I, state->BindExpr(CL, state->getLValue(CL, LC)));<br>
- }<br>
- else<br>
- MakeNode(Dst, CL, *I, state->BindExpr(CL, ILV));<br>
- }<br>
-}<br>
-<br>
-void ExprEngine::VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred,<br>
- ExplodedNodeSet& Dst) {<br>
-<br>
- // The CFG has one DeclStmt per Decl.<br>
- const Decl* D = *DS->decl_begin();<br>
-<br>
- if (!D || !isa<VarDecl>(D))<br>
- return;<br>
-<br>
- const VarDecl* VD = dyn_cast<VarDecl>(D);<br>
- const Expr* InitEx = VD->getInit();<br>
-<br>
- // FIXME: static variables may have an initializer, but the second<br>
- // time a function is called those values may not be current.<br>
- ExplodedNodeSet Tmp;<br>
-<br>
- if (InitEx) {<br>
- if (VD->getType()->isReferenceType() && !InitEx->isLValue()) {<br>
- // If the initializer is C++ record type, it should already has a<br>
- // temp object.<br>
- if (!InitEx->getType()->isRecordType())<br>
- CreateCXXTemporaryObject(InitEx, Pred, Tmp);<br>
- else<br>
- Tmp.Add(Pred);<br>
- } else<br>
- Visit(InitEx, Pred, Tmp);<br>
- } else<br>
- Tmp.Add(Pred);<br>
-<br>
- ExplodedNodeSet Tmp2;<br>
- CheckerVisit(DS, Tmp2, Tmp, PreVisitStmtCallback);<br>
-<br>
- for (ExplodedNodeSet::iterator I=Tmp2.begin(), E=Tmp2.end(); I!=E; ++I) {<br>
- ExplodedNode *N = *I;<br>
- const GRState *state = GetState(N);<br>
-<br>
- // Decls without InitExpr are not initialized explicitly.<br>
- const LocationContext *LC = N->getLocationContext();<br>
-<br>
- if (InitEx) {<br>
- SVal InitVal = state->getSVal(InitEx);<br>
-<br>
- // We bound the temp obj region to the CXXConstructExpr. Now recover<br>
- // the lazy compound value when the variable is not a reference.<br>
- if (AMgr.getLangOptions().CPlusPlus && VD->getType()->isRecordType() &&<br>
- !VD->getType()->isReferenceType() && isa<loc::MemRegionVal>(InitVal)){<br>
- InitVal = state->getSVal(cast<loc::MemRegionVal>(InitVal).getRegion());<br>
- assert(isa<nonloc::LazyCompoundVal>(InitVal));<br>
- }<br>
-<br>
- // Recover some path-sensitivity if a scalar value evaluated to<br>
- // UnknownVal.<br>
- if ((InitVal.isUnknown() ||<br>
- !getConstraintManager().canReasonAbout(InitVal)) &&<br>
- !VD->getType()->isReferenceType()) {<br>
- InitVal = svalBuilder.getConjuredSymbolVal(NULL, InitEx,<br>
- Builder->getCurrentBlockCount());<br>
- }<br>
-<br>
- evalBind(Dst, DS, *I, state,<br>
- loc::MemRegionVal(state->getRegion(VD, LC)), InitVal, true);<br>
- }<br>
- else {<br>
- state = state->bindDeclWithNoInit(state->getRegion(VD, LC));<br>
- MakeNode(Dst, DS, *I, state);<br>
- }<br>
- }<br>
-}<br>
-<br>
-void ExprEngine::VisitCondInit(const VarDecl *VD, const Stmt *S,<br>
- ExplodedNode *Pred, ExplodedNodeSet& Dst) {<br>
-<br>
- const Expr* InitEx = VD->getInit();<br>
- ExplodedNodeSet Tmp;<br>
- Visit(InitEx, Pred, Tmp);<br>
-<br>
- for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {<br>
- ExplodedNode *N = *I;<br>
- const GRState *state = GetState(N);<br>
-<br>
- const LocationContext *LC = N->getLocationContext();<br>
- SVal InitVal = state->getSVal(InitEx);<br>
-<br>
- // Recover some path-sensitivity if a scalar value evaluated to<br>
- // UnknownVal.<br>
- if (InitVal.isUnknown() ||<br>
- !getConstraintManager().canReasonAbout(InitVal)) {<br>
- InitVal = svalBuilder.getConjuredSymbolVal(NULL, InitEx,<br>
- Builder->getCurrentBlockCount());<br>
- }<br>
-<br>
- evalBind(Dst, S, N, state,<br>
- loc::MemRegionVal(state->getRegion(VD, LC)), InitVal, true);<br>
- }<br>
-}<br>
-<br>
-namespace {<br>
- // This class is used by VisitInitListExpr as an item in a worklist<br>
- // for processing the values contained in an InitListExpr.<br>
-class InitListWLItem {<br>
-public:<br>
- llvm::ImmutableList<SVal> Vals;<br>
- ExplodedNode* N;<br>
- InitListExpr::const_reverse_iterator Itr;<br>
-<br>
- InitListWLItem(ExplodedNode* n, llvm::ImmutableList<SVal> vals,<br>
- InitListExpr::const_reverse_iterator itr)<br>
- : Vals(vals), N(n), Itr(itr) {}<br>
-};<br>
-}<br>
-<br>
-<br>
-void ExprEngine::VisitInitListExpr(const InitListExpr* E, ExplodedNode* Pred,<br>
- ExplodedNodeSet& Dst) {<br>
-<br>
- const GRState* state = GetState(Pred);<br>
- QualType T = getContext().getCanonicalType(E->getType());<br>
- unsigned NumInitElements = E->getNumInits();<br>
-<br>
- if (T->isArrayType() || T->isRecordType() || T->isVectorType()) {<br>
- llvm::ImmutableList<SVal> StartVals = getBasicVals().getEmptySValList();<br>
-<br>
- // Handle base case where the initializer has no elements.<br>
- // e.g: static int* myArray[] = {};<br>
- if (NumInitElements == 0) {<br>
- SVal V = svalBuilder.makeCompoundVal(T, StartVals);<br>
- MakeNode(Dst, E, Pred, state->BindExpr(E, V));<br>
- return;<br>
- }<br>
-<br>
- // Create a worklist to process the initializers.<br>
- llvm::SmallVector<InitListWLItem, 10> WorkList;<br>
- WorkList.reserve(NumInitElements);<br>
- WorkList.push_back(InitListWLItem(Pred, StartVals, E->rbegin()));<br>
- InitListExpr::const_reverse_iterator ItrEnd = E->rend();<br>
- assert(!(E->rbegin() == E->rend()));<br>
-<br>
- // Process the worklist until it is empty.<br>
- while (!WorkList.empty()) {<br>
- InitListWLItem X = WorkList.back();<br>
- WorkList.pop_back();<br>
-<br>
- ExplodedNodeSet Tmp;<br>
- Visit(*X.Itr, X.N, Tmp);<br>
-<br>
- InitListExpr::const_reverse_iterator NewItr = X.Itr + 1;<br>
-<br>
- for (ExplodedNodeSet::iterator NI=Tmp.begin(),NE=Tmp.end();NI!=NE;++NI) {<br>
- // Get the last initializer value.<br>
- state = GetState(*NI);<br>
- SVal InitV = state->getSVal(cast<Expr>(*X.Itr));<br>
-<br>
- // Construct the new list of values by prepending the new value to<br>
- // the already constructed list.<br>
- llvm::ImmutableList<SVal> NewVals =<br>
- getBasicVals().consVals(InitV, X.Vals);<br>
-<br>
- if (NewItr == ItrEnd) {<br>
- // Now we have a list holding all init values. Make CompoundValData.<br>
- SVal V = svalBuilder.makeCompoundVal(T, NewVals);<br>
-<br>
- // Make final state and node.<br>
- MakeNode(Dst, E, *NI, state->BindExpr(E, V));<br>
- }<br>
- else {<br>
- // Still some initializer values to go. Push them onto the worklist.<br>
- WorkList.push_back(InitListWLItem(*NI, NewVals, NewItr));<br>
- }<br>
- }<br>
- }<br>
-<br>
- return;<br>
- }<br>
-<br>
- if (Loc::IsLocType(T) || T->isIntegerType()) {<br>
- assert (E->getNumInits() == 1);<br>
- ExplodedNodeSet Tmp;<br>
- const Expr* Init = E->getInit(0);<br>
- Visit(Init, Pred, Tmp);<br>
- for (ExplodedNodeSet::iterator I=Tmp.begin(), EI=Tmp.end(); I != EI; ++I) {<br>
- state = GetState(*I);<br>
- MakeNode(Dst, E, *I, state->BindExpr(E, state->getSVal(Init)));<br>
- }<br>
- return;<br>
- }<br>
-<br>
- assert(0 && "unprocessed InitListExpr type");<br>
-}<br>
-<br>
-/// VisitSizeOfAlignOfExpr - Transfer function for sizeof(type).<br>
-void ExprEngine::VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr* Ex,<br>
- ExplodedNode* Pred,<br>
- ExplodedNodeSet& Dst) {<br>
- QualType T = Ex->getTypeOfArgument();<br>
- CharUnits amt;<br>
-<br>
- if (Ex->isSizeOf()) {<br>
- if (T == getContext().VoidTy) {<br>
- // sizeof(void) == 1 byte.<br>
- amt = CharUnits::One();<br>
- }<br>
- else if (!T->isConstantSizeType()) {<br>
- assert(T->isVariableArrayType() && "Unknown non-constant-sized type.");<br>
-<br>
- // FIXME: Add support for VLA type arguments, not just VLA expressions.<br>
- // When that happens, we should probably refactor VLASizeChecker's code.<br>
- if (Ex->isArgumentType()) {<br>
- Dst.Add(Pred);<br>
- return;<br>
- }<br>
-<br>
- // Get the size by getting the extent of the sub-expression.<br>
- // First, visit the sub-expression to find its region.<br>
- const Expr *Arg = Ex->getArgumentExpr();<br>
- ExplodedNodeSet Tmp;<br>
- Visit(Arg, Pred, Tmp);<br>
-<br>
- for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {<br>
- const GRState* state = GetState(*I);<br>
- const MemRegion *MR = state->getSVal(Arg).getAsRegion();<br>
-<br>
- // If the subexpression can't be resolved to a region, we don't know<br>
- // anything about its size. Just leave the state as is and continue.<br>
- if (!MR) {<br>
- Dst.Add(*I);<br>
- continue;<br>
- }<br>
-<br>
- // The result is the extent of the VLA.<br>
- SVal Extent = cast<SubRegion>(MR)->getExtent(svalBuilder);<br>
- MakeNode(Dst, Ex, *I, state->BindExpr(Ex, Extent));<br>
- }<br>
-<br>
- return;<br>
- }<br>
- else if (T->getAs<ObjCObjectType>()) {<br>
- // Some code tries to take the sizeof an ObjCObjectType, relying that<br>
- // the compiler has laid out its representation. Just report Unknown<br>
- // for these.<br>
- Dst.Add(Pred);<br>
- return;<br>
- }<br>
- else {<br>
- // All other cases.<br>
- amt = getContext().getTypeSizeInChars(T);<br>
- }<br>
- }<br>
- else // Get alignment of the type.<br>
- amt = getContext().getTypeAlignInChars(T);<br>
-<br>
- MakeNode(Dst, Ex, Pred,<br>
- GetState(Pred)->BindExpr(Ex,<br>
- svalBuilder.makeIntVal(amt.getQuantity(), Ex->getType())));<br>
-}<br>
-<br>
-void ExprEngine::VisitOffsetOfExpr(const OffsetOfExpr* OOE,<br>
- ExplodedNode* Pred, ExplodedNodeSet& Dst) {<br>
- Expr::EvalResult Res;<br>
- if (OOE->Evaluate(Res, getContext()) && Res.Val.isInt()) {<br>
- const APSInt &IV = Res.Val.getInt();<br>
- assert(IV.getBitWidth() == getContext().getTypeSize(OOE->getType()));<br>
- assert(OOE->getType()->isIntegerType());<br>
- assert(IV.isSigned() == OOE->getType()->isSignedIntegerType());<br>
- SVal X = svalBuilder.makeIntVal(IV);<br>
- MakeNode(Dst, OOE, Pred, GetState(Pred)->BindExpr(OOE, X));<br>
- return;<br>
- }<br>
- // FIXME: Handle the case where __builtin_offsetof is not a constant.<br>
- Dst.Add(Pred);<br>
-}<br>
-<br>
-void ExprEngine::VisitUnaryOperator(const UnaryOperator* U,<br>
- ExplodedNode* Pred,<br>
- ExplodedNodeSet& Dst) {<br>
-<br>
- switch (U->getOpcode()) {<br>
-<br>
- default:<br>
- break;<br>
-<br>
- case UO_Real: {<br>
- const Expr* Ex = U->getSubExpr()->IgnoreParens();<br>
- ExplodedNodeSet Tmp;<br>
- Visit(Ex, Pred, Tmp);<br>
-<br>
- for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {<br>
-<br>
- // FIXME: We don't have complex SValues yet.<br>
- if (Ex->getType()->isAnyComplexType()) {<br>
- // Just report "Unknown."<br>
- Dst.Add(*I);<br>
- continue;<br>
- }<br>
-<br>
- // For all other types, UO_Real is an identity operation.<br>
- assert (U->getType() == Ex->getType());<br>
- const GRState* state = GetState(*I);<br>
- MakeNode(Dst, U, *I, state->BindExpr(U, state->getSVal(Ex)));<br>
- }<br>
-<br>
- return;<br>
- }<br>
-<br>
- case UO_Imag: {<br>
-<br>
- const Expr* Ex = U->getSubExpr()->IgnoreParens();<br>
- ExplodedNodeSet Tmp;<br>
- Visit(Ex, Pred, Tmp);<br>
-<br>
- for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {<br>
- // FIXME: We don't have complex SValues yet.<br>
- if (Ex->getType()->isAnyComplexType()) {<br>
- // Just report "Unknown."<br>
- Dst.Add(*I);<br>
- continue;<br>
- }<br>
-<br>
- // For all other types, UO_Imag returns 0.<br>
- const GRState* state = GetState(*I);<br>
- SVal X = svalBuilder.makeZeroVal(Ex->getType());<br>
- MakeNode(Dst, U, *I, state->BindExpr(U, X));<br>
- }<br>
-<br>
- return;<br>
- }<br>
-<br>
- case UO_Plus:<br>
- assert(!U->isLValue());<br>
- // FALL-THROUGH.<br>
- case UO_Deref:<br>
- case UO_AddrOf:<br>
- case UO_Extension: {<br>
-<br>
- // Unary "+" is a no-op, similar to a parentheses. We still have places<br>
- // where it may be a block-level expression, so we need to<br>
- // generate an extra node that just propagates the value of the<br>
- // subexpression.<br>
-<br>
- const Expr* Ex = U->getSubExpr()->IgnoreParens();<br>
- ExplodedNodeSet Tmp;<br>
- Visit(Ex, Pred, Tmp);<br>
-<br>
- for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {<br>
- const GRState* state = GetState(*I);<br>
- MakeNode(Dst, U, *I, state->BindExpr(U, state->getSVal(Ex)));<br>
- }<br>
-<br>
- return;<br>
- }<br>
-<br>
- case UO_LNot:<br>
- case UO_Minus:<br>
- case UO_Not: {<br>
- assert (!U->isLValue());<br>
- const Expr* Ex = U->getSubExpr()->IgnoreParens();<br>
- ExplodedNodeSet Tmp;<br>
- Visit(Ex, Pred, Tmp);<br>
-<br>
- for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {<br>
- const GRState* state = GetState(*I);<br>
-<br>
- // Get the value of the subexpression.<br>
- SVal V = state->getSVal(Ex);<br>
-<br>
- if (V.isUnknownOrUndef()) {<br>
- MakeNode(Dst, U, *I, state->BindExpr(U, V));<br>
- continue;<br>
- }<br>
-<br>
-// QualType DstT = getContext().getCanonicalType(U->getType());<br>
-// QualType SrcT = getContext().getCanonicalType(Ex->getType());<br>
-//<br>
-// if (DstT != SrcT) // Perform promotions.<br>
-// V = evalCast(V, DstT);<br>
-//<br>
-// if (V.isUnknownOrUndef()) {<br>
-// MakeNode(Dst, U, *I, BindExpr(St, U, V));<br>
-// continue;<br>
-// }<br>
-<br>
- switch (U->getOpcode()) {<br>
- default:<br>
- assert(false && "Invalid Opcode.");<br>
- break;<br>
-<br>
- case UO_Not:<br>
- // FIXME: Do we need to handle promotions?<br>
- state = state->BindExpr(U, evalComplement(cast<NonLoc>(V)));<br>
- break;<br>
-<br>
- case UO_Minus:<br>
- // FIXME: Do we need to handle promotions?<br>
- state = state->BindExpr(U, evalMinus(cast<NonLoc>(V)));<br>
- break;<br>
-<br>
- case UO_LNot:<br>
-<br>
- // C99 <a href="http://6.5.3.3" target="_blank">6.5.3.3</a>: "The expression !E is equivalent to (0==E)."<br>
- //<br>
- // Note: technically we do "E == 0", but this is the same in the<br>
- // transfer functions as "0 == E".<br>
- SVal Result;<br>
-<br>
- if (isa<Loc>(V)) {<br>
- Loc X = svalBuilder.makeNull();<br>
- Result = evalBinOp(state, BO_EQ, cast<Loc>(V), X,<br>
- U->getType());<br>
- }<br>
- else {<br>
- nonloc::ConcreteInt X(getBasicVals().getValue(0, Ex->getType()));<br>
- Result = evalBinOp(state, BO_EQ, cast<NonLoc>(V), X,<br>
- U->getType());<br>
- }<br>
-<br>
- state = state->BindExpr(U, Result);<br>
-<br>
- break;<br>
- }<br>
-<br>
- MakeNode(Dst, U, *I, state);<br>
- }<br>
-<br>
- return;<br>
- }<br>
- }<br>
-<br>
- // Handle ++ and -- (both pre- and post-increment).<br>
- assert (U->isIncrementDecrementOp());<br>
- ExplodedNodeSet Tmp;<br>
- const Expr* Ex = U->getSubExpr()->IgnoreParens();<br>
- Visit(Ex, Pred, Tmp);<br>
-<br>
- for (ExplodedNodeSet::iterator I = Tmp.begin(), E = Tmp.end(); I!=E; ++I) {<br>
-<br>
- const GRState* state = GetState(*I);<br>
- SVal loc = state->getSVal(Ex);<br>
-<br>
- // Perform a load.<br>
- ExplodedNodeSet Tmp2;<br>
- evalLoad(Tmp2, Ex, *I, state, loc);<br>
-<br>
- for (ExplodedNodeSet::iterator I2=Tmp2.begin(), E2=Tmp2.end();I2!=E2;++I2) {<br>
-<br>
- state = GetState(*I2);<br>
- SVal V2_untested = state->getSVal(Ex);<br>
-<br>
- // Propagate unknown and undefined values.<br>
- if (V2_untested.isUnknownOrUndef()) {<br>
- MakeNode(Dst, U, *I2, state->BindExpr(U, V2_untested));<br>
- continue;<br>
- }<br>
- DefinedSVal V2 = cast<DefinedSVal>(V2_untested);<br>
-<br>
- // Handle all other values.<br>
- BinaryOperator::Opcode Op = U->isIncrementOp() ? BO_Add<br>
- : BO_Sub;<br>
-<br>
- // If the UnaryOperator has non-location type, use its type to create the<br>
- // constant value. If the UnaryOperator has location type, create the<br>
- // constant with int type and pointer width.<br>
- SVal RHS;<br>
-<br>
- if (U->getType()->isAnyPointerType())<br>
- RHS = svalBuilder.makeArrayIndex(1);<br>
- else<br>
- RHS = svalBuilder.makeIntVal(1, U->getType());<br>
-<br>
- SVal Result = evalBinOp(state, Op, V2, RHS, U->getType());<br>
-<br>
- // Conjure a new symbol if necessary to recover precision.<br>
- if (Result.isUnknown() || !getConstraintManager().canReasonAbout(Result)){<br>
- DefinedOrUnknownSVal SymVal =<br>
- svalBuilder.getConjuredSymbolVal(NULL, Ex,<br>
- Builder->getCurrentBlockCount());<br>
- Result = SymVal;<br>
-<br>
- // If the value is a location, ++/-- should always preserve<br>
- // non-nullness. Check if the original value was non-null, and if so<br>
- // propagate that constraint.<br>
- if (Loc::IsLocType(U->getType())) {<br>
- DefinedOrUnknownSVal Constraint =<br>
- svalBuilder.evalEQ(state, V2,svalBuilder.makeZeroVal(U->getType()));<br>
-<br>
- if (!state->assume(Constraint, true)) {<br>
- // It isn't feasible for the original value to be null.<br>
- // Propagate this constraint.<br>
- Constraint = svalBuilder.evalEQ(state, SymVal,<br>
- svalBuilder.makeZeroVal(U->getType()));<br>
-<br>
-<br>
- state = state->assume(Constraint, false);<br>
- assert(state);<br>
- }<br>
- }<br>
- }<br>
-<br>
- // Since the lvalue-to-rvalue conversion is explicit in the AST,<br>
- // we bind an l-value if the operator is prefix and an lvalue (in C++).<br>
- if (U->isLValue())<br>
- state = state->BindExpr(U, loc);<br>
- else<br>
- state = state->BindExpr(U, V2);<br>
-<br>
- // Perform the store.<br>
- evalStore(Dst, NULL, U, *I2, state, loc, Result);<br>
- }<br>
- }<br>
-}<br>
-<br>
-void ExprEngine::VisitAsmStmt(const AsmStmt* A, ExplodedNode* Pred,<br>
- ExplodedNodeSet& Dst) {<br>
- VisitAsmStmtHelperOutputs(A, A->begin_outputs(), A->end_outputs(), Pred, Dst);<br>
-}<br>
-<br>
-void ExprEngine::VisitAsmStmtHelperOutputs(const AsmStmt* A,<br>
- AsmStmt::const_outputs_iterator I,<br>
- AsmStmt::const_outputs_iterator E,<br>
- ExplodedNode* Pred, ExplodedNodeSet& Dst) {<br>
- if (I == E) {<br>
- VisitAsmStmtHelperInputs(A, A->begin_inputs(), A->end_inputs(), Pred, Dst);<br>
- return;<br>
- }<br>
-<br>
- ExplodedNodeSet Tmp;<br>
- Visit(*I, Pred, Tmp);<br>
- ++I;<br>
-<br>
- for (ExplodedNodeSet::iterator NI = Tmp.begin(), NE = Tmp.end();NI != NE;++NI)<br>
- VisitAsmStmtHelperOutputs(A, I, E, *NI, Dst);<br>
-}<br>
-<br>
-void ExprEngine::VisitAsmStmtHelperInputs(const AsmStmt* A,<br>
- AsmStmt::const_inputs_iterator I,<br>
- AsmStmt::const_inputs_iterator E,<br>
- ExplodedNode* Pred,<br>
- ExplodedNodeSet& Dst) {<br>
- if (I == E) {<br>
-<br>
- // We have processed both the inputs and the outputs. All of the outputs<br>
- // should evaluate to Locs. Nuke all of their values.<br>
-<br>
- // FIXME: Some day in the future it would be nice to allow a "plug-in"<br>
- // which interprets the inline asm and stores proper results in the<br>
- // outputs.<br>
-<br>
- const GRState* state = GetState(Pred);<br>
-<br>
- for (AsmStmt::const_outputs_iterator OI = A->begin_outputs(),<br>
- OE = A->end_outputs(); OI != OE; ++OI) {<br>
-<br>
- SVal X = state->getSVal(*OI);<br>
- assert (!isa<NonLoc>(X)); // Should be an Lval, or unknown, undef.<br>
-<br>
- if (isa<Loc>(X))<br>
- state = state->bindLoc(cast<Loc>(X), UnknownVal());<br>
- }<br>
-<br>
- MakeNode(Dst, A, Pred, state);<br>
- return;<br>
- }<br>
-<br>
- ExplodedNodeSet Tmp;<br>
- Visit(*I, Pred, Tmp);<br>
-<br>
- ++I;<br>
-<br>
- for (ExplodedNodeSet::iterator NI = Tmp.begin(), NE = Tmp.end(); NI!=NE; ++NI)<br>
- VisitAsmStmtHelperInputs(A, I, E, *NI, Dst);<br>
-}<br>
-<br>
-void ExprEngine::VisitReturnStmt(const ReturnStmt *RS, ExplodedNode *Pred,<br>
- ExplodedNodeSet &Dst) {<br>
- ExplodedNodeSet Src;<br>
- if (const Expr *RetE = RS->getRetValue()) {<br>
- // Record the returned expression in the state. It will be used in<br>
- // ProcessCallExit to bind the return value to the call expr.<br>
- {<br>
- static int Tag = 0;<br>
- SaveAndRestore<const void *> OldTag(Builder->Tag, &Tag);<br>
- const GRState *state = GetState(Pred);<br>
- state = state->set<ReturnExpr>(RetE);<br>
- Pred = Builder->generateNode(RetE, state, Pred);<br>
- }<br>
- // We may get a NULL Pred because we generated a cached node.<br>
- if (Pred)<br>
- Visit(RetE, Pred, Src);<br>
- }<br>
- else {<br>
- Src.Add(Pred);<br>
- }<br>
-<br>
- ExplodedNodeSet CheckedSet;<br>
- CheckerVisit(RS, CheckedSet, Src, PreVisitStmtCallback);<br>
-<br>
- for (ExplodedNodeSet::iterator I = CheckedSet.begin(), E = CheckedSet.end();<br>
- I != E; ++I) {<br>
-<br>
- assert(Builder && "StmtNodeBuilder must be defined.");<br>
-<br>
- Pred = *I;<br>
- unsigned size = Dst.size();<br>
-<br>
- SaveAndRestore<bool> OldSink(Builder->BuildSinks);<br>
- SaveOr OldHasGen(Builder->HasGeneratedNode);<br>
-<br>
- getTF().evalReturn(Dst, *this, *Builder, RS, Pred);<br>
-<br>
- // Handle the case where no nodes where generated.<br>
- if (!Builder->BuildSinks && Dst.size() == size &&<br>
- !Builder->HasGeneratedNode)<br>
- MakeNode(Dst, RS, Pred, GetState(Pred));<br>
- }<br>
-}<br>
-<br>
-//===----------------------------------------------------------------------===//<br>
-// Transfer functions: Binary operators.<br>
-//===----------------------------------------------------------------------===//<br>
-<br>
-void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,<br>
- ExplodedNode* Pred,<br>
- ExplodedNodeSet& Dst) {<br>
- ExplodedNodeSet Tmp1;<br>
- Expr* LHS = B->getLHS()->IgnoreParens();<br>
- Expr* RHS = B->getRHS()->IgnoreParens();<br>
-<br>
- Visit(LHS, Pred, Tmp1);<br>
- ExplodedNodeSet Tmp3;<br>
-<br>
- for (ExplodedNodeSet::iterator I1=Tmp1.begin(), E1=Tmp1.end(); I1!=E1; ++I1) {<br>
- SVal LeftV = GetState(*I1)->getSVal(LHS);<br>
- ExplodedNodeSet Tmp2;<br>
- Visit(RHS, *I1, Tmp2);<br>
-<br>
- ExplodedNodeSet CheckedSet;<br>
- CheckerVisit(B, CheckedSet, Tmp2, PreVisitStmtCallback);<br>
-<br>
- // With both the LHS and RHS evaluated, process the operation itself.<br>
-<br>
- for (ExplodedNodeSet::iterator I2=CheckedSet.begin(), E2=CheckedSet.end();<br>
- I2 != E2; ++I2) {<br>
-<br>
- const GRState *state = GetState(*I2);<br>
- SVal RightV = state->getSVal(RHS);<br>
-<br>
- BinaryOperator::Opcode Op = B->getOpcode();<br>
-<br>
- if (Op == BO_Assign) {<br>
- // EXPERIMENTAL: "Conjured" symbols.<br>
- // FIXME: Handle structs.<br>
- QualType T = RHS->getType();<br>
-<br>
- if (RightV.isUnknown() ||!getConstraintManager().canReasonAbout(RightV))<br>
- {<br>
- unsigned Count = Builder->getCurrentBlockCount();<br>
- RightV = svalBuilder.getConjuredSymbolVal(NULL, B->getRHS(), Count);<br>
- }<br>
-<br>
- SVal ExprVal = B->isLValue() ? LeftV : RightV;<br>
-<br>
- // Simulate the effects of a "store": bind the value of the RHS<br>
- // to the L-Value represented by the LHS.<br>
- evalStore(Tmp3, B, LHS, *I2, state->BindExpr(B, ExprVal), LeftV,RightV);<br>
- continue;<br>
- }<br>
-<br>
- if (!B->isAssignmentOp()) {<br>
- // Process non-assignments except commas or short-circuited<br>
- // logical expressions (LAnd and LOr).<br>
- SVal Result = evalBinOp(state, Op, LeftV, RightV, B->getType());<br>
-<br>
- if (Result.isUnknown()) {<br>
- MakeNode(Tmp3, B, *I2, state);<br>
- continue;<br>
- }<br>
-<br>
- state = state->BindExpr(B, Result);<br>
-<br>
- MakeNode(Tmp3, B, *I2, state);<br>
- continue;<br>
- }<br>
-<br>
- assert (B->isCompoundAssignmentOp());<br>
-<br>
- switch (Op) {<br>
- default:<br>
- assert(0 && "Invalid opcode for compound assignment.");<br>
- case BO_MulAssign: Op = BO_Mul; break;<br>
- case BO_DivAssign: Op = BO_Div; break;<br>
- case BO_RemAssign: Op = BO_Rem; break;<br>
- case BO_AddAssign: Op = BO_Add; break;<br>
- case BO_SubAssign: Op = BO_Sub; break;<br>
- case BO_ShlAssign: Op = BO_Shl; break;<br>
- case BO_ShrAssign: Op = BO_Shr; break;<br>
- case BO_AndAssign: Op = BO_And; break;<br>
- case BO_XorAssign: Op = BO_Xor; break;<br>
- case BO_OrAssign: Op = BO_Or; break;<br>
- }<br>
-<br>
- // Perform a load (the LHS). This performs the checks for<br>
- // null dereferences, and so on.<br>
- ExplodedNodeSet Tmp4;<br>
- SVal location = state->getSVal(LHS);<br>
- evalLoad(Tmp4, LHS, *I2, state, location);<br>
-<br>
- for (ExplodedNodeSet::iterator I4=Tmp4.begin(), E4=Tmp4.end(); I4!=E4;<br>
- ++I4) {<br>
- state = GetState(*I4);<br>
- SVal V = state->getSVal(LHS);<br>
-<br>
- // Get the computation type.<br>
- QualType CTy =<br>
- cast<CompoundAssignOperator>(B)->getComputationResultType();<br>
- CTy = getContext().getCanonicalType(CTy);<br>
-<br>
- QualType CLHSTy =<br>
- cast<CompoundAssignOperator>(B)->getComputationLHSType();<br>
- CLHSTy = getContext().getCanonicalType(CLHSTy);<br>
-<br>
- QualType LTy = getContext().getCanonicalType(LHS->getType());<br>
- QualType RTy = getContext().getCanonicalType(RHS->getType());<br>
-<br>
- // Promote LHS.<br>
- V = svalBuilder.evalCast(V, CLHSTy, LTy);<br>
-<br>
- // Compute the result of the operation.<br>
- SVal Result = svalBuilder.evalCast(evalBinOp(state, Op, V, RightV, CTy),<br>
- B->getType(), CTy);<br>
-<br>
- // EXPERIMENTAL: "Conjured" symbols.<br>
- // FIXME: Handle structs.<br>
-<br>
- SVal LHSVal;<br>
-<br>
- if (Result.isUnknown() ||<br>
- !getConstraintManager().canReasonAbout(Result)) {<br>
-<br>
- unsigned Count = Builder->getCurrentBlockCount();<br>
-<br>
- // The symbolic value is actually for the type of the left-hand side<br>
- // expression, not the computation type, as this is the value the<br>
- // LValue on the LHS will bind to.<br>
- LHSVal = svalBuilder.getConjuredSymbolVal(NULL, B->getRHS(), LTy, Count);<br>
-<br>
- // However, we need to convert the symbol to the computation type.<br>
- Result = svalBuilder.evalCast(LHSVal, CTy, LTy);<br>
- }<br>
- else {<br>
- // The left-hand side may bind to a different value then the<br>
- // computation type.<br>
- LHSVal = svalBuilder.evalCast(Result, LTy, CTy);<br>
- }<br>
-<br>
- // In C++, assignment and compound assignment operators return an<br>
- // lvalue.<br>
- if (B->isLValue())<br>
- state = state->BindExpr(B, location);<br>
- else<br>
- state = state->BindExpr(B, Result);<br>
-<br>
- evalStore(Tmp3, B, LHS, *I4, state, location, LHSVal);<br>
- }<br>
- }<br>
- }<br>
-<br>
- CheckerVisit(B, Dst, Tmp3, PostVisitStmtCallback);<br>
-}<br>
-<br>
-//===----------------------------------------------------------------------===//<br>
-// Checker registration/lookup.<br>
-//===----------------------------------------------------------------------===//<br>
-<br>
-Checker *ExprEngine::lookupChecker(void *tag) const {<br>
- CheckerMap::const_iterator I = CheckerM.find(tag);<br>
- return (I == CheckerM.end()) ? NULL : Checkers[I->second].second;<br>
-}<br>
-<br>
-//===----------------------------------------------------------------------===//<br>
-// Visualization.<br>
-//===----------------------------------------------------------------------===//<br>
-<br>
-#ifndef NDEBUG<br>
-static ExprEngine* GraphPrintCheckerState;<br>
-static SourceManager* GraphPrintSourceManager;<br>
-<br>
-namespace llvm {<br>
-template<><br>
-struct DOTGraphTraits<ExplodedNode*> :<br>
- public DefaultDOTGraphTraits {<br>
-<br>
- DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {}<br>
-<br>
- // FIXME: Since we do not cache error nodes in ExprEngine now, this does not<br>
- // work.<br>
- static std::string getNodeAttributes(const ExplodedNode* N, void*) {<br>
-<br>
-#if 0<br>
- // FIXME: Replace with a general scheme to tell if the node is<br>
- // an error node.<br>
- if (GraphPrintCheckerState->isImplicitNullDeref(N) ||<br>
- GraphPrintCheckerState->isExplicitNullDeref(N) ||<br>
- GraphPrintCheckerState->isUndefDeref(N) ||<br>
- GraphPrintCheckerState->isUndefStore(N) ||<br>
- GraphPrintCheckerState->isUndefControlFlow(N) ||<br>
- GraphPrintCheckerState->isUndefResult(N) ||<br>
- GraphPrintCheckerState->isBadCall(N) ||<br>
- GraphPrintCheckerState->isUndefArg(N))<br>
- return "color=\"red\",style=\"filled\"";<br>
-<br>
- if (GraphPrintCheckerState->isNoReturnCall(N))<br>
- return "color=\"blue\",style=\"filled\"";<br>
-#endif<br>
- return "";<br>
- }<br>
-<br>
- static std::string getNodeLabel(const ExplodedNode* N, void*){<br>
-<br>
- std::string sbuf;<br>
- llvm::raw_string_ostream Out(sbuf);<br>
-<br>
- // Program Location.<br>
- ProgramPoint Loc = N->getLocation();<br>
-<br>
- switch (Loc.getKind()) {<br>
- case ProgramPoint::BlockEntranceKind:<br>
- Out << "Block Entrance: B"<br>
- << cast<BlockEntrance>(Loc).getBlock()->getBlockID();<br>
- break;<br>
-<br>
- case ProgramPoint::BlockExitKind:<br>
- assert (false);<br>
- break;<br>
-<br>
- case ProgramPoint::CallEnterKind:<br>
- Out << "CallEnter";<br>
- break;<br>
-<br>
- case ProgramPoint::CallExitKind:<br>
- Out << "CallExit";<br>
- break;<br>
-<br>
- default: {<br>
- if (StmtPoint *L = dyn_cast<StmtPoint>(&Loc)) {<br>
- const Stmt* S = L->getStmt();<br>
- SourceLocation SLoc = S->getLocStart();<br>
-<br>
- Out << S->getStmtClassName() << ' ' << (void*) S << ' ';<br>
- LangOptions LO; // FIXME.<br>
- S->printPretty(Out, 0, PrintingPolicy(LO));<br>
-<br>
- if (SLoc.isFileID()) {<br>
- Out << "\\lline="<br>
- << GraphPrintSourceManager->getInstantiationLineNumber(SLoc)<br>
- << " col="<br>
- << GraphPrintSourceManager->getInstantiationColumnNumber(SLoc)<br>
- << "\\l";<br>
- }<br>
-<br>
- if (isa<PreStmt>(Loc))<br>
- Out << "\\lPreStmt\\l;";<br>
- else if (isa<PostLoad>(Loc))<br>
- Out << "\\lPostLoad\\l;";<br>
- else if (isa<PostStore>(Loc))<br>
- Out << "\\lPostStore\\l";<br>
- else if (isa<PostLValue>(Loc))<br>
- Out << "\\lPostLValue\\l";<br>
-<br>
-#if 0<br>
- // FIXME: Replace with a general scheme to determine<br>
- // the name of the check.<br>
- if (GraphPrintCheckerState->isImplicitNullDeref(N))<br>
- Out << "\\|Implicit-Null Dereference.\\l";<br>
- else if (GraphPrintCheckerState->isExplicitNullDeref(N))<br>
- Out << "\\|Explicit-Null Dereference.\\l";<br>
- else if (GraphPrintCheckerState->isUndefDeref(N))<br>
- Out << "\\|Dereference of undefialied value.\\l";<br>
- else if (GraphPrintCheckerState->isUndefStore(N))<br>
- Out << "\\|Store to Undefined Loc.";<br>
- else if (GraphPrintCheckerState->isUndefResult(N))<br>
- Out << "\\|Result of operation is undefined.";<br>
- else if (GraphPrintCheckerState->isNoReturnCall(N))<br>
- Out << "\\|Call to function marked \"noreturn\".";<br>
- else if (GraphPrintCheckerState->isBadCall(N))<br>
- Out << "\\|Call to NULL/Undefined.";<br>
- else if (GraphPrintCheckerState->isUndefArg(N))<br>
- Out << "\\|Argument in call is undefined";<br>
-#endif<br>
-<br>
- break;<br>
- }<br>
-<br>
- const BlockEdge& E = cast<BlockEdge>(Loc);<br>
- Out << "Edge: (B" << E.getSrc()->getBlockID() << ", B"<br>
- << E.getDst()->getBlockID() << ')';<br>
-<br>
- if (const Stmt* T = E.getSrc()->getTerminator()) {<br>
-<br>
- SourceLocation SLoc = T->getLocStart();<br>
-<br>
- Out << "\\|Terminator: ";<br>
- LangOptions LO; // FIXME.<br>
- E.getSrc()->printTerminator(Out, LO);<br>
-<br>
- if (SLoc.isFileID()) {<br>
- Out << "\\lline="<br>
- << GraphPrintSourceManager->getInstantiationLineNumber(SLoc)<br>
- << " col="<br>
- << GraphPrintSourceManager->getInstantiationColumnNumber(SLoc);<br>
- }<br>
-<br>
- if (isa<SwitchStmt>(T)) {<br>
- const Stmt* Label = E.getDst()->getLabel();<br>
-<br>
- if (Label) {<br>
- if (const CaseStmt* C = dyn_cast<CaseStmt>(Label)) {<br>
- Out << "\\lcase ";<br>
- LangOptions LO; // FIXME.<br>
- C->getLHS()->printPretty(Out, 0, PrintingPolicy(LO));<br>
-<br>
- if (const Stmt* RHS = C->getRHS()) {<br>
- Out << " .. ";<br>
- RHS->printPretty(Out, 0, PrintingPolicy(LO));<br>
- }<br>
-<br>
- Out << ":";<br>
- }<br>
- else {<br>
- assert (isa<DefaultStmt>(Label));<br>
- Out << "\\ldefault:";<br>
- }<br>
- }<br>
- else<br>
- Out << "\\l(implicit) default:";<br>
- }<br>
- else if (isa<IndirectGotoStmt>(T)) {<br>
- // FIXME<br>
- }<br>
- else {<br>
- Out << "\\lCondition: ";<br>
- if (*E.getSrc()->succ_begin() == E.getDst())<br>
- Out << "true";<br>
- else<br>
- Out << "false";<br>
- }<br>
-<br>
- Out << "\\l";<br>
- }<br>
-<br>
-#if 0<br>
- // FIXME: Replace with a general scheme to determine<br>
- // the name of the check.<br>
- if (GraphPrintCheckerState->isUndefControlFlow(N)) {<br>
- Out << "\\|Control-flow based on\\lUndefined value.\\l";<br>
- }<br>
-#endif<br>
- }<br>
- }<br>
-<br>
- const GRState *state = N->getState();<br>
- Out << "\\|StateID: " << (void*) state<br>
- << " NodeID: " << (void*) N << "\\|";<br>
- state->printDOT(Out, *N->getLocationContext()->getCFG());<br>
- Out << "\\l";<br>
- return Out.str();<br>
- }<br>
-};<br>
-} // end llvm namespace<br>
-#endif<br>
-<br>
-#ifndef NDEBUG<br>
-template <typename ITERATOR><br>
-ExplodedNode* GetGraphNode(ITERATOR I) { return *I; }<br>
-<br>
-template <> ExplodedNode*<br>
-GetGraphNode<llvm::DenseMap<ExplodedNode*, Expr*>::iterator><br>
- (llvm::DenseMap<ExplodedNode*, Expr*>::iterator I) {<br>
- return I->first;<br>
-}<br>
-#endif<br>
-<br>
-void ExprEngine::ViewGraph(bool trim) {<br>
-#ifndef NDEBUG<br>
- if (trim) {<br>
- std::vector<ExplodedNode*> Src;<br>
-<br>
- // Flush any outstanding reports to make sure we cover all the nodes.<br>
- // This does not cause them to get displayed.<br>
- for (BugReporter::iterator I=BR.begin(), E=BR.end(); I!=E; ++I)<br>
- const_cast<BugType*>(*I)->FlushReports(BR);<br>
-<br>
- // Iterate through the reports and get their nodes.<br>
- for (BugReporter::iterator I=BR.begin(), E=BR.end(); I!=E; ++I) {<br>
- for (BugType::const_iterator I2=(*I)->begin(), E2=(*I)->end();<br>
- I2!=E2; ++I2) {<br>
- const BugReportEquivClass& EQ = *I2;<br>
- const BugReport &R = **EQ.begin();<br>
- ExplodedNode *N = const_cast<ExplodedNode*>(R.getErrorNode());<br>
- if (N) Src.push_back(N);<br>
- }<br>
- }<br>
-<br>
- ViewGraph(&Src[0], &Src[0]+Src.size());<br>
- }<br>
- else {<br>
- GraphPrintCheckerState = this;<br>
- GraphPrintSourceManager = &getContext().getSourceManager();<br>
-<br>
- llvm::ViewGraph(*G.roots_begin(), "ExprEngine");<br>
-<br>
- GraphPrintCheckerState = NULL;<br>
- GraphPrintSourceManager = NULL;<br>
- }<br>
-#endif<br>
-}<br>
-<br>
-void ExprEngine::ViewGraph(ExplodedNode** Beg, ExplodedNode** End) {<br>
-#ifndef NDEBUG<br>
- GraphPrintCheckerState = this;<br>
- GraphPrintSourceManager = &getContext().getSourceManager();<br>
-<br>
- std::auto_ptr<ExplodedGraph> TrimmedG(G.Trim(Beg, End).first);<br>
-<br>
- if (!TrimmedG.get())<br>
- llvm::errs() << "warning: Trimmed ExplodedGraph is empty.\n";<br>
- else<br>
- llvm::ViewGraph(*TrimmedG->roots_begin(), "TrimmedExprEngine");<br>
-<br>
- GraphPrintCheckerState = NULL;<br>
- GraphPrintSourceManager = NULL;<br>
-#endif<br>
-}<br>
<br>
Modified: cfe/trunk/tools/driver/Makefile<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/driver/Makefile?rev=123166&r1=123165&r2=123166&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/driver/Makefile?rev=123166&r1=123165&r2=123166&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/tools/driver/Makefile (original)<br>
+++ cfe/trunk/tools/driver/Makefile Mon Jan 10 03:23:01 2011<br>
@@ -39,7 +39,8 @@<br>
ipo selectiondag<br>
USEDLIBS = clangFrontendTool.a clangFrontend.a clangDriver.a \<br>
clangSerialization.a clangCodeGen.a clangParse.a clangSema.a \<br>
- clangStaticAnalyzerCheckers.a clangStaticAnalyzerCore.a clangAnalysis.a clangIndex.a clangRewrite.a \<br>
+ clangStaticAnalyzerCheckers.a clangStaticAnalyzerCore.a \<br>
+ clangAnalysis.a clangIndex.a clangRewrite.a \<br>
clangAST.a clangLex.a clangBasic.a<br>
<br>
include $(CLANG_LEVEL)/Makefile<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br>