From 33de3f0333ca0b5274291b8d76c86758c0484691 Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Wed, 7 May 2008 17:43:59 +0000 Subject: [PATCH] This patch introduces declaration of getter methods for ObjC2's properties. Couple of property tests will fail with this patch. Will fix them next. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@50818 91177308-0d34-0410-b5e6-96231b3b80d8 --- Driver/ASTConsumers.cpp | 8 ++++---- include/clang/AST/DeclObjC.h | 19 +++++++++++++++++-- lib/AST/DeclObjC.cpp | 30 ++++++++++++++++++++++++++++++ lib/Parse/ParseObjc.cpp | 9 +++++++-- lib/Sema/SemaDeclObjC.cpp | 21 +++++++++++++-------- 5 files changed, 71 insertions(+), 16 deletions(-) diff --git a/Driver/ASTConsumers.cpp b/Driver/ASTConsumers.cpp index d8acc0d59e..3276228e60 100644 --- a/Driver/ASTConsumers.cpp +++ b/Driver/ASTConsumers.cpp @@ -273,16 +273,16 @@ void DeclPrinter::PrintObjCInterfaceDecl(ObjCInterfaceDecl *OID) { for (ObjCInterfaceDecl::classprop_iterator I = OID->classprop_begin(), E = OID->classprop_end(); I != E; ++I) PrintObjCPropertyDecl(*I); - + bool eol_needed = false; for (ObjCInterfaceDecl::classmeth_iterator I = OID->classmeth_begin(), E = OID->classmeth_end(); I != E; ++I) - PrintObjCMethodDecl(*I); + eol_needed = true, PrintObjCMethodDecl(*I); for (ObjCInterfaceDecl::instmeth_iterator I = OID->instmeth_begin(), E = OID->instmeth_end(); I != E; ++I) - PrintObjCMethodDecl(*I); + eol_needed = true, PrintObjCMethodDecl(*I); - Out << "@end\n"; + Out << (eol_needed ? "\n@end\n" : "@end\n"); // FIXME: implement the rest... } diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index 509f0e0747..9079445f3a 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -322,6 +322,10 @@ public: void mergeProperties(ObjCPropertyDecl **Properties, unsigned NumProperties); + void addPropertyMethods(ASTContext &Context, + ObjCPropertyDecl* Property, + llvm::SmallVector &insMethods); + typedef ObjCPropertyDecl * const * classprop_iterator; classprop_iterator classprop_begin() const { return PropertyDecl; } classprop_iterator classprop_end() const { @@ -1078,10 +1082,15 @@ private: Selector GetterName; // getter name of NULL if no getter Selector SetterName; // setter name of NULL if no setter + ObjCMethodDecl *GetterMethodDecl; // Declaration of getter instance method + ObjCMethodDecl *SetterMethodDecl; // Declaration of setter instance method + ObjCPropertyDecl(SourceLocation L, IdentifierInfo *Id, QualType T) : NamedDecl(ObjCProperty, L, Id), DeclType(T), - PropertyAttributes(OBJC_PR_noattr), GetterName(Selector()), - SetterName(Selector()) {} + PropertyAttributes(OBJC_PR_noattr), PropertyImplementation(None), + GetterName(Selector()), + SetterName(Selector()), + GetterMethodDecl(0), SetterMethodDecl(0) {} public: static ObjCPropertyDecl *Create(ASTContext &C, SourceLocation L, IdentifierInfo *Id, QualType T, @@ -1102,6 +1111,12 @@ public: Selector getSetterName() const { return SetterName; } void setSetterName(Selector Sel) { SetterName = Sel; } + ObjCMethodDecl *getGetterMethodDecl() const { return GetterMethodDecl; } + void setGetterMethodDecl(ObjCMethodDecl *gDecl) { GetterMethodDecl = gDecl; } + + ObjCMethodDecl *getSetterMethodDecl() const { return SetterMethodDecl; } + void setSetterMethodDecl(ObjCMethodDecl *gDecl) { SetterMethodDecl = gDecl; } + // Related to @optional/@required declared in @protocol void setPropertyImplementation(PropertyControl pc) { PropertyImplementation = pc; diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp index 0cb777d8de..3c89a6aa7d 100644 --- a/lib/AST/DeclObjC.cpp +++ b/lib/AST/DeclObjC.cpp @@ -270,6 +270,36 @@ void ObjCInterfaceDecl::mergeProperties(ObjCPropertyDecl **Properties, } } +/// addPropertyMethods - Goes through list of properties declared in this class +/// and builds setter/getter method declartions depending on the setter/getter +/// attributes of the property. +/// +void ObjCInterfaceDecl::addPropertyMethods( + ASTContext &Context, + ObjCPropertyDecl *property, + llvm::SmallVector &insMethods) { + // Find the default getter and if one not found, add one. + ObjCMethodDecl *GetterDecl = getInstanceMethod(property->getGetterName()); + if (GetterDecl) { + // An instance method with same name as property getter name found. + property->setGetterMethodDecl(GetterDecl); + } + else { + // No instance method of same name as property getter name was found. + // Declare a getter method and add it to the list of methods + // for this class. + QualType resultDeclType = property->getType(); + ObjCMethodDecl* ObjCMethod = + ObjCMethodDecl::Create(Context, property->getLocation(), + property->getLocation(), + property->getGetterName(), resultDeclType, + this, 0, + true, false, ObjCMethodDecl::Required); + property->setGetterMethodDecl(ObjCMethod); + insMethods.push_back(ObjCMethod); + } +} + /// addProperties - Insert property declaration AST nodes into /// ObjCProtocolDecl's PropertyDecl field. /// diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp index 1ff5877d2c..4795a464f5 100644 --- a/lib/Parse/ParseObjc.cpp +++ b/lib/Parse/ParseObjc.cpp @@ -271,9 +271,14 @@ void Parser::ParseObjCInterfaceDeclList(DeclTy *interfaceDecl, FieldDeclarator &FD = FieldDeclarators[i]; // Install the property declarator into interfaceDecl. Selector GetterSel = - PP.getSelectorTable().getNullarySelector(OCDS.getGetterName()); + PP.getSelectorTable().getNullarySelector(OCDS.getGetterName() + ? OCDS.getGetterName() + : FD.D.getIdentifier()); Selector SetterSel = - PP.getSelectorTable().getNullarySelector(OCDS.getSetterName()); + PP.getSelectorTable().getNullarySelector(OCDS.getSetterName() + ? OCDS.getSetterName() + // FIXME. This is not right! + : FD.D.getIdentifier()); DeclTy *Property = Actions.ActOnProperty(CurScope, DS.getSourceRange().getBegin(), FD, OCDS, GetterSel, SetterSel, diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index f9e4f5b14d..96710cc20c 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -872,12 +872,17 @@ void Sema::ActOnAtEnd(SourceLocation AtEndLoc, DeclTy *classDecl, } if (ObjCInterfaceDecl *I = dyn_cast(ClassDecl)) { - I->addMethods(&insMethods[0], insMethods.size(), - &clsMethods[0], clsMethods.size(), AtEndLoc); // Compares properties declaraed in this class to those of its // super class. ComparePropertiesInBaseAndSuper(I); MergeProtocolPropertiesIntoClass(I, I); + for (ObjCInterfaceDecl::classprop_iterator P = I->classprop_begin(), + E = I->classprop_end(); P != E; ++P) { + I->addPropertyMethods(Context, *P, insMethods); + } + I->addMethods(&insMethods[0], insMethods.size(), + &clsMethods[0], clsMethods.size(), AtEndLoc); + } else if (ObjCProtocolDecl *P = dyn_cast(ClassDecl)) { P->addMethods(&insMethods[0], insMethods.size(), &clsMethods[0], clsMethods.size(), AtEndLoc); @@ -1029,19 +1034,19 @@ Sema::DeclTy *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc, QualType T = GetTypeForDeclarator(FD.D, S); ObjCPropertyDecl *PDecl = ObjCPropertyDecl::Create(Context, AtLoc, FD.D.getIdentifier(), T); + // Regardless of setter/getter attribute, we save the default getter/setter + // selector names in anticipation of declaration of setter/getter methods. + PDecl->setGetterName(GetterSel); + PDecl->setSetterName(SetterSel); if (ODS.getPropertyAttributes() & ObjCDeclSpec::DQ_PR_readonly) PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readonly); - if (ODS.getPropertyAttributes() & ObjCDeclSpec::DQ_PR_getter) { + if (ODS.getPropertyAttributes() & ObjCDeclSpec::DQ_PR_getter) PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_getter); - PDecl->setGetterName(GetterSel); - } - if (ODS.getPropertyAttributes() & ObjCDeclSpec::DQ_PR_setter) { + if (ODS.getPropertyAttributes() & ObjCDeclSpec::DQ_PR_setter) PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_setter); - PDecl->setSetterName(SetterSel); - } if (ODS.getPropertyAttributes() & ObjCDeclSpec::DQ_PR_assign) PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_assign); -- 2.40.0