diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2020-01-17 20:45:01 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2020-01-17 20:45:01 +0000 |
commit | 706b4fc47bbc608932d3b491ae19a3b9cde9497b (patch) | |
tree | 4adf86a776049cbf7f69a1929c4babcbbef925eb /clang/lib/Analysis/BodyFarm.cpp | |
parent | 7cc9cf2bf09f069cb2dd947ead05d0b54301fb71 (diff) |
Notes
Diffstat (limited to 'clang/lib/Analysis/BodyFarm.cpp')
-rw-r--r-- | clang/lib/Analysis/BodyFarm.cpp | 105 |
1 files changed, 65 insertions, 40 deletions
diff --git a/clang/lib/Analysis/BodyFarm.cpp b/clang/lib/Analysis/BodyFarm.cpp index 43f9e715b3de..1a7891550542 100644 --- a/clang/lib/Analysis/BodyFarm.cpp +++ b/clang/lib/Analysis/BodyFarm.cpp @@ -737,50 +737,69 @@ static const ObjCIvarDecl *findBackingIvar(const ObjCPropertyDecl *Prop) { } static Stmt *createObjCPropertyGetter(ASTContext &Ctx, - const ObjCPropertyDecl *Prop) { - // First, find the backing ivar. - const ObjCIvarDecl *IVar = findBackingIvar(Prop); - if (!IVar) - return nullptr; + const ObjCMethodDecl *MD) { + // First, find the backing ivar. + const ObjCIvarDecl *IVar = nullptr; + + // Property accessor stubs sometimes do not correspond to any property decl + // in the current interface (but in a superclass). They still have a + // corresponding property impl decl in this case. + if (MD->isSynthesizedAccessorStub()) { + const ObjCInterfaceDecl *IntD = MD->getClassInterface(); + const ObjCImplementationDecl *ImpD = IntD->getImplementation(); + for (const auto *PI: ImpD->property_impls()) { + if (const ObjCPropertyDecl *P = PI->getPropertyDecl()) { + if (P->getGetterName() == MD->getSelector()) + IVar = P->getPropertyIvarDecl(); + } + } + } - // Ignore weak variables, which have special behavior. - if (Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_weak) - return nullptr; + if (!IVar) { + const ObjCPropertyDecl *Prop = MD->findPropertyDecl(); + IVar = findBackingIvar(Prop); + if (!IVar) + return nullptr; + + // Ignore weak variables, which have special behavior. + if (Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_weak) + return nullptr; - // Look to see if Sema has synthesized a body for us. This happens in - // Objective-C++ because the return value may be a C++ class type with a - // non-trivial copy constructor. We can only do this if we can find the - // @synthesize for this property, though (or if we know it's been auto- - // synthesized). - const ObjCImplementationDecl *ImplDecl = - IVar->getContainingInterface()->getImplementation(); - if (ImplDecl) { - for (const auto *I : ImplDecl->property_impls()) { - if (I->getPropertyDecl() != Prop) - continue; - - if (I->getGetterCXXConstructor()) { - ASTMaker M(Ctx); - return M.makeReturn(I->getGetterCXXConstructor()); + // Look to see if Sema has synthesized a body for us. This happens in + // Objective-C++ because the return value may be a C++ class type with a + // non-trivial copy constructor. We can only do this if we can find the + // @synthesize for this property, though (or if we know it's been auto- + // synthesized). + const ObjCImplementationDecl *ImplDecl = + IVar->getContainingInterface()->getImplementation(); + if (ImplDecl) { + for (const auto *I : ImplDecl->property_impls()) { + if (I->getPropertyDecl() != Prop) + continue; + + if (I->getGetterCXXConstructor()) { + ASTMaker M(Ctx); + return M.makeReturn(I->getGetterCXXConstructor()); + } } } - } - // Sanity check that the property is the same type as the ivar, or a - // reference to it, and that it is either an object pointer or trivially - // copyable. - if (!Ctx.hasSameUnqualifiedType(IVar->getType(), - Prop->getType().getNonReferenceType())) - return nullptr; - if (!IVar->getType()->isObjCLifetimeType() && - !IVar->getType().isTriviallyCopyableType(Ctx)) - return nullptr; + // Sanity check that the property is the same type as the ivar, or a + // reference to it, and that it is either an object pointer or trivially + // copyable. + if (!Ctx.hasSameUnqualifiedType(IVar->getType(), + Prop->getType().getNonReferenceType())) + return nullptr; + if (!IVar->getType()->isObjCLifetimeType() && + !IVar->getType().isTriviallyCopyableType(Ctx)) + return nullptr; + } // Generate our body: // return self->_ivar; ASTMaker M(Ctx); - const VarDecl *selfVar = Prop->getGetterMethodDecl()->getSelfDecl(); + const VarDecl *selfVar = MD->getSelfDecl(); if (!selfVar) return nullptr; @@ -791,7 +810,7 @@ static Stmt *createObjCPropertyGetter(ASTContext &Ctx, selfVar->getType()), IVar); - if (!Prop->getType()->isReferenceType()) + if (!MD->getReturnType()->isReferenceType()) loadedIVar = M.makeLvalueToRvalue(loadedIVar, IVar->getType()); return M.makeReturn(loadedIVar); @@ -814,10 +833,6 @@ Stmt *BodyFarm::getBody(const ObjCMethodDecl *D) { return Val.getValue(); Val = nullptr; - const ObjCPropertyDecl *Prop = D->findPropertyDecl(); - if (!Prop) - return nullptr; - // For now, we only synthesize getters. // Synthesizing setters would cause false negatives in the // RetainCountChecker because the method body would bind the parameter @@ -830,7 +845,17 @@ Stmt *BodyFarm::getBody(const ObjCMethodDecl *D) { if (D->param_size() != 0) return nullptr; - Val = createObjCPropertyGetter(C, Prop); + // If the property was defined in an extension, search the extensions for + // overrides. + const ObjCInterfaceDecl *OID = D->getClassInterface(); + if (dyn_cast<ObjCInterfaceDecl>(D->getParent()) != OID) + for (auto *Ext : OID->known_extensions()) { + auto *OMD = Ext->getInstanceMethod(D->getSelector()); + if (OMD && !OMD->isImplicit()) + return nullptr; + } + + Val = createObjCPropertyGetter(C, D); return Val.getValue(); } |