Special members which are defaulted or deleted on their first declaration are
trivial if the implicit declaration would be. Don't forget to set the Trivial
flag on the special member as well as on the class. It doesn't seem ideal that
we have two separate mechanisms for storing this information, but this patch
does not attempt to address that.

This leaves us in an interesting position where the has_trivial_X trait for a
class says 'yes' for a deleted but trivial X, but is_trivially_Xable says 'no'.
This seems to be what the standard requires.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@151465 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 1f5255d..9a31dd8 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -3871,6 +3871,10 @@
     // FIXME: a compatible, but different, explicit exception specification
     // will be silently overridden. We should issue a warning if this happens.
     EPI.ExtInfo = CtorType->getExtInfo();
+
+    // Such a function is also trivial if the implicitly-declared function
+    // would have been.
+    CD->setTrivial(CD->getParent()->hasTrivialDefaultConstructor());
   }
 
   if (HadError) {
@@ -3966,6 +3970,10 @@
     //  -- [...] it shall have the same parameter type as if it had been
     //     implicitly declared.
     CD->setType(Context.getFunctionType(Context.VoidTy, &ArgType, 1, EPI));
+
+    // Such a function is also trivial if the implicitly-declared function
+    // would have been.
+    CD->setTrivial(CD->getParent()->hasTrivialCopyConstructor());
   }
 
   if (HadError) {
@@ -4053,6 +4061,10 @@
     EPI.RefQualifier = OperType->getRefQualifier();
     EPI.ExtInfo = OperType->getExtInfo();
     MD->setType(Context.getFunctionType(ReturnType, &ArgType, 1, EPI));
+
+    // Such a function is also trivial if the implicitly-declared function
+    // would have been.
+    MD->setTrivial(MD->getParent()->hasTrivialCopyAssignment());
   }
 
   if (HadError) {
@@ -4146,6 +4158,10 @@
     //  -- [...] it shall have the same parameter type as if it had been
     //     implicitly declared.
     CD->setType(Context.getFunctionType(Context.VoidTy, &ArgType, 1, EPI));
+
+    // Such a function is also trivial if the implicitly-declared function
+    // would have been.
+    CD->setTrivial(CD->getParent()->hasTrivialMoveConstructor());
   }
 
   if (HadError) {
@@ -4231,6 +4247,10 @@
     EPI.RefQualifier = OperType->getRefQualifier();
     EPI.ExtInfo = OperType->getExtInfo();
     MD->setType(Context.getFunctionType(ReturnType, &ArgType, 1, EPI));
+
+    // Such a function is also trivial if the implicitly-declared function
+    // would have been.
+    MD->setTrivial(MD->getParent()->hasTrivialMoveAssignment());
   }
 
   if (HadError) {
@@ -4278,6 +4298,10 @@
     // There are no parameters.
     EPI.ExtInfo = DtorType->getExtInfo();
     DD->setType(Context.getFunctionType(Context.VoidTy, 0, 0, EPI));
+
+    // Such a function is also trivial if the implicitly-declared function
+    // would have been.
+    DD->setTrivial(DD->getParent()->hasTrivialDestructor());
   }
 
   if (ShouldDeleteSpecialMember(DD, CXXDestructor)) {
@@ -10254,6 +10278,35 @@
     // recovery.
   }
   Fn->setDeletedAsWritten();
+
+  CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Dcl);
+  if (!MD)
+    return;
+
+  // A deleted special member function is trivial if the corresponding
+  // implicitly-declared function would have been.
+  switch (getSpecialMember(MD)) {
+  case CXXInvalid:
+    break;
+  case CXXDefaultConstructor:
+    MD->setTrivial(MD->getParent()->hasTrivialDefaultConstructor());
+    break;
+  case CXXCopyConstructor:
+    MD->setTrivial(MD->getParent()->hasTrivialCopyConstructor());
+    break;
+  case CXXMoveConstructor:
+    MD->setTrivial(MD->getParent()->hasTrivialMoveConstructor());
+    break;
+  case CXXCopyAssignment:
+    MD->setTrivial(MD->getParent()->hasTrivialCopyAssignment());
+    break;
+  case CXXMoveAssignment:
+    MD->setTrivial(MD->getParent()->hasTrivialMoveAssignment());
+    break;
+  case CXXDestructor:
+    MD->setTrivial(MD->getParent()->hasTrivialDestructor());
+    break;
+  }
 }
 
 void Sema::SetDeclDefaulted(Decl *Dcl, SourceLocation DefaultLoc) {
diff --git a/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp b/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp
index d401a97..06dd1bb 100644
--- a/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp
+++ b/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp
@@ -35,7 +35,8 @@
 };
 constexpr S3 s3a = S3(0);
 constexpr S3 s3b = s3a;
-constexpr S3 s3c = S3(); // expected-error {{constant expression}} expected-note {{non-constexpr constructor}}
+constexpr S3 s3c = S3();
+constexpr S3 s3d; // expected-error {{constant expression}} expected-note {{non-constexpr constructor}}
 
 struct S4 {
   S4() = default;
diff --git a/test/CXX/special/class.ctor/p5-0x.cpp b/test/CXX/special/class.ctor/p5-0x.cpp
index b2fa0cf..b81755d 100644
--- a/test/CXX/special/class.ctor/p5-0x.cpp
+++ b/test/CXX/special/class.ctor/p5-0x.cpp
@@ -25,10 +25,8 @@
 Deleted1a d1a; // expected-error {{implicitly-deleted default constructor}}
 union NotDeleted1a { DefaultedDefCtor1 nu; };
 NotDeleted1a nd1a;
-// FIXME: clang implements the pre-FDIS rule, under which DefaultedDefCtor2's
-// default constructor is non-trivial.
-union NotDeleted1b { DefaultedDefCtor2 nu; }; // unexpected-note {{defined here}}
-NotDeleted1b nd1b; // unexpected-error {{implicitly-deleted default constructor}}
+union NotDeleted1b { DefaultedDefCtor2 nu; };
+NotDeleted1b nd1b;
 
 // - any non-static data member with no brace-or-equal-initializer is of
 // reference type,
@@ -170,4 +168,3 @@
 
 template<typename T> class Trivial5 { Trivial5() = delete; };
 static_assert(__has_trivial_constructor(Trivial5<int>), "Trivial5 is trivial");
-
diff --git a/test/CodeGenCXX/constructor-init.cpp b/test/CodeGenCXX/constructor-init.cpp
index 6af5188..9f808f6 100644
--- a/test/CodeGenCXX/constructor-init.cpp
+++ b/test/CodeGenCXX/constructor-init.cpp
@@ -201,7 +201,7 @@
     pair2(const pair2&) = default;
   };
 
-  struct pair {
+  struct pair : X { // Make the copy constructor non-trivial, so we actually generate it.
     int second[4];
     // CHECK-PR10720: define linkonce_odr void @_ZN7PR107204pairC2ERKS0_
     // CHECK-PR10720-NOT: ret
@@ -220,4 +220,3 @@
   }
 
 }
-
diff --git a/test/CodeGenCXX/pr9965.cpp b/test/CodeGenCXX/pr9965.cpp
index f625f48..0d267ff 100644
--- a/test/CodeGenCXX/pr9965.cpp
+++ b/test/CodeGenCXX/pr9965.cpp
@@ -1,6 +1,7 @@
 // RUN: %clang_cc1 -std=c++11 -emit-llvm -o - %s | FileCheck %s
+struct A { A(); };
 template<typename T>
-struct X
+struct X : A // default constructor is not trivial
 {
     X() = default;
     ~X() {} // not a literal type
diff --git a/test/SemaCXX/type-traits.cpp b/test/SemaCXX/type-traits.cpp
index fd41c17..f53939a 100644
--- a/test/SemaCXX/type-traits.cpp
+++ b/test/SemaCXX/type-traits.cpp
@@ -932,6 +932,41 @@
   NonTCStruct(const NonTCStruct&) {}
 };
 
+struct AllDefaulted {
+  AllDefaulted() = default;
+  AllDefaulted(const AllDefaulted &) = default;
+  AllDefaulted(AllDefaulted &&) = default;
+  AllDefaulted &operator=(const AllDefaulted &) = default;
+  AllDefaulted &operator=(AllDefaulted &&) = default;
+  ~AllDefaulted() = default;
+};
+
+struct AllDeleted {
+  AllDeleted() = delete;
+  AllDeleted(const AllDeleted &) = delete;
+  AllDeleted(AllDeleted &&) = delete;
+  AllDeleted &operator=(const AllDeleted &) = delete;
+  AllDeleted &operator=(AllDeleted &&) = delete;
+  ~AllDeleted() = delete;
+};
+
+struct ExtDefaulted {
+  ExtDefaulted();
+  ExtDefaulted(const ExtDefaulted &);
+  ExtDefaulted(ExtDefaulted &&);
+  ExtDefaulted &operator=(const ExtDefaulted &);
+  ExtDefaulted &operator=(ExtDefaulted &&);
+  ~ExtDefaulted();
+};
+
+// Despite being defaulted, these functions are not trivial.
+ExtDefaulted::ExtDefaulted() = default;
+ExtDefaulted::ExtDefaulted(const ExtDefaulted &) = default;
+ExtDefaulted::ExtDefaulted(ExtDefaulted &&) = default;
+ExtDefaulted &ExtDefaulted::operator=(const ExtDefaulted &) = default;
+ExtDefaulted &ExtDefaulted::operator=(ExtDefaulted &&) = default;
+ExtDefaulted::~ExtDefaulted() = default;
+
 void is_trivial2()
 {
   int t01[T(__is_trivial(char))];
@@ -956,11 +991,14 @@
   int t20[T(__is_trivial(Union))];
   int t21[T(__is_trivial(UnionAr))];
   int t22[T(__is_trivial(TrivialStruct))];
+  int t23[T(__is_trivial(AllDefaulted))];
+  int t24[T(__is_trivial(AllDeleted))];
 
   int t30[F(__is_trivial(void))];
   int t31[F(__is_trivial(NonTrivialStruct))];
   int t32[F(__is_trivial(SuperNonTrivialStruct))];
   int t33[F(__is_trivial(NonTCStruct))];
+  int t34[F(__is_trivial(ExtDefaulted))];
 }
 
 void is_trivially_copyable2()
@@ -988,10 +1026,13 @@
   int t21[T(__is_trivially_copyable(UnionAr))];
   int t22[T(__is_trivially_copyable(TrivialStruct))];
   int t23[T(__is_trivially_copyable(NonTrivialStruct))];
+  int t24[T(__is_trivially_copyable(AllDefaulted))];
+  int t25[T(__is_trivially_copyable(AllDeleted))];
 
   int t30[F(__is_trivially_copyable(void))];
-  int t32[F(__is_trivially_copyable(SuperNonTrivialStruct))];
-  int t31[F(__is_trivially_copyable(NonTCStruct))];
+  int t31[F(__is_trivially_copyable(SuperNonTrivialStruct))];
+  int t32[F(__is_trivially_copyable(NonTCStruct))];
+  int t33[F(__is_trivially_copyable(ExtDefaulted))];
 }
 
 struct CStruct {
@@ -1147,6 +1188,8 @@
   { int arr[T(__has_trivial_constructor(HasCopyAssign))]; }
   { int arr[T(__has_trivial_constructor(HasMoveAssign))]; }
   { int arr[T(__has_trivial_constructor(const Int))]; }
+  { int arr[T(__has_trivial_constructor(AllDefaulted))]; }
+  { int arr[T(__has_trivial_constructor(AllDeleted))]; }
 
   { int arr[F(__has_trivial_constructor(HasCons))]; }
   { int arr[F(__has_trivial_constructor(HasRef))]; }
@@ -1157,6 +1200,7 @@
   { int arr[F(__has_trivial_constructor(cvoid))]; }
   { int arr[F(__has_trivial_constructor(HasTemplateCons))]; }
   { int arr[F(__has_trivial_constructor(AllPrivate))]; }
+  { int arr[F(__has_trivial_constructor(ExtDefaulted))]; }
 }
 
 void has_trivial_copy_constructor() {
@@ -1177,6 +1221,8 @@
   { int arr[T(__has_trivial_copy(HasCopyAssign))]; }
   { int arr[T(__has_trivial_copy(HasMoveAssign))]; }
   { int arr[T(__has_trivial_copy(const Int))]; }
+  { int arr[T(__has_trivial_copy(AllDefaulted))]; }
+  { int arr[T(__has_trivial_copy(AllDeleted))]; }
 
   { int arr[F(__has_trivial_copy(HasCopy))]; }
   { int arr[F(__has_trivial_copy(HasTemplateCons))]; }
@@ -1185,6 +1231,7 @@
   { int arr[F(__has_trivial_copy(void))]; }
   { int arr[F(__has_trivial_copy(cvoid))]; }
   { int arr[F(__has_trivial_copy(AllPrivate))]; }
+  { int arr[F(__has_trivial_copy(ExtDefaulted))]; }
 }
 
 void has_trivial_copy_assignment() {
@@ -1201,6 +1248,8 @@
   { int arr[T(__has_trivial_assign(HasCopy))]; }
   { int arr[T(__has_trivial_assign(HasMove))]; }
   { int arr[T(__has_trivial_assign(HasMoveAssign))]; }
+  { int arr[T(__has_trivial_assign(AllDefaulted))]; }
+  { int arr[T(__has_trivial_assign(AllDeleted))]; }
 
   { int arr[F(__has_trivial_assign(IntRef))]; }
   { int arr[F(__has_trivial_assign(HasCopyAssign))]; }
@@ -1212,6 +1261,7 @@
   { int arr[F(__has_trivial_assign(void))]; }
   { int arr[F(__has_trivial_assign(cvoid))]; }
   { int arr[F(__has_trivial_assign(AllPrivate))]; }
+  { int arr[F(__has_trivial_assign(ExtDefaulted))]; }
 }
 
 void has_trivial_destructor() {
@@ -1234,11 +1284,14 @@
   { int arr[T(__has_trivial_destructor(const Int))]; }
   { int arr[T(__has_trivial_destructor(DerivesAr))]; }
   { int arr[T(__has_trivial_destructor(VirtAr))]; }
+  { int arr[T(__has_trivial_destructor(AllDefaulted))]; }
+  { int arr[T(__has_trivial_destructor(AllDeleted))]; }
 
   { int arr[F(__has_trivial_destructor(HasDest))]; }
   { int arr[F(__has_trivial_destructor(void))]; }
   { int arr[F(__has_trivial_destructor(cvoid))]; }
   { int arr[F(__has_trivial_destructor(AllPrivate))]; }
+  { int arr[F(__has_trivial_destructor(ExtDefaulted))]; }
 }
 
 struct A { ~A() {} };
@@ -1460,13 +1513,11 @@
   isBaseOfF<DerivedB<int>, BaseA<int> >();
 }
 
-#if 0
 template<class T, class U>
 class TemplateClass {};
 
 template<class T>
 using TemplateAlias = TemplateClass<T, int>;
-#endif
 
 typedef class Base BaseTypedef;
 
@@ -1474,9 +1525,7 @@
 {
   int t01[T(__is_same(Base, Base))];
   int t02[T(__is_same(Base, BaseTypedef))];
-#if 0
   int t03[T(__is_same(TemplateClass<int, int>, TemplateAlias<int>))];
-#endif
 
   int t10[F(__is_same(Base, const Base))];
   int t11[F(__is_same(Base, Base&))];
@@ -1668,10 +1717,25 @@
                                             const NonTrivialDefault&)))]; }
   { int arr[T((__is_trivially_constructible(NonTrivialDefault,
                                             NonTrivialDefault&&)))]; }
+  { int arr[T((__is_trivially_constructible(AllDefaulted)))]; }
+  { int arr[T((__is_trivially_constructible(AllDefaulted,
+                                            const AllDefaulted &)))]; }
+  { int arr[T((__is_trivially_constructible(AllDefaulted,
+                                            AllDefaulted &&)))]; }
 
   { int arr[F((__is_trivially_constructible(int, int*)))]; }
   { int arr[F((__is_trivially_constructible(NonTrivialDefault)))]; }
   { int arr[F((__is_trivially_constructible(ThreeArgCtor, int*, char*, int&)))]; }
+  { int arr[F((__is_trivially_constructible(AllDeleted)))]; }
+  { int arr[F((__is_trivially_constructible(AllDeleted,
+                                            const AllDeleted &)))]; }
+  { int arr[F((__is_trivially_constructible(AllDeleted,
+                                            AllDeleted &&)))]; }
+  { int arr[F((__is_trivially_constructible(ExtDefaulted)))]; }
+  { int arr[F((__is_trivially_constructible(ExtDefaulted,
+                                            const ExtDefaulted &)))]; }
+  { int arr[F((__is_trivially_constructible(ExtDefaulted,
+                                            ExtDefaulted &&)))]; }
 
   { int arr[T((__is_trivially_assignable(int&, int)))]; }
   { int arr[T((__is_trivially_assignable(int&, int&)))]; }
@@ -1682,6 +1746,10 @@
   { int arr[T((__is_trivially_assignable(POD&, POD&&)))]; }
   { int arr[T((__is_trivially_assignable(POD&, const POD&)))]; }
   { int arr[T((__is_trivially_assignable(int*&, int*)))]; }
+  { int arr[T((__is_trivially_assignable(AllDefaulted,
+                                         const AllDefaulted &)))]; }
+  { int arr[T((__is_trivially_assignable(AllDefaulted,
+                                         AllDefaulted &&)))]; }
 
   { int arr[F((__is_trivially_assignable(int*&, float*)))]; }
   { int arr[F((__is_trivially_assignable(HasCopyAssign&, HasCopyAssign)))]; }
@@ -1692,18 +1760,22 @@
                                         TrivialMoveButNotCopy&)))]; }
   { int arr[F((__is_trivially_assignable(TrivialMoveButNotCopy&,
                                         const TrivialMoveButNotCopy&)))]; }
+  { int arr[F((__is_trivially_assignable(AllDeleted,
+                                         const AllDeleted &)))]; }
+  { int arr[F((__is_trivially_assignable(AllDeleted,
+                                         AllDeleted &&)))]; }
+  { int arr[F((__is_trivially_assignable(ExtDefaulted,
+                                         const ExtDefaulted &)))]; }
+  { int arr[F((__is_trivially_assignable(ExtDefaulted,
+                                         ExtDefaulted &&)))]; }
 
-  // FIXME: The following answers are wrong, because we don't properly
-  // mark user-declared constructors/assignment operators/destructors
-  // that are defaulted on their first declaration as trivial when we
-  // can.
-  { int arr[F((__is_trivially_assignable(HasDefaultTrivialCopyAssign&,
+  { int arr[T((__is_trivially_assignable(HasDefaultTrivialCopyAssign&,
                                          HasDefaultTrivialCopyAssign&)))]; }
-  { int arr[F((__is_trivially_assignable(HasDefaultTrivialCopyAssign&,
+  { int arr[T((__is_trivially_assignable(HasDefaultTrivialCopyAssign&,
                                        const HasDefaultTrivialCopyAssign&)))]; }
-  { int arr[F((__is_trivially_assignable(TrivialMoveButNotCopy&,
+  { int arr[T((__is_trivially_assignable(TrivialMoveButNotCopy&,
                                          TrivialMoveButNotCopy)))]; }
-  { int arr[F((__is_trivially_assignable(TrivialMoveButNotCopy&,
+  { int arr[T((__is_trivially_assignable(TrivialMoveButNotCopy&,
                                          TrivialMoveButNotCopy&&)))]; }
 }