SemaObjCProperty.cpp 119 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820
  1. //===--- SemaObjCProperty.cpp - Semantic Analysis for ObjC @property ------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This file implements semantic analysis for Objective C @property and
  10. // @synthesize declarations.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "clang/Sema/SemaInternal.h"
  14. #include "clang/AST/ASTMutationListener.h"
  15. #include "clang/AST/DeclObjC.h"
  16. #include "clang/AST/ExprCXX.h"
  17. #include "clang/AST/ExprObjC.h"
  18. #include "clang/Basic/SourceManager.h"
  19. #include "clang/Lex/Lexer.h"
  20. #include "clang/Lex/Preprocessor.h"
  21. #include "clang/Sema/Initialization.h"
  22. #include "llvm/ADT/DenseSet.h"
  23. #include "llvm/ADT/SmallString.h"
  24. using namespace clang;
  25. //===----------------------------------------------------------------------===//
  26. // Grammar actions.
  27. //===----------------------------------------------------------------------===//
  28. /// getImpliedARCOwnership - Given a set of property attributes and a
  29. /// type, infer an expected lifetime. The type's ownership qualification
  30. /// is not considered.
  31. ///
  32. /// Returns OCL_None if the attributes as stated do not imply an ownership.
  33. /// Never returns OCL_Autoreleasing.
  34. static Qualifiers::ObjCLifetime
  35. getImpliedARCOwnership(ObjCPropertyAttribute::Kind attrs, QualType type) {
  36. // retain, strong, copy, weak, and unsafe_unretained are only legal
  37. // on properties of retainable pointer type.
  38. if (attrs &
  39. (ObjCPropertyAttribute::kind_retain | ObjCPropertyAttribute::kind_strong |
  40. ObjCPropertyAttribute::kind_copy)) {
  41. return Qualifiers::OCL_Strong;
  42. } else if (attrs & ObjCPropertyAttribute::kind_weak) {
  43. return Qualifiers::OCL_Weak;
  44. } else if (attrs & ObjCPropertyAttribute::kind_unsafe_unretained) {
  45. return Qualifiers::OCL_ExplicitNone;
  46. }
  47. // assign can appear on other types, so we have to check the
  48. // property type.
  49. if (attrs & ObjCPropertyAttribute::kind_assign &&
  50. type->isObjCRetainableType()) {
  51. return Qualifiers::OCL_ExplicitNone;
  52. }
  53. return Qualifiers::OCL_None;
  54. }
  55. /// Check the internal consistency of a property declaration with
  56. /// an explicit ownership qualifier.
  57. static void checkPropertyDeclWithOwnership(Sema &S,
  58. ObjCPropertyDecl *property) {
  59. if (property->isInvalidDecl()) return;
  60. ObjCPropertyAttribute::Kind propertyKind = property->getPropertyAttributes();
  61. Qualifiers::ObjCLifetime propertyLifetime
  62. = property->getType().getObjCLifetime();
  63. assert(propertyLifetime != Qualifiers::OCL_None);
  64. Qualifiers::ObjCLifetime expectedLifetime
  65. = getImpliedARCOwnership(propertyKind, property->getType());
  66. if (!expectedLifetime) {
  67. // We have a lifetime qualifier but no dominating property
  68. // attribute. That's okay, but restore reasonable invariants by
  69. // setting the property attribute according to the lifetime
  70. // qualifier.
  71. ObjCPropertyAttribute::Kind attr;
  72. if (propertyLifetime == Qualifiers::OCL_Strong) {
  73. attr = ObjCPropertyAttribute::kind_strong;
  74. } else if (propertyLifetime == Qualifiers::OCL_Weak) {
  75. attr = ObjCPropertyAttribute::kind_weak;
  76. } else {
  77. assert(propertyLifetime == Qualifiers::OCL_ExplicitNone);
  78. attr = ObjCPropertyAttribute::kind_unsafe_unretained;
  79. }
  80. property->setPropertyAttributes(attr);
  81. return;
  82. }
  83. if (propertyLifetime == expectedLifetime) return;
  84. property->setInvalidDecl();
  85. S.Diag(property->getLocation(),
  86. diag::err_arc_inconsistent_property_ownership)
  87. << property->getDeclName()
  88. << expectedLifetime
  89. << propertyLifetime;
  90. }
  91. /// Check this Objective-C property against a property declared in the
  92. /// given protocol.
  93. static void
  94. CheckPropertyAgainstProtocol(Sema &S, ObjCPropertyDecl *Prop,
  95. ObjCProtocolDecl *Proto,
  96. llvm::SmallPtrSetImpl<ObjCProtocolDecl *> &Known) {
  97. // Have we seen this protocol before?
  98. if (!Known.insert(Proto).second)
  99. return;
  100. // Look for a property with the same name.
  101. if (ObjCPropertyDecl *ProtoProp = Proto->getProperty(
  102. Prop->getIdentifier(), Prop->isInstanceProperty())) {
  103. S.DiagnosePropertyMismatch(Prop, ProtoProp, Proto->getIdentifier(), true);
  104. return;
  105. }
  106. // Check this property against any protocols we inherit.
  107. for (auto *P : Proto->protocols())
  108. CheckPropertyAgainstProtocol(S, Prop, P, Known);
  109. }
  110. static unsigned deducePropertyOwnershipFromType(Sema &S, QualType T) {
  111. // In GC mode, just look for the __weak qualifier.
  112. if (S.getLangOpts().getGC() != LangOptions::NonGC) {
  113. if (T.isObjCGCWeak())
  114. return ObjCPropertyAttribute::kind_weak;
  115. // In ARC/MRC, look for an explicit ownership qualifier.
  116. // For some reason, this only applies to __weak.
  117. } else if (auto ownership = T.getObjCLifetime()) {
  118. switch (ownership) {
  119. case Qualifiers::OCL_Weak:
  120. return ObjCPropertyAttribute::kind_weak;
  121. case Qualifiers::OCL_Strong:
  122. return ObjCPropertyAttribute::kind_strong;
  123. case Qualifiers::OCL_ExplicitNone:
  124. return ObjCPropertyAttribute::kind_unsafe_unretained;
  125. case Qualifiers::OCL_Autoreleasing:
  126. case Qualifiers::OCL_None:
  127. return 0;
  128. }
  129. llvm_unreachable("bad qualifier");
  130. }
  131. return 0;
  132. }
  133. static const unsigned OwnershipMask =
  134. (ObjCPropertyAttribute::kind_assign | ObjCPropertyAttribute::kind_retain |
  135. ObjCPropertyAttribute::kind_copy | ObjCPropertyAttribute::kind_weak |
  136. ObjCPropertyAttribute::kind_strong |
  137. ObjCPropertyAttribute::kind_unsafe_unretained);
  138. static unsigned getOwnershipRule(unsigned attr) {
  139. unsigned result = attr & OwnershipMask;
  140. // From an ownership perspective, assign and unsafe_unretained are
  141. // identical; make sure one also implies the other.
  142. if (result & (ObjCPropertyAttribute::kind_assign |
  143. ObjCPropertyAttribute::kind_unsafe_unretained)) {
  144. result |= ObjCPropertyAttribute::kind_assign |
  145. ObjCPropertyAttribute::kind_unsafe_unretained;
  146. }
  147. return result;
  148. }
  149. Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
  150. SourceLocation LParenLoc,
  151. FieldDeclarator &FD,
  152. ObjCDeclSpec &ODS,
  153. Selector GetterSel,
  154. Selector SetterSel,
  155. tok::ObjCKeywordKind MethodImplKind,
  156. DeclContext *lexicalDC) {
  157. unsigned Attributes = ODS.getPropertyAttributes();
  158. FD.D.setObjCWeakProperty((Attributes & ObjCPropertyAttribute::kind_weak) !=
  159. 0);
  160. TypeSourceInfo *TSI = GetTypeForDeclarator(FD.D, S);
  161. QualType T = TSI->getType();
  162. if (!getOwnershipRule(Attributes)) {
  163. Attributes |= deducePropertyOwnershipFromType(*this, T);
  164. }
  165. bool isReadWrite = ((Attributes & ObjCPropertyAttribute::kind_readwrite) ||
  166. // default is readwrite!
  167. !(Attributes & ObjCPropertyAttribute::kind_readonly));
  168. // Proceed with constructing the ObjCPropertyDecls.
  169. ObjCContainerDecl *ClassDecl = cast<ObjCContainerDecl>(CurContext);
  170. ObjCPropertyDecl *Res = nullptr;
  171. if (ObjCCategoryDecl *CDecl = dyn_cast<ObjCCategoryDecl>(ClassDecl)) {
  172. if (CDecl->IsClassExtension()) {
  173. Res = HandlePropertyInClassExtension(S, AtLoc, LParenLoc,
  174. FD,
  175. GetterSel, ODS.getGetterNameLoc(),
  176. SetterSel, ODS.getSetterNameLoc(),
  177. isReadWrite, Attributes,
  178. ODS.getPropertyAttributes(),
  179. T, TSI, MethodImplKind);
  180. if (!Res)
  181. return nullptr;
  182. }
  183. }
  184. if (!Res) {
  185. Res = CreatePropertyDecl(S, ClassDecl, AtLoc, LParenLoc, FD,
  186. GetterSel, ODS.getGetterNameLoc(), SetterSel,
  187. ODS.getSetterNameLoc(), isReadWrite, Attributes,
  188. ODS.getPropertyAttributes(), T, TSI,
  189. MethodImplKind);
  190. if (lexicalDC)
  191. Res->setLexicalDeclContext(lexicalDC);
  192. }
  193. // Validate the attributes on the @property.
  194. CheckObjCPropertyAttributes(Res, AtLoc, Attributes,
  195. (isa<ObjCInterfaceDecl>(ClassDecl) ||
  196. isa<ObjCProtocolDecl>(ClassDecl)));
  197. // Check consistency if the type has explicit ownership qualification.
  198. if (Res->getType().getObjCLifetime())
  199. checkPropertyDeclWithOwnership(*this, Res);
  200. llvm::SmallPtrSet<ObjCProtocolDecl *, 16> KnownProtos;
  201. if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(ClassDecl)) {
  202. // For a class, compare the property against a property in our superclass.
  203. bool FoundInSuper = false;
  204. ObjCInterfaceDecl *CurrentInterfaceDecl = IFace;
  205. while (ObjCInterfaceDecl *Super = CurrentInterfaceDecl->getSuperClass()) {
  206. if (ObjCPropertyDecl *SuperProp = Super->getProperty(
  207. Res->getIdentifier(), Res->isInstanceProperty())) {
  208. DiagnosePropertyMismatch(Res, SuperProp, Super->getIdentifier(), false);
  209. FoundInSuper = true;
  210. break;
  211. }
  212. CurrentInterfaceDecl = Super;
  213. }
  214. if (FoundInSuper) {
  215. // Also compare the property against a property in our protocols.
  216. for (auto *P : CurrentInterfaceDecl->protocols()) {
  217. CheckPropertyAgainstProtocol(*this, Res, P, KnownProtos);
  218. }
  219. } else {
  220. // Slower path: look in all protocols we referenced.
  221. for (auto *P : IFace->all_referenced_protocols()) {
  222. CheckPropertyAgainstProtocol(*this, Res, P, KnownProtos);
  223. }
  224. }
  225. } else if (ObjCCategoryDecl *Cat = dyn_cast<ObjCCategoryDecl>(ClassDecl)) {
  226. // We don't check if class extension. Because properties in class extension
  227. // are meant to override some of the attributes and checking has already done
  228. // when property in class extension is constructed.
  229. if (!Cat->IsClassExtension())
  230. for (auto *P : Cat->protocols())
  231. CheckPropertyAgainstProtocol(*this, Res, P, KnownProtos);
  232. } else {
  233. ObjCProtocolDecl *Proto = cast<ObjCProtocolDecl>(ClassDecl);
  234. for (auto *P : Proto->protocols())
  235. CheckPropertyAgainstProtocol(*this, Res, P, KnownProtos);
  236. }
  237. ActOnDocumentableDecl(Res);
  238. return Res;
  239. }
  240. static ObjCPropertyAttribute::Kind
  241. makePropertyAttributesAsWritten(unsigned Attributes) {
  242. unsigned attributesAsWritten = 0;
  243. if (Attributes & ObjCPropertyAttribute::kind_readonly)
  244. attributesAsWritten |= ObjCPropertyAttribute::kind_readonly;
  245. if (Attributes & ObjCPropertyAttribute::kind_readwrite)
  246. attributesAsWritten |= ObjCPropertyAttribute::kind_readwrite;
  247. if (Attributes & ObjCPropertyAttribute::kind_getter)
  248. attributesAsWritten |= ObjCPropertyAttribute::kind_getter;
  249. if (Attributes & ObjCPropertyAttribute::kind_setter)
  250. attributesAsWritten |= ObjCPropertyAttribute::kind_setter;
  251. if (Attributes & ObjCPropertyAttribute::kind_assign)
  252. attributesAsWritten |= ObjCPropertyAttribute::kind_assign;
  253. if (Attributes & ObjCPropertyAttribute::kind_retain)
  254. attributesAsWritten |= ObjCPropertyAttribute::kind_retain;
  255. if (Attributes & ObjCPropertyAttribute::kind_strong)
  256. attributesAsWritten |= ObjCPropertyAttribute::kind_strong;
  257. if (Attributes & ObjCPropertyAttribute::kind_weak)
  258. attributesAsWritten |= ObjCPropertyAttribute::kind_weak;
  259. if (Attributes & ObjCPropertyAttribute::kind_copy)
  260. attributesAsWritten |= ObjCPropertyAttribute::kind_copy;
  261. if (Attributes & ObjCPropertyAttribute::kind_unsafe_unretained)
  262. attributesAsWritten |= ObjCPropertyAttribute::kind_unsafe_unretained;
  263. if (Attributes & ObjCPropertyAttribute::kind_nonatomic)
  264. attributesAsWritten |= ObjCPropertyAttribute::kind_nonatomic;
  265. if (Attributes & ObjCPropertyAttribute::kind_atomic)
  266. attributesAsWritten |= ObjCPropertyAttribute::kind_atomic;
  267. if (Attributes & ObjCPropertyAttribute::kind_class)
  268. attributesAsWritten |= ObjCPropertyAttribute::kind_class;
  269. if (Attributes & ObjCPropertyAttribute::kind_direct)
  270. attributesAsWritten |= ObjCPropertyAttribute::kind_direct;
  271. return (ObjCPropertyAttribute::Kind)attributesAsWritten;
  272. }
  273. static bool LocPropertyAttribute( ASTContext &Context, const char *attrName,
  274. SourceLocation LParenLoc, SourceLocation &Loc) {
  275. if (LParenLoc.isMacroID())
  276. return false;
  277. SourceManager &SM = Context.getSourceManager();
  278. std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(LParenLoc);
  279. // Try to load the file buffer.
  280. bool invalidTemp = false;
  281. StringRef file = SM.getBufferData(locInfo.first, &invalidTemp);
  282. if (invalidTemp)
  283. return false;
  284. const char *tokenBegin = file.data() + locInfo.second;
  285. // Lex from the start of the given location.
  286. Lexer lexer(SM.getLocForStartOfFile(locInfo.first),
  287. Context.getLangOpts(),
  288. file.begin(), tokenBegin, file.end());
  289. Token Tok;
  290. do {
  291. lexer.LexFromRawLexer(Tok);
  292. if (Tok.is(tok::raw_identifier) && Tok.getRawIdentifier() == attrName) {
  293. Loc = Tok.getLocation();
  294. return true;
  295. }
  296. } while (Tok.isNot(tok::r_paren));
  297. return false;
  298. }
  299. /// Check for a mismatch in the atomicity of the given properties.
  300. static void checkAtomicPropertyMismatch(Sema &S,
  301. ObjCPropertyDecl *OldProperty,
  302. ObjCPropertyDecl *NewProperty,
  303. bool PropagateAtomicity) {
  304. // If the atomicity of both matches, we're done.
  305. bool OldIsAtomic = (OldProperty->getPropertyAttributes() &
  306. ObjCPropertyAttribute::kind_nonatomic) == 0;
  307. bool NewIsAtomic = (NewProperty->getPropertyAttributes() &
  308. ObjCPropertyAttribute::kind_nonatomic) == 0;
  309. if (OldIsAtomic == NewIsAtomic) return;
  310. // Determine whether the given property is readonly and implicitly
  311. // atomic.
  312. auto isImplicitlyReadonlyAtomic = [](ObjCPropertyDecl *Property) -> bool {
  313. // Is it readonly?
  314. auto Attrs = Property->getPropertyAttributes();
  315. if ((Attrs & ObjCPropertyAttribute::kind_readonly) == 0)
  316. return false;
  317. // Is it nonatomic?
  318. if (Attrs & ObjCPropertyAttribute::kind_nonatomic)
  319. return false;
  320. // Was 'atomic' specified directly?
  321. if (Property->getPropertyAttributesAsWritten() &
  322. ObjCPropertyAttribute::kind_atomic)
  323. return false;
  324. return true;
  325. };
  326. // If we're allowed to propagate atomicity, and the new property did
  327. // not specify atomicity at all, propagate.
  328. const unsigned AtomicityMask = (ObjCPropertyAttribute::kind_atomic |
  329. ObjCPropertyAttribute::kind_nonatomic);
  330. if (PropagateAtomicity &&
  331. ((NewProperty->getPropertyAttributesAsWritten() & AtomicityMask) == 0)) {
  332. unsigned Attrs = NewProperty->getPropertyAttributes();
  333. Attrs = Attrs & ~AtomicityMask;
  334. if (OldIsAtomic)
  335. Attrs |= ObjCPropertyAttribute::kind_atomic;
  336. else
  337. Attrs |= ObjCPropertyAttribute::kind_nonatomic;
  338. NewProperty->overwritePropertyAttributes(Attrs);
  339. return;
  340. }
  341. // One of the properties is atomic; if it's a readonly property, and
  342. // 'atomic' wasn't explicitly specified, we're okay.
  343. if ((OldIsAtomic && isImplicitlyReadonlyAtomic(OldProperty)) ||
  344. (NewIsAtomic && isImplicitlyReadonlyAtomic(NewProperty)))
  345. return;
  346. // Diagnose the conflict.
  347. const IdentifierInfo *OldContextName;
  348. auto *OldDC = OldProperty->getDeclContext();
  349. if (auto Category = dyn_cast<ObjCCategoryDecl>(OldDC))
  350. OldContextName = Category->getClassInterface()->getIdentifier();
  351. else
  352. OldContextName = cast<ObjCContainerDecl>(OldDC)->getIdentifier();
  353. S.Diag(NewProperty->getLocation(), diag::warn_property_attribute)
  354. << NewProperty->getDeclName() << "atomic"
  355. << OldContextName;
  356. S.Diag(OldProperty->getLocation(), diag::note_property_declare);
  357. }
  358. ObjCPropertyDecl *
  359. Sema::HandlePropertyInClassExtension(Scope *S,
  360. SourceLocation AtLoc,
  361. SourceLocation LParenLoc,
  362. FieldDeclarator &FD,
  363. Selector GetterSel,
  364. SourceLocation GetterNameLoc,
  365. Selector SetterSel,
  366. SourceLocation SetterNameLoc,
  367. const bool isReadWrite,
  368. unsigned &Attributes,
  369. const unsigned AttributesAsWritten,
  370. QualType T,
  371. TypeSourceInfo *TSI,
  372. tok::ObjCKeywordKind MethodImplKind) {
  373. ObjCCategoryDecl *CDecl = cast<ObjCCategoryDecl>(CurContext);
  374. // Diagnose if this property is already in continuation class.
  375. DeclContext *DC = CurContext;
  376. IdentifierInfo *PropertyId = FD.D.getIdentifier();
  377. ObjCInterfaceDecl *CCPrimary = CDecl->getClassInterface();
  378. // We need to look in the @interface to see if the @property was
  379. // already declared.
  380. if (!CCPrimary) {
  381. Diag(CDecl->getLocation(), diag::err_continuation_class);
  382. return nullptr;
  383. }
  384. bool isClassProperty =
  385. (AttributesAsWritten & ObjCPropertyAttribute::kind_class) ||
  386. (Attributes & ObjCPropertyAttribute::kind_class);
  387. // Find the property in the extended class's primary class or
  388. // extensions.
  389. ObjCPropertyDecl *PIDecl = CCPrimary->FindPropertyVisibleInPrimaryClass(
  390. PropertyId, ObjCPropertyDecl::getQueryKind(isClassProperty));
  391. // If we found a property in an extension, complain.
  392. if (PIDecl && isa<ObjCCategoryDecl>(PIDecl->getDeclContext())) {
  393. Diag(AtLoc, diag::err_duplicate_property);
  394. Diag(PIDecl->getLocation(), diag::note_property_declare);
  395. return nullptr;
  396. }
  397. // Check for consistency with the previous declaration, if there is one.
  398. if (PIDecl) {
  399. // A readonly property declared in the primary class can be refined
  400. // by adding a readwrite property within an extension.
  401. // Anything else is an error.
  402. if (!(PIDecl->isReadOnly() && isReadWrite)) {
  403. // Tailor the diagnostics for the common case where a readwrite
  404. // property is declared both in the @interface and the continuation.
  405. // This is a common error where the user often intended the original
  406. // declaration to be readonly.
  407. unsigned diag =
  408. (Attributes & ObjCPropertyAttribute::kind_readwrite) &&
  409. (PIDecl->getPropertyAttributesAsWritten() &
  410. ObjCPropertyAttribute::kind_readwrite)
  411. ? diag::err_use_continuation_class_redeclaration_readwrite
  412. : diag::err_use_continuation_class;
  413. Diag(AtLoc, diag)
  414. << CCPrimary->getDeclName();
  415. Diag(PIDecl->getLocation(), diag::note_property_declare);
  416. return nullptr;
  417. }
  418. // Check for consistency of getters.
  419. if (PIDecl->getGetterName() != GetterSel) {
  420. // If the getter was written explicitly, complain.
  421. if (AttributesAsWritten & ObjCPropertyAttribute::kind_getter) {
  422. Diag(AtLoc, diag::warn_property_redecl_getter_mismatch)
  423. << PIDecl->getGetterName() << GetterSel;
  424. Diag(PIDecl->getLocation(), diag::note_property_declare);
  425. }
  426. // Always adopt the getter from the original declaration.
  427. GetterSel = PIDecl->getGetterName();
  428. Attributes |= ObjCPropertyAttribute::kind_getter;
  429. }
  430. // Check consistency of ownership.
  431. unsigned ExistingOwnership
  432. = getOwnershipRule(PIDecl->getPropertyAttributes());
  433. unsigned NewOwnership = getOwnershipRule(Attributes);
  434. if (ExistingOwnership && NewOwnership != ExistingOwnership) {
  435. // If the ownership was written explicitly, complain.
  436. if (getOwnershipRule(AttributesAsWritten)) {
  437. Diag(AtLoc, diag::warn_property_attr_mismatch);
  438. Diag(PIDecl->getLocation(), diag::note_property_declare);
  439. }
  440. // Take the ownership from the original property.
  441. Attributes = (Attributes & ~OwnershipMask) | ExistingOwnership;
  442. }
  443. // If the redeclaration is 'weak' but the original property is not,
  444. if ((Attributes & ObjCPropertyAttribute::kind_weak) &&
  445. !(PIDecl->getPropertyAttributesAsWritten() &
  446. ObjCPropertyAttribute::kind_weak) &&
  447. PIDecl->getType()->getAs<ObjCObjectPointerType>() &&
  448. PIDecl->getType().getObjCLifetime() == Qualifiers::OCL_None) {
  449. Diag(AtLoc, diag::warn_property_implicitly_mismatched);
  450. Diag(PIDecl->getLocation(), diag::note_property_declare);
  451. }
  452. }
  453. // Create a new ObjCPropertyDecl with the DeclContext being
  454. // the class extension.
  455. ObjCPropertyDecl *PDecl = CreatePropertyDecl(S, CDecl, AtLoc, LParenLoc,
  456. FD, GetterSel, GetterNameLoc,
  457. SetterSel, SetterNameLoc,
  458. isReadWrite,
  459. Attributes, AttributesAsWritten,
  460. T, TSI, MethodImplKind, DC);
  461. // If there was no declaration of a property with the same name in
  462. // the primary class, we're done.
  463. if (!PIDecl) {
  464. ProcessPropertyDecl(PDecl);
  465. return PDecl;
  466. }
  467. if (!Context.hasSameType(PIDecl->getType(), PDecl->getType())) {
  468. bool IncompatibleObjC = false;
  469. QualType ConvertedType;
  470. // Relax the strict type matching for property type in continuation class.
  471. // Allow property object type of continuation class to be different as long
  472. // as it narrows the object type in its primary class property. Note that
  473. // this conversion is safe only because the wider type is for a 'readonly'
  474. // property in primary class and 'narrowed' type for a 'readwrite' property
  475. // in continuation class.
  476. QualType PrimaryClassPropertyT = Context.getCanonicalType(PIDecl->getType());
  477. QualType ClassExtPropertyT = Context.getCanonicalType(PDecl->getType());
  478. if (!isa<ObjCObjectPointerType>(PrimaryClassPropertyT) ||
  479. !isa<ObjCObjectPointerType>(ClassExtPropertyT) ||
  480. (!isObjCPointerConversion(ClassExtPropertyT, PrimaryClassPropertyT,
  481. ConvertedType, IncompatibleObjC))
  482. || IncompatibleObjC) {
  483. Diag(AtLoc,
  484. diag::err_type_mismatch_continuation_class) << PDecl->getType();
  485. Diag(PIDecl->getLocation(), diag::note_property_declare);
  486. return nullptr;
  487. }
  488. }
  489. // Check that atomicity of property in class extension matches the previous
  490. // declaration.
  491. checkAtomicPropertyMismatch(*this, PIDecl, PDecl, true);
  492. // Make sure getter/setter are appropriately synthesized.
  493. ProcessPropertyDecl(PDecl);
  494. return PDecl;
  495. }
  496. ObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S,
  497. ObjCContainerDecl *CDecl,
  498. SourceLocation AtLoc,
  499. SourceLocation LParenLoc,
  500. FieldDeclarator &FD,
  501. Selector GetterSel,
  502. SourceLocation GetterNameLoc,
  503. Selector SetterSel,
  504. SourceLocation SetterNameLoc,
  505. const bool isReadWrite,
  506. const unsigned Attributes,
  507. const unsigned AttributesAsWritten,
  508. QualType T,
  509. TypeSourceInfo *TInfo,
  510. tok::ObjCKeywordKind MethodImplKind,
  511. DeclContext *lexicalDC){
  512. IdentifierInfo *PropertyId = FD.D.getIdentifier();
  513. // Property defaults to 'assign' if it is readwrite, unless this is ARC
  514. // and the type is retainable.
  515. bool isAssign;
  516. if (Attributes & (ObjCPropertyAttribute::kind_assign |
  517. ObjCPropertyAttribute::kind_unsafe_unretained)) {
  518. isAssign = true;
  519. } else if (getOwnershipRule(Attributes) || !isReadWrite) {
  520. isAssign = false;
  521. } else {
  522. isAssign = (!getLangOpts().ObjCAutoRefCount ||
  523. !T->isObjCRetainableType());
  524. }
  525. // Issue a warning if property is 'assign' as default and its
  526. // object, which is gc'able conforms to NSCopying protocol
  527. if (getLangOpts().getGC() != LangOptions::NonGC && isAssign &&
  528. !(Attributes & ObjCPropertyAttribute::kind_assign)) {
  529. if (const ObjCObjectPointerType *ObjPtrTy =
  530. T->getAs<ObjCObjectPointerType>()) {
  531. ObjCInterfaceDecl *IDecl = ObjPtrTy->getObjectType()->getInterface();
  532. if (IDecl)
  533. if (ObjCProtocolDecl* PNSCopying =
  534. LookupProtocol(&Context.Idents.get("NSCopying"), AtLoc))
  535. if (IDecl->ClassImplementsProtocol(PNSCopying, true))
  536. Diag(AtLoc, diag::warn_implements_nscopying) << PropertyId;
  537. }
  538. }
  539. if (T->isObjCObjectType()) {
  540. SourceLocation StarLoc = TInfo->getTypeLoc().getEndLoc();
  541. StarLoc = getLocForEndOfToken(StarLoc);
  542. Diag(FD.D.getIdentifierLoc(), diag::err_statically_allocated_object)
  543. << FixItHint::CreateInsertion(StarLoc, "*");
  544. T = Context.getObjCObjectPointerType(T);
  545. SourceLocation TLoc = TInfo->getTypeLoc().getBeginLoc();
  546. TInfo = Context.getTrivialTypeSourceInfo(T, TLoc);
  547. }
  548. DeclContext *DC = CDecl;
  549. ObjCPropertyDecl *PDecl = ObjCPropertyDecl::Create(Context, DC,
  550. FD.D.getIdentifierLoc(),
  551. PropertyId, AtLoc,
  552. LParenLoc, T, TInfo);
  553. bool isClassProperty =
  554. (AttributesAsWritten & ObjCPropertyAttribute::kind_class) ||
  555. (Attributes & ObjCPropertyAttribute::kind_class);
  556. // Class property and instance property can have the same name.
  557. if (ObjCPropertyDecl *prevDecl = ObjCPropertyDecl::findPropertyDecl(
  558. DC, PropertyId, ObjCPropertyDecl::getQueryKind(isClassProperty))) {
  559. Diag(PDecl->getLocation(), diag::err_duplicate_property);
  560. Diag(prevDecl->getLocation(), diag::note_property_declare);
  561. PDecl->setInvalidDecl();
  562. }
  563. else {
  564. DC->addDecl(PDecl);
  565. if (lexicalDC)
  566. PDecl->setLexicalDeclContext(lexicalDC);
  567. }
  568. if (T->isArrayType() || T->isFunctionType()) {
  569. Diag(AtLoc, diag::err_property_type) << T;
  570. PDecl->setInvalidDecl();
  571. }
  572. ProcessDeclAttributes(S, PDecl, FD.D);
  573. // Regardless of setter/getter attribute, we save the default getter/setter
  574. // selector names in anticipation of declaration of setter/getter methods.
  575. PDecl->setGetterName(GetterSel, GetterNameLoc);
  576. PDecl->setSetterName(SetterSel, SetterNameLoc);
  577. PDecl->setPropertyAttributesAsWritten(
  578. makePropertyAttributesAsWritten(AttributesAsWritten));
  579. if (Attributes & ObjCPropertyAttribute::kind_readonly)
  580. PDecl->setPropertyAttributes(ObjCPropertyAttribute::kind_readonly);
  581. if (Attributes & ObjCPropertyAttribute::kind_getter)
  582. PDecl->setPropertyAttributes(ObjCPropertyAttribute::kind_getter);
  583. if (Attributes & ObjCPropertyAttribute::kind_setter)
  584. PDecl->setPropertyAttributes(ObjCPropertyAttribute::kind_setter);
  585. if (isReadWrite)
  586. PDecl->setPropertyAttributes(ObjCPropertyAttribute::kind_readwrite);
  587. if (Attributes & ObjCPropertyAttribute::kind_retain)
  588. PDecl->setPropertyAttributes(ObjCPropertyAttribute::kind_retain);
  589. if (Attributes & ObjCPropertyAttribute::kind_strong)
  590. PDecl->setPropertyAttributes(ObjCPropertyAttribute::kind_strong);
  591. if (Attributes & ObjCPropertyAttribute::kind_weak)
  592. PDecl->setPropertyAttributes(ObjCPropertyAttribute::kind_weak);
  593. if (Attributes & ObjCPropertyAttribute::kind_copy)
  594. PDecl->setPropertyAttributes(ObjCPropertyAttribute::kind_copy);
  595. if (Attributes & ObjCPropertyAttribute::kind_unsafe_unretained)
  596. PDecl->setPropertyAttributes(ObjCPropertyAttribute::kind_unsafe_unretained);
  597. if (isAssign)
  598. PDecl->setPropertyAttributes(ObjCPropertyAttribute::kind_assign);
  599. // In the semantic attributes, one of nonatomic or atomic is always set.
  600. if (Attributes & ObjCPropertyAttribute::kind_nonatomic)
  601. PDecl->setPropertyAttributes(ObjCPropertyAttribute::kind_nonatomic);
  602. else
  603. PDecl->setPropertyAttributes(ObjCPropertyAttribute::kind_atomic);
  604. // 'unsafe_unretained' is alias for 'assign'.
  605. if (Attributes & ObjCPropertyAttribute::kind_unsafe_unretained)
  606. PDecl->setPropertyAttributes(ObjCPropertyAttribute::kind_assign);
  607. if (isAssign)
  608. PDecl->setPropertyAttributes(ObjCPropertyAttribute::kind_unsafe_unretained);
  609. if (MethodImplKind == tok::objc_required)
  610. PDecl->setPropertyImplementation(ObjCPropertyDecl::Required);
  611. else if (MethodImplKind == tok::objc_optional)
  612. PDecl->setPropertyImplementation(ObjCPropertyDecl::Optional);
  613. if (Attributes & ObjCPropertyAttribute::kind_nullability)
  614. PDecl->setPropertyAttributes(ObjCPropertyAttribute::kind_nullability);
  615. if (Attributes & ObjCPropertyAttribute::kind_null_resettable)
  616. PDecl->setPropertyAttributes(ObjCPropertyAttribute::kind_null_resettable);
  617. if (Attributes & ObjCPropertyAttribute::kind_class)
  618. PDecl->setPropertyAttributes(ObjCPropertyAttribute::kind_class);
  619. if ((Attributes & ObjCPropertyAttribute::kind_direct) ||
  620. CDecl->hasAttr<ObjCDirectMembersAttr>()) {
  621. if (isa<ObjCProtocolDecl>(CDecl)) {
  622. Diag(PDecl->getLocation(), diag::err_objc_direct_on_protocol) << true;
  623. } else if (getLangOpts().ObjCRuntime.allowsDirectDispatch()) {
  624. PDecl->setPropertyAttributes(ObjCPropertyAttribute::kind_direct);
  625. } else {
  626. Diag(PDecl->getLocation(), diag::warn_objc_direct_property_ignored)
  627. << PDecl->getDeclName();
  628. }
  629. }
  630. return PDecl;
  631. }
  632. static void checkARCPropertyImpl(Sema &S, SourceLocation propertyImplLoc,
  633. ObjCPropertyDecl *property,
  634. ObjCIvarDecl *ivar) {
  635. if (property->isInvalidDecl() || ivar->isInvalidDecl()) return;
  636. QualType ivarType = ivar->getType();
  637. Qualifiers::ObjCLifetime ivarLifetime = ivarType.getObjCLifetime();
  638. // The lifetime implied by the property's attributes.
  639. Qualifiers::ObjCLifetime propertyLifetime =
  640. getImpliedARCOwnership(property->getPropertyAttributes(),
  641. property->getType());
  642. // We're fine if they match.
  643. if (propertyLifetime == ivarLifetime) return;
  644. // None isn't a valid lifetime for an object ivar in ARC, and
  645. // __autoreleasing is never valid; don't diagnose twice.
  646. if ((ivarLifetime == Qualifiers::OCL_None &&
  647. S.getLangOpts().ObjCAutoRefCount) ||
  648. ivarLifetime == Qualifiers::OCL_Autoreleasing)
  649. return;
  650. // If the ivar is private, and it's implicitly __unsafe_unretained
  651. // because of its type, then pretend it was actually implicitly
  652. // __strong. This is only sound because we're processing the
  653. // property implementation before parsing any method bodies.
  654. if (ivarLifetime == Qualifiers::OCL_ExplicitNone &&
  655. propertyLifetime == Qualifiers::OCL_Strong &&
  656. ivar->getAccessControl() == ObjCIvarDecl::Private) {
  657. SplitQualType split = ivarType.split();
  658. if (split.Quals.hasObjCLifetime()) {
  659. assert(ivarType->isObjCARCImplicitlyUnretainedType());
  660. split.Quals.setObjCLifetime(Qualifiers::OCL_Strong);
  661. ivarType = S.Context.getQualifiedType(split);
  662. ivar->setType(ivarType);
  663. return;
  664. }
  665. }
  666. switch (propertyLifetime) {
  667. case Qualifiers::OCL_Strong:
  668. S.Diag(ivar->getLocation(), diag::err_arc_strong_property_ownership)
  669. << property->getDeclName()
  670. << ivar->getDeclName()
  671. << ivarLifetime;
  672. break;
  673. case Qualifiers::OCL_Weak:
  674. S.Diag(ivar->getLocation(), diag::err_weak_property)
  675. << property->getDeclName()
  676. << ivar->getDeclName();
  677. break;
  678. case Qualifiers::OCL_ExplicitNone:
  679. S.Diag(ivar->getLocation(), diag::err_arc_assign_property_ownership)
  680. << property->getDeclName() << ivar->getDeclName()
  681. << ((property->getPropertyAttributesAsWritten() &
  682. ObjCPropertyAttribute::kind_assign) != 0);
  683. break;
  684. case Qualifiers::OCL_Autoreleasing:
  685. llvm_unreachable("properties cannot be autoreleasing");
  686. case Qualifiers::OCL_None:
  687. // Any other property should be ignored.
  688. return;
  689. }
  690. S.Diag(property->getLocation(), diag::note_property_declare);
  691. if (propertyImplLoc.isValid())
  692. S.Diag(propertyImplLoc, diag::note_property_synthesize);
  693. }
  694. /// setImpliedPropertyAttributeForReadOnlyProperty -
  695. /// This routine evaludates life-time attributes for a 'readonly'
  696. /// property with no known lifetime of its own, using backing
  697. /// 'ivar's attribute, if any. If no backing 'ivar', property's
  698. /// life-time is assumed 'strong'.
  699. static void setImpliedPropertyAttributeForReadOnlyProperty(
  700. ObjCPropertyDecl *property, ObjCIvarDecl *ivar) {
  701. Qualifiers::ObjCLifetime propertyLifetime =
  702. getImpliedARCOwnership(property->getPropertyAttributes(),
  703. property->getType());
  704. if (propertyLifetime != Qualifiers::OCL_None)
  705. return;
  706. if (!ivar) {
  707. // if no backing ivar, make property 'strong'.
  708. property->setPropertyAttributes(ObjCPropertyAttribute::kind_strong);
  709. return;
  710. }
  711. // property assumes owenership of backing ivar.
  712. QualType ivarType = ivar->getType();
  713. Qualifiers::ObjCLifetime ivarLifetime = ivarType.getObjCLifetime();
  714. if (ivarLifetime == Qualifiers::OCL_Strong)
  715. property->setPropertyAttributes(ObjCPropertyAttribute::kind_strong);
  716. else if (ivarLifetime == Qualifiers::OCL_Weak)
  717. property->setPropertyAttributes(ObjCPropertyAttribute::kind_weak);
  718. }
  719. static bool isIncompatiblePropertyAttribute(unsigned Attr1, unsigned Attr2,
  720. ObjCPropertyAttribute::Kind Kind) {
  721. return (Attr1 & Kind) != (Attr2 & Kind);
  722. }
  723. static bool areIncompatiblePropertyAttributes(unsigned Attr1, unsigned Attr2,
  724. unsigned Kinds) {
  725. return ((Attr1 & Kinds) != 0) != ((Attr2 & Kinds) != 0);
  726. }
  727. /// SelectPropertyForSynthesisFromProtocols - Finds the most appropriate
  728. /// property declaration that should be synthesised in all of the inherited
  729. /// protocols. It also diagnoses properties declared in inherited protocols with
  730. /// mismatched types or attributes, since any of them can be candidate for
  731. /// synthesis.
  732. static ObjCPropertyDecl *
  733. SelectPropertyForSynthesisFromProtocols(Sema &S, SourceLocation AtLoc,
  734. ObjCInterfaceDecl *ClassDecl,
  735. ObjCPropertyDecl *Property) {
  736. assert(isa<ObjCProtocolDecl>(Property->getDeclContext()) &&
  737. "Expected a property from a protocol");
  738. ObjCInterfaceDecl::ProtocolPropertySet ProtocolSet;
  739. ObjCInterfaceDecl::PropertyDeclOrder Properties;
  740. for (const auto *PI : ClassDecl->all_referenced_protocols()) {
  741. if (const ObjCProtocolDecl *PDecl = PI->getDefinition())
  742. PDecl->collectInheritedProtocolProperties(Property, ProtocolSet,
  743. Properties);
  744. }
  745. if (ObjCInterfaceDecl *SDecl = ClassDecl->getSuperClass()) {
  746. while (SDecl) {
  747. for (const auto *PI : SDecl->all_referenced_protocols()) {
  748. if (const ObjCProtocolDecl *PDecl = PI->getDefinition())
  749. PDecl->collectInheritedProtocolProperties(Property, ProtocolSet,
  750. Properties);
  751. }
  752. SDecl = SDecl->getSuperClass();
  753. }
  754. }
  755. if (Properties.empty())
  756. return Property;
  757. ObjCPropertyDecl *OriginalProperty = Property;
  758. size_t SelectedIndex = 0;
  759. for (const auto &Prop : llvm::enumerate(Properties)) {
  760. // Select the 'readwrite' property if such property exists.
  761. if (Property->isReadOnly() && !Prop.value()->isReadOnly()) {
  762. Property = Prop.value();
  763. SelectedIndex = Prop.index();
  764. }
  765. }
  766. if (Property != OriginalProperty) {
  767. // Check that the old property is compatible with the new one.
  768. Properties[SelectedIndex] = OriginalProperty;
  769. }
  770. QualType RHSType = S.Context.getCanonicalType(Property->getType());
  771. unsigned OriginalAttributes = Property->getPropertyAttributesAsWritten();
  772. enum MismatchKind {
  773. IncompatibleType = 0,
  774. HasNoExpectedAttribute,
  775. HasUnexpectedAttribute,
  776. DifferentGetter,
  777. DifferentSetter
  778. };
  779. // Represents a property from another protocol that conflicts with the
  780. // selected declaration.
  781. struct MismatchingProperty {
  782. const ObjCPropertyDecl *Prop;
  783. MismatchKind Kind;
  784. StringRef AttributeName;
  785. };
  786. SmallVector<MismatchingProperty, 4> Mismatches;
  787. for (ObjCPropertyDecl *Prop : Properties) {
  788. // Verify the property attributes.
  789. unsigned Attr = Prop->getPropertyAttributesAsWritten();
  790. if (Attr != OriginalAttributes) {
  791. auto Diag = [&](bool OriginalHasAttribute, StringRef AttributeName) {
  792. MismatchKind Kind = OriginalHasAttribute ? HasNoExpectedAttribute
  793. : HasUnexpectedAttribute;
  794. Mismatches.push_back({Prop, Kind, AttributeName});
  795. };
  796. // The ownership might be incompatible unless the property has no explicit
  797. // ownership.
  798. bool HasOwnership =
  799. (Attr & (ObjCPropertyAttribute::kind_retain |
  800. ObjCPropertyAttribute::kind_strong |
  801. ObjCPropertyAttribute::kind_copy |
  802. ObjCPropertyAttribute::kind_assign |
  803. ObjCPropertyAttribute::kind_unsafe_unretained |
  804. ObjCPropertyAttribute::kind_weak)) != 0;
  805. if (HasOwnership &&
  806. isIncompatiblePropertyAttribute(OriginalAttributes, Attr,
  807. ObjCPropertyAttribute::kind_copy)) {
  808. Diag(OriginalAttributes & ObjCPropertyAttribute::kind_copy, "copy");
  809. continue;
  810. }
  811. if (HasOwnership && areIncompatiblePropertyAttributes(
  812. OriginalAttributes, Attr,
  813. ObjCPropertyAttribute::kind_retain |
  814. ObjCPropertyAttribute::kind_strong)) {
  815. Diag(OriginalAttributes & (ObjCPropertyAttribute::kind_retain |
  816. ObjCPropertyAttribute::kind_strong),
  817. "retain (or strong)");
  818. continue;
  819. }
  820. if (isIncompatiblePropertyAttribute(OriginalAttributes, Attr,
  821. ObjCPropertyAttribute::kind_atomic)) {
  822. Diag(OriginalAttributes & ObjCPropertyAttribute::kind_atomic, "atomic");
  823. continue;
  824. }
  825. }
  826. if (Property->getGetterName() != Prop->getGetterName()) {
  827. Mismatches.push_back({Prop, DifferentGetter, ""});
  828. continue;
  829. }
  830. if (!Property->isReadOnly() && !Prop->isReadOnly() &&
  831. Property->getSetterName() != Prop->getSetterName()) {
  832. Mismatches.push_back({Prop, DifferentSetter, ""});
  833. continue;
  834. }
  835. QualType LHSType = S.Context.getCanonicalType(Prop->getType());
  836. if (!S.Context.propertyTypesAreCompatible(LHSType, RHSType)) {
  837. bool IncompatibleObjC = false;
  838. QualType ConvertedType;
  839. if (!S.isObjCPointerConversion(RHSType, LHSType, ConvertedType, IncompatibleObjC)
  840. || IncompatibleObjC) {
  841. Mismatches.push_back({Prop, IncompatibleType, ""});
  842. continue;
  843. }
  844. }
  845. }
  846. if (Mismatches.empty())
  847. return Property;
  848. // Diagnose incompability.
  849. {
  850. bool HasIncompatibleAttributes = false;
  851. for (const auto &Note : Mismatches)
  852. HasIncompatibleAttributes =
  853. Note.Kind != IncompatibleType ? true : HasIncompatibleAttributes;
  854. // Promote the warning to an error if there are incompatible attributes or
  855. // incompatible types together with readwrite/readonly incompatibility.
  856. auto Diag = S.Diag(Property->getLocation(),
  857. Property != OriginalProperty || HasIncompatibleAttributes
  858. ? diag::err_protocol_property_mismatch
  859. : diag::warn_protocol_property_mismatch);
  860. Diag << Mismatches[0].Kind;
  861. switch (Mismatches[0].Kind) {
  862. case IncompatibleType:
  863. Diag << Property->getType();
  864. break;
  865. case HasNoExpectedAttribute:
  866. case HasUnexpectedAttribute:
  867. Diag << Mismatches[0].AttributeName;
  868. break;
  869. case DifferentGetter:
  870. Diag << Property->getGetterName();
  871. break;
  872. case DifferentSetter:
  873. Diag << Property->getSetterName();
  874. break;
  875. }
  876. }
  877. for (const auto &Note : Mismatches) {
  878. auto Diag =
  879. S.Diag(Note.Prop->getLocation(), diag::note_protocol_property_declare)
  880. << Note.Kind;
  881. switch (Note.Kind) {
  882. case IncompatibleType:
  883. Diag << Note.Prop->getType();
  884. break;
  885. case HasNoExpectedAttribute:
  886. case HasUnexpectedAttribute:
  887. Diag << Note.AttributeName;
  888. break;
  889. case DifferentGetter:
  890. Diag << Note.Prop->getGetterName();
  891. break;
  892. case DifferentSetter:
  893. Diag << Note.Prop->getSetterName();
  894. break;
  895. }
  896. }
  897. if (AtLoc.isValid())
  898. S.Diag(AtLoc, diag::note_property_synthesize);
  899. return Property;
  900. }
  901. /// Determine whether any storage attributes were written on the property.
  902. static bool hasWrittenStorageAttribute(ObjCPropertyDecl *Prop,
  903. ObjCPropertyQueryKind QueryKind) {
  904. if (Prop->getPropertyAttributesAsWritten() & OwnershipMask) return true;
  905. // If this is a readwrite property in a class extension that refines
  906. // a readonly property in the original class definition, check it as
  907. // well.
  908. // If it's a readonly property, we're not interested.
  909. if (Prop->isReadOnly()) return false;
  910. // Is it declared in an extension?
  911. auto Category = dyn_cast<ObjCCategoryDecl>(Prop->getDeclContext());
  912. if (!Category || !Category->IsClassExtension()) return false;
  913. // Find the corresponding property in the primary class definition.
  914. auto OrigClass = Category->getClassInterface();
  915. for (auto *Found : OrigClass->lookup(Prop->getDeclName())) {
  916. if (ObjCPropertyDecl *OrigProp = dyn_cast<ObjCPropertyDecl>(Found))
  917. return OrigProp->getPropertyAttributesAsWritten() & OwnershipMask;
  918. }
  919. // Look through all of the protocols.
  920. for (const auto *Proto : OrigClass->all_referenced_protocols()) {
  921. if (ObjCPropertyDecl *OrigProp = Proto->FindPropertyDeclaration(
  922. Prop->getIdentifier(), QueryKind))
  923. return OrigProp->getPropertyAttributesAsWritten() & OwnershipMask;
  924. }
  925. return false;
  926. }
  927. /// Create a synthesized property accessor stub inside the \@implementation.
  928. static ObjCMethodDecl *
  929. RedeclarePropertyAccessor(ASTContext &Context, ObjCImplementationDecl *Impl,
  930. ObjCMethodDecl *AccessorDecl, SourceLocation AtLoc,
  931. SourceLocation PropertyLoc) {
  932. ObjCMethodDecl *Decl = AccessorDecl;
  933. ObjCMethodDecl *ImplDecl = ObjCMethodDecl::Create(
  934. Context, AtLoc.isValid() ? AtLoc : Decl->getBeginLoc(),
  935. PropertyLoc.isValid() ? PropertyLoc : Decl->getEndLoc(),
  936. Decl->getSelector(), Decl->getReturnType(),
  937. Decl->getReturnTypeSourceInfo(), Impl, Decl->isInstanceMethod(),
  938. Decl->isVariadic(), Decl->isPropertyAccessor(),
  939. /* isSynthesized*/ true, Decl->isImplicit(), Decl->isDefined(),
  940. Decl->getImplementationControl(), Decl->hasRelatedResultType());
  941. ImplDecl->getMethodFamily();
  942. if (Decl->hasAttrs())
  943. ImplDecl->setAttrs(Decl->getAttrs());
  944. ImplDecl->setSelfDecl(Decl->getSelfDecl());
  945. ImplDecl->setCmdDecl(Decl->getCmdDecl());
  946. SmallVector<SourceLocation, 1> SelLocs;
  947. Decl->getSelectorLocs(SelLocs);
  948. ImplDecl->setMethodParams(Context, Decl->parameters(), SelLocs);
  949. ImplDecl->setLexicalDeclContext(Impl);
  950. ImplDecl->setDefined(false);
  951. return ImplDecl;
  952. }
  953. /// ActOnPropertyImplDecl - This routine performs semantic checks and
  954. /// builds the AST node for a property implementation declaration; declared
  955. /// as \@synthesize or \@dynamic.
  956. ///
  957. Decl *Sema::ActOnPropertyImplDecl(Scope *S,
  958. SourceLocation AtLoc,
  959. SourceLocation PropertyLoc,
  960. bool Synthesize,
  961. IdentifierInfo *PropertyId,
  962. IdentifierInfo *PropertyIvar,
  963. SourceLocation PropertyIvarLoc,
  964. ObjCPropertyQueryKind QueryKind) {
  965. ObjCContainerDecl *ClassImpDecl =
  966. dyn_cast<ObjCContainerDecl>(CurContext);
  967. // Make sure we have a context for the property implementation declaration.
  968. if (!ClassImpDecl) {
  969. Diag(AtLoc, diag::err_missing_property_context);
  970. return nullptr;
  971. }
  972. if (PropertyIvarLoc.isInvalid())
  973. PropertyIvarLoc = PropertyLoc;
  974. SourceLocation PropertyDiagLoc = PropertyLoc;
  975. if (PropertyDiagLoc.isInvalid())
  976. PropertyDiagLoc = ClassImpDecl->getBeginLoc();
  977. ObjCPropertyDecl *property = nullptr;
  978. ObjCInterfaceDecl *IDecl = nullptr;
  979. // Find the class or category class where this property must have
  980. // a declaration.
  981. ObjCImplementationDecl *IC = nullptr;
  982. ObjCCategoryImplDecl *CatImplClass = nullptr;
  983. if ((IC = dyn_cast<ObjCImplementationDecl>(ClassImpDecl))) {
  984. IDecl = IC->getClassInterface();
  985. // We always synthesize an interface for an implementation
  986. // without an interface decl. So, IDecl is always non-zero.
  987. assert(IDecl &&
  988. "ActOnPropertyImplDecl - @implementation without @interface");
  989. // Look for this property declaration in the @implementation's @interface
  990. property = IDecl->FindPropertyDeclaration(PropertyId, QueryKind);
  991. if (!property) {
  992. Diag(PropertyLoc, diag::err_bad_property_decl) << IDecl->getDeclName();
  993. return nullptr;
  994. }
  995. if (property->isClassProperty() && Synthesize) {
  996. Diag(PropertyLoc, diag::err_synthesize_on_class_property) << PropertyId;
  997. return nullptr;
  998. }
  999. unsigned PIkind = property->getPropertyAttributesAsWritten();
  1000. if ((PIkind & (ObjCPropertyAttribute::kind_atomic |
  1001. ObjCPropertyAttribute::kind_nonatomic)) == 0) {
  1002. if (AtLoc.isValid())
  1003. Diag(AtLoc, diag::warn_implicit_atomic_property);
  1004. else
  1005. Diag(IC->getLocation(), diag::warn_auto_implicit_atomic_property);
  1006. Diag(property->getLocation(), diag::note_property_declare);
  1007. }
  1008. if (const ObjCCategoryDecl *CD =
  1009. dyn_cast<ObjCCategoryDecl>(property->getDeclContext())) {
  1010. if (!CD->IsClassExtension()) {
  1011. Diag(PropertyLoc, diag::err_category_property) << CD->getDeclName();
  1012. Diag(property->getLocation(), diag::note_property_declare);
  1013. return nullptr;
  1014. }
  1015. }
  1016. if (Synthesize && (PIkind & ObjCPropertyAttribute::kind_readonly) &&
  1017. property->hasAttr<IBOutletAttr>() && !AtLoc.isValid()) {
  1018. bool ReadWriteProperty = false;
  1019. // Search into the class extensions and see if 'readonly property is
  1020. // redeclared 'readwrite', then no warning is to be issued.
  1021. for (auto *Ext : IDecl->known_extensions()) {
  1022. DeclContext::lookup_result R = Ext->lookup(property->getDeclName());
  1023. if (auto *ExtProp = R.find_first<ObjCPropertyDecl>()) {
  1024. PIkind = ExtProp->getPropertyAttributesAsWritten();
  1025. if (PIkind & ObjCPropertyAttribute::kind_readwrite) {
  1026. ReadWriteProperty = true;
  1027. break;
  1028. }
  1029. }
  1030. }
  1031. if (!ReadWriteProperty) {
  1032. Diag(property->getLocation(), diag::warn_auto_readonly_iboutlet_property)
  1033. << property;
  1034. SourceLocation readonlyLoc;
  1035. if (LocPropertyAttribute(Context, "readonly",
  1036. property->getLParenLoc(), readonlyLoc)) {
  1037. SourceLocation endLoc =
  1038. readonlyLoc.getLocWithOffset(strlen("readonly")-1);
  1039. SourceRange ReadonlySourceRange(readonlyLoc, endLoc);
  1040. Diag(property->getLocation(),
  1041. diag::note_auto_readonly_iboutlet_fixup_suggest) <<
  1042. FixItHint::CreateReplacement(ReadonlySourceRange, "readwrite");
  1043. }
  1044. }
  1045. }
  1046. if (Synthesize && isa<ObjCProtocolDecl>(property->getDeclContext()))
  1047. property = SelectPropertyForSynthesisFromProtocols(*this, AtLoc, IDecl,
  1048. property);
  1049. } else if ((CatImplClass = dyn_cast<ObjCCategoryImplDecl>(ClassImpDecl))) {
  1050. if (Synthesize) {
  1051. Diag(AtLoc, diag::err_synthesize_category_decl);
  1052. return nullptr;
  1053. }
  1054. IDecl = CatImplClass->getClassInterface();
  1055. if (!IDecl) {
  1056. Diag(AtLoc, diag::err_missing_property_interface);
  1057. return nullptr;
  1058. }
  1059. ObjCCategoryDecl *Category =
  1060. IDecl->FindCategoryDeclaration(CatImplClass->getIdentifier());
  1061. // If category for this implementation not found, it is an error which
  1062. // has already been reported eralier.
  1063. if (!Category)
  1064. return nullptr;
  1065. // Look for this property declaration in @implementation's category
  1066. property = Category->FindPropertyDeclaration(PropertyId, QueryKind);
  1067. if (!property) {
  1068. Diag(PropertyLoc, diag::err_bad_category_property_decl)
  1069. << Category->getDeclName();
  1070. return nullptr;
  1071. }
  1072. } else {
  1073. Diag(AtLoc, diag::err_bad_property_context);
  1074. return nullptr;
  1075. }
  1076. ObjCIvarDecl *Ivar = nullptr;
  1077. bool CompleteTypeErr = false;
  1078. bool compat = true;
  1079. // Check that we have a valid, previously declared ivar for @synthesize
  1080. if (Synthesize) {
  1081. // @synthesize
  1082. if (!PropertyIvar)
  1083. PropertyIvar = PropertyId;
  1084. // Check that this is a previously declared 'ivar' in 'IDecl' interface
  1085. ObjCInterfaceDecl *ClassDeclared;
  1086. Ivar = IDecl->lookupInstanceVariable(PropertyIvar, ClassDeclared);
  1087. QualType PropType = property->getType();
  1088. QualType PropertyIvarType = PropType.getNonReferenceType();
  1089. if (RequireCompleteType(PropertyDiagLoc, PropertyIvarType,
  1090. diag::err_incomplete_synthesized_property,
  1091. property->getDeclName())) {
  1092. Diag(property->getLocation(), diag::note_property_declare);
  1093. CompleteTypeErr = true;
  1094. }
  1095. if (getLangOpts().ObjCAutoRefCount &&
  1096. (property->getPropertyAttributesAsWritten() &
  1097. ObjCPropertyAttribute::kind_readonly) &&
  1098. PropertyIvarType->isObjCRetainableType()) {
  1099. setImpliedPropertyAttributeForReadOnlyProperty(property, Ivar);
  1100. }
  1101. ObjCPropertyAttribute::Kind kind = property->getPropertyAttributes();
  1102. bool isARCWeak = false;
  1103. if (kind & ObjCPropertyAttribute::kind_weak) {
  1104. // Add GC __weak to the ivar type if the property is weak.
  1105. if (getLangOpts().getGC() != LangOptions::NonGC) {
  1106. assert(!getLangOpts().ObjCAutoRefCount);
  1107. if (PropertyIvarType.isObjCGCStrong()) {
  1108. Diag(PropertyDiagLoc, diag::err_gc_weak_property_strong_type);
  1109. Diag(property->getLocation(), diag::note_property_declare);
  1110. } else {
  1111. PropertyIvarType =
  1112. Context.getObjCGCQualType(PropertyIvarType, Qualifiers::Weak);
  1113. }
  1114. // Otherwise, check whether ARC __weak is enabled and works with
  1115. // the property type.
  1116. } else {
  1117. if (!getLangOpts().ObjCWeak) {
  1118. // Only complain here when synthesizing an ivar.
  1119. if (!Ivar) {
  1120. Diag(PropertyDiagLoc,
  1121. getLangOpts().ObjCWeakRuntime
  1122. ? diag::err_synthesizing_arc_weak_property_disabled
  1123. : diag::err_synthesizing_arc_weak_property_no_runtime);
  1124. Diag(property->getLocation(), diag::note_property_declare);
  1125. }
  1126. CompleteTypeErr = true; // suppress later diagnostics about the ivar
  1127. } else {
  1128. isARCWeak = true;
  1129. if (const ObjCObjectPointerType *ObjT =
  1130. PropertyIvarType->getAs<ObjCObjectPointerType>()) {
  1131. const ObjCInterfaceDecl *ObjI = ObjT->getInterfaceDecl();
  1132. if (ObjI && ObjI->isArcWeakrefUnavailable()) {
  1133. Diag(property->getLocation(),
  1134. diag::err_arc_weak_unavailable_property)
  1135. << PropertyIvarType;
  1136. Diag(ClassImpDecl->getLocation(), diag::note_implemented_by_class)
  1137. << ClassImpDecl->getName();
  1138. }
  1139. }
  1140. }
  1141. }
  1142. }
  1143. if (AtLoc.isInvalid()) {
  1144. // Check when default synthesizing a property that there is
  1145. // an ivar matching property name and issue warning; since this
  1146. // is the most common case of not using an ivar used for backing
  1147. // property in non-default synthesis case.
  1148. ObjCInterfaceDecl *ClassDeclared=nullptr;
  1149. ObjCIvarDecl *originalIvar =
  1150. IDecl->lookupInstanceVariable(property->getIdentifier(),
  1151. ClassDeclared);
  1152. if (originalIvar) {
  1153. Diag(PropertyDiagLoc,
  1154. diag::warn_autosynthesis_property_ivar_match)
  1155. << PropertyId << (Ivar == nullptr) << PropertyIvar
  1156. << originalIvar->getIdentifier();
  1157. Diag(property->getLocation(), diag::note_property_declare);
  1158. Diag(originalIvar->getLocation(), diag::note_ivar_decl);
  1159. }
  1160. }
  1161. if (!Ivar) {
  1162. // In ARC, give the ivar a lifetime qualifier based on the
  1163. // property attributes.
  1164. if ((getLangOpts().ObjCAutoRefCount || isARCWeak) &&
  1165. !PropertyIvarType.getObjCLifetime() &&
  1166. PropertyIvarType->isObjCRetainableType()) {
  1167. // It's an error if we have to do this and the user didn't
  1168. // explicitly write an ownership attribute on the property.
  1169. if (!hasWrittenStorageAttribute(property, QueryKind) &&
  1170. !(kind & ObjCPropertyAttribute::kind_strong)) {
  1171. Diag(PropertyDiagLoc,
  1172. diag::err_arc_objc_property_default_assign_on_object);
  1173. Diag(property->getLocation(), diag::note_property_declare);
  1174. } else {
  1175. Qualifiers::ObjCLifetime lifetime =
  1176. getImpliedARCOwnership(kind, PropertyIvarType);
  1177. assert(lifetime && "no lifetime for property?");
  1178. Qualifiers qs;
  1179. qs.addObjCLifetime(lifetime);
  1180. PropertyIvarType = Context.getQualifiedType(PropertyIvarType, qs);
  1181. }
  1182. }
  1183. Ivar = ObjCIvarDecl::Create(Context, ClassImpDecl,
  1184. PropertyIvarLoc,PropertyIvarLoc, PropertyIvar,
  1185. PropertyIvarType, /*TInfo=*/nullptr,
  1186. ObjCIvarDecl::Private,
  1187. (Expr *)nullptr, true);
  1188. if (RequireNonAbstractType(PropertyIvarLoc,
  1189. PropertyIvarType,
  1190. diag::err_abstract_type_in_decl,
  1191. AbstractSynthesizedIvarType)) {
  1192. Diag(property->getLocation(), diag::note_property_declare);
  1193. // An abstract type is as bad as an incomplete type.
  1194. CompleteTypeErr = true;
  1195. }
  1196. if (!CompleteTypeErr) {
  1197. const RecordType *RecordTy = PropertyIvarType->getAs<RecordType>();
  1198. if (RecordTy && RecordTy->getDecl()->hasFlexibleArrayMember()) {
  1199. Diag(PropertyIvarLoc, diag::err_synthesize_variable_sized_ivar)
  1200. << PropertyIvarType;
  1201. CompleteTypeErr = true; // suppress later diagnostics about the ivar
  1202. }
  1203. }
  1204. if (CompleteTypeErr)
  1205. Ivar->setInvalidDecl();
  1206. ClassImpDecl->addDecl(Ivar);
  1207. IDecl->makeDeclVisibleInContext(Ivar);
  1208. if (getLangOpts().ObjCRuntime.isFragile())
  1209. Diag(PropertyDiagLoc, diag::err_missing_property_ivar_decl)
  1210. << PropertyId;
  1211. // Note! I deliberately want it to fall thru so, we have a
  1212. // a property implementation and to avoid future warnings.
  1213. } else if (getLangOpts().ObjCRuntime.isNonFragile() &&
  1214. !declaresSameEntity(ClassDeclared, IDecl)) {
  1215. Diag(PropertyDiagLoc, diag::err_ivar_in_superclass_use)
  1216. << property->getDeclName() << Ivar->getDeclName()
  1217. << ClassDeclared->getDeclName();
  1218. Diag(Ivar->getLocation(), diag::note_previous_access_declaration)
  1219. << Ivar << Ivar->getName();
  1220. // Note! I deliberately want it to fall thru so more errors are caught.
  1221. }
  1222. property->setPropertyIvarDecl(Ivar);
  1223. QualType IvarType = Context.getCanonicalType(Ivar->getType());
  1224. // Check that type of property and its ivar are type compatible.
  1225. if (!Context.hasSameType(PropertyIvarType, IvarType)) {
  1226. if (isa<ObjCObjectPointerType>(PropertyIvarType)
  1227. && isa<ObjCObjectPointerType>(IvarType))
  1228. compat =
  1229. Context.canAssignObjCInterfaces(
  1230. PropertyIvarType->getAs<ObjCObjectPointerType>(),
  1231. IvarType->getAs<ObjCObjectPointerType>());
  1232. else {
  1233. compat = (CheckAssignmentConstraints(PropertyIvarLoc, PropertyIvarType,
  1234. IvarType)
  1235. == Compatible);
  1236. }
  1237. if (!compat) {
  1238. Diag(PropertyDiagLoc, diag::err_property_ivar_type)
  1239. << property->getDeclName() << PropType
  1240. << Ivar->getDeclName() << IvarType;
  1241. Diag(Ivar->getLocation(), diag::note_ivar_decl);
  1242. // Note! I deliberately want it to fall thru so, we have a
  1243. // a property implementation and to avoid future warnings.
  1244. }
  1245. else {
  1246. // FIXME! Rules for properties are somewhat different that those
  1247. // for assignments. Use a new routine to consolidate all cases;
  1248. // specifically for property redeclarations as well as for ivars.
  1249. QualType lhsType =Context.getCanonicalType(PropertyIvarType).getUnqualifiedType();
  1250. QualType rhsType =Context.getCanonicalType(IvarType).getUnqualifiedType();
  1251. if (lhsType != rhsType &&
  1252. lhsType->isArithmeticType()) {
  1253. Diag(PropertyDiagLoc, diag::err_property_ivar_type)
  1254. << property->getDeclName() << PropType
  1255. << Ivar->getDeclName() << IvarType;
  1256. Diag(Ivar->getLocation(), diag::note_ivar_decl);
  1257. // Fall thru - see previous comment
  1258. }
  1259. }
  1260. // __weak is explicit. So it works on Canonical type.
  1261. if ((PropType.isObjCGCWeak() && !IvarType.isObjCGCWeak() &&
  1262. getLangOpts().getGC() != LangOptions::NonGC)) {
  1263. Diag(PropertyDiagLoc, diag::err_weak_property)
  1264. << property->getDeclName() << Ivar->getDeclName();
  1265. Diag(Ivar->getLocation(), diag::note_ivar_decl);
  1266. // Fall thru - see previous comment
  1267. }
  1268. // Fall thru - see previous comment
  1269. if ((property->getType()->isObjCObjectPointerType() ||
  1270. PropType.isObjCGCStrong()) && IvarType.isObjCGCWeak() &&
  1271. getLangOpts().getGC() != LangOptions::NonGC) {
  1272. Diag(PropertyDiagLoc, diag::err_strong_property)
  1273. << property->getDeclName() << Ivar->getDeclName();
  1274. // Fall thru - see previous comment
  1275. }
  1276. }
  1277. if (getLangOpts().ObjCAutoRefCount || isARCWeak ||
  1278. Ivar->getType().getObjCLifetime())
  1279. checkARCPropertyImpl(*this, PropertyLoc, property, Ivar);
  1280. } else if (PropertyIvar)
  1281. // @dynamic
  1282. Diag(PropertyDiagLoc, diag::err_dynamic_property_ivar_decl);
  1283. assert (property && "ActOnPropertyImplDecl - property declaration missing");
  1284. ObjCPropertyImplDecl *PIDecl =
  1285. ObjCPropertyImplDecl::Create(Context, CurContext, AtLoc, PropertyLoc,
  1286. property,
  1287. (Synthesize ?
  1288. ObjCPropertyImplDecl::Synthesize
  1289. : ObjCPropertyImplDecl::Dynamic),
  1290. Ivar, PropertyIvarLoc);
  1291. if (CompleteTypeErr || !compat)
  1292. PIDecl->setInvalidDecl();
  1293. if (ObjCMethodDecl *getterMethod = property->getGetterMethodDecl()) {
  1294. getterMethod->createImplicitParams(Context, IDecl);
  1295. // Redeclare the getter within the implementation as DeclContext.
  1296. if (Synthesize) {
  1297. // If the method hasn't been overridden, create a synthesized implementation.
  1298. ObjCMethodDecl *OMD = ClassImpDecl->getMethod(
  1299. getterMethod->getSelector(), getterMethod->isInstanceMethod());
  1300. if (!OMD)
  1301. OMD = RedeclarePropertyAccessor(Context, IC, getterMethod, AtLoc,
  1302. PropertyLoc);
  1303. PIDecl->setGetterMethodDecl(OMD);
  1304. }
  1305. if (getLangOpts().CPlusPlus && Synthesize && !CompleteTypeErr &&
  1306. Ivar->getType()->isRecordType()) {
  1307. // For Objective-C++, need to synthesize the AST for the IVAR object to be
  1308. // returned by the getter as it must conform to C++'s copy-return rules.
  1309. // FIXME. Eventually we want to do this for Objective-C as well.
  1310. SynthesizedFunctionScope Scope(*this, getterMethod);
  1311. ImplicitParamDecl *SelfDecl = getterMethod->getSelfDecl();
  1312. DeclRefExpr *SelfExpr = new (Context)
  1313. DeclRefExpr(Context, SelfDecl, false, SelfDecl->getType(), VK_LValue,
  1314. PropertyDiagLoc);
  1315. MarkDeclRefReferenced(SelfExpr);
  1316. Expr *LoadSelfExpr = ImplicitCastExpr::Create(
  1317. Context, SelfDecl->getType(), CK_LValueToRValue, SelfExpr, nullptr,
  1318. VK_PRValue, FPOptionsOverride());
  1319. Expr *IvarRefExpr =
  1320. new (Context) ObjCIvarRefExpr(Ivar,
  1321. Ivar->getUsageType(SelfDecl->getType()),
  1322. PropertyDiagLoc,
  1323. Ivar->getLocation(),
  1324. LoadSelfExpr, true, true);
  1325. ExprResult Res = PerformCopyInitialization(
  1326. InitializedEntity::InitializeResult(PropertyDiagLoc,
  1327. getterMethod->getReturnType()),
  1328. PropertyDiagLoc, IvarRefExpr);
  1329. if (!Res.isInvalid()) {
  1330. Expr *ResExpr = Res.getAs<Expr>();
  1331. if (ResExpr)
  1332. ResExpr = MaybeCreateExprWithCleanups(ResExpr);
  1333. PIDecl->setGetterCXXConstructor(ResExpr);
  1334. }
  1335. }
  1336. if (property->hasAttr<NSReturnsNotRetainedAttr>() &&
  1337. !getterMethod->hasAttr<NSReturnsNotRetainedAttr>()) {
  1338. Diag(getterMethod->getLocation(),
  1339. diag::warn_property_getter_owning_mismatch);
  1340. Diag(property->getLocation(), diag::note_property_declare);
  1341. }
  1342. if (getLangOpts().ObjCAutoRefCount && Synthesize)
  1343. switch (getterMethod->getMethodFamily()) {
  1344. case OMF_retain:
  1345. case OMF_retainCount:
  1346. case OMF_release:
  1347. case OMF_autorelease:
  1348. Diag(getterMethod->getLocation(), diag::err_arc_illegal_method_def)
  1349. << 1 << getterMethod->getSelector();
  1350. break;
  1351. default:
  1352. break;
  1353. }
  1354. }
  1355. if (ObjCMethodDecl *setterMethod = property->getSetterMethodDecl()) {
  1356. setterMethod->createImplicitParams(Context, IDecl);
  1357. // Redeclare the setter within the implementation as DeclContext.
  1358. if (Synthesize) {
  1359. ObjCMethodDecl *OMD = ClassImpDecl->getMethod(
  1360. setterMethod->getSelector(), setterMethod->isInstanceMethod());
  1361. if (!OMD)
  1362. OMD = RedeclarePropertyAccessor(Context, IC, setterMethod,
  1363. AtLoc, PropertyLoc);
  1364. PIDecl->setSetterMethodDecl(OMD);
  1365. }
  1366. if (getLangOpts().CPlusPlus && Synthesize && !CompleteTypeErr &&
  1367. Ivar->getType()->isRecordType()) {
  1368. // FIXME. Eventually we want to do this for Objective-C as well.
  1369. SynthesizedFunctionScope Scope(*this, setterMethod);
  1370. ImplicitParamDecl *SelfDecl = setterMethod->getSelfDecl();
  1371. DeclRefExpr *SelfExpr = new (Context)
  1372. DeclRefExpr(Context, SelfDecl, false, SelfDecl->getType(), VK_LValue,
  1373. PropertyDiagLoc);
  1374. MarkDeclRefReferenced(SelfExpr);
  1375. Expr *LoadSelfExpr = ImplicitCastExpr::Create(
  1376. Context, SelfDecl->getType(), CK_LValueToRValue, SelfExpr, nullptr,
  1377. VK_PRValue, FPOptionsOverride());
  1378. Expr *lhs =
  1379. new (Context) ObjCIvarRefExpr(Ivar,
  1380. Ivar->getUsageType(SelfDecl->getType()),
  1381. PropertyDiagLoc,
  1382. Ivar->getLocation(),
  1383. LoadSelfExpr, true, true);
  1384. ObjCMethodDecl::param_iterator P = setterMethod->param_begin();
  1385. ParmVarDecl *Param = (*P);
  1386. QualType T = Param->getType().getNonReferenceType();
  1387. DeclRefExpr *rhs = new (Context)
  1388. DeclRefExpr(Context, Param, false, T, VK_LValue, PropertyDiagLoc);
  1389. MarkDeclRefReferenced(rhs);
  1390. ExprResult Res = BuildBinOp(S, PropertyDiagLoc,
  1391. BO_Assign, lhs, rhs);
  1392. if (property->getPropertyAttributes() &
  1393. ObjCPropertyAttribute::kind_atomic) {
  1394. Expr *callExpr = Res.getAs<Expr>();
  1395. if (const CXXOperatorCallExpr *CXXCE =
  1396. dyn_cast_or_null<CXXOperatorCallExpr>(callExpr))
  1397. if (const FunctionDecl *FuncDecl = CXXCE->getDirectCallee())
  1398. if (!FuncDecl->isTrivial())
  1399. if (property->getType()->isReferenceType()) {
  1400. Diag(PropertyDiagLoc,
  1401. diag::err_atomic_property_nontrivial_assign_op)
  1402. << property->getType();
  1403. Diag(FuncDecl->getBeginLoc(), diag::note_callee_decl)
  1404. << FuncDecl;
  1405. }
  1406. }
  1407. PIDecl->setSetterCXXAssignment(Res.getAs<Expr>());
  1408. }
  1409. }
  1410. if (IC) {
  1411. if (Synthesize)
  1412. if (ObjCPropertyImplDecl *PPIDecl =
  1413. IC->FindPropertyImplIvarDecl(PropertyIvar)) {
  1414. Diag(PropertyLoc, diag::err_duplicate_ivar_use)
  1415. << PropertyId << PPIDecl->getPropertyDecl()->getIdentifier()
  1416. << PropertyIvar;
  1417. Diag(PPIDecl->getLocation(), diag::note_previous_use);
  1418. }
  1419. if (ObjCPropertyImplDecl *PPIDecl
  1420. = IC->FindPropertyImplDecl(PropertyId, QueryKind)) {
  1421. Diag(PropertyLoc, diag::err_property_implemented) << PropertyId;
  1422. Diag(PPIDecl->getLocation(), diag::note_previous_declaration);
  1423. return nullptr;
  1424. }
  1425. IC->addPropertyImplementation(PIDecl);
  1426. if (getLangOpts().ObjCDefaultSynthProperties &&
  1427. getLangOpts().ObjCRuntime.isNonFragile() &&
  1428. !IDecl->isObjCRequiresPropertyDefs()) {
  1429. // Diagnose if an ivar was lazily synthesdized due to a previous
  1430. // use and if 1) property is @dynamic or 2) property is synthesized
  1431. // but it requires an ivar of different name.
  1432. ObjCInterfaceDecl *ClassDeclared=nullptr;
  1433. ObjCIvarDecl *Ivar = nullptr;
  1434. if (!Synthesize)
  1435. Ivar = IDecl->lookupInstanceVariable(PropertyId, ClassDeclared);
  1436. else {
  1437. if (PropertyIvar && PropertyIvar != PropertyId)
  1438. Ivar = IDecl->lookupInstanceVariable(PropertyId, ClassDeclared);
  1439. }
  1440. // Issue diagnostics only if Ivar belongs to current class.
  1441. if (Ivar && Ivar->getSynthesize() &&
  1442. declaresSameEntity(IC->getClassInterface(), ClassDeclared)) {
  1443. Diag(Ivar->getLocation(), diag::err_undeclared_var_use)
  1444. << PropertyId;
  1445. Ivar->setInvalidDecl();
  1446. }
  1447. }
  1448. } else {
  1449. if (Synthesize)
  1450. if (ObjCPropertyImplDecl *PPIDecl =
  1451. CatImplClass->FindPropertyImplIvarDecl(PropertyIvar)) {
  1452. Diag(PropertyDiagLoc, diag::err_duplicate_ivar_use)
  1453. << PropertyId << PPIDecl->getPropertyDecl()->getIdentifier()
  1454. << PropertyIvar;
  1455. Diag(PPIDecl->getLocation(), diag::note_previous_use);
  1456. }
  1457. if (ObjCPropertyImplDecl *PPIDecl =
  1458. CatImplClass->FindPropertyImplDecl(PropertyId, QueryKind)) {
  1459. Diag(PropertyDiagLoc, diag::err_property_implemented) << PropertyId;
  1460. Diag(PPIDecl->getLocation(), diag::note_previous_declaration);
  1461. return nullptr;
  1462. }
  1463. CatImplClass->addPropertyImplementation(PIDecl);
  1464. }
  1465. if (PIDecl->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic &&
  1466. PIDecl->getPropertyDecl() &&
  1467. PIDecl->getPropertyDecl()->isDirectProperty()) {
  1468. Diag(PropertyLoc, diag::err_objc_direct_dynamic_property);
  1469. Diag(PIDecl->getPropertyDecl()->getLocation(),
  1470. diag::note_previous_declaration);
  1471. return nullptr;
  1472. }
  1473. return PIDecl;
  1474. }
  1475. //===----------------------------------------------------------------------===//
  1476. // Helper methods.
  1477. //===----------------------------------------------------------------------===//
  1478. /// DiagnosePropertyMismatch - Compares two properties for their
  1479. /// attributes and types and warns on a variety of inconsistencies.
  1480. ///
  1481. void
  1482. Sema::DiagnosePropertyMismatch(ObjCPropertyDecl *Property,
  1483. ObjCPropertyDecl *SuperProperty,
  1484. const IdentifierInfo *inheritedName,
  1485. bool OverridingProtocolProperty) {
  1486. ObjCPropertyAttribute::Kind CAttr = Property->getPropertyAttributes();
  1487. ObjCPropertyAttribute::Kind SAttr = SuperProperty->getPropertyAttributes();
  1488. // We allow readonly properties without an explicit ownership
  1489. // (assign/unsafe_unretained/weak/retain/strong/copy) in super class
  1490. // to be overridden by a property with any explicit ownership in the subclass.
  1491. if (!OverridingProtocolProperty &&
  1492. !getOwnershipRule(SAttr) && getOwnershipRule(CAttr))
  1493. ;
  1494. else {
  1495. if ((CAttr & ObjCPropertyAttribute::kind_readonly) &&
  1496. (SAttr & ObjCPropertyAttribute::kind_readwrite))
  1497. Diag(Property->getLocation(), diag::warn_readonly_property)
  1498. << Property->getDeclName() << inheritedName;
  1499. if ((CAttr & ObjCPropertyAttribute::kind_copy) !=
  1500. (SAttr & ObjCPropertyAttribute::kind_copy))
  1501. Diag(Property->getLocation(), diag::warn_property_attribute)
  1502. << Property->getDeclName() << "copy" << inheritedName;
  1503. else if (!(SAttr & ObjCPropertyAttribute::kind_readonly)) {
  1504. unsigned CAttrRetain = (CAttr & (ObjCPropertyAttribute::kind_retain |
  1505. ObjCPropertyAttribute::kind_strong));
  1506. unsigned SAttrRetain = (SAttr & (ObjCPropertyAttribute::kind_retain |
  1507. ObjCPropertyAttribute::kind_strong));
  1508. bool CStrong = (CAttrRetain != 0);
  1509. bool SStrong = (SAttrRetain != 0);
  1510. if (CStrong != SStrong)
  1511. Diag(Property->getLocation(), diag::warn_property_attribute)
  1512. << Property->getDeclName() << "retain (or strong)" << inheritedName;
  1513. }
  1514. }
  1515. // Check for nonatomic; note that nonatomic is effectively
  1516. // meaningless for readonly properties, so don't diagnose if the
  1517. // atomic property is 'readonly'.
  1518. checkAtomicPropertyMismatch(*this, SuperProperty, Property, false);
  1519. // Readonly properties from protocols can be implemented as "readwrite"
  1520. // with a custom setter name.
  1521. if (Property->getSetterName() != SuperProperty->getSetterName() &&
  1522. !(SuperProperty->isReadOnly() &&
  1523. isa<ObjCProtocolDecl>(SuperProperty->getDeclContext()))) {
  1524. Diag(Property->getLocation(), diag::warn_property_attribute)
  1525. << Property->getDeclName() << "setter" << inheritedName;
  1526. Diag(SuperProperty->getLocation(), diag::note_property_declare);
  1527. }
  1528. if (Property->getGetterName() != SuperProperty->getGetterName()) {
  1529. Diag(Property->getLocation(), diag::warn_property_attribute)
  1530. << Property->getDeclName() << "getter" << inheritedName;
  1531. Diag(SuperProperty->getLocation(), diag::note_property_declare);
  1532. }
  1533. QualType LHSType =
  1534. Context.getCanonicalType(SuperProperty->getType());
  1535. QualType RHSType =
  1536. Context.getCanonicalType(Property->getType());
  1537. if (!Context.propertyTypesAreCompatible(LHSType, RHSType)) {
  1538. // Do cases not handled in above.
  1539. // FIXME. For future support of covariant property types, revisit this.
  1540. bool IncompatibleObjC = false;
  1541. QualType ConvertedType;
  1542. if (!isObjCPointerConversion(RHSType, LHSType,
  1543. ConvertedType, IncompatibleObjC) ||
  1544. IncompatibleObjC) {
  1545. Diag(Property->getLocation(), diag::warn_property_types_are_incompatible)
  1546. << Property->getType() << SuperProperty->getType() << inheritedName;
  1547. Diag(SuperProperty->getLocation(), diag::note_property_declare);
  1548. }
  1549. }
  1550. }
  1551. bool Sema::DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *property,
  1552. ObjCMethodDecl *GetterMethod,
  1553. SourceLocation Loc) {
  1554. if (!GetterMethod)
  1555. return false;
  1556. QualType GetterType = GetterMethod->getReturnType().getNonReferenceType();
  1557. QualType PropertyRValueType =
  1558. property->getType().getNonReferenceType().getAtomicUnqualifiedType();
  1559. bool compat = Context.hasSameType(PropertyRValueType, GetterType);
  1560. if (!compat) {
  1561. const ObjCObjectPointerType *propertyObjCPtr = nullptr;
  1562. const ObjCObjectPointerType *getterObjCPtr = nullptr;
  1563. if ((propertyObjCPtr =
  1564. PropertyRValueType->getAs<ObjCObjectPointerType>()) &&
  1565. (getterObjCPtr = GetterType->getAs<ObjCObjectPointerType>()))
  1566. compat = Context.canAssignObjCInterfaces(getterObjCPtr, propertyObjCPtr);
  1567. else if (CheckAssignmentConstraints(Loc, GetterType, PropertyRValueType)
  1568. != Compatible) {
  1569. Diag(Loc, diag::err_property_accessor_type)
  1570. << property->getDeclName() << PropertyRValueType
  1571. << GetterMethod->getSelector() << GetterType;
  1572. Diag(GetterMethod->getLocation(), diag::note_declared_at);
  1573. return true;
  1574. } else {
  1575. compat = true;
  1576. QualType lhsType = Context.getCanonicalType(PropertyRValueType);
  1577. QualType rhsType =Context.getCanonicalType(GetterType).getUnqualifiedType();
  1578. if (lhsType != rhsType && lhsType->isArithmeticType())
  1579. compat = false;
  1580. }
  1581. }
  1582. if (!compat) {
  1583. Diag(Loc, diag::warn_accessor_property_type_mismatch)
  1584. << property->getDeclName()
  1585. << GetterMethod->getSelector();
  1586. Diag(GetterMethod->getLocation(), diag::note_declared_at);
  1587. return true;
  1588. }
  1589. return false;
  1590. }
  1591. /// CollectImmediateProperties - This routine collects all properties in
  1592. /// the class and its conforming protocols; but not those in its super class.
  1593. static void
  1594. CollectImmediateProperties(ObjCContainerDecl *CDecl,
  1595. ObjCContainerDecl::PropertyMap &PropMap,
  1596. ObjCContainerDecl::PropertyMap &SuperPropMap,
  1597. bool CollectClassPropsOnly = false,
  1598. bool IncludeProtocols = true) {
  1599. if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl)) {
  1600. for (auto *Prop : IDecl->properties()) {
  1601. if (CollectClassPropsOnly && !Prop->isClassProperty())
  1602. continue;
  1603. PropMap[std::make_pair(Prop->getIdentifier(), Prop->isClassProperty())] =
  1604. Prop;
  1605. }
  1606. // Collect the properties from visible extensions.
  1607. for (auto *Ext : IDecl->visible_extensions())
  1608. CollectImmediateProperties(Ext, PropMap, SuperPropMap,
  1609. CollectClassPropsOnly, IncludeProtocols);
  1610. if (IncludeProtocols) {
  1611. // Scan through class's protocols.
  1612. for (auto *PI : IDecl->all_referenced_protocols())
  1613. CollectImmediateProperties(PI, PropMap, SuperPropMap,
  1614. CollectClassPropsOnly);
  1615. }
  1616. }
  1617. if (ObjCCategoryDecl *CATDecl = dyn_cast<ObjCCategoryDecl>(CDecl)) {
  1618. for (auto *Prop : CATDecl->properties()) {
  1619. if (CollectClassPropsOnly && !Prop->isClassProperty())
  1620. continue;
  1621. PropMap[std::make_pair(Prop->getIdentifier(), Prop->isClassProperty())] =
  1622. Prop;
  1623. }
  1624. if (IncludeProtocols) {
  1625. // Scan through class's protocols.
  1626. for (auto *PI : CATDecl->protocols())
  1627. CollectImmediateProperties(PI, PropMap, SuperPropMap,
  1628. CollectClassPropsOnly);
  1629. }
  1630. }
  1631. else if (ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(CDecl)) {
  1632. for (auto *Prop : PDecl->properties()) {
  1633. if (CollectClassPropsOnly && !Prop->isClassProperty())
  1634. continue;
  1635. ObjCPropertyDecl *PropertyFromSuper =
  1636. SuperPropMap[std::make_pair(Prop->getIdentifier(),
  1637. Prop->isClassProperty())];
  1638. // Exclude property for protocols which conform to class's super-class,
  1639. // as super-class has to implement the property.
  1640. if (!PropertyFromSuper ||
  1641. PropertyFromSuper->getIdentifier() != Prop->getIdentifier()) {
  1642. ObjCPropertyDecl *&PropEntry =
  1643. PropMap[std::make_pair(Prop->getIdentifier(),
  1644. Prop->isClassProperty())];
  1645. if (!PropEntry)
  1646. PropEntry = Prop;
  1647. }
  1648. }
  1649. // Scan through protocol's protocols.
  1650. for (auto *PI : PDecl->protocols())
  1651. CollectImmediateProperties(PI, PropMap, SuperPropMap,
  1652. CollectClassPropsOnly);
  1653. }
  1654. }
  1655. /// CollectSuperClassPropertyImplementations - This routine collects list of
  1656. /// properties to be implemented in super class(s) and also coming from their
  1657. /// conforming protocols.
  1658. static void CollectSuperClassPropertyImplementations(ObjCInterfaceDecl *CDecl,
  1659. ObjCInterfaceDecl::PropertyMap &PropMap) {
  1660. if (ObjCInterfaceDecl *SDecl = CDecl->getSuperClass()) {
  1661. while (SDecl) {
  1662. SDecl->collectPropertiesToImplement(PropMap);
  1663. SDecl = SDecl->getSuperClass();
  1664. }
  1665. }
  1666. }
  1667. /// IvarBacksCurrentMethodAccessor - This routine returns 'true' if 'IV' is
  1668. /// an ivar synthesized for 'Method' and 'Method' is a property accessor
  1669. /// declared in class 'IFace'.
  1670. bool
  1671. Sema::IvarBacksCurrentMethodAccessor(ObjCInterfaceDecl *IFace,
  1672. ObjCMethodDecl *Method, ObjCIvarDecl *IV) {
  1673. if (!IV->getSynthesize())
  1674. return false;
  1675. ObjCMethodDecl *IMD = IFace->lookupMethod(Method->getSelector(),
  1676. Method->isInstanceMethod());
  1677. if (!IMD || !IMD->isPropertyAccessor())
  1678. return false;
  1679. // look up a property declaration whose one of its accessors is implemented
  1680. // by this method.
  1681. for (const auto *Property : IFace->instance_properties()) {
  1682. if ((Property->getGetterName() == IMD->getSelector() ||
  1683. Property->getSetterName() == IMD->getSelector()) &&
  1684. (Property->getPropertyIvarDecl() == IV))
  1685. return true;
  1686. }
  1687. // Also look up property declaration in class extension whose one of its
  1688. // accessors is implemented by this method.
  1689. for (const auto *Ext : IFace->known_extensions())
  1690. for (const auto *Property : Ext->instance_properties())
  1691. if ((Property->getGetterName() == IMD->getSelector() ||
  1692. Property->getSetterName() == IMD->getSelector()) &&
  1693. (Property->getPropertyIvarDecl() == IV))
  1694. return true;
  1695. return false;
  1696. }
  1697. static bool SuperClassImplementsProperty(ObjCInterfaceDecl *IDecl,
  1698. ObjCPropertyDecl *Prop) {
  1699. bool SuperClassImplementsGetter = false;
  1700. bool SuperClassImplementsSetter = false;
  1701. if (Prop->getPropertyAttributes() & ObjCPropertyAttribute::kind_readonly)
  1702. SuperClassImplementsSetter = true;
  1703. while (IDecl->getSuperClass()) {
  1704. ObjCInterfaceDecl *SDecl = IDecl->getSuperClass();
  1705. if (!SuperClassImplementsGetter && SDecl->getInstanceMethod(Prop->getGetterName()))
  1706. SuperClassImplementsGetter = true;
  1707. if (!SuperClassImplementsSetter && SDecl->getInstanceMethod(Prop->getSetterName()))
  1708. SuperClassImplementsSetter = true;
  1709. if (SuperClassImplementsGetter && SuperClassImplementsSetter)
  1710. return true;
  1711. IDecl = IDecl->getSuperClass();
  1712. }
  1713. return false;
  1714. }
  1715. /// Default synthesizes all properties which must be synthesized
  1716. /// in class's \@implementation.
  1717. void Sema::DefaultSynthesizeProperties(Scope *S, ObjCImplDecl *IMPDecl,
  1718. ObjCInterfaceDecl *IDecl,
  1719. SourceLocation AtEnd) {
  1720. ObjCInterfaceDecl::PropertyMap PropMap;
  1721. IDecl->collectPropertiesToImplement(PropMap);
  1722. if (PropMap.empty())
  1723. return;
  1724. ObjCInterfaceDecl::PropertyMap SuperPropMap;
  1725. CollectSuperClassPropertyImplementations(IDecl, SuperPropMap);
  1726. for (const auto &PropEntry : PropMap) {
  1727. ObjCPropertyDecl *Prop = PropEntry.second;
  1728. // Is there a matching property synthesize/dynamic?
  1729. if (Prop->isInvalidDecl() ||
  1730. Prop->isClassProperty() ||
  1731. Prop->getPropertyImplementation() == ObjCPropertyDecl::Optional)
  1732. continue;
  1733. // Property may have been synthesized by user.
  1734. if (IMPDecl->FindPropertyImplDecl(
  1735. Prop->getIdentifier(), Prop->getQueryKind()))
  1736. continue;
  1737. ObjCMethodDecl *ImpMethod = IMPDecl->getInstanceMethod(Prop->getGetterName());
  1738. if (ImpMethod && !ImpMethod->getBody()) {
  1739. if (Prop->getPropertyAttributes() & ObjCPropertyAttribute::kind_readonly)
  1740. continue;
  1741. ImpMethod = IMPDecl->getInstanceMethod(Prop->getSetterName());
  1742. if (ImpMethod && !ImpMethod->getBody())
  1743. continue;
  1744. }
  1745. if (ObjCPropertyImplDecl *PID =
  1746. IMPDecl->FindPropertyImplIvarDecl(Prop->getIdentifier())) {
  1747. Diag(Prop->getLocation(), diag::warn_no_autosynthesis_shared_ivar_property)
  1748. << Prop->getIdentifier();
  1749. if (PID->getLocation().isValid())
  1750. Diag(PID->getLocation(), diag::note_property_synthesize);
  1751. continue;
  1752. }
  1753. ObjCPropertyDecl *PropInSuperClass =
  1754. SuperPropMap[std::make_pair(Prop->getIdentifier(),
  1755. Prop->isClassProperty())];
  1756. if (ObjCProtocolDecl *Proto =
  1757. dyn_cast<ObjCProtocolDecl>(Prop->getDeclContext())) {
  1758. // We won't auto-synthesize properties declared in protocols.
  1759. // Suppress the warning if class's superclass implements property's
  1760. // getter and implements property's setter (if readwrite property).
  1761. // Or, if property is going to be implemented in its super class.
  1762. if (!SuperClassImplementsProperty(IDecl, Prop) && !PropInSuperClass) {
  1763. Diag(IMPDecl->getLocation(),
  1764. diag::warn_auto_synthesizing_protocol_property)
  1765. << Prop << Proto;
  1766. Diag(Prop->getLocation(), diag::note_property_declare);
  1767. std::string FixIt =
  1768. (Twine("@synthesize ") + Prop->getName() + ";\n\n").str();
  1769. Diag(AtEnd, diag::note_add_synthesize_directive)
  1770. << FixItHint::CreateInsertion(AtEnd, FixIt);
  1771. }
  1772. continue;
  1773. }
  1774. // If property to be implemented in the super class, ignore.
  1775. if (PropInSuperClass) {
  1776. if ((Prop->getPropertyAttributes() &
  1777. ObjCPropertyAttribute::kind_readwrite) &&
  1778. (PropInSuperClass->getPropertyAttributes() &
  1779. ObjCPropertyAttribute::kind_readonly) &&
  1780. !IMPDecl->getInstanceMethod(Prop->getSetterName()) &&
  1781. !IDecl->HasUserDeclaredSetterMethod(Prop)) {
  1782. Diag(Prop->getLocation(), diag::warn_no_autosynthesis_property)
  1783. << Prop->getIdentifier();
  1784. Diag(PropInSuperClass->getLocation(), diag::note_property_declare);
  1785. } else {
  1786. Diag(Prop->getLocation(), diag::warn_autosynthesis_property_in_superclass)
  1787. << Prop->getIdentifier();
  1788. Diag(PropInSuperClass->getLocation(), diag::note_property_declare);
  1789. Diag(IMPDecl->getLocation(), diag::note_while_in_implementation);
  1790. }
  1791. continue;
  1792. }
  1793. // We use invalid SourceLocations for the synthesized ivars since they
  1794. // aren't really synthesized at a particular location; they just exist.
  1795. // Saying that they are located at the @implementation isn't really going
  1796. // to help users.
  1797. ObjCPropertyImplDecl *PIDecl = dyn_cast_or_null<ObjCPropertyImplDecl>(
  1798. ActOnPropertyImplDecl(S, SourceLocation(), SourceLocation(),
  1799. true,
  1800. /* property = */ Prop->getIdentifier(),
  1801. /* ivar = */ Prop->getDefaultSynthIvarName(Context),
  1802. Prop->getLocation(), Prop->getQueryKind()));
  1803. if (PIDecl && !Prop->isUnavailable()) {
  1804. Diag(Prop->getLocation(), diag::warn_missing_explicit_synthesis);
  1805. Diag(IMPDecl->getLocation(), diag::note_while_in_implementation);
  1806. }
  1807. }
  1808. }
  1809. void Sema::DefaultSynthesizeProperties(Scope *S, Decl *D,
  1810. SourceLocation AtEnd) {
  1811. if (!LangOpts.ObjCDefaultSynthProperties || LangOpts.ObjCRuntime.isFragile())
  1812. return;
  1813. ObjCImplementationDecl *IC=dyn_cast_or_null<ObjCImplementationDecl>(D);
  1814. if (!IC)
  1815. return;
  1816. if (ObjCInterfaceDecl* IDecl = IC->getClassInterface())
  1817. if (!IDecl->isObjCRequiresPropertyDefs())
  1818. DefaultSynthesizeProperties(S, IC, IDecl, AtEnd);
  1819. }
  1820. static void DiagnoseUnimplementedAccessor(
  1821. Sema &S, ObjCInterfaceDecl *PrimaryClass, Selector Method,
  1822. ObjCImplDecl *IMPDecl, ObjCContainerDecl *CDecl, ObjCCategoryDecl *C,
  1823. ObjCPropertyDecl *Prop,
  1824. llvm::SmallPtrSet<const ObjCMethodDecl *, 8> &SMap) {
  1825. // Check to see if we have a corresponding selector in SMap and with the
  1826. // right method type.
  1827. auto I = llvm::find_if(SMap, [&](const ObjCMethodDecl *x) {
  1828. return x->getSelector() == Method &&
  1829. x->isClassMethod() == Prop->isClassProperty();
  1830. });
  1831. // When reporting on missing property setter/getter implementation in
  1832. // categories, do not report when they are declared in primary class,
  1833. // class's protocol, or one of it super classes. This is because,
  1834. // the class is going to implement them.
  1835. if (I == SMap.end() &&
  1836. (PrimaryClass == nullptr ||
  1837. !PrimaryClass->lookupPropertyAccessor(Method, C,
  1838. Prop->isClassProperty()))) {
  1839. unsigned diag =
  1840. isa<ObjCCategoryDecl>(CDecl)
  1841. ? (Prop->isClassProperty()
  1842. ? diag::warn_impl_required_in_category_for_class_property
  1843. : diag::warn_setter_getter_impl_required_in_category)
  1844. : (Prop->isClassProperty()
  1845. ? diag::warn_impl_required_for_class_property
  1846. : diag::warn_setter_getter_impl_required);
  1847. S.Diag(IMPDecl->getLocation(), diag) << Prop->getDeclName() << Method;
  1848. S.Diag(Prop->getLocation(), diag::note_property_declare);
  1849. if (S.LangOpts.ObjCDefaultSynthProperties &&
  1850. S.LangOpts.ObjCRuntime.isNonFragile())
  1851. if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(CDecl))
  1852. if (const ObjCInterfaceDecl *RID = ID->isObjCRequiresPropertyDefs())
  1853. S.Diag(RID->getLocation(), diag::note_suppressed_class_declare);
  1854. }
  1855. }
  1856. void Sema::DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl,
  1857. ObjCContainerDecl *CDecl,
  1858. bool SynthesizeProperties) {
  1859. ObjCContainerDecl::PropertyMap PropMap;
  1860. ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl);
  1861. // Since we don't synthesize class properties, we should emit diagnose even
  1862. // if SynthesizeProperties is true.
  1863. ObjCContainerDecl::PropertyMap NoNeedToImplPropMap;
  1864. // Gather properties which need not be implemented in this class
  1865. // or category.
  1866. if (!IDecl)
  1867. if (ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl)) {
  1868. // For categories, no need to implement properties declared in
  1869. // its primary class (and its super classes) if property is
  1870. // declared in one of those containers.
  1871. if ((IDecl = C->getClassInterface())) {
  1872. IDecl->collectPropertiesToImplement(NoNeedToImplPropMap);
  1873. }
  1874. }
  1875. if (IDecl)
  1876. CollectSuperClassPropertyImplementations(IDecl, NoNeedToImplPropMap);
  1877. // When SynthesizeProperties is true, we only check class properties.
  1878. CollectImmediateProperties(CDecl, PropMap, NoNeedToImplPropMap,
  1879. SynthesizeProperties/*CollectClassPropsOnly*/);
  1880. // Scan the @interface to see if any of the protocols it adopts
  1881. // require an explicit implementation, via attribute
  1882. // 'objc_protocol_requires_explicit_implementation'.
  1883. if (IDecl) {
  1884. std::unique_ptr<ObjCContainerDecl::PropertyMap> LazyMap;
  1885. for (auto *PDecl : IDecl->all_referenced_protocols()) {
  1886. if (!PDecl->hasAttr<ObjCExplicitProtocolImplAttr>())
  1887. continue;
  1888. // Lazily construct a set of all the properties in the @interface
  1889. // of the class, without looking at the superclass. We cannot
  1890. // use the call to CollectImmediateProperties() above as that
  1891. // utilizes information from the super class's properties as well
  1892. // as scans the adopted protocols. This work only triggers for protocols
  1893. // with the attribute, which is very rare, and only occurs when
  1894. // analyzing the @implementation.
  1895. if (!LazyMap) {
  1896. ObjCContainerDecl::PropertyMap NoNeedToImplPropMap;
  1897. LazyMap.reset(new ObjCContainerDecl::PropertyMap());
  1898. CollectImmediateProperties(CDecl, *LazyMap, NoNeedToImplPropMap,
  1899. /* CollectClassPropsOnly */ false,
  1900. /* IncludeProtocols */ false);
  1901. }
  1902. // Add the properties of 'PDecl' to the list of properties that
  1903. // need to be implemented.
  1904. for (auto *PropDecl : PDecl->properties()) {
  1905. if ((*LazyMap)[std::make_pair(PropDecl->getIdentifier(),
  1906. PropDecl->isClassProperty())])
  1907. continue;
  1908. PropMap[std::make_pair(PropDecl->getIdentifier(),
  1909. PropDecl->isClassProperty())] = PropDecl;
  1910. }
  1911. }
  1912. }
  1913. if (PropMap.empty())
  1914. return;
  1915. llvm::DenseSet<ObjCPropertyDecl *> PropImplMap;
  1916. for (const auto *I : IMPDecl->property_impls())
  1917. PropImplMap.insert(I->getPropertyDecl());
  1918. llvm::SmallPtrSet<const ObjCMethodDecl *, 8> InsMap;
  1919. // Collect property accessors implemented in current implementation.
  1920. for (const auto *I : IMPDecl->methods())
  1921. InsMap.insert(I);
  1922. ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl);
  1923. ObjCInterfaceDecl *PrimaryClass = nullptr;
  1924. if (C && !C->IsClassExtension())
  1925. if ((PrimaryClass = C->getClassInterface()))
  1926. // Report unimplemented properties in the category as well.
  1927. if (ObjCImplDecl *IMP = PrimaryClass->getImplementation()) {
  1928. // When reporting on missing setter/getters, do not report when
  1929. // setter/getter is implemented in category's primary class
  1930. // implementation.
  1931. for (const auto *I : IMP->methods())
  1932. InsMap.insert(I);
  1933. }
  1934. for (ObjCContainerDecl::PropertyMap::iterator
  1935. P = PropMap.begin(), E = PropMap.end(); P != E; ++P) {
  1936. ObjCPropertyDecl *Prop = P->second;
  1937. // Is there a matching property synthesize/dynamic?
  1938. if (Prop->isInvalidDecl() ||
  1939. Prop->getPropertyImplementation() == ObjCPropertyDecl::Optional ||
  1940. PropImplMap.count(Prop) ||
  1941. Prop->getAvailability() == AR_Unavailable)
  1942. continue;
  1943. // Diagnose unimplemented getters and setters.
  1944. DiagnoseUnimplementedAccessor(*this,
  1945. PrimaryClass, Prop->getGetterName(), IMPDecl, CDecl, C, Prop, InsMap);
  1946. if (!Prop->isReadOnly())
  1947. DiagnoseUnimplementedAccessor(*this,
  1948. PrimaryClass, Prop->getSetterName(),
  1949. IMPDecl, CDecl, C, Prop, InsMap);
  1950. }
  1951. }
  1952. void Sema::diagnoseNullResettableSynthesizedSetters(const ObjCImplDecl *impDecl) {
  1953. for (const auto *propertyImpl : impDecl->property_impls()) {
  1954. const auto *property = propertyImpl->getPropertyDecl();
  1955. // Warn about null_resettable properties with synthesized setters,
  1956. // because the setter won't properly handle nil.
  1957. if (propertyImpl->getPropertyImplementation() ==
  1958. ObjCPropertyImplDecl::Synthesize &&
  1959. (property->getPropertyAttributes() &
  1960. ObjCPropertyAttribute::kind_null_resettable) &&
  1961. property->getGetterMethodDecl() && property->getSetterMethodDecl()) {
  1962. auto *getterImpl = propertyImpl->getGetterMethodDecl();
  1963. auto *setterImpl = propertyImpl->getSetterMethodDecl();
  1964. if ((!getterImpl || getterImpl->isSynthesizedAccessorStub()) &&
  1965. (!setterImpl || setterImpl->isSynthesizedAccessorStub())) {
  1966. SourceLocation loc = propertyImpl->getLocation();
  1967. if (loc.isInvalid())
  1968. loc = impDecl->getBeginLoc();
  1969. Diag(loc, diag::warn_null_resettable_setter)
  1970. << setterImpl->getSelector() << property->getDeclName();
  1971. }
  1972. }
  1973. }
  1974. }
  1975. void
  1976. Sema::AtomicPropertySetterGetterRules (ObjCImplDecl* IMPDecl,
  1977. ObjCInterfaceDecl* IDecl) {
  1978. // Rules apply in non-GC mode only
  1979. if (getLangOpts().getGC() != LangOptions::NonGC)
  1980. return;
  1981. ObjCContainerDecl::PropertyMap PM;
  1982. for (auto *Prop : IDecl->properties())
  1983. PM[std::make_pair(Prop->getIdentifier(), Prop->isClassProperty())] = Prop;
  1984. for (const auto *Ext : IDecl->known_extensions())
  1985. for (auto *Prop : Ext->properties())
  1986. PM[std::make_pair(Prop->getIdentifier(), Prop->isClassProperty())] = Prop;
  1987. for (ObjCContainerDecl::PropertyMap::iterator I = PM.begin(), E = PM.end();
  1988. I != E; ++I) {
  1989. const ObjCPropertyDecl *Property = I->second;
  1990. ObjCMethodDecl *GetterMethod = nullptr;
  1991. ObjCMethodDecl *SetterMethod = nullptr;
  1992. unsigned Attributes = Property->getPropertyAttributes();
  1993. unsigned AttributesAsWritten = Property->getPropertyAttributesAsWritten();
  1994. if (!(AttributesAsWritten & ObjCPropertyAttribute::kind_atomic) &&
  1995. !(AttributesAsWritten & ObjCPropertyAttribute::kind_nonatomic)) {
  1996. GetterMethod = Property->isClassProperty() ?
  1997. IMPDecl->getClassMethod(Property->getGetterName()) :
  1998. IMPDecl->getInstanceMethod(Property->getGetterName());
  1999. SetterMethod = Property->isClassProperty() ?
  2000. IMPDecl->getClassMethod(Property->getSetterName()) :
  2001. IMPDecl->getInstanceMethod(Property->getSetterName());
  2002. if (GetterMethod && GetterMethod->isSynthesizedAccessorStub())
  2003. GetterMethod = nullptr;
  2004. if (SetterMethod && SetterMethod->isSynthesizedAccessorStub())
  2005. SetterMethod = nullptr;
  2006. if (GetterMethod) {
  2007. Diag(GetterMethod->getLocation(),
  2008. diag::warn_default_atomic_custom_getter_setter)
  2009. << Property->getIdentifier() << 0;
  2010. Diag(Property->getLocation(), diag::note_property_declare);
  2011. }
  2012. if (SetterMethod) {
  2013. Diag(SetterMethod->getLocation(),
  2014. diag::warn_default_atomic_custom_getter_setter)
  2015. << Property->getIdentifier() << 1;
  2016. Diag(Property->getLocation(), diag::note_property_declare);
  2017. }
  2018. }
  2019. // We only care about readwrite atomic property.
  2020. if ((Attributes & ObjCPropertyAttribute::kind_nonatomic) ||
  2021. !(Attributes & ObjCPropertyAttribute::kind_readwrite))
  2022. continue;
  2023. if (const ObjCPropertyImplDecl *PIDecl = IMPDecl->FindPropertyImplDecl(
  2024. Property->getIdentifier(), Property->getQueryKind())) {
  2025. if (PIDecl->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
  2026. continue;
  2027. GetterMethod = PIDecl->getGetterMethodDecl();
  2028. SetterMethod = PIDecl->getSetterMethodDecl();
  2029. if (GetterMethod && GetterMethod->isSynthesizedAccessorStub())
  2030. GetterMethod = nullptr;
  2031. if (SetterMethod && SetterMethod->isSynthesizedAccessorStub())
  2032. SetterMethod = nullptr;
  2033. if ((bool)GetterMethod ^ (bool)SetterMethod) {
  2034. SourceLocation MethodLoc =
  2035. (GetterMethod ? GetterMethod->getLocation()
  2036. : SetterMethod->getLocation());
  2037. Diag(MethodLoc, diag::warn_atomic_property_rule)
  2038. << Property->getIdentifier() << (GetterMethod != nullptr)
  2039. << (SetterMethod != nullptr);
  2040. // fixit stuff.
  2041. if (Property->getLParenLoc().isValid() &&
  2042. !(AttributesAsWritten & ObjCPropertyAttribute::kind_atomic)) {
  2043. // @property () ... case.
  2044. SourceLocation AfterLParen =
  2045. getLocForEndOfToken(Property->getLParenLoc());
  2046. StringRef NonatomicStr = AttributesAsWritten? "nonatomic, "
  2047. : "nonatomic";
  2048. Diag(Property->getLocation(),
  2049. diag::note_atomic_property_fixup_suggest)
  2050. << FixItHint::CreateInsertion(AfterLParen, NonatomicStr);
  2051. } else if (Property->getLParenLoc().isInvalid()) {
  2052. //@property id etc.
  2053. SourceLocation startLoc =
  2054. Property->getTypeSourceInfo()->getTypeLoc().getBeginLoc();
  2055. Diag(Property->getLocation(),
  2056. diag::note_atomic_property_fixup_suggest)
  2057. << FixItHint::CreateInsertion(startLoc, "(nonatomic) ");
  2058. } else
  2059. Diag(MethodLoc, diag::note_atomic_property_fixup_suggest);
  2060. Diag(Property->getLocation(), diag::note_property_declare);
  2061. }
  2062. }
  2063. }
  2064. }
  2065. void Sema::DiagnoseOwningPropertyGetterSynthesis(const ObjCImplementationDecl *D) {
  2066. if (getLangOpts().getGC() == LangOptions::GCOnly)
  2067. return;
  2068. for (const auto *PID : D->property_impls()) {
  2069. const ObjCPropertyDecl *PD = PID->getPropertyDecl();
  2070. if (PD && !PD->hasAttr<NSReturnsNotRetainedAttr>() &&
  2071. !PD->isClassProperty()) {
  2072. ObjCMethodDecl *IM = PID->getGetterMethodDecl();
  2073. if (IM && !IM->isSynthesizedAccessorStub())
  2074. continue;
  2075. ObjCMethodDecl *method = PD->getGetterMethodDecl();
  2076. if (!method)
  2077. continue;
  2078. ObjCMethodFamily family = method->getMethodFamily();
  2079. if (family == OMF_alloc || family == OMF_copy ||
  2080. family == OMF_mutableCopy || family == OMF_new) {
  2081. if (getLangOpts().ObjCAutoRefCount)
  2082. Diag(PD->getLocation(), diag::err_cocoa_naming_owned_rule);
  2083. else
  2084. Diag(PD->getLocation(), diag::warn_cocoa_naming_owned_rule);
  2085. // Look for a getter explicitly declared alongside the property.
  2086. // If we find one, use its location for the note.
  2087. SourceLocation noteLoc = PD->getLocation();
  2088. SourceLocation fixItLoc;
  2089. for (auto *getterRedecl : method->redecls()) {
  2090. if (getterRedecl->isImplicit())
  2091. continue;
  2092. if (getterRedecl->getDeclContext() != PD->getDeclContext())
  2093. continue;
  2094. noteLoc = getterRedecl->getLocation();
  2095. fixItLoc = getterRedecl->getEndLoc();
  2096. }
  2097. Preprocessor &PP = getPreprocessor();
  2098. TokenValue tokens[] = {
  2099. tok::kw___attribute, tok::l_paren, tok::l_paren,
  2100. PP.getIdentifierInfo("objc_method_family"), tok::l_paren,
  2101. PP.getIdentifierInfo("none"), tok::r_paren,
  2102. tok::r_paren, tok::r_paren
  2103. };
  2104. StringRef spelling = "__attribute__((objc_method_family(none)))";
  2105. StringRef macroName = PP.getLastMacroWithSpelling(noteLoc, tokens);
  2106. if (!macroName.empty())
  2107. spelling = macroName;
  2108. auto noteDiag = Diag(noteLoc, diag::note_cocoa_naming_declare_family)
  2109. << method->getDeclName() << spelling;
  2110. if (fixItLoc.isValid()) {
  2111. SmallString<64> fixItText(" ");
  2112. fixItText += spelling;
  2113. noteDiag << FixItHint::CreateInsertion(fixItLoc, fixItText);
  2114. }
  2115. }
  2116. }
  2117. }
  2118. }
  2119. void Sema::DiagnoseMissingDesignatedInitOverrides(
  2120. const ObjCImplementationDecl *ImplD,
  2121. const ObjCInterfaceDecl *IFD) {
  2122. assert(IFD->hasDesignatedInitializers());
  2123. const ObjCInterfaceDecl *SuperD = IFD->getSuperClass();
  2124. if (!SuperD)
  2125. return;
  2126. SelectorSet InitSelSet;
  2127. for (const auto *I : ImplD->instance_methods())
  2128. if (I->getMethodFamily() == OMF_init)
  2129. InitSelSet.insert(I->getSelector());
  2130. SmallVector<const ObjCMethodDecl *, 8> DesignatedInits;
  2131. SuperD->getDesignatedInitializers(DesignatedInits);
  2132. for (SmallVector<const ObjCMethodDecl *, 8>::iterator
  2133. I = DesignatedInits.begin(), E = DesignatedInits.end(); I != E; ++I) {
  2134. const ObjCMethodDecl *MD = *I;
  2135. if (!InitSelSet.count(MD->getSelector())) {
  2136. // Don't emit a diagnostic if the overriding method in the subclass is
  2137. // marked as unavailable.
  2138. bool Ignore = false;
  2139. if (auto *IMD = IFD->getInstanceMethod(MD->getSelector())) {
  2140. Ignore = IMD->isUnavailable();
  2141. } else {
  2142. // Check the methods declared in the class extensions too.
  2143. for (auto *Ext : IFD->visible_extensions())
  2144. if (auto *IMD = Ext->getInstanceMethod(MD->getSelector())) {
  2145. Ignore = IMD->isUnavailable();
  2146. break;
  2147. }
  2148. }
  2149. if (!Ignore) {
  2150. Diag(ImplD->getLocation(),
  2151. diag::warn_objc_implementation_missing_designated_init_override)
  2152. << MD->getSelector();
  2153. Diag(MD->getLocation(), diag::note_objc_designated_init_marked_here);
  2154. }
  2155. }
  2156. }
  2157. }
  2158. /// AddPropertyAttrs - Propagates attributes from a property to the
  2159. /// implicitly-declared getter or setter for that property.
  2160. static void AddPropertyAttrs(Sema &S, ObjCMethodDecl *PropertyMethod,
  2161. ObjCPropertyDecl *Property) {
  2162. // Should we just clone all attributes over?
  2163. for (const auto *A : Property->attrs()) {
  2164. if (isa<DeprecatedAttr>(A) ||
  2165. isa<UnavailableAttr>(A) ||
  2166. isa<AvailabilityAttr>(A))
  2167. PropertyMethod->addAttr(A->clone(S.Context));
  2168. }
  2169. }
  2170. /// ProcessPropertyDecl - Make sure that any user-defined setter/getter methods
  2171. /// have the property type and issue diagnostics if they don't.
  2172. /// Also synthesize a getter/setter method if none exist (and update the
  2173. /// appropriate lookup tables.
  2174. void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property) {
  2175. ObjCMethodDecl *GetterMethod, *SetterMethod;
  2176. ObjCContainerDecl *CD = cast<ObjCContainerDecl>(property->getDeclContext());
  2177. if (CD->isInvalidDecl())
  2178. return;
  2179. bool IsClassProperty = property->isClassProperty();
  2180. GetterMethod = IsClassProperty ?
  2181. CD->getClassMethod(property->getGetterName()) :
  2182. CD->getInstanceMethod(property->getGetterName());
  2183. // if setter or getter is not found in class extension, it might be
  2184. // in the primary class.
  2185. if (!GetterMethod)
  2186. if (const ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CD))
  2187. if (CatDecl->IsClassExtension())
  2188. GetterMethod = IsClassProperty ? CatDecl->getClassInterface()->
  2189. getClassMethod(property->getGetterName()) :
  2190. CatDecl->getClassInterface()->
  2191. getInstanceMethod(property->getGetterName());
  2192. SetterMethod = IsClassProperty ?
  2193. CD->getClassMethod(property->getSetterName()) :
  2194. CD->getInstanceMethod(property->getSetterName());
  2195. if (!SetterMethod)
  2196. if (const ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CD))
  2197. if (CatDecl->IsClassExtension())
  2198. SetterMethod = IsClassProperty ? CatDecl->getClassInterface()->
  2199. getClassMethod(property->getSetterName()) :
  2200. CatDecl->getClassInterface()->
  2201. getInstanceMethod(property->getSetterName());
  2202. DiagnosePropertyAccessorMismatch(property, GetterMethod,
  2203. property->getLocation());
  2204. // synthesizing accessors must not result in a direct method that is not
  2205. // monomorphic
  2206. if (!GetterMethod) {
  2207. if (const ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CD)) {
  2208. auto *ExistingGetter = CatDecl->getClassInterface()->lookupMethod(
  2209. property->getGetterName(), !IsClassProperty, true, false, CatDecl);
  2210. if (ExistingGetter) {
  2211. if (ExistingGetter->isDirectMethod() || property->isDirectProperty()) {
  2212. Diag(property->getLocation(), diag::err_objc_direct_duplicate_decl)
  2213. << property->isDirectProperty() << 1 /* property */
  2214. << ExistingGetter->isDirectMethod()
  2215. << ExistingGetter->getDeclName();
  2216. Diag(ExistingGetter->getLocation(), diag::note_previous_declaration);
  2217. }
  2218. }
  2219. }
  2220. }
  2221. if (!property->isReadOnly() && !SetterMethod) {
  2222. if (const ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CD)) {
  2223. auto *ExistingSetter = CatDecl->getClassInterface()->lookupMethod(
  2224. property->getSetterName(), !IsClassProperty, true, false, CatDecl);
  2225. if (ExistingSetter) {
  2226. if (ExistingSetter->isDirectMethod() || property->isDirectProperty()) {
  2227. Diag(property->getLocation(), diag::err_objc_direct_duplicate_decl)
  2228. << property->isDirectProperty() << 1 /* property */
  2229. << ExistingSetter->isDirectMethod()
  2230. << ExistingSetter->getDeclName();
  2231. Diag(ExistingSetter->getLocation(), diag::note_previous_declaration);
  2232. }
  2233. }
  2234. }
  2235. }
  2236. if (!property->isReadOnly() && SetterMethod) {
  2237. if (Context.getCanonicalType(SetterMethod->getReturnType()) !=
  2238. Context.VoidTy)
  2239. Diag(SetterMethod->getLocation(), diag::err_setter_type_void);
  2240. if (SetterMethod->param_size() != 1 ||
  2241. !Context.hasSameUnqualifiedType(
  2242. (*SetterMethod->param_begin())->getType().getNonReferenceType(),
  2243. property->getType().getNonReferenceType())) {
  2244. Diag(property->getLocation(),
  2245. diag::warn_accessor_property_type_mismatch)
  2246. << property->getDeclName()
  2247. << SetterMethod->getSelector();
  2248. Diag(SetterMethod->getLocation(), diag::note_declared_at);
  2249. }
  2250. }
  2251. // Synthesize getter/setter methods if none exist.
  2252. // Find the default getter and if one not found, add one.
  2253. // FIXME: The synthesized property we set here is misleading. We almost always
  2254. // synthesize these methods unless the user explicitly provided prototypes
  2255. // (which is odd, but allowed). Sema should be typechecking that the
  2256. // declarations jive in that situation (which it is not currently).
  2257. if (!GetterMethod) {
  2258. // No instance/class method of same name as property getter name was found.
  2259. // Declare a getter method and add it to the list of methods
  2260. // for this class.
  2261. SourceLocation Loc = property->getLocation();
  2262. // The getter returns the declared property type with all qualifiers
  2263. // removed.
  2264. QualType resultTy = property->getType().getAtomicUnqualifiedType();
  2265. // If the property is null_resettable, the getter returns nonnull.
  2266. if (property->getPropertyAttributes() &
  2267. ObjCPropertyAttribute::kind_null_resettable) {
  2268. QualType modifiedTy = resultTy;
  2269. if (auto nullability = AttributedType::stripOuterNullability(modifiedTy)) {
  2270. if (*nullability == NullabilityKind::Unspecified)
  2271. resultTy = Context.getAttributedType(attr::TypeNonNull,
  2272. modifiedTy, modifiedTy);
  2273. }
  2274. }
  2275. GetterMethod = ObjCMethodDecl::Create(
  2276. Context, Loc, Loc, property->getGetterName(), resultTy, nullptr, CD,
  2277. !IsClassProperty, /*isVariadic=*/false,
  2278. /*isPropertyAccessor=*/true, /*isSynthesizedAccessorStub=*/false,
  2279. /*isImplicitlyDeclared=*/true, /*isDefined=*/false,
  2280. (property->getPropertyImplementation() == ObjCPropertyDecl::Optional)
  2281. ? ObjCMethodDecl::Optional
  2282. : ObjCMethodDecl::Required);
  2283. CD->addDecl(GetterMethod);
  2284. AddPropertyAttrs(*this, GetterMethod, property);
  2285. if (property->isDirectProperty())
  2286. GetterMethod->addAttr(ObjCDirectAttr::CreateImplicit(Context, Loc));
  2287. if (property->hasAttr<NSReturnsNotRetainedAttr>())
  2288. GetterMethod->addAttr(NSReturnsNotRetainedAttr::CreateImplicit(Context,
  2289. Loc));
  2290. if (property->hasAttr<ObjCReturnsInnerPointerAttr>())
  2291. GetterMethod->addAttr(
  2292. ObjCReturnsInnerPointerAttr::CreateImplicit(Context, Loc));
  2293. if (const SectionAttr *SA = property->getAttr<SectionAttr>())
  2294. GetterMethod->addAttr(SectionAttr::CreateImplicit(
  2295. Context, SA->getName(), Loc, AttributeCommonInfo::AS_GNU,
  2296. SectionAttr::GNU_section));
  2297. if (getLangOpts().ObjCAutoRefCount)
  2298. CheckARCMethodDecl(GetterMethod);
  2299. } else
  2300. // A user declared getter will be synthesize when @synthesize of
  2301. // the property with the same name is seen in the @implementation
  2302. GetterMethod->setPropertyAccessor(true);
  2303. GetterMethod->createImplicitParams(Context,
  2304. GetterMethod->getClassInterface());
  2305. property->setGetterMethodDecl(GetterMethod);
  2306. // Skip setter if property is read-only.
  2307. if (!property->isReadOnly()) {
  2308. // Find the default setter and if one not found, add one.
  2309. if (!SetterMethod) {
  2310. // No instance/class method of same name as property setter name was
  2311. // found.
  2312. // Declare a setter method and add it to the list of methods
  2313. // for this class.
  2314. SourceLocation Loc = property->getLocation();
  2315. SetterMethod =
  2316. ObjCMethodDecl::Create(Context, Loc, Loc,
  2317. property->getSetterName(), Context.VoidTy,
  2318. nullptr, CD, !IsClassProperty,
  2319. /*isVariadic=*/false,
  2320. /*isPropertyAccessor=*/true,
  2321. /*isSynthesizedAccessorStub=*/false,
  2322. /*isImplicitlyDeclared=*/true,
  2323. /*isDefined=*/false,
  2324. (property->getPropertyImplementation() ==
  2325. ObjCPropertyDecl::Optional) ?
  2326. ObjCMethodDecl::Optional :
  2327. ObjCMethodDecl::Required);
  2328. // Remove all qualifiers from the setter's parameter type.
  2329. QualType paramTy =
  2330. property->getType().getUnqualifiedType().getAtomicUnqualifiedType();
  2331. // If the property is null_resettable, the setter accepts a
  2332. // nullable value.
  2333. if (property->getPropertyAttributes() &
  2334. ObjCPropertyAttribute::kind_null_resettable) {
  2335. QualType modifiedTy = paramTy;
  2336. if (auto nullability = AttributedType::stripOuterNullability(modifiedTy)){
  2337. if (*nullability == NullabilityKind::Unspecified)
  2338. paramTy = Context.getAttributedType(attr::TypeNullable,
  2339. modifiedTy, modifiedTy);
  2340. }
  2341. }
  2342. // Invent the arguments for the setter. We don't bother making a
  2343. // nice name for the argument.
  2344. ParmVarDecl *Argument = ParmVarDecl::Create(Context, SetterMethod,
  2345. Loc, Loc,
  2346. property->getIdentifier(),
  2347. paramTy,
  2348. /*TInfo=*/nullptr,
  2349. SC_None,
  2350. nullptr);
  2351. SetterMethod->setMethodParams(Context, Argument, std::nullopt);
  2352. AddPropertyAttrs(*this, SetterMethod, property);
  2353. if (property->isDirectProperty())
  2354. SetterMethod->addAttr(ObjCDirectAttr::CreateImplicit(Context, Loc));
  2355. CD->addDecl(SetterMethod);
  2356. if (const SectionAttr *SA = property->getAttr<SectionAttr>())
  2357. SetterMethod->addAttr(SectionAttr::CreateImplicit(
  2358. Context, SA->getName(), Loc, AttributeCommonInfo::AS_GNU,
  2359. SectionAttr::GNU_section));
  2360. // It's possible for the user to have set a very odd custom
  2361. // setter selector that causes it to have a method family.
  2362. if (getLangOpts().ObjCAutoRefCount)
  2363. CheckARCMethodDecl(SetterMethod);
  2364. } else
  2365. // A user declared setter will be synthesize when @synthesize of
  2366. // the property with the same name is seen in the @implementation
  2367. SetterMethod->setPropertyAccessor(true);
  2368. SetterMethod->createImplicitParams(Context,
  2369. SetterMethod->getClassInterface());
  2370. property->setSetterMethodDecl(SetterMethod);
  2371. }
  2372. // Add any synthesized methods to the global pool. This allows us to
  2373. // handle the following, which is supported by GCC (and part of the design).
  2374. //
  2375. // @interface Foo
  2376. // @property double bar;
  2377. // @end
  2378. //
  2379. // void thisIsUnfortunate() {
  2380. // id foo;
  2381. // double bar = [foo bar];
  2382. // }
  2383. //
  2384. if (!IsClassProperty) {
  2385. if (GetterMethod)
  2386. AddInstanceMethodToGlobalPool(GetterMethod);
  2387. if (SetterMethod)
  2388. AddInstanceMethodToGlobalPool(SetterMethod);
  2389. } else {
  2390. if (GetterMethod)
  2391. AddFactoryMethodToGlobalPool(GetterMethod);
  2392. if (SetterMethod)
  2393. AddFactoryMethodToGlobalPool(SetterMethod);
  2394. }
  2395. ObjCInterfaceDecl *CurrentClass = dyn_cast<ObjCInterfaceDecl>(CD);
  2396. if (!CurrentClass) {
  2397. if (ObjCCategoryDecl *Cat = dyn_cast<ObjCCategoryDecl>(CD))
  2398. CurrentClass = Cat->getClassInterface();
  2399. else if (ObjCImplDecl *Impl = dyn_cast<ObjCImplDecl>(CD))
  2400. CurrentClass = Impl->getClassInterface();
  2401. }
  2402. if (GetterMethod)
  2403. CheckObjCMethodOverrides(GetterMethod, CurrentClass, Sema::RTC_Unknown);
  2404. if (SetterMethod)
  2405. CheckObjCMethodOverrides(SetterMethod, CurrentClass, Sema::RTC_Unknown);
  2406. }
  2407. void Sema::CheckObjCPropertyAttributes(Decl *PDecl,
  2408. SourceLocation Loc,
  2409. unsigned &Attributes,
  2410. bool propertyInPrimaryClass) {
  2411. // FIXME: Improve the reported location.
  2412. if (!PDecl || PDecl->isInvalidDecl())
  2413. return;
  2414. if ((Attributes & ObjCPropertyAttribute::kind_readonly) &&
  2415. (Attributes & ObjCPropertyAttribute::kind_readwrite))
  2416. Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
  2417. << "readonly" << "readwrite";
  2418. ObjCPropertyDecl *PropertyDecl = cast<ObjCPropertyDecl>(PDecl);
  2419. QualType PropertyTy = PropertyDecl->getType();
  2420. // Check for copy or retain on non-object types.
  2421. if ((Attributes &
  2422. (ObjCPropertyAttribute::kind_weak | ObjCPropertyAttribute::kind_copy |
  2423. ObjCPropertyAttribute::kind_retain |
  2424. ObjCPropertyAttribute::kind_strong)) &&
  2425. !PropertyTy->isObjCRetainableType() &&
  2426. !PropertyDecl->hasAttr<ObjCNSObjectAttr>()) {
  2427. Diag(Loc, diag::err_objc_property_requires_object)
  2428. << (Attributes & ObjCPropertyAttribute::kind_weak
  2429. ? "weak"
  2430. : Attributes & ObjCPropertyAttribute::kind_copy
  2431. ? "copy"
  2432. : "retain (or strong)");
  2433. Attributes &=
  2434. ~(ObjCPropertyAttribute::kind_weak | ObjCPropertyAttribute::kind_copy |
  2435. ObjCPropertyAttribute::kind_retain |
  2436. ObjCPropertyAttribute::kind_strong);
  2437. PropertyDecl->setInvalidDecl();
  2438. }
  2439. // Check for assign on object types.
  2440. if ((Attributes & ObjCPropertyAttribute::kind_assign) &&
  2441. !(Attributes & ObjCPropertyAttribute::kind_unsafe_unretained) &&
  2442. PropertyTy->isObjCRetainableType() &&
  2443. !PropertyTy->isObjCARCImplicitlyUnretainedType()) {
  2444. Diag(Loc, diag::warn_objc_property_assign_on_object);
  2445. }
  2446. // Check for more than one of { assign, copy, retain }.
  2447. if (Attributes & ObjCPropertyAttribute::kind_assign) {
  2448. if (Attributes & ObjCPropertyAttribute::kind_copy) {
  2449. Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
  2450. << "assign" << "copy";
  2451. Attributes &= ~ObjCPropertyAttribute::kind_copy;
  2452. }
  2453. if (Attributes & ObjCPropertyAttribute::kind_retain) {
  2454. Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
  2455. << "assign" << "retain";
  2456. Attributes &= ~ObjCPropertyAttribute::kind_retain;
  2457. }
  2458. if (Attributes & ObjCPropertyAttribute::kind_strong) {
  2459. Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
  2460. << "assign" << "strong";
  2461. Attributes &= ~ObjCPropertyAttribute::kind_strong;
  2462. }
  2463. if (getLangOpts().ObjCAutoRefCount &&
  2464. (Attributes & ObjCPropertyAttribute::kind_weak)) {
  2465. Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
  2466. << "assign" << "weak";
  2467. Attributes &= ~ObjCPropertyAttribute::kind_weak;
  2468. }
  2469. if (PropertyDecl->hasAttr<IBOutletCollectionAttr>())
  2470. Diag(Loc, diag::warn_iboutletcollection_property_assign);
  2471. } else if (Attributes & ObjCPropertyAttribute::kind_unsafe_unretained) {
  2472. if (Attributes & ObjCPropertyAttribute::kind_copy) {
  2473. Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
  2474. << "unsafe_unretained" << "copy";
  2475. Attributes &= ~ObjCPropertyAttribute::kind_copy;
  2476. }
  2477. if (Attributes & ObjCPropertyAttribute::kind_retain) {
  2478. Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
  2479. << "unsafe_unretained" << "retain";
  2480. Attributes &= ~ObjCPropertyAttribute::kind_retain;
  2481. }
  2482. if (Attributes & ObjCPropertyAttribute::kind_strong) {
  2483. Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
  2484. << "unsafe_unretained" << "strong";
  2485. Attributes &= ~ObjCPropertyAttribute::kind_strong;
  2486. }
  2487. if (getLangOpts().ObjCAutoRefCount &&
  2488. (Attributes & ObjCPropertyAttribute::kind_weak)) {
  2489. Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
  2490. << "unsafe_unretained" << "weak";
  2491. Attributes &= ~ObjCPropertyAttribute::kind_weak;
  2492. }
  2493. } else if (Attributes & ObjCPropertyAttribute::kind_copy) {
  2494. if (Attributes & ObjCPropertyAttribute::kind_retain) {
  2495. Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
  2496. << "copy" << "retain";
  2497. Attributes &= ~ObjCPropertyAttribute::kind_retain;
  2498. }
  2499. if (Attributes & ObjCPropertyAttribute::kind_strong) {
  2500. Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
  2501. << "copy" << "strong";
  2502. Attributes &= ~ObjCPropertyAttribute::kind_strong;
  2503. }
  2504. if (Attributes & ObjCPropertyAttribute::kind_weak) {
  2505. Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
  2506. << "copy" << "weak";
  2507. Attributes &= ~ObjCPropertyAttribute::kind_weak;
  2508. }
  2509. } else if ((Attributes & ObjCPropertyAttribute::kind_retain) &&
  2510. (Attributes & ObjCPropertyAttribute::kind_weak)) {
  2511. Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) << "retain"
  2512. << "weak";
  2513. Attributes &= ~ObjCPropertyAttribute::kind_retain;
  2514. } else if ((Attributes & ObjCPropertyAttribute::kind_strong) &&
  2515. (Attributes & ObjCPropertyAttribute::kind_weak)) {
  2516. Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) << "strong"
  2517. << "weak";
  2518. Attributes &= ~ObjCPropertyAttribute::kind_weak;
  2519. }
  2520. if (Attributes & ObjCPropertyAttribute::kind_weak) {
  2521. // 'weak' and 'nonnull' are mutually exclusive.
  2522. if (auto nullability = PropertyTy->getNullability()) {
  2523. if (*nullability == NullabilityKind::NonNull)
  2524. Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
  2525. << "nonnull" << "weak";
  2526. }
  2527. }
  2528. if ((Attributes & ObjCPropertyAttribute::kind_atomic) &&
  2529. (Attributes & ObjCPropertyAttribute::kind_nonatomic)) {
  2530. Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) << "atomic"
  2531. << "nonatomic";
  2532. Attributes &= ~ObjCPropertyAttribute::kind_atomic;
  2533. }
  2534. // Warn if user supplied no assignment attribute, property is
  2535. // readwrite, and this is an object type.
  2536. if (!getOwnershipRule(Attributes) && PropertyTy->isObjCRetainableType()) {
  2537. if (Attributes & ObjCPropertyAttribute::kind_readonly) {
  2538. // do nothing
  2539. } else if (getLangOpts().ObjCAutoRefCount) {
  2540. // With arc, @property definitions should default to strong when
  2541. // not specified.
  2542. PropertyDecl->setPropertyAttributes(ObjCPropertyAttribute::kind_strong);
  2543. } else if (PropertyTy->isObjCObjectPointerType()) {
  2544. bool isAnyClassTy = (PropertyTy->isObjCClassType() ||
  2545. PropertyTy->isObjCQualifiedClassType());
  2546. // In non-gc, non-arc mode, 'Class' is treated as a 'void *' no need to
  2547. // issue any warning.
  2548. if (isAnyClassTy && getLangOpts().getGC() == LangOptions::NonGC)
  2549. ;
  2550. else if (propertyInPrimaryClass) {
  2551. // Don't issue warning on property with no life time in class
  2552. // extension as it is inherited from property in primary class.
  2553. // Skip this warning in gc-only mode.
  2554. if (getLangOpts().getGC() != LangOptions::GCOnly)
  2555. Diag(Loc, diag::warn_objc_property_no_assignment_attribute);
  2556. // If non-gc code warn that this is likely inappropriate.
  2557. if (getLangOpts().getGC() == LangOptions::NonGC)
  2558. Diag(Loc, diag::warn_objc_property_default_assign_on_object);
  2559. }
  2560. }
  2561. // FIXME: Implement warning dependent on NSCopying being
  2562. // implemented. See also:
  2563. // <rdar://5168496&4855821&5607453&5096644&4947311&5698469&4947014&5168496>
  2564. // (please trim this list while you are at it).
  2565. }
  2566. if (!(Attributes & ObjCPropertyAttribute::kind_copy) &&
  2567. !(Attributes & ObjCPropertyAttribute::kind_readonly) &&
  2568. getLangOpts().getGC() == LangOptions::GCOnly &&
  2569. PropertyTy->isBlockPointerType())
  2570. Diag(Loc, diag::warn_objc_property_copy_missing_on_block);
  2571. else if ((Attributes & ObjCPropertyAttribute::kind_retain) &&
  2572. !(Attributes & ObjCPropertyAttribute::kind_readonly) &&
  2573. !(Attributes & ObjCPropertyAttribute::kind_strong) &&
  2574. PropertyTy->isBlockPointerType())
  2575. Diag(Loc, diag::warn_objc_property_retain_of_block);
  2576. if ((Attributes & ObjCPropertyAttribute::kind_readonly) &&
  2577. (Attributes & ObjCPropertyAttribute::kind_setter))
  2578. Diag(Loc, diag::warn_objc_readonly_property_has_setter);
  2579. }