"This patch implements the restrictions on union members detailed in
[class.union]p1", from John McCall!


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@76766 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 2b8d0a8..3681709 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -400,19 +400,40 @@
     // C++ [class.ctor]p5:
     //   A constructor is trivial if its class has no virtual base classes.
     Class->setHasTrivialConstructor(false);
+
+    // C++ [class.copy]p6:
+    //   A copy constructor is trivial if its class has no virtual base classes.
+    Class->setHasTrivialCopyConstructor(false);
+
+    // C++ [class.copy]p11:
+    //   A copy assignment operator is trivial if its class has no virtual
+    //   base classes.
+    Class->setHasTrivialCopyAssignment(false);
   } else {
     // C++ [class.ctor]p5:
     //   A constructor is trivial if all the direct base classes of its 
     //   class have trivial constructors.
-    Class->setHasTrivialConstructor(cast<CXXRecordDecl>(BaseDecl)->
-                                    hasTrivialConstructor());
+    if (!cast<CXXRecordDecl>(BaseDecl)->hasTrivialConstructor())
+      Class->setHasTrivialConstructor(false);
+
+    // C++ [class.copy]p6:
+    //   A copy constructor is trivial if all the direct base classes of its
+    //   class have trivial copy constructors.
+    if (!cast<CXXRecordDecl>(BaseDecl)->hasTrivialCopyConstructor())
+      Class->setHasTrivialCopyConstructor(false);
+
+    // C++ [class.copy]p11:
+    //   A copy assignment operator is trivial if all the direct base classes
+    //   of its class have trivial copy assignment operators.
+    if (!cast<CXXRecordDecl>(BaseDecl)->hasTrivialCopyAssignment())
+      Class->setHasTrivialCopyAssignment(false);
   }
 
   // C++ [class.ctor]p3:
   //   A destructor is trivial if all the direct base classes of its class
   //   have trivial destructors.
-  Class->setHasTrivialDestructor(cast<CXXRecordDecl>(BaseDecl)->
-                                 hasTrivialDestructor());
+  if (!cast<CXXRecordDecl>(BaseDecl)->hasTrivialDestructor())
+    Class->setHasTrivialDestructor(false);
   
   // Create the base specifier.
   // FIXME: Allocate via ASTContext?
@@ -1154,30 +1175,6 @@
   if (RD->isAbstract()) 
     AbstractClassUsageDiagnoser(*this, RD);
     
-  if (RD->hasTrivialConstructor() || RD->hasTrivialDestructor()) {
-    for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
-         i != e; ++i) {
-      // All the nonstatic data members must have trivial constructors.
-      QualType FTy = i->getType();
-      while (const ArrayType *AT = Context.getAsArrayType(FTy))
-        FTy = AT->getElementType();
-      
-      if (const RecordType *RT = FTy->getAsRecordType()) {
-        CXXRecordDecl *FieldRD = cast<CXXRecordDecl>(RT->getDecl());
-        
-        if (!FieldRD->hasTrivialConstructor())
-          RD->setHasTrivialConstructor(false);
-        if (!FieldRD->hasTrivialDestructor())
-          RD->setHasTrivialDestructor(false);
-        
-        // If RD has neither a trivial constructor nor a trivial destructor
-        // we don't need to continue checking.
-        if (!RD->hasTrivialConstructor() && !RD->hasTrivialDestructor())
-          break;
-      }
-    }
-  }
-      
   if (!RD->isDependentType())
     AddImplicitlyDeclaredMembersToClass(RD);
 }
@@ -1213,6 +1210,7 @@
                                  /*isImplicitlyDeclared=*/true);
     DefaultCon->setAccess(AS_public);
     DefaultCon->setImplicit();
+    DefaultCon->setTrivial(ClassDecl->hasTrivialConstructor());
     ClassDecl->addDecl(DefaultCon);
   }
 
@@ -1283,6 +1281,7 @@
                                    /*isImplicitlyDeclared=*/true);
     CopyConstructor->setAccess(AS_public);
     CopyConstructor->setImplicit();
+    CopyConstructor->setTrivial(ClassDecl->hasTrivialCopyConstructor());
 
     // Add the parameter to the constructor.
     ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyConstructor,
@@ -1359,6 +1358,7 @@
                             /*isStatic=*/false, /*isInline=*/true);
     CopyAssignment->setAccess(AS_public);
     CopyAssignment->setImplicit();
+    CopyAssignment->setTrivial(ClassDecl->hasTrivialCopyAssignment());
 
     // Add the parameter to the operator.
     ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyAssignment,
@@ -1388,6 +1388,7 @@
                                   /*isImplicitlyDeclared=*/true);
     Destructor->setAccess(AS_public);
     Destructor->setImplicit();
+    Destructor->setTrivial(ClassDecl->hasTrivialDestructor());
     ClassDecl->addDecl(Destructor);
   }
 }