aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Sema/SemaDeclCXX.cpp53
-rw-r--r--test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp3
-rw-r--r--test/CXX/special/class.ctor/p5-0x.cpp7
-rw-r--r--test/CodeGenCXX/constructor-init.cpp3
-rw-r--r--test/CodeGenCXX/pr9965.cpp3
-rw-r--r--test/SemaCXX/type-traits.cpp102
6 files changed, 147 insertions, 24 deletions
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 1f5255dae7..9a31dd8ef8 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -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) {
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 d401a97ca2..06dd1bb055 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 @@ 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;
diff --git a/test/CXX/special/class.ctor/p5-0x.cpp b/test/CXX/special/class.ctor/p5-0x.cpp
index b2fa0cf298..b81755dcd3 100644
--- a/test/CXX/special/class.ctor/p5-0x.cpp
+++ b/test/CXX/special/class.ctor/p5-0x.cpp
@@ -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");
-
diff --git a/test/CodeGenCXX/constructor-init.cpp b/test/CodeGenCXX/constructor-init.cpp
index 6af5188a41..9f808f6680 100644
--- a/test/CodeGenCXX/constructor-init.cpp
+++ b/test/CodeGenCXX/constructor-init.cpp
@@ -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 {
}
}
-
diff --git a/test/CodeGenCXX/pr9965.cpp b/test/CodeGenCXX/pr9965.cpp
index f625f48c33..0d267ff703 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 fd41c17ab2..f53939ac17 100644
--- a/test/SemaCXX/type-traits.cpp
+++ b/test/SemaCXX/type-traits.cpp
@@ -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&&)))]; }
}