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