diff options
author | Douglas Gregor <dgregor@apple.com> | 2011-11-28 20:03:15 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2011-11-28 20:03:15 +0000 |
commit | 7db3e95b0dc0ba8c7b22ea56a7331f7ff44944f3 (patch) | |
tree | a7e297e6843c4ad263a0e8652972eed30bde056f | |
parent | 7a5898c3fe1cab3d7718804c96ee231c0682e0cb (diff) | |
download | bcm5719-llvm-7db3e95b0dc0ba8c7b22ea56a7331f7ff44944f3.tar.gz bcm5719-llvm-7db3e95b0dc0ba8c7b22ea56a7331f7ff44944f3.zip |
When synthesizing an implicitly-defined copy or move constructor, or
when computing the exception specification of a copy or move constructor,
ignore non-static data member initializers. Fixes PR11418 /
<rdar://problem/10478642>.
llvm-svn: 145269
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 22 | ||||
-rw-r--r-- | clang/test/CXX/special/class.copy/p15-0x.cpp | 23 | ||||
-rw-r--r-- | clang/test/CXX/special/class.copy/p15-inclass.cpp | 42 |
3 files changed, 80 insertions, 7 deletions
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 52eb9b0d3f3..59c5e7894fd 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/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/clang/test/CXX/special/class.copy/p15-0x.cpp b/clang/test/CXX/special/class.copy/p15-0x.cpp index 32b2714fd70..fff88442555 100644 --- a/clang/test/CXX/special/class.copy/p15-0x.cpp +++ b/clang/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/clang/test/CXX/special/class.copy/p15-inclass.cpp b/clang/test/CXX/special/class.copy/p15-inclass.cpp new file mode 100644 index 00000000000..c4f8eafd937 --- /dev/null +++ b/clang/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 +} |