class SourceManager;
// Decls
class Decl;
+ class ObjCPropertyDecl;
class RecordDecl;
class TagDecl;
class TranslationUnitDecl;
/// 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.
/// 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.
}
}
+/// 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<ObjCCategoryImplDecl>(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<ObjCImplementationDecl>(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<const RecordType *, 8> &ERType) const {
// FIXME: This currently doesn't encode:
/// 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);
/// 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.
OptClassMethods);
Values[3] = EmitPropertyList(std::string("\01L_OBJC_$_PROP_PROTO_LIST_") +
PD->getName(),
+ 0,
PD->classprop_begin(),
PD->classprop_end());
};
*/
llvm::Constant *CGObjCMac::EmitPropertyList(const std::string &Name,
+ const Decl *Container,
ObjCPropertyDecl * const *begin,
ObjCPropertyDecl * const *end) {
std::vector<llvm::Constant*> 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));
}
// 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 {
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());
}
// 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));
}
}
for (std::set<IdentifierInfo*>::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());