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

Akira Hatanaka via cfe-commits cfe-commits at lists.llvm.org
Thu Jul 25 17:02:18 PDT 2019


Author: ahatanak
Date: Thu Jul 25 17:02:17 2019
New Revision: 367076

URL: http://llvm.org/viewvc/llvm-project?rev=367076&view=rev
Log:
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.

Added:
    cfe/trunk/test/CodeGenObjC/Inputs/strong_in_union.h
Removed:
    cfe/trunk/test/PCH/non-trivial-c-union.m
    cfe/trunk/test/SemaObjC/non-trivial-c-union.m
Modified:
    cfe/trunk/include/clang/AST/Decl.h
    cfe/trunk/include/clang/AST/DeclBase.h
    cfe/trunk/include/clang/AST/Type.h
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/AST/Decl.cpp
    cfe/trunk/lib/AST/Type.cpp
    cfe/trunk/lib/Sema/Sema.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaType.cpp
    cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
    cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
    cfe/trunk/test/CodeGenObjC/strong-in-c-struct.m
    cfe/trunk/test/SemaObjC/arc-decls.m

Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=367076&r1=367075&r2=367076&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Thu Jul 25 17:02:17 2019
@@ -3746,30 +3746,6 @@ public:
     RecordDeclBits.NonTrivialToPrimitiveDestroy = V;
   }
 
-  bool hasNonTrivialToPrimitiveDefaultInitializeCUnion() const {
-    return RecordDeclBits.HasNonTrivialToPrimitiveDefaultInitializeCUnion;
-  }
-
-  void setHasNonTrivialToPrimitiveDefaultInitializeCUnion(bool V) {
-    RecordDeclBits.HasNonTrivialToPrimitiveDefaultInitializeCUnion = V;
-  }
-
-  bool hasNonTrivialToPrimitiveDestructCUnion() const {
-    return RecordDeclBits.HasNonTrivialToPrimitiveDestructCUnion;
-  }
-
-  void setHasNonTrivialToPrimitiveDestructCUnion(bool V) {
-    RecordDeclBits.HasNonTrivialToPrimitiveDestructCUnion = V;
-  }
-
-  bool hasNonTrivialToPrimitiveCopyCUnion() const {
-    return RecordDeclBits.HasNonTrivialToPrimitiveCopyCUnion;
-  }
-
-  void setHasNonTrivialToPrimitiveCopyCUnion(bool V) {
-    RecordDeclBits.HasNonTrivialToPrimitiveCopyCUnion = V;
-  }
-
   /// Determine whether this class can be passed in registers. In C++ mode,
   /// it must have at least one trivial, non-deleted copy or move constructor.
   /// FIXME: This should be set as part of completeDefinition.

Modified: cfe/trunk/include/clang/AST/DeclBase.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclBase.h?rev=367076&r1=367075&r2=367076&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclBase.h (original)
+++ cfe/trunk/include/clang/AST/DeclBase.h Thu Jul 25 17:02:17 2019
@@ -1440,13 +1440,6 @@ class DeclContext {
     uint64_t NonTrivialToPrimitiveCopy : 1;
     uint64_t NonTrivialToPrimitiveDestroy : 1;
 
-    /// The following bits indicate whether this is or contains a C union that
-    /// is non-trivial to default-initialize, destruct, or copy. These bits
-    /// imply the associated basic non-triviality predicates declared above.
-    uint64_t HasNonTrivialToPrimitiveDefaultInitializeCUnion : 1;
-    uint64_t HasNonTrivialToPrimitiveDestructCUnion : 1;
-    uint64_t HasNonTrivialToPrimitiveCopyCUnion : 1;
-
     /// Indicates whether this struct is destroyed in the callee.
     uint64_t ParamDestroyedInCallee : 1;
 
@@ -1455,7 +1448,7 @@ class DeclContext {
   };
 
   /// Number of non-inherited bits in RecordDeclBitfields.
-  enum { NumRecordDeclBits = 14 };
+  enum { NumRecordDeclBits = 11 };
 
   /// Stores the bits used by OMPDeclareReductionDecl.
   /// If modified NumOMPDeclareReductionDeclBits and the accessor

Modified: cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=367076&r1=367075&r2=367076&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Thu Jul 25 17:02:17 2019
@@ -1130,6 +1130,12 @@ public:
   };
 
   /// Check if this is a non-trivial type that would cause a C struct
+  /// transitively containing this type to be non-trivial. This function can be
+  /// used to determine whether a field of this type can be declared inside a C
+  /// union.
+  bool isNonTrivialPrimitiveCType(const ASTContext &Ctx) const;
+
+  /// Check if this is a non-trivial type that would cause a C struct
   /// transitively containing this type to be non-trivial to copy and return the
   /// kind.
   PrimitiveCopyKind isNonTrivialToPrimitiveCopy() const;
@@ -1158,22 +1164,6 @@ public:
     return isDestructedTypeImpl(*this);
   }
 
-  /// Check if this is or contains a C union that is non-trivial to
-  /// default-initialize, which is a union that has a member that is non-trivial
-  /// to default-initialize. If this returns true,
-  /// isNonTrivialToPrimitiveDefaultInitialize returns PDIK_Struct.
-  bool hasNonTrivialToPrimitiveDefaultInitializeCUnion() const;
-
-  /// Check if this is or contains a C union that is non-trivial to destruct,
-  /// which is a union that has a member that is non-trivial to destruct. If
-  /// this returns true, isDestructedType returns DK_nontrivial_c_struct.
-  bool hasNonTrivialToPrimitiveDestructCUnion() const;
-
-  /// Check if this is or contains a C union that is non-trivial to copy, which
-  /// is a union that has a member that is non-trivial to copy. If this returns
-  /// true, isNonTrivialToPrimitiveCopy returns PCK_Struct.
-  bool hasNonTrivialToPrimitiveCopyCUnion() const;
-
   /// Determine whether expressions of the given type are forbidden
   /// from being lvalues in C.
   ///
@@ -1246,11 +1236,6 @@ private:
                                                  const ASTContext &C);
   static QualType IgnoreParens(QualType T);
   static DestructionKind isDestructedTypeImpl(QualType type);
-
-  /// Check if \param RD is or contains a non-trivial C union.
-  static bool hasNonTrivialToPrimitiveDefaultInitializeCUnion(const RecordDecl *RD);
-  static bool hasNonTrivialToPrimitiveDestructCUnion(const RecordDecl *RD);
-  static bool hasNonTrivialToPrimitiveCopyCUnion(const RecordDecl *RD);
 };
 
 } // namespace clang
@@ -6264,24 +6249,6 @@ inline Qualifiers::GC QualType::getObjCG
   return getQualifiers().getObjCGCAttr();
 }
 
-inline bool QualType::hasNonTrivialToPrimitiveDefaultInitializeCUnion() const {
-  if (auto *RD = getTypePtr()->getBaseElementTypeUnsafe()->getAsRecordDecl())
-    return hasNonTrivialToPrimitiveDefaultInitializeCUnion(RD);
-  return false;
-}
-
-inline bool QualType::hasNonTrivialToPrimitiveDestructCUnion() const {
-  if (auto *RD = getTypePtr()->getBaseElementTypeUnsafe()->getAsRecordDecl())
-    return hasNonTrivialToPrimitiveDestructCUnion(RD);
-  return false;
-}
-
-inline bool QualType::hasNonTrivialToPrimitiveCopyCUnion() const {
-  if (auto *RD = getTypePtr()->getBaseElementTypeUnsafe()->getAsRecordDecl())
-    return hasNonTrivialToPrimitiveCopyCUnion(RD);
-  return false;
-}
-
 inline FunctionType::ExtInfo getFunctionExtInfo(const Type &t) {
   if (const auto *PT = t.getAs<PointerType>()) {
     if (const auto *FT = PT->getPointeeType()->getAs<FunctionType>())

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=367076&r1=367075&r2=367076&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Thu Jul 25 17:02:17 2019
@@ -620,23 +620,8 @@ def warn_cstruct_memaccess : Warning<
   InGroup<NonTrivialMemaccess>;
 def note_nontrivial_field : Note<
   "field is non-trivial to %select{copy|default-initialize}0">;
-def err_non_trivial_c_union_in_invalid_context : Error<
-  "cannot %select{"
-  "use type %1 for a function/method parameter|"
-  "use type %1 for function/method return|"
-  "default-initialize an object of type %1|"
-  "declare an automatic variable of type %1|"
-  "copy-initialize an object of type %1|"
-  "assign to a variable of type %1|"
-  "construct an automatic compound literal of type %1|"
-  "capture a variable of type %1|"
-  "cannot use volatile type %1 where it causes an lvalue-to-rvalue conversion"
-  "}3 "
-  "since it %select{contains|is}2 a union that is non-trivial to "
-  "%select{default-initialize|destruct|copy}0">;
-def note_non_trivial_c_union : Note<
-  "%select{%2 has subobjects that are|%3 has type %2 that is}0 "
-  "non-trivial to %select{default-initialize|destruct|copy}1">;
+def err_nontrivial_primitive_type_in_union : Error<
+  "non-trivial C types are disallowed in union">;
 def warn_dyn_class_memaccess : Warning<
   "%select{destination for|source of|first operand of|second operand of}0 this "
   "%1 call is a pointer to %select{|class containing a }2dynamic class %3; "

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=367076&r1=367075&r2=367076&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Thu Jul 25 17:02:17 2019
@@ -2114,48 +2114,6 @@ public:
   bool SetParamDefaultArgument(ParmVarDecl *Param, Expr *DefaultArg,
                                SourceLocation EqualLoc);
 
-  // Contexts where using non-trivial C union types can be disallowed. This is
-  // passed to err_non_trivial_c_union_in_invalid_context.
-  enum NonTrivialCUnionContext {
-    // Function parameter.
-    NTCUC_FunctionParam,
-    // Function return.
-    NTCUC_FunctionReturn,
-    // Default-initialized object.
-    NTCUC_DefaultInitializedObject,
-    // Variable with automatic storage duration.
-    NTCUC_AutoVar,
-    // Initializer expression that might copy from another object.
-    NTCUC_CopyInit,
-    // Assignment.
-    NTCUC_Assignment,
-    // Compound literal.
-    NTCUC_CompoundLiteral,
-    // Block capture.
-    NTCUC_BlockCapture,
-    // lvalue-to-rvalue conversion of volatile type.
-    NTCUC_LValueToRValueVolatile,
-  };
-
-  /// Emit diagnostics if the initializer or any of its explicit or
-  /// implicitly-generated subexpressions require copying or
-  /// default-initializing a type that is or contains a C union type that is
-  /// non-trivial to copy or default-initialize.
-  void checkNonTrivialCUnionInInitializer(const Expr *Init, SourceLocation Loc);
-
-  // These flags are passed to checkNonTrivialCUnion.
-  enum NonTrivialCUnionKind {
-    NTCUK_Init = 0x1,
-    NTCUK_Destruct = 0x2,
-    NTCUK_Copy = 0x4,
-  };
-
-  /// Emit diagnostics if a non-trivial C union type or a struct that contains
-  /// a non-trivial C union is used in an invalid context.
-  void checkNonTrivialCUnion(QualType QT, SourceLocation Loc,
-                             NonTrivialCUnionContext UseContext,
-                             unsigned NonTrivialKind);
-
   void AddInitializerToDecl(Decl *dcl, Expr *init, bool DirectInit);
   void ActOnUninitializedDecl(Decl *dcl);
   void ActOnInitializerError(Decl *Dcl);

Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=367076&r1=367075&r2=367076&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Thu Jul 25 17:02:17 2019
@@ -4252,9 +4252,6 @@ RecordDecl::RecordDecl(Kind DK, TagKind
   setNonTrivialToPrimitiveDefaultInitialize(false);
   setNonTrivialToPrimitiveCopy(false);
   setNonTrivialToPrimitiveDestroy(false);
-  setHasNonTrivialToPrimitiveDefaultInitializeCUnion(false);
-  setHasNonTrivialToPrimitiveDestructCUnion(false);
-  setHasNonTrivialToPrimitiveCopyCUnion(false);
   setParamDestroyedInCallee(false);
   setArgPassingRestrictions(APK_CanPassInRegs);
 }

Modified: cfe/trunk/lib/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=367076&r1=367075&r2=367076&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Type.cpp (original)
+++ cfe/trunk/lib/AST/Type.cpp Thu Jul 25 17:02:17 2019
@@ -2276,16 +2276,60 @@ bool QualType::isNonWeakInMRRWithObjCWea
          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 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::hasNonTrivialToPrimitiveCopyCUnion(const RecordDecl *RD) {
-  return RD->hasNonTrivialToPrimitiveCopyCUnion();
+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

Modified: cfe/trunk/lib/Sema/Sema.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.cpp?rev=367076&r1=367075&r2=367076&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.cpp (original)
+++ cfe/trunk/lib/Sema/Sema.cpp Thu Jul 25 17:02:17 2019
@@ -1658,24 +1658,12 @@ static void markEscapingByrefs(const Fun
   // 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);
     }
   }
 

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=367076&r1=367075&r2=367076&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Thu Jul 25 17:02:17 2019
@@ -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 @@ NamedDecl *Sema::ActOnVariableDeclarator
 
     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 @@ Sema::ActOnFunctionDeclarator(Scope *S,
             << 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 @@ bool Sema::DeduceVariableDeclarationType
   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 @@ void Sema::AddInitializerToDecl(Decl *Re
       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 @@ void Sema::ActOnUninitializedDecl(Decl *
       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 @@ ParmVarDecl *Sema::CheckParameter(DeclCo
                                          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 @@ void Sema::ActOnFields(Scope *S, SourceL
   // 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 @@ void Sema::ActOnFields(Scope *S, SourceL
         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 @@ void Sema::ActOnFields(Scope *S, SourceL
 
     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>()) {

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=367076&r1=367075&r2=367076&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Thu Jul 25 17:02:17 2019
@@ -6076,7 +6076,7 @@ Sema::BuildCompoundLiteralExpr(SourceLoc
         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 @@ Sema::BuildCompoundLiteralExpr(SourceLoc
     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 @@ ExprResult Sema::CreateBuiltinBinOp(Sour
           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 @@ ExprResult Sema::ActOnBlockStmtExpr(Sour
       !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 @@ static ExprResult rebuildPotentialResult
 }
 
 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 [...]

Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=367076&r1=367075&r2=367076&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Thu Jul 25 17:02:17 2019
@@ -2456,11 +2456,6 @@ bool Sema::CheckFunctionReturnType(QualT
     return true;
   }
 
-  if (T.hasNonTrivialToPrimitiveDestructCUnion() ||
-      T.hasNonTrivialToPrimitiveCopyCUnion())
-    checkNonTrivialCUnion(T, Loc, NTCUC_FunctionReturn,
-                          NTCUK_Destruct|NTCUK_Copy);
-
   return false;
 }
 

Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=367076&r1=367075&r2=367076&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Thu Jul 25 17:02:17 2019
@@ -794,9 +794,6 @@ ASTDeclReader::VisitRecordDeclImpl(Recor
   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;

Modified: cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterDecl.cpp?rev=367076&r1=367075&r2=367076&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriterDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriterDecl.cpp Thu Jul 25 17:02:17 2019
@@ -476,9 +476,6 @@ void ASTDeclWriter::VisitRecordDecl(Reco
   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 @@ void ASTWriter::WriteDeclAbbrevs() {
   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

Added: cfe/trunk/test/CodeGenObjC/Inputs/strong_in_union.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/Inputs/strong_in_union.h?rev=367076&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenObjC/Inputs/strong_in_union.h (added)
+++ cfe/trunk/test/CodeGenObjC/Inputs/strong_in_union.h Thu Jul 25 17:02:17 2019
@@ -0,0 +1,10 @@
+#ifndef STRONG_IN_UNION_H
+#define STRONG_IN_UNION_H
+#pragma clang system_header
+
+typedef union {
+  id f0;
+  int *f1;
+} U;
+
+#endif // STRONG_IN_UNION_H

Modified: cfe/trunk/test/CodeGenObjC/strong-in-c-struct.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/strong-in-c-struct.m?rev=367076&r1=367075&r2=367076&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenObjC/strong-in-c-struct.m (original)
+++ cfe/trunk/test/CodeGenObjC/strong-in-c-struct.m Thu Jul 25 17:02:17 2019
@@ -1,10 +1,11 @@
-// RUN: %clang_cc1 -triple arm64-apple-ios11 -fobjc-arc -fblocks  -fobjc-runtime=ios-11.0 -emit-llvm -o - -DUSESTRUCT %s | FileCheck %s
+// RUN: %clang_cc1 -triple arm64-apple-ios11 -fobjc-arc -fblocks  -fobjc-runtime=ios-11.0 -emit-llvm -o - -DUSESTRUCT -I %S/Inputs %s | FileCheck %s
 
-// RUN: %clang_cc1 -triple arm64-apple-ios11 -fobjc-arc -fblocks  -fobjc-runtime=ios-11.0 -emit-pch -o %t %s
-// RUN: %clang_cc1 -triple arm64-apple-ios11 -fobjc-arc -fblocks  -fobjc-runtime=ios-11.0 -include-pch %t -emit-llvm -o - -DUSESTRUCT %s | FileCheck %s
+// RUN: %clang_cc1 -triple arm64-apple-ios11 -fobjc-arc -fblocks  -fobjc-runtime=ios-11.0 -emit-pch -I %S/Inputs -o %t %s
+// RUN: %clang_cc1 -triple arm64-apple-ios11 -fobjc-arc -fblocks  -fobjc-runtime=ios-11.0 -include-pch %t -emit-llvm -o - -DUSESTRUCT -I %S/Inputs %s | FileCheck %s
 
 #ifndef HEADER
 #define HEADER
+#include "strong_in_union.h"
 
 typedef void (^BlockTy)(void);
 
@@ -694,6 +695,14 @@ void test_copy_constructor_Bitfield1(Bit
   Bitfield1 t = *a;
 }
 
+// CHECK: define void @test_strong_in_union()
+// CHECK: alloca %{{.*}}
+// CHECK-NEXT: ret void
+
+void test_strong_in_union() {
+  U t;
+}
+
 // CHECK: define void @test_copy_constructor_VolatileArray(
 // CHECK: call void @__copy_constructor_8_8_s0_AB8s4n16_tv64w32_AE(
 

Removed: cfe/trunk/test/PCH/non-trivial-c-union.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/non-trivial-c-union.m?rev=367075&view=auto
==============================================================================
--- cfe/trunk/test/PCH/non-trivial-c-union.m (original)
+++ cfe/trunk/test/PCH/non-trivial-c-union.m (removed)
@@ -1,24 +0,0 @@
-// RUN: %clang_cc1 -fblocks -fobjc-arc -fobjc-runtime-has-weak -emit-pch -o %t.pch %s
-// RUN: %clang_cc1 -fblocks -fobjc-arc -fobjc-runtime-has-weak -include-pch %t.pch -verify %s
-
-#ifndef HEADER
-#define HEADER
-
-typedef union {
-  id f0;
-} U0;
-
-#else
-
-// expected-note at -6 {{'U0' has subobjects that are non-trivial to destruct}}
-// expected-note at -7 {{'U0' has subobjects that are non-trivial to copy}}
-// expected-note at -8 {{'U0' has subobjects that are non-trivial to default-initialize}}
-// expected-note at -8 {{f0 has type '__strong id' that is non-trivial to destruct}}
-// expected-note at -9 {{f0 has type '__strong id' that is non-trivial to copy}}
-// expected-note at -10 {{f0 has type '__strong id' that is non-trivial to default-initialize}}
-
-U0 foo0(void); // expected-error {{cannot use type 'U0' for function/method return since it is a union that is non-trivial to destruct}} expected-error {{cannot use type 'U0' for function/method return since it is a union that is non-trivial to copy}}
-
-U0 g0; // expected-error {{cannot default-initialize an object of type 'U0' since it is a union that is non-trivial to default-initialize}}
-
-#endif

Modified: cfe/trunk/test/SemaObjC/arc-decls.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/arc-decls.m?rev=367076&r1=367075&r2=367076&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/arc-decls.m (original)
+++ cfe/trunk/test/SemaObjC/arc-decls.m Thu Jul 25 17:02:17 2019
@@ -8,7 +8,11 @@ struct A {
 };
 
 union u {
-  id u;
+    id u; // expected-error {{ARC forbids Objective-C objects in union}}
+};
+
+union u_nontrivial_c {
+  struct A a; // expected-error {{non-trivial C types are disallowed in union}}
 };
 
 // Volatile fields are fine.

Removed: cfe/trunk/test/SemaObjC/non-trivial-c-union.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/non-trivial-c-union.m?rev=367075&view=auto
==============================================================================
--- cfe/trunk/test/SemaObjC/non-trivial-c-union.m (original)
+++ cfe/trunk/test/SemaObjC/non-trivial-c-union.m (removed)
@@ -1,82 +0,0 @@
-// RUN: %clang_cc1 -fsyntax-only -fblocks -fobjc-arc -fobjc-runtime-has-weak -verify %s
-
-typedef union { // expected-note 12 {{'U0' has subobjects that are non-trivial to default-initialize}} expected-note 36 {{'U0' has subobjects that are non-trivial to destruct}} expected-note 28 {{'U0' has subobjects that are non-trivial to copy}}
-  id f0; // expected-note 12 {{f0 has type '__strong id' that is non-trivial to default-initialize}} expected-note 36 {{f0 has type '__strong id' that is non-trivial to destruct}} expected-note 28 {{f0 has type '__strong id' that is non-trivial to copy}}
-  __weak id f1; // expected-note 12 {{f1 has type '__weak id' that is non-trivial to default-initialize}} expected-note 36 {{f1 has type '__weak id' that is non-trivial to destruct}} expected-note 28 {{f1 has type '__weak id' that is non-trivial to copy}}
-} U0;
-
-typedef struct {
-  U0 f0;
-  id f1;
-} S0;
-
-id g0;
-U0 ug0; // expected-error {{cannot default-initialize an object of type 'U0' since it is a union that is non-trivial to default-initialize}}
-U0 ug1 = { .f0 = 0 };
-S0 sg0; // expected-error {{cannot default-initialize an object of type 'S0' since it contains a union that is non-trivial to default-initialize}}
-S0 sg1 = { .f0 = {0}, .f1 = 0 };
-S0 sg2 = { .f1 = 0 }; // expected-error {{cannot default-initialize an object of type 'U0' since it is a union that is non-trivial to default-initialize}}
-
-U0 foo0(U0); // expected-error {{cannot use type 'U0' for a function/method parameter since it is a union that is non-trivial to destruct}} expected-error {{cannot use type 'U0' for a function/method parameter since it is a union that is non-trivial to copy}} expected-error {{cannot use type 'U0' for function/method return since it is a union that is non-trivial to destruct}} expected-error {{cannot use type 'U0' for function/method return since it is a union that is non-trivial to copy}}
-S0 foo1(S0); // expected-error {{cannot use type 'S0' for a function/method parameter since it contains a union that is non-trivial to destruct}} expected-error {{cannot use type 'S0' for a function/method parameter since it contains a union that is non-trivial to copy}} expected-error {{cannot use type 'S0' for function/method return since it contains a union that is non-trivial to destruct}} expected-error {{cannot use type 'S0' for function/method return since it contains a union that is non-trivial to copy}}
-
- at interface C
--(U0)m0:(U0)arg; // expected-error {{cannot use type 'U0' for a function/method parameter since it is a union that is non-trivial to destruct}} expected-error {{cannot use type 'U0' for a function/method parameter since it is a union that is non-trivial to copy}} expected-error {{cannot use type 'U0' for function/method return since it is a union that is non-trivial to destruct}} expected-error {{cannot use type 'U0' for function/method return since it is a union that is non-trivial to copy}}
--(S0)m1:(S0)arg; // expected-error {{cannot use type 'S0' for a function/method parameter since it contains a union that is non-trivial to destruct}} expected-error {{cannot use type 'S0' for a function/method parameter since it contains a union that is non-trivial to copy}} expected-error {{cannot use type 'S0' for function/method return since it contains a union that is non-trivial to destruct}} expected-error {{cannot use type 'S0' for function/method return since it contains a union that is non-trivial to copy}}
- at end
-
-void testBlockFunction(void) {
-  (void)^(U0 a){ return ug0; }; // expected-error {{cannot use type 'U0' for a function/method parameter since it is a union that is non-trivial to destruct}} expected-error {{cannot use type 'U0' for a function/method parameter since it is a union that is non-trivial to copy}} expected-error {{cannot use type 'U0' for function/method return since it is a union that is non-trivial to destruct}} expected-error {{cannot use type 'U0' for function/method return since it is a union that is non-trivial to copy}}
-  (void)^(S0 a){ return sg0; }; // expected-error {{cannot use type 'S0' for a function/method parameter since it contains a union that is non-trivial to destruct}} expected-error {{cannot use type 'S0' for a function/method parameter since it contains a union that is non-trivial to copy}} expected-error {{cannot use type 'S0' for function/method return since it contains a union that is non-trivial to destruct}} expected-error {{cannot use type 'S0' for function/method return since it contains a union that is non-trivial to copy}}
-}
-void testAutoVar(void) {
-  U0 u0; // expected-error {{cannot declare an automatic variable of type 'U0' since it is a union that is non-trivial to destruct}} expected-error {{cannot default-initialize an object of type 'U0' since it is a union that is non-trivial to default-initialize}}
-  U0 u1 = ug0; // expected-error {{cannot declare an automatic variable of type 'U0' since it is a union that is non-trivial to destruct}} expected-error {{cannot copy-initialize an object of type 'U0' since it is a union that is non-trivial to copy}}
-  U0 u2 = { g0 }; // expected-error {{cannot declare an automatic variable of type 'U0' since it is a union that is non-trivial to destruct}}
-  U0 u3 = { .f1 = g0 }; // expected-error {{cannot declare an automatic variable of type 'U0' since it is a union that is non-trivial to destruct}}
-  S0 s0; // expected-error {{cannot declare an automatic variable of type 'S0' since it contains a union that is non-trivial to destruct}} expected-error {{cannot default-initialize an object of type 'S0' since it contains a union that is non-trivial to default-initialize}}
-  S0 s1 = sg0; // expected-error {{declare an automatic variable of type 'S0' since it contains a union that is non-trivial to destruct}} expected-error {{cannot copy-initialize an object of type 'S0' since it contains a union that is non-trivial to copy}}
-  S0 s2 = { ug0 }; // expected-error {{cannot declare an automatic variable of type 'S0' since it contains a union that is non-trivial to destruct}} expected-error {{cannot copy-initialize an object of type 'U0' since it is a union that is non-trivial to copy}}
-  S0 s3 = { .f0 = ug0 }; // expected-error {{cannot declare an automatic variable of type 'S0' since it contains a union that is non-trivial to destruct}} expected-error {{cannot copy-initialize an object of type 'U0' since it is a union that is non-trivial to copy}}
-  S0 s4 = { .f1 = g0 }; // expected-error {{cannot declare an automatic variable of type 'S0' since it contains a union that is non-trivial to destruct}} expected-error {{cannot default-initialize an object of type 'U0' since it is a union that is non-trivial to default-initialize}}
-}
-
-void testAssignment(void) {
-  ug0 = ug1; // expected-error {{cannot assign to a variable of type 'U0' since it is a union that is non-trivial to copy}}
-  sg0 = sg1; // expected-error {{cannot assign to a variable of type 'S0' since it contains a union that is non-trivial to copy}}
-}
-
-U0 ug2 = (U0){ .f1 = 0 }; // expected-error {{cannot copy-initialize an object of type 'U0' since it is a union that is non-trivial to copy}}
-S0 sg3 = (S0){ .f0 = {0}, .f1 = 0 }; // expected-error {{cannot copy-initialize an object of type 'S0' since it contains a union that is non-trivial to copy}}
-S0 *sg4 = &(S0){ .f1 = 0 }; // expected-error {{cannot default-initialize an object of type 'U0' since it is a union that is non-trivial to default-initialize}}
-
-void testCompoundLiteral(void) {
-  const U0 *t0 = &(U0){ .f0 = g0 }; // expected-error {{cannot construct an automatic compound literal of type 'U0' since it is a union that is non-trivial to destruct}}
-  const U0 *t1 = &(U0){ .f1 = g0 }; // expected-error {{cannot construct an automatic compound literal of type 'U0' since it is a union that is non-trivial to destruct}}
-  const S0 *t2 = &(S0){ .f0 = ug0 }; // expected-error {{cannot construct an automatic compound literal of type 'S0' since it contains a union that is non-trivial to destruct}} expected-error {{cannot copy-initialize an object of type 'U0' since it is a union that is non-trivial to copy}}
-  const S0 *t3 = &(S0){ .f1 = g0 }; // expected-error {{cannot construct an automatic compound literal of type 'S0' since it contains a union that is non-trivial to destruct}} expected-error {{cannot default-initialize an object of type 'U0' since it is a union that is non-trivial to default-initialize}}
-}
-
-typedef void (^BlockTy)(void);
-void escapingFunc(BlockTy);
-void noescapingFunc(__attribute__((noescape)) BlockTy);
-
-void testBlockCapture(void) {
-  U0 t0; // expected-error {{cannot declare an automatic variable of type 'U0' since it is a union that is non-trivial to destruct}} expected-error {{cannot default-initialize an object of type 'U0' since it is a union that is non-trivial to default-initialize}}
-  S0 t1; // expected-error {{cannot declare an automatic variable of type 'S0' since it contains a union that is non-trivial to destruct}} expected-error {{cannot default-initialize an object of type 'S0' since it contains a union that is non-trivial to default-initialize}}
-  __block U0 t2; // expected-error {{cannot declare an automatic variable of type 'U0' since it is a union that is non-trivial to destruct}} expected-error {{cannot default-initialize an object of type 'U0' since it is a union that is non-trivial to default-initialize}}
-  __block S0 t3; // expected-error {{cannot declare an automatic variable of type 'S0' since it contains a union that is non-trivial to destruct}} expected-error {{cannot default-initialize an object of type 'S0' since it contains a union that is non-trivial to default-initialize}}
-
-  escapingFunc(^{ g0 = t0.f0; }); // expected-error {{cannot capture a variable of type 'U0' since it is a union that is non-trivial to destruct}} expected-error {{cannot capture a variable of type 'U0' since it is a union that is non-trivial to copy}}
-  escapingFunc(^{ g0 = t1.f0.f0; }); // expected-error {{cannot capture a variable of type 'S0' since it contains a union that is non-trivial to destruct}} expected-error {{cannot capture a variable of type 'S0' since it contains a union that is non-trivial to copy}}
-  escapingFunc(^{ g0 = t2.f0; }); // expected-error {{cannot capture a variable of type 'U0' since it is a union that is non-trivial to destruct}} expected-error {{cannot capture a variable of type 'U0' since it is a union that is non-trivial to copy}}
-  escapingFunc(^{ g0 = t3.f0.f0; }); // expected-error {{cannot capture a variable of type 'S0' since it contains a union that is non-trivial to destruct}} expected-error {{cannot capture a variable of type 'S0' since it contains a union that is non-trivial to copy}}
-  noescapingFunc(^{ g0 = t0.f0; }); // expected-error {{cannot capture a variable of type 'U0' since it is a union that is non-trivial to destruct}} expected-error {{cannot capture a variable of type 'U0' since it is a union that is non-trivial to copy}}
-  noescapingFunc(^{ g0 = t1.f0.f0; }); // expected-error {{cannot capture a variable of type 'S0' since it contains a union that is non-trivial to destruct}} expected-error {{cannot capture a variable of type 'S0' since it contains a union that is non-trivial to copy}}
-  noescapingFunc(^{ g0 = t2.f0; });
-  noescapingFunc(^{ g0 = t3.f0.f0; });
-}
-
-void testVolatileLValueToRValue(volatile U0 *a) {
-  (void)*a; // expected-error {{cannot use volatile type 'volatile U0' where it causes an lvalue-to-rvalue conversion since it is a union that is non-trivial to destruct}} // expected-error {{cannot use volatile type 'volatile U0' where it causes an lvalue-to-rvalue conversion since it is a union that is non-trivial to copy}}
-}




More information about the cfe-commits mailing list