From: Daniel Dunbar Date: Thu, 28 Aug 2008 04:38:10 +0000 (+0000) Subject: NeXT: Emit mostly-correct property type encoding. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c56f34a1c1779de15330bdb3eec39b3418802d47;p=clang NeXT: Emit mostly-correct property type encoding. - Added ASTContext::getObjCEncodingForPropertyDecl. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@55461 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 1f9fec3c02..85f9d8bca7 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -38,6 +38,7 @@ namespace clang { class SourceManager; // Decls class Decl; + class ObjCPropertyDecl; class RecordDecl; class TagDecl; class TranslationUnitDecl; @@ -277,7 +278,15 @@ public: /// getObjCEncodingForMethodDecl - Return the encoded type for this method /// declaration. - void getObjCEncodingForMethodDecl(ObjCMethodDecl *Decl, std::string &S); + void getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl, std::string &S); + + /// getObjCEncodingForPropertyDecl - Return the encoded type for + /// this method declaration. If non-NULL, Container must be either + /// an ObjCCategoryImplDecl or ObjCImplementationDecl; it should + /// only be NULL when getting encodings for protocol properties. + void getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *Decl, + const Decl *Container, + std::string &S); /// getObjCEncodingTypeSize returns size of type for objective-c encoding /// purpose. diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index d17be725f5..a4b54f25e0 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -1396,9 +1396,10 @@ int ASTContext::getObjCEncodingTypeSize(QualType type) { /// getObjCEncodingForMethodDecl - Return the encoded type for this method /// declaration. -void ASTContext::getObjCEncodingForMethodDecl(ObjCMethodDecl *Decl, +void ASTContext::getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl, std::string& S) { + // FIXME: This is not very efficient. // Encode type qualifer, 'in', 'inout', etc. for the return type. getObjCEncodingForTypeQualifier(Decl->getObjCDeclQualifier(), S); // Encode result type. @@ -1436,6 +1437,91 @@ void ASTContext::getObjCEncodingForMethodDecl(ObjCMethodDecl *Decl, } } +/// getObjCEncodingForPropertyDecl - Return the encoded type for this +/// method declaration. If non-NULL, Container must be either an +/// ObjCCategoryImplDecl or ObjCImplementationDecl; it should only be +/// NULL when getting encodings for protocol properties. +void ASTContext::getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD, + const Decl *Container, + std::string& S) +{ + // Collect information from the property implementation decl(s). + bool Dynamic = false; + ObjCPropertyImplDecl *SynthesizePID = 0; + + // FIXME: Duplicated code due to poor abstraction. + if (Container) { + if (const ObjCCategoryImplDecl *CID = + dyn_cast(Container)) { + for (ObjCCategoryImplDecl::propimpl_iterator + i = CID->propimpl_begin(), e = CID->propimpl_end(); i != e; ++i) { + ObjCPropertyImplDecl *PID = *i; + if (PID->getPropertyDecl() == PD) { + if (PID->getPropertyImplementation()==ObjCPropertyImplDecl::Dynamic) { + Dynamic = true; + } else { + SynthesizePID = PID; + } + } + } + } else { + const ObjCImplementationDecl *OID = cast(Container); + for (ObjCCategoryImplDecl::propimpl_iterator + i = OID->propimpl_begin(), e = OID->propimpl_end(); i != e; ++i) { + ObjCPropertyImplDecl *PID = *i; + if (PID->getPropertyDecl() == PD) { + if (PID->getPropertyImplementation()==ObjCPropertyImplDecl::Dynamic) { + Dynamic = true; + } else { + SynthesizePID = PID; + } + } + } + } + } + + // FIXME: This is not very efficient. + S = "T"; + + // Encode result type. + // FIXME: GCC uses a generating_property_type_encoding mode during + // this part. Investigate. + getObjCEncodingForType(PD->getType(), S, EncodingRecordTypes); + + if (PD->isReadOnly()) { + S += ",R"; + } else { + switch (PD->getSetterKind()) { + case ObjCPropertyDecl::Assign: break; + case ObjCPropertyDecl::Copy: S += ",C"; break; + case ObjCPropertyDecl::Retain: S += ",&"; break; + } + } + + // It really isn't clear at all what this means, since properties + // are "dynamic by default". + if (Dynamic) + S += ",D"; + + if (PD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_getter) { + S += ",G"; + S += PD->getGetterName().getName(); + } + + if (PD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_setter) { + S += ",S"; + S += PD->getSetterName().getName(); + } + + if (SynthesizePID) { + const ObjCIvarDecl *OID = SynthesizePID->getPropertyIvarDecl(); + S += ",V"; + S += OID->getName(); + } + + // FIXME: OBJCGC: weak & strong +} + void ASTContext::getObjCEncodingForType(QualType T, std::string& S, llvm::SmallVector &ERType) const { // FIXME: This currently doesn't encode: diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp index fa8ed4dd82..69a0c4b06e 100644 --- a/lib/CodeGen/CGObjCMac.cpp +++ b/lib/CodeGen/CGObjCMac.cpp @@ -267,6 +267,7 @@ private: /// EmitPropertyList - Emit the given property list. The return /// value has type PropertyListPtrTy. llvm::Constant *EmitPropertyList(const std::string &Name, + const Decl *Container, ObjCPropertyDecl * const *begin, ObjCPropertyDecl * const *end); @@ -315,8 +316,9 @@ private: /// name. The return value has type char *. llvm::Constant *GetPropertyName(IdentifierInfo *Ident); - // FIXME: This is a horrible name too. - llvm::Constant *GetPropertyType(const ObjCPropertyDecl *PD); + // FIXME: This can be dropped once string functions are unified. + llvm::Constant *GetPropertyTypeString(const ObjCPropertyDecl *PD, + const Decl *Container); /// GetNameForMethod - Return a name for the given method. /// \param[out] NameOut - The return value. @@ -623,6 +625,7 @@ CGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD, OptClassMethods); Values[3] = EmitPropertyList(std::string("\01L_OBJC_$_PROP_PROTO_LIST_") + PD->getName(), + 0, PD->classprop_begin(), PD->classprop_end()); @@ -702,13 +705,14 @@ CGObjCMac::EmitProtocolList(const std::string &Name, }; */ llvm::Constant *CGObjCMac::EmitPropertyList(const std::string &Name, + const Decl *Container, ObjCPropertyDecl * const *begin, ObjCPropertyDecl * const *end) { std::vector Properties, Prop(2); for (; begin != end; ++begin) { const ObjCPropertyDecl *PD = *begin; Prop[0] = GetPropertyName(PD->getIdentifier()); - Prop[1] = GetPropertyType(PD); + Prop[1] = GetPropertyTypeString(PD, Container); Properties.push_back(llvm::ConstantStruct::get(ObjCTypes.PropertyTy, Prop)); } @@ -843,6 +847,7 @@ void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) { // If there is no category @interface then there can be no properties. if (Category) { Values[6] = EmitPropertyList(std::string("\01L_OBJC_$_PROP_LIST_") + ExtName, + OCD, Category->classprop_begin(), Category->classprop_end()); } else { @@ -1120,6 +1125,7 @@ CGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID) { Values[1] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy); Values[2] = EmitPropertyList(std::string("\01L_OBJC_$_PROP_LIST_") + ID->getName(), + ID, ID->getClassInterface()->classprop_begin(), ID->getClassInterface()->classprop_end()); @@ -1599,9 +1605,11 @@ llvm::Constant *CGObjCMac::GetPropertyName(IdentifierInfo *Ident) { } // FIXME: Merge into a single cstring creation function. -llvm::Constant *CGObjCMac::GetPropertyType(const ObjCPropertyDecl *PD) { - std::string TypeStr("MOOO!"); - //CGM.getContext().getObjCEncodingForMethodDecl(D, TypeStr); +// FIXME: This Decl should be more precise. +llvm::Constant *CGObjCMac::GetPropertyTypeString(const ObjCPropertyDecl *PD, + const Decl *Container) { + std::string TypeStr; + CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container, TypeStr); return GetPropertyName(&CGM.getContext().Idents.get(TypeStr)); } @@ -1650,7 +1658,7 @@ void CGObjCMac::FinishModule() { } for (std::set::iterator i = DefinedSymbols.begin(), e = DefinedSymbols.end(); i != e; ++i) { - s << "\t.objc_class_name_" << (*i)->getName() << " = 0\n" + s << "\t.objc_class_name_" << (*i)->getName() << "=0\n" << "\t.globl .objc_class_name_" << (*i)->getName() << "\n"; } CGM.getModule().appendModuleInlineAsm(s.str());