/// 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<ObjCMethodDecl>(fd) || isa<FunctionDecl>(fd));
+ }
QualType getLocationType() const {
- return getContext().getPointerType(FD->getType());
+ const ASTContext &Ctx = getContext();
+ if (const FunctionDecl *D = dyn_cast<FunctionDecl>(FD)) {
+ return Ctx.getPointerType(D->getType());
+ }
+
+ assert(isa<ObjCMethodDecl>(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;
}
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) {
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);
switch (MR->getKind()) {
case MemRegion::FunctionTextRegionKind: {
- const FunctionDecl *FD = cast<FunctionTextRegion>(MR)->getDecl();
+ const NamedDecl *FD = cast<FunctionTextRegion>(MR)->getDecl();
if (FD)
os << "the address of the function '" << *FD << '\'';
else
const MemRegion *MR) {
switch (MR->getKind()) {
case MemRegion::FunctionTextRegionKind: {
- const FunctionDecl *FD = cast<FunctionTextRegion>(MR)->getDecl();
+ const NamedDecl *FD = cast<FunctionTextRegion>(MR)->getDecl();
if (FD)
os << "the address of the function '" << *FD << '\'';
else
}
void FunctionTextRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
- const FunctionDecl *FD,
+ const NamedDecl *FD,
const MemRegion*) {
ID.AddInteger(MemRegion::FunctionTextRegionKind);
ID.AddPointer(FD);
}
else {
assert(D->isStaticLocal());
- const Decl *D = STC->getDecl();
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
+ const Decl *STCD = STC->getDecl();
+ if (isa<FunctionDecl>(STCD) || isa<ObjCMethodDecl>(STCD))
sReg = getGlobalsRegion(MemRegion::StaticGlobalSpaceRegionKind,
- getFunctionTextRegion(FD));
- else if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) {
+ getFunctionTextRegion(cast<NamedDecl>(STCD)));
+ else if (const BlockDecl *BD = dyn_cast<BlockDecl>(STCD)) {
const BlockTextRegion *BTR =
getBlockTextRegion(BD,
C.getCanonicalType(BD->getSignatureAsWritten()->getType()),
BTR);
}
else {
- // FIXME: For ObjC-methods, we need a new CodeTextRegion. For now
- // just use the main global memspace.
sReg = getGlobalsRegion();
}
}
}
const FunctionTextRegion *
-MemRegionManager::getFunctionTextRegion(const FunctionDecl *FD) {
+MemRegionManager::getFunctionTextRegion(const NamedDecl *FD) {
return getSubRegion<FunctionTextRegion>(FD, getCodeRegion());
}
if (const loc::MemRegionVal* X = dyn_cast<loc::MemRegionVal>(this)) {
const MemRegion* R = X->getRegion();
if (const FunctionTextRegion *CTR = R->getAs<FunctionTextRegion>())
- return CTR->getDecl();
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CTR->getDecl()))
+ return FD;
}
return 0;
--- /dev/null
+// 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