]> granicus.if.org Git - clang/commitdiff
Special members which are defaulted or deleted on their first declaration are
authorRichard Smith <richard-llvm@metafoo.co.uk>
Sun, 26 Feb 2012 00:31:33 +0000 (00:31 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Sun, 26 Feb 2012 00:31:33 +0000 (00:31 +0000)
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

lib/Sema/SemaDeclCXX.cpp
test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp
test/CXX/special/class.ctor/p5-0x.cpp
test/CodeGenCXX/constructor-init.cpp
test/CodeGenCXX/pr9965.cpp
test/SemaCXX/type-traits.cpp

index 1f5255dae7ff29f5248b2d49948b14388a9d64db..9a31dd8ef872cf9568fd1946517671df34e01d2d 100644 (file)
@@ -3871,6 +3871,10 @@ void Sema::CheckExplicitlyDefaultedDefaultConstructor(CXXConstructorDecl *CD) {
     // 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 @@ void Sema::CheckExplicitlyDefaultedCopyConstructor(CXXConstructorDecl *CD) {
     //  -- [...] 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 @@ void Sema::CheckExplicitlyDefaultedCopyAssignment(CXXMethodDecl *MD) {
     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 @@ void Sema::CheckExplicitlyDefaultedMoveConstructor(CXXConstructorDecl *CD) {
     //  -- [...] 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 @@ void Sema::CheckExplicitlyDefaultedMoveAssignment(CXXMethodDecl *MD) {
     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 @@ void Sema::CheckExplicitlyDefaultedDestructor(CXXDestructorDecl *DD) {
     // 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 @@ void Sema::SetDeclDeleted(Decl *Dcl, SourceLocation DelLoc) {
     // 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) {
index d401a97ca25cac48c172495d94efb530d76c6e3c..06dd1bb05560b95f1bb0cba0f1ce33920e4330ca 100644 (file)
@@ -35,7 +35,8 @@ struct S3 {
 };
 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;
index b2fa0cf29844914d68fc88c3f3c0693546858f90..b81755dcd33e62de1934fb4d89098e4e2be84755 100644 (file)
@@ -25,10 +25,8 @@ union Deleted1a { UserProvidedDefCtor u; }; // expected-note {{defined here}}
 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 @@ static_assert(__has_trivial_constructor(Trivial4<int>), "Trivial4 is trivial");
 
 template<typename T> class Trivial5 { Trivial5() = delete; };
 static_assert(__has_trivial_constructor(Trivial5<int>), "Trivial5 is trivial");
-
index 6af5188a41f682b86f1a6cab7b87991110be40a5..9f808f6680ed0bcbbad2d21ccd17907165f08660 100644 (file)
@@ -201,7 +201,7 @@ namespace PR10720 {
     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 @@ namespace PR10720 {
   }
 
 }
-
index f625f48c33f6924fecf9d7e893c1780bc9b4d09c..0d267ff70372f43300984812383c5b568bb11523 100644 (file)
@@ -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
index fd41c17ab2768436046f85f2ac2f88c41ab6cc0e..f53939ac1790bf1ee028d881e6382f7a07042b4b 100644 (file)
@@ -932,6 +932,41 @@ struct NonTCStruct {
   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 @@ void is_trivial2()
   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 @@ void is_trivially_copyable2()
   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 @@ void has_trivial_default_constructor() {
   { 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 @@ void has_trivial_default_constructor() {
   { 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 @@ void has_trivial_copy_constructor() {
   { 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 @@ void has_trivial_copy_constructor() {
   { 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 @@ void has_trivial_copy_assignment() {
   { 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 @@ void has_trivial_copy_assignment() {
   { 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 @@ void has_trivial_destructor() {
   { 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 @@ void is_base_of() {
   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 @@ void is_same()
 {
   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 @@ void trivial_checks()
                                             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 @@ void trivial_checks()
   { 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 @@ void trivial_checks()
                                         TrivialMoveButNotCopy&)))]; }
   { int arr[F((__is_trivially_assignable(TrivialMoveButNotCopy&,
                                         const TrivialMoveButNotCopy&)))]; }
-
-  // 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[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 &&)))]; }
+
+  { 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&&)))]; }
 }