[cfe-commits] r151465 - in /cfe/trunk: 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

Richard Smith richard-llvm at metafoo.co.uk
Sat Feb 25 16:31:34 PST 2012


Author: rsmith
Date: Sat Feb 25 18:31:33 2012
New Revision: 151465

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

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

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=151465&r1=151464&r2=151465&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Sat Feb 25 18:31:33 2012
@@ -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) {

Modified: cfe/trunk/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp?rev=151465&r1=151464&r2=151465&view=diff
==============================================================================
--- cfe/trunk/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp (original)
+++ cfe/trunk/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp Sat Feb 25 18:31:33 2012
@@ -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;

Modified: cfe/trunk/test/CXX/special/class.ctor/p5-0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/special/class.ctor/p5-0x.cpp?rev=151465&r1=151464&r2=151465&view=diff
==============================================================================
--- cfe/trunk/test/CXX/special/class.ctor/p5-0x.cpp (original)
+++ cfe/trunk/test/CXX/special/class.ctor/p5-0x.cpp Sat Feb 25 18:31:33 2012
@@ -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");
-

Modified: cfe/trunk/test/CodeGenCXX/constructor-init.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/constructor-init.cpp?rev=151465&r1=151464&r2=151465&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/constructor-init.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/constructor-init.cpp Sat Feb 25 18:31:33 2012
@@ -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 @@
   }
 
 }
-

Modified: cfe/trunk/test/CodeGenCXX/pr9965.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/pr9965.cpp?rev=151465&r1=151464&r2=151465&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/pr9965.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/pr9965.cpp Sat Feb 25 18:31:33 2012
@@ -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

Modified: cfe/trunk/test/SemaCXX/type-traits.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/type-traits.cpp?rev=151465&r1=151464&r2=151465&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/type-traits.cpp (original)
+++ cfe/trunk/test/SemaCXX/type-traits.cpp Sat Feb 25 18:31:33 2012
@@ -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&&)))]; }
 }
 





More information about the cfe-commits mailing list