Revert "[Sema] Diagnose default-initialization, destruction, and copying of"

This reverts commit r365985.

Prior to r365985, clang used to mark C union fields that have
non-trivial ObjC ownership qualifiers as unavailable if the union was
declared in a system header. r365985 stopped doing so, which caused the
swift compiler to crash when it tried to import a non-trivial union.

I have a patch that fixes the crash (https://reviews.llvm.org/D65256),
but I'm temporarily reverting the original patch until we can decide on
whether it's taking the right approach.

llvm-svn: 367076
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 21cf9da..21dd542 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -4252,9 +4252,6 @@
   setNonTrivialToPrimitiveDefaultInitialize(false);
   setNonTrivialToPrimitiveCopy(false);
   setNonTrivialToPrimitiveDestroy(false);
-  setHasNonTrivialToPrimitiveDefaultInitializeCUnion(false);
-  setHasNonTrivialToPrimitiveDestructCUnion(false);
-  setHasNonTrivialToPrimitiveCopyCUnion(false);
   setParamDestroyedInCallee(false);
   setArgPassingRestrictions(APK_CanPassInRegs);
 }
diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index ed75a0b..8d474a8 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -2276,16 +2276,60 @@
          getObjCLifetime() != Qualifiers::OCL_Weak;
 }
 
-bool QualType::hasNonTrivialToPrimitiveDefaultInitializeCUnion(const RecordDecl *RD) {
-  return RD->hasNonTrivialToPrimitiveDefaultInitializeCUnion();
-}
+namespace {
+// Helper class that determines whether this is a type that is non-trivial to
+// primitive copy or move, or is a struct type that has a field of such type.
+template <bool IsMove>
+struct IsNonTrivialCopyMoveVisitor
+    : CopiedTypeVisitor<IsNonTrivialCopyMoveVisitor<IsMove>, IsMove, bool> {
+  using Super =
+      CopiedTypeVisitor<IsNonTrivialCopyMoveVisitor<IsMove>, IsMove, bool>;
+  IsNonTrivialCopyMoveVisitor(const ASTContext &C) : Ctx(C) {}
+  void preVisit(QualType::PrimitiveCopyKind PCK, QualType QT) {}
 
-bool QualType::hasNonTrivialToPrimitiveDestructCUnion(const RecordDecl *RD) {
-  return RD->hasNonTrivialToPrimitiveDestructCUnion();
-}
+  bool visitWithKind(QualType::PrimitiveCopyKind PCK, QualType QT) {
+    if (const auto *AT = this->Ctx.getAsArrayType(QT))
+      return this->asDerived().visit(Ctx.getBaseElementType(AT));
+    return Super::visitWithKind(PCK, QT);
+  }
 
-bool QualType::hasNonTrivialToPrimitiveCopyCUnion(const RecordDecl *RD) {
-  return RD->hasNonTrivialToPrimitiveCopyCUnion();
+  bool visitARCStrong(QualType QT) { return true; }
+  bool visitARCWeak(QualType QT) { return true; }
+  bool visitTrivial(QualType QT) { return false; }
+  // Volatile fields are considered trivial.
+  bool visitVolatileTrivial(QualType QT) { return false; }
+
+  bool visitStruct(QualType QT) {
+    const RecordDecl *RD = QT->castAs<RecordType>()->getDecl();
+    // We don't want to apply the C restriction in C++ because C++
+    // (1) can apply the restriction at a finer grain by banning copying or
+    //     destroying the union, and
+    // (2) allows users to override these restrictions by declaring explicit
+    //     constructors/etc, which we're not proposing to add to C.
+    if (isa<CXXRecordDecl>(RD))
+      return false;
+    for (const FieldDecl *FD : RD->fields())
+      if (this->asDerived().visit(FD->getType()))
+        return true;
+    return false;
+  }
+
+  const ASTContext &Ctx;
+};
+
+} // namespace
+
+bool QualType::isNonTrivialPrimitiveCType(const ASTContext &Ctx) const {
+  if (isNonTrivialToPrimitiveDefaultInitialize())
+    return true;
+  DestructionKind DK = isDestructedType();
+  if (DK != DK_none && DK != DK_cxx_destructor)
+    return true;
+  if (IsNonTrivialCopyMoveVisitor<false>(Ctx).visit(*this))
+    return true;
+  if (IsNonTrivialCopyMoveVisitor<true>(Ctx).visit(*this))
+    return true;
+  return false;
 }
 
 QualType::PrimitiveDefaultInitializeKind
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index 11fed28..3941643 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -1658,24 +1658,12 @@
   // Set the EscapingByref flag of __block variables captured by
   // escaping blocks.
   for (const BlockDecl *BD : FSI.Blocks) {
+    if (BD->doesNotEscape())
+      continue;
     for (const BlockDecl::Capture &BC : BD->captures()) {
       VarDecl *VD = BC.getVariable();
-      if (VD->hasAttr<BlocksAttr>()) {
-        // Nothing to do if this is a __block variable captured by a
-        // non-escaping block.
-        if (BD->doesNotEscape())
-          continue;
+      if (VD->hasAttr<BlocksAttr>())
         VD->setEscapingByref();
-      }
-      // Check whether the captured variable is or contains an object of
-      // non-trivial C union type.
-      QualType CapType = BC.getVariable()->getType();
-      if (CapType.hasNonTrivialToPrimitiveDestructCUnion() ||
-          CapType.hasNonTrivialToPrimitiveCopyCUnion())
-        S.checkNonTrivialCUnion(BC.getVariable()->getType(),
-                                BD->getCaretLocation(),
-                                Sema::NTCUC_BlockCapture,
-                                Sema::NTCUK_Destruct|Sema::NTCUK_Copy);
     }
   }
 
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 2602e52..1c7b2b0 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -22,7 +22,6 @@
 #include "clang/AST/DeclTemplate.h"
 #include "clang/AST/EvaluatedExprVisitor.h"
 #include "clang/AST/ExprCXX.h"
-#include "clang/AST/NonTrivialTypeVisitor.h"
 #include "clang/AST/StmtCXX.h"
 #include "clang/Basic/Builtins.h"
 #include "clang/Basic/PartialDiagnostic.h"
@@ -6505,11 +6504,6 @@
 
     if (D.isInvalidType())
       NewVD->setInvalidDecl();
-
-    if (NewVD->getType().hasNonTrivialToPrimitiveDestructCUnion() &&
-        NewVD->hasLocalStorage())
-      checkNonTrivialCUnion(NewVD->getType(), NewVD->getLocation(),
-                            NTCUC_AutoVar, NTCUK_Destruct);
   } else {
     bool Invalid = false;
 
@@ -8932,12 +8926,6 @@
             << FunctionType::getNameForCallConv(CC);
       }
     }
-
-   if (NewFD->getReturnType().hasNonTrivialToPrimitiveDestructCUnion() ||
-       NewFD->getReturnType().hasNonTrivialToPrimitiveCopyCUnion())
-     checkNonTrivialCUnion(NewFD->getReturnType(),
-                           NewFD->getReturnTypeSourceRange().getBegin(),
-                           NTCUC_FunctionReturn, NTCUK_Destruct|NTCUK_Copy);
   } else {
     // C++11 [replacement.functions]p3:
     //  The program's definitions shall not be specified as inline.
@@ -11084,264 +11072,6 @@
   return VDecl->isInvalidDecl();
 }
 
-void Sema::checkNonTrivialCUnionInInitializer(const Expr *Init,
-                                              SourceLocation Loc) {
-  if (auto *CE = dyn_cast<ConstantExpr>(Init))
-    Init = CE->getSubExpr();
-
-  QualType InitType = Init->getType();
-  assert((InitType.hasNonTrivialToPrimitiveDefaultInitializeCUnion() ||
-          InitType.hasNonTrivialToPrimitiveCopyCUnion()) &&
-         "shouldn't be called if type doesn't have a non-trivial C struct");
-  if (auto *ILE = dyn_cast<InitListExpr>(Init)) {
-    for (auto I : ILE->inits()) {
-      if (!I->getType().hasNonTrivialToPrimitiveDefaultInitializeCUnion() &&
-          !I->getType().hasNonTrivialToPrimitiveCopyCUnion())
-        continue;
-      SourceLocation SL = I->getExprLoc();
-      checkNonTrivialCUnionInInitializer(I, SL.isValid() ? SL : Loc);
-    }
-    return;
-  }
-
-  if (isa<ImplicitValueInitExpr>(Init)) {
-    if (InitType.hasNonTrivialToPrimitiveDefaultInitializeCUnion())
-      checkNonTrivialCUnion(InitType, Loc, NTCUC_DefaultInitializedObject,
-                            NTCUK_Init);
-  } else {
-    // Assume all other explicit initializers involving copying some existing
-    // object.
-    // TODO: ignore any explicit initializers where we can guarantee
-    // copy-elision.
-    if (InitType.hasNonTrivialToPrimitiveCopyCUnion())
-      checkNonTrivialCUnion(InitType, Loc, NTCUC_CopyInit, NTCUK_Copy);
-  }
-}
-
-namespace {
-
-struct DiagNonTrivalCUnionDefaultInitializeVisitor
-    : DefaultInitializedTypeVisitor<DiagNonTrivalCUnionDefaultInitializeVisitor,
-                                    void> {
-  using Super =
-      DefaultInitializedTypeVisitor<DiagNonTrivalCUnionDefaultInitializeVisitor,
-                                    void>;
-
-  DiagNonTrivalCUnionDefaultInitializeVisitor(
-      QualType OrigTy, SourceLocation OrigLoc,
-      Sema::NonTrivialCUnionContext UseContext, Sema &S)
-      : OrigTy(OrigTy), OrigLoc(OrigLoc), UseContext(UseContext), S(S) {}
-
-  void visitWithKind(QualType::PrimitiveDefaultInitializeKind PDIK, QualType QT,
-                     const FieldDecl *FD, bool InNonTrivialUnion) {
-    if (const auto *AT = S.Context.getAsArrayType(QT))
-      return this->asDerived().visit(S.Context.getBaseElementType(AT), FD,
-                                     InNonTrivialUnion);
-    return Super::visitWithKind(PDIK, QT, FD, InNonTrivialUnion);
-  }
-
-  void visitARCStrong(QualType QT, const FieldDecl *FD,
-                      bool InNonTrivialUnion) {
-    if (InNonTrivialUnion)
-      S.Diag(FD->getLocation(), diag::note_non_trivial_c_union)
-          << 1 << 0 << QT << FD->getName();
-  }
-
-  void visitARCWeak(QualType QT, const FieldDecl *FD, bool InNonTrivialUnion) {
-    if (InNonTrivialUnion)
-      S.Diag(FD->getLocation(), diag::note_non_trivial_c_union)
-          << 1 << 0 << QT << FD->getName();
-  }
-
-  void visitStruct(QualType QT, const FieldDecl *FD, bool InNonTrivialUnion) {
-    const RecordDecl *RD = QT->castAs<RecordType>()->getDecl();
-    if (RD->isUnion()) {
-      if (OrigLoc.isValid()) {
-        bool IsUnion = false;
-        if (auto *OrigRD = OrigTy->getAsRecordDecl())
-          IsUnion = OrigRD->isUnion();
-        S.Diag(OrigLoc, diag::err_non_trivial_c_union_in_invalid_context)
-            << 0 << OrigTy << IsUnion << UseContext;
-        // Reset OrigLoc so that this diagnostic is emitted only once.
-        OrigLoc = SourceLocation();
-      }
-      InNonTrivialUnion = true;
-    }
-
-    if (InNonTrivialUnion)
-      S.Diag(RD->getLocation(), diag::note_non_trivial_c_union)
-          << 0 << 0 << QT.getUnqualifiedType() << "";
-
-    for (const FieldDecl *FD : RD->fields())
-      asDerived().visit(FD->getType(), FD, InNonTrivialUnion);
-  }
-
-  void visitTrivial(QualType QT, const FieldDecl *FD, bool InNonTrivialUnion) {}
-
-  // The non-trivial C union type or the struct/union type that contains a
-  // non-trivial C union.
-  QualType OrigTy;
-  SourceLocation OrigLoc;
-  Sema::NonTrivialCUnionContext UseContext;
-  Sema &S;
-};
-
-struct DiagNonTrivalCUnionDestructedTypeVisitor
-    : DestructedTypeVisitor<DiagNonTrivalCUnionDestructedTypeVisitor, void> {
-  using Super =
-      DestructedTypeVisitor<DiagNonTrivalCUnionDestructedTypeVisitor, void>;
-
-  DiagNonTrivalCUnionDestructedTypeVisitor(
-      QualType OrigTy, SourceLocation OrigLoc,
-      Sema::NonTrivialCUnionContext UseContext, Sema &S)
-      : OrigTy(OrigTy), OrigLoc(OrigLoc), UseContext(UseContext), S(S) {}
-
-  void visitWithKind(QualType::DestructionKind DK, QualType QT,
-                     const FieldDecl *FD, bool InNonTrivialUnion) {
-    if (const auto *AT = S.Context.getAsArrayType(QT))
-      return this->asDerived().visit(S.Context.getBaseElementType(AT), FD,
-                                     InNonTrivialUnion);
-    return Super::visitWithKind(DK, QT, FD, InNonTrivialUnion);
-  }
-
-  void visitARCStrong(QualType QT, const FieldDecl *FD,
-                      bool InNonTrivialUnion) {
-    if (InNonTrivialUnion)
-      S.Diag(FD->getLocation(), diag::note_non_trivial_c_union)
-          << 1 << 1 << QT << FD->getName();
-  }
-
-  void visitARCWeak(QualType QT, const FieldDecl *FD, bool InNonTrivialUnion) {
-    if (InNonTrivialUnion)
-      S.Diag(FD->getLocation(), diag::note_non_trivial_c_union)
-          << 1 << 1 << QT << FD->getName();
-  }
-
-  void visitStruct(QualType QT, const FieldDecl *FD, bool InNonTrivialUnion) {
-    const RecordDecl *RD = QT->castAs<RecordType>()->getDecl();
-    if (RD->isUnion()) {
-      if (OrigLoc.isValid()) {
-        bool IsUnion = false;
-        if (auto *OrigRD = OrigTy->getAsRecordDecl())
-          IsUnion = OrigRD->isUnion();
-        S.Diag(OrigLoc, diag::err_non_trivial_c_union_in_invalid_context)
-            << 1 << OrigTy << IsUnion << UseContext;
-        // Reset OrigLoc so that this diagnostic is emitted only once.
-        OrigLoc = SourceLocation();
-      }
-      InNonTrivialUnion = true;
-    }
-
-    if (InNonTrivialUnion)
-      S.Diag(RD->getLocation(), diag::note_non_trivial_c_union)
-          << 0 << 1 << QT.getUnqualifiedType() << "";
-
-    for (const FieldDecl *FD : RD->fields())
-      asDerived().visit(FD->getType(), FD, InNonTrivialUnion);
-  }
-
-  void visitTrivial(QualType QT, const FieldDecl *FD, bool InNonTrivialUnion) {}
-  void visitCXXDestructor(QualType QT, const FieldDecl *FD,
-                          bool InNonTrivialUnion) {}
-
-  // The non-trivial C union type or the struct/union type that contains a
-  // non-trivial C union.
-  QualType OrigTy;
-  SourceLocation OrigLoc;
-  Sema::NonTrivialCUnionContext UseContext;
-  Sema &S;
-};
-
-struct DiagNonTrivalCUnionCopyVisitor
-    : CopiedTypeVisitor<DiagNonTrivalCUnionCopyVisitor, false, void> {
-  using Super = CopiedTypeVisitor<DiagNonTrivalCUnionCopyVisitor, false, void>;
-
-  DiagNonTrivalCUnionCopyVisitor(QualType OrigTy, SourceLocation OrigLoc,
-                                 Sema::NonTrivialCUnionContext UseContext,
-                                 Sema &S)
-      : OrigTy(OrigTy), OrigLoc(OrigLoc), UseContext(UseContext), S(S) {}
-
-  void visitWithKind(QualType::PrimitiveCopyKind PCK, QualType QT,
-                     const FieldDecl *FD, bool InNonTrivialUnion) {
-    if (const auto *AT = S.Context.getAsArrayType(QT))
-      return this->asDerived().visit(S.Context.getBaseElementType(AT), FD,
-                                     InNonTrivialUnion);
-    return Super::visitWithKind(PCK, QT, FD, InNonTrivialUnion);
-  }
-
-  void visitARCStrong(QualType QT, const FieldDecl *FD,
-                      bool InNonTrivialUnion) {
-    if (InNonTrivialUnion)
-      S.Diag(FD->getLocation(), diag::note_non_trivial_c_union)
-          << 1 << 2 << QT << FD->getName();
-  }
-
-  void visitARCWeak(QualType QT, const FieldDecl *FD, bool InNonTrivialUnion) {
-    if (InNonTrivialUnion)
-      S.Diag(FD->getLocation(), diag::note_non_trivial_c_union)
-          << 1 << 2 << QT << FD->getName();
-  }
-
-  void visitStruct(QualType QT, const FieldDecl *FD, bool InNonTrivialUnion) {
-    const RecordDecl *RD = QT->castAs<RecordType>()->getDecl();
-    if (RD->isUnion()) {
-      if (OrigLoc.isValid()) {
-        bool IsUnion = false;
-        if (auto *OrigRD = OrigTy->getAsRecordDecl())
-          IsUnion = OrigRD->isUnion();
-        S.Diag(OrigLoc, diag::err_non_trivial_c_union_in_invalid_context)
-            << 2 << OrigTy << IsUnion << UseContext;
-        // Reset OrigLoc so that this diagnostic is emitted only once.
-        OrigLoc = SourceLocation();
-      }
-      InNonTrivialUnion = true;
-    }
-
-    if (InNonTrivialUnion)
-      S.Diag(RD->getLocation(), diag::note_non_trivial_c_union)
-          << 0 << 2 << QT.getUnqualifiedType() << "";
-
-    for (const FieldDecl *FD : RD->fields())
-      asDerived().visit(FD->getType(), FD, InNonTrivialUnion);
-  }
-
-  void preVisit(QualType::PrimitiveCopyKind PCK, QualType QT,
-                const FieldDecl *FD, bool InNonTrivialUnion) {}
-  void visitTrivial(QualType QT, const FieldDecl *FD, bool InNonTrivialUnion) {}
-  void visitVolatileTrivial(QualType QT, const FieldDecl *FD,
-                            bool InNonTrivialUnion) {}
-
-  // The non-trivial C union type or the struct/union type that contains a
-  // non-trivial C union.
-  QualType OrigTy;
-  SourceLocation OrigLoc;
-  Sema::NonTrivialCUnionContext UseContext;
-  Sema &S;
-};
-
-} // namespace
-
-void Sema::checkNonTrivialCUnion(QualType QT, SourceLocation Loc,
-                                 NonTrivialCUnionContext UseContext,
-                                 unsigned NonTrivialKind) {
-  assert((QT.hasNonTrivialToPrimitiveDefaultInitializeCUnion() ||
-          QT.hasNonTrivialToPrimitiveDestructCUnion() ||
-          QT.hasNonTrivialToPrimitiveCopyCUnion()) &&
-         "shouldn't be called if type doesn't have a non-trivial C union");
-
-  if ((NonTrivialKind & NTCUK_Init) &&
-      QT.hasNonTrivialToPrimitiveDefaultInitializeCUnion())
-    DiagNonTrivalCUnionDefaultInitializeVisitor(QT, Loc, UseContext, *this)
-        .visit(QT, nullptr, false);
-  if ((NonTrivialKind & NTCUK_Destruct) &&
-      QT.hasNonTrivialToPrimitiveDestructCUnion())
-    DiagNonTrivalCUnionDestructedTypeVisitor(QT, Loc, UseContext, *this)
-        .visit(QT, nullptr, false);
-  if ((NonTrivialKind & NTCUK_Copy) && QT.hasNonTrivialToPrimitiveCopyCUnion())
-    DiagNonTrivalCUnionCopyVisitor(QT, Loc, UseContext, *this)
-        .visit(QT, nullptr, false);
-}
-
 /// AddInitializerToDecl - Adds the initializer Init to the
 /// declaration dcl. If DirectInit is true, this is C++ direct
 /// initialization rather than copy initialization.
@@ -11747,12 +11477,6 @@
       CheckForConstantInitializer(Init, DclT);
   }
 
-  QualType InitType = Init->getType();
-  if (!InitType.isNull() &&
-      (InitType.hasNonTrivialToPrimitiveDefaultInitializeCUnion() ||
-       InitType.hasNonTrivialToPrimitiveCopyCUnion()))
-    checkNonTrivialCUnionInInitializer(Init, Init->getExprLoc());
-
   // We will represent direct-initialization similarly to copy-initialization:
   //    int x(1);  -as-> int x = 1;
   //    ClassType x(a,b,c); -as-> ClassType x = ClassType(a,b,c);
@@ -11877,14 +11601,7 @@
       return;
     }
 
-    VarDecl::DefinitionKind DefKind = Var->isThisDeclarationADefinition();
-    if (!Var->isInvalidDecl() && DefKind != VarDecl::DeclarationOnly &&
-        Var->getType().hasNonTrivialToPrimitiveDefaultInitializeCUnion())
-      checkNonTrivialCUnion(Var->getType(), Var->getLocation(),
-                            NTCUC_DefaultInitializedObject, NTCUK_Init);
-
-
-    switch (DefKind) {
+    switch (Var->isThisDeclarationADefinition()) {
     case VarDecl::Definition:
       if (!Var->isStaticDataMember() || !Var->getAnyInitializer())
         break;
@@ -12977,11 +12694,6 @@
                                          Context.getAdjustedParameterType(T),
                                          TSInfo, SC, nullptr);
 
-  if (New->getType().hasNonTrivialToPrimitiveDestructCUnion() ||
-      New->getType().hasNonTrivialToPrimitiveCopyCUnion())
-    checkNonTrivialCUnion(New->getType(), New->getLocation(),
-                          NTCUC_FunctionParam, NTCUK_Destruct|NTCUK_Copy);
-
   // Parameters can not be abstract class types.
   // For record types, this is done by the AbstractClassUsageDiagnoser once
   // the class has been completely parsed.
@@ -16228,6 +15940,7 @@
   // Verify that all the fields are okay.
   SmallVector<FieldDecl*, 32> RecFields;
 
+  bool ObjCFieldLifetimeErrReported = false;
   for (ArrayRef<Decl *>::iterator i = Fields.begin(), end = Fields.end();
        i != end; ++i) {
     FieldDecl *FD = cast<FieldDecl>(*i);
@@ -16366,12 +16079,38 @@
         Record->setHasObjectMember(true);
       if (Record && FDTTy->getDecl()->hasVolatileMember())
         Record->setHasVolatileMember(true);
+      if (Record && Record->isUnion() &&
+          FD->getType().isNonTrivialPrimitiveCType(Context))
+        Diag(FD->getLocation(),
+             diag::err_nontrivial_primitive_type_in_union);
     } else if (FDTy->isObjCObjectType()) {
       /// A field cannot be an Objective-c object
       Diag(FD->getLocation(), diag::err_statically_allocated_object)
         << FixItHint::CreateInsertion(FD->getLocation(), "*");
       QualType T = Context.getObjCObjectPointerType(FD->getType());
       FD->setType(T);
+    } else if (getLangOpts().allowsNonTrivialObjCLifetimeQualifiers() &&
+               Record && !ObjCFieldLifetimeErrReported && Record->isUnion() &&
+               !getLangOpts().CPlusPlus) {
+      // It's an error in ARC or Weak if a field has lifetime.
+      // We don't want to report this in a system header, though,
+      // so we just make the field unavailable.
+      // FIXME: that's really not sufficient; we need to make the type
+      // itself invalid to, say, initialize or copy.
+      QualType T = FD->getType();
+      if (T.hasNonTrivialObjCLifetime()) {
+        SourceLocation loc = FD->getLocation();
+        if (getSourceManager().isInSystemHeader(loc)) {
+          if (!FD->hasAttr<UnavailableAttr>()) {
+            FD->addAttr(UnavailableAttr::CreateImplicit(Context, "",
+                          UnavailableAttr::IR_ARCFieldWithOwnership, loc));
+          }
+        } else {
+          Diag(FD->getLocation(), diag::err_arc_objc_object_in_tag)
+            << T->isBlockPointerType() << Record->getTagKind();
+        }
+        ObjCFieldLifetimeErrReported = true;
+      }
     } else if (getLangOpts().ObjC &&
                getLangOpts().getGC() != LangOptions::NonGC &&
                Record && !Record->hasObjectMember()) {
@@ -16391,23 +16130,14 @@
 
     if (Record && !getLangOpts().CPlusPlus && !FD->hasAttr<UnavailableAttr>()) {
       QualType FT = FD->getType();
-      if (FT.isNonTrivialToPrimitiveDefaultInitialize()) {
+      if (FT.isNonTrivialToPrimitiveDefaultInitialize())
         Record->setNonTrivialToPrimitiveDefaultInitialize(true);
-        if (FT.hasNonTrivialToPrimitiveDefaultInitializeCUnion() ||
-            Record->isUnion())
-          Record->setHasNonTrivialToPrimitiveDefaultInitializeCUnion(true);
-      }
       QualType::PrimitiveCopyKind PCK = FT.isNonTrivialToPrimitiveCopy();
-      if (PCK != QualType::PCK_Trivial && PCK != QualType::PCK_VolatileTrivial) {
+      if (PCK != QualType::PCK_Trivial && PCK != QualType::PCK_VolatileTrivial)
         Record->setNonTrivialToPrimitiveCopy(true);
-        if (FT.hasNonTrivialToPrimitiveCopyCUnion() || Record->isUnion())
-          Record->setHasNonTrivialToPrimitiveCopyCUnion(true);
-      }
       if (FT.isDestructedType()) {
         Record->setNonTrivialToPrimitiveDestroy(true);
         Record->setParamDestroyedInCallee(true);
-        if (FT.hasNonTrivialToPrimitiveDestructCUnion() || Record->isUnion())
-          Record->setHasNonTrivialToPrimitiveDestructCUnion(true);
       }
 
       if (const auto *RT = FT->getAs<RecordType>()) {
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 8f5a892..52fa932 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -6076,7 +6076,7 @@
         ILE->setInit(i, ConstantExpr::Create(Context, Init));
       }
 
-  auto *E = new (Context) CompoundLiteralExpr(LParenLoc, TInfo, literalType,
+  Expr *E = new (Context) CompoundLiteralExpr(LParenLoc, TInfo, literalType,
                                               VK, LiteralExpr, isFileScope);
   if (isFileScope) {
     if (!LiteralExpr->isTypeDependent() &&
@@ -6094,19 +6094,6 @@
     return ExprError();
   }
 
-  // Compound literals that have automatic storage duration are destroyed at
-  // the end of the scope. Emit diagnostics if it is or contains a C union type
-  // that is non-trivial to destruct.
-  if (!isFileScope)
-    if (E->getType().hasNonTrivialToPrimitiveDestructCUnion())
-      checkNonTrivialCUnion(E->getType(), E->getExprLoc(),
-                            NTCUC_CompoundLiteral, NTCUK_Destruct);
-
-  if (E->getType().hasNonTrivialToPrimitiveDefaultInitializeCUnion() ||
-      E->getType().hasNonTrivialToPrimitiveCopyCUnion())
-    checkNonTrivialCUnionInInitializer(E->getInitializer(),
-                                       E->getInitializer()->getExprLoc());
-
   return MaybeBindToTemporary(E);
 }
 
@@ -12556,10 +12543,6 @@
           if (auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
             if (VD->hasLocalStorage() && getCurScope()->isDeclScope(VD))
               BE->getBlockDecl()->setCanAvoidCopyToHeap();
-
-      if (LHS.get()->getType().hasNonTrivialToPrimitiveCopyCUnion())
-        checkNonTrivialCUnion(LHS.get()->getType(), LHS.get()->getExprLoc(),
-                              NTCUC_Assignment, NTCUK_Copy);
     }
     RecordModifiableNonNullParam(*this, LHS.get());
     break;
@@ -13972,11 +13955,6 @@
       !BD->isDependentContext())
     computeNRVO(Body, BSI);
 
-  if (RetTy.hasNonTrivialToPrimitiveDestructCUnion() ||
-      RetTy.hasNonTrivialToPrimitiveCopyCUnion())
-    checkNonTrivialCUnion(RetTy, BD->getCaretLocation(), NTCUC_FunctionReturn,
-                          NTCUK_Destruct|NTCUK_Copy);
-
   PopDeclContext();
 
   // Pop the block scope now but keep it alive to the end of this function.
@@ -16228,15 +16206,6 @@
 }
 
 ExprResult Sema::CheckLValueToRValueConversionOperand(Expr *E) {
-  // Check whether the operand is or contains an object of non-trivial C union
-  // type.
-  if (E->getType().isVolatileQualified() &&
-      (E->getType().hasNonTrivialToPrimitiveDestructCUnion() ||
-       E->getType().hasNonTrivialToPrimitiveCopyCUnion()))
-    checkNonTrivialCUnion(E->getType(), E->getExprLoc(),
-                          Sema::NTCUC_LValueToRValueVolatile,
-                          NTCUK_Destruct|NTCUK_Copy);
-
   // C++2a [basic.def.odr]p4:
   //   [...] an expression of non-volatile-qualified non-class type to which
   //   the lvalue-to-rvalue conversion is applied [...]
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index 29acf61..62ff33a 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -2456,11 +2456,6 @@
     return true;
   }
 
-  if (T.hasNonTrivialToPrimitiveDestructCUnion() ||
-      T.hasNonTrivialToPrimitiveCopyCUnion())
-    checkNonTrivialCUnion(T, Loc, NTCUC_FunctionReturn,
-                          NTCUK_Destruct|NTCUK_Copy);
-
   return false;
 }
 
diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp
index 3cac82a..b40e3cf 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -794,9 +794,6 @@
   RD->setNonTrivialToPrimitiveDefaultInitialize(Record.readInt());
   RD->setNonTrivialToPrimitiveCopy(Record.readInt());
   RD->setNonTrivialToPrimitiveDestroy(Record.readInt());
-  RD->setHasNonTrivialToPrimitiveDefaultInitializeCUnion(Record.readInt());
-  RD->setHasNonTrivialToPrimitiveDestructCUnion(Record.readInt());
-  RD->setHasNonTrivialToPrimitiveCopyCUnion(Record.readInt());
   RD->setParamDestroyedInCallee(Record.readInt());
   RD->setArgPassingRestrictions((RecordDecl::ArgPassingKind)Record.readInt());
   return Redecl;
diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp
index b713155..3d9dd71 100644
--- a/clang/lib/Serialization/ASTWriterDecl.cpp
+++ b/clang/lib/Serialization/ASTWriterDecl.cpp
@@ -476,9 +476,6 @@
   Record.push_back(D->isNonTrivialToPrimitiveDefaultInitialize());
   Record.push_back(D->isNonTrivialToPrimitiveCopy());
   Record.push_back(D->isNonTrivialToPrimitiveDestroy());
-  Record.push_back(D->hasNonTrivialToPrimitiveDefaultInitializeCUnion());
-  Record.push_back(D->hasNonTrivialToPrimitiveDestructCUnion());
-  Record.push_back(D->hasNonTrivialToPrimitiveCopyCUnion());
   Record.push_back(D->isParamDestroyedInCallee());
   Record.push_back(D->getArgPassingRestrictions());
 
@@ -2002,12 +1999,6 @@
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1));
   // isNonTrivialToPrimitiveDestroy
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1));
-  // hasNonTrivialToPrimitiveDefaultInitializeCUnion
-  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1));
-  // hasNonTrivialToPrimitiveDestructCUnion
-  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1));
-  // hasNonTrivialToPrimitiveCopyCUnion
-  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1));
   // isParamDestroyedInCallee
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1));
   // getArgPassingRestrictions