summaryrefslogtreecommitdiffstats
path: root/test/CodeGenCXX
diff options
context:
space:
mode:
Diffstat (limited to 'test/CodeGenCXX')
-rw-r--r--test/CodeGenCXX/2009-05-04-PureConstNounwind.cpp18
-rw-r--r--test/CodeGenCXX/2009-12-23-MissingSext.cpp10
-rw-r--r--test/CodeGenCXX/2010-07-23-DeclLoc.cpp4
-rw-r--r--test/CodeGenCXX/aarch64-arguments.cpp5
-rw-r--r--test/CodeGenCXX/aarch64-cxxabi.cpp96
-rw-r--r--test/CodeGenCXX/arm.cpp70
-rw-r--r--test/CodeGenCXX/assign-operator.cpp26
-rw-r--r--test/CodeGenCXX/attr.cpp12
-rw-r--r--test/CodeGenCXX/bitfield.cpp428
-rw-r--r--test/CodeGenCXX/blocks-cxx11.cpp30
-rw-r--r--test/CodeGenCXX/blocks.cpp33
-rw-r--r--test/CodeGenCXX/bool-bitfield.cpp14
-rw-r--r--test/CodeGenCXX/builtins.cpp2
-rw-r--r--test/CodeGenCXX/c-linkage.cpp20
-rw-r--r--test/CodeGenCXX/catch-undef-behavior.cpp210
-rw-r--r--test/CodeGenCXX/constructor-alias.cpp12
-rw-r--r--test/CodeGenCXX/constructor-destructor-return-this.cpp60
-rw-r--r--test/CodeGenCXX/copy-assign-synthesis-1.cpp6
-rw-r--r--test/CodeGenCXX/coverage.cpp7
-rw-r--r--test/CodeGenCXX/cp-blocks-linetables.cpp61
-rw-r--r--test/CodeGenCXX/cxx0x-delegating-ctors.cpp38
-rw-r--r--test/CodeGenCXX/cxx0x-initializer-array.cpp103
-rw-r--r--test/CodeGenCXX/cxx11-exception-spec.cpp71
-rw-r--r--test/CodeGenCXX/cxx11-noreturn.cpp10
-rw-r--r--test/CodeGenCXX/cxx11-trivial-initializer-struct.cpp21
-rw-r--r--test/CodeGenCXX/debug-info-artificial-arg.cpp11
-rw-r--r--test/CodeGenCXX/debug-info-byval.cpp2
-rw-r--r--test/CodeGenCXX/debug-info-char16.cpp2
-rw-r--r--test/CodeGenCXX/debug-info-class.cpp44
-rw-r--r--test/CodeGenCXX/debug-info-dup-fwd-decl.cpp6
-rw-r--r--test/CodeGenCXX/debug-info-enum-class.cpp8
-rw-r--r--test/CodeGenCXX/debug-info-flex-member.cpp2
-rw-r--r--test/CodeGenCXX/debug-info-fwd-ref.cpp9
-rw-r--r--test/CodeGenCXX/debug-info-method.cpp25
-rw-r--r--test/CodeGenCXX/debug-info-namespace.cpp21
-rw-r--r--test/CodeGenCXX/debug-info-nullptr.cpp2
-rw-r--r--test/CodeGenCXX/debug-info-pubtypes.cpp4
-rw-r--r--test/CodeGenCXX/debug-info-rvalue-ref.cpp2
-rw-r--r--test/CodeGenCXX/debug-info-same-line.cpp98
-rw-r--r--test/CodeGenCXX/debug-info-static-fns.cpp2
-rw-r--r--test/CodeGenCXX/debug-info-static-member.cpp41
-rw-r--r--test/CodeGenCXX/debug-info-template-member.cpp6
-rw-r--r--test/CodeGenCXX/debug-info-template-quals.cpp20
-rw-r--r--test/CodeGenCXX/debug-info-union-template.cpp15
-rw-r--r--test/CodeGenCXX/debug-info-union.cpp8
-rw-r--r--test/CodeGenCXX/debug-info-use-after-free.cpp3
-rw-r--r--test/CodeGenCXX/debug-info-zero-length-arrays.cpp12
-rw-r--r--test/CodeGenCXX/debug-lambda-expressions.cpp50
-rw-r--r--test/CodeGenCXX/debug-lambda-this.cpp2
-rw-r--r--test/CodeGenCXX/default-destructor-synthesis.cpp4
-rw-r--r--test/CodeGenCXX/delete.cpp4
-rw-r--r--test/CodeGenCXX/derived-to-base.cpp6
-rw-r--r--test/CodeGenCXX/destructors.cpp10
-rw-r--r--test/CodeGenCXX/dynamic-cast-always-null.cpp4
-rw-r--r--test/CodeGenCXX/dynamic-cast-hint.cpp53
-rw-r--r--test/CodeGenCXX/dynamic-cast.cpp7
-rw-r--r--test/CodeGenCXX/eh.cpp23
-rw-r--r--test/CodeGenCXX/exception-spec-decay.cpp33
-rw-r--r--test/CodeGenCXX/exceptions.cpp82
-rw-r--r--test/CodeGenCXX/extern-c.cpp32
-rw-r--r--test/CodeGenCXX/global-array-destruction.cpp17
-rw-r--r--test/CodeGenCXX/global-dtor-no-atexit.cpp10
-rw-r--r--test/CodeGenCXX/global-init.cpp4
-rw-r--r--test/CodeGenCXX/implicit-copy-assign-operator.cpp2
-rw-r--r--test/CodeGenCXX/implicit-copy-constructor.cpp5
-rw-r--r--test/CodeGenCXX/inheriting-constructor.cpp11
-rw-r--r--test/CodeGenCXX/key-function-vtable.cpp3
-rw-r--r--test/CodeGenCXX/lambda-expressions.cpp33
-rw-r--r--test/CodeGenCXX/mangle-ms-back-references-pr13207.cpp4
-rw-r--r--test/CodeGenCXX/mangle-ms-templates.cpp13
-rw-r--r--test/CodeGenCXX/mangle-ms-vector-types.cpp33
-rw-r--r--test/CodeGenCXX/mangle-ms.cpp11
-rw-r--r--test/CodeGenCXX/mangle.cpp25
-rw-r--r--test/CodeGenCXX/member-functions.cpp63
-rw-r--r--test/CodeGenCXX/member-initializers.cpp5
-rw-r--r--test/CodeGenCXX/microsoft-abi-array-cookies.cpp4
-rw-r--r--test/CodeGenCXX/microsoft-abi-constructors.cpp24
-rw-r--r--test/CodeGenCXX/microsoft-abi-default-cc.cpp4
-rwxr-xr-xtest/CodeGenCXX/microsoft-abi-member-pointers.cpp51
-rw-r--r--test/CodeGenCXX/microsoft-abi-static-initializers.cpp10
-rw-r--r--test/CodeGenCXX/microsoft-abi-structors.cpp215
-rw-r--r--test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp113
-rw-r--r--test/CodeGenCXX/no-exceptions.cpp4
-rw-r--r--test/CodeGenCXX/no-opt-volatile-memcpy.cpp50
-rw-r--r--test/CodeGenCXX/noinline-template.cpp4
-rw-r--r--test/CodeGenCXX/nrvo.cpp7
-rw-r--r--test/CodeGenCXX/pod-member-memcpys.cpp256
-rw-r--r--test/CodeGenCXX/pointers-to-data-members.cpp6
-rw-r--r--test/CodeGenCXX/pragma-weak.cpp31
-rw-r--r--test/CodeGenCXX/predefined-expr.cpp2
-rw-r--r--test/CodeGenCXX/reference-cast.cpp4
-rw-r--r--test/CodeGenCXX/references.cpp9
-rw-r--r--test/CodeGenCXX/runtimecc.cpp53
-rw-r--r--test/CodeGenCXX/sizeof-unwind-exception.cpp15
-rw-r--r--test/CodeGenCXX/temp-order.cpp2
-rw-r--r--test/CodeGenCXX/template-anonymous-types.cpp16
-rw-r--r--test/CodeGenCXX/template-linkage.cpp20
-rw-r--r--test/CodeGenCXX/temporaries.cpp21
-rw-r--r--test/CodeGenCXX/threadsafe-statics.cpp8
-rw-r--r--test/CodeGenCXX/thunks.cpp4
-rw-r--r--test/CodeGenCXX/trivial-constructor-init.cpp18
-rw-r--r--test/CodeGenCXX/type_visibility.cpp170
-rw-r--r--test/CodeGenCXX/typeid.cpp4
-rw-r--r--test/CodeGenCXX/value-init.cpp6
-rw-r--r--test/CodeGenCXX/virtual-base-cast.cpp8
-rw-r--r--test/CodeGenCXX/virtual-function-calls.cpp15
-rw-r--r--test/CodeGenCXX/visibility-inlines-hidden.cpp29
-rw-r--r--test/CodeGenCXX/visibility-ms-compat.cpp112
-rw-r--r--test/CodeGenCXX/visibility.cpp217
-rw-r--r--test/CodeGenCXX/vtable-available-externally.cpp9
-rw-r--r--test/CodeGenCXX/vtable-key-function-arm.cpp307
-rw-r--r--test/CodeGenCXX/vtable-key-function-ios.cpp189
-rw-r--r--test/CodeGenCXX/vtable-linkage.cpp26
113 files changed, 3962 insertions, 340 deletions
diff --git a/test/CodeGenCXX/2009-05-04-PureConstNounwind.cpp b/test/CodeGenCXX/2009-05-04-PureConstNounwind.cpp
index 7acc07d..3828388 100644
--- a/test/CodeGenCXX/2009-05-04-PureConstNounwind.cpp
+++ b/test/CodeGenCXX/2009-05-04-PureConstNounwind.cpp
@@ -3,13 +3,19 @@ int c(void) __attribute__((const));
int p(void) __attribute__((pure));
int t(void);
-// CHECK: define i32 @_Z1fv() {
+// CHECK: define i32 @_Z1fv() [[TF:#[0-9]+]] {
int f(void) {
- // CHECK: call i32 @_Z1cv() nounwind readnone
- // CHECK: call i32 @_Z1pv() nounwind readonly
+ // CHECK: call i32 @_Z1cv() [[NUW_RN_CALL:#[0-9]+]]
+ // CHECK: call i32 @_Z1pv() [[NUW_RO_CALL:#[0-9]+]]
return c() + p() + t();
}
-// CHECK: declare i32 @_Z1cv() nounwind readnone
-// CHECK: declare i32 @_Z1pv() nounwind readonly
-// CHECK-NOT: declare i32 @_Z1tv() nounwind
+// CHECK: declare i32 @_Z1cv() [[NUW_RN:#[0-9]+]]
+// CHECK: declare i32 @_Z1pv() [[NUW_RO:#[0-9]+]]
+// CHECK: declare i32 @_Z1tv() [[TF]]
+
+// CHECK: attributes [[TF]] = { {{.*}} }
+// CHECK: attributes [[NUW_RN]] = { nounwind readnone{{.*}} }
+// CHECK: attributes [[NUW_RO]] = { nounwind readonly{{.*}} }
+// CHECK: attributes [[NUW_RN_CALL]] = { nounwind readnone }
+// CHECK: attributes [[NUW_RO_CALL]] = { nounwind readonly }
diff --git a/test/CodeGenCXX/2009-12-23-MissingSext.cpp b/test/CodeGenCXX/2009-12-23-MissingSext.cpp
index e6ff7b3..2b42367 100644
--- a/test/CodeGenCXX/2009-12-23-MissingSext.cpp
+++ b/test/CodeGenCXX/2009-12-23-MissingSext.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -triple x86_64-unknown-unknown -emit-llvm -o - | FileCheck %s
// The store of p.y into the temporary was not
// getting extended to 32 bits, so uninitialized
// bits of the temporary were used. 7366161.
@@ -8,8 +8,12 @@ struct foo {
};
int bar(struct foo p, int x) {
// CHECK: bar
-// CHECK: and {{.*}} 16777215
-// CHECK: and {{.*}} 16777215
+// CHECK: %[[val:.*]] = load i32* {{.*}}
+// CHECK-NEXT: ashr i32 %[[val]]
+// CHECK: = load i32* {{.*}}
+// CHECK: = load i32* {{.*}}
+// CHECK: %[[val:.*]] = load i32* {{.*}}
+// CHECK-NEXT: ashr i32 %[[val]]
x = (p.y > x ? x : p.y);
return x;
// CHECK: ret
diff --git a/test/CodeGenCXX/2010-07-23-DeclLoc.cpp b/test/CodeGenCXX/2010-07-23-DeclLoc.cpp
index 7405448..4c68902 100644
--- a/test/CodeGenCXX/2010-07-23-DeclLoc.cpp
+++ b/test/CodeGenCXX/2010-07-23-DeclLoc.cpp
@@ -1,9 +1,9 @@
// RUN: %clang_cc1 -emit-llvm -g %s -o - | FileCheck %s
// Require the template function declaration refer to the correct filename.
// First, locate the function decl in metadata, and pluck out the file handle:
-// CHECK: {{extract_dwarf_data_from_header.*extract_dwarf_data_from_header.*extract_dwarf_data_from_header.*[^ ]+", metadata !}}[[filehandle:[0-9]+]],
+// CHECK: metadata [[filehandle:![0-9]+]], {{[^,]*}}, {{.*extract_dwarf_data_from_header.*extract_dwarf_data_from_header.*extract_dwarf_data_from_header.*[^ ]+", }}
// Second: Require that filehandle refer to the correct filename:
-// CHECK: {{^!}}[[filehandle]] = metadata {{![{].*}} metadata !"decl_should_be_here.hpp",
+// CHECK: [[filehandle]] = {{.*}}decl_should_be_here.hpp"
typedef long unsigned int __darwin_size_t;
typedef __darwin_size_t size_t;
typedef unsigned char uint8_t;
diff --git a/test/CodeGenCXX/aarch64-arguments.cpp b/test/CodeGenCXX/aarch64-arguments.cpp
new file mode 100644
index 0000000..f56ad0b
--- /dev/null
+++ b/test/CodeGenCXX/aarch64-arguments.cpp
@@ -0,0 +1,5 @@
+// RUN: %clang_cc1 -triple aarch64-none-linux -emit-llvm -w -o - %s | FileCheck -check-prefix=PCS %s
+
+// PCS: define void @{{.*}}(i8 %a
+struct s0 {};
+void f0(s0 a) {}
diff --git a/test/CodeGenCXX/aarch64-cxxabi.cpp b/test/CodeGenCXX/aarch64-cxxabi.cpp
new file mode 100644
index 0000000..04d9493
--- /dev/null
+++ b/test/CodeGenCXX/aarch64-cxxabi.cpp
@@ -0,0 +1,96 @@
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -emit-llvm -w -o - %s | FileCheck %s
+
+// Check differences between the generic Itanium ABI, the AArch32 version and
+// the AArch64 version.
+
+////////////////////////////////////////////////////////////////////////////////
+
+// The ABI says that the key function is the "textually first, non-inline,
+// non-pure, virtual member function". The generic version decides this after
+// the completion of the class definition; the AArch32 version decides this at
+// the end of the translation unit.
+
+// We construct a class which needs a VTable here under generic ABI, but not
+// AArch32.
+
+// (see next section for explanation of guard)
+// CHECK: @_ZGVZ15guard_variablesiE4mine = internal global i64 0
+
+// CHECK: @_ZTV16CheckKeyFunction =
+struct CheckKeyFunction {
+ virtual void foo();
+};
+
+// This is not inline when CheckKeyFunction is completed, so
+// CheckKeyFunction::foo is the key function. VTables should be emitted.
+inline void CheckKeyFunction::foo() {
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+// Guard variables only specify and use the low bit to determine status, rather
+// than the low byte as in the generic Itanium ABI. However, unlike 32-bit ARM,
+// they *are* 64-bits wide so check that in case confusion has occurred.
+
+class Guarded {
+public:
+ Guarded(int i);
+ ~Guarded();
+};
+
+void guard_variables(int a) {
+ static Guarded mine(a);
+// CHECK: [[GUARDBIT:%[0-9]+]] = and i64 {{%[0-9]+}}, 1
+// CHECK: icmp eq i64 [[GUARDBIT]], 0
+
+ // As guards are 64-bit, these helpers should take 64-bit pointers.
+// CHECK: call i32 @__cxa_guard_acquire(i64*
+// CHECK: call void @__cxa_guard_release(i64*
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+// Member function pointers use the adj field to distinguish between virtual and
+// nonvirtual members. As a result the adjustment is shifted (if ptr was used, a
+// mask would be expected instead).
+
+class C {
+ int a();
+ virtual int b();
+};
+
+
+int member_pointer(C &c, int (C::*func)()) {
+// CHECK: ashr i64 %[[MEMPTRADJ:[0-9a-z.]+]], 1
+// CHECK: %[[ISVIRTUAL:[0-9]+]] = and i64 %[[MEMPTRADJ]], 1
+// CHECK: icmp ne i64 %[[ISVIRTUAL]], 0
+ return (c.*func)();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+// AArch64 PCS says that va_list type is based on "struct __va_list ..." in the
+// std namespace, which means it should mangle as "St9__va_list".
+
+// CHECK: @_Z7va_funcSt9__va_list
+void va_func(__builtin_va_list l) {
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+// AArch64 constructors (like generic Itanium, but unlike AArch32) do not return
+// "this".
+
+void test_constructor() {
+ Guarded g(42);
+// CHECK: call void @_ZN7GuardedC1Ei
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+// In principle the AArch32 ABI allows this to be accomplished via a call to
+// __aeabi_atexit instead of __cxa_atexit. Clang doesn't make use of this at the
+// moment, but it's definitely not allowed for AArch64.
+
+// CHECK: call i32 @__cxa_atexit
+Guarded g(42);
diff --git a/test/CodeGenCXX/arm.cpp b/test/CodeGenCXX/arm.cpp
index 6c60f30..48f2f00 100644
--- a/test/CodeGenCXX/arm.cpp
+++ b/test/CodeGenCXX/arm.cpp
@@ -56,15 +56,15 @@ namespace test1 {
// CHECK: [[THIS:%.*]] = alloca [[A]]*, align 4
// CHECK: store [[A]]* {{.*}}, [[A]]** [[THIS]]
// CHECK: [[THIS1:%.*]] = load [[A]]** [[THIS]]
- // CHECK: call [[A]]* @_ZN5test11AC2Ei(
- // CHECK: ret [[A]]* [[THIS1]]
+ // CHECK: [[THIS2:%.*]] = call [[A]]* @_ZN5test11AC2Ei(
+ // CHECK: ret [[A]]* [[THIS2]]
// CHECK: define linkonce_odr [[A]]* @_ZN5test11AD1Ev([[A]]* %this) unnamed_addr
// CHECK: [[THIS:%.*]] = alloca [[A]]*, align 4
// CHECK: store [[A]]* {{.*}}, [[A]]** [[THIS]]
// CHECK: [[THIS1:%.*]] = load [[A]]** [[THIS]]
- // CHECK: call [[A]]* @_ZN5test11AD2Ev(
- // CHECK: ret [[A]]* [[THIS1]]
+ // CHECK: [[THIS2:%.*]] = call [[A]]* @_ZN5test11AD2Ev(
+ // CHECK: ret [[A]]* [[THIS2]]
}
// Awkward virtual cases.
@@ -274,11 +274,11 @@ namespace test6 {
// CHECK-NEXT: [[V:%.*]] = load [[A]]** [[AVAR]], align 4
// CHECK-NEXT: [[ISNULL:%.*]] = icmp eq [[A]]* [[V]], null
// CHECK-NEXT: br i1 [[ISNULL]]
- // CHECK: [[T0:%.*]] = bitcast [[A]]* [[V]] to [[A]]* ([[A]]*)***
- // CHECK-NEXT: [[T1:%.*]] = load [[A]]* ([[A]]*)*** [[T0]]
- // CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds [[A]]* ([[A]]*)** [[T1]], i64 1
- // CHECK-NEXT: [[T3:%.*]] = load [[A]]* ([[A]]*)** [[T2]]
- // CHECK-NEXT: call [[A]]* [[T3]]([[A]]* [[V]])
+ // CHECK: [[T0:%.*]] = bitcast [[A]]* [[V]] to void ([[A]]*)***
+ // CHECK-NEXT: [[T1:%.*]] = load void ([[A]]*)*** [[T0]]
+ // CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds void ([[A]]*)** [[T1]], i64 1
+ // CHECK-NEXT: [[T3:%.*]] = load void ([[A]]*)** [[T2]]
+ // CHECK-NEXT: call void [[T3]]([[A]]* [[V]])
// CHECK-NEXT: br label
// CHECK: ret void
delete a;
@@ -357,6 +357,58 @@ namespace test8 {
}
}
+// rdar://12836470
+// Use a larger-than-mandated array cookie when allocating an
+// array whose type is overaligned.
+namespace test9 {
+ class __attribute__((aligned(16))) A {
+ float data[4];
+ public:
+ A();
+ ~A();
+ };
+
+ A *testNew(unsigned n) {
+ return new A[n];
+ }
+// CHECK: define [[TEST9:%.*]]* @_ZN5test97testNewEj(i32
+// CHECK: [[N_VAR:%.*]] = alloca i32, align 4
+// CHECK: [[N:%.*]] = load i32* [[N_VAR]], align 4
+// CHECK-NEXT: [[T0:%.*]] = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 [[N]], i32 16)
+// CHECK-NEXT: [[O0:%.*]] = extractvalue { i32, i1 } [[T0]], 1
+// CHECK-NEXT: [[T1:%.*]] = extractvalue { i32, i1 } [[T0]], 0
+// CHECK-NEXT: [[T2:%.*]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[T1]], i32 16)
+// CHECK-NEXT: [[O1:%.*]] = extractvalue { i32, i1 } [[T2]], 1
+// CHECK-NEXT: [[OVERFLOW:%.*]] = or i1 [[O0]], [[O1]]
+// CHECK-NEXT: [[T3:%.*]] = extractvalue { i32, i1 } [[T2]], 0
+// CHECK-NEXT: [[T4:%.*]] = select i1 [[OVERFLOW]], i32 -1, i32 [[T3]]
+// CHECK-NEXT: [[ALLOC:%.*]] = call noalias i8* @_Znam(i32 [[T4]])
+// CHECK-NEXT: [[T0:%.*]] = bitcast i8* [[ALLOC]] to i32*
+// CHECK-NEXT: store i32 16, i32* [[T0]]
+// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i32* [[T0]], i32 1
+// CHECK-NEXT: store i32 [[N]], i32* [[T1]]
+// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds i8* [[ALLOC]], i64 16
+// CHECK-NEXT: bitcast i8* [[T0]] to [[TEST9]]*
+// Array allocation follows.
+
+ void testDelete(A *array) {
+ delete[] array;
+ }
+// CHECK: define void @_ZN5test910testDeleteEPNS_1AE(
+// CHECK: [[BEGIN:%.*]] = load [[TEST9]]**
+// CHECK-NEXT: [[T0:%.*]] = icmp eq [[TEST9]]* [[BEGIN]], null
+// CHECK-NEXT: br i1 [[T0]],
+// CHECK: [[T0:%.*]] = bitcast [[TEST9]]* [[BEGIN]] to i8*
+// CHECK-NEXT: [[ALLOC:%.*]] = getelementptr inbounds i8* [[T0]], i64 -16
+// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds i8* [[ALLOC]], i64 4
+// CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to i32*
+// CHECK-NEXT: [[N:%.*]] = load i32* [[T1]]
+// CHECK-NEXT: [[END:%.*]] = getelementptr inbounds [[TEST9]]* [[BEGIN]], i32 [[N]]
+// CHECK-NEXT: [[T0:%.*]] = icmp eq [[TEST9]]* [[BEGIN]], [[END]]
+// CHECK-NEXT: br i1 [[T0]],
+// Array deallocation follows.
+}
+
// CHECK: define linkonce_odr [[C:%.*]]* @_ZTv0_n12_N5test21CD1Ev(
// CHECK: call [[C]]* @_ZN5test21CD1Ev(
// CHECK: ret [[C]]* undef
diff --git a/test/CodeGenCXX/assign-operator.cpp b/test/CodeGenCXX/assign-operator.cpp
index e19df27..40695b7 100644
--- a/test/CodeGenCXX/assign-operator.cpp
+++ b/test/CodeGenCXX/assign-operator.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -emit-llvm -verify -o - |FileCheck %s
+// RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -emit-llvm -o - -std=c++11 |FileCheck %s
class x {
public: int operator=(int);
@@ -28,3 +28,27 @@ namespace test1 {
A<int> a;
}
+
+// Ensure that we use memcpy when we would have selected a trivial assignment
+// operator, even for a non-trivially-copyable type.
+struct A {
+ A &operator=(const A&);
+};
+struct B {
+ B(const B&);
+ B &operator=(const B&) = default;
+ int n;
+};
+struct C {
+ A a;
+ B b[16];
+};
+void b(C &a, C &b) {
+ // CHECK: define {{.*}} @_ZN1CaSERKS_(
+ // CHECK: call {{.*}} @_ZN1AaSERKS_(
+ // CHECK-NOT: call {{.*}} @_ZN1BaSERKS_(
+ // CHECK: call {{.*}} @{{.*}}memcpy
+ // CHECK-NOT: call {{.*}} @_ZN1BaSERKS_(
+ // CHECK: }
+ a = b;
+}
diff --git a/test/CodeGenCXX/attr.cpp b/test/CodeGenCXX/attr.cpp
index a0dd748..4748cda 100644
--- a/test/CodeGenCXX/attr.cpp
+++ b/test/CodeGenCXX/attr.cpp
@@ -2,7 +2,7 @@
// CHECK: @test2 = alias i32 ()* @_Z5test1v
-// CHECK: define i32 @_Z3foov() nounwind align 1024
+// CHECK: define i32 @_Z3foov() [[NUW:#[0-9]+]] align 1024
int foo() __attribute__((aligned(1024)));
int foo() { }
@@ -13,16 +13,16 @@ class C {
void bar4() __attribute__((aligned(1024)));
} c;
-// CHECK: define void @_ZN1C4bar1Ev(%class.C* %this) unnamed_addr nounwind align 2
+// CHECK: define void @_ZN1C4bar1Ev(%class.C* %this) unnamed_addr [[NUW]] align 2
void C::bar1() { }
-// CHECK: define void @_ZN1C4bar2Ev(%class.C* %this) unnamed_addr nounwind align 2
+// CHECK: define void @_ZN1C4bar2Ev(%class.C* %this) unnamed_addr [[NUW]] align 2
void C::bar2() { }
-// CHECK: define void @_ZN1C4bar3Ev(%class.C* %this) unnamed_addr nounwind align 1024
+// CHECK: define void @_ZN1C4bar3Ev(%class.C* %this) unnamed_addr [[NUW]] align 1024
void C::bar3() { }
-// CHECK: define void @_ZN1C4bar4Ev(%class.C* %this) nounwind align 1024
+// CHECK: define void @_ZN1C4bar4Ev(%class.C* %this) [[NUW]] align 1024
void C::bar4() { }
// PR6635
@@ -30,3 +30,5 @@ void C::bar4() { }
int test1() { return 10; }
// CHECK at top of file
extern "C" int test2() __attribute__((alias("_Z5test1v")));
+
+// CHECK: attributes [[NUW]] = { nounwind{{.*}} }
diff --git a/test/CodeGenCXX/bitfield.cpp b/test/CodeGenCXX/bitfield.cpp
new file mode 100644
index 0000000..1814aa2
--- /dev/null
+++ b/test/CodeGenCXX/bitfield.cpp
@@ -0,0 +1,428 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -verify -emit-llvm -o - %s \
+// RUN: | FileCheck -check-prefix=CHECK-X86-64 %s
+// RUN: %clang_cc1 -triple powerpc64-unknown-unknown -verify -emit-llvm -o - %s \
+// RUN: | FileCheck -check-prefix=CHECK-PPC64 %s
+//
+// Tests for bitfield access patterns in C++ with special attention to
+// conformance to C++11 memory model requirements.
+
+namespace N0 {
+ // Test basic bitfield layout access across interesting byte and word
+ // boundaries on both little endian and big endian platforms.
+ struct __attribute__((packed)) S {
+ unsigned b00 : 14;
+ unsigned b01 : 2;
+ unsigned b20 : 6;
+ unsigned b21 : 2;
+ unsigned b30 : 30;
+ unsigned b31 : 2;
+ unsigned b70 : 6;
+ unsigned b71 : 2;
+ };
+ unsigned read00(S* s) {
+ // CHECK-X86-64: define i32 @_ZN2N06read00
+ // CHECK-X86-64: %[[ptr:.*]] = bitcast %{{.*}}* %{{.*}} to i64*
+ // CHECK-X86-64: %[[val:.*]] = load i64* %[[ptr]]
+ // CHECK-X86-64: %[[and:.*]] = and i64 %[[val]], 16383
+ // CHECK-X86-64: %[[trunc:.*]] = trunc i64 %[[and]] to i32
+ // CHECK-X86-64: ret i32 %[[trunc]]
+ // CHECK-PPC64: define zeroext i32 @_ZN2N06read00
+ // CHECK-PPC64: %[[ptr:.*]] = bitcast %{{.*}}* %{{.*}} to i64*
+ // CHECK-PPC64: %[[val:.*]] = load i64* %[[ptr]]
+ // CHECK-PPC64: %[[shr:.*]] = lshr i64 %[[val]], 50
+ // CHECK-PPC64: %[[trunc:.*]] = trunc i64 %[[shr]] to i32
+ // CHECK-PPC64: ret i32 %[[trunc]]
+ return s->b00;
+ }
+ unsigned read01(S* s) {
+ // CHECK-X86-64: define i32 @_ZN2N06read01
+ // CHECK-X86-64: %[[ptr:.*]] = bitcast %{{.*}}* %{{.*}} to i64*
+ // CHECK-X86-64: %[[val:.*]] = load i64* %[[ptr]]
+ // CHECK-X86-64: %[[shr:.*]] = lshr i64 %[[val]], 14
+ // CHECK-X86-64: %[[and:.*]] = and i64 %[[shr]], 3
+ // CHECK-X86-64: %[[trunc:.*]] = trunc i64 %[[and]] to i32
+ // CHECK-X86-64: ret i32 %[[trunc]]
+ // CHECK-PPC64: define zeroext i32 @_ZN2N06read01
+ // CHECK-PPC64: %[[ptr:.*]] = bitcast %{{.*}}* %{{.*}} to i64*
+ // CHECK-PPC64: %[[val:.*]] = load i64* %[[ptr]]
+ // CHECK-PPC64: %[[shr:.*]] = lshr i64 %[[val]], 48
+ // CHECK-PPC64: %[[and:.*]] = and i64 %[[shr]], 3
+ // CHECK-PPC64: %[[trunc:.*]] = trunc i64 %[[and]] to i32
+ // CHECK-PPC64: ret i32 %[[trunc]]
+ return s->b01;
+ }
+ unsigned read20(S* s) {
+ // CHECK-X86-64: define i32 @_ZN2N06read20
+ // CHECK-X86-64: %[[ptr:.*]] = bitcast %{{.*}}* %{{.*}} to i64*
+ // CHECK-X86-64: %[[val:.*]] = load i64* %[[ptr]]
+ // CHECK-X86-64: %[[shr:.*]] = lshr i64 %[[val]], 16
+ // CHECK-X86-64: %[[and:.*]] = and i64 %[[shr]], 63
+ // CHECK-X86-64: %[[trunc:.*]] = trunc i64 %[[and]] to i32
+ // CHECK-X86-64: ret i32 %[[trunc]]
+ // CHECK-PPC64: define zeroext i32 @_ZN2N06read20
+ // CHECK-PPC64: %[[ptr:.*]] = bitcast %{{.*}}* %{{.*}} to i64*
+ // CHECK-PPC64: %[[val:.*]] = load i64* %[[ptr]]
+ // CHECK-PPC64: %[[shr:.*]] = lshr i64 %[[val]], 42
+ // CHECK-PPC64: %[[and:.*]] = and i64 %[[shr]], 63
+ // CHECK-PPC64: %[[trunc:.*]] = trunc i64 %[[and]] to i32
+ // CHECK-PPC64: ret i32 %[[trunc]]
+ return s->b20;
+ }
+ unsigned read21(S* s) {
+ // CHECK-X86-64: define i32 @_ZN2N06read21
+ // CHECK-X86-64: %[[ptr:.*]] = bitcast %{{.*}}* %{{.*}} to i64*
+ // CHECK-X86-64: %[[val:.*]] = load i64* %[[ptr]]
+ // CHECK-X86-64: %[[shr:.*]] = lshr i64 %[[val]], 22
+ // CHECK-X86-64: %[[and:.*]] = and i64 %[[shr]], 3
+ // CHECK-X86-64: %[[trunc:.*]] = trunc i64 %[[and]] to i32
+ // CHECK-X86-64: ret i32 %[[trunc]]
+ // CHECK-PPC64: define zeroext i32 @_ZN2N06read21
+ // CHECK-PPC64: %[[ptr:.*]] = bitcast %{{.*}}* %{{.*}} to i64*
+ // CHECK-PPC64: %[[val:.*]] = load i64* %[[ptr]]
+ // CHECK-PPC64: %[[shr:.*]] = lshr i64 %[[val]], 40
+ // CHECK-PPC64: %[[and:.*]] = and i64 %[[shr]], 3
+ // CHECK-PPC64: %[[trunc:.*]] = trunc i64 %[[and]] to i32
+ // CHECK-PPC64: ret i32 %[[trunc]]
+ return s->b21;
+ }
+ unsigned read30(S* s) {
+ // CHECK-X86-64: define i32 @_ZN2N06read30
+ // CHECK-X86-64: %[[ptr:.*]] = bitcast %{{.*}}* %{{.*}} to i64*
+ // CHECK-X86-64: %[[val:.*]] = load i64* %[[ptr]]
+ // CHECK-X86-64: %[[shr:.*]] = lshr i64 %[[val]], 24
+ // CHECK-X86-64: %[[and:.*]] = and i64 %[[shr]], 1073741823
+ // CHECK-X86-64: %[[trunc:.*]] = trunc i64 %[[and]] to i32
+ // CHECK-X86-64: ret i32 %[[trunc]]
+ // CHECK-PPC64: define zeroext i32 @_ZN2N06read30
+ // CHECK-PPC64: %[[ptr:.*]] = bitcast %{{.*}}* %{{.*}} to i64*
+ // CHECK-PPC64: %[[val:.*]] = load i64* %[[ptr]]
+ // CHECK-PPC64: %[[shr:.*]] = lshr i64 %[[val]], 10
+ // CHECK-PPC64: %[[and:.*]] = and i64 %[[shr]], 1073741823
+ // CHECK-PPC64: %[[trunc:.*]] = trunc i64 %[[and]] to i32
+ // CHECK-PPC64: ret i32 %[[trunc]]
+ return s->b30;
+ }
+ unsigned read31(S* s) {
+ // CHECK-X86-64: define i32 @_ZN2N06read31
+ // CHECK-X86-64: %[[ptr:.*]] = bitcast %{{.*}}* %{{.*}} to i64*
+ // CHECK-X86-64: %[[val:.*]] = load i64* %[[ptr]]
+ // CHECK-X86-64: %[[shr:.*]] = lshr i64 %[[val]], 54
+ // CHECK-X86-64: %[[and:.*]] = and i64 %[[shr]], 3
+ // CHECK-X86-64: %[[trunc:.*]] = trunc i64 %[[and]] to i32
+ // CHECK-X86-64: ret i32 %[[trunc]]
+ // CHECK-PPC64: define zeroext i32 @_ZN2N06read31
+ // CHECK-PPC64: %[[ptr:.*]] = bitcast %{{.*}}* %{{.*}} to i64*
+ // CHECK-PPC64: %[[val:.*]] = load i64* %[[ptr]]
+ // CHECK-PPC64: %[[shr:.*]] = lshr i64 %[[val]], 8
+ // CHECK-PPC64: %[[and:.*]] = and i64 %[[shr]], 3
+ // CHECK-PPC64: %[[trunc:.*]] = trunc i64 %[[and]] to i32
+ // CHECK-PPC64: ret i32 %[[trunc]]
+ return s->b31;
+ }
+ unsigned read70(S* s) {
+ // CHECK-X86-64: define i32 @_ZN2N06read70
+ // CHECK-X86-64: %[[ptr:.*]] = bitcast %{{.*}}* %{{.*}} to i64*
+ // CHECK-X86-64: %[[val:.*]] = load i64* %[[ptr]]
+ // CHECK-X86-64: %[[shr:.*]] = lshr i64 %[[val]], 56
+ // CHECK-X86-64: %[[and:.*]] = and i64 %[[shr]], 63
+ // CHECK-X86-64: %[[trunc:.*]] = trunc i64 %[[and]] to i32
+ // CHECK-X86-64: ret i32 %[[trunc]]
+ // CHECK-PPC64: define zeroext i32 @_ZN2N06read70
+ // CHECK-PPC64: %[[ptr:.*]] = bitcast %{{.*}}* %{{.*}} to i64*
+ // CHECK-PPC64: %[[val:.*]] = load i64* %[[ptr]]
+ // CHECK-PPC64: %[[shr:.*]] = lshr i64 %[[val]], 2
+ // CHECK-PPC64: %[[and:.*]] = and i64 %[[shr]], 63
+ // CHECK-PPC64: %[[trunc:.*]] = trunc i64 %[[and]] to i32
+ // CHECK-PPC64: ret i32 %[[trunc]]
+ return s->b70;
+ }
+ unsigned read71(S* s) {
+ // CHECK-X86-64: define i32 @_ZN2N06read71
+ // CHECK-X86-64: %[[ptr:.*]] = bitcast %{{.*}}* %{{.*}} to i64*
+ // CHECK-X86-64: %[[val:.*]] = load i64* %[[ptr]]
+ // CHECK-X86-64: %[[shr:.*]] = lshr i64 %[[val]], 62
+ // CHECK-X86-64: %[[trunc:.*]] = trunc i64 %[[shr]] to i32
+ // CHECK-X86-64: ret i32 %[[trunc]]
+ // CHECK-PPC64: define zeroext i32 @_ZN2N06read71
+ // CHECK-PPC64: %[[ptr:.*]] = bitcast %{{.*}}* %{{.*}} to i64*
+ // CHECK-PPC64: %[[val:.*]] = load i64* %[[ptr]]
+ // CHECK-PPC64: %[[and:.*]] = and i64 %[[val]], 3
+ // CHECK-PPC64: %[[trunc:.*]] = trunc i64 %[[and]] to i32
+ // CHECK-PPC64: ret i32 %[[trunc]]
+ return s->b71;
+ }
+}
+
+namespace N1 {
+ // Ensure that neither loads nor stores to bitfields are not widened into
+ // other memory locations. (PR13691)
+ //
+ // NOTE: We could potentially widen loads based on their alignment if we are
+ // comfortable requiring that subsequent memory locations within the
+ // alignment-widened load are not volatile.
+ struct S {
+ char a;
+ unsigned b : 1;
+ char c;
+ };
+ unsigned read(S* s) {
+ // CHECK-X86-64: define i32 @_ZN2N14read
+ // CHECK-X86-64: %[[ptr:.*]] = getelementptr inbounds %{{.*}}* %{{.*}}, i32 0, i32 1
+ // CHECK-X86-64: %[[val:.*]] = load i8* %[[ptr]]
+ // CHECK-X86-64: %[[and:.*]] = and i8 %[[val]], 1
+ // CHECK-X86-64: %[[ext:.*]] = zext i8 %[[and]] to i32
+ // CHECK-X86-64: ret i32 %[[ext]]
+ // CHECK-PPC64: define zeroext i32 @_ZN2N14read
+ // CHECK-PPC64: %[[ptr:.*]] = getelementptr inbounds %{{.*}}* %{{.*}}, i32 0, i32 1
+ // CHECK-PPC64: %[[val:.*]] = load i8* %[[ptr]]
+ // CHECK-PPC64: %[[shr:.*]] = lshr i8 %[[val]], 7
+ // CHECK-PPC64: %[[ext:.*]] = zext i8 %[[shr]] to i32
+ // CHECK-PPC64: ret i32 %[[ext]]
+ return s->b;
+ }
+ void write(S* s, unsigned x) {
+ // CHECK-X86-64: define void @_ZN2N15write
+ // CHECK-X86-64: %[[ptr:.*]] = getelementptr inbounds %{{.*}}* %{{.*}}, i32 0, i32 1
+ // CHECK-X86-64: %[[x_trunc:.*]] = trunc i32 %{{.*}} to i8
+ // CHECK-X86-64: %[[old:.*]] = load i8* %[[ptr]]
+ // CHECK-X86-64: %[[x_and:.*]] = and i8 %[[x_trunc]], 1
+ // CHECK-X86-64: %[[old_and:.*]] = and i8 %[[old]], -2
+ // CHECK-X86-64: %[[new:.*]] = or i8 %[[old_and]], %[[x_and]]
+ // CHECK-X86-64: store i8 %[[new]], i8* %[[ptr]]
+ // CHECK-PPC64: define void @_ZN2N15write
+ // CHECK-PPC64: %[[ptr:.*]] = getelementptr inbounds %{{.*}}* %{{.*}}, i32 0, i32 1
+ // CHECK-PPC64: %[[x_trunc:.*]] = trunc i32 %{{.*}} to i8
+ // CHECK-PPC64: %[[old:.*]] = load i8* %[[ptr]]
+ // CHECK-PPC64: %[[x_and:.*]] = and i8 %[[x_trunc]], 1
+ // CHECK-PPC64: %[[x_shl:.*]] = shl i8 %[[x_and]], 7
+ // CHECK-PPC64: %[[old_and:.*]] = and i8 %[[old]], 127
+ // CHECK-PPC64: %[[new:.*]] = or i8 %[[old_and]], %[[x_shl]]
+ // CHECK-PPC64: store i8 %[[new]], i8* %[[ptr]]
+ s->b = x;
+ }
+}
+
+namespace N2 {
+ // Do widen loads and stores to bitfields when those bitfields have padding
+ // within the struct following them.
+ struct S {
+ unsigned b : 24;
+ void *p;
+ };
+ unsigned read(S* s) {
+ // CHECK-X86-64: define i32 @_ZN2N24read
+ // CHECK-X86-64: %[[ptr:.*]] = bitcast %{{.*}}* %{{.*}} to i32*
+ // CHECK-X86-64: %[[val:.*]] = load i32* %[[ptr]]
+ // CHECK-X86-64: %[[and:.*]] = and i32 %[[val]], 16777215
+ // CHECK-X86-64: ret i32 %[[and]]
+ // CHECK-PPC64: define zeroext i32 @_ZN2N24read
+ // CHECK-PPC64: %[[ptr:.*]] = bitcast %{{.*}}* %{{.*}} to i32*
+ // CHECK-PPC64: %[[val:.*]] = load i32* %[[ptr]]
+ // CHECK-PPC64: %[[shr:.*]] = lshr i32 %[[val]], 8
+ // CHECK-PPC64: ret i32 %[[shr]]
+ return s->b;
+ }
+ void write(S* s, unsigned x) {
+ // CHECK-X86-64: define void @_ZN2N25write
+ // CHECK-X86-64: %[[ptr:.*]] = bitcast %{{.*}}* %{{.*}} to i32*
+ // CHECK-X86-64: %[[old:.*]] = load i32* %[[ptr]]
+ // CHECK-X86-64: %[[x_and:.*]] = and i32 %{{.*}}, 16777215
+ // CHECK-X86-64: %[[old_and:.*]] = and i32 %[[old]], -16777216
+ // CHECK-X86-64: %[[new:.*]] = or i32 %[[old_and]], %[[x_and]]
+ // CHECK-X86-64: store i32 %[[new]], i32* %[[ptr]]
+ // CHECK-PPC64: define void @_ZN2N25write
+ // CHECK-PPC64: %[[ptr:.*]] = bitcast %{{.*}}* %{{.*}} to i32*
+ // CHECK-PPC64: %[[old:.*]] = load i32* %[[ptr]]
+ // CHECK-PPC64: %[[x_and:.*]] = and i32 %{{.*}}, 16777215
+ // CHECK-PPC64: %[[x_shl:.*]] = shl i32 %[[x_and]], 8
+ // CHECK-PPC64: %[[old_and:.*]] = and i32 %[[old]], 255
+ // CHECK-PPC64: %[[new:.*]] = or i32 %[[old_and]], %[[x_shl]]
+ // CHECK-PPC64: store i32 %[[new]], i32* %[[ptr]]
+ s->b = x;
+ }
+}
+
+namespace N3 {
+ // Do widen loads and stores to bitfields through the trailing padding at the
+ // end of a struct.
+ struct S {
+ unsigned b : 24;
+ };
+ unsigned read(S* s) {
+ // CHECK-X86-64: define i32 @_ZN2N34read
+ // CHECK-X86-64: %[[ptr:.*]] = bitcast %{{.*}}* %{{.*}} to i32*
+ // CHECK-X86-64: %[[val:.*]] = load i32* %[[ptr]]
+ // CHECK-X86-64: %[[and:.*]] = and i32 %[[val]], 16777215
+ // CHECK-X86-64: ret i32 %[[and]]
+ // CHECK-PPC64: define zeroext i32 @_ZN2N34read
+ // CHECK-PPC64: %[[ptr:.*]] = bitcast %{{.*}}* %{{.*}} to i32*
+ // CHECK-PPC64: %[[val:.*]] = load i32* %[[ptr]]
+ // CHECK-PPC64: %[[shr:.*]] = lshr i32 %[[val]], 8
+ // CHECK-PPC64: ret i32 %[[shr]]
+ return s->b;
+ }
+ void write(S* s, unsigned x) {
+ // CHECK-X86-64: define void @_ZN2N35write
+ // CHECK-X86-64: %[[ptr:.*]] = bitcast %{{.*}}* %{{.*}} to i32*
+ // CHECK-X86-64: %[[old:.*]] = load i32* %[[ptr]]
+ // CHECK-X86-64: %[[x_and:.*]] = and i32 %{{.*}}, 16777215
+ // CHECK-X86-64: %[[old_and:.*]] = and i32 %[[old]], -16777216
+ // CHECK-X86-64: %[[new:.*]] = or i32 %[[old_and]], %[[x_and]]
+ // CHECK-X86-64: store i32 %[[new]], i32* %[[ptr]]
+ // CHECK-PPC64: define void @_ZN2N35write
+ // CHECK-PPC64: %[[ptr:.*]] = bitcast %{{.*}}* %{{.*}} to i32*
+ // CHECK-PPC64: %[[old:.*]] = load i32* %[[ptr]]
+ // CHECK-PPC64: %[[x_and:.*]] = and i32 %{{.*}}, 16777215
+ // CHECK-PPC64: %[[x_shl:.*]] = shl i32 %[[x_and]], 8
+ // CHECK-PPC64: %[[old_and:.*]] = and i32 %[[old]], 255
+ // CHECK-PPC64: %[[new:.*]] = or i32 %[[old_and]], %[[x_shl]]
+ // CHECK-PPC64: store i32 %[[new]], i32* %[[ptr]]
+ s->b = x;
+ }
+}
+
+namespace N4 {
+ // Do NOT widen loads and stores to bitfields into padding at the end of
+ // a class which might end up with members inside of it when inside a derived
+ // class.
+ struct Base {
+ virtual ~Base() {}
+
+ unsigned b : 24;
+ };
+ // Imagine some other translation unit introduces:
+#if 0
+ struct Derived : public Base {
+ char c;
+ };
+#endif
+ unsigned read(Base* s) {
+ // FIXME: We should widen this load as long as the function isn't being
+ // instrumented by thread-sanitizer.
+ //
+ // CHECK-X86-64: define i32 @_ZN2N44read
+ // CHECK-X86-64: %[[gep:.*]] = getelementptr inbounds {{.*}}* %{{.*}}, i32 0, i32 1
+ // CHECK-X86-64: %[[ptr:.*]] = bitcast [3 x i8]* %[[gep]] to i24*
+ // CHECK-X86-64: %[[val:.*]] = load i24* %[[ptr]]
+ // CHECK-X86-64: %[[ext:.*]] = zext i24 %[[val]] to i32
+ // CHECK-X86-64: ret i32 %[[ext]]
+ // CHECK-PPC64: define zeroext i32 @_ZN2N44read
+ // CHECK-PPC64: %[[gep:.*]] = getelementptr inbounds {{.*}}* %{{.*}}, i32 0, i32 1
+ // CHECK-PPC64: %[[ptr:.*]] = bitcast [3 x i8]* %[[gep]] to i24*
+ // CHECK-PPC64: %[[val:.*]] = load i24* %[[ptr]]
+ // CHECK-PPC64: %[[ext:.*]] = zext i24 %[[val]] to i32
+ // CHECK-PPC64: ret i32 %[[ext]]
+ return s->b;
+ }
+ void write(Base* s, unsigned x) {
+ // CHECK-X86-64: define void @_ZN2N45write
+ // CHECK-X86-64: %[[gep:.*]] = getelementptr inbounds {{.*}}* %{{.*}}, i32 0, i32 1
+ // CHECK-X86-64: %[[ptr:.*]] = bitcast [3 x i8]* %[[gep]] to i24*
+ // CHECK-X86-64: %[[new:.*]] = trunc i32 %{{.*}} to i24
+ // CHECK-X86-64: store i24 %[[new]], i24* %[[ptr]]
+ // CHECK-PPC64: define void @_ZN2N45write
+ // CHECK-PPC64: %[[gep:.*]] = getelementptr inbounds {{.*}}* %{{.*}}, i32 0, i32 1
+ // CHECK-PPC64: %[[ptr:.*]] = bitcast [3 x i8]* %[[gep]] to i24*
+ // CHECK-PPC64: %[[new:.*]] = trunc i32 %{{.*}} to i24
+ // CHECK-PPC64: store i24 %[[new]], i24* %[[ptr]]
+ s->b = x;
+ }
+}
+
+namespace N5 {
+ // Widen through padding at the end of a struct even if that struct
+ // participates in a union with another struct which has a separate field in
+ // that location. The reasoning is that if the operation is storing to that
+ // member of the union, it must be the active member, and thus we can write
+ // through the padding. If it is a load, it might be a load of a common
+ // prefix through a non-active member, but in such a case the extra bits
+ // loaded are masked off anyways.
+ union U {
+ struct X { unsigned b : 24; char c; } x;
+ struct Y { unsigned b : 24; } y;
+ };
+ unsigned read(U* u) {
+ // CHECK-X86-64: define i32 @_ZN2N54read
+ // CHECK-X86-64: %[[ptr:.*]] = bitcast %{{.*}}* %{{.*}} to i32*
+ // CHECK-X86-64: %[[val:.*]] = load i32* %[[ptr]]
+ // CHECK-X86-64: %[[and:.*]] = and i32 %[[val]], 16777215
+ // CHECK-X86-64: ret i32 %[[and]]
+ // CHECK-PPC64: define zeroext i32 @_ZN2N54read
+ // CHECK-PPC64: %[[ptr:.*]] = bitcast %{{.*}}* %{{.*}} to i32*
+ // CHECK-PPC64: %[[val:.*]] = load i32* %[[ptr]]
+ // CHECK-PPC64: %[[shr:.*]] = lshr i32 %[[val]], 8
+ // CHECK-PPC64: ret i32 %[[shr]]
+ return u->y.b;
+ }
+ void write(U* u, unsigned x) {
+ // CHECK-X86-64: define void @_ZN2N55write
+ // CHECK-X86-64: %[[ptr:.*]] = bitcast %{{.*}}* %{{.*}} to i32*
+ // CHECK-X86-64: %[[old:.*]] = load i32* %[[ptr]]
+ // CHECK-X86-64: %[[x_and:.*]] = and i32 %{{.*}}, 16777215
+ // CHECK-X86-64: %[[old_and:.*]] = and i32 %[[old]], -16777216
+ // CHECK-X86-64: %[[new:.*]] = or i32 %[[old_and]], %[[x_and]]
+ // CHECK-X86-64: store i32 %[[new]], i32* %[[ptr]]
+ // CHECK-PPC64: define void @_ZN2N55write
+ // CHECK-PPC64: %[[ptr:.*]] = bitcast %{{.*}}* %{{.*}} to i32*
+ // CHECK-PPC64: %[[old:.*]] = load i32* %[[ptr]]
+ // CHECK-PPC64: %[[x_and:.*]] = and i32 %{{.*}}, 16777215
+ // CHECK-PPC64: %[[x_shl:.*]] = shl i32 %[[x_and]], 8
+ // CHECK-PPC64: %[[old_and:.*]] = and i32 %[[old]], 255
+ // CHECK-PPC64: %[[new:.*]] = or i32 %[[old_and]], %[[x_shl]]
+ // CHECK-PPC64: store i32 %[[new]], i32* %[[ptr]]
+ u->y.b = x;
+ }
+}
+
+namespace N6 {
+ // Zero-length bitfields partition the memory locations of bitfields for the
+ // purposes of the memory model. That means stores must not span zero-length
+ // bitfields and loads may only span them when we are not instrumenting with
+ // thread sanitizer.
+ // FIXME: We currently don't widen loads even without thread sanitizer, even
+ // though we could.
+ struct S {
+ unsigned b1 : 24;
+ unsigned char : 0;
+ unsigned char b2 : 8;
+ };
+ unsigned read(S* s) {
+ // CHECK-X86-64: define i32 @_ZN2N64read
+ // CHECK-X86-64: %[[ptr1:.*]] = bitcast {{.*}}* %{{.*}} to i24*
+ // CHECK-X86-64: %[[val1:.*]] = load i24* %[[ptr1]]
+ // CHECK-X86-64: %[[ext1:.*]] = zext i24 %[[val1]] to i32
+ // CHECK-X86-64: %[[ptr2:.*]] = getelementptr inbounds {{.*}}* %{{.*}}, i32 0, i32 1
+ // CHECK-X86-64: %[[val2:.*]] = load i8* %[[ptr2]]
+ // CHECK-X86-64: %[[ext2:.*]] = zext i8 %[[val2]] to i32
+ // CHECK-X86-64: %[[add:.*]] = add nsw i32 %[[ext1]], %[[ext2]]
+ // CHECK-X86-64: ret i32 %[[add]]
+ // CHECK-PPC64: define zeroext i32 @_ZN2N64read
+ // CHECK-PPC64: %[[ptr1:.*]] = bitcast {{.*}}* %{{.*}} to i24*
+ // CHECK-PPC64: %[[val1:.*]] = load i24* %[[ptr1]]
+ // CHECK-PPC64: %[[ext1:.*]] = zext i24 %[[val1]] to i32
+ // CHECK-PPC64: %[[ptr2:.*]] = getelementptr inbounds {{.*}}* %{{.*}}, i32 0, i32 1
+ // CHECK-PPC64: %[[val2:.*]] = load i8* %[[ptr2]]
+ // CHECK-PPC64: %[[ext2:.*]] = zext i8 %[[val2]] to i32
+ // CHECK-PPC64: %[[add:.*]] = add nsw i32 %[[ext1]], %[[ext2]]
+ // CHECK-PPC64: ret i32 %[[add]]
+ return s->b1 + s->b2;
+ }
+ void write(S* s, unsigned x) {
+ // CHECK-X86-64: define void @_ZN2N65write
+ // CHECK-X86-64: %[[ptr1:.*]] = bitcast {{.*}}* %{{.*}} to i24*
+ // CHECK-X86-64: %[[new1:.*]] = trunc i32 %{{.*}} to i24
+ // CHECK-X86-64: store i24 %[[new1]], i24* %[[ptr1]]
+ // CHECK-X86-64: %[[new2:.*]] = trunc i32 %{{.*}} to i8
+ // CHECK-X86-64: %[[ptr2:.*]] = getelementptr inbounds {{.*}}* %{{.*}}, i32 0, i32 1
+ // CHECK-X86-64: store i8 %[[new2]], i8* %[[ptr2]]
+ // CHECK-PPC64: define void @_ZN2N65write
+ // CHECK-PPC64: %[[ptr1:.*]] = bitcast {{.*}}* %{{.*}} to i24*
+ // CHECK-PPC64: %[[new1:.*]] = trunc i32 %{{.*}} to i24
+ // CHECK-PPC64: store i24 %[[new1]], i24* %[[ptr1]]
+ // CHECK-PPC64: %[[new2:.*]] = trunc i32 %{{.*}} to i8
+ // CHECK-PPC64: %[[ptr2:.*]] = getelementptr inbounds {{.*}}* %{{.*}}, i32 0, i32 1
+ // CHECK-PPC64: store i8 %[[new2]], i8* %[[ptr2]]
+ s->b1 = x;
+ s->b2 = x;
+ }
+}
diff --git a/test/CodeGenCXX/blocks-cxx11.cpp b/test/CodeGenCXX/blocks-cxx11.cpp
index 996db1a..3f0380a 100644
--- a/test/CodeGenCXX/blocks-cxx11.cpp
+++ b/test/CodeGenCXX/blocks-cxx11.cpp
@@ -82,3 +82,33 @@ namespace test_complex_int_ref_mutable {
}
}
+// rdar://13295759
+namespace test_block_in_lambda {
+ void takeBlock(void (^block)());
+
+ // The captured variable has to be non-POD so that we have a copy expression.
+ struct A {
+ void *p;
+ A(const A &);
+ ~A();
+ void use() const;
+ };
+
+ void test(A a) {
+ auto lambda = [a]() {
+ takeBlock(^{ a.use(); });
+ };
+ lambda(); // make sure we emit the invocation function
+ }
+ // CHECK: define internal void @"_ZZN20test_block_in_lambda4testENS_1AEENK3$_0clEv"(
+ // CHECK: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]], align 8
+ // CHECK: [[THIS:%.*]] = load [[LAMBDA_T:%.*]]**
+ // CHECK: [[TO_DESTROY:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
+ // CHECK: [[T0:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
+ // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[LAMBDA_T]]* [[THIS]], i32 0, i32 0
+ // CHECK-NEXT: call void @_ZN20test_block_in_lambda1AC1ERKS0_({{.*}}* [[T0]], {{.*}}* [[T1]])
+ // CHECK-NEXT: [[T0:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to void ()*
+ // CHECK-NEXT: call void @_ZN20test_block_in_lambda9takeBlockEU13block_pointerFvvE(void ()* [[T0]])
+ // CHECK-NEXT: call void @_ZN20test_block_in_lambda1AD1Ev({{.*}}* [[TO_DESTROY]])
+ // CHECK-NEXT: ret void
+}
diff --git a/test/CodeGenCXX/blocks.cpp b/test/CodeGenCXX/blocks.cpp
index 1500c0d..81eef0e 100644
--- a/test/CodeGenCXX/blocks.cpp
+++ b/test/CodeGenCXX/blocks.cpp
@@ -120,9 +120,11 @@ namespace test4 {
}
// CHECK: define void @_ZN5test44testEv()
// CHECK: define internal void @___ZN5test44testEv_block_invoke
- // CHECK: [[TMP:%.*]] = alloca [[A:%.*]], align 1
- // CHECK-NEXT: bitcast i8*
- // CHECK-NEXT: call void @_ZN5test41AC1Ev([[A]]* [[TMP]])
+ // CHECK: [[TMP:%.*]] = alloca [[A:%.*]], align 1
+ // CHECK-NEXT: store i8* [[BLOCKDESC:%.*]], i8** {{.*}}, align 8
+ // CHECK-NEXT: load i8*
+ // CHECK-NEXT: bitcast i8* [[BLOCKDESC]] to <{ i8*, i32, i32, i8*, %struct.__block_descriptor* }>*
+ // CHECK: call void @_ZN5test41AC1Ev([[A]]* [[TMP]])
// CHECK-NEXT: call void @_ZN5test43fooENS_1AE([[A]]* [[TMP]])
// CHECK-NEXT: call void @_ZN5test41AD1Ev([[A]]* [[TMP]])
// CHECK-NEXT: ret void
@@ -226,3 +228,28 @@ namespace test8 {
template int X::foo<int>();
}
+
+// rdar://13459289
+namespace test9 {
+ struct B {
+ void *p;
+ B();
+ B(const B&);
+ ~B();
+ };
+
+ void use_block(void (^)());
+ void use_block_2(void (^)(), const B &a);
+
+ // Ensuring that creating a non-trivial capture copy expression
+ // doesn't end up stealing the block registration for the block we
+ // just parsed. That block must have captures or else it won't
+ // force registration. Must occur within a block for some reason.
+ void test() {
+ B x;
+ use_block(^{
+ int y;
+ use_block_2(^{ (void)y; }, x);
+ });
+ }
+}
diff --git a/test/CodeGenCXX/bool-bitfield.cpp b/test/CodeGenCXX/bool-bitfield.cpp
new file mode 100644
index 0000000..06bdf2b
--- /dev/null
+++ b/test/CodeGenCXX/bool-bitfield.cpp
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -verify -emit-llvm -o - %s \
+// RUN: | FileCheck %s
+
+// PR14638; make sure this doesn't crash.
+struct A {
+ bool m_sorted : 1;
+};
+void func1(bool b, A& a1)
+{
+ if ((a1.m_sorted = b)) {}
+}
+// CHECK: define void @_Z5func1bR1A
+// CHECK: br i1
+// CHECK: ret void
diff --git a/test/CodeGenCXX/builtins.cpp b/test/CodeGenCXX/builtins.cpp
index 0629c31..c9b0bff 100644
--- a/test/CodeGenCXX/builtins.cpp
+++ b/test/CodeGenCXX/builtins.cpp
@@ -4,6 +4,6 @@
extern "C" char memmove();
int main() {
- // CHECK: call signext i8 @memmove()
+ // CHECK: call {{signext i8|i8}} @memmove()
return memmove();
}
diff --git a/test/CodeGenCXX/c-linkage.cpp b/test/CodeGenCXX/c-linkage.cpp
index b1f07b7..f6e64d9 100644
--- a/test/CodeGenCXX/c-linkage.cpp
+++ b/test/CodeGenCXX/c-linkage.cpp
@@ -11,3 +11,23 @@ extern "C" {
}
// CHECK: define void @_ZN1N1X1fEv
+
+extern "C" {
+ static void test2_f() {
+ }
+ // CHECK: define internal void @_Z7test2_fv
+ static void test2_f(int x) {
+ }
+ // CHECK: define internal void @_Z7test2_fi
+ void test2_use() {
+ test2_f();
+ test2_f(42);
+ }
+}
+
+extern "C" {
+ struct test3_s {
+ };
+ bool operator==(const int& a, const test3_s& b) {
+ }
+}
diff --git a/test/CodeGenCXX/catch-undef-behavior.cpp b/test/CodeGenCXX/catch-undef-behavior.cpp
index fd9e3d7..d6d0edfa 100644
--- a/test/CodeGenCXX/catch-undef-behavior.cpp
+++ b/test/CodeGenCXX/catch-undef-behavior.cpp
@@ -1,7 +1,15 @@
-// RUN: %clang_cc1 -fsanitize=signed-integer-overflow,divide-by-zero,shift,unreachable,return,vla-bound,alignment,null,vptr,object-size,float-cast-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s
+// RUN: %clang_cc1 -fsanitize=signed-integer-overflow,integer-divide-by-zero,float-divide-by-zero,shift,unreachable,return,vla-bound,alignment,null,vptr,object-size,float-cast-overflow,bool,enum,bounds -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s
+
+struct S {
+ double d;
+ int a, b;
+ virtual int f();
+};
+
+struct T : S {};
// CHECK: @_Z17reference_binding
-void reference_binding(int *p) {
+void reference_binding(int *p, S *q) {
// C++ core issue 453: If an lvalue to which a reference is directly bound
// designates neither an existing object or function of an appropriate type,
// nor a region of storage of suitable size and alignment to contain an object
@@ -16,13 +24,11 @@ void reference_binding(int *p) {
// CHECK-NEXT: %[[MISALIGN:.*]] = and i64 %[[PTRINT]], 3
// CHECK-NEXT: icmp eq i64 %[[MISALIGN]], 0
int &r = *p;
-}
-struct S {
- double d;
- int a, b;
- virtual int f();
-};
+ // A reference is not required to refer to an object within its lifetime.
+ // CHECK-NOT: __ubsan_handle_dynamic_type_cache_miss
+ S &r2 = *q;
+}
// CHECK: @_Z13member_access
void member_access(S *p) {
@@ -70,6 +76,8 @@ void member_access(S *p) {
// CHECK-NEXT: br i1
// CHECK: call void @__ubsan_handle_dynamic_type_cache_miss({{.*}}, i64 %{{.*}}, i64 %[[HASH]])
+ // CHECK-NOT: unreachable
+ // CHECK: {{.*}}:
// (2) Check 'p->b' is appropriately sized and aligned for a load.
@@ -103,6 +111,8 @@ void member_access(S *p) {
// CHECK: getelementptr inbounds [128 x i64]* @__ubsan_vptr_type_cache, i32 0, i64 %
// CHECK: br i1
// CHECK: call void @__ubsan_handle_dynamic_type_cache_miss({{.*}}, i64 %{{.*}}, i64 %{{.*}})
+ // CHECK-NOT: unreachable
+ // CHECK: {{.*}}:
k = p->f();
}
@@ -120,7 +130,12 @@ int lsh_overflow(int a, int b) {
// CHECK-NEXT: %[[SHIFTED_OUT_NOT_SIGN:.*]] = lshr i32 %[[SHIFTED_OUT]], 1
// CHECK-NEXT: %[[NO_OVERFLOW:.*]] = icmp eq i32 %[[SHIFTED_OUT_NOT_SIGN]], 0
- // CHECK-NEXT: br i1 %[[NO_OVERFLOW]]
+
+ // CHECK: %[[VALID:.*]] = phi i1 [ %[[INBOUNDS]], {{.*}} ], [ %[[NO_OVERFLOW]], {{.*}} ]
+ // CHECK-NEXT: br i1 %[[VALID]]
+
+ // CHECK: call void @__ubsan_handle_shift_out_of_bounds
+ // CHECK-NOT: call void @__ubsan_handle_shift_out_of_bounds
// CHECK: %[[RET:.*]] = shl i32 %[[LHS]], %[[RHS]]
// CHECK-NEXT: ret i32 %[[RET]]
@@ -129,6 +144,181 @@ int lsh_overflow(int a, int b) {
// CHECK: @_Z9no_return
int no_return() {
- // CHECK: call void @__ubsan_handle_missing_return(i8* bitcast ({{.*}}* @{{.*}} to i8*)) noreturn nounwind
+ // CHECK: call void @__ubsan_handle_missing_return(i8* bitcast ({{.*}}* @{{.*}} to i8*)) [[NR_NUW:#[0-9]+]]
// CHECK-NEXT: unreachable
}
+
+// CHECK: @_Z9sour_bool
+bool sour_bool(bool *p) {
+ // CHECK: %[[OK:.*]] = icmp ule i8 {{.*}}, 1
+ // CHECK: br i1 %[[OK]]
+ // CHECK: call void @__ubsan_handle_load_invalid_value(i8* bitcast ({{.*}}), i64 {{.*}})
+ return *p;
+}
+
+enum E1 { e1a = 0, e1b = 127 } e1;
+enum E2 { e2a = -1, e2b = 64 } e2;
+enum E3 { e3a = (1u << 31) - 1 } e3;
+
+// CHECK: @_Z14bad_enum_value
+int bad_enum_value() {
+ // CHECK: %[[E1:.*]] = icmp ule i32 {{.*}}, 127
+ // CHECK: br i1 %[[E1]]
+ // CHECK: call void @__ubsan_handle_load_invalid_value(
+ int a = e1;
+
+ // CHECK: %[[E2HI:.*]] = icmp sle i32 {{.*}}, 127
+ // CHECK: %[[E2LO:.*]] = icmp sge i32 {{.*}}, -128
+ // CHECK: %[[E2:.*]] = and i1 %[[E2HI]], %[[E2LO]]
+ // CHECK: br i1 %[[E2]]
+ // CHECK: call void @__ubsan_handle_load_invalid_value(
+ int b = e2;
+
+ // CHECK: %[[E3:.*]] = icmp ule i32 {{.*}}, 2147483647
+ // CHECK: br i1 %[[E3]]
+ // CHECK: call void @__ubsan_handle_load_invalid_value(
+ int c = e3;
+ return a + b + c;
+}
+
+// CHECK: @_Z20bad_downcast_pointer
+void bad_downcast_pointer(S *p) {
+ // CHECK: %[[NONNULL:.*]] = icmp ne {{.*}}, null
+ // CHECK: br i1 %[[NONNULL]],
+
+ // CHECK: %[[SIZE:.*]] = call i64 @llvm.objectsize.i64(
+ // CHECK: %[[E1:.*]] = icmp uge i64 %[[SIZE]], 24
+ // CHECK: %[[MISALIGN:.*]] = and i64 %{{.*}}, 7
+ // CHECK: %[[E2:.*]] = icmp eq i64 %[[MISALIGN]], 0
+ // CHECK: %[[E12:.*]] = and i1 %[[E1]], %[[E2]]
+ // CHECK: br i1 %[[E12]],
+
+ // CHECK: call void @__ubsan_handle_type_mismatch
+ // CHECK: br label
+
+ // CHECK: br i1 %{{.*}},
+
+ // CHECK: call void @__ubsan_handle_dynamic_type_cache_miss
+ // CHECK: br label
+ (void) static_cast<T*>(p);
+}
+
+// CHECK: @_Z22bad_downcast_reference
+void bad_downcast_reference(S &p) {
+ // CHECK: %[[E1:.*]] = icmp ne {{.*}}, null
+ // CHECK-NOT: br i1
+ // CHECK: %[[SIZE:.*]] = call i64 @llvm.objectsize.i64(
+ // CHECK: %[[E2:.*]] = icmp uge i64 %[[SIZE]], 24
+ // CHECK: %[[E12:.*]] = and i1 %[[E1]], %[[E2]]
+ // CHECK: %[[MISALIGN:.*]] = and i64 %{{.*}}, 7
+ // CHECK: %[[E3:.*]] = icmp eq i64 %[[MISALIGN]], 0
+ // CHECK: %[[E123:.*]] = and i1 %[[E12]], %[[E3]]
+ // CHECK: br i1 %[[E123]],
+
+ // CHECK: call void @__ubsan_handle_type_mismatch
+ // CHECK: br label
+
+ // CHECK: br i1 %{{.*}},
+
+ // CHECK: call void @__ubsan_handle_dynamic_type_cache_miss
+ // CHECK: br label
+ (void) static_cast<T&>(p);
+}
+
+// CHECK: @_Z11array_index
+int array_index(const int (&a)[4], int n) {
+ // CHECK: %[[K1_OK:.*]] = icmp ult i64 %{{.*}}, 4
+ // CHECK: br i1 %[[K1_OK]]
+ // CHECK: call void @__ubsan_handle_out_of_bounds(
+ int k1 = a[n];
+
+ // CHECK: %[[R1_OK:.*]] = icmp ule i64 %{{.*}}, 4
+ // CHECK: br i1 %[[R1_OK]]
+ // CHECK: call void @__ubsan_handle_out_of_bounds(
+ const int *r1 = &a[n];
+
+ // CHECK: %[[K2_OK:.*]] = icmp ult i64 %{{.*}}, 8
+ // CHECK: br i1 %[[K2_OK]]
+ // CHECK: call void @__ubsan_handle_out_of_bounds(
+ int k2 = ((const int(&)[8])a)[n];
+
+ // CHECK: %[[K3_OK:.*]] = icmp ult i64 %{{.*}}, 4
+ // CHECK: br i1 %[[K3_OK]]
+ // CHECK: call void @__ubsan_handle_out_of_bounds(
+ int k3 = n[a];
+
+ return k1 + *r1 + k2;
+}
+
+// CHECK: @_Z17multi_array_index
+int multi_array_index(int n, int m) {
+ int arr[4][6];
+
+ // CHECK: %[[IDX2_OK:.*]] = icmp ult i64 %{{.*}}, 6
+ // CHECK: br i1 %[[IDX2_OK]]
+ // CHECK: call void @__ubsan_handle_out_of_bounds(
+
+ // CHECK: %[[IDX1_OK:.*]] = icmp ult i64 %{{.*}}, 4
+ // CHECK: br i1 %[[IDX1_OK]]
+ // CHECK: call void @__ubsan_handle_out_of_bounds(
+ return arr[n][m];
+}
+
+// CHECK: @_Z11array_arith
+int array_arith(const int (&a)[4], int n) {
+ // CHECK: %[[K1_OK:.*]] = icmp ule i64 %{{.*}}, 4
+ // CHECK: br i1 %[[K1_OK]]
+ // CHECK: call void @__ubsan_handle_out_of_bounds(
+ const int *k1 = a + n;
+
+ // CHECK: %[[K2_OK:.*]] = icmp ule i64 %{{.*}}, 8
+ // CHECK: br i1 %[[K2_OK]]
+ // CHECK: call void @__ubsan_handle_out_of_bounds(
+ const int *k2 = (const int(&)[8])a + n;
+
+ return *k1 + *k2;
+}
+
+struct ArrayMembers {
+ int a1[5];
+ int a2[1];
+};
+// CHECK: @_Z18struct_array_index
+int struct_array_index(ArrayMembers *p, int n) {
+ // CHECK: %[[IDX_OK:.*]] = icmp ult i64 %{{.*}}, 5
+ // CHECK: br i1 %[[IDX_OK]]
+ // CHECK: call void @__ubsan_handle_out_of_bounds(
+ return p->a1[n];
+}
+
+// CHECK: @_Z16flex_array_index
+int flex_array_index(ArrayMembers *p, int n) {
+ // CHECK-NOT: call void @__ubsan_handle_out_of_bounds(
+ return p->a2[n];
+}
+
+extern int incomplete[];
+// CHECK: @_Z22incomplete_array_index
+int incomplete_array_index(int n) {
+ // CHECK-NOT: call void @__ubsan_handle_out_of_bounds(
+ return incomplete[n];
+}
+
+typedef __attribute__((ext_vector_type(4))) int V4I;
+// CHECK: @_Z12vector_index
+int vector_index(V4I v, int n) {
+ // CHECK: %[[IDX_OK:.*]] = icmp ult i64 %{{.*}}, 4
+ // CHECK: br i1 %[[IDX_OK]]
+ // CHECK: call void @__ubsan_handle_out_of_bounds(
+ return v[n];
+}
+
+// CHECK: @_Z12string_index
+char string_index(int n) {
+ // CHECK: %[[IDX_OK:.*]] = icmp ult i64 %{{.*}}, 6
+ // CHECK: br i1 %[[IDX_OK]]
+ // CHECK: call void @__ubsan_handle_out_of_bounds(
+ return "Hello"[n];
+}
+
+// CHECK: attributes [[NR_NUW]] = { noreturn nounwind }
diff --git a/test/CodeGenCXX/constructor-alias.cpp b/test/CodeGenCXX/constructor-alias.cpp
new file mode 100644
index 0000000..18a4777
--- /dev/null
+++ b/test/CodeGenCXX/constructor-alias.cpp
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -emit-llvm -triple mipsel--linux-gnu -mconstructor-aliases -o - %s | FileCheck %s
+
+// The target attribute code used to get confused with aliases. Make sure
+// we don't crash when an alias is used.
+
+struct B {
+ B();
+};
+B::B() {
+}
+
+// CHECK: @_ZN1BC1Ev = alias void (%struct.B*)* @_ZN1BC2Ev
diff --git a/test/CodeGenCXX/constructor-destructor-return-this.cpp b/test/CodeGenCXX/constructor-destructor-return-this.cpp
new file mode 100644
index 0000000..1ff922d
--- /dev/null
+++ b/test/CodeGenCXX/constructor-destructor-return-this.cpp
@@ -0,0 +1,60 @@
+//RUN: %clang_cc1 %s -emit-llvm -o - -triple=thumbv7-apple-ios3.0 -target-abi apcs-gnu | FileCheck %s
+
+// For constructors/desctructors that return 'this', if there exists a callsite
+// that returns 'this' and is immediately before the return instruction, make
+// sure we are using the return value from the callsite.
+// rdar://12818789
+
+// CHECK: define linkonce_odr [[A:%.*]] @_ZN11ObjectCacheC1Ev([[A]] %this) unnamed_addr
+// CHECK: [[THIS1:%.*]] = call [[A]] @_ZN11ObjectCacheC2Ev(
+// CHECK-NEXT: ret [[A]] [[THIS1]]
+
+// CHECK: define linkonce_odr [[A:%.*]] @_ZN5TimerI11ObjectCacheEC1EPS0_MS0_FvPS1_E([[A]] %this
+// CHECK: [[THIS1:%.*]] = call [[A]] @_ZN5TimerI11ObjectCacheEC2EPS0_MS0_FvPS1_E(
+// CHECK-NEXT: ret [[A]] [[THIS1]]
+
+// CHECK: define linkonce_odr [[A:%.*]] @_ZN5TimerI11ObjectCacheED1Ev([[A]] %this) unnamed_addr
+// CHECK: [[THIS1:%.*]] = call [[A]] @_ZN5TimerI11ObjectCacheED2Ev(
+// CHECK-NEXT: ret [[A]] [[THIS1]]
+
+// CHECK: define linkonce_odr [[A:%.*]] @_ZN5TimerI11ObjectCacheED2Ev([[A]] %this) unnamed_addr
+// CHECK: [[THIS1:%.*]] = call [[B:%.*]] @_ZN9TimerBaseD2Ev(
+// CHECK-NEXT: [[THIS2:%.*]] = bitcast [[B]] [[THIS1]] to [[A]]
+// CHECK-NEXT: ret [[A]] [[THIS2]]
+
+class TimerBase {
+public:
+ TimerBase();
+ virtual ~TimerBase();
+};
+
+template <typename TimerFiredClass> class Timer : public TimerBase {
+public:
+ typedef void (TimerFiredClass::*TimerFiredFunction)(Timer*);
+
+ Timer(TimerFiredClass* o, TimerFiredFunction f)
+ : m_object(o), m_function(f) { }
+
+private:
+ virtual void fired() { (m_object->*m_function)(this); }
+
+ TimerFiredClass* m_object;
+ TimerFiredFunction m_function;
+};
+
+class ObjectCache {
+public:
+ explicit ObjectCache();
+ ~ObjectCache();
+
+private:
+ Timer<ObjectCache> m_notificationPostTimer;
+};
+
+inline ObjectCache::ObjectCache() : m_notificationPostTimer(this, 0) { }
+inline ObjectCache::~ObjectCache() { }
+
+ObjectCache *test() {
+ ObjectCache *dd = new ObjectCache();
+ return dd;
+}
diff --git a/test/CodeGenCXX/copy-assign-synthesis-1.cpp b/test/CodeGenCXX/copy-assign-synthesis-1.cpp
index 46d0483..5d09b54 100644
--- a/test/CodeGenCXX/copy-assign-synthesis-1.cpp
+++ b/test/CodeGenCXX/copy-assign-synthesis-1.cpp
@@ -96,14 +96,8 @@ int main() {
// CHECK-LP64: .globl __ZN1XaSERKS_
// CHECK-LP64: .weak_definition __ZN1XaSERKS_
// CHECK-LP64: __ZN1XaSERKS_:
-// CHECK-LP64: .globl __ZN1QaSERKS_
-// CHECK-LP64: .weak_definition __ZN1QaSERKS_
-// CHECK-LP64: __ZN1QaSERKS_:
// CHECK-LP32: .globl __ZN1XaSERKS_
// CHECK-LP32: .weak_definition __ZN1XaSERKS_
// CHECK-LP32: __ZN1XaSERKS_:
-// CHECK-LP32: .globl __ZN1QaSERKS_
-// CHECK-LP32: .weak_definition __ZN1QaSERKS_
-// CHECK-LP32: __ZN1QaSERKS_:
diff --git a/test/CodeGenCXX/coverage.cpp b/test/CodeGenCXX/coverage.cpp
new file mode 100644
index 0000000..1f1611b
--- /dev/null
+++ b/test/CodeGenCXX/coverage.cpp
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 %s -emit-llvm -o - -test-coverage -femit-coverage-notes | FileCheck %s
+
+extern "C" void test_name1() {}
+void test_name2() {}
+
+// CHECK: metadata !"test_name1", metadata !"test_name1", metadata !"",{{.*}}DW_TAG_subprogram
+// CHECK: metadata !"test_name2", metadata !"test_name2", metadata !"_Z10test_name2v",{{.*}}DW_TAG_subprogram
diff --git a/test/CodeGenCXX/cp-blocks-linetables.cpp b/test/CodeGenCXX/cp-blocks-linetables.cpp
new file mode 100644
index 0000000..d5dd46c
--- /dev/null
+++ b/test/CodeGenCXX/cp-blocks-linetables.cpp
@@ -0,0 +1,61 @@
+// RUN: %clang_cc1 -fblocks -g -emit-llvm %s -o - | FileCheck %s
+// Ensure that we generate a line table entry for the block cleanup.
+// CHECK: define {{.*}} @__main_block_invoke
+// CHECK: _NSConcreteStackBlock
+// CHECK: = bitcast {{.*}}, !dbg ![[L1:[0-9]+]]
+// CHECK-NOT: call {{.*}} @_Block_object_dispose{{.*}}, !dbg ![[L1]]
+// CHECK: ret
+
+void * _NSConcreteStackBlock;
+#ifdef __cplusplus
+extern "C" void exit(int);
+#else
+extern void exit(int);
+#endif
+
+enum numbers {
+ zero, one, two, three, four
+};
+
+typedef enum numbers (^myblock)(enum numbers);
+
+
+double test(myblock I) {
+ return I(three);
+}
+
+int main() {
+ __block enum numbers x = one;
+ __block enum numbers y = two;
+
+ /* Breakpoint for first Block function. */
+ myblock CL = ^(enum numbers z)
+ { enum numbers savex = x;
+ { __block enum numbers x = savex;
+ y = z;
+ if (y != three)
+ exit (6);
+ test (
+ /* Breakpoint for second Block function. */
+ ^ (enum numbers z) {
+ if (y != three) {
+ exit(1);
+ }
+ if (x != one)
+ exit(2);
+ x = z;
+ if (x != three)
+ exit(3);
+ if (y != three)
+ exit(4);
+ return (enum numbers) four;
+ });}
+ return x;
+ };
+
+ enum numbers res = (enum numbers)test(CL);
+
+ if (res != one)
+ exit (5);
+ return 0;
+}
diff --git a/test/CodeGenCXX/cxx0x-delegating-ctors.cpp b/test/CodeGenCXX/cxx0x-delegating-ctors.cpp
index 338159c..e909f03 100644
--- a/test/CodeGenCXX/cxx0x-delegating-ctors.cpp
+++ b/test/CodeGenCXX/cxx0x-delegating-ctors.cpp
@@ -29,12 +29,12 @@ delegator::delegator(bool)
// CHECK: define {{.*}} @_ZN9delegatorC1Ec
// CHECK: {{.*}} @_ZN9delegatorC1Eb
// CHECK: void @__cxa_throw
-// CHECK: void @_ZSt9terminatev
+// CHECK: void @__clang_call_terminate
// CHECK: {{.*}} @_ZN9delegatorD1Ev
// CHECK: define {{.*}} @_ZN9delegatorC2Ec
// CHECK: {{.*}} @_ZN9delegatorC2Eb
// CHECK: void @__cxa_throw
-// CHECK: void @_ZSt9terminatev
+// CHECK: void @__clang_call_terminate
// CHECK: {{.*}} @_ZN9delegatorD2Ev
delegator::delegator(char)
: delegator(true) {
@@ -65,3 +65,37 @@ namespace PR12890 {
}
// CHECK: define {{.*}} @_ZN7PR128901XC1Ei(%"class.PR12890::X"* %this, i32)
// CHECK: call void @llvm.memset.p0i8.{{i32|i64}}(i8* {{.*}}, i8 0, {{i32|i64}} 4, i32 4, i1 false)
+
+namespace PR14588 {
+ void other();
+
+ class Base {
+ public:
+ Base() { squawk(); }
+ virtual ~Base() {}
+
+ virtual void squawk() { other(); }
+ };
+
+
+ class Foo : public virtual Base {
+ public:
+ Foo();
+ Foo(const void * inVoid);
+ virtual ~Foo() {}
+
+ virtual void squawk() { other(); }
+ };
+
+ // CHECK: define void @_ZN7PR145883FooC1Ev(%"class.PR14588::Foo"*
+ // CHECK: call void @_ZN7PR145883FooC1EPKv(
+ // CHECK: invoke void @_ZN7PR145885otherEv()
+ // CHECK: call void @_ZN7PR145883FooD1Ev
+ // CHECK: resume
+
+ Foo::Foo() : Foo(__null) { other(); }
+ Foo::Foo(const void *inVoid) {
+ squawk();
+ }
+
+}
diff --git a/test/CodeGenCXX/cxx0x-initializer-array.cpp b/test/CodeGenCXX/cxx0x-initializer-array.cpp
index df68997..3144e94 100644
--- a/test/CodeGenCXX/cxx0x-initializer-array.cpp
+++ b/test/CodeGenCXX/cxx0x-initializer-array.cpp
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 -triple i386-unknown-unknown -std=c++11 -S -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple i386-unknown-unknown -std=c++11 -S -emit-llvm -o - %s -Wno-address-of-temporary | FileCheck %s
+
+// CHECK: @[[THREE_NULL_MEMPTRS:.*]] = private constant [3 x i32] [i32 -1, i32 -1, i32 -1]
struct A { int a[1]; };
typedef A x[];
@@ -7,4 +9,103 @@ int f() {
// CHECK: define i32 @_Z1fv
// CHECK: store i32 1
// (It's okay if the output changes here, as long as we don't crash.)
+ return 0;
+}
+
+namespace ValueInitArrayOfMemPtr {
+ struct S {};
+ typedef int (S::*p);
+ typedef p a[3];
+ void f(const a &);
+
+ struct Agg1 {
+ int n;
+ p x;
+ };
+
+ struct Agg2 {
+ int n;
+ a x;
+ };
+
+ struct S1 {
+ p x;
+ S1();
+ };
+
+ // CHECK: define void @_ZN22ValueInitArrayOfMemPtr1fEi
+ void f(int n) {
+ Agg1 a = { n };
+ // CHECK: store i32 -1,
+
+ Agg2 b = { n };
+ // CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* %{{.*}}, i8* bitcast ([3 x i32]* @[[THREE_NULL_MEMPTRS]] to i8*), i32 12, i32 4, i1 false)
+ }
+
+ // CHECK: define void @_ZN22ValueInitArrayOfMemPtr1gEv
+ void g() {
+ // CHECK: store i32 -1,
+ f(a{});
+ }
+}
+
+namespace array_dtor {
+ struct S { S(); ~S(); };
+ using T = S[3];
+ void f(const T &);
+ void f(T *);
+ // CHECK: define void @_ZN10array_dtor1gEv(
+ void g() {
+ // CHECK: %[[ARRAY:.*]] = alloca [3 x
+ // CHECK: br
+
+ // Construct loop.
+ // CHECK: call void @_ZN10array_dtor1SC1Ev(
+ // CHECK: br i1
+
+ // CHECK: call void @_ZN10array_dtor1fERA3_KNS_1SE(
+ // CHECK: br
+
+ // Destruct loop.
+ // CHECK: call void @_ZN10array_dtor1SD1Ev(
+ // CHECK: br i1
+ f(T{});
+
+ // CHECK: ret void
+ }
+ // CHECK: define void @_ZN10array_dtor1hEv(
+ void h() {
+ // CHECK: %[[ARRAY:.*]] = alloca [3 x
+ // CHECK: br
+
+ // CHECK: call void @_ZN10array_dtor1SC1Ev(
+ // CHECK: br i1
+ T &&t = T{};
+
+ // CHECK: call void @_ZN10array_dtor1fERA3_KNS_1SE(
+ // CHECK: br
+ f(t);
+
+ // CHECK: call void @_ZN10array_dtor1SD1Ev(
+ // CHECK: br i1
+
+ // CHECK: ret void
+ }
+ // CHECK: define void @_ZN10array_dtor1iEv(
+ void i() {
+ // CHECK: %[[ARRAY:.*]] = alloca [3 x
+ // CHECK: br
+
+ // CHECK: call void @_ZN10array_dtor1SC1Ev(
+ // CHECK: br i1
+
+ // CHECK: call void @_ZN10array_dtor1fEPA3_NS_1SE(
+ // CHECK: br
+
+ // CHECK: call void @_ZN10array_dtor1SD1Ev(
+ // CHECK: br i1
+ f(&T{});
+
+ // CHECK: ret void
+ }
}
diff --git a/test/CodeGenCXX/cxx11-exception-spec.cpp b/test/CodeGenCXX/cxx11-exception-spec.cpp
index 194b80c..49ca861 100644
--- a/test/CodeGenCXX/cxx11-exception-spec.cpp
+++ b/test/CodeGenCXX/cxx11-exception-spec.cpp
@@ -10,99 +10,99 @@ template<typename T> struct S {
static void g() noexcept(sizeof(T) == 4);
};
-// CHECK: define {{.*}} @_Z1fIsEvv() {
+// CHECK: define {{.*}} @_Z1fIsEvv() [[NONE:#[0-9]+]] {
template<> void f<short>() { h(); }
-// CHECK: define {{.*}} @_Z1fIA2_sEvv() nounwind {
+// CHECK: define {{.*}} @_Z1fIA2_sEvv() [[NUW:#[0-9]+]] {
template<> void f<short[2]>() noexcept { h(); }
// CHECK: define {{.*}} @_ZN1SIsE1fEv()
-// CHECK-NOT: nounwind
+// CHECK-NOT: [[NUW]]
template<> void S<short>::f() { h(); }
-// CHECK: define {{.*}} @_ZN1SIA2_sE1fEv() nounwind
+// CHECK: define {{.*}} @_ZN1SIA2_sE1fEv() [[NUW]]
template<> void S<short[2]>::f() noexcept { h(); }
-// CHECK: define {{.*}} @_Z1fIDsEvv() {
+// CHECK: define {{.*}} @_Z1fIDsEvv() [[NONE]] {
template void f<char16_t>();
-// CHECK: define {{.*}} @_Z1fIA2_DsEvv() nounwind {
+// CHECK: define {{.*}} @_Z1fIA2_DsEvv() [[NUW]] {
template void f<char16_t[2]>();
// CHECK: define {{.*}} @_ZN1SIDsE1fEv()
-// CHECK-NOT: nounwind
+// CHECK-NOT: [[NUW]]
template void S<char16_t>::f();
-// CHECK: define {{.*}} @_ZN1SIA2_DsE1fEv() nounwind
+// CHECK: define {{.*}} @_ZN1SIA2_DsE1fEv() [[NUW]]
template void S<char16_t[2]>::f();
void h() {
- // CHECK: define {{.*}} @_Z1fIiEvv() nounwind {
+ // CHECK: define {{.*}} @_Z1fIiEvv() [[NUW]] {
f<int>();
- // CHECK: define {{.*}} @_Z1fIA2_iEvv() {
+ // CHECK: define {{.*}} @_Z1fIA2_iEvv() [[NONE]] {
f<int[2]>();
- // CHECK: define {{.*}} @_ZN1SIiE1fEv() nounwind
+ // CHECK: define {{.*}} @_ZN1SIiE1fEv() [[NUW]]
S<int>::f();
// CHECK: define {{.*}} @_ZN1SIA2_iE1fEv()
- // CHECK-NOT: nounwind
+ // CHECK-NOT: [[NUW]]
S<int[2]>::f();
- // CHECK: define {{.*}} @_Z1fIfEvv() nounwind {
+ // CHECK: define {{.*}} @_Z1fIfEvv() [[NUW]] {
void (*f1)() = &f<float>;
- // CHECK: define {{.*}} @_Z1fIdEvv() {
+ // CHECK: define {{.*}} @_Z1fIdEvv() [[NONE]] {
void (*f2)() = &f<double>;
- // CHECK: define {{.*}} @_ZN1SIfE1fEv() nounwind
+ // CHECK: define {{.*}} @_ZN1SIfE1fEv() [[NUW]]
void (*f3)() = &S<float>::f;
// CHECK: define {{.*}} @_ZN1SIdE1fEv()
- // CHECK-NOT: nounwind
+ // CHECK-NOT: [[NUW]]
void (*f4)() = &S<double>::f;
- // CHECK: define {{.*}} @_Z1fIA4_cEvv() nounwind {
+ // CHECK: define {{.*}} @_Z1fIA4_cEvv() [[NUW]] {
(void)&f<char[4]>;
- // CHECK: define {{.*}} @_Z1fIcEvv() {
+ // CHECK: define {{.*}} @_Z1fIcEvv() [[NONE]] {
(void)&f<char>;
- // CHECK: define {{.*}} @_ZN1SIA4_cE1fEv() nounwind
+ // CHECK: define {{.*}} @_ZN1SIA4_cE1fEv() [[NUW]]
(void)&S<char[4]>::f;
// CHECK: define {{.*}} @_ZN1SIcE1fEv()
- // CHECK-NOT: nounwind
+ // CHECK-NOT: [[NUW]]
(void)&S<char>::f;
}
// CHECK: define {{.*}} @_Z1iv
void i() {
- // CHECK: declare {{.*}} @_Z1gIiEvv() nounwind
+ // CHECK: declare {{.*}} @_Z1gIiEvv() [[NUW]]
g<int>();
// CHECK: declare {{.*}} @_Z1gIA2_iEvv()
- // CHECK-NOT: nounwind
+ // CHECK-NOT: [[NUW]]
g<int[2]>();
- // CHECK: declare {{.*}} @_ZN1SIiE1gEv() nounwind
+ // CHECK: declare {{.*}} @_ZN1SIiE1gEv() [[NUW]]
S<int>::g();
// CHECK: declare {{.*}} @_ZN1SIA2_iE1gEv()
- // CHECK-NOT: nounwind
+ // CHECK-NOT: [[NUW]]
S<int[2]>::g();
- // CHECK: declare {{.*}} @_Z1gIfEvv() nounwind
+ // CHECK: declare {{.*}} @_Z1gIfEvv() [[NUW]]
void (*g1)() = &g<float>;
// CHECK: declare {{.*}} @_Z1gIdEvv()
- // CHECK-NOT: nounwind
+ // CHECK-NOT: [[NUW]]
void (*g2)() = &g<double>;
- // CHECK: declare {{.*}} @_ZN1SIfE1gEv() nounwind
+ // CHECK: declare {{.*}} @_ZN1SIfE1gEv() [[NUW]]
void (*g3)() = &S<float>::g;
// CHECK: declare {{.*}} @_ZN1SIdE1gEv()
- // CHECK-NOT: nounwind
+ // CHECK-NOT: [[NUW]]
void (*g4)() = &S<double>::g;
- // CHECK: declare {{.*}} @_Z1gIA4_cEvv() nounwind
+ // CHECK: declare {{.*}} @_Z1gIA4_cEvv() [[NUW]]
(void)&g<char[4]>;
// CHECK: declare {{.*}} @_Z1gIcEvv()
- // CHECK-NOT: nounwind
+ // CHECK-NOT: [[NUW]]
(void)&g<char>;
- // CHECK: declare {{.*}} @_ZN1SIA4_cE1gEv() nounwind
+ // CHECK: declare {{.*}} @_ZN1SIA4_cE1gEv() [[NUW]]
(void)&S<char[4]>::g;
// CHECK: declare {{.*}} @_ZN1SIcE1gEv()
- // CHECK-NOT: nounwind
+ // CHECK-NOT: [[NUW]]
(void)&S<char>::g;
}
@@ -113,8 +113,11 @@ template<typename T> struct Nested {
// CHECK: define {{.*}} @_Z1jv
void j() {
// CHECK: declare {{.*}} @_ZN6NestedIiE1fILb1EcEEvv(
- // CHECK-NOT: nounwind
+ // CHECK-NOT: [[NUW]]
Nested<int>().f<true, char>();
- // CHECK: declare {{.*}} @_ZN6NestedIlE1fILb0ElEEvv({{.*}}) nounwind
+ // CHECK: declare {{.*}} @_ZN6NestedIlE1fILb0ElEEvv({{.*}}) [[NUW]]
Nested<long>().f<false, long>();
}
+
+// CHECK: attributes [[NONE]] = { {{.*}} }
+// CHECK: attributes [[NUW]] = { nounwind{{.*}} }
diff --git a/test/CodeGenCXX/cxx11-noreturn.cpp b/test/CodeGenCXX/cxx11-noreturn.cpp
new file mode 100644
index 0000000..31c651d
--- /dev/null
+++ b/test/CodeGenCXX/cxx11-noreturn.cpp
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -emit-llvm -std=c++11 %s -o - | FileCheck %s
+
+int g();
+
+// CHECK: _Z1fv(){{.*}} [[NR:#[0-9]+]]
+[[noreturn]] int f() {
+ while (g()) {}
+}
+
+// CHECK: attributes [[NR]] = { noreturn nounwind{{.*}} }
diff --git a/test/CodeGenCXX/cxx11-trivial-initializer-struct.cpp b/test/CodeGenCXX/cxx11-trivial-initializer-struct.cpp
new file mode 100644
index 0000000..cded6da
--- /dev/null
+++ b/test/CodeGenCXX/cxx11-trivial-initializer-struct.cpp
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -std=c++11 -S -emit-llvm -o %t-c++11.ll %s -triple x86_64-apple-darwin10
+// RUN: FileCheck %s < %t-c++11.ll
+// RUN: %clang_cc1 -std=c++98 -S -emit-llvm -o %t.ll %s -triple x86_64-apple-darwin10
+// RUN: diff %t.ll %t-c++11.ll
+
+// rdar://12897704
+
+struct sAFSearchPos {
+ unsigned char *pos;
+ unsigned char count;
+};
+
+static volatile struct sAFSearchPos testPositions;
+// CHECK: @_ZL13testPositions = internal global %struct.sAFSearchPos zeroinitializer
+
+static volatile struct sAFSearchPos arrayPositions[100][10][5];
+// CHECK: @_ZL14arrayPositions = internal global [100 x [10 x [5 x %struct.sAFSearchPos]]] zeroinitializer
+
+int main() {
+ return testPositions.count + arrayPositions[10][4][3].count;
+}
diff --git a/test/CodeGenCXX/debug-info-artificial-arg.cpp b/test/CodeGenCXX/debug-info-artificial-arg.cpp
index ee93849..ff0f663 100644
--- a/test/CodeGenCXX/debug-info-artificial-arg.cpp
+++ b/test/CodeGenCXX/debug-info-artificial-arg.cpp
@@ -22,9 +22,8 @@ int main(int argc, char **argv) {
A reallyA (500);
}
-// FIXME: The numbers are truly awful.
-// CHECK: !16 = metadata !{i32 786447, i32 0, metadata !"", i32 0, i32 0, i64 64, i64 64, i64 0, i32 1088, metadata !17} ; [ DW_TAG_pointer_type ] [line 0, size 64, align 64, offset 0] [from A]
-// CHECK: !17 = metadata !{i32 {{.*}}, null, metadata !"A", metadata !6, i32 8, i64 128, i64 64, i32 0, i32 0, null, metadata !18, i32 0, metadata !17, null} ; [ DW_TAG_class_type ]
-// CHECK: metadata !17, metadata !"A", metadata !"A", metadata !"", metadata !6, i32 12, metadata !43, i1 false, i1 false, i32 0, i32 0, null, i32 256, i1 false, null, null, i32 0, metadata !45, i32 12} ; [ DW_TAG_subprogram ]
-// CHECK: metadata !"", i32 0, i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !44, i32 0, i32 0} ; [ DW_TAG_subroutine_type ]
-// CHECK: !44 = metadata !{null, metadata !16, metadata !9, metadata !32}
+// CHECK: ![[ARTARG:.*]] = {{.*}} ; [ DW_TAG_pointer_type ] [line 0, size 64, align 64, offset 0] [artificial] [from A]
+// CHECK: ![[CLASSTYPE:.*]] = {{.*}} ; [ DW_TAG_class_type ] [A]
+// CHECK: metadata ![[CLASSTYPE]], {{.*}} ; [ DW_TAG_subprogram ] [line 12] [A]
+// CHECK: metadata [[FUNCTYPE:![0-9]*]], i32 0, i32 0} ; [ DW_TAG_subroutine_type ]
+// CHECK: [[FUNCTYPE]] = metadata !{null, metadata ![[ARTARG]], metadata !{{.*}}, metadata !{{.*}}}
diff --git a/test/CodeGenCXX/debug-info-byval.cpp b/test/CodeGenCXX/debug-info-byval.cpp
index 56ffe13..e6317fc 100644
--- a/test/CodeGenCXX/debug-info-byval.cpp
+++ b/test/CodeGenCXX/debug-info-byval.cpp
@@ -23,7 +23,7 @@ void foo(EVT e);
EVT bar();
void get(int *i, unsigned dl, VAL v, VAL *p, unsigned n, EVT missing_arg) {
-//CHECK: .asciz "missing_arg"
+//CHECK: .{{asciz|string}} "missing_arg"
EVT e = bar();
if (dl == n)
foo(missing_arg);
diff --git a/test/CodeGenCXX/debug-info-char16.cpp b/test/CodeGenCXX/debug-info-char16.cpp
index 24216f9..06a05b3 100644
--- a/test/CodeGenCXX/debug-info-char16.cpp
+++ b/test/CodeGenCXX/debug-info-char16.cpp
@@ -3,4 +3,4 @@
// 16 is DW_ATE_UTF (0x10) encoding attribute.
char16_t char_a = u'h';
-// CHECK: !7 = metadata !{i32 {{.*}}, null, metadata !"char16_t", null, i32 0, i64 16, i64 16, i64 0, i32 0, i32 16} ; [ DW_TAG_base_type ]
+// CHECK: !{{.*}} = {{.*}} ; [ DW_TAG_base_type ] [char16_t]
diff --git a/test/CodeGenCXX/debug-info-class.cpp b/test/CodeGenCXX/debug-info-class.cpp
index 062227a..df24926 100644
--- a/test/CodeGenCXX/debug-info-class.cpp
+++ b/test/CodeGenCXX/debug-info-class.cpp
@@ -1,24 +1,48 @@
-// RUN: %clang -emit-llvm -g -S %s -o - | FileCheck %s
struct foo;
-void func(foo *f) { // CHECK: DW_TAG_structure_type
+void func(foo *f) {
}
class bar;
-void func(bar *f) { // CHECK: DW_TAG_class_type
+void func(bar *f) {
}
union baz;
-void func(baz *f) { // CHECK: DW_TAG_union_type
+void func(baz *f) {
}
-struct A { // CHECK: DW_TAG_structure_type
+
+class B {
+public:
+ virtual ~B();
+};
+struct A {
int one;
- static const int HdrSize = 52; // CHECK: HdrSize
+ static const int HdrSize = 52;
int two;
A() {
int x = 1;
}
};
-class B { // CHECK: DW_TAG_class_type
-};
-int main() {
- A a;
+
+
+int main(int argc, char **argv) {
B b;
+ if (argc) {
+ A a;
+ }
+ return 0;
}
+
+// RUN: %clang -target x86_64-unknown_unknown -emit-llvm -g -S %s -o - | FileCheck %s
+// RUN: %clang -target i686-cygwin -emit-llvm -g -S %s -o - | FileCheck %s
+// RUN: %clang -target armv7l-unknown-linux-gnueabihf -emit-llvm -g -S %s -o - | FileCheck %s
+
+// CHECK: invoke {{.+}} @_ZN1BD1Ev(%class.B* %b)
+// CHECK-NEXT: unwind label %{{.+}}, !dbg ![[EXCEPTLOC:.*]]
+// CHECK: store i32 0, i32* %{{.+}}, !dbg ![[RETLOC:.*]]
+// CHECK: DW_TAG_structure_type ] [foo]
+// CHECK: DW_TAG_class_type ] [bar]
+// CHECK: DW_TAG_union_type ] [baz]
+// CHECK: DW_TAG_structure_type ] [A]
+// CHECK: HdrSize
+// CHECK: DW_TAG_class_type ] [B]
+// CHECK: metadata !"_vptr$B", {{.*}}, i32 64, metadata !{{.*}}} ; [ DW_TAG_member ]
+// CHECK: ![[EXCEPTLOC]] = metadata !{i32 31,
+// CHECK: ![[RETLOC]] = metadata !{i32 30,
diff --git a/test/CodeGenCXX/debug-info-dup-fwd-decl.cpp b/test/CodeGenCXX/debug-info-dup-fwd-decl.cpp
index e67987b..04fe7a0 100644
--- a/test/CodeGenCXX/debug-info-dup-fwd-decl.cpp
+++ b/test/CodeGenCXX/debug-info-dup-fwd-decl.cpp
@@ -19,6 +19,6 @@ protected:
Test t;
-// CHECK: metadata !"", null, i32 0, i64 64, i64 64, i64 0, i32 0, metadata {{.*}} [ DW_TAG_pointer_type ]
-// CHECK: metadata !"data", metadata !6, i32 14, i64 32, i64 32, i32 0, i32 0
-// CHECK-NOT: metadata !"data", metadata {{.*}}, i32 14, i64 0, i64 0, i32 0, i32 4,
+// CHECK: ; [ DW_TAG_pointer_type ]
+// CHECK: ; [ DW_TAG_structure_type ] [data]
+// CHECK-NOT: ; [ DW_TAG_structure_type ] [data]
diff --git a/test/CodeGenCXX/debug-info-enum-class.cpp b/test/CodeGenCXX/debug-info-enum-class.cpp
index fd243ab..929327b 100644
--- a/test/CodeGenCXX/debug-info-enum-class.cpp
+++ b/test/CodeGenCXX/debug-info-enum-class.cpp
@@ -9,10 +9,10 @@ B b;
C c;
D d;
-// CHECK: metadata !{i32 {{.*}}, null, metadata !"A", metadata !4, i32 3, i64 32, i64 32, i32 0, i32 0, metadata !5, metadata !6, i32 0, i32 0} ; [ DW_TAG_enumeration_type ]
-// CHECK: metadata !{i32 {{.*}}, null, metadata !"B", metadata !4, i32 4, i64 64, i64 64, i32 0, i32 0, metadata !9, metadata !10, i32 0, i32 0} ; [ DW_TAG_enumeration_type ]
-// CHECK: metadata !{i32 {{.*}}, null, metadata !"C", metadata !4, i32 5, i64 32, i64 32, i32 0, i32 0, null, metadata !13, i32 0, i32 0} ; [ DW_TAG_enumeration_type ]
-// CHECK: metadata !{i32 {{.*}}, null, metadata !"D", metadata !4, i32 6, i64 16, i64 16, i32 0, i32 4, null, null, i32 0} ; [ DW_TAG_enumeration_type ]
+// CHECK: ; [ DW_TAG_enumeration_type ] [A] [line 3, size 32, align 32, offset 0] [from int]
+// CHECK: ; [ DW_TAG_enumeration_type ] [B] [line 4, size 64, align 64, offset 0] [from long unsigned int]
+// CHECK: ; [ DW_TAG_enumeration_type ] [C] [line 5, size 32, align 32, offset 0] [from ]
+// CHECK: ; [ DW_TAG_enumeration_type ] [D] [line 6, size 16, align 16, offset 0] [fwd] [from ]
namespace PR14029 {
// Make sure this doesn't crash/assert.
diff --git a/test/CodeGenCXX/debug-info-flex-member.cpp b/test/CodeGenCXX/debug-info-flex-member.cpp
index b6aa6da..11329aa 100644
--- a/test/CodeGenCXX/debug-info-flex-member.cpp
+++ b/test/CodeGenCXX/debug-info-flex-member.cpp
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 -emit-llvm -g -triple x86_64-apple-darwin %s -o - | FileCheck %s
-// CHECK: metadata !{i32 {{.*}}, i64 1, i64 0} ; [ DW_TAG_subrange_type ]
+// CHECK: metadata !{i32 {{.*}}, i64 0, i64 -1} ; [ DW_TAG_subrange_type ]
struct StructName {
int member[];
diff --git a/test/CodeGenCXX/debug-info-fwd-ref.cpp b/test/CodeGenCXX/debug-info-fwd-ref.cpp
index 9135032..c479506 100644
--- a/test/CodeGenCXX/debug-info-fwd-ref.cpp
+++ b/test/CodeGenCXX/debug-info-fwd-ref.cpp
@@ -18,8 +18,7 @@ int main(int argc, char** argv) {
// Make sure we have two DW_TAG_structure_types for baz and bar and no forward
// references.
-// CHECK: metadata !{i32 {{.*}}, null, metadata !"bar", metadata !6, i32 8, i64 128, i64 64, i32 0, i32 0, null, metadata !18, i32 0, null, null} ; [ DW_TAG_structure_type ]
-// CHECK: metadata !{i32 {{.*}}, null, metadata !"baz", metadata !6, i32 3, i64 32, i64 32, i32 0, i32 0, null, metadata !21, i32 0, null, null} ; [ DW_TAG_structure_type ]
-// CHECK-NOT: metadata !{i32 {{.*}}, null, metadata !"bar", metadata !6, i32 8, i64 0, i64 0, i32 0, i32 4, i32 0, null, i32 0, i32 0} ; [ DW_TAG_structure_type ]
-// CHECK-NOT: metadata !{i32 {{.*}}, null, metadata !"baz", metadata !6, i32 3, i64 0, i64 0, i32 0, i32 4, null, null, i32 0, null, null} ; [ DW_TAG_structure_type ]
-
+// CHECK-NOT: [fwd]
+// CHECK: [ DW_TAG_structure_type ] [bar]
+// CHECK: [ DW_TAG_structure_type ] [baz]
+// CHECK-NOT: [fwd]
diff --git a/test/CodeGenCXX/debug-info-method.cpp b/test/CodeGenCXX/debug-info-method.cpp
index cb022bc..3ee4d9b 100644
--- a/test/CodeGenCXX/debug-info-method.cpp
+++ b/test/CodeGenCXX/debug-info-method.cpp
@@ -1,6 +1,27 @@
-// RUN: %clang -fverbose-asm -g -S %s -o - | grep DW_ACCESS_protected
+// RUN: %clang_cc1 -emit-llvm -std=c++11 -g %s -o - | FileCheck %s
+// CHECK: ![[THISTYPE:[0-9]+]] = {{.*}} ; [ DW_TAG_pointer_type ] {{.*}} [artificial] [from A]
+// CHECK: metadata !"_ZN1A3fooEiS_3$_0", {{.*}} [protected]
+// CHECK: DW_TAG_ptr_to_member_type
+// CHECK: {{.*}}metadata ![[MEMFUNTYPE:[0-9]+]], metadata !{{.*}}} ; [ DW_TAG_ptr_to_member_type ] {{.*}} [from ]
+// CHECK: ![[MEMFUNTYPE]] = {{.*}}metadata ![[MEMFUNARGS:[0-9]+]], i32 0, i32 0} ; [ DW_TAG_subroutine_type ] {{.*}} [from ]
+// CHECK: ![[MEMFUNARGS]] = {{.*}}, metadata ![[THISTYPE]],
+// CHECK: ""{{.*}}DW_TAG_arg_variable
+// CHECK: ""{{.*}}DW_TAG_arg_variable
+// CHECK: ""{{.*}}DW_TAG_arg_variable
+union {
+ int a;
+ float b;
+} u;
+
class A {
protected:
- int foo();
+ void foo(int, A, decltype(u));
};
+
+void A::foo(int, A, decltype(u)) {
+}
+
A a;
+
+int A::*x = 0;
+int (A::*y)(int) = 0;
diff --git a/test/CodeGenCXX/debug-info-namespace.cpp b/test/CodeGenCXX/debug-info-namespace.cpp
index 27f5eae..262e996 100644
--- a/test/CodeGenCXX/debug-info-namespace.cpp
+++ b/test/CodeGenCXX/debug-info-namespace.cpp
@@ -1,12 +1,17 @@
-// RUN: %clang -g -S -fverbose-asm %s -o - | FileCheck %s
+// RUN: %clang -g -S -emit-llvm %s -o - | FileCheck %s
-// CHECK: TAG_namespace
namespace A {
- enum numbers {
- ZERO,
- ONE
- };
+#line 1 "foo.cpp"
+namespace B {
+int i;
}
+}
+
+// CHECK: [[FILE:![0-9]*]] {{.*}}debug-info-namespace.cpp"
+// CHECK: [[VAR:![0-9]*]] = {{.*}}, metadata [[NS:![0-9]*]], metadata !"i", {{.*}} ; [ DW_TAG_variable ] [i]
+// CHECK: [[NS]] = {{.*}}, metadata [[FILE2:![0-9]*]], metadata [[CTXT:![0-9]*]], {{.*}} ; [ DW_TAG_namespace ] [B] [line 1]
+// CHECK: [[CTXT]] = {{.*}}, metadata [[FILE]], null, {{.*}} ; [ DW_TAG_namespace ] [A] [line 3]
+// CHECK: [[FILE2]]} ; [ DW_TAG_file_type ] [{{.*}}foo.cpp]
-using namespace A;
-numbers n;
+// FIXME: It is confused on win32 to generate file entry when dosish filename is given.
+// REQUIRES: shell
diff --git a/test/CodeGenCXX/debug-info-nullptr.cpp b/test/CodeGenCXX/debug-info-nullptr.cpp
index 4cc7e54..42e9741 100644
--- a/test/CodeGenCXX/debug-info-nullptr.cpp
+++ b/test/CodeGenCXX/debug-info-nullptr.cpp
@@ -4,4 +4,4 @@ void foo() {
decltype(nullptr) t = 0;
}
-// CHECK: metadata !{i32 {{.*}}, null, metadata !"nullptr_t", null, i32 0, i64 0, i64 0, i64 0, i32 0, i32 0} ; [ DW_TAG_unspecified_type ]
+// CHECK: [ DW_TAG_unspecified_type ] [nullptr_t]
diff --git a/test/CodeGenCXX/debug-info-pubtypes.cpp b/test/CodeGenCXX/debug-info-pubtypes.cpp
index 612b6b5..6ca3da8 100644
--- a/test/CodeGenCXX/debug-info-pubtypes.cpp
+++ b/test/CodeGenCXX/debug-info-pubtypes.cpp
@@ -3,10 +3,10 @@
// RUN: FileCheck %s < %t
// FIXME: This testcase shouldn't rely on assembly emission.
-//CHECK: Lpubtypes_begin1:
+//CHECK: Lpubtypes_begin[[SECNUM:[0-9]:]]
//CHECK: .asciz "G"
//CHECK-NEXT: .long 0
-//CHECK-NEXT: Lpubtypes_end1:
+//CHECK-NEXT: Lpubtypes_end[[SECNUM]]
class G {
public:
diff --git a/test/CodeGenCXX/debug-info-rvalue-ref.cpp b/test/CodeGenCXX/debug-info-rvalue-ref.cpp
index b633c5c..142f587 100644
--- a/test/CodeGenCXX/debug-info-rvalue-ref.cpp
+++ b/test/CodeGenCXX/debug-info-rvalue-ref.cpp
@@ -8,4 +8,4 @@ void foo (int &&i)
printf("%d\n", i);
}
-// CHECK: metadata !{i32 {{.*}}, null, null, null, i32 0, i64 0, i64 0, i64 0, i32 0, metadata !10} ; [ DW_TAG_rvalue_reference_type ]
+// CHECK: metadata !{i32 {{.*}}, null, null, null, i32 0, i64 0, i64 0, i64 0, i32 0, metadata !{{.*}}} ; [ DW_TAG_rvalue_reference_type ]
diff --git a/test/CodeGenCXX/debug-info-same-line.cpp b/test/CodeGenCXX/debug-info-same-line.cpp
new file mode 100644
index 0000000..ad24503
--- /dev/null
+++ b/test/CodeGenCXX/debug-info-same-line.cpp
@@ -0,0 +1,98 @@
+// RUN: %clang_cc1 -g -emit-llvm -o - %s | FileCheck %s
+
+// Make sure that clang outputs distinct debug info for a function
+// that is inlined twice on the same line. Otherwise it would appear
+// as if the function was only inlined once.
+
+#define INLINE inline __attribute__((always_inline))
+
+INLINE int
+product (int x, int y)
+{
+ int result = x * y;
+ return result;
+}
+
+INLINE int
+sum (int a, int b)
+{
+ int result = a + b;
+ return result;
+}
+
+int
+strange_max (int m, int n)
+{
+ if (m > n)
+ return m;
+ else if (n > m)
+ return n;
+ else
+ return 0;
+}
+
+int
+foo (int i, int j)
+{
+ if (strange_max (i, j) == i)
+ return product (i, j);
+ else if (strange_max (i, j) == j)
+ return sum (i, j);
+ else
+ return product (sum (i, i), sum (j, j));
+}
+
+int
+main(int argc, char const *argv[])
+{
+
+ int array[3];
+ int n;
+
+ array[0] = foo (1238, 78392);
+ array[1] = foo (379265, 23674);
+ array[2] = foo (872934, 234);
+
+ n = strange_max(array[0], strange_max(array[1], array[2]));
+
+ return n & 0xf;
+}
+
+// CHECK: define {{.*}} @_Z3fooii
+// i
+// CHECK: call void @llvm.dbg.declare
+// j
+// CHECK: call void @llvm.dbg.declare
+// x
+// CHECK: call void @llvm.dbg.declare
+// y
+// CHECK: call void @llvm.dbg.declare
+// result
+// CHECK: call void @llvm.dbg.declare
+
+// CHECK: call void @llvm.dbg.declare(metadata !{i32* %{{.*}}}, metadata ![[A_MD:[0-9]+]]), !dbg ![[A_DI:[0-9]+]]
+// CHECK: call void @llvm.dbg.declare(metadata !{i32* %{{.*}}}, metadata ![[B_MD:[0-9]+]]), !dbg ![[B_DI:[0-9]+]]
+// result
+// CHECK: call void @llvm.dbg.declare
+
+// We want to see a distinct !dbg node.
+// CHECK-NOT: call void @llvm.dbg.declare(metadata !{i32* %{{.*}}}, metadata ![[A_MD]]), !dbg ![[A_DI]]
+// CHECK: call void @llvm.dbg.declare(metadata !{i32* %{{.*}}}, metadata ![[A_MD]]), !dbg !{{.*}}
+// CHECK-NOT: call void @llvm.dbg.declare(metadata !{i32* %{{.*}}}, metadata ![[B_MD]]), !dbg ![[B_DI]]
+// CHECK: call void @llvm.dbg.declare(metadata !{i32* %{{.*}}}, metadata ![[B_MD]]), !dbg !{{.*}}
+// result
+// CHECK: call void @llvm.dbg.declare
+
+// CHECK: define {{.*}} @main
+// CHECK: call {{.*}} @_Z3fooii
+// CHECK: call {{.*}} @_Z3fooii
+// CHECK: call {{.*}} @_Z3fooii
+// CHECK: store
+// CHECK: getelementptr
+// We want to see the same !dbg node for non-inlined functions.
+// Needed for GDB compatibility.
+// CHECK: load {{.*}} !dbg ![[DBG:.*]]
+// CHECK: load {{.*}} !dbg ![[DBG]]
+// CHECK: load {{.*}} !dbg ![[DBG]]
+// CHECK: call {{.*}} @_Z11strange_maxii(i32 {{.*}}, i32 {{.*}}), !dbg ![[DBG]]
+// CHECK: call {{.*}} @_Z11strange_maxii(i32 {{.*}}, i32 {{.*}}), !dbg ![[DBG]]
diff --git a/test/CodeGenCXX/debug-info-static-fns.cpp b/test/CodeGenCXX/debug-info-static-fns.cpp
index ee46f25..136261c 100644
--- a/test/CodeGenCXX/debug-info-static-fns.cpp
+++ b/test/CodeGenCXX/debug-info-static-fns.cpp
@@ -7,4 +7,4 @@ namespace A {
}
// Verify that a is present and mangled.
-// CHECK: metadata !{i32 {{.*}}, i32 0, metadata !6, metadata !"a", metadata !"a", metadata !"_ZN1AL1aEi", metadata !7, i32 4, metadata !8, i1 true, i1 true, i32 0, i32 0, null, i32 256, i1 false, i32 (i32)* @_ZN1AL1aEi, null, null, metadata !1, i32 4} ; [ DW_TAG_subprogram ]
+// CHECK: metadata !"_ZN1AL1aEi", {{.*}}, i32 (i32)* @_ZN1AL1aEi, {{.*}} ; [ DW_TAG_subprogram ] [line 4] [local] [def] [a]
diff --git a/test/CodeGenCXX/debug-info-static-member.cpp b/test/CodeGenCXX/debug-info-static-member.cpp
new file mode 100644
index 0000000..774f7b1
--- /dev/null
+++ b/test/CodeGenCXX/debug-info-static-member.cpp
@@ -0,0 +1,41 @@
+// RUN: %clangxx -target x86_64-unknown-unknown -g -O0 %s -emit-llvm -S -o - | FileCheck %s
+// PR14471
+
+
+class C
+{
+ static int a;
+ const static bool const_a = true;
+protected:
+ static int b;
+ const static float const_b = 3.14;
+public:
+ static int c;
+ const static int const_c = 18;
+ int d;
+};
+
+int C::a = 4;
+int C::b = 2;
+int C::c = 1;
+
+int main()
+{
+ C instance_C;
+ instance_C.d = 8;
+ return C::c;
+}
+
+// The definition of C::a drives the emission of class C, which is
+// why the definition of "a" comes before the declarations while
+// "b" and "c" come after.
+
+// CHECK: metadata !"a", {{.*}} @_ZN1C1aE, metadata ![[DECL_A:[0-9]+]]} ; [ DW_TAG_variable ] [a] {{.*}} [def]
+// CHECK: ![[DECL_A]] = metadata {{.*}} [ DW_TAG_member ] [a] [line {{.*}}, size 0, align 0, offset 0] [private] [static]
+// CHECK: metadata !"const_a", {{.*}}, i1 true} ; [ DW_TAG_member ] [const_a] [line {{.*}}, size 0, align 0, offset 0] [private] [static]
+// CHECK: ![[DECL_B:[0-9]+]] {{.*}} metadata !"b", {{.*}} [ DW_TAG_member ] [b] [line {{.*}}, size 0, align 0, offset 0] [protected] [static]
+// CHECK: metadata !"const_b", {{.*}}, float 0x{{.*}}} ; [ DW_TAG_member ] [const_b] [line {{.*}}, size 0, align 0, offset 0] [protected] [static]
+// CHECK: ![[DECL_C:[0-9]+]] {{.*}} metadata !"c", {{.*}} [ DW_TAG_member ] [c] [line {{.*}}, size 0, align 0, offset 0] [static]
+// CHECK: metadata !"const_c", {{.*}} [ DW_TAG_member ] [const_c] [line {{.*}}, size 0, align 0, offset 0] [static]
+// CHECK: metadata !"b", {{.*}} @_ZN1C1bE, metadata ![[DECL_B]]} ; [ DW_TAG_variable ] [b] {{.*}} [def]
+// CHECK: metadata !"c", {{.*}} @_ZN1C1cE, metadata ![[DECL_C]]} ; [ DW_TAG_variable ] [c] {{.*}} [def]
diff --git a/test/CodeGenCXX/debug-info-template-member.cpp b/test/CodeGenCXX/debug-info-template-member.cpp
index 6208c80..6be7f9b 100644
--- a/test/CodeGenCXX/debug-info-template-member.cpp
+++ b/test/CodeGenCXX/debug-info-template-member.cpp
@@ -16,6 +16,6 @@ private:
MyClass m;
-// CHECK: metadata !{i32 {{.*}}, null, metadata !"MyClass", metadata {{.*}}, i32 {{.*}}, i64 8, i64 8, i32 0, i32 0, null, metadata [[C_MEM:.*]], i32 0, null, null} ; [ DW_TAG_class_type ]
-// CHECK: [[C_MEM]] = metadata !{metadata {{.*}}, metadata [[C_TEMP:.*]], metadata {{.*}}}
-// CHECK: [[C_TEMP]] = metadata !{i32 {{.*}}, i32 0, metadata {{.*}}, metadata !"add<2>", metadata !"add<2>", metadata !"_ZN7MyClass3addILi2EEEii", metadata {{.*}}
+// CHECK: metadata [[C_MEM:![0-9]*]], i32 0, null, null} ; [ DW_TAG_class_type ] [MyClass]
+// CHECK: [[C_MEM]] = metadata !{metadata {{.*}}, metadata [[C_TEMP:![0-9]*]], metadata {{.*}}}
+// CHECK: [[C_TEMP]] = {{.*}} ; [ DW_TAG_subprogram ] [line 11] [private] [add<2>]
diff --git a/test/CodeGenCXX/debug-info-template-quals.cpp b/test/CodeGenCXX/debug-info-template-quals.cpp
index ffb1ca3..335c8ab 100644
--- a/test/CodeGenCXX/debug-info-template-quals.cpp
+++ b/test/CodeGenCXX/debug-info-template-quals.cpp
@@ -4,7 +4,7 @@ template<typename _CharT>
struct basic_string {
basic_string&
- assign(const _CharT* __s)
+ assign(const _CharT* __s, const basic_string<_CharT> &x)
{
return *this;
}
@@ -12,12 +12,16 @@ struct basic_string {
void foo (const char *c) {
basic_string<char> str;
- str.assign(c);
+ str.assign(c, str);
}
-// CHECK: [[P:.*]] = metadata !{i32 {{.*}}, metadata [[CON:.*]]} ; [ DW_TAG_pointer_type ] [line 0, size 64, align 64, offset 0] [from ]
-// CHECK: [[CON]] = metadata !{i32 {{.*}}, metadata [[CH:.*]]} ; [ DW_TAG_const_type ] [line 0, size 0, align 0, offset 0] [from char]
-// CHECK: [[CH]] = metadata !{i32 {{.*}}, metadata !"char", {{.*}}} ; [ DW_TAG_base_type ] [char] [line 0, size 8, align 8, offset 0, enc DW_ATE_signed_char]
-// CHECK: metadata !{i32 {{.*}}, metadata !"_ZN12basic_stringIcE6assignEPKc", metadata !6, i32 7, metadata [[TYPE:.*]], i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 false, %struct.basic_string* (%struct.basic_string*, i8*)* @_ZN12basic_stringIcE6assignEPKc, null, metadata !18, metadata !1, i32 8} ; [ DW_TAG_subprogram ] [line 7] [def] [scope 8] [assign]
-// CHECK: [[TYPE]] = metadata !{i32 {{.*}}, null, metadata [[ARGS:.*]], i32 0, i32 0}
-// CHECK: [[ARGS]] = metadata !{metadata !15, metadata !24, metadata [[P]]}
+// CHECK: [[P:.*]] = {{.*}}, metadata [[CON:![0-9]*]]} ; [ DW_TAG_pointer_type ] [line 0, size 64, align 64, offset 0] [from ]
+// CHECK: [[CON]] = {{.*}}, metadata [[CH:![0-9]*]]} ; [ DW_TAG_const_type ] [line 0, size 0, align 0, offset 0] [from char]
+// CHECK: [[CH]] = {{.*}} ; [ DW_TAG_base_type ] [char] [line 0, size 8, align 8, offset 0, enc DW_ATE_signed_char]
+
+// CHECK: {{.*}} metadata [[TYPE:![0-9]*]], {{.*}}, metadata !{{[0-9]*}}, metadata !{{[0-9]*}}, i32 8} ; [ DW_TAG_subprogram ] [line 7] [def] [scope 8] [assign]
+// CHECK: [[TYPE]] = metadata !{i32 {{.*}}, metadata [[ARGS:.*]], i32 0, i32 0} ; [ DW_TAG_subroutine_type ]
+// CHECK: [[ARGS]] = metadata !{metadata !{{.*}}, metadata !{{.*}}, metadata [[P]], metadata [[R:.*]]}
+// CHECK: [[BS:.*]] = {{.*}} ; [ DW_TAG_structure_type ] [basic_string<char>] [line 4, size 8, align 8, offset 0] [from ]
+// CHECK: [[R]] = {{.*}}, metadata [[CON2:![0-9]*]]} ; [ DW_TAG_reference_type ] [line 0, size 0, align 0, offset 0] [from ]
+// CHECK: [[CON2]] = {{.*}}, metadata [[BS]]} ; [ DW_TAG_const_type ] [line 0, size 0, align 0, offset 0] [from basic_string<char>]
diff --git a/test/CodeGenCXX/debug-info-union-template.cpp b/test/CodeGenCXX/debug-info-union-template.cpp
new file mode 100644
index 0000000..f5e6e14
--- /dev/null
+++ b/test/CodeGenCXX/debug-info-union-template.cpp
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -emit-llvm -g -triple x86_64-linux-gnu %s -o - | FileCheck %s
+
+// Make sure that the union type has template parameters.
+
+namespace PR15637 {
+ template <typename T> union Value { int a; };
+ void g(float value) {
+ Value<float> tempValue;
+ }
+ Value<float> f;
+}
+
+// CHECK: {{.*}}, metadata !"Value<float>", {{.*}}, null, metadata [[TTPARAM:.*]]} ; [ DW_TAG_union_type ] [Value<float>]
+// CHECK: [[TTPARAM]] = metadata !{metadata [[PARAMS:.*]]}
+// CHECK: [[PARAMS]] = metadata !{{{.*}}metadata !"T",{{.*}}} ; [ DW_TAG_template_type_parameter ]
diff --git a/test/CodeGenCXX/debug-info-union.cpp b/test/CodeGenCXX/debug-info-union.cpp
index 588fa20..0aa48dc 100644
--- a/test/CodeGenCXX/debug-info-union.cpp
+++ b/test/CodeGenCXX/debug-info-union.cpp
@@ -10,7 +10,7 @@ union E {
E e;
-// CHECK: metadata !{i32 {{.*}}, null, metadata !"E", metadata !{{.*}}, i32 3, i64 32, i64 32, i64 0, i32 0, null, metadata !{{.*}}, i32 0, null} ; [ DW_TAG_union_type ]
-// CHECK: metadata !{i32 {{.*}}, i32 0, metadata !{{.*}}, metadata !"bb", metadata !"bb", metadata !"_ZN1E2bbEv", metadata !{{.*}}, i32 6, metadata !{{.*}}, i1 false, i1 false, i32 0, i32 0, null, i32 256, i1 false, null, null, i32 0, metadata !{{.*}}, i32 6} ; [ DW_TAG_subprogram ]
-// CHECK: metadata !{i32 {{.*}}, i32 0, metadata !{{.*}}, metadata !"aa", metadata !"aa", metadata !"_ZN1E2aaEv", metadata !{{.*}}, i32 7, metadata !{{.*}}, i1 false, i1 false, i32 0, i32 0, null, i32 256, i1 false, null, null, i32 0, metadata !{{.*}}, i32 7} ; [ DW_TAG_subprogram ]
-// CHECK: metadata !{i32 {{.*}}, i32 0, metadata !{{.*}}, metadata !"E", metadata !"E", metadata !"", metadata !{{.*}}, i32 8, metadata !{{.*}}, i1 false, i1 false, i32 0, i32 0, null, i32 256, i1 false, null, null, i32 0, metadata !{{.*}}, i32 8} ; [ DW_TAG_subprogram ]
+// CHECK: {{.*}} ; [ DW_TAG_union_type ] [E] [line 3, size 32, align 32, offset 0]
+// CHECK: {{.*}} ; [ DW_TAG_subprogram ] [line 6] [bb]
+// CHECK: {{.*}} ; [ DW_TAG_subprogram ] [line 7] [aa]
+// CHECK: {{.*}} ; [ DW_TAG_subprogram ] [line 8] [E]
diff --git a/test/CodeGenCXX/debug-info-use-after-free.cpp b/test/CodeGenCXX/debug-info-use-after-free.cpp
index 9757ca4..852e148 100644
--- a/test/CodeGenCXX/debug-info-use-after-free.cpp
+++ b/test/CodeGenCXX/debug-info-use-after-free.cpp
@@ -192,6 +192,7 @@ __gnu_cxx {
public:
typedef _EqualKey
key_equal;
+ typedef void key_type;
};
using
std::equal_to;
@@ -217,7 +218,7 @@ __gnu_cxx {
_Alloc >
_Ht;
public:
- typename _Ht::key_type;
+ typedef typename _Ht::key_type key_type;
typedef typename
_Ht::key_equal
key_equal;
diff --git a/test/CodeGenCXX/debug-info-zero-length-arrays.cpp b/test/CodeGenCXX/debug-info-zero-length-arrays.cpp
new file mode 100644
index 0000000..fb47022
--- /dev/null
+++ b/test/CodeGenCXX/debug-info-zero-length-arrays.cpp
@@ -0,0 +1,12 @@
+// RUN: %clang -target x86_64-unknown-unknown -fverbose-asm -g -O0 -S -emit-llvm %s -o - | FileCheck %s
+// <rdar://problem/12566646>
+
+class A {
+ int x[];
+};
+A a;
+
+// CHECK: metadata [[ARRAY_TYPE:![0-9]*]]} ; [ DW_TAG_member ] [x]
+// CHECK: metadata [[ELEM_TYPE:![0-9]*]], i32 0, i32 0} ; [ DW_TAG_array_type ] [line 0, size 0, align 32, offset 0] [from int]
+// CHECK: [[ELEM_TYPE]] = metadata !{metadata [[SUBRANGE:.*]]}
+// CHECK: [[SUBRANGE]] = metadata !{i32 786465, i64 0, i64 -1} ; [ DW_TAG_subrange_type ] [unbounded]
diff --git a/test/CodeGenCXX/debug-lambda-expressions.cpp b/test/CodeGenCXX/debug-lambda-expressions.cpp
index 430371f..39c9a44 100644
--- a/test/CodeGenCXX/debug-lambda-expressions.cpp
+++ b/test/CodeGenCXX/debug-lambda-expressions.cpp
@@ -15,57 +15,57 @@ struct D { D(); D(const D&); int x; };
int d(int x) { D y[10]; [x,y] { return y[x].x; }(); }
// Randomness for file. -- 6
-// CHECK: [[FILE:.*]] = metadata !{i32 {{.*}}, metadata !{{.*}}debug-lambda-expressions.cpp{{.*}}; [ DW_TAG_file_type ]
+// CHECK: [[FILE:.*]] = {{.*}} [ DW_TAG_file_type ] [{{.*}}debug-lambda-expressions.cpp]
// A: 10
-// CHECK: [[A_FUNC:.*]] = metadata !{i32 {{.*}}, i32 0, metadata [[FILE]], metadata !"a", metadata !"a", metadata !"_Z1av", metadata {{.*}}, i32 [[A_LINE:.*]], metadata {{.*}}, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 false, i32 ()* @_Z1av, null, null, {{.*}} [ DW_TAG_subprogram ]
+// CHECK: [[A_FUNC:.*]] = {{.*}} [ DW_TAG_subprogram ] [line [[A_LINE:.*]]] [def] [a]
// B: 14
-// CHECK: [[B_FUNC:.*]] = metadata !{i32 786478, i32 0, metadata [[FILE]], metadata !"b", metadata !"b", metadata !"_Z1bi", metadata [[FILE]], i32 [[B_LINE:.*]], metadata {{.*}}, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 false, i32 (i32)* @_Z1bi, null, null, {{.*}} ; [ DW_TAG_subprogram ]
+// CHECK: [[B_FUNC:.*]] = {{.*}} [ DW_TAG_subprogram ] [line [[B_LINE:.*]]] [def] [b]
// C: 17
-// CHECK: [[C_FUNC:.*]] = metadata !{i32 {{.*}}, i32 0, metadata [[FILE]], metadata !"c", metadata !"c", metadata !"_Z1ci", metadata [[FILE]], i32 [[C_LINE:.*]], metadata {{.*}}, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 false, i32 (i32)* @_Z1ci, null, null, metadata {{.*}} ; [ DW_TAG_subprogram ]
+// CHECK: [[C_FUNC:.*]] = {{.*}} [ DW_TAG_subprogram ] [line [[C_LINE:.*]]] [def] [c]
// D: 18
-// CHECK: [[D_FUNC:.*]] = metadata !{i32 {{.*}}, i32 0, metadata [[FILE]], metadata !"d", metadata !"d", metadata !"_Z1di", metadata [[FILE]], i32 [[D_LINE:.*]], metadata {{.*}}, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 false, i32 (i32)* @_Z1di, null, null, metadata {{.*}} ; [ DW_TAG_subprogram ]
+// CHECK: [[D_FUNC:.*]] = {{.*}} [ DW_TAG_subprogram ] [line [[D_LINE:.*]]] [def] [d]
// Back to D. -- 24
-// CHECK: [[LAM_D:.*]] = metadata !{i32 {{.*}}, metadata [[D_FUNC]], metadata !"", metadata [[FILE]], i32 [[D_LINE]], i64 352, i64 32, i32 0, i32 0, null, metadata [[LAM_D_ARGS:.*]], i32 0, null, null} ; [ DW_TAG_class_type ]
+// CHECK: [[LAM_D:.*]] = {{.*}}, metadata [[D_FUNC]], {{.*}}, metadata [[LAM_D_ARGS:.*]], i32 0, null, null} ; [ DW_TAG_class_type ] [line [[D_LINE]],
// CHECK: [[LAM_D_ARGS]] = metadata !{metadata [[CAP_D_X:.*]], metadata [[CAP_D_Y:.*]], metadata [[CON_LAM_D:.*]], metadata [[DES_LAM_D:.*]]}
-// CHECK: [[CAP_D_X]] = metadata !{i32 {{.*}}, metadata [[LAM_D]], metadata !"x", metadata [[FILE]], i32 [[D_LINE]], i64 32, i64 32, i64 0, i32 1, metadata {{.*}} ; [ DW_TAG_member ]
-// CHECK: [[CAP_D_Y]] = metadata !{i32 {{.*}}, metadata [[LAM_D]], metadata !"y", metadata [[FILE]], i32 [[D_LINE]], i64 320, i64 32, i64 32, i32 1, metadata {{.*}} ; [ DW_TAG_member ]
-// CHECK: [[CON_LAM_D]] = metadata {{.*}}[[LAM_D]], metadata !"operator()", metadata !"operator()"{{.*}}[ DW_TAG_subprogram ]
-// CHECK: [[DES_LAM_D]] = metadata {{.*}}[[LAM_D]], metadata !"~", metadata !"~"{{.*}}[ DW_TAG_subprogram ]
+// CHECK: [[CAP_D_X]] = {{.*}}, metadata [[LAM_D]], {{.*}} [ DW_TAG_member ] [x] [line [[D_LINE]],
+// CHECK: [[CAP_D_Y]] = {{.*}}, metadata [[LAM_D]], {{.*}} [ DW_TAG_member ] [y] [line [[D_LINE]],
+// CHECK: [[CON_LAM_D]] = {{.*}}, metadata [[LAM_D]], {{.*}} [ DW_TAG_subprogram ] [line [[D_LINE]]] [operator()]
+// CHECK: [[DES_LAM_D]] = {{.*}}, metadata [[LAM_D]], {{.*}} [ DW_TAG_subprogram ] [line [[D_LINE]]] [~]
// Back to C. -- 55
-// CHECK: [[LAM_C:.*]] = metadata !{i32 {{.*}}, metadata [[C_FUNC]], metadata !"", metadata [[FILE]], i32 [[C_LINE]], i64 64, i64 64, i32 0, i32 0, null, metadata [[LAM_C_ARGS:.*]], i32 0, null, null} ; [ DW_TAG_class_type ]
+// CHECK: [[LAM_C:.*]] = {{.*}}, metadata [[C_FUNC]], {{.*}}, metadata [[LAM_C_ARGS:.*]], i32 0, null, null} ; [ DW_TAG_class_type ] [line [[C_LINE]],
// CHECK: [[LAM_C_ARGS]] = metadata !{metadata [[CAP_C:.*]], metadata [[CON_LAM_C:.*]], metadata [[DES_LAM_C:.*]]}
// Ignoring the member type for now.
-// CHECK: [[CAP_C]] = metadata !{i32 {{.*}}, metadata [[LAM_C]], metadata !"x", metadata [[FILE]], i32 [[C_LINE]], i64 64, i64 64, i64 0, i32 1, metadata {{.*}}} ; [ DW_TAG_member ]
-// CHECK: [[CON_LAM_C]] = metadata {{.*}}[[LAM_C]], metadata !"operator()", metadata !"operator()"{{.*}}[ DW_TAG_subprogram ]
-// CHECK: [[DES_LAM_C]] = metadata {{.*}}[[LAM_C]], metadata !"~", metadata !"~"{{.*}}[ DW_TAG_subprogram ]
+// CHECK: [[CAP_C]] = {{.*}}, metadata [[LAM_C]], {{.*}}} ; [ DW_TAG_member ] [x] [line [[C_LINE]],
+// CHECK: [[CON_LAM_C]] = {{.*}}, metadata [[LAM_C]], {{.*}} [ DW_TAG_subprogram ] [line [[C_LINE]]] [operator()]
+// CHECK: [[DES_LAM_C]] = {{.*}}, metadata [[LAM_C]], {{.*}} [ DW_TAG_subprogram ] [line [[C_LINE]]] [~]
// Back to B. -- 67
-// CHECK: [[LAM_B:.*]] = metadata !{i32 {{.*}}, metadata [[B_FUNC]], metadata !"", metadata [[FILE]], i32 [[B_LINE]], i64 32, i64 32, i32 0, i32 0, null, metadata [[LAM_B_ARGS:.*]], i32 0, null, null} ; [ DW_TAG_class_type ]
+// CHECK: [[LAM_B:.*]] = {{.*}}, metadata [[B_FUNC]], {{.*}}, metadata [[LAM_B_ARGS:.*]], i32 0, null, null} ; [ DW_TAG_class_type ] [line [[B_LINE]],
// CHECK: [[LAM_B_ARGS]] = metadata !{metadata [[CAP_B:.*]], metadata [[CON_LAM_B:.*]], metadata [[DES_LAM_B:.*]]}
-// CHECK: [[CAP_B]] = metadata !{i32 {{.*}}, metadata [[LAM_B]], metadata !"x", metadata [[FILE]], i32 [[B_LINE]], i64 32, i64 32, i64 0, i32 1, metadata {{.*}}} ; [ DW_TAG_member ]
-// CHECK: [[CON_LAM_B]] = metadata {{.*}}[[LAM_B]], metadata !"operator()", metadata !"operator()"{{.*}}[ DW_TAG_subprogram ]
-// CHECK: [[DES_LAM_B]] = metadata {{.*}}[[LAM_B]], metadata !"~", metadata !"~"{{.*}}[ DW_TAG_subprogram ]
+// CHECK: [[CAP_B]] = {{.*}}, metadata [[LAM_B]], {{.*}}} ; [ DW_TAG_member ] [x] [line [[B_LINE]],
+// CHECK: [[CON_LAM_B]] = {{.*}}, metadata [[LAM_B]], {{.*}} [ DW_TAG_subprogram ] [line [[B_LINE]]] [operator()]
+// CHECK: [[DES_LAM_B]] = {{.*}}, metadata [[LAM_B]], {{.*}} [ DW_TAG_subprogram ] [line [[B_LINE]]] [~]
// Back to A. -- 78
-// CHECK: [[LAM_A:.*]] = metadata !{i32 {{.*}}, metadata [[A_FUNC]], metadata !"", metadata [[FILE]], i32 [[A_LINE]], i64 8, i64 8, i32 0, i32 0, null, metadata [[LAM_A_ARGS:.*]], i32 0, null, null} ; [ DW_TAG_class_type ]
+// CHECK: [[LAM_A:.*]] = {{.*}}, metadata [[A_FUNC]], {{.*}}, metadata [[LAM_A_ARGS:.*]], i32 0, null, null} ; [ DW_TAG_class_type ] [line [[A_LINE]],
// CHECK: [[LAM_A_ARGS]] = metadata !{metadata [[CON_LAM_A:.*]], metadata [[DES_LAM_A:.*]]}
-// CHECK: [[CON_LAM_A]] = metadata {{.*}}[[LAM_A]], metadata !"operator()", metadata !"operator()"{{.*}}[ DW_TAG_subprogram ]
-// CHECK: [[DES_LAM_A]] = metadata {{.*}}[[LAM_A]], metadata !"~", metadata !"~"{{.*}}[ DW_TAG_subprogram ]
+// CHECK: [[CON_LAM_A]] = {{.*}}, metadata [[LAM_A]], {{.*}} [ DW_TAG_subprogram ] [line [[A_LINE]]] [operator()]
+// CHECK: [[DES_LAM_A]] = {{.*}}, metadata [[LAM_A]], {{.*}} [ DW_TAG_subprogram ] [line [[A_LINE]]] [~]
// CVAR:
-// CHECK: metadata !{i32 {{.*}}, i32 0, null, metadata !"cvar", metadata !"cvar", metadata !"", metadata [[FILE]], i32 [[CVAR_LINE:.*]], metadata ![[CVAR_T:.*]], i32 0, i32 1, %class.anon.0* @cvar} ; [ DW_TAG_variable ]
-// CHECK: [[CVAR_T]] = metadata !{i32 {{.*}}, null, metadata !"", metadata [[FILE]], i32 [[CVAR_LINE]], i64 8, i64 8, i32 0, i32 0, null, metadata ![[CVAR_ARGS:.*]], i32 0, null, null} ; [ DW_TAG_class_type ]
+// CHECK: {{.*}} metadata [[CVAR_T:![0-9]*]], {{.*}} ; [ DW_TAG_variable ] [cvar] [line [[CVAR_LINE:[0-9]*]]]
+// CHECK: [[CVAR_T]] = {{.*}}, metadata ![[CVAR_ARGS:.*]], i32 0, null, null} ; [ DW_TAG_class_type ] [line [[CVAR_LINE]],
// CHECK: [[CVAR_ARGS]] = metadata !{metadata !{{.*}}, metadata !{{.*}}, metadata !{{.*}}}
// VAR:
-// CHECK: metadata !{i32 {{.*}}, i32 0, null, metadata !"var", metadata !"var", metadata !"", metadata [[FILE]], i32 [[VAR_LINE:.*]], metadata ![[VAR_T:.*]], i32 1, i32 1, %class.anon* @var} ; [ DW_TAG_variable ]
-// CHECK: [[VAR_T]] = metadata !{i32 {{.*}}, null, metadata !"", metadata [[FILE]], i32 [[VAR_LINE]], i64 8, i64 8, i32 0, i32 0, null, metadata ![[VAR_ARGS:.*]], i32 0, null, null} ; [ DW_TAG_class_type ]
+// CHECK: {{.*}} metadata [[VAR_T:![0-9]*]], {{.*}} ; [ DW_TAG_variable ] [var] [line [[VAR_LINE:[0-9]*]]]
+// CHECK: [[VAR_T]] = {{.*}}, metadata [[VAR_ARGS:![0-9]*]], i32 0, null, null} ; [ DW_TAG_class_type ] [line [[VAR_LINE]],
// CHECK: [[VAR_ARGS]] = metadata !{metadata !{{.*}}, metadata !{{.*}}, metadata !{{.*}}}
diff --git a/test/CodeGenCXX/debug-lambda-this.cpp b/test/CodeGenCXX/debug-lambda-this.cpp
index 7c37fbe..e7155e7 100644
--- a/test/CodeGenCXX/debug-lambda-this.cpp
+++ b/test/CodeGenCXX/debug-lambda-this.cpp
@@ -12,4 +12,4 @@ int D::d(int x) {
}();
}
-// CHECK: metadata !{i32 {{.*}}, metadata !"this", metadata !6, i32 11, i64 64, i64 64, i64 0, i32 1, metadata !37} ; [ DW_TAG_member ] [this] [line 11, size 64, align 64, offset 0] [private] [from ]
+// CHECK: {{.*}} [ DW_TAG_member ] [this] [line 11, size 64, align 64, offset 0] [private] [from ]
diff --git a/test/CodeGenCXX/default-destructor-synthesis.cpp b/test/CodeGenCXX/default-destructor-synthesis.cpp
index fac5cc0..af78004 100644
--- a/test/CodeGenCXX/default-destructor-synthesis.cpp
+++ b/test/CodeGenCXX/default-destructor-synthesis.cpp
@@ -24,7 +24,7 @@ struct M : Q, P {
Q q_arr[2][3];
};
-// CHECK: define i32 @_Z1fv() nounwind
+// CHECK: define i32 @_Z1fv() [[NUW:#[0-9]+]]
int f() {
{
count = 1;
@@ -34,3 +34,5 @@ int f() {
// CHECK: ret i32 1
return count;
}
+
+// CHECK: attributes [[NUW]] = { nounwind{{.*}} }
diff --git a/test/CodeGenCXX/delete.cpp b/test/CodeGenCXX/delete.cpp
index 7a91ca8..1299b29 100644
--- a/test/CodeGenCXX/delete.cpp
+++ b/test/CodeGenCXX/delete.cpp
@@ -129,7 +129,7 @@ namespace test4 {
// CHECK-NEXT: [[DTOR:%.*]] = load void ([[X]]*)** [[T0]]
// CHECK-NEXT: call void [[DTOR]]([[X]]* [[OBJ:%.*]])
// Call the global operator delete.
- // CHECK-NEXT: call void @_ZdlPv(i8* [[ALLOCATED]]) nounwind
+ // CHECK-NEXT: call void @_ZdlPv(i8* [[ALLOCATED]]) [[NUW:#[0-9]+]]
::delete xp;
}
}
@@ -144,3 +144,5 @@ namespace test5 {
delete [] p2;
}
}
+
+// CHECK: attributes [[NUW]] = { nounwind{{.*}} }
diff --git a/test/CodeGenCXX/derived-to-base.cpp b/test/CodeGenCXX/derived-to-base.cpp
index 76b79fc..c69b456 100644
--- a/test/CodeGenCXX/derived-to-base.cpp
+++ b/test/CodeGenCXX/derived-to-base.cpp
@@ -15,7 +15,7 @@ void f() {
b.f();
}
-// CHECK: define %struct.B* @_Z1fP1A(%struct.A* %a) nounwind
+// CHECK: define %struct.B* @_Z1fP1A(%struct.A* %a) [[NUW:#[0-9]+]]
B *f(A *a) {
// CHECK-NOT: br label
// CHECK: ret %struct.B*
@@ -25,7 +25,7 @@ B *f(A *a) {
// PR5965
namespace PR5965 {
-// CHECK: define %struct.A* @_ZN6PR59651fEP1B(%struct.B* %b) nounwind
+// CHECK: define %struct.A* @_ZN6PR59651fEP1B(%struct.B* %b) [[NUW]]
A *f(B* b) {
// CHECK-NOT: br label
// CHECK: ret %struct.A*
@@ -45,3 +45,5 @@ namespace test3 {
foo(B());
}
}
+
+// CHECK: attributes [[NUW]] = { nounwind{{.*}} }
diff --git a/test/CodeGenCXX/destructors.cpp b/test/CodeGenCXX/destructors.cpp
index d665445..7dc188b 100644
--- a/test/CodeGenCXX/destructors.cpp
+++ b/test/CodeGenCXX/destructors.cpp
@@ -370,11 +370,11 @@ namespace test9 {
// CHECK: define internal void @_ZN5test312_GLOBAL__N_11DD0Ev(%"struct.test3::<anonymous namespace>::D"* %this) unnamed_addr
// CHECK: invoke void @_ZN5test312_GLOBAL__N_11DD1Ev(
- // CHECK: call void @_ZdlPv({{.*}}) nounwind
+ // CHECK: call void @_ZdlPv({{.*}}) [[NUW:#[0-9]+]]
// CHECK: ret void
// CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
// CHECK-NEXT: cleanup
- // CHECK: call void @_ZdlPv({{.*}}) nounwind
+ // CHECK: call void @_ZdlPv({{.*}}) [[NUW]]
// CHECK: resume { i8*, i32 }
// Checked at top of file:
@@ -401,11 +401,11 @@ namespace test9 {
// CHECK: define internal void @_ZN5test312_GLOBAL__N_11CD0Ev(%"struct.test3::<anonymous namespace>::C"* %this) unnamed_addr
// CHECK: invoke void @_ZN5test312_GLOBAL__N_11CD1Ev(
- // CHECK: call void @_ZdlPv({{.*}}) nounwind
+ // CHECK: call void @_ZdlPv({{.*}}) [[NUW]]
// CHECK: ret void
// CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
// CHECK-NEXT: cleanup
- // CHECK: call void @_ZdlPv({{.*}}) nounwind
+ // CHECK: call void @_ZdlPv({{.*}}) [[NUW]]
// CHECK: resume { i8*, i32 }
// CHECK: define internal void @_ZThn8_N5test312_GLOBAL__N_11CD1Ev(
@@ -417,3 +417,5 @@ namespace test9 {
// CHECK: getelementptr inbounds i8* {{.*}}, i64 -8
// CHECK: call void @_ZN5test312_GLOBAL__N_11CD0Ev(
// CHECK: ret void
+
+ // CHECK: attributes [[NUW]] = { nounwind{{.*}} }
diff --git a/test/CodeGenCXX/dynamic-cast-always-null.cpp b/test/CodeGenCXX/dynamic-cast-always-null.cpp
index 836cb11..db4346f 100644
--- a/test/CodeGenCXX/dynamic-cast-always-null.cpp
+++ b/test/CodeGenCXX/dynamic-cast-always-null.cpp
@@ -13,7 +13,7 @@ C *f(B* b) {
// CHECK: @_Z1fR1B
C &f(B& b) {
// CHECK-NOT: call i8* @__dynamic_cast
- // CHECK: call void @__cxa_bad_cast() noreturn
+ // CHECK: call void @__cxa_bad_cast() [[NR:#[0-9]+]]
// CHECK: ret %struct.C* undef
return dynamic_cast<C&>(b);
}
@@ -22,3 +22,5 @@ void dont_crash() {
(void) dynamic_cast<void*>((A*)0);
(void) dynamic_cast<void*>((B*)0);
}
+
+// CHECK: attributes [[NR]] = { noreturn }
diff --git a/test/CodeGenCXX/dynamic-cast-hint.cpp b/test/CodeGenCXX/dynamic-cast-hint.cpp
new file mode 100644
index 0000000..27b76e0
--- /dev/null
+++ b/test/CodeGenCXX/dynamic-cast-hint.cpp
@@ -0,0 +1,53 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin12 -emit-llvm -o - %s | FileCheck %s
+
+class A { virtual ~A() {} };
+class B { virtual ~B() {} };
+
+class C : A { char x; };
+class D : public A { short y; };
+class E : public A, public B { int z; };
+class F : public virtual A { long long w; };
+class G : virtual A { long long w; };
+
+class H : public E { int a; };
+class I : public F { char b; };
+
+class J : public H { char q; };
+class K : public C, public B { char q; };
+
+class XA : public A { };
+class XB : public A { };
+class XC : public virtual A { };
+class X : public XA, public XB, public XC { };
+
+void test(A *a, B *b) {
+ volatile C *ac = dynamic_cast<C *>(a);
+// CHECK: i8* bitcast ({ i8*, i8* }* @_ZTI1A to i8*), i8* bitcast ({ i8*, i8*, i32, i32, i8*, i64 }* @_ZTI1C to i8*), i64 -2)
+ volatile D *ad = dynamic_cast<D *>(a);
+// CHECK: i8* bitcast ({ i8*, i8* }* @_ZTI1A to i8*), i8* bitcast ({ i8*, i8*, i8* }* @_ZTI1D to i8*), i64 0)
+ volatile E *ae = dynamic_cast<E *>(a);
+// CHECK: i8* bitcast ({ i8*, i8* }* @_ZTI1A to i8*), i8* bitcast ({ i8*, i8*, i32, i32, i8*, i64, i8*, i64 }* @_ZTI1E to i8*), i64 0)
+ volatile F *af = dynamic_cast<F *>(a);
+// CHECK: i8* bitcast ({ i8*, i8* }* @_ZTI1A to i8*), i8* bitcast ({ i8*, i8*, i32, i32, i8*, i64 }* @_ZTI1F to i8*), i64 -1)
+ volatile G *ag = dynamic_cast<G *>(a);
+// CHECK: i8* bitcast ({ i8*, i8* }* @_ZTI1A to i8*), i8* bitcast ({ i8*, i8*, i32, i32, i8*, i64 }* @_ZTI1G to i8*), i64 -2)
+ volatile H *ah = dynamic_cast<H *>(a);
+// CHECK: i8* bitcast ({ i8*, i8* }* @_ZTI1A to i8*), i8* bitcast ({ i8*, i8*, i8* }* @_ZTI1H to i8*), i64 0)
+ volatile I *ai = dynamic_cast<I *>(a);
+// CHECK: i8* bitcast ({ i8*, i8* }* @_ZTI1A to i8*), i8* bitcast ({ i8*, i8*, i8* }* @_ZTI1I to i8*), i64 -1)
+ volatile J *aj = dynamic_cast<J *>(a);
+// CHECK: i8* bitcast ({ i8*, i8* }* @_ZTI1A to i8*), i8* bitcast ({ i8*, i8*, i8* }* @_ZTI1J to i8*), i64 0)
+ volatile K *ak = dynamic_cast<K *>(a);
+// CHECK: i8* bitcast ({ i8*, i8* }* @_ZTI1A to i8*), i8* bitcast ({ i8*, i8*, i32, i32, i8*, i64, i8*, i64 }* @_ZTI1K to i8*), i64 -2)
+ volatile X *ax = dynamic_cast<X *>(a);
+// CHECK: i8* bitcast ({ i8*, i8* }* @_ZTI1A to i8*), i8* bitcast ({ i8*, i8*, i32, i32, i8*, i64, i8*, i64, i8*, i64 }* @_ZTI1X to i8*), i64 -1)
+
+ volatile E *be = dynamic_cast<E *>(b);
+// CHECK: i8* bitcast ({ i8*, i8* }* @_ZTI1B to i8*), i8* bitcast ({ i8*, i8*, i32, i32, i8*, i64, i8*, i64 }* @_ZTI1E to i8*), i64 8)
+ volatile G *bg = dynamic_cast<G *>(b);
+// CHECK: i8* bitcast ({ i8*, i8* }* @_ZTI1B to i8*), i8* bitcast ({ i8*, i8*, i32, i32, i8*, i64 }* @_ZTI1G to i8*), i64 -2)
+ volatile J *bj = dynamic_cast<J *>(b);
+// CHECK: i8* bitcast ({ i8*, i8* }* @_ZTI1B to i8*), i8* bitcast ({ i8*, i8*, i8* }* @_ZTI1J to i8*), i64 8)
+ volatile K *bk = dynamic_cast<K *>(b);
+// CHECK: i8* bitcast ({ i8*, i8* }* @_ZTI1B to i8*), i8* bitcast ({ i8*, i8*, i32, i32, i8*, i64, i8*, i64 }* @_ZTI1K to i8*), i64 16)
+}
diff --git a/test/CodeGenCXX/dynamic-cast.cpp b/test/CodeGenCXX/dynamic-cast.cpp
index 813e36e..fe85e21 100644
--- a/test/CodeGenCXX/dynamic-cast.cpp
+++ b/test/CodeGenCXX/dynamic-cast.cpp
@@ -8,7 +8,7 @@ const B& f(A *a) {
try {
// CHECK: call i8* @__dynamic_cast
// CHECK: br i1
- // CHECK: invoke void @__cxa_bad_cast() noreturn
+ // CHECK: invoke void @__cxa_bad_cast() [[NR:#[0-9]+]]
dynamic_cast<const B&>(*a);
} catch (...) {
// CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
@@ -16,3 +16,8 @@ const B& f(A *a) {
}
return fail;
}
+
+// CHECK: declare i8* @__dynamic_cast(i8*, i8*, i8*, i64) [[NUW_RO:#[0-9]+]]
+
+// CHECK: attributes [[NUW_RO]] = { nounwind readonly }
+// CHECK: attributes [[NR]] = { noreturn }
diff --git a/test/CodeGenCXX/eh.cpp b/test/CodeGenCXX/eh.cpp
index 584af40..70887f7 100644
--- a/test/CodeGenCXX/eh.cpp
+++ b/test/CodeGenCXX/eh.cpp
@@ -14,7 +14,7 @@ void test1() {
// CHECK-NEXT: [[EXN:%.*]] = bitcast i8* [[EXNOBJ]] to [[DSTAR:%[^*]*\*]]
// CHECK-NEXT: [[EXN2:%.*]] = bitcast [[DSTAR]] [[EXN]] to i8*
// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[EXN2]], i8* bitcast ([[DSTAR]] @d1 to i8*), i64 8, i32 8, i1 false)
-// CHECK-NEXT: call void @__cxa_throw(i8* [[EXNOBJ]], i8* bitcast ({ i8*, i8* }* @_ZTI7test1_D to i8*), i8* null) noreturn
+// CHECK-NEXT: call void @__cxa_throw(i8* [[EXNOBJ]], i8* bitcast ({ i8*, i8* }* @_ZTI7test1_D to i8*), i8* null) [[NR:#[0-9]+]]
// CHECK-NEXT: unreachable
@@ -37,7 +37,7 @@ void test2() {
// CHECK-NEXT: invoke void @_ZN7test2_DC1ERKS_([[DSTAR]] [[EXN]], [[DSTAR]] @d2)
// CHECK-NEXT: to label %[[CONT:.*]] unwind label %{{.*}}
// : [[CONT]]: (can't check this in Release-Asserts builds)
-// CHECK: call void @__cxa_throw(i8* [[EXNOBJ]], i8* bitcast ({{.*}}* @_ZTI7test2_D to i8*), i8* null) noreturn
+// CHECK: call void @__cxa_throw(i8* [[EXNOBJ]], i8* bitcast ({{.*}}* @_ZTI7test2_D to i8*), i8* null) [[NR]]
// CHECK-NEXT: unreachable
@@ -55,7 +55,7 @@ void test3() {
// CHECK: [[EXNOBJ:%.*]] = call i8* @__cxa_allocate_exception(i64 8)
// CHECK-NEXT: [[EXN:%.*]] = bitcast i8* [[EXNOBJ]] to [[D:%[^*]+]]**
// CHECK-NEXT: store [[D]]* null, [[D]]** [[EXN]]
-// CHECK-NEXT: call void @__cxa_throw(i8* [[EXNOBJ]], i8* bitcast ({ i8*, i8*, i32, i8* }* @_ZTIPV7test3_D to i8*), i8* null) noreturn
+// CHECK-NEXT: call void @__cxa_throw(i8* [[EXNOBJ]], i8* bitcast ({ i8*, i8*, i32, i8* }* @_ZTIPV7test3_D to i8*), i8* null) [[NR]]
// CHECK-NEXT: unreachable
@@ -64,7 +64,7 @@ void test4() {
}
// CHECK: define void @_Z5test4v()
-// CHECK: call void @__cxa_rethrow() noreturn
+// CHECK: call void @__cxa_rethrow() [[NR]]
// CHECK-NEXT: unreachable
@@ -83,7 +83,7 @@ namespace test5 {
// CHECK: [[EXNOBJ:%.*]] = call i8* @__cxa_allocate_exception(i64 1)
// CHECK: [[EXNCAST:%.*]] = bitcast i8* [[EXNOBJ]] to [[A:%[^*]*]]*
// CHECK-NEXT: invoke void @_ZN5test51AC1Ev([[A]]* [[EXNCAST]])
-// CHECK: invoke void @__cxa_throw(i8* [[EXNOBJ]], i8* bitcast ({{.*}}* @_ZTIN5test51AE to i8*), i8* bitcast (void ([[A]]*)* @_ZN5test51AD1Ev to i8*)) noreturn
+// CHECK: invoke void @__cxa_throw(i8* [[EXNOBJ]], i8* bitcast ({{.*}}* @_ZTIN5test51AE to i8*), i8* bitcast (void ([[A]]*)* @_ZN5test51AD1Ev to i8*)) [[NR]]
// CHECK-NEXT: to label {{%.*}} unwind label %[[HANDLER:[^ ]*]]
// : [[HANDLER]]: (can't check this in Release-Asserts builds)
// CHECK: {{%.*}} = call i32 @llvm.eh.typeid.for(i8* bitcast ({{.*}}* @_ZTIN5test51AE to i8*))
@@ -222,7 +222,7 @@ namespace test10 {
// CHECK-NEXT: bitcast
// CHECK-NEXT: load i32*
// CHECK-NEXT: store i32
- // CHECK-NEXT: call void @__cxa_end_catch() nounwind
+ // CHECK-NEXT: call void @__cxa_end_catch() [[NUW:#[0-9]+]]
} catch (B a) {
// CHECK: call i8* @__cxa_begin_catch
// CHECK-NEXT: bitcast
@@ -251,11 +251,11 @@ namespace test11 {
opaque();
} catch (int**&p) {
// CHECK: [[EXN:%.*]] = load i8**
- // CHECK-NEXT: call i8* @__cxa_begin_catch(i8* [[EXN]]) nounwind
+ // CHECK-NEXT: call i8* @__cxa_begin_catch(i8* [[EXN]]) [[NUW]]
// CHECK-NEXT: [[ADJ1:%.*]] = getelementptr i8* [[EXN]], i32 32
// CHECK-NEXT: [[ADJ2:%.*]] = bitcast i8* [[ADJ1]] to i32***
// CHECK-NEXT: store i32*** [[ADJ2]], i32**** [[P:%.*]]
- // CHECK-NEXT: call void @__cxa_end_catch() nounwind
+ // CHECK-NEXT: call void @__cxa_end_catch() [[NUW]]
}
}
@@ -272,11 +272,11 @@ namespace test11 {
opaque();
} catch (A*&p) {
// CHECK: [[EXN:%.*]] = load i8** [[EXNSLOT]]
- // CHECK-NEXT: [[ADJ1:%.*]] = call i8* @__cxa_begin_catch(i8* [[EXN]]) nounwind
+ // CHECK-NEXT: [[ADJ1:%.*]] = call i8* @__cxa_begin_catch(i8* [[EXN]]) [[NUW]]
// CHECK-NEXT: [[ADJ2:%.*]] = bitcast i8* [[ADJ1]] to [[A]]*
// CHECK-NEXT: store [[A]]* [[ADJ2]], [[A]]** [[TMP]]
// CHECK-NEXT: store [[A]]** [[TMP]], [[A]]*** [[P]]
- // CHECK-NEXT: call void @__cxa_end_catch() nounwind
+ // CHECK-NEXT: call void @__cxa_end_catch() [[NUW]]
}
}
}
@@ -444,3 +444,6 @@ namespace test16 {
// CHECK-NEXT: br label
}
}
+
+// CHECK: attributes [[NUW]] = { nounwind }
+// CHECK: attributes [[NR]] = { noreturn }
diff --git a/test/CodeGenCXX/exception-spec-decay.cpp b/test/CodeGenCXX/exception-spec-decay.cpp
new file mode 100644
index 0000000..4928353
--- /dev/null
+++ b/test/CodeGenCXX/exception-spec-decay.cpp
@@ -0,0 +1,33 @@
+// RUN: %clang_cc1 -fcxx-exceptions -fexceptions %s -triple=i686-unknown-linux -emit-llvm -o - | FileCheck %s
+typedef int Array[10];
+
+void foo() throw (Array) {
+ throw 0;
+ // CHECK: landingpad
+ // CHECK-NEXT: filter {{.*}} @_ZTIPi
+}
+
+struct S {
+ void foo() throw (S[10]) {
+ throw 0;
+ }
+};
+
+template <typename T>
+struct S2 {
+ void foo() throw (T) {
+ throw 0;
+ }
+};
+
+int main() {
+ S s;
+ s.foo();
+ // CHECK: landingpad
+ // CHECK-NEXT: filter {{.*}} @_ZTIP1S
+
+ S2 <int[10]> s2;
+ s2.foo();
+ // CHECK: landingpad
+ // CHECK-NEXT: filter {{.*}} @_ZTIPi
+}
diff --git a/test/CodeGenCXX/exceptions.cpp b/test/CodeGenCXX/exceptions.cpp
index 723e8d1..f6f5079 100644
--- a/test/CodeGenCXX/exceptions.cpp
+++ b/test/CodeGenCXX/exceptions.cpp
@@ -69,6 +69,13 @@ namespace test1 {
return new A(B().x);
}
+ // rdar://11904428
+ // Terminate landing pads should call __cxa_begin_catch first.
+ // CHECK: define linkonce_odr hidden void @__clang_call_terminate(i8*) [[NI_NR_NUW:#[0-9]+]]
+ // CHECK-NEXT: [[T0:%.*]] = call i8* @__cxa_begin_catch(i8* %0) [[NUW:#[0-9]+]]
+ // CHECK-NEXT: call void @_ZSt9terminatev() [[NR_NUW:#[0-9]+]]
+ // CHECK-NEXT: unreachable
+
A *d() {
// CHECK: define [[A:%.*]]* @_ZN5test11dEv()
// CHECK: [[ACTIVE:%.*]] = alloca i1
@@ -157,7 +164,7 @@ namespace test2 {
// CHECK-NEXT: invoke void @_ZN5test21AC1Ei([[A]]* [[CAST]], i32 5)
// CHECK: ret [[A]]* [[CAST]]
// CHECK: invoke void @_ZN5test21AdlEPvm(i8* [[NEW]], i64 8)
- // CHECK: call void @_ZSt9terminatev()
+ // CHECK: call void @__clang_call_terminate(i8* {{%.*}}) [[NR_NUW]]
return new A(5);
}
}
@@ -183,7 +190,7 @@ namespace test3 {
// CHECK-NEXT: invoke void @_ZN5test31AC1Ei([[A]]* [[CAST]], i32 5)
// CHECK: ret [[A]]* [[CAST]]
// CHECK: invoke void @_ZN5test31AdlEPvS1_d(i8* [[NEW]], i8* [[FOO]], double [[BAR]])
- // CHECK: call void @_ZSt9terminatev()
+ // CHECK: call void @__clang_call_terminate(i8* {{%.*}}) [[NR_NUW]]
return new(foo(),bar()) A(5);
}
@@ -274,7 +281,7 @@ namespace test5 {
// CHECK-NEXT: invoke void @_ZN5test51TC1Ev([[T_T]]* [[T]])
// CHECK: invoke void @_ZN5test51AC1ERKS0_RKNS_1TE([[A_T]]* [[A]], [[A_T]]* [[SRC]], [[T_T]]* [[T]])
// CHECK: invoke void @_ZN5test51TD1Ev([[T_T]]* [[T]])
- // CHECK: call i8* @__cxa_begin_catch(i8* [[EXN]]) nounwind
+ // CHECK: call i8* @__cxa_begin_catch(i8* [[EXN]]) [[NUW]]
// CHECK-NEXT: invoke void @_ZN5test51AD1Ev([[A_T]]* [[A]])
// CHECK: call void @__cxa_end_catch()
void test() {
@@ -451,3 +458,72 @@ namespace test10 {
// CHECK: invoke void @__cxa_rethrow()
// CHECK: unreachable
}
+
+// Ensure that an exception in a constructor destroys
+// already-constructed array members. PR14514
+namespace test11 {
+ struct A {
+ A();
+ ~A() {}
+ };
+
+ struct C {
+ A single;
+ A array[2][3];
+
+ C();
+ };
+
+ C::C() {
+ throw 0;
+ }
+ // CHECK: define void @_ZN6test111CC2Ev(
+ // CHECK: [[THIS:%.*]] = load [[C:%.*]]** {{%.*}}
+ // Construct single.
+ // CHECK-NEXT: [[SINGLE:%.*]] = getelementptr inbounds [[C]]* [[THIS]], i32 0, i32 0
+ // CHECK-NEXT: call void @_ZN6test111AC1Ev([[A:%.*]]* [[SINGLE]])
+ // Construct array.
+ // CHECK-NEXT: [[ARRAY:%.*]] = getelementptr inbounds [[C]]* [[THIS]], i32 0, i32 1
+ // CHECK-NEXT: [[ARRAYBEGIN:%.*]] = getelementptr inbounds [2 x [3 x [[A]]]]* [[ARRAY]], i32 0, i32 0, i32 0
+ // CHECK-NEXT: [[ARRAYEND:%.*]] = getelementptr inbounds [[A]]* [[ARRAYBEGIN]], i64 6
+ // CHECK-NEXT: br label
+ // CHECK: [[CUR:%.*]] = phi [[A]]* [ [[ARRAYBEGIN]], {{%.*}} ], [ [[NEXT:%.*]], {{%.*}} ]
+ // CHECK-NEXT: invoke void @_ZN6test111AC1Ev([[A:%.*]]* [[CUR]])
+ // CHECK: [[NEXT]] = getelementptr inbounds [[A]]* [[CUR]], i64 1
+ // CHECK-NEXT: [[DONE:%.*]] = icmp eq [[A]]* [[NEXT]], [[ARRAYEND]]
+ // CHECK-NEXT: br i1 [[DONE]],
+ // throw 0;
+ // CHECK: invoke void @__cxa_throw(
+ // Landing pad 1, from constructor in array-initialization loop:
+ // CHECK: landingpad
+ // - First, destroy already-constructed bits of array.
+ // CHECK: [[EMPTY:%.*]] = icmp eq [[A]]* [[ARRAYBEGIN]], [[CUR]]
+ // CHECK-NEXT: br i1 [[EMPTY]]
+ // CHECK: [[AFTER:%.*]] = phi [[A]]* [ [[CUR]], {{%.*}} ], [ [[ELT:%.*]], {{%.*}} ]
+ // CHECK-NEXT: [[ELT]] = getelementptr inbounds [[A]]* [[AFTER]], i64 -1
+ // CHECK-NEXT: invoke void @_ZN6test111AD1Ev([[A]]* [[ELT]])
+ // CHECK: [[DONE:%.*]] = icmp eq [[A]]* [[ELT]], [[ARRAYBEGIN]]
+ // CHECK-NEXT: br i1 [[DONE]],
+ // - Next, chain to cleanup for single.
+ // CHECK: br label
+ // Landing pad 2, from throw site.
+ // CHECK: landingpad
+ // - First, destroy all of array.
+ // CHECK: [[ARRAYBEGIN:%.*]] = getelementptr inbounds [2 x [3 x [[A]]]]* [[ARRAY]], i32 0, i32 0, i32 0
+ // CHECK-NEXT: [[ARRAYEND:%.*]] = getelementptr inbounds [[A]]* [[ARRAYBEGIN]], i64 6
+ // CHECK-NEXT: br label
+ // CHECK: [[AFTER:%.*]] = phi [[A]]* [ [[ARRAYEND]], {{%.*}} ], [ [[ELT:%.*]], {{%.*}} ]
+ // CHECK-NEXT: [[ELT]] = getelementptr inbounds [[A]]* [[AFTER]], i64 -1
+ // CHECK-NEXT: invoke void @_ZN6test111AD1Ev([[A]]* [[ELT]])
+ // CHECK: [[DONE:%.*]] = icmp eq [[A]]* [[ELT]], [[ARRAYBEGIN]]
+ // CHECK-NEXT: br i1 [[DONE]],
+ // - Next, chain to cleanup for single.
+ // CHECK: br label
+ // Finally, the cleanup for single.
+ // CHECK: invoke void @_ZN6test111AD1Ev([[A]]* [[SINGLE]])
+ // CHECK: br label
+ // CHECK: resume
+ // (After this is a terminate landingpad.)
+}
+
+// CHECK: attributes [[NI_NR_NUW]] = { noinline noreturn nounwind }
diff --git a/test/CodeGenCXX/extern-c.cpp b/test/CodeGenCXX/extern-c.cpp
index ca5cd73..a8c4f0c 100644
--- a/test/CodeGenCXX/extern-c.cpp
+++ b/test/CodeGenCXX/extern-c.cpp
@@ -1,16 +1,38 @@
-// RUN: %clang_cc1 -emit-llvm %s -o %t
+// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s
namespace foo {
-// RUN: not grep "@a = global i32" %t
+// CHECK-NOT: @a = global i32
extern "C" int a;
-// RUN: not grep "@_ZN3foo1bE = global i32" %t
+// CHECK-NOT: @_ZN3foo1bE = global i32
extern int b;
-// RUN: grep "@_ZN3foo1cE = global i32" %t | count 1
+// CHECK: @_ZN3foo1cE = global i32
int c = 5;
-// RUN: not grep "@_ZN3foo1dE" %t
+// CHECK-NOT: @_ZN3foo1dE
extern "C" struct d;
}
+
+namespace test1 {
+ namespace {
+ struct X {};
+ }
+ extern "C" {
+ // CHECK: @test1_b = global
+ X test1_b = X();
+ }
+ void *use = &test1_b;
+ // CHECK: @_ZN5test13useE = global
+}
+
+namespace test2 {
+ namespace {
+ struct X {};
+ }
+
+ // CHECK: @test2_b = global
+ extern "C" X test2_b;
+ X test2_b;
+}
diff --git a/test/CodeGenCXX/global-array-destruction.cpp b/test/CodeGenCXX/global-array-destruction.cpp
index 076ef94..087d655 100644
--- a/test/CodeGenCXX/global-array-destruction.cpp
+++ b/test/CodeGenCXX/global-array-destruction.cpp
@@ -43,3 +43,20 @@ T t[2][3] = { 1.0, 2, 3.0, 4, 5.0, 6, 7.0, 8, 9.0, 10, 11.0, 12 };
// CHECK: call void @_ZN1TD1Ev
// CHECK: icmp eq {{.*}} @t
// CHECK: br i1 {{.*}}
+
+static T t2[2][3] = { 1.0, 2, 3.0, 4, 5.0, 6, 7.0, 8, 9.0, 10, 11.0, 12 };
+
+// CHECK: call {{.*}} @__cxa_atexit
+// CHECK: getelementptr inbounds ({{.*}} bitcast {{.*}}* @_ZL2t2 to %struct.T*), i64 6
+// CHECK: call void @_ZN1TD1Ev
+// CHECK: icmp eq {{.*}} @_ZL2t
+// CHECK: br i1 {{.*}}
+
+using U = T[2][3];
+U &&u = U{ {{1.0, 2}, {3.0, 4}, {5.0, 6}}, {{7.0, 8}, {9.0, 10}, {11.0, 12}} };
+
+// CHECK: call {{.*}} @__cxa_atexit
+// CHECK: getelementptr inbounds ([2 x [3 x {{.*}}]]* @_ZGR1u, i64 1, i64 0, i64 0)
+// CHECK: call void @_ZN1TD1Ev
+// CHECK: icmp eq {{.*}} @_ZGR1u
+// CHECK: br i1 {{.*}}
diff --git a/test/CodeGenCXX/global-dtor-no-atexit.cpp b/test/CodeGenCXX/global-dtor-no-atexit.cpp
index def97b2..7c4b6aa 100644
--- a/test/CodeGenCXX/global-dtor-no-atexit.cpp
+++ b/test/CodeGenCXX/global-dtor-no-atexit.cpp
@@ -5,12 +5,12 @@
// CHECK: call void @_ZN1AC1Ev([[A:%.*]]* @a)
// CHECK-NEXT: call i32 @atexit(void ()* @__dtor_a)
-// CHECK: define internal void @__dtor_a() nounwind
+// CHECK: define internal void @__dtor_a() [[NUW:#[0-9]+]]
// CHECK: call void @_ZN1AD1Ev([[A]]* @a)
// CHECK: call void @_ZN1AC1Ev([[A]]* @b)
// CHECK-NEXT: call i32 @atexit(void ()* @__dtor_b)
-// CHECK: define internal void @__dtor_b() nounwind
+// CHECK: define internal void @__dtor_b() [[NUW]]
// CHECK: call void @_ZN1AD1Ev([[A]]* @b)
class A {
@@ -33,12 +33,14 @@ A a, b;
// CHECK-NEXT: call i32 @atexit(void ()* @__dtor__ZZ4funcvE2a2)
// CHECK-NEXT: call void @__cxa_guard_release(i64* @_ZGVZ4funcvE2a2)
-// CHECK: define internal void @__dtor__ZZ4funcvE2a1() nounwind
+// CHECK: define internal void @__dtor__ZZ4funcvE2a1() [[NUW]]
// CHECK: call void @_ZN1AD1Ev([[A]]* @_ZZ4funcvE2a1)
-// CHECK: define internal void @__dtor__ZZ4funcvE2a2() nounwind
+// CHECK: define internal void @__dtor__ZZ4funcvE2a2() [[NUW]]
// CHECK: call void @_ZN1AD1Ev([[A]]* @_ZZ4funcvE2a2)
void func() {
static A a1, a2;
}
+
+// CHECK: attributes [[NUW]] = { nounwind }
diff --git a/test/CodeGenCXX/global-init.cpp b/test/CodeGenCXX/global-init.cpp
index 2a53ad9..426cf9c 100644
--- a/test/CodeGenCXX/global-init.cpp
+++ b/test/CodeGenCXX/global-init.cpp
@@ -200,4 +200,6 @@ namespace test7 {
// CHECK: call void [[TEST1_Z_INIT]]
// rdar://problem/8090834: this should be nounwind
-// CHECK-NOEXC: define internal void @_GLOBAL__I_a() nounwind section "__TEXT,__StaticInit,regular,pure_instructions" {
+// CHECK-NOEXC: define internal void @_GLOBAL__I_a() [[NUW:#[0-9]+]] section "__TEXT,__StaticInit,regular,pure_instructions" {
+
+// CHECK-NOEXC: attributes [[NUW]] = { nounwind }
diff --git a/test/CodeGenCXX/implicit-copy-assign-operator.cpp b/test/CodeGenCXX/implicit-copy-assign-operator.cpp
index 0ec89fc..79586fb 100644
--- a/test/CodeGenCXX/implicit-copy-assign-operator.cpp
+++ b/test/CodeGenCXX/implicit-copy-assign-operator.cpp
@@ -44,7 +44,7 @@ void test_D(D d1, D d2) {
// CHECK: {{call.*_ZN1AaSERS_}}
// CHECK: {{call.*_ZN1BaSERS_}}
// CHECK: {{call.*_ZN1CaSERKS_}}
-// CHECK: {{call void @llvm.memcpy.p0i8.p0i8.i64.*i64 24}}
+// CHECK: {{call void @llvm.memcpy.p0i8.p0i8.i64.*i64 28}}
// CHECK: {{call.*_ZN1BaSERS_}}
// CHECK: br
// CHECK: {{call.*_ZN1CaSERKS_}}
diff --git a/test/CodeGenCXX/implicit-copy-constructor.cpp b/test/CodeGenCXX/implicit-copy-constructor.cpp
index 8a3a422..24e84d5 100644
--- a/test/CodeGenCXX/implicit-copy-constructor.cpp
+++ b/test/CodeGenCXX/implicit-copy-constructor.cpp
@@ -46,7 +46,7 @@ void f(D d) {
// CHECK: call void @_ZN1AD1Ev
// CHECK: call void @_ZN1AC2ERS_
// CHECK: call void @_ZN1BC2ERS_
-// CHECK: {{call void @llvm.memcpy.p0i8.p0i8.i64.*i64 24}}
+// CHECK: {{call void @llvm.memcpy.p0i8.p0i8.i64.*i64 28}}
// CHECK: call void @_ZN1BC1ERS_
// CHECK: br
// CHECK: {{icmp ult.*, 2}}
@@ -54,8 +54,7 @@ void f(D d) {
// CHECK: call void @_ZN1AC1Ev
// CHECK: call void @_ZN1CC1ERS_1A
// CHECK: call void @_ZN1AD1Ev
-// CHECK: {{call void @llvm.memcpy.p0i8.p0i8.i64.*i64 288}}
-// CHECK: {{call void @llvm.memcpy.p0i8.p0i8.i64.*i64 12}}
+// CHECK: {{call void @llvm.memcpy.p0i8.p0i8.i64.*i64 300}}
// CHECK: ret void
diff --git a/test/CodeGenCXX/inheriting-constructor.cpp b/test/CodeGenCXX/inheriting-constructor.cpp
index a998402..adb9f6d 100644
--- a/test/CodeGenCXX/inheriting-constructor.cpp
+++ b/test/CodeGenCXX/inheriting-constructor.cpp
@@ -1,11 +1,18 @@
// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin10 -emit-llvm -o - %s | FileCheck %s
-// XFAIL: *
-
// PR12219
struct A { A(int); virtual ~A(); };
struct B : A { using A::A; ~B(); };
B::~B() {}
+
+B b(123);
+
// CHECK: define void @_ZN1BD0Ev
// CHECK: define void @_ZN1BD1Ev
// CHECK: define void @_ZN1BD2Ev
+
+// CHECK: define linkonce_odr void @_ZN1BC1Ei(
+// CHECK: call void @_ZN1BC2Ei(
+
+// CHECK: define linkonce_odr void @_ZN1BC2Ei(
+// CHECK: call void @_ZN1AC2Ei(
diff --git a/test/CodeGenCXX/key-function-vtable.cpp b/test/CodeGenCXX/key-function-vtable.cpp
index 8e474bd..0ecd898 100644
--- a/test/CodeGenCXX/key-function-vtable.cpp
+++ b/test/CodeGenCXX/key-function-vtable.cpp
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-none-linux-gnu %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -triple arm-apple-darwin %s -emit-llvm -o - | FileCheck %s
// Simple key function test
struct testa { virtual void a(); };
diff --git a/test/CodeGenCXX/lambda-expressions.cpp b/test/CodeGenCXX/lambda-expressions.cpp
index cee4f17..68ae68f 100644
--- a/test/CodeGenCXX/lambda-expressions.cpp
+++ b/test/CodeGenCXX/lambda-expressions.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10.0.0 -emit-llvm -o - %s -fexceptions -std=c++11 | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10.0.0 -fblocks -emit-llvm -o - %s -fexceptions -std=c++11 | FileCheck %s
// CHECK-NOT: @unused
auto unused = [](int i) { return i+1; };
@@ -80,6 +80,26 @@ int g() {
return [] { return r; } ();
};
+// PR14773
+// CHECK: [[ARRVAL:%[0-9a-zA-Z]*]] = load i32* getelementptr inbounds ([0 x i32]* bitcast (<{}>* @_ZZ14staticarrayrefvE5array to [0 x i32]*), i32 0, i64 0), align 4
+// CHECK-NEXT: store i32 [[ARRVAL]]
+void staticarrayref(){
+ static int array[] = {};
+ (void)[](){
+ int (&xxx)[0] = array;
+ int y = xxx[0];
+ }();
+}
+
+// CHECK: define internal void @"_ZZ1hvEN3$_88__invokeEv"(%struct.A* noalias sret %agg.result) {{.*}} {
+// CHECK-NOT: =
+// CHECK: call void @"_ZZ1hvENK3$_8clEv"(%struct.A* sret %agg.result,
+// CHECK-NEXT: ret void
+struct A { ~A(); };
+void h() {
+ A (*h)() = [] { return A(); };
+}
+
// CHECK: define internal i32 @"_ZZ1fvEN3$_58__invokeEii"
// CHECK: store i32
// CHECK-NEXT: store i32
@@ -89,3 +109,14 @@ int g() {
// CHECK-NEXT: ret i32
// CHECK: define internal void @"_ZZ1e1ES_bEN3$_4D2Ev"
+
+// <rdar://problem/12778708>
+struct XXX {};
+void nestedCapture () {
+ XXX localKey;
+ ^() {
+ [&]() {
+ ^{ XXX k = localKey; };
+ };
+ };
+}
diff --git a/test/CodeGenCXX/mangle-ms-back-references-pr13207.cpp b/test/CodeGenCXX/mangle-ms-back-references-pr13207.cpp
index 27b4768..fbc6492 100644
--- a/test/CodeGenCXX/mangle-ms-back-references-pr13207.cpp
+++ b/test/CodeGenCXX/mangle-ms-back-references-pr13207.cpp
@@ -1,7 +1,5 @@
// RUN: %clang_cc1 -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s
-// FIXME: add tests for return types with complex templates when PR13389 is fixed.
-
template<class X, class Y, class Z>
class A {};
template<class X>
@@ -15,6 +13,8 @@ void foo_abb(A<char, B<char>, B<char> >) {}
// CHECK: "\01?foo_abb@@YAXV?$A@DV?$B@D@@V1@@@@Z"
void foo_abc(A<char, B<char>, C<char> >) {}
// CHECK: "\01?foo_abc@@YAXV?$A@DV?$B@D@@V?$C@D@@@@@Z"
+void foo_bt(bool a, B<bool(bool)> b) {}
+// CHECK: "\01?foo_bt@@YAX_NV?$B@$$A6A_N_N@Z@@@Z"
namespace N {
template<class X, class Y, class Z>
diff --git a/test/CodeGenCXX/mangle-ms-templates.cpp b/test/CodeGenCXX/mangle-ms-templates.cpp
index e16fe93..d0e8af4 100644
--- a/test/CodeGenCXX/mangle-ms-templates.cpp
+++ b/test/CodeGenCXX/mangle-ms-templates.cpp
@@ -78,3 +78,16 @@ namespace space {
void use() {
space::foo(42);
}
+
+// PR13455
+typedef void (*FunctionPointer)(void);
+
+template <FunctionPointer function>
+void FunctionPointerTemplate() {
+ function();
+}
+
+void spam() {
+ FunctionPointerTemplate<spam>();
+// CHECK: "\01??$FunctionPointerTemplate@$1?spam@@YAXXZ@@YAXXZ"
+}
diff --git a/test/CodeGenCXX/mangle-ms-vector-types.cpp b/test/CodeGenCXX/mangle-ms-vector-types.cpp
new file mode 100644
index 0000000..64cb725
--- /dev/null
+++ b/test/CodeGenCXX/mangle-ms-vector-types.cpp
@@ -0,0 +1,33 @@
+// RUN: %clang_cc1 -fms-extensions -ffreestanding -target-feature +avx -emit-llvm %s -o - -cxx-abi microsoft -triple=i686-pc-win32 | FileCheck %s
+
+#include <xmmintrin.h>
+#include <emmintrin.h>
+#include <immintrin.h>
+
+void foo64(__m64) {}
+// CHECK: define void @"\01?foo64@@YAXT__m64@@@Z"
+
+void foo128(__m128) {}
+// CHECK: define void @"\01?foo128@@YAXT__m128@@@Z"
+
+void foo128d(__m128d) {}
+// CHECK: define void @"\01?foo128d@@YAXU__m128d@@@Z"
+
+void foo128i(__m128i) {}
+// CHECK: define void @"\01?foo128i@@YAXT__m128i@@@Z"
+
+void foo256(__m256) {}
+// CHECK: define void @"\01?foo256@@YAXT__m256@@@Z"
+
+void foo256d(__m256d) {}
+// CHECK: define void @"\01?foo256d@@YAXU__m256d@@@Z"
+
+void foo256i(__m256i) {}
+// CHECK: define void @"\01?foo256i@@YAXT__m256i@@@Z"
+
+// We have a custom mangling for vector types not standardized by Intel.
+void foov8hi(__v8hi) {}
+// CHECK: define void @"\01?foov8hi@@YAXT__clang_vec8_F@@@Z"
+
+// Clang does not support vectors of complex types, so we can't test the
+// mangling of them.
diff --git a/test/CodeGenCXX/mangle-ms.cpp b/test/CodeGenCXX/mangle-ms.cpp
index 0edb4b4..6441d67 100644
--- a/test/CodeGenCXX/mangle-ms.cpp
+++ b/test/CodeGenCXX/mangle-ms.cpp
@@ -3,6 +3,7 @@
// CHECK: @"\01?a@@3HA"
// CHECK: @"\01?b@N@@3HA"
+// CHECK: @"\01?anonymous@?A@N@@3HA"
// CHECK: @c
// CHECK: @"\01?d@foo@@0FB"
// CHECK: @"\01?e@foo@@1JC"
@@ -24,10 +25,16 @@
int a;
-namespace N { int b; }
+namespace N {
+ int b;
+
+ namespace {
+ int anonymous;
+ }
+}
static int c;
-int _c(void) {return c;}
+int _c(void) {return N::anonymous + c;}
// CHECK: @"\01?_c@@YAHXZ"
class foo {
diff --git a/test/CodeGenCXX/mangle.cpp b/test/CodeGenCXX/mangle.cpp
index ba1b3bf..e7955a8 100644
--- a/test/CodeGenCXX/mangle.cpp
+++ b/test/CodeGenCXX/mangle.cpp
@@ -218,7 +218,7 @@ struct S7 {
// PR5139
// CHECK: @_ZN2S7C1Ev
// CHECK: @_ZN2S7C2Ev
-// CHECK: @"_ZN2S73$_0C1Ev"
+// CHECK: @_ZN2S7Ut_C1Ev
S7::S7() {}
// PR5063
@@ -852,3 +852,26 @@ namespace test36 {
// CHECK: define weak_odr {{.*}} @_ZN6test362f1IJifEEENS_1AIXsZfp_EEEDpT_
template A<2> f1(int, float);
}
+
+namespace test37 {
+ struct foo {
+ struct {
+ } a;
+ typedef struct { } b;
+ typedef struct { } *c;
+ struct {
+ } d;
+ };
+ template<typename T> void func(T) { }
+ void test() {
+ // CHECK: define linkonce_odr void @_ZN6test374funcINS_3fooUt_EEEvT_
+ func(foo().a);
+ // CHECK: define linkonce_odr void @_ZN6test374funcINS_3fooUt0_EEEvT_
+ func(*foo::c());
+ // CHECK: define linkonce_odr void @_ZN6test374funcINS_3fooUt1_EEEvT_
+ func(foo().d);
+ }
+}
+
+// CHECK: define void @_Z6ASfuncPU3AS3i
+void ASfunc(__attribute__((address_space(3))) int* x) {}
diff --git a/test/CodeGenCXX/member-functions.cpp b/test/CodeGenCXX/member-functions.cpp
index 1310eb0..75b354c 100644
--- a/test/CodeGenCXX/member-functions.cpp
+++ b/test/CodeGenCXX/member-functions.cpp
@@ -1,66 +1,85 @@
-// RUN: %clang_cc1 -emit-llvm %s -triple x86_64-apple-darwin9 -o %t
+// RUN: %clang_cc1 -emit-llvm -triple x86_64-apple-darwin9 -o - %s | FileCheck %s
+
struct C {
void f();
void g(int, ...);
};
-// RUN: grep "define void @_ZN1C1fEv" %t | count 1
+// CHECK: define void @_ZN1C1fEv
void C::f() {
}
+// CHECK: define void @_Z5test1v
void test1() {
C c;
-
-// RUN: grep "call void @_ZN1C1fEv" %t | count 1
+
+ // CHECK: call void @_ZN1C1fEv
c.f();
-
-// RUN: grep "call void (.struct.C\*, i32, ...)\* @_ZN1C1gEiz" %t | count 1
+
+ // CHECK: call void (%struct.C*, i32, ...)* @_ZN1C1gEiz
c.g(1, 2, 3);
}
struct S {
- // RUN: grep "define linkonce_odr void @_ZN1SC1Ev.*unnamed_addr" %t
inline S() { }
- // RUN: grep "define linkonce_odr void @_ZN1SC1Ev.*unnamed_addr" %t
inline ~S() { }
-
-
- // RUN: grep "define linkonce_odr void @_ZN1S9f_inline1Ev" %t
+
void f_inline1() { }
- // RUN: grep "define linkonce_odr void @_ZN1S9f_inline2Ev" %t
inline void f_inline2() { }
-
- // RUN: grep "define linkonce_odr void @_ZN1S1gEv" %t
+
static void g() { }
-
static void f();
- // RUN: grep "define linkonce_odr void @_ZN1S1vEv.*unnamed_addr" %t
virtual void v() {}
};
-// RUN: grep "define void @_ZN1S1fEv" %t
+// CHECK: define void @_ZN1S1fEv
void S::f() {
}
void test2() {
S s;
-
+
s.f_inline1();
s.f_inline2();
-
+
S::g();
-
}
+// S::S()
+// CHECK: define linkonce_odr void @_ZN1SC1Ev{{.*}} unnamed_addr
+
+// S::f_inline1()
+// CHECK: define linkonce_odr void @_ZN1S9f_inline1Ev
+
+// S::f_inline2()
+// CHECK: define linkonce_odr void @_ZN1S9f_inline2Ev
+
+// S::g()
+// CHECK: define linkonce_odr void @_ZN1S1gEv
+
+// S::~S()
+// CHECK: define linkonce_odr void @_ZN1SD1Ev{{.*}} unnamed_addr
+
struct T {
T operator+(const T&);
};
+// CHECK: define void @_Z5test3v
void test3() {
T t1, t2;
-
- // RUN: grep "call void @_ZN1TplERKS_" %t
+
+ // CHECK: call void @_ZN1TplERKS_
T result = t1 + t2;
}
+
+// S::~S()
+// CHECK: define linkonce_odr void @_ZN1SD2Ev{{.*}} unnamed_addr
+
+// S::S()
+// CHECK: define linkonce_odr void @_ZN1SC2Ev{{.*}} unnamed_addr
+
+// S::v()
+// CHECK: define linkonce_odr void @_ZN1S1vEv{{.*}}unnamed_addr
+
diff --git a/test/CodeGenCXX/member-initializers.cpp b/test/CodeGenCXX/member-initializers.cpp
index 244a164..c22b99d 100644
--- a/test/CodeGenCXX/member-initializers.cpp
+++ b/test/CodeGenCXX/member-initializers.cpp
@@ -12,7 +12,7 @@ struct B : A {
int i;
};
-// CHECK: define i32 @_Z1fv() nounwind
+// CHECK: define i32 @_Z1fv() #0
int f() {
B b;
@@ -21,7 +21,7 @@ int f() {
}
// Test that we don't try to fold the default value of j when initializing i.
-// CHECK: define i32 @_Z9test_foldv() nounwind
+// CHECK: define i32 @_Z9test_foldv() [[NUW_RN:#[0-9]+]]
int test_fold() {
struct A {
A(const int j = 1) : i(j) { }
@@ -32,3 +32,4 @@ int test_fold() {
return A(2).i;
}
+// CHECK: attributes [[NUW_RN]] = { nounwind readnone{{.*}} }
diff --git a/test/CodeGenCXX/microsoft-abi-array-cookies.cpp b/test/CodeGenCXX/microsoft-abi-array-cookies.cpp
index e07b097..1ba1f6a 100644
--- a/test/CodeGenCXX/microsoft-abi-array-cookies.cpp
+++ b/test/CodeGenCXX/microsoft-abi-array-cookies.cpp
@@ -5,7 +5,7 @@ struct ClassWithoutDtor {
};
void check_array_no_cookies() {
-// CHECK: define void @"\01?check_array_no_cookies@@YAXXZ"() nounwind
+// CHECK: define void @"\01?check_array_no_cookies@@YAXXZ"() [[NUW:#[0-9]+]]
// CHECK: call noalias i8* @"\01??_U@YAPAXI@Z"(i32 42)
ClassWithoutDtor *array = new ClassWithoutDtor[42];
@@ -57,3 +57,5 @@ void check_array_cookies_aligned() {
// CHECK: [[ARRAY_AS_CHAR:%.*]] = bitcast [[CLASS]]*
// CHECK: getelementptr inbounds i8* [[ARRAY_AS_CHAR]], i64 -8
}
+
+// CHECK: attributes [[NUW]] = { nounwind{{.*}} }
diff --git a/test/CodeGenCXX/microsoft-abi-constructors.cpp b/test/CodeGenCXX/microsoft-abi-constructors.cpp
deleted file mode 100644
index 89731ff..0000000
--- a/test/CodeGenCXX/microsoft-abi-constructors.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-// RUN: %clang_cc1 -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s
-
-class A {
- public:
- A() { }
- ~A() { }
-};
-
-void no_contstructor_destructor_infinite_recursion() {
- A a;
-
-// CHECK: define linkonce_odr x86_thiscallcc %class.A* @"\01??0A@@QAE@XZ"(%class.A* %this)
-// CHECK: [[THIS_ADDR:%[.0-9A-Z_a-z]+]] = alloca %class.A*, align 4
-// CHECK-NEXT: store %class.A* %this, %class.A** [[THIS_ADDR]], align 4
-// CHECK-NEXT: [[T1:%[.0-9A-Z_a-z]+]] = load %class.A** [[THIS_ADDR]]
-// CHECK-NEXT: ret %class.A* [[T1]]
-// CHECK-NEXT: }
-
-// Make sure that the destructor doesn't call itself:
-// CHECK: define {{.*}} @"\01??1A@@QAE@XZ"
-// CHECK-NOT: call void @"\01??1A@@QAE@XZ"
-// CHECK: ret
-}
-
diff --git a/test/CodeGenCXX/microsoft-abi-default-cc.cpp b/test/CodeGenCXX/microsoft-abi-default-cc.cpp
index d0d25ce..7f2fc0a 100644
--- a/test/CodeGenCXX/microsoft-abi-default-cc.cpp
+++ b/test/CodeGenCXX/microsoft-abi-default-cc.cpp
@@ -28,8 +28,8 @@ public:
void baz();
void METHOD_CC qux();
- void static_baz();
- void __cdecl static_qux();
+ static void static_baz();
+ static void __cdecl static_qux();
};
void METHOD_CC A::baz() {}
diff --git a/test/CodeGenCXX/microsoft-abi-member-pointers.cpp b/test/CodeGenCXX/microsoft-abi-member-pointers.cpp
new file mode 100755
index 0000000..997e007
--- /dev/null
+++ b/test/CodeGenCXX/microsoft-abi-member-pointers.cpp
@@ -0,0 +1,51 @@
+// RUN: %clang_cc1 -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s
+
+struct POD {
+ int a;
+ int b;
+};
+
+void podMemPtrs() {
+ int POD::*memptr;
+ memptr = &POD::a;
+ memptr = &POD::b;
+ if (memptr)
+ memptr = 0;
+// Check that member pointers use the right offsets and that null is -1.
+// CHECK: define void @"\01?podMemPtrs@@YAXXZ"() #0 {
+// CHECK: %[[memptr:.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 0, i32* %[[memptr]], align 4
+// CHECK-NEXT: store i32 4, i32* %[[memptr]], align 4
+// CHECK-NEXT: %[[memptr_val:.*]] = load i32* %[[memptr]], align 4
+// CHECK-NEXT: %{{.*}} = icmp ne i32 %[[memptr_val]], -1
+// CHECK-NEXT: br i1 %{{.*}}, label %{{.*}}, label %{{.*}}
+// CHECK: store i32 -1, i32* %[[memptr]], align 4
+// CHECK: ret void
+// CHECK: }
+}
+
+struct Polymorphic {
+ virtual void myVirtual();
+ int a;
+ int b;
+};
+
+void polymorphicMemPtrs() {
+ int Polymorphic::*memptr;
+ memptr = &Polymorphic::a;
+ memptr = &Polymorphic::b;
+ if (memptr)
+ memptr = 0;
+// Member pointers for polymorphic classes include the vtable slot in their
+// offset and use 0 to represent null.
+// CHECK: define void @"\01?polymorphicMemPtrs@@YAXXZ"() #0 {
+// CHECK: %[[memptr:.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 4, i32* %[[memptr]], align 4
+// CHECK-NEXT: store i32 8, i32* %[[memptr]], align 4
+// CHECK-NEXT: %[[memptr_val:.*]] = load i32* %[[memptr]], align 4
+// CHECK-NEXT: %{{.*}} = icmp ne i32 %[[memptr_val]], 0
+// CHECK-NEXT: br i1 %{{.*}}, label %{{.*}}, label %{{.*}}
+// CHECK: store i32 0, i32* %[[memptr]], align 4
+// CHECK: ret void
+// CHECK: }
+}
diff --git a/test/CodeGenCXX/microsoft-abi-static-initializers.cpp b/test/CodeGenCXX/microsoft-abi-static-initializers.cpp
index 448f1ee..35e343b 100644
--- a/test/CodeGenCXX/microsoft-abi-static-initializers.cpp
+++ b/test/CodeGenCXX/microsoft-abi-static-initializers.cpp
@@ -5,12 +5,12 @@ struct S {
~S() {}
} s;
-// CHECK: define internal void [[INIT_s:@.*global_var.*]] nounwind
+// CHECK: define internal void [[INIT_s:@.*global_var.*]] [[NUW:#[0-9]+]]
// CHECK: %{{[.0-9A-Z_a-z]+}} = call x86_thiscallcc %struct.S* @"\01??0S@@QAE@XZ"
// CHECK: call i32 @atexit(void ()* @"__dtor_\01?s@@3US@@A")
// CHECK: ret void
-// CHECK: define internal void @"__dtor_\01?s@@3US@@A"() nounwind {
+// CHECK: define internal void @"__dtor_\01?s@@3US@@A"() [[NUW]] {
// CHECK: call x86_thiscallcc void @"\01??1S@@QAE@XZ"
// CHECK: ret void
@@ -33,7 +33,7 @@ void force_usage() {
(void)B<int>::foo; // (void) - force usage
}
-// CHECK: define internal void [[INIT_foo:@.*global_var.*]] nounwind
+// CHECK: define internal void [[INIT_foo:@.*global_var.*]] [[NUW]]
// CHECK: %{{[.0-9A-Z_a-z]+}} = call x86_thiscallcc %class.A* @"\01??0A@@QAE@XZ"
// CHECK: call i32 @atexit(void ()* [[FOO_DTOR:@"__dtor_.*foo@.*]])
// CHECK: ret void
@@ -46,7 +46,9 @@ void force_usage() {
// CHECK: call x86_thiscallcc void @"\01??1A@@QAE@XZ"{{.*}}foo
// CHECK: ret void
-// CHECK: define internal void @_GLOBAL__I_a() nounwind {
+// CHECK: define internal void @_GLOBAL__I_a() [[NUW]] {
// CHECK: call void [[INIT_s]]
// CHECK: call void [[INIT_foo]]
// CHECK: ret void
+
+// CHECK: attributes [[NUW]] = { nounwind }
diff --git a/test/CodeGenCXX/microsoft-abi-structors.cpp b/test/CodeGenCXX/microsoft-abi-structors.cpp
new file mode 100644
index 0000000..864540d
--- /dev/null
+++ b/test/CodeGenCXX/microsoft-abi-structors.cpp
@@ -0,0 +1,215 @@
+// RUN: %clang_cc1 -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 -fno-rtti > %t 2>&1
+// RUN: FileCheck %s < %t
+// Using a different check prefix as the inline destructors might be placed
+// anywhere in the output.
+// RUN: FileCheck --check-prefix=DTORS %s < %t
+
+namespace basic {
+
+class A {
+ public:
+ A() { }
+ ~A() { }
+};
+
+void no_constructor_destructor_infinite_recursion() {
+ A a;
+
+// CHECK: define linkonce_odr x86_thiscallcc %"class.basic::A"* @"\01??0A@basic@@QAE@XZ"(%"class.basic::A"* %this)
+// CHECK: [[THIS_ADDR:%[.0-9A-Z_a-z]+]] = alloca %"class.basic::A"*, align 4
+// CHECK-NEXT: store %"class.basic::A"* %this, %"class.basic::A"** [[THIS_ADDR]], align 4
+// CHECK-NEXT: [[T1:%[.0-9A-Z_a-z]+]] = load %"class.basic::A"** [[THIS_ADDR]]
+// CHECK-NEXT: ret %"class.basic::A"* [[T1]]
+// CHECK-NEXT: }
+
+// Make sure that the destructor doesn't call itself:
+// CHECK: define {{.*}} @"\01??1A@basic@@QAE@XZ"
+// CHECK-NOT: call void @"\01??1A@basic@@QAE@XZ"
+// CHECK: ret
+}
+
+struct B {
+ B();
+};
+
+// Tests that we can define constructors outside the class (PR12784).
+B::B() {
+ // CHECK: define x86_thiscallcc %"struct.basic::B"* @"\01??0B@basic@@QAE@XZ"(%"struct.basic::B"* %this)
+ // CHECK: ret
+}
+
+struct C {
+ virtual ~C() {
+// Complete destructor first:
+// DTORS: define {{.*}} x86_thiscallcc void @"\01??1C@basic@@UAE@XZ"(%"struct.basic::C"* %this)
+
+// Then, the scalar deleting destructor (used in the vtable):
+// FIXME: add a test that verifies that the out-of-line scalar deleting
+// destructor is linkonce_odr too.
+// DTORS: define linkonce_odr x86_thiscallcc void @"\01??_GC@basic@@UAEPAXI@Z"(%"struct.basic::C"* %this, i1 zeroext %should_call_delete)
+// DTORS: %[[FROMBOOL:[0-9a-z]+]] = zext i1 %should_call_delete to i8
+// DTORS-NEXT: store i8 %[[FROMBOOL]], i8* %[[SHOULD_DELETE_VAR:[0-9a-z._]+]], align 1
+// DTORS: %[[SHOULD_DELETE_VALUE:[0-9a-z._]+]] = load i8* %[[SHOULD_DELETE_VAR]]
+// DTORS: call x86_thiscallcc void @"\01??1C@basic@@UAE@XZ"(%"struct.basic::C"* %[[THIS:[0-9a-z]+]])
+// DTORS-NEXT: %[[CONDITION:[0-9]+]] = icmp eq i8 %[[SHOULD_DELETE_VALUE]], 0
+// DTORS-NEXT: br i1 %[[CONDITION]], label %[[CONTINUE_LABEL:[0-9a-z._]+]], label %[[CALL_DELETE_LABEL:[0-9a-z._]+]]
+//
+// DTORS: [[CALL_DELETE_LABEL]]
+// DTORS-NEXT: %[[THIS_AS_VOID:[0-9a-z]+]] = bitcast %"struct.basic::C"* %[[THIS]] to i8*
+// DTORS-NEXT: call void @"\01??3@YAXPAX@Z"(i8* %[[THIS_AS_VOID]]) [[NUW:#[0-9]+]]
+// DTORS-NEXT: br label %[[CONTINUE_LABEL]]
+//
+// DTORS: [[CONTINUE_LABEL]]
+// DTORS-NEXT: ret void
+ }
+ virtual void foo();
+};
+
+// Emits the vftable in the output.
+void C::foo() {}
+
+void check_vftable_offset() {
+ C c;
+// The vftable pointer should point at the beginning of the vftable.
+// CHECK: [[THIS_PTR:%[0-9]+]] = bitcast %"struct.basic::C"* {{.*}} to i8***
+// CHECK: store i8** getelementptr inbounds ([2 x i8*]* @"\01??_7C@basic@@6B@", i64 0, i64 0), i8*** [[THIS_PTR]]
+}
+
+void call_complete_dtor(C *obj_ptr) {
+// CHECK: define void @"\01?call_complete_dtor@basic@@YAXPAUC@1@@Z"(%"struct.basic::C"* %obj_ptr)
+ obj_ptr->~C();
+// CHECK: %[[OBJ_PTR_VALUE:.*]] = load %"struct.basic::C"** %{{.*}}, align 4
+// CHECK-NEXT: %[[PVTABLE:.*]] = bitcast %"struct.basic::C"* %[[OBJ_PTR_VALUE]] to void (%"struct.basic::C"*, i1)***
+// CHECK-NEXT: %[[VTABLE:.*]] = load void (%"struct.basic::C"*, i1)*** %[[PVTABLE]]
+// CHECK-NEXT: %[[PVDTOR:.*]] = getelementptr inbounds void (%"struct.basic::C"*, i1)** %[[VTABLE]], i64 0
+// CHECK-NEXT: %[[VDTOR:.*]] = load void (%"struct.basic::C"*, i1)** %[[PVDTOR]]
+// CHECK-NEXT: call x86_thiscallcc void %[[VDTOR]](%"struct.basic::C"* %[[OBJ_PTR_VALUE]], i1 zeroext false)
+// CHECK-NEXT: ret void
+}
+
+void call_deleting_dtor(C *obj_ptr) {
+// CHECK: define void @"\01?call_deleting_dtor@basic@@YAXPAUC@1@@Z"(%"struct.basic::C"* %obj_ptr)
+ delete obj_ptr;
+// CHECK: %[[OBJ_PTR_VALUE:.*]] = load %"struct.basic::C"** %{{.*}}, align 4
+// CHECK: br i1 {{.*}}, label %[[DELETE_NULL:.*]], label %[[DELETE_NOTNULL:.*]]
+
+// CHECK: [[DELETE_NOTNULL]]
+// CHECK-NEXT: %[[PVTABLE:.*]] = bitcast %"struct.basic::C"* %[[OBJ_PTR_VALUE]] to void (%"struct.basic::C"*, i1)***
+// CHECK-NEXT: %[[VTABLE:.*]] = load void (%"struct.basic::C"*, i1)*** %[[PVTABLE]]
+// CHECK-NEXT: %[[PVDTOR:.*]] = getelementptr inbounds void (%"struct.basic::C"*, i1)** %[[VTABLE]], i64 0
+// CHECK-NEXT: %[[VDTOR:.*]] = load void (%"struct.basic::C"*, i1)** %[[PVDTOR]]
+// CHECK-NEXT: call x86_thiscallcc void %[[VDTOR]](%"struct.basic::C"* %[[OBJ_PTR_VALUE]], i1 zeroext true)
+// CHECK: ret void
+}
+
+struct D {
+ static int foo();
+
+ D() {
+ static int ctor_static = foo();
+ // CHECK that the static in the ctor gets mangled correctly:
+ // CHECK: @"\01?ctor_static@?1???0D@basic@@QAE@XZ@4HA"
+ }
+ ~D() {
+ static int dtor_static = foo();
+ // CHECK that the static in the dtor gets mangled correctly:
+ // CHECK: @"\01?dtor_static@?1???1D@basic@@QAE@XZ@4HA"
+ }
+};
+
+void use_D() { D c; }
+
+// DTORS: attributes [[NUW]] = { nounwind{{.*}} }
+
+} // end namespace basic
+
+
+namespace constructors {
+
+struct A {
+ A() {}
+};
+
+struct B : A {
+ B();
+ ~B();
+};
+
+B::B() {
+ // CHECK: define x86_thiscallcc %"struct.constructors::B"* @"\01??0B@constructors@@QAE@XZ"(%"struct.constructors::B"* %this)
+ // CHECK: call x86_thiscallcc %"struct.constructors::A"* @"\01??0A@constructors@@QAE@XZ"(%"struct.constructors::A"* %{{.*}})
+ // CHECK: ret
+}
+
+struct C : virtual A {
+ C();
+};
+
+C::C() {
+ // CHECK: define x86_thiscallcc %"struct.constructors::C"* @"\01??0C@constructors@@QAE@XZ"(%"struct.constructors::C"* %this, i32 %is_most_derived)
+ // TODO: make sure this works in the Release build too;
+ // CHECK: store i32 %is_most_derived, i32* %[[IS_MOST_DERIVED_VAR:.*]], align 4
+ // CHECK: %[[IS_MOST_DERIVED_VAL:.*]] = load i32* %[[IS_MOST_DERIVED_VAR]]
+ // CHECK: %[[SHOULD_CALL_VBASE_CTORS:.*]] = icmp ne i32 %[[IS_MOST_DERIVED_VAL]], 0
+ // CHECK: br i1 %[[SHOULD_CALL_VBASE_CTORS]], label %[[INIT_VBASES:.*]], label %[[SKIP_VBASES:.*]]
+ //
+ // CHECK: [[INIT_VBASES]]
+ // CHECK-NEXT: bitcast %"struct.constructors::C"* %{{.*}} to %"struct.constructors::A"*
+ // CHECK-NEXT: call x86_thiscallcc %"struct.constructors::A"* @"\01??0A@constructors@@QAE@XZ"(%"struct.constructors::A"* %{{.*}})
+ // CHECK-NEXT: br label %[[SKIP_VBASES]]
+ //
+ // CHECK: [[SKIP_VBASES]]
+ // CHECK: @"\01??_7C@constructors@@6B@"
+ // CHECK: ret
+}
+
+void create_C() {
+ C c;
+ // CHECK: define void @"\01?create_C@constructors@@YAXXZ"()
+ // CHECK: call x86_thiscallcc %"struct.constructors::C"* @"\01??0C@constructors@@QAE@XZ"(%"struct.constructors::C"* %c, i32 1)
+ // CHECK: ret
+}
+
+struct D : C {
+ D();
+};
+
+D::D() {
+ // CHECK: define x86_thiscallcc %"struct.constructors::D"* @"\01??0D@constructors@@QAE@XZ"(%"struct.constructors::D"* %this, i32 %is_most_derived) unnamed_addr
+ // CHECK: store i32 %is_most_derived, i32* %[[IS_MOST_DERIVED_VAR:.*]], align 4
+ // CHECK: %[[IS_MOST_DERIVED_VAL:.*]] = load i32* %[[IS_MOST_DERIVED_VAR]]
+ // CHECK: %[[SHOULD_CALL_VBASE_CTORS:.*]] = icmp ne i32 %[[IS_MOST_DERIVED_VAL]], 0
+ // CHECK: br i1 %[[SHOULD_CALL_VBASE_CTORS]], label %[[INIT_VBASES:.*]], label %[[SKIP_VBASES:.*]]
+ //
+ // CHECK: [[INIT_VBASES]]
+ // CHECK-NEXT: bitcast %"struct.constructors::D"* %{{.*}} to %"struct.constructors::A"*
+ // CHECK-NEXT: call x86_thiscallcc %"struct.constructors::A"* @"\01??0A@constructors@@QAE@XZ"(%"struct.constructors::A"* %{{.*}})
+ // CHECK-NEXT: br label %[[SKIP_VBASES]]
+ //
+ // CHECK: [[SKIP_VBASES]]
+ // CHECK: call x86_thiscallcc %"struct.constructors::C"* @"\01??0C@constructors@@QAE@XZ"(%"struct.constructors::C"* %{{.*}}, i32 0)
+ // CHECK: ret
+}
+
+struct E : virtual C {
+ E();
+};
+
+E::E() {
+ // CHECK: define x86_thiscallcc %"struct.constructors::E"* @"\01??0E@constructors@@QAE@XZ"(%"struct.constructors::E"* %this, i32 %is_most_derived) unnamed_addr
+ // CHECK: store i32 %is_most_derived, i32* %[[IS_MOST_DERIVED_VAR:.*]], align 4
+ // CHECK: %[[IS_MOST_DERIVED_VAL:.*]] = load i32* %[[IS_MOST_DERIVED_VAR]]
+ // CHECK: %[[SHOULD_CALL_VBASE_CTORS:.*]] = icmp ne i32 %[[IS_MOST_DERIVED_VAL]], 0
+ // CHECK: br i1 %[[SHOULD_CALL_VBASE_CTORS]], label %[[INIT_VBASES:.*]], label %[[SKIP_VBASES:.*]]
+ //
+ // CHECK: [[INIT_VBASES]]
+ // CHECK-NEXT: bitcast %"struct.constructors::E"* %{{.*}} to %"struct.constructors::A"*
+ // CHECK-NEXT: call x86_thiscallcc %"struct.constructors::A"* @"\01??0A@constructors@@QAE@XZ"(%"struct.constructors::A"* %{{.*}})
+ // CHECK: call x86_thiscallcc %"struct.constructors::C"* @"\01??0C@constructors@@QAE@XZ"(%"struct.constructors::C"* %{{.*}}, i32 0)
+ // CHECK-NEXT: br label %[[SKIP_VBASES]]
+ //
+ // CHECK: [[SKIP_VBASES]]
+ // CHECK: ret
+}
+
+} // end namespace constructors
diff --git a/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp b/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp
new file mode 100644
index 0000000..5d430db
--- /dev/null
+++ b/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp
@@ -0,0 +1,113 @@
+// RUN: %clang_cc1 %s -fno-rtti -cxx-abi microsoft -triple=i386-pc-win32 -emit-llvm -fdump-vtable-layouts -o - > %t 2>&1
+// RUN: FileCheck --check-prefix=EMITS-VTABLE %s < %t
+// RUN: FileCheck --check-prefix=CHECK-A %s < %t
+// RUN: FileCheck --check-prefix=CHECK-B %s < %t
+// RUN: FileCheck --check-prefix=CHECK-C %s < %t
+// RUN: FileCheck --check-prefix=CHECK-D %s < %t
+// RUN: FileCheck --check-prefix=CHECK-E %s < %t
+// RUN: FileCheck --check-prefix=CHECK-F %s < %t
+// RUN: FileCheck --check-prefix=CHECK-G %s < %t
+
+struct A {
+ // CHECK-A: Vtable for 'A' (3 entries)
+ // CHECK-A-NEXT: 0 | void A::f()
+ // CHECK-A-NEXT: 1 | void A::g()
+ // CHECK-A-NEXT: 2 | void A::h()
+ // EMITS-VTABLE: @"\01??_7A@@6B@" = unnamed_addr constant [3 x i8*]
+ virtual void f();
+ virtual void g();
+ virtual void h();
+ int ia;
+};
+void A::f() {}
+
+struct B : A {
+ // CHECK-B: Vtable for 'B' (5 entries)
+ // CHECK-B-NEXT: 0 | void B::f()
+ // CHECK-B-NEXT: 1 | void A::g()
+ // CHECK-B-NEXT: 2 | void A::h()
+ // CHECK-B-NEXT: 3 | void B::i()
+ // CHECK-B-NEXT: 4 | void B::j()
+ // EMITS-VTABLE: @"\01??_7B@@6B@" = unnamed_addr constant [5 x i8*]
+ virtual void f(); // overrides A::f()
+ virtual void i();
+ virtual void j();
+};
+void B::f() {}
+
+struct C {
+ // CHECK-C: Vtable for 'C' (2 entries)
+ // CHECK-C-NEXT: 0 | C::~C() [scalar deleting]
+ // CHECK-C-NEXT: 1 | void C::f()
+ // CHECK-C: VTable indices for 'C' (2 entries).
+ // CHECK-C-NEXT: 0 | C::~C() [scalar deleting]
+ // CHECK-C-NEXT: 1 | void C::f()
+ // Never used, so doesn't emit a vtable.
+ virtual ~C();
+
+ virtual void f();
+};
+void C::f() {}
+
+struct D {
+ // CHECK-D: Vtable for 'D' (2 entries)
+ // CHECK-D-NEXT: 0 | void D::f()
+ // CHECK-D-NEXT: 1 | D::~D() [scalar deleting]
+ // EMITS-VTABLE: @"\01??_7D@@6B@" = unnamed_addr constant [2 x i8*]
+ virtual void f();
+
+ virtual ~D();
+};
+void D::f() {}
+
+struct E : A {
+ // CHECK-E: Vtable for 'E' (5 entries)
+ // CHECK-E-NEXT: 0 | void A::f()
+ // CHECK-E-NEXT: 1 | void A::g()
+ // CHECK-E-NEXT: 2 | void A::h()
+ // CHECK-E-NEXT: 3 | E::~E() [scalar deleting]
+ // CHECK-E-NEXT: 4 | void E::i()
+ // CHECK-E: VTable indices for 'E' (2 entries).
+ // CHECK-E-NEXT: 3 | E::~E() [scalar deleting]
+ // CHECK-E-NEXT: 4 | void E::i()
+
+ // Never used, so doesn't emit a vtable.
+ virtual ~E();
+ virtual void i();
+};
+void E::i() {}
+
+struct F : A {
+ // CHECK-F: Vtable for 'F' (5 entries)
+ // CHECK-F-NEXT: 0 | void A::f()
+ // CHECK-F-NEXT: 1 | void A::g()
+ // CHECK-F-NEXT: 2 | void A::h()
+ // CHECK-F-NEXT: 3 | void F::i()
+ // CHECK-F-NEXT: 4 | F::~F() [scalar deleting]
+ // CHECK-F: VTable indices for 'F' (2 entries).
+ // CHECK-F-NEXT: 3 | void F::i()
+ // CHECK-F-NEXT: 4 | F::~F() [scalar deleting]
+ // EMITS-VTABLE: @"\01??_7F@@6B@" = unnamed_addr constant [5 x i8*]
+ virtual void i();
+ virtual ~F();
+};
+void F::i() {}
+
+struct G : E {
+ // CHECK-G: Vtable for 'G' (6 entries)
+ // CHECK-G-NEXT: 0 | void G::f()
+ // CHECK-G-NEXT: 1 | void A::g()
+ // CHECK-G-NEXT: 2 | void A::h()
+ // CHECK-G-NEXT: 3 | G::~G() [scalar deleting]
+ // CHECK-G-NEXT: 4 | void E::i()
+ // CHECK-G-NEXT: 5 | void G::j()
+ // CHECK-G: VTable indices for 'G' (3 entries).
+ // CHECK-G-NEXT: 0 | void G::f()
+ // CHECK-G-NEXT: 3 | G::~G() [scalar deleting]
+ // CHECK-G-NEXT: 5 | void G::j()
+ // Never used, so doesn't emit a vtable.
+ virtual void f(); // overrides A::f()
+ virtual ~G();
+ virtual void j();
+};
+void G::j() {}
diff --git a/test/CodeGenCXX/no-exceptions.cpp b/test/CodeGenCXX/no-exceptions.cpp
index da672c4..ceb3b8e 100644
--- a/test/CodeGenCXX/no-exceptions.cpp
+++ b/test/CodeGenCXX/no-exceptions.cpp
@@ -2,7 +2,7 @@
void g();
-// CHECK: define void @_Z1fv() nounwind
+// CHECK: define void @_Z1fv() [[NUW:#[0-9]+]]
void f() throw (int) {
// CHECK-NOT: invoke void @_Z1gv
@@ -10,3 +10,5 @@ void f() throw (int) {
// CHECK: call void @_Z1gv()
// CHECK: ret void
}
+
+// CHECK: attributes [[NUW]] = { nounwind{{.*}} }
diff --git a/test/CodeGenCXX/no-opt-volatile-memcpy.cpp b/test/CodeGenCXX/no-opt-volatile-memcpy.cpp
new file mode 100644
index 0000000..e542e4a
--- /dev/null
+++ b/test/CodeGenCXX/no-opt-volatile-memcpy.cpp
@@ -0,0 +1,50 @@
+// RUN: %clang_cc1 -O0 -triple=x86_64-apple-darwin -emit-llvm -o - %s | FileCheck %s
+// rdar://11861085
+
+struct s {
+ char filler [128];
+ volatile int x;
+};
+
+struct s gs;
+
+void foo (void) {
+ struct s ls;
+ ls = ls;
+ gs = gs;
+ ls = gs;
+}
+// CHECK: define void @_Z3foov()
+// CHECK: %[[LS:.*]] = alloca %struct.s, align 4
+// CHECK-NEXT: %[[ZERO:.*]] = bitcast %struct.s* %[[LS]] to i8*
+// CHECK-NEXT: %[[ONE:.*]] = bitcast %struct.s* %[[LS]] to i8*
+// CHECK-NEXT: call void @llvm.memcpy.{{.*}}(i8* %[[ZERO]], i8* %[[ONE]], i64 132, i32 4, i1 true)
+// CHECK-NEXT: call void @llvm.memcpy.{{.*}}(i8* getelementptr inbounds (%struct.s* @gs, i32 0, i32 0, i32 0), i8* getelementptr inbounds (%struct.s* @gs, i32 0, i32 0, i32 0), i64 132, i32 4, i1 true)
+// CHECK-NEXT: %[[TWO:.*]] = bitcast %struct.s* %[[LS]] to i8*
+// CHECK-NEXT: call void @llvm.memcpy.{{.*}}(i8* %[[TWO]], i8* getelementptr inbounds (%struct.s* @gs, i32 0, i32 0, i32 0), i64 132, i32 4, i1 true)
+
+
+struct s1 {
+ struct s y;
+};
+
+struct s1 s;
+
+void fee (void) {
+ s = s;
+ s.y = gs;
+}
+// CHECK: define void @_Z3feev()
+// CHECK: call void @llvm.memcpy.{{.*}}(i8* getelementptr inbounds (%struct.s1* @s, i32 0, i32 0, i32 0, i32 0), i8* getelementptr inbounds (%struct.s1* @s, i32 0, i32 0, i32 0, i32 0), i64 132, i32 4, i1 true)
+// CHECK-NEXT: call void @llvm.memcpy.{{.*}}(i8* getelementptr inbounds (%struct.s1* @s, i32 0, i32 0, i32 0, i32 0), i8* getelementptr inbounds (%struct.s* @gs, i32 0, i32 0, i32 0), i64 132, i32 4, i1 true)
+
+struct d : s1 {
+};
+
+d gd;
+
+void gorf(void) {
+ gd = gd;
+}
+// CHECK: define void @_Z4gorfv()
+// CHECK: call void @llvm.memcpy.{{.*}}(i8* getelementptr inbounds (%struct.d* @gd, i32 0, i32 0, i32 0, i32 0, i32 0), i8* getelementptr inbounds (%struct.d* @gd, i32 0, i32 0, i32 0, i32 0, i32 0), i64 132, i32 4, i1 true)
diff --git a/test/CodeGenCXX/noinline-template.cpp b/test/CodeGenCXX/noinline-template.cpp
index 6ee3935..51a84f7 100644
--- a/test/CodeGenCXX/noinline-template.cpp
+++ b/test/CodeGenCXX/noinline-template.cpp
@@ -3,7 +3,7 @@
// This was a problem in Sema, but only shows up as noinline missing
// in CodeGen.
-// CHECK: define linkonce_odr void @_ZN6VectorIiE13growStorageByEv(%struct.Vector* %this) nounwind noinline
+// CHECK: define linkonce_odr void @_ZN6VectorIiE13growStorageByEv(%struct.Vector* %this) [[NI:#[0-9]+]]
template <class Ty> struct Vector {
void growStorageBy();
@@ -14,3 +14,5 @@ void foo() {
Vector<int> strs;
strs.growStorageBy();
}
+
+// CHECK: attributes [[NI]] = { noinline nounwind{{.*}} }
diff --git a/test/CodeGenCXX/nrvo.cpp b/test/CodeGenCXX/nrvo.cpp
index 8ff7dd7..747ab6d 100644
--- a/test/CodeGenCXX/nrvo.cpp
+++ b/test/CodeGenCXX/nrvo.cpp
@@ -100,9 +100,10 @@ X test2(bool B) {
// CHECK-EH: resume { i8*, i32 }
// %terminate.lpad: terminate landing pad.
- // CHECK-EH: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+ // CHECK-EH: [[T0:%.*]] = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
// CHECK-EH-NEXT: catch i8* null
- // CHECK-EH-NEXT: call void @_ZSt9terminatev()
+ // CHECK-EH-NEXT: [[T1:%.*]] = extractvalue { i8*, i32 } [[T0]], 0
+ // CHECK-EH-NEXT: call void @__clang_call_terminate(i8* [[T1]]) [[NR_NUW:#[0-9]+]]
// CHECK-EH-NEXT: unreachable
}
@@ -159,3 +160,5 @@ X test6() {
// CHECK-NEXT: call {{.*}} @_ZN1XD1Ev([[X]]* [[A]])
// CHECK-NEXT: ret void
}
+
+// CHECK-EH: attributes [[NR_NUW]] = { noreturn nounwind }
diff --git a/test/CodeGenCXX/pod-member-memcpys.cpp b/test/CodeGenCXX/pod-member-memcpys.cpp
new file mode 100644
index 0000000..534d5d1
--- /dev/null
+++ b/test/CodeGenCXX/pod-member-memcpys.cpp
@@ -0,0 +1,256 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -std=c++03 -fexceptions -fcxx-exceptions -O1 -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple i386-apple-darwin10 -emit-llvm -std=c++03 -O0 -o - %s | FileCheck --check-prefix=CHECK-2 %s
+
+struct POD {
+ int w, x, y, z;
+};
+
+struct PODLike {
+ int w, x, y, z;
+ PODLike();
+ ~PODLike();
+};
+
+struct NonPOD {
+ NonPOD();
+ NonPOD(const NonPOD&);
+ NonPOD& operator=(const NonPOD&);
+};
+
+struct Basic {
+ int a, b, c, d;
+ NonPOD np;
+ int w, x, y, z;
+};
+
+struct PODMember {
+ int a, b, c, d;
+ POD p;
+ NonPOD np;
+ int w, x, y, z;
+};
+
+struct PODLikeMember {
+ int a, b, c, d;
+ PODLike pl;
+ NonPOD np;
+ int w, x, y, z;
+};
+
+struct ArrayMember {
+ int a, b, c, d;
+ int e[12];
+ NonPOD np;
+ int f[12];
+ int w, x, y, z;
+};
+
+struct VolatileMember {
+ int a, b, c, d;
+ volatile int v;
+ NonPOD np;
+ int w, x, y, z;
+};
+
+struct BitfieldMember {
+ int a, b, c, d;
+ NonPOD np;
+ int w : 6;
+ int x : 6;
+ int y : 6;
+ int z : 6;
+};
+
+struct BitfieldMember2 {
+ unsigned a : 1;
+ unsigned b, c, d;
+ NonPOD np;
+};
+
+struct InnerClassMember {
+ struct {
+ int a, b, c, d;
+ } a;
+ int b, c, d, e;
+ NonPOD np;
+ int w, x, y, z;
+};
+
+struct ReferenceMember {
+ ReferenceMember(int &a, int &b, int &c, int &d)
+ : a(a), b(b), c(c), d(d) {}
+ int &a;
+ int &b;
+ NonPOD np;
+ int &c;
+ int &d;
+};
+
+struct __attribute__((packed)) PackedMembers {
+ char c;
+ NonPOD np;
+ int w, x, y, z;
+};
+
+// COPY-ASSIGNMENT OPERATORS:
+
+// Assignment operators are output in the order they're encountered.
+
+#define CALL_AO(T) void callAO##T(T& a, const T& b) { a = b; }
+
+CALL_AO(Basic)
+CALL_AO(PODMember)
+CALL_AO(PODLikeMember)
+CALL_AO(ArrayMember)
+CALL_AO(VolatileMember)
+CALL_AO(BitfieldMember)
+CALL_AO(InnerClassMember)
+CALL_AO(PackedMembers)
+
+// Basic copy-assignment:
+// CHECK: define linkonce_odr %struct.Basic* @_ZN5BasicaSERKS_(%struct.Basic* %this, %struct.Basic*)
+// CHECK: tail call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}})
+// CHECK: tail call %struct.NonPOD* @_ZN6NonPODaSERKS_
+// CHECK: tail call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}})
+// CHECK: ret %struct.Basic* %this
+
+// PODMember copy-assignment:
+// CHECK: define linkonce_odr %struct.PODMember* @_ZN9PODMemberaSERKS_(%struct.PODMember* %this, %struct.PODMember*)
+// CHECK: tail call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 32, i32 4{{.*}})
+// CHECK: tail call %struct.NonPOD* @_ZN6NonPODaSERKS_
+// CHECK: tail call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}})
+// CHECK: ret %struct.PODMember* %this
+
+// PODLikeMember copy-assignment:
+// CHECK: define linkonce_odr %struct.PODLikeMember* @_ZN13PODLikeMemberaSERKS_(%struct.PODLikeMember* %this, %struct.PODLikeMember*)
+// CHECK: tail call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 32, i32 4{{.*}})
+// CHECK: tail call %struct.NonPOD* @_ZN6NonPODaSERKS_
+// CHECK: tail call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}})
+// CHECK: ret %struct.PODLikeMember* %this
+
+// ArrayMember copy-assignment:
+// CHECK: define linkonce_odr %struct.ArrayMember* @_ZN11ArrayMemberaSERKS_(%struct.ArrayMember* %this, %struct.ArrayMember*)
+// CHECK: tail call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 64, i32 4{{.*}})
+// CHECK: tail call %struct.NonPOD* @_ZN6NonPODaSERKS_
+// CHECK: tail call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 64, i32 4{{.*}})
+// CHECK: ret %struct.ArrayMember* %this
+
+// VolatileMember copy-assignment:
+// CHECK: define linkonce_odr %struct.VolatileMember* @_ZN14VolatileMemberaSERKS_(%struct.VolatileMember* %this, %struct.VolatileMember*)
+// CHECK: tail call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}})
+// CHECK: load volatile i32* {{.*}}, align 4
+// CHECK: store volatile i32 {{.*}}, align 4
+// CHECK: tail call %struct.NonPOD* @_ZN6NonPODaSERKS_
+// CHECK: tail call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}})
+// CHECK: ret %struct.VolatileMember* %this
+
+// BitfieldMember copy-assignment:
+// CHECK: define linkonce_odr %struct.BitfieldMember* @_ZN14BitfieldMemberaSERKS_(%struct.BitfieldMember* %this, %struct.BitfieldMember*)
+// CHECK: tail call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}})
+// CHECK: tail call %struct.NonPOD* @_ZN6NonPODaSERKS_
+// CHECK: tail call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 3, i32 1{{.*}})
+// CHECK: ret %struct.BitfieldMember* %this
+
+// InnerClass copy-assignment:
+// CHECK: define linkonce_odr %struct.InnerClassMember* @_ZN16InnerClassMemberaSERKS_(%struct.InnerClassMember* %this, %struct.InnerClassMember*)
+// CHECK: tail call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 32, i32 4{{.*}})
+// CHECK: tail call %struct.NonPOD* @_ZN6NonPODaSERKS_
+// CHECK: tail call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}})
+// CHECK: ret %struct.InnerClassMember* %this
+
+// PackedMembers copy-assignment:
+// CHECK: define linkonce_odr %struct.PackedMembers* @_ZN13PackedMembersaSERKS_(%struct.PackedMembers* %this, %struct.PackedMembers*)
+// CHECK: tail call %struct.NonPOD* @_ZN6NonPODaSERKS_
+// CHECK: tail call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 1{{.*}})
+// CHECK: ret %struct.PackedMembers* %this
+
+// COPY-CONSTRUCTORS:
+
+// Clang outputs copy-constructors in the reverse of the order that
+// copy-constructor calls are encountered. Add functions that call the copy
+// constructors of the classes above in reverse order here.
+
+#define CALL_CC(T) T callCC##T(const T& b) { return b; }
+
+CALL_CC(PackedMembers)
+CALL_CC(BitfieldMember2)
+CALL_CC(ReferenceMember)
+CALL_CC(InnerClassMember)
+CALL_CC(BitfieldMember)
+CALL_CC(VolatileMember)
+CALL_CC(ArrayMember)
+CALL_CC(PODLikeMember)
+CALL_CC(PODMember)
+CALL_CC(Basic)
+
+// Basic copy-constructor:
+// CHECK: define linkonce_odr void @_ZN5BasicC2ERKS_(%struct.Basic* %this, %struct.Basic*)
+// CHECK: tail call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}})
+// CHECK: tail call void @_ZN6NonPODC1ERKS_
+// CHECK: tail call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}})
+// CHECK: ret void
+
+// PODMember copy-constructor:
+// CHECK: define linkonce_odr void @_ZN9PODMemberC2ERKS_(%struct.PODMember* %this, %struct.PODMember*)
+// CHECK: tail call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 32, i32 4{{.*}})
+// CHECK: tail call void @_ZN6NonPODC1ERKS_
+// CHECK: tail call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}})
+// CHECK: ret void
+
+// PODLikeMember copy-constructor:
+// CHECK: define linkonce_odr void @_ZN13PODLikeMemberC2ERKS_(%struct.PODLikeMember* %this, %struct.PODLikeMember*)
+// CHECK: tail call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 32, i32 4{{.*}})
+// CHECK: invoke void @_ZN6NonPODC1ERKS_
+// CHECK: tail call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}})
+// CHECK: ret void
+// CHECK: landingpad
+// CHECK: invoke void @_ZN7PODLikeD1Ev
+
+// ArrayMember copy-constructor:
+// CHECK: define linkonce_odr void @_ZN11ArrayMemberC2ERKS_(%struct.ArrayMember* %this, %struct.ArrayMember*)
+// CHECK: tail call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 64, i32 4{{.*}})
+// CHECK: tail call void @_ZN6NonPODC1ERKS_
+// CHECK: tail call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 64, i32 4{{.*}})
+// CHECK: ret void
+
+// VolatileMember copy-constructor:
+// CHECK: define linkonce_odr void @_ZN14VolatileMemberC2ERKS_(%struct.VolatileMember* %this, %struct.VolatileMember*)
+// CHECK: tail call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}})
+// CHECK: load volatile i32* {{.*}}, align 4
+// CHECK: store volatile i32 {{.*}}, align 4
+// CHECK: tail call void @_ZN6NonPODC1ERKS_
+// CHECK: tail call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}})
+// CHECK: ret void
+
+// BitfieldMember copy-constructor:
+// CHECK: define linkonce_odr void @_ZN14BitfieldMemberC2ERKS_(%struct.BitfieldMember* %this, %struct.BitfieldMember*)
+// CHECK: tail call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}})
+// CHECK: tail call void @_ZN6NonPODC1ERKS_
+// CHECK: tail call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 3, i32 1{{.*}})
+// CHECK: ret void
+
+// InnerClass copy-constructor:
+// CHECK: define linkonce_odr void @_ZN16InnerClassMemberC2ERKS_(%struct.InnerClassMember* %this, %struct.InnerClassMember*)
+// CHECK: tail call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 32, i32 4{{.*}})
+// CHECK: tail call void @_ZN6NonPODC1ERKS_
+// CHECK: tail call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}})
+// CHECK: ret void
+
+// ReferenceMember copy-constructor:
+// CHECK: define linkonce_odr void @_ZN15ReferenceMemberC2ERKS_(%struct.ReferenceMember* %this, %struct.ReferenceMember*)
+// CHECK: tail call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 8{{.*}})
+// CHECK: tail call void @_ZN6NonPODC1ERKS_
+// CHECK: tail call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 8{{.*}})
+// CHECK: ret void
+
+// BitfieldMember2 copy-constructor:
+// CHECK-2: define linkonce_odr void @_ZN15BitfieldMember2C2ERKS_(%struct.BitfieldMember2* %this, %struct.BitfieldMember2*)
+// CHECK-2: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4, i1 false)
+// CHECK-2: call void @_ZN6NonPODC1ERKS_
+// CHECK-2: ret void
+
+// PackedMembers copy-assignment:
+// CHECK: define linkonce_odr void @_ZN13PackedMembersC2ERKS_(%struct.PackedMembers* %this, %struct.PackedMembers*)
+// CHECK: tail call void @_ZN6NonPODC1ERKS_
+// CHECK: tail call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 1{{.*}})
+// CHECK: ret void
diff --git a/test/CodeGenCXX/pointers-to-data-members.cpp b/test/CodeGenCXX/pointers-to-data-members.cpp
index fe69cd5..7335c97 100644
--- a/test/CodeGenCXX/pointers-to-data-members.cpp
+++ b/test/CodeGenCXX/pointers-to-data-members.cpp
@@ -151,13 +151,13 @@ struct A {
A() : a() {}
};
-// CHECK-O3: define zeroext i1 @_ZN6PR71395checkEv() nounwind readnone
+// CHECK-O3: define zeroext i1 @_ZN6PR71395checkEv() [[NUW:#[0-9]+]]
bool check() {
// CHECK-O3: ret i1 true
return A().a.data == 0;
}
-// CHECK-O3: define zeroext i1 @_ZN6PR71396check2Ev() nounwind readnone
+// CHECK-O3: define zeroext i1 @_ZN6PR71396check2Ev() [[NUW]]
bool check2() {
// CHECK-O3: ret i1 true
return ptr_to_member_type() == 0;
@@ -254,3 +254,5 @@ namespace PR13097 {
// CHECK-NOT: memcpy
// CHECK: call void @_ZN7PR130971XC1ERKS0_
}
+
+// CHECK-O3: attributes [[NUW]] = { nounwind readnone{{.*}} }
diff --git a/test/CodeGenCXX/pragma-weak.cpp b/test/CodeGenCXX/pragma-weak.cpp
new file mode 100644
index 0000000..ed537ff
--- /dev/null
+++ b/test/CodeGenCXX/pragma-weak.cpp
@@ -0,0 +1,31 @@
+// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s
+
+#pragma weak zex
+int zex;
+// GCC produces a weak symbol for this because it matches mangled names.
+// Different c++ ABIs may or may not mangle this, so we produce a strong
+// symbol.
+// CHECK: @zex = global i32
+
+#pragma weak foo
+struct S { void foo(); };
+void S::foo() {}
+// CHECK: define void @_ZN1S3fooEv(
+
+#pragma weak zed
+namespace bar { void zed() {} }
+// CHECK: define void @_ZN3bar3zedEv(
+
+#pragma weak bah
+void bah() {}
+// CHECK: define void @_Z3bahv(
+
+#pragma weak baz
+extern "C" void baz() {}
+// CHECK: define weak void @baz(
+
+#pragma weak _Z3baxv
+void bax() {}
+// GCC produces a weak symbol for this one, but it doesn't look like a good
+// idea to expose the mangling to the pragma unless we really have to.
+// CHECK: define void @_Z3baxv(
diff --git a/test/CodeGenCXX/predefined-expr.cpp b/test/CodeGenCXX/predefined-expr.cpp
index 1795ec8..24ead8f 100644
--- a/test/CodeGenCXX/predefined-expr.cpp
+++ b/test/CodeGenCXX/predefined-expr.cpp
@@ -142,7 +142,7 @@ public:
printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__);
}
- inline void inlineFunction() {
+ inline void (inlineFunction)() {
printf("__func__ %s\n", __func__);
printf("__FUNCTION__ %s\n", __FUNCTION__);
printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__);
diff --git a/test/CodeGenCXX/reference-cast.cpp b/test/CodeGenCXX/reference-cast.cpp
index 1d08b2b..f157ae9 100644
--- a/test/CodeGenCXX/reference-cast.cpp
+++ b/test/CodeGenCXX/reference-cast.cpp
@@ -3,7 +3,7 @@
// PR6024
extern int i;
-// CHECK: define i32* @_Z16lvalue_noop_castv() nounwind
+// CHECK: define i32* @_Z16lvalue_noop_castv() [[NUW:#[0-9]+]]
const int &lvalue_noop_cast() {
if (i == 0)
// CHECK: store i32 17, i32*
@@ -192,3 +192,5 @@ namespace PR10650 {
// CHECK: define i64 @_ZN7PR106504testEPNS_6HelperE
// CHECK: store i64
}
+
+// CHECK: attributes [[NUW]] = { nounwind{{.*}} }
diff --git a/test/CodeGenCXX/references.cpp b/test/CodeGenCXX/references.cpp
index d315f71..df5a336 100644
--- a/test/CodeGenCXX/references.cpp
+++ b/test/CodeGenCXX/references.cpp
@@ -283,12 +283,11 @@ namespace PR9565 {
void f() {
// CHECK: call void @llvm.memcpy
a x = { 0, 0 };
- // CHECK: [[WITH_SEVENTEEN:%[a-zA-Z0-9]+]] = or i32 [[WITHOUT_SEVENTEEN:%[a-zA-Z0-9]+]], 17
- // CHECK: store i32 [[WITH_SEVENTEEN]], i32* [[XA:%[a-zA-Z0-9]+]]
+ // CHECK: [[WITH_SEVENTEEN:%[.a-zA-Z0-9]+]] = or i32 [[WITHOUT_SEVENTEEN:%[.a-zA-Z0-9]+]], 17
+ // CHECK: store i32 [[WITH_SEVENTEEN]], i32* [[XA:%[.a-zA-Z0-9]+]]
x.a = 17;
// CHECK-NEXT: bitcast
- // CHECK-NEXT: load
- // CHECK-NEXT: and
+ // CHECK-NEXT: load
// CHECK-NEXT: shl
// CHECK-NEXT: ashr
// CHECK-NEXT: store i32
@@ -297,7 +296,7 @@ namespace PR9565 {
// CHECK-NEXT: bitcast
// CHECK-NEXT: load
// CHECK-NEXT: and
- // CHECK-NEXT: or
+ // CHECK-NEXT: or i32 {{.*}}, 19456
// CHECK-NEXT: store i32
x.b = 19;
// CHECK-NEXT: ret void
diff --git a/test/CodeGenCXX/runtimecc.cpp b/test/CodeGenCXX/runtimecc.cpp
new file mode 100644
index 0000000..66d3f41
--- /dev/null
+++ b/test/CodeGenCXX/runtimecc.cpp
@@ -0,0 +1,53 @@
+// RUN: %clang_cc1 %s -triple=armv7-apple-darwin10 -emit-llvm -o - -fexceptions -fcxx-exceptions | FileCheck %s
+
+// Check that we annotate all compiler-synthesized runtime calls and
+// functions with the actual ABI-determined CC. This usually doesn't
+// matter as long as we're internally consistent (and the LLVM-default
+// CC is consistent with the real one), but it's possible for user
+// translation units to define these runtime functions (or, equivalently,
+// for us to get LTO'ed with such a translation unit), and then the
+// mismatch will kill us.
+//
+// rdar://12818655
+
+// CHECK: [[A:%.*]] = type { double }
+
+namespace test0 {
+ struct A {
+ double d;
+ A();
+ ~A();
+ };
+
+ A global;
+// CHECK: define internal arm_aapcscc void @__cxx_global_var_init()
+// CHECK: call arm_aapcscc [[A]]* @_ZN5test01AC1Ev([[A]]* @_ZN5test06globalE)
+// CHECK-NEXT: call arm_aapcscc i32 @__cxa_atexit(void (i8*)* bitcast ([[A]]* ([[A]]*)* @_ZN5test01AD1Ev to void (i8*)*), i8* bitcast ([[A]]* @_ZN5test06globalE to i8*), i8* @__dso_handle) [[NOUNWIND:#[0-9]+]]
+// CHECK-NEXT: ret void
+}
+
+// CHECK: declare arm_aapcscc i32 @__cxa_atexit(void (i8*)*, i8*, i8*) [[NOUNWIND]]
+
+namespace test1 {
+ void test() {
+ throw 0;
+ }
+
+// CHECK: define arm_aapcscc void @_ZN5test14testEv()
+// CHECK: [[T0:%.*]] = call arm_aapcscc i8* @__cxa_allocate_exception(i32 4) [[NOUNWIND]]
+// CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to i32*
+// CHECK-NEXT: store i32 0, i32* [[T1]]
+// CHECK-NEXT: call arm_aapcscc void @__cxa_throw(i8* [[T0]], i8* bitcast (i8** @_ZTIi to i8*), i8* null) [[NORETURN:#[0-9]+]]
+// CHECK-NEXT: unreachable
+}
+
+// CHECK: declare arm_aapcscc i8* @__cxa_allocate_exception(i32)
+
+// CHECK: declare arm_aapcscc void @__cxa_throw(i8*, i8*, i8*)
+
+// CHECK: define internal arm_aapcscc void @_GLOBAL__I_a()
+// CHECK: call arm_aapcscc void @__cxx_global_var_init()
+
+
+// CHECK: attributes [[NOUNWIND]] = { nounwind }
+// CHECK: attributes [[NORETURN]] = { noreturn }
diff --git a/test/CodeGenCXX/sizeof-unwind-exception.cpp b/test/CodeGenCXX/sizeof-unwind-exception.cpp
index 5db4df7..95bb9d0 100644
--- a/test/CodeGenCXX/sizeof-unwind-exception.cpp
+++ b/test/CodeGenCXX/sizeof-unwind-exception.cpp
@@ -15,14 +15,19 @@ void test() {
// PR10789: different platforms have different sizes for struct UnwindException.
-// X86-64: [[T0:%.*]] = tail call i8* @__cxa_begin_catch(i8* [[EXN:%.*]]) nounwind
+// X86-64: [[T0:%.*]] = tail call i8* @__cxa_begin_catch(i8* [[EXN:%.*]]) [[NUW:#[0-9]+]]
// X86-64-NEXT: [[T1:%.*]] = getelementptr i8* [[EXN]], i64 32
-// X86-32: [[T0:%.*]] = tail call i8* @__cxa_begin_catch(i8* [[EXN:%.*]]) nounwind
+// X86-32: [[T0:%.*]] = tail call i8* @__cxa_begin_catch(i8* [[EXN:%.*]]) [[NUW:#[0-9]+]]
// X86-32-NEXT: [[T1:%.*]] = getelementptr i8* [[EXN]], i64 32
-// ARM-DARWIN: [[T0:%.*]] = tail call i8* @__cxa_begin_catch(i8* [[EXN:%.*]]) nounwind
+// ARM-DARWIN: [[T0:%.*]] = tail call i8* @__cxa_begin_catch(i8* [[EXN:%.*]]) [[NUW:#[0-9]+]]
// ARM-DARWIN-NEXT: [[T1:%.*]] = getelementptr i8* [[EXN]], i64 32
-// ARM-EABI: [[T0:%.*]] = tail call i8* @__cxa_begin_catch(i8* [[EXN:%.*]]) nounwind
+// ARM-EABI: [[T0:%.*]] = tail call i8* @__cxa_begin_catch(i8* [[EXN:%.*]]) [[NUW:#[0-9]+]]
// ARM-EABI-NEXT: [[T1:%.*]] = getelementptr i8* [[EXN]], i32 88
-// MIPS: [[T0:%.*]] = tail call i8* @__cxa_begin_catch(i8* [[EXN:%.*]]) nounwind
+// MIPS: [[T0:%.*]] = tail call i8* @__cxa_begin_catch(i8* [[EXN:%.*]]) [[NUW:#[0-9]+]]
// MIPS-NEXT: [[T1:%.*]] = getelementptr i8* [[EXN]], i32 24
+// X86-64: attributes [[NUW]] = { nounwind }
+// X86-32: attributes [[NUW]] = { nounwind }
+// ARM-DARWIN: attributes [[NUW]] = { nounwind }
+// ARM-EABI: attributes [[NUW]] = { nounwind }
+// MIPS: attributes [[NUW]] = { nounwind }
diff --git a/test/CodeGenCXX/temp-order.cpp b/test/CodeGenCXX/temp-order.cpp
index 341cd0c..67cd4b7 100644
--- a/test/CodeGenCXX/temp-order.cpp
+++ b/test/CodeGenCXX/temp-order.cpp
@@ -1,5 +1,5 @@
// Output file should have no calls to error() with folding.
-// RUN: %clang_cc1 -triple i386-unknown-unknown -O3 -emit-llvm -o %t %s
+// RUN: %clang_cc1 -triple i386-unknown-unknown -mllvm -inline-threshold=1024 -O3 -emit-llvm -o %t %s
// RUN: FileCheck %s < %t
static unsigned pow(unsigned Base, unsigned Power) {
diff --git a/test/CodeGenCXX/template-anonymous-types.cpp b/test/CodeGenCXX/template-anonymous-types.cpp
index 72fe090..3df487a 100644
--- a/test/CodeGenCXX/template-anonymous-types.cpp
+++ b/test/CodeGenCXX/template-anonymous-types.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -triple x86_64-unknown-linux-gnu -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -triple x86_64-unknown-linux-gnu -emit-llvm -w -o - | FileCheck %s
struct S {
enum { FOO = 42 };
@@ -17,21 +17,21 @@ template <typename T> int f(T t) {
}
void test() {
- // Look for two instantiations, entirely internal to this TU, one for FOO's
+ // Look for two instantiations, one for FOO's
// type and one for BAR's.
- // CHECK: define internal i32 @"_Z1fIN1S3$_0EEiT_"(i32 %t)
+ // CHECK: define linkonce_odr i32 @_Z1fIN1SUt_EEiT_(i32 %t)
(void)f(S::FOO);
- // CHECK: define internal i32 @"_Z1fIN1S3$_1EEiT_"(i32 %t)
+ // CHECK: define linkonce_odr i32 @_Z1fIN1SUt0_EEiT_(i32 %t)
(void)f(S::BAR);
// Now check for the class template instantiations. Annoyingly, they are in
// reverse order.
//
// BAR's instantiation of X:
- // CHECK: define internal i32 @"_ZN1XIN1S3$_1EE1fEv"(%struct.X* %this)
- // CHECK: define internal void @"_ZN1XIN1S3$_1EEC2ES1_"(%struct.X* %this, i32 %t) unnamed_addr
+ // CHECK: define linkonce_odr i32 @_ZN1XIN1SUt0_EE1fEv(%struct.X* %this)
+ // CHECK: define linkonce_odr void @_ZN1XIN1SUt0_EEC2ES1_(%struct.X* %this, i32 %t) unnamed_addr
//
// FOO's instantiation of X:
- // CHECK: define internal i32 @"_ZN1XIN1S3$_0EE1fEv"(%struct.X.0* %this)
- // CHECK: define internal void @"_ZN1XIN1S3$_0EEC2ES1_"(%struct.X.0* %this, i32 %t) unnamed_addr
+ // CHECK: define linkonce_odr i32 @_ZN1XIN1SUt_EE1fEv(%struct.X.0* %this)
+ // CHECK: define linkonce_odr void @_ZN1XIN1SUt_EEC2ES1_(%struct.X.0* %this, i32 %t) unnamed_addr
}
diff --git a/test/CodeGenCXX/template-linkage.cpp b/test/CodeGenCXX/template-linkage.cpp
index 20508c1..3acd12e 100644
--- a/test/CodeGenCXX/template-linkage.cpp
+++ b/test/CodeGenCXX/template-linkage.cpp
@@ -1,4 +1,7 @@
// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s
+
+// CHECK: Outer5Inner{{.*}}localE6memberE = external global
+
template<typename T> struct A {
virtual void f(T) { }
inline void g() { }
@@ -42,3 +45,20 @@ void test_X1() {
X1<char> i1c;
}
+namespace PR14825 {
+struct Outer {
+ template <typename T> struct Inner {
+ static int member;
+ };
+ template <typename T> void Get() {
+ int m = Inner<T>::member;
+ }
+};
+
+void test() {
+ struct local {};
+ Outer o;
+ typedef void (Outer::*mptr)();
+ mptr method = &Outer::Get<local>;
+}
+}
diff --git a/test/CodeGenCXX/temporaries.cpp b/test/CodeGenCXX/temporaries.cpp
index e90c947..a369c2e 100644
--- a/test/CodeGenCXX/temporaries.cpp
+++ b/test/CodeGenCXX/temporaries.cpp
@@ -537,3 +537,24 @@ namespace PR11365 {
(void) (A [3]) {};
}
}
+
+namespace AssignmentOp {
+ struct A { ~A(); };
+ struct B { A operator=(const B&); };
+ struct C : B { B b1, b2; };
+ // CHECK: define void @_ZN12AssignmentOp1fE
+ void f(C &c1, const C &c2) {
+ // CHECK: call {{.*}} @_ZN12AssignmentOp1CaSERKS0_(
+ c1 = c2;
+ }
+
+ // Ensure that each 'A' temporary is destroyed before the next subobject is
+ // copied.
+ // CHECK: define {{.*}} @_ZN12AssignmentOp1CaSERKS0_(
+ // CHECK: call {{.*}} @_ZN12AssignmentOp1BaSERKS
+ // CHECK: call {{.*}} @_ZN12AssignmentOp1AD1Ev(
+ // CHECK: call {{.*}} @_ZN12AssignmentOp1BaSERKS
+ // CHECK: call {{.*}} @_ZN12AssignmentOp1AD1Ev(
+ // CHECK: call {{.*}} @_ZN12AssignmentOp1BaSERKS
+ // CHECK: call {{.*}} @_ZN12AssignmentOp1AD1Ev(
+}
diff --git a/test/CodeGenCXX/threadsafe-statics.cpp b/test/CodeGenCXX/threadsafe-statics.cpp
index 8afc274..9aecc2d 100644
--- a/test/CodeGenCXX/threadsafe-statics.cpp
+++ b/test/CodeGenCXX/threadsafe-statics.cpp
@@ -6,7 +6,7 @@ int f();
// WITH-TSS: @_ZZ1gvE1a = internal global i32 0, align 4
// WITH-TSS: @_ZGVZ1gvE1a = internal global i64 0
-// WITH-TSS: define void @_Z1gv() nounwind
+// WITH-TSS: define void @_Z1gv() [[NUW:#[0-9]+]]
// WITH-TSS: call i32 @__cxa_guard_acquire
// WITH-TSS: call void @__cxa_guard_release
// WITH-TSS: ret void
@@ -17,7 +17,11 @@ void g() {
// NO-TSS: @_ZZ1gvE1a = internal global i32 0, align 4
// NO-TSS: @_ZGVZ1gvE1a = internal global i8 0
-// NO-TSS: define void @_Z1gv() nounwind
+// NO-TSS: define void @_Z1gv() [[NUW:#[0-9]+]]
// NO-TSS-NOT: call i32 @__cxa_guard_acquire
// NO-TSS-NOT: call void @__cxa_guard_release
// NO-TSS: ret void
+
+// WITH-TSS: attributes [[NUW]] = { nounwind{{.*}} }
+
+// NO-TSS: attributes [[NUW]] = { nounwind{{.*}} }
diff --git a/test/CodeGenCXX/thunks.cpp b/test/CodeGenCXX/thunks.cpp
index 0659259..6e58830 100644
--- a/test/CodeGenCXX/thunks.cpp
+++ b/test/CodeGenCXX/thunks.cpp
@@ -339,7 +339,7 @@ namespace Test14 {
};
void C::f() {
}
- // CHECK: define void @_ZThn8_N6Test141C1fEv({{.*}}) {{.*}} uwtable
+ // CHECK: define void @_ZThn8_N6Test141C1fEv({{.*}}) unnamed_addr [[NUW:#[0-9]+]]
}
/**** The following has to go at the end of the file ****/
@@ -347,3 +347,5 @@ namespace Test14 {
// This is from Test5:
// CHECK: define linkonce_odr void @_ZTv0_n24_N5Test51B1fEv
// CHECK: define internal void @_ZThn8_N6Test4B12_GLOBAL__N_11C1fEv(
+
+// CHECK: attributes [[NUW]] = { nounwind uwtable{{.*}} }
diff --git a/test/CodeGenCXX/trivial-constructor-init.cpp b/test/CodeGenCXX/trivial-constructor-init.cpp
index 343dc65..65ed45e 100644
--- a/test/CodeGenCXX/trivial-constructor-init.cpp
+++ b/test/CodeGenCXX/trivial-constructor-init.cpp
@@ -1,5 +1,4 @@
-// RUN: %clang_cc1 -S %s -o %t-64.s
-// RUN: %clang_cc1 -S %s -o %t-32.s
+// RUN: %clang_cc1 -emit-llvm %s -o - -std=c++11 | FileCheck %s
extern "C" int printf(...);
@@ -16,5 +15,20 @@ struct A {
A a;
+struct B {
+ B() = default;
+ B(const B&);
+};
+
+// CHECK-NOT: _ZL1b
+static B b;
+
+struct C {
+ ~C();
+};
+
+// CHECK: _ZL1c
+static C c[4];
+
int main() {
}
diff --git a/test/CodeGenCXX/type_visibility.cpp b/test/CodeGenCXX/type_visibility.cpp
new file mode 100644
index 0000000..5c45611
--- /dev/null
+++ b/test/CodeGenCXX/type_visibility.cpp
@@ -0,0 +1,170 @@
+// RUN: %clang_cc1 %s -std=c++11 -triple=x86_64-apple-darwin10 -emit-llvm -o %t.ll
+// RUN: FileCheck %s -check-prefix=FUNS < %t.ll
+// RUN: FileCheck %s -check-prefix=VARS < %t.ll
+// RUN: %clang_cc1 %s -std=c++11 -triple=x86_64-apple-darwin10 -fvisibility hidden -emit-llvm -o %t.ll
+// RUN: FileCheck %s -check-prefix=FUNS-HIDDEN < %t.ll
+// RUN: FileCheck %s -check-prefix=VARS-HIDDEN < %t.ll
+
+#define HIDDEN __attribute__((visibility("hidden")))
+#define PROTECTED __attribute__((visibility("protected")))
+#define DEFAULT __attribute__((visibility("default")))
+#define TYPE_HIDDEN __attribute__((type_visibility("hidden")))
+#define TYPE_PROTECTED __attribute__((type_visibility("protected")))
+#define TYPE_DEFAULT __attribute__((type_visibility("default")))
+
+// type_visibility is rdar://11880378
+
+#if !__has_attribute(type_visibility)
+#error No type_visibility attribute!
+#endif
+
+// The template tests come first because IR-gen reorders RTTI wierdly.
+namespace temp0 {
+ struct A;
+ template <class T> struct TYPE_DEFAULT B {
+ virtual void foo() {}
+ };
+
+ template struct B<A>;
+ // FUNS: define weak_odr void @_ZN5temp01BINS_1AEE3fooEv(
+ // VARS: @_ZTVN5temp01BINS_1AEEE = weak_odr unnamed_addr constant
+ // VARS: @_ZTSN5temp01BINS_1AEEE = weak_odr constant
+ // VARS: @_ZTIN5temp01BINS_1AEEE = weak_odr unnamed_addr constant
+ // FUNS-HIDDEN: define weak_odr hidden void @_ZN5temp01BINS_1AEE3fooEv(
+ // VARS-HIDDEN: @_ZTVN5temp01BINS_1AEEE = weak_odr hidden unnamed_addr constant
+ // VARS-HIDDEN: @_ZTSN5temp01BINS_1AEEE = weak_odr hidden constant
+ // VARS-HIDDEN: @_ZTIN5temp01BINS_1AEEE = weak_odr hidden unnamed_addr constant
+}
+
+namespace temp1 {
+ struct TYPE_DEFAULT A;
+ template <class T> struct TYPE_DEFAULT B {
+ virtual void foo() {}
+ };
+
+ template struct B<A>;
+ // FUNS: define weak_odr void @_ZN5temp11BINS_1AEE3fooEv(
+ // VARS: @_ZTVN5temp11BINS_1AEEE = weak_odr unnamed_addr constant
+ // VARS: @_ZTSN5temp11BINS_1AEEE = weak_odr constant
+ // VARS: @_ZTIN5temp11BINS_1AEEE = weak_odr unnamed_addr constant
+ // FUNS-HIDDEN: define weak_odr hidden void @_ZN5temp11BINS_1AEE3fooEv(
+ // VARS-HIDDEN: @_ZTVN5temp11BINS_1AEEE = weak_odr unnamed_addr constant
+ // VARS-HIDDEN: @_ZTSN5temp11BINS_1AEEE = weak_odr constant
+ // VARS-HIDDEN: @_ZTIN5temp11BINS_1AEEE = weak_odr unnamed_addr constant
+}
+
+namespace temp2 {
+ struct TYPE_DEFAULT A;
+ template <class T> struct B {
+ virtual void foo() {}
+ };
+
+ template struct B<A>;
+ // FUNS: define weak_odr void @_ZN5temp21BINS_1AEE3fooEv(
+ // VARS: @_ZTVN5temp21BINS_1AEEE = weak_odr unnamed_addr constant
+ // VARS: @_ZTSN5temp21BINS_1AEEE = weak_odr constant
+ // VARS: @_ZTIN5temp21BINS_1AEEE = weak_odr unnamed_addr constant
+ // FUNS-HIDDEN: define weak_odr hidden void @_ZN5temp21BINS_1AEE3fooEv(
+ // VARS-HIDDEN: @_ZTVN5temp21BINS_1AEEE = weak_odr hidden unnamed_addr constant
+ // VARS-HIDDEN: @_ZTSN5temp21BINS_1AEEE = weak_odr hidden constant
+ // VARS-HIDDEN: @_ZTIN5temp21BINS_1AEEE = weak_odr hidden unnamed_addr constant
+}
+
+namespace temp3 {
+ struct TYPE_HIDDEN A;
+ template <class T> struct TYPE_DEFAULT B {
+ virtual void foo() {}
+ };
+
+ template struct B<A>;
+ // FUNS: define weak_odr hidden void @_ZN5temp31BINS_1AEE3fooEv(
+ // VARS: @_ZTVN5temp31BINS_1AEEE = weak_odr hidden unnamed_addr constant
+ // VARS: @_ZTSN5temp31BINS_1AEEE = weak_odr hidden constant
+ // VARS: @_ZTIN5temp31BINS_1AEEE = weak_odr hidden unnamed_addr constant
+ // FUNS-HIDDEN: define weak_odr hidden void @_ZN5temp31BINS_1AEE3fooEv(
+ // VARS-HIDDEN: @_ZTVN5temp31BINS_1AEEE = weak_odr hidden unnamed_addr constant
+ // VARS-HIDDEN: @_ZTSN5temp31BINS_1AEEE = weak_odr hidden constant
+ // VARS-HIDDEN: @_ZTIN5temp31BINS_1AEEE = weak_odr hidden unnamed_addr constant
+}
+
+namespace temp4 {
+ struct TYPE_DEFAULT A;
+ template <class T> struct TYPE_HIDDEN B {
+ virtual void foo() {}
+ };
+
+ template struct B<A>;
+ // FUNS: define weak_odr void @_ZN5temp41BINS_1AEE3fooEv(
+ // VARS: @_ZTVN5temp41BINS_1AEEE = weak_odr hidden unnamed_addr constant
+ // VARS: @_ZTSN5temp41BINS_1AEEE = weak_odr hidden constant
+ // VARS: @_ZTIN5temp41BINS_1AEEE = weak_odr hidden unnamed_addr constant
+ // FUNS-HIDDEN: define weak_odr hidden void @_ZN5temp41BINS_1AEE3fooEv(
+ // VARS-HIDDEN: @_ZTVN5temp41BINS_1AEEE = weak_odr hidden unnamed_addr constant
+ // VARS-HIDDEN: @_ZTSN5temp41BINS_1AEEE = weak_odr hidden constant
+ // VARS-HIDDEN: @_ZTIN5temp41BINS_1AEEE = weak_odr hidden unnamed_addr constant
+}
+
+namespace type0 {
+ struct TYPE_DEFAULT A {
+ virtual void foo();
+ };
+
+ void A::foo() {}
+ // FUNS: define void @_ZN5type01A3fooEv(
+ // VARS: @_ZTVN5type01AE = unnamed_addr constant
+ // VARS: @_ZTSN5type01AE = constant
+ // VARS: @_ZTIN5type01AE = unnamed_addr constant
+ // FUNS-HIDDEN: define hidden void @_ZN5type01A3fooEv(
+ // VARS-HIDDEN: @_ZTVN5type01AE = unnamed_addr constant
+ // VARS-HIDDEN: @_ZTSN5type01AE = constant
+ // VARS-HIDDEN: @_ZTIN5type01AE = unnamed_addr constant
+}
+
+namespace type1 {
+ struct HIDDEN TYPE_DEFAULT A {
+ virtual void foo();
+ };
+
+ void A::foo() {}
+ // FUNS: define hidden void @_ZN5type11A3fooEv(
+ // VARS: @_ZTVN5type11AE = unnamed_addr constant
+ // VARS: @_ZTSN5type11AE = constant
+ // VARS: @_ZTIN5type11AE = unnamed_addr constant
+ // FUNS-HIDDEN: define hidden void @_ZN5type11A3fooEv(
+ // VARS-HIDDEN: @_ZTVN5type11AE = unnamed_addr constant
+ // VARS-HIDDEN: @_ZTSN5type11AE = constant
+ // VARS-HIDDEN: @_ZTIN5type11AE = unnamed_addr constant
+}
+
+namespace type2 {
+ struct TYPE_HIDDEN A {
+ virtual void foo();
+ };
+
+ void A::foo() {}
+ // FUNS: define void @_ZN5type21A3fooEv(
+ // VARS: @_ZTVN5type21AE = hidden unnamed_addr constant
+ // VARS: @_ZTSN5type21AE = hidden constant
+ // VARS: @_ZTIN5type21AE = hidden unnamed_addr constant
+ // FUNS-HIDDEN: define hidden void @_ZN5type21A3fooEv(
+ // VARS-HIDDEN: @_ZTVN5type21AE = hidden unnamed_addr constant
+ // VARS-HIDDEN: @_ZTSN5type21AE = hidden constant
+ // VARS-HIDDEN: @_ZTIN5type21AE = hidden unnamed_addr constant
+}
+
+namespace type3 {
+ struct DEFAULT TYPE_HIDDEN A {
+ virtual void foo();
+ };
+
+ void A::foo() {}
+ // FUNS: define void @_ZN5type31A3fooEv(
+ // VARS: @_ZTVN5type31AE = hidden unnamed_addr constant
+ // VARS: @_ZTSN5type31AE = hidden constant
+ // VARS: @_ZTIN5type31AE = hidden unnamed_addr constant
+ // FUNS-HIDDEN: define void @_ZN5type31A3fooEv(
+ // VARS-HIDDEN: @_ZTVN5type31AE = hidden unnamed_addr constant
+ // VARS-HIDDEN: @_ZTSN5type31AE = hidden constant
+ // VARS-HIDDEN: @_ZTIN5type31AE = hidden unnamed_addr constant
+}
+
diff --git a/test/CodeGenCXX/typeid.cpp b/test/CodeGenCXX/typeid.cpp
index fce3795..a1bc967 100644
--- a/test/CodeGenCXX/typeid.cpp
+++ b/test/CodeGenCXX/typeid.cpp
@@ -31,7 +31,7 @@ const std::type_info &a_ti = typeid(a);
const char *f() {
try {
// CHECK: br i1
- // CHECK: invoke void @__cxa_bad_typeid() noreturn
+ // CHECK: invoke void @__cxa_bad_typeid() [[NR:#[0-9]+]]
return typeid(*static_cast<A *>(0)).name();
} catch (...) {
// CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
@@ -42,3 +42,5 @@ const char *f() {
}
}
+
+// CHECK: attributes [[NR]] = { noreturn }
diff --git a/test/CodeGenCXX/value-init.cpp b/test/CodeGenCXX/value-init.cpp
index 6e60f80..60dca99 100644
--- a/test/CodeGenCXX/value-init.cpp
+++ b/test/CodeGenCXX/value-init.cpp
@@ -256,6 +256,12 @@ namespace PR11124 {
// CHECK-NEXT: call void @_ZN7PR111242B2C2Ev
}
+// Ensure we produce an i1 here, and don't assert.
+// CHECK: define void @_Z9r170806_bv(
+// CHECK: call void @_Z9r170806_ab(i1 zeroext false)
+void r170806_a(bool b = bool());
+void r170806_b() { r170806_a(); }
+
// CHECK: define linkonce_odr void @_ZN8zeroinit2X3IiEC2Ev(%"struct.zeroinit::X3"* %this) unnamed_addr
// CHECK: call void @llvm.memset.p0i8.i64
// CHECK-NEXT: call void @_ZN8zeroinit2X2IiEC2Ev
diff --git a/test/CodeGenCXX/virtual-base-cast.cpp b/test/CodeGenCXX/virtual-base-cast.cpp
index 73b7c1c..f469636 100644
--- a/test/CodeGenCXX/virtual-base-cast.cpp
+++ b/test/CodeGenCXX/virtual-base-cast.cpp
@@ -11,23 +11,25 @@ struct D : virtual C, virtual CC { int e; };
D* x;
A* a() { return x; }
-// CHECK: @_Z1av() nounwind
+// CHECK: @_Z1av() [[NUW:#[0-9]+]]
// CHECK: [[VBASEOFFSETPTRA:%[a-zA-Z0-9\.]+]] = getelementptr i8* {{.*}}, i64 -16
// CHECK: [[CASTVBASEOFFSETPTRA:%[a-zA-Z0-9\.]+]] = bitcast i8* [[VBASEOFFSETPTRA]] to i32*
// CHECK: load i32* [[CASTVBASEOFFSETPTRA]]
// CHECK: }
B* b() { return x; }
-// CHECK: @_Z1bv() nounwind
+// CHECK: @_Z1bv() [[NUW]]
// CHECK: [[VBASEOFFSETPTRA:%[a-zA-Z0-9\.]+]] = getelementptr i8* {{.*}}, i64 -20
// CHECK: [[CASTVBASEOFFSETPTRA:%[a-zA-Z0-9\.]+]] = bitcast i8* [[VBASEOFFSETPTRA]] to i32*
// CHECK: load i32* [[CASTVBASEOFFSETPTRA]]
// CHECK: }
BB* c() { return x; }
-// CHECK: @_Z1cv() nounwind
+// CHECK: @_Z1cv() [[NUW]]
// CHECK: [[VBASEOFFSETPTRC:%[a-zA-Z0-9\.]+]] = getelementptr i8* {{.*}}, i64 -24
// CHECK: [[CASTVBASEOFFSETPTRC:%[a-zA-Z0-9\.]+]] = bitcast i8* [[VBASEOFFSETPTRC]] to i32*
// CHECK: [[VBASEOFFSETC:%[a-zA-Z0-9\.]+]] = load i32* [[CASTVBASEOFFSETPTRC]]
// CHECK: add i32 [[VBASEOFFSETC]], 8
// CHECK: }
+
+// CHECK: attributes [[NUW]] = { nounwind{{.*}} }
diff --git a/test/CodeGenCXX/virtual-function-calls.cpp b/test/CodeGenCXX/virtual-function-calls.cpp
index 46e7b2d..e1b380f 100644
--- a/test/CodeGenCXX/virtual-function-calls.cpp
+++ b/test/CodeGenCXX/virtual-function-calls.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -std=c++11 -emit-llvm -o - | FileCheck %s
// PR5021
namespace PR5021 {
@@ -36,3 +36,16 @@ namespace Test1 {
b->f();
}
}
+
+namespace VirtualNoreturn {
+ struct A {
+ [[noreturn]] virtual void f();
+ };
+
+ // CHECK: @_ZN15VirtualNoreturn1f
+ void f(A *p) {
+ p->f();
+ // CHECK: call void %{{[^#]*$}}
+ // CHECK-NOT: unreachable
+ }
+}
diff --git a/test/CodeGenCXX/visibility-inlines-hidden.cpp b/test/CodeGenCXX/visibility-inlines-hidden.cpp
index 8519c8c..e5bc743 100644
--- a/test/CodeGenCXX/visibility-inlines-hidden.cpp
+++ b/test/CodeGenCXX/visibility-inlines-hidden.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple i386-unknown-unknown -fvisibility-inlines-hidden -emit-llvm -o - %s -O2 -disable-llvm-optzns | FileCheck %s
+// RUN: %clang_cc1 -triple i386-unknown-unknown -std=c++11 -fvisibility-inlines-hidden -emit-llvm -o - %s -O2 -disable-llvm-optzns | FileCheck %s
// The trickery with optimization in the run line is to get IR
// generation to emit available_externally function bodies, but not
@@ -135,3 +135,30 @@ namespace test4 {
}
// CHECK: define available_externally void @_ZN5test43fooE
}
+
+namespace test5 {
+ // just don't crash.
+ template <int> inline void Op();
+ class UnaryInstruction {
+ UnaryInstruction() {
+ Op<0>();
+ }
+ };
+ template <int Idx_nocapture> void Op() {
+ }
+}
+
+namespace test6 {
+ // just don't crash.
+ template <typename T>
+ void f(T x) {
+ }
+ struct C {
+ static void g() {
+ f([](){});
+ }
+ };
+ void g() {
+ C::g();
+ }
+}
diff --git a/test/CodeGenCXX/visibility-ms-compat.cpp b/test/CodeGenCXX/visibility-ms-compat.cpp
new file mode 100644
index 0000000..58a8fed
--- /dev/null
+++ b/test/CodeGenCXX/visibility-ms-compat.cpp
@@ -0,0 +1,112 @@
+// RUN: %clang_cc1 %s -std=c++11 -triple=x86_64-apple-darwin10 -fvisibility hidden -ftype-visibility default -emit-llvm -o %t
+// RUN: FileCheck %s < %t
+// RUN: FileCheck -check-prefix=CHECK-GLOBAL %s < %t
+
+// The two visibility options above are how we translate
+// -fvisibility-ms-compat in the driver.
+
+// rdar://13079314
+
+#define HIDDEN __attribute__((visibility("hidden")))
+#define PROTECTED __attribute__((visibility("protected")))
+#define DEFAULT __attribute__((visibility("default")))
+
+namespace std {
+ class type_info;
+};
+
+namespace test0 {
+ struct A {
+ static void foo();
+ static void bar();
+ };
+
+ void A::foo() { bar(); }
+ // CHECK: define hidden void @_ZN5test01A3fooEv()
+ // CHECK: declare void @_ZN5test01A3barEv()
+
+ const std::type_info &ti = typeid(A);
+ // CHECK-GLOBAL: @_ZTSN5test01AE = linkonce_odr constant
+ // CHECK-GLOBAL: @_ZTIN5test01AE = linkonce_odr unnamed_addr constant
+ // CHECK-GLOBAL: @_ZN5test02tiE = hidden constant
+}
+
+namespace test1 {
+ struct HIDDEN A {
+ static void foo();
+ static void bar();
+ };
+
+ void A::foo() { bar(); }
+ // CHECK: define hidden void @_ZN5test11A3fooEv()
+ // CHECK: declare hidden void @_ZN5test11A3barEv()
+
+ const std::type_info &ti = typeid(A);
+ // CHECK-GLOBAL: @_ZTSN5test11AE = linkonce_odr hidden constant
+ // CHECK-GLOBAL: @_ZTIN5test11AE = linkonce_odr hidden unnamed_addr constant
+ // CHECK-GLOBAL: @_ZN5test12tiE = hidden constant
+}
+
+namespace test2 {
+ struct DEFAULT A {
+ static void foo();
+ static void bar();
+ };
+
+ void A::foo() { bar(); }
+ // CHECK: define void @_ZN5test21A3fooEv()
+ // CHECK: declare void @_ZN5test21A3barEv()
+
+ const std::type_info &ti = typeid(A);
+ // CHECK-GLOBAL: @_ZTSN5test21AE = linkonce_odr constant
+ // CHECK-GLOBAL: @_ZTIN5test21AE = linkonce_odr unnamed_addr constant
+ // CHECK-GLOBAL: @_ZN5test22tiE = hidden constant
+}
+
+namespace test3 {
+ struct A { int x; };
+ template <class T> struct B {
+ static void foo() { bar(); }
+ static void bar();
+ };
+
+ template void B<A>::foo();
+ // CHECK: define weak_odr hidden void @_ZN5test31BINS_1AEE3fooEv()
+ // CHECK: declare void @_ZN5test31BINS_1AEE3barEv()
+
+ const std::type_info &ti = typeid(B<A>);
+ // CHECK-GLOBAL: @_ZTSN5test31BINS_1AEEE = linkonce_odr constant
+ // CHECK-GLOBAL: @_ZTIN5test31BINS_1AEEE = linkonce_odr unnamed_addr constant
+}
+
+namespace test4 {
+ struct A { int x; };
+ template <class T> struct DEFAULT B {
+ static void foo() { bar(); }
+ static void bar();
+ };
+
+ template void B<A>::foo();
+ // CHECK: define weak_odr void @_ZN5test41BINS_1AEE3fooEv()
+ // CHECK: declare void @_ZN5test41BINS_1AEE3barEv()
+
+ const std::type_info &ti = typeid(B<A>);
+ // CHECK-GLOBAL: @_ZTSN5test41BINS_1AEEE = linkonce_odr constant
+ // CHECK-GLOBAL: @_ZTIN5test41BINS_1AEEE = linkonce_odr unnamed_addr constant
+}
+
+namespace test5 {
+ struct A { int x; };
+ template <class T> struct HIDDEN B {
+ static void foo() { bar(); }
+ static void bar();
+ };
+
+ template void B<A>::foo();
+ // CHECK: define weak_odr hidden void @_ZN5test51BINS_1AEE3fooEv()
+ // CHECK: declare hidden void @_ZN5test51BINS_1AEE3barEv()
+
+ const std::type_info &ti = typeid(B<A>);
+ // CHECK-GLOBAL: @_ZTSN5test51BINS_1AEEE = linkonce_odr hidden constant
+ // CHECK-GLOBAL: @_ZTIN5test51BINS_1AEEE = linkonce_odr hidden unnamed_addr constant
+}
diff --git a/test/CodeGenCXX/visibility.cpp b/test/CodeGenCXX/visibility.cpp
index 0145039..87add44 100644
--- a/test/CodeGenCXX/visibility.cpp
+++ b/test/CodeGenCXX/visibility.cpp
@@ -47,7 +47,7 @@ namespace test29 {
struct RECT {
int top;
};
- __attribute__ ((visibility ("default"))) extern RECT data_rect;
+ DEFAULT extern RECT data_rect;
RECT data_rect = { -1};
#pragma GCC visibility pop
// CHECK: @_ZN6test299data_rectE = global
@@ -70,7 +70,7 @@ namespace test41 {
// Unlike gcc we propagate the information that foo not only is hidden, but
// has been explicitly marked as so. This lets us produce a hidden undefined
// reference to bar.
- struct __attribute__((visibility("hidden"))) foo {};
+ struct HIDDEN foo {};
extern foo bar;
foo *zed() {
return &bar;
@@ -119,7 +119,7 @@ namespace test48 {
namespace test27 {
template<typename T>
class C {
- class __attribute__((visibility("default"))) D {
+ class DEFAULT D {
void f();
};
};
@@ -526,7 +526,7 @@ namespace Test20 {
namespace test21 {
enum En { en };
template<En> struct A {
- __attribute__((visibility("default"))) void foo() {}
+ DEFAULT void foo() {}
};
// CHECK: define weak_odr void @_ZN6test211AILNS_2EnE0EE3fooEv(
@@ -580,9 +580,7 @@ namespace PR10113 {
};
template class foo::bar<zed>;
// CHECK: define weak_odr void @_ZN7PR101133foo3barINS_3zedEE3zedEv
-
- // FIXME: This should be hidden as zed is hidden.
- // CHECK-HIDDEN: define weak_odr void @_ZN7PR101133foo3barINS_3zedEE3zedEv
+ // CHECK-HIDDEN: define weak_odr hidden void @_ZN7PR101133foo3barINS_3zedEE3zedEv
}
namespace PR11690 {
@@ -613,9 +611,7 @@ namespace PR11690_2 {
};
template class foo::zed<baz>;
// CHECK: define weak_odr void @_ZN9PR11690_23foo3zedINS_3bazENS0_3barEE3barEv
-
- // FIXME: This should be hidden as baz is hidden.
- // CHECK-HIDDEN: define weak_odr void @_ZN9PR11690_23foo3zedINS_3bazENS0_3barEE3barEv
+ // CHECK-HIDDEN: define weak_odr hidden void @_ZN9PR11690_23foo3zedINS_3bazENS0_3barEE3barEv
}
namespace test23 {
@@ -670,7 +666,7 @@ namespace test24 {
namespace test26 {
template<typename T>
class C {
- __attribute__((visibility("default"))) void f();
+ DEFAULT void f();
};
template<>
@@ -729,10 +725,10 @@ namespace test34 {
namespace test35 {
// This is a really ugly testcase. GCC propagates the DEFAULT in zed's
- // definition. What we do instead is be conservative about merging
- // implicit visibilities.
- // FIXME: Maybe the best thing to do here is error? The test at least
- // makes sure we don't produce a hidden symbol for foo<zed>::bar.
+ // definition. It's not really clear what we can do here, because we
+ // produce the symbols before even seeing the DEFAULT definition of zed.
+ // FIXME: Maybe the best thing to do here is error? It's certainly hard
+ // to argue that this ought to be valid.
template<typename T>
struct DEFAULT foo {
void bar() {}
@@ -742,7 +738,7 @@ namespace test35 {
class DEFAULT zed {
};
// CHECK: define weak_odr void @_ZN6test353fooINS_3zedEE3barEv
- // CHECK-HIDDEN: define weak_odr void @_ZN6test353fooINS_3zedEE3barEv
+ // CHECK-HIDDEN: define weak_odr hidden void @_ZN6test353fooINS_3zedEE3barEv
}
namespace test36 {
@@ -821,8 +817,8 @@ namespace test42 {
};
void bar<foo>::zed() {
}
- // CHECK: define hidden void @_ZN6test423barINS_3fooEE3zedEv
- // CHECK-HIDDEN: define hidden void @_ZN6test423barINS_3fooEE3zedEv
+ // CHECK: define void @_ZN6test423barINS_3fooEE3zedEv
+ // CHECK-HIDDEN: define void @_ZN6test423barINS_3fooEE3zedEv
}
namespace test43 {
@@ -834,8 +830,8 @@ namespace test43 {
template <>
DEFAULT void bar<foo>() {
}
- // CHECK: define hidden void @_ZN6test433barINS_3fooEEEvv
- // CHECK-HIDDEN: define hidden void @_ZN6test433barINS_3fooEEEvv
+ // CHECK: define void @_ZN6test433barINS_3fooEEEvv
+ // CHECK-HIDDEN: define void @_ZN6test433barINS_3fooEEEvv
}
namespace test44 {
@@ -893,7 +889,7 @@ namespace test47 {
namespace {
struct zed;
}
- template __attribute__((visibility("default"))) void foo::bar<zed>();
+ template DEFAULT void foo::bar<zed>();
void baz() {
foo::bar<zed>();
}
@@ -1021,7 +1017,7 @@ namespace test54 {
namespace test55 {
template <class T>
- struct __attribute__((visibility("hidden"))) foo {
+ struct HIDDEN foo {
static void bar();
};
template <class T> struct foo;
@@ -1035,7 +1031,7 @@ namespace test55 {
namespace test56 {
template <class T> struct foo;
template <class T>
- struct __attribute__((visibility("hidden"))) foo {
+ struct HIDDEN foo {
static void bar();
};
void foobar() {
@@ -1066,7 +1062,7 @@ namespace test58 {
#pragma GCC visibility push(hidden)
struct foo;
template<typename T>
- struct __attribute__((visibility("default"))) bar {
+ struct DEFAULT bar {
static void zed() {
}
};
@@ -1097,9 +1093,9 @@ namespace test59 {
namespace test60 {
template<int i>
- class __attribute__((visibility("hidden"))) a {};
+ class HIDDEN a {};
template<int i>
- class __attribute__((visibility("default"))) b {};
+ class DEFAULT b {};
template<template<int> class x, template<int> class y>
void test() {}
void use() {
@@ -1112,3 +1108,172 @@ namespace test60 {
// CHECK-HIDDEN: define linkonce_odr hidden void @_ZN6test604testINS_1bENS_1aEEEvv
}
}
+
+namespace test61 {
+ template <typename T1>
+ struct Class1
+ {
+ void f1() { f2(); }
+ inline void f2();
+ };
+ template<>
+ inline void Class1<int>::f2()
+ {
+ }
+ void g(Class1<int> *x) {
+ x->f1();
+ }
+}
+namespace test61 {
+ // Just test that we don't crash. Currently we apply this attribute. Current
+ // gcc issues a warning about it being unused since "the type is already
+ // defined". We should probably do the same.
+ template class HIDDEN Class1<int>;
+}
+
+namespace test62 {
+ template <typename T1>
+ struct Class1
+ {
+ void f1() { f2(); }
+ inline void f2() {}
+ };
+ template<>
+ inline void Class1<int>::f2()
+ {
+ }
+ void g(Class1<int> *x) {
+ x->f2();
+ }
+}
+namespace test62 {
+ template class HIDDEN Class1<int>;
+ // Just test that we don't crash. Currently we apply this attribute. Current
+ // gcc issues a warning about it being unused since "the type is already
+ // defined". We should probably do the same.
+}
+
+namespace test63 {
+ enum HIDDEN E { E0 };
+ struct A {
+ template <E> static void foo() {}
+
+ template <E> struct B {
+ static void foo() {}
+ };
+ };
+
+ void test() {
+ A::foo<E0>();
+ A::B<E0>::foo();
+ }
+ // CHECK: define linkonce_odr hidden void @_ZN6test631A3fooILNS_1EE0EEEvv()
+ // CHECK: define linkonce_odr hidden void @_ZN6test631A1BILNS_1EE0EE3fooEv()
+}
+
+// Don't ignore the visibility of template arguments just because we
+// explicitly instantiated something.
+namespace test64 {
+ struct HIDDEN A {};
+ template <class P> struct B {
+ static DEFAULT void foo() {}
+ };
+
+ template class B<A>;
+ // CHECK: define weak_odr hidden void @_ZN6test641BINS_1AEE3fooEv()
+}
+
+namespace test65 {
+ class HIDDEN A {};
+ template <class T> struct B {
+ static void func();
+ template <class U> static void funcT1();
+ template <class U> static void funcT2();
+ class Inner {};
+ template <class U> class InnerT {};
+ };
+ template <template <class T> class Temp> struct C {
+ static void foo() {}
+ };
+
+ // CHECK: define void @_ZN6test651BINS_1AEE4funcEv()
+ template <> DEFAULT void B<A>::func() {}
+
+ // CHECK: define void @_ZN6test651BINS_1AEE6funcT2IS1_EEvv()
+ template <> template <> DEFAULT void B<A>::funcT2<A>() {}
+
+ // CHECK: define linkonce_odr void @_ZN6test651BINS_1AEE6funcT1IiEEvv()
+ // CHECK: define linkonce_odr hidden void @_ZN6test651BINS_1AEE6funcT1IS1_EEvv()
+ template <> template <class T> DEFAULT void B<A>::funcT1() {}
+
+ // CHECK: define linkonce_odr void @_ZN6test651BINS_1AEE5Inner3fooEv()
+ template <> struct DEFAULT B<A>::Inner {
+ static void foo() {}
+ };
+
+ // CHECK: define linkonce_odr void @_ZN6test651BINS_1AEE6InnerTIiE3fooEv()
+ // CHECK: define linkonce_odr hidden void @_ZN6test651BINS_1AEE6InnerTIS1_E3fooEv()
+ template <> template <class U> struct DEFAULT B<A>::InnerT {
+ static void foo() {}
+ };
+
+ void test() {
+ B<A>::funcT1<int>();
+ B<A>::funcT1<A>();
+ B<A>::Inner::foo();
+ B<A>::InnerT<int>::foo();
+ B<A>::InnerT<A>::foo();
+ }
+
+ template class C<B<A>::InnerT>;
+}
+
+namespace test66 {
+ template <typename T>
+ struct DEFAULT barT {
+ static void zed() {}
+ };
+ class foo;
+ class DEFAULT foo;
+ template struct barT<foo>;
+ // CHECK: define weak_odr void @_ZN6test664barTINS_3fooEE3zedEv
+ // CHECK-HIDDEN: define weak_odr void @_ZN6test664barTINS_3fooEE3zedEv
+
+ template <int* I>
+ struct DEFAULT barI {
+ static void zed() {}
+ };
+ extern int I;
+ extern int I DEFAULT;
+ template struct barI<&I>;
+ // CHECK: define weak_odr void @_ZN6test664barIIXadL_ZNS_1IEEEE3zedEv
+ // CHECK-HIDDEN: define weak_odr void @_ZN6test664barIIXadL_ZNS_1IEEEE3zedEv
+
+ typedef void (*fType)(void);
+ template<fType F>
+ struct DEFAULT barF {
+ static void zed() {}
+ };
+ void F();
+ void F() DEFAULT;
+ template struct barF<F>;
+ // CHECK: define weak_odr void @_ZN6test664barFIXadL_ZNS_1FEvEEE3zedEv
+ // CHECK-HIDDEN: define weak_odr void @_ZN6test664barFIXadL_ZNS_1FEvEEE3zedEv
+}
+
+namespace test67 {
+ template <typename T>
+ struct DEFAULT bar {
+ static void zed() {}
+ };
+
+ class foo;
+ class compute {
+ void f(foo *rootfoo);
+ };
+ class DEFAULT foo;
+
+ template struct bar<foo>;
+ // CHECK: define weak_odr void @_ZN6test673barINS_3fooEE3zedEv
+ // CHECK-HIDDEN: define weak_odr void @_ZN6test673barINS_3fooEE3zedEv
+}
diff --git a/test/CodeGenCXX/vtable-available-externally.cpp b/test/CodeGenCXX/vtable-available-externally.cpp
index 23baac9..693b36a 100644
--- a/test/CodeGenCXX/vtable-available-externally.cpp
+++ b/test/CodeGenCXX/vtable-available-externally.cpp
@@ -6,13 +6,14 @@
#include <typeinfo>
-// Test1::A's key function (f) is not defined in this translation unit, but in
-// order to devirtualize calls, we emit the class related data with
+// Test1::A's key function (f) is not defined in this translation
+// unit, but in order to devirtualize calls, we emit the v-table with
// available_externally linkage.
+//
+// There's no real reason to do this to the RTTI, though.
// CHECK-TEST1: @_ZTVN5Test11AE = available_externally
-// CHECK-TEST1: @_ZTSN5Test11AE = available_externally
-// CHECK-TEST1: @_ZTIN5Test11AE = available_externally
+// CHECK-TEST1: @_ZTIN5Test11AE = external constant i8*
namespace Test1 {
struct A {
diff --git a/test/CodeGenCXX/vtable-key-function-arm.cpp b/test/CodeGenCXX/vtable-key-function-arm.cpp
new file mode 100644
index 0000000..08efe8a
--- /dev/null
+++ b/test/CodeGenCXX/vtable-key-function-arm.cpp
@@ -0,0 +1,307 @@
+// RUN: %clang_cc1 %s -triple=armv7-unknown-unknown -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -triple=armv7-unknown-unknown -emit-llvm -o - | FileCheck -check-prefix=CHECK-LATE %s
+
+// The 'a' variants ask for the v-table first.
+// The 'b' variants ask for the v-table second.
+// The 'c' variants ask for the v-table third.
+// We do a separate CHECK-LATE pass because the RTTI defintion gets
+// changed after the fact, which causes reordering of the globals.
+
+// These are not separated into namespaces because the way that Sema
+// currently reports namespaces to IR-generation (i.e., en masse for
+// the entire namespace at once) subverts the ordering that we're
+// trying to test.
+
+namespace std { class type_info; }
+extern void use(const std::type_info &rtti);
+
+/*** Test0a ******************************************************************/
+
+struct Test0a {
+ Test0a();
+ virtual inline void foo();
+ virtual void bar();
+};
+
+// V-table should be defined externally.
+Test0a::Test0a() { use(typeid(Test0a)); }
+// CHECK: @_ZTV6Test0a = external unnamed_addr constant
+// CHECK: @_ZTI6Test0a = external constant
+
+// This is still not a key function.
+void Test0a::foo() {}
+
+/*** Test0b ******************************************************************/
+
+struct Test0b {
+ Test0b();
+ virtual inline void foo();
+ virtual void bar();
+};
+
+// This is still not a key function.
+void Test0b::foo() {}
+
+// V-table should be defined externally.
+Test0b::Test0b() { use(typeid(Test0b)); }
+// CHECK: @_ZTV6Test0b = external unnamed_addr constant
+// CHECK: @_ZTI6Test0b = external constant
+
+/*** Test1a ******************************************************************/
+
+struct Test1a {
+ Test1a();
+ virtual void foo();
+ virtual void bar();
+};
+
+// V-table should be defined externally.
+Test1a::Test1a() { use(typeid(Test1a)); }
+// CHECK: @_ZTV6Test1a = external unnamed_addr constant
+// CHECK: @_ZTI6Test1a = external constant
+
+// 'bar' becomes the key function when 'foo' is defined inline.
+inline void Test1a::foo() {}
+
+/*** Test1b ******************************************************************/
+
+struct Test1b {
+ Test1b();
+ virtual void foo();
+ virtual void bar();
+};
+
+// 'bar' becomes the key function when 'foo' is defined inline.
+inline void Test1b::foo() {}
+
+// V-table should be defined externally.
+Test1b::Test1b() { use(typeid(Test1b)); }
+// CHECK: @_ZTV6Test1b = external unnamed_addr constant
+// CHECK: @_ZTI6Test1b = external constant
+
+/*** Test2a ******************************************************************/
+
+struct Test2a {
+ Test2a();
+ virtual void foo();
+ virtual void bar();
+};
+
+// V-table should be defined with strong linkage.
+Test2a::Test2a() { use(typeid(Test2a)); }
+// CHECK: @_ZTV6Test2a = unnamed_addr constant
+// CHECK-LATE: @_ZTS6Test2a = constant
+// CHECK-LATE: @_ZTI6Test2a = unnamed_addr constant
+
+// 'bar' becomes the key function when 'foo' is defined inline.
+void Test2a::bar() {}
+inline void Test2a::foo() {}
+
+/*** Test2b ******************************************************************/
+
+struct Test2b {
+ Test2b();
+ virtual void foo();
+ virtual void bar();
+};
+
+// 'bar' becomes the key function when 'foo' is defined inline.
+void Test2b::bar() {}
+
+// V-table should be defined with strong linkage.
+Test2b::Test2b() { use(typeid(Test2b)); }
+// CHECK: @_ZTV6Test2b = unnamed_addr constant
+// CHECK-LATE: @_ZTS6Test2b = constant
+// CHECK-LATE: @_ZTI6Test2b = unnamed_addr constant
+
+inline void Test2b::foo() {}
+
+/*** Test2c ******************************************************************/
+
+struct Test2c {
+ Test2c();
+ virtual void foo();
+ virtual void bar();
+};
+
+// 'bar' becomes the key function when 'foo' is defined inline.
+void Test2c::bar() {}
+inline void Test2c::foo() {}
+
+// V-table should be defined with strong linkage.
+Test2c::Test2c() { use(typeid(Test2c)); }
+// CHECK: @_ZTV6Test2c = unnamed_addr constant
+// CHECK: @_ZTS6Test2c = constant
+// CHECK: @_ZTI6Test2c = unnamed_addr constant
+
+/*** Test3a ******************************************************************/
+
+struct Test3a {
+ Test3a();
+ virtual void foo();
+ virtual void bar();
+};
+
+// V-table should be defined with weak linkage.
+Test3a::Test3a() { use(typeid(Test3a)); }
+// CHECK: @_ZTV6Test3a = linkonce_odr unnamed_addr constant
+// CHECK-LATE: @_ZTS6Test3a = linkonce_odr constant
+// CHECK-LATE: @_ZTI6Test3a = linkonce_odr unnamed_addr constant
+
+// There ceases to be a key function after these declarations.
+inline void Test3a::bar() {}
+inline void Test3a::foo() {}
+
+/*** Test3b ******************************************************************/
+
+struct Test3b {
+ Test3b();
+ virtual void foo();
+ virtual void bar();
+};
+
+// There ceases to be a key function after these declarations.
+inline void Test3b::bar() {}
+
+// V-table should be defined with weak linkage.
+Test3b::Test3b() { use(typeid(Test3b)); }
+// CHECK: @_ZTV6Test3b = linkonce_odr unnamed_addr constant
+// CHECK-LATE: @_ZTS6Test3b = linkonce_odr constant
+// CHECK-LATE: @_ZTI6Test3b = linkonce_odr unnamed_addr constant
+
+inline void Test3b::foo() {}
+
+/*** Test3c ******************************************************************/
+
+struct Test3c {
+ Test3c();
+ virtual void foo();
+ virtual void bar();
+};
+
+// There ceases to be a key function after these declarations.
+inline void Test3c::bar() {}
+inline void Test3c::foo() {}
+
+// V-table should be defined with weak linkage.
+Test3c::Test3c() { use(typeid(Test3c)); }
+// CHECK: @_ZTV6Test3c = linkonce_odr unnamed_addr constant
+// CHECK: @_ZTS6Test3c = linkonce_odr constant
+// CHECK: @_ZTI6Test3c = linkonce_odr unnamed_addr constant
+
+/*** Test4a ******************************************************************/
+
+template <class T> struct Test4a {
+ Test4a();
+ virtual void foo();
+ virtual void bar();
+};
+
+// V-table should be defined with weak linkage.
+template <> Test4a<int>::Test4a() { use(typeid(Test4a)); }
+// CHECK: @_ZTV6Test4aIiE = linkonce_odr unnamed_addr constant
+// CHECK: @_ZTS6Test4aIiE = linkonce_odr constant
+// CHECK: @_ZTI6Test4aIiE = linkonce_odr unnamed_addr constant
+
+// There ceases to be a key function after these declarations.
+template <> inline void Test4a<int>::bar() {}
+template <> inline void Test4a<int>::foo() {}
+
+/*** Test4b ******************************************************************/
+
+template <class T> struct Test4b {
+ Test4b();
+ virtual void foo();
+ virtual void bar();
+};
+
+// There ceases to be a key function after these declarations.
+template <> inline void Test4b<int>::bar() {}
+
+// V-table should be defined with weak linkage.
+template <> Test4b<int>::Test4b() { use(typeid(Test4b)); }
+// CHECK: @_ZTV6Test4bIiE = linkonce_odr unnamed_addr constant
+// CHECK: @_ZTS6Test4bIiE = linkonce_odr constant
+// CHECK: @_ZTI6Test4bIiE = linkonce_odr unnamed_addr constant
+
+template <> inline void Test4b<int>::foo() {}
+
+/*** Test4c ******************************************************************/
+
+template <class T> struct Test4c {
+ Test4c();
+ virtual void foo();
+ virtual void bar();
+};
+
+// There ceases to be a key function after these declarations.
+template <> inline void Test4c<int>::bar() {}
+template <> inline void Test4c<int>::foo() {}
+
+// V-table should be defined with weak linkage.
+template <> Test4c<int>::Test4c() { use(typeid(Test4c)); }
+// CHECK: @_ZTV6Test4cIiE = linkonce_odr unnamed_addr constant
+// CHECK: @_ZTS6Test4cIiE = linkonce_odr constant
+// CHECK: @_ZTI6Test4cIiE = linkonce_odr unnamed_addr constant
+
+/*** Test5a ******************************************************************/
+
+template <class T> struct Test5a {
+ Test5a();
+ virtual void foo();
+ virtual void bar();
+};
+
+template <> inline void Test5a<int>::bar();
+template <> inline void Test5a<int>::foo();
+
+// V-table should be defined with weak linkage.
+template <> Test5a<int>::Test5a() { use(typeid(Test5a)); }
+// CHECK: @_ZTV6Test5aIiE = linkonce_odr unnamed_addr constant
+// CHECK: @_ZTS6Test5aIiE = linkonce_odr constant
+// CHECK: @_ZTI6Test5aIiE = linkonce_odr unnamed_addr constant
+
+// There ceases to be a key function after these declarations.
+template <> inline void Test5a<int>::bar() {}
+template <> inline void Test5a<int>::foo() {}
+
+/*** Test5b ******************************************************************/
+
+template <class T> struct Test5b {
+ Test5b();
+ virtual void foo();
+ virtual void bar();
+};
+
+// There ceases to be a key function after these declarations.
+template <> inline void Test5a<int>::bar();
+template <> inline void Test5b<int>::bar() {}
+
+// V-table should be defined with weak linkage.
+template <> Test5b<int>::Test5b() { use(typeid(Test5b)); }
+// CHECK: @_ZTV6Test5bIiE = linkonce_odr unnamed_addr constant
+// CHECK: @_ZTS6Test5bIiE = linkonce_odr constant
+// CHECK: @_ZTI6Test5bIiE = linkonce_odr unnamed_addr constant
+
+template <> inline void Test5a<int>::foo();
+template <> inline void Test5b<int>::foo() {}
+
+/*** Test5c ******************************************************************/
+
+template <class T> struct Test5c {
+ Test5c();
+ virtual void foo();
+ virtual void bar();
+};
+
+// There ceases to be a key function after these declarations.
+template <> inline void Test5a<int>::bar();
+template <> inline void Test5a<int>::foo();
+template <> inline void Test5c<int>::bar() {}
+template <> inline void Test5c<int>::foo() {}
+
+// V-table should be defined with weak linkage.
+template <> Test5c<int>::Test5c() { use(typeid(Test5c)); }
+// CHECK: @_ZTV6Test5cIiE = linkonce_odr unnamed_addr constant
+// CHECK: @_ZTS6Test5cIiE = linkonce_odr constant
+// CHECK: @_ZTI6Test5cIiE = linkonce_odr unnamed_addr constant
diff --git a/test/CodeGenCXX/vtable-key-function-ios.cpp b/test/CodeGenCXX/vtable-key-function-ios.cpp
new file mode 100644
index 0000000..bcd3e88
--- /dev/null
+++ b/test/CodeGenCXX/vtable-key-function-ios.cpp
@@ -0,0 +1,189 @@
+// RUN: %clang_cc1 %s -triple=armv7-apple-darwin -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -triple=armv7-apple-darwin -emit-llvm -o - | FileCheck -check-prefix=CHECK-LATE %s
+
+// The 'a' variants ask for the v-table first.
+// The 'b' variants ask for the v-table second.
+// The 'c' variants ask for the v-table third.
+// We do a separate CHECK-LATE pass because the RTTI defintion gets
+// changed after the fact, which causes reordering of the globals.
+
+// These are not separated into namespaces because the way that Sema
+// currently reports namespaces to IR-generation (i.e., en masse for
+// the entire namespace at once) subverts the ordering that we're
+// trying to test.
+
+namespace std { class type_info; }
+extern void use(const std::type_info &rtti);
+
+/*** Test0a ******************************************************************/
+
+struct Test0a {
+ Test0a();
+ virtual inline void foo();
+ virtual void bar();
+};
+
+// V-table should be defined externally.
+Test0a::Test0a() { use(typeid(Test0a)); }
+// CHECK: @_ZTV6Test0a = external unnamed_addr constant
+// CHECK: @_ZTI6Test0a = external constant
+
+// This is not a key function.
+void Test0a::foo() {}
+
+/*** Test0b ******************************************************************/
+
+struct Test0b {
+ Test0b();
+ virtual inline void foo();
+ virtual void bar();
+};
+
+// This is not a key function.
+void Test0b::foo() {}
+
+// V-table should be defined externally.
+Test0b::Test0b() { use(typeid(Test0b)); }
+// CHECK: @_ZTV6Test0b = external unnamed_addr constant
+// CHECK: @_ZTI6Test0b = external constant
+
+/*** Test1a ******************************************************************/
+
+struct Test1a {
+ Test1a();
+ virtual void foo();
+ virtual void bar();
+};
+
+// V-table needs to be defined weakly.
+Test1a::Test1a() { use(typeid(Test1a)); }
+// CHECK: @_ZTV6Test1a = linkonce_odr unnamed_addr constant
+// CHECK-LATE: @_ZTS6Test1a = linkonce_odr constant
+// CHECK-LATE: @_ZTI6Test1a = linkonce_odr unnamed_addr constant
+
+// This defines the key function.
+inline void Test1a::foo() {}
+
+/*** Test1b ******************************************************************/
+
+struct Test1b {
+ Test1b();
+ virtual void foo();
+ virtual void bar();
+};
+
+// This defines the key function.
+inline void Test1b::foo() {}
+
+// V-table should be defined weakly..
+Test1b::Test1b() { use(typeid(Test1b)); }
+// CHECK: @_ZTV6Test1b = linkonce_odr unnamed_addr constant
+// CHECK: @_ZTS6Test1b = linkonce_odr constant
+// CHECK: @_ZTI6Test1b = linkonce_odr unnamed_addr constant
+
+/*** Test2a ******************************************************************/
+
+struct Test2a {
+ Test2a();
+ virtual void foo();
+ virtual void bar();
+};
+
+// V-table should be defined with weak linkage.
+Test2a::Test2a() { use(typeid(Test2a)); }
+// CHECK: @_ZTV6Test2a = linkonce_odr unnamed_addr constant
+// CHECK-LATE: @_ZTS6Test2a = linkonce_odr constant
+// CHECK-LATE: @_ZTI6Test2a = linkonce_odr unnamed_addr constant
+
+void Test2a::bar() {}
+inline void Test2a::foo() {}
+
+/*** Test2b ******************************************************************/
+
+struct Test2b {
+ Test2b();
+ virtual void foo();
+ virtual void bar();
+};
+
+void Test2b::bar() {}
+
+// V-table should be defined with weak linkage.
+Test2b::Test2b() { use(typeid(Test2b)); }
+// CHECK: @_ZTV6Test2b = linkonce_odr unnamed_addr constant
+// CHECK-LATE: @_ZTS6Test2b = linkonce_odr constant
+// CHECK-LATE: @_ZTI6Test2b = linkonce_odr unnamed_addr constant
+
+inline void Test2b::foo() {}
+
+/*** Test2c ******************************************************************/
+
+struct Test2c {
+ Test2c();
+ virtual void foo();
+ virtual void bar();
+};
+
+void Test2c::bar() {}
+inline void Test2c::foo() {}
+
+// V-table should be defined with weak linkage.
+Test2c::Test2c() { use(typeid(Test2c)); }
+// CHECK: @_ZTV6Test2c = linkonce_odr unnamed_addr constant
+// CHECK: @_ZTS6Test2c = linkonce_odr constant
+// CHECK: @_ZTI6Test2c = linkonce_odr unnamed_addr constant
+
+/*** Test3a ******************************************************************/
+
+struct Test3a {
+ Test3a();
+ virtual void foo();
+ virtual void bar();
+};
+
+// V-table should be defined with weak linkage.
+Test3a::Test3a() { use(typeid(Test3a)); }
+// CHECK: @_ZTV6Test3a = linkonce_odr unnamed_addr constant
+// CHECK-LATE: @_ZTS6Test3a = linkonce_odr constant
+// CHECK-LATE: @_ZTI6Test3a = linkonce_odr unnamed_addr constant
+
+// This defines the key function.
+inline void Test3a::bar() {}
+inline void Test3a::foo() {}
+
+/*** Test3b ******************************************************************/
+
+struct Test3b {
+ Test3b();
+ virtual void foo();
+ virtual void bar();
+};
+
+inline void Test3b::bar() {}
+
+// V-table should be defined with weak linkage.
+Test3b::Test3b() { use(typeid(Test3b)); }
+// CHECK: @_ZTV6Test3b = linkonce_odr unnamed_addr constant
+// CHECK-LATE: @_ZTS6Test3b = linkonce_odr constant
+// CHECK-LATE: @_ZTI6Test3b = linkonce_odr unnamed_addr constant
+
+// This defines the key function.
+inline void Test3b::foo() {}
+
+/*** Test3c ******************************************************************/
+
+struct Test3c {
+ Test3c();
+ virtual void foo();
+ virtual void bar();
+};
+
+// This defines the key function.
+inline void Test3c::bar() {}
+inline void Test3c::foo() {}
+
+// V-table should be defined with weak linkage.
+Test3c::Test3c() { use(typeid(Test3c)); }
+// CHECK: @_ZTV6Test3c = linkonce_odr unnamed_addr constant
+// CHECK: @_ZTS6Test3c = linkonce_odr constant
+// CHECK: @_ZTI6Test3c = linkonce_odr unnamed_addr constant
diff --git a/test/CodeGenCXX/vtable-linkage.cpp b/test/CodeGenCXX/vtable-linkage.cpp
index 4633a3f..b945e56 100644
--- a/test/CodeGenCXX/vtable-linkage.cpp
+++ b/test/CodeGenCXX/vtable-linkage.cpp
@@ -1,5 +1,6 @@
// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o %t
// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -fhidden-weak-vtables -emit-llvm -o %t.hidden
+// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -disable-llvm-optzns -O3 -emit-llvm -o %t.opt
// RUN: FileCheck --check-prefix=CHECK-1 %s < %t
// RUN: FileCheck --check-prefix=CHECK-2 %s < %t
// RUN: FileCheck --check-prefix=CHECK-2-HIDDEN %s < %t.hidden
@@ -12,7 +13,9 @@
// RUN: FileCheck --check-prefix=CHECK-7 %s < %t
// RUN: FileCheck --check-prefix=CHECK-8 %s < %t
// RUN: FileCheck --check-prefix=CHECK-9 %s < %t
+// RUN: FileCheck --check-prefix=CHECK-9-OPT %s < %t.opt
// RUN: FileCheck --check-prefix=CHECK-10 %s < %t
+// RUN: FileCheck --check-prefix=CHECK-10-OPT %s < %t.opt
// RUN: FileCheck --check-prefix=CHECK-11 %s < %t
// RUN: FileCheck --check-prefix=CHECK-12 %s < %t
// RUN: FileCheck --check-prefix=CHECK-13 %s < %t
@@ -160,11 +163,13 @@ void use_F() {
// F<int> is an explicit template instantiation declaration without a
// key function, so its vtable should have external linkage.
// CHECK-9: @_ZTV1FIiE = external unnamed_addr constant
+// CHECK-9-OPT: @_ZTV1FIiE = available_externally unnamed_addr constant
// E<int> is an explicit template instantiation declaration. It has a
// key function that is not instantiated, so we should only reference
// its vtable, not define it.
// CHECK-10: @_ZTV1EIiE = external unnamed_addr constant
+// CHECK-10-OPT: @_ZTV1EIiE = available_externally unnamed_addr constant
// The anonymous struct for e has no linkage, so the vtable should have
// internal linkage.
@@ -214,3 +219,24 @@ public:
void use_H() {
H<int> h;
}
+
+// RUN: FileCheck --check-prefix=CHECK-I %s < %t
+// RUN: FileCheck --check-prefix=CHECK-I-OPT %s < %t.opt
+
+// I<int> has an explicit instantiation declaration and needs a VTT and
+// construction vtables. We emit the VTT available_externally, but point it at
+// internal construction vtables because there is no way to form a reference to
+// the real construction vtables.
+
+// CHECK-I: @_ZTV1IIiE = external unnamed_addr constant
+// CHECK-I: @_ZTT1IIiE = external unnamed_addr constant
+// CHECK-I-NOT: @_ZTC1IIiE
+//
+// CHECK-I-OPT: @_ZTV1IIiE = available_externally unnamed_addr constant
+// CHECK-I-OPT: @_ZTT1IIiE = available_externally unnamed_addr constant {{.*}} @_ZTC1IIiE0_6VBase2
+// CHECK-I-OPT: @_ZTC1IIiE0_6VBase2 = internal unnamed_addr constant
+struct VBase1 { virtual void f(); }; struct VBase2 : virtual VBase1 {};
+template<typename T>
+struct I : VBase2 {};
+extern template struct I<int>;
+I<int> i;
OpenPOWER on IntegriCloud