19d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek//===--- SemaObjCProperty.cpp - Semantic Analysis for ObjC @property ------===// 29d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek// 39d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek// The LLVM Compiler Infrastructure 49d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek// 59d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek// This file is distributed under the University of Illinois Open Source 69d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek// License. See LICENSE.TXT for details. 79d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek// 89d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek//===----------------------------------------------------------------------===// 99d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek// 109d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek// This file implements semantic analysis for Objective C @property and 119d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek// @synthesize declarations. 129d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek// 139d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek//===----------------------------------------------------------------------===// 149d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek 152d88708cbe4e4ec5e04e4acb6bd7f5be68557379John McCall#include "clang/Sema/SemaInternal.h" 1655fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/AST/ASTMutationListener.h" 177cd088e519d7e6caa4c4c12db52e0e4ae35d25c2John McCall#include "clang/AST/DeclObjC.h" 1857e264e9f4ff0a72f3585a960cdf63437b76fa93Fariborz Jahanian#include "clang/AST/ExprCXX.h" 1955fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/AST/ExprObjC.h" 20edcc27f6171fd8cc736d057d87b128252fcb7344Fariborz Jahanian#include "clang/Basic/SourceManager.h" 2155fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Lex/Lexer.h" 2255fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Sema/Initialization.h" 2350df6ae41f232612e5e88b19e0db9900d08d2f6cJohn McCall#include "llvm/ADT/DenseSet.h" 248fe83e1df954d72c0f4ffc15d20a5222ec151c21Benjamin Kramer#include "llvm/ADT/SmallString.h" 259d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek 269d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenekusing namespace clang; 279d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek 2828685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek//===----------------------------------------------------------------------===// 2928685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek// Grammar actions. 3028685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek//===----------------------------------------------------------------------===// 3128685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek 32265941bc308d65cc270d5c4de5806f37ce405606John McCall/// getImpliedARCOwnership - Given a set of property attributes and a 33265941bc308d65cc270d5c4de5806f37ce405606John McCall/// type, infer an expected lifetime. The type's ownership qualification 34265941bc308d65cc270d5c4de5806f37ce405606John McCall/// is not considered. 35265941bc308d65cc270d5c4de5806f37ce405606John McCall/// 36265941bc308d65cc270d5c4de5806f37ce405606John McCall/// Returns OCL_None if the attributes as stated do not imply an ownership. 37265941bc308d65cc270d5c4de5806f37ce405606John McCall/// Never returns OCL_Autoreleasing. 38265941bc308d65cc270d5c4de5806f37ce405606John McCallstatic Qualifiers::ObjCLifetime getImpliedARCOwnership( 39265941bc308d65cc270d5c4de5806f37ce405606John McCall ObjCPropertyDecl::PropertyAttributeKind attrs, 40265941bc308d65cc270d5c4de5806f37ce405606John McCall QualType type) { 41265941bc308d65cc270d5c4de5806f37ce405606John McCall // retain, strong, copy, weak, and unsafe_unretained are only legal 42265941bc308d65cc270d5c4de5806f37ce405606John McCall // on properties of retainable pointer type. 43265941bc308d65cc270d5c4de5806f37ce405606John McCall if (attrs & (ObjCPropertyDecl::OBJC_PR_retain | 44265941bc308d65cc270d5c4de5806f37ce405606John McCall ObjCPropertyDecl::OBJC_PR_strong | 45265941bc308d65cc270d5c4de5806f37ce405606John McCall ObjCPropertyDecl::OBJC_PR_copy)) { 46d64c2eb83d7ec86faa4f2554935a977a19573f59John McCall return Qualifiers::OCL_Strong; 47265941bc308d65cc270d5c4de5806f37ce405606John McCall } else if (attrs & ObjCPropertyDecl::OBJC_PR_weak) { 48265941bc308d65cc270d5c4de5806f37ce405606John McCall return Qualifiers::OCL_Weak; 49265941bc308d65cc270d5c4de5806f37ce405606John McCall } else if (attrs & ObjCPropertyDecl::OBJC_PR_unsafe_unretained) { 50265941bc308d65cc270d5c4de5806f37ce405606John McCall return Qualifiers::OCL_ExplicitNone; 51265941bc308d65cc270d5c4de5806f37ce405606John McCall } 52265941bc308d65cc270d5c4de5806f37ce405606John McCall 53265941bc308d65cc270d5c4de5806f37ce405606John McCall // assign can appear on other types, so we have to check the 54265941bc308d65cc270d5c4de5806f37ce405606John McCall // property type. 55265941bc308d65cc270d5c4de5806f37ce405606John McCall if (attrs & ObjCPropertyDecl::OBJC_PR_assign && 56265941bc308d65cc270d5c4de5806f37ce405606John McCall type->isObjCRetainableType()) { 57265941bc308d65cc270d5c4de5806f37ce405606John McCall return Qualifiers::OCL_ExplicitNone; 58265941bc308d65cc270d5c4de5806f37ce405606John McCall } 59265941bc308d65cc270d5c4de5806f37ce405606John McCall 60265941bc308d65cc270d5c4de5806f37ce405606John McCall return Qualifiers::OCL_None; 61265941bc308d65cc270d5c4de5806f37ce405606John McCall} 62265941bc308d65cc270d5c4de5806f37ce405606John McCall 63f85e193739c953358c865005855253af4f68a497John McCall/// Check the internal consistency of a property declaration. 64f85e193739c953358c865005855253af4f68a497John McCallstatic void checkARCPropertyDecl(Sema &S, ObjCPropertyDecl *property) { 65f85e193739c953358c865005855253af4f68a497John McCall if (property->isInvalidDecl()) return; 66f85e193739c953358c865005855253af4f68a497John McCall 67f85e193739c953358c865005855253af4f68a497John McCall ObjCPropertyDecl::PropertyAttributeKind propertyKind 68f85e193739c953358c865005855253af4f68a497John McCall = property->getPropertyAttributes(); 69f85e193739c953358c865005855253af4f68a497John McCall Qualifiers::ObjCLifetime propertyLifetime 70f85e193739c953358c865005855253af4f68a497John McCall = property->getType().getObjCLifetime(); 71f85e193739c953358c865005855253af4f68a497John McCall 72f85e193739c953358c865005855253af4f68a497John McCall // Nothing to do if we don't have a lifetime. 73f85e193739c953358c865005855253af4f68a497John McCall if (propertyLifetime == Qualifiers::OCL_None) return; 74f85e193739c953358c865005855253af4f68a497John McCall 75265941bc308d65cc270d5c4de5806f37ce405606John McCall Qualifiers::ObjCLifetime expectedLifetime 76265941bc308d65cc270d5c4de5806f37ce405606John McCall = getImpliedARCOwnership(propertyKind, property->getType()); 77265941bc308d65cc270d5c4de5806f37ce405606John McCall if (!expectedLifetime) { 78f85e193739c953358c865005855253af4f68a497John McCall // We have a lifetime qualifier but no dominating property 79265941bc308d65cc270d5c4de5806f37ce405606John McCall // attribute. That's okay, but restore reasonable invariants by 80265941bc308d65cc270d5c4de5806f37ce405606John McCall // setting the property attribute according to the lifetime 81265941bc308d65cc270d5c4de5806f37ce405606John McCall // qualifier. 82265941bc308d65cc270d5c4de5806f37ce405606John McCall ObjCPropertyDecl::PropertyAttributeKind attr; 83265941bc308d65cc270d5c4de5806f37ce405606John McCall if (propertyLifetime == Qualifiers::OCL_Strong) { 84265941bc308d65cc270d5c4de5806f37ce405606John McCall attr = ObjCPropertyDecl::OBJC_PR_strong; 85265941bc308d65cc270d5c4de5806f37ce405606John McCall } else if (propertyLifetime == Qualifiers::OCL_Weak) { 86265941bc308d65cc270d5c4de5806f37ce405606John McCall attr = ObjCPropertyDecl::OBJC_PR_weak; 87265941bc308d65cc270d5c4de5806f37ce405606John McCall } else { 88265941bc308d65cc270d5c4de5806f37ce405606John McCall assert(propertyLifetime == Qualifiers::OCL_ExplicitNone); 89265941bc308d65cc270d5c4de5806f37ce405606John McCall attr = ObjCPropertyDecl::OBJC_PR_unsafe_unretained; 90265941bc308d65cc270d5c4de5806f37ce405606John McCall } 91265941bc308d65cc270d5c4de5806f37ce405606John McCall property->setPropertyAttributes(attr); 92f85e193739c953358c865005855253af4f68a497John McCall return; 93f85e193739c953358c865005855253af4f68a497John McCall } 94f85e193739c953358c865005855253af4f68a497John McCall 95f85e193739c953358c865005855253af4f68a497John McCall if (propertyLifetime == expectedLifetime) return; 96f85e193739c953358c865005855253af4f68a497John McCall 97f85e193739c953358c865005855253af4f68a497John McCall property->setInvalidDecl(); 98f85e193739c953358c865005855253af4f68a497John McCall S.Diag(property->getLocation(), 99b8b0313e84700b5c6d597b3be4de41c97b7550f1Argyrios Kyrtzidis diag::err_arc_inconsistent_property_ownership) 100f85e193739c953358c865005855253af4f68a497John McCall << property->getDeclName() 101265941bc308d65cc270d5c4de5806f37ce405606John McCall << expectedLifetime 102f85e193739c953358c865005855253af4f68a497John McCall << propertyLifetime; 103f85e193739c953358c865005855253af4f68a497John McCall} 104f85e193739c953358c865005855253af4f68a497John McCall 105dad633b0a0955ceb4579e9508224562ad41b6a8dFariborz Jahanianstatic unsigned deduceWeakPropertyFromType(Sema &S, QualType T) { 106dad633b0a0955ceb4579e9508224562ad41b6a8dFariborz Jahanian if ((S.getLangOpts().getGC() != LangOptions::NonGC && 107dad633b0a0955ceb4579e9508224562ad41b6a8dFariborz Jahanian T.isObjCGCWeak()) || 108dad633b0a0955ceb4579e9508224562ad41b6a8dFariborz Jahanian (S.getLangOpts().ObjCAutoRefCount && 109dad633b0a0955ceb4579e9508224562ad41b6a8dFariborz Jahanian T.getObjCLifetime() == Qualifiers::OCL_Weak)) 110dad633b0a0955ceb4579e9508224562ad41b6a8dFariborz Jahanian return ObjCDeclSpec::DQ_PR_weak; 111dad633b0a0955ceb4579e9508224562ad41b6a8dFariborz Jahanian return 0; 112dad633b0a0955ceb4579e9508224562ad41b6a8dFariborz Jahanian} 113dad633b0a0955ceb4579e9508224562ad41b6a8dFariborz Jahanian 114b892d7010f9c2c61e2f3a2686546cbfbffbedef3Douglas Gregor/// \brief Check this Objective-C property against a property declared in the 115b892d7010f9c2c61e2f3a2686546cbfbffbedef3Douglas Gregor/// given protocol. 116b892d7010f9c2c61e2f3a2686546cbfbffbedef3Douglas Gregorstatic void 117b892d7010f9c2c61e2f3a2686546cbfbffbedef3Douglas GregorCheckPropertyAgainstProtocol(Sema &S, ObjCPropertyDecl *Prop, 118b892d7010f9c2c61e2f3a2686546cbfbffbedef3Douglas Gregor ObjCProtocolDecl *Proto, 119b892d7010f9c2c61e2f3a2686546cbfbffbedef3Douglas Gregor llvm::SmallPtrSet<ObjCProtocolDecl *, 16> &Known) { 120b892d7010f9c2c61e2f3a2686546cbfbffbedef3Douglas Gregor // Have we seen this protocol before? 121b892d7010f9c2c61e2f3a2686546cbfbffbedef3Douglas Gregor if (!Known.insert(Proto)) 122b892d7010f9c2c61e2f3a2686546cbfbffbedef3Douglas Gregor return; 123b892d7010f9c2c61e2f3a2686546cbfbffbedef3Douglas Gregor 124b892d7010f9c2c61e2f3a2686546cbfbffbedef3Douglas Gregor // Look for a property with the same name. 125b892d7010f9c2c61e2f3a2686546cbfbffbedef3Douglas Gregor DeclContext::lookup_result R = Proto->lookup(Prop->getDeclName()); 126b892d7010f9c2c61e2f3a2686546cbfbffbedef3Douglas Gregor for (unsigned I = 0, N = R.size(); I != N; ++I) { 127b892d7010f9c2c61e2f3a2686546cbfbffbedef3Douglas Gregor if (ObjCPropertyDecl *ProtoProp = dyn_cast<ObjCPropertyDecl>(R[I])) { 1281cd6fab3930d5c058c201895654c6b0bd6ecb8c1Fariborz Jahanian S.DiagnosePropertyMismatch(Prop, ProtoProp, Proto->getIdentifier(), true); 129b892d7010f9c2c61e2f3a2686546cbfbffbedef3Douglas Gregor return; 130b892d7010f9c2c61e2f3a2686546cbfbffbedef3Douglas Gregor } 131b892d7010f9c2c61e2f3a2686546cbfbffbedef3Douglas Gregor } 132b892d7010f9c2c61e2f3a2686546cbfbffbedef3Douglas Gregor 133b892d7010f9c2c61e2f3a2686546cbfbffbedef3Douglas Gregor // Check this property against any protocols we inherit. 134651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (auto *P : Proto->protocols()) 135651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines CheckPropertyAgainstProtocol(S, Prop, P, Known); 136b892d7010f9c2c61e2f3a2686546cbfbffbedef3Douglas Gregor} 137b892d7010f9c2c61e2f3a2686546cbfbffbedef3Douglas Gregor 138d226f65006733ed7f709c3174f22ce33391cb58fJohn McCallDecl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc, 13977bfb8b43ec3f7dee3a71f6e854b03ad29dab84fFariborz Jahanian SourceLocation LParenLoc, 140d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall FieldDeclarator &FD, 141d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall ObjCDeclSpec &ODS, 142d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall Selector GetterSel, 143d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall Selector SetterSel, 144d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall bool *isOverridingProperty, 1454a2e9ea0c191176ebe996516a9cf4f93b7e932ccTed Kremenek tok::ObjCKeywordKind MethodImplKind, 1464a2e9ea0c191176ebe996516a9cf4f93b7e932ccTed Kremenek DeclContext *lexicalDC) { 147ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling unsigned Attributes = ODS.getPropertyAttributes(); 148f85e193739c953358c865005855253af4f68a497John McCall TypeSourceInfo *TSI = GetTypeForDeclarator(FD.D, S); 149f85e193739c953358c865005855253af4f68a497John McCall QualType T = TSI->getType(); 150ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling Attributes |= deduceWeakPropertyFromType(*this, T); 151dad633b0a0955ceb4579e9508224562ad41b6a8dFariborz Jahanian 152ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling bool isReadWrite = ((Attributes & ObjCDeclSpec::DQ_PR_readwrite) || 15328685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek // default is readwrite! 154ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling !(Attributes & ObjCDeclSpec::DQ_PR_readonly)); 15528685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek // property is defaulted to 'assign' if it is readwrite and is 15628685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek // not retain or copy 157ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling bool isAssign = ((Attributes & ObjCDeclSpec::DQ_PR_assign) || 15828685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek (isReadWrite && 159ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling !(Attributes & ObjCDeclSpec::DQ_PR_retain) && 160ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling !(Attributes & ObjCDeclSpec::DQ_PR_strong) && 161ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling !(Attributes & ObjCDeclSpec::DQ_PR_copy) && 162ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling !(Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained) && 163ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling !(Attributes & ObjCDeclSpec::DQ_PR_weak))); 16414086764e340267e17803d0f8243070ffae2c76eFariborz Jahanian 165aabd094cf694039fe823987e133af7ac25cb9711Douglas Gregor // Proceed with constructing the ObjCPropertyDecls. 166a28948f34817476d02412fa204cae038e228c827Fariborz Jahanian ObjCContainerDecl *ClassDecl = cast<ObjCContainerDecl>(CurContext); 1676bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines ObjCPropertyDecl *Res = nullptr; 168aabd094cf694039fe823987e133af7ac25cb9711Douglas Gregor if (ObjCCategoryDecl *CDecl = dyn_cast<ObjCCategoryDecl>(ClassDecl)) { 169ae415dc21ee6402cee1675ec8bb965a24f9e5b6bFariborz Jahanian if (CDecl->IsClassExtension()) { 170aabd094cf694039fe823987e133af7ac25cb9711Douglas Gregor Res = HandlePropertyInClassExtension(S, AtLoc, LParenLoc, 171ae415dc21ee6402cee1675ec8bb965a24f9e5b6bFariborz Jahanian FD, GetterSel, SetterSel, 172ae415dc21ee6402cee1675ec8bb965a24f9e5b6bFariborz Jahanian isAssign, isReadWrite, 173ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling Attributes, 174dbbdec994f5a96b5c25aaa679cd86ecabf545f7bArgyrios Kyrtzidis ODS.getPropertyAttributes(), 175ae415dc21ee6402cee1675ec8bb965a24f9e5b6bFariborz Jahanian isOverridingProperty, TSI, 176ae415dc21ee6402cee1675ec8bb965a24f9e5b6bFariborz Jahanian MethodImplKind); 177aabd094cf694039fe823987e133af7ac25cb9711Douglas Gregor if (!Res) 1786bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 179ae415dc21ee6402cee1675ec8bb965a24f9e5b6bFariborz Jahanian } 180aabd094cf694039fe823987e133af7ac25cb9711Douglas Gregor } 181aabd094cf694039fe823987e133af7ac25cb9711Douglas Gregor 182aabd094cf694039fe823987e133af7ac25cb9711Douglas Gregor if (!Res) { 183aabd094cf694039fe823987e133af7ac25cb9711Douglas Gregor Res = CreatePropertyDecl(S, ClassDecl, AtLoc, LParenLoc, FD, 184aabd094cf694039fe823987e133af7ac25cb9711Douglas Gregor GetterSel, SetterSel, isAssign, isReadWrite, 185aabd094cf694039fe823987e133af7ac25cb9711Douglas Gregor Attributes, ODS.getPropertyAttributes(), 186aabd094cf694039fe823987e133af7ac25cb9711Douglas Gregor TSI, MethodImplKind); 187aabd094cf694039fe823987e133af7ac25cb9711Douglas Gregor if (lexicalDC) 188aabd094cf694039fe823987e133af7ac25cb9711Douglas Gregor Res->setLexicalDeclContext(lexicalDC); 189aabd094cf694039fe823987e133af7ac25cb9711Douglas Gregor } 1904a2e9ea0c191176ebe996516a9cf4f93b7e932ccTed Kremenek 191842f07b065ac481fce9d82d55cb62e36bac6c921Fariborz Jahanian // Validate the attributes on the @property. 192ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling CheckObjCPropertyAttributes(Res, AtLoc, Attributes, 193cea06d26b8f3a2599bba79f7e072b7550de949a7Fariborz Jahanian (isa<ObjCInterfaceDecl>(ClassDecl) || 194cea06d26b8f3a2599bba79f7e072b7550de949a7Fariborz Jahanian isa<ObjCProtocolDecl>(ClassDecl))); 195f85e193739c953358c865005855253af4f68a497John McCall 1964e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie if (getLangOpts().ObjCAutoRefCount) 197f85e193739c953358c865005855253af4f68a497John McCall checkARCPropertyDecl(*this, Res); 198f85e193739c953358c865005855253af4f68a497John McCall 199b892d7010f9c2c61e2f3a2686546cbfbffbedef3Douglas Gregor llvm::SmallPtrSet<ObjCProtocolDecl *, 16> KnownProtos; 200aabd094cf694039fe823987e133af7ac25cb9711Douglas Gregor if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(ClassDecl)) { 201b892d7010f9c2c61e2f3a2686546cbfbffbedef3Douglas Gregor // For a class, compare the property against a property in our superclass. 202b892d7010f9c2c61e2f3a2686546cbfbffbedef3Douglas Gregor bool FoundInSuper = false; 203651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ObjCInterfaceDecl *CurrentInterfaceDecl = IFace; 204651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines while (ObjCInterfaceDecl *Super = CurrentInterfaceDecl->getSuperClass()) { 205aabd094cf694039fe823987e133af7ac25cb9711Douglas Gregor DeclContext::lookup_result R = Super->lookup(Res->getDeclName()); 206b892d7010f9c2c61e2f3a2686546cbfbffbedef3Douglas Gregor for (unsigned I = 0, N = R.size(); I != N; ++I) { 207b892d7010f9c2c61e2f3a2686546cbfbffbedef3Douglas Gregor if (ObjCPropertyDecl *SuperProp = dyn_cast<ObjCPropertyDecl>(R[I])) { 2081cd6fab3930d5c058c201895654c6b0bd6ecb8c1Fariborz Jahanian DiagnosePropertyMismatch(Res, SuperProp, Super->getIdentifier(), false); 209b892d7010f9c2c61e2f3a2686546cbfbffbedef3Douglas Gregor FoundInSuper = true; 210b892d7010f9c2c61e2f3a2686546cbfbffbedef3Douglas Gregor break; 211b892d7010f9c2c61e2f3a2686546cbfbffbedef3Douglas Gregor } 212b892d7010f9c2c61e2f3a2686546cbfbffbedef3Douglas Gregor } 213651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (FoundInSuper) 214651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines break; 215651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines else 216651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines CurrentInterfaceDecl = Super; 217b892d7010f9c2c61e2f3a2686546cbfbffbedef3Douglas Gregor } 218b892d7010f9c2c61e2f3a2686546cbfbffbedef3Douglas Gregor 219b892d7010f9c2c61e2f3a2686546cbfbffbedef3Douglas Gregor if (FoundInSuper) { 220b892d7010f9c2c61e2f3a2686546cbfbffbedef3Douglas Gregor // Also compare the property against a property in our protocols. 221651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (auto *P : CurrentInterfaceDecl->protocols()) { 222651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines CheckPropertyAgainstProtocol(*this, Res, P, KnownProtos); 223b892d7010f9c2c61e2f3a2686546cbfbffbedef3Douglas Gregor } 224b892d7010f9c2c61e2f3a2686546cbfbffbedef3Douglas Gregor } else { 225b892d7010f9c2c61e2f3a2686546cbfbffbedef3Douglas Gregor // Slower path: look in all protocols we referenced. 226651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (auto *P : IFace->all_referenced_protocols()) { 227651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines CheckPropertyAgainstProtocol(*this, Res, P, KnownProtos); 228b892d7010f9c2c61e2f3a2686546cbfbffbedef3Douglas Gregor } 229b892d7010f9c2c61e2f3a2686546cbfbffbedef3Douglas Gregor } 230b892d7010f9c2c61e2f3a2686546cbfbffbedef3Douglas Gregor } else if (ObjCCategoryDecl *Cat = dyn_cast<ObjCCategoryDecl>(ClassDecl)) { 231651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (auto *P : Cat->protocols()) 232651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines CheckPropertyAgainstProtocol(*this, Res, P, KnownProtos); 233b892d7010f9c2c61e2f3a2686546cbfbffbedef3Douglas Gregor } else { 234b892d7010f9c2c61e2f3a2686546cbfbffbedef3Douglas Gregor ObjCProtocolDecl *Proto = cast<ObjCProtocolDecl>(ClassDecl); 235651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (auto *P : Proto->protocols()) 236651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines CheckPropertyAgainstProtocol(*this, Res, P, KnownProtos); 237aabd094cf694039fe823987e133af7ac25cb9711Douglas Gregor } 238aabd094cf694039fe823987e133af7ac25cb9711Douglas Gregor 239abd56c816e9164b17bb3e7154a511b0c9896ffdbDmitri Gribenko ActOnDocumentableDecl(Res); 240842f07b065ac481fce9d82d55cb62e36bac6c921Fariborz Jahanian return Res; 241e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek} 242e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek 243b98ffded10453d80369951f33f3892f35d747c95Argyrios Kyrtzidisstatic ObjCPropertyDecl::PropertyAttributeKind 244ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill WendlingmakePropertyAttributesAsWritten(unsigned Attributes) { 245b98ffded10453d80369951f33f3892f35d747c95Argyrios Kyrtzidis unsigned attributesAsWritten = 0; 246ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling if (Attributes & ObjCDeclSpec::DQ_PR_readonly) 247b98ffded10453d80369951f33f3892f35d747c95Argyrios Kyrtzidis attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_readonly; 248ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling if (Attributes & ObjCDeclSpec::DQ_PR_readwrite) 249b98ffded10453d80369951f33f3892f35d747c95Argyrios Kyrtzidis attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_readwrite; 250ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling if (Attributes & ObjCDeclSpec::DQ_PR_getter) 251b98ffded10453d80369951f33f3892f35d747c95Argyrios Kyrtzidis attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_getter; 252ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling if (Attributes & ObjCDeclSpec::DQ_PR_setter) 253b98ffded10453d80369951f33f3892f35d747c95Argyrios Kyrtzidis attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_setter; 254ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling if (Attributes & ObjCDeclSpec::DQ_PR_assign) 255b98ffded10453d80369951f33f3892f35d747c95Argyrios Kyrtzidis attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_assign; 256ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling if (Attributes & ObjCDeclSpec::DQ_PR_retain) 257b98ffded10453d80369951f33f3892f35d747c95Argyrios Kyrtzidis attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_retain; 258ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling if (Attributes & ObjCDeclSpec::DQ_PR_strong) 259b98ffded10453d80369951f33f3892f35d747c95Argyrios Kyrtzidis attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_strong; 260ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling if (Attributes & ObjCDeclSpec::DQ_PR_weak) 261b98ffded10453d80369951f33f3892f35d747c95Argyrios Kyrtzidis attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_weak; 262ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling if (Attributes & ObjCDeclSpec::DQ_PR_copy) 263b98ffded10453d80369951f33f3892f35d747c95Argyrios Kyrtzidis attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_copy; 264ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling if (Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained) 265b98ffded10453d80369951f33f3892f35d747c95Argyrios Kyrtzidis attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_unsafe_unretained; 266ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling if (Attributes & ObjCDeclSpec::DQ_PR_nonatomic) 267b98ffded10453d80369951f33f3892f35d747c95Argyrios Kyrtzidis attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_nonatomic; 268ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling if (Attributes & ObjCDeclSpec::DQ_PR_atomic) 269b98ffded10453d80369951f33f3892f35d747c95Argyrios Kyrtzidis attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_atomic; 270b98ffded10453d80369951f33f3892f35d747c95Argyrios Kyrtzidis 271b98ffded10453d80369951f33f3892f35d747c95Argyrios Kyrtzidis return (ObjCPropertyDecl::PropertyAttributeKind)attributesAsWritten; 272b98ffded10453d80369951f33f3892f35d747c95Argyrios Kyrtzidis} 273b98ffded10453d80369951f33f3892f35d747c95Argyrios Kyrtzidis 2745bf0e3522fac400cf7bf49a775554f0fc942b336Fariborz Jahanianstatic bool LocPropertyAttribute( ASTContext &Context, const char *attrName, 275edcc27f6171fd8cc736d057d87b128252fcb7344Fariborz Jahanian SourceLocation LParenLoc, SourceLocation &Loc) { 276edcc27f6171fd8cc736d057d87b128252fcb7344Fariborz Jahanian if (LParenLoc.isMacroID()) 277edcc27f6171fd8cc736d057d87b128252fcb7344Fariborz Jahanian return false; 278edcc27f6171fd8cc736d057d87b128252fcb7344Fariborz Jahanian 279edcc27f6171fd8cc736d057d87b128252fcb7344Fariborz Jahanian SourceManager &SM = Context.getSourceManager(); 280edcc27f6171fd8cc736d057d87b128252fcb7344Fariborz Jahanian std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(LParenLoc); 281edcc27f6171fd8cc736d057d87b128252fcb7344Fariborz Jahanian // Try to load the file buffer. 282edcc27f6171fd8cc736d057d87b128252fcb7344Fariborz Jahanian bool invalidTemp = false; 283edcc27f6171fd8cc736d057d87b128252fcb7344Fariborz Jahanian StringRef file = SM.getBufferData(locInfo.first, &invalidTemp); 284edcc27f6171fd8cc736d057d87b128252fcb7344Fariborz Jahanian if (invalidTemp) 285edcc27f6171fd8cc736d057d87b128252fcb7344Fariborz Jahanian return false; 286edcc27f6171fd8cc736d057d87b128252fcb7344Fariborz Jahanian const char *tokenBegin = file.data() + locInfo.second; 287edcc27f6171fd8cc736d057d87b128252fcb7344Fariborz Jahanian 288edcc27f6171fd8cc736d057d87b128252fcb7344Fariborz Jahanian // Lex from the start of the given location. 289edcc27f6171fd8cc736d057d87b128252fcb7344Fariborz Jahanian Lexer lexer(SM.getLocForStartOfFile(locInfo.first), 290edcc27f6171fd8cc736d057d87b128252fcb7344Fariborz Jahanian Context.getLangOpts(), 291edcc27f6171fd8cc736d057d87b128252fcb7344Fariborz Jahanian file.begin(), tokenBegin, file.end()); 292edcc27f6171fd8cc736d057d87b128252fcb7344Fariborz Jahanian Token Tok; 293edcc27f6171fd8cc736d057d87b128252fcb7344Fariborz Jahanian do { 294edcc27f6171fd8cc736d057d87b128252fcb7344Fariborz Jahanian lexer.LexFromRawLexer(Tok); 2956bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if (Tok.is(tok::raw_identifier) && Tok.getRawIdentifier() == attrName) { 296edcc27f6171fd8cc736d057d87b128252fcb7344Fariborz Jahanian Loc = Tok.getLocation(); 297edcc27f6171fd8cc736d057d87b128252fcb7344Fariborz Jahanian return true; 298edcc27f6171fd8cc736d057d87b128252fcb7344Fariborz Jahanian } 299edcc27f6171fd8cc736d057d87b128252fcb7344Fariborz Jahanian } while (Tok.isNot(tok::r_paren)); 300edcc27f6171fd8cc736d057d87b128252fcb7344Fariborz Jahanian return false; 301edcc27f6171fd8cc736d057d87b128252fcb7344Fariborz Jahanian 3022b309fb125906b1fb10efb1890860cd042fbfab3Fariborz Jahanian} 3032b309fb125906b1fb10efb1890860cd042fbfab3Fariborz Jahanian 304d9f95b35dc4fc168a167a9b9b61a5f9e1d0462baFariborz Jahanianstatic unsigned getOwnershipRule(unsigned attr) { 305dad633b0a0955ceb4579e9508224562ad41b6a8dFariborz Jahanian return attr & (ObjCPropertyDecl::OBJC_PR_assign | 306dad633b0a0955ceb4579e9508224562ad41b6a8dFariborz Jahanian ObjCPropertyDecl::OBJC_PR_retain | 307dad633b0a0955ceb4579e9508224562ad41b6a8dFariborz Jahanian ObjCPropertyDecl::OBJC_PR_copy | 308dad633b0a0955ceb4579e9508224562ad41b6a8dFariborz Jahanian ObjCPropertyDecl::OBJC_PR_weak | 309dad633b0a0955ceb4579e9508224562ad41b6a8dFariborz Jahanian ObjCPropertyDecl::OBJC_PR_strong | 310dad633b0a0955ceb4579e9508224562ad41b6a8dFariborz Jahanian ObjCPropertyDecl::OBJC_PR_unsafe_unretained); 311dad633b0a0955ceb4579e9508224562ad41b6a8dFariborz Jahanian} 312dad633b0a0955ceb4579e9508224562ad41b6a8dFariborz Jahanian 313aabd094cf694039fe823987e133af7ac25cb9711Douglas GregorObjCPropertyDecl * 314a28948f34817476d02412fa204cae038e228c827Fariborz JahanianSema::HandlePropertyInClassExtension(Scope *S, 31577bfb8b43ec3f7dee3a71f6e854b03ad29dab84fFariborz Jahanian SourceLocation AtLoc, 31677bfb8b43ec3f7dee3a71f6e854b03ad29dab84fFariborz Jahanian SourceLocation LParenLoc, 31777bfb8b43ec3f7dee3a71f6e854b03ad29dab84fFariborz Jahanian FieldDeclarator &FD, 318e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek Selector GetterSel, Selector SetterSel, 319e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek const bool isAssign, 320e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek const bool isReadWrite, 321ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling const unsigned Attributes, 322dbbdec994f5a96b5c25aaa679cd86ecabf545f7bArgyrios Kyrtzidis const unsigned AttributesAsWritten, 323e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek bool *isOverridingProperty, 32483a230c83a54190366138c1a4f4310ef838b88fcJohn McCall TypeSourceInfo *T, 325e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek tok::ObjCKeywordKind MethodImplKind) { 32658a764940df0cd41767367eb2f4fced6f374176bFariborz Jahanian ObjCCategoryDecl *CDecl = cast<ObjCCategoryDecl>(CurContext); 327e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek // Diagnose if this property is already in continuation class. 328a28948f34817476d02412fa204cae038e228c827Fariborz Jahanian DeclContext *DC = CurContext; 329e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek IdentifierInfo *PropertyId = FD.D.getIdentifier(); 3302a2891410b02d146b779cdb29eeb9b6d1a9fa030Fariborz Jahanian ObjCInterfaceDecl *CCPrimary = CDecl->getClassInterface(); 3312a2891410b02d146b779cdb29eeb9b6d1a9fa030Fariborz Jahanian 332d329724745b49f894b768d47275b7c2713106e89Douglas Gregor if (CCPrimary) { 3332a2891410b02d146b779cdb29eeb9b6d1a9fa030Fariborz Jahanian // Check for duplicate declaration of this property in current and 3342a2891410b02d146b779cdb29eeb9b6d1a9fa030Fariborz Jahanian // other class extensions. 335651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (const auto *Ext : CCPrimary->known_extensions()) { 336d329724745b49f894b768d47275b7c2713106e89Douglas Gregor if (ObjCPropertyDecl *prevDecl 337651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines = ObjCPropertyDecl::findPropertyDecl(Ext, PropertyId)) { 3382a2891410b02d146b779cdb29eeb9b6d1a9fa030Fariborz Jahanian Diag(AtLoc, diag::err_duplicate_property); 3392a2891410b02d146b779cdb29eeb9b6d1a9fa030Fariborz Jahanian Diag(prevDecl->getLocation(), diag::note_property_declare); 3406bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 3412a2891410b02d146b779cdb29eeb9b6d1a9fa030Fariborz Jahanian } 3422a2891410b02d146b779cdb29eeb9b6d1a9fa030Fariborz Jahanian } 343d329724745b49f894b768d47275b7c2713106e89Douglas Gregor } 344d329724745b49f894b768d47275b7c2713106e89Douglas Gregor 345e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek // Create a new ObjCPropertyDecl with the DeclContext being 346e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek // the class extension. 34788f5e9be350f4b107f8665183a6d441874e0fcc7Fariborz Jahanian // FIXME. We should really be using CreatePropertyDecl for this. 348e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek ObjCPropertyDecl *PDecl = 349e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek ObjCPropertyDecl::Create(Context, DC, FD.D.getIdentifierLoc(), 35077bfb8b43ec3f7dee3a71f6e854b03ad29dab84fFariborz Jahanian PropertyId, AtLoc, LParenLoc, T); 351b98ffded10453d80369951f33f3892f35d747c95Argyrios Kyrtzidis PDecl->setPropertyAttributesAsWritten( 352dbbdec994f5a96b5c25aaa679cd86ecabf545f7bArgyrios Kyrtzidis makePropertyAttributesAsWritten(AttributesAsWritten)); 353ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling if (Attributes & ObjCDeclSpec::DQ_PR_readonly) 35422f757b38da3fc9f17ea9e99524064fdfbca3456Fariborz Jahanian PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readonly); 355ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling if (Attributes & ObjCDeclSpec::DQ_PR_readwrite) 35622f757b38da3fc9f17ea9e99524064fdfbca3456Fariborz Jahanian PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readwrite); 357b7b25659355d736a4f19099d96acc54d672340a5Fariborz Jahanian if (Attributes & ObjCDeclSpec::DQ_PR_nonatomic) 358b7b25659355d736a4f19099d96acc54d672340a5Fariborz Jahanian PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_nonatomic); 359b7b25659355d736a4f19099d96acc54d672340a5Fariborz Jahanian if (Attributes & ObjCDeclSpec::DQ_PR_atomic) 360b7b25659355d736a4f19099d96acc54d672340a5Fariborz Jahanian PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_atomic); 36188f5e9be350f4b107f8665183a6d441874e0fcc7Fariborz Jahanian // Set setter/getter selector name. Needed later. 36288f5e9be350f4b107f8665183a6d441874e0fcc7Fariborz Jahanian PDecl->setGetterName(GetterSel); 36388f5e9be350f4b107f8665183a6d441874e0fcc7Fariborz Jahanian PDecl->setSetterName(SetterSel); 36491ae6b43b3a294243698cdb544dd7a18efa4c7a8Douglas Gregor ProcessDeclAttributes(S, PDecl, FD.D); 365e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek DC->addDecl(PDecl); 366e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek 367e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek // We need to look in the @interface to see if the @property was 368e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek // already declared. 369e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek if (!CCPrimary) { 370e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek Diag(CDecl->getLocation(), diag::err_continuation_class); 371e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek *isOverridingProperty = true; 3726bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 373e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek } 374e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek 375e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek // Find the property in continuation class's primary class only. 376e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek ObjCPropertyDecl *PIDecl = 377e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek CCPrimary->FindPropertyVisibleInPrimaryClass(PropertyId); 378e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek 379e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek if (!PIDecl) { 380e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek // No matching property found in the primary class. Just fall thru 381e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek // and add property to continuation class's primary class. 382d7c15a64ba8ebdca0dd48dd1d2f233107d34494eArgyrios Kyrtzidis ObjCPropertyDecl *PrimaryPDecl = 38377bfb8b43ec3f7dee3a71f6e854b03ad29dab84fFariborz Jahanian CreatePropertyDecl(S, CCPrimary, AtLoc, LParenLoc, 384e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek FD, GetterSel, SetterSel, isAssign, isReadWrite, 385ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling Attributes,AttributesAsWritten, T, MethodImplKind, DC); 386e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek 387e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek // A case of continuation class adding a new property in the class. This 388e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek // is not what it was meant for. However, gcc supports it and so should we. 389e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek // Make sure setter/getters are declared here. 3906bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines ProcessPropertyDecl(PrimaryPDecl, CCPrimary, 3916bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines /* redeclaredProperty = */ nullptr, 392a054fb46b1fb596d1719b89d2d9a5be3c32a4b0dTed Kremenek /* lexicalDC = */ CDecl); 393d7c15a64ba8ebdca0dd48dd1d2f233107d34494eArgyrios Kyrtzidis PDecl->setGetterMethodDecl(PrimaryPDecl->getGetterMethodDecl()); 394d7c15a64ba8ebdca0dd48dd1d2f233107d34494eArgyrios Kyrtzidis PDecl->setSetterMethodDecl(PrimaryPDecl->getSetterMethodDecl()); 395c80553efdc269dabd4ed0c3210555f45729ab5ddArgyrios Kyrtzidis if (ASTMutationListener *L = Context.getASTMutationListener()) 3966bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines L->AddedObjCPropertyInClassExtension(PrimaryPDecl, /*OrigProp=*/nullptr, 3976bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines CDecl); 398d7c15a64ba8ebdca0dd48dd1d2f233107d34494eArgyrios Kyrtzidis return PrimaryPDecl; 399e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek } 400e23518342e326e3d6e9139f05384f030e2a94d4aFariborz Jahanian if (!Context.hasSameType(PIDecl->getType(), PDecl->getType())) { 401e23518342e326e3d6e9139f05384f030e2a94d4aFariborz Jahanian bool IncompatibleObjC = false; 402e23518342e326e3d6e9139f05384f030e2a94d4aFariborz Jahanian QualType ConvertedType; 403ff2a0ecae1d7692dbb63aa540dba41a8c21d7ee4Fariborz Jahanian // Relax the strict type matching for property type in continuation class. 404ff2a0ecae1d7692dbb63aa540dba41a8c21d7ee4Fariborz Jahanian // Allow property object type of continuation class to be different as long 405ad7eff2faf517779689327dc268817c2c2c8ebc4Fariborz Jahanian // as it narrows the object type in its primary class property. Note that 406ad7eff2faf517779689327dc268817c2c2c8ebc4Fariborz Jahanian // this conversion is safe only because the wider type is for a 'readonly' 407ad7eff2faf517779689327dc268817c2c2c8ebc4Fariborz Jahanian // property in primary class and 'narrowed' type for a 'readwrite' property 408ad7eff2faf517779689327dc268817c2c2c8ebc4Fariborz Jahanian // in continuation class. 409e23518342e326e3d6e9139f05384f030e2a94d4aFariborz Jahanian if (!isa<ObjCObjectPointerType>(PIDecl->getType()) || 410e23518342e326e3d6e9139f05384f030e2a94d4aFariborz Jahanian !isa<ObjCObjectPointerType>(PDecl->getType()) || 411e23518342e326e3d6e9139f05384f030e2a94d4aFariborz Jahanian (!isObjCPointerConversion(PDecl->getType(), PIDecl->getType(), 412e23518342e326e3d6e9139f05384f030e2a94d4aFariborz Jahanian ConvertedType, IncompatibleObjC)) 413e23518342e326e3d6e9139f05384f030e2a94d4aFariborz Jahanian || IncompatibleObjC) { 414e23518342e326e3d6e9139f05384f030e2a94d4aFariborz Jahanian Diag(AtLoc, 415e23518342e326e3d6e9139f05384f030e2a94d4aFariborz Jahanian diag::err_type_mismatch_continuation_class) << PDecl->getType(); 416e23518342e326e3d6e9139f05384f030e2a94d4aFariborz Jahanian Diag(PIDecl->getLocation(), diag::note_property_declare); 4176bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 418e23518342e326e3d6e9139f05384f030e2a94d4aFariborz Jahanian } 419a4b984d8396724a8e1137c22186c558c0cb0bf3fFariborz Jahanian } 420a4b984d8396724a8e1137c22186c558c0cb0bf3fFariborz Jahanian 421e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek // The property 'PIDecl's readonly attribute will be over-ridden 422e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek // with continuation class's readwrite property attribute! 42380aa1cd7973561889e51c1c152c8990a8de9c953Fariborz Jahanian unsigned PIkind = PIDecl->getPropertyAttributesAsWritten(); 424e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek if (isReadWrite && (PIkind & ObjCPropertyDecl::OBJC_PR_readonly)) { 425dc1031bf257457bd58cc19426a21e0fa1fa95789Fariborz Jahanian PIkind &= ~ObjCPropertyDecl::OBJC_PR_readonly; 426dc1031bf257457bd58cc19426a21e0fa1fa95789Fariborz Jahanian PIkind |= ObjCPropertyDecl::OBJC_PR_readwrite; 427dad633b0a0955ceb4579e9508224562ad41b6a8dFariborz Jahanian PIkind |= deduceWeakPropertyFromType(*this, PIDecl->getType()); 428ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling unsigned ClassExtensionMemoryModel = getOwnershipRule(Attributes); 429d9f95b35dc4fc168a167a9b9b61a5f9e1d0462baFariborz Jahanian unsigned PrimaryClassMemoryModel = getOwnershipRule(PIkind); 430dad633b0a0955ceb4579e9508224562ad41b6a8dFariborz Jahanian if (PrimaryClassMemoryModel && ClassExtensionMemoryModel && 431dad633b0a0955ceb4579e9508224562ad41b6a8dFariborz Jahanian (PrimaryClassMemoryModel != ClassExtensionMemoryModel)) { 432e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek Diag(AtLoc, diag::warn_property_attr_mismatch); 433e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek Diag(PIDecl->getLocation(), diag::note_property_declare); 434e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek } 4359d9a9436246160fe1dc3fe768ba5f69874d4b6edFariborz Jahanian else if (getLangOpts().ObjCAutoRefCount) { 4369d9a9436246160fe1dc3fe768ba5f69874d4b6edFariborz Jahanian QualType PrimaryPropertyQT = 4379d9a9436246160fe1dc3fe768ba5f69874d4b6edFariborz Jahanian Context.getCanonicalType(PIDecl->getType()).getUnqualifiedType(); 4389d9a9436246160fe1dc3fe768ba5f69874d4b6edFariborz Jahanian if (isa<ObjCObjectPointerType>(PrimaryPropertyQT)) { 439d75c6a7233e63ca924f5882a668cd41f2dc3ce27Bill Wendling bool PropertyIsWeak = ((PIkind & ObjCPropertyDecl::OBJC_PR_weak) != 0); 4409d9a9436246160fe1dc3fe768ba5f69874d4b6edFariborz Jahanian Qualifiers::ObjCLifetime PrimaryPropertyLifeTime = 4419d9a9436246160fe1dc3fe768ba5f69874d4b6edFariborz Jahanian PrimaryPropertyQT.getObjCLifetime(); 4429d9a9436246160fe1dc3fe768ba5f69874d4b6edFariborz Jahanian if (PrimaryPropertyLifeTime == Qualifiers::OCL_None && 443d75c6a7233e63ca924f5882a668cd41f2dc3ce27Bill Wendling (Attributes & ObjCDeclSpec::DQ_PR_weak) && 444d75c6a7233e63ca924f5882a668cd41f2dc3ce27Bill Wendling !PropertyIsWeak) { 4459d9a9436246160fe1dc3fe768ba5f69874d4b6edFariborz Jahanian Diag(AtLoc, diag::warn_property_implicitly_mismatched); 4469d9a9436246160fe1dc3fe768ba5f69874d4b6edFariborz Jahanian Diag(PIDecl->getLocation(), diag::note_property_declare); 4479d9a9436246160fe1dc3fe768ba5f69874d4b6edFariborz Jahanian } 4489d9a9436246160fe1dc3fe768ba5f69874d4b6edFariborz Jahanian } 4499d9a9436246160fe1dc3fe768ba5f69874d4b6edFariborz Jahanian } 4509d9a9436246160fe1dc3fe768ba5f69874d4b6edFariborz Jahanian 4519944c769b69b1904a7b16d3ce10fbdc9c67c764fTed Kremenek DeclContext *DC = cast<DeclContext>(CCPrimary); 4529944c769b69b1904a7b16d3ce10fbdc9c67c764fTed Kremenek if (!ObjCPropertyDecl::findPropertyDecl(DC, 4539944c769b69b1904a7b16d3ce10fbdc9c67c764fTed Kremenek PIDecl->getDeclName().getAsIdentifierInfo())) { 454651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // In mrr mode, 'readwrite' property must have an explicit 455651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // memory attribute. If none specified, select the default (assign). 456651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!getLangOpts().ObjCAutoRefCount) { 457651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!(PIkind & (ObjCDeclSpec::DQ_PR_assign | 458651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ObjCDeclSpec::DQ_PR_retain | 459651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ObjCDeclSpec::DQ_PR_strong | 460651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ObjCDeclSpec::DQ_PR_copy | 461651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ObjCDeclSpec::DQ_PR_unsafe_unretained | 462651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ObjCDeclSpec::DQ_PR_weak))) 463651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines PIkind |= ObjCPropertyDecl::OBJC_PR_assign; 464651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 465651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 466e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek // Protocol is not in the primary class. Must build one for it. 467e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek ObjCDeclSpec ProtocolPropertyODS; 468e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek // FIXME. Assuming that ObjCDeclSpec::ObjCPropertyAttributeKind 469e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek // and ObjCPropertyDecl::PropertyAttributeKind have identical 470e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek // values. Should consolidate both into one enum type. 471e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek ProtocolPropertyODS. 472e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek setPropertyAttributes((ObjCDeclSpec::ObjCPropertyAttributeKind) 473e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek PIkind); 474a28948f34817476d02412fa204cae038e228c827Fariborz Jahanian // Must re-establish the context from class extension to primary 475a28948f34817476d02412fa204cae038e228c827Fariborz Jahanian // class context. 4767939418cbdf1b610a69e6adf29cd7dc8d0e9eaf8Fariborz Jahanian ContextRAII SavedContext(*this, CCPrimary); 4777939418cbdf1b610a69e6adf29cd7dc8d0e9eaf8Fariborz Jahanian 478d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall Decl *ProtocolPtrTy = 47977bfb8b43ec3f7dee3a71f6e854b03ad29dab84fFariborz Jahanian ActOnProperty(S, AtLoc, LParenLoc, FD, ProtocolPropertyODS, 480e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek PIDecl->getGetterName(), 481e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek PIDecl->getSetterName(), 482a28948f34817476d02412fa204cae038e228c827Fariborz Jahanian isOverridingProperty, 4834a2e9ea0c191176ebe996516a9cf4f93b7e932ccTed Kremenek MethodImplKind, 4844a2e9ea0c191176ebe996516a9cf4f93b7e932ccTed Kremenek /* lexicalDC = */ CDecl); 485d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall PIDecl = cast<ObjCPropertyDecl>(ProtocolPtrTy); 48628685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek } 487e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek PIDecl->makeitReadWriteAttribute(); 488ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling if (Attributes & ObjCDeclSpec::DQ_PR_retain) 489e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_retain); 490ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling if (Attributes & ObjCDeclSpec::DQ_PR_strong) 491f85e193739c953358c865005855253af4f68a497John McCall PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_strong); 492ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling if (Attributes & ObjCDeclSpec::DQ_PR_copy) 493e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_copy); 494e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek PIDecl->setSetterName(SetterSel); 495e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek } else { 496788f489a37bf1150deb9378cec6a6eb902d0d1b2Ted Kremenek // Tailor the diagnostics for the common case where a readwrite 497788f489a37bf1150deb9378cec6a6eb902d0d1b2Ted Kremenek // property is declared both in the @interface and the continuation. 498788f489a37bf1150deb9378cec6a6eb902d0d1b2Ted Kremenek // This is a common error where the user often intended the original 499788f489a37bf1150deb9378cec6a6eb902d0d1b2Ted Kremenek // declaration to be readonly. 500788f489a37bf1150deb9378cec6a6eb902d0d1b2Ted Kremenek unsigned diag = 501ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling (Attributes & ObjCDeclSpec::DQ_PR_readwrite) && 502788f489a37bf1150deb9378cec6a6eb902d0d1b2Ted Kremenek (PIkind & ObjCPropertyDecl::OBJC_PR_readwrite) 503788f489a37bf1150deb9378cec6a6eb902d0d1b2Ted Kremenek ? diag::err_use_continuation_class_redeclaration_readwrite 504788f489a37bf1150deb9378cec6a6eb902d0d1b2Ted Kremenek : diag::err_use_continuation_class; 505788f489a37bf1150deb9378cec6a6eb902d0d1b2Ted Kremenek Diag(AtLoc, diag) 506e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek << CCPrimary->getDeclName(); 507e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek Diag(PIDecl->getLocation(), diag::note_property_declare); 5086bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 509e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek } 510e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek *isOverridingProperty = true; 511e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek // Make sure setter decl is synthesized, and added to primary class's list. 5128254aa62d9189395be1eed61194cd4b5ee6cb4a2Ted Kremenek ProcessPropertyDecl(PIDecl, CCPrimary, PDecl, CDecl); 513d7c15a64ba8ebdca0dd48dd1d2f233107d34494eArgyrios Kyrtzidis PDecl->setGetterMethodDecl(PIDecl->getGetterMethodDecl()); 514d7c15a64ba8ebdca0dd48dd1d2f233107d34494eArgyrios Kyrtzidis PDecl->setSetterMethodDecl(PIDecl->getSetterMethodDecl()); 515c80553efdc269dabd4ed0c3210555f45729ab5ddArgyrios Kyrtzidis if (ASTMutationListener *L = Context.getASTMutationListener()) 516c80553efdc269dabd4ed0c3210555f45729ab5ddArgyrios Kyrtzidis L->AddedObjCPropertyInClassExtension(PDecl, PIDecl, CDecl); 5176defd9f31eec51278d056f1bff885018e2321373Fariborz Jahanian return PDecl; 518e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek} 519e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek 520e3d67bcc7b89b335dbcd097a299658057ea31097Ted KremenekObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S, 521e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek ObjCContainerDecl *CDecl, 522e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek SourceLocation AtLoc, 52377bfb8b43ec3f7dee3a71f6e854b03ad29dab84fFariborz Jahanian SourceLocation LParenLoc, 524e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek FieldDeclarator &FD, 525e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek Selector GetterSel, 526e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek Selector SetterSel, 527e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek const bool isAssign, 528e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek const bool isReadWrite, 529ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling const unsigned Attributes, 530dbbdec994f5a96b5c25aaa679cd86ecabf545f7bArgyrios Kyrtzidis const unsigned AttributesAsWritten, 53183a230c83a54190366138c1a4f4310ef838b88fcJohn McCall TypeSourceInfo *TInfo, 53223173d7f029f430611caceea72ae61ba6b80af1cTed Kremenek tok::ObjCKeywordKind MethodImplKind, 53323173d7f029f430611caceea72ae61ba6b80af1cTed Kremenek DeclContext *lexicalDC){ 534e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek IdentifierInfo *PropertyId = FD.D.getIdentifier(); 53583a230c83a54190366138c1a4f4310ef838b88fcJohn McCall QualType T = TInfo->getType(); 53628685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek 53728685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek // Issue a warning if property is 'assign' as default and its object, which is 53828685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek // gc'able conforms to NSCopying protocol 5394e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie if (getLangOpts().getGC() != LangOptions::NonGC && 540ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling isAssign && !(Attributes & ObjCDeclSpec::DQ_PR_assign)) 541c12c5bba6ceb6acd4e51e7a0fc03257da9cfd44eJohn McCall if (const ObjCObjectPointerType *ObjPtrTy = 542c12c5bba6ceb6acd4e51e7a0fc03257da9cfd44eJohn McCall T->getAs<ObjCObjectPointerType>()) { 543c12c5bba6ceb6acd4e51e7a0fc03257da9cfd44eJohn McCall ObjCInterfaceDecl *IDecl = ObjPtrTy->getObjectType()->getInterface(); 544c12c5bba6ceb6acd4e51e7a0fc03257da9cfd44eJohn McCall if (IDecl) 545c12c5bba6ceb6acd4e51e7a0fc03257da9cfd44eJohn McCall if (ObjCProtocolDecl* PNSCopying = 546c12c5bba6ceb6acd4e51e7a0fc03257da9cfd44eJohn McCall LookupProtocol(&Context.Idents.get("NSCopying"), AtLoc)) 547c12c5bba6ceb6acd4e51e7a0fc03257da9cfd44eJohn McCall if (IDecl->ClassImplementsProtocol(PNSCopying, true)) 548c12c5bba6ceb6acd4e51e7a0fc03257da9cfd44eJohn McCall Diag(AtLoc, diag::warn_implements_nscopying) << PropertyId; 54928685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek } 55027d4644f4fad002b9e1be87c4e07f0f0c8240e1dEli Friedman 55127d4644f4fad002b9e1be87c4e07f0f0c8240e1dEli Friedman if (T->isObjCObjectType()) { 55227d4644f4fad002b9e1be87c4e07f0f0c8240e1dEli Friedman SourceLocation StarLoc = TInfo->getTypeLoc().getLocEnd(); 5536bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines StarLoc = getLocForEndOfToken(StarLoc); 55427d4644f4fad002b9e1be87c4e07f0f0c8240e1dEli Friedman Diag(FD.D.getIdentifierLoc(), diag::err_statically_allocated_object) 55527d4644f4fad002b9e1be87c4e07f0f0c8240e1dEli Friedman << FixItHint::CreateInsertion(StarLoc, "*"); 55627d4644f4fad002b9e1be87c4e07f0f0c8240e1dEli Friedman T = Context.getObjCObjectPointerType(T); 55727d4644f4fad002b9e1be87c4e07f0f0c8240e1dEli Friedman SourceLocation TLoc = TInfo->getTypeLoc().getLocStart(); 55827d4644f4fad002b9e1be87c4e07f0f0c8240e1dEli Friedman TInfo = Context.getTrivialTypeSourceInfo(T, TLoc); 55927d4644f4fad002b9e1be87c4e07f0f0c8240e1dEli Friedman } 56028685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek 561e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek DeclContext *DC = cast<DeclContext>(CDecl); 56228685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek ObjCPropertyDecl *PDecl = ObjCPropertyDecl::Create(Context, DC, 56328685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek FD.D.getIdentifierLoc(), 56477bfb8b43ec3f7dee3a71f6e854b03ad29dab84fFariborz Jahanian PropertyId, AtLoc, LParenLoc, TInfo); 565e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek 5669f550ff05d496e6b9480e5619a21d9da0c9e27c1Ted Kremenek if (ObjCPropertyDecl *prevDecl = 5679f550ff05d496e6b9480e5619a21d9da0c9e27c1Ted Kremenek ObjCPropertyDecl::findPropertyDecl(DC, PropertyId)) { 56828685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek Diag(PDecl->getLocation(), diag::err_duplicate_property); 569894ae6ad081465a3b168db7e60ab3f94e3730b57Ted Kremenek Diag(prevDecl->getLocation(), diag::note_property_declare); 57028685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek PDecl->setInvalidDecl(); 57128685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek } 57223173d7f029f430611caceea72ae61ba6b80af1cTed Kremenek else { 57328685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek DC->addDecl(PDecl); 57423173d7f029f430611caceea72ae61ba6b80af1cTed Kremenek if (lexicalDC) 57523173d7f029f430611caceea72ae61ba6b80af1cTed Kremenek PDecl->setLexicalDeclContext(lexicalDC); 57623173d7f029f430611caceea72ae61ba6b80af1cTed Kremenek } 57728685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek 57828685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek if (T->isArrayType() || T->isFunctionType()) { 57928685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek Diag(AtLoc, diag::err_property_type) << T; 58028685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek PDecl->setInvalidDecl(); 58128685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek } 58228685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek 58328685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek ProcessDeclAttributes(S, PDecl, FD.D); 58428685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek 58528685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek // Regardless of setter/getter attribute, we save the default getter/setter 58628685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek // selector names in anticipation of declaration of setter/getter methods. 58728685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek PDecl->setGetterName(GetterSel); 58828685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek PDecl->setSetterName(SetterSel); 5890a68dc7f04be1542ce249ff4adb169453698ad91Argyrios Kyrtzidis PDecl->setPropertyAttributesAsWritten( 590dbbdec994f5a96b5c25aaa679cd86ecabf545f7bArgyrios Kyrtzidis makePropertyAttributesAsWritten(AttributesAsWritten)); 5910a68dc7f04be1542ce249ff4adb169453698ad91Argyrios Kyrtzidis 592ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling if (Attributes & ObjCDeclSpec::DQ_PR_readonly) 59328685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readonly); 59428685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek 595ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling if (Attributes & ObjCDeclSpec::DQ_PR_getter) 59628685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_getter); 59728685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek 598ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling if (Attributes & ObjCDeclSpec::DQ_PR_setter) 59928685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_setter); 60028685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek 60128685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek if (isReadWrite) 60228685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readwrite); 60328685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek 604ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling if (Attributes & ObjCDeclSpec::DQ_PR_retain) 60528685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_retain); 60628685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek 607ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling if (Attributes & ObjCDeclSpec::DQ_PR_strong) 608f85e193739c953358c865005855253af4f68a497John McCall PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_strong); 609f85e193739c953358c865005855253af4f68a497John McCall 610ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling if (Attributes & ObjCDeclSpec::DQ_PR_weak) 611f85e193739c953358c865005855253af4f68a497John McCall PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_weak); 612f85e193739c953358c865005855253af4f68a497John McCall 613ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling if (Attributes & ObjCDeclSpec::DQ_PR_copy) 61428685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_copy); 61528685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek 616ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling if (Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained) 617f85e193739c953358c865005855253af4f68a497John McCall PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_unsafe_unretained); 618f85e193739c953358c865005855253af4f68a497John McCall 61928685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek if (isAssign) 62028685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_assign); 62128685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek 622265941bc308d65cc270d5c4de5806f37ce405606John McCall // In the semantic attributes, one of nonatomic or atomic is always set. 623ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling if (Attributes & ObjCDeclSpec::DQ_PR_nonatomic) 62428685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_nonatomic); 625265941bc308d65cc270d5c4de5806f37ce405606John McCall else 62645937ae10a0f70f74508165aab4f2b63e18ea747Fariborz Jahanian PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_atomic); 62728685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek 628f85e193739c953358c865005855253af4f68a497John McCall // 'unsafe_unretained' is alias for 'assign'. 629ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling if (Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained) 630f85e193739c953358c865005855253af4f68a497John McCall PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_assign); 631f85e193739c953358c865005855253af4f68a497John McCall if (isAssign) 632f85e193739c953358c865005855253af4f68a497John McCall PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_unsafe_unretained); 633f85e193739c953358c865005855253af4f68a497John McCall 63428685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek if (MethodImplKind == tok::objc_required) 63528685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek PDecl->setPropertyImplementation(ObjCPropertyDecl::Required); 63628685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek else if (MethodImplKind == tok::objc_optional) 63728685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek PDecl->setPropertyImplementation(ObjCPropertyDecl::Optional); 63828685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek 639e3d67bcc7b89b335dbcd097a299658057ea31097Ted Kremenek return PDecl; 64028685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek} 64128685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek 642f85e193739c953358c865005855253af4f68a497John McCallstatic void checkARCPropertyImpl(Sema &S, SourceLocation propertyImplLoc, 643f85e193739c953358c865005855253af4f68a497John McCall ObjCPropertyDecl *property, 644f85e193739c953358c865005855253af4f68a497John McCall ObjCIvarDecl *ivar) { 645f85e193739c953358c865005855253af4f68a497John McCall if (property->isInvalidDecl() || ivar->isInvalidDecl()) return; 646f85e193739c953358c865005855253af4f68a497John McCall 647f85e193739c953358c865005855253af4f68a497John McCall QualType ivarType = ivar->getType(); 648f85e193739c953358c865005855253af4f68a497John McCall Qualifiers::ObjCLifetime ivarLifetime = ivarType.getObjCLifetime(); 649f85e193739c953358c865005855253af4f68a497John McCall 650265941bc308d65cc270d5c4de5806f37ce405606John McCall // The lifetime implied by the property's attributes. 651265941bc308d65cc270d5c4de5806f37ce405606John McCall Qualifiers::ObjCLifetime propertyLifetime = 652265941bc308d65cc270d5c4de5806f37ce405606John McCall getImpliedARCOwnership(property->getPropertyAttributes(), 653265941bc308d65cc270d5c4de5806f37ce405606John McCall property->getType()); 654f85e193739c953358c865005855253af4f68a497John McCall 655265941bc308d65cc270d5c4de5806f37ce405606John McCall // We're fine if they match. 656265941bc308d65cc270d5c4de5806f37ce405606John McCall if (propertyLifetime == ivarLifetime) return; 657f85e193739c953358c865005855253af4f68a497John McCall 658265941bc308d65cc270d5c4de5806f37ce405606John McCall // These aren't valid lifetimes for object ivars; don't diagnose twice. 659265941bc308d65cc270d5c4de5806f37ce405606John McCall if (ivarLifetime == Qualifiers::OCL_None || 660265941bc308d65cc270d5c4de5806f37ce405606John McCall ivarLifetime == Qualifiers::OCL_Autoreleasing) 661265941bc308d65cc270d5c4de5806f37ce405606John McCall return; 662265941bc308d65cc270d5c4de5806f37ce405606John McCall 663d64c2eb83d7ec86faa4f2554935a977a19573f59John McCall // If the ivar is private, and it's implicitly __unsafe_unretained 664d64c2eb83d7ec86faa4f2554935a977a19573f59John McCall // becaues of its type, then pretend it was actually implicitly 665d64c2eb83d7ec86faa4f2554935a977a19573f59John McCall // __strong. This is only sound because we're processing the 666d64c2eb83d7ec86faa4f2554935a977a19573f59John McCall // property implementation before parsing any method bodies. 667d64c2eb83d7ec86faa4f2554935a977a19573f59John McCall if (ivarLifetime == Qualifiers::OCL_ExplicitNone && 668d64c2eb83d7ec86faa4f2554935a977a19573f59John McCall propertyLifetime == Qualifiers::OCL_Strong && 669d64c2eb83d7ec86faa4f2554935a977a19573f59John McCall ivar->getAccessControl() == ObjCIvarDecl::Private) { 670d64c2eb83d7ec86faa4f2554935a977a19573f59John McCall SplitQualType split = ivarType.split(); 671d64c2eb83d7ec86faa4f2554935a977a19573f59John McCall if (split.Quals.hasObjCLifetime()) { 672d64c2eb83d7ec86faa4f2554935a977a19573f59John McCall assert(ivarType->isObjCARCImplicitlyUnretainedType()); 673d64c2eb83d7ec86faa4f2554935a977a19573f59John McCall split.Quals.setObjCLifetime(Qualifiers::OCL_Strong); 674d64c2eb83d7ec86faa4f2554935a977a19573f59John McCall ivarType = S.Context.getQualifiedType(split); 675d64c2eb83d7ec86faa4f2554935a977a19573f59John McCall ivar->setType(ivarType); 676d64c2eb83d7ec86faa4f2554935a977a19573f59John McCall return; 677d64c2eb83d7ec86faa4f2554935a977a19573f59John McCall } 678d64c2eb83d7ec86faa4f2554935a977a19573f59John McCall } 679d64c2eb83d7ec86faa4f2554935a977a19573f59John McCall 680265941bc308d65cc270d5c4de5806f37ce405606John McCall switch (propertyLifetime) { 681265941bc308d65cc270d5c4de5806f37ce405606John McCall case Qualifiers::OCL_Strong: 682135aa60c613bdcc0e8e237b12bf93cab04284419Argyrios Kyrtzidis S.Diag(ivar->getLocation(), diag::err_arc_strong_property_ownership) 683265941bc308d65cc270d5c4de5806f37ce405606John McCall << property->getDeclName() 684265941bc308d65cc270d5c4de5806f37ce405606John McCall << ivar->getDeclName() 685265941bc308d65cc270d5c4de5806f37ce405606John McCall << ivarLifetime; 686265941bc308d65cc270d5c4de5806f37ce405606John McCall break; 687265941bc308d65cc270d5c4de5806f37ce405606John McCall 688265941bc308d65cc270d5c4de5806f37ce405606John McCall case Qualifiers::OCL_Weak: 689135aa60c613bdcc0e8e237b12bf93cab04284419Argyrios Kyrtzidis S.Diag(ivar->getLocation(), diag::error_weak_property) 690265941bc308d65cc270d5c4de5806f37ce405606John McCall << property->getDeclName() 691265941bc308d65cc270d5c4de5806f37ce405606John McCall << ivar->getDeclName(); 692265941bc308d65cc270d5c4de5806f37ce405606John McCall break; 693265941bc308d65cc270d5c4de5806f37ce405606John McCall 694265941bc308d65cc270d5c4de5806f37ce405606John McCall case Qualifiers::OCL_ExplicitNone: 695135aa60c613bdcc0e8e237b12bf93cab04284419Argyrios Kyrtzidis S.Diag(ivar->getLocation(), diag::err_arc_assign_property_ownership) 696265941bc308d65cc270d5c4de5806f37ce405606John McCall << property->getDeclName() 697265941bc308d65cc270d5c4de5806f37ce405606John McCall << ivar->getDeclName() 698265941bc308d65cc270d5c4de5806f37ce405606John McCall << ((property->getPropertyAttributesAsWritten() 699265941bc308d65cc270d5c4de5806f37ce405606John McCall & ObjCPropertyDecl::OBJC_PR_assign) != 0); 700265941bc308d65cc270d5c4de5806f37ce405606John McCall break; 701265941bc308d65cc270d5c4de5806f37ce405606John McCall 702265941bc308d65cc270d5c4de5806f37ce405606John McCall case Qualifiers::OCL_Autoreleasing: 703265941bc308d65cc270d5c4de5806f37ce405606John McCall llvm_unreachable("properties cannot be autoreleasing"); 704265941bc308d65cc270d5c4de5806f37ce405606John McCall 705265941bc308d65cc270d5c4de5806f37ce405606John McCall case Qualifiers::OCL_None: 706265941bc308d65cc270d5c4de5806f37ce405606John McCall // Any other property should be ignored. 707f85e193739c953358c865005855253af4f68a497John McCall return; 708f85e193739c953358c865005855253af4f68a497John McCall } 709f85e193739c953358c865005855253af4f68a497John McCall 710f85e193739c953358c865005855253af4f68a497John McCall S.Diag(property->getLocation(), diag::note_property_declare); 711135aa60c613bdcc0e8e237b12bf93cab04284419Argyrios Kyrtzidis if (propertyImplLoc.isValid()) 712135aa60c613bdcc0e8e237b12bf93cab04284419Argyrios Kyrtzidis S.Diag(propertyImplLoc, diag::note_property_synthesize); 713f85e193739c953358c865005855253af4f68a497John McCall} 714f85e193739c953358c865005855253af4f68a497John McCall 715015f608042a1d247899866849e69a4e9a1aff6a8Fariborz Jahanian/// setImpliedPropertyAttributeForReadOnlyProperty - 716015f608042a1d247899866849e69a4e9a1aff6a8Fariborz Jahanian/// This routine evaludates life-time attributes for a 'readonly' 717015f608042a1d247899866849e69a4e9a1aff6a8Fariborz Jahanian/// property with no known lifetime of its own, using backing 718015f608042a1d247899866849e69a4e9a1aff6a8Fariborz Jahanian/// 'ivar's attribute, if any. If no backing 'ivar', property's 719015f608042a1d247899866849e69a4e9a1aff6a8Fariborz Jahanian/// life-time is assumed 'strong'. 720015f608042a1d247899866849e69a4e9a1aff6a8Fariborz Jahanianstatic void setImpliedPropertyAttributeForReadOnlyProperty( 721015f608042a1d247899866849e69a4e9a1aff6a8Fariborz Jahanian ObjCPropertyDecl *property, ObjCIvarDecl *ivar) { 722015f608042a1d247899866849e69a4e9a1aff6a8Fariborz Jahanian Qualifiers::ObjCLifetime propertyLifetime = 723015f608042a1d247899866849e69a4e9a1aff6a8Fariborz Jahanian getImpliedARCOwnership(property->getPropertyAttributes(), 724015f608042a1d247899866849e69a4e9a1aff6a8Fariborz Jahanian property->getType()); 725015f608042a1d247899866849e69a4e9a1aff6a8Fariborz Jahanian if (propertyLifetime != Qualifiers::OCL_None) 726015f608042a1d247899866849e69a4e9a1aff6a8Fariborz Jahanian return; 727015f608042a1d247899866849e69a4e9a1aff6a8Fariborz Jahanian 728015f608042a1d247899866849e69a4e9a1aff6a8Fariborz Jahanian if (!ivar) { 729015f608042a1d247899866849e69a4e9a1aff6a8Fariborz Jahanian // if no backing ivar, make property 'strong'. 730015f608042a1d247899866849e69a4e9a1aff6a8Fariborz Jahanian property->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_strong); 731015f608042a1d247899866849e69a4e9a1aff6a8Fariborz Jahanian return; 732015f608042a1d247899866849e69a4e9a1aff6a8Fariborz Jahanian } 733015f608042a1d247899866849e69a4e9a1aff6a8Fariborz Jahanian // property assumes owenership of backing ivar. 734015f608042a1d247899866849e69a4e9a1aff6a8Fariborz Jahanian QualType ivarType = ivar->getType(); 735015f608042a1d247899866849e69a4e9a1aff6a8Fariborz Jahanian Qualifiers::ObjCLifetime ivarLifetime = ivarType.getObjCLifetime(); 736015f608042a1d247899866849e69a4e9a1aff6a8Fariborz Jahanian if (ivarLifetime == Qualifiers::OCL_Strong) 737015f608042a1d247899866849e69a4e9a1aff6a8Fariborz Jahanian property->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_strong); 738015f608042a1d247899866849e69a4e9a1aff6a8Fariborz Jahanian else if (ivarLifetime == Qualifiers::OCL_Weak) 739015f608042a1d247899866849e69a4e9a1aff6a8Fariborz Jahanian property->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_weak); 740015f608042a1d247899866849e69a4e9a1aff6a8Fariborz Jahanian return; 741015f608042a1d247899866849e69a4e9a1aff6a8Fariborz Jahanian} 74228685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek 7438dbda516d343706bae904f800c6d64e145d58a8cFariborz Jahanian/// DiagnosePropertyMismatchDeclInProtocols - diagnose properties declared 7448dbda516d343706bae904f800c6d64e145d58a8cFariborz Jahanian/// in inherited protocols with mismatched types. Since any of them can 7458dbda516d343706bae904f800c6d64e145d58a8cFariborz Jahanian/// be candidate for synthesis. 746b1a4d37c0549501fe12907bc6ffa81bc5d04b98aBenjamin Kramerstatic void 747b1a4d37c0549501fe12907bc6ffa81bc5d04b98aBenjamin KramerDiagnosePropertyMismatchDeclInProtocols(Sema &S, SourceLocation AtLoc, 748b1a4d37c0549501fe12907bc6ffa81bc5d04b98aBenjamin Kramer ObjCInterfaceDecl *ClassDecl, 7498dbda516d343706bae904f800c6d64e145d58a8cFariborz Jahanian ObjCPropertyDecl *Property) { 7508dbda516d343706bae904f800c6d64e145d58a8cFariborz Jahanian ObjCInterfaceDecl::ProtocolPropertyMap PropMap; 751651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (const auto *PI : ClassDecl->all_referenced_protocols()) { 752651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (const ObjCProtocolDecl *PDecl = PI->getDefinition()) 7538dbda516d343706bae904f800c6d64e145d58a8cFariborz Jahanian PDecl->collectInheritedProtocolProperties(Property, PropMap); 7548dbda516d343706bae904f800c6d64e145d58a8cFariborz Jahanian } 7558dbda516d343706bae904f800c6d64e145d58a8cFariborz Jahanian if (ObjCInterfaceDecl *SDecl = ClassDecl->getSuperClass()) 7568dbda516d343706bae904f800c6d64e145d58a8cFariborz Jahanian while (SDecl) { 757651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (const auto *PI : SDecl->all_referenced_protocols()) { 758651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (const ObjCProtocolDecl *PDecl = PI->getDefinition()) 7598dbda516d343706bae904f800c6d64e145d58a8cFariborz Jahanian PDecl->collectInheritedProtocolProperties(Property, PropMap); 7608dbda516d343706bae904f800c6d64e145d58a8cFariborz Jahanian } 7618dbda516d343706bae904f800c6d64e145d58a8cFariborz Jahanian SDecl = SDecl->getSuperClass(); 7628dbda516d343706bae904f800c6d64e145d58a8cFariborz Jahanian } 7638dbda516d343706bae904f800c6d64e145d58a8cFariborz Jahanian 7648dbda516d343706bae904f800c6d64e145d58a8cFariborz Jahanian if (PropMap.empty()) 7658dbda516d343706bae904f800c6d64e145d58a8cFariborz Jahanian return; 7668dbda516d343706bae904f800c6d64e145d58a8cFariborz Jahanian 7678dbda516d343706bae904f800c6d64e145d58a8cFariborz Jahanian QualType RHSType = S.Context.getCanonicalType(Property->getType()); 7688dbda516d343706bae904f800c6d64e145d58a8cFariborz Jahanian bool FirsTime = true; 7698dbda516d343706bae904f800c6d64e145d58a8cFariborz Jahanian for (ObjCInterfaceDecl::ProtocolPropertyMap::iterator 7708dbda516d343706bae904f800c6d64e145d58a8cFariborz Jahanian I = PropMap.begin(), E = PropMap.end(); I != E; I++) { 7718dbda516d343706bae904f800c6d64e145d58a8cFariborz Jahanian ObjCPropertyDecl *Prop = I->second; 7728dbda516d343706bae904f800c6d64e145d58a8cFariborz Jahanian QualType LHSType = S.Context.getCanonicalType(Prop->getType()); 7738dbda516d343706bae904f800c6d64e145d58a8cFariborz Jahanian if (!S.Context.propertyTypesAreCompatible(LHSType, RHSType)) { 7748dbda516d343706bae904f800c6d64e145d58a8cFariborz Jahanian bool IncompatibleObjC = false; 7758dbda516d343706bae904f800c6d64e145d58a8cFariborz Jahanian QualType ConvertedType; 7768dbda516d343706bae904f800c6d64e145d58a8cFariborz Jahanian if (!S.isObjCPointerConversion(RHSType, LHSType, ConvertedType, IncompatibleObjC) 7778dbda516d343706bae904f800c6d64e145d58a8cFariborz Jahanian || IncompatibleObjC) { 7788dbda516d343706bae904f800c6d64e145d58a8cFariborz Jahanian if (FirsTime) { 7798dbda516d343706bae904f800c6d64e145d58a8cFariborz Jahanian S.Diag(Property->getLocation(), diag::warn_protocol_property_mismatch) 7808dbda516d343706bae904f800c6d64e145d58a8cFariborz Jahanian << Property->getType(); 7818dbda516d343706bae904f800c6d64e145d58a8cFariborz Jahanian FirsTime = false; 7828dbda516d343706bae904f800c6d64e145d58a8cFariborz Jahanian } 7838dbda516d343706bae904f800c6d64e145d58a8cFariborz Jahanian S.Diag(Prop->getLocation(), diag::note_protocol_property_declare) 7848dbda516d343706bae904f800c6d64e145d58a8cFariborz Jahanian << Prop->getType(); 7858dbda516d343706bae904f800c6d64e145d58a8cFariborz Jahanian } 7868dbda516d343706bae904f800c6d64e145d58a8cFariborz Jahanian } 7878dbda516d343706bae904f800c6d64e145d58a8cFariborz Jahanian } 7888dbda516d343706bae904f800c6d64e145d58a8cFariborz Jahanian if (!FirsTime && AtLoc.isValid()) 7898dbda516d343706bae904f800c6d64e145d58a8cFariborz Jahanian S.Diag(AtLoc, diag::note_property_synthesize); 7908dbda516d343706bae904f800c6d64e145d58a8cFariborz Jahanian} 7918dbda516d343706bae904f800c6d64e145d58a8cFariborz Jahanian 79228685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek/// ActOnPropertyImplDecl - This routine performs semantic checks and 79328685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek/// builds the AST node for a property implementation declaration; declared 794699c9044c7d53a2774d0dd261a6901dd2c4a545fJames Dennett/// as \@synthesize or \@dynamic. 79528685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek/// 796d226f65006733ed7f709c3174f22ce33391cb58fJohn McCallDecl *Sema::ActOnPropertyImplDecl(Scope *S, 797d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall SourceLocation AtLoc, 798d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall SourceLocation PropertyLoc, 799d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall bool Synthesize, 800d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall IdentifierInfo *PropertyId, 801a4ffd85a6684e42f900aad5459e58ad91bb88755Douglas Gregor IdentifierInfo *PropertyIvar, 802a4ffd85a6684e42f900aad5459e58ad91bb88755Douglas Gregor SourceLocation PropertyIvarLoc) { 803e9686572f17968048a5e097254f85c202ea44aecTed Kremenek ObjCContainerDecl *ClassImpDecl = 80484e0ccff7a6e51d7b81fd58686b493a4880dd44dFariborz Jahanian dyn_cast<ObjCContainerDecl>(CurContext); 80528685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek // Make sure we have a context for the property implementation declaration. 80628685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek if (!ClassImpDecl) { 80728685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek Diag(AtLoc, diag::error_missing_property_context); 8086bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 80928685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek } 810f911242f43ae1b0a85c323631fe817df95c9cbe9Argyrios Kyrtzidis if (PropertyIvarLoc.isInvalid()) 811f911242f43ae1b0a85c323631fe817df95c9cbe9Argyrios Kyrtzidis PropertyIvarLoc = PropertyLoc; 812e4c043d3fdd0f98ab724aa4f1419cec9985ea2c4Eli Friedman SourceLocation PropertyDiagLoc = PropertyLoc; 813e4c043d3fdd0f98ab724aa4f1419cec9985ea2c4Eli Friedman if (PropertyDiagLoc.isInvalid()) 814e4c043d3fdd0f98ab724aa4f1419cec9985ea2c4Eli Friedman PropertyDiagLoc = ClassImpDecl->getLocStart(); 8156bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines ObjCPropertyDecl *property = nullptr; 8166bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines ObjCInterfaceDecl *IDecl = nullptr; 81728685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek // Find the class or category class where this property must have 81828685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek // a declaration. 8196bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines ObjCImplementationDecl *IC = nullptr; 8206bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines ObjCCategoryImplDecl *CatImplClass = nullptr; 82128685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek if ((IC = dyn_cast<ObjCImplementationDecl>(ClassImpDecl))) { 82228685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek IDecl = IC->getClassInterface(); 82328685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek // We always synthesize an interface for an implementation 82428685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek // without an interface decl. So, IDecl is always non-zero. 82528685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek assert(IDecl && 82628685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek "ActOnPropertyImplDecl - @implementation without @interface"); 82728685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek 82828685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek // Look for this property declaration in the @implementation's @interface 82928685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek property = IDecl->FindPropertyDeclaration(PropertyId); 83028685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek if (!property) { 83128685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek Diag(PropertyLoc, diag::error_bad_property_decl) << IDecl->getDeclName(); 8326bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 83328685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek } 834dd4430e596fac34e9ce44228a249f71e73effd4aFariborz Jahanian unsigned PIkind = property->getPropertyAttributesAsWritten(); 83545937ae10a0f70f74508165aab4f2b63e18ea747Fariborz Jahanian if ((PIkind & (ObjCPropertyDecl::OBJC_PR_atomic | 83645937ae10a0f70f74508165aab4f2b63e18ea747Fariborz Jahanian ObjCPropertyDecl::OBJC_PR_nonatomic) ) == 0) { 837dd4430e596fac34e9ce44228a249f71e73effd4aFariborz Jahanian if (AtLoc.isValid()) 838dd4430e596fac34e9ce44228a249f71e73effd4aFariborz Jahanian Diag(AtLoc, diag::warn_implicit_atomic_property); 839dd4430e596fac34e9ce44228a249f71e73effd4aFariborz Jahanian else 840dd4430e596fac34e9ce44228a249f71e73effd4aFariborz Jahanian Diag(IC->getLocation(), diag::warn_auto_implicit_atomic_property); 841dd4430e596fac34e9ce44228a249f71e73effd4aFariborz Jahanian Diag(property->getLocation(), diag::note_property_declare); 842dd4430e596fac34e9ce44228a249f71e73effd4aFariborz Jahanian } 843dd4430e596fac34e9ce44228a249f71e73effd4aFariborz Jahanian 84428685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek if (const ObjCCategoryDecl *CD = 84528685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek dyn_cast<ObjCCategoryDecl>(property->getDeclContext())) { 84628685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek if (!CD->IsClassExtension()) { 84728685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek Diag(PropertyLoc, diag::error_category_property) << CD->getDeclName(); 84828685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek Diag(property->getLocation(), diag::note_property_declare); 8496bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 85028685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek } 85128685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek } 8522b309fb125906b1fb10efb1890860cd042fbfab3Fariborz Jahanian if (Synthesize&& 8532b309fb125906b1fb10efb1890860cd042fbfab3Fariborz Jahanian (PIkind & ObjCPropertyDecl::OBJC_PR_readonly) && 8542b309fb125906b1fb10efb1890860cd042fbfab3Fariborz Jahanian property->hasAttr<IBOutletAttr>() && 8552b309fb125906b1fb10efb1890860cd042fbfab3Fariborz Jahanian !AtLoc.isValid()) { 856125643455953069b925b30d2e4ae5674063984edFariborz Jahanian bool ReadWriteProperty = false; 857125643455953069b925b30d2e4ae5674063984edFariborz Jahanian // Search into the class extensions and see if 'readonly property is 858125643455953069b925b30d2e4ae5674063984edFariborz Jahanian // redeclared 'readwrite', then no warning is to be issued. 859651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (auto *Ext : IDecl->known_extensions()) { 860125643455953069b925b30d2e4ae5674063984edFariborz Jahanian DeclContext::lookup_result R = Ext->lookup(property->getDeclName()); 861125643455953069b925b30d2e4ae5674063984edFariborz Jahanian if (!R.empty()) 862125643455953069b925b30d2e4ae5674063984edFariborz Jahanian if (ObjCPropertyDecl *ExtProp = dyn_cast<ObjCPropertyDecl>(R[0])) { 863125643455953069b925b30d2e4ae5674063984edFariborz Jahanian PIkind = ExtProp->getPropertyAttributesAsWritten(); 864125643455953069b925b30d2e4ae5674063984edFariborz Jahanian if (PIkind & ObjCPropertyDecl::OBJC_PR_readwrite) { 865125643455953069b925b30d2e4ae5674063984edFariborz Jahanian ReadWriteProperty = true; 866125643455953069b925b30d2e4ae5674063984edFariborz Jahanian break; 867125643455953069b925b30d2e4ae5674063984edFariborz Jahanian } 868125643455953069b925b30d2e4ae5674063984edFariborz Jahanian } 869125643455953069b925b30d2e4ae5674063984edFariborz Jahanian } 870125643455953069b925b30d2e4ae5674063984edFariborz Jahanian 871125643455953069b925b30d2e4ae5674063984edFariborz Jahanian if (!ReadWriteProperty) { 872a4475a6b8277f24ed15d7b67d9dab77444c77cb1Ted Kremenek Diag(property->getLocation(), diag::warn_auto_readonly_iboutlet_property) 873651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines << property; 874125643455953069b925b30d2e4ae5674063984edFariborz Jahanian SourceLocation readonlyLoc; 875125643455953069b925b30d2e4ae5674063984edFariborz Jahanian if (LocPropertyAttribute(Context, "readonly", 876125643455953069b925b30d2e4ae5674063984edFariborz Jahanian property->getLParenLoc(), readonlyLoc)) { 877125643455953069b925b30d2e4ae5674063984edFariborz Jahanian SourceLocation endLoc = 878125643455953069b925b30d2e4ae5674063984edFariborz Jahanian readonlyLoc.getLocWithOffset(strlen("readonly")-1); 879125643455953069b925b30d2e4ae5674063984edFariborz Jahanian SourceRange ReadonlySourceRange(readonlyLoc, endLoc); 880125643455953069b925b30d2e4ae5674063984edFariborz Jahanian Diag(property->getLocation(), 881125643455953069b925b30d2e4ae5674063984edFariborz Jahanian diag::note_auto_readonly_iboutlet_fixup_suggest) << 882125643455953069b925b30d2e4ae5674063984edFariborz Jahanian FixItHint::CreateReplacement(ReadonlySourceRange, "readwrite"); 883125643455953069b925b30d2e4ae5674063984edFariborz Jahanian } 884edcc27f6171fd8cc736d057d87b128252fcb7344Fariborz Jahanian } 8852b309fb125906b1fb10efb1890860cd042fbfab3Fariborz Jahanian } 8868dbda516d343706bae904f800c6d64e145d58a8cFariborz Jahanian if (Synthesize && isa<ObjCProtocolDecl>(property->getDeclContext())) 8878dbda516d343706bae904f800c6d64e145d58a8cFariborz Jahanian DiagnosePropertyMismatchDeclInProtocols(*this, AtLoc, IDecl, property); 8882b309fb125906b1fb10efb1890860cd042fbfab3Fariborz Jahanian 88928685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek } else if ((CatImplClass = dyn_cast<ObjCCategoryImplDecl>(ClassImpDecl))) { 89028685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek if (Synthesize) { 89128685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek Diag(AtLoc, diag::error_synthesize_category_decl); 8926bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 89328685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek } 89428685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek IDecl = CatImplClass->getClassInterface(); 89528685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek if (!IDecl) { 89628685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek Diag(AtLoc, diag::error_missing_property_interface); 8976bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 89828685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek } 89928685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek ObjCCategoryDecl *Category = 90028685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek IDecl->FindCategoryDeclaration(CatImplClass->getIdentifier()); 90128685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek 90228685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek // If category for this implementation not found, it is an error which 90328685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek // has already been reported eralier. 90428685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek if (!Category) 9056bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 90628685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek // Look for this property declaration in @implementation's category 90728685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek property = Category->FindPropertyDeclaration(PropertyId); 90828685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek if (!property) { 90928685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek Diag(PropertyLoc, diag::error_bad_category_property_decl) 91028685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek << Category->getDeclName(); 9116bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 91228685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek } 91328685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek } else { 91428685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek Diag(AtLoc, diag::error_bad_property_context); 9156bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 91628685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek } 9176bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines ObjCIvarDecl *Ivar = nullptr; 918e4c043d3fdd0f98ab724aa4f1419cec9985ea2c4Eli Friedman bool CompleteTypeErr = false; 919744147138cd2a77320c431578da130cc3d81a1d5Fariborz Jahanian bool compat = true; 92028685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek // Check that we have a valid, previously declared ivar for @synthesize 92128685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek if (Synthesize) { 92228685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek // @synthesize 92328685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek if (!PropertyIvar) 92428685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek PropertyIvar = PropertyId; 925015f608042a1d247899866849e69a4e9a1aff6a8Fariborz Jahanian // Check that this is a previously declared 'ivar' in 'IDecl' interface 926015f608042a1d247899866849e69a4e9a1aff6a8Fariborz Jahanian ObjCInterfaceDecl *ClassDeclared; 927015f608042a1d247899866849e69a4e9a1aff6a8Fariborz Jahanian Ivar = IDecl->lookupInstanceVariable(PropertyIvar, ClassDeclared); 928265941bc308d65cc270d5c4de5806f37ce405606John McCall QualType PropType = property->getType(); 929265941bc308d65cc270d5c4de5806f37ce405606John McCall QualType PropertyIvarType = PropType.getNonReferenceType(); 930e4c043d3fdd0f98ab724aa4f1419cec9985ea2c4Eli Friedman 931e4c043d3fdd0f98ab724aa4f1419cec9985ea2c4Eli Friedman if (RequireCompleteType(PropertyDiagLoc, PropertyIvarType, 932d10099e5c8238fa0327f03921cf2e3c8975c881eDouglas Gregor diag::err_incomplete_synthesized_property, 933d10099e5c8238fa0327f03921cf2e3c8975c881eDouglas Gregor property->getDeclName())) { 934e4c043d3fdd0f98ab724aa4f1419cec9985ea2c4Eli Friedman Diag(property->getLocation(), diag::note_property_declare); 935e4c043d3fdd0f98ab724aa4f1419cec9985ea2c4Eli Friedman CompleteTypeErr = true; 936e4c043d3fdd0f98ab724aa4f1419cec9985ea2c4Eli Friedman } 937e4c043d3fdd0f98ab724aa4f1419cec9985ea2c4Eli Friedman 9384e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie if (getLangOpts().ObjCAutoRefCount && 939015f608042a1d247899866849e69a4e9a1aff6a8Fariborz Jahanian (property->getPropertyAttributesAsWritten() & 9403efd348d3586b22bb0153f17181128a1b3c41140Fariborz Jahanian ObjCPropertyDecl::OBJC_PR_readonly) && 9413efd348d3586b22bb0153f17181128a1b3c41140Fariborz Jahanian PropertyIvarType->isObjCRetainableType()) { 942015f608042a1d247899866849e69a4e9a1aff6a8Fariborz Jahanian setImpliedPropertyAttributeForReadOnlyProperty(property, Ivar); 943015f608042a1d247899866849e69a4e9a1aff6a8Fariborz Jahanian } 944015f608042a1d247899866849e69a4e9a1aff6a8Fariborz Jahanian 945015f608042a1d247899866849e69a4e9a1aff6a8Fariborz Jahanian ObjCPropertyDecl::PropertyAttributeKind kind 946015f608042a1d247899866849e69a4e9a1aff6a8Fariborz Jahanian = property->getPropertyAttributes(); 947265941bc308d65cc270d5c4de5806f37ce405606John McCall 948265941bc308d65cc270d5c4de5806f37ce405606John McCall // Add GC __weak to the ivar type if the property is weak. 949265941bc308d65cc270d5c4de5806f37ce405606John McCall if ((kind & ObjCPropertyDecl::OBJC_PR_weak) && 9504e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie getLangOpts().getGC() != LangOptions::NonGC) { 9514e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie assert(!getLangOpts().ObjCAutoRefCount); 952265941bc308d65cc270d5c4de5806f37ce405606John McCall if (PropertyIvarType.isObjCGCStrong()) { 953e4c043d3fdd0f98ab724aa4f1419cec9985ea2c4Eli Friedman Diag(PropertyDiagLoc, diag::err_gc_weak_property_strong_type); 954265941bc308d65cc270d5c4de5806f37ce405606John McCall Diag(property->getLocation(), diag::note_property_declare); 955265941bc308d65cc270d5c4de5806f37ce405606John McCall } else { 956265941bc308d65cc270d5c4de5806f37ce405606John McCall PropertyIvarType = 957265941bc308d65cc270d5c4de5806f37ce405606John McCall Context.getObjCGCQualType(PropertyIvarType, Qualifiers::Weak); 958edc08821d3f73514291b339db29aca1a17485e39Fariborz Jahanian } 959edc08821d3f73514291b339db29aca1a17485e39Fariborz Jahanian } 960e95f8ef6563bdf26de5294873733a3425c09db42Fariborz Jahanian if (AtLoc.isInvalid()) { 961e95f8ef6563bdf26de5294873733a3425c09db42Fariborz Jahanian // Check when default synthesizing a property that there is 962e95f8ef6563bdf26de5294873733a3425c09db42Fariborz Jahanian // an ivar matching property name and issue warning; since this 963e95f8ef6563bdf26de5294873733a3425c09db42Fariborz Jahanian // is the most common case of not using an ivar used for backing 964e95f8ef6563bdf26de5294873733a3425c09db42Fariborz Jahanian // property in non-default synthesis case. 9656bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines ObjCInterfaceDecl *ClassDeclared=nullptr; 966e95f8ef6563bdf26de5294873733a3425c09db42Fariborz Jahanian ObjCIvarDecl *originalIvar = 967e95f8ef6563bdf26de5294873733a3425c09db42Fariborz Jahanian IDecl->lookupInstanceVariable(property->getIdentifier(), 968e95f8ef6563bdf26de5294873733a3425c09db42Fariborz Jahanian ClassDeclared); 969e95f8ef6563bdf26de5294873733a3425c09db42Fariborz Jahanian if (originalIvar) { 970e95f8ef6563bdf26de5294873733a3425c09db42Fariborz Jahanian Diag(PropertyDiagLoc, 971e95f8ef6563bdf26de5294873733a3425c09db42Fariborz Jahanian diag::warn_autosynthesis_property_ivar_match) 9726bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines << PropertyId << (Ivar == nullptr) << PropertyIvar 97320e7d992140cc6bc94f2e65f3638346527150756Fariborz Jahanian << originalIvar->getIdentifier(); 974e95f8ef6563bdf26de5294873733a3425c09db42Fariborz Jahanian Diag(property->getLocation(), diag::note_property_declare); 975e95f8ef6563bdf26de5294873733a3425c09db42Fariborz Jahanian Diag(originalIvar->getLocation(), diag::note_ivar_decl); 976dd3284b17829adfd542ecf4a7b4423dce1d7502bFariborz Jahanian } 977e95f8ef6563bdf26de5294873733a3425c09db42Fariborz Jahanian } 978e95f8ef6563bdf26de5294873733a3425c09db42Fariborz Jahanian 979e95f8ef6563bdf26de5294873733a3425c09db42Fariborz Jahanian if (!Ivar) { 980265941bc308d65cc270d5c4de5806f37ce405606John McCall // In ARC, give the ivar a lifetime qualifier based on the 981f85e193739c953358c865005855253af4f68a497John McCall // property attributes. 9824e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie if (getLangOpts().ObjCAutoRefCount && 983265941bc308d65cc270d5c4de5806f37ce405606John McCall !PropertyIvarType.getObjCLifetime() && 984265941bc308d65cc270d5c4de5806f37ce405606John McCall PropertyIvarType->isObjCRetainableType()) { 985f85e193739c953358c865005855253af4f68a497John McCall 986265941bc308d65cc270d5c4de5806f37ce405606John McCall // It's an error if we have to do this and the user didn't 987265941bc308d65cc270d5c4de5806f37ce405606John McCall // explicitly write an ownership attribute on the property. 988473506bd9dfd84944c2c5ca2c2a38814f46febc6Argyrios Kyrtzidis if (!property->hasWrittenStorageAttribute() && 989265941bc308d65cc270d5c4de5806f37ce405606John McCall !(kind & ObjCPropertyDecl::OBJC_PR_strong)) { 990e4c043d3fdd0f98ab724aa4f1419cec9985ea2c4Eli Friedman Diag(PropertyDiagLoc, 991473506bd9dfd84944c2c5ca2c2a38814f46febc6Argyrios Kyrtzidis diag::err_arc_objc_property_default_assign_on_object); 992473506bd9dfd84944c2c5ca2c2a38814f46febc6Argyrios Kyrtzidis Diag(property->getLocation(), diag::note_property_declare); 993265941bc308d65cc270d5c4de5806f37ce405606John McCall } else { 994265941bc308d65cc270d5c4de5806f37ce405606John McCall Qualifiers::ObjCLifetime lifetime = 995265941bc308d65cc270d5c4de5806f37ce405606John McCall getImpliedARCOwnership(kind, PropertyIvarType); 996265941bc308d65cc270d5c4de5806f37ce405606John McCall assert(lifetime && "no lifetime for property?"); 9976dce88d9f71cd4be18554af94145a9147b363199Fariborz Jahanian if (lifetime == Qualifiers::OCL_Weak) { 9986dce88d9f71cd4be18554af94145a9147b363199Fariborz Jahanian bool err = false; 9996dce88d9f71cd4be18554af94145a9147b363199Fariborz Jahanian if (const ObjCObjectPointerType *ObjT = 1000a8eaf008e92759142982f7b40720b2b2674bd663Richard Smith PropertyIvarType->getAs<ObjCObjectPointerType>()) { 1001a8eaf008e92759142982f7b40720b2b2674bd663Richard Smith const ObjCInterfaceDecl *ObjI = ObjT->getInterfaceDecl(); 1002a8eaf008e92759142982f7b40720b2b2674bd663Richard Smith if (ObjI && ObjI->isArcWeakrefUnavailable()) { 100380abce3d1597edaf427f65ce15d8433f3f13315dFariborz Jahanian Diag(property->getLocation(), 100480abce3d1597edaf427f65ce15d8433f3f13315dFariborz Jahanian diag::err_arc_weak_unavailable_property) << PropertyIvarType; 100580abce3d1597edaf427f65ce15d8433f3f13315dFariborz Jahanian Diag(ClassImpDecl->getLocation(), diag::note_implemented_by_class) 100680abce3d1597edaf427f65ce15d8433f3f13315dFariborz Jahanian << ClassImpDecl->getName(); 10076dce88d9f71cd4be18554af94145a9147b363199Fariborz Jahanian err = true; 10086dce88d9f71cd4be18554af94145a9147b363199Fariborz Jahanian } 1009a8eaf008e92759142982f7b40720b2b2674bd663Richard Smith } 10100a7dd788dbef975f35f273c7ab913f480f7edd60John McCall if (!err && !getLangOpts().ObjCARCWeak) { 1011e4c043d3fdd0f98ab724aa4f1419cec9985ea2c4Eli Friedman Diag(PropertyDiagLoc, diag::err_arc_weak_no_runtime); 10126dce88d9f71cd4be18554af94145a9147b363199Fariborz Jahanian Diag(property->getLocation(), diag::note_property_declare); 10136dce88d9f71cd4be18554af94145a9147b363199Fariborz Jahanian } 1014f85e193739c953358c865005855253af4f68a497John McCall } 10156dce88d9f71cd4be18554af94145a9147b363199Fariborz Jahanian 1016f85e193739c953358c865005855253af4f68a497John McCall Qualifiers qs; 1017265941bc308d65cc270d5c4de5806f37ce405606John McCall qs.addObjCLifetime(lifetime); 1018f85e193739c953358c865005855253af4f68a497John McCall PropertyIvarType = Context.getQualifiedType(PropertyIvarType, qs); 1019f85e193739c953358c865005855253af4f68a497John McCall } 1020f85e193739c953358c865005855253af4f68a497John McCall } 1021f85e193739c953358c865005855253af4f68a497John McCall 1022f85e193739c953358c865005855253af4f68a497John McCall if (kind & ObjCPropertyDecl::OBJC_PR_weak && 10234e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie !getLangOpts().ObjCAutoRefCount && 10244e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie getLangOpts().getGC() == LangOptions::NonGC) { 1025e4c043d3fdd0f98ab724aa4f1419cec9985ea2c4Eli Friedman Diag(PropertyDiagLoc, diag::error_synthesize_weak_non_arc_or_gc); 1026f85e193739c953358c865005855253af4f68a497John McCall Diag(property->getLocation(), diag::note_property_declare); 1027f85e193739c953358c865005855253af4f68a497John McCall } 1028f85e193739c953358c865005855253af4f68a497John McCall 1029ff676cb48fe8bf7be2feaa251dc7c5fb15af4730Abramo Bagnara Ivar = ObjCIvarDecl::Create(Context, ClassImpDecl, 1030f911242f43ae1b0a85c323631fe817df95c9cbe9Argyrios Kyrtzidis PropertyIvarLoc,PropertyIvarLoc, PropertyIvar, 10316bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines PropertyIvarType, /*Dinfo=*/nullptr, 10327504966cc0d07eac26baabec80a7406695efb307Fariborz Jahanian ObjCIvarDecl::Private, 10336bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines (Expr *)nullptr, true); 10348540b6e778545008fd521b002929b89ce10506ceFariborz Jahanian if (RequireNonAbstractType(PropertyIvarLoc, 10358540b6e778545008fd521b002929b89ce10506ceFariborz Jahanian PropertyIvarType, 10368540b6e778545008fd521b002929b89ce10506ceFariborz Jahanian diag::err_abstract_type_in_decl, 10378540b6e778545008fd521b002929b89ce10506ceFariborz Jahanian AbstractSynthesizedIvarType)) { 10388540b6e778545008fd521b002929b89ce10506ceFariborz Jahanian Diag(property->getLocation(), diag::note_property_declare); 1039e4c043d3fdd0f98ab724aa4f1419cec9985ea2c4Eli Friedman Ivar->setInvalidDecl(); 10408540b6e778545008fd521b002929b89ce10506ceFariborz Jahanian } else if (CompleteTypeErr) 10418540b6e778545008fd521b002929b89ce10506ceFariborz Jahanian Ivar->setInvalidDecl(); 104229fa69addf8b19871e7866c32c92b5d142c4bfbcDaniel Dunbar ClassImpDecl->addDecl(Ivar); 10431b7f9cbed1b96b58a6e5f7808ebc9345a76a0936Richard Smith IDecl->makeDeclVisibleInContext(Ivar); 104428685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek 1045260611a32535c851237926bfcf78869b13c07d5bJohn McCall if (getLangOpts().ObjCRuntime.isFragile()) 1046e4c043d3fdd0f98ab724aa4f1419cec9985ea2c4Eli Friedman Diag(PropertyDiagLoc, diag::error_missing_property_ivar_decl) 1047e4c043d3fdd0f98ab724aa4f1419cec9985ea2c4Eli Friedman << PropertyId; 104828685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek // Note! I deliberately want it to fall thru so, we have a 104928685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek // a property implementation and to avoid future warnings. 1050260611a32535c851237926bfcf78869b13c07d5bJohn McCall } else if (getLangOpts().ObjCRuntime.isNonFragile() && 105160ef308e51c71b760d7f598c1b763ceb7b768148Douglas Gregor !declaresSameEntity(ClassDeclared, IDecl)) { 1052e4c043d3fdd0f98ab724aa4f1419cec9985ea2c4Eli Friedman Diag(PropertyDiagLoc, diag::error_ivar_in_superclass_use) 105328685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek << property->getDeclName() << Ivar->getDeclName() 105428685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek << ClassDeclared->getDeclName(); 105528685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek Diag(Ivar->getLocation(), diag::note_previous_access_declaration) 10564087f27e5416c799bcb6be072f905be752acb61cDaniel Dunbar << Ivar << Ivar->getName(); 105728685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek // Note! I deliberately want it to fall thru so more errors are caught. 105828685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek } 10595bf5c2ec54ede5352293e5739e9b44bea2f6b01bAnna Zaks property->setPropertyIvarDecl(Ivar); 10605bf5c2ec54ede5352293e5739e9b44bea2f6b01bAnna Zaks 106128685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek QualType IvarType = Context.getCanonicalType(Ivar->getType()); 106228685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek 106328685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek // Check that type of property and its ivar are type compatible. 1064744147138cd2a77320c431578da130cc3d81a1d5Fariborz Jahanian if (!Context.hasSameType(PropertyIvarType, IvarType)) { 106514086764e340267e17803d0f8243070ffae2c76eFariborz Jahanian if (isa<ObjCObjectPointerType>(PropertyIvarType) 1066f85e193739c953358c865005855253af4f68a497John McCall && isa<ObjCObjectPointerType>(IvarType)) 1067b3cd3c0c8a234803dcb9b9c0dfe10106674141cdRichard Smith compat = 106862ac5d01aade35790a6d8e814edb21062da5d3f7Fariborz Jahanian Context.canAssignObjCInterfaces( 106914086764e340267e17803d0f8243070ffae2c76eFariborz Jahanian PropertyIvarType->getAs<ObjCObjectPointerType>(), 107062ac5d01aade35790a6d8e814edb21062da5d3f7Fariborz Jahanian IvarType->getAs<ObjCObjectPointerType>()); 1071b608b987718c6d841115464f79ab2d1820a63e17Douglas Gregor else { 1072f911242f43ae1b0a85c323631fe817df95c9cbe9Argyrios Kyrtzidis compat = (CheckAssignmentConstraints(PropertyIvarLoc, PropertyIvarType, 1073f911242f43ae1b0a85c323631fe817df95c9cbe9Argyrios Kyrtzidis IvarType) 1074daa8e4e888758d55a7a759dd4a91b83921cef222John McCall == Compatible); 1075b608b987718c6d841115464f79ab2d1820a63e17Douglas Gregor } 107662ac5d01aade35790a6d8e814edb21062da5d3f7Fariborz Jahanian if (!compat) { 1077e4c043d3fdd0f98ab724aa4f1419cec9985ea2c4Eli Friedman Diag(PropertyDiagLoc, diag::error_property_ivar_type) 1078f921a4868cf1876636f6684e7f68697b18c0cb47Ted Kremenek << property->getDeclName() << PropType 1079f921a4868cf1876636f6684e7f68697b18c0cb47Ted Kremenek << Ivar->getDeclName() << IvarType; 1080f921a4868cf1876636f6684e7f68697b18c0cb47Ted Kremenek Diag(Ivar->getLocation(), diag::note_ivar_decl); 108128685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek // Note! I deliberately want it to fall thru so, we have a 108228685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek // a property implementation and to avoid future warnings. 108328685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek } 1084744147138cd2a77320c431578da130cc3d81a1d5Fariborz Jahanian else { 1085744147138cd2a77320c431578da130cc3d81a1d5Fariborz Jahanian // FIXME! Rules for properties are somewhat different that those 1086744147138cd2a77320c431578da130cc3d81a1d5Fariborz Jahanian // for assignments. Use a new routine to consolidate all cases; 1087744147138cd2a77320c431578da130cc3d81a1d5Fariborz Jahanian // specifically for property redeclarations as well as for ivars. 1088744147138cd2a77320c431578da130cc3d81a1d5Fariborz Jahanian QualType lhsType =Context.getCanonicalType(PropertyIvarType).getUnqualifiedType(); 1089744147138cd2a77320c431578da130cc3d81a1d5Fariborz Jahanian QualType rhsType =Context.getCanonicalType(IvarType).getUnqualifiedType(); 1090744147138cd2a77320c431578da130cc3d81a1d5Fariborz Jahanian if (lhsType != rhsType && 1091744147138cd2a77320c431578da130cc3d81a1d5Fariborz Jahanian lhsType->isArithmeticType()) { 1092744147138cd2a77320c431578da130cc3d81a1d5Fariborz Jahanian Diag(PropertyDiagLoc, diag::error_property_ivar_type) 1093744147138cd2a77320c431578da130cc3d81a1d5Fariborz Jahanian << property->getDeclName() << PropType 1094744147138cd2a77320c431578da130cc3d81a1d5Fariborz Jahanian << Ivar->getDeclName() << IvarType; 1095744147138cd2a77320c431578da130cc3d81a1d5Fariborz Jahanian Diag(Ivar->getLocation(), diag::note_ivar_decl); 1096744147138cd2a77320c431578da130cc3d81a1d5Fariborz Jahanian // Fall thru - see previous comment 1097744147138cd2a77320c431578da130cc3d81a1d5Fariborz Jahanian } 109828685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek } 109928685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek // __weak is explicit. So it works on Canonical type. 1100f85e193739c953358c865005855253af4f68a497John McCall if ((PropType.isObjCGCWeak() && !IvarType.isObjCGCWeak() && 11014e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie getLangOpts().getGC() != LangOptions::NonGC)) { 1102e4c043d3fdd0f98ab724aa4f1419cec9985ea2c4Eli Friedman Diag(PropertyDiagLoc, diag::error_weak_property) 110328685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek << property->getDeclName() << Ivar->getDeclName(); 1104edc08821d3f73514291b339db29aca1a17485e39Fariborz Jahanian Diag(Ivar->getLocation(), diag::note_ivar_decl); 110528685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek // Fall thru - see previous comment 110628685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek } 1107f85e193739c953358c865005855253af4f68a497John McCall // Fall thru - see previous comment 110828685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek if ((property->getType()->isObjCObjectPointerType() || 110928685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek PropType.isObjCGCStrong()) && IvarType.isObjCGCWeak() && 11104e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie getLangOpts().getGC() != LangOptions::NonGC) { 1111e4c043d3fdd0f98ab724aa4f1419cec9985ea2c4Eli Friedman Diag(PropertyDiagLoc, diag::error_strong_property) 111228685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek << property->getDeclName() << Ivar->getDeclName(); 111328685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek // Fall thru - see previous comment 111428685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek } 111528685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek } 11164e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie if (getLangOpts().ObjCAutoRefCount) 1117f85e193739c953358c865005855253af4f68a497John McCall checkARCPropertyImpl(*this, PropertyLoc, property, Ivar); 111828685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek } else if (PropertyIvar) 111928685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek // @dynamic 1120e4c043d3fdd0f98ab724aa4f1419cec9985ea2c4Eli Friedman Diag(PropertyDiagLoc, diag::error_dynamic_property_ivar_decl); 1121f85e193739c953358c865005855253af4f68a497John McCall 112228685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek assert (property && "ActOnPropertyImplDecl - property declaration missing"); 112328685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek ObjCPropertyImplDecl *PIDecl = 112428685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek ObjCPropertyImplDecl::Create(Context, CurContext, AtLoc, PropertyLoc, 112528685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek property, 112628685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek (Synthesize ? 112728685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek ObjCPropertyImplDecl::Synthesize 112828685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek : ObjCPropertyImplDecl::Dynamic), 1129a4ffd85a6684e42f900aad5459e58ad91bb88755Douglas Gregor Ivar, PropertyIvarLoc); 1130e4c043d3fdd0f98ab724aa4f1419cec9985ea2c4Eli Friedman 1131744147138cd2a77320c431578da130cc3d81a1d5Fariborz Jahanian if (CompleteTypeErr || !compat) 1132e4c043d3fdd0f98ab724aa4f1419cec9985ea2c4Eli Friedman PIDecl->setInvalidDecl(); 1133e4c043d3fdd0f98ab724aa4f1419cec9985ea2c4Eli Friedman 113417cb326cb62a59f53d92236394af40eaae4eddbdFariborz Jahanian if (ObjCMethodDecl *getterMethod = property->getGetterMethodDecl()) { 113517cb326cb62a59f53d92236394af40eaae4eddbdFariborz Jahanian getterMethod->createImplicitParams(Context, IDecl); 1136e4c043d3fdd0f98ab724aa4f1419cec9985ea2c4Eli Friedman if (getLangOpts().CPlusPlus && Synthesize && !CompleteTypeErr && 11370313f441b72ef6b69a93e5003c684b01cb72fd46Fariborz Jahanian Ivar->getType()->isRecordType()) { 113817cb326cb62a59f53d92236394af40eaae4eddbdFariborz Jahanian // For Objective-C++, need to synthesize the AST for the IVAR object to be 113917cb326cb62a59f53d92236394af40eaae4eddbdFariborz Jahanian // returned by the getter as it must conform to C++'s copy-return rules. 114017cb326cb62a59f53d92236394af40eaae4eddbdFariborz Jahanian // FIXME. Eventually we want to do this for Objective-C as well. 11419a14db3fefa73ef8a702dea1928fd0ee0befe59bEli Friedman SynthesizedFunctionScope Scope(*this, getterMethod); 114217cb326cb62a59f53d92236394af40eaae4eddbdFariborz Jahanian ImplicitParamDecl *SelfDecl = getterMethod->getSelfDecl(); 114317cb326cb62a59f53d92236394af40eaae4eddbdFariborz Jahanian DeclRefExpr *SelfExpr = 1144f4b88a45902af1802a1cb42ba48b1c474474f228John McCall new (Context) DeclRefExpr(SelfDecl, false, SelfDecl->getType(), 1145651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines VK_LValue, PropertyDiagLoc); 11469a14db3fefa73ef8a702dea1928fd0ee0befe59bEli Friedman MarkDeclRefReferenced(SelfExpr); 1147651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Expr *LoadSelfExpr = 1148651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ImplicitCastExpr::Create(Context, SelfDecl->getType(), 11496bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines CK_LValueToRValue, SelfExpr, nullptr, 11506bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines VK_RValue); 115117cb326cb62a59f53d92236394af40eaae4eddbdFariborz Jahanian Expr *IvarRefExpr = 11529a14db3fefa73ef8a702dea1928fd0ee0befe59bEli Friedman new (Context) ObjCIvarRefExpr(Ivar, Ivar->getType(), PropertyDiagLoc, 11530c70181854a95fca0e0d56dfa1203eb2216052eaFariborz Jahanian Ivar->getLocation(), 1154651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines LoadSelfExpr, true, true); 1155651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ExprResult Res = PerformCopyInitialization( 1156651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines InitializedEntity::InitializeResult(PropertyDiagLoc, 1157651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines getterMethod->getReturnType(), 1158651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines /*NRVO=*/false), 1159ef8225444452a1486bd721f3285301fe84643b00Stephen Hines PropertyDiagLoc, IvarRefExpr); 116017cb326cb62a59f53d92236394af40eaae4eddbdFariborz Jahanian if (!Res.isInvalid()) { 1161ef8225444452a1486bd721f3285301fe84643b00Stephen Hines Expr *ResExpr = Res.getAs<Expr>(); 116217cb326cb62a59f53d92236394af40eaae4eddbdFariborz Jahanian if (ResExpr) 11634765fa05b5652fcc4356371c2f481d0ea9a1b007John McCall ResExpr = MaybeCreateExprWithCleanups(ResExpr); 116417cb326cb62a59f53d92236394af40eaae4eddbdFariborz Jahanian PIDecl->setGetterCXXConstructor(ResExpr); 116517cb326cb62a59f53d92236394af40eaae4eddbdFariborz Jahanian } 116617cb326cb62a59f53d92236394af40eaae4eddbdFariborz Jahanian } 1167831fb9622581fc3b777848e6b097a0cb23d124deFariborz Jahanian if (property->hasAttr<NSReturnsNotRetainedAttr>() && 1168831fb9622581fc3b777848e6b097a0cb23d124deFariborz Jahanian !getterMethod->hasAttr<NSReturnsNotRetainedAttr>()) { 1169831fb9622581fc3b777848e6b097a0cb23d124deFariborz Jahanian Diag(getterMethod->getLocation(), 1170831fb9622581fc3b777848e6b097a0cb23d124deFariborz Jahanian diag::warn_property_getter_owning_mismatch); 1171831fb9622581fc3b777848e6b097a0cb23d124deFariborz Jahanian Diag(property->getLocation(), diag::note_property_declare); 1172831fb9622581fc3b777848e6b097a0cb23d124deFariborz Jahanian } 1173b8ed071b88c1fd100eaa701f5fd7f5ebe8b9e362Fariborz Jahanian if (getLangOpts().ObjCAutoRefCount && Synthesize) 1174b8ed071b88c1fd100eaa701f5fd7f5ebe8b9e362Fariborz Jahanian switch (getterMethod->getMethodFamily()) { 1175b8ed071b88c1fd100eaa701f5fd7f5ebe8b9e362Fariborz Jahanian case OMF_retain: 1176b8ed071b88c1fd100eaa701f5fd7f5ebe8b9e362Fariborz Jahanian case OMF_retainCount: 1177b8ed071b88c1fd100eaa701f5fd7f5ebe8b9e362Fariborz Jahanian case OMF_release: 1178b8ed071b88c1fd100eaa701f5fd7f5ebe8b9e362Fariborz Jahanian case OMF_autorelease: 1179b8ed071b88c1fd100eaa701f5fd7f5ebe8b9e362Fariborz Jahanian Diag(getterMethod->getLocation(), diag::err_arc_illegal_method_def) 1180b8ed071b88c1fd100eaa701f5fd7f5ebe8b9e362Fariborz Jahanian << 1 << getterMethod->getSelector(); 1181b8ed071b88c1fd100eaa701f5fd7f5ebe8b9e362Fariborz Jahanian break; 1182b8ed071b88c1fd100eaa701f5fd7f5ebe8b9e362Fariborz Jahanian default: 1183b8ed071b88c1fd100eaa701f5fd7f5ebe8b9e362Fariborz Jahanian break; 1184b8ed071b88c1fd100eaa701f5fd7f5ebe8b9e362Fariborz Jahanian } 118517cb326cb62a59f53d92236394af40eaae4eddbdFariborz Jahanian } 118617cb326cb62a59f53d92236394af40eaae4eddbdFariborz Jahanian if (ObjCMethodDecl *setterMethod = property->getSetterMethodDecl()) { 118717cb326cb62a59f53d92236394af40eaae4eddbdFariborz Jahanian setterMethod->createImplicitParams(Context, IDecl); 1188e4c043d3fdd0f98ab724aa4f1419cec9985ea2c4Eli Friedman if (getLangOpts().CPlusPlus && Synthesize && !CompleteTypeErr && 1189e4c043d3fdd0f98ab724aa4f1419cec9985ea2c4Eli Friedman Ivar->getType()->isRecordType()) { 119017cb326cb62a59f53d92236394af40eaae4eddbdFariborz Jahanian // FIXME. Eventually we want to do this for Objective-C as well. 11919a14db3fefa73ef8a702dea1928fd0ee0befe59bEli Friedman SynthesizedFunctionScope Scope(*this, setterMethod); 119217cb326cb62a59f53d92236394af40eaae4eddbdFariborz Jahanian ImplicitParamDecl *SelfDecl = setterMethod->getSelfDecl(); 119317cb326cb62a59f53d92236394af40eaae4eddbdFariborz Jahanian DeclRefExpr *SelfExpr = 1194f4b88a45902af1802a1cb42ba48b1c474474f228John McCall new (Context) DeclRefExpr(SelfDecl, false, SelfDecl->getType(), 1195651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines VK_LValue, PropertyDiagLoc); 11969a14db3fefa73ef8a702dea1928fd0ee0befe59bEli Friedman MarkDeclRefReferenced(SelfExpr); 1197651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Expr *LoadSelfExpr = 1198651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ImplicitCastExpr::Create(Context, SelfDecl->getType(), 11996bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines CK_LValueToRValue, SelfExpr, nullptr, 12006bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines VK_RValue); 120117cb326cb62a59f53d92236394af40eaae4eddbdFariborz Jahanian Expr *lhs = 12029a14db3fefa73ef8a702dea1928fd0ee0befe59bEli Friedman new (Context) ObjCIvarRefExpr(Ivar, Ivar->getType(), PropertyDiagLoc, 12030c70181854a95fca0e0d56dfa1203eb2216052eaFariborz Jahanian Ivar->getLocation(), 1204651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines LoadSelfExpr, true, true); 120517cb326cb62a59f53d92236394af40eaae4eddbdFariborz Jahanian ObjCMethodDecl::param_iterator P = setterMethod->param_begin(); 120617cb326cb62a59f53d92236394af40eaae4eddbdFariborz Jahanian ParmVarDecl *Param = (*P); 12073c3b7f90a863af43fa63043d396553ecf205351cJohn McCall QualType T = Param->getType().getNonReferenceType(); 12089a14db3fefa73ef8a702dea1928fd0ee0befe59bEli Friedman DeclRefExpr *rhs = new (Context) DeclRefExpr(Param, false, T, 12099a14db3fefa73ef8a702dea1928fd0ee0befe59bEli Friedman VK_LValue, PropertyDiagLoc); 12109a14db3fefa73ef8a702dea1928fd0ee0befe59bEli Friedman MarkDeclRefReferenced(rhs); 12119a14db3fefa73ef8a702dea1928fd0ee0befe59bEli Friedman ExprResult Res = BuildBinOp(S, PropertyDiagLoc, 12122de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall BO_Assign, lhs, rhs); 121357e264e9f4ff0a72f3585a960cdf63437b76fa93Fariborz Jahanian if (property->getPropertyAttributes() & 121457e264e9f4ff0a72f3585a960cdf63437b76fa93Fariborz Jahanian ObjCPropertyDecl::OBJC_PR_atomic) { 1215ef8225444452a1486bd721f3285301fe84643b00Stephen Hines Expr *callExpr = Res.getAs<Expr>(); 121657e264e9f4ff0a72f3585a960cdf63437b76fa93Fariborz Jahanian if (const CXXOperatorCallExpr *CXXCE = 121713bf6336ab395eb6af487ab96d32229460907769Fariborz Jahanian dyn_cast_or_null<CXXOperatorCallExpr>(callExpr)) 121813bf6336ab395eb6af487ab96d32229460907769Fariborz Jahanian if (const FunctionDecl *FuncDecl = CXXCE->getDirectCallee()) 121957e264e9f4ff0a72f3585a960cdf63437b76fa93Fariborz Jahanian if (!FuncDecl->isTrivial()) 122020abee6b95c4f5a61e471b4b616439280ca4a81bFariborz Jahanian if (property->getType()->isReferenceType()) { 12219a14db3fefa73ef8a702dea1928fd0ee0befe59bEli Friedman Diag(PropertyDiagLoc, 122220abee6b95c4f5a61e471b4b616439280ca4a81bFariborz Jahanian diag::err_atomic_property_nontrivial_assign_op) 122357e264e9f4ff0a72f3585a960cdf63437b76fa93Fariborz Jahanian << property->getType(); 122420abee6b95c4f5a61e471b4b616439280ca4a81bFariborz Jahanian Diag(FuncDecl->getLocStart(), 122520abee6b95c4f5a61e471b4b616439280ca4a81bFariborz Jahanian diag::note_callee_decl) << FuncDecl; 122620abee6b95c4f5a61e471b4b616439280ca4a81bFariborz Jahanian } 122757e264e9f4ff0a72f3585a960cdf63437b76fa93Fariborz Jahanian } 1228ef8225444452a1486bd721f3285301fe84643b00Stephen Hines PIDecl->setSetterCXXAssignment(Res.getAs<Expr>()); 122917cb326cb62a59f53d92236394af40eaae4eddbdFariborz Jahanian } 123017cb326cb62a59f53d92236394af40eaae4eddbdFariborz Jahanian } 123117cb326cb62a59f53d92236394af40eaae4eddbdFariborz Jahanian 123228685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek if (IC) { 123328685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek if (Synthesize) 123428685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek if (ObjCPropertyImplDecl *PPIDecl = 123528685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek IC->FindPropertyImplIvarDecl(PropertyIvar)) { 123628685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek Diag(PropertyLoc, diag::error_duplicate_ivar_use) 123728685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek << PropertyId << PPIDecl->getPropertyDecl()->getIdentifier() 123828685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek << PropertyIvar; 123928685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek Diag(PPIDecl->getLocation(), diag::note_previous_use); 124028685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek } 124128685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek 124228685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek if (ObjCPropertyImplDecl *PPIDecl 124328685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek = IC->FindPropertyImplDecl(PropertyId)) { 124428685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek Diag(PropertyLoc, diag::error_property_implemented) << PropertyId; 124528685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek Diag(PPIDecl->getLocation(), diag::note_previous_declaration); 12466bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 124728685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek } 124828685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek IC->addPropertyImplementation(PIDecl); 12494e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie if (getLangOpts().ObjCDefaultSynthProperties && 1250260611a32535c851237926bfcf78869b13c07d5bJohn McCall getLangOpts().ObjCRuntime.isNonFragile() && 125171207fc0470e1eee40a2951cd5cc3ff47725b755Ted Kremenek !IDecl->isObjCRequiresPropertyDefs()) { 1252ad51e74030a59a8aa4ef0ebca1d7a701602ef53bFariborz Jahanian // Diagnose if an ivar was lazily synthesdized due to a previous 1253ad51e74030a59a8aa4ef0ebca1d7a701602ef53bFariborz Jahanian // use and if 1) property is @dynamic or 2) property is synthesized 1254cdaa6a8fed16d8bd3987fb4f3304dfb4e52876c3Fariborz Jahanian // but it requires an ivar of different name. 12556bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines ObjCInterfaceDecl *ClassDeclared=nullptr; 12566bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines ObjCIvarDecl *Ivar = nullptr; 1257ad51e74030a59a8aa4ef0ebca1d7a701602ef53bFariborz Jahanian if (!Synthesize) 1258ad51e74030a59a8aa4ef0ebca1d7a701602ef53bFariborz Jahanian Ivar = IDecl->lookupInstanceVariable(PropertyId, ClassDeclared); 1259ad51e74030a59a8aa4ef0ebca1d7a701602ef53bFariborz Jahanian else { 1260ad51e74030a59a8aa4ef0ebca1d7a701602ef53bFariborz Jahanian if (PropertyIvar && PropertyIvar != PropertyId) 1261ad51e74030a59a8aa4ef0ebca1d7a701602ef53bFariborz Jahanian Ivar = IDecl->lookupInstanceVariable(PropertyId, ClassDeclared); 1262ad51e74030a59a8aa4ef0ebca1d7a701602ef53bFariborz Jahanian } 1263cdaa6a8fed16d8bd3987fb4f3304dfb4e52876c3Fariborz Jahanian // Issue diagnostics only if Ivar belongs to current class. 1264cdaa6a8fed16d8bd3987fb4f3304dfb4e52876c3Fariborz Jahanian if (Ivar && Ivar->getSynthesize() && 126560ef308e51c71b760d7f598c1b763ceb7b768148Douglas Gregor declaresSameEntity(IC->getClassInterface(), ClassDeclared)) { 1266ad51e74030a59a8aa4ef0ebca1d7a701602ef53bFariborz Jahanian Diag(Ivar->getLocation(), diag::err_undeclared_var_use) 1267ad51e74030a59a8aa4ef0ebca1d7a701602ef53bFariborz Jahanian << PropertyId; 1268ad51e74030a59a8aa4ef0ebca1d7a701602ef53bFariborz Jahanian Ivar->setInvalidDecl(); 1269ad51e74030a59a8aa4ef0ebca1d7a701602ef53bFariborz Jahanian } 1270ad51e74030a59a8aa4ef0ebca1d7a701602ef53bFariborz Jahanian } 127128685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek } else { 127228685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek if (Synthesize) 127328685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek if (ObjCPropertyImplDecl *PPIDecl = 127428685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek CatImplClass->FindPropertyImplIvarDecl(PropertyIvar)) { 1275e4c043d3fdd0f98ab724aa4f1419cec9985ea2c4Eli Friedman Diag(PropertyDiagLoc, diag::error_duplicate_ivar_use) 127628685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek << PropertyId << PPIDecl->getPropertyDecl()->getIdentifier() 127728685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek << PropertyIvar; 127828685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek Diag(PPIDecl->getLocation(), diag::note_previous_use); 127928685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek } 128028685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek 128128685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek if (ObjCPropertyImplDecl *PPIDecl = 128228685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek CatImplClass->FindPropertyImplDecl(PropertyId)) { 1283e4c043d3fdd0f98ab724aa4f1419cec9985ea2c4Eli Friedman Diag(PropertyDiagLoc, diag::error_property_implemented) << PropertyId; 128428685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek Diag(PPIDecl->getLocation(), diag::note_previous_declaration); 12856bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 128628685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek } 128728685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek CatImplClass->addPropertyImplementation(PIDecl); 128828685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek } 128928685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek 1290d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall return PIDecl; 129128685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek} 129228685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek 129328685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek//===----------------------------------------------------------------------===// 129428685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek// Helper methods. 129528685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek//===----------------------------------------------------------------------===// 129628685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek 12979d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek/// DiagnosePropertyMismatch - Compares two properties for their 12989d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek/// attributes and types and warns on a variety of inconsistencies. 12999d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek/// 13009d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenekvoid 13019d64c15223497f31899cc47fbe1531873dc06f2eTed KremenekSema::DiagnosePropertyMismatch(ObjCPropertyDecl *Property, 13029d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek ObjCPropertyDecl *SuperProperty, 13031cd6fab3930d5c058c201895654c6b0bd6ecb8c1Fariborz Jahanian const IdentifierInfo *inheritedName, 13041cd6fab3930d5c058c201895654c6b0bd6ecb8c1Fariborz Jahanian bool OverridingProtocolProperty) { 13059d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek ObjCPropertyDecl::PropertyAttributeKind CAttr = 13061cd6fab3930d5c058c201895654c6b0bd6ecb8c1Fariborz Jahanian Property->getPropertyAttributes(); 13079d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek ObjCPropertyDecl::PropertyAttributeKind SAttr = 13081cd6fab3930d5c058c201895654c6b0bd6ecb8c1Fariborz Jahanian SuperProperty->getPropertyAttributes(); 13091cd6fab3930d5c058c201895654c6b0bd6ecb8c1Fariborz Jahanian 13101cd6fab3930d5c058c201895654c6b0bd6ecb8c1Fariborz Jahanian // We allow readonly properties without an explicit ownership 13111cd6fab3930d5c058c201895654c6b0bd6ecb8c1Fariborz Jahanian // (assign/unsafe_unretained/weak/retain/strong/copy) in super class 13121cd6fab3930d5c058c201895654c6b0bd6ecb8c1Fariborz Jahanian // to be overridden by a property with any explicit ownership in the subclass. 13131cd6fab3930d5c058c201895654c6b0bd6ecb8c1Fariborz Jahanian if (!OverridingProtocolProperty && 13141cd6fab3930d5c058c201895654c6b0bd6ecb8c1Fariborz Jahanian !getOwnershipRule(SAttr) && getOwnershipRule(CAttr)) 13151cd6fab3930d5c058c201895654c6b0bd6ecb8c1Fariborz Jahanian ; 13161cd6fab3930d5c058c201895654c6b0bd6ecb8c1Fariborz Jahanian else { 13171cd6fab3930d5c058c201895654c6b0bd6ecb8c1Fariborz Jahanian if ((CAttr & ObjCPropertyDecl::OBJC_PR_readonly) 13181cd6fab3930d5c058c201895654c6b0bd6ecb8c1Fariborz Jahanian && (SAttr & ObjCPropertyDecl::OBJC_PR_readwrite)) 13191cd6fab3930d5c058c201895654c6b0bd6ecb8c1Fariborz Jahanian Diag(Property->getLocation(), diag::warn_readonly_property) 13201cd6fab3930d5c058c201895654c6b0bd6ecb8c1Fariborz Jahanian << Property->getDeclName() << inheritedName; 13211cd6fab3930d5c058c201895654c6b0bd6ecb8c1Fariborz Jahanian if ((CAttr & ObjCPropertyDecl::OBJC_PR_copy) 13221cd6fab3930d5c058c201895654c6b0bd6ecb8c1Fariborz Jahanian != (SAttr & ObjCPropertyDecl::OBJC_PR_copy)) 1323f85e193739c953358c865005855253af4f68a497John McCall Diag(Property->getLocation(), diag::warn_property_attribute) 13241cd6fab3930d5c058c201895654c6b0bd6ecb8c1Fariborz Jahanian << Property->getDeclName() << "copy" << inheritedName; 13251cd6fab3930d5c058c201895654c6b0bd6ecb8c1Fariborz Jahanian else if (!(SAttr & ObjCPropertyDecl::OBJC_PR_readonly)){ 13261cd6fab3930d5c058c201895654c6b0bd6ecb8c1Fariborz Jahanian unsigned CAttrRetain = 13271cd6fab3930d5c058c201895654c6b0bd6ecb8c1Fariborz Jahanian (CAttr & 13281cd6fab3930d5c058c201895654c6b0bd6ecb8c1Fariborz Jahanian (ObjCPropertyDecl::OBJC_PR_retain | ObjCPropertyDecl::OBJC_PR_strong)); 13291cd6fab3930d5c058c201895654c6b0bd6ecb8c1Fariborz Jahanian unsigned SAttrRetain = 13301cd6fab3930d5c058c201895654c6b0bd6ecb8c1Fariborz Jahanian (SAttr & 13311cd6fab3930d5c058c201895654c6b0bd6ecb8c1Fariborz Jahanian (ObjCPropertyDecl::OBJC_PR_retain | ObjCPropertyDecl::OBJC_PR_strong)); 13321cd6fab3930d5c058c201895654c6b0bd6ecb8c1Fariborz Jahanian bool CStrong = (CAttrRetain != 0); 13331cd6fab3930d5c058c201895654c6b0bd6ecb8c1Fariborz Jahanian bool SStrong = (SAttrRetain != 0); 13341cd6fab3930d5c058c201895654c6b0bd6ecb8c1Fariborz Jahanian if (CStrong != SStrong) 13351cd6fab3930d5c058c201895654c6b0bd6ecb8c1Fariborz Jahanian Diag(Property->getLocation(), diag::warn_property_attribute) 13361cd6fab3930d5c058c201895654c6b0bd6ecb8c1Fariborz Jahanian << Property->getDeclName() << "retain (or strong)" << inheritedName; 13371cd6fab3930d5c058c201895654c6b0bd6ecb8c1Fariborz Jahanian } 1338f85e193739c953358c865005855253af4f68a497John McCall } 13399d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek 13409d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek if ((CAttr & ObjCPropertyDecl::OBJC_PR_nonatomic) 1341b7b25659355d736a4f19099d96acc54d672340a5Fariborz Jahanian != (SAttr & ObjCPropertyDecl::OBJC_PR_nonatomic)) { 13429d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek Diag(Property->getLocation(), diag::warn_property_attribute) 13439d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek << Property->getDeclName() << "atomic" << inheritedName; 1344b7b25659355d736a4f19099d96acc54d672340a5Fariborz Jahanian Diag(SuperProperty->getLocation(), diag::note_property_declare); 1345b7b25659355d736a4f19099d96acc54d672340a5Fariborz Jahanian } 1346b7b25659355d736a4f19099d96acc54d672340a5Fariborz Jahanian if (Property->getSetterName() != SuperProperty->getSetterName()) { 13479d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek Diag(Property->getLocation(), diag::warn_property_attribute) 13489d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek << Property->getDeclName() << "setter" << inheritedName; 1349b7b25659355d736a4f19099d96acc54d672340a5Fariborz Jahanian Diag(SuperProperty->getLocation(), diag::note_property_declare); 1350b7b25659355d736a4f19099d96acc54d672340a5Fariborz Jahanian } 1351b7b25659355d736a4f19099d96acc54d672340a5Fariborz Jahanian if (Property->getGetterName() != SuperProperty->getGetterName()) { 13529d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek Diag(Property->getLocation(), diag::warn_property_attribute) 13539d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek << Property->getDeclName() << "getter" << inheritedName; 1354b7b25659355d736a4f19099d96acc54d672340a5Fariborz Jahanian Diag(SuperProperty->getLocation(), diag::note_property_declare); 1355b7b25659355d736a4f19099d96acc54d672340a5Fariborz Jahanian } 13569d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek 13579d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek QualType LHSType = 13589d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek Context.getCanonicalType(SuperProperty->getType()); 13599d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek QualType RHSType = 13609d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek Context.getCanonicalType(Property->getType()); 13619d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek 1362c286f3835eb6001c61664cef5d610dfaf80a6e9bFariborz Jahanian if (!Context.propertyTypesAreCompatible(LHSType, RHSType)) { 13638beb6a2426b5a6b79ecf019316d9fbd30755e087Fariborz Jahanian // Do cases not handled in above. 13648beb6a2426b5a6b79ecf019316d9fbd30755e087Fariborz Jahanian // FIXME. For future support of covariant property types, revisit this. 13658beb6a2426b5a6b79ecf019316d9fbd30755e087Fariborz Jahanian bool IncompatibleObjC = false; 13668beb6a2426b5a6b79ecf019316d9fbd30755e087Fariborz Jahanian QualType ConvertedType; 13678beb6a2426b5a6b79ecf019316d9fbd30755e087Fariborz Jahanian if (!isObjCPointerConversion(RHSType, LHSType, 13688beb6a2426b5a6b79ecf019316d9fbd30755e087Fariborz Jahanian ConvertedType, IncompatibleObjC) || 136913546a871db44c707001f507a9edfd0d5bcc81b4Fariborz Jahanian IncompatibleObjC) { 13708beb6a2426b5a6b79ecf019316d9fbd30755e087Fariborz Jahanian Diag(Property->getLocation(), diag::warn_property_types_are_incompatible) 13718beb6a2426b5a6b79ecf019316d9fbd30755e087Fariborz Jahanian << Property->getType() << SuperProperty->getType() << inheritedName; 137213546a871db44c707001f507a9edfd0d5bcc81b4Fariborz Jahanian Diag(SuperProperty->getLocation(), diag::note_property_declare); 137313546a871db44c707001f507a9edfd0d5bcc81b4Fariborz Jahanian } 13749d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek } 13759d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek} 13769d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek 13779d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenekbool Sema::DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *property, 13789d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek ObjCMethodDecl *GetterMethod, 13799d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek SourceLocation Loc) { 13809abf88c9286d7465ce18285f87bb302f588b59fcFariborz Jahanian if (!GetterMethod) 13819abf88c9286d7465ce18285f87bb302f588b59fcFariborz Jahanian return false; 1382651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines QualType GetterType = GetterMethod->getReturnType().getNonReferenceType(); 13839abf88c9286d7465ce18285f87bb302f588b59fcFariborz Jahanian QualType PropertyIvarType = property->getType().getNonReferenceType(); 13849abf88c9286d7465ce18285f87bb302f588b59fcFariborz Jahanian bool compat = Context.hasSameType(PropertyIvarType, GetterType); 13859abf88c9286d7465ce18285f87bb302f588b59fcFariborz Jahanian if (!compat) { 13869abf88c9286d7465ce18285f87bb302f588b59fcFariborz Jahanian if (isa<ObjCObjectPointerType>(PropertyIvarType) && 13879abf88c9286d7465ce18285f87bb302f588b59fcFariborz Jahanian isa<ObjCObjectPointerType>(GetterType)) 13889abf88c9286d7465ce18285f87bb302f588b59fcFariborz Jahanian compat = 13899abf88c9286d7465ce18285f87bb302f588b59fcFariborz Jahanian Context.canAssignObjCInterfaces( 1390490a52b4947381879a47b4251db5fb81cdf5d02bFariborz Jahanian GetterType->getAs<ObjCObjectPointerType>(), 1391490a52b4947381879a47b4251db5fb81cdf5d02bFariborz Jahanian PropertyIvarType->getAs<ObjCObjectPointerType>()); 1392490a52b4947381879a47b4251db5fb81cdf5d02bFariborz Jahanian else if (CheckAssignmentConstraints(Loc, GetterType, PropertyIvarType) 13939abf88c9286d7465ce18285f87bb302f588b59fcFariborz Jahanian != Compatible) { 13949abf88c9286d7465ce18285f87bb302f588b59fcFariborz Jahanian Diag(Loc, diag::error_property_accessor_type) 13959abf88c9286d7465ce18285f87bb302f588b59fcFariborz Jahanian << property->getDeclName() << PropertyIvarType 13969abf88c9286d7465ce18285f87bb302f588b59fcFariborz Jahanian << GetterMethod->getSelector() << GetterType; 13979abf88c9286d7465ce18285f87bb302f588b59fcFariborz Jahanian Diag(GetterMethod->getLocation(), diag::note_declared_at); 13989abf88c9286d7465ce18285f87bb302f588b59fcFariborz Jahanian return true; 13999abf88c9286d7465ce18285f87bb302f588b59fcFariborz Jahanian } else { 14009abf88c9286d7465ce18285f87bb302f588b59fcFariborz Jahanian compat = true; 14019abf88c9286d7465ce18285f87bb302f588b59fcFariborz Jahanian QualType lhsType =Context.getCanonicalType(PropertyIvarType).getUnqualifiedType(); 14029abf88c9286d7465ce18285f87bb302f588b59fcFariborz Jahanian QualType rhsType =Context.getCanonicalType(GetterType).getUnqualifiedType(); 14039abf88c9286d7465ce18285f87bb302f588b59fcFariborz Jahanian if (lhsType != rhsType && lhsType->isArithmeticType()) 14049abf88c9286d7465ce18285f87bb302f588b59fcFariborz Jahanian compat = false; 14059d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek } 14069d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek } 14079abf88c9286d7465ce18285f87bb302f588b59fcFariborz Jahanian 14089abf88c9286d7465ce18285f87bb302f588b59fcFariborz Jahanian if (!compat) { 14099abf88c9286d7465ce18285f87bb302f588b59fcFariborz Jahanian Diag(Loc, diag::warn_accessor_property_type_mismatch) 14109abf88c9286d7465ce18285f87bb302f588b59fcFariborz Jahanian << property->getDeclName() 14119abf88c9286d7465ce18285f87bb302f588b59fcFariborz Jahanian << GetterMethod->getSelector(); 14129abf88c9286d7465ce18285f87bb302f588b59fcFariborz Jahanian Diag(GetterMethod->getLocation(), diag::note_declared_at); 14139abf88c9286d7465ce18285f87bb302f588b59fcFariborz Jahanian return true; 14149abf88c9286d7465ce18285f87bb302f588b59fcFariborz Jahanian } 14159abf88c9286d7465ce18285f87bb302f588b59fcFariborz Jahanian 14169d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek return false; 14179d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek} 14189d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek 14199d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek/// CollectImmediateProperties - This routine collects all properties in 14200dfe23c5d571222e74e3ed74c6fff3cee792118eDouglas Gregor/// the class and its conforming protocols; but not those in its super class. 1421651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic void CollectImmediateProperties(ObjCContainerDecl *CDecl, 1422651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ObjCContainerDecl::PropertyMap &PropMap, 1423651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ObjCContainerDecl::PropertyMap &SuperPropMap, 1424651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines bool IncludeProtocols = true) { 1425651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 14269d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl)) { 1427651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (auto *Prop : IDecl->properties()) 14289d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek PropMap[Prop->getIdentifier()] = Prop; 1429651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (IncludeProtocols) { 1430651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Scan through class's protocols. 1431651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (auto *PI : IDecl->all_referenced_protocols()) 1432651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines CollectImmediateProperties(PI, PropMap, SuperPropMap); 14339d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek } 14349d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek } 14359d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek if (ObjCCategoryDecl *CATDecl = dyn_cast<ObjCCategoryDecl>(CDecl)) { 14369d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek if (!CATDecl->IsClassExtension()) 1437651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (auto *Prop : CATDecl->properties()) 14389d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek PropMap[Prop->getIdentifier()] = Prop; 1439651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (IncludeProtocols) { 1440651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Scan through class's protocols. 1441651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (auto *PI : CATDecl->protocols()) 1442651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines CollectImmediateProperties(PI, PropMap, SuperPropMap); 1443651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 14449d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek } 14459d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek else if (ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(CDecl)) { 1446651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (auto *Prop : PDecl->properties()) { 1447cfa6a27f3cc5add888c6ac84dbcc45854cfd8666Fariborz Jahanian ObjCPropertyDecl *PropertyFromSuper = SuperPropMap[Prop->getIdentifier()]; 1448cfa6a27f3cc5add888c6ac84dbcc45854cfd8666Fariborz Jahanian // Exclude property for protocols which conform to class's super-class, 1449cfa6a27f3cc5add888c6ac84dbcc45854cfd8666Fariborz Jahanian // as super-class has to implement the property. 1450a929ec7b673b244bec024ba7eb95140404a7af5dFariborz Jahanian if (!PropertyFromSuper || 1451a929ec7b673b244bec024ba7eb95140404a7af5dFariborz Jahanian PropertyFromSuper->getIdentifier() != Prop->getIdentifier()) { 1452cfa6a27f3cc5add888c6ac84dbcc45854cfd8666Fariborz Jahanian ObjCPropertyDecl *&PropEntry = PropMap[Prop->getIdentifier()]; 1453cfa6a27f3cc5add888c6ac84dbcc45854cfd8666Fariborz Jahanian if (!PropEntry) 1454cfa6a27f3cc5add888c6ac84dbcc45854cfd8666Fariborz Jahanian PropEntry = Prop; 1455cfa6a27f3cc5add888c6ac84dbcc45854cfd8666Fariborz Jahanian } 14569d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek } 14579d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek // scan through protocol's protocols. 1458651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (auto *PI : PDecl->protocols()) 1459651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines CollectImmediateProperties(PI, PropMap, SuperPropMap); 14609d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek } 14619d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek} 14629d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek 1463509d477ae5a24282719320fe92038ccf57358840Fariborz Jahanian/// CollectSuperClassPropertyImplementations - This routine collects list of 1464509d477ae5a24282719320fe92038ccf57358840Fariborz Jahanian/// properties to be implemented in super class(s) and also coming from their 1465509d477ae5a24282719320fe92038ccf57358840Fariborz Jahanian/// conforming protocols. 1466509d477ae5a24282719320fe92038ccf57358840Fariborz Jahanianstatic void CollectSuperClassPropertyImplementations(ObjCInterfaceDecl *CDecl, 1467e63aedd0cb064fc106636ad856cc0e645e6374ceAnna Zaks ObjCInterfaceDecl::PropertyMap &PropMap) { 1468509d477ae5a24282719320fe92038ccf57358840Fariborz Jahanian if (ObjCInterfaceDecl *SDecl = CDecl->getSuperClass()) { 1469cfaed8d399a34e79fbab9f70eb4ea1bbeb81a02bFariborz Jahanian ObjCInterfaceDecl::PropertyDeclOrder PO; 1470509d477ae5a24282719320fe92038ccf57358840Fariborz Jahanian while (SDecl) { 1471cfaed8d399a34e79fbab9f70eb4ea1bbeb81a02bFariborz Jahanian SDecl->collectPropertiesToImplement(PropMap, PO); 1472509d477ae5a24282719320fe92038ccf57358840Fariborz Jahanian SDecl = SDecl->getSuperClass(); 1473509d477ae5a24282719320fe92038ccf57358840Fariborz Jahanian } 1474509d477ae5a24282719320fe92038ccf57358840Fariborz Jahanian } 1475509d477ae5a24282719320fe92038ccf57358840Fariborz Jahanian} 1476509d477ae5a24282719320fe92038ccf57358840Fariborz Jahanian 147726202291b161f8598c0c342cba12c6552e44d44cFariborz Jahanian/// IvarBacksCurrentMethodAccessor - This routine returns 'true' if 'IV' is 147826202291b161f8598c0c342cba12c6552e44d44cFariborz Jahanian/// an ivar synthesized for 'Method' and 'Method' is a property accessor 147926202291b161f8598c0c342cba12c6552e44d44cFariborz Jahanian/// declared in class 'IFace'. 148026202291b161f8598c0c342cba12c6552e44d44cFariborz Jahanianbool 148126202291b161f8598c0c342cba12c6552e44d44cFariborz JahanianSema::IvarBacksCurrentMethodAccessor(ObjCInterfaceDecl *IFace, 148226202291b161f8598c0c342cba12c6552e44d44cFariborz Jahanian ObjCMethodDecl *Method, ObjCIvarDecl *IV) { 148326202291b161f8598c0c342cba12c6552e44d44cFariborz Jahanian if (!IV->getSynthesize()) 148426202291b161f8598c0c342cba12c6552e44d44cFariborz Jahanian return false; 148526202291b161f8598c0c342cba12c6552e44d44cFariborz Jahanian ObjCMethodDecl *IMD = IFace->lookupMethod(Method->getSelector(), 148626202291b161f8598c0c342cba12c6552e44d44cFariborz Jahanian Method->isInstanceMethod()); 148726202291b161f8598c0c342cba12c6552e44d44cFariborz Jahanian if (!IMD || !IMD->isPropertyAccessor()) 148826202291b161f8598c0c342cba12c6552e44d44cFariborz Jahanian return false; 148926202291b161f8598c0c342cba12c6552e44d44cFariborz Jahanian 149026202291b161f8598c0c342cba12c6552e44d44cFariborz Jahanian // look up a property declaration whose one of its accessors is implemented 149126202291b161f8598c0c342cba12c6552e44d44cFariborz Jahanian // by this method. 1492651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (const auto *Property : IFace->properties()) { 1493651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if ((Property->getGetterName() == IMD->getSelector() || 1494651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Property->getSetterName() == IMD->getSelector()) && 1495651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines (Property->getPropertyIvarDecl() == IV)) 149626202291b161f8598c0c342cba12c6552e44d44cFariborz Jahanian return true; 149726202291b161f8598c0c342cba12c6552e44d44cFariborz Jahanian } 149826202291b161f8598c0c342cba12c6552e44d44cFariborz Jahanian return false; 149926202291b161f8598c0c342cba12c6552e44d44cFariborz Jahanian} 150026202291b161f8598c0c342cba12c6552e44d44cFariborz Jahanian 1501651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic bool SuperClassImplementsProperty(ObjCInterfaceDecl *IDecl, 1502651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ObjCPropertyDecl *Prop) { 1503651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines bool SuperClassImplementsGetter = false; 1504651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines bool SuperClassImplementsSetter = false; 1505651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_readonly) 1506651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SuperClassImplementsSetter = true; 1507651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1508651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines while (IDecl->getSuperClass()) { 1509651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ObjCInterfaceDecl *SDecl = IDecl->getSuperClass(); 1510651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!SuperClassImplementsGetter && SDecl->getInstanceMethod(Prop->getGetterName())) 1511651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SuperClassImplementsGetter = true; 1512651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1513651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!SuperClassImplementsSetter && SDecl->getInstanceMethod(Prop->getSetterName())) 1514651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SuperClassImplementsSetter = true; 1515651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (SuperClassImplementsGetter && SuperClassImplementsSetter) 1516651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return true; 1517651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines IDecl = IDecl->getSuperClass(); 1518651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1519651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return false; 1520651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 152126202291b161f8598c0c342cba12c6552e44d44cFariborz Jahanian 1522699c9044c7d53a2774d0dd261a6901dd2c4a545fJames Dennett/// \brief Default synthesizes all properties which must be synthesized 1523699c9044c7d53a2774d0dd261a6901dd2c4a545fJames Dennett/// in class's \@implementation. 1524d2ee809f9e7c2c7a83b8918efa11e98863463f78Ted Kremenekvoid Sema::DefaultSynthesizeProperties(Scope *S, ObjCImplDecl* IMPDecl, 1525d2ee809f9e7c2c7a83b8918efa11e98863463f78Ted Kremenek ObjCInterfaceDecl *IDecl) { 1526509d477ae5a24282719320fe92038ccf57358840Fariborz Jahanian 1527b36ea375e20f71df19c101fa2399b7ea3a607e04Anna Zaks ObjCInterfaceDecl::PropertyMap PropMap; 1528cfaed8d399a34e79fbab9f70eb4ea1bbeb81a02bFariborz Jahanian ObjCInterfaceDecl::PropertyDeclOrder PropertyOrder; 1529cfaed8d399a34e79fbab9f70eb4ea1bbeb81a02bFariborz Jahanian IDecl->collectPropertiesToImplement(PropMap, PropertyOrder); 1530509d477ae5a24282719320fe92038ccf57358840Fariborz Jahanian if (PropMap.empty()) 1531509d477ae5a24282719320fe92038ccf57358840Fariborz Jahanian return; 1532b36ea375e20f71df19c101fa2399b7ea3a607e04Anna Zaks ObjCInterfaceDecl::PropertyMap SuperPropMap; 1533509d477ae5a24282719320fe92038ccf57358840Fariborz Jahanian CollectSuperClassPropertyImplementations(IDecl, SuperPropMap); 1534509d477ae5a24282719320fe92038ccf57358840Fariborz Jahanian 1535cfaed8d399a34e79fbab9f70eb4ea1bbeb81a02bFariborz Jahanian for (unsigned i = 0, e = PropertyOrder.size(); i != e; i++) { 1536cfaed8d399a34e79fbab9f70eb4ea1bbeb81a02bFariborz Jahanian ObjCPropertyDecl *Prop = PropertyOrder[i]; 15376071af93f9b3c5a361c2f11566003d729418be3dFariborz Jahanian // Is there a matching property synthesize/dynamic? 15386071af93f9b3c5a361c2f11566003d729418be3dFariborz Jahanian if (Prop->isInvalidDecl() || 15396071af93f9b3c5a361c2f11566003d729418be3dFariborz Jahanian Prop->getPropertyImplementation() == ObjCPropertyDecl::Optional) 15406071af93f9b3c5a361c2f11566003d729418be3dFariborz Jahanian continue; 15416071af93f9b3c5a361c2f11566003d729418be3dFariborz Jahanian // Property may have been synthesized by user. 15426071af93f9b3c5a361c2f11566003d729418be3dFariborz Jahanian if (IMPDecl->FindPropertyImplDecl(Prop->getIdentifier())) 15436071af93f9b3c5a361c2f11566003d729418be3dFariborz Jahanian continue; 15446071af93f9b3c5a361c2f11566003d729418be3dFariborz Jahanian if (IMPDecl->getInstanceMethod(Prop->getGetterName())) { 15456071af93f9b3c5a361c2f11566003d729418be3dFariborz Jahanian if (Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_readonly) 15466071af93f9b3c5a361c2f11566003d729418be3dFariborz Jahanian continue; 15476071af93f9b3c5a361c2f11566003d729418be3dFariborz Jahanian if (IMPDecl->getInstanceMethod(Prop->getSetterName())) 15486071af93f9b3c5a361c2f11566003d729418be3dFariborz Jahanian continue; 15496071af93f9b3c5a361c2f11566003d729418be3dFariborz Jahanian } 1550509d477ae5a24282719320fe92038ccf57358840Fariborz Jahanian // If property to be implemented in the super class, ignore. 15516114a3c9baf29b3db1e0853a829ae1278285aef4Fariborz Jahanian if (SuperPropMap[Prop->getIdentifier()]) { 15526114a3c9baf29b3db1e0853a829ae1278285aef4Fariborz Jahanian ObjCPropertyDecl *PropInSuperClass = SuperPropMap[Prop->getIdentifier()]; 15536114a3c9baf29b3db1e0853a829ae1278285aef4Fariborz Jahanian if ((Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_readwrite) && 15546114a3c9baf29b3db1e0853a829ae1278285aef4Fariborz Jahanian (PropInSuperClass->getPropertyAttributes() & 15551d0d2fe76496ee2f8da9f56cb7f7eb24c4ffba05Fariborz Jahanian ObjCPropertyDecl::OBJC_PR_readonly) && 15565bdaef55d486f20346fe16f3d41324694d3ff0d5Fariborz Jahanian !IMPDecl->getInstanceMethod(Prop->getSetterName()) && 15575bdaef55d486f20346fe16f3d41324694d3ff0d5Fariborz Jahanian !IDecl->HasUserDeclaredSetterMethod(Prop)) { 15586114a3c9baf29b3db1e0853a829ae1278285aef4Fariborz Jahanian Diag(Prop->getLocation(), diag::warn_no_autosynthesis_property) 1559651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines << Prop->getIdentifier(); 15606114a3c9baf29b3db1e0853a829ae1278285aef4Fariborz Jahanian Diag(PropInSuperClass->getLocation(), diag::note_property_declare); 15616114a3c9baf29b3db1e0853a829ae1278285aef4Fariborz Jahanian } 1562509d477ae5a24282719320fe92038ccf57358840Fariborz Jahanian continue; 15636114a3c9baf29b3db1e0853a829ae1278285aef4Fariborz Jahanian } 1564a6ba40c1e573aee7882baa804e596e243b9c4e2aFariborz Jahanian if (ObjCPropertyImplDecl *PID = 1565a6ba40c1e573aee7882baa804e596e243b9c4e2aFariborz Jahanian IMPDecl->FindPropertyImplIvarDecl(Prop->getIdentifier())) { 1566a6ba40c1e573aee7882baa804e596e243b9c4e2aFariborz Jahanian if (PID->getPropertyDecl() != Prop) { 1567a6ba40c1e573aee7882baa804e596e243b9c4e2aFariborz Jahanian Diag(Prop->getLocation(), diag::warn_no_autosynthesis_shared_ivar_property) 1568651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines << Prop->getIdentifier(); 1569a6ba40c1e573aee7882baa804e596e243b9c4e2aFariborz Jahanian if (!PID->getLocation().isInvalid()) 1570a6ba40c1e573aee7882baa804e596e243b9c4e2aFariborz Jahanian Diag(PID->getLocation(), diag::note_property_synthesize); 1571a6ba40c1e573aee7882baa804e596e243b9c4e2aFariborz Jahanian } 1572a6ba40c1e573aee7882baa804e596e243b9c4e2aFariborz Jahanian continue; 1573a6ba40c1e573aee7882baa804e596e243b9c4e2aFariborz Jahanian } 1574651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (ObjCProtocolDecl *Proto = 1575651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines dyn_cast<ObjCProtocolDecl>(Prop->getDeclContext())) { 1576f8aba8c618920db8f6ef2db0c554b0c270503cefFariborz Jahanian // We won't auto-synthesize properties declared in protocols. 1577651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Suppress the warning if class's superclass implements property's 1578651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // getter and implements property's setter (if readwrite property). 1579651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!SuperClassImplementsProperty(IDecl, Prop)) { 1580651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Diag(IMPDecl->getLocation(), 1581651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines diag::warn_auto_synthesizing_protocol_property) 1582651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines << Prop << Proto; 1583651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Diag(Prop->getLocation(), diag::note_property_declare); 1584651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1585f8aba8c618920db8f6ef2db0c554b0c270503cefFariborz Jahanian continue; 1586f8aba8c618920db8f6ef2db0c554b0c270503cefFariborz Jahanian } 15872a6af6b7874e41f3e6213e8d18623c4bac150354Ted Kremenek 15882a6af6b7874e41f3e6213e8d18623c4bac150354Ted Kremenek // We use invalid SourceLocations for the synthesized ivars since they 15892a6af6b7874e41f3e6213e8d18623c4bac150354Ted Kremenek // aren't really synthesized at a particular location; they just exist. 15902a6af6b7874e41f3e6213e8d18623c4bac150354Ted Kremenek // Saying that they are located at the @implementation isn't really going 15912a6af6b7874e41f3e6213e8d18623c4bac150354Ted Kremenek // to help users. 1592975eef64182a78d1afc0f3da8cba4cb961cda5e4Fariborz Jahanian ObjCPropertyImplDecl *PIDecl = dyn_cast_or_null<ObjCPropertyImplDecl>( 1593975eef64182a78d1afc0f3da8cba4cb961cda5e4Fariborz Jahanian ActOnPropertyImplDecl(S, SourceLocation(), SourceLocation(), 1594975eef64182a78d1afc0f3da8cba4cb961cda5e4Fariborz Jahanian true, 1595975eef64182a78d1afc0f3da8cba4cb961cda5e4Fariborz Jahanian /* property = */ Prop->getIdentifier(), 1596ad0ce53c8219456938405b84c5d13341a47e3d94Anna Zaks /* ivar = */ Prop->getDefaultSynthIvarName(Context), 1597390fff8e8b480fa146ffc14cbc63a1c2f9e2d206Argyrios Kyrtzidis Prop->getLocation())); 1598975eef64182a78d1afc0f3da8cba4cb961cda5e4Fariborz Jahanian if (PIDecl) { 1599975eef64182a78d1afc0f3da8cba4cb961cda5e4Fariborz Jahanian Diag(Prop->getLocation(), diag::warn_missing_explicit_synthesis); 16005ea66619a3108e2985e952b9a60a84316d464b25Fariborz Jahanian Diag(IMPDecl->getLocation(), diag::note_while_in_implementation); 1601975eef64182a78d1afc0f3da8cba4cb961cda5e4Fariborz Jahanian } 16022a6af6b7874e41f3e6213e8d18623c4bac150354Ted Kremenek } 1603509d477ae5a24282719320fe92038ccf57358840Fariborz Jahanian} 16049d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek 16058697d308c1bdd50e5c45757ac11be701c26e9e97Fariborz Jahanianvoid Sema::DefaultSynthesizeProperties(Scope *S, Decl *D) { 1606260611a32535c851237926bfcf78869b13c07d5bJohn McCall if (!LangOpts.ObjCDefaultSynthProperties || LangOpts.ObjCRuntime.isFragile()) 16078697d308c1bdd50e5c45757ac11be701c26e9e97Fariborz Jahanian return; 16088697d308c1bdd50e5c45757ac11be701c26e9e97Fariborz Jahanian ObjCImplementationDecl *IC=dyn_cast_or_null<ObjCImplementationDecl>(D); 16098697d308c1bdd50e5c45757ac11be701c26e9e97Fariborz Jahanian if (!IC) 16108697d308c1bdd50e5c45757ac11be701c26e9e97Fariborz Jahanian return; 16118697d308c1bdd50e5c45757ac11be701c26e9e97Fariborz Jahanian if (ObjCInterfaceDecl* IDecl = IC->getClassInterface()) 161271207fc0470e1eee40a2951cd5cc3ff47725b755Ted Kremenek if (!IDecl->isObjCRequiresPropertyDefs()) 1613eb4f2c56c298071d58b441ccf801b039be93788aFariborz Jahanian DefaultSynthesizeProperties(S, IC, IDecl); 16148697d308c1bdd50e5c45757ac11be701c26e9e97Fariborz Jahanian} 16158697d308c1bdd50e5c45757ac11be701c26e9e97Fariborz Jahanian 1616651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic void DiagnoseUnimplementedAccessor(Sema &S, 1617651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ObjCInterfaceDecl *PrimaryClass, 1618651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Selector Method, 1619651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ObjCImplDecl* IMPDecl, 1620651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ObjCContainerDecl *CDecl, 1621651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ObjCCategoryDecl *C, 1622651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ObjCPropertyDecl *Prop, 1623651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Sema::SelectorSet &SMap) { 1624651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // When reporting on missing property setter/getter implementation in 1625651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // categories, do not report when they are declared in primary class, 1626651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // class's protocol, or one of it super classes. This is because, 1627651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // the class is going to implement them. 1628651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!SMap.count(Method) && 16296bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines (PrimaryClass == nullptr || 1630651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines !PrimaryClass->lookupPropertyAccessor(Method, C))) { 1631651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines S.Diag(IMPDecl->getLocation(), 1632651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines isa<ObjCCategoryDecl>(CDecl) ? 1633651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines diag::warn_setter_getter_impl_required_in_category : 1634651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines diag::warn_setter_getter_impl_required) 1635651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines << Prop->getDeclName() << Method; 1636651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines S.Diag(Prop->getLocation(), 1637651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines diag::note_property_declare); 1638651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (S.LangOpts.ObjCDefaultSynthProperties && 1639651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines S.LangOpts.ObjCRuntime.isNonFragile()) 1640651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(CDecl)) 1641651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (const ObjCInterfaceDecl *RID = ID->isObjCRequiresPropertyDefs()) 1642651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines S.Diag(RID->getLocation(), diag::note_suppressed_class_declare); 1643651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1644651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 1645651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 164617cb326cb62a59f53d92236394af40eaae4eddbdFariborz Jahanianvoid Sema::DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl, 1647651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ObjCContainerDecl *CDecl, 1648651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines bool SynthesizeProperties) { 1649651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ObjCContainerDecl::PropertyMap PropMap; 1650651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl); 1651651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1652651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!SynthesizeProperties) { 1653651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ObjCContainerDecl::PropertyMap NoNeedToImplPropMap; 1654651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Gather properties which need not be implemented in this class 1655651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // or category. 1656651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!IDecl) 1657651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl)) { 1658651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // For categories, no need to implement properties declared in 1659651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // its primary class (and its super classes) if property is 1660651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // declared in one of those containers. 1661651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if ((IDecl = C->getClassInterface())) { 1662651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ObjCInterfaceDecl::PropertyDeclOrder PO; 1663651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines IDecl->collectPropertiesToImplement(NoNeedToImplPropMap, PO); 1664651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1665651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1666651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (IDecl) 1667651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines CollectSuperClassPropertyImplementations(IDecl, NoNeedToImplPropMap); 1668651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1669651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines CollectImmediateProperties(CDecl, PropMap, NoNeedToImplPropMap); 1670651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1671651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1672651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Scan the @interface to see if any of the protocols it adopts 1673651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // require an explicit implementation, via attribute 1674651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // 'objc_protocol_requires_explicit_implementation'. 1675651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (IDecl) { 1676651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::unique_ptr<ObjCContainerDecl::PropertyMap> LazyMap; 1677651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1678651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (auto *PDecl : IDecl->all_referenced_protocols()) { 1679651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!PDecl->hasAttr<ObjCExplicitProtocolImplAttr>()) 1680651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines continue; 1681651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Lazily construct a set of all the properties in the @interface 1682651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // of the class, without looking at the superclass. We cannot 1683651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // use the call to CollectImmediateProperties() above as that 16846bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines // utilizes information from the super class's properties as well 1685651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // as scans the adopted protocols. This work only triggers for protocols 1686651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // with the attribute, which is very rare, and only occurs when 1687651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // analyzing the @implementation. 1688651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!LazyMap) { 1689651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ObjCContainerDecl::PropertyMap NoNeedToImplPropMap; 1690651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines LazyMap.reset(new ObjCContainerDecl::PropertyMap()); 1691651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines CollectImmediateProperties(CDecl, *LazyMap, NoNeedToImplPropMap, 1692651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines /* IncludeProtocols */ false); 1693651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1694651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Add the properties of 'PDecl' to the list of properties that 1695651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // need to be implemented. 1696651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (auto *PropDecl : PDecl->properties()) { 1697651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if ((*LazyMap)[PropDecl->getIdentifier()]) 1698651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines continue; 1699651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines PropMap[PropDecl->getIdentifier()] = PropDecl; 1700cfaed8d399a34e79fbab9f70eb4ea1bbeb81a02bFariborz Jahanian } 1701277076a4cdf684e6ea102197a635d4a352998018Fariborz Jahanian } 1702651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1703651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 17049d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek if (PropMap.empty()) 17059d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek return; 17069d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek 17079d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek llvm::DenseSet<ObjCPropertyDecl *> PropImplMap; 1708651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (const auto *I : IMPDecl->property_impls()) 1709262bc18e32500558af7cb0afa205b34bd37bafedDavid Blaikie PropImplMap.insert(I->getPropertyDecl()); 17109d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek 1711c775b1a0702621e297d00452a897381c8bf10f3fFariborz Jahanian SelectorSet InsMap; 1712c775b1a0702621e297d00452a897381c8bf10f3fFariborz Jahanian // Collect property accessors implemented in current implementation. 1713651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (const auto *I : IMPDecl->instance_methods()) 1714651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines InsMap.insert(I->getSelector()); 1715c775b1a0702621e297d00452a897381c8bf10f3fFariborz Jahanian 1716c775b1a0702621e297d00452a897381c8bf10f3fFariborz Jahanian ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl); 17176bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines ObjCInterfaceDecl *PrimaryClass = nullptr; 1718c775b1a0702621e297d00452a897381c8bf10f3fFariborz Jahanian if (C && !C->IsClassExtension()) 1719c775b1a0702621e297d00452a897381c8bf10f3fFariborz Jahanian if ((PrimaryClass = C->getClassInterface())) 1720c775b1a0702621e297d00452a897381c8bf10f3fFariborz Jahanian // Report unimplemented properties in the category as well. 1721c775b1a0702621e297d00452a897381c8bf10f3fFariborz Jahanian if (ObjCImplDecl *IMP = PrimaryClass->getImplementation()) { 1722c775b1a0702621e297d00452a897381c8bf10f3fFariborz Jahanian // When reporting on missing setter/getters, do not report when 1723c775b1a0702621e297d00452a897381c8bf10f3fFariborz Jahanian // setter/getter is implemented in category's primary class 1724c775b1a0702621e297d00452a897381c8bf10f3fFariborz Jahanian // implementation. 1725651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (const auto *I : IMP->instance_methods()) 1726651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines InsMap.insert(I->getSelector()); 1727c775b1a0702621e297d00452a897381c8bf10f3fFariborz Jahanian } 1728c775b1a0702621e297d00452a897381c8bf10f3fFariborz Jahanian 1729b36ea375e20f71df19c101fa2399b7ea3a607e04Anna Zaks for (ObjCContainerDecl::PropertyMap::iterator 17309d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek P = PropMap.begin(), E = PropMap.end(); P != E; ++P) { 17319d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek ObjCPropertyDecl *Prop = P->second; 17329d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek // Is there a matching propery synthesize/dynamic? 17339d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek if (Prop->isInvalidDecl() || 17349d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek Prop->getPropertyImplementation() == ObjCPropertyDecl::Optional || 17357cdc45751cb5b200ad5fff0de28c5d1a64b6fce3Douglas Gregor PropImplMap.count(Prop) || 17367cdc45751cb5b200ad5fff0de28c5d1a64b6fce3Douglas Gregor Prop->getAvailability() == AR_Unavailable) 17379d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek continue; 1738651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1739651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Diagnose unimplemented getters and setters. 1740651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines DiagnoseUnimplementedAccessor(*this, 1741651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines PrimaryClass, Prop->getGetterName(), IMPDecl, CDecl, C, Prop, InsMap); 1742651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!Prop->isReadOnly()) 1743651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines DiagnoseUnimplementedAccessor(*this, 1744651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines PrimaryClass, Prop->getSetterName(), 1745651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines IMPDecl, CDecl, C, Prop, InsMap); 17469d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek } 17479d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek} 17489d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek 17499d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenekvoid 17509d64c15223497f31899cc47fbe1531873dc06f2eTed KremenekSema::AtomicPropertySetterGetterRules (ObjCImplDecl* IMPDecl, 17519d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek ObjCContainerDecl* IDecl) { 17529d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek // Rules apply in non-GC mode only 17534e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie if (getLangOpts().getGC() != LangOptions::NonGC) 17549d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek return; 1755651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (const auto *Property : IDecl->properties()) { 17566bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines ObjCMethodDecl *GetterMethod = nullptr; 17576bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines ObjCMethodDecl *SetterMethod = nullptr; 175894659e4bdb87534f591ae185812548c42d6efacbArgyrios Kyrtzidis bool LookedUpGetterSetter = false; 175994659e4bdb87534f591ae185812548c42d6efacbArgyrios Kyrtzidis 1760ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling unsigned Attributes = Property->getPropertyAttributes(); 1761265941bc308d65cc270d5c4de5806f37ce405606John McCall unsigned AttributesAsWritten = Property->getPropertyAttributesAsWritten(); 176294659e4bdb87534f591ae185812548c42d6efacbArgyrios Kyrtzidis 1763265941bc308d65cc270d5c4de5806f37ce405606John McCall if (!(AttributesAsWritten & ObjCPropertyDecl::OBJC_PR_atomic) && 1764265941bc308d65cc270d5c4de5806f37ce405606John McCall !(AttributesAsWritten & ObjCPropertyDecl::OBJC_PR_nonatomic)) { 176594659e4bdb87534f591ae185812548c42d6efacbArgyrios Kyrtzidis GetterMethod = IMPDecl->getInstanceMethod(Property->getGetterName()); 176694659e4bdb87534f591ae185812548c42d6efacbArgyrios Kyrtzidis SetterMethod = IMPDecl->getInstanceMethod(Property->getSetterName()); 176794659e4bdb87534f591ae185812548c42d6efacbArgyrios Kyrtzidis LookedUpGetterSetter = true; 176894659e4bdb87534f591ae185812548c42d6efacbArgyrios Kyrtzidis if (GetterMethod) { 176994659e4bdb87534f591ae185812548c42d6efacbArgyrios Kyrtzidis Diag(GetterMethod->getLocation(), 177094659e4bdb87534f591ae185812548c42d6efacbArgyrios Kyrtzidis diag::warn_default_atomic_custom_getter_setter) 1771293a45e724a15fb58b8805a5791f9f3aee769cf6Argyrios Kyrtzidis << Property->getIdentifier() << 0; 177294659e4bdb87534f591ae185812548c42d6efacbArgyrios Kyrtzidis Diag(Property->getLocation(), diag::note_property_declare); 177394659e4bdb87534f591ae185812548c42d6efacbArgyrios Kyrtzidis } 177494659e4bdb87534f591ae185812548c42d6efacbArgyrios Kyrtzidis if (SetterMethod) { 177594659e4bdb87534f591ae185812548c42d6efacbArgyrios Kyrtzidis Diag(SetterMethod->getLocation(), 177694659e4bdb87534f591ae185812548c42d6efacbArgyrios Kyrtzidis diag::warn_default_atomic_custom_getter_setter) 1777293a45e724a15fb58b8805a5791f9f3aee769cf6Argyrios Kyrtzidis << Property->getIdentifier() << 1; 177894659e4bdb87534f591ae185812548c42d6efacbArgyrios Kyrtzidis Diag(Property->getLocation(), diag::note_property_declare); 177994659e4bdb87534f591ae185812548c42d6efacbArgyrios Kyrtzidis } 178094659e4bdb87534f591ae185812548c42d6efacbArgyrios Kyrtzidis } 178194659e4bdb87534f591ae185812548c42d6efacbArgyrios Kyrtzidis 17829d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek // We only care about readwrite atomic property. 1783ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling if ((Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic) || 1784ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling !(Attributes & ObjCPropertyDecl::OBJC_PR_readwrite)) 17859d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek continue; 17869d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek if (const ObjCPropertyImplDecl *PIDecl 17879d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek = IMPDecl->FindPropertyImplDecl(Property->getIdentifier())) { 17889d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek if (PIDecl->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) 17899d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek continue; 179094659e4bdb87534f591ae185812548c42d6efacbArgyrios Kyrtzidis if (!LookedUpGetterSetter) { 179194659e4bdb87534f591ae185812548c42d6efacbArgyrios Kyrtzidis GetterMethod = IMPDecl->getInstanceMethod(Property->getGetterName()); 179294659e4bdb87534f591ae185812548c42d6efacbArgyrios Kyrtzidis SetterMethod = IMPDecl->getInstanceMethod(Property->getSetterName()); 179394659e4bdb87534f591ae185812548c42d6efacbArgyrios Kyrtzidis } 17949d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek if ((GetterMethod && !SetterMethod) || (!GetterMethod && SetterMethod)) { 17959d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek SourceLocation MethodLoc = 17969d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek (GetterMethod ? GetterMethod->getLocation() 17979d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek : SetterMethod->getLocation()); 17989d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek Diag(MethodLoc, diag::warn_atomic_property_rule) 17996bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines << Property->getIdentifier() << (GetterMethod != nullptr) 18006bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines << (SetterMethod != nullptr); 180177bfb8b43ec3f7dee3a71f6e854b03ad29dab84fFariborz Jahanian // fixit stuff. 180277bfb8b43ec3f7dee3a71f6e854b03ad29dab84fFariborz Jahanian if (!AttributesAsWritten) { 180377bfb8b43ec3f7dee3a71f6e854b03ad29dab84fFariborz Jahanian if (Property->getLParenLoc().isValid()) { 180477bfb8b43ec3f7dee3a71f6e854b03ad29dab84fFariborz Jahanian // @property () ... case. 180577bfb8b43ec3f7dee3a71f6e854b03ad29dab84fFariborz Jahanian SourceRange PropSourceRange(Property->getAtLoc(), 180677bfb8b43ec3f7dee3a71f6e854b03ad29dab84fFariborz Jahanian Property->getLParenLoc()); 180777bfb8b43ec3f7dee3a71f6e854b03ad29dab84fFariborz Jahanian Diag(Property->getLocation(), diag::note_atomic_property_fixup_suggest) << 180877bfb8b43ec3f7dee3a71f6e854b03ad29dab84fFariborz Jahanian FixItHint::CreateReplacement(PropSourceRange, "@property (nonatomic"); 180977bfb8b43ec3f7dee3a71f6e854b03ad29dab84fFariborz Jahanian } 181077bfb8b43ec3f7dee3a71f6e854b03ad29dab84fFariborz Jahanian else { 181177bfb8b43ec3f7dee3a71f6e854b03ad29dab84fFariborz Jahanian //@property id etc. 181277bfb8b43ec3f7dee3a71f6e854b03ad29dab84fFariborz Jahanian SourceLocation endLoc = 181377bfb8b43ec3f7dee3a71f6e854b03ad29dab84fFariborz Jahanian Property->getTypeSourceInfo()->getTypeLoc().getBeginLoc(); 181477bfb8b43ec3f7dee3a71f6e854b03ad29dab84fFariborz Jahanian endLoc = endLoc.getLocWithOffset(-1); 181577bfb8b43ec3f7dee3a71f6e854b03ad29dab84fFariborz Jahanian SourceRange PropSourceRange(Property->getAtLoc(), endLoc); 181677bfb8b43ec3f7dee3a71f6e854b03ad29dab84fFariborz Jahanian Diag(Property->getLocation(), diag::note_atomic_property_fixup_suggest) << 181777bfb8b43ec3f7dee3a71f6e854b03ad29dab84fFariborz Jahanian FixItHint::CreateReplacement(PropSourceRange, "@property (nonatomic) "); 181877bfb8b43ec3f7dee3a71f6e854b03ad29dab84fFariborz Jahanian } 181977bfb8b43ec3f7dee3a71f6e854b03ad29dab84fFariborz Jahanian } 182077bfb8b43ec3f7dee3a71f6e854b03ad29dab84fFariborz Jahanian else if (!(AttributesAsWritten & ObjCPropertyDecl::OBJC_PR_atomic)) { 182177bfb8b43ec3f7dee3a71f6e854b03ad29dab84fFariborz Jahanian // @property () ... case. 182277bfb8b43ec3f7dee3a71f6e854b03ad29dab84fFariborz Jahanian SourceLocation endLoc = Property->getLParenLoc(); 182377bfb8b43ec3f7dee3a71f6e854b03ad29dab84fFariborz Jahanian SourceRange PropSourceRange(Property->getAtLoc(), endLoc); 182477bfb8b43ec3f7dee3a71f6e854b03ad29dab84fFariborz Jahanian Diag(Property->getLocation(), diag::note_atomic_property_fixup_suggest) << 182577bfb8b43ec3f7dee3a71f6e854b03ad29dab84fFariborz Jahanian FixItHint::CreateReplacement(PropSourceRange, "@property (nonatomic, "); 182677bfb8b43ec3f7dee3a71f6e854b03ad29dab84fFariborz Jahanian } 182777bfb8b43ec3f7dee3a71f6e854b03ad29dab84fFariborz Jahanian else 182877bfb8b43ec3f7dee3a71f6e854b03ad29dab84fFariborz Jahanian Diag(MethodLoc, diag::note_atomic_property_fixup_suggest); 18299d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek Diag(Property->getLocation(), diag::note_property_declare); 18309d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek } 18319d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek } 18329d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek } 18339d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek} 18349d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek 1835f85e193739c953358c865005855253af4f68a497John McCallvoid Sema::DiagnoseOwningPropertyGetterSynthesis(const ObjCImplementationDecl *D) { 18364e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie if (getLangOpts().getGC() == LangOptions::GCOnly) 1837f85e193739c953358c865005855253af4f68a497John McCall return; 1838f85e193739c953358c865005855253af4f68a497John McCall 1839651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (const auto *PID : D->property_impls()) { 1840f85e193739c953358c865005855253af4f68a497John McCall const ObjCPropertyDecl *PD = PID->getPropertyDecl(); 1841831fb9622581fc3b777848e6b097a0cb23d124deFariborz Jahanian if (PD && !PD->hasAttr<NSReturnsNotRetainedAttr>() && 1842831fb9622581fc3b777848e6b097a0cb23d124deFariborz Jahanian !D->getInstanceMethod(PD->getGetterName())) { 1843f85e193739c953358c865005855253af4f68a497John McCall ObjCMethodDecl *method = PD->getGetterMethodDecl(); 1844f85e193739c953358c865005855253af4f68a497John McCall if (!method) 1845f85e193739c953358c865005855253af4f68a497John McCall continue; 1846f85e193739c953358c865005855253af4f68a497John McCall ObjCMethodFamily family = method->getMethodFamily(); 1847f85e193739c953358c865005855253af4f68a497John McCall if (family == OMF_alloc || family == OMF_copy || 1848f85e193739c953358c865005855253af4f68a497John McCall family == OMF_mutableCopy || family == OMF_new) { 18494e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie if (getLangOpts().ObjCAutoRefCount) 1850651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Diag(PD->getLocation(), diag::err_cocoa_naming_owned_rule); 1851f85e193739c953358c865005855253af4f68a497John McCall else 1852651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Diag(PD->getLocation(), diag::warn_cocoa_naming_owned_rule); 1853f85e193739c953358c865005855253af4f68a497John McCall } 1854f85e193739c953358c865005855253af4f68a497John McCall } 1855f85e193739c953358c865005855253af4f68a497John McCall } 1856f85e193739c953358c865005855253af4f68a497John McCall} 1857f85e193739c953358c865005855253af4f68a497John McCall 1858651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesvoid Sema::DiagnoseMissingDesignatedInitOverrides( 1859651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const ObjCImplementationDecl *ImplD, 1860651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const ObjCInterfaceDecl *IFD) { 1861651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines assert(IFD->hasDesignatedInitializers()); 1862651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const ObjCInterfaceDecl *SuperD = IFD->getSuperClass(); 1863651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!SuperD) 1864651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return; 1865651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1866651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SelectorSet InitSelSet; 1867651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (const auto *I : ImplD->instance_methods()) 1868651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (I->getMethodFamily() == OMF_init) 1869651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines InitSelSet.insert(I->getSelector()); 1870651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1871651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SmallVector<const ObjCMethodDecl *, 8> DesignatedInits; 1872651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SuperD->getDesignatedInitializers(DesignatedInits); 1873651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (SmallVector<const ObjCMethodDecl *, 8>::iterator 1874651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines I = DesignatedInits.begin(), E = DesignatedInits.end(); I != E; ++I) { 1875651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const ObjCMethodDecl *MD = *I; 1876651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!InitSelSet.count(MD->getSelector())) { 1877651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Diag(ImplD->getLocation(), 1878651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines diag::warn_objc_implementation_missing_designated_init_override) 1879651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines << MD->getSelector(); 1880651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Diag(MD->getLocation(), diag::note_objc_designated_init_marked_here); 1881651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1882651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1883651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 1884651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 18855de74d19ddcf84cfe9d7d973192ba93fd0c64d4fJohn McCall/// AddPropertyAttrs - Propagates attributes from a property to the 18865de74d19ddcf84cfe9d7d973192ba93fd0c64d4fJohn McCall/// implicitly-declared getter or setter for that property. 18875de74d19ddcf84cfe9d7d973192ba93fd0c64d4fJohn McCallstatic void AddPropertyAttrs(Sema &S, ObjCMethodDecl *PropertyMethod, 18885de74d19ddcf84cfe9d7d973192ba93fd0c64d4fJohn McCall ObjCPropertyDecl *Property) { 18895de74d19ddcf84cfe9d7d973192ba93fd0c64d4fJohn McCall // Should we just clone all attributes over? 1890651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (const auto *A : Property->attrs()) { 1891651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (isa<DeprecatedAttr>(A) || 1892651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines isa<UnavailableAttr>(A) || 1893651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines isa<AvailabilityAttr>(A)) 1894651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines PropertyMethod->addAttr(A->clone(S.Context)); 18950a0d2b179085a52c10402feebeb6db8b4d96a140Douglas Gregor } 18965de74d19ddcf84cfe9d7d973192ba93fd0c64d4fJohn McCall} 18975de74d19ddcf84cfe9d7d973192ba93fd0c64d4fJohn McCall 18989d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek/// ProcessPropertyDecl - Make sure that any user-defined setter/getter methods 18999d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek/// have the property type and issue diagnostics if they don't. 19009d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek/// Also synthesize a getter/setter method if none exist (and update the 19019d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek/// appropriate lookup tables. FIXME: Should reconsider if adding synthesized 19029d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek/// methods is the "right" thing to do. 19039d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenekvoid Sema::ProcessPropertyDecl(ObjCPropertyDecl *property, 19048254aa62d9189395be1eed61194cd4b5ee6cb4a2Ted Kremenek ObjCContainerDecl *CD, 19058254aa62d9189395be1eed61194cd4b5ee6cb4a2Ted Kremenek ObjCPropertyDecl *redeclaredProperty, 19068254aa62d9189395be1eed61194cd4b5ee6cb4a2Ted Kremenek ObjCContainerDecl *lexicalDC) { 19078254aa62d9189395be1eed61194cd4b5ee6cb4a2Ted Kremenek 19089d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek ObjCMethodDecl *GetterMethod, *SetterMethod; 19099d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek 19106bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if (CD->isInvalidDecl()) 19116bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return; 19126bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 19139d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek GetterMethod = CD->getInstanceMethod(property->getGetterName()); 19149d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek SetterMethod = CD->getInstanceMethod(property->getSetterName()); 19159d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek DiagnosePropertyAccessorMismatch(property, GetterMethod, 19169d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek property->getLocation()); 19179d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek 19189d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek if (SetterMethod) { 19199d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek ObjCPropertyDecl::PropertyAttributeKind CAttr = 19209d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek property->getPropertyAttributes(); 19219d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek if ((!(CAttr & ObjCPropertyDecl::OBJC_PR_readonly)) && 1922651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Context.getCanonicalType(SetterMethod->getReturnType()) != 1923651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Context.VoidTy) 19249d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek Diag(SetterMethod->getLocation(), diag::err_setter_type_void); 19259d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek if (SetterMethod->param_size() != 1 || 19262aac0c9f8bc4dca3f883f429af8c1f57132d62d0Fariborz Jahanian !Context.hasSameUnqualifiedType( 1927bb13c320fff4bc4b3536e62626c97d7b055c6113Fariborz Jahanian (*SetterMethod->param_begin())->getType().getNonReferenceType(), 1928bb13c320fff4bc4b3536e62626c97d7b055c6113Fariborz Jahanian property->getType().getNonReferenceType())) { 19299d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek Diag(property->getLocation(), 19309d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek diag::warn_accessor_property_type_mismatch) 19319d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek << property->getDeclName() 19329d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek << SetterMethod->getSelector(); 19339d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek Diag(SetterMethod->getLocation(), diag::note_declared_at); 19349d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek } 19359d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek } 19369d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek 19379d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek // Synthesize getter/setter methods if none exist. 19389d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek // Find the default getter and if one not found, add one. 19399d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek // FIXME: The synthesized property we set here is misleading. We almost always 19409d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek // synthesize these methods unless the user explicitly provided prototypes 19419d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek // (which is odd, but allowed). Sema should be typechecking that the 19429d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek // declarations jive in that situation (which it is not currently). 19439d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek if (!GetterMethod) { 19449d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek // No instance method of same name as property getter name was found. 19459d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek // Declare a getter method and add it to the list of methods 19469d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek // for this class. 1947a054fb46b1fb596d1719b89d2d9a5be3c32a4b0dTed Kremenek SourceLocation Loc = redeclaredProperty ? 1948a054fb46b1fb596d1719b89d2d9a5be3c32a4b0dTed Kremenek redeclaredProperty->getLocation() : 1949a054fb46b1fb596d1719b89d2d9a5be3c32a4b0dTed Kremenek property->getLocation(); 1950a054fb46b1fb596d1719b89d2d9a5be3c32a4b0dTed Kremenek 1951a054fb46b1fb596d1719b89d2d9a5be3c32a4b0dTed Kremenek GetterMethod = ObjCMethodDecl::Create(Context, Loc, Loc, 1952a054fb46b1fb596d1719b89d2d9a5be3c32a4b0dTed Kremenek property->getGetterName(), 19536bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines property->getType(), nullptr, CD, 19546bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines /*isInstance=*/true, /*isVariadic=*/false, 19556bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines /*isPropertyAccessor=*/true, 195675cf3e86d33ce810c12084126385371b335c30baArgyrios Kyrtzidis /*isImplicitlyDeclared=*/true, /*isDefined=*/false, 19579d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek (property->getPropertyImplementation() == 19589d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek ObjCPropertyDecl::Optional) ? 19599d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek ObjCMethodDecl::Optional : 19609d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek ObjCMethodDecl::Required); 19619d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek CD->addDecl(GetterMethod); 19625de74d19ddcf84cfe9d7d973192ba93fd0c64d4fJohn McCall 19635de74d19ddcf84cfe9d7d973192ba93fd0c64d4fJohn McCall AddPropertyAttrs(*this, GetterMethod, property); 19645de74d19ddcf84cfe9d7d973192ba93fd0c64d4fJohn McCall 196523173d7f029f430611caceea72ae61ba6b80af1cTed Kremenek // FIXME: Eventually this shouldn't be needed, as the lexical context 196623173d7f029f430611caceea72ae61ba6b80af1cTed Kremenek // and the real context should be the same. 1967a054fb46b1fb596d1719b89d2d9a5be3c32a4b0dTed Kremenek if (lexicalDC) 196823173d7f029f430611caceea72ae61ba6b80af1cTed Kremenek GetterMethod->setLexicalDeclContext(lexicalDC); 1969831fb9622581fc3b777848e6b097a0cb23d124deFariborz Jahanian if (property->hasAttr<NSReturnsNotRetainedAttr>()) 1970651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines GetterMethod->addAttr(NSReturnsNotRetainedAttr::CreateImplicit(Context, 1971651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Loc)); 1972937ec1d9575ec455bc2d4e1f159f64980b476196Fariborz Jahanian 1973937ec1d9575ec455bc2d4e1f159f64980b476196Fariborz Jahanian if (property->hasAttr<ObjCReturnsInnerPointerAttr>()) 1974937ec1d9575ec455bc2d4e1f159f64980b476196Fariborz Jahanian GetterMethod->addAttr( 1975651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ObjCReturnsInnerPointerAttr::CreateImplicit(Context, Loc)); 1976651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1977651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (const SectionAttr *SA = property->getAttr<SectionAttr>()) 19786bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines GetterMethod->addAttr( 19796bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines SectionAttr::CreateImplicit(Context, SectionAttr::GNU_section, 19806bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines SA->getName(), Loc)); 1981b846381fc3099b2340ba8c74d16178203a60d9a0John McCall 1982b846381fc3099b2340ba8c74d16178203a60d9a0John McCall if (getLangOpts().ObjCAutoRefCount) 1983b846381fc3099b2340ba8c74d16178203a60d9a0John McCall CheckARCMethodDecl(GetterMethod); 19849d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek } else 19859d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek // A user declared getter will be synthesize when @synthesize of 19869d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek // the property with the same name is seen in the @implementation 19871e4691b9d8e1bdcc8ef62b323969d702c51b3c08Jordan Rose GetterMethod->setPropertyAccessor(true); 19889d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek property->setGetterMethodDecl(GetterMethod); 19899d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek 19909d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek // Skip setter if property is read-only. 19919d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek if (!property->isReadOnly()) { 19929d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek // Find the default setter and if one not found, add one. 19939d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek if (!SetterMethod) { 19949d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek // No instance method of same name as property setter name was found. 19959d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek // Declare a setter method and add it to the list of methods 19969d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek // for this class. 19978254aa62d9189395be1eed61194cd4b5ee6cb4a2Ted Kremenek SourceLocation Loc = redeclaredProperty ? 19988254aa62d9189395be1eed61194cd4b5ee6cb4a2Ted Kremenek redeclaredProperty->getLocation() : 19998254aa62d9189395be1eed61194cd4b5ee6cb4a2Ted Kremenek property->getLocation(); 20008254aa62d9189395be1eed61194cd4b5ee6cb4a2Ted Kremenek 20018254aa62d9189395be1eed61194cd4b5ee6cb4a2Ted Kremenek SetterMethod = 2002491306a83c4f0f49f95a3bcbca8580cb98a91c7aArgyrios Kyrtzidis ObjCMethodDecl::Create(Context, Loc, Loc, 20036bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines property->getSetterName(), Context.VoidTy, 20046bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines nullptr, CD, /*isInstance=*/true, 20056bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines /*isVariadic=*/false, 20061e4691b9d8e1bdcc8ef62b323969d702c51b3c08Jordan Rose /*isPropertyAccessor=*/true, 200775cf3e86d33ce810c12084126385371b335c30baArgyrios Kyrtzidis /*isImplicitlyDeclared=*/true, 200875cf3e86d33ce810c12084126385371b335c30baArgyrios Kyrtzidis /*isDefined=*/false, 20099d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek (property->getPropertyImplementation() == 20109d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek ObjCPropertyDecl::Optional) ? 20118254aa62d9189395be1eed61194cd4b5ee6cb4a2Ted Kremenek ObjCMethodDecl::Optional : 20128254aa62d9189395be1eed61194cd4b5ee6cb4a2Ted Kremenek ObjCMethodDecl::Required); 20138254aa62d9189395be1eed61194cd4b5ee6cb4a2Ted Kremenek 20149d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek // Invent the arguments for the setter. We don't bother making a 20159d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek // nice name for the argument. 2016ff676cb48fe8bf7be2feaa251dc7c5fb15af4730Abramo Bagnara ParmVarDecl *Argument = ParmVarDecl::Create(Context, SetterMethod, 2017ff676cb48fe8bf7be2feaa251dc7c5fb15af4730Abramo Bagnara Loc, Loc, 20189d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek property->getIdentifier(), 2019f85e193739c953358c865005855253af4f68a497John McCall property->getType().getUnqualifiedType(), 20206bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines /*TInfo=*/nullptr, 2021d931b086984257de68868a64a235c2b4b34003fbJohn McCall SC_None, 20226bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines nullptr); 20235543169296beeb183b9c9392debc774fcf493eebDmitri Gribenko SetterMethod->setMethodParams(Context, Argument, None); 20245de74d19ddcf84cfe9d7d973192ba93fd0c64d4fJohn McCall 20255de74d19ddcf84cfe9d7d973192ba93fd0c64d4fJohn McCall AddPropertyAttrs(*this, SetterMethod, property); 20265de74d19ddcf84cfe9d7d973192ba93fd0c64d4fJohn McCall 20279d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek CD->addDecl(SetterMethod); 202823173d7f029f430611caceea72ae61ba6b80af1cTed Kremenek // FIXME: Eventually this shouldn't be needed, as the lexical context 202923173d7f029f430611caceea72ae61ba6b80af1cTed Kremenek // and the real context should be the same. 20308254aa62d9189395be1eed61194cd4b5ee6cb4a2Ted Kremenek if (lexicalDC) 203123173d7f029f430611caceea72ae61ba6b80af1cTed Kremenek SetterMethod->setLexicalDeclContext(lexicalDC); 2032651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (const SectionAttr *SA = property->getAttr<SectionAttr>()) 20336bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines SetterMethod->addAttr( 20346bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines SectionAttr::CreateImplicit(Context, SectionAttr::GNU_section, 20356bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines SA->getName(), Loc)); 2036b846381fc3099b2340ba8c74d16178203a60d9a0John McCall // It's possible for the user to have set a very odd custom 2037b846381fc3099b2340ba8c74d16178203a60d9a0John McCall // setter selector that causes it to have a method family. 2038b846381fc3099b2340ba8c74d16178203a60d9a0John McCall if (getLangOpts().ObjCAutoRefCount) 2039b846381fc3099b2340ba8c74d16178203a60d9a0John McCall CheckARCMethodDecl(SetterMethod); 20409d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek } else 20419d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek // A user declared setter will be synthesize when @synthesize of 20429d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek // the property with the same name is seen in the @implementation 20431e4691b9d8e1bdcc8ef62b323969d702c51b3c08Jordan Rose SetterMethod->setPropertyAccessor(true); 20449d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek property->setSetterMethodDecl(SetterMethod); 20459d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek } 20469d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek // Add any synthesized methods to the global pool. This allows us to 20479d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek // handle the following, which is supported by GCC (and part of the design). 20489d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek // 20499d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek // @interface Foo 20509d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek // @property double bar; 20519d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek // @end 20529d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek // 20539d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek // void thisIsUnfortunate() { 20549d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek // id foo; 20559d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek // double bar = [foo bar]; 20569d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek // } 20579d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek // 20589d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek if (GetterMethod) 20599d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek AddInstanceMethodToGlobalPool(GetterMethod); 20609d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek if (SetterMethod) 20619d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek AddInstanceMethodToGlobalPool(SetterMethod); 2062e15db6f0d226a3bc88d244512d1004c7c1c07391Argyrios Kyrtzidis 2063e15db6f0d226a3bc88d244512d1004c7c1c07391Argyrios Kyrtzidis ObjCInterfaceDecl *CurrentClass = dyn_cast<ObjCInterfaceDecl>(CD); 2064e15db6f0d226a3bc88d244512d1004c7c1c07391Argyrios Kyrtzidis if (!CurrentClass) { 2065e15db6f0d226a3bc88d244512d1004c7c1c07391Argyrios Kyrtzidis if (ObjCCategoryDecl *Cat = dyn_cast<ObjCCategoryDecl>(CD)) 2066e15db6f0d226a3bc88d244512d1004c7c1c07391Argyrios Kyrtzidis CurrentClass = Cat->getClassInterface(); 2067e15db6f0d226a3bc88d244512d1004c7c1c07391Argyrios Kyrtzidis else if (ObjCImplDecl *Impl = dyn_cast<ObjCImplDecl>(CD)) 2068e15db6f0d226a3bc88d244512d1004c7c1c07391Argyrios Kyrtzidis CurrentClass = Impl->getClassInterface(); 2069e15db6f0d226a3bc88d244512d1004c7c1c07391Argyrios Kyrtzidis } 2070e15db6f0d226a3bc88d244512d1004c7c1c07391Argyrios Kyrtzidis if (GetterMethod) 2071e15db6f0d226a3bc88d244512d1004c7c1c07391Argyrios Kyrtzidis CheckObjCMethodOverrides(GetterMethod, CurrentClass, Sema::RTC_Unknown); 2072e15db6f0d226a3bc88d244512d1004c7c1c07391Argyrios Kyrtzidis if (SetterMethod) 2073e15db6f0d226a3bc88d244512d1004c7c1c07391Argyrios Kyrtzidis CheckObjCMethodOverrides(SetterMethod, CurrentClass, Sema::RTC_Unknown); 20749d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek} 20759d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek 2076d226f65006733ed7f709c3174f22ce33391cb58fJohn McCallvoid Sema::CheckObjCPropertyAttributes(Decl *PDecl, 20779d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek SourceLocation Loc, 2078ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling unsigned &Attributes, 2079cea06d26b8f3a2599bba79f7e072b7550de949a7Fariborz Jahanian bool propertyInPrimaryClass) { 20809d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek // FIXME: Improve the reported location. 2081f85e193739c953358c865005855253af4f68a497John McCall if (!PDecl || PDecl->isInvalidDecl()) 20825fcd52a6c94c7f93bd80062248353c45330da23aTed Kremenek return; 2083dc1031bf257457bd58cc19426a21e0fa1fa95789Fariborz Jahanian 2084dc1031bf257457bd58cc19426a21e0fa1fa95789Fariborz Jahanian if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) && 2085dc1031bf257457bd58cc19426a21e0fa1fa95789Fariborz Jahanian (Attributes & ObjCDeclSpec::DQ_PR_readwrite)) 2086dc1031bf257457bd58cc19426a21e0fa1fa95789Fariborz Jahanian Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 2087dc1031bf257457bd58cc19426a21e0fa1fa95789Fariborz Jahanian << "readonly" << "readwrite"; 2088dc1031bf257457bd58cc19426a21e0fa1fa95789Fariborz Jahanian 20895fcd52a6c94c7f93bd80062248353c45330da23aTed Kremenek ObjCPropertyDecl *PropertyDecl = cast<ObjCPropertyDecl>(PDecl); 2090dc1031bf257457bd58cc19426a21e0fa1fa95789Fariborz Jahanian QualType PropertyTy = PropertyDecl->getType(); 2091dc1031bf257457bd58cc19426a21e0fa1fa95789Fariborz Jahanian unsigned PropertyOwnership = getOwnershipRule(Attributes); 2092dc1031bf257457bd58cc19426a21e0fa1fa95789Fariborz Jahanian 2093651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // 'readonly' property with no obvious lifetime. 2094651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // its life time will be determined by its backing ivar. 2095651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (getLangOpts().ObjCAutoRefCount && 2096651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Attributes & ObjCDeclSpec::DQ_PR_readonly && 2097651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines PropertyTy->isObjCRetainableType() && 2098651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines !PropertyOwnership) 2099651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return; 21009d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek 210128685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek // Check for copy or retain on non-object types. 2102ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling if ((Attributes & (ObjCDeclSpec::DQ_PR_weak | ObjCDeclSpec::DQ_PR_copy | 2103f85e193739c953358c865005855253af4f68a497John McCall ObjCDeclSpec::DQ_PR_retain | ObjCDeclSpec::DQ_PR_strong)) && 2104f85e193739c953358c865005855253af4f68a497John McCall !PropertyTy->isObjCRetainableType() && 2105651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines !PropertyDecl->hasAttr<ObjCNSObjectAttr>()) { 210628685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek Diag(Loc, diag::err_objc_property_requires_object) 2107ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling << (Attributes & ObjCDeclSpec::DQ_PR_weak ? "weak" : 2108ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling Attributes & ObjCDeclSpec::DQ_PR_copy ? "copy" : "retain (or strong)"); 2109ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling Attributes &= ~(ObjCDeclSpec::DQ_PR_weak | ObjCDeclSpec::DQ_PR_copy | 2110f85e193739c953358c865005855253af4f68a497John McCall ObjCDeclSpec::DQ_PR_retain | ObjCDeclSpec::DQ_PR_strong); 2111977ea7864a50eee39f6bef8a5a79154ac9ba4b3eJohn McCall PropertyDecl->setInvalidDecl(); 211228685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek } 21139d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek 211428685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek // Check for more than one of { assign, copy, retain }. 2115ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling if (Attributes & ObjCDeclSpec::DQ_PR_assign) { 2116ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling if (Attributes & ObjCDeclSpec::DQ_PR_copy) { 211728685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 211828685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek << "assign" << "copy"; 2119ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling Attributes &= ~ObjCDeclSpec::DQ_PR_copy; 212028685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek } 2121ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling if (Attributes & ObjCDeclSpec::DQ_PR_retain) { 212228685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 212328685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek << "assign" << "retain"; 2124ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling Attributes &= ~ObjCDeclSpec::DQ_PR_retain; 212528685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek } 2126ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling if (Attributes & ObjCDeclSpec::DQ_PR_strong) { 2127f85e193739c953358c865005855253af4f68a497John McCall Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 2128f85e193739c953358c865005855253af4f68a497John McCall << "assign" << "strong"; 2129ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling Attributes &= ~ObjCDeclSpec::DQ_PR_strong; 2130f85e193739c953358c865005855253af4f68a497John McCall } 21314e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie if (getLangOpts().ObjCAutoRefCount && 2132ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling (Attributes & ObjCDeclSpec::DQ_PR_weak)) { 2133f85e193739c953358c865005855253af4f68a497John McCall Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 2134f85e193739c953358c865005855253af4f68a497John McCall << "assign" << "weak"; 2135ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling Attributes &= ~ObjCDeclSpec::DQ_PR_weak; 2136f85e193739c953358c865005855253af4f68a497John McCall } 2137651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (PropertyDecl->hasAttr<IBOutletCollectionAttr>()) 2138548fba96250b6624a96459780e30fd459eed1528Fariborz Jahanian Diag(Loc, diag::warn_iboutletcollection_property_assign); 2139ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling } else if (Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained) { 2140ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling if (Attributes & ObjCDeclSpec::DQ_PR_copy) { 2141f85e193739c953358c865005855253af4f68a497John McCall Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 2142f85e193739c953358c865005855253af4f68a497John McCall << "unsafe_unretained" << "copy"; 2143ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling Attributes &= ~ObjCDeclSpec::DQ_PR_copy; 2144f85e193739c953358c865005855253af4f68a497John McCall } 2145ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling if (Attributes & ObjCDeclSpec::DQ_PR_retain) { 2146f85e193739c953358c865005855253af4f68a497John McCall Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 2147f85e193739c953358c865005855253af4f68a497John McCall << "unsafe_unretained" << "retain"; 2148ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling Attributes &= ~ObjCDeclSpec::DQ_PR_retain; 2149f85e193739c953358c865005855253af4f68a497John McCall } 2150ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling if (Attributes & ObjCDeclSpec::DQ_PR_strong) { 2151f85e193739c953358c865005855253af4f68a497John McCall Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 2152f85e193739c953358c865005855253af4f68a497John McCall << "unsafe_unretained" << "strong"; 2153ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling Attributes &= ~ObjCDeclSpec::DQ_PR_strong; 2154f85e193739c953358c865005855253af4f68a497John McCall } 21554e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie if (getLangOpts().ObjCAutoRefCount && 2156ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling (Attributes & ObjCDeclSpec::DQ_PR_weak)) { 2157f85e193739c953358c865005855253af4f68a497John McCall Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 2158f85e193739c953358c865005855253af4f68a497John McCall << "unsafe_unretained" << "weak"; 2159ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling Attributes &= ~ObjCDeclSpec::DQ_PR_weak; 2160f85e193739c953358c865005855253af4f68a497John McCall } 2161ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling } else if (Attributes & ObjCDeclSpec::DQ_PR_copy) { 2162ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling if (Attributes & ObjCDeclSpec::DQ_PR_retain) { 216328685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 216428685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek << "copy" << "retain"; 2165ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling Attributes &= ~ObjCDeclSpec::DQ_PR_retain; 216628685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek } 2167ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling if (Attributes & ObjCDeclSpec::DQ_PR_strong) { 2168f85e193739c953358c865005855253af4f68a497John McCall Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 2169f85e193739c953358c865005855253af4f68a497John McCall << "copy" << "strong"; 2170ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling Attributes &= ~ObjCDeclSpec::DQ_PR_strong; 2171f85e193739c953358c865005855253af4f68a497John McCall } 2172ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling if (Attributes & ObjCDeclSpec::DQ_PR_weak) { 2173f85e193739c953358c865005855253af4f68a497John McCall Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 2174f85e193739c953358c865005855253af4f68a497John McCall << "copy" << "weak"; 2175ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling Attributes &= ~ObjCDeclSpec::DQ_PR_weak; 2176f85e193739c953358c865005855253af4f68a497John McCall } 2177f85e193739c953358c865005855253af4f68a497John McCall } 2178ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling else if ((Attributes & ObjCDeclSpec::DQ_PR_retain) && 2179ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling (Attributes & ObjCDeclSpec::DQ_PR_weak)) { 2180f85e193739c953358c865005855253af4f68a497John McCall Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 2181f85e193739c953358c865005855253af4f68a497John McCall << "retain" << "weak"; 2182ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling Attributes &= ~ObjCDeclSpec::DQ_PR_retain; 2183f85e193739c953358c865005855253af4f68a497John McCall } 2184ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling else if ((Attributes & ObjCDeclSpec::DQ_PR_strong) && 2185ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling (Attributes & ObjCDeclSpec::DQ_PR_weak)) { 2186f85e193739c953358c865005855253af4f68a497John McCall Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 2187f85e193739c953358c865005855253af4f68a497John McCall << "strong" << "weak"; 2188ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling Attributes &= ~ObjCDeclSpec::DQ_PR_weak; 218928685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek } 21909d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek 2191ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling if ((Attributes & ObjCDeclSpec::DQ_PR_atomic) && 2192ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling (Attributes & ObjCDeclSpec::DQ_PR_nonatomic)) { 21939d1bbeab2475fe45a3d4cb8de6810bc3275f1dd7Fariborz Jahanian Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 21949d1bbeab2475fe45a3d4cb8de6810bc3275f1dd7Fariborz Jahanian << "atomic" << "nonatomic"; 2195ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling Attributes &= ~ObjCDeclSpec::DQ_PR_atomic; 21969d1bbeab2475fe45a3d4cb8de6810bc3275f1dd7Fariborz Jahanian } 21979d1bbeab2475fe45a3d4cb8de6810bc3275f1dd7Fariborz Jahanian 219828685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek // Warn if user supplied no assignment attribute, property is 219928685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek // readwrite, and this is an object type. 2200ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling if (!(Attributes & (ObjCDeclSpec::DQ_PR_assign | ObjCDeclSpec::DQ_PR_copy | 2201f85e193739c953358c865005855253af4f68a497John McCall ObjCDeclSpec::DQ_PR_unsafe_unretained | 2202f85e193739c953358c865005855253af4f68a497John McCall ObjCDeclSpec::DQ_PR_retain | ObjCDeclSpec::DQ_PR_strong | 2203f85e193739c953358c865005855253af4f68a497John McCall ObjCDeclSpec::DQ_PR_weak)) && 220428685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek PropertyTy->isObjCObjectPointerType()) { 22054e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie if (getLangOpts().ObjCAutoRefCount) 2206bc03aea4bec84d7abecabd26b8583adb687c4089Fariborz Jahanian // With arc, @property definitions should default to (strong) when 2207f21a92d35953adb038ffbe37cd1a4083e0df0ec0Fariborz Jahanian // not specified; including when property is 'readonly'. 2208bc03aea4bec84d7abecabd26b8583adb687c4089Fariborz Jahanian PropertyDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_strong); 2209ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling else if (!(Attributes & ObjCDeclSpec::DQ_PR_readonly)) { 22109f37cd1810646ffc9002c7a6477fe158ee15ede4Fariborz Jahanian bool isAnyClassTy = 22119f37cd1810646ffc9002c7a6477fe158ee15ede4Fariborz Jahanian (PropertyTy->isObjCClassType() || 22129f37cd1810646ffc9002c7a6477fe158ee15ede4Fariborz Jahanian PropertyTy->isObjCQualifiedClassType()); 22139f37cd1810646ffc9002c7a6477fe158ee15ede4Fariborz Jahanian // In non-gc, non-arc mode, 'Class' is treated as a 'void *' no need to 22149f37cd1810646ffc9002c7a6477fe158ee15ede4Fariborz Jahanian // issue any warning. 22154e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie if (isAnyClassTy && getLangOpts().getGC() == LangOptions::NonGC) 22169f37cd1810646ffc9002c7a6477fe158ee15ede4Fariborz Jahanian ; 2217f224fb5de15e10cecd2d87fee73b0e39b503d924Fariborz Jahanian else if (propertyInPrimaryClass) { 2218f224fb5de15e10cecd2d87fee73b0e39b503d924Fariborz Jahanian // Don't issue warning on property with no life time in class 2219f224fb5de15e10cecd2d87fee73b0e39b503d924Fariborz Jahanian // extension as it is inherited from property in primary class. 2220bc03aea4bec84d7abecabd26b8583adb687c4089Fariborz Jahanian // Skip this warning in gc-only mode. 22214e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie if (getLangOpts().getGC() != LangOptions::GCOnly) 2222bc03aea4bec84d7abecabd26b8583adb687c4089Fariborz Jahanian Diag(Loc, diag::warn_objc_property_no_assignment_attribute); 22230a68dc7f04be1542ce249ff4adb169453698ad91Argyrios Kyrtzidis 2224bc03aea4bec84d7abecabd26b8583adb687c4089Fariborz Jahanian // If non-gc code warn that this is likely inappropriate. 22254e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie if (getLangOpts().getGC() == LangOptions::NonGC) 2226bc03aea4bec84d7abecabd26b8583adb687c4089Fariborz Jahanian Diag(Loc, diag::warn_objc_property_default_assign_on_object); 22279f37cd1810646ffc9002c7a6477fe158ee15ede4Fariborz Jahanian } 2228bc03aea4bec84d7abecabd26b8583adb687c4089Fariborz Jahanian } 22299d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek 223028685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek // FIXME: Implement warning dependent on NSCopying being 223128685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek // implemented. See also: 223228685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek // <rdar://5168496&4855821&5607453&5096644&4947311&5698469&4947014&5168496> 223328685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek // (please trim this list while you are at it). 223428685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek } 22359d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek 2236ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling if (!(Attributes & ObjCDeclSpec::DQ_PR_copy) 2237ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling &&!(Attributes & ObjCDeclSpec::DQ_PR_readonly) 22384e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie && getLangOpts().getGC() == LangOptions::GCOnly 223928685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek && PropertyTy->isBlockPointerType()) 224028685ab2ddeea146841bf2e277e25c7b32dfc9f6Ted Kremenek Diag(Loc, diag::warn_objc_property_copy_missing_on_block); 2241ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling else if ((Attributes & ObjCDeclSpec::DQ_PR_retain) && 2242ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling !(Attributes & ObjCDeclSpec::DQ_PR_readonly) && 2243ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling !(Attributes & ObjCDeclSpec::DQ_PR_strong) && 2244528a499eb84d61667f65b16a13780c135b822f6bFariborz Jahanian PropertyTy->isBlockPointerType()) 2245528a499eb84d61667f65b16a13780c135b822f6bFariborz Jahanian Diag(Loc, diag::warn_objc_property_retain_of_block); 224648a98c7a8467a9570d2fc7f2aab7f5273a3e218eFariborz Jahanian 2247ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) && 2248ad017fa7a4df7389d245d02a49b3c79ed70bedb9Bill Wendling (Attributes & ObjCDeclSpec::DQ_PR_setter)) 224948a98c7a8467a9570d2fc7f2aab7f5273a3e218eFariborz Jahanian Diag(Loc, diag::warn_objc_readonly_property_has_setter); 225048a98c7a8467a9570d2fc7f2aab7f5273a3e218eFariborz Jahanian 22519d64c15223497f31899cc47fbe1531873dc06f2eTed Kremenek} 2252