diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AST/Expr.cpp | 241 | ||||
-rw-r--r-- | lib/AST/StmtDumper.cpp | 19 | ||||
-rw-r--r-- | lib/AST/StmtPrinter.cpp | 18 | ||||
-rw-r--r-- | lib/Checker/BasicObjCFoundationChecks.cpp | 41 | ||||
-rw-r--r-- | lib/Checker/BugReporterVisitors.cpp | 10 | ||||
-rw-r--r-- | lib/Checker/CFRefCount.cpp | 113 | ||||
-rw-r--r-- | lib/Checker/CallAndMessageChecker.cpp | 12 | ||||
-rw-r--r-- | lib/Checker/CheckObjCDealloc.cpp | 20 | ||||
-rw-r--r-- | lib/Checker/GRExprEngine.cpp | 8 | ||||
-rw-r--r-- | lib/Checker/NSAutoreleasePoolChecker.cpp | 2 | ||||
-rw-r--r-- | lib/CodeGen/CGObjC.cpp | 39 | ||||
-rw-r--r-- | lib/Frontend/PCHReaderStmt.cpp | 48 | ||||
-rw-r--r-- | lib/Frontend/PCHWriterStmt.cpp | 35 | ||||
-rw-r--r-- | lib/Frontend/RewriteObjC.cpp | 445 | ||||
-rw-r--r-- | lib/Index/Analyzer.cpp | 79 | ||||
-rw-r--r-- | lib/Sema/SemaCodeComplete.cpp | 25 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 8 | ||||
-rw-r--r-- | lib/Sema/SemaExprObjC.cpp | 191 |
18 files changed, 802 insertions, 552 deletions
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 88b5b5e567..71e8d072e4 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -2239,101 +2239,156 @@ void ExtVectorElementExpr::getEncodedElementAccess( } } -// constructor for instance messages. -ObjCMessageExpr::ObjCMessageExpr(ASTContext &C, Expr *receiver, - Selector selInfo, - QualType retType, ObjCMethodDecl *mproto, - SourceLocation LBrac, SourceLocation RBrac, - Expr **ArgExprs, unsigned nargs) - : Expr(ObjCMessageExprClass, retType, false, false), SelName(selInfo), - MethodProto(mproto) { - NumArgs = nargs; - SubExprs = new (C) Stmt*[NumArgs+1]; - SubExprs[RECEIVER] = receiver; - if (NumArgs) { - for (unsigned i = 0; i != NumArgs; ++i) - SubExprs[i+ARGS_START] = static_cast<Expr *>(ArgExprs[i]); - } - LBracloc = LBrac; - RBracloc = RBrac; -} - -// constructor for class messages. -// FIXME: clsName should be typed to ObjCInterfaceType -ObjCMessageExpr::ObjCMessageExpr(ASTContext &C, IdentifierInfo *clsName, - SourceLocation clsNameLoc, Selector selInfo, - QualType retType, ObjCMethodDecl *mproto, - SourceLocation LBrac, SourceLocation RBrac, - Expr **ArgExprs, unsigned nargs) - : Expr(ObjCMessageExprClass, retType, false, false), ClassNameLoc(clsNameLoc), - SelName(selInfo), MethodProto(mproto) { - NumArgs = nargs; - SubExprs = new (C) Stmt*[NumArgs+1]; - SubExprs[RECEIVER] = (Expr*) ((uintptr_t) clsName | IsClsMethDeclUnknown); - if (NumArgs) { - for (unsigned i = 0; i != NumArgs; ++i) - SubExprs[i+ARGS_START] = static_cast<Expr *>(ArgExprs[i]); - } - LBracloc = LBrac; - RBracloc = RBrac; -} - -// constructor for class messages. -ObjCMessageExpr::ObjCMessageExpr(ASTContext &C, ObjCInterfaceDecl *cls, - SourceLocation clsNameLoc, Selector selInfo, - QualType retType, - ObjCMethodDecl *mproto, SourceLocation LBrac, - SourceLocation RBrac, Expr **ArgExprs, - unsigned nargs) - : Expr(ObjCMessageExprClass, retType, false, false), ClassNameLoc(clsNameLoc), - SelName(selInfo), MethodProto(mproto) +ObjCMessageExpr::ObjCMessageExpr(QualType T, + SourceLocation LBracLoc, + SourceLocation SuperLoc, + bool IsInstanceSuper, + QualType SuperType, + Selector Sel, + ObjCMethodDecl *Method, + Expr **Args, unsigned NumArgs, + SourceLocation RBracLoc) + : Expr(ObjCMessageExprClass, T, /*TypeDependent=*/false, + hasAnyValueDependentArguments(Args, NumArgs)), + NumArgs(NumArgs), Kind(IsInstanceSuper? SuperInstance : SuperClass), + HasMethod(Method != 0), SuperLoc(SuperLoc), + SelectorOrMethod(reinterpret_cast<uintptr_t>(Method? Method + : Sel.getAsOpaquePtr())), + LBracLoc(LBracLoc), RBracLoc(RBracLoc) { - NumArgs = nargs; - SubExprs = new (C) Stmt*[NumArgs+1]; - SubExprs[RECEIVER] = (Expr*) ((uintptr_t) cls | IsClsMethDeclKnown); - if (NumArgs) { - for (unsigned i = 0; i != NumArgs; ++i) - SubExprs[i+ARGS_START] = static_cast<Expr *>(ArgExprs[i]); - } - LBracloc = LBrac; - RBracloc = RBrac; -} + setReceiverPointer(SuperType.getAsOpaquePtr()); + if (NumArgs) + memcpy(getArgs(), Args, NumArgs * sizeof(Expr *)); +} + +ObjCMessageExpr::ObjCMessageExpr(QualType T, + SourceLocation LBracLoc, + TypeSourceInfo *Receiver, + Selector Sel, + ObjCMethodDecl *Method, + Expr **Args, unsigned NumArgs, + SourceLocation RBracLoc) + : Expr(ObjCMessageExprClass, T, T->isDependentType(), + (T->isDependentType() || + hasAnyValueDependentArguments(Args, NumArgs))), + NumArgs(NumArgs), Kind(Class), HasMethod(Method != 0), + SelectorOrMethod(reinterpret_cast<uintptr_t>(Method? Method + : Sel.getAsOpaquePtr())), + LBracLoc(LBracLoc), RBracLoc(RBracLoc) +{ + setReceiverPointer(Receiver); + if (NumArgs) + memcpy(getArgs(), Args, NumArgs * sizeof(Expr *)); +} + +ObjCMessageExpr::ObjCMessageExpr(QualType T, + SourceLocation LBracLoc, + Expr *Receiver, + Selector Sel, + ObjCMethodDecl *Method, + Expr **Args, unsigned NumArgs, + SourceLocation RBracLoc) + : Expr(ObjCMessageExprClass, T, T->isDependentType(), + (T->isDependentType() || + hasAnyValueDependentArguments(Args, NumArgs))), + NumArgs(NumArgs), Kind(Instance), HasMethod(Method != 0), + SelectorOrMethod(reinterpret_cast<uintptr_t>(Method? Method + : Sel.getAsOpaquePtr())), + LBracLoc(LBracLoc), RBracLoc(RBracLoc) +{ + setReceiverPointer(Receiver); + if (NumArgs) + memcpy(getArgs(), Args, NumArgs * sizeof(Expr *)); +} + +ObjCMessageExpr *ObjCMessageExpr::Create(ASTContext &Context, QualType T, + SourceLocation LBracLoc, + SourceLocation SuperLoc, + bool IsInstanceSuper, + QualType SuperType, + Selector Sel, + ObjCMethodDecl *Method, + Expr **Args, unsigned NumArgs, + SourceLocation RBracLoc) { + unsigned Size = sizeof(ObjCMessageExpr) + sizeof(void *) + + NumArgs * sizeof(Expr *); + void *Mem = Context.Allocate(Size, llvm::AlignOf<ObjCMessageExpr>::Alignment); + return new (Mem) ObjCMessageExpr(T, LBracLoc, SuperLoc, IsInstanceSuper, + SuperType, Sel, Method, Args, NumArgs, + RBracLoc); +} + +ObjCMessageExpr *ObjCMessageExpr::Create(ASTContext &Context, QualType T, + SourceLocation LBracLoc, + TypeSourceInfo *Receiver, + Selector Sel, + ObjCMethodDecl *Method, + Expr **Args, unsigned NumArgs, + SourceLocation RBracLoc) { + unsigned Size = sizeof(ObjCMessageExpr) + sizeof(void *) + + NumArgs * sizeof(Expr *); + void *Mem = Context.Allocate(Size, llvm::AlignOf<ObjCMessageExpr>::Alignment); + return new (Mem) ObjCMessageExpr(T, LBracLoc, Receiver, Sel, Method, Args, + NumArgs, RBracLoc); +} + +ObjCMessageExpr *ObjCMessageExpr::Create(ASTContext &Context, QualType T, + SourceLocation LBracLoc, + Expr *Receiver, + Selector Sel, + ObjCMethodDecl *Method, + Expr **Args, unsigned NumArgs, + SourceLocation RBracLoc) { + unsigned Size = sizeof(ObjCMessageExpr) + sizeof(void *) + + NumArgs * sizeof(Expr *); + void *Mem = Context.Allocate(Size, llvm::AlignOf<ObjCMessageExpr>::Alignment); + return new (Mem) ObjCMessageExpr(T, LBracLoc, Receiver, Sel, Method, Args, + NumArgs, RBracLoc); +} + +ObjCMessageExpr *ObjCMessageExpr::CreateEmpty(ASTContext &Context, + unsigned NumArgs) { + unsigned Size = sizeof(ObjCMessageExpr) + sizeof(void *) + + NumArgs * sizeof(Expr *); + void *Mem = Context.Allocate(Size, llvm::AlignOf<ObjCMessageExpr>::Alignment); + return new (Mem) ObjCMessageExpr(EmptyShell(), NumArgs); +} + +Selector ObjCMessageExpr::getSelector() const { + if (HasMethod) + return reinterpret_cast<const ObjCMethodDecl *>(SelectorOrMethod) + ->getSelector(); + return Selector(SelectorOrMethod); +} + +ObjCInterfaceDecl *ObjCMessageExpr::getReceiverInterface() const { + switch (getReceiverKind()) { + case Instance: + if (const ObjCObjectPointerType *Ptr + = getInstanceReceiver()->getType()->getAs<ObjCObjectPointerType>()) + return Ptr->getInterfaceDecl(); + break; -ObjCMessageExpr::ClassInfo ObjCMessageExpr::getClassInfo() const { - uintptr_t x = (uintptr_t) SubExprs[RECEIVER]; - switch (x & Flags) { - default: - assert(false && "Invalid ObjCMessageExpr."); - case IsInstMeth: - return ClassInfo(0, 0, SourceLocation()); - case IsClsMethDeclUnknown: - return ClassInfo(0, (IdentifierInfo*) (x & ~Flags), ClassNameLoc); - case IsClsMethDeclKnown: { - ObjCInterfaceDecl* D = (ObjCInterfaceDecl*) (x & ~Flags); - return ClassInfo(D, D->getIdentifier(), ClassNameLoc); - } - } -} + case Class: + if (const ObjCInterfaceType *Iface + = getClassReceiver()->getAs<ObjCInterfaceType>()) + return Iface->getDecl(); + break; -void ObjCMessageExpr::setClassInfo(const ObjCMessageExpr::ClassInfo &CI) { - if (CI.Decl == 0 && CI.Name == 0) { - SubExprs[RECEIVER] = (Expr*)((uintptr_t)0 | IsInstMeth); - return; - } + case SuperInstance: + if (const ObjCObjectPointerType *Ptr + = getSuperType()->getAs<ObjCObjectPointerType>()) + return Ptr->getInterfaceDecl(); + break; - if (CI.Decl == 0) - SubExprs[RECEIVER] = (Expr*)((uintptr_t)CI.Name | IsClsMethDeclUnknown); - else - SubExprs[RECEIVER] = (Expr*)((uintptr_t)CI.Decl | IsClsMethDeclKnown); - ClassNameLoc = CI.Loc; -} + case SuperClass: + if (const ObjCObjectPointerType *Iface + = getSuperType()->getAs<ObjCObjectPointerType>()) + return Iface->getInterfaceDecl(); + break; + } -void ObjCMessageExpr::DoDestroy(ASTContext &C) { - DestroyChildren(C); - if (SubExprs) - C.Deallocate(SubExprs); - this->~ObjCMessageExpr(); - C.Deallocate((void*) this); + return 0; } bool ChooseExpr::isConditionTrue(ASTContext &C) const { @@ -2809,10 +2864,12 @@ Stmt::child_iterator ObjCProtocolExpr::child_end() { // ObjCMessageExpr Stmt::child_iterator ObjCMessageExpr::child_begin() { - return getReceiver() ? &SubExprs[0] : &SubExprs[0] + ARGS_START; + if (getReceiverKind() == Instance) + return reinterpret_cast<Stmt **>(this + 1); + return getArgs(); } Stmt::child_iterator ObjCMessageExpr::child_end() { - return &SubExprs[0]+ARGS_START+getNumArgs(); + return getArgs() + getNumArgs(); } // Blocks diff --git a/lib/AST/StmtDumper.cpp b/lib/AST/StmtDumper.cpp index 79f61f2bf3..05adc0292e 100644 --- a/lib/AST/StmtDumper.cpp +++ b/lib/AST/StmtDumper.cpp @@ -505,8 +505,23 @@ void StmtDumper::DumpCXXTemporary(CXXTemporary *Temporary) { void StmtDumper::VisitObjCMessageExpr(ObjCMessageExpr* Node) { DumpExpr(Node); OS << " selector=" << Node->getSelector().getAsString(); - if (IdentifierInfo *clsName = Node->getClassName()) - OS << " class=" << clsName->getNameStart(); + switch (Node->getReceiverKind()) { + case ObjCMessageExpr::Instance: + break; + + case ObjCMessageExpr::Class: + OS << " class="; + DumpType(Node->getClassReceiver()); + break; + + case ObjCMessageExpr::SuperInstance: + OS << " super (instance)"; + break; + + case ObjCMessageExpr::SuperClass: + OS << " super (class)"; + break; + } } void StmtDumper::VisitObjCEncodeExpr(ObjCEncodeExpr *Node) { diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp index 44d475853d..a895b63a79 100644 --- a/lib/AST/StmtPrinter.cpp +++ b/lib/AST/StmtPrinter.cpp @@ -1247,9 +1247,21 @@ void StmtPrinter::VisitObjCProtocolExpr(ObjCProtocolExpr *Node) { void StmtPrinter::VisitObjCMessageExpr(ObjCMessageExpr *Mess) { OS << "["; - Expr *receiver = Mess->getReceiver(); - if (receiver) PrintExpr(receiver); - else OS << Mess->getClassName()->getName(); + switch (Mess->getReceiverKind()) { + case ObjCMessageExpr::Instance: + PrintExpr(Mess->getInstanceReceiver()); + break; + + case ObjCMessageExpr::Class: + OS << Mess->getClassReceiver().getAsString(Policy); + break; + + case ObjCMessageExpr::SuperInstance: + case ObjCMessageExpr::SuperClass: + OS << "Super"; + break; + } + OS << ' '; Selector selector = Mess->getSelector(); if (selector.isUnarySelector()) { diff --git a/lib/Checker/BasicObjCFoundationChecks.cpp b/lib/Checker/BasicObjCFoundationChecks.cpp index 810d0fbb99..e7275ca551 100644 --- a/lib/Checker/BasicObjCFoundationChecks.cpp +++ b/lib/Checker/BasicObjCFoundationChecks.cpp @@ -31,13 +31,22 @@ using namespace clang; static const ObjCInterfaceType* GetReceiverType(const ObjCMessageExpr* ME) { - const Expr* Receiver = ME->getReceiver(); - - if (!Receiver) - return NULL; + QualType T; + switch (ME->getReceiverKind()) { + case ObjCMessageExpr::Instance: + T = ME->getInstanceReceiver()->getType(); + break; + + case ObjCMessageExpr::SuperInstance: + T = ME->getSuperType(); + break; + + case ObjCMessageExpr::Class: + case ObjCMessageExpr::SuperClass: + return 0; + } - if (const ObjCObjectPointerType *PT = - Receiver->getType()->getAs<ObjCObjectPointerType>()) + if (const ObjCObjectPointerType *PT = T->getAs<ObjCObjectPointerType>()) return PT->getInterfaceType(); return NULL; @@ -509,11 +518,21 @@ public: void ClassReleaseChecker::PreVisitObjCMessageExpr(CheckerContext &C, const ObjCMessageExpr *ME) { - - const IdentifierInfo *ClsName = ME->getClassName(); - if (!ClsName) + ObjCInterfaceDecl *Class = 0; + switch (ME->getReceiverKind()) { + case ObjCMessageExpr::Class: + Class = ME->getClassReceiver()->getAs<ObjCInterfaceType>()->getDecl(); + break; + + case ObjCMessageExpr::SuperClass: + Class = ME->getSuperType()->getAs<ObjCInterfaceType>()->getDecl(); + break; + + case ObjCMessageExpr::Instance: + case ObjCMessageExpr::SuperInstance: return; - + } + Selector S = ME->getSelector(); if (!(S == releaseS || S == retainS || S == autoreleaseS || S == drainS)) return; @@ -531,7 +550,7 @@ void ClassReleaseChecker::PreVisitObjCMessageExpr(CheckerContext &C, llvm::raw_svector_ostream os(buf); os << "The '" << S.getAsString() << "' message should be sent to instances " - "of class '" << ClsName->getName() + "of class '" << Class->getName() << "' and not the class directly"; RangedBugReport *report = new RangedBugReport(*BT, os.str(), N); diff --git a/lib/Checker/BugReporterVisitors.cpp b/lib/Checker/BugReporterVisitors.cpp index 544129bbf2..776e12bd2a 100644 --- a/lib/Checker/BugReporterVisitors.cpp +++ b/lib/Checker/BugReporterVisitors.cpp @@ -47,14 +47,6 @@ const Stmt *clang::bugreporter::GetDerefExpr(const ExplodedNode *N) { } const Stmt* -clang::bugreporter::GetReceiverExpr(const ExplodedNode *N){ - const Stmt *S = N->getLocationAs<PostStmt>()->getStmt(); - if (const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(S)) - return ME->getReceiver(); - return NULL; -} - -const Stmt* clang::bugreporter::GetDenomExpr(const ExplodedNode *N) { const Stmt *S = N->getLocationAs<PreStmt>()->getStmt(); if (const BinaryOperator *BE = dyn_cast<BinaryOperator>(S)) @@ -402,7 +394,7 @@ public: const ObjCMessageExpr *ME = P->getStmtAs<ObjCMessageExpr>(); if (!ME) return 0; - const Expr *Receiver = ME->getReceiver(); + const Expr *Receiver = ME->getInstanceReceiver(); if (!Receiver) return 0; const GRState *state = N->getState(); diff --git a/lib/Checker/CFRefCount.cpp b/lib/Checker/CFRefCount.cpp index a0b4666160..d26ee1db56 100644 --- a/lib/Checker/CFRefCount.cpp +++ b/lib/Checker/CFRefCount.cpp @@ -603,12 +603,33 @@ public: Selector S = ME->getSelector(); - if (Expr* Receiver = ME->getReceiver()) { - const ObjCInterfaceDecl* OD = getReceiverDecl(Receiver); - return OD ? M[ObjCSummaryKey(OD->getIdentifier(), S)] : M[S]; + const ObjCInterfaceDecl* OD = 0; + bool IsInstanceMessage = false; + switch (ME->getReceiverKind()) { + case ObjCMessageExpr::Instance: + OD = getReceiverDecl(ME->getInstanceReceiver()); + IsInstanceMessage = true; + break; + + case ObjCMessageExpr::SuperInstance: + IsInstanceMessage = true; + OD = ME->getSuperType()->getAs<ObjCObjectPointerType>() + ->getInterfaceDecl(); + break; + + case ObjCMessageExpr::Class: + OD = ME->getClassReceiver()->getAs<ObjCInterfaceType>()->getDecl(); + break; + + case ObjCMessageExpr::SuperClass: + OD = ME->getSuperType()->getAs<ObjCInterfaceType>()->getDecl(); + break; } - return M[ObjCSummaryKey(ME->getClassName(), S)]; + if (IsInstanceMessage) + return OD ? M[ObjCSummaryKey(OD->getIdentifier(), S)] : M[S]; + + return M[ObjCSummaryKey(OD->getIdentifier(), S)]; } RetainSummary*& operator[](ObjCSummaryKey K) { @@ -836,7 +857,7 @@ public: RetainSummary* getInstanceMethodSummary(const ObjCMessageExpr* ME, const ObjCInterfaceDecl* ID) { - return getInstanceMethodSummary(ME->getSelector(), ME->getClassName(), + return getInstanceMethodSummary(ME->getSelector(), 0, ID, ME->getMethodDecl(), ME->getType()); } @@ -851,8 +872,21 @@ public: QualType RetTy); RetainSummary *getClassMethodSummary(const ObjCMessageExpr *ME) { - return getClassMethodSummary(ME->getSelector(), ME->getClassName(), - ME->getClassInfo().Decl, + ObjCInterfaceDecl *Class = 0; + switch (ME->getReceiverKind()) { + case ObjCMessageExpr::Class: + case ObjCMessageExpr::SuperClass: + Class = ME->getReceiverInterface(); + break; + + case ObjCMessageExpr::Instance: + case ObjCMessageExpr::SuperInstance: + break; + } + + return getClassMethodSummary(ME->getSelector(), + Class? Class->getIdentifier() : 0, + Class, ME->getMethodDecl(), ME->getType()); } @@ -1333,37 +1367,44 @@ RetainSummaryManager::getInstanceMethodSummary(const ObjCMessageExpr *ME, // We need the type-information of the tracked receiver object // Retrieve it from the state. - const Expr *Receiver = ME->getReceiver(); + const Expr *Receiver = ME->getInstanceReceiver(); const ObjCInterfaceDecl* ID = 0; // FIXME: Is this really working as expected? There are cases where // we just use the 'ID' from the message expression. - SVal receiverV = state->getSValAsScalarOrLoc(Receiver); + SVal receiverV; + + if (const Expr *Receiver = ME->getInstanceReceiver()) { + receiverV = state->getSValAsScalarOrLoc(Receiver); - // FIXME: Eventually replace the use of state->get<RefBindings> with - // a generic API for reasoning about the Objective-C types of symbolic - // objects. - if (SymbolRef Sym = receiverV.getAsLocSymbol()) - if (const RefVal *T = state->get<RefBindings>(Sym)) - if (const ObjCObjectPointerType* PT = + // FIXME: Eventually replace the use of state->get<RefBindings> with + // a generic API for reasoning about the Objective-C types of symbolic + // objects. + if (SymbolRef Sym = receiverV.getAsLocSymbol()) + if (const RefVal *T = state->get<RefBindings>(Sym)) + if (const ObjCObjectPointerType* PT = T->getType()->getAs<ObjCObjectPointerType>()) - ID = PT->getInterfaceDecl(); + ID = PT->getInterfaceDecl(); - // FIXME: this is a hack. This may or may not be the actual method - // that is called. - if (!ID) { - if (const ObjCObjectPointerType *PT = - Receiver->getType()->getAs<ObjCObjectPointerType>()) - ID = PT->getInterfaceDecl(); + // FIXME: this is a hack. This may or may not be the actual method + // that is called. + if (!ID) { + if (const ObjCObjectPointerType *PT = + Receiver->getType()->getAs<ObjCObjectPointerType>()) + ID = PT->getInterfaceDecl(); + } + } else { + // FIXME: Hack for 'super'. + ID = ME->getReceiverInterface(); } - + // FIXME: The receiver could be a reference to a class, meaning that // we should use the class method. RetainSummary *Summ = getInstanceMethodSummary(ME, ID); // Special-case: are we sending a mesage to "self"? // This is a hack. When we have full-IP this should be removed. - if (isa<ObjCMethodDecl>(LC->getDecl())) { + if (isa<ObjCMethodDecl>(LC->getDecl()) && Receiver) { if (const loc::MemRegionVal *L = dyn_cast<loc::MemRegionVal>(&receiverV)) { // Get the region associated with 'self'. if (const ImplicitParamDecl *SelfDecl = LC->getSelfDecl()) { @@ -2144,7 +2185,7 @@ PathDiagnosticPiece* CFRefReport::VisitNode(const ExplodedNode* N, } } else if (const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(S)) { - if (const Expr *receiver = ME->getReceiver()) + if (const Expr *receiver = ME->getInstanceReceiver()) if (CurrSt->getSValAsScalarOrLoc(receiver).getAsLocSymbol() == Sym) { // The symbol we are tracking is the receiver. AEffects.push_back(Summ->getReceiverEffect()); @@ -2510,7 +2551,7 @@ static QualType GetReturnType(const Expr* RetE, ASTContext& Ctx) { // 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().Decl; + const ObjCInterfaceDecl *D = ME->getReceiverInterface(); return !D ? RetTy : Ctx.getPointerType(Ctx.getObjCInterfaceType(D)); } @@ -2660,15 +2701,15 @@ void CFRefCount::EvalSummary(ExplodedNodeSet& Dst, RetEffect RE = Summ.getRetEffect(); if (RE.getKind() == RetEffect::OwnedWhenTrackedReceiver) { - assert(Receiver); - SVal V = state->getSValAsScalarOrLoc(Receiver); bool found = false; - if (SymbolRef Sym = V.getAsLocSymbol()) - if (state->get<RefBindings>(Sym)) { - found = true; - RE = Summaries.getObjAllocRetEffect(); - } - + if (Receiver) { + SVal V = state->getSValAsScalarOrLoc(Receiver); + if (SymbolRef Sym = V.getAsLocSymbol()) + if (state->get<RefBindings>(Sym)) { + found = true; + RE = Summaries.getObjAllocRetEffect(); + } + } // FIXME: Otherwise, this is a send-to-super instance message. if (!found) RE = RetEffect::MakeNoRet(); } @@ -2802,12 +2843,12 @@ void CFRefCount::EvalObjCMessageExpr(ExplodedNodeSet& Dst, ExplodedNode* Pred, const GRState *state) { RetainSummary *Summ = - ME->getReceiver() + ME->isInstanceMessage() ? Summaries.getInstanceMethodSummary(ME, state,Pred->getLocationContext()) : Summaries.getClassMethodSummary(ME); assert(Summ && "RetainSummary is null"); - EvalSummary(Dst, Eng, Builder, ME, ME->getReceiver(), *Summ, NULL, + EvalSummary(Dst, Eng, Builder, ME, ME->getInstanceReceiver(), *Summ, NULL, ME->arg_begin(), ME->arg_end(), Pred, state); } diff --git a/lib/Checker/CallAndMessageChecker.cpp b/lib/Checker/CallAndMessageChecker.cpp index ce9f26ec69..9d0dc33395 100644 --- a/lib/Checker/CallAndMessageChecker.cpp +++ b/lib/Checker/CallAndMessageChecker.cpp @@ -218,7 +218,8 @@ void CallAndMessageChecker::PreVisitObjCMessageExpr(CheckerContext &C, const GRState *state = C.getState(); - if (const Expr *receiver = ME->getReceiver()) + // FIXME: Handle 'super'? + if (const Expr *receiver = ME->getInstanceReceiver()) if (state->getSVal(receiver).isUndef()) { if (ExplodedNode *N = C.GenerateSink()) { if (!BT_msg_undef) @@ -265,10 +266,11 @@ void CallAndMessageChecker::EmitNilReceiverBug(CheckerContext &C, << ME->getType().getAsString() << "' that will be garbage"; EnhancedBugReport *report = new EnhancedBugReport(*BT_msg_ret, os.str(), N); - const Expr *receiver = ME->getReceiver(); - report->addRange(receiver->getSourceRange()); - report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, - receiver); + if (const Expr *receiver = ME->getInstanceReceiver()) { + report->addRange(receiver->getSourceRange()); + report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, + receiver); + } C.EmitReport(report); } diff --git a/lib/Checker/CheckObjCDealloc.cpp b/lib/Checker/CheckObjCDealloc.cpp index f510de573e..c23be873f4 100644 --- a/lib/Checker/CheckObjCDealloc.cpp +++ b/lib/Checker/CheckObjCDealloc.cpp @@ -27,10 +27,14 @@ using namespace clang; static bool scan_dealloc(Stmt* S, Selector Dealloc) { if (ObjCMessageExpr* ME = dyn_cast<ObjCMessageExpr>(S)) - if (ME->getSelector() == Dealloc) - if (ME->getReceiver()) - if (Expr* Receiver = ME->getReceiver()->IgnoreParenCasts()) - return isa<ObjCSuperExpr>(Receiver); + if (ME->getSelector() == Dealloc) { + switch (ME->getReceiverKind()) { + case ObjCMessageExpr::Instance: return false; + case ObjCMessageExpr::SuperInstance: return true; + case ObjCMessageExpr::Class: break; + case ObjCMessageExpr::SuperClass: break; + } + } // Recurse to children. @@ -50,16 +54,16 @@ static bool scan_ivar_release(Stmt* S, ObjCIvarDecl* ID, // [mMyIvar release] if (ObjCMessageExpr* ME = dyn_cast<ObjCMessageExpr>(S)) if (ME->getSelector() == Release) - if (ME->getReceiver()) - if (Expr* Receiver = ME->getReceiver()->IgnoreParenCasts()) + if (ME->getInstanceReceiver()) + if (Expr* Receiver = ME->getInstanceReceiver()->IgnoreParenCasts()) if (ObjCIvarRefExpr* E = dyn_cast<ObjCIvarRefExpr>(Receiver)) if (E->getDecl() == ID) return true; // [self setMyIvar:nil]; if (ObjCMessageExpr* ME = dyn_cast<ObjCMessageExpr>(S)) - if (ME->getReceiver()) - if (Expr* Receiver = ME->getReceiver()->IgnoreParenCasts()) + if (ME->getInstanceReceiver()) + if (Expr* Receiver = ME->getInstanceReceiver()->IgnoreParenCasts()) if (DeclRefExpr* E = dyn_cast<DeclRefExpr>(Receiver)) if (E->getDecl()->getIdentifier() == SelfII) if (ME->getMethodDecl() == PD->getSetterMethodDecl() && diff --git a/lib/Checker/GRExprEngine.cpp b/lib/Checker/GRExprEngine.cpp index b5f8fee5a2..a39e7f57b1 100644 --- a/lib/Checker/GRExprEngine.cpp +++ b/lib/Checker/GRExprEngine.cpp @@ -2124,7 +2124,7 @@ void GRExprEngine::VisitObjCMessageExpr(ObjCMessageExpr* ME, ExplodedNode* Pred, // But first evaluate the receiver (if any). ObjCMessageExpr::arg_iterator AI = ME->arg_begin(), AE = ME->arg_end(); - if (Expr *Receiver = ME->getReceiver()) { + if (Expr *Receiver = ME->getInstanceReceiver()) { ExplodedNodeSet Tmp; Visit(Receiver, Pred, Tmp); @@ -2176,7 +2176,7 @@ void GRExprEngine::VisitObjCMessageExpr(ObjCMessageExpr* ME, ExplodedNode* Pred, SaveAndRestore<bool> OldSink(Builder->BuildSinks); SaveOr OldHasGen(Builder->HasGeneratedNode); - if (const Expr *Receiver = ME->getReceiver()) { + if (const Expr *Receiver = ME->getInstanceReceiver()) { const GRState *state = GetState(Pred); // Bifurcate the state into nil and non-nil ones. @@ -2206,8 +2206,8 @@ void GRExprEngine::VisitObjCMessageExpr(ObjCMessageExpr* ME, ExplodedNode* Pred, // Dispatch to plug-in transfer function. EvalObjCMessageExpr(DstEval, ME, Pred, notNilState); } - else { - IdentifierInfo* ClsName = ME->getClassName(); + else if (ObjCInterfaceDecl *Iface = ME->getReceiverInterface()) { + IdentifierInfo* ClsName = Iface->getIdentifier(); Selector S = ME->getSelector(); // Check for special instance methods. diff --git a/lib/Checker/NSAutoreleasePoolChecker.cpp b/lib/Checker/NSAutoreleasePoolChecker.cpp index 29bac9c384..48f03a369e 100644 --- a/lib/Checker/NSAutoreleasePoolChecker.cpp +++ b/lib/Checker/NSAutoreleasePoolChecker.cpp @@ -56,7 +56,7 @@ void NSAutoreleasePoolChecker::PreVisitObjCMessageExpr(CheckerContext &C, const ObjCMessageExpr *ME) { - const Expr *receiver = ME->getReceiver(); + const Expr *receiver = ME->getInstanceReceiver(); if (!receiver) return; diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp index ce96388507..e5da29a61b 100644 --- a/lib/CodeGen/CGObjC.cpp +++ b/lib/CodeGen/CGObjC.cpp @@ -53,31 +53,34 @@ RValue CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E) { // arguments in generic code. CGObjCRuntime &Runtime = CGM.getObjCRuntime(); - const Expr *ReceiverExpr = E->getReceiver(); bool isSuperMessage = false; bool isClassMessage = false; // Find the receiver llvm::Value *Receiver; - if (!ReceiverExpr) { - const ObjCInterfaceDecl *OID = E->getClassInfo().Decl; - - // Very special case, super send in class method. The receiver is - // self (the class object) and the send uses super semantics. - if (!OID) { - assert(E->getClassName()->isStr("super") && - "Unexpected missing class interface in message send."); - isSuperMessage = true; - Receiver = LoadObjCSelf(); - } else { - Receiver = Runtime.GetClass(Builder, OID); - } - + switch (E->getReceiverKind()) { + case ObjCMessageExpr::Instance: + Receiver = EmitScalarExpr(E->getInstanceReceiver()); + break; + + case ObjCMessageExpr::Class: { + const ObjCInterfaceType *IFace + = E->getClassReceiver()->getAs<ObjCInterfaceType>(); + assert(IFace && "Invalid Objective-C class message send"); + Receiver = Runtime.GetClass(Builder, IFace->getDecl()); isClassMessage = true; - } else if (isa<ObjCSuperExpr>(E->getReceiver())) { + break; + } + + case ObjCMessageExpr::SuperInstance: + Receiver = LoadObjCSelf(); isSuperMessage = true; + break; + + case ObjCMessageExpr::SuperClass: Receiver = LoadObjCSelf(); - } else { - Receiver = EmitScalarExpr(E->getReceiver()); + isSuperMessage = true; + isClassMessage = true; + break; } CallArgList Args; diff --git a/lib/Frontend/PCHReaderStmt.cpp b/lib/Frontend/PCHReaderStmt.cpp index 60318dee77..d253654f7c 100644 --- a/lib/Frontend/PCHReaderStmt.cpp +++ b/lib/Frontend/PCHReaderStmt.cpp @@ -782,25 +782,42 @@ unsigned PCHStmtReader::Vis |