head	1.1;
branch	1.1.1;
access;
symbols
	netbsd-11-0-RC4:1.1.1.10
	netbsd-11-0-RC3:1.1.1.10
	netbsd-11-0-RC2:1.1.1.10
	netbsd-11-0-RC1:1.1.1.10
	perseant-exfatfs-base-20250801:1.1.1.10
	netbsd-11:1.1.1.10.0.10
	netbsd-11-base:1.1.1.10
	netbsd-10-1-RELEASE:1.1.1.10
	perseant-exfatfs-base-20240630:1.1.1.10
	perseant-exfatfs:1.1.1.10.0.8
	perseant-exfatfs-base:1.1.1.10
	netbsd-8-3-RELEASE:1.1.1.7
	netbsd-9-4-RELEASE:1.1.1.9
	netbsd-10-0-RELEASE:1.1.1.10
	netbsd-10-0-RC6:1.1.1.10
	netbsd-10-0-RC5:1.1.1.10
	netbsd-10-0-RC4:1.1.1.10
	netbsd-10-0-RC3:1.1.1.10
	netbsd-10-0-RC2:1.1.1.10
	netbsd-10-0-RC1:1.1.1.10
	netbsd-10:1.1.1.10.0.6
	netbsd-10-base:1.1.1.10
	netbsd-9-3-RELEASE:1.1.1.9
	cjep_sun2x:1.1.1.10.0.4
	cjep_sun2x-base:1.1.1.10
	cjep_staticlib_x-base1:1.1.1.10
	netbsd-9-2-RELEASE:1.1.1.9
	cjep_staticlib_x:1.1.1.10.0.2
	cjep_staticlib_x-base:1.1.1.10
	netbsd-9-1-RELEASE:1.1.1.9
	phil-wifi-20200421:1.1.1.10
	phil-wifi-20200411:1.1.1.10
	phil-wifi-20200406:1.1.1.10
	netbsd-8-2-RELEASE:1.1.1.7
	netbsd-9-0-RELEASE:1.1.1.9
	netbsd-9-0-RC2:1.1.1.9
	netbsd-9-0-RC1:1.1.1.9
	netbsd-9:1.1.1.9.0.2
	netbsd-9-base:1.1.1.9
	phil-wifi-20190609:1.1.1.9
	netbsd-8-1-RELEASE:1.1.1.7
	netbsd-8-1-RC1:1.1.1.7
	pgoyette-compat-merge-20190127:1.1.1.8.2.1
	pgoyette-compat-20190127:1.1.1.9
	pgoyette-compat-20190118:1.1.1.9
	pgoyette-compat-1226:1.1.1.9
	pgoyette-compat-1126:1.1.1.9
	pgoyette-compat-1020:1.1.1.9
	pgoyette-compat-0930:1.1.1.9
	pgoyette-compat-0906:1.1.1.9
	netbsd-7-2-RELEASE:1.1.1.4.2.1
	pgoyette-compat-0728:1.1.1.9
	clang-337282:1.1.1.9
	netbsd-8-0-RELEASE:1.1.1.7
	phil-wifi:1.1.1.8.0.4
	phil-wifi-base:1.1.1.8
	pgoyette-compat-0625:1.1.1.8
	netbsd-8-0-RC2:1.1.1.7
	pgoyette-compat-0521:1.1.1.8
	pgoyette-compat-0502:1.1.1.8
	pgoyette-compat-0422:1.1.1.8
	netbsd-8-0-RC1:1.1.1.7
	pgoyette-compat-0415:1.1.1.8
	pgoyette-compat-0407:1.1.1.8
	pgoyette-compat-0330:1.1.1.8
	pgoyette-compat-0322:1.1.1.8
	pgoyette-compat-0315:1.1.1.8
	netbsd-7-1-2-RELEASE:1.1.1.4.2.1
	pgoyette-compat:1.1.1.8.0.2
	pgoyette-compat-base:1.1.1.8
	netbsd-7-1-1-RELEASE:1.1.1.4.2.1
	clang-319952:1.1.1.8
	matt-nb8-mediatek:1.1.1.7.0.10
	matt-nb8-mediatek-base:1.1.1.7
	clang-309604:1.1.1.8
	perseant-stdc-iso10646:1.1.1.7.0.8
	perseant-stdc-iso10646-base:1.1.1.7
	netbsd-8:1.1.1.7.0.6
	netbsd-8-base:1.1.1.7
	prg-localcount2-base3:1.1.1.7
	prg-localcount2-base2:1.1.1.7
	prg-localcount2-base1:1.1.1.7
	prg-localcount2:1.1.1.7.0.4
	prg-localcount2-base:1.1.1.7
	pgoyette-localcount-20170426:1.1.1.7
	bouyer-socketcan-base1:1.1.1.7
	pgoyette-localcount-20170320:1.1.1.7
	netbsd-7-1:1.1.1.4.2.1.0.6
	netbsd-7-1-RELEASE:1.1.1.4.2.1
	netbsd-7-1-RC2:1.1.1.4.2.1
	clang-294123:1.1.1.7
	netbsd-7-nhusb-base-20170116:1.1.1.4.2.1
	bouyer-socketcan:1.1.1.7.0.2
	bouyer-socketcan-base:1.1.1.7
	clang-291444:1.1.1.7
	pgoyette-localcount-20170107:1.1.1.6
	netbsd-7-1-RC1:1.1.1.4.2.1
	pgoyette-localcount-20161104:1.1.1.6
	netbsd-7-0-2-RELEASE:1.1.1.4.2.1
	localcount-20160914:1.1.1.6
	netbsd-7-nhusb:1.1.1.4.2.1.0.4
	netbsd-7-nhusb-base:1.1.1.4.2.1
	clang-280599:1.1.1.6
	pgoyette-localcount-20160806:1.1.1.6
	pgoyette-localcount-20160726:1.1.1.6
	pgoyette-localcount:1.1.1.6.0.2
	pgoyette-localcount-base:1.1.1.6
	netbsd-7-0-1-RELEASE:1.1.1.4.2.1
	clang-261930:1.1.1.6
	netbsd-7-0:1.1.1.4.2.1.0.2
	netbsd-7-0-RELEASE:1.1.1.4.2.1
	netbsd-7-0-RC3:1.1.1.4.2.1
	netbsd-7-0-RC2:1.1.1.4.2.1
	netbsd-7-0-RC1:1.1.1.4.2.1
	clang-237755:1.1.1.5
	clang-232565:1.1.1.5
	clang-227398:1.1.1.5
	tls-maxphys-base:1.1.1.4
	tls-maxphys:1.1.1.4.0.4
	netbsd-7:1.1.1.4.0.2
	netbsd-7-base:1.1.1.4
	clang-215315:1.1.1.4
	clang-209886:1.1.1.4
	yamt-pagecache:1.1.1.3.0.4
	yamt-pagecache-base9:1.1.1.3
	tls-earlyentropy:1.1.1.3.0.2
	tls-earlyentropy-base:1.1.1.4
	riastradh-xf86-video-intel-2-7-1-pre-2-21-15:1.1.1.3
	riastradh-drm2-base3:1.1.1.3
	clang-202566:1.1.1.3
	clang-201163:1.1.1.2
	clang-199312:1.1.1.2
	clang-198450:1.1.1.1
	clang-196603:1.1.1.1
	clang-195771:1.1.1.1
	LLVM:1.1.1;
locks; strict;
comment	@// @;


1.1
date	2013.11.28.14.14.58;	author joerg;	state Exp;
branches
	1.1.1.1;
next	;
commitid	ow8OybrawrB1f3fx;

1.1.1.1
date	2013.11.28.14.14.58;	author joerg;	state Exp;
branches;
next	1.1.1.2;
commitid	ow8OybrawrB1f3fx;

1.1.1.2
date	2014.01.15.21.26.09;	author joerg;	state Exp;
branches;
next	1.1.1.3;
commitid	NQXlzzA0SPkc5glx;

1.1.1.3
date	2014.03.04.19.55.42;	author joerg;	state Exp;
branches
	1.1.1.3.2.1
	1.1.1.3.4.1;
next	1.1.1.4;
commitid	29z1hJonZISIXprx;

1.1.1.4
date	2014.05.30.18.14.47;	author joerg;	state Exp;
branches
	1.1.1.4.2.1
	1.1.1.4.4.1;
next	1.1.1.5;
commitid	8q0kdlBlCn09GACx;

1.1.1.5
date	2015.01.29.19.57.35;	author joerg;	state Exp;
branches;
next	1.1.1.6;
commitid	mlISSizlPKvepX7y;

1.1.1.6
date	2016.02.27.22.10.23;	author joerg;	state Exp;
branches
	1.1.1.6.2.1;
next	1.1.1.7;
commitid	tIimz3oDlh1NpBWy;

1.1.1.7
date	2017.01.11.10.40.05;	author joerg;	state Exp;
branches;
next	1.1.1.8;
commitid	CNnUNfII1jgNmxBz;

1.1.1.8
date	2017.08.01.19.34.21;	author joerg;	state Exp;
branches
	1.1.1.8.2.1
	1.1.1.8.4.1;
next	1.1.1.9;
commitid	pMuDy65V0VicSx1A;

1.1.1.9
date	2018.07.17.18.31.27;	author joerg;	state Exp;
branches;
next	1.1.1.10;
commitid	wDzL46ALjrCZgwKA;

1.1.1.10
date	2019.11.13.22.20.15;	author joerg;	state dead;
branches;
next	;
commitid	QD8YATxuNG34YJKB;

1.1.1.3.2.1
date	2014.08.10.07.08.14;	author tls;	state Exp;
branches;
next	;
commitid	t01A1TLTYxkpGMLx;

1.1.1.3.4.1
date	2014.03.04.19.55.42;	author yamt;	state dead;
branches;
next	1.1.1.3.4.2;
commitid	WSrDtL5nYAUyiyBx;

1.1.1.3.4.2
date	2014.05.22.16.18.57;	author yamt;	state Exp;
branches;
next	;
commitid	WSrDtL5nYAUyiyBx;

1.1.1.4.2.1
date	2015.06.04.20.04.34;	author snj;	state Exp;
branches;
next	;
commitid	yRnjq9fueSo6n9oy;

1.1.1.4.4.1
date	2014.05.30.18.14.47;	author tls;	state dead;
branches;
next	1.1.1.4.4.2;
commitid	jTnpym9Qu0o4R1Nx;

1.1.1.4.4.2
date	2014.08.19.23.47.58;	author tls;	state Exp;
branches;
next	;
commitid	jTnpym9Qu0o4R1Nx;

1.1.1.6.2.1
date	2017.03.20.06.52.59;	author pgoyette;	state Exp;
branches;
next	;
commitid	jjw7cAwgyKq7RfKz;

1.1.1.8.2.1
date	2018.07.28.04.33.42;	author pgoyette;	state Exp;
branches;
next	;
commitid	1UP1xAIUxv1ZgRLA;

1.1.1.8.4.1
date	2019.06.10.21.45.52;	author christos;	state Exp;
branches;
next	1.1.1.8.4.2;
commitid	jtc8rnCzWiEEHGqB;

1.1.1.8.4.2
date	2020.04.13.07.47.29;	author martin;	state dead;
branches;
next	;
commitid	X01YhRUPVUDaec4C;


desc
@@


1.1
log
@Initial revision
@
text
@// RUN: %clang_cc1 %s -fno-rtti -cxx-abi microsoft -triple=i386-pc-win32 -emit-llvm -o %t
// RUN: FileCheck %s < %t
// RUN: FileCheck --check-prefix=CHECK2 %s < %t

// For now, just make sure x86_64 doesn't crash.
// RUN: %clang_cc1 %s -fno-rtti -cxx-abi microsoft -triple=x86_64-pc-win32 -emit-llvm -o %t

struct VBase {
  virtual ~VBase();
  virtual void foo();
  virtual void bar();
  int field;
};

struct B : virtual VBase {
  B();
  virtual ~B();
  virtual void foo();
  virtual void bar();
};

B::B() {
  // CHECK-LABEL: define x86_thiscallcc %struct.B* @@"\01??0B@@@@QAE@@XZ"
  // CHECK:   %[[THIS:.*]] = load %struct.B**
  // CHECK:   br i1 %{{.*}}, label %[[INIT_VBASES:.*]], label %[[SKIP_VBASES:.*]]

  // Don't check the INIT_VBASES case as it's covered by the ctor tests.

  // CHECK: %[[SKIP_VBASES]]
  // CHECK:   %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
  // CHECK:   %[[VBPTR:.*]] = getelementptr inbounds i8* %[[THIS_i8]], i32 0
  // ...
  // CHECK:   %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
  // CHECK:   %[[VFPTR_i8:.*]] = getelementptr inbounds i8* %[[THIS_i8]], i32 %{{.*}}
  // CHECK:   %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to [3 x i8*]**
  // CHECK:   store [3 x i8*]* @@"\01??_7B@@@@6B@@", [3 x i8*]** %[[VFPTR]]

  // Initialize vtorDisp:
  // CHECK:   %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
  // CHECK:   %[[VBPTR:.*]] = getelementptr inbounds i8* %[[THIS_i8]], i32 0
  // ...
  // CHECK:   %[[VBASE_OFFSET:.*]] = add nsw i32 0, %{{.*}}
  // CHECK:   %[[VTORDISP_VAL:.*]] = sub i32 %[[VBASE_OFFSET]], 8
  // CHECK:   %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
  // CHECK:   %[[VBASE_i8:.*]] = getelementptr inbounds i8* %[[THIS_i8]], i32 %[[VBASE_OFFSET]]
  // CHECK:   %[[VTORDISP_i8:.*]] = getelementptr i8* %[[VBASE_i8]], i32 -4
  // CHECK:   %[[VTORDISP_PTR:.*]] = bitcast i8* %[[VTORDISP_i8]] to i32*
  // CHECK:   store i32 %[[VTORDISP_VAL]], i32* %[[VTORDISP_PTR]]

  // CHECK: ret
}

B::~B() {
  // CHECK-LABEL: define x86_thiscallcc void @@"\01??1B@@@@UAE@@XZ"
  // Adjust the this parameter:
  // CHECK:   %[[THIS_PARAM_i8:.*]] = bitcast %struct.B* {{.*}} to i8*
  // CHECK:   %[[THIS_i8:.*]] = getelementptr inbounds i8* %[[THIS_PARAM_i8]], i32 -8
  // CHECK:   %[[THIS:.*]] = bitcast i8* %[[THIS_i8]] to %struct.B*
  // CHECK:   store %struct.B* %[[THIS]], %struct.B** %[[THIS_ADDR:.*]], align 4
  // CHECK:   %[[THIS:.*]] = load %struct.B** %[[THIS_ADDR]]

  // Restore the vfptr that could have been changed by a subclass.
  // CHECK:   %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
  // CHECK:   %[[VBPTR:.*]] = getelementptr inbounds i8* %[[THIS_i8]], i32 0
  // ...
  // CHECK:   %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
  // CHECK:   %[[VFPTR_i8:.*]] = getelementptr inbounds i8* %[[THIS_i8]], i32 %{{.*}}
  // CHECK:   %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to [3 x i8*]**
  // CHECK:   store [3 x i8*]* @@"\01??_7B@@@@6B@@", [3 x i8*]** %[[VFPTR]]

  // Initialize vtorDisp:
  // CHECK:   %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
  // CHECK:   %[[VBPTR:.*]] = getelementptr inbounds i8* %[[THIS_i8]], i32 0
  // ...
  // CHECK:   %[[VBASE_OFFSET:.*]] = add nsw i32 0, %{{.*}}
  // CHECK:   %[[VTORDISP_VAL:.*]] = sub i32 %[[VBASE_OFFSET]], 8
  // CHECK:   %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
  // CHECK:   %[[VBASE_i8:.*]] = getelementptr inbounds i8* %[[THIS_i8]], i32 %[[VBASE_OFFSET]]
  // CHECK:   %[[VTORDISP_i8:.*]] = getelementptr i8* %[[VBASE_i8]], i32 -4
  // CHECK:   %[[VTORDISP_PTR:.*]] = bitcast i8* %[[VTORDISP_i8]] to i32*
  // CHECK:   store i32 %[[VTORDISP_VAL]], i32* %[[VTORDISP_PTR]]

  foo();  // Avoid the "trivial destructor" optimization.

  // CHECK: ret

  // CHECK2-LABEL: define linkonce_odr x86_thiscallcc void @@"\01??_DB@@@@UAE@@XZ"(%struct.B*
  // CHECK2: %[[THIS:.*]] = load %struct.B** {{.*}}
  // CHECK2: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
  // CHECK2: %[[B_i8:.*]] = getelementptr i8* %[[THIS_i8]], i32 8
  // CHECK2: %[[B:.*]] = bitcast i8* %[[B_i8]] to %struct.B*
  // CHECK2: call x86_thiscallcc void @@"\01??1B@@@@UAE@@XZ"(%struct.B* %[[B]])
  // CHECK2: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
  // CHECK2: %[[VBASE_i8:.*]] = getelementptr inbounds i8* %[[THIS_i8]], i64 8
  // CHECK2: %[[VBASE:.*]] = bitcast i8* %[[VBASE_i8]] to %struct.VBase*
  // CHECK2: call x86_thiscallcc void @@"\01??1VBase@@@@UAE@@XZ"(%struct.VBase* %[[VBASE]])
  // CHECK2: ret

  // CHECK2-LABEL: define linkonce_odr x86_thiscallcc void @@"\01??_GB@@@@UAEPAXI@@Z"
  // CHECK2:   %[[THIS_PARAM_i8:.*]] = bitcast %struct.B* {{.*}} to i8*
  // CHECK2:   %[[THIS_i8:.*]] = getelementptr inbounds i8* %[[THIS_PARAM_i8:.*]], i32 -8
  // CHECK2:   %[[THIS:.*]] = bitcast i8* %[[THIS_i8]] to %struct.B*
  // CHECK2:   store %struct.B* %[[THIS]], %struct.B** %[[THIS_ADDR:.*]], align 4
  // CHECK2:   %[[THIS:.*]] = load %struct.B** %[[THIS_ADDR]]
  // CHECK2:   call x86_thiscallcc void @@"\01??_DB@@@@UAE@@XZ"(%struct.B* %[[THIS]])
  // ...
  // CHECK2: ret
}

void B::foo() {
// CHECK-LABEL: define x86_thiscallcc void @@"\01?foo@@B@@@@UAEXXZ"(i8*
//
// B::foo gets 'this' cast to VBase* in ECX (i.e. this+8) so we
// need to adjust 'this' before use.
//
// CHECK: %[[THIS_ADDR:.*]] = alloca %struct.B*, align 4
// CHECK: %[[THIS_i8:.*]] = getelementptr inbounds i8* %[[ECX:.*]], i32 -8
// CHECK: %[[THIS:.*]] = bitcast i8* %[[THIS_i8]] to %struct.B*
// CHECK: store %struct.B* %[[THIS]], %struct.B** %[[THIS_ADDR]], align 4

  field = 42;
// CHECK: %[[THIS:.*]] = load %struct.B** %[[THIS_ADDR]]
// CHECK: %[[THIS8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
// CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8* %[[THIS8]], i32 0
// CHECK: %[[VBPTR8:.*]] = bitcast i8* %[[VBPTR]] to i8**
// CHECK: %[[VBTABLE:.*]] = load i8** %[[VBPTR8]]
// CHECK: %[[VBENTRY8:.*]] = getelementptr inbounds i8* %[[VBTABLE]], i32 4
// CHECK: %[[VBENTRY:.*]] = bitcast i8* %[[VBENTRY8]] to i32*
// CHECK: %[[VBOFFSET32:.*]] = load i32* %[[VBENTRY]]
// CHECK: %[[VBOFFSET:.*]] = add nsw i32 0, %[[VBOFFSET32]]
// CHECK: %[[THIS8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
// CHECK: %[[VBASE_i8:.*]] = getelementptr inbounds i8* %[[THIS8]], i32 %[[VBOFFSET]]
// CHECK: %[[VBASE:.*]] = bitcast i8* %[[VBASE_i8]] to %struct.VBase*
// CHECK: %[[FIELD:.*]] = getelementptr inbounds %struct.VBase* %[[VBASE]], i32 0, i32 1
// CHECK: store i32 42, i32* %[[FIELD]], align 4
//
// CHECK: ret void
}

void call_vbase_bar(B *obj) {
// CHECK-LABEL: define void @@"\01?call_vbase_bar@@@@YAXPAUB@@@@@@Z"(%struct.B* %obj)
// CHECK: %[[OBJ:.*]] = load %struct.B

  obj->bar();
// When calling a vbase's virtual method, one needs to adjust 'this'
// at the caller site.
//
// CHECK: %[[OBJ_i8:.*]] = bitcast %struct.B* %[[OBJ]] to i8*
// CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 0
// CHECK: %[[VBPTR8:.*]] = bitcast i8* %[[VBPTR]] to i8**
// CHECK: %[[VBTABLE:.*]] = load i8** %[[VBPTR8]]
// CHECK: %[[VBENTRY8:.*]] = getelementptr inbounds i8* %[[VBTABLE]], i32 4
// CHECK: %[[VBENTRY:.*]] = bitcast i8* %[[VBENTRY8]] to i32*
// CHECK: %[[VBOFFSET32:.*]] = load i32* %[[VBENTRY]]
// CHECK: %[[VBOFFSET:.*]] = add nsw i32 0, %[[VBOFFSET32]]
// CHECK: %[[VBASE_i8:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 %[[VBOFFSET]]
// CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VBASE_i8]] to void (i8*)***
// CHECK: %[[VFTABLE:.*]] = load void (i8*)*** %[[VFPTR]]
// CHECK: %[[VFUN:.*]] = getelementptr inbounds void (i8*)** %[[VFTABLE]], i64 2
// CHECK: %[[VFUN_VALUE:.*]] = load void (i8*)** %[[VFUN]]
//
// CHECK: %[[OBJ_i8:.*]] = bitcast %struct.B* %[[OBJ]] to i8*
// CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 0
// CHECK: %[[VBPTR8:.*]] = bitcast i8* %[[VBPTR]] to i8**
// CHECK: %[[VBTABLE:.*]] = load i8** %[[VBPTR8]]
// CHECK: %[[VBENTRY8:.*]] = getelementptr inbounds i8* %[[VBTABLE]], i32 4
// CHECK: %[[VBENTRY:.*]] = bitcast i8* %[[VBENTRY8]] to i32*
// CHECK: %[[VBOFFSET32:.*]] = load i32* %[[VBENTRY]]
// CHECK: %[[VBOFFSET:.*]] = add nsw i32 0, %[[VBOFFSET32]]
// CHECK: %[[VBASE:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 %[[VBOFFSET]]
//
// CHECK: call x86_thiscallcc void %[[VFUN_VALUE]](i8* %[[VBASE]])
//
// CHECK: ret void
}

void delete_B(B *obj) {
// CHECK-LABEL: define void @@"\01?delete_B@@@@YAXPAUB@@@@@@Z"(%struct.B* %obj)
// CHECK: %[[OBJ:.*]] = load %struct.B

  delete obj;
// CHECK: %[[OBJ_i8:.*]] = bitcast %struct.B* %[[OBJ]] to i8*
// CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 0
// CHECK: %[[VBPTR8:.*]] = bitcast i8* %[[VBPTR]] to i8**
// CHECK: %[[VBTABLE:.*]] = load i8** %[[VBPTR8]]
// CHECK: %[[VBENTRY8:.*]] = getelementptr inbounds i8* %[[VBTABLE]], i32 4
// CHECK: %[[VBENTRY:.*]] = bitcast i8* %[[VBENTRY8]] to i32*
// CHECK: %[[VBOFFSET32:.*]] = load i32* %[[VBENTRY]]
// CHECK: %[[VBOFFSET:.*]] = add nsw i32 0, %[[VBOFFSET32]]
// CHECK: %[[VBASE_i8:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 %[[VBOFFSET]]
// CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VBASE_i8]] to void (%struct.B*, i32)***
// CHECK: %[[VFTABLE:.*]] = load void (%struct.B*, i32)*** %[[VFPTR]]
// CHECK: %[[VFUN:.*]] = getelementptr inbounds void (%struct.B*, i32)** %[[VFTABLE]], i64 0
// CHECK: %[[VFUN_VALUE:.*]] = load void (%struct.B*, i32)** %[[VFUN]]
//
// CHECK: %[[OBJ_i8:.*]] = bitcast %struct.B* %[[OBJ]] to i8*
// CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 0
// CHECK: %[[VBPTR8:.*]] = bitcast i8* %[[VBPTR]] to i8**
// CHECK: %[[VBTABLE:.*]] = load i8** %[[VBPTR8]]
// CHECK: %[[VBENTRY8:.*]] = getelementptr inbounds i8* %[[VBTABLE]], i32 4
// CHECK: %[[VBENTRY:.*]] = bitcast i8* %[[VBENTRY8]] to i32*
// CHECK: %[[VBOFFSET32:.*]] = load i32* %[[VBENTRY]]
// CHECK: %[[VBOFFSET:.*]] = add nsw i32 0, %[[VBOFFSET32]]
// CHECK: %[[VBASE_i8:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 %[[VBOFFSET]]
// CHECK: %[[VBASE:.*]] = bitcast i8* %[[VBASE_i8]] to %struct.B*
//
// CHECK: call x86_thiscallcc void %[[VFUN_VALUE]](%struct.B* %[[VBASE]], i32 1)
// CHECK: ret void
}

void call_complete_dtor() {
  // CHECK-LABEL: define void @@"\01?call_complete_dtor@@@@YAXXZ"
  B b;
  // CHECK: call x86_thiscallcc %struct.B* @@"\01??0B@@@@QAE@@XZ"(%struct.B* %[[B:.*]], i32 1)
  // CHECK-NOT: getelementptr
  // CHECK: call x86_thiscallcc void @@"\01??_DB@@@@UAE@@XZ"(%struct.B* %[[B]])
  // CHECK: ret
}

struct C : B {
  C();
  // has an implicit vdtor.
};

// Used to crash on an assertion.
C::C() {
// CHECK-LABEL: define x86_thiscallcc %struct.C* @@"\01??0C@@@@QAE@@XZ"
}

namespace multiple_vbases {
struct A {
  virtual void a();
};

struct B {
  virtual void b();
};

struct C {
  virtual void c();
};

struct D : virtual A, virtual B, virtual C {
  virtual void a();
  virtual void b();
  virtual void c();
  D();
};

D::D() {
  // CHECK-LABEL: define x86_thiscallcc %"struct.multiple_vbases::D"* @@"\01??0D@@multiple_vbases@@@@QAE@@XZ"
  // Just make sure we emit 3 vtordisps after initializing vfptrs.
  // CHECK: store [1 x i8*]* @@"\01??_7D@@multiple_vbases@@@@6BA@@1@@@@", [1 x i8*]** %{{.*}}
  // CHECK: store [1 x i8*]* @@"\01??_7D@@multiple_vbases@@@@6BB@@1@@@@", [1 x i8*]** %{{.*}}
  // CHECK: store [1 x i8*]* @@"\01??_7D@@multiple_vbases@@@@6BC@@1@@@@", [1 x i8*]** %{{.*}}
  // ...
  // CHECK: store i32 %{{.*}}, i32* %{{.*}}
  // CHECK: store i32 %{{.*}}, i32* %{{.*}}
  // CHECK: store i32 %{{.*}}, i32* %{{.*}}
  // CHECK: ret
}
}

namespace diamond {
struct A {
  A();
  virtual ~A();
};

struct B : virtual A {
  B();
  ~B();
};

struct C : virtual A {
  C();
  ~C();
  int c1, c2, c3;
};

struct Z {
  int z;
};

struct D : virtual Z, B, C {
  D();
  ~D();
} d;

D::~D() {
  // CHECK-LABEL: define x86_thiscallcc void @@"\01??1D@@diamond@@@@UAE@@XZ"(%"struct.diamond::D"*)
  // CHECK: %[[ARG_i8:.*]] = bitcast %"struct.diamond::D"* %{{.*}} to i8*
  // CHECK: %[[THIS_i8:.*]] = getelementptr inbounds i8* %[[ARG_i8]], i32 -24
  // CHECK: %[[THIS:.*]] = bitcast i8* %[[THIS_i8]] to %"struct.diamond::D"*
  // CHECK: store %"struct.diamond::D"* %[[THIS]], %"struct.diamond::D"** %[[THIS_VAL:.*]], align 4
  // CHECK: %[[THIS:.*]] = load %"struct.diamond::D"** %[[THIS_VAL]]
  // CHECK: %[[D_i8:.*]] = bitcast %"struct.diamond::D"* %[[THIS]] to i8*
  // CHECK: %[[C_i8:.*]] = getelementptr inbounds i8* %[[D_i8]], i64 4
  // CHECK: %[[C:.*]] = bitcast i8* %[[C_i8]] to %"struct.diamond::C"*
  // CHECK: %[[C_i8:.*]] = bitcast %"struct.diamond::C"* %[[C]] to i8*
  // CHECK: %[[ARG_i8:.*]] = getelementptr i8* %{{.*}}, i32 16
  // FIXME: We might consider changing the dtor this parameter type to i8*.
  // CHECK: %[[ARG:.*]] = bitcast i8* %[[ARG_i8]] to %"struct.diamond::C"*
  // CHECK: call x86_thiscallcc void @@"\01??1C@@diamond@@@@UAE@@XZ"(%"struct.diamond::C"* %[[ARG]])

  // CHECK: %[[B:.*]] = bitcast %"struct.diamond::D"* %[[THIS]] to %"struct.diamond::B"*
  // CHECK: %[[B_i8:.*]] = bitcast %"struct.diamond::B"* %[[B]] to i8*
  // CHECK: %[[ARG_i8:.*]] = getelementptr i8* %[[B_i8]], i32 4
  // CHECK: %[[ARG:.*]] = bitcast i8* %[[ARG_i8]] to %"struct.diamond::B"*
  // CHECK: call x86_thiscallcc void @@"\01??1B@@diamond@@@@UAE@@XZ"(%"struct.diamond::B"* %[[ARG]])
  // CHECK: ret void
}

}
@


1.1.1.1
log
@Import Clang 3.4rc1 r195771.
@
text
@@


1.1.1.2
log
@Import Clang 3.5svn r199312
@
text
@d1 1
a1 1
// RUN: %clang_cc1 %s -fno-rtti -triple=i386-pc-win32 -emit-llvm -o %t
d6 1
a6 1
// RUN: %clang_cc1 %s -fno-rtti -triple=x86_64-pc-win32 -emit-llvm -o %t
a314 27

namespace test2 {
struct A { A(); };
struct B : virtual A { B() {} };
struct C : B, A { C() {} };

// PR18435: Order mattered here.  We were generating code for the delegating
// call to B() from C().
void callC() { C x; }

// CHECK-LABEL: define linkonce_odr x86_thiscallcc %"struct.test2::C"* @@"\01??0C@@test2@@@@QAE@@XZ"
// CHECK:           (%"struct.test2::C"* returned %this, i32 %is_most_derived)
// CHECK: br i1
//   Virtual bases
// CHECK: call x86_thiscallcc %"struct.test2::A"* @@"\01??0A@@test2@@@@QAE@@XZ"(%"struct.test2::A"* %{{.*}})
// CHECK: br label
//   Non-virtual bases
// CHECK: call x86_thiscallcc %"struct.test2::B"* @@"\01??0B@@test2@@@@QAE@@XZ"(%"struct.test2::B"* %{{.*}}, i32 0)
// CHECK: call x86_thiscallcc %"struct.test2::A"* @@"\01??0A@@test2@@@@QAE@@XZ"(%"struct.test2::A"* %{{.*}})
// CHECK: ret

// CHECK2-LABEL: define linkonce_odr x86_thiscallcc %"struct.test2::B"* @@"\01??0B@@test2@@@@QAE@@XZ"
// CHECK2:           (%"struct.test2::B"* returned %this, i32 %is_most_derived)
// CHECK2: call x86_thiscallcc %"struct.test2::A"* @@"\01??0A@@test2@@@@QAE@@XZ"(%"struct.test2::A"* %{{.*}})
// CHECK2: ret

}
@


1.1.1.3
log
@Import Clang 3.5svn r202566.
@
text
@d220 1
a220 6
struct X : virtual VBase {
  int x;
};


struct C : X {
@


1.1.1.3.2.1
log
@Rebase.
@
text
@d220 6
a225 1
struct C : B {
a346 121

namespace test3 {
// PR19104: A non-virtual call of a virtual method doesn't use vftable thunks,
// so requires only static adjustment which is different to the one used
// for virtual calls.
struct A {
  virtual void foo();
};

struct B : virtual A {
  virtual void bar();
};

struct C : virtual A {
  virtual void foo();
};

struct D : B, C {
  virtual void bar();
  int field;  // Laid out between C and A subobjects in D.
};

void D::bar() {
  // CHECK-LABEL: define x86_thiscallcc void @@"\01?bar@@D@@test3@@@@UAEXXZ"(%"struct.test3::D"* %this)

  C::foo();
  // Shouldn't need any vbtable lookups.  All we have to do is adjust to C*,
  // then compensate for the adjustment performed in the C::foo() prologue.
  // CHECK-NOT: load i8**
  // CHECK: %[[OBJ_i8:.*]] = bitcast %"struct.test3::D"* %{{.*}} to i8*
  // CHECK: %[[C_i8:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 8
  // CHECK: %[[C:.*]] = bitcast i8* %[[C_i8]] to %"struct.test3::C"*
  // CHECK: %[[C_i8:.*]] = bitcast %"struct.test3::C"* %[[C]] to i8*
  // CHECK: %[[ARG:.*]] = getelementptr i8* %[[C_i8]], i32 4
  // CHECK: call x86_thiscallcc void @@"\01?foo@@C@@test3@@@@UAEXXZ"(i8* %[[ARG]])
  // CHECK: ret
}
}

namespace test4{
// PR19172: We used to merge method vftable locations wrong.

struct A {
  virtual ~A() {}
};

struct B {
  virtual ~B() {}
};

struct C : virtual A, B {
  virtual ~C();
};

void foo(void*);

C::~C() {
  // CHECK-LABEL: define x86_thiscallcc void @@"\01??1C@@test4@@@@UAE@@XZ"(%"struct.test4::C"* %this)

  // In this case "this" points to the most derived class, so no GEPs needed.
  // CHECK-NOT: getelementptr
  // CHECK-NOT: bitcast
  // CHECK: %[[VFPTR_i8:.*]] = bitcast %"struct.test4::C"* %{{.*}} to [1 x i8*]**
  // CHECK: store [1 x i8*]* @@"\01??_7C@@test4@@@@6BB@@1@@@@", [1 x i8*]** %[[VFPTR_i8]]

  foo(this);
  // CHECK: ret
}

void destroy(C *obj) {
  // CHECK-LABEL: define void @@"\01?destroy@@test4@@@@YAXPAUC@@1@@@@Z"(%"struct.test4::C"* %obj)

  delete obj;
  // CHECK: %[[VPTR:.*]] = bitcast %"struct.test4::C"* %[[OBJ:.*]] to void (%"struct.test4::C"*, i32)***
  // CHECK: %[[VFTABLE:.*]] = load void (%"struct.test4::C"*, i32)*** %[[VPTR]]
  // CHECK: %[[VFTENTRY:.*]] = getelementptr inbounds void (%"struct.test4::C"*, i32)** %[[VFTABLE]], i64 0
  // CHECK: %[[VFUN:.*]] = load void (%"struct.test4::C"*, i32)** %[[VFTENTRY]]
  // CHECK: call x86_thiscallcc void %[[VFUN]](%"struct.test4::C"* %[[OBJ]], i32 1)
  // CHECK: ret
}

struct D {
  virtual void d();
};

// The first non-virtual base doesn't have a vdtor,
// but "this adjustment" is not needed.
struct E : D, B, virtual A {
  virtual ~E();
};

E::~E() {
  // CHECK-LABEL: define x86_thiscallcc void @@"\01??1E@@test4@@@@UAE@@XZ"(%"struct.test4::E"* %this)

  // In this case "this" points to the most derived class, so no GEPs needed.
  // CHECK-NOT: getelementptr
  // CHECK-NOT: bitcast
  // CHECK: %[[VFPTR_i8:.*]] = bitcast %"struct.test4::E"* %{{.*}} to [1 x i8*]**
  // CHECK: store [1 x i8*]* @@"\01??_7E@@test4@@@@6BD@@1@@@@", [1 x i8*]** %[[VFPTR_i8]]
  foo(this);
}

void destroy(E *obj) {
  // CHECK-LABEL: define void @@"\01?destroy@@test4@@@@YAXPAUE@@1@@@@Z"(%"struct.test4::E"* %obj)

  // CHECK-NOT: getelementptr
  // CHECK: %[[OBJ_i8:.*]] = bitcast %"struct.test4::E"* %[[OBJ:.*]] to i8*
  // CHECK: %[[B_i8:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 4
  // CHECK: %[[VPTR:.*]] = bitcast i8* %[[B_i8]] to void (%"struct.test4::E"*, i32)***
  // CHECK: %[[VFTABLE:.*]] = load void (%"struct.test4::E"*, i32)*** %[[VPTR]]
  // CHECK: %[[VFTENTRY:.*]] = getelementptr inbounds void (%"struct.test4::E"*, i32)** %[[VFTABLE]], i64 0
  // CHECK: %[[VFUN:.*]] = load void (%"struct.test4::E"*, i32)** %[[VFTENTRY]]
  // CHECK: %[[OBJ_i8:.*]] = bitcast %"struct.test4::E"* %[[OBJ]] to i8*
  // CHECK: %[[B_i8:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 4
  // FIXME: in fact, the call should take i8* and the bitcast is redundant.
  // CHECK: %[[B_as_E:.*]] = bitcast i8* %[[B_i8]] to %"struct.test4::E"*
  // CHECK: call x86_thiscallcc void %[[VFUN]](%"struct.test4::E"* %[[B_as_E]], i32 1)
  delete obj;
}

}
@


1.1.1.4
log
@Import Clang 3.5svn r209886.
@
text
@d220 6
a225 1
struct C : B {
a346 121

namespace test3 {
// PR19104: A non-virtual call of a virtual method doesn't use vftable thunks,
// so requires only static adjustment which is different to the one used
// for virtual calls.
struct A {
  virtual void foo();
};

struct B : virtual A {
  virtual void bar();
};

struct C : virtual A {
  virtual void foo();
};

struct D : B, C {
  virtual void bar();
  int field;  // Laid out between C and A subobjects in D.
};

void D::bar() {
  // CHECK-LABEL: define x86_thiscallcc void @@"\01?bar@@D@@test3@@@@UAEXXZ"(%"struct.test3::D"* %this)

  C::foo();
  // Shouldn't need any vbtable lookups.  All we have to do is adjust to C*,
  // then compensate for the adjustment performed in the C::foo() prologue.
  // CHECK-NOT: load i8**
  // CHECK: %[[OBJ_i8:.*]] = bitcast %"struct.test3::D"* %{{.*}} to i8*
  // CHECK: %[[C_i8:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 8
  // CHECK: %[[C:.*]] = bitcast i8* %[[C_i8]] to %"struct.test3::C"*
  // CHECK: %[[C_i8:.*]] = bitcast %"struct.test3::C"* %[[C]] to i8*
  // CHECK: %[[ARG:.*]] = getelementptr i8* %[[C_i8]], i32 4
  // CHECK: call x86_thiscallcc void @@"\01?foo@@C@@test3@@@@UAEXXZ"(i8* %[[ARG]])
  // CHECK: ret
}
}

namespace test4{
// PR19172: We used to merge method vftable locations wrong.

struct A {
  virtual ~A() {}
};

struct B {
  virtual ~B() {}
};

struct C : virtual A, B {
  virtual ~C();
};

void foo(void*);

C::~C() {
  // CHECK-LABEL: define x86_thiscallcc void @@"\01??1C@@test4@@@@UAE@@XZ"(%"struct.test4::C"* %this)

  // In this case "this" points to the most derived class, so no GEPs needed.
  // CHECK-NOT: getelementptr
  // CHECK-NOT: bitcast
  // CHECK: %[[VFPTR_i8:.*]] = bitcast %"struct.test4::C"* %{{.*}} to [1 x i8*]**
  // CHECK: store [1 x i8*]* @@"\01??_7C@@test4@@@@6BB@@1@@@@", [1 x i8*]** %[[VFPTR_i8]]

  foo(this);
  // CHECK: ret
}

void destroy(C *obj) {
  // CHECK-LABEL: define void @@"\01?destroy@@test4@@@@YAXPAUC@@1@@@@Z"(%"struct.test4::C"* %obj)

  delete obj;
  // CHECK: %[[VPTR:.*]] = bitcast %"struct.test4::C"* %[[OBJ:.*]] to void (%"struct.test4::C"*, i32)***
  // CHECK: %[[VFTABLE:.*]] = load void (%"struct.test4::C"*, i32)*** %[[VPTR]]
  // CHECK: %[[VFTENTRY:.*]] = getelementptr inbounds void (%"struct.test4::C"*, i32)** %[[VFTABLE]], i64 0
  // CHECK: %[[VFUN:.*]] = load void (%"struct.test4::C"*, i32)** %[[VFTENTRY]]
  // CHECK: call x86_thiscallcc void %[[VFUN]](%"struct.test4::C"* %[[OBJ]], i32 1)
  // CHECK: ret
}

struct D {
  virtual void d();
};

// The first non-virtual base doesn't have a vdtor,
// but "this adjustment" is not needed.
struct E : D, B, virtual A {
  virtual ~E();
};

E::~E() {
  // CHECK-LABEL: define x86_thiscallcc void @@"\01??1E@@test4@@@@UAE@@XZ"(%"struct.test4::E"* %this)

  // In this case "this" points to the most derived class, so no GEPs needed.
  // CHECK-NOT: getelementptr
  // CHECK-NOT: bitcast
  // CHECK: %[[VFPTR_i8:.*]] = bitcast %"struct.test4::E"* %{{.*}} to [1 x i8*]**
  // CHECK: store [1 x i8*]* @@"\01??_7E@@test4@@@@6BD@@1@@@@", [1 x i8*]** %[[VFPTR_i8]]
  foo(this);
}

void destroy(E *obj) {
  // CHECK-LABEL: define void @@"\01?destroy@@test4@@@@YAXPAUE@@1@@@@Z"(%"struct.test4::E"* %obj)

  // CHECK-NOT: getelementptr
  // CHECK: %[[OBJ_i8:.*]] = bitcast %"struct.test4::E"* %[[OBJ:.*]] to i8*
  // CHECK: %[[B_i8:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 4
  // CHECK: %[[VPTR:.*]] = bitcast i8* %[[B_i8]] to void (%"struct.test4::E"*, i32)***
  // CHECK: %[[VFTABLE:.*]] = load void (%"struct.test4::E"*, i32)*** %[[VPTR]]
  // CHECK: %[[VFTENTRY:.*]] = getelementptr inbounds void (%"struct.test4::E"*, i32)** %[[VFTABLE]], i64 0
  // CHECK: %[[VFUN:.*]] = load void (%"struct.test4::E"*, i32)** %[[VFTENTRY]]
  // CHECK: %[[OBJ_i8:.*]] = bitcast %"struct.test4::E"* %[[OBJ]] to i8*
  // CHECK: %[[B_i8:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 4
  // FIXME: in fact, the call should take i8* and the bitcast is redundant.
  // CHECK: %[[B_as_E:.*]] = bitcast i8* %[[B_i8]] to %"struct.test4::E"*
  // CHECK: call x86_thiscallcc void %[[VFUN]](%"struct.test4::E"* %[[B_as_E]], i32 1)
  delete obj;
}

}
@


1.1.1.4.2.1
log
@Update LLVM to 3.6.1, requested by joerg in ticket 824.
@
text
@d35 2
a36 2
  // CHECK:   %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to i32 (...)***
  // CHECK:   store i32 (...)** bitcast ([3 x i8*]* @@"\01??_7B@@@@6B@@" to i32 (...)**), i32 (...)*** %[[VFPTR]]
d68 2
a69 2
  // CHECK:   %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to i32 (...)***
  // CHECK:   store i32 (...)** bitcast ([3 x i8*]* @@"\01??_7B@@@@6B@@" to i32 (...)**), i32 (...)*** %[[VFPTR]]
d99 1
a99 1
  // CHECK2-LABEL: define linkonce_odr x86_thiscallcc i8* @@"\01??_GB@@@@UAEPAXI@@Z"
d125 4
a128 3
// CHECK: %[[VBPTR8:.*]] = bitcast i8* %[[VBPTR]] to i32**
// CHECK: %[[VBTABLE:.*]] = load i32** %[[VBPTR8]]
// CHECK: %[[VBENTRY:.*]] = getelementptr inbounds i32* %[[VBTABLE]], i32 1
d150 4
a153 3
// CHECK: %[[VBPTR8:.*]] = bitcast i8* %[[VBPTR]] to i32**
// CHECK: %[[VBTABLE:.*]] = load i32** %[[VBPTR8]]
// CHECK: %[[VBENTRY:.*]] = getelementptr inbounds i32* %[[VBTABLE]], i32 1
d164 4
a167 3
// CHECK: %[[VBPTR8:.*]] = bitcast i8* %[[VBPTR]] to i32**
// CHECK: %[[VBTABLE:.*]] = load i32** %[[VBPTR8]]
// CHECK: %[[VBENTRY:.*]] = getelementptr inbounds i32* %[[VBTABLE]], i32 1
d184 4
a187 3
// CHECK: %[[VBPTR8:.*]] = bitcast i8* %[[VBPTR]] to i32**
// CHECK: %[[VBTABLE:.*]] = load i32** %[[VBPTR8]]
// CHECK: %[[VBENTRY:.*]] = getelementptr inbounds i32* %[[VBTABLE]], i32 1
d191 4
a194 4
// CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VBASE_i8]] to i8* (%struct.B*, i32)***
// CHECK: %[[VFTABLE:.*]] = load i8* (%struct.B*, i32)*** %[[VFPTR]]
// CHECK: %[[VFUN:.*]] = getelementptr inbounds i8* (%struct.B*, i32)** %[[VFTABLE]], i64 0
// CHECK: %[[VFUN_VALUE:.*]] = load i8* (%struct.B*, i32)** %[[VFUN]]
d198 4
a201 3
// CHECK: %[[VBPTR8:.*]] = bitcast i8* %[[VBPTR]] to i32**
// CHECK: %[[VBTABLE:.*]] = load i32** %[[VBPTR8]]
// CHECK: %[[VBENTRY:.*]] = getelementptr inbounds i32* %[[VBTABLE]], i32 1
d207 1
a207 1
// CHECK: call x86_thiscallcc i8* %[[VFUN_VALUE]](%struct.B* %[[VBASE]], i32 1)
d253 3
a255 3
  // CHECK: store i32 (...)** bitcast ([1 x i8*]* @@"\01??_7D@@multiple_vbases@@@@6BA@@1@@@@" to i32 (...)**), i32 (...)*** %{{.*}}
  // CHECK: store i32 (...)** bitcast ([1 x i8*]* @@"\01??_7D@@multiple_vbases@@@@6BB@@1@@@@" to i32 (...)**), i32 (...)*** %{{.*}}
  // CHECK: store i32 (...)** bitcast ([1 x i8*]* @@"\01??_7D@@multiple_vbases@@@@6BC@@1@@@@" to i32 (...)**), i32 (...)*** %{{.*}}
d404 2
a405 2
  // CHECK: %[[VFPTR_i8:.*]] = bitcast %"struct.test4::C"* %{{.*}} to i32 (...)***
  // CHECK: store i32 (...)** bitcast ([1 x i8*]* @@"\01??_7C@@test4@@@@6BB@@1@@@@" to i32 (...)**), i32 (...)*** %[[VFPTR_i8]]
d415 5
a419 5
  // CHECK: %[[VPTR:.*]] = bitcast %"struct.test4::C"* %[[OBJ:.*]] to i8* (%"struct.test4::C"*, i32)***
  // CHECK: %[[VFTABLE:.*]] = load i8* (%"struct.test4::C"*, i32)*** %[[VPTR]]
  // CHECK: %[[VFTENTRY:.*]] = getelementptr inbounds i8* (%"struct.test4::C"*, i32)** %[[VFTABLE]], i64 0
  // CHECK: %[[VFUN:.*]] = load i8* (%"struct.test4::C"*, i32)** %[[VFTENTRY]]
  // CHECK: call x86_thiscallcc i8* %[[VFUN]](%"struct.test4::C"* %[[OBJ]], i32 1)
d439 2
a440 2
  // CHECK: %[[VFPTR_i8:.*]] = bitcast %"struct.test4::E"* %{{.*}} to i32 (...)***
  // CHECK: store i32 (...)** bitcast ([1 x i8*]* @@"\01??_7E@@test4@@@@6BD@@1@@@@" to i32 (...)**), i32 (...)*** %[[VFPTR_i8]]
d450 4
a453 4
  // CHECK: %[[VPTR:.*]] = bitcast i8* %[[B_i8]] to i8* (%"struct.test4::E"*, i32)***
  // CHECK: %[[VFTABLE:.*]] = load i8* (%"struct.test4::E"*, i32)*** %[[VPTR]]
  // CHECK: %[[VFTENTRY:.*]] = getelementptr inbounds i8* (%"struct.test4::E"*, i32)** %[[VFTABLE]], i64 0
  // CHECK: %[[VFUN:.*]] = load i8* (%"struct.test4::E"*, i32)** %[[VFTENTRY]]
d458 1
a458 1
  // CHECK: call x86_thiscallcc i8* %[[VFUN]](%"struct.test4::E"* %[[B_as_E]], i32 1)
@


1.1.1.5
log
@Import Clang 3.6RC1 r227398.
@
text
@d35 2
a36 2
  // CHECK:   %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to i32 (...)***
  // CHECK:   store i32 (...)** bitcast ([3 x i8*]* @@"\01??_7B@@@@6B@@" to i32 (...)**), i32 (...)*** %[[VFPTR]]
d68 2
a69 2
  // CHECK:   %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to i32 (...)***
  // CHECK:   store i32 (...)** bitcast ([3 x i8*]* @@"\01??_7B@@@@6B@@" to i32 (...)**), i32 (...)*** %[[VFPTR]]
d99 1
a99 1
  // CHECK2-LABEL: define linkonce_odr x86_thiscallcc i8* @@"\01??_GB@@@@UAEPAXI@@Z"
d125 4
a128 3
// CHECK: %[[VBPTR8:.*]] = bitcast i8* %[[VBPTR]] to i32**
// CHECK: %[[VBTABLE:.*]] = load i32** %[[VBPTR8]]
// CHECK: %[[VBENTRY:.*]] = getelementptr inbounds i32* %[[VBTABLE]], i32 1
d150 4
a153 3
// CHECK: %[[VBPTR8:.*]] = bitcast i8* %[[VBPTR]] to i32**
// CHECK: %[[VBTABLE:.*]] = load i32** %[[VBPTR8]]
// CHECK: %[[VBENTRY:.*]] = getelementptr inbounds i32* %[[VBTABLE]], i32 1
d164 4
a167 3
// CHECK: %[[VBPTR8:.*]] = bitcast i8* %[[VBPTR]] to i32**
// CHECK: %[[VBTABLE:.*]] = load i32** %[[VBPTR8]]
// CHECK: %[[VBENTRY:.*]] = getelementptr inbounds i32* %[[VBTABLE]], i32 1
d184 4
a187 3
// CHECK: %[[VBPTR8:.*]] = bitcast i8* %[[VBPTR]] to i32**
// CHECK: %[[VBTABLE:.*]] = load i32** %[[VBPTR8]]
// CHECK: %[[VBENTRY:.*]] = getelementptr inbounds i32* %[[VBTABLE]], i32 1
d191 4
a194 4
// CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VBASE_i8]] to i8* (%struct.B*, i32)***
// CHECK: %[[VFTABLE:.*]] = load i8* (%struct.B*, i32)*** %[[VFPTR]]
// CHECK: %[[VFUN:.*]] = getelementptr inbounds i8* (%struct.B*, i32)** %[[VFTABLE]], i64 0
// CHECK: %[[VFUN_VALUE:.*]] = load i8* (%struct.B*, i32)** %[[VFUN]]
d198 4
a201 3
// CHECK: %[[VBPTR8:.*]] = bitcast i8* %[[VBPTR]] to i32**
// CHECK: %[[VBTABLE:.*]] = load i32** %[[VBPTR8]]
// CHECK: %[[VBENTRY:.*]] = getelementptr inbounds i32* %[[VBTABLE]], i32 1
d207 1
a207 1
// CHECK: call x86_thiscallcc i8* %[[VFUN_VALUE]](%struct.B* %[[VBASE]], i32 1)
d253 3
a255 3
  // CHECK: store i32 (...)** bitcast ([1 x i8*]* @@"\01??_7D@@multiple_vbases@@@@6BA@@1@@@@" to i32 (...)**), i32 (...)*** %{{.*}}
  // CHECK: store i32 (...)** bitcast ([1 x i8*]* @@"\01??_7D@@multiple_vbases@@@@6BB@@1@@@@" to i32 (...)**), i32 (...)*** %{{.*}}
  // CHECK: store i32 (...)** bitcast ([1 x i8*]* @@"\01??_7D@@multiple_vbases@@@@6BC@@1@@@@" to i32 (...)**), i32 (...)*** %{{.*}}
d404 2
a405 2
  // CHECK: %[[VFPTR_i8:.*]] = bitcast %"struct.test4::C"* %{{.*}} to i32 (...)***
  // CHECK: store i32 (...)** bitcast ([1 x i8*]* @@"\01??_7C@@test4@@@@6BB@@1@@@@" to i32 (...)**), i32 (...)*** %[[VFPTR_i8]]
d415 5
a419 5
  // CHECK: %[[VPTR:.*]] = bitcast %"struct.test4::C"* %[[OBJ:.*]] to i8* (%"struct.test4::C"*, i32)***
  // CHECK: %[[VFTABLE:.*]] = load i8* (%"struct.test4::C"*, i32)*** %[[VPTR]]
  // CHECK: %[[VFTENTRY:.*]] = getelementptr inbounds i8* (%"struct.test4::C"*, i32)** %[[VFTABLE]], i64 0
  // CHECK: %[[VFUN:.*]] = load i8* (%"struct.test4::C"*, i32)** %[[VFTENTRY]]
  // CHECK: call x86_thiscallcc i8* %[[VFUN]](%"struct.test4::C"* %[[OBJ]], i32 1)
d439 2
a440 2
  // CHECK: %[[VFPTR_i8:.*]] = bitcast %"struct.test4::E"* %{{.*}} to i32 (...)***
  // CHECK: store i32 (...)** bitcast ([1 x i8*]* @@"\01??_7E@@test4@@@@6BD@@1@@@@" to i32 (...)**), i32 (...)*** %[[VFPTR_i8]]
d450 4
a453 4
  // CHECK: %[[VPTR:.*]] = bitcast i8* %[[B_i8]] to i8* (%"struct.test4::E"*, i32)***
  // CHECK: %[[VFTABLE:.*]] = load i8* (%"struct.test4::E"*, i32)*** %[[VPTR]]
  // CHECK: %[[VFTENTRY:.*]] = getelementptr inbounds i8* (%"struct.test4::E"*, i32)** %[[VFTABLE]], i64 0
  // CHECK: %[[VFUN:.*]] = load i8* (%"struct.test4::E"*, i32)** %[[VFTENTRY]]
d458 1
a458 1
  // CHECK: call x86_thiscallcc i8* %[[VFUN]](%"struct.test4::E"* %[[B_as_E]], i32 1)
@


1.1.1.6
log
@Import Clang 3.8.0rc3 r261930.
@
text
@d24 1
a24 1
  // CHECK:   %[[THIS:.*]] = load %struct.B*, %struct.B**
d31 1
a31 1
  // CHECK:   %[[VBPTR:.*]] = getelementptr inbounds i8, i8* %[[THIS_i8]], i32 0
d34 1
a34 1
  // CHECK:   %[[VFPTR_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_i8]], i32 %{{.*}}
d40 1
a40 1
  // CHECK:   %[[VBPTR:.*]] = getelementptr inbounds i8, i8* %[[THIS_i8]], i32 0
d45 2
a46 2
  // CHECK:   %[[VBASE_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_i8]], i32 %[[VBASE_OFFSET]]
  // CHECK:   %[[VTORDISP_i8:.*]] = getelementptr i8, i8* %[[VBASE_i8]], i32 -4
d57 1
a57 1
  // CHECK:   %[[THIS_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_PARAM_i8]], i32 -8
d60 1
a60 1
  // CHECK:   %[[THIS:.*]] = load %struct.B*, %struct.B** %[[THIS_ADDR]]
d64 1
a64 1
  // CHECK:   %[[VBPTR:.*]] = getelementptr inbounds i8, i8* %[[THIS_i8]], i32 0
d67 1
a67 1
  // CHECK:   %[[VFPTR_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_i8]], i32 %{{.*}}
d73 1
a73 1
  // CHECK:   %[[VBPTR:.*]] = getelementptr inbounds i8, i8* %[[THIS_i8]], i32 0
d78 2
a79 2
  // CHECK:   %[[VBASE_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_i8]], i32 %[[VBASE_OFFSET]]
  // CHECK:   %[[VTORDISP_i8:.*]] = getelementptr i8, i8* %[[VBASE_i8]], i32 -4
d88 1
a88 1
  // CHECK2: %[[THIS:.*]] = load %struct.B*, %struct.B** {{.*}}
d90 1
a90 1
  // CHECK2: %[[B_i8:.*]] = getelementptr i8, i8* %[[THIS_i8]], i32 8
d94 1
a94 1
  // CHECK2: %[[VBASE_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_i8]], i32 8
d101 1
a101 1
  // CHECK2:   %[[THIS_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_PARAM_i8:.*]], i32 -8
d104 1
a104 1
  // CHECK2:   %[[THIS:.*]] = load %struct.B*, %struct.B** %[[THIS_ADDR]]
d117 1
a117 1
// CHECK: %[[THIS_i8:.*]] = getelementptr inbounds i8, i8* %[[ECX:.*]], i32 -8
d122 1
a122 1
// CHECK: %[[THIS:.*]] = load %struct.B*, %struct.B** %[[THIS_ADDR]]
d124 1
a124 1
// CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8, i8* %[[THIS8]], i32 0
d126 3
a128 3
// CHECK: %[[VBTABLE:.*]] = load i32*, i32** %[[VBPTR8]]
// CHECK: %[[VBENTRY:.*]] = getelementptr inbounds i32, i32* %[[VBTABLE]], i32 1
// CHECK: %[[VBOFFSET32:.*]] = load i32, i32* %[[VBENTRY]]
d131 1
a131 1
// CHECK: %[[VBASE_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS8]], i32 %[[VBOFFSET]]
d133 1
a133 1
// CHECK: %[[FIELD:.*]] = getelementptr inbounds %struct.VBase, %struct.VBase* %[[VBASE]], i32 0, i32 1
d148 1
a148 1
// CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8, i8* %[[OBJ_i8]], i32 0
d150 3
a152 3
// CHECK: %[[VBTABLE:.*]] = load i32*, i32** %[[VBPTR8]]
// CHECK: %[[VBENTRY:.*]] = getelementptr inbounds i32, i32* %[[VBTABLE]], i32 1
// CHECK: %[[VBOFFSET32:.*]] = load i32, i32* %[[VBENTRY]]
d154 1
a154 1
// CHECK: %[[VBASE_i8:.*]] = getelementptr inbounds i8, i8* %[[OBJ_i8]], i32 %[[VBOFFSET]]
d156 3
a158 3
// CHECK: %[[VFTABLE:.*]] = load void (i8*)**, void (i8*)*** %[[VFPTR]]
// CHECK: %[[VFUN:.*]] = getelementptr inbounds void (i8*)*, void (i8*)** %[[VFTABLE]], i64 2
// CHECK: %[[VFUN_VALUE:.*]] = load void (i8*)*, void (i8*)** %[[VFUN]]
d161 1
a161 1
// CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8, i8* %[[OBJ_i8]], i32 0
d163 3
a165 3
// CHECK: %[[VBTABLE:.*]] = load i32*, i32** %[[VBPTR8]]
// CHECK: %[[VBENTRY:.*]] = getelementptr inbounds i32, i32* %[[VBTABLE]], i32 1
// CHECK: %[[VBOFFSET32:.*]] = load i32, i32* %[[VBENTRY]]
d167 1
a167 1
// CHECK: %[[VBASE:.*]] = getelementptr inbounds i8, i8* %[[OBJ_i8]], i32 %[[VBOFFSET]]
d180 1
a180 1
// CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8, i8* %[[OBJ_i8]], i32 0
d182 3
a184 3
// CHECK: %[[VBTABLE:.*]] = load i32*, i32** %[[VBPTR8]]
// CHECK: %[[VBENTRY:.*]] = getelementptr inbounds i32, i32* %[[VBTABLE]], i32 1
// CHECK: %[[VBOFFSET32:.*]] = load i32, i32* %[[VBENTRY]]
d186 1
a186 1
// CHECK: %[[VBASE_i8:.*]] = getelementptr inbounds i8, i8* %[[OBJ_i8]], i32 %[[VBOFFSET]]
d188 3
a190 3
// CHECK: %[[VFTABLE:.*]] = load i8* (%struct.B*, i32)**, i8* (%struct.B*, i32)*** %[[VFPTR]]
// CHECK: %[[VFUN:.*]] = getelementptr inbounds i8* (%struct.B*, i32)*, i8* (%struct.B*, i32)** %[[VFTABLE]], i64 0
// CHECK: %[[VFUN_VALUE:.*]] = load i8* (%struct.B*, i32)*, i8* (%struct.B*, i32)** %[[VFUN]]
d193 1
a193 1
// CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8, i8* %[[OBJ_i8]], i32 0
d195 3
a197 3
// CHECK: %[[VBTABLE:.*]] = load i32*, i32** %[[VBPTR8]]
// CHECK: %[[VBENTRY:.*]] = getelementptr inbounds i32, i32* %[[VBTABLE]], i32 1
// CHECK: %[[VBOFFSET32:.*]] = load i32, i32* %[[VBENTRY]]
d199 1
a199 1
// CHECK: %[[VBASE_i8:.*]] = getelementptr inbounds i8, i8* %[[OBJ_i8]], i32 %[[VBOFFSET]]
d288 1
a288 1
  // CHECK: %[[THIS_i8:.*]] = getelementptr inbounds i8, i8* %[[ARG_i8]], i32 -24
d291 1
a291 1
  // CHECK: %[[THIS:.*]] = load %"struct.diamond::D"*, %"struct.diamond::D"** %[[THIS_VAL]]
d293 1
a293 1
  // CHECK: %[[C_i8:.*]] = getelementptr inbounds i8, i8* %[[D_i8]], i32 4
d296 1
a296 1
  // CHECK: %[[ARG_i8:.*]] = getelementptr i8, i8* %{{.*}}, i32 16
d303 1
a303 1
  // CHECK: %[[ARG_i8:.*]] = getelementptr i8, i8* %[[B_i8]], i32 4
d365 1
a365 1
  // CHECK-NOT: load i8*, i8**
d367 1
a367 1
  // CHECK: %[[C_i8:.*]] = getelementptr inbounds i8, i8* %[[OBJ_i8]], i32 8
d370 1
a370 1
  // CHECK: %[[ARG:.*]] = getelementptr i8, i8* %[[C_i8]], i32 4
d411 3
a413 3
  // CHECK: %[[VFTABLE:.*]] = load i8* (%"struct.test4::C"*, i32)**, i8* (%"struct.test4::C"*, i32)*** %[[VPTR]]
  // CHECK: %[[VFTENTRY:.*]] = getelementptr inbounds i8* (%"struct.test4::C"*, i32)*, i8* (%"struct.test4::C"*, i32)** %[[VFTABLE]], i64 0
  // CHECK: %[[VFUN:.*]] = load i8* (%"struct.test4::C"*, i32)*, i8* (%"struct.test4::C"*, i32)** %[[VFTENTRY]]
d444 1
a444 1
  // CHECK: %[[B_i8:.*]] = getelementptr inbounds i8, i8* %[[OBJ_i8]], i32 4
d446 3
a448 3
  // CHECK: %[[VFTABLE:.*]] = load i8* (%"struct.test4::E"*, i32)**, i8* (%"struct.test4::E"*, i32)*** %[[VPTR]]
  // CHECK: %[[VFTENTRY:.*]] = getelementptr inbounds i8* (%"struct.test4::E"*, i32)*, i8* (%"struct.test4::E"*, i32)** %[[VFTABLE]], i64 0
  // CHECK: %[[VFUN:.*]] = load i8* (%"struct.test4::E"*, i32)*, i8* (%"struct.test4::E"*, i32)** %[[VFTENTRY]]
d450 1
a450 1
  // CHECK: %[[B_i8:.*]] = getelementptr inbounds i8, i8* %[[OBJ_i8]], i32 4
a457 26

namespace test5 {
// PR25370: Don't zero-initialize vbptrs in virtual bases.
struct A {
  virtual void f();
};

struct B : virtual A {
  int Field;
};

struct C : B {
  C();
};

C::C() : B() {}
// CHECK-LABEL: define x86_thiscallcc %"struct.test5::C"* @@"\01??0C@@test5@@@@QAE@@XZ"(
// CHECK:   %[[THIS:.*]] = load %"struct.test5::C"*, %"struct.test5::C"**
// CHECK:   br i1 %{{.*}}, label %[[INIT_VBASES:.*]], label %[[SKIP_VBASES:.*]]

// CHECK: %[[SKIP_VBASES]]
// CHECK:   %[[B:.*]] = bitcast %"struct.test5::C"* %[[THIS]] to %"struct.test5::B"*
// CHECK:   %[[B_i8:.*]] = bitcast %"struct.test5::B"* %[[B]] to i8*
// CHECK:   %[[FIELD:.*]] = getelementptr inbounds i8, i8* %[[B_i8]], i32 4
// CHECK:   call void @@llvm.memset.p0i8.i32(i8* %[[FIELD]], i8 0, i32 4, i32 4, i1 false)
}
@


1.1.1.6.2.1
log
@Sync with HEAD
@
text
@d36 1
a36 1
  // CHECK:   store i32 (...)** bitcast ({ [3 x i8*] }* @@"\01??_7B@@@@6B@@" to i32 (...)**), i32 (...)*** %[[VFPTR]]
d69 1
a69 1
  // CHECK:   store i32 (...)** bitcast ({ [3 x i8*] }* @@"\01??_7B@@@@6B@@" to i32 (...)**), i32 (...)*** %[[VFPTR]]
d248 3
a250 3
  // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @@"\01??_7D@@multiple_vbases@@@@6BA@@1@@@@" to i32 (...)**), i32 (...)*** %{{.*}}
  // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @@"\01??_7D@@multiple_vbases@@@@6BB@@1@@@@" to i32 (...)**), i32 (...)*** %{{.*}}
  // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @@"\01??_7D@@multiple_vbases@@@@6BC@@1@@@@" to i32 (...)**), i32 (...)*** %{{.*}}
d286 1
a286 1
  // CHECK-LABEL: define x86_thiscallcc void @@"\01??1D@@diamond@@@@UAE@@XZ"(%"struct.diamond::D"*{{.*}})
d400 1
a400 1
  // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @@"\01??_7C@@test4@@@@6BB@@1@@@@" to i32 (...)**), i32 (...)*** %[[VFPTR_i8]]
d435 1
a435 1
  // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @@"\01??_7E@@test4@@@@6BD@@1@@@@" to i32 (...)**), i32 (...)*** %[[VFPTR_i8]]
a483 40

namespace pr27621 {
// Devirtualization through a static_cast used to make us compute the 'this'
// adjustment for B::g instead of C::g. When we directly call C::g, 'this' is a
// B*, and the prologue of C::g will adjust it to a C*.
struct A { virtual void f(); };
struct B { virtual void g(); };
struct C final : A, B {
  virtual void h();
  void g() override;
};
void callit(C *p) {
  static_cast<B*>(p)->g();
}
// CHECK-LABEL: define void @@"\01?callit@@pr27621@@@@YAXPAUC@@1@@@@Z"(%"struct.pr27621::C"* %{{.*}})
// CHECK: %[[B_i8:.*]] = getelementptr i8, i8* %{{.*}}, i32 4
// CHECK: call x86_thiscallcc void @@"\01?g@@C@@pr27621@@@@UAEXXZ"(i8* %[[B_i8]])
}

namespace test6 {
class A {};
class B : virtual A {};
class C : virtual B {
  virtual void m_fn1();
  float field;
};
class D : C {
  D();
};
D::D() : C() {}
// CHECK-LABEL: define x86_thiscallcc %"class.test6::D"* @@"\01??0D@@test6@@@@AAE@@XZ"(
// CHECK:   %[[THIS:.*]] = load %"class.test6::D"*, %"class.test6::D"**
// CHECK:   br i1 %{{.*}}, label %[[INIT_VBASES:.*]], label %[[SKIP_VBASES:.*]]

// CHECK: %[[SKIP_VBASES]]
// CHECK:   %[[C:.*]] = bitcast %"class.test6::D"* %[[THIS]] to %"class.test6::C"*
// CHECK:   %[[C_i8:.*]] = bitcast %"class.test6::C"* %[[C]] to i8*
// CHECK:   %[[FIELD:.*]] = getelementptr inbounds i8, i8* %[[C_i8]], i32 8
// CHECK:   call void @@llvm.memset.p0i8.i32(i8* %[[FIELD]], i8 0, i32 4, i32 4, i1 false)
}
@


1.1.1.7
log
@Import Clang pre-4.0.0 r291444.
@
text
@d36 1
a36 1
  // CHECK:   store i32 (...)** bitcast ({ [3 x i8*] }* @@"\01??_7B@@@@6B@@" to i32 (...)**), i32 (...)*** %[[VFPTR]]
d69 1
a69 1
  // CHECK:   store i32 (...)** bitcast ({ [3 x i8*] }* @@"\01??_7B@@@@6B@@" to i32 (...)**), i32 (...)*** %[[VFPTR]]
d248 3
a250 3
  // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @@"\01??_7D@@multiple_vbases@@@@6BA@@1@@@@" to i32 (...)**), i32 (...)*** %{{.*}}
  // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @@"\01??_7D@@multiple_vbases@@@@6BB@@1@@@@" to i32 (...)**), i32 (...)*** %{{.*}}
  // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @@"\01??_7D@@multiple_vbases@@@@6BC@@1@@@@" to i32 (...)**), i32 (...)*** %{{.*}}
d286 1
a286 1
  // CHECK-LABEL: define x86_thiscallcc void @@"\01??1D@@diamond@@@@UAE@@XZ"(%"struct.diamond::D"*{{.*}})
d400 1
a400 1
  // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @@"\01??_7C@@test4@@@@6BB@@1@@@@" to i32 (...)**), i32 (...)*** %[[VFPTR_i8]]
d435 1
a435 1
  // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @@"\01??_7E@@test4@@@@6BD@@1@@@@" to i32 (...)**), i32 (...)*** %[[VFPTR_i8]]
a483 40

namespace pr27621 {
// Devirtualization through a static_cast used to make us compute the 'this'
// adjustment for B::g instead of C::g. When we directly call C::g, 'this' is a
// B*, and the prologue of C::g will adjust it to a C*.
struct A { virtual void f(); };
struct B { virtual void g(); };
struct C final : A, B {
  virtual void h();
  void g() override;
};
void callit(C *p) {
  static_cast<B*>(p)->g();
}
// CHECK-LABEL: define void @@"\01?callit@@pr27621@@@@YAXPAUC@@1@@@@Z"(%"struct.pr27621::C"* %{{.*}})
// CHECK: %[[B_i8:.*]] = getelementptr i8, i8* %{{.*}}, i32 4
// CHECK: call x86_thiscallcc void @@"\01?g@@C@@pr27621@@@@UAEXXZ"(i8* %[[B_i8]])
}

namespace test6 {
class A {};
class B : virtual A {};
class C : virtual B {
  virtual void m_fn1();
  float field;
};
class D : C {
  D();
};
D::D() : C() {}
// CHECK-LABEL: define x86_thiscallcc %"class.test6::D"* @@"\01??0D@@test6@@@@AAE@@XZ"(
// CHECK:   %[[THIS:.*]] = load %"class.test6::D"*, %"class.test6::D"**
// CHECK:   br i1 %{{.*}}, label %[[INIT_VBASES:.*]], label %[[SKIP_VBASES:.*]]

// CHECK: %[[SKIP_VBASES]]
// CHECK:   %[[C:.*]] = bitcast %"class.test6::D"* %[[THIS]] to %"class.test6::C"*
// CHECK:   %[[C_i8:.*]] = bitcast %"class.test6::C"* %[[C]] to i8*
// CHECK:   %[[FIELD:.*]] = getelementptr inbounds i8, i8* %[[C_i8]], i32 8
// CHECK:   call void @@llvm.memset.p0i8.i32(i8* %[[FIELD]], i8 0, i32 4, i32 4, i1 false)
}
@


1.1.1.8
log
@Import clang r309604 from branches/release_50
@
text
@d87 1
a87 1
  // CHECK2-LABEL: define linkonce_odr x86_thiscallcc void @@"\01??_DB@@@@QAEXXZ"(%struct.B*
d105 1
a105 1
  // CHECK2:   call x86_thiscallcc void @@"\01??_DB@@@@QAEXXZ"(%struct.B* %[[THIS]])
d211 1
a211 1
  // CHECK: call x86_thiscallcc void @@"\01??_DB@@@@QAEXXZ"(%struct.B* %[[B]])
@


1.1.1.8.4.1
log
@Sync with HEAD
@
text
@d1 1
a1 1
// RUN: %clang_cc1 %s -fno-rtti -std=c++11 -Wno-inaccessible-base -triple=i386-pc-win32 -emit-llvm -o %t
d6 1
a6 1
// RUN: %clang_cc1 %s -fno-rtti -std=c++11 -Wno-inaccessible-base -triple=x86_64-pc-win32 -emit-llvm -o %t
d23 1
a23 1
  // CHECK-LABEL: define dso_local x86_thiscallcc %struct.B* @@"??0B@@@@QAE@@XZ"
d36 1
a36 1
  // CHECK:   store i32 (...)** bitcast ({ [3 x i8*] }* @@"??_7B@@@@6B@@" to i32 (...)**), i32 (...)*** %[[VFPTR]]
d54 7
a60 9
  // CHECK-LABEL: define dso_local x86_thiscallcc void @@"??1B@@@@UAE@@XZ"
  // Store initial this:
  // CHECK:   %[[THIS_ADDR:.*]] = alloca %struct.B*
  // CHECK:   store %struct.B* %{{.*}}, %struct.B** %[[THIS_ADDR]], align 4
  // Reload and adjust the this parameter:
  // CHECK:   %[[THIS_RELOAD:.*]] = load %struct.B*, %struct.B** %[[THIS_ADDR]]
  // CHECK:   %[[THIS_UNADJ_i8:.*]] = bitcast %struct.B* %[[THIS_RELOAD]] to i8*
  // CHECK:   %[[THIS_ADJ_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_UNADJ_i8]], i32 -8
  // CHECK:   %[[THIS:.*]] = bitcast i8* %[[THIS_ADJ_i8]] to %struct.B*
d69 1
a69 1
  // CHECK:   store i32 (...)** bitcast ({ [3 x i8*] }* @@"??_7B@@@@6B@@" to i32 (...)**), i32 (...)*** %[[VFPTR]]
d87 1
a87 1
  // CHECK2-LABEL: define linkonce_odr dso_local x86_thiscallcc void @@"??_DB@@@@QAEXXZ"(%struct.B*
d92 1
a92 1
  // CHECK2: call x86_thiscallcc void @@"??1B@@@@UAE@@XZ"(%struct.B* %[[B]])
d96 1
a96 1
  // CHECK2: call x86_thiscallcc void @@"??1VBase@@@@UAE@@XZ"(%struct.VBase* %[[VBASE]])
d99 2
a100 4
  // CHECK2-LABEL: define linkonce_odr dso_local x86_thiscallcc i8* @@"??_GB@@@@UAEPAXI@@Z"
  // CHECK2:   store %struct.B* %{{.*}}, %struct.B** %[[THIS_ADDR:.*]], align 4
  // CHECK2:   %[[THIS:.*]] = load %struct.B*, %struct.B** %[[THIS_ADDR]]
  // CHECK2:   %[[THIS_PARAM_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
d103 3
a105 1
  // CHECK2:   call x86_thiscallcc void @@"??_DB@@@@QAEXXZ"(%struct.B* %[[THIS]])
d111 1
a111 1
// CHECK-LABEL: define dso_local x86_thiscallcc void @@"?foo@@B@@@@UAEXXZ"(i8*
d116 4
a119 15
// Coerce this to correct type:
// CHECK:   %[[THIS_STORE:.*]] = alloca %struct.B*
// CHECK:   %[[THIS_ADDR:.*]] = alloca %struct.B*
// CHECK:   %[[COERCE_VAL:.*]] = bitcast i8* %{{.*}} to %struct.B*
// CHECK:   store %struct.B* %[[COERCE_VAL]], %struct.B** %[[THIS_STORE]], align 4
//
// Store initial this:
// CHECK:   %[[THIS_INIT:.*]] = load %struct.B*, %struct.B** %[[THIS_STORE]]
// CHECK:   store %struct.B* %[[THIS_INIT]], %struct.B** %[[THIS_ADDR]], align 4
//
// Reload and adjust the this parameter:
// CHECK:   %[[THIS_RELOAD:.*]] = load %struct.B*, %struct.B** %[[THIS_ADDR]]
// CHECK:   %[[THIS_UNADJ_i8:.*]] = bitcast %struct.B* %[[THIS_RELOAD]] to i8*
// CHECK:   %[[THIS_ADJ_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_UNADJ_i8]], i32 -8
// CHECK:   %[[THIS:.*]] = bitcast i8* %[[THIS_ADJ_i8]] to %struct.B*
d122 1
d140 1
a140 1
// CHECK-LABEL: define dso_local void @@"?call_vbase_bar@@@@YAXPAUB@@@@@@Z"(%struct.B* %obj)
d154 5
a158 1
// CHECK: %[[VBASE:.*]] = getelementptr inbounds i8, i8* %[[OBJ_i8]], i32 %[[VBOFFSET]]
d167 1
a167 5
// CHECK: %[[VBASE_i8:.*]] = getelementptr inbounds i8, i8* %[[OBJ_i8]], i32 %[[VBOFFSET]]
// CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VBASE_i8]] to void (i8*)***
// CHECK: %[[VFTABLE:.*]] = load void (i8*)**, void (i8*)*** %[[VFPTR]]
// CHECK: %[[VFUN:.*]] = getelementptr inbounds void (i8*)*, void (i8*)** %[[VFTABLE]], i64 2
// CHECK: %[[VFUN_VALUE:.*]] = load void (i8*)*, void (i8*)** %[[VFUN]]
d175 1
a175 1
// CHECK-LABEL: define dso_local void @@"?delete_B@@@@YAXPAUB@@@@@@Z"(%struct.B* %obj)
d187 4
a190 1
// CHECK: %[[VBASE:.*]] = bitcast i8* %[[VBASE_i8]] to %struct.B*
d200 1
a200 4
// CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VBASE_i8]] to i8* (%struct.B*, i32)***
// CHECK: %[[VFTABLE:.*]] = load i8* (%struct.B*, i32)**, i8* (%struct.B*, i32)*** %[[VFPTR]]
// CHECK: %[[VFUN:.*]] = getelementptr inbounds i8* (%struct.B*, i32)*, i8* (%struct.B*, i32)** %[[VFTABLE]], i64 0
// CHECK: %[[VFUN_VALUE:.*]] = load i8* (%struct.B*, i32)*, i8* (%struct.B*, i32)** %[[VFUN]]
d207 1
a207 1
  // CHECK-LABEL: define dso_local void @@"?call_complete_dtor@@@@YAXXZ"
d209 1
a209 1
  // CHECK: call x86_thiscallcc %struct.B* @@"??0B@@@@QAE@@XZ"(%struct.B* %[[B:.*]], i32 1)
d211 1
a211 1
  // CHECK: call x86_thiscallcc void @@"??_DB@@@@QAEXXZ"(%struct.B* %[[B]])
d222 1
a222 1
// CHECK-LABEL: define dso_local x86_thiscallcc %struct.C* @@"??0C@@@@QAE@@XZ"
d246 1
a246 1
  // CHECK-LABEL: define dso_local x86_thiscallcc %"struct.multiple_vbases::D"* @@"??0D@@multiple_vbases@@@@QAE@@XZ"
d248 3
a250 3
  // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @@"??_7D@@multiple_vbases@@@@6BA@@1@@@@" to i32 (...)**), i32 (...)*** %{{.*}}
  // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @@"??_7D@@multiple_vbases@@@@6BB@@1@@@@" to i32 (...)**), i32 (...)*** %{{.*}}
  // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @@"??_7D@@multiple_vbases@@@@6BC@@1@@@@" to i32 (...)**), i32 (...)*** %{{.*}}
d286 6
a291 11
  // CHECK-LABEL: define dso_local x86_thiscallcc void @@"??1D@@diamond@@@@UAE@@XZ"(%"struct.diamond::D"*{{.*}})
  // Store initial this:
  // CHECK: %[[THIS_ADDR:.*]] = alloca %"struct.diamond::D"*
  // CHECK: store %"struct.diamond::D"* %{{.*}}, %"struct.diamond::D"** %[[THIS_ADDR]], align 4
  //
  // Reload and adjust the this parameter:
  // CHECK: %[[THIS_RELOAD:.*]] = load %"struct.diamond::D"*, %"struct.diamond::D"** %[[THIS_ADDR]]
  // CHECK: %[[THIS_UNADJ_i8:.*]] = bitcast %"struct.diamond::D"* %[[THIS_RELOAD]] to i8*
  // CHECK: %[[THIS_ADJ_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_UNADJ_i8]], i32 -24
  // CHECK: %[[THIS:.*]] = bitcast i8* %[[THIS_ADJ_i8]] to %"struct.diamond::D"*
  //
d299 1
a299 1
  // CHECK: call x86_thiscallcc void @@"??1C@@diamond@@@@UAE@@XZ"(%"struct.diamond::C"* %[[ARG]])
d305 1
a305 1
  // CHECK: call x86_thiscallcc void @@"??1B@@diamond@@@@UAE@@XZ"(%"struct.diamond::B"* %[[ARG]])
d320 1
a320 1
// CHECK-LABEL: define linkonce_odr dso_local x86_thiscallcc %"struct.test2::C"* @@"??0C@@test2@@@@QAE@@XZ"
d324 1
a324 1
// CHECK: call x86_thiscallcc %"struct.test2::A"* @@"??0A@@test2@@@@QAE@@XZ"(%"struct.test2::A"* %{{.*}})
d327 2
a328 2
// CHECK: call x86_thiscallcc %"struct.test2::B"* @@"??0B@@test2@@@@QAE@@XZ"(%"struct.test2::B"* %{{.*}}, i32 0)
// CHECK: call x86_thiscallcc %"struct.test2::A"* @@"??0A@@test2@@@@QAE@@XZ"(%"struct.test2::A"* %{{.*}})
d331 1
a331 1
// CHECK2-LABEL: define linkonce_odr dso_local x86_thiscallcc %"struct.test2::B"* @@"??0B@@test2@@@@QAE@@XZ"
d333 1
a333 1
// CHECK2: call x86_thiscallcc %"struct.test2::A"* @@"??0A@@test2@@@@QAE@@XZ"(%"struct.test2::A"* %{{.*}})
d360 1
a360 1
  // CHECK-LABEL: define dso_local x86_thiscallcc void @@"?bar@@D@@test3@@@@UAEXXZ"(%"struct.test3::D"* %this)
d371 1
a371 1
  // CHECK: call x86_thiscallcc void @@"?foo@@C@@test3@@@@UAEXXZ"(i8* %[[ARG]])
d394 1
a394 1
  // CHECK-LABEL: define dso_local x86_thiscallcc void @@"??1C@@test4@@@@UAE@@XZ"(%"struct.test4::C"* %this)
d400 1
a400 1
  // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @@"??_7C@@test4@@@@6BB@@1@@@@" to i32 (...)**), i32 (...)*** %[[VFPTR_i8]]
d407 1
a407 1
  // CHECK-LABEL: define dso_local void @@"?destroy@@test4@@@@YAXPAUC@@1@@@@Z"(%"struct.test4::C"* %obj)
d429 1
a429 1
  // CHECK-LABEL: define dso_local x86_thiscallcc void @@"??1E@@test4@@@@UAE@@XZ"(%"struct.test4::E"* %this)
d435 1
a435 1
  // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @@"??_7E@@test4@@@@6BD@@1@@@@" to i32 (...)**), i32 (...)*** %[[VFPTR_i8]]
d440 1
a440 1
  // CHECK-LABEL: define dso_local void @@"?destroy@@test4@@@@YAXPAUE@@1@@@@Z"(%"struct.test4::E"* %obj)
a442 4
  // CHECK: %[[OBJ_i8:.*]] = bitcast %"struct.test4::E"* %[[OBJ]] to i8*
  // CHECK: %[[B_i8:.*]] = getelementptr inbounds i8, i8* %[[OBJ_i8]], i32 4
  // FIXME: in fact, the call should take i8* and the bitcast is redundant.
  // CHECK: %[[B_as_E:.*]] = bitcast i8* %[[B_i8]] to %"struct.test4::E"*
d449 4
d474 1
a474 1
// CHECK-LABEL: define dso_local x86_thiscallcc %"struct.test5::C"* @@"??0C@@test5@@@@QAE@@XZ"(
d482 1
a482 1
// CHECK:   call void @@llvm.memset.p0i8.i32(i8* align 4 %[[FIELD]], i8 0, i32 4, i1 false)
d498 1
a498 1
// CHECK-LABEL: define dso_local void @@"?callit@@pr27621@@@@YAXPAUC@@1@@@@Z"(%"struct.pr27621::C"* %{{.*}})
d500 1
a500 1
// CHECK: call x86_thiscallcc void @@"?g@@C@@pr27621@@@@UAEXXZ"(i8* %[[B_i8]])
d514 1
a514 1
// CHECK-LABEL: define dso_local x86_thiscallcc %"class.test6::D"* @@"??0D@@test6@@@@AAE@@XZ"(
d522 1
a522 18
// CHECK:   call void @@llvm.memset.p0i8.i32(i8* align 4 %[[FIELD]], i8 0, i32 4, i1 false)
}

namespace pr36921 {
struct A {
  virtual ~A() {}
};
struct B {
  virtual ~B() {}
};
struct C : virtual B {};
struct D : virtual A, C {};
D d;
// CHECK-LABEL: define linkonce_odr dso_local x86_thiscallcc i8* @@"??_GD@@pr36921@@@@UAEPAXI@@Z"(
// CHECK:   %[[THIS:.*]] = load %"struct.pr36921::D"*, %"struct.pr36921::D"**
// CHECK:   %[[THIS_UNADJ_i8:.*]] = bitcast %"struct.pr36921::D"* %[[THIS_RELOAD]] to i8*
// CHECK:   %[[THIS_ADJ_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_UNADJ_i8]], i32 -4
// CHECK:   %[[THIS:.*]] = bitcast i8* %[[THIS_ADJ_i8]] to %"struct.pr36921::D"*
@


1.1.1.8.4.2
log
@Mostly merge changes from HEAD upto 20200411
@
text
@@


1.1.1.8.2.1
log
@Sync with HEAD
@
text
@d1 1
a1 1
// RUN: %clang_cc1 %s -fno-rtti -std=c++11 -Wno-inaccessible-base -triple=i386-pc-win32 -emit-llvm -o %t
d6 1
a6 1
// RUN: %clang_cc1 %s -fno-rtti -std=c++11 -Wno-inaccessible-base -triple=x86_64-pc-win32 -emit-llvm -o %t
d23 1
a23 1
  // CHECK-LABEL: define dso_local x86_thiscallcc %struct.B* @@"??0B@@@@QAE@@XZ"
d36 1
a36 1
  // CHECK:   store i32 (...)** bitcast ({ [3 x i8*] }* @@"??_7B@@@@6B@@" to i32 (...)**), i32 (...)*** %[[VFPTR]]
d54 7
a60 9
  // CHECK-LABEL: define dso_local x86_thiscallcc void @@"??1B@@@@UAE@@XZ"
  // Store initial this:
  // CHECK:   %[[THIS_ADDR:.*]] = alloca %struct.B*
  // CHECK:   store %struct.B* %{{.*}}, %struct.B** %[[THIS_ADDR]], align 4
  // Reload and adjust the this parameter:
  // CHECK:   %[[THIS_RELOAD:.*]] = load %struct.B*, %struct.B** %[[THIS_ADDR]]
  // CHECK:   %[[THIS_UNADJ_i8:.*]] = bitcast %struct.B* %[[THIS_RELOAD]] to i8*
  // CHECK:   %[[THIS_ADJ_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_UNADJ_i8]], i32 -8
  // CHECK:   %[[THIS:.*]] = bitcast i8* %[[THIS_ADJ_i8]] to %struct.B*
d69 1
a69 1
  // CHECK:   store i32 (...)** bitcast ({ [3 x i8*] }* @@"??_7B@@@@6B@@" to i32 (...)**), i32 (...)*** %[[VFPTR]]
d87 1
a87 1
  // CHECK2-LABEL: define linkonce_odr dso_local x86_thiscallcc void @@"??_DB@@@@QAEXXZ"(%struct.B*
d92 1
a92 1
  // CHECK2: call x86_thiscallcc void @@"??1B@@@@UAE@@XZ"(%struct.B* %[[B]])
d96 1
a96 1
  // CHECK2: call x86_thiscallcc void @@"??1VBase@@@@UAE@@XZ"(%struct.VBase* %[[VBASE]])
d99 2
a100 4
  // CHECK2-LABEL: define linkonce_odr dso_local x86_thiscallcc i8* @@"??_GB@@@@UAEPAXI@@Z"
  // CHECK2:   store %struct.B* %{{.*}}, %struct.B** %[[THIS_ADDR:.*]], align 4
  // CHECK2:   %[[THIS:.*]] = load %struct.B*, %struct.B** %[[THIS_ADDR]]
  // CHECK2:   %[[THIS_PARAM_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
d103 3
a105 1
  // CHECK2:   call x86_thiscallcc void @@"??_DB@@@@QAEXXZ"(%struct.B* %[[THIS]])
d111 1
a111 1
// CHECK-LABEL: define dso_local x86_thiscallcc void @@"?foo@@B@@@@UAEXXZ"(i8*
d116 4
a119 15
// Coerce this to correct type:
// CHECK:   %[[THIS_STORE:.*]] = alloca %struct.B*
// CHECK:   %[[THIS_ADDR:.*]] = alloca %struct.B*
// CHECK:   %[[COERCE_VAL:.*]] = bitcast i8* %{{.*}} to %struct.B*
// CHECK:   store %struct.B* %[[COERCE_VAL]], %struct.B** %[[THIS_STORE]], align 4
//
// Store initial this:
// CHECK:   %[[THIS_INIT:.*]] = load %struct.B*, %struct.B** %[[THIS_STORE]]
// CHECK:   store %struct.B* %[[THIS_INIT]], %struct.B** %[[THIS_ADDR]], align 4
//
// Reload and adjust the this parameter:
// CHECK:   %[[THIS_RELOAD:.*]] = load %struct.B*, %struct.B** %[[THIS_ADDR]]
// CHECK:   %[[THIS_UNADJ_i8:.*]] = bitcast %struct.B* %[[THIS_RELOAD]] to i8*
// CHECK:   %[[THIS_ADJ_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_UNADJ_i8]], i32 -8
// CHECK:   %[[THIS:.*]] = bitcast i8* %[[THIS_ADJ_i8]] to %struct.B*
d122 1
d140 1
a140 1
// CHECK-LABEL: define dso_local void @@"?call_vbase_bar@@@@YAXPAUB@@@@@@Z"(%struct.B* %obj)
d154 5
a158 1
// CHECK: %[[VBASE:.*]] = getelementptr inbounds i8, i8* %[[OBJ_i8]], i32 %[[VBOFFSET]]
d167 1
a167 5
// CHECK: %[[VBASE_i8:.*]] = getelementptr inbounds i8, i8* %[[OBJ_i8]], i32 %[[VBOFFSET]]
// CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VBASE_i8]] to void (i8*)***
// CHECK: %[[VFTABLE:.*]] = load void (i8*)**, void (i8*)*** %[[VFPTR]]
// CHECK: %[[VFUN:.*]] = getelementptr inbounds void (i8*)*, void (i8*)** %[[VFTABLE]], i64 2
// CHECK: %[[VFUN_VALUE:.*]] = load void (i8*)*, void (i8*)** %[[VFUN]]
d175 1
a175 1
// CHECK-LABEL: define dso_local void @@"?delete_B@@@@YAXPAUB@@@@@@Z"(%struct.B* %obj)
d187 4
a190 1
// CHECK: %[[VBASE:.*]] = bitcast i8* %[[VBASE_i8]] to %struct.B*
d200 1
a200 4
// CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VBASE_i8]] to i8* (%struct.B*, i32)***
// CHECK: %[[VFTABLE:.*]] = load i8* (%struct.B*, i32)**, i8* (%struct.B*, i32)*** %[[VFPTR]]
// CHECK: %[[VFUN:.*]] = getelementptr inbounds i8* (%struct.B*, i32)*, i8* (%struct.B*, i32)** %[[VFTABLE]], i64 0
// CHECK: %[[VFUN_VALUE:.*]] = load i8* (%struct.B*, i32)*, i8* (%struct.B*, i32)** %[[VFUN]]
d207 1
a207 1
  // CHECK-LABEL: define dso_local void @@"?call_complete_dtor@@@@YAXXZ"
d209 1
a209 1
  // CHECK: call x86_thiscallcc %struct.B* @@"??0B@@@@QAE@@XZ"(%struct.B* %[[B:.*]], i32 1)
d211 1
a211 1
  // CHECK: call x86_thiscallcc void @@"??_DB@@@@QAEXXZ"(%struct.B* %[[B]])
d222 1
a222 1
// CHECK-LABEL: define dso_local x86_thiscallcc %struct.C* @@"??0C@@@@QAE@@XZ"
d246 1
a246 1
  // CHECK-LABEL: define dso_local x86_thiscallcc %"struct.multiple_vbases::D"* @@"??0D@@multiple_vbases@@@@QAE@@XZ"
d248 3
a250 3
  // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @@"??_7D@@multiple_vbases@@@@6BA@@1@@@@" to i32 (...)**), i32 (...)*** %{{.*}}
  // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @@"??_7D@@multiple_vbases@@@@6BB@@1@@@@" to i32 (...)**), i32 (...)*** %{{.*}}
  // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @@"??_7D@@multiple_vbases@@@@6BC@@1@@@@" to i32 (...)**), i32 (...)*** %{{.*}}
d286 6
a291 11
  // CHECK-LABEL: define dso_local x86_thiscallcc void @@"??1D@@diamond@@@@UAE@@XZ"(%"struct.diamond::D"*{{.*}})
  // Store initial this:
  // CHECK: %[[THIS_ADDR:.*]] = alloca %"struct.diamond::D"*
  // CHECK: store %"struct.diamond::D"* %{{.*}}, %"struct.diamond::D"** %[[THIS_ADDR]], align 4
  //
  // Reload and adjust the this parameter:
  // CHECK: %[[THIS_RELOAD:.*]] = load %"struct.diamond::D"*, %"struct.diamond::D"** %[[THIS_ADDR]]
  // CHECK: %[[THIS_UNADJ_i8:.*]] = bitcast %"struct.diamond::D"* %[[THIS_RELOAD]] to i8*
  // CHECK: %[[THIS_ADJ_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_UNADJ_i8]], i32 -24
  // CHECK: %[[THIS:.*]] = bitcast i8* %[[THIS_ADJ_i8]] to %"struct.diamond::D"*
  //
d299 1
a299 1
  // CHECK: call x86_thiscallcc void @@"??1C@@diamond@@@@UAE@@XZ"(%"struct.diamond::C"* %[[ARG]])
d305 1
a305 1
  // CHECK: call x86_thiscallcc void @@"??1B@@diamond@@@@UAE@@XZ"(%"struct.diamond::B"* %[[ARG]])
d320 1
a320 1
// CHECK-LABEL: define linkonce_odr dso_local x86_thiscallcc %"struct.test2::C"* @@"??0C@@test2@@@@QAE@@XZ"
d324 1
a324 1
// CHECK: call x86_thiscallcc %"struct.test2::A"* @@"??0A@@test2@@@@QAE@@XZ"(%"struct.test2::A"* %{{.*}})
d327 2
a328 2
// CHECK: call x86_thiscallcc %"struct.test2::B"* @@"??0B@@test2@@@@QAE@@XZ"(%"struct.test2::B"* %{{.*}}, i32 0)
// CHECK: call x86_thiscallcc %"struct.test2::A"* @@"??0A@@test2@@@@QAE@@XZ"(%"struct.test2::A"* %{{.*}})
d331 1
a331 1
// CHECK2-LABEL: define linkonce_odr dso_local x86_thiscallcc %"struct.test2::B"* @@"??0B@@test2@@@@QAE@@XZ"
d333 1
a333 1
// CHECK2: call x86_thiscallcc %"struct.test2::A"* @@"??0A@@test2@@@@QAE@@XZ"(%"struct.test2::A"* %{{.*}})
d360 1
a360 1
  // CHECK-LABEL: define dso_local x86_thiscallcc void @@"?bar@@D@@test3@@@@UAEXXZ"(%"struct.test3::D"* %this)
d371 1
a371 1
  // CHECK: call x86_thiscallcc void @@"?foo@@C@@test3@@@@UAEXXZ"(i8* %[[ARG]])
d394 1
a394 1
  // CHECK-LABEL: define dso_local x86_thiscallcc void @@"??1C@@test4@@@@UAE@@XZ"(%"struct.test4::C"* %this)
d400 1
a400 1
  // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @@"??_7C@@test4@@@@6BB@@1@@@@" to i32 (...)**), i32 (...)*** %[[VFPTR_i8]]
d407 1
a407 1
  // CHECK-LABEL: define dso_local void @@"?destroy@@test4@@@@YAXPAUC@@1@@@@Z"(%"struct.test4::C"* %obj)
d429 1
a429 1
  // CHECK-LABEL: define dso_local x86_thiscallcc void @@"??1E@@test4@@@@UAE@@XZ"(%"struct.test4::E"* %this)
d435 1
a435 1
  // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @@"??_7E@@test4@@@@6BD@@1@@@@" to i32 (...)**), i32 (...)*** %[[VFPTR_i8]]
d440 1
a440 1
  // CHECK-LABEL: define dso_local void @@"?destroy@@test4@@@@YAXPAUE@@1@@@@Z"(%"struct.test4::E"* %obj)
a442 4
  // CHECK: %[[OBJ_i8:.*]] = bitcast %"struct.test4::E"* %[[OBJ]] to i8*
  // CHECK: %[[B_i8:.*]] = getelementptr inbounds i8, i8* %[[OBJ_i8]], i32 4
  // FIXME: in fact, the call should take i8* and the bitcast is redundant.
  // CHECK: %[[B_as_E:.*]] = bitcast i8* %[[B_i8]] to %"struct.test4::E"*
d449 4
d474 1
a474 1
// CHECK-LABEL: define dso_local x86_thiscallcc %"struct.test5::C"* @@"??0C@@test5@@@@QAE@@XZ"(
d482 1
a482 1
// CHECK:   call void @@llvm.memset.p0i8.i32(i8* align 4 %[[FIELD]], i8 0, i32 4, i1 false)
d498 1
a498 1
// CHECK-LABEL: define dso_local void @@"?callit@@pr27621@@@@YAXPAUC@@1@@@@Z"(%"struct.pr27621::C"* %{{.*}})
d500 1
a500 1
// CHECK: call x86_thiscallcc void @@"?g@@C@@pr27621@@@@UAEXXZ"(i8* %[[B_i8]])
d514 1
a514 1
// CHECK-LABEL: define dso_local x86_thiscallcc %"class.test6::D"* @@"??0D@@test6@@@@AAE@@XZ"(
d522 1
a522 18
// CHECK:   call void @@llvm.memset.p0i8.i32(i8* align 4 %[[FIELD]], i8 0, i32 4, i1 false)
}

namespace pr36921 {
struct A {
  virtual ~A() {}
};
struct B {
  virtual ~B() {}
};
struct C : virtual B {};
struct D : virtual A, C {};
D d;
// CHECK-LABEL: define linkonce_odr dso_local x86_thiscallcc i8* @@"??_GD@@pr36921@@@@UAEPAXI@@Z"(
// CHECK:   %[[THIS:.*]] = load %"struct.pr36921::D"*, %"struct.pr36921::D"**
// CHECK:   %[[THIS_UNADJ_i8:.*]] = bitcast %"struct.pr36921::D"* %[[THIS_RELOAD]] to i8*
// CHECK:   %[[THIS_ADJ_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_UNADJ_i8]], i32 -4
// CHECK:   %[[THIS:.*]] = bitcast i8* %[[THIS_ADJ_i8]] to %"struct.pr36921::D"*
@


1.1.1.9
log
@Import clang r337282 from trunk
@
text
@d1 1
a1 1
// RUN: %clang_cc1 %s -fno-rtti -std=c++11 -Wno-inaccessible-base -triple=i386-pc-win32 -emit-llvm -o %t
d6 1
a6 1
// RUN: %clang_cc1 %s -fno-rtti -std=c++11 -Wno-inaccessible-base -triple=x86_64-pc-win32 -emit-llvm -o %t
d23 1
a23 1
  // CHECK-LABEL: define dso_local x86_thiscallcc %struct.B* @@"??0B@@@@QAE@@XZ"
d36 1
a36 1
  // CHECK:   store i32 (...)** bitcast ({ [3 x i8*] }* @@"??_7B@@@@6B@@" to i32 (...)**), i32 (...)*** %[[VFPTR]]
d54 7
a60 9
  // CHECK-LABEL: define dso_local x86_thiscallcc void @@"??1B@@@@UAE@@XZ"
  // Store initial this:
  // CHECK:   %[[THIS_ADDR:.*]] = alloca %struct.B*
  // CHECK:   store %struct.B* %{{.*}}, %struct.B** %[[THIS_ADDR]], align 4
  // Reload and adjust the this parameter:
  // CHECK:   %[[THIS_RELOAD:.*]] = load %struct.B*, %struct.B** %[[THIS_ADDR]]
  // CHECK:   %[[THIS_UNADJ_i8:.*]] = bitcast %struct.B* %[[THIS_RELOAD]] to i8*
  // CHECK:   %[[THIS_ADJ_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_UNADJ_i8]], i32 -8
  // CHECK:   %[[THIS:.*]] = bitcast i8* %[[THIS_ADJ_i8]] to %struct.B*
d69 1
a69 1
  // CHECK:   store i32 (...)** bitcast ({ [3 x i8*] }* @@"??_7B@@@@6B@@" to i32 (...)**), i32 (...)*** %[[VFPTR]]
d87 1
a87 1
  // CHECK2-LABEL: define linkonce_odr dso_local x86_thiscallcc void @@"??_DB@@@@QAEXXZ"(%struct.B*
d92 1
a92 1
  // CHECK2: call x86_thiscallcc void @@"??1B@@@@UAE@@XZ"(%struct.B* %[[B]])
d96 1
a96 1
  // CHECK2: call x86_thiscallcc void @@"??1VBase@@@@UAE@@XZ"(%struct.VBase* %[[VBASE]])
d99 2
a100 4
  // CHECK2-LABEL: define linkonce_odr dso_local x86_thiscallcc i8* @@"??_GB@@@@UAEPAXI@@Z"
  // CHECK2:   store %struct.B* %{{.*}}, %struct.B** %[[THIS_ADDR:.*]], align 4
  // CHECK2:   %[[THIS:.*]] = load %struct.B*, %struct.B** %[[THIS_ADDR]]
  // CHECK2:   %[[THIS_PARAM_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
d103 3
a105 1
  // CHECK2:   call x86_thiscallcc void @@"??_DB@@@@QAEXXZ"(%struct.B* %[[THIS]])
d111 1
a111 1
// CHECK-LABEL: define dso_local x86_thiscallcc void @@"?foo@@B@@@@UAEXXZ"(i8*
d116 4
a119 15
// Coerce this to correct type:
// CHECK:   %[[THIS_STORE:.*]] = alloca %struct.B*
// CHECK:   %[[THIS_ADDR:.*]] = alloca %struct.B*
// CHECK:   %[[COERCE_VAL:.*]] = bitcast i8* %{{.*}} to %struct.B*
// CHECK:   store %struct.B* %[[COERCE_VAL]], %struct.B** %[[THIS_STORE]], align 4
//
// Store initial this:
// CHECK:   %[[THIS_INIT:.*]] = load %struct.B*, %struct.B** %[[THIS_STORE]]
// CHECK:   store %struct.B* %[[THIS_INIT]], %struct.B** %[[THIS_ADDR]], align 4
//
// Reload and adjust the this parameter:
// CHECK:   %[[THIS_RELOAD:.*]] = load %struct.B*, %struct.B** %[[THIS_ADDR]]
// CHECK:   %[[THIS_UNADJ_i8:.*]] = bitcast %struct.B* %[[THIS_RELOAD]] to i8*
// CHECK:   %[[THIS_ADJ_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_UNADJ_i8]], i32 -8
// CHECK:   %[[THIS:.*]] = bitcast i8* %[[THIS_ADJ_i8]] to %struct.B*
d122 1
d140 1
a140 1
// CHECK-LABEL: define dso_local void @@"?call_vbase_bar@@@@YAXPAUB@@@@@@Z"(%struct.B* %obj)
d154 5
a158 1
// CHECK: %[[VBASE:.*]] = getelementptr inbounds i8, i8* %[[OBJ_i8]], i32 %[[VBOFFSET]]
d167 1
a167 5
// CHECK: %[[VBASE_i8:.*]] = getelementptr inbounds i8, i8* %[[OBJ_i8]], i32 %[[VBOFFSET]]
// CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VBASE_i8]] to void (i8*)***
// CHECK: %[[VFTABLE:.*]] = load void (i8*)**, void (i8*)*** %[[VFPTR]]
// CHECK: %[[VFUN:.*]] = getelementptr inbounds void (i8*)*, void (i8*)** %[[VFTABLE]], i64 2
// CHECK: %[[VFUN_VALUE:.*]] = load void (i8*)*, void (i8*)** %[[VFUN]]
d175 1
a175 1
// CHECK-LABEL: define dso_local void @@"?delete_B@@@@YAXPAUB@@@@@@Z"(%struct.B* %obj)
d187 4
a190 1
// CHECK: %[[VBASE:.*]] = bitcast i8* %[[VBASE_i8]] to %struct.B*
d200 1
a200 4
// CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VBASE_i8]] to i8* (%struct.B*, i32)***
// CHECK: %[[VFTABLE:.*]] = load i8* (%struct.B*, i32)**, i8* (%struct.B*, i32)*** %[[VFPTR]]
// CHECK: %[[VFUN:.*]] = getelementptr inbounds i8* (%struct.B*, i32)*, i8* (%struct.B*, i32)** %[[VFTABLE]], i64 0
// CHECK: %[[VFUN_VALUE:.*]] = load i8* (%struct.B*, i32)*, i8* (%struct.B*, i32)** %[[VFUN]]
d207 1
a207 1
  // CHECK-LABEL: define dso_local void @@"?call_complete_dtor@@@@YAXXZ"
d209 1
a209 1
  // CHECK: call x86_thiscallcc %struct.B* @@"??0B@@@@QAE@@XZ"(%struct.B* %[[B:.*]], i32 1)
d211 1
a211 1
  // CHECK: call x86_thiscallcc void @@"??_DB@@@@QAEXXZ"(%struct.B* %[[B]])
d222 1
a222 1
// CHECK-LABEL: define dso_local x86_thiscallcc %struct.C* @@"??0C@@@@QAE@@XZ"
d246 1
a246 1
  // CHECK-LABEL: define dso_local x86_thiscallcc %"struct.multiple_vbases::D"* @@"??0D@@multiple_vbases@@@@QAE@@XZ"
d248 3
a250 3
  // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @@"??_7D@@multiple_vbases@@@@6BA@@1@@@@" to i32 (...)**), i32 (...)*** %{{.*}}
  // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @@"??_7D@@multiple_vbases@@@@6BB@@1@@@@" to i32 (...)**), i32 (...)*** %{{.*}}
  // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @@"??_7D@@multiple_vbases@@@@6BC@@1@@@@" to i32 (...)**), i32 (...)*** %{{.*}}
d286 6
a291 11
  // CHECK-LABEL: define dso_local x86_thiscallcc void @@"??1D@@diamond@@@@UAE@@XZ"(%"struct.diamond::D"*{{.*}})
  // Store initial this:
  // CHECK: %[[THIS_ADDR:.*]] = alloca %"struct.diamond::D"*
  // CHECK: store %"struct.diamond::D"* %{{.*}}, %"struct.diamond::D"** %[[THIS_ADDR]], align 4
  //
  // Reload and adjust the this parameter:
  // CHECK: %[[THIS_RELOAD:.*]] = load %"struct.diamond::D"*, %"struct.diamond::D"** %[[THIS_ADDR]]
  // CHECK: %[[THIS_UNADJ_i8:.*]] = bitcast %"struct.diamond::D"* %[[THIS_RELOAD]] to i8*
  // CHECK: %[[THIS_ADJ_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_UNADJ_i8]], i32 -24
  // CHECK: %[[THIS:.*]] = bitcast i8* %[[THIS_ADJ_i8]] to %"struct.diamond::D"*
  //
d299 1
a299 1
  // CHECK: call x86_thiscallcc void @@"??1C@@diamond@@@@UAE@@XZ"(%"struct.diamond::C"* %[[ARG]])
d305 1
a305 1
  // CHECK: call x86_thiscallcc void @@"??1B@@diamond@@@@UAE@@XZ"(%"struct.diamond::B"* %[[ARG]])
d320 1
a320 1
// CHECK-LABEL: define linkonce_odr dso_local x86_thiscallcc %"struct.test2::C"* @@"??0C@@test2@@@@QAE@@XZ"
d324 1
a324 1
// CHECK: call x86_thiscallcc %"struct.test2::A"* @@"??0A@@test2@@@@QAE@@XZ"(%"struct.test2::A"* %{{.*}})
d327 2
a328 2
// CHECK: call x86_thiscallcc %"struct.test2::B"* @@"??0B@@test2@@@@QAE@@XZ"(%"struct.test2::B"* %{{.*}}, i32 0)
// CHECK: call x86_thiscallcc %"struct.test2::A"* @@"??0A@@test2@@@@QAE@@XZ"(%"struct.test2::A"* %{{.*}})
d331 1
a331 1
// CHECK2-LABEL: define linkonce_odr dso_local x86_thiscallcc %"struct.test2::B"* @@"??0B@@test2@@@@QAE@@XZ"
d333 1
a333 1
// CHECK2: call x86_thiscallcc %"struct.test2::A"* @@"??0A@@test2@@@@QAE@@XZ"(%"struct.test2::A"* %{{.*}})
d360 1
a360 1
  // CHECK-LABEL: define dso_local x86_thiscallcc void @@"?bar@@D@@test3@@@@UAEXXZ"(%"struct.test3::D"* %this)
d371 1
a371 1
  // CHECK: call x86_thiscallcc void @@"?foo@@C@@test3@@@@UAEXXZ"(i8* %[[ARG]])
d394 1
a394 1
  // CHECK-LABEL: define dso_local x86_thiscallcc void @@"??1C@@test4@@@@UAE@@XZ"(%"struct.test4::C"* %this)
d400 1
a400 1
  // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @@"??_7C@@test4@@@@6BB@@1@@@@" to i32 (...)**), i32 (...)*** %[[VFPTR_i8]]
d407 1
a407 1
  // CHECK-LABEL: define dso_local void @@"?destroy@@test4@@@@YAXPAUC@@1@@@@Z"(%"struct.test4::C"* %obj)
d429 1
a429 1
  // CHECK-LABEL: define dso_local x86_thiscallcc void @@"??1E@@test4@@@@UAE@@XZ"(%"struct.test4::E"* %this)
d435 1
a435 1
  // CHECK: store i32 (...)** bitcast ({ [1 x i8*] }* @@"??_7E@@test4@@@@6BD@@1@@@@" to i32 (...)**), i32 (...)*** %[[VFPTR_i8]]
d440 1
a440 1
  // CHECK-LABEL: define dso_local void @@"?destroy@@test4@@@@YAXPAUE@@1@@@@Z"(%"struct.test4::E"* %obj)
a442 4
  // CHECK: %[[OBJ_i8:.*]] = bitcast %"struct.test4::E"* %[[OBJ]] to i8*
  // CHECK: %[[B_i8:.*]] = getelementptr inbounds i8, i8* %[[OBJ_i8]], i32 4
  // FIXME: in fact, the call should take i8* and the bitcast is redundant.
  // CHECK: %[[B_as_E:.*]] = bitcast i8* %[[B_i8]] to %"struct.test4::E"*
d449 4
d474 1
a474 1
// CHECK-LABEL: define dso_local x86_thiscallcc %"struct.test5::C"* @@"??0C@@test5@@@@QAE@@XZ"(
d482 1
a482 1
// CHECK:   call void @@llvm.memset.p0i8.i32(i8* align 4 %[[FIELD]], i8 0, i32 4, i1 false)
d498 1
a498 1
// CHECK-LABEL: define dso_local void @@"?callit@@pr27621@@@@YAXPAUC@@1@@@@Z"(%"struct.pr27621::C"* %{{.*}})
d500 1
a500 1
// CHECK: call x86_thiscallcc void @@"?g@@C@@pr27621@@@@UAEXXZ"(i8* %[[B_i8]])
d514 1
a514 1
// CHECK-LABEL: define dso_local x86_thiscallcc %"class.test6::D"* @@"??0D@@test6@@@@AAE@@XZ"(
d522 1
a522 18
// CHECK:   call void @@llvm.memset.p0i8.i32(i8* align 4 %[[FIELD]], i8 0, i32 4, i1 false)
}

namespace pr36921 {
struct A {
  virtual ~A() {}
};
struct B {
  virtual ~B() {}
};
struct C : virtual B {};
struct D : virtual A, C {};
D d;
// CHECK-LABEL: define linkonce_odr dso_local x86_thiscallcc i8* @@"??_GD@@pr36921@@@@UAEPAXI@@Z"(
// CHECK:   %[[THIS:.*]] = load %"struct.pr36921::D"*, %"struct.pr36921::D"**
// CHECK:   %[[THIS_UNADJ_i8:.*]] = bitcast %"struct.pr36921::D"* %[[THIS_RELOAD]] to i8*
// CHECK:   %[[THIS_ADJ_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_UNADJ_i8]], i32 -4
// CHECK:   %[[THIS:.*]] = bitcast i8* %[[THIS_ADJ_i8]] to %"struct.pr36921::D"*
@


1.1.1.10
log
@Mark old LLVM instance as dead.
@
text
@@


1.1.1.4.4.1
log
@file microsoft-abi-virtual-inheritance.cpp was added on branch tls-maxphys on 2014-08-19 23:47:58 +0000
@
text
@d1 462
@


1.1.1.4.4.2
log
@Rebase to HEAD as of a few days ago.
@
text
@a0 462
// RUN: %clang_cc1 %s -fno-rtti -triple=i386-pc-win32 -emit-llvm -o %t
// RUN: FileCheck %s < %t
// RUN: FileCheck --check-prefix=CHECK2 %s < %t

// For now, just make sure x86_64 doesn't crash.
// RUN: %clang_cc1 %s -fno-rtti -triple=x86_64-pc-win32 -emit-llvm -o %t

struct VBase {
  virtual ~VBase();
  virtual void foo();
  virtual void bar();
  int field;
};

struct B : virtual VBase {
  B();
  virtual ~B();
  virtual void foo();
  virtual void bar();
};

B::B() {
  // CHECK-LABEL: define x86_thiscallcc %struct.B* @@"\01??0B@@@@QAE@@XZ"
  // CHECK:   %[[THIS:.*]] = load %struct.B**
  // CHECK:   br i1 %{{.*}}, label %[[INIT_VBASES:.*]], label %[[SKIP_VBASES:.*]]

  // Don't check the INIT_VBASES case as it's covered by the ctor tests.

  // CHECK: %[[SKIP_VBASES]]
  // CHECK:   %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
  // CHECK:   %[[VBPTR:.*]] = getelementptr inbounds i8* %[[THIS_i8]], i32 0
  // ...
  // CHECK:   %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
  // CHECK:   %[[VFPTR_i8:.*]] = getelementptr inbounds i8* %[[THIS_i8]], i32 %{{.*}}
  // CHECK:   %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to [3 x i8*]**
  // CHECK:   store [3 x i8*]* @@"\01??_7B@@@@6B@@", [3 x i8*]** %[[VFPTR]]

  // Initialize vtorDisp:
  // CHECK:   %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
  // CHECK:   %[[VBPTR:.*]] = getelementptr inbounds i8* %[[THIS_i8]], i32 0
  // ...
  // CHECK:   %[[VBASE_OFFSET:.*]] = add nsw i32 0, %{{.*}}
  // CHECK:   %[[VTORDISP_VAL:.*]] = sub i32 %[[VBASE_OFFSET]], 8
  // CHECK:   %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
  // CHECK:   %[[VBASE_i8:.*]] = getelementptr inbounds i8* %[[THIS_i8]], i32 %[[VBASE_OFFSET]]
  // CHECK:   %[[VTORDISP_i8:.*]] = getelementptr i8* %[[VBASE_i8]], i32 -4
  // CHECK:   %[[VTORDISP_PTR:.*]] = bitcast i8* %[[VTORDISP_i8]] to i32*
  // CHECK:   store i32 %[[VTORDISP_VAL]], i32* %[[VTORDISP_PTR]]

  // CHECK: ret
}

B::~B() {
  // CHECK-LABEL: define x86_thiscallcc void @@"\01??1B@@@@UAE@@XZ"
  // Adjust the this parameter:
  // CHECK:   %[[THIS_PARAM_i8:.*]] = bitcast %struct.B* {{.*}} to i8*
  // CHECK:   %[[THIS_i8:.*]] = getelementptr inbounds i8* %[[THIS_PARAM_i8]], i32 -8
  // CHECK:   %[[THIS:.*]] = bitcast i8* %[[THIS_i8]] to %struct.B*
  // CHECK:   store %struct.B* %[[THIS]], %struct.B** %[[THIS_ADDR:.*]], align 4
  // CHECK:   %[[THIS:.*]] = load %struct.B** %[[THIS_ADDR]]

  // Restore the vfptr that could have been changed by a subclass.
  // CHECK:   %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
  // CHECK:   %[[VBPTR:.*]] = getelementptr inbounds i8* %[[THIS_i8]], i32 0
  // ...
  // CHECK:   %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
  // CHECK:   %[[VFPTR_i8:.*]] = getelementptr inbounds i8* %[[THIS_i8]], i32 %{{.*}}
  // CHECK:   %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to [3 x i8*]**
  // CHECK:   store [3 x i8*]* @@"\01??_7B@@@@6B@@", [3 x i8*]** %[[VFPTR]]

  // Initialize vtorDisp:
  // CHECK:   %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
  // CHECK:   %[[VBPTR:.*]] = getelementptr inbounds i8* %[[THIS_i8]], i32 0
  // ...
  // CHECK:   %[[VBASE_OFFSET:.*]] = add nsw i32 0, %{{.*}}
  // CHECK:   %[[VTORDISP_VAL:.*]] = sub i32 %[[VBASE_OFFSET]], 8
  // CHECK:   %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
  // CHECK:   %[[VBASE_i8:.*]] = getelementptr inbounds i8* %[[THIS_i8]], i32 %[[VBASE_OFFSET]]
  // CHECK:   %[[VTORDISP_i8:.*]] = getelementptr i8* %[[VBASE_i8]], i32 -4
  // CHECK:   %[[VTORDISP_PTR:.*]] = bitcast i8* %[[VTORDISP_i8]] to i32*
  // CHECK:   store i32 %[[VTORDISP_VAL]], i32* %[[VTORDISP_PTR]]

  foo();  // Avoid the "trivial destructor" optimization.

  // CHECK: ret

  // CHECK2-LABEL: define linkonce_odr x86_thiscallcc void @@"\01??_DB@@@@UAE@@XZ"(%struct.B*
  // CHECK2: %[[THIS:.*]] = load %struct.B** {{.*}}
  // CHECK2: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
  // CHECK2: %[[B_i8:.*]] = getelementptr i8* %[[THIS_i8]], i32 8
  // CHECK2: %[[B:.*]] = bitcast i8* %[[B_i8]] to %struct.B*
  // CHECK2: call x86_thiscallcc void @@"\01??1B@@@@UAE@@XZ"(%struct.B* %[[B]])
  // CHECK2: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
  // CHECK2: %[[VBASE_i8:.*]] = getelementptr inbounds i8* %[[THIS_i8]], i64 8
  // CHECK2: %[[VBASE:.*]] = bitcast i8* %[[VBASE_i8]] to %struct.VBase*
  // CHECK2: call x86_thiscallcc void @@"\01??1VBase@@@@UAE@@XZ"(%struct.VBase* %[[VBASE]])
  // CHECK2: ret

  // CHECK2-LABEL: define linkonce_odr x86_thiscallcc void @@"\01??_GB@@@@UAEPAXI@@Z"
  // CHECK2:   %[[THIS_PARAM_i8:.*]] = bitcast %struct.B* {{.*}} to i8*
  // CHECK2:   %[[THIS_i8:.*]] = getelementptr inbounds i8* %[[THIS_PARAM_i8:.*]], i32 -8
  // CHECK2:   %[[THIS:.*]] = bitcast i8* %[[THIS_i8]] to %struct.B*
  // CHECK2:   store %struct.B* %[[THIS]], %struct.B** %[[THIS_ADDR:.*]], align 4
  // CHECK2:   %[[THIS:.*]] = load %struct.B** %[[THIS_ADDR]]
  // CHECK2:   call x86_thiscallcc void @@"\01??_DB@@@@UAE@@XZ"(%struct.B* %[[THIS]])
  // ...
  // CHECK2: ret
}

void B::foo() {
// CHECK-LABEL: define x86_thiscallcc void @@"\01?foo@@B@@@@UAEXXZ"(i8*
//
// B::foo gets 'this' cast to VBase* in ECX (i.e. this+8) so we
// need to adjust 'this' before use.
//
// CHECK: %[[THIS_ADDR:.*]] = alloca %struct.B*, align 4
// CHECK: %[[THIS_i8:.*]] = getelementptr inbounds i8* %[[ECX:.*]], i32 -8
// CHECK: %[[THIS:.*]] = bitcast i8* %[[THIS_i8]] to %struct.B*
// CHECK: store %struct.B* %[[THIS]], %struct.B** %[[THIS_ADDR]], align 4

  field = 42;
// CHECK: %[[THIS:.*]] = load %struct.B** %[[THIS_ADDR]]
// CHECK: %[[THIS8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
// CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8* %[[THIS8]], i32 0
// CHECK: %[[VBPTR8:.*]] = bitcast i8* %[[VBPTR]] to i8**
// CHECK: %[[VBTABLE:.*]] = load i8** %[[VBPTR8]]
// CHECK: %[[VBENTRY8:.*]] = getelementptr inbounds i8* %[[VBTABLE]], i32 4
// CHECK: %[[VBENTRY:.*]] = bitcast i8* %[[VBENTRY8]] to i32*
// CHECK: %[[VBOFFSET32:.*]] = load i32* %[[VBENTRY]]
// CHECK: %[[VBOFFSET:.*]] = add nsw i32 0, %[[VBOFFSET32]]
// CHECK: %[[THIS8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
// CHECK: %[[VBASE_i8:.*]] = getelementptr inbounds i8* %[[THIS8]], i32 %[[VBOFFSET]]
// CHECK: %[[VBASE:.*]] = bitcast i8* %[[VBASE_i8]] to %struct.VBase*
// CHECK: %[[FIELD:.*]] = getelementptr inbounds %struct.VBase* %[[VBASE]], i32 0, i32 1
// CHECK: store i32 42, i32* %[[FIELD]], align 4
//
// CHECK: ret void
}

void call_vbase_bar(B *obj) {
// CHECK-LABEL: define void @@"\01?call_vbase_bar@@@@YAXPAUB@@@@@@Z"(%struct.B* %obj)
// CHECK: %[[OBJ:.*]] = load %struct.B

  obj->bar();
// When calling a vbase's virtual method, one needs to adjust 'this'
// at the caller site.
//
// CHECK: %[[OBJ_i8:.*]] = bitcast %struct.B* %[[OBJ]] to i8*
// CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 0
// CHECK: %[[VBPTR8:.*]] = bitcast i8* %[[VBPTR]] to i8**
// CHECK: %[[VBTABLE:.*]] = load i8** %[[VBPTR8]]
// CHECK: %[[VBENTRY8:.*]] = getelementptr inbounds i8* %[[VBTABLE]], i32 4
// CHECK: %[[VBENTRY:.*]] = bitcast i8* %[[VBENTRY8]] to i32*
// CHECK: %[[VBOFFSET32:.*]] = load i32* %[[VBENTRY]]
// CHECK: %[[VBOFFSET:.*]] = add nsw i32 0, %[[VBOFFSET32]]
// CHECK: %[[VBASE_i8:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 %[[VBOFFSET]]
// CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VBASE_i8]] to void (i8*)***
// CHECK: %[[VFTABLE:.*]] = load void (i8*)*** %[[VFPTR]]
// CHECK: %[[VFUN:.*]] = getelementptr inbounds void (i8*)** %[[VFTABLE]], i64 2
// CHECK: %[[VFUN_VALUE:.*]] = load void (i8*)** %[[VFUN]]
//
// CHECK: %[[OBJ_i8:.*]] = bitcast %struct.B* %[[OBJ]] to i8*
// CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 0
// CHECK: %[[VBPTR8:.*]] = bitcast i8* %[[VBPTR]] to i8**
// CHECK: %[[VBTABLE:.*]] = load i8** %[[VBPTR8]]
// CHECK: %[[VBENTRY8:.*]] = getelementptr inbounds i8* %[[VBTABLE]], i32 4
// CHECK: %[[VBENTRY:.*]] = bitcast i8* %[[VBENTRY8]] to i32*
// CHECK: %[[VBOFFSET32:.*]] = load i32* %[[VBENTRY]]
// CHECK: %[[VBOFFSET:.*]] = add nsw i32 0, %[[VBOFFSET32]]
// CHECK: %[[VBASE:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 %[[VBOFFSET]]
//
// CHECK: call x86_thiscallcc void %[[VFUN_VALUE]](i8* %[[VBASE]])
//
// CHECK: ret void
}

void delete_B(B *obj) {
// CHECK-LABEL: define void @@"\01?delete_B@@@@YAXPAUB@@@@@@Z"(%struct.B* %obj)
// CHECK: %[[OBJ:.*]] = load %struct.B

  delete obj;
// CHECK: %[[OBJ_i8:.*]] = bitcast %struct.B* %[[OBJ]] to i8*
// CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 0
// CHECK: %[[VBPTR8:.*]] = bitcast i8* %[[VBPTR]] to i8**
// CHECK: %[[VBTABLE:.*]] = load i8** %[[VBPTR8]]
// CHECK: %[[VBENTRY8:.*]] = getelementptr inbounds i8* %[[VBTABLE]], i32 4
// CHECK: %[[VBENTRY:.*]] = bitcast i8* %[[VBENTRY8]] to i32*
// CHECK: %[[VBOFFSET32:.*]] = load i32* %[[VBENTRY]]
// CHECK: %[[VBOFFSET:.*]] = add nsw i32 0, %[[VBOFFSET32]]
// CHECK: %[[VBASE_i8:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 %[[VBOFFSET]]
// CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VBASE_i8]] to void (%struct.B*, i32)***
// CHECK: %[[VFTABLE:.*]] = load void (%struct.B*, i32)*** %[[VFPTR]]
// CHECK: %[[VFUN:.*]] = getelementptr inbounds void (%struct.B*, i32)** %[[VFTABLE]], i64 0
// CHECK: %[[VFUN_VALUE:.*]] = load void (%struct.B*, i32)** %[[VFUN]]
//
// CHECK: %[[OBJ_i8:.*]] = bitcast %struct.B* %[[OBJ]] to i8*
// CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 0
// CHECK: %[[VBPTR8:.*]] = bitcast i8* %[[VBPTR]] to i8**
// CHECK: %[[VBTABLE:.*]] = load i8** %[[VBPTR8]]
// CHECK: %[[VBENTRY8:.*]] = getelementptr inbounds i8* %[[VBTABLE]], i32 4
// CHECK: %[[VBENTRY:.*]] = bitcast i8* %[[VBENTRY8]] to i32*
// CHECK: %[[VBOFFSET32:.*]] = load i32* %[[VBENTRY]]
// CHECK: %[[VBOFFSET:.*]] = add nsw i32 0, %[[VBOFFSET32]]
// CHECK: %[[VBASE_i8:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 %[[VBOFFSET]]
// CHECK: %[[VBASE:.*]] = bitcast i8* %[[VBASE_i8]] to %struct.B*
//
// CHECK: call x86_thiscallcc void %[[VFUN_VALUE]](%struct.B* %[[VBASE]], i32 1)
// CHECK: ret void
}

void call_complete_dtor() {
  // CHECK-LABEL: define void @@"\01?call_complete_dtor@@@@YAXXZ"
  B b;
  // CHECK: call x86_thiscallcc %struct.B* @@"\01??0B@@@@QAE@@XZ"(%struct.B* %[[B:.*]], i32 1)
  // CHECK-NOT: getelementptr
  // CHECK: call x86_thiscallcc void @@"\01??_DB@@@@UAE@@XZ"(%struct.B* %[[B]])
  // CHECK: ret
}

struct C : B {
  C();
  // has an implicit vdtor.
};

// Used to crash on an assertion.
C::C() {
// CHECK-LABEL: define x86_thiscallcc %struct.C* @@"\01??0C@@@@QAE@@XZ"
}

namespace multiple_vbases {
struct A {
  virtual void a();
};

struct B {
  virtual void b();
};

struct C {
  virtual void c();
};

struct D : virtual A, virtual B, virtual C {
  virtual void a();
  virtual void b();
  virtual void c();
  D();
};

D::D() {
  // CHECK-LABEL: define x86_thiscallcc %"struct.multiple_vbases::D"* @@"\01??0D@@multiple_vbases@@@@QAE@@XZ"
  // Just make sure we emit 3 vtordisps after initializing vfptrs.
  // CHECK: store [1 x i8*]* @@"\01??_7D@@multiple_vbases@@@@6BA@@1@@@@", [1 x i8*]** %{{.*}}
  // CHECK: store [1 x i8*]* @@"\01??_7D@@multiple_vbases@@@@6BB@@1@@@@", [1 x i8*]** %{{.*}}
  // CHECK: store [1 x i8*]* @@"\01??_7D@@multiple_vbases@@@@6BC@@1@@@@", [1 x i8*]** %{{.*}}
  // ...
  // CHECK: store i32 %{{.*}}, i32* %{{.*}}
  // CHECK: store i32 %{{.*}}, i32* %{{.*}}
  // CHECK: store i32 %{{.*}}, i32* %{{.*}}
  // CHECK: ret
}
}

namespace diamond {
struct A {
  A();
  virtual ~A();
};

struct B : virtual A {
  B();
  ~B();
};

struct C : virtual A {
  C();
  ~C();
  int c1, c2, c3;
};

struct Z {
  int z;
};

struct D : virtual Z, B, C {
  D();
  ~D();
} d;

D::~D() {
  // CHECK-LABEL: define x86_thiscallcc void @@"\01??1D@@diamond@@@@UAE@@XZ"(%"struct.diamond::D"*)
  // CHECK: %[[ARG_i8:.*]] = bitcast %"struct.diamond::D"* %{{.*}} to i8*
  // CHECK: %[[THIS_i8:.*]] = getelementptr inbounds i8* %[[ARG_i8]], i32 -24
  // CHECK: %[[THIS:.*]] = bitcast i8* %[[THIS_i8]] to %"struct.diamond::D"*
  // CHECK: store %"struct.diamond::D"* %[[THIS]], %"struct.diamond::D"** %[[THIS_VAL:.*]], align 4
  // CHECK: %[[THIS:.*]] = load %"struct.diamond::D"** %[[THIS_VAL]]
  // CHECK: %[[D_i8:.*]] = bitcast %"struct.diamond::D"* %[[THIS]] to i8*
  // CHECK: %[[C_i8:.*]] = getelementptr inbounds i8* %[[D_i8]], i64 4
  // CHECK: %[[C:.*]] = bitcast i8* %[[C_i8]] to %"struct.diamond::C"*
  // CHECK: %[[C_i8:.*]] = bitcast %"struct.diamond::C"* %[[C]] to i8*
  // CHECK: %[[ARG_i8:.*]] = getelementptr i8* %{{.*}}, i32 16
  // FIXME: We might consider changing the dtor this parameter type to i8*.
  // CHECK: %[[ARG:.*]] = bitcast i8* %[[ARG_i8]] to %"struct.diamond::C"*
  // CHECK: call x86_thiscallcc void @@"\01??1C@@diamond@@@@UAE@@XZ"(%"struct.diamond::C"* %[[ARG]])

  // CHECK: %[[B:.*]] = bitcast %"struct.diamond::D"* %[[THIS]] to %"struct.diamond::B"*
  // CHECK: %[[B_i8:.*]] = bitcast %"struct.diamond::B"* %[[B]] to i8*
  // CHECK: %[[ARG_i8:.*]] = getelementptr i8* %[[B_i8]], i32 4
  // CHECK: %[[ARG:.*]] = bitcast i8* %[[ARG_i8]] to %"struct.diamond::B"*
  // CHECK: call x86_thiscallcc void @@"\01??1B@@diamond@@@@UAE@@XZ"(%"struct.diamond::B"* %[[ARG]])
  // CHECK: ret void
}

}

namespace test2 {
struct A { A(); };
struct B : virtual A { B() {} };
struct C : B, A { C() {} };

// PR18435: Order mattered here.  We were generating code for the delegating
// call to B() from C().
void callC() { C x; }

// CHECK-LABEL: define linkonce_odr x86_thiscallcc %"struct.test2::C"* @@"\01??0C@@test2@@@@QAE@@XZ"
// CHECK:           (%"struct.test2::C"* returned %this, i32 %is_most_derived)
// CHECK: br i1
//   Virtual bases
// CHECK: call x86_thiscallcc %"struct.test2::A"* @@"\01??0A@@test2@@@@QAE@@XZ"(%"struct.test2::A"* %{{.*}})
// CHECK: br label
//   Non-virtual bases
// CHECK: call x86_thiscallcc %"struct.test2::B"* @@"\01??0B@@test2@@@@QAE@@XZ"(%"struct.test2::B"* %{{.*}}, i32 0)
// CHECK: call x86_thiscallcc %"struct.test2::A"* @@"\01??0A@@test2@@@@QAE@@XZ"(%"struct.test2::A"* %{{.*}})
// CHECK: ret

// CHECK2-LABEL: define linkonce_odr x86_thiscallcc %"struct.test2::B"* @@"\01??0B@@test2@@@@QAE@@XZ"
// CHECK2:           (%"struct.test2::B"* returned %this, i32 %is_most_derived)
// CHECK2: call x86_thiscallcc %"struct.test2::A"* @@"\01??0A@@test2@@@@QAE@@XZ"(%"struct.test2::A"* %{{.*}})
// CHECK2: ret

}

namespace test3 {
// PR19104: A non-virtual call of a virtual method doesn't use vftable thunks,
// so requires only static adjustment which is different to the one used
// for virtual calls.
struct A {
  virtual void foo();
};

struct B : virtual A {
  virtual void bar();
};

struct C : virtual A {
  virtual void foo();
};

struct D : B, C {
  virtual void bar();
  int field;  // Laid out between C and A subobjects in D.
};

void D::bar() {
  // CHECK-LABEL: define x86_thiscallcc void @@"\01?bar@@D@@test3@@@@UAEXXZ"(%"struct.test3::D"* %this)

  C::foo();
  // Shouldn't need any vbtable lookups.  All we have to do is adjust to C*,
  // then compensate for the adjustment performed in the C::foo() prologue.
  // CHECK-NOT: load i8**
  // CHECK: %[[OBJ_i8:.*]] = bitcast %"struct.test3::D"* %{{.*}} to i8*
  // CHECK: %[[C_i8:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 8
  // CHECK: %[[C:.*]] = bitcast i8* %[[C_i8]] to %"struct.test3::C"*
  // CHECK: %[[C_i8:.*]] = bitcast %"struct.test3::C"* %[[C]] to i8*
  // CHECK: %[[ARG:.*]] = getelementptr i8* %[[C_i8]], i32 4
  // CHECK: call x86_thiscallcc void @@"\01?foo@@C@@test3@@@@UAEXXZ"(i8* %[[ARG]])
  // CHECK: ret
}
}

namespace test4{
// PR19172: We used to merge method vftable locations wrong.

struct A {
  virtual ~A() {}
};

struct B {
  virtual ~B() {}
};

struct C : virtual A, B {
  virtual ~C();
};

void foo(void*);

C::~C() {
  // CHECK-LABEL: define x86_thiscallcc void @@"\01??1C@@test4@@@@UAE@@XZ"(%"struct.test4::C"* %this)

  // In this case "this" points to the most derived class, so no GEPs needed.
  // CHECK-NOT: getelementptr
  // CHECK-NOT: bitcast
  // CHECK: %[[VFPTR_i8:.*]] = bitcast %"struct.test4::C"* %{{.*}} to [1 x i8*]**
  // CHECK: store [1 x i8*]* @@"\01??_7C@@test4@@@@6BB@@1@@@@", [1 x i8*]** %[[VFPTR_i8]]

  foo(this);
  // CHECK: ret
}

void destroy(C *obj) {
  // CHECK-LABEL: define void @@"\01?destroy@@test4@@@@YAXPAUC@@1@@@@Z"(%"struct.test4::C"* %obj)

  delete obj;
  // CHECK: %[[VPTR:.*]] = bitcast %"struct.test4::C"* %[[OBJ:.*]] to void (%"struct.test4::C"*, i32)***
  // CHECK: %[[VFTABLE:.*]] = load void (%"struct.test4::C"*, i32)*** %[[VPTR]]
  // CHECK: %[[VFTENTRY:.*]] = getelementptr inbounds void (%"struct.test4::C"*, i32)** %[[VFTABLE]], i64 0
  // CHECK: %[[VFUN:.*]] = load void (%"struct.test4::C"*, i32)** %[[VFTENTRY]]
  // CHECK: call x86_thiscallcc void %[[VFUN]](%"struct.test4::C"* %[[OBJ]], i32 1)
  // CHECK: ret
}

struct D {
  virtual void d();
};

// The first non-virtual base doesn't have a vdtor,
// but "this adjustment" is not needed.
struct E : D, B, virtual A {
  virtual ~E();
};

E::~E() {
  // CHECK-LABEL: define x86_thiscallcc void @@"\01??1E@@test4@@@@UAE@@XZ"(%"struct.test4::E"* %this)

  // In this case "this" points to the most derived class, so no GEPs needed.
  // CHECK-NOT: getelementptr
  // CHECK-NOT: bitcast
  // CHECK: %[[VFPTR_i8:.*]] = bitcast %"struct.test4::E"* %{{.*}} to [1 x i8*]**
  // CHECK: store [1 x i8*]* @@"\01??_7E@@test4@@@@6BD@@1@@@@", [1 x i8*]** %[[VFPTR_i8]]
  foo(this);
}

void destroy(E *obj) {
  // CHECK-LABEL: define void @@"\01?destroy@@test4@@@@YAXPAUE@@1@@@@Z"(%"struct.test4::E"* %obj)

  // CHECK-NOT: getelementptr
  // CHECK: %[[OBJ_i8:.*]] = bitcast %"struct.test4::E"* %[[OBJ:.*]] to i8*
  // CHECK: %[[B_i8:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 4
  // CHECK: %[[VPTR:.*]] = bitcast i8* %[[B_i8]] to void (%"struct.test4::E"*, i32)***
  // CHECK: %[[VFTABLE:.*]] = load void (%"struct.test4::E"*, i32)*** %[[VPTR]]
  // CHECK: %[[VFTENTRY:.*]] = getelementptr inbounds void (%"struct.test4::E"*, i32)** %[[VFTABLE]], i64 0
  // CHECK: %[[VFUN:.*]] = load void (%"struct.test4::E"*, i32)** %[[VFTENTRY]]
  // CHECK: %[[OBJ_i8:.*]] = bitcast %"struct.test4::E"* %[[OBJ]] to i8*
  // CHECK: %[[B_i8:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 4
  // FIXME: in fact, the call should take i8* and the bitcast is redundant.
  // CHECK: %[[B_as_E:.*]] = bitcast i8* %[[B_i8]] to %"struct.test4::E"*
  // CHECK: call x86_thiscallcc void %[[VFUN]](%"struct.test4::E"* %[[B_as_E]], i32 1)
  delete obj;
}

}
@


1.1.1.3.4.1
log
@file microsoft-abi-virtual-inheritance.cpp was added on branch yamt-pagecache on 2014-05-22 16:18:57 +0000
@
text
@d1 346
@


1.1.1.3.4.2
log
@sync with head.

for a reference, the tree before this commit was tagged
as yamt-pagecache-tag8.

this commit was splitted into small chunks to avoid
a limitation of cvs.  ("Protocol error: too many arguments")
@
text
@a0 346
// RUN: %clang_cc1 %s -fno-rtti -triple=i386-pc-win32 -emit-llvm -o %t
// RUN: FileCheck %s < %t
// RUN: FileCheck --check-prefix=CHECK2 %s < %t

// For now, just make sure x86_64 doesn't crash.
// RUN: %clang_cc1 %s -fno-rtti -triple=x86_64-pc-win32 -emit-llvm -o %t

struct VBase {
  virtual ~VBase();
  virtual void foo();
  virtual void bar();
  int field;
};

struct B : virtual VBase {
  B();
  virtual ~B();
  virtual void foo();
  virtual void bar();
};

B::B() {
  // CHECK-LABEL: define x86_thiscallcc %struct.B* @@"\01??0B@@@@QAE@@XZ"
  // CHECK:   %[[THIS:.*]] = load %struct.B**
  // CHECK:   br i1 %{{.*}}, label %[[INIT_VBASES:.*]], label %[[SKIP_VBASES:.*]]

  // Don't check the INIT_VBASES case as it's covered by the ctor tests.

  // CHECK: %[[SKIP_VBASES]]
  // CHECK:   %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
  // CHECK:   %[[VBPTR:.*]] = getelementptr inbounds i8* %[[THIS_i8]], i32 0
  // ...
  // CHECK:   %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
  // CHECK:   %[[VFPTR_i8:.*]] = getelementptr inbounds i8* %[[THIS_i8]], i32 %{{.*}}
  // CHECK:   %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to [3 x i8*]**
  // CHECK:   store [3 x i8*]* @@"\01??_7B@@@@6B@@", [3 x i8*]** %[[VFPTR]]

  // Initialize vtorDisp:
  // CHECK:   %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
  // CHECK:   %[[VBPTR:.*]] = getelementptr inbounds i8* %[[THIS_i8]], i32 0
  // ...
  // CHECK:   %[[VBASE_OFFSET:.*]] = add nsw i32 0, %{{.*}}
  // CHECK:   %[[VTORDISP_VAL:.*]] = sub i32 %[[VBASE_OFFSET]], 8
  // CHECK:   %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
  // CHECK:   %[[VBASE_i8:.*]] = getelementptr inbounds i8* %[[THIS_i8]], i32 %[[VBASE_OFFSET]]
  // CHECK:   %[[VTORDISP_i8:.*]] = getelementptr i8* %[[VBASE_i8]], i32 -4
  // CHECK:   %[[VTORDISP_PTR:.*]] = bitcast i8* %[[VTORDISP_i8]] to i32*
  // CHECK:   store i32 %[[VTORDISP_VAL]], i32* %[[VTORDISP_PTR]]

  // CHECK: ret
}

B::~B() {
  // CHECK-LABEL: define x86_thiscallcc void @@"\01??1B@@@@UAE@@XZ"
  // Adjust the this parameter:
  // CHECK:   %[[THIS_PARAM_i8:.*]] = bitcast %struct.B* {{.*}} to i8*
  // CHECK:   %[[THIS_i8:.*]] = getelementptr inbounds i8* %[[THIS_PARAM_i8]], i32 -8
  // CHECK:   %[[THIS:.*]] = bitcast i8* %[[THIS_i8]] to %struct.B*
  // CHECK:   store %struct.B* %[[THIS]], %struct.B** %[[THIS_ADDR:.*]], align 4
  // CHECK:   %[[THIS:.*]] = load %struct.B** %[[THIS_ADDR]]

  // Restore the vfptr that could have been changed by a subclass.
  // CHECK:   %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
  // CHECK:   %[[VBPTR:.*]] = getelementptr inbounds i8* %[[THIS_i8]], i32 0
  // ...
  // CHECK:   %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
  // CHECK:   %[[VFPTR_i8:.*]] = getelementptr inbounds i8* %[[THIS_i8]], i32 %{{.*}}
  // CHECK:   %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to [3 x i8*]**
  // CHECK:   store [3 x i8*]* @@"\01??_7B@@@@6B@@", [3 x i8*]** %[[VFPTR]]

  // Initialize vtorDisp:
  // CHECK:   %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
  // CHECK:   %[[VBPTR:.*]] = getelementptr inbounds i8* %[[THIS_i8]], i32 0
  // ...
  // CHECK:   %[[VBASE_OFFSET:.*]] = add nsw i32 0, %{{.*}}
  // CHECK:   %[[VTORDISP_VAL:.*]] = sub i32 %[[VBASE_OFFSET]], 8
  // CHECK:   %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
  // CHECK:   %[[VBASE_i8:.*]] = getelementptr inbounds i8* %[[THIS_i8]], i32 %[[VBASE_OFFSET]]
  // CHECK:   %[[VTORDISP_i8:.*]] = getelementptr i8* %[[VBASE_i8]], i32 -4
  // CHECK:   %[[VTORDISP_PTR:.*]] = bitcast i8* %[[VTORDISP_i8]] to i32*
  // CHECK:   store i32 %[[VTORDISP_VAL]], i32* %[[VTORDISP_PTR]]

  foo();  // Avoid the "trivial destructor" optimization.

  // CHECK: ret

  // CHECK2-LABEL: define linkonce_odr x86_thiscallcc void @@"\01??_DB@@@@UAE@@XZ"(%struct.B*
  // CHECK2: %[[THIS:.*]] = load %struct.B** {{.*}}
  // CHECK2: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
  // CHECK2: %[[B_i8:.*]] = getelementptr i8* %[[THIS_i8]], i32 8
  // CHECK2: %[[B:.*]] = bitcast i8* %[[B_i8]] to %struct.B*
  // CHECK2: call x86_thiscallcc void @@"\01??1B@@@@UAE@@XZ"(%struct.B* %[[B]])
  // CHECK2: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
  // CHECK2: %[[VBASE_i8:.*]] = getelementptr inbounds i8* %[[THIS_i8]], i64 8
  // CHECK2: %[[VBASE:.*]] = bitcast i8* %[[VBASE_i8]] to %struct.VBase*
  // CHECK2: call x86_thiscallcc void @@"\01??1VBase@@@@UAE@@XZ"(%struct.VBase* %[[VBASE]])
  // CHECK2: ret

  // CHECK2-LABEL: define linkonce_odr x86_thiscallcc void @@"\01??_GB@@@@UAEPAXI@@Z"
  // CHECK2:   %[[THIS_PARAM_i8:.*]] = bitcast %struct.B* {{.*}} to i8*
  // CHECK2:   %[[THIS_i8:.*]] = getelementptr inbounds i8* %[[THIS_PARAM_i8:.*]], i32 -8
  // CHECK2:   %[[THIS:.*]] = bitcast i8* %[[THIS_i8]] to %struct.B*
  // CHECK2:   store %struct.B* %[[THIS]], %struct.B** %[[THIS_ADDR:.*]], align 4
  // CHECK2:   %[[THIS:.*]] = load %struct.B** %[[THIS_ADDR]]
  // CHECK2:   call x86_thiscallcc void @@"\01??_DB@@@@UAE@@XZ"(%struct.B* %[[THIS]])
  // ...
  // CHECK2: ret
}

void B::foo() {
// CHECK-LABEL: define x86_thiscallcc void @@"\01?foo@@B@@@@UAEXXZ"(i8*
//
// B::foo gets 'this' cast to VBase* in ECX (i.e. this+8) so we
// need to adjust 'this' before use.
//
// CHECK: %[[THIS_ADDR:.*]] = alloca %struct.B*, align 4
// CHECK: %[[THIS_i8:.*]] = getelementptr inbounds i8* %[[ECX:.*]], i32 -8
// CHECK: %[[THIS:.*]] = bitcast i8* %[[THIS_i8]] to %struct.B*
// CHECK: store %struct.B* %[[THIS]], %struct.B** %[[THIS_ADDR]], align 4

  field = 42;
// CHECK: %[[THIS:.*]] = load %struct.B** %[[THIS_ADDR]]
// CHECK: %[[THIS8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
// CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8* %[[THIS8]], i32 0
// CHECK: %[[VBPTR8:.*]] = bitcast i8* %[[VBPTR]] to i8**
// CHECK: %[[VBTABLE:.*]] = load i8** %[[VBPTR8]]
// CHECK: %[[VBENTRY8:.*]] = getelementptr inbounds i8* %[[VBTABLE]], i32 4
// CHECK: %[[VBENTRY:.*]] = bitcast i8* %[[VBENTRY8]] to i32*
// CHECK: %[[VBOFFSET32:.*]] = load i32* %[[VBENTRY]]
// CHECK: %[[VBOFFSET:.*]] = add nsw i32 0, %[[VBOFFSET32]]
// CHECK: %[[THIS8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
// CHECK: %[[VBASE_i8:.*]] = getelementptr inbounds i8* %[[THIS8]], i32 %[[VBOFFSET]]
// CHECK: %[[VBASE:.*]] = bitcast i8* %[[VBASE_i8]] to %struct.VBase*
// CHECK: %[[FIELD:.*]] = getelementptr inbounds %struct.VBase* %[[VBASE]], i32 0, i32 1
// CHECK: store i32 42, i32* %[[FIELD]], align 4
//
// CHECK: ret void
}

void call_vbase_bar(B *obj) {
// CHECK-LABEL: define void @@"\01?call_vbase_bar@@@@YAXPAUB@@@@@@Z"(%struct.B* %obj)
// CHECK: %[[OBJ:.*]] = load %struct.B

  obj->bar();
// When calling a vbase's virtual method, one needs to adjust 'this'
// at the caller site.
//
// CHECK: %[[OBJ_i8:.*]] = bitcast %struct.B* %[[OBJ]] to i8*
// CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 0
// CHECK: %[[VBPTR8:.*]] = bitcast i8* %[[VBPTR]] to i8**
// CHECK: %[[VBTABLE:.*]] = load i8** %[[VBPTR8]]
// CHECK: %[[VBENTRY8:.*]] = getelementptr inbounds i8* %[[VBTABLE]], i32 4
// CHECK: %[[VBENTRY:.*]] = bitcast i8* %[[VBENTRY8]] to i32*
// CHECK: %[[VBOFFSET32:.*]] = load i32* %[[VBENTRY]]
// CHECK: %[[VBOFFSET:.*]] = add nsw i32 0, %[[VBOFFSET32]]
// CHECK: %[[VBASE_i8:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 %[[VBOFFSET]]
// CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VBASE_i8]] to void (i8*)***
// CHECK: %[[VFTABLE:.*]] = load void (i8*)*** %[[VFPTR]]
// CHECK: %[[VFUN:.*]] = getelementptr inbounds void (i8*)** %[[VFTABLE]], i64 2
// CHECK: %[[VFUN_VALUE:.*]] = load void (i8*)** %[[VFUN]]
//
// CHECK: %[[OBJ_i8:.*]] = bitcast %struct.B* %[[OBJ]] to i8*
// CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 0
// CHECK: %[[VBPTR8:.*]] = bitcast i8* %[[VBPTR]] to i8**
// CHECK: %[[VBTABLE:.*]] = load i8** %[[VBPTR8]]
// CHECK: %[[VBENTRY8:.*]] = getelementptr inbounds i8* %[[VBTABLE]], i32 4
// CHECK: %[[VBENTRY:.*]] = bitcast i8* %[[VBENTRY8]] to i32*
// CHECK: %[[VBOFFSET32:.*]] = load i32* %[[VBENTRY]]
// CHECK: %[[VBOFFSET:.*]] = add nsw i32 0, %[[VBOFFSET32]]
// CHECK: %[[VBASE:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 %[[VBOFFSET]]
//
// CHECK: call x86_thiscallcc void %[[VFUN_VALUE]](i8* %[[VBASE]])
//
// CHECK: ret void
}

void delete_B(B *obj) {
// CHECK-LABEL: define void @@"\01?delete_B@@@@YAXPAUB@@@@@@Z"(%struct.B* %obj)
// CHECK: %[[OBJ:.*]] = load %struct.B

  delete obj;
// CHECK: %[[OBJ_i8:.*]] = bitcast %struct.B* %[[OBJ]] to i8*
// CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 0
// CHECK: %[[VBPTR8:.*]] = bitcast i8* %[[VBPTR]] to i8**
// CHECK: %[[VBTABLE:.*]] = load i8** %[[VBPTR8]]
// CHECK: %[[VBENTRY8:.*]] = getelementptr inbounds i8* %[[VBTABLE]], i32 4
// CHECK: %[[VBENTRY:.*]] = bitcast i8* %[[VBENTRY8]] to i32*
// CHECK: %[[VBOFFSET32:.*]] = load i32* %[[VBENTRY]]
// CHECK: %[[VBOFFSET:.*]] = add nsw i32 0, %[[VBOFFSET32]]
// CHECK: %[[VBASE_i8:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 %[[VBOFFSET]]
// CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VBASE_i8]] to void (%struct.B*, i32)***
// CHECK: %[[VFTABLE:.*]] = load void (%struct.B*, i32)*** %[[VFPTR]]
// CHECK: %[[VFUN:.*]] = getelementptr inbounds void (%struct.B*, i32)** %[[VFTABLE]], i64 0
// CHECK: %[[VFUN_VALUE:.*]] = load void (%struct.B*, i32)** %[[VFUN]]
//
// CHECK: %[[OBJ_i8:.*]] = bitcast %struct.B* %[[OBJ]] to i8*
// CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 0
// CHECK: %[[VBPTR8:.*]] = bitcast i8* %[[VBPTR]] to i8**
// CHECK: %[[VBTABLE:.*]] = load i8** %[[VBPTR8]]
// CHECK: %[[VBENTRY8:.*]] = getelementptr inbounds i8* %[[VBTABLE]], i32 4
// CHECK: %[[VBENTRY:.*]] = bitcast i8* %[[VBENTRY8]] to i32*
// CHECK: %[[VBOFFSET32:.*]] = load i32* %[[VBENTRY]]
// CHECK: %[[VBOFFSET:.*]] = add nsw i32 0, %[[VBOFFSET32]]
// CHECK: %[[VBASE_i8:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 %[[VBOFFSET]]
// CHECK: %[[VBASE:.*]] = bitcast i8* %[[VBASE_i8]] to %struct.B*
//
// CHECK: call x86_thiscallcc void %[[VFUN_VALUE]](%struct.B* %[[VBASE]], i32 1)
// CHECK: ret void
}

void call_complete_dtor() {
  // CHECK-LABEL: define void @@"\01?call_complete_dtor@@@@YAXXZ"
  B b;
  // CHECK: call x86_thiscallcc %struct.B* @@"\01??0B@@@@QAE@@XZ"(%struct.B* %[[B:.*]], i32 1)
  // CHECK-NOT: getelementptr
  // CHECK: call x86_thiscallcc void @@"\01??_DB@@@@UAE@@XZ"(%struct.B* %[[B]])
  // CHECK: ret
}

struct X : virtual VBase {
  int x;
};


struct C : X {
  C();
  // has an implicit vdtor.
};

// Used to crash on an assertion.
C::C() {
// CHECK-LABEL: define x86_thiscallcc %struct.C* @@"\01??0C@@@@QAE@@XZ"
}

namespace multiple_vbases {
struct A {
  virtual void a();
};

struct B {
  virtual void b();
};

struct C {
  virtual void c();
};

struct D : virtual A, virtual B, virtual C {
  virtual void a();
  virtual void b();
  virtual void c();
  D();
};

D::D() {
  // CHECK-LABEL: define x86_thiscallcc %"struct.multiple_vbases::D"* @@"\01??0D@@multiple_vbases@@@@QAE@@XZ"
  // Just make sure we emit 3 vtordisps after initializing vfptrs.
  // CHECK: store [1 x i8*]* @@"\01??_7D@@multiple_vbases@@@@6BA@@1@@@@", [1 x i8*]** %{{.*}}
  // CHECK: store [1 x i8*]* @@"\01??_7D@@multiple_vbases@@@@6BB@@1@@@@", [1 x i8*]** %{{.*}}
  // CHECK: store [1 x i8*]* @@"\01??_7D@@multiple_vbases@@@@6BC@@1@@@@", [1 x i8*]** %{{.*}}
  // ...
  // CHECK: store i32 %{{.*}}, i32* %{{.*}}
  // CHECK: store i32 %{{.*}}, i32* %{{.*}}
  // CHECK: store i32 %{{.*}}, i32* %{{.*}}
  // CHECK: ret
}
}

namespace diamond {
struct A {
  A();
  virtual ~A();
};

struct B : virtual A {
  B();
  ~B();
};

struct C : virtual A {
  C();
  ~C();
  int c1, c2, c3;
};

struct Z {
  int z;
};

struct D : virtual Z, B, C {
  D();
  ~D();
} d;

D::~D() {
  // CHECK-LABEL: define x86_thiscallcc void @@"\01??1D@@diamond@@@@UAE@@XZ"(%"struct.diamond::D"*)
  // CHECK: %[[ARG_i8:.*]] = bitcast %"struct.diamond::D"* %{{.*}} to i8*
  // CHECK: %[[THIS_i8:.*]] = getelementptr inbounds i8* %[[ARG_i8]], i32 -24
  // CHECK: %[[THIS:.*]] = bitcast i8* %[[THIS_i8]] to %"struct.diamond::D"*
  // CHECK: store %"struct.diamond::D"* %[[THIS]], %"struct.diamond::D"** %[[THIS_VAL:.*]], align 4
  // CHECK: %[[THIS:.*]] = load %"struct.diamond::D"** %[[THIS_VAL]]
  // CHECK: %[[D_i8:.*]] = bitcast %"struct.diamond::D"* %[[THIS]] to i8*
  // CHECK: %[[C_i8:.*]] = getelementptr inbounds i8* %[[D_i8]], i64 4
  // CHECK: %[[C:.*]] = bitcast i8* %[[C_i8]] to %"struct.diamond::C"*
  // CHECK: %[[C_i8:.*]] = bitcast %"struct.diamond::C"* %[[C]] to i8*
  // CHECK: %[[ARG_i8:.*]] = getelementptr i8* %{{.*}}, i32 16
  // FIXME: We might consider changing the dtor this parameter type to i8*.
  // CHECK: %[[ARG:.*]] = bitcast i8* %[[ARG_i8]] to %"struct.diamond::C"*
  // CHECK: call x86_thiscallcc void @@"\01??1C@@diamond@@@@UAE@@XZ"(%"struct.diamond::C"* %[[ARG]])

  // CHECK: %[[B:.*]] = bitcast %"struct.diamond::D"* %[[THIS]] to %"struct.diamond::B"*
  // CHECK: %[[B_i8:.*]] = bitcast %"struct.diamond::B"* %[[B]] to i8*
  // CHECK: %[[ARG_i8:.*]] = getelementptr i8* %[[B_i8]], i32 4
  // CHECK: %[[ARG:.*]] = bitcast i8* %[[ARG_i8]] to %"struct.diamond::B"*
  // CHECK: call x86_thiscallcc void @@"\01??1B@@diamond@@@@UAE@@XZ"(%"struct.diamond::B"* %[[ARG]])
  // CHECK: ret void
}

}

namespace test2 {
struct A { A(); };
struct B : virtual A { B() {} };
struct C : B, A { C() {} };

// PR18435: Order mattered here.  We were generating code for the delegating
// call to B() from C().
void callC() { C x; }

// CHECK-LABEL: define linkonce_odr x86_thiscallcc %"struct.test2::C"* @@"\01??0C@@test2@@@@QAE@@XZ"
// CHECK:           (%"struct.test2::C"* returned %this, i32 %is_most_derived)
// CHECK: br i1
//   Virtual bases
// CHECK: call x86_thiscallcc %"struct.test2::A"* @@"\01??0A@@test2@@@@QAE@@XZ"(%"struct.test2::A"* %{{.*}})
// CHECK: br label
//   Non-virtual bases
// CHECK: call x86_thiscallcc %"struct.test2::B"* @@"\01??0B@@test2@@@@QAE@@XZ"(%"struct.test2::B"* %{{.*}}, i32 0)
// CHECK: call x86_thiscallcc %"struct.test2::A"* @@"\01??0A@@test2@@@@QAE@@XZ"(%"struct.test2::A"* %{{.*}})
// CHECK: ret

// CHECK2-LABEL: define linkonce_odr x86_thiscallcc %"struct.test2::B"* @@"\01??0B@@test2@@@@QAE@@XZ"
// CHECK2:           (%"struct.test2::B"* returned %this, i32 %is_most_derived)
// CHECK2: call x86_thiscallcc %"struct.test2::A"* @@"\01??0A@@test2@@@@QAE@@XZ"(%"struct.test2::A"* %{{.*}})
// CHECK2: ret

}
@


