diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/ASTDumper.cpp | 2 | ||||
-rw-r--r-- | clang/lib/AST/ASTImporter.cpp | 3 | ||||
-rw-r--r-- | clang/lib/AST/DeclObjC.cpp | 8 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 1 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclObjC.cpp | 96 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 10 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExprObjC.cpp | 12 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReaderDecl.cpp | 3 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTWriterDecl.cpp | 2 |
9 files changed, 83 insertions, 54 deletions
diff --git a/clang/lib/AST/ASTDumper.cpp b/clang/lib/AST/ASTDumper.cpp index a5591a917da..a968500cfa0 100644 --- a/clang/lib/AST/ASTDumper.cpp +++ b/clang/lib/AST/ASTDumper.cpp @@ -1241,8 +1241,6 @@ void ASTDumper::VisitObjCIvarDecl(const ObjCIvarDecl *D) { dumpType(D->getType()); if (D->getSynthesize()) OS << " synthesize"; - if (D->getBackingIvarReferencedInAccessor()) - OS << " BackingIvarReferencedInAccessor"; switch (D->getAccessControl()) { case ObjCIvarDecl::None: diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index cb967b3fb23..508fa0a201d 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -3016,8 +3016,7 @@ Decl *ASTNodeImporter::VisitObjCIvarDecl(ObjCIvarDecl *D) { Importer.Import(D->getInnerLocStart()), Loc, Name.getAsIdentifierInfo(), T, TInfo, D->getAccessControl(), - BitWidth, D->getSynthesize(), - D->getBackingIvarReferencedInAccessor()); + BitWidth, D->getSynthesize()); ToIvar->setLexicalDeclContext(LexicalDC); Importer.Imported(D, ToIvar); LexicalDC->addDeclInternal(ToIvar); diff --git a/clang/lib/AST/DeclObjC.cpp b/clang/lib/AST/DeclObjC.cpp index 3db1acf0039..f6685de71aa 100644 --- a/clang/lib/AST/DeclObjC.cpp +++ b/clang/lib/AST/DeclObjC.cpp @@ -1440,8 +1440,7 @@ ObjCIvarDecl *ObjCIvarDecl::Create(ASTContext &C, ObjCContainerDecl *DC, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, AccessControl ac, Expr *BW, - bool synthesized, - bool backingIvarReferencedInAccessor) { + bool synthesized) { if (DC) { // Ivar's can only appear in interfaces, implementations (via synthesized // properties), and class extensions (via direct declaration, or synthesized @@ -1469,13 +1468,12 @@ ObjCIvarDecl *ObjCIvarDecl::Create(ASTContext &C, ObjCContainerDecl *DC, } return new (C, DC) ObjCIvarDecl(DC, StartLoc, IdLoc, Id, T, TInfo, ac, BW, - synthesized, backingIvarReferencedInAccessor); + synthesized); } ObjCIvarDecl *ObjCIvarDecl::CreateDeserialized(ASTContext &C, unsigned ID) { return new (C, ID) ObjCIvarDecl(0, SourceLocation(), SourceLocation(), 0, - QualType(), 0, ObjCIvarDecl::None, 0, false, - false); + QualType(), 0, ObjCIvarDecl::None, 0, false); } const ObjCInterfaceDecl *ObjCIvarDecl::getContainingInterface() const { diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index e9fcf835099..607c37ac03f 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -1392,7 +1392,6 @@ void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) { // Remove this name from our lexical scope. IdResolver.RemoveDecl(D); } - DiagnoseUnusedBackingIvarInAccessor(S); } void Sema::ActOnStartFunctionDeclarator() { diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp index edbd7141844..8279263d99f 100644 --- a/clang/lib/Sema/SemaDeclObjC.cpp +++ b/clang/lib/Sema/SemaDeclObjC.cpp @@ -15,6 +15,7 @@ #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTMutationListener.h" +#include "clang/AST/DataRecursiveASTVisitor.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprObjC.h" @@ -2693,6 +2694,7 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, ArrayRef<Decl *> allMethods, ImplMethodsVsClassMethods(S, IC, IDecl); AtomicPropertySetterGetterRules(IC, IDecl); DiagnoseOwningPropertyGetterSynthesis(IC); + DiagnoseUnusedBackingIvarInAccessor(S, IC); if (IDecl->hasDesignatedInitializers()) DiagnoseMissingDesignatedInitOverrides(IC, IDecl); @@ -3494,39 +3496,83 @@ Sema::GetIvarBackingPropertyAccessor(const ObjCMethodDecl *Method, const ObjCInterfaceDecl *IDecl = Method->getClassInterface(); if (!IDecl) return 0; - Method = IDecl->lookupMethod(Method->getSelector(), true); + Method = IDecl->lookupMethod(Method->getSelector(), /*isInstance=*/true, + /*shallowCategoryLookup=*/false, + /*followSuper=*/false); if (!Method || !Method->isPropertyAccessor()) return 0; - if ((PDecl = Method->findPropertyDecl())) { - if (!PDecl->getDeclContext()) - return 0; - // Make sure property belongs to accessor's class and not to - // one of its super classes. - if (const ObjCInterfaceDecl *CID = - dyn_cast<ObjCInterfaceDecl>(PDecl->getDeclContext())) - if (CID != IDecl) - return 0; + if ((PDecl = Method->findPropertyDecl())) return PDecl->getPropertyIvarDecl(); - } + return 0; } -void Sema::DiagnoseUnusedBackingIvarInAccessor(Scope *S) { - if (S->hasUnrecoverableErrorOccurred() || !S->isInObjcMethodOuterScope()) - return; - - const ObjCMethodDecl *CurMethod = getCurMethodDecl(); - if (!CurMethod) +namespace { + /// Used by Sema::DiagnoseUnusedBackingIvarInAccessor to check if a property + /// accessor references the backing ivar. + class UnusedBackingIvarChecker : public DataRecursiveASTVisitor<UnusedBackingIvarChecker> { + public: + Sema &S; + const ObjCMethodDecl *Method; + const ObjCIvarDecl *IvarD; + bool AccessedIvar; + bool InvokedSelfMethod; + + UnusedBackingIvarChecker(Sema &S, const ObjCMethodDecl *Method, + const ObjCIvarDecl *IvarD) + : S(S), Method(Method), IvarD(IvarD), + AccessedIvar(false), InvokedSelfMethod(false) { + assert(IvarD); + } + + bool VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) { + if (E->getDecl() == IvarD) { + AccessedIvar = true; + return false; + } + return true; + } + + bool VisitObjCMessageExpr(ObjCMessageExpr *E) { + if (E->getReceiverKind() == ObjCMessageExpr::Instance && + S.isSelfExpr(E->getInstanceReceiver(), Method)) { + InvokedSelfMethod = true; + } + return true; + } + }; +} + +void Sema::DiagnoseUnusedBackingIvarInAccessor(Scope *S, + const ObjCImplementationDecl *ImplD) { + if (S->hasUnrecoverableErrorOccurred()) return; - const ObjCPropertyDecl *PDecl; - const ObjCIvarDecl *IV = GetIvarBackingPropertyAccessor(CurMethod, PDecl); - if (IV && !IV->getBackingIvarReferencedInAccessor()) { + + for (ObjCImplementationDecl::instmeth_iterator + MI = ImplD->instmeth_begin(), + ME = ImplD->instmeth_end(); MI != ME; ++MI) { + const ObjCMethodDecl *CurMethod = *MI; + unsigned DIAG = diag::warn_unused_property_backing_ivar; + SourceLocation Loc = CurMethod->getLocation(); + if (Diags.getDiagnosticLevel(DIAG, Loc) == DiagnosticsEngine::Ignored) + continue; + + const ObjCPropertyDecl *PDecl; + const ObjCIvarDecl *IV = GetIvarBackingPropertyAccessor(CurMethod, PDecl); + if (!IV) + continue; + + UnusedBackingIvarChecker Checker(*this, CurMethod, IV); + Checker.TraverseStmt(CurMethod->getBody()); + if (Checker.AccessedIvar) + continue; + // Do not issue this warning if backing ivar is used somewhere and accessor - // implementation makes a call to a method. This is to prevent false positive in - // some corner cases. - if (!IV->isReferenced() || !CurMethod->getMethodCallsMethod()) { - Diag(getCurMethodDecl()->getLocation(), diag::warn_unused_property_backing_ivar) - << IV->getDeclName(); + // implementation makes a self call. This is to prevent false positive in + // cases where the ivar is accessed by another method that the accessor + // delegates to. + if (!IV->isReferenced() || !Checker.InvokedSelfMethod) { + Diag(Loc, DIAG) << IV->getDeclName(); Diag(PDecl->getLocation(), diag::note_property_declare); } } diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index aa9d6947cbb..f4802792573 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -2248,15 +2248,7 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S, return ExprError(); MarkAnyDeclReferenced(Loc, IV, true); - if (!IV->getBackingIvarReferencedInAccessor()) { - // Mark this ivar 'referenced' in this method, if it is a backing ivar - // of a property and current method is one of its property accessor. - const ObjCPropertyDecl *PDecl; - const ObjCIvarDecl *BIV = GetIvarBackingPropertyAccessor(CurMethod, PDecl); - if (BIV && BIV == IV) - IV->setBackingIvarReferencedInAccessor(true); - } - + ObjCMethodFamily MF = CurMethod->getMethodFamily(); if (MF != OMF_init && MF != OMF_dealloc && MF != OMF_finalize && !IvarBacksCurrentMethodAccessor(IFace, CurMethod, IV)) diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp index 48881de3ae4..87cff1273a4 100644 --- a/clang/lib/Sema/SemaExprObjC.cpp +++ b/clang/lib/Sema/SemaExprObjC.cpp @@ -1380,10 +1380,14 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType, return IsError; } -bool Sema::isSelfExpr(Expr *receiver) { +bool Sema::isSelfExpr(Expr *RExpr) { // 'self' is objc 'self' in an objc method only. - ObjCMethodDecl *method = - dyn_cast_or_null<ObjCMethodDecl>(CurContext->getNonClosureAncestor()); + ObjCMethodDecl *Method = + dyn_cast_or_null<ObjCMethodDecl>(CurContext->getNonClosureAncestor()); + return isSelfExpr(RExpr, Method); +} + +bool Sema::isSelfExpr(Expr *receiver, const ObjCMethodDecl *method) { if (!method) return false; receiver = receiver->IgnoreParenLValueCasts(); @@ -2643,8 +2647,6 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, } } } - if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) - CurMeth->setMethodCallsMethod(true); return MaybeBindToTemporary(Result); } diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 9f10c607bae..fc61be33fa3 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -702,7 +702,6 @@ void ASTDeclReader::VisitObjCMethodDecl(ObjCMethodDecl *MD) { MD->setDefined(Record[Idx++]); MD->IsOverriding = Record[Idx++]; MD->HasSkippedBody = Record[Idx++]; - MD->MethodCallsMethod = Record[Idx++]; MD->IsRedeclaration = Record[Idx++]; MD->HasRedeclaration = Record[Idx++]; @@ -803,8 +802,6 @@ void ASTDeclReader::VisitObjCIvarDecl(ObjCIvarDecl *IVD) { IVD->setNextIvar(0); bool synth = Record[Idx++]; IVD->setSynthesize(synth); - bool backingIvarReferencedInAccessor = Record[Idx++]; - IVD->setBackingIvarReferencedInAccessor(backingIvarReferencedInAccessor); } void ASTDeclReader::VisitObjCProtocolDecl(ObjCProtocolDecl *PD) { diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index 604ce567512..5770cd72785 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -438,7 +438,6 @@ void ASTDeclWriter::VisitObjCMethodDecl(ObjCMethodDecl *D) { Record.push_back(D->isDefined()); Record.push_back(D->IsOverriding); Record.push_back(D->HasSkippedBody); - Record.push_back(D->MethodCallsMethod); Record.push_back(D->IsRedeclaration); Record.push_back(D->HasRedeclaration); @@ -530,7 +529,6 @@ void ASTDeclWriter::VisitObjCIvarDecl(ObjCIvarDecl *D) { // FIXME: stable encoding for @public/@private/@protected/@package Record.push_back(D->getAccessControl()); Record.push_back(D->getSynthesize()); - Record.push_back(D->getBackingIvarReferencedInAccessor()); if (!D->hasAttrs() && !D->isImplicit() && |