]> granicus.if.org Git - clang/commitdiff
NeXT: Emit mostly-correct property type encoding.
authorDaniel Dunbar <daniel@zuster.org>
Thu, 28 Aug 2008 04:38:10 +0000 (04:38 +0000)
committerDaniel Dunbar <daniel@zuster.org>
Thu, 28 Aug 2008 04:38:10 +0000 (04:38 +0000)
 - Added ASTContext::getObjCEncodingForPropertyDecl.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@55461 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/ASTContext.h
lib/AST/ASTContext.cpp
lib/CodeGen/CGObjCMac.cpp

index 1f9fec3c02dce8fe8ca3552ace64246a4634b84c..85f9d8bca73548876b59a39cc741b5466b1d5ddf 100644 (file)
@@ -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.
index d17be725f5f4382d001e5d317f83ba56e2af1e70..a4b54f25e061a5e5629a9ff3f582068d846a94f9 100644 (file)
@@ -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<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:
index fa8ed4dd8238223754b76a7734330115b720aa2b..69a0c4b06e87e2f4566ecfc42c9815e31a8ee118 100644 (file)
@@ -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<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));
   }
@@ -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<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());