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