summaryrefslogtreecommitdiffstats
path: root/test/CodeGenCXX
diff options
context:
space:
mode:
Diffstat (limited to 'test/CodeGenCXX')
-rw-r--r--test/CodeGenCXX/2004-11-27-FriendDefaultArgCrash.cpp2
-rw-r--r--test/CodeGenCXX/2005-02-14-BitFieldOffset.cpp12
-rw-r--r--test/CodeGenCXX/2007-05-03-VectorInit.cpp2
-rw-r--r--test/CodeGenCXX/2010-05-10-Var-DbgInfo.cpp2
-rw-r--r--test/CodeGenCXX/DynArrayInit.cpp2
-rw-r--r--test/CodeGenCXX/PR5050-constructor-conversion.cpp4
-rw-r--r--test/CodeGenCXX/aarch64-mangle-neon-vectors.cpp85
-rw-r--r--test/CodeGenCXX/aarch64-neon.cpp13
-rw-r--r--test/CodeGenCXX/abstract-class-ctors-dtors.cpp8
-rw-r--r--test/CodeGenCXX/address-of-fntemplate.cpp4
-rw-r--r--test/CodeGenCXX/alloca-align.cpp6
-rw-r--r--test/CodeGenCXX/anonymous-namespaces.cpp21
-rw-r--r--test/CodeGenCXX/anonymous-union-member-initializer.cpp12
-rw-r--r--test/CodeGenCXX/apple-kext-indirect-virtual-dtor-call.cpp4
-rw-r--r--test/CodeGenCXX/apple-kext-linkage.C12
-rw-r--r--test/CodeGenCXX/arm-vaarg.cpp27
-rw-r--r--test/CodeGenCXX/arm.cpp52
-rw-r--r--test/CodeGenCXX/array-construction.cpp4
-rw-r--r--test/CodeGenCXX/array-operator-delete-call.cpp4
-rw-r--r--test/CodeGenCXX/atomic.cpp2
-rw-r--r--test/CodeGenCXX/atomicinit.cpp6
-rw-r--r--test/CodeGenCXX/attr-cleanup.cpp11
-rw-r--r--test/CodeGenCXX/attr.cpp2
-rw-r--r--test/CodeGenCXX/bitfield-layout.cpp4
-rw-r--r--test/CodeGenCXX/bitfield.cpp84
-rw-r--r--test/CodeGenCXX/block-byref-cxx-objc.cpp8
-rw-r--r--test/CodeGenCXX/block-in-ctor-dtor.cpp20
-rw-r--r--test/CodeGenCXX/blocks-cxx11.cpp4
-rw-r--r--test/CodeGenCXX/blocks.cpp28
-rw-r--r--test/CodeGenCXX/bool-bitfield.cpp4
-rw-r--r--test/CodeGenCXX/builtins.cpp21
-rw-r--r--test/CodeGenCXX/c-linkage.cpp6
-rw-r--r--test/CodeGenCXX/c99-variable-length-array.cpp2
-rw-r--r--test/CodeGenCXX/call-arg-zero-temp.cpp4
-rw-r--r--test/CodeGenCXX/captured-statements.cpp189
-rw-r--r--test/CodeGenCXX/cast-conversion.cpp4
-rw-r--r--test/CodeGenCXX/catch-undef-behavior.cpp158
-rw-r--r--test/CodeGenCXX/catch-undef-behavior2.cpp9
-rw-r--r--test/CodeGenCXX/compound-literals.cpp4
-rw-r--r--test/CodeGenCXX/condition.cpp8
-rw-r--r--test/CodeGenCXX/conditional-gnu-ext.cpp8
-rw-r--r--test/CodeGenCXX/conditional-temporaries.cpp6
-rw-r--r--test/CodeGenCXX/const-init-cxx11.cpp110
-rw-r--r--test/CodeGenCXX/const-init-cxx1y.cpp48
-rw-r--r--test/CodeGenCXX/const-init.cpp2
-rw-r--r--test/CodeGenCXX/constructor-attr.cpp2
-rw-r--r--test/CodeGenCXX/constructor-conversion.cpp4
-rw-r--r--test/CodeGenCXX/constructor-default-arg.cpp4
-rw-r--r--test/CodeGenCXX/constructor-destructor-return-this.cpp138
-rw-r--r--test/CodeGenCXX/constructor-for-array-members.cpp4
-rw-r--r--test/CodeGenCXX/constructor-init.cpp16
-rw-r--r--test/CodeGenCXX/constructor-template.cpp4
-rw-r--r--test/CodeGenCXX/constructors.cpp22
-rw-r--r--test/CodeGenCXX/conversion-function.cpp4
-rw-r--r--test/CodeGenCXX/convert-to-fptr.cpp4
-rw-r--r--test/CodeGenCXX/copy-assign-synthesis-1.cpp16
-rw-r--r--test/CodeGenCXX/copy-assign-synthesis-2.cpp2
-rw-r--r--test/CodeGenCXX/copy-assign-synthesis.cpp2
-rw-r--r--test/CodeGenCXX/copy-constructor-elim-2.cpp6
-rw-r--r--test/CodeGenCXX/copy-constructor-elim.cpp4
-rw-r--r--test/CodeGenCXX/copy-constructor-synthesis-2.cpp2
-rw-r--r--test/CodeGenCXX/copy-constructor-synthesis.cpp45
-rw-r--r--test/CodeGenCXX/copy-initialization.cpp2
-rw-r--r--test/CodeGenCXX/crash.cpp35
-rw-r--r--test/CodeGenCXX/ctor-dtor-alias.cpp163
-rw-r--r--test/CodeGenCXX/cxx-block-objects.cpp4
-rw-r--r--test/CodeGenCXX/cxx0x-delegating-ctors.cpp2
-rw-r--r--test/CodeGenCXX/cxx0x-initializer-array.cpp12
-rw-r--r--test/CodeGenCXX/cxx0x-initializer-constructors.cpp24
-rw-r--r--test/CodeGenCXX/cxx0x-initializer-stdinitializerlist-pr12086.cpp107
-rw-r--r--test/CodeGenCXX/cxx0x-initializer-stdinitializerlist-startend.cpp10
-rw-r--r--test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp202
-rw-r--r--test/CodeGenCXX/cxx11-exception-spec.cpp2
-rw-r--r--test/CodeGenCXX/cxx11-initializer-array-new.cpp106
-rw-r--r--test/CodeGenCXX/cxx11-thread-local-reference.cpp4
-rw-r--r--test/CodeGenCXX/cxx11-thread-local.cpp21
-rw-r--r--test/CodeGenCXX/cxx1y-deduced-return-type.cpp32
-rw-r--r--test/CodeGenCXX/cxx1y-init-captures.cpp102
-rw-r--r--test/CodeGenCXX/cxx1y-initializer-aggregate.cpp17
-rw-r--r--test/CodeGenCXX/cxx1y-sized-deallocation.cpp110
-rw-r--r--test/CodeGenCXX/cxx1y-variable-template.cpp24
-rw-r--r--test/CodeGenCXX/debug-info-artificial-arg.cpp8
-rw-r--r--test/CodeGenCXX/debug-info-class-limited.cpp52
-rw-r--r--test/CodeGenCXX/debug-info-class-nolimit.cpp30
-rw-r--r--test/CodeGenCXX/debug-info-class.cpp87
-rw-r--r--test/CodeGenCXX/debug-info-cxx1y.cpp7
-rw-r--r--test/CodeGenCXX/debug-info-decl-nested.cpp61
-rw-r--r--test/CodeGenCXX/debug-info-enum-class.cpp8
-rw-r--r--test/CodeGenCXX/debug-info-enum.cpp40
-rw-r--r--test/CodeGenCXX/debug-info-friend.cpp19
-rw-r--r--test/CodeGenCXX/debug-info-function-context.cpp36
-rw-r--r--test/CodeGenCXX/debug-info-gline-tables-only.cpp10
-rw-r--r--test/CodeGenCXX/debug-info-global-ctor-dtor.cpp6
-rw-r--r--test/CodeGenCXX/debug-info-globalinit.cpp12
-rw-r--r--test/CodeGenCXX/debug-info-limit-type.cpp24
-rw-r--r--test/CodeGenCXX/debug-info-limit.cpp14
-rw-r--r--test/CodeGenCXX/debug-info-limited.cpp33
-rw-r--r--test/CodeGenCXX/debug-info-method.cpp5
-rw-r--r--test/CodeGenCXX/debug-info-namespace.cpp66
-rw-r--r--test/CodeGenCXX/debug-info-nullptr.cpp2
-rw-r--r--test/CodeGenCXX/debug-info-pubtypes.cpp5
-rw-r--r--test/CodeGenCXX/debug-info-same-line.cpp25
-rw-r--r--test/CodeGenCXX/debug-info-scope.cpp32
-rw-r--r--test/CodeGenCXX/debug-info-static-member.cpp14
-rw-r--r--test/CodeGenCXX/debug-info-template-limit.cpp4
-rw-r--r--test/CodeGenCXX/debug-info-template-member.cpp89
-rw-r--r--test/CodeGenCXX/debug-info-template-quals.cpp12
-rw-r--r--test/CodeGenCXX/debug-info-template.cpp138
-rw-r--r--test/CodeGenCXX/debug-info-thunk.cpp2
-rw-r--r--test/CodeGenCXX/debug-info-union-template.cpp2
-rw-r--r--test/CodeGenCXX/debug-info-uuid.cpp19
-rw-r--r--test/CodeGenCXX/debug-info-zero-length-arrays.cpp2
-rw-r--r--test/CodeGenCXX/debug-info.cpp53
-rw-r--r--test/CodeGenCXX/debug-lambda-expressions.cpp30
-rw-r--r--test/CodeGenCXX/decl-ref-init.cpp4
-rw-r--r--test/CodeGenCXX/default-arg-temps.cpp6
-rw-r--r--test/CodeGenCXX/default-arguments.cpp8
-rw-r--r--test/CodeGenCXX/default-constructor-for-members.cpp4
-rw-r--r--test/CodeGenCXX/default-constructor-template-member.cpp3
-rw-r--r--test/CodeGenCXX/deferred-global-init.cpp4
-rw-r--r--test/CodeGenCXX/delayed-template-parsing.cpp18
-rw-r--r--test/CodeGenCXX/delete-two-arg.cpp8
-rw-r--r--test/CodeGenCXX/delete.cpp18
-rw-r--r--test/CodeGenCXX/derived-to-base-conv.cpp6
-rw-r--r--test/CodeGenCXX/derived-to-virtual-base-class-calls-final.cpp2
-rw-r--r--test/CodeGenCXX/destructor-exception-spec.cpp2
-rw-r--r--test/CodeGenCXX/destructors.cpp114
-rw-r--r--test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp20
-rw-r--r--test/CodeGenCXX/devirtualize-virtual-function-calls.cpp2
-rw-r--r--test/CodeGenCXX/dynamic_cast-no-rtti.cpp26
-rw-r--r--test/CodeGenCXX/eh.cpp30
-rw-r--r--test/CodeGenCXX/empty-classes.cpp2
-rw-r--r--test/CodeGenCXX/empty-nontrivially-copyable.cpp25
-rw-r--r--test/CodeGenCXX/exceptions.cpp12
-rw-r--r--test/CodeGenCXX/explicit-instantiation.cpp8
-rw-r--r--test/CodeGenCXX/fastcall.cpp4
-rw-r--r--test/CodeGenCXX/for-range.cpp8
-rw-r--r--test/CodeGenCXX/forward-enum.cpp2
-rw-r--r--test/CodeGenCXX/fp16-mangle.cpp4
-rw-r--r--test/CodeGenCXX/function-template-explicit-specialization.cpp4
-rw-r--r--test/CodeGenCXX/global-array-destruction.cpp2
-rw-r--r--test/CodeGenCXX/global-block-literal-helpers.cpp16
-rw-r--r--test/CodeGenCXX/global-dtor-no-atexit.cpp2
-rw-r--r--test/CodeGenCXX/global-init.cpp4
-rw-r--r--test/CodeGenCXX/goto.cpp2
-rw-r--r--test/CodeGenCXX/implicit-copy-assign-operator.cpp2
-rw-r--r--test/CodeGenCXX/implicit-copy-constructor.cpp2
-rw-r--r--test/CodeGenCXX/implicit-instantiation-1.cpp2
-rw-r--r--test/CodeGenCXX/inheriting-constructor.cpp14
-rw-r--r--test/CodeGenCXX/init-invariant.cpp4
-rw-r--r--test/CodeGenCXX/inline-functions.cpp10
-rw-r--r--test/CodeGenCXX/instantiate-temporaries.cpp4
-rw-r--r--test/CodeGenCXX/invalid.cpp11
-rw-r--r--test/CodeGenCXX/lambda-expressions-inside-auto-functions.cpp77
-rw-r--r--test/CodeGenCXX/lambda-expressions-nested-linkage.cpp50
-rw-r--r--test/CodeGenCXX/lambda-expressions.cpp28
-rw-r--r--test/CodeGenCXX/linetable-cleanup.cpp36
-rw-r--r--test/CodeGenCXX/linkage.cpp222
-rw-r--r--test/CodeGenCXX/lpad-linetable.cpp69
-rw-r--r--test/CodeGenCXX/lvalue-bitcasts.cpp6
-rw-r--r--test/CodeGenCXX/mangle-98.cpp6
-rw-r--r--test/CodeGenCXX/mangle-address-space.cpp6
-rw-r--r--test/CodeGenCXX/mangle-alias-template.cpp2
-rw-r--r--test/CodeGenCXX/mangle-exprs.cpp22
-rw-r--r--test/CodeGenCXX/mangle-extreme.cpp2
-rw-r--r--test/CodeGenCXX/mangle-lambdas.cpp83
-rw-r--r--test/CodeGenCXX/mangle-local-class-names.cpp30
-rw-r--r--test/CodeGenCXX/mangle-ms-arg-qualifiers.cpp117
-rw-r--r--test/CodeGenCXX/mangle-ms-back-references-pr13207.cpp30
-rw-r--r--test/CodeGenCXX/mangle-ms-back-references.cpp5
-rw-r--r--test/CodeGenCXX/mangle-ms-templates.cpp155
-rw-r--r--test/CodeGenCXX/mangle-ms.cpp273
-rw-r--r--test/CodeGenCXX/mangle-neon-vectors.cpp17
-rw-r--r--test/CodeGenCXX/mangle-nullptr-arg.cpp6
-rw-r--r--test/CodeGenCXX/mangle-ref-qualifiers.cpp10
-rw-r--r--test/CodeGenCXX/mangle-subst-std.cpp12
-rw-r--r--test/CodeGenCXX/mangle-subst.cpp12
-rw-r--r--test/CodeGenCXX/mangle-system-header.cpp4
-rw-r--r--test/CodeGenCXX/mangle-template.cpp12
-rw-r--r--test/CodeGenCXX/mangle-unnamed.cpp4
-rw-r--r--test/CodeGenCXX/mangle-valist.cpp10
-rw-r--r--test/CodeGenCXX/mangle-variadic-templates.cpp30
-rw-r--r--test/CodeGenCXX/mangle-windows.cpp42
-rw-r--r--test/CodeGenCXX/mangle.cpp252
-rw-r--r--test/CodeGenCXX/member-expressions.cpp2
-rw-r--r--test/CodeGenCXX/member-function-pointer-calls.cpp4
-rw-r--r--test/CodeGenCXX/member-function-pointers.cpp5
-rw-r--r--test/CodeGenCXX/member-functions.cpp14
-rw-r--r--test/CodeGenCXX/member-init-anon-union.cpp2
-rw-r--r--test/CodeGenCXX/member-initializers.cpp2
-rw-r--r--test/CodeGenCXX/member-templates.cpp4
-rw-r--r--test/CodeGenCXX/microsoft-abi-alignment-fail.cpp10
-rw-r--r--test/CodeGenCXX/microsoft-abi-constexpr-vs-inheritance.cpp23
-rw-r--r--test/CodeGenCXX/microsoft-abi-default-cc.cpp12
-rw-r--r--test/CodeGenCXX/microsoft-abi-exceptions.cpp157
-rwxr-xr-xtest/CodeGenCXX/microsoft-abi-member-pointers.cpp210
-rw-r--r--test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp201
-rw-r--r--test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp90
-rw-r--r--test/CodeGenCXX/microsoft-abi-static-initializers.cpp124
-rw-r--r--test/CodeGenCXX/microsoft-abi-structors-alias.cpp9
-rw-r--r--test/CodeGenCXX/microsoft-abi-structors.cpp168
-rw-r--r--test/CodeGenCXX/microsoft-abi-thunks.cpp154
-rw-r--r--test/CodeGenCXX/microsoft-abi-vbtables.cpp479
-rw-r--r--test/CodeGenCXX/microsoft-abi-virtual-inheritance-vtordisps.cpp83
-rw-r--r--test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp314
-rw-r--r--test/CodeGenCXX/microsoft-abi-virtual-member-pointers.cpp108
-rw-r--r--test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance.cpp579
-rw-r--r--test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp191
-rw-r--r--test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance-vtordisps.cpp324
-rw-r--r--test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp575
-rw-r--r--test/CodeGenCXX/microsoft-interface.cpp16
-rw-r--r--test/CodeGenCXX/microsoft-new.cpp39
-rw-r--r--test/CodeGenCXX/microsoft-uuidof-unsupported-target.cpp13
-rw-r--r--test/CodeGenCXX/microsoft-uuidof.cpp94
-rw-r--r--test/CodeGenCXX/move-assignment.cpp26
-rw-r--r--test/CodeGenCXX/ms-integer-static-data-members.cpp35
-rw-r--r--test/CodeGenCXX/new-alias.cpp13
-rw-r--r--test/CodeGenCXX/new-array-init-exceptions.cpp4
-rw-r--r--test/CodeGenCXX/new-array-init.cpp8
-rw-r--r--test/CodeGenCXX/new.cpp106
-rw-r--r--test/CodeGenCXX/no-opt-volatile-memcpy.cpp8
-rw-r--r--test/CodeGenCXX/noexcept.cpp49
-rw-r--r--test/CodeGenCXX/nrvo.cpp18
-rw-r--r--test/CodeGenCXX/override-layout.cpp6
-rw-r--r--test/CodeGenCXX/partial-destruction.cpp6
-rw-r--r--test/CodeGenCXX/pod-member-memcpys.cpp152
-rw-r--r--test/CodeGenCXX/pointers-to-data-members.cpp6
-rw-r--r--test/CodeGenCXX/pr11676.cpp17
-rw-r--r--test/CodeGenCXX/pr11797.cpp2
-rw-r--r--test/CodeGenCXX/pr12251.cpp78
-rw-r--r--test/CodeGenCXX/pr13396.cpp12
-rw-r--r--test/CodeGenCXX/pr9130.cpp2
-rw-r--r--test/CodeGenCXX/pr9965.cpp2
-rw-r--r--test/CodeGenCXX/pragma-visibility.cpp14
-rw-r--r--test/CodeGenCXX/pragma-weak.cpp10
-rw-r--r--test/CodeGenCXX/predefined-expr.cpp22
-rw-r--r--test/CodeGenCXX/ptr-to-member-function.cpp4
-rw-r--r--test/CodeGenCXX/reference-cast.cpp20
-rw-r--r--test/CodeGenCXX/references.cpp18
-rw-r--r--test/CodeGenCXX/return.cpp2
-rw-r--r--test/CodeGenCXX/rtti-layout.cpp2
-rw-r--r--test/CodeGenCXX/runtimecc.cpp6
-rw-r--r--test/CodeGenCXX/rvalue-references.cpp14
-rw-r--r--test/CodeGenCXX/scoped-enums.cpp9
-rw-r--r--test/CodeGenCXX/skip-vtable-pointer-initialization.cpp16
-rw-r--r--test/CodeGenCXX/static-data-member.cpp6
-rw-r--r--test/CodeGenCXX/static-init-1.cpp8
-rw-r--r--test/CodeGenCXX/static-init-4.cpp7
-rw-r--r--test/CodeGenCXX/static-init-pnacl.cpp14
-rw-r--r--test/CodeGenCXX/static-init.cpp16
-rw-r--r--test/CodeGenCXX/static-member-variable-explicit-specialization.cpp89
-rw-r--r--test/CodeGenCXX/stmtexpr.cpp7
-rw-r--r--test/CodeGenCXX/template-anonymous-types.cpp12
-rw-r--r--test/CodeGenCXX/template-dependent-bind-temporary.cpp2
-rw-r--r--test/CodeGenCXX/template-inner-struct-visibility-hidden.cpp4
-rw-r--r--test/CodeGenCXX/template-instantiation.cpp20
-rw-r--r--test/CodeGenCXX/template-linkage.cpp12
-rw-r--r--test/CodeGenCXX/temporaries.cpp243
-rw-r--r--test/CodeGenCXX/thiscall-struct-return.cpp4
-rw-r--r--test/CodeGenCXX/threadsafe-statics-exceptions.cpp2
-rw-r--r--test/CodeGenCXX/throw-expression-cleanup.cpp2
-rw-r--r--test/CodeGenCXX/throw-expressions.cpp26
-rw-r--r--test/CodeGenCXX/thunks-available-externally.cpp11
-rw-r--r--test/CodeGenCXX/thunks.cpp44
-rw-r--r--test/CodeGenCXX/type_visibility.cpp36
-rw-r--r--test/CodeGenCXX/typeid.cpp5
-rw-r--r--test/CodeGenCXX/unknown-anytype.cpp62
-rw-r--r--test/CodeGenCXX/value-init.cpp20
-rw-r--r--test/CodeGenCXX/vararg-conversion-ctor.cpp2
-rw-r--r--test/CodeGenCXX/vararg-non-pod.cpp2
-rw-r--r--test/CodeGenCXX/varargs.cpp4
-rw-r--r--test/CodeGenCXX/variadic-templates.cpp4
-rw-r--r--test/CodeGenCXX/virt-dtor-gen.cpp2
-rw-r--r--test/CodeGenCXX/virtual-base-cast.cpp54
-rw-r--r--test/CodeGenCXX/virtual-base-destructor-call.cpp22
-rw-r--r--test/CodeGenCXX/virtual-bases.cpp12
-rw-r--r--test/CodeGenCXX/virtual-destructor-calls.cpp8
-rw-r--r--test/CodeGenCXX/virtual-functions-incomplete-types.cpp2
-rw-r--r--test/CodeGenCXX/visibility-hidden-extern-templates.cpp6
-rw-r--r--test/CodeGenCXX/visibility-inlines-hidden.cpp38
-rw-r--r--test/CodeGenCXX/visibility-ms-compat.cpp12
-rw-r--r--test/CodeGenCXX/visibility.cpp258
-rw-r--r--test/CodeGenCXX/vla.cpp2
-rw-r--r--test/CodeGenCXX/volatile.cpp4
-rw-r--r--test/CodeGenCXX/vtable-available-externally.cpp26
-rw-r--r--test/CodeGenCXX/vtable-layout.cpp188
-rw-r--r--test/CodeGenCXX/vtable-linkage.cpp139
-rw-r--r--test/CodeGenCXX/vtable-pointer-initialization.cpp10
-rw-r--r--test/CodeGenCXX/x86_32-arguments.cpp30
-rw-r--r--test/CodeGenCXX/x86_64-arguments.cpp18
290 files changed, 9650 insertions, 1820 deletions
diff --git a/test/CodeGenCXX/2004-11-27-FriendDefaultArgCrash.cpp b/test/CodeGenCXX/2004-11-27-FriendDefaultArgCrash.cpp
index 3bfecd5..c478e7d 100644
--- a/test/CodeGenCXX/2004-11-27-FriendDefaultArgCrash.cpp
+++ b/test/CodeGenCXX/2004-11-27-FriendDefaultArgCrash.cpp
@@ -4,6 +4,6 @@
namespace nm {
struct str {
- friend int foo(int arg = 0);
+ friend void foo(int arg = 0) {};
};
}
diff --git a/test/CodeGenCXX/2005-02-14-BitFieldOffset.cpp b/test/CodeGenCXX/2005-02-14-BitFieldOffset.cpp
deleted file mode 100644
index c37f5dc..0000000
--- a/test/CodeGenCXX/2005-02-14-BitFieldOffset.cpp
+++ /dev/null
@@ -1,12 +0,0 @@
-// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s
-
-// CHECK-NOT: i32 6
-struct QVectorTypedData {
- int size;
- unsigned int sharable : 1;
- unsigned short array[1];
-};
-
-void foo(QVectorTypedData *X) {
- X->array[0] = 123;
-}
diff --git a/test/CodeGenCXX/2007-05-03-VectorInit.cpp b/test/CodeGenCXX/2007-05-03-VectorInit.cpp
index 5bc196f..b22b52a 100644
--- a/test/CodeGenCXX/2007-05-03-VectorInit.cpp
+++ b/test/CodeGenCXX/2007-05-03-VectorInit.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm %s -O0 -o -
+// RUN: %clang_cc1 -emit-llvm %s -o -
// PR1378
typedef float v4sf __attribute__((vector_size(16)));
diff --git a/test/CodeGenCXX/2010-05-10-Var-DbgInfo.cpp b/test/CodeGenCXX/2010-05-10-Var-DbgInfo.cpp
index 7c05535..802f4c3 100644
--- a/test/CodeGenCXX/2010-05-10-Var-DbgInfo.cpp
+++ b/test/CodeGenCXX/2010-05-10-Var-DbgInfo.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm -O0 -g %s -o /dev/null
+// RUN: %clang_cc1 -emit-llvm -g %s -o /dev/null
// PR 7104
struct A {
diff --git a/test/CodeGenCXX/DynArrayInit.cpp b/test/CodeGenCXX/DynArrayInit.cpp
index 4b4c2ec..fb865e3 100644
--- a/test/CodeGenCXX/DynArrayInit.cpp
+++ b/test/CodeGenCXX/DynArrayInit.cpp
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -O3 -emit-llvm -o - %s | FileCheck %s
// PR7490
-// CHECK: define signext i8 @_Z2f0v
+// CHECK-LABEL: define signext i8 @_Z2f0v
// CHECK: ret i8 0
// CHECK: }
inline void* operator new[](unsigned long, void* __p) { return __p; }
diff --git a/test/CodeGenCXX/PR5050-constructor-conversion.cpp b/test/CodeGenCXX/PR5050-constructor-conversion.cpp
index c50dafb..a1b05eb 100644
--- a/test/CodeGenCXX/PR5050-constructor-conversion.cpp
+++ b/test/CodeGenCXX/PR5050-constructor-conversion.cpp
@@ -1,8 +1,8 @@
// REQUIRES: x86-registered-target,x86-64-registered-target
// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -S %s -o %t-64.s
-// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s
+// RUN: FileCheck -check-prefix CHECK-LP64 --input-file=%t-64.s %s
// RUN: %clang_cc1 -triple i386-apple-darwin -std=c++11 -S %s -o %t-32.s
-// RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s
+// RUN: FileCheck -check-prefix CHECK-LP32 --input-file=%t-32.s %s
struct A { A(const A&, int i1 = 1); };
diff --git a/test/CodeGenCXX/aarch64-mangle-neon-vectors.cpp b/test/CodeGenCXX/aarch64-mangle-neon-vectors.cpp
new file mode 100644
index 0000000..2514704
--- /dev/null
+++ b/test/CodeGenCXX/aarch64-mangle-neon-vectors.cpp
@@ -0,0 +1,85 @@
+// REQUIRES: aarch64-registered-target
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +neon %s -emit-llvm -o - | FileCheck %s
+
+typedef unsigned char uint8_t;
+typedef unsigned short uint16_t;
+typedef signed char int8_t;
+typedef signed short int16_t;
+typedef signed long long int64_t;
+typedef unsigned long long uint64_t;
+typedef unsigned char poly8_t;
+typedef unsigned short poly16_t;
+typedef __fp16 float16_t;
+typedef float float32_t;
+typedef double float64_t;
+
+typedef __attribute__((neon_vector_type(8))) int8_t int8x8_t;
+typedef __attribute__((neon_vector_type(16))) int8_t int8x16_t;
+typedef __attribute__((neon_vector_type(4))) int16_t int16x4_t;
+typedef __attribute__((neon_vector_type(8))) int16_t int16x8_t;
+typedef __attribute__((neon_vector_type(2))) int int32x2_t;
+typedef __attribute__((neon_vector_type(4))) int int32x4_t;
+typedef __attribute__((neon_vector_type(2))) int64_t int64x2_t;
+typedef __attribute__((neon_vector_type(8))) uint8_t uint8x8_t;
+typedef __attribute__((neon_vector_type(16))) uint8_t uint8x16_t;
+typedef __attribute__((neon_vector_type(4))) uint16_t uint16x4_t;
+typedef __attribute__((neon_vector_type(8))) uint16_t uint16x8_t;
+typedef __attribute__((neon_vector_type(2))) unsigned int uint32x2_t;
+typedef __attribute__((neon_vector_type(4))) unsigned int uint32x4_t;
+typedef __attribute__((neon_vector_type(2))) uint64_t uint64x2_t;
+typedef __attribute__((neon_vector_type(4))) float16_t float16x4_t;
+typedef __attribute__((neon_vector_type(8))) float16_t float16x8_t;
+typedef __attribute__((neon_vector_type(2))) float32_t float32x2_t;
+typedef __attribute__((neon_vector_type(4))) float32_t float32x4_t;
+typedef __attribute__((neon_vector_type(2))) float64_t float64x2_t;
+typedef __attribute__((neon_polyvector_type(8))) poly8_t poly8x8_t;
+typedef __attribute__((neon_polyvector_type(16))) poly8_t poly8x16_t;
+typedef __attribute__((neon_polyvector_type(4))) poly16_t poly16x4_t;
+typedef __attribute__((neon_polyvector_type(8))) poly16_t poly16x8_t;
+
+// CHECK: 10__Int8x8_t
+void f1(int8x8_t) {}
+// CHECK: 11__Int16x4_t
+void f2(int16x4_t) {}
+// CHECK: 11__Int32x2_t
+void f3(int32x2_t) {}
+// CHECK: 11__Uint8x8_t
+void f4(uint8x8_t) {}
+// CHECK: 12__Uint16x4_t
+void f5(uint16x4_t) {}
+// CHECK: 13__Float16x4_t
+void f6(float16x4_t) {}
+// CHECK: 13__Float16x8_t
+void f7(float16x8_t) {}
+// CHECK: 12__Uint32x2_t
+void f8(uint32x2_t) {}
+// CHECK: 13__Float32x2_t
+void f9(float32x2_t) {}
+// CHECK: 13__Float32x4_t
+void f10(float32x4_t) {}
+// CHECK: 11__Poly8x8_t
+void f11(poly8x8_t v) {}
+// CHECK: 12__Poly16x4_t
+void f12(poly16x4_t v) {}
+// CHECK:12__Poly8x16_t
+void f13(poly8x16_t v) {}
+// CHECK:12__Poly16x8_t
+void f14(poly16x8_t v) {}
+// CHECK: 11__Int8x16_t
+void f15(int8x16_t) {}
+// CHECK: 11__Int16x8_t
+void f16(int16x8_t) {}
+// CHECK:11__Int32x4_t
+void f17(int32x4_t) {}
+// CHECK: 12__Uint8x16_t
+void f18(uint8x16_t) {}
+// CHECK: 12__Uint16x8_t
+void f19(uint16x8_t) {}
+// CHECK: 12__Uint32x4_t
+void f20(uint32x4_t) {}
+// CHECK: 11__Int64x2_t
+void f21(int64x2_t) {}
+// CHECK: 12__Uint64x2_t
+void f22(uint64x2_t) {}
+// CHECK: 13__Float64x2_t
+void f23(float64x2_t) {}
diff --git a/test/CodeGenCXX/aarch64-neon.cpp b/test/CodeGenCXX/aarch64-neon.cpp
new file mode 100644
index 0000000..5d2a00b
--- /dev/null
+++ b/test/CodeGenCXX/aarch64-neon.cpp
@@ -0,0 +1,13 @@
+// REQUIRES: aarch64-registered-target
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +neon \
+// RUN: -ffp-contract=fast -S -O3 -o - %s | FileCheck %s
+
+// Test whether arm_neon.h can be used in .cpp file.
+
+#include "arm_neon.h"
+
+poly64x1_t test_vld1_p64(poly64_t const * ptr) {
+ // CHECK: test_vld1_p64
+ return vld1_p64(ptr);
+ // CHECK: ld1 {{{v[0-9]+}}.1d}, [{{x[0-9]+|sp}}]
+}
diff --git a/test/CodeGenCXX/abstract-class-ctors-dtors.cpp b/test/CodeGenCXX/abstract-class-ctors-dtors.cpp
index 012c223..793bbde 100644
--- a/test/CodeGenCXX/abstract-class-ctors-dtors.cpp
+++ b/test/CodeGenCXX/abstract-class-ctors-dtors.cpp
@@ -7,10 +7,10 @@ struct A {
~A();
};
-// CHECK-NOT: define void @_ZN1AC1Ev
-// CHECK: define void @_ZN1AC2Ev
-// CHECK: define void @_ZN1AD1Ev
-// CHECK: define void @_ZN1AD2Ev
+// CHECK-NOT-LABEL: define void @_ZN1AC1Ev
+// CHECK-LABEL: define void @_ZN1AC2Ev
+// CHECK-LABEL: define void @_ZN1AD1Ev
+// CHECK-LABEL: define void @_ZN1AD2Ev
A::A() { }
A::~A() { }
diff --git a/test/CodeGenCXX/address-of-fntemplate.cpp b/test/CodeGenCXX/address-of-fntemplate.cpp
index 162c6e5..7179452 100644
--- a/test/CodeGenCXX/address-of-fntemplate.cpp
+++ b/test/CodeGenCXX/address-of-fntemplate.cpp
@@ -9,8 +9,8 @@ void test() {
// CHECK: @_Z1fIiEvv
void (*p2)() = f<int>;
}
-// CHECK: define linkonce_odr void @_Z1fIiEvT_
-// CHECK: define linkonce_odr void @_Z1fIiEvv
+// CHECK-LABEL: define linkonce_odr void @_Z1fIiEvT_
+// CHECK-LABEL: define linkonce_odr void @_Z1fIiEvv
namespace PR6973 {
template<typename T>
diff --git a/test/CodeGenCXX/alloca-align.cpp b/test/CodeGenCXX/alloca-align.cpp
index 99d6ab5..079b55d 100644
--- a/test/CodeGenCXX/alloca-align.cpp
+++ b/test/CodeGenCXX/alloca-align.cpp
@@ -6,19 +6,19 @@ struct s0 {
int TheStores __attribute__((aligned(16)));
};
-// CHECK: define void @f0
+// CHECK-LABEL: define void @f0
// CHECK: alloca %struct.s0, align 16
extern "C" void f0() {
(void) s0();
}
-// CHECK: define void @f1
+// CHECK-LABEL: define void @f1
// CHECK: alloca %struct.s0, align 16
extern "C" void f1() {
(void) (struct s0) { 0, 0, 0, 0 };
}
-// CHECK: define i32 @f2
+// CHECK-LABEL: define i32 @f2
// CHECK: alloca %struct.s1, align 2
struct s1 { short x; short y; };
extern "C" struct s1 f2(int a, struct s1 *x, struct s1 *y) {
diff --git a/test/CodeGenCXX/anonymous-namespaces.cpp b/test/CodeGenCXX/anonymous-namespaces.cpp
index 32e17a3..abc700f 100644
--- a/test/CodeGenCXX/anonymous-namespaces.cpp
+++ b/test/CodeGenCXX/anonymous-namespaces.cpp
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -triple x86_64-apple-darwin10 -emit-llvm %s -o - > %t
-// RUN: FileCheck %s -check-prefix=1 < %t
-// RUN: FileCheck %s -check-prefix=2 < %t
+// RUN: FileCheck %s -check-prefix=CHECK-1 < %t
+// RUN: FileCheck %s -check-prefix=CHECK-2 < %t
int f();
@@ -28,12 +28,12 @@ namespace {
struct E : public virtual EBase { virtual ~E() {} };
};
- // CHECK-1: define internal i32 @_ZN12_GLOBAL__N_13fooEv()
+ // CHECK-1-LABEL: define internal i32 @_ZN12_GLOBAL__N_13fooEv()
int foo() {
return 32;
}
- // CHECK-1: define internal i32 @_ZN12_GLOBAL__N_11A3fooEv()
+ // CHECK-1-LABEL: define internal i32 @_ZN12_GLOBAL__N_11A3fooEv()
namespace A {
int foo() {
return 45;
@@ -58,11 +58,20 @@ namespace test2 {
struct C;
}
- // CHECK-2: define void @_ZN5test24testEv()
+ // CHECK-2-LABEL: define void @_ZN5test24testEv()
// CHECK-2: call void @_ZN5test21A1BINS_12_GLOBAL__N_11CEE3fooEv()
void test() {
A::B<C>::foo();
}
- // CHECK-2: define internal void @_ZN5test21A1BINS_12_GLOBAL__N_11CEE3fooEv()
+ // CHECK-2-LABEL: define internal void @_ZN5test21A1BINS_12_GLOBAL__N_11CEE3fooEv()
}
+
+namespace {
+
+int bar() {
+ extern int a;
+ return a;
+}
+
+} // namespace
diff --git a/test/CodeGenCXX/anonymous-union-member-initializer.cpp b/test/CodeGenCXX/anonymous-union-member-initializer.cpp
index 8dc4f47..98e982d 100644
--- a/test/CodeGenCXX/anonymous-union-member-initializer.cpp
+++ b/test/CodeGenCXX/anonymous-union-member-initializer.cpp
@@ -31,7 +31,7 @@ namespace PR7021 {
union { long l; };
};
- // CHECK: define void @_ZN6PR70211fENS_1XES0_
+ // CHECK-LABEL: define void @_ZN6PR70211fENS_1XES0_
void f(X x, X z) {
X x1;
@@ -61,7 +61,7 @@ namespace test2 {
};
A::A() : b(10) { }
- // CHECK: define void @_ZN5test21AC2Ev(
+ // CHECK-LABEL: define void @_ZN5test21AC2Ev(
// CHECK-NOT: }
// CHECK: store i32 10
// CHECK: }
@@ -79,14 +79,14 @@ namespace PR10512 {
};
};
- // CHECK: define void @_ZN7PR105121AC2Ev
+ // CHECK-LABEL: define void @_ZN7PR105121AC2Ev
// CHECK: [[THISADDR:%[a-zA-z0-9.]+]] = alloca [[A:%"struct[A-Za-z0-9:.]+"]]
// CHECK-NEXT: store [[A]]* [[THIS:%[a-zA-z0-9.]+]], [[A]]** [[THISADDR]]
// CHECK-NEXT: [[THIS1:%[a-zA-z0-9.]+]] = load [[A]]** [[THISADDR]]
// CHECK-NEXT: ret void
A::A() {}
- // CHECK: define void @_ZN7PR105121AC2Ei
+ // CHECK-LABEL: define void @_ZN7PR105121AC2Ei
// CHECK: [[THISADDR:%[a-zA-z0-9.]+]] = alloca [[A:%"struct[A-Za-z0-9:.]+"]]
// CHECK-NEXT: [[XADDR:%[a-zA-z0-9.]+]] = alloca i32
// CHECK-NEXT: store [[A]]* [[THIS:%[a-zA-z0-9.]+]], [[A]]** [[THISADDR]]
@@ -100,7 +100,7 @@ namespace PR10512 {
// CHECK-NEXT: ret void
A::A(int x) : x(x) { }
- // CHECK: define void @_ZN7PR105121AC2El
+ // CHECK-LABEL: define void @_ZN7PR105121AC2El
// CHECK: [[THISADDR:%[a-zA-z0-9.]+]] = alloca [[A:%"struct[A-Za-z0-9:.]+"]]
// CHECK-NEXT: [[XADDR:%[a-zA-z0-9.]+]] = alloca i64
// CHECK-NEXT: store [[A]]* [[THIS:%[a-zA-z0-9.]+]], [[A]]** [[THISADDR]]
@@ -130,7 +130,7 @@ namespace test3 {
};
A::A() : callback(0), callback_value(0) {}
- // CHECK: define void @_ZN5test31AC2Ev(
+ // CHECK-LABEL: define void @_ZN5test31AC2Ev(
// CHECK: [[THIS:%.*]] = load
// CHECK-NEXT: [[UNION:%.*]] = getelementptr inbounds {{.*}} [[THIS]], i32 0, i32 0
// CHECK-NEXT: [[STRUCT:%.*]] = bitcast {{.*}}* [[UNION]] to
diff --git a/test/CodeGenCXX/apple-kext-indirect-virtual-dtor-call.cpp b/test/CodeGenCXX/apple-kext-indirect-virtual-dtor-call.cpp
index bd275f1..7ac5b58 100644
--- a/test/CodeGenCXX/apple-kext-indirect-virtual-dtor-call.cpp
+++ b/test/CodeGenCXX/apple-kext-indirect-virtual-dtor-call.cpp
@@ -1,9 +1,9 @@
// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fapple-kext -fno-rtti -emit-llvm -o - %s | FileCheck %s
-// CHECK: define void @_ZN2B1D0Ev
+// CHECK-LABEL: define void @_ZN2B1D0Ev
// CHECK: [[T1:%.*]] = load void (%struct.B1*)** getelementptr inbounds (void (%struct.B1*)** bitcast ([5 x i8*]* @_ZTV2B1 to void (%struct.B1*)**), i64 2)
// CHECK-NEXT: call void [[T1]](%struct.B1* [[T2:%.*]])
-// CHECK: define void @_Z6DELETEP2B1
+// CHECK-LABEL: define void @_Z6DELETEP2B1
// CHECK: [[T3:%.*]] = load void (%struct.B1*)** getelementptr inbounds (void (%struct.B1*)** bitcast ([5 x i8*]* @_ZTV2B1 to void (%struct.B1*)**), i64 2)
// CHECK-NEXT: call void [[T3]](%struct.B1* [[T4:%.*]])
diff --git a/test/CodeGenCXX/apple-kext-linkage.C b/test/CodeGenCXX/apple-kext-linkage.C
index 59d228e..e66b038 100644
--- a/test/CodeGenCXX/apple-kext-linkage.C
+++ b/test/CodeGenCXX/apple-kext-linkage.C
@@ -13,21 +13,21 @@ void foo() {
Derived d1; // ok
}
-// CHECK: define internal i32 @_Z1fj(
+// CHECK-LABEL: define internal i32 @_Z1fj(
inline unsigned f(unsigned n) { return n == 0 ? 0 : n + f(n-1); }
unsigned g(unsigned n) { return f(n); }
// rdar://problem/10133200: give explicit instantiations external linkage in kernel mode
-// CHECK: define void @_Z3barIiEvv()
+// CHECK-LABEL: define void @_Z3barIiEvv()
template <typename T> void bar() {}
template void bar<int>();
-// CHECK: define internal i32 @_Z5identIiET_S0_(
+// CHECK-LABEL: define internal i32 @_Z5identIiET_S0_(
template <typename X> X ident(X x) { return x; }
int foo(int n) { return ident(n); }
-// CHECK: define internal void @_ZN7DerivedD1Ev(
-// CHECK: define internal void @_ZN7DerivedD0Ev(
-// CHECK: define internal void @_ZN7DeriveddlEPv(
+// CHECK-LABEL: define internal void @_ZN7DerivedD1Ev(
+// CHECK-LABEL: define internal void @_ZN7DerivedD0Ev(
+// CHECK-LABEL: define internal void @_ZN7DeriveddlEPv(
diff --git a/test/CodeGenCXX/arm-vaarg.cpp b/test/CodeGenCXX/arm-vaarg.cpp
new file mode 100644
index 0000000..9850fb3
--- /dev/null
+++ b/test/CodeGenCXX/arm-vaarg.cpp
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -triple armv7-apple-ios -emit-llvm -o - %s | FileCheck %s
+struct Empty {};
+
+Empty emptyvar;
+
+int take_args(int a, ...) {
+ __builtin_va_list l;
+ __builtin_va_start(l, a);
+// CHECK: call void @llvm.va_start
+
+ emptyvar = __builtin_va_arg(l, Empty);
+// CHECK: load i8**
+// CHECK-NOT: getelementptr
+// CHECK: [[EMPTY_PTR:%[a-zA-Z0-9._]+]] = bitcast i8* {{%[a-zA-Z0-9._]+}} to %struct.Empty*
+
+ // It's conceivable that EMPTY_PTR may not actually be a valid pointer
+ // (e.g. it's at the very bottom of the stack and the next page is
+ // invalid). This doesn't matter provided it's never loaded (there's no
+ // well-defined way to tell), but it becomes a problem if we do try to use it.
+// CHECK-NOT: load %struct.Empty* [[EMPTY_PTR]]
+
+ int i = __builtin_va_arg(l, int);
+// CHECK: load i32*
+
+ __builtin_va_end(l);
+ return i;
+}
diff --git a/test/CodeGenCXX/arm.cpp b/test/CodeGenCXX/arm.cpp
index 48f2f00..2fb9c49 100644
--- a/test/CodeGenCXX/arm.cpp
+++ b/test/CodeGenCXX/arm.cpp
@@ -28,7 +28,7 @@ bar baz;
// CHECK: call [[BAR:%.*]]* @_ZN3barC1Ev(
// CHECK-NEXT: call i32 @atexit(void ()* @__dtor_baz)
-// CHECK: define internal void @__dtor_baz()
+// CHECK-LABEL: define internal void @__dtor_baz()
// CHECK: call [[BAR]]* @_ZN3barD1Ev([[BAR]]* @baz)
// Destructors and constructors must return this.
@@ -41,7 +41,7 @@ namespace test1 {
void bar() { foo(); }
};
- // CHECK: define void @_ZN5test14testEv()
+ // CHECK-LABEL: define void @_ZN5test14testEv()
void test() {
// CHECK: [[AV:%.*]] = alloca [[A:%.*]], align 1
// CHECK: call [[A]]* @_ZN5test11AC1Ei([[A]]* [[AV]], i32 10)
@@ -52,19 +52,19 @@ namespace test1 {
a.bar();
}
- // CHECK: define linkonce_odr [[A]]* @_ZN5test11AC1Ei([[A]]* %this, i32 %i) unnamed_addr
+ // CHECK: define linkonce_odr [[A]]* @_ZN5test11AC1Ei([[A]]* returned %this, i32 %i) unnamed_addr
// CHECK: [[THIS:%.*]] = alloca [[A]]*, align 4
// CHECK: store [[A]]* {{.*}}, [[A]]** [[THIS]]
// CHECK: [[THIS1:%.*]] = load [[A]]** [[THIS]]
- // CHECK: [[THIS2:%.*]] = call [[A]]* @_ZN5test11AC2Ei(
- // CHECK: ret [[A]]* [[THIS2]]
+ // CHECK: {{%.*}} = call [[A]]* @_ZN5test11AC2Ei(
+ // CHECK: ret [[A]]* [[THIS1]]
- // CHECK: define linkonce_odr [[A]]* @_ZN5test11AD1Ev([[A]]* %this) unnamed_addr
+ // CHECK: define linkonce_odr [[A]]* @_ZN5test11AD1Ev([[A]]* returned %this) unnamed_addr
// CHECK: [[THIS:%.*]] = alloca [[A]]*, align 4
// CHECK: store [[A]]* {{.*}}, [[A]]** [[THIS]]
// CHECK: [[THIS1:%.*]] = load [[A]]** [[THIS]]
- // CHECK: [[THIS2:%.*]] = call [[A]]* @_ZN5test11AD2Ev(
- // CHECK: ret [[A]]* [[THIS2]]
+ // CHECK: {{%.*}} = call [[A]]* @_ZN5test11AD2Ev(
+ // CHECK: ret [[A]]* [[THIS1]]
}
// Awkward virtual cases.
@@ -107,7 +107,7 @@ namespace test3 {
};
void a() {
- // CHECK: define void @_ZN5test31aEv()
+ // CHECK-LABEL: define void @_ZN5test31aEv()
// CHECK: call noalias i8* @_Znam(i32 48)
// CHECK: store i32 4
// CHECK: store i32 10
@@ -115,7 +115,7 @@ namespace test3 {
}
void b(int n) {
- // CHECK: define void @_ZN5test31bEi(
+ // CHECK-LABEL: define void @_ZN5test31bEi(
// CHECK: [[N:%.*]] = load i32*
// CHECK: @llvm.umul.with.overflow.i32(i32 [[N]], i32 4)
// CHECK: @llvm.uadd.with.overflow.i32(i32 {{.*}}, i32 8)
@@ -128,7 +128,7 @@ namespace test3 {
}
void c() {
- // CHECK: define void @_ZN5test31cEv()
+ // CHECK-LABEL: define void @_ZN5test31cEv()
// CHECK: call noalias i8* @_Znam(i32 808)
// CHECK: store i32 4
// CHECK: store i32 200
@@ -136,7 +136,7 @@ namespace test3 {
}
void d(int n) {
- // CHECK: define void @_ZN5test31dEi(
+ // CHECK-LABEL: define void @_ZN5test31dEi(
// CHECK: [[N:%.*]] = load i32*
// CHECK: @llvm.umul.with.overflow.i32(i32 [[N]], i32 80)
// CHECK: [[NE:%.*]] = mul i32 [[N]], 20
@@ -149,7 +149,7 @@ namespace test3 {
}
void e(A *x) {
- // CHECK: define void @_ZN5test31eEPNS_1AE(
+ // CHECK-LABEL: define void @_ZN5test31eEPNS_1AE(
// CHECK: icmp eq {{.*}}, null
// CHECK: getelementptr {{.*}}, i64 -8
// CHECK: getelementptr {{.*}}, i64 4
@@ -161,7 +161,7 @@ namespace test3 {
}
void f(A (*x)[20]) {
- // CHECK: define void @_ZN5test31fEPA20_NS_1AE(
+ // CHECK-LABEL: define void @_ZN5test31fEPA20_NS_1AE(
// CHECK: icmp eq {{.*}}, null
// CHECK: getelementptr {{.*}}, i64 -8
// CHECK: getelementptr {{.*}}, i64 4
@@ -180,7 +180,7 @@ namespace test4 {
};
void a() {
- // CHECK: define void @_ZN5test41aEv()
+ // CHECK-LABEL: define void @_ZN5test41aEv()
// CHECK: call noalias i8* @_Znam(i32 48)
// CHECK: store i32 4
// CHECK: store i32 10
@@ -188,7 +188,7 @@ namespace test4 {
}
void b(int n) {
- // CHECK: define void @_ZN5test41bEi(
+ // CHECK-LABEL: define void @_ZN5test41bEi(
// CHECK: [[N:%.*]] = load i32*
// CHECK: @llvm.umul.with.overflow.i32(i32 [[N]], i32 4)
// CHECK: @llvm.uadd.with.overflow.i32(i32 {{.*}}, i32 8)
@@ -200,7 +200,7 @@ namespace test4 {
}
void c() {
- // CHECK: define void @_ZN5test41cEv()
+ // CHECK-LABEL: define void @_ZN5test41cEv()
// CHECK: call noalias i8* @_Znam(i32 808)
// CHECK: store i32 4
// CHECK: store i32 200
@@ -208,7 +208,7 @@ namespace test4 {
}
void d(int n) {
- // CHECK: define void @_ZN5test41dEi(
+ // CHECK-LABEL: define void @_ZN5test41dEi(
// CHECK: [[N:%.*]] = load i32*
// CHECK: @llvm.umul.with.overflow.i32(i32 [[N]], i32 80)
// CHECK: [[NE:%.*]] = mul i32 [[N]], 20
@@ -221,7 +221,7 @@ namespace test4 {
}
void e(A *x) {
- // CHECK: define void @_ZN5test41eEPNS_1AE(
+ // CHECK-LABEL: define void @_ZN5test41eEPNS_1AE(
// CHECK: [[ALLOC:%.*]] = getelementptr inbounds {{.*}}, i64 -8
// CHECK: getelementptr inbounds {{.*}}, i64 4
// CHECK: bitcast
@@ -233,7 +233,7 @@ namespace test4 {
}
void f(A (*x)[20]) {
- // CHECK: define void @_ZN5test41fEPA20_NS_1AE(
+ // CHECK-LABEL: define void @_ZN5test41fEPA20_NS_1AE(
// CHECK: [[ALLOC:%.*]] = getelementptr inbounds {{.*}}, i64 -8
// CHECK: getelementptr inbounds {{.*}}, i64 4
// CHECK: bitcast
@@ -251,7 +251,7 @@ namespace test5 {
~A();
};
- // CHECK: define void @_ZN5test54testEPNS_1AE
+ // CHECK-LABEL: define void @_ZN5test54testEPNS_1AE
void test(A *a) {
// CHECK: [[PTR:%.*]] = alloca [[A:%.*]]*, align 4
// CHECK-NEXT: store [[A]]* {{.*}}, [[A]]** [[PTR]], align 4
@@ -267,7 +267,7 @@ namespace test6 {
virtual ~A();
};
- // CHECK: define void @_ZN5test64testEPNS_1AE
+ // CHECK-LABEL: define void @_ZN5test64testEPNS_1AE
void test(A *a) {
// CHECK: [[AVAR:%.*]] = alloca [[A:%.*]]*, align 4
// CHECK-NEXT: store [[A]]* {{.*}}, [[A]]** [[AVAR]], align 4
@@ -290,7 +290,7 @@ namespace test7 {
// Static and guard tested at top of file
- // CHECK: define void @_ZN5test74testEv()
+ // CHECK-LABEL: define void @_ZN5test74testEv()
void test() {
// CHECK: [[T0:%.*]] = load i32* @_ZGVZN5test74testEvE1x
// CHECK-NEXT: [[T1:%.*]] = and i32 [[T0]], 1
@@ -325,7 +325,7 @@ namespace test8 {
// Static and guard tested at top of file
- // CHECK: define void @_ZN5test84testEv()
+ // CHECK-LABEL: define void @_ZN5test84testEv()
void test() {
// CHECK: [[T0:%.*]] = load i32* @_ZGVZN5test84testEvE1x
// CHECK-NEXT: [[T1:%.*]] = and i32 [[T0]], 1
@@ -394,7 +394,7 @@ namespace test9 {
void testDelete(A *array) {
delete[] array;
}
-// CHECK: define void @_ZN5test910testDeleteEPNS_1AE(
+// CHECK-LABEL: define void @_ZN5test910testDeleteEPNS_1AE(
// CHECK: [[BEGIN:%.*]] = load [[TEST9]]**
// CHECK-NEXT: [[T0:%.*]] = icmp eq [[TEST9]]* [[BEGIN]], null
// CHECK-NEXT: br i1 [[T0]],
@@ -413,7 +413,7 @@ namespace test9 {
// CHECK: call [[C]]* @_ZN5test21CD1Ev(
// CHECK: ret [[C]]* undef
- // CHECK: define linkonce_odr void @_ZTv0_n12_N5test21CD0Ev(
+ // CHECK-LABEL: define linkonce_odr void @_ZTv0_n12_N5test21CD0Ev(
// CHECK: call void @_ZN5test21CD0Ev(
// CHECK: ret void
diff --git a/test/CodeGenCXX/array-construction.cpp b/test/CodeGenCXX/array-construction.cpp
index 7b565a4..645ad1d 100644
--- a/test/CodeGenCXX/array-construction.cpp
+++ b/test/CodeGenCXX/array-construction.cpp
@@ -1,8 +1,8 @@
// REQUIRES: x86-registered-target,x86-64-registered-target
// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -S %s -o %t-64.s
-// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s
+// RUN: FileCheck -check-prefix CHECK-LP64 --input-file=%t-64.s %s
// RUN: %clang_cc1 -triple i386-apple-darwin -std=c++11 -S %s -o %t-32.s
-// RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s
+// RUN: FileCheck -check-prefix CHECK-LP32 --input-file=%t-32.s %s
extern "C" int printf(...);
diff --git a/test/CodeGenCXX/array-operator-delete-call.cpp b/test/CodeGenCXX/array-operator-delete-call.cpp
index 1b23c4d..8d6f50f 100644
--- a/test/CodeGenCXX/array-operator-delete-call.cpp
+++ b/test/CodeGenCXX/array-operator-delete-call.cpp
@@ -1,8 +1,8 @@
// REQUIRES: x86-registered-target,x86-64-registered-target
// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -S %s -o %t-64.s
-// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s
+// RUN: FileCheck -check-prefix CHECK-LP64 --input-file=%t-64.s %s
// RUN: %clang_cc1 -triple i386-apple-darwin -std=c++11 -S %s -o %t-32.s
-// RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s
+// RUN: FileCheck -check-prefix CHECK-LP32 --input-file=%t-32.s %s
extern "C" int printf(...);
diff --git a/test/CodeGenCXX/atomic.cpp b/test/CodeGenCXX/atomic.cpp
index 36bb4ef..653f16d 100644
--- a/test/CodeGenCXX/atomic.cpp
+++ b/test/CodeGenCXX/atomic.cpp
@@ -5,7 +5,7 @@ namespace PR11411 {
void f();
};
- // CHECK: define linkonce_odr void @_ZN7PR114113PtrIiE1fEv
+ // CHECK-LABEL: define linkonce_odr void @_ZN7PR114113PtrIiE1fEv
// CHECK-NOT: ret
template<typename _Tp> inline void Ptr<_Tp>::f() {
int* _refcount;
diff --git a/test/CodeGenCXX/atomicinit.cpp b/test/CodeGenCXX/atomicinit.cpp
index 38d012e..ee2e9e4 100644
--- a/test/CodeGenCXX/atomicinit.cpp
+++ b/test/CodeGenCXX/atomicinit.cpp
@@ -18,7 +18,7 @@ struct B {
_Atomic(B) b;
-// CHECK: define void @_Z11atomic_initR1Ai
+// CHECK-LABEL: define void @_Z11atomic_initR1Ai
void atomic_init(A& a, int i) {
// CHECK-NOT: atomic
// CHECK: tail call void @_ZN1BC1Ei
@@ -26,7 +26,7 @@ void atomic_init(A& a, int i) {
// CHECK-NEXT: ret void
}
-// CHECK: define void @_Z16atomic_init_boolPU7_Atomicbb
+// CHECK-LABEL: define void @_Z16atomic_init_boolPU7_Atomicbb
void atomic_init_bool(_Atomic(bool) *ab, bool b) {
// CHECK-NOT: atomic
// CHECK: {{zext i1.*to i8}}
@@ -40,7 +40,7 @@ struct AtomicBoolMember {
AtomicBoolMember(bool b);
};
-// CHECK: define void @_ZN16AtomicBoolMemberC2Eb
+// CHECK-LABEL: define void @_ZN16AtomicBoolMemberC2Eb
// CHECK: {{zext i1.*to i8}}
// CHECK-NEXT: store i8
// CHECK-NEXT: ret void
diff --git a/test/CodeGenCXX/attr-cleanup.cpp b/test/CodeGenCXX/attr-cleanup.cpp
new file mode 100644
index 0000000..ff15b03
--- /dev/null
+++ b/test/CodeGenCXX/attr-cleanup.cpp
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s
+
+namespace N {
+ void free(void *i) {}
+}
+
+int main(void) {
+ // CHECK: call void @_ZN1N4freeEPv
+ void *fp __attribute__((cleanup(N::free)));
+ return 0;
+}
diff --git a/test/CodeGenCXX/attr.cpp b/test/CodeGenCXX/attr.cpp
index 4748cda..8bcff36 100644
--- a/test/CodeGenCXX/attr.cpp
+++ b/test/CodeGenCXX/attr.cpp
@@ -26,7 +26,7 @@ void C::bar3() { }
void C::bar4() { }
// PR6635
-// CHECK: define i32 @_Z5test1v()
+// CHECK-LABEL: define i32 @_Z5test1v()
int test1() { return 10; }
// CHECK at top of file
extern "C" int test2() __attribute__((alias("_Z5test1v")));
diff --git a/test/CodeGenCXX/bitfield-layout.cpp b/test/CodeGenCXX/bitfield-layout.cpp
index 15f33d2..646300a 100644
--- a/test/CodeGenCXX/bitfield-layout.cpp
+++ b/test/CodeGenCXX/bitfield-layout.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - -O3 | FileCheck -check-prefix LP64 %s
-// RUN: %clang_cc1 %s -triple=i386-apple-darwin10 -emit-llvm -o - -O3 | FileCheck -check-prefix LP32 %s
+// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - -O3 | FileCheck -check-prefix CHECK-LP64 %s
+// RUN: %clang_cc1 %s -triple=i386-apple-darwin10 -emit-llvm -o - -O3 | FileCheck -check-prefix CHECK-LP32 %s
// CHECK-LP64: %union.Test1 = type { i32, [4 x i8] }
union Test1 {
diff --git a/test/CodeGenCXX/bitfield.cpp b/test/CodeGenCXX/bitfield.cpp
index 1814aa2..2c454b0 100644
--- a/test/CodeGenCXX/bitfield.cpp
+++ b/test/CodeGenCXX/bitfield.cpp
@@ -1,6 +1,6 @@
-// RUN: %clang_cc1 -triple x86_64-unknown-unknown -verify -emit-llvm -o - %s \
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -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: %clang_cc1 -triple powerpc64-unknown-unknown -emit-llvm -o - %s \
// RUN: | FileCheck -check-prefix=CHECK-PPC64 %s
//
// Tests for bitfield access patterns in C++ with special attention to
@@ -20,13 +20,13 @@ namespace N0 {
unsigned b71 : 2;
};
unsigned read00(S* s) {
- // CHECK-X86-64: define i32 @_ZN2N06read00
+ // CHECK-X86-64-LABEL: 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-LABEL: define zeroext i32 @_ZN2N06read00
// CHECK-PPC64: %[[ptr:.*]] = bitcast %{{.*}}* %{{.*}} to i64*
// CHECK-PPC64: %[[val:.*]] = load i64* %[[ptr]]
// CHECK-PPC64: %[[shr:.*]] = lshr i64 %[[val]], 50
@@ -35,14 +35,14 @@ namespace N0 {
return s->b00;
}
unsigned read01(S* s) {
- // CHECK-X86-64: define i32 @_ZN2N06read01
+ // CHECK-X86-64-LABEL: 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-LABEL: define zeroext i32 @_ZN2N06read01
// CHECK-PPC64: %[[ptr:.*]] = bitcast %{{.*}}* %{{.*}} to i64*
// CHECK-PPC64: %[[val:.*]] = load i64* %[[ptr]]
// CHECK-PPC64: %[[shr:.*]] = lshr i64 %[[val]], 48
@@ -52,14 +52,14 @@ namespace N0 {
return s->b01;
}
unsigned read20(S* s) {
- // CHECK-X86-64: define i32 @_ZN2N06read20
+ // CHECK-X86-64-LABEL: 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-LABEL: define zeroext i32 @_ZN2N06read20
// CHECK-PPC64: %[[ptr:.*]] = bitcast %{{.*}}* %{{.*}} to i64*
// CHECK-PPC64: %[[val:.*]] = load i64* %[[ptr]]
// CHECK-PPC64: %[[shr:.*]] = lshr i64 %[[val]], 42
@@ -69,14 +69,14 @@ namespace N0 {
return s->b20;
}
unsigned read21(S* s) {
- // CHECK-X86-64: define i32 @_ZN2N06read21
+ // CHECK-X86-64-LABEL: 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-LABEL: define zeroext i32 @_ZN2N06read21
// CHECK-PPC64: %[[ptr:.*]] = bitcast %{{.*}}* %{{.*}} to i64*
// CHECK-PPC64: %[[val:.*]] = load i64* %[[ptr]]
// CHECK-PPC64: %[[shr:.*]] = lshr i64 %[[val]], 40
@@ -86,14 +86,14 @@ namespace N0 {
return s->b21;
}
unsigned read30(S* s) {
- // CHECK-X86-64: define i32 @_ZN2N06read30
+ // CHECK-X86-64-LABEL: 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-LABEL: define zeroext i32 @_ZN2N06read30
// CHECK-PPC64: %[[ptr:.*]] = bitcast %{{.*}}* %{{.*}} to i64*
// CHECK-PPC64: %[[val:.*]] = load i64* %[[ptr]]
// CHECK-PPC64: %[[shr:.*]] = lshr i64 %[[val]], 10
@@ -103,14 +103,14 @@ namespace N0 {
return s->b30;
}
unsigned read31(S* s) {
- // CHECK-X86-64: define i32 @_ZN2N06read31
+ // CHECK-X86-64-LABEL: 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-LABEL: define zeroext i32 @_ZN2N06read31
// CHECK-PPC64: %[[ptr:.*]] = bitcast %{{.*}}* %{{.*}} to i64*
// CHECK-PPC64: %[[val:.*]] = load i64* %[[ptr]]
// CHECK-PPC64: %[[shr:.*]] = lshr i64 %[[val]], 8
@@ -120,14 +120,14 @@ namespace N0 {
return s->b31;
}
unsigned read70(S* s) {
- // CHECK-X86-64: define i32 @_ZN2N06read70
+ // CHECK-X86-64-LABEL: 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-LABEL: define zeroext i32 @_ZN2N06read70
// CHECK-PPC64: %[[ptr:.*]] = bitcast %{{.*}}* %{{.*}} to i64*
// CHECK-PPC64: %[[val:.*]] = load i64* %[[ptr]]
// CHECK-PPC64: %[[shr:.*]] = lshr i64 %[[val]], 2
@@ -137,13 +137,13 @@ namespace N0 {
return s->b70;
}
unsigned read71(S* s) {
- // CHECK-X86-64: define i32 @_ZN2N06read71
+ // CHECK-X86-64-LABEL: 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-LABEL: define zeroext i32 @_ZN2N06read71
// CHECK-PPC64: %[[ptr:.*]] = bitcast %{{.*}}* %{{.*}} to i64*
// CHECK-PPC64: %[[val:.*]] = load i64* %[[ptr]]
// CHECK-PPC64: %[[and:.*]] = and i64 %[[val]], 3
@@ -166,13 +166,13 @@ namespace N1 {
char c;
};
unsigned read(S* s) {
- // CHECK-X86-64: define i32 @_ZN2N14read
+ // CHECK-X86-64-LABEL: 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-LABEL: 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
@@ -181,7 +181,7 @@ namespace N1 {
return s->b;
}
void write(S* s, unsigned x) {
- // CHECK-X86-64: define void @_ZN2N15write
+ // CHECK-X86-64-LABEL: 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]]
@@ -189,7 +189,7 @@ namespace N1 {
// 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-LABEL: 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]]
@@ -210,12 +210,12 @@ namespace N2 {
void *p;
};
unsigned read(S* s) {
- // CHECK-X86-64: define i32 @_ZN2N24read
+ // CHECK-X86-64-LABEL: 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-LABEL: define zeroext i32 @_ZN2N24read
// CHECK-PPC64: %[[ptr:.*]] = bitcast %{{.*}}* %{{.*}} to i32*
// CHECK-PPC64: %[[val:.*]] = load i32* %[[ptr]]
// CHECK-PPC64: %[[shr:.*]] = lshr i32 %[[val]], 8
@@ -223,14 +223,14 @@ namespace N2 {
return s->b;
}
void write(S* s, unsigned x) {
- // CHECK-X86-64: define void @_ZN2N25write
+ // CHECK-X86-64-LABEL: 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-LABEL: define void @_ZN2N25write
// CHECK-PPC64: %[[ptr:.*]] = bitcast %{{.*}}* %{{.*}} to i32*
// CHECK-PPC64: %[[old:.*]] = load i32* %[[ptr]]
// CHECK-PPC64: %[[x_and:.*]] = and i32 %{{.*}}, 16777215
@@ -249,12 +249,12 @@ namespace N3 {
unsigned b : 24;
};
unsigned read(S* s) {
- // CHECK-X86-64: define i32 @_ZN2N34read
+ // CHECK-X86-64-LABEL: 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-LABEL: define zeroext i32 @_ZN2N34read
// CHECK-PPC64: %[[ptr:.*]] = bitcast %{{.*}}* %{{.*}} to i32*
// CHECK-PPC64: %[[val:.*]] = load i32* %[[ptr]]
// CHECK-PPC64: %[[shr:.*]] = lshr i32 %[[val]], 8
@@ -262,14 +262,14 @@ namespace N3 {
return s->b;
}
void write(S* s, unsigned x) {
- // CHECK-X86-64: define void @_ZN2N35write
+ // CHECK-X86-64-LABEL: 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-LABEL: define void @_ZN2N35write
// CHECK-PPC64: %[[ptr:.*]] = bitcast %{{.*}}* %{{.*}} to i32*
// CHECK-PPC64: %[[old:.*]] = load i32* %[[ptr]]
// CHECK-PPC64: %[[x_and:.*]] = and i32 %{{.*}}, 16777215
@@ -300,13 +300,13 @@ namespace N4 {
// 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-LABEL: 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-LABEL: 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]]
@@ -315,12 +315,12 @@ namespace N4 {
return s->b;
}
void write(Base* s, unsigned x) {
- // CHECK-X86-64: define void @_ZN2N45write
+ // CHECK-X86-64-LABEL: 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-LABEL: 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
@@ -342,12 +342,12 @@ namespace N5 {
struct Y { unsigned b : 24; } y;
};
unsigned read(U* u) {
- // CHECK-X86-64: define i32 @_ZN2N54read
+ // CHECK-X86-64-LABEL: 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-LABEL: define zeroext i32 @_ZN2N54read
// CHECK-PPC64: %[[ptr:.*]] = bitcast %{{.*}}* %{{.*}} to i32*
// CHECK-PPC64: %[[val:.*]] = load i32* %[[ptr]]
// CHECK-PPC64: %[[shr:.*]] = lshr i32 %[[val]], 8
@@ -355,14 +355,14 @@ namespace N5 {
return u->y.b;
}
void write(U* u, unsigned x) {
- // CHECK-X86-64: define void @_ZN2N55write
+ // CHECK-X86-64-LABEL: 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-LABEL: define void @_ZN2N55write
// CHECK-PPC64: %[[ptr:.*]] = bitcast %{{.*}}* %{{.*}} to i32*
// CHECK-PPC64: %[[old:.*]] = load i32* %[[ptr]]
// CHECK-PPC64: %[[x_and:.*]] = and i32 %{{.*}}, 16777215
@@ -387,7 +387,7 @@ namespace N6 {
unsigned char b2 : 8;
};
unsigned read(S* s) {
- // CHECK-X86-64: define i32 @_ZN2N64read
+ // CHECK-X86-64-LABEL: 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
@@ -396,7 +396,7 @@ namespace N6 {
// 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-LABEL: define zeroext i32 @_ZN2N64read
// CHECK-PPC64: %[[ptr1:.*]] = bitcast {{.*}}* %{{.*}} to i24*
// CHECK-PPC64: %[[val1:.*]] = load i24* %[[ptr1]]
// CHECK-PPC64: %[[ext1:.*]] = zext i24 %[[val1]] to i32
@@ -408,14 +408,14 @@ namespace N6 {
return s->b1 + s->b2;
}
void write(S* s, unsigned x) {
- // CHECK-X86-64: define void @_ZN2N65write
+ // CHECK-X86-64-LABEL: 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-LABEL: define void @_ZN2N65write
// CHECK-PPC64: %[[ptr1:.*]] = bitcast {{.*}}* %{{.*}} to i24*
// CHECK-PPC64: %[[new1:.*]] = trunc i32 %{{.*}} to i24
// CHECK-PPC64: store i24 %[[new1]], i24* %[[ptr1]]
diff --git a/test/CodeGenCXX/block-byref-cxx-objc.cpp b/test/CodeGenCXX/block-byref-cxx-objc.cpp
index 30f1f07..616fd67 100644
--- a/test/CodeGenCXX/block-byref-cxx-objc.cpp
+++ b/test/CodeGenCXX/block-byref-cxx-objc.cpp
@@ -15,13 +15,13 @@ int main()
return 0;
}
-// CHECK: define internal void @__Block_byref_object_copy_
+// CHECK-LABEL: define internal void @__Block_byref_object_copy_
// CHECK: call {{.*}} @_ZN1AC1ERKS_
-// CHECK: define internal void @__Block_byref_object_dispose_
+// CHECK-LABEL: define internal void @__Block_byref_object_dispose_
// CHECK: call {{.*}} @_ZN1AD1Ev
-// CHECK: define internal void @__copy_helper_block_
+// CHECK-LABEL: define internal void @__copy_helper_block_
// CHECK: call void @_Block_object_assign
-// CHECK: define internal void @__destroy_helper_block_
+// CHECK-LABEL: define internal void @__destroy_helper_block_
// CHECK: call void @_Block_object_dispose
// rdar://problem/11135650
diff --git a/test/CodeGenCXX/block-in-ctor-dtor.cpp b/test/CodeGenCXX/block-in-ctor-dtor.cpp
index 4ee6b1c..bd37d44 100644
--- a/test/CodeGenCXX/block-in-ctor-dtor.cpp
+++ b/test/CodeGenCXX/block-in-ctor-dtor.cpp
@@ -36,13 +36,13 @@ X::~X() {
};
-// CHECK: define internal void @___ZN4ZoneC2Ev_block_invoke
-// CHECK: define internal void @___ZN4ZoneC2Ev_block_invoke_
-// CHECK: define internal void @___ZN4ZoneD2Ev_block_invoke
-// CHECK: define internal void @___ZN4ZoneD2Ev_block_invoke_
-// CHECK: define internal void @___ZN1XC1Ev_block_invoke
-// CHECK: define internal void @___ZN1XC1Ev_block_invoke_
-// CHECK: define internal void @___ZN1XC2Ev_block_invoke
-// CHECK: define internal void @___ZN1XC2Ev_block_invoke_
-// CHECK: define internal void @___ZN1XD2Ev_block_invoke
-// CHECK: define internal void @___ZN1XD2Ev_block_invoke_
+// CHECK-LABEL: define internal void @___ZN4ZoneC2Ev_block_invoke
+// CHECK-LABEL: define internal void @___ZN4ZoneC2Ev_block_invoke_
+// CHECK-LABEL: define internal void @___ZN4ZoneD2Ev_block_invoke
+// CHECK-LABEL: define internal void @___ZN4ZoneD2Ev_block_invoke_
+// CHECK-LABEL: define internal void @___ZN1XC1Ev_block_invoke
+// CHECK-LABEL: define internal void @___ZN1XC1Ev_block_invoke_
+// CHECK-LABEL: define internal void @___ZN1XC2Ev_block_invoke
+// CHECK-LABEL: define internal void @___ZN1XC2Ev_block_invoke_
+// CHECK-LABEL: define internal void @___ZN1XD2Ev_block_invoke
+// CHECK-LABEL: define internal void @___ZN1XD2Ev_block_invoke_
diff --git a/test/CodeGenCXX/blocks-cxx11.cpp b/test/CodeGenCXX/blocks-cxx11.cpp
index 3f0380a..9ff5826 100644
--- a/test/CodeGenCXX/blocks-cxx11.cpp
+++ b/test/CodeGenCXX/blocks-cxx11.cpp
@@ -46,7 +46,7 @@ namespace test_complex_int {
void test() {
constexpr _Complex int x = 500;
takeABlock(^{ takeItByValue(x); });
- // CHECK: store i32 500,
+ // CHECK: store { i32, i32 } { i32 500, i32 0 },
// CHECK: store i32 500,
// CHECK-NEXT: store i32 0,
@@ -100,7 +100,7 @@ namespace test_block_in_lambda {
};
lambda(); // make sure we emit the invocation function
}
- // CHECK: define internal void @"_ZZN20test_block_in_lambda4testENS_1AEENK3$_0clEv"(
+ // CHECK-LABEL: 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
diff --git a/test/CodeGenCXX/blocks.cpp b/test/CodeGenCXX/blocks.cpp
index 81eef0e..8a6fdac 100644
--- a/test/CodeGenCXX/blocks.cpp
+++ b/test/CodeGenCXX/blocks.cpp
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 %s -fblocks -triple x86_64-apple-darwin -emit-llvm -o - | FileCheck %s
namespace test0 {
- // CHECK: define void @_ZN5test04testEi(
+ // CHECK-LABEL: define void @_ZN5test04testEi(
// CHECK: define internal void @___ZN5test04testEi_block_invoke{{.*}}(
// CHECK: define internal void @___ZN5test04testEi_block_invoke_2{{.*}}(
void test(int x) {
@@ -13,7 +13,7 @@ extern void (^out)();
namespace test1 {
// Capturing const objects doesn't require a local block.
- // CHECK: define void @_ZN5test15test1Ev()
+ // CHECK-LABEL: define void @_ZN5test15test1Ev()
// CHECK: store void ()* bitcast ({{.*}} @__block_literal_global{{.*}} to void ()*), void ()** @out
void test1() {
const int NumHorsemen = 4;
@@ -21,7 +21,7 @@ namespace test1 {
}
// That applies to structs too...
- // CHECK: define void @_ZN5test15test2Ev()
+ // CHECK-LABEL: define void @_ZN5test15test2Ev()
// CHECK: store void ()* bitcast ({{.*}} @__block_literal_global{{.*}} to void ()*), void ()** @out
struct loc { double x, y; };
void test2() {
@@ -30,7 +30,7 @@ namespace test1 {
}
// ...unless they have mutable fields...
- // CHECK: define void @_ZN5test15test3Ev()
+ // CHECK-LABEL: define void @_ZN5test15test3Ev()
// CHECK: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
// CHECK: [[T0:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to void ()*
// CHECK: store void ()* [[T0]], void ()** @out
@@ -41,7 +41,7 @@ namespace test1 {
}
// ...or non-trivial destructors...
- // CHECK: define void @_ZN5test15test4Ev()
+ // CHECK-LABEL: define void @_ZN5test15test4Ev()
// CHECK: [[OBJ:%.*]] = alloca
// CHECK: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
// CHECK: [[T0:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to void ()*
@@ -69,22 +69,22 @@ namespace test2 {
~B();
};
- // CHECK: define void @_ZN5test24testEv()
+ // CHECK-LABEL: define void @_ZN5test24testEv()
void test() {
__block A a;
__block B b;
}
- // CHECK: define internal void @__Block_byref_object_copy
+ // CHECK-LABEL: define internal void @__Block_byref_object_copy
// CHECK: call void @_ZN5test21AC1ERKS0_(
- // CHECK: define internal void @__Block_byref_object_dispose
+ // CHECK-LABEL: define internal void @__Block_byref_object_dispose
// CHECK: call void @_ZN5test21AD1Ev(
- // CHECK: define internal void @__Block_byref_object_copy
+ // CHECK-LABEL: define internal void @__Block_byref_object_copy
// CHECK: call void @_ZN5test21BC1ERKS0_(
- // CHECK: define internal void @__Block_byref_object_dispose
+ // CHECK-LABEL: define internal void @__Block_byref_object_dispose
// CHECK: call void @_ZN5test21BD1Ev(
}
@@ -118,8 +118,8 @@ namespace test4 {
extern void consume(void(^)());
consume(^{ return foo(A()); });
}
- // CHECK: define void @_ZN5test44testEv()
- // CHECK: define internal void @___ZN5test44testEv_block_invoke
+ // CHECK-LABEL: define void @_ZN5test44testEv()
+ // CHECK-LABEL: define internal void @___ZN5test44testEv_block_invoke
// CHECK: [[TMP:%.*]] = alloca [[A:%.*]], align 1
// CHECK-NEXT: store i8* [[BLOCKDESC:%.*]], i8** {{.*}}, align 8
// CHECK-NEXT: load i8*
@@ -147,7 +147,7 @@ namespace test5 {
doWithBlock(b);
}
- // CHECK: define void @_ZN5test54testEb(
+ // CHECK-LABEL: define void @_ZN5test54testEb(
// CHECK: [[COND:%.*]] = alloca i8
// CHECK-NEXT: [[X:%.*]] = alloca [[A:%.*]], align 4
// CHECK-NEXT: [[B:%.*]] = alloca void ()*, align 8
@@ -197,7 +197,7 @@ namespace test6 {
bar();
}
- // CHECK: define void @_ZN5test64testEv()
+ // CHECK-LABEL: define void @_ZN5test64testEv()
// CHECK: [[TEMP:%.*]] = alloca [[A:%.*]], align 1
// CHECK-NEXT: call void @_ZN5test61AC1Ev([[A]]* [[TEMP]])
// CHECK-NEXT: call void @_ZN5test63fooERKNS_1AEU13block_pointerFvvE(
diff --git a/test/CodeGenCXX/bool-bitfield.cpp b/test/CodeGenCXX/bool-bitfield.cpp
index 06bdf2b..a5a344f 100644
--- a/test/CodeGenCXX/bool-bitfield.cpp
+++ b/test/CodeGenCXX/bool-bitfield.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple x86_64-unknown-unknown -verify -emit-llvm -o - %s \
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s \
// RUN: | FileCheck %s
// PR14638; make sure this doesn't crash.
@@ -9,6 +9,6 @@ void func1(bool b, A& a1)
{
if ((a1.m_sorted = b)) {}
}
-// CHECK: define void @_Z5func1bR1A
+// CHECK-LABEL: define void @_Z5func1bR1A
// CHECK: br i1
// CHECK: ret void
diff --git a/test/CodeGenCXX/builtins.cpp b/test/CodeGenCXX/builtins.cpp
index c9b0bff..98e2d1a 100644
--- a/test/CodeGenCXX/builtins.cpp
+++ b/test/CodeGenCXX/builtins.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple=x86_64-linux-gnu -emit-llvm -o - %s | FileCheck %s
// PR8839
extern "C" char memmove();
@@ -7,3 +7,22 @@ int main() {
// CHECK: call {{signext i8|i8}} @memmove()
return memmove();
}
+
+struct S;
+// CHECK: define {{.*}} @_Z9addressofbR1SS0_(
+S *addressof(bool b, S &s, S &t) {
+ // CHECK: %[[LVALUE:.*]] = phi
+ // CHECK: ret {{.*}}* %[[LVALUE]]
+ return __builtin_addressof(b ? s : t);
+}
+
+extern "C" int __builtin_abs(int); // #1
+long __builtin_abs(long); // #2
+extern "C" int __builtin_abs(int); // #3
+
+int x = __builtin_abs(-2);
+// CHECK: store i32 2, i32* @x, align 4
+
+long y = __builtin_abs(-2l);
+// CHECK: [[Y:%.+]] = call i64 @_Z13__builtin_absl(i64 -2)
+// CHECK: store i64 [[Y]], i64* @y, align 8
diff --git a/test/CodeGenCXX/c-linkage.cpp b/test/CodeGenCXX/c-linkage.cpp
index f6e64d9..1607623 100644
--- a/test/CodeGenCXX/c-linkage.cpp
+++ b/test/CodeGenCXX/c-linkage.cpp
@@ -10,15 +10,15 @@ extern "C" {
}
}
-// CHECK: define void @_ZN1N1X1fEv
+// CHECK-LABEL: define void @_ZN1N1X1fEv
extern "C" {
static void test2_f() {
}
- // CHECK: define internal void @_Z7test2_fv
+ // CHECK-LABEL: define internal void @_Z7test2_fv
static void test2_f(int x) {
}
- // CHECK: define internal void @_Z7test2_fi
+ // CHECK-LABEL: define internal void @_Z7test2_fi
void test2_use() {
test2_f();
test2_f(42);
diff --git a/test/CodeGenCXX/c99-variable-length-array.cpp b/test/CodeGenCXX/c99-variable-length-array.cpp
index d486f9b..2cd8e11 100644
--- a/test/CodeGenCXX/c99-variable-length-array.cpp
+++ b/test/CodeGenCXX/c99-variable-length-array.cpp
@@ -9,7 +9,7 @@ struct Y {
~Y();
};
-// CHECK: define void @_Z1fiPPKc(
+// CHECK-LABEL: define void @_Z1fiPPKc(
void f(int argc, const char* argv[]) {
// CHECK: call void @_ZN1XC1Ev
X x;
diff --git a/test/CodeGenCXX/call-arg-zero-temp.cpp b/test/CodeGenCXX/call-arg-zero-temp.cpp
index 101e81f..14238f2 100644
--- a/test/CodeGenCXX/call-arg-zero-temp.cpp
+++ b/test/CodeGenCXX/call-arg-zero-temp.cpp
@@ -1,8 +1,8 @@
// REQUIRES: x86-registered-target,x86-64-registered-target
// RUN: %clang_cc1 -triple x86_64-apple-darwin -S %s -o %t-64.s
-// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s
+// RUN: FileCheck -check-prefix CHECK-LP64 --input-file=%t-64.s %s
// RUN: %clang_cc1 -triple i386-apple-darwin -S %s -o %t-32.s
-// RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s
+// RUN: FileCheck -check-prefix CHECK-LP32 --input-file=%t-32.s %s
extern "C" int printf(...);
diff --git a/test/CodeGenCXX/captured-statements.cpp b/test/CodeGenCXX/captured-statements.cpp
new file mode 100644
index 0000000..2843c2b
--- /dev/null
+++ b/test/CodeGenCXX/captured-statements.cpp
@@ -0,0 +1,189 @@
+// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o %t
+// RUN: FileCheck %s -input-file=%t -check-prefix=CHECK-1
+// RUN: FileCheck %s -input-file=%t -check-prefix=CHECK-2
+// RUN: FileCheck %s -input-file=%t -check-prefix=CHECK-3
+// RUN: FileCheck %s -input-file=%t -check-prefix=CHECK-4
+// RUN: FileCheck %s -input-file=%t -check-prefix=CHECK-5
+// RUN: FileCheck %s -input-file=%t -check-prefix=CHECK-6
+// RUN: FileCheck %s -input-file=%t -check-prefix=CHECK-7
+
+struct Foo {
+ int x;
+ float y;
+ ~Foo() {}
+};
+
+struct TestClass {
+ int x;
+
+ TestClass() : x(0) {};
+ void MemberFunc() {
+ Foo f;
+ #pragma clang __debug captured
+ {
+ f.y = x;
+ }
+ }
+};
+
+void test1() {
+ TestClass c;
+ c.MemberFunc();
+ // CHECK-1: %[[Capture:struct\.anon[\.0-9]*]] = type { %struct.Foo*, %struct.TestClass* }
+
+ // CHECK-1: define {{.*}} void @_ZN9TestClass10MemberFuncEv
+ // CHECK-1: alloca %struct.anon
+ // CHECK-1: getelementptr inbounds %[[Capture]]* %{{[^,]*}}, i32 0, i32 0
+ // CHECK-1: store %struct.Foo* %f, %struct.Foo**
+ // CHECK-1: getelementptr inbounds %[[Capture]]* %{{[^,]*}}, i32 0, i32 1
+ // CHECK-1: call void @[[HelperName:[A-Za-z0-9_]+]](%[[Capture]]*
+ // CHECK-1: call {{.*}}FooD1Ev
+ // CHECK-1: ret
+}
+
+// CHECK-1: define internal void @[[HelperName]]
+// CHECK-1: getelementptr inbounds %[[Capture]]* {{[^,]*}}, i32 0, i32 1
+// CHECK-1: getelementptr inbounds %struct.TestClass* {{[^,]*}}, i32 0, i32 0
+// CHECK-1: getelementptr inbounds %[[Capture]]* {{[^,]*}}, i32 0, i32 0
+
+void test2(int x) {
+ int y = [&]() {
+ #pragma clang __debug captured
+ {
+ x++;
+ }
+ return x;
+ }();
+
+ // CHECK-2-LABEL: define void @_Z5test2i
+ // CHECK-2: call {{.*}} @[[Lambda:["$\w]+]]
+ //
+ // CHECK-2: define internal {{.*}} @[[Lambda]]
+ // CHECK-2: call void @[[HelperName:["$_A-Za-z0-9]+]](%[[Capture:.*]]*
+ //
+ // CHECK-2: define internal void @[[HelperName]]
+ // CHECK-2: getelementptr inbounds %[[Capture]]*
+ // CHECK-2: load i32**
+ // CHECK-2: load i32*
+}
+
+void test3(int x) {
+ #pragma clang __debug captured
+ {
+ x = [=]() { return x + 1; } ();
+ }
+
+ // CHECK-3: %[[Capture:struct\.anon[\.0-9]*]] = type { i32* }
+
+ // CHECK-3-LABEL: define void @_Z5test3i
+ // CHECK-3: store i32*
+ // CHECK-3: call void @{{.*}}__captured_stmt
+ // CHECK-3: ret void
+}
+
+void test4() {
+ #pragma clang __debug captured
+ {
+ Foo f;
+ f.x = 5;
+ }
+ // CHECK-4-LABEL: define void @_Z5test4v
+ // CHECK-4: call void @[[HelperName:["$_A-Za-z0-9]+]](%[[Capture:.*]]*
+ // CHECK-4: ret void
+ //
+ // CHECK-4: define internal void @[[HelperName]]
+ // CHECK-4: store i32 5, i32*
+ // CHECK-4: call {{.*}}FooD1Ev
+}
+
+template <typename T, int id>
+void touch(const T &) {}
+
+template <typename T, unsigned id>
+void template_capture_var() {
+ T x;
+ #pragma clang __debug captured
+ {
+ touch<T, id>(x);
+ }
+}
+
+template <typename T, int id>
+class Val {
+ T v;
+public:
+ void set() {
+ #pragma clang __debug captured
+ {
+ touch<T, id>(v);
+ }
+ }
+
+ template <typename U, int id2>
+ void foo(U u) {
+ #pragma clang __debug captured
+ {
+ touch<U, id + id2>(u);
+ }
+ }
+};
+
+void test_capture_var() {
+ // CHECK-5: define {{.*}} void @_Z20template_capture_varIiLj201EEvv
+ // CHECK-5-NOT: }
+ // CHECK-5: store i32*
+ // CHECK-5: call void @__captured_stmt
+ // CHECK-5-NEXT: ret void
+ template_capture_var<int, 201>();
+
+ // CHECK-5: define {{.*}} void @_ZN3ValIfLi202EE3setEv
+ // CHECK-5-NOT: }
+ // CHECK-5: store %class.Val*
+ // CHECK-5: call void @__captured_stmt
+ // CHECK-5-NEXT: ret void
+ Val<float, 202> Obj;
+ Obj.set();
+
+ // CHECK-5: define {{.*}} void @_ZN3ValIfLi202EE3fooIdLi203EEEvT_
+ // CHECK-5-NOT: }
+ // CHECK-5: store %class.Val*
+ // CHECK-5: store double
+ // CHECK-5: call void @__captured_stmt
+ // CHECK-5-NEXT: ret void
+ Obj.foo<double, 203>(1.0);
+}
+
+template <typename T>
+void template_capture_lambda() {
+ T x, y;
+ [=, &y]() {
+ #pragma clang __debug captured
+ {
+ y += x;
+ }
+ }();
+}
+
+void test_capture_lambda() {
+ // CHECK-6: define {{.*}} void @_ZZ23template_capture_lambdaIiEvvENKUlvE_clEv
+ // CHECK-6-NOT: }
+ // CHECK-6: store i32*
+ // CHECK-6: store i32*
+ // CHECK-6: call void @__captured_stmt
+ // CHECK-6-NEXT: ret void
+ template_capture_lambda<int>();
+}
+
+inline int test_captured_linkage() {
+ // CHECK-7: @_ZZ21test_captured_linkagevE1i = linkonce_odr global i32 0
+ int j;
+ #pragma clang __debug captured
+ {
+ static int i = 0;
+ j = ++i;
+ }
+ return j;
+}
+void call_test_captured_linkage() {
+ test_captured_linkage();
+}
diff --git a/test/CodeGenCXX/cast-conversion.cpp b/test/CodeGenCXX/cast-conversion.cpp
index d023b9a..5565f65 100644
--- a/test/CodeGenCXX/cast-conversion.cpp
+++ b/test/CodeGenCXX/cast-conversion.cpp
@@ -1,8 +1,8 @@
// REQUIRES: x86-registered-target,x86-64-registered-target
// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -S %s -o %t-64.s
-// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s
+// RUN: FileCheck -check-prefix CHECK-LP64 --input-file=%t-64.s %s
// RUN: %clang_cc1 -triple i386-apple-darwin -std=c++11 -S %s -o %t-32.s
-// RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s
+// RUN: FileCheck -check-prefix CHECK-LP32 --input-file=%t-32.s %s
struct A {
A(int);
diff --git a/test/CodeGenCXX/catch-undef-behavior.cpp b/test/CodeGenCXX/catch-undef-behavior.cpp
index d6d0edfa..338da57 100644
--- a/test/CodeGenCXX/catch-undef-behavior.cpp
+++ b/test/CodeGenCXX/catch-undef-behavior.cpp
@@ -1,4 +1,4 @@
-// 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
+// RUN: %clang_cc1 -std=c++11 -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,array-bounds,function -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s
struct S {
double d;
@@ -186,7 +186,7 @@ void bad_downcast_pointer(S *p) {
// CHECK: %[[NONNULL:.*]] = icmp ne {{.*}}, null
// CHECK: br i1 %[[NONNULL]],
- // CHECK: %[[SIZE:.*]] = call i64 @llvm.objectsize.i64(
+ // CHECK: %[[SIZE:.*]] = call i64 @llvm.objectsize.i64.p0i8(
// CHECK: %[[E1:.*]] = icmp uge i64 %[[SIZE]], 24
// CHECK: %[[MISALIGN:.*]] = and i64 %{{.*}}, 7
// CHECK: %[[E2:.*]] = icmp eq i64 %[[MISALIGN]], 0
@@ -207,7 +207,7 @@ void bad_downcast_pointer(S *p) {
void bad_downcast_reference(S &p) {
// CHECK: %[[E1:.*]] = icmp ne {{.*}}, null
// CHECK-NOT: br i1
- // CHECK: %[[SIZE:.*]] = call i64 @llvm.objectsize.i64(
+ // CHECK: %[[SIZE:.*]] = call i64 @llvm.objectsize.i64.p0i8(
// CHECK: %[[E2:.*]] = icmp uge i64 %[[SIZE]], 24
// CHECK: %[[E12:.*]] = and i1 %[[E1]], %[[E2]]
// CHECK: %[[MISALIGN:.*]] = and i64 %{{.*}}, 7
@@ -321,4 +321,156 @@ char string_index(int n) {
return "Hello"[n];
}
+class A // align=4
+{
+ int a1, a2, a3;
+};
+
+class B // align=8
+{
+ long b1, b2;
+};
+
+class C : public A, public B // align=16
+{
+ alignas(16) int c1;
+};
+
+// Make sure we check the alignment of the pointer after subtracting any
+// offset. The pointer before subtraction doesn't need to be aligned for
+// the destination type.
+
+// CHECK-LABEL: define void @_Z16downcast_pointerP1B(%class.B* %b)
+void downcast_pointer(B *b) {
+ (void) static_cast<C*>(b);
+ // Alignment check from EmitTypeCheck(TCK_DowncastPointer, ...)
+ // CHECK: [[SUB:%[.a-z0-9]*]] = getelementptr i8* {{.*}}, i64 -16
+ // CHECK-NEXT: [[C:%[0-9]*]] = bitcast i8* [[SUB]] to %class.C*
+ // null check goes here
+ // CHECK: [[FROM_PHI:%[0-9]*]] = phi %class.C* [ [[C]], {{.*}} ], {{.*}}
+ // Objectsize check goes here
+ // CHECK: [[C_INT:%[0-9]*]] = ptrtoint %class.C* [[FROM_PHI]] to i64
+ // CHECK-NEXT: [[MASKED:%[0-9]*]] = and i64 [[C_INT]], 15
+ // CHECK-NEXT: [[TEST:%[0-9]*]] = icmp eq i64 [[MASKED]], 0
+ // AND the alignment test with the objectsize test.
+ // CHECK-NEXT: [[AND:%[0-9]*]] = and i1 {{.*}}, [[TEST]]
+ // CHECK-NEXT: br i1 [[AND]]
+}
+
+// CHECK-LABEL: define void @_Z18downcast_referenceR1B(%class.B* %b)
+void downcast_reference(B &b) {
+ (void) static_cast<C&>(b);
+ // Alignment check from EmitTypeCheck(TCK_DowncastReference, ...)
+ // CHECK: [[SUB:%[.a-z0-9]*]] = getelementptr i8* {{.*}}, i64 -16
+ // CHECK-NEXT: [[C:%[0-9]*]] = bitcast i8* [[SUB]] to %class.C*
+ // Objectsize check goes here
+ // CHECK: [[C_INT:%[0-9]*]] = ptrtoint %class.C* [[C]] to i64
+ // CHECK-NEXT: [[MASKED:%[0-9]*]] = and i64 [[C_INT]], 15
+ // CHECK-NEXT: [[TEST:%[0-9]*]] = icmp eq i64 [[MASKED]], 0
+ // AND the alignment test with the objectsize test.
+ // CHECK-NEXT: [[AND:%[0-9]*]] = and i1 {{.*}}, [[TEST]]
+ // CHECK-NEXT: br i1 [[AND]]
+}
+
+// CHECK-LABEL: @_Z22indirect_function_callPFviE({{.*}} prefix <{ i32, i8* }> <{ i32 1413876459, i8* bitcast ({ i8*, i8* }* @_ZTIFvPFviEE to i8*) }>
+void indirect_function_call(void (*p)(int)) {
+ // CHECK: [[PTR:%[0-9]*]] = bitcast void (i32)* {{.*}} to <{ i32, i8* }>*
+
+ // Signature check
+ // CHECK-NEXT: [[SIGPTR:%[0-9]*]] = getelementptr <{ i32, i8* }>* [[PTR]], i32 0, i32 0
+ // CHECK-NEXT: [[SIG:%[0-9]*]] = load i32* [[SIGPTR]]
+ // CHECK-NEXT: [[SIGCMP:%[0-9]*]] = icmp eq i32 [[SIG]], 1413876459
+ // CHECK-NEXT: br i1 [[SIGCMP]]
+
+ // RTTI pointer check
+ // CHECK: [[RTTIPTR:%[0-9]*]] = getelementptr <{ i32, i8* }>* [[PTR]], i32 0, i32 1
+ // CHECK-NEXT: [[RTTI:%[0-9]*]] = load i8** [[RTTIPTR]]
+ // CHECK-NEXT: [[RTTICMP:%[0-9]*]] = icmp eq i8* [[RTTI]], bitcast ({ i8*, i8* }* @_ZTIFviE to i8*)
+ // CHECK-NEXT: br i1 [[RTTICMP]]
+ p(42);
+}
+
+namespace CopyValueRepresentation {
+ // CHECK-LABEL: define {{.*}} @_ZN23CopyValueRepresentation2S3aSERKS0_
+ // CHECK-NOT: call {{.*}} @__ubsan_handle_load_invalid_value
+ // CHECK-LABEL: define {{.*}} @_ZN23CopyValueRepresentation2S4aSEOS0_
+ // CHECK-NOT: call {{.*}} @__ubsan_handle_load_invalid_value
+ // CHECK-LABEL: define {{.*}} @_ZN23CopyValueRepresentation2S5C2ERKS0_
+ // CHECK-NOT: call {{.*}} __ubsan_handle_load_invalid_value
+ // CHECK-LABEL: define {{.*}} @_ZN23CopyValueRepresentation2S2C2ERKS0_
+ // CHECK: __ubsan_handle_load_invalid_value
+ // CHECK-LABEL: define {{.*}} @_ZN23CopyValueRepresentation2S1C2ERKS0_
+ // CHECK-NOT: call {{.*}} __ubsan_handle_load_invalid_value
+
+ struct CustomCopy { CustomCopy(); CustomCopy(const CustomCopy&); };
+ struct S1 {
+ CustomCopy CC;
+ bool b;
+ };
+ void callee1(S1);
+ void test1() {
+ S1 s11;
+ callee1(s11);
+ S1 s12;
+ s12 = s11;
+ }
+
+ static bool some_global_bool;
+ struct ExprCopy {
+ ExprCopy();
+ ExprCopy(const ExprCopy&, bool b = some_global_bool);
+ };
+ struct S2 {
+ ExprCopy EC;
+ bool b;
+ };
+ void callee2(S2);
+ void test2(void) {
+ S2 s21;
+ callee2(s21);
+ S2 s22;
+ s22 = s21;
+ }
+
+ struct CustomAssign { CustomAssign &operator=(const CustomAssign&); };
+ struct S3 {
+ CustomAssign CA;
+ bool b;
+ };
+ void test3() {
+ S3 x, y;
+ x = y;
+ }
+
+ struct CustomMove {
+ CustomMove();
+ CustomMove(const CustomMove&&);
+ CustomMove &operator=(const CustomMove&&);
+ };
+ struct S4 {
+ CustomMove CM;
+ bool b;
+ };
+ void test4() {
+ S4 x, y;
+ x = static_cast<S4&&>(y);
+ }
+
+ struct EnumCustomCopy {
+ EnumCustomCopy();
+ EnumCustomCopy(const EnumCustomCopy&);
+ };
+ struct S5 {
+ EnumCustomCopy ECC;
+ bool b;
+ };
+ void callee5(S5);
+ void test5() {
+ S5 s51;
+ callee5(s51);
+ S5 s52;
+ s52 = s51;
+ }
+}
+
// CHECK: attributes [[NR_NUW]] = { noreturn nounwind }
diff --git a/test/CodeGenCXX/catch-undef-behavior2.cpp b/test/CodeGenCXX/catch-undef-behavior2.cpp
new file mode 100644
index 0000000..b8b31ca
--- /dev/null
+++ b/test/CodeGenCXX/catch-undef-behavior2.cpp
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -std=c++11 -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,array-bounds,function -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s
+
+bool GetOptionalBool(bool *value);
+bool GetBool(bool default_value) {
+ // CHECK-LABEL: @_Z7GetBoolb
+ // CHECK-NOT: select
+ bool value;
+ return GetOptionalBool(&value) ? value : default_value;
+}
diff --git a/test/CodeGenCXX/compound-literals.cpp b/test/CodeGenCXX/compound-literals.cpp
index 5df0ea5..f1d8802 100644
--- a/test/CodeGenCXX/compound-literals.cpp
+++ b/test/CodeGenCXX/compound-literals.cpp
@@ -12,7 +12,7 @@ struct Y {
X x;
};
-// CHECK: define i32 @_Z1fv()
+// CHECK-LABEL: define i32 @_Z1fv()
int f() {
// CHECK: [[LVALUE:%[a-z0-9.]+]] = alloca
// CHECK-NEXT: [[I:%[a-z0-9]+]] = getelementptr inbounds {{.*}}* [[LVALUE]], i32 0, i32 0
@@ -26,7 +26,7 @@ int f() {
return ((Y){17, "seventeen"}).i;
}
-// CHECK: define i32 @_Z1gv()
+// CHECK-LABEL: define i32 @_Z1gv()
int g() {
// CHECK: store [2 x i32]* %{{[a-z0-9.]+}}, [2 x i32]** [[V:%[a-z0-9.]+]]
const int (&v)[2] = (int [2]) {1,2};
diff --git a/test/CodeGenCXX/condition.cpp b/test/CodeGenCXX/condition.cpp
index cc2eaf5..452f1c3 100644
--- a/test/CodeGenCXX/condition.cpp
+++ b/test/CodeGenCXX/condition.cpp
@@ -26,7 +26,7 @@ struct Y {
X getX();
-// CHECK: define void @_Z11if_destructi(
+// CHECK-LABEL: define void @_Z11if_destructi(
void if_destruct(int z) {
// Verify that the condition variable is destroyed at the end of the
// "if" statement.
@@ -95,7 +95,7 @@ void switch_destruct(int z) {
int foo();
-// CHECK: define void @_Z14while_destructi
+// CHECK-LABEL: define void @_Z14while_destructi
void while_destruct(int z) {
// CHECK: [[Z:%.*]] = alloca i32
// CHECK: [[CLEANUPDEST:%.*]] = alloca i32
@@ -135,7 +135,7 @@ void while_destruct(int z) {
// CHECK: ret
}
-// CHECK: define void @_Z12for_destructi(
+// CHECK-LABEL: define void @_Z12for_destructi(
void for_destruct(int z) {
// CHECK: [[Z:%.*]] = alloca i32
// CHECK: [[CLEANUPDEST:%.*]] = alloca i32
@@ -224,7 +224,7 @@ void for_destruct(int z) {
}
void do_destruct(int z) {
- // CHECK: define void @_Z11do_destruct
+ // CHECK-LABEL: define void @_Z11do_destruct
do {
// CHECK: store i32 77
z = 77;
diff --git a/test/CodeGenCXX/conditional-gnu-ext.cpp b/test/CodeGenCXX/conditional-gnu-ext.cpp
index 104a91d..44ebf98 100644
--- a/test/CodeGenCXX/conditional-gnu-ext.cpp
+++ b/test/CodeGenCXX/conditional-gnu-ext.cpp
@@ -77,7 +77,7 @@ namespace test3 {
};
B test0(B &x) {
- // CHECK: define void @_ZN5test35test0ERNS_1BE(
+ // CHECK-LABEL: define void @_ZN5test35test0ERNS_1BE(
// CHECK: [[X:%.*]] = alloca [[B:%.*]]*,
// CHECK-NEXT: store [[B]]* {{%.*}}, [[B]]** [[X]]
// CHECK-NEXT: [[T0:%.*]] = load [[B]]** [[X]]
@@ -92,7 +92,7 @@ namespace test3 {
}
B test1() {
- // CHECK: define void @_ZN5test35test1Ev(
+ // CHECK-LABEL: define void @_ZN5test35test1Ev(
// CHECK: [[TEMP:%.*]] = alloca [[B]],
// CHECK-NEXT: call void @_ZN5test312test1_helperEv([[B]]* sret [[TEMP]])
// CHECK-NEXT: [[BOOL:%.*]] = call zeroext i1 @_ZN5test31BcvbEv([[B]]* [[TEMP]])
@@ -109,7 +109,7 @@ namespace test3 {
A test2(B &x) {
- // CHECK: define void @_ZN5test35test2ERNS_1BE(
+ // CHECK-LABEL: define void @_ZN5test35test2ERNS_1BE(
// CHECK: [[X:%.*]] = alloca [[B]]*,
// CHECK-NEXT: store [[B]]* {{%.*}}, [[B]]** [[X]]
// CHECK-NEXT: [[T0:%.*]] = load [[B]]** [[X]]
@@ -124,7 +124,7 @@ namespace test3 {
}
A test3() {
- // CHECK: define void @_ZN5test35test3Ev(
+ // CHECK-LABEL: define void @_ZN5test35test3Ev(
// CHECK: [[TEMP:%.*]] = alloca [[B]],
// CHECK-NEXT: call void @_ZN5test312test3_helperEv([[B]]* sret [[TEMP]])
// CHECK-NEXT: [[BOOL:%.*]] = call zeroext i1 @_ZN5test31BcvbEv([[B]]* [[TEMP]])
diff --git a/test/CodeGenCXX/conditional-temporaries.cpp b/test/CodeGenCXX/conditional-temporaries.cpp
index d538287..a3cc2fe 100644
--- a/test/CodeGenCXX/conditional-temporaries.cpp
+++ b/test/CodeGenCXX/conditional-temporaries.cpp
@@ -36,19 +36,19 @@ Checker c;
}
-// CHECK: define i32 @_Z12getCtorCallsv()
+// CHECK-LABEL: define i32 @_Z12getCtorCallsv()
int getCtorCalls() {
// CHECK: ret i32 5
return ctorcalls;
}
-// CHECK: define i32 @_Z12getDtorCallsv()
+// CHECK-LABEL: define i32 @_Z12getDtorCallsv()
int getDtorCalls() {
// CHECK: ret i32 5
return dtorcalls;
}
-// CHECK: define zeroext i1 @_Z7successv()
+// CHECK-LABEL: define zeroext i1 @_Z7successv()
bool success() {
// CHECK: ret i1 true
return ctorcalls == dtorcalls;
diff --git a/test/CodeGenCXX/const-init-cxx11.cpp b/test/CodeGenCXX/const-init-cxx11.cpp
index 833adba..d21e911 100644
--- a/test/CodeGenCXX/const-init-cxx11.cpp
+++ b/test/CodeGenCXX/const-init-cxx11.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin -emit-llvm -o - %s -std=c++11 | FileCheck %s
+// RUN: not %clang_cc1 -verify -triple x86_64-apple-darwin -emit-llvm -o - %s -std=c++11 | FileCheck %s
// FIXME: The padding in all these objects should be zero-initialized.
namespace StructUnion {
@@ -224,12 +224,50 @@ namespace LiteralReference {
constexpr Lit() : n(5) {}
int n;
};
- // FIXME: This should have static initialization, but we do not implement
- // that yet. For now, just check that we don't set the (pointer) value of
- // the reference to 5!
- //
- // CHECK: @_ZN16LiteralReference3litE = global {{.*}} null
+
+ // This creates a non-const temporary and binds a reference to it.
+ // CHECK: @[[TEMP:.*]] = private global {{.*}} { i32 5 }, align 4
+ // CHECK: @_ZN16LiteralReference3litE = constant {{.*}} @[[TEMP]], align 8
const Lit &lit = Lit();
+
+ // This creates a const temporary as part of the reference initialization.
+ // CHECK: @[[TEMP:.*]] = private constant {{.*}} { i32 5 }, align 4
+ // CHECK: @_ZN16LiteralReference4lit2E = constant {{.*}} @[[TEMP]], align 8
+ const Lit &lit2 = {};
+
+ struct A { int &&r1; const int &&r2; };
+ struct B { A &&a1; const A &&a2; };
+ B b = { { 0, 1 }, { 2, 3 } };
+ // CHECK: @[[TEMP0:.*]] = private global i32 0, align 4
+ // CHECK: @[[TEMP1:.*]] = private constant i32 1, align 4
+ // CHECK: @[[TEMPA1:.*]] = private global {{.*}} { i32* @[[TEMP0]], i32* @[[TEMP1]] }, align 8
+ // CHECK: @[[TEMP2:.*]] = private global i32 2, align 4
+ // CHECK: @[[TEMP3:.*]] = private constant i32 3, align 4
+ // CHECK: @[[TEMPA2:.*]] = private constant {{.*}} { i32* @[[TEMP2]], i32* @[[TEMP3]] }, align 8
+ // CHECK: @_ZN16LiteralReference1bE = global {{.*}} { {{.*}}* @[[TEMPA1]], {{.*}}* @[[TEMPA2]] }, align 8
+
+ struct Subobj {
+ int a, b, c;
+ };
+ // CHECK: @[[TEMP:.*]] = private global {{.*}} { i32 1, i32 2, i32 3 }, align 4
+ // CHECK: @_ZN16LiteralReference2soE = constant {{.*}} (i8* getelementptr {{.*}} @[[TEMP]]{{.*}}, i64 4)
+ constexpr int &&so = Subobj{ 1, 2, 3 }.b;
+
+ struct Dummy { int padding; };
+ struct Derived : Dummy, Subobj {
+ constexpr Derived() : Dummy{200}, Subobj{4, 5, 6} {}
+ };
+ using ConstDerived = const Derived;
+ // CHECK: @[[TEMPCOMMA:.*]] = private constant {{.*}} { i32 200, i32 4, i32 5, i32 6 }
+ // CHECK: @_ZN16LiteralReference5commaE = constant {{.*}} getelementptr {{.*}} @[[TEMPCOMMA]]{{.*}}, i64 8)
+ constexpr const int &comma = (1, (2, ConstDerived{}).b);
+
+ // CHECK: @[[TEMPDERIVED:.*]] = private global {{.*}} { i32 200, i32 4, i32 5, i32 6 }
+ // CHECK: @_ZN16LiteralReference4baseE = constant {{.*}} getelementptr {{.*}} @[[TEMPDERIVED]]{{.*}}, i64 4)
+ constexpr Subobj &&base = Derived{};
+
+ // CHECK: @_ZN16LiteralReference7derivedE = constant {{.*}} @[[TEMPDERIVED]]
+ constexpr Derived &derived = static_cast<Derived&>(base);
}
namespace NonLiteralConstexpr {
@@ -330,6 +368,32 @@ namespace PR13273 {
extern const S s {};
}
+namespace ArrayTemporary {
+ struct A { const int (&x)[3]; };
+ struct B { const A (&x)[2]; };
+ // CHECK: @[[A1:_ZGRN14ArrayTemporary1bE.*]] = private constant [3 x i32] [i32 1, i32 2, i32 3]
+ // CHECK: @[[A2:_ZGRN14ArrayTemporary1bE.*]] = private constant [3 x i32] [i32 4, i32 5, i32 6]
+ // CHECK: @[[ARR:_ZGRN14ArrayTemporary1bE.*]] = private constant [2 x {{.*}}] [{{.*}} { [3 x i32]* @[[A1]] }, {{.*}} { [3 x i32]* @[[A2]] }]
+ // CHECK: @[[B:_ZGRN14ArrayTemporary1bE.*]] = private global {{.*}} { [2 x {{.*}}]* @[[ARR]] }
+ // CHECK: @_ZN14ArrayTemporary1bE = constant {{.*}}* @[[B]]
+ B &&b = { { { { 1, 2, 3 } }, { { 4, 5, 6 } } } };
+}
+
+namespace UnemittedTemporaryDecl {
+ constexpr int &&ref = 0;
+ extern constexpr int &ref2 = ref;
+ // CHECK: @_ZGRN22UnemittedTemporaryDecl3refE = private global i32 0
+
+ // FIXME: This declaration should not be emitted -- it isn't odr-used.
+ // CHECK: @_ZN22UnemittedTemporaryDecl3refE
+
+ // CHECK: @_ZN22UnemittedTemporaryDecl4ref2E = constant i32* @_ZGRN22UnemittedTemporaryDecl3refE
+}
+
+// CHECK: @_ZZN12LocalVarInit3aggEvE1a = internal constant {{.*}} i32 101
+// CHECK: @_ZZN12LocalVarInit4ctorEvE1a = internal constant {{.*}} i32 102
+// CHECK: @_ZZN12LocalVarInit8mutable_EvE1a = private unnamed_addr constant {{.*}} i32 103
+
// Constant initialization tests go before this point,
// dynamic initialization tests go after.
@@ -356,6 +420,40 @@ namespace PR13273 {
// CHECK-NOT: }
// CHECK: call {{.*}}cxa_atexit{{.*}}@_ZN19NonLiteralConstexpr4BothD1Ev
+// PR12848: Don't emit dynamic initializers for local constexpr variables.
+namespace LocalVarInit {
+ constexpr int f(int n) { return n; }
+ struct Agg { int k; };
+ struct Ctor { constexpr Ctor(int n) : k(n) {} int k; };
+ struct Mutable { constexpr Mutable(int n) : k(n) {} mutable int k; };
+
+ // CHECK: define {{.*}} @_ZN12LocalVarInit6scalarEv
+ // CHECK-NOT: call
+ // CHECK: store i32 100,
+ // CHECK-NOT: call
+ // CHECK: ret i32 100
+ int scalar() { constexpr int a = { f(100) }; return a; }
+
+ // CHECK: define {{.*}} @_ZN12LocalVarInit3aggEv
+ // CHECK-NOT: call
+ // CHECK: ret i32 101
+ int agg() { constexpr Agg a = { f(101) }; return a.k; }
+
+ // CHECK: define {{.*}} @_ZN12LocalVarInit4ctorEv
+ // CHECK-NOT: call
+ // CHECK: ret i32 102
+ int ctor() { constexpr Ctor a = { f(102) }; return a.k; }
+
+ // CHECK: define {{.*}} @_ZN12LocalVarInit8mutable_Ev
+ // CHECK-NOT: call
+ // CHECK: call {{.*}}memcpy{{.*}} @_ZZN12LocalVarInit8mutable_EvE1a
+ // CHECK-NOT: call
+ // Can't fold return value due to 'mutable'.
+ // CHECK-NOT: ret i32 103
+ // CHECK: }
+ int mutable_() { constexpr Mutable a = { f(103) }; return a.k; }
+}
+
namespace CrossFuncLabelDiff {
// Make sure we refuse to constant-fold the variable b.
constexpr long a(bool x) { return x ? 0 : (long)&&lbl + (0 && ({lbl: 0;})); }
diff --git a/test/CodeGenCXX/const-init-cxx1y.cpp b/test/CodeGenCXX/const-init-cxx1y.cpp
new file mode 100644
index 0000000..978c428
--- /dev/null
+++ b/test/CodeGenCXX/const-init-cxx1y.cpp
@@ -0,0 +1,48 @@
+// RUN: not %clang_cc1 -verify -triple x86_64-apple-darwin -emit-llvm -o - %s -std=c++1y | FileCheck %s
+
+struct A {
+ constexpr A() : n(1) {}
+ ~A();
+ int n;
+};
+struct B : A {
+ A a[3];
+ constexpr B() {
+ ++a[0].n;
+ a[1].n += 2;
+ a[2].n = n + a[1].n;
+ }
+};
+B b;
+
+// CHECK: @b = global {{.*}} i32 1, {{.*}} { i32 2 }, {{.*}} { i32 3 }, {{.*}} { i32 4 }
+// CHECK-NOT: _ZN1BC
+
+namespace ModifyStaticTemporary {
+ struct A { int &&temporary; int x; };
+ constexpr int f(int &r) { r *= 9; return r - 12; }
+ A a = { 6, f(a.temporary) };
+ // CHECK: @_ZGRN21ModifyStaticTemporary1aE = private global i32 54
+ // CHECK: @_ZN21ModifyStaticTemporary1aE = global {{.*}} i32* @_ZGRN21ModifyStaticTemporary1aE, i32 42
+
+ A b = { 7, ++b.temporary };
+ // CHECK: @_ZGRN21ModifyStaticTemporary1bE = private global i32 8
+ // CHECK: @_ZN21ModifyStaticTemporary1bE = global {{.*}} i32* @_ZGRN21ModifyStaticTemporary1bE, i32 8
+
+ // Can't emit all of 'c' as a constant here, so emit the initial value of
+ // 'c.temporary', not the value as modified by the partial evaluation within
+ // the initialization of 'c.x'.
+ A c = { 10, (++c.temporary, b.x) };
+ // CHECK: @_ZGRN21ModifyStaticTemporary1cE = private global i32 10
+ // CHECK: @_ZN21ModifyStaticTemporary1cE = global {{.*}} zeroinitializer
+}
+
+// CHECK: __cxa_atexit({{.*}} @_ZN1BD1Ev {{.*}} @b
+
+// CHECK: define
+// CHECK-NOT: @_ZGRN21ModifyStaticTemporary1cE
+// CHECK: store {{.*}} @_ZGRN21ModifyStaticTemporary1cE, {{.*}} @_ZN21ModifyStaticTemporary1cE
+// CHECK: add
+// CHECK: store
+// CHECK: load {{.*}} @_ZN21ModifyStaticTemporary1bE
+// CHECK: store {{.*}} @_ZN21ModifyStaticTemporary1cE
diff --git a/test/CodeGenCXX/const-init.cpp b/test/CodeGenCXX/const-init.cpp
index 201ce8f..05896ff 100644
--- a/test/CodeGenCXX/const-init.cpp
+++ b/test/CodeGenCXX/const-init.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin -emit-llvm -o - %s | FileCheck %s
+// RUN: not %clang_cc1 -verify -triple x86_64-apple-darwin -emit-llvm -o - %s | FileCheck %s
// CHECK: @a = global i32 10
int a = 10;
diff --git a/test/CodeGenCXX/constructor-attr.cpp b/test/CodeGenCXX/constructor-attr.cpp
index 691795f..4f6d635 100644
--- a/test/CodeGenCXX/constructor-attr.cpp
+++ b/test/CodeGenCXX/constructor-attr.cpp
@@ -5,7 +5,7 @@
// PR6521
void bar();
struct Foo {
- // CHECK: define linkonce_odr void @_ZN3Foo3fooEv
+ // CHECK-LABEL: define linkonce_odr void @_ZN3Foo3fooEv
static void foo() __attribute__((constructor)) {
bar();
}
diff --git a/test/CodeGenCXX/constructor-conversion.cpp b/test/CodeGenCXX/constructor-conversion.cpp
index f503463..ebb414d 100644
--- a/test/CodeGenCXX/constructor-conversion.cpp
+++ b/test/CodeGenCXX/constructor-conversion.cpp
@@ -1,8 +1,8 @@
// REQUIRES: x86-registered-target,x86-64-registered-target
// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -S %s -o %t-64.s
-// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s
+// RUN: FileCheck -check-prefix CHECK-LP64 --input-file=%t-64.s %s
// RUN: %clang_cc1 -triple i386-apple-darwin -std=c++11 -S %s -o %t-32.s
-// RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s
+// RUN: FileCheck -check-prefix CHECK-LP32 --input-file=%t-32.s %s
extern "C" int printf(...);
diff --git a/test/CodeGenCXX/constructor-default-arg.cpp b/test/CodeGenCXX/constructor-default-arg.cpp
index 32086c1..c2cf44c 100644
--- a/test/CodeGenCXX/constructor-default-arg.cpp
+++ b/test/CodeGenCXX/constructor-default-arg.cpp
@@ -1,8 +1,8 @@
// REQUIRES: x86-registered-target,x86-64-registered-target
// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -S %s -o %t-64.s
-// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s
+// RUN: FileCheck -check-prefix CHECK-LP64 --input-file=%t-64.s %s
// RUN: %clang_cc1 -triple i386-apple-darwin -std=c++11 -S %s -o %t-32.s
-// RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s
+// RUN: FileCheck -check-prefix CHECK-LP32 --input-file=%t-32.s %s
extern "C" int printf(...);
diff --git a/test/CodeGenCXX/constructor-destructor-return-this.cpp b/test/CodeGenCXX/constructor-destructor-return-this.cpp
index 1ff922d..ea2ea45 100644
--- a/test/CodeGenCXX/constructor-destructor-return-this.cpp
+++ b/test/CodeGenCXX/constructor-destructor-return-this.cpp
@@ -1,60 +1,116 @@
-//RUN: %clang_cc1 %s -emit-llvm -o - -triple=thumbv7-apple-ios3.0 -target-abi apcs-gnu | FileCheck %s
+//RUN: %clang_cc1 %s -emit-llvm -o - -triple=i686-unknown-linux | FileCheck --check-prefix=CHECKGEN %s
+//RUN: %clang_cc1 %s -emit-llvm -o - -triple=thumbv7-apple-ios3.0 -target-abi apcs-gnu | FileCheck --check-prefix=CHECKARM %s
+//RUN: %clang_cc1 %s -emit-llvm -o - -triple=i386-pc-win32 -cxx-abi microsoft -fno-rtti | FileCheck --check-prefix=CHECKMS %s
+// FIXME: these tests crash on the bots when run with -triple=x86_64-pc-win32
-// 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
+// Make sure we attach the 'returned' attribute to the 'this' parameter of
+// constructors and destructors which return this (and only these cases)
-// CHECK: define linkonce_odr [[A:%.*]] @_ZN11ObjectCacheC1Ev([[A]] %this) unnamed_addr
-// CHECK: [[THIS1:%.*]] = call [[A]] @_ZN11ObjectCacheC2Ev(
-// CHECK-NEXT: ret [[A]] [[THIS1]]
+class A {
+public:
+ A();
+ ~A();
-// CHECK: define linkonce_odr [[A:%.*]] @_ZN5TimerI11ObjectCacheEC1EPS0_MS0_FvPS1_E([[A]] %this
-// CHECK: [[THIS1:%.*]] = call [[A]] @_ZN5TimerI11ObjectCacheEC2EPS0_MS0_FvPS1_E(
-// CHECK-NEXT: ret [[A]] [[THIS1]]
+private:
+ int x_;
+};
-// CHECK: define linkonce_odr [[A:%.*]] @_ZN5TimerI11ObjectCacheED1Ev([[A]] %this) unnamed_addr
-// CHECK: [[THIS1:%.*]] = call [[A]] @_ZN5TimerI11ObjectCacheED2Ev(
-// CHECK-NEXT: ret [[A]] [[THIS1]]
+class B : public A {
+public:
+ B(int *i);
+ ~B();
+
+private:
+ int *i_;
+};
-// 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]]
+B::B(int *i) : i_(i) { }
+B::~B() { }
-class TimerBase {
+// CHECKGEN-LABEL: define void @_ZN1BC1EPi(%class.B* %this, i32* %i)
+// CHECKGEN-LABEL: define void @_ZN1BC2EPi(%class.B* %this, i32* %i)
+// CHECKGEN-LABEL: define void @_ZN1BD1Ev(%class.B* %this)
+// CHECKGEN-LABEL: define void @_ZN1BD2Ev(%class.B* %this)
+
+// CHECKARM-LABEL: define %class.B* @_ZN1BC1EPi(%class.B* returned %this, i32* %i)
+// CHECKARM-LABEL: define %class.B* @_ZN1BC2EPi(%class.B* returned %this, i32* %i)
+// CHECKARM-LABEL: define %class.B* @_ZN1BD1Ev(%class.B* returned %this)
+// CHECKARM-LABEL: define %class.B* @_ZN1BD2Ev(%class.B* returned %this)
+
+// CHECKMS-LABEL: define x86_thiscallcc %class.B* @"\01??0B@@QAE@PAH@Z"(%class.B* returned %this, i32* %i)
+// CHECKMS-LABEL: define x86_thiscallcc void @"\01??1B@@QAE@XZ"(%class.B* %this)
+
+class C : public A, public B {
public:
- TimerBase();
- virtual ~TimerBase();
+ C(int *i, char *c);
+ virtual ~C();
+private:
+ char *c_;
};
-template <typename TimerFiredClass> class Timer : public TimerBase {
-public:
- typedef void (TimerFiredClass::*TimerFiredFunction)(Timer*);
+C::C(int *i, char *c) : B(i), c_(c) { }
+C::~C() { }
- Timer(TimerFiredClass* o, TimerFiredFunction f)
- : m_object(o), m_function(f) { }
+// CHECKGEN-LABEL: define void @_ZN1CC1EPiPc(%class.C* %this, i32* %i, i8* %c)
+// CHECKGEN-LABEL: define void @_ZN1CC2EPiPc(%class.C* %this, i32* %i, i8* %c)
+// CHECKGEN-LABEL: define void @_ZN1CD0Ev(%class.C* %this)
+// CHECKGEN-LABEL: define void @_ZN1CD1Ev(%class.C* %this)
+// CHECKGEN-LABEL: define void @_ZN1CD2Ev(%class.C* %this)
-private:
- virtual void fired() { (m_object->*m_function)(this); }
+// CHECKARM-LABEL: define %class.C* @_ZN1CC1EPiPc(%class.C* returned %this, i32* %i, i8* %c)
+// CHECKARM-LABEL: define %class.C* @_ZN1CC2EPiPc(%class.C* returned %this, i32* %i, i8* %c)
+// CHECKARM-LABEL: define void @_ZN1CD0Ev(%class.C* %this)
+// CHECKARM-LABEL: define %class.C* @_ZN1CD1Ev(%class.C* returned %this)
+// CHECKARM-LABEL: define %class.C* @_ZN1CD2Ev(%class.C* returned %this)
- TimerFiredClass* m_object;
- TimerFiredFunction m_function;
-};
+// CHECKMS-LABEL: define x86_thiscallcc %class.C* @"\01??0C@@QAE@PAHPAD@Z"(%class.C* returned %this, i32* %i, i8* %c)
+// CHECKMS-LABEL: define x86_thiscallcc void @"\01??1C@@UAE@XZ"(%class.C* %this)
-class ObjectCache {
+class D : public virtual A {
public:
- explicit ObjectCache();
- ~ObjectCache();
+ D();
+ ~D();
+};
-private:
- Timer<ObjectCache> m_notificationPostTimer;
+D::D() { }
+D::~D() { }
+
+// CHECKGEN-LABEL: define void @_ZN1DC1Ev(%class.D* %this)
+// CHECKGEN-LABEL: define void @_ZN1DC2Ev(%class.D* %this, i8** %vtt)
+// CHECKGEN-LABEL: define void @_ZN1DD1Ev(%class.D* %this)
+// CHECKGEN-LABEL: define void @_ZN1DD2Ev(%class.D* %this, i8** %vtt)
+
+// CHECKARM-LABEL: define %class.D* @_ZN1DC1Ev(%class.D* returned %this)
+// CHECKARM-LABEL: define %class.D* @_ZN1DC2Ev(%class.D* returned %this, i8** %vtt)
+// CHECKARM-LABEL: define %class.D* @_ZN1DD1Ev(%class.D* returned %this)
+// CHECKARM-LABEL: define %class.D* @_ZN1DD2Ev(%class.D* returned %this, i8** %vtt)
+
+// CHECKMS-LABEL: define x86_thiscallcc %class.D* @"\01??0D@@QAE@XZ"(%class.D* returned %this, i32 %is_most_derived)
+// CHECKMS-LABEL: define x86_thiscallcc void @"\01??1D@@QAE@XZ"(%class.D* %this)
+
+class E {
+public:
+ E();
+ virtual ~E();
};
-inline ObjectCache::ObjectCache() : m_notificationPostTimer(this, 0) { }
-inline ObjectCache::~ObjectCache() { }
+E* gete();
-ObjectCache *test() {
- ObjectCache *dd = new ObjectCache();
- return dd;
+void test_destructor() {
+ const E& e1 = E();
+ E* e2 = gete();
+ e2->~E();
}
+
+// CHECKARM-LABEL: define void @_Z15test_destructorv()
+
+// Verify that virtual calls to destructors are not marked with a 'returned'
+// this parameter at the call site...
+// CHECKARM: [[VFN:%.*]] = getelementptr inbounds %class.E* (%class.E*)**
+// CHECKARM: [[THUNK:%.*]] = load %class.E* (%class.E*)** [[VFN]]
+// CHECKARM: call %class.E* [[THUNK]](%class.E* %
+
+// ...but static calls create declarations with 'returned' this
+// CHECKARM: {{%.*}} = call %class.E* @_ZN1ED1Ev(%class.E* %
+
+// CHECKARM: declare %class.E* @_ZN1ED1Ev(%class.E* returned)
diff --git a/test/CodeGenCXX/constructor-for-array-members.cpp b/test/CodeGenCXX/constructor-for-array-members.cpp
index 7a365cd..7842d9c 100644
--- a/test/CodeGenCXX/constructor-for-array-members.cpp
+++ b/test/CodeGenCXX/constructor-for-array-members.cpp
@@ -1,8 +1,8 @@
// REQUIRES: x86-registered-target,x86-64-registered-target
// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -S %s -o %t-64.s
-// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s
+// RUN: FileCheck -check-prefix CHECK-LP64 --input-file=%t-64.s %s
// RUN: %clang_cc1 -triple i386-apple-darwin -std=c++11 -S %s -o %t-32.s
-// RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s
+// RUN: FileCheck -check-prefix CHECK-LP32 --input-file=%t-32.s %s
extern "C" int printf(...);
diff --git a/test/CodeGenCXX/constructor-init.cpp b/test/CodeGenCXX/constructor-init.cpp
index b33184e..477a439 100644
--- a/test/CodeGenCXX/constructor-init.cpp
+++ b/test/CodeGenCXX/constructor-init.cpp
@@ -70,7 +70,7 @@ template <class T> struct A {
operator int() {return 0;}
};
-// CHECK: define void @_Z1fv()
+// CHECK-LABEL: define void @_Z1fv()
void f() {
// CHECK: call void @_ZN1AIsEC1Ei
A<short> a4 = 97;
@@ -93,7 +93,7 @@ namespace InitVTable {
B(int);
};
- // CHECK: define void @_ZN10InitVTable1BC2Ev(%"struct.InitVTable::B"* %this) unnamed_addr
+ // CHECK-LABEL: define void @_ZN10InitVTable1BC2Ev(%"struct.InitVTable::B"* %this) unnamed_addr
// CHECK: [[T0:%.*]] = bitcast [[B:%.*]]* [[THIS:%.*]] to i8***
// CHECK-NEXT: store i8** getelementptr inbounds ([3 x i8*]* @_ZTVN10InitVTable1BE, i64 0, i64 2), i8*** [[T0]]
// CHECK: [[VTBL:%.*]] = load i32 ([[B]]*)*** {{%.*}}
@@ -106,7 +106,7 @@ namespace InitVTable {
// CHECK-NEXT: ret void
B::B() : A(foo()) {}
- // CHECK: define void @_ZN10InitVTable1BC2Ei(%"struct.InitVTable::B"* %this, i32 %x) unnamed_addr
+ // CHECK-LABEL: define void @_ZN10InitVTable1BC2Ei(%"struct.InitVTable::B"* %this, i32 %x) unnamed_addr
// CHECK: [[ARG:%.*]] = add nsw i32 {{%.*}}, 5
// CHECK-NEXT: call void @_ZN10InitVTable1AC2Ei({{.*}}* {{%.*}}, i32 [[ARG]])
// CHECK-NEXT: [[T0:%.*]] = bitcast [[B]]* {{%.*}} to i8***
@@ -120,7 +120,7 @@ namespace rdar9694300 {
int x;
};
- // CHECK: define void @_ZN11rdar96943001fEv
+ // CHECK-LABEL: define void @_ZN11rdar96943001fEv
void f() {
// CHECK: alloca
X x;
@@ -163,7 +163,7 @@ template<typename T> struct X;
// Make sure that the instantiated constructor initializes start and
// end properly.
-// CHECK: define linkonce_odr void @_ZN1XIiEC2ERKS0_(%struct.X* %this, %struct.X* %other) unnamed_addr
+// CHECK-LABEL: define linkonce_odr void @_ZN1XIiEC2ERKS0_(%struct.X* %this, %struct.X* %other) unnamed_addr
// CHECK: {{store.*null}}
// CHECK: {{store.*null}}
// CHECK: ret
@@ -200,7 +200,7 @@ namespace PR10720 {
// CHECK-PR10720: ret
pair2 &operator=(pair2&&) = default;
- // CHECK-PR10720: define linkonce_odr void @_ZN7PR107205pair2C2EOS0_
+ // CHECK-PR10720-LABEL: define linkonce_odr void @_ZN7PR107205pair2C2EOS0_
// CHECK-PR10720-NOT: ret
// CHECK-PR10720: load
// CHECK-PR10720: icmp ult
@@ -210,7 +210,7 @@ namespace PR10720 {
// CHECK-PR10720: ret void
pair2(pair2&&) = default;
- // CHECK-PR10720: define linkonce_odr void @_ZN7PR107205pair2C2ERKS0_
+ // CHECK-PR10720-LABEL: define linkonce_odr void @_ZN7PR107205pair2C2ERKS0_
// CHECK-PR10720-NOT: ret
// CHECK-PR10720: load
// CHECK-PR10720: icmp ult
@@ -223,7 +223,7 @@ namespace PR10720 {
struct pair : X { // Make the copy constructor non-trivial, so we actually generate it.
int second[4];
- // CHECK-PR10720: define linkonce_odr void @_ZN7PR107204pairC2ERKS0_
+ // CHECK-PR10720-LABEL: define linkonce_odr void @_ZN7PR107204pairC2ERKS0_
// CHECK-PR10720-NOT: ret
// CHECK-PR10720: call void @llvm.memcpy
// CHECK-PR10720-NEXT: ret void
diff --git a/test/CodeGenCXX/constructor-template.cpp b/test/CodeGenCXX/constructor-template.cpp
index fe4687c..0d38d10 100644
--- a/test/CodeGenCXX/constructor-template.cpp
+++ b/test/CodeGenCXX/constructor-template.cpp
@@ -1,8 +1,8 @@
// REQUIRES: x86-registered-target,x86-64-registered-target
// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -S %s -o %t-64.s
-// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s
+// RUN: FileCheck -check-prefix CHECK-LP64 --input-file=%t-64.s %s
// RUN: %clang_cc1 -triple i386-apple-darwin -std=c++11 -S %s -o %t-32.s
-// RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s
+// RUN: FileCheck -check-prefix CHECK-LP32 --input-file=%t-32.s %s
// PR4826
struct A {
diff --git a/test/CodeGenCXX/constructors.cpp b/test/CodeGenCXX/constructors.cpp
index 9e2da31..f730b9e 100644
--- a/test/CodeGenCXX/constructors.cpp
+++ b/test/CodeGenCXX/constructors.cpp
@@ -21,18 +21,18 @@ struct A {
A::A(struct Undeclared &ref) : mem(0) {}
// Check that delegation works.
-// CHECK: define void @_ZN1AC1ER10Undeclared(%struct.A* %this, %struct.Undeclared* %ref) unnamed_addr
+// CHECK-LABEL: define void @_ZN1AC1ER10Undeclared(%struct.A* %this, %struct.Undeclared* %ref) unnamed_addr
// CHECK: call void @_ZN1AC2ER10Undeclared(
-// CHECK: define void @_ZN1AC2ER10Undeclared(%struct.A* %this, %struct.Undeclared* %ref) unnamed_addr
+// CHECK-LABEL: define void @_ZN1AC2ER10Undeclared(%struct.A* %this, %struct.Undeclared* %ref) unnamed_addr
// CHECK: call void @_ZN6MemberC1Ei(
A::A(ValueClass v) : mem(v.y - v.x) {}
-// CHECK: define void @_ZN1AC1E10ValueClass(%struct.A* %this, i64 %v.coerce) unnamed_addr
+// CHECK-LABEL: define void @_ZN1AC1E10ValueClass(%struct.A* %this, i64 %v.coerce) unnamed_addr
// CHECK: call void @_ZN1AC2E10ValueClass(
-// CHECK: define void @_ZN1AC2E10ValueClass(%struct.A* %this, i64 %v.coerce) unnamed_addr
+// CHECK-LABEL: define void @_ZN1AC2E10ValueClass(%struct.A* %this, i64 %v.coerce) unnamed_addr
// CHECK: call void @_ZN6MemberC1Ei(
@@ -44,10 +44,10 @@ struct B : A {
B::B(struct Undeclared &ref) : A(ref), mem(1) {}
-// CHECK: define void @_ZN1BC1ER10Undeclared(%struct.B* %this, %struct.Undeclared* %ref) unnamed_addr
+// CHECK-LABEL: define void @_ZN1BC1ER10Undeclared(%struct.B* %this, %struct.Undeclared* %ref) unnamed_addr
// CHECK: call void @_ZN1BC2ER10Undeclared(
-// CHECK: define void @_ZN1BC2ER10Undeclared(%struct.B* %this, %struct.Undeclared* %ref) unnamed_addr
+// CHECK-LABEL: define void @_ZN1BC2ER10Undeclared(%struct.B* %this, %struct.Undeclared* %ref) unnamed_addr
// CHECK: call void @_ZN1AC2ER10Undeclared(
// CHECK: call void @_ZN6MemberC1Ei(
@@ -64,12 +64,12 @@ struct C : virtual A {
};
C::C(int x) : A(ValueClass(x, x+1)), mem(x * x) {}
-// CHECK: define void @_ZN1CC1Ei(%struct.C* %this, i32 %x) unnamed_addr
+// CHECK-LABEL: define void @_ZN1CC1Ei(%struct.C* %this, i32 %x) unnamed_addr
// CHECK: call void @_ZN10ValueClassC1Eii(
// CHECK: call void @_ZN1AC2E10ValueClass(
// CHECK: call void @_ZN6MemberC1Ei(
-// CHECK: define void @_ZN1CC2Ei(%struct.C* %this, i8** %vtt, i32 %x) unnamed_addr
+// CHECK-LABEL: define void @_ZN1CC2Ei(%struct.C* %this, i8** %vtt, i32 %x) unnamed_addr
// CHECK: call void @_ZN6MemberC1Ei(
@@ -83,12 +83,12 @@ struct D : A {
D::D(int x, ...) : A(ValueClass(x, x+1)), mem(x*x) {}
-// CHECK: define void @_ZN1DC1Eiz(%struct.D* %this, i32 %x, ...) unnamed_addr
+// CHECK-LABEL: define void @_ZN1DC1Eiz(%struct.D* %this, i32 %x, ...) unnamed_addr
// CHECK: call void @_ZN10ValueClassC1Eii(
// CHECK: call void @_ZN1AC2E10ValueClass(
// CHECK: call void @_ZN6MemberC1Ei(
-// CHECK: define void @_ZN1DC2Eiz(%struct.D* %this, i32 %x, ...) unnamed_addr
+// CHECK-LABEL: define void @_ZN1DC2Eiz(%struct.D* %this, i32 %x, ...) unnamed_addr
// CHECK: call void @_ZN10ValueClassC1Eii(
// CHECK: call void @_ZN1AC2E10ValueClass(
// CHECK: call void @_ZN6MemberC1Ei(
@@ -109,7 +109,7 @@ namespace test1 {
struct A { A(); void *ptr; };
struct B { B(); int x; A a[0]; };
B::B() {}
- // CHECK: define void @_ZN5test11BC2Ev(
+ // CHECK-LABEL: define void @_ZN5test11BC2Ev(
// CHECK: [[THIS:%.*]] = load [[B:%.*]]**
// CHECK-NEXT: ret void
}
diff --git a/test/CodeGenCXX/conversion-function.cpp b/test/CodeGenCXX/conversion-function.cpp
index 76d9e02..ec098d0 100644
--- a/test/CodeGenCXX/conversion-function.cpp
+++ b/test/CodeGenCXX/conversion-function.cpp
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -S %s -o %t-64.s
-// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s
+// RUN: FileCheck -check-prefix CHECK-LP64 --input-file=%t-64.s %s
// RUN: %clang_cc1 -triple i386-apple-darwin -std=c++11 -S %s -o %t-32.s
-// RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s
+// RUN: FileCheck -check-prefix CHECK-LP32 --input-file=%t-32.s %s
// XFAIL: *
extern "C" int printf(...);
struct S {
diff --git a/test/CodeGenCXX/convert-to-fptr.cpp b/test/CodeGenCXX/convert-to-fptr.cpp
index 425f79d..e497acf 100644
--- a/test/CodeGenCXX/convert-to-fptr.cpp
+++ b/test/CodeGenCXX/convert-to-fptr.cpp
@@ -1,8 +1,8 @@
// REQUIRES: x86-registered-target,x86-64-registered-target
// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -S %s -o %t-64.s
-// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s
+// RUN: FileCheck -check-prefix CHECK-LP64 --input-file=%t-64.s %s
// RUN: %clang_cc1 -triple i386-apple-darwin -std=c++11 -S %s -o %t-32.s
-// RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s
+// RUN: FileCheck -check-prefix CHECK-LP32 --input-file=%t-32.s %s
extern "C" int printf(...);
diff --git a/test/CodeGenCXX/copy-assign-synthesis-1.cpp b/test/CodeGenCXX/copy-assign-synthesis-1.cpp
index 5d09b54..2ffc7bc 100644
--- a/test/CodeGenCXX/copy-assign-synthesis-1.cpp
+++ b/test/CodeGenCXX/copy-assign-synthesis-1.cpp
@@ -1,8 +1,8 @@
// REQUIRES: x86-registered-target,x86-64-registered-target
-// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -S %s -o %t-64.s
-// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s
-// RUN: %clang_cc1 -triple i386-apple-darwin -std=c++11 -S %s -o %t-32.s
-// RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -emit-llvm %s -o - | \
+// RUN: FileCheck %s
+// RUN: %clang_cc1 -triple i386-apple-darwin -std=c++11 -emit-llvm %s -o - | \
+// RUN: FileCheck %s
extern "C" int printf(...);
@@ -93,11 +93,5 @@ int main() {
dstY.pr();
}
-// CHECK-LP64: .globl __ZN1XaSERKS_
-// CHECK-LP64: .weak_definition __ZN1XaSERKS_
-// CHECK-LP64: __ZN1XaSERKS_:
-
-// CHECK-LP32: .globl __ZN1XaSERKS_
-// CHECK-LP32: .weak_definition __ZN1XaSERKS_
-// CHECK-LP32: __ZN1XaSERKS_:
+// CHECK: define linkonce_odr %struct.X* @_ZN1XaSERKS_
diff --git a/test/CodeGenCXX/copy-assign-synthesis-2.cpp b/test/CodeGenCXX/copy-assign-synthesis-2.cpp
index c25e046..18e92f9 100644
--- a/test/CodeGenCXX/copy-assign-synthesis-2.cpp
+++ b/test/CodeGenCXX/copy-assign-synthesis-2.cpp
@@ -1,4 +1,4 @@
// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s
struct A {};
A& (A::*x)(const A&) = &A::operator=;
-// CHECK: define linkonce_odr %struct.A* @_ZN1AaSERKS_
+// CHECK-LABEL: define linkonce_odr %struct.A* @_ZN1AaSERKS_
diff --git a/test/CodeGenCXX/copy-assign-synthesis.cpp b/test/CodeGenCXX/copy-assign-synthesis.cpp
index e9fc0c3..9c8ae88 100644
--- a/test/CodeGenCXX/copy-assign-synthesis.cpp
+++ b/test/CodeGenCXX/copy-assign-synthesis.cpp
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 -emit-llvm -o %t %s
-// RUN: grep "_ZN1XaSERK1X" %t | count 0
+// RUN: not grep "_ZN1XaSERK1X" %t
extern "C" int printf(...);
diff --git a/test/CodeGenCXX/copy-constructor-elim-2.cpp b/test/CodeGenCXX/copy-constructor-elim-2.cpp
index 4ff8775..727af1b 100644
--- a/test/CodeGenCXX/copy-constructor-elim-2.cpp
+++ b/test/CodeGenCXX/copy-constructor-elim-2.cpp
@@ -2,7 +2,7 @@
struct A { int x; A(int); ~A(); };
A f() { return A(0); }
-// CHECK: define void @_Z1fv
+// CHECK-LABEL: define void @_Z1fv
// CHECK: call {{.*}} @_ZN1AC1Ei
// CHECK-NEXT: ret void
@@ -21,7 +21,7 @@ namespace no_elide_base {
Derived(const Other &O);
};
- // CHECK: define {{.*}} @_ZN13no_elide_base7DerivedC1ERKNS_5OtherE(%"struct.no_elide_base::Derived"* %this, %"struct.no_elide_base::Other"* %O) unnamed_addr
+ // CHECK: define {{.*}} @_ZN13no_elide_base7DerivedC1ERKNS_5OtherE(%"struct.no_elide_base::Derived"* returned %this, %"struct.no_elide_base::Other"* %O) unnamed_addr
Derived::Derived(const Other &O)
// CHECK: call {{.*}} @_ZNK13no_elide_base5OthercvNS_4BaseEEv
// CHECK: call {{.*}} @_ZN13no_elide_base4BaseC2ERKS0_
@@ -63,7 +63,7 @@ namespace PR12139 {
static A makeA() { A a; a.value = 2; return a; }
};
- // CHECK: define i32 @_ZN7PR121394testEv
+ // CHECK-LABEL: define i32 @_ZN7PR121394testEv
int test() {
// CHECK: call void @_ZN7PR121391A5makeAEv
// CHECK-NEXT: call %"struct.PR12139::A"* @_ZN7PR121391AC1ERKS0_i
diff --git a/test/CodeGenCXX/copy-constructor-elim.cpp b/test/CodeGenCXX/copy-constructor-elim.cpp
index c883584..ad3a87b 100644
--- a/test/CodeGenCXX/copy-constructor-elim.cpp
+++ b/test/CodeGenCXX/copy-constructor-elim.cpp
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 -emit-llvm -o %t %s
-// RUN: grep "_ZN1CC1ERK1C" %t | count 0
-// RUN: grep "_ZN1SC1ERK1S" %t | count 0
+// RUN: not grep "_ZN1CC1ERK1C" %t
+// RUN: not grep "_ZN1SC1ERK1S" %t
extern "C" int printf(...);
diff --git a/test/CodeGenCXX/copy-constructor-synthesis-2.cpp b/test/CodeGenCXX/copy-constructor-synthesis-2.cpp
index d028a28..03c6633 100644
--- a/test/CodeGenCXX/copy-constructor-synthesis-2.cpp
+++ b/test/CodeGenCXX/copy-constructor-synthesis-2.cpp
@@ -3,5 +3,5 @@
struct A { virtual void a(); };
A x(A& y) { return y; }
-// CHECK: define linkonce_odr {{.*}} @_ZN1AC1ERKS_(%struct.A* %this, %struct.A*) unnamed_addr
+// CHECK: define linkonce_odr {{.*}} @_ZN1AC1ERKS_(%struct.A* {{.*}}%this, %struct.A*) unnamed_addr
// CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTV1A, i64 0, i64 2)
diff --git a/test/CodeGenCXX/copy-constructor-synthesis.cpp b/test/CodeGenCXX/copy-constructor-synthesis.cpp
index 68f6805..c8b265c 100644
--- a/test/CodeGenCXX/copy-constructor-synthesis.cpp
+++ b/test/CodeGenCXX/copy-constructor-synthesis.cpp
@@ -21,7 +21,7 @@ struct P {
};
-// CHECK: define linkonce_odr void @_ZN1XC1ERKS_(%struct.X* %this, %struct.X*) unnamed_addr
+// CHECK-LABEL: define linkonce_odr void @_ZN1XC1ERKS_(%struct.X* %this, %struct.X*) unnamed_addr
struct X : M, N, P { // ...
X() : f1(1.0), d1(2.0), i1(3), name("HELLO"), bf1(0xff), bf2(0xabcd),
au_i1(1234), au1_4("MASKED") {}
@@ -136,7 +136,33 @@ void f(B b1) {
B b2 = b1;
}
-// CHECK: define linkonce_odr void @_ZN6PR66281BC2ERKS0_(%"struct.PR6628::B"* %this, %"struct.PR6628::B"*) unnamed_addr
+// CHECK: define linkonce_odr [[A:%.*]]* @_ZN12rdar138169401AaSERKS0_(
+// CHECK: [[THIS:%.*]] = load [[A]]**
+// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[A]]* [[THIS]], i32 0, i32 1
+// CHECK-NEXT: [[T1:%.*]] = bitcast [2 x i8]* [[T0]] to i16*
+// CHECK-NEXT: [[OTHER:%.*]] = load [[A]]**
+// CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds [[A]]* [[OTHER]], i32 0, i32 1
+// CHECK-NEXT: [[T3:%.*]] = bitcast [2 x i8]* [[T2]] to i16*
+// CHECK-NEXT: [[T4:%.*]] = bitcast i16* [[T1]] to i8*
+// CHECK-NEXT: [[T5:%.*]] = bitcast i16* [[T3]] to i8*
+// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[T4]], i8* [[T5]], i64 8, i32 8, i1 false)
+// CHECK-NEXT: ret [[A]]* [[THIS]]
+
+// CHECK-LABEL: define linkonce_odr void @_ZN12rdar138169401AC2ERKS0_(
+// CHECK: [[THIS:%.*]] = load [[A]]**
+// CHECK-NEXT: [[T0:%.*]] = bitcast [[A]]* [[THIS]] to i8***
+// CHECK-NEXT: store i8** getelementptr inbounds ([4 x i8*]* @_ZTVN12rdar138169401AE, i64 0, i64 2), i8*** [[T0]]
+// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[A]]* [[THIS]], i32 0, i32 1
+// CHECK-NEXT: [[T1:%.*]] = bitcast [2 x i8]* [[T0]] to i16*
+// CHECK-NEXT: [[OTHER:%.*]] = load [[A]]**
+// CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds [[A]]* [[OTHER]], i32 0, i32 1
+// CHECK-NEXT: [[T3:%.*]] = bitcast [2 x i8]* [[T2]] to i16*
+// CHECK-NEXT: [[T4:%.*]] = bitcast i16* [[T1]] to i8*
+// CHECK-NEXT: [[T5:%.*]] = bitcast i16* [[T3]] to i8*
+// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[T4]], i8* [[T5]], i64 8, i32 8, i1 false)
+// CHECK-NEXT: ret void
+
+// CHECK-LABEL: define linkonce_odr void @_ZN6PR66281BC2ERKS0_(%"struct.PR6628::B"* %this, %"struct.PR6628::B"*) unnamed_addr
// CHECK: call void @_ZN6PR66281TC1Ev
// CHECK: call void @_ZN6PR66281TC1Ev
// CHECK: call void @_ZN6PR66281AC2ERKS0_RKNS_1TES5_
@@ -154,3 +180,18 @@ void f(B b1) {
// CHECK: call void @_ZN6PR66281TD1Ev
}
+// rdar://13816940
+// Test above because things get weirdly re-ordered.
+namespace rdar13816940 {
+ struct A {
+ virtual ~A();
+ unsigned short a : 1;
+ unsigned short : 15;
+ unsigned other;
+ };
+
+ void test(A &a) {
+ A x = a; // force copy constructor into existence
+ x = a; // also force the copy assignment operator
+ }
+}
diff --git a/test/CodeGenCXX/copy-initialization.cpp b/test/CodeGenCXX/copy-initialization.cpp
index aecd64e..1a16013 100644
--- a/test/CodeGenCXX/copy-initialization.cpp
+++ b/test/CodeGenCXX/copy-initialization.cpp
@@ -12,7 +12,7 @@ struct Bar {
void f(Foo);
-// CHECK: define void @_Z1g3Foo(%struct.Foo* %foo)
+// CHECK-LABEL: define void @_Z1g3Foo(%struct.Foo* %foo)
void g(Foo foo) {
// CHECK: call void @_ZN3BarC1Ev
// CHECK: @_ZNK3BarcvRK3FooEv
diff --git a/test/CodeGenCXX/crash.cpp b/test/CodeGenCXX/crash.cpp
new file mode 100644
index 0000000..073542d
--- /dev/null
+++ b/test/CodeGenCXX/crash.cpp
@@ -0,0 +1,35 @@
+// RUN: %clang_cc1 %s -std=c++11 -emit-llvm-only
+// CHECK that we don't crash.
+
+// PR11676's example is ill-formed:
+/*
+union _XEvent {
+};
+void ProcessEvent() {
+ _XEvent pluginEvent = _XEvent();
+}
+*/
+
+// Example from PR11665:
+void f() {
+ union U { int field; } u = U();
+ (void)U().field;
+}
+
+namespace PR17476 {
+struct string {
+ string(const char *__s);
+ string &operator+=(const string &__str);
+};
+
+template <class ELFT> void finalizeDefaultAtomValues() {
+ auto startEnd = [&](const char * sym)->void {
+ string start("__");
+ start += sym;
+ }
+ ;
+ startEnd("preinit_array");
+}
+
+void f() { finalizeDefaultAtomValues<int>(); }
+}
diff --git a/test/CodeGenCXX/ctor-dtor-alias.cpp b/test/CodeGenCXX/ctor-dtor-alias.cpp
new file mode 100644
index 0000000..235d165
--- /dev/null
+++ b/test/CodeGenCXX/ctor-dtor-alias.cpp
@@ -0,0 +1,163 @@
+// RUN: %clang_cc1 %s -triple x86_64-linux -emit-llvm -o - -mconstructor-aliases -O1 -disable-llvm-optzns | FileCheck %s
+// RUN: %clang_cc1 %s -triple x86_64-linux -emit-llvm -o - -mconstructor-aliases | FileCheck --check-prefix=NOOPT %s
+
+// RUN: %clang_cc1 -cc1 -triple x86_64--netbsd -emit-llvm \
+// RUN: -mconstructor-aliases -O2 %s -o - | FileCheck --check-prefix=CHECK-RAUW %s
+
+namespace test1 {
+// test that we don't produce an alias when the destructor is weak_odr. The
+// reason to avoid it that another TU might have no explicit template
+// instantiation definition or declaration, causing it to to output only
+// one of the destructors as linkonce_odr, producing a different comdat.
+
+// CHECK-DAG: define weak_odr void @_ZN5test16foobarIvEC2Ev
+// CHECK-DAG: define weak_odr void @_ZN5test16foobarIvEC1Ev
+
+template <typename T> struct foobar {
+ foobar() {}
+};
+
+template struct foobar<void>;
+}
+
+namespace test2 {
+// test that when the destrucor is linkonce_odr we just replace every use of
+// C1 with C2.
+
+// CHECK-DAG: define linkonce_odr void @_ZN5test26foobarIvEC2Ev(
+// CHECK-DAG: call void @_ZN5test26foobarIvEC2Ev
+void g();
+template <typename T> struct foobar {
+ foobar() { g(); }
+};
+foobar<void> x;
+}
+
+namespace test3 {
+// test that instead of an internal alias we just use the other destructor
+// directly.
+
+// CHECK-DAG: define internal void @_ZN5test312_GLOBAL__N_11AD2Ev(
+// CHECK-DAG: call i32 @__cxa_atexit{{.*}}_ZN5test312_GLOBAL__N_11AD2Ev
+namespace {
+struct A {
+ ~A() {}
+};
+
+struct B : public A {};
+}
+
+B x;
+}
+
+namespace test4 {
+ // Test that we don't produce aliases from B to A. We cannot because we cannot
+ // guarantee that they will be present in every TU. Instead, we just call
+ // A's destructor directly.
+
+ // CHECK-DAG: define linkonce_odr void @_ZN5test41AD2Ev(
+ // CHECK-DAG: call i32 @__cxa_atexit{{.*}}_ZN5test41AD2Ev
+
+ // test that we don't do this optimization at -O0 so that the debugger can
+ // see both destructors.
+ // NOOPT-DAG: call i32 @__cxa_atexit{{.*}}@_ZN5test41BD2Ev
+ // NOOOPT-DAG: define linkonce_odr void @_ZN5test41BD2Ev
+ struct A {
+ virtual ~A() {}
+ };
+ struct B : public A{
+ ~B() {}
+ };
+ B X;
+}
+
+namespace test5 {
+ // similar to test4, but with an internal B.
+
+ // CHECK-DAG: define linkonce_odr void @_ZN5test51AD2Ev(
+ // CHECK-DAG: call i32 @__cxa_atexit{{.*}}_ZN5test51AD2Ev
+ struct A {
+ virtual ~A() {}
+ };
+ namespace {
+ struct B : public A{
+ ~B() {}
+ };
+ }
+ B X;
+}
+
+namespace test6 {
+ // Test that we use ~A directly, even when ~A is not defined. The symbol for
+ // ~B would have been internal and still contain a reference to ~A.
+ struct A {
+ virtual ~A();
+ };
+ namespace {
+ struct B : public A {
+ ~B() {}
+ };
+ }
+ B X;
+ // CHECK-DAG: call i32 @__cxa_atexit({{.*}}@_ZN5test61AD2Ev
+}
+
+namespace test7 {
+ // Test that we don't produce an alias from ~B to ~A<int> (or crash figuring
+ // out if we should).
+ // pr17875.
+ // CHECK-DAG: define void @_ZN5test71BD2Ev
+ template <typename> struct A {
+ ~A() {}
+ };
+ class B : A<int> {
+ ~B();
+ };
+ template class A<int>;
+ B::~B() {}
+}
+
+namespace test8 {
+ // Test that we replace ~zed with ~bar which is an alias to ~foo.
+ // CHECK-DAG: call i32 @__cxa_atexit({{.*}}@_ZN5test83barD2Ev
+ // CHECK-DAG: @_ZN5test83barD2Ev = alias {{.*}} @_ZN5test83fooD2Ev
+ struct foo {
+ ~foo();
+ };
+ foo::~foo() {}
+ struct bar : public foo {
+ ~bar();
+ };
+ bar::~bar() {}
+ struct zed : public bar {};
+ zed foo;
+}
+
+// CHECK-RAUW: @_ZTV1C = linkonce_odr unnamed_addr constant [4 x i8*] [{{[^@]*}}@_ZTI1C {{[^@]*}}@_ZN1CD2Ev {{[^@]*}}@_ZN1CD0Ev {{[^@]*}}]
+// r194296 replaced C::~C with B::~B without emitting the later.
+
+class A {
+public:
+ A(int);
+ virtual ~A();
+};
+
+template <class>
+class B : A {
+public:
+ B()
+ : A(0) {
+ }
+ __attribute__((always_inline)) ~B() {
+ }
+};
+
+extern template class B<char>;
+
+class C : B<char> {
+};
+
+void
+fn1() {
+ new C;
+}
diff --git a/test/CodeGenCXX/cxx-block-objects.cpp b/test/CodeGenCXX/cxx-block-objects.cpp
index b989065..ff868fc 100644
--- a/test/CodeGenCXX/cxx-block-objects.cpp
+++ b/test/CodeGenCXX/cxx-block-objects.cpp
@@ -25,9 +25,9 @@ main()
return 0;
}
-// CHECK: define internal void @__copy_helper_block_
+// CHECK-LABEL: define internal void @__copy_helper_block_
// CHECK: call void @_ZN1AC1ERKS_
-// CHECK:define internal void @__destroy_helper_block_
+// CHECK-LABEL:define internal void @__destroy_helper_block_
// CHECK: call void @_ZN1AD1Ev
diff --git a/test/CodeGenCXX/cxx0x-delegating-ctors.cpp b/test/CodeGenCXX/cxx0x-delegating-ctors.cpp
index e909f03..c48e61f 100644
--- a/test/CodeGenCXX/cxx0x-delegating-ctors.cpp
+++ b/test/CodeGenCXX/cxx0x-delegating-ctors.cpp
@@ -87,7 +87,7 @@ namespace PR14588 {
virtual void squawk() { other(); }
};
- // CHECK: define void @_ZN7PR145883FooC1Ev(%"class.PR14588::Foo"*
+ // CHECK-LABEL: define void @_ZN7PR145883FooC1Ev(%"class.PR14588::Foo"*
// CHECK: call void @_ZN7PR145883FooC1EPKv(
// CHECK: invoke void @_ZN7PR145885otherEv()
// CHECK: call void @_ZN7PR145883FooD1Ev
diff --git a/test/CodeGenCXX/cxx0x-initializer-array.cpp b/test/CodeGenCXX/cxx0x-initializer-array.cpp
index 3144e94..49bc86f 100644
--- a/test/CodeGenCXX/cxx0x-initializer-array.cpp
+++ b/test/CodeGenCXX/cxx0x-initializer-array.cpp
@@ -6,7 +6,7 @@ struct A { int a[1]; };
typedef A x[];
int f() {
x{{{1}}};
- // CHECK: define i32 @_Z1fv
+ // CHECK-LABEL: define i32 @_Z1fv
// CHECK: store i32 1
// (It's okay if the output changes here, as long as we don't crash.)
return 0;
@@ -33,7 +33,7 @@ namespace ValueInitArrayOfMemPtr {
S1();
};
- // CHECK: define void @_ZN22ValueInitArrayOfMemPtr1fEi
+ // CHECK-LABEL: define void @_ZN22ValueInitArrayOfMemPtr1fEi
void f(int n) {
Agg1 a = { n };
// CHECK: store i32 -1,
@@ -42,7 +42,7 @@ namespace ValueInitArrayOfMemPtr {
// 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
+ // CHECK-LABEL: define void @_ZN22ValueInitArrayOfMemPtr1gEv
void g() {
// CHECK: store i32 -1,
f(a{});
@@ -54,7 +54,7 @@ namespace array_dtor {
using T = S[3];
void f(const T &);
void f(T *);
- // CHECK: define void @_ZN10array_dtor1gEv(
+ // CHECK-LABEL: define void @_ZN10array_dtor1gEv(
void g() {
// CHECK: %[[ARRAY:.*]] = alloca [3 x
// CHECK: br
@@ -73,7 +73,7 @@ namespace array_dtor {
// CHECK: ret void
}
- // CHECK: define void @_ZN10array_dtor1hEv(
+ // CHECK-LABEL: define void @_ZN10array_dtor1hEv(
void h() {
// CHECK: %[[ARRAY:.*]] = alloca [3 x
// CHECK: br
@@ -91,7 +91,7 @@ namespace array_dtor {
// CHECK: ret void
}
- // CHECK: define void @_ZN10array_dtor1iEv(
+ // CHECK-LABEL: define void @_ZN10array_dtor1iEv(
void i() {
// CHECK: %[[ARRAY:.*]] = alloca [3 x
// CHECK: br
diff --git a/test/CodeGenCXX/cxx0x-initializer-constructors.cpp b/test/CodeGenCXX/cxx0x-initializer-constructors.cpp
index be5b44d..f60536e 100644
--- a/test/CodeGenCXX/cxx0x-initializer-constructors.cpp
+++ b/test/CodeGenCXX/cxx0x-initializer-constructors.cpp
@@ -6,21 +6,21 @@ struct S {
};
void fn1() {
- // CHECK: define void @_Z3fn1v
+ // CHECK-LABEL: define void @_Z3fn1v
S s { 1 };
// CHECK: alloca %struct.S, align 1
// CHECK: call void @_ZN1SC1Ei(%struct.S* %s, i32 1)
}
void fn2() {
- // CHECK: define void @_Z3fn2v
+ // CHECK-LABEL: define void @_Z3fn2v
S s { 1, 2.0, 3.0 };
// CHECK: alloca %struct.S, align 1
// CHECK: call void @_ZN1SC1Eidd(%struct.S* %s, i32 1, double 2.000000e+00, double 3.000000e+00)
}
void fn3() {
- // CHECK: define void @_Z3fn3v
+ // CHECK-LABEL: define void @_Z3fn3v
S sa[] { { 1 }, { 2 }, { 3 } };
// CHECK: alloca [3 x %struct.S], align 1
// CHECK: call void @_ZN1SC1Ei(%struct.S* %{{.+}}, i32 1)
@@ -29,9 +29,25 @@ void fn3() {
}
void fn4() {
- // CHECK: define void @_Z3fn4v
+ // CHECK-LABEL: define void @_Z3fn4v
S sa[] { { 1, 2.0, 3.0 }, { 4, 5.0, 6.0 } };
// CHECK: alloca [2 x %struct.S], align 1
// CHECK: call void @_ZN1SC1Eidd(%struct.S* %{{.+}}, i32 1, double 2.000000e+00, double 3.000000e+00)
// CHECK: call void @_ZN1SC1Eidd(%struct.S* %{{.+}}, i32 4, double 5.000000e+00, double 6.000000e+00)
}
+
+namespace TreeTransformBracedInit {
+ struct S {};
+ struct T { T(const S &); T(const T&); ~T(); };
+ void x(const T &);
+ template<typename> void foo(const S &s) {
+ // Instantiation of this expression used to lose the CXXBindTemporaryExpr
+ // node and thus not destroy the temporary.
+ x({s});
+ }
+ template void foo<void>(const S&);
+ // CHECK: define {{.*}} void @_ZN23TreeTransformBracedInit3fooIvEEvRKNS_1SE(
+ // CHECK: call void @_ZN23TreeTransformBracedInit1TC1ERKNS_1SE(
+ // CHECK-NEXT: call void @_ZN23TreeTransformBracedInit1xERKNS_1TE(
+ // CHECK-NEXT: call void @_ZN23TreeTransformBracedInit1TD1Ev(
+}
diff --git a/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist-pr12086.cpp b/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist-pr12086.cpp
index 14d2f77..091d7b7 100644
--- a/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist-pr12086.cpp
+++ b/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist-pr12086.cpp
@@ -1,18 +1,28 @@
-// RUN: %clang_cc1 -std=c++11 -emit-llvm -o - -verify %s
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++11 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-STATIC-BL
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++11 -emit-llvm -o - %s -Dconstexpr= | FileCheck %s --check-prefix=CHECK-DYNAMIC-BL
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++11 -emit-llvm -o - %s -DUSE_END | FileCheck %s --check-prefix=CHECK-STATIC-BE
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++11 -emit-llvm -o - %s -DUSE_END -Dconstexpr= | FileCheck %s --check-prefix=CHECK-DYNAMIC-BE
namespace std {
typedef decltype(sizeof(int)) size_t;
- // libc++'s implementation
template <class _E>
class initializer_list
{
const _E* __begin_;
+#ifdef USE_END
+ const _E* __end_;
+#else
size_t __size_;
+#endif
- initializer_list(const _E* __b, size_t __s)
+ constexpr initializer_list(const _E* __b, size_t __s)
: __begin_(__b),
+#ifdef USE_END
+ __end_(__b + __s)
+#else
__size_(__s)
+#endif
{}
public:
@@ -24,14 +34,99 @@ namespace std {
typedef const _E* iterator;
typedef const _E* const_iterator;
- initializer_list() : __begin_(nullptr), __size_(0) {}
+#ifdef USE_END
+ constexpr initializer_list() : __begin_(nullptr), __end_(nullptr) {}
+
+ size_t size() const {return __end_ - __begin_;}
+ const _E* begin() const {return __begin_;}
+ const _E* end() const {return __end_;}
+#else
+ constexpr initializer_list() : __begin_(nullptr), __size_(0) {}
size_t size() const {return __size_;}
const _E* begin() const {return __begin_;}
const _E* end() const {return __begin_ + __size_;}
+#endif
};
}
-std::initializer_list<std::initializer_list<int>> pleasefail = {
- {1, 2}, {3, 4}, {5, 6} // expected-error {{cannot compile}}
+constexpr int a = 2, b = 4, c = 6;
+std::initializer_list<std::initializer_list<int>> nested = {
+ {1, a}, {3, b}, {5, c}
};
+
+// CHECK-STATIC-BL: @_ZGR6nested = private constant [2 x i32] [i32 1, i32 2], align 4
+// CHECK-STATIC-BL: @_ZGR6nested1 = private constant [2 x i32] [i32 3, i32 4], align 4
+// CHECK-STATIC-BL: @_ZGR6nested2 = private constant [2 x i32] [i32 5, i32 6], align 4
+// CHECK-STATIC-BL: @_ZGR6nested3 = private constant [3 x {{.*}}] [
+// CHECK-STATIC-BL: {{.*}} { i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested, i32 0, i32 0), i64 2 },
+// CHECK-STATIC-BL: {{.*}} { i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested1, i32 0, i32 0), i64 2 },
+// CHECK-STATIC-BL: {{.*}} { i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested2, i32 0, i32 0), i64 2 }
+// CHECK-STATIC-BL: ], align 8
+// CHECK-STATIC-BL: @nested = global {{.*}} { {{.*}} getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested3, i32 0, i32 0), i64 3 }, align 8
+
+// CHECK-DYNAMIC-BL: @nested = global
+// CHECK-DYNAMIC-BL: @_ZGR6nested = private global [3 x
+// CHECK-DYNAMIC-BL: @_ZGR6nested1 = private global [2 x i32] zeroinitializer
+// CHECK-DYNAMIC-BL: @_ZGR6nested2 = private global [2 x i32] zeroinitializer
+// CHECK-DYNAMIC-BL: @_ZGR6nested3 = private global [2 x i32] zeroinitializer
+// CHECK-DYNAMIC-BL: store i32 1, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested1, i64 0, i64 0)
+// CHECK-DYNAMIC-BL: store i32 {{.*}}, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested1, i64 0, i64 1)
+// CHECK-DYNAMIC-BL: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested1, i64 0, i64 0),
+// CHECK-DYMAMIC-BL: i32** getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 0, i32 0), align 8
+// CHECK-DYNAMIC-BL: store i64 2, i64* getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 0, i32 1), align 8
+// CHECK-DYNAMIC-BL: store i32 3, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested2, i64 0, i64 0)
+// CHECK-DYNAMIC-BL: store i32 {{.*}}, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested2, i64 0, i64 1)
+// CHECK-DYNAMIC-BL: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested2, i64 0, i64 0),
+// CHECK-DYNAMIC-BL: i32** getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 1, i32 0), align 8
+// CHECK-DYNAMIC-BL: store i64 2, i64* getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 1, i32 1), align 8
+// CHECK-DYNAMIC-BL: store i32 5, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested3, i64 0, i64 0)
+// CHECK-DYNAMIC-BL: store i32 {{.*}}, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested3, i64 0, i64 1)
+// CHECK-DYNAMIC-BL: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested3, i64 0, i64 0),
+// CHECK-DYNAMIC-BL: i32** getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 2, i32 0), align 8
+// CHECK-DYNAMIC-BL: store i64 2, i64* getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 2, i32 1), align 8
+// CHECK-DYNAMIC-BL: store {{.*}}* getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 0),
+// CHECK-DYNAMIC-BL: {{.*}}** getelementptr inbounds ({{.*}}* @nested, i32 0, i32 0), align 8
+// CHECK-DYNAMIC-BL: store i64 3, i64* getelementptr inbounds ({{.*}}* @nested, i32 0, i32 1), align 8
+
+// CHECK-STATIC-BE: @_ZGR6nested = private constant [2 x i32] [i32 1, i32 2], align 4
+// CHECK-STATIC-BE: @_ZGR6nested1 = private constant [2 x i32] [i32 3, i32 4], align 4
+// CHECK-STATIC-BE: @_ZGR6nested2 = private constant [2 x i32] [i32 5, i32 6], align 4
+// CHECK-STATIC-BE: @_ZGR6nested3 = private constant [3 x {{.*}}] [
+// CHECK-STATIC-BE: {{.*}} { i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested, i32 0, i32 0),
+// CHECK-STATIC-BE: i32* bitcast (i8* getelementptr (i8* bitcast ([2 x i32]* @_ZGR6nested to i8*), i64 8) to i32*) }
+// CHECK-STATIC-BE: {{.*}} { i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested1, i32 0, i32 0),
+// CHECK-STATIC-BE: i32* bitcast (i8* getelementptr (i8* bitcast ([2 x i32]* @_ZGR6nested1 to i8*), i64 8) to i32*) }
+// CHECK-STATIC-BE: {{.*}} { i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested2, i32 0, i32 0),
+// CHECK-STATIC-BE: i32* bitcast (i8* getelementptr (i8* bitcast ([2 x i32]* @_ZGR6nested2 to i8*), i64 8) to i32*) }
+// CHECK-STATIC-BE: ], align 8
+// CHECK-STATIC-BE: @nested = global {{.*}} { {{.*}} getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested3, i32 0, i32 0),
+// CHECK-STATIC-BE: {{.*}} bitcast ({{.*}}* getelementptr (i8* bitcast ([3 x {{.*}}]* @_ZGR6nested3 to i8*), i64 48) to {{.*}}*) }
+
+// CHECK-DYNAMIC-BE: @nested = global
+// CHECK-DYNAMIC-BE: @_ZGR6nested = private global [3 x
+// CHECK-DYNAMIC-BE: @_ZGR6nested1 = private global [2 x i32] zeroinitializer
+// CHECK-DYNAMIC-BE: @_ZGR6nested2 = private global [2 x i32] zeroinitializer
+// CHECK-DYNAMIC-BE: @_ZGR6nested3 = private global [2 x i32] zeroinitializer
+// CHECK-DYNAMIC-BE: store i32 1, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested1, i64 0, i64 0)
+// CHECK-DYNAMIC-BE: store i32 {{.*}}, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested1, i64 0, i64 1)
+// CHECK-DYNAMIC-BE: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested1, i64 0, i64 0),
+// CHECK-DYMAMIC-BE: i32** getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 0, i32 0), align 8
+// CHECK-DYNAMIC-BE: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested1, i64 1, i64 0),
+// CHECK-DYMAMIC-BE: i32** getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 0, i32 1), align 8
+// CHECK-DYNAMIC-BE: store i32 3, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested2, i64 0, i64 0)
+// CHECK-DYNAMIC-BE: store i32 {{.*}}, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested2, i64 0, i64 1)
+// CHECK-DYNAMIC-BE: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested2, i64 0, i64 0),
+// CHECK-DYNAMIC-BE: i32** getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 1, i32 0), align 8
+// CHECK-DYNAMIC-BE: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested2, i64 1, i64 0),
+// CHECK-DYNAMIC-BE: i32** getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 1, i32 1), align 8
+// CHECK-DYNAMIC-BE: store i32 5, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested3, i64 0, i64 0)
+// CHECK-DYNAMIC-BE: store i32 {{.*}}, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested3, i64 0, i64 1)
+// CHECK-DYNAMIC-BE: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested3, i64 0, i64 0),
+// CHECK-DYNAMIC-BE: i32** getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 2, i32 0), align 8
+// CHECK-DYNAMIC-BE: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested3, i64 1, i64 0),
+// CHECK-DYNAMIC-BE: i32** getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 2, i32 1), align 8
+// CHECK-DYNAMIC-BE: store {{.*}}* getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 0),
+// CHECK-DYNAMIC-BE: {{.*}}** getelementptr inbounds ({{.*}}* @nested, i32 0, i32 0), align 8
+// CHECK-DYNAMIC-BE: store {{.*}}* getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 1, i64 0),
+// CHECK-DYNAMIC-BE: {{.*}}** getelementptr inbounds ({{.*}}* @nested, i32 0, i32 1), align 8
diff --git a/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist-startend.cpp b/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist-startend.cpp
index 209ee65..8e0d161 100644
--- a/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist-startend.cpp
+++ b/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist-startend.cpp
@@ -32,12 +32,12 @@ namespace std {
};
}
-// CHECK: @_ZL25globalInitList1__initlist = internal global [3 x i32] [i32 1, i32 2, i32 3]
-// CHECK: @globalInitList1 = global {{[^ ]+}} { i32* getelementptr inbounds ([3 x i32]* @_ZL25globalInitList1__initlist, {{[^)]*}}), i32*
+// CHECK: @_ZGR15globalInitList1 = private constant [3 x i32] [i32 1, i32 2, i32 3]
+// CHECK: @globalInitList1 = global {{[^ ]+}} { i32* getelementptr inbounds ([3 x i32]* @_ZGR15globalInitList1, {{[^)]*}}), i32*
std::initializer_list<int> globalInitList1 = {1, 2, 3};
void fn1(int i) {
- // CHECK: define void @_Z3fn1i
+ // CHECK-LABEL: define void @_Z3fn1i
// temporary array
// CHECK: [[array:%[^ ]+]] = alloca [3 x i32]
// CHECK: getelementptr inbounds [3 x i32]* [[array]], i{{32|64}} 0
@@ -66,7 +66,7 @@ struct destroyme2 {
void fn2() {
- // CHECK: define void @_Z3fn2v
+ // CHECK-LABEL: define void @_Z3fn2v
void target(std::initializer_list<destroyme1>);
// objects should be destroyed before dm2, after call returns
target({ destroyme1(), destroyme1() });
@@ -76,7 +76,7 @@ void fn2() {
}
void fn3() {
- // CHECK: define void @_Z3fn3v
+ // CHECK-LABEL: define void @_Z3fn3v
// objects should be destroyed after dm2
auto list = { destroyme1(), destroyme1() };
destroyme2 dm2;
diff --git a/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp b/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp
index d683493..164cbce 100644
--- a/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp
+++ b/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp
@@ -47,23 +47,48 @@ struct wantslist1 {
~wantslist1();
};
-// CHECK: @_ZL25globalInitList1__initlist = internal global [3 x i32] [i32 1, i32 2, i32 3]
-// CHECK: @globalInitList1 = global %{{[^ ]+}} { i32* getelementptr inbounds ([3 x i32]* @_ZL25globalInitList1__initlist, i32 0, i32 0), i{{32|64}} 3 }
+// CHECK: @_ZGR15globalInitList1 = private constant [3 x i32] [i32 1, i32 2, i32 3]
+// CHECK: @globalInitList1 = global %{{[^ ]+}} { i32* getelementptr inbounds ([3 x i32]* @_ZGR15globalInitList1, i32 0, i32 0), i{{32|64}} 3 }
std::initializer_list<int> globalInitList1 = {1, 2, 3};
namespace thread_local_global_array {
- // CHECK: @_ZN25thread_local_global_arrayL11x__initlistE = internal thread_local global [4 x i32] [i32 1, i32 2, i32 3, i32 4]
- // CHECK: @_ZN25thread_local_global_array1xE = thread_local global {{.*}} @_ZN25thread_local_global_arrayL11x__initlistE, {{.*}} i64 4
+ // FIXME: We should be able to constant-evaluate this even though the
+ // initializer is not a constant expression (pointers to thread_local
+ // objects aren't really a problem).
+ //
+ // CHECK: @_ZN25thread_local_global_array1xE = thread_local global
+ // CHECK: @_ZGRN25thread_local_global_array1xE = private thread_local constant [4 x i32] [i32 1, i32 2, i32 3, i32 4]
std::initializer_list<int> thread_local x = { 1, 2, 3, 4 };
}
-// CHECK: @_ZL25globalInitList2__initlist = internal global [2 x %{{[^ ]*}}] zeroinitializer
-// CHECK: @globalInitList2 = global %{{[^ ]+}} { %[[WITHARG:[^ *]+]]* getelementptr inbounds ([2 x
+// CHECK: @globalInitList2 = global %{{[^ ]+}} zeroinitializer
+// CHECK: @_ZGR15globalInitList2 = private global [2 x %[[WITHARG:[^ ]*]]] zeroinitializer
+
+// CHECK: @_ZN15partly_constant1kE = global i32 0, align 4
+// CHECK: @_ZN15partly_constant2ilE = global {{.*}} null, align 8
+// CHECK: @[[PARTLY_CONSTANT_OUTER:_ZGRN15partly_constant2ilE.*]] = private global {{.*}} zeroinitializer, align 8
+// CHECK: @[[PARTLY_CONSTANT_INNER:_ZGRN15partly_constant2ilE.*]] = private global [3 x {{.*}}] zeroinitializer, align 8
+// CHECK: @[[PARTLY_CONSTANT_FIRST:_ZGRN15partly_constant2ilE.*]] = private constant [3 x i32] [i32 1, i32 2, i32 3], align 4
+// CHECK: @[[PARTLY_CONSTANT_SECOND:_ZGRN15partly_constant2ilE.*]] = private global [2 x i32] zeroinitializer, align 4
+// CHECK: @[[PARTLY_CONSTANT_THIRD:_ZGRN15partly_constant2ilE.*]] = private constant [4 x i32] [i32 5, i32 6, i32 7, i32 8], align 4
+
// CHECK: appending global
-// CHECK: define internal void
-// CHECK: call void @_ZN8witharg1C1ERK10destroyme1(%[[WITHARG]]* getelementptr inbounds ([2 x %[[WITHARG]]]* @_ZL25globalInitList2__initlist, i{{32|64}} 0, i{{32|64}} 0
-// CHECK: call void @_ZN8witharg1C1ERK10destroyme1(%[[WITHARG]]* getelementptr inbounds ([2 x %[[WITHARG]]]* @_ZL25globalInitList2__initlist, i{{32|64}} 0, i{{32|64}} 1
+
+
+// thread_local initializer:
+// CHECK-LABEL: define internal void
+// CHECK: store i32* getelementptr inbounds ([4 x i32]* @_ZGRN25thread_local_global_array1xE, i64 0, i64 0),
+// CHECK: i32** getelementptr inbounds ({{.*}}* @_ZN25thread_local_global_array1xE, i32 0, i32 0), align 8
+// CHECK: store i64 4, i64* getelementptr inbounds ({{.*}}* @_ZN25thread_local_global_array1xE, i32 0, i32 1), align 8
+
+
+// CHECK-LABEL: define internal void
+// CHECK: call void @_ZN8witharg1C1ERK10destroyme1(%[[WITHARG]]* getelementptr inbounds ([2 x %[[WITHARG]]]* @_ZGR15globalInitList2, i{{32|64}} 0, i{{32|64}} 0
+// CHECK: call void @_ZN8witharg1C1ERK10destroyme1(%[[WITHARG]]* getelementptr inbounds ([2 x %[[WITHARG]]]* @_ZGR15globalInitList2, i{{32|64}} 0, i{{32|64}} 1
// CHECK: __cxa_atexit
+// CHECK: store %[[WITHARG]]* getelementptr inbounds ([2 x %[[WITHARG]]]* @_ZGR15globalInitList2, i64 0, i64 0),
+// CHECK: %[[WITHARG]]** getelementptr inbounds (%{{.*}}* @globalInitList2, i32 0, i32 0), align 8
+// CHECK: store i64 2, i64* getelementptr inbounds (%{{.*}}* @globalInitList2, i32 0, i32 1), align 8
// CHECK: call void @_ZN10destroyme1D1Ev
// CHECK: call void @_ZN10destroyme1D1Ev
std::initializer_list<witharg1> globalInitList2 = {
@@ -71,7 +96,7 @@ std::initializer_list<witharg1> globalInitList2 = {
};
void fn1(int i) {
- // CHECK: define void @_Z3fn1i
+ // CHECK-LABEL: define void @_Z3fn1i
// temporary array
// CHECK: [[array:%[^ ]+]] = alloca [3 x i32]
// CHECK: getelementptr inbounds [3 x i32]* [[array]], i{{32|64}} 0
@@ -91,7 +116,7 @@ void fn1(int i) {
}
void fn2() {
- // CHECK: define void @_Z3fn2v
+ // CHECK-LABEL: define void @_Z3fn2v
void target(std::initializer_list<destroyme1>);
// objects should be destroyed before dm2, after call returns
// CHECK: call void @_Z6targetSt16initializer_listI10destroyme1E
@@ -102,7 +127,7 @@ void fn2() {
}
void fn3() {
- // CHECK: define void @_Z3fn3v
+ // CHECK-LABEL: define void @_Z3fn3v
// objects should be destroyed after dm2
auto list = { destroyme1(), destroyme1() };
destroyme2 dm2;
@@ -111,7 +136,7 @@ void fn3() {
}
void fn4() {
- // CHECK: define void @_Z3fn4v
+ // CHECK-LABEL: define void @_Z3fn4v
void target(std::initializer_list<witharg1>);
// objects should be destroyed before dm2, after call returns
// CHECK: call void @_ZN8witharg1C1ERK10destroyme1
@@ -124,7 +149,7 @@ void fn4() {
}
void fn5() {
- // CHECK: define void @_Z3fn5v
+ // CHECK-LABEL: define void @_Z3fn5v
// temps should be destroyed before dm2
// objects should be destroyed after dm2
// CHECK: call void @_ZN8witharg1C1ERK10destroyme1
@@ -136,7 +161,7 @@ void fn5() {
}
void fn6() {
- // CHECK: define void @_Z3fn6v
+ // CHECK-LABEL: define void @_Z3fn6v
void target(const wantslist1&);
// objects should be destroyed before dm2, after call returns
// CHECK: call void @_ZN10wantslist1C1ESt16initializer_listI10destroyme1E
@@ -149,7 +174,7 @@ void fn6() {
}
void fn7() {
- // CHECK: define void @_Z3fn7v
+ // CHECK-LABEL: define void @_Z3fn7v
// temps should be destroyed before dm2
// object should be destroyed after dm2
// CHECK: call void @_ZN10wantslist1C1ESt16initializer_listI10destroyme1E
@@ -161,7 +186,7 @@ void fn7() {
}
void fn8() {
- // CHECK: define void @_Z3fn8v
+ // CHECK-LABEL: define void @_Z3fn8v
void target(std::initializer_list<std::initializer_list<destroyme1>>);
// objects should be destroyed before dm2, after call returns
// CHECK: call void @_Z6targetSt16initializer_listIS_I10destroyme1EE
@@ -175,7 +200,7 @@ void fn8() {
}
void fn9() {
- // CHECK: define void @_Z3fn9v
+ // CHECK-LABEL: define void @_Z3fn9v
// objects should be destroyed after dm2
std::initializer_list<destroyme1> inner;
std::initializer_list<std::initializer_list<destroyme1>> list =
@@ -193,7 +218,7 @@ struct haslist1 {
haslist1();
};
-// CHECK: define void @_ZN8haslist1C2Ev
+// CHECK-LABEL: define void @_ZN8haslist1C2Ev
haslist1::haslist1()
// CHECK: alloca [3 x i32]
// CHECK: store i32 1
@@ -210,7 +235,7 @@ struct haslist2 {
haslist2();
};
-// CHECK: define void @_ZN8haslist2C2Ev
+// CHECK-LABEL: define void @_ZN8haslist2C2Ev
haslist2::haslist2()
: il{destroyme1(), destroyme1()}
{
@@ -220,7 +245,7 @@ haslist2::haslist2()
}
void fn10() {
- // CHECK: define void @_Z4fn10v
+ // CHECK-LABEL: define void @_Z4fn10v
// CHECK: alloca [3 x i32]
// CHECK: call noalias i8* @_Znw{{[jm]}}
// CHECK: store i32 1
@@ -232,7 +257,7 @@ void fn10() {
}
void fn11() {
- // CHECK: define void @_Z4fn11v
+ // CHECK-LABEL: define void @_Z4fn11v
(void) new std::initializer_list<destroyme1> {destroyme1(), destroyme1()};
// CHECK: call void @_ZN10destroyme1D1Ev
destroyme2 dm2;
@@ -260,7 +285,7 @@ namespace PR12178 {
namespace rdar13325066 {
struct X { ~X(); };
- // CHECK: define void @_ZN12rdar133250664loopERNS_1XES1_
+ // CHECK-LABEL: define void @_ZN12rdar133250664loopERNS_1XES1_
void loop(X &x1, X &x2) {
// CHECK: br label
// CHECK: br i1
@@ -275,3 +300,134 @@ namespace rdar13325066 {
for (X x : { x1, x2 }) { }
}
}
+
+namespace dtors {
+ struct S {
+ S();
+ ~S();
+ };
+ void z();
+
+ // CHECK-LABEL: define void @_ZN5dtors1fEv(
+ void f() {
+ // CHECK: call void @_ZN5dtors1SC1Ev(
+ // CHECK: call void @_ZN5dtors1SC1Ev(
+ std::initializer_list<S>{ S(), S() };
+
+ // Destruction loop for underlying array.
+ // CHECK: br label
+ // CHECK: call void @_ZN5dtors1SD1Ev(
+ // CHECK: br i1
+
+ // CHECK: call void @_ZN5dtors1zEv(
+ z();
+
+ // CHECK-NOT: call void @_ZN5dtors1SD1Ev(
+ }
+
+ // CHECK-LABEL: define void @_ZN5dtors1gEv(
+ void g() {
+ // CHECK: call void @_ZN5dtors1SC1Ev(
+ // CHECK: call void @_ZN5dtors1SC1Ev(
+ auto x = std::initializer_list<S>{ S(), S() };
+
+ // Destruction loop for underlying array.
+ // CHECK: br label
+ // CHECK: call void @_ZN5dtors1SD1Ev(
+ // CHECK: br i1
+
+ // CHECK: call void @_ZN5dtors1zEv(
+ z();
+
+ // CHECK-NOT: call void @_ZN5dtors1SD1Ev(
+ }
+
+ // CHECK-LABEL: define void @_ZN5dtors1hEv(
+ void h() {
+ // CHECK: call void @_ZN5dtors1SC1Ev(
+ // CHECK: call void @_ZN5dtors1SC1Ev(
+ std::initializer_list<S> x = { S(), S() };
+
+ // CHECK-NOT: call void @_ZN5dtors1SD1Ev(
+
+ // CHECK: call void @_ZN5dtors1zEv(
+ z();
+
+ // Destruction loop for underlying array.
+ // CHECK: br label
+ // CHECK: call void @_ZN5dtors1SD1Ev(
+ // CHECK: br i1
+ }
+}
+
+namespace partly_constant {
+ int k;
+ std::initializer_list<std::initializer_list<int>> &&il = { { 1, 2, 3 }, { 4, k }, { 5, 6, 7, 8 } };
+ // First init list.
+ // CHECK-NOT: @[[PARTLY_CONSTANT_FIRST]],
+ // CHECK: store i32* getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_FIRST]], i64 0, i64 0),
+ // CHECK: i32** getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_INNER]], i64 0, i64 0, i32 0)
+ // CHECK: store i64 3, i64* getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_INNER]], i64 0, i64 0, i32 1)
+ // CHECK-NOT: @[[PARTLY_CONSTANT_FIRST]],
+ //
+ // Second init list array (non-constant).
+ // CHECK: store i32 4, i32* getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_SECOND]], i64 0, i64 0)
+ // CHECK: load i32* @_ZN15partly_constant1kE
+ // CHECK: store i32 {{.*}}, i32* getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_SECOND]], i64 0, i64 1)
+ //
+ // Second init list.
+ // CHECK: store i32* getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_SECOND]], i64 0, i64 0),
+ // CHECK: i32** getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_INNER]], i64 0, i64 1, i32 0)
+ // CHECK: store i64 2, i64* getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_INNER]], i64 0, i64 1, i32 1)
+ //
+ // Third init list.
+ // CHECK-NOT: @[[PARTLY_CONSTANT_THIRD]],
+ // CHECK: store i32* getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_THIRD]], i64 0, i64 0),
+ // CHECK: i32** getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_INNER]], i64 0, i64 2, i32 0)
+ // CHECK: store i64 4, i64* getelementptr inbounds ({{.*}}* @_ZGRN15partly_constant2ilE4, i64 0, i64 2, i32 1)
+ // CHECK-NOT: @[[PARTLY_CONSTANT_THIRD]],
+ //
+ // Outer init list.
+ // CHECK: store {{.*}}* getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_INNER]], i64 0, i64 0),
+ // CHECK: {{.*}}** getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_OUTER]], i32 0, i32 0)
+ // CHECK: store i64 3, i64* getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_OUTER]], i32 0, i32 1)
+ //
+ // 'il' reference.
+ // CHECK: store {{.*}}* @[[PARTLY_CONSTANT_OUTER]], {{.*}}** @_ZN15partly_constant2ilE, align 8
+}
+
+namespace nested {
+ struct A { A(); ~A(); };
+ struct B { const A &a; ~B(); };
+ struct C { std::initializer_list<B> b; ~C(); };
+ void f();
+ // CHECK-LABEL: define void @_ZN6nested1gEv(
+ void g() {
+ // CHECK: call void @_ZN6nested1AC1Ev(
+ // CHECK-NOT: call
+ // CHECK: call void @_ZN6nested1AC1Ev(
+ // CHECK-NOT: call
+ const C &c { { { A() }, { A() } } };
+
+ // CHECK: call void @_ZN6nested1fEv(
+ // CHECK-NOT: call
+ f();
+
+ // CHECK: call void @_ZN6nested1CD1Ev(
+ // CHECK-NOT: call
+
+ // Destroy B[2] array.
+ // FIXME: This isn't technically correct: reverse construction order would
+ // destroy the second B then the second A then the first B then the first A.
+ // CHECK: call void @_ZN6nested1BD1Ev(
+ // CHECK-NOT: call
+ // CHECK: br
+
+ // CHECK-NOT: call
+ // CHECK: call void @_ZN6nested1AD1Ev(
+ // CHECK-NOT: call
+ // CHECK: call void @_ZN6nested1AD1Ev(
+ // CHECK-NOT: call
+ // CHECK: }
+ }
+}
diff --git a/test/CodeGenCXX/cxx11-exception-spec.cpp b/test/CodeGenCXX/cxx11-exception-spec.cpp
index 49ca861..96ea1d7 100644
--- a/test/CodeGenCXX/cxx11-exception-spec.cpp
+++ b/test/CodeGenCXX/cxx11-exception-spec.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -verify -fexceptions -fcxx-exceptions -triple x86_64-linux-gnu | FileCheck %s
+// RUN: not %clang_cc1 -std=c++11 -emit-llvm %s -o - -verify -fexceptions -fcxx-exceptions -triple x86_64-linux-gnu | FileCheck %s
void h();
diff --git a/test/CodeGenCXX/cxx11-initializer-array-new.cpp b/test/CodeGenCXX/cxx11-initializer-array-new.cpp
new file mode 100644
index 0000000..23577be
--- /dev/null
+++ b/test/CodeGenCXX/cxx11-initializer-array-new.cpp
@@ -0,0 +1,106 @@
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++11 %s -emit-llvm -o - | FileCheck %s
+
+// PR10878
+
+struct S { S(); S(int); ~S(); int n; };
+
+void *p = new S[2][3]{ { 1, 2, 3 }, { 4, 5, 6 } };
+
+// CHECK-LABEL: define
+// CHECK: %[[ALLOC:.*]] = call noalias i8* @_Znam(i64 32)
+// CHECK: %[[COOKIE:.*]] = bitcast i8* %[[ALLOC]] to i64*
+// CHECK: store i64 6, i64* %[[COOKIE]]
+// CHECK: %[[START_AS_i8:.*]] = getelementptr inbounds i8* %[[ALLOC]], i64 8
+// CHECK: %[[START_AS_S:.*]] = bitcast i8* %[[START_AS_i8]] to %[[S:.*]]*
+//
+// Explicit initializers:
+//
+// { 1, 2, 3 }
+//
+// CHECK: %[[S_0:.*]] = bitcast %[[S]]* %[[START_AS_S]] to [3 x %[[S]]]*
+//
+// CHECK: %[[S_0_0:.*]] = getelementptr inbounds [3 x %[[S]]]* %[[S_0]], i64 0, i64 0
+// CHECK: call void @_ZN1SC1Ei(%[[S]]* %[[S_0_0]], i32 1)
+// CHECK: %[[S_0_1:.*]] = getelementptr inbounds %[[S]]* %[[S_0_0]], i64 1
+// CHECK: call void @_ZN1SC1Ei(%[[S]]* %[[S_0_1]], i32 2)
+// CHECK: %[[S_0_2:.*]] = getelementptr inbounds %[[S]]* %[[S_0_1]], i64 1
+// CHECK: call void @_ZN1SC1Ei(%[[S]]* %[[S_0_2]], i32 3)
+//
+// { 4, 5, 6 }
+//
+// CHECK: %[[S_1:.*]] = getelementptr [3 x %[[S]]]* %[[S_0]], i32 1
+//
+// CHECK: %[[S_1_0:.*]] = getelementptr inbounds [3 x %[[S]]]* %[[S_1]], i64 0, i64 0
+// CHECK: call void @_ZN1SC1Ei(%[[S]]* %[[S_1_0]], i32 4)
+// CHECK: %[[S_1_1:.*]] = getelementptr inbounds %[[S]]* %[[S_1_0]], i64 1
+// CHECK: call void @_ZN1SC1Ei(%[[S]]* %[[S_1_1]], i32 5)
+// CHECK: %[[S_1_2:.*]] = getelementptr inbounds %[[S]]* %[[S_1_1]], i64 1
+// CHECK: call void @_ZN1SC1Ei(%[[S]]* %[[S_1_2]], i32 6)
+//
+// CHECK-NOT: br i1
+// CHECK-NOT: call
+// CHECK: }
+
+int n;
+void *q = new S[n][3]{ { 1, 2, 3 }, { 4, 5, 6 } };
+
+// CHECK-LABEL: define
+//
+// CHECK: load i32* @n
+// CHECK: call {{.*}} @llvm.umul.with.overflow.i64(i64 %[[N:.*]], i64 12)
+// CHECK: %[[ELTS:.*]] = mul i64 %[[N]], 3
+// CHECK: call {{.*}} @llvm.uadd.with.overflow.i64(i64 %{{.*}}, i64 8)
+// CHECK: %[[ALLOC:.*]] = call noalias i8* @_Znam(i64 %{{.*}})
+//
+// CHECK: %[[COOKIE:.*]] = bitcast i8* %[[ALLOC]] to i64*
+// CHECK: store i64 %[[ELTS]], i64* %[[COOKIE]]
+// CHECK: %[[START_AS_i8:.*]] = getelementptr inbounds i8* %[[ALLOC]], i64 8
+// CHECK: %[[START_AS_S:.*]] = bitcast i8* %[[START_AS_i8]] to %[[S]]*
+// CHECK: %[[END_AS_S:.*]] = getelementptr inbounds %[[S]]* %[[START_AS_S]], i64 %[[ELTS]]
+//
+// Explicit initializers:
+//
+// { 1, 2, 3 }
+//
+// CHECK: %[[S_0:.*]] = bitcast %[[S]]* %[[START_AS_S]] to [3 x %[[S]]]*
+//
+// CHECK: %[[S_0_0:.*]] = getelementptr inbounds [3 x %[[S]]]* %[[S_0]], i64 0, i64 0
+// CHECK: call void @_ZN1SC1Ei(%[[S]]* %[[S_0_0]], i32 1)
+// CHECK: %[[S_0_1:.*]] = getelementptr inbounds %[[S]]* %[[S_0_0]], i64 1
+// CHECK: call void @_ZN1SC1Ei(%[[S]]* %[[S_0_1]], i32 2)
+// CHECK: %[[S_0_2:.*]] = getelementptr inbounds %[[S]]* %[[S_0_1]], i64 1
+// CHECK: call void @_ZN1SC1Ei(%[[S]]* %[[S_0_2]], i32 3)
+//
+// { 4, 5, 6 }
+//
+// CHECK: %[[S_1:.*]] = getelementptr [3 x %[[S]]]* %[[S_0]], i32 1
+//
+// CHECK: %[[S_1_0:.*]] = getelementptr inbounds [3 x %[[S]]]* %[[S_1]], i64 0, i64 0
+// CHECK: call void @_ZN1SC1Ei(%[[S]]* %[[S_1_0]], i32 4)
+// CHECK: %[[S_1_1:.*]] = getelementptr inbounds %[[S]]* %[[S_1_0]], i64 1
+// CHECK: call void @_ZN1SC1Ei(%[[S]]* %[[S_1_1]], i32 5)
+// CHECK: %[[S_1_2:.*]] = getelementptr inbounds %[[S]]* %[[S_1_1]], i64 1
+// CHECK: call void @_ZN1SC1Ei(%[[S]]* %[[S_1_2]], i32 6)
+//
+// CHECK: %[[S_2:.*]] = getelementptr [3 x %[[S]]]* %[[S_1]], i32 1
+// CHECK: %[[S_2_AS_S:.*]] = bitcast [3 x %[[S]]]* %[[S_2]] to %[[S]]*
+// CHECK: icmp eq %[[S]]* %[[S_2_AS_S]], %[[END_AS_S]]
+// CHECK: br i1
+//
+// S[n-2][3] initialization loop:
+//
+// CHECK: %[[END_INNER:.*]] = getelementptr inbounds %[[S]]* %{{.*}}, i64 3
+// CHECK: br label
+//
+// S[3] initialization loop:
+//
+// CHECK: call void @_ZN1SC1Ev(%[[S]]*
+// CHECK: %[[NEXT_INNER:.*]] = getelementptr inbounds %[[S]]* %{{.*}}, i64 1
+// CHECK: icmp eq %[[S]]* %[[NEXT_INNER]], %[[END_INNER]]
+// CHECK: br i1
+//
+// CHECK: %[[NEXT_OUTER:.*]] = getelementptr %[[S]]* %{{.*}}, i32 1
+// CHECK: icmp eq %[[S]]* %[[NEXT_OUTER]], %[[END_AS_S]]
+// CHECK: br i1
+//
+// CHECK: }
diff --git a/test/CodeGenCXX/cxx11-thread-local-reference.cpp b/test/CodeGenCXX/cxx11-thread-local-reference.cpp
index 2ea9acd..7759d41 100644
--- a/test/CodeGenCXX/cxx11-thread-local-reference.cpp
+++ b/test/CodeGenCXX/cxx11-thread-local-reference.cpp
@@ -13,7 +13,7 @@ int &g() { return r; }
// CHECK: call i32* @_Z1fv()
// CHECK: store i32* %{{.*}}, i32** @r, align 8
-// CHECK: define i32* @_Z1gv()
+// CHECK-LABEL: define i32* @_Z1gv()
// CHECK: call i32* @_ZTW1r()
// CHECK: ret i32* %{{.*}}
@@ -22,5 +22,5 @@ int &g() { return r; }
// CHECK: load i32** @r, align 8
// CHECK: ret i32* %{{.*}}
-// CHECK: define internal void @__tls_init()
+// CHECK-LABEL: define internal void @__tls_init()
// CHECK: call void @[[R_INIT]]()
diff --git a/test/CodeGenCXX/cxx11-thread-local.cpp b/test/CodeGenCXX/cxx11-thread-local.cpp
index a7141d1..509562d 100644
--- a/test/CodeGenCXX/cxx11-thread-local.cpp
+++ b/test/CodeGenCXX/cxx11-thread-local.cpp
@@ -35,7 +35,7 @@ int e = V<int>::m;
// CHECK: @_ZZ8tls_dtorvE1u = internal thread_local global
// CHECK: @_ZGVZ8tls_dtorvE1u = internal thread_local global i8 0
-// CHECK: @_ZGRZ8tls_dtorvE1u = internal thread_local global
+// CHECK: @_ZGRZ8tls_dtorvE1u = private thread_local global
// CHECK: @_ZGVN1VIiE1mE = weak_odr thread_local global i64 0
@@ -55,7 +55,7 @@ int e = V<int>::m;
// CHECK: call i32 @_Z1fv()
// CHECK-NEXT: store i32 {{.*}}, i32* @a, align 4
-// CHECK: define i32 @_Z1fv()
+// CHECK-LABEL: define i32 @_Z1fv()
int f() {
// CHECK: %[[GUARD:.*]] = load i8* @_ZGVZ1fvE1n, align 1
// CHECK: %[[NEED_INIT:.*]] = icmp eq i8 %[[GUARD]], 0
@@ -76,7 +76,7 @@ int f() {
// CHECK-NEXT: load i32* %{{.*}}, align 4
// CHECK-NEXT: store i32 %{{.*}}, i32* @c, align 4
-// CHECK: define weak_odr hidden i32* @_ZTW1b()
+// CHECK-LABEL: define weak_odr hidden i32* @_ZTW1b()
// CHECK: br i1 icmp ne (void ()* @_ZTH1b, void ()* null),
// not null:
// CHECK: call void @_ZTH1b()
@@ -97,7 +97,7 @@ int f() {
// CHECK-NEXT: load i32* %{{.*}}, align 4
// CHECK-NEXT: store i32 %{{.*}}, i32* @e, align 4
-// CHECK: define weak_odr hidden i32* @_ZTWN1VIiE1mE()
+// CHECK-LABEL: define weak_odr hidden i32* @_ZTWN1VIiE1mE()
// CHECK: call void @_ZTHN1VIiE1mE()
// CHECK: ret i32* @_ZN1VIiE1mE
@@ -105,7 +105,7 @@ int f() {
struct S { S(); ~S(); };
struct T { ~T(); };
-// CHECK: define void @_Z8tls_dtorv()
+// CHECK-LABEL: define void @_Z8tls_dtorv()
void tls_dtor() {
// CHECK: load i8* @_ZGVZ8tls_dtorvE1s
// CHECK: call void @_ZN1SC1Ev(%struct.S* @_ZZ8tls_dtorvE1s)
@@ -128,6 +128,13 @@ void tls_dtor() {
// CHECK: declare i32 @__cxa_thread_atexit(void (i8*)*, i8*, i8*)
+// CHECK: define {{.*}} @_Z7PR15991v(
+int PR15991() {
+ thread_local int n;
+ auto l = [] { return n; };
+ return l();
+}
+
// CHECK: define {{.*}} @[[V_M_INIT:.*]]()
// CHECK: load i8* bitcast (i64* @_ZGVN1VIiE1mE to i8*)
// CHECK: %[[V_M_INITIALIZED:.*]] = icmp eq i8 %{{.*}}, 0
@@ -164,10 +171,10 @@ void tls_dtor() {
// CHECK: declare extern_weak void @_ZTH1b()
-// CHECK: define internal hidden i32* @_ZTWL1d()
+// CHECK-LABEL: define internal hidden i32* @_ZTWL1d()
// CHECK: call void @_ZTHL1d()
// CHECK: ret i32* @_ZL1d
-// CHECK: define weak_odr hidden i32* @_ZTWN1U1mE()
+// CHECK-LABEL: define weak_odr hidden i32* @_ZTWN1U1mE()
// CHECK: call void @_ZTHN1U1mE()
// CHECK: ret i32* @_ZN1U1mE
diff --git a/test/CodeGenCXX/cxx1y-deduced-return-type.cpp b/test/CodeGenCXX/cxx1y-deduced-return-type.cpp
new file mode 100644
index 0000000..6d15a22
--- /dev/null
+++ b/test/CodeGenCXX/cxx1y-deduced-return-type.cpp
@@ -0,0 +1,32 @@
+// RUN: %clang_cc1 -std=c++1y -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s
+
+// CHECK: @x = global {{.*}} zeroinitializer
+
+// CHECK: define {{.*}} @_Z1fv
+inline auto f() {
+ int n = 0;
+ // CHECK: load i32
+ // CHECK: store i32
+ // CHECK: ret
+ return [=] () mutable { return ++n; };
+}
+
+auto x = f();
+
+template<typename T> auto *g(T t) { return t; }
+template<typename T> decltype(auto) h(T t) { return t; }
+
+// CHECK: define {{.*}} @_Z1zv
+void z() {
+ // CHECK: call {{.*}} @_Z1gIPZ1fvEUlvE_EPDaT_(
+ // CHECK: call {{.*}} @_Z1hIPZ1fvEUlvE_EDcT_(
+ g(&x);
+ h(&x);
+}
+
+auto i() { return [] {}; }
+// CHECK: define {{.*}} @_Z1jv
+auto j() {
+ // CHECK: call {{.*}} @"_Z1hIZ1ivE3$_0EDcT_"()
+ h(i());
+}
diff --git a/test/CodeGenCXX/cxx1y-init-captures.cpp b/test/CodeGenCXX/cxx1y-init-captures.cpp
new file mode 100644
index 0000000..a60269f
--- /dev/null
+++ b/test/CodeGenCXX/cxx1y-init-captures.cpp
@@ -0,0 +1,102 @@
+// RUN: %clang_cc1 -std=c++1y -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s
+
+struct S {
+ S();
+ S(S &&);
+ ~S();
+};
+
+void f() {
+ (void) [s(S{})] {};
+}
+
+// CHECK-LABEL: define void @_Z1fv(
+// CHECK: call void @_ZN1SC1Ev(
+// CHECK: call void @"_ZZ1fvEN3$_0D1Ev"(
+
+// CHECK-LABEL: define internal void @"_ZZ1fvEN3$_0D1Ev"(
+// CHECK: @"_ZZ1fvEN3$_0D2Ev"(
+
+// D2 at end of file.
+
+void g() {
+ [a(1), b(2)] { return a + b; } ();
+}
+
+// CHECK-LABEL: define void @_Z1gv(
+// CHECK: getelementptr inbounds {{.*}}, i32 0, i32 0
+// CHECK: store i32 1, i32*
+// CHECK: getelementptr inbounds {{.*}}, i32 0, i32 1
+// CHECK: store i32 2, i32*
+// CHECK: call i32 @"_ZZ1gvENK3$_1clEv"(
+
+// CHECK-LABEL: define internal i32 @"_ZZ1gvENK3$_1clEv"(
+// CHECK: getelementptr inbounds {{.*}}, i32 0, i32 0
+// CHECK: load i32*
+// CHECK: getelementptr inbounds {{.*}}, i32 0, i32 1
+// CHECK: load i32*
+// CHECK: add nsw i32
+
+int h(int a) {
+ // CHECK-LABEL: define i32 @_Z1hi(
+ // CHECK: %[[A_ADDR:.*]] = alloca i32,
+ // CHECK: %[[OUTER:.*]] = alloca
+ // CHECK: store i32 {{.*}}, i32* %[[A_ADDR]],
+ //
+ // Initialize init-capture 'b(a)' by reference.
+ // CHECK: getelementptr inbounds {{.*}}* %[[OUTER]], i32 0, i32 0
+ // CHECK: store i32* %[[A_ADDR]], i32** {{.*}},
+ //
+ // Initialize init-capture 'c(a)' by copy.
+ // CHECK: getelementptr inbounds {{.*}}* %[[OUTER]], i32 0, i32 1
+ // CHECK: load i32* %[[A_ADDR]],
+ // CHECK: store i32
+ //
+ // CHECK: call i32 @"_ZZ1hiENK3$_2clEv"({{.*}}* %[[OUTER]])
+ return [&b(a), c(a)] {
+ // CHECK-LABEL: define internal i32 @"_ZZ1hiENK3$_2clEv"(
+ // CHECK: %[[OUTER_ADDR:.*]] = alloca
+ // CHECK: %[[INNER:.*]] = alloca
+ // CHECK: store {{.*}}, {{.*}}** %[[OUTER_ADDR]],
+ //
+ // Capture outer 'c' by reference.
+ // CHECK: %[[OUTER:.*]] = load {{.*}}** %[[OUTER_ADDR]]
+ // CHECK: getelementptr inbounds {{.*}}* %[[INNER]], i32 0, i32 0
+ // CHECK-NEXT: getelementptr inbounds {{.*}}* %[[OUTER]], i32 0, i32 1
+ // CHECK-NEXT: store i32* %
+ //
+ // Capture outer 'b' by copy.
+ // CHECK: getelementptr inbounds {{.*}}* %[[INNER]], i32 0, i32 1
+ // CHECK-NEXT: getelementptr inbounds {{.*}}* %[[OUTER]], i32 0, i32 0
+ // CHECK-NEXT: load i32** %
+ // CHECK-NEXT: load i32* %
+ // CHECK-NEXT: store i32
+ //
+ // CHECK: call i32 @"_ZZZ1hiENK3$_2clEvENKUlvE_clEv"({{.*}}* %[[INNER]])
+ return [=, &c] {
+ // CHECK-LABEL: define internal i32 @"_ZZZ1hiENK3$_2clEvENKUlvE_clEv"(
+ // CHECK: %[[INNER_ADDR:.*]] = alloca
+ // CHECK: store {{.*}}, {{.*}}** %[[INNER_ADDR]],
+ // CHECK: %[[INNER:.*]] = load {{.*}}** %[[INNER_ADDR]]
+ //
+ // Load capture of 'b'
+ // CHECK: getelementptr inbounds {{.*}}* %[[INNER]], i32 0, i32 1
+ // CHECK: load i32* %
+ //
+ // Load capture of 'c'
+ // CHECK: getelementptr inbounds {{.*}}* %[[INNER]], i32 0, i32 0
+ // CHECK: load i32** %
+ // CHECK: load i32* %
+ //
+ // CHECK: add nsw i32
+ return b + c;
+ } ();
+ } ();
+}
+
+// Ensure we can emit code for init-captures in global lambdas too.
+auto global_lambda = [a = 0] () mutable { return ++a; };
+int get_incremented() { return global_lambda(); }
+
+// CHECK-LABEL: define internal void @"_ZZ1fvEN3$_0D2Ev"(
+// CHECK: call void @_ZN1SD1Ev(
diff --git a/test/CodeGenCXX/cxx1y-initializer-aggregate.cpp b/test/CodeGenCXX/cxx1y-initializer-aggregate.cpp
index ef78c43..ae49a04 100644
--- a/test/CodeGenCXX/cxx1y-initializer-aggregate.cpp
+++ b/test/CodeGenCXX/cxx1y-initializer-aggregate.cpp
@@ -25,7 +25,11 @@ A b { 4, "bazquux", .x = 42, .c = 9 };
A c { 1, 0, 'A', f(), { 3 } };
// CHECK: @[[STR_A:.*]] = {{.*}} [7 x i8] c"foobar\00"
+// CHECK: @a = global {{.*}} zeroinitializer
+
+// @b has a constant initializer
// CHECK: @[[STR_B:.*]] = {{.*}} [8 x i8] c"bazquux\00"
+// CHECK: @b = global {{.*}} i32 4, {{.*}} @[[STR_B]], {{.*}} i8 117, i32 42, {{.*}} i8 9
B x;
B y {};
@@ -44,18 +48,9 @@ B z { 1 };
// CHECK: store i32 %{{.*}}, i32* getelementptr inbounds ({{.*}}* @a, i32 0, i32 3)
// CHECK: call void @{{.*}}C1Ev({{.*}} getelementptr inbounds (%struct.A* @a, i32 0, i32 4))
-// Initialization of 'b':
+// No dynamic initialization of 'b':
-// CHECK: store i32 4, i32* getelementptr inbounds ({{.*}} @b, i32 0, i32 0)
-// CHECK: store i8* {{.*}} @[[STR_B]]{{.*}}, i8** getelementptr inbounds ({{.*}} @b, i32 0, i32 1)
-// CHECK: load i32* getelementptr inbounds ({{.*}} @b, i32 0, i32 0)
-// CHECK: load i8** getelementptr inbounds ({{.*}} @b, i32 0, i32 1)
-// CHECK: getelementptr inbounds i8* %{{.*}}, {{.*}} %{{.*}}
-// CHECK: store i8 %{{.*}}, i8* getelementptr inbounds ({{.*}} @b, i32 0, i32 2)
-// CHECK-NOT: @_ZN1A1fEv
-// CHECK: store i32 42, i32* getelementptr inbounds ({{.*}}* @b, i32 0, i32 3)
-// CHECK-NOT: C1Ev
-// CHECK: store i8 9, i8* {{.*}} @b, i32 0, i32 4)
+// CHECK-NOT: @b
// Initialization of 'c':
diff --git a/test/CodeGenCXX/cxx1y-sized-deallocation.cpp b/test/CodeGenCXX/cxx1y-sized-deallocation.cpp
new file mode 100644
index 0000000..7fd3ece
--- /dev/null
+++ b/test/CodeGenCXX/cxx1y-sized-deallocation.cpp
@@ -0,0 +1,110 @@
+// RUN: %clang_cc1 -std=c++1y %s -emit-llvm -triple x86_64-linux-gnu -o - | FileCheck %s
+// RUN: %clang_cc1 -std=c++11 -fsized-deallocation %s -emit-llvm -triple x86_64-linux-gnu -o - | FileCheck %s
+// RUN: %clang_cc1 -std=c++11 %s -emit-llvm -triple x86_64-linux-gnu -o - | FileCheck %s --check-prefix=CHECK-UNSIZED
+
+// CHECK-UNSIZED-NOT: _ZdlPvm
+// CHECK-UNSIZED-NOT: _ZdaPvm
+
+typedef decltype(sizeof(0)) size_t;
+
+typedef int A;
+struct B { int n; };
+struct C { ~C() {} };
+struct D { D(); virtual ~D() {} };
+struct E {
+ void *operator new(size_t);
+ void *operator new[](size_t);
+ void operator delete(void *) noexcept;
+ void operator delete[](void *) noexcept;
+};
+struct F {
+ void *operator new(size_t);
+ void *operator new[](size_t);
+ void operator delete(void *, size_t) noexcept;
+ void operator delete[](void *, size_t) noexcept;
+};
+
+template<typename T> T get();
+
+template<typename T>
+void del() {
+ ::delete get<T*>();
+ ::delete[] get<T*>();
+ delete get<T*>();
+ delete[] get<T*>();
+}
+
+template void del<A>();
+template void del<B>();
+template void del<C>();
+template void del<D>();
+template void del<E>();
+template void del<F>();
+
+D::D() {}
+
+// CHECK-LABEL: define weak_odr void @_Z3delIiEvv()
+// CHECK: call void @_ZdlPvm(i8* %{{[^ ]*}}, i64 4)
+// CHECK: call void @_ZdaPv(i8* %{{[^ ]*}})
+//
+// CHECK: call void @_ZdlPvm(i8* %{{[^ ]*}}, i64 4)
+// CHECK: call void @_ZdaPv(i8* %{{[^ ]*}})
+
+// CHECK-LABEL: define linkonce void @_ZdlPvm(i8*
+// CHECK: call void @_ZdlPv(i8* %0)
+
+// CHECK-LABEL: define weak_odr void @_Z3delI1BEvv()
+// CHECK: call void @_ZdlPvm(i8* %{{[^ ]*}}, i64 4)
+// CHECK: call void @_ZdaPv(i8* %{{[^ ]*}})
+//
+// CHECK: call void @_ZdlPvm(i8* %{{[^ ]*}}, i64 4)
+// CHECK: call void @_ZdaPv(i8* %{{[^ ]*}})
+
+// CHECK-LABEL: define weak_odr void @_Z3delI1CEvv()
+// CHECK: call void @_ZdlPvm(i8* %{{[^ ]*}}, i64 1)
+// CHECK: mul i64 1, %{{[^ ]*}}
+// CHECK: add i64 %{{[^ ]*}}, 8
+// CHECK: call void @_ZdaPvm(i8* %{{[^ ]*}}, i64 %{{[^ ]*}})
+//
+// CHECK: call void @_ZdlPvm(i8* %{{[^ ]*}}, i64 1)
+// CHECK: mul i64 1, %{{[^ ]*}}
+// CHECK: add i64 %{{[^ ]*}}, 8
+// CHECK: call void @_ZdaPvm(i8* %{{[^ ]*}}, i64 %{{[^ ]*}})
+
+// CHECK-LABEL: define linkonce void @_ZdaPvm(i8*
+// CHECK: call void @_ZdaPv(i8* %0)
+
+// CHECK-LABEL: define weak_odr void @_Z3delI1DEvv()
+// CHECK: call void @_ZdlPvm(i8* %{{[^ ]*}}, i64 8)
+// CHECK: mul i64 8, %{{[^ ]*}}
+// CHECK: add i64 %{{[^ ]*}}, 8
+// CHECK: call void @_ZdaPvm(i8* %{{[^ ]*}}, i64 %{{[^ ]*}})
+//
+// CHECK-NOT: Zdl
+// CHECK: call void %{{.*}}
+// CHECK-NOT: Zdl
+// CHECK: mul i64 8, %{{[^ ]*}}
+// CHECK: add i64 %{{[^ ]*}}, 8
+// CHECK: call void @_ZdaPvm(i8* %{{[^ ]*}}, i64 %{{[^ ]*}})
+
+// CHECK-LABEL: define weak_odr void @_Z3delI1EEvv()
+// CHECK: call void @_ZdlPvm(i8* %{{[^ ]*}}, i64 1)
+// CHECK: call void @_ZdaPv(i8* %{{[^ ]*}})
+//
+// CHECK: call void @_ZN1EdlEPv(i8* %{{[^ ]*}})
+// CHECK: call void @_ZN1EdaEPv(i8* %{{[^ ]*}})
+
+// CHECK-LABEL: define weak_odr void @_Z3delI1FEvv()
+// CHECK: call void @_ZdlPvm(i8* %{{[^ ]*}}, i64 1)
+// CHECK: mul i64 1, %{{[^ ]*}}
+// CHECK: add i64 %{{[^ ]*}}, 8
+// CHECK: call void @_ZdaPvm(i8* %{{[^ ]*}}, i64 %{{[^ ]*}})
+//
+// CHECK: call void @_ZN1FdlEPvm(i8* %{{[^ ]*}}, i64 1)
+// CHECK: mul i64 1, %{{[^ ]*}}
+// CHECK: add i64 %{{[^ ]*}}, 8
+// CHECK: call void @_ZN1FdaEPvm(i8* %{{[^ ]*}}, i64 %{{[^ ]*}})
+
+
+// CHECK-LABEL: define linkonce_odr void @_ZN1DD0Ev(%{{[^ ]*}}* %this)
+// CHECK: call void @_ZdlPvm(i8* %{{[^ ]*}}, i64 8)
diff --git a/test/CodeGenCXX/cxx1y-variable-template.cpp b/test/CodeGenCXX/cxx1y-variable-template.cpp
new file mode 100644
index 0000000..d1e7060
--- /dev/null
+++ b/test/CodeGenCXX/cxx1y-variable-template.cpp
@@ -0,0 +1,24 @@
+// RUN: %clang_cc1 -std=c++1y -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck %s
+
+// Check that we keep the 'extern' when we instantiate the definition of this
+// variable template specialization.
+template<typename T> extern const int extern_redecl;
+template<typename T> const int extern_redecl = 5;
+template const int extern_redecl<int>;
+
+// CHECK: @_Z13extern_redeclIiE = weak_odr constant
+
+template<typename T> struct Outer {
+ template<typename U> struct Inner {
+ template<typename V> static int arr[];
+ };
+};
+Outer<char[100]> outer_int;
+int init_arr();
+template<typename T> template<typename U> template<typename V> int Outer<T>::Inner<U>::arr[sizeof(T) + sizeof(U) + sizeof(V)] = { init_arr() };
+int *p = Outer<char[100]>::Inner<char[20]>::arr<char[3]>;
+
+// CHECK: @_ZN5OuterIA100_cE5InnerIA20_cE3arrIA3_cEE = weak_odr global [123 x i32] zeroinitializer
+// CHECK: @_ZGVN5OuterIA100_cE5InnerIA20_cE3arrIA3_cEE = weak_odr global
+
+// CHECK: call {{.*}}@_Z8init_arrv
diff --git a/test/CodeGenCXX/debug-info-artificial-arg.cpp b/test/CodeGenCXX/debug-info-artificial-arg.cpp
index ff0f663..84f496f 100644
--- a/test/CodeGenCXX/debug-info-artificial-arg.cpp
+++ b/test/CodeGenCXX/debug-info-artificial-arg.cpp
@@ -22,8 +22,8 @@ int main(int argc, char **argv) {
A reallyA (500);
}
-// 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: ![[CLASSTYPE:.*]] = {{.*}}, metadata !"_ZTS1A"} ; [ DW_TAG_class_type ] [A]
+// CHECK: ![[ARTARG:.*]] = {{.*}} ; [ DW_TAG_pointer_type ] [line 0, size 64, align 64, offset 0] [artificial] [from _ZTS1A]
+// CHECK: metadata !"_ZTS1A", {{.*}} ; [ DW_TAG_subprogram ] [line 12] [A]
+// CHECK: metadata [[FUNCTYPE:![0-9]*]], i32 0, null, null, null} ; [ DW_TAG_subroutine_type ]
// CHECK: [[FUNCTYPE]] = metadata !{null, metadata ![[ARTARG]], metadata !{{.*}}, metadata !{{.*}}}
diff --git a/test/CodeGenCXX/debug-info-class-limited.cpp b/test/CodeGenCXX/debug-info-class-limited.cpp
new file mode 100644
index 0000000..a4b9f46
--- /dev/null
+++ b/test/CodeGenCXX/debug-info-class-limited.cpp
@@ -0,0 +1,52 @@
+// RUN: %clang -emit-llvm -g -S %s -o - | FileCheck %s
+
+namespace PR16214_1 {
+// CHECK-DAG: [ DW_TAG_structure_type ] [foo] [line [[@LINE+1]], {{.*}} [def]
+struct foo {
+ int i;
+};
+
+typedef foo bar;
+
+bar *a;
+bar b;
+}
+
+namespace PR14467 {
+// CHECK-DAG: [ DW_TAG_structure_type ] [foo] [line [[@LINE+1]], {{.*}} [def]
+struct foo {
+};
+
+foo *bar(foo *a) {
+ foo *b = new foo(*a);
+ return b;
+}
+}
+
+namespace test1 {
+// CHECK-DAG: [ DW_TAG_structure_type ] [foo] [line [[@LINE+1]], {{.*}} [decl]
+struct foo {
+};
+
+extern int bar(foo *a);
+int baz(foo *a) {
+ return bar(a);
+}
+}
+
+namespace test2 {
+// FIXME: if we were a bit fancier, we could realize that the 'foo' type is only
+// required because of the 'bar' type which is not required at all (or might
+// only be required to be declared)
+// CHECK-DAG: [ DW_TAG_structure_type ] [foo] [line [[@LINE+1]], {{.*}} [def]
+struct foo {
+};
+
+struct bar {
+ foo f;
+};
+
+void func() {
+ foo *f;
+}
+}
diff --git a/test/CodeGenCXX/debug-info-class-nolimit.cpp b/test/CodeGenCXX/debug-info-class-nolimit.cpp
new file mode 100644
index 0000000..ce72bd3
--- /dev/null
+++ b/test/CodeGenCXX/debug-info-class-nolimit.cpp
@@ -0,0 +1,30 @@
+// RUN: %clang_cc1 -triple x86_64-unk-unk -fno-limit-debug-info -o - -emit-llvm -g %s | FileCheck %s
+
+namespace rdar14101097_1 { // see also PR16214
+// Check that we emit debug info for the definition of a struct if the
+// definition is available, even if it's used via a pointer wrapped in a
+// typedef.
+// CHECK: [ DW_TAG_structure_type ] [foo] {{.*}}[def]
+struct foo {
+};
+
+typedef foo *foop;
+
+void bar() {
+ foop f;
+}
+}
+
+namespace rdar14101097_2 {
+// As above, except trickier because we first encounter only a declaration of
+// the type and no debug-info related use after we see the definition of the
+// type.
+// CHECK: [ DW_TAG_structure_type ] [foo] {{.*}}[def]
+struct foo;
+void bar() {
+ foo *f;
+}
+struct foo {
+};
+}
+
diff --git a/test/CodeGenCXX/debug-info-class.cpp b/test/CodeGenCXX/debug-info-class.cpp
index df24926..e1402c9 100644
--- a/test/CodeGenCXX/debug-info-class.cpp
+++ b/test/CodeGenCXX/debug-info-class.cpp
@@ -12,6 +12,51 @@ class B {
public:
virtual ~B();
};
+
+B::~B() {
+}
+
+struct C {
+ static int s;
+ virtual ~C();
+};
+
+C::~C() {
+}
+
+struct D {
+ D();
+ virtual ~D();
+ void func() {
+ }
+};
+
+struct E {
+ E();
+ virtual ~E();
+ virtual void func() {
+ }
+};
+
+struct F {
+ struct inner {
+ };
+ static const int i = 2;
+ virtual ~F();
+};
+
+struct G {
+ virtual void func();
+ struct inner {
+ int j;
+ };
+};
+
+struct H {};
+struct I : virtual H {};
+struct J : I {};
+J j;
+
struct A {
int one;
static const int HdrSize = 52;
@@ -21,9 +66,17 @@ struct A {
}
};
+void f1() {
+ D x;
+ x.func();
+ E y;
+ int i = F::i;
+ F::inner z;
+}
int main(int argc, char **argv) {
B b;
+ G::inner c_i;
if (argc) {
A a;
}
@@ -40,9 +93,33 @@ int main(int argc, char **argv) {
// 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: DW_TAG_class_type ] [B] {{.*}} [def]
// CHECK: metadata !"_vptr$B", {{.*}}, i32 64, metadata !{{.*}}} ; [ DW_TAG_member ]
-// CHECK: ![[EXCEPTLOC]] = metadata !{i32 31,
-// CHECK: ![[RETLOC]] = metadata !{i32 30,
+
+// CHECK: [[C:![0-9]*]] = {{.*}} metadata [[C_MEM:![0-9]*]], i32 0, metadata !"_ZTS1C", null, metadata !"_ZTS1C"} ; [ DW_TAG_structure_type ] [C] {{.*}} [def]
+// CHECK: [[C_MEM]] = metadata !{metadata [[C_VPTR:![0-9]*]], metadata [[C_S:![0-9]*]], metadata [[C_DTOR:![0-9]*]]}
+// CHECK: [[C_VPTR]] = {{.*}} ; [ DW_TAG_member ] [_vptr$C] {{.*}} [artificial]
+// CHECK: [[C_S]] = {{.*}} ; [ DW_TAG_member ] [s] {{.*}} [static] [from int]
+// CHECK: [[C_DTOR]] = {{.*}} ; [ DW_TAG_subprogram ] {{.*}} [~C]
+
+// CHECK: metadata [[D_MEM:![0-9]*]], i32 0, null, null, metadata !"_ZTS1D"} ; [ DW_TAG_structure_type ] [D] {{.*}} [decl]
+// CHECK: [[D_MEM]] = metadata !{metadata [[D_FUNC:![0-9]*]]}
+// CHECK: [[D_FUNC]] = {{.*}} ; [ DW_TAG_subprogram ] {{.*}} [func]
+// CHECK: null, i32 0, null, null, metadata !"_ZTS1E"} ; [ DW_TAG_structure_type ] [E] {{.*}} [decl]
+// CHECK: [[F:![0-9]*]] = {{.*}} metadata [[F_MEM:![0-9]*]], i32 0, null, null, metadata !"_ZTS1F"} ; [ DW_TAG_structure_type ] [F] {{.*}} [decl]
+// CHECK: [[F_MEM]] = metadata !{metadata [[F_I:![0-9]*]]}
+// CHECK: [[F_I]] = {{.*}} ; [ DW_TAG_member ] [i]
+
+// CHECK: null, i32 0, null, null, metadata !"_ZTS1G"} ; [ DW_TAG_structure_type ] [G] {{.*}} [decl]
+// CHECK: metadata [[G_INNER_MEM:![0-9]*]], i32 0, null, null, metadata !"_ZTSN1G5innerE"} ; [ DW_TAG_structure_type ] [inner] [line 50, {{.*}} [def]
+// CHECK: [[G_INNER_MEM]] = metadata !{metadata [[G_INNER_I:![0-9]*]]}
+// CHECK: [[G_INNER_I]] = {{.*}} ; [ DW_TAG_member ] [j] {{.*}} [from int]
+
+// CHECK: ; [ DW_TAG_structure_type ] [A]
+// CHECK: HdrSize
+// CHECK: ; [ DW_TAG_structure_type ] [I] {{.*}} [def]
+
+// CHECK: [[F_I_DEF:![0-9]*]] = {{.*}}, metadata [[F_I]]} ; [ DW_TAG_variable ] [i]
+
+// CHECK: ![[EXCEPTLOC]] = metadata !{i32 84,
+// CHECK: ![[RETLOC]] = metadata !{i32 83,
diff --git a/test/CodeGenCXX/debug-info-cxx1y.cpp b/test/CodeGenCXX/debug-info-cxx1y.cpp
new file mode 100644
index 0000000..3cb7e45
--- /dev/null
+++ b/test/CodeGenCXX/debug-info-cxx1y.cpp
@@ -0,0 +1,7 @@
+// RUN: not %clang_cc1 -emit-llvm-only -std=c++1y -g %s 2>&1 | FileCheck %s
+
+struct foo {
+ auto func(); // CHECK: error: debug information for auto is not yet supported
+};
+
+foo f;
diff --git a/test/CodeGenCXX/debug-info-decl-nested.cpp b/test/CodeGenCXX/debug-info-decl-nested.cpp
new file mode 100644
index 0000000..f79a8e9
--- /dev/null
+++ b/test/CodeGenCXX/debug-info-decl-nested.cpp
@@ -0,0 +1,61 @@
+// RUN: %clang_cc1 -std=c++11 -g -emit-llvm -g -triple x86_64-apple-darwin %s -o %t
+// RUN: cat %t | FileCheck %s -check-prefix=CHECK0
+// RUN: cat %t | FileCheck %s -check-prefix=CHECK1
+// RUN: cat %t | FileCheck %s -check-prefix=CHECK2
+//
+// This test ensures that we associate a declaration with the
+// definition of the constructor for OuterClass. The declaration is
+// necessary so the backend can emit the DW_AT_specification attribute
+// for the definition.
+//
+// rdar://problem/13116508
+
+class Foo;
+class OuterClass
+{
+ static class InnerClass {
+ public:
+ InnerClass(); // Here createContextChain() generates a limited type for OuterClass.
+ } theInnerClass;
+// CHECK0: [[DECL:[0-9]+]] = {{.*}} ; [ DW_TAG_subprogram ] [line [[@LINE+1]]] [private] [OuterClass]
+ OuterClass(const Foo *); // line 10
+};
+OuterClass::InnerClass OuterClass::theInnerClass; // This toplevel decl causes InnerClass to be generated.
+// CHECK0: metadata {{.*}}, metadata ![[DECL]], metadata {{.*}}, i32 [[@LINE+1]]} ; [ DW_TAG_subprogram ] [line [[@LINE+1]]] [def] [OuterClass]
+OuterClass::OuterClass(const Foo *meta) { } // line 13
+
+
+
+
+
+class Foo1;
+class OuterClass1
+{
+ static class InnerClass1 {
+ public:
+ InnerClass1();
+ } theInnerClass1;
+// CHECK1: [[DECL:[0-9]+]] = {{.*}} ; [ DW_TAG_subprogram ] [line [[@LINE+2]]] [private] [Bar]
+// CHECK1: metadata {{.*}}, metadata ![[DECL]], metadata {{.*}}, i32 [[@LINE+4]]} ; [ DW_TAG_subprogram ] [line [[@LINE+4]]] [def] [Bar]
+ void Bar(const Foo1 *);
+};
+OuterClass1::InnerClass1 OuterClass1::theInnerClass1;
+void OuterClass1::Bar(const Foo1 *meta) { }
+
+
+
+
+
+class Foo2;
+class OuterClass2
+{
+ static class InnerClass2 {
+ public:
+ InnerClass2();
+ } theInnerClass2;
+// CHECK2: [[DECL:[0-9]+]] = {{.*}} ; [ DW_TAG_subprogram ] [line [[@LINE+1]]] [private] [~OuterClass2]
+ ~OuterClass2(); // line 10
+};
+OuterClass2::InnerClass2 OuterClass2::theInnerClass2;
+// CHECK2: metadata {{.*}}, metadata ![[DECL]], metadata {{.*}}, i32 [[@LINE+1]]} ; [ DW_TAG_subprogram ] [line [[@LINE+1]]] [def] [~OuterClass2]
+OuterClass2::~OuterClass2() { }
diff --git a/test/CodeGenCXX/debug-info-enum-class.cpp b/test/CodeGenCXX/debug-info-enum-class.cpp
index 929327b..0f4b09a 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: ; [ 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 ]
+// CHECK: ; [ DW_TAG_enumeration_type ] [A] [line 3, size 32, align 32, offset 0] [def] [from int]
+// CHECK: ; [ DW_TAG_enumeration_type ] [B] [line 4, size 64, align 64, offset 0] [def] [from long unsigned int]
+// CHECK: ; [ DW_TAG_enumeration_type ] [C] [line 5, size 32, align 32, offset 0] [def] [from ]
+// CHECK: ; [ DW_TAG_enumeration_type ] [D] [line 6, size 16, align 16, offset 0] [decl] [from ]
namespace PR14029 {
// Make sure this doesn't crash/assert.
diff --git a/test/CodeGenCXX/debug-info-enum.cpp b/test/CodeGenCXX/debug-info-enum.cpp
index c08fc35..f0e2608 100644
--- a/test/CodeGenCXX/debug-info-enum.cpp
+++ b/test/CodeGenCXX/debug-info-enum.cpp
@@ -1,8 +1,36 @@
-// RUN: %clang -fverbose-asm -S -g %s -o - | grep DW_TAG_enumeration_type
+// RUN: %clang_cc1 -emit-llvm -g %s -o - | FileCheck %s
-int v;
-enum index { MAX };
-void foo(void)
-{
- v = MAX;
+// CHECK: [[ENUMS:![0-9]*]], {{[^,]*}}, {{[^,]*}}, {{[^,]*}}, {{[^,]*}}, {{[^,]*}}} ; [ DW_TAG_compile_unit ]
+// CHECK: [[ENUMS]] = metadata !{metadata [[E1:![0-9]*]], metadata [[E2:![0-9]*]], metadata [[E3:![0-9]*]]}
+
+namespace test1 {
+// CHECK: [[E1]] = metadata !{i32 {{[^,]*}}, {{[^,]*}}, metadata [[TEST1:![0-9]*]], {{.*}}, metadata [[TEST1_ENUMS:![0-9]*]], {{[^,]*}}, null, null, metadata !"_ZTSN5test11eE"} ; [ DW_TAG_enumeration_type ] [e]
+// CHECK: [[TEST1]] = {{.*}} ; [ DW_TAG_namespace ] [test1]
+// CHECK: [[TEST1_ENUMS]] = metadata !{metadata [[TEST1_E:![0-9]*]]}
+// CHECK: [[TEST1_E]] = {{.*}}, metadata !"E", i64 0} ; [ DW_TAG_enumerator ] [E :: 0]
+enum e { E };
+void foo() {
+ int v = E;
+}
+}
+
+namespace test2 {
+// rdar://8195980
+// CHECK: [[E2]] = metadata !{i32 {{[^,]*}}, {{[^,]*}}, metadata [[TEST2:![0-9]*]], {{.*}}, metadata [[TEST1_ENUMS]], {{[^,]*}}, null, null, metadata !"_ZTSN5test21eE"} ; [ DW_TAG_enumeration_type ] [e]
+// CHECK: [[TEST2]] = {{.*}} ; [ DW_TAG_namespace ] [test2]
+enum e { E };
+bool func(int i) {
+ return i == E;
+}
+}
+
+namespace test3 {
+// CHECK: [[E3]] = metadata !{i32 {{[^,]*}}, {{[^,]*}}, metadata [[TEST3:![0-9]*]], {{.*}}, metadata [[TEST3_ENUMS:![0-9]*]], {{[^,]*}}, null, null, metadata !"_ZTSN5test31eE"} ; [ DW_TAG_enumeration_type ] [e]
+// CHECK: [[TEST3]] = {{.*}} ; [ DW_TAG_namespace ] [test3]
+// CHECK: [[TEST3_ENUMS]] = metadata !{metadata [[TEST3_E:![0-9]*]]}
+// CHECK: [[TEST3_E]] = {{.*}}, metadata !"E", i64 -1} ; [ DW_TAG_enumerator ] [E :: -1]
+enum e { E = -1 };
+void func() {
+ e x;
+}
}
diff --git a/test/CodeGenCXX/debug-info-friend.cpp b/test/CodeGenCXX/debug-info-friend.cpp
index c50f281..b103b14 100644
--- a/test/CodeGenCXX/debug-info-friend.cpp
+++ b/test/CodeGenCXX/debug-info-friend.cpp
@@ -1,11 +1,20 @@
-// RUN: %clang -fverbose-asm -S -g %s -o - | grep DW_TAG_friend
+// RUN: %clang -emit-llvm -S -g %s -o - | FileCheck %s
class MyFriend;
-class SomeClass
-{
- friend class MyFriend;
+class SomeClass {
+ friend class MyFriend;
+ typedef int SomeType;
};
-SomeClass sc;
+SomeClass *x;
+struct MyFriend {
+ static void func(SomeClass::SomeType) {
+ }
+};
+
+// Emitting debug info for friends unnecessarily bloats debug info without any
+// known benefit or debugger feature that requires it. Re-enable this is a
+// use-case appears.
+// CHECK-NOT: DW_TAG_friend
diff --git a/test/CodeGenCXX/debug-info-function-context.cpp b/test/CodeGenCXX/debug-info-function-context.cpp
new file mode 100644
index 0000000..4ca1c8d
--- /dev/null
+++ b/test/CodeGenCXX/debug-info-function-context.cpp
@@ -0,0 +1,36 @@
+// RUN: %clang_cc1 -emit-llvm -g -triple x86_64-pc-linux-gnu %s -o - | FileCheck %s
+
+struct C {
+ void member_function();
+ static int static_member_function();
+ static int static_member_variable;
+};
+
+int C::static_member_variable = 0;
+
+void C::member_function() { static_member_variable = 0; }
+
+int C::static_member_function() { return static_member_variable; }
+
+C global_variable;
+
+int global_function() { return -1; }
+
+namespace ns {
+void global_namespace_function() { global_variable.member_function(); }
+int global_namespace_variable = 1;
+}
+
+// Check that the functions that belong to C have C as a context and the
+// functions that belong to the namespace have it as a context, and the global
+// function has the file as a context.
+
+// CHECK: metadata !"_ZTS1C", metadata !"member_function"{{.*}} [ DW_TAG_subprogram ] [line 11] [def] [member_function]
+
+// CHECK: metadata !"_ZTS1C", metadata !"static_member_function"{{.*}} [ DW_TAG_subprogram ] [line 13] [def] [static_member_function]
+
+// CHECK: metadata !22, metadata !"global_function"{{.*}} [ DW_TAG_subprogram ] [line 17] [def] [global_function]
+// CHECK: !22 = {{.*}} [ DW_TAG_file_type ]
+
+// CHECK: metadata !24, metadata !"global_namespace_function"{{.*}} [ DW_TAG_subprogram ] [line 20] [def] [global_namespace_function]
+// CHECK: !24 = {{.*}} [ DW_TAG_namespace ] [ns] [line 19]
diff --git a/test/CodeGenCXX/debug-info-gline-tables-only.cpp b/test/CodeGenCXX/debug-info-gline-tables-only.cpp
index 8d2e63d..7ecdeb2 100644
--- a/test/CodeGenCXX/debug-info-gline-tables-only.cpp
+++ b/test/CodeGenCXX/debug-info-gline-tables-only.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -O0 -gline-tables-only -S -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -gline-tables-only -S -emit-llvm -o - | FileCheck %s
// Checks that clang with "-gline-tables-only" doesn't emit debug info
// for variables and types.
@@ -13,9 +13,17 @@ class E : public C {
// CHECK-NOT: DW_TAG_reference type
void x(const D& d);
};
+struct F {
+ enum X { };
+ void func(X);
+ virtual ~F();
+};
+F::~F() {
+}
}
// CHECK-NOT: DW_TAG_variable
NS::C c;
NS::D d;
NS::E e;
+NS::F f;
diff --git a/test/CodeGenCXX/debug-info-global-ctor-dtor.cpp b/test/CodeGenCXX/debug-info-global-ctor-dtor.cpp
index bdaf58c..afa7707 100644
--- a/test/CodeGenCXX/debug-info-global-ctor-dtor.cpp
+++ b/test/CodeGenCXX/debug-info-global-ctor-dtor.cpp
@@ -20,8 +20,8 @@ void foo() {
// CHECK-NOKEXT: [ DW_TAG_subprogram ] [line 12] [local] [def] [__dtor_glob]
// CHECK-NOKEXT: [ DW_TAG_subprogram ] [line 13] [local] [def] [__cxx_global_var_init1]
// CHECK-NOKEXT: [ DW_TAG_subprogram ] [line 13] [local] [def] [__cxx_global_array_dtor]
-// CHECK-NOKEXT: [ DW_TAG_subprogram ] [line 13] [local] [def] [__dtor_]
+// CHECK-NOKEXT: [ DW_TAG_subprogram ] [line 13] [local] [def] [__dtor_array]
// CHECK-NOKEXT: [ DW_TAG_subprogram ] [line 16] [local] [def] [__dtor__ZZ3foovE4stat]
-// CHECK-NOKEXT: [ DW_TAG_subprogram ] [line {{.*}}] [local] [def] [_GLOBAL__I_a]
+// CHECK-NOKEXT: [ DW_TAG_subprogram ] [line {{.*}}] [local] [def]{{$}}
-// CHECK-KEXT: [ DW_TAG_subprogram ] [line {{.*}}] [local] [def] [_GLOBAL__D_a]
+// CHECK-KEXT: [ DW_TAG_subprogram ] [line {{.*}}] [local] [def]{{$}}
diff --git a/test/CodeGenCXX/debug-info-globalinit.cpp b/test/CodeGenCXX/debug-info-globalinit.cpp
index b3891c1..30c8bfc 100644
--- a/test/CodeGenCXX/debug-info-globalinit.cpp
+++ b/test/CodeGenCXX/debug-info-globalinit.cpp
@@ -12,19 +12,27 @@ int test() {
static int i = test();
__attribute__((nodebug)) static int j = test();
+static int k = test();
int main(void) {}
-// CHECK: define internal void @__cxx_global_var_init()
+// CHECK-LABEL: define internal void @__cxx_global_var_init()
// CHECK-NOT: __cxx_global_var_init
// CHECK: %[[C0:.+]] = call i32 @_Z4testv(), !dbg ![[LINE:.*]]
// CHECK-NOT: __cxx_global_var_init
// CHECK: store i32 %[[C0]], i32* @_ZL1i, align 4, !dbg
//
-// CHECK: define internal void @__cxx_global_var_init1()
+// CHECK-LABEL: define internal void @__cxx_global_var_init1()
// CHECK-NOT: dbg
// CHECK: %[[C1:.+]] = call i32 @_Z4testv()
// CHECK-NOT: dbg
// CHECK: store i32 %[[C1]], i32* @_ZL1j, align 4
+//
+// CHECK-LABEL: define internal void @__cxx_global_var_init2()
+// CHECK-NOT: __cxx_global_var_init
+// CHECK: %[[C2:.+]] = call i32 @_Z4testv(), !dbg ![[LINE2:.*]]
+// CHECK-NOT: __cxx_global_var_init
+// CHECK: store i32 %[[C2]], i32* @_ZL1k, align 4, !dbg
//
// CHECK: ![[LINE]] = metadata !{i32 13, i32
+// CHECK: ![[LINE2]] = metadata !{i32 15, i32
diff --git a/test/CodeGenCXX/debug-info-limit-type.cpp b/test/CodeGenCXX/debug-info-limit-type.cpp
deleted file mode 100644
index e03024f..0000000
--- a/test/CodeGenCXX/debug-info-limit-type.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-// RUN: %clang -emit-llvm -g -S %s -o - | FileCheck %s
-// XFAIL: *
-
-class B {
-public:
- int bb;
- void fn2() {}
-};
-
-class A {
-public:
- int aa;
- void fn1(B b) { b.fn2(); }
-};
-
-void foo(A *aptr) {
-}
-
-void bar() {
- A a;
-}
-
-// B should only be emitted as a forward reference (i32 4).
-// CHECK: metadata !"B", metadata !6, i32 3, i32 0, i32 0, i32 0, i32 4} ; [ DW_TAG_class_type ]
diff --git a/test/CodeGenCXX/debug-info-limit.cpp b/test/CodeGenCXX/debug-info-limit.cpp
deleted file mode 100644
index bca887b..0000000
--- a/test/CodeGenCXX/debug-info-limit.cpp
+++ /dev/null
@@ -1,14 +0,0 @@
-// RUN: %clang -emit-llvm -g -S %s -o - | FileCheck %s
-
-// TAG_member is used to encode debug info for class constructor.
-// CHECK: TAG_member
-class A {
-public:
- int z;
-};
-
-A *foo (A* x) {
- A *a = new A(*x);
- return a;
-}
-
diff --git a/test/CodeGenCXX/debug-info-limited.cpp b/test/CodeGenCXX/debug-info-limited.cpp
new file mode 100644
index 0000000..54a2424
--- /dev/null
+++ b/test/CodeGenCXX/debug-info-limited.cpp
@@ -0,0 +1,33 @@
+// RUN: %clang -flimit-debug-info -emit-llvm -g -S %s -o - | FileCheck %s
+
+// CHECK: ; [ DW_TAG_class_type ] [A] {{.*}} [def]
+class A {
+public:
+ int z;
+};
+
+A *foo (A* x) {
+ A *a = new A(*x);
+ return a;
+}
+
+// Verify that we're not emitting a full definition of B in limit debug mode.
+// CHECK: ; [ DW_TAG_class_type ] [B] {{.*}} [decl]
+
+class B {
+public:
+ int y;
+};
+
+extern int bar(B *b);
+int baz(B *b) {
+ return bar(b);
+}
+
+
+// CHECK: ; [ DW_TAG_structure_type ] [C] {{.*}} [decl]
+
+struct C {
+};
+
+C (*x)(C);
diff --git a/test/CodeGenCXX/debug-info-method.cpp b/test/CodeGenCXX/debug-info-method.cpp
index 3ee4d9b..50b3f66 100644
--- a/test/CodeGenCXX/debug-info-method.cpp
+++ b/test/CodeGenCXX/debug-info-method.cpp
@@ -1,9 +1,10 @@
// 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 !"_ZTS1A"} ; [ DW_TAG_class_type ] [A]
// CHECK: metadata !"_ZN1A3fooEiS_3$_0", {{.*}} [protected]
+// CHECK: ![[THISTYPE:[0-9]+]] = {{.*}} ; [ DW_TAG_pointer_type ] {{.*}} [artificial] [from _ZTS1A]
// 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: ![[MEMFUNTYPE]] = {{.*}}metadata ![[MEMFUNARGS:[0-9]+]], i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] {{.*}} [from ]
// CHECK: ![[MEMFUNARGS]] = {{.*}}, metadata ![[THISTYPE]],
// CHECK: ""{{.*}}DW_TAG_arg_variable
// CHECK: ""{{.*}}DW_TAG_arg_variable
diff --git a/test/CodeGenCXX/debug-info-namespace.cpp b/test/CodeGenCXX/debug-info-namespace.cpp
index 13a7914..a2d7ede 100644
--- a/test/CodeGenCXX/debug-info-namespace.cpp
+++ b/test/CodeGenCXX/debug-info-namespace.cpp
@@ -1,14 +1,24 @@
-// RUN: %clang -g -S -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang -g -S -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang -g -gline-tables-only -S -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-GMLT %s
+// RUN: %clang -g -fno-limit-debug-info -S -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-NOLIMIT %s
namespace A {
#line 1 "foo.cpp"
namespace B {
int i;
+void f1() { }
+void f1(int) { }
+struct foo;
+struct bar { };
+typedef bar baz;
}
+}
+namespace A {
using namespace B;
}
using namespace A;
+namespace E = A;
int func(bool b) {
if (b) {
@@ -16,22 +26,52 @@ int func(bool b) {
return i;
}
using namespace A;
- return B::i;
+ using B::foo;
+ using B::bar;
+ using B::f1;
+ using B::i;
+ using B::baz;
+ namespace X = A;
+ namespace Y = X;
+ return i + X::B::i + Y::B::i;
}
+// This should work even if 'i' and 'func' were declarations & not definitions,
+// but it doesn't yet.
+
// CHECK: [[CU:![0-9]*]] = {{.*}}[[MODULES:![0-9]*]], metadata !""} ; [ DW_TAG_compile_unit ]
// CHECK: [[FILE:![0-9]*]] {{.*}}debug-info-namespace.cpp"
-// CHECK: [[FUNC:![0-9]*]] {{.*}} ; [ DW_TAG_subprogram ] [line 9] [def] [func]
-// CHECK: [[FILE2:![0-9]*]]} ; [ DW_TAG_file_type ] [{{.*}}foo.cpp]
-// CHECK: [[VAR:![0-9]*]] = {{.*}}, metadata [[NS:![0-9]*]], metadata !"i", {{.*}} ; [ DW_TAG_variable ] [i]
-// CHECK: [[NS]] = {{.*}}, metadata [[FILE2]], metadata [[CTXT:![0-9]*]], {{.*}} ; [ DW_TAG_namespace ] [B] [line 1]
-// CHECK: [[CTXT]] = {{.*}}, metadata [[FILE]], null, {{.*}} ; [ DW_TAG_namespace ] [A] [line 3]
-// CHECK: [[MODULES]] = metadata !{metadata [[M1:![0-9]*]], metadata [[M2:![0-9]*]], metadata [[M3:![0-9]*]], metadata [[M4:![0-9]*]]}
-// CHECK: [[M1]] = metadata !{i32 {{[0-9]*}}, metadata [[CTXT]], metadata [[NS]], i32 4} ; [ DW_TAG_imported_module ]
-// CHECK: [[M2]] = metadata !{i32 {{[0-9]*}}, metadata [[CU]], metadata [[CTXT]], i32 7} ; [ DW_TAG_imported_module ]
-// CHECK: [[M3]] = metadata !{i32 {{[0-9]*}}, metadata [[LEX:![0-9]*]], metadata [[NS]], i32 11} ; [ DW_TAG_imported_module ]
-// CHECK: [[LEX]] = metadata !{i32 {{[0-9]*}}, metadata [[FILE2]], metadata [[FUNC]], i32 10, i32 0, i32 0} ; [ DW_TAG_lexical_block ]
-// CHECK: [[M4]] = metadata !{i32 {{[0-9]*}}, metadata [[FUNC]], metadata [[CTXT]], i32 14} ; [ DW_TAG_imported_module ]
+// CHECK: [[FOO:![0-9]*]] {{.*}} ; [ DW_TAG_structure_type ] [foo] [line 5, size 0, align 0, offset 0] [decl] [from ]
+// CHECK: [[FOOCPP:![0-9]*]] = metadata !{metadata !"foo.cpp", {{.*}}
+// CHECK: [[NS:![0-9]*]] = {{.*}}, metadata [[FILE2:![0-9]*]], metadata [[CTXT:![0-9]*]], {{.*}} ; [ DW_TAG_namespace ] [B] [line 1]
+// CHECK: [[CTXT]] = {{.*}}, metadata [[FILE]], null, {{.*}} ; [ DW_TAG_namespace ] [A] [line 5]
+// CHECK: [[BAR:![0-9]*]] {{.*}} ; [ DW_TAG_structure_type ] [bar] [line 6, {{.*}}] [decl] [from ]
+// CHECK: [[F1:![0-9]*]] {{.*}} ; [ DW_TAG_subprogram ] [line 4] [def] [f1]
+// CHECK: [[FUNC:![0-9]*]] {{.*}} ; [ DW_TAG_subprogram ] {{.*}} [def] [func]
+// CHECK: [[FILE2]]} ; [ DW_TAG_file_type ] [{{.*}}foo.cpp]
+// CHECK: [[I:![0-9]*]] = {{.*}}, metadata [[NS]], metadata !"i", {{.*}} ; [ DW_TAG_variable ] [i]
+// CHECK: [[MODULES]] = metadata !{metadata [[M1:![0-9]*]], metadata [[M2:![0-9]*]], metadata [[M3:![0-9]*]], metadata [[M4:![0-9]*]], metadata [[M5:![0-9]*]], metadata [[M6:![0-9]*]], metadata [[M7:![0-9]*]], metadata [[M8:![0-9]*]], metadata [[M9:![0-9]*]], metadata [[M10:![0-9]*]], metadata [[M11:![0-9]*]], metadata [[M12:![0-9]*]]}
+// CHECK: [[M1]] = metadata !{i32 {{[0-9]*}}, metadata [[CTXT]], metadata [[NS]], i32 11} ; [ DW_TAG_imported_module ]
+// CHECK: [[M2]] = metadata !{i32 {{[0-9]*}}, metadata [[CU]], metadata [[CTXT]], i32 {{[0-9]*}}} ; [ DW_TAG_imported_module ]
+// CHECK: [[M3]] = metadata !{i32 {{[0-9]*}}, metadata [[CU]], metadata [[CTXT]], i32 15, metadata !"E"} ; [ DW_TAG_imported_module ]
+// CHECK: [[M4]] = metadata !{i32 {{[0-9]*}}, metadata [[LEX2:![0-9]*]], metadata [[NS]], i32 19} ; [ DW_TAG_imported_module ]
+// CHECK: [[LEX2]] = metadata !{i32 {{[0-9]*}}, metadata [[FILE2]], metadata [[LEX1:![0-9]+]], i32 {{[0-9]*}}, i32 0, i32 {{.*}}} ; [ DW_TAG_lexical_block ]
+// CHECK: [[LEX1]] = metadata !{i32 {{[0-9]*}}, metadata [[FILE2]], metadata [[FUNC]], i32 {{[0-9]*}}, i32 0, i32 {{.*}}} ; [ DW_TAG_lexical_block ]
+// CHECK: [[M5]] = metadata !{i32 {{[0-9]*}}, metadata [[FUNC]], metadata [[CTXT]], i32 {{[0-9]*}}} ; [ DW_TAG_imported_module ]
+// CHECK: [[M6]] = metadata !{i32 {{[0-9]*}}, metadata [[FUNC]], metadata [[FOO:![0-9]*]], i32 23} ; [ DW_TAG_imported_declaration ]
+// CHECK: [[M7]] = metadata !{i32 {{[0-9]*}}, metadata [[FUNC]], metadata [[BAR:![0-9]*]], i32 {{[0-9]*}}} ; [ DW_TAG_imported_declaration ]
+// CHECK: [[M8]] = metadata !{i32 {{[0-9]*}}, metadata [[FUNC]], metadata [[F1]], i32 {{[0-9]*}}} ; [ DW_TAG_imported_declaration ]
+// CHECK: [[M9]] = metadata !{i32 {{[0-9]*}}, metadata [[FUNC]], metadata [[I]], i32 {{[0-9]*}}} ; [ DW_TAG_imported_declaration ]
+// CHECK: [[M10]] = metadata !{i32 {{[0-9]*}}, metadata [[FUNC]], metadata [[BAZ:![0-9]*]], i32 {{[0-9]*}}} ; [ DW_TAG_imported_declaration ]
+// CHECK: [[BAZ]] = metadata !{i32 {{[0-9]*}}, metadata [[FOOCPP]], metadata [[NS]], {{.*}}, metadata !"_ZTSN1A1B3barE"} ; [ DW_TAG_typedef ] [baz] {{.*}} [from _ZTSN1A1B3barE]
+// CHECK: [[M11]] = metadata !{i32 {{[0-9]*}}, metadata [[FUNC]], metadata [[CTXT]], i32 {{[0-9]*}}, metadata !"X"} ; [ DW_TAG_imported_module ]
+// CHECK: [[M12]] = metadata !{i32 {{[0-9]*}}, metadata [[FUNC]], metadata [[M11]], i32 {{[0-9]*}}, metadata !"Y"} ; [ DW_TAG_imported_module ]
+
+// CHECK-GMLT: [[CU:![0-9]*]] = {{.*}}[[MODULES:![0-9]*]], metadata !""} ; [ DW_TAG_compile_unit ]
+// CHECK-GMLT: [[MODULES]] = metadata !{i32 0}
+
+// CHECK-NOLIMIT: ; [ DW_TAG_structure_type ] [bar] [line 6, {{.*}}] [def] [from ]
// FIXME: It is confused on win32 to generate file entry when dosish filename is given.
// REQUIRES: shell
+// REQUIRES: shell-preserves-root
diff --git a/test/CodeGenCXX/debug-info-nullptr.cpp b/test/CodeGenCXX/debug-info-nullptr.cpp
index 42e9741..ef9b618 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: [ DW_TAG_unspecified_type ] [nullptr_t]
+// CHECK: [ DW_TAG_unspecified_type ] [decltype(nullptr)]
diff --git a/test/CodeGenCXX/debug-info-pubtypes.cpp b/test/CodeGenCXX/debug-info-pubtypes.cpp
index 6ca3da8..6393cdd 100644
--- a/test/CodeGenCXX/debug-info-pubtypes.cpp
+++ b/test/CodeGenCXX/debug-info-pubtypes.cpp
@@ -1,6 +1,5 @@
// REQUIRES: x86-64-registered-target
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -g -fno-limit-debug-info -S %s -o %t
-// RUN: FileCheck %s < %t
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -g -fno-limit-debug-info -S -mllvm -generate-dwarf-pub-sections=Enable %s -o - | FileCheck %s
// FIXME: This testcase shouldn't rely on assembly emission.
//CHECK: Lpubtypes_begin[[SECNUM:[0-9]:]]
@@ -10,7 +9,7 @@
class G {
public:
- void foo();
+ void foo();
};
void G::foo() {
diff --git a/test/CodeGenCXX/debug-info-same-line.cpp b/test/CodeGenCXX/debug-info-same-line.cpp
index ad24503..519e9ee 100644
--- a/test/CodeGenCXX/debug-info-same-line.cpp
+++ b/test/CodeGenCXX/debug-info-same-line.cpp
@@ -83,6 +83,21 @@ main(int argc, char const *argv[])
// 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
+
+// Again: we want to see a distinct !dbg node.
+// CHECK: call void @llvm.dbg.declare(metadata !{i32* %{{.*}}}, metadata ![[X_MD:[0-9]+]]), !dbg ![[X_DI:[0-9]+]]
+// CHECK: call void @llvm.dbg.declare(metadata !{i32* %{{.*}}}, metadata ![[Y_MD:[0-9]+]]), !dbg ![[Y_DI:[0-9]+]]
+// result
+// CHECK: call void @llvm.dbg.declare
+
+
// CHECK: define {{.*}} @main
// CHECK: call {{.*}} @_Z3fooii
// CHECK: call {{.*}} @_Z3fooii
@@ -96,3 +111,13 @@ main(int argc, char const *argv[])
// CHECK: load {{.*}} !dbg ![[DBG]]
// CHECK: call {{.*}} @_Z11strange_maxii(i32 {{.*}}, i32 {{.*}}), !dbg ![[DBG]]
// CHECK: call {{.*}} @_Z11strange_maxii(i32 {{.*}}, i32 {{.*}}), !dbg ![[DBG]]
+
+
+// Verify that product() has its own inlined_at location at column 15.
+// CHECK-DAG: ![[A_MD]] = metadata{{.*}}[ DW_TAG_arg_variable ] [a]
+// CHECK-DAG: ![[B_MD]] = metadata{{.*}}[ DW_TAG_arg_variable ] [b]
+// CHECK-DAG: ![[X_MD]] = metadata{{.*}}[ DW_TAG_arg_variable ] [x]
+// CHECK-DAG: ![[Y_MD]] = metadata{{.*}}[ DW_TAG_arg_variable ] [y]
+// CHECK-DAG: ![[X_DI]] = metadata !{i32 {{[0-9]+}}, i32 {{[0-9]+}}, metadata !{{[0-9]+}}, metadata ![[PRODUCT:[0-9]+]]}
+// CHECK-DAG: [[PRODUCT]] = metadata !{i32 {{.*}}, i32 16, metadata !{{.*}}, null}
+// CHECK-DAG: ![[Y_DI]] = metadata !{i32 {{[0-9]+}}, i32 {{[0-9]+}}, metadata !{{[0-9]+}}, metadata ![[PRODUCT]]}
diff --git a/test/CodeGenCXX/debug-info-scope.cpp b/test/CodeGenCXX/debug-info-scope.cpp
new file mode 100644
index 0000000..557ee31
--- /dev/null
+++ b/test/CodeGenCXX/debug-info-scope.cpp
@@ -0,0 +1,32 @@
+// RUN: %clang_cc1 -g -emit-llvm %s -o -| FileCheck %s
+//
+// Two variables with the same name in subsequent if staments need to be in separate scopes.
+//
+// rdar://problem/14024005
+//
+
+int printf(const char*, ...);
+
+char *return_char (int input)
+{
+ if (input%2 == 0)
+ return "I am even.\n";
+ else
+ return "I am odd.\n";
+}
+
+int main2() {
+// CHECK: [ DW_TAG_auto_variable ] [ptr] [line [[@LINE+2]]]
+// CHECK metadata !{i32 {{.*}}, metadata !{{.*}}, i32 [[@LINE+1]], {{.*}}} ; [ DW_TAG_lexical_block ]
+ if (char *ptr = return_char(1)) {
+ printf ("%s", ptr);
+ }
+// CHECK: [ DW_TAG_auto_variable ] [ptr] [line [[@LINE+2]]]
+// CHECK metadata !{i32 {{.*}}, metadata !{{.*}}, i32 [[@LINE+1]], {{.*}}} ; [ DW_TAG_lexical_block ]
+ if (char *ptr = return_char(2)) {
+ printf ("%s", ptr);
+ }
+ else printf ("%s", ptr);
+
+ return 0;
+}
diff --git a/test/CodeGenCXX/debug-info-static-member.cpp b/test/CodeGenCXX/debug-info-static-member.cpp
index 774f7b1..1ac235c 100644
--- a/test/CodeGenCXX/debug-info-static-member.cpp
+++ b/test/CodeGenCXX/debug-info-static-member.cpp
@@ -1,7 +1,9 @@
-// RUN: %clangxx -target x86_64-unknown-unknown -g -O0 %s -emit-llvm -S -o - | FileCheck %s
+// RUN: %clangxx -target x86_64-unknown-unknown -g %s -emit-llvm -S -o - | FileCheck %s
// PR14471
-
+enum X {
+ Y
+};
class C
{
static int a;
@@ -13,6 +15,7 @@ public:
static int c;
const static int const_c = 18;
int d;
+ static X x_a;
};
int C::a = 4;
@@ -30,12 +33,15 @@ int main()
// 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 !"_ZTS1X"} ; [ DW_TAG_enumeration_type ] [X]
+// CHECK: metadata !"_ZTS1C"} ; [ DW_TAG_class_type ] [C]
+// CHECK: ![[DECL_A:[0-9]+]] = 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 !"x_a", {{.*}} [ DW_TAG_member ] [x_a] {{.*}} [static]
+// CHECK: metadata !"a", {{.*}} @_ZN1C1aE, metadata ![[DECL_A]]} ; [ DW_TAG_variable ] [a] {{.*}} [def]
// 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-limit.cpp b/test/CodeGenCXX/debug-info-template-limit.cpp
index afad31b..c3e241e 100644
--- a/test/CodeGenCXX/debug-info-template-limit.cpp
+++ b/test/CodeGenCXX/debug-info-template-limit.cpp
@@ -1,8 +1,8 @@
// RUN: %clang -flimit-debug-info -emit-llvm -g -S %s -o - | FileCheck %s
// Check that this pointer type is TC<int>
-// CHECK: ![[LINE:[0-9]+]]} ; [ DW_TAG_pointer_type ]{{.*}}[from TC<int>]
-// CHECK-NEXT: ![[LINE]] ={{.*}}"TC<int>"
+// CHECK: ![[LINE:[0-9]+]] = {{.*}}"TC<int>", {{.*}} metadata !"_ZTS2TCIiE"} ; [ DW_TAG_class_type ]
+// CHECK: metadata !"_ZTS2TCIiE"} ; [ DW_TAG_pointer_type ]{{.*}}[from _ZTS2TCIiE]
template<typename T>
class TC {
diff --git a/test/CodeGenCXX/debug-info-template-member.cpp b/test/CodeGenCXX/debug-info-template-member.cpp
index 6be7f9b..9ac1bef 100644
--- a/test/CodeGenCXX/debug-info-template-member.cpp
+++ b/test/CodeGenCXX/debug-info-template-member.cpp
@@ -1,21 +1,78 @@
// RUN: %clang_cc1 -emit-llvm -g -triple x86_64-apple-darwin %s -o - | FileCheck %s
-class MyClass
-{
-public:
- int add2(int j)
- {
- return add<2>(j);
- }
-private:
- template <int i> int add(int j)
- {
- return i + j;
- }
+struct MyClass {
+ template <int i> int add(int j) {
+ return i + j;
+ }
+ virtual void func() {
+ }
};
-MyClass m;
+int add2(int x) {
+ return MyClass().add<2>(x);
+}
+
+inline int add3(int x) {
+ return MyClass().add<3>(x); // even though add<3> is ODR used, don't emit it since we don't codegen it
+}
+
+// CHECK: [[FOO_MEM:![0-9]*]], i32 0, null, null, metadata !"_ZTS3foo"} ; [ DW_TAG_structure_type ] [foo]
+// CHECK: [[FOO_MEM]] = metadata !{metadata [[FOO_FUNC:![0-9]*]]}
+// CHECK: [[FOO_FUNC]] = {{.*}}, metadata !"_ZN3foo4funcEN5outerIS_E5innerE", i32 {{[0-9]*}}, metadata [[FOO_FUNC_TYPE:![0-9]*]], {{.*}} ; [ DW_TAG_subprogram ] {{.*}} [func]
+// CHECK: [[FOO_FUNC_TYPE]] = {{.*}}, metadata [[FOO_FUNC_PARAMS:![0-9]*]], i32 0, null, null, null} ; [ DW_TAG_subroutine_type ]
+// CHECK: [[FOO_FUNC_PARAMS]] = metadata !{null, metadata !{{[0-9]*}}, metadata [[OUTER_FOO_INNER:![0-9]*]]}
+// CHECK: [[OUTER_FOO_INNER]] = {{.*}} ; [ DW_TAG_structure_type ] [inner]
+
+// CHECK: metadata [[VIRT_MEM:![0-9]*]], i32 0, metadata !"_ZTS4virtI4elemE", metadata [[VIRT_TEMP_PARAM:![0-9]*]], metadata !"_ZTS4virtI4elemE"} ; [ DW_TAG_structure_type ] [virt<elem>] {{.*}} [def]
+// CHECK: [[VIRT_TEMP_PARAM]] = metadata !{metadata [[VIRT_T:![0-9]*]]}
+// CHECK: [[VIRT_T]] = {{.*}}, metadata !"T", metadata !"_ZTS4elem", {{.*}} ; [ DW_TAG_template_type_parameter ]
+
+// CHECK: [[C:![0-9]*]] = {{.*}}, metadata [[C_MEM:![0-9]*]], i32 0, metadata !"_ZTS7MyClass", null, metadata !"_ZTS7MyClass"} ; [ DW_TAG_structure_type ] [MyClass]
+// CHECK: [[C_MEM]] = metadata !{metadata [[C_VPTR:![0-9]*]], metadata [[C_ADD:![0-9]*]], metadata [[C_FUNC:![0-9]*]], metadata [[C_CTOR:![0-9]*]]}
+// CHECK: [[C_VPTR]] = {{.*}} ; [ DW_TAG_member ] [_vptr$MyClass]
+
+// CHECK: [[C_ADD]] = {{.*}} ; [ DW_TAG_subprogram ] [line 4] [add<2>]
+// CHECK: [[C_FUNC]] = {{.*}} ; [ DW_TAG_subprogram ] [line 7] [func]
+// CHECK: [[C_CTOR]] = {{.*}} ; [ DW_TAG_subprogram ] [line 0] [MyClass]
+
+// CHECK: [[ELEM:![0-9]*]] = {{.*}}, metadata [[ELEM_MEM:![0-9]*]], i32 0, null, null, metadata !"_ZTS4elem"} ; [ DW_TAG_structure_type ] [elem] {{.*}} [def]
+// CHECK: [[ELEM_MEM]] = metadata !{metadata [[ELEM_X:![0-9]*]]}
+// CHECK: [[ELEM_X]] = {{.*}} ; [ DW_TAG_member ] [x] {{.*}} [static] [from _ZTS4virtI4elemE]
+
+template<typename T>
+struct outer {
+ struct inner {
+ int i;
+ };
+};
+
+struct foo {
+ void func(outer<foo>::inner);
+};
+
+inline void func() {
+ // require 'foo' to be complete before the emission of 'inner' so that, when
+ // constructing the context chain for 'x' we emit the full definition of
+ // 'foo', which requires the definition of 'inner' again
+ foo f;
+}
+
+outer<foo>::inner x;
+
+// CHECK: metadata [[OUTER_FOO_INNER]], i32 {{[0-9]*}}, i32 {{[0-9]*}}, %"struct.outer<foo>::inner"* @x, {{.*}} ; [ DW_TAG_variable ] [x]
+
+template <typename T>
+struct virt {
+ T* values;
+ virtual ~virt();
+};
+struct elem {
+ static virt<elem> x; // ensure that completing 'elem' will require/completing 'virt<elem>'
+};
+inline void f1() {
+ elem e; // ensure 'elem' is required to be complete when it is emitted as a template argument for 'virt<elem>'
+};
+void f2() {
+ virt<elem> d; // emit 'virt<elem>'
+}
-// 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 335c8ab..740f7bf 100644
--- a/test/CodeGenCXX/debug-info-template-quals.cpp
+++ b/test/CodeGenCXX/debug-info-template-quals.cpp
@@ -15,13 +15,13 @@ void foo (const char *c) {
str.assign(c, str);
}
-// CHECK: [[P:.*]] = {{.*}}, metadata [[CON:![0-9]*]]} ; [ DW_TAG_pointer_type ] [line 0, size 64, align 64, offset 0] [from ]
+// CHECK: [[BS:.*]] = {{.*}} ; [ DW_TAG_structure_type ] [basic_string<char>] [line 4, size 8, align 8, offset 0] [def] [from ]
+// CHECK: [[TYPE:![0-9]*]] = metadata !{i32 {{.*}}, metadata [[ARGS:.*]], i32 0, null, null, null} ; [ DW_TAG_subroutine_type ]
+// CHECK: [[ARGS]] = metadata !{metadata !{{.*}}, metadata !{{.*}}, metadata [[P:![0-9]*]], metadata [[R:.*]]}
+// 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>]
+// CHECK: [[CON2]] = {{.*}}, metadata !"_ZTS12basic_stringIcE"} ; [ DW_TAG_const_type ] [line 0, size 0, align 0, offset 0] [from _ZTS12basic_stringIcE]
+// CHECK: {{.*}} metadata [[TYPE]], {{.*}}, metadata !{{[0-9]*}}, metadata !{{[0-9]*}}, i32 8} ; [ DW_TAG_subprogram ] [line 7] [def] [scope 8] [assign]
diff --git a/test/CodeGenCXX/debug-info-template.cpp b/test/CodeGenCXX/debug-info-template.cpp
index 9d52159..f58973b 100644
--- a/test/CodeGenCXX/debug-info-template.cpp
+++ b/test/CodeGenCXX/debug-info-template.cpp
@@ -1,46 +1,116 @@
-// RUN: %clang -emit-llvm -g -S %s -o - | FileCheck %s
+// RUN: %clang -S -emit-llvm -target x86_64-unknown_unknown -g %s -o - -std=c++11 | FileCheck %s
-//CHECK: TC<int>
-//CHECK: DW_TAG_template_type_parameter
+// CHECK: {{.*}}, i1 false, metadata !"", i32 0, metadata !{{[0-9]]*}}, metadata [[RETAIN:![0-9]*]], {{.*}} ; [ DW_TAG_compile_unit ]
+// CHECK: [[EMPTY:![0-9]*]] = metadata !{i32 0}
+// CHECK: [[RETAIN]] = metadata !{metadata !{{[0-9]]*}}, metadata [[FOO:![0-9]*]],
-template<typename T>
-class TC {
-public:
- TC(const TC &) {}
- TC() {}
-};
-TC<int> tci;
+// CHECK: [[TC:![0-9]*]] = {{.*}}, metadata [[TCARGS:![0-9]*]], metadata !"{{.*}}"} ; [ DW_TAG_structure_type ] [TC<unsigned int, 2, &glb, &foo::e, &foo::f, &func, tmpl_impl, 1, 2, 3>]
+// CHECK: [[TCARGS]] = metadata !{metadata [[TCARG1:![0-9]*]], metadata [[TCARG2:![0-9]*]], metadata [[TCARG3:![0-9]*]], metadata [[TCARG4:![0-9]*]], metadata [[TCARG5:![0-9]*]], metadata [[TCARG6:![0-9]*]], metadata [[TCARG7:![0-9]*]], metadata [[TCARG8:![0-9]*]]}
+//
+// We seem to be missing file/line/col info on template value parameters -
+// metadata supports it but it's not populated. GCC doesn't emit it either,
+// perhaps we should just drop it from the metadata.
+//
+// CHECK: [[TCARG1]] = {{.*}}metadata !"T", metadata [[UINT:![0-9]*]], {{.*}} ; [ DW_TAG_template_type_parameter ]
+// CHECK: [[UINT:![0-9]*]] = {{.*}} ; [ DW_TAG_base_type ] [unsigned int]
+// CHECK: [[TCARG2]] = {{.*}}metadata !"", metadata [[UINT]], i32 2, {{.*}} ; [ DW_TAG_template_value_parameter ]
+// CHECK: [[TCARG3]] = {{.*}}metadata !"x", metadata [[INTPTR:![0-9]*]], i32* @glb, {{.*}} ; [ DW_TAG_template_value_parameter ]
+// CHECK: [[INTPTR]] = {{.*}}, metadata [[INT:![0-9]*]]} ; [ DW_TAG_pointer_type ] [line 0, size 64, align 64, offset 0] [from int]
+// CHECK: [[INT]] = {{.*}} ; [ DW_TAG_base_type ] [int]
+// CHECK: [[TCARG4]] = {{.*}}metadata !"a", metadata [[MEMINTPTR:![0-9]*]], i64 8, {{.*}} ; [ DW_TAG_template_value_parameter ]
+// CHECK: [[MEMINTPTR]] = {{.*}}, metadata !"_ZTS3foo"} ; [ DW_TAG_ptr_to_member_type ] {{.*}}[from int]
+//
+// Currently Clang emits the pointer-to-member-function value, but LLVM doesn't
+// use it (GCC doesn't emit a value for pointers to member functions either - so
+// it's not clear what, if any, format would be acceptable to GDB)
+//
+// CHECK: [[TCARG5]] = {{.*}}metadata !"b", metadata [[MEMFUNPTR:![0-9]*]], { i64, i64 } { i64 ptrtoint (void (%struct.foo*)* @_ZN3foo1fEv to i64), i64 0 }, {{.*}} ; [ DW_TAG_template_value_parameter ]
+// CHECK: [[MEMFUNPTR]] = {{.*}}, metadata [[FTYPE:![0-9]*]], metadata !"_ZTS3foo"} ; [ DW_TAG_ptr_to_member_type ]
+// CHECK: [[FTYPE]] = {{.*}}, metadata [[FARGS:![0-9]*]], i32 0, null, null, null} ; [ DW_TAG_subroutine_type ]
+// CHECK: [[FARGS]] = metadata !{null, metadata [[FARG1:![0-9]*]]}
+// CHECK: [[FARG1]] = {{.*}} ; [ DW_TAG_pointer_type ] [line 0, size 64, align 64, offset 0] [artificial] [from _ZTS3foo]
+//
+// CHECK: [[TCARG6]] = {{.*}}metadata !"f", metadata [[FUNPTR:![0-9]*]], void ()* @_Z4funcv, {{.*}} ; [ DW_TAG_template_value_parameter ]
+// CHECK: [[FUNPTR]] = {{.*}}, metadata [[FUNTYPE:![0-9]*]]} ; [ DW_TAG_pointer_type ]
+// CHECK: [[FUNTYPE]] = {{.*}}, metadata [[FUNARGS:![0-9]*]], i32 0, null, null, null} ; [ DW_TAG_subroutine_type ]
+// CHECK: [[FUNARGS]] = metadata !{null}
+// CHECK: [[TCARG7]] = {{.*}}metadata !"tmpl", null, metadata !"tmpl_impl", {{.*}} ; [ DW_TAG_GNU_template_template_param ]
+// CHECK: [[TCARG8]] = {{.*}}metadata !"Is", null, metadata [[TCARG8_VALS:![0-9]*]], {{.*}} ; [ DW_TAG_GNU_template_parameter_pack ]
+// CHECK: [[TCARG8_VALS]] = metadata !{metadata [[TCARG8_1:![0-9]*]], metadata [[TCARG8_2:![0-9]*]], metadata [[TCARG8_3:![0-9]*]]}
+// CHECK: [[TCARG8_1]] = {{.*}}metadata !"", metadata [[INT]], i32 1, {{.*}} ; [ DW_TAG_template_value_parameter ]
+// CHECK: [[TCARG8_2]] = {{.*}}metadata !"", metadata [[INT]], i32 2, {{.*}} ; [ DW_TAG_template_value_parameter ]
+// CHECK: [[TCARG8_3]] = {{.*}}metadata !"", metadata [[INT]], i32 3, {{.*}} ; [ DW_TAG_template_value_parameter ]
+//
+// We could just emit a declaration of 'foo' here, rather than the entire
+// definition (same goes for any time we emit a member (function or data)
+// pointer type)
+// CHECK: [[FOO]] = {{.*}}, metadata !"_ZTS3foo"} ; [ DW_TAG_structure_type ] [foo]
+// CHECK: metadata !"f", metadata !"_ZN3foo1fEv", i32 {{[0-9]*}}, metadata [[FTYPE:![0-9]*]],
+//
+
+
+// CHECK: [[TCNESTED:![0-9]*]] = metadata !{i32 {{[0-9]*}}, metadata !{{[0-9]*}}, metadata !"_ZTS2TCIjLj2EXadL_Z3glbEEXadL_ZN3foo1eEEEXadL_ZNS0_1fEvEEXadL_Z4funcvEE9tmpl_implJLi1ELi2ELi3EEE", {{.*}} ; [ DW_TAG_structure_type ] [nested]
+// CHECK: [[TCNT:![0-9]*]] = {{.*}}, metadata [[TCNARGS:![0-9]*]], metadata !"{{.*}}"} ; [ DW_TAG_structure_type ] [TC<int, -3, nullptr, nullptr, nullptr, nullptr, tmpl_impl>]
+// CHECK: [[TCNARGS]] = metadata !{metadata [[TCNARG1:![0-9]*]], metadata [[TCNARG2:![0-9]*]], metadata [[TCNARG3:![0-9]*]], metadata [[TCNARG4:![0-9]*]], metadata [[TCNARG5:![0-9]*]], metadata [[TCNARG6:![0-9]*]], metadata [[TCARG7:![0-9]*]], metadata [[TCNARG8:![0-9]*]]}
+// CHECK: [[TCNARG1]] = {{.*}}metadata !"T", metadata [[INT]], {{.*}} ; [ DW_TAG_template_type_parameter ]
+// CHECK: [[TCNARG2]] = {{.*}}metadata !"", metadata [[INT]], i32 -3, {{.*}} ; [ DW_TAG_template_value_parameter ]
+// CHECK: [[TCNARG3]] = {{.*}}metadata !"x", metadata [[INTPTR]], i8 0, {{.*}} ; [ DW_TAG_template_value_parameter ]
+
+// The interesting null pointer: -1 for member data pointers (since they are
+// just an offset in an object, they can be zero and non-null for the first
+// member)
+
+// CHECK: [[TCNARG4]] = {{.*}}metadata !"a", metadata [[MEMINTPTR]], i64 -1, {{.*}} ; [ DW_TAG_template_value_parameter ]
+//
+// In some future iteration we could possibly emit the value of a null member
+// function pointer as '{ i64, i64 } zeroinitializer' as it may be handled
+// naturally from the LLVM CodeGen side once we decide how to handle non-null
+// member function pointers. For now, it's simpler just to emit the 'i8 0'.
+//
+// CHECK: [[TCNARG5]] = {{.*}}metadata !"b", metadata [[MEMFUNPTR]], i8 0, {{.*}} ; [ DW_TAG_template_value_parameter ]
+// CHECK: [[TCNARG6]] = {{.*}}metadata !"f", metadata [[FUNPTR]], i8 0, {{.*}} ; [ DW_TAG_template_value_parameter ]
+// CHECK: [[TCNARG8]] = {{.*}}metadata !"Is", null, metadata [[EMPTY]], {{.*}} ; [ DW_TAG_GNU_template_parameter_pack ]
+
+// CHECK: metadata [[PTOARGS:![0-9]*]], metadata !"{{.*}}"} ; [ DW_TAG_structure_type ] [PaddingAtEndTemplate<&PaddedObj>]
+// CHECK: [[PTOARGS]] = metadata !{metadata [[PTOARG1:![0-9]*]]}
+// CHECK: [[PTOARG1]] = {{.*}}metadata !"", metadata [[CONST_PADDINGATEND_PTR:![0-9]*]], { i32, i8, [3 x i8] }* @PaddedObj, {{.*}} ; [ DW_TAG_template_value_parameter ]
+// CHECK: [[CONST_PADDINGATEND_PTR]] = {{.*}} ; [ DW_TAG_pointer_type ] [line 0, size 64, align 64, offset 0] [from _ZTS12PaddingAtEnd]
-//CHECK: TU<2>
-//CHECK: DW_TAG_template_value_parameter
-template<unsigned >
-class TU {
- int b;
+// CHECK: metadata [[TCNESTED]], i32 0, i32 1, %"struct.TC<unsigned int, 2, &glb, &foo::e, &foo::f, &func, tmpl_impl, 1, 2, 3>::nested"* @tci, null} ; [ DW_TAG_variable ] [tci]
+
+// CHECK: metadata [[TCNT:![0-9]*]], i32 0, i32 1, %struct.TC* @tcn, null} ; [ DW_TAG_variable ] [tcn]
+struct foo {
+ char pad[8]; // make the member pointer to 'e' a bit more interesting (nonzero)
+ int e;
+ void f();
+};
+
+template<typename T, T, int *x, int foo::*a, void (foo::*b)(), void (*f)(), template<typename> class tmpl, int ...Is>
+struct TC {
+ struct nested {
+ };
};
-TU<2> u2;
+int glb;
+void func();
-// PR9600
-template<typename T> class vector {};
-class Foo;
-typedef vector<Foo*> FooVector[3];
-struct Test {
- virtual void foo(FooVector *);
+template<typename>
+struct tmpl_impl {
};
-static Test test;
-// PR9608
-template <int i> struct TheTemplate {
- struct Empty2 {};
- typedef const Empty2 DependentType[i];
- TheTemplate() {}
-};
+TC<unsigned, 2, &glb, &foo::e, &foo::f, &func, tmpl_impl, 1, 2, 3>::nested tci;
+TC<int, -3, nullptr, nullptr, nullptr, nullptr, tmpl_impl> tcn;
-class TheTemplateTest : public TheTemplate<42> {
- TheTemplateTest();
- void method(const TheTemplate<42>::DependentType *) {}
-};
+struct PaddingAtEnd {
+ int i;
+ char c;
+};
+
+PaddingAtEnd PaddedObj = {};
-TheTemplateTest::TheTemplateTest() : TheTemplate<42>() {}
+template <const PaddingAtEnd *>
+struct PaddingAtEndTemplate {
+};
+PaddingAtEndTemplate<&PaddedObj> PaddedTemplateObj;
diff --git a/test/CodeGenCXX/debug-info-thunk.cpp b/test/CodeGenCXX/debug-info-thunk.cpp
index 394ebd8..2a50895 100644
--- a/test/CodeGenCXX/debug-info-thunk.cpp
+++ b/test/CodeGenCXX/debug-info-thunk.cpp
@@ -14,4 +14,4 @@ struct C : A, B {
void C::f() { }
-// CHECK: [ DW_TAG_subprogram ] [line 15] [def] [_ZThn{{4|8}}_N1C1fEv]
+// CHECK: metadata !"_ZThn{{4|8}}_N1C1fEv", i32 15, {{.*}} ; [ DW_TAG_subprogram ] [line 15] [def]{{$}}
diff --git a/test/CodeGenCXX/debug-info-union-template.cpp b/test/CodeGenCXX/debug-info-union-template.cpp
index f5e6e14..570520d 100644
--- a/test/CodeGenCXX/debug-info-union-template.cpp
+++ b/test/CodeGenCXX/debug-info-union-template.cpp
@@ -10,6 +10,6 @@ namespace PR15637 {
Value<float> f;
}
-// CHECK: {{.*}}, metadata !"Value<float>", {{.*}}, null, metadata [[TTPARAM:.*]]} ; [ DW_TAG_union_type ] [Value<float>]
+// CHECK: {{.*}}, metadata !"Value<float>", {{.*}}, null, metadata [[TTPARAM:.*]], metadata !"_ZTSN7PR156375ValueIfEE"} ; [ 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-uuid.cpp b/test/CodeGenCXX/debug-info-uuid.cpp
new file mode 100644
index 0000000..a57e2f0
--- /dev/null
+++ b/test/CodeGenCXX/debug-info-uuid.cpp
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 -emit-llvm -fms-extensions -triple=x86_64-pc-win32 -cxx-abi microsoft -g %s -o - -std=c++11 | FileCheck %s
+// RUN: not %clang_cc1 -emit-llvm -fms-extensions -triple=x86_64-unknown-unknown -g %s -o - -std=c++11 2>&1 | FileCheck %s --check-prefix=CHECK-ITANIUM
+
+// CHECK: metadata [[TGIARGS:![0-9]*]], null} ; [ DW_TAG_structure_type ] [tmpl_guid<&__uuidof(uuid)>]
+// CHECK: [[TGIARGS]] = metadata !{metadata [[TGIARG1:![0-9]*]]}
+// CHECK: [[TGIARG1]] = {{.*}}metadata !"", metadata [[CONST_GUID_PTR:![0-9]*]], { i32, i16, i16, [8 x i8] }* @_GUID_12345678_1234_1234_1234_1234567890ab, {{.*}} ; [ DW_TAG_template_value_parameter ]
+// CHECK: [[CONST_GUID_PTR]] = {{.*}}, metadata [[CONST_GUID:![0-9]*]]} ; [ DW_TAG_pointer_type ] [line 0, size 64, align 64, offset 0] [from ]
+// CHECK: [[CONST_GUID]] = {{.*}}, metadata [[GUID:![0-9]*]]} ; [ DW_TAG_const_type ] [line 0, size 0, align 0, offset 0] [from _GUID]
+// CHECK: [[GUID]] = {{.*}} ; [ DW_TAG_structure_type ] [_GUID]
+
+// CHECK-ITANIUM: error: cannot yet mangle expression type CXXUuidofExpr
+
+struct _GUID;
+template <const _GUID *>
+struct tmpl_guid {
+};
+
+struct __declspec(uuid("{12345678-1234-1234-1234-1234567890ab}")) uuid;
+tmpl_guid<&__uuidof(uuid)> tgi;
diff --git a/test/CodeGenCXX/debug-info-zero-length-arrays.cpp b/test/CodeGenCXX/debug-info-zero-length-arrays.cpp
index fb47022..1017965 100644
--- a/test/CodeGenCXX/debug-info-zero-length-arrays.cpp
+++ b/test/CodeGenCXX/debug-info-zero-length-arrays.cpp
@@ -7,6 +7,6 @@ class A {
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: metadata [[ELEM_TYPE:![0-9]*]], i32 0, null, null, null} ; [ 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-info.cpp b/test/CodeGenCXX/debug-info.cpp
index 33b5278..93a4fe3 100644
--- a/test/CodeGenCXX/debug-info.cpp
+++ b/test/CodeGenCXX/debug-info.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm-only -g %s
+// RUN: %clang_cc1 -triple x86_64-none-linux-gnu -emit-llvm -g %s -o - | FileCheck %s
template<typename T> struct Identity {
typedef T Type;
};
@@ -67,3 +67,54 @@ class Cls {
Cls obj;
}
+
+namespace pr14763 {
+struct foo {
+ foo(const foo&);
+};
+
+foo func(foo f) {
+ return f; // reference 'f' for now because otherwise we hit another bug
+}
+
+// CHECK: [[FOO:![0-9]*]] = metadata !{i32 {{[0-9]*}}, metadata !{{[0-9]*}}, metadata [[PR14763:![0-9]*]], {{.*}} ; [ DW_TAG_structure_type ] [foo]
+// CHECK: [[PR14763]] = {{.*}} ; [ DW_TAG_namespace ] [pr14763]
+// CHECK: [[INCTYPE:![0-9]*]] = {{.*}} ; [ DW_TAG_structure_type ] [incomplete]{{.*}} [decl]
+// CHECK: metadata [[A_MEM:![0-9]*]], i32 0, null, null, metadata !"_ZTSN7pr162141aE"} ; [ DW_TAG_structure_type ] [a]
+// CHECK: [[A_MEM]] = metadata !{metadata [[A_I:![0-9]*]]}
+// CHECK: [[A_I]] = {{.*}} ; [ DW_TAG_member ] [i] {{.*}} [from int]
+// CHECK: ; [ DW_TAG_structure_type ] [b] {{.*}}[decl]
+
+// CHECK: [[FUNC:![0-9]*]] = {{.*}} metadata !"_ZN7pr147634funcENS_3fooE", i32 {{[0-9]*}}, metadata [[FUNC_TYPE:![0-9]*]], {{.*}} ; [ DW_TAG_subprogram ] {{.*}} [def] [func]
+}
+
+namespace pr9608 { // also pr9600
+struct incomplete;
+incomplete (*x)[3];
+// CHECK: metadata [[INCARRAYPTR:![0-9]*]], i32 0, i32 1, [3 x i8]** @_ZN6pr96081xE, null} ; [ DW_TAG_variable ] [x]
+// CHECK: [[INCARRAYPTR]] = {{.*}}metadata [[INCARRAY:![0-9]*]]} ; [ DW_TAG_pointer_type ]
+// CHECK: [[INCARRAY]] = {{.*}}metadata !"_ZTSN6pr960810incompleteE", metadata {{![0-9]*}}, i32 0, null, null, null} ; [ DW_TAG_array_type ] [line 0, size 0, align 0, offset 0] [from _ZTSN6pr960810incompleteE]
+}
+
+// For some reason the argument for PR14763 ended up all the way down here
+// CHECK: = metadata !{i32 {{[0-9]*}}, metadata [[FUNC]], {{.*}}, metadata [[FOO]], i32 8192, i32 0} ; [ DW_TAG_arg_variable ] [f]
+
+namespace pr16214 {
+struct a {
+ int i;
+};
+
+typedef a at;
+
+struct b {
+};
+
+typedef b bt;
+
+void func() {
+ at a_inst;
+ bt *b_ptr_inst;
+ const bt *b_cnst_ptr_inst;
+}
+
+}
diff --git a/test/CodeGenCXX/debug-lambda-expressions.cpp b/test/CodeGenCXX/debug-lambda-expressions.cpp
index 39c9a44..0b087360 100644
--- a/test/CodeGenCXX/debug-lambda-expressions.cpp
+++ b/test/CodeGenCXX/debug-lambda-expressions.cpp
@@ -12,7 +12,7 @@ int b(int x) { return [x]{return x;}(); }
int c(int x) { return [&x]{return x;}(); }
struct D { D(); D(const D&); int x; };
-int d(int x) { D y[10]; [x,y] { return y[x].x; }(); }
+int d(int x) { D y[10]; return [x,y] { return y[x].x; }(); }
// Randomness for file. -- 6
// CHECK: [[FILE:.*]] = {{.*}} [ DW_TAG_file_type ] [{{.*}}debug-lambda-expressions.cpp]
@@ -30,42 +30,38 @@ int d(int x) { D y[10]; [x,y] { return y[x].x; }(); }
// CHECK: [[D_FUNC:.*]] = {{.*}} [ DW_TAG_subprogram ] [line [[D_LINE:.*]]] [def] [d]
// Back to D. -- 24
-// 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: [[LAM_D:.*]] = {{.*}}, metadata [[D_FUNC]], {{.*}}, metadata [[LAM_D_ARGS:.*]], i32 0, null, 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:.*]]}
// 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 [[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:.*]]}
+// CHECK: [[LAM_C:.*]] = {{.*}}, metadata [[C_FUNC]], {{.*}}, metadata [[LAM_C_ARGS:.*]], i32 0, null, null, null} ; [ DW_TAG_class_type ] [line [[C_LINE]],
+// CHECK: [[LAM_C_ARGS]] = metadata !{metadata [[CAP_C:.*]], metadata [[CON_LAM_C:.*]]}
// Ignoring the member type for now.
// 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 [[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: [[LAM_B:.*]] = {{.*}}, metadata [[B_FUNC]], {{.*}}, metadata [[LAM_B_ARGS:.*]], i32 0, null, null, null} ; [ DW_TAG_class_type ] [line [[B_LINE]],
+// CHECK: [[LAM_B_ARGS]] = metadata !{metadata [[CAP_B:.*]], metadata [[CON_LAM_B:.*]]}
// 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 [[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: [[LAM_A:.*]] = {{.*}}, metadata [[A_FUNC]], {{.*}}, metadata [[LAM_A_ARGS:.*]], i32 0, null, null, null} ; [ DW_TAG_class_type ] [line [[A_LINE]],
+// CHECK: [[LAM_A_ARGS]] = metadata !{metadata [[CON_LAM_A:.*]]}
// 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 [[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 !{{.*}}}
+// CHECK: [[CVAR_T]] = {{.*}}, metadata ![[CVAR_ARGS:.*]], i32 0, null, null, null} ; [ DW_TAG_class_type ] [line [[CVAR_LINE]],
+// CHECK: [[CVAR_ARGS]] = metadata !{metadata !{{.*}}}
// VAR:
// 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 !{{.*}}}
+// CHECK: [[VAR_T]] = {{.*}}, metadata [[VAR_ARGS:![0-9]*]], i32 0, null, null, null} ; [ DW_TAG_class_type ] [line [[VAR_LINE]],
+// CHECK: [[VAR_ARGS]] = metadata !{metadata !{{.*}}}
diff --git a/test/CodeGenCXX/decl-ref-init.cpp b/test/CodeGenCXX/decl-ref-init.cpp
index a066fbb..1a82ee2 100644
--- a/test/CodeGenCXX/decl-ref-init.cpp
+++ b/test/CodeGenCXX/decl-ref-init.cpp
@@ -1,8 +1,8 @@
// REQUIRES: x86-registered-target,x86-64-registered-target
// RUN: %clang_cc1 -triple x86_64-apple-darwin -S %s -o %t-64.s
-// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s
+// RUN: FileCheck -check-prefix CHECK-LP64 --input-file=%t-64.s %s
// RUN: %clang_cc1 -triple i386-apple-darwin -S %s -o %t-32.s
-// RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s
+// RUN: FileCheck -check-prefix CHECK-LP32 --input-file=%t-32.s %s
struct A {};
diff --git a/test/CodeGenCXX/default-arg-temps.cpp b/test/CodeGenCXX/default-arg-temps.cpp
index 3d741d5..4375600 100644
--- a/test/CodeGenCXX/default-arg-temps.cpp
+++ b/test/CodeGenCXX/default-arg-temps.cpp
@@ -13,7 +13,7 @@ public:
X(const X&, const T& t = T());
};
-// CHECK: define void @_Z1gv()
+// CHECK-LABEL: define void @_Z1gv()
void g() {
// CHECK: call void @_ZN1TC1Ev([[T:%.*]]* [[AGG1:%.*]])
// CHECK-NEXT: call void @_Z1fRK1T([[T]]* [[AGG1]])
@@ -41,7 +41,7 @@ void g() {
class obj{ int a; float b; double d; };
-// CHECK: define void @_Z1hv()
+// CHECK-LABEL: define void @_Z1hv()
void h() {
// CHECK: call void @llvm.memset.p0i8.i64(
obj o = obj();
@@ -61,7 +61,7 @@ namespace test1 {
C c;
A a;
- // CHECK: define linkonce_odr void @_ZN5test11DC2Ev(%"struct.test1::D"* %this) unnamed_addr
+ // CHECK-LABEL: define linkonce_odr void @_ZN5test11DC2Ev(%"struct.test1::D"* %this) unnamed_addr
// CHECK: call void @_ZN5test11BC1Ev(
// CHECK-NEXT: call void @_ZN5test11CC1ERKNS_1BE(
// CHECK-NEXT: call void @_ZN5test11BD1Ev(
diff --git a/test/CodeGenCXX/default-arguments.cpp b/test/CodeGenCXX/default-arguments.cpp
index 206d4d6..83cae3a 100644
--- a/test/CodeGenCXX/default-arguments.cpp
+++ b/test/CodeGenCXX/default-arguments.cpp
@@ -26,7 +26,7 @@ struct B {
B(const A1& = A1(), const A2& = A2());
};
-// CHECK: define void @_Z2f1v()
+// CHECK-LABEL: define void @_Z2f1v()
void f1() {
// CHECK: call void @_ZN2A1C1Ev(
@@ -42,10 +42,10 @@ struct C {
C();
};
-// CHECK: define void @_ZN1CC1Ev(%struct.C* %this) unnamed_addr
+// CHECK-LABEL: define void @_ZN1CC1Ev(%struct.C* %this) unnamed_addr
// CHECK: call void @_ZN1CC2Ev(
-// CHECK: define void @_ZN1CC2Ev(%struct.C* %this) unnamed_addr
+// CHECK-LABEL: define void @_ZN1CC2Ev(%struct.C* %this) unnamed_addr
// CHECK: call void @_ZN2A1C1Ev(
// CHECK: call void @_ZN2A2C1Ev(
// CHECK: call void @_ZN1BC1ERK2A1RK2A2(
@@ -53,7 +53,7 @@ struct C {
// CHECK: call void @_ZN2A1D1Ev
C::C() { }
-// CHECK: define void @_Z2f3v()
+// CHECK-LABEL: define void @_Z2f3v()
void f3() {
// CHECK: call void @_ZN2A1C1Ev(
// CHECK: call void @_ZN2A2C1Ev(
diff --git a/test/CodeGenCXX/default-constructor-for-members.cpp b/test/CodeGenCXX/default-constructor-for-members.cpp
index 714811f..6065b49 100644
--- a/test/CodeGenCXX/default-constructor-for-members.cpp
+++ b/test/CodeGenCXX/default-constructor-for-members.cpp
@@ -1,8 +1,8 @@
// REQUIRES: x86-registered-target,x86-64-registered-target
// RUN: %clang_cc1 -triple x86_64-apple-darwin -S %s -o %t-64.s
-// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s
+// RUN: FileCheck -check-prefix CHECK-LP64 --input-file=%t-64.s %s
// RUN: %clang_cc1 -triple i386-apple-darwin -S %s -o %t-32.s
-// RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s
+// RUN: FileCheck -check-prefix CHECK-LP32 --input-file=%t-32.s %s
extern "C" int printf(...);
diff --git a/test/CodeGenCXX/default-constructor-template-member.cpp b/test/CodeGenCXX/default-constructor-template-member.cpp
index 0dd64df..2156964 100644
--- a/test/CodeGenCXX/default-constructor-template-member.cpp
+++ b/test/CodeGenCXX/default-constructor-template-member.cpp
@@ -5,6 +5,7 @@ struct B { A<int> x; };
void a() {
B b;
}
+
// CHECK: call {{.*}} @_ZN1BC1Ev
-// CHECK: define linkonce_odr {{.*}} @_ZN1BC1Ev(%struct.B* %this) unnamed_addr
+// CHECK: define linkonce_odr {{.*}} @_ZN1BC1Ev(%struct.B* {{.*}}%this) unnamed_addr
// CHECK: call {{.*}} @_ZN1AIiEC1Ev
diff --git a/test/CodeGenCXX/deferred-global-init.cpp b/test/CodeGenCXX/deferred-global-init.cpp
index 24c8c67..deb458f 100644
--- a/test/CodeGenCXX/deferred-global-init.cpp
+++ b/test/CodeGenCXX/deferred-global-init.cpp
@@ -7,10 +7,10 @@ void* bar() { return a; }
// CHECK: @_ZL1a = internal global i8* null
-// CHECK: define internal void @__cxx_global_var_init
+// CHECK-LABEL: define internal void @__cxx_global_var_init
// CHECK: load i8** @foo
// CHECK: ret void
-// CHECK: define internal void @_GLOBAL__I_a
+// CHECK-LABEL: define internal void @_GLOBAL__I_a
// CHECK: call void @__cxx_global_var_init()
// CHECK: ret void
diff --git a/test/CodeGenCXX/delayed-template-parsing.cpp b/test/CodeGenCXX/delayed-template-parsing.cpp
new file mode 100644
index 0000000..fa177d4
--- /dev/null
+++ b/test/CodeGenCXX/delayed-template-parsing.cpp
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -cxx-abi microsoft -fms-extensions -fdelayed-template-parsing -triple=i386-pc-win32 | FileCheck %s
+// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -cxx-abi microsoft -fms-extensions -fdelayed-template-parsing -triple=x86_64-pc-win32 | FileCheck -check-prefix X64 %s
+
+namespace ClassScopeSpecialization {
+ struct Type {
+ template <int i>
+ void Foo() {}
+ template <>
+ void Foo<0>() {}
+ };
+
+ void call() {
+ Type T;
+// CHECK: call {{.*}} @"\01??$Foo@$0A@@Type@ClassScopeSpecialization@@QAEXXZ"
+// X64: call {{.*}} @"\01??$Foo@$0A@@Type@ClassScopeSpecialization@@QEAAXXZ"
+ T.Foo<0>();
+ }
+}
diff --git a/test/CodeGenCXX/delete-two-arg.cpp b/test/CodeGenCXX/delete-two-arg.cpp
index b82e9ba..f8e6bff 100644
--- a/test/CodeGenCXX/delete-two-arg.cpp
+++ b/test/CodeGenCXX/delete-two-arg.cpp
@@ -1,11 +1,11 @@
-// RUN: %clang_cc1 -triple i686-pc-linux-gnu %s -o - -emit-llvm -verify | FileCheck %s
+// RUN: not %clang_cc1 -triple i686-pc-linux-gnu %s -o - -emit-llvm -verify | FileCheck %s
typedef __typeof(sizeof(int)) size_t;
namespace test1 {
struct A { void operator delete(void*,size_t); int x; };
- // CHECK: define void @_ZN5test11aEPNS_1AE(
+ // CHECK-LABEL: define void @_ZN5test11aEPNS_1AE(
void a(A *x) {
// CHECK: load
// CHECK-NEXT: icmp eq {{.*}}, null
@@ -35,7 +35,7 @@ namespace test2 {
return ::new A[10];
}
- // CHECK: define void @_ZN5test24testEPNS_1AE(
+ // CHECK-LABEL: define void @_ZN5test24testEPNS_1AE(
void test(A *p) {
// CHECK: [[P:%.*]] = alloca [[A]]*, align 4
// CHECK-NEXT: store [[A]]* {{%.*}}, [[A]]** [[P]], align 4
@@ -60,7 +60,7 @@ namespace test3 {
};
struct B : A {};
- // CHECK: define void @_ZN5test34testEv()
+ // CHECK-LABEL: define void @_ZN5test34testEv()
void test() {
// CHECK: call noalias i8* @_Znaj(i32 24)
// CHECK-NEXT: bitcast
diff --git a/test/CodeGenCXX/delete.cpp b/test/CodeGenCXX/delete.cpp
index 1299b29..cdd5a89 100644
--- a/test/CodeGenCXX/delete.cpp
+++ b/test/CodeGenCXX/delete.cpp
@@ -19,7 +19,7 @@ struct T {
int a;
};
-// CHECK: define void @_Z2t4P1T
+// CHECK-LABEL: define void @_Z2t4P1T
void t4(T *t) {
// CHECK: call void @_ZN1TD1Ev
// CHECK-NEXT: bitcast
@@ -46,7 +46,7 @@ namespace test0 {
~A() {}
};
- // CHECK: define void @_ZN5test04testEPNS_1AE(
+ // CHECK-LABEL: define void @_ZN5test04testEPNS_1AE(
void test(A *a) {
// CHECK: call void @_ZN5test01AD1Ev
// CHECK-NEXT: bitcast
@@ -54,8 +54,8 @@ namespace test0 {
delete a;
}
- // CHECK: define linkonce_odr void @_ZN5test01AD1Ev(%"struct.test0::A"* %this) unnamed_addr
- // CHECK: define linkonce_odr void @_ZN5test01AdlEPv
+ // CHECK-LABEL: define linkonce_odr void @_ZN5test01AD1Ev(%"struct.test0::A"* %this) unnamed_addr
+ // CHECK-LABEL: define linkonce_odr void @_ZN5test01AdlEPv
}
namespace test1 {
@@ -64,7 +64,7 @@ namespace test1 {
~A();
};
- // CHECK: define void @_ZN5test14testEPA10_A20_NS_1AE(
+ // CHECK-LABEL: define void @_ZN5test14testEPA10_A20_NS_1AE(
void test(A (*arr)[10][20]) {
delete [] arr;
// CHECK: icmp eq [10 x [20 x [[A:%.*]]]]* [[PTR:%.*]], null
@@ -88,7 +88,7 @@ namespace test1 {
}
namespace test2 {
- // CHECK: define void @_ZN5test21fEPb
+ // CHECK-LABEL: define void @_ZN5test21fEPb
void f(bool *b) {
// CHECK: call void @_ZdlPv(i8*
delete b;
@@ -111,7 +111,7 @@ namespace test4 {
void operator delete (void *);
};
- // CHECK: define void @_ZN5test421global_delete_virtualEPNS_1XE
+ // CHECK-LABEL: define void @_ZN5test421global_delete_virtualEPNS_1XE
void global_delete_virtual(X *xp) {
// Load the offset-to-top from the vtable and apply it.
// This has to be done first because the dtor can mess it up.
@@ -136,7 +136,7 @@ namespace test4 {
namespace test5 {
struct Incomplete;
- // CHECK: define void @_ZN5test523array_delete_incompleteEPNS_10IncompleteES1_
+ // CHECK-LABEL: define void @_ZN5test523array_delete_incompleteEPNS_10IncompleteES1_
void array_delete_incomplete(Incomplete *p1, Incomplete *p2) {
// CHECK: call void @_ZdlPv
delete p1;
@@ -145,4 +145,4 @@ namespace test5 {
}
}
-// CHECK: attributes [[NUW]] = { nounwind{{.*}} }
+// CHECK: attributes [[NUW]] = {{[{].*}} nounwind {{.*[}]}}
diff --git a/test/CodeGenCXX/derived-to-base-conv.cpp b/test/CodeGenCXX/derived-to-base-conv.cpp
index 9b15c68..675c50c 100644
--- a/test/CodeGenCXX/derived-to-base-conv.cpp
+++ b/test/CodeGenCXX/derived-to-base-conv.cpp
@@ -31,7 +31,7 @@ struct X {
void test0_helper(A);
void test0(X x) {
test0_helper(x);
- // CHECK: define void @_Z5test01X(
+ // CHECK-LABEL: define void @_Z5test01X(
// CHECK: [[TMP:%.*]] = alloca [[A:%.*]], align
// CHECK-NEXT: [[T0:%.*]] = call [[B:%.*]]* @_ZN1XcvR1BEv(
// CHECK-NEXT: [[T1:%.*]] = bitcast [[B]]* [[T0]] to [[A]]*
@@ -60,7 +60,7 @@ struct Derived : Base {
void test1_helper(Base);
void test1(Derived bb) {
- // CHECK: define void @_Z5test17Derived(
+ // CHECK-LABEL: define void @_Z5test17Derived(
// CHECK-NOT: call {{.*}} @_ZN4BasecvR7DerivedEv(
// CHECK: call void @_ZN4BaseC1ERKS_(
// CHECK-NOT: call {{.*}} @_ZN4BasecvR7DerivedEv(
@@ -75,7 +75,7 @@ class Test2a {};
class Test2b final : public virtual Test2a {};
void test2(Test2b &x) {
Test2a &y = x;
- // CHECK: define void @_Z5test2R6Test2b(
+ // CHECK-LABEL: define void @_Z5test2R6Test2b(
// CHECK: [[X:%.*]] = alloca [[B:%.*]]*, align 8
// CHECK-NEXT: [[Y:%.*]] = alloca [[A:%.*]]*, align 8
// CHECK-NEXT: store [[B]]* {{%.*}}, [[B]]** [[X]], align 8
diff --git a/test/CodeGenCXX/derived-to-virtual-base-class-calls-final.cpp b/test/CodeGenCXX/derived-to-virtual-base-class-calls-final.cpp
index 0e15302..f2ecfc1 100644
--- a/test/CodeGenCXX/derived-to-virtual-base-class-calls-final.cpp
+++ b/test/CodeGenCXX/derived-to-virtual-base-class-calls-final.cpp
@@ -9,7 +9,7 @@ struct D final : virtual C {
virtual void f();
};
-// CHECK: define %struct.B* @_Z1fR1D
+// CHECK-LABEL: define %struct.B* @_Z1fR1D
B &f(D &d) {
// CHECK-NOT: load i8**
return d;
diff --git a/test/CodeGenCXX/destructor-exception-spec.cpp b/test/CodeGenCXX/destructor-exception-spec.cpp
index 579daef..e111ba0 100644
--- a/test/CodeGenCXX/destructor-exception-spec.cpp
+++ b/test/CodeGenCXX/destructor-exception-spec.cpp
@@ -1,4 +1,6 @@
// RUN: %clang_cc1 -emit-llvm-only %s -std=c++11
+// RUN: %clang_cc1 -emit-llvm-only -fno-use-cxa-atexit %s -std=c++11
+// RUN: %clang_cc1 -cxx-abi microsoft -fno-rtti -emit-llvm-only %s -std=c++11
// PR13479: don't crash with -fno-exceptions.
namespace {
diff --git a/test/CodeGenCXX/destructors.cpp b/test/CodeGenCXX/destructors.cpp
index 7dc188b..799cca2 100644
--- a/test/CodeGenCXX/destructors.cpp
+++ b/test/CodeGenCXX/destructors.cpp
@@ -1,14 +1,10 @@
-// RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -emit-llvm -o - -mconstructor-aliases -fcxx-exceptions -fexceptions | FileCheck %s
+// RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -emit-llvm -o - -mconstructor-aliases -fcxx-exceptions -fexceptions -O1 -disable-llvm-optzns | FileCheck %s
-// CHECK: @_ZN5test01AD1Ev = alias {{.*}} @_ZN5test01AD2Ev
-// CHECK: @_ZN5test11MD2Ev = alias {{.*}} @_ZN5test11AD2Ev
-// CHECK: @_ZN5test11ND2Ev = alias {{.*}} @_ZN5test11AD2Ev
-// CHECK: @_ZN5test11OD2Ev = alias {{.*}} @_ZN5test11AD2Ev
-// CHECK: @_ZN5test11SD2Ev = alias bitcast {{.*}} @_ZN5test11AD2Ev
-
-// CHECK: @_ZN5test312_GLOBAL__N_11DD1Ev = alias internal {{.*}} @_ZN5test312_GLOBAL__N_11DD2Ev
-// CHECK: @_ZN5test312_GLOBAL__N_11DD2Ev = alias internal bitcast {{.*}} @_ZN5test312_GLOBAL__N_11CD2Ev
-// CHECK: @_ZN5test312_GLOBAL__N_11CD1Ev = alias internal {{.*}} @_ZN5test312_GLOBAL__N_11CD2Ev
+// CHECK-DAG: @_ZN5test01AD1Ev = alias {{.*}} @_ZN5test01AD2Ev
+// CHECK-DAG: @_ZN5test11MD2Ev = alias {{.*}} @_ZN5test11AD2Ev
+// CHECK-DAG: @_ZN5test11ND2Ev = alias {{.*}} @_ZN5test11AD2Ev
+// CHECK-DAG: @_ZN5test11OD2Ev = alias {{.*}} @_ZN5test11AD2Ev
+// CHECK-DAG: @_ZN5test11SD2Ev = alias bitcast {{.*}} @_ZN5test11AD2Ev
struct A {
int a;
@@ -40,13 +36,13 @@ namespace PR7526 {
struct allocator_derived : allocator { };
- // CHECK: define void @_ZN6PR75269allocatorD2Ev(%"struct.PR7526::allocator"* %this) unnamed_addr
+ // CHECK-LABEL: define void @_ZN6PR75263fooEv()
+ // CHECK: call void {{.*}} @_ZN6PR75269allocatorD2Ev
+
+ // CHECK-LABEL: define void @_ZN6PR75269allocatorD2Ev(%"struct.PR7526::allocator"* %this) unnamed_addr
// CHECK: call void @__cxa_call_unexpected
allocator::~allocator() throw() { foo(); }
- // CHECK: define linkonce_odr void @_ZN6PR752617allocator_derivedD1Ev(%"struct.PR7526::allocator_derived"* %this) unnamed_addr
- // CHECK-NOT: call void @__cxa_call_unexpected
- // CHECK: }
void foo() {
allocator_derived ad;
}
@@ -93,7 +89,7 @@ namespace test0 {
// complete destructor alias tested above
-// CHECK: define void @_ZN5test01AD2Ev(%"struct.test0::A"* %this) unnamed_addr
+// CHECK-LABEL: define void @_ZN5test01AD2Ev(%"struct.test0::A"* %this) unnamed_addr
// CHECK: invoke void @_ZN5test06MemberD1Ev
// CHECK: unwind label [[MEM_UNWIND:%[a-zA-Z0-9.]+]]
// CHECK: invoke void @_ZN5test04BaseD2Ev
@@ -106,7 +102,7 @@ namespace test0 {
B::~B() try { } catch (int i) {}
// It will suppress the delegation optimization here, though.
-// CHECK: define void @_ZN5test01BD1Ev(%"struct.test0::B"* %this) unnamed_addr
+// CHECK-LABEL: define void @_ZN5test01BD1Ev(%"struct.test0::B"* %this) unnamed_addr
// CHECK: invoke void @_ZN5test06MemberD1Ev
// CHECK: unwind label [[MEM_UNWIND:%[a-zA-Z0-9.]+]]
// CHECK: invoke void @_ZN5test04BaseD2Ev
@@ -114,7 +110,7 @@ namespace test0 {
// CHECK: invoke void @_ZN5test05VBaseD2Ev
// CHECK: unwind label [[VBASE_UNWIND:%[a-zA-Z0-9.]+]]
-// CHECK: define void @_ZN5test01BD2Ev(%"struct.test0::B"* %this, i8** %vtt) unnamed_addr
+// CHECK-LABEL: define void @_ZN5test01BD2Ev(%"struct.test0::B"* %this, i8** %vtt) unnamed_addr
// CHECK: invoke void @_ZN5test06MemberD1Ev
// CHECK: unwind label [[MEM_UNWIND:%[a-zA-Z0-9.]+]]
// CHECK: invoke void @_ZN5test04BaseD2Ev
@@ -142,24 +138,24 @@ namespace test1 {
O::~O() {} // alias tested above
struct P : NonEmpty, A { ~P(); };
- P::~P() {} // CHECK: define void @_ZN5test11PD2Ev(%"struct.test1::P"* %this) unnamed_addr
+ P::~P() {} // CHECK-LABEL: define void @_ZN5test11PD2Ev(%"struct.test1::P"* %this) unnamed_addr
struct Q : A, B { ~Q(); };
- Q::~Q() {} // CHECK: define void @_ZN5test11QD2Ev(%"struct.test1::Q"* %this) unnamed_addr
+ Q::~Q() {} // CHECK-LABEL: define void @_ZN5test11QD2Ev(%"struct.test1::Q"* %this) unnamed_addr
struct R : A { ~R(); };
- R::~R() { A a; } // CHECK: define void @_ZN5test11RD2Ev(%"struct.test1::R"* %this) unnamed_addr
+ R::~R() { A a; } // CHECK-LABEL: define void @_ZN5test11RD2Ev(%"struct.test1::R"* %this) unnamed_addr
struct S : A { ~S(); int x; };
S::~S() {} // alias tested above
struct T : A { ~T(); B x; };
- T::~T() {} // CHECK: define void @_ZN5test11TD2Ev(%"struct.test1::T"* %this) unnamed_addr
+ T::~T() {} // CHECK-LABEL: define void @_ZN5test11TD2Ev(%"struct.test1::T"* %this) unnamed_addr
// The VTT parameter prevents this. We could still make this work
// for calling conventions that are safe against extra parameters.
struct U : A, virtual B { ~U(); };
- U::~U() {} // CHECK: define void @_ZN5test11UD2Ev(%"struct.test1::U"* %this, i8** %vtt) unnamed_addr
+ U::~U() {} // CHECK-LABEL: define void @_ZN5test11UD2Ev(%"struct.test1::U"* %this, i8** %vtt) unnamed_addr
}
// PR6471
@@ -168,7 +164,7 @@ namespace test2 {
struct B : A { ~B(); };
B::~B() {}
- // CHECK: define void @_ZN5test21BD2Ev(%"struct.test2::B"* %this) unnamed_addr
+ // CHECK-LABEL: define void @_ZN5test21BD2Ev(%"struct.test2::B"* %this) unnamed_addr
// CHECK: call void @_ZN5test21AD2Ev
}
@@ -184,18 +180,12 @@ namespace test3 {
void test() {
new D; // Force emission of D's vtable
}
-
- // Checked at top of file:
- // @_ZN5test312_GLOBAL__N_11CD1Ev = alias internal {{.*}} @_ZN5test312_GLOBAL__N_11CD2Ev
-
- // More checks at end of file.
-
}
namespace test4 {
struct A { ~A(); };
- // CHECK: define void @_ZN5test43fooEv()
+ // CHECK-LABEL: define void @_ZN5test43fooEv()
// CHECK: call void @_ZN5test41AD1Ev
// CHECK: ret void
void foo() {
@@ -208,7 +198,7 @@ namespace test4 {
return;
}
- // CHECK: define void @_ZN5test43barEi(
+ // CHECK-LABEL: define void @_ZN5test43barEi(
// CHECK: [[X:%.*]] = alloca i32
// CHECK-NEXT: [[A:%.*]] = alloca
// CHECK: br label
@@ -233,7 +223,7 @@ namespace test4 {
namespace test5 {
struct A { ~A(); };
- // CHECK: define void @_ZN5test53fooEv()
+ // CHECK-LABEL: define void @_ZN5test53fooEv()
// CHECK: [[ELEMS:%.*]] = alloca [5 x [[A:%.*]]], align
// CHECK-NEXT: [[EXN:%.*]] = alloca i8*
// CHECK-NEXT: [[SEL:%.*]] = alloca i32
@@ -272,7 +262,7 @@ namespace test6 {
};
C::C() { opaque(); }
- // CHECK: define void @_ZN5test61CC1Ev(%"struct.test6::C"* %this) unnamed_addr
+ // CHECK-LABEL: define void @_ZN5test61CC1Ev(%"struct.test6::C"* %this) unnamed_addr
// CHECK: call void @_ZN5test61BILj2EEC2Ev
// CHECK: invoke void @_ZN5test61BILj3EEC2Ev
// CHECK: invoke void @_ZN5test61BILj0EEC2Ev
@@ -282,7 +272,7 @@ namespace test6 {
// FIXME: way too much EH cleanup code follows
C::~C() { opaque(); }
- // CHECK: define void @_ZN5test61CD1Ev(%"struct.test6::C"* %this) unnamed_addr
+ // CHECK-LABEL: define void @_ZN5test61CD1Ev(%"struct.test6::C"* %this) unnamed_addr
// CHECK: invoke void @_ZN5test61CD2Ev
// CHECK: invoke void @_ZN5test61BILj3EED2Ev
// CHECK: call void @_ZN5test61BILj2EED2Ev
@@ -290,7 +280,7 @@ namespace test6 {
// CHECK: invoke void @_ZN5test61BILj3EED2Ev
// CHECK: invoke void @_ZN5test61BILj2EED2Ev
- // CHECK: define void @_ZN5test61CD2Ev(%"struct.test6::C"* %this, i8** %vtt) unnamed_addr
+ // CHECK-LABEL: define void @_ZN5test61CD2Ev(%"struct.test6::C"* %this, i8** %vtt) unnamed_addr
// CHECK: invoke void @_ZN5test66opaqueEv
// CHECK: invoke void @_ZN5test61AD1Ev
// CHECK: invoke void @_ZN5test61AD1Ev
@@ -318,7 +308,7 @@ namespace test7 {
};
// Verify that this doesn't get emitted as an alias
- // CHECK: define void @_ZN5test71BD2Ev(
+ // CHECK-LABEL: define void @_ZN5test71BD2Ev(
// CHECK: invoke void @_ZN5test71DD1Ev(
// CHECK: call void @_ZN5test71AD2Ev(
B::~B() {}
@@ -338,7 +328,7 @@ namespace test8 {
l: die();
}
- // CHECK: define void @_ZN5test84testEv()
+ // CHECK-LABEL: define void @_ZN5test84testEv()
// CHECK: [[X:%.*]] = alloca [[A:%.*]], align 1
// CHECK-NEXT: [[Y:%.*]] = alloca [[A:%.*]], align 1
// CHECK: call void @_ZN5test81AC1Ev([[A]]* [[X]])
@@ -366,10 +356,26 @@ namespace test9 {
// CHECK: call void @_ZN5test92f2Ev()
}
+namespace test10 {
+ // We used to crash trying to replace _ZN6test106OptionD1Ev with
+ // _ZN6test106OptionD2Ev twice.
+ struct Option {
+ virtual ~Option() {}
+ };
+ template <class DataType> class opt : public Option {};
+ template class opt<int>;
+ // CHECK-LABEL: define zeroext i1 @_ZN6test1016handleOccurrenceEv(
+ bool handleOccurrence() {
+ // CHECK: call void @_ZN6test106OptionD2Ev(
+ Option x;
+ return true;
+ }
+}
+
// Checks from test3:
- // CHECK: define internal void @_ZN5test312_GLOBAL__N_11DD0Ev(%"struct.test3::<anonymous namespace>::D"* %this) unnamed_addr
- // CHECK: invoke void @_ZN5test312_GLOBAL__N_11DD1Ev(
+ // CHECK-LABEL: define internal void @_ZN5test312_GLOBAL__N_11DD0Ev(%"struct.test3::<anonymous namespace>::D"* %this) unnamed_addr
+ // CHECK: invoke void {{.*}} @_ZN5test312_GLOBAL__N_11CD2Ev
// CHECK: call void @_ZdlPv({{.*}}) [[NUW:#[0-9]+]]
// CHECK: ret void
// CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
@@ -377,21 +383,22 @@ namespace test9 {
// CHECK: call void @_ZdlPv({{.*}}) [[NUW]]
// CHECK: resume { i8*, i32 }
- // Checked at top of file:
- // @_ZN5test312_GLOBAL__N_11DD1Ev = alias internal {{.*}} @_ZN5test312_GLOBAL__N_11DD2Ev
- // @_ZN5test312_GLOBAL__N_11DD2Ev = alias internal bitcast {{.*}} @_ZN5test312_GLOBAL__N_11CD2Ev
-
- // CHECK: define internal void @_ZThn8_N5test312_GLOBAL__N_11DD1Ev(
+ // CHECK-LABEL: define internal void @_ZThn8_N5test312_GLOBAL__N_11DD1Ev(
// CHECK: getelementptr inbounds i8* {{.*}}, i64 -8
- // CHECK: call void @_ZN5test312_GLOBAL__N_11DD1Ev(
+ // CHECK: call void {{.*}} @_ZN5test312_GLOBAL__N_11CD2Ev
// CHECK: ret void
- // CHECK: define internal void @_ZThn8_N5test312_GLOBAL__N_11DD0Ev(
+ // CHECK-LABEL: define internal void @_ZThn8_N5test312_GLOBAL__N_11DD0Ev(
// CHECK: getelementptr inbounds i8* {{.*}}, i64 -8
// CHECK: call void @_ZN5test312_GLOBAL__N_11DD0Ev(
// CHECK: ret void
- // CHECK: define internal void @_ZN5test312_GLOBAL__N_11CD2Ev(%"struct.test3::<anonymous namespace>::C"* %this) unnamed_addr
+ // CHECK-LABEL: define internal void @_ZThn8_N5test312_GLOBAL__N_11CD1Ev(
+ // CHECK: getelementptr inbounds i8* {{.*}}, i64 -8
+ // CHECK: call void @_ZN5test312_GLOBAL__N_11CD2Ev(
+ // CHECK: ret void
+
+ // CHECK-LABEL: define internal void @_ZN5test312_GLOBAL__N_11CD2Ev(%"struct.test3::<anonymous namespace>::C"* %this) unnamed_addr
// CHECK: invoke void @_ZN5test31BD2Ev(
// CHECK: call void @_ZN5test31AD2Ev(
// CHECK: ret void
@@ -399,8 +406,8 @@ namespace test9 {
// CHECK: declare void @_ZN5test31BD2Ev(
// CHECK: declare void @_ZN5test31AD2Ev(
- // CHECK: define internal void @_ZN5test312_GLOBAL__N_11CD0Ev(%"struct.test3::<anonymous namespace>::C"* %this) unnamed_addr
- // CHECK: invoke void @_ZN5test312_GLOBAL__N_11CD1Ev(
+ // CHECK-LABEL: define internal void @_ZN5test312_GLOBAL__N_11CD0Ev(%"struct.test3::<anonymous namespace>::C"* %this) unnamed_addr
+ // CHECK: invoke void @_ZN5test312_GLOBAL__N_11CD2Ev(
// CHECK: call void @_ZdlPv({{.*}}) [[NUW]]
// CHECK: ret void
// CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
@@ -408,14 +415,9 @@ namespace test9 {
// CHECK: call void @_ZdlPv({{.*}}) [[NUW]]
// CHECK: resume { i8*, i32 }
- // CHECK: define internal void @_ZThn8_N5test312_GLOBAL__N_11CD1Ev(
- // CHECK: getelementptr inbounds i8* {{.*}}, i64 -8
- // CHECK: call void @_ZN5test312_GLOBAL__N_11CD1Ev(
- // CHECK: ret void
-
- // CHECK: define internal void @_ZThn8_N5test312_GLOBAL__N_11CD0Ev(
+ // CHECK-LABEL: define internal void @_ZThn8_N5test312_GLOBAL__N_11CD0Ev(
// CHECK: getelementptr inbounds i8* {{.*}}, i64 -8
// CHECK: call void @_ZN5test312_GLOBAL__N_11CD0Ev(
// CHECK: ret void
- // CHECK: attributes [[NUW]] = { nounwind{{.*}} }
+ // CHECK: attributes [[NUW]] = {{[{].*}} nounwind {{.*[}]}}
diff --git a/test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp b/test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp
index 40f3cad..11026e8 100644
--- a/test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp
+++ b/test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp
@@ -5,7 +5,7 @@ namespace Test1 {
virtual int f() final;
};
- // CHECK: define i32 @_ZN5Test11fEPNS_1AE
+ // CHECK-LABEL: define i32 @_ZN5Test11fEPNS_1AE
int f(A *a) {
// CHECK: call i32 @_ZN5Test11A1fEv
return a->f();
@@ -17,7 +17,7 @@ namespace Test2 {
virtual int f();
};
- // CHECK: define i32 @_ZN5Test21fEPNS_1AE
+ // CHECK-LABEL: define i32 @_ZN5Test21fEPNS_1AE
int f(A *a) {
// CHECK: call i32 @_ZN5Test21A1fEv
return a->f();
@@ -31,19 +31,19 @@ namespace Test3 {
struct B final : A { };
- // CHECK: define i32 @_ZN5Test31fEPNS_1BE
+ // CHECK-LABEL: define i32 @_ZN5Test31fEPNS_1BE
int f(B *b) {
// CHECK: call i32 @_ZN5Test31A1fEv
return b->f();
}
- // CHECK: define i32 @_ZN5Test31fERNS_1BE
+ // CHECK-LABEL: define i32 @_ZN5Test31fERNS_1BE
int f(B &b) {
// CHECK: call i32 @_ZN5Test31A1fEv
return b.f();
}
- // CHECK: define i32 @_ZN5Test31fEPv
+ // CHECK-LABEL: define i32 @_ZN5Test31fEPv
int f(void *v) {
// CHECK: call i32 @_ZN5Test31A1fEv
return static_cast<B*>(v)->f();
@@ -59,7 +59,7 @@ namespace Test4 {
virtual void f();
};
- // CHECK: define void @_ZN5Test41fEPNS_1BE
+ // CHECK-LABEL: define void @_ZN5Test41fEPNS_1BE
void f(B* d) {
// CHECK: call void @_ZN5Test41B1fEv
static_cast<A*>(d)->f();
@@ -78,7 +78,7 @@ namespace Test5 {
struct C final : B {
};
- // CHECK: define void @_ZN5Test51fEPNS_1CE
+ // CHECK-LABEL: define void @_ZN5Test51fEPNS_1CE
void f(C* d) {
// FIXME: It should be possible to devirtualize this case, but that is
// not implemented yet.
@@ -105,7 +105,7 @@ namespace Test6 {
struct D final : public C, public B {
};
- // CHECK: define void @_ZN5Test61fEPNS_1DE
+ // CHECK-LABEL: define void @_ZN5Test61fEPNS_1DE
void f(D* d) {
// CHECK: call void @_ZN5Test61DD1Ev
static_cast<A*>(d)->~A();
@@ -126,7 +126,7 @@ namespace Test7 {
virtual int f() {return z;}
};
- // CHECK: define i32 @_ZN5Test71fEPNS_3zedE
+ // CHECK-LABEL: define i32 @_ZN5Test71fEPNS_3zedE
int f(zed *z) {
// CHECK: alloca
// CHECK-NEXT: store
@@ -144,7 +144,7 @@ namespace Test8 {
virtual int foo() { return b; }
};
struct C final : A, B { };
- // CHECK: define i32 @_ZN5Test84testEPNS_1CE
+ // CHECK-LABEL: define i32 @_ZN5Test84testEPNS_1CE
int test(C *c) {
// CHECK: %[[THIS:.*]] = phi
// CHECK-NEXT: call i32 @_ZN5Test81B3fooEv(%"struct.Test8::B"* %[[THIS]])
diff --git a/test/CodeGenCXX/devirtualize-virtual-function-calls.cpp b/test/CodeGenCXX/devirtualize-virtual-function-calls.cpp
index 52f1cd3..911ddee 100644
--- a/test/CodeGenCXX/devirtualize-virtual-function-calls.cpp
+++ b/test/CodeGenCXX/devirtualize-virtual-function-calls.cpp
@@ -79,7 +79,7 @@ namespace test3 {
struct D : public B {
};
void f(D d) {
- // CHECK: define void @_ZN5test31fENS_1DE
+ // CHECK-LABEL: define void @_ZN5test31fENS_1DE
d.B::~B();
}
}
diff --git a/test/CodeGenCXX/dynamic_cast-no-rtti.cpp b/test/CodeGenCXX/dynamic_cast-no-rtti.cpp
new file mode 100644
index 0000000..0e26de5
--- /dev/null
+++ b/test/CodeGenCXX/dynamic_cast-no-rtti.cpp
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -emit-llvm %s -verify -fno-rtti -o - | FileCheck %s
+// expected-no-diagnostics
+
+struct A {
+ virtual ~A(){};
+};
+
+struct B : public A {
+ B() : A() {}
+};
+
+// An upcast can be resolved statically and can be used with -fno-rtti, iff it
+// does not use runtime support.
+A *upcast(B *b) {
+ return dynamic_cast<A *>(b);
+// CHECK-LABEL: define %struct.A* @_Z6upcastP1B
+// CHECK-NOT: call i8* @__dynamic_cast
+}
+
+// A NoOp dynamic_cast can be used with -fno-rtti iff it does not use
+// runtime support.
+B *samecast(B *b) {
+ return dynamic_cast<B *>(b);
+// CHECK-LABEL: define %struct.B* @_Z8samecastP1B
+// CHECK-NOT: call i8* @__dynamic_cast
+}
diff --git a/test/CodeGenCXX/eh.cpp b/test/CodeGenCXX/eh.cpp
index 70887f7..2a61e61 100644
--- a/test/CodeGenCXX/eh.cpp
+++ b/test/CodeGenCXX/eh.cpp
@@ -9,7 +9,7 @@ void test1() {
throw d1;
}
-// CHECK: define void @_Z5test1v()
+// CHECK-LABEL: define void @_Z5test1v()
// CHECK: [[EXNOBJ:%.*]] = call i8* @__cxa_allocate_exception(i64 8)
// CHECK-NEXT: [[EXN:%.*]] = bitcast i8* [[EXNOBJ]] to [[DSTAR:%[^*]*\*]]
// CHECK-NEXT: [[EXN2:%.*]] = bitcast [[DSTAR]] [[EXN]] to i8*
@@ -29,7 +29,7 @@ void test2() {
throw d2;
}
-// CHECK: define void @_Z5test2v()
+// CHECK-LABEL: define void @_Z5test2v()
// CHECK: [[EXNVAR:%.*]] = alloca i8*
// CHECK-NEXT: [[SELECTORVAR:%.*]] = alloca i32
// CHECK-NEXT: [[EXNOBJ:%.*]] = call i8* @__cxa_allocate_exception(i64 16)
@@ -51,7 +51,7 @@ void test3() {
throw (volatile test3_D *)0;
}
-// CHECK: define void @_Z5test3v()
+// CHECK-LABEL: define void @_Z5test3v()
// CHECK: [[EXNOBJ:%.*]] = call i8* @__cxa_allocate_exception(i64 8)
// CHECK-NEXT: [[EXN:%.*]] = bitcast i8* [[EXNOBJ]] to [[D:%[^*]+]]**
// CHECK-NEXT: store [[D]]* null, [[D]]** [[EXN]]
@@ -63,7 +63,7 @@ void test4() {
throw;
}
-// CHECK: define void @_Z5test4v()
+// CHECK-LABEL: define void @_Z5test4v()
// CHECK: call void @__cxa_rethrow() [[NR]]
// CHECK-NEXT: unreachable
@@ -79,7 +79,7 @@ namespace test5 {
void test() {
try { throw A(); } catch (A &x) {}
}
-// CHECK: define void @_ZN5test54testEv()
+// CHECK-LABEL: define void @_ZN5test54testEv()
// CHECK: [[EXNOBJ:%.*]] = call i8* @__cxa_allocate_exception(i64 1)
// CHECK: [[EXNCAST:%.*]] = bitcast i8* [[EXNOBJ]] to [[A:%[^*]*]]*
// CHECK-NEXT: invoke void @_ZN5test51AC1Ev([[A]]* [[EXNCAST]])
@@ -101,7 +101,7 @@ namespace test6 {
// PR7127
namespace test7 {
-// CHECK: define i32 @_ZN5test73fooEv()
+// CHECK-LABEL: define i32 @_ZN5test73fooEv()
int foo() {
// CHECK: [[CAUGHTEXNVAR:%.*]] = alloca i8*
// CHECK-NEXT: [[SELECTORVAR:%.*]] = alloca i32
@@ -160,7 +160,7 @@ namespace test8 {
struct A { A(const A&); ~A(); };
void bar();
- // CHECK: define void @_ZN5test83fooEv()
+ // CHECK-LABEL: define void @_ZN5test83fooEv()
void foo() {
try {
// CHECK: invoke void @_ZN5test83barEv()
@@ -184,11 +184,11 @@ namespace test9 {
struct A { A(); };
- // CHECK: define void @_ZN5test91AC1Ev(%"struct.test9::A"* %this) unnamed_addr
+ // CHECK-LABEL: define void @_ZN5test91AC1Ev(%"struct.test9::A"* %this) unnamed_addr
// CHECK: call void @_ZN5test91AC2Ev
// CHECK-NEXT: ret void
- // CHECK: define void @_ZN5test91AC2Ev(%"struct.test9::A"* %this) unnamed_addr
+ // CHECK-LABEL: define void @_ZN5test91AC2Ev(%"struct.test9::A"* %this) unnamed_addr
A::A() try {
// CHECK: invoke void @_ZN5test96opaqueEv()
opaque();
@@ -210,7 +210,7 @@ namespace test10 {
struct A { ~A(); };
struct B { int x; };
- // CHECK: define void @_ZN6test103fooEv()
+ // CHECK-LABEL: define void @_ZN6test103fooEv()
void foo() {
A a; // force a cleanup context
@@ -244,7 +244,7 @@ namespace test10 {
namespace test11 {
void opaque();
- // CHECK: define void @_ZN6test113fooEv()
+ // CHECK-LABEL: define void @_ZN6test113fooEv()
void foo() {
try {
// CHECK: invoke void @_ZN6test116opaqueEv()
@@ -261,7 +261,7 @@ namespace test11 {
struct A {};
- // CHECK: define void @_ZN6test113barEv()
+ // CHECK-LABEL: define void @_ZN6test113barEv()
void bar() {
try {
// CHECK: [[EXNSLOT:%.*]] = alloca i8*
@@ -286,7 +286,7 @@ namespace test12 {
struct A { ~A() noexcept(false); };
bool opaque(const A&);
- // CHECK: define void @_ZN6test124testEv()
+ // CHECK-LABEL: define void @_ZN6test124testEv()
void test() {
// CHECK: [[X:%.*]] = alloca [[A:%.*]],
// CHECK: [[EHCLEANUPDEST:%.*]] = alloca i32
@@ -371,7 +371,7 @@ namespace test15 {
bool opaque(int);
- // CHECK: define void @_ZN6test153fooEv()
+ // CHECK-LABEL: define void @_ZN6test153fooEv()
void foo() {
A a;
@@ -405,7 +405,7 @@ namespace test16 {
void foo();
bool cond();
- // CHECK: define void @_ZN6test163barEv()
+ // CHECK-LABEL: define void @_ZN6test163barEv()
void bar() {
// CHECK: [[EXN_SAVE:%.*]] = alloca i8*
// CHECK-NEXT: [[EXN_ACTIVE:%.*]] = alloca i1
diff --git a/test/CodeGenCXX/empty-classes.cpp b/test/CodeGenCXX/empty-classes.cpp
index 1ce1dad..8491480 100644
--- a/test/CodeGenCXX/empty-classes.cpp
+++ b/test/CodeGenCXX/empty-classes.cpp
@@ -29,7 +29,7 @@ struct D : A, Empty {
#define CHECK(x) if (!(x)) return __LINE__
// PR7012
-// CHECK: define i32 @_Z1fv()
+// CHECK-LABEL: define i32 @_Z1fv()
int f() {
B b1;
diff --git a/test/CodeGenCXX/empty-nontrivially-copyable.cpp b/test/CodeGenCXX/empty-nontrivially-copyable.cpp
new file mode 100644
index 0000000..9ee3281
--- /dev/null
+++ b/test/CodeGenCXX/empty-nontrivially-copyable.cpp
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -triple armv7-apple-ios -x c++ -emit-llvm -o - %s | FileCheck %s
+
+// According to the Itanium ABI (3.1.1), types with non-trivial copy
+// constructors passed by value should be passed indirectly, with the caller
+// creating a temporary.
+
+struct Empty;
+
+struct Empty {
+ Empty(const Empty &e);
+ bool check();
+};
+
+bool foo(Empty e) {
+// CHECK: @_Z3foo5Empty(%struct.Empty* %e)
+// CHECK: call {{.*}} @_ZN5Empty5checkEv(%struct.Empty* %e)
+ return e.check();
+}
+
+void caller(Empty &e) {
+// CHECK: @_Z6callerR5Empty(%struct.Empty* %e)
+// CHECK: call {{.*}} @_ZN5EmptyC1ERKS_(%struct.Empty* [[NEWTMP:%.*]], %struct.Empty*
+// CHECK: call {{.*}} @_Z3foo5Empty(%struct.Empty* [[NEWTMP]])
+ foo(e);
+}
diff --git a/test/CodeGenCXX/exceptions.cpp b/test/CodeGenCXX/exceptions.cpp
index f6f5079..d37e610 100644
--- a/test/CodeGenCXX/exceptions.cpp
+++ b/test/CodeGenCXX/exceptions.cpp
@@ -269,7 +269,7 @@ namespace test5 {
void foo();
- // CHECK: define void @_ZN5test54testEv()
+ // CHECK-LABEL: define void @_ZN5test54testEv()
// CHECK: [[EXNSLOT:%.*]] = alloca i8*
// CHECK-NEXT: [[SELECTORSLOT:%.*]] = alloca i32
// CHECK-NEXT: [[A:%.*]] = alloca [[A_T:%.*]], align 1
@@ -403,7 +403,7 @@ namespace test8 {
void test() {
throw makeA();
}
- // CHECK: define void @_ZN5test84testEv
+ // CHECK-LABEL: define void @_ZN5test84testEv
}
// Make sure we generate the correct code for the delete[] call which
@@ -432,14 +432,14 @@ namespace test10 {
struct A { ~A(); };
A::~A() try { cleanup(); } catch (...) { return; }
- // CHECK: define void @_ZN6test101AD1Ev(
+ // CHECK-LABEL: define void @_ZN6test101AD1Ev(
// CHECK: invoke void @_ZN6test107cleanupEv()
// CHECK-NOT: rethrow
// CHECK: ret void
struct B { ~B(); };
B::~B() try { cleanup(); } catch (...) {}
- // CHECK: define void @_ZN6test101BD1Ev(
+ // CHECK-LABEL: define void @_ZN6test101BD1Ev(
// CHECK: invoke void @_ZN6test107cleanupEv()
// CHECK: call i8* @__cxa_begin_catch
// CHECK-NEXT: invoke void @__cxa_rethrow()
@@ -447,7 +447,7 @@ namespace test10 {
struct C { ~C(); };
C::~C() try { cleanup(); } catch (...) { if (suppress) return; }
- // CHECK: define void @_ZN6test101CD1Ev(
+ // CHECK-LABEL: define void @_ZN6test101CD1Ev(
// CHECK: invoke void @_ZN6test107cleanupEv()
// CHECK: call i8* @__cxa_begin_catch
// CHECK-NEXT: load i8* @_ZN6test108suppressE, align 1
@@ -477,7 +477,7 @@ namespace test11 {
C::C() {
throw 0;
}
- // CHECK: define void @_ZN6test111CC2Ev(
+ // CHECK-LABEL: define void @_ZN6test111CC2Ev(
// CHECK: [[THIS:%.*]] = load [[C:%.*]]** {{%.*}}
// Construct single.
// CHECK-NEXT: [[SINGLE:%.*]] = getelementptr inbounds [[C]]* [[THIS]], i32 0, i32 0
diff --git a/test/CodeGenCXX/explicit-instantiation.cpp b/test/CodeGenCXX/explicit-instantiation.cpp
index 8daf3c6..6a4fd82 100644
--- a/test/CodeGenCXX/explicit-instantiation.cpp
+++ b/test/CodeGenCXX/explicit-instantiation.cpp
@@ -13,7 +13,7 @@ Result plus<T, U, Result>::operator()(const T& t, const U& u) const {
return t + u;
}
-// CHECK: define weak_odr i32 @_ZNK4plusIillEclERKiRKl
+// CHECK-LABEL: define weak_odr i32 @_ZNK4plusIillEclERKiRKl
template struct plus<int, long, long>;
// Check that we emit definitions from explicit instantiations even when they
@@ -27,16 +27,16 @@ template <typename T> struct S {
};
};
-// CHECK: define weak_odr void @_ZN1SIiE1fEv
+// CHECK-LABEL: define weak_odr void @_ZN1SIiE1fEv
template void S<int>::f();
-// CHECK: define weak_odr void @_ZN1SIiE1gEv
+// CHECK-LABEL: define weak_odr void @_ZN1SIiE1gEv
template void S<int>::g();
// See the check line at the top of the file.
template int S<int>::i;
-// CHECK: define weak_odr void @_ZN1SIiE2S21hEv
+// CHECK-LABEL: define weak_odr void @_ZN1SIiE2S21hEv
template void S<int>::S2::h();
template <typename T> void S<T>::f() {}
diff --git a/test/CodeGenCXX/fastcall.cpp b/test/CodeGenCXX/fastcall.cpp
index c0a9106..0326ce5 100644
--- a/test/CodeGenCXX/fastcall.cpp
+++ b/test/CodeGenCXX/fastcall.cpp
@@ -2,7 +2,7 @@
void __attribute__((fastcall)) foo1(int &y);
void bar1(int &y) {
- // CHECK: define void @_Z4bar1Ri
+ // CHECK-LABEL: define void @_Z4bar1Ri
// CHECK: call x86_fastcallcc void @_Z4foo1Ri(i32* inreg %
foo1(y);
}
@@ -14,7 +14,7 @@ struct S1 {
void __attribute__((fastcall)) foo2(S1 a, int b);
void bar2(S1 a, int b) {
- // CHECK: define void @_Z4bar22S1i
+ // CHECK-LABEL: define void @_Z4bar22S1i
// CHECK: call x86_fastcallcc void @_Z4foo22S1i(%struct.S1* inreg %{{.*}}, i32 inreg %
foo2(a, b);
}
diff --git a/test/CodeGenCXX/for-range.cpp b/test/CodeGenCXX/for-range.cpp
index 926fe44..8124129 100644
--- a/test/CodeGenCXX/for-range.cpp
+++ b/test/CodeGenCXX/for-range.cpp
@@ -32,7 +32,7 @@ B *end(C&);
extern B array[5];
-// CHECK: define void @_Z9for_arrayv(
+// CHECK-LABEL: define void @_Z9for_arrayv(
void for_array() {
// CHECK: call void @_ZN1AC1Ev(%struct.A* [[A:.*]])
A a;
@@ -40,7 +40,7 @@ void for_array() {
// CHECK-NOT: 5begin
// CHECK-NOT: 3end
// CHECK: getelementptr {{.*}}, i32 0
- // CHECK: getelementptr {{.*}}, i64 1, i64 0
+ // CHECK: getelementptr {{.*}}, i64 5
// CHECK: br label %[[COND:.*]]
// CHECK: [[COND]]:
@@ -61,7 +61,7 @@ void for_array() {
// CHECK: ret void
}
-// CHECK: define void @_Z9for_rangev(
+// CHECK-LABEL: define void @_Z9for_rangev(
void for_range() {
// CHECK: call void @_ZN1AC1Ev(%struct.A* [[A:.*]])
A a;
@@ -93,7 +93,7 @@ void for_range() {
// CHECK: ret void
}
-// CHECK: define void @_Z16for_member_rangev(
+// CHECK-LABEL: define void @_Z16for_member_rangev(
void for_member_range() {
// CHECK: call void @_ZN1AC1Ev(%struct.A* [[A:.*]])
A a;
diff --git a/test/CodeGenCXX/forward-enum.cpp b/test/CodeGenCXX/forward-enum.cpp
index c1169e0..685e4f3 100644
--- a/test/CodeGenCXX/forward-enum.cpp
+++ b/test/CodeGenCXX/forward-enum.cpp
@@ -3,7 +3,7 @@
enum MyEnum : char;
void bar(MyEnum value) { }
-// CHECK: define void @_Z3foo6MyEnum
+// CHECK-LABEL: define void @_Z3foo6MyEnum
void foo(MyEnum value)
{
// CHECK: call void @_Z3bar6MyEnum(i8 signext
diff --git a/test/CodeGenCXX/fp16-mangle.cpp b/test/CodeGenCXX/fp16-mangle.cpp
index 4a056d6..bd5a319 100644
--- a/test/CodeGenCXX/fp16-mangle.cpp
+++ b/test/CodeGenCXX/fp16-mangle.cpp
@@ -4,9 +4,9 @@
template <typename T, typename U> struct S { static int i; };
template <> int S<__fp16, __fp16>::i = 3;
-// CHECK: define void @_Z1fPDh(i16* %x)
+// CHECK-LABEL: define void @_Z1fPDh(i16* %x)
void f (__fp16 *x) { }
-// CHECK: define void @_Z1gPDhS_(i16* %x, i16* %y)
+// CHECK-LABEL: define void @_Z1gPDhS_(i16* %x, i16* %y)
void g (__fp16 *x, __fp16 *y) { }
diff --git a/test/CodeGenCXX/function-template-explicit-specialization.cpp b/test/CodeGenCXX/function-template-explicit-specialization.cpp
index 21f0127..5d26dcd 100644
--- a/test/CodeGenCXX/function-template-explicit-specialization.cpp
+++ b/test/CodeGenCXX/function-template-explicit-specialization.cpp
@@ -3,11 +3,11 @@
template<typename T> void a(T);
template<> void a(int) {}
-// CHECK: define void @_Z1aIiEvT_
+// CHECK-LABEL: define void @_Z1aIiEvT_
namespace X {
template<typename T> void b(T);
template<> void b(int) {}
}
-// CHECK: define void @_ZN1X1bIiEEvT_
+// CHECK-LABEL: define void @_ZN1X1bIiEEvT_
diff --git a/test/CodeGenCXX/global-array-destruction.cpp b/test/CodeGenCXX/global-array-destruction.cpp
index 087d655..6ebc139 100644
--- a/test/CodeGenCXX/global-array-destruction.cpp
+++ b/test/CodeGenCXX/global-array-destruction.cpp
@@ -56,7 +56,7 @@ 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: getelementptr inbounds ({{.*}}* getelementptr inbounds ([2 x [3 x {{.*}}]]* @_ZGR1u, i32 0, i32 0, i32 0), i64 6)
// CHECK: call void @_ZN1TD1Ev
// CHECK: icmp eq {{.*}} @_ZGR1u
// CHECK: br i1 {{.*}}
diff --git a/test/CodeGenCXX/global-block-literal-helpers.cpp b/test/CodeGenCXX/global-block-literal-helpers.cpp
index 350ea54..762b5d9 100644
--- a/test/CodeGenCXX/global-block-literal-helpers.cpp
+++ b/test/CodeGenCXX/global-block-literal-helpers.cpp
@@ -5,23 +5,23 @@ namespace N {
typedef void (^BL)();
int func(BL, BL, BL);
-// CHECK: define internal void @_ZN1N8ArrBlockE_block_invoke(
-// CHECK: define internal void @_ZN1N8ArrBlockE_block_invoke_2(
-// CHECK: define internal void @_ZN1N8ArrBlockE_block_invoke_3
+// CHECK-LABEL: define internal void @_ZN1N8ArrBlockE_block_invoke(
+// CHECK-LABEL: define internal void @_ZN1N8ArrBlockE_block_invoke_2(
+// CHECK-LABEL: define internal void @_ZN1N8ArrBlockE_block_invoke_3
BL ArrBlock [] = { ^{}, ^{}, ^{} };
-// CHECK: define internal void @_ZN1N4ivalE_block_invoke_4(
-// CHECK: define internal void @_ZN1N4ivalE_block_invoke_5(
-// CHECK: define internal void @_ZN1N4ivalE_block_invoke_6(
+// CHECK-LABEL: define internal void @_ZN1N4ivalE_block_invoke_4(
+// CHECK-LABEL: define internal void @_ZN1N4ivalE_block_invoke_5(
+// CHECK-LABEL: define internal void @_ZN1N4ivalE_block_invoke_6(
int ival = func(^{}, ^{}, ^{});
-// CHECK: define internal void @_ZN1N9gvarlobalE_block_invoke_7(
+// CHECK-LABEL: define internal void @_ZN1N9gvarlobalE_block_invoke_7(
void (^gvarlobal)(void) = ^{};
struct S {
BL field = ^{};
};
-// CHECK: define internal void @_ZN1N3blfE_block_invoke_8(
+// CHECK-LABEL: define internal void @_ZN1N3blfE_block_invoke_8(
S blf;
};
diff --git a/test/CodeGenCXX/global-dtor-no-atexit.cpp b/test/CodeGenCXX/global-dtor-no-atexit.cpp
index 7c4b6aa..9d35e84 100644
--- a/test/CodeGenCXX/global-dtor-no-atexit.cpp
+++ b/test/CodeGenCXX/global-dtor-no-atexit.cpp
@@ -22,7 +22,7 @@ public:
A a, b;
// PR9593
-// CHECK: define void @_Z4funcv()
+// CHECK-LABEL: define void @_Z4funcv()
// CHECK: call i32 @__cxa_guard_acquire(i64* @_ZGVZ4funcvE2a1)
// CHECK: call void @_ZN1AC1Ev([[A]]* @_ZZ4funcvE2a1)
// CHECK-NEXT: call i32 @atexit(void ()* @__dtor__ZZ4funcvE2a1)
diff --git a/test/CodeGenCXX/global-init.cpp b/test/CodeGenCXX/global-init.cpp
index 426cf9c..69631c2 100644
--- a/test/CodeGenCXX/global-init.cpp
+++ b/test/CodeGenCXX/global-init.cpp
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 -triple=x86_64-apple-darwin10 -emit-llvm -fexceptions %s -o - |FileCheck %s
-// RUN: %clang_cc1 -triple=x86_64-apple-darwin10 -emit-llvm %s -o - |FileCheck -check-prefix NOEXC %s
+// RUN: %clang_cc1 -triple=x86_64-apple-darwin10 -emit-llvm %s -o - |FileCheck -check-prefix CHECK-NOEXC %s
struct A {
A();
@@ -45,7 +45,7 @@ namespace test1 {
const int y = x - 1; // This gets deferred.
const int z = ~y; // This also gets deferred, but gets "undeferred" before y.
int test() { return z; }
-// CHECK: define i32 @_ZN5test14testEv()
+// CHECK-LABEL: define i32 @_ZN5test14testEv()
// All of these initializers end up delayed, so we check them later.
}
diff --git a/test/CodeGenCXX/goto.cpp b/test/CodeGenCXX/goto.cpp
index 77b6166..904f95f 100644
--- a/test/CodeGenCXX/goto.cpp
+++ b/test/CodeGenCXX/goto.cpp
@@ -5,7 +5,7 @@ namespace test0 {
struct A { A(); ~A(); };
struct V { V(const A &a = A()); ~V(); };
- // CHECK: define linkonce_odr i32 @_ZN5test04testILi0EEEii
+ // CHECK-LABEL: define linkonce_odr i32 @_ZN5test04testILi0EEEii
template<int X> int test(int x) {
// CHECK: [[RET:%.*]] = alloca i32
// CHECK-NEXT: [[X:%.*]] = alloca i32
diff --git a/test/CodeGenCXX/implicit-copy-assign-operator.cpp b/test/CodeGenCXX/implicit-copy-assign-operator.cpp
index 79586fb..2674021 100644
--- a/test/CodeGenCXX/implicit-copy-assign-operator.cpp
+++ b/test/CodeGenCXX/implicit-copy-assign-operator.cpp
@@ -40,7 +40,7 @@ void test_D(D d1, D d2) {
d1 = d2;
}
-// CHECK: define linkonce_odr %struct.D* @_ZN1DaSERS_
+// CHECK-LABEL: define linkonce_odr %struct.D* @_ZN1DaSERS_
// CHECK: {{call.*_ZN1AaSERS_}}
// CHECK: {{call.*_ZN1BaSERS_}}
// CHECK: {{call.*_ZN1CaSERKS_}}
diff --git a/test/CodeGenCXX/implicit-copy-constructor.cpp b/test/CodeGenCXX/implicit-copy-constructor.cpp
index 24e84d5..bb04318 100644
--- a/test/CodeGenCXX/implicit-copy-constructor.cpp
+++ b/test/CodeGenCXX/implicit-copy-constructor.cpp
@@ -40,7 +40,7 @@ void f(D d) {
D d2(d);
}
-// CHECK: define linkonce_odr void @_ZN1DC1ERS_(%struct.D* %this, %struct.D*) unnamed_addr
+// CHECK-LABEL: define linkonce_odr void @_ZN1DC1ERS_(%struct.D* %this, %struct.D*) unnamed_addr
// CHECK: call void @_ZN1AC1Ev
// CHECK: call void @_ZN1CC2ERS_1A
// CHECK: call void @_ZN1AD1Ev
diff --git a/test/CodeGenCXX/implicit-instantiation-1.cpp b/test/CodeGenCXX/implicit-instantiation-1.cpp
index 0c826e4..bf6a141 100644
--- a/test/CodeGenCXX/implicit-instantiation-1.cpp
+++ b/test/CodeGenCXX/implicit-instantiation-1.cpp
@@ -20,7 +20,7 @@ void foo(X<int> &xi, X<float> *xfp, int i, float f) {
// RUN: grep "linkonce_odr.*_ZN1XIfE1fEf" %t | count 1
xfp->f(f);
- // RUN: grep "linkonce_odr.*_ZN1XIfE1hEf" %t | count 0
+ // RUN: not grep "linkonce_odr.*_ZN1XIfE1hEf" %t
}
diff --git a/test/CodeGenCXX/inheriting-constructor.cpp b/test/CodeGenCXX/inheriting-constructor.cpp
index 0f39784..c99a20c 100644
--- a/test/CodeGenCXX/inheriting-constructor.cpp
+++ b/test/CodeGenCXX/inheriting-constructor.cpp
@@ -11,18 +11,18 @@ struct C { template<typename T> C(T); };
struct D : C { using C::C; };
D d(123);
-// CHECK: define void @_ZN1BD0Ev
-// CHECK: define void @_ZN1BD1Ev
-// CHECK: define void @_ZN1BD2Ev
+// CHECK-LABEL: define void @_ZN1BD0Ev
+// CHECK-LABEL: define void @_ZN1BD1Ev
+// CHECK-LABEL: define void @_ZN1BD2Ev
-// CHECK: define linkonce_odr void @_ZN1BC1Ei(
+// CHECK-LABEL: define linkonce_odr void @_ZN1BC1Ei(
// CHECK: call void @_ZN1BC2Ei(
-// CHECK: define linkonce_odr void @_ZN1DC1IiEET_(
+// CHECK-LABEL: define linkonce_odr void @_ZN1DC1IiEET_(
// CHECK: call void @_ZN1DC2IiEET_(
-// CHECK: define linkonce_odr void @_ZN1DC2IiEET_(
+// CHECK-LABEL: define linkonce_odr void @_ZN1DC2IiEET_(
// CHECK: call void @_ZN1CC2IiEET_(
-// CHECK: define linkonce_odr void @_ZN1BC2Ei(
+// CHECK-LABEL: define linkonce_odr void @_ZN1BC2Ei(
// CHECK: call void @_ZN1AC2Ei(
diff --git a/test/CodeGenCXX/init-invariant.cpp b/test/CodeGenCXX/init-invariant.cpp
index 9eb1989..45816b2 100644
--- a/test/CodeGenCXX/init-invariant.cpp
+++ b/test/CodeGenCXX/init-invariant.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple i686-linux-gnu -emit-llvm %s -O0 -o - | FileCheck %s --check-prefix=CHECK-O0
+// RUN: %clang_cc1 -triple i686-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-O0
// RUN: %clang_cc1 -triple i686-linux-gnu -emit-llvm %s -O1 -o - | FileCheck %s
// Check that we add an llvm.invariant.start to mark when a global becomes
@@ -54,7 +54,7 @@ void e() {
// CHECK: store {{.*}}, i32* @d
// CHECK: call {{.*}}@llvm.invariant.start(i64 4, i8* bitcast ({{.*}} @d to i8*))
-// CHECK: define void @_Z1ev(
+// CHECK-LABEL: define void @_Z1ev(
// CHECK: call void @_ZN1AC1Ev(%struct.A* @_ZZ1evE1a)
// CHECK: call {{.*}}@llvm.invariant.start(i64 4, i8* bitcast ({{.*}} @_ZZ1evE1a to i8*))
// CHECK-NOT: llvm.invariant.end
diff --git a/test/CodeGenCXX/inline-functions.cpp b/test/CodeGenCXX/inline-functions.cpp
index 8c011de..9f8e536 100644
--- a/test/CodeGenCXX/inline-functions.cpp
+++ b/test/CodeGenCXX/inline-functions.cpp
@@ -5,7 +5,7 @@ struct A {
inline void f();
};
-// CHECK-NOT: define void @_ZN1A1fEv
+// CHECK-NOT-LABEL: define void @_ZN1A1fEv
void A::f() { }
template<typename> struct B { };
@@ -19,13 +19,13 @@ void B<char>::f() { }
// We need a final CHECK line here.
-// CHECK: define void @_Z1fv
+// CHECK-LABEL: define void @_Z1fv
void f() { }
// <rdar://problem/8740363>
inline void f1(int);
-// CHECK: define linkonce_odr void @_Z2f1i
+// CHECK-LABEL: define linkonce_odr void @_Z2f1i
void f1(int) { }
void test_f1() { f1(17); }
@@ -38,7 +38,7 @@ namespace test1 {
void g() {}
};
- // CHECK: define linkonce_odr void @_ZN5test11C4funcEv(
+ // CHECK-LABEL: define linkonce_odr void @_ZN5test11C4funcEv(
class C {
public:
@@ -65,5 +65,5 @@ namespace test2 {
A a;
f(a);
}
- // CHECK: define linkonce_odr void @_ZN5test21fERKNS_1AE
+ // CHECK-LABEL: define linkonce_odr void @_ZN5test21fERKNS_1AE
}
diff --git a/test/CodeGenCXX/instantiate-temporaries.cpp b/test/CodeGenCXX/instantiate-temporaries.cpp
index 29cfc07..c08ea78 100644
--- a/test/CodeGenCXX/instantiate-temporaries.cpp
+++ b/test/CodeGenCXX/instantiate-temporaries.cpp
@@ -18,7 +18,7 @@ void call() {
Y().get();
}
-// CHECK: define weak_odr void @_Z4callIiEvv
+// CHECK-LABEL: define weak_odr void @_Z4callIiEvv
// CHECK: call void @_ZN1Y3getEv
// CHECK-NEXT: call void @_ZN1XD1Ev
// CHECK-NEXT: ret void
@@ -29,7 +29,7 @@ void compound_literal() {
(X2){};
}
-// CHECK: define weak_odr void @_Z16compound_literalIiEvv
+// CHECK-LABEL: define weak_odr void @_Z16compound_literalIiEvv
// CHECK: call void @_ZN1XC1Ev
// CHECK-NEXT: call void @_ZN2X2D1Ev
// CHECK-NEXT: ret void
diff --git a/test/CodeGenCXX/invalid.cpp b/test/CodeGenCXX/invalid.cpp
new file mode 100644
index 0000000..d346246
--- /dev/null
+++ b/test/CodeGenCXX/invalid.cpp
@@ -0,0 +1,11 @@
+// RUN: not %clang_cc1 -g -emit-llvm %s
+
+// Don't attempt to codegen invalid code that would lead to a crash
+
+// PR16933
+struct A;
+A *x;
+struct A {
+ B y;
+};
+A y;
diff --git a/test/CodeGenCXX/lambda-expressions-inside-auto-functions.cpp b/test/CodeGenCXX/lambda-expressions-inside-auto-functions.cpp
new file mode 100644
index 0000000..0083f08
--- /dev/null
+++ b/test/CodeGenCXX/lambda-expressions-inside-auto-functions.cpp
@@ -0,0 +1,77 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10.0.0 -fblocks -emit-llvm -o - %s -fexceptions -std=c++1y | FileCheck %s
+
+// CHECK-LABEL: define void @_ZN19non_inline_function3fooEv
+// CHECK-LABEL: define internal void @"_ZZN19non_inline_function3fooEvENK3$_0clEi"(%class.anon
+// CHECK-LABEL: define internal signext i8 @"_ZZZN19non_inline_function3fooEvENK3$_0clEiENKUlcE_clEc"(%class.anon
+// CHECK-LABEL: define linkonce_odr void @_ZN19non_inline_function4foo2IiEEDav()
+namespace non_inline_function {
+auto foo() {
+ auto L = [](int a) {
+ return [](char b) {
+ return b;
+ };
+ };
+ L(3)('a');
+ return L;
+}
+
+template<typename T>
+auto foo2() {
+ return [](const T&) { return 42; };
+}
+
+auto use = foo2<int>();
+
+}
+//CHECK-LABEL: define linkonce_odr void @_ZN22inline_member_function1X3fooEv(%"struct.inline_member_function::X"* %this)
+//CHECK-LABEL: define linkonce_odr void @_ZZN22inline_member_function1X3fooEvENKUliE_clEi(%class.anon
+//CHECK-LABEL: define linkonce_odr signext i8 @_ZZZN22inline_member_function1X3fooEvENKUliE_clEiENKUlcE_clEc(%class.anon
+
+namespace inline_member_function {
+struct X {
+auto foo() {
+ auto L = [](int a) {
+ return [](char b) {
+ return b;
+ };
+ };
+ return L;
+}
+};
+
+auto run1 = X{}.foo()(3)('a');
+
+template<typename S>
+struct A {
+ template<typename T> static auto default_lambda() {
+ return [](const T&) { return 42; };
+ }
+
+ template<class U = decltype(default_lambda<S>())>
+ U func(U u = default_lambda<S>()) { return u; }
+
+ template<class T> auto foo() { return [](const T&) { return 42; }; }
+};
+//CHECK-LABEL: define linkonce_odr i32 @_ZZN22inline_member_function1AIdE14default_lambdaIdEEDavENKUlRKdE_clES5_(%class.anon
+int run2 = A<double>{}.func()(3.14);
+
+//CHECK-LABEL: define linkonce_odr i32 @_ZZN22inline_member_function1AIcE14default_lambdaIcEEDavENKUlRKcE_clES5_(%class.anon
+int run3 = A<char>{}.func()('a');
+} // end inline_member_function
+
+
+// CHECK-LABEL: define linkonce_odr void @_ZN15inline_function3fooEv()
+// CHECK: define linkonce_odr void @_ZZN15inline_function3fooEvENKUliE_clEi(%class.anon
+// CHECK: define linkonce_odr signext i8 @_ZZZN15inline_function3fooEvENKUliE_clEiENKUlcE_clEc(%class.anon
+namespace inline_function {
+inline auto foo() {
+ auto L = [](int a) {
+ return [](char b) {
+ return b;
+ };
+ };
+ return L;
+}
+auto use = foo()(3)('a');
+}
+
diff --git a/test/CodeGenCXX/lambda-expressions-nested-linkage.cpp b/test/CodeGenCXX/lambda-expressions-nested-linkage.cpp
new file mode 100644
index 0000000..accc5d2
--- /dev/null
+++ b/test/CodeGenCXX/lambda-expressions-nested-linkage.cpp
@@ -0,0 +1,50 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10.0.0 -fblocks -emit-llvm -o - %s -fexceptions -std=c++11 | FileCheck %s
+
+// CHECK-LABEL: define void @_ZN19non_inline_function3fooEv()
+// CHECK-LABEL: define internal void @"_ZZN19non_inline_function3fooEvENK3$_0clEi"(%class.anon
+// CHECK-LABEL: define internal signext i8 @"_ZZZN19non_inline_function3fooEvENK3$_0clEiENKUlcE_clEc"(%class.anon
+namespace non_inline_function {
+void foo() {
+ auto L = [](int a) {
+ return [](char b) {
+ return b;
+ };
+ };
+ L(3)('a');
+}
+}
+
+namespace non_template {
+ struct L {
+ int t = ([](int a) { return [](int b) { return b; };})(2)(3);
+ };
+ L l;
+}
+
+namespace lambdas_in_NSDMIs_template_class {
+template<class T>
+struct L {
+ T t2 = ([](int a) { return [](int b) { return b; };})(T{})(T{});
+};
+L<int> l;
+}
+
+// CHECK-LABEL: define linkonce_odr i32 @_ZN15inline_function3fooEv
+// CHECK: define linkonce_odr void @_ZZN15inline_function3fooEvENKUliE_clEi
+// CHECK: define linkonce_odr signext i8 @_ZZZN15inline_function3fooEvENKUliE_clEiENKUlcE_clEc
+namespace inline_function {
+inline int foo() {
+ auto L = [](int a) {
+ return [](char b) {
+ return b;
+ };
+ };
+ L(3)('a');
+}
+int use = foo();
+}
+// CHECK: define linkonce_odr void @_ZNK32lambdas_in_NSDMIs_template_class1LIiEUliE_clEi(%class.anon
+// CHECK: define linkonce_odr i32 @_ZZNK32lambdas_in_NSDMIs_template_class1LIiEUliE_clEiENKUliE_clEi(%class.anon
+
+// CHECK: define linkonce_odr void @_ZNK12non_template1L1tMUliE_clEi(%class.anon
+// CHECK: define linkonce_odr i32 @_ZZNK12non_template1L1tMUliE_clEiENKUliE_clEi(%class.anon
diff --git a/test/CodeGenCXX/lambda-expressions.cpp b/test/CodeGenCXX/lambda-expressions.cpp
index 68ae68f..2f9a4f2 100644
--- a/test/CodeGenCXX/lambda-expressions.cpp
+++ b/test/CodeGenCXX/lambda-expressions.cpp
@@ -11,27 +11,27 @@ void *use = &used;
extern "C" auto cvar = []{};
int a() { return []{ return 1; }(); }
-// CHECK: define i32 @_Z1av
+// CHECK-LABEL: define i32 @_Z1av
// CHECK: call i32 @"_ZZ1avENK3$_0clEv"
-// CHECK: define internal i32 @"_ZZ1avENK3$_0clEv"
+// CHECK-LABEL: define internal i32 @"_ZZ1avENK3$_0clEv"
// CHECK: ret i32 1
int b(int x) { return [x]{return x;}(); }
-// CHECK: define i32 @_Z1bi
+// CHECK-LABEL: define i32 @_Z1bi
// CHECK: store i32
// CHECK: load i32*
// CHECK: store i32
// CHECK: call i32 @"_ZZ1biENK3$_1clEv"
-// CHECK: define internal i32 @"_ZZ1biENK3$_1clEv"
+// CHECK-LABEL: define internal i32 @"_ZZ1biENK3$_1clEv"
// CHECK: load i32*
// CHECK: ret i32
int c(int x) { return [&x]{return x;}(); }
-// CHECK: define i32 @_Z1ci
+// CHECK-LABEL: define i32 @_Z1ci
// CHECK: store i32
// CHECK: store i32*
// CHECK: call i32 @"_ZZ1ciENK3$_2clEv"
-// CHECK: define internal i32 @"_ZZ1ciENK3$_2clEv"
+// CHECK-LABEL: define internal i32 @"_ZZ1ciENK3$_2clEv"
// CHECK: load i32**
// CHECK: load i32*
// CHECK: ret i32
@@ -39,32 +39,32 @@ int c(int x) { return [&x]{return x;}(); }
struct D { D(); D(const D&); int x; };
int d(int x) { D y[10]; [x,y] { return y[x].x; }(); }
-// CHECK: define i32 @_Z1di
+// CHECK-LABEL: define i32 @_Z1di
// CHECK: call void @_ZN1DC1Ev
// CHECK: icmp ult i64 %{{.*}}, 10
// CHECK: call void @_ZN1DC1ERKS_
// CHECK: call i32 @"_ZZ1diENK3$_3clEv"
-// CHECK: define internal i32 @"_ZZ1diENK3$_3clEv"
+// CHECK-LABEL: define internal i32 @"_ZZ1diENK3$_3clEv"
// CHECK: load i32*
// CHECK: load i32*
// CHECK: ret i32
struct E { E(); E(const E&); ~E(); int x; };
int e(E a, E b, bool cond) { [a,b,cond](){ return (cond ? a : b).x; }(); }
-// CHECK: define i32 @_Z1e1ES_b
+// CHECK-LABEL: define i32 @_Z1e1ES_b
// CHECK: call void @_ZN1EC1ERKS_
// CHECK: invoke void @_ZN1EC1ERKS_
// CHECK: invoke i32 @"_ZZ1e1ES_bENK3$_4clEv"
// CHECK: call void @"_ZZ1e1ES_bEN3$_4D1Ev"
// CHECK: call void @"_ZZ1e1ES_bEN3$_4D1Ev"
-// CHECK: define internal i32 @"_ZZ1e1ES_bENK3$_4clEv"
+// CHECK-LABEL: define internal i32 @"_ZZ1e1ES_bENK3$_4clEv"
// CHECK: trunc i8
// CHECK: load i32*
// CHECK: ret i32
void f() {
- // CHECK: define void @_Z1fv()
+ // CHECK-LABEL: define void @_Z1fv()
// CHECK: @"_ZZ1fvENK3$_5cvPFiiiEEv"
// CHECK-NEXT: store i32 (i32, i32)*
// CHECK-NEXT: ret void
@@ -74,7 +74,7 @@ void f() {
static int k;
int g() {
int &r = k;
- // CHECK: define internal i32 @"_ZZ1gvENK3$_6clEv"(
+ // CHECK-LABEL: define internal i32 @"_ZZ1gvENK3$_6clEv"(
// CHECK-NOT: }
// CHECK: load i32* @_ZL1k,
return [] { return r; } ();
@@ -100,7 +100,7 @@ void h() {
A (*h)() = [] { return A(); };
}
-// CHECK: define internal i32 @"_ZZ1fvEN3$_58__invokeEii"
+// CHECK-LABEL: define internal i32 @"_ZZ1fvEN3$_58__invokeEii"
// CHECK: store i32
// CHECK-NEXT: store i32
// CHECK-NEXT: load i32*
@@ -108,7 +108,7 @@ void h() {
// CHECK-NEXT: call i32 @"_ZZ1fvENK3$_5clEii"
// CHECK-NEXT: ret i32
-// CHECK: define internal void @"_ZZ1e1ES_bEN3$_4D2Ev"
+// CHECK-LABEL: define internal void @"_ZZ1e1ES_bEN3$_4D2Ev"
// <rdar://problem/12778708>
struct XXX {};
diff --git a/test/CodeGenCXX/linetable-cleanup.cpp b/test/CodeGenCXX/linetable-cleanup.cpp
index 4077af6..96b8572 100644
--- a/test/CodeGenCXX/linetable-cleanup.cpp
+++ b/test/CodeGenCXX/linetable-cleanup.cpp
@@ -1,12 +1,18 @@
// RUN: %clang_cc1 -emit-llvm -g -triple x86_64-apple-darwin10 %s -o - | FileCheck %s
-// Check the line numbers for cleanup code with EH in combinatin with
+// Check the line numbers for cleanup code with EH in combination with
// simple return expressions.
// CHECK: define {{.*}}foo
// CHECK: call void @_ZN1CD1Ev(%class.C* {{.*}}), !dbg ![[CLEANUP:[0-9]+]]
// CHECK: ret i32 0, !dbg ![[RET:[0-9]+]]
+// CHECK: define {{.*}}bar
+// CHECK: ret void, !dbg ![[RETBAR:[0-9]+]]
+
+// CHECK: define {{.*}}baz
+// CHECK: ret void, !dbg ![[RETBAZ:[0-9]+]]
+
class C {
public:
~C() {}
@@ -22,3 +28,31 @@ int foo()
return 0;
// CHECK: ![[RET]] = metadata !{i32 [[@LINE+1]], i32 0, metadata !{{.*}}, null}
}
+
+void bar()
+{
+ if (!foo())
+ // CHECK: {{.*}} = metadata !{i32 [[@LINE+1]], i32 0, metadata !{{.*}}, null}
+ return;
+
+ if (foo()) {
+ C c;
+ c.i = foo();
+ }
+ // Clang creates only a single ret instruction. Make sure it is at a useful line.
+ // CHECK: ![[RETBAR]] = metadata !{i32 [[@LINE+1]], i32 0, metadata !{{.*}}, null}
+}
+
+void baz()
+{
+ if (!foo())
+ // CHECK: {{.*}} = metadata !{i32 [[@LINE+1]], i32 0, metadata !{{.*}}, null}
+ return;
+
+ if (foo()) {
+ // no cleanup
+ // CHECK: {{.*}} = metadata !{i32 [[@LINE+1]], i32 0, metadata !{{.*}}, null}
+ return;
+ }
+ // CHECK: ![[RETBAZ]] = metadata !{i32 [[@LINE+1]], i32 0, metadata !{{.*}}, null}
+}
diff --git a/test/CodeGenCXX/linkage.cpp b/test/CodeGenCXX/linkage.cpp
new file mode 100644
index 0000000..19f1b20
--- /dev/null
+++ b/test/CodeGenCXX/linkage.cpp
@@ -0,0 +1,222 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -std=c++11 -O1 -disable-llvm-optzns %s -o - | FileCheck %s
+
+namespace test1 {
+ // CHECK-DAG-LABEL: define linkonce_odr void @_ZN5test11fIZNS_1gEvE1SEEvT_(
+ template <typename T> void f(T) {}
+ inline void *g() {
+ struct S {
+ } s;
+ return reinterpret_cast<void *>(f<S>);
+ }
+ void *h() { return g(); }
+}
+
+namespace test2 {
+ // CHECK-DAG-LABEL: define internal void @_ZN5test21fIZNS_L1gEvE1SEEvT_(
+ template <typename T> void f(T) {}
+ static inline void *g() {
+ struct S {
+ } s;
+ return reinterpret_cast<void *>(f<S>);
+ }
+ void *h() { return g(); }
+}
+
+namespace test3 {
+ // CHECK-DAG-LABEL: define internal void @_ZN5test31fIZNS_1gEvE1SEEvT_(
+ template <typename T> void f(T) {}
+ void *g() {
+ struct S {
+ } s;
+ return reinterpret_cast<void *>(f<S>);
+ }
+ void *h() { return g(); }
+}
+
+namespace test4 {
+ // CHECK-DAG-LABEL: define linkonce_odr void @_ZN5test41fIZNS_1gILi1EEEPvvE1SEEvT_(
+ template <typename T> void f(T) {}
+ template <int N> inline void *g() {
+ struct S {
+ } s;
+ return reinterpret_cast<void *>(f<S>);
+ }
+ extern template void *g<1>();
+ template void *g<1>();
+}
+
+namespace test5 {
+ // CHECK-DAG-LABEL: define linkonce_odr void @_ZN5test51fIZNS_1gILi1EEEPvvE1SEEvT_(
+ template <typename T> void f(T) {}
+ template <int N> inline void *g() {
+ struct S {
+ } s;
+ return reinterpret_cast<void *>(f<S>);
+ }
+ extern template void *g<1>();
+ void *h() { return g<1>(); }
+}
+
+namespace test6 {
+ // CHECK-DAG-LABEL: define linkonce_odr void @_ZN5test61fIZZNS_1gEvEN1S1hEvE1TEEvv(
+ template <typename T> void f() {}
+
+ inline void *g() {
+ struct S {
+ void *h() {
+ struct T {
+ };
+ return (void *)f<T>;
+ }
+ } s;
+ return s.h();
+ }
+
+ void *h() { return g(); }
+}
+
+namespace test7 {
+ // CHECK-DAG-LABEL: define internal void @_ZN5test71fIZZNS_1gEvEN1S1hEvE1TEEvv(
+ template <typename T> void f() {}
+
+ void *g() {
+ struct S {
+ void *h() {
+ struct T {
+ };
+ return (void *)f<T>;
+ }
+ } s;
+ return s.h();
+ }
+
+ void *h() { return g(); }
+}
+
+namespace test8 {
+ // CHECK-DAG-LABEL: define linkonce_odr void @_ZN5test81fIZNS_1gEvE1SEEvT_(
+ template <typename T> void f(T) {}
+ inline void *g() {
+ enum S {
+ };
+ return reinterpret_cast<void *>(f<S>);
+ }
+ void *h() { return g(); }
+}
+
+namespace test9 {
+ // CHECK-DAG-LABEL: define linkonce_odr void @_ZN5test91fIPZNS_1gEvE1SEEvT_(
+ template <typename T> void f(T) {}
+ inline void *g() {
+ struct S {
+ } s;
+ return reinterpret_cast<void *>(f<S*>);
+ }
+ void *h() { return g(); }
+}
+
+namespace test10 {
+ // CHECK-DAG-LABEL: define linkonce_odr void @_ZN6test101fIPFZNS_1gEvE1SvEEEvT_(
+ template <typename T> void f(T) {}
+ inline void *g() {
+ struct S {
+ } s;
+ typedef S(*ftype)();
+ return reinterpret_cast<void *>(f<ftype>);
+ }
+ void *h() { return g(); }
+}
+
+namespace test11 {
+ // CHECK-DAG-LABEL: define internal void @_ZN6test111fIPFZNS_1gEvE1SPNS_12_GLOBAL__N_11IEEEEvT_(
+ namespace {
+ struct I {
+ };
+ }
+
+ template <typename T> void f(T) {}
+ inline void *g() {
+ struct S {
+ };
+ typedef S(*ftype)(I * x);
+ return reinterpret_cast<void *>(f<ftype>);
+ }
+ void *h() { return g(); }
+}
+
+namespace test12 {
+ // CHECK-DAG-LABEL: define linkonce_odr void @_ZN6test123fooIZNS_3barIZNS_3zedEvE2S2EEPvvE2S1EEvv
+ template <typename T> void foo() {}
+ template <typename T> inline void *bar() {
+ enum S1 {
+ };
+ return reinterpret_cast<void *>(foo<S1>);
+ }
+ inline void *zed() {
+ enum S2 {
+ };
+ return reinterpret_cast<void *>(bar<S2>);
+ }
+ void *h() { return zed(); }
+}
+
+namespace test13 {
+ // CHECK-DAG-LABEL: define linkonce_odr void @_ZZN6test133fooEvEN1S3barEv(
+ inline void *foo() {
+ struct S {
+ static void bar() {}
+ };
+ return (void *)S::bar;
+ }
+ void *zed() { return foo(); }
+}
+
+namespace test14 {
+ // CHECK-DAG-LABEL: define linkonce_odr void @_ZN6test143fooIZNS_1fEvE1SE3barILPS1_0EEEvv(
+ template <typename T> struct foo {
+ template <T *P> static void bar() {}
+ static void *g() { return (void *)bar<nullptr>; }
+ };
+ inline void *f() {
+ struct S {
+ };
+ return foo<S>::g();
+ }
+ void h() { f(); }
+}
+
+namespace test15 {
+ // CHECK-DAG-LABEL: define linkonce_odr void @_ZN6test153zedIZNS_3fooIiEEPvvE3barEEvv(
+ template <class T> void zed() {}
+ template <class T> void *foo() {
+ class bar {
+ };
+ return reinterpret_cast<void *>(zed<bar>);
+ }
+ void test() { foo<int>(); }
+}
+
+namespace test16 {
+ // CHECK-DAG-LABEL: define linkonce_odr void @_ZN6test163zedIZNS_3fooIiE3barEvE1SEEvv(
+ template <class T> void zed() {}
+ template <class T> struct foo {
+ static void *bar();
+ };
+ template <class T> void *foo<T>::bar() {
+ class S {
+ };
+ return reinterpret_cast<void *>(zed<S>);
+ }
+ void *test() { return foo<int>::bar(); }
+}
+
+namespace test17 {
+ // CHECK-DAG: @_ZZN6test173fooILi42EEEPivE3bar = linkonce_odr
+ // CHECK-DAG-LABEL: define weak_odr i32* @_ZN6test173fooILi42EEEPiv(
+ template<int I>
+ int *foo() {
+ static int bar;
+ return &bar;
+ }
+ template int *foo<42>();
+}
diff --git a/test/CodeGenCXX/lpad-linetable.cpp b/test/CodeGenCXX/lpad-linetable.cpp
new file mode 100644
index 0000000..dba2ad6
--- /dev/null
+++ b/test/CodeGenCXX/lpad-linetable.cpp
@@ -0,0 +1,69 @@
+// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -emit-llvm -g -triple x86_64-apple-darwin10 %s -o - | FileCheck %s
+// The landing pad should have the line number of the closing brace of the function.
+// rdar://problem/13888152
+// CHECK: ret i32
+// CHECK: landingpad {{.*}}
+// CHECK-NEXT: !dbg ![[LPAD:[0-9]+]]
+// CHECK: ![[LPAD]] = metadata !{i32 24, i32 0, metadata !{{.*}}, null}
+
+# 1 "/usr/include/c++/4.2.1/vector" 1 3
+typedef long unsigned int __darwin_size_t;
+typedef __darwin_size_t size_t;
+namespace std {
+ template<typename _Tp>
+ class allocator
+ {
+ public:
+ template<typename _Tp1>
+ struct rebind
+ { typedef allocator<_Tp1> other; };
+ ~allocator() throw() { }
+ };
+ template<typename _Tp, typename _Alloc>
+ struct _Vector_base
+ {
+ typedef typename _Alloc::template rebind<_Tp>::other _Tp_alloc_type;
+ struct _Vector_impl
+ {
+ _Vector_impl(_Tp_alloc_type const& __a) { }
+ };
+ typedef _Alloc allocator_type;
+ _Vector_base(const allocator_type& __a)
+ : _M_impl(__a)
+ { }
+ ~_Vector_base() { }
+ _Vector_impl _M_impl;
+ };
+ template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
+ class vector
+ : protected _Vector_base<_Tp, _Alloc>
+ {
+ typedef _Vector_base<_Tp, _Alloc> _Base;
+ public:
+ typedef _Tp value_type;
+ typedef size_t size_type;
+ typedef _Alloc allocator_type;
+ vector(const allocator_type& __a = allocator_type())
+ : _Base(__a)
+ { }
+ size_type
+ push_back(const value_type& __x)
+ {}
+ };
+}
+# 10 "main.cpp" 2
+
+
+
+
+int main (int argc, char const *argv[], char const *envp[])
+{ // 15
+ std::vector<long> longs;
+ std::vector<short> shorts;
+ for (int i=0; i<12; i++)
+ {
+ longs.push_back(i);
+ shorts.push_back(i);
+ }
+ return 0; // 23
+} // 24
diff --git a/test/CodeGenCXX/lvalue-bitcasts.cpp b/test/CodeGenCXX/lvalue-bitcasts.cpp
index 8c5fa4a..86355b2 100644
--- a/test/CodeGenCXX/lvalue-bitcasts.cpp
+++ b/test/CodeGenCXX/lvalue-bitcasts.cpp
@@ -3,7 +3,7 @@
struct X { int i; float f; };
struct Y { X x; };
-// CHECK: define void @_Z21reinterpret_cast_testRiRfR1X
+// CHECK-LABEL: define void @_Z21reinterpret_cast_testRiRfR1X
void reinterpret_cast_test(int &ir, float &fr, X &xr) {
// CHECK: load float**
// CHECK: bitcast float*
@@ -48,7 +48,7 @@ void reinterpret_cast_test(int &ir, float &fr, X &xr) {
// CHECK: ret void
}
-// CHECK: define void @_Z6c_castRiRfR1X
+// CHECK-LABEL: define void @_Z6c_castRiRfR1X
void c_cast(int &ir, float &fr, X &xr) {
// CHECK: load float**
// CHECK: bitcast float*
@@ -93,7 +93,7 @@ void c_cast(int &ir, float &fr, X &xr) {
// CHECK: ret void
}
-// CHECK: define void @_Z15functional_castRiRfR1X
+// CHECK-LABEL: define void @_Z15functional_castRiRfR1X
void functional_cast(int &ir, float &fr, X &xr) {
typedef int &intref;
typedef float &floatref;
diff --git a/test/CodeGenCXX/mangle-98.cpp b/test/CodeGenCXX/mangle-98.cpp
index a9ab6ca..a329caf 100644
--- a/test/CodeGenCXX/mangle-98.cpp
+++ b/test/CodeGenCXX/mangle-98.cpp
@@ -2,11 +2,11 @@
template <bool B> struct S3 {};
-// CHECK: define void @_Z1f2S3ILb1EE
+// CHECK-LABEL: define void @_Z1f2S3ILb1EE
void f(S3<true>) {}
-// CHECK: define void @_Z1f2S3ILb0EE
+// CHECK-LABEL: define void @_Z1f2S3ILb0EE
void f(S3<false>) {}
-// CHECK: define void @_Z2f22S3ILb1EE
+// CHECK-LABEL: define void @_Z2f22S3ILb1EE
void f2(S3<100>) {}
diff --git a/test/CodeGenCXX/mangle-address-space.cpp b/test/CodeGenCXX/mangle-address-space.cpp
index ff23c20..4a4a1f3 100644
--- a/test/CodeGenCXX/mangle-address-space.cpp
+++ b/test/CodeGenCXX/mangle-address-space.cpp
@@ -1,12 +1,12 @@
// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s
-// CHECK: define void @_Z2f0Pc
+// CHECK-LABEL: define void @_Z2f0Pc
void f0(char *p) { }
-// CHECK: define void @_Z2f0PU3AS1c
+// CHECK-LABEL: define void @_Z2f0PU3AS1c
void f0(char __attribute__((address_space(1))) *p) { }
struct OpaqueType;
typedef OpaqueType __attribute__((address_space(100))) * OpaqueTypePtr;
-// CHECK: define void @_Z2f0PU5AS10010OpaqueType
+// CHECK-LABEL: define void @_Z2f0PU5AS10010OpaqueType
void f0(OpaqueTypePtr) { }
diff --git a/test/CodeGenCXX/mangle-alias-template.cpp b/test/CodeGenCXX/mangle-alias-template.cpp
index 5ace0b0..b6719c5 100644
--- a/test/CodeGenCXX/mangle-alias-template.cpp
+++ b/test/CodeGenCXX/mangle-alias-template.cpp
@@ -15,7 +15,7 @@ template<typename,typename,typename> struct S {};
template<typename T, typename U> using U = S<T, int, U>;
template<typename...Ts> void h(U<Ts...>, Ts...);
-// CHECK: define void @_Z1zv(
+// CHECK-LABEL: define void @_Z1zv(
void z() {
vector<int> VI;
f(VI);
diff --git a/test/CodeGenCXX/mangle-exprs.cpp b/test/CodeGenCXX/mangle-exprs.cpp
index 2d7a883..e935f51 100644
--- a/test/CodeGenCXX/mangle-exprs.cpp
+++ b/test/CodeGenCXX/mangle-exprs.cpp
@@ -70,22 +70,22 @@ namespace Casts {
template <int N> T<N> f() { return T<N>(); }
- // CHECK: define weak_odr void @_ZN5Casts8implicitILj4EEEvPN9enable_ifIXleT_Li4EEvE4typeE
+ // CHECK-LABEL: define weak_odr void @_ZN5Casts8implicitILj4EEEvPN9enable_ifIXleT_Li4EEvE4typeE
template void implicit<4>(void*);
- // CHECK: define weak_odr void @_ZN5Casts6cstyleILj4EEEvPN9enable_ifIXleT_cvjLi4EEvE4typeE
+ // CHECK-LABEL: define weak_odr void @_ZN5Casts6cstyleILj4EEEvPN9enable_ifIXleT_cvjLi4EEvE4typeE
template void cstyle<4>(void*);
- // CHECK: define weak_odr void @_ZN5Casts10functionalILj4EEEvPN9enable_ifIXleT_cvjLi4EEvE4typeE
+ // CHECK-LABEL: define weak_odr void @_ZN5Casts10functionalILj4EEEvPN9enable_ifIXleT_cvjLi4EEvE4typeE
template void functional<4>(void*);
- // CHECK: define weak_odr void @_ZN5Casts7static_ILj4EEEvPN9enable_ifIXleT_cvjLi4EEvE4typeE
+ // CHECK-LABEL: define weak_odr void @_ZN5Casts7static_ILj4EEEvPN9enable_ifIXleT_cvjLi4EEvE4typeE
template void static_<4>(void*);
- // CHECK: define weak_odr void @_ZN5Casts1fILi6EEENS_1TIXT_EEEv
+ // CHECK-LABEL: define weak_odr void @_ZN5Casts1fILi6EEENS_1TIXT_EEEv
template T<6> f<6>();
- // CHECK: define weak_odr void @_ZN5Casts5auto_IiEEvDTnw_DapicvT__EEE(
+ // CHECK-LABEL: define weak_odr void @_ZN5Casts5auto_IiEEvDTnw_DapicvT__EEE(
template void auto_<int>(int*);
- // CHECK: define weak_odr void @_ZN5Casts7scalar_IiEEvDTcmcvT__Ecvi_EE(
+ // CHECK-LABEL: define weak_odr void @_ZN5Casts7scalar_IiEEvDTcmcvT__Ecvi_EE(
template void scalar_<int>(int);
}
@@ -93,10 +93,10 @@ namespace test1 {
short foo(short);
int foo(int);
- // CHECK: define linkonce_odr signext i16 @_ZN5test11aIsEEDTcl3foocvT__EEES1_(
+ // CHECK-LABEL: define linkonce_odr signext i16 @_ZN5test11aIsEEDTcl3foocvT__EEES1_(
template <class T> auto a(T t) -> decltype(foo(T())) { return foo(t); }
- // CHECK: define linkonce_odr signext i16 @_ZN5test11bIsEEDTcp3foocvT__EEES1_(
+ // CHECK-LABEL: define linkonce_odr signext i16 @_ZN5test11bIsEEDTcp3foocvT__EEES1_(
template <class T> auto b(T t) -> decltype((foo)(T())) { return (foo)(t); }
void test(short s) {
@@ -124,7 +124,7 @@ namespace test2 {
float baz(float(*)());
void fred(float(*)(), float);
- // CHECK: define void @_ZN5test211instantiateEv
+ // CHECK-LABEL: define void @_ZN5test211instantiateEv
void instantiate() {
// CHECK: call void @_ZN5test21aIPFfvEEEvT_DTclfL0p_EE(
a(foo, 0.0f);
@@ -156,7 +156,7 @@ namespace test3 {
int *member;
};
- // CHECK: define void @_ZN5test311instantiateEv
+ // CHECK-LABEL: define void @_ZN5test311instantiateEv
void instantiate() {
X x;
int *ip;
diff --git a/test/CodeGenCXX/mangle-extreme.cpp b/test/CodeGenCXX/mangle-extreme.cpp
index ef2d466..9fa678a 100644
--- a/test/CodeGenCXX/mangle-extreme.cpp
+++ b/test/CodeGenCXX/mangle-extreme.cpp
@@ -2,7 +2,7 @@
struct X { };
-// CHECK: define void @_Z1fPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP1XS13_S12_S11_S10_SZ_SY_SX_SW_SV_SU_ST_SS_SR_SQ_SP_SO_SN_SM_SL_SK_SJ_SI_SH_SG_SF_SE_SD_SC_SB_SA_S9_S8_S7_S6_S5_S4_S3_S2_S1_S0_S_(
+// CHECK-LABEL: define void @_Z1fPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP1XS13_S12_S11_S10_SZ_SY_SX_SW_SV_SU_ST_SS_SR_SQ_SP_SO_SN_SM_SL_SK_SJ_SI_SH_SG_SF_SE_SD_SC_SB_SA_S9_S8_S7_S6_S5_S4_S3_S2_S1_S0_S_(
void f(X****************************************,
X****************************************,
X***************************************,
diff --git a/test/CodeGenCXX/mangle-lambdas.cpp b/test/CodeGenCXX/mangle-lambdas.cpp
index 0bd5ad2..659b437 100644
--- a/test/CodeGenCXX/mangle-lambdas.cpp
+++ b/test/CodeGenCXX/mangle-lambdas.cpp
@@ -1,11 +1,11 @@
// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-macosx10.7.0 -emit-llvm -o - %s | FileCheck %s
// CHECK: @_ZZNK7PR12917IJiiEE1nMUlvE_clEvE1n = linkonce_odr global i32 0
-// CHECK: @_ZZN7PR12917IJicdEEC1EicdEd_N1nE = linkonce_odr global i32 0
-// CHECK: @_ZZN7PR12917IJicdEEC1EicdEd0_N1nE = linkonce_odr global i32 0
-// CHECK: @_ZZN7PR12917IJicdEEC1EicdEd1_N1nE = linkonce_odr global i32 0
+// CHECK: @_ZZZN7PR12917IJicdEEC1EicdEd_NKUlvE_clEvE1n = linkonce_odr global i32 0
+// CHECK: @_ZZZN7PR12917IJicdEEC1EicdEd0_NKUlvE_clEvE1n = linkonce_odr global i32 0
+// CHECK: @_ZZZN7PR12917IJicdEEC1EicdEd1_NKUlvE_clEvE1n = linkonce_odr global i32 0
-// CHECK: define linkonce_odr void @_Z11inline_funci
+// CHECK-LABEL: define linkonce_odr void @_Z11inline_funci
inline void inline_func(int n) {
// CHECK: call i32 @_ZZ11inline_funciENKUlvE_clEv
int i = []{ return 1; }();
@@ -41,7 +41,7 @@ struct S {
void S::g(int i = []{return 1;}(),
int j = []{return 2; }()) {}
-// CHECK: define void @_Z6test_S1S
+// CHECK-LABEL: define void @_Z6test_S1S
void test_S(S s) {
// CHECK: call i32 @_ZZN1S1fEiiEd0_NKUlvE_clEv
// CHECK-NEXT: call i32 @_ZZN1S1fEiiEd0_NKUlvE0_clEv
@@ -63,15 +63,15 @@ void test_S(S s) {
}
// Check the linkage of the lambda call operators used in test_S.
-// CHECK: define linkonce_odr i32 @_ZZN1S1fEiiEd0_NKUlvE_clEv
+// CHECK-LABEL: define linkonce_odr i32 @_ZZN1S1fEiiEd0_NKUlvE_clEv
// CHECK: ret i32 1
-// CHECK: define linkonce_odr i32 @_ZZN1S1fEiiEd0_NKUlvE0_clEv
+// CHECK-LABEL: define linkonce_odr i32 @_ZZN1S1fEiiEd0_NKUlvE0_clEv
// CHECK: ret i32 2
-// CHECK: define linkonce_odr i32 @_ZZN1S1fEiiEd_NKUlvE_clEv
+// CHECK-LABEL: define linkonce_odr i32 @_ZZN1S1fEiiEd_NKUlvE_clEv
// CHECK: ret i32 3
-// CHECK: define internal i32 @"_ZNK1S3$_0clEv"
+// CHECK-LABEL: define internal i32 @"_ZNK1S3$_0clEv"
// CHECK: ret i32 1
-// CHECK: define internal i32 @"_ZNK1S3$_1clEv"
+// CHECK-LABEL: define internal i32 @"_ZNK1S3$_1clEv"
// CHECK: ret i32 2
template<typename T>
@@ -81,7 +81,7 @@ struct ST {
T = []{return T(3);}());
};
-// CHECK: define void @_Z7test_ST2STIdE
+// CHECK-LABEL: define void @_Z7test_ST2STIdE
void test_ST(ST<double> st) {
// CHECK: call double @_ZZN2STIdE1fEddEd0_NKUlvE_clEv
// CHECK-NEXT: call double @_ZZN2STIdE1fEddEd0_NKUlvE0_clEv
@@ -94,11 +94,11 @@ void test_ST(ST<double> st) {
}
// Check the linkage of the lambda call operators used in test_ST.
-// CHECK: define linkonce_odr double @_ZZN2STIdE1fEddEd0_NKUlvE_clEv
+// CHECK-LABEL: define linkonce_odr double @_ZZN2STIdE1fEddEd0_NKUlvE_clEv
// CHECK: ret double 1
-// CHECK: define linkonce_odr double @_ZZN2STIdE1fEddEd0_NKUlvE0_clEv
+// CHECK-LABEL: define linkonce_odr double @_ZZN2STIdE1fEddEd0_NKUlvE0_clEv
// CHECK: ret double 2
-// CHECK: define linkonce_odr double @_ZZN2STIdE1fEddEd_NKUlvE_clEv
+// CHECK-LABEL: define linkonce_odr double @_ZZN2STIdE1fEddEd_NKUlvE_clEv
// CHECK: ret double 3
template<typename T>
@@ -106,6 +106,7 @@ struct StaticMembers {
static T x;
static T y;
static T z;
+ static int (*f)();
};
template<typename T> int accept_lambda(T);
@@ -119,39 +120,47 @@ T StaticMembers<T>::y = []{return 3;}();
template<typename T>
T StaticMembers<T>::z = accept_lambda([]{return 4;});
-// CHECK: define internal void @__cxx_global_var_init()
+template<typename T>
+int (*StaticMembers<T>::f)() = []{return 5;};
+
+// CHECK-LABEL: define internal void @__cxx_global_var_init()
// CHECK: call i32 @_ZNK13StaticMembersIfE1xMUlvE_clEv
// CHECK-NEXT: call i32 @_ZNK13StaticMembersIfE1xMUlvE0_clEv
// CHECK-NEXT: add nsw
-// CHECK: define linkonce_odr i32 @_ZNK13StaticMembersIfE1xMUlvE_clEv
+// CHECK-LABEL: define linkonce_odr i32 @_ZNK13StaticMembersIfE1xMUlvE_clEv
// CHECK: ret i32 1
-// CHECK: define linkonce_odr i32 @_ZNK13StaticMembersIfE1xMUlvE0_clEv
+// CHECK-LABEL: define linkonce_odr i32 @_ZNK13StaticMembersIfE1xMUlvE0_clEv
// CHECK: ret i32 2
template float StaticMembers<float>::x;
-// CHECK: define internal void @__cxx_global_var_init1()
+// CHECK-LABEL: define internal void @__cxx_global_var_init1()
// CHECK: call i32 @_ZNK13StaticMembersIfE1yMUlvE_clEv
-// CHECK: define linkonce_odr i32 @_ZNK13StaticMembersIfE1yMUlvE_clEv
+// CHECK-LABEL: define linkonce_odr i32 @_ZNK13StaticMembersIfE1yMUlvE_clEv
// CHECK: ret i32 3
template float StaticMembers<float>::y;
-// CHECK: define internal void @__cxx_global_var_init2()
+// CHECK-LABEL: define internal void @__cxx_global_var_init2()
// CHECK: call i32 @_Z13accept_lambdaIN13StaticMembersIfE1zMUlvE_EEiT_
// CHECK: declare i32 @_Z13accept_lambdaIN13StaticMembersIfE1zMUlvE_EEiT_()
template float StaticMembers<float>::z;
-// CHECK: define internal void @__cxx_global_var_init3
+// CHECK-LABEL: define internal void @__cxx_global_var_init3()
+// CHECK: call {{.*}} @_ZNK13StaticMembersIfE1fMUlvE_cvPFivEEv
+// CHECK-LABEL: define linkonce_odr i32 ()* @_ZNK13StaticMembersIfE1fMUlvE_cvPFivEEv
+template int (*StaticMembers<float>::f)();
+
+// CHECK-LABEL: define internal void @__cxx_global_var_init4
// CHECK: call i32 @"_ZNK13StaticMembersIdE3$_2clEv"
-// CHECK: define internal i32 @"_ZNK13StaticMembersIdE3$_2clEv"
+// CHECK-LABEL: define internal i32 @"_ZNK13StaticMembersIdE3$_2clEv"
// CHECK: ret i32 42
template<> double StaticMembers<double>::z = []{return 42; }();
template<typename T>
void func_template(T = []{ return T(); }());
-// CHECK: define void @_Z17use_func_templatev()
+// CHECK-LABEL: define void @_Z17use_func_templatev()
void use_func_template() {
- // CHECK: call i32 @"_ZZ13func_templateIiEvT_ENKS_IiE3$_3clEv"
+ // CHECK: call i32 @"_ZZ13func_templateIiEvT_ENK3$_3clEv"
func_template<int>();
}
@@ -183,7 +192,7 @@ namespace PR12123 {
};
void B::h() { f(); }
}
-// CHECK: define linkonce_odr %"struct.PR12123::A"* @_ZZN7PR121231B1fERKSt9type_infoEd_NKUlvE_clEv
+// CHECK-LABEL: define linkonce_odr %"struct.PR12123::A"* @_ZZN7PR121231B1fERKSt9type_infoEd_NKUlvE_clEv
namespace PR12808 {
template <typename> struct B {
@@ -196,11 +205,11 @@ namespace PR12808 {
void f() {
b<int>(1);
}
- // CHECK: define linkonce_odr void @_ZZN7PR128081bIiEEviENKS0_IiEUlvE_clEv
- // CHECK: define linkonce_odr i32 @_ZZZN7PR128081bIiEEviENKS0_IiEUlvE_clEvENKUlvE_clEv
+ // CHECK-LABEL: define linkonce_odr void @_ZZN7PR128081bIiEEviENKUlvE_clEv
+ // CHECK-LABEL: define linkonce_odr i32 @_ZZZN7PR128081bIiEEviENKUlvE_clEvENKUlvE_clEv
}
-// CHECK: define linkonce_odr void @_Z1fIZZNK23TestNestedInstantiationclEvENKUlvE_clEvEUlvE_EvT_
+// CHECK-LABEL: define linkonce_odr void @_Z1fIZZNK23TestNestedInstantiationclEvENKUlvE_clEvEUlvE_EvT_
struct Members {
int x = [] { return 1; }() + [] { return 2; }();
@@ -208,7 +217,7 @@ struct Members {
};
void test_Members() {
- // CHECK: define linkonce_odr void @_ZN7MembersC2Ev
+ // CHECK-LABEL: define linkonce_odr void @_ZN7MembersC2Ev
// CHECK: call i32 @_ZNK7Members1xMUlvE_clEv
// CHECK-NEXT: call i32 @_ZNK7Members1xMUlvE0_clE
// CHECK-NEXT: add nsw i32
@@ -232,21 +241,21 @@ void test_NestedInstantiation() {
}
// Check the linkage of the lambdas used in test_Members.
-// CHECK: define linkonce_odr i32 @_ZNK7Members1xMUlvE_clEv
+// CHECK-LABEL: define linkonce_odr i32 @_ZNK7Members1xMUlvE_clEv
// CHECK: ret i32 1
-// CHECK: define linkonce_odr i32 @_ZNK7Members1xMUlvE0_clEv
+// CHECK-LABEL: define linkonce_odr i32 @_ZNK7Members1xMUlvE0_clEv
// CHECK: ret i32 2
-// CHECK: define linkonce_odr i32 @_ZNK7Members1yMUlvE_clEv
+// CHECK-LABEL: define linkonce_odr i32 @_ZNK7Members1yMUlvE_clEv
// CHECK: ret i32 3
// Check linkage of the various lambdas.
-// CHECK: define linkonce_odr i32 @_ZZ11inline_funciENKUlvE_clEv
+// CHECK-LABEL: define linkonce_odr i32 @_ZZ11inline_funciENKUlvE_clEv
// CHECK: ret i32 1
-// CHECK: define linkonce_odr i32 @_ZZ11inline_funciENKUlvE0_clEv
+// CHECK-LABEL: define linkonce_odr i32 @_ZZ11inline_funciENKUlvE0_clEv
// CHECK: ret i32
-// CHECK: define linkonce_odr double @_ZZ11inline_funciENKUlvE1_clEv
+// CHECK-LABEL: define linkonce_odr double @_ZZ11inline_funciENKUlvE1_clEv
// CHECK: ret double
-// CHECK: define linkonce_odr i32 @_ZZ11inline_funciENKUliE_clEi
+// CHECK-LABEL: define linkonce_odr i32 @_ZZ11inline_funciENKUliE_clEi
// CHECK: ret i32
-// CHECK: define linkonce_odr i32 @_ZZ11inline_funciENKUlvE2_clEv
+// CHECK-LABEL: define linkonce_odr i32 @_ZZ11inline_funciENKUlvE2_clEv
// CHECK: ret i32 17
diff --git a/test/CodeGenCXX/mangle-local-class-names.cpp b/test/CodeGenCXX/mangle-local-class-names.cpp
index 3321460..8b950fc 100644
--- a/test/CodeGenCXX/mangle-local-class-names.cpp
+++ b/test/CodeGenCXX/mangle-local-class-names.cpp
@@ -55,3 +55,33 @@ void GORF (float IVAR1)
}
}
+// CHECK: @_ZZ12OmittingCodefEN4SSSSC1E_0RKf
+inline void OmittingCode(float x) {
+ if (0) {
+ struct SSSS {
+ float bv;
+ SSSS(const float& from): bv(from) { }
+ };
+
+ SSSS VAR1(x);
+ }
+
+ struct SSSS {
+ float bv;
+ SSSS(const float& from): bv(from) { }
+ };
+
+ SSSS VAR2(x);
+}
+void CallOmittingCode() { OmittingCode(1); }
+
+// CHECK: @_ZZ15LocalAnonStructvENUt0_1gEv
+inline void LocalAnonStruct() {
+ if (0) {
+ struct { void f() {} } x;
+ x.f();
+ }
+ struct { void g() {} } y;
+ y.g();
+}
+void CallLocalAnonStruct() { LocalAnonStruct(); }
diff --git a/test/CodeGenCXX/mangle-ms-arg-qualifiers.cpp b/test/CodeGenCXX/mangle-ms-arg-qualifiers.cpp
index d03ba52..50a2383 100644
--- a/test/CodeGenCXX/mangle-ms-arg-qualifiers.cpp
+++ b/test/CodeGenCXX/mangle-ms-arg-qualifiers.cpp
@@ -1,123 +1,240 @@
// RUN: %clang_cc1 -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm %s -o - -cxx-abi microsoft -triple=x86_64-pc-win32 | FileCheck -check-prefix=X64 %s
void foo(const unsigned int) {}
// CHECK: "\01?foo@@YAXI@Z"
+// X64: "\01?foo@@YAXI@Z"
void foo(const double) {}
// CHECK: "\01?foo@@YAXN@Z"
+// X64: "\01?foo@@YAXN@Z"
void bar(const volatile double) {}
// CHECK: "\01?bar@@YAXN@Z"
+// X64: "\01?bar@@YAXN@Z"
void foo_pad(char * x) {}
// CHECK: "\01?foo_pad@@YAXPAD@Z"
+// X64: "\01?foo_pad@@YAXPEAD@Z"
void foo_pbd(const char * x) {}
// CHECK: "\01?foo_pbd@@YAXPBD@Z"
+// X64: "\01?foo_pbd@@YAXPEBD@Z"
void foo_pcd(volatile char * x) {}
// CHECK: "\01?foo_pcd@@YAXPCD@Z"
+// X64: "\01?foo_pcd@@YAXPECD@Z"
void foo_qad(char * const x) {}
// CHECK: "\01?foo_qad@@YAXQAD@Z"
+// X64: "\01?foo_qad@@YAXQEAD@Z"
void foo_rad(char * volatile x) {}
// CHECK: "\01?foo_rad@@YAXRAD@Z"
+// X64: "\01?foo_rad@@YAXREAD@Z"
void foo_sad(char * const volatile x) {}
// CHECK: "\01?foo_sad@@YAXSAD@Z"
+// X64: "\01?foo_sad@@YAXSEAD@Z"
void foo_papad(char ** x) {}
// CHECK: "\01?foo_papad@@YAXPAPAD@Z"
+// X64: "\01?foo_papad@@YAXPEAPEAD@Z"
void foo_papbd(char const ** x) {}
// CHECK: "\01?foo_papbd@@YAXPAPBD@Z"
+// X64: "\01?foo_papbd@@YAXPEAPEBD@Z"
void foo_papcd(char volatile ** x) {}
// CHECK: "\01?foo_papcd@@YAXPAPCD@Z"
+// X64: "\01?foo_papcd@@YAXPEAPECD@Z"
void foo_pbqad(char * const* x) {}
// CHECK: "\01?foo_pbqad@@YAXPBQAD@Z"
+// X64: "\01?foo_pbqad@@YAXPEBQEAD@Z"
void foo_pcrad(char * volatile* x) {}
// CHECK: "\01?foo_pcrad@@YAXPCRAD@Z"
+// X64: "\01?foo_pcrad@@YAXPECREAD@Z"
void foo_qapad(char ** const x) {}
// CHECK: "\01?foo_qapad@@YAXQAPAD@Z"
+// X64: "\01?foo_qapad@@YAXQEAPEAD@Z"
void foo_rapad(char ** volatile x) {}
// CHECK: "\01?foo_rapad@@YAXRAPAD@Z"
+// X64: "\01?foo_rapad@@YAXREAPEAD@Z"
void foo_pbqbd(const char * const* x) {}
// CHECK: "\01?foo_pbqbd@@YAXPBQBD@Z"
+// X64: "\01?foo_pbqbd@@YAXPEBQEBD@Z"
void foo_pbqcd(volatile char * const* x) {}
// CHECK: "\01?foo_pbqcd@@YAXPBQCD@Z"
+// X64: "\01?foo_pbqcd@@YAXPEBQECD@Z"
void foo_pcrbd(const char * volatile* x) {}
// CHECK: "\01?foo_pcrbd@@YAXPCRBD@Z"
+// X64: "\01?foo_pcrbd@@YAXPECREBD@Z"
void foo_pcrcd(volatile char * volatile* x) {}
// CHECK: "\01?foo_pcrcd@@YAXPCRCD@Z"
+// X64: "\01?foo_pcrcd@@YAXPECRECD@Z"
void foo_aad(char &x) {}
// CHECK: "\01?foo_aad@@YAXAAD@Z"
+// X64: "\01?foo_aad@@YAXAEAD@Z"
void foo_abd(const char &x) {}
// CHECK: "\01?foo_abd@@YAXABD@Z"
+// X64: "\01?foo_abd@@YAXAEBD@Z"
void foo_aapad(char *&x) {}
// CHECK: "\01?foo_aapad@@YAXAAPAD@Z"
+// X64: "\01?foo_aapad@@YAXAEAPEAD@Z"
void foo_aapbd(const char *&x) {}
// CHECK: "\01?foo_aapbd@@YAXAAPBD@Z"
+// X64: "\01?foo_aapbd@@YAXAEAPEBD@Z"
void foo_abqad(char * const &x) {}
// CHECK: "\01?foo_abqad@@YAXABQAD@Z"
+// X64: "\01?foo_abqad@@YAXAEBQEAD@Z"
void foo_abqbd(const char * const &x) {}
// CHECK: "\01?foo_abqbd@@YAXABQBD@Z"
+// X64: "\01?foo_abqbd@@YAXAEBQEBD@Z"
void foo_aay144h(int (&x)[5][5]) {}
// CHECK: "\01?foo_aay144h@@YAXAAY144H@Z"
+// X64: "\01?foo_aay144h@@YAXAEAY144H@Z"
void foo_aay144cbh(const int (&x)[5][5]) {}
// CHECK: "\01?foo_aay144cbh@@YAXAAY144$$CBH@Z"
+// X64: "\01?foo_aay144cbh@@YAXAEAY144$$CBH@Z"
void foo_qay144h(int (&&x)[5][5]) {}
// CHECK: "\01?foo_qay144h@@YAX$$QAY144H@Z"
+// X64: "\01?foo_qay144h@@YAX$$QEAY144H@Z"
void foo_qay144cbh(const int (&&x)[5][5]) {}
// CHECK: "\01?foo_qay144cbh@@YAX$$QAY144$$CBH@Z"
+// X64: "\01?foo_qay144cbh@@YAX$$QEAY144$$CBH@Z"
void foo_p6ahxz(int x()) {}
// CHECK: "\01?foo_p6ahxz@@YAXP6AHXZ@Z"
+// X64: "\01?foo_p6ahxz@@YAXP6AHXZ@Z"
void foo_a6ahxz(int (&x)()) {}
// CHECK: "\01?foo_a6ahxz@@YAXA6AHXZ@Z"
+// X64: "\01?foo_a6ahxz@@YAXA6AHXZ@Z"
void foo_q6ahxz(int (&&x)()) {}
// CHECK: "\01?foo_q6ahxz@@YAX$$Q6AHXZ@Z"
+// X64: "\01?foo_q6ahxz@@YAX$$Q6AHXZ@Z"
void foo_qay04h(int x[5][5]) {}
// CHECK: "\01?foo_qay04h@@YAXQAY04H@Z"
+// X64: "\01?foo_qay04h@@YAXQEAY04H@Z"
void foo_qay04cbh(const int x[5][5]) {}
// CHECK: "\01?foo_qay04cbh@@YAXQAY04$$CBH@Z"
+// X64: "\01?foo_qay04cbh@@YAXQEAY04$$CBH@Z"
typedef double Vector[3];
void foo(Vector*) {}
// CHECK: "\01?foo@@YAXPAY02N@Z"
+// X64: "\01?foo@@YAXPEAY02N@Z"
void foo(Vector) {}
// CHECK: "\01?foo@@YAXQAN@Z"
+// X64: "\01?foo@@YAXQEAN@Z"
void foo_const(const Vector) {}
// CHECK: "\01?foo_const@@YAXQBN@Z"
+// X64: "\01?foo_const@@YAXQEBN@Z"
void foo_volatile(volatile Vector) {}
// CHECK: "\01?foo_volatile@@YAXQCN@Z"
+// X64: "\01?foo_volatile@@YAXQECN@Z"
void foo(Vector*, const Vector, const double) {}
// CHECK: "\01?foo@@YAXPAY02NQBNN@Z"
+// X64: "\01?foo@@YAXPEAY02NQEBNN@Z"
+
+typedef void (*ConstFunPtr)(int *const d);
+void foo_fnptrconst(ConstFunPtr f) { }
+// CHECK: "\01?foo_fnptrconst@@YAXP6AXQAH@Z@Z"
+// X64: "\01?foo_fnptrconst@@YAXP6AXQEAH@Z@Z"
+
+typedef void (*ArrayFunPtr)(int d[1]);
+void foo_fnptrarray(ArrayFunPtr f) { }
+// CHECK: "\01?foo_fnptrarray@@YAXP6AXQAH@Z@Z"
+// X64: "\01?foo_fnptrarray@@YAXP6AXQEAH@Z@Z"
+
+void foo_fnptrbackref1(ArrayFunPtr f1, ArrayFunPtr f2) { }
+// CHECK: "\01?foo_fnptrbackref1@@YAXP6AXQAH@Z1@Z"
+// X64: "\01?foo_fnptrbackref1@@YAXP6AXQEAH@Z1@Z"
+
+void foo_fnptrbackref2(ArrayFunPtr f1, ConstFunPtr f2) { }
+// CHECK: "\01?foo_fnptrbackref2@@YAXP6AXQAH@Z1@Z"
+// X64: "\01?foo_fnptrbackref2@@YAXP6AXQEAH@Z1@Z"
+
+typedef void (*NormalFunPtr)(int *d);
+void foo_fnptrbackref3(ArrayFunPtr f1, NormalFunPtr f2) { }
+// CHECK: "\01?foo_fnptrbackref3@@YAXP6AXQAH@Z1@Z"
+// X64: "\01?foo_fnptrbackref3@@YAXP6AXQEAH@Z1@Z"
+
+void foo_fnptrbackref4(NormalFunPtr f1, ArrayFunPtr f2) { }
+// CHECK: "\01?foo_fnptrbackref4@@YAXP6AXPAH@Z1@Z"
+// X64: "\01?foo_fnptrbackref4@@YAXP6AXPEAH@Z1@Z"
+
+ArrayFunPtr ret_fnptrarray() { return 0; }
+// CHECK: "\01?ret_fnptrarray@@YAP6AXQAH@ZXZ"
+// X64: "\01?ret_fnptrarray@@YAP6AXQEAH@ZXZ"
+
+// Test that we mangle the forward decl when we have a redeclaration with a
+// slightly different type.
+void mangle_fwd(char * const x);
+void mangle_fwd(char * x) {}
+// CHECK: "\01?mangle_fwd@@YAXQAD@Z"
+// X64: "\01?mangle_fwd@@YAXQEAD@Z"
+
+void mangle_no_fwd(char * x) {}
+// CHECK: "\01?mangle_no_fwd@@YAXPAD@Z"
+// X64: "\01?mangle_no_fwd@@YAXPEAD@Z"
+
+// The first argument gets mangled as-if it were written "int *const"
+// The second arg should not form a backref because it isn't qualified
+void mangle_no_backref0(int[], int *) {}
+// CHECK: "\01?mangle_no_backref0@@YAXQAHPAH@Z"
+// X64: "\01?mangle_no_backref0@@YAXQEAHPEAH@Z"
+
+void mangle_no_backref1(int[], int *const) {}
+// CHECK: "\01?mangle_no_backref1@@YAXQAHQAH@Z"
+// X64: "\01?mangle_no_backref1@@YAXQEAHQEAH@Z"
+
+typedef void fun_type(void);
+typedef void (*ptr_to_fun_type)(void);
+
+// Pointer to function types don't backref with function types
+void mangle_no_backref2(fun_type, ptr_to_fun_type) {}
+// CHECK: "\01?mangle_no_backref2@@YAXP6AXXZP6AXXZ@Z"
+// X64: "\01?mangle_no_backref2@@YAXP6AXXZP6AXXZ@Z"
+
+void mangle_yes_backref0(int[], int []) {}
+// CHECK: "\01?mangle_yes_backref0@@YAXQAH0@Z"
+// X64: "\01?mangle_yes_backref0@@YAXQEAH0@Z"
+
+void mangle_yes_backref1(int *const, int *const) {}
+// CHECK: "\01?mangle_yes_backref1@@YAXQAH0@Z"
+// X64: "\01?mangle_yes_backref1@@YAXQEAH0@Z"
+
+void mangle_yes_backref2(fun_type *const[], ptr_to_fun_type const[]) {}
+// CHECK: "\01?mangle_yes_backref2@@YAXQBQ6AXXZ0@Z"
+// X64: "\01?mangle_yes_backref2@@YAXQEBQ6AXXZ0@Z"
+
+void mangle_yes_backref3(ptr_to_fun_type *const, void (**const)(void)) {}
+// CHECK: "\01?mangle_yes_backref3@@YAXQAP6AXXZ0@Z"
+// X64: "\01?mangle_yes_backref3@@YAXQEAP6AXXZ0@Z"
diff --git a/test/CodeGenCXX/mangle-ms-back-references-pr13207.cpp b/test/CodeGenCXX/mangle-ms-back-references-pr13207.cpp
index fbc6492..e10cc8e 100644
--- a/test/CodeGenCXX/mangle-ms-back-references-pr13207.cpp
+++ b/test/CodeGenCXX/mangle-ms-back-references-pr13207.cpp
@@ -107,7 +107,7 @@ void call_l_foo(L* l) { l->foo(I<A>()); }
void foo(I<A> x) {}
// CHECK: "\01?foo@PR13207@@YAXV?$I@VA@PR13207@@@1@@Z"
void foo2(I<A> x, I<A> y) { }
-// CHECK "\01?foo2@PR13207@@YAXV?$I@VA@PR13207@@@1@0@Z"
+// CHECK: "\01?foo2@PR13207@@YAXV?$I@VA@PR13207@@@1@0@Z"
void bar(J<A,B> x) {}
// CHECK: "\01?bar@PR13207@@YAXV?$J@VA@PR13207@@VB@2@@1@@Z"
void spam(K<A,B,C> x) {}
@@ -163,3 +163,31 @@ void foobar(NC::Y<NB::Y<NA::Y<NA::X> > > x) {}
// CHECK: "\01?foobar@NC@PR13207@@YAXV?$Y@V?$Y@V?$Y@VX@NA@PR13207@@@NA@PR13207@@@NB@PR13207@@@12@@Z"
}
}
+
+// Function template names are not considered for backreferencing, but normal
+// function names are.
+namespace fn_space {
+struct RetVal { int hash; };
+template <typename T>
+RetVal fun_tmpl(const T &t) { return RetVal(); }
+RetVal fun_normal(int t) { return RetVal(); }
+void fun_instantiate() {
+ fun_normal(1);
+ fun_tmpl(1);
+}
+// CHECK: "\01?fun_normal@fn_space@@YA?AURetVal@1@H@Z"
+// CHECK: "\01??$fun_tmpl@H@fn_space@@YA?AURetVal@0@ABH@Z"
+
+template <typename T, RetVal (*F)(T)>
+RetVal fun_tmpl_recurse(T t) {
+ if (!t)
+ return RetVal();
+ return F(t - 1);
+}
+RetVal ident(int x) { return RetVal(); }
+void fun_instantiate2() {
+ fun_tmpl_recurse<int, fun_tmpl_recurse<int, ident> >(10);
+}
+// CHECK: "\01??$fun_tmpl_recurse@H$1??$fun_tmpl_recurse@H$1?ident@fn_space@@YA?AURetVal@2@H@Z@fn_space@@YA?AURetVal@1@H@Z@fn_space@@YA?AURetVal@0@H@Z"
+// CHECK: "\01??$fun_tmpl_recurse@H$1?ident@fn_space@@YA?AURetVal@2@H@Z@fn_space@@YA?AURetVal@0@H@Z"
+}
diff --git a/test/CodeGenCXX/mangle-ms-back-references.cpp b/test/CodeGenCXX/mangle-ms-back-references.cpp
index 5f93590..4f17326 100644
--- a/test/CodeGenCXX/mangle-ms-back-references.cpp
+++ b/test/CodeGenCXX/mangle-ms-back-references.cpp
@@ -61,3 +61,8 @@ void h2(void (*f_ptr)(void *), void *arg) {}
PInt3Func h3(PInt3Func x, PInt3Func y, int* z) { return 0; }
// CHECK: "\01?h3@@YAP6APAHPAH0@ZP6APAH00@Z10@Z"
+
+namespace foo {
+void foo() { }
+// CHECK: "\01?foo@0@YAXXZ"
+}
diff --git a/test/CodeGenCXX/mangle-ms-templates.cpp b/test/CodeGenCXX/mangle-ms-templates.cpp
index 10e6824..514f573 100644
--- a/test/CodeGenCXX/mangle-ms-templates.cpp
+++ b/test/CodeGenCXX/mangle-ms-templates.cpp
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -fms-extensions -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s
+// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -cxx-abi microsoft -fms-extensions -fdelayed-template-parsing -triple=i386-pc-win32 | FileCheck %s
+// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -cxx-abi microsoft -fms-extensions -fdelayed-template-parsing -triple=x86_64-pc-win32 | FileCheck -check-prefix X64 %s
template<typename T>
class Class {
@@ -23,6 +24,18 @@ class IntTemplate {
IntTemplate() {}
};
+template<long long param>
+class LongLongTemplate {
+ public:
+ LongLongTemplate() {}
+};
+
+template<unsigned long long param>
+class UnsignedLongLongTemplate {
+ public:
+ UnsignedLongLongTemplate() {}
+};
+
template<>
class BoolTemplate<true> {
public:
@@ -33,65 +46,113 @@ class BoolTemplate<true> {
void template_mangling() {
Class<Typename> c1;
// CHECK: call {{.*}} @"\01??0?$Class@VTypename@@@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$Class@VTypename@@@@QEAA@XZ"
Class<const Typename> c1_const;
// CHECK: call {{.*}} @"\01??0?$Class@$$CBVTypename@@@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$Class@$$CBVTypename@@@@QEAA@XZ"
Class<volatile Typename> c1_volatile;
// CHECK: call {{.*}} @"\01??0?$Class@$$CCVTypename@@@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$Class@$$CCVTypename@@@@QEAA@XZ"
Class<const volatile Typename> c1_cv;
// CHECK: call {{.*}} @"\01??0?$Class@$$CDVTypename@@@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$Class@$$CDVTypename@@@@QEAA@XZ"
Class<Nested<Typename> > c2;
// CHECK: call {{.*}} @"\01??0?$Class@V?$Nested@VTypename@@@@@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$Class@V?$Nested@VTypename@@@@@@QEAA@XZ"
Class<int * const> c_intpc;
// CHECK: call {{.*}} @"\01??0?$Class@QAH@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$Class@QEAH@@QEAA@XZ"
Class<int()> c_ft;
// CHECK: call {{.*}} @"\01??0?$Class@$$A6AHXZ@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$Class@$$A6AHXZ@@QEAA@XZ"
Class<int[]> c_inti;
// CHECK: call {{.*}} @"\01??0?$Class@$$BY0A@H@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$Class@$$BY0A@H@@QEAA@XZ"
Class<int[5]> c_int5;
// CHECK: call {{.*}} @"\01??0?$Class@$$BY04H@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$Class@$$BY04H@@QEAA@XZ"
Class<const int[5]> c_intc5;
// CHECK: call {{.*}} @"\01??0?$Class@$$BY04$$CBH@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$Class@$$BY04$$CBH@@QEAA@XZ"
Class<int * const[5]> c_intpc5;
// CHECK: call {{.*}} @"\01??0?$Class@$$BY04QAH@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$Class@$$BY04QEAH@@QEAA@XZ"
BoolTemplate<false> _false;
// CHECK: call {{.*}} @"\01??0?$BoolTemplate@$0A@@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$BoolTemplate@$0A@@@QEAA@XZ"
BoolTemplate<true> _true;
// PR13158
_true.Foo(1);
// CHECK: call {{.*}} @"\01??0?$BoolTemplate@$00@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$BoolTemplate@$00@@QEAA@XZ"
// CHECK: call {{.*}} @"\01??$Foo@H@?$BoolTemplate@$00@@QAEXH@Z"
+// X64: call {{.*}} @"\01??$Foo@H@?$BoolTemplate@$00@@QEAAXH@Z"
IntTemplate<0> zero;
// CHECK: call {{.*}} @"\01??0?$IntTemplate@$0A@@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$IntTemplate@$0A@@@QEAA@XZ"
IntTemplate<5> five;
// CHECK: call {{.*}} @"\01??0?$IntTemplate@$04@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$IntTemplate@$04@@QEAA@XZ"
IntTemplate<11> eleven;
// CHECK: call {{.*}} @"\01??0?$IntTemplate@$0L@@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$IntTemplate@$0L@@@QEAA@XZ"
IntTemplate<256> _256;
// CHECK: call {{.*}} @"\01??0?$IntTemplate@$0BAA@@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$IntTemplate@$0BAA@@@QEAA@XZ"
IntTemplate<513> _513;
// CHECK: call {{.*}} @"\01??0?$IntTemplate@$0CAB@@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$IntTemplate@$0CAB@@@QEAA@XZ"
IntTemplate<1026> _1026;
// CHECK: call {{.*}} @"\01??0?$IntTemplate@$0EAC@@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$IntTemplate@$0EAC@@@QEAA@XZ"
IntTemplate<65535> ffff;
// CHECK: call {{.*}} @"\01??0?$IntTemplate@$0PPPP@@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$IntTemplate@$0PPPP@@@QEAA@XZ"
+
+ IntTemplate<-1> neg_1;
+// CHECK: call {{.*}} @"\01??0?$IntTemplate@$0?0@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$IntTemplate@$0?0@@QEAA@XZ"
+ IntTemplate<-9> neg_9;
+// CHECK: call {{.*}} @"\01??0?$IntTemplate@$0?8@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$IntTemplate@$0?8@@QEAA@XZ"
+ IntTemplate<-10> neg_10;
+// CHECK: call {{.*}} @"\01??0?$IntTemplate@$0?9@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$IntTemplate@$0?9@@QEAA@XZ"
+ IntTemplate<-11> neg_11;
+// CHECK: call {{.*}} @"\01??0?$IntTemplate@$0?L@@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$IntTemplate@$0?L@@@QEAA@XZ"
+
+ LongLongTemplate<-9223372036854775807LL-1LL> int64_min;
+// CHECK: call {{.*}} @"\01??0?$LongLongTemplate@$0?IAAAAAAAAAAAAAAA@@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$LongLongTemplate@$0?IAAAAAAAAAAAAAAA@@@QEAA@XZ"
+ LongLongTemplate<9223372036854775807LL> int64_max;
+// CHECK: call {{.*}} @"\01??0?$LongLongTemplate@$0HPPPPPPPPPPPPPPP@@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$LongLongTemplate@$0HPPPPPPPPPPPPPPP@@@QEAA@XZ"
+ UnsignedLongLongTemplate<18446744073709551615ULL> uint64_max;
+// CHECK: call {{.*}} @"\01??0?$UnsignedLongLongTemplate@$0?0@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$UnsignedLongLongTemplate@$0?0@@QEAA@XZ"
+ UnsignedLongLongTemplate<(unsigned long long)-1> uint64_neg_1;
+// CHECK: call {{.*}} @"\01??0?$UnsignedLongLongTemplate@$0?0@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$UnsignedLongLongTemplate@$0?0@@QEAA@XZ"
}
namespace space {
template<class T> const T& foo(const T& l) { return l; }
}
// CHECK: "\01??$foo@H@space@@YAABHABH@Z"
+// X64: "\01??$foo@H@space@@YAAEBHAEBH@Z"
void use() {
space::foo(42);
@@ -108,4 +169,96 @@ void FunctionPointerTemplate() {
void spam() {
FunctionPointerTemplate<spam>();
// CHECK: "\01??$FunctionPointerTemplate@$1?spam@@YAXXZ@@YAXXZ"
+// X64: "\01??$FunctionPointerTemplate@$1?spam@@YAXXZ@@YAXXZ"
+}
+
+// Unlike Itanium, there is no character code to indicate an argument pack.
+// Tested with MSVC 2013, the first version which supports variadic templates.
+
+template <typename ...Ts> void variadic_fn_template(const Ts &...args) { }
+void variadic_fn_instantiate() {
+ variadic_fn_template(0, 1, 3, 4);
+ variadic_fn_template(0, 1, 'a', "b");
+}
+// CHECK: "\01??$variadic_fn_template@HHHH@@YAXABH000@Z"
+// CHECK: "\01??$variadic_fn_template@HHD$$BY01D@@YAXABH0ABDAAY01$$CBD@Z"
+
+template <typename ...Ts>
+struct VariadicClass {
+ VariadicClass() { }
+ int x;
+};
+void variadic_class_instantiate() {
+ VariadicClass<int, char, bool> a;
+ VariadicClass<bool, char, int> b;
+}
+// CHECK: call {{.*}} @"\01??0?$VariadicClass@HD_N@@QAE@XZ"
+// CHECK: call {{.*}} @"\01??0?$VariadicClass@_NDH@@QAE@XZ"
+
+template <typename T>
+struct Second {};
+
+template <typename T, template <class> class>
+struct Type {};
+
+template <template <class> class T>
+struct Type2 {};
+
+template <template <class> class T, bool B>
+struct Thing;
+
+template <template <class> class T>
+struct Thing<T, false> { };
+
+template <template <class> class T>
+struct Thing<T, true> { };
+
+void template_template_fun(Type<Thing<Second, true>, Second>) { }
+// CHECK: "\01?template_template_fun@@YAXU?$Type@U?$Thing@USecond@@$00@@USecond@@@@@Z"
+
+template <typename T>
+void template_template_specialization();
+
+template <>
+void template_template_specialization<void (Type<Thing<Second, true>, Second>)>() {
+}
+// CHECK: "\01??$template_template_specialization@$$A6AXU?$Type@U?$Thing@USecond@@$00@@USecond@@@@@Z@@YAXXZ"
+
+// PR16788
+template <decltype(nullptr)> struct S1 {};
+void f(S1<nullptr>) {}
+// CHECK: "\01?f@@YAXU?$S1@$0A@@@@Z"
+
+struct record {
+ int first;
+ int second;
+};
+template <const record &>
+struct type1 {
+};
+extern const record inst;
+void recref(type1<inst>) {}
+// CHECK: "\01?recref@@YAXU?$type1@$E?inst@@3Urecord@@B@@@Z"
+
+struct _GUID {};
+struct __declspec(uuid("{12345678-1234-1234-1234-1234567890aB}")) uuid;
+
+template <typename T, const _GUID *G = &__uuidof(T)>
+struct UUIDType1 {};
+
+template <typename T, const _GUID &G = __uuidof(T)>
+struct UUIDType2 {};
+
+void fun(UUIDType1<uuid> a) {}
+// CHECK: "\01?fun@@YAXU?$UUIDType1@Uuuid@@$1?_GUID_12345678_1234_1234_1234_1234567890ab@@3U__s_GUID@@B@@@Z"
+void fun(UUIDType2<uuid> b) {}
+// CHECK: "\01?fun@@YAXU?$UUIDType2@Uuuid@@$E?_GUID_12345678_1234_1234_1234_1234567890ab@@3U__s_GUID@@B@@@Z"
+
+template <typename T> struct TypeWithFriendDefinition {
+ friend void FunctionDefinedWithInjectedName(TypeWithFriendDefinition<T>) {}
+};
+// CHECK: call {{.*}} @"\01?FunctionDefinedWithInjectedName@@YAXU?$TypeWithFriendDefinition@H@@@Z"
+void CallFunctionDefinedWithInjectedName() {
+ FunctionDefinedWithInjectedName(TypeWithFriendDefinition<int>());
}
+// CHECK: @"\01?FunctionDefinedWithInjectedName@@YAXU?$TypeWithFriendDefinition@H@@@Z"
diff --git a/test/CodeGenCXX/mangle-ms.cpp b/test/CodeGenCXX/mangle-ms.cpp
index 1b98a84..68ec2b3 100644
--- a/test/CodeGenCXX/mangle-ms.cpp
+++ b/test/CodeGenCXX/mangle-ms.cpp
@@ -1,57 +1,51 @@
-// RUN: %clang_cc1 -fms-extensions -fblocks -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s
-// RUN: %clang_cc1 -fms-compatibility -fblocks -emit-llvm %s -o - -cxx-abi microsoft -triple=x86_64-pc-win32 | FileCheck -check-prefix X64 %s
-
-// 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"
-// CHECK: @"\01?f@foo@@2DD"
-// CHECK: @"\01?g@bar@@2HA"
-// CHECK: @"\01?h1@@3QAHA"
-// CHECK: @"\01?h2@@3QBHB"
-// CHECK: @"\01?i@@3PAY0BE@HA"
-// CHECK: @"\01?j@@3P6GHCE@ZA"
-// CHECK: @"\01?k@@3PTfoo@@DA"
-// CHECK: @"\01?l@@3P8foo@@AEHH@ZA"
-// CHECK: @"\01?color1@@3PANA"
-// CHECK: @"\01?color2@@3QBNB"
-// CHECK: @"\01?color3@@3QAY02$$CBNA"
-// CHECK: @"\01?color4@@3QAY02$$CBNA"
+// RUN: %clang_cc1 -fblocks -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 -std=c++11 | FileCheck %s
+// RUN: %clang_cc1 -fblocks -emit-llvm %s -o - -cxx-abi microsoft -triple=x86_64-pc-win32 -std=c++11| FileCheck -check-prefix X64 %s
int a;
+// CHECK-DAG: @"\01?a@@3HA"
namespace N {
int b;
+// CHECK-DAG: @"\01?b@N@@3HA"
namespace {
int anonymous;
+// CHECK-DAG: @"\01?anonymous@?A@N@@3HA"
}
}
static int c;
+// CHECK-DAG: @c
+
int _c(void) {return N::anonymous + c;}
-// CHECK: @"\01?_c@@YAHXZ"
+// CHECK-DAG: @"\01?_c@@YAHXZ"
+// X64-DAG: @"\01?_c@@YAHXZ"
class foo {
static const short d;
+// CHECK-DAG: @"\01?d@foo@@0FB"
protected:
static volatile long e;
+// CHECK-DAG: @"\01?e@foo@@1JC"
public:
static const volatile char f;
+// CHECK-DAG: @"\01?f@foo@@2DD"
int operator+(int a);
foo(){}
-//CHECK: @"\01??0foo@@QAE@XZ"
+// CHECK-DAG: @"\01??0foo@@QAE@XZ"
+// X64-DAG: @"\01??0foo@@QEAA@XZ"
~foo(){}
-//CHECK: @"\01??1foo@@QAE@XZ"
+// CHECK-DAG: @"\01??1foo@@QAE@XZ"
+// X64-DAG: @"\01??1foo@@QEAA@XZ
foo(int i){}
-//CHECK: @"\01??0foo@@QAE@H@Z"
+// CHECK-DAG: @"\01??0foo@@QAE@H@Z"
+// X64-DAG: @"\01??0foo@@QEAA@H@Z"
foo(char *q){}
-//CHECK: @"\01??0foo@@QAE@PAD@Z"
+// CHECK-DAG: @"\01??0foo@@QAE@PAD@Z"
+// X64-DAG: @"\01??0foo@@QEAA@PEAD@Z"
static foo* static_method() { return 0; }
@@ -76,13 +70,16 @@ enum quux {
};
foo bar() { return foo(); }
-//CHECK: @"\01?bar@@YA?AVfoo@@XZ"
+// CHECK-DAG: @"\01?bar@@YA?AVfoo@@XZ"
+// X64-DAG: @"\01?bar@@YA?AVfoo@@XZ"
int foo::operator+(int a) {
-//CHECK: @"\01??Hfoo@@QAEHH@Z"
+// CHECK-DAG: @"\01??Hfoo@@QAEHH@Z"
+// X64-DAG: @"\01??Hfoo@@QEAAHH@Z"
foo::static_method();
-//CHECK: @"\01?static_method@foo@@SAPAV1@XZ"
+// CHECK-DAG: @"\01?static_method@foo@@SAPAV1@XZ"
+// X64-DAG: @"\01?static_method@foo@@SAPEAV1@XZ"
bar();
return a;
}
@@ -92,106 +89,278 @@ volatile long foo::e;
const volatile char foo::f = 'C';
int bar::g;
+// CHECK-DAG: @"\01?g@bar@@2HA"
extern int * const h1 = &a;
+// CHECK-DAG: @"\01?h1@@3QAHA"
extern const int * const h2 = &a;
+// CHECK-DAG: @"\01?h2@@3QBHB"
int i[10][20];
+// CHECK-DAG: @"\01?i@@3PAY0BE@HA"
int (__stdcall *j)(signed char, unsigned char);
+// CHECK-DAG: @"\01?j@@3P6GHCE@ZA"
const volatile char foo2::*k;
+// CHECK-DAG: @"\01?k@@3PTfoo@@DT1@"
+// X64-DAG: @"\01?k@@3PETfoo@@DET1@"
int (foo2::*l)(int);
+// CHECK-DAG: @"\01?l@@3P8foo@@AEHH@ZQ1@"
// Static functions are mangled, too.
// Also make sure calling conventions, arglists, and throw specs work.
static void __stdcall alpha(float a, double b) throw() {}
bool __fastcall beta(long long a, wchar_t b) throw(signed char, unsigned char) {
-// CHECK: @"\01?beta@@YI_N_J_W@Z"
+// CHECK-DAG: @"\01?beta@@YI_N_J_W@Z"
+// X64-DAG: @"\01?beta@@YA_N_J_W@Z"
alpha(0.f, 0.0);
return false;
}
-// CHECK: @"\01?alpha@@YGXMN@Z"
-// X64: @"\01?alpha@@YAXMN@Z"
+// CHECK-DAG: @"\01?alpha@@YGXMN@Z"
+// X64-DAG: @"\01?alpha@@YAXMN@Z"
// Make sure tag-type mangling works.
void gamma(class foo, struct bar, union baz, enum quux) {}
-// CHECK: @"\01?gamma@@YAXVfoo@@Ubar@@Tbaz@@W4quux@@@Z"
+// CHECK-DAG: @"\01?gamma@@YAXVfoo@@Ubar@@Tbaz@@W4quux@@@Z"
+// X64-DAG: @"\01?gamma@@YAXVfoo@@Ubar@@Tbaz@@W4quux@@@Z"
// Make sure pointer/reference-type mangling works.
void delta(int * const a, const long &) {}
-// CHECK: @"\01?delta@@YAXQAHABJ@Z"
+// CHECK-DAG: @"\01?delta@@YAXQAHABJ@Z"
+// X64-DAG: @"\01?delta@@YAXQEAHAEBJ@Z"
// Array mangling.
void epsilon(int a[][10][20]) {}
-// CHECK: @"\01?epsilon@@YAXQAY19BE@H@Z"
+// CHECK-DAG: @"\01?epsilon@@YAXQAY19BE@H@Z"
+// X64-DAG: @"\01?epsilon@@YAXQEAY19BE@H@Z"
void zeta(int (*)(int, int)) {}
-// CHECK: @"\01?zeta@@YAXP6AHHH@Z@Z"
+// CHECK-DAG: @"\01?zeta@@YAXP6AHHH@Z@Z"
+// X64-DAG: @"\01?zeta@@YAXP6AHHH@Z@Z"
// Blocks mangling (Clang extension). A block should be mangled slightly
// differently from a similar function pointer.
void eta(int (^)(int, int)) {}
-// CHECK: @"\01?eta@@YAXP_EAHHH@Z@Z"
+// CHECK-DAG: @"\01?eta@@YAXP_EAHHH@Z@Z"
typedef int theta_arg(int,int);
void theta(theta_arg^ block) {}
-// CHECK: @"\01?theta@@YAXP_EAHHH@Z@Z"
+// CHECK-DAG: @"\01?theta@@YAXP_EAHHH@Z@Z"
void operator_new_delete() {
char *ptr = new char;
-// CHECK: @"\01??2@YAPAXI@Z"
+// CHECK-DAG: @"\01??2@YAPAXI@Z"
delete ptr;
-// CHECK: @"\01??3@YAXPAX@Z"
+// CHECK-DAG: @"\01??3@YAXPAX@Z"
char *array = new char[42];
-// CHECK: @"\01??_U@YAPAXI@Z"
+// CHECK-DAG: @"\01??_U@YAPAXI@Z"
delete [] array;
-// CHECK: @"\01??_V@YAXPAX@Z"
+// CHECK-DAG: @"\01??_V@YAXPAX@Z"
}
// PR13022
void (redundant_parens)();
void redundant_parens_use() { redundant_parens(); }
-// CHECK: @"\01?redundant_parens@@YAXXZ"
+// CHECK-DAG: @"\01?redundant_parens@@YAXXZ"
+// X64-DAG: @"\01?redundant_parens@@YAXXZ"
// PR13047
typedef double RGB[3];
RGB color1;
+// CHECK-DAG: @"\01?color1@@3PANA"
extern const RGB color2 = {};
+// CHECK-DAG: @"\01?color2@@3QBNB"
extern RGB const color3[5] = {};
+// CHECK-DAG: @"\01?color3@@3QAY02$$CBNA"
extern RGB const ((color4)[5]) = {};
+// CHECK-DAG: @"\01?color4@@3QAY02$$CBNA"
+
+struct B;
+volatile int B::* volatile memptr1;
+// X64-DAG: @"\01?memptr1@@3RESB@@HES1@"
+volatile int B::* memptr2;
+// X64-DAG: @"\01?memptr2@@3PESB@@HES1@"
+int B::* volatile memptr3;
+// X64-DAG: @"\01?memptr3@@3REQB@@HEQ1@"
+typedef int (*fun)();
+volatile fun B::* volatile funmemptr1;
+// X64-DAG: @"\01?funmemptr1@@3RESB@@R6AHXZES1@"
+volatile fun B::* funmemptr2;
+// X64-DAG: @"\01?funmemptr2@@3PESB@@R6AHXZES1@"
+fun B::* volatile funmemptr3;
+// X64-DAG: @"\01?funmemptr3@@3REQB@@P6AHXZEQ1@"
+void (B::* volatile memptrtofun1)();
+// X64-DAG: @"\01?memptrtofun1@@3R8B@@EAAXXZEQ1@"
+const void (B::* memptrtofun2)();
+// X64-DAG: @"\01?memptrtofun2@@3P8B@@EAAXXZEQ1@"
+volatile void (B::* memptrtofun3)();
+// X64-DAG: @"\01?memptrtofun3@@3P8B@@EAAXXZEQ1@"
+int (B::* volatile memptrtofun4)();
+// X64-DAG: @"\01?memptrtofun4@@3R8B@@EAAHXZEQ1@"
+volatile int (B::* memptrtofun5)();
+// X64-DAG: @"\01?memptrtofun5@@3P8B@@EAA?CHXZEQ1@"
+const int (B::* memptrtofun6)();
+// X64-DAG: @"\01?memptrtofun6@@3P8B@@EAA?BHXZEQ1@"
+fun (B::* volatile memptrtofun7)();
+// X64-DAG: @"\01?memptrtofun7@@3R8B@@EAAP6AHXZXZEQ1@"
+volatile fun (B::* memptrtofun8)();
+// X64-DAG: @"\01?memptrtofun8@@3P8B@@EAAR6AHXZXZEQ1@"
+const fun (B::* memptrtofun9)();
+// X64-DAG: @"\01?memptrtofun9@@3P8B@@EAAQ6AHXZXZEQ1@"
// PR12603
enum E {};
-// CHECK: "\01?fooE@@YA?AW4E@@XZ"
+// CHECK-DAG: "\01?fooE@@YA?AW4E@@XZ"
+// X64-DAG: "\01?fooE@@YA?AW4E@@XZ"
E fooE() { return E(); }
class X {};
-// CHECK: "\01?fooX@@YA?AVX@@XZ"
+// CHECK-DAG: "\01?fooX@@YA?AVX@@XZ"
+// X64-DAG: "\01?fooX@@YA?AVX@@XZ"
X fooX() { return X(); }
namespace PR13182 {
extern char s0[];
- // CHECK: @"\01?s0@PR13182@@3PADA"
+ // CHECK-DAG: @"\01?s0@PR13182@@3PADA"
extern char s1[42];
- // CHECK: @"\01?s1@PR13182@@3PADA"
+ // CHECK-DAG: @"\01?s1@PR13182@@3PADA"
extern const char s2[];
- // CHECK: @"\01?s2@PR13182@@3QBDB"
+ // CHECK-DAG: @"\01?s2@PR13182@@3QBDB"
extern const char s3[42];
- // CHECK: @"\01?s3@PR13182@@3QBDB"
+ // CHECK-DAG: @"\01?s3@PR13182@@3QBDB"
extern volatile char s4[];
- // CHECK: @"\01?s4@PR13182@@3RCDC"
+ // CHECK-DAG: @"\01?s4@PR13182@@3RCDC"
extern const volatile char s5[];
- // CHECK: @"\01?s5@PR13182@@3SDDD"
+ // CHECK-DAG: @"\01?s5@PR13182@@3SDDD"
extern const char* const* s6;
- // CHECK: @"\01?s6@PR13182@@3PBQBDB"
+ // CHECK-DAG: @"\01?s6@PR13182@@3PBQBDB"
char foo() {
return s0[0] + s1[0] + s2[0] + s3[0] + s4[0] + s5[0] + s6[0][0];
}
}
+
+extern "C" inline void extern_c_func() {
+ static int local;
+// CHECK-DAG: @"\01?local@?1??extern_c_func@@9@4HA"
+// X64-DAG: @"\01?local@?1??extern_c_func@@9@4HA"
+}
+
+void call_extern_c_func() {
+ extern_c_func();
+}
+
+int main() { return 0; }
+// CHECK-DAG: @main
+// X64-DAG: @main
+
+int wmain() { return 0; }
+// CHECK-DAG: @wmain
+// X64-DAG: @wmain
+
+int WinMain() { return 0; }
+// CHECK-DAG: @WinMain
+// X64-DAG: @WinMain
+
+int wWinMain() { return 0; }
+// CHECK-DAG: @wWinMain
+// X64-DAG: @wWinMain
+
+int DllMain() { return 0; }
+// CHECK-DAG: @DllMain
+// X64-DAG: @DllMain
+
+inline int inline_function_with_local_type() {
+ static struct {
+ int a_field;
+ } static_variable_in_inline_function = { 20 }, second_static = { 40 };
+ // CHECK: @"\01?static_variable_in_inline_function@?1??inline_function_with_local_type@@YAHXZ@4U<unnamed-type-static_variable_in_inline_function>@?1??1@YAHXZ@A"
+
+ return static_variable_in_inline_function.a_field + second_static.a_field;
+}
+
+int call_inline_function_with_local_type() {
+ return inline_function_with_local_type();
+}
+
+template <typename T>
+inline int templated_inline_function_with_local_type() {
+ static struct {
+ int a_field;
+ } static_variable_in_templated_inline_function = { 20 },
+ second_static = { 40 };
+ // CHECK: @"\01?static_variable_in_templated_inline_function@?1???$templated_inline_function_with_local_type@H@@YAHXZ@4U<unnamed-type-static_variable_in_templated_inline_function>@?1???$templated_inline_function_with_local_type@H@@YAHXZ@A"
+
+ return static_variable_in_templated_inline_function.a_field +
+ second_static.a_field;
+}
+
+int call_templated_inline_function_with_local_type() {
+ return templated_inline_function_with_local_type<int>();
+}
+
+// PR17371
+struct OverloadedNewDelete {
+ // __cdecl
+ void *operator new(__SIZE_TYPE__);
+ void *operator new[](__SIZE_TYPE__);
+ void operator delete(void *);
+ void operator delete[](void *);
+ // __thiscall
+ int operator+(int);
+};
+
+void *OverloadedNewDelete::operator new(__SIZE_TYPE__ s) { return 0; }
+void *OverloadedNewDelete::operator new[](__SIZE_TYPE__ s) { return 0; }
+void OverloadedNewDelete::operator delete(void *) { }
+void OverloadedNewDelete::operator delete[](void *) { }
+int OverloadedNewDelete::operator+(int x) { return x; };
+
+// CHECK-DAG: ??2OverloadedNewDelete@@SAPAXI@Z
+// CHECK-DAG: ??_UOverloadedNewDelete@@SAPAXI@Z
+// CHECK-DAG: ??3OverloadedNewDelete@@SAXPAX@Z
+// CHECK-DAG: ??_VOverloadedNewDelete@@SAXPAX@Z
+// CHECK-DAG: ??HOverloadedNewDelete@@QAEHH@Z
+
+// X64-DAG: ??2OverloadedNewDelete@@SAPEAX_K@Z
+// X64-DAG: ??_UOverloadedNewDelete@@SAPEAX_K@Z
+// X64-DAG: ??3OverloadedNewDelete@@SAXPEAX@Z
+// X64-DAG: ??_VOverloadedNewDelete@@SAXPEAX@Z
+// X64-DAG: ??HOverloadedNewDelete@@QEAAHH@Z
+
+// Indirecting the function type through a typedef will require a calling
+// convention adjustment before building the method decl.
+
+typedef void *__thiscall OperatorNewType(__SIZE_TYPE__);
+typedef void __thiscall OperatorDeleteType(void *);
+
+struct TypedefNewDelete {
+ OperatorNewType operator new;
+ OperatorNewType operator new[];
+ OperatorDeleteType operator delete;
+ OperatorDeleteType operator delete[];
+};
+
+void *TypedefNewDelete::operator new(__SIZE_TYPE__ s) { return 0; }
+void *TypedefNewDelete::operator new[](__SIZE_TYPE__ s) { return 0; }
+void TypedefNewDelete::operator delete(void *) { }
+void TypedefNewDelete::operator delete[](void *) { }
+
+// CHECK-DAG: ??2TypedefNewDelete@@SAPAXI@Z
+// CHECK-DAG: ??_UTypedefNewDelete@@SAPAXI@Z
+// CHECK-DAG: ??3TypedefNewDelete@@SAXPAX@Z
+// CHECK-DAG: ??_VTypedefNewDelete@@SAXPAX@Z
+
+namespace PR18022 {
+
+struct { } a;
+decltype(a) fun(decltype(a) x, decltype(a)) { return x; }
+// CHECK-DAG: ?fun@PR18022@@YA?AU<unnamed-type-a>@1@U21@0@Z
+
+}
diff --git a/test/CodeGenCXX/mangle-neon-vectors.cpp b/test/CodeGenCXX/mangle-neon-vectors.cpp
index 3723deb..249ec2e 100644
--- a/test/CodeGenCXX/mangle-neon-vectors.cpp
+++ b/test/CodeGenCXX/mangle-neon-vectors.cpp
@@ -1,6 +1,7 @@
-// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -triple arm-none-linux-gnueabi -target-feature +neon %s -emit-llvm -o - | FileCheck %s
typedef float float32_t;
+typedef __fp16 float16_t;
typedef signed char poly8_t;
typedef short poly16_t;
typedef unsigned long long uint64_t;
@@ -11,8 +12,10 @@ typedef __attribute__((neon_vector_type(1))) uint64_t uint64x1_t;
typedef __attribute__((neon_vector_type(2))) uint64_t uint64x2_t;
typedef __attribute__((neon_vector_type(2))) float32_t float32x2_t;
typedef __attribute__((neon_vector_type(4))) float32_t float32x4_t;
-typedef __attribute__((neon_polyvector_type(16))) poly8_t poly8x16_t;
-typedef __attribute__((neon_polyvector_type(8))) poly16_t poly16x8_t;
+typedef __attribute__((neon_vector_type(4))) float16_t float16x4_t;
+typedef __attribute__((neon_vector_type(8))) float16_t float16x8_t;
+typedef __attribute__((neon_polyvector_type(16))) poly8_t poly8x16_t;
+typedef __attribute__((neon_polyvector_type(8))) poly16_t poly16x8_t;
// CHECK: 16__simd64_int32_t
void f1(int32x2_t v) { }
@@ -26,7 +29,11 @@ void f4(uint64x2_t v) { }
void f5(float32x2_t v) { }
// CHECK: 19__simd128_float32_t
void f6(float32x4_t v) { }
+// CHECK: 18__simd64_float16_t
+void f7(float16x4_t v) {}
+// CHECK: 19__simd128_float16_t
+void f8(float16x8_t v) {}
// CHECK: 17__simd128_poly8_t
-void f7(poly8x16_t v) { }
+void f9(poly8x16_t v) {}
// CHECK: 18__simd128_poly16_t
-void f8(poly16x8_t v) { }
+void f10(poly16x8_t v) {}
diff --git a/test/CodeGenCXX/mangle-nullptr-arg.cpp b/test/CodeGenCXX/mangle-nullptr-arg.cpp
index 07bf52f..b55ea6d 100644
--- a/test/CodeGenCXX/mangle-nullptr-arg.cpp
+++ b/test/CodeGenCXX/mangle-nullptr-arg.cpp
@@ -2,15 +2,15 @@
template<int *ip> struct IP {};
-// CHECK: define void @_Z5test12IPILPi0EE
+// CHECK-LABEL: define void @_Z5test12IPILPi0EE
void test1(IP<nullptr>) {}
struct X{ };
template<int X::*pm> struct PM {};
-// CHECK: define void @_Z5test22PMILM1Xi0EE
+// CHECK-LABEL: define void @_Z5test22PMILM1Xi0EE
void test2(PM<nullptr>) { }
-// CHECK: define void @_Z5test316DependentTypePtrIPiLS0_0EE
+// CHECK-LABEL: define void @_Z5test316DependentTypePtrIPiLS0_0EE
template<typename T, T x> struct DependentTypePtr {};
void test3(DependentTypePtr<int*,nullptr>) { }
diff --git a/test/CodeGenCXX/mangle-ref-qualifiers.cpp b/test/CodeGenCXX/mangle-ref-qualifiers.cpp
index ce2af50..4552c93 100644
--- a/test/CodeGenCXX/mangle-ref-qualifiers.cpp
+++ b/test/CodeGenCXX/mangle-ref-qualifiers.cpp
@@ -5,17 +5,17 @@ struct X {
int h() const &&;
};
-// CHECK: define i32 @_ZNR1X1fEv
+// CHECK-LABEL: define i32 @_ZNR1X1fEv
int X::f() & { return 0; }
-// CHECK: define i32 @_ZNO1X1gEv
+// CHECK-LABEL: define i32 @_ZNO1X1gEv
int X::g() && { return 0; }
-// CHECK: define i32 @_ZNKO1X1hEv
+// CHECK-LABEL: define i32 @_ZNKO1X1hEv
int X::h() const && { return 0; }
-// CHECK: define void @_Z1fM1XFivREMS_FivOEMS_KFivOE
+// CHECK-LABEL: define void @_Z1fM1XFivREMS_FivOEMS_KFivOE
void f(int (X::*)() &, int (X::*)() &&, int (X::*)() const&&) { }
-// CHECK: define void @_Z1g1AIFivEES_IFivREES_IFivOEES_IKFivEES_IKFivREES_IKFivOEES_IVKFivEES_IVKFivREES_IVKFivOEE()
+// CHECK-LABEL: define void @_Z1g1AIFivEES_IFivREES_IFivOEES_IKFivEES_IKFivREES_IKFivOEES_IVKFivEES_IVKFivREES_IVKFivOEE()
template <class T> struct A {};
void g(A<int()>, A<int()&>, A<int()&&>,
A<int() const>, A<int() const &>, A<int() const &&>,
diff --git a/test/CodeGenCXX/mangle-subst-std.cpp b/test/CodeGenCXX/mangle-subst-std.cpp
index 04e3e84..6277c7a 100644
--- a/test/CodeGenCXX/mangle-subst-std.cpp
+++ b/test/CodeGenCXX/mangle-subst-std.cpp
@@ -15,8 +15,8 @@
namespace std {
struct A { A(); };
- // CHECK: define void @_ZNSt1AC1Ev(%"struct.std::A"* %this) unnamed_addr
- // CHECK: define void @_ZNSt1AC2Ev(%"struct.std::A"* %this) unnamed_addr
+ // CHECK-LABEL: define void @_ZNSt1AC1Ev(%"struct.std::A"* %this) unnamed_addr
+ // CHECK-LABEL: define void @_ZNSt1AC2Ev(%"struct.std::A"* %this) unnamed_addr
A::A() { }
};
@@ -24,14 +24,14 @@ namespace std {
template<typename> struct allocator { };
}
-// CHECK: define void @_Z1fSaIcESaIiE
+// CHECK-LABEL: define void @_Z1fSaIcESaIiE
void f(std::allocator<char>, std::allocator<int>) { }
namespace std {
template<typename, typename, typename> struct basic_string { };
}
-// CHECK: define void @_Z1fSbIcciE
+// CHECK-LABEL: define void @_Z1fSbIcciE
void f(std::basic_string<char, char, int>) { }
namespace std {
@@ -90,7 +90,7 @@ namespace std
}
// Make sure we don't treat the following like std::string
-// CHECK: define void @_Z1f12basic_stringIcSt11char_traitsIcESaIcEE
+// CHECK-LABEL: define void @_Z1f12basic_stringIcSt11char_traitsIcESaIcEE
template<typename, typename, typename> struct basic_string { };
typedef basic_string<char, std::char_traits<char>, std::allocator<char> > not_string;
void f(not_string) { }
@@ -106,7 +106,7 @@ namespace N {
namespace std {
struct A { void f(); };
- // CHECK: define void @_ZN1N3std1A1fEv
+ // CHECK-LABEL: define void @_ZN1N3std1A1fEv
void A::f() { }
}
}
diff --git a/test/CodeGenCXX/mangle-subst.cpp b/test/CodeGenCXX/mangle-subst.cpp
index d83a081..30360aea 100644
--- a/test/CodeGenCXX/mangle-subst.cpp
+++ b/test/CodeGenCXX/mangle-subst.cpp
@@ -2,19 +2,19 @@
struct X {};
-// CHECK: define void @_Z1f1XS_(
+// CHECK-LABEL: define void @_Z1f1XS_(
void f(X, X) { }
-// CHECK: define void @_Z1fR1XS0_(
+// CHECK-LABEL: define void @_Z1fR1XS0_(
void f(X&, X&) { }
-// CHECK: define void @_Z1fRK1XS1_(
+// CHECK-LABEL: define void @_Z1fRK1XS1_(
void f(const X&, const X&) { }
typedef void T();
struct S {};
-// CHECK: define void @_Z1fPFvvEM1SFvvE(
+// CHECK-LABEL: define void @_Z1fPFvvEM1SFvvE(
void f(T*, T (S::*)) {}
namespace A {
@@ -22,14 +22,14 @@ namespace A {
struct B { };
};
-// CHECK: define void @_Z1fN1A1AENS_1BE(
+// CHECK-LABEL: define void @_Z1fN1A1AENS_1BE(
void f(A::A a, A::B b) { }
struct C {
struct D { };
};
-// CHECK: define void @_Z1fN1C1DERS_PS_S1_(
+// CHECK-LABEL: define void @_Z1fN1C1DERS_PS_S1_(
void f(C::D, C&, C*, C&) { }
template<typename T>
diff --git a/test/CodeGenCXX/mangle-system-header.cpp b/test/CodeGenCXX/mangle-system-header.cpp
index 6716b58..3ab5f96 100644
--- a/test/CodeGenCXX/mangle-system-header.cpp
+++ b/test/CodeGenCXX/mangle-system-header.cpp
@@ -3,9 +3,9 @@
// PR5420
# 1 "fake_system_header.h" 1 3 4
-// CHECK: define void @_ZdlPvS_(
+// CHECK-LABEL: define void @_ZdlPvS_(
void operator delete (void*, void*) {}
// PR6217
-// CHECK: define void @_Z3barv()
+// CHECK-LABEL: define void @_Z3barv()
void bar() { }
diff --git a/test/CodeGenCXX/mangle-template.cpp b/test/CodeGenCXX/mangle-template.cpp
index 15a85c7..3b7f302 100644
--- a/test/CodeGenCXX/mangle-template.cpp
+++ b/test/CodeGenCXX/mangle-template.cpp
@@ -82,7 +82,7 @@ namespace test7 {
X(U*, typename int_c<(meta<T>::value + meta<U>::value)>::type *) { }
};
- // CHECK: define weak_odr {{.*}} @_ZN5test71XIiEC1IdEEPT_PNS_5int_cIXplL_ZNS_4metaIiE5valueEEsr4metaIS3_EE5valueEE4typeE(%"struct.test7::X"* %this, double*, float*) unnamed_addr
+ // CHECK: define weak_odr {{.*}} @_ZN5test71XIiEC1IdEEPT_PNS_5int_cIXplL_ZNS_4metaIiE5valueEEsr4metaIS3_EE5valueEE4typeE(
template X<int>::X(double*, float*);
}
@@ -101,7 +101,7 @@ namespace test8 {
template<typename T>
void f(int_c<meta<T>::type::value>) { }
- // CHECK: define weak_odr void @_ZN5test81fIiEEvNS_5int_cIXsr4metaIT_E4typeE5valueEEE
+ // CHECK-LABEL: define weak_odr void @_ZN5test81fIiEEvNS_5int_cIXsr4metaIT_E4typeE5valueEEE(
template void f<int>(int_c<sizeof(int)>);
}
@@ -160,13 +160,13 @@ namespace test12 {
const int n = 10;
template<typename T, T v> void test() {}
void use() {
- // CHECK: define internal void @_ZN6test124testIFivEXadL_ZNS_L1fEvEEEEvv(
+ // CHECK-LABEL: define internal void @_ZN6test124testIFivEXadL_ZNS_L1fEvEEEEvv(
test<int(), &f>();
- // CHECK: define internal void @_ZN6test124testIRFivELZNS_L1fEvEEEvv(
+ // CHECK-LABEL: define internal void @_ZN6test124testIRFivELZNS_L1fEvEEEvv(
test<int(&)(), f>();
- // CHECK: define internal void @_ZN6test124testIPKiXadL_ZNS_L1nEEEEEvv(
+ // CHECK-LABEL: define internal void @_ZN6test124testIPKiXadL_ZNS_L1nEEEEEvv(
test<const int*, &n>();
- // CHECK: define internal void @_ZN6test124testIRKiLZNS_L1nEEEEvv(
+ // CHECK-LABEL: define internal void @_ZN6test124testIRKiLZNS_L1nEEEEvv(
test<const int&, n>();
}
}
diff --git a/test/CodeGenCXX/mangle-unnamed.cpp b/test/CodeGenCXX/mangle-unnamed.cpp
index 53f381c..a62bdd5 100644
--- a/test/CodeGenCXX/mangle-unnamed.cpp
+++ b/test/CodeGenCXX/mangle-unnamed.cpp
@@ -80,7 +80,7 @@ template <class T> struct Test8 {
template <class T> void make_test8(T value) { Test8<T> t(value); }
void test8() { make_test8(T8); }
-// CHECK: define internal void @"_ZNV3$_35test9Ev"(
+// CHECK-LABEL: define internal void @"_ZNV3$_35test9Ev"(
typedef volatile struct {
void test9() volatile {}
} Test9;
@@ -89,4 +89,4 @@ void test9() {
a.test9();
}
-// CHECK: define internal void @"_ZN5Test8I3$_2EC1ES0_"(
+// CHECK-LABEL: define internal void @"_ZN5Test8I3$_2EC1ES0_"(
diff --git a/test/CodeGenCXX/mangle-valist.cpp b/test/CodeGenCXX/mangle-valist.cpp
index 73fd58e..0fcc1db 100644
--- a/test/CodeGenCXX/mangle-valist.cpp
+++ b/test/CodeGenCXX/mangle-valist.cpp
@@ -15,30 +15,30 @@ void Test2::test2(const char *fmt, va_list ap) {
// RUN: %clang_cc1 %s -emit-llvm -o - \
// RUN: -triple armv7-unknown-linux \
-// RUN: | FileCheck -check-prefix=MANGLE-ARM-AAPCS %s
+// RUN: | FileCheck -check-prefix=CHECK-MANGLE-ARM-AAPCS %s
// CHECK-MANGLE-ARM-AAPCS: @_ZN5test15test1EPKcSt9__va_list
// CHECK-MANGLE-ARM-AAPCS: @_ZN5Test25test2EPKcSt9__va_list
// RUN: %clang_cc1 %s -emit-llvm -o - \
// RUN: -triple armv7-unknown-linux -target-abi apcs-gnu \
-// RUN: | FileCheck -check-prefix=MANGLE-ARM-APCS %s
+// RUN: | FileCheck -check-prefix=CHECK-MANGLE-ARM-APCS %s
// CHECK-MANGLE-ARM-APCS: @_ZN5test15test1EPKcPv
// CHECK-MANGLE-ARM-APCS: @_ZN5Test25test2EPKcPv
// RUN: %clang_cc1 %s -emit-llvm -o - \
// RUN: -triple mipsel-unknown-linux \
-// RUN: | FileCheck -check-prefix=MANGLE-MIPSEL %s
+// RUN: | FileCheck -check-prefix=CHECK-MANGLE-MIPSEL %s
// CHECK-MANGLE-MIPSEL: @_ZN5test15test1EPKcPv
// CHECK-MANGLE-MIPSEL: @_ZN5Test25test2EPKcPv
// RUN: %clang_cc1 %s -emit-llvm -o - \
// RUN: -triple i686-unknown-linux \
-// RUN: | FileCheck -check-prefix=MANGLE-X86 %s
+// RUN: | FileCheck -check-prefix=CHECK-MANGLE-X86 %s
// CHECK-MANGLE-X86: @_ZN5test15test1EPKcPc
// CHECK-MANGLE-X86: @_ZN5Test25test2EPKcPc
// RUN: %clang_cc1 %s -emit-llvm -o - \
// RUN: -triple x86_64-unknown-linux \
-// RUN: | FileCheck -check-prefix=MANGLE-X86-64 %s
+// RUN: | FileCheck -check-prefix=CHECK-MANGLE-X86-64 %s
// CHECK-MANGLE-X86-64: @_ZN5test15test1EPKcP13__va_list_tag
// CHECK-MANGLE-X86-64: @_ZN5Test25test2EPKcP13__va_list_tag
diff --git a/test/CodeGenCXX/mangle-variadic-templates.cpp b/test/CodeGenCXX/mangle-variadic-templates.cpp
index b5bdae2..264cc11 100644
--- a/test/CodeGenCXX/mangle-variadic-templates.cpp
+++ b/test/CodeGenCXX/mangle-variadic-templates.cpp
@@ -9,59 +9,59 @@ template<typename ...Types> struct tuple { };
template<int ...Values> struct int_tuple { };
template<template<typename> class ...Templates> struct template_tuple { };
-// CHECK: define weak_odr void @_Z2f0IJEEv1XIXsZT_EJDpRT_EE
+// CHECK-LABEL: define weak_odr void @_Z2f0IJEEv1XIXsZT_EJDpRT_EE
template<typename ...Types>
void f0(X<sizeof...(Types), Types&...>) { }
template void f0(X<0>);
-// CHECK: define weak_odr void @_Z2f0IJifdEEv1XIXsZT_EJDpRT_EE
+// CHECK-LABEL: define weak_odr void @_Z2f0IJifdEEv1XIXsZT_EJDpRT_EE
template void f0<int, float, double>(X<3, int&, float&, double&>);
// Mangling for template argument packs
template<typename ...Types> void f1() {}
-// CHECK: define weak_odr void @_Z2f1IJEEvv
+// CHECK-LABEL: define weak_odr void @_Z2f1IJEEvv
template void f1<>();
-// CHECK: define weak_odr void @_Z2f1IJiEEvv
+// CHECK-LABEL: define weak_odr void @_Z2f1IJiEEvv
template void f1<int>();
-// CHECK: define weak_odr void @_Z2f1IJifEEvv
+// CHECK-LABEL: define weak_odr void @_Z2f1IJifEEvv
template void f1<int, float>();
// Mangling function parameter packs
template<typename ...Types> void f2(Types...) {}
-// CHECK: define weak_odr void @_Z2f2IJEEvDpT_
+// CHECK-LABEL: define weak_odr void @_Z2f2IJEEvDpT_
template void f2<>();
-// CHECK: define weak_odr void @_Z2f2IJiEEvDpT_
+// CHECK-LABEL: define weak_odr void @_Z2f2IJiEEvDpT_
template void f2<int>(int);
-// CHECK: define weak_odr void @_Z2f2IJifEEvDpT_
+// CHECK-LABEL: define weak_odr void @_Z2f2IJifEEvDpT_
template void f2<int, float>(int, float);
// Mangling non-trivial function parameter packs
template<typename ...Types> void f3(const Types *...) {}
-// CHECK: define weak_odr void @_Z2f3IJEEvDpPKT_
+// CHECK-LABEL: define weak_odr void @_Z2f3IJEEvDpPKT_
template void f3<>();
-// CHECK: define weak_odr void @_Z2f3IJiEEvDpPKT_
+// CHECK-LABEL: define weak_odr void @_Z2f3IJiEEvDpPKT_
template void f3<int>(const int*);
-// CHECK: define weak_odr void @_Z2f3IJifEEvDpPKT_
+// CHECK-LABEL: define weak_odr void @_Z2f3IJifEEvDpPKT_
template void f3<int, float>(const int*, const float*);
// Mangling of type pack expansions in a template argument
template<typename ...Types> tuple<Types...> f4() {}
-// CHECK: define weak_odr void @_Z2f4IJifdEE5tupleIJDpT_EEv
+// CHECK-LABEL: define weak_odr void @_Z2f4IJifdEE5tupleIJDpT_EEv
template tuple<int, float, double> f4();
// Mangling of type pack expansions in a function type
template<typename R, typename ...ArgTypes> identity<R(ArgTypes...)> f5() {}
-// CHECK: define weak_odr void @_Z2f5IiJifdEE8identityIFT_DpT0_EEv
+// CHECK-LABEL: define weak_odr void @_Z2f5IiJifdEE8identityIFT_DpT0_EEv
template identity<int(int, float, double)> f5();
// Mangling of non-type template argument expansions
template<int ...Values> int_tuple<Values...> f6() {}
-// CHECK: define weak_odr void @_Z2f6IJLi1ELi2ELi3EEE9int_tupleIJXspT_EEEv
+// CHECK-LABEL: define weak_odr void @_Z2f6IJLi1ELi2ELi3EEE9int_tupleIJXspT_EEEv
template int_tuple<1, 2, 3> f6();
// Mangling of template template argument expansions
template<template<typename> class ...Templates>
template_tuple<Templates...> f7() {}
-// CHECK: define weak_odr void @_Z2f7IJ8identity13add_referenceEE14template_tupleIJDpT_EEv
+// CHECK-LABEL: define weak_odr void @_Z2f7IJ8identity13add_referenceEE14template_tupleIJDpT_EEv
template template_tuple<identity, add_reference> f7();
diff --git a/test/CodeGenCXX/mangle-windows.cpp b/test/CodeGenCXX/mangle-windows.cpp
new file mode 100644
index 0000000..c087616
--- /dev/null
+++ b/test/CodeGenCXX/mangle-windows.cpp
@@ -0,0 +1,42 @@
+// RUN: %clang_cc1 -emit-llvm %s -o - -cxx-abi microsoft \
+// RUN: -triple=i386-pc-win32 | FileCheck --check-prefix=WIN %s
+//
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-mingw32 | \
+// RUN: FileCheck --check-prefix=ITANIUM %s
+
+void __stdcall f1(void) {}
+// WIN: define x86_stdcallcc void @"\01?f1@@YGXXZ"
+// ITANIUM: define x86_stdcallcc void @"\01__Z2f1v@0"
+
+void __fastcall f2(void) {}
+// WIN: define x86_fastcallcc void @"\01?f2@@YIXXZ"
+// ITANIUM: define x86_fastcallcc void @"\01@_Z2f2v@0"
+
+extern "C" void __stdcall f3(void) {}
+// WIN: define x86_stdcallcc void @"\01_f3@0"
+// ITANIUM: define x86_stdcallcc void @"\01_f3@0"
+
+extern "C" void __fastcall f4(void) {}
+// WIN: define x86_fastcallcc void @"\01@f4@0"
+// ITANIUM: define x86_fastcallcc void @"\01@f4@0"
+
+struct Foo {
+ void __stdcall foo();
+ static void __stdcall bar();
+};
+
+void Foo::foo() {}
+// WIN: define x86_stdcallcc void @"\01?foo@Foo@@QAGXXZ"
+// ITANIUM: define x86_stdcallcc void @"\01__ZN3Foo3fooEv@4"
+
+void Foo::bar() {}
+// WIN: define x86_stdcallcc void @"\01?bar@Foo@@SGXXZ"
+// ITANIUM: define x86_stdcallcc void @"\01__ZN3Foo3barEv@0"
+
+// Mostly a test that we don't crash and that the names start with a \01.
+// gcc on mingw produces __Zpp@4
+// cl produces _++@4
+extern "C" void __stdcall operator++(Foo &x) {
+}
+// WIN: define x86_stdcallcc void @"\01??E@YGXAAUFoo@@@Z"
+// ITANIUM: define x86_stdcallcc void @"\01__ZppR3Foo@4"
diff --git a/test/CodeGenCXX/mangle.cpp b/test/CodeGenCXX/mangle.cpp
index e7955a8..d836f36 100644
--- a/test/CodeGenCXX/mangle.cpp
+++ b/test/CodeGenCXX/mangle.cpp
@@ -9,37 +9,37 @@ struct Y { };
// CHECK: @_ZGVZN1N1gEvE1a = internal global
//CHECK: @pr5966_i = external global
-//CHECK: @_ZL8pr5966_i = internal global
+//CHECK: @_ZL8pr5966_j = internal global
-// CHECK: define zeroext i1 @_ZplRK1YRA100_P1X
+// CHECK-LABEL: define zeroext i1 @_ZplRK1YRA100_P1X
bool operator+(const Y&, X* (&xs)[100]) { return false; }
-// CHECK: define void @_Z1f1s
+// CHECK-LABEL: define void @_Z1f1s
typedef struct { int a; } s;
void f(s) { }
-// CHECK: define void @_Z1f1e
+// CHECK-LABEL: define void @_Z1f1e
typedef enum { foo } e;
void f(e) { }
-// CHECK: define void @_Z1f1u
+// CHECK-LABEL: define void @_Z1f1u
typedef union { int a; } u;
void f(u) { }
-// CHECK: define void @_Z1f1x
+// CHECK-LABEL: define void @_Z1f1x
typedef struct { int a; } x,y;
void f(y) { }
-// CHECK: define void @_Z1fv
+// CHECK-LABEL: define void @_Z1fv
void f() { }
-// CHECK: define void @_ZN1N1fEv
+// CHECK-LABEL: define void @_ZN1N1fEv
namespace N { void f() { } }
-// CHECK: define void @_ZN1N1N1fEv
+// CHECK-LABEL: define void @_ZN1N1N1fEv
namespace N { namespace N { void f() { } } }
-// CHECK: define void @unmangled_function
+// CHECK-LABEL: define void @unmangled_function
extern "C" { namespace N { void unmangled_function() { } } }
extern "C" { namespace N { int unmangled_variable = 10; } }
@@ -50,41 +50,41 @@ namespace N { int f(int, int) { static int b; return b; } }
namespace N { int h(); void g() { static int a = h(); } }
-// CHECK: define void @_Z1fno
+// CHECK-LABEL: define void @_Z1fno
void f(__int128_t, __uint128_t) { }
template <typename T> struct S1 {};
-// CHECK: define void @_Z1f2S1IiE
+// CHECK-LABEL: define void @_Z1f2S1IiE
void f(S1<int>) {}
-// CHECK: define void @_Z1f2S1IdE
+// CHECK-LABEL: define void @_Z1f2S1IdE
void f(S1<double>) {}
template <int N> struct S2 {};
-// CHECK: define void @_Z1f2S2ILi100EE
+// CHECK-LABEL: define void @_Z1f2S2ILi100EE
void f(S2<100>) {}
-// CHECK: define void @_Z1f2S2ILin100EE
+// CHECK-LABEL: define void @_Z1f2S2ILin100EE
void f(S2<-100>) {}
template <bool B> struct S3 {};
-// CHECK: define void @_Z1f2S3ILb1EE
+// CHECK-LABEL: define void @_Z1f2S3ILb1EE
void f(S3<true>) {}
-// CHECK: define void @_Z1f2S3ILb0EE
+// CHECK-LABEL: define void @_Z1f2S3ILb0EE
void f(S3<false>) {}
struct S;
-// CHECK: define void @_Z1fM1SKFvvE
+// CHECK-LABEL: define void @_Z1fM1SKFvvE
void f(void (S::*)() const) {}
-// CHECK: define void @_Z1fM1SFvvE
+// CHECK-LABEL: define void @_Z1fM1SFvvE
void f(void (S::*)()) {}
-// CHECK: define void @_Z1fi
+// CHECK-LABEL: define void @_Z1fi
void f(const int) { }
template<typename T, typename U> void ft1(U u, T t) { }
@@ -238,7 +238,7 @@ template<bool, typename> struct __enable_if {};
template<typename T> struct __enable_if<true, T> { typedef T __type; };
template<typename T>
-// CHECK: define linkonce_odr void @_ZN6PR57968__fill_aIiEENS_11__enable_ifIXntsr16__is_scalar_typeIT_EE7__valueEvE6__typeEv
+// CHECK-LABEL: define linkonce_odr void @_ZN6PR57968__fill_aIiEENS_11__enable_ifIXntsr16__is_scalar_typeIT_EE7__valueEvE6__typeEv
typename __enable_if<!__is_scalar_type<T>::__value, void>::__type __fill_a() { };
void f() { __fill_a<int>(); }
@@ -247,26 +247,26 @@ void f() { __fill_a<int>(); }
namespace Expressions {
// Unary operators.
-// CHECK: define weak_odr void @_ZN11Expressions2f1ILi1EEEvPAplngT_Li2E_i
+// CHECK-LABEL: define weak_odr void @_ZN11Expressions2f1ILi1EEEvPAplngT_Li2E_i
template <int i> void f1(int (*)[(-i) + 2]) { };
template void f1<1>(int (*)[1]);
-// CHECK: define weak_odr void @_ZN11Expressions2f2ILi1EEEvPApsT__i
+// CHECK-LABEL: define weak_odr void @_ZN11Expressions2f2ILi1EEEvPApsT__i
template <int i> void f2(int (*)[+i]) { };
template void f2<1>(int (*)[1]);
// Binary operators.
-// CHECK: define weak_odr void @_ZN11Expressions2f3ILi1EEEvPAplT_T__i
+// CHECK-LABEL: define weak_odr void @_ZN11Expressions2f3ILi1EEEvPAplT_T__i
template <int i> void f3(int (*)[i+i]) { };
template void f3<1>(int (*)[2]);
-// CHECK: define weak_odr void @_ZN11Expressions2f4ILi1EEEvPAplplLi2ET_T__i
+// CHECK-LABEL: define weak_odr void @_ZN11Expressions2f4ILi1EEEvPAplplLi2ET_T__i
template <int i> void f4(int (*)[2 + i+i]) { };
template void f4<1>(int (*)[4]);
// The ternary operator.
-// CHECK: define weak_odr void @_ZN11Expressions2f4ILb1EEEvPAquT_Li1ELi2E_i
+// CHECK-LABEL: define weak_odr void @_ZN11Expressions2f4ILb1EEEvPAquT_Li1ELi2E_i
template <bool b> void f4(int (*)[b ? 1 : 2]) { };
template void f4<true>(int (*)[1]);
}
@@ -280,13 +280,13 @@ struct Ops {
void *v;
};
-// CHECK: define %struct.Ops* @_ZN3OpsplERKS_
+// CHECK-LABEL: define %struct.Ops* @_ZN3OpsplERKS_
Ops& Ops::operator+(const Ops&) { return *this; }
-// CHECK: define %struct.Ops* @_ZN3OpsmiERKS_
+// CHECK-LABEL: define %struct.Ops* @_ZN3OpsmiERKS_
Ops& Ops::operator-(const Ops&) { return *this; }
-// CHECK: define %struct.Ops* @_ZN3OpsanERKS_
+// CHECK-LABEL: define %struct.Ops* @_ZN3OpsanERKS_
Ops& Ops::operator&(const Ops&) { return *this; }
-// CHECK: define %struct.Ops* @_ZN3OpsmlERKS_
+// CHECK-LABEL: define %struct.Ops* @_ZN3OpsmlERKS_
Ops& Ops::operator*(const Ops&) { return *this; }
// PR5861
@@ -302,11 +302,11 @@ template<typename T, typename = Policy<P, true> > class Alloc
T *allocate(int, const void*) { return 0; }
};
-// CHECK: define weak_odr i8* @_ZN6PR58615AllocIcNS_6PolicyINS_1PELb1EEEE8allocateEiPKv
+// CHECK-LABEL: define weak_odr i8* @_ZN6PR58615AllocIcNS_6PolicyINS_1PELb1EEEE8allocateEiPKv
template class Alloc<char>;
}
-// CHECK: define void @_Z1fU13block_pointerFiiiE
+// CHECK-LABEL: define void @_Z1fU13block_pointerFiiiE
void f(int (^)(int, int)) { }
void pr5966_foo() {
@@ -314,10 +314,10 @@ void pr5966_foo() {
pr5966_i = 0;
}
-static int pr5966_i;
+static int pr5966_j;
void pr5966_bar() {
- pr5966_i = 0;
+ pr5966_j = 0;
}
namespace test0 {
@@ -330,29 +330,29 @@ namespace test0 {
char buffer[1];
f(0.0, buffer);
}
- // CHECK: define void @_ZN5test05test0Ev()
- // CHECK: define linkonce_odr void @_ZN5test01fIdEEvT_RAszcl3ovlcvS1__EE_c(
+ // CHECK-LABEL: define void @_ZN5test05test0Ev()
+ // CHECK-LABEL: define linkonce_odr void @_ZN5test01fIdEEvT_RAszcl3ovlcvS1__EE_c(
void test1() {
char buffer[sizeof(int)];
f(1, buffer);
}
- // CHECK: define void @_ZN5test05test1Ev()
- // CHECK: define linkonce_odr void @_ZN5test01fIiEEvT_RAszcl3ovlcvS1__EE_c(
+ // CHECK-LABEL: define void @_ZN5test05test1Ev()
+ // CHECK-LABEL: define linkonce_odr void @_ZN5test01fIiEEvT_RAszcl3ovlcvS1__EE_c(
template <class T> void g(char (&buffer)[sizeof(T() + 5.0f)]) {}
void test2() {
char buffer[sizeof(float)];
g<float>(buffer);
}
- // CHECK: define linkonce_odr void @_ZN5test01gIfEEvRAszplcvT__ELf40a00000E_c(
+ // CHECK-LABEL: define linkonce_odr void @_ZN5test01gIfEEvRAszplcvT__ELf40a00000E_c(
template <class T> void h(char (&buffer)[sizeof(T() + 5.0)]) {}
void test3() {
char buffer[sizeof(double)];
h<float>(buffer);
}
- // CHECK: define linkonce_odr void @_ZN5test01hIfEEvRAszplcvT__ELd4014000000000000E_c(
+ // CHECK-LABEL: define linkonce_odr void @_ZN5test01hIfEEvRAszplcvT__ELd4014000000000000E_c(
template <class T> void j(char (&buffer)[sizeof(T().buffer)]) {}
struct A { double buffer[128]; };
@@ -360,25 +360,25 @@ namespace test0 {
char buffer[1024];
j<A>(buffer);
}
- // CHECK: define linkonce_odr void @_ZN5test01jINS_1AEEEvRAszdtcvT__E6buffer_c(
+ // CHECK-LABEL: define linkonce_odr void @_ZN5test01jINS_1AEEEvRAszdtcvT__E6buffer_c(
template <class T> void k(char (&buffer)[sizeof(T() + 0.0f)]) {}
void test5() {
char buffer[sizeof(float)];
k<float>(buffer);
}
- // CHECK: define linkonce_odr void @_ZN5test01kIfEEvRAszplcvT__ELf00000000E_c(
+ // CHECK-LABEL: define linkonce_odr void @_ZN5test01kIfEEvRAszplcvT__ELf00000000E_c(
}
namespace test1 {
template<typename T> struct X { };
template<template<class> class Y, typename T> void f(Y<T>) { }
- // CHECK: define weak_odr void @_ZN5test11fINS_1XEiEEvT_IT0_E
+ // CHECK-LABEL: define weak_odr void @_ZN5test11fINS_1XEiEEvT_IT0_E
template void f(X<int>);
}
-// CHECK: define internal void @_ZL27functionWithInternalLinkagev()
+// CHECK-LABEL: define internal void @_ZL27functionWithInternalLinkagev()
static void functionWithInternalLinkage() { }
void g() { functionWithInternalLinkage(); }
@@ -392,7 +392,7 @@ namespace test2 {
return read_member(obj);
}
- // CHECK: define linkonce_odr i32 @_ZN5test211read_memberINS_1AEEEDtptcvPT_Li0E6memberERS2_(
+ // CHECK-LABEL: define linkonce_odr i32 @_ZN5test211read_memberINS_1AEEEDtptcvPT_Li0E6memberERS2_(
}
// rdar://problem/9280586
@@ -402,16 +402,16 @@ namespace test3 {
struct Path2 : AmbiguousBase { double p; };
struct Derived : Path1, Path2 { };
- // CHECK: define linkonce_odr i32 @_ZN5test38get_ab_1INS_7DerivedEEEDtptcvPT_Li0Esr5Path1E2abERS2_(
+ // CHECK-LABEL: define linkonce_odr i32 @_ZN5test38get_ab_1INS_7DerivedEEEDtptcvPT_Li0Esr5Path1E2abERS2_(
template <class T> decltype(((T*) 0)->Path1::ab) get_ab_1(T &ref) { return ref.Path1::ab; }
- // CHECK: define linkonce_odr i32 @_ZN5test38get_ab_2INS_7DerivedEEEDtptcvPT_Li0Esr5Path2E2abERS2_(
+ // CHECK-LABEL: define linkonce_odr i32 @_ZN5test38get_ab_2INS_7DerivedEEEDtptcvPT_Li0Esr5Path2E2abERS2_(
template <class T> decltype(((T*) 0)->Path2::ab) get_ab_2(T &ref) { return ref.Path2::ab; }
- // CHECK: define linkonce_odr float @_ZN5test37get_p_1INS_7DerivedEEEDtptcvPT_Li0Esr5Path1E1pERS2_(
+ // CHECK-LABEL: define linkonce_odr float @_ZN5test37get_p_1INS_7DerivedEEEDtptcvPT_Li0Esr5Path1E1pERS2_(
template <class T> decltype(((T*) 0)->Path1::p) get_p_1(T &ref) { return ref.Path1::p; }
- // CHECK: define linkonce_odr double @_ZN5test37get_p_2INS_7DerivedEEEDtptcvPT_Li0Esr5Path2E1pERS2_(
+ // CHECK-LABEL: define linkonce_odr double @_ZN5test37get_p_2INS_7DerivedEEEDtptcvPT_Li0Esr5Path2E1pERS2_(
template <class T> decltype(((T*) 0)->Path2::p) get_p_2(T &ref) { return ref.Path2::p; }
Derived obj;
@@ -423,7 +423,7 @@ namespace test3 {
}
}
-// CHECK: define void @_ZN5test41gEPNS_3zedIXadL_ZNS_3foo3barEEEEE
+// CHECK-LABEL: define void @_ZN5test41gEPNS_3zedIXadL_ZNS_3foo3barEEEEE
namespace test4 {
struct foo { int bar; };
template <int (foo::*)>
@@ -431,7 +431,7 @@ namespace test4 {
void g(zed<&foo::bar>*)
{}
}
-// CHECK: define void @_ZN5test51gEPNS_3zedIXadL_ZNS_3foo3barEEEEE
+// CHECK-LABEL: define void @_ZN5test51gEPNS_3zedIXadL_ZNS_3foo3barEEEEE
namespace test5 {
struct foo { static int bar; };
template <int *>
@@ -439,7 +439,7 @@ namespace test5 {
void g(zed<&foo::bar>*)
{}
}
-// CHECK: define void @_ZN5test61gEPNS_3zedIXadL_ZNS_3foo3barEvEEEE
+// CHECK-LABEL: define void @_ZN5test61gEPNS_3zedIXadL_ZNS_3foo3barEvEEEE
namespace test6 {
struct foo { int bar(); };
template <int (foo::*)()>
@@ -447,7 +447,7 @@ namespace test6 {
void g(zed<&foo::bar>*)
{}
}
-// CHECK: define void @_ZN5test71gEPNS_3zedIXadL_ZNS_3foo3barEvEEEE
+// CHECK-LABEL: define void @_ZN5test71gEPNS_3zedIXadL_ZNS_3foo3barEvEEEE
namespace test7 {
struct foo { static int bar(); };
template <int (*f)()>
@@ -455,7 +455,7 @@ namespace test7 {
void g(zed<&foo::bar>*)
{}
}
-// CHECK: define weak_odr void @_ZN5test81AILZNS_1B5valueEEE3incEv
+// CHECK-LABEL: define weak_odr void @_ZN5test81AILZNS_1B5valueEEE3incEv
namespace test8 {
template <int &counter> class A { void inc() { counter++; } };
class B { public: static int value; };
@@ -482,7 +482,7 @@ namespace test10 {
template <char P1> struct S {};
template <char P2> void f(struct S<false ? 'a' : P2> ) {}
- // CHECK: define weak_odr void @_ZN6test101fILc3EEEvNS_1SIXquLb0ELc97ET_EEE(
+ // CHECK-LABEL: define weak_odr void @_ZN6test101fILc3EEEvNS_1SIXquLb0ELc97ET_EEE(
template void f<(char) 3>(struct S<3>);
}
@@ -512,7 +512,7 @@ namespace test13 {
template <template<class> class T> void foo(const A<T> &a) {}
- // CHECK: define weak_odr void @_ZN6test133fooINS_1BEEEvRKNS_1AIT_EE(
+ // CHECK-LABEL: define weak_odr void @_ZN6test133fooINS_1BEEEvRKNS_1AIT_EE(
template void foo(const A<B> &a);
}
@@ -521,7 +521,7 @@ namespace test14 {
struct S {
static int a(), x;
};
- // CHECK: define i32 @_ZN6test141S1aEv
+ // CHECK-LABEL: define i32 @_ZN6test141S1aEv
// CHECK: load i32* @_ZN6test141S1xE
int S::a() { return S::x; }
}
@@ -534,7 +534,7 @@ namespace test15 {
template <int I> void f(S<I + e>) {}
- // CHECK: define weak_odr void @_ZN6test151fILi7EEEvNS_1SIXplT_LNS_1EE3EEEE(
+ // CHECK-LABEL: define weak_odr void @_ZN6test151fILi7EEEvNS_1SIXplT_LNS_1EE3EEEE(
template void f<7>(S<7 + e>);
}
@@ -548,7 +548,7 @@ namespace test17 {
template <class T> A<sizeof(T::foo())> func(void);
- // CHECK: define void @_ZN6test174testEv()
+ // CHECK-LABEL: define void @_ZN6test174testEv()
// CHECK: call {{.*}} @_ZN6test174funcINS_1BEEENS_1AIXszclsrT_3fooEEEEv()
void test() {
func<B>();
@@ -577,10 +577,10 @@ namespace test18 {
template <typename T> void f(S<&T::operator&>) {}
template void f<A>(S<&A::operator&>);
- // CHECK: define weak_odr void @_ZN6test181fINS_1AEEEvNS_1SIXadsrT_plEEE
- // CHECK: define weak_odr void @_ZN6test181fINS_1AEEEvNS_1SIXadsrT_miEEE
- // CHECK: define weak_odr void @_ZN6test181fINS_1AEEEvNS_1SIXadsrT_mlEEE
- // CHECK: define weak_odr void @_ZN6test181fINS_1AEEEvNS_1SIXadsrT_anEEE
+ // CHECK-LABEL: define weak_odr void @_ZN6test181fINS_1AEEEvNS_1SIXadsrT_plEEE
+ // CHECK-LABEL: define weak_odr void @_ZN6test181fINS_1AEEEvNS_1SIXadsrT_miEEE
+ // CHECK-LABEL: define weak_odr void @_ZN6test181fINS_1AEEEvNS_1SIXadsrT_mlEEE
+ // CHECK-LABEL: define weak_odr void @_ZN6test181fINS_1AEEEvNS_1SIXadsrT_anEEE
}
// rdar://problem/8332117
@@ -599,13 +599,13 @@ namespace test19 {
template <typename T> void g (S<&T::operator int>) {}
template <typename T> void g (S<&T::template operator- <double> >) {}
- // CHECK: define weak_odr void @_ZN6test191gINS_1AEEEvNS_1SIXadsrT_1fIiEEEE(
+ // CHECK-LABEL: define weak_odr void @_ZN6test191gINS_1AEEEvNS_1SIXadsrT_1fIiEEEE(
template void g<A>(S<&A::f<int> >);
- // CHECK: define weak_odr void @_ZN6test191gINS_1AEEEvNS_1SIXadsrT_plEEE(
+ // CHECK-LABEL: define weak_odr void @_ZN6test191gINS_1AEEEvNS_1SIXadsrT_plEEE(
template void g<A>(S<&A::operator+>);
- // CHECK: define weak_odr void @_ZN6test191gINS_1AEEEvNS_1SIXadsrT_cviEEE(
+ // CHECK-LABEL: define weak_odr void @_ZN6test191gINS_1AEEEvNS_1SIXadsrT_cviEEE(
template void g<A>(S<&A::operator int>);
- // CHECK: define weak_odr void @_ZN6test191gINS_1AEEEvNS_1SIXadsrT_miIdEEEE(
+ // CHECK-LABEL: define weak_odr void @_ZN6test191gINS_1AEEEvNS_1SIXadsrT_miIdEEEE(
template void g<A>(S<&A::operator-<double> >);
}
@@ -613,23 +613,23 @@ namespace test20 {
template <class T> T *f(const T&);
template <class T> T *f(T*);
- // CHECK: define weak_odr void @_ZN6test205test0IiEEvDTcl1fIPT_ELi0EEE(
+ // CHECK-LABEL: define weak_odr void @_ZN6test205test0IiEEvDTcl1fIPT_ELi0EEE(
template <class T> void test0(decltype(f<T*>(0))) {}
template void test0<int>(decltype(f<int*>(0)));
- // CHECK: define weak_odr void @_ZN6test205test1IiEEvDTcl1fIEcvT__EEE(
+ // CHECK-LABEL: define weak_odr void @_ZN6test205test1IiEEvDTcl1fIEcvT__EEE(
template <class T> void test1(decltype(f<>(T()))) {}
template void test1<int>(decltype(f<>(int())));
}
// rdar:// 8620510
namespace test21 {
- // CHECK: define void @_ZN6test2112vla_arg_funcEiPA_i(
+ // CHECK-LABEL: define void @_ZN6test2112vla_arg_funcEiPA_i(
void vla_arg_func(int X, int a[X][X]) {}
}
namespace test22 {
- // CHECK: define void @_ZN6test221fEDn(
+ // CHECK-LABEL: define void @_ZN6test221fEDn(
void f(decltype(nullptr)) { }
}
@@ -637,12 +637,12 @@ namespace test22 {
namespace test23 {
typedef void * const vpc;
- // CHECK: define void @_ZN6test231fERA10_KPv(
+ // CHECK-LABEL: define void @_ZN6test231fERA10_KPv(
void f(vpc (&)[10]) {}
typedef vpc vpca5[5];
void f(vpca5 volatile (&)[10]) {}
- // CHECK: define void @_ZN6test231fERA10_A5_VKPv(
+ // CHECK-LABEL: define void @_ZN6test231fERA10_A5_VKPv(
}
namespace test24 {
@@ -652,10 +652,10 @@ namespace test24 {
foo();
}
- static char foo() {}
+ static char bar() {}
void test1() {
- // CHECK: call signext i8 @_ZN6test24L3fooEv()
- foo();
+ // CHECK: call signext i8 @_ZN6test24L3barEv()
+ bar();
}
}
@@ -757,11 +757,11 @@ namespace test31 { // instantiation-dependent mangling of decltype
void g(int);
template<class T> auto f3(T p)->decltype(g(p)) {}
- // CHECK: define weak_odr i32 @_ZN6test312f1IiEEiT_(
+ // CHECK-LABEL: define weak_odr i32 @_ZN6test312f1IiEEiT_(
template int f1(int);
- // CHECK: define weak_odr i32 @_ZN6test312f2IiEEDtfp_ET_
+ // CHECK-LABEL: define weak_odr i32 @_ZN6test312f2IiEEDtfp_ET_
template int f2(int);
- // CHECK: define weak_odr void @_ZN6test312f3IiEEDTcl1gfp_EET_
+ // CHECK-LABEL: define weak_odr void @_ZN6test312f3IiEEDTcl1gfp_EET_
template void f3(int);
}
@@ -802,14 +802,14 @@ namespace test34 {
template<typename T>
void f(decltype(sizeof(decltype(T() + T())))) {}
- // CHECK: define weak_odr void @_ZN6test341fIiEEvDTstDTplcvT__EcvS1__EEE
+ // CHECK-LABEL: define weak_odr void @_ZN6test341fIiEEvDTstDTplcvT__EcvS1__EEE
template void f<int>(decltype(sizeof(1)));
// Mangling for non-instantiation-dependent sizeof expressions.
template<unsigned N>
void f2(int (&)[N + sizeof(int*)]) {}
- // CHECK: define weak_odr void @_ZN6test342f2ILj4EEEvRAplT_Lm8E_i
+ // CHECK-LABEL: define weak_odr void @_ZN6test342f2ILj4EEEvRAplT_Lm8E_i
template void f2<4>(int (&)[4 + sizeof(int*)]);
// Mangling for non-instantiation-dependent sizeof expressions
@@ -817,7 +817,7 @@ namespace test34 {
template<unsigned long long N>
void f3(int (&)[N + sizeof(int*)]) {}
- // CHECK: define weak_odr void @_ZN6test342f3ILy4EEEvRAplT_Ly8E_i
+ // CHECK-LABEL: define weak_odr void @_ZN6test342f3ILy4EEEvRAplT_Ly8E_i
template void f3<4>(int (&)[4 + sizeof(int*)]);
// Mangling for instantiation-dependent sizeof() expressions as
@@ -826,7 +826,7 @@ namespace test34 {
template<typename T> void f4(::test34::A<sizeof(sizeof(decltype(T() + T())))>) { }
- // CHECK: define weak_odr void @_ZN6test342f4IiEEvNS_1AIXszstDTplcvT__EcvS2__EEEEE
+ // CHECK-LABEL: define weak_odr void @_ZN6test342f4IiEEvNS_1AIXszstDTplcvT__EcvS2__EEEEE
template void f4<int>(A<sizeof(sizeof(int))>);
}
@@ -839,7 +839,7 @@ namespace test35 {
template<typename T>
void f1(decltype(sizeof(&T::template operator+<int>))) {}
- // CHECK: define weak_odr void @_ZN6test352f1INS_1AEEEvDTszadsrT_plIiEE
+ // CHECK-LABEL: define weak_odr void @_ZN6test352f1INS_1AEEEvDTszadsrT_plIiEE
template void f1<A>(__SIZE_TYPE__);
}
@@ -864,14 +864,90 @@ namespace test37 {
};
template<typename T> void func(T) { }
void test() {
- // CHECK: define linkonce_odr void @_ZN6test374funcINS_3fooUt_EEEvT_
+ // CHECK-LABEL: define linkonce_odr void @_ZN6test374funcINS_3fooUt_EEEvT_
func(foo().a);
- // CHECK: define linkonce_odr void @_ZN6test374funcINS_3fooUt0_EEEvT_
+ // CHECK-LABEL: define linkonce_odr void @_ZN6test374funcINS_3fooUt0_EEEvT_
func(*foo::c());
- // CHECK: define linkonce_odr void @_ZN6test374funcINS_3fooUt1_EEEvT_
+ // CHECK-LABEL: define linkonce_odr void @_ZN6test374funcINS_3fooUt1_EEEvT_
func(foo().d);
}
}
-// CHECK: define void @_Z6ASfuncPU3AS3i
+// CHECK-LABEL: define void @_Z6ASfuncPU3AS3i
void ASfunc(__attribute__((address_space(3))) int* x) {}
+
+namespace test38 {
+ // CHECK-LABEL: define linkonce_odr void @_ZN6test384funcINS_3fooUt_EEEvT_
+ typedef struct {
+ struct {
+ } a;
+ } foo;
+
+ template <typename T> void func(T) {}
+ void test() { func(foo().a); }
+}
+
+namespace test39 {
+ // CHECK-LABEL: define internal void @"_ZN6test394funcINS_3$_03$_1EEEvT_"
+ typedef struct {
+ struct {} a;
+ } *foo;
+ template<typename T> void func(T) {}
+ void test(foo x) {
+ func(x->a);
+ }
+}
+
+namespace test40 {
+ // CHECK: i32* @_ZZN6test401fEvE1a_0
+ void h(int&);
+ inline void f() {
+ if (0) {
+ static int a;
+ }
+ static int a;
+ h(a);
+ };
+ void g() { f(); }
+}
+
+namespace test41 {
+ // CHECK: define linkonce_odr void @_ZN6test414funcINS_1XEEEvNS_3fooILi20ES1_EE
+ template <int i, class T> struct foo {
+ template <class T2 = T> friend void func(foo x) {}
+ };
+
+ struct X {};
+
+ void g() { func(foo<20, X>()); }
+}
+
+namespace test42 {
+ // CHECK: define linkonce_odr void @_ZN6test424funcINS_1XEEEvNS_3fooILi20ES1_EE
+ template <int i, template <class> class T> struct foo {
+ template <template <class> class T2 = T> friend void func(foo x) {}
+ };
+
+ template <class V> struct X {
+ };
+
+ void g() { func(foo<20, X>()); }
+}
+
+namespace test43 {
+ // CHECK-LABEL: define void @_ZN6test431gEPNS_3zedIXadL_ZNS_3fooUt_3barEEEEE
+ struct foo { union { int bar; }; };
+ template <int (foo::*)>
+ struct zed {};
+ void g(zed<&foo::bar>*)
+ {}
+}
+
+namespace test44 {
+ struct foo { void bar() __restrict { }; } obj;
+
+ void f() {
+ obj.bar();
+ }
+ // CHECK-LABEL: define linkonce_odr void @_ZN6test443foo3barEv(%"struct.test44::foo"* %this)
+}
diff --git a/test/CodeGenCXX/member-expressions.cpp b/test/CodeGenCXX/member-expressions.cpp
index d9fb394..4850272 100644
--- a/test/CodeGenCXX/member-expressions.cpp
+++ b/test/CodeGenCXX/member-expressions.cpp
@@ -58,7 +58,7 @@ namespace test4 {
extern C *c_ptr;
- // CHECK: define i32 @_ZN5test44testEv()
+ // CHECK-LABEL: define i32 @_ZN5test44testEv()
int test() {
// CHECK: load {{.*}} @_ZN5test45c_ptrE
// CHECK-NEXT: bitcast
diff --git a/test/CodeGenCXX/member-function-pointer-calls.cpp b/test/CodeGenCXX/member-function-pointer-calls.cpp
index f8960aa..99162eb 100644
--- a/test/CodeGenCXX/member-function-pointer-calls.cpp
+++ b/test/CodeGenCXX/member-function-pointer-calls.cpp
@@ -8,14 +8,14 @@ int f(A* a, int (A::*fp)()) {
return (a->*fp)();
}
-// CHECK: define i32 @_Z2g1v()
+// CHECK-LABEL: define i32 @_Z2g1v()
// CHECK: ret i32 1
int g1() {
A a;
return f(&a, &A::vf1);
}
-// CHECK: define i32 @_Z2g2v()
+// CHECK-LABEL: define i32 @_Z2g2v()
// CHECK: ret i32 2
int g2() {
A a;
diff --git a/test/CodeGenCXX/member-function-pointers.cpp b/test/CodeGenCXX/member-function-pointers.cpp
index 84b54b6..fb06fa7 100644
--- a/test/CodeGenCXX/member-function-pointers.cpp
+++ b/test/CodeGenCXX/member-function-pointers.cpp
@@ -4,6 +4,9 @@
// RUN: %clang_cc1 %s -emit-llvm -o - -triple=i386-unknown-unknown | FileCheck -check-prefix GLOBAL-LP32 %s
// RUN: %clang_cc1 %s -emit-llvm -o - -triple=armv7-unknown-unknown | FileCheck -check-prefix GLOBAL-ARM %s
+// PNaCl uses the same representation of method pointers as ARM.
+// RUN: %clang_cc1 %s -emit-llvm -o - -triple=le32-unknown-nacl | FileCheck -check-prefix GLOBAL-ARM %s
+
struct A { int a; void f(); virtual void vf1(); virtual void vf2(); };
struct B { int b; virtual void g(); };
struct C : B, A { };
@@ -226,7 +229,7 @@ namespace test9 {
fooptr p;
};
- // CODE-LP64: define void @_ZN5test94testEv(
+ // CODE-LP64-LABEL: define void @_ZN5test94testEv(
// CODE-LP64: alloca i32
// CODE-LP64-NEXT: ret void
void test() {
diff --git a/test/CodeGenCXX/member-functions.cpp b/test/CodeGenCXX/member-functions.cpp
index 75b354c..1773c67 100644
--- a/test/CodeGenCXX/member-functions.cpp
+++ b/test/CodeGenCXX/member-functions.cpp
@@ -5,11 +5,11 @@ struct C {
void g(int, ...);
};
-// CHECK: define void @_ZN1C1fEv
+// CHECK-LABEL: define void @_ZN1C1fEv
void C::f() {
}
-// CHECK: define void @_Z5test1v
+// CHECK-LABEL: define void @_Z5test1v
void test1() {
C c;
@@ -34,7 +34,7 @@ struct S {
virtual void v() {}
};
-// CHECK: define void @_ZN1S1fEv
+// CHECK-LABEL: define void @_ZN1S1fEv
void S::f() {
}
@@ -51,13 +51,13 @@ void test2() {
// CHECK: define linkonce_odr void @_ZN1SC1Ev{{.*}} unnamed_addr
// S::f_inline1()
-// CHECK: define linkonce_odr void @_ZN1S9f_inline1Ev
+// CHECK-LABEL: define linkonce_odr void @_ZN1S9f_inline1Ev
// S::f_inline2()
-// CHECK: define linkonce_odr void @_ZN1S9f_inline2Ev
+// CHECK-LABEL: define linkonce_odr void @_ZN1S9f_inline2Ev
// S::g()
-// CHECK: define linkonce_odr void @_ZN1S1gEv
+// CHECK-LABEL: define linkonce_odr void @_ZN1S1gEv
// S::~S()
// CHECK: define linkonce_odr void @_ZN1SD1Ev{{.*}} unnamed_addr
@@ -66,7 +66,7 @@ struct T {
T operator+(const T&);
};
-// CHECK: define void @_Z5test3v
+// CHECK-LABEL: define void @_Z5test3v
void test3() {
T t1, t2;
diff --git a/test/CodeGenCXX/member-init-anon-union.cpp b/test/CodeGenCXX/member-init-anon-union.cpp
index 4db31f0..bfe1667 100644
--- a/test/CodeGenCXX/member-init-anon-union.cpp
+++ b/test/CodeGenCXX/member-init-anon-union.cpp
@@ -11,7 +11,7 @@ static union {
int f() { return a; }
-// CHECK: define internal void @__cxx_global_var_init
+// CHECK-LABEL: define internal void @__cxx_global_var_init
// CHECK-NOT: }
// CHECK: call {{.*}}@"[[CONSTRUCT_GLOBAL:.*]]C1Ev"
diff --git a/test/CodeGenCXX/member-initializers.cpp b/test/CodeGenCXX/member-initializers.cpp
index c22b99d..c98e6bf 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() #0
+// CHECK-LABEL: define i32 @_Z1fv() #0
int f() {
B b;
diff --git a/test/CodeGenCXX/member-templates.cpp b/test/CodeGenCXX/member-templates.cpp
index 7e4bdca..c72dd6e 100644
--- a/test/CodeGenCXX/member-templates.cpp
+++ b/test/CodeGenCXX/member-templates.cpp
@@ -15,8 +15,8 @@ struct B {
template<typename T> B::B(T) {}
-// CHECK: define weak_odr void @_ZN1BC1IiEET_(%struct.B* %this, i32) unnamed_addr
-// CHECK: define weak_odr void @_ZN1BC2IiEET_(%struct.B* %this, i32) unnamed_addr
+// CHECK-LABEL: define weak_odr void @_ZN1BC1IiEET_(%struct.B* %this, i32) unnamed_addr
+// CHECK-LABEL: define weak_odr void @_ZN1BC2IiEET_(%struct.B* %this, i32) unnamed_addr
template B::B(int);
template<typename T>
diff --git a/test/CodeGenCXX/microsoft-abi-alignment-fail.cpp b/test/CodeGenCXX/microsoft-abi-alignment-fail.cpp
new file mode 100644
index 0000000..7407efe
--- /dev/null
+++ b/test/CodeGenCXX/microsoft-abi-alignment-fail.cpp
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -fno-rtti -emit-llvm -cxx-abi microsoft -triple=i686-pc-win32 -o - %s 2>/dev/null | FileCheck %s
+// RUN: %clang_cc1 -fno-rtti -emit-llvm -cxx-abi microsoft -triple=x86_64-pc-win32 -o - %s 2>/dev/null | FileCheck %s -check-prefix CHECK-X64
+
+struct B { char a; };
+struct A : virtual B {} a;
+
+// The <> indicate that the pointer is packed, which is required to support
+// microsoft layout in 32 bit mode, but not 64 bit mode.
+// CHECK: %struct.A = type <{ i32*, %struct.B }>
+// CHECK-X64: %struct.A = type { i32*, %struct.B }
diff --git a/test/CodeGenCXX/microsoft-abi-constexpr-vs-inheritance.cpp b/test/CodeGenCXX/microsoft-abi-constexpr-vs-inheritance.cpp
new file mode 100644
index 0000000..92db9a7
--- /dev/null
+++ b/test/CodeGenCXX/microsoft-abi-constexpr-vs-inheritance.cpp
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -std=c++11 -fno-rtti -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s
+
+struct A {
+ constexpr A(int x) : x(x) {}
+ virtual void f();
+ int x;
+};
+
+A a(42);
+// CHECK: @"\01?a@@3UA@@A" = global { [1 x i8*]*, i32 } { [1 x i8*]* @"\01??_7A@@6B@", i32 42 }, align 4
+
+struct B {
+ constexpr B(int y) : y(y) {}
+ virtual void g();
+ int y;
+};
+
+struct C : A, B {
+ constexpr C() : A(777), B(13) {}
+};
+
+C c;
+// CHECK: @"\01?c@@3UC@@A" = global { [1 x i8*]*, i32, [1 x i8*]*, i32 } { [1 x i8*]* @"\01??_7C@@6BA@@@", i32 777, [1 x i8*]* @"\01??_7C@@6BB@@@", i32 13 }
diff --git a/test/CodeGenCXX/microsoft-abi-default-cc.cpp b/test/CodeGenCXX/microsoft-abi-default-cc.cpp
index 7f2fc0a..d7fba99 100644
--- a/test/CodeGenCXX/microsoft-abi-default-cc.cpp
+++ b/test/CodeGenCXX/microsoft-abi-default-cc.cpp
@@ -12,13 +12,13 @@
void foo();
void __cdecl foo();
void __cdecl foo() {}
-// GCABI: define void @_Z3foov()
+// GCABI-LABEL: define void @_Z3foov()
// MSABI: define void @"\01?foo@@YAXXZ"
void __cdecl bar();
void bar();
void bar() {}
-// GCABI: define void @_Z3barv()
+// GCABI-LABEL: define void @_Z3barv()
// MSABI: define void @"\01?bar@@YAXXZ"
// Test that it's OK to mark either the method declaration or method definition
@@ -33,15 +33,15 @@ public:
};
void METHOD_CC A::baz() {}
-// GCABI: define void @_ZN1A3bazEv
+// GCABI-LABEL: define void @_ZN1A3bazEv
// MSABI: define x86_thiscallcc void @"\01?baz@A@@QAEXXZ"
void A::qux() {}
-// GCABI: define void @_ZN1A3quxEv
+// GCABI-LABEL: define void @_ZN1A3quxEv
// MSABI: define x86_thiscallcc void @"\01?qux@A@@QAEXXZ"
void __cdecl static_baz() {}
-// GCABI: define void @_Z10static_bazv
+// GCABI-LABEL: define void @_Z10static_bazv
// MSABI: define void @"\01?static_baz@@YAXXZ"
void static_qux() {}
-// GCABI: define void @_Z10static_quxv
+// GCABI-LABEL: define void @_Z10static_quxv
// MSABI: define void @"\01?static_qux@@YAXXZ"
diff --git a/test/CodeGenCXX/microsoft-abi-exceptions.cpp b/test/CodeGenCXX/microsoft-abi-exceptions.cpp
new file mode 100644
index 0000000..7757ea0
--- /dev/null
+++ b/test/CodeGenCXX/microsoft-abi-exceptions.cpp
@@ -0,0 +1,157 @@
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -cxx-abi microsoft -fexceptions -fno-rtti | FileCheck -check-prefix WIN32 %s
+
+struct A {
+ A();
+ ~A();
+ int a;
+};
+
+A getA();
+
+int TakesTwo(A a, A b);
+void HasEHCleanup() {
+ TakesTwo(getA(), getA());
+}
+
+// With exceptions, we need to clean up at least one of these temporaries.
+// WIN32: define void @"\01?HasEHCleanup@@YAXXZ"() {{.*}} {
+// First one doesn't have any cleanups, no need for invoke.
+// WIN32: call void @"\01?getA@@YA?AUA@@XZ"(%struct.A* sret %{{.*}})
+// If this call throws, we have to cleanup the first temporary.
+// WIN32: invoke void @"\01?getA@@YA?AUA@@XZ"(%struct.A* sret %{{.*}})
+// If this call throws, we already popped our cleanups
+// WIN32: call i32 @"\01?TakesTwo@@YAHUA@@0@Z"
+// WIN32: ret void
+//
+// There should be one dtor call for unwinding from the second getA.
+// WIN32: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"
+// WIN32: }
+
+void TakeRef(const A &a);
+int HasDeactivatedCleanups() {
+ return TakesTwo((TakeRef(A()), A()), (TakeRef(A()), A()));
+}
+
+// WIN32: define i32 @"\01?HasDeactivatedCleanups@@YAHXZ"() {{.*}} {
+// WIN32: %[[isactive:.*]] = alloca i1
+// WIN32: call x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
+// WIN32: invoke void @"\01?TakeRef@@YAXABUA@@@Z"
+// WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %[[arg1:.*]])
+// WIN32: store i1 true, i1* %[[isactive]]
+// WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
+// WIN32: invoke void @"\01?TakeRef@@YAXABUA@@@Z"
+// WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
+// WIN32: store i1 false, i1* %[[isactive]]
+// WIN32: invoke i32 @"\01?TakesTwo@@YAHUA@@0@Z"
+// Destroy the two const ref temporaries.
+// WIN32: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"
+// WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ"
+// WIN32: ret i32
+//
+// Conditionally destroy arg1.
+// WIN32: %[[cond:.*]] = load i1* %[[isactive]]
+// WIN32: br i1 %[[cond]]
+// WIN32: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[arg1]])
+// WIN32: }
+
+// Test putting the cleanups inside a conditional.
+int CouldThrow();
+int HasConditionalCleanup(bool cond) {
+ return (cond ? TakesTwo(A(), A()) : CouldThrow());
+}
+
+// WIN32: define i32 @"\01?HasConditionalCleanup@@YAH_N@Z"(i1 zeroext %{{.*}}) {{.*}} {
+// WIN32: store i1 false
+// WIN32: br i1
+// No cleanups, so we call and then activate a cleanup if it succeeds.
+// WIN32: call x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %[[arg1:.*]])
+// WIN32: store i1 true
+// Now we have a cleanup for the first aggregate, so we invoke.
+// WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %{{.*}})
+// Now we have no cleanups because TakeTwo will destruct both args.
+// WIN32: call i32 @"\01?TakesTwo@@YAHUA@@0@Z"
+// Still no cleanups, so call.
+// WIN32: call i32 @"\01?CouldThrow@@YAHXZ"()
+// Somewhere in the landing pad for our single invoke, call the dtor.
+// WIN32: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[arg1]])
+// WIN32: }
+
+// Now test both.
+int HasConditionalDeactivatedCleanups(bool cond) {
+ return (cond ? TakesTwo((TakeRef(A()), A()), (TakeRef(A()), A())) : CouldThrow());
+}
+
+// WIN32: define i32 @"\01?HasConditionalDeactivatedCleanups@@YAH_N@Z"{{.*}} {
+// WIN32: %[[arg1:.*]] = alloca %struct.A, align 4
+// WIN32: alloca i1
+// WIN32: %[[arg1_cond:.*]] = alloca i1
+// Start all four cleanups as deactivated.
+// WIN32: store i1 false
+// WIN32: store i1 false
+// WIN32: store i1 false
+// WIN32: store i1 false
+// WIN32: br i1
+// True condition.
+// WIN32: call x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
+// WIN32: store i1 true
+// WIN32: invoke void @"\01?TakeRef@@YAXABUA@@@Z"
+// WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %[[arg1]])
+// WIN32: store i1 true, i1* %[[arg1_cond]]
+// WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
+// WIN32: store i1 true
+// WIN32: invoke void @"\01?TakeRef@@YAXABUA@@@Z"
+// WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
+// WIN32: store i1 true
+// WIN32: store i1 false, i1* %[[arg1_cond]]
+// WIN32: invoke i32 @"\01?TakesTwo@@YAHUA@@0@Z"
+// False condition.
+// WIN32: invoke i32 @"\01?CouldThrow@@YAHXZ"()
+// Two normal cleanups for TakeRef args.
+// WIN32: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"
+// WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ"
+// WIN32: ret i32
+//
+// Somewhere in the landing pad soup, we conditionally destroy arg1.
+// WIN32: %[[isactive:.*]] = load i1* %[[arg1_cond]]
+// WIN32: br i1 %[[isactive]]
+// WIN32: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[arg1]])
+// WIN32: }
+
+namespace crash_on_partial_destroy {
+struct A {
+ virtual ~A();
+};
+
+struct B : virtual A {
+ // Has an implicit destructor.
+};
+
+struct C : B {
+ C();
+};
+
+void foo();
+// We used to crash when emitting this.
+C::C() { foo(); }
+
+// Verify that we don't bother with a vbtable lookup when adjusting the this
+// pointer to call a base destructor from a constructor while unwinding.
+// WIN32-LABEL: define {{.*}} @"\01??0C@crash_on_partial_destroy@@QAE@XZ"{{.*}} {
+// WIN32: landingpad
+//
+// We shouldn't do any vbptr loads, just constant GEPs.
+// WIN32-NOT: load
+// WIN32: getelementptr i8* %{{.*}}, i32 4
+// WIN32-NOT: load
+// WIN32: bitcast i8* %{{.*}} to %"struct.crash_on_partial_destroy::B"*
+// WIN32: invoke x86_thiscallcc void @"\01??1B@crash_on_partial_destroy@@UAE@XZ"
+//
+// WIN32-NOT: load
+// WIN32: bitcast %"struct.crash_on_partial_destroy::C"* %{{.*}} to i8*
+// WIN32-NOT: load
+// WIN32: getelementptr inbounds i8* %{{.*}}, i64 4
+// WIN32-NOT: load
+// WIN32: bitcast i8* %{{.*}} to %"struct.crash_on_partial_destroy::A"*
+// WIN32: invoke x86_thiscallcc void @"\01??1A@crash_on_partial_destroy@@UAE@XZ"
+// WIN32: }
+}
diff --git a/test/CodeGenCXX/microsoft-abi-member-pointers.cpp b/test/CodeGenCXX/microsoft-abi-member-pointers.cpp
index 3fffc9d..c0dcd3c 100755
--- a/test/CodeGenCXX/microsoft-abi-member-pointers.cpp
+++ b/test/CodeGenCXX/microsoft-abi-member-pointers.cpp
@@ -1,16 +1,20 @@
// RUN: %clang_cc1 -fno-rtti -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s
+// FIXME: Test x86_64 member pointers when codegen no longer asserts on records
+// with virtual bases.
struct B1 {
void foo();
int b;
};
struct B2 {
+ int b2;
void foo();
};
struct Single : B1 {
void foo();
};
struct Multiple : B1, B2 {
+ int m;
void foo();
};
struct Virtual : virtual B1 {
@@ -34,9 +38,11 @@ struct Polymorphic {
// offset.
struct NonZeroVBPtr : POD, Virtual {
int n;
+ void foo();
};
struct Unspecified;
+struct UnspecSingle;
// Check that we can lower the LLVM types and get the null initializers right.
int Single ::*s_d_memptr;
@@ -45,29 +51,95 @@ int Multiple ::*m_d_memptr;
int Virtual ::*v_d_memptr;
int NonZeroVBPtr::*n_d_memptr;
int Unspecified::*u_d_memptr;
-// CHECK: @"\01?s_d_memptr@@3PQSingle@@HA" = global i32 -1, align 4
-// CHECK: @"\01?p_d_memptr@@3PQPolymorphic@@HA" = global i32 0, align 4
-// CHECK: @"\01?m_d_memptr@@3PQMultiple@@HA" = global i32 -1, align 4
-// CHECK: @"\01?v_d_memptr@@3PQVirtual@@HA" = global { i32, i32 }
+int UnspecSingle::*us_d_memptr;
+// CHECK: @"\01?s_d_memptr@@3PQSingle@@HQ1@" = global i32 -1, align 4
+// CHECK: @"\01?p_d_memptr@@3PQPolymorphic@@HQ1@" = global i32 0, align 4
+// CHECK: @"\01?m_d_memptr@@3PQMultiple@@HQ1@" = global i32 -1, align 4
+// CHECK: @"\01?v_d_memptr@@3PQVirtual@@HQ1@" = global { i32, i32 }
// CHECK: { i32 0, i32 -1 }, align 4
-// CHECK: @"\01?n_d_memptr@@3PQNonZeroVBPtr@@HA" = global { i32, i32 }
+// CHECK: @"\01?n_d_memptr@@3PQNonZeroVBPtr@@HQ1@" = global { i32, i32 }
// CHECK: { i32 0, i32 -1 }, align 4
-// CHECK: @"\01?u_d_memptr@@3PQUnspecified@@HA" = global { i32, i32, i32 }
+// CHECK: @"\01?u_d_memptr@@3PQUnspecified@@HQ1@" = global { i32, i32, i32 }
+// CHECK: { i32 0, i32 0, i32 -1 }, align 4
+// CHECK: @"\01?us_d_memptr@@3PQUnspecSingle@@HQ1@" = global { i32, i32, i32 }
// CHECK: { i32 0, i32 0, i32 -1 }, align 4
void (Single ::*s_f_memptr)();
void (Multiple::*m_f_memptr)();
void (Virtual ::*v_f_memptr)();
-// CHECK: @"\01?s_f_memptr@@3P8Single@@AEXXZA" = global i8* null, align 4
-// CHECK: @"\01?m_f_memptr@@3P8Multiple@@AEXXZA" = global { i8*, i32 } zeroinitializer, align 4
-// CHECK: @"\01?v_f_memptr@@3P8Virtual@@AEXXZA" = global { i8*, i32, i32 } zeroinitializer, align 4
+// CHECK: @"\01?s_f_memptr@@3P8Single@@AEXXZQ1@" = global i8* null, align 4
+// CHECK: @"\01?m_f_memptr@@3P8Multiple@@AEXXZQ1@" = global { i8*, i32 } zeroinitializer, align 4
+// CHECK: @"\01?v_f_memptr@@3P8Virtual@@AEXXZQ1@" = global { i8*, i32, i32 } zeroinitializer, align 4
// We can define Unspecified after locking in the inheritance model.
-struct Unspecified : Virtual {
+struct Unspecified : Multiple, Virtual {
void foo();
int u;
};
+struct UnspecSingle {
+ void foo();
+};
+
+// Test memptr emission in a constant expression.
+namespace Const {
+void (Single ::*s_f_mp)() = &Single::foo;
+void (Multiple ::*m_f_mp)() = &B2::foo;
+void (Virtual ::*v_f_mp)() = &Virtual::foo;
+void (Unspecified::*u_f_mp)() = &Unspecified::foo;
+void (UnspecSingle::*us_f_mp)() = &UnspecSingle::foo;
+// CHECK: @"\01?s_f_mp@Const@@3P8Single@@AEXXZQ2@" =
+// CHECK: global i8* bitcast ({{.*}} @"\01?foo@Single@@QAEXXZ" to i8*), align 4
+// CHECK: @"\01?m_f_mp@Const@@3P8Multiple@@AEXXZQ2@" =
+// CHECK: global { i8*, i32 } { i8* bitcast ({{.*}} @"\01?foo@B2@@QAEXXZ" to i8*), i32 4 }, align 4
+// CHECK: @"\01?v_f_mp@Const@@3P8Virtual@@AEXXZQ2@" =
+// CHECK: global { i8*, i32, i32 } { i8* bitcast ({{.*}} @"\01?foo@Virtual@@QAEXXZ" to i8*), i32 0, i32 0 }, align 4
+// CHECK: @"\01?u_f_mp@Const@@3P8Unspecified@@AEXXZQ2@" =
+// CHECK: global { i8*, i32, i32, i32 } { i8* bitcast ({{.*}} @"\01?foo@Unspecified@@QAEXXZ" to i8*), i32 0, i32 12, i32 0 }, align 4
+// CHECK: @"\01?us_f_mp@Const@@3P8UnspecSingle@@AEXXZQ2@" =
+// CHECK: global { i8*, i32, i32, i32 } { i8* bitcast ({{.*}} @"\01?foo@UnspecSingle@@QAEXXZ" to i8*), i32 0, i32 0, i32 0 }, align 4
+}
+
+namespace CastParam {
+// This exercises ConstExprEmitter instead of ValueDecl::evaluateValue. The
+// extra reinterpret_cast for the parameter type requires more careful folding.
+// FIXME: Or does it? If reinterpret_casts are no-ops, we should be able to
+// strip them in evaluateValue() and just proceed as normal with an APValue.
+struct A {
+ int a;
+ void foo(A *p);
+};
+struct B { int b; };
+struct C : B, A { int c; };
+
+void (A::*ptr1)(void *) = (void (A::*)(void *)) &A::foo;
+// CHECK: @"\01?ptr1@CastParam@@3P8A@1@AEXPAX@ZQ21@" =
+// CHECK: global i8* bitcast (void ({{.*}})* @"\01?foo@A@CastParam@@QAEXPAU12@@Z" to i8*), align 4
+
+// Try a reinterpret_cast followed by a memptr conversion.
+void (C::*ptr2)(void *) = (void (C::*)(void *)) (void (A::*)(void *)) &A::foo;
+// CHECK: @"\01?ptr2@CastParam@@3P8C@1@AEXPAX@ZQ21@" =
+// CHECK: global { i8*, i32 } { i8* bitcast (void ({{.*}})* @"\01?foo@A@CastParam@@QAEXPAU12@@Z" to i8*), i32 4 }, align 4
+
+void (C::*ptr3)(void *) = (void (C::*)(void *)) (void (A::*)(void *)) (void (A::*)(A *)) 0;
+// CHECK: @"\01?ptr3@CastParam@@3P8C@1@AEXPAX@ZQ21@" =
+// CHECK: global { i8*, i32 } zeroinitializer, align 4
+
+struct D : C {
+ virtual void isPolymorphic();
+ int d;
+};
+
+// Try a cast that changes the inheritance model. Null for D is 0, but null for
+// C is -1. We need the cast to long in order to hit the non-APValue path.
+int C::*ptr4 = (int C::*) (int D::*) (long D::*) 0;
+// CHECK: @"\01?ptr4@CastParam@@3PQC@1@HQ21@" = global i32 -1, align 4
+
+// MSVC rejects this but we accept it.
+int C::*ptr5 = (int C::*) (long D::*) 0;
+// CHECK: @"\01?ptr5@CastParam@@3PQC@1@HQ21@" = global i32 -1, align 4
+}
+
struct UnspecWithVBPtr;
int UnspecWithVBPtr::*forceUnspecWithVBPtr;
struct UnspecWithVBPtr : B1, virtual B2 {
@@ -82,7 +154,7 @@ void EmitNonVirtualMemberPointers() {
void (Virtual ::*v_f_memptr)() = &Virtual::foo;
void (Unspecified::*u_f_memptr)() = &Unspecified::foo;
void (UnspecWithVBPtr::*u2_f_memptr)() = &UnspecWithVBPtr::foo;
-// CHECK: define void @"\01?EmitNonVirtualMemberPointers@@YAXXZ"() #0 {
+// CHECK: define void @"\01?EmitNonVirtualMemberPointers@@YAXXZ"() {{.*}} {
// CHECK: alloca i8*, align 4
// CHECK: alloca { i8*, i32 }, align 4
// CHECK: alloca { i8*, i32, i32 }, align 4
@@ -95,7 +167,7 @@ void EmitNonVirtualMemberPointers() {
// CHECK: { i8* bitcast (void (%{{.*}}*)* @"\01?foo@Virtual@@QAEXXZ" to i8*), i32 0, i32 0 },
// CHECK: { i8*, i32, i32 }* %{{.*}}, align 4
// CHECK: store { i8*, i32, i32, i32 }
-// CHECK: { i8* bitcast (void (%{{.*}}*)* @"\01?foo@Unspecified@@QAEXXZ" to i8*), i32 0, i32 0, i32 0 },
+// CHECK: { i8* bitcast (void (%{{.*}}*)* @"\01?foo@Unspecified@@QAEXXZ" to i8*), i32 0, i32 12, i32 0 },
// CHECK: { i8*, i32, i32, i32 }* %{{.*}}, align 4
// CHECK: store { i8*, i32, i32, i32 }
// CHECK: { i8* bitcast (void (%{{.*}}*)* @"\01?foo@UnspecWithVBPtr@@QAEXXZ" to i8*),
@@ -112,7 +184,7 @@ void podMemPtrs() {
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: define void @"\01?podMemPtrs@@YAXXZ"() {{.*}} {
// CHECK: %[[memptr:.*]] = alloca i32, align 4
// CHECK-NEXT: store i32 0, i32* %[[memptr]], align 4
// CHECK-NEXT: store i32 4, i32* %[[memptr]], align 4
@@ -132,7 +204,7 @@ void polymorphicMemPtrs() {
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: define void @"\01?polymorphicMemPtrs@@YAXXZ"() {{.*}} {
// CHECK: %[[memptr:.*]] = alloca i32, align 4
// CHECK-NEXT: store i32 4, i32* %[[memptr]], align 4
// CHECK-NEXT: store i32 8, i32* %[[memptr]], align 4
@@ -233,7 +305,7 @@ int loadDataMemberPointerUnspecified(Unspecified *o, int Unspecified::*memptr) {
void callMemberPointerSingle(Single *o, void (Single::*memptr)()) {
(o->*memptr)();
// Just look for an indirect thiscall.
-// CHECK: define void @"\01?callMemberPointerSingle@@{{.*}} #0 {
+// CHECK: define void @"\01?callMemberPointerSingle@@{{.*}} {{.*}} {
// CHECK: call x86_thiscallcc void %{{.*}}(%{{.*}} %{{.*}})
// CHECK: ret void
// CHECK: }
@@ -241,7 +313,7 @@ void callMemberPointerSingle(Single *o, void (Single::*memptr)()) {
void callMemberPointerMultiple(Multiple *o, void (Multiple::*memptr)()) {
(o->*memptr)();
-// CHECK: define void @"\01?callMemberPointerMultiple@@{{.*}} #0 {
+// CHECK: define void @"\01?callMemberPointerMultiple@@{{.*}} {
// CHECK: %[[memptr0:.*]] = extractvalue { i8*, i32 } %{{.*}}, 0
// CHECK: %[[memptr1:.*]] = extractvalue { i8*, i32 } %{{.*}}, 1
// CHECK: %[[this_adjusted:.*]] = getelementptr inbounds i8* %{{.*}}, i32 %[[memptr1]]
@@ -255,7 +327,7 @@ void callMemberPointerMultiple(Multiple *o, void (Multiple::*memptr)()) {
void callMemberPointerVirtualBase(Virtual *o, void (Virtual::*memptr)()) {
(o->*memptr)();
// This shares a lot with virtual data member pointers.
-// CHECK: define void @"\01?callMemberPointerVirtualBase@@{{.*}} #0 {
+// CHECK: define void @"\01?callMemberPointerVirtualBase@@{{.*}} {
// CHECK: %[[memptr0:.*]] = extractvalue { i8*, i32, i32 } %{{.*}}, 0
// CHECK: %[[memptr1:.*]] = extractvalue { i8*, i32, i32 } %{{.*}}, 1
// CHECK: %[[memptr2:.*]] = extractvalue { i8*, i32, i32 } %{{.*}}, 2
@@ -361,3 +433,107 @@ bool unspecDataMemptrEq(int Unspecified::*l, int Unspecified::*r) {
// CHECK: ret i1
// CHECK: }
}
+
+void (Multiple::*convertB2FuncToMultiple(void (B2::*mp)()))() {
+ return mp;
+// CHECK: define i64 @"\01?convertB2FuncToMultiple@@YAP8Multiple@@AEXXZP8B2@@AEXXZ@Z"{{.*}} {
+// CHECK: store
+// CHECK: %[[mp:.*]] = load i8** %{{.*}}, align 4
+// CHECK: icmp ne i8* %[[mp]], null
+// CHECK: br i1 %{{.*}} label %{{.*}}, label %{{.*}}
+//
+// memptr.convert: ; preds = %entry
+// CHECK: insertvalue { i8*, i32 } undef, i8* %[[mp]], 0
+// CHECK: insertvalue { i8*, i32 } %{{.*}}, i32 4, 1
+// CHECK: br label
+//
+// memptr.converted: ; preds = %memptr.convert, %entry
+// CHECK: phi { i8*, i32 } [ zeroinitializer, %{{.*}} ], [ {{.*}} ]
+// CHECK: }
+}
+
+void (B2::*convertMultipleFuncToB2(void (Multiple::*mp)()))() {
+// FIXME: cl emits warning C4407 on this code because of the representation
+// change. We might want to do the same.
+ return static_cast<void (B2::*)()>(mp);
+// FIXME: We should return i8* instead of i32 here. The ptrtoint cast prevents
+// LLVM from optimizing away the branch. This is likely a bug in
+// lib/CodeGen/TargetInfo.cpp with how we classify memptr types for returns.
+//
+// CHECK: define i32 @"\01?convertMultipleFuncToB2@@YAP8B2@@AEXXZP8Multiple@@AEXXZ@Z"{{.*}} {
+// CHECK: store
+// CHECK: %[[src:.*]] = load { i8*, i32 }* %{{.*}}, align 4
+// CHECK: extractvalue { i8*, i32 } %[[src]], 0
+// CHECK: icmp ne i8* %{{.*}}, null
+// CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}}
+//
+// memptr.convert: ; preds = %entry
+// CHECK: %[[fp:.*]] = extractvalue { i8*, i32 } %[[src]], 0
+// CHECK: br label
+//
+// memptr.converted: ; preds = %memptr.convert, %entry
+// CHECK: phi i8* [ null, %{{.*}} ], [ %[[fp]], %{{.*}} ]
+// CHECK: }
+}
+
+namespace Test1 {
+
+struct A { int a; };
+struct B { int b; };
+struct C : virtual A { int c; };
+struct D : B, C { int d; };
+
+void (D::*convertCToD(void (C::*mp)()))() {
+ return mp;
+// CHECK: define void @"\01?convertCToD@Test1@@YAP8D@1@AEXXZP8C@1@AEXXZ@Z"{{.*}} {
+// CHECK: store
+// CHECK: load { i8*, i32, i32 }* %{{.*}}, align 4
+// CHECK: extractvalue { i8*, i32, i32 } %{{.*}}, 0
+// CHECK: icmp ne i8* %{{.*}}, null
+// CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}}
+//
+// memptr.convert: ; preds = %entry
+// CHECK: extractvalue { i8*, i32, i32 } %{{.*}}, 0
+// CHECK: extractvalue { i8*, i32, i32 } %{{.*}}, 1
+// CHECK: extractvalue { i8*, i32, i32 } %{{.*}}, 2
+// CHECK: %[[adj:.*]] = add nsw i32 %{{.*}}, 4
+// CHECK: insertvalue { i8*, i32, i32 } undef, i8* {{.*}}, 0
+// CHECK: insertvalue { i8*, i32, i32 } {{.*}}, i32 %[[adj]], 1
+// CHECK: insertvalue { i8*, i32, i32 } {{.*}}, i32 {{.*}}, 2
+// CHECK: br label
+//
+// memptr.converted: ; preds = %memptr.convert, %entry
+// CHECK: phi { i8*, i32, i32 } [ { i8* null, i32 0, i32 -1 }, {{.*}} ], [ {{.*}} ]
+// CHECK: }
+}
+
+}
+
+namespace Test2 {
+// Test that we dynamically convert between different null reps.
+
+struct A { int a; };
+struct B : A { int b; };
+struct C : A {
+ int c;
+ virtual void hasVfPtr();
+};
+
+int A::*reinterpret(int B::*mp) {
+ return reinterpret_cast<int A::*>(mp);
+// CHECK: define i32 @"\01?reinterpret@Test2@@YAPQA@1@HPQB@1@H@Z"{{.*}} {
+// CHECK-NOT: select
+// CHECK: ret i32
+// CHECK: }
+}
+
+int A::*reinterpret(int C::*mp) {
+ return reinterpret_cast<int A::*>(mp);
+// CHECK: define i32 @"\01?reinterpret@Test2@@YAPQA@1@HPQC@1@H@Z"{{.*}} {
+// CHECK: %[[mp:.*]] = load i32*
+// CHECK: %[[cmp:.*]] = icmp ne i32 %[[mp]], 0
+// CHECK: select i1 %[[cmp]], i32 %[[mp]], i32 -1
+// CHECK: }
+}
+
+}
diff --git a/test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp b/test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp
new file mode 100644
index 0000000..802f0ca
--- /dev/null
+++ b/test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp
@@ -0,0 +1,201 @@
+// RUN: %clang_cc1 -fno-rtti -emit-llvm %s -o - -mconstructor-aliases -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s
+
+struct Left {
+ virtual void left();
+};
+
+struct Right {
+ virtual void right();
+};
+
+struct ChildNoOverride : Left, Right {
+};
+
+struct ChildOverride : Left, Right {
+ virtual void left();
+ virtual void right();
+};
+
+extern "C" void foo(void *);
+
+void call_left_no_override(ChildNoOverride *child) {
+// CHECK: define void @"\01?call_left_no_override
+// CHECK: %[[CHILD:.*]] = load %struct.ChildNoOverride
+
+ child->left();
+// Only need to cast 'this' to Left*.
+// CHECK: %[[LEFT:.*]] = bitcast %struct.ChildNoOverride* %[[CHILD]] to %struct.Left*
+// CHECK: %[[VFPTR:.*]] = bitcast %struct.Left* %[[LEFT]] to void (%struct.Left*)***
+// CHECK: %[[VFTABLE:.*]] = load void (%struct.Left*)*** %[[VFPTR]]
+// CHECK: %[[VFUN:.*]] = getelementptr inbounds void (%struct.Left*)** %[[VFTABLE]], i64 0
+// CHECK: %[[VFUN_VALUE:.*]] = load void (%struct.Left*)** %[[VFUN]]
+// CHECK: call x86_thiscallcc void %[[VFUN_VALUE]](%struct.Left* %[[LEFT]])
+// CHECK: ret
+}
+
+void ChildOverride::left() {
+// CHECK: define x86_thiscallcc void @"\01?left@ChildOverride@@UAEXXZ"(%struct.ChildOverride* %[[THIS:.*]])
+//
+// No need to adjust 'this' as the ChildOverride's layout begins with Left.
+// CHECK: %[[THIS_ADDR:.*]] = alloca %struct.ChildOverride*, align 4
+// CHECK: store %struct.ChildOverride* %[[THIS]], %struct.ChildOverride** %[[THIS_ADDR]], align 4
+
+ foo(this);
+// CHECK: %[[THIS:.*]] = load %struct.ChildOverride** %[[THIS_ADDR]]
+// CHECK: %[[THIS_i8:.*]] = bitcast %struct.ChildOverride* %[[THIS]] to i8*
+// CHECK: call void @foo(i8* %[[THIS_i8]])
+// CHECK: ret
+}
+
+void call_left_override(ChildOverride *child) {
+// CHECK: define void @"\01?call_left_override
+// CHECK: %[[CHILD:.*]] = load %struct.ChildOverride
+
+ child->left();
+// CHECK: %[[VFPTR:.*]] = bitcast %struct.ChildOverride* %[[CHILD]] to void (%struct.ChildOverride*)***
+// CHECK: %[[VFTABLE:.*]] = load void (%struct.ChildOverride*)*** %[[VFPTR]]
+// CHECK: %[[VFUN:.*]] = getelementptr inbounds void (%struct.ChildOverride*)** %[[VFTABLE]], i64 0
+// CHECK: %[[VFUN_VALUE:.*]] = load void (%struct.ChildOverride*)** %[[VFUN]]
+//
+// CHECK: call x86_thiscallcc void %[[VFUN_VALUE]](%struct.ChildOverride* %[[CHILD]])
+// CHECK: ret
+}
+
+void call_right_no_override(ChildNoOverride *child) {
+// CHECK: define void @"\01?call_right_no_override
+// CHECK: %[[CHILD:.*]] = load %struct.ChildNoOverride
+
+ child->right();
+// When calling a right base's virtual method, one needs to adjust 'this' at
+// the caller site.
+//
+// CHECK: %[[CHILD_i8:.*]] = bitcast %struct.ChildNoOverride* %[[CHILD]] to i8*
+// CHECK: %[[RIGHT_i8:.*]] = getelementptr inbounds i8* %[[CHILD_i8]], i32 4
+// CHECK: %[[RIGHT:.*]] = bitcast i8* %[[RIGHT_i8]] to %struct.Right*
+//
+// CHECK: %[[VFPTR:.*]] = bitcast %struct.Right* %[[RIGHT]] to void (%struct.Right*)***
+// CHECK: %[[VFTABLE:.*]] = load void (%struct.Right*)*** %[[VFPTR]]
+// CHECK: %[[VFUN:.*]] = getelementptr inbounds void (%struct.Right*)** %[[VFTABLE]], i64 0
+// CHECK: %[[VFUN_VALUE:.*]] = load void (%struct.Right*)** %[[VFUN]]
+// CHECK: call x86_thiscallcc void %[[VFUN_VALUE]](%struct.Right* %[[RIGHT]])
+// CHECK: ret
+}
+
+void ChildOverride::right() {
+// CHECK: define x86_thiscallcc void @"\01?right@ChildOverride@@UAEXXZ"(i8*
+//
+// ChildOverride::right gets 'this' cast to Right* in ECX (i.e. this+4) so we
+// need to adjust 'this' before use.
+//
+// CHECK: %[[THIS_ADDR:.*]] = alloca %struct.ChildOverride*, align 4
+// CHECK: %[[THIS_i8:.*]] = getelementptr inbounds i8* %[[ECX:.*]], i32 -4
+// CHECK: %[[THIS:.*]] = bitcast i8* %[[THIS_i8]] to %struct.ChildOverride*
+// CHECK: store %struct.ChildOverride* %[[THIS]], %struct.ChildOverride** %[[THIS_ADDR]], align 4
+
+ foo(this);
+// CHECK: %[[THIS:.*]] = load %struct.ChildOverride** %[[THIS_ADDR]]
+// CHECK: %[[THIS_PARAM:.*]] = bitcast %struct.ChildOverride* %[[THIS]] to i8*
+// CHECK: call void @foo(i8* %[[THIS_PARAM]])
+// CHECK: ret
+}
+
+void call_right_override(ChildOverride *child) {
+// CHECK: define void @"\01?call_right_override
+// CHECK: %[[CHILD:.*]] = load %struct.ChildOverride
+
+ child->right();
+// When calling a right child's virtual method, one needs to adjust 'this' at
+// the caller site.
+//
+// CHECK: %[[CHILD_i8:.*]] = bitcast %struct.ChildOverride* %[[CHILD]] to i8*
+//
+// CHECK: %[[VFPTR_i8:.*]] = getelementptr inbounds i8* %[[CHILD_i8]], i32 4
+// CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to void (i8*)***
+// CHECK: %[[VFTABLE:.*]] = load void (i8*)*** %[[VFPTR]]
+// CHECK: %[[VFUN:.*]] = getelementptr inbounds void (i8*)** %[[VFTABLE]], i64 0
+// CHECK: %[[VFUN_VALUE:.*]] = load void (i8*)** %[[VFUN]]
+//
+// CHECK: %[[CHILD_i8:.*]] = bitcast %struct.ChildOverride* %[[CHILD]] to i8*
+// CHECK: %[[RIGHT:.*]] = getelementptr inbounds i8* %[[CHILD_i8]], i32 4
+//
+// CHECK: call x86_thiscallcc void %[[VFUN_VALUE]](i8* %[[RIGHT]])
+// CHECK: ret
+}
+
+struct GrandchildOverride : ChildOverride {
+ virtual void right();
+};
+
+void GrandchildOverride::right() {
+// CHECK: define x86_thiscallcc void @"\01?right@GrandchildOverride@@UAEXXZ"(i8*
+//
+// CHECK: %[[THIS_ADDR:.*]] = alloca %struct.GrandchildOverride*, align 4
+// CHECK: %[[THIS_i8:.*]] = getelementptr inbounds i8* %[[ECX:.*]], i32 -4
+// CHECK: %[[THIS:.*]] = bitcast i8* %[[THIS_i8]] to %struct.GrandchildOverride*
+// CHECK: store %struct.GrandchildOverride* %[[THIS]], %struct.GrandchildOverride** %[[THIS_ADDR]], align 4
+
+ foo(this);
+// CHECK: %[[THIS:.*]] = load %struct.GrandchildOverride** %[[THIS_ADDR]]
+// CHECK: %[[THIS_PARAM:.*]] = bitcast %struct.GrandchildOverride* %[[THIS]] to i8*
+// CHECK: call void @foo(i8* %[[THIS_PARAM]])
+// CHECK: ret
+}
+
+void call_grandchild_right(GrandchildOverride *obj) {
+ // Just make sure we don't crash.
+ obj->right();
+}
+
+void emit_ctors() {
+ Left l;
+ // CHECK: define {{.*}} @"\01??0Left@@QAE@XZ"
+ // CHECK-NOT: getelementptr
+ // CHECK: store [1 x i8*]* @"\01??_7Left@@6B@"
+ // CHECK: ret
+
+ Right r;
+ // CHECK: define {{.*}} @"\01??0Right@@QAE@XZ"
+ // CHECK-NOT: getelementptr
+ // CHECK: store [1 x i8*]* @"\01??_7Right@@6B@"
+ // CHECK: ret
+
+ ChildOverride co;
+ // CHECK: define {{.*}} @"\01??0ChildOverride@@QAE@XZ"
+ // CHECK: %[[THIS:.*]] = load %struct.ChildOverride**
+ // CHECK: %[[VFPTR:.*]] = bitcast %struct.ChildOverride* %[[THIS]] to [1 x i8*]**
+ // CHECK: store [1 x i8*]* @"\01??_7ChildOverride@@6BLeft@@@", [1 x i8*]** %[[VFPTR]]
+ // CHECK: %[[THIS_i8:.*]] = bitcast %struct.ChildOverride* %[[THIS]] to i8*
+ // CHECK: %[[VFPTR_i8:.*]] = getelementptr inbounds i8* %[[THIS_i8]], i32 4
+ // CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to [1 x i8*]**
+ // CHECK: store [1 x i8*]* @"\01??_7ChildOverride@@6BRight@@@", [1 x i8*]** %[[VFPTR]]
+ // CHECK: ret
+
+ GrandchildOverride gc;
+ // CHECK: define {{.*}} @"\01??0GrandchildOverride@@QAE@XZ"
+ // CHECK: %[[THIS:.*]] = load %struct.GrandchildOverride**
+ // CHECK: %[[VFPTR:.*]] = bitcast %struct.GrandchildOverride* %[[THIS]] to [1 x i8*]**
+ // CHECK: store [1 x i8*]* @"\01??_7GrandchildOverride@@6BLeft@@@", [1 x i8*]** %[[VFPTR]]
+ // CHECK: %[[THIS_i8:.*]] = bitcast %struct.GrandchildOverride* %[[THIS]] to i8*
+ // CHECK: %[[VFPTR_i8:.*]] = getelementptr inbounds i8* %[[THIS_i8]], i32 4
+ // CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to [1 x i8*]**
+ // CHECK: store [1 x i8*]* @"\01??_7GrandchildOverride@@6BRight@@@", [1 x i8*]** %[[VFPTR]]
+ // CHECK: ret
+}
+
+struct LeftWithNonVirtualDtor {
+ virtual void left();
+ ~LeftWithNonVirtualDtor();
+};
+
+struct AsymmetricChild : LeftWithNonVirtualDtor, Right {
+ virtual ~AsymmetricChild();
+};
+
+void call_asymmetric_child_complete_dtor() {
+ // CHECK-LABEL: define void @"\01?call_asymmetric_child_complete_dtor@@YAXXZ"
+ AsymmetricChild obj;
+ // CHECK: call x86_thiscallcc %struct.AsymmetricChild* @"\01??0AsymmetricChild@@QAE@XZ"(%struct.AsymmetricChild* %[[OBJ:.*]])
+ // CHECK-NOT: getelementptr
+ // CHECK: call x86_thiscallcc void @"\01??1AsymmetricChild@@UAE@XZ"(%struct.AsymmetricChild* %[[OBJ]])
+ // CHECK: ret
+}
diff --git a/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp b/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
index 060c172..d0750e6 100644
--- a/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
+++ b/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-linux | FileCheck -check-prefix LINUX %s
-// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 -cxx-abi microsoft | FileCheck -check-prefix WIN32 %s
-// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-pc-win32 -cxx-abi microsoft | FileCheck -check-prefix WIN64 %s
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -cxx-abi microsoft -fno-rtti | FileCheck -check-prefix WIN32 %s
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-pc-win32 -mconstructor-aliases -cxx-abi microsoft -fno-rtti | FileCheck -check-prefix WIN64 %s
struct Empty {};
@@ -22,6 +22,12 @@ struct SmallWithCtor {
int x;
};
+struct SmallWithDtor {
+ SmallWithDtor();
+ ~SmallWithDtor();
+ int x;
+};
+
struct SmallWithVftable {
int x;
virtual void foo();
@@ -43,70 +49,108 @@ struct Big {
// Returning structs that fit into a register.
Small small_return() { return Small(); }
-// LINUX: define void @_Z12small_returnv(%struct.Small* noalias sret %agg.result)
+// LINUX-LABEL: define void @_Z12small_returnv(%struct.Small* noalias sret %agg.result)
// WIN32: define i32 @"\01?small_return@@YA?AUSmall@@XZ"()
// WIN64: define i32 @"\01?small_return@@YA?AUSmall@@XZ"()
Medium medium_return() { return Medium(); }
-// LINUX: define void @_Z13medium_returnv(%struct.Medium* noalias sret %agg.result)
+// LINUX-LABEL: define void @_Z13medium_returnv(%struct.Medium* noalias sret %agg.result)
// WIN32: define i64 @"\01?medium_return@@YA?AUMedium@@XZ"()
// WIN64: define i64 @"\01?medium_return@@YA?AUMedium@@XZ"()
// Returning structs that fit into a register but are not POD.
SmallCpp11NotCpp03Pod small_non_pod_return() { return SmallCpp11NotCpp03Pod(); }
-// LINUX: define void @_Z20small_non_pod_returnv(%struct.SmallCpp11NotCpp03Pod* noalias sret %agg.result)
+// LINUX-LABEL: define void @_Z20small_non_pod_returnv(%struct.SmallCpp11NotCpp03Pod* noalias sret %agg.result)
// WIN32: define void @"\01?small_non_pod_return@@YA?AUSmallCpp11NotCpp03Pod@@XZ"(%struct.SmallCpp11NotCpp03Pod* noalias sret %agg.result)
// WIN64: define void @"\01?small_non_pod_return@@YA?AUSmallCpp11NotCpp03Pod@@XZ"(%struct.SmallCpp11NotCpp03Pod* noalias sret %agg.result)
SmallWithCtor small_with_ctor_return() { return SmallWithCtor(); }
-// LINUX: define void @_Z22small_with_ctor_returnv(%struct.SmallWithCtor* noalias sret %agg.result)
+// LINUX-LABEL: define void @_Z22small_with_ctor_returnv(%struct.SmallWithCtor* noalias sret %agg.result)
// WIN32: define void @"\01?small_with_ctor_return@@YA?AUSmallWithCtor@@XZ"(%struct.SmallWithCtor* noalias sret %agg.result)
// WIN64: define void @"\01?small_with_ctor_return@@YA?AUSmallWithCtor@@XZ"(%struct.SmallWithCtor* noalias sret %agg.result)
SmallWithVftable small_with_vftable_return() { return SmallWithVftable(); }
-// LINUX: define void @_Z25small_with_vftable_returnv(%struct.SmallWithVftable* noalias sret %agg.result)
+// LINUX-LABEL: define void @_Z25small_with_vftable_returnv(%struct.SmallWithVftable* noalias sret %agg.result)
// WIN32: define void @"\01?small_with_vftable_return@@YA?AUSmallWithVftable@@XZ"(%struct.SmallWithVftable* noalias sret %agg.result)
// WIN64: define void @"\01?small_with_vftable_return@@YA?AUSmallWithVftable@@XZ"(%struct.SmallWithVftable* noalias sret %agg.result)
MediumWithCopyCtor medium_with_copy_ctor_return() { return MediumWithCopyCtor(); }
-// LINUX: define void @_Z28medium_with_copy_ctor_returnv(%struct.MediumWithCopyCtor* noalias sret %agg.result)
+// LINUX-LABEL: define void @_Z28medium_with_copy_ctor_returnv(%struct.MediumWithCopyCtor* noalias sret %agg.result)
// WIN32: define void @"\01?medium_with_copy_ctor_return@@YA?AUMediumWithCopyCtor@@XZ"(%struct.MediumWithCopyCtor* noalias sret %agg.result)
// WIN64: define void @"\01?medium_with_copy_ctor_return@@YA?AUMediumWithCopyCtor@@XZ"(%struct.MediumWithCopyCtor* noalias sret %agg.result)
// Returning a large struct that doesn't fit into a register.
Big big_return() { return Big(); }
-// LINUX: define void @_Z10big_returnv(%struct.Big* noalias sret %agg.result)
+// LINUX-LABEL: define void @_Z10big_returnv(%struct.Big* noalias sret %agg.result)
// WIN32: define void @"\01?big_return@@YA?AUBig@@XZ"(%struct.Big* noalias sret %agg.result)
// WIN64: define void @"\01?big_return@@YA?AUBig@@XZ"(%struct.Big* noalias sret %agg.result)
void small_arg(Small s) {}
-// LINUX: define void @_Z9small_arg5Small(%struct.Small* byval align 4 %s)
+// LINUX-LABEL: define void @_Z9small_arg5Small(%struct.Small* byval align 4 %s)
// WIN32: define void @"\01?small_arg@@YAXUSmall@@@Z"(%struct.Small* byval align 4 %s)
// WIN64: define void @"\01?small_arg@@YAXUSmall@@@Z"(i32 %s.coerce)
void medium_arg(Medium s) {}
-// LINUX: define void @_Z10medium_arg6Medium(%struct.Medium* byval align 4 %s)
+// LINUX-LABEL: define void @_Z10medium_arg6Medium(%struct.Medium* byval align 4 %s)
// WIN32: define void @"\01?medium_arg@@YAXUMedium@@@Z"(%struct.Medium* byval align 4 %s)
// WIN64: define void @"\01?medium_arg@@YAXUMedium@@@Z"(i64 %s.coerce)
void small_arg_with_ctor(SmallWithCtor s) {}
-// LINUX: define void @_Z19small_arg_with_ctor13SmallWithCtor(%struct.SmallWithCtor* byval align 4 %s)
+// LINUX-LABEL: define void @_Z19small_arg_with_ctor13SmallWithCtor(%struct.SmallWithCtor* byval align 4 %s)
// WIN32: define void @"\01?small_arg_with_ctor@@YAXUSmallWithCtor@@@Z"(%struct.SmallWithCtor* byval align 4 %s)
// WIN64: define void @"\01?small_arg_with_ctor@@YAXUSmallWithCtor@@@Z"(i32 %s.coerce)
+// Test that dtors are invoked in the callee.
+void small_arg_with_dtor(SmallWithDtor s) {}
+// WIN32: define void @"\01?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(%struct.SmallWithDtor* byval align 4 %s) {{.*}} {
+// WIN32: call x86_thiscallcc void @"\01??1SmallWithDtor@@QAE@XZ"(%struct.SmallWithDtor* %s)
+// WIN32: }
+// WIN64: define void @"\01?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(%struct.SmallWithDtor* byval %s) {{.*}} {
+// WIN64: call void @"\01??1SmallWithDtor@@QEAA@XZ"(%struct.SmallWithDtor* %s)
+// WIN64: }
+
+// Test that references aren't destroyed in the callee.
+void ref_small_arg_with_dtor(const SmallWithDtor &s) { }
+// WIN32: define void @"\01?ref_small_arg_with_dtor@@YAXABUSmallWithDtor@@@Z"(%struct.SmallWithDtor* %s) {{.*}} {
+// WIN32-NOT: call x86_thiscallcc void @"\01??1SmallWithDtor@@QAE@XZ"
+// WIN32: }
+
+// Test that temporaries passed by reference are destroyed in the caller.
+void temporary_ref_with_dtor() {
+ ref_small_arg_with_dtor(SmallWithDtor());
+}
+// WIN32: define void @"\01?temporary_ref_with_dtor@@YAXXZ"() {{.*}} {
+// WIN32: call x86_thiscallcc %struct.SmallWithDtor* @"\01??0SmallWithDtor@@QAE@XZ"
+// WIN32: call void @"\01?ref_small_arg_with_dtor@@YAXABUSmallWithDtor@@@Z"
+// WIN32: call x86_thiscallcc void @"\01??1SmallWithDtor@@QAE@XZ"
+// WIN32: }
+
+void takes_two_by_val_with_dtor(SmallWithDtor a, SmallWithDtor b);
+void eh_cleanup_arg_with_dtor() {
+ takes_two_by_val_with_dtor(SmallWithDtor(), SmallWithDtor());
+}
+// When exceptions are off, we don't have any cleanups. See
+// microsoft-abi-exceptions.cpp for these cleanups.
+// WIN32: define void @"\01?eh_cleanup_arg_with_dtor@@YAXXZ"() {{.*}} {
+// WIN32: call x86_thiscallcc %struct.SmallWithDtor* @"\01??0SmallWithDtor@@QAE@XZ"
+// WIN32: call x86_thiscallcc %struct.SmallWithDtor* @"\01??0SmallWithDtor@@QAE@XZ"
+// WIN32: call void @"\01?takes_two_by_val_with_dtor@@YAXUSmallWithDtor@@0@Z"
+// WIN32-NOT: call x86_thiscallcc void @"\01??1SmallWithDtor@@QAE@XZ"
+// WIN32: }
+
void small_arg_with_vftable(SmallWithVftable s) {}
-// LINUX: define void @_Z22small_arg_with_vftable16SmallWithVftable(%struct.SmallWithVftable* %s)
+// LINUX-LABEL: define void @_Z22small_arg_with_vftable16SmallWithVftable(%struct.SmallWithVftable* %s)
// WIN32: define void @"\01?small_arg_with_vftable@@YAXUSmallWithVftable@@@Z"(%struct.SmallWithVftable* byval align 4 %s)
// WIN64: define void @"\01?small_arg_with_vftable@@YAXUSmallWithVftable@@@Z"(%struct.SmallWithVftable* byval %s)
void medium_arg_with_copy_ctor(MediumWithCopyCtor s) {}
-// LINUX: define void @_Z25medium_arg_with_copy_ctor18MediumWithCopyCtor(%struct.MediumWithCopyCtor* %s)
+// LINUX-LABEL: define void @_Z25medium_arg_with_copy_ctor18MediumWithCopyCtor(%struct.MediumWithCopyCtor* %s)
// WIN32: define void @"\01?medium_arg_with_copy_ctor@@YAXUMediumWithCopyCtor@@@Z"(%struct.MediumWithCopyCtor* byval align 4 %s)
// WIN64: define void @"\01?medium_arg_with_copy_ctor@@YAXUMediumWithCopyCtor@@@Z"(%struct.MediumWithCopyCtor* byval %s)
void big_arg(Big s) {}
-// LINUX: define void @_Z7big_arg3Big(%struct.Big* byval align 4 %s)
+// LINUX-LABEL: define void @_Z7big_arg3Big(%struct.Big* byval align 4 %s)
// WIN32: define void @"\01?big_arg@@YAXUBig@@@Z"(%struct.Big* byval align 4 %s)
// WIN64: define void @"\01?big_arg@@YAXUBig@@@Z"(%struct.Big* %s)
@@ -167,3 +211,19 @@ void use_class() {
c.thiscall_method_arg(SmallWithCtor());
c.thiscall_method_arg(Big());
}
+
+struct X {
+ X();
+ ~X();
+};
+void g(X) {
+}
+// WIN32: define void @"\01?g@@YAXUX@@@Z"(%struct.X* byval align 4) {{.*}} {
+// WIN32: call x86_thiscallcc void @"\01??1X@@QAE@XZ"(%struct.X* %0)
+// WIN32: }
+void f() {
+ g(X());
+}
+// WIN32: define void @"\01?f@@YAXXZ"() {{.*}} {
+// WIN32-NOT: call {{.*}} @"\01??1X@@QAE@XZ"
+// WIN32: }
diff --git a/test/CodeGenCXX/microsoft-abi-static-initializers.cpp b/test/CodeGenCXX/microsoft-abi-static-initializers.cpp
index 35e343b..c0b9722 100644
--- a/test/CodeGenCXX/microsoft-abi-static-initializers.cpp
+++ b/test/CodeGenCXX/microsoft-abi-static-initializers.cpp
@@ -1,19 +1,85 @@
-// RUN: %clang_cc1 -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm %s -o - -mconstructor-aliases -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s
+
+// CHECK: @llvm.global_ctors = appending global [2 x { i32, void ()* }]
+// CHECK: [{ i32, void ()* } { i32 65535, void ()* @"\01??__Efoo@?$B@H@@YAXXZ" },
+// CHECK: { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I_a }]
struct S {
- S() {}
- ~S() {}
-} s;
+ S();
+ ~S();
+};
-// CHECK: define internal void [[INIT_s:@.*global_var.*]] [[NUW:#[0-9]+]]
+S s;
+
+// CHECK: define internal void @"\01??__Es@@YAXXZ"() [[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: call i32 @atexit(void ()* @"\01??__Fs@@YAXXZ")
// CHECK: ret void
-// CHECK: define internal void @"__dtor_\01?s@@3US@@A"() [[NUW]] {
+// CHECK: define internal void @"\01??__Fs@@YAXXZ"() [[NUW]] {
// CHECK: call x86_thiscallcc void @"\01??1S@@QAE@XZ"
// CHECK: ret void
+void StaticLocal() {
+ static S TheS;
+}
+// CHECK-LABEL: define void @"\01?StaticLocal@@YAXXZ"()
+// CHECK: load i32* @"\01?$S1@?1??StaticLocal@@YAXXZ@4IA"
+// CHECK: store i32 {{.*}}, i32* @"\01?$S1@?1??StaticLocal@@YAXXZ@4IA"
+// CHECK: ret
+
+void MultipleStatics() {
+ static S S1;
+ static S S2;
+ static S S3;
+ static S S4;
+ static S S5;
+ static S S6;
+ static S S7;
+ static S S8;
+ static S S9;
+ static S S10;
+ static S S11;
+ static S S12;
+ static S S13;
+ static S S14;
+ static S S15;
+ static S S16;
+ static S S17;
+ static S S18;
+ static S S19;
+ static S S20;
+ static S S21;
+ static S S22;
+ static S S23;
+ static S S24;
+ static S S25;
+ static S S26;
+ static S S27;
+ static S S28;
+ static S S29;
+ static S S30;
+ static S S31;
+ static S S32;
+ static S S33;
+ static S S34;
+ static S S35;
+}
+// CHECK-LABEL: define void @"\01?MultipleStatics@@YAXXZ"()
+// CHECK: load i32* @"\01?$S1@?1??MultipleStatics@@YAXXZ@4IA"
+// CHECK: and i32 {{.*}}, 1
+// CHECK: and i32 {{.*}}, 2
+// CHECK: and i32 {{.*}}, 4
+// CHECK: and i32 {{.*}}, 8
+// CHECK: and i32 {{.*}}, 16
+// ...
+// CHECK: and i32 {{.*}}, -2147483648
+// CHECK: load i32* @"\01?$S1@?1??MultipleStatics@@YAXXZ@4IA1"
+// CHECK: and i32 {{.*}}, 1
+// CHECK: and i32 {{.*}}, 2
+// CHECK: and i32 {{.*}}, 4
+// CHECK: ret
+
// Force WeakODRLinkage by using templates
class A {
public:
@@ -29,26 +95,60 @@ class B {
template<typename T> A B<T>::foo;
+inline S &UnreachableStatic() {
+ if (0) {
+ static S s; // bit 1
+ return s;
+ }
+ static S s; // bit 2
+ return s;
+}
+
+// CHECK-LABEL: define linkonce_odr %struct.S* @"\01?UnreachableStatic@@YAAAUS@@XZ"()
+// CHECK: and i32 {{.*}}, 2
+// CHECK: or i32 {{.*}}, 2
+// CHECK: ret
+
+inline S &getS() {
+ static S TheS;
+ return TheS;
+}
+
+// CHECK-LABEL: define linkonce_odr %struct.S* @"\01?getS@@YAAAUS@@XZ"
+// CHECK: load i32* @"\01??_B?1??getS@@YAAAUS@@XZ@51"
+// CHECK: and i32 {{.*}}, 1
+// CHECK: icmp ne i32 {{.*}}, 0
+// CHECK: br i1
+// init:
+// CHECK: or i32 {{.*}}, 1
+// CHECK: store i32 {{.*}}, i32* @"\01??_B?1??getS@@YAAAUS@@XZ@51"
+// CHECK: call x86_thiscallcc %struct.S* @"\01??0S@@QAE@XZ"(%struct.S* @"\01?TheS@?1??getS@@YAAAUS@@XZ@4U2@A")
+// CHECK: call i32 @atexit(void ()* @"\01??__FTheS@?1??getS@@YAAAUS@@XZ@YAXXZ")
+// CHECK: br label
+// init.end:
+// CHECK: ret %struct.S* @"\01?TheS@?1??getS@@YAAAUS@@XZ@4U2@A"
+
void force_usage() {
+ UnreachableStatic();
+ getS();
(void)B<int>::foo; // (void) - force usage
}
-// CHECK: define internal void [[INIT_foo:@.*global_var.*]] [[NUW]]
+// CHECK: define internal void @"\01??__Efoo@?$B@H@@YAXXZ"() [[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: call i32 @atexit(void ()* @"\01??__Ffoo@?$B@H@@YAXXZ")
// CHECK: ret void
// CHECK: define linkonce_odr x86_thiscallcc %class.A* @"\01??0A@@QAE@XZ"
// CHECK: define linkonce_odr x86_thiscallcc void @"\01??1A@@QAE@XZ"
-// CHECK: define internal void [[FOO_DTOR]]
+// CHECK: define internal void @"\01??__Ffoo@?$B@H@@YAXXZ"
// CHECK: call x86_thiscallcc void @"\01??1A@@QAE@XZ"{{.*}}foo
// CHECK: ret void
// CHECK: define internal void @_GLOBAL__I_a() [[NUW]] {
-// CHECK: call void [[INIT_s]]
-// CHECK: call void [[INIT_foo]]
+// CHECK: call void @"\01??__Es@@YAXXZ"()
// CHECK: ret void
// CHECK: attributes [[NUW]] = { nounwind }
diff --git a/test/CodeGenCXX/microsoft-abi-structors-alias.cpp b/test/CodeGenCXX/microsoft-abi-structors-alias.cpp
new file mode 100644
index 0000000..d54520f
--- /dev/null
+++ b/test/CodeGenCXX/microsoft-abi-structors-alias.cpp
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 -fno-rtti -mconstructor-aliases | FileCheck %s
+
+namespace test1 {
+template <typename T> class A {
+ ~A() {}
+};
+template class A<char>;
+// CHECK: define weak_odr x86_thiscallcc void @"\01??1?$A@D@test1@@AAE@XZ"
+}
diff --git a/test/CodeGenCXX/microsoft-abi-structors.cpp b/test/CodeGenCXX/microsoft-abi-structors.cpp
index 864540d..c2f1395 100644
--- a/test/CodeGenCXX/microsoft-abi-structors.cpp
+++ b/test/CodeGenCXX/microsoft-abi-structors.cpp
@@ -1,27 +1,31 @@
-// RUN: %clang_cc1 -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 -fno-rtti > %t 2>&1
+// RUN: %clang_cc1 -emit-llvm %s -o - -mconstructor-aliases -cxx-abi microsoft -triple=i386-pc-win32 -fno-rtti > %t
// 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
+// vftables are emitted very late, so do another pass to try to keep the checks
+// in source order.
+// RUN: FileCheck --check-prefix DTORS %s < %t
+//
+// RUN: %clang_cc1 -emit-llvm %s -o - -mconstructor-aliases -cxx-abi microsoft -triple=x86_64-pc-win32 -fno-rtti | FileCheck --check-prefix DTORS-X64 %s
namespace basic {
class A {
public:
A() { }
- ~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: define linkonce_odr x86_thiscallcc %"class.basic::A"* @"\01??0A@basic@@QAE@XZ"(%"class.basic::A"* returned %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: }
+}
+A::~A() {
// 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"
@@ -34,33 +38,29 @@ struct 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: define x86_thiscallcc %"struct.basic::B"* @"\01??0B@basic@@QAE@XZ"(%"struct.basic::B"* returned %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: define linkonce_odr x86_thiscallcc void @"\01??_GC@basic@@UAEPAXI@Z"(%"struct.basic::C"* %this, i32 %should_call_delete)
+// DTORS: store i32 %should_call_delete, i32* %[[SHOULD_DELETE_VAR:[0-9a-z._]+]], align 4
+// DTORS: %[[SHOULD_DELETE_VALUE:[0-9a-z._]+]] = load i32* %[[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: %[[CONDITION:[0-9]+]] = icmp eq i32 %[[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: call void @"\01??3@YAXPAX@Z"(i8* %[[THIS_AS_VOID]])
// DTORS-NEXT: br label %[[CONTINUE_LABEL]]
//
// DTORS: [[CONTINUE_LABEL]]
// DTORS-NEXT: ret void
+
+// Check that we do the mangling correctly on x64.
+// DTORS-X64: @"\01??_GC@basic@@UEAAPEAXI@Z"
}
virtual void foo();
};
@@ -71,19 +71,19 @@ 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]]
+// CHECK: [[THIS_PTR:%[0-9]+]] = bitcast %"struct.basic::C"* {{.*}} to [2 x i8*]**
+// CHECK: store [2 x i8*]* @"\01??_7C@basic@@6B@", [2 x 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: %[[PVTABLE:.*]] = bitcast %"struct.basic::C"* %[[OBJ_PTR_VALUE]] to void (%"struct.basic::C"*, i32)***
+// CHECK-NEXT: %[[VTABLE:.*]] = load void (%"struct.basic::C"*, i32)*** %[[PVTABLE]]
+// CHECK-NEXT: %[[PVDTOR:.*]] = getelementptr inbounds void (%"struct.basic::C"*, i32)** %[[VTABLE]], i64 0
+// CHECK-NEXT: %[[VDTOR:.*]] = load void (%"struct.basic::C"*, i32)** %[[PVDTOR]]
+// CHECK-NEXT: call x86_thiscallcc void %[[VDTOR]](%"struct.basic::C"* %[[OBJ_PTR_VALUE]], i32 0)
// CHECK-NEXT: ret void
}
@@ -94,11 +94,11 @@ void call_deleting_dtor(C *obj_ptr) {
// 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-NEXT: %[[PVTABLE:.*]] = bitcast %"struct.basic::C"* %[[OBJ_PTR_VALUE]] to void (%"struct.basic::C"*, i32)***
+// CHECK-NEXT: %[[VTABLE:.*]] = load void (%"struct.basic::C"*, i32)*** %[[PVTABLE]]
+// CHECK-NEXT: %[[PVDTOR:.*]] = getelementptr inbounds void (%"struct.basic::C"*, i32)** %[[VTABLE]], i64 0
+// CHECK-NEXT: %[[VDTOR:.*]] = load void (%"struct.basic::C"*, i32)** %[[PVDTOR]]
+// CHECK-NEXT: call x86_thiscallcc void %[[VDTOR]](%"struct.basic::C"* %[[OBJ_PTR_VALUE]], i32 1)
// CHECK: ret void
}
@@ -119,8 +119,6 @@ struct D {
void use_D() { D c; }
-// DTORS: attributes [[NUW]] = { nounwind{{.*}} }
-
} // end namespace basic
@@ -136,7 +134,7 @@ struct B : A {
};
B::B() {
- // CHECK: define x86_thiscallcc %"struct.constructors::B"* @"\01??0B@constructors@@QAE@XZ"(%"struct.constructors::B"* %this)
+ // CHECK: define x86_thiscallcc %"struct.constructors::B"* @"\01??0B@constructors@@QAE@XZ"(%"struct.constructors::B"* returned %this)
// CHECK: call x86_thiscallcc %"struct.constructors::A"* @"\01??0A@constructors@@QAE@XZ"(%"struct.constructors::A"* %{{.*}})
// CHECK: ret
}
@@ -146,7 +144,7 @@ struct C : virtual A {
};
C::C() {
- // CHECK: define x86_thiscallcc %"struct.constructors::C"* @"\01??0C@constructors@@QAE@XZ"(%"struct.constructors::C"* %this, i32 %is_most_derived)
+ // CHECK: define x86_thiscallcc %"struct.constructors::C"* @"\01??0C@constructors@@QAE@XZ"(%"struct.constructors::C"* returned %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]]
@@ -154,12 +152,19 @@ C::C() {
// 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: %[[this_i8:.*]] = bitcast %"struct.constructors::C"* %{{.*}} to i8*
+ // CHECK-NEXT: %[[vbptr_off:.*]] = getelementptr inbounds i8* %[[this_i8]], i64 0
+ // CHECK-NEXT: %[[vbptr:.*]] = bitcast i8* %[[vbptr_off]] to [2 x i32]**
+ // CHECK-NEXT: store [2 x i32]* @"\01??_8C@constructors@@7B@", [2 x i32]** %[[vbptr]]
+ // CHECK-NEXT: bitcast %"struct.constructors::C"* %{{.*}} to i8*
+ // CHECK-NEXT: getelementptr inbounds i8* %{{.*}}, i64 4
+ // CHECK-NEXT: bitcast i8* %{{.*}} 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@"
+ // Class C does not define or override methods, so shouldn't change the vfptr.
+ // CHECK-NOT: @"\01??_7C@constructors@@6B@"
// CHECK: ret
}
@@ -175,14 +180,20 @@ struct D : C {
};
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: define x86_thiscallcc %"struct.constructors::D"* @"\01??0D@constructors@@QAE@XZ"(%"struct.constructors::D"* returned %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: %[[this_i8:.*]] = bitcast %"struct.constructors::D"* %{{.*}} to i8*
+ // CHECK-NEXT: %[[vbptr_off:.*]] = getelementptr inbounds i8* %[[this_i8]], i64 0
+ // CHECK-NEXT: %[[vbptr:.*]] = bitcast i8* %[[vbptr_off]] to [2 x i32]**
+ // CHECK-NEXT: store [2 x i32]* @"\01??_8D@constructors@@7B@", [2 x i32]** %[[vbptr]]
+ // CHECK-NEXT: bitcast %"struct.constructors::D"* %{{.*}} to i8*
+ // CHECK-NEXT: getelementptr inbounds i8* %{{.*}}, i64 4
+ // CHECK-NEXT: bitcast i8* %{{.*}} 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]]
//
@@ -196,14 +207,23 @@ struct E : virtual C {
};
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: define x86_thiscallcc %"struct.constructors::E"* @"\01??0E@constructors@@QAE@XZ"(%"struct.constructors::E"* returned %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: %[[this_i8:.*]] = bitcast %"struct.constructors::E"* %{{.*}} to i8*
+ // CHECK-NEXT: %[[offs:.*]] = getelementptr inbounds i8* %[[this_i8]], i64 0
+ // CHECK-NEXT: %[[vbptr_E:.*]] = bitcast i8* %[[offs]] to [3 x i32]**
+ // CHECK-NEXT: store [3 x i32]* @"\01??_8E@constructors@@7B01@@", [3 x i32]** %[[vbptr_E]]
+ // CHECK-NEXT: %[[offs:.*]] = getelementptr inbounds i8* %[[this_i8]], i64 4
+ // CHECK-NEXT: %[[vbptr_C:.*]] = bitcast i8* %[[offs]] to [2 x i32]**
+ // CHECK-NEXT: store [2 x i32]* @"\01??_8E@constructors@@7BC@1@@", [2 x i32]** %[[vbptr_C]]
+ // CHECK-NEXT: bitcast %"struct.constructors::E"* %{{.*}} to i8*
+ // CHECK-NEXT: getelementptr inbounds i8* %{{.*}}, i64 4
+ // CHECK-NEXT: bitcast i8* %{{.*}} 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]]
@@ -212,4 +232,70 @@ E::E() {
// CHECK: ret
}
+// PR16735 - even abstract classes should have a constructor emitted.
+struct F {
+ F();
+ virtual void f() = 0;
+};
+
+F::F() {}
+// CHECK: define x86_thiscallcc %"struct.constructors::F"* @"\01??0F@constructors@@QAE@XZ"
+
} // end namespace constructors
+
+namespace dtors {
+
+struct A {
+ ~A();
+};
+
+void call_nv_complete(A *a) {
+ a->~A();
+// CHECK: define void @"\01?call_nv_complete@dtors@@YAXPAUA@1@@Z"
+// CHECK: call x86_thiscallcc void @"\01??1A@dtors@@QAE@XZ"
+// CHECK: ret
+}
+
+// CHECK: declare x86_thiscallcc void @"\01??1A@dtors@@QAE@XZ"
+
+// Now try some virtual bases, where we need the complete dtor.
+
+struct B : virtual A { ~B(); };
+struct C : virtual A { ~C(); };
+struct D : B, C { ~D(); };
+
+void call_vbase_complete(D *d) {
+ d->~D();
+// CHECK: define void @"\01?call_vbase_complete@dtors@@YAXPAUD@1@@Z"
+// CHECK: call x86_thiscallcc void @"\01??_DD@dtors@@QAE@XZ"(%"struct.dtors::D"* %{{[^,]+}})
+// CHECK: ret
+}
+
+// The complete dtor should call the base dtors for D and the vbase A (once).
+// CHECK: define linkonce_odr x86_thiscallcc void @"\01??_DD@dtors@@QAE@XZ"
+// CHECK-NOT: call
+// CHECK: call x86_thiscallcc void @"\01??1D@dtors@@QAE@XZ"
+// CHECK-NOT: call
+// CHECK: call x86_thiscallcc void @"\01??1A@dtors@@QAE@XZ"
+// CHECK-NOT: call
+// CHECK: ret
+
+void destroy_d_complete() {
+ D d;
+// CHECK: define void @"\01?destroy_d_complete@dtors@@YAXXZ"
+// CHECK: call x86_thiscallcc void @"\01??_DD@dtors@@QAE@XZ"(%"struct.dtors::D"* %{{[^,]+}})
+// CHECK: ret
+}
+
+// FIXME: Clang manually inlines the deletion, so we don't get a call to the
+// deleting dtor (_G). The only way to call deleting dtors currently is through
+// a vftable.
+void call_nv_deleting_dtor(D *d) {
+ delete d;
+// CHECK: define void @"\01?call_nv_deleting_dtor@dtors@@YAXPAUD@1@@Z"
+// CHECK: call x86_thiscallcc void @"\01??_DD@dtors@@QAE@XZ"(%"struct.dtors::D"* %{{[^,]+}})
+// CHECK: call void @"\01??3@YAXPAX@Z"
+// CHECK: ret
+}
+
+}
diff --git a/test/CodeGenCXX/microsoft-abi-thunks.cpp b/test/CodeGenCXX/microsoft-abi-thunks.cpp
new file mode 100644
index 0000000..f1bc385
--- /dev/null
+++ b/test/CodeGenCXX/microsoft-abi-thunks.cpp
@@ -0,0 +1,154 @@
+// RUN: %clang_cc1 -fno-rtti -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 >%t 2>&1
+// RUN: FileCheck --check-prefix=MANGLING %s < %t
+// RUN: FileCheck --check-prefix=XMANGLING %s < %t
+// RUN: FileCheck --check-prefix=CODEGEN %s < %t
+// RUN: %clang_cc1 -fno-rtti -emit-llvm %s -o - -cxx-abi microsoft -triple=x86_64-pc-win32 2>&1 | FileCheck --check-prefix=MANGLING-X64 %s
+
+void foo(void *);
+
+struct A {
+ virtual ~A();
+ virtual void public_f();
+ // Make sure we don't emit unneeded thunks:
+ // XMANGLING-NOT: @"\01?public_f@A@@QAEXXZ"
+ protected:
+ virtual void protected_f();
+ private:
+ virtual void private_f();
+};
+
+struct B {
+ virtual ~B();
+ virtual void public_f();
+ protected:
+ virtual void protected_f();
+ private:
+ virtual void private_f();
+};
+
+
+struct C : A, B {
+ C();
+
+ virtual ~C();
+ // MANGLING-DAG: @"\01??1C@@UAE@XZ"
+ // MANGLING-DAG: @"\01??_GC@@UAEPAXI@Z"
+ // MANGLING-DAG: @"\01??_EC@@W3AEPAXI@Z"
+ // MANGLING-X64-DAG: @"\01??1C@@UEAA@XZ"
+ // MANGLING-X64-DAG: @"\01??_GC@@UEAAPEAXI@Z"
+ // MANGLING-X64-DAG: @"\01??_EC@@W7EAAPEAXI@Z"
+
+ // Overrides public_f() of two subobjects with distinct vfptrs, thus needs a thunk.
+ virtual void public_f();
+ // MANGLING-DAG: @"\01?public_f@C@@UAEXXZ"
+ // MANGLING-DAG: @"\01?public_f@C@@W3AEXXZ"
+ // MANGLING-X64-DAG: @"\01?public_f@C@@UEAAXXZ"
+ // MANGLING-X64-DAG: @"\01?public_f@C@@W7EAAXXZ"
+ protected:
+ virtual void protected_f();
+ // MANGLING-DAG: @"\01?protected_f@C@@MAEXXZ"
+ // MANGLING-DAG: @"\01?protected_f@C@@O3AEXXZ"
+ // MANGLING-X64-DAG: @"\01?protected_f@C@@MEAAXXZ"
+ // MANGLING-X64-DAG: @"\01?protected_f@C@@O7EAAXXZ"
+
+ private:
+ virtual void private_f();
+ // MANGLING-DAG: @"\01?private_f@C@@EAEXXZ"
+ // MANGLING-DAG: @"\01?private_f@C@@G3AEXXZ"
+ // MANGLING-X64-DAG: @"\01?private_f@C@@EEAAXXZ"
+ // MANGLING-X64-DAG: @"\01?private_f@C@@G7EAAXXZ"
+};
+
+C::C() {} // Emits vftable and forces thunk generation.
+
+// CODEGEN-LABEL: define weak x86_thiscallcc void @"\01??_EC@@W3AEPAXI@Z"(%struct.C* %this, i32 %should_call_delete)
+// CODEGEN: getelementptr i8* {{.*}}, i32 -4
+// FIXME: should actually call _EC, not _GC.
+// CODEGEN: call x86_thiscallcc void @"\01??_GC@@UAEPAXI@Z"
+// CODEGEN: ret
+
+// CODEGEN-LABEL: define weak x86_thiscallcc void @"\01?public_f@C@@W3AEXXZ"(%struct.C*
+// CODEGEN: getelementptr i8* {{.*}}, i32 -4
+// CODEGEN: call x86_thiscallcc void @"\01?public_f@C@@UAEXXZ"(%struct.C*
+// CODEGEN: ret
+
+void zoo(C* obj) {
+ delete obj;
+}
+
+struct D {
+ virtual B* goo();
+};
+
+struct E : D {
+ E();
+ virtual C* goo();
+ // MANGLING-DAG: @"\01?goo@E@@UAEPAUC@@XZ"
+ // MANGLING-DAG: @"\01?goo@E@@QAEPAUB@@XZ"
+ // MANGLING-X64-DAG: @"\01?goo@E@@UEAAPEAUC@@XZ"
+ // MANGLING-X64-DAG: @"\01?goo@E@@QEAAPEAUB@@XZ"
+};
+
+E::E() {} // Emits vftable and forces thunk generation.
+
+// CODEGEN-LABEL: define weak x86_thiscallcc %struct.C* @"\01?goo@E@@QAEPAUB@@XZ"
+// CODEGEN: call x86_thiscallcc %struct.C* @"\01?goo@E@@UAEPAUC@@XZ"
+// CODEGEN: getelementptr inbounds i8* {{.*}}, i32 4
+// CODEGEN: ret
+
+struct F : virtual A, virtual B {
+ virtual void own_method();
+ virtual ~F();
+};
+
+F f; // Just make sure we don't crash, e.g. mangling the complete dtor.
+
+struct G : C { };
+
+struct H : E {
+ virtual G* goo();
+ // MANGLING-DAG: @"\01?goo@H@@UAEPAUG@@XZ"
+ // MANGLING-DAG: @"\01?goo@H@@QAEPAUB@@XZ"
+ // MANGLING-DAG: @"\01?goo@H@@QAEPAUC@@XZ"
+ // MANGLING-X64-DAG: @"\01?goo@H@@UEAAPEAUG@@XZ"
+ // MANGLING-X64-DAG: @"\01?goo@H@@QEAAPEAUB@@XZ"
+ // MANGLING-X64-DAG: @"\01?goo@H@@QEAAPEAUC@@XZ"
+};
+
+H h;
+
+struct I : D {
+ I();
+ virtual F* goo();
+};
+
+I::I() {} // Emits vftable and forces thunk generation.
+
+// CODEGEN-LABEL: define weak x86_thiscallcc %struct.{{[BF]}}* @"\01?goo@I@@QAEPAUB@@XZ"
+// CODEGEN: %[[ORIG_RET:.*]] = call x86_thiscallcc %struct.F* @"\01?goo@I@@UAEPAUF@@XZ"
+// CODEGEN: %[[ORIG_RET_i8:.*]] = bitcast %struct.F* %[[ORIG_RET]] to i8*
+// CODEGEN: %[[VBPTR_i8:.*]] = getelementptr inbounds i8* %[[ORIG_RET_i8]], i32 4
+// CODEGEN: %[[VBPTR:.*]] = bitcast i8* %[[VBPTR_i8]] to i8**
+// CODEGEN: %[[VBTABLE:.*]] = load i8** %[[VBPTR]]
+// CODEGEN: %[[VBASE_OFFSET_PTR_i8:.*]] = getelementptr inbounds i8* %[[VBTABLE]], i32 8
+// CODEGEN: %[[VBASE_OFFSET_PTR:.*]] = bitcast i8* %[[VBASE_OFFSET_PTR_i8]] to i32*
+// CODEGEN: %[[VBASE_OFFSET:.*]] = load i32* %[[VBASE_OFFSET_PTR]]
+// CODEGEN: %[[RES_i8:.*]] = getelementptr inbounds i8* %[[VBPTR_i8]], i32 %[[VBASE_OFFSET]]
+// CODEGEN: %[[RES:.*]] = bitcast i8* %[[RES_i8]] to %struct.F*
+// CODEGEN: phi %struct.F* {{.*}} %[[RES]]
+// CODEGEN: ret %struct.{{[BF]}}*
+
+namespace CrashOnThunksForAttributedType {
+// We used to crash on this because the type of foo is an AttributedType, not
+// FunctionType, and we had to look through the sugar.
+struct A {
+ virtual void __stdcall foo();
+};
+struct B {
+ virtual void __stdcall foo();
+};
+struct C : A, B {
+ virtual void __stdcall foo();
+};
+C c;
+}
diff --git a/test/CodeGenCXX/microsoft-abi-vbtables.cpp b/test/CodeGenCXX/microsoft-abi-vbtables.cpp
new file mode 100644
index 0000000..6de556b
--- /dev/null
+++ b/test/CodeGenCXX/microsoft-abi-vbtables.cpp
@@ -0,0 +1,479 @@
+// RUN: %clang_cc1 %s -fno-rtti -cxx-abi microsoft -triple=i386-pc-win32 -emit-llvm -o - | FileCheck %s
+
+// See microsoft-abi-structors.cpp for constructor codegen tests.
+
+namespace Test1 {
+// Classic diamond, fully virtual.
+struct A { int a; };
+struct B : virtual A { int b; };
+struct C : virtual A { int c; };
+struct D : virtual B, virtual C { int d; };
+D d; // Force vbtable emission.
+
+// Layout should be:
+// D: vbptr D
+// int d
+// A: int a
+// B: vbptr B
+// int b
+// C: vbptr C
+// int c
+
+// CHECK-DAG: @"\01??_8D@Test1@@7B01@@" = linkonce_odr unnamed_addr constant [4 x i32] [i32 0, i32 8, i32 12, i32 20]
+// CHECK-DAG: @"\01??_8D@Test1@@7BB@1@@" = {{.*}} [2 x i32] [i32 0, i32 -4]
+// CHECK-DAG: @"\01??_8D@Test1@@7BC@1@@" = {{.*}} [2 x i32] [i32 0, i32 -12]
+// CHECK-DAG: @"\01??_8C@Test1@@7B@" = {{.*}} [2 x i32] [i32 0, i32 8]
+// CHECK-DAG: @"\01??_8B@Test1@@7B@" = {{.*}} [2 x i32] [i32 0, i32 8]
+}
+
+namespace Test2 {
+// Classic diamond, only A is virtual.
+struct A { int a; };
+struct B : virtual A { int b; };
+struct C : virtual A { int c; };
+struct D : B, C { int d; };
+D d; // Force vbtable emission.
+
+// Layout should be:
+// B: vbptr B
+// int b
+// C: vbptr C
+// int c
+// D: int d
+// A: int a
+
+// CHECK-DAG: @"\01??_8D@Test2@@7BB@1@@" = {{.*}} [2 x i32] [i32 0, i32 20]
+// CHECK-DAG: @"\01??_8D@Test2@@7BC@1@@" = {{.*}} [2 x i32] [i32 0, i32 12]
+// CHECK-DAG: @"\01??_8C@Test2@@7B@" = {{.*}} [2 x i32] [i32 0, i32 8]
+// CHECK-DAG: @"\01??_8B@Test2@@7B@" = {{.*}} [2 x i32] [i32 0, i32 8]
+}
+
+namespace Test3 {
+struct A { int a; };
+struct B { int b; };
+struct C : virtual A, virtual B { int c; };
+C c;
+
+// CHECK-DAG: @"\01??_8C@Test3@@7B@" = {{.*}} [3 x i32] [i32 0, i32 8, i32 12]
+}
+
+namespace Test4 {
+// Test reusing a vbptr from a non-virtual base.
+struct A { int a; };
+struct B : virtual A { int b; };
+struct C : B, virtual A { int c; };
+C c; // Force vbtable emission.
+
+// CHECK-DAG: @"\01??_8C@Test4@@7B@" = {{.*}} [2 x i32] [i32 0, i32 12]
+// CHECK-DAG: @"\01??_8B@Test4@@7B@" = {{.*}} [2 x i32] [i32 0, i32 8]
+}
+
+namespace Test5 {
+// Test multiple base subobjects of the same type when that type has a virtual
+// base.
+struct A { int a; };
+struct B : virtual A { int b; };
+struct C : B { int c; };
+struct D : B, C { int d; };
+D d; // Force vbtable emission.
+
+// CHECK-DAG: @"\01??_8D@Test5@@7BB@1@@"
+// CHECK-DAG: @"\01??_8D@Test5@@7BC@1@@"
+// CHECK-DAG: @"\01??_8C@Test5@@7B@"
+// CHECK-DAG: @"\01??_8B@Test5@@7B@"
+}
+
+namespace Test6 {
+// Test that we skip unneeded base path component names.
+struct A { int a; };
+struct B : virtual A { int b; };
+struct C : B { int c; };
+struct D : B, C { int d; };
+struct E : D { int e; };
+struct F : E, B, C { int f; };
+struct G : F, virtual E { int g; };
+G g;
+
+// CHECK-DAG: @"\01??_8G@Test6@@7BB@1@E@1@F@1@@" =
+// CHECK-DAG: @"\01??_8G@Test6@@7BC@1@E@1@F@1@@" =
+// CHECK-DAG: @"\01??_8G@Test6@@7BB@1@F@1@@" =
+// CHECK-DAG: @"\01??_8G@Test6@@7BC@1@F@1@@" =
+// CHECK-DAG: @"\01??_8G@Test6@@7BB@1@E@1@@" =
+// CHECK-DAG: @"\01??_8G@Test6@@7BC@1@E@1@@" =
+// CHECK-DAG: @"\01??_8F@Test6@@7BB@1@E@1@@" = {{.*}} [2 x i32] [i32 0, i32 52]
+// CHECK-DAG: @"\01??_8F@Test6@@7BC@1@E@1@@" = {{.*}} [2 x i32] [i32 0, i32 44]
+// CHECK-DAG: @"\01??_8F@Test6@@7BB@1@@" = {{.*}} [2 x i32] [i32 0, i32 24]
+// CHECK-DAG: @"\01??_8F@Test6@@7BC@1@@" = {{.*}} [2 x i32] [i32 0, i32 16]
+// CHECK-DAG: @"\01??_8C@Test6@@7B@" = {{.*}} [2 x i32] [i32 0, i32 12]
+// CHECK-DAG: @"\01??_8B@Test6@@7B@" = {{.*}} [2 x i32] [i32 0, i32 8]
+// CHECK-DAG: @"\01??_8E@Test6@@7BB@1@@" = {{.*}} [2 x i32] [i32 0, i32 28]
+// CHECK-DAG: @"\01??_8E@Test6@@7BC@1@@" = {{.*}} [2 x i32] [i32 0, i32 20]
+// CHECK-DAG: @"\01??_8D@Test6@@7BB@1@@" = {{.*}} [2 x i32] [i32 0, i32 24]
+// CHECK-DAG: @"\01??_8D@Test6@@7BC@1@@" = {{.*}} [2 x i32] [i32 0, i32 16]
+}
+
+namespace Test7 {
+// Test a non-virtual base which reuses the vbptr of another base.
+struct A { int a; };
+struct B { int b; };
+struct C { int c; };
+struct D : virtual A { int d; };
+struct E : B, D, virtual A, virtual C { int e; };
+E o;
+
+// CHECK-DAG: @"\01??_8E@Test7@@7B@" = {{.*}} [3 x i32] [i32 0, i32 12, i32 16]
+// CHECK-DAG: @"\01??_8D@Test7@@7B@" = {{.*}} [2 x i32] [i32 0, i32 8]
+}
+
+namespace Test8 {
+// Test a virtual base which reuses the vbptr of another base.
+struct A { int a; };
+struct B : virtual A { int b; };
+struct C : B { int c; };
+struct D : virtual C { int d; };
+D o;
+
+// CHECK-DAG: @"\01??_8D@Test8@@7B01@@" = {{.*}} [3 x i32] [i32 0, i32 8, i32 12]
+// CHECK-DAG: @"\01??_8D@Test8@@7BC@1@@" = {{.*}} [2 x i32] [i32 0, i32 -4]
+// CHECK-DAG: @"\01??_8C@Test8@@7B@" = {{.*}} [2 x i32] [i32 0, i32 12]
+// CHECK-DAG: @"\01??_8B@Test8@@7B@" = {{.*}} [2 x i32] [i32 0, i32 8]
+}
+
+namespace Test9 {
+// D has to add to B's vbtable because D has more morally virtual bases than B.
+// D then takes B's vbptr and the vbtable is named for D, not B.
+struct A { int a; };
+struct B : virtual A { int b; };
+struct C : virtual B { int c; };
+struct BB : B { int bb; }; // Indirection =/
+struct D : BB, C { int d; };
+struct E : virtual D { };
+E e;
+
+// CHECK-DAG: @"\01??_8E@Test9@@7B01@@" =
+// CHECK-DAG: @"\01??_8E@Test9@@7BD@1@@" =
+// CHECK-DAG: @"\01??_8E@Test9@@7BC@1@@" =
+// CHECK-DAG: @"\01??_8E@Test9@@7BB@1@@" =
+// CHECK-DAG: @"\01??_8D@Test9@@7B@" =
+// CHECK-DAG: @"\01??_8D@Test9@@7BC@1@@" =
+// CHECK-DAG: @"\01??_8D@Test9@@7BB@1@@" =
+// CHECK-DAG: @"\01??_8C@Test9@@7B01@@" =
+// CHECK-DAG: @"\01??_8C@Test9@@7BB@1@@" =
+// CHECK-DAG: @"\01??_8BB@Test9@@7B@" =
+// CHECK-DAG: @"\01??_8B@Test9@@7B@" =
+}
+
+namespace Test10 {
+struct A { int a; };
+struct B { int b; };
+struct C : virtual A { int c; };
+struct D : B, C { int d; };
+D d;
+
+// CHECK-DAG: @"\01??_8D@Test10@@7B@" =
+// CHECK-DAG: @"\01??_8C@Test10@@7B@" =
+
+}
+
+namespace Test11 {
+// Typical diamond with an extra single inheritance indirection for B and C.
+struct A { int a; };
+struct B : virtual A { int b; };
+struct C : virtual A { int c; };
+struct D : B { int d; };
+struct E : C { int e; };
+struct F : D, E { int f; };
+F f;
+
+// CHECK-DAG: @"\01??_8F@Test11@@7BD@1@@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 28]
+// CHECK-DAG: @"\01??_8F@Test11@@7BE@1@@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 16]
+// CHECK-DAG: @"\01??_8E@Test11@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 12]
+// CHECK-DAG: @"\01??_8C@Test11@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 8]
+// CHECK-DAG: @"\01??_8D@Test11@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 12]
+// CHECK-DAG: @"\01??_8B@Test11@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 8]
+
+}
+
+namespace Test12 {
+// Another vbptr inside a virtual base.
+struct A { int a; };
+struct B : virtual A { int b; };
+struct C : virtual B { int c; };
+struct D : C, B { int d; };
+struct E : D, C, B { int e; };
+E e;
+
+// CHECK-DAG: @"\01??_8E@Test12@@7BC@1@D@1@@" =
+// CHECK-DAG: @"\01??_8E@Test12@@7BB@1@D@1@@" =
+// CHECK-DAG: @"\01??_8E@Test12@@7BD@1@@" =
+// CHECK-DAG: @"\01??_8E@Test12@@7BC@1@@" =
+// CHECK-DAG: @"\01??_8E@Test12@@7BB@1@@" =
+// CHECK-DAG: @"\01??_8C@Test12@@7B01@@" =
+// CHECK-DAG: @"\01??_8C@Test12@@7BB@1@@" =
+// CHECK-DAG: @"\01??_8D@Test12@@7BC@1@@" =
+// CHECK-DAG: @"\01??_8D@Test12@@7BB@1@@" =
+// CHECK-DAG: @"\01??_8D@Test12@@7B@" =
+// CHECK-DAG: @"\01??_8B@Test12@@7B@" =
+}
+
+namespace Test13 {
+struct A { int a; };
+struct B : virtual A { int b; };
+struct C : virtual B { int c; };
+struct D : virtual C { int d; };
+struct E : D, C, B { int e; };
+E e;
+
+// CHECK-DAG: @"\01??_8E@Test13@@7BD@1@@" =
+// CHECK-DAG: @"\01??_8E@Test13@@7BC@1@D@1@@" =
+// CHECK-DAG: @"\01??_8E@Test13@@7BB@1@D@1@@" =
+// CHECK-DAG: @"\01??_8E@Test13@@7BC@1@@" =
+// CHECK-DAG: @"\01??_8E@Test13@@7BB@1@@" =
+// CHECK-DAG: @"\01??_8D@Test13@@7B@" =
+// CHECK-DAG: @"\01??_8D@Test13@@7BC@1@@" =
+// CHECK-DAG: @"\01??_8D@Test13@@7BB@1@@" =
+// CHECK-DAG: @"\01??_8C@Test13@@7B01@@" =
+// CHECK-DAG: @"\01??_8C@Test13@@7BB@1@@" =
+// CHECK-DAG: @"\01??_8B@Test13@@7B@" =
+}
+
+namespace Test14 {
+struct A { int a; };
+struct B : virtual A { int b; };
+struct C : virtual B { int c; };
+struct D : virtual C { int d; };
+struct E : D, virtual C, virtual B { int e; };
+E e;
+
+// CHECK-DAG: @"\01??_8E@Test14@@7B@" =
+// CHECK-DAG: @"\01??_8E@Test14@@7BC@1@@" =
+// CHECK-DAG: @"\01??_8E@Test14@@7BB@1@@" =
+// CHECK-DAG: @"\01??_8D@Test14@@7B@" =
+// CHECK-DAG: @"\01??_8D@Test14@@7BC@1@@" =
+// CHECK-DAG: @"\01??_8D@Test14@@7BB@1@@" =
+// CHECK-DAG: @"\01??_8C@Test14@@7B01@@" =
+// CHECK-DAG: @"\01??_8C@Test14@@7BB@1@@" =
+// CHECK-DAG: @"\01??_8B@Test14@@7B@" =
+}
+
+namespace Test15 {
+struct A { int a; };
+struct B : virtual A { int b; };
+struct C : virtual A { int c; };
+struct D : virtual B { int d; };
+struct E : D, C, B { int e; };
+E e;
+
+// CHECK-DAG: @"\01??_8E@Test15@@7BD@1@@" =
+// CHECK-DAG: @"\01??_8E@Test15@@7BB@1@D@1@@" =
+// CHECK-DAG: @"\01??_8E@Test15@@7BC@1@@" =
+// CHECK-DAG: @"\01??_8E@Test15@@7BB@1@@" =
+// CHECK-DAG: @"\01??_8C@Test15@@7B@" =
+// CHECK-DAG: @"\01??_8D@Test15@@7B01@@" =
+// CHECK-DAG: @"\01??_8D@Test15@@7BB@1@@" =
+// CHECK-DAG: @"\01??_8B@Test15@@7B@" =
+}
+
+namespace Test16 {
+struct A { int a; };
+struct B : virtual A { int b; };
+struct C : virtual B { int c; }; // ambig
+struct D : virtual C { int d; };
+struct E : virtual D { int e; }; // ambig
+struct F : E, D, C, B { int f; }; // ambig
+F f;
+
+// CHECK-DAG: @"\01??_8F@Test16@@7BE@1@@" =
+// CHECK-DAG: @"\01??_8F@Test16@@7BD@1@E@1@@" =
+// CHECK-DAG: @"\01??_8F@Test16@@7BC@1@E@1@@" =
+// CHECK-DAG: @"\01??_8F@Test16@@7BB@1@E@1@@" =
+// CHECK-DAG: @"\01??_8F@Test16@@7BD@1@@" =
+// CHECK-DAG: @"\01??_8F@Test16@@7BC@1@@" =
+// CHECK-DAG: @"\01??_8F@Test16@@7BB@1@@" =
+// CHECK-DAG: @"\01??_8E@Test16@@7B01@@" =
+// CHECK-DAG: @"\01??_8E@Test16@@7BD@1@@" =
+// CHECK-DAG: @"\01??_8E@Test16@@7BC@1@@" =
+// CHECK-DAG: @"\01??_8E@Test16@@7BB@1@@" =
+// CHECK-DAG: @"\01??_8D@Test16@@7B@" =
+// CHECK-DAG: @"\01??_8D@Test16@@7BC@1@@" =
+// CHECK-DAG: @"\01??_8D@Test16@@7BB@1@@" =
+// CHECK-DAG: @"\01??_8C@Test16@@7B01@@" =
+// CHECK-DAG: @"\01??_8C@Test16@@7BB@1@@" =
+// CHECK-DAG: @"\01??_8B@Test16@@7B@" =
+}
+
+namespace Test17 {
+// This test case has an interesting alternating pattern of using "vbtable of B"
+// and "vbtable of C for C". This may be the key to the underlying algorithm.
+struct A { int a; };
+struct B : virtual A { int b; };
+struct C : virtual B { int c; }; // ambig
+struct D : virtual C { int d; };
+struct E : virtual D { int e; }; // ambig
+struct F : virtual E { int f; };
+struct G : virtual F { int g; }; // ambig
+struct H : virtual G { int h; };
+struct I : virtual H { int i; }; // ambig
+struct J : virtual I { int j; };
+struct K : virtual J { int k; }; // ambig
+K k;
+
+// CHECK-DAG: @"\01??_8K@Test17@@7B01@@" =
+// CHECK-DAG: @"\01??_8J@Test17@@7B@" =
+// CHECK-DAG: @"\01??_8I@Test17@@7B01@@" =
+// CHECK-DAG: @"\01??_8H@Test17@@7B@" =
+// CHECK-DAG: @"\01??_8G@Test17@@7B01@@" =
+// CHECK-DAG: @"\01??_8F@Test17@@7B@" =
+// CHECK-DAG: @"\01??_8E@Test17@@7B01@@" =
+// CHECK-DAG: @"\01??_8D@Test17@@7B@" =
+// CHECK-DAG: @"\01??_8C@Test17@@7B01@@" =
+// CHECK-DAG: @"\01??_8B@Test17@@7B@" =
+}
+
+namespace Test18 {
+struct A { int a; };
+struct B : virtual A { int b; };
+struct C : B { int c; };
+struct D : C, B { int d; };
+struct E : D, C, B { int e; };
+E e;
+
+// CHECK-DAG: @"\01??_8E@Test18@@7BC@1@D@1@@" =
+// CHECK-DAG: @"\01??_8E@Test18@@7BB@1@D@1@@" =
+// CHECK-DAG: @"\01??_8E@Test18@@7BC@1@@" =
+// CHECK-DAG: @"\01??_8E@Test18@@7BB@1@@" =
+// CHECK-DAG: @"\01??_8B@Test18@@7B@" =
+// CHECK-DAG: @"\01??_8C@Test18@@7B@" =
+// CHECK-DAG: @"\01??_8D@Test18@@7BC@1@@" =
+// CHECK-DAG: @"\01??_8D@Test18@@7BB@1@@" =
+}
+
+namespace Test19 {
+struct A { int a; };
+struct B : virtual A { int b; };
+struct C : virtual B { int c; };
+struct D : virtual C, virtual B { int d; };
+struct E : virtual D, virtual C, virtual B { int e; };
+E e;
+
+// CHECK-DAG: @"\01??_8E@Test19@@7B01@@" =
+// CHECK-DAG: @"\01??_8E@Test19@@7BD@1@@" =
+// CHECK-DAG: @"\01??_8E@Test19@@7BC@1@@" =
+// CHECK-DAG: @"\01??_8E@Test19@@7BB@1@@" =
+// CHECK-DAG: @"\01??_8D@Test19@@7B@" =
+// CHECK-DAG: @"\01??_8D@Test19@@7BC@1@@" =
+// CHECK-DAG: @"\01??_8D@Test19@@7BB@1@@" =
+// CHECK-DAG: @"\01??_8C@Test19@@7B01@@" =
+// CHECK-DAG: @"\01??_8C@Test19@@7BB@1@@" =
+// CHECK-DAG: @"\01??_8B@Test19@@7B@" =
+}
+
+namespace Test20 {
+// E has no direct vbases, but it adds to C's vbtable anyway.
+struct A { int a; };
+struct B { int b; };
+struct C : virtual A { int c; };
+struct D : virtual B { int d; };
+struct E : C, D { int e; };
+E f;
+
+// CHECK-DAG: @"\01??_8E@Test20@@7BC@1@@" = linkonce_odr unnamed_addr constant [3 x i32] [i32 0, i32 20, i32 24]
+// CHECK-DAG: @"\01??_8E@Test20@@7BD@1@@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 16]
+// CHECK-DAG: @"\01??_8D@Test20@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 8]
+// CHECK-DAG: @"\01??_8C@Test20@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 8]
+}
+
+namespace Test21 {
+struct A { int a; };
+struct B : virtual A { int b; };
+struct C : B { int c; };
+struct D : B { int d; };
+struct E : C, D { int e; };
+struct F : virtual E { int f; };
+struct G : E { int g; };
+struct H : F, G { int h; };
+H h;
+
+// CHECK-DAG: @"\01??_8H@Test21@@7B@" =
+// CHECK-DAG: @"\01??_8H@Test21@@7BC@1@F@1@@" =
+// CHECK-DAG: @"\01??_8H@Test21@@7BD@1@F@1@@" =
+// CHECK-DAG: @"\01??_8H@Test21@@7BC@1@G@1@@" =
+// CHECK-DAG: @"\01??_8H@Test21@@7BD@1@G@1@@" =
+// CHECK-DAG: @"\01??_8G@Test21@@7BC@1@@" =
+// CHECK-DAG: @"\01??_8G@Test21@@7BD@1@@" =
+// CHECK-DAG: @"\01??_8F@Test21@@7B@" =
+// CHECK-DAG: @"\01??_8F@Test21@@7BC@1@@" =
+// CHECK-DAG: @"\01??_8F@Test21@@7BD@1@@" =
+// CHECK-DAG: @"\01??_8E@Test21@@7BC@1@@" =
+// CHECK-DAG: @"\01??_8E@Test21@@7BD@1@@" =
+// CHECK-DAG: @"\01??_8D@Test21@@7B@" =
+// CHECK-DAG: @"\01??_8B@Test21@@7B@" =
+// CHECK-DAG: @"\01??_8C@Test21@@7B@" =
+}
+
+namespace Test22 {
+struct A { int a; };
+struct B : virtual A { int b; };
+struct C { int c; };
+struct D : B, virtual C { int d; };
+D d;
+
+// CHECK-DAG: @"\01??_8D@Test22@@7B@" = linkonce_odr unnamed_addr constant [3 x i32] [i32 0, i32 12, i32 16]
+// CHECK-DAG: @"\01??_8B@Test22@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 8]
+}
+
+namespace Test23 {
+struct A { int a; };
+struct B : virtual A { int b; };
+struct C { int c; };
+// Note the unusual order of bases. It forces C to be laid out before A.
+struct D : virtual C, B { int d; };
+D d;
+
+// CHECK-DAG: @"\01??_8D@Test23@@7B@" = linkonce_odr unnamed_addr constant [3 x i32] [i32 0, i32 16, i32 12]
+// CHECK-DAG: @"\01??_8B@Test23@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 8]
+}
+
+namespace Test24 {
+struct A { int a; };
+struct B : virtual A { int b; };
+struct C { int c; };
+struct D : virtual C, B {
+ virtual void f(); // Issues a vfptr, but the vbptr is still shared with B.
+ int d;
+};
+D d;
+
+// CHECK-DAG: @"\01??_8D@Test24@@7B@" = linkonce_odr unnamed_addr constant [3 x i32] [i32 0, i32 16, i32 12]
+// CHECK-DAG: @"\01??_8B@Test24@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 8]
+}
+
+namespace Test25 {
+struct A { int a; };
+struct B : virtual A {
+ virtual void f(); // Issues a vfptr.
+ int b;
+};
+struct C { int c; };
+struct D : virtual C, B { int d; };
+D d;
+
+// CHECK-DAG: @"\01??_8D@Test25@@7B@" = linkonce_odr unnamed_addr constant [3 x i32] [i32 -4, i32 16, i32 12]
+// CHECK-DAG: @"\01??_8B@Test25@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 -4, i32 8]
+}
+
+namespace Test26 {
+struct A { int a; };
+struct B { int b; };
+struct C { int c; };
+struct D : virtual A { int d; };
+struct E : virtual B {
+ virtual void foo(); // Issues a vfptr.
+ int e;
+};
+struct F: virtual C, D, E { int f; };
+F f;
+// F reuses the D's vbptr, even though D is laid out after E.
+// CHECK-DAG: @"\01??_8F@Test26@@7BD@1@@" = linkonce_odr unnamed_addr constant [4 x i32] [i32 0, i32 16, i32 12, i32 20]
+// CHECK-DAG: @"\01??_8F@Test26@@7BE@1@@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 -4, i32 28]
+}
diff --git a/test/CodeGenCXX/microsoft-abi-virtual-inheritance-vtordisps.cpp b/test/CodeGenCXX/microsoft-abi-virtual-inheritance-vtordisps.cpp
new file mode 100644
index 0000000..8e23ade
--- /dev/null
+++ b/test/CodeGenCXX/microsoft-abi-virtual-inheritance-vtordisps.cpp
@@ -0,0 +1,83 @@
+// RUN: %clang_cc1 %s -fno-rtti -cxx-abi microsoft -triple=i386-pc-win32 -emit-llvm -o - | FileCheck %s
+
+// For now, just make sure x86_64 doesn't crash.
+// RUN: %clang_cc1 %s -fno-rtti -cxx-abi microsoft -triple=x86_64-pc-win32 -emit-llvm -o %t
+
+struct A {
+ virtual void f();
+};
+
+struct B {
+ virtual void f();
+};
+
+struct C : A, B {};
+
+struct D : virtual C {
+ D();
+ ~D();
+ virtual void f();
+ void g();
+ int xxx;
+};
+
+D::D() {} // Forces vftable emission.
+
+// CHECK-LABEL: define weak x86_thiscallcc void @"\01?f@D@@$4PPPPPPPM@A@AEXXZ"
+// CHECK: %[[ECX:.*]] = load %struct.D** %{{.*}}
+// CHECK: %[[ECX_i8:.*]] = bitcast %struct.D* %[[ECX]] to i8*
+// CHECK: %[[VTORDISP_PTR_i8:.*]] = getelementptr i8* %[[ECX_i8]], i32 -4
+// CHECK: %[[VTORDISP_PTR:.*]] = bitcast i8* %[[VTORDISP_PTR_i8]] to i32*
+// CHECK: %[[VTORDISP:.*]] = load i32* %[[VTORDISP_PTR]]
+// CHECK: %[[VTORDISP_NEG:.*]] = sub i32 0, %[[VTORDISP]]
+// CHECK: %[[ADJUSTED_i8:.*]] = getelementptr i8* %[[ECX_i8]], i32 %[[VTORDISP_NEG]]
+// CHECK: call x86_thiscallcc void @"\01?f@D@@UAEXXZ"(i8* %[[ADJUSTED_i8]])
+// CHECK: ret void
+
+// CHECK-LABEL: define weak x86_thiscallcc void @"\01?f@D@@$4PPPPPPPI@3AEXXZ"
+// CHECK: %[[ECX:.*]] = load %struct.D** %{{.*}}
+// CHECK: %[[ECX_i8:.*]] = bitcast %struct.D* %[[ECX]] to i8*
+// CHECK: %[[VTORDISP_PTR_i8:.*]] = getelementptr i8* %[[ECX_i8]], i32 -8
+// CHECK: %[[VTORDISP_PTR:.*]] = bitcast i8* %[[VTORDISP_PTR_i8]] to i32*
+// CHECK: %[[VTORDISP:.*]] = load i32* %[[VTORDISP_PTR]]
+// CHECK: %[[VTORDISP_NEG:.*]] = sub i32 0, %[[VTORDISP]]
+// CHECK: %[[VTORDISP_ADJUSTED_i8:.*]] = getelementptr i8* %[[ECX_i8]], i32 %[[VTORDISP_NEG]]
+// CHECK: %[[ADJUSTED_i8:.*]] = getelementptr i8* %[[VTORDISP_ADJUSTED_i8]], i32 -4
+// CHECK: call x86_thiscallcc void @"\01?f@D@@UAEXXZ"(i8* %[[ADJUSTED_i8]])
+// CHECK: ret void
+
+struct E : virtual A {
+ virtual void f();
+ ~E();
+};
+
+struct F {
+ virtual void z();
+};
+
+struct G : virtual F, virtual E {
+ int ggg;
+ G();
+ ~G();
+};
+
+G::G() {} // Forces vftable emission.
+
+// CHECK-LABEL: define weak x86_thiscallcc void @"\01?f@E@@$R4BA@M@PPPPPPPM@7AEXXZ"(i8*)
+// CHECK: %[[ECX:.*]] = load %struct.E** %{{.*}}
+// CHECK: %[[ECX_i8:.*]] = bitcast %struct.E* %[[ECX]] to i8*
+// CHECK: %[[VTORDISP_PTR_i8:.*]] = getelementptr i8* %[[ECX_i8]], i32 -4
+// CHECK: %[[VTORDISP_PTR:.*]] = bitcast i8* %[[VTORDISP_PTR_i8]] to i32*
+// CHECK: %[[VTORDISP:.*]] = load i32* %[[VTORDISP_PTR]]
+// CHECK: %[[VTORDISP_NEG:.*]] = sub i32 0, %[[VTORDISP]]
+// CHECK: %[[VTORDISP_ADJUSTED_i8:.*]] = getelementptr i8* %[[ECX_i8]], i32 %[[VTORDISP_NEG]]
+// CHECK: %[[VBPTR_i8:.*]] = getelementptr inbounds i8* %[[VTORDISP_ADJUSTED_i8]], i32 -16
+// CHECK: %[[VBPTR:.*]] = bitcast i8* %[[VBPTR_i8]] to i8**
+// CHECK: %[[VBTABLE:.*]] = load i8** %[[VBPTR]]
+// CHECK: %[[VBOFFSET_PTR_i8:.*]] = getelementptr inbounds i8* %[[VBTABLE]], i32 12
+// CHECK: %[[VBOFFSET_PTR:.*]] = bitcast i8* %[[VBOFFSET_PTR_i8]] to i32*
+// CHECK: %[[VBASE_OFFSET:.*]] = load i32* %[[VBOFFSET_PTR]]
+// CHECK: %[[VBASE:.*]] = getelementptr inbounds i8* %[[VBPTR_i8]], i32 %[[VBASE_OFFSET]]
+// CHECK: %[[ARG_i8:.*]] = getelementptr i8* %[[VBASE]], i32 8
+// CHECK: call x86_thiscallcc void @"\01?f@E@@UAEXXZ"(i8* %[[ARG_i8]])
+// CHECK: ret void
diff --git a/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp b/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp
new file mode 100644
index 0000000..7c223ca
--- /dev/null
+++ b/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp
@@ -0,0 +1,314 @@
+// RUN: %clang_cc1 %s -fno-rtti -cxx-abi microsoft -triple=i386-pc-win32 -emit-llvm -o %t
+// RUN: FileCheck %s < %t
+// RUN: FileCheck --check-prefix=CHECK2 %s < %t
+
+// For now, just make sure x86_64 doesn't crash.
+// RUN: %clang_cc1 %s -fno-rtti -cxx-abi microsoft -triple=x86_64-pc-win32 -emit-llvm -o %t
+
+struct VBase {
+ virtual ~VBase();
+ virtual void foo();
+ virtual void bar();
+ int field;
+};
+
+struct B : virtual VBase {
+ B();
+ virtual ~B();
+ virtual void foo();
+ virtual void bar();
+};
+
+B::B() {
+ // CHECK-LABEL: define x86_thiscallcc %struct.B* @"\01??0B@@QAE@XZ"
+ // CHECK: %[[THIS:.*]] = load %struct.B**
+ // CHECK: br i1 %{{.*}}, label %[[INIT_VBASES:.*]], label %[[SKIP_VBASES:.*]]
+
+ // Don't check the INIT_VBASES case as it's covered by the ctor tests.
+
+ // CHECK: %[[SKIP_VBASES]]
+ // CHECK: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
+ // CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8* %[[THIS_i8]], i32 0
+ // ...
+ // CHECK: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
+ // CHECK: %[[VFPTR_i8:.*]] = getelementptr inbounds i8* %[[THIS_i8]], i32 %{{.*}}
+ // CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to [3 x i8*]**
+ // CHECK: store [3 x i8*]* @"\01??_7B@@6B@", [3 x i8*]** %[[VFPTR]]
+
+ // Initialize vtorDisp:
+ // CHECK: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
+ // CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8* %[[THIS_i8]], i32 0
+ // ...
+ // CHECK: %[[VBASE_OFFSET:.*]] = add nsw i32 0, %{{.*}}
+ // CHECK: %[[VTORDISP_VAL:.*]] = sub i32 %[[VBASE_OFFSET]], 8
+ // CHECK: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
+ // CHECK: %[[VBASE_i8:.*]] = getelementptr inbounds i8* %[[THIS_i8]], i32 %[[VBASE_OFFSET]]
+ // CHECK: %[[VTORDISP_i8:.*]] = getelementptr i8* %[[VBASE_i8]], i32 -4
+ // CHECK: %[[VTORDISP_PTR:.*]] = bitcast i8* %[[VTORDISP_i8]] to i32*
+ // CHECK: store i32 %[[VTORDISP_VAL]], i32* %[[VTORDISP_PTR]]
+
+ // CHECK: ret
+}
+
+B::~B() {
+ // CHECK-LABEL: define x86_thiscallcc void @"\01??1B@@UAE@XZ"
+ // Adjust the this parameter:
+ // CHECK: %[[THIS_PARAM_i8:.*]] = bitcast %struct.B* {{.*}} to i8*
+ // CHECK: %[[THIS_i8:.*]] = getelementptr inbounds i8* %[[THIS_PARAM_i8]], i32 -8
+ // CHECK: %[[THIS:.*]] = bitcast i8* %[[THIS_i8]] to %struct.B*
+ // CHECK: store %struct.B* %[[THIS]], %struct.B** %[[THIS_ADDR:.*]], align 4
+ // CHECK: %[[THIS:.*]] = load %struct.B** %[[THIS_ADDR]]
+
+ // Restore the vfptr that could have been changed by a subclass.
+ // CHECK: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
+ // CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8* %[[THIS_i8]], i32 0
+ // ...
+ // CHECK: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
+ // CHECK: %[[VFPTR_i8:.*]] = getelementptr inbounds i8* %[[THIS_i8]], i32 %{{.*}}
+ // CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to [3 x i8*]**
+ // CHECK: store [3 x i8*]* @"\01??_7B@@6B@", [3 x i8*]** %[[VFPTR]]
+
+ // Initialize vtorDisp:
+ // CHECK: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
+ // CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8* %[[THIS_i8]], i32 0
+ // ...
+ // CHECK: %[[VBASE_OFFSET:.*]] = add nsw i32 0, %{{.*}}
+ // CHECK: %[[VTORDISP_VAL:.*]] = sub i32 %[[VBASE_OFFSET]], 8
+ // CHECK: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
+ // CHECK: %[[VBASE_i8:.*]] = getelementptr inbounds i8* %[[THIS_i8]], i32 %[[VBASE_OFFSET]]
+ // CHECK: %[[VTORDISP_i8:.*]] = getelementptr i8* %[[VBASE_i8]], i32 -4
+ // CHECK: %[[VTORDISP_PTR:.*]] = bitcast i8* %[[VTORDISP_i8]] to i32*
+ // CHECK: store i32 %[[VTORDISP_VAL]], i32* %[[VTORDISP_PTR]]
+
+ foo(); // Avoid the "trivial destructor" optimization.
+
+ // CHECK: ret
+
+ // CHECK2-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_DB@@UAE@XZ"(%struct.B*
+ // CHECK2: %[[THIS:.*]] = load %struct.B** {{.*}}
+ // CHECK2: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
+ // CHECK2: %[[B_i8:.*]] = getelementptr i8* %[[THIS_i8]], i32 8
+ // CHECK2: %[[B:.*]] = bitcast i8* %[[B_i8]] to %struct.B*
+ // CHECK2: call x86_thiscallcc void @"\01??1B@@UAE@XZ"(%struct.B* %[[B]])
+ // CHECK2: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
+ // CHECK2: %[[VBASE_i8:.*]] = getelementptr inbounds i8* %[[THIS_i8]], i64 8
+ // CHECK2: %[[VBASE:.*]] = bitcast i8* %[[VBASE_i8]] to %struct.VBase*
+ // CHECK2: call x86_thiscallcc void @"\01??1VBase@@UAE@XZ"(%struct.VBase* %[[VBASE]])
+ // CHECK2: ret
+
+ // CHECK2-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_GB@@UAEPAXI@Z"
+ // CHECK2: %[[THIS_PARAM_i8:.*]] = bitcast %struct.B* {{.*}} to i8*
+ // CHECK2: %[[THIS_i8:.*]] = getelementptr inbounds i8* %[[THIS_PARAM_i8:.*]], i32 -8
+ // CHECK2: %[[THIS:.*]] = bitcast i8* %[[THIS_i8]] to %struct.B*
+ // CHECK2: store %struct.B* %[[THIS]], %struct.B** %[[THIS_ADDR:.*]], align 4
+ // CHECK2: %[[THIS:.*]] = load %struct.B** %[[THIS_ADDR]]
+ // CHECK2: call x86_thiscallcc void @"\01??_DB@@UAE@XZ"(%struct.B* %[[THIS]])
+ // ...
+ // CHECK2: ret
+}
+
+void B::foo() {
+// CHECK-LABEL: define x86_thiscallcc void @"\01?foo@B@@UAEXXZ"(i8*
+//
+// B::foo gets 'this' cast to VBase* in ECX (i.e. this+8) so we
+// need to adjust 'this' before use.
+//
+// CHECK: %[[THIS_ADDR:.*]] = alloca %struct.B*, align 4
+// CHECK: %[[THIS_i8:.*]] = getelementptr inbounds i8* %[[ECX:.*]], i32 -8
+// CHECK: %[[THIS:.*]] = bitcast i8* %[[THIS_i8]] to %struct.B*
+// CHECK: store %struct.B* %[[THIS]], %struct.B** %[[THIS_ADDR]], align 4
+
+ field = 42;
+// CHECK: %[[THIS:.*]] = load %struct.B** %[[THIS_ADDR]]
+// CHECK: %[[THIS8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
+// CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8* %[[THIS8]], i32 0
+// CHECK: %[[VBPTR8:.*]] = bitcast i8* %[[VBPTR]] to i8**
+// CHECK: %[[VBTABLE:.*]] = load i8** %[[VBPTR8]]
+// CHECK: %[[VBENTRY8:.*]] = getelementptr inbounds i8* %[[VBTABLE]], i32 4
+// CHECK: %[[VBENTRY:.*]] = bitcast i8* %[[VBENTRY8]] to i32*
+// CHECK: %[[VBOFFSET32:.*]] = load i32* %[[VBENTRY]]
+// CHECK: %[[VBOFFSET:.*]] = add nsw i32 0, %[[VBOFFSET32]]
+// CHECK: %[[THIS8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
+// CHECK: %[[VBASE_i8:.*]] = getelementptr inbounds i8* %[[THIS8]], i32 %[[VBOFFSET]]
+// CHECK: %[[VBASE:.*]] = bitcast i8* %[[VBASE_i8]] to %struct.VBase*
+// CHECK: %[[FIELD:.*]] = getelementptr inbounds %struct.VBase* %[[VBASE]], i32 0, i32 1
+// CHECK: store i32 42, i32* %[[FIELD]], align 4
+//
+// CHECK: ret void
+}
+
+void call_vbase_bar(B *obj) {
+// CHECK-LABEL: define void @"\01?call_vbase_bar@@YAXPAUB@@@Z"(%struct.B* %obj)
+// CHECK: %[[OBJ:.*]] = load %struct.B
+
+ obj->bar();
+// When calling a vbase's virtual method, one needs to adjust 'this'
+// at the caller site.
+//
+// CHECK: %[[OBJ_i8:.*]] = bitcast %struct.B* %[[OBJ]] to i8*
+// CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 0
+// CHECK: %[[VBPTR8:.*]] = bitcast i8* %[[VBPTR]] to i8**
+// CHECK: %[[VBTABLE:.*]] = load i8** %[[VBPTR8]]
+// CHECK: %[[VBENTRY8:.*]] = getelementptr inbounds i8* %[[VBTABLE]], i32 4
+// CHECK: %[[VBENTRY:.*]] = bitcast i8* %[[VBENTRY8]] to i32*
+// CHECK: %[[VBOFFSET32:.*]] = load i32* %[[VBENTRY]]
+// CHECK: %[[VBOFFSET:.*]] = add nsw i32 0, %[[VBOFFSET32]]
+// CHECK: %[[VBASE_i8:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 %[[VBOFFSET]]
+// CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VBASE_i8]] to void (i8*)***
+// CHECK: %[[VFTABLE:.*]] = load void (i8*)*** %[[VFPTR]]
+// CHECK: %[[VFUN:.*]] = getelementptr inbounds void (i8*)** %[[VFTABLE]], i64 2
+// CHECK: %[[VFUN_VALUE:.*]] = load void (i8*)** %[[VFUN]]
+//
+// CHECK: %[[OBJ_i8:.*]] = bitcast %struct.B* %[[OBJ]] to i8*
+// CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 0
+// CHECK: %[[VBPTR8:.*]] = bitcast i8* %[[VBPTR]] to i8**
+// CHECK: %[[VBTABLE:.*]] = load i8** %[[VBPTR8]]
+// CHECK: %[[VBENTRY8:.*]] = getelementptr inbounds i8* %[[VBTABLE]], i32 4
+// CHECK: %[[VBENTRY:.*]] = bitcast i8* %[[VBENTRY8]] to i32*
+// CHECK: %[[VBOFFSET32:.*]] = load i32* %[[VBENTRY]]
+// CHECK: %[[VBOFFSET:.*]] = add nsw i32 0, %[[VBOFFSET32]]
+// CHECK: %[[VBASE:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 %[[VBOFFSET]]
+//
+// CHECK: call x86_thiscallcc void %[[VFUN_VALUE]](i8* %[[VBASE]])
+//
+// CHECK: ret void
+}
+
+void delete_B(B *obj) {
+// CHECK-LABEL: define void @"\01?delete_B@@YAXPAUB@@@Z"(%struct.B* %obj)
+// CHECK: %[[OBJ:.*]] = load %struct.B
+
+ delete obj;
+// CHECK: %[[OBJ_i8:.*]] = bitcast %struct.B* %[[OBJ]] to i8*
+// CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 0
+// CHECK: %[[VBPTR8:.*]] = bitcast i8* %[[VBPTR]] to i8**
+// CHECK: %[[VBTABLE:.*]] = load i8** %[[VBPTR8]]
+// CHECK: %[[VBENTRY8:.*]] = getelementptr inbounds i8* %[[VBTABLE]], i32 4
+// CHECK: %[[VBENTRY:.*]] = bitcast i8* %[[VBENTRY8]] to i32*
+// CHECK: %[[VBOFFSET32:.*]] = load i32* %[[VBENTRY]]
+// CHECK: %[[VBOFFSET:.*]] = add nsw i32 0, %[[VBOFFSET32]]
+// CHECK: %[[VBASE_i8:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 %[[VBOFFSET]]
+// CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VBASE_i8]] to void (%struct.B*, i32)***
+// CHECK: %[[VFTABLE:.*]] = load void (%struct.B*, i32)*** %[[VFPTR]]
+// CHECK: %[[VFUN:.*]] = getelementptr inbounds void (%struct.B*, i32)** %[[VFTABLE]], i64 0
+// CHECK: %[[VFUN_VALUE:.*]] = load void (%struct.B*, i32)** %[[VFUN]]
+//
+// CHECK: %[[OBJ_i8:.*]] = bitcast %struct.B* %[[OBJ]] to i8*
+// CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 0
+// CHECK: %[[VBPTR8:.*]] = bitcast i8* %[[VBPTR]] to i8**
+// CHECK: %[[VBTABLE:.*]] = load i8** %[[VBPTR8]]
+// CHECK: %[[VBENTRY8:.*]] = getelementptr inbounds i8* %[[VBTABLE]], i32 4
+// CHECK: %[[VBENTRY:.*]] = bitcast i8* %[[VBENTRY8]] to i32*
+// CHECK: %[[VBOFFSET32:.*]] = load i32* %[[VBENTRY]]
+// CHECK: %[[VBOFFSET:.*]] = add nsw i32 0, %[[VBOFFSET32]]
+// CHECK: %[[VBASE_i8:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 %[[VBOFFSET]]
+// CHECK: %[[VBASE:.*]] = bitcast i8* %[[VBASE_i8]] to %struct.B*
+//
+// CHECK: call x86_thiscallcc void %[[VFUN_VALUE]](%struct.B* %[[VBASE]], i32 1)
+// CHECK: ret void
+}
+
+void call_complete_dtor() {
+ // CHECK-LABEL: define void @"\01?call_complete_dtor@@YAXXZ"
+ B b;
+ // CHECK: call x86_thiscallcc %struct.B* @"\01??0B@@QAE@XZ"(%struct.B* %[[B:.*]], i32 1)
+ // CHECK-NOT: getelementptr
+ // CHECK: call x86_thiscallcc void @"\01??_DB@@UAE@XZ"(%struct.B* %[[B]])
+ // CHECK: ret
+}
+
+struct C : B {
+ C();
+ // has an implicit vdtor.
+};
+
+// Used to crash on an assertion.
+C::C() {
+// CHECK-LABEL: define x86_thiscallcc %struct.C* @"\01??0C@@QAE@XZ"
+}
+
+namespace multiple_vbases {
+struct A {
+ virtual void a();
+};
+
+struct B {
+ virtual void b();
+};
+
+struct C {
+ virtual void c();
+};
+
+struct D : virtual A, virtual B, virtual C {
+ virtual void a();
+ virtual void b();
+ virtual void c();
+ D();
+};
+
+D::D() {
+ // CHECK-LABEL: define x86_thiscallcc %"struct.multiple_vbases::D"* @"\01??0D@multiple_vbases@@QAE@XZ"
+ // Just make sure we emit 3 vtordisps after initializing vfptrs.
+ // CHECK: store [1 x i8*]* @"\01??_7D@multiple_vbases@@6BA@1@@", [1 x i8*]** %{{.*}}
+ // CHECK: store [1 x i8*]* @"\01??_7D@multiple_vbases@@6BB@1@@", [1 x i8*]** %{{.*}}
+ // CHECK: store [1 x i8*]* @"\01??_7D@multiple_vbases@@6BC@1@@", [1 x i8*]** %{{.*}}
+ // ...
+ // CHECK: store i32 %{{.*}}, i32* %{{.*}}
+ // CHECK: store i32 %{{.*}}, i32* %{{.*}}
+ // CHECK: store i32 %{{.*}}, i32* %{{.*}}
+ // CHECK: ret
+}
+}
+
+namespace diamond {
+struct A {
+ A();
+ virtual ~A();
+};
+
+struct B : virtual A {
+ B();
+ ~B();
+};
+
+struct C : virtual A {
+ C();
+ ~C();
+ int c1, c2, c3;
+};
+
+struct Z {
+ int z;
+};
+
+struct D : virtual Z, B, C {
+ D();
+ ~D();
+} d;
+
+D::~D() {
+ // CHECK-LABEL: define x86_thiscallcc void @"\01??1D@diamond@@UAE@XZ"(%"struct.diamond::D"*)
+ // CHECK: %[[ARG_i8:.*]] = bitcast %"struct.diamond::D"* %{{.*}} to i8*
+ // CHECK: %[[THIS_i8:.*]] = getelementptr inbounds i8* %[[ARG_i8]], i32 -24
+ // CHECK: %[[THIS:.*]] = bitcast i8* %[[THIS_i8]] to %"struct.diamond::D"*
+ // CHECK: store %"struct.diamond::D"* %[[THIS]], %"struct.diamond::D"** %[[THIS_VAL:.*]], align 4
+ // CHECK: %[[THIS:.*]] = load %"struct.diamond::D"** %[[THIS_VAL]]
+ // CHECK: %[[D_i8:.*]] = bitcast %"struct.diamond::D"* %[[THIS]] to i8*
+ // CHECK: %[[C_i8:.*]] = getelementptr inbounds i8* %[[D_i8]], i64 4
+ // CHECK: %[[C:.*]] = bitcast i8* %[[C_i8]] to %"struct.diamond::C"*
+ // CHECK: %[[C_i8:.*]] = bitcast %"struct.diamond::C"* %[[C]] to i8*
+ // CHECK: %[[ARG_i8:.*]] = getelementptr i8* %{{.*}}, i32 16
+ // FIXME: We might consider changing the dtor this parameter type to i8*.
+ // CHECK: %[[ARG:.*]] = bitcast i8* %[[ARG_i8]] to %"struct.diamond::C"*
+ // CHECK: call x86_thiscallcc void @"\01??1C@diamond@@UAE@XZ"(%"struct.diamond::C"* %[[ARG]])
+
+ // CHECK: %[[B:.*]] = bitcast %"struct.diamond::D"* %[[THIS]] to %"struct.diamond::B"*
+ // CHECK: %[[B_i8:.*]] = bitcast %"struct.diamond::B"* %[[B]] to i8*
+ // CHECK: %[[ARG_i8:.*]] = getelementptr i8* %[[B_i8]], i32 4
+ // CHECK: %[[ARG:.*]] = bitcast i8* %[[ARG_i8]] to %"struct.diamond::B"*
+ // CHECK: call x86_thiscallcc void @"\01??1B@diamond@@UAE@XZ"(%"struct.diamond::B"* %[[ARG]])
+ // CHECK: ret void
+}
+
+}
diff --git a/test/CodeGenCXX/microsoft-abi-virtual-member-pointers.cpp b/test/CodeGenCXX/microsoft-abi-virtual-member-pointers.cpp
new file mode 100644
index 0000000..51a04c8
--- /dev/null
+++ b/test/CodeGenCXX/microsoft-abi-virtual-member-pointers.cpp
@@ -0,0 +1,108 @@
+// RUN: %clang_cc1 -fno-rtti -emit-llvm -cxx-abi microsoft -triple=i386-pc-win32 %s -o - | FileCheck %s --check-prefix=CHECK32
+// RUN: %clang_cc1 -fno-rtti -emit-llvm -cxx-abi microsoft -triple=x86_64-pc-win32 %s -o - | FileCheck %s --check-prefix=CHECK64
+
+struct S {
+ int x, y, z;
+};
+
+struct C {
+ virtual void foo();
+ virtual int bar(int, double);
+ virtual S baz(int);
+};
+
+namespace {
+struct D {
+ virtual void foo();
+};
+}
+
+void f() {
+ void (C::*ptr)();
+ ptr = &C::foo;
+ ptr = &C::foo; // Don't crash trying to define the thunk twice :)
+
+ int (C::*ptr2)(int, double);
+ ptr2 = &C::bar;
+
+ S (C::*ptr3)(int);
+ ptr3 = &C::baz;
+
+ void (D::*ptr4)();
+ ptr4 = &D::foo;
+
+// CHECK32-LABEL: define void @"\01?f@@YAXXZ"()
+// CHECK32: store i8* bitcast (void (%struct.C*)* @"\01??_9C@@$BA@AE" to i8*), i8** %ptr
+// CHECK32: store i8* bitcast (i32 (%struct.C*, i32, double)* @"\01??_9C@@$B3AE" to i8*), i8** %ptr2
+// CHECK32: store i8* bitcast (void (%struct.S*, %struct.C*, i32)* @"\01??_9C@@$B7AE" to i8*), i8** %ptr3
+// CHECK32: store i8* bitcast (void (%"struct.<anonymous namespace>::D"*)* @"\01??_9D@?A@@$BA@AE" to i8*), i8** %ptr4
+// CHECK32: }
+//
+// CHECK64-LABEL: define void @"\01?f@@YAXXZ"()
+// CHECK64: store i8* bitcast (void (%struct.C*)* @"\01??_9C@@$BA@AA" to i8*), i8** %ptr
+// CHECK64: store i8* bitcast (i32 (%struct.C*, i32, double)* @"\01??_9C@@$B7AA" to i8*), i8** %ptr2
+// CHECK64: store i8* bitcast (void (%struct.S*, %struct.C*, i32)* @"\01??_9C@@$BBA@AA" to i8*), i8** %ptr3
+// CHECK64: store i8* bitcast (void (%"struct.<anonymous namespace>::D"*)* @"\01??_9D@?A@@$BA@AA" to i8*), i8** %ptr
+// CHECK64: }
+}
+
+
+// Thunk for calling the 1st virtual function in C with no parameters.
+// CHECK32-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_9C@@$BA@AE"(%struct.C* %this) unnamed_addr
+// CHECK32: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*)** %{{.*}}, i64 0
+// CHECK32: [[CALLEE:%.*]] = load void (%struct.C*)** [[VPTR]]
+// CHECK32: call x86_thiscallcc void [[CALLEE]](%struct.C* %{{.*}})
+// CHECK32: ret void
+// CHECK32: }
+//
+// CHECK64-LABEL: define linkonce_odr void @"\01??_9C@@$BA@AA"(%struct.C* %this) unnamed_addr
+// CHECK64: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*)** %{{.*}}, i64 0
+// CHECK64: [[CALLEE:%.*]] = load void (%struct.C*)** [[VPTR]]
+// CHECK64: call void [[CALLEE]](%struct.C* %{{.*}})
+// CHECK64: ret void
+// CHECK64: }
+
+// Thunk for calling the 2nd virtual function in C, taking int and double as parameters, returning int.
+// CHECK32-LABEL: define linkonce_odr x86_thiscallcc i32 @"\01??_9C@@$B3AE"(%struct.C* %this, i32, double) unnamed_addr
+// CHECK32: [[VPTR:%.*]] = getelementptr inbounds i32 (%struct.C*, i32, double)** %{{.*}}, i64 1
+// CHECK32: [[CALLEE:%.*]] = load i32 (%struct.C*, i32, double)** [[VPTR]]
+// CHECK32: [[CALL:%.*]] = call x86_thiscallcc i32 [[CALLEE]](%struct.C* %{{.*}}, i32 %{{.*}}, double %{{.*}})
+// CHECK32: ret i32 [[CALL]]
+// CHECK32: }
+//
+// CHECK64-LABEL: define linkonce_odr i32 @"\01??_9C@@$B7AA"(%struct.C* %this, i32, double) unnamed_addr
+// CHECK64: [[VPTR:%.*]] = getelementptr inbounds i32 (%struct.C*, i32, double)** %{{.*}}, i64 1
+// CHECK64: [[CALLEE:%.*]] = load i32 (%struct.C*, i32, double)** [[VPTR]]
+// CHECK64: [[CALL:%.*]] = call i32 [[CALLEE]](%struct.C* %{{.*}}, i32 %{{.*}}, double %{{.*}})
+// CHECK64: ret i32 [[CALL]]
+// CHECK64: }
+
+// Thunk for calling the 3rd virtual function in C, taking an int parameter, returning a struct.
+// CHECK32-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_9C@@$B7AE"(%struct.S* noalias sret %agg.result, %struct.C* %this, i32) unnamed_addr
+// CHECK32: [[VPTR:%.*]] = getelementptr inbounds void (%struct.S*, %struct.C*, i32)** %{{.*}}, i64 2
+// CHECK32: [[CALLEE:%.*]] = load void (%struct.S*, %struct.C*, i32)** [[VPTR]]
+// CHECK32: call x86_thiscallcc void [[CALLEE]](%struct.S* sret %agg.result, %struct.C* %{{.*}}, i32 %{{.*}})
+// CHECK32: ret void
+// CHECK32: }
+//
+// CHECK64-LABEL: define linkonce_odr void @"\01??_9C@@$BBA@AA"(%struct.S* noalias sret %agg.result, %struct.C* %this, i32) unnamed_addr
+// CHECK64: [[VPTR:%.*]] = getelementptr inbounds void (%struct.S*, %struct.C*, i32)** %{{.*}}, i64 2
+// CHECK64: [[CALLEE:%.*]] = load void (%struct.S*, %struct.C*, i32)** [[VPTR]]
+// CHECK64: call void [[CALLEE]](%struct.S* sret %agg.result, %struct.C* %{{.*}}, i32 %{{.*}})
+// CHECK64: ret void
+// CHECK64: }
+
+// Thunk for calling the virtual function in internal class D.
+// CHECK32-LABEL: define internal x86_thiscallcc void @"\01??_9D@?A@@$BA@AE"(%"struct.<anonymous namespace>::D"* %this) unnamed_addr
+// CHECK32: [[VPTR:%.*]] = getelementptr inbounds void (%"struct.<anonymous namespace>::D"*)** %{{.*}}, i64 0
+// CHECK32: [[CALLEE:%.*]] = load void (%"struct.<anonymous namespace>::D"*)** [[VPTR]]
+// CHECK32: call x86_thiscallcc void [[CALLEE]](%"struct.<anonymous namespace>::D"* %{{.*}})
+// CHECK32: ret void
+// CHECK32: }
+//
+// CHECK64-LABEL: define internal void @"\01??_9D@?A@@$BA@AA"(%"struct.<anonymous namespace>::D"* %this) unnamed_addr
+// CHECK64: [[VPTR:%.*]] = getelementptr inbounds void (%"struct.<anonymous namespace>::D"*)** %{{.*}}, i64 0
+// CHECK64: [[CALLEE:%.*]] = load void (%"struct.<anonymous namespace>::D"*)** [[VPTR]]
+// CHECK64: call void [[CALLEE]](%"struct.<anonymous namespace>::D"* %{{.*}})
+// CHECK64: ret void
+// CHECK64: }
diff --git a/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance.cpp b/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance.cpp
new file mode 100644
index 0000000..d93dee1
--- /dev/null
+++ b/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance.cpp
@@ -0,0 +1,579 @@
+// RUN: %clang_cc1 %s -fno-rtti -cxx-abi microsoft -triple=i386-pc-win32 -emit-llvm -o %t.ll -fdump-vtable-layouts >%t
+
+// RUN: FileCheck --check-prefix=NO-THUNKS-Test1 %s < %t
+// RUN: FileCheck --check-prefix=NO-THUNKS-Test2 %s < %t
+// RUN: FileCheck --check-prefix=NO-THUNKS-Test3 %s < %t
+// RUN: FileCheck --check-prefix=NO-THUNKS-Test4 %s < %t
+// RUN: FileCheck --check-prefix=NO-THUNKS-Test5 %s < %t
+// RUN: FileCheck --check-prefix=NO-THUNKS-Test6 %s < %t
+// RUN: FileCheck --check-prefix=NO-THUNKS-Test7 %s < %t
+// RUN: FileCheck --check-prefix=NO-THUNKS-Test8 %s < %t
+// RUN: FileCheck --check-prefix=NO-THUNKS-Test9 %s < %t
+// RUN: FileCheck --check-prefix=PURE-VIRTUAL-Test1 %s < %t
+// RUN: FileCheck --check-prefix=THIS-THUNKS-Test1 %s < %t
+// RUN: FileCheck --check-prefix=THIS-THUNKS-Test2 %s < %t
+// RUN: FileCheck --check-prefix=THIS-THUNKS-Test3 %s < %t
+// RUN: FileCheck --check-prefix=VDTOR-THUNKS-Test3 %s < %t
+// RUN: FileCheck --check-prefix=VDTOR-THUNKS-Test5 %s < %t
+// RUN: FileCheck --check-prefix=VDTOR-THUNKS-Test6 %s < %t
+// RUN: FileCheck --check-prefix=VDTOR-THUNKS-Test7 %s < %t
+// RUN: FileCheck --check-prefix=RET-THUNKS-Test1 %s < %t
+// RUN: FileCheck --check-prefix=RET-THUNKS-Test2 %s < %t
+// RUN: FileCheck --check-prefix=RET-THUNKS-Test3 %s < %t
+// RUN: FileCheck --check-prefix=RET-THUNKS-Test4 %s < %t
+// RUN: FileCheck --check-prefix=RET-THUNKS-Test5 %s < %t
+// RUN: FileCheck --check-prefix=RET-THUNKS-Test6 %s < %t
+
+// RUN: FileCheck --check-prefix=MANGLING %s < %t.ll
+
+struct Empty {
+ // Doesn't have a vftable!
+};
+
+struct A {
+ virtual void f();
+};
+
+struct B {
+ virtual void g();
+ // Add an extra virtual method so it's easier to check for the absence of thunks.
+ virtual void h();
+};
+
+struct C {
+ virtual void g(); // Might "collide" with B::g if both are bases of some class.
+};
+
+
+namespace no_thunks {
+
+struct Test1: A, B {
+ // NO-THUNKS-Test1: VFTable for 'A' in 'no_thunks::Test1' (1 entries)
+ // NO-THUNKS-Test1-NEXT: 0 | void no_thunks::Test1::f()
+
+ // NO-THUNKS-Test1: VFTable for 'B' in 'no_thunks::Test1' (2 entries)
+ // NO-THUNKS-Test1-NEXT: 0 | void B::g()
+ // NO-THUNKS-Test1-NEXT: 1 | void B::h()
+
+ // NO-THUNKS-Test1: VFTable indices for 'no_thunks::Test1' (1 entries)
+ // NO-THUNKS-Test1-NEXT: 0 | void no_thunks::Test1::f()
+
+ // MANGLING-DAG: @"\01??_7Test1@no_thunks@@6BA@@@"
+ // MANGLING-DAG: @"\01??_7Test1@no_thunks@@6BB@@@"
+
+ // Overrides only the left child's method (A::f), needs no thunks.
+ virtual void f();
+};
+
+Test1 t1;
+
+struct Test2: A, B {
+ // NO-THUNKS-Test2: VFTable for 'A' in 'no_thunks::Test2' (1 entries)
+ // NO-THUNKS-Test2-NEXT: 0 | void A::f()
+
+ // NO-THUNKS-Test2: VFTable for 'B' in 'no_thunks::Test2' (2 entries)
+ // NO-THUNKS-Test2-NEXT: 0 | void no_thunks::Test2::g()
+ // NO-THUNKS-Test2-NEXT: 1 | void B::h()
+
+ // NO-THUNKS-Test2: VFTable indices for 'no_thunks::Test2' (1 entries).
+ // NO-THUNKS-Test2-NEXT: via vfptr at offset 4
+ // NO-THUNKS-Test2-NEXT: 0 | void no_thunks::Test2::g()
+
+ // Overrides only the right child's method (B::g), needs this adjustment but
+ // not thunks.
+ virtual void g();
+};
+
+Test2 t2;
+
+struct Test3: A, B {
+ // NO-THUNKS-Test3: VFTable for 'A' in 'no_thunks::Test3' (2 entries)
+ // NO-THUNKS-Test3-NEXT: 0 | void A::f()
+ // NO-THUNKS-Test3-NEXT: 1 | void no_thunks::Test3::i()
+
+ // NO-THUNKS-Test3: VFTable for 'B' in 'no_thunks::Test3' (2 entries)
+ // NO-THUNKS-Test3-NEXT: 0 | void B::g()
+ // NO-THUNKS-Test3-NEXT: 1 | void B::h()
+
+ // NO-THUNKS-Test3: VFTable indices for 'no_thunks::Test3' (1 entries).
+ // NO-THUNKS-Test3-NEXT: 1 | void no_thunks::Test3::i()
+
+ // Only adds a new method.
+ virtual void i();
+};
+
+Test3 t3;
+
+// Only the right base has a vftable, so it's laid out before the left one!
+struct Test4 : Empty, A {
+ // NO-THUNKS-Test4: VFTable for 'A' in 'no_thunks::Test4' (1 entries)
+ // NO-THUNKS-Test4-NEXT: 0 | void no_thunks::Test4::f()
+
+ // NO-THUNKS-Test4: VFTable indices for 'no_thunks::Test4' (1 entries).
+ // NO-THUNKS-Test4-NEXT: 0 | void no_thunks::Test4::f()
+
+ // MANGLING-DAG: @"\01??_7Test4@no_thunks@@6B@"
+
+ virtual void f();
+};
+
+Test4 t4;
+
+// 2-level structure with repeating subobject types, but no thunks needed.
+struct Test5: Test1, Test2 {
+ // NO-THUNKS-Test5: VFTable for 'A' in 'no_thunks::Test1' in 'no_thunks::Test5' (2 entries)
+ // NO-THUNKS-Test5-NEXT: 0 | void no_thunks::Test1::f()
+ // NO-THUNKS-Test5-NEXT: 1 | void no_thunks::Test5::z()
+
+ // NO-THUNKS-Test5: VFTable for 'B' in 'no_thunks::Test1' in 'no_thunks::Test5' (2 entries)
+ // NO-THUNKS-Test5-NEXT: 0 | void B::g()
+ // NO-THUNKS-Test5-NEXT: 1 | void B::h()
+
+ // NO-THUNKS-Test5: VFTable for 'A' in 'no_thunks::Test2' in 'no_thunks::Test5' (1 entries)
+ // NO-THUNKS-Test5-NEXT: 0 | void A::f()
+
+ // NO-THUNKS-Test5: VFTable for 'B' in 'no_thunks::Test2' in 'no_thunks::Test5' (2 entries)
+ // NO-THUNKS-Test5-NEXT: 0 | void no_thunks::Test2::g()
+ // NO-THUNKS-Test5-NEXT: 1 | void B::h()
+
+ // NO-THUNKS-Test5: VFTable indices for 'no_thunks::Test5' (1 entries).
+ // NO-THUNKS-Test5-NEXT: 1 | void no_thunks::Test5::z()
+
+ // MANGLING-DAG: @"\01??_7Test5@no_thunks@@6BA@@Test1@1@@"
+ // MANGLING-DAG: @"\01??_7Test5@no_thunks@@6BA@@Test2@1@@"
+ // MANGLING-DAG: @"\01??_7Test5@no_thunks@@6BB@@Test1@1@@"
+ // MANGLING-DAG: @"\01??_7Test5@no_thunks@@6BB@@Test2@1@@"
+
+ virtual void z();
+};
+
+Test5 t5;
+
+struct Test6: Test1 {
+ // NO-THUNKS-Test6: VFTable for 'A' in 'no_thunks::Test1' in 'no_thunks::Test6' (1 entries).
+ // NO-THUNKS-Test6-NEXT: 0 | void no_thunks::Test6::f()
+
+ // NO-THUNKS-Test6: VFTable for 'B' in 'no_thunks::Test1' in 'no_thunks::Test6' (2 entries).
+ // NO-THUNKS-Test6-NEXT: 0 | void B::g()
+ // NO-THUNKS-Test6-NEXT: 1 | void B::h()
+
+ // NO-THUNKS-Test6: VFTable indices for 'no_thunks::Test6' (1 entries).
+ // NO-THUNKS-Test6-NEXT: 0 | void no_thunks::Test6::f()
+
+ // MANGLING-DAG: @"\01??_7Test6@no_thunks@@6BA@@@"
+ // MANGLING-DAG: @"\01??_7Test6@no_thunks@@6BB@@@"
+
+ // Overrides both no_thunks::Test1::f and A::f.
+ virtual void f();
+};
+
+Test6 t6;
+
+struct Test7: Test2 {
+ // NO-THUNKS-Test7: VFTable for 'A' in 'no_thunks::Test2' in 'no_thunks::Test7' (1 entries).
+ // NO-THUNKS-Test7-NEXT: 0 | void A::f()
+
+ // NO-THUNKS-Test7: VFTable for 'B' in 'no_thunks::Test2' in 'no_thunks::Test7' (2 entries).
+ // NO-THUNKS-Test7-NEXT: 0 | void no_thunks::Test7::g()
+ // NO-THUNKS-Test7-NEXT: 1 | void B::h()
+
+ // NO-THUNKS-Test7: VFTable indices for 'no_thunks::Test7' (1 entries).
+ // NO-THUNKS-Test7-NEXT: via vfptr at offset 4
+ // NO-THUNKS-Test7-NEXT: 0 | void no_thunks::Test7::g()
+
+ // Overrides both no_thunks::Test2::g and B::g.
+ virtual void g();
+};
+
+Test7 t7;
+
+struct Test8: Test3 {
+ // NO-THUNKS-Test8: VFTable for 'A' in 'no_thunks::Test3' in 'no_thunks::Test8' (2 entries).
+ // NO-THUNKS-Test8-NEXT: 0 | void A::f()
+ // NO-THUNKS-Test8-NEXT: 1 | void no_thunks::Test3::i()
+
+ // NO-THUNKS-Test8: VFTable for 'B' in 'no_thunks::Test3' in 'no_thunks::Test8' (2 entries).
+ // NO-THUNKS-Test8-NEXT: 0 | void no_thunks::Test8::g()
+ // NO-THUNKS-Test8-NEXT: 1 | void B::h()
+
+ // NO-THUNKS-Test8: VFTable indices for 'no_thunks::Test8' (1 entries).
+ // NO-THUNKS-Test8-NEXT: via vfptr at offset 4
+ // NO-THUNKS-Test8-NEXT: 0 | void no_thunks::Test8::g()
+
+ // Overrides grandparent's B::g.
+ virtual void g();
+};
+
+Test8 t8;
+
+struct D : A {
+ virtual void g();
+};
+
+// Repeating subobject.
+struct Test9: A, D {
+ // NO-THUNKS-Test9: VFTable for 'A' in 'no_thunks::Test9' (2 entries).
+ // NO-THUNKS-Test9-NEXT: 0 | void A::f()
+ // NO-THUNKS-Test9-NEXT: 1 | void no_thunks::Test9::h()
+
+ // NO-THUNKS-Test9: VFTable for 'A' in 'no_thunks::D' in 'no_thunks::Test9' (2 entries).
+ // NO-THUNKS-Test9-NEXT: 0 | void A::f()
+ // NO-THUNKS-Test9-NEXT: 1 | void no_thunks::D::g()
+
+ // NO-THUNKS-Test9: VFTable indices for 'no_thunks::Test9' (1 entries).
+ // NO-THUNKS-Test9-NEXT: 1 | void no_thunks::Test9::h()
+
+ // MANGLING-DAG: @"\01??_7Test9@no_thunks@@6BA@@@"
+ // MANGLING-DAG: @"\01??_7Test9@no_thunks@@6BD@1@@"
+
+ virtual void h();
+};
+
+Test9 t9;
+}
+
+namespace pure_virtual {
+struct D {
+ virtual void g() = 0;
+ virtual void h();
+};
+
+
+struct Test1: A, D {
+ // PURE-VIRTUAL-Test1: VFTable for 'A' in 'pure_virtual::Test1' (1 entries)
+ // PURE-VIRTUAL-Test1-NEXT: 0 | void A::f()
+
+ // PURE-VIRTUAL-Test1: VFTable for 'pure_virtual::D' in 'pure_virtual::Test1' (2 entries)
+ // PURE-VIRTUAL-Test1-NEXT: 0 | void pure_virtual::Test1::g()
+ // PURE-VIRTUAL-Test1-NEXT: 1 | void pure_virtual::D::h()
+
+ // PURE-VIRTUAL-Test1: VFTable indices for 'pure_virtual::Test1' (1 entries).
+ // PURE-VIRTUAL-Test1-NEXT: via vfptr at offset 4
+ // PURE-VIRTUAL-Test1-NEXT: 0 | void pure_virtual::Test1::g()
+
+ // MANGLING-DAG: @"\01??_7Test1@pure_virtual@@6BA@@@"
+ // MANGLING-DAG: @"\01??_7Test1@pure_virtual@@6BD@1@@"
+
+ // Overrides only the right child's method (pure_virtual::D::g), needs this adjustment but
+ // not thunks.
+ virtual void g();
+};
+
+Test1 t1;
+}
+
+namespace this_adjustment {
+
+// Overrides methods of two bases at the same time, thus needing thunks.
+struct Test1 : B, C {
+ // THIS-THUNKS-Test1: VFTable for 'B' in 'this_adjustment::Test1' (2 entries).
+ // THIS-THUNKS-Test1-NEXT: 0 | void this_adjustment::Test1::g()
+ // THIS-THUNKS-Test1-NEXT: 1 | void B::h()
+
+ // THIS-THUNKS-Test1: VFTable for 'C' in 'this_adjustment::Test1' (1 entries).
+ // THIS-THUNKS-Test1-NEXT: 0 | void this_adjustment::Test1::g()
+ // THIS-THUNKS-Test1-NEXT: [this adjustment: -4 non-virtual]
+
+ // THIS-THUNKS-Test1: Thunks for 'void this_adjustment::Test1::g()' (1 entry).
+ // THIS-THUNKS-Test1-NEXT: 0 | [this adjustment: -4 non-virtual]
+
+ // THIS-THUNKS-Test1: VFTable indices for 'this_adjustment::Test1' (1 entries).
+ // THIS-THUNKS-Test1-NEXT: 0 | void this_adjustment::Test1::g()
+
+ // MANGLING-DAG: @"\01??_7Test1@this_adjustment@@6BB@@@"
+ // MANGLING-DAG: @"\01??_7Test1@this_adjustment@@6BC@@@"
+
+ virtual void g();
+};
+
+Test1 t1;
+
+struct Test2 : A, B, C {
+ // THIS-THUNKS-Test2: VFTable for 'A' in 'this_adjustment::Test2' (1 entries).
+ // THIS-THUNKS-Test2-NEXT: 0 | void A::f()
+
+ // THIS-THUNKS-Test2: VFTable for 'B' in 'this_adjustment::Test2' (2 entries).
+ // THIS-THUNKS-Test2-NEXT: 0 | void this_adjustment::Test2::g()
+ // THIS-THUNKS-Test2-NEXT: 1 | void B::h()
+
+ // THIS-THUNKS-Test2: VFTable for 'C' in 'this_adjustment::Test2' (1 entries).
+ // THIS-THUNKS-Test2-NEXT: 0 | void this_adjustment::Test2::g()
+ // THIS-THUNKS-Test2-NEXT: [this adjustment: -4 non-virtual]
+
+ // THIS-THUNKS-Test2: Thunks for 'void this_adjustment::Test2::g()' (1 entry).
+ // THIS-THUNKS-Test2-NEXT: 0 | [this adjustment: -4 non-virtual]
+
+ // THIS-THUNKS-Test2: VFTable indices for 'this_adjustment::Test2' (1 entries).
+ // THIS-THUNKS-Test2-NEXT: via vfptr at offset 4
+ // THIS-THUNKS-Test2-NEXT: 0 | void this_adjustment::Test2::g()
+
+ // MANGLING-DAG: @"\01??_7Test2@this_adjustment@@6BA@@@"
+ // MANGLING-DAG: @"\01??_7Test2@this_adjustment@@6BB@@@"
+ // MANGLING-DAG: @"\01??_7Test2@this_adjustment@@6BC@@@"
+
+ virtual void g();
+};
+
+Test2 t2;
+
+// Overrides methods of two bases at the same time, thus needing thunks.
+struct Test3: no_thunks::Test1, no_thunks::Test2 {
+ // THIS-THUNKS-Test3: VFTable for 'A' in 'no_thunks::Test1' in 'this_adjustment::Test3' (1 entries).
+ // THIS-THUNKS-Test3-NEXT: 0 | void this_adjustment::Test3::f()
+
+ // THIS-THUNKS-Test3: VFTable for 'B' in 'no_thunks::Test1' in 'this_adjustment::Test3' (2 entries).
+ // THIS-THUNKS-Test3-NEXT: 0 | void this_adjustment::Test3::g()
+ // THIS-THUNKS-Test3-NEXT: 1 | void B::h()
+
+ // THIS-THUNKS-Test3: VFTable for 'A' in 'no_thunks::Test2' in 'this_adjustment::Test3' (1 entries).
+ // THIS-THUNKS-Test3-NEXT: 0 | void this_adjustment::Test3::f()
+ // THIS-THUNKS-Test3-NEXT: [this adjustment: -8 non-virtual]
+
+ // THIS-THUNKS-Test3: Thunks for 'void this_adjustment::Test3::f()' (1 entry).
+ // THIS-THUNKS-Test3-NEXT: 0 | [this adjustment: -8 non-virtual]
+
+ // THIS-THUNKS-Test3: VFTable for 'B' in 'no_thunks::Test2' in 'this_adjustment::Test3' (2 entries).
+ // THIS-THUNKS-Test3-NEXT: 0 | void this_adjustment::Test3::g()
+ // THIS-THUNKS-Test3-NEXT: [this adjustment: -8 non-virtual]
+ // THIS-THUNKS-Test3-NEXT: 1 | void B::h()
+
+ // THIS-THUNKS-Test3: Thunks for 'void this_adjustment::Test3::g()' (1 entry).
+ // THIS-THUNKS-Test3-NEXT: 0 | [this adjustment: -8 non-virtual]
+
+ // THIS-THUNKS-Test3: VFTable indices for 'this_adjustment::Test3' (2 entries).
+ // THIS-THUNKS-Test3-NEXT: via vfptr at offset 0
+ // THIS-THUNKS-Test3-NEXT: 0 | void this_adjustment::Test3::f()
+ // THIS-THUNKS-Test3-NEXT: via vfptr at offset 4
+ // THIS-THUNKS-Test3-NEXT: 0 | void this_adjustment::Test3::g()
+
+ virtual void f();
+ virtual void g();
+};
+
+Test3 t3;
+}
+
+namespace vdtor {
+struct Test1 {
+ virtual ~Test1();
+ virtual void z1();
+};
+
+struct Test2 {
+ virtual ~Test2();
+};
+
+struct Test3 : Test1, Test2 {
+ // VDTOR-THUNKS-Test3: VFTable for 'vdtor::Test1' in 'vdtor::Test3' (2 entries).
+ // VDTOR-THUNKS-Test3-NEXT: 0 | vdtor::Test3::~Test3() [scalar deleting]
+ // VDTOR-THUNKS-Test3-NEXT: 1 | void vdtor::Test1::z1()
+
+ // VDTOR-THUNKS-Test3: VFTable for 'vdtor::Test2' in 'vdtor::Test3' (1 entries).
+ // VDTOR-THUNKS-Test3-NEXT: 0 | vdtor::Test3::~Test3() [scalar deleting]
+ // VDTOR-THUNKS-Test3-NEXT: [this adjustment: -4 non-virtual]
+
+ // VDTOR-THUNKS-Test3: Thunks for 'vdtor::Test3::~Test3()' (1 entry).
+ // VDTOR-THUNKS-Test3-NEXT: 0 | [this adjustment: -4 non-virtual]
+
+ // VDTOR-THUNKS-Test3: VFTable indices for 'vdtor::Test3' (1 entries).
+ // VDTOR-THUNKS-Test3-NEXT: 0 | vdtor::Test3::~Test3() [scalar deleting]
+ virtual ~Test3();
+};
+
+Test3 t3;
+
+struct Test4 {
+ // No virtual destructor here!
+ virtual void z4();
+};
+
+struct Test5 : Test4, Test2 {
+ // Implicit virtual dtor here!
+
+ // VDTOR-THUNKS-Test5: VFTable for 'vdtor::Test4' in 'vdtor::Test5' (1 entries).
+ // VDTOR-THUNKS-Test5-NEXT: 0 | void vdtor::Test4::z4()
+
+ // VDTOR-THUNKS-Test5: VFTable for 'vdtor::Test2' in 'vdtor::Test5' (1 entries).
+ // VDTOR-THUNKS-Test5-NEXT: 0 | vdtor::Test5::~Test5() [scalar deleting]
+ // VDTOR-THUNKS-Test5-NEXT: [this adjustment: -4 non-virtual]
+
+ // VDTOR-THUNKS-Test5: Thunks for 'vdtor::Test5::~Test5()' (1 entry).
+ // VDTOR-THUNKS-Test5-NEXT: 0 | [this adjustment: -4 non-virtual]
+
+ // VDTOR-THUNKS-Test5: VFTable indices for 'vdtor::Test5' (1 entries).
+ // VDTOR-THUNKS-Test5-NEXT: -- accessible via vfptr at offset 4 --
+ // VDTOR-THUNKS-Test5-NEXT: 0 | vdtor::Test5::~Test5() [scalar deleting]
+};
+
+Test5 t5;
+
+struct Test6 : Test4, Test2 {
+ // Implicit virtual dtor here!
+
+ // VDTOR-THUNKS-Test6: VFTable for 'vdtor::Test4' in 'vdtor::Test6' (1 entries).
+ // VDTOR-THUNKS-Test6-NEXT: 0 | void vdtor::Test4::z4()
+
+ // VDTOR-THUNKS-Test6: VFTable for 'vdtor::Test2' in 'vdtor::Test6' (1 entries).
+ // VDTOR-THUNKS-Test6-NEXT: 0 | vdtor::Test6::~Test6() [scalar deleting]
+ // VDTOR-THUNKS-Test6-NEXT: [this adjustment: -4 non-virtual]
+
+ // VDTOR-THUNKS-Test6: Thunks for 'vdtor::Test6::~Test6()' (1 entry).
+ // VDTOR-THUNKS-Test6-NEXT: 0 | [this adjustment: -4 non-virtual]
+
+ // VDTOR-THUNKS-Test6: VFTable indices for 'vdtor::Test6' (1 entries).
+ // VDTOR-THUNKS-Test6-NEXT: -- accessible via vfptr at offset 4 --
+ // VDTOR-THUNKS-Test6-NEXT: 0 | vdtor::Test6::~Test6() [scalar deleting]
+};
+
+Test6 t6;
+
+struct Test7 : Test5 {
+ // VDTOR-THUNKS-Test7: VFTable for 'vdtor::Test4' in 'vdtor::Test5' in 'vdtor::Test7' (1 entries).
+ // VDTOR-THUNKS-Test7-NEXT: 0 | void vdtor::Test4::z4()
+
+ // VDTOR-THUNKS-Test7: VFTable for 'vdtor::Test2' in 'vdtor::Test5' in 'vdtor::Test7' (1 entries).
+ // VDTOR-THUNKS-Test7-NEXT: 0 | vdtor::Test7::~Test7() [scalar deleting]
+ // VDTOR-THUNKS-Test7-NEXT: [this adjustment: -4 non-virtual]
+
+ // VDTOR-THUNKS-Test7: Thunks for 'vdtor::Test7::~Test7()' (1 entry).
+ // VDTOR-THUNKS-Test7-NEXT: 0 | [this adjustment: -4 non-virtual]
+
+ // VDTOR-THUNKS-Test7: VFTable indices for 'vdtor::Test7' (1 entries).
+ // VDTOR-THUNKS-Test7-NEXT: -- accessible via vfptr at offset 4 --
+ // VDTOR-THUNKS-Test7-NEXT: 0 | vdtor::Test7::~Test7() [scalar deleting]
+ virtual ~Test7();
+};
+
+Test7 t7;
+
+}
+
+namespace return_adjustment {
+
+struct Ret1 {
+ virtual C* foo();
+ virtual void z();
+};
+
+struct Test1 : Ret1 {
+ // RET-THUNKS-Test1: VFTable for 'return_adjustment::Ret1' in 'return_adjustment::Test1' (3 entries).
+ // RET-THUNKS-Test1-NEXT: 0 | this_adjustment::Test1 *return_adjustment::Test1::foo()
+ // RET-THUNKS-Test1-NEXT: [return adjustment: 4 non-virtual]
+ // RET-THUNKS-Test1-NEXT: 1 | void return_adjustment::Ret1::z()
+ // RET-THUNKS-Test1-NEXT: 2 | this_adjustment::Test1 *return_adjustment::Test1::foo()
+
+ // RET-THUNKS-Test1: VFTable indices for 'return_adjustment::Test1' (1 entries).
+ // RET-THUNKS-Test1-NEXT: 2 | this_adjustment::Test1 *return_adjustment::Test1::foo()
+
+ // MANGLING-DAG: @"\01??_7Test1@return_adjustment@@6B@"
+
+ virtual this_adjustment::Test1* foo();
+};
+
+Test1 t1;
+
+struct Ret2 : B, this_adjustment::Test1 { };
+
+struct Test2 : Test1 {
+ // RET-THUNKS-Test2: VFTable for 'return_adjustment::Ret1' in 'return_adjustment::Test1' in 'return_adjustment::Test2' (4 entries).
+ // RET-THUNKS-Test2-NEXT: 0 | return_adjustment::Ret2 *return_adjustment::Test2::foo()
+ // RET-THUNKS-Test2-NEXT: [return adjustment: 8 non-virtual]
+ // RET-THUNKS-Test2-NEXT: 1 | void return_adjustment::Ret1::z()
+ // RET-THUNKS-Test2-NEXT: 2 | return_adjustment::Ret2 *return_adjustment::Test2::foo()
+ // RET-THUNKS-Test2-NEXT: [return adjustment: 4 non-virtual]
+ // RET-THUNKS-Test2-NEXT: 3 | return_adjustment::Ret2 *return_adjustment::Test2::foo()
+
+ // RET-THUNKS-Test2: VFTable indices for 'return_adjustment::Test2' (1 entries).
+ // RET-THUNKS-Test2-NEXT: 3 | return_adjustment::Ret2 *return_adjustment::Test2::foo()
+
+ virtual Ret2* foo();
+};
+
+Test2 t2;
+
+struct Test3: B, Ret1 {
+ // RET-THUNKS-Test3: VFTable for 'B' in 'return_adjustment::Test3' (2 entries).
+ // RET-THUNKS-Test3-NEXT: 0 | void B::g()
+ // RET-THUNKS-Test3-NEXT: 1 | void B::h()
+
+ // RET-THUNKS-Test3: VFTable for 'return_adjustment::Ret1' in 'return_adjustment::Test3' (3 entries).
+ // RET-THUNKS-Test3-NEXT: 0 | this_adjustment::Test1 *return_adjustment::Test3::foo()
+ // RET-THUNKS-Test3-NEXT: [return adjustment: 4 non-virtual]
+ // RET-THUNKS-Test3-NEXT: 1 | void return_adjustment::Ret1::z()
+ // RET-THUNKS-Test3-NEXT: 2 | this_adjustment::Test1 *return_adjustment::Test3::foo()
+
+ // RET-THUNKS-Test3: VFTable indices for 'return_adjustment::Test3' (1 entries).
+ // RET-THUNKS-Test3-NEXT: via vfptr at offset 4
+ // RET-THUNKS-Test3-NEXT: 2 | this_adjustment::Test1 *return_adjustment::Test3::foo()
+
+ virtual this_adjustment::Test1* foo();
+};
+
+Test3 t3;
+
+struct Test4 : Test3 {
+ // RET-THUNKS-Test4: VFTable for 'B' in 'return_adjustment::Test3' in 'return_adjustment::Test4' (2 entries).
+ // RET-THUNKS-Test4-NEXT: 0 | void B::g()
+ // RET-THUNKS-Test4-NEXT: 1 | void B::h()
+
+ // RET-THUNKS-Test4: VFTable for 'return_adjustment::Ret1' in 'return_adjustment::Test3' in 'return_adjustment::Test4' (4 entries).
+ // RET-THUNKS-Test4-NEXT: 0 | return_adjustment::Ret2 *return_adjustment::Test4::foo()
+ // RET-THUNKS-Test4-NEXT: [return adjustment: 8 non-virtual]
+ // RET-THUNKS-Test4-NEXT: 1 | void return_adjustment::Ret1::z()
+ // RET-THUNKS-Test4-NEXT: 2 | return_adjustment::Ret2 *return_adjustment::Test4::foo()
+ // RET-THUNKS-Test4-NEXT: [return adjustment: 4 non-virtual]
+ // RET-THUNKS-Test4-NEXT: 3 | return_adjustment::Ret2 *return_adjustment::Test4::foo()
+
+ // RET-THUNKS-Test4: VFTable indices for 'return_adjustment::Test4' (1 entries).
+ // RET-THUNKS-Test4-NEXT: -- accessible via vfptr at offset 4 --
+ // RET-THUNKS-Test4-NEXT: 3 | return_adjustment::Ret2 *return_adjustment::Test4::foo()
+
+ virtual Ret2* foo();
+};
+
+Test4 t4;
+
+struct Test5 : Ret1, Test1 {
+ // RET-THUNKS-Test5: VFTable for 'return_adjustment::Ret1' in 'return_adjustment::Test5' (3 entries).
+ // RET-THUNKS-Test5-NEXT: 0 | return_adjustment::Ret2 *return_adjustment::Test5::foo()
+ // RET-THUNKS-Test5-NEXT: [return adjustment: 8 non-virtual]
+ // RET-THUNKS-Test5-NEXT: 1 | void return_adjustment::Ret1::z()
+ // RET-THUNKS-Test5-NEXT: 2 | return_adjustment::Ret2 *return_adjustment::Test5::foo()
+
+ // RET-THUNKS-Test5: VFTable for 'return_adjustment::Ret1' in 'return_adjustment::Test1' in 'return_adjustment::Test5' (4 entries).
+ // RET-THUNKS-Test5-NEXT: 0 | return_adjustment::Ret2 *return_adjustment::Test5::foo()
+ // RET-THUNKS-Test5-NEXT: [return adjustment: 8 non-virtual]
+ // RET-THUNKS-Test5-NEXT: [this adjustment: -4 non-virtual]
+ // RET-THUNKS-Test5-NEXT: 1 | void return_adjustment::Ret1::z()
+ // RET-THUNKS-Test5-NEXT: 2 | return_adjustment::Ret2 *return_adjustment::Test5::foo()
+ // RET-THUNKS-Test5-NEXT: [return adjustment: 4 non-virtual]
+ // RET-THUNKS-Test5-NEXT: [this adjustment: -4 non-virtual]
+ // RET-THUNKS-Test5-NEXT: 3 | return_adjustment::Ret2 *return_adjustment::Test5::foo()
+ // RET-THUNKS-Test5-NEXT: [this adjustment: -4 non-virtual]
+
+ // RET-THUNKS-Test5: VFTable indices for 'return_adjustment::Test5' (1 entries).
+ // RET-THUNKS-Test5-NEXT: 2 | return_adjustment::Ret2 *return_adjustment::Test5::foo()
+
+ virtual Ret2* foo();
+};
+
+Test5 t5;
+
+struct Ret3 : this_adjustment::Test1 { };
+
+struct Test6 : Test1 {
+ virtual Ret3* foo();
+ // RET-THUNKS-Test6: VFTable for 'return_adjustment::Ret1' in 'return_adjustment::Test1' in 'return_adjustment::Test6' (4 entries).
+ // RET-THUNKS-Test6-NEXT: 0 | return_adjustment::Ret3 *return_adjustment::Test6::foo()
+ // RET-THUNKS-Test6-NEXT: [return adjustment: 4 non-virtual]
+ // RET-THUNKS-Test6-NEXT: 1 | void return_adjustment::Ret1::z()
+ // RET-THUNKS-Test6-NEXT: 2 | return_adjustment::Ret3 *return_adjustment::Test6::foo()
+ // RET-THUNKS-Test6-NEXT: 3 | return_adjustment::Ret3 *return_adjustment::Test6::foo()
+
+ // RET-THUNKS-Test6: VFTable indices for 'return_adjustment::Test6' (1 entries).
+ // RET-THUNKS-Test6-NEXT: 3 | return_adjustment::Ret3 *return_adjustment::Test6::foo()
+};
+
+Test6 t6;
+
+}
diff --git a/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp b/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp
index 5d430db..6fe12b0 100644
--- a/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp
+++ b/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp
@@ -1,5 +1,6 @@
-// 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: %clang_cc1 %s -fno-rtti -cxx-abi microsoft -triple=i386-pc-win32 -emit-llvm -fdump-vtable-layouts -o %t.ll > %t
+// RUN: FileCheck --check-prefix=EMITS-VFTABLE %s < %t.ll
+// RUN: FileCheck --check-prefix=NO-VFTABLE %s < %t.ll
// RUN: FileCheck --check-prefix=CHECK-A %s < %t
// RUN: FileCheck --check-prefix=CHECK-B %s < %t
// RUN: FileCheck --check-prefix=CHECK-C %s < %t
@@ -7,107 +8,245 @@
// RUN: FileCheck --check-prefix=CHECK-E %s < %t
// RUN: FileCheck --check-prefix=CHECK-F %s < %t
// RUN: FileCheck --check-prefix=CHECK-G %s < %t
+// RUN: FileCheck --check-prefix=CHECK-I %s < %t
+// RUN: FileCheck --check-prefix=CHECK-J %s < %t
+// RUN: FileCheck --check-prefix=CHECK-K %s < %t
+// RUN: FileCheck --check-prefix=CHECK-L %s < %t
+// RUN: FileCheck --check-prefix=CHECK-M %s < %t
+// RUN: FileCheck --check-prefix=CHECK-N %s < %t
struct A {
- // CHECK-A: Vtable for 'A' (3 entries)
+ // CHECK-A: VFTable 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*]
+ // CHECK-A: VFTable indices 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()
+
virtual void f();
virtual void g();
virtual void h();
int ia;
};
-void A::f() {}
+A a;
+// EMITS-VFTABLE-DAG: @"\01??_7A@@6B@" = linkonce_odr unnamed_addr constant [3 x i8*]
struct B : A {
- // CHECK-B: Vtable for 'B' (5 entries)
+ // CHECK-B: VFTable for 'A' in '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*]
+ // CHECK-B: VFTable indices for 'B' (3 entries)
+ // CHECK-B-NEXT: 0 | void B::f()
+ // CHECK-B-NEXT: 3 | void B::i()
+ // CHECK-B-NEXT: 4 | void B::j()
+
virtual void f(); // overrides A::f()
virtual void i();
virtual void j();
};
-void B::f() {}
+B b;
+// EMITS-VFTABLE-DAG: @"\01??_7B@@6B@" = linkonce_odr unnamed_addr constant [5 x i8*]
struct C {
- // CHECK-C: Vtable for 'C' (2 entries)
+ // CHECK-C: VFTable 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: VFTable 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 ~C();
virtual void f();
};
void C::f() {}
+// NO-VFTABLE-NOT: @"\01??_7C@@6B@"
struct D {
- // CHECK-D: Vtable for 'D' (2 entries)
+ // CHECK-D: VFTable for 'D' (2 entries)
+ // CHECK-D-NEXT: 0 | void D::f()
+ // CHECK-D-NEXT: 1 | D::~D() [scalar deleting]
+ // CHECK-D: VFTable indices 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 void f();
virtual ~D();
};
-void D::f() {}
+D d;
+// EMITS-VFTABLE-DAG: @"\01??_7D@@6B@" = linkonce_odr unnamed_addr constant [2 x i8*]
struct E : A {
- // CHECK-E: Vtable for 'E' (5 entries)
+ // CHECK-E: VFTable for 'A' in '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: VFTable 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.
+ // ~E would be the key method, but it isn't used, and MS ABI has no key
+ // methods.
virtual ~E();
virtual void i();
};
void E::i() {}
+// NO-VFTABLE-NOT: @"\01??_7E@@6B@"
struct F : A {
- // CHECK-F: Vtable for 'F' (5 entries)
+ // CHECK-F: VFTable for 'A' in '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: VFTable 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() {}
+F f;
+// EMITS-VFTABLE-DAG: @"\01??_7F@@6B@" = linkonce_odr unnamed_addr constant [5 x i8*]
struct G : E {
- // CHECK-G: Vtable for 'G' (6 entries)
+ // CHECK-G: VFTable for 'A' in 'E' in '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: VFTable 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() {}
+// NO-VFTABLE-NOT: @"\01??_7G@@6B@"
+
+// Test that the usual Itanium-style key method does not emit a vtable.
+struct H {
+ virtual void f();
+};
+void H::f() {}
+// NO-VFTABLE-NOT: @"\01??_7H@@6B@"
+
+struct Empty { };
+
+struct I : Empty {
+ // CHECK-I: VFTable for 'I' (2 entries)
+ // CHECK-I-NEXT: 0 | void I::f()
+ // CHECK-I-NEXT: 1 | void I::g()
+ virtual void f();
+ virtual void g();
+};
+
+I i;
+
+struct J {
+ // CHECK-J: VFTable for 'J' (6 entries)
+ // CHECK-J-NEXT: 0 | void J::foo(long)
+ // CHECK-J-NEXT: 1 | void J::foo(int)
+ // CHECK-J-NEXT: 2 | void J::foo(short)
+ // CHECK-J-NEXT: 3 | void J::bar(long)
+ // CHECK-J-NEXT: 4 | void J::bar(int)
+ // CHECK-J-NEXT: 5 | void J::bar(short)
+ virtual void foo(short);
+ virtual void bar(short);
+ virtual void foo(int);
+ virtual void bar(int);
+ virtual void foo(long);
+ virtual void bar(long);
+};
+
+J j;
+
+struct K : J {
+ // CHECK-K: VFTable for 'J' in 'K' (9 entries)
+ // CHECK-K-NEXT: 0 | void J::foo(long)
+ // CHECK-K-NEXT: 1 | void J::foo(int)
+ // CHECK-K-NEXT: 2 | void J::foo(short)
+ // CHECK-K-NEXT: 3 | void J::bar(long)
+ // CHECK-K-NEXT: 4 | void J::bar(int)
+ // CHECK-K-NEXT: 5 | void J::bar(short)
+ // CHECK-K-NEXT: 6 | void K::bar(double)
+ // CHECK-K-NEXT: 7 | void K::bar(float)
+ // CHECK-K-NEXT: 8 | void K::foo(float)
+ virtual void bar(float);
+ virtual void foo(float);
+ virtual void bar(double);
+};
+
+K k;
+
+struct L : J {
+ // CHECK-L: VFTable for 'J' in 'L' (9 entries)
+ // CHECK-L-NEXT: 0 | void J::foo(long)
+ // CHECK-L-NEXT: 1 | void L::foo(int)
+ // CHECK-L-NEXT: 2 | void J::foo(short)
+ // CHECK-L-NEXT: 3 | void J::bar(long)
+ // CHECK-L-NEXT: 4 | void J::bar(int)
+ // CHECK-L-NEXT: 5 | void J::bar(short)
+ // CHECK-L-NEXT: 6 | void L::foo(float)
+ // CHECK-L-NEXT: 7 | void L::bar(double)
+ // CHECK-L-NEXT: 8 | void L::bar(float)
+
+ // This case is interesting. Since the J::foo(int) override is the first method in
+ // the class, foo(float) precedes the bar(double) and bar(float) in the vftable.
+ virtual void foo(int);
+ virtual void bar(float);
+ virtual void foo(float);
+ virtual void bar(double);
+};
+
+L l;
+
+struct M : J {
+ // CHECK-M: VFTable for 'J' in 'M' (11 entries)
+ // CHECK-M-NEXT: 0 | void J::foo(long)
+ // CHECK-M-NEXT: 1 | void M::foo(int)
+ // CHECK-M-NEXT: 2 | void J::foo(short)
+ // CHECK-M-NEXT: 3 | void J::bar(long)
+ // CHECK-M-NEXT: 4 | void J::bar(int)
+ // CHECK-M-NEXT: 5 | void J::bar(short)
+ // CHECK-M-NEXT: 6 | void M::foo(float)
+ // CHECK-M-NEXT: 7 | void M::spam(long)
+ // CHECK-M-NEXT: 8 | void M::spam(int)
+ // CHECK-M-NEXT: 9 | void M::bar(double)
+ // CHECK-M-NEXT: 10 | void M::bar(float)
+
+ virtual void foo(int);
+ virtual void spam(int);
+ virtual void bar(float);
+ virtual void bar(double);
+ virtual void foo(float);
+ virtual void spam(long);
+};
+
+M m;
+
+struct N {
+ // CHECK-N: VFTable for 'N' (4 entries)
+ // CHECK-N-NEXT: 0 | void N::operator+(int)
+ // CHECK-N-NEXT: 1 | void N::operator+(short)
+ // CHECK-N-NEXT: 2 | void N::operator*(int)
+ // CHECK-N-NEXT: 3 | void N::operator*(short)
+ virtual void operator+(short);
+ virtual void operator*(short);
+ virtual void operator+(int);
+ virtual void operator*(int);
+};
+
+N n;
diff --git a/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance-vtordisps.cpp b/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance-vtordisps.cpp
new file mode 100644
index 0000000..3fef0e4
--- /dev/null
+++ b/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance-vtordisps.cpp
@@ -0,0 +1,324 @@
+// RUN: %clang_cc1 -fno-rtti -emit-llvm -fdump-vtable-layouts %s -o %t.ll -cxx-abi microsoft -triple=i386-pc-win32 >%t
+// RUN: FileCheck --check-prefix=VTABLE-SIMPLE-A %s < %t
+// RUN: FileCheck --check-prefix=VTABLE-SIMPLE-B %s < %t
+// RUN: FileCheck --check-prefix=VTABLE-SIMPLE-C %s < %t
+// RUN: FileCheck --check-prefix=VTABLE-EXTENDED-A %s < %t
+// RUN: FileCheck --check-prefix=VTABLE-EXTENDED-B %s < %t
+// RUN: FileCheck --check-prefix=VTABLE-EXTENDED-C %s < %t
+// RUN: FileCheck --check-prefix=VTABLE-EXTENDED-E %s < %t
+// RUN: FileCheck --check-prefix=VTABLE-EXTENDED-F %s < %t
+// RUN: FileCheck --check-prefix=VTABLE-EXTENDED-G %s < %t
+// RUN: FileCheck --check-prefix=VTABLE-EXTENDED-H %s < %t
+// RUN: FileCheck --check-prefix=VTABLE-PR17738-A %s < %t
+// RUN: FileCheck --check-prefix=MANGLING %s < %t.ll
+
+// For now, just make sure x86_64 doesn't crash.
+// RUN: %clang_cc1 -fno-rtti -emit-llvm-only -fdump-vtable-layouts %s -cxx-abi microsoft -triple=x86_64-pc-win32 >/dev/null
+
+struct V1 {
+ virtual void f();
+ virtual ~V1();
+};
+
+struct V2 {
+ virtual void f();
+ virtual ~V2();
+ int v;
+};
+
+struct Z {
+ virtual void g();
+ virtual ~Z();
+ int x;
+};
+
+struct V3 : Z, V2 {
+};
+
+struct V4 : Z, V1, V2 {
+ int y;
+};
+
+void use_somewhere_else(void*);
+
+namespace simple {
+// In case of a single-layer virtual inheritance, the "this" adjustment is done
+// staically:
+// struct A {
+// virtual void f(); // Expects "(A*)this" in ECX
+// };
+// struct B : virtual A {
+// virtual void f(); // Expects "(char*)(B*)this + 12" in ECX
+// virtual ~B(); // Might call f()
+// };
+//
+// If a class overrides a virtual function of its base and has a non-trivial
+// ctor/dtor that call(s) the virtual function (or may escape "this" to some
+// code that might call it), a virtual adjustment might be needed in case the
+// current class layout and the most derived class layout are different.
+// This is done using vtordisp thunks.
+//
+// A simple vtordisp{A,B} thunk for Method@Class is something like:
+// sub ecx, [ecx+A] // apply the vtordisp adjustment
+// sub ecx, B // apply the subobject adjustment, if needed.
+// jmp Method@Class
+
+struct A : virtual V1 {
+ // VTABLE-SIMPLE-A: VFTable for 'V1' in 'simple::A' (2 entries).
+ // VTABLE-SIMPLE-A-NEXT: 0 | void simple::A::f()
+ // VTABLE-SIMPLE-A-NEXT: [this adjustment: vtordisp at -4, 0 non-virtual]
+ // VTABLE-SIMPLE-A-NEXT: 1 | simple::A::~A() [scalar deleting]
+ // VTABLE-SIMPLE-A-NEXT: [this adjustment: vtordisp at -4, 0 non-virtual]
+
+ virtual void f();
+ // MANGLING-DAG: @"\01?f@A@simple@@$4PPPPPPPM@A@AEXXZ"
+
+ virtual ~A();
+ // MANGLING-DAG: @"\01??_EA@simple@@$4PPPPPPPM@A@AEPAXI@Z"
+};
+
+A a;
+
+struct B : virtual V3 {
+ // VTABLE-SIMPLE-B: VFTable for 'Z' in 'V3' in 'simple::B' (2 entries).
+ // VTABLE-SIMPLE-B-NEXT: 0 | void Z::g()
+ // VTABLE-SIMPLE-B-NEXT: 1 | simple::B::~B() [scalar deleting]
+ // VTABLE-SIMPLE-B-NEXT: [this adjustment: vtordisp at -4, 0 non-virtual]
+
+ // VTABLE-SIMPLE-B: VFTable for 'V2' in 'V3' in 'simple::B' (2 entries).
+ // VTABLE-SIMPLE-B-NEXT: 0 | void simple::B::f()
+ // VTABLE-SIMPLE-B-NEXT: [this adjustment: vtordisp at -12, 0 non-virtual]
+ // VTABLE-SIMPLE-B-NEXT: 1 | simple::B::~B() [scalar deleting]
+ // VTABLE-SIMPLE-B-NEXT: [this adjustment: vtordisp at -12, -8 non-virtual]
+
+ // FIXME: The vtordisp thunk should only get emitted for a constructor
+ // if "this" leaves scope.
+ B() { use_somewhere_else(this); }
+
+ virtual void f();
+ // MANGLING-DAG: @"\01?f@B@simple@@$4PPPPPPPE@A@AEXXZ"
+
+ // Has an implicit destructor.
+ // MANGLING-DAG: @"\01??_EB@simple@@$4PPPPPPPE@7AEPAXI@Z"
+ // MANGLING-DAG: @"\01??_EB@simple@@$4PPPPPPPM@A@AEPAXI@Z"
+};
+
+B b;
+
+struct C : virtual V4 {
+ // VTABLE-SIMPLE-C: VFTable for 'Z' in 'V4' in 'simple::C' (2 entries).
+ // VTABLE-SIMPLE-C-NEXT: 0 | void Z::g()
+ // VTABLE-SIMPLE-C-NEXT: 1 | simple::C::~C() [scalar deleting]
+ // VTABLE-SIMPLE-C-NEXT: [this adjustment: vtordisp at -4, 0 non-virtual]
+
+ // VTABLE-SIMPLE-C: VFTable for 'V1' in 'V4' in 'simple::C' (2 entries).
+ // VTABLE-SIMPLE-C-NEXT: 0 | void simple::C::f()
+ // VTABLE-SIMPLE-C-NEXT: [this adjustment: vtordisp at -12, 0 non-virtual]
+ // VTABLE-SIMPLE-C-NEXT: 1 | simple::C::~C() [scalar deleting]
+ // VTABLE-SIMPLE-C-NEXT: [this adjustment: vtordisp at -12, -8 non-virtual]
+
+ // VTABLE-SIMPLE-C: VFTable for 'V2' in 'V4' in 'simple::C' (2 entries).
+ // VTABLE-SIMPLE-C-NEXT: 0 | void simple::C::f()
+ // VTABLE-SIMPLE-C-NEXT: [this adjustment: vtordisp at -16, -4 non-virtual]
+ // VTABLE-SIMPLE-C-NEXT: 1 | simple::C::~C() [scalar deleting]
+ // VTABLE-SIMPLE-C-NEXT: [this adjustment: vtordisp at -16, -12 non-virtual]
+
+ int x;
+ virtual void f();
+ // MANGLING-DAG: @"\01?f@C@simple@@$4PPPPPPPA@3AEXXZ"
+ // MANGLING-DAG: @"\01?f@C@simple@@$4PPPPPPPE@A@AEXXZ"
+ virtual ~C();
+ // MANGLING-DAG: @"\01??_EC@simple@@$4PPPPPPPA@M@AEPAXI@Z"
+ // MANGLING-DAG: @"\01??_EC@simple@@$4PPPPPPPE@7AEPAXI@Z"
+ // MANGLING-DAG: @"\01??_EC@simple@@$4PPPPPPPM@A@AEPAXI@Z"
+};
+
+C c;
+}
+
+namespace extended {
+// If a virtual function requires vtordisp adjustment and the final overrider
+// is defined in another vitual base of the most derived class,
+// we need to know two vbase offsets.
+// In this case, we should use the extended form of vtordisp thunks, called
+// vtordispex thunks.
+//
+// vtordispex{A,B,C,D} thunk for Method@Class is something like:
+// sub ecx, [ecx+C] // apply the vtordisp adjustment
+// sub ecx, A // jump to the vbtable of the most derived class
+// mov eax, [ecx] // load the vbtable address
+// add ecx, [eax+B] // lookup the final overrider's vbase offset
+// add ecx, D // apphy the subobject offset if needed
+// jmp Method@Class
+
+struct A : virtual simple::A {
+ // VTABLE-EXTENDED-A: VFTable for 'V1' in 'simple::A' in 'extended::A' (2 entries).
+ // VTABLE-EXTENDED-A-NEXT: 0 | void simple::A::f()
+ // VTABLE-EXTENDED-A-NEXT: [this adjustment: vtordisp at -4, vbptr at 8 to the left,
+ // VTABLE-EXTENDED-A-NEXT: vboffset at 8 in the vbtable, 8 non-virtual]
+ // VTABLE-EXTENDED-A-NEXT: 1 | extended::A::~A() [scalar deleting]
+ // VTABLE-EXTENDED-A-NEXT: [this adjustment: vtordisp at -4, 0 non-virtual]
+
+ // `vtordispex{8,8,4294967292,8}'
+ // MANGLING-DAG: @"\01?f@A@simple@@$R477PPPPPPPM@7AEXXZ"
+
+ virtual ~A();
+ // vtordisp{4294967292,0}
+ // MANGLING-DAG: @"\01??_EA@extended@@$4PPPPPPPM@A@AEPAXI@Z"
+};
+
+A a;
+
+struct B : virtual simple::A {
+ // This class has an implicit dtor. Vdtors don't require vtordispex thunks
+ // as the most derived class always has an implicit dtor,
+ // which is a final overrider.
+
+ // VTABLE-EXTENDED-B: VFTable for 'V1' in 'simple::A' in 'extended::B' (2 entries).
+ // ...
+ // VTABLE-EXTENDED-B: 1 | extended::B::~B() [scalar deleting]
+ // VTABLE-EXTENDED-B-NEXT: [this adjustment: vtordisp at -4, 0 non-virtual]
+
+ // vtordisp{4294967292,0}
+ // MANGLING-DAG: @"\01??_EB@extended@@$4PPPPPPPM@A@AEPAXI@Z"
+};
+
+B b;
+
+struct C : virtual simple::A {
+ // VTABLE-EXTENDED-C: VFTable for 'V1' in 'simple::A' in 'extended::C' (2 entries).
+ // VTABLE-EXTENDED-C-NEXT: 0 | void simple::A::f()
+ // VTABLE-EXTENDED-C-NEXT: [this adjustment: vtordisp at -4, vbptr at 12 to the left,
+ // VTABLE-EXTENDED-C-NEXT: vboffset at 8 in the vbtable, 8 non-virtual]
+
+ // `vtordispex{12,8,4294967292,8}'
+ // MANGLING-DAG: @"\01?f@A@simple@@$R4M@7PPPPPPPM@7AEXXZ"
+ int x;
+ virtual ~C();
+ // MANGLING-DAG: @"\01??_EC@extended@@$4PPPPPPPM@A@AEPAXI@Z"
+};
+
+C c;
+
+struct D : virtual V2 {
+ virtual void f();
+ virtual ~D();
+ int x;
+};
+
+struct E : virtual D {
+ // VTABLE-EXTENDED-E: VFTable for 'V2' in 'extended::D' in 'extended::E' (2 entries).
+ // VTABLE-EXTENDED-E-NEXT: 0 | void extended::D::f()
+ // VTABLE-EXTENDED-E-NEXT: [this adjustment: vtordisp at -4, vbptr at 8 to the left,
+ // VTABLE-EXTENDED-E-NEXT: vboffset at 8 in the vbtable, 12 non-virtual]
+
+ // `vtordispex{8,8,4294967292,12}'
+ // MANGLING-DAG: @"\01?f@D@extended@@$R477PPPPPPPM@M@AEXXZ"
+
+ virtual ~E();
+ // MANGLING-DAG: @"\01??_EE@extended@@$4PPPPPPPM@A@AEPAXI@Z"
+};
+
+E e;
+
+struct F : virtual Z, virtual D {
+ // VTABLE-EXTENDED-F: VFTable for 'V2' in 'extended::D' in 'extended::F' (2 entries).
+ // VTABLE-EXTENDED-F-NEXT: 0 | void extended::D::f()
+ // VTABLE-EXTENDED-F-NEXT: [this adjustment: vtordisp at -4, vbptr at 20 to the left,
+ // VTABLE-EXTENDED-F-NEXT: vboffset at 12 in the vbtable, 12 non-virtual]
+
+ // `vtordispex{20,12,4294967292,12}'
+ // MANGLING-DAG: @"\01?f@D@extended@@$R4BE@M@PPPPPPPM@M@AEXXZ"
+ int x;
+ virtual ~F();
+ // MANGLING-DAG: @"\01??_EF@extended@@$4PPPPPPPM@M@AEPAXI@Z"
+};
+
+F f;
+
+struct G : virtual simple::A {
+ // VTABLE-EXTENDED-G: VFTable for 'extended::G' (1 entries).
+ // VTABLE-EXTENDED-G-NEXT: 0 | void extended::G::g()
+
+ // VTABLE-EXTENDED-G: VFTable for 'V1' in 'simple::A' in 'extended::G' (2 entries).
+ // VTABLE-EXTENDED-G-NEXT: 0 | void simple::A::f()
+ // VTABLE-EXTENDED-G-NEXT: [this adjustment: vtordisp at -4, vbptr at 8 to the left,
+ // VTABLE-EXTENDED-G-NEXT: vboffset at 8 in the vbtable, 8 non-virtual]
+ // VTABLE-EXTENDED-G-NEXT: 1 | extended::G::~G() [scalar deleting]
+ // VTABLE-EXTENDED-G-NEXT: [this adjustment: vtordisp at -4, 0 non-virtual]
+
+ // Emits a G's own vfptr, thus moving the vbptr in the layout.
+ virtual void g();
+
+ virtual ~G();
+ // vtordisp{4294967292,0}
+ // MANGLING-DAG: @"\01??_EG@extended@@$4PPPPPPPM@A@AEPAXI@Z"
+};
+
+G g;
+
+struct H : Z, A {
+ // VTABLE-EXTENDED-H: VFTable for 'Z' in 'extended::H' (2 entries).
+ // VTABLE-EXTENDED-H-NEXT: 0 | void Z::g()
+ // VTABLE-EXTENDED-H-NEXT: 1 | extended::H::~H() [scalar deleting]
+
+ // VTABLE-EXTENDED-H: VFTable for 'V1' in 'simple::A' in 'extended::A' in 'extended::H' (2 entries).
+ // VTABLE-EXTENDED-H-NEXT: 0 | void simple::A::f()
+ // VTABLE-EXTENDED-H-NEXT: [this adjustment: vtordisp at -4, vbptr at 8 to the left,
+ // VTABLE-EXTENDED-H-NEXT: vboffset at 8 in the vbtable, 8 non-virtual]
+
+ // MANGLING-DAG: @"\01?f@A@simple@@$R477PPPPPPPM@7AEXXZ"
+ // MANGLING-DAG: @"\01??_EH@extended@@$4PPPPPPPM@BA@AEPAXI@Z"
+};
+
+H h;
+}
+
+namespace pr17738 {
+// These classes should have vtordispex thunks but MSVS CL miscompiles them.
+// Just do the right thing.
+
+struct A : virtual simple::B {
+ // VTABLE-PR17738-A: VFTable for 'V2' in 'V3' in 'simple::B' in 'pr17738::A' (2 entries).
+ // VTABLE-PR17738-A-NEXT: 0 | void simple::B::f()
+ // VTABLE-PR17738-A-NEXT: [this adjustment: vtordisp at -12, vbptr at 20 to the left,
+ // VTABLE-PR17738-A-NEXT: vboffset at 8 in the vbtable, 16 non-virtual]
+
+ // MANGLING-DAG: @"\01?f@B@simple@@$R4BE@7PPPPPPPE@BA@AEXXZ"
+ int a;
+ virtual ~A();
+};
+
+A a;
+}
+
+namespace access {
+struct A {
+ virtual ~A();
+protected:
+ virtual void prot();
+private:
+ virtual void priv();
+};
+
+struct B : virtual A {
+ virtual ~B();
+protected:
+ virtual void prot();
+ // MANGLING-DAG: @"\01?prot@B@access@@$2PPPPPPPM@A@AEXXZ"
+private:
+ virtual void priv();
+ // MANGLING-DAG: @"\01?priv@B@access@@$0PPPPPPPM@A@AEXXZ"
+};
+
+B b;
+
+struct C : virtual B {
+ virtual ~C();
+
+ // MANGLING-DAG: @"\01?prot@B@access@@$R277PPPPPPPM@7AEXXZ"
+ // MANGLING-DAG: @"\01?priv@B@access@@$R077PPPPPPPM@7AEXXZ"
+};
+
+C c;
+}
diff --git a/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp b/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp
new file mode 100644
index 0000000..b58a0b1
--- /dev/null
+++ b/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp
@@ -0,0 +1,575 @@
+// RUN: %clang_cc1 -fno-rtti -emit-llvm -o %t.ll -fdump-vtable-layouts %s -cxx-abi microsoft -triple=i386-pc-win32 >%t
+
+// RUN: FileCheck --check-prefix=VTABLE-C %s < %t
+// RUN: FileCheck --check-prefix=VTABLE-D %s < %t
+// RUN: FileCheck --check-prefix=TEST1 %s < %t
+// RUN: FileCheck --check-prefix=TEST2 %s < %t
+// RUN: FileCheck --check-prefix=TEST3 %s < %t
+// RUN: FileCheck --check-prefix=TEST4 %s < %t
+// RUN: FileCheck --check-prefix=TEST5 %s < %t
+// RUN: FileCheck --check-prefix=TEST6 %s < %t
+// RUN: FileCheck --check-prefix=TEST7 %s < %t
+// RUN: FileCheck --check-prefix=TEST8-X %s < %t
+// RUN: FileCheck --check-prefix=TEST8-Z %s < %t
+// RUN: FileCheck --check-prefix=TEST9-Y %s < %t
+// RUN: FileCheck --check-prefix=TEST9-Z %s < %t
+// RUN: FileCheck --check-prefix=TEST9-W %s < %t
+// RUN: FileCheck --check-prefix=TEST9-T %s < %t
+// RUN: FileCheck --check-prefix=TEST10 %s < %t
+// RUN: FileCheck --check-prefix=VDTORS-Y %s < %t
+// RUN: FileCheck --check-prefix=VDTORS-U %s < %t
+// RUN: FileCheck --check-prefix=VDTORS-V %s < %t
+// RUN: FileCheck --check-prefix=VDTORS-P %s < %t
+// RUN: FileCheck --check-prefix=RET-W %s < %t
+// RUN: FileCheck --check-prefix=RET-T %s < %t
+// RUN: FileCheck --check-prefix=RET-V %s < %t
+
+// RUN: FileCheck --check-prefix=MANGLING %s < %t.ll
+
+struct Empty { };
+
+struct A {
+ virtual void f();
+ virtual void z(); // Useful to check there are no thunks for f() when appropriate.
+};
+
+struct B {
+ virtual void g();
+};
+
+struct C: virtual A {
+ // VTABLE-C: VFTable for 'A' in 'C' (2 entries)
+ // VTABLE-C-NEXT: 0 | void C::f()
+ // VTABLE-C-NEXT: 1 | void A::z()
+
+ // VTABLE-C: VFTable indices for 'C' (1 entries)
+ // VTABLE-C-NEXT: vbtable index 1, vfptr at offset 0
+ // VTABLE-C-NEXT: 0 | void C::f()
+
+ // MANGLING-DAG: @"\01??_7C@@6B@"
+
+ virtual void f();
+};
+
+C c;
+
+struct D: virtual A {
+ // VTABLE-D: VFTable for 'D' (1 entries).
+ // VTABLE-D-NEXT: 0 | void D::h()
+
+ // VTABLE-D: VFTable for 'A' in 'D' (2 entries).
+ // VTABLE-D-NEXT: 0 | void D::f()
+ // VTABLE-D-NEXT: 1 | void A::z()
+
+ // VTABLE-D: VFTable indices for 'D' (2 entries).
+ // VTABLE-D-NEXT: via vfptr at offset 0
+ // VTABLE-D-NEXT: 0 | void D::h()
+ // VTABLE-D-NEXT: via vbtable index 1, vfptr at offset 0
+ // VTABLE-D-NEXT: 0 | void D::f()
+
+ // MANGLING-DAG: @"\01??_7D@@6B0@@"
+ // MANGLING-DAG: @"\01??_7D@@6BA@@@"
+
+ virtual void f();
+ virtual void h();
+};
+
+void D::h() {}
+D d;
+
+namespace Test1 {
+
+struct X { int x; };
+
+// X and A get reordered in the layout since X doesn't have a vfptr while A has.
+struct Y : X, A { };
+// MANGLING-DAG: @"\01??_7Y@Test1@@6B@"
+
+struct Z : virtual Y {
+ // TEST1: VFTable for 'A' in 'Test1::Y' in 'Test1::Z' (2 entries).
+ // TEST1-NEXT: 0 | void A::f()
+ // TEST1-NEXT: 1 | void A::z()
+
+ // TEST1-NOT: VFTable indices for 'Test1::Z'
+
+ // MANGLING-DAG: @"\01??_7Z@Test1@@6B@"
+};
+
+Z z;
+}
+
+namespace Test2 {
+
+struct X: virtual A, virtual B {
+ // TEST2: VFTable for 'Test2::X' (1 entries).
+ // TEST2-NEXT: 0 | void Test2::X::h()
+
+ // TEST2: VFTable for 'A' in 'Test2::X' (2 entries).
+ // TEST2-NEXT: 0 | void A::f()
+ // TEST2-NEXT: 1 | void A::z()
+
+ // TEST2: VFTable for 'B' in 'Test2::X' (1 entries).
+ // TEST2-NEXT: 0 | void B::g()
+
+ // TEST2: VFTable indices for 'Test2::X' (1 entries).
+ // TEST2-NEXT: 0 | void Test2::X::h()
+
+ // MANGLING-DAG: @"\01??_7X@Test2@@6B01@@"
+ // MANGLING-DAG: @"\01??_7X@Test2@@6BA@@@"
+ // MANGLING-DAG: @"\01??_7X@Test2@@6BB@@@"
+
+ virtual void h();
+};
+
+X x;
+}
+
+namespace Test3 {
+
+struct X : virtual A {
+ // MANGLING-DAG: @"\01??_7X@Test3@@6B@"
+};
+
+struct Y: virtual X {
+ // TEST3: VFTable for 'A' in 'Test3::X' in 'Test3::Y' (2 entries).
+ // TEST3-NEXT: 0 | void A::f()
+ // TEST3-NEXT: 1 | void A::z()
+
+ // TEST3-NOT: VFTable indices for 'Test3::Y'
+
+ // MANGLING-DAG: @"\01??_7Y@Test3@@6B@"
+};
+
+Y y;
+}
+
+namespace Test4 {
+
+struct X: virtual C {
+ // This one's interesting. C::f expects (A*) to be passed as 'this' and does
+ // ECX-=4 to cast to (C*). In X, C and A vbases are reordered, so the thunk
+ // should pass a pointer to the end of X in order
+ // for ECX-=4 to point at the C part.
+
+ // TEST4: VFTable for 'A' in 'C' in 'Test4::X' (2 entries).
+ // TEST4-NEXT: 0 | void C::f()
+ // TEST4-NEXT: [this adjustment: 8 non-virtual]
+ // TEST4-NEXT: 1 | void A::z()
+
+ // TEST4-NOT: VFTable indices for 'Test4::X'
+
+ // MANGLING-DAG: @"\01??_7X@Test4@@6B@"
+
+ // Also check the mangling of the thunk.
+ // MANGLING-DAG: define weak x86_thiscallcc void @"\01?f@C@@WPPPPPPPI@AEXXZ"
+};
+
+X x;
+}
+
+namespace Test5 {
+
+// New methods are added to the base's vftable.
+struct X : A {
+ // MANGLING-DAG: @"\01??_7X@Test5@@6B@"
+ virtual void g();
+};
+
+struct Y : virtual X {
+ // TEST5: VFTable for 'Test5::Y' (1 entries).
+ // TEST5-NEXT: 0 | void Test5::Y::h()
+
+ // TEST5: VFTable for 'A' in 'Test5::X' in 'Test5::Y' (3 entries).
+ // TEST5-NEXT: 0 | void A::f()
+ // TEST5-NEXT: 1 | void A::z()
+ // TEST5-NEXT: 2 | void Test5::X::g()
+
+ // TEST5: VFTable indices for 'Test5::Y' (1 entries).
+ // TEST5-NEXT: 0 | void Test5::Y::h()
+
+ // MANGLING-DAG: @"\01??_7Y@Test5@@6B01@@"
+ // MANGLING-DAG: @"\01??_7Y@Test5@@6BX@1@@"
+
+ virtual void h();
+};
+
+Y y;
+}
+
+namespace Test6 {
+
+struct X : A, virtual Empty {
+ // TEST6: VFTable for 'A' in 'Test6::X' (2 entries).
+ // TEST6-NEXT: 0 | void A::f()
+ // TEST6-NEXT: 1 | void A::z()
+
+ // TEST6-NOT: VFTable indices for 'Test6::X'
+
+ // MANGLING-DAG: @"\01??_7X@Test6@@6B@"
+};
+
+X x;
+}
+
+namespace Test7 {
+
+struct X : C {
+ // MANGLING-DAG: @"\01??_7X@Test7@@6B@"
+};
+
+struct Y : virtual X {
+ // TEST7: VFTable for 'A' in 'C' in 'Test7::X' in 'Test7::Y' (2 entries).
+ // TEST7-NEXT: 0 | void C::f()
+ // TEST7-NEXT: [this adjustment: 8 non-virtual]
+ // TEST7-NEXT: 1 | void A::z()
+
+ // TEST7: Thunks for 'void C::f()' (1 entry).
+ // TEST7-NEXT: 0 | [this adjustment: 8 non-virtual]
+
+ // TEST7-NOT: VFTable indices for 'Test7::Y'
+
+ // MANGLING-DAG: @"\01??_7Y@Test7@@6B@"
+};
+
+Y y;
+}
+
+namespace Test8 {
+
+// This is a typical diamond inheritance with a shared 'A' vbase.
+struct X : D, C {
+ // TEST8-X: VFTable for 'D' in 'Test8::X' (1 entries).
+ // TEST8-X-NEXT: 0 | void D::h()
+
+ // TEST8-X: VFTable for 'A' in 'D' in 'Test8::X' (2 entries).
+ // TEST8-X-NEXT: 0 | void Test8::X::f()
+ // TEST8-X-NEXT: 1 | void A::z()
+
+ // TEST8-X: VFTable indices for 'Test8::X' (1 entries).
+ // TEST8-X-NEXT: via vbtable index 1, vfptr at offset 0
+ // TEST8-X-NEXT: 0 | void Test8::X::f()
+
+ // MANGLING-DAG: @"\01??_7X@Test8@@6BA@@@"
+ // MANGLING-DAG: @"\01??_7X@Test8@@6BD@@@"
+
+ virtual void f();
+};
+
+X x;
+
+// Another diamond inheritance which led to AST crashes.
+struct Y : virtual A {};
+
+class Z : Y, C {
+ // TEST8-Z: VFTable for 'A' in 'Test8::Y' in 'Test8::Z' (2 entries).
+ // TEST8-Z-NEXT: 0 | void Test8::Z::f()
+ // TEST8-Z-NEXT: 1 | void A::z()
+
+ // TEST8-Z: VFTable indices for 'Test8::Z' (1 entries).
+ // TEST8-Z-NEXT: via vbtable index 1, vfptr at offset 0
+ // TEST8-Z-NEXT: 0 | void Test8::Z::f()
+ virtual void f();
+};
+Z z;
+}
+
+namespace Test9 {
+
+struct X : A { };
+
+struct Y : virtual X {
+ // TEST9-Y: VFTable for 'Test9::Y' (1 entries).
+ // TEST9-Y-NEXT: 0 | void Test9::Y::h()
+
+ // TEST9-Y: VFTable for 'A' in 'Test9::X' in 'Test9::Y' (2 entries).
+ // TEST9-Y-NEXT: 0 | void A::f()
+ // TEST9-Y-NEXT: 1 | void A::z()
+
+ // TEST9-Y: VFTable indices for 'Test9::Y' (1 entries).
+ // TEST9-Y-NEXT: 0 | void Test9::Y::h()
+
+ // MANGLING-DAG: @"\01??_7Y@Test9@@6B01@@"
+ // MANGLING-DAG: @"\01??_7Y@Test9@@6BX@1@@"
+
+ virtual void h();
+};
+
+Y y;
+
+struct Z : Y, virtual B {
+ // TEST9-Z: VFTable for 'Test9::Y' in 'Test9::Z' (1 entries).
+ // TEST9-Z-NEXT: 0 | void Test9::Y::h()
+
+ // TEST9-Z: VFTable for 'A' in 'Test9::X' in 'Test9::Y' in 'Test9::Z' (2 entries).
+ // TEST9-Z-NEXT: 0 | void A::f()
+ // TEST9-Z-NEXT: 1 | void A::z()
+
+ // TEST9-Z: VFTable for 'B' in 'Test9::Z' (1 entries).
+ // TEST9-Z-NEXT: 0 | void B::g()
+
+ // TEST9-Z-NOT: VFTable indices for 'Test9::Z'
+
+ // MANGLING-DAG: @"\01??_7Z@Test9@@6BX@1@@"
+ // MANGLING-DAG: @"\01??_7Z@Test9@@6BY@1@@"
+
+ // FIXME this one is wrong:
+ // INCORRECT MANGLING-DAG: @"\01??_7Z@Test9@@6BB@@@"
+ // MANGLING-DAG-SHOULD-BE: @"\01??_7Z@Test9@@6B@"
+};
+
+Z z;
+
+struct W : Z, D, virtual A, virtual B {
+ // TEST9-W: VFTable for 'Test9::Y' in 'Test9::Z' in 'Test9::W' (1 entries).
+ // TEST9-W-NEXT: 0 | void Test9::Y::h()
+
+ // TEST9-W: VFTable for 'A' in 'Test9::X' in 'Test9::Y' in 'Test9::Z' in 'Test9::W' (2 entries).
+ // TEST9-W-NEXT: 0 | void A::f()
+ // TEST9-W-NEXT: 1 | void A::z()
+
+ // TEST9-W: VFTable for 'B' in 'Test9::Z' in 'Test9::W' (1 entries).
+ // TEST9-W-NEXT: 0 | void B::g()
+
+ // TEST9-W: VFTable for 'D' in 'Test9::W' (1 entries).
+ // TEST9-W-NEXT: 0 | void D::h()
+
+ // TEST9-W: VFTable for 'A' in 'D' in 'Test9::W' (2 entries).
+ // TEST9-W-NEXT: 0 | void D::f()
+ // TEST9-W-NEXT: [this adjustment: -8 non-virtual]
+ // TEST9-W-NEXT: 1 | void A::z()
+
+ // TEST9-W: Thunks for 'void D::f()' (1 entry).
+ // TEST9-W-NEXT: 0 | [this adjustment: -8 non-virtual]
+
+ // TEST9-W-NOT: VFTable indices for 'Test9::W'
+
+ // MANGLING-DAG: @"\01??_7W@Test9@@6BA@@@"
+ // MANGLING-DAG: @"\01??_7W@Test9@@6BD@@@"
+ // MANGLING-DAG: @"\01??_7W@Test9@@6BX@1@@"
+
+ // FIXME: these two are wrong:
+ // INCORRECT MANGLING-DAG: @"\01??_7W@Test9@@6BB@@@"
+ // MANGLING-DAG-SHOULD-BE: @"\01??_7W@Test9@@6B@"
+ // INCORRECT MANGLING-DAG: @"\01??_7W@Test9@@6BY@1@Z@1@@"
+ // MANGLING-DAG-SHOULD-BE: @"\01??_7W@Test9@@6BY@1@@"
+};
+
+W w;
+
+struct T : Z, D, virtual A, virtual B {
+ // TEST9-T: VFTable for 'Test9::Y' in 'Test9::Z' in 'Test9::T' (1 entries).
+ // TEST9-T-NEXT: 0 | void Test9::T::h()
+
+ // TEST9-T: VFTable for 'A' in 'Test9::X' in 'Test9::Y' in 'Test9::Z' in 'Test9::T' (2 entries).
+ // TEST9-T-NEXT: 0 | void Test9::T::f()
+ // TEST9-T-NEXT: 1 | void Test9::T::z()
+
+ // TEST9-T: VFTable for 'B' in 'Test9::Z' in 'Test9::T' (1 entries).
+ // TEST9-T-NEXT: 0 | void Test9::T::g()
+
+ // TEST9-T: VFTable for 'D' in 'Test9::T' (1 entries).
+ // TEST9-T-NEXT: 0 | void Test9::T::h()
+ // TEST9-T-NEXT: [this adjustment: -8 non-virtual]
+
+ // TEST9-T: Thunks for 'void Test9::T::h()' (1 entry).
+ // TEST9-T-NEXT: 0 | [this adjustment: -8 non-virtual]
+
+ // TEST9-T: VFTable for 'A' in 'D' in 'Test9::T' (2 entries).
+ // TEST9-T-NEXT: 0 | void Test9::T::f()
+ // TEST9-T-NEXT: [this adjustment: -8 non-virtual]
+ // TEST9-T-NEXT: 1 | void Test9::T::z()
+ // TEST9-T-NEXT: [this adjustment: -8 non-virtual]
+
+ // TEST9-T: Thunks for 'void Test9::T::f()' (1 entry).
+ // TEST9-T-NEXT: 0 | [this adjustment: -8 non-virtual]
+
+ // TEST9-T: Thunks for 'void Test9::T::z()' (1 entry).
+ // TEST9-T-NEXT: 0 | [this adjustment: -8 non-virtual]
+
+ // TEST9-T: VFTable indices for 'Test9::T' (4 entries).
+ // TEST9-T-NEXT: via vfptr at offset 0
+ // TEST9-T-NEXT: 0 | void Test9::T::h()
+ // TEST9-T-NEXT: via vbtable index 1, vfptr at offset 0
+ // TEST9-T-NEXT: 0 | void Test9::T::f()
+ // TEST9-T-NEXT: 1 | void Test9::T::z()
+ // TEST9-T-NEXT: via vbtable index 2, vfptr at offset 0
+ // TEST9-T-NEXT: 0 | void Test9::T::g()
+
+ // MANGLING-DAG: @"\01??_7T@Test9@@6BA@@@"
+ // MANGLING-DAG: @"\01??_7T@Test9@@6BD@@@"
+ // MANGLING-DAG: @"\01??_7T@Test9@@6BX@1@@"
+
+ // FIXME: these two are wrong:
+ // INCORRECT MANGLING-DAG: @"\01??_7T@Test9@@6BB@@@"
+ // MANGLING-DAG-SHOULD-BE: @"\01??_7T@Test9@@6B@"
+ // INCORRECT MANGLING-DAG: @"\01??_7T@Test9@@6BY@1@Z@1@@"
+ // MANGLING-DAG-SHOULD-BE: @"\01??_7T@Test9@@6BY@1@@"
+
+ virtual void f();
+ virtual void g();
+ virtual void h();
+ virtual void z();
+};
+
+T t;
+}
+
+namespace Test10 {
+struct X : virtual C, virtual A {
+ // TEST10: VFTable for 'A' in 'C' in 'Test10::X' (2 entries).
+ // TEST10-NEXT: 0 | void Test10::X::f()
+ // TEST10-NEXT: 1 | void A::z()
+
+ // TEST10: VFTable indices for 'Test10::X' (1 entries).
+ // TEST10-NEXT: via vbtable index 1, vfptr at offset 0
+ // TEST10-NEXT: 0 | void Test10::X::f()
+ virtual void f();
+};
+
+void X::f() {}
+X x;
+}
+
+namespace vdtors {
+struct X {
+ virtual ~X();
+ virtual void zzz();
+};
+
+struct Y : virtual X {
+ // VDTORS-Y: VFTable for 'vdtors::X' in 'vdtors::Y' (2 entries).
+ // VDTORS-Y-NEXT: 0 | vdtors::Y::~Y() [scalar deleting]
+ // VDTORS-Y-NEXT: 1 | void vdtors::X::zzz()
+
+ // VDTORS-Y-NOT: Thunks for 'vdtors::Y::~Y()'
+ virtual ~Y();
+};
+
+Y y;
+
+struct Z {
+ virtual void z();
+};
+
+struct W : Z, X {
+ // Implicit virtual dtor.
+};
+
+struct U : virtual W {
+ // VDTORS-U: VFTable for 'vdtors::Z' in 'vdtors::W' in 'vdtors::U' (1 entries).
+ // VDTORS-U-NEXT: 0 | void vdtors::Z::z()
+
+ // VDTORS-U: VFTable for 'vdtors::X' in 'vdtors::W' in 'vdtors::U' (2 entries).
+ // VDTORS-U-NEXT: 0 | vdtors::U::~U() [scalar deleting]
+ // VDTORS-U-NEXT: [this adjustment: -4 non-virtual]
+ // VDTORS-U-NEXT: 1 | void vdtors::X::zzz()
+
+ // VDTORS-U: Thunks for 'vdtors::W::~W()' (1 entry).
+ // VDTORS-U-NEXT: 0 | [this adjustment: -4 non-virtual]
+
+ // VDTORS-U: VFTable indices for 'vdtors::U' (1 entries).
+ // VDTORS-U-NEXT: -- accessible via vbtable index 1, vfptr at offset 4 --
+ // VDTORS-U-NEXT: 0 | vdtors::U::~U() [scalar deleting]
+ virtual ~U();
+};
+
+U u;
+
+struct V : virtual W {
+ // VDTORS-V: VFTable for 'vdtors::Z' in 'vdtors::W' in 'vdtors::V' (1 entries).
+ // VDTORS-V-NEXT: 0 | void vdtors::Z::z()
+
+ // VDTORS-V: VFTable for 'vdtors::X' in 'vdtors::W' in 'vdtors::V' (2 entries).
+ // VDTORS-V-NEXT: 0 | vdtors::V::~V() [scalar deleting]
+ // VDTORS-V-NEXT: [this adjustment: -4 non-virtual]
+ // VDTORS-V-NEXT: 1 | void vdtors::X::zzz()
+
+ // VDTORS-V: Thunks for 'vdtors::W::~W()' (1 entry).
+ // VDTORS-V-NEXT: 0 | [this adjustment: -4 non-virtual]
+
+ // VDTORS-V: VFTable indices for 'vdtors::V' (1 entries).
+ // VDTORS-V-NEXT: -- accessible via vbtable index 1, vfptr at offset 4 --
+ // VDTORS-V-NEXT: 0 | vdtors::V::~V() [scalar deleting]
+};
+
+V v;
+
+struct T : virtual X {
+ virtual ~T();
+};
+
+struct P : T, Y {
+ // VDTORS-P: VFTable for 'vdtors::X' in 'vdtors::T' in 'vdtors::P' (2 entries).
+ // VDTORS-P-NEXT: 0 | vdtors::P::~P() [scalar deleting]
+ // VDTORS-P-NEXT: 1 | void vdtors::X::zzz()
+
+ // VDTORS-P-NOT: Thunks for 'vdtors::P::~P()'
+ virtual ~P();
+};
+
+P p;
+
+}
+
+namespace return_adjustment {
+
+struct X : virtual A {
+ virtual void f();
+};
+
+struct Y : virtual A, virtual X {
+ virtual void f();
+};
+
+struct Z {
+ virtual A* foo();
+};
+
+struct W : Z {
+ // RET-W: VFTable for 'return_adjustment::Z' in 'return_adjustment::W' (2 entries).
+ // RET-W-NEXT: 0 | return_adjustment::X *return_adjustment::W::foo()
+ // RET-W-NEXT: [return adjustment: vbase #1, 0 non-virtual]
+ // RET-W-NEXT: 1 | return_adjustment::X *return_adjustment::W::foo()
+
+ // RET-W: VFTable indices for 'return_adjustment::W' (1 entries).
+ // RET-W-NEXT: 1 | return_adjustment::X *return_adjustment::W::foo()
+
+ virtual X* foo();
+};
+
+W y;
+
+struct T : W {
+ // RET-T: VFTable for 'return_adjustment::Z' in 'return_adjustment::W' in 'return_adjustment::T' (3 entries).
+ // RET-T-NEXT: 0 | return_adjustment::Y *return_adjustment::T::foo()
+ // RET-T-NEXT: [return adjustment: vbase #1, 0 non-virtual]
+ // RET-T-NEXT: 1 | return_adjustment::Y *return_adjustment::T::foo()
+ // RET-T-NEXT: [return adjustment: vbase #2, 0 non-virtual]
+ // RET-T-NEXT: 2 | return_adjustment::Y *return_adjustment::T::foo()
+
+ // RET-T: VFTable indices for 'return_adjustment::T' (1 entries).
+ // RET-T-NEXT: 2 | return_adjustment::Y *return_adjustment::T::foo()
+
+ virtual Y* foo();
+};
+
+T t;
+
+struct U : virtual A {
+ virtual void g(); // adds a vfptr
+};
+
+struct V : Z {
+ // RET-V: VFTable for 'return_adjustment::Z' in 'return_adjustment::V' (2 entries).
+ // RET-V-NEXT: 0 | return_adjustment::U *return_adjustment::V::foo()
+ // RET-V-NEXT: [return adjustment: vbptr at offset 4, vbase #1, 0 non-virtual]
+ // RET-V-NEXT: 1 | return_adjustment::U *return_adjustment::V::foo()
+
+ // RET-V: VFTable indices for 'return_adjustment::V' (1 entries).
+ // RET-V-NEXT: 1 | return_adjustment::U *return_adjustment::V::foo()
+
+ virtual U* foo();
+};
+
+V v;
+}
diff --git a/test/CodeGenCXX/microsoft-interface.cpp b/test/CodeGenCXX/microsoft-interface.cpp
index 0b44bab..419075a 100644
--- a/test/CodeGenCXX/microsoft-interface.cpp
+++ b/test/CodeGenCXX/microsoft-interface.cpp
@@ -19,25 +19,25 @@ int fn() {
// CHECK: @_ZTV1S = linkonce_odr unnamed_addr constant [3 x i8*] [i8* null, i8* bitcast ({ i8*, i8*, i8* }* @_ZTI1S to i8*), i8* bitcast (i32 (%struct.S*)* @_ZN1S4testEv to i8*)]
-// CHECK: define i32 @_Z2fnv()
+// CHECK-LABEL: define i32 @_Z2fnv()
// CHECK: call void @_ZN1SC1Ev(%struct.S* %s)
// CHECK: %{{[.0-9A-Z_a-z]+}} = call i32 @_ZN1S4testEv(%struct.S* %s)
-// CHECK: define linkonce_odr void @_ZN1SC1Ev(%struct.S* %this)
+// CHECK-LABEL: define linkonce_odr void @_ZN1SC1Ev(%struct.S* %this)
// CHECK: call void @_ZN1SC2Ev(%struct.S* %{{[.0-9A-Z_a-z]+}})
-// CHECK: define linkonce_odr i32 @_ZN1S4testEv(%struct.S* %this)
+// CHECK-LABEL: define linkonce_odr i32 @_ZN1S4testEv(%struct.S* %this)
// CHECK: %{{[.0-9A-Z_a-z]+}} = call i32 @_ZN1I4testEv(%__interface.I* %{{[.0-9A-Z_a-z]+}})
-// CHECK: define linkonce_odr i32 @_ZN1I4testEv(%__interface.I* %this)
+// CHECK-LABEL: define linkonce_odr i32 @_ZN1I4testEv(%__interface.I* %this)
// CHECK: ret i32 1
-// CHECK: define linkonce_odr void @_ZN1SC2Ev(%struct.S* %this)
+// CHECK-LABEL: define linkonce_odr void @_ZN1SC2Ev(%struct.S* %this)
// CHECK: call void @_ZN1IC2Ev(%__interface.I* %{{[.0-9A-Z_a-z]+}})
// CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTV1S, i64 0, i64 2), i8*** %{{[.0-9A-Z_a-z]+}}
-// CHECK: define linkonce_odr void @_ZN1IC2Ev(%__interface.I* %this)
+// CHECK-LABEL: define linkonce_odr void @_ZN1IC2Ev(%__interface.I* %this)
// CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTV1I, i64 0, i64 2), i8*** %{{[.0-9A-Z_a-z]+}}
-// CHECK-NOT: define linkonce_odr %__interface.I* @_ZN1IaSERKS_(%__interface.I* %this, %__interface.I*)
-// CHECK-NOT: define linkonce_odr %__interface.I* @_ZN1IaSEOS_(%__interface.I* %this, %__interface.I*)
+// CHECK-NOT-LABEL: define linkonce_odr %__interface.I* @_ZN1IaSERKS_(%__interface.I* %this, %__interface.I*)
+// CHECK-NOT-LABEL: define linkonce_odr %__interface.I* @_ZN1IaSEOS_(%__interface.I* %this, %__interface.I*)
diff --git a/test/CodeGenCXX/microsoft-new.cpp b/test/CodeGenCXX/microsoft-new.cpp
new file mode 100644
index 0000000..48e93d4
--- /dev/null
+++ b/test/CodeGenCXX/microsoft-new.cpp
@@ -0,0 +1,39 @@
+// RUN: %clang_cc1 -triple i686-pc-win32 -fms-compatibility %s -emit-llvm -o - | FileCheck %s
+
+#include <stddef.h>
+
+struct arbitrary_t {} arbitrary;
+void *operator new(size_t size, arbitrary_t);
+
+struct arbitrary2_t {} arbitrary2;
+void *operator new[](size_t size, arbitrary2_t);
+
+namespace PR13164 {
+ void f() {
+ // MSVC will fall back on the non-array operator new.
+ void *a;
+ int *p = new(arbitrary) int[4];
+ // CHECK: call i8* @_Znwj11arbitrary_t(i32 16, %struct.arbitrary_t*
+ }
+
+ struct S {
+ void *operator new[](size_t size, arbitrary_t);
+ };
+
+ void g() {
+ S *s = new(arbitrary) S[2];
+ // CHECK: call i8* @_ZN7PR131641SnaEj11arbitrary_t(i32 2, %struct.arbitrary_t*
+ S *s1 = new(arbitrary) S;
+ // CHECK: call i8* @_Znwj11arbitrary_t(i32 1, %struct.arbitrary_t*
+ }
+
+ struct T {
+ void *operator new(size_t size, arbitrary2_t);
+ };
+
+ void h() {
+ // This should still call the global operator new[].
+ T *t = new(arbitrary2) T[2];
+ // CHECK: call i8* @_Znaj12arbitrary2_t(i32 2, %struct.arbitrary2_t*
+ }
+}
diff --git a/test/CodeGenCXX/microsoft-uuidof-unsupported-target.cpp b/test/CodeGenCXX/microsoft-uuidof-unsupported-target.cpp
deleted file mode 100644
index 4f68aa3..0000000
--- a/test/CodeGenCXX/microsoft-uuidof-unsupported-target.cpp
+++ /dev/null
@@ -1,13 +0,0 @@
-// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-macosx10.8.0 -fms-extensions -verify
-
-typedef struct _GUID
-{
- unsigned long Data1;
- unsigned short Data2;
- unsigned short Data3;
- unsigned char Data4[8];
-} GUID;
-
-struct __declspec(uuid("87654321-4321-4321-4321-ba0987654321")) S { };
-
-GUID g = __uuidof(S); // expected-error {{__uuidof codegen is not supported on this architecture}}
diff --git a/test/CodeGenCXX/microsoft-uuidof.cpp b/test/CodeGenCXX/microsoft-uuidof.cpp
index 8eeb449..ab3d9b6 100644
--- a/test/CodeGenCXX/microsoft-uuidof.cpp
+++ b/test/CodeGenCXX/microsoft-uuidof.cpp
@@ -1,72 +1,112 @@
+// RUN: %clang_cc1 -emit-llvm %s -o - -DDEFINE_GUID -triple=i386-pc-win32 -fms-extensions | FileCheck %s --check-prefix=CHECK-DEFINE-GUID
// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 -fms-extensions | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm %s -o - -DDEFINE_GUID -DWRONG_GUID -triple=i386-pc-win32 -fms-extensions | FileCheck %s --check-prefix=CHECK-DEFINE-WRONG-GUID
-typedef struct _GUID
-{
+#ifdef DEFINE_GUID
+struct _GUID {
+#ifdef WRONG_GUID
+ unsigned int SomethingWentWrong;
+#else
unsigned long Data1;
unsigned short Data2;
unsigned short Data3;
unsigned char Data4[8];
-} GUID;
+#endif
+};
+#endif
+typedef struct _GUID GUID;
-struct __declspec(uuid("12345678-1234-1234-1234-1234567890ab")) S1 { } s1;
+struct __declspec(uuid("12345678-1234-1234-1234-1234567890aB")) S1 { } s1;
struct __declspec(uuid("87654321-4321-4321-4321-ba0987654321")) S2 { };
+struct __declspec(uuid("{12345678-1234-1234-1234-1234567890ac}")) Curly;
+
+#ifdef DEFINE_GUID
+// Make sure we can properly generate code when the UUID has curly braces on it.
+GUID thing = __uuidof(Curly);
+// CHECK-DEFINE-GUID: @thing = global %struct._GUID zeroinitializer, align 4
+// CHECK-DEFINE-WRONG-GUID: @thing = global %struct._GUID zeroinitializer, align 4
// This gets initialized in a static initializer.
-// CHECK: @g = global %struct._GUID zeroinitializer, align 4
+// CHECK-DEFINE-GUID: @g = global %struct._GUID zeroinitializer, align 4
+// CHECK-DEFINE-WRONG-GUID: @g = global %struct._GUID zeroinitializer, align 4
GUID g = __uuidof(S1);
+#endif
// First global use of __uuidof(S1) forces the creation of the global.
-// CHECK: @__uuid_12345678-1234-1234-1234-1234567890ab = private unnamed_addr constant %struct._GUID { i32 305419896, i16 4660, i16 4660, [8 x i8] c"\124\124Vx\90\AB" }
-// CHECK: @gr = constant %struct._GUID* @__uuid_12345678-1234-1234-1234-1234567890ab, align 4
+// CHECK: @_GUID_12345678_1234_1234_1234_1234567890ab = linkonce_odr constant { i32, i16, i16, [8 x i8] } { i32 305419896, i16 4660, i16 4660, [8 x i8] c"\124\124Vx\90\AB" }
+// CHECK: @gr = constant %struct._GUID* bitcast ({ i32, i16, i16, [8 x i8] }* @_GUID_12345678_1234_1234_1234_1234567890ab to %struct._GUID*), align 4
const GUID& gr = __uuidof(S1);
-// CHECK: @gp = global %struct._GUID* @__uuid_12345678-1234-1234-1234-1234567890ab, align 4
+// CHECK: @gp = global %struct._GUID* bitcast ({ i32, i16, i16, [8 x i8] }* @_GUID_12345678_1234_1234_1234_1234567890ab to %struct._GUID*), align 4
const GUID* gp = &__uuidof(S1);
+// CHECK: @cp = global %struct._GUID* bitcast ({ i32, i16, i16, [8 x i8] }* @_GUID_12345678_1234_1234_1234_1234567890ac to %struct._GUID*), align 4
+const GUID* cp = &__uuidof(Curly);
+
// Special case: _uuidof(0)
-// CHECK: @zeroiid = constant %struct._GUID* @__uuid_00000000-0000-0000-0000-000000000000, align 4
+// CHECK: @zeroiid = constant %struct._GUID* bitcast ({ i32, i16, i16, [8 x i8] }* @_GUID_00000000_0000_0000_0000_000000000000 to %struct._GUID*), align 4
const GUID& zeroiid = __uuidof(0);
// __uuidof(S2) hasn't been used globally yet, so it's emitted when it's used
// in a function and is emitted at the end of the globals section.
-// CHECK: @__uuid_87654321-4321-4321-4321-ba0987654321 = private unnamed_addr constant %struct._GUID { i32 -2023406815, i16 17185, i16 17185, [8 x i8] c"C!\BA\09\87eC!" }
+// CHECK: @_GUID_87654321_4321_4321_4321_ba0987654321 = linkonce_odr constant { i32, i16, i16, [8 x i8] } { i32 -2023406815, i16 17185, i16 17185, [8 x i8] c"C!\BA\09\87eC!" }
+
+// The static initializer for thing.
+// CHECK-DEFINE-GUID: call void @llvm.memcpy.p0i8.p0i8.i32(i8* bitcast (%struct._GUID* @thing to i8*), i8* bitcast ({ i32, i16, i16, [8 x i8] }* @_GUID_12345678_1234_1234_1234_1234567890ac to i8*), i32 16, i32 4, i1 false)
+// CHECK-DEFINE-WRONG-GUID: call void @llvm.memcpy.p0i8.p0i8.i32(i8* bitcast (%struct._GUID* @thing to i8*), i8* bitcast ({ i32, i16, i16, [8 x i8] }* @_GUID_12345678_1234_1234_1234_1234567890ac to i8*), i32 4, i32 4, i1 false)
// The static initializer for g.
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* bitcast (%struct._GUID* @g to i8*), i8* bitcast (%struct._GUID* @__uuid_12345678-1234-1234-1234-1234567890ab to i8*), i32 16, i32 4, i1 false)
+// CHECK-DEFINE-GUID: call void @llvm.memcpy.p0i8.p0i8.i32(i8* bitcast (%struct._GUID* @g to i8*), i8* bitcast ({ i32, i16, i16, [8 x i8] }* @_GUID_12345678_1234_1234_1234_1234567890ab to i8*), i32 16, i32 4, i1 false)
+// CHECK-DEFINE-WRONG-GUID: call void @llvm.memcpy.p0i8.p0i8.i32(i8* bitcast (%struct._GUID* @g to i8*), i8* bitcast ({ i32, i16, i16, [8 x i8] }* @_GUID_12345678_1234_1234_1234_1234567890ab to i8*), i32 4, i32 4, i1 false)
+#ifdef DEFINE_GUID
void fun() {
- // CHECK: %s1_1 = alloca %struct._GUID, align 4
- // CHECK: %s1_2 = alloca %struct._GUID, align 4
- // CHECK: %s1_3 = alloca %struct._GUID, align 4
+ // CHECK-DEFINE-GUID: %s1_1 = alloca %struct._GUID, align 4
+ // CHECK-DEFINE-WRONG-GUID: %s1_1 = alloca %struct._GUID, align 4
+ // CHECK-DEFINE-GUID: %s1_2 = alloca %struct._GUID, align 4
+ // CHECK-DEFINE-WRONG-GUID: %s1_2 = alloca %struct._GUID, align 4
+ // CHECK-DEFINE-GUID: %s1_3 = alloca %struct._GUID, align 4
+ // CHECK-DEFINE-WRONG-GUID: %s1_3 = alloca %struct._GUID, align 4
- // CHECK: [[U1:%.+]] = bitcast %struct._GUID* %s1_1 to i8*
- // CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[U1]], i8* bitcast (%struct._GUID* @__uuid_12345678-1234-1234-1234-1234567890ab to i8*), i32 16, i32 4, i1 false)
+ // CHECK-DEFINE-GUID: [[U1:%.+]] = bitcast %struct._GUID* %s1_1 to i8*
+ // CHECK-DEFINE-WRONG-GUID: [[U1:%.+]] = bitcast %struct._GUID* %s1_1 to i8*
+ // CHECK-DEFINE-GUID: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[U1]], i8* bitcast ({ i32, i16, i16, [8 x i8] }* @_GUID_12345678_1234_1234_1234_1234567890ab to i8*), i32 16, i32 4, i1 false)
+ // CHECK-DEFINE-WRONG-GUID: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[U1]], i8* bitcast ({ i32, i16, i16, [8 x i8] }* @_GUID_12345678_1234_1234_1234_1234567890ab to i8*), i32 4, i32 4, i1 false)
GUID s1_1 = __uuidof(S1);
- // CHECK: [[U2:%.+]] = bitcast %struct._GUID* %s1_2 to i8*
- // CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[U2]], i8* bitcast (%struct._GUID* @__uuid_12345678-1234-1234-1234-1234567890ab to i8*), i32 16, i32 4, i1 false)
+ // CHECK-DEFINE-GUID: [[U2:%.+]] = bitcast %struct._GUID* %s1_2 to i8*
+ // CHECK-DEFINE-WRONG-GUID: [[U2:%.+]] = bitcast %struct._GUID* %s1_2 to i8*
+ // CHECK-DEFINE-GUID: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[U2]], i8* bitcast ({ i32, i16, i16, [8 x i8] }* @_GUID_12345678_1234_1234_1234_1234567890ab to i8*), i32 16, i32 4, i1 false)
+ // CHECK-DEFINE-WRONG-GUID: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[U2]], i8* bitcast ({ i32, i16, i16, [8 x i8] }* @_GUID_12345678_1234_1234_1234_1234567890ab to i8*), i32 4, i32 4, i1 false)
GUID s1_2 = __uuidof(S1);
- // CHECK: [[U3:%.+]] = bitcast %struct._GUID* %s1_3 to i8*
- // CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[U3]], i8* bitcast (%struct._GUID* @__uuid_12345678-1234-1234-1234-1234567890ab to i8*), i32 16, i32 4, i1 false)
+ // CHECK-DEFINE-GUID: [[U3:%.+]] = bitcast %struct._GUID* %s1_3 to i8*
+ // CHECK-DEFINE-WRONG-GUID: [[U3:%.+]] = bitcast %struct._GUID* %s1_3 to i8*
+ // CHECK-DEFINE-GUID: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[U3]], i8* bitcast ({ i32, i16, i16, [8 x i8] }* @_GUID_12345678_1234_1234_1234_1234567890ab to i8*), i32 16, i32 4, i1 false)
+ // CHECK-DEFINE-WRONG-GUID: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[U3]], i8* bitcast ({ i32, i16, i16, [8 x i8] }* @_GUID_12345678_1234_1234_1234_1234567890ab to i8*), i32 4, i32 4, i1 false)
GUID s1_3 = __uuidof(s1);
}
+#endif
void gun() {
- // CHECK: %s2_1 = alloca %struct._GUID, align 4
- // CHECK: %s2_2 = alloca %struct._GUID, align 4
+#ifdef DEFINE_GUID
+ // CHECK-DEFINE-GUID: %s2_1 = alloca %struct._GUID, align 4
+ // CHECK-DEFINE-WRONG-GUID: %s2_1 = alloca %struct._GUID, align 4
+ // CHECK-DEFINE-GUID: %s2_2 = alloca %struct._GUID, align 4
+ // CHECK-DEFINE-WRONG-GUID: %s2_2 = alloca %struct._GUID, align 4
+ GUID s2_1 = __uuidof(S2);
+ GUID s2_2 = __uuidof(S2);
+#endif
// CHECK: %r = alloca %struct._GUID*, align 4
// CHECK: %p = alloca %struct._GUID*, align 4
// CHECK: %zeroiid = alloca %struct._GUID*, align 4
- GUID s2_1 = __uuidof(S2);
- GUID s2_2 = __uuidof(S2);
- // CHECK: store %struct._GUID* @__uuid_87654321-4321-4321-4321-ba0987654321, %struct._GUID** %r, align 4
+ // CHECK: store %struct._GUID* bitcast ({ i32, i16, i16, [8 x i8] }* @_GUID_87654321_4321_4321_4321_ba0987654321 to %struct._GUID*), %struct._GUID** %r, align 4
const GUID& r = __uuidof(S2);
- // CHECK: store %struct._GUID* @__uuid_87654321-4321-4321-4321-ba0987654321, %struct._GUID** %p, align 4
+ // CHECK: store %struct._GUID* bitcast ({ i32, i16, i16, [8 x i8] }* @_GUID_87654321_4321_4321_4321_ba0987654321 to %struct._GUID*), %struct._GUID** %p, align 4
const GUID* p = &__uuidof(S2);
// Special case _uuidof(0), local scope version.
- // CHECK: store %struct._GUID* @__uuid_00000000-0000-0000-0000-000000000000, %struct._GUID** %zeroiid, align 4
+ // CHECK: store %struct._GUID* bitcast ({ i32, i16, i16, [8 x i8] }* @_GUID_00000000_0000_0000_0000_000000000000 to %struct._GUID*), %struct._GUID** %zeroiid, align 4
const GUID& zeroiid = __uuidof(0);
}
diff --git a/test/CodeGenCXX/move-assignment.cpp b/test/CodeGenCXX/move-assignment.cpp
new file mode 100644
index 0000000..3653eab
--- /dev/null
+++ b/test/CodeGenCXX/move-assignment.cpp
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -emit-llvm -std=c++11 -o - %s -triple x86_64-pc-linux-gnu | FileCheck %s
+
+struct A {
+ A &operator=(A&&);
+};
+
+struct B {
+ A a;
+ int i;
+ bool b;
+ char c;
+ long l;
+ float f;
+};
+
+void test1() {
+ B b1, b2;
+ b1 = static_cast<B&&>(b2);
+}
+
+// CHECK-LABEL: define {{.*}} @_ZN1BaSEOS_
+// CHECK: call {{.*}} @_ZN1AaSEOS_
+// CHECK-NOT: store
+// CHECK: call {{.*}}memcpy{{.*}}, i64 24
+// CHECK-NOT: store
+// CHECK: ret
diff --git a/test/CodeGenCXX/ms-integer-static-data-members.cpp b/test/CodeGenCXX/ms-integer-static-data-members.cpp
new file mode 100644
index 0000000..00beaa6
--- /dev/null
+++ b/test/CodeGenCXX/ms-integer-static-data-members.cpp
@@ -0,0 +1,35 @@
+// RUN: %clang_cc1 -emit-llvm -cxx-abi microsoft -triple=i386-pc-win32 %s -o - | FileCheck %s
+// RUN: %clang_cc1 -DINLINE_INIT -emit-llvm -cxx-abi microsoft -triple=i386-pc-win32 %s -o - | FileCheck %s --check-prefix=CHECK-INLINE
+// RUN: %clang_cc1 -DREAL_DEFINITION -emit-llvm -cxx-abi microsoft -triple=i386-pc-win32 %s -o - | FileCheck %s --check-prefix=CHECK-OUTOFLINE
+// RUN: %clang_cc1 -DINLINE_INIT -DREAL_DEFINITION -emit-llvm -cxx-abi microsoft -triple=i386-pc-win32 %s -o - | FileCheck %s --check-prefix=CHECK-INLINE
+
+struct S {
+ // For MS ABI, we emit a linkonce_odr definition here, even though it's really just a declaration.
+#ifdef INLINE_INIT
+ static const int x = 5;
+#else
+ static const int x;
+#endif
+};
+
+const int *f() {
+ return &S::x;
+};
+
+#ifdef REAL_DEFINITION
+#ifdef INLINE_INIT
+const int S::x;
+#else
+const int S::x = 5;
+#endif
+#endif
+
+
+// Inline initialization.
+// CHECK-INLINE: @"\01?x@S@@2HB" = linkonce_odr constant i32 5, align 4
+
+// Out-of-line initialization.
+// CHECK-OUTOFLINE: @"\01?x@S@@2HB" = constant i32 5, align 4
+
+// No initialization.
+// CHECK: @"\01?x@S@@2HB" = external constant i32
diff --git a/test/CodeGenCXX/new-alias.cpp b/test/CodeGenCXX/new-alias.cpp
new file mode 100644
index 0000000..7ddc1f9
--- /dev/null
+++ b/test/CodeGenCXX/new-alias.cpp
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -emit-llvm -triple x86_64-linux-gnu -std=c++11 -o - %s | FileCheck %s
+
+using size_t = decltype(sizeof(0));
+
+extern "C" char *something(long long x) {
+}
+
+// CHECK: @_Znwm = alias i8* (i64)* @something
+void *operator new(size_t) __attribute__((alias("something")));
+
+// PR16715: don't assert here.
+// CHECK: call noalias i8* @_Znwm(i64 4){{$}}
+int *pr16715 = new int;
diff --git a/test/CodeGenCXX/new-array-init-exceptions.cpp b/test/CodeGenCXX/new-array-init-exceptions.cpp
index 5d9cc9fa..5cfb757 100644
--- a/test/CodeGenCXX/new-array-init-exceptions.cpp
+++ b/test/CodeGenCXX/new-array-init-exceptions.cpp
@@ -7,7 +7,7 @@ struct Throws {
~Throws();
};
-// CHECK: define void @_Z7cleanupi
+// CHECK-LABEL: define void @_Z7cleanupi
void cleanup(int n) {
// CHECK: invoke void @_ZN6ThrowsC1Ei
// CHECK-NEXT: to label %{{[^ ]+}} unwind label %[[LPAD:[^ ]+]]
@@ -25,7 +25,7 @@ void cleanup(int n) {
}
-// CHECK: define void @_Z7cleanupv
+// CHECK-LABEL: define void @_Z7cleanupv
void cleanup() {
// CHECK: invoke void @_ZN6ThrowsC1Ei
// CHECK-NEXT: to label %{{[^ ]+}} unwind label %[[LPAD2:[^ ]+]]
diff --git a/test/CodeGenCXX/new-array-init.cpp b/test/CodeGenCXX/new-array-init.cpp
index 231df24..0e925c0 100644
--- a/test/CodeGenCXX/new-array-init.cpp
+++ b/test/CodeGenCXX/new-array-init.cpp
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 -std=c++11 -triple i386-unknown-unknown %s -emit-llvm -o - | FileCheck %s
-// CHECK: define void @_Z2fni
+// CHECK-LABEL: define void @_Z2fni
void fn(int n) {
// CHECK: icmp ult i{{32|64}} %{{[^ ]+}}, 3
// CHECK: store i32 1
@@ -11,21 +11,21 @@ void fn(int n) {
new int[n] { 1, 2, 3 };
}
-// CHECK: define void @_Z15const_underflowv
+// CHECK-LABEL: define void @_Z15const_underflowv
void const_underflow() {
// CHECK-NOT: icmp ult i{{32|64}} %{{[^ ]+}}, 3
// CHECK: call noalias i8* @_Zna{{.}}(i{{32|64}} -1)
new int[2] { 1, 2, 3 };
}
-// CHECK: define void @_Z11const_exactv
+// CHECK-LABEL: define void @_Z11const_exactv
void const_exact() {
// CHECK-NOT: icmp ult i{{32|64}} %{{[^ ]+}}, 3
// CHECK-NOT: icmp eq i32*
new int[3] { 1, 2, 3 };
}
-// CHECK: define void @_Z16const_sufficientv
+// CHECK-LABEL: define void @_Z16const_sufficientv
void const_sufficient() {
// CHECK-NOT: icmp ult i{{32|64}} %{{[^ ]+}}, 3
new int[4] { 1, 2, 3 };
diff --git a/test/CodeGenCXX/new.cpp b/test/CodeGenCXX/new.cpp
index e052390..91da77a 100644
--- a/test/CodeGenCXX/new.cpp
+++ b/test/CodeGenCXX/new.cpp
@@ -2,9 +2,24 @@
typedef __typeof__(sizeof(0)) size_t;
+// Ensure that this declaration doesn't cause operator new to lose its
+// 'noalias' attribute.
+void *operator new[](size_t);
+
void t1() {
- int* a = new int;
+ delete new int;
+ delete [] new int [3];
+}
+
+// CHECK: declare noalias i8* @_Znwm(i64) [[ATTR_NOBUILTIN:#[^ ]*]]
+// CHECK: declare void @_ZdlPv(i8*) [[ATTR_NOBUILTIN_NOUNWIND:#[^ ]*]]
+// CHECK: declare noalias i8* @_Znam(i64) [[ATTR_NOBUILTIN]]
+// CHECK: declare void @_ZdaPv(i8*) [[ATTR_NOBUILTIN_NOUNWIND]]
+
+namespace std {
+ struct nothrow_t {};
}
+std::nothrow_t nothrow;
// Declare the reserved placement operators.
void *operator new(size_t, void*) throw();
@@ -12,6 +27,13 @@ void operator delete(void*, void*) throw();
void *operator new[](size_t, void*) throw();
void operator delete[](void*, void*) throw();
+// Declare the replaceable global allocation operators.
+void *operator new(size_t, const std::nothrow_t &) throw();
+void *operator new[](size_t, const std::nothrow_t &) throw();
+void operator delete(void *, const std::nothrow_t &) throw();
+void operator delete[](void *, const std::nothrow_t &) throw();
+
+
void t2(int* a) {
int* b = new (a) int;
}
@@ -77,10 +99,6 @@ void t8(int n) {
new U[n];
}
-// noalias
-// CHECK: declare noalias i8* @_Znam
-void *operator new[](size_t);
-
void t9() {
bool b;
@@ -98,7 +116,7 @@ A* t10() {
return new(1, 2, 3.45, 100) A;
}
-// CHECK: define void @_Z3t11i
+// CHECK-LABEL: define void @_Z3t11i
struct B { int a; };
struct Bmemptr { int Bmemptr::* memptr; int a; };
@@ -122,7 +140,7 @@ void t11(int n) {
struct Empty { };
// We don't need to initialize an empty class.
-// CHECK: define void @_Z3t12v
+// CHECK-LABEL: define void @_Z3t12v
void t12() {
// CHECK: call noalias i8* @_Znam
// CHECK-NOT: br
@@ -136,7 +154,7 @@ void t12() {
}
// Zero-initialization
-// CHECK: define void @_Z3t13i
+// CHECK-LABEL: define void @_Z3t13i
void t13(int n) {
// CHECK: call noalias i8* @_Znwm
// CHECK: store i32 0, i32*
@@ -171,7 +189,7 @@ void f() {
namespace test15 {
struct A { A(); ~A(); };
- // CHECK: define void @_ZN6test155test0EPv(
+ // CHECK-LABEL: define void @_ZN6test155test0EPv(
// CHECK: [[P:%.*]] = load i8*
// CHECK-NEXT: icmp eq i8* [[P]], null
// CHECK-NEXT: br i1
@@ -181,7 +199,7 @@ namespace test15 {
new (p) A();
}
- // CHECK: define void @_ZN6test155test1EPv(
+ // CHECK-LABEL: define void @_ZN6test155test1EPv(
// CHECK: [[P:%.*]] = load i8**
// CHECK-NEXT: icmp eq i8* [[P]], null
// CHECK-NEXT: br i1
@@ -199,7 +217,7 @@ namespace test15 {
// TODO: it's okay if all these size calculations get dropped.
// FIXME: maybe we should try to throw on overflow?
- // CHECK: define void @_ZN6test155test2EPvi(
+ // CHECK-LABEL: define void @_ZN6test155test2EPvi(
// CHECK: [[N:%.*]] = load i32*
// CHECK-NEXT: [[T0:%.*]] = sext i32 [[N]] to i64
// CHECK-NEXT: [[T1:%.*]] = icmp slt i64 [[T0]], 0
@@ -220,7 +238,7 @@ namespace test15 {
}
namespace PR10197 {
- // CHECK: define weak_odr void @_ZN7PR101971fIiEEvv()
+ // CHECK-LABEL: define weak_odr void @_ZN7PR101971fIiEEvv()
template<typename T>
void f() {
// CHECK: [[CALL:%.*]] = call noalias i8* @_Znwm
@@ -235,7 +253,7 @@ namespace PR10197 {
namespace PR11523 {
class MyClass;
typedef int MyClass::* NewTy;
- // CHECK: define i64* @_ZN7PR115231fEv
+ // CHECK-LABEL: define i64* @_ZN7PR115231fEv
// CHECK: store i64 -1
NewTy* f() { return new NewTy[2](); }
}
@@ -254,9 +272,69 @@ namespace PR11757 {
namespace PR13380 {
struct A { A() {} };
struct B : public A { int x; };
- // CHECK: define i8* @_ZN7PR133801fEv
+ // CHECK-LABEL: define i8* @_ZN7PR133801fEv
// CHECK: call noalias i8* @_Znam(
// CHECK: call void @llvm.memset.p0i8
// CHECK-NEXT: call void @_ZN7PR133801BC1Ev
void* f() { return new B[2](); }
}
+
+struct MyPlacementType {} mpt;
+void *operator new(size_t, MyPlacementType);
+
+namespace N3664 {
+ struct S { S() throw(int); };
+
+ // CHECK-LABEL-LABEL: define void @_ZN5N36641fEv
+ void f() {
+ // CHECK: call noalias i8* @_Znwm(i64 4) [[ATTR_BUILTIN_NEW:#[^ ]*]]
+ int *p = new int;
+ // CHECK: call void @_ZdlPv({{.*}}) [[ATTR_BUILTIN_DELETE:#[^ ]*]]
+ delete p;
+
+ // CHECK: call noalias i8* @_Znam(i64 12) [[ATTR_BUILTIN_NEW]]
+ int *q = new int[3];
+ // CHECK: call void @_ZdaPv({{.*}}) [[ATTR_BUILTIN_DELETE]]
+ delete [] p;
+
+ // CHECK: call i8* @_ZnamRKSt9nothrow_t(i64 3, {{.*}}) [[ATTR_BUILTIN_NOTHROW_NEW:#[^ ]*]]
+ (void) new (nothrow) S[3];
+
+ // CHECK: call i8* @_Znwm15MyPlacementType(i64 4){{$}}
+ (void) new (mpt) int;
+ }
+
+ // FIXME: Can we mark this noalias?
+ // CHECK: declare i8* @_ZnamRKSt9nothrow_t(i64, {{.*}}) [[ATTR_NOBUILTIN_NOUNWIND]]
+
+ // CHECK-LABEL-LABEL: define void @_ZN5N36641gEv
+ void g() {
+ // It's OK for there to be attributes here, so long as we don't have a
+ // 'builtin' attribute.
+ // CHECK: call noalias i8* @_Znwm(i64 4){{$}}
+ int *p = (int*)operator new(4);
+ // CHECK: call void @_ZdlPv({{.*}}) [[ATTR_NOUNWIND:#[^ ]*]]
+ operator delete(p);
+
+ // CHECK: call noalias i8* @_Znam(i64 12){{$}}
+ int *q = (int*)operator new[](12);
+ // CHECK: call void @_ZdaPv({{.*}}) [[ATTR_NOUNWIND]]
+ operator delete [](p);
+
+ // CHECK: call i8* @_ZnamRKSt9nothrow_t(i64 3, {{.*}}) [[ATTR_NOUNWIND]]
+ (void) operator new[](3, nothrow);
+ }
+}
+
+// CHECK-DAG: attributes [[ATTR_NOBUILTIN]] = {{[{].*}} nobuiltin {{.*[}]}}
+// CHECK-DAG: attributes [[ATTR_NOBUILTIN_NOUNWIND]] = {{[{].*}} nobuiltin nounwind {{.*[}]}}
+
+// CHECK: attributes [[ATTR_NOUNWIND]] =
+// CHECK-NOT: builtin
+// CHECK-NOT: attributes
+// CHECK: nounwind
+// CHECK-NOT: builtin
+// CHECK: attributes
+
+// CHECK-DAG: attributes [[ATTR_BUILTIN_NEW]] = {{[{].*}} builtin {{.*[}]}}
+// CHECK-DAG: attributes [[ATTR_BUILTIN_DELETE]] = {{[{].*}} builtin {{.*[}]}}
diff --git a/test/CodeGenCXX/no-opt-volatile-memcpy.cpp b/test/CodeGenCXX/no-opt-volatile-memcpy.cpp
index e542e4a..d1e2e1d 100644
--- a/test/CodeGenCXX/no-opt-volatile-memcpy.cpp
+++ b/test/CodeGenCXX/no-opt-volatile-memcpy.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -O0 -triple=x86_64-apple-darwin -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple=x86_64-apple-darwin -emit-llvm -o - %s | FileCheck %s
// rdar://11861085
struct s {
@@ -14,7 +14,7 @@ void foo (void) {
gs = gs;
ls = gs;
}
-// CHECK: define void @_Z3foov()
+// CHECK-LABEL: 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*
@@ -34,7 +34,7 @@ void fee (void) {
s = s;
s.y = gs;
}
-// CHECK: define void @_Z3feev()
+// CHECK-LABEL: 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)
@@ -46,5 +46,5 @@ d gd;
void gorf(void) {
gd = gd;
}
-// CHECK: define void @_Z4gorfv()
+// CHECK-LABEL: 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/noexcept.cpp b/test/CodeGenCXX/noexcept.cpp
new file mode 100644
index 0000000..dd4cfda
--- /dev/null
+++ b/test/CodeGenCXX/noexcept.cpp
@@ -0,0 +1,49 @@
+// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - -fcxx-exceptions -fexceptions -std=c++11 | FileCheck %s
+
+// rdar://11904428
+// Ensure that we call __cxa_begin_catch before calling
+// std::terminate in a noexcept function.
+namespace test0 {
+ void foo();
+
+ struct A {
+ A();
+ ~A();
+ };
+
+ void test() noexcept {
+ A a;
+ foo();
+ }
+}
+// CHECK-LABEL: define void @_ZN5test04testEv()
+// CHECK: [[EXN:%.*]] = alloca i8*
+// This goes to the terminate lpad.
+// CHECK: invoke void @_ZN5test01AC1Ev(
+// This goes to the cleanup-and-then-terminate lpad.
+// CHECK: invoke void @_ZN5test03fooEv()
+// Destructors don't throw by default in C++11.
+// CHECK: call void @_ZN5test01AD1Ev(
+// Cleanup lpad.
+// CHECK: [[T0:%.*]] = landingpad
+// CHECK-NEXT: catch i8* null
+// CHECK-NEXT: [[T1:%.*]] = extractvalue { i8*, i32 } [[T0]], 0
+// CHECK-NEXT: store i8* [[T1]], i8** [[EXN]]
+// (Calling this destructor is not technically required.)
+// CHECK: call void @_ZN5test01AD1Ev(
+// CHECK-NEXT: br label
+// The terminate landing pad jumps in here for some reason.
+// CHECK: [[T0:%.*]] = landingpad
+// CHECK-NEXT: catch i8* null
+// CHECK-NEXT: [[T1:%.*]] = extractvalue { i8*, i32 } [[T0]], 0
+// CHECK-NEXT: call void @__clang_call_terminate(i8* [[T1]])
+// CHECK-NEXT: unreachable
+// The terminate handler chained to by the cleanup lpad.
+// CHECK: [[T0:%.*]] = load i8** [[EXN]]
+// CHECK-NEXT: call void @__clang_call_terminate(i8* [[T0]])
+// CHECK-NEXT: unreachable
+
+// CHECK-LABEL: define linkonce_odr hidden void @__clang_call_terminate(
+// CHECK: call i8* @__cxa_begin_catch(
+// CHECK-NEXT: call void @_ZSt9terminatev()
+// CHECK-NEXT: unreachable
diff --git a/test/CodeGenCXX/nrvo.cpp b/test/CodeGenCXX/nrvo.cpp
index 747ab6d..b83dd72 100644
--- a/test/CodeGenCXX/nrvo.cpp
+++ b/test/CodeGenCXX/nrvo.cpp
@@ -9,8 +9,8 @@ public:
~X();
};
-// CHECK: define void @_Z5test0v
-// CHECK-EH: define void @_Z5test0v
+// CHECK-LABEL: define void @_Z5test0v
+// CHECK-EH-LABEL: define void @_Z5test0v
X test0() {
X x;
// CHECK: call {{.*}} @_ZN1XC1Ev
@@ -21,8 +21,8 @@ X test0() {
return x;
}
-// CHECK: define void @_Z5test1b(
-// CHECK-EH: define void @_Z5test1b(
+// CHECK-LABEL: define void @_Z5test1b(
+// CHECK-EH-LABEL: define void @_Z5test1b(
X test1(bool B) {
// CHECK: tail call {{.*}} @_ZN1XC1Ev
// CHECK-NEXT: ret void
@@ -34,8 +34,8 @@ X test1(bool B) {
// CHECK-EH-NEXT: ret void
}
-// CHECK: define void @_Z5test2b
-// CHECK-EH: define void @_Z5test2b
+// CHECK-LABEL: define void @_Z5test2b
+// CHECK-EH-LABEL: define void @_Z5test2b
X test2(bool B) {
// No NRVO.
@@ -120,7 +120,7 @@ X test3(bool B) {
extern "C" void exit(int) throw();
-// CHECK: define void @_Z5test4b
+// CHECK-LABEL: define void @_Z5test4b
X test4(bool B) {
{
// CHECK: tail call {{.*}} @_ZN1XC1Ev
@@ -135,7 +135,7 @@ X test4(bool B) {
}
#ifdef __EXCEPTIONS
-// CHECK-EH: define void @_Z5test5
+// CHECK-EH-LABEL: define void @_Z5test5
void may_throw();
X test5() {
try {
@@ -150,7 +150,7 @@ X test5() {
#endif
// rdar://problem/10430868
-// CHECK: define void @_Z5test6v
+// CHECK-LABEL: define void @_Z5test6v
X test6() {
X a __attribute__((aligned(8)));
return a;
diff --git a/test/CodeGenCXX/override-layout.cpp b/test/CodeGenCXX/override-layout.cpp
index aba4c91..418c4ff 100644
--- a/test/CodeGenCXX/override-layout.cpp
+++ b/test/CodeGenCXX/override-layout.cpp
@@ -1,6 +1,6 @@
-// RUN: %clang_cc1 -fdump-record-layouts-simple %s 2> %t.layouts
-// RUN: %clang_cc1 -fdump-record-layouts-simple %s > %t.before 2>&1
-// RUN: %clang_cc1 -DPACKED= -DALIGNED16= -fdump-record-layouts-simple -foverride-record-layout=%t.layouts %s > %t.after 2>&1
+// RUN: %clang_cc1 -fdump-record-layouts-simple %s > %t.layouts
+// RUN: %clang_cc1 -fdump-record-layouts-simple %s > %t.before
+// RUN: %clang_cc1 -DPACKED= -DALIGNED16= -fdump-record-layouts-simple -foverride-record-layout=%t.layouts %s > %t.after
// RUN: diff -u %t.before %t.after
// RUN: FileCheck %s < %t.after
diff --git a/test/CodeGenCXX/partial-destruction.cpp b/test/CodeGenCXX/partial-destruction.cpp
index f232a15..22daebe 100644
--- a/test/CodeGenCXX/partial-destruction.cpp
+++ b/test/CodeGenCXX/partial-destruction.cpp
@@ -11,7 +11,7 @@ namespace test0 {
A as[10] = { 5, 7 };
opaque();
}
- // CHECK: define void @_ZN5test04testEv()
+ // CHECK-LABEL: define void @_ZN5test04testEv()
// CHECK: [[AS:%.*]] = alloca [10 x [[A:%.*]]], align
// CHECK-NEXT: [[ENDVAR:%.*]] = alloca [[A]]*
// CHECK-NEXT: [[EXN:%.*]] = alloca i8*
@@ -98,7 +98,7 @@ namespace test1 {
void test() {
B v = { 5, 6, 7, 8 };
}
- // CHECK: define void @_ZN5test14testEv()
+ // CHECK-LABEL: define void @_ZN5test14testEv()
// CHECK: [[V:%.*]] = alloca [[B:%.*]], align 4
// CHECK-NEXT: alloca i8*
// CHECK-NEXT: alloca i32
@@ -128,7 +128,7 @@ namespace test2 {
void test() {
A v[4][7];
- // CHECK: define void @_ZN5test24testEv()
+ // CHECK-LABEL: define void @_ZN5test24testEv()
// CHECK: [[V:%.*]] = alloca [4 x [7 x [[A:%.*]]]], align 1
// CHECK-NEXT: alloca i8*
// CHECK-NEXT: alloca i32
diff --git a/test/CodeGenCXX/pod-member-memcpys.cpp b/test/CodeGenCXX/pod-member-memcpys.cpp
index 534d5d1..5c79568 100644
--- a/test/CodeGenCXX/pod-member-memcpys.cpp
+++ b/test/CodeGenCXX/pod-member-memcpys.cpp
@@ -1,5 +1,5 @@
-// 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
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -std=c++03 -fexceptions -fcxx-exceptions -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple i386-apple-darwin10 -emit-llvm -std=c++03 -o - %s | FileCheck --check-prefix=CHECK-2 %s
struct POD {
int w, x, y, z;
@@ -108,61 +108,61 @@ 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
+// CHECK-LABEL: define linkonce_odr %struct.Basic* @_ZN5BasicaSERKS_(%struct.Basic* %this, %struct.Basic*)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}})
+// CHECK: call %struct.NonPOD* @_ZN6NonPODaSERKS_
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}})
+// CHECK: ret %struct.Basic*
// 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
+// CHECK-LABEL: define linkonce_odr %struct.PODMember* @_ZN9PODMemberaSERKS_(%struct.PODMember* %this, %struct.PODMember*)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 32, i32 4{{.*}})
+// CHECK: call %struct.NonPOD* @_ZN6NonPODaSERKS_
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}})
+// CHECK: ret %struct.PODMember*
// 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
+// CHECK-LABEL: define linkonce_odr %struct.PODLikeMember* @_ZN13PODLikeMemberaSERKS_(%struct.PODLikeMember* %this, %struct.PODLikeMember*)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 32, i32 4{{.*}})
+// CHECK: call %struct.NonPOD* @_ZN6NonPODaSERKS_
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}})
+// CHECK: ret %struct.PODLikeMember*
// 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
+// CHECK-LABEL: define linkonce_odr %struct.ArrayMember* @_ZN11ArrayMemberaSERKS_(%struct.ArrayMember* %this, %struct.ArrayMember*)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 64, i32 4{{.*}})
+// CHECK: call %struct.NonPOD* @_ZN6NonPODaSERKS_
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 64, i32 4{{.*}})
+// CHECK: ret %struct.ArrayMember*
// 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-LABEL: define linkonce_odr %struct.VolatileMember* @_ZN14VolatileMemberaSERKS_(%struct.VolatileMember* %this, %struct.VolatileMember*)
+// CHECK: 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
+// CHECK: call %struct.NonPOD* @_ZN6NonPODaSERKS_
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}})
+// CHECK: ret %struct.VolatileMember*
// 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
+// CHECK-LABEL: define linkonce_odr %struct.BitfieldMember* @_ZN14BitfieldMemberaSERKS_(%struct.BitfieldMember* %this, %struct.BitfieldMember*)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}})
+// CHECK: call %struct.NonPOD* @_ZN6NonPODaSERKS_
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 3, i32 1{{.*}})
+// CHECK: ret %struct.BitfieldMember*
// 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
+// CHECK-LABEL: define linkonce_odr %struct.InnerClassMember* @_ZN16InnerClassMemberaSERKS_(%struct.InnerClassMember* %this, %struct.InnerClassMember*)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 32, i32 4{{.*}})
+// CHECK: call %struct.NonPOD* @_ZN6NonPODaSERKS_
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}})
+// CHECK: ret %struct.InnerClassMember*
// 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
+// CHECK-LABEL: define linkonce_odr %struct.PackedMembers* @_ZN13PackedMembersaSERKS_(%struct.PackedMembers* %this, %struct.PackedMembers*)
+// CHECK: call %struct.NonPOD* @_ZN6NonPODaSERKS_
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 1{{.*}})
+// CHECK: ret %struct.PackedMembers*
// COPY-CONSTRUCTORS:
@@ -184,73 +184,73 @@ 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-LABEL: define linkonce_odr void @_ZN5BasicC2ERKS_(%struct.Basic* %this, %struct.Basic*)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}})
+// CHECK: call void @_ZN6NonPODC1ERKS_
+// CHECK: 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-LABEL: define linkonce_odr void @_ZN9PODMemberC2ERKS_(%struct.PODMember* %this, %struct.PODMember*)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 32, i32 4{{.*}})
+// CHECK: call void @_ZN6NonPODC1ERKS_
+// CHECK: 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-LABEL: define linkonce_odr void @_ZN13PODLikeMemberC2ERKS_(%struct.PODLikeMember* %this, %struct.PODLikeMember*)
+// CHECK: 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: 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-LABEL: define linkonce_odr void @_ZN11ArrayMemberC2ERKS_(%struct.ArrayMember* %this, %struct.ArrayMember*)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 64, i32 4{{.*}})
+// CHECK: call void @_ZN6NonPODC1ERKS_
+// CHECK: 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-LABEL: define linkonce_odr void @_ZN14VolatileMemberC2ERKS_(%struct.VolatileMember* %this, %struct.VolatileMember*)
+// CHECK: 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: call void @_ZN6NonPODC1ERKS_
+// CHECK: 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-LABEL: define linkonce_odr void @_ZN14BitfieldMemberC2ERKS_(%struct.BitfieldMember* %this, %struct.BitfieldMember*)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}})
+// CHECK: call void @_ZN6NonPODC1ERKS_
+// CHECK: 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-LABEL: define linkonce_odr void @_ZN16InnerClassMemberC2ERKS_(%struct.InnerClassMember* %this, %struct.InnerClassMember*)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 32, i32 4{{.*}})
+// CHECK: call void @_ZN6NonPODC1ERKS_
+// CHECK: 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-LABEL: define linkonce_odr void @_ZN15ReferenceMemberC2ERKS_(%struct.ReferenceMember* %this, %struct.ReferenceMember*)
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 8{{.*}})
+// CHECK: call void @_ZN6NonPODC1ERKS_
+// CHECK: 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-LABEL: 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-LABEL: define linkonce_odr void @_ZN13PackedMembersC2ERKS_(%struct.PackedMembers* %this, %struct.PackedMembers*)
+// CHECK: call void @_ZN6NonPODC1ERKS_
+// CHECK: 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 7335c97..f0199c8 100644
--- a/test/CodeGenCXX/pointers-to-data-members.cpp
+++ b/test/CodeGenCXX/pointers-to-data-members.cpp
@@ -124,7 +124,7 @@ struct A {
A();
};
-// CHECK: define void @_ZN9ValueInit1AC2Ev(%"struct.ValueInit::A"* %this) unnamed_addr
+// CHECK-LABEL: define void @_ZN9ValueInit1AC2Ev(%"struct.ValueInit::A"* %this) unnamed_addr
// CHECK: store i64 -1, i64*
// CHECK: ret void
A::A() : a() {}
@@ -202,7 +202,7 @@ namespace BoolPtrToMember {
bool member;
};
- // CHECK: define i8* @_ZN15BoolPtrToMember1fERNS_1XEMS0_b
+ // CHECK-LABEL: define i8* @_ZN15BoolPtrToMember1fERNS_1XEMS0_b
bool &f(X &x, bool X::*member) {
// CHECK: {{bitcast.* to i8\*}}
// CHECK-NEXT: getelementptr inbounds i8*
@@ -249,7 +249,7 @@ namespace PR13097 {
};
A f();
X g() { return f().*&A::x; }
- // CHECK: define void @_ZN7PR130971gEv
+ // CHECK-LABEL: define void @_ZN7PR130971gEv
// CHECK: call void @_ZN7PR130971fEv
// CHECK-NOT: memcpy
// CHECK: call void @_ZN7PR130971XC1ERKS0_
diff --git a/test/CodeGenCXX/pr11676.cpp b/test/CodeGenCXX/pr11676.cpp
deleted file mode 100644
index 896751a..0000000
--- a/test/CodeGenCXX/pr11676.cpp
+++ /dev/null
@@ -1,17 +0,0 @@
-// RUN: %clang_cc1 %s -std=c++11 -emit-llvm-only
-// CHECK that we don't crash.
-
-// PR11676's example is ill-formed:
-/*
-union _XEvent {
-};
-void ProcessEvent() {
- _XEvent pluginEvent = _XEvent();
-}
-*/
-
-// Example from PR11665:
-void f() {
- union U { int field; } u = U();
- (void)U().field;
-}
diff --git a/test/CodeGenCXX/pr11797.cpp b/test/CodeGenCXX/pr11797.cpp
index 05221ac..1098372 100644
--- a/test/CodeGenCXX/pr11797.cpp
+++ b/test/CodeGenCXX/pr11797.cpp
@@ -5,4 +5,4 @@ namespace std __attribute__ ((__visibility__ ("default"))) {}
void foo() {
}
#pragma GCC visibility pop
-// CHECK: define void @_Z3foov()
+// CHECK-LABEL: define void @_Z3foov()
diff --git a/test/CodeGenCXX/pr12251.cpp b/test/CodeGenCXX/pr12251.cpp
index f3f2ec4..bb1c82d 100644
--- a/test/CodeGenCXX/pr12251.cpp
+++ b/test/CodeGenCXX/pr12251.cpp
@@ -4,97 +4,97 @@
bool f(bool *x) {
return *x;
}
-// CHECK: define zeroext i1 @_Z1fPb
-// CHECK: load i8* %{{.*}}, align 1, !range !0
+// CHECK-LABEL: define zeroext i1 @_Z1fPb
+// CHECK: load i8* %{{[^ ]*}}, align 1, !range [[RANGE_i8_0_2:![^ ]*]]
// Only enum-tests follow. Ensure that after the bool test, no further range
// metadata shows up when strict enums are disabled.
-// NO-STRICT-ENUMS: define zeroext i1 @_Z1fPb
-// NO-STRICT-ENUMS: load i8* %{{.*}}, align 1, !range !0
+// NO-STRICT-ENUMS-LABEL: define zeroext i1 @_Z1fPb
+// NO-STRICT-ENUMS: load i8* %{{[^ ]*}}, align 1, !range
// NO-STRICT-ENUMS-NOT: !range
enum e1 { };
e1 g1(e1 *x) {
return *x;
}
-// CHECK: define i32 @_Z2g1P2e1
-// CHECK: load i32* %x, align 4, !range !1
+// CHECK-LABEL: define i32 @_Z2g1P2e1
+// CHECK: load i32* %x, align 4, !range [[RANGE_i32_0_1:![^ ]*]]
enum e2 { e2_a = 0 };
e2 g2(e2 *x) {
return *x;
}
-// CHECK: define i32 @_Z2g2P2e2
-// CHECK: load i32* %x, align 4, !range !1
+// CHECK-LABEL: define i32 @_Z2g2P2e2
+// CHECK: load i32* %x, align 4, !range [[RANGE_i32_0_1]]
enum e3 { e3_a = 16 };
e3 g3(e3 *x) {
return *x;
}
-// CHECK: define i32 @_Z2g3P2e3
-// CHECK: load i32* %x, align 4, !range !2
+// CHECK-LABEL: define i32 @_Z2g3P2e3
+// CHECK: load i32* %x, align 4, !range [[RANGE_i32_0_32:![^ ]*]]
enum e4 { e4_a = -16};
e4 g4(e4 *x) {
return *x;
}
-// CHECK: define i32 @_Z2g4P2e4
-// CHECK: load i32* %x, align 4, !range !3
+// CHECK-LABEL: define i32 @_Z2g4P2e4
+// CHECK: load i32* %x, align 4, !range [[RANGE_i32_m16_16:![^ ]*]]
enum e5 { e5_a = -16, e5_b = 16};
e5 g5(e5 *x) {
return *x;
}
-// CHECK: define i32 @_Z2g5P2e5
-// CHECK: load i32* %x, align 4, !range !4
+// CHECK-LABEL: define i32 @_Z2g5P2e5
+// CHECK: load i32* %x, align 4, !range [[RANGE_i32_m32_32:![^ ]*]]
enum e6 { e6_a = -1 };
e6 g6(e6 *x) {
return *x;
}
-// CHECK: define i32 @_Z2g6P2e6
-// CHECK: load i32* %x, align 4, !range !5
+// CHECK-LABEL: define i32 @_Z2g6P2e6
+// CHECK: load i32* %x, align 4, !range [[RANGE_i32_m1_1:![^ ]*]]
enum e7 { e7_a = -16, e7_b = 2};
e7 g7(e7 *x) {
return *x;
}
-// CHECK: define i32 @_Z2g7P2e7
-// CHECK: load i32* %x, align 4, !range !3
+// CHECK-LABEL: define i32 @_Z2g7P2e7
+// CHECK: load i32* %x, align 4, !range [[RANGE_i32_m16_16]]
enum e8 { e8_a = -17};
e8 g8(e8 *x) {
return *x;
}
-// CHECK: define i32 @_Z2g8P2e8
-// CHECK: load i32* %x, align 4, !range !4
+// CHECK-LABEL: define i32 @_Z2g8P2e8
+// CHECK: load i32* %x, align 4, !range [[RANGE_i32_m32_32:![^ ]*]]
enum e9 { e9_a = 17};
e9 g9(e9 *x) {
return *x;
}
-// CHECK: define i32 @_Z2g9P2e9
-// CHECK: load i32* %x, align 4, !range !2
+// CHECK-LABEL: define i32 @_Z2g9P2e9
+// CHECK: load i32* %x, align 4, !range [[RANGE_i32_0_32]]
enum e10 { e10_a = -16, e10_b = 32};
e10 g10(e10 *x) {
return *x;
}
-// CHECK: define i32 @_Z3g10P3e10
-// CHECK: load i32* %x, align 4, !range !6
+// CHECK-LABEL: define i32 @_Z3g10P3e10
+// CHECK: load i32* %x, align 4, !range [[RANGE_i32_m64_64:![^ ]*]]
enum e11 {e11_a = 4294967296 };
enum e11 g11(enum e11 *x) {
return *x;
}
-// CHECK: define i64 @_Z3g11P3e11
-// CHECK: load i64* %x, align {{[84]}}, !range !7
+// CHECK-LABEL: define i64 @_Z3g11P3e11
+// CHECK: load i64* %x, align {{[84]}}, !range [[RANGE_i64_0_2pow33:![^ ]*]]
enum e12 {e12_a = 9223372036854775808U };
enum e12 g12(enum e12 *x) {
return *x;
}
-// CHECK: define i64 @_Z3g12P3e12
+// CHECK-LABEL: define i64 @_Z3g12P3e12
// CHECK: load i64* %x, align {{[84]}}
// CHECK-NOT: range
// CHECK: ret
@@ -103,7 +103,7 @@ enum e13 : char {e13_a = -1 };
e13 g13(e13 *x) {
return *x;
}
-// CHECK: define signext i8 @_Z3g13P3e13
+// CHECK-LABEL: define signext i8 @_Z3g13P3e13
// CHECK: load i8* %x, align 1
// CHECK-NOT: range
// CHECK: ret
@@ -112,7 +112,7 @@ enum class e14 {e14_a = 1};
e14 g14(e14 *x) {
return *x;
}
-// CHECK: define i32 @_Z3g14P3e14
+// CHECK-LABEL: define i32 @_Z3g14P3e14
// CHECK: load i32* %x, align 4
// CHECK-NOT: range
// CHECK: ret
@@ -121,7 +121,7 @@ enum e15 { e15_a = 2147483648 };
e15 g15(e15 *x) {
return *x;
}
-// CHECK: define i32 @_Z3g15P3e15
+// CHECK-LABEL: define i32 @_Z3g15P3e15
// CHECK: load i32* %x, align 4
// CHECK-NOT: range
// CHECK: ret
@@ -130,17 +130,17 @@ enum e16 { e16_a = -2147483648 };
e16 g16(e16 *x) {
return *x;
}
-// CHECK: define i32 @_Z3g16P3e16
+// CHECK-LABEL: define i32 @_Z3g16P3e16
// CHECK: load i32* %x, align 4
// CHECK-NOT: range
// CHECK: ret
-// CHECK: !0 = metadata !{i8 0, i8 2}
-// CHECK: !1 = metadata !{i32 0, i32 1}
-// CHECK: !2 = metadata !{i32 0, i32 32}
-// CHECK: !3 = metadata !{i32 -16, i32 16}
-// CHECK: !4 = metadata !{i32 -32, i32 32}
-// CHECK: !5 = metadata !{i32 -1, i32 1}
-// CHECK: !6 = metadata !{i32 -64, i32 64}
-// CHECK: !7 = metadata !{i64 0, i64 8589934592}
+// CHECK: [[RANGE_i8_0_2]] = metadata !{i8 0, i8 2}
+// CHECK: [[RANGE_i32_0_1]] = metadata !{i32 0, i32 1}
+// CHECK: [[RANGE_i32_0_32]] = metadata !{i32 0, i32 32}
+// CHECK: [[RANGE_i32_m16_16]] = metadata !{i32 -16, i32 16}
+// CHECK: [[RANGE_i32_m32_32]] = metadata !{i32 -32, i32 32}
+// CHECK: [[RANGE_i32_m1_1]] = metadata !{i32 -1, i32 1}
+// CHECK: [[RANGE_i32_m64_64]] = metadata !{i32 -64, i32 64}
+// CHECK: [[RANGE_i64_0_2pow33]] = metadata !{i64 0, i64 8589934592}
diff --git a/test/CodeGenCXX/pr13396.cpp b/test/CodeGenCXX/pr13396.cpp
index 7d4e2ce..3d582c5 100644
--- a/test/CodeGenCXX/pr13396.cpp
+++ b/test/CodeGenCXX/pr13396.cpp
@@ -7,13 +7,13 @@ struct foo {
};
foo::foo() {
- // CHECK: define void @_ZN3fooC1Ev(%struct.foo* inreg %this)
- // CHECK: define void @_ZN3fooC2Ev(%struct.foo* inreg %this)
+ // CHECK-LABEL: define void @_ZN3fooC1Ev(%struct.foo* inreg %this)
+ // CHECK-LABEL: define void @_ZN3fooC2Ev(%struct.foo* inreg %this)
}
foo::~foo() {
- // CHECK: define void @_ZN3fooD1Ev(%struct.foo* inreg %this)
- // CHECK: define void @_ZN3fooD2Ev(%struct.foo* inreg %this)
+ // CHECK-LABEL: define void @_ZN3fooD1Ev(%struct.foo* inreg %this)
+ // CHECK-LABEL: define void @_ZN3fooD2Ev(%struct.foo* inreg %this)
}
void dummy() {
@@ -21,6 +21,6 @@ void dummy() {
// older clangs accept:
// template foo::foo(int x);
foo x(10);
- // CHECK: define linkonce_odr void @_ZN3fooC1IiEET_(%struct.foo* inreg %this, i32 inreg %x)
- // CHECK: define linkonce_odr void @_ZN3fooC2IiEET_(%struct.foo* inreg %this, i32 inreg %x)
+ // CHECK-LABEL: define linkonce_odr void @_ZN3fooC1IiEET_(%struct.foo* inreg %this, i32 inreg %x)
+ // CHECK-LABEL: define linkonce_odr void @_ZN3fooC2IiEET_(%struct.foo* inreg %this, i32 inreg %x)
}
diff --git a/test/CodeGenCXX/pr9130.cpp b/test/CodeGenCXX/pr9130.cpp
index b28f394..e726e5a 100644
--- a/test/CodeGenCXX/pr9130.cpp
+++ b/test/CodeGenCXX/pr9130.cpp
@@ -11,4 +11,4 @@ class nsVorbisState : public nsOggCodecState {
nsVorbisState::~nsVorbisState() {
}
-// CHECK: define linkonce_odr i32 @_ZN15nsOggCodecState9StartTimeEv
+// CHECK-LABEL: define linkonce_odr i32 @_ZN15nsOggCodecState9StartTimeEv
diff --git a/test/CodeGenCXX/pr9965.cpp b/test/CodeGenCXX/pr9965.cpp
index 0d267ff..c2d54e1 100644
--- a/test/CodeGenCXX/pr9965.cpp
+++ b/test/CodeGenCXX/pr9965.cpp
@@ -8,7 +8,7 @@ struct X : A // default constructor is not trivial
};
X<int> x;
-// CHECK: define internal void @__cxx_global_var_init()
+// CHECK-LABEL: define internal void @__cxx_global_var_init()
// CHECK: call {{.*}} @_ZN1XIiEC1Ev
// CHECK: define linkonce_odr {{.*}} @_ZN1XIiEC1Ev
// CHECK: define linkonce_odr {{.*}} @_ZN1XIiEC2Ev
diff --git a/test/CodeGenCXX/pragma-visibility.cpp b/test/CodeGenCXX/pragma-visibility.cpp
index 0640d42..c0ba904 100644
--- a/test/CodeGenCXX/pragma-visibility.cpp
+++ b/test/CodeGenCXX/pragma-visibility.cpp
@@ -28,8 +28,8 @@ template<> int x4<int>::y = 10;
template<int x> int f() { return x; }
extern "C" int g() { return f<3>(); }
#pragma GCC visibility pop
-// CHECK: define hidden i32 @g()
-// CHECK: define linkonce_odr hidden i32 @_Z1fILi3EEiv()
+// CHECK-LABEL: define hidden i32 @g()
+// CHECK-LABEL: define linkonce_odr hidden i32 @_Z1fILi3EEiv()
#pragma GCC visibility push(hidden)
template<class T> struct x5 {
@@ -37,19 +37,19 @@ template<class T> struct x5 {
};
#pragma GCC visibility pop
template<> void x5<int>::y() {}
-// CHECK: define hidden void @_ZN2x5IiE1yEv
+// CHECK-LABEL: define hidden void @_ZN2x5IiE1yEv
#pragma GCC visibility push(hidden)
namespace n __attribute((visibility("default"))) {
void f() {}
- // CHECK: define void @_ZN1n1fEv
+ // CHECK-LABEL: define void @_ZN1n1fEv
}
#pragma GCC visibility pop
namespace n __attribute((visibility("default"))) {
#pragma GCC visibility push(hidden)
void g() {}
- // CHECK: define hidden void @_ZN1n1gEv
+ // CHECK-LABEL: define hidden void @_ZN1n1gEv
#pragma GCC visibility pop
}
@@ -69,6 +69,6 @@ namespace test2 {
bar<foo>::f();
bar<int>::f();
}
- // CHECK: define linkonce_odr hidden void @_ZN5test23barINS_3fooEE1fEv
- // CHECK: define linkonce_odr void @_ZN5test23barIiE1fEv
+ // CHECK-LABEL: define linkonce_odr hidden void @_ZN5test23barINS_3fooEE1fEv
+ // CHECK-LABEL: define linkonce_odr void @_ZN5test23barIiE1fEv
}
diff --git a/test/CodeGenCXX/pragma-weak.cpp b/test/CodeGenCXX/pragma-weak.cpp
index ed537ff..c033079 100644
--- a/test/CodeGenCXX/pragma-weak.cpp
+++ b/test/CodeGenCXX/pragma-weak.cpp
@@ -10,22 +10,22 @@ int zex;
#pragma weak foo
struct S { void foo(); };
void S::foo() {}
-// CHECK: define void @_ZN1S3fooEv(
+// CHECK-LABEL: define void @_ZN1S3fooEv(
#pragma weak zed
namespace bar { void zed() {} }
-// CHECK: define void @_ZN3bar3zedEv(
+// CHECK-LABEL: define void @_ZN3bar3zedEv(
#pragma weak bah
void bah() {}
-// CHECK: define void @_Z3bahv(
+// CHECK-LABEL: define void @_Z3bahv(
#pragma weak baz
extern "C" void baz() {}
-// CHECK: define weak void @baz(
+// CHECK-LABEL: 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(
+// CHECK-LABEL: define void @_Z3baxv(
diff --git a/test/CodeGenCXX/predefined-expr.cpp b/test/CodeGenCXX/predefined-expr.cpp
index 24ead8f..9062ee0 100644
--- a/test/CodeGenCXX/predefined-expr.cpp
+++ b/test/CodeGenCXX/predefined-expr.cpp
@@ -9,6 +9,8 @@
// CHECK: private unnamed_addr constant [57 x i8] c"void NonTypeTemplateParam<42>::size() const [Count = 42]\00"
// CHECK: private unnamed_addr constant [122 x i8] c"static void ClassWithTemplateTemplateParam<char, NS::ClassTemplate>::staticMember() [T = char, Param = NS::ClassTemplate]\00"
// CHECK: private unnamed_addr constant [106 x i8] c"void OuterClass<int *>::MiddleClass::InnerClass<float>::memberFunction(T, U) const [T = int *, U = float]\00"
+// CHECK: private unnamed_addr constant [51 x i8] c"void functionTemplateWithCapturedStmt(T) [T = int]\00"
+// CHECK: private unnamed_addr constant [76 x i8] c"auto functionTemplateWithLambda(int)::<anonymous class>::operator()() const\00"
// CHECK: private unnamed_addr constant [65 x i8] c"void functionTemplateWithUnnamedTemplateParameter(T) [T = float]\00"
// CHECK: private unnamed_addr constant [60 x i8] c"void functionTemplateExplicitSpecialization(T) [T = double]\00"
@@ -376,6 +378,23 @@ void functionTemplateWithUnnamedTemplateParameter(T t)
}
template <typename T>
+void functionTemplateWithLambda(T t)
+{
+ []() {
+ printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__);
+ } ();
+}
+
+template <typename T>
+void functionTemplateWithCapturedStmt(T t)
+{
+ #pragma clang __debug captured
+ {
+ printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__);
+ }
+}
+
+template <typename T>
class OuterClass
{
public:
@@ -500,6 +519,9 @@ int main() {
functionTemplateExplicitSpecialization(0.0);
functionTemplateWithUnnamedTemplateParameter<int, float>(0.0f);
+ functionTemplateWithLambda<int>(0);
+ functionTemplateWithCapturedStmt<int>(0);
+
OuterClass<int *>::MiddleClass::InnerClass<float> omi;
omi.memberFunction(0, 0.0f);
diff --git a/test/CodeGenCXX/ptr-to-member-function.cpp b/test/CodeGenCXX/ptr-to-member-function.cpp
index 3989c03..914a90a 100644
--- a/test/CodeGenCXX/ptr-to-member-function.cpp
+++ b/test/CodeGenCXX/ptr-to-member-function.cpp
@@ -1,8 +1,8 @@
// REQUIRES: x86-registered-target,x86-64-registered-target
// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -S %s -o %t-64.s
-// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s
+// RUN: FileCheck -check-prefix CHECK-LP64 --input-file=%t-64.s %s
// RUN: %clang_cc1 -triple i386-apple-darwin -std=c++11 -S %s -o %t-32.s
-// RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s
+// RUN: FileCheck -check-prefix CHECK-LP32 --input-file=%t-32.s %s
// 13.3.3.2 Ranking implicit conversion sequences
extern "C" int printf(...);
diff --git a/test/CodeGenCXX/reference-cast.cpp b/test/CodeGenCXX/reference-cast.cpp
index f157ae9..60ea393 100644
--- a/test/CodeGenCXX/reference-cast.cpp
+++ b/test/CodeGenCXX/reference-cast.cpp
@@ -15,7 +15,7 @@ const int &lvalue_noop_cast() {
return 17;
}
-// CHECK: define i16* @_Z20lvalue_integral_castv()
+// CHECK-LABEL: define i16* @_Z20lvalue_integral_castv()
const short &lvalue_integral_cast() {
if (i == 0)
// CHECK: store i16 17, i16*
@@ -27,7 +27,7 @@ const short &lvalue_integral_cast() {
return 17;
}
-// CHECK: define i16* @_Z29lvalue_floating_integral_castv()
+// CHECK-LABEL: define i16* @_Z29lvalue_floating_integral_castv()
const short &lvalue_floating_integral_cast() {
if (i == 0)
// CHECK: store i16 17, i16*
@@ -39,7 +39,7 @@ const short &lvalue_floating_integral_cast() {
return 17.5;
}
-// CHECK: define float* @_Z29lvalue_integral_floating_castv()
+// CHECK-LABEL: define float* @_Z29lvalue_integral_floating_castv()
const float &lvalue_integral_floating_cast() {
if (i == 0)
// CHECK: store float 1.700000e+{{0*}}1, float*
@@ -51,7 +51,7 @@ const float &lvalue_integral_floating_cast() {
return 17;
}
-// CHECK: define float* @_Z20lvalue_floating_castv()
+// CHECK-LABEL: define float* @_Z20lvalue_floating_castv()
const float &lvalue_floating_cast() {
if (i == 0)
// CHECK: store float 1.700000e+{{0*}}1, float*
@@ -65,7 +65,7 @@ const float &lvalue_floating_cast() {
int get_int();
-// CHECK: define i8* @_Z24lvalue_integer_bool_castv()
+// CHECK-LABEL: define i8* @_Z24lvalue_integer_bool_castv()
const bool &lvalue_integer_bool_cast() {
if (i == 0)
// CHECK: call i32 @_Z7get_intv()
@@ -82,7 +82,7 @@ const bool &lvalue_integer_bool_cast() {
float get_float();
-// CHECK: define i8* @_Z25lvalue_floating_bool_castv()
+// CHECK-LABEL: define i8* @_Z25lvalue_floating_bool_castv()
const bool &lvalue_floating_bool_cast() {
if (i == 0)
// CHECK: call float @_Z9get_floatv()
@@ -107,7 +107,7 @@ typedef int (X::*pmf)(int);
pm get_pointer_to_member_data();
pmf get_pointer_to_member_function();
-// CHECK: define i8* @_Z26lvalue_ptrmem_to_bool_castv()
+// CHECK-LABEL: define i8* @_Z26lvalue_ptrmem_to_bool_castv()
const bool &lvalue_ptrmem_to_bool_cast() {
if (i == 0)
// CHECK: call i64 @_Z26get_pointer_to_member_datav()
@@ -125,7 +125,7 @@ const bool &lvalue_ptrmem_to_bool_cast() {
return get_pointer_to_member_data();
}
-// CHECK: define i8* @_Z27lvalue_ptrmem_to_bool_cast2v
+// CHECK-LABEL: define i8* @_Z27lvalue_ptrmem_to_bool_cast2v
const bool &lvalue_ptrmem_to_bool_cast2() {
if (i == 0)
// CHECK: {{call.*_Z30get_pointer_to_member_functionv}}
@@ -169,7 +169,7 @@ const _Complex float &f1() {
return get_complex_double();
}
-// CHECK: define i32 @_Z7pr10592RKi(i32*
+// CHECK-LABEL: define i32 @_Z7pr10592RKi(i32*
unsigned pr10592(const int &v) {
// CHECK: [[VADDR:%[a-zA-Z0-9.]+]] = alloca i32*
// CHECK-NEXT: [[REFTMP:%[a-zA-Z0-9.]+]] = alloca i32
@@ -189,7 +189,7 @@ namespace PR10650 {
unsigned long long test(Helper *obj) {
return static_cast<const unsigned long long&>(obj->id());
}
- // CHECK: define i64 @_ZN7PR106504testEPNS_6HelperE
+ // CHECK-LABEL: define i64 @_ZN7PR106504testEPNS_6HelperE
// CHECK: store i64
}
diff --git a/test/CodeGenCXX/references.cpp b/test/CodeGenCXX/references.cpp
index df5a336..ec7a3d5 100644
--- a/test/CodeGenCXX/references.cpp
+++ b/test/CodeGenCXX/references.cpp
@@ -1,6 +1,6 @@
-// RUN: %clang_cc1 -triple x86_64-apple-darwin -verify -emit-llvm -o - %s | FileCheck %s
+// RUN: not %clang_cc1 -triple x86_64-apple-darwin -verify -emit-llvm -o - %s | FileCheck %s
void t1() {
- // CHECK: define void @_Z2t1v
+ // CHECK-LABEL: define void @_Z2t1v
// CHECK: [[REFLOAD:%.*]] = load i32** @a, align 8
// CHECK: load i32* [[REFLOAD]], align 4
extern int& a;
@@ -8,7 +8,7 @@ void t1() {
}
void t2(int& a) {
- // CHECK: define void @_Z2t2Ri
+ // CHECK-LABEL: define void @_Z2t2Ri
// CHECK: [[REFLOAD2:%.*]] = load i32** {{.*}}, align 8
// CHECK: load i32* [[REFLOAD2]], align 4
int b = a;
@@ -189,7 +189,7 @@ namespace N2 {
P getP();
- // CHECK: define void @_ZN2N21fEi
+ // CHECK-LABEL: define void @_ZN2N21fEi
// CHECK: call void @_ZN2N24getPEv
// CHECK: getelementptr inbounds
// CHECK: store i32 17
@@ -218,7 +218,7 @@ namespace N2 {
Z getZ();
- // CHECK: define void @_ZN2N21gEi
+ // CHECK-LABEL: define void @_ZN2N21gEi
// CHECK: call void @_ZN2N24getZEv
// CHECK: {{getelementptr inbounds.*i32 0, i32 0}}
// CHECK: {{getelementptr inbounds.*i32 0, i32 0}}
@@ -240,7 +240,7 @@ struct A {
~A();
};
-// CHECK: define internal void @__cxx_global_var_init
+// CHECK-LABEL: define internal void @__cxx_global_var_init
// CHECK: call void @_ZN2N31AC1Ei(%"struct.N3::A"* @_ZGRN2N35sA123E, i32 123)
// CHECK: call i32 @__cxa_atexit
// CHECK: ret void
@@ -255,7 +255,7 @@ struct A {
};
void f() {
- // CHECK: define void @_ZN2N41fEv
+ // CHECK-LABEL: define void @_ZN2N41fEv
// CHECK: call void @_ZN2N41AC1Ev(%"struct.N4::A"* @_ZGRZN2N41fEvE2ar)
// CHECK: call i32 @__cxa_atexit
// CHECK: ret void
@@ -279,7 +279,7 @@ void h() {
// PR9565
namespace PR9565 {
struct a { int a : 10, b : 10; };
- // CHECK: define void @_ZN6PR95651fEv()
+ // CHECK-LABEL: define void @_ZN6PR95651fEv()
void f() {
// CHECK: call void @llvm.memcpy
a x = { 0, 0 };
@@ -306,7 +306,7 @@ namespace PR9565 {
namespace N6 {
extern struct x {char& x;}y;
int a() { return y.x; }
- // CHECK: define i32 @_ZN2N61aEv
+ // CHECK-LABEL: define i32 @_ZN2N61aEv
// CHECK: [[REFLOAD3:%.*]] = load i8** getelementptr inbounds (%"struct.N6::x"* @_ZN2N61yE, i32 0, i32 0), align 8
// CHECK: load i8* [[REFLOAD3]], align 1
}
diff --git a/test/CodeGenCXX/return.cpp b/test/CodeGenCXX/return.cpp
index 43d40ae..1975055 100644
--- a/test/CodeGenCXX/return.cpp
+++ b/test/CodeGenCXX/return.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm -O0 -o - %s | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s
// RUN: %clang_cc1 -emit-llvm -O -o - %s | FileCheck %s --check-prefix=CHECK-OPT
// CHECK: @_Z9no_return
diff --git a/test/CodeGenCXX/rtti-layout.cpp b/test/CodeGenCXX/rtti-layout.cpp
index 7128c4e..0db2577 100644
--- a/test/CodeGenCXX/rtti-layout.cpp
+++ b/test/CodeGenCXX/rtti-layout.cpp
@@ -101,7 +101,7 @@ struct B {
static int (B::*d)[10];
};
-// CHECK: define i32 @_Z1fv()
+// CHECK-LABEL: define i32 @_Z1fv()
int f() {
// Vectors should be treated as fundamental types.
typedef short __v4hi __attribute__ ((__vector_size__ (8)));
diff --git a/test/CodeGenCXX/runtimecc.cpp b/test/CodeGenCXX/runtimecc.cpp
index 66d3f41..646c61e 100644
--- a/test/CodeGenCXX/runtimecc.cpp
+++ b/test/CodeGenCXX/runtimecc.cpp
@@ -20,7 +20,7 @@ namespace test0 {
};
A global;
-// CHECK: define internal arm_aapcscc void @__cxx_global_var_init()
+// CHECK-LABEL: 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
@@ -33,7 +33,7 @@ namespace test1 {
throw 0;
}
-// CHECK: define arm_aapcscc void @_ZN5test14testEv()
+// CHECK-LABEL: 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]]
@@ -45,7 +45,7 @@ namespace test1 {
// CHECK: declare arm_aapcscc void @__cxa_throw(i8*, i8*, i8*)
-// CHECK: define internal arm_aapcscc void @_GLOBAL__I_a()
+// CHECK-LABEL: define internal arm_aapcscc void @_GLOBAL__I_a()
// CHECK: call arm_aapcscc void @__cxx_global_var_init()
diff --git a/test/CodeGenCXX/rvalue-references.cpp b/test/CodeGenCXX/rvalue-references.cpp
index b8d47dc..2e0fa82 100644
--- a/test/CodeGenCXX/rvalue-references.cpp
+++ b/test/CodeGenCXX/rvalue-references.cpp
@@ -7,7 +7,7 @@ struct B : Spacer, A { };
B &getB();
-// CHECK: define %struct.A* @_Z4getAv()
+// CHECK-LABEL: define %struct.A* @_Z4getAv()
// CHECK: call %struct.B* @_Z4getBv()
// CHECK-NEXT: bitcast %struct.B*
// CHECK-NEXT: getelementptr inbounds i8*
@@ -19,17 +19,17 @@ int &getIntLValue();
int &&getIntXValue();
int getIntPRValue();
-// CHECK: define i32* @_Z2f0v()
+// CHECK-LABEL: define i32* @_Z2f0v()
// CHECK: call i32* @_Z12getIntLValuev()
// CHECK-NEXT: ret i32*
int &&f0() { return static_cast<int&&>(getIntLValue()); }
-// CHECK: define i32* @_Z2f1v()
+// CHECK-LABEL: define i32* @_Z2f1v()
// CHECK: call i32* @_Z12getIntXValuev()
// CHECK-NEXT: ret i32*
int &&f1() { return static_cast<int&&>(getIntXValue()); }
-// CHECK: define i32* @_Z2f2v
+// CHECK-LABEL: define i32* @_Z2f2v
// CHECK: call i32 @_Z13getIntPRValuev()
// CHECK-NEXT: store i32 {{.*}}, i32*
// CHECK-NEXT: ret i32*
@@ -59,7 +59,7 @@ public:
C test();
-// CHECK: define void @_Z15elide_copy_initv
+// CHECK-LABEL: define void @_Z15elide_copy_initv
void elide_copy_init() {
ok = false;
// CHECK: call void @_Z4testv
@@ -68,7 +68,7 @@ void elide_copy_init() {
// CHECK-NEXT: ret void
}
-// CHECK: define void @_Z16test_move_returnv
+// CHECK-LABEL: define void @_Z16test_move_returnv
C test_move_return() {
// CHECK: call void @_ZN1CC1Ei
C a1(3);
@@ -94,7 +94,7 @@ namespace test1 {
B(int i);
};
- // CHECK: define void @_ZN5test11BC2Ei(
+ // CHECK-LABEL: define void @_ZN5test11BC2Ei(
// CHECK: [[T0:%.*]] = call i32* @_ZN5test14moveERi(
// CHECK-NEXT: [[T1:%.*]] = load i32* [[T0]]
// CHECK-NEXT: call void @_ZN5test11AC1Ei({{.*}}, i32 [[T1]])
diff --git a/test/CodeGenCXX/scoped-enums.cpp b/test/CodeGenCXX/scoped-enums.cpp
index c20faaa..159172d 100644
--- a/test/CodeGenCXX/scoped-enums.cpp
+++ b/test/CodeGenCXX/scoped-enums.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -std=c++11 -emit-llvm -o - %s
+// RUN: %clang_cc1 -std=c++11 -emit-llvm -o - %s | FileCheck %s
// PR9923
enum class Color { red, blue, green };
@@ -15,3 +15,10 @@ void h(Colour);
void i() {
h(Colour::grey);
}
+
+enum struct PR17103 : int { a = -1, b = 1 };
+bool cmp(PR17103 x, PR17103 y) { return x < y; }
+
+// CHECK-LABEL: @_Z3cmp7PR17103S_(
+// CHECK-NOT: }
+// CHECK: icmp slt
diff --git a/test/CodeGenCXX/skip-vtable-pointer-initialization.cpp b/test/CodeGenCXX/skip-vtable-pointer-initialization.cpp
index 84697be..29926b9 100644
--- a/test/CodeGenCXX/skip-vtable-pointer-initialization.cpp
+++ b/test/CodeGenCXX/skip-vtable-pointer-initialization.cpp
@@ -10,7 +10,7 @@ struct A {
~A();
};
-// CHECK: define void @_ZN5Test11AD2Ev
+// CHECK-LABEL: define void @_ZN5Test11AD2Ev
// CHECK-NOT: store i8** getelementptr inbounds ([3 x i8*]* @_ZTVN5Test11AE, i64 0, i64 2), i8***
A::~A()
{
@@ -26,7 +26,7 @@ struct A {
~A();
};
-// CHECK: define void @_ZN5Test21AD2Ev
+// CHECK-LABEL: define void @_ZN5Test21AD2Ev
// CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTVN5Test21AE, i64 0, i64 2), i8***
A::~A() {
f();
@@ -49,7 +49,7 @@ struct A {
Field field;
};
-// CHECK: define void @_ZN5Test31AD2Ev
+// CHECK-LABEL: define void @_ZN5Test31AD2Ev
// CHECK-NOT: store i8** getelementptr inbounds ([3 x i8*]* @_ZTVN5Test31AE, i64 0, i64 2), i8***
A::~A() {
@@ -75,7 +75,7 @@ struct A {
Field field;
};
-// CHECK: define void @_ZN5Test41AD2Ev
+// CHECK-LABEL: define void @_ZN5Test41AD2Ev
// CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTVN5Test41AE, i64 0, i64 2), i8***
A::~A()
{
@@ -99,7 +99,7 @@ struct A {
Field field;
};
-// CHECK: define void @_ZN5Test51AD2Ev
+// CHECK-LABEL: define void @_ZN5Test51AD2Ev
// CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTVN5Test51AE, i64 0, i64 2), i8***
A::~A()
{
@@ -127,7 +127,7 @@ struct A {
Field field;
};
-// CHECK: define void @_ZN5Test61AD2Ev
+// CHECK-LABEL: define void @_ZN5Test61AD2Ev
// CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTVN5Test61AE, i64 0, i64 2), i8***
A::~A()
{
@@ -153,7 +153,7 @@ struct A {
Field field;
};
-// CHECK: define void @_ZN5Test71AD2Ev
+// CHECK-LABEL: define void @_ZN5Test71AD2Ev
// CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTVN5Test71AE, i64 0, i64 2), i8***
A::~A()
{
@@ -179,7 +179,7 @@ struct A {
Field field;
};
-// CHECK: define void @_ZN5Test81AD2Ev
+// CHECK-LABEL: define void @_ZN5Test81AD2Ev
// CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTVN5Test81AE, i64 0, i64 2), i8***
A::~A()
{
diff --git a/test/CodeGenCXX/static-data-member.cpp b/test/CodeGenCXX/static-data-member.cpp
index 4ad339d..eea9794 100644
--- a/test/CodeGenCXX/static-data-member.cpp
+++ b/test/CodeGenCXX/static-data-member.cpp
@@ -42,7 +42,7 @@ namespace test2 {
template struct A<int>;
}
- // CHECK: define internal void @__cxx_global_var_init()
+ // CHECK-LABEL: define internal void @__cxx_global_var_init()
// CHECK: [[TMP:%.*]] = call i32 @_ZN5test23fooEv()
// CHECK-NEXT: store i32 [[TMP]], i32* @_ZN5test212_GLOBAL__N_11AIiE1xE, align 4
// CHECK-NEXT: ret void
@@ -60,7 +60,7 @@ namespace test3 {
template <class T> int A<T>::x = foo();
template struct A<int>;
- // CHECK: define internal void @__cxx_global_var_init1()
+ // CHECK-LABEL: define internal void @__cxx_global_var_init1()
// CHECK: [[GUARDBYTE:%.*]] = load i8* bitcast (i64* @_ZGVN5test31AIiE1xE to i8*)
// CHECK-NEXT: [[UNINITIALIZED:%.*]] = icmp eq i8 [[GUARDBYTE]], 0
// CHECK-NEXT: br i1 [[UNINITIALIZED]]
@@ -79,7 +79,7 @@ namespace test4 {
};
int f(A *a) {
- // CHECK: define i32 @_ZN5test41fEPNS_1AE
+ // CHECK-LABEL: define i32 @_ZN5test41fEPNS_1AE
// CHECK: ret i32 76
return a->n;
}
diff --git a/test/CodeGenCXX/static-init-1.cpp b/test/CodeGenCXX/static-init-1.cpp
index a926c0a..09bf7bf 100644
--- a/test/CodeGenCXX/static-init-1.cpp
+++ b/test/CodeGenCXX/static-init-1.cpp
@@ -1,5 +1,4 @@
-// RUN: %clang_cc1 -triple=x86_64-apple-darwin9 -emit-llvm %s -o %t
-// RUN: grep "call i32 @_Z5func1i" %t | count 3
+// RUN: %clang_cc1 -triple=x86_64-apple-darwin9 -emit-llvm %s -o - | FileCheck %s
extern "C" int printf(...);
@@ -9,15 +8,18 @@ int func2(int c) { return printf("loading the func2(%d)\n", c); };
int func1(int c) { return printf("loading the func1(%d)\n", c); }
static int loader_1 = func1(++count);
+// CHECK: call i32 @_Z5func1i
int loader_2 = func2(++count);
static int loader_3 = func1(++count);
-
+// CHECK: call i32 @_Z5func1i
int main() {}
int loader_4 = func2(++count);
static int loader_5 = func1(++count);
int loader_6 = func2(++count);
+// CHECK: call i32 @_Z5func1i
+// CHECK-NOT: call i32 @_Z5func1i
diff --git a/test/CodeGenCXX/static-init-4.cpp b/test/CodeGenCXX/static-init-4.cpp
new file mode 100644
index 0000000..a4bb987
--- /dev/null
+++ b/test/CodeGenCXX/static-init-4.cpp
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 -std=c++11 -S -emit-llvm -o - %s -triple x86_64-linux-gnu | FileCheck %s
+
+typedef __attribute__((vector_size(4*4))) float float32x4_t;
+union QDSUnion { float32x4_t q; float s[4]; };
+constexpr float32x4_t a = {1,2,3,4};
+QDSUnion t = {{(a)}};
+// CHECK: @t = global %union.QDSUnion { <4 x float> <float 1.000000e+00, float 2.000000e+00, float 3.000000e+00, float 4.000000e+00> }
diff --git a/test/CodeGenCXX/static-init-pnacl.cpp b/test/CodeGenCXX/static-init-pnacl.cpp
new file mode 100644
index 0000000..de35ec3
--- /dev/null
+++ b/test/CodeGenCXX/static-init-pnacl.cpp
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -emit-llvm -triple=le32-unknown-nacl -o - %s | FileCheck %s
+
+int f();
+
+// Test that PNaCl uses the Itanium/x86 ABI in which the static
+// variable's guard variable is tested via "load i8 and compare with
+// zero" rather than the ARM ABI which uses "load i32 and test the
+// bottom bit".
+void g() {
+ static int a = f();
+}
+// CHECK: [[LOAD:%.*]] = load atomic i8* bitcast (i64* @_ZGVZ1gvE1a to i8*) acquire
+// CHECK-NEXT: [[GUARD:%.*]] = icmp eq i8 [[LOAD]], 0
+// CHECK-NEXT: br i1 [[GUARD]]
diff --git a/test/CodeGenCXX/static-init.cpp b/test/CodeGenCXX/static-init.cpp
index 74278f7..f522775 100644
--- a/test/CodeGenCXX/static-init.cpp
+++ b/test/CodeGenCXX/static-init.cpp
@@ -54,7 +54,7 @@ namespace test0 {
}
namespace test1 {
- // CHECK: define internal i32 @_ZN5test1L6getvarEi(
+ // CHECK-LABEL: define internal i32 @_ZN5test1L6getvarEi(
static inline int getvar(int index) {
static const int var[] = { 1, 0, 2, 4 };
return var[index];
@@ -68,7 +68,7 @@ char base_req[] = { "foo" };
unsigned char base_req_uchar[] = { "bar" };
namespace union_static_local {
- // CHECK: define internal void @_ZZN18union_static_local4testEvEN1c4mainEv
+ // CHECK-LABEL: define internal void @_ZZN18union_static_local4testEvEN1c4mainEv
// CHECK: call void @_ZN18union_static_local1fEPNS_1xE(%"union.union_static_local::x"* bitcast ({ [2 x i8*] }* @_ZZN18union_static_local4testEvE3foo to %"union.union_static_local::x"*))
union x { long double y; const char *x[2]; };
void f(union x*);
@@ -103,14 +103,14 @@ namespace test2 {
B::B() {
static int x = foo();
}
- // CHECK: define void @_ZN5test21BC1Ev
+ // CHECK-LABEL: define void @_ZN5test21BC1Ev
// CHECK: load atomic i8* bitcast (i64* @_ZGVZN5test21BC1EvE1x to i8*) acquire,
// CHECK: call i32 @__cxa_guard_acquire(i64* @_ZGVZN5test21BC1EvE1x)
// CHECK: [[T0:%.*]] = call i32 @_ZN5test23fooEv()
// CHECK: store i32 [[T0]], i32* @_ZZN5test21BC1EvE1x,
// CHECK: call void @__cxa_guard_release(i64* @_ZGVZN5test21BC1EvE1x)
- // CHECK: define void @_ZN5test21BC2Ev
+ // CHECK-LABEL: define void @_ZN5test21BC2Ev
// CHECK: load atomic i8* bitcast (i64* @_ZGVZN5test21BC1EvE1x to i8*) acquire,
// CHECK: call i32 @__cxa_guard_acquire(i64* @_ZGVZN5test21BC1EvE1x)
// CHECK: [[T0:%.*]] = call i32 @_ZN5test23fooEv()
@@ -122,10 +122,10 @@ namespace test2 {
B::~B() {
static int y = foo();
}
- // CHECK: define void @_ZN5test21BD1Ev(
+ // CHECK-LABEL: define void @_ZN5test21BD1Ev(
// CHECK: call void @_ZN5test21BD2Ev(
- // CHECK: define void @_ZN5test21BD2Ev(
+ // CHECK-LABEL: define void @_ZN5test21BD2Ev(
// CHECK: load atomic i8* bitcast (i64* @_ZGVZN5test21BD1EvE1y to i8*) acquire,
// CHECK: call i32 @__cxa_guard_acquire(i64* @_ZGVZN5test21BD1EvE1y)
// CHECK: [[T0:%.*]] = call i32 @_ZN5test23fooEv()
@@ -149,6 +149,6 @@ namespace test3 {
union U { char x; int i; };
static U u = { 'a' };
}
- // CHECK: define void @_ZN5test31BC1Ev(
- // CHECK: define void @_ZN5test31BC2Ev(
+ // CHECK-LABEL: define void @_ZN5test31BC1Ev(
+ // CHECK-LABEL: define void @_ZN5test31BC2Ev(
}
diff --git a/test/CodeGenCXX/static-member-variable-explicit-specialization.cpp b/test/CodeGenCXX/static-member-variable-explicit-specialization.cpp
index 94fd9aa..50772bf 100644
--- a/test/CodeGenCXX/static-member-variable-explicit-specialization.cpp
+++ b/test/CodeGenCXX/static-member-variable-explicit-specialization.cpp
@@ -1,6 +1,10 @@
-// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -std=c++1y -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s
// CHECK: ; ModuleID
-template<typename> struct A { static int a; };
+
+extern "C" int foo();
+
+template<typename T> struct A { static int a; };
+template<typename T> int A<T>::a = foo();
// CHECK-NOT: @_ZN1AIcE1aE
template<> int A<char>::a;
@@ -8,4 +12,85 @@ template<> int A<char>::a;
// CHECK: @_ZN1AIbE1aE = global i32 10
template<> int A<bool>::a = 10;
+// CHECK: @llvm.global_ctors = appending global [7 x { i32, void ()* }]
+// CHECK: [{ i32, void ()* } { i32 65535, void ()* @[[unordered1:[^ ]*]] },
+// CHECK: { i32, void ()* } { i32 65535, void ()* @[[unordered2:[^ ]*]] },
+// CHECK: { i32, void ()* } { i32 65535, void ()* @[[unordered3:[^ ]*]] },
+// CHECK: { i32, void ()* } { i32 65535, void ()* @[[unordered4:[^ ]*]] },
+// CHECK: { i32, void ()* } { i32 65535, void ()* @[[unordered5:[^ ]*]] },
+// CHECK: { i32, void ()* } { i32 65535, void ()* @[[unordered6:[^ ]*]] },
+// CHECK: { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I_a }]
+
+template int A<short>::a; // Unordered
+int b = foo();
+int c = foo();
+int d = A<void>::a; // Unordered
+
+// An explicit specialization is ordered, and goes in __GLOBAL_I_a.
+template<> struct A<int> { static int a; };
+int A<int>::a = foo();
+
+template<typename T> struct S { static T x; static T y; };
+template<> int S<int>::x = foo();
+template<> int S<int>::y = S<int>::x;
+
+template<typename T> T x = foo();
+template short x<short>; // Unordered
+template<> int x<int> = foo();
+int e = x<char>; // Unordered
+
+namespace ns {
+template <typename T> struct a {
+ static int i;
+};
+template<typename T> int a<T>::i = foo();
+template struct a<int>;
+
+struct b {
+ template <typename T> static T i;
+};
+template<typename T> T b::i = foo();
+template int b::i<int>;
+}
+// CHECK: define internal void @[[unordered1]]
+// CHECK: call i32 @foo()
+// CHECK: store {{.*}} @_ZN1AIsE1aE
+// CHECK: ret
+
+// CHECK: define internal void @[[unordered2]]
+// CHECK: call i32 @foo()
+// CHECK: store {{.*}} @_Z1xIsE
+// CHECK: ret
+
+// CHECK: define internal void @[[unordered3]]
+// CHECK: call i32 @foo()
+// CHECK: store {{.*}} @_ZN2ns1aIiE1iE
+// CHECK: ret
+
+// CHECK: define internal void @[[unordered4]]
+// CHECK: call i32 @foo()
+// CHECK: store {{.*}} @_ZN2ns1b1iIiEE
+// CHECK: ret
+
+// CHECK: define internal void @[[unordered5]]
+// CHECK: call i32 @foo()
+// CHECK: store {{.*}} @_ZN1AIvE1aE
+// CHECK: ret
+
+// CHECK: define internal void @[[unordered6]]
+// CHECK: call i32 @foo()
+// CHECK: store {{.*}} @_Z1xIcE
+// CHECK: ret
+// CHECK: define internal void @_GLOBAL__I_a()
+// We call unique stubs for every ordered dynamic initializer in the TU.
+// CHECK: call
+// CHECK: call
+// CHECK: call
+// CHECK: call
+// CHECK: call
+// CHECK: call
+// CHECK: call
+// CHECK: call
+// CHECK-NOT: call
+// CHECK: ret
diff --git a/test/CodeGenCXX/stmtexpr.cpp b/test/CodeGenCXX/stmtexpr.cpp
index 1f0e4ac..5d4d6bc 100644
--- a/test/CodeGenCXX/stmtexpr.cpp
+++ b/test/CodeGenCXX/stmtexpr.cpp
@@ -73,3 +73,10 @@ int* foo5() {
return (({ a; }));
}
+// <rdar://problem/14074868>
+// Make sure this doesn't crash.
+int foo5(bool b) {
+ int y = 0;
+ y = ({ A a(1); if (b) goto G; a.i; });
+ G: return y;
+}
diff --git a/test/CodeGenCXX/template-anonymous-types.cpp b/test/CodeGenCXX/template-anonymous-types.cpp
index 3df487a..f4d6549 100644
--- a/test/CodeGenCXX/template-anonymous-types.cpp
+++ b/test/CodeGenCXX/template-anonymous-types.cpp
@@ -19,19 +19,19 @@ template <typename T> int f(T t) {
void test() {
// Look for two instantiations, one for FOO's
// type and one for BAR's.
- // CHECK: define linkonce_odr i32 @_Z1fIN1SUt_EEiT_(i32 %t)
+ // CHECK-LABEL: define linkonce_odr i32 @_Z1fIN1SUt_EEiT_(i32 %t)
(void)f(S::FOO);
- // CHECK: define linkonce_odr i32 @_Z1fIN1SUt0_EEiT_(i32 %t)
+ // CHECK-LABEL: 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 linkonce_odr i32 @_ZN1XIN1SUt0_EE1fEv(%struct.X* %this)
- // CHECK: define linkonce_odr void @_ZN1XIN1SUt0_EEC2ES1_(%struct.X* %this, i32 %t) unnamed_addr
+ // CHECK-LABEL: define linkonce_odr i32 @_ZN1XIN1SUt0_EE1fEv(%struct.X* %this)
+ // CHECK-LABEL: define linkonce_odr void @_ZN1XIN1SUt0_EEC2ES1_(%struct.X* %this, i32 %t) unnamed_addr
//
// FOO's instantiation of X:
- // 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
+ // CHECK-LABEL: define linkonce_odr i32 @_ZN1XIN1SUt_EE1fEv(%struct.X.0* %this)
+ // CHECK-LABEL: define linkonce_odr void @_ZN1XIN1SUt_EEC2ES1_(%struct.X.0* %this, i32 %t) unnamed_addr
}
diff --git a/test/CodeGenCXX/template-dependent-bind-temporary.cpp b/test/CodeGenCXX/template-dependent-bind-temporary.cpp
index cc1ce86..ca980c3 100644
--- a/test/CodeGenCXX/template-dependent-bind-temporary.cpp
+++ b/test/CodeGenCXX/template-dependent-bind-temporary.cpp
@@ -18,7 +18,7 @@ void IntToString(T a)
}
int main() {
-// CHECK: define linkonce_odr void @_Z11IntToStringIcEvT_(
+// CHECK-LABEL: define linkonce_odr void @_Z11IntToStringIcEvT_(
IntToString('a');
}
diff --git a/test/CodeGenCXX/template-inner-struct-visibility-hidden.cpp b/test/CodeGenCXX/template-inner-struct-visibility-hidden.cpp
index 2c62b60..de86f10 100644
--- a/test/CodeGenCXX/template-inner-struct-visibility-hidden.cpp
+++ b/test/CodeGenCXX/template-inner-struct-visibility-hidden.cpp
@@ -2,8 +2,8 @@
// Verify that symbols are hidden.
// CHECK: @_ZN1CIiE5Inner6Inner26StaticE = weak_odr hidden global
-// CHECK: define weak_odr hidden void @_ZN1CIiE5Inner1fEv
-// CHECK: define weak_odr hidden void @_ZN1CIiE5Inner6Inner21gEv
+// CHECK-LABEL: define weak_odr hidden void @_ZN1CIiE5Inner1fEv
+// CHECK-LABEL: define weak_odr hidden void @_ZN1CIiE5Inner6Inner21gEv
template<typename T>
struct C {
diff --git a/test/CodeGenCXX/template-instantiation.cpp b/test/CodeGenCXX/template-instantiation.cpp
index b90716b..80283a1 100644
--- a/test/CodeGenCXX/template-instantiation.cpp
+++ b/test/CodeGenCXX/template-instantiation.cpp
@@ -13,16 +13,16 @@
// CHECK-NOT: _ZTVN5test31SIiEE
// CHECK-NOT: _ZTSN5test31SIiEE
-// CHECK: define linkonce_odr void @_ZN5test21CIiEC1Ev(%"class.test2::C"* %this) unnamed_addr
-// CHECK: define linkonce_odr void @_ZN5test21CIiE6foobarIdEEvT_(
-// CHECK: define available_externally void @_ZN5test21CIiE6zedbarEd(
-
-// CHECK: define linkonce_odr void @_ZN7PR106662g1ENS_1SILi1EEE()
-// CHECK: define linkonce_odr void @_ZN7PR106662g1ENS_1SILi2EEE()
-// CHECK: define linkonce_odr void @_ZN7PR106662g1ENS_1SILi3EEE()
-// CHECK: define linkonce_odr void @_ZN7PR106662g2ENS_1SILi1EEE()
-// CHECK: define linkonce_odr void @_ZN7PR106662g2ENS_1SILi2EEE()
-// CHECK: define linkonce_odr void @_ZN7PR106662g2ENS_1SILi3EEE()
+// CHECK-LABEL: define linkonce_odr void @_ZN5test21CIiEC1Ev(%"class.test2::C"* %this) unnamed_addr
+// CHECK-LABEL: define linkonce_odr void @_ZN5test21CIiE6foobarIdEEvT_(
+// CHECK-LABEL: define available_externally void @_ZN5test21CIiE6zedbarEd(
+
+// CHECK-LABEL: define linkonce_odr void @_ZN7PR106662g1ENS_1SILi1EEE()
+// CHECK-LABEL: define linkonce_odr void @_ZN7PR106662g1ENS_1SILi2EEE()
+// CHECK-LABEL: define linkonce_odr void @_ZN7PR106662g1ENS_1SILi3EEE()
+// CHECK-LABEL: define linkonce_odr void @_ZN7PR106662g2ENS_1SILi1EEE()
+// CHECK-LABEL: define linkonce_odr void @_ZN7PR106662g2ENS_1SILi2EEE()
+// CHECK-LABEL: define linkonce_odr void @_ZN7PR106662g2ENS_1SILi3EEE()
// CHECK: declare void @_ZN7PR106662h1ENS_1SILi1EEE()
// CHECK: declare void @_ZN7PR106662h1ENS_1SILi2EEE()
// CHECK: declare void @_ZN7PR106662h1ENS_1SILi3EEE()
diff --git a/test/CodeGenCXX/template-linkage.cpp b/test/CodeGenCXX/template-linkage.cpp
index 3acd12e..a84affa 100644
--- a/test/CodeGenCXX/template-linkage.cpp
+++ b/test/CodeGenCXX/template-linkage.cpp
@@ -9,19 +9,19 @@ template<typename T> struct A {
// Explicit instantiations have external linkage.
-// CHECK: define weak_odr void @_ZN1AIiE1gEv(
+// CHECK-LABEL: define weak_odr void @_ZN1AIiE1gEv(
template void A<int>::g();
-// CHECK: define weak_odr void @_ZN1AIfE1fEf(
-// CHECK: define weak_odr void @_ZN1AIfE1gEv(
+// CHECK-LABEL: define weak_odr void @_ZN1AIfE1fEf(
+// CHECK-LABEL: define weak_odr void @_ZN1AIfE1gEv(
// FIXME: This should also emit the vtable.
template struct A<float>;
-// CHECK: define weak_odr void @_Z1fIiEvT_
+// CHECK-LABEL: define weak_odr void @_Z1fIiEvT_
template <typename T> void f(T) { }
template void f<int>(int);
-// CHECK: define weak_odr void @_Z1gIiEvT_
+// CHECK-LABEL: define weak_odr void @_Z1gIiEvT_
template <typename T> inline void g(T) { }
template void g<int>(int);
@@ -40,7 +40,7 @@ template<typename T> void X1<T>::blarg() { }
extern template struct X0<char>;
extern template struct X1<char>;
-// CHECK: define linkonce_odr void @_ZN2X1IcED1Ev(%struct.X1* %this) unnamed_addr
+// CHECK-LABEL: define linkonce_odr void @_ZN2X1IcED1Ev(%struct.X1* %this) unnamed_addr
void test_X1() {
X1<char> i1c;
}
diff --git a/test/CodeGenCXX/temporaries.cpp b/test/CodeGenCXX/temporaries.cpp
index a369c2e..e8a7a1f 100644
--- a/test/CodeGenCXX/temporaries.cpp
+++ b/test/CodeGenCXX/temporaries.cpp
@@ -1,4 +1,32 @@
-// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 -std=c++11 | FileCheck %s
+
+namespace PR16263 {
+ const unsigned int n = 1234;
+ extern const int &r = (const int&)n;
+ // CHECK: @_ZGRN7PR162631rE = private constant i32 1234,
+ // CHECK: @_ZN7PR162631rE = constant i32* @_ZGRN7PR162631rE,
+
+ extern const int &s = reinterpret_cast<const int&>(n);
+ // CHECK: @_ZN7PR16263L1nE = internal constant i32 1234, align 4
+ // CHECK: @_ZN7PR162631sE = constant i32* @_ZN7PR16263L1nE, align 8
+
+ struct A { int n; };
+ struct B { int n; };
+ struct C : A, B {};
+ extern const A &&a = (A&&)(A&&)(C&&)(C{});
+ // CHECK: @_ZGRN7PR162631aE = private global {{.*}} zeroinitializer,
+ // CHECK: @_ZN7PR162631aE = constant {{.*}} bitcast ({{.*}}* @_ZGRN7PR162631aE to
+
+ extern const int &&t = ((B&&)C{}).n;
+ // CHECK: @_ZGRN7PR162631tE = private global {{.*}} zeroinitializer,
+ // CHECK: @_ZN7PR162631tE = constant i32* {{.*}}* @_ZGRN7PR162631tE {{.*}} 4
+
+ struct D { double d; C c; };
+ extern const int &&u = (123, static_cast<B&&>(0, ((D&&)D{}).*&D::c).n);
+ // CHECK: @_ZGRN7PR162631uE = private global {{.*}} zeroinitializer
+ // CHECK: @_ZN7PR162631uE = constant i32* {{.*}} @_ZGRN7PR162631uE {{.*}} 12
+}
+
struct A {
A();
~A();
@@ -226,7 +254,7 @@ namespace PR5867 {
};
void f(S, int);
- // CHECK: define void @_ZN6PR58671gEv
+ // CHECK-LABEL: define void @_ZN6PR58671gEv
void g() {
// CHECK: call void @_ZN6PR58671SC1Ev
// CHECK-NEXT: call void @_ZN6PR58671fENS_1SEi
@@ -235,7 +263,7 @@ namespace PR5867 {
(f)(S(), 0);
}
- // CHECK: define linkonce_odr void @_ZN6PR58672g2IiEEvT_
+ // CHECK-LABEL: define linkonce_odr void @_ZN6PR58672g2IiEEvT_
template<typename T>
void g2(T) {
// CHECK: call void @_ZN6PR58671SC1Ev
@@ -256,7 +284,7 @@ namespace PR6199 {
struct B { operator A(); };
- // CHECK: define weak_odr void @_ZN6PR61992f2IiEENS_1AET_
+ // CHECK-LABEL: define weak_odr void @_ZN6PR61992f2IiEENS_1AET_
template<typename T> A f2(T) {
B b;
// CHECK: call void @_ZN6PR61991BcvNS_1AEEv
@@ -278,7 +306,7 @@ struct A {
int& f(int);
-// CHECK: define void @_ZN3T121gEv
+// CHECK-LABEL: define void @_ZN3T121gEv
void g() {
// CHECK: call void @_ZN3T121AC1Ev
// CHECK-NEXT: call i32 @_ZN3T121A1fEv(
@@ -325,7 +353,7 @@ namespace PR7556 {
struct A { ~A(); };
struct B { int i; ~B(); };
struct C { int C::*pm; ~C(); };
- // CHECK: define void @_ZN6PR75563fooEv()
+ // CHECK-LABEL: define void @_ZN6PR75563fooEv()
void foo() {
// CHECK: call void @_ZN6PR75561AD1Ev
A();
@@ -350,7 +378,7 @@ namespace Elision {
A fooA();
void takeA(A a);
- // CHECK: define void @_ZN7Elision5test0Ev()
+ // CHECK-LABEL: define void @_ZN7Elision5test0Ev()
void test0() {
// CHECK: [[I:%.*]] = alloca [[A:%.*]], align 8
// CHECK-NEXT: [[J:%.*]] = alloca [[A]], align 8
@@ -378,7 +406,7 @@ namespace Elision {
}
- // CHECK: define void @_ZN7Elision5test1EbNS_1AE(
+ // CHECK-LABEL: define void @_ZN7Elision5test1EbNS_1AE(
void test1(bool c, A x) {
// CHECK: [[I:%.*]] = alloca [[A]], align 8
// CHECK-NEXT: [[J:%.*]] = alloca [[A]], align 8
@@ -417,7 +445,7 @@ namespace Elision {
// CHECK: ret void
}
- // CHECK: define void @_ZN7Elision5test4Ev()
+ // CHECK-LABEL: define void @_ZN7Elision5test4Ev()
void test4() {
// CHECK: [[X:%.*]] = alloca [[A]], align 8
// CHECK-NEXT: [[XS:%.*]] = alloca [2 x [[A]]], align 16
@@ -493,7 +521,7 @@ namespace Elision {
namespace PR8623 {
struct A { A(int); ~A(); };
- // CHECK: define void @_ZN6PR86233fooEb(
+ // CHECK-LABEL: define void @_ZN6PR86233fooEb(
void foo(bool b) {
// CHECK: [[TMP:%.*]] = alloca [[A:%.*]], align 1
// CHECK-NEXT: [[LCONS:%.*]] = alloca i1
@@ -523,7 +551,7 @@ namespace PR8623 {
namespace PR11365 {
struct A { A(); ~A(); };
- // CHECK: define void @_ZN7PR113653fooEv(
+ // CHECK-LABEL: define void @_ZN7PR113653fooEv(
void foo() {
// CHECK: [[BEGIN:%.*]] = getelementptr inbounds [3 x [[A:%.*]]]* {{.*}}, i32 0, i32 0
// CHECK-NEXT: [[END:%.*]] = getelementptr inbounds [[A]]* [[BEGIN]], i64 3
@@ -542,7 +570,7 @@ namespace AssignmentOp {
struct A { ~A(); };
struct B { A operator=(const B&); };
struct C : B { B b1, b2; };
- // CHECK: define void @_ZN12AssignmentOp1fE
+ // CHECK-LABEL: define void @_ZN12AssignmentOp1fE
void f(C &c1, const C &c2) {
// CHECK: call {{.*}} @_ZN12AssignmentOp1CaSERKS0_(
c1 = c2;
@@ -558,3 +586,194 @@ namespace AssignmentOp {
// CHECK: call {{.*}} @_ZN12AssignmentOp1BaSERKS
// CHECK: call {{.*}} @_ZN12AssignmentOp1AD1Ev(
}
+
+namespace BindToSubobject {
+ struct A {
+ A();
+ ~A();
+ int a;
+ };
+
+ void f(), g();
+
+ // CHECK: call void @_ZN15BindToSubobject1AC1Ev({{.*}} @_ZGRN15BindToSubobject1aE)
+ // CHECK: call i32 @__cxa_atexit({{.*}} bitcast ({{.*}} @_ZN15BindToSubobject1AD1Ev to void (i8*)*), i8* bitcast ({{.*}} @_ZGRN15BindToSubobject1aE to i8*), i8* @__dso_handle)
+ // CHECK: store i32* getelementptr inbounds ({{.*}} @_ZGRN15BindToSubobject1aE, i32 0, i32 0), i32** @_ZN15BindToSubobject1aE, align 8
+ int &&a = A().a;
+
+ // CHECK: call void @_ZN15BindToSubobject1fEv()
+ // CHECK: call void @_ZN15BindToSubobject1AC1Ev({{.*}} @_ZGRN15BindToSubobject1bE)
+ // CHECK: call i32 @__cxa_atexit({{.*}} bitcast ({{.*}} @_ZN15BindToSubobject1AD1Ev to void (i8*)*), i8* bitcast ({{.*}} @_ZGRN15BindToSubobject1bE to i8*), i8* @__dso_handle)
+ // CHECK: store i32* getelementptr inbounds ({{.*}} @_ZGRN15BindToSubobject1bE, i32 0, i32 0), i32** @_ZN15BindToSubobject1bE, align 8
+ int &&b = (f(), A().a);
+
+ int A::*h();
+
+ // CHECK: call void @_ZN15BindToSubobject1fEv()
+ // CHECK: call void @_ZN15BindToSubobject1gEv()
+ // CHECK: call void @_ZN15BindToSubobject1AC1Ev({{.*}} @_ZGRN15BindToSubobject1cE)
+ // CHECK: call i32 @__cxa_atexit({{.*}} bitcast ({{.*}} @_ZN15BindToSubobject1AD1Ev to void (i8*)*), i8* bitcast ({{.*}} @_ZGRN15BindToSubobject1cE to i8*), i8* @__dso_handle)
+ // CHECK: call {{.*}} @_ZN15BindToSubobject1hE
+ // CHECK: getelementptr
+ // CHECK: store i32* {{.*}}, i32** @_ZN15BindToSubobject1cE, align 8
+ int &&c = (f(), (g(), A().*h()));
+
+ struct B {
+ int padding;
+ A a;
+ };
+
+ // CHECK: call void @_ZN15BindToSubobject1BC1Ev({{.*}} @_ZGRN15BindToSubobject1dE)
+ // CHECK: call i32 @__cxa_atexit({{.*}} bitcast ({{.*}} @_ZN15BindToSubobject1BD1Ev to void (i8*)*), i8* bitcast ({{.*}} @_ZGRN15BindToSubobject1dE to i8*), i8* @__dso_handle)
+ // CHECK: call {{.*}} @_ZN15BindToSubobject1hE
+ // CHECK: getelementptr {{.*}} getelementptr
+ // CHECK: store i32* {{.*}}, i32** @_ZN15BindToSubobject1dE, align 8
+ int &&d = (B().a).*h();
+}
+
+namespace Bitfield {
+ struct S { int a : 5; ~S(); };
+
+ // Do not lifetime extend the S() temporary here.
+ // CHECK: alloca
+ // CHECK: call {{.*}}memset
+ // CHECK: store i32 {{.*}}, i32* @_ZGRN8Bitfield1rE
+ // CHECK: call void @_ZN8Bitfield1SD1
+ // CHECK: store i32* @_ZGRN8Bitfield1rE, i32** @_ZN8Bitfield1rE, align 8
+ int &&r = S().a;
+}
+
+namespace Vector {
+ typedef __attribute__((vector_size(16))) int vi4a;
+ typedef __attribute__((ext_vector_type(4))) int vi4b;
+ struct S {
+ vi4a v;
+ vi4b w;
+ };
+ // CHECK: alloca
+ // CHECK: extractelement
+ // CHECK: store i32 {{.*}}, i32* @_ZGRN6Vector1rE
+ // CHECK: store i32* @_ZGRN6Vector1rE, i32** @_ZN6Vector1rE,
+ int &&r = S().v[1];
+
+ // CHECK: alloca
+ // CHECK: extractelement
+ // CHECK: store i32 {{.*}}, i32* @_ZGRN6Vector1sE
+ // CHECK: store i32* @_ZGRN6Vector1sE, i32** @_ZN6Vector1sE,
+ int &&s = S().w[1];
+ // FIXME PR16204: The following code leads to an assertion in Sema.
+ //int &&s = S().w.y;
+}
+
+namespace ImplicitTemporaryCleanup {
+ struct A { A(int); ~A(); };
+ void g();
+
+ // CHECK-LABEL: define void @_ZN24ImplicitTemporaryCleanup1fEv(
+ void f() {
+ // CHECK: call {{.*}} @_ZN24ImplicitTemporaryCleanup1AC1Ei(
+ A &&a = 0;
+
+ // CHECK: call {{.*}} @_ZN24ImplicitTemporaryCleanup1gEv(
+ g();
+
+ // CHECK: call {{.*}} @_ZN24ImplicitTemporaryCleanup1AD1Ev(
+ }
+}
+
+namespace MultipleExtension {
+ struct A { A(); ~A(); };
+ struct B { B(); ~B(); };
+ struct C { C(); ~C(); };
+ struct D { D(); ~D(); int n; C c; };
+ struct E { const A &a; B b; const C &c; ~E(); };
+
+ E &&e1 = { A(), B(), D().c };
+
+ // CHECK: call void @_ZN17MultipleExtension1AC1Ev({{.*}} @[[TEMPA:_ZGRN17MultipleExtension2e1E.*]])
+ // CHECK: call i32 @__cxa_atexit({{.*}} @_ZN17MultipleExtension1AD1Ev {{.*}} @[[TEMPA]]
+ // CHECK: store {{.*}} @[[TEMPA]], {{.*}} getelementptr inbounds ({{.*}} @[[TEMPE:_ZGRN17MultipleExtension2e1E.*]], i32 0, i32 0)
+
+ // CHECK: call void @_ZN17MultipleExtension1BC1Ev({{.*}} getelementptr inbounds ({{.*}} @[[TEMPE]], i32 0, i32 1))
+
+ // CHECK: call void @_ZN17MultipleExtension1DC1Ev({{.*}} @[[TEMPD:_ZGRN17MultipleExtension2e1E.*]])
+ // CHECK: call i32 @__cxa_atexit({{.*}} @_ZN17MultipleExtension1DD1Ev {{.*}} @[[TEMPD]]
+ // CHECK: store {{.*}} @[[TEMPD]], {{.*}} getelementptr inbounds ({{.*}} @[[TEMPE]], i32 0, i32 2)
+ // CHECK: call i32 @__cxa_atexit({{.*}} @_ZN17MultipleExtension1ED1Ev {{.*}} @[[TEMPE]]
+ // CHECK: store {{.*}} @[[TEMPE]], %"struct.MultipleExtension::E"** @_ZN17MultipleExtension2e1E, align 8
+
+ E e2 = { A(), B(), D().c };
+
+ // CHECK: call void @_ZN17MultipleExtension1AC1Ev({{.*}} @[[TEMPA:_ZGRN17MultipleExtension2e2E.*]])
+ // CHECK: call i32 @__cxa_atexit({{.*}} @_ZN17MultipleExtension1AD1Ev {{.*}} @[[TEMPA]]
+ // CHECK: store {{.*}} @[[TEMPA]], {{.*}} getelementptr inbounds ({{.*}} @[[E:_ZN17MultipleExtension2e2E]], i32 0, i32 0)
+
+ // CHECK: call void @_ZN17MultipleExtension1BC1Ev({{.*}} getelementptr inbounds ({{.*}} @[[E]], i32 0, i32 1))
+
+ // CHECK: call void @_ZN17MultipleExtension1DC1Ev({{.*}} @[[TEMPD:_ZGRN17MultipleExtension2e2E.*]])
+ // CHECK: call i32 @__cxa_atexit({{.*}} @_ZN17MultipleExtension1DD1Ev {{.*}} @[[TEMPD]]
+ // CHECK: store {{.*}} @[[TEMPD]], {{.*}} getelementptr inbounds ({{.*}} @[[E]], i32 0, i32 2)
+ // CHECK: call i32 @__cxa_atexit({{.*}} @_ZN17MultipleExtension1ED1Ev {{.*}} @[[E]]
+
+
+ void g();
+ // CHECK: define void @[[NS:_ZN17MultipleExtension]]1fEv(
+ void f() {
+ E &&e1 = { A(), B(), D().c };
+ // CHECK: %[[TEMPE1_A:.*]] = getelementptr inbounds {{.*}} %[[TEMPE1:.*]], i32 0, i32 0
+ // CHECK: call void @[[NS]]1AC1Ev({{.*}} %[[TEMPA1:.*]])
+ // CHECK: store {{.*}} %[[TEMPA1]], {{.*}} %[[TEMPE1_A]]
+ // CHECK: %[[TEMPE1_B:.*]] = getelementptr inbounds {{.*}} %[[TEMPE1]], i32 0, i32 1
+ // CHECK: call void @[[NS]]1BC1Ev({{.*}} %[[TEMPE1_B]])
+ // CHECK: %[[TEMPE1_C:.*]] = getelementptr inbounds {{.*}} %[[TEMPE1]], i32 0, i32 2
+ // CHECK: call void @[[NS]]1DC1Ev({{.*}} %[[TEMPD1:.*]])
+ // CHECK: %[[TEMPD1_C:.*]] = getelementptr inbounds {{.*}} %[[TEMPD1]], i32 0, i32 1
+ // CHECK: store {{.*}} %[[TEMPD1_C]], {{.*}} %[[TEMPE1_C]]
+ // CHECK: store {{.*}} %[[TEMPE1]], {{.*}} %[[E1:.*]]
+
+ g();
+ // CHECK: call void @[[NS]]1gEv()
+
+ E e2 = { A(), B(), D().c };
+ // CHECK: %[[TEMPE2_A:.*]] = getelementptr inbounds {{.*}} %[[E2:.*]], i32 0, i32 0
+ // CHECK: call void @[[NS]]1AC1Ev({{.*}} %[[TEMPA2:.*]])
+ // CHECK: store {{.*}} %[[TEMPA2]], {{.*}} %[[TEMPE2_A]]
+ // CHECK: %[[TEMPE2_B:.*]] = getelementptr inbounds {{.*}} %[[E2]], i32 0, i32 1
+ // CHECK: call void @[[NS]]1BC1Ev({{.*}} %[[TEMPE2_B]])
+ // CHECK: %[[TEMPE2_C:.*]] = getelementptr inbounds {{.*}} %[[E2]], i32 0, i32 2
+ // CHECK: call void @[[NS]]1DC1Ev({{.*}} %[[TEMPD2:.*]])
+ // CHECK: %[[TEMPD2_C:.*]] = getelementptr inbounds {{.*}} %[[TEMPD2]], i32 0, i32 1
+ // CHECK: store {{.*}} %[[TEMPD2_C]], {{.*}}* %[[TEMPE2_C]]
+
+ g();
+ // CHECK: call void @[[NS]]1gEv()
+
+ // CHECK: call void @[[NS]]1ED1Ev({{.*}} %[[E2]])
+ // CHECK: call void @[[NS]]1DD1Ev({{.*}} %[[TEMPD2]])
+ // CHECK: call void @[[NS]]1AD1Ev({{.*}} %[[TEMPA2]])
+ // CHECK: call void @[[NS]]1ED1Ev({{.*}} %[[TEMPE1]])
+ // CHECK: call void @[[NS]]1DD1Ev({{.*}} %[[TEMPD1]])
+ // CHECK: call void @[[NS]]1AD1Ev({{.*}} %[[TEMPA1]])
+ }
+}
+
+namespace PR14130 {
+ struct S { S(int); };
+ struct U { S &&s; };
+ U v { { 0 } };
+ // CHECK: call void @_ZN7PR141301SC1Ei({{.*}} @_ZGRN7PR141301vE, i32 0)
+ // CHECK: store {{.*}} @_ZGRN7PR141301vE, {{.*}} @_ZN7PR141301vE
+}
+
+namespace Ctor {
+ struct A { A(); ~A(); };
+ void f();
+ struct B {
+ A &&a;
+ B() : a{} { f(); }
+ } b;
+ // CHECK: define {{.*}}void @_ZN4Ctor1BC1Ev(
+ // CHECK: call void @_ZN4Ctor1AC1Ev(
+ // CHECK: call void @_ZN4Ctor1fEv(
+ // CHECK: call void @_ZN4Ctor1AD1Ev(
+}
diff --git a/test/CodeGenCXX/thiscall-struct-return.cpp b/test/CodeGenCXX/thiscall-struct-return.cpp
index ff53125..a6be5aa 100644
--- a/test/CodeGenCXX/thiscall-struct-return.cpp
+++ b/test/CodeGenCXX/thiscall-struct-return.cpp
@@ -1,7 +1,7 @@
// For MSVC ABI compatibility, all structures returned by value using the
// thiscall calling convention must use the hidden parameter.
//
-// RUN: %clang_cc1 -triple i386-PC-Win32 %s -fms-compatibility -O0 -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -triple i386-PC-Win32 %s -fms-compatibility -emit-llvm -o - | FileCheck %s
// This structure would normally be returned via EAX
struct S {
@@ -29,7 +29,7 @@ public:
}
};
-// CHECK: define void @_Z4testv()
+// CHECK-LABEL: define void @_Z4testv()
void test( void ) {
// CHECK: call void @_ZN1CC1Ev(%class.C* [[C:%.+]])
C c;
diff --git a/test/CodeGenCXX/threadsafe-statics-exceptions.cpp b/test/CodeGenCXX/threadsafe-statics-exceptions.cpp
index 769d120..70decc9 100644
--- a/test/CodeGenCXX/threadsafe-statics-exceptions.cpp
+++ b/test/CodeGenCXX/threadsafe-statics-exceptions.cpp
@@ -7,7 +7,7 @@ struct X {
struct Y { };
-// CHECK: define void @_Z1fv
+// CHECK-LABEL: define void @_Z1fv
void f() {
// CHECK: call i32 @__cxa_guard_acquire(i64* @_ZGVZ1fvE1x)
// CHECK: invoke void @_ZN1XC1Ev
diff --git a/test/CodeGenCXX/throw-expression-cleanup.cpp b/test/CodeGenCXX/throw-expression-cleanup.cpp
index e1ecd38..9944e16 100644
--- a/test/CodeGenCXX/throw-expression-cleanup.cpp
+++ b/test/CodeGenCXX/throw-expression-cleanup.cpp
@@ -14,7 +14,7 @@ void f() {
} catch (...) { }
}
-// CHECK: define void @_Z1fv
+// CHECK-LABEL: define void @_Z1fv
// CHECK: call void @_ZN5ErrorC1ERK1X
// CHECK: invoke void @__cxa_throw
// CHECK: landingpad
diff --git a/test/CodeGenCXX/throw-expressions.cpp b/test/CodeGenCXX/throw-expressions.cpp
index ba8a868..d9bf8fd 100644
--- a/test/CodeGenCXX/throw-expressions.cpp
+++ b/test/CodeGenCXX/throw-expressions.cpp
@@ -23,7 +23,31 @@ int test4() {
int test5(bool x, bool y, int z) {
return (x ? throw 1 : y) ? z : throw 2;
}
-// CHECK: define i32 @_Z5test5bbi(
+// CHECK-LABEL: define i32 @_Z5test5bbi(
+// CHECK: br i1
+//
+// x.true:
+// CHECK: call void @__cxa_throw(
+// CHECK-NEXT: unreachable
+//
+// x.false:
+// CHECK: br i1
+//
+// y.true:
+// CHECK: load i32*
+// CHECK: br label
+//
+// y.false:
+// CHECK: call void @__cxa_throw(
+// CHECK-NEXT: unreachable
+//
+// end:
+// CHECK: ret i32
+
+int test6(bool x, bool y, int z) {
+ return (x ? throw 1 : y) ? z : (throw 2);
+}
+// CHECK-LABEL: define i32 @_Z5test6bbi(
// CHECK: br i1
//
// x.true:
diff --git a/test/CodeGenCXX/thunks-available-externally.cpp b/test/CodeGenCXX/thunks-available-externally.cpp
index dfdb786..01e4947 100644
--- a/test/CodeGenCXX/thunks-available-externally.cpp
+++ b/test/CodeGenCXX/thunks-available-externally.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -emit-llvm -O3 -o - | FileCheck %s
+// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -emit-llvm-only -O3
// Check that we don't assert on this case.
namespace Test1 {
@@ -58,15 +58,6 @@ static void f(B* b) {
b->f();
}
-// CHECK: define void @_ZN5Test21fEv()
-// CHECK: call void @_ZN5Test21C1fEv
-// CHECK: ret void
-// CHECK: define available_externally void @_ZThn16_N5Test21C1fEv
-void f() {
- C c;
- f(&c);
-}
-
}
// Test that we don't assert.
diff --git a/test/CodeGenCXX/thunks.cpp b/test/CodeGenCXX/thunks.cpp
index 6e58830..defb706 100644
--- a/test/CodeGenCXX/thunks.cpp
+++ b/test/CodeGenCXX/thunks.cpp
@@ -1,5 +1,6 @@
// RUN: %clang_cc1 %s -triple=x86_64-pc-linux-gnu -munwind-tables -emit-llvm -o - | FileCheck %s
-// RUN: %clang_cc1 %s -triple=x86_64-pc-linux-gnu -munwind-tables -fhidden-weak-vtables -emit-llvm -o - | FileCheck -check-prefix=HIDDEN %s
+// RUN: %clang_cc1 %s -triple=x86_64-pc-linux-gnu -munwind-tables -emit-llvm -o - -O1 -disable-llvm-optzns | FileCheck %s
+// RUN: %clang_cc1 %s -triple=x86_64-pc-linux-gnu -munwind-tables -fhidden-weak-vtables -emit-llvm -o - | FileCheck -check-prefix=CHECK-HIDDEN %s
namespace Test1 {
@@ -19,7 +20,7 @@ struct C : A, B {
virtual void f();
};
-// CHECK: define void @_ZThn8_N5Test11C1fEv(
+// CHECK-LABEL: define void @_ZThn8_N5Test11C1fEv(
void C::f() { }
}
@@ -37,7 +38,7 @@ struct B : virtual A {
virtual void f();
};
-// CHECK: define void @_ZTv0_n24_N5Test21B1fEv(
+// CHECK-LABEL: define void @_ZTv0_n24_N5Test21B1fEv(
void B::f() { }
}
@@ -82,7 +83,7 @@ struct __attribute__((visibility("protected"))) C : A, B {
virtual void f();
};
-// CHECK: define protected void @_ZThn8_N5Test41C1fEv(
+// CHECK-LABEL: define protected void @_ZThn8_N5Test41C1fEv(
void C::f() { }
}
@@ -165,7 +166,7 @@ namespace Test6 {
virtual X f();
};
- // CHECK: define void @_ZThn16_N5Test66Thunks1fEv
+ // CHECK-LABEL: define void @_ZThn16_N5Test66Thunks1fEv
// CHECK-NOT: memcpy
// CHECK: {{call void @_ZN5Test66Thunks1fEv.*sret}}
// CHECK: ret void
@@ -211,7 +212,7 @@ namespace Test7 {
void D::baz(X, X&, _Complex float, Small, Small&, Large) { }
- // CHECK: define void @_ZThn8_N5Test71D3bazENS_1XERS1_CfNS_5SmallERS4_NS_5LargeE(
+ // CHECK-LABEL: define void @_ZThn8_N5Test71D3bazENS_1XERS1_CfNS_5SmallERS4_NS_5LargeE(
// CHECK-NOT: memcpy
// CHECK: ret void
void testD() { D d; }
@@ -226,7 +227,7 @@ namespace Test8 {
// CHECK: define void @_ZN5Test81C6helperENS_6NonPODE([[NONPODTYPE:%.*]]*
void C::helper(NonPOD var) {}
- // CHECK: define void @_ZThn8_N5Test81C3barENS_6NonPODE(
+ // CHECK-LABEL: define void @_ZThn8_N5Test81C3barENS_6NonPODE(
// CHECK-NOT: load [[NONPODTYPE]]*
// CHECK-NOT: memcpy
// CHECK: ret void
@@ -250,8 +251,8 @@ namespace Test10 {
struct B { virtual void foo(); };
struct C : A, B { void foo() {} };
- // CHECK-HIDDEN: define linkonce_odr void @_ZN6Test101C3fooEv
- // CHECK-HIDDEN: define linkonce_odr hidden void @_ZThn8_N6Test101C3fooEv
+ // CHECK-HIDDEN-LABEL: define linkonce_odr void @_ZN6Test101C3fooEv
+ // CHECK-HIDDEN-LABEL: define linkonce_odr hidden void @_ZThn8_N6Test101C3fooEv
void test() {
C c;
@@ -342,10 +343,31 @@ namespace Test14 {
// CHECK: define void @_ZThn8_N6Test141C1fEv({{.*}}) unnamed_addr [[NUW:#[0-9]+]]
}
+// Varargs non-covariant thunk test.
+// PR18098
+namespace Test15 {
+ struct A {
+ virtual ~A();
+ };
+ struct B {
+ virtual void f(int x, ...);
+ };
+ struct C : A, B {
+ virtual void c();
+ virtual void f(int x, ...);
+ };
+ void C::c() {}
+
+ // C::c
+ // CHECK: declare void @_ZN6Test151C1fEiz
+ // non-virtual thunk to C::f
+ // CHECK: declare void @_ZThn8_N6Test151C1fEiz
+}
+
/**** The following has to go at the end of the file ****/
// This is from Test5:
-// CHECK: define linkonce_odr void @_ZTv0_n24_N5Test51B1fEv
-// CHECK: define internal void @_ZThn8_N6Test4B12_GLOBAL__N_11C1fEv(
+// CHECK-LABEL: define linkonce_odr void @_ZTv0_n24_N5Test51B1fEv
+// CHECK-LABEL: define internal void @_ZThn8_N6Test4B12_GLOBAL__N_11C1fEv(
// CHECK: attributes [[NUW]] = { nounwind uwtable{{.*}} }
diff --git a/test/CodeGenCXX/type_visibility.cpp b/test/CodeGenCXX/type_visibility.cpp
index 5c45611..11e5091 100644
--- a/test/CodeGenCXX/type_visibility.cpp
+++ b/test/CodeGenCXX/type_visibility.cpp
@@ -26,11 +26,11 @@ namespace temp0 {
};
template struct B<A>;
- // FUNS: define weak_odr void @_ZN5temp01BINS_1AEE3fooEv(
+ // FUNS-LABEL: 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(
+ // FUNS-HIDDEN-LABEL: 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
@@ -43,11 +43,11 @@ namespace temp1 {
};
template struct B<A>;
- // FUNS: define weak_odr void @_ZN5temp11BINS_1AEE3fooEv(
+ // FUNS-LABEL: 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(
+ // FUNS-HIDDEN-LABEL: 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
@@ -60,11 +60,11 @@ namespace temp2 {
};
template struct B<A>;
- // FUNS: define weak_odr void @_ZN5temp21BINS_1AEE3fooEv(
+ // FUNS-LABEL: 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(
+ // FUNS-HIDDEN-LABEL: 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
@@ -77,11 +77,11 @@ namespace temp3 {
};
template struct B<A>;
- // FUNS: define weak_odr hidden void @_ZN5temp31BINS_1AEE3fooEv(
+ // FUNS-LABEL: 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(
+ // FUNS-HIDDEN-LABEL: 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
@@ -94,11 +94,11 @@ namespace temp4 {
};
template struct B<A>;
- // FUNS: define weak_odr void @_ZN5temp41BINS_1AEE3fooEv(
+ // FUNS-LABEL: 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(
+ // FUNS-HIDDEN-LABEL: 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
@@ -110,11 +110,11 @@ namespace type0 {
};
void A::foo() {}
- // FUNS: define void @_ZN5type01A3fooEv(
+ // FUNS-LABEL: define void @_ZN5type01A3fooEv(
// VARS: @_ZTVN5type01AE = unnamed_addr constant
// VARS: @_ZTSN5type01AE = constant
// VARS: @_ZTIN5type01AE = unnamed_addr constant
- // FUNS-HIDDEN: define hidden void @_ZN5type01A3fooEv(
+ // FUNS-HIDDEN-LABEL: define hidden void @_ZN5type01A3fooEv(
// VARS-HIDDEN: @_ZTVN5type01AE = unnamed_addr constant
// VARS-HIDDEN: @_ZTSN5type01AE = constant
// VARS-HIDDEN: @_ZTIN5type01AE = unnamed_addr constant
@@ -126,11 +126,11 @@ namespace type1 {
};
void A::foo() {}
- // FUNS: define hidden void @_ZN5type11A3fooEv(
+ // FUNS-LABEL: define hidden void @_ZN5type11A3fooEv(
// VARS: @_ZTVN5type11AE = unnamed_addr constant
// VARS: @_ZTSN5type11AE = constant
// VARS: @_ZTIN5type11AE = unnamed_addr constant
- // FUNS-HIDDEN: define hidden void @_ZN5type11A3fooEv(
+ // FUNS-HIDDEN-LABEL: define hidden void @_ZN5type11A3fooEv(
// VARS-HIDDEN: @_ZTVN5type11AE = unnamed_addr constant
// VARS-HIDDEN: @_ZTSN5type11AE = constant
// VARS-HIDDEN: @_ZTIN5type11AE = unnamed_addr constant
@@ -142,11 +142,11 @@ namespace type2 {
};
void A::foo() {}
- // FUNS: define void @_ZN5type21A3fooEv(
+ // FUNS-LABEL: 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(
+ // FUNS-HIDDEN-LABEL: define hidden void @_ZN5type21A3fooEv(
// VARS-HIDDEN: @_ZTVN5type21AE = hidden unnamed_addr constant
// VARS-HIDDEN: @_ZTSN5type21AE = hidden constant
// VARS-HIDDEN: @_ZTIN5type21AE = hidden unnamed_addr constant
@@ -158,11 +158,11 @@ namespace type3 {
};
void A::foo() {}
- // FUNS: define void @_ZN5type31A3fooEv(
+ // FUNS-LABEL: define void @_ZN5type31A3fooEv(
// VARS: @_ZTVN5type31AE = hidden unnamed_addr constant
// VARS: @_ZTSN5type31AE = hidden constant
// VARS: @_ZTIN5type31AE = hidden unnamed_addr constant
- // FUNS-HIDDEN: define void @_ZN5type31A3fooEv(
+ // FUNS-HIDDEN-LABEL: 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 a1bc967..9d21290 100644
--- a/test/CodeGenCXX/typeid.cpp
+++ b/test/CodeGenCXX/typeid.cpp
@@ -27,7 +27,10 @@ extern A &a;
// CHECK: @_ZN5Test14a_tiE = global
const std::type_info &a_ti = typeid(a);
-// CHECK: define i8* @_ZN5Test11fEv
+// CHECK: @_ZN5Test18A10_c_tiE = constant %"class.std::type_info"* bitcast ({ i8*, i8* }* @_ZTIA10_c to %"class.std::type_info"*), align 8
+const std::type_info &A10_c_ti = typeid(char const[10]);
+
+// CHECK-LABEL: define i8* @_ZN5Test11fEv
const char *f() {
try {
// CHECK: br i1
diff --git a/test/CodeGenCXX/unknown-anytype.cpp b/test/CodeGenCXX/unknown-anytype.cpp
index 902cc8d..aacb849 100644
--- a/test/CodeGenCXX/unknown-anytype.cpp
+++ b/test/CodeGenCXX/unknown-anytype.cpp
@@ -1,33 +1,45 @@
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -funknown-anytype -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -funknown-anytype -emit-llvm -o %t %s
+// RUN: FileCheck -check-prefix COMMON %s < %t
+// RUN: FileCheck -check-prefix X86_64 %s < %t
+// RUN: %clang_cc1 -triple i386-apple-darwin10 -funknown-anytype -emit-llvm -o %t %s
+// RUN: FileCheck -check-prefix COMMON %s < %t
+// RUN: FileCheck -check-prefix I386 %s < %t
+
+// x86-64 is the special case here because of its variadic convention.
+// We want to ensure that it always uses a variadic convention even if
+// other platforms do not.
+// rdar://13731520
int test0() {
extern __unknown_anytype test0_any;
- // CHECK: load i32* @test0_any
+ // COMMON: load i32* @test0_any
return (int) test0_any;
}
int test1() {
extern __unknown_anytype test1_any();
- // CHECK: call i32 @_Z9test1_anyv()
+ // COMMON: call i32 @_Z9test1_anyv()
return (int) test1_any();
}
extern "C" __unknown_anytype test2_any(...);
float test2() {
- // CHECK: call float (...)* @test2_any(double {{[^,]+}})
+ // X86_64: call float (double, ...)* @test2_any(double {{[^,]+}})
+ // I386: call float (double, ...)* @test2_any(double {{[^,]+}})
return (float) test2_any(0.5f);
}
extern "C" __unknown_anytype test2a_any(...);
float test2a() {
- // CHECK: call float (...)* @test2a_any(float {{[^,]+}})
+ // X86_64: call float (float, ...)* @test2a_any(float {{[^,]+}})
+ // I386: call float (float, ...)* @test2a_any(float {{[^,]+}})
return (float) test2a_any((float) 0.5f);
}
float test3() {
extern __unknown_anytype test3_any;
- // CHECK: [[FN:%.*]] = load float (i32)** @test3_any,
- // CHECK: call float [[FN]](i32 5)
+ // COMMON: [[FN:%.*]] = load float (i32)** @test3_any,
+ // COMMON: call float [[FN]](i32 5)
return ((float(*)(int)) test3_any)(5);
}
@@ -36,22 +48,22 @@ namespace test4 {
extern __unknown_anytype test4_any2;
int test() {
- // CHECK: load i32* @_ZN5test410test4_any1E
- // CHECK: load i8* @_ZN5test410test4_any2E
+ // COMMON: load i32* @_ZN5test410test4_any1E
+ // COMMON: load i8* @_ZN5test410test4_any2E
return (int) test4_any1 + (char) test4_any2;
}
}
extern "C" __unknown_anytype test5_any();
void test5() {
- // CHECK: call void @test5_any()
+ // COMMON: call void @test5_any()
return (void) test5_any();
}
extern "C" __unknown_anytype test6_any(float *);
long test6() {
- // CHECK: call i64 @test6_any(float* null)
- return (long) test6_any(0);
+ // COMMON: call i64 @test6_any(float* null)
+ return (long long) test6_any(0);
}
struct Test7 {
@@ -59,7 +71,7 @@ struct Test7 {
};
extern "C" __unknown_anytype test7_any(int);
Test7 test7() {
- // CHECK: call void @test7_any({{%.*}}* sret {{%.*}}, i32 5)
+ // COMMON: call void @test7_any({{%.*}}* sret {{%.*}}, i32 5)
return (Test7) test7_any(5);
}
@@ -71,29 +83,35 @@ struct Test8 {
};
void Test8::test() {
float f;
- // CHECK: call i32 @_ZN5Test83fooEv(
+ // COMMON: call i32 @_ZN5Test83fooEv(
f = (int) foo();
- // CHECK: call i32 @_ZN5Test83fooEi(
+ // COMMON: call i32 @_ZN5Test83fooEi(
f = (int) foo(5);
- // CHECK: call i32 @_ZN5Test83fooEv(
+ // COMMON: call i32 @_ZN5Test83fooEv(
f = (float) this->foo();
- // CHECK: call i32 @_ZN5Test83fooEi(
+ // COMMON: call i32 @_ZN5Test83fooEi(
f = (float) this->foo(5);
}
void test8(Test8 *p) {
double d;
- // CHECK: call i32 @_ZN5Test83fooEv(
+ // COMMON: call i32 @_ZN5Test83fooEv(
d = (double) p->foo();
- // CHECK: call i32 @_ZN5Test83fooEi(
+ // COMMON: call i32 @_ZN5Test83fooEi(
d = (double) p->foo(5);
- // CHECK: call i32 @_ZN5Test83fooEv(
+ // COMMON: call i32 @_ZN5Test83fooEv(
d = (bool) (*p).foo();
- // CHECK: call i32 @_ZN5Test83fooEi(
+ // COMMON: call i32 @_ZN5Test83fooEi(
d = (bool) (*p).foo(5);
}
extern "C" __unknown_anytype test9_foo;
void *test9() {
- // CHECK: ret i8* bitcast (i32* @test9_foo to i8*)
+ // COMMON: ret i8* bitcast (i32* @test9_foo to i8*)
return (int*) &test9_foo;
}
+
+// Don't explode on this.
+extern "C" __unknown_anytype test10_any(...);
+void test10() {
+ (void) test10_any(), (void) test10_any();
+}
diff --git a/test/CodeGenCXX/value-init.cpp b/test/CodeGenCXX/value-init.cpp
index 60dca99..fad459b 100644
--- a/test/CodeGenCXX/value-init.cpp
+++ b/test/CodeGenCXX/value-init.cpp
@@ -74,7 +74,7 @@ namespace ptrmem {
int S::*mem2;
};
- // CHECK: define i32 @_ZN6ptrmem4testEPNS_1SE
+ // CHECK-LABEL: define i32 @_ZN6ptrmem4testEPNS_1SE
int test(S *s) {
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64
// CHECK: getelementptr
@@ -99,7 +99,7 @@ struct Test2 {
struct Test3 : public Test { };
-// CHECK: define void @_ZN6PR98011fEv
+// CHECK-LABEL: define void @_ZN6PR98011fEv
void f() {
// CHECK-NOT: call void @llvm.memset.p0i8.i64
// CHECK: call void @_ZN6PR98014TestC1Ei
@@ -131,7 +131,7 @@ void f() {
namespace zeroinit {
struct S { int i; };
- // CHECK: define i32 @_ZN8zeroinit4testEv()
+ // CHECK-LABEL: define i32 @_ZN8zeroinit4testEv()
int test() {
// CHECK: call void @llvm.memset.p0i8.i64
// CHECK: ret i32 0
@@ -148,7 +148,7 @@ namespace zeroinit {
void f();
};
- // CHECK: define void @_ZN8zeroinit9testX0_X1Ev
+ // CHECK-LABEL: define void @_ZN8zeroinit9testX0_X1Ev
void testX0_X1() {
// CHECK: call void @llvm.memset.p0i8.i64
// CHECK-NEXT: call void @_ZN8zeroinit2X1C1Ev
@@ -169,7 +169,7 @@ namespace zeroinit {
};
- // CHECK: define void @_ZN8zeroinit9testX0_X3Ev
+ // CHECK-LABEL: define void @_ZN8zeroinit9testX0_X3Ev
void testX0_X3() {
// CHECK-NOT: call void @llvm.memset
// CHECK: call void @_ZN8zeroinit2X3IiEC1Ev
@@ -201,7 +201,7 @@ namespace test6 {
void test() {
A arr[10][20] = { 5 };
};
- // CHECK: define void @_ZN5test64testEv()
+ // CHECK-LABEL: define void @_ZN5test64testEv()
// CHECK: [[ARR:%.*]] = alloca [10 x [20 x [[A:%.*]]]],
// CHECK-NEXT: [[INNER:%.*]] = getelementptr inbounds [10 x [20 x [[A]]]]* [[ARR]], i64 0, i64 0
@@ -243,7 +243,7 @@ namespace PR11124 {
struct B : virtual A { int b; };
struct C : B { C(); };
C::C() : A(3), B() {}
- // CHECK: define void @_ZN7PR111241CC1Ev
+ // CHECK-LABEL: define void @_ZN7PR111241CC1Ev
// CHECK: call void @llvm.memset.p0i8.i64(i8* {{.*}}, i8 0, i64 12, i32 8, i1 false)
// CHECK-NEXT: call void @_ZN7PR111241BC2Ev
// Make sure C::C doesn't overwrite parts of A while it is zero-initializing B
@@ -251,18 +251,18 @@ namespace PR11124 {
struct B2 : virtual A { int B::*b; };
struct C2 : B2 { C2(); };
C2::C2() : A(3), B2() {}
- // CHECK: define void @_ZN7PR111242C2C1Ev
+ // CHECK-LABEL: define void @_ZN7PR111242C2C1Ev
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %{{.*}}, i8* {{.*}}, i64 16, i32 8, i1 false)
// CHECK-NEXT: call void @_ZN7PR111242B2C2Ev
}
// Ensure we produce an i1 here, and don't assert.
-// CHECK: define void @_Z9r170806_bv(
+// CHECK-LABEL: 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-LABEL: define linkonce_odr void @_ZN8zeroinit2X3IiEC2Ev(%"struct.zeroinit::X3"* %this) unnamed_addr
// CHECK: call void @llvm.memset.p0i8.i64
// CHECK-NEXT: call void @_ZN8zeroinit2X2IiEC2Ev
// CHECK-NEXT: ret void
diff --git a/test/CodeGenCXX/vararg-conversion-ctor.cpp b/test/CodeGenCXX/vararg-conversion-ctor.cpp
index a49b1db..e496f6d 100644
--- a/test/CodeGenCXX/vararg-conversion-ctor.cpp
+++ b/test/CodeGenCXX/vararg-conversion-ctor.cpp
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -emit-llvm %s -o %t-64.ll
-// RUN: FileCheck -check-prefix LPLL64 --input-file=%t-64.ll %s
+// RUN: FileCheck -check-prefix CHECK-LPLL64 --input-file=%t-64.ll %s
extern "C" int printf(...);
diff --git a/test/CodeGenCXX/vararg-non-pod.cpp b/test/CodeGenCXX/vararg-non-pod.cpp
index 6c6f459..9497179 100644
--- a/test/CodeGenCXX/vararg-non-pod.cpp
+++ b/test/CodeGenCXX/vararg-non-pod.cpp
@@ -8,7 +8,7 @@ struct X {
void vararg(...);
-// CHECK: define void @_Z4test1X
+// CHECK-LABEL: define void @_Z4test1X
void test(X x) {
// CHECK: call void @llvm.trap()
vararg(x);
diff --git a/test/CodeGenCXX/varargs.cpp b/test/CodeGenCXX/varargs.cpp
index af34336..31bbee98 100644
--- a/test/CodeGenCXX/varargs.cpp
+++ b/test/CodeGenCXX/varargs.cpp
@@ -7,7 +7,7 @@ namespace test0 {
// though there is no way to do a va_begin. Otherwise, the optimizer
// will warn about 'dropped arguments' at the call site.
- // CHECK: define i32 @_ZN5test05test1Ez(...)
+ // CHECK-LABEL: define i32 @_ZN5test05test1Ez(...)
int test1(...) {
return -1;
}
@@ -30,7 +30,7 @@ namespace test1 {
A x;
foo(x);
}
- // CHECK: define void @_ZN5test14testEv()
+ // CHECK-LABEL: define void @_ZN5test14testEv()
// CHECK: [[X:%.*]] = alloca [[A:%.*]], align 4
// CHECK-NEXT: [[TMP:%.*]] = alloca [[A]], align 4
// CHECK-NEXT: [[T0:%.*]] = bitcast [[A]]* [[TMP]] to i8*
diff --git a/test/CodeGenCXX/variadic-templates.cpp b/test/CodeGenCXX/variadic-templates.cpp
index c56bec3..4974b65 100644
--- a/test/CodeGenCXX/variadic-templates.cpp
+++ b/test/CodeGenCXX/variadic-templates.cpp
@@ -5,7 +5,7 @@ int get_num_types(Types...) {
return sizeof...(Types);
}
-// CHECK: define weak_odr i32 @_Z13get_num_typesIJifdEEiDpT_
+// CHECK-LABEL: define weak_odr i32 @_Z13get_num_typesIJifdEEiDpT_
// CHECK: ret i32 3
template int get_num_types(int, float, double);
@@ -13,7 +13,7 @@ template int get_num_types(int, float, double);
namespace test1 {
template <class... T> void foo() {
int values[sizeof...(T)+1] = { T::value... };
- // CHECK: define linkonce_odr void @_ZN5test13fooIJEEEvv()
+ // CHECK-LABEL: define linkonce_odr void @_ZN5test13fooIJEEEvv()
// CHECK: alloca [1 x i32], align 4
}
diff --git a/test/CodeGenCXX/virt-dtor-gen.cpp b/test/CodeGenCXX/virt-dtor-gen.cpp
index 1a6c583..78a0b81 100644
--- a/test/CodeGenCXX/virt-dtor-gen.cpp
+++ b/test/CodeGenCXX/virt-dtor-gen.cpp
@@ -7,4 +7,4 @@ class Foo {
};
Foo::~Foo() {}
-// CHECK: define void @_ZN3FooD0Ev(%class.Foo* %this) unnamed_addr
+// CHECK-LABEL: define void @_ZN3FooD0Ev(%class.Foo* %this) unnamed_addr
diff --git a/test/CodeGenCXX/virtual-base-cast.cpp b/test/CodeGenCXX/virtual-base-cast.cpp
index f469636..40e68f6 100644
--- a/test/CodeGenCXX/virtual-base-cast.cpp
+++ b/test/CodeGenCXX/virtual-base-cast.cpp
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -emit-llvm %s -o - -triple i686-pc-linux-gnu | FileCheck %s
+// RUN: %clang_cc1 -cxx-abi microsoft -emit-llvm %s -o - -triple i686-pc-win32 | FileCheck -check-prefix MSVC %s
struct A { int a; virtual int aa(); };
struct B { int b; virtual int bb(); };
@@ -17,6 +18,16 @@ A* a() { return x; }
// CHECK: load i32* [[CASTVBASEOFFSETPTRA]]
// CHECK: }
+// MSVC: @"\01?a@@YAPAUA@@XZ"() [[NUW:#[0-9]+]] {
+// MSVC: %[[vbptr_off:.*]] = getelementptr inbounds i8* {{.*}}, i32 0
+// MSVC: %[[vbptr:.*]] = bitcast i8* %[[vbptr_off]] to i8**
+// MSVC: %[[vbtable:.*]] = load i8** %[[vbptr]]
+// MSVC: %[[entry:.*]] = getelementptr inbounds i8* {{.*}}, i32 4
+// MSVC: %[[entry_i32:.*]] = bitcast i8* %[[entry]] to i32*
+// MSVC: %[[offset:.*]] = load i32* %[[entry_i32]]
+// MSVC: add nsw i32 0, %[[offset]]
+// MSVC: }
+
B* b() { return x; }
// CHECK: @_Z1bv() [[NUW]]
// CHECK: [[VBASEOFFSETPTRA:%[a-zA-Z0-9\.]+]] = getelementptr i8* {{.*}}, i64 -20
@@ -24,6 +35,18 @@ B* b() { return x; }
// CHECK: load i32* [[CASTVBASEOFFSETPTRA]]
// CHECK: }
+// Same as 'a' except we use a different vbtable offset.
+// MSVC: @"\01?b@@YAPAUB@@XZ"() [[NUW:#[0-9]+]] {
+// MSVC: %[[vbptr_off:.*]] = getelementptr inbounds i8* {{.*}}, i32 0
+// MSVC: %[[vbptr:.*]] = bitcast i8* %[[vbptr_off]] to i8**
+// MSVC: %[[vbtable:.*]] = load i8** %[[vbptr]]
+// MSVC: %[[entry:.*]] = getelementptr inbounds i8* {{.*}}, i32 8
+// MSVC: %[[entry_i32:.*]] = bitcast i8* %[[entry]] to i32*
+// MSVC: %[[offset:.*]] = load i32* %[[entry_i32]]
+// MSVC: add nsw i32 0, %[[offset]]
+// MSVC: }
+
+
BB* c() { return x; }
// CHECK: @_Z1cv() [[NUW]]
// CHECK: [[VBASEOFFSETPTRC:%[a-zA-Z0-9\.]+]] = getelementptr i8* {{.*}}, i64 -24
@@ -32,4 +55,35 @@ BB* c() { return x; }
// CHECK: add i32 [[VBASEOFFSETC]], 8
// CHECK: }
+// Same as 'a' except we use a different vbtable offset.
+// MSVC: @"\01?c@@YAPAUBB@@XZ"() [[NUW:#[0-9]+]] {
+// MSVC: %[[vbptr_off:.*]] = getelementptr inbounds i8* {{.*}}, i32 0
+// MSVC: %[[vbptr:.*]] = bitcast i8* %[[vbptr_off]] to i8**
+// MSVC: %[[vbtable:.*]] = load i8** %[[vbptr]]
+// MSVC: %[[entry:.*]] = getelementptr inbounds i8* {{.*}}, i32 16
+// MSVC: %[[entry_i32:.*]] = bitcast i8* %[[entry]] to i32*
+// MSVC: %[[offset:.*]] = load i32* %[[entry_i32]]
+// MSVC: add nsw i32 0, %[[offset]]
+// MSVC: }
+
+// Put the vbptr at a non-zero offset inside a non-virtual base.
+struct E { int e; };
+struct F : E, D { int f; };
+
+F* y;
+
+BB* d() { return y; }
+
+// Same as 'c' except the vbptr offset is 4, changing the initial GEP and the
+// final add.
+// MSVC: @"\01?d@@YAPAUBB@@XZ"() [[NUW:#[0-9]+]] {
+// MSVC: %[[vbptr_off:.*]] = getelementptr inbounds i8* {{.*}}, i32 4
+// MSVC: %[[vbptr:.*]] = bitcast i8* %[[vbptr_off]] to i8**
+// MSVC: %[[vbtable:.*]] = load i8** %[[vbptr]]
+// MSVC: %[[entry:.*]] = getelementptr inbounds i8* {{.*}}, i32 16
+// MSVC: %[[entry_i32:.*]] = bitcast i8* %[[entry]] to i32*
+// MSVC: %[[offset:.*]] = load i32* %[[entry_i32]]
+// MSVC: add nsw i32 4, %[[offset]]
+// MSVC: }
+
// CHECK: attributes [[NUW]] = { nounwind{{.*}} }
diff --git a/test/CodeGenCXX/virtual-base-destructor-call.cpp b/test/CodeGenCXX/virtual-base-destructor-call.cpp
index 2424d21..5014eaf 100644
--- a/test/CodeGenCXX/virtual-base-destructor-call.cpp
+++ b/test/CodeGenCXX/virtual-base-destructor-call.cpp
@@ -18,34 +18,34 @@ int main() {
// basic_iostream's complete dtor calls its base dtor, then its
// virtual base's dtor.
-// CHECK: define linkonce_odr {{.*}} @_ZN14basic_iostreamIcED1Ev(%struct.basic_iostream* %this) unnamed_addr
+// CHECK: define linkonce_odr {{.*}} @_ZN14basic_iostreamIcED1Ev(%struct.basic_iostream* {{.*}}%this) unnamed_addr
// CHECK: call {{.*}} @_ZN14basic_iostreamIcED2Ev
// CHECK: call {{.*}} @_ZN9basic_iosD2Ev
// basic_iostream's base dtor calls its non-virtual base dtor.
-// CHECK: define linkonce_odr {{.*}} @_ZN14basic_iostreamIcED2Ev(%struct.basic_iostream* %this, i8** %vtt) unnamed_addr
+// CHECK: define linkonce_odr {{.*}} @_ZN14basic_iostreamIcED2Ev(%struct.basic_iostream* {{.*}}%this, i8** %vtt) unnamed_addr
// CHECK: call {{.*}} @_ZN13basic_istreamIcED2Ev
// CHECK: }
-// basic_iostream's deleting dtor calls its complete dtor, then
-// operator delete().
-// CHECK: define linkonce_odr {{.*}} @_ZN14basic_iostreamIcED0Ev(%struct.basic_iostream* %this) unnamed_addr
-// CHECK: call {{.*}} @_ZN14basic_iostreamIcED1Ev
-// CHECK: call {{.*}} @_ZdlPv
-
// basic_istream's complete dtor calls the base dtor,
// then its virtual base's base dtor.
-// CHECK: define linkonce_odr {{.*}} @_ZN13basic_istreamIcED1Ev(%struct.basic_istream* %this) unnamed_addr
+// CHECK: define linkonce_odr {{.*}} @_ZN13basic_istreamIcED1Ev(%struct.basic_istream* {{.*}}%this) unnamed_addr
// CHECK: call {{.*}} @_ZN13basic_istreamIcED2Ev
// CHECK: call {{.*}} @_ZN9basic_iosD2Ev
// basic_istream's deleting dtor calls the complete dtor, then
// operator delete().
-// CHECK: define linkonce_odr {{.*}} @_ZN13basic_istreamIcED0Ev(%struct.basic_istream* %this) unnamed_addr
+// CHECK: define linkonce_odr {{.*}} @_ZN13basic_istreamIcED0Ev(%struct.basic_istream* {{.*}}%this) unnamed_addr
// CHECK: call {{.*}} @_ZN13basic_istreamIcED1Ev
// CHECK: call {{.*}} @_ZdlPv
+// basic_iostream's deleting dtor calls its complete dtor, then
+// operator delete().
+// CHECK: define linkonce_odr {{.*}} @_ZN14basic_iostreamIcED0Ev(%struct.basic_iostream* {{.*}}%this) unnamed_addr
+// CHECK: call {{.*}} @_ZN14basic_iostreamIcED1Ev
+// CHECK: call {{.*}} @_ZdlPv
+
// basic_istream's base dtor is a no-op.
-// CHECK: define linkonce_odr {{.*}} @_ZN13basic_istreamIcED2Ev(%struct.basic_istream* %this, i8** %vtt) unnamed_addr
+// CHECK: define linkonce_odr {{.*}} @_ZN13basic_istreamIcED2Ev(%struct.basic_istream* {{.*}}%this, i8** %vtt) unnamed_addr
// CHECK-NOT: call
// CHECK: }
diff --git a/test/CodeGenCXX/virtual-bases.cpp b/test/CodeGenCXX/virtual-bases.cpp
index c9f13f8..2878e95 100644
--- a/test/CodeGenCXX/virtual-bases.cpp
+++ b/test/CodeGenCXX/virtual-bases.cpp
@@ -5,23 +5,23 @@ struct A {
};
// CHECK: @_ZN1AC1Ev = alias {{.*}} @_ZN1AC2Ev
-// CHECK: define void @_ZN1AC2Ev(%struct.A* %this) unnamed_addr
+// CHECK-LABEL: define void @_ZN1AC2Ev(%struct.A* %this) unnamed_addr
A::A() { }
struct B : virtual A {
B();
};
-// CHECK: define void @_ZN1BC1Ev(%struct.B* %this) unnamed_addr
-// CHECK: define void @_ZN1BC2Ev(%struct.B* %this, i8** %vtt) unnamed_addr
+// CHECK-LABEL: define void @_ZN1BC1Ev(%struct.B* %this) unnamed_addr
+// CHECK-LABEL: define void @_ZN1BC2Ev(%struct.B* %this, i8** %vtt) unnamed_addr
B::B() { }
struct C : virtual A {
C(bool);
};
-// CHECK: define void @_ZN1CC1Eb(%struct.C* %this, i1 zeroext) unnamed_addr
-// CHECK: define void @_ZN1CC2Eb(%struct.C* %this, i8** %vtt, i1 zeroext) unnamed_addr
+// CHECK-LABEL: define void @_ZN1CC1Eb(%struct.C* %this, i1 zeroext) unnamed_addr
+// CHECK-LABEL: define void @_ZN1CC2Eb(%struct.C* %this, i8** %vtt, i1 zeroext) unnamed_addr
C::C(bool) { }
// PR6251
@@ -39,7 +39,7 @@ struct D : B, C {
D();
};
-// CHECK: define void @_ZN6PR62511DC1Ev(%"struct.PR6251::D"* %this) unnamed_addr
+// CHECK-LABEL: define void @_ZN6PR62511DC1Ev(%"struct.PR6251::D"* %this) unnamed_addr
// CHECK: call void @_ZN6PR62511AIcEC2Ev
// CHECK-NOT: call void @_ZN6PR62511AIcEC2Ev
// CHECK: ret void
diff --git a/test/CodeGenCXX/virtual-destructor-calls.cpp b/test/CodeGenCXX/virtual-destructor-calls.cpp
index 7ef50b2..ae3704f 100644
--- a/test/CodeGenCXX/virtual-destructor-calls.cpp
+++ b/test/CodeGenCXX/virtual-destructor-calls.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin10 -mconstructor-aliases | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin10 -mconstructor-aliases -O1 -disable-llvm-optzns | FileCheck %s
struct Member {
~Member();
@@ -21,12 +21,12 @@ struct B : A {
// CHECK: @_ZN1CD2Ev = alias bitcast {{.*}} @_ZN1BD2Ev
// Deleting dtor: defers to the complete dtor.
-// CHECK: define void @_ZN1BD0Ev(%struct.B* %this) unnamed_addr
+// CHECK-LABEL: define void @_ZN1BD0Ev(%struct.B* %this) unnamed_addr
// CHECK: call void @_ZN1BD1Ev
// CHECK: call void @_ZdlPv
// Base dtor: actually calls A's base dtor.
-// CHECK: define void @_ZN1BD2Ev(%struct.B* %this) unnamed_addr
+// CHECK-LABEL: define void @_ZN1BD2Ev(%struct.B* %this) unnamed_addr
// CHECK: call void @_ZN6MemberD1Ev
// CHECK: call void @_ZN1AD2Ev
@@ -41,7 +41,7 @@ C::~C() { }
// Complete dtor: just an alias (checked above).
// Deleting dtor: defers to the complete dtor.
-// CHECK: define void @_ZN1CD0Ev(%struct.C* %this) unnamed_addr
+// CHECK-LABEL: define void @_ZN1CD0Ev(%struct.C* %this) unnamed_addr
// CHECK: call void @_ZN1CD1Ev
// CHECK: call void @_ZdlPv
diff --git a/test/CodeGenCXX/virtual-functions-incomplete-types.cpp b/test/CodeGenCXX/virtual-functions-incomplete-types.cpp
index afa658f..624c89d 100644
--- a/test/CodeGenCXX/virtual-functions-incomplete-types.cpp
+++ b/test/CodeGenCXX/virtual-functions-incomplete-types.cpp
@@ -9,7 +9,7 @@ struct B {
void B::f() { }
-// CHECK: define i32 @_ZN1D1gEv(%struct.D* %this)
+// CHECK-LABEL: define i32 @_ZN1D1gEv(%struct.D* %this)
// CHECK: declare void @_ZN1B1gEv()
struct C;
diff --git a/test/CodeGenCXX/visibility-hidden-extern-templates.cpp b/test/CodeGenCXX/visibility-hidden-extern-templates.cpp
index 7629b77..549e674 100644
--- a/test/CodeGenCXX/visibility-hidden-extern-templates.cpp
+++ b/test/CodeGenCXX/visibility-hidden-extern-templates.cpp
@@ -14,13 +14,13 @@ extern template struct X<char>;
// <rdar://problem/8109763>
void test_X(X<int> xi, X<char> xc) {
- // CHECK: define weak_odr hidden void @_ZN1XIiE1fEv
+ // CHECK-LABEL: define weak_odr hidden void @_ZN1XIiE1fEv
xi.f();
- // CHECK: define weak_odr hidden void @_ZN1XIiE1gEv
+ // CHECK-LABEL: define weak_odr hidden void @_ZN1XIiE1gEv
xi.g();
// CHECK: declare void @_ZN1XIcE1fEv
xc.f();
- // CHECK: define available_externally void @_ZN1XIcE1gEv
+ // CHECK-LABEL: define available_externally void @_ZN1XIcE1gEv
xc.g();
}
diff --git a/test/CodeGenCXX/visibility-inlines-hidden.cpp b/test/CodeGenCXX/visibility-inlines-hidden.cpp
index e5bc743..7c0757b 100644
--- a/test/CodeGenCXX/visibility-inlines-hidden.cpp
+++ b/test/CodeGenCXX/visibility-inlines-hidden.cpp
@@ -37,31 +37,31 @@ struct __attribute__((visibility("default"))) X2 {
extern template struct X1<float>;
void use(X0 *x0, X1<int> *x1, X2 *x2, X1<float> *x3) {
- // CHECK: define linkonce_odr void @_ZN2X02f1Ev
+ // CHECK-LABEL: define linkonce_odr void @_ZN2X02f1Ev
x0->f1();
- // CHECK: define linkonce_odr hidden void @_ZN2X02f2Ev
+ // CHECK-LABEL: define linkonce_odr hidden void @_ZN2X02f2Ev
x0->f2();
- // CHECK: define linkonce_odr hidden void @_ZN2X02f3Ev
+ // CHECK-LABEL: define linkonce_odr hidden void @_ZN2X02f3Ev
x0->f3();
- // CHECK: define linkonce_odr hidden void @_ZN2X02f5Ev
+ // CHECK-LABEL: define linkonce_odr hidden void @_ZN2X02f5Ev
X0::f5();
- // CHECK: define linkonce_odr hidden void @_ZN2X02f6Ev
+ // CHECK-LABEL: define linkonce_odr hidden void @_ZN2X02f6Ev
x0->X0::f6();
- // CHECK: define linkonce_odr void @_ZN2X1IiE2f1Ev
+ // CHECK-LABEL: define linkonce_odr void @_ZN2X1IiE2f1Ev
x1->f1();
- // CHECK: define linkonce_odr hidden void @_ZN2X1IiE2f2Ev
+ // CHECK-LABEL: define linkonce_odr hidden void @_ZN2X1IiE2f2Ev
x1->f2();
- // CHECK: define linkonce_odr hidden void @_ZN2X1IiE2f3Ev
+ // CHECK-LABEL: define linkonce_odr hidden void @_ZN2X1IiE2f3Ev
x1->f3();
- // CHECK: define linkonce_odr hidden void @_ZN2X1IiE2f4Ev
+ // CHECK-LABEL: define linkonce_odr hidden void @_ZN2X1IiE2f4Ev
x1->f4();
- // CHECK: define linkonce_odr hidden void @_ZN2X1IiE2f5Ev
+ // CHECK-LABEL: define linkonce_odr hidden void @_ZN2X1IiE2f5Ev
X1<int>::f5();
- // CHECK: define linkonce_odr hidden void @_ZN2X1IiE2f6Ev
+ // CHECK-LABEL: define linkonce_odr hidden void @_ZN2X1IiE2f6Ev
x1->X1::f6();
- // CHECK: define linkonce_odr hidden void @_ZN2X22f2Ev
+ // CHECK-LABEL: define linkonce_odr hidden void @_ZN2X22f2Ev
x2->f2();
- // CHECK: define available_externally void @_ZN2X1IfE2f2Ev
+ // CHECK-LABEL: define available_externally void @_ZN2X1IfE2f2Ev
x3->f2();
}
@@ -95,7 +95,7 @@ namespace test2 {
ns::foo<arg>();
}
- // CHECK: define available_externally void @_ZN5test22ns3fooINS_1BINS_1AEEEEEvv()
+ // CHECK-LABEL: define available_externally void @_ZN5test22ns3fooINS_1BINS_1AEEEEEvv()
}
namespace PR11642 {
@@ -106,7 +106,7 @@ namespace PR11642 {
};
extern template class Foo<int>;
template class Foo<int>;
- // CHECK: define weak_odr i32 @_ZN7PR116423FooIiE3fooEi
+ // CHECK-LABEL: define weak_odr i32 @_ZN7PR116423FooIiE3fooEi
}
// Test that clang implements the new gcc behaviour for inline functions.
@@ -122,9 +122,9 @@ namespace test3 {
foo();
zed<int>();
}
- // CHECK: define weak_odr void @_ZN5test33zedIfEEvv
- // CHECK: define linkonce_odr hidden void @_ZN5test33fooEv
- // CHECK: define linkonce_odr hidden void @_ZN5test33zedIiEEvv
+ // CHECK-LABEL: define weak_odr void @_ZN5test33zedIfEEvv
+ // CHECK-LABEL: define linkonce_odr hidden void @_ZN5test33fooEv
+ // CHECK-LABEL: define linkonce_odr hidden void @_ZN5test33zedIiEEvv
}
namespace test4 {
@@ -133,7 +133,7 @@ namespace test4 {
void bar() {
foo();
}
- // CHECK: define available_externally void @_ZN5test43fooE
+ // CHECK-LABEL: define available_externally void @_ZN5test43fooE
}
namespace test5 {
diff --git a/test/CodeGenCXX/visibility-ms-compat.cpp b/test/CodeGenCXX/visibility-ms-compat.cpp
index 58a8fed..25446cd 100644
--- a/test/CodeGenCXX/visibility-ms-compat.cpp
+++ b/test/CodeGenCXX/visibility-ms-compat.cpp
@@ -22,7 +22,7 @@ namespace test0 {
};
void A::foo() { bar(); }
- // CHECK: define hidden void @_ZN5test01A3fooEv()
+ // CHECK-LABEL: define hidden void @_ZN5test01A3fooEv()
// CHECK: declare void @_ZN5test01A3barEv()
const std::type_info &ti = typeid(A);
@@ -38,7 +38,7 @@ namespace test1 {
};
void A::foo() { bar(); }
- // CHECK: define hidden void @_ZN5test11A3fooEv()
+ // CHECK-LABEL: define hidden void @_ZN5test11A3fooEv()
// CHECK: declare hidden void @_ZN5test11A3barEv()
const std::type_info &ti = typeid(A);
@@ -54,7 +54,7 @@ namespace test2 {
};
void A::foo() { bar(); }
- // CHECK: define void @_ZN5test21A3fooEv()
+ // CHECK-LABEL: define void @_ZN5test21A3fooEv()
// CHECK: declare void @_ZN5test21A3barEv()
const std::type_info &ti = typeid(A);
@@ -71,7 +71,7 @@ namespace test3 {
};
template void B<A>::foo();
- // CHECK: define weak_odr hidden void @_ZN5test31BINS_1AEE3fooEv()
+ // CHECK-LABEL: define weak_odr hidden void @_ZN5test31BINS_1AEE3fooEv()
// CHECK: declare void @_ZN5test31BINS_1AEE3barEv()
const std::type_info &ti = typeid(B<A>);
@@ -87,7 +87,7 @@ namespace test4 {
};
template void B<A>::foo();
- // CHECK: define weak_odr void @_ZN5test41BINS_1AEE3fooEv()
+ // CHECK-LABEL: define weak_odr void @_ZN5test41BINS_1AEE3fooEv()
// CHECK: declare void @_ZN5test41BINS_1AEE3barEv()
const std::type_info &ti = typeid(B<A>);
@@ -103,7 +103,7 @@ namespace test5 {
};
template void B<A>::foo();
- // CHECK: define weak_odr hidden void @_ZN5test51BINS_1AEE3fooEv()
+ // CHECK-LABEL: define weak_odr hidden void @_ZN5test51BINS_1AEE3fooEv()
// CHECK: declare hidden void @_ZN5test51BINS_1AEE3barEv()
const std::type_info &ti = typeid(B<A>);
diff --git a/test/CodeGenCXX/visibility.cpp b/test/CodeGenCXX/visibility.cpp
index 87add44..1c4d5bb 100644
--- a/test/CodeGenCXX/visibility.cpp
+++ b/test/CodeGenCXX/visibility.cpp
@@ -139,12 +139,16 @@ namespace test27 {
// CHECK: @_ZGVZN6Test193fooIiEEvvE1a = linkonce_odr global i64
// CHECK-HIDDEN: @_ZZN6Test193fooIiEEvvE1a = linkonce_odr hidden global
// CHECK-HIDDEN: @_ZGVZN6Test193fooIiEEvvE1a = linkonce_odr hidden global i64
+// CHECK: @_ZZN6test681fC1EvE4test = linkonce_odr global
+// CHECK: @_ZGVZN6test681fC1EvE4test = linkonce_odr global
+// CHECK-HIDDEN: @_ZZN6test681fC1EvE4test = linkonce_odr hidden global
+// CHECK-HIDDEN: @_ZGVZN6test681fC1EvE4test = linkonce_odr hidden global
// CHECK-HIDDEN: @_ZTVN6Test161AIcEE = external unnamed_addr constant
// CHECK-HIDDEN: @_ZTTN6Test161AIcEE = external unnamed_addr constant
// CHECK: @_ZTVN5Test63fooE = linkonce_odr hidden unnamed_addr constant
namespace Test1 {
- // CHECK: define hidden void @_ZN5Test11fEv
+ // CHECK-LABEL: define hidden void @_ZN5Test11fEv
void HIDDEN f() { }
}
@@ -155,7 +159,7 @@ namespace Test2 {
};
// A::f is a member function of a hidden class.
- // CHECK: define hidden void @_ZN5Test21A1fEv
+ // CHECK-LABEL: define hidden void @_ZN5Test21A1fEv
void A::f() { }
}
@@ -167,7 +171,7 @@ namespace Test3 {
};
// B is a nested class where its parent class is hidden.
- // CHECK: define hidden void @_ZN5Test31A1B1fEv
+ // CHECK-LABEL: define hidden void @_ZN5Test31A1B1fEv
void A::B::f() { }
}
@@ -175,7 +179,7 @@ namespace Test4 HIDDEN {
int VariableInHiddenNamespace = 10;
// Test4::g is in a hidden namespace.
- // CHECK: define hidden void @_ZN5Test41gEv
+ // CHECK-LABEL: define hidden void @_ZN5Test41gEv
void g() { }
struct DEFAULT A {
@@ -183,7 +187,7 @@ namespace Test4 HIDDEN {
};
// A has default visibility.
- // CHECK: define void @_ZN5Test41A1fEv
+ // CHECK-LABEL: define void @_ZN5Test41A1fEv
void A::f() { }
}
@@ -191,13 +195,13 @@ namespace Test5 {
namespace NS HIDDEN {
// f is in NS which is hidden.
- // CHECK: define hidden void @_ZN5Test52NS1fEv()
+ // CHECK-LABEL: define hidden void @_ZN5Test52NS1fEv()
void f() { }
}
namespace NS {
// g is in NS, but this NS decl is not hidden.
- // CHECK: define void @_ZN5Test52NS1gEv
+ // CHECK-LABEL: define void @_ZN5Test52NS1gEv
void g() { }
}
}
@@ -231,7 +235,7 @@ namespace Test7 {
class B : public A {};
B b; // top of file
- // CHECK: define linkonce_odr hidden void @_ZN5Test74ArefILZNS_1aEEE3fooEv()
+ // CHECK-LABEL: define linkonce_odr hidden void @_ZN5Test74ArefILZNS_1aEEE3fooEv()
void test() {
Aref<a>::foo();
}
@@ -240,7 +244,7 @@ namespace Test7 {
namespace Test8 {
void foo();
void bar() {}
- // CHECK-HIDDEN: define hidden void @_ZN5Test83barEv()
+ // CHECK-HIDDEN-LABEL: define hidden void @_ZN5Test83barEv()
// CHECK-HIDDEN: declare void @_ZN5Test83fooEv()
void test() {
@@ -256,8 +260,8 @@ namespace Test9 {
void DEFAULT test9_fun(struct A *a) { }
struct A DEFAULT test9_var; // above
}
- // CHECK: define void @test9_fun(
- // CHECK-HIDDEN: define void @test9_fun(
+ // CHECK-LABEL: define void @test9_fun(
+ // CHECK-HIDDEN-LABEL: define void @test9_fun(
void test() {
A a = test9_var;
@@ -273,8 +277,8 @@ namespace Test10 {
void foo(A*);
};
- // CHECK: define void @_ZN6Test101B3fooEPNS_1AE(
- // CHECK-HIDDEN: define void @_ZN6Test101B3fooEPNS_1AE(
+ // CHECK-LABEL: define void @_ZN6Test101B3fooEPNS_1AE(
+ // CHECK-HIDDEN-LABEL: define void @_ZN6Test101B3fooEPNS_1AE(
void B::foo(A*) {}
}
@@ -291,10 +295,10 @@ namespace Test11 {
a.bar();
}
- // CHECK: define linkonce_odr void @_ZN6Test111A3fooEv(
- // CHECK: define linkonce_odr void @_ZN6Test111A3barEv(
- // CHECK-HIDDEN: define linkonce_odr hidden void @_ZN6Test111A3fooEv(
- // CHECK-HIDDEN: define linkonce_odr void @_ZN6Test111A3barEv(
+ // CHECK-LABEL: define linkonce_odr void @_ZN6Test111A3fooEv(
+ // CHECK-LABEL: define linkonce_odr void @_ZN6Test111A3barEv(
+ // CHECK-HIDDEN-LABEL: define linkonce_odr hidden void @_ZN6Test111A3fooEv(
+ // CHECK-HIDDEN-LABEL: define linkonce_odr void @_ZN6Test111A3barEv(
}
// Tested at top of file.
@@ -481,7 +485,7 @@ namespace Test20 {
static void test1();
};
- // CHECK: define hidden void @_ZN6Test201AILj0EE5test0Ev()
+ // CHECK-LABEL: define hidden void @_ZN6Test201AILj0EE5test0Ev()
void A<0>::test0() {}
// CHECK: declare hidden void @_ZN6Test201AILj0EE5test1Ev()
@@ -495,7 +499,7 @@ namespace Test20 {
static void test3();
};
- // CHECK: define void @_ZN6Test201AILj1EE5test2Ev()
+ // CHECK-LABEL: define void @_ZN6Test201AILj1EE5test2Ev()
void A<1>::test2() {}
// CHECK: declare void @_ZN6Test201AILj1EE5test3Ev()
@@ -511,7 +515,7 @@ namespace Test20 {
static void test5();
};
- // CHECK: define linkonce_odr hidden void @_ZN6Test201BINS_1AILj2EEEE5test4Ev()
+ // CHECK-LABEL: define linkonce_odr hidden void @_ZN6Test201BINS_1AILj2EEEE5test4Ev()
void test4() {
B<A<2> >::test4();
}
@@ -529,7 +533,7 @@ namespace test21 {
DEFAULT void foo() {}
};
- // CHECK: define weak_odr void @_ZN6test211AILNS_2EnE0EE3fooEv(
+ // CHECK-LABEL: define weak_odr void @_ZN6test211AILNS_2EnE0EE3fooEv(
template void A<en>::foo();
}
@@ -556,13 +560,13 @@ namespace test22 {
B<A2>::bar();
}
// CHECK: declare void @_ZN6test221BINS_2A1EE3fooEv()
- // CHECK: define linkonce_odr void @_ZN6test221BINS_2A1EE3barEv()
+ // CHECK-LABEL: define linkonce_odr void @_ZN6test221BINS_2A1EE3barEv()
// CHECK: declare void @_ZN6test221BINS_2A2EE3fooEv()
- // CHECK: define linkonce_odr void @_ZN6test221BINS_2A2EE3barEv()
+ // CHECK-LABEL: define linkonce_odr void @_ZN6test221BINS_2A2EE3barEv()
// CHECK-HIDDEN: declare void @_ZN6test221BINS_2A1EE3fooEv()
- // CHECK-HIDDEN: define linkonce_odr void @_ZN6test221BINS_2A1EE3barEv()
+ // CHECK-HIDDEN-LABEL: define linkonce_odr void @_ZN6test221BINS_2A1EE3barEv()
// CHECK-HIDDEN: declare void @_ZN6test221BINS_2A2EE3fooEv()
- // CHECK-HIDDEN: define linkonce_odr hidden void @_ZN6test221BINS_2A2EE3barEv()
+ // CHECK-HIDDEN-LABEL: define linkonce_odr hidden void @_ZN6test221BINS_2A2EE3barEv()
}
namespace PR10113 {
@@ -573,14 +577,14 @@ namespace PR10113 {
};
}
template class foo::bar<char>;
- // CHECK: define weak_odr void @_ZN7PR101133foo3barIcE3zedEv
- // CHECK-HIDDEN: define weak_odr void @_ZN7PR101133foo3barIcE3zedEv
+ // CHECK-LABEL: define weak_odr void @_ZN7PR101133foo3barIcE3zedEv
+ // CHECK-HIDDEN-LABEL: define weak_odr void @_ZN7PR101133foo3barIcE3zedEv
struct zed {
};
template class foo::bar<zed>;
- // CHECK: define weak_odr void @_ZN7PR101133foo3barINS_3zedEE3zedEv
- // CHECK-HIDDEN: define weak_odr hidden void @_ZN7PR101133foo3barINS_3zedEE3zedEv
+ // CHECK-LABEL: define weak_odr void @_ZN7PR101133foo3barINS_3zedEE3zedEv
+ // CHECK-HIDDEN-LABEL: define weak_odr hidden void @_ZN7PR101133foo3barINS_3zedEE3zedEv
}
namespace PR11690 {
@@ -589,13 +593,13 @@ namespace PR11690 {
}
};
template class DEFAULT Class<char>;
- // CHECK: define weak_odr void @_ZNK7PR116905ClassIcE4sizeEv
- // CHECK-HIDDEN: define weak_odr void @_ZNK7PR116905ClassIcE4sizeEv
+ // CHECK-LABEL: define weak_odr void @_ZNK7PR116905ClassIcE4sizeEv
+ // CHECK-HIDDEN-LABEL: define weak_odr void @_ZNK7PR116905ClassIcE4sizeEv
template<class T> void Method() {}
template DEFAULT void Method<char>();
- // CHECK: define weak_odr void @_ZN7PR116906MethodIcEEvv
- // CHECK-HIDDEN: define weak_odr void @_ZN7PR116906MethodIcEEvv
+ // CHECK-LABEL: define weak_odr void @_ZN7PR116906MethodIcEEvv
+ // CHECK-HIDDEN-LABEL: define weak_odr void @_ZN7PR116906MethodIcEEvv
}
namespace PR11690_2 {
@@ -610,8 +614,8 @@ namespace PR11690_2 {
struct baz {
};
template class foo::zed<baz>;
- // CHECK: define weak_odr void @_ZN9PR11690_23foo3zedINS_3bazENS0_3barEE3barEv
- // CHECK-HIDDEN: define weak_odr hidden void @_ZN9PR11690_23foo3zedINS_3bazENS0_3barEE3barEv
+ // CHECK-LABEL: define weak_odr void @_ZN9PR11690_23foo3zedINS_3bazENS0_3barEE3barEv
+ // CHECK-HIDDEN-LABEL: define weak_odr hidden void @_ZN9PR11690_23foo3zedINS_3bazENS0_3barEE3barEv
}
namespace test23 {
@@ -629,8 +633,8 @@ namespace test23 {
X<A> y;
y.f();
}
- // CHECK: define linkonce_odr void @_ZN6test231XINS_1AEE1fEv
- // CHECK-HIDDEN: define linkonce_odr hidden void @_ZN6test231XINS_1AEE1fEv
+ // CHECK-LABEL: define linkonce_odr void @_ZN6test231XINS_1AEE1fEv
+ // CHECK-HIDDEN-LABEL: define linkonce_odr hidden void @_ZN6test231XINS_1AEE1fEv
}
namespace PR12001 {
@@ -643,8 +647,8 @@ namespace PR12001 {
void f() {
Bind(Version());
}
- // CHECK: define linkonce_odr void @_ZN7PR120014BindINS_7VersionEEEvRKT_
- // CHECK-HIDDEN: define linkonce_odr hidden void @_ZN7PR120014BindINS_7VersionEEEvRKT_
+ // CHECK-LABEL: define linkonce_odr void @_ZN7PR120014BindINS_7VersionEEEvRKT_
+ // CHECK-HIDDEN-LABEL: define linkonce_odr hidden void @_ZN7PR120014BindINS_7VersionEEEvRKT_
}
namespace test24 {
@@ -659,8 +663,8 @@ namespace test24 {
S s;
s.mem<A>();
}
- // CHECK: define linkonce_odr void @_ZN6test241S3memINS_1AEEEvv
- // CHECK-HIDDEN: define linkonce_odr hidden void @_ZN6test241S3memINS_1AEEEvv
+ // CHECK-LABEL: define linkonce_odr void @_ZN6test241S3memINS_1AEEEvv
+ // CHECK-HIDDEN-LABEL: define linkonce_odr hidden void @_ZN6test241S3memINS_1AEEEvv
}
namespace test26 {
@@ -672,8 +676,8 @@ namespace test26 {
template<>
void C<int>::f() { }
- // CHECK: define void @_ZN6test261CIiE1fEv
- // CHECK-HIDDEN: define void @_ZN6test261CIiE1fEv
+ // CHECK-LABEL: define void @_ZN6test261CIiE1fEv
+ // CHECK-HIDDEN-LABEL: define void @_ZN6test261CIiE1fEv
}
namespace test31 {
@@ -697,8 +701,8 @@ namespace test32 {
};
void A::B::baz() {
}
- // CHECK: define void @_ZN6test321A1B3bazEv
- // CHECK-HIDDEN: define void @_ZN6test321A1B3bazEv
+ // CHECK-LABEL: define void @_ZN6test321A1B3bazEv
+ // CHECK-HIDDEN-LABEL: define void @_ZN6test321A1B3bazEv
}
namespace test33 {
@@ -709,8 +713,8 @@ namespace test33 {
struct HIDDEN zed {
};
template class DEFAULT foo<zed>;
- // CHECK: define weak_odr void @_ZN6test333fooINS_3zedEE3barEv
- // CHECK-HIDDEN: define weak_odr void @_ZN6test333fooINS_3zedEE3barEv
+ // CHECK-LABEL: define weak_odr void @_ZN6test333fooINS_3zedEE3barEv
+ // CHECK-HIDDEN-LABEL: define weak_odr void @_ZN6test333fooINS_3zedEE3barEv
}
namespace test34 {
@@ -719,8 +723,8 @@ namespace test34 {
template<class T>
void bar() {}
template DEFAULT void bar<foo>();
- // CHECK: define weak_odr void @_ZN6test343barINS_3fooEEEvv
- // CHECK-HIDDEN: define weak_odr void @_ZN6test343barINS_3fooEEEvv
+ // CHECK-LABEL: define weak_odr void @_ZN6test343barINS_3fooEEEvv
+ // CHECK-HIDDEN-LABEL: define weak_odr void @_ZN6test343barINS_3fooEEEvv
}
namespace test35 {
@@ -737,8 +741,8 @@ namespace test35 {
template class foo<zed>;
class DEFAULT zed {
};
- // CHECK: define weak_odr void @_ZN6test353fooINS_3zedEE3barEv
- // CHECK-HIDDEN: define weak_odr hidden void @_ZN6test353fooINS_3zedEE3barEv
+ // CHECK-LABEL: define weak_odr void @_ZN6test353fooINS_3zedEE3barEv
+ // CHECK-HIDDEN-LABEL: define weak_odr hidden void @_ZN6test353fooINS_3zedEE3barEv
}
namespace test36 {
@@ -749,8 +753,8 @@ namespace test36 {
class DEFAULT S1 {};
struct HIDDEN S2 {};
template class foo<S1, S2>;
- // CHECK: define weak_odr hidden void @_ZN6test363fooINS_2S1ENS_2S2EE3barEv
- // CHECK-HIDDEN: define weak_odr hidden void @_ZN6test363fooINS_2S1ENS_2S2EE3barEv
+ // CHECK-LABEL: define weak_odr hidden void @_ZN6test363fooINS_2S1ENS_2S2EE3barEv
+ // CHECK-HIDDEN-LABEL: define weak_odr hidden void @_ZN6test363fooINS_2S1ENS_2S2EE3barEv
}
namespace test37 {
@@ -759,8 +763,8 @@ namespace test37 {
template<class T>
DEFAULT void bar() {}
template DEFAULT void bar<foo>();
- // CHECK: define weak_odr void @_ZN6test373barINS_3fooEEEvv
- // CHECK-HIDDEN: define weak_odr void @_ZN6test373barINS_3fooEEEvv
+ // CHECK-LABEL: define weak_odr void @_ZN6test373barINS_3fooEEEvv
+ // CHECK-HIDDEN-LABEL: define weak_odr void @_ZN6test373barINS_3fooEEEvv
}
namespace test38 {
@@ -771,8 +775,8 @@ namespace test38 {
struct HIDDEN zed {
};
template class foo<zed>;
- // CHECK: define weak_odr hidden void @_ZN6test383fooINS_3zedEE3barEv
- // CHECK-HIDDEN: define weak_odr hidden void @_ZN6test383fooINS_3zedEE3barEv
+ // CHECK-LABEL: define weak_odr hidden void @_ZN6test383fooINS_3zedEE3barEv
+ // CHECK-HIDDEN-LABEL: define weak_odr hidden void @_ZN6test383fooINS_3zedEE3barEv
}
namespace test39 {
@@ -790,19 +794,19 @@ namespace test39 {
template void A<hidden_t>::B<hidden_t>::temp<default_t>();
template void A<hidden_t>::B<hidden_t>::temp<hidden_t>();
- // CHECK: define weak_odr hidden void @_ZN6test391AINS_8hidden_tEE1BIS1_E6hiddenEv
- // CHECK: define weak_odr void @_ZN6test391AINS_8hidden_tEE1BIS1_E6noattrEv
- // CHECK: define weak_odr void @_ZN6test391AINS_8hidden_tEE1BIS1_E4tempINS_9default_tEEEvv
+ // CHECK-LABEL: define weak_odr hidden void @_ZN6test391AINS_8hidden_tEE1BIS1_E6hiddenEv
+ // CHECK-LABEL: define weak_odr void @_ZN6test391AINS_8hidden_tEE1BIS1_E6noattrEv
+ // CHECK-LABEL: define weak_odr void @_ZN6test391AINS_8hidden_tEE1BIS1_E4tempINS_9default_tEEEvv
// GCC produces a default for this one. Why?
- // CHECK: define weak_odr hidden void @_ZN6test391AINS_8hidden_tEE1BIS1_E4tempIS1_EEvv
+ // CHECK-LABEL: define weak_odr hidden void @_ZN6test391AINS_8hidden_tEE1BIS1_E4tempIS1_EEvv
- // CHECK-HIDDEN: define weak_odr hidden void @_ZN6test391AINS_8hidden_tEE1BIS1_E6hiddenEv
- // CHECK-HIDDEN: define weak_odr void @_ZN6test391AINS_8hidden_tEE1BIS1_E6noattrEv
- // CHECK-HIDDEN: define weak_odr void @_ZN6test391AINS_8hidden_tEE1BIS1_E4tempINS_9default_tEEEvv
+ // CHECK-HIDDEN-LABEL: define weak_odr hidden void @_ZN6test391AINS_8hidden_tEE1BIS1_E6hiddenEv
+ // CHECK-HIDDEN-LABEL: define weak_odr void @_ZN6test391AINS_8hidden_tEE1BIS1_E6noattrEv
+ // CHECK-HIDDEN-LABEL: define weak_odr void @_ZN6test391AINS_8hidden_tEE1BIS1_E4tempINS_9default_tEEEvv
// GCC produces a default for this one. Why?
- // CHECK-HIDDEN: define weak_odr hidden void @_ZN6test391AINS_8hidden_tEE1BIS1_E4tempIS1_EEvv
+ // CHECK-HIDDEN-LABEL: define weak_odr hidden void @_ZN6test391AINS_8hidden_tEE1BIS1_E4tempIS1_EEvv
}
namespace test42 {
@@ -817,8 +821,8 @@ namespace test42 {
};
void bar<foo>::zed() {
}
- // CHECK: define void @_ZN6test423barINS_3fooEE3zedEv
- // CHECK-HIDDEN: define void @_ZN6test423barINS_3fooEE3zedEv
+ // CHECK-LABEL: define void @_ZN6test423barINS_3fooEE3zedEv
+ // CHECK-HIDDEN-LABEL: define void @_ZN6test423barINS_3fooEE3zedEv
}
namespace test43 {
@@ -830,8 +834,8 @@ namespace test43 {
template <>
DEFAULT void bar<foo>() {
}
- // CHECK: define void @_ZN6test433barINS_3fooEEEvv
- // CHECK-HIDDEN: define void @_ZN6test433barINS_3fooEEEvv
+ // CHECK-LABEL: define void @_ZN6test433barINS_3fooEEEvv
+ // CHECK-HIDDEN-LABEL: define void @_ZN6test433barINS_3fooEEEvv
}
namespace test44 {
@@ -844,8 +848,8 @@ namespace test44 {
}
template struct DEFAULT foo<bar>;
foo<bar> x;
- // CHECK: define internal void @_ZN6test443fooINS_12_GLOBAL__N_13barEEC1Ev
- // CHECK-HIDDEN: define internal void @_ZN6test443fooINS_12_GLOBAL__N_13barEEC1Ev
+ // CHECK-LABEL: define internal void @_ZN6test443fooINS_12_GLOBAL__N_13barEEC1Ev
+ // CHECK-HIDDEN-LABEL: define internal void @_ZN6test443fooINS_12_GLOBAL__N_13barEEC1Ev
}
namespace test45 {
@@ -861,8 +865,8 @@ namespace test45 {
}
template struct DEFAULT foo<int>::bar<zed>;
foo<int>::bar<zed> x;
- // CHECK: define internal void @_ZN6test453fooIiE3barINS_12_GLOBAL__N_13zedEEC1Ev
- // CHECK-HIDDEN: define internal void @_ZN6test453fooIiE3barINS_12_GLOBAL__N_13zedEEC1Ev
+ // CHECK-LABEL: define internal void @_ZN6test453fooIiE3barINS_12_GLOBAL__N_13zedEEC1Ev
+ // CHECK-HIDDEN-LABEL: define internal void @_ZN6test453fooIiE3barINS_12_GLOBAL__N_13zedEEC1Ev
}
namespace test46 {
@@ -876,8 +880,8 @@ namespace test46 {
void zed() {
foo<bar>();
}
- // CHECK: define internal void @_ZN6test463fooINS_12_GLOBAL__N_13barEEEvv
- // CHECK-HIDDEN: define internal void @_ZN6test463fooINS_12_GLOBAL__N_13barEEEvv
+ // CHECK-LABEL: define internal void @_ZN6test463fooINS_12_GLOBAL__N_13barEEEvv
+ // CHECK-HIDDEN-LABEL: define internal void @_ZN6test463fooINS_12_GLOBAL__N_13barEEEvv
}
namespace test47 {
@@ -893,8 +897,8 @@ namespace test47 {
void baz() {
foo::bar<zed>();
}
- // CHECK: define internal void @_ZN6test473foo3barINS_12_GLOBAL__N_13zedEEEvv
- // CHECK-HIDDEN: define internal void @_ZN6test473foo3barINS_12_GLOBAL__N_13zedEEEvv
+ // CHECK-LABEL: define internal void @_ZN6test473foo3barINS_12_GLOBAL__N_13zedEEEvv
+ // CHECK-HIDDEN-LABEL: define internal void @_ZN6test473foo3barINS_12_GLOBAL__N_13zedEEEvv
}
namespace test49 {
@@ -914,8 +918,8 @@ namespace test49 {
};
template void bar::zed<&x>();
- // CHECK: define weak_odr hidden void @_ZN6test493bar3zedIXadL_ZNS_1xEEEEEvv
- // CHECK-HIDDEN: define weak_odr hidden void @_ZN6test493bar3zedIXadL_ZNS_1xEEEEEvv
+ // CHECK-LABEL: define weak_odr hidden void @_ZN6test493bar3zedIXadL_ZNS_1xEEEEEvv
+ // CHECK-HIDDEN-LABEL: define weak_odr hidden void @_ZN6test493bar3zedIXadL_ZNS_1xEEEEEvv
}
namespace test50 {
@@ -932,8 +936,8 @@ namespace test50 {
}
};
template void bar<&x>::zed();
- // CHECK: define weak_odr hidden void @_ZN6test503barIXadL_ZNS_1xEEEE3zedEv
- // CHECK-HIDDEN: define weak_odr hidden void @_ZN6test503barIXadL_ZNS_1xEEEE3zedEv
+ // CHECK-LABEL: define weak_odr hidden void @_ZN6test503barIXadL_ZNS_1xEEEE3zedEv
+ // CHECK-HIDDEN-LABEL: define weak_odr hidden void @_ZN6test503barIXadL_ZNS_1xEEEE3zedEv
}
namespace test51 {
@@ -948,8 +952,8 @@ namespace test51 {
void DEFAULT zed() {
}
template void zed<&x>();
- // CHECK: define weak_odr hidden void @_ZN6test513zedIXadL_ZNS_1xEEEEEvv
- // CHECK-HIDDEN: define weak_odr hidden void @_ZN6test513zedIXadL_ZNS_1xEEEEEvv
+ // CHECK-LABEL: define weak_odr hidden void @_ZN6test513zedIXadL_ZNS_1xEEEEEvv
+ // CHECK-HIDDEN-LABEL: define weak_odr hidden void @_ZN6test513zedIXadL_ZNS_1xEEEEEvv
}
namespace test52 {
@@ -967,8 +971,8 @@ namespace test52 {
void f() {
zed<nullptr>();
}
- // CHECK: define internal void @_ZN6test523zedILPNS_12_GLOBAL__N_13fooE0EEEvv
- // CHECK-HIDDEN: define internal void @_ZN6test523zedILPNS_12_GLOBAL__N_13fooE0EEEvv
+ // CHECK-LABEL: define internal void @_ZN6test523zedILPNS_12_GLOBAL__N_13fooE0EEEvv
+ // CHECK-HIDDEN-LABEL: define internal void @_ZN6test523zedILPNS_12_GLOBAL__N_13fooE0EEEvv
}
namespace test53 {
@@ -1070,8 +1074,8 @@ namespace test58 {
bar<foo>::zed();
}
#pragma GCC visibility pop
- // CHECK: define linkonce_odr hidden void @_ZN6test583barINS_3fooEE3zedEv
- // CHECK-HIDDEN: define linkonce_odr hidden void @_ZN6test583barINS_3fooEE3zedEv
+ // CHECK-LABEL: define linkonce_odr hidden void @_ZN6test583barINS_3fooEE3zedEv
+ // CHECK-HIDDEN-LABEL: define linkonce_odr hidden void @_ZN6test583barINS_3fooEE3zedEv
}
namespace test59 {
@@ -1082,12 +1086,12 @@ namespace test59 {
void test() {}
void use() {
test<&g, &f>();
- // CHECK: define linkonce_odr hidden void @_ZN6test594testIXadL_ZNS_1gEvEEXadL_ZNS_1fEvEEEEvv
- // CHECK-HIDDEN: define linkonce_odr hidden void @_ZN6test594testIXadL_ZNS_1gEvEEXadL_ZNS_1fEvEEEEvv
+ // CHECK-LABEL: define linkonce_odr hidden void @_ZN6test594testIXadL_ZNS_1gEvEEXadL_ZNS_1fEvEEEEvv
+ // CHECK-HIDDEN-LABEL: define linkonce_odr hidden void @_ZN6test594testIXadL_ZNS_1gEvEEXadL_ZNS_1fEvEEEEvv
test<&f, &g>();
- // CHECK: define linkonce_odr hidden void @_ZN6test594testIXadL_ZNS_1fEvEEXadL_ZNS_1gEvEEEEvv
- // CHECK-HIDDEN: define linkonce_odr hidden void @_ZN6test594testIXadL_ZNS_1fEvEEXadL_ZNS_1gEvEEEEvv
+ // CHECK-LABEL: define linkonce_odr hidden void @_ZN6test594testIXadL_ZNS_1fEvEEXadL_ZNS_1gEvEEEEvv
+ // CHECK-HIDDEN-LABEL: define linkonce_odr hidden void @_ZN6test594testIXadL_ZNS_1fEvEEXadL_ZNS_1gEvEEEEvv
}
}
@@ -1100,12 +1104,12 @@ namespace test60 {
void test() {}
void use() {
test<a, b>();
- // CHECK: define linkonce_odr hidden void @_ZN6test604testINS_1aENS_1bEEEvv
- // CHECK-HIDDEN: define linkonce_odr hidden void @_ZN6test604testINS_1aENS_1bEEEvv
+ // CHECK-LABEL: define linkonce_odr hidden void @_ZN6test604testINS_1aENS_1bEEEvv
+ // CHECK-HIDDEN-LABEL: define linkonce_odr hidden void @_ZN6test604testINS_1aENS_1bEEEvv
test<b, a>();
- // CHECK: define linkonce_odr hidden void @_ZN6test604testINS_1bENS_1aEEEvv
- // CHECK-HIDDEN: define linkonce_odr hidden void @_ZN6test604testINS_1bENS_1aEEEvv
+ // CHECK-LABEL: define linkonce_odr hidden void @_ZN6test604testINS_1bENS_1aEEEvv
+ // CHECK-HIDDEN-LABEL: define linkonce_odr hidden void @_ZN6test604testINS_1bENS_1aEEEvv
}
}
@@ -1167,8 +1171,8 @@ namespace test63 {
A::foo<E0>();
A::B<E0>::foo();
}
- // CHECK: define linkonce_odr hidden void @_ZN6test631A3fooILNS_1EE0EEEvv()
- // CHECK: define linkonce_odr hidden void @_ZN6test631A1BILNS_1EE0EE3fooEv()
+ // CHECK-LABEL: define linkonce_odr hidden void @_ZN6test631A3fooILNS_1EE0EEEvv()
+ // CHECK-LABEL: define linkonce_odr hidden void @_ZN6test631A1BILNS_1EE0EE3fooEv()
}
// Don't ignore the visibility of template arguments just because we
@@ -1180,7 +1184,7 @@ namespace test64 {
};
template class B<A>;
- // CHECK: define weak_odr hidden void @_ZN6test641BINS_1AEE3fooEv()
+ // CHECK-LABEL: define weak_odr hidden void @_ZN6test641BINS_1AEE3fooEv()
}
namespace test65 {
@@ -1196,23 +1200,23 @@ namespace test65 {
static void foo() {}
};
- // CHECK: define void @_ZN6test651BINS_1AEE4funcEv()
+ // CHECK-LABEL: define void @_ZN6test651BINS_1AEE4funcEv()
template <> DEFAULT void B<A>::func() {}
- // CHECK: define void @_ZN6test651BINS_1AEE6funcT2IS1_EEvv()
+ // CHECK-LABEL: 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()
+ // CHECK-LABEL: define linkonce_odr void @_ZN6test651BINS_1AEE6funcT1IiEEvv()
+ // CHECK-LABEL: define linkonce_odr hidden void @_ZN6test651BINS_1AEE6funcT1IS1_EEvv()
template <> template <class T> DEFAULT void B<A>::funcT1() {}
- // CHECK: define linkonce_odr void @_ZN6test651BINS_1AEE5Inner3fooEv()
+ // CHECK-LABEL: 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()
+ // CHECK-LABEL: define linkonce_odr void @_ZN6test651BINS_1AEE6InnerTIiE3fooEv()
+ // CHECK-LABEL: define linkonce_odr hidden void @_ZN6test651BINS_1AEE6InnerTIS1_E3fooEv()
template <> template <class U> struct DEFAULT B<A>::InnerT {
static void foo() {}
};
@@ -1236,8 +1240,8 @@ namespace test66 {
class foo;
class DEFAULT foo;
template struct barT<foo>;
- // CHECK: define weak_odr void @_ZN6test664barTINS_3fooEE3zedEv
- // CHECK-HIDDEN: define weak_odr void @_ZN6test664barTINS_3fooEE3zedEv
+ // CHECK-LABEL: define weak_odr void @_ZN6test664barTINS_3fooEE3zedEv
+ // CHECK-HIDDEN-LABEL: define weak_odr void @_ZN6test664barTINS_3fooEE3zedEv
template <int* I>
struct DEFAULT barI {
@@ -1246,8 +1250,8 @@ namespace test66 {
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
+ // CHECK-LABEL: define weak_odr void @_ZN6test664barIIXadL_ZNS_1IEEEE3zedEv
+ // CHECK-HIDDEN-LABEL: define weak_odr void @_ZN6test664barIIXadL_ZNS_1IEEEE3zedEv
typedef void (*fType)(void);
template<fType F>
@@ -1257,8 +1261,8 @@ namespace test66 {
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
+ // CHECK-LABEL: define weak_odr void @_ZN6test664barFIXadL_ZNS_1FEvEEE3zedEv
+ // CHECK-HIDDEN-LABEL: define weak_odr void @_ZN6test664barFIXadL_ZNS_1FEvEEE3zedEv
}
namespace test67 {
@@ -1274,6 +1278,34 @@ namespace test67 {
class DEFAULT foo;
template struct bar<foo>;
- // CHECK: define weak_odr void @_ZN6test673barINS_3fooEE3zedEv
- // CHECK-HIDDEN: define weak_odr void @_ZN6test673barINS_3fooEE3zedEv
+ // CHECK-LABEL: define weak_odr void @_ZN6test673barINS_3fooEE3zedEv
+ // CHECK-HIDDEN-LABEL: define weak_odr void @_ZN6test673barINS_3fooEE3zedEv
+}
+
+namespace test68 {
+ class A { public: ~A(); };
+ class f {
+ public:
+ f() {
+ static A test;
+ }
+ };
+ void g() {
+ f a;
+ }
+ // Check lines at top of file.
+}
+
+namespace test69 {
+ // PR18174
+ namespace foo {
+ void f();
+ }
+ namespace foo {
+ void f() {};
+ }
+ namespace foo __attribute__((visibility("hidden"))) {
+ }
+ // CHECK-LABEL: define void @_ZN6test693foo1fEv
+ // CHECK-HIDDEN-LABEL: define hidden void @_ZN6test693foo1fEv
}
diff --git a/test/CodeGenCXX/vla.cpp b/test/CodeGenCXX/vla.cpp
index b523c76..b22f21c 100644
--- a/test/CodeGenCXX/vla.cpp
+++ b/test/CodeGenCXX/vla.cpp
@@ -16,7 +16,7 @@ int f() {
// rdar://problem/9506377
void test0(void *array, int n) {
- // CHECK: define void @_Z5test0Pvi(
+ // CHECK-LABEL: define void @_Z5test0Pvi(
// CHECK: [[ARRAY:%.*]] = alloca i8*, align 8
// CHECK-NEXT: [[N:%.*]] = alloca i32, align 4
// CHECK-NEXT: [[REF:%.*]] = alloca i16*, align 8
diff --git a/test/CodeGenCXX/volatile.cpp b/test/CodeGenCXX/volatile.cpp
index 6ebb2f1..38c8829 100644
--- a/test/CodeGenCXX/volatile.cpp
+++ b/test/CodeGenCXX/volatile.cpp
@@ -11,7 +11,7 @@ namespace test0 {
volatile A *array;
- // CHECK: define void @_ZN5test04testENS_1AE(
+ // CHECK-LABEL: define void @_ZN5test04testENS_1AE(
void test(A t) {
// CHECK: [[ARR:%.*]] = load [[A:%.*]]** @_ZN5test05arrayE, align 8
// CHECK-NEXT: [[IDX:%.*]] = getelementptr inbounds [[A]]* [[ARR]], i64 0
@@ -24,7 +24,7 @@ namespace test0 {
namespace test1 {
volatile int *x;
- // CHECK: define void @_ZN5test14testEv()
+ // CHECK-LABEL: define void @_ZN5test14testEv()
void test() {
// CHECK: [[TMP:%.*]] = load i32** @_ZN5test11xE, align 8
// CHECK-NEXT: ret void
diff --git a/test/CodeGenCXX/vtable-available-externally.cpp b/test/CodeGenCXX/vtable-available-externally.cpp
index 693b36a..282bd2a 100644
--- a/test/CodeGenCXX/vtable-available-externally.cpp
+++ b/test/CodeGenCXX/vtable-available-externally.cpp
@@ -1,19 +1,11 @@
-// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -emit-llvm -O3 -o %t
+// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -emit-llvm -o %t
// RUN: FileCheck --check-prefix=CHECK-TEST1 %s < %t
// RUN: FileCheck --check-prefix=CHECK-TEST2 %s < %t
// RUN: FileCheck --check-prefix=CHECK-TEST5 %s < %t
-// RUN: FileCheck --check-prefix=CHECK-TEST7 %s < %t
#include <typeinfo>
-// 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: @_ZTIN5Test11AE = external constant i8*
+// CHECK-TEST1: @_ZTVN5Test11AE = external unnamed_addr constant
namespace Test1 {
struct A {
@@ -28,7 +20,7 @@ void f(A* a) {
a->f();
};
-// CHECK: define void @_ZN5Test11gEv
+// CHECK-LABEL: define void @_ZN5Test11gEv
// CHECK: call void @_ZN5Test11A1fEv
void g() {
A a;
@@ -106,7 +98,7 @@ void f() {
}
// PR9130, test that we emit a definition of A::f.
-// CHECK-TEST5: define linkonce_odr void @_ZN5Test51A1fEv
+// CHECK-TEST5-LABEL: define linkonce_odr void @_ZN5Test51A1fEv
namespace Test5 {
struct A {
@@ -159,14 +151,4 @@ struct c11 : c10, c1{
struct c28 : virtual c11{
void f6 ();
};
-
-// CHECK-TEST7: define void @_ZN5Test79check_c28Ev
-// CHECK-TEST7: call void @_ZN5Test73c282f6Ev
-// CHECK-TEST7: ret void
-void check_c28 () {
- c28 obj;
- c11 *ptr = &obj;
- ptr->f6 ();
-}
-
}
diff --git a/test/CodeGenCXX/vtable-layout.cpp b/test/CodeGenCXX/vtable-layout.cpp
index 1e831d2..ca5384d 100644
--- a/test/CodeGenCXX/vtable-layout.cpp
+++ b/test/CodeGenCXX/vtable-layout.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm-only -fdump-vtable-layouts > %t 2>&1
+// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm-only -fdump-vtable-layouts > %t
// RUN: FileCheck --check-prefix=CHECK-1 %s < %t
// RUN: FileCheck --check-prefix=CHECK-2 %s < %t
// RUN: FileCheck --check-prefix=CHECK-3 %s < %t
@@ -44,6 +44,7 @@
// RUN: FileCheck --check-prefix=CHECK-43 %s < %t
// RUN: FileCheck --check-prefix=CHECK-44 %s < %t
// RUN: FileCheck --check-prefix=CHECK-45 %s < %t
+// RUN: FileCheck --check-prefix=CHECK-46 %s < %t
// For now, just verify this doesn't crash.
namespace test0 {
@@ -61,6 +62,9 @@ namespace Test1 {
// CHECK-1-NEXT: 1 | Test1::A RTTI
// CHECK-1-NEXT: -- (Test1::A, 0) vtable address --
// CHECK-1-NEXT: 2 | void Test1::A::f()
+//
+// CHECK-1: VTable indices for 'Test1::A' (1 entries).
+// CHECK-1-NEXT: 0 | void Test1::A::f()
struct A {
virtual void f();
};
@@ -82,6 +86,15 @@ namespace Test2 {
// CHECK-2-NEXT: 6 | Test2::A::~A() [deleting]
// CHECK-2-NEXT: 7 | void Test2::A::h()
// CHECK-2-NEXT: 8 | Test2::A &Test2::A::operator=(const Test2::A &)
+//
+// CHECK-2: VTable indices for 'Test2::A' (7 entries).
+// CHECK-2-NEXT: 0 | void Test2::A::f()
+// CHECK-2-NEXT: 1 | void Test2::A::f() const
+// CHECK-2-NEXT: 2 | Test2::A *Test2::A::g(int)
+// CHECK-2-NEXT: 3 | Test2::A::~A() [complete]
+// CHECK-2-NEXT: 4 | Test2::A::~A() [deleting]
+// CHECK-2-NEXT: 5 | void Test2::A::h()
+// CHECK-2-NEXT: 6 | Test2::A &Test2::A::operator=(const Test2::A &)
struct A {
virtual void f();
virtual void f() const;
@@ -103,6 +116,12 @@ void A::f() { }
// CHECK-3-NEXT: 3 | void Test2::B::g() [pure]
// CHECK-3-NEXT: 4 | Test2::B::~B() [complete] [pure]
// CHECK-3-NEXT: 5 | Test2::B::~B() [deleting] [pure]
+//
+// CHECK-3: VTable indices for 'Test2::B' (4 entries).
+// CHECK-3-NEXT: 0 | void Test2::B::f()
+// CHECK-3-NEXT: 1 | void Test2::B::g()
+// CHECK-3-NEXT: 2 | Test2::B::~B() [complete]
+// CHECK-3-NEXT: 3 | Test2::B::~B() [deleting]
struct B {
virtual void f();
virtual void g() = 0;
@@ -123,6 +142,9 @@ namespace Test3 {
// CHECK-4-NEXT: 1 | Test3::A RTTI
// CHECK-4-NEXT: -- (Test3::A, 0) vtable address --
// CHECK-4-NEXT: 2 | void Test3::A::f()
+//
+// CHECK-4: VTable indices for 'Test3::A' (1 entries).
+// CHECK-4-NEXT: 0 | void Test3::A::f()
struct A {
virtual void f();
};
@@ -135,6 +157,10 @@ void A::f() { }
// CHECK-5-NEXT: -- (Test3::B, 0) vtable address --
// CHECK-5-NEXT: 2 | void Test3::B::f()
// CHECK-5-NEXT: 3 | void Test3::B::g()
+//
+// CHECK-5: VTable indices for 'Test3::B' (2 entries).
+// CHECK-5-NEXT: 0 | void Test3::B::f()
+// CHECK-5-NEXT: 1 | void Test3::B::g()
struct B : A {
virtual void f();
virtual void g();
@@ -149,6 +175,10 @@ void B::f() { }
// CHECK-6-NEXT: 2 | void Test3::A::f()
// CHECK-6-NEXT: 3 | void Test3::C::g()
// CHECK-6-NEXT: 4 | void Test3::C::h()
+//
+// CHECK-6: VTable indices for 'Test3::C' (2 entries).
+// CHECK-6-NEXT: 1 | void Test3::C::g()
+// CHECK-6-NEXT: 2 | void Test3::C::h()
struct C : A {
virtual void g();
virtual void h();
@@ -164,6 +194,11 @@ void C::g() { }
// CHECK-7-NEXT: 2 | void Test3::D::f()
// CHECK-7-NEXT: 3 | void Test3::D::g()
// CHECK-7-NEXT: 4 | void Test3::D::h()
+//
+// CHECK-7: VTable indices for 'Test3::D' (3 entries).
+// CHECK-7-NEXT: 0 | void Test3::D::f()
+// CHECK-7-NEXT: 1 | void Test3::D::g()
+// CHECK-7-NEXT: 2 | void Test3::D::h()
struct D : B {
virtual void f();
virtual void g();
@@ -193,7 +228,9 @@ struct A {
// CHECK-8-NEXT: 2 | Test4::R3 *Test4::B::f()
// CHECK-8-NEXT: [return adjustment: 4 non-virtual]
// CHECK-8-NEXT: 3 | Test4::R3 *Test4::B::f()
-
+//
+// CHECK-8: VTable indices for 'Test4::B' (1 entries).
+// CHECK-8-NEXT: 1 | Test4::R3 *Test4::B::f()
struct B : A {
virtual R3 *f();
};
@@ -215,6 +252,9 @@ struct C {
// CHECK-9-NEXT: 2 | Test4::V2 *Test4::D::f()
// CHECK-9-NEXT: [return adjustment: 0 non-virtual, -24 vbase offset offset]
// CHECK-9-NEXT: 3 | Test4::V2 *Test4::D::f()
+//
+// CHECK-9: VTable indices for 'Test4::D' (1 entries).
+// CHECK-9-NEXT: 1 | Test4::V2 *Test4::D::f()
struct D : C {
virtual V2 *f();
};
@@ -231,7 +271,9 @@ struct V3 : virtual R3 { int r3; };
// CHECK-10-NEXT: 2 | Test4::V3 *Test4::E::f()
// CHECK-10-NEXT: [return adjustment: 4 non-virtual, -24 vbase offset offset]
// CHECK-10-NEXT: 3 | Test4::V3 *Test4::E::f()
-
+//
+// CHECK-10: VTable indices for 'Test4::E' (1 entries).
+// CHECK-10-NEXT: 1 | Test4::V3 *Test4::E::f()
struct E : A {
virtual V3 *f();
};
@@ -247,6 +289,10 @@ V3 *E::f() { return 0;}
// CHECK-11-NEXT: 2 | Test4::R3 *Test4::F::f() [pure]
// CHECK-11-NEXT: 3 | void Test4::F::g()
// CHECK-11-NEXT: 4 | Test4::R3 *Test4::F::f() [pure]
+//
+// CHECK-11: VTable indices for 'Test4::F' (2 entries).
+// CHECK-11-NEXT: 1 | void Test4::F::g()
+// CHECK-11-NEXT: 2 | Test4::R3 *Test4::F::f()
struct F : A {
virtual void g();
virtual R3 *f() = 0;
@@ -289,6 +335,9 @@ struct B2 : A {
// CHECK-12-NEXT: -- (Test5::B2, 16) vtable address --
// CHECK-12-NEXT: 7 | void Test5::A::f()
// CHECK-12-NEXT: 8 | void Test5::B2::g()
+//
+// CHECK-12: VTable indices for 'Test5::C' (1 entries).
+// CHECK-12-NEXT: 2 | void Test5::C::h()
struct C : B1, B2 {
virtual void h();
};
@@ -319,6 +368,9 @@ struct A2 {
// CHECK-13-NEXT: -- (Test6::A2, 16) vtable address --
// CHECK-13-NEXT: 5 | void Test6::C::f()
// CHECK-13-NEXT: [this adjustment: -16 non-virtual]
+//
+// CHECK-13: VTable indices for 'Test6::C' (1 entries).
+// CHECK-13-NEXT: 0 | void Test6::C::f()
struct C : A1, A2 {
virtual void f();
};
@@ -360,6 +412,9 @@ struct C { virtual void c(); };
// CHECK-14-NEXT: -- (Test7::B2, 24) vtable address --
// CHECK-14-NEXT: 9 | void Test7::D::f()
// CHECK-14-NEXT: [this adjustment: -24 non-virtual]
+//
+// CHECK-14: VTable indices for 'Test7::D' (1 entries).
+// CHECK-14-NEXT: 1 | void Test7::D::f()
struct D : C, B1, B2 {
virtual void f();
};
@@ -379,7 +434,10 @@ struct A { };
// CHECK-15-NEXT: 1 | Test8::B RTTI
// CHECK-15-NEXT: -- (Test8::B, 0) vtable address --
// CHECK-15-NEXT: 2 | void Test8::B::f()
-struct B : A {
+//
+// CHECK-15: VTable indices for 'Test8::B' (1 entries).
+// CHECK-15-NEXT: 0 | void Test8::B::f()
+struct B : A {
virtual void f();
};
void B::f() { }
@@ -400,6 +458,9 @@ struct A2 { int a2; };
// CHECK-16-NEXT: 3 | Test9::B RTTI
// CHECK-16-NEXT: -- (Test9::B, 0) vtable address --
// CHECK-16-NEXT: 4 | void Test9::B::f()
+//
+// CHECK-16: VTable indices for 'Test9::B' (1 entries).
+// CHECK-16-NEXT: 0 | void Test9::B::f()
struct B : virtual A1, virtual A2 {
int b;
@@ -430,6 +491,9 @@ struct A2 { virtual void a2(); };
// CHECK-17-NEXT: 5 | Test10::C RTTI
// CHECK-17-NEXT: -- (Test10::A2, 8) vtable address --
// CHECK-17-NEXT: 6 | void Test10::A2::a2()
+//
+// CHECK-17: VTable indices for 'Test10::C' (1 entries).
+// CHECK-17-NEXT: 1 | void Test10::C::f()
struct B : A1, A2 {
int b;
};
@@ -461,6 +525,9 @@ struct B : A1, virtual A2 {
// CHECK-18-NEXT: 5 | vbase_offset (16)
// CHECK-18-NEXT: 6 | offset_to_top (-8)
// CHECK-18-NEXT: 7 | Test11::C RTTI
+//
+// CHECK-18: VTable indices for 'Test11::C' (1 entries).
+// CHECK-18-NEXT: 0 | void Test11::C::f()
struct C : virtual B {
virtual void f();
};
@@ -498,6 +565,10 @@ namespace Test12 {
// CHECK-19-NEXT: 17 | Test12::B RTTI
// CHECK-19-NEXT: -- (Test12::A3, 40) vtable address --
// CHECK-19-NEXT: 18 | void Test12::A3::a3()
+//
+// CHECK-19: VTable indices for 'Test12::B' (2 entries).
+// CHECK-19-NEXT: 0 | void Test12::B::f()
+// CHECK-19-NEXT: 1 | void Test12::B::a()
struct A1 {
virtual void a1();
int a;
@@ -548,6 +619,9 @@ struct B : virtual A {
// CHECK-20-NEXT: -- (Test13::B, 0) vtable address --
// CHECK-20-NEXT: -- (Test13::C, 0) vtable address --
// CHECK-20-NEXT: 5 | void Test13::C::f()
+//
+// CHECK-20: VTable indices for 'Test13::C' (1 entries).
+// CHECK-20-NEXT: 0 | void Test13::C::f()
struct C : virtual B, virtual A {
virtual void f();
};
@@ -577,6 +651,9 @@ struct C : virtual B { };
// CHECK-21-NEXT: -- (Test14::C, 0) vtable address --
// CHECK-21-NEXT: -- (Test14::D, 0) vtable address --
// CHECK-21-NEXT: 4 | void Test14::D::f()
+//
+// CHECK-21: VTable indices for 'Test14::D' (1 entries).
+// CHECK-21-NEXT: 0 | void Test14::D::f()
struct D : C, virtual B {
virtual void f();
};
@@ -608,6 +685,9 @@ struct C : virtual B { };
// CHECK-22-NEXT: -- (Test15::B, 8) vtable address --
// CHECK-22-NEXT: -- (Test15::C, 8) vtable address --
// CHECK-22-NEXT: 10 | void Test15::B::b()
+//
+// CHECK-22: VTable indices for 'Test15::D' (1 entries).
+// CHECK-22-NEXT: 1 | void Test15::D::f()
struct D : A, virtual B, virtual C {
virtual void f();
};
@@ -648,6 +728,11 @@ struct C : A, B { virtual ~C(); };
// CHECK-23-NEXT: [this adjustment: -8 non-virtual, -24 vcall offset offset]
// CHECK-23-NEXT: 14 | Test16::D::~D() [deleting]
// CHECK-23-NEXT: [this adjustment: -8 non-virtual, -24 vcall offset offset]
+//
+// CHECK-23: VTable indices for 'Test16::D' (3 entries).
+// CHECK-23-NEXT: 0 | void Test16::D::f()
+// CHECK-23-NEXT: 1 | Test16::D::~D() [complete]
+// CHECK-23-NEXT: 2 | Test16::D::~D() [deleting]
struct D : virtual C {
virtual void f();
};
@@ -683,6 +768,9 @@ struct D : virtual B, virtual C { virtual void f(); };
// CHECK-24-NEXT: -- (Test17::C, 8) vtable address --
// CHECK-24-NEXT: 12 | void Test17::E::f()
// CHECK-24-NEXT: [this adjustment: 0 non-virtual, -24 vcall offset offset]
+//
+// CHECK-24: VTable indices for 'Test17::E' (1 entries).
+// CHECK-24-NEXT: 0 | void Test17::E::f()
class E : virtual D {
virtual void f();
};
@@ -741,6 +829,10 @@ struct C : A, B {
// CHECK-25-NEXT: 22 | void Test18::D::f()
// CHECK-25-NEXT: [this adjustment: -8 non-virtual, -32 vcall offset offset]
// CHECK-25-NEXT: 23 | [unused] void Test18::C::g()
+//
+// CHECK-25: VTable indices for 'Test18::D' (2 entries).
+// CHECK-25-NEXT: 0 | void Test18::D::f()
+// CHECK-25-NEXT: 2 | void Test18::D::h()
// CHECK-25: Construction vtable for ('Test18::B', 0) in 'Test18::D' (7 entries).
// CHECK-25-NEXT: 0 | vbase_offset (0)
@@ -848,6 +940,9 @@ struct C {
// CHECK-26-NEXT: -- (Test19::A, 24) vtable address --
// CHECK-26-NEXT: 12 | void Test19::D::f()
// CHECK-26-NEXT: [this adjustment: 0 non-virtual, -24 vcall offset offset]
+//
+// CHECK-26: VTable indices for 'Test19::D' (1 entries).
+// CHECK-26-NEXT: 1 | void Test19::D::f()
struct D : C, B, virtual A {
virtual void f();
};
@@ -880,7 +975,11 @@ struct B : A { };
// CHECK-27-NEXT: -- (Test20::B, 8) vtable address --
// CHECK-27-NEXT: 7 | void Test20::C::f() [pure]
// CHECK-27-NEXT: 8 | void Test20::A::g()
-struct C : A, B {
+//
+// CHECK-27: VTable indices for 'Test20::C' (2 entries).
+// CHECK-27-NEXT: 0 | void Test20::C::f()
+// CHECK-27-NEXT: 2 | void Test20::C::h()
+struct C : A, B {
virtual void f() = 0;
virtual void h();
};
@@ -931,6 +1030,9 @@ class E : virtual C { };
// CHECK-28-NEXT: Test21::C | -48
// CHECK-28-NEXT: Test21::D | -56
// CHECK-28-NEXT: Test21::E | -64
+//
+// CHECK-28: VTable indices for 'Test21::F' (1 entries).
+// CHECK-28-NEXT: 0 | void Test21::F::f()
class F : virtual D, virtual E {
virtual void f();
};
@@ -960,6 +1062,9 @@ struct V2 : virtual V1 {
// CHECK-29-NEXT: 6 | offset_to_top (-16)
// CHECK-29-NEXT: 7 | Test22::C RTTI
// CHECK-29-NEXT: -- (Test22::V2, 16) vtable address --
+//
+// CHECK-29: VTable indices for 'Test22::C' (1 entries).
+// CHECK-29-NEXT: 0 | void Test22::C::f()
// CHECK-29: Construction vtable for ('Test22::V2', 16) in 'Test22::C' (3 entries).
// CHECK-29-NEXT: 0 | vbase_offset (-4)
@@ -1052,6 +1157,9 @@ struct C : virtual A { };
// CHECK-31-NEXT: 8 | Test24::D RTTI
// CHECK-31-NEXT: -- (Test24::C, 8) vtable address --
// CHECK-31-NEXT: 9 | [unused] void Test24::D::f()
+//
+// CHECK-31: VTable indices for 'Test24::D' (1 entries).
+// CHECK-31-NEXT: 0 | void Test24::D::f()
// CHECK-31: Construction vtable for ('Test24::B', 0) in 'Test24::D' (5 entries).
// CHECK-31-NEXT: 0 | vbase_offset (0)
@@ -1108,6 +1216,9 @@ struct B : virtual V { };
// CHECK-32-NEXT: 9 | Test25::C RTTI
// CHECK-32-NEXT: -- (Test25::B, 8) vtable address --
// CHECK-32-NEXT: 10 | [unused] void Test25::V::f()
+//
+// CHECK-32: VTable indices for 'Test25::C' (1 entries).
+// CHECK-32-NEXT: 1 | void Test25::C::g()
// CHECK-32: Construction vtable for ('Test25::A', 0) in 'Test25::C' (5 entries).
// CHECK-32-NEXT: 0 | vbase_offset (0)
@@ -1174,6 +1285,9 @@ struct C : virtual A {
// CHECK-33-NEXT: -- (Test26::C, 8) vtable address --
// CHECK-33-NEXT: 13 | void Test26::A::a()
// CHECK-33-NEXT: 14 | void Test26::C::b()
+//
+// CHECK-33: VTable indices for 'Test26::D' (1 entries).
+// CHECK-33-NEXT: 1 | void Test26::D::d()
// CHECK-33: Construction vtable for ('Test26::C', 8) in 'Test26::D' (7 entries).
// CHECK-33-NEXT: 0 | vcall_offset (0)
@@ -1232,6 +1346,9 @@ struct D : A, virtual B, C {
// CHECK-34-NEXT: 11 | Test27::E RTTI
// CHECK-34-NEXT: -- (Test27::B, 16) vtable address --
// CHECK-34-NEXT: 12 | void Test27::B::b()
+//
+// CHECK-34: VTable indices for 'Test27::E' (1 entries).
+// CHECK-34-NEXT: 2 | void Test27::E::e()
// CHECK-34: Construction vtable for ('Test27::D', 0) in 'Test27::E' (9 entries).
// CHECK-34-NEXT: 0 | vbase_offset (16)
@@ -1293,6 +1410,9 @@ struct D : virtual C {
// CHECK-35-NEXT: 12 | Test28::E RTTI
// CHECK-35-NEXT: -- (Test28::B, 16) vtable address --
// CHECK-35-NEXT: 13 | void Test28::B::b()
+//
+// CHECK-35: VTable indices for 'Test28::E' (1 entries).
+// CHECK-35-NEXT : 0 | void Test28::E::e()
// CHECK-35: Construction vtable for ('Test28::D', 0) in 'Test28::E' (13 entries).
// CHECK-35-NEXT: 0 | vbase_offset (8)
@@ -1342,6 +1462,9 @@ struct A {
// CHECK-36-NEXT: [return adjustment: 0 non-virtual, -24 vbase offset offset]
// CHECK-36-NEXT: [this adjustment: 0 non-virtual, -24 vcall offset offset]
// CHECK-36-NEXT: 5 | Test29::V2 *Test29::B::f()
+//
+// CHECK-36: VTable indices for 'Test29::B' (1 entries).
+// CHECK-36-NEXT: 1 | Test29::V2 *Test29::B::f()
struct B : virtual A {
virtual V2 *f();
};
@@ -1403,6 +1526,9 @@ struct C : A, virtual B {
// CHECK-37-NEXT: -- (Test31::C, 8) vtable address --
// CHECK-37-NEXT: 10 | void Test31::D::f()
// CHECK-37-NEXT: [this adjustment: 0 non-virtual, -24 vcall offset offset]
+//
+// CHECK-37: VTable indices for 'Test31::D' (1 entries).
+// CHECK-37-NEXT: 0 | void Test31::D::f()
struct D : virtual C {
virtual void f();
};
@@ -1494,6 +1620,9 @@ struct E : A, D {
// CHECK-39-NEXT: 28 | Test33::F RTTI
// CHECK-39-NEXT: -- (Test33::B, 24) vtable address --
// CHECK-39-NEXT: 29 | void Test33::B::b()
+//
+// CHECK-39: VTable indices for 'Test33::F' (1 entries).
+// CHECK-39-NEXT: 1 | void Test33::F::f()
struct F : virtual E, A {
virtual void f();
};
@@ -1631,12 +1760,15 @@ struct G : virtual E { };
// CHECK-41-NEXT: 29 | void Test35::C::c()
// CHECK-41-NEXT: 30 | void Test35::D::d()
// CHECK-41-NEXT: 31 | void Test35::E::e()
-
+//
// CHECK-41: Virtual base offset offsets for 'Test35::H' (4 entries).
// CHECK-41-NEXT: Test35::A | -32
// CHECK-41-NEXT: Test35::B | -24
// CHECK-41-NEXT: Test35::D | -56
// CHECK-41-NEXT: Test35::E | -64
+//
+// CHECK-41: VTable indices for 'Test35::H' (1 entries).
+// CHECK-41-NEXT: 2 | void Test35::H::h()
struct H : F, G {
virtual void h();
};
@@ -1676,6 +1808,9 @@ struct C : virtual A {
// CHECK-42-NEXT: -- (Test36::B, 8) vtable address --
// CHECK-42-NEXT: 11 | void Test36::C::f()
// CHECK-42-NEXT: [this adjustment: 0 non-virtual, -24 vcall offset offset]
+//
+// CHECK-42: VTable indices for 'Test36::D' (1 entries).
+// CHECK-42-NEXT: 1 | void Test36::D::g()
struct D : virtual B, C {
virtual void g();
};
@@ -1721,6 +1856,10 @@ namespace Test38 {
// CHECK-44-NEXT: -- (Test38::B, 0) vtable address --
// CHECK-44-NEXT: 5 | void *Test38::B::foo()
// CHECK-44-NEXT: 6 | const void *Test38::B::foo() const
+ //
+ // CHECK-44: VTable indices for 'Test38::B' (2 entries).
+ // CHECK-44-NEXT: 0 | void *Test38::B::foo()
+ // CHECK-44-NEXT: 1 | const void *Test38::B::foo() const
class B : virtual public A {
void *foo();
const void *foo() const;
@@ -1741,6 +1880,9 @@ namespace Test39 {
// CHECK-45-NEXT: -- (Test39::B, 0) vtable address --
// CHECK-45-NEXT: 2 | void Test39::A::foo() [deleted]
// CHECK-45-NEXT: 3 | void Test39::B::foo2()
+ //
+ // CHECK-45: VTable indices for 'Test39::B' (1 entries).
+ // CHECK-45-NEXT: 1 | void Test39::B::foo2()
struct B: A {
virtual void foo2();
};
@@ -1748,3 +1890,37 @@ namespace Test39 {
void B::foo2() {
}
}
+
+namespace Test40 {
+ struct A {
+ virtual void foo() = 0;
+ };
+
+ struct B : public A {
+ virtual void foo();
+ };
+
+ struct C: public B {
+ // CHECK-46: VTable indices for 'Test40::C' (8 entries).
+ // CHECK-46-NEXT: 1 | int Test40::C::f(int)
+ // CHECK-46-NEXT: 2 | int Test40::C::f()
+ // CHECK-46-NEXT: 3 | int Test40::C::g(int)
+ // CHECK-46-NEXT: 4 | int Test40::C::g()
+ // CHECK-46-NEXT: 5 | int Test40::C::h(int)
+ // CHECK-46-NEXT: 6 | int Test40::C::h()
+ // CHECK-46-NEXT: 7 | int Test40::C::i(int)
+ // CHECK-46-NEXT: 8 | int Test40::C::i()
+ virtual int f(int);
+ virtual int f();
+ virtual int g(int);
+ virtual int g();
+ virtual int h(int);
+ virtual int h();
+ virtual int i(int);
+ virtual int i();
+ };
+
+ class D : C {};
+
+ D d;
+}
diff --git a/test/CodeGenCXX/vtable-linkage.cpp b/test/CodeGenCXX/vtable-linkage.cpp
index b945e56..c17e333 100644
--- a/test/CodeGenCXX/vtable-linkage.cpp
+++ b/test/CodeGenCXX/vtable-linkage.cpp
@@ -1,24 +1,9 @@
// 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
-// RUN: FileCheck --check-prefix=CHECK-3 %s < %t
-// RUN: FileCheck --check-prefix=CHECK-4 %s < %t
-// RUN: FileCheck --check-prefix=CHECK-5 %s < %t
-// RUN: FileCheck --check-prefix=CHECK-5-HIDDEN %s < %t.hidden
-// RUN: FileCheck --check-prefix=CHECK-6 %s < %t
-// RUN: FileCheck --check-prefix=CHECK-6-HIDDEN %s < %t.hidden
-// 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
+// RUN: FileCheck --check-prefix=CHECK %s < %t
+// RUN: FileCheck --check-prefix=CHECK-HIDDEN %s < %t.hidden
+// RUN: FileCheck --check-prefix=CHECK-OPT %s < %t.opt
namespace {
struct A {
@@ -102,96 +87,94 @@ void use_F() {
// B has a key function that is not defined in this translation unit so its vtable
// has external linkage.
-// CHECK-1: @_ZTV1B = external unnamed_addr constant
+// CHECK-DAG: @_ZTV1B = external unnamed_addr constant
// C has no key function, so its vtable should have weak_odr linkage
// and hidden visibility (rdar://problem/7523229).
-// CHECK-2: @_ZTV1C = linkonce_odr unnamed_addr constant
-// CHECK-2: @_ZTS1C = linkonce_odr constant
-// CHECK-2: @_ZTI1C = linkonce_odr unnamed_addr constant
-// CHECK-2: @_ZTT1C = linkonce_odr unnamed_addr constant
-// CHECK-2-HIDDEN: @_ZTV1C = linkonce_odr hidden unnamed_addr constant
-// CHECK-2-HIDDEN: @_ZTS1C = linkonce_odr constant
-// CHECK-2-HIDDEN: @_ZTI1C = linkonce_odr hidden unnamed_addr constant
-// CHECK-2-HIDDEN: @_ZTT1C = linkonce_odr hidden unnamed_addr constant
+// CHECK-DAG: @_ZTV1C = linkonce_odr unnamed_addr constant
+// CHECK-DAG: @_ZTS1C = linkonce_odr constant
+// CHECK-DAG: @_ZTI1C = linkonce_odr unnamed_addr constant
+// CHECK-DAG: @_ZTT1C = linkonce_odr unnamed_addr constant
+// CHECK-HIDDEN-DAG: @_ZTV1C = linkonce_odr hidden unnamed_addr constant
+// CHECK-HIDDEN-DAG: @_ZTS1C = linkonce_odr constant
+// CHECK-HIDDEN-DAG: @_ZTI1C = linkonce_odr hidden unnamed_addr constant
+// CHECK-HIDDEN-DAG: @_ZTT1C = linkonce_odr hidden unnamed_addr constant
// D has a key function that is defined in this translation unit so its vtable is
// defined in the translation unit.
-// CHECK-3: @_ZTV1D = unnamed_addr constant
-// CHECK-3: @_ZTS1D = constant
-// CHECK-3: @_ZTI1D = unnamed_addr constant
+// CHECK-DAG: @_ZTV1D = unnamed_addr constant
+// CHECK-DAG: @_ZTS1D = constant
+// CHECK-DAG: @_ZTI1D = unnamed_addr constant
// E<char> is an explicit specialization with a key function defined
// in this translation unit, so its vtable should have external
// linkage.
-// CHECK-4: @_ZTV1EIcE = unnamed_addr constant
-// CHECK-4: @_ZTS1EIcE = constant
-// CHECK-4: @_ZTI1EIcE = unnamed_addr constant
+// CHECK-DAG: @_ZTV1EIcE = unnamed_addr constant
+// CHECK-DAG: @_ZTS1EIcE = constant
+// CHECK-DAG: @_ZTI1EIcE = unnamed_addr constant
// E<short> is an explicit template instantiation with a key function
// defined in this translation unit, so its vtable should have
// weak_odr linkage.
-// CHECK-5: @_ZTV1EIsE = weak_odr unnamed_addr constant
-// CHECK-5: @_ZTS1EIsE = weak_odr constant
-// CHECK-5: @_ZTI1EIsE = weak_odr unnamed_addr constant
-// CHECK-5-HIDDEN: @_ZTV1EIsE = weak_odr unnamed_addr constant
-// CHECK-5-HIDDEN: @_ZTS1EIsE = weak_odr constant
-// CHECK-5-HIDDEN: @_ZTI1EIsE = weak_odr unnamed_addr constant
+// CHECK-DAG: @_ZTV1EIsE = weak_odr unnamed_addr constant
+// CHECK-DAG: @_ZTS1EIsE = weak_odr constant
+// CHECK-DAG: @_ZTI1EIsE = weak_odr unnamed_addr constant
+// CHECK-HIDDEN-DAG: @_ZTV1EIsE = weak_odr unnamed_addr constant
+// CHECK-HIDDEN-DAG: @_ZTS1EIsE = weak_odr constant
+// CHECK-HIDDEN-DAG: @_ZTI1EIsE = weak_odr unnamed_addr constant
// F<short> is an explicit template instantiation without a key
// function, so its vtable should have weak_odr linkage
-// CHECK-6: @_ZTV1FIsE = weak_odr unnamed_addr constant
-// CHECK-6: @_ZTS1FIsE = weak_odr constant
-// CHECK-6: @_ZTI1FIsE = weak_odr unnamed_addr constant
-// CHECK-6-HIDDEN: @_ZTV1FIsE = weak_odr unnamed_addr constant
-// CHECK-6-HIDDEN: @_ZTS1FIsE = weak_odr constant
-// CHECK-6-HIDDEN: @_ZTI1FIsE = weak_odr unnamed_addr constant
+// CHECK-DAG: @_ZTV1FIsE = weak_odr unnamed_addr constant
+// CHECK-DAG: @_ZTS1FIsE = weak_odr constant
+// CHECK-DAG: @_ZTI1FIsE = weak_odr unnamed_addr constant
+// CHECK-HIDDEN-DAG: @_ZTV1FIsE = weak_odr unnamed_addr constant
+// CHECK-HIDDEN-DAG: @_ZTS1FIsE = weak_odr constant
+// CHECK-HIDDEN-DAG: @_ZTI1FIsE = weak_odr unnamed_addr constant
// E<long> is an implicit template instantiation with a key function
// defined in this translation unit, so its vtable should have
// linkonce_odr linkage.
-// CHECK-7: @_ZTV1EIlE = linkonce_odr unnamed_addr constant
-// CHECK-7: @_ZTS1EIlE = linkonce_odr constant
-// CHECK-7: @_ZTI1EIlE = linkonce_odr unnamed_addr constant
+// CHECK-DAG: @_ZTV1EIlE = linkonce_odr unnamed_addr constant
+// CHECK-DAG: @_ZTS1EIlE = linkonce_odr constant
+// CHECK-DAG: @_ZTI1EIlE = linkonce_odr unnamed_addr constant
// F<long> is an implicit template instantiation with no key function,
// so its vtable should have linkonce_odr linkage.
-// CHECK-8: @_ZTV1FIlE = linkonce_odr unnamed_addr constant
-// CHECK-8: @_ZTS1FIlE = linkonce_odr constant
-// CHECK-8: @_ZTI1FIlE = linkonce_odr unnamed_addr constant
+// CHECK-DAG: @_ZTV1FIlE = linkonce_odr unnamed_addr constant
+// CHECK-DAG: @_ZTS1FIlE = linkonce_odr constant
+// CHECK-DAG: @_ZTI1FIlE = linkonce_odr unnamed_addr constant
// 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
+// CHECK-DAG: @_ZTV1FIiE = external unnamed_addr constant
+// CHECK-OPT-DAG: @_ZTV1FIiE = external 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
+// CHECK-DAG: @_ZTV1EIiE = external unnamed_addr constant
+// CHECK-OPT-DAG: @_ZTV1EIiE = external unnamed_addr constant
// The anonymous struct for e has no linkage, so the vtable should have
// internal linkage.
-// CHECK-11: @"_ZTV3$_0" = internal unnamed_addr constant
-// CHECK-11: @"_ZTS3$_0" = internal constant
-// CHECK-11: @"_ZTI3$_0" = internal unnamed_addr constant
+// CHECK-DAG: @"_ZTV3$_0" = internal unnamed_addr constant
+// CHECK-DAG: @"_ZTS3$_0" = internal constant
+// CHECK-DAG: @"_ZTI3$_0" = internal unnamed_addr constant
// The A vtable should have internal linkage since it is inside an anonymous
// namespace.
-// CHECK-12: @_ZTVN12_GLOBAL__N_11AE = internal unnamed_addr constant
-// CHECK-12: @_ZTSN12_GLOBAL__N_11AE = internal constant
-// CHECK-12: @_ZTIN12_GLOBAL__N_11AE = internal unnamed_addr constant
+// CHECK-DAG: @_ZTVN12_GLOBAL__N_11AE = internal unnamed_addr constant
+// CHECK-DAG: @_ZTSN12_GLOBAL__N_11AE = internal constant
+// CHECK-DAG: @_ZTIN12_GLOBAL__N_11AE = internal unnamed_addr constant
// F<char> is an explicit specialization without a key function, so
// its vtable should have linkonce_odr linkage.
-// CHECK-13: @_ZTV1FIcE = linkonce_odr unnamed_addr constant
-// CHECK-13: @_ZTS1FIcE = linkonce_odr constant
-// CHECK-13: @_ZTI1FIcE = linkonce_odr unnamed_addr constant
+// CHECK-DAG: @_ZTV1FIcE = linkonce_odr unnamed_addr constant
+// CHECK-DAG: @_ZTS1FIcE = linkonce_odr constant
+// CHECK-DAG: @_ZTI1FIcE = linkonce_odr unnamed_addr constant
-// RUN: FileCheck --check-prefix=CHECK-G %s < %t
-//
-// CHECK-G: @_ZTV1GIiE = linkonce_odr unnamed_addr constant
+// CHECK-DAG: @_ZTV1GIiE = linkonce_odr unnamed_addr constant
template <typename T>
class G {
public:
@@ -205,11 +188,9 @@ template <typename T>
void G<T>::f0() {}
void G_f0() { new G<int>(); }
-// RUN: FileCheck --check-prefix=CHECK-H %s < %t
-
// H<int> has a key function without a body but it's a template instantiation
// so its VTable must be emitted.
-// CHECK-H: @_ZTV1HIiE = linkonce_odr unnamed_addr constant
+// CHECK-DAG: @_ZTV1HIiE = linkonce_odr unnamed_addr constant
template <typename T>
class H {
public:
@@ -220,21 +201,15 @@ 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.
+// construction vtables.
-// CHECK-I: @_ZTV1IIiE = external unnamed_addr constant
-// CHECK-I: @_ZTT1IIiE = external unnamed_addr constant
-// CHECK-I-NOT: @_ZTC1IIiE
+// CHECK-DAG: @_ZTV1IIiE = external unnamed_addr constant
+// CHECK-DAG: @_ZTT1IIiE = external unnamed_addr constant
+// CHECK-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
+// CHECK-OPT-DAG: @_ZTV1IIiE = external unnamed_addr constant
+// CHECK-OPT-DAG: @_ZTT1IIiE = external unnamed_addr constant
struct VBase1 { virtual void f(); }; struct VBase2 : virtual VBase1 {};
template<typename T>
struct I : VBase2 {};
diff --git a/test/CodeGenCXX/vtable-pointer-initialization.cpp b/test/CodeGenCXX/vtable-pointer-initialization.cpp
index 9b1eaa5..85e08d8 100644
--- a/test/CodeGenCXX/vtable-pointer-initialization.cpp
+++ b/test/CodeGenCXX/vtable-pointer-initialization.cpp
@@ -19,14 +19,14 @@ struct A : Base {
Field field;
};
-// CHECK: define void @_ZN1AC2Ev(%struct.A* %this) unnamed_addr
+// CHECK-LABEL: define void @_ZN1AC2Ev(%struct.A* %this) unnamed_addr
// CHECK: call void @_ZN4BaseC2Ev(
// CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTV1A, i64 0, i64 2)
// CHECK: call void @_ZN5FieldC1Ev(
// CHECK: ret void
A::A() { }
-// CHECK: define void @_ZN1AD2Ev(%struct.A* %this) unnamed_addr
+// CHECK-LABEL: define void @_ZN1AD2Ev(%struct.A* %this) unnamed_addr
// CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTV1A, i64 0, i64 2)
// CHECK: call void @_ZN5FieldD1Ev(
// CHECK: call void @_ZN4BaseD2Ev(
@@ -41,16 +41,16 @@ struct B : Base {
void f() { B b; }
-// CHECK: define linkonce_odr void @_ZN1BC1Ev(%struct.B* %this) unnamed_addr
+// CHECK-LABEL: define linkonce_odr void @_ZN1BC1Ev(%struct.B* %this) unnamed_addr
// CHECK: call void @_ZN1BC2Ev(
-// CHECK: define linkonce_odr void @_ZN1BD1Ev(%struct.B* %this) unnamed_addr
+// CHECK-LABEL: define linkonce_odr void @_ZN1BD1Ev(%struct.B* %this) unnamed_addr
// CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTV1B, i64 0, i64 2)
// CHECK: call void @_ZN5FieldD1Ev(
// CHECK: call void @_ZN4BaseD2Ev(
// CHECK: ret void
-// CHECK: define linkonce_odr void @_ZN1BC2Ev(%struct.B* %this) unnamed_addr
+// CHECK-LABEL: define linkonce_odr void @_ZN1BC2Ev(%struct.B* %this) unnamed_addr
// CHECK: call void @_ZN4BaseC2Ev(
// CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTV1B, i64 0, i64 2)
// CHECK: call void @_ZN5FieldC1Ev
diff --git a/test/CodeGenCXX/x86_32-arguments.cpp b/test/CodeGenCXX/x86_32-arguments.cpp
index 4404de0..2c7234e 100644
--- a/test/CodeGenCXX/x86_32-arguments.cpp
+++ b/test/CodeGenCXX/x86_32-arguments.cpp
@@ -6,9 +6,9 @@ struct S {
short s;
};
-// CHECK: define void @_Z1fv(%struct.S* noalias sret %
+// CHECK-LABEL: define void @_Z1fv(%struct.S* noalias sret %
S f() { return S(); }
-// CHECK: define void @_Z1f1S(%struct.S*)
+// CHECK-LABEL: define void @_Z1f1S(%struct.S*)
void f(S) { }
// Non-trivial dtors, should both be passed indirectly.
@@ -18,10 +18,10 @@ public:
double c;
};
-// CHECK: define void @_Z1gv(%class.C* noalias sret %
+// CHECK-LABEL: define void @_Z1gv(%class.C* noalias sret %
C g() { return C(); }
-// CHECK: define void @_Z1f1C(%class.C*)
+// CHECK-LABEL: define void @_Z1f1C(%class.C*)
void f(C) { }
@@ -29,7 +29,7 @@ void f(C) { }
// PR7058 - Missing byval on MI thunk definition.
-// CHECK: define void @_ZThn4_N18BasicAliasAnalysis13getModRefInfoE8CallSite
+// CHECK-LABEL: define void @_ZThn4_N18BasicAliasAnalysis13getModRefInfoE8CallSite
// ...
// CHECK: %struct.CallSite* byval align 4 %CS)
struct CallSite {
@@ -57,38 +57,38 @@ void BasicAliasAnalysis::getModRefInfo(CallSite CS) {
//
// PR7098.
-// CHECK: define i64 @_Z2f0v()
+// CHECK-LABEL: define i64 @_Z2f0v()
struct s0_0 { int x; };
struct s0_1 : s0_0 { int* y; };
s0_1 f0() { return s0_1(); }
-// CHECK: define i32 @_Z2f1v()
+// CHECK-LABEL: define i32 @_Z2f1v()
struct s1_0 { int x; };
struct s1_1 : s1_0 { };
s1_1 f1() { return s1_1(); }
-// CHECK: define double @_Z2f2v()
+// CHECK-LABEL: define double @_Z2f2v()
struct s2_0 { double x; };
struct s2_1 : s2_0 { };
s2_1 f2() { return s2_1(); }
-// CHECK: define double @_Z2f3v()
+// CHECK-LABEL: define double @_Z2f3v()
struct s3_0 { };
struct s3_1 { double x; };
struct s3_2 : s3_0, s3_1 { };
s3_2 f3() { return s3_2(); }
-// CHECK: define i64 @_Z2f4v()
+// CHECK-LABEL: define i64 @_Z2f4v()
struct s4_0 { float x; };
struct s4_1 { float x; };
struct s4_2 : s4_0, s4_1 { };
s4_2 f4() { return s4_2(); }
-// CHECK: define i32* @_Z2f5v()
+// CHECK-LABEL: define i32* @_Z2f5v()
struct s5 { s5(); int &x; };
s5 f5() { return s5(); }
-// CHECK: define i32 @_Z4f6_0M2s6i(i32 %a)
+// CHECK-LABEL: define i32 @_Z4f6_0M2s6i(i32 %a)
// CHECK: define i64 @_Z4f6_1M2s6FivE({ i32, i32 }* byval align 4)
// FIXME: It would be nice to avoid byval on the previous case.
struct s6 {};
@@ -97,19 +97,19 @@ typedef int (s6::*s6_mfp)();
s6_mdp f6_0(s6_mdp a) { return a; }
s6_mfp f6_1(s6_mfp a) { return a; }
-// CHECK: define double @_Z2f7v()
+// CHECK-LABEL: define double @_Z2f7v()
struct s7_0 { unsigned : 0; };
struct s7_1 { double x; };
struct s7 : s7_0, s7_1 { };
s7 f7() { return s7(); }
-// CHECK: define void @_Z2f8v(%struct.s8* noalias sret %agg.result)
+// CHECK-LABEL: define void @_Z2f8v(%struct.s8* noalias sret %agg.result)
struct s8_0 { };
struct s8_1 { double x; };
struct s8 { s8_0 a; s8_1 b; };
s8 f8() { return s8(); }
-// CHECK: define void @_Z2f9v(%struct.s9* noalias sret %agg.result)
+// CHECK-LABEL: define void @_Z2f9v(%struct.s9* noalias sret %agg.result)
struct s9_0 { unsigned : 0; };
struct s9_1 { double x; };
struct s9 { s9_0 a; s9_1 b; };
diff --git a/test/CodeGenCXX/x86_64-arguments.cpp b/test/CodeGenCXX/x86_64-arguments.cpp
index 6721803..2172e08 100644
--- a/test/CodeGenCXX/x86_64-arguments.cpp
+++ b/test/CodeGenCXX/x86_64-arguments.cpp
@@ -3,28 +3,28 @@
// Basic base class test.
struct f0_s0 { unsigned a; };
struct f0_s1 : public f0_s0 { void *b; };
-// CHECK: define void @_Z2f05f0_s1(i32 %a0.coerce0, i8* %a0.coerce1)
+// CHECK-LABEL: define void @_Z2f05f0_s1(i32 %a0.coerce0, i8* %a0.coerce1)
void f0(f0_s1 a0) { }
// Check with two eight-bytes in base class.
struct f1_s0 { unsigned a; unsigned b; float c; };
struct f1_s1 : public f1_s0 { float d;};
-// CHECK: define void @_Z2f15f1_s1(i64 %a0.coerce0, <2 x float> %a0.coerce1)
+// CHECK-LABEL: define void @_Z2f15f1_s1(i64 %a0.coerce0, <2 x float> %a0.coerce1)
void f1(f1_s1 a0) { }
// Check with two eight-bytes in base class and merge.
struct f2_s0 { unsigned a; unsigned b; float c; };
struct f2_s1 : public f2_s0 { char d;};
-// CHECK: define void @_Z2f25f2_s1(i64 %a0.coerce0, i64 %a0.coerce1)
+// CHECK-LABEL: define void @_Z2f25f2_s1(i64 %a0.coerce0, i64 %a0.coerce1)
void f2(f2_s1 a0) { }
// PR5831
-// CHECK: define void @_Z2f34s3_1(i64 %x.coerce)
+// CHECK-LABEL: define void @_Z2f34s3_1(i64 %x.coerce)
struct s3_0 {};
struct s3_1 { struct s3_0 a; long b; };
void f3(struct s3_1 x) {}
-// CHECK: define i64 @_Z4f4_0M2s4i(i64 %a)
+// CHECK-LABEL: define i64 @_Z4f4_0M2s4i(i64 %a)
// CHECK: define {{.*}} @_Z4f4_1M2s4FivE(i64 %a.coerce0, i64 %a.coerce1)
struct s4 {};
typedef int s4::* s4_mdp;
@@ -41,7 +41,7 @@ struct StringRef {
void AddKeyword(StringRef, int x);
void foo() {
- // CHECK: define void @_ZN6PR75233fooEv()
+ // CHECK-LABEL: define void @_ZN6PR75233fooEv()
// CHECK: call void @_ZN6PR752310AddKeywordENS_9StringRefEi(i8* {{.*}}, i32 4)
AddKeyword(StringRef(), 4);
}
@@ -54,7 +54,7 @@ namespace PR7742 { // Also rdar://8250764
struct c2 : public s2 {};
- // CHECK: define <2 x float> @_ZN6PR77423fooEPNS_2c2E(%"struct.PR7742::c2"* %P)
+ // CHECK-LABEL: define <2 x float> @_ZN6PR77423fooEPNS_2c2E(%"struct.PR7742::c2"* %P)
c2 foo(c2 *P) {
return c2();
}
@@ -72,7 +72,7 @@ namespace PR5179 {
B1 b1;
};
- // CHECK: define i8* @_ZN6PR51793barENS_2B2E(i32* %b2.coerce)
+ // CHECK-LABEL: define i8* @_ZN6PR51793barENS_2B2E(i32* %b2.coerce)
const void *bar(B2 b2) {
return b2.b1.pa;
}
@@ -114,7 +114,7 @@ namespace test6 {
int test(outer x) {
return x.x + x.f;
}
- // CHECK: define i32 @_ZN5test64testENS_5outerE(i64 %x.coerce0, i32 %x.coerce1)
+ // CHECK-LABEL: define i32 @_ZN5test64testENS_5outerE(i64 %x.coerce0, i32 %x.coerce1)
}
namespace test7 {
OpenPOWER on IntegriCloud