aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Sema/SemaDeclCXX.cpp22
-rw-r--r--test/CXX/special/class.copy/p15-0x.cpp23
-rw-r--r--test/CXX/special/class.copy/p15-inclass.cpp42
3 files changed, 80 insertions, 7 deletions
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 52eb9b0d3f..59c5e7894f 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -2633,6 +2633,19 @@ struct BaseAndFieldInfo {
else
IIK = IIK_Default;
}
+
+ bool isImplicitCopyOrMove() const {
+ switch (IIK) {
+ case IIK_Copy:
+ case IIK_Move:
+ return true;
+
+ case IIK_Default:
+ return false;
+ }
+
+ return false;
+ }
};
}
@@ -2678,7 +2691,7 @@ static bool CollectFieldInitializer(Sema &SemaRef, BaseAndFieldInfo &Info,
// C++0x [class.base.init]p8: if the entity is a non-static data member that
// has a brace-or-equal-initializer, the entity is initialized as specified
// in [dcl.init].
- if (Field->hasInClassInitializer()) {
+ if (Field->hasInClassInitializer() && !Info.isImplicitCopyOrMove()) {
CXXCtorInitializer *Init;
if (Indirect)
Init = new (SemaRef.Context) CXXCtorInitializer(SemaRef.Context, Indirect,
@@ -8583,12 +8596,7 @@ Sema::ComputeDefaultedMoveCtorExceptionSpec(CXXRecordDecl *ClassDecl) {
for (RecordDecl::field_iterator F = ClassDecl->field_begin(),
FEnd = ClassDecl->field_end();
F != FEnd; ++F) {
- if (F->hasInClassInitializer()) {
- if (Expr *E = F->getInClassInitializer())
- ExceptSpec.CalledExpr(E);
- else if (!F->isInvalidDecl())
- ExceptSpec.SetDelayed();
- } else if (const RecordType *RecordTy
+ if (const RecordType *RecordTy
= Context.getBaseElementType(F->getType())->getAs<RecordType>()) {
CXXRecordDecl *FieldRecDecl = cast<CXXRecordDecl>(RecordTy->getDecl());
CXXConstructorDecl *Constructor = LookupMovingConstructor(FieldRecDecl);
diff --git a/test/CXX/special/class.copy/p15-0x.cpp b/test/CXX/special/class.copy/p15-0x.cpp
index 32b2714fd7..fff8844255 100644
--- a/test/CXX/special/class.copy/p15-0x.cpp
+++ b/test/CXX/special/class.copy/p15-0x.cpp
@@ -16,3 +16,26 @@ namespace PR10622 {
bar obj2(obj);
}
}
+
+namespace PR11418 {
+ template<typename T>
+ T may_throw() {
+ return T();
+ }
+
+ template<typename T> T &&declval() noexcept;
+
+ struct NonPOD {
+ NonPOD();
+ NonPOD(const NonPOD &) noexcept;
+ NonPOD(NonPOD &&) noexcept;
+ };
+
+ struct X {
+ NonPOD np = may_throw<NonPOD>();
+ };
+
+ static_assert(noexcept(declval<X>()), "noexcept isn't working at all");
+ static_assert(noexcept(X(declval<X&>())), "copy constructor can't throw");
+ static_assert(noexcept(X(declval<X>())), "move constructor can't throw");
+}
diff --git a/test/CXX/special/class.copy/p15-inclass.cpp b/test/CXX/special/class.copy/p15-inclass.cpp
new file mode 100644
index 0000000000..c4f8eafd93
--- /dev/null
+++ b/test/CXX/special/class.copy/p15-inclass.cpp
@@ -0,0 +1,42 @@
+// RUN: %clang_cc1 -std=c++11 -emit-llvm -o - %s | FileCheck %s
+
+namespace PR11418 {
+ struct NonPOD {
+ NonPOD();
+ NonPOD(const NonPOD &);
+ NonPOD(NonPOD &&);
+ };
+
+ struct X {
+ NonPOD np;
+ int a = 17;
+ };
+
+ void check_copy(X x) {
+ X x2(x);
+ }
+
+ void check_move(X x) {
+ X x3(static_cast<X&&>(x));
+ }
+
+ // CHECK: define linkonce_odr void @_ZN7PR114181XC2EOS0_
+ // CHECK-NOT: 17
+ // CHECK: call void @_ZN7PR114186NonPODC1EOS0_
+ // CHECK-NOT: 17
+ // CHECK: load i32*
+ // CHECK-NOT: 17
+ // CHECK: store i32
+ // CHECK-NOT: 17
+ // CHECK: ret
+
+ // CHECK: define linkonce_odr void @_ZN7PR114181XC2ERKS0_
+ // CHECK-NOT: 17
+ // CHECK: call void @_ZN7PR114186NonPODC1ERKS0_
+ // CHECK-NOT: 17
+ // CHECK: load i32*
+ // CHECK-NOT: 17
+ // CHECK: store i32
+ // CHECK-NOT: 17
+ // CHECK: ret
+}