clang API Documentation

SemaObjCProperty.cpp
Go to the documentation of this file.
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 }