]> granicus.if.org Git - clang/commitdiff
When synthesizing an implicitly-defined copy or move constructor, or
authorDouglas Gregor <dgregor@apple.com>
Mon, 28 Nov 2011 20:03:15 +0000 (20:03 +0000)
committerDouglas Gregor <dgregor@apple.com>
Mon, 28 Nov 2011 20:03:15 +0000 (20:03 +0000)
when computing the exception specification of a copy or move constructor,
ignore non-static data member initializers. Fixes PR11418 /
<rdar://problem/10478642>.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@145269 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaDeclCXX.cpp
test/CXX/special/class.copy/p15-0x.cpp
test/CXX/special/class.copy/p15-inclass.cpp [new file with mode: 0644]

index 52eb9b0d3f36f2323f7a282afc2ca8ca33d262b0..59c5e7894fd374c8fcf5a42c0b0237c9d5236607 100644 (file)
@@ -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);
index 32b2714fd70288cf8117047d41c973888d1cdb5a..fff88442555c0e48cdbfddb45b9fcd4e21bf024b 100644 (file)
@@ -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 (file)
index 0000000..c4f8eaf
--- /dev/null
@@ -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
+}