SemaObjCProperty.cpp revision f921a4868cf1876636f6684e7f68697b18c0cb47
1c3aae25116e66c177579b0b79182b09340b19753Chris Lattner//===--- SemaObjCProperty.cpp - Semantic Analysis for ObjC @property ------===//
2edf128a7fa90f2b0b7ee24741a04a7ae1ecd6f7eMisha Brukman//
3b576c94c15af9a440f69d9d03c2afead7971118cJohn Criswell//                     The LLVM Compiler Infrastructure
4b576c94c15af9a440f69d9d03c2afead7971118cJohn Criswell//
54ee451de366474b9c228b4e5fa573795a715216dChris Lattner// This file is distributed under the University of Illinois Open Source
64ee451de366474b9c228b4e5fa573795a715216dChris Lattner// License. See LICENSE.TXT for details.
7edf128a7fa90f2b0b7ee24741a04a7ae1ecd6f7eMisha Brukman//
8b576c94c15af9a440f69d9d03c2afead7971118cJohn Criswell//===----------------------------------------------------------------------===//
978ec311bd5fcdf44ed64841a0f5df1124b3a9b17Chris Lattner//
10c3aae25116e66c177579b0b79182b09340b19753Chris Lattner//  This file implements semantic analysis for Objective C @property and
1178ec311bd5fcdf44ed64841a0f5df1124b3a9b17Chris Lattner//  @synthesize declarations.
1278ec311bd5fcdf44ed64841a0f5df1124b3a9b17Chris Lattner//
1378ec311bd5fcdf44ed64841a0f5df1124b3a9b17Chris Lattner//===----------------------------------------------------------------------===//
14c3aae25116e66c177579b0b79182b09340b19753Chris Lattner
150ff39b3feb10477c224138156941234f5fa46f58Evan Cheng#include "Sema.h"
164d86e2a6b8edc814165a3e63f55bfaea0b8f224dAnton Korobeynikov
17b3a0417cad8b625acc3033bd5e24afb9ffd0b084Lauro Ramos Venanciousing namespace clang;
1870a248d284af550ae46c8dfc18ea2bbc15d31eb0Chris Lattner
1995c218a83ecf77590b9dc40c636720772d2b5cd7Christopher Lamb//===----------------------------------------------------------------------===//
20c3aae25116e66c177579b0b79182b09340b19753Chris Lattner// Grammar actions.
21707e0184233f27e0e9f9aee0309f2daab8cfe7f8Dan Gohman//===----------------------------------------------------------------------===//
22c3aae25116e66c177579b0b79182b09340b19753Chris Lattner
23d6594ae54cfde4db4d30272192645c0a45fb9902Evan ChengSema::DeclPtrTy Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
2437ce9df0da6cddc3b8bfef9b63d33d058a0f2f15Chris Lattner                                    FieldDeclarator &FD,
25a844bdeab31ef04221e7ef59a8467893584cc14dEvan Cheng                                    ObjCDeclSpec &ODS,
2669de1932b350d7cdfc0ed1f4198d6f78c7822a02Dan Gohman                                    Selector GetterSel,
276f0d024a534af18d9e60b3ea757376cd8a3a980eDan Gohman                                    Selector SetterSel,
2895c218a83ecf77590b9dc40c636720772d2b5cd7Christopher Lamb                                    DeclPtrTy ClassCategory,
29b48da3953642d3d006edebd7fc6c1ca5bcfdb5cdChris Lattner                                    bool *isOverridingProperty,
30760f86f3395750ef6d03ecfe6f82d2867fbf568bDan Gohman                                    tok::ObjCKeywordKind MethodImplKind) {
31f3e133a35f5aa6ed32ca29aa3675eff349d61008Chris Lattner  unsigned Attributes = ODS.getPropertyAttributes();
32f3e133a35f5aa6ed32ca29aa3675eff349d61008Chris Lattner  bool isReadWrite = ((Attributes & ObjCDeclSpec::DQ_PR_readwrite) ||
336f287b22d2e57600b4cd5dc209d0d869e7736c0bBill Wendling                      // default is readwrite!
34b4459088d62670b0f0333eab1b260622955ec3e5Owen Anderson                      !(Attributes & ObjCDeclSpec::DQ_PR_readonly));
35944fac71e082cc2664cc71b4d3f6c72bab7143fbChris Lattner  // property is defaulted to 'assign' if it is readwrite and is
36944fac71e082cc2664cc71b4d3f6c72bab7143fbChris Lattner  // not retain or copy
37b4459088d62670b0f0333eab1b260622955ec3e5Owen Anderson  bool isAssign = ((Attributes & ObjCDeclSpec::DQ_PR_assign) ||
38012f241987a017ea74d34d4c126997f84902ef61Chris Lattner                   (isReadWrite &&
39d48c5e871a0f3386e536e0987ca06dbc4e274acfChris Lattner                    !(Attributes & ObjCDeclSpec::DQ_PR_retain) &&
40af47b11b959713d70c45bee1922e468adfaeaff0Duncan Sands                    !(Attributes & ObjCDeclSpec::DQ_PR_copy)));
41190a418bf6b49a4ef1c1980229a2f0d516e8a2cdChris Lattner
42115c036a4c83cd277ffac0867a21b34f63829db7Evan Cheng  QualType T = GetTypeForDeclarator(FD.D, S);
43fd161e964aa02636c00364ae4d46bf4e384df096Jeff Cohen  if (T->isReferenceType()) {
4497af751deb9b26fd42fbcee082da9ccc4ded5b45Jeff Cohen    Diag(AtLoc, diag::error_reference_property);
45e25738cab63977282f8ebc26012142debfbd1d20Chris Lattner    return DeclPtrTy();
46d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke  }
470b3e525a3a6b55b66dc5676675712b26e4c1ed9fChris Lattner  // Validate the attributes on the @property.
480b3e525a3a6b55b66dc5676675712b26e4c1ed9fChris Lattner  CheckObjCPropertyAttributes(T, AtLoc, Attributes);
4983ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands
500b3e525a3a6b55b66dc5676675712b26e4c1ed9fChris Lattner  // Proceed with constructing the ObjCPropertDecls.
510b3e525a3a6b55b66dc5676675712b26e4c1ed9fChris Lattner  ObjCContainerDecl *ClassDecl =
520b3e525a3a6b55b66dc5676675712b26e4c1ed9fChris Lattner    cast<ObjCContainerDecl>(ClassCategory.getAs<Decl>());
530b3e525a3a6b55b66dc5676675712b26e4c1ed9fChris Lattner
5483ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands  if (ObjCCategoryDecl *CDecl = dyn_cast<ObjCCategoryDecl>(ClassDecl))
5583ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands    if (CDecl->IsClassExtension())
56ec4a5672f86a42730d8fcf98243322520eaffb33Chris Lattner      return HandlePropertyInClassExtension(S, CDecl, AtLoc,
57ec4a5672f86a42730d8fcf98243322520eaffb33Chris Lattner                                            FD, GetterSel, SetterSel,
58ec4a5672f86a42730d8fcf98243322520eaffb33Chris Lattner                                            isAssign, isReadWrite,
59ec4a5672f86a42730d8fcf98243322520eaffb33Chris Lattner                                            Attributes,
60ec4a5672f86a42730d8fcf98243322520eaffb33Chris Lattner                                            isOverridingProperty, T,
61ec4a5672f86a42730d8fcf98243322520eaffb33Chris Lattner                                            MethodImplKind);
62ec4a5672f86a42730d8fcf98243322520eaffb33Chris Lattner
63ec4a5672f86a42730d8fcf98243322520eaffb33Chris Lattner  return DeclPtrTy::make(CreatePropertyDecl(S, ClassDecl, AtLoc, FD,
64ec4a5672f86a42730d8fcf98243322520eaffb33Chris Lattner                                            GetterSel, SetterSel,
65f8dc0617baceeba8ccd67c8881eb88eb1be2902cChris Lattner                                            isAssign, isReadWrite,
66f8dc0617baceeba8ccd67c8881eb88eb1be2902cChris Lattner                                            Attributes, T, MethodImplKind));
6758b968be853ef02d0f448e5e2c31676e361c210fJim Laskey}
6858b968be853ef02d0f448e5e2c31676e361c210fJim Laskey
6958b968be853ef02d0f448e5e2c31676e361c210fJim LaskeySema::DeclPtrTy
7058b968be853ef02d0f448e5e2c31676e361c210fJim LaskeySema::HandlePropertyInClassExtension(Scope *S, ObjCCategoryDecl *CDecl,
7158b968be853ef02d0f448e5e2c31676e361c210fJim Laskey                                     SourceLocation AtLoc, FieldDeclarator &FD,
7258b968be853ef02d0f448e5e2c31676e361c210fJim Laskey                                     Selector GetterSel, Selector SetterSel,
7358b968be853ef02d0f448e5e2c31676e361c210fJim Laskey                                     const bool isAssign,
7458b968be853ef02d0f448e5e2c31676e361c210fJim Laskey                                     const bool isReadWrite,
75e6c1742914149d44360fbf05a653041a672282afDale Johannesen                                     const unsigned Attributes,
764fbd796a1251a27e6590765a0a34876f436a0af9Dan Gohman                                     bool *isOverridingProperty,
7758b968be853ef02d0f448e5e2c31676e361c210fJim Laskey                                     QualType T,
7858b968be853ef02d0f448e5e2c31676e361c210fJim Laskey                                     tok::ObjCKeywordKind MethodImplKind) {
7983ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands
80f04afdbb48568ef09f11fd10ac03426101f2dbf8Dale Johannesen  // Diagnose if this property is already in continuation class.
8183ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands  DeclContext *DC = cast<DeclContext>(CDecl);
82fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel  IdentifierInfo *PropertyId = FD.D.getIdentifier();
839dd2ce46c58dd05f0835df77f308396715890d66Dale Johannesen
849dd2ce46c58dd05f0835df77f308396715890d66Dale Johannesen  if (ObjCPropertyDecl *prevDecl =
859dd2ce46c58dd05f0835df77f308396715890d66Dale Johannesen        ObjCPropertyDecl::findPropertyDecl(DC, PropertyId)) {
86ec4a5672f86a42730d8fcf98243322520eaffb33Chris Lattner    Diag(AtLoc, diag::err_duplicate_property);
87fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel    Diag(prevDecl->getLocation(), diag::note_property_declare);
88f04afdbb48568ef09f11fd10ac03426101f2dbf8Dale Johannesen    return DeclPtrTy();
89f04afdbb48568ef09f11fd10ac03426101f2dbf8Dale Johannesen  }
9023a98551ab65eeb8fe5019df8b7db4891582a4bdDale Johannesen
9123a98551ab65eeb8fe5019df8b7db4891582a4bdDale Johannesen  // Create a new ObjCPropertyDecl with the DeclContext being
9223a98551ab65eeb8fe5019df8b7db4891582a4bdDale Johannesen  // the class extension.
9323a98551ab65eeb8fe5019df8b7db4891582a4bdDale Johannesen  ObjCPropertyDecl *PDecl =
94f04afdbb48568ef09f11fd10ac03426101f2dbf8Dale Johannesen    ObjCPropertyDecl::Create(Context, DC, FD.D.getIdentifierLoc(),
95f04afdbb48568ef09f11fd10ac03426101f2dbf8Dale Johannesen                             PropertyId, AtLoc, T);
9658b968be853ef02d0f448e5e2c31676e361c210fJim Laskey  if (Attributes & ObjCDeclSpec::DQ_PR_readonly)
9761d4399dfc7046595e30ad34a28c72a885cb8100Chris Lattner    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readonly);
9858b968be853ef02d0f448e5e2c31676e361c210fJim Laskey  if (Attributes & ObjCDeclSpec::DQ_PR_readwrite)
995cdcc58d51c792d329202bab97c34aefbc043b15Chris Lattner    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readwrite);
100a8df166fbef047c90adba3c673162a1b1f6681c4Evan Cheng
10161d4399dfc7046595e30ad34a28c72a885cb8100Chris Lattner  DC->addDecl(PDecl);
102a8df166fbef047c90adba3c673162a1b1f6681c4Evan Cheng
103547a16f27315a08527c41dc521c7cdf6ad9a0b6cChris Lattner  // We need to look in the @interface to see if the @property was
104547a16f27315a08527c41dc521c7cdf6ad9a0b6cChris Lattner  // already declared.
105ba36cb5242eb02b12b277f82b9efe497f7da4d7fGabor Greif  ObjCInterfaceDecl *CCPrimary = CDecl->getClassInterface();
106fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel  if (!CCPrimary) {
107a8df166fbef047c90adba3c673162a1b1f6681c4Evan Cheng    Diag(CDecl->getLocation(), diag::err_continuation_class);
108fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel    *isOverridingProperty = true;
10961d4399dfc7046595e30ad34a28c72a885cb8100Chris Lattner    return DeclPtrTy();
110fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel  }
11161d4399dfc7046595e30ad34a28c72a885cb8100Chris Lattner
11261d4399dfc7046595e30ad34a28c72a885cb8100Chris Lattner  // Find the property in continuation class's primary class only.
11361d4399dfc7046595e30ad34a28c72a885cb8100Chris Lattner  ObjCPropertyDecl *PIDecl =
114fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel    CCPrimary->FindPropertyVisibleInPrimaryClass(PropertyId);
11561d4399dfc7046595e30ad34a28c72a885cb8100Chris Lattner
11661d4399dfc7046595e30ad34a28c72a885cb8100Chris Lattner  if (!PIDecl) {
117fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel    // No matching property found in the primary class. Just fall thru
11861d4399dfc7046595e30ad34a28c72a885cb8100Chris Lattner    // and add property to continuation class's primary class.
11961d4399dfc7046595e30ad34a28c72a885cb8100Chris Lattner    ObjCPropertyDecl *PDecl =
120475871a144eb604ddaf37503397ba0941442e5fbDan Gohman      CreatePropertyDecl(S, CCPrimary, AtLoc,
121a8df166fbef047c90adba3c673162a1b1f6681c4Evan Cheng                         FD, GetterSel, SetterSel, isAssign, isReadWrite,
122a8df166fbef047c90adba3c673162a1b1f6681c4Evan Cheng                         Attributes, T, MethodImplKind);
123a8df166fbef047c90adba3c673162a1b1f6681c4Evan Cheng
124a8df166fbef047c90adba3c673162a1b1f6681c4Evan Cheng    // A case of continuation class adding a new property in the class. This
1256c231501f80e1ff05e3cada3d051b1c826d1f478Dan Gohman    // is not what it was meant for. However, gcc supports it and so should we.
12623a98551ab65eeb8fe5019df8b7db4891582a4bdDale Johannesen    // Make sure setter/getters are declared here.
1276c231501f80e1ff05e3cada3d051b1c826d1f478Dan Gohman    ProcessPropertyDecl(PDecl, CCPrimary);
128a8df166fbef047c90adba3c673162a1b1f6681c4Evan Cheng    return DeclPtrTy::make(PDecl);
12961d4399dfc7046595e30ad34a28c72a885cb8100Chris Lattner
130fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel  }
13161d4399dfc7046595e30ad34a28c72a885cb8100Chris Lattner
13261d4399dfc7046595e30ad34a28c72a885cb8100Chris Lattner  // The property 'PIDecl's readonly attribute will be over-ridden
13361d4399dfc7046595e30ad34a28c72a885cb8100Chris Lattner  // with continuation class's readwrite property attribute!
13461d4399dfc7046595e30ad34a28c72a885cb8100Chris Lattner  unsigned PIkind = PIDecl->getPropertyAttributes();
13561d4399dfc7046595e30ad34a28c72a885cb8100Chris Lattner  if (isReadWrite && (PIkind & ObjCPropertyDecl::OBJC_PR_readonly)) {
13661d4399dfc7046595e30ad34a28c72a885cb8100Chris Lattner    unsigned retainCopyNonatomic =
13761d4399dfc7046595e30ad34a28c72a885cb8100Chris Lattner    (ObjCPropertyDecl::OBJC_PR_retain |
13861d4399dfc7046595e30ad34a28c72a885cb8100Chris Lattner     ObjCPropertyDecl::OBJC_PR_copy |
13961d4399dfc7046595e30ad34a28c72a885cb8100Chris Lattner     ObjCPropertyDecl::OBJC_PR_nonatomic);
14061d4399dfc7046595e30ad34a28c72a885cb8100Chris Lattner    if ((Attributes & retainCopyNonatomic) !=
1414a147842eb24a7611fcd7bfb37c55185b4664927Evan Cheng        (PIkind & retainCopyNonatomic)) {
1424a147842eb24a7611fcd7bfb37c55185b4664927Evan Cheng      Diag(AtLoc, diag::warn_property_attr_mismatch);
1434a147842eb24a7611fcd7bfb37c55185b4664927Evan Cheng      Diag(PIDecl->getLocation(), diag::note_property_declare);
144547a16f27315a08527c41dc521c7cdf6ad9a0b6cChris Lattner    }
145547a16f27315a08527c41dc521c7cdf6ad9a0b6cChris Lattner    DeclContext *DC = cast<DeclContext>(CCPrimary);
146ba36cb5242eb02b12b277f82b9efe497f7da4d7fGabor Greif    if (!ObjCPropertyDecl::findPropertyDecl(DC,
147fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel                                 PIDecl->getDeclName().getAsIdentifierInfo())) {
1484a147842eb24a7611fcd7bfb37c55185b4664927Evan Cheng      // Protocol is not in the primary class. Must build one for it.
149fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel      ObjCDeclSpec ProtocolPropertyODS;
150a8df166fbef047c90adba3c673162a1b1f6681c4Evan Cheng      // FIXME. Assuming that ObjCDeclSpec::ObjCPropertyAttributeKind
151fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel      // and ObjCPropertyDecl::PropertyAttributeKind have identical
152a8df166fbef047c90adba3c673162a1b1f6681c4Evan Cheng      // values.  Should consolidate both into one enum type.
153a8df166fbef047c90adba3c673162a1b1f6681c4Evan Cheng      ProtocolPropertyODS.
154a8df166fbef047c90adba3c673162a1b1f6681c4Evan Cheng      setPropertyAttributes((ObjCDeclSpec::ObjCPropertyAttributeKind)
155fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel                            PIkind);
156a8df166fbef047c90adba3c673162a1b1f6681c4Evan Cheng
157a8df166fbef047c90adba3c673162a1b1f6681c4Evan Cheng      DeclPtrTy ProtocolPtrTy =
158fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel        ActOnProperty(S, AtLoc, FD, ProtocolPropertyODS,
15968f32cbb1f9e62d5e6047b048c0d7d217b8717e1Dan Gohman                      PIDecl->getGetterName(),
160a8df166fbef047c90adba3c673162a1b1f6681c4Evan Cheng                      PIDecl->getSetterName(),
161475871a144eb604ddaf37503397ba0941442e5fbDan Gohman                      DeclPtrTy::make(CCPrimary), isOverridingProperty,
162a8df166fbef047c90adba3c673162a1b1f6681c4Evan Cheng                      MethodImplKind);
163a8df166fbef047c90adba3c673162a1b1f6681c4Evan Cheng      PIDecl = ProtocolPtrTy.getAs<ObjCPropertyDecl>();
164a8df166fbef047c90adba3c673162a1b1f6681c4Evan Cheng    }
165a8df166fbef047c90adba3c673162a1b1f6681c4Evan Cheng    PIDecl->makeitReadWriteAttribute();
166eaf089430e7681fcddc3465c3b33b9645273ab02Dale Johannesen    if (Attributes & ObjCDeclSpec::DQ_PR_retain)
167a8df166fbef047c90adba3c673162a1b1f6681c4Evan Cheng      PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_retain);
168a8df166fbef047c90adba3c673162a1b1f6681c4Evan Cheng    if (Attributes & ObjCDeclSpec::DQ_PR_copy)
169a8df166fbef047c90adba3c673162a1b1f6681c4Evan Cheng      PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_copy);
170fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel    PIDecl->setSetterName(SetterSel);
17168f32cbb1f9e62d5e6047b048c0d7d217b8717e1Dan Gohman  } else {
172a8df166fbef047c90adba3c673162a1b1f6681c4Evan Cheng    Diag(AtLoc, diag::err_use_continuation_class)
173a8df166fbef047c90adba3c673162a1b1f6681c4Evan Cheng      << CCPrimary->getDeclName();
174a8df166fbef047c90adba3c673162a1b1f6681c4Evan Cheng    Diag(PIDecl->getLocation(), diag::note_property_declare);
175a8df166fbef047c90adba3c673162a1b1f6681c4Evan Cheng  }
176a8df166fbef047c90adba3c673162a1b1f6681c4Evan Cheng  *isOverridingProperty = true;
177a8df166fbef047c90adba3c673162a1b1f6681c4Evan Cheng  // Make sure setter decl is synthesized, and added to primary class's list.
1784a147842eb24a7611fcd7bfb37c55185b4664927Evan Cheng  ProcessPropertyDecl(PIDecl, CCPrimary);
1794a147842eb24a7611fcd7bfb37c55185b4664927Evan Cheng  return DeclPtrTy();
180efec751a1b786724862ceff52748df94873a807eEvan Cheng}
181efec751a1b786724862ceff52748df94873a807eEvan Cheng
182efec751a1b786724862ceff52748df94873a807eEvan ChengObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S,
183efec751a1b786724862ceff52748df94873a807eEvan Cheng                                           ObjCContainerDecl *CDecl,
184efec751a1b786724862ceff52748df94873a807eEvan Cheng                                           SourceLocation AtLoc,
185efec751a1b786724862ceff52748df94873a807eEvan Cheng                                           FieldDeclarator &FD,
186efec751a1b786724862ceff52748df94873a807eEvan Cheng                                           Selector GetterSel,
187efec751a1b786724862ceff52748df94873a807eEvan Cheng                                           Selector SetterSel,
188efec751a1b786724862ceff52748df94873a807eEvan Cheng                                           const bool isAssign,
189efec751a1b786724862ceff52748df94873a807eEvan Cheng                                           const bool isReadWrite,
190efec751a1b786724862ceff52748df94873a807eEvan Cheng                                           const unsigned Attributes,
191efec751a1b786724862ceff52748df94873a807eEvan Cheng                                           QualType T,
192efec751a1b786724862ceff52748df94873a807eEvan Cheng                                           tok::ObjCKeywordKind MethodImplKind){
193475871a144eb604ddaf37503397ba0941442e5fbDan Gohman
194efec751a1b786724862ceff52748df94873a807eEvan Cheng  IdentifierInfo *PropertyId = FD.D.getIdentifier();
195efec751a1b786724862ceff52748df94873a807eEvan Cheng
196efec751a1b786724862ceff52748df94873a807eEvan Cheng  // Issue a warning if property is 'assign' as default and its object, which is
197efec751a1b786724862ceff52748df94873a807eEvan Cheng  // gc'able conforms to NSCopying protocol
198efec751a1b786724862ceff52748df94873a807eEvan Cheng  if (getLangOptions().getGCMode() != LangOptions::NonGC &&
199efec751a1b786724862ceff52748df94873a807eEvan Cheng      isAssign && !(Attributes & ObjCDeclSpec::DQ_PR_assign))
200efec751a1b786724862ceff52748df94873a807eEvan Cheng    if (T->isObjCObjectPointerType()) {
201bb81d97feb396a8bb21d074db1c57e9f66525f40Evan Cheng      QualType InterfaceTy = T->getPointeeType();
2024406604047423576e36657c7ede266ca42e79642Dan Gohman      if (const ObjCInterfaceType *OIT =
203bb81d97feb396a8bb21d074db1c57e9f66525f40Evan Cheng          InterfaceTy->getAs<ObjCInterfaceType>()) {
204475871a144eb604ddaf37503397ba0941442e5fbDan Gohman        ObjCInterfaceDecl *IDecl = OIT->getDecl();
2054406604047423576e36657c7ede266ca42e79642Dan Gohman        if (IDecl)
2064406604047423576e36657c7ede266ca42e79642Dan Gohman          if (ObjCProtocolDecl* PNSCopying =
207e8be6c63915e0389f1eef6b53c64300d13b2ce99Dan Gohman              LookupProtocol(&Context.Idents.get("NSCopying")))
208e8be6c63915e0389f1eef6b53c64300d13b2ce99Dan Gohman            if (IDecl->ClassImplementsProtocol(PNSCopying, true))
2094406604047423576e36657c7ede266ca42e79642Dan Gohman              Diag(AtLoc, diag::warn_implements_nscopying) << PropertyId;
2104406604047423576e36657c7ede266ca42e79642Dan Gohman      }
211bb81d97feb396a8bb21d074db1c57e9f66525f40Evan Cheng    }
212bb81d97feb396a8bb21d074db1c57e9f66525f40Evan Cheng  if (T->isObjCInterfaceType())
213c3aae25116e66c177579b0b79182b09340b19753Chris Lattner    Diag(FD.D.getIdentifierLoc(), diag::err_statically_allocated_object);
214c3aae25116e66c177579b0b79182b09340b19753Chris Lattner
215c3aae25116e66c177579b0b79182b09340b19753Chris Lattner  DeclContext *DC = cast<DeclContext>(CDecl);
216c3aae25116e66c177579b0b79182b09340b19753Chris Lattner  ObjCPropertyDecl *PDecl = ObjCPropertyDecl::Create(Context, DC,
217c3aae25116e66c177579b0b79182b09340b19753Chris Lattner                                                     FD.D.getIdentifierLoc(),
218c3aae25116e66c177579b0b79182b09340b19753Chris Lattner                                                     PropertyId, AtLoc, T);
219c3aae25116e66c177579b0b79182b09340b19753Chris Lattner
220c3aae25116e66c177579b0b79182b09340b19753Chris Lattner  if (ObjCPropertyDecl *prevDecl =
221c3aae25116e66c177579b0b79182b09340b19753Chris Lattner        ObjCPropertyDecl::findPropertyDecl(DC, PropertyId)) {
222a1dc6025422cd0e6f951c69a8427f7f885cf52c3Bill Wendling    Diag(PDecl->getLocation(), diag::err_duplicate_property);
223c3aae25116e66c177579b0b79182b09340b19753Chris Lattner    Diag(prevDecl->getLocation(), diag::note_property_declare);
224c3aae25116e66c177579b0b79182b09340b19753Chris Lattner    PDecl->setInvalidDecl();
225c3aae25116e66c177579b0b79182b09340b19753Chris Lattner  }
226c3aae25116e66c177579b0b79182b09340b19753Chris Lattner  else
227c3aae25116e66c177579b0b79182b09340b19753Chris Lattner    DC->addDecl(PDecl);
228c3aae25116e66c177579b0b79182b09340b19753Chris Lattner
229c3aae25116e66c177579b0b79182b09340b19753Chris Lattner  if (T->isArrayType() || T->isFunctionType()) {
230c3aae25116e66c177579b0b79182b09340b19753Chris Lattner    Diag(AtLoc, diag::err_property_type) << T;
231c3aae25116e66c177579b0b79182b09340b19753Chris Lattner    PDecl->setInvalidDecl();
232c3aae25116e66c177579b0b79182b09340b19753Chris Lattner  }
233a1dc6025422cd0e6f951c69a8427f7f885cf52c3Bill Wendling
234c3aae25116e66c177579b0b79182b09340b19753Chris Lattner  ProcessDeclAttributes(S, PDecl, FD.D);
235a1dc6025422cd0e6f951c69a8427f7f885cf52c3Bill Wendling
236a1dc6025422cd0e6f951c69a8427f7f885cf52c3Bill Wendling  // Regardless of setter/getter attribute, we save the default getter/setter
237c3aae25116e66c177579b0b79182b09340b19753Chris Lattner  // selector names in anticipation of declaration of setter/getter methods.
238c3aae25116e66c177579b0b79182b09340b19753Chris Lattner  PDecl->setGetterName(GetterSel);
239c3aae25116e66c177579b0b79182b09340b19753Chris Lattner  PDecl->setSetterName(SetterSel);
240c3aae25116e66c177579b0b79182b09340b19753Chris Lattner
241c3aae25116e66c177579b0b79182b09340b19753Chris Lattner  if (Attributes & ObjCDeclSpec::DQ_PR_readonly)
242c3aae25116e66c177579b0b79182b09340b19753Chris Lattner    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readonly);
243c3aae25116e66c177579b0b79182b09340b19753Chris Lattner
244c3aae25116e66c177579b0b79182b09340b19753Chris Lattner  if (Attributes & ObjCDeclSpec::DQ_PR_getter)
245c3aae25116e66c177579b0b79182b09340b19753Chris Lattner    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_getter);
246c3aae25116e66c177579b0b79182b09340b19753Chris Lattner
247c3aae25116e66c177579b0b79182b09340b19753Chris Lattner  if (Attributes & ObjCDeclSpec::DQ_PR_setter)
248c3aae25116e66c177579b0b79182b09340b19753Chris Lattner    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_setter);
249c3aae25116e66c177579b0b79182b09340b19753Chris Lattner
250c3aae25116e66c177579b0b79182b09340b19753Chris Lattner  if (isReadWrite)
251c3aae25116e66c177579b0b79182b09340b19753Chris Lattner    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readwrite);
252c3aae25116e66c177579b0b79182b09340b19753Chris Lattner
253c3aae25116e66c177579b0b79182b09340b19753Chris Lattner  if (Attributes & ObjCDeclSpec::DQ_PR_retain)
254c3aae25116e66c177579b0b79182b09340b19753Chris Lattner    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_retain);
255c3aae25116e66c177579b0b79182b09340b19753Chris Lattner
256c3aae25116e66c177579b0b79182b09340b19753Chris Lattner  if (Attributes & ObjCDeclSpec::DQ_PR_copy)
257c3aae25116e66c177579b0b79182b09340b19753Chris Lattner    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_copy);
258c3aae25116e66c177579b0b79182b09340b19753Chris Lattner
259c3aae25116e66c177579b0b79182b09340b19753Chris Lattner  if (isAssign)
260c3aae25116e66c177579b0b79182b09340b19753Chris Lattner    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_assign);
261c3aae25116e66c177579b0b79182b09340b19753Chris Lattner
262c3aae25116e66c177579b0b79182b09340b19753Chris Lattner  if (Attributes & ObjCDeclSpec::DQ_PR_nonatomic)
263c3aae25116e66c177579b0b79182b09340b19753Chris Lattner    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_nonatomic);
264c3aae25116e66c177579b0b79182b09340b19753Chris Lattner
265c3aae25116e66c177579b0b79182b09340b19753Chris Lattner  if (MethodImplKind == tok::objc_required)
266c3aae25116e66c177579b0b79182b09340b19753Chris Lattner    PDecl->setPropertyImplementation(ObjCPropertyDecl::Required);
267c3aae25116e66c177579b0b79182b09340b19753Chris Lattner  else if (MethodImplKind == tok::objc_optional)
268c3aae25116e66c177579b0b79182b09340b19753Chris Lattner    PDecl->setPropertyImplementation(ObjCPropertyDecl::Optional);
269edf128a7fa90f2b0b7ee24741a04a7ae1ecd6f7eMisha Brukman
270c3aae25116e66c177579b0b79182b09340b19753Chris Lattner  return PDecl;
271edf128a7fa90f2b0b7ee24741a04a7ae1ecd6f7eMisha Brukman}
272c3aae25116e66c177579b0b79182b09340b19753Chris Lattner
273c3aae25116e66c177579b0b79182b09340b19753Chris Lattner
274c3aae25116e66c177579b0b79182b09340b19753Chris Lattner/// ActOnPropertyImplDecl - This routine performs semantic checks and
275e41102bb610aeebe73eeec6a4afe62301de10042Chris Lattner/// builds the AST node for a property implementation declaration; declared
276fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel/// as @synthesize or @dynamic.
277e41102bb610aeebe73eeec6a4afe62301de10042Chris Lattner///
278e41102bb610aeebe73eeec6a4afe62301de10042Chris LattnerSema::DeclPtrTy Sema::ActOnPropertyImplDecl(SourceLocation AtLoc,
279e41102bb610aeebe73eeec6a4afe62301de10042Chris Lattner                                            SourceLocation PropertyLoc,
280fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel                                            bool Synthesize,
281c3aae25116e66c177579b0b79182b09340b19753Chris Lattner                                            DeclPtrTy ClassCatImpDecl,
282c3aae25116e66c177579b0b79182b09340b19753Chris Lattner                                            IdentifierInfo *PropertyId,
283c3aae25116e66c177579b0b79182b09340b19753Chris Lattner                                            IdentifierInfo *PropertyIvar) {
284c3aae25116e66c177579b0b79182b09340b19753Chris Lattner  Decl *ClassImpDecl = ClassCatImpDecl.getAs<Decl>();
285c3aae25116e66c177579b0b79182b09340b19753Chris Lattner  // Make sure we have a context for the property implementation declaration.
286c3aae25116e66c177579b0b79182b09340b19753Chris Lattner  if (!ClassImpDecl) {
287c3aae25116e66c177579b0b79182b09340b19753Chris Lattner    Diag(AtLoc, diag::error_missing_property_context);
288c3aae25116e66c177579b0b79182b09340b19753Chris Lattner    return DeclPtrTy();
289c3aae25116e66c177579b0b79182b09340b19753Chris Lattner  }
290c3aae25116e66c177579b0b79182b09340b19753Chris Lattner  ObjCPropertyDecl *property = 0;
291c3aae25116e66c177579b0b79182b09340b19753Chris Lattner  ObjCInterfaceDecl* IDecl = 0;
292edf128a7fa90f2b0b7ee24741a04a7ae1ecd6f7eMisha Brukman  // Find the class or category class where this property must have
293c3aae25116e66c177579b0b79182b09340b19753Chris Lattner  // a declaration.
294c3aae25116e66c177579b0b79182b09340b19753Chris Lattner  ObjCImplementationDecl *IC = 0;
295a83385fb7bdb325921d091729d95e2e1f4d49cc1Chris Lattner  ObjCCategoryImplDecl* CatImplClass = 0;
296fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel  if ((IC = dyn_cast<ObjCImplementationDecl>(ClassImpDecl))) {
297a83385fb7bdb325921d091729d95e2e1f4d49cc1Chris Lattner    IDecl = IC->getClassInterface();
298a83385fb7bdb325921d091729d95e2e1f4d49cc1Chris Lattner    // We always synthesize an interface for an implementation
299a83385fb7bdb325921d091729d95e2e1f4d49cc1Chris Lattner    // without an interface decl. So, IDecl is always non-zero.
300a83385fb7bdb325921d091729d95e2e1f4d49cc1Chris Lattner    assert(IDecl &&
301883a52de66da854de158b602952d8242acddcb48Chris Lattner           "ActOnPropertyImplDecl - @implementation without @interface");
302d64a78c9ed62f2615ca1ea524d1f1942f798c8deDan Gohman
303883a52de66da854de158b602952d8242acddcb48Chris Lattner    // Look for this property declaration in the @implementation's @interface
304883a52de66da854de158b602952d8242acddcb48Chris Lattner    property = IDecl->FindPropertyDeclaration(PropertyId);
305883a52de66da854de158b602952d8242acddcb48Chris Lattner    if (!property) {
306a83385fb7bdb325921d091729d95e2e1f4d49cc1Chris Lattner      Diag(PropertyLoc, diag::error_bad_property_decl) << IDecl->getDeclName();
307a83385fb7bdb325921d091729d95e2e1f4d49cc1Chris Lattner      return DeclPtrTy();
308fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel    }
309a83385fb7bdb325921d091729d95e2e1f4d49cc1Chris Lattner    if (const ObjCCategoryDecl *CD =
310c3aae25116e66c177579b0b79182b09340b19753Chris Lattner        dyn_cast<ObjCCategoryDecl>(property->getDeclContext())) {
311c3aae25116e66c177579b0b79182b09340b19753Chris Lattner      if (!CD->IsClassExtension()) {
312b48da3953642d3d006edebd7fc6c1ca5bcfdb5cdChris Lattner        Diag(PropertyLoc, diag::error_category_property) << CD->getDeclName();
3136448d91ad1e5497fe2f7015d61b57cb5f3040879Dan Gohman        Diag(property->getLocation(), diag::note_property_declare);
314b48da3953642d3d006edebd7fc6c1ca5bcfdb5cdChris Lattner        return DeclPtrTy();
315b48da3953642d3d006edebd7fc6c1ca5bcfdb5cdChris Lattner      }
31658b968be853ef02d0f448e5e2c31676e361c210fJim Laskey    }
317583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey  } else if ((CatImplClass = dyn_cast<ObjCCategoryImplDecl>(ClassImpDecl))) {
318583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey    if (Synthesize) {
319583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey      Diag(AtLoc, diag::error_synthesize_category_decl);
320def69b92e70d156ed6f8c7af33c9a87d3f475e09Jim Laskey      return DeclPtrTy();
321def69b92e70d156ed6f8c7af33c9a87d3f475e09Jim Laskey    }
322583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey    IDecl = CatImplClass->getClassInterface();
323583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey    if (!IDecl) {
324583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey      Diag(AtLoc, diag::error_missing_property_interface);
325583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey      return DeclPtrTy();
326583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey    }
327583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey    ObjCCategoryDecl *Category =
328844731a7f1909f55935e3514c9e713a62d67662eDan Gohman    IDecl->FindCategoryDeclaration(CatImplClass->getIdentifier());
329fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel
330583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey    // If category for this implementation not found, it is an error which
331583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey    // has already been reported eralier.
332def69b92e70d156ed6f8c7af33c9a87d3f475e09Jim Laskey    if (!Category)
333def69b92e70d156ed6f8c7af33c9a87d3f475e09Jim Laskey      return DeclPtrTy();
334583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey    // Look for this property declaration in @implementation's category
335475871a144eb604ddaf37503397ba0941442e5fbDan Gohman    property = Category->FindPropertyDeclaration(PropertyId);
33663e3f14df6cf76f1a12de1153e1114f4b20b15a9Chris Lattner    if (!property) {
337ba36cb5242eb02b12b277f82b9efe497f7da4d7fGabor Greif      Diag(PropertyLoc, diag::error_bad_category_property_decl)
33899a6cb92d173c142073416c81efe6d3daeb80b49Gabor Greif      << Category->getDeclName();
33963e3f14df6cf76f1a12de1153e1114f4b20b15a9Chris Lattner      return DeclPtrTy();
340583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey    }
341583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey  } else {
3426d9cdd56173fb915a9e3a8f0f6b5a8ed9bed1098Dan Gohman    Diag(AtLoc, diag::error_bad_property_context);
3436d9cdd56173fb915a9e3a8f0f6b5a8ed9bed1098Dan Gohman    return DeclPtrTy();
3446d9cdd56173fb915a9e3a8f0f6b5a8ed9bed1098Dan Gohman  }
3456d9cdd56173fb915a9e3a8f0f6b5a8ed9bed1098Dan Gohman  ObjCIvarDecl *Ivar = 0;
3466d9cdd56173fb915a9e3a8f0f6b5a8ed9bed1098Dan Gohman  // Check that we have a valid, previously declared ivar for @synthesize
347e7852d014432a06c783de3c350eb96e686f10f92Dan Gohman  if (Synthesize) {
348e7852d014432a06c783de3c350eb96e686f10f92Dan Gohman    // @synthesize
3496d9cdd56173fb915a9e3a8f0f6b5a8ed9bed1098Dan Gohman    if (!PropertyIvar)
3506d9cdd56173fb915a9e3a8f0f6b5a8ed9bed1098Dan Gohman      PropertyIvar = PropertyId;
3516d9cdd56173fb915a9e3a8f0f6b5a8ed9bed1098Dan Gohman    QualType PropType = Context.getCanonicalType(property->getType());
352583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey    // Check that this is a previously declared 'ivar' in 'IDecl' interface
353fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel    ObjCInterfaceDecl *ClassDeclared;
354475871a144eb604ddaf37503397ba0941442e5fbDan Gohman    Ivar = IDecl->lookupInstanceVariable(PropertyIvar, ClassDeclared);
355583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey    if (!Ivar) {
356583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey      DeclContext *EnclosingContext = cast_or_null<DeclContext>(ClassImpDecl);
357583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey      assert(EnclosingContext &&
358583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey             "null DeclContext for synthesized ivar - ActOnPropertyImplDecl");
359583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey      Ivar = ObjCIvarDecl::Create(Context, EnclosingContext, PropertyLoc,
3600dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands                                  PropertyIvar, PropType, /*Dinfo=*/0,
3610dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands                                  ObjCIvarDecl::Public,
3620dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands                                  (Expr *)0);
3632041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen      EnclosingContext->addDecl(Ivar);
3642a4ed82ce2ba4a02f2a02eb4ed8ce5186f3f93daChris Lattner      IDecl->makeDeclVisibleInContext(Ivar, false);
3652a4ed82ce2ba4a02f2a02eb4ed8ce5186f3f93daChris Lattner      property->setPropertyIvarDecl(Ivar);
3662a4ed82ce2ba4a02f2a02eb4ed8ce5186f3f93daChris Lattner
3672041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen      if (!getLangOptions().ObjCNonFragileABI)
368276dcbdc8db6614cfd5004dc7dc35e437ddf9c58Duncan Sands        Diag(PropertyLoc, diag::error_missing_property_ivar_decl) << PropertyId;
369276dcbdc8db6614cfd5004dc7dc35e437ddf9c58Duncan Sands      // Note! I deliberately want it to fall thru so, we have a
370276dcbdc8db6614cfd5004dc7dc35e437ddf9c58Duncan Sands      // a property implementation and to avoid future warnings.
3712041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen    } else if (getLangOptions().ObjCNonFragileABI &&
3722041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen               ClassDeclared != IDecl) {
3734fbd796a1251a27e6590765a0a34876f436a0af9Dan Gohman      Diag(PropertyLoc, diag::error_ivar_in_superclass_use)
3742041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen      << property->getDeclName() << Ivar->getDeclName()
3752041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen      << ClassDeclared->getDeclName();
376eaf089430e7681fcddc3465c3b33b9645273ab02Dale Johannesen      Diag(Ivar->getLocation(), diag::note_previous_access_declaration)
3774fbd796a1251a27e6590765a0a34876f436a0af9Dan Gohman      << Ivar << Ivar->getNameAsCString();
3782041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen      // Note! I deliberately want it to fall thru so more errors are caught.
379eaf089430e7681fcddc3465c3b33b9645273ab02Dale Johannesen    }
3802041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen    QualType IvarType = Context.getCanonicalType(Ivar->getType());
381b3a0417cad8b625acc3033bd5e24afb9ffd0b084Lauro Ramos Venancio
382b3a0417cad8b625acc3033bd5e24afb9ffd0b084Lauro Ramos Venancio    // Check that type of property and its ivar are type compatible.
383b3a0417cad8b625acc3033bd5e24afb9ffd0b084Lauro Ramos Venancio    if (PropType != IvarType) {
384b8d2f550b84523e8a73198f98e5d450ec3b4fee7Dan Gohman      if (CheckAssignmentConstraints(PropType, IvarType) != Compatible) {
3852041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen        Diag(PropertyLoc, diag::error_property_ivar_type)
3862041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen          << property->getDeclName() << PropType
3872a4ed82ce2ba4a02f2a02eb4ed8ce5186f3f93daChris Lattner          << Ivar->getDeclName() << IvarType;
3882041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen        Diag(Ivar->getLocation(), diag::note_ivar_decl);
3892041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen        // Note! I deliberately want it to fall thru so, we have a
3902041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen        // a property implementation and to avoid future warnings.
3912041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen      }
3922041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen
3932041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen      // FIXME! Rules for properties are somewhat different that those
3942041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen      // for assignments. Use a new routine to consolidate all cases;
3952041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen      // specifically for property redeclarations as well as for ivars.
3967f460203b0c5350e9b2c592f438e40f7a7de6e45Dan Gohman      QualType lhsType =Context.getCanonicalType(PropType).getUnqualifiedType();
3977f460203b0c5350e9b2c592f438e40f7a7de6e45Dan Gohman      QualType rhsType =Context.getCanonicalType(IvarType).getUnqualifiedType();
3987f460203b0c5350e9b2c592f438e40f7a7de6e45Dan Gohman      if (lhsType != rhsType &&
3997f460203b0c5350e9b2c592f438e40f7a7de6e45Dan Gohman          lhsType->isArithmeticType()) {
4007f460203b0c5350e9b2c592f438e40f7a7de6e45Dan Gohman        Diag(PropertyLoc, diag::error_property_ivar_type)
4017f460203b0c5350e9b2c592f438e40f7a7de6e45Dan Gohman          << property->getDeclName() << PropType
4027f460203b0c5350e9b2c592f438e40f7a7de6e45Dan Gohman          << Ivar->getDeclName() << IvarType;
40369de1932b350d7cdfc0ed1f4198d6f78c7822a02Dan Gohman        Diag(Ivar->getLocation(), diag::note_ivar_decl);
40469de1932b350d7cdfc0ed1f4198d6f78c7822a02Dan Gohman        // Fall thru - see previous comment
40569de1932b350d7cdfc0ed1f4198d6f78c7822a02Dan Gohman      }
40669de1932b350d7cdfc0ed1f4198d6f78c7822a02Dan Gohman      // __weak is explicit. So it works on Canonical type.
40736b5c1338a03453ba1c110b120269ca972fb65a3Dan Gohman      if (PropType.isObjCGCWeak() && !IvarType.isObjCGCWeak() &&
408b8d2f550b84523e8a73198f98e5d450ec3b4fee7Dan Gohman          getLangOptions().getGCMode() != LangOptions::NonGC) {
4092041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen        Diag(PropertyLoc, diag::error_weak_property)
4102041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen        << property->getDeclName() << Ivar->getDeclName();
4112041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen        // Fall thru - see previous comment
4122041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen      }
4132041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen      if ((property->getType()->isObjCObjectPointerType() ||
4142041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen           PropType.isObjCGCStrong()) && IvarType.isObjCGCWeak() &&
4152041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen          getLangOptions().getGCMode() != LangOptions::NonGC) {
4162041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen        Diag(PropertyLoc, diag::error_strong_property)
4172041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen        << property->getDeclName() << Ivar->getDeclName();
4182041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen        // Fall thru - see previous comment
4192041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen      }
4202041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen    }
421b8d2f550b84523e8a73198f98e5d450ec3b4fee7Dan Gohman  } else if (PropertyIvar)
4222041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen    // @dynamic
4232041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen    Diag(PropertyLoc, diag::error_dynamic_property_ivar_decl);
4242041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen  assert (property && "ActOnPropertyImplDecl - property declaration missing");
4252041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen  ObjCPropertyImplDecl *PIDecl =
4262041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen  ObjCPropertyImplDecl::Create(Context, CurContext, AtLoc, PropertyLoc,
4272041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen                               property,
4282041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen                               (Synthesize ?
4292041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen                                ObjCPropertyImplDecl::Synthesize
4305eb0cecbc5dd370e33d4e0ab1abee7ce8597ca9cDan Gohman                                : ObjCPropertyImplDecl::Dynamic),
4315eb0cecbc5dd370e33d4e0ab1abee7ce8597ca9cDan Gohman                               Ivar);
4325eb0cecbc5dd370e33d4e0ab1abee7ce8597ca9cDan Gohman  if (IC) {
4335eb0cecbc5dd370e33d4e0ab1abee7ce8597ca9cDan Gohman    if (Synthesize)
4345eb0cecbc5dd370e33d4e0ab1abee7ce8597ca9cDan Gohman      if (ObjCPropertyImplDecl *PPIDecl =
4355eb0cecbc5dd370e33d4e0ab1abee7ce8597ca9cDan Gohman          IC->FindPropertyImplIvarDecl(PropertyIvar)) {
4362041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen        Diag(PropertyLoc, diag::error_duplicate_ivar_use)
437b8d2f550b84523e8a73198f98e5d450ec3b4fee7Dan Gohman        << PropertyId << PPIDecl->getPropertyDecl()->getIdentifier()
4383b3adbb7456411957681e590b29697b3af307dd1Duncan Sands        << PropertyIvar;
439a7ce741ff0ab02510833854bfa6a1c8c265faee3Dan Gohman        Diag(PPIDecl->getLocation(), diag::note_previous_use);
4402041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen      }
4412041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen
4422041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen    if (ObjCPropertyImplDecl *PPIDecl
443b8d2f550b84523e8a73198f98e5d450ec3b4fee7Dan Gohman        = IC->FindPropertyImplDecl(PropertyId)) {
4443b3adbb7456411957681e590b29697b3af307dd1Duncan Sands      Diag(PropertyLoc, diag::error_property_implemented) << PropertyId;
445a7ce741ff0ab02510833854bfa6a1c8c265faee3Dan Gohman      Diag(PPIDecl->getLocation(), diag::note_previous_declaration);
4462041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen      return DeclPtrTy();
4472041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen    }
4480b1d4a798d1dd2f39521b6b381cd1c1911c9ab52Dan Gohman    IC->addPropertyImplementation(PIDecl);
4490b1d4a798d1dd2f39521b6b381cd1c1911c9ab52Dan Gohman  } else {
4500b1d4a798d1dd2f39521b6b381cd1c1911c9ab52Dan Gohman    if (Synthesize)
4510b1d4a798d1dd2f39521b6b381cd1c1911c9ab52Dan Gohman      if (ObjCPropertyImplDecl *PPIDecl =
4520b1d4a798d1dd2f39521b6b381cd1c1911c9ab52Dan Gohman          CatImplClass->FindPropertyImplIvarDecl(PropertyIvar)) {
4530b1d4a798d1dd2f39521b6b381cd1c1911c9ab52Dan Gohman        Diag(PropertyLoc, diag::error_duplicate_ivar_use)
4540b1d4a798d1dd2f39521b6b381cd1c1911c9ab52Dan Gohman        << PropertyId << PPIDecl->getPropertyDecl()->getIdentifier()
4550b1d4a798d1dd2f39521b6b381cd1c1911c9ab52Dan Gohman        << PropertyIvar;
4560b1d4a798d1dd2f39521b6b381cd1c1911c9ab52Dan Gohman        Diag(PPIDecl->getLocation(), diag::note_previous_use);
4570b1d4a798d1dd2f39521b6b381cd1c1911c9ab52Dan Gohman      }
4580b1d4a798d1dd2f39521b6b381cd1c1911c9ab52Dan Gohman
4590b1d4a798d1dd2f39521b6b381cd1c1911c9ab52Dan Gohman    if (ObjCPropertyImplDecl *PPIDecl =
460b8d2f550b84523e8a73198f98e5d450ec3b4fee7Dan Gohman        CatImplClass->FindPropertyImplDecl(PropertyId)) {
461a7ce741ff0ab02510833854bfa6a1c8c265faee3Dan Gohman      Diag(PropertyLoc, diag::error_property_implemented) << PropertyId;
462a7ce741ff0ab02510833854bfa6a1c8c265faee3Dan Gohman      Diag(PPIDecl->getLocation(), diag::note_previous_declaration);
46328873106309db515d58889a4c4fa3e0a92d1b60eMon P Wang      return DeclPtrTy();
464583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey    }
4659008ca6b6b4f638cfafccb593cbc5b1d3f5ab877Nate Begeman    CatImplClass->addPropertyImplementation(PIDecl);
4669008ca6b6b4f638cfafccb593cbc5b1d3f5ab877Nate Begeman  }
4679008ca6b6b4f638cfafccb593cbc5b1d3f5ab877Nate Begeman
4689008ca6b6b4f638cfafccb593cbc5b1d3f5ab877Nate Begeman  return DeclPtrTy::make(PIDecl);
4699008ca6b6b4f638cfafccb593cbc5b1d3f5ab877Nate Begeman}
4709008ca6b6b4f638cfafccb593cbc5b1d3f5ab877Nate Begeman
4719008ca6b6b4f638cfafccb593cbc5b1d3f5ab877Nate Begeman//===----------------------------------------------------------------------===//
47228873106309db515d58889a4c4fa3e0a92d1b60eMon P Wang// Helper methods.
473583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey//===----------------------------------------------------------------------===//
474583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey
4750dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands/// DiagnosePropertyMismatch - Compares two properties for their
4760dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands/// attributes and types and warns on a variety of inconsistencies.
4770dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands///
4780dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sandsvoid
4790dc4045bd27c177416745d2e72277b0a92c3ab83Duncan SandsSema::DiagnosePropertyMismatch(ObjCPropertyDecl *Property,
4800dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands                               ObjCPropertyDecl *SuperProperty,
4810dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands                               const IdentifierInfo *inheritedName) {
4820dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands  ObjCPropertyDecl::PropertyAttributeKind CAttr =
4830dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands  Property->getPropertyAttributes();
4840dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands  ObjCPropertyDecl::PropertyAttributeKind SAttr =
4850dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands  SuperProperty->getPropertyAttributes();
4860dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands  if ((CAttr & ObjCPropertyDecl::OBJC_PR_readonly)
4870dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands      && (SAttr & ObjCPropertyDecl::OBJC_PR_readwrite))
488b8d2f550b84523e8a73198f98e5d450ec3b4fee7Dan Gohman    Diag(Property->getLocation(), diag::warn_readonly_property)
489a7ce741ff0ab02510833854bfa6a1c8c265faee3Dan Gohman      << Property->getDeclName() << inheritedName;
490a7ce741ff0ab02510833854bfa6a1c8c265faee3Dan Gohman  if ((CAttr & ObjCPropertyDecl::OBJC_PR_copy)
491b8d2f550b84523e8a73198f98e5d450ec3b4fee7Dan Gohman      != (SAttr & ObjCPropertyDecl::OBJC_PR_copy))
492a1dc6025422cd0e6f951c69a8427f7f885cf52c3Bill Wendling    Diag(Property->getLocation(), diag::warn_property_attribute)
493a7ce741ff0ab02510833854bfa6a1c8c265faee3Dan Gohman      << Property->getDeclName() << "copy" << inheritedName;
494a7ce741ff0ab02510833854bfa6a1c8c265faee3Dan Gohman  else if ((CAttr & ObjCPropertyDecl::OBJC_PR_retain)
495a7ce741ff0ab02510833854bfa6a1c8c265faee3Dan Gohman           != (SAttr & ObjCPropertyDecl::OBJC_PR_retain))
496a7ce741ff0ab02510833854bfa6a1c8c265faee3Dan Gohman    Diag(Property->getLocation(), diag::warn_property_attribute)
497a7ce741ff0ab02510833854bfa6a1c8c265faee3Dan Gohman      << Property->getDeclName() << "retain" << inheritedName;
498a7ce741ff0ab02510833854bfa6a1c8c265faee3Dan Gohman
499a7ce741ff0ab02510833854bfa6a1c8c265faee3Dan Gohman  if ((CAttr & ObjCPropertyDecl::OBJC_PR_nonatomic)
500a7ce741ff0ab02510833854bfa6a1c8c265faee3Dan Gohman      != (SAttr & ObjCPropertyDecl::OBJC_PR_nonatomic))
501a7ce741ff0ab02510833854bfa6a1c8c265faee3Dan Gohman    Diag(Property->getLocation(), diag::warn_property_attribute)
502a7ce741ff0ab02510833854bfa6a1c8c265faee3Dan Gohman      << Property->getDeclName() << "atomic" << inheritedName;
503b8d2f550b84523e8a73198f98e5d450ec3b4fee7Dan Gohman  if (Property->getSetterName() != SuperProperty->getSetterName())
504b8d2f550b84523e8a73198f98e5d450ec3b4fee7Dan Gohman    Diag(Property->getLocation(), diag::warn_property_attribute)
505583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey      << Property->getDeclName() << "setter" << inheritedName;
50658b968be853ef02d0f448e5e2c31676e361c210fJim Laskey  if (Property->getGetterName() != SuperProperty->getGetterName())
50758b968be853ef02d0f448e5e2c31676e361c210fJim Laskey    Diag(Property->getLocation(), diag::warn_property_attribute)
508b48da3953642d3d006edebd7fc6c1ca5bcfdb5cdChris Lattner      << Property->getDeclName() << "getter" << inheritedName;
5090dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands
5100dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands  QualType LHSType =
5110dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands    Context.getCanonicalType(SuperProperty->getType());
5120dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands  QualType RHSType =
5130dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands    Context.getCanonicalType(Property->getType());
5140dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands
5150dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands  if (!Context.typesAreCompatible(LHSType, RHSType)) {
5160dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands    // FIXME: Incorporate this test with typesAreCompatible.
5170dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands    if (LHSType->isObjCQualifiedIdType() && RHSType->isObjCQualifiedIdType())
5180dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands      if (Context.ObjCQualifiedIdTypesAreCompatible(LHSType, RHSType, false))
5190dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands        return;
5200dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands    Diag(Property->getLocation(), diag::warn_property_types_are_incompatible)
5210dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands      << Property->getType() << SuperProperty->getType() << inheritedName;
5220dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands  }
5230dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands}
5240dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands
5250dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sandsbool Sema::DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *property,
5260dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands                                            ObjCMethodDecl *GetterMethod,
5270dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands                                            SourceLocation Loc) {
5280dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands  if (GetterMethod &&
5290dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands      GetterMethod->getResultType() != property->getType()) {
5300dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands    AssignConvertType result = Incompatible;
5310dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands    if (property->getType()->isObjCObjectPointerType())
5320e12e6e0418564d4b2e83138fe2044be29a6f6d5Chris Lattner      result = CheckAssignmentConstraints(GetterMethod->getResultType(),
533190a418bf6b49a4ef1c1980229a2f0d516e8a2cdChris Lattner                                          property->getType());
534190a418bf6b49a4ef1c1980229a2f0d516e8a2cdChris Lattner    if (result != Compatible) {
5350e12e6e0418564d4b2e83138fe2044be29a6f6d5Chris Lattner      Diag(Loc, diag::warn_accessor_property_type_mismatch)
5360e12e6e0418564d4b2e83138fe2044be29a6f6d5Chris Lattner      << property->getDeclName()
5379503859c545496838165a340b1e1730dc1b83736Chris Lattner      << GetterMethod->getSelector();
5380e12e6e0418564d4b2e83138fe2044be29a6f6d5Chris Lattner      Diag(GetterMethod->getLocation(), diag::note_declared_at);
539190a418bf6b49a4ef1c1980229a2f0d516e8a2cdChris Lattner      return true;
540fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel    }
541190a418bf6b49a4ef1c1980229a2f0d516e8a2cdChris Lattner  }
542de202b3cda00f17ba2c047be7270b51f9585a413Chris Lattner  return false;
543190a418bf6b49a4ef1c1980229a2f0d516e8a2cdChris Lattner}
544190a418bf6b49a4ef1c1980229a2f0d516e8a2cdChris Lattner
545190a418bf6b49a4ef1c1980229a2f0d516e8a2cdChris Lattner/// ComparePropertiesInBaseAndSuper - This routine compares property
5460fe9c6e7babb3c0731d9cb864ec498ec4184760fDan Gohman/// declarations in base and its super class, if any, and issues
547fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel/// diagnostics in a variety of inconsistant situations.
5480e12e6e0418564d4b2e83138fe2044be29a6f6d5Chris Lattner///
5499503859c545496838165a340b1e1730dc1b83736Chris Lattnervoid Sema::ComparePropertiesInBaseAndSuper(ObjCInterfaceDecl *IDecl) {
5500e12e6e0418564d4b2e83138fe2044be29a6f6d5Chris Lattner  ObjCInterfaceDecl *SDecl = IDecl->getSuperClass();
5510e12e6e0418564d4b2e83138fe2044be29a6f6d5Chris Lattner  if (!SDecl)
5520fe9c6e7babb3c0731d9cb864ec498ec4184760fDan Gohman    return;
5530fe9c6e7babb3c0731d9cb864ec498ec4184760fDan Gohman  // FIXME: O(N^2)
5540fe9c6e7babb3c0731d9cb864ec498ec4184760fDan Gohman  for (ObjCInterfaceDecl::prop_iterator S = SDecl->prop_begin(),
5550fe9c6e7babb3c0731d9cb864ec498ec4184760fDan Gohman       E = SDecl->prop_end(); S != E; ++S) {
556130a6471b90f66e99b1f9f42877fdf611c330ac6Evan Cheng    ObjCPropertyDecl *SuperPDecl = (*S);
557130a6471b90f66e99b1f9f42877fdf611c330ac6Evan Cheng    // Does property in super class has declaration in current class?
558130a6471b90f66e99b1f9f42877fdf611c330ac6Evan Cheng    for (ObjCInterfaceDecl::prop_iterator I = IDecl->prop_begin(),
559130a6471b90f66e99b1f9f42877fdf611c330ac6Evan Cheng         E = IDecl->prop_end(); I != E; ++I) {
560e7852d014432a06c783de3c350eb96e686f10f92Dan Gohman      ObjCPropertyDecl *PDecl = (*I);
561fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel      if (SuperPDecl->getIdentifier() == PDecl->getIdentifier())
562f8dc0617baceeba8ccd67c8881eb88eb1be2902cChris Lattner          DiagnosePropertyMismatch(PDecl, SuperPDecl,
563edfcf598faab9ce294712551ecf67093acd1c66eDuncan Sands                                   SDecl->getIdentifier());
564fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel    }
565130a6471b90f66e99b1f9f42877fdf611c330ac6Evan Cheng  }
566130a6471b90f66e99b1f9f42877fdf611c330ac6Evan Cheng}
567130a6471b90f66e99b1f9f42877fdf611c330ac6Evan Cheng
568130a6471b90f66e99b1f9f42877fdf611c330ac6Evan Cheng/// MatchOneProtocolPropertiesInClass - This routine goes thru the list
569130a6471b90f66e99b1f9f42877fdf611c330ac6Evan Cheng/// of properties declared in a protocol and compares their attribute against
570e7852d014432a06c783de3c350eb96e686f10f92Dan Gohman/// the same property declared in the class or category.
571e7852d014432a06c783de3c350eb96e686f10f92Dan Gohmanvoid
572e7852d014432a06c783de3c350eb96e686f10f92Dan GohmanSema::MatchOneProtocolPropertiesInClass(Decl *CDecl,
573e7852d014432a06c783de3c350eb96e686f10f92Dan Gohman                                          ObjCProtocolDecl *PDecl) {
574e7852d014432a06c783de3c350eb96e686f10f92Dan Gohman  ObjCInterfaceDecl *IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(CDecl);
575130a6471b90f66e99b1f9f42877fdf611c330ac6Evan Cheng  if (!IDecl) {
576130a6471b90f66e99b1f9f42877fdf611c330ac6Evan Cheng    // Category
577130a6471b90f66e99b1f9f42877fdf611c330ac6Evan Cheng    ObjCCategoryDecl *CatDecl = static_cast<ObjCCategoryDecl*>(CDecl);
578130a6471b90f66e99b1f9f42877fdf611c330ac6Evan Cheng    assert (CatDecl && "MatchOneProtocolPropertiesInClass");
579a1dc6025422cd0e6f951c69a8427f7f885cf52c3Bill Wendling    if (!CatDecl->IsClassExtension())
580c53361294957b63a9c1e405256c6f0a81db1685cDan Gohman      for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(),
581130a6471b90f66e99b1f9f42877fdf611c330ac6Evan Cheng           E = PDecl->prop_end(); P != E; ++P) {
582130a6471b90f66e99b1f9f42877fdf611c330ac6Evan Cheng        ObjCPropertyDecl *Pr = (*P);
583130a6471b90f66e99b1f9f42877fdf611c330ac6Evan Cheng        ObjCCategoryDecl::prop_iterator CP, CE;
5840fe9c6e7babb3c0731d9cb864ec498ec4184760fDan Gohman        // Is this property already in  category's list of properties?
585e8be6c63915e0389f1eef6b53c64300d13b2ce99Dan Gohman        for (CP = CatDecl->prop_begin(), CE = CatDecl->prop_end(); CP!=CE; ++CP)
5860fe9c6e7babb3c0731d9cb864ec498ec4184760fDan Gohman          if ((*CP)->getIdentifier() == Pr->getIdentifier())
5870fe9c6e7babb3c0731d9cb864ec498ec4184760fDan Gohman            break;
5880fe9c6e7babb3c0731d9cb864ec498ec4184760fDan Gohman        if (CP != CE)
589c26aefa15ae7f02b37923f6fed5a74d60e76ff56Chris Lattner          // Property protocol already exist in class. Diagnose any mismatch.
590c26aefa15ae7f02b37923f6fed5a74d60e76ff56Chris Lattner          DiagnosePropertyMismatch((*CP), Pr, PDecl->getIdentifier());
591c26aefa15ae7f02b37923f6fed5a74d60e76ff56Chris Lattner      }
592c26aefa15ae7f02b37923f6fed5a74d60e76ff56Chris Lattner    return;
593fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel  }
5941e111c7bbb50eec1cb1ebc7d12fcfb22c36f8d87Chris Lattner  for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(),
5951e111c7bbb50eec1cb1ebc7d12fcfb22c36f8d87Chris Lattner       E = PDecl->prop_end(); P != E; ++P) {
5961e111c7bbb50eec1cb1ebc7d12fcfb22c36f8d87Chris Lattner    ObjCPropertyDecl *Pr = (*P);
5971e111c7bbb50eec1cb1ebc7d12fcfb22c36f8d87Chris Lattner    ObjCInterfaceDecl::prop_iterator CP, CE;
5981e111c7bbb50eec1cb1ebc7d12fcfb22c36f8d87Chris Lattner    // Is this property already in  class's list of properties?
599e77f89de8cb6690ac45b87b03c588e9d287c1eebDan Gohman    for (CP = IDecl->prop_begin(), CE = IDecl->prop_end(); CP != CE; ++CP)
600e77f89de8cb6690ac45b87b03c588e9d287c1eebDan Gohman      if ((*CP)->getIdentifier() == Pr->getIdentifier())
601c53361294957b63a9c1e405256c6f0a81db1685cDan Gohman        break;
602f06c835f769aa1cf67801ed1f6bd366a447c18b1Dan Gohman    if (CP != CE)
603e7852d014432a06c783de3c350eb96e686f10f92Dan Gohman      // Property protocol already exist in class. Diagnose any mismatch.
604a1dc6025422cd0e6f951c69a8427f7f885cf52c3Bill Wendling      DiagnosePropertyMismatch((*CP), Pr, PDecl->getIdentifier());
605c53361294957b63a9c1e405256c6f0a81db1685cDan Gohman    }
606c53361294957b63a9c1e405256c6f0a81db1685cDan Gohman}
607c53361294957b63a9c1e405256c6f0a81db1685cDan Gohman
608c53361294957b63a9c1e405256c6f0a81db1685cDan Gohman/// CompareProperties - This routine compares properties
609c53361294957b63a9c1e405256c6f0a81db1685cDan Gohman/// declared in 'ClassOrProtocol' objects (which can be a class or an
61063e3f14df6cf76f1a12de1153e1114f4b20b15a9Chris Lattner/// inherited protocol with the list of properties for class/category 'CDecl'
611fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel///
612c53361294957b63a9c1e405256c6f0a81db1685cDan Gohmanvoid Sema::CompareProperties(Decl *CDecl,
613c53361294957b63a9c1e405256c6f0a81db1685cDan Gohman                             DeclPtrTy ClassOrProtocol) {
614c53361294957b63a9c1e405256c6f0a81db1685cDan Gohman  Decl *ClassDecl = ClassOrProtocol.getAs<Decl>();
615c53361294957b63a9c1e405256c6f0a81db1685cDan Gohman  ObjCInterfaceDecl *IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(CDecl);
6161146728bfaeb471f675b805ceb27a08d28bbf468Dan Gohman
617c26aefa15ae7f02b37923f6fed5a74d60e76ff56Chris Lattner  if (!IDecl) {
618c26aefa15ae7f02b37923f6fed5a74d60e76ff56Chris Lattner    // Category
619149c58ce0b94e64faf3c4ccdbf894061cf7d66e1Chris Lattner    ObjCCategoryDecl *CatDecl = static_cast<ObjCCategoryDecl*>(CDecl);
620149c58ce0b94e64faf3c4ccdbf894061cf7d66e1Chris Lattner    assert (CatDecl && "CompareProperties");
621149c58ce0b94e64faf3c4ccdbf894061cf7d66e1Chris Lattner    if (ObjCCategoryDecl *MDecl = dyn_cast<ObjCCategoryDecl>(ClassDecl)) {
622149c58ce0b94e64faf3c4ccdbf894061cf7d66e1Chris Lattner      for (ObjCCategoryDecl::protocol_iterator P = MDecl->protocol_begin(),
623095cc29f321382e1f7d295e262a28197f92c5491Dan Gohman           E = MDecl->protocol_end(); P != E; ++P)
6246621e3b9636174886c9665b648f2ddc13effbc8aChris Lattner      // Match properties of category with those of protocol (*P)
6250e12e6e0418564d4b2e83138fe2044be29a6f6d5Chris Lattner      MatchOneProtocolPropertiesInClass(CatDecl, *P);
626f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman
627f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman      // Go thru the list of protocols for this category and recursively match
628095cc29f321382e1f7d295e262a28197f92c5491Dan Gohman      // their properties with those in the category.
629095cc29f321382e1f7d295e262a28197f92c5491Dan Gohman      for (ObjCCategoryDecl::protocol_iterator P = CatDecl->protocol_begin(),
6307cf7e3f33f25544d08492d47cc8a1cbba25dc8d7Chris Lattner           E = CatDecl->protocol_end(); P != E; ++P)
6317cf7e3f33f25544d08492d47cc8a1cbba25dc8d7Chris Lattner        CompareProperties(CatDecl, DeclPtrTy::make(*P));
6327cf7e3f33f25544d08492d47cc8a1cbba25dc8d7Chris Lattner    } else {
6336621e3b9636174886c9665b648f2ddc13effbc8aChris Lattner      ObjCProtocolDecl *MD = cast<ObjCProtocolDecl>(ClassDecl);
6347cf7e3f33f25544d08492d47cc8a1cbba25dc8d7Chris Lattner      for (ObjCProtocolDecl::protocol_iterator P = MD->protocol_begin(),
6357cf7e3f33f25544d08492d47cc8a1cbba25dc8d7Chris Lattner           E = MD->protocol_end(); P != E; ++P)
636056292fd738924f3f7703725d8f630983794b5a5Bill Wendling        MatchOneProtocolPropertiesInClass(CatDecl, *P);
637056292fd738924f3f7703725d8f630983794b5a5Bill Wendling    }
6380e12e6e0418564d4b2e83138fe2044be29a6f6d5Chris Lattner    return;
6391af2231da64a14d638406d133c7912bfc1c8a9ceChris Lattner  }
6401af2231da64a14d638406d133c7912bfc1c8a9ceChris Lattner
6411af2231da64a14d638406d133c7912bfc1c8a9ceChris Lattner  if (ObjCInterfaceDecl *MDecl = dyn_cast<ObjCInterfaceDecl>(ClassDecl)) {
6421af2231da64a14d638406d133c7912bfc1c8a9ceChris Lattner    for (ObjCInterfaceDecl::protocol_iterator P = MDecl->protocol_begin(),
6431af2231da64a14d638406d133c7912bfc1c8a9ceChris Lattner         E = MDecl->protocol_end(); P != E; ++P)
6442a2de66db2093a5bc1fd620d1b6ae7992a552b24Andrew Lenharth      // Match properties of class IDecl with those of protocol (*P).
6451af2231da64a14d638406d133c7912bfc1c8a9ceChris Lattner      MatchOneProtocolPropertiesInClass(IDecl, *P);
646f411b83c8c6853c2a922b692e782566353153f08Duncan Sands
64783ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands    // Go thru the list of protocols for this class and recursively match
64883ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands    // their properties with those declared in the class.
649f411b83c8c6853c2a922b692e782566353153f08Duncan Sands    for (ObjCInterfaceDecl::protocol_iterator P = IDecl->protocol_begin(),
650f411b83c8c6853c2a922b692e782566353153f08Duncan Sands         E = IDecl->protocol_end(); P != E; ++P)
65183ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands      CompareProperties(IDecl, DeclPtrTy::make(*P));
65283ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands  } else {
653f411b83c8c6853c2a922b692e782566353153f08Duncan Sands    ObjCProtocolDecl *MD = cast<ObjCProtocolDecl>(ClassDecl);
65415e4b01920d6a0ffbe35d3e5aa88a4b42970b6a7Chris Lattner    for (ObjCProtocolDecl::protocol_iterator P = MD->protocol_begin(),
655f411b83c8c6853c2a922b692e782566353153f08Duncan Sands         E = MD->protocol_end(); P != E; ++P)
6560e12e6e0418564d4b2e83138fe2044be29a6f6d5Chris Lattner      MatchOneProtocolPropertiesInClass(IDecl, *P);
6574a283e90af7984762eb3e984cee747d32c82e3dbChris Lattner  }
6584a283e90af7984762eb3e984cee747d32c82e3dbChris Lattner}
6590e12e6e0418564d4b2e83138fe2044be29a6f6d5Chris Lattner
6600e12e6e0418564d4b2e83138fe2044be29a6f6d5Chris Lattner/// isPropertyReadonly - Return true if property is readonly, by searching
6616621e3b9636174886c9665b648f2ddc13effbc8aChris Lattner/// for the property in the class and in its categories and implementations
662fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel///
6636621e3b9636174886c9665b648f2ddc13effbc8aChris Lattnerbool Sema::isPropertyReadonly(ObjCPropertyDecl *PDecl,
6646621e3b9636174886c9665b648f2ddc13effbc8aChris Lattner                              ObjCInterfaceDecl *IDecl) {
6656621e3b9636174886c9665b648f2ddc13effbc8aChris Lattner  // by far the most common case.
6660dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands  if (!PDecl->isReadOnly())
667b5bec2b6f6f4a4da96170d1c258ad424112ad2c5Dan Gohman    return false;
668832171cb9724d2d31c8dfb73172e2be8f6dd13eeBill Wendling  // Even if property is ready only, if interface has a user defined setter,
6696621e3b9636174886c9665b648f2ddc13effbc8aChris Lattner  // it is not considered read only.
6706621e3b9636174886c9665b648f2ddc13effbc8aChris Lattner  if (IDecl->getInstanceMethod(PDecl->getSetterName()))
6716621e3b9636174886c9665b648f2ddc13effbc8aChris Lattner    return false;
672095cc29f321382e1f7d295e262a28197f92c5491Dan Gohman
6730e12e6e0418564d4b2e83138fe2044be29a6f6d5Chris Lattner  // Main class has the property as 'readonly'. Must search
6740e12e6e0418564d4b2e83138fe2044be29a6f6d5Chris Lattner  // through the category list to see if the property's
675399461095b033438d1f5863cd0d6f82a616f74dcDan Gohman  // attribute has been over-ridden to 'readwrite'.
676399461095b033438d1f5863cd0d6f82a616f74dcDan Gohman  for (ObjCCategoryDecl *Category = IDecl->getCategoryList();
677399461095b033438d1f5863cd0d6f82a616f74dcDan Gohman       Category; Category = Category->getNextClassCategory()) {
678399461095b033438d1f5863cd0d6f82a616f74dcDan Gohman    // Even if property is ready only, if a category has a user defined setter,
6798b8749f367fd30a8a3d57284576a6d59b60b69ebChris Lattner    // it is not considered read only.
680399461095b033438d1f5863cd0d6f82a616f74dcDan Gohman    if (Category->getInstanceMethod(PDecl->getSetterName()))
681399461095b033438d1f5863cd0d6f82a616f74dcDan Gohman      return false;
682399461095b033438d1f5863cd0d6f82a616f74dcDan Gohman    ObjCPropertyDecl *P =
683399461095b033438d1f5863cd0d6f82a616f74dcDan Gohman      Category->FindPropertyDeclaration(PDecl->getIdentifier());
684399461095b033438d1f5863cd0d6f82a616f74dcDan Gohman    if (P && !P->isReadOnly())
685399461095b033438d1f5863cd0d6f82a616f74dcDan Gohman      return false;
686399461095b033438d1f5863cd0d6f82a616f74dcDan Gohman  }
687399461095b033438d1f5863cd0d6f82a616f74dcDan Gohman
688399461095b033438d1f5863cd0d6f82a616f74dcDan Gohman  // Also, check for definition of a setter method in the implementation if
689399461095b033438d1f5863cd0d6f82a616f74dcDan Gohman  // all else failed.
690399461095b033438d1f5863cd0d6f82a616f74dcDan Gohman  if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(CurContext)) {
691399461095b033438d1f5863cd0d6f82a616f74dcDan Gohman    if (ObjCImplementationDecl *IMD =
692399461095b033438d1f5863cd0d6f82a616f74dcDan Gohman        dyn_cast<ObjCImplementationDecl>(OMD->getDeclContext())) {
693399461095b033438d1f5863cd0d6f82a616f74dcDan Gohman      if (IMD->getInstanceMethod(PDecl->getSetterName()))
694fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel        return false;
695399461095b033438d1f5863cd0d6f82a616f74dcDan Gohman    } else if (ObjCCategoryImplDecl *CIMD =
696399461095b033438d1f5863cd0d6f82a616f74dcDan Gohman               dyn_cast<ObjCCategoryImplDecl>(OMD->getDeclContext())) {
697399461095b033438d1f5863cd0d6f82a616f74dcDan Gohman      if (CIMD->getInstanceMethod(PDecl->getSetterName()))
698399461095b033438d1f5863cd0d6f82a616f74dcDan Gohman        return false;
699399461095b033438d1f5863cd0d6f82a616f74dcDan Gohman    }
70071e8685633e7938ee752004cceedccbd0d850527Evan Cheng  }
701399461095b033438d1f5863cd0d6f82a616f74dcDan Gohman  // Lastly, look through the implementation (if one is in scope).
702399461095b033438d1f5863cd0d6f82a616f74dcDan Gohman  if (ObjCImplementationDecl *ImpDecl = IDecl->getImplementation())
703fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel    if (ImpDecl->getInstanceMethod(PDecl->getSetterName()))
704399461095b033438d1f5863cd0d6f82a616f74dcDan Gohman      return false;
7058b8749f367fd30a8a3d57284576a6d59b60b69ebChris Lattner  // If all fails, look at the super class.
7068b8749f367fd30a8a3d57284576a6d59b60b69ebChris Lattner  if (ObjCInterfaceDecl *SIDecl = IDecl->getSuperClass())
707df6eb30fa9bc8600862cae18fce66da466188323Chris Lattner    return isPropertyReadonly(PDecl, SIDecl);
708fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel  return true;
709df6eb30fa9bc8600862cae18fce66da466188323Chris Lattner}
710df6eb30fa9bc8600862cae18fce66da466188323Chris Lattner
711475871a144eb604ddaf37503397ba0941442e5fbDan Gohman/// CollectImmediateProperties - This routine collects all properties in
712a5682853b9921bbb0dd2ee175c9bd44142d4819eChris Lattner/// the class and its conforming protocols; but not those it its super class.
7130dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sandsvoid Sema::CollectImmediateProperties(ObjCContainerDecl *CDecl,
7140dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands                llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& PropMap) {
71571e8685633e7938ee752004cceedccbd0d850527Evan Cheng  if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl)) {
716475871a144eb604ddaf37503397ba0941442e5fbDan Gohman    for (ObjCContainerDecl::prop_iterator P = IDecl->prop_begin(),
717583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey         E = IDecl->prop_end(); P != E; ++P) {
71863e3f14df6cf76f1a12de1153e1114f4b20b15a9Chris Lattner      ObjCPropertyDecl *Prop = (*P);
7190dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands      PropMap[Prop->getIdentifier()] = Prop;
720a5682853b9921bbb0dd2ee175c9bd44142d4819eChris Lattner    }
721df6eb30fa9bc8600862cae18fce66da466188323Chris Lattner    // scan through class's protocols.
722df6eb30fa9bc8600862cae18fce66da466188323Chris Lattner    for (ObjCInterfaceDecl::protocol_iterator PI = IDecl->protocol_begin(),
723df6eb30fa9bc8600862cae18fce66da466188323Chris Lattner         E = IDecl->protocol_end(); PI != E; ++PI)
724fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel      CollectImmediateProperties((*PI), PropMap);
725df6eb30fa9bc8600862cae18fce66da466188323Chris Lattner  }
726df6eb30fa9bc8600862cae18fce66da466188323Chris Lattner  if (ObjCCategoryDecl *CATDecl = dyn_cast<ObjCCategoryDecl>(CDecl)) {
727fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel    if (!CATDecl->IsClassExtension())
728475871a144eb604ddaf37503397ba0941442e5fbDan Gohman      for (ObjCContainerDecl::prop_iterator P = CATDecl->prop_begin(),
729a5682853b9921bbb0dd2ee175c9bd44142d4819eChris Lattner           E = CATDecl->prop_end(); P != E; ++P) {
7300dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands        ObjCPropertyDecl *Prop = (*P);
7310dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands        PropMap[Prop->getIdentifier()] = Prop;
7320dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands      }
733475871a144eb604ddaf37503397ba0941442e5fbDan Gohman    // scan through class's protocols.
734583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey    for (ObjCInterfaceDecl::protocol_iterator PI = CATDecl->protocol_begin(),
73563e3f14df6cf76f1a12de1153e1114f4b20b15a9Chris Lattner         E = CATDecl->protocol_end(); PI != E; ++PI)
7360dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands      CollectImmediateProperties((*PI), PropMap);
737a5682853b9921bbb0dd2ee175c9bd44142d4819eChris Lattner  }
738df6eb30fa9bc8600862cae18fce66da466188323Chris Lattner  else if (ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(CDecl)) {
739df6eb30fa9bc8600862cae18fce66da466188323Chris Lattner    for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(),
740df6eb30fa9bc8600862cae18fce66da466188323Chris Lattner         E = PDecl->prop_end(); P != E; ++P) {
741df6eb30fa9bc8600862cae18fce66da466188323Chris Lattner      ObjCPropertyDecl *Prop = (*P);
742fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel      ObjCPropertyDecl *&PropEntry = PropMap[Prop->getIdentifier()];
743df6eb30fa9bc8600862cae18fce66da466188323Chris Lattner      if (!PropEntry)
744df6eb30fa9bc8600862cae18fce66da466188323Chris Lattner        PropEntry = Prop;
745fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel    }
746475871a144eb604ddaf37503397ba0941442e5fbDan Gohman    // scan through protocol's protocols.
747a5682853b9921bbb0dd2ee175c9bd44142d4819eChris Lattner    for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(),
7480dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands         E = PDecl->protocol_end(); PI != E; ++PI)
7490dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands      CollectImmediateProperties((*PI), PropMap);
75071e8685633e7938ee752004cceedccbd0d850527Evan Cheng  }
751583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey}
752575e2f4ea874deae3af8a940f30df5348d272190Dan Gohman
7530dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands/// LookupPropertyDecl - Looks up a property in the current class and all
754a5682853b9921bbb0dd2ee175c9bd44142d4819eChris Lattner/// its protocols.
755df6eb30fa9bc8600862cae18fce66da466188323Chris LattnerObjCPropertyDecl *Sema::LookupPropertyDecl(const ObjCContainerDecl *CDecl,
7568b8749f367fd30a8a3d57284576a6d59b60b69ebChris Lattner                                     IdentifierInfo *II) {
757d038e04188047eca4749d025ef1f05f7ae660bcaDuncan Sands  if (const ObjCInterfaceDecl *IDecl =
758d038e04188047eca4749d025ef1f05f7ae660bcaDuncan Sands        dyn_cast<ObjCInterfaceDecl>(CDecl)) {
759d038e04188047eca4749d025ef1f05f7ae660bcaDuncan Sands    for (ObjCContainerDecl::prop_iterator P = IDecl->prop_begin(),
760d038e04188047eca4749d025ef1f05f7ae660bcaDuncan Sands         E = IDecl->prop_end(); P != E; ++P) {
761d038e04188047eca4749d025ef1f05f7ae660bcaDuncan Sands      ObjCPropertyDecl *Prop = (*P);
762d22ec5f62813f8cf2ed8091f44a14377209b1a59Duncan Sands      if (Prop->getIdentifier() == II)
763d22ec5f62813f8cf2ed8091f44a14377209b1a59Duncan Sands        return Prop;
764d22ec5f62813f8cf2ed8091f44a14377209b1a59Duncan Sands    }
765d22ec5f62813f8cf2ed8091f44a14377209b1a59Duncan Sands    // scan through class's protocols.
766d22ec5f62813f8cf2ed8091f44a14377209b1a59Duncan Sands    for (ObjCInterfaceDecl::protocol_iterator PI = IDecl->protocol_begin(),
767d22ec5f62813f8cf2ed8091f44a14377209b1a59Duncan Sands         E = IDecl->protocol_end(); PI != E; ++PI) {
768d22ec5f62813f8cf2ed8091f44a14377209b1a59Duncan Sands      ObjCPropertyDecl *Prop = LookupPropertyDecl((*PI), II);
769d22ec5f62813f8cf2ed8091f44a14377209b1a59Duncan Sands      if (Prop)
770d22ec5f62813f8cf2ed8091f44a14377209b1a59Duncan Sands        return Prop;
771d22ec5f62813f8cf2ed8091f44a14377209b1a59Duncan Sands    }
772d22ec5f62813f8cf2ed8091f44a14377209b1a59Duncan Sands  }
773d22ec5f62813f8cf2ed8091f44a14377209b1a59Duncan Sands  else if (const ObjCProtocolDecl *PDecl =
774d22ec5f62813f8cf2ed8091f44a14377209b1a59Duncan Sands            dyn_cast<ObjCProtocolDecl>(CDecl)) {
775d22ec5f62813f8cf2ed8091f44a14377209b1a59Duncan Sands    for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(),
776d038e04188047eca4749d025ef1f05f7ae660bcaDuncan Sands         E = PDecl->prop_end(); P != E; ++P) {
777d22ec5f62813f8cf2ed8091f44a14377209b1a59Duncan Sands      ObjCPropertyDecl *Prop = (*P);
778d22ec5f62813f8cf2ed8091f44a14377209b1a59Duncan Sands      if (Prop->getIdentifier() == II)
779d038e04188047eca4749d025ef1f05f7ae660bcaDuncan Sands        return Prop;
780d22ec5f62813f8cf2ed8091f44a14377209b1a59Duncan Sands    }
78115684b29552393553524171bff1913e750f390f8Rafael Espindola    // scan through protocol's protocols.
78215684b29552393553524171bff1913e750f390f8Rafael Espindola    for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(),
78315684b29552393553524171bff1913e750f390f8Rafael Espindola         E = PDecl->protocol_end(); PI != E; ++PI) {
7849008ca6b6b4f638cfafccb593cbc5b1d3f5ab877Nate Begeman      ObjCPropertyDecl *Prop = LookupPropertyDecl((*PI), II);
7859008ca6b6b4f638cfafccb593cbc5b1d3f5ab877Nate Begeman      if (Prop)
7869008ca6b6b4f638cfafccb593cbc5b1d3f5ab877Nate Begeman        return Prop;
787d038e04188047eca4749d025ef1f05f7ae660bcaDuncan Sands    }
788d038e04188047eca4749d025ef1f05f7ae660bcaDuncan Sands  }
789d038e04188047eca4749d025ef1f05f7ae660bcaDuncan Sands  return 0;
790d038e04188047eca4749d025ef1f05f7ae660bcaDuncan Sands}
791d038e04188047eca4749d025ef1f05f7ae660bcaDuncan Sands
7929c6e70eca9a49c146b26621cbcbb9464ceeac024Dan Gohman
7939c6e70eca9a49c146b26621cbcbb9464ceeac024Dan Gohmanvoid Sema::DiagnoseUnimplementedProperties(ObjCImplDecl* IMPDecl,
7949c6e70eca9a49c146b26621cbcbb9464ceeac024Dan Gohman                                      ObjCContainerDecl *CDecl,
7959c6e70eca9a49c146b26621cbcbb9464ceeac024Dan Gohman                                      const llvm::DenseSet<Selector>& InsMap) {
7969c6e70eca9a49c146b26621cbcbb9464ceeac024Dan Gohman  llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*> PropMap;
7979c6e70eca9a49c146b26621cbcbb9464ceeac024Dan Gohman  CollectImmediateProperties(CDecl, PropMap);
7989c6e70eca9a49c146b26621cbcbb9464ceeac024Dan Gohman  if (PropMap.empty())
7999c6e70eca9a49c146b26621cbcbb9464ceeac024Dan Gohman    return;
8009c6e70eca9a49c146b26621cbcbb9464ceeac024Dan Gohman
8019c6e70eca9a49c146b26621cbcbb9464ceeac024Dan Gohman  llvm::DenseSet<ObjCPropertyDecl *> PropImplMap;
8020e12e6e0418564d4b2e83138fe2044be29a6f6d5Chris Lattner  for (ObjCImplDecl::propimpl_iterator
80392570c4a1a11cbdaf5ffb13547428dbee1103875Dale Johannesen       I = IMPDecl->propimpl_begin(),
8047c3234c6be0dc0bdf4b5d6f848cd728a77f349d7Dan Gohman       EI = IMPDecl->propimpl_end(); I != EI; ++I)
805b51d40cf40eac676dda3ae9dfeb55822fa403394Devang Patel    PropImplMap.insert((*I)->getPropertyDecl());
80692570c4a1a11cbdaf5ffb13547428dbee1103875Dale Johannesen
80792570c4a1a11cbdaf5ffb13547428dbee1103875Dale Johannesen  for (llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>::iterator
808f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman       P = PropMap.begin(), E = PropMap.end(); P != E; ++P) {
8096f17966a804f53518aa06fd0b5f035d5b1a51589Dan Gohman    ObjCPropertyDecl *Prop = P->second;
8106f17966a804f53518aa06fd0b5f035d5b1a51589Dan Gohman    // Is there a matching propery synthesize/dynamic?
8116e7a1617ac4a34792d9097b8d3644b72f57a45f7Devang Patel    if (Prop->isInvalidDecl() ||
8126e7a1617ac4a34792d9097b8d3644b72f57a45f7Devang Patel        Prop->getPropertyImplementation() == ObjCPropertyDecl::Optional ||
8137c3234c6be0dc0bdf4b5d6f848cd728a77f349d7Dan Gohman        PropImplMap.count(Prop))
8147c3234c6be0dc0bdf4b5d6f848cd728a77f349d7Dan Gohman      continue;
8156e7a1617ac4a34792d9097b8d3644b72f57a45f7Devang Patel    if (LangOpts.ObjCNonFragileABI2) {
8167c3234c6be0dc0bdf4b5d6f848cd728a77f349d7Dan Gohman      ActOnPropertyImplDecl(IMPDecl->getLocation(),
8177c3234c6be0dc0bdf4b5d6f848cd728a77f349d7Dan Gohman                            SourceLocation(),
81878ec311bd5fcdf44ed64841a0f5df1124b3a9b17Chris Lattner                            true, DeclPtrTy::make(IMPDecl),
819f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman                            Prop->getIdentifier(),
820f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman                            Prop->getIdentifier());
821f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman      continue;
822f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman    }
8231146728bfaeb471f675b805ceb27a08d28bbf468Dan Gohman    if (!InsMap.count(Prop->getGetterName())) {
8241146728bfaeb471f675b805ceb27a08d28bbf468Dan Gohman      Diag(Prop->getLocation(),
825c53361294957b63a9c1e405256c6f0a81db1685cDan Gohman           isa<ObjCCategoryDecl>(CDecl) ?
826c53361294957b63a9c1e405256c6f0a81db1685cDan Gohman            diag::warn_setter_getter_impl_required_in_category :
82778ec311bd5fcdf44ed64841a0f5df1124b3a9b17Chris Lattner            diag::warn_setter_getter_impl_required)
82878ec311bd5fcdf44ed64841a0f5df1124b3a9b17Chris Lattner      << Prop->getDeclName() << Prop->getGetterName();
8297c3234c6be0dc0bdf4b5d6f848cd728a77f349d7Dan Gohman      Diag(IMPDecl->getLocation(),
830f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman           diag::note_property_impl_required);
831f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman    }
832f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman
833f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman    if (!Prop->isReadOnly() && !InsMap.count(Prop->getSetterName())) {
834f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman      Diag(Prop->getLocation(),
835056292fd738924f3f7703725d8f630983794b5a5Bill Wendling           isa<ObjCCategoryDecl>(CDecl) ?
836056292fd738924f3f7703725d8f630983794b5a5Bill Wendling           diag::warn_setter_getter_impl_required_in_category :
837f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman           diag::warn_setter_getter_impl_required)
838f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman      << Prop->getDeclName() << Prop->getSetterName();
839f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman      Diag(IMPDecl->getLocation(),
840f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman           diag::note_property_impl_required);
841f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman    }
842e7852d014432a06c783de3c350eb96e686f10f92Dan Gohman  }
843f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman}
844f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman
845f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohmanvoid
846f350b277f32d7d47f86c0e54f4aec4d470500618Dan GohmanSema::AtomicPropertySetterGetterRules (ObjCImplDecl* IMPDecl,
8476ce610f04bb232ce8b57e50e885f30f65d19e1a6Bill Wendling                                       ObjCContainerDecl* IDecl) {
8486ce610f04bb232ce8b57e50e885f30f65d19e1a6Bill Wendling  // Rules apply in non-GC mode only
8496ce610f04bb232ce8b57e50e885f30f65d19e1a6Bill Wendling  if (getLangOptions().getGCMode() != LangOptions::NonGC)
8506ce610f04bb232ce8b57e50e885f30f65d19e1a6Bill Wendling    return;
8516ce610f04bb232ce8b57e50e885f30f65d19e1a6Bill Wendling  for (ObjCContainerDecl::prop_iterator I = IDecl->prop_begin(),
8526ce610f04bb232ce8b57e50e885f30f65d19e1a6Bill Wendling       E = IDecl->prop_end();
8536ce610f04bb232ce8b57e50e885f30f65d19e1a6Bill Wendling       I != E; ++I) {
8546ce610f04bb232ce8b57e50e885f30f65d19e1a6Bill Wendling    ObjCPropertyDecl *Property = (*I);
8554c2454623841f05c6c665659b34c214950d12d7eBob Wilson    unsigned Attributes = Property->getPropertyAttributes();
8564c2454623841f05c6c665659b34c214950d12d7eBob Wilson    // We only care about readwrite atomic property.
85741b9d278add97c744930aa2a0048ff1c01e48c4fBill Wendling    if ((Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic) ||
858bd209ab9bc0f6ad667c15df4453955c2ed4c2434Dan Gohman        !(Attributes & ObjCPropertyDecl::OBJC_PR_readwrite))
859bd209ab9bc0f6ad667c15df4453955c2ed4c2434Dan Gohman      continue;
860bd209ab9bc0f6ad667c15df4453955c2ed4c2434Dan Gohman    if (const ObjCPropertyImplDecl *PIDecl
86141b9d278add97c744930aa2a0048ff1c01e48c4fBill Wendling         = IMPDecl->FindPropertyImplDecl(Property->getIdentifier())) {
86241b9d278add97c744930aa2a0048ff1c01e48c4fBill Wendling      if (PIDecl->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
86341b9d278add97c744930aa2a0048ff1c01e48c4fBill Wendling        continue;
864475871a144eb604ddaf37503397ba0941442e5fbDan Gohman      ObjCMethodDecl *GetterMethod =
8650ff39b3feb10477c224138156941234f5fa46f58Evan Cheng        IMPDecl->getInstanceMethod(Property->getGetterName());
866ce9bc12c6f3c3544f7518c0c60203f2f9dff342fDan Gohman      ObjCMethodDecl *SetterMethod =
867ce9bc12c6f3c3544f7518c0c60203f2f9dff342fDan Gohman        IMPDecl->getInstanceMethod(Property->getSetterName());
868ce9bc12c6f3c3544f7518c0c60203f2f9dff342fDan Gohman      if ((GetterMethod && !SetterMethod) || (!GetterMethod && SetterMethod)) {
86983ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands        SourceLocation MethodLoc =
8706394b099e836f56a937cdcc7332c9487b504ca68Dan Gohman          (GetterMethod ? GetterMethod->getLocation()
8716394b099e836f56a937cdcc7332c9487b504ca68Dan Gohman                        : SetterMethod->getLocation());
872475871a144eb604ddaf37503397ba0941442e5fbDan Gohman        Diag(MethodLoc, diag::warn_atomic_property_rule)
8734fbd796a1251a27e6590765a0a34876f436a0af9Dan Gohman          << Property->getIdentifier();
8744fbd796a1251a27e6590765a0a34876f436a0af9Dan Gohman        Diag(Property->getLocation(), diag::note_property_declare);
8754fbd796a1251a27e6590765a0a34876f436a0af9Dan Gohman      }
8764fbd796a1251a27e6590765a0a34876f436a0af9Dan Gohman    }
87783ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands  }
878890813243f9b4f5aa9c6d5ab79ffe948458197abDan Gohman}
8790ff39b3feb10477c224138156941234f5fa46f58Evan Cheng
88083ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands/// ProcessPropertyDecl - Make sure that any user-defined setter/getter methods
8816394b099e836f56a937cdcc7332c9487b504ca68Dan Gohman/// have the property type and issue diagnostics if they don't.
88261b09412fe2c98367730c7064d56eff537b03434Chris Lattner/// Also synthesize a getter/setter method if none exist (and update the
88361b09412fe2c98367730c7064d56eff537b03434Chris Lattner/// appropriate lookup tables. FIXME: Should reconsider if adding synthesized
884583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey/// methods is the "right" thing to do.
8856d9cdd56173fb915a9e3a8f0f6b5a8ed9bed1098Dan Gohmanvoid Sema::ProcessPropertyDecl(ObjCPropertyDecl *property,
8864fbd796a1251a27e6590765a0a34876f436a0af9Dan Gohman                               ObjCContainerDecl *CD) {
88761b09412fe2c98367730c7064d56eff537b03434Chris Lattner  ObjCMethodDecl *GetterMethod, *SetterMethod;
888890813243f9b4f5aa9c6d5ab79ffe948458197abDan Gohman
889890813243f9b4f5aa9c6d5ab79ffe948458197abDan Gohman  GetterMethod = CD->getInstanceMethod(property->getGetterName());
89083ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands  SetterMethod = CD->getInstanceMethod(property->getSetterName());
891475871a144eb604ddaf37503397ba0941442e5fbDan Gohman  DiagnosePropertyAccessorMismatch(property, GetterMethod,
892890813243f9b4f5aa9c6d5ab79ffe948458197abDan Gohman                                   property->getLocation());
893fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman
8944fbd796a1251a27e6590765a0a34876f436a0af9Dan Gohman  if (SetterMethod) {
895890813243f9b4f5aa9c6d5ab79ffe948458197abDan Gohman    ObjCPropertyDecl::PropertyAttributeKind CAttr =
896890813243f9b4f5aa9c6d5ab79ffe948458197abDan Gohman      property->getPropertyAttributes();
897890813243f9b4f5aa9c6d5ab79ffe948458197abDan Gohman    if ((!(CAttr & ObjCPropertyDecl::OBJC_PR_readonly)) &&
898890813243f9b4f5aa9c6d5ab79ffe948458197abDan Gohman        Context.getCanonicalType(SetterMethod->getResultType()) !=
899475871a144eb604ddaf37503397ba0941442e5fbDan Gohman          Context.VoidTy)
90083ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands      Diag(SetterMethod->getLocation(), diag::err_setter_type_void);
901475871a144eb604ddaf37503397ba0941442e5fbDan Gohman    if (SetterMethod->param_size() != 1 ||
90283ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands        ((*SetterMethod->param_begin())->getType() != property->getType())) {
903a87008d90b7d894cfca53d407642acfd7be2af3cEvan Cheng      Diag(property->getLocation(),
904a87008d90b7d894cfca53d407642acfd7be2af3cEvan Cheng           diag::warn_accessor_property_type_mismatch)
905890813243f9b4f5aa9c6d5ab79ffe948458197abDan Gohman        << property->getDeclName()
906890813243f9b4f5aa9c6d5ab79ffe948458197abDan Gohman        << SetterMethod->getSelector();
90778ec311bd5fcdf44ed64841a0f5df1124b3a9b17Chris Lattner      Diag(SetterMethod->getLocation(), diag::note_declared_at);
90878ec311bd5fcdf44ed64841a0f5df1124b3a9b17Chris Lattner    }
909475871a144eb604ddaf37503397ba0941442e5fbDan Gohman  }
9100bd4893a0726889b942405262e53d06cf3fe3be8Chris Lattner
9110bd4893a0726889b942405262e53d06cf3fe3be8Chris Lattner  // Synthesize getter/setter methods if none exist.
9120bd4893a0726889b942405262e53d06cf3fe3be8Chris Lattner  // Find the default getter and if one not found, add one.
9130bd4893a0726889b942405262e53d06cf3fe3be8Chris Lattner  // FIXME: The synthesized property we set here is misleading. We almost always
914475871a144eb604ddaf37503397ba0941442e5fbDan Gohman  // synthesize these methods unless the user explicitly provided prototypes
9154fbd796a1251a27e6590765a0a34876f436a0af9Dan Gohman  // (which is odd, but allowed). Sema should be typechecking that the
9164fbd796a1251a27e6590765a0a34876f436a0af9Dan Gohman  // declarations jive in that situation (which it is not currently).
9174fbd796a1251a27e6590765a0a34876f436a0af9Dan Gohman  if (!GetterMethod) {
9184fbd796a1251a27e6590765a0a34876f436a0af9Dan Gohman    // No instance method of same name as property getter name was found.
91983ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands    // Declare a getter method and add it to the list of methods
920fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel    // for this class.
92183ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands    GetterMethod = ObjCMethodDecl::Create(Context, property->getLocation(),
92283ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands                             property->getLocation(), property->getGetterName(),
923c3aae25116e66c177579b0b79182b09340b19753Chris Lattner                             property->getType(), 0, CD, true, false, true,
924d8658616cf8b6ad984974bb764dc9ee4b77499aaChris Lattner                             (property->getPropertyImplementation() ==
925d8658616cf8b6ad984974bb764dc9ee4b77499aaChris Lattner                              ObjCPropertyDecl::Optional) ?
926d8658616cf8b6ad984974bb764dc9ee4b77499aaChris Lattner                             ObjCMethodDecl::Optional :
927c9f8f416800784ca6453222b307bc44ad24739b0Chris Lattner                             ObjCMethodDecl::Required);
928583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey    CD->addDecl(GetterMethod);
9296d9cdd56173fb915a9e3a8f0f6b5a8ed9bed1098Dan Gohman  } else
9304fbd796a1251a27e6590765a0a34876f436a0af9Dan Gohman    // A user declared getter will be synthesize when @synthesize of
931c9f8f416800784ca6453222b307bc44ad24739b0Chris Lattner    // the property with the same name is seen in the @implementation
932c908dcde45c6d7ddff0443cbc174a7cbfec21d1bEvan Cheng    GetterMethod->setSynthesized(true);
933c908dcde45c6d7ddff0443cbc174a7cbfec21d1bEvan Cheng  property->setGetterMethodDecl(GetterMethod);
93483ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands
935475871a144eb604ddaf37503397ba0941442e5fbDan Gohman  // Skip setter if property is read-only.
936c908dcde45c6d7ddff0443cbc174a7cbfec21d1bEvan Cheng  if (!property->isReadOnly()) {
937fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman    // Find the default setter and if one not found, add one.
9384fbd796a1251a27e6590765a0a34876f436a0af9Dan Gohman    if (!SetterMethod) {
939c908dcde45c6d7ddff0443cbc174a7cbfec21d1bEvan Cheng      // No instance method of same name as property setter name was found.
940c908dcde45c6d7ddff0443cbc174a7cbfec21d1bEvan Cheng      // Declare a setter method and add it to the list of methods
941c908dcde45c6d7ddff0443cbc174a7cbfec21d1bEvan Cheng      // for this class.
942c908dcde45c6d7ddff0443cbc174a7cbfec21d1bEvan Cheng      SetterMethod = ObjCMethodDecl::Create(Context, property->getLocation(),
943475871a144eb604ddaf37503397ba0941442e5fbDan Gohman                               property->getLocation(),
94483ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands                               property->getSetterName(),
945475871a144eb604ddaf37503397ba0941442e5fbDan Gohman                               Context.VoidTy, 0, CD, true, false, true,
94683ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands                               (property->getPropertyImplementation() ==
947a87008d90b7d894cfca53d407642acfd7be2af3cEvan Cheng                                ObjCPropertyDecl::Optional) ?
948a87008d90b7d894cfca53d407642acfd7be2af3cEvan Cheng                               ObjCMethodDecl::Optional :
949a87008d90b7d894cfca53d407642acfd7be2af3cEvan Cheng                               ObjCMethodDecl::Required);
9507f32156bb9c017b71971c52fac892fa7b9b06dd2Dan Gohman      // Invent the arguments for the setter. We don't bother making a
9517f32156bb9c017b71971c52fac892fa7b9b06dd2Dan Gohman      // nice name for the argument.
952c3aae25116e66c177579b0b79182b09340b19753Chris Lattner      ParmVarDecl *Argument = ParmVarDecl::Create(Context, SetterMethod,
953c3aae25116e66c177579b0b79182b09340b19753Chris Lattner                                                  property->getLocation(),
954475871a144eb604ddaf37503397ba0941442e5fbDan Gohman                                                  property->getIdentifier(),
95583ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands                                                  property->getType(),
95683ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands                                                  /*TInfo=*/0,
957f04afdbb48568ef09f11fd10ac03426101f2dbf8Dale Johannesen                                                  VarDecl::None,
958f04afdbb48568ef09f11fd10ac03426101f2dbf8Dale Johannesen                                                  0);
959f04afdbb48568ef09f11fd10ac03426101f2dbf8Dale Johannesen      SetterMethod->setMethodParams(Context, &Argument, 1);
960f04afdbb48568ef09f11fd10ac03426101f2dbf8Dale Johannesen      CD->addDecl(SetterMethod);
961f04afdbb48568ef09f11fd10ac03426101f2dbf8Dale Johannesen    } else
962f04afdbb48568ef09f11fd10ac03426101f2dbf8Dale Johannesen      // A user declared setter will be synthesize when @synthesize of
963475871a144eb604ddaf37503397ba0941442e5fbDan Gohman      // the property with the same name is seen in the @implementation
9646520e20e4fb31f2e65e25c38b372b19d33a83df4Dan Gohman      SetterMethod->setSynthesized(true);
9652a4ed82ce2ba4a02f2a02eb4ed8ce5186f3f93daChris Lattner    property->setSetterMethodDecl(SetterMethod);
9662a4ed82ce2ba4a02f2a02eb4ed8ce5186f3f93daChris Lattner  }
9672a4ed82ce2ba4a02f2a02eb4ed8ce5186f3f93daChris Lattner  // Add any synthesized methods to the global pool. This allows us to
9682a4ed82ce2ba4a02f2a02eb4ed8ce5186f3f93daChris Lattner  // handle the following, which is supported by GCC (and part of the design).
9692a4ed82ce2ba4a02f2a02eb4ed8ce5186f3f93daChris Lattner  //
9706520e20e4fb31f2e65e25c38b372b19d33a83df4Dan Gohman  // @interface Foo
9714401361a2fb92c82317dbfbb1616f54ced2b51f3Dan Gohman  // @property double bar;
9726520e20e4fb31f2e65e25c38b372b19d33a83df4Dan Gohman  // @end
9736520e20e4fb31f2e65e25c38b372b19d33a83df4Dan Gohman  //
9746520e20e4fb31f2e65e25c38b372b19d33a83df4Dan Gohman  // void thisIsUnfortunate() {
9754d86e2a6b8edc814165a3e63f55bfaea0b8f224dAnton Korobeynikov  //   id foo;
9764d86e2a6b8edc814165a3e63f55bfaea0b8f224dAnton Korobeynikov  //   double bar = [foo bar];
977c73ede0a9beaee2e11d004f816a8207d9bd79072Anton Korobeynikov  // }
9784d86e2a6b8edc814165a3e63f55bfaea0b8f224dAnton Korobeynikov  //
97919e861a4ffb896f16a691d5ac869e894df3cd464Anton Korobeynikov  if (GetterMethod)
9804d86e2a6b8edc814165a3e63f55bfaea0b8f224dAnton Korobeynikov    AddInstanceMethodToGlobalPool(GetterMethod);
9814d86e2a6b8edc814165a3e63f55bfaea0b8f224dAnton Korobeynikov  if (SetterMethod)
9822a4ed82ce2ba4a02f2a02eb4ed8ce5186f3f93daChris Lattner    AddInstanceMethodToGlobalPool(SetterMethod);
983b3a0417cad8b625acc3033bd5e24afb9ffd0b084Lauro Ramos Venancio}
984b3a0417cad8b625acc3033bd5e24afb9ffd0b084Lauro Ramos Venancio
985b3a0417cad8b625acc3033bd5e24afb9ffd0b084Lauro Ramos Venanciovoid Sema::CheckObjCPropertyAttributes(QualType PropertyTy,
986b3a0417cad8b625acc3033bd5e24afb9ffd0b084Lauro Ramos Venancio                                       SourceLocation Loc,
9874d86e2a6b8edc814165a3e63f55bfaea0b8f224dAnton Korobeynikov                                       unsigned &Attributes) {
988583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey  // FIXME: Improve the reported location.
9896d9cdd56173fb915a9e3a8f0f6b5a8ed9bed1098Dan Gohman
99061b09412fe2c98367730c7064d56eff537b03434Chris Lattner  // readonly and readwrite/assign/retain/copy conflict.
99161b09412fe2c98367730c7064d56eff537b03434Chris Lattner  if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
9922a4ed82ce2ba4a02f2a02eb4ed8ce5186f3f93daChris Lattner      (Attributes & (ObjCDeclSpec::DQ_PR_readwrite |
99361b09412fe2c98367730c7064d56eff537b03434Chris Lattner                     ObjCDeclSpec::DQ_PR_assign |
99461b09412fe2c98367730c7064d56eff537b03434Chris Lattner                     ObjCDeclSpec::DQ_PR_copy |
99574692c0d65d92865674ff8e0491a21b98950284aDan Gohman                     ObjCDeclSpec::DQ_PR_retain))) {
996fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman    const char * which = (Attributes & ObjCDeclSpec::DQ_PR_readwrite) ?
9972a4ed82ce2ba4a02f2a02eb4ed8ce5186f3f93daChris Lattner                          "readwrite" :
99861b09412fe2c98367730c7064d56eff537b03434Chris Lattner                         (Attributes & ObjCDeclSpec::DQ_PR_assign) ?
999c3aae25116e66c177579b0b79182b09340b19753Chris Lattner                          "assign" :
1000475871a144eb604ddaf37503397ba0941442e5fbDan Gohman                         (Attributes & ObjCDeclSpec::DQ_PR_copy) ?
1001c3aae25116e66c177579b0b79182b09340b19753Chris Lattner                          "copy" : "retain";
1002c3aae25116e66c177579b0b79182b09340b19753Chris Lattner
1003475871a144eb604ddaf37503397ba0941442e5fbDan Gohman    Diag(Loc, (Attributes & (ObjCDeclSpec::DQ_PR_readwrite)) ?
1004c9f8f416800784ca6453222b307bc44ad24739b0Chris Lattner                 diag::err_objc_property_attr_mutually_exclusive :
1005583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey                 diag::warn_objc_property_attr_mutually_exclusive)
10066d9cdd56173fb915a9e3a8f0f6b5a8ed9bed1098Dan Gohman      << "readonly" << which;
1007c9f8f416800784ca6453222b307bc44ad24739b0Chris Lattner  }
1008c9f8f416800784ca6453222b307bc44ad24739b0Chris Lattner
1009c9f8f416800784ca6453222b307bc44ad24739b0Chris Lattner  // Check for copy or retain on non-object types.
1010475871a144eb604ddaf37503397ba0941442e5fbDan Gohman  if ((Attributes & (ObjCDeclSpec::DQ_PR_copy | ObjCDeclSpec::DQ_PR_retain)) &&
1011fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman      !PropertyTy->isObjCObjectPointerType() &&
10120e5f1306b059b62d7725f324e087efbc8e7a782dDan Gohman      !PropertyTy->isBlockPointerType() &&
1013c9f8f416800784ca6453222b307bc44ad24739b0Chris Lattner      !Context.isObjCNSObjectType(PropertyTy)) {
101437efe6764568a3829fee26aba532283131d1a104Nate Begeman    Diag(Loc, diag::err_objc_property_requires_object)
1015475871a144eb604ddaf37503397ba0941442e5fbDan Gohman      << (Attributes & ObjCDeclSpec::DQ_PR_copy ? "copy" : "retain");
101637efe6764568a3829fee26aba532283131d1a104Nate Begeman    Attributes &= ~(ObjCDeclSpec::DQ_PR_copy | ObjCDeclSpec::DQ_PR_retain);
101737efe6764568a3829fee26aba532283131d1a104Nate Begeman  }
1018475871a144eb604ddaf37503397ba0941442e5fbDan Gohman
1019c9f8f416800784ca6453222b307bc44ad24739b0Chris Lattner  // Check for more than one of { assign, copy, retain }.
1020583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey  if (Attributes & ObjCDeclSpec::DQ_PR_assign) {
10216d9cdd56173fb915a9e3a8f0f6b5a8ed9bed1098Dan Gohman    if (Attributes & ObjCDeclSpec::DQ_PR_copy) {
1022c9f8f416800784ca6453222b307bc44ad24739b0Chris Lattner      Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
1023c9f8f416800784ca6453222b307bc44ad24739b0Chris Lattner        << "assign" << "copy";
1024c9f8f416800784ca6453222b307bc44ad24739b0Chris Lattner      Attributes &= ~ObjCDeclSpec::DQ_PR_copy;
1025475871a144eb604ddaf37503397ba0941442e5fbDan Gohman    }
1026fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman    if (Attributes & ObjCDeclSpec::DQ_PR_retain) {
10270e5f1306b059b62d7725f324e087efbc8e7a782dDan Gohman      Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
1028c9f8f416800784ca6453222b307bc44ad24739b0Chris Lattner        << "assign" << "retain";
102937efe6764568a3829fee26aba532283131d1a104Nate Begeman      Attributes &= ~ObjCDeclSpec::DQ_PR_retain;
1030475871a144eb604ddaf37503397ba0941442e5fbDan Gohman    }
103137efe6764568a3829fee26aba532283131d1a104Nate Begeman  } else if (Attributes & ObjCDeclSpec::DQ_PR_copy) {
103237efe6764568a3829fee26aba532283131d1a104Nate Begeman    if (Attributes & ObjCDeclSpec::DQ_PR_retain) {
1033475871a144eb604ddaf37503397ba0941442e5fbDan Gohman      Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
1034475871a144eb604ddaf37503397ba0941442e5fbDan Gohman        << "copy" << "retain";
1035475871a144eb604ddaf37503397ba0941442e5fbDan Gohman      Attributes &= ~ObjCDeclSpec::DQ_PR_retain;
103650284d81f863a6576582e1a171a22eb0f012ddf3Dan Gohman    }
10371606e8e4cd937e6de6681f686c266cf61722d972Evan Cheng  }
1038c9f8f416800784ca6453222b307bc44ad24739b0Chris Lattner
1039583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey  // Warn if user supplied no assignment attribute, property is
10406d9cdd56173fb915a9e3a8f0f6b5a8ed9bed1098Dan Gohman  // readwrite, and this is an object type.
1041c9f8f416800784ca6453222b307bc44ad24739b0Chris Lattner  if (!(Attributes & (ObjCDeclSpec::DQ_PR_assign | ObjCDeclSpec::DQ_PR_copy |
1042c9f8f416800784ca6453222b307bc44ad24739b0Chris Lattner                      ObjCDeclSpec::DQ_PR_retain)) &&
1043130fc13506b4da64981632c83734721a8b5b2d2dChris Lattner      !(Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
1044c9f8f416800784ca6453222b307bc44ad24739b0Chris Lattner      PropertyTy->isObjCObjectPointerType()) {
1045c9f8f416800784ca6453222b307bc44ad24739b0Chris Lattner    // Skip this warning in gc-only mode.
1046475871a144eb604ddaf37503397ba0941442e5fbDan Gohman    if (getLangOptions().getGCMode() != LangOptions::GCOnly)
1047fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman      Diag(Loc, diag::warn_objc_property_no_assignment_attribute);
10480e5f1306b059b62d7725f324e087efbc8e7a782dDan Gohman
1049c9f8f416800784ca6453222b307bc44ad24739b0Chris Lattner    // If non-gc code warn that this is likely inappropriate.
10504025a9c2cc4ac3b9efa465a2f64be50fdaba9da9Chris Lattner    if (getLangOptions().getGCMode() == LangOptions::NonGC)
1051475871a144eb604ddaf37503397ba0941442e5fbDan Gohman      Diag(Loc, diag::warn_objc_property_default_assign_on_object);
10524025a9c2cc4ac3b9efa465a2f64be50fdaba9da9Chris Lattner
10534025a9c2cc4ac3b9efa465a2f64be50fdaba9da9Chris Lattner    // FIXME: Implement warning dependent on NSCopying being
1054c3aae25116e66c177579b0b79182b09340b19753Chris Lattner    // implemented. See also:
1055475871a144eb604ddaf37503397ba0941442e5fbDan Gohman    // <rdar://5168496&4855821&5607453&5096644&4947311&5698469&4947014&5168496>
1056475871a144eb604ddaf37503397ba0941442e5fbDan Gohman    // (please trim this list while you are at it).
1057475871a144eb604ddaf37503397ba0941442e5fbDan Gohman  }
105850284d81f863a6576582e1a171a22eb0f012ddf3Dan Gohman
10591606e8e4cd937e6de6681f686c266cf61722d972Evan Cheng  if (!(Attributes & ObjCDeclSpec::DQ_PR_copy)
1060d6594ae54cfde4db4d30272192645c0a45fb9902Evan Cheng      && getLangOptions().getGCMode() == LangOptions::GCOnly
1061583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey      && PropertyTy->isBlockPointerType())
10626d9cdd56173fb915a9e3a8f0f6b5a8ed9bed1098Dan Gohman    Diag(Loc, diag::warn_objc_property_copy_missing_on_block);
1063d6594ae54cfde4db4d30272192645c0a45fb9902Evan Cheng}
1064d6594ae54cfde4db4d30272192645c0a45fb9902Evan Cheng
1065583bd47f777fe3eb8305872fa0eadab31e833dffJim LaskeyObjCIvarDecl*
1066d6594ae54cfde4db4d30272192645c0a45fb9902Evan ChengSema::SynthesizeNewPropertyIvar(ObjCInterfaceDecl *IDecl,
1067d6594ae54cfde4db4d30272192645c0a45fb9902Evan Cheng                                IdentifierInfo *NameII) {
1068475871a144eb604ddaf37503397ba0941442e5fbDan Gohman  ObjCIvarDecl *Ivar = 0;
1069fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman  ObjCPropertyDecl *Prop = LookupPropertyDecl(IDecl, NameII);
10700e5f1306b059b62d7725f324e087efbc8e7a782dDan Gohman  if (Prop && !Prop->isInvalidDecl()) {
1071d6594ae54cfde4db4d30272192645c0a45fb9902Evan Cheng    DeclContext *EnclosingContext = cast_or_null<DeclContext>(IDecl);
1072d6594ae54cfde4db4d30272192645c0a45fb9902Evan Cheng    QualType PropType = Context.getCanonicalType(Prop->getType());
1073475871a144eb604ddaf37503397ba0941442e5fbDan Gohman    assert(EnclosingContext &&
1074d6594ae54cfde4db4d30272192645c0a45fb9902Evan Cheng           "null DeclContext for synthesized ivar - SynthesizeNewPropertyIvar");
1075d6594ae54cfde4db4d30272192645c0a45fb9902Evan Cheng    Ivar = ObjCIvarDecl::Create(Context, EnclosingContext,
1076475871a144eb604ddaf37503397ba0941442e5fbDan Gohman                                              Prop->getLocation(),
1077583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey                                              NameII, PropType, /*Dinfo=*/0,
10786d9cdd56173fb915a9e3a8f0f6b5a8ed9bed1098Dan Gohman                                              ObjCIvarDecl::Public,
107961b09412fe2c98367730c7064d56eff537b03434Chris Lattner                                              (Expr *)0);
108061b09412fe2c98367730c7064d56eff537b03434Chris Lattner    Ivar->setLexicalDeclContext(IDecl);
108161b09412fe2c98367730c7064d56eff537b03434Chris Lattner    IDecl->addDecl(Ivar);
1082475871a144eb604ddaf37503397ba0941442e5fbDan Gohman    Prop->setPropertyIvarDecl(Ivar);
1083fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman  }
10840e5f1306b059b62d7725f324e087efbc8e7a782dDan Gohman  return Ivar;
108561b09412fe2c98367730c7064d56eff537b03434Chris Lattner}
1086c3aae25116e66c177579b0b79182b09340b19753Chris Lattner
1087475871a144eb604ddaf37503397ba0941442e5fbDan Gohman