From 25a792b0361d80337c75a14320f5be1b210066dc Mon Sep 17 00:00:00 2001 From: Argyrios Kyrtzidis Date: Tue, 1 Mar 2011 01:47:48 +0000 Subject: [PATCH] [analyzer] Remove SVal::getAsVarDecl() and reason about MemRegions, not Decls. Suggestion by Ted! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@126734 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../StaticAnalyzer/Core/PathSensitive/SVals.h | 4 -- lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp | 45 ++++++++++++++-------- lib/StaticAnalyzer/Core/SVals.cpp | 10 ----- 3 files changed, 28 insertions(+), 31 deletions(-) diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h index 35c7274f7d..0d430794e7 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h @@ -125,10 +125,6 @@ public: /// Otherwise return 0. const FunctionDecl* getAsFunctionDecl() const; - /// \brief If this SVal is a MemRegionVal and wraps a VarDecl, - /// return that VarDecl. Otherwise return 0. - const VarDecl* getAsVarDecl() const; - /// getAsLocSymbol - If this SVal is a location (subclasses Loc) and /// wraps a symbol, return that SymbolRef. Otherwise return NULL. SymbolRef getAsLocSymbol() const; diff --git a/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp b/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp index c4d533150d..307d185fed 100644 --- a/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp @@ -28,8 +28,8 @@ using namespace clang; using namespace ento; -static bool IsNSError(const ParmVarDecl *PD, IdentifierInfo *II); -static bool IsCFError(const ParmVarDecl *PD, IdentifierInfo *II); +static bool IsNSError(QualType T, IdentifierInfo *II); +static bool IsCFError(QualType T, IdentifierInfo *II); //===----------------------------------------------------------------------===// // NSErrorMethodChecker @@ -62,7 +62,7 @@ void NSErrorMethodChecker::checkASTDecl(const ObjCMethodDecl *D, bool hasNSError = false; for (ObjCMethodDecl::param_iterator I = D->param_begin(), E = D->param_end(); I != E; ++I) { - if (IsNSError(*I, II)) { + if (IsNSError((*I)->getType(), II)) { hasNSError = true; break; } @@ -108,7 +108,7 @@ void CFErrorFunctionChecker::checkASTDecl(const FunctionDecl *D, bool hasCFError = false; for (FunctionDecl::param_const_iterator I = D->param_begin(), E = D->param_end(); I != E; ++I) { - if (IsCFError(*I, II)) { + if (IsCFError((*I)->getType(), II)) { hasCFError = true; break; } @@ -191,6 +191,17 @@ static void setFlag(const GRState *state, SVal val, CheckerContext &C) { C.addTransition(state->set(sym, true)); } +static QualType parameterTypeFromSVal(SVal val) { + if (const loc::MemRegionVal* X = dyn_cast(&val)) { + const MemRegion* R = X->getRegion(); + if (const VarRegion *VR = R->getAs()) + if (VR->hasStackParametersStorage()) + return VR->getValueType(); + } + + return QualType(); +} + void NSOrCFErrorDerefChecker::checkLocation(SVal loc, bool isLoad, CheckerContext &C) const { if (!isLoad) @@ -198,6 +209,7 @@ void NSOrCFErrorDerefChecker::checkLocation(SVal loc, bool isLoad, if (loc.isUndef() || !isa(loc)) return; + ASTContext &Ctx = C.getASTContext(); const GRState *state = C.getState(); // If we are loading from NSError**/CFErrorRef* parameter, mark the resulting @@ -205,23 +217,22 @@ void NSOrCFErrorDerefChecker::checkLocation(SVal loc, bool isLoad, // ImplicitNullDerefEvent event. // FIXME: Cumbersome! Maybe add hook at construction of SVals at start of // function ? - - const VarDecl *VD = loc.getAsVarDecl(); - if (!VD) return; - const ParmVarDecl *PD = dyn_cast(VD); - if (!PD) return; + + QualType parmT = parameterTypeFromSVal(loc); + if (parmT.isNull()) + return; if (!NSErrorII) - NSErrorII = &PD->getASTContext().Idents.get("NSError"); + NSErrorII = &Ctx.Idents.get("NSError"); if (!CFErrorII) - CFErrorII = &PD->getASTContext().Idents.get("CFErrorRef"); + CFErrorII = &Ctx.Idents.get("CFErrorRef"); - if (ShouldCheckNSError && IsNSError(PD, NSErrorII)) { + if (ShouldCheckNSError && IsNSError(parmT, NSErrorII)) { setFlag(state, state->getSVal(cast(loc)), C); return; } - if (ShouldCheckCFError && IsCFError(PD, CFErrorII)) { + if (ShouldCheckCFError && IsCFError(parmT, CFErrorII)) { setFlag(state, state->getSVal(cast(loc)), C); return; } @@ -267,9 +278,9 @@ void NSOrCFErrorDerefChecker::checkEvent(ImplicitNullDerefEvent event) const { BR.EmitReport(report); } -static bool IsNSError(const ParmVarDecl *PD, IdentifierInfo *II) { +static bool IsNSError(QualType T, IdentifierInfo *II) { - const PointerType* PPT = PD->getType()->getAs(); + const PointerType* PPT = T->getAs(); if (!PPT) return false; @@ -288,8 +299,8 @@ static bool IsNSError(const ParmVarDecl *PD, IdentifierInfo *II) { return false; } -static bool IsCFError(const ParmVarDecl *PD, IdentifierInfo *II) { - const PointerType* PPT = PD->getType()->getAs(); +static bool IsCFError(QualType T, IdentifierInfo *II) { + const PointerType* PPT = T->getAs(); if (!PPT) return false; const TypedefType* TT = PPT->getPointeeType()->getAs(); diff --git a/lib/StaticAnalyzer/Core/SVals.cpp b/lib/StaticAnalyzer/Core/SVals.cpp index 76ad94e40d..4614e349de 100644 --- a/lib/StaticAnalyzer/Core/SVals.cpp +++ b/lib/StaticAnalyzer/Core/SVals.cpp @@ -60,16 +60,6 @@ const FunctionDecl *SVal::getAsFunctionDecl() const { return NULL; } -const VarDecl* SVal::getAsVarDecl() const { - if (const loc::MemRegionVal* X = dyn_cast(this)) { - const MemRegion* R = X->getRegion(); - if (const VarRegion *VR = R->getAs()) - return cast(VR->getDecl()); - } - - return NULL; -} - /// getAsLocSymbol - If this SVal is a location (subclasses Loc) and /// wraps a symbol, return that SymbolRef. Otherwise return 0. // FIXME: should we consider SymbolRef wrapped in CodeTextRegion? -- 2.11.4.GIT