diff options
author | Steve Naroff <snaroff@apple.com> | 2009-07-10 23:34:53 +0000 |
---|---|---|
committer | Steve Naroff <snaroff@apple.com> | 2009-07-10 23:34:53 +0000 |
commit | 14108da7f7fc059772711e4ffee1322a27b152a7 (patch) | |
tree | 5461a189505985c1c245c3f63a48030f0cd5e929 /lib/Analysis/CFRefCount.cpp | |
parent | 7ecbfbcddd278eede10bd38fa03a95a2110b191a (diff) |
This patch includes a conceptually simple, but very intrusive/pervasive change.
The idea is to segregate Objective-C "object" pointers from general C pointers (utilizing the recently added ObjCObjectPointerType). The fun starts in Sema::GetTypeForDeclarator(), where "SomeInterface *" is now represented by a single AST node (rather than a PointerType whose Pointee is an ObjCInterfaceType). Since a significant amount of code assumed ObjC object pointers where based on C pointers/structs, this patch is very tedious. It should also explain why it is hard to accomplish this in smaller, self-contained patches.
This patch does most of the "heavy lifting" related to moving from PointerType->ObjCObjectPointerType. It doesn't include all potential "cleanups". The good news is additional cleanups can be done later (some are noted in the code). This patch is so large that I didn't want to include any changes that are purely aesthetic.
By making the ObjC types truly built-in, they are much easier to work with (and require fewer "hacks"). For example, there is no need for ASTContext::isObjCIdStructType() or ASTContext::isObjCClassStructType()! We believe this change (and the follow-up cleanups) will pay dividends over time.
Given the amount of code change, I do expect some fallout from this change (though it does pass all of the clang tests). If you notice any problems, please let us know asap! Thanks.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@75314 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis/CFRefCount.cpp')
-rw-r--r-- | lib/Analysis/CFRefCount.cpp | 94 |
1 files changed, 39 insertions, 55 deletions
diff --git a/lib/Analysis/CFRefCount.cpp b/lib/Analysis/CFRefCount.cpp index c74668cf0f..1cfd783492 100644 --- a/lib/Analysis/CFRefCount.cpp +++ b/lib/Analysis/CFRefCount.cpp @@ -547,14 +547,12 @@ public: return I == M.end() ? M.find(ObjCSummaryKey(S)) : I; } - ObjCInterfaceDecl* getReceiverDecl(Expr* E) { - - const PointerType* PT = E->getType()->getAsPointerType(); - if (!PT) return 0; - - ObjCInterfaceType* OI = dyn_cast<ObjCInterfaceType>(PT->getPointeeType()); - - return OI ? OI->getDecl() : 0; + const ObjCInterfaceDecl* getReceiverDecl(Expr* E) { + if (const ObjCObjectPointerType* PT = + E->getType()->getAsObjCObjectPointerType()) + return PT->getInterfaceDecl(); + + return NULL; } iterator end() { return M.end(); } @@ -564,7 +562,7 @@ public: Selector S = ME->getSelector(); if (Expr* Receiver = ME->getReceiver()) { - ObjCInterfaceDecl* OD = getReceiverDecl(Receiver); + const ObjCInterfaceDecl* OD = getReceiverDecl(Receiver); return OD ? M[ObjCSummaryKey(OD->getIdentifier(), S)] : M[S]; } @@ -886,20 +884,20 @@ bool RetainSummaryManager::isTrackedObjCObjectType(QualType Ty) { if (!Ctx.isObjCObjectPointerType(Ty)) return false; - // We assume that id<..>, id, and "Class" all represent tracked objects. - const PointerType *PT = Ty->getAsPointerType(); - if (PT == 0) + const ObjCObjectPointerType *PT = Ty->getAsObjCObjectPointerType(); + + // Can be true for objects with the 'NSObject' attribute. + if (!PT) return true; - - const ObjCInterfaceType *OT = PT->getPointeeType()->getAsObjCInterfaceType(); - + // We assume that id<..>, id, and "Class" all represent tracked objects. - if (!OT) + if (PT->isObjCIdType() || PT->isObjCQualifiedIdType() || + PT->isObjCClassType()) return true; - + // Does the interface subclass NSObject? // FIXME: We can memoize here if this gets too expensive. - ObjCInterfaceDecl* ID = OT->getDecl(); + const ObjCInterfaceDecl *ID = PT->getInterfaceDecl(); // Assume that anything declared with a forward declaration and no // @interface subclasses NSObject. @@ -908,7 +906,6 @@ bool RetainSummaryManager::isTrackedObjCObjectType(QualType Ty) { IdentifierInfo* NSObjectII = &Ctx.Idents.get("NSObject"); - for ( ; ID ; ID = ID->getSuperClass()) if (ID->getIdentifier() == NSObjectII) return true; @@ -977,7 +974,7 @@ RetainSummary* RetainSummaryManager::getSummary(FunctionDecl* FD) { case 17: // Handle: id NSMakeCollectable(CFTypeRef) if (!memcmp(FName, "NSMakeCollectable", 17)) { - S = (RetTy == Ctx.getObjCIdType()) + S = (RetTy->isObjCIdType()) ? getUnarySummary(FT, cfmakecollectable) : getPersistentStopSummary(); } @@ -2726,34 +2723,26 @@ CFRefLeakReport::CFRefLeakReport(CFRefBug& D, const CFRefCount &tf, /// While the the return type can be queried directly from RetEx, when /// invoking class methods we augment to the return type to be that of /// a pointer to the class (as opposed it just being id). -static QualType GetReturnType(Expr* RetE, ASTContext& Ctx) { - +static QualType GetReturnType(const Expr* RetE, ASTContext& Ctx) { QualType RetTy = RetE->getType(); - - // FIXME: We aren't handling id<...>. - const PointerType* PT = RetTy->getAsPointerType(); - if (!PT) - return RetTy; - - // If RetEx is not a message expression just return its type. - // If RetEx is a message expression, return its types if it is something + // If RetE is not a message expression just return its type. + // If RetE is a message expression, return its types if it is something /// more specific than id. + if (const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(RetE)) + if (const ObjCObjectPointerType *PT = RetTy->getAsObjCObjectPointerType()) + if (PT->isObjCQualifiedIdType() || PT->isObjCIdType() || + PT->isObjCClassType()) { + // At this point we know the return type of the message expression is + // id, id<...>, or Class. If we have an ObjCInterfaceDecl, we know this + // is a call to a class method whose type we can resolve. In such + // cases, promote the return type to XXX* (where XXX is the class). + const ObjCInterfaceDecl *D = ME->getClassInfo().first; + return !D ? RetTy : Ctx.getPointerType(Ctx.getObjCInterfaceType(D)); + } - ObjCMessageExpr* ME = dyn_cast<ObjCMessageExpr>(RetE); - - if (!ME || !Ctx.isObjCIdStructType(PT->getPointeeType())) - return RetTy; - - ObjCInterfaceDecl* D = ME->getClassInfo().first; - - // At this point we know the return type of the message expression is id. - // If we have an ObjCInterceDecl, we know this is a call to a class method - // whose type we can resolve. In such cases, promote the return type to - // Class*. - return !D ? RetTy : Ctx.getPointerType(Ctx.getObjCInterfaceType(D)); + return RetTy; } - void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst, GRExprEngine& Eng, GRStmtNodeBuilder<GRState>& Builder, @@ -3009,26 +2998,21 @@ void CFRefCount::EvalObjCMessageExpr(ExplodedNodeSet<GRState>& Dst, SVal V = St->getSValAsScalarOrLoc(Receiver); SymbolRef Sym = V.getAsLocSymbol(); + if (Sym) { if (const RefVal* T = St->get<RefBindings>(Sym)) { - QualType Ty = T->getType(); - - if (const PointerType* PT = Ty->getAsPointerType()) { - QualType PointeeTy = PT->getPointeeType(); - - if (ObjCInterfaceType* IT = dyn_cast<ObjCInterfaceType>(PointeeTy)) - ID = IT->getDecl(); - } + if (const ObjCObjectPointerType* PT = + T->getType()->getAsObjCObjectPointerType()) + ID = PT->getInterfaceDecl(); } } // FIXME: this is a hack. This may or may not be the actual method // that is called. if (!ID) { - if (const PointerType *PT = Receiver->getType()->getAsPointerType()) - if (const ObjCInterfaceType *p = - PT->getPointeeType()->getAsObjCInterfaceType()) - ID = p->getDecl(); + if (const ObjCObjectPointerType *PT = + Receiver->getType()->getAsObjCObjectPointerType()) + ID = PT->getInterfaceDecl(); } // FIXME: The receiver could be a reference to a class, meaning that |