Representation of objc gc's attribute using ExtQualType.
Note that one test attr-objc-gc.m fails. I will fix this
after removing these attributes from the Decl nodes.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@64889 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 4a3f00f..6b49b85 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -725,7 +725,7 @@
   // Check if we've already instantiated an address space qual'd type of this
   // type.
   llvm::FoldingSetNodeID ID;
-  ExtQualType::Profile(ID, T.getTypePtr(), AddressSpace, ExtQualType::GCNone);      
+  ExtQualType::Profile(ID, T.getTypePtr(), AddressSpace, T.getObjCGCAttr());      
   void *InsertPos = 0;
   if (ExtQualType *EXTQy = ExtQualTypes.FindNodeOrInsertPos(ID, InsertPos))
     return QualType(EXTQy, 0);
@@ -741,12 +741,47 @@
     assert(NewIP == 0 && "Shouldn't be in the map!"); NewIP = NewIP;
   }
   ExtQualType *New = new (*this, 8) ExtQualType(T.getTypePtr(), Canonical, 
-                                                AddressSpace, ExtQualType::GCNone);
+                                                AddressSpace, 
+                                                QualType::GCNone);
   ExtQualTypes.InsertNode(New, InsertPos);
   Types.push_back(New);
   return QualType(New, T.getCVRQualifiers());
 }
 
+QualType ASTContext::getObjCGCQualType(QualType T, 
+                                       QualType::GCAttrTypes attr) {
+  QualType CanT = getCanonicalType(T);
+  if (CanT.getObjCGCAttr() == attr)
+    return T;
+  
+  // Type's cannot have multiple ExtQuals, therefore we know we only have to deal
+  // with CVR qualifiers from here on out.
+  assert(CanT.getObjCGCAttr() == QualType::GCNone && 
+         "Type is already gc qualified");
+  
+  // Check if we've already instantiated an gc qual'd type of this type.
+  llvm::FoldingSetNodeID ID;
+  ExtQualType::Profile(ID, T.getTypePtr(), T.getAddressSpace(), attr);      
+  void *InsertPos = 0;
+  if (ExtQualType *EXTQy = ExtQualTypes.FindNodeOrInsertPos(ID, InsertPos))
+    return QualType(EXTQy, 0);
+  
+  // If the base type isn't canonical, this won't be a canonical type either,
+  // so fill in the canonical type field.
+  QualType Canonical;
+  if (!T->isCanonical()) {
+    Canonical = getObjCGCQualType(CanT, attr);
+    
+    // Get the new insert position for the node we care about.
+    ExtQualType *NewIP = ExtQualTypes.FindNodeOrInsertPos(ID, InsertPos);
+    assert(NewIP == 0 && "Shouldn't be in the map!"); NewIP = NewIP;
+  }
+  ExtQualType *New = new (*this, 8) ExtQualType(T.getTypePtr(), Canonical, 
+                                                0, attr);
+  ExtQualTypes.InsertNode(New, InsertPos);
+  Types.push_back(New);
+  return QualType(New, T.getCVRQualifiers());
+}
 
 /// getComplexType - Return the uniqued reference to the type for a complex
 /// number with the specified element type.
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index bc59707..6c72a76 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -1058,11 +1058,11 @@
     S = "__attribute__((address_space("+llvm::utostr_32(AddressSpace)+")))" + S;
     space = true;
   }
-  if (GCAttrType != GCNone) {
+  if (GCAttrType != QualType::GCNone) {
     if (space)
       S += ' ';
     S += "__attribute__((objc_gc(";
-    if (GCAttrType == Weak)
+    if (GCAttrType == QualType::Weak)
       S += "weak";
     else
       S += "strong";
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index db885e9..e6aafda 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -758,6 +758,35 @@
   Type = S.Context.getAddrSpaceQualType(Type, ASIdx);
 }
 
+/// HandleObjCGCTypeAttribute - Process an objc's gc attribute on the
+/// specified type.  The attribute contains 1 argument, weak or strong.
+static void HandleObjCGCTypeAttribute(QualType &Type, 
+                                      const AttributeList &Attr, Sema &S){
+  // FIXME. Needs more work for this to make sense.
+  if (Type.getObjCGCAttr() != QualType::GCNone) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_address_multiple_qualifiers);
+    return;
+  }
+  
+  // Check the attribute arguments.
+  QualType::GCAttrTypes attr;
+  if (!Attr.getParameterName() || Attr.getNumArgs() != 0) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+    return;
+  }
+  if (Attr.getParameterName()->isStr("weak")) 
+    attr = QualType::Weak;
+  else if (Attr.getParameterName()->isStr("strong"))
+    attr = QualType::Strong;
+  else {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported)
+      << "objc_gc" << Attr.getParameterName();
+    return;
+  }
+  
+  Type = S.Context.getObjCGCQualType(Type, attr);
+}
+
 void Sema::ProcessTypeAttributeList(QualType &Result, const AttributeList *AL) {
   // Scan through and apply attributes to this type where it makes sense.  Some
   // attributes (such as __address_space__, __vector_size__, etc) apply to the
@@ -771,6 +800,9 @@
     case AttributeList::AT_address_space:
       HandleAddressSpaceTypeAttribute(Result, *AL, *this);
       break;
+    case AttributeList::AT_objc_gc:
+      HandleObjCGCTypeAttribute(Result, *AL, *this);
+      break;
     }
   }
 }