예제 #1
0
  A test5() {
    // CHECK:      [[AT0:%.*]] = alloca [[A]], align 8
    // CHECK-NEXT: [[BT0:%.*]] = alloca [[B:%.*]], align 8
    // CHECK-NEXT: [[X:%.*]] = alloca [[A]], align 8
    // CHECK-NEXT: [[BT1:%.*]] = alloca [[B]], align 8
    // CHECK-NEXT: [[BT2:%.*]] = alloca [[B]], align 8

    // CHECK:      call void @_ZN7Elision1BC1Ev([[B]]* [[BT0]])
    // CHECK-NEXT: [[AM:%.*]] = getelementptr inbounds [[B]], [[B]]* [[BT0]], i32 0, i32 0
    // CHECK-NEXT: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[AT0]], [[A]]* dereferenceable({{[0-9]+}}) [[AM]])
    // CHECK-NEXT: call void @_ZN7Elision5takeAENS_1AE([[A]]* [[AT0]])
    // CHECK-NEXT: call void @_ZN7Elision1AD1Ev([[A]]* [[AT0]])
    // CHECK-NEXT: call void @_ZN7Elision1BD1Ev([[B]]* [[BT0]])
    takeA(B().a);

    // CHECK-NEXT: call void @llvm.lifetime.end
    // CHECK-NEXT: call void @_ZN7Elision1BC1Ev([[B]]* [[BT1]])
    // CHECK-NEXT: [[AM:%.*]] = getelementptr inbounds [[B]], [[B]]* [[BT1]], i32 0, i32 0
    // CHECK-NEXT: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[X]], [[A]]* dereferenceable({{[0-9]+}}) [[AM]])
    // CHECK-NEXT: call void @_ZN7Elision1BD1Ev([[B]]* [[BT1]])
    A x = B().a;

    // CHECK-NEXT: call void @_ZN7Elision1BC1Ev([[B]]* [[BT2]])
    // CHECK-NEXT: [[AM:%.*]] = getelementptr inbounds [[B]], [[B]]* [[BT2]], i32 0, i32 0
    // CHECK-NEXT: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[RET:%.*]], [[A]]* dereferenceable({{[0-9]+}}) [[AM]])
    // CHECK-NEXT: call void @_ZN7Elision1BD1Ev([[B]]* [[BT2]])
    return B().a;

    // CHECK:      call void @_ZN7Elision1AD1Ev([[A]]* [[X]])
  }
// We handle the case correctly where the move consists of an implicit call
// to a conversion operator.
void implicitConversionOperator() {
  struct Convertible {
    operator A() && { return A(); }
  };
  void takeA(A a);

  Convertible convertible;
  takeA(std::move(convertible));
  convertible;
  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: 'convertible' used after it was moved
  // CHECK-MESSAGES: [[@LINE-3]]:9: note: move occurred here
}