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/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index d17be72..a4b54f2 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -1396,9 +1396,10 @@
 
 /// 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 @@
   }
 }
 
+/// 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: