clang API Documentation
00001 //===--- SemaObjCProperty.cpp - Semantic Analysis for ObjC @property ------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file implements semantic analysis for Objective C @property and 00011 // @synthesize declarations. 00012 // 00013 //===----------------------------------------------------------------------===// 00014 00015 #include "clang/Sema/SemaInternal.h" 00016 #include "clang/AST/ASTMutationListener.h" 00017 #include "clang/AST/DeclObjC.h" 00018 #include "clang/AST/ExprCXX.h" 00019 #include "clang/AST/ExprObjC.h" 00020 #include "clang/Basic/SourceManager.h" 00021 #include "clang/Lex/Lexer.h" 00022 #include "clang/Sema/Initialization.h" 00023 #include "llvm/ADT/DenseSet.h" 00024 #include "llvm/ADT/SmallString.h" 00025 00026 using namespace clang; 00027 00028 //===----------------------------------------------------------------------===// 00029 // Grammar actions. 00030 //===----------------------------------------------------------------------===// 00031 00032 /// getImpliedARCOwnership - Given a set of property attributes and a 00033 /// type, infer an expected lifetime. The type's ownership qualification 00034 /// is not considered. 00035 /// 00036 /// Returns OCL_None if the attributes as stated do not imply an ownership. 00037 /// Never returns OCL_Autoreleasing. 00038 static Qualifiers::ObjCLifetime getImpliedARCOwnership( 00039 ObjCPropertyDecl::PropertyAttributeKind attrs, 00040 QualType type) { 00041 // retain, strong, copy, weak, and unsafe_unretained are only legal 00042 // on properties of retainable pointer type. 00043 if (attrs & (ObjCPropertyDecl::OBJC_PR_retain | 00044 ObjCPropertyDecl::OBJC_PR_strong | 00045 ObjCPropertyDecl::OBJC_PR_copy)) { 00046 return Qualifiers::OCL_Strong; 00047 } else if (attrs & ObjCPropertyDecl::OBJC_PR_weak) { 00048 return Qualifiers::OCL_Weak; 00049 } else if (attrs & ObjCPropertyDecl::OBJC_PR_unsafe_unretained) { 00050 return Qualifiers::OCL_ExplicitNone; 00051 } 00052 00053 // assign can appear on other types, so we have to check the 00054 // property type. 00055 if (attrs & ObjCPropertyDecl::OBJC_PR_assign && 00056 type->isObjCRetainableType()) { 00057 return Qualifiers::OCL_ExplicitNone; 00058 } 00059 00060 return Qualifiers::OCL_None; 00061 } 00062 00063 /// Check the internal consistency of a property declaration. 00064 static void checkARCPropertyDecl(Sema &S, ObjCPropertyDecl *property) { 00065 if (property->isInvalidDecl()) return; 00066 00067 ObjCPropertyDecl::PropertyAttributeKind propertyKind 00068 = property->getPropertyAttributes(); 00069 Qualifiers::ObjCLifetime propertyLifetime 00070 = property->getType().getObjCLifetime(); 00071 00072 // Nothing to do if we don't have a lifetime. 00073 if (propertyLifetime == Qualifiers::OCL_None) return; 00074 00075 Qualifiers::ObjCLifetime expectedLifetime 00076 = getImpliedARCOwnership(propertyKind, property->getType()); 00077 if (!expectedLifetime) { 00078 // We have a lifetime qualifier but no dominating property 00079 // attribute. That's okay, but restore reasonable invariants by 00080 // setting the property attribute according to the lifetime 00081 // qualifier. 00082 ObjCPropertyDecl::PropertyAttributeKind attr; 00083 if (propertyLifetime == Qualifiers::OCL_Strong) { 00084 attr = ObjCPropertyDecl::OBJC_PR_strong; 00085 } else if (propertyLifetime == Qualifiers::OCL_Weak) { 00086 attr = ObjCPropertyDecl::OBJC_PR_weak; 00087 } else { 00088 assert(propertyLifetime == Qualifiers::OCL_ExplicitNone); 00089 attr = ObjCPropertyDecl::OBJC_PR_unsafe_unretained; 00090 } 00091 property->setPropertyAttributes(attr); 00092 return; 00093 } 00094 00095 if (propertyLifetime == expectedLifetime) return; 00096 00097 property->setInvalidDecl(); 00098 S.Diag(property->getLocation(), 00099 diag::err_arc_inconsistent_property_ownership) 00100 << property->getDeclName() 00101 << expectedLifetime 00102 << propertyLifetime; 00103 } 00104 00105 static unsigned deduceWeakPropertyFromType(Sema &S, QualType T) { 00106 if ((S.getLangOpts().getGC() != LangOptions::NonGC && 00107 T.isObjCGCWeak()) || 00108 (S.getLangOpts().ObjCAutoRefCount && 00109 T.getObjCLifetime() == Qualifiers::OCL_Weak)) 00110 return ObjCDeclSpec::DQ_PR_weak; 00111 return 0; 00112 } 00113 00114 /// \brief Check this Objective-C property against a property declared in the 00115 /// given protocol. 00116 static void 00117 CheckPropertyAgainstProtocol(Sema &S, ObjCPropertyDecl *Prop, 00118 ObjCProtocolDecl *Proto, 00119 llvm::SmallPtrSetImpl<ObjCProtocolDecl *> &Known) { 00120 // Have we seen this protocol before? 00121 if (!Known.insert(Proto)) 00122 return; 00123 00124 // Look for a property with the same name. 00125 DeclContext::lookup_result R = Proto->lookup(Prop->getDeclName()); 00126 for (unsigned I = 0, N = R.size(); I != N; ++I) { 00127 if (ObjCPropertyDecl *ProtoProp = dyn_cast<ObjCPropertyDecl>(R[I])) { 00128 S.DiagnosePropertyMismatch(Prop, ProtoProp, Proto->getIdentifier(), true); 00129 return; 00130 } 00131 } 00132 00133 // Check this property against any protocols we inherit. 00134 for (auto *P : Proto->protocols()) 00135 CheckPropertyAgainstProtocol(S, Prop, P, Known); 00136 } 00137 00138 Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc, 00139 SourceLocation LParenLoc, 00140 FieldDeclarator &FD, 00141 ObjCDeclSpec &ODS, 00142 Selector GetterSel, 00143 Selector SetterSel, 00144 bool *isOverridingProperty, 00145 tok::ObjCKeywordKind MethodImplKind, 00146 DeclContext *lexicalDC) { 00147 unsigned Attributes = ODS.getPropertyAttributes(); 00148 TypeSourceInfo *TSI = GetTypeForDeclarator(FD.D, S); 00149 QualType T = TSI->getType(); 00150 Attributes |= deduceWeakPropertyFromType(*this, T); 00151 00152 bool isReadWrite = ((Attributes & ObjCDeclSpec::DQ_PR_readwrite) || 00153 // default is readwrite! 00154 !(Attributes & ObjCDeclSpec::DQ_PR_readonly)); 00155 // property is defaulted to 'assign' if it is readwrite and is 00156 // not retain or copy 00157 bool isAssign = ((Attributes & ObjCDeclSpec::DQ_PR_assign) || 00158 (isReadWrite && 00159 !(Attributes & ObjCDeclSpec::DQ_PR_retain) && 00160 !(Attributes & ObjCDeclSpec::DQ_PR_strong) && 00161 !(Attributes & ObjCDeclSpec::DQ_PR_copy) && 00162 !(Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained) && 00163 !(Attributes & ObjCDeclSpec::DQ_PR_weak))); 00164 00165 // Proceed with constructing the ObjCPropertyDecls. 00166 ObjCContainerDecl *ClassDecl = cast<ObjCContainerDecl>(CurContext); 00167 ObjCPropertyDecl *Res = nullptr; 00168 if (ObjCCategoryDecl *CDecl = dyn_cast<ObjCCategoryDecl>(ClassDecl)) { 00169 if (CDecl->IsClassExtension()) { 00170 Res = HandlePropertyInClassExtension(S, AtLoc, LParenLoc, 00171 FD, GetterSel, SetterSel, 00172 isAssign, isReadWrite, 00173 Attributes, 00174 ODS.getPropertyAttributes(), 00175 isOverridingProperty, TSI, 00176 MethodImplKind); 00177 if (!Res) 00178 return nullptr; 00179 } 00180 } 00181 00182 if (!Res) { 00183 Res = CreatePropertyDecl(S, ClassDecl, AtLoc, LParenLoc, FD, 00184 GetterSel, SetterSel, isAssign, isReadWrite, 00185 Attributes, ODS.getPropertyAttributes(), 00186 TSI, MethodImplKind); 00187 if (lexicalDC) 00188 Res->setLexicalDeclContext(lexicalDC); 00189 } 00190 00191 // Validate the attributes on the @property. 00192 CheckObjCPropertyAttributes(Res, AtLoc, Attributes, 00193 (isa<ObjCInterfaceDecl>(ClassDecl) || 00194 isa<ObjCProtocolDecl>(ClassDecl))); 00195 00196 if (getLangOpts().ObjCAutoRefCount) 00197 checkARCPropertyDecl(*this, Res); 00198 00199 llvm::SmallPtrSet<ObjCProtocolDecl *, 16> KnownProtos; 00200 if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(ClassDecl)) { 00201 // For a class, compare the property against a property in our superclass. 00202 bool FoundInSuper = false; 00203 ObjCInterfaceDecl *CurrentInterfaceDecl = IFace; 00204 while (ObjCInterfaceDecl *Super = CurrentInterfaceDecl->getSuperClass()) { 00205 DeclContext::lookup_result R = Super->lookup(Res->getDeclName()); 00206 for (unsigned I = 0, N = R.size(); I != N; ++I) { 00207 if (ObjCPropertyDecl *SuperProp = dyn_cast<ObjCPropertyDecl>(R[I])) { 00208 DiagnosePropertyMismatch(Res, SuperProp, Super->getIdentifier(), false); 00209 FoundInSuper = true; 00210 break; 00211 } 00212 } 00213 if (FoundInSuper) 00214 break; 00215 else 00216 CurrentInterfaceDecl = Super; 00217 } 00218 00219 if (FoundInSuper) { 00220 // Also compare the property against a property in our protocols. 00221 for (auto *P : CurrentInterfaceDecl->protocols()) { 00222 CheckPropertyAgainstProtocol(*this, Res, P, KnownProtos); 00223 } 00224 } else { 00225 // Slower path: look in all protocols we referenced. 00226 for (auto *P : IFace->all_referenced_protocols()) { 00227 CheckPropertyAgainstProtocol(*this, Res, P, KnownProtos); 00228 } 00229 } 00230 } else if (ObjCCategoryDecl *Cat = dyn_cast<ObjCCategoryDecl>(ClassDecl)) { 00231 for (auto *P : Cat->protocols()) 00232 CheckPropertyAgainstProtocol(*this, Res, P, KnownProtos); 00233 } else { 00234 ObjCProtocolDecl *Proto = cast<ObjCProtocolDecl>(ClassDecl); 00235 for (auto *P : Proto->protocols()) 00236 CheckPropertyAgainstProtocol(*this, Res, P, KnownProtos); 00237 } 00238 00239 ActOnDocumentableDecl(Res); 00240 return Res; 00241 } 00242 00243 static ObjCPropertyDecl::PropertyAttributeKind 00244 makePropertyAttributesAsWritten(unsigned Attributes) { 00245 unsigned attributesAsWritten = 0; 00246 if (Attributes & ObjCDeclSpec::DQ_PR_readonly) 00247 attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_readonly; 00248 if (Attributes & ObjCDeclSpec::DQ_PR_readwrite) 00249 attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_readwrite; 00250 if (Attributes & ObjCDeclSpec::DQ_PR_getter) 00251 attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_getter; 00252 if (Attributes & ObjCDeclSpec::DQ_PR_setter) 00253 attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_setter; 00254 if (Attributes & ObjCDeclSpec::DQ_PR_assign) 00255 attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_assign; 00256 if (Attributes & ObjCDeclSpec::DQ_PR_retain) 00257 attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_retain; 00258 if (Attributes & ObjCDeclSpec::DQ_PR_strong) 00259 attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_strong; 00260 if (Attributes & ObjCDeclSpec::DQ_PR_weak) 00261 attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_weak; 00262 if (Attributes & ObjCDeclSpec::DQ_PR_copy) 00263 attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_copy; 00264 if (Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained) 00265 attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_unsafe_unretained; 00266 if (Attributes & ObjCDeclSpec::DQ_PR_nonatomic) 00267 attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_nonatomic; 00268 if (Attributes & ObjCDeclSpec::DQ_PR_atomic) 00269 attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_atomic; 00270 00271 return (ObjCPropertyDecl::PropertyAttributeKind)attributesAsWritten; 00272 } 00273 00274 static bool LocPropertyAttribute( ASTContext &Context, const char *attrName, 00275 SourceLocation LParenLoc, SourceLocation &Loc) { 00276 if (LParenLoc.isMacroID()) 00277 return false; 00278 00279 SourceManager &SM = Context.getSourceManager(); 00280 std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(LParenLoc); 00281 // Try to load the file buffer. 00282 bool invalidTemp = false; 00283 StringRef file = SM.getBufferData(locInfo.first, &invalidTemp); 00284 if (invalidTemp) 00285 return false; 00286 const char *tokenBegin = file.data() + locInfo.second; 00287 00288 // Lex from the start of the given location. 00289 Lexer lexer(SM.getLocForStartOfFile(locInfo.first), 00290 Context.getLangOpts(), 00291 file.begin(), tokenBegin, file.end()); 00292 Token Tok; 00293 do { 00294 lexer.LexFromRawLexer(Tok); 00295 if (Tok.is(tok::raw_identifier) && Tok.getRawIdentifier() == attrName) { 00296 Loc = Tok.getLocation(); 00297 return true; 00298 } 00299 } while (Tok.isNot(tok::r_paren)); 00300 return false; 00301 00302 } 00303 00304 static unsigned getOwnershipRule(unsigned attr) { 00305 return attr & (ObjCPropertyDecl::OBJC_PR_assign | 00306 ObjCPropertyDecl::OBJC_PR_retain | 00307 ObjCPropertyDecl::OBJC_PR_copy | 00308 ObjCPropertyDecl::OBJC_PR_weak | 00309 ObjCPropertyDecl::OBJC_PR_strong | 00310 ObjCPropertyDecl::OBJC_PR_unsafe_unretained); 00311 } 00312 00313 ObjCPropertyDecl * 00314 Sema::HandlePropertyInClassExtension(Scope *S, 00315 SourceLocation AtLoc, 00316 SourceLocation LParenLoc, 00317 FieldDeclarator &FD, 00318 Selector GetterSel, Selector SetterSel, 00319 const bool isAssign, 00320 const bool isReadWrite, 00321 const unsigned Attributes, 00322 const unsigned AttributesAsWritten, 00323 bool *isOverridingProperty, 00324 TypeSourceInfo *T, 00325 tok::ObjCKeywordKind MethodImplKind) { 00326 ObjCCategoryDecl *CDecl = cast<ObjCCategoryDecl>(CurContext); 00327 // Diagnose if this property is already in continuation class. 00328 DeclContext *DC = CurContext; 00329 IdentifierInfo *PropertyId = FD.D.getIdentifier(); 00330 ObjCInterfaceDecl *CCPrimary = CDecl->getClassInterface(); 00331 00332 if (CCPrimary) { 00333 // Check for duplicate declaration of this property in current and 00334 // other class extensions. 00335 for (const auto *Ext : CCPrimary->known_extensions()) { 00336 if (ObjCPropertyDecl *prevDecl 00337 = ObjCPropertyDecl::findPropertyDecl(Ext, PropertyId)) { 00338 Diag(AtLoc, diag::err_duplicate_property); 00339 Diag(prevDecl->getLocation(), diag::note_property_declare); 00340 return nullptr; 00341 } 00342 } 00343 } 00344 00345 // Create a new ObjCPropertyDecl with the DeclContext being 00346 // the class extension. 00347 // FIXME. We should really be using CreatePropertyDecl for this. 00348 ObjCPropertyDecl *PDecl = 00349 ObjCPropertyDecl::Create(Context, DC, FD.D.getIdentifierLoc(), 00350 PropertyId, AtLoc, LParenLoc, T); 00351 PDecl->setPropertyAttributesAsWritten( 00352 makePropertyAttributesAsWritten(AttributesAsWritten)); 00353 if (Attributes & ObjCDeclSpec::DQ_PR_readonly) 00354 PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readonly); 00355 if (Attributes & ObjCDeclSpec::DQ_PR_readwrite) 00356 PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readwrite); 00357 if (Attributes & ObjCDeclSpec::DQ_PR_nonatomic) 00358 PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_nonatomic); 00359 if (Attributes & ObjCDeclSpec::DQ_PR_atomic) 00360 PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_atomic); 00361 // Set setter/getter selector name. Needed later. 00362 PDecl->setGetterName(GetterSel); 00363 PDecl->setSetterName(SetterSel); 00364 ProcessDeclAttributes(S, PDecl, FD.D); 00365 DC->addDecl(PDecl); 00366 00367 // We need to look in the @interface to see if the @property was 00368 // already declared. 00369 if (!CCPrimary) { 00370 Diag(CDecl->getLocation(), diag::err_continuation_class); 00371 *isOverridingProperty = true; 00372 return nullptr; 00373 } 00374 00375 // Find the property in continuation class's primary class only. 00376 ObjCPropertyDecl *PIDecl = 00377 CCPrimary->FindPropertyVisibleInPrimaryClass(PropertyId); 00378 00379 if (!PIDecl) { 00380 // No matching property found in the primary class. Just fall thru 00381 // and add property to continuation class's primary class. 00382 ObjCPropertyDecl *PrimaryPDecl = 00383 CreatePropertyDecl(S, CCPrimary, AtLoc, LParenLoc, 00384 FD, GetterSel, SetterSel, isAssign, isReadWrite, 00385 Attributes,AttributesAsWritten, T, MethodImplKind, DC); 00386 00387 // A case of continuation class adding a new property in the class. This 00388 // is not what it was meant for. However, gcc supports it and so should we. 00389 // Make sure setter/getters are declared here. 00390 ProcessPropertyDecl(PrimaryPDecl, CCPrimary, 00391 /* redeclaredProperty = */ nullptr, 00392 /* lexicalDC = */ CDecl); 00393 PDecl->setGetterMethodDecl(PrimaryPDecl->getGetterMethodDecl()); 00394 PDecl->setSetterMethodDecl(PrimaryPDecl->getSetterMethodDecl()); 00395 if (ASTMutationListener *L = Context.getASTMutationListener()) 00396 L->AddedObjCPropertyInClassExtension(PrimaryPDecl, /*OrigProp=*/nullptr, 00397 CDecl); 00398 return PrimaryPDecl; 00399 } 00400 if (!Context.hasSameType(PIDecl->getType(), PDecl->getType())) { 00401 bool IncompatibleObjC = false; 00402 QualType ConvertedType; 00403 // Relax the strict type matching for property type in continuation class. 00404 // Allow property object type of continuation class to be different as long 00405 // as it narrows the object type in its primary class property. Note that 00406 // this conversion is safe only because the wider type is for a 'readonly' 00407 // property in primary class and 'narrowed' type for a 'readwrite' property 00408 // in continuation class. 00409 if (!isa<ObjCObjectPointerType>(PIDecl->getType()) || 00410 !isa<ObjCObjectPointerType>(PDecl->getType()) || 00411 (!isObjCPointerConversion(PDecl->getType(), PIDecl->getType(), 00412 ConvertedType, IncompatibleObjC)) 00413 || IncompatibleObjC) { 00414 Diag(AtLoc, 00415 diag::err_type_mismatch_continuation_class) << PDecl->getType(); 00416 Diag(PIDecl->getLocation(), diag::note_property_declare); 00417 return nullptr; 00418 } 00419 } 00420 00421 // The property 'PIDecl's readonly attribute will be over-ridden 00422 // with continuation class's readwrite property attribute! 00423 unsigned PIkind = PIDecl->getPropertyAttributesAsWritten(); 00424 if (isReadWrite && (PIkind & ObjCPropertyDecl::OBJC_PR_readonly)) { 00425 PIkind &= ~ObjCPropertyDecl::OBJC_PR_readonly; 00426 PIkind |= ObjCPropertyDecl::OBJC_PR_readwrite; 00427 PIkind |= deduceWeakPropertyFromType(*this, PIDecl->getType()); 00428 unsigned ClassExtensionMemoryModel = getOwnershipRule(Attributes); 00429 unsigned PrimaryClassMemoryModel = getOwnershipRule(PIkind); 00430 if (PrimaryClassMemoryModel && ClassExtensionMemoryModel && 00431 (PrimaryClassMemoryModel != ClassExtensionMemoryModel)) { 00432 Diag(AtLoc, diag::warn_property_attr_mismatch); 00433 Diag(PIDecl->getLocation(), diag::note_property_declare); 00434 } 00435 else if (getLangOpts().ObjCAutoRefCount) { 00436 QualType PrimaryPropertyQT = 00437 Context.getCanonicalType(PIDecl->getType()).getUnqualifiedType(); 00438 if (isa<ObjCObjectPointerType>(PrimaryPropertyQT)) { 00439 bool PropertyIsWeak = ((PIkind & ObjCPropertyDecl::OBJC_PR_weak) != 0); 00440 Qualifiers::ObjCLifetime PrimaryPropertyLifeTime = 00441 PrimaryPropertyQT.getObjCLifetime(); 00442 if (PrimaryPropertyLifeTime == Qualifiers::OCL_None && 00443 (Attributes & ObjCDeclSpec::DQ_PR_weak) && 00444 !PropertyIsWeak) { 00445 Diag(AtLoc, diag::warn_property_implicitly_mismatched); 00446 Diag(PIDecl->getLocation(), diag::note_property_declare); 00447 } 00448 } 00449 } 00450 00451 DeclContext *DC = cast<DeclContext>(CCPrimary); 00452 if (!ObjCPropertyDecl::findPropertyDecl(DC, 00453 PIDecl->getDeclName().getAsIdentifierInfo())) { 00454 // In mrr mode, 'readwrite' property must have an explicit 00455 // memory attribute. If none specified, select the default (assign). 00456 if (!getLangOpts().ObjCAutoRefCount) { 00457 if (!(PIkind & (ObjCDeclSpec::DQ_PR_assign | 00458 ObjCDeclSpec::DQ_PR_retain | 00459 ObjCDeclSpec::DQ_PR_strong | 00460 ObjCDeclSpec::DQ_PR_copy | 00461 ObjCDeclSpec::DQ_PR_unsafe_unretained | 00462 ObjCDeclSpec::DQ_PR_weak))) 00463 PIkind |= ObjCPropertyDecl::OBJC_PR_assign; 00464 } 00465 00466 // Protocol is not in the primary class. Must build one for it. 00467 ObjCDeclSpec ProtocolPropertyODS; 00468 // FIXME. Assuming that ObjCDeclSpec::ObjCPropertyAttributeKind 00469 // and ObjCPropertyDecl::PropertyAttributeKind have identical 00470 // values. Should consolidate both into one enum type. 00471 ProtocolPropertyODS. 00472 setPropertyAttributes((ObjCDeclSpec::ObjCPropertyAttributeKind) 00473 PIkind); 00474 // Must re-establish the context from class extension to primary 00475 // class context. 00476 ContextRAII SavedContext(*this, CCPrimary); 00477 00478 Decl *ProtocolPtrTy = 00479 ActOnProperty(S, AtLoc, LParenLoc, FD, ProtocolPropertyODS, 00480 PIDecl->getGetterName(), 00481 PIDecl->getSetterName(), 00482 isOverridingProperty, 00483 MethodImplKind, 00484 /* lexicalDC = */ CDecl); 00485 PIDecl = cast<ObjCPropertyDecl>(ProtocolPtrTy); 00486 } 00487 PIDecl->makeitReadWriteAttribute(); 00488 if (Attributes & ObjCDeclSpec::DQ_PR_retain) 00489 PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_retain); 00490 if (Attributes & ObjCDeclSpec::DQ_PR_strong) 00491 PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_strong); 00492 if (Attributes & ObjCDeclSpec::DQ_PR_copy) 00493 PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_copy); 00494 PIDecl->setSetterName(SetterSel); 00495 } else { 00496 // Tailor the diagnostics for the common case where a readwrite 00497 // property is declared both in the @interface and the continuation. 00498 // This is a common error where the user often intended the original 00499 // declaration to be readonly. 00500 unsigned diag = 00501 (Attributes & ObjCDeclSpec::DQ_PR_readwrite) && 00502 (PIkind & ObjCPropertyDecl::OBJC_PR_readwrite) 00503 ? diag::err_use_continuation_class_redeclaration_readwrite 00504 : diag::err_use_continuation_class; 00505 Diag(AtLoc, diag) 00506 << CCPrimary->getDeclName(); 00507 Diag(PIDecl->getLocation(), diag::note_property_declare); 00508 return nullptr; 00509 } 00510 *isOverridingProperty = true; 00511 // Make sure setter decl is synthesized, and added to primary class's list. 00512 ProcessPropertyDecl(PIDecl, CCPrimary, PDecl, CDecl); 00513 PDecl->setGetterMethodDecl(PIDecl->getGetterMethodDecl()); 00514 PDecl->setSetterMethodDecl(PIDecl->getSetterMethodDecl()); 00515 if (ASTMutationListener *L = Context.getASTMutationListener()) 00516 L->AddedObjCPropertyInClassExtension(PDecl, PIDecl, CDecl); 00517 return PDecl; 00518 } 00519 00520 ObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S, 00521 ObjCContainerDecl *CDecl, 00522 SourceLocation AtLoc, 00523 SourceLocation LParenLoc, 00524 FieldDeclarator &FD, 00525 Selector GetterSel, 00526 Selector SetterSel, 00527 const bool isAssign, 00528 const bool isReadWrite, 00529 const unsigned Attributes, 00530 const unsigned AttributesAsWritten, 00531 TypeSourceInfo *TInfo, 00532 tok::ObjCKeywordKind MethodImplKind, 00533 DeclContext *lexicalDC){ 00534 IdentifierInfo *PropertyId = FD.D.getIdentifier(); 00535 QualType T = TInfo->getType(); 00536 00537 // Issue a warning if property is 'assign' as default and its object, which is 00538 // gc'able conforms to NSCopying protocol 00539 if (getLangOpts().getGC() != LangOptions::NonGC && 00540 isAssign && !(Attributes & ObjCDeclSpec::DQ_PR_assign)) 00541 if (const ObjCObjectPointerType *ObjPtrTy = 00542 T->getAs<ObjCObjectPointerType>()) { 00543 ObjCInterfaceDecl *IDecl = ObjPtrTy->getObjectType()->getInterface(); 00544 if (IDecl) 00545 if (ObjCProtocolDecl* PNSCopying = 00546 LookupProtocol(&Context.Idents.get("NSCopying"), AtLoc)) 00547 if (IDecl->ClassImplementsProtocol(PNSCopying, true)) 00548 Diag(AtLoc, diag::warn_implements_nscopying) << PropertyId; 00549 } 00550 00551 if (T->isObjCObjectType()) { 00552 SourceLocation StarLoc = TInfo->getTypeLoc().getLocEnd(); 00553 StarLoc = getLocForEndOfToken(StarLoc); 00554 Diag(FD.D.getIdentifierLoc(), diag::err_statically_allocated_object) 00555 << FixItHint::CreateInsertion(StarLoc, "*"); 00556 T = Context.getObjCObjectPointerType(T); 00557 SourceLocation TLoc = TInfo->getTypeLoc().getLocStart(); 00558 TInfo = Context.getTrivialTypeSourceInfo(T, TLoc); 00559 } 00560 00561 DeclContext *DC = cast<DeclContext>(CDecl); 00562 ObjCPropertyDecl *PDecl = ObjCPropertyDecl::Create(Context, DC, 00563 FD.D.getIdentifierLoc(), 00564 PropertyId, AtLoc, LParenLoc, TInfo); 00565 00566 if (ObjCPropertyDecl *prevDecl = 00567 ObjCPropertyDecl::findPropertyDecl(DC, PropertyId)) { 00568 Diag(PDecl->getLocation(), diag::err_duplicate_property); 00569 Diag(prevDecl->getLocation(), diag::note_property_declare); 00570 PDecl->setInvalidDecl(); 00571 } 00572 else { 00573 DC->addDecl(PDecl); 00574 if (lexicalDC) 00575 PDecl->setLexicalDeclContext(lexicalDC); 00576 } 00577 00578 if (T->isArrayType() || T->isFunctionType()) { 00579 Diag(AtLoc, diag::err_property_type) << T; 00580 PDecl->setInvalidDecl(); 00581 } 00582 00583 ProcessDeclAttributes(S, PDecl, FD.D); 00584 00585 // Regardless of setter/getter attribute, we save the default getter/setter 00586 // selector names in anticipation of declaration of setter/getter methods. 00587 PDecl->setGetterName(GetterSel); 00588 PDecl->setSetterName(SetterSel); 00589 PDecl->setPropertyAttributesAsWritten( 00590 makePropertyAttributesAsWritten(AttributesAsWritten)); 00591 00592 if (Attributes & ObjCDeclSpec::DQ_PR_readonly) 00593 PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readonly); 00594 00595 if (Attributes & ObjCDeclSpec::DQ_PR_getter) 00596 PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_getter); 00597 00598 if (Attributes & ObjCDeclSpec::DQ_PR_setter) 00599 PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_setter); 00600 00601 if (isReadWrite) 00602 PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readwrite); 00603 00604 if (Attributes & ObjCDeclSpec::DQ_PR_retain) 00605 PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_retain); 00606 00607 if (Attributes & ObjCDeclSpec::DQ_PR_strong) 00608 PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_strong); 00609 00610 if (Attributes & ObjCDeclSpec::DQ_PR_weak) 00611 PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_weak); 00612 00613 if (Attributes & ObjCDeclSpec::DQ_PR_copy) 00614 PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_copy); 00615 00616 if (Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained) 00617 PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_unsafe_unretained); 00618 00619 if (isAssign) 00620 PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_assign); 00621 00622 // In the semantic attributes, one of nonatomic or atomic is always set. 00623 if (Attributes & ObjCDeclSpec::DQ_PR_nonatomic) 00624 PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_nonatomic); 00625 else 00626 PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_atomic); 00627 00628 // 'unsafe_unretained' is alias for 'assign'. 00629 if (Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained) 00630 PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_assign); 00631 if (isAssign) 00632 PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_unsafe_unretained); 00633 00634 if (MethodImplKind == tok::objc_required) 00635 PDecl->setPropertyImplementation(ObjCPropertyDecl::Required); 00636 else if (MethodImplKind == tok::objc_optional) 00637 PDecl->setPropertyImplementation(ObjCPropertyDecl::Optional); 00638 00639 return PDecl; 00640 } 00641 00642 static void checkARCPropertyImpl(Sema &S, SourceLocation propertyImplLoc, 00643 ObjCPropertyDecl *property, 00644 ObjCIvarDecl *ivar) { 00645 if (property->isInvalidDecl() || ivar->isInvalidDecl()) return; 00646 00647 QualType ivarType = ivar->getType(); 00648 Qualifiers::ObjCLifetime ivarLifetime = ivarType.getObjCLifetime(); 00649 00650 // The lifetime implied by the property's attributes. 00651 Qualifiers::ObjCLifetime propertyLifetime = 00652 getImpliedARCOwnership(property->getPropertyAttributes(), 00653 property->getType()); 00654 00655 // We're fine if they match. 00656 if (propertyLifetime == ivarLifetime) return; 00657 00658 // These aren't valid lifetimes for object ivars; don't diagnose twice. 00659 if (ivarLifetime == Qualifiers::OCL_None || 00660 ivarLifetime == Qualifiers::OCL_Autoreleasing) 00661 return; 00662 00663 // If the ivar is private, and it's implicitly __unsafe_unretained 00664 // becaues of its type, then pretend it was actually implicitly 00665 // __strong. This is only sound because we're processing the 00666 // property implementation before parsing any method bodies. 00667 if (ivarLifetime == Qualifiers::OCL_ExplicitNone && 00668 propertyLifetime == Qualifiers::OCL_Strong && 00669 ivar->getAccessControl() == ObjCIvarDecl::Private) { 00670 SplitQualType split = ivarType.split(); 00671 if (split.Quals.hasObjCLifetime()) { 00672 assert(ivarType->isObjCARCImplicitlyUnretainedType()); 00673 split.Quals.setObjCLifetime(Qualifiers::OCL_Strong); 00674 ivarType = S.Context.getQualifiedType(split); 00675 ivar->setType(ivarType); 00676 return; 00677 } 00678 } 00679 00680 switch (propertyLifetime) { 00681 case Qualifiers::OCL_Strong: 00682 S.Diag(ivar->getLocation(), diag::err_arc_strong_property_ownership) 00683 << property->getDeclName() 00684 << ivar->getDeclName() 00685 << ivarLifetime; 00686 break; 00687 00688 case Qualifiers::OCL_Weak: 00689 S.Diag(ivar->getLocation(), diag::error_weak_property) 00690 << property->getDeclName() 00691 << ivar->getDeclName(); 00692 break; 00693 00694 case Qualifiers::OCL_ExplicitNone: 00695 S.Diag(ivar->getLocation(), diag::err_arc_assign_property_ownership) 00696 << property->getDeclName() 00697 << ivar->getDeclName() 00698 << ((property->getPropertyAttributesAsWritten() 00699 & ObjCPropertyDecl::OBJC_PR_assign) != 0); 00700 break; 00701 00702 case Qualifiers::OCL_Autoreleasing: 00703 llvm_unreachable("properties cannot be autoreleasing"); 00704 00705 case Qualifiers::OCL_None: 00706 // Any other property should be ignored. 00707 return; 00708 } 00709 00710 S.Diag(property->getLocation(), diag::note_property_declare); 00711 if (propertyImplLoc.isValid()) 00712 S.Diag(propertyImplLoc, diag::note_property_synthesize); 00713 } 00714 00715 /// setImpliedPropertyAttributeForReadOnlyProperty - 00716 /// This routine evaludates life-time attributes for a 'readonly' 00717 /// property with no known lifetime of its own, using backing 00718 /// 'ivar's attribute, if any. If no backing 'ivar', property's 00719 /// life-time is assumed 'strong'. 00720 static void setImpliedPropertyAttributeForReadOnlyProperty( 00721 ObjCPropertyDecl *property, ObjCIvarDecl *ivar) { 00722 Qualifiers::ObjCLifetime propertyLifetime = 00723 getImpliedARCOwnership(property->getPropertyAttributes(), 00724 property->getType()); 00725 if (propertyLifetime != Qualifiers::OCL_None) 00726 return; 00727 00728 if (!ivar) { 00729 // if no backing ivar, make property 'strong'. 00730 property->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_strong); 00731 return; 00732 } 00733 // property assumes owenership of backing ivar. 00734 QualType ivarType = ivar->getType(); 00735 Qualifiers::ObjCLifetime ivarLifetime = ivarType.getObjCLifetime(); 00736 if (ivarLifetime == Qualifiers::OCL_Strong) 00737 property->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_strong); 00738 else if (ivarLifetime == Qualifiers::OCL_Weak) 00739 property->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_weak); 00740 return; 00741 } 00742 00743 /// DiagnosePropertyMismatchDeclInProtocols - diagnose properties declared 00744 /// in inherited protocols with mismatched types. Since any of them can 00745 /// be candidate for synthesis. 00746 static void 00747 DiagnosePropertyMismatchDeclInProtocols(Sema &S, SourceLocation AtLoc, 00748 ObjCInterfaceDecl *ClassDecl, 00749 ObjCPropertyDecl *Property) { 00750 ObjCInterfaceDecl::ProtocolPropertyMap PropMap; 00751 for (const auto *PI : ClassDecl->all_referenced_protocols()) { 00752 if (const ObjCProtocolDecl *PDecl = PI->getDefinition()) 00753 PDecl->collectInheritedProtocolProperties(Property, PropMap); 00754 } 00755 if (ObjCInterfaceDecl *SDecl = ClassDecl->getSuperClass()) 00756 while (SDecl) { 00757 for (const auto *PI : SDecl->all_referenced_protocols()) { 00758 if (const ObjCProtocolDecl *PDecl = PI->getDefinition()) 00759 PDecl->collectInheritedProtocolProperties(Property, PropMap); 00760 } 00761 SDecl = SDecl->getSuperClass(); 00762 } 00763 00764 if (PropMap.empty()) 00765 return; 00766 00767 QualType RHSType = S.Context.getCanonicalType(Property->getType()); 00768 bool FirsTime = true; 00769 for (ObjCInterfaceDecl::ProtocolPropertyMap::iterator 00770 I = PropMap.begin(), E = PropMap.end(); I != E; I++) { 00771 ObjCPropertyDecl *Prop = I->second; 00772 QualType LHSType = S.Context.getCanonicalType(Prop->getType()); 00773 if (!S.Context.propertyTypesAreCompatible(LHSType, RHSType)) { 00774 bool IncompatibleObjC = false; 00775 QualType ConvertedType; 00776 if (!S.isObjCPointerConversion(RHSType, LHSType, ConvertedType, IncompatibleObjC) 00777 || IncompatibleObjC) { 00778 if (FirsTime) { 00779 S.Diag(Property->getLocation(), diag::warn_protocol_property_mismatch) 00780 << Property->getType(); 00781 FirsTime = false; 00782 } 00783 S.Diag(Prop->getLocation(), diag::note_protocol_property_declare) 00784 << Prop->getType(); 00785 } 00786 } 00787 } 00788 if (!FirsTime && AtLoc.isValid()) 00789 S.Diag(AtLoc, diag::note_property_synthesize); 00790 } 00791 00792 /// ActOnPropertyImplDecl - This routine performs semantic checks and 00793 /// builds the AST node for a property implementation declaration; declared 00794 /// as \@synthesize or \@dynamic. 00795 /// 00796 Decl *Sema::ActOnPropertyImplDecl(Scope *S, 00797 SourceLocation AtLoc, 00798 SourceLocation PropertyLoc, 00799 bool Synthesize, 00800 IdentifierInfo *PropertyId, 00801 IdentifierInfo *PropertyIvar, 00802 SourceLocation PropertyIvarLoc) { 00803 ObjCContainerDecl *ClassImpDecl = 00804 dyn_cast<ObjCContainerDecl>(CurContext); 00805 // Make sure we have a context for the property implementation declaration. 00806 if (!ClassImpDecl) { 00807 Diag(AtLoc, diag::error_missing_property_context); 00808 return nullptr; 00809 } 00810 if (PropertyIvarLoc.isInvalid()) 00811 PropertyIvarLoc = PropertyLoc; 00812 SourceLocation PropertyDiagLoc = PropertyLoc; 00813 if (PropertyDiagLoc.isInvalid()) 00814 PropertyDiagLoc = ClassImpDecl->getLocStart(); 00815 ObjCPropertyDecl *property = nullptr; 00816 ObjCInterfaceDecl *IDecl = nullptr; 00817 // Find the class or category class where this property must have 00818 // a declaration. 00819 ObjCImplementationDecl *IC = nullptr; 00820 ObjCCategoryImplDecl *CatImplClass = nullptr; 00821 if ((IC = dyn_cast<ObjCImplementationDecl>(ClassImpDecl))) { 00822 IDecl = IC->getClassInterface(); 00823 // We always synthesize an interface for an implementation 00824 // without an interface decl. So, IDecl is always non-zero. 00825 assert(IDecl && 00826 "ActOnPropertyImplDecl - @implementation without @interface"); 00827 00828 // Look for this property declaration in the @implementation's @interface 00829 property = IDecl->FindPropertyDeclaration(PropertyId); 00830 if (!property) { 00831 Diag(PropertyLoc, diag::error_bad_property_decl) << IDecl->getDeclName(); 00832 return nullptr; 00833 } 00834 unsigned PIkind = property->getPropertyAttributesAsWritten(); 00835 if ((PIkind & (ObjCPropertyDecl::OBJC_PR_atomic | 00836 ObjCPropertyDecl::OBJC_PR_nonatomic) ) == 0) { 00837 if (AtLoc.isValid()) 00838 Diag(AtLoc, diag::warn_implicit_atomic_property); 00839 else 00840 Diag(IC->getLocation(), diag::warn_auto_implicit_atomic_property); 00841 Diag(property->getLocation(), diag::note_property_declare); 00842 } 00843 00844 if (const ObjCCategoryDecl *CD = 00845 dyn_cast<ObjCCategoryDecl>(property->getDeclContext())) { 00846 if (!CD->IsClassExtension()) { 00847 Diag(PropertyLoc, diag::error_category_property) << CD->getDeclName(); 00848 Diag(property->getLocation(), diag::note_property_declare); 00849 return nullptr; 00850 } 00851 } 00852 if (Synthesize&& 00853 (PIkind & ObjCPropertyDecl::OBJC_PR_readonly) && 00854 property->hasAttr<IBOutletAttr>() && 00855 !AtLoc.isValid()) { 00856 bool ReadWriteProperty = false; 00857 // Search into the class extensions and see if 'readonly property is 00858 // redeclared 'readwrite', then no warning is to be issued. 00859 for (auto *Ext : IDecl->known_extensions()) { 00860 DeclContext::lookup_result R = Ext->lookup(property->getDeclName()); 00861 if (!R.empty()) 00862 if (ObjCPropertyDecl *ExtProp = dyn_cast<ObjCPropertyDecl>(R[0])) { 00863 PIkind = ExtProp->getPropertyAttributesAsWritten(); 00864 if (PIkind & ObjCPropertyDecl::OBJC_PR_readwrite) { 00865 ReadWriteProperty = true; 00866 break; 00867 } 00868 } 00869 } 00870 00871 if (!ReadWriteProperty) { 00872 Diag(property->getLocation(), diag::warn_auto_readonly_iboutlet_property) 00873 << property; 00874 SourceLocation readonlyLoc; 00875 if (LocPropertyAttribute(Context, "readonly", 00876 property->getLParenLoc(), readonlyLoc)) { 00877 SourceLocation endLoc = 00878 readonlyLoc.getLocWithOffset(strlen("readonly")-1); 00879 SourceRange ReadonlySourceRange(readonlyLoc, endLoc); 00880 Diag(property->getLocation(), 00881 diag::note_auto_readonly_iboutlet_fixup_suggest) << 00882 FixItHint::CreateReplacement(ReadonlySourceRange, "readwrite"); 00883 } 00884 } 00885 } 00886 if (Synthesize && isa<ObjCProtocolDecl>(property->getDeclContext())) 00887 DiagnosePropertyMismatchDeclInProtocols(*this, AtLoc, IDecl, property); 00888 00889 } else if ((CatImplClass = dyn_cast<ObjCCategoryImplDecl>(ClassImpDecl))) { 00890 if (Synthesize) { 00891 Diag(AtLoc, diag::error_synthesize_category_decl); 00892 return nullptr; 00893 } 00894 IDecl = CatImplClass->getClassInterface(); 00895 if (!IDecl) { 00896 Diag(AtLoc, diag::error_missing_property_interface); 00897 return nullptr; 00898 } 00899 ObjCCategoryDecl *Category = 00900 IDecl->FindCategoryDeclaration(CatImplClass->getIdentifier()); 00901 00902 // If category for this implementation not found, it is an error which 00903 // has already been reported eralier. 00904 if (!Category) 00905 return nullptr; 00906 // Look for this property declaration in @implementation's category 00907 property = Category->FindPropertyDeclaration(PropertyId); 00908 if (!property) { 00909 Diag(PropertyLoc, diag::error_bad_category_property_decl) 00910 << Category->getDeclName(); 00911 return nullptr; 00912 } 00913 } else { 00914 Diag(AtLoc, diag::error_bad_property_context); 00915 return nullptr; 00916 } 00917 ObjCIvarDecl *Ivar = nullptr; 00918 bool CompleteTypeErr = false; 00919 bool compat = true; 00920 // Check that we have a valid, previously declared ivar for @synthesize 00921 if (Synthesize) { 00922 // @synthesize 00923 if (!PropertyIvar) 00924 PropertyIvar = PropertyId; 00925 // Check that this is a previously declared 'ivar' in 'IDecl' interface 00926 ObjCInterfaceDecl *ClassDeclared; 00927 Ivar = IDecl->lookupInstanceVariable(PropertyIvar, ClassDeclared); 00928 QualType PropType = property->getType(); 00929 QualType PropertyIvarType = PropType.getNonReferenceType(); 00930 00931 if (RequireCompleteType(PropertyDiagLoc, PropertyIvarType, 00932 diag::err_incomplete_synthesized_property, 00933 property->getDeclName())) { 00934 Diag(property->getLocation(), diag::note_property_declare); 00935 CompleteTypeErr = true; 00936 } 00937 00938 if (getLangOpts().ObjCAutoRefCount && 00939 (property->getPropertyAttributesAsWritten() & 00940 ObjCPropertyDecl::OBJC_PR_readonly) && 00941 PropertyIvarType->isObjCRetainableType()) { 00942 setImpliedPropertyAttributeForReadOnlyProperty(property, Ivar); 00943 } 00944 00945 ObjCPropertyDecl::PropertyAttributeKind kind 00946 = property->getPropertyAttributes(); 00947 00948 // Add GC __weak to the ivar type if the property is weak. 00949 if ((kind & ObjCPropertyDecl::OBJC_PR_weak) && 00950 getLangOpts().getGC() != LangOptions::NonGC) { 00951 assert(!getLangOpts().ObjCAutoRefCount); 00952 if (PropertyIvarType.isObjCGCStrong()) { 00953 Diag(PropertyDiagLoc, diag::err_gc_weak_property_strong_type); 00954 Diag(property->getLocation(), diag::note_property_declare); 00955 } else { 00956 PropertyIvarType = 00957 Context.getObjCGCQualType(PropertyIvarType, Qualifiers::Weak); 00958 } 00959 } 00960 if (AtLoc.isInvalid()) { 00961 // Check when default synthesizing a property that there is 00962 // an ivar matching property name and issue warning; since this 00963 // is the most common case of not using an ivar used for backing 00964 // property in non-default synthesis case. 00965 ObjCInterfaceDecl *ClassDeclared=nullptr; 00966 ObjCIvarDecl *originalIvar = 00967 IDecl->lookupInstanceVariable(property->getIdentifier(), 00968 ClassDeclared); 00969 if (originalIvar) { 00970 Diag(PropertyDiagLoc, 00971 diag::warn_autosynthesis_property_ivar_match) 00972 << PropertyId << (Ivar == nullptr) << PropertyIvar 00973 << originalIvar->getIdentifier(); 00974 Diag(property->getLocation(), diag::note_property_declare); 00975 Diag(originalIvar->getLocation(), diag::note_ivar_decl); 00976 } 00977 } 00978 00979 if (!Ivar) { 00980 // In ARC, give the ivar a lifetime qualifier based on the 00981 // property attributes. 00982 if (getLangOpts().ObjCAutoRefCount && 00983 !PropertyIvarType.getObjCLifetime() && 00984 PropertyIvarType->isObjCRetainableType()) { 00985 00986 // It's an error if we have to do this and the user didn't 00987 // explicitly write an ownership attribute on the property. 00988 if (!property->hasWrittenStorageAttribute() && 00989 !(kind & ObjCPropertyDecl::OBJC_PR_strong)) { 00990 Diag(PropertyDiagLoc, 00991 diag::err_arc_objc_property_default_assign_on_object); 00992 Diag(property->getLocation(), diag::note_property_declare); 00993 } else { 00994 Qualifiers::ObjCLifetime lifetime = 00995 getImpliedARCOwnership(kind, PropertyIvarType); 00996 assert(lifetime && "no lifetime for property?"); 00997 if (lifetime == Qualifiers::OCL_Weak) { 00998 bool err = false; 00999 if (const ObjCObjectPointerType *ObjT = 01000 PropertyIvarType->getAs<ObjCObjectPointerType>()) { 01001 const ObjCInterfaceDecl *ObjI = ObjT->getInterfaceDecl(); 01002 if (ObjI && ObjI->isArcWeakrefUnavailable()) { 01003 Diag(property->getLocation(), 01004 diag::err_arc_weak_unavailable_property) << PropertyIvarType; 01005 Diag(ClassImpDecl->getLocation(), diag::note_implemented_by_class) 01006 << ClassImpDecl->getName(); 01007 err = true; 01008 } 01009 } 01010 if (!err && !getLangOpts().ObjCARCWeak) { 01011 Diag(PropertyDiagLoc, diag::err_arc_weak_no_runtime); 01012 Diag(property->getLocation(), diag::note_property_declare); 01013 } 01014 } 01015 01016 Qualifiers qs; 01017 qs.addObjCLifetime(lifetime); 01018 PropertyIvarType = Context.getQualifiedType(PropertyIvarType, qs); 01019 } 01020 } 01021 01022 if (kind & ObjCPropertyDecl::OBJC_PR_weak && 01023 !getLangOpts().ObjCAutoRefCount && 01024 getLangOpts().getGC() == LangOptions::NonGC) { 01025 Diag(PropertyDiagLoc, diag::error_synthesize_weak_non_arc_or_gc); 01026 Diag(property->getLocation(), diag::note_property_declare); 01027 } 01028 01029 Ivar = ObjCIvarDecl::Create(Context, ClassImpDecl, 01030 PropertyIvarLoc,PropertyIvarLoc, PropertyIvar, 01031 PropertyIvarType, /*Dinfo=*/nullptr, 01032 ObjCIvarDecl::Private, 01033 (Expr *)nullptr, true); 01034 if (RequireNonAbstractType(PropertyIvarLoc, 01035 PropertyIvarType, 01036 diag::err_abstract_type_in_decl, 01037 AbstractSynthesizedIvarType)) { 01038 Diag(property->getLocation(), diag::note_property_declare); 01039 Ivar->setInvalidDecl(); 01040 } else if (CompleteTypeErr) 01041 Ivar->setInvalidDecl(); 01042 ClassImpDecl->addDecl(Ivar); 01043 IDecl->makeDeclVisibleInContext(Ivar); 01044 01045 if (getLangOpts().ObjCRuntime.isFragile()) 01046 Diag(PropertyDiagLoc, diag::error_missing_property_ivar_decl) 01047 << PropertyId; 01048 // Note! I deliberately want it to fall thru so, we have a 01049 // a property implementation and to avoid future warnings. 01050 } else if (getLangOpts().ObjCRuntime.isNonFragile() && 01051 !declaresSameEntity(ClassDeclared, IDecl)) { 01052 Diag(PropertyDiagLoc, diag::error_ivar_in_superclass_use) 01053 << property->getDeclName() << Ivar->getDeclName() 01054 << ClassDeclared->getDeclName(); 01055 Diag(Ivar->getLocation(), diag::note_previous_access_declaration) 01056 << Ivar << Ivar->getName(); 01057 // Note! I deliberately want it to fall thru so more errors are caught. 01058 } 01059 property->setPropertyIvarDecl(Ivar); 01060 01061 QualType IvarType = Context.getCanonicalType(Ivar->getType()); 01062 01063 // Check that type of property and its ivar are type compatible. 01064 if (!Context.hasSameType(PropertyIvarType, IvarType)) { 01065 if (isa<ObjCObjectPointerType>(PropertyIvarType) 01066 && isa<ObjCObjectPointerType>(IvarType)) 01067 compat = 01068 Context.canAssignObjCInterfaces( 01069 PropertyIvarType->getAs<ObjCObjectPointerType>(), 01070 IvarType->getAs<ObjCObjectPointerType>()); 01071 else { 01072 compat = (CheckAssignmentConstraints(PropertyIvarLoc, PropertyIvarType, 01073 IvarType) 01074 == Compatible); 01075 } 01076 if (!compat) { 01077 Diag(PropertyDiagLoc, diag::error_property_ivar_type) 01078 << property->getDeclName() << PropType 01079 << Ivar->getDeclName() << IvarType; 01080 Diag(Ivar->getLocation(), diag::note_ivar_decl); 01081 // Note! I deliberately want it to fall thru so, we have a 01082 // a property implementation and to avoid future warnings. 01083 } 01084 else { 01085 // FIXME! Rules for properties are somewhat different that those 01086 // for assignments. Use a new routine to consolidate all cases; 01087 // specifically for property redeclarations as well as for ivars. 01088 QualType lhsType =Context.getCanonicalType(PropertyIvarType).getUnqualifiedType(); 01089 QualType rhsType =Context.getCanonicalType(IvarType).getUnqualifiedType(); 01090 if (lhsType != rhsType && 01091 lhsType->isArithmeticType()) { 01092 Diag(PropertyDiagLoc, diag::error_property_ivar_type) 01093 << property->getDeclName() << PropType 01094 << Ivar->getDeclName() << IvarType; 01095 Diag(Ivar->getLocation(), diag::note_ivar_decl); 01096 // Fall thru - see previous comment 01097 } 01098 } 01099 // __weak is explicit. So it works on Canonical type. 01100 if ((PropType.isObjCGCWeak() && !IvarType.isObjCGCWeak() && 01101 getLangOpts().getGC() != LangOptions::NonGC)) { 01102 Diag(PropertyDiagLoc, diag::error_weak_property) 01103 << property->getDeclName() << Ivar->getDeclName(); 01104 Diag(Ivar->getLocation(), diag::note_ivar_decl); 01105 // Fall thru - see previous comment 01106 } 01107 // Fall thru - see previous comment 01108 if ((property->getType()->isObjCObjectPointerType() || 01109 PropType.isObjCGCStrong()) && IvarType.isObjCGCWeak() && 01110 getLangOpts().getGC() != LangOptions::NonGC) { 01111 Diag(PropertyDiagLoc, diag::error_strong_property) 01112 << property->getDeclName() << Ivar->getDeclName(); 01113 // Fall thru - see previous comment 01114 } 01115 } 01116 if (getLangOpts().ObjCAutoRefCount) 01117 checkARCPropertyImpl(*this, PropertyLoc, property, Ivar); 01118 } else if (PropertyIvar) 01119 // @dynamic 01120 Diag(PropertyDiagLoc, diag::error_dynamic_property_ivar_decl); 01121 01122 assert (property && "ActOnPropertyImplDecl - property declaration missing"); 01123 ObjCPropertyImplDecl *PIDecl = 01124 ObjCPropertyImplDecl::Create(Context, CurContext, AtLoc, PropertyLoc, 01125 property, 01126 (Synthesize ? 01127 ObjCPropertyImplDecl::Synthesize 01128 : ObjCPropertyImplDecl::Dynamic), 01129 Ivar, PropertyIvarLoc); 01130 01131 if (CompleteTypeErr || !compat) 01132 PIDecl->setInvalidDecl(); 01133 01134 if (ObjCMethodDecl *getterMethod = property->getGetterMethodDecl()) { 01135 getterMethod->createImplicitParams(Context, IDecl); 01136 if (getLangOpts().CPlusPlus && Synthesize && !CompleteTypeErr && 01137 Ivar->getType()->isRecordType()) { 01138 // For Objective-C++, need to synthesize the AST for the IVAR object to be 01139 // returned by the getter as it must conform to C++'s copy-return rules. 01140 // FIXME. Eventually we want to do this for Objective-C as well. 01141 SynthesizedFunctionScope Scope(*this, getterMethod); 01142 ImplicitParamDecl *SelfDecl = getterMethod->getSelfDecl(); 01143 DeclRefExpr *SelfExpr = 01144 new (Context) DeclRefExpr(SelfDecl, false, SelfDecl->getType(), 01145 VK_LValue, PropertyDiagLoc); 01146 MarkDeclRefReferenced(SelfExpr); 01147 Expr *LoadSelfExpr = 01148 ImplicitCastExpr::Create(Context, SelfDecl->getType(), 01149 CK_LValueToRValue, SelfExpr, nullptr, 01150 VK_RValue); 01151 Expr *IvarRefExpr = 01152 new (Context) ObjCIvarRefExpr(Ivar, Ivar->getType(), PropertyDiagLoc, 01153 Ivar->getLocation(), 01154 LoadSelfExpr, true, true); 01155 ExprResult Res = PerformCopyInitialization( 01156 InitializedEntity::InitializeResult(PropertyDiagLoc, 01157 getterMethod->getReturnType(), 01158 /*NRVO=*/false), 01159 PropertyDiagLoc, IvarRefExpr); 01160 if (!Res.isInvalid()) { 01161 Expr *ResExpr = Res.getAs<Expr>(); 01162 if (ResExpr) 01163 ResExpr = MaybeCreateExprWithCleanups(ResExpr); 01164 PIDecl->setGetterCXXConstructor(ResExpr); 01165 } 01166 } 01167 if (property->hasAttr<NSReturnsNotRetainedAttr>() && 01168 !getterMethod->hasAttr<NSReturnsNotRetainedAttr>()) { 01169 Diag(getterMethod->getLocation(), 01170 diag::warn_property_getter_owning_mismatch); 01171 Diag(property->getLocation(), diag::note_property_declare); 01172 } 01173 if (getLangOpts().ObjCAutoRefCount && Synthesize) 01174 switch (getterMethod->getMethodFamily()) { 01175 case OMF_retain: 01176 case OMF_retainCount: 01177 case OMF_release: 01178 case OMF_autorelease: 01179 Diag(getterMethod->getLocation(), diag::err_arc_illegal_method_def) 01180 << 1 << getterMethod->getSelector(); 01181 break; 01182 default: 01183 break; 01184 } 01185 } 01186 if (ObjCMethodDecl *setterMethod = property->getSetterMethodDecl()) { 01187 setterMethod->createImplicitParams(Context, IDecl); 01188 if (getLangOpts().CPlusPlus && Synthesize && !CompleteTypeErr && 01189 Ivar->getType()->isRecordType()) { 01190 // FIXME. Eventually we want to do this for Objective-C as well. 01191 SynthesizedFunctionScope Scope(*this, setterMethod); 01192 ImplicitParamDecl *SelfDecl = setterMethod->getSelfDecl(); 01193 DeclRefExpr *SelfExpr = 01194 new (Context) DeclRefExpr(SelfDecl, false, SelfDecl->getType(), 01195 VK_LValue, PropertyDiagLoc); 01196 MarkDeclRefReferenced(SelfExpr); 01197 Expr *LoadSelfExpr = 01198 ImplicitCastExpr::Create(Context, SelfDecl->getType(), 01199 CK_LValueToRValue, SelfExpr, nullptr, 01200 VK_RValue); 01201 Expr *lhs = 01202 new (Context) ObjCIvarRefExpr(Ivar, Ivar->getType(), PropertyDiagLoc, 01203 Ivar->getLocation(), 01204 LoadSelfExpr, true, true); 01205 ObjCMethodDecl::param_iterator P = setterMethod->param_begin(); 01206 ParmVarDecl *Param = (*P); 01207 QualType T = Param->getType().getNonReferenceType(); 01208 DeclRefExpr *rhs = new (Context) DeclRefExpr(Param, false, T, 01209 VK_LValue, PropertyDiagLoc); 01210 MarkDeclRefReferenced(rhs); 01211 ExprResult Res = BuildBinOp(S, PropertyDiagLoc, 01212 BO_Assign, lhs, rhs); 01213 if (property->getPropertyAttributes() & 01214 ObjCPropertyDecl::OBJC_PR_atomic) { 01215 Expr *callExpr = Res.getAs<Expr>(); 01216 if (const CXXOperatorCallExpr *CXXCE = 01217 dyn_cast_or_null<CXXOperatorCallExpr>(callExpr)) 01218 if (const FunctionDecl *FuncDecl = CXXCE->getDirectCallee()) 01219 if (!FuncDecl->isTrivial()) 01220 if (property->getType()->isReferenceType()) { 01221 Diag(PropertyDiagLoc, 01222 diag::err_atomic_property_nontrivial_assign_op) 01223 << property->getType(); 01224 Diag(FuncDecl->getLocStart(), 01225 diag::note_callee_decl) << FuncDecl; 01226 } 01227 } 01228 PIDecl->setSetterCXXAssignment(Res.getAs<Expr>()); 01229 } 01230 } 01231 01232 if (IC) { 01233 if (Synthesize) 01234 if (ObjCPropertyImplDecl *PPIDecl = 01235 IC->FindPropertyImplIvarDecl(PropertyIvar)) { 01236 Diag(PropertyLoc, diag::error_duplicate_ivar_use) 01237 << PropertyId << PPIDecl->getPropertyDecl()->getIdentifier() 01238 << PropertyIvar; 01239 Diag(PPIDecl->getLocation(), diag::note_previous_use); 01240 } 01241 01242 if (ObjCPropertyImplDecl *PPIDecl 01243 = IC->FindPropertyImplDecl(PropertyId)) { 01244 Diag(PropertyLoc, diag::error_property_implemented) << PropertyId; 01245 Diag(PPIDecl->getLocation(), diag::note_previous_declaration); 01246 return nullptr; 01247 } 01248 IC->addPropertyImplementation(PIDecl); 01249 if (getLangOpts().ObjCDefaultSynthProperties && 01250 getLangOpts().ObjCRuntime.isNonFragile() && 01251 !IDecl->isObjCRequiresPropertyDefs()) { 01252 // Diagnose if an ivar was lazily synthesdized due to a previous 01253 // use and if 1) property is @dynamic or 2) property is synthesized 01254 // but it requires an ivar of different name. 01255 ObjCInterfaceDecl *ClassDeclared=nullptr; 01256 ObjCIvarDecl *Ivar = nullptr; 01257 if (!Synthesize) 01258 Ivar = IDecl->lookupInstanceVariable(PropertyId, ClassDeclared); 01259 else { 01260 if (PropertyIvar && PropertyIvar != PropertyId) 01261 Ivar = IDecl->lookupInstanceVariable(PropertyId, ClassDeclared); 01262 } 01263 // Issue diagnostics only if Ivar belongs to current class. 01264 if (Ivar && Ivar->getSynthesize() && 01265 declaresSameEntity(IC->getClassInterface(), ClassDeclared)) { 01266 Diag(Ivar->getLocation(), diag::err_undeclared_var_use) 01267 << PropertyId; 01268 Ivar->setInvalidDecl(); 01269 } 01270 } 01271 } else { 01272 if (Synthesize) 01273 if (ObjCPropertyImplDecl *PPIDecl = 01274 CatImplClass->FindPropertyImplIvarDecl(PropertyIvar)) { 01275 Diag(PropertyDiagLoc, diag::error_duplicate_ivar_use) 01276 << PropertyId << PPIDecl->getPropertyDecl()->getIdentifier() 01277 << PropertyIvar; 01278 Diag(PPIDecl->getLocation(), diag::note_previous_use); 01279 } 01280 01281 if (ObjCPropertyImplDecl *PPIDecl = 01282 CatImplClass->FindPropertyImplDecl(PropertyId)) { 01283 Diag(PropertyDiagLoc, diag::error_property_implemented) << PropertyId; 01284 Diag(PPIDecl->getLocation(), diag::note_previous_declaration); 01285 return nullptr; 01286 } 01287 CatImplClass->addPropertyImplementation(PIDecl); 01288 } 01289 01290 return PIDecl; 01291 } 01292 01293 //===----------------------------------------------------------------------===// 01294 // Helper methods. 01295 //===----------------------------------------------------------------------===// 01296 01297 /// DiagnosePropertyMismatch - Compares two properties for their 01298 /// attributes and types and warns on a variety of inconsistencies. 01299 /// 01300 void 01301 Sema::DiagnosePropertyMismatch(ObjCPropertyDecl *Property, 01302 ObjCPropertyDecl *SuperProperty, 01303 const IdentifierInfo *inheritedName, 01304 bool OverridingProtocolProperty) { 01305 ObjCPropertyDecl::PropertyAttributeKind CAttr = 01306 Property->getPropertyAttributes(); 01307 ObjCPropertyDecl::PropertyAttributeKind SAttr = 01308 SuperProperty->getPropertyAttributes(); 01309 01310 // We allow readonly properties without an explicit ownership 01311 // (assign/unsafe_unretained/weak/retain/strong/copy) in super class 01312 // to be overridden by a property with any explicit ownership in the subclass. 01313 if (!OverridingProtocolProperty && 01314 !getOwnershipRule(SAttr) && getOwnershipRule(CAttr)) 01315 ; 01316 else { 01317 if ((CAttr & ObjCPropertyDecl::OBJC_PR_readonly) 01318 && (SAttr & ObjCPropertyDecl::OBJC_PR_readwrite)) 01319 Diag(Property->getLocation(), diag::warn_readonly_property) 01320 << Property->getDeclName() << inheritedName; 01321 if ((CAttr & ObjCPropertyDecl::OBJC_PR_copy) 01322 != (SAttr & ObjCPropertyDecl::OBJC_PR_copy)) 01323 Diag(Property->getLocation(), diag::warn_property_attribute) 01324 << Property->getDeclName() << "copy" << inheritedName; 01325 else if (!(SAttr & ObjCPropertyDecl::OBJC_PR_readonly)){ 01326 unsigned CAttrRetain = 01327 (CAttr & 01328 (ObjCPropertyDecl::OBJC_PR_retain | ObjCPropertyDecl::OBJC_PR_strong)); 01329 unsigned SAttrRetain = 01330 (SAttr & 01331 (ObjCPropertyDecl::OBJC_PR_retain | ObjCPropertyDecl::OBJC_PR_strong)); 01332 bool CStrong = (CAttrRetain != 0); 01333 bool SStrong = (SAttrRetain != 0); 01334 if (CStrong != SStrong) 01335 Diag(Property->getLocation(), diag::warn_property_attribute) 01336 << Property->getDeclName() << "retain (or strong)" << inheritedName; 01337 } 01338 } 01339 01340 if ((CAttr & ObjCPropertyDecl::OBJC_PR_nonatomic) 01341 != (SAttr & ObjCPropertyDecl::OBJC_PR_nonatomic)) { 01342 Diag(Property->getLocation(), diag::warn_property_attribute) 01343 << Property->getDeclName() << "atomic" << inheritedName; 01344 Diag(SuperProperty->getLocation(), diag::note_property_declare); 01345 } 01346 if (Property->getSetterName() != SuperProperty->getSetterName()) { 01347 Diag(Property->getLocation(), diag::warn_property_attribute) 01348 << Property->getDeclName() << "setter" << inheritedName; 01349 Diag(SuperProperty->getLocation(), diag::note_property_declare); 01350 } 01351 if (Property->getGetterName() != SuperProperty->getGetterName()) { 01352 Diag(Property->getLocation(), diag::warn_property_attribute) 01353 << Property->getDeclName() << "getter" << inheritedName; 01354 Diag(SuperProperty->getLocation(), diag::note_property_declare); 01355 } 01356 01357 QualType LHSType = 01358 Context.getCanonicalType(SuperProperty->getType()); 01359 QualType RHSType = 01360 Context.getCanonicalType(Property->getType()); 01361 01362 if (!Context.propertyTypesAreCompatible(LHSType, RHSType)) { 01363 // Do cases not handled in above. 01364 // FIXME. For future support of covariant property types, revisit this. 01365 bool IncompatibleObjC = false; 01366 QualType ConvertedType; 01367 if (!isObjCPointerConversion(RHSType, LHSType, 01368 ConvertedType, IncompatibleObjC) || 01369 IncompatibleObjC) { 01370 Diag(Property->getLocation(), diag::warn_property_types_are_incompatible) 01371 << Property->getType() << SuperProperty->getType() << inheritedName; 01372 Diag(SuperProperty->getLocation(), diag::note_property_declare); 01373 } 01374 } 01375 } 01376 01377 bool Sema::DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *property, 01378 ObjCMethodDecl *GetterMethod, 01379 SourceLocation Loc) { 01380 if (!GetterMethod) 01381 return false; 01382 QualType GetterType = GetterMethod->getReturnType().getNonReferenceType(); 01383 QualType PropertyIvarType = property->getType().getNonReferenceType(); 01384 bool compat = Context.hasSameType(PropertyIvarType, GetterType); 01385 if (!compat) { 01386 if (isa<ObjCObjectPointerType>(PropertyIvarType) && 01387 isa<ObjCObjectPointerType>(GetterType)) 01388 compat = 01389 Context.canAssignObjCInterfaces( 01390 GetterType->getAs<ObjCObjectPointerType>(), 01391 PropertyIvarType->getAs<ObjCObjectPointerType>()); 01392 else if (CheckAssignmentConstraints(Loc, GetterType, PropertyIvarType) 01393 != Compatible) { 01394 Diag(Loc, diag::error_property_accessor_type) 01395 << property->getDeclName() << PropertyIvarType 01396 << GetterMethod->getSelector() << GetterType; 01397 Diag(GetterMethod->getLocation(), diag::note_declared_at); 01398 return true; 01399 } else { 01400 compat = true; 01401 QualType lhsType =Context.getCanonicalType(PropertyIvarType).getUnqualifiedType(); 01402 QualType rhsType =Context.getCanonicalType(GetterType).getUnqualifiedType(); 01403 if (lhsType != rhsType && lhsType->isArithmeticType()) 01404 compat = false; 01405 } 01406 } 01407 01408 if (!compat) { 01409 Diag(Loc, diag::warn_accessor_property_type_mismatch) 01410 << property->getDeclName() 01411 << GetterMethod->getSelector(); 01412 Diag(GetterMethod->getLocation(), diag::note_declared_at); 01413 return true; 01414 } 01415 01416 return false; 01417 } 01418 01419 /// CollectImmediateProperties - This routine collects all properties in 01420 /// the class and its conforming protocols; but not those in its super class. 01421 static void CollectImmediateProperties(ObjCContainerDecl *CDecl, 01422 ObjCContainerDecl::PropertyMap &PropMap, 01423 ObjCContainerDecl::PropertyMap &SuperPropMap, 01424 bool IncludeProtocols = true) { 01425 01426 if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl)) { 01427 for (auto *Prop : IDecl->properties()) 01428 PropMap[Prop->getIdentifier()] = Prop; 01429 if (IncludeProtocols) { 01430 // Scan through class's protocols. 01431 for (auto *PI : IDecl->all_referenced_protocols()) 01432 CollectImmediateProperties(PI, PropMap, SuperPropMap); 01433 } 01434 } 01435 if (ObjCCategoryDecl *CATDecl = dyn_cast<ObjCCategoryDecl>(CDecl)) { 01436 if (!CATDecl->IsClassExtension()) 01437 for (auto *Prop : CATDecl->properties()) 01438 PropMap[Prop->getIdentifier()] = Prop; 01439 if (IncludeProtocols) { 01440 // Scan through class's protocols. 01441 for (auto *PI : CATDecl->protocols()) 01442 CollectImmediateProperties(PI, PropMap, SuperPropMap); 01443 } 01444 } 01445 else if (ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(CDecl)) { 01446 for (auto *Prop : PDecl->properties()) { 01447 ObjCPropertyDecl *PropertyFromSuper = SuperPropMap[Prop->getIdentifier()]; 01448 // Exclude property for protocols which conform to class's super-class, 01449 // as super-class has to implement the property. 01450 if (!PropertyFromSuper || 01451 PropertyFromSuper->getIdentifier() != Prop->getIdentifier()) { 01452 ObjCPropertyDecl *&PropEntry = PropMap[Prop->getIdentifier()]; 01453 if (!PropEntry) 01454 PropEntry = Prop; 01455 } 01456 } 01457 // scan through protocol's protocols. 01458 for (auto *PI : PDecl->protocols()) 01459 CollectImmediateProperties(PI, PropMap, SuperPropMap); 01460 } 01461 } 01462 01463 /// CollectSuperClassPropertyImplementations - This routine collects list of 01464 /// properties to be implemented in super class(s) and also coming from their 01465 /// conforming protocols. 01466 static void CollectSuperClassPropertyImplementations(ObjCInterfaceDecl *CDecl, 01467 ObjCInterfaceDecl::PropertyMap &PropMap) { 01468 if (ObjCInterfaceDecl *SDecl = CDecl->getSuperClass()) { 01469 ObjCInterfaceDecl::PropertyDeclOrder PO; 01470 while (SDecl) { 01471 SDecl->collectPropertiesToImplement(PropMap, PO); 01472 SDecl = SDecl->getSuperClass(); 01473 } 01474 } 01475 } 01476 01477 /// IvarBacksCurrentMethodAccessor - This routine returns 'true' if 'IV' is 01478 /// an ivar synthesized for 'Method' and 'Method' is a property accessor 01479 /// declared in class 'IFace'. 01480 bool 01481 Sema::IvarBacksCurrentMethodAccessor(ObjCInterfaceDecl *IFace, 01482 ObjCMethodDecl *Method, ObjCIvarDecl *IV) { 01483 if (!IV->getSynthesize()) 01484 return false; 01485 ObjCMethodDecl *IMD = IFace->lookupMethod(Method->getSelector(), 01486 Method->isInstanceMethod()); 01487 if (!IMD || !IMD->isPropertyAccessor()) 01488 return false; 01489 01490 // look up a property declaration whose one of its accessors is implemented 01491 // by this method. 01492 for (const auto *Property : IFace->properties()) { 01493 if ((Property->getGetterName() == IMD->getSelector() || 01494 Property->getSetterName() == IMD->getSelector()) && 01495 (Property->getPropertyIvarDecl() == IV)) 01496 return true; 01497 } 01498 return false; 01499 } 01500 01501 static bool SuperClassImplementsProperty(ObjCInterfaceDecl *IDecl, 01502 ObjCPropertyDecl *Prop) { 01503 bool SuperClassImplementsGetter = false; 01504 bool SuperClassImplementsSetter = false; 01505 if (Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_readonly) 01506 SuperClassImplementsSetter = true; 01507 01508 while (IDecl->getSuperClass()) { 01509 ObjCInterfaceDecl *SDecl = IDecl->getSuperClass(); 01510 if (!SuperClassImplementsGetter && SDecl->getInstanceMethod(Prop->getGetterName())) 01511 SuperClassImplementsGetter = true; 01512 01513 if (!SuperClassImplementsSetter && SDecl->getInstanceMethod(Prop->getSetterName())) 01514 SuperClassImplementsSetter = true; 01515 if (SuperClassImplementsGetter && SuperClassImplementsSetter) 01516 return true; 01517 IDecl = IDecl->getSuperClass(); 01518 } 01519 return false; 01520 } 01521 01522 /// \brief Default synthesizes all properties which must be synthesized 01523 /// in class's \@implementation. 01524 void Sema::DefaultSynthesizeProperties(Scope *S, ObjCImplDecl* IMPDecl, 01525 ObjCInterfaceDecl *IDecl) { 01526 01527 ObjCInterfaceDecl::PropertyMap PropMap; 01528 ObjCInterfaceDecl::PropertyDeclOrder PropertyOrder; 01529 IDecl->collectPropertiesToImplement(PropMap, PropertyOrder); 01530 if (PropMap.empty()) 01531 return; 01532 ObjCInterfaceDecl::PropertyMap SuperPropMap; 01533 CollectSuperClassPropertyImplementations(IDecl, SuperPropMap); 01534 01535 for (unsigned i = 0, e = PropertyOrder.size(); i != e; i++) { 01536 ObjCPropertyDecl *Prop = PropertyOrder[i]; 01537 // Is there a matching property synthesize/dynamic? 01538 if (Prop->isInvalidDecl() || 01539 Prop->getPropertyImplementation() == ObjCPropertyDecl::Optional) 01540 continue; 01541 // Property may have been synthesized by user. 01542 if (IMPDecl->FindPropertyImplDecl(Prop->getIdentifier())) 01543 continue; 01544 if (IMPDecl->getInstanceMethod(Prop->getGetterName())) { 01545 if (Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_readonly) 01546 continue; 01547 if (IMPDecl->getInstanceMethod(Prop->getSetterName())) 01548 continue; 01549 } 01550 if (ObjCPropertyImplDecl *PID = 01551 IMPDecl->FindPropertyImplIvarDecl(Prop->getIdentifier())) { 01552 Diag(Prop->getLocation(), diag::warn_no_autosynthesis_shared_ivar_property) 01553 << Prop->getIdentifier(); 01554 if (!PID->getLocation().isInvalid()) 01555 Diag(PID->getLocation(), diag::note_property_synthesize); 01556 continue; 01557 } 01558 ObjCPropertyDecl *PropInSuperClass = SuperPropMap[Prop->getIdentifier()]; 01559 if (ObjCProtocolDecl *Proto = 01560 dyn_cast<ObjCProtocolDecl>(Prop->getDeclContext())) { 01561 // We won't auto-synthesize properties declared in protocols. 01562 // Suppress the warning if class's superclass implements property's 01563 // getter and implements property's setter (if readwrite property). 01564 // Or, if property is going to be implemented in its super class. 01565 if (!SuperClassImplementsProperty(IDecl, Prop) && !PropInSuperClass) { 01566 Diag(IMPDecl->getLocation(), 01567 diag::warn_auto_synthesizing_protocol_property) 01568 << Prop << Proto; 01569 Diag(Prop->getLocation(), diag::note_property_declare); 01570 } 01571 continue; 01572 } 01573 // If property to be implemented in the super class, ignore. 01574 if (PropInSuperClass) { 01575 if ((Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_readwrite) && 01576 (PropInSuperClass->getPropertyAttributes() & 01577 ObjCPropertyDecl::OBJC_PR_readonly) && 01578 !IMPDecl->getInstanceMethod(Prop->getSetterName()) && 01579 !IDecl->HasUserDeclaredSetterMethod(Prop)) { 01580 Diag(Prop->getLocation(), diag::warn_no_autosynthesis_property) 01581 << Prop->getIdentifier(); 01582 Diag(PropInSuperClass->getLocation(), diag::note_property_declare); 01583 } 01584 else { 01585 Diag(Prop->getLocation(), diag::warn_autosynthesis_property_in_superclass) 01586 << Prop->getIdentifier(); 01587 Diag(PropInSuperClass->getLocation(), diag::note_property_declare); 01588 Diag(IMPDecl->getLocation(), diag::note_while_in_implementation); 01589 } 01590 continue; 01591 } 01592 // We use invalid SourceLocations for the synthesized ivars since they 01593 // aren't really synthesized at a particular location; they just exist. 01594 // Saying that they are located at the @implementation isn't really going 01595 // to help users. 01596 ObjCPropertyImplDecl *PIDecl = dyn_cast_or_null<ObjCPropertyImplDecl>( 01597 ActOnPropertyImplDecl(S, SourceLocation(), SourceLocation(), 01598 true, 01599 /* property = */ Prop->getIdentifier(), 01600 /* ivar = */ Prop->getDefaultSynthIvarName(Context), 01601 Prop->getLocation())); 01602 if (PIDecl) { 01603 Diag(Prop->getLocation(), diag::warn_missing_explicit_synthesis); 01604 Diag(IMPDecl->getLocation(), diag::note_while_in_implementation); 01605 } 01606 } 01607 } 01608 01609 void Sema::DefaultSynthesizeProperties(Scope *S, Decl *D) { 01610 if (!LangOpts.ObjCDefaultSynthProperties || LangOpts.ObjCRuntime.isFragile()) 01611 return; 01612 ObjCImplementationDecl *IC=dyn_cast_or_null<ObjCImplementationDecl>(D); 01613 if (!IC) 01614 return; 01615 if (ObjCInterfaceDecl* IDecl = IC->getClassInterface()) 01616 if (!IDecl->isObjCRequiresPropertyDefs()) 01617 DefaultSynthesizeProperties(S, IC, IDecl); 01618 } 01619 01620 static void DiagnoseUnimplementedAccessor(Sema &S, 01621 ObjCInterfaceDecl *PrimaryClass, 01622 Selector Method, 01623 ObjCImplDecl* IMPDecl, 01624 ObjCContainerDecl *CDecl, 01625 ObjCCategoryDecl *C, 01626 ObjCPropertyDecl *Prop, 01627 Sema::SelectorSet &SMap) { 01628 // When reporting on missing property setter/getter implementation in 01629 // categories, do not report when they are declared in primary class, 01630 // class's protocol, or one of it super classes. This is because, 01631 // the class is going to implement them. 01632 if (!SMap.count(Method) && 01633 (PrimaryClass == nullptr || 01634 !PrimaryClass->lookupPropertyAccessor(Method, C))) { 01635 S.Diag(IMPDecl->getLocation(), 01636 isa<ObjCCategoryDecl>(CDecl) ? 01637 diag::warn_setter_getter_impl_required_in_category : 01638 diag::warn_setter_getter_impl_required) 01639 << Prop->getDeclName() << Method; 01640 S.Diag(Prop->getLocation(), 01641 diag::note_property_declare); 01642 if (S.LangOpts.ObjCDefaultSynthProperties && 01643 S.LangOpts.ObjCRuntime.isNonFragile()) 01644 if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(CDecl)) 01645 if (const ObjCInterfaceDecl *RID = ID->isObjCRequiresPropertyDefs()) 01646 S.Diag(RID->getLocation(), diag::note_suppressed_class_declare); 01647 } 01648 } 01649 01650 void Sema::DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl, 01651 ObjCContainerDecl *CDecl, 01652 bool SynthesizeProperties) { 01653 ObjCContainerDecl::PropertyMap PropMap; 01654 ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl); 01655 01656 if (!SynthesizeProperties) { 01657 ObjCContainerDecl::PropertyMap NoNeedToImplPropMap; 01658 // Gather properties which need not be implemented in this class 01659 // or category. 01660 if (!IDecl) 01661 if (ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl)) { 01662 // For categories, no need to implement properties declared in 01663 // its primary class (and its super classes) if property is 01664 // declared in one of those containers. 01665 if ((IDecl = C->getClassInterface())) { 01666 ObjCInterfaceDecl::PropertyDeclOrder PO; 01667 IDecl->collectPropertiesToImplement(NoNeedToImplPropMap, PO); 01668 } 01669 } 01670 if (IDecl) 01671 CollectSuperClassPropertyImplementations(IDecl, NoNeedToImplPropMap); 01672 01673 CollectImmediateProperties(CDecl, PropMap, NoNeedToImplPropMap); 01674 } 01675 01676 // Scan the @interface to see if any of the protocols it adopts 01677 // require an explicit implementation, via attribute 01678 // 'objc_protocol_requires_explicit_implementation'. 01679 if (IDecl) { 01680 std::unique_ptr<ObjCContainerDecl::PropertyMap> LazyMap; 01681 01682 for (auto *PDecl : IDecl->all_referenced_protocols()) { 01683 if (!PDecl->hasAttr<ObjCExplicitProtocolImplAttr>()) 01684 continue; 01685 // Lazily construct a set of all the properties in the @interface 01686 // of the class, without looking at the superclass. We cannot 01687 // use the call to CollectImmediateProperties() above as that 01688 // utilizes information from the super class's properties as well 01689 // as scans the adopted protocols. This work only triggers for protocols 01690 // with the attribute, which is very rare, and only occurs when 01691 // analyzing the @implementation. 01692 if (!LazyMap) { 01693 ObjCContainerDecl::PropertyMap NoNeedToImplPropMap; 01694 LazyMap.reset(new ObjCContainerDecl::PropertyMap()); 01695 CollectImmediateProperties(CDecl, *LazyMap, NoNeedToImplPropMap, 01696 /* IncludeProtocols */ false); 01697 } 01698 // Add the properties of 'PDecl' to the list of properties that 01699 // need to be implemented. 01700 for (auto *PropDecl : PDecl->properties()) { 01701 if ((*LazyMap)[PropDecl->getIdentifier()]) 01702 continue; 01703 PropMap[PropDecl->getIdentifier()] = PropDecl; 01704 } 01705 } 01706 } 01707 01708 if (PropMap.empty()) 01709 return; 01710 01711 llvm::DenseSet<ObjCPropertyDecl *> PropImplMap; 01712 for (const auto *I : IMPDecl->property_impls()) 01713 PropImplMap.insert(I->getPropertyDecl()); 01714 01715 SelectorSet InsMap; 01716 // Collect property accessors implemented in current implementation. 01717 for (const auto *I : IMPDecl->instance_methods()) 01718 InsMap.insert(I->getSelector()); 01719 01720 ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl); 01721 ObjCInterfaceDecl *PrimaryClass = nullptr; 01722 if (C && !C->IsClassExtension()) 01723 if ((PrimaryClass = C->getClassInterface())) 01724 // Report unimplemented properties in the category as well. 01725 if (ObjCImplDecl *IMP = PrimaryClass->getImplementation()) { 01726 // When reporting on missing setter/getters, do not report when 01727 // setter/getter is implemented in category's primary class 01728 // implementation. 01729 for (const auto *I : IMP->instance_methods()) 01730 InsMap.insert(I->getSelector()); 01731 } 01732 01733 for (ObjCContainerDecl::PropertyMap::iterator 01734 P = PropMap.begin(), E = PropMap.end(); P != E; ++P) { 01735 ObjCPropertyDecl *Prop = P->second; 01736 // Is there a matching propery synthesize/dynamic? 01737 if (Prop->isInvalidDecl() || 01738 Prop->getPropertyImplementation() == ObjCPropertyDecl::Optional || 01739 PropImplMap.count(Prop) || 01740 Prop->getAvailability() == AR_Unavailable) 01741 continue; 01742 01743 // Diagnose unimplemented getters and setters. 01744 DiagnoseUnimplementedAccessor(*this, 01745 PrimaryClass, Prop->getGetterName(), IMPDecl, CDecl, C, Prop, InsMap); 01746 if (!Prop->isReadOnly()) 01747 DiagnoseUnimplementedAccessor(*this, 01748 PrimaryClass, Prop->getSetterName(), 01749 IMPDecl, CDecl, C, Prop, InsMap); 01750 } 01751 } 01752 01753 void 01754 Sema::AtomicPropertySetterGetterRules (ObjCImplDecl* IMPDecl, 01755 ObjCContainerDecl* IDecl) { 01756 // Rules apply in non-GC mode only 01757 if (getLangOpts().getGC() != LangOptions::NonGC) 01758 return; 01759 for (const auto *Property : IDecl->properties()) { 01760 ObjCMethodDecl *GetterMethod = nullptr; 01761 ObjCMethodDecl *SetterMethod = nullptr; 01762 bool LookedUpGetterSetter = false; 01763 01764 unsigned Attributes = Property->getPropertyAttributes(); 01765 unsigned AttributesAsWritten = Property->getPropertyAttributesAsWritten(); 01766 01767 if (!(AttributesAsWritten & ObjCPropertyDecl::OBJC_PR_atomic) && 01768 !(AttributesAsWritten & ObjCPropertyDecl::OBJC_PR_nonatomic)) { 01769 GetterMethod = IMPDecl->getInstanceMethod(Property->getGetterName()); 01770 SetterMethod = IMPDecl->getInstanceMethod(Property->getSetterName()); 01771 LookedUpGetterSetter = true; 01772 if (GetterMethod) { 01773 Diag(GetterMethod->getLocation(), 01774 diag::warn_default_atomic_custom_getter_setter) 01775 << Property->getIdentifier() << 0; 01776 Diag(Property->getLocation(), diag::note_property_declare); 01777 } 01778 if (SetterMethod) { 01779 Diag(SetterMethod->getLocation(), 01780 diag::warn_default_atomic_custom_getter_setter) 01781 << Property->getIdentifier() << 1; 01782 Diag(Property->getLocation(), diag::note_property_declare); 01783 } 01784 } 01785 01786 // We only care about readwrite atomic property. 01787 if ((Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic) || 01788 !(Attributes & ObjCPropertyDecl::OBJC_PR_readwrite)) 01789 continue; 01790 if (const ObjCPropertyImplDecl *PIDecl 01791 = IMPDecl->FindPropertyImplDecl(Property->getIdentifier())) { 01792 if (PIDecl->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) 01793 continue; 01794 if (!LookedUpGetterSetter) { 01795 GetterMethod = IMPDecl->getInstanceMethod(Property->getGetterName()); 01796 SetterMethod = IMPDecl->getInstanceMethod(Property->getSetterName()); 01797 } 01798 if ((GetterMethod && !SetterMethod) || (!GetterMethod && SetterMethod)) { 01799 SourceLocation MethodLoc = 01800 (GetterMethod ? GetterMethod->getLocation() 01801 : SetterMethod->getLocation()); 01802 Diag(MethodLoc, diag::warn_atomic_property_rule) 01803 << Property->getIdentifier() << (GetterMethod != nullptr) 01804 << (SetterMethod != nullptr); 01805 // fixit stuff. 01806 if (!AttributesAsWritten) { 01807 if (Property->getLParenLoc().isValid()) { 01808 // @property () ... case. 01809 SourceRange PropSourceRange(Property->getAtLoc(), 01810 Property->getLParenLoc()); 01811 Diag(Property->getLocation(), diag::note_atomic_property_fixup_suggest) << 01812 FixItHint::CreateReplacement(PropSourceRange, "@property (nonatomic"); 01813 } 01814 else { 01815 //@property id etc. 01816 SourceLocation endLoc = 01817 Property->getTypeSourceInfo()->getTypeLoc().getBeginLoc(); 01818 endLoc = endLoc.getLocWithOffset(-1); 01819 SourceRange PropSourceRange(Property->getAtLoc(), endLoc); 01820 Diag(Property->getLocation(), diag::note_atomic_property_fixup_suggest) << 01821 FixItHint::CreateReplacement(PropSourceRange, "@property (nonatomic) "); 01822 } 01823 } 01824 else if (!(AttributesAsWritten & ObjCPropertyDecl::OBJC_PR_atomic)) { 01825 // @property () ... case. 01826 SourceLocation endLoc = Property->getLParenLoc(); 01827 SourceRange PropSourceRange(Property->getAtLoc(), endLoc); 01828 Diag(Property->getLocation(), diag::note_atomic_property_fixup_suggest) << 01829 FixItHint::CreateReplacement(PropSourceRange, "@property (nonatomic, "); 01830 } 01831 else 01832 Diag(MethodLoc, diag::note_atomic_property_fixup_suggest); 01833 Diag(Property->getLocation(), diag::note_property_declare); 01834 } 01835 } 01836 } 01837 } 01838 01839 void Sema::DiagnoseOwningPropertyGetterSynthesis(const ObjCImplementationDecl *D) { 01840 if (getLangOpts().getGC() == LangOptions::GCOnly) 01841 return; 01842 01843 for (const auto *PID : D->property_impls()) { 01844 const ObjCPropertyDecl *PD = PID->getPropertyDecl(); 01845 if (PD && !PD->hasAttr<NSReturnsNotRetainedAttr>() && 01846 !D->getInstanceMethod(PD->getGetterName())) { 01847 ObjCMethodDecl *method = PD->getGetterMethodDecl(); 01848 if (!method) 01849 continue; 01850 ObjCMethodFamily family = method->getMethodFamily(); 01851 if (family == OMF_alloc || family == OMF_copy || 01852 family == OMF_mutableCopy || family == OMF_new) { 01853 if (getLangOpts().ObjCAutoRefCount) 01854 Diag(PD->getLocation(), diag::err_cocoa_naming_owned_rule); 01855 else 01856 Diag(PD->getLocation(), diag::warn_cocoa_naming_owned_rule); 01857 } 01858 } 01859 } 01860 } 01861 01862 void Sema::DiagnoseMissingDesignatedInitOverrides( 01863 const ObjCImplementationDecl *ImplD, 01864 const ObjCInterfaceDecl *IFD) { 01865 assert(IFD->hasDesignatedInitializers()); 01866 const ObjCInterfaceDecl *SuperD = IFD->getSuperClass(); 01867 if (!SuperD) 01868 return; 01869 01870 SelectorSet InitSelSet; 01871 for (const auto *I : ImplD->instance_methods()) 01872 if (I->getMethodFamily() == OMF_init) 01873 InitSelSet.insert(I->getSelector()); 01874 01875 SmallVector<const ObjCMethodDecl *, 8> DesignatedInits; 01876 SuperD->getDesignatedInitializers(DesignatedInits); 01877 for (SmallVector<const ObjCMethodDecl *, 8>::iterator 01878 I = DesignatedInits.begin(), E = DesignatedInits.end(); I != E; ++I) { 01879 const ObjCMethodDecl *MD = *I; 01880 if (!InitSelSet.count(MD->getSelector())) { 01881 Diag(ImplD->getLocation(), 01882 diag::warn_objc_implementation_missing_designated_init_override) 01883 << MD->getSelector(); 01884 Diag(MD->getLocation(), diag::note_objc_designated_init_marked_here); 01885 } 01886 } 01887 } 01888 01889 /// AddPropertyAttrs - Propagates attributes from a property to the 01890 /// implicitly-declared getter or setter for that property. 01891 static void AddPropertyAttrs(Sema &S, ObjCMethodDecl *PropertyMethod, 01892 ObjCPropertyDecl *Property) { 01893 // Should we just clone all attributes over? 01894 for (const auto *A : Property->attrs()) { 01895 if (isa<DeprecatedAttr>(A) || 01896 isa<UnavailableAttr>(A) || 01897 isa<AvailabilityAttr>(A)) 01898 PropertyMethod->addAttr(A->clone(S.Context)); 01899 } 01900 } 01901 01902 /// ProcessPropertyDecl - Make sure that any user-defined setter/getter methods 01903 /// have the property type and issue diagnostics if they don't. 01904 /// Also synthesize a getter/setter method if none exist (and update the 01905 /// appropriate lookup tables. FIXME: Should reconsider if adding synthesized 01906 /// methods is the "right" thing to do. 01907 void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property, 01908 ObjCContainerDecl *CD, 01909 ObjCPropertyDecl *redeclaredProperty, 01910 ObjCContainerDecl *lexicalDC) { 01911 01912 ObjCMethodDecl *GetterMethod, *SetterMethod; 01913 01914 if (CD->isInvalidDecl()) 01915 return; 01916 01917 GetterMethod = CD->getInstanceMethod(property->getGetterName()); 01918 SetterMethod = CD->getInstanceMethod(property->getSetterName()); 01919 DiagnosePropertyAccessorMismatch(property, GetterMethod, 01920 property->getLocation()); 01921 01922 if (SetterMethod) { 01923 ObjCPropertyDecl::PropertyAttributeKind CAttr = 01924 property->getPropertyAttributes(); 01925 if ((!(CAttr & ObjCPropertyDecl::OBJC_PR_readonly)) && 01926 Context.getCanonicalType(SetterMethod->getReturnType()) != 01927 Context.VoidTy) 01928 Diag(SetterMethod->getLocation(), diag::err_setter_type_void); 01929 if (SetterMethod->param_size() != 1 || 01930 !Context.hasSameUnqualifiedType( 01931 (*SetterMethod->param_begin())->getType().getNonReferenceType(), 01932 property->getType().getNonReferenceType())) { 01933 Diag(property->getLocation(), 01934 diag::warn_accessor_property_type_mismatch) 01935 << property->getDeclName() 01936 << SetterMethod->getSelector(); 01937 Diag(SetterMethod->getLocation(), diag::note_declared_at); 01938 } 01939 } 01940 01941 // Synthesize getter/setter methods if none exist. 01942 // Find the default getter and if one not found, add one. 01943 // FIXME: The synthesized property we set here is misleading. We almost always 01944 // synthesize these methods unless the user explicitly provided prototypes 01945 // (which is odd, but allowed). Sema should be typechecking that the 01946 // declarations jive in that situation (which it is not currently). 01947 if (!GetterMethod) { 01948 // No instance method of same name as property getter name was found. 01949 // Declare a getter method and add it to the list of methods 01950 // for this class. 01951 SourceLocation Loc = redeclaredProperty ? 01952 redeclaredProperty->getLocation() : 01953 property->getLocation(); 01954 01955 GetterMethod = ObjCMethodDecl::Create(Context, Loc, Loc, 01956 property->getGetterName(), 01957 property->getType(), nullptr, CD, 01958 /*isInstance=*/true, /*isVariadic=*/false, 01959 /*isPropertyAccessor=*/true, 01960 /*isImplicitlyDeclared=*/true, /*isDefined=*/false, 01961 (property->getPropertyImplementation() == 01962 ObjCPropertyDecl::Optional) ? 01963 ObjCMethodDecl::Optional : 01964 ObjCMethodDecl::Required); 01965 CD->addDecl(GetterMethod); 01966 01967 AddPropertyAttrs(*this, GetterMethod, property); 01968 01969 // FIXME: Eventually this shouldn't be needed, as the lexical context 01970 // and the real context should be the same. 01971 if (lexicalDC) 01972 GetterMethod->setLexicalDeclContext(lexicalDC); 01973 if (property->hasAttr<NSReturnsNotRetainedAttr>()) 01974 GetterMethod->addAttr(NSReturnsNotRetainedAttr::CreateImplicit(Context, 01975 Loc)); 01976 01977 if (property->hasAttr<ObjCReturnsInnerPointerAttr>()) 01978 GetterMethod->addAttr( 01979 ObjCReturnsInnerPointerAttr::CreateImplicit(Context, Loc)); 01980 01981 if (const SectionAttr *SA = property->getAttr<SectionAttr>()) 01982 GetterMethod->addAttr( 01983 SectionAttr::CreateImplicit(Context, SectionAttr::GNU_section, 01984 SA->getName(), Loc)); 01985 01986 if (getLangOpts().ObjCAutoRefCount) 01987 CheckARCMethodDecl(GetterMethod); 01988 } else 01989 // A user declared getter will be synthesize when @synthesize of 01990 // the property with the same name is seen in the @implementation 01991 GetterMethod->setPropertyAccessor(true); 01992 property->setGetterMethodDecl(GetterMethod); 01993 01994 // Skip setter if property is read-only. 01995 if (!property->isReadOnly()) { 01996 // Find the default setter and if one not found, add one. 01997 if (!SetterMethod) { 01998 // No instance method of same name as property setter name was found. 01999 // Declare a setter method and add it to the list of methods 02000 // for this class. 02001 SourceLocation Loc = redeclaredProperty ? 02002 redeclaredProperty->getLocation() : 02003 property->getLocation(); 02004 02005 SetterMethod = 02006 ObjCMethodDecl::Create(Context, Loc, Loc, 02007 property->getSetterName(), Context.VoidTy, 02008 nullptr, CD, /*isInstance=*/true, 02009 /*isVariadic=*/false, 02010 /*isPropertyAccessor=*/true, 02011 /*isImplicitlyDeclared=*/true, 02012 /*isDefined=*/false, 02013 (property->getPropertyImplementation() == 02014 ObjCPropertyDecl::Optional) ? 02015 ObjCMethodDecl::Optional : 02016 ObjCMethodDecl::Required); 02017 02018 // Invent the arguments for the setter. We don't bother making a 02019 // nice name for the argument. 02020 ParmVarDecl *Argument = ParmVarDecl::Create(Context, SetterMethod, 02021 Loc, Loc, 02022 property->getIdentifier(), 02023 property->getType().getUnqualifiedType(), 02024 /*TInfo=*/nullptr, 02025 SC_None, 02026 nullptr); 02027 SetterMethod->setMethodParams(Context, Argument, None); 02028 02029 AddPropertyAttrs(*this, SetterMethod, property); 02030 02031 CD->addDecl(SetterMethod); 02032 // FIXME: Eventually this shouldn't be needed, as the lexical context 02033 // and the real context should be the same. 02034 if (lexicalDC) 02035 SetterMethod->setLexicalDeclContext(lexicalDC); 02036 if (const SectionAttr *SA = property->getAttr<SectionAttr>()) 02037 SetterMethod->addAttr( 02038 SectionAttr::CreateImplicit(Context, SectionAttr::GNU_section, 02039 SA->getName(), Loc)); 02040 // It's possible for the user to have set a very odd custom 02041 // setter selector that causes it to have a method family. 02042 if (getLangOpts().ObjCAutoRefCount) 02043 CheckARCMethodDecl(SetterMethod); 02044 } else 02045 // A user declared setter will be synthesize when @synthesize of 02046 // the property with the same name is seen in the @implementation 02047 SetterMethod->setPropertyAccessor(true); 02048 property->setSetterMethodDecl(SetterMethod); 02049 } 02050 // Add any synthesized methods to the global pool. This allows us to 02051 // handle the following, which is supported by GCC (and part of the design). 02052 // 02053 // @interface Foo 02054 // @property double bar; 02055 // @end 02056 // 02057 // void thisIsUnfortunate() { 02058 // id foo; 02059 // double bar = [foo bar]; 02060 // } 02061 // 02062 if (GetterMethod) 02063 AddInstanceMethodToGlobalPool(GetterMethod); 02064 if (SetterMethod) 02065 AddInstanceMethodToGlobalPool(SetterMethod); 02066 02067 ObjCInterfaceDecl *CurrentClass = dyn_cast<ObjCInterfaceDecl>(CD); 02068 if (!CurrentClass) { 02069 if (ObjCCategoryDecl *Cat = dyn_cast<ObjCCategoryDecl>(CD)) 02070 CurrentClass = Cat->getClassInterface(); 02071 else if (ObjCImplDecl *Impl = dyn_cast<ObjCImplDecl>(CD)) 02072 CurrentClass = Impl->getClassInterface(); 02073 } 02074 if (GetterMethod) 02075 CheckObjCMethodOverrides(GetterMethod, CurrentClass, Sema::RTC_Unknown); 02076 if (SetterMethod) 02077 CheckObjCMethodOverrides(SetterMethod, CurrentClass, Sema::RTC_Unknown); 02078 } 02079 02080 void Sema::CheckObjCPropertyAttributes(Decl *PDecl, 02081 SourceLocation Loc, 02082 unsigned &Attributes, 02083 bool propertyInPrimaryClass) { 02084 // FIXME: Improve the reported location. 02085 if (!PDecl || PDecl->isInvalidDecl()) 02086 return; 02087 02088 if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) && 02089 (Attributes & ObjCDeclSpec::DQ_PR_readwrite)) 02090 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 02091 << "readonly" << "readwrite"; 02092 02093 ObjCPropertyDecl *PropertyDecl = cast<ObjCPropertyDecl>(PDecl); 02094 QualType PropertyTy = PropertyDecl->getType(); 02095 unsigned PropertyOwnership = getOwnershipRule(Attributes); 02096 02097 // 'readonly' property with no obvious lifetime. 02098 // its life time will be determined by its backing ivar. 02099 if (getLangOpts().ObjCAutoRefCount && 02100 Attributes & ObjCDeclSpec::DQ_PR_readonly && 02101 PropertyTy->isObjCRetainableType() && 02102 !PropertyOwnership) 02103 return; 02104 02105 // Check for copy or retain on non-object types. 02106 if ((Attributes & (ObjCDeclSpec::DQ_PR_weak | ObjCDeclSpec::DQ_PR_copy | 02107 ObjCDeclSpec::DQ_PR_retain | ObjCDeclSpec::DQ_PR_strong)) && 02108 !PropertyTy->isObjCRetainableType() && 02109 !PropertyDecl->hasAttr<ObjCNSObjectAttr>()) { 02110 Diag(Loc, diag::err_objc_property_requires_object) 02111 << (Attributes & ObjCDeclSpec::DQ_PR_weak ? "weak" : 02112 Attributes & ObjCDeclSpec::DQ_PR_copy ? "copy" : "retain (or strong)"); 02113 Attributes &= ~(ObjCDeclSpec::DQ_PR_weak | ObjCDeclSpec::DQ_PR_copy | 02114 ObjCDeclSpec::DQ_PR_retain | ObjCDeclSpec::DQ_PR_strong); 02115 PropertyDecl->setInvalidDecl(); 02116 } 02117 02118 // Check for more than one of { assign, copy, retain }. 02119 if (Attributes & ObjCDeclSpec::DQ_PR_assign) { 02120 if (Attributes & ObjCDeclSpec::DQ_PR_copy) { 02121 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 02122 << "assign" << "copy"; 02123 Attributes &= ~ObjCDeclSpec::DQ_PR_copy; 02124 } 02125 if (Attributes & ObjCDeclSpec::DQ_PR_retain) { 02126 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 02127 << "assign" << "retain"; 02128 Attributes &= ~ObjCDeclSpec::DQ_PR_retain; 02129 } 02130 if (Attributes & ObjCDeclSpec::DQ_PR_strong) { 02131 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 02132 << "assign" << "strong"; 02133 Attributes &= ~ObjCDeclSpec::DQ_PR_strong; 02134 } 02135 if (getLangOpts().ObjCAutoRefCount && 02136 (Attributes & ObjCDeclSpec::DQ_PR_weak)) { 02137 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 02138 << "assign" << "weak"; 02139 Attributes &= ~ObjCDeclSpec::DQ_PR_weak; 02140 } 02141 if (PropertyDecl->hasAttr<IBOutletCollectionAttr>()) 02142 Diag(Loc, diag::warn_iboutletcollection_property_assign); 02143 } else if (Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained) { 02144 if (Attributes & ObjCDeclSpec::DQ_PR_copy) { 02145 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 02146 << "unsafe_unretained" << "copy"; 02147 Attributes &= ~ObjCDeclSpec::DQ_PR_copy; 02148 } 02149 if (Attributes & ObjCDeclSpec::DQ_PR_retain) { 02150 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 02151 << "unsafe_unretained" << "retain"; 02152 Attributes &= ~ObjCDeclSpec::DQ_PR_retain; 02153 } 02154 if (Attributes & ObjCDeclSpec::DQ_PR_strong) { 02155 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 02156 << "unsafe_unretained" << "strong"; 02157 Attributes &= ~ObjCDeclSpec::DQ_PR_strong; 02158 } 02159 if (getLangOpts().ObjCAutoRefCount && 02160 (Attributes & ObjCDeclSpec::DQ_PR_weak)) { 02161 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 02162 << "unsafe_unretained" << "weak"; 02163 Attributes &= ~ObjCDeclSpec::DQ_PR_weak; 02164 } 02165 } else if (Attributes & ObjCDeclSpec::DQ_PR_copy) { 02166 if (Attributes & ObjCDeclSpec::DQ_PR_retain) { 02167 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 02168 << "copy" << "retain"; 02169 Attributes &= ~ObjCDeclSpec::DQ_PR_retain; 02170 } 02171 if (Attributes & ObjCDeclSpec::DQ_PR_strong) { 02172 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 02173 << "copy" << "strong"; 02174 Attributes &= ~ObjCDeclSpec::DQ_PR_strong; 02175 } 02176 if (Attributes & ObjCDeclSpec::DQ_PR_weak) { 02177 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 02178 << "copy" << "weak"; 02179 Attributes &= ~ObjCDeclSpec::DQ_PR_weak; 02180 } 02181 } 02182 else if ((Attributes & ObjCDeclSpec::DQ_PR_retain) && 02183 (Attributes & ObjCDeclSpec::DQ_PR_weak)) { 02184 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 02185 << "retain" << "weak"; 02186 Attributes &= ~ObjCDeclSpec::DQ_PR_retain; 02187 } 02188 else if ((Attributes & ObjCDeclSpec::DQ_PR_strong) && 02189 (Attributes & ObjCDeclSpec::DQ_PR_weak)) { 02190 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 02191 << "strong" << "weak"; 02192 Attributes &= ~ObjCDeclSpec::DQ_PR_weak; 02193 } 02194 02195 if ((Attributes & ObjCDeclSpec::DQ_PR_atomic) && 02196 (Attributes & ObjCDeclSpec::DQ_PR_nonatomic)) { 02197 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 02198 << "atomic" << "nonatomic"; 02199 Attributes &= ~ObjCDeclSpec::DQ_PR_atomic; 02200 } 02201 02202 // Warn if user supplied no assignment attribute, property is 02203 // readwrite, and this is an object type. 02204 if (!(Attributes & (ObjCDeclSpec::DQ_PR_assign | ObjCDeclSpec::DQ_PR_copy | 02205 ObjCDeclSpec::DQ_PR_unsafe_unretained | 02206 ObjCDeclSpec::DQ_PR_retain | ObjCDeclSpec::DQ_PR_strong | 02207 ObjCDeclSpec::DQ_PR_weak)) && 02208 PropertyTy->isObjCObjectPointerType()) { 02209 if (getLangOpts().ObjCAutoRefCount) 02210 // With arc, @property definitions should default to (strong) when 02211 // not specified; including when property is 'readonly'. 02212 PropertyDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_strong); 02213 else if (!(Attributes & ObjCDeclSpec::DQ_PR_readonly)) { 02214 bool isAnyClassTy = 02215 (PropertyTy->isObjCClassType() || 02216 PropertyTy->isObjCQualifiedClassType()); 02217 // In non-gc, non-arc mode, 'Class' is treated as a 'void *' no need to 02218 // issue any warning. 02219 if (isAnyClassTy && getLangOpts().getGC() == LangOptions::NonGC) 02220 ; 02221 else if (propertyInPrimaryClass) { 02222 // Don't issue warning on property with no life time in class 02223 // extension as it is inherited from property in primary class. 02224 // Skip this warning in gc-only mode. 02225 if (getLangOpts().getGC() != LangOptions::GCOnly) 02226 Diag(Loc, diag::warn_objc_property_no_assignment_attribute); 02227 02228 // If non-gc code warn that this is likely inappropriate. 02229 if (getLangOpts().getGC() == LangOptions::NonGC) 02230 Diag(Loc, diag::warn_objc_property_default_assign_on_object); 02231 } 02232 } 02233 02234 // FIXME: Implement warning dependent on NSCopying being 02235 // implemented. See also: 02236 // <rdar://5168496&4855821&5607453&5096644&4947311&5698469&4947014&5168496> 02237 // (please trim this list while you are at it). 02238 } 02239 02240 if (!(Attributes & ObjCDeclSpec::DQ_PR_copy) 02241 &&!(Attributes & ObjCDeclSpec::DQ_PR_readonly) 02242 && getLangOpts().getGC() == LangOptions::GCOnly 02243 && PropertyTy->isBlockPointerType()) 02244 Diag(Loc, diag::warn_objc_property_copy_missing_on_block); 02245 else if ((Attributes & ObjCDeclSpec::DQ_PR_retain) && 02246 !(Attributes & ObjCDeclSpec::DQ_PR_readonly) && 02247 !(Attributes & ObjCDeclSpec::DQ_PR_strong) && 02248 PropertyTy->isBlockPointerType()) 02249 Diag(Loc, diag::warn_objc_property_retain_of_block); 02250 02251 if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) && 02252 (Attributes & ObjCDeclSpec::DQ_PR_setter)) 02253 Diag(Loc, diag::warn_objc_readonly_property_has_setter); 02254 02255 }