From 5fc1d0c4532c55cc47ba6628f296bf5b86d2eaf0 Mon Sep 17 00:00:00 2001 From: Anna Zaks Date: Mon, 17 Sep 2012 19:13:56 +0000 Subject: [PATCH] [analyzer] Teach the analyzer about implicit initialization of statics in ObjCMethods. Extend FunctionTextRegion to represent ObjC methods as well as functions. Note, it is not clear what type ObjCMethod region should return. Since the type of the FunctionText region is not currently used, defer solving this issue. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@164046 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Core/PathSensitive/MemRegion.h | 28 +++++++++++++------ .../Checkers/CStringChecker.cpp | 2 +- lib/StaticAnalyzer/Checkers/MallocChecker.cpp | 2 +- lib/StaticAnalyzer/Core/MemRegion.cpp | 14 ++++------ lib/StaticAnalyzer/Core/SVals.cpp | 3 +- test/Analysis/static_local.m | 18 ++++++++++++ 6 files changed, 48 insertions(+), 19 deletions(-) create mode 100644 test/Analysis/static_local.m diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h index 8484aefdc3..3c9c33a645 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h @@ -533,16 +533,28 @@ public: /// FunctionTextRegion - A region that represents code texts of function. class FunctionTextRegion : public CodeTextRegion { - const FunctionDecl *FD; + const NamedDecl *FD; public: - FunctionTextRegion(const FunctionDecl *fd, const MemRegion* sreg) - : CodeTextRegion(sreg, FunctionTextRegionKind), FD(fd) {} + FunctionTextRegion(const NamedDecl *fd, const MemRegion* sreg) + : CodeTextRegion(sreg, FunctionTextRegionKind), FD(fd) { + assert(isa(fd) || isa(fd)); + } QualType getLocationType() const { - return getContext().getPointerType(FD->getType()); + const ASTContext &Ctx = getContext(); + if (const FunctionDecl *D = dyn_cast(FD)) { + return Ctx.getPointerType(D->getType()); + } + + assert(isa(FD)); + assert(false && "Getting the type of ObjCMethod is not supported yet"); + + // TODO: We might want to return a different type here (ex: id (*ty)(...)) + // depending on how it is used. + return QualType(); } - - const FunctionDecl *getDecl() const { + + const NamedDecl *getDecl() const { return FD; } @@ -550,7 +562,7 @@ public: void Profile(llvm::FoldingSetNodeID& ID) const; - static void ProfileRegion(llvm::FoldingSetNodeID& ID, const FunctionDecl *FD, + static void ProfileRegion(llvm::FoldingSetNodeID& ID, const NamedDecl *FD, const MemRegion*); static bool classof(const MemRegion* R) { @@ -1217,7 +1229,7 @@ public: return getCXXBaseObjectRegion(baseReg->getDecl(), superRegion); } - const FunctionTextRegion *getFunctionTextRegion(const FunctionDecl *FD); + const FunctionTextRegion *getFunctionTextRegion(const NamedDecl *FD); const BlockTextRegion *getBlockTextRegion(const BlockDecl *BD, CanQualType locTy, AnalysisDeclContext *AC); diff --git a/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/lib/StaticAnalyzer/Checkers/CStringChecker.cpp index 1e5189d69f..e9ca429521 100644 --- a/lib/StaticAnalyzer/Checkers/CStringChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/CStringChecker.cpp @@ -842,7 +842,7 @@ bool CStringChecker::SummarizeRegion(raw_ostream &os, ASTContext &Ctx, switch (MR->getKind()) { case MemRegion::FunctionTextRegionKind: { - const FunctionDecl *FD = cast(MR)->getDecl(); + const NamedDecl *FD = cast(MR)->getDecl(); if (FD) os << "the address of the function '" << *FD << '\''; else diff --git a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp index f57ea12ee0..c036d739dd 100644 --- a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -739,7 +739,7 @@ bool MallocChecker::SummarizeRegion(raw_ostream &os, const MemRegion *MR) { switch (MR->getKind()) { case MemRegion::FunctionTextRegionKind: { - const FunctionDecl *FD = cast(MR)->getDecl(); + const NamedDecl *FD = cast(MR)->getDecl(); if (FD) os << "the address of the function '" << *FD << '\''; else diff --git a/lib/StaticAnalyzer/Core/MemRegion.cpp b/lib/StaticAnalyzer/Core/MemRegion.cpp index 8c3c1250e6..48d459452d 100644 --- a/lib/StaticAnalyzer/Core/MemRegion.cpp +++ b/lib/StaticAnalyzer/Core/MemRegion.cpp @@ -352,7 +352,7 @@ void ElementRegion::Profile(llvm::FoldingSetNodeID& ID) const { } void FunctionTextRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, - const FunctionDecl *FD, + const NamedDecl *FD, const MemRegion*) { ID.AddInteger(MemRegion::FunctionTextRegionKind); ID.AddPointer(FD); @@ -748,11 +748,11 @@ const VarRegion* MemRegionManager::getVarRegion(const VarDecl *D, } else { assert(D->isStaticLocal()); - const Decl *D = STC->getDecl(); - if (const FunctionDecl *FD = dyn_cast(D)) + const Decl *STCD = STC->getDecl(); + if (isa(STCD) || isa(STCD)) sReg = getGlobalsRegion(MemRegion::StaticGlobalSpaceRegionKind, - getFunctionTextRegion(FD)); - else if (const BlockDecl *BD = dyn_cast(D)) { + getFunctionTextRegion(cast(STCD))); + else if (const BlockDecl *BD = dyn_cast(STCD)) { const BlockTextRegion *BTR = getBlockTextRegion(BD, C.getCanonicalType(BD->getSignatureAsWritten()->getType()), @@ -761,8 +761,6 @@ const VarRegion* MemRegionManager::getVarRegion(const VarDecl *D, BTR); } else { - // FIXME: For ObjC-methods, we need a new CodeTextRegion. For now - // just use the main global memspace. sReg = getGlobalsRegion(); } } @@ -845,7 +843,7 @@ MemRegionManager::getElementRegion(QualType elementType, NonLoc Idx, } const FunctionTextRegion * -MemRegionManager::getFunctionTextRegion(const FunctionDecl *FD) { +MemRegionManager::getFunctionTextRegion(const NamedDecl *FD) { return getSubRegion(FD, getCodeRegion()); } diff --git a/lib/StaticAnalyzer/Core/SVals.cpp b/lib/StaticAnalyzer/Core/SVals.cpp index 8437f50f91..e34ab6a2be 100644 --- a/lib/StaticAnalyzer/Core/SVals.cpp +++ b/lib/StaticAnalyzer/Core/SVals.cpp @@ -51,7 +51,8 @@ const FunctionDecl *SVal::getAsFunctionDecl() const { if (const loc::MemRegionVal* X = dyn_cast(this)) { const MemRegion* R = X->getRegion(); if (const FunctionTextRegion *CTR = R->getAs()) - return CTR->getDecl(); + if (const FunctionDecl *FD = dyn_cast(CTR->getDecl())) + return FD; } return 0; diff --git a/test/Analysis/static_local.m b/test/Analysis/static_local.m new file mode 100644 index 0000000000..709262535f --- /dev/null +++ b/test/Analysis/static_local.m @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -analyze -analyzer-checker=core -verify -Wno-objc-root-class %s + +// Test reasoning about static locals in ObjCMethods. +int *getValidPtr(); +@interface Radar11275803 +- (int) useStaticInMethod; +@end +@implementation Radar11275803 + +- (int) useStaticInMethod +{ + static int *explInit = 0; + static int implInit; + if (!implInit) + explInit = getValidPtr(); + return *explInit; //no-warning +} +@end \ No newline at end of file -- 2.40.0