From: Fariborz Jahanian Date: Wed, 31 Aug 2011 22:24:06 +0000 (+0000) Subject: objective-c: this patch (re)introduces objective-c's default property X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8697d308c1bdd50e5c45757ac11be701c26e9e97;p=clang objective-c: this patch (re)introduces objective-c's default property synthesis. This new feature is currently placed under -fobjc-default-synthesize-properties option and is off by default pending further testing. It will become the default feature soon. // rdar://8843851 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@138913 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index e6412d3d45..22d29b9dcd 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -1829,14 +1829,6 @@ public: ObjCIvarDecl **Fields, unsigned nIvars, SourceLocation Loc); - /// \brief Determine whether we can synthesize a provisional ivar for the - /// given name. - ObjCPropertyDecl *canSynthesizeProvisionalIvar(IdentifierInfo *II); - - /// \brief Determine whether we can synthesize a provisional ivar for the - /// given property. - bool canSynthesizeProvisionalIvar(ObjCPropertyDecl *Property); - /// ImplMethodsVsClassMethods - This is main routine to warn if any method /// remains unimplemented in the class or category @implementation. void ImplMethodsVsClassMethods(Scope *S, ObjCImplDecl* IMPDecl, @@ -1853,6 +1845,7 @@ public: /// properties which must be synthesized in class's @implementation. void DefaultSynthesizeProperties (Scope *S, ObjCImplDecl* IMPDecl, ObjCInterfaceDecl *IDecl); + void DefaultSynthesizeProperties(Scope *S, Decl *D); /// CollectImmediateProperties - This routine collects all properties in /// the class and its conforming protocols; but not those it its super class. @@ -2245,10 +2238,6 @@ public: // Primary Expressions. SourceRange getExprRange(Expr *E) const; - - ObjCIvarDecl *SynthesizeProvisionalIvar(LookupResult &Lookup, - IdentifierInfo *II, - SourceLocation NameLoc); ExprResult ActOnIdExpression(Scope *S, CXXScopeSpec &SS, UnqualifiedId &Name, bool HasTrailingLParen, bool IsAddressOfOperand); diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp index 22747e4c8f..1486065411 100644 --- a/lib/Driver/Tools.cpp +++ b/lib/Driver/Tools.cpp @@ -1880,18 +1880,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } } - // FIXME: Don't expose -fobjc-default-synthesize-properties as a top-level - // driver flag yet. This feature is still under active development - // and shouldn't be exposed as a user visible feature (which may change). - // Clang still supports this as a -cc1 option for development and testing. -#if 0 // -fobjc-default-synthesize-properties=0 is default. if (Args.hasFlag(options::OPT_fobjc_default_synthesize_properties, options::OPT_fno_objc_default_synthesize_properties, getToolChain().IsObjCDefaultSynthPropertiesDefault())) { CmdArgs.push_back("-fobjc-default-synthesize-properties"); } -#endif } // Allow -fno-objc-arr to trump -fobjc-arr/-fobjc-arc. diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp index e3f7978420..c9a12b14df 100644 --- a/lib/Parse/ParseObjc.cpp +++ b/lib/Parse/ParseObjc.cpp @@ -1401,22 +1401,23 @@ Parser::ParseObjCAtEndDeclaration(SourceRange atEnd) { "ParseObjCAtEndDeclaration(): Expected @end"); ConsumeToken(); // the "end" identifier SmallVector DeclsInGroup; - + Actions.DefaultSynthesizeProperties(getCurScope(), ObjCImpDecl); for (size_t i = 0; i < LateParsedObjCMethods.size(); ++i) { Decl *D = ParseLexedObjCMethodDefs(*LateParsedObjCMethods[i]); DeclsInGroup.push_back(D); } - LateParsedObjCMethods.clear(); DeclsInGroup.push_back(ObjCImpDecl); + if (ObjCImpDecl) { Actions.ActOnAtEnd(getCurScope(), atEnd); - ObjCImpDecl = 0; PendingObjCImpDecl.pop_back(); } - else { + else // missing @implementation Diag(atEnd.getBegin(), diag::err_expected_implementation); - } + + LateParsedObjCMethods.clear(); + ObjCImpDecl = 0; return Actions.BuildDeclaratorGroup( DeclsInGroup.data(), DeclsInGroup.size(), false); } diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index 5e19148c38..21ba3f9be5 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -990,9 +990,6 @@ bool ResultBuilder::IsOrdinaryName(NamedDecl *ND) const { else if (SemaRef.getLangOptions().ObjC1) { if (isa(ND)) return true; - if (isa(ND) && - SemaRef.canSynthesizeProvisionalIvar(cast(ND))) - return true; } return ND->getIdentifierNamespace() & IDNS; @@ -1011,9 +1008,6 @@ bool ResultBuilder::IsOrdinaryNonTypeName(NamedDecl *ND) const { else if (SemaRef.getLangOptions().ObjC1) { if (isa(ND)) return true; - if (isa(ND) && - SemaRef.canSynthesizeProvisionalIvar(cast(ND))) - return true; } return ND->getIdentifierNamespace() & IDNS; diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index e09896a60c..85352c2e5a 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -420,24 +420,6 @@ Sema::NameClassification Sema::ClassifyName(Scope *S, ExprResult E = LookupInObjCMethod(Result, S, Name, true); if (E.get() || E.isInvalid()) return E; - - // Synthesize ivars lazily. - if (getLangOptions().ObjCDefaultSynthProperties && - getLangOptions().ObjCNonFragileABI2) { - if (SynthesizeProvisionalIvar(Result, Name, NameLoc)) { - if (const ObjCPropertyDecl *Property = - canSynthesizeProvisionalIvar(Name)) { - Diag(NameLoc, diag::warn_synthesized_ivar_access) << Name; - Diag(Property->getLocation(), diag::note_property_declare); - } - - // FIXME: This is strange. Shouldn't we just take the ivar returned - // from SynthesizeProvisionalIvar and continue with that? - E = LookupInObjCMethod(Result, S, Name, true); - if (E.get() || E.isInvalid()) - return E; - } - } } bool SecondTry = false; diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index 0bc9412c65..3e657c70e6 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -2201,10 +2201,6 @@ void Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, } } } - - if (LangOpts.ObjCDefaultSynthProperties && - LangOpts.ObjCNonFragileABI2) - DefaultSynthesizeProperties(S, IC, IDecl); ImplMethodsVsClassMethods(S, IC, IDecl); AtomicPropertySetterGetterRules(IC, IDecl); DiagnoseOwningPropertyGetterSynthesis(IC); diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 928b11bd0b..b8f35639e3 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -1553,90 +1553,6 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, return true; } -ObjCPropertyDecl *Sema::canSynthesizeProvisionalIvar(IdentifierInfo *II) { - ObjCMethodDecl *CurMeth = getCurMethodDecl(); - ObjCInterfaceDecl *IDecl = CurMeth->getClassInterface(); - if (!IDecl) - return 0; - ObjCImplementationDecl *ClassImpDecl = IDecl->getImplementation(); - if (!ClassImpDecl) - return 0; - ObjCPropertyDecl *property = LookupPropertyDecl(IDecl, II); - if (!property) - return 0; - if (ObjCPropertyImplDecl *PIDecl = ClassImpDecl->FindPropertyImplDecl(II)) - if (PIDecl->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic || - PIDecl->getPropertyIvarDecl()) - return 0; - return property; -} - -bool Sema::canSynthesizeProvisionalIvar(ObjCPropertyDecl *Property) { - ObjCMethodDecl *CurMeth = getCurMethodDecl(); - ObjCInterfaceDecl *IDecl = CurMeth->getClassInterface(); - if (!IDecl) - return false; - ObjCImplementationDecl *ClassImpDecl = IDecl->getImplementation(); - if (!ClassImpDecl) - return false; - if (ObjCPropertyImplDecl *PIDecl - = ClassImpDecl->FindPropertyImplDecl(Property->getIdentifier())) - if (PIDecl->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic || - PIDecl->getPropertyIvarDecl()) - return false; - - return true; -} - -ObjCIvarDecl *Sema::SynthesizeProvisionalIvar(LookupResult &Lookup, - IdentifierInfo *II, - SourceLocation NameLoc) { - ObjCMethodDecl *CurMeth = getCurMethodDecl(); - bool LookForIvars; - if (Lookup.empty()) - LookForIvars = true; - else if (CurMeth->isClassMethod()) - LookForIvars = false; - else - LookForIvars = (Lookup.isSingleResult() && - Lookup.getFoundDecl()->isDefinedOutsideFunctionOrMethod() && - (Lookup.getAsSingle() != 0)); - if (!LookForIvars) - return 0; - - ObjCInterfaceDecl *IDecl = CurMeth->getClassInterface(); - if (!IDecl) - return 0; - ObjCImplementationDecl *ClassImpDecl = IDecl->getImplementation(); - if (!ClassImpDecl) - return 0; - bool DynamicImplSeen = false; - ObjCPropertyDecl *property = LookupPropertyDecl(IDecl, II); - if (!property) - return 0; - if (ObjCPropertyImplDecl *PIDecl = ClassImpDecl->FindPropertyImplDecl(II)) { - DynamicImplSeen = - (PIDecl->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic); - // property implementation has a designated ivar. No need to assume a new - // one. - if (!DynamicImplSeen && PIDecl->getPropertyIvarDecl()) - return 0; - } - if (!DynamicImplSeen) { - QualType PropType = Context.getCanonicalType(property->getType()); - ObjCIvarDecl *Ivar = ObjCIvarDecl::Create(Context, ClassImpDecl, - NameLoc, NameLoc, - II, PropType, /*Dinfo=*/0, - ObjCIvarDecl::Private, - (Expr *)0, true); - ClassImpDecl->addDecl(Ivar); - IDecl->makeDeclVisibleInContext(Ivar, false); - property->setPropertyIvarDecl(Ivar); - return Ivar; - } - return 0; -} - ExprResult Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS, UnqualifiedId &Id, @@ -1726,19 +1642,6 @@ ExprResult Sema::ActOnIdExpression(Scope *S, if (Expr *Ex = E.takeAs()) return Owned(Ex); - // Synthesize ivars lazily. - if (getLangOptions().ObjCDefaultSynthProperties && - getLangOptions().ObjCNonFragileABI2) { - if (SynthesizeProvisionalIvar(R, II, NameLoc)) { - if (const ObjCPropertyDecl *Property = - canSynthesizeProvisionalIvar(II)) { - Diag(NameLoc, diag::warn_synthesized_ivar_access) << II; - Diag(Property->getLocation(), diag::note_property_declare); - } - return ActOnIdExpression(S, SS, Id, HasTrailingLParen, - isAddressOfOperand); - } - } // for further use, this must be set to false if in class method. IvarLookupFollowUp = getCurMethodDecl()->isInstanceMethod(); } diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index 5dbadf7dea..c5dc144695 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -2885,24 +2885,7 @@ static void LookupVisibleDecls(Scope *S, LookupResult &Result, Result.getNameLoc(), Sema::LookupMemberName); if (ObjCInterfaceDecl *IFace = Method->getClassInterface()) { LookupVisibleDecls(IFace, IvarResult, /*QualifiedNameLookup=*/false, - /*InBaseClass=*/false, Consumer, Visited); - - // Look for properties from which we can synthesize ivars, if - // permitted. - if (Result.getSema().getLangOptions().ObjCNonFragileABI2 && - IFace->getImplementation() && - Result.getLookupKind() == Sema::LookupOrdinaryName) { - for (ObjCInterfaceDecl::prop_iterator - P = IFace->prop_begin(), - PEnd = IFace->prop_end(); - P != PEnd; ++P) { - if (Result.getSema().canSynthesizeProvisionalIvar(*P) && - !IFace->lookupInstanceVariable((*P)->getIdentifier())) { - Consumer.FoundDecl(*P, Visited.checkHidden(*P), false); - Visited.add(*P); - } - } - } + /*InBaseClass=*/false, Consumer, Visited); } } diff --git a/lib/Sema/SemaObjCProperty.cpp b/lib/Sema/SemaObjCProperty.cpp index f4743acec5..84052fd9d8 100644 --- a/lib/Sema/SemaObjCProperty.cpp +++ b/lib/Sema/SemaObjCProperty.cpp @@ -1289,6 +1289,16 @@ void Sema::DefaultSynthesizeProperties (Scope *S, ObjCImplDecl* IMPDecl, } } +void Sema::DefaultSynthesizeProperties(Scope *S, Decl *D) { + if (!LangOpts.ObjCDefaultSynthProperties || !LangOpts.ObjCNonFragileABI2) + return; + ObjCImplementationDecl *IC=dyn_cast_or_null(D); + if (!IC) + return; + if (ObjCInterfaceDecl* IDecl = IC->getClassInterface()) + DefaultSynthesizeProperties(S, IC, IDecl); +} + void Sema::DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl, ObjCContainerDecl *CDecl, const llvm::DenseSet& InsMap) { diff --git a/test/SemaObjC/default-synthesize-1.m b/test/SemaObjC/default-synthesize-1.m index a55834dd30..3a27a1d9c7 100644 --- a/test/SemaObjC/default-synthesize-1.m +++ b/test/SemaObjC/default-synthesize-1.m @@ -68,19 +68,19 @@ //@synthesize howMany, what; // REM: Redundant anyway - (int) howMany { - return howMany; + return howMany; // expected-error {{use of undeclared identifier 'howMany'}} } - (void) setHowMany: (int) value { - howMany = value; + howMany = value; // expected-error {{use of undeclared identifier 'howMany'}} } - (NSString*) what { - return what; + return what; // expected-error {{use of undeclared identifier 'what'}} } - (void) setWhat: (NSString*) value { - if (what != value) { - [what release]; - what = [value retain]; + if (what != value) { // expected-error {{use of undeclared identifier 'what'}} + [what release]; // expected-error {{use of undeclared identifier 'what'}} + what = [value retain]; // expected-error {{use of undeclared identifier 'what'}} } } @end diff --git a/test/SemaObjC/direct-synthesized-ivar-access.m b/test/SemaObjC/direct-synthesized-ivar-access.m index a72fb5f19c..d9be872b45 100644 --- a/test/SemaObjC/direct-synthesized-ivar-access.m +++ b/test/SemaObjC/direct-synthesized-ivar-access.m @@ -1,14 +1,15 @@ // RUN: %clang_cc1 -Wnonfragile-abi2 -fsyntax-only -fobjc-nonfragile-abi -fobjc-default-synthesize-properties -verify %s // rdar://8673791 +// rdar://9943851 @interface I { } -@property int IVAR; // expected-note {{property declared here}} +@property int IVAR; - (int) OK; @end @implementation I -- (int) Meth { return IVAR; } // expected-warning {{direct access of synthesized ivar by using property access 'IVAR'}} +- (int) Meth { return IVAR; } - (int) OK { return self.IVAR; } @end