[ObjC] Allow declaring __weak pointer fields in C structs in ARC.

This patch uses the infrastructure added in r326307 for enabling
non-trivial fields to be declared in C structs to allow __weak fields in
C structs in ARC.

This recommits r327206, which was reverted because it caused
module-enabled builders to fail. I discovered that the
CXXRecordDecl::CanPassInRegisters flag wasn't being set correctly in
some cases after I moved it to RecordDecl.

Thanks to Eric Liu for helping me investigate the bug.

rdar://problem/33599681

https://reviews.llvm.org/D44095

llvm-svn: 327870
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index ac262e7..6b9260d 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -1105,7 +1105,6 @@
       = FromData.HasConstexprNonCopyMoveConstructor;
     ToData.HasDefaultedDefaultConstructor
       = FromData.HasDefaultedDefaultConstructor;
-    ToData.CanPassInRegisters = FromData.CanPassInRegisters;
     ToData.DefaultedDefaultConstructorIsConstexpr
       = FromData.DefaultedDefaultConstructorIsConstexpr;
     ToData.HasConstexprDefaultConstructor
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index b640dcc..35364d6 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -3931,7 +3931,8 @@
       HasObjectMember(false), HasVolatileMember(false),
       LoadedFieldsFromExternalStorage(false),
       NonTrivialToPrimitiveDefaultInitialize(false),
-      NonTrivialToPrimitiveCopy(false), NonTrivialToPrimitiveDestroy(false) {
+      NonTrivialToPrimitiveCopy(false), NonTrivialToPrimitiveDestroy(false),
+      CanPassInRegisters(true) {
   assert(classof(static_cast<Decl*>(this)) && "Invalid Kind!");
 }
 
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp
index 487386f..2718723 100644
--- a/clang/lib/AST/DeclCXX.cpp
+++ b/clang/lib/AST/DeclCXX.cpp
@@ -93,7 +93,6 @@
       DeclaredNonTrivialSpecialMembersForCall(0), HasIrrelevantDestructor(true),
       HasConstexprNonCopyMoveConstructor(false),
       HasDefaultedDefaultConstructor(false),
-      CanPassInRegisters(true),
       DefaultedDefaultConstructorIsConstexpr(true),
       HasConstexprDefaultConstructor(false),
       HasNonLiteralTypeFieldsOrBases(false), ComputedVisibleConversions(false),
diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index 99f5b13..2985aac 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -2214,11 +2214,14 @@
     if (RT->getDecl()->isNonTrivialToPrimitiveDefaultInitialize())
       return PDIK_Struct;
 
-  Qualifiers::ObjCLifetime Lifetime = getQualifiers().getObjCLifetime();
-  if (Lifetime == Qualifiers::OCL_Strong)
+  switch (getQualifiers().getObjCLifetime()) {
+  case Qualifiers::OCL_Strong:
     return PDIK_ARCStrong;
-
-  return PDIK_Trivial;
+  case Qualifiers::OCL_Weak:
+    return PDIK_ARCWeak;
+  default:
+    return PDIK_Trivial;
+  }
 }
 
 QualType::PrimitiveCopyKind QualType::isNonTrivialToPrimitiveCopy() const {
@@ -2228,10 +2231,14 @@
       return PCK_Struct;
 
   Qualifiers Qs = getQualifiers();
-  if (Qs.getObjCLifetime() == Qualifiers::OCL_Strong)
+  switch (Qs.getObjCLifetime()) {
+  case Qualifiers::OCL_Strong:
     return PCK_ARCStrong;
-
-  return Qs.hasVolatile() ? PCK_VolatileTrivial : PCK_Trivial;
+  case Qualifiers::OCL_Weak:
+    return PCK_ARCWeak;
+  default:
+    return Qs.hasVolatile() ? PCK_VolatileTrivial : PCK_Trivial;
+  }
 }
 
 QualType::PrimitiveCopyKind
@@ -2239,6 +2246,17 @@
   return isNonTrivialToPrimitiveCopy();
 }
 
+bool QualType::canPassInRegisters() const {
+  if (const auto *RT =
+          getTypePtr()->getBaseElementTypeUnsafe()->getAs<RecordType>())
+    return RT->getDecl()->canPassInRegisters();
+
+  if (getQualifiers().getObjCLifetime() == Qualifiers::OCL_Weak)
+    return false;
+
+  return true;
+}
+
 bool Type::isLiteralType(const ASTContext &Ctx) const {
   if (isDependentType())
     return false;