aboutsummaryrefslogtreecommitdiff
path: root/test/CodeGenCXX
diff options
context:
space:
mode:
Diffstat (limited to 'test/CodeGenCXX')
-rw-r--r--test/CodeGenCXX/2003-11-27-MultipleInheritanceThunk.cpp3
-rw-r--r--test/CodeGenCXX/2004-03-08-ReinterpretCastCopy.cpp3
-rw-r--r--test/CodeGenCXX/2004-03-09-UnmangledBuiltinMethods.cpp2
-rw-r--r--test/CodeGenCXX/2006-09-12-OpaqueStructCrash.cpp3
-rw-r--r--test/CodeGenCXX/2010-05-11-alwaysinlineinstantiation.cpp2
-rw-r--r--test/CodeGenCXX/Inputs/debug-info-class-limited.cpp (renamed from test/CodeGenCXX/debug-info-class-limited.cpp)11
-rw-r--r--test/CodeGenCXX/PR19955.cpp27
-rw-r--r--test/CodeGenCXX/PR20038.cpp16
-rw-r--r--test/CodeGenCXX/PR5050-constructor-conversion.cpp15
-rw-r--r--test/CodeGenCXX/PR5093-static-member-function.cpp2
-rw-r--r--test/CodeGenCXX/PR5863-unreachable-block.cpp2
-rw-r--r--test/CodeGenCXX/aarch64-arguments.cpp2
-rw-r--r--test/CodeGenCXX/aarch64-cxxabi.cpp6
-rw-r--r--test/CodeGenCXX/aarch64-mangle-neon-vectors.cpp7
-rw-r--r--test/CodeGenCXX/aarch64-neon.cpp6
-rw-r--r--test/CodeGenCXX/abstract-class-ctors-dtors.cpp4
-rw-r--r--test/CodeGenCXX/address-of-fntemplate.cpp2
-rw-r--r--test/CodeGenCXX/address-space-ref.cpp34
-rw-r--r--test/CodeGenCXX/apple-kext.cpp4
-rw-r--r--test/CodeGenCXX/arm.cpp18
-rw-r--r--test/CodeGenCXX/arm64-constructor-return.cpp19
-rw-r--r--test/CodeGenCXX/arm64-darwinpcs.cpp15
-rw-r--r--test/CodeGenCXX/arm64-empty-struct.cpp27
-rw-r--r--test/CodeGenCXX/arm64.cpp88
-rw-r--r--test/CodeGenCXX/array-construction.cpp14
-rw-r--r--test/CodeGenCXX/array-operator-delete-call.cpp13
-rw-r--r--test/CodeGenCXX/atomicinit.cpp56
-rw-r--r--test/CodeGenCXX/attr-cleanup.cpp2
-rw-r--r--test/CodeGenCXX/attr-used.cpp20
-rw-r--r--test/CodeGenCXX/bitfield-layout.cpp2
-rw-r--r--test/CodeGenCXX/bitfield.cpp58
-rw-r--r--test/CodeGenCXX/block-byref-cxx-objc.cpp2
-rw-r--r--test/CodeGenCXX/block-in-ctor-dtor.cpp4
-rw-r--r--test/CodeGenCXX/block.cpp3
-rw-r--r--test/CodeGenCXX/blocks-cxx11.cpp2
-rw-r--r--test/CodeGenCXX/blocks.cpp2
-rw-r--r--test/CodeGenCXX/c-linkage.cpp4
-rw-r--r--test/CodeGenCXX/call-arg-zero-temp.cpp2
-rw-r--r--test/CodeGenCXX/captured-statements.cpp2
-rw-r--r--test/CodeGenCXX/cast-conversion.cpp28
-rw-r--r--test/CodeGenCXX/catch-undef-behavior.cpp48
-rw-r--r--test/CodeGenCXX/class-layout.cpp11
-rw-r--r--test/CodeGenCXX/conditional-gnu-ext.cpp4
-rw-r--r--test/CodeGenCXX/const-base-cast.cpp2
-rw-r--r--test/CodeGenCXX/const-global-linkage.cpp2
-rw-r--r--test/CodeGenCXX/const-init-cxx11.cpp42
-rw-r--r--test/CodeGenCXX/const-init-cxx1y.cpp55
-rw-r--r--test/CodeGenCXX/constructor-attr.cpp2
-rw-r--r--test/CodeGenCXX/constructor-conversion.cpp19
-rw-r--r--test/CodeGenCXX/constructor-default-arg.cpp19
-rw-r--r--test/CodeGenCXX/constructor-destructor-return-this.cpp49
-rw-r--r--test/CodeGenCXX/constructor-direct-call.cpp15
-rw-r--r--test/CodeGenCXX/constructor-for-array-members.cpp13
-rw-r--r--test/CodeGenCXX/constructor-init-reference.cpp4
-rw-r--r--test/CodeGenCXX/constructor-init.cpp2
-rw-r--r--test/CodeGenCXX/constructor-template.cpp2
-rw-r--r--test/CodeGenCXX/constructors.cpp32
-rw-r--r--test/CodeGenCXX/convert-to-fptr.cpp17
-rw-r--r--test/CodeGenCXX/copy-assign-synthesis-1.cpp4
-rw-r--r--test/CodeGenCXX/copy-assign-synthesis-2.cpp4
-rw-r--r--test/CodeGenCXX/copy-constructor-elim-2.cpp3
-rw-r--r--test/CodeGenCXX/copy-constructor-elim.cpp9
-rw-r--r--test/CodeGenCXX/copy-constructor-synthesis-2.cpp4
-rw-r--r--test/CodeGenCXX/copy-constructor-synthesis.cpp18
-rw-r--r--test/CodeGenCXX/coverage.cpp2
-rw-r--r--test/CodeGenCXX/ctor-dtor-alias.cpp4
-rw-r--r--test/CodeGenCXX/cxx0x-defaulted-templates.cpp6
-rw-r--r--test/CodeGenCXX/cxx0x-delegating-ctors.cpp22
-rw-r--r--test/CodeGenCXX/cxx0x-initializer-stdinitializerlist-pr12086.cpp128
-rw-r--r--test/CodeGenCXX/cxx0x-initializer-stdinitializerlist-startend.cpp4
-rw-r--r--test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp54
-rw-r--r--test/CodeGenCXX/cxx11-exception-spec.cpp3
-rw-r--r--test/CodeGenCXX/cxx11-initializer-aggregate.cpp21
-rw-r--r--test/CodeGenCXX/cxx11-initializer-array-new.cpp86
-rw-r--r--test/CodeGenCXX/cxx11-noreturn.cpp2
-rw-r--r--test/CodeGenCXX/cxx11-thread-local-reference.cpp4
-rw-r--r--test/CodeGenCXX/cxx11-thread-local.cpp32
-rw-r--r--test/CodeGenCXX/cxx11-unrestricted-union.cpp2
-rw-r--r--test/CodeGenCXX/cxx1y-initializer-aggregate.cpp2
-rw-r--r--test/CodeGenCXX/cxx1y-variable-template.cpp4
-rw-r--r--test/CodeGenCXX/debug-info-alias.cpp37
-rw-r--r--test/CodeGenCXX/debug-info-anon-union-vars.cpp28
-rw-r--r--test/CodeGenCXX/debug-info-byval.cpp3
-rw-r--r--test/CodeGenCXX/debug-info-char16.cpp2
-rw-r--r--test/CodeGenCXX/debug-info-class-limited-plugin.test2
-rw-r--r--test/CodeGenCXX/debug-info-class-limited.test1
-rw-r--r--test/CodeGenCXX/debug-info-class-nolimit.cpp4
-rw-r--r--test/CodeGenCXX/debug-info-class.cpp15
-rw-r--r--test/CodeGenCXX/debug-info-ctor2.cpp3
-rw-r--r--test/CodeGenCXX/debug-info-dup-fwd-decl.cpp2
-rw-r--r--test/CodeGenCXX/debug-info-enum-class.cpp52
-rw-r--r--test/CodeGenCXX/debug-info-enum.cpp11
-rw-r--r--test/CodeGenCXX/debug-info-function-context.cpp8
-rw-r--r--test/CodeGenCXX/debug-info-gline-tables-only.cpp2
-rw-r--r--test/CodeGenCXX/debug-info-global-ctor-dtor.cpp4
-rw-r--r--test/CodeGenCXX/debug-info-global.cpp19
-rw-r--r--test/CodeGenCXX/debug-info-indirect-field-decl.cpp17
-rw-r--r--test/CodeGenCXX/debug-info-limited.cpp3
-rw-r--r--test/CodeGenCXX/debug-info-line-if.cpp20
-rw-r--r--test/CodeGenCXX/debug-info-member.cpp3
-rw-r--r--test/CodeGenCXX/debug-info-method-spec.cpp3
-rw-r--r--test/CodeGenCXX/debug-info-method.cpp2
-rw-r--r--test/CodeGenCXX/debug-info-method2.cpp2
-rw-r--r--test/CodeGenCXX/debug-info-namespace.cpp34
-rw-r--r--test/CodeGenCXX/debug-info-pubtypes.cpp16
-rw-r--r--test/CodeGenCXX/debug-info-qualifiers.cpp26
-rw-r--r--test/CodeGenCXX/debug-info-same-line.cpp155
-rw-r--r--test/CodeGenCXX/debug-info-scope.cpp4
-rw-r--r--test/CodeGenCXX/debug-info-template-explicit-specialization.cpp93
-rw-r--r--test/CodeGenCXX/debug-info-template-fwd.cpp27
-rw-r--r--test/CodeGenCXX/debug-info-template-limit.cpp2
-rw-r--r--test/CodeGenCXX/debug-info-template-member.cpp6
-rw-r--r--test/CodeGenCXX/debug-info-template-partial-specialization.cpp31
-rw-r--r--test/CodeGenCXX/debug-info-template.cpp10
-rw-r--r--test/CodeGenCXX/debug-info-thunk.cpp2
-rw-r--r--test/CodeGenCXX/debug-info-use-after-free.cpp2
-rw-r--r--test/CodeGenCXX/debug-info-uuid.cpp2
-rw-r--r--test/CodeGenCXX/debug-info-varargs.cpp22
-rw-r--r--test/CodeGenCXX/debug-info-vtable-optzn.cpp22
-rw-r--r--test/CodeGenCXX/debug-info.cpp20
-rw-r--r--test/CodeGenCXX/decl-ref-init.cpp16
-rw-r--r--test/CodeGenCXX/default-arg-temps.cpp4
-rw-r--r--test/CodeGenCXX/default-arguments.cpp6
-rw-r--r--test/CodeGenCXX/default-constructor-default-argument.cpp2
-rw-r--r--test/CodeGenCXX/default-constructor-for-members.cpp13
-rw-r--r--test/CodeGenCXX/default-constructor-template-member.cpp2
-rw-r--r--test/CodeGenCXX/default-destructor-nested.cpp2
-rw-r--r--test/CodeGenCXX/deferred-global-init.cpp4
-rw-r--r--test/CodeGenCXX/delayed-template-parsing.cpp4
-rw-r--r--test/CodeGenCXX/delete-two-arg.cpp3
-rw-r--r--test/CodeGenCXX/dependent-type-member-pointer.cpp1
-rw-r--r--test/CodeGenCXX/derived-to-base-conv.cpp4
-rw-r--r--test/CodeGenCXX/derived-to-virtual-base-class-calls-final.cpp4
-rw-r--r--test/CodeGenCXX/destructor-exception-spec.cpp6
-rw-r--r--test/CodeGenCXX/destructors.cpp37
-rw-r--r--test/CodeGenCXX/dllexport-members.cpp647
-rw-r--r--test/CodeGenCXX/dllexport.cpp686
-rw-r--r--test/CodeGenCXX/dllimport-members.cpp875
-rw-r--r--test/CodeGenCXX/dllimport-rtti.cpp13
-rw-r--r--test/CodeGenCXX/dllimport.cpp771
-rw-r--r--test/CodeGenCXX/duplicate-mangled-name.cpp10
-rw-r--r--test/CodeGenCXX/dynamic_cast-no-rtti.cpp2
-rw-r--r--test/CodeGenCXX/eh.cpp11
-rw-r--r--test/CodeGenCXX/elide-call-reference.cpp2
-rw-r--r--test/CodeGenCXX/empty-nontrivially-copyable.cpp3
-rw-r--r--test/CodeGenCXX/enable_if.cpp20
-rw-r--r--test/CodeGenCXX/exceptions-no-rtti.cpp10
-rw-r--r--test/CodeGenCXX/exceptions.cpp2
-rw-r--r--test/CodeGenCXX/explicit-instantiation.cpp76
-rw-r--r--test/CodeGenCXX/extern-c.cpp18
-rw-r--r--test/CodeGenCXX/fastcall.cpp2
-rw-r--r--test/CodeGenCXX/field-access-debug-info.cpp7
-rw-r--r--test/CodeGenCXX/flatten.cpp10
-rw-r--r--test/CodeGenCXX/funcsig.cpp29
-rw-r--r--test/CodeGenCXX/function-template-explicit-specialization.cpp2
-rw-r--r--test/CodeGenCXX/function-template-specialization.cpp2
-rw-r--r--test/CodeGenCXX/global-array-destruction.cpp4
-rw-r--r--test/CodeGenCXX/global-init.cpp6
-rw-r--r--test/CodeGenCXX/global-llvm-constant.cpp2
-rw-r--r--test/CodeGenCXX/globalinit-loc.cpp23
-rw-r--r--test/CodeGenCXX/goto.cpp2
-rw-r--r--test/CodeGenCXX/implicit-copy-assign-operator.cpp3
-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.cpp4
-rw-r--r--test/CodeGenCXX/init-priority-attr.cpp26
-rw-r--r--test/CodeGenCXX/inline-functions.cpp58
-rw-r--r--test/CodeGenCXX/instrument-functions.cpp2
-rw-r--r--test/CodeGenCXX/int64_uint64.cpp23
-rw-r--r--test/CodeGenCXX/internal-linkage.cpp2
-rw-r--r--test/CodeGenCXX/linetable-cleanup.cpp6
-rw-r--r--test/CodeGenCXX/linetable-eh.cpp44
-rw-r--r--test/CodeGenCXX/linetable-fnbegin.cpp28
-rw-r--r--test/CodeGenCXX/linkage.cpp42
-rw-r--r--test/CodeGenCXX/mangle-abi-examples.cpp2
-rw-r--r--test/CodeGenCXX/mangle-address-space.cpp2
-rw-r--r--test/CodeGenCXX/mangle-alias-template.cpp7
-rw-r--r--test/CodeGenCXX/mangle-lambdas.cpp2
-rw-r--r--test/CodeGenCXX/mangle-local-class-names.cpp2
-rw-r--r--test/CodeGenCXX/mangle-local-class-vtables.cpp2
-rw-r--r--test/CodeGenCXX/mangle-local-classes-nested.cpp2
-rw-r--r--test/CodeGenCXX/mangle-ms-abi-examples.cpp8
-rw-r--r--test/CodeGenCXX/mangle-ms-arg-qualifiers.cpp24
-rw-r--r--test/CodeGenCXX/mangle-ms-back-references-pr13207.cpp2
-rw-r--r--test/CodeGenCXX/mangle-ms-back-references.cpp2
-rw-r--r--test/CodeGenCXX/mangle-ms-cxx11.cpp132
-rw-r--r--test/CodeGenCXX/mangle-ms-cxx14.cpp40
-rw-r--r--test/CodeGenCXX/mangle-ms-return-qualifiers.cpp8
-rw-r--r--test/CodeGenCXX/mangle-ms-string-literals.cpp721
-rw-r--r--test/CodeGenCXX/mangle-ms-template-callback.cpp19
-rw-r--r--test/CodeGenCXX/mangle-ms-templates-memptrs-2.cpp45
-rw-r--r--test/CodeGenCXX/mangle-ms-templates-memptrs.cpp143
-rw-r--r--test/CodeGenCXX/mangle-ms-templates.cpp18
-rw-r--r--test/CodeGenCXX/mangle-ms-vector-types.cpp2
-rw-r--r--test/CodeGenCXX/mangle-ms.cpp19
-rw-r--r--test/CodeGenCXX/mangle-neon-vectors.cpp43
-rw-r--r--test/CodeGenCXX/mangle-nullptr-arg.cpp2
-rw-r--r--test/CodeGenCXX/mangle-std-externc.cpp4
-rw-r--r--test/CodeGenCXX/mangle-subst-std.cpp2
-rw-r--r--test/CodeGenCXX/mangle-template.cpp30
-rw-r--r--test/CodeGenCXX/mangle-windows.cpp4
-rw-r--r--test/CodeGenCXX/mangle.cpp52
-rw-r--r--test/CodeGenCXX/member-alignment.cpp2
-rw-r--r--test/CodeGenCXX/member-function-pointer-calls.cpp5
-rw-r--r--test/CodeGenCXX/member-init-anon-union.cpp34
-rw-r--r--test/CodeGenCXX/member-templates.cpp2
-rw-r--r--test/CodeGenCXX/microsoft-abi-alignment-fail.cpp8
-rw-r--r--test/CodeGenCXX/microsoft-abi-arg-order.cpp74
-rw-r--r--test/CodeGenCXX/microsoft-abi-array-cookies.cpp2
-rw-r--r--test/CodeGenCXX/microsoft-abi-byval-sret.cpp29
-rw-r--r--test/CodeGenCXX/microsoft-abi-byval-vararg.cpp52
-rw-r--r--test/CodeGenCXX/microsoft-abi-cdecl-method-sret.cpp44
-rw-r--r--test/CodeGenCXX/microsoft-abi-constexpr-vs-inheritance.cpp2
-rw-r--r--test/CodeGenCXX/microsoft-abi-default-cc.cpp4
-rw-r--r--test/CodeGenCXX/microsoft-abi-dynamic-cast.cpp130
-rw-r--r--test/CodeGenCXX/microsoft-abi-exceptions.cpp65
-rwxr-xr-xtest/CodeGenCXX/microsoft-abi-member-pointers.cpp180
-rw-r--r--test/CodeGenCXX/microsoft-abi-methods.cpp2
-rw-r--r--test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp2
-rwxr-xr-xtest/CodeGenCXX/microsoft-abi-non-virtual-base-ordering.cpp10
-rw-r--r--test/CodeGenCXX/microsoft-abi-nontrivial-covariant-thunk.cpp24
-rw-r--r--test/CodeGenCXX/microsoft-abi-rtti.cpp267
-rw-r--r--test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp158
-rw-r--r--test/CodeGenCXX/microsoft-abi-static-initializers.cpp123
-rw-r--r--test/CodeGenCXX/microsoft-abi-structors-alias.cpp21
-rw-r--r--test/CodeGenCXX/microsoft-abi-structors.cpp145
-rw-r--r--test/CodeGenCXX/microsoft-abi-thunks.cpp23
-rw-r--r--test/CodeGenCXX/microsoft-abi-try-throw.cpp23
-rw-r--r--test/CodeGenCXX/microsoft-abi-typeid.cpp52
-rw-r--r--test/CodeGenCXX/microsoft-abi-vbtables.cpp53
-rw-r--r--test/CodeGenCXX/microsoft-abi-vftables.cpp42
-rw-r--r--test/CodeGenCXX/microsoft-abi-virtual-inheritance-vtordisps.cpp10
-rw-r--r--test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp152
-rw-r--r--test/CodeGenCXX/microsoft-abi-virtual-member-pointers.cpp80
-rw-r--r--test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-no-thunks.cpp302
-rw-r--r--test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-pure-virtual.cpp35
-rw-r--r--test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-return-adjustment.cpp297
-rw-r--r--test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-this-adjustment.cpp140
-rw-r--r--test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-vdtors.cpp94
-rw-r--r--test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance.cpp579
-rw-r--r--test/CodeGenCXX/microsoft-abi-vtables-return-thunks.cpp106
-rw-r--r--test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp279
-rw-r--r--test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance-vtordisps.cpp411
-rw-r--r--test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp667
-rw-r--r--test/CodeGenCXX/microsoft-compatibility.cpp21
-rw-r--r--test/CodeGenCXX/microsoft-interface.cpp25
-rw-r--r--test/CodeGenCXX/microsoft-new.cpp78
-rw-r--r--test/CodeGenCXX/microsoft-no-rtti-data.cpp21
-rw-r--r--test/CodeGenCXX/microsoft-templ-uuidof.cpp37
-rw-r--r--test/CodeGenCXX/microsoft-uuidof.cpp6
-rw-r--r--test/CodeGenCXX/mingw-new-abi.cpp13
-rw-r--r--test/CodeGenCXX/mips-size_t-ptrdiff_t.cpp49
-rw-r--r--test/CodeGenCXX/ms-integer-static-data-members-exported.cpp22
-rw-r--r--test/CodeGenCXX/ms-integer-static-data-members.cpp8
-rw-r--r--test/CodeGenCXX/ms_wide_predefined_expr.cpp2
-rw-r--r--test/CodeGenCXX/new-array-init.cpp19
-rw-r--r--test/CodeGenCXX/new.cpp17
-rw-r--r--test/CodeGenCXX/no-elide-constructors.cpp35
-rw-r--r--test/CodeGenCXX/noinline-template.cpp4
-rw-r--r--test/CodeGenCXX/nrvo.cpp50
-rw-r--r--test/CodeGenCXX/pod-member-memcpys.cpp52
-rw-r--r--test/CodeGenCXX/pointers-to-data-members.cpp2
-rw-r--r--test/CodeGenCXX/poly-unsigned.cpp20
-rw-r--r--test/CodeGenCXX/pr11797.cpp2
-rw-r--r--test/CodeGenCXX/pr12104.cpp6
-rw-r--r--test/CodeGenCXX/pr13396.cpp4
-rw-r--r--test/CodeGenCXX/pr18661.cpp14
-rw-r--r--test/CodeGenCXX/pr18962.cpp32
-rw-r--r--test/CodeGenCXX/pr9965.cpp2
-rw-r--r--test/CodeGenCXX/pragma-init_seg.cpp72
-rw-r--r--test/CodeGenCXX/pragma-pack-3.cpp18
-rw-r--r--test/CodeGenCXX/pragma-weak.cpp4
-rw-r--r--test/CodeGenCXX/predefined-expr.cpp12
-rw-r--r--test/CodeGenCXX/ptr-to-member-function.cpp17
-rw-r--r--test/CodeGenCXX/reference-cast.cpp18
-rw-r--r--test/CodeGenCXX/reference-field.cpp4
-rw-r--r--test/CodeGenCXX/reference-init.cpp2
-rw-r--r--test/CodeGenCXX/references.cpp4
-rw-r--r--test/CodeGenCXX/return.cpp4
-rw-r--r--test/CodeGenCXX/rtti-fundamental.cpp125
-rw-r--r--test/CodeGenCXX/rtti-linkage.cpp113
-rw-r--r--test/CodeGenCXX/rtti-visibility.cpp12
-rw-r--r--test/CodeGenCXX/runtimecc.cpp2
-rw-r--r--test/CodeGenCXX/rvalue-references.cpp16
-rw-r--r--test/CodeGenCXX/scoped-enums.cpp2
-rw-r--r--test/CodeGenCXX/sparcv9-abi.cpp26
-rw-r--r--test/CodeGenCXX/specialized-static-data-mem-init.cpp6
-rw-r--r--test/CodeGenCXX/split-stacks.cpp33
-rw-r--r--test/CodeGenCXX/static-init-3.cpp4
-rw-r--r--test/CodeGenCXX/static-init.cpp12
-rw-r--r--test/CodeGenCXX/static-member-variable-explicit-specialization.cpp20
-rw-r--r--test/CodeGenCXX/stmtexpr.cpp2
-rw-r--r--test/CodeGenCXX/template-dependent-bind-temporary.cpp2
-rw-r--r--test/CodeGenCXX/template-inner-struct-visibility-hidden.cpp6
-rw-r--r--test/CodeGenCXX/template-instantiation.cpp28
-rw-r--r--test/CodeGenCXX/temporaries.cpp87
-rw-r--r--test/CodeGenCXX/throw-expression-dtor.cpp2
-rw-r--r--test/CodeGenCXX/throw-expressions.cpp45
-rw-r--r--test/CodeGenCXX/thunk-use-after-free.cpp2
-rw-r--r--test/CodeGenCXX/thunks.cpp9
-rw-r--r--test/CodeGenCXX/tls-init-funcs.cpp26
-rw-r--r--test/CodeGenCXX/trivial-constructor-init.cpp2
-rw-r--r--test/CodeGenCXX/type-traits.cpp (renamed from test/CodeGenCXX/unary-type-trait.cpp)2
-rw-r--r--test/CodeGenCXX/type_visibility.cpp36
-rw-r--r--test/CodeGenCXX/typeid-should-throw.cpp82
-rw-r--r--test/CodeGenCXX/uncopyable-args.cpp206
-rw-r--r--test/CodeGenCXX/value-init.cpp53
-rw-r--r--test/CodeGenCXX/vararg-non-pod.cpp2
-rw-r--r--test/CodeGenCXX/virt-dtor-gen.cpp4
-rw-r--r--test/CodeGenCXX/virt-dtor-key.cpp4
-rw-r--r--test/CodeGenCXX/virt-template-vtable.cpp2
-rw-r--r--test/CodeGenCXX/virtual-base-cast.cpp2
-rw-r--r--test/CodeGenCXX/virtual-base-ctor.cpp2
-rw-r--r--test/CodeGenCXX/virtual-base-destructor-call.cpp2
-rw-r--r--test/CodeGenCXX/virtual-bases.cpp4
-rw-r--r--test/CodeGenCXX/virtual-destructor-calls.cpp10
-rw-r--r--test/CodeGenCXX/virtual-destructor-synthesis.cpp2
-rw-r--r--test/CodeGenCXX/virtual-function-calls.cpp6
-rw-r--r--test/CodeGenCXX/virtual-implicit-copy-assignment.cpp2
-rw-r--r--test/CodeGenCXX/virtual-implicit-move-assignment.cpp2
-rw-r--r--test/CodeGenCXX/virtual-inherited-destructor.cpp2
-rw-r--r--test/CodeGenCXX/virtual-pseudo-destructor-call.cpp2
-rw-r--r--test/CodeGenCXX/visibility-hidden-extern-templates.cpp10
-rw-r--r--test/CodeGenCXX/visibility-ms-compat.cpp12
-rw-r--r--test/CodeGenCXX/vla.cpp2
-rw-r--r--test/CodeGenCXX/volatile-1.cpp6
-rw-r--r--test/CodeGenCXX/volatile.cpp2
-rw-r--r--test/CodeGenCXX/vtable-available-externally.cpp2
-rw-r--r--test/CodeGenCXX/vtable-cast-crash.cpp2
-rw-r--r--test/CodeGenCXX/vtable-key-function-arm.cpp26
-rw-r--r--test/CodeGenCXX/vtable-key-function-ios.cpp18
-rw-r--r--test/CodeGenCXX/vtable-layout-abi-examples.cpp2
-rw-r--r--test/CodeGenCXX/vtable-linkage.cpp32
-rw-r--r--test/CodeGenCXX/weak-extern-typeinfo.cpp16
-rw-r--r--test/CodeGenCXX/weak-external.cpp2
-rw-r--r--test/CodeGenCXX/windows-itanium-exceptions.cpp47
336 files changed, 11185 insertions, 2358 deletions
diff --git a/test/CodeGenCXX/2003-11-27-MultipleInheritanceThunk.cpp b/test/CodeGenCXX/2003-11-27-MultipleInheritanceThunk.cpp
index 3e5339732767..a70f6e01280e 100644
--- a/test/CodeGenCXX/2003-11-27-MultipleInheritanceThunk.cpp
+++ b/test/CodeGenCXX/2003-11-27-MultipleInheritanceThunk.cpp
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -emit-llvm %s -o -
+// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm %s -o -
+// RUN: %clang_cc1 -triple %ms_abi_triple -fno-rtti -emit-llvm %s -o -
struct CallSite {
diff --git a/test/CodeGenCXX/2004-03-08-ReinterpretCastCopy.cpp b/test/CodeGenCXX/2004-03-08-ReinterpretCastCopy.cpp
index a6e2e30dd59b..a4411fc46832 100644
--- a/test/CodeGenCXX/2004-03-08-ReinterpretCastCopy.cpp
+++ b/test/CodeGenCXX/2004-03-08-ReinterpretCastCopy.cpp
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -emit-llvm %s -o -
+// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm %s -o -
+// RUN: %clang_cc1 -triple %ms_abi_triple -fno-rtti -emit-llvm %s -o -
struct A {
virtual void Method() = 0;
diff --git a/test/CodeGenCXX/2004-03-09-UnmangledBuiltinMethods.cpp b/test/CodeGenCXX/2004-03-09-UnmangledBuiltinMethods.cpp
index 5d8c8b004b79..03c4ed623fdf 100644
--- a/test/CodeGenCXX/2004-03-09-UnmangledBuiltinMethods.cpp
+++ b/test/CodeGenCXX/2004-03-09-UnmangledBuiltinMethods.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -o - %s | FileCheck %s
// CHECK: _ZN11AccessFlags6strlenEv
struct AccessFlags {
diff --git a/test/CodeGenCXX/2006-09-12-OpaqueStructCrash.cpp b/test/CodeGenCXX/2006-09-12-OpaqueStructCrash.cpp
index bd270dd60238..c5a2d5abc3ef 100644
--- a/test/CodeGenCXX/2006-09-12-OpaqueStructCrash.cpp
+++ b/test/CodeGenCXX/2006-09-12-OpaqueStructCrash.cpp
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -emit-llvm -o - %s
+// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -o - %s
+// RUN: %clang_cc1 -triple %ms_abi_triple -fno-rtti -emit-llvm -o - %s
struct A {
virtual ~A();
diff --git a/test/CodeGenCXX/2010-05-11-alwaysinlineinstantiation.cpp b/test/CodeGenCXX/2010-05-11-alwaysinlineinstantiation.cpp
index fe0740b7cb5c..bf00c0f36bfe 100644
--- a/test/CodeGenCXX/2010-05-11-alwaysinlineinstantiation.cpp
+++ b/test/CodeGenCXX/2010-05-11-alwaysinlineinstantiation.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple %s -o - | FileCheck %s
// CHECK-NOT: ZN12basic_stringIcEC1Ev
// CHECK: ZN12basic_stringIcED1Ev
diff --git a/test/CodeGenCXX/debug-info-class-limited.cpp b/test/CodeGenCXX/Inputs/debug-info-class-limited.cpp
index a4b9f46ec653..31a026101bb6 100644
--- a/test/CodeGenCXX/debug-info-class-limited.cpp
+++ b/test/CodeGenCXX/Inputs/debug-info-class-limited.cpp
@@ -1,16 +1,13 @@
-// 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 {
+// CHECK-DAG: [ DW_TAG_structure_type ] [PR16214] [line [[@LINE+1]], {{.*}} [def]
+struct PR16214 {
int i;
};
-typedef foo bar;
+typedef PR16214 bar;
bar *a;
bar b;
-}
namespace PR14467 {
// CHECK-DAG: [ DW_TAG_structure_type ] [foo] [line [[@LINE+1]], {{.*}} [def]
@@ -24,7 +21,7 @@ foo *bar(foo *a) {
}
namespace test1 {
-// CHECK-DAG: [ DW_TAG_structure_type ] [foo] [line [[@LINE+1]], {{.*}} [decl]
+// CHECK-DAG: [ DW_TAG_structure_type ] [foo] [line [[@LINE+1]], {{.*}} [def]
struct foo {
};
diff --git a/test/CodeGenCXX/PR19955.cpp b/test/CodeGenCXX/PR19955.cpp
new file mode 100644
index 000000000000..9e101550b419
--- /dev/null
+++ b/test/CodeGenCXX/PR19955.cpp
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -triple i686-windows-msvc -fno-rtti -emit-llvm -std=c++1y -O0 -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-windows-msvc -fno-rtti -emit-llvm -std=c++1y -O0 -o - %s | FileCheck %s --check-prefix X64
+
+extern int __declspec(dllimport) var;
+extern void __declspec(dllimport) fun();
+
+extern int *varp;
+int *varp = &var;
+// CHECK-DAG: @"\01?varp@@3PAHA" = global i32* null
+// X64-DAG: @"\01?varp@@3PEAHEA" = global i32* null
+
+extern void (*funp)();
+void (*funp)() = &fun;
+// CHECK-DAG: @"\01?funp@@3P6AXXZA" = global void ()* null
+// X64-DAG: @"\01?funp@@3P6AXXZEA" = global void ()* null
+
+// CHECK-LABEL: @"\01??__Evarp@@YAXXZ"
+// CHECK-DAG: store i32* @"\01?var@@3HA", i32** @"\01?varp@@3PAHA"
+
+// X64-LABEL: @"\01??__Evarp@@YAXXZ"
+// X64-DAG: store i32* @"\01?var@@3HA", i32** @"\01?varp@@3PEAHEA"
+
+// CHECK-LABEL: @"\01??__Efunp@@YAXXZ"()
+// CHECK-DAG: store void ()* @"\01?fun@@YAXXZ", void ()** @"\01?funp@@3P6AXXZA"
+
+// X64-LABEL: @"\01??__Efunp@@YAXXZ"()
+// X64-DAG: store void ()* @"\01?fun@@YAXXZ", void ()** @"\01?funp@@3P6AXXZEA"
diff --git a/test/CodeGenCXX/PR20038.cpp b/test/CodeGenCXX/PR20038.cpp
new file mode 100644
index 000000000000..c24685d696b6
--- /dev/null
+++ b/test/CodeGenCXX/PR20038.cpp
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -triple %itanium_abi_triple -g -emit-llvm %s -o - | FileCheck %s
+
+struct C {
+ ~C();
+};
+extern bool b;
+// CHECK: call {{.*}}, !dbg [[DTOR_CALL1_LOC:![0-9]*]]
+// CHECK: call {{.*}}, !dbg [[DTOR_CALL2_LOC:![0-9]*]]
+// CHECK: [[FUN1:.*]] = {{.*}}; [ DW_TAG_subprogram ] {{.*}} [def] [fun1]
+// CHECK: [[FUN2:.*]] = {{.*}}; [ DW_TAG_subprogram ] {{.*}} [def] [fun2]
+// CHECK: [[DTOR_CALL1_LOC]] = metadata !{i32 [[@LINE+2]], i32 0, metadata [[FUN1_BLOCK:.*]], null}
+// CHECK: [[FUN1_BLOCK]] = metadata !{{{[^,]*}}, {{[^,]*}}, metadata [[FUN1]],
+void fun1() { b && (C(), 1); }
+// CHECK: [[DTOR_CALL2_LOC]] = metadata !{i32 [[@LINE+2]], i32 0, metadata [[FUN2_BLOCK1:.*]], null}
+// CHECK: [[FUN2_BLOCK1]] = metadata !{{{[^,]*}}, {{[^,]*}}, metadata [[FUN2]],
+bool fun2() { return (C(), b) && 0; }
diff --git a/test/CodeGenCXX/PR5050-constructor-conversion.cpp b/test/CodeGenCXX/PR5050-constructor-conversion.cpp
index a1b05ebc70b1..ce6cc0e846e2 100644
--- a/test/CodeGenCXX/PR5050-constructor-conversion.cpp
+++ b/test/CodeGenCXX/PR5050-constructor-conversion.cpp
@@ -1,8 +1,7 @@
-// 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 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 CHECK-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
struct A { A(const A&, int i1 = 1); };
@@ -12,8 +11,4 @@ A f(const B &b) {
return b;
}
-// CHECK-LP64: callq __ZN1AC1ERKS_i
-
-// CHECK-LP32: calll L__ZN1AC1ERKS_i
-
-
+// CHECK: call void @_ZN1AC1ERKS_i
diff --git a/test/CodeGenCXX/PR5093-static-member-function.cpp b/test/CodeGenCXX/PR5093-static-member-function.cpp
index ceab8528e8bc..d61a87ac16dc 100644
--- a/test/CodeGenCXX/PR5093-static-member-function.cpp
+++ b/test/CodeGenCXX/PR5093-static-member-function.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -emit-llvm -triple %itanium_abi_triple -o - | FileCheck %s
struct a {
static void f();
};
diff --git a/test/CodeGenCXX/PR5863-unreachable-block.cpp b/test/CodeGenCXX/PR5863-unreachable-block.cpp
index 3f32d7570435..50d17314cb49 100644
--- a/test/CodeGenCXX/PR5863-unreachable-block.cpp
+++ b/test/CodeGenCXX/PR5863-unreachable-block.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -emit-llvm-only %s
+// RUN: %clang_cc1 -triple %itanium_abi_triple -fcxx-exceptions -fexceptions -emit-llvm-only %s
// PR5863
class E { };
diff --git a/test/CodeGenCXX/aarch64-arguments.cpp b/test/CodeGenCXX/aarch64-arguments.cpp
index f56ad0bbdcf3..013051ccaea3 100644
--- a/test/CodeGenCXX/aarch64-arguments.cpp
+++ b/test/CodeGenCXX/aarch64-arguments.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple aarch64-none-linux -emit-llvm -w -o - %s | FileCheck -check-prefix=PCS %s
+// RUN: %clang_cc1 -triple arm64-none-linux -emit-llvm -w -o - %s | FileCheck -check-prefix=PCS %s
// PCS: define void @{{.*}}(i8 %a
struct s0 {};
diff --git a/test/CodeGenCXX/aarch64-cxxabi.cpp b/test/CodeGenCXX/aarch64-cxxabi.cpp
index 04d9493ae6b0..6c08ff2fc3ed 100644
--- a/test/CodeGenCXX/aarch64-cxxabi.cpp
+++ b/test/CodeGenCXX/aarch64-cxxabi.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -emit-llvm -w -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple arm64-none-linux-gnu -emit-llvm -w -o - %s | FileCheck %s
// Check differences between the generic Itanium ABI, the AArch32 version and
// the AArch64 version.
@@ -40,8 +40,8 @@ public:
void guard_variables(int a) {
static Guarded mine(a);
-// CHECK: [[GUARDBIT:%[0-9]+]] = and i64 {{%[0-9]+}}, 1
-// CHECK: icmp eq i64 [[GUARDBIT]], 0
+// CHECK: [[GUARDBIT:%[0-9]+]] = and i8 {{%[0-9]+}}, 1
+// CHECK: icmp eq i8 [[GUARDBIT]], 0
// As guards are 64-bit, these helpers should take 64-bit pointers.
// CHECK: call i32 @__cxa_guard_acquire(i64*
diff --git a/test/CodeGenCXX/aarch64-mangle-neon-vectors.cpp b/test/CodeGenCXX/aarch64-mangle-neon-vectors.cpp
index 2514704f1d88..3b4a309327fe 100644
--- a/test/CodeGenCXX/aarch64-mangle-neon-vectors.cpp
+++ b/test/CodeGenCXX/aarch64-mangle-neon-vectors.cpp
@@ -1,12 +1,11 @@
-// REQUIRES: aarch64-registered-target
-// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +neon %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -triple arm64-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 signed long int64_t;
+typedef unsigned long uint64_t;
typedef unsigned char poly8_t;
typedef unsigned short poly16_t;
typedef __fp16 float16_t;
diff --git a/test/CodeGenCXX/aarch64-neon.cpp b/test/CodeGenCXX/aarch64-neon.cpp
index 5d2a00bebe73..d6f6b0e894fb 100644
--- a/test/CodeGenCXX/aarch64-neon.cpp
+++ b/test/CodeGenCXX/aarch64-neon.cpp
@@ -1,13 +1,13 @@
// REQUIRES: aarch64-registered-target
-// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +neon \
+// RUN: %clang_cc1 -triple arm64-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.
+// Test whether arm_neon.h works as expected in C++.
#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}}]
+ // CHECK: {{ld1 { v[0-9]+.1d }|ldr d[0-9]+}}, [{{x[0-9]+|sp}}]
}
diff --git a/test/CodeGenCXX/abstract-class-ctors-dtors.cpp b/test/CodeGenCXX/abstract-class-ctors-dtors.cpp
index 793bbde05021..f36922413d83 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-LABEL: define void @_ZN1AC1Ev
+// CHECK-NOT: define void @_ZN1AC1Ev
// CHECK-LABEL: define void @_ZN1AC2Ev
-// CHECK-LABEL: define void @_ZN1AD1Ev
// CHECK-LABEL: define void @_ZN1AD2Ev
+// CHECK-LABEL: define void @_ZN1AD1Ev
A::A() { }
A::~A() { }
diff --git a/test/CodeGenCXX/address-of-fntemplate.cpp b/test/CodeGenCXX/address-of-fntemplate.cpp
index 71794520f0a0..4ff597acb304 100644
--- a/test/CodeGenCXX/address-of-fntemplate.cpp
+++ b/test/CodeGenCXX/address-of-fntemplate.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -emit-llvm -triple %itanium_abi_triple -o - | FileCheck %s
template <typename T> void f(T) {}
template <typename T> void f() { }
diff --git a/test/CodeGenCXX/address-space-ref.cpp b/test/CodeGenCXX/address-space-ref.cpp
new file mode 100644
index 000000000000..de6bddca66a7
--- /dev/null
+++ b/test/CodeGenCXX/address-space-ref.cpp
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 %s -std=c++11 -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s
+
+// For a reference to a complete type, output the dereferenceable attribute (in
+// any address space).
+
+typedef int a __attribute__((address_space(1)));
+
+a & foo(a &x, a & y) {
+ return x;
+}
+
+// CHECK: define dereferenceable(4) i32 addrspace(1)* @_Z3fooRU3AS1iS0_(i32 addrspace(1)* dereferenceable(4) %x, i32 addrspace(1)* dereferenceable(4) %y)
+
+// For a reference to an incomplete type in an alternate address space, output
+// neither dereferenceable nor nonnull.
+
+class bc;
+typedef bc b __attribute__((address_space(1)));
+
+b & bar(b &x, b & y) {
+ return x;
+}
+
+// CHECK: define %class.bc addrspace(1)* @_Z3barRU3AS12bcS1_(%class.bc addrspace(1)* %x, %class.bc addrspace(1)* %y)
+
+// For a reference to an incomplete type in addrspace(0), output nonnull.
+
+bc & bar2(bc &x, bc & y) {
+ return x;
+}
+
+// CHECK: define nonnull %class.bc* @_Z4bar2R2bcS0_(%class.bc* nonnull %x, %class.bc* nonnull %y)
+
+
diff --git a/test/CodeGenCXX/apple-kext.cpp b/test/CodeGenCXX/apple-kext.cpp
index 03506a8aacf5..0d7ccfb3be1a 100644
--- a/test/CodeGenCXX/apple-kext.cpp
+++ b/test/CodeGenCXX/apple-kext.cpp
@@ -1,8 +1,8 @@
// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fno-use-cxa-atexit -fapple-kext -emit-llvm -o - %s | FileCheck %s
// CHECK: @_ZN5test01aE = global [[A:%.*]] zeroinitializer
-// CHECK: @llvm.global_ctors = appending global {{.*}} { i32 65535, void ()* [[CTOR0:@.*]] }
-// CHECK: @llvm.global_dtors = appending global {{.*}} { i32 65535, void ()* [[DTOR0:@.*]] }
+// CHECK: @llvm.global_ctors = appending global {{.*}} { i32 65535, void ()* [[CTOR0:@.*]], i8* null }
+// CHECK: @llvm.global_dtors = appending global {{.*}} { i32 65535, void ()* [[DTOR0:@.*]], i8* null }
// rdar://11241230
namespace test0 {
diff --git a/test/CodeGenCXX/arm.cpp b/test/CodeGenCXX/arm.cpp
index 2fb9c49bb707..b6629f444e3f 100644
--- a/test/CodeGenCXX/arm.cpp
+++ b/test/CodeGenCXX/arm.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -triple=thumbv7-apple-ios3.0 -fno-use-cxa-atexit -target-abi apcs-gnu -emit-llvm -o - -fexceptions | FileCheck %s
+// RUN: %clang_cc1 %s -triple=thumbv7-apple-ios6.0 -fno-use-cxa-atexit -target-abi apcs-gnu -emit-llvm -o - -fexceptions | FileCheck %s
// CHECK: @_ZZN5test74testEvE1x = internal global i32 0, align 4
// CHECK: @_ZGVZN5test74testEvE1x = internal global i32 0
@@ -28,6 +28,7 @@ bar baz;
// CHECK: call [[BAR:%.*]]* @_ZN3barC1Ev(
// CHECK-NEXT: call i32 @atexit(void ()* @__dtor_baz)
+// CHECK-NOT: @_GLOBAL__D_a()
// CHECK-LABEL: define internal void @__dtor_baz()
// CHECK: call [[BAR]]* @_ZN3barD1Ev([[BAR]]* @baz)
@@ -292,9 +293,9 @@ namespace test7 {
// CHECK-LABEL: define void @_ZN5test74testEv()
void test() {
- // CHECK: [[T0:%.*]] = load i32* @_ZGVZN5test74testEvE1x
- // CHECK-NEXT: [[T1:%.*]] = and i32 [[T0]], 1
- // CHECK-NEXT: [[T2:%.*]] = icmp eq i32 [[T1]], 0
+ // CHECK: [[T0:%.*]] = load atomic i8* bitcast (i32* @_ZGVZN5test74testEvE1x to i8*) acquire, align 1
+ // CHECK-NEXT: [[T1:%.*]] = and i8 [[T0]], 1
+ // CHECK-NEXT: [[T2:%.*]] = icmp eq i8 [[T1]], 0
// CHECK-NEXT: br i1 [[T2]]
// -> fallthrough, end
// CHECK: [[T3:%.*]] = call i32 @__cxa_guard_acquire(i32* @_ZGVZN5test74testEvE1x)
@@ -327,9 +328,9 @@ namespace test8 {
// CHECK-LABEL: define void @_ZN5test84testEv()
void test() {
- // CHECK: [[T0:%.*]] = load i32* @_ZGVZN5test84testEvE1x
- // CHECK-NEXT: [[T1:%.*]] = and i32 [[T0]], 1
- // CHECK-NEXT: [[T2:%.*]] = icmp eq i32 [[T1]], 0
+ // CHECK: [[T0:%.*]] = load atomic i8* bitcast (i32* @_ZGVZN5test84testEvE1x to i8*) acquire, align 1
+ // CHECK-NEXT: [[T1:%.*]] = and i8 [[T0]], 1
+ // CHECK-NEXT: [[T2:%.*]] = icmp eq i8 [[T1]], 0
// CHECK-NEXT: br i1 [[T2]]
// -> fallthrough, end
// CHECK: [[T3:%.*]] = call i32 @__cxa_guard_acquire(i32* @_ZGVZN5test84testEvE1x)
@@ -416,6 +417,3 @@ namespace test9 {
// CHECK-LABEL: define linkonce_odr void @_ZTv0_n12_N5test21CD0Ev(
// CHECK: call void @_ZN5test21CD0Ev(
// CHECK: ret void
-
-// CH_ECK: @_GLOBAL__D_a()
-// CH_ECK: call %class.bar* @_ZN3barD1Ev(%class.bar* @baz)
diff --git a/test/CodeGenCXX/arm64-constructor-return.cpp b/test/CodeGenCXX/arm64-constructor-return.cpp
new file mode 100644
index 000000000000..0d5b3b38258c
--- /dev/null
+++ b/test/CodeGenCXX/arm64-constructor-return.cpp
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 %s -triple=arm64-apple-ios7.0.0 -emit-llvm -o - | FileCheck %s
+// rdar://12162905
+
+struct S {
+ S();
+ int iField;
+};
+
+S::S() {
+ iField = 1;
+};
+
+// CHECK: %struct.S* @_ZN1SC2Ev(%struct.S* returned %this)
+
+// CHECK: %struct.S* @_ZN1SC1Ev(%struct.S* returned %this)
+// CHECK: [[THISADDR:%[a-zA-z0-9.]+]] = alloca %struct.S*
+// CHECK: store %struct.S* %this, %struct.S** [[THISADDR]]
+// CHECK: [[THIS1:%.*]] = load %struct.S** [[THISADDR]]
+// CHECK: ret %struct.S* [[THIS1]]
diff --git a/test/CodeGenCXX/arm64-darwinpcs.cpp b/test/CodeGenCXX/arm64-darwinpcs.cpp
new file mode 100644
index 000000000000..0a0ec3af49cf
--- /dev/null
+++ b/test/CodeGenCXX/arm64-darwinpcs.cpp
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -triple arm64-linux-gnu -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple arm64-linux-gnu -emit-llvm -o - %s -target-abi darwinpcs | FileCheck %s --check-prefix=CHECK-DARWIN
+
+void test_extensions(bool a, char b, short c) {}
+// CHECK: define void @_Z15test_extensionsbcs(i1 %a, i8 %b, i16 %c)
+// CHECK-DARWIN: define void @_Z15test_extensionsbcs(i1 zeroext %a, i8 signext %b, i16 signext %c)
+
+struct Empty {};
+void test_empty(Empty e) {}
+// CHECK: define void @_Z10test_empty5Empty(i8
+// CHECK-DARWIN: define void @_Z10test_empty5Empty()
+
+struct HFA {
+ float a[3];
+};
diff --git a/test/CodeGenCXX/arm64-empty-struct.cpp b/test/CodeGenCXX/arm64-empty-struct.cpp
new file mode 100644
index 000000000000..6fa4e95295be
--- /dev/null
+++ b/test/CodeGenCXX/arm64-empty-struct.cpp
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -triple arm64-apple-ios -target-abi darwinpcs -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: va_arg i8** {{%[a-zA-Z0-9._]+}}, i32
+
+ __builtin_va_end(l);
+ return i;
+}
diff --git a/test/CodeGenCXX/arm64.cpp b/test/CodeGenCXX/arm64.cpp
new file mode 100644
index 000000000000..d0d4f4f70efc
--- /dev/null
+++ b/test/CodeGenCXX/arm64.cpp
@@ -0,0 +1,88 @@
+// RUN: %clang_cc1 %s -triple=arm64-apple-ios -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -triple=arm64-apple-ios -emit-llvm -o - | FileCheck -check-prefix=CHECK-GLOBALS %s
+
+// __cxa_guard_acquire argument is 64-bit
+// rdar://11540122
+struct A {
+ A();
+};
+
+void f() {
+ // CHECK: call i32 @__cxa_guard_acquire(i64*
+ static A a;
+}
+
+// ARM64 uses the C++11 definition of POD.
+// rdar://12650514
+namespace test1 {
+ // This class is POD in C++11 and cannot have objects allocated in
+ // its tail-padding.
+ struct ABase {};
+ struct A : ABase {
+ int x;
+ char c;
+ };
+
+ struct B : A {
+ char d;
+ };
+
+ int test() {
+ return sizeof(B);
+ }
+ // CHECK: define i32 @_ZN5test14testEv()
+ // CHECK: ret i32 12
+}
+
+namespace std {
+ class type_info;
+}
+
+// ARM64 uses string comparisons for what would otherwise be
+// default-visibility weak RTTI. rdar://12650568
+namespace test2 {
+ struct A {
+ virtual void foo();
+ };
+ void A::foo() {}
+ // Tested below because these globals get kindof oddly rearranged.
+
+ struct __attribute__((visibility("hidden"))) B {};
+ const std::type_info &b0 = typeid(B);
+ // CHECK-GLOBALS: @_ZTSN5test21BE = linkonce_odr hidden constant
+ // CHECK-GLOBALS: @_ZTIN5test21BE = linkonce_odr hidden constant { {{.*}}, i8* getelementptr inbounds ([11 x i8]* @_ZTSN5test21BE, i32 0, i32 0) }
+
+ const std::type_info &b1 = typeid(B*);
+ // CHECK-GLOBALS: @_ZTSPN5test21BE = linkonce_odr hidden constant
+ // CHECK-GLOBALS: @_ZTIPN5test21BE = linkonce_odr hidden constant { {{.*}}, i8* getelementptr inbounds ([12 x i8]* @_ZTSPN5test21BE, i32 0, i32 0), i32 0, i8* bitcast
+
+ struct C {};
+ const std::type_info &c0 = typeid(C);
+ // CHECK-GLOBALS: @_ZTSN5test21CE = linkonce_odr hidden constant
+ // CHECK-GLOBALS: @_ZTIN5test21CE = linkonce_odr hidden constant { {{.*}}, i8* inttoptr (i64 add (i64 ptrtoint ([11 x i8]* @_ZTSN5test21CE to i64), i64 -9223372036854775808) to i8*) }
+
+ const std::type_info &c1 = typeid(C*);
+ // CHECK-GLOBALS: @_ZTSPN5test21CE = linkonce_odr hidden constant
+ // CHECK-GLOBALS: @_ZTIPN5test21CE = linkonce_odr hidden constant { {{.*}}, i8* inttoptr (i64 add (i64 ptrtoint ([12 x i8]* @_ZTSPN5test21CE to i64), i64 -9223372036854775808) to i8*), i32 0, i8* bitcast
+
+ // This class is explicitly-instantiated, but that instantiation
+ // doesn't guarantee to emit RTTI, so we can still demote the visibility.
+ template <class T> class D {};
+ template class D<int>;
+ const std::type_info &d0 = typeid(D<int>);
+ // CHECK-GLOBALS: @_ZTSN5test21DIiEE = linkonce_odr hidden constant
+ // CHECK-GLOBALS: @_ZTIN5test21DIiEE = linkonce_odr hidden constant { {{.*}}, i8* inttoptr (i64 add (i64 ptrtoint ([14 x i8]* @_ZTSN5test21DIiEE to i64), i64 -9223372036854775808) to i8*) }
+
+ // This class is explicitly-instantiated and *does* guarantee to
+ // emit RTTI, so we're stuck with having to use default visibility.
+ template <class T> class E {
+ virtual void foo() {}
+ };
+ template class E<int>;
+ // CHECK-GLOBALS: @_ZTSN5test21EIiEE = weak_odr constant [14 x i8]
+ // CHECK-GLOBALS: @_ZTIN5test21EIiEE = weak_odr constant { {{.*}}, i8* inttoptr (i64 add (i64 ptrtoint ([14 x i8]* @_ZTSN5test21EIiEE to i64), i64 -9223372036854775808) to i8*) }
+
+ // CHECK-GLOBALS: @_ZTSN5test21AE = constant [11 x i8]
+ // CHECK-GLOBALS: @_ZTIN5test21AE = constant { {{.*}}, i8* getelementptr inbounds ([11 x i8]* @_ZTSN5test21AE, i32 0, i32 0) }
+
+}
diff --git a/test/CodeGenCXX/array-construction.cpp b/test/CodeGenCXX/array-construction.cpp
index 645ad1d787df..53b81f2d85ba 100644
--- a/test/CodeGenCXX/array-construction.cpp
+++ b/test/CodeGenCXX/array-construction.cpp
@@ -1,8 +1,7 @@
-// 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 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 CHECK-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(...);
@@ -31,7 +30,4 @@ int main() {
h, i, j, array[h][i][j].i, array[h][i][j].f);
}
-// CHECK-LP64: callq __ZN4xptoC1Ev
-
-// CHECK-LP32: calll L__ZN4xptoC1Ev
-
+// CHECK: call void @_ZN4xptoC1Ev
diff --git a/test/CodeGenCXX/array-operator-delete-call.cpp b/test/CodeGenCXX/array-operator-delete-call.cpp
index 8d6f50fdfab1..890b142c10f8 100644
--- a/test/CodeGenCXX/array-operator-delete-call.cpp
+++ b/test/CodeGenCXX/array-operator-delete-call.cpp
@@ -1,8 +1,7 @@
-// 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 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 CHECK-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(...);
@@ -58,7 +57,5 @@ int main()
}
COST c2;
-// CHECK-LP64: callq __ZdaPv
-
-// CHECK-LP32: calll L__ZdaPv
+// CHECK: call void @_ZdaPv
diff --git a/test/CodeGenCXX/atomicinit.cpp b/test/CodeGenCXX/atomicinit.cpp
index ee2e9e4cf244..f453194468dd 100644
--- a/test/CodeGenCXX/atomicinit.cpp
+++ b/test/CodeGenCXX/atomicinit.cpp
@@ -1,4 +1,10 @@
-// RUN: %clang_cc1 %s -emit-llvm -O1 -o - -triple=i686-apple-darwin9 | FileCheck %s
+// RUN: %clang_cc1 %s -emit-llvm -O1 -o - -triple=i686-apple-darwin9 -std=c++11 | FileCheck %s
+
+// CHECK-DAG: @_ZN7PR180978constant1aE = global {{.*}} { i16 1, i8 6, i8 undef }, align 4
+// CHECK-DAG: @_ZN7PR180978constant1bE = global {{.*}} { i16 2, i8 6, i8 undef }, align 4
+// CHECK-DAG: @_ZN7PR180978constant1cE = global {{.*}} { i16 3, i8 6, i8 undef }, align 4
+// CHECK-DAG: @_ZN7PR180978constant1yE = global {{.*}} { {{.*}} { i16 4, i8 6, i8 undef }, i32 5 }, align 4
+
struct A {
_Atomic(int) i;
A(int j);
@@ -46,3 +52,51 @@ struct AtomicBoolMember {
// CHECK-NEXT: ret void
AtomicBoolMember::AtomicBoolMember(bool b) : ab(b) { }
+namespace PR18097 {
+ namespace dynamic {
+ struct X {
+ X(int);
+ short n;
+ char c;
+ };
+
+ // CHECK-LABEL: define {{.*}} @__cxx_global_var_init
+ // CHECK: call void @_ZN7PR180977dynamic1XC1Ei({{.*}}* @_ZN7PR180977dynamic1aE, i32 1)
+ _Atomic(X) a = X(1);
+
+ // CHECK-LABEL: define {{.*}} @__cxx_global_var_init
+ // CHECK: call void @_ZN7PR180977dynamic1XC1Ei({{.*}}* @_ZN7PR180977dynamic1bE, i32 2)
+ _Atomic(X) b(X(2));
+
+ // CHECK-LABEL: define {{.*}} @__cxx_global_var_init
+ // CHECK: call void @_ZN7PR180977dynamic1XC1Ei({{.*}}* @_ZN7PR180977dynamic1cE, i32 3)
+ _Atomic(X) c{X(3)};
+
+ struct Y {
+ _Atomic(X) a;
+ _Atomic(int) b;
+ };
+ // CHECK-LABEL: define {{.*}} @__cxx_global_var_init
+ // CHECK: call void @_ZN7PR180977dynamic1XC1Ei({{.*}}* getelementptr inbounds ({{.*}}* @_ZN7PR180977dynamic1yE, i32 0, i32 0), i32 4)
+ // CHECK: store i32 5, i32* getelementptr inbounds ({{.*}}* @_ZN7PR180977dynamic1yE, i32 0, i32 1)
+ Y y = { X(4), 5 };
+ }
+
+ // CHECKs at top of file.
+ namespace constant {
+ struct X {
+ constexpr X(int n) : n(n) {}
+ short n;
+ char c = 6;
+ };
+ _Atomic(X) a = X(1);
+ _Atomic(X) b(X(2));
+ _Atomic(X) c{X(3)};
+
+ struct Y {
+ _Atomic(X) a;
+ _Atomic(int) b;
+ };
+ Y y = { X(4), 5 };
+ }
+}
diff --git a/test/CodeGenCXX/attr-cleanup.cpp b/test/CodeGenCXX/attr-cleanup.cpp
index ff15b03de57c..18a7798481e9 100644
--- a/test/CodeGenCXX/attr-cleanup.cpp
+++ b/test/CodeGenCXX/attr-cleanup.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -o - %s | FileCheck %s
namespace N {
void free(void *i) {}
diff --git a/test/CodeGenCXX/attr-used.cpp b/test/CodeGenCXX/attr-used.cpp
index 2c82184081b9..861734667357 100644
--- a/test/CodeGenCXX/attr-used.cpp
+++ b/test/CodeGenCXX/attr-used.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -o - %s | FileCheck %s
// <rdar://problem/8684363>: clang++ not respecting __attribute__((used)) on destructors
struct X0 {
@@ -7,3 +7,21 @@ struct X0 {
// CHECK: define linkonce_odr {{.*}} @_ZN2X0D1Ev
__attribute__((used)) ~X0() {}
};
+
+// PR19743: not emitting __attribute__((used)) inline methods in nested classes.
+struct X1 {
+ struct Nested {
+ // CHECK: define linkonce_odr {{.*}} @_ZN2X16Nested1fEv
+ void __attribute__((used)) f() {}
+ };
+};
+
+struct X2 {
+ // We must delay emission of bar() until foo() has had its body parsed,
+ // otherwise foo() would not be emitted.
+ void __attribute__((used)) bar() { foo(); }
+ void foo() { }
+
+ // CHECK: define linkonce_odr {{.*}} @_ZN2X23barEv
+ // CHECK: define linkonce_odr {{.*}} @_ZN2X23fooEv
+};
diff --git a/test/CodeGenCXX/bitfield-layout.cpp b/test/CodeGenCXX/bitfield-layout.cpp
index 646300a7d1cb..46f41111a1de 100644
--- a/test/CodeGenCXX/bitfield-layout.cpp
+++ b/test/CodeGenCXX/bitfield-layout.cpp
@@ -12,7 +12,7 @@ union Test2 {
int : 6;
} t2;
-// CHECK-LP64: %union.Test3 = type { [2 x i8] }
+// CHECK-LP64: %union.Test3 = type { i16 }
union Test3 {
int : 9;
} t3;
diff --git a/test/CodeGenCXX/bitfield.cpp b/test/CodeGenCXX/bitfield.cpp
index 2c454b0c072c..fafeffe1ed23 100644
--- a/test/CodeGenCXX/bitfield.cpp
+++ b/test/CodeGenCXX/bitfield.cpp
@@ -298,7 +298,7 @@ namespace N4 {
#endif
unsigned read(Base* s) {
// FIXME: We should widen this load as long as the function isn't being
- // instrumented by thread-sanitizer.
+ // instrumented by ThreadSanitizer.
//
// CHECK-X86-64-LABEL: define i32 @_ZN2N44read
// CHECK-X86-64: %[[gep:.*]] = getelementptr inbounds {{.*}}* %{{.*}}, i32 0, i32 1
@@ -378,8 +378,8 @@ namespace N6 {
// Zero-length bitfields partition the memory locations of bitfields for the
// purposes of the memory model. That means stores must not span zero-length
// bitfields and loads may only span them when we are not instrumenting with
- // thread sanitizer.
- // FIXME: We currently don't widen loads even without thread sanitizer, even
+ // ThreadSanitizer.
+ // FIXME: We currently don't widen loads even without ThreadSanitizer, even
// though we could.
struct S {
unsigned b1 : 24;
@@ -426,3 +426,55 @@ namespace N6 {
s->b2 = x;
}
}
+
+namespace N7 {
+ // Similar to N4 except that this adds a virtual base to the picture. (PR18430)
+ // Do NOT widen loads and stores to bitfields into padding at the end of
+ // a class which might end up with members inside of it when inside a derived
+ // class.
+ struct B1 {
+ virtual void f();
+ unsigned b1 : 24;
+ };
+ struct B2 : virtual B1 {
+ virtual ~B2();
+ unsigned b : 24;
+ };
+ // Imagine some other translation unit introduces:
+#if 0
+ struct Derived : public B2 {
+ char c;
+ };
+#endif
+ unsigned read(B2* s) {
+ // FIXME: We should widen this load as long as the function isn't being
+ // instrumented by ThreadSanitizer.
+ //
+ // CHECK-X86-64-LABEL: define i32 @_ZN2N74read
+ // 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-LABEL: define zeroext i32 @_ZN2N74read
+ // CHECK-PPC64: %[[gep:.*]] = getelementptr inbounds {{.*}}* %{{.*}}, i32 0, i32 1
+ // CHECK-PPC64: %[[ptr:.*]] = bitcast [3 x i8]* %[[gep]] to i24*
+ // CHECK-PPC64: %[[val:.*]] = load i24* %[[ptr]]
+ // CHECK-PPC64: %[[ext:.*]] = zext i24 %[[val]] to i32
+ // CHECK-PPC64: ret i32 %[[ext]]
+ return s->b;
+ }
+ void write(B2* s, unsigned x) {
+ // CHECK-X86-64-LABEL: define void @_ZN2N75write
+ // 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-LABEL: define void @_ZN2N75write
+ // CHECK-PPC64: %[[gep:.*]] = getelementptr inbounds {{.*}}* %{{.*}}, i32 0, i32 1
+ // CHECK-PPC64: %[[ptr:.*]] = bitcast [3 x i8]* %[[gep]] to i24*
+ // CHECK-PPC64: %[[new:.*]] = trunc i32 %{{.*}} to i24
+ // CHECK-PPC64: store i24 %[[new]], i24* %[[ptr]]
+ s->b = x;
+ }
+}
diff --git a/test/CodeGenCXX/block-byref-cxx-objc.cpp b/test/CodeGenCXX/block-byref-cxx-objc.cpp
index 616fd67ccc38..5c35ad72a20d 100644
--- a/test/CodeGenCXX/block-byref-cxx-objc.cpp
+++ b/test/CodeGenCXX/block-byref-cxx-objc.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -emit-llvm -o - -fblocks | FileCheck %s
+// RUN: %clang_cc1 %s -emit-llvm -triple %itanium_abi_triple -o - -fblocks | FileCheck %s
// rdar://8594790
struct A {
diff --git a/test/CodeGenCXX/block-in-ctor-dtor.cpp b/test/CodeGenCXX/block-in-ctor-dtor.cpp
index bd37d4418d4f..0dc0ab00437f 100644
--- a/test/CodeGenCXX/block-in-ctor-dtor.cpp
+++ b/test/CodeGenCXX/block-in-ctor-dtor.cpp
@@ -40,9 +40,9 @@ X::~X() {
// 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 @___ZN1XC1Ev_block_invoke
+// CHECK-LABEL: define internal void @___ZN1XC1Ev_block_invoke_
// CHECK-LABEL: define internal void @___ZN1XD2Ev_block_invoke
// CHECK-LABEL: define internal void @___ZN1XD2Ev_block_invoke_
diff --git a/test/CodeGenCXX/block.cpp b/test/CodeGenCXX/block.cpp
index 619d8b0c7ba4..aa356688dd63 100644
--- a/test/CodeGenCXX/block.cpp
+++ b/test/CodeGenCXX/block.cpp
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 %s -emit-llvm -o - -fblocks
+// RUN: %clang_cc1 %s -triple %itanium_abi_triple -emit-llvm -o - -fblocks
+// RUN: %clang_cc1 %s -triple %ms_abi_triple -fno-rtti -emit-llvm -o - -fblocks
// Just test that this doesn't crash the compiler...
void func(void*);
diff --git a/test/CodeGenCXX/blocks-cxx11.cpp b/test/CodeGenCXX/blocks-cxx11.cpp
index 9ff5826ec5f1..10d1c655d1f9 100644
--- a/test/CodeGenCXX/blocks-cxx11.cpp
+++ b/test/CodeGenCXX/blocks-cxx11.cpp
@@ -106,7 +106,7 @@ namespace test_block_in_lambda {
// CHECK: [[TO_DESTROY:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
// CHECK: [[T0:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[LAMBDA_T]]* [[THIS]], i32 0, i32 0
- // CHECK-NEXT: call void @_ZN20test_block_in_lambda1AC1ERKS0_({{.*}}* [[T0]], {{.*}}* [[T1]])
+ // CHECK-NEXT: call void @_ZN20test_block_in_lambda1AC1ERKS0_({{.*}}* [[T0]], {{.*}}* dereferenceable({{[0-9]+}}) [[T1]])
// CHECK-NEXT: [[T0:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to void ()*
// CHECK-NEXT: call void @_ZN20test_block_in_lambda9takeBlockEU13block_pointerFvvE(void ()* [[T0]])
// CHECK-NEXT: call void @_ZN20test_block_in_lambda1AD1Ev({{.*}}* [[TO_DESTROY]])
diff --git a/test/CodeGenCXX/blocks.cpp b/test/CodeGenCXX/blocks.cpp
index 8a6fdacf8d1f..6b11083ad739 100644
--- a/test/CodeGenCXX/blocks.cpp
+++ b/test/CodeGenCXX/blocks.cpp
@@ -164,7 +164,7 @@ namespace test5 {
// CHECK-NOT: br
// CHECK: [[CAPTURE:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
- // CHECK-NEXT: call void @_ZN5test51AC1ERKS0_([[A]]* [[CAPTURE]], [[A]]* [[X]])
+ // CHECK-NEXT: call void @_ZN5test51AC1ERKS0_([[A]]* [[CAPTURE]], [[A]]* dereferenceable({{[0-9]+}}) [[X]])
// CHECK-NEXT: store i1 true, i1* [[CLEANUP_ACTIVE]]
// CHECK-NEXT: bitcast [[BLOCK_T]]* [[BLOCK]] to void ()*
// CHECK-NEXT: br label
diff --git a/test/CodeGenCXX/c-linkage.cpp b/test/CodeGenCXX/c-linkage.cpp
index 1607623c6fea..2f8729e4971a 100644
--- a/test/CodeGenCXX/c-linkage.cpp
+++ b/test/CodeGenCXX/c-linkage.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -o - %s | FileCheck %s
// pr6644
extern "C" {
@@ -10,7 +10,7 @@ extern "C" {
}
}
-// CHECK-LABEL: define void @_ZN1N1X1fEv
+// CHECK-LABEL: define {{.*}}void @_ZN1N1X1fEv
extern "C" {
static void test2_f() {
diff --git a/test/CodeGenCXX/call-arg-zero-temp.cpp b/test/CodeGenCXX/call-arg-zero-temp.cpp
index 14238f214515..beef2fd94a23 100644
--- a/test/CodeGenCXX/call-arg-zero-temp.cpp
+++ b/test/CodeGenCXX/call-arg-zero-temp.cpp
@@ -1,4 +1,4 @@
-// REQUIRES: x86-registered-target,x86-64-registered-target
+// REQUIRES: x86-registered-target
// RUN: %clang_cc1 -triple x86_64-apple-darwin -S %s -o %t-64.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
diff --git a/test/CodeGenCXX/captured-statements.cpp b/test/CodeGenCXX/captured-statements.cpp
index 2843c2b69c95..fb35446c7e98 100644
--- a/test/CodeGenCXX/captured-statements.cpp
+++ b/test/CodeGenCXX/captured-statements.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o %t
+// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -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
diff --git a/test/CodeGenCXX/cast-conversion.cpp b/test/CodeGenCXX/cast-conversion.cpp
index 5565f6548437..ce8f82089e1a 100644
--- a/test/CodeGenCXX/cast-conversion.cpp
+++ b/test/CodeGenCXX/cast-conversion.cpp
@@ -1,8 +1,7 @@
-// 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 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 CHECK-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
struct A {
A(int);
@@ -18,16 +17,9 @@ int main () {
static_cast<B>(10);
}
-// CHECK-LP64: callq __ZN1AC1Ei
-// CHECK-LP64: callq __ZN1BC1E1A
-// CHECK-LP64: callq __ZN1AC1Ei
-// CHECK-LP64: callq __ZN1BC1E1A
-// CHECK-LP64: callq __ZN1AC1Ei
-// CHECK-LP64: callq __ZN1BC1E1A
-
-// CHECK-LP32: calll L__ZN1AC1Ei
-// CHECK-LP32: calll L__ZN1BC1E1A
-// CHECK-LP32: calll L__ZN1AC1Ei
-// CHECK-LP32: calll L__ZN1BC1E1A
-// CHECK-LP32: calll L__ZN1AC1Ei
-// CHECK-LP32: calll L__ZN1BC1E1A
+// CHECK: call void @_ZN1AC1Ei
+// CHECK: call void @_ZN1BC1E1A
+// CHECK: call void @_ZN1AC1Ei
+// CHECK: call void @_ZN1BC1E1A
+// CHECK: call void @_ZN1AC1Ei
+// CHECK: call void @_ZN1BC1E1A
diff --git a/test/CodeGenCXX/catch-undef-behavior.cpp b/test/CodeGenCXX/catch-undef-behavior.cpp
index 338da57f0c7b..333855d0ba61 100644
--- a/test/CodeGenCXX/catch-undef-behavior.cpp
+++ b/test/CodeGenCXX/catch-undef-behavior.cpp
@@ -1,4 +1,6 @@
// 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
+// RUN: %clang_cc1 -std=c++11 -fsanitize=vptr,address -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=CHECK-ASAN
+// RUN: %clang_cc1 -std=c++11 -fsanitize=vptr -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=DOWNCAST-NULL
struct S {
double d;
@@ -6,9 +8,15 @@ struct S {
virtual int f();
};
+// Check that type descriptor global is not modified by ASan.
+// CHECK-ASAN: [[TYPE_DESCR:@[0-9]+]] = private unnamed_addr constant { i16, i16, [4 x i8] } { i16 -1, i16 0, [4 x i8] c"'S'\00" }
+
+// Check that type mismatch handler is not modified by ASan.
+// CHECK-ASAN: private unnamed_addr global { { [{{.*}} x i8]*, i32, i32 }, { i16, i16, [4 x i8] }*, i8*, i8 } { {{.*}}, { i16, i16, [4 x i8] }* [[TYPE_DESCR]], {{.*}} }
+
struct T : S {};
-// CHECK: @_Z17reference_binding
+// CHECK-LABEL: @_Z17reference_binding
void reference_binding(int *p, S *q) {
// C++ core issue 453: If an lvalue to which a reference is directly bound
// designates neither an existing object or function of an appropriate type,
@@ -30,7 +38,8 @@ void reference_binding(int *p, S *q) {
S &r2 = *q;
}
-// CHECK: @_Z13member_access
+// CHECK-LABEL: @_Z13member_access
+// CHECK-ASAN-LABEL: @_Z13member_access
void member_access(S *p) {
// (1a) Check 'p' is appropriately sized and aligned for member access.
@@ -117,7 +126,7 @@ void member_access(S *p) {
k = p->f();
}
-// CHECK: @_Z12lsh_overflow
+// CHECK-LABEL: @_Z12lsh_overflow
int lsh_overflow(int a, int b) {
// CHECK: %[[INBOUNDS:.*]] = icmp ule i32 %[[RHS:.*]], 31
// CHECK-NEXT: br i1 %[[INBOUNDS]]
@@ -142,13 +151,13 @@ int lsh_overflow(int a, int b) {
return a << b;
}
-// CHECK: @_Z9no_return
+// CHECK-LABEL: @_Z9no_return
int no_return() {
// CHECK: call void @__ubsan_handle_missing_return(i8* bitcast ({{.*}}* @{{.*}} to i8*)) [[NR_NUW:#[0-9]+]]
// CHECK-NEXT: unreachable
}
-// CHECK: @_Z9sour_bool
+// CHECK-LABEL: @_Z9sour_bool
bool sour_bool(bool *p) {
// CHECK: %[[OK:.*]] = icmp ule i8 {{.*}}, 1
// CHECK: br i1 %[[OK]]
@@ -160,7 +169,7 @@ enum E1 { e1a = 0, e1b = 127 } e1;
enum E2 { e2a = -1, e2b = 64 } e2;
enum E3 { e3a = (1u << 31) - 1 } e3;
-// CHECK: @_Z14bad_enum_value
+// CHECK-LABEL: @_Z14bad_enum_value
int bad_enum_value() {
// CHECK: %[[E1:.*]] = icmp ule i32 {{.*}}, 127
// CHECK: br i1 %[[E1]]
@@ -181,11 +190,16 @@ int bad_enum_value() {
return a + b + c;
}
-// CHECK: @_Z20bad_downcast_pointer
+// CHECK-LABEL: @_Z20bad_downcast_pointer
+// DOWNCAST-NULL-LABEL: @_Z20bad_downcast_pointer
void bad_downcast_pointer(S *p) {
// CHECK: %[[NONNULL:.*]] = icmp ne {{.*}}, null
// CHECK: br i1 %[[NONNULL]],
+ // A null poiner access is guarded without -fsanitize=null.
+ // DOWNCAST-NULL: %[[NONNULL:.*]] = icmp ne {{.*}}, null
+ // DOWNCAST-NULL: br i1 %[[NONNULL]],
+
// CHECK: %[[SIZE:.*]] = call i64 @llvm.objectsize.i64.p0i8(
// CHECK: %[[E1:.*]] = icmp uge i64 %[[SIZE]], 24
// CHECK: %[[MISALIGN:.*]] = and i64 %{{.*}}, 7
@@ -203,7 +217,7 @@ void bad_downcast_pointer(S *p) {
(void) static_cast<T*>(p);
}
-// CHECK: @_Z22bad_downcast_reference
+// CHECK-LABEL: @_Z22bad_downcast_reference
void bad_downcast_reference(S &p) {
// CHECK: %[[E1:.*]] = icmp ne {{.*}}, null
// CHECK-NOT: br i1
@@ -225,7 +239,7 @@ void bad_downcast_reference(S &p) {
(void) static_cast<T&>(p);
}
-// CHECK: @_Z11array_index
+// CHECK-LABEL: @_Z11array_index
int array_index(const int (&a)[4], int n) {
// CHECK: %[[K1_OK:.*]] = icmp ult i64 %{{.*}}, 4
// CHECK: br i1 %[[K1_OK]]
@@ -250,7 +264,7 @@ int array_index(const int (&a)[4], int n) {
return k1 + *r1 + k2;
}
-// CHECK: @_Z17multi_array_index
+// CHECK-LABEL: @_Z17multi_array_index
int multi_array_index(int n, int m) {
int arr[4][6];
@@ -264,7 +278,7 @@ int multi_array_index(int n, int m) {
return arr[n][m];
}
-// CHECK: @_Z11array_arith
+// CHECK-LABEL: @_Z11array_arith
int array_arith(const int (&a)[4], int n) {
// CHECK: %[[K1_OK:.*]] = icmp ule i64 %{{.*}}, 4
// CHECK: br i1 %[[K1_OK]]
@@ -283,7 +297,7 @@ struct ArrayMembers {
int a1[5];
int a2[1];
};
-// CHECK: @_Z18struct_array_index
+// CHECK-LABEL: @_Z18struct_array_index
int struct_array_index(ArrayMembers *p, int n) {
// CHECK: %[[IDX_OK:.*]] = icmp ult i64 %{{.*}}, 5
// CHECK: br i1 %[[IDX_OK]]
@@ -291,21 +305,21 @@ int struct_array_index(ArrayMembers *p, int n) {
return p->a1[n];
}
-// CHECK: @_Z16flex_array_index
+// CHECK-LABEL: @_Z16flex_array_index
int flex_array_index(ArrayMembers *p, int n) {
// CHECK-NOT: call void @__ubsan_handle_out_of_bounds(
return p->a2[n];
}
extern int incomplete[];
-// CHECK: @_Z22incomplete_array_index
+// CHECK-LABEL: @_Z22incomplete_array_index
int incomplete_array_index(int n) {
// CHECK-NOT: call void @__ubsan_handle_out_of_bounds(
return incomplete[n];
}
typedef __attribute__((ext_vector_type(4))) int V4I;
-// CHECK: @_Z12vector_index
+// CHECK-LABEL: @_Z12vector_index
int vector_index(V4I v, int n) {
// CHECK: %[[IDX_OK:.*]] = icmp ult i64 %{{.*}}, 4
// CHECK: br i1 %[[IDX_OK]]
@@ -313,7 +327,7 @@ int vector_index(V4I v, int n) {
return v[n];
}
-// CHECK: @_Z12string_index
+// CHECK-LABEL: @_Z12string_index
char string_index(int n) {
// CHECK: %[[IDX_OK:.*]] = icmp ult i64 %{{.*}}, 6
// CHECK: br i1 %[[IDX_OK]]
@@ -357,7 +371,7 @@ void downcast_pointer(B *b) {
// CHECK-NEXT: br i1 [[AND]]
}
-// CHECK-LABEL: define void @_Z18downcast_referenceR1B(%class.B* %b)
+// CHECK-LABEL: define void @_Z18downcast_referenceR1B(%class.B* dereferenceable({{[0-9]+}}) %b)
void downcast_reference(B &b) {
(void) static_cast<C&>(b);
// Alignment check from EmitTypeCheck(TCK_DowncastReference, ...)
diff --git a/test/CodeGenCXX/class-layout.cpp b/test/CodeGenCXX/class-layout.cpp
index 21e1a2b40f04..d7d84a86abad 100644
--- a/test/CodeGenCXX/class-layout.cpp
+++ b/test/CodeGenCXX/class-layout.cpp
@@ -39,7 +39,7 @@ namespace Test5 {
char a;
};
- // CHECK: %"struct.Test5::B" = type { [9 x i8], i8, i8, [5 x i8] }
+ // CHECK: %"struct.Test5::B" = type { %"struct.Test5::A.base", i8, i8, [5 x i8] }
struct B : A {
char b : 1;
char c;
@@ -91,3 +91,12 @@ namespace Test7 {
B* b;
#pragma pack ()
}
+
+// Shouldn't crash.
+namespace Test8 {
+ struct A {};
+ struct D { int a; };
+ struct B : virtual D, A { };
+ struct C : B, A { void f() {} };
+ C c;
+}
diff --git a/test/CodeGenCXX/conditional-gnu-ext.cpp b/test/CodeGenCXX/conditional-gnu-ext.cpp
index 44ebf9808e4a..3a61a63cf449 100644
--- a/test/CodeGenCXX/conditional-gnu-ext.cpp
+++ b/test/CodeGenCXX/conditional-gnu-ext.cpp
@@ -83,7 +83,7 @@ namespace test3 {
// CHECK-NEXT: [[T0:%.*]] = load [[B]]** [[X]]
// CHECK-NEXT: [[BOOL:%.*]] = call zeroext i1 @_ZN5test31BcvbEv([[B]]* [[T0]])
// CHECK-NEXT: br i1 [[BOOL]]
- // CHECK: call void @_ZN5test31BC1ERKS0_([[B]]* [[RESULT:%.*]], [[B]]* [[T0]])
+ // CHECK: call void @_ZN5test31BC1ERKS0_([[B]]* [[RESULT:%.*]], [[B]]* dereferenceable({{[0-9]+}}) [[T0]])
// CHECK-NEXT: br label
// CHECK: call void @_ZN5test31BC1Ev([[B]]* [[RESULT]])
// CHECK-NEXT: br label
@@ -97,7 +97,7 @@ namespace test3 {
// CHECK-NEXT: call void @_ZN5test312test1_helperEv([[B]]* sret [[TEMP]])
// CHECK-NEXT: [[BOOL:%.*]] = call zeroext i1 @_ZN5test31BcvbEv([[B]]* [[TEMP]])
// CHECK-NEXT: br i1 [[BOOL]]
- // CHECK: call void @_ZN5test31BC1ERKS0_([[B]]* [[RESULT:%.*]], [[B]]* [[TEMP]])
+ // CHECK: call void @_ZN5test31BC1ERKS0_([[B]]* [[RESULT:%.*]], [[B]]* dereferenceable({{[0-9]+}}) [[TEMP]])
// CHECK-NEXT: br label
// CHECK: call void @_ZN5test31BC1Ev([[B]]* [[RESULT]])
// CHECK-NEXT: br label
diff --git a/test/CodeGenCXX/const-base-cast.cpp b/test/CodeGenCXX/const-base-cast.cpp
index 320c790c5e2d..dd980d5469bf 100644
--- a/test/CodeGenCXX/const-base-cast.cpp
+++ b/test/CodeGenCXX/const-base-cast.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck %s
// Check that the following construct, which is similar to one which occurs
// in Firefox, is folded correctly.
diff --git a/test/CodeGenCXX/const-global-linkage.cpp b/test/CodeGenCXX/const-global-linkage.cpp
index df78fdd0287c..e1e932197479 100644
--- a/test/CodeGenCXX/const-global-linkage.cpp
+++ b/test/CodeGenCXX/const-global-linkage.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck %s
const int x = 10;
const int y = 20;
diff --git a/test/CodeGenCXX/const-init-cxx11.cpp b/test/CodeGenCXX/const-init-cxx11.cpp
index d21e91178e40..f671e0ad8802 100644
--- a/test/CodeGenCXX/const-init-cxx11.cpp
+++ b/test/CodeGenCXX/const-init-cxx11.cpp
@@ -382,17 +382,22 @@ namespace ArrayTemporary {
namespace UnemittedTemporaryDecl {
constexpr int &&ref = 0;
extern constexpr int &ref2 = ref;
- // CHECK: @_ZGRN22UnemittedTemporaryDecl3refE = private global i32 0
+ // 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: @_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
+// CHECK: @_ZGRN33ClassTemplateWithStaticDataMember1SIvE1aE_ = linkonce_odr constant i32 5
+// CHECK: @_ZN33ClassTemplateWithStaticDataMember3useE = constant i32* @_ZGRN33ClassTemplateWithStaticDataMember1SIvE1aE_
+// CHECK: @_ZGRN39ClassTemplateWithHiddenStaticDataMember1SIvE1aE_ = linkonce_odr hidden constant i32 5
+// CHECK: @_ZN39ClassTemplateWithHiddenStaticDataMember3useE = constant i32* @_ZGRN39ClassTemplateWithHiddenStaticDataMember1SIvE1aE_
+// CHECK: @_ZGRZN20InlineStaticConstRef3funEvE1i_ = linkonce_odr constant i32 10
// Constant initialization tests go before this point,
// dynamic initialization tests go after.
@@ -527,10 +532,10 @@ namespace InitFromConst {
// CHECK: call void @_ZN13InitFromConst7consumeIdEEvT_(double 4.300000e+00)
consume(d);
- // CHECK: call void @_ZN13InitFromConst7consumeIRKNS_1SEEEvT_(%"struct.InitFromConst::S"* @_ZN13InitFromConstL1sE)
+ // CHECK: call void @_ZN13InitFromConst7consumeIRKNS_1SEEEvT_(%"struct.InitFromConst::S"* dereferenceable({{[0-9]+}}) @_ZN13InitFromConstL1sE)
consume<const S&>(s);
- // CHECK: call void @_ZN13InitFromConst7consumeIRKNS_1SEEEvT_(%"struct.InitFromConst::S"* @_ZN13InitFromConstL1sE)
+ // CHECK: call void @_ZN13InitFromConst7consumeIRKNS_1SEEEvT_(%"struct.InitFromConst::S"* dereferenceable({{[0-9]+}}) @_ZN13InitFromConstL1sE)
consume<const S&>(r);
// CHECK: call void @_ZN13InitFromConst7consumeIPKNS_1SEEEvT_(%"struct.InitFromConst::S"* @_ZN13InitFromConstL1sE)
@@ -552,3 +557,32 @@ namespace Null {
// CHECK: call {{.*}} @_ZN4Null4nullEv(
int S::*q = null();
}
+
+namespace InlineStaticConstRef {
+ inline const int &fun() {
+ static const int &i = 10;
+ return i;
+ // CHECK: ret i32* @_ZGRZN20InlineStaticConstRef3funEvE1i_
+ }
+ const int &use = fun();
+}
+
+namespace ClassTemplateWithStaticDataMember {
+ template <typename T>
+ struct S {
+ static const int &a;
+ };
+ template <typename T>
+ const int &S<T>::a = 5;
+ const int &use = S<void>::a;
+}
+
+namespace ClassTemplateWithHiddenStaticDataMember {
+ template <typename T>
+ struct S {
+ __attribute__((visibility("hidden"))) static const int &a;
+ };
+ template <typename T>
+ const int &S<T>::a = 5;
+ const int &use = S<void>::a;
+}
diff --git a/test/CodeGenCXX/const-init-cxx1y.cpp b/test/CodeGenCXX/const-init-cxx1y.cpp
index 978c428e078a..9348b43f486f 100644
--- a/test/CodeGenCXX/const-init-cxx1y.cpp
+++ b/test/CodeGenCXX/const-init-cxx1y.cpp
@@ -1,4 +1,5 @@
-// RUN: not %clang_cc1 -verify -triple x86_64-apple-darwin -emit-llvm -o - %s -std=c++1y | FileCheck %s
+// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin -emit-llvm -o - %s -std=c++1y | FileCheck %s
+// expected-no-diagnostics
struct A {
constexpr A() : n(1) {}
@@ -22,26 +23,64 @@ 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
+ // 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
+ // 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: @_ZGRN21ModifyStaticTemporary1cE_ = private global i32 10
// CHECK: @_ZN21ModifyStaticTemporary1cE = global {{.*}} zeroinitializer
}
+// CHECK: @_ZGRN28VariableTemplateWithConstRef1iIvEE_ = linkonce_odr constant i32 5, align 4
+// CHECK: @_ZN28VariableTemplateWithConstRef3useE = constant i32* @_ZGRN28VariableTemplateWithConstRef1iIvEE_
+namespace VariableTemplateWithConstRef {
+ template <typename T>
+ const int &i = 5;
+ const int &use = i<void>;
+}
+
+// CHECK: @_ZGRN34HiddenVariableTemplateWithConstRef1iIvEE_ = linkonce_odr hidden constant i32 5, align 4
+// CHECK: @_ZN34HiddenVariableTemplateWithConstRef3useE = constant i32* @_ZGRN34HiddenVariableTemplateWithConstRef1iIvEE_
+namespace HiddenVariableTemplateWithConstRef {
+ template <typename T>
+ __attribute__((visibility("hidden"))) const int &i = 5;
+ const int &use = i<void>;
+}
+
+// CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE1_ = linkonce_odr constant i32 1
+// CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE0_ = linkonce_odr global {{.*}} { i32* @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE1_ }
+// CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE3_ = linkonce_odr constant i32 2
+// CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE2_ = linkonce_odr global {{.*}} { i32* @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE3_ }
+// CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE5_ = linkonce_odr constant i32 3
+// CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE4_ = linkonce_odr global {{.*}} { i32* @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE5_ }
+// CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE7_ = linkonce_odr constant i32 4
+// CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE6_ = linkonce_odr global {{.*}} { i32* @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE7_ }
+// CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE_ = linkonce_odr global %"struct.VariableTemplateWithPack::S" { {{.*}}* @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE0_, {{.*}}* @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE2_, {{.*}}* @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE4_, {{.*}}* @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE6_ }
+// CHECK: @_ZN24VariableTemplateWithPack1pE = global {{.*}} @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE_
+namespace VariableTemplateWithPack {
+ struct A {
+ const int &r;
+ };
+ struct S {
+ A &&a, &&b, &&c, &&d;
+ };
+ template <int... N>
+ S &&s = {A{N}...};
+ S *p = &s<1, 2, 3, 4>;
+}
+
// CHECK: __cxa_atexit({{.*}} @_ZN1BD1Ev {{.*}} @b
// CHECK: define
-// CHECK-NOT: @_ZGRN21ModifyStaticTemporary1cE
-// CHECK: store {{.*}} @_ZGRN21ModifyStaticTemporary1cE, {{.*}} @_ZN21ModifyStaticTemporary1cE
+// CHECK-NOT: @_ZGRN21ModifyStaticTemporary1cE_
+// CHECK: store {{.*}} @_ZGRN21ModifyStaticTemporary1cE_, {{.*}} @_ZN21ModifyStaticTemporary1cE
// CHECK: add
// CHECK: store
// CHECK: load {{.*}} @_ZN21ModifyStaticTemporary1bE
diff --git a/test/CodeGenCXX/constructor-attr.cpp b/test/CodeGenCXX/constructor-attr.cpp
index 4f6d635e95d1..468ce36688f7 100644
--- a/test/CodeGenCXX/constructor-attr.cpp
+++ b/test/CodeGenCXX/constructor-attr.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck %s
// CHECK: @llvm.global_ctors
diff --git a/test/CodeGenCXX/constructor-conversion.cpp b/test/CodeGenCXX/constructor-conversion.cpp
index ebb414da960b..bace54fc596d 100644
--- a/test/CodeGenCXX/constructor-conversion.cpp
+++ b/test/CodeGenCXX/constructor-conversion.cpp
@@ -1,8 +1,7 @@
-// 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 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 CHECK-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(...);
@@ -46,10 +45,6 @@ int main() {
g(3); // g(X(3))
}
-// CHECK-LP64: callq __ZN1XC1Ei
-// CHECK-LP64: callq __ZN1XC1EPKci
-// CHECK-LP64: callq __ZN1XC1Ev
-
-// CHECK-LP32: calll L__ZN1XC1Ei
-// CHECK-LP32: calll L__ZN1XC1EPKci
-// CHECK-LP32: calll L__ZN1XC1Ev
+// CHECK: call void @_ZN1XC1Ei
+// CHECK: call void @_ZN1XC1EPKci
+// CHECK: call void @_ZN1XC1Ev
diff --git a/test/CodeGenCXX/constructor-default-arg.cpp b/test/CodeGenCXX/constructor-default-arg.cpp
index c2cf44ce810c..98a586494dd0 100644
--- a/test/CodeGenCXX/constructor-default-arg.cpp
+++ b/test/CodeGenCXX/constructor-default-arg.cpp
@@ -1,8 +1,7 @@
-// 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 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 CHECK-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(...);
@@ -31,10 +30,6 @@ int main() {
X d(a, 5, 6);
}
-// CHECK-LP64: callq __ZN1XC1ERKS_iii
-// CHECK-LP64: callq __ZN1XC1ERKS_iii
-// CHECK-LP64: callq __ZN1XC1ERKS_iii
-
-// CHECK-LP32: calll L__ZN1XC1ERKS_iii
-// CHECK-LP32: calll L__ZN1XC1ERKS_iii
-// CHECK-LP32: calll L__ZN1XC1ERKS_iii
+// CHECK: call void @_ZN1XC1ERKS_iii
+// CHECK: call void @_ZN1XC1ERKS_iii
+// CHECK: call void @_ZN1XC1ERKS_iii
diff --git a/test/CodeGenCXX/constructor-destructor-return-this.cpp b/test/CodeGenCXX/constructor-destructor-return-this.cpp
index ea2ea45a3273..ce6ddd29f644 100644
--- a/test/CodeGenCXX/constructor-destructor-return-this.cpp
+++ b/test/CodeGenCXX/constructor-destructor-return-this.cpp
@@ -1,6 +1,7 @@
//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
+//RUN: %clang_cc1 %s -emit-llvm -o - -triple=thumbv7-apple-ios6.0 -target-abi apcs-gnu | FileCheck --check-prefix=CHECKARM %s
+//RUN: %clang_cc1 %s -emit-llvm -o - -triple=thumbv7-apple-ios5.0 -target-abi apcs-gnu | FileCheck --check-prefix=CHECKIOS5 %s
+//RUN: %clang_cc1 %s -emit-llvm -o - -triple=i386-pc-win32 -fno-rtti | FileCheck --check-prefix=CHECKMS %s
// FIXME: these tests crash on the bots when run with -triple=x86_64-pc-win32
// Make sure we attach the 'returned' attribute to the 'this' parameter of
@@ -27,15 +28,20 @@ private:
B::B(int *i) : i_(i) { }
B::~B() { }
-// 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 @_ZN1BC1EPi(%class.B* %this, i32* %i)
// CHECKGEN-LABEL: define void @_ZN1BD2Ev(%class.B* %this)
+// CHECKGEN-LABEL: define void @_ZN1BD1Ev(%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* @_ZN1BC1EPi(%class.B* returned %this, i32* %i)
// CHECKARM-LABEL: define %class.B* @_ZN1BD2Ev(%class.B* returned %this)
+// CHECKARM-LABEL: define %class.B* @_ZN1BD1Ev(%class.B* returned %this)
+
+// CHECKIOS5-LABEL: define %class.B* @_ZN1BC2EPi(%class.B* %this, i32* %i)
+// CHECKIOS5-LABEL: define %class.B* @_ZN1BC1EPi(%class.B* %this, i32* %i)
+// CHECKIOS5-LABEL: define %class.B* @_ZN1BD2Ev(%class.B* %this)
+// CHECKIOS5-LABEL: define %class.B* @_ZN1BD1Ev(%class.B* %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)
@@ -51,17 +57,23 @@ private:
C::C(int *i, char *c) : B(i), c_(c) { }
C::~C() { }
-// 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 @_ZN1CC1EPiPc(%class.C* %this, i32* %i, i8* %c)
// CHECKGEN-LABEL: define void @_ZN1CD2Ev(%class.C* %this)
+// CHECKGEN-LABEL: define void @_ZN1CD1Ev(%class.C* %this)
+// CHECKGEN-LABEL: define void @_ZN1CD0Ev(%class.C* %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* @_ZN1CC1EPiPc(%class.C* returned %this, i32* %i, i8* %c)
// CHECKARM-LABEL: define %class.C* @_ZN1CD2Ev(%class.C* returned %this)
+// CHECKARM-LABEL: define %class.C* @_ZN1CD1Ev(%class.C* returned %this)
+// CHECKARM-LABEL: define void @_ZN1CD0Ev(%class.C* %this)
+
+// CHECKIOS5-LABEL: define %class.C* @_ZN1CC2EPiPc(%class.C* %this, i32* %i, i8* %c)
+// CHECKIOS5-LABEL: define %class.C* @_ZN1CC1EPiPc(%class.C* %this, i32* %i, i8* %c)
+// CHECKIOS5-LABEL: define %class.C* @_ZN1CD2Ev(%class.C* %this)
+// CHECKIOS5-LABEL: define %class.C* @_ZN1CD1Ev(%class.C* %this)
+// CHECKIOS5-LABEL: define void @_ZN1CD0Ev(%class.C* %this)
// 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)
@@ -75,15 +87,20 @@ public:
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 @_ZN1DC1Ev(%class.D* %this)
// CHECKGEN-LABEL: define void @_ZN1DD2Ev(%class.D* %this, i8** %vtt)
+// CHECKGEN-LABEL: define void @_ZN1DD1Ev(%class.D* %this)
-// 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* @_ZN1DC1Ev(%class.D* returned %this)
// CHECKARM-LABEL: define %class.D* @_ZN1DD2Ev(%class.D* returned %this, i8** %vtt)
+// CHECKARM-LABEL: define %class.D* @_ZN1DD1Ev(%class.D* returned %this)
+
+// CHECKIOS5-LABEL: define %class.D* @_ZN1DC2Ev(%class.D* %this, i8** %vtt)
+// CHECKIOS5-LABEL: define %class.D* @_ZN1DC1Ev(%class.D* %this)
+// CHECKIOS5-LABEL: define %class.D* @_ZN1DD2Ev(%class.D* %this, i8** %vtt)
+// CHECKIOS5-LABEL: define %class.D* @_ZN1DD1Ev(%class.D* %this)
// 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)
diff --git a/test/CodeGenCXX/constructor-direct-call.cpp b/test/CodeGenCXX/constructor-direct-call.cpp
index 75e6f216ca51..9567d0968dae 100644
--- a/test/CodeGenCXX/constructor-direct-call.cpp
+++ b/test/CodeGenCXX/constructor-direct-call.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple i686-pc-win32 -fms-extensions -Wmicrosoft %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -triple i686-pc-mingw32 -fms-extensions -Wmicrosoft %s -emit-llvm -o - | FileCheck %s
class Test1 {
public:
@@ -22,10 +22,10 @@ public:
void f2() {
// CHECK: %var = alloca %class.Test2, align 4
- // CHECK-NEXT: call void @_ZN5Test2C1Ev(%class.Test2* %var)
+ // CHECK-NEXT: call x86_thiscallcc void @_ZN5Test2C1Ev(%class.Test2* %var)
Test2 var;
- // CHECK-NEXT: call void @_ZN5Test2C1Ev(%class.Test2* %var)
+ // CHECK-NEXT: call x86_thiscallcc void @_ZN5Test2C1Ev(%class.Test2* %var)
var.Test2::Test2();
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* %{{.*}}, i8* %{{.*}}, i32 8, i32 4, i1 false)
@@ -45,16 +45,15 @@ public:
};
void f3() {
- // CHECK: call void @_ZN5Test3C1Ev(%class.Test3* %var)
+ // CHECK: call x86_thiscallcc void @_ZN5Test3C1Ev(%class.Test3* %var)
Test3 var;
- // CHECK-NEXT: call void @_ZN5Test3C1Ev(%class.Test3* %var2)
+ // CHECK-NEXT: call x86_thiscallcc void @_ZN5Test3C1Ev(%class.Test3* %var2)
Test3 var2;
- // CHECK-NEXT: call void @_ZN5Test3C1Ev(%class.Test3* %var)
+ // CHECK-NEXT: call x86_thiscallcc void @_ZN5Test3C1Ev(%class.Test3* %var)
var.Test3::Test3();
- // CHECK-NEXT: call void @_ZN5Test3C1ERKS_(%class.Test3* %var, %class.Test3* %var2)
+ // CHECK-NEXT: call x86_thiscallcc void @_ZN5Test3C1ERKS_(%class.Test3* %var, %class.Test3* dereferenceable({{[0-9]+}}) %var2)
var.Test3::Test3(var2);
}
-
diff --git a/test/CodeGenCXX/constructor-for-array-members.cpp b/test/CodeGenCXX/constructor-for-array-members.cpp
index 7842d9c725e5..8ea7eacd2b2b 100644
--- a/test/CodeGenCXX/constructor-for-array-members.cpp
+++ b/test/CodeGenCXX/constructor-for-array-members.cpp
@@ -1,8 +1,7 @@
-// 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 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 CHECK-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(...);
@@ -39,6 +38,4 @@ int main() {
m1.pr();
}
-// CHECK-LP64: callq __ZN1SC1Ev
-
-// CHECK-LP32: calll L__ZN1SC1Ev
+// CHECK: call void @_ZN1SC1Ev
diff --git a/test/CodeGenCXX/constructor-init-reference.cpp b/test/CodeGenCXX/constructor-init-reference.cpp
index 5e7515976518..61f426da51fd 100644
--- a/test/CodeGenCXX/constructor-init-reference.cpp
+++ b/test/CodeGenCXX/constructor-init-reference.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm -o - %s | grep "store i32\* @x, i32\*\*"
+// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck %s
int x;
struct A {
@@ -6,4 +6,4 @@ struct A {
A() : y(x) {}
};
A z;
-
+// CHECK: store i32* @x, i32**
diff --git a/test/CodeGenCXX/constructor-init.cpp b/test/CodeGenCXX/constructor-init.cpp
index 477a439f337a..a8f483e53ab5 100644
--- a/test/CodeGenCXX/constructor-init.cpp
+++ b/test/CodeGenCXX/constructor-init.cpp
@@ -163,7 +163,7 @@ template<typename T> struct X;
// Make sure that the instantiated constructor initializes start and
// end properly.
-// CHECK-LABEL: 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* dereferenceable({{[0-9]+}}) %other) unnamed_addr
// CHECK: {{store.*null}}
// CHECK: {{store.*null}}
// CHECK: ret
diff --git a/test/CodeGenCXX/constructor-template.cpp b/test/CodeGenCXX/constructor-template.cpp
index 0d38d10c1382..675e3cfc0a41 100644
--- a/test/CodeGenCXX/constructor-template.cpp
+++ b/test/CodeGenCXX/constructor-template.cpp
@@ -1,4 +1,4 @@
-// REQUIRES: x86-registered-target,x86-64-registered-target
+// REQUIRES: x86-registered-target
// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -S %s -o %t-64.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
diff --git a/test/CodeGenCXX/constructors.cpp b/test/CodeGenCXX/constructors.cpp
index f730b9ef491a..b99c5a194157 100644
--- a/test/CodeGenCXX/constructors.cpp
+++ b/test/CodeGenCXX/constructors.cpp
@@ -21,20 +21,19 @@ struct A {
A::A(struct Undeclared &ref) : mem(0) {}
// Check that delegation works.
-// CHECK-LABEL: define void @_ZN1AC1ER10Undeclared(%struct.A* %this, %struct.Undeclared* %ref) unnamed_addr
-// CHECK: call void @_ZN1AC2ER10Undeclared(
-
-// CHECK-LABEL: define void @_ZN1AC2ER10Undeclared(%struct.A* %this, %struct.Undeclared* %ref) unnamed_addr
+// CHECK-LABEL: define void @_ZN1AC2ER10Undeclared(%struct.A* %this, %struct.Undeclared* nonnull %ref) unnamed_addr
// CHECK: call void @_ZN6MemberC1Ei(
-A::A(ValueClass v) : mem(v.y - v.x) {}
+// CHECK-LABEL: define void @_ZN1AC1ER10Undeclared(%struct.A* %this, %struct.Undeclared* nonnull %ref) unnamed_addr
+// CHECK: call void @_ZN1AC2ER10Undeclared(
-// CHECK-LABEL: define void @_ZN1AC1E10ValueClass(%struct.A* %this, i64 %v.coerce) unnamed_addr
-// CHECK: call void @_ZN1AC2E10ValueClass(
+A::A(ValueClass v) : mem(v.y - v.x) {}
// CHECK-LABEL: define void @_ZN1AC2E10ValueClass(%struct.A* %this, i64 %v.coerce) unnamed_addr
// CHECK: call void @_ZN6MemberC1Ei(
+// CHECK-LABEL: define void @_ZN1AC1E10ValueClass(%struct.A* %this, i64 %v.coerce) unnamed_addr
+// CHECK: call void @_ZN1AC2E10ValueClass(
/* Test that things work for inheritance. */
struct B : A {
@@ -44,13 +43,12 @@ struct B : A {
B::B(struct Undeclared &ref) : A(ref), mem(1) {}
-// CHECK-LABEL: define void @_ZN1BC1ER10Undeclared(%struct.B* %this, %struct.Undeclared* %ref) unnamed_addr
-// CHECK: call void @_ZN1BC2ER10Undeclared(
-
-// CHECK-LABEL: define void @_ZN1BC2ER10Undeclared(%struct.B* %this, %struct.Undeclared* %ref) unnamed_addr
+// CHECK-LABEL: define void @_ZN1BC2ER10Undeclared(%struct.B* %this, %struct.Undeclared* nonnull %ref) unnamed_addr
// CHECK: call void @_ZN1AC2ER10Undeclared(
// CHECK: call void @_ZN6MemberC1Ei(
+// CHECK-LABEL: define void @_ZN1BC1ER10Undeclared(%struct.B* %this, %struct.Undeclared* nonnull %ref) unnamed_addr
+// CHECK: call void @_ZN1BC2ER10Undeclared(
/* Test that the delegation optimization is disabled for classes with
@@ -64,15 +62,14 @@ struct C : virtual A {
};
C::C(int x) : A(ValueClass(x, x+1)), mem(x * x) {}
+// CHECK-LABEL: define void @_ZN1CC2Ei(%struct.C* %this, i8** %vtt, i32 %x) unnamed_addr
+// CHECK: call void @_ZN6MemberC1Ei(
+
// 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-LABEL: define void @_ZN1CC2Ei(%struct.C* %this, i8** %vtt, i32 %x) unnamed_addr
-// CHECK: call void @_ZN6MemberC1Ei(
-
-
/* Test that the delegation optimization is disabled for varargs
constructors. */
@@ -83,17 +80,16 @@ struct D : A {
D::D(int x, ...) : A(ValueClass(x, x+1)), mem(x*x) {}
-// CHECK-LABEL: define void @_ZN1DC1Eiz(%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(
-// CHECK-LABEL: define void @_ZN1DC2Eiz(%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(
-
// PR6622: this shouldn't crash
namespace test0 {
struct A {};
diff --git a/test/CodeGenCXX/convert-to-fptr.cpp b/test/CodeGenCXX/convert-to-fptr.cpp
index e497acf33dc4..c3be9627ba73 100644
--- a/test/CodeGenCXX/convert-to-fptr.cpp
+++ b/test/CodeGenCXX/convert-to-fptr.cpp
@@ -1,8 +1,7 @@
-// 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 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 CHECK-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(...);
@@ -39,9 +38,5 @@ int main()
return 0;
}
-// CHECK-LP64: callq __ZN1AcvPFiiEEv
-// CHECK-LP64: callq __ZN1BcvRFiiEEv
-
-// CHECK-LP32: calll L__ZN1AcvPFiiEEv
-// CHECK-LP32: calll L__ZN1BcvRFiiEEv
-
+// CHECK: call i32 (i32)* (%struct.A*)* @_ZN1AcvPFiiEEv
+// CHECK: call i32 (i32)* (%struct.B*)* @_ZN1BcvRFiiEEv
diff --git a/test/CodeGenCXX/copy-assign-synthesis-1.cpp b/test/CodeGenCXX/copy-assign-synthesis-1.cpp
index 2ffc7bcb7c8d..5813d9c92d80 100644
--- a/test/CodeGenCXX/copy-assign-synthesis-1.cpp
+++ b/test/CodeGenCXX/copy-assign-synthesis-1.cpp
@@ -1,4 +1,3 @@
-// REQUIRES: x86-registered-target,x86-64-registered-target
// 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 - | \
@@ -93,5 +92,4 @@ int main() {
dstY.pr();
}
-// CHECK: define linkonce_odr %struct.X* @_ZN1XaSERKS_
-
+// CHECK: define linkonce_odr dereferenceable({{[0-9]+}}) %struct.X* @_ZN1XaSERKS_
diff --git a/test/CodeGenCXX/copy-assign-synthesis-2.cpp b/test/CodeGenCXX/copy-assign-synthesis-2.cpp
index 18e92f98ebde..0bc7d3d6529f 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
+// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck %s
struct A {};
A& (A::*x)(const A&) = &A::operator=;
-// CHECK-LABEL: define linkonce_odr %struct.A* @_ZN1AaSERKS_
+// CHECK-LABEL: define linkonce_odr {{.*}}%struct.A* @_ZN1AaSERKS_
diff --git a/test/CodeGenCXX/copy-constructor-elim-2.cpp b/test/CodeGenCXX/copy-constructor-elim-2.cpp
index 727af1ba7cd3..c263b7ebf952 100644
--- a/test/CodeGenCXX/copy-constructor-elim-2.cpp
+++ b/test/CodeGenCXX/copy-constructor-elim-2.cpp
@@ -21,7 +21,7 @@ namespace no_elide_base {
Derived(const Other &O);
};
- // CHECK: define {{.*}} @_ZN13no_elide_base7DerivedC1ERKNS_5OtherE(%"struct.no_elide_base::Derived"* returned %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"* dereferenceable({{[0-9]+}}) %O) unnamed_addr
Derived::Derived(const Other &O)
// CHECK: call {{.*}} @_ZNK13no_elide_base5OthercvNS_4BaseEEv
// CHECK: call {{.*}} @_ZN13no_elide_base4BaseC2ERKS0_
@@ -74,4 +74,3 @@ namespace PR12139 {
return a.value;
}
}
-
diff --git a/test/CodeGenCXX/copy-constructor-elim.cpp b/test/CodeGenCXX/copy-constructor-elim.cpp
index ad3a87b9d5f8..8e9bee973771 100644
--- a/test/CodeGenCXX/copy-constructor-elim.cpp
+++ b/test/CodeGenCXX/copy-constructor-elim.cpp
@@ -1,6 +1,9 @@
-// RUN: %clang_cc1 -emit-llvm -o %t %s
-// RUN: not grep "_ZN1CC1ERK1C" %t
-// RUN: not grep "_ZN1SC1ERK1S" %t
+// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK
+// RUN: %clang_cc1 -triple %ms_abi_triple -emit-llvm -o - %s | FileCheck %s -check-prefix MS
+// CHECK-NOT: _ZN1CC1ERK1C
+// CHECK-NOT: _ZN1SC1ERK1S
+// MS-NOT: ?0C@@QAE@ABV0
+// MS-NOT: ?0S@@QAE@ABV0
extern "C" int printf(...);
diff --git a/test/CodeGenCXX/copy-constructor-synthesis-2.cpp b/test/CodeGenCXX/copy-constructor-synthesis-2.cpp
index 03c66339947d..4bb0fee25e51 100644
--- a/test/CodeGenCXX/copy-constructor-synthesis-2.cpp
+++ b/test/CodeGenCXX/copy-constructor-synthesis-2.cpp
@@ -1,7 +1,7 @@
-// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck %s
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* dereferenceable({{[0-9]+}})) 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 c8b265ca2d12..47f8e131d62e 100644
--- a/test/CodeGenCXX/copy-constructor-synthesis.cpp
+++ b/test/CodeGenCXX/copy-constructor-synthesis.cpp
@@ -21,7 +21,7 @@ struct P {
};
-// CHECK-LABEL: define linkonce_odr void @_ZN1XC1ERKS_(%struct.X* %this, %struct.X*) unnamed_addr
+// CHECK-LABEL: define linkonce_odr void @_ZN1XC1ERKS_(%struct.X* %this, %struct.X* dereferenceable({{[0-9]+}})) 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,15 +136,13 @@ void f(B b1) {
B b2 = b1;
}
-// CHECK: define linkonce_odr [[A:%.*]]* @_ZN12rdar138169401AaSERKS0_(
+// CHECK: define linkonce_odr dereferenceable({{[0-9]+}}) [[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: [[T4:%.*]] = bitcast i16* [[T0]] to i8*
+// CHECK-NEXT: [[T5:%.*]] = bitcast i16* [[T2]] 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]]
@@ -153,16 +151,14 @@ void f(B b1) {
// 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: [[T4:%.*]] = bitcast i16* [[T0]] to i8*
+// CHECK-NEXT: [[T5:%.*]] = bitcast i16* [[T2]] 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-LABEL: define linkonce_odr void @_ZN6PR66281BC2ERKS0_(%"struct.PR6628::B"* %this, %"struct.PR6628::B"* dereferenceable({{[0-9]+}})) unnamed_addr
// CHECK: call void @_ZN6PR66281TC1Ev
// CHECK: call void @_ZN6PR66281TC1Ev
// CHECK: call void @_ZN6PR66281AC2ERKS0_RKNS_1TES5_
diff --git a/test/CodeGenCXX/coverage.cpp b/test/CodeGenCXX/coverage.cpp
index 1f1611bd8fcd..88f74098efa8 100644
--- a/test/CodeGenCXX/coverage.cpp
+++ b/test/CodeGenCXX/coverage.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -emit-llvm -o - -test-coverage -femit-coverage-notes | FileCheck %s
+// RUN: %clang_cc1 %s -triple %itanium_abi_triple -emit-llvm -o - -test-coverage -femit-coverage-notes | FileCheck %s
extern "C" void test_name1() {}
void test_name2() {}
diff --git a/test/CodeGenCXX/ctor-dtor-alias.cpp b/test/CodeGenCXX/ctor-dtor-alias.cpp
index d8d1fab7cef3..d869a2bfd5d9 100644
--- a/test/CodeGenCXX/ctor-dtor-alias.cpp
+++ b/test/CodeGenCXX/ctor-dtor-alias.cpp
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 %s -triple i686-linux -emit-llvm -o - -mconstructor-aliases -O1 -disable-llvm-optzns | FileCheck %s
// RUN: %clang_cc1 %s -triple i686-linux -emit-llvm -o - -mconstructor-aliases | FileCheck --check-prefix=NOOPT %s
-// RUN: %clang_cc1 -cc1 -triple x86_64--netbsd -emit-llvm \
+// RUN: %clang_cc1 -triple x86_64--netbsd -emit-llvm \
// RUN: -mconstructor-aliases -O2 %s -o - | FileCheck --check-prefix=CHECK-RAUW %s
namespace test1 {
@@ -61,7 +61,7 @@ namespace test4 {
// 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
+ // NOOPT-DAG: define linkonce_odr void @_ZN5test41BD2Ev
struct A {
virtual ~A() {}
};
diff --git a/test/CodeGenCXX/cxx0x-defaulted-templates.cpp b/test/CodeGenCXX/cxx0x-defaulted-templates.cpp
index f4d5ccc0e331..6f4c53331d4d 100644
--- a/test/CodeGenCXX/cxx0x-defaulted-templates.cpp
+++ b/test/CodeGenCXX/cxx0x-defaulted-templates.cpp
@@ -1,16 +1,16 @@
-// RUN: %clang_cc1 -std=c++11 -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck %s
template <typename T>
struct X {
X();
};
-// CHECK: define {{.*}} @_ZN1XIbEC1Ev
// CHECK: define {{.*}} @_ZN1XIbEC2Ev
+// CHECK: define {{.*}} @_ZN1XIbEC1Ev
template <> X<bool>::X() = default;
-// CHECK: define weak_odr {{.*}} @_ZN1XIiEC1Ev
// CHECK: define weak_odr {{.*}} @_ZN1XIiEC2Ev
+// CHECK: define weak_odr {{.*}} @_ZN1XIiEC1Ev
template <typename T> X<T>::X() = default;
template X<int>::X();
diff --git a/test/CodeGenCXX/cxx0x-delegating-ctors.cpp b/test/CodeGenCXX/cxx0x-delegating-ctors.cpp
index c48e61fd14e0..dcc055696e4d 100644
--- a/test/CodeGenCXX/cxx0x-delegating-ctors.cpp
+++ b/test/CodeGenCXX/cxx0x-delegating-ctors.cpp
@@ -26,28 +26,30 @@ delegator::delegator() {
delegator::delegator(bool)
{}
-// CHECK: define {{.*}} @_ZN9delegatorC1Ec
-// CHECK: {{.*}} @_ZN9delegatorC1Eb
-// CHECK: void @__cxa_throw
-// CHECK: void @__clang_call_terminate
-// CHECK: {{.*}} @_ZN9delegatorD1Ev
-// CHECK: define {{.*}} @_ZN9delegatorC2Ec
+// CHECK-LABEL: define {{.*}} @_ZN9delegatorC2Ec
// CHECK: {{.*}} @_ZN9delegatorC2Eb
// CHECK: void @__cxa_throw
// CHECK: void @__clang_call_terminate
// CHECK: {{.*}} @_ZN9delegatorD2Ev
+
+// CHECK-LABEL: define {{.*}} @_ZN9delegatorC1Ec
+// CHECK: {{.*}} @_ZN9delegatorC1Eb
+// CHECK: void @__cxa_throw
+// CHECK: void @__clang_call_terminate
+// CHECK: {{.*}} @_ZN9delegatorD1Ev
delegator::delegator(char)
: delegator(true) {
throw 0;
}
-// CHECK: define {{.*}} @_ZN9delegatorC1Ei
-// CHECK: {{.*}} @_ZN9delegatorC1Ev
+// CHECK-LABEL: define {{.*}} @_ZN9delegatorC2Ei
+// CHECK: {{.*}} @_ZN9delegatorC2Ev
// CHECK-NOT: void @_ZSt9terminatev
// CHECK: ret
// CHECK-NOT: void @_ZSt9terminatev
-// CHECK: define {{.*}} @_ZN9delegatorC2Ei
-// CHECK: {{.*}} @_ZN9delegatorC2Ev
+
+// CHECK-LABEL: define {{.*}} @_ZN9delegatorC1Ei
+// CHECK: {{.*}} @_ZN9delegatorC1Ev
// CHECK-NOT: void @_ZSt9terminatev
// CHECK: ret
// CHECK-NOT: void @_ZSt9terminatev
diff --git a/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist-pr12086.cpp b/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist-pr12086.cpp
index 091d7b70117c..91e913e8ea56 100644
--- a/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist-pr12086.cpp
+++ b/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist-pr12086.cpp
@@ -55,78 +55,78 @@ 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: @_ZGR6nested0_ = 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: @_ZGR6nested_ = private constant [3 x {{.*}}] [
+// CHECK-STATIC-BL: {{.*}} { i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested0_, 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-STATIC-BL: @nested = global {{.*}} { {{.*}} getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested_, 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: @_ZGR6nested_ = private global [3 x
+// CHECK-DYNAMIC-BL: @_ZGR6nested0_ = private global [2 x i32] zeroinitializer
+// CHECK-DYNAMIC-BL: @_ZGR6nested1_ = private global [2 x i32] zeroinitializer
+// CHECK-DYNAMIC-BL: @_ZGR6nested2_ = private global [2 x i32] zeroinitializer
+// CHECK-DYNAMIC-BL: store i32 1, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested0_, i64 0, i64 0)
+// CHECK-DYNAMIC-BL: store i32 {{.*}}, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested0_, i64 0, i64 1)
+// CHECK-DYNAMIC-BL: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested0_, i64 0, i64 0),
+// CHECK-DYNAMIC-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]* @_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-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]* @_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 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: @_ZGR6nested0_ = 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: @_ZGR6nested_ = private constant [3 x {{.*}}] [
+// CHECK-STATIC-BE: {{.*}} { i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested0_, i32 0, i32 0),
+// CHECK-STATIC-BE: i32* bitcast (i8* getelementptr (i8* bitcast ([2 x i32]* @_ZGR6nested0_ 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-STATIC-BE: @nested = global {{.*}} { {{.*}} getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested_, i32 0, i32 0),
+// CHECK-STATIC-BE: {{.*}} bitcast ({{.*}}* getelementptr (i8* bitcast ([3 x {{.*}}]* @_ZGR6nested_ 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: @_ZGR6nested_ = private global [3 x
+// CHECK-DYNAMIC-BE: @_ZGR6nested0_ = private global [2 x i32] zeroinitializer
+// CHECK-DYNAMIC-BE: @_ZGR6nested1_ = private global [2 x i32] zeroinitializer
+// CHECK-DYNAMIC-BE: @_ZGR6nested2_ = private global [2 x i32] zeroinitializer
+// CHECK-DYNAMIC-BE: store i32 1, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested0_, i64 0, i64 0)
+// CHECK-DYNAMIC-BE: store i32 {{.*}}, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested0_, i64 0, i64 1)
+// CHECK-DYNAMIC-BE: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested0_, i64 0, i64 0),
+// CHECK-DYNAMIC-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]* @_ZGR6nested0_, i64 1, i64 0),
+// CHECK-DYNAMIC-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]* @_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-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]* @_ZGR6nested1_, 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]* @_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 2, 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 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: 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 8e0d161bc0f4..5a48346be758 100644
--- a/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist-startend.cpp
+++ b/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist-startend.cpp
@@ -32,8 +32,8 @@ namespace std {
};
}
-// CHECK: @_ZGR15globalInitList1 = private constant [3 x i32] [i32 1, i32 2, i32 3]
-// CHECK: @globalInitList1 = global {{[^ ]+}} { i32* getelementptr inbounds ([3 x i32]* @_ZGR15globalInitList1, {{[^)]*}}), 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) {
diff --git a/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp b/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp
index 164cbce027ef..4d30344e3c8d 100644
--- a/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp
+++ b/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -std=c++11 -S -triple x86_64-none-linux-gnu -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-none-linux-gnu -emit-llvm -o - %s | FileCheck %s
namespace std {
typedef decltype(sizeof(int)) size_t;
@@ -47,8 +47,8 @@ struct wantslist1 {
~wantslist1();
};
-// 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 }
+// 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 {
@@ -57,12 +57,12 @@ namespace thread_local_global_array {
// 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]
+ // 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: @globalInitList2 = global %{{[^ ]+}} zeroinitializer
-// CHECK: @_ZGR15globalInitList2 = private global [2 x %[[WITHARG:[^ ]*]]] zeroinitializer
+// CHECK: @_ZGR15globalInitList2_ = private global [2 x %[[WITHARG:[^ ]*]]] zeroinitializer
// CHECK: @_ZN15partly_constant1kE = global i32 0, align 4
// CHECK: @_ZN15partly_constant2ilE = global {{.*}} null, align 8
@@ -77,16 +77,16 @@ namespace thread_local_global_array {
// 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: 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: 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: 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
@@ -384,7 +384,7 @@ namespace partly_constant {
// 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: store i64 4, i64* getelementptr inbounds ({{.*}}* @_ZGRN15partly_constant2ilE4_, i64 0, i64 2, i32 1)
// CHECK-NOT: @[[PARTLY_CONSTANT_THIRD]],
//
// Outer init list.
@@ -431,3 +431,37 @@ namespace nested {
// CHECK: }
}
}
+
+namespace DR1070 {
+ struct A {
+ A(std::initializer_list<int>);
+ };
+ struct B {
+ int i;
+ A a;
+ };
+ B b = {1};
+ struct C {
+ std::initializer_list<int> a;
+ B b;
+ std::initializer_list<double> c;
+ };
+ C c = {};
+}
+
+namespace ArrayOfInitList {
+ struct S {
+ S(std::initializer_list<int>);
+ };
+ S x[1] = {};
+}
+
+namespace PR20445 {
+ struct vector { vector(std::initializer_list<int>); };
+ struct MyClass { explicit MyClass(const vector &v); };
+ template<int x> void f() { new MyClass({42, 43}); }
+ template void f<0>();
+ // CHECK-LABEL: define {{.*}} @_ZN7PR204451fILi0EEEvv(
+ // CHECK: call void @_ZN7PR204456vectorC1ESt16initializer_listIiE(
+ // CHECK: call void @_ZN7PR204457MyClassC1ERKNS_6vectorE(
+}
diff --git a/test/CodeGenCXX/cxx11-exception-spec.cpp b/test/CodeGenCXX/cxx11-exception-spec.cpp
index 96ea1d7f00ed..3b1516b92536 100644
--- a/test/CodeGenCXX/cxx11-exception-spec.cpp
+++ b/test/CodeGenCXX/cxx11-exception-spec.cpp
@@ -1,4 +1,5 @@
-// RUN: not %clang_cc1 -std=c++11 -emit-llvm %s -o - -verify -fexceptions -fcxx-exceptions -triple x86_64-linux-gnu | FileCheck %s
+// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -verify -fexceptions -fcxx-exceptions -triple x86_64-linux-gnu | FileCheck %s
+// expected-no-diagnostics
void h();
diff --git a/test/CodeGenCXX/cxx11-initializer-aggregate.cpp b/test/CodeGenCXX/cxx11-initializer-aggregate.cpp
index acc77825ae84..789970b58b53 100644
--- a/test/CodeGenCXX/cxx11-initializer-aggregate.cpp
+++ b/test/CodeGenCXX/cxx11-initializer-aggregate.cpp
@@ -20,6 +20,25 @@ int &fn2(int &v) {
// CHECK: %[[INITLIST2:.*]] = alloca %struct.B, align 8
// CHECK: %[[R:.*]] = getelementptr inbounds %struct.B* %[[INITLIST2:.*]], i32 0, i32 0
// CHECK: store i32* %{{.*}}, i32** %[[R]], align 8
- // CHECK: call i32* @_ZN1B1fEv(%struct.B* %[[INITLIST2:.*]])
+ // CHECK: call dereferenceable({{[0-9]+}}) i32* @_ZN1B1fEv(%struct.B* %[[INITLIST2:.*]])
return B{v}.f();
}
+
+// CHECK: define {{.*}}@__cxx_global_var_init(
+//
+// CHECK: call {{.*}}@_ZN14NonTrivialInit1AC1Ev(
+// CHECK: getelementptr inbounds {{.*}}, i64 1
+// CHECK: br i1
+//
+// CHECK: getelementptr inbounds {{.*}}, i64 1
+// CHECK: icmp eq {{.*}}, i64 30
+// CHECK: br i1
+//
+// CHECK: call i32 @__cxa_atexit(
+namespace NonTrivialInit {
+ struct A { A(); A(const A&) = delete; ~A(); };
+ struct B { A a[20]; };
+ // NB, this must be large enough to be worth memsetting for this test to be
+ // meaningful.
+ B b[30] = {};
+}
diff --git a/test/CodeGenCXX/cxx11-initializer-array-new.cpp b/test/CodeGenCXX/cxx11-initializer-array-new.cpp
index 23577bec661a..2393939b031d 100644
--- a/test/CodeGenCXX/cxx11-initializer-array-new.cpp
+++ b/test/CodeGenCXX/cxx11-initializer-array-new.cpp
@@ -28,7 +28,7 @@ void *p = new S[2][3]{ { 1, 2, 3 }, { 4, 5, 6 } };
//
// { 4, 5, 6 }
//
-// CHECK: %[[S_1:.*]] = getelementptr [3 x %[[S]]]* %[[S_0]], i32 1
+// CHECK: %[[S_1:.*]] = getelementptr inbounds [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)
@@ -56,7 +56,6 @@ void *q = new S[n][3]{ { 1, 2, 3 }, { 4, 5, 6 } };
// 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:
//
@@ -73,7 +72,7 @@ void *q = new S[n][3]{ { 1, 2, 3 }, { 4, 5, 6 } };
//
// { 4, 5, 6 }
//
-// CHECK: %[[S_1:.*]] = getelementptr [3 x %[[S]]]* %[[S_0]], i32 1
+// CHECK: %[[S_1:.*]] = getelementptr inbounds [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)
@@ -82,25 +81,80 @@ void *q = new S[n][3]{ { 1, 2, 3 }, { 4, 5, 6 } };
// 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
+// And the rest.
+//
+// CHECK: %[[S_2:.*]] = getelementptr inbounds [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: %[[REST:.*]] = sub i64 %[[ELTS]], 6
+// CHECK: icmp eq i64 %[[REST]], 0
+// CHECK: br i1
//
-// CHECK: %[[END_INNER:.*]] = getelementptr inbounds %[[S]]* %{{.*}}, i64 3
+// CHECK: %[[END:.*]] = getelementptr inbounds %[[S]]* %[[S_2_AS_S]], i64 %[[REST]]
// CHECK: br label
//
-// S[3] initialization loop:
+// CHECK: %[[CUR:.*]] = phi %[[S]]* [ %[[S_2_AS_S]], {{.*}} ], [ %[[NEXT:.*]], {{.*}} ]
+// CHECK: call void @_ZN1SC1Ev(%[[S]]* %[[CUR]])
+// CHECK: %[[NEXT]] = getelementptr inbounds %[[S]]* %[[CUR]], i64 1
+// CHECK: icmp eq %[[S]]* %[[NEXT]], %[[END]]
+// CHECK: br i1
//
-// 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: }
+
+struct T { int a; };
+void *r = new T[n][3]{ { 1, 2, 3 }, { 4, 5, 6 } };
+
+// CHECK-LABEL: define
//
-// CHECK: %[[NEXT_OUTER:.*]] = getelementptr %[[S]]* %{{.*}}, i32 1
-// CHECK: icmp eq %[[S]]* %[[NEXT_OUTER]], %[[END_AS_S]]
-// CHECK: br i1
+// CHECK: load i32* @n
+// CHECK: call {{.*}} @llvm.umul.with.overflow.i64(i64 %[[N:.*]], i64 12)
+// CHECK: %[[ELTS:.*]] = mul i64 %[[N]], 3
+//
+// No cookie.
+// CHECK-NOT: @llvm.uadd.with.overflow
+//
+// CHECK: %[[ALLOC:.*]] = call noalias i8* @_Znam(i64 %{{.*}})
+//
+// CHECK: %[[START_AS_T:.*]] = bitcast i8* %[[ALLOC]] to %[[T:.*]]*
+//
+// Explicit initializers:
+//
+// { 1, 2, 3 }
+//
+// CHECK: %[[T_0:.*]] = bitcast %[[T]]* %[[START_AS_T]] to [3 x %[[T]]]*
+//
+// CHECK: %[[T_0_0:.*]] = getelementptr inbounds [3 x %[[T]]]* %[[T_0]], i64 0, i64 0
+// CHECK: %[[T_0_0_0:.*]] = getelementptr inbounds %[[T]]* %[[T_0_0]], i32 0, i32 0
+// CHECK: store i32 1, i32* %[[T_0_0_0]]
+// CHECK: %[[T_0_1:.*]] = getelementptr inbounds %[[T]]* %[[T_0_0]], i64 1
+// CHECK: %[[T_0_1_0:.*]] = getelementptr inbounds %[[T]]* %[[T_0_1]], i32 0, i32 0
+// CHECK: store i32 2, i32* %[[T_0_1_0]]
+// CHECK: %[[T_0_2:.*]] = getelementptr inbounds %[[T]]* %[[T_0_1]], i64 1
+// CHECK: %[[T_0_2_0:.*]] = getelementptr inbounds %[[T]]* %[[T_0_2]], i32 0, i32 0
+// CHECK: store i32 3, i32* %[[T_0_2_0]]
+//
+// { 4, 5, 6 }
+//
+// CHECK: %[[T_1:.*]] = getelementptr inbounds [3 x %[[T]]]* %[[T_0]], i32 1
+//
+// CHECK: %[[T_1_0:.*]] = getelementptr inbounds [3 x %[[T]]]* %[[T_1]], i64 0, i64 0
+// CHECK: %[[T_1_0_0:.*]] = getelementptr inbounds %[[T]]* %[[T_1_0]], i32 0, i32 0
+// CHECK: store i32 4, i32* %[[T_1_0_0]]
+// CHECK: %[[T_1_1:.*]] = getelementptr inbounds %[[T]]* %[[T_1_0]], i64 1
+// CHECK: %[[T_1_1_0:.*]] = getelementptr inbounds %[[T]]* %[[T_1_1]], i32 0, i32 0
+// CHECK: store i32 5, i32* %[[T_1_1_0]]
+// CHECK: %[[T_1_2:.*]] = getelementptr inbounds %[[T]]* %[[T_1_1]], i64 1
+// CHECK: %[[T_1_2_0:.*]] = getelementptr inbounds %[[T]]* %[[T_1_2]], i32 0, i32 0
+// CHECK: store i32 6, i32* %[[T_1_2_0]]
+//
+// And the rest gets memset to 0.
+//
+// CHECK: %[[T_2:.*]] = getelementptr inbounds [3 x %[[T]]]* %[[T_1]], i32 1
+// CHECK: %[[T_2_AS_T:.*]] = bitcast [3 x %[[T]]]* %[[T_2]] to %[[T]]*
+//
+// CHECK: %[[SIZE:.*]] = sub i64 %{{.*}}, 24
+// CHECK: %[[REST:.*]] = bitcast %[[T]]* %[[T_2_AS_T]] to i8*
+// CHECK: call void @llvm.memset.p0i8.i64(i8* %[[REST]], i8 0, i64 %[[SIZE]], i32 4, i1 false)
//
// CHECK: }
+
diff --git a/test/CodeGenCXX/cxx11-noreturn.cpp b/test/CodeGenCXX/cxx11-noreturn.cpp
index 31c651d75efc..b876bb9661ba 100644
--- a/test/CodeGenCXX/cxx11-noreturn.cpp
+++ b/test/CodeGenCXX/cxx11-noreturn.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm -std=c++11 %s -o - | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -std=c++11 %s -o - | FileCheck %s
int g();
diff --git a/test/CodeGenCXX/cxx11-thread-local-reference.cpp b/test/CodeGenCXX/cxx11-thread-local-reference.cpp
index 7759d41b0f92..4143164d91ca 100644
--- a/test/CodeGenCXX/cxx11-thread-local-reference.cpp
+++ b/test/CodeGenCXX/cxx11-thread-local-reference.cpp
@@ -10,10 +10,10 @@ thread_local int &r = f();
int &g() { return r; }
// CHECK: define {{.*}} @[[R_INIT:.*]]()
-// CHECK: call i32* @_Z1fv()
+// CHECK: call dereferenceable({{[0-9]+}}) i32* @_Z1fv()
// CHECK: store i32* %{{.*}}, i32** @r, align 8
-// CHECK-LABEL: define i32* @_Z1gv()
+// CHECK-LABEL: define dereferenceable({{[0-9]+}}) i32* @_Z1gv()
// CHECK: call i32* @_ZTW1r()
// CHECK: ret i32* %{{.*}}
diff --git a/test/CodeGenCXX/cxx11-thread-local.cpp b/test/CodeGenCXX/cxx11-thread-local.cpp
index 509562dd8fc1..a3690b352989 100644
--- a/test/CodeGenCXX/cxx11-thread-local.cpp
+++ b/test/CodeGenCXX/cxx11-thread-local.cpp
@@ -21,7 +21,7 @@ template<typename T> thread_local int V<T>::m = g();
// CHECK: @e = global i32 0
int e = V<int>::m;
-// CHECK: @_ZN1VIiE1mE = weak_odr thread_local global i32 0
+// CHECK: @_ZN1VIiE1mE = linkonce_odr thread_local global i32 0
// CHECK: @_ZZ1fvE1n = internal thread_local global i32 0
@@ -35,9 +35,9 @@ int e = V<int>::m;
// CHECK: @_ZZ8tls_dtorvE1u = internal thread_local global
// CHECK: @_ZGVZ8tls_dtorvE1u = internal thread_local global i8 0
-// CHECK: @_ZGRZ8tls_dtorvE1u = private thread_local global
+// CHECK: @_ZGRZ8tls_dtorvE1u_ = internal thread_local global
-// CHECK: @_ZGVN1VIiE1mE = weak_odr thread_local global i64 0
+// CHECK: @_ZGVN1VIiE1mE = linkonce_odr thread_local global i64 0
// CHECK: @__tls_guard = internal thread_local global i8 0
@@ -46,7 +46,7 @@ int e = V<int>::m;
// CHECK: @_ZTH1a = alias void ()* @__tls_init
// CHECK: @_ZTHL1d = alias internal void ()* @__tls_init
// CHECK: @_ZTHN1U1mE = alias void ()* @__tls_init
-// CHECK: @_ZTHN1VIiE1mE = alias weak_odr void ()* @__tls_init
+// CHECK: @_ZTHN1VIiE1mE = alias linkonce_odr void ()* @__tls_init
// Individual variable initialization functions:
@@ -120,8 +120,8 @@ void tls_dtor() {
static thread_local T t;
// CHECK: load i8* @_ZGVZ8tls_dtorvE1u
- // CHECK: call void @_ZN1SC1Ev(%struct.S* @_ZGRZ8tls_dtorvE1u)
- // CHECK: call i32 @__cxa_thread_atexit({{.*}}@_ZN1SD1Ev {{.*}} @_ZGRZ8tls_dtorvE1u{{.*}} @__dso_handle
+ // CHECK: call void @_ZN1SC1Ev(%struct.S* @_ZGRZ8tls_dtorvE1u_)
+ // CHECK: call i32 @__cxa_thread_atexit({{.*}}@_ZN1SD1Ev {{.*}} @_ZGRZ8tls_dtorvE1u_{{.*}} @__dso_handle
// CHECK: store i8 1, i8* @_ZGVZ8tls_dtorvE1u
static thread_local const S &u = S();
}
@@ -135,6 +135,24 @@ int PR15991() {
return l();
}
+struct PR19254 {
+ static thread_local int n;
+ int f();
+};
+// CHECK: define {{.*}} @_ZN7PR192541fEv(
+int PR19254::f() {
+ // CHECK: call void @_ZTHN7PR192541nE(
+ return this->n;
+}
+
+namespace {
+thread_local int anon_i{1};
+}
+void set_anon_i() {
+ anon_i = 2;
+}
+// CHECK-LABEL: define internal i32* @_ZTWN12_GLOBAL__N_16anon_iE()
+
// CHECK: define {{.*}} @[[V_M_INIT:.*]]()
// CHECK: load i8* bitcast (i64* @_ZGVN1VIiE1mE to i8*)
// CHECK: %[[V_M_INITIALIZED:.*]] = icmp eq i8 %{{.*}}, 0
@@ -171,7 +189,7 @@ int PR15991() {
// CHECK: declare extern_weak void @_ZTH1b()
-// CHECK-LABEL: define internal hidden i32* @_ZTWL1d()
+// CHECK-LABEL: define internal i32* @_ZTWL1d()
// CHECK: call void @_ZTHL1d()
// CHECK: ret i32* @_ZL1d
diff --git a/test/CodeGenCXX/cxx11-unrestricted-union.cpp b/test/CodeGenCXX/cxx11-unrestricted-union.cpp
index 0397775b7e3c..2f22ad2f964a 100644
--- a/test/CodeGenCXX/cxx11-unrestricted-union.cpp
+++ b/test/CodeGenCXX/cxx11-unrestricted-union.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++11 -emit-llvm %s -o - | FileCheck %s
struct A {
A(); A(const A&); A(A&&); A &operator=(const A&); A &operator=(A&&); ~A();
diff --git a/test/CodeGenCXX/cxx1y-initializer-aggregate.cpp b/test/CodeGenCXX/cxx1y-initializer-aggregate.cpp
index ae49a047f624..8bdf8633d61e 100644
--- a/test/CodeGenCXX/cxx1y-initializer-aggregate.cpp
+++ b/test/CodeGenCXX/cxx1y-initializer-aggregate.cpp
@@ -46,7 +46,7 @@ B z { 1 };
// CHECK: store i8 %{{.*}}, i8* getelementptr inbounds ({{.*}} @a, i32 0, i32 2)
// CHECK: call i32 @_ZN1A1fEv({{.*}} @a)
// CHECK: store i32 %{{.*}}, i32* getelementptr inbounds ({{.*}}* @a, i32 0, i32 3)
-// CHECK: call void @{{.*}}C1Ev({{.*}} getelementptr inbounds (%struct.A* @a, i32 0, i32 4))
+// CHECK: store double 1.000000e+00, double* getelementptr inbounds ({{.*}} @a, i32 0, i32 4, i32 0)
// No dynamic initialization of 'b':
diff --git a/test/CodeGenCXX/cxx1y-variable-template.cpp b/test/CodeGenCXX/cxx1y-variable-template.cpp
index d1e70603e280..cd73817d8508 100644
--- a/test/CodeGenCXX/cxx1y-variable-template.cpp
+++ b/test/CodeGenCXX/cxx1y-variable-template.cpp
@@ -18,7 +18,7 @@ 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: @_ZN5OuterIA100_cE5InnerIA20_cE3arrIA3_cEE = linkonce_odr global [123 x i32] zeroinitializer
+// CHECK: @_ZGVN5OuterIA100_cE5InnerIA20_cE3arrIA3_cEE = linkonce_odr global
// CHECK: call {{.*}}@_Z8init_arrv
diff --git a/test/CodeGenCXX/debug-info-alias.cpp b/test/CodeGenCXX/debug-info-alias.cpp
new file mode 100644
index 000000000000..fb18ac5da006
--- /dev/null
+++ b/test/CodeGenCXX/debug-info-alias.cpp
@@ -0,0 +1,37 @@
+// RUN: %clang -g -std=c++11 -S -emit-llvm %s -o - | FileCheck %s
+
+template<typename T>
+struct foo {
+};
+namespace x {
+// splitting these over multiple lines to make sure the right token is used for
+// the location
+template<typename T>
+using
+# 42
+bar
+= foo<T*>;
+}
+
+// CHECK: metadata [[BINT:![0-9]*]], i32 0, i32 1, {{.*}} ; [ DW_TAG_variable ] [bi]
+// CHECK: [[BINT]] = {{.*}} ; [ DW_TAG_typedef ] [bar<int>] [line 42
+x::bar<int> bi;
+// CHECK: metadata [[BFLOAT:![0-9]*]], i32 0, i32 1, {{.*}} ; [ DW_TAG_variable ] [bf]
+// CHECK: [[BFLOAT]] = {{.*}} ; [ DW_TAG_typedef ] [bar<float>] [line 42
+x::bar<float> bf;
+
+using
+// CHECK: metadata [[NARF:![0-9]*]], i32 0, i32 1, {{.*}} ; [ DW_TAG_variable ] [n]
+# 142
+narf // CHECK: [[NARF]] = {{.*}} ; [ DW_TAG_typedef ] [narf] [line 142
+= int;
+narf n;
+
+template <typename T>
+using tv = void;
+// CHECK: null} ; [ DW_TAG_typedef ] [tv<int>] {{.*}} [from ]
+tv<int> *tvp;
+
+using v = void;
+// CHECK: null} ; [ DW_TAG_typedef ] [v] {{.*}} [from ]
+v *vp;
diff --git a/test/CodeGenCXX/debug-info-anon-union-vars.cpp b/test/CodeGenCXX/debug-info-anon-union-vars.cpp
new file mode 100644
index 000000000000..396b7e94a8ea
--- /dev/null
+++ b/test/CodeGenCXX/debug-info-anon-union-vars.cpp
@@ -0,0 +1,28 @@
+// RUN: %clang_cc1 -emit-llvm -gdwarf-4 -triple x86_64-linux-gnu %s -o - | FileCheck %s
+
+// Make sure that we emit a global variable for each of the members of the
+// anonymous union.
+
+static union {
+ int c;
+ int d;
+ union {
+ int a;
+ };
+ struct {
+ int b;
+ };
+};
+
+int test_it() {
+ c = 1;
+ d = 2;
+ a = 4;
+ return (c == 1);
+}
+
+// CHECK: [[FILE:.*]] = {{.*}}[ DW_TAG_file_type ] [{{.*}}debug-info-anon-union-vars.cpp]
+// CHECK: [[FILE]]{{.*}}[ DW_TAG_variable ] [c] [line 6] [local] [def]
+// CHECK: [[FILE]]{{.*}}[ DW_TAG_variable ] [d] [line 6] [local] [def]
+// CHECK: [[FILE]]{{.*}}[ DW_TAG_variable ] [a] [line 6] [local] [def]
+// CHECK: [[FILE]]{{.*}}[ DW_TAG_variable ] [b] [line 6] [local] [def]
diff --git a/test/CodeGenCXX/debug-info-byval.cpp b/test/CodeGenCXX/debug-info-byval.cpp
index e6317fc2de0e..5b0850b9643c 100644
--- a/test/CodeGenCXX/debug-info-byval.cpp
+++ b/test/CodeGenCXX/debug-info-byval.cpp
@@ -1,4 +1,5 @@
-// RUN: %clang -g -S %s -o - | FileCheck %s
+// FIXME: Check IR rather than asm, then triple is not needed.
+// RUN: %clang -Xclang -triple=%itanium_abi_triple -g -S %s -o - | FileCheck %s
// Test to check presence of debug info for byval parameter.
// Radar 8350436.
class DAG {
diff --git a/test/CodeGenCXX/debug-info-char16.cpp b/test/CodeGenCXX/debug-info-char16.cpp
index 06a05b31dd1c..e6e2f1521bd7 100644
--- a/test/CodeGenCXX/debug-info-char16.cpp
+++ b/test/CodeGenCXX/debug-info-char16.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm -std=c++11 -g %s -o -| FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -std=c++11 -g %s -o -| FileCheck %s
// 16 is DW_ATE_UTF (0x10) encoding attribute.
char16_t char_a = u'h';
diff --git a/test/CodeGenCXX/debug-info-class-limited-plugin.test b/test/CodeGenCXX/debug-info-class-limited-plugin.test
new file mode 100644
index 000000000000..61d258d9ffc4
--- /dev/null
+++ b/test/CodeGenCXX/debug-info-class-limited-plugin.test
@@ -0,0 +1,2 @@
+RUN: %clang_cc1 -emit-llvm -fno-standalone-debug -g -o - -load %llvmshlibdir/PrintFunctionNames%pluginext -add-plugin print-function-names %S/Inputs/debug-info-class-limited.cpp 2>&1 | FileCheck %S/Inputs/debug-info-class-limited.cpp
+REQUIRES: plugins, examples
diff --git a/test/CodeGenCXX/debug-info-class-limited.test b/test/CodeGenCXX/debug-info-class-limited.test
new file mode 100644
index 000000000000..0b10728f3c97
--- /dev/null
+++ b/test/CodeGenCXX/debug-info-class-limited.test
@@ -0,0 +1 @@
+RUN: %clang_cc1 -emit-llvm -fno-standalone-debug -g %S/Inputs/debug-info-class-limited.cpp -o - | FileCheck %S/Inputs/debug-info-class-limited.cpp
diff --git a/test/CodeGenCXX/debug-info-class-nolimit.cpp b/test/CodeGenCXX/debug-info-class-nolimit.cpp
index ce72bd347cab..7a6ee4d441a9 100644
--- a/test/CodeGenCXX/debug-info-class-nolimit.cpp
+++ b/test/CodeGenCXX/debug-info-class-nolimit.cpp
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 -triple x86_64-unk-unk -fno-limit-debug-info -o - -emit-llvm -g %s | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-unk-unk -fstandalone-debug -o - -emit-llvm -g %s | FileCheck %s
+// On Darwin, this should be the default:
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -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
diff --git a/test/CodeGenCXX/debug-info-class.cpp b/test/CodeGenCXX/debug-info-class.cpp
index e1402c96f043..34add0432c49 100644
--- a/test/CodeGenCXX/debug-info-class.cpp
+++ b/test/CodeGenCXX/debug-info-class.cpp
@@ -102,13 +102,9 @@ int main(int argc, char **argv) {
// 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 !"_ZTS1D"} ; [ DW_TAG_structure_type ] [D] {{.*}} [decl]
// 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: [[F:![0-9]*]] = {{.*}} null, i32 0, null, null, metadata !"_ZTS1F"} ; [ DW_TAG_structure_type ] [F] {{.*}} [decl]
// 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]
@@ -118,8 +114,13 @@ int main(int argc, char **argv) {
// CHECK: ; [ DW_TAG_structure_type ] [A]
// CHECK: HdrSize
// CHECK: ; [ DW_TAG_structure_type ] [I] {{.*}} [def]
+//
+// CHECK: metadata !"_ZTS1D", {{.*}}, metadata [[D_FUNC_DECL:![0-9]*]], metadata {{![0-9]*}}, i32 {{[0-9]*}}} ; [ DW_TAG_subprogram ] {{.*}} [def] [func]
+// CHECK: [[D_FUNC_DECL]] = {{.*}}, metadata !"_ZTS1D", {{.*}}, i32 0, null, i32 {{[0-9]*}}} ; [ DW_TAG_subprogram ] {{.*}} [func]
-// CHECK: [[F_I_DEF:![0-9]*]] = {{.*}}, metadata [[F_I]]} ; [ DW_TAG_variable ] [i]
+// CHECK: [[F_I_DEF:![0-9]*]] = {{.*}}, metadata [[F_I:![0-9]*]]} ; [ DW_TAG_variable ] [i]
+
+// CHECK: [[F_I]] = {{.*}}, metadata !"_ZTS1F", {{.*}} ; [ DW_TAG_member ] [i]
// CHECK: ![[EXCEPTLOC]] = metadata !{i32 84,
// CHECK: ![[RETLOC]] = metadata !{i32 83,
diff --git a/test/CodeGenCXX/debug-info-ctor2.cpp b/test/CodeGenCXX/debug-info-ctor2.cpp
index 19bd64b3cdad..3bc931e98448 100644
--- a/test/CodeGenCXX/debug-info-ctor2.cpp
+++ b/test/CodeGenCXX/debug-info-ctor2.cpp
@@ -1,4 +1,5 @@
-// RUN: %clang -fverbose-asm -g -S %s -o - | grep AT_explicit
+// FIXME: Check IR rather than asm, then triple is not needed.
+// RUN: %clang -Xclang -triple=%itanium_abi_triple -fverbose-asm -g -S %s -o - | grep AT_explicit
class MyClass
diff --git a/test/CodeGenCXX/debug-info-dup-fwd-decl.cpp b/test/CodeGenCXX/debug-info-dup-fwd-decl.cpp
index 04fe7a03e168..1b9a055527d0 100644
--- a/test/CodeGenCXX/debug-info-dup-fwd-decl.cpp
+++ b/test/CodeGenCXX/debug-info-dup-fwd-decl.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm -g -triple x86_64-apple-darwin -fno-limit-debug-info %s -o - | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -g -triple x86_64-apple-darwin -fstandalone-debug %s -o - | FileCheck %s
class Test
{
diff --git a/test/CodeGenCXX/debug-info-enum-class.cpp b/test/CodeGenCXX/debug-info-enum-class.cpp
index 0f4b09afb5dd..f0b97ccd2c8e 100644
--- a/test/CodeGenCXX/debug-info-enum-class.cpp
+++ b/test/CodeGenCXX/debug-info-enum-class.cpp
@@ -12,7 +12,6 @@ D d;
// 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.
@@ -27,3 +26,54 @@ namespace PR14029 {
};
Test<int> t;
}
+
+namespace test2 {
+// FIXME: this should just be a declaration under -fno-standalone-debug
+// CHECK: metadata !{i32 {{[^,]*}}, {{[^,]*}}, metadata [[TEST2:![0-9]*]], {{.*}}, metadata [[TEST_ENUMS:![0-9]*]], {{[^,]*}}, null, null, metadata !"_ZTSN5test21EE"} ; [ DW_TAG_enumeration_type ] [E]
+// CHECK: [[TEST2]] = {{.*}} ; [ DW_TAG_namespace ] [test2]
+// CHECK: [[TEST_ENUMS]] = metadata !{metadata [[TEST_E:![0-9]*]]}
+// CHECK: [[TEST_E]] = {{.*}}, metadata !"e", i64 0} ; [ DW_TAG_enumerator ] [e :: 0]
+enum E : int;
+void func(E *) {
+}
+enum E : int { e };
+}
+
+namespace test3 {
+// FIXME: this should just be a declaration under -fno-standalone-debug
+// CHECK: metadata !{i32 {{[^,]*}}, {{[^,]*}}, metadata [[TEST3:![0-9]*]], {{.*}}, metadata [[TEST_ENUMS]], {{[^,]*}}, null, null, metadata !"_ZTSN5test31EE"} ; [ DW_TAG_enumeration_type ] [E]
+// CHECK: [[TEST3]] = {{.*}} ; [ DW_TAG_namespace ] [test3]
+enum E : int { e };
+void func(E *) {
+}
+}
+
+namespace test4 {
+// CHECK: metadata !{i32 {{[^,]*}}, {{[^,]*}}, metadata [[TEST4:![0-9]*]], {{.*}}, metadata [[TEST_ENUMS]], {{[^,]*}}, null, null, metadata !"_ZTSN5test41EE"} ; [ DW_TAG_enumeration_type ] [E]
+// CHECK: [[TEST4]] = {{.*}} ; [ DW_TAG_namespace ] [test4]
+enum E : int;
+void f1(E *) {
+}
+enum E : int { e };
+void f2(E) {
+}
+}
+
+// CHECK: ; [ DW_TAG_enumeration_type ] [D] [line 6, size 16, align 16, offset 0] [decl] [from ]
+
+namespace test5 {
+// CHECK: metadata !{i32 {{[^,]*}}, {{[^,]*}}, metadata [[TEST5:![0-9]*]], {{.*}}, null, {{[^,]*}}, null, null, metadata !"_ZTSN5test51EE"} ; [ DW_TAG_enumeration_type ] [E]
+// CHECK: [[TEST5]] = {{.*}} ; [ DW_TAG_namespace ] [test5]
+enum E : int;
+void f1(E *) {
+}
+}
+
+namespace test6 {
+// Ensure typedef'd enums aren't manifest by debug info generation.
+// This could cause "typedef changes linkage of anonymous type, but linkage was
+// already computed" errors.
+// CHECK-NOT: test7
+typedef enum {
+} E;
+}
diff --git a/test/CodeGenCXX/debug-info-enum.cpp b/test/CodeGenCXX/debug-info-enum.cpp
index f0e2608db856..810c3ee7ae9b 100644
--- a/test/CodeGenCXX/debug-info-enum.cpp
+++ b/test/CodeGenCXX/debug-info-enum.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm -g %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -g %s -o - | FileCheck %s
// CHECK: [[ENUMS:![0-9]*]], {{[^,]*}}, {{[^,]*}}, {{[^,]*}}, {{[^,]*}}, {{[^,]*}}} ; [ DW_TAG_compile_unit ]
// CHECK: [[ENUMS]] = metadata !{metadata [[E1:![0-9]*]], metadata [[E2:![0-9]*]], metadata [[E3:![0-9]*]]}
@@ -34,3 +34,12 @@ void func() {
e x;
}
}
+
+namespace test4 {
+// Don't try to build debug info for a dependent enum.
+// CHECK-NOT: test4
+template <typename T>
+struct S {
+ enum e { E = T::v };
+};
+}
diff --git a/test/CodeGenCXX/debug-info-function-context.cpp b/test/CodeGenCXX/debug-info-function-context.cpp
index 4ca1c8d1eced..e65d3289f8b1 100644
--- a/test/CodeGenCXX/debug-info-function-context.cpp
+++ b/test/CodeGenCXX/debug-info-function-context.cpp
@@ -29,8 +29,8 @@ int global_namespace_variable = 1;
// 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 [[FILE:![0-9]*]], metadata !"global_function"{{.*}} [ DW_TAG_subprogram ] [line 17] [def] [global_function]
+// CHECK: [[FILE]] = {{.*}} [ 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]
+// CHECK: metadata [[NS:![0-9]*]], metadata !"global_namespace_function"{{.*}} [ DW_TAG_subprogram ] [line 20] [def] [global_namespace_function]
+// CHECK: [[NS]] = {{.*}} [ 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 7ecdeb2ec22e..b766c73cc22a 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 -gline-tables-only -S -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -fno-rtti -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.
diff --git a/test/CodeGenCXX/debug-info-global-ctor-dtor.cpp b/test/CodeGenCXX/debug-info-global-ctor-dtor.cpp
index afa77077a25d..28b1fab31bc7 100644
--- a/test/CodeGenCXX/debug-info-global-ctor-dtor.cpp
+++ b/test/CodeGenCXX/debug-info-global-ctor-dtor.cpp
@@ -1,6 +1,6 @@
-// RUN: %clang_cc1 %s -g -fno-use-cxa-atexit -S -emit-llvm -o - \
+// RUN: %clang_cc1 %s -g -triple %itanium_abi_triple -fno-use-cxa-atexit -S -emit-llvm -o - \
// RUN: | FileCheck %s --check-prefix=CHECK-NOKEXT
-// RUN: %clang_cc1 %s -g -fno-use-cxa-atexit -fapple-kext -S -emit-llvm -o - \
+// RUN: %clang_cc1 %s -g -triple %itanium_abi_triple -fno-use-cxa-atexit -fapple-kext -S -emit-llvm -o - \
// RUN: | FileCheck %s --check-prefix=CHECK-KEXT
class A {
diff --git a/test/CodeGenCXX/debug-info-global.cpp b/test/CodeGenCXX/debug-info-global.cpp
new file mode 100644
index 000000000000..8dc30c892316
--- /dev/null
+++ b/test/CodeGenCXX/debug-info-global.cpp
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 -triple x86_64-none-linux-gnu -emit-llvm -g %s -o - | FileCheck %s
+
+// Multiple references to the same constant should result in only one entry in
+// the globals list.
+
+namespace ns {
+const int cnst = 42;
+}
+int f1() {
+ return ns::cnst + ns::cnst;
+}
+
+// CHECK: metadata [[GLOBALS:![0-9]*]], metadata {{![0-9]*}}, metadata !"{{.*}}", i32 {{[0-9]*}}} ; [ DW_TAG_compile_unit ]
+
+// CHECK: [[GLOBALS]] = metadata !{metadata [[CNST:![0-9]*]]}
+
+// CHECK: [[CNST]] = {{.*}}, metadata [[NS:![0-9]*]], metadata !"cnst", {{.*}}; [ DW_TAG_variable ] [cnst]
+// CHECK: [[NS]] = {{.*}}; [ DW_TAG_namespace ] [ns]
+
diff --git a/test/CodeGenCXX/debug-info-indirect-field-decl.cpp b/test/CodeGenCXX/debug-info-indirect-field-decl.cpp
new file mode 100644
index 000000000000..131cebae4875
--- /dev/null
+++ b/test/CodeGenCXX/debug-info-indirect-field-decl.cpp
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -emit-llvm -g -triple x86_64-apple-darwin %s -o - | FileCheck %s
+//
+// Test that indirect field decls are handled gracefully.
+// rdar://problem/16348575
+//
+template <class T, int T::*ptr> class Foo { };
+
+struct Bar {
+ int i1;
+ // CHECK: [ DW_TAG_member ] [line [[@LINE+1]], size 32, align 32, offset 32] [from _ZTSN3BarUt_E]
+ union {
+ // CHECK: [ DW_TAG_member ] [i2] [line [[@LINE+1]], size 32, align 32, offset 0] [from int]
+ int i2;
+ };
+};
+
+Foo<Bar, &Bar::i2> the_foo;
diff --git a/test/CodeGenCXX/debug-info-limited.cpp b/test/CodeGenCXX/debug-info-limited.cpp
index 54a2424fddd9..294d1f6b6d20 100644
--- a/test/CodeGenCXX/debug-info-limited.cpp
+++ b/test/CodeGenCXX/debug-info-limited.cpp
@@ -11,8 +11,7 @@ A *foo (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]
+// CHECK: ; [ DW_TAG_class_type ] [B] {{.*}} [def]
class B {
public:
diff --git a/test/CodeGenCXX/debug-info-line-if.cpp b/test/CodeGenCXX/debug-info-line-if.cpp
new file mode 100644
index 000000000000..e14090f03f98
--- /dev/null
+++ b/test/CodeGenCXX/debug-info-line-if.cpp
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -g -std=c++11 -S -emit-llvm %s -o - | FileCheck %s
+// PR19864
+int main() {
+ int v[] = {13, 21, 8, 3, 34, 1, 5, 2};
+ int a = 0, b = 0;
+ for (int x : v)
+ if (x >= 3)
+ ++b; // CHECK: add nsw{{.*}}, 1
+ else if (x >= 0)
+ ++a; // CHECK: add nsw{{.*}}, 1
+ // The continuation block if the if statement should not share the
+ // location of the ++a statement. Having it point to the end of
+ // the condition is not ideal either, but it's less missleading.
+
+ // CHECK: br label
+ // CHECK: br label
+ // CHECK: br label {{.*}}, !dbg ![[DBG:.*]]
+ // CHECK: ![[DBG]] = metadata !{i32 [[@LINE-11]], i32 0, metadata !{{.*}}, null}
+
+}
diff --git a/test/CodeGenCXX/debug-info-member.cpp b/test/CodeGenCXX/debug-info-member.cpp
index 8c2e3ebded4b..7ba97b5b54e7 100644
--- a/test/CodeGenCXX/debug-info-member.cpp
+++ b/test/CodeGenCXX/debug-info-member.cpp
@@ -1,4 +1,5 @@
-// RUN: %clang -fverbose-asm -g -S %s -o - | grep DW_ACCESS_public
+// FIXME: Check IR rather than asm, then triple is not needed.
+// RUN: %clang -Xclang -triple=%itanium_abi_triple -fverbose-asm -g -S %s -o - | grep DW_ACCESS_public
class A {
public:
int x;
diff --git a/test/CodeGenCXX/debug-info-method-spec.cpp b/test/CodeGenCXX/debug-info-method-spec.cpp
index 2068c5ce4fad..c00da004f456 100644
--- a/test/CodeGenCXX/debug-info-method-spec.cpp
+++ b/test/CodeGenCXX/debug-info-method-spec.cpp
@@ -1,4 +1,5 @@
-// RUN: %clang -fverbose-asm -g -S %s -o - | grep DW_AT_specification
+// FIXME: Check IR rather than asm, then triple is not needed.
+// RUN: %clang -Xclang -triple=%itanium_abi_triple -fverbose-asm -g -S %s -o - | grep DW_AT_specification
// Radar 9254491
class A {
public:
diff --git a/test/CodeGenCXX/debug-info-method.cpp b/test/CodeGenCXX/debug-info-method.cpp
index 50b3f66354e0..49b8dc47855d 100644
--- a/test/CodeGenCXX/debug-info-method.cpp
+++ b/test/CodeGenCXX/debug-info-method.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm -std=c++11 -g %s -o - | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -std=c++11 -g %s -o - | FileCheck %s
// 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]
diff --git a/test/CodeGenCXX/debug-info-method2.cpp b/test/CodeGenCXX/debug-info-method2.cpp
index a927c49d307a..a365312b2584 100644
--- a/test/CodeGenCXX/debug-info-method2.cpp
+++ b/test/CodeGenCXX/debug-info-method2.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -flimit-debug-info -x c++ -g -S -emit-llvm < %s | FileCheck %s
+// RUN: %clang_cc1 -fno-standalone-debug -x c++ -g -S -emit-llvm < %s | FileCheck %s
// rdar://10336845
// Preserve type qualifiers in -flimit-debug-info mode.
diff --git a/test/CodeGenCXX/debug-info-namespace.cpp b/test/CodeGenCXX/debug-info-namespace.cpp
index a2d7ede1643e..a1284d2d2771 100644
--- a/test/CodeGenCXX/debug-info-namespace.cpp
+++ b/test/CodeGenCXX/debug-info-namespace.cpp
@@ -1,6 +1,6 @@
-// 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
+// RUN: %clang_cc1 -g -fno-standalone-debug -S -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -g -gline-tables-only -S -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-GMLT %s
+// RUN: %clang_cc1 -g -fstandalone-debug -S -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-NOLIMIT %s
namespace A {
#line 1 "foo.cpp"
@@ -36,42 +36,48 @@ int func(bool b) {
return i + X::B::i + Y::B::i;
}
+namespace A {
+using 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: [[CU:![0-9]*]] = {{.*}}[[MODULES:![0-9]*]], metadata !"", i32 1} ; [ DW_TAG_compile_unit ]
// 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: [[CTXT]] = {{.*}}, metadata [[FILE:![0-9]*]], null, {{.*}} ; [ DW_TAG_namespace ] [A] [line 5]
+// CHECK: [[FILE]] {{.*}}debug-info-namespace.cpp"
// 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: [[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]*]], metadata [[M13:![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: [[M3]] = metadata !{i32 {{[0-9]*}}, metadata [[CU]], metadata [[CTXT]], i32 15, metadata !"E"} ; [ DW_TAG_imported_declaration ]
// 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: [[M6]] = metadata !{i32 {{[0-9]*}}, metadata [[FUNC]], metadata [[FOO:!"_ZTSN1A1B3fooE"]], i32 23} ; [ DW_TAG_imported_declaration ]
+// CHECK: [[M7]] = metadata !{i32 {{[0-9]*}}, metadata [[FUNC]], metadata [[BAR:!"_ZTSN1A1B3barE"]], 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: [[M11]] = metadata !{i32 {{[0-9]*}}, metadata [[FUNC]], metadata [[CTXT]], i32 {{[0-9]*}}, metadata !"X"} ; [ DW_TAG_imported_declaration ]
+// CHECK: [[M12]] = metadata !{i32 {{[0-9]*}}, metadata [[FUNC]], metadata [[M11]], i32 {{[0-9]*}}, metadata !"Y"} ; [ DW_TAG_imported_declaration ]
+// CHECK: [[M13]] = metadata !{i32 {{[0-9]*}}, metadata [[CTXT]], metadata [[I]], i32 {{[0-9]*}}} ; [ DW_TAG_imported_declaration ]
-// CHECK-GMLT: [[CU:![0-9]*]] = {{.*}}[[MODULES:![0-9]*]], metadata !""} ; [ DW_TAG_compile_unit ]
-// CHECK-GMLT: [[MODULES]] = metadata !{i32 0}
+// CHECK-GMLT: [[CU:![0-9]*]] = {{.*}}[[MODULES:![0-9]*]], metadata !"", i32 2} ; [ DW_TAG_compile_unit ]
+// CHECK-GMLT: [[MODULES]] = metadata !{}
// 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
+// REQUIRES: dw2
diff --git a/test/CodeGenCXX/debug-info-pubtypes.cpp b/test/CodeGenCXX/debug-info-pubtypes.cpp
deleted file mode 100644
index 6393cddeef67..000000000000
--- a/test/CodeGenCXX/debug-info-pubtypes.cpp
+++ /dev/null
@@ -1,16 +0,0 @@
-// REQUIRES: x86-64-registered-target
-// 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]:]]
-//CHECK: .asciz "G"
-//CHECK-NEXT: .long 0
-//CHECK-NEXT: Lpubtypes_end[[SECNUM]]
-
-class G {
-public:
- void foo();
-};
-
-void G::foo() {
-}
diff --git a/test/CodeGenCXX/debug-info-qualifiers.cpp b/test/CodeGenCXX/debug-info-qualifiers.cpp
new file mode 100644
index 000000000000..c6b935f9039a
--- /dev/null
+++ b/test/CodeGenCXX/debug-info-qualifiers.cpp
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -std=c++11 -emit-llvm -g -triple x86_64-apple-darwin %s -o - | FileCheck %s
+// Test (r)value and CVR qualifiers on C++11 non-static member functions.
+class A {
+public:
+ // CHECK: i32 [[@LINE+2]], metadata ![[PLSR:[0-9]+]], {{.*}}[ DW_TAG_subprogram ] [line [[@LINE+2]]] [reference] [l]
+ // CHECK: ![[PLSR]] ={{.*}}[ DW_TAG_subroutine_type ]{{.*}}[reference]
+ void l() const &;
+ // CHECK: ![[ARGS:[0-9]+]] = metadata !{null, metadata ![[THIS:[0-9]+]]}
+ // CHECK: ![[THIS]] = {{.*}} metadata ![[CONST_A:.*]]} ; [ DW_TAG_pointer_type ]
+ // CHECK: ![[CONST_A]] = {{.*}} [ DW_TAG_const_type ]
+ // CHECK: i32 [[@LINE+2]], metadata ![[PRSR:[0-9]+]], {{.*}}[ DW_TAG_subprogram ] [line [[@LINE+2]]] [rvalue reference] [r]
+ // CHECK: ![[PRSR]] ={{.*}}metadata ![[ARGS]], i32 0, null, null, null}{{.*}}[ DW_TAG_subroutine_type ]{{.*}}[rvalue reference]
+ void r() const &&;
+};
+
+void g() {
+ A a;
+ // The type of pl is "void (A::*)() const &".
+ // CHECK: metadata ![[PL:[0-9]+]], i32 0, i32 0} ; [ DW_TAG_auto_variable ] [pl] [line [[@LINE+2]]]
+ // CHECK: metadata ![[PLSR]], metadata !"{{.*}}"} ; [ DW_TAG_ptr_to_member_type ]
+ auto pl = &A::l;
+
+ // CHECK: metadata ![[PR:[0-9]+]], i32 0, i32 0} ; [ DW_TAG_auto_variable ] [pr] [line [[@LINE+2]]]
+ // CHECK: metadata ![[PRSR]], metadata !"{{.*}}"} ; [ DW_TAG_ptr_to_member_type ]
+ auto pr = &A::r;
+}
diff --git a/test/CodeGenCXX/debug-info-same-line.cpp b/test/CodeGenCXX/debug-info-same-line.cpp
index 519e9eeb87a4..965a538f8472 100644
--- a/test/CodeGenCXX/debug-info-same-line.cpp
+++ b/test/CodeGenCXX/debug-info-same-line.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -g -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -g -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck %s
// Make sure that clang outputs distinct debug info for a function
// that is inlined twice on the same line. Otherwise it would appear
@@ -6,118 +6,59 @@
#define INLINE inline __attribute__((always_inline))
-INLINE int
-product (int x, int y)
-{
- int result = x * y;
- return result;
-}
-
-INLINE int
-sum (int a, int b)
-{
- int result = a + b;
- return result;
-}
+int i;
-int
-strange_max (int m, int n)
-{
- if (m > n)
- return m;
- else if (n > m)
- return n;
- else
- return 0;
+INLINE void sum(int a, int b) {
+ i = a + b;
}
-int
-foo (int i, int j)
-{
- if (strange_max (i, j) == i)
- return product (i, j);
- else if (strange_max (i, j) == j)
- return sum (i, j);
- else
- return product (sum (i, i), sum (j, j));
+void noinline(int x, int y) {
+ i = x + y;
}
-int
-main(int argc, char const *argv[])
-{
-
- int array[3];
- int n;
+#define CALLS sum(9, 10), sum(11, 12)
- array[0] = foo (1238, 78392);
- array[1] = foo (379265, 23674);
- array[2] = foo (872934, 234);
-
- n = strange_max(array[0], strange_max(array[1], array[2]));
-
- return n & 0xf;
+inline void inlsum(int t, int u) {
+ i = t + u;
}
-// CHECK: define {{.*}} @_Z3fooii
-// i
-// CHECK: call void @llvm.dbg.declare
-// j
-// CHECK: call void @llvm.dbg.declare
-// x
-// CHECK: call void @llvm.dbg.declare
-// y
-// CHECK: call void @llvm.dbg.declare
-// result
-// CHECK: call void @llvm.dbg.declare
-
-// CHECK: call void @llvm.dbg.declare(metadata !{i32* %{{.*}}}, metadata ![[A_MD:[0-9]+]]), !dbg ![[A_DI:[0-9]+]]
-// CHECK: call void @llvm.dbg.declare(metadata !{i32* %{{.*}}}, metadata ![[B_MD:[0-9]+]]), !dbg ![[B_DI:[0-9]+]]
-// result
-// CHECK: call void @llvm.dbg.declare
-
-// We want to see a distinct !dbg node.
-// CHECK-NOT: call void @llvm.dbg.declare(metadata !{i32* %{{.*}}}, metadata ![[A_MD]]), !dbg ![[A_DI]]
-// CHECK: call void @llvm.dbg.declare(metadata !{i32* %{{.*}}}, metadata ![[A_MD]]), !dbg !{{.*}}
-// CHECK-NOT: call void @llvm.dbg.declare(metadata !{i32* %{{.*}}}, metadata ![[B_MD]]), !dbg ![[B_DI]]
-// CHECK: call void @llvm.dbg.declare(metadata !{i32* %{{.*}}}, metadata ![[B_MD]]), !dbg !{{.*}}
-// result
-// CHECK: call void @llvm.dbg.declare
-
-// 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
-// CHECK: call {{.*}} @_Z3fooii
-// CHECK: store
-// CHECK: getelementptr
-// We want to see the same !dbg node for non-inlined functions.
-// Needed for GDB compatibility.
-// CHECK: load {{.*}} !dbg ![[DBG:.*]]
-// CHECK: load {{.*}} !dbg ![[DBG]]
-// CHECK: load {{.*}} !dbg ![[DBG]]
-// CHECK: call {{.*}} @_Z11strange_maxii(i32 {{.*}}, i32 {{.*}}), !dbg ![[DBG]]
-// CHECK: call {{.*}} @_Z11strange_maxii(i32 {{.*}}, i32 {{.*}}), !dbg ![[DBG]]
-
+int main() {
+ sum(1, 2), sum(3, 4);
+ noinline(5, 6), noinline(7, 8);
+ CALLS;
+ inlsum(13, 14), inlsum(15, 16);
+}
-// 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]]}
+// CHECK-LABEL: @main
+// CHECK: = add {{.*}} !dbg [[FIRST_INLINE:![0-9]*]]
+// CHECK: = add {{.*}} !dbg [[SECOND_INLINE:![0-9]*]]
+
+// Check that we don't give column information (and thus end up with distinct
+// line entries) for two non-inlined calls on the same line.
+// CHECK: call {{.*}}noinline{{.*}}({{i32[ ]?[a-z]*}} 5, {{i32[ ]?[a-z]*}} 6), !dbg [[NOINLINE:![0-9]*]]
+// CHECK: call {{.*}}noinline{{.*}}({{i32[ ]?[a-z]*}} 7, {{i32[ ]?[a-z]*}} 8), !dbg [[NOINLINE]]
+
+// FIXME: These should be separate locations but because the two calls have the
+// same line /and/ column, they get coalesced into a single inlined call by
+// accident. We need discriminators or some other changes to LLVM to cope with
+// this. (this is, unfortunately, an LLVM test disguised as a Clang test - since
+// inlining is forced to happen here). It's possible this could be fixed in
+// Clang, but I doubt it'll be the right place for the fix.
+// CHECK: = add {{.*}} !dbg [[FIRST_MACRO_INLINE:![0-9]*]]
+// CHECK: = add {{.*}} !dbg [[FIRST_MACRO_INLINE]]
+
+// Even if the functions are marked inline but do not get inlined, they
+// shouldn't use column information, and thus should be at the same debug
+// location.
+// CHECK: call {{.*}}inlsum{{.*}}({{i32[ ]?[a-z]*}} 13, {{i32[ ]?[a-z]*}} 14), !dbg [[INL_FIRST:![0-9]*]]
+// CHECK: call {{.*}}inlsum{{.*}}({{i32[ ]?[a-z]*}} 15, {{i32[ ]?[a-z]*}} 16), !dbg [[INL_SECOND:![0-9]*]]
+
+// [[FIRST_INLINE]] =
+// [[SECOND_INLINE]] =
+
+// FIXME: These should be the same location since the functions appear on the
+// same line and were not inlined - they needlessly have column information
+// intended to disambiguate inlined calls, which is going to confuse GDB as it
+// doesn't cope well with column information.
+// [[INL_FIRST]] =
+// [[INL_SECOND]] =
diff --git a/test/CodeGenCXX/debug-info-scope.cpp b/test/CodeGenCXX/debug-info-scope.cpp
index 557ee3178354..0447dc04d56b 100644
--- a/test/CodeGenCXX/debug-info-scope.cpp
+++ b/test/CodeGenCXX/debug-info-scope.cpp
@@ -17,12 +17,12 @@ char *return_char (int input)
int main2() {
// CHECK: [ DW_TAG_auto_variable ] [ptr] [line [[@LINE+2]]]
-// CHECK metadata !{i32 {{.*}}, metadata !{{.*}}, i32 [[@LINE+1]], {{.*}}} ; [ DW_TAG_lexical_block ]
+// 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 ]
+// CHECK: metadata !{i32 {{.*}}, metadata !{{.*}}, i32 [[@LINE+1]], {{.*}}} ; [ DW_TAG_lexical_block ]
if (char *ptr = return_char(2)) {
printf ("%s", ptr);
}
diff --git a/test/CodeGenCXX/debug-info-template-explicit-specialization.cpp b/test/CodeGenCXX/debug-info-template-explicit-specialization.cpp
new file mode 100644
index 000000000000..506c0d535751
--- /dev/null
+++ b/test/CodeGenCXX/debug-info-template-explicit-specialization.cpp
@@ -0,0 +1,93 @@
+// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -g %s -o - -fno-standalone-debug | FileCheck %s
+
+// Run again with -gline-tables-only and verify we don't crash. We won't output
+// type info at all.
+// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -g %s -o - -gline-tables-only | FileCheck %s -check-prefix LINES-ONLY
+
+// LINES-ONLY-NOT: DW_TAG_structure_type
+
+template <typename T>
+struct a {
+};
+extern template class a<int>;
+// CHECK-NOT: ; [ DW_TAG_structure_type ] [a<int>]
+
+template <typename T>
+struct b {
+};
+extern template class b<int>;
+b<int> bi;
+// CHECK: ; [ DW_TAG_structure_type ] [b<int>] {{.*}} [def]
+
+template <typename T>
+struct c {
+ void f() {}
+};
+extern template class c<int>;
+c<int> ci;
+// CHECK: ; [ DW_TAG_structure_type ] [c<int>] {{.*}} [decl]
+
+template <typename T>
+struct d {
+ void f();
+};
+extern template class d<int>;
+d<int> di;
+// CHECK: ; [ DW_TAG_structure_type ] [d<int>] {{.*}} [def]
+
+template <typename T>
+struct e {
+ void f();
+};
+template <typename T>
+void e<T>::f() {
+}
+extern template class e<int>;
+e<int> ei;
+// There's no guarantee that the out of line definition will appear before the
+// explicit template instantiation definition, so conservatively emit the type
+// definition here.
+// CHECK: ; [ DW_TAG_structure_type ] [e<int>] {{.*}} [def]
+
+template <typename T>
+struct f {
+ void g();
+};
+extern template class f<int>;
+template <typename T>
+void f<T>::g() {
+}
+f<int> fi;
+// CHECK: ; [ DW_TAG_structure_type ] [f<int>] {{.*}} [def]
+
+template <typename T>
+struct g {
+ void f();
+};
+template <>
+void g<int>::f();
+extern template class g<int>;
+g<int> gi;
+// CHECK: ; [ DW_TAG_structure_type ] [g<int>] {{.*}} [def]
+
+template <typename T>
+struct h {
+};
+template class h<int>;
+// CHECK: ; [ DW_TAG_structure_type ] [h<int>] {{.*}} [def]
+
+template <typename T>
+struct i {
+ void f() {}
+};
+template<> void i<int>::f();
+extern template class i<int>;
+i<int> ii;
+// CHECK: ; [ DW_TAG_structure_type ] [i<int>] {{.*}} [def]
+
+template <typename T1, typename T2 = T1>
+struct j {
+};
+extern template class j<int>;
+j<int> jj;
+// CHECK: ; [ DW_TAG_structure_type ] [j<int, int>]
diff --git a/test/CodeGenCXX/debug-info-template-fwd.cpp b/test/CodeGenCXX/debug-info-template-fwd.cpp
new file mode 100644
index 000000000000..b2b70730efdf
--- /dev/null
+++ b/test/CodeGenCXX/debug-info-template-fwd.cpp
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin -g -emit-llvm -o - | FileCheck %s
+// This test is for a crash when emitting debug info for not-yet-completed
+// types.
+// Test that we don't actually emit a forward decl for the offending class:
+// CHECK: [ DW_TAG_structure_type ] [Derived<int>] {{.*}} [def]
+// rdar://problem/15931354
+template <class A> class Derived;
+
+template <class A> class Base {
+ static Derived<A> *create();
+};
+
+template <class A> struct Derived : Base<A> {
+};
+
+Base<int> *f;
+
+// During the instantiation of Derived<int>, Base<int> becomes required to be
+// complete - since the declaration has already been emitted (due to 'f',
+// above), we immediately try to build debug info for Base<int> which then
+// requires the (incomplete definition) of Derived<int> which is problematic.
+//
+// (if 'f' is not present, the point at which Base<int> becomes required to be
+// complete during the instantiation of Derived<int> is a no-op because
+// Base<int> was never emitted so we ignore it and carry on until we
+// wire up the base class of Derived<int> in the debug info later on)
+Derived<int> d;
diff --git a/test/CodeGenCXX/debug-info-template-limit.cpp b/test/CodeGenCXX/debug-info-template-limit.cpp
index c3e241ecc806..e1f23ada21ed 100644
--- a/test/CodeGenCXX/debug-info-template-limit.cpp
+++ b/test/CodeGenCXX/debug-info-template-limit.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang -flimit-debug-info -emit-llvm -g -S %s -o - | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -fno-standalone-debug -triple %itanium_abi_triple -g %s -o - | FileCheck %s
// Check that this pointer type is TC<int>
// CHECK: ![[LINE:[0-9]+]] = {{.*}}"TC<int>", {{.*}} metadata !"_ZTS2TCIiE"} ; [ DW_TAG_class_type ]
diff --git a/test/CodeGenCXX/debug-info-template-member.cpp b/test/CodeGenCXX/debug-info-template-member.cpp
index 9ac1befc1019..c9a3d9b9177c 100644
--- a/test/CodeGenCXX/debug-info-template-member.cpp
+++ b/test/CodeGenCXX/debug-info-template-member.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm -g -triple x86_64-apple-darwin %s -o - | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -g -fno-standalone-debug -triple x86_64-apple-darwin %s -o - | FileCheck %s
struct MyClass {
template <int i> int add(int j) {
@@ -21,7 +21,7 @@ inline int add3(int x) {
// 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: [[OUTER_FOO_INNER]] = {{.*}}, null, metadata !"[[OUTER_FOO_INNER_ID:.*]]"} ; [ 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]*]]}
@@ -59,7 +59,7 @@ inline void func() {
outer<foo>::inner x;
-// CHECK: metadata [[OUTER_FOO_INNER]], i32 {{[0-9]*}}, i32 {{[0-9]*}}, %"struct.outer<foo>::inner"* @x, {{.*}} ; [ DW_TAG_variable ] [x]
+// CHECK: metadata !"[[OUTER_FOO_INNER_ID]]", i32 {{[0-9]*}}, i32 {{[0-9]*}}, %"struct.outer<foo>::inner"* @x, {{.*}} ; [ DW_TAG_variable ] [x]
template <typename T>
struct virt {
diff --git a/test/CodeGenCXX/debug-info-template-partial-specialization.cpp b/test/CodeGenCXX/debug-info-template-partial-specialization.cpp
new file mode 100644
index 000000000000..cce84af4023c
--- /dev/null
+++ b/test/CodeGenCXX/debug-info-template-partial-specialization.cpp
@@ -0,0 +1,31 @@
+// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -g %s -o - -fstandalone-debug | FileCheck %s
+namespace __pointer_type_imp
+{
+ template <class _Tp, class _Dp, bool > struct __pointer_type1 {};
+
+ // CHECK: metadata ![[PARAMS:[0-9]+]], metadata !"_ZTSN18__pointer_type_imp15__pointer_type1I1C14default_deleteIS1_ELb0EEE"} ; [ DW_TAG_structure_type ] [__pointer_type1<C, default_delete<C>, false>] [line [[@LINE+1]], size 8, align 8, offset 0] [def] [from ]
+ template <class _Tp, class _Dp> struct __pointer_type1<_Tp, _Dp, false>
+ {
+ typedef _Tp* type;
+ };
+}
+template <class _Tp, class _Dp>
+struct __pointer_type2
+{
+ // Test that the bool template type parameter is emitted.
+ //
+ // CHECK: ![[PARAMS]] = metadata !{metadata !{{.*}}, metadata !{{.*}}, metadata ![[FALSE:[0-9]+]]}
+ // CHECK: ![[FALSE]] = {{.*}} i8 0, {{.*}}} ; [ DW_TAG_template_value_parameter ]
+ typedef typename __pointer_type_imp::__pointer_type1<_Tp, _Dp, false>::type type;
+};
+template <class _Tp> struct default_delete {};
+template <class _Tp, class _Dp = default_delete<_Tp> > class unique_ptr
+{
+ typedef typename __pointer_type2<_Tp, _Dp>::type pointer;
+ unique_ptr(pointer __p, _Dp __d) {}
+};
+class C {
+ unique_ptr<C> Ptr;
+};
+void foo(C &c) {
+}
diff --git a/test/CodeGenCXX/debug-info-template.cpp b/test/CodeGenCXX/debug-info-template.cpp
index f58973bcceae..d071830eaf67 100644
--- a/test/CodeGenCXX/debug-info-template.cpp
+++ b/test/CodeGenCXX/debug-info-template.cpp
@@ -1,7 +1,7 @@
// RUN: %clang -S -emit-llvm -target x86_64-unknown_unknown -g %s -o - -std=c++11 | FileCheck %s
// 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: [[EMPTY:![0-9]*]] = metadata !{}
// CHECK: [[RETAIN]] = metadata !{metadata !{{[0-9]]*}}, metadata [[FOO:![0-9]*]],
@@ -50,8 +50,8 @@
//
-// 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: metadata !{i32 {{[0-9]*}}, metadata !{{[0-9]*}}, metadata !"_ZTS2TCIjLj2EXadL_Z3glbEEXadL_ZN3foo1eEEEXadL_ZNS0_1fEvEEXadL_Z4funcvEE9tmpl_implJLi1ELi2ELi3EEE", {{.*}}, metadata !"[[TCNESTED:.*]]"} ; [ DW_TAG_structure_type ] [nested]
+// CHECK: metadata [[TCNARGS:![0-9]*]], metadata !"[[TCNT:.*]]"} ; [ 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 ]
@@ -77,9 +77,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: 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 !"[[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]
+// CHECK: metadata !"[[TCNT]]", 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;
diff --git a/test/CodeGenCXX/debug-info-thunk.cpp b/test/CodeGenCXX/debug-info-thunk.cpp
index 2a5089572534..1d6f1a77b49a 100644
--- a/test/CodeGenCXX/debug-info-thunk.cpp
+++ b/test/CodeGenCXX/debug-info-thunk.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -g -S -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -triple %itanium_abi_triple -g -S -emit-llvm -o - | FileCheck %s
struct A {
virtual void f();
diff --git a/test/CodeGenCXX/debug-info-use-after-free.cpp b/test/CodeGenCXX/debug-info-use-after-free.cpp
index 852e14895618..0f28a9063fb8 100644
--- a/test/CodeGenCXX/debug-info-use-after-free.cpp
+++ b/test/CodeGenCXX/debug-info-use-after-free.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -g -emit-llvm-only %s
+// RUN: %clang_cc1 -g -triple %itanium_abi_triple -emit-llvm-only %s
// Check that we don't crash.
// PR12305, PR12315
diff --git a/test/CodeGenCXX/debug-info-uuid.cpp b/test/CodeGenCXX/debug-info-uuid.cpp
index a57e2f0a84ae..6137400de07c 100644
--- a/test/CodeGenCXX/debug-info-uuid.cpp
+++ b/test/CodeGenCXX/debug-info-uuid.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm -fms-extensions -triple=x86_64-pc-win32 -cxx-abi microsoft -g %s -o - -std=c++11 | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -fms-extensions -triple=x86_64-pc-win32 -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)>]
diff --git a/test/CodeGenCXX/debug-info-varargs.cpp b/test/CodeGenCXX/debug-info-varargs.cpp
new file mode 100644
index 000000000000..cc92477dbb92
--- /dev/null
+++ b/test/CodeGenCXX/debug-info-varargs.cpp
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -g %s -o - | FileCheck %s
+
+struct A
+{
+ // CHECK-DAG: ", i32 [[@LINE+1]], metadata ![[ATY:[0-9]+]]{{.*}}[ DW_TAG_subprogram ]{{.*}}[a]
+ void a(int c, ...) {}
+ // CHECK: ![[ATY]] ={{.*}} metadata ![[AARGS:[0-9]+]], i32 0, null, null, null} ; [ DW_TAG_subroutine_type ]
+ // CHECK: ![[AARGS]] = {{.*}} metadata ![[UNSPEC:[0-9]+]]}
+ // CHECK: ![[UNSPEC]] = {{.*}} [ DW_TAG_unspecified_parameters ]
+};
+
+ // CHECK: ", i32 [[@LINE+1]], metadata ![[BTY:[0-9]+]]{{.*}}[ DW_TAG_subprogram ]{{.*}}[b]
+void b(int c, ...) {
+ // CHECK: ![[BTY]] ={{.*}} metadata ![[BARGS:[0-9]+]], i32 0, null, null, null} ; [ DW_TAG_subroutine_type ]
+ // CHECK: ![[BARGS]] = {{.*}} metadata ![[UNSPEC:[0-9]+]]}
+
+ A a;
+
+ // CHECK: metadata ![[PST:[0-9]+]], i32 0, i32 0} ; [ DW_TAG_auto_variable ] [fptr] [line [[@LINE+1]]]
+ void (*fptr)(int, ...) = b;
+ // CHECK: ![[PST]] ={{.*}} metadata ![[BTY]]} ; [ DW_TAG_pointer_type ]
+}
diff --git a/test/CodeGenCXX/debug-info-vtable-optzn.cpp b/test/CodeGenCXX/debug-info-vtable-optzn.cpp
new file mode 100644
index 000000000000..c693f794b26f
--- /dev/null
+++ b/test/CodeGenCXX/debug-info-vtable-optzn.cpp
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 -emit-llvm -g -triple x86_64-apple-darwin %s -o - | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -g -triple amd64-unknown-freebsd %s -o - | FileCheck %s
+//
+// This tests that the "emit debug info for a C++ class only in the
+// module that has its vtable" optimization is disabled by default on
+// Darwin and FreeBSD.
+//
+// CHECK: [ DW_TAG_member ] [lost]
+class A
+{
+ virtual bool f() = 0;
+ int lost;
+};
+
+class B : public A
+{
+ B *g();
+};
+
+B *B::g() {
+ return this;
+}
diff --git a/test/CodeGenCXX/debug-info.cpp b/test/CodeGenCXX/debug-info.cpp
index 93a4fe3f466a..7c89dfc04ce1 100644
--- a/test/CodeGenCXX/debug-info.cpp
+++ b/test/CodeGenCXX/debug-info.cpp
@@ -51,11 +51,6 @@ namespace VirtualBase {
}
}
-void foo() {
- const wchar_t c = L'x';
- wchar_t d = c;
-}
-
namespace b5249287 {
template <typename T> class A {
struct B;
@@ -77,7 +72,7 @@ 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: metadata !{i32 {{[0-9]*}}, metadata !{{[0-9]*}}, metadata [[PR14763:![0-9]*]], {{.*}}, metadata !"[[FOO:.*]]"} ; [ 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]
@@ -88,6 +83,13 @@ foo func(foo f) {
// CHECK: [[FUNC:![0-9]*]] = {{.*}} metadata !"_ZN7pr147634funcENS_3fooE", i32 {{[0-9]*}}, metadata [[FUNC_TYPE:![0-9]*]], {{.*}} ; [ DW_TAG_subprogram ] {{.*}} [def] [func]
}
+void foo() {
+ const wchar_t c = L'x';
+ wchar_t d = c;
+}
+
+// CHECK-NOT: ; [ DW_TAG_variable ] [c]
+
namespace pr9608 { // also pr9600
struct incomplete;
incomplete (*x)[3];
@@ -96,8 +98,10 @@ incomplete (*x)[3];
// 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]
+// For some reason function arguments ended up down here
+// CHECK: = metadata !{i32 {{[0-9]*}}, metadata [[FUNC]], {{.*}}, metadata !"[[FOO]]", i32 8192, i32 0} ; [ DW_TAG_arg_variable ] [f]
+
+// CHECK: ; [ DW_TAG_auto_variable ] [c]
namespace pr16214 {
struct a {
diff --git a/test/CodeGenCXX/decl-ref-init.cpp b/test/CodeGenCXX/decl-ref-init.cpp
index 1a82ee2b485b..117d277c95e6 100644
--- a/test/CodeGenCXX/decl-ref-init.cpp
+++ b/test/CodeGenCXX/decl-ref-init.cpp
@@ -1,8 +1,7 @@
-// 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 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 CHECK-LP32 --input-file=%t-32.s %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm %s -o - | \
+// RUN: FileCheck %s
+// RUN: %clang_cc1 -triple i386-apple-darwin -emit-llvm %s -o - | \
+// RUN: FileCheck %s
struct A {};
@@ -24,8 +23,5 @@ int main() {
const A& rca2 = d();
}
-// CHECK-LP64: callq __ZN1BcvR1AEv
-// CHECK-LP64: callq __ZN1BcvR1AEv
-
-// CHECK-LP32: calll L__ZN1BcvR1AEv
-// CHECK-LP32: calll L__ZN1BcvR1AEv
+// CHECK: call dereferenceable({{[0-9]+}}) %struct.A* @_ZN1BcvR1AEv
+// CHECK: call dereferenceable({{[0-9]+}}) %struct.A* @_ZN1BcvR1AEv
diff --git a/test/CodeGenCXX/default-arg-temps.cpp b/test/CodeGenCXX/default-arg-temps.cpp
index 43756006f209..6a7f43a51287 100644
--- a/test/CodeGenCXX/default-arg-temps.cpp
+++ b/test/CodeGenCXX/default-arg-temps.cpp
@@ -16,12 +16,12 @@ public:
// CHECK-LABEL: define void @_Z1gv()
void g() {
// CHECK: call void @_ZN1TC1Ev([[T:%.*]]* [[AGG1:%.*]])
- // CHECK-NEXT: call void @_Z1fRK1T([[T]]* [[AGG1]])
+ // CHECK-NEXT: call void @_Z1fRK1T([[T]]* dereferenceable({{[0-9]+}}) [[AGG1]])
// CHECK-NEXT: call void @_ZN1TD1Ev([[T]]* [[AGG1]])
f();
// CHECK-NEXT: call void @_ZN1TC1Ev([[T:%.*]]* [[AGG2:%.*]])
- // CHECK-NEXT: call void @_Z1fRK1T([[T]]* [[AGG2]])
+ // CHECK-NEXT: call void @_Z1fRK1T([[T]]* dereferenceable({{[0-9]+}}) [[AGG2]])
// CHECK-NEXT: call void @_ZN1TD1Ev([[T]]* [[AGG2]])
f();
diff --git a/test/CodeGenCXX/default-arguments.cpp b/test/CodeGenCXX/default-arguments.cpp
index 83cae3afd561..d364835850c3 100644
--- a/test/CodeGenCXX/default-arguments.cpp
+++ b/test/CodeGenCXX/default-arguments.cpp
@@ -42,15 +42,15 @@ struct C {
C();
};
-// CHECK-LABEL: define void @_ZN1CC1Ev(%struct.C* %this) unnamed_addr
-// CHECK: call void @_ZN1CC2Ev(
-
// CHECK-LABEL: define void @_ZN1CC2Ev(%struct.C* %this) unnamed_addr
// CHECK: call void @_ZN2A1C1Ev(
// CHECK: call void @_ZN2A2C1Ev(
// CHECK: call void @_ZN1BC1ERK2A1RK2A2(
// CHECK: call void @_ZN2A2D1Ev
// CHECK: call void @_ZN2A1D1Ev
+
+// CHECK-LABEL: define void @_ZN1CC1Ev(%struct.C* %this) unnamed_addr
+// CHECK: call void @_ZN1CC2Ev(
C::C() { }
// CHECK-LABEL: define void @_Z2f3v()
diff --git a/test/CodeGenCXX/default-constructor-default-argument.cpp b/test/CodeGenCXX/default-constructor-default-argument.cpp
index 374a967e3e2a..17ecc35645e9 100644
--- a/test/CodeGenCXX/default-constructor-default-argument.cpp
+++ b/test/CodeGenCXX/default-constructor-default-argument.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %s
// Check that call to constructor for struct A is generated correctly.
struct A { A(int x = 2); };
diff --git a/test/CodeGenCXX/default-constructor-for-members.cpp b/test/CodeGenCXX/default-constructor-for-members.cpp
index 6065b49ac158..5eb8cd1767bb 100644
--- a/test/CodeGenCXX/default-constructor-for-members.cpp
+++ b/test/CodeGenCXX/default-constructor-for-members.cpp
@@ -1,8 +1,7 @@
-// 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 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 CHECK-LP32 --input-file=%t-32.s %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm %s -o - | \
+// RUN: FileCheck %s
+// RUN: %clang_cc1 -triple i386-apple-darwin -emit-llvm %s -o - | \
+// RUN: FileCheck %s
extern "C" int printf(...);
@@ -19,6 +18,4 @@ int main() {
M m1;
}
-// CHECK-LP64: callq __ZN1SC1Ev
-
-// CHECK-LP32: calll L__ZN1SC1Ev
+// CHECK: call void @_ZN1SC1Ev
diff --git a/test/CodeGenCXX/default-constructor-template-member.cpp b/test/CodeGenCXX/default-constructor-template-member.cpp
index 215696405a4f..93df81846037 100644
--- a/test/CodeGenCXX/default-constructor-template-member.cpp
+++ b/test/CodeGenCXX/default-constructor-template-member.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck %s
template <class T> struct A { A(); };
struct B { A<int> x; };
diff --git a/test/CodeGenCXX/default-destructor-nested.cpp b/test/CodeGenCXX/default-destructor-nested.cpp
index 565a7279c56e..77b06d639f4c 100644
--- a/test/CodeGenCXX/default-destructor-nested.cpp
+++ b/test/CodeGenCXX/default-destructor-nested.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -emit-llvm-only
+// RUN: %clang_cc1 %s -triple %itanium_abi_triple -emit-llvm-only
// PR6294
class A {
diff --git a/test/CodeGenCXX/deferred-global-init.cpp b/test/CodeGenCXX/deferred-global-init.cpp
index deb458f55c7d..f64f507ac919 100644
--- a/test/CodeGenCXX/deferred-global-init.cpp
+++ b/test/CodeGenCXX/deferred-global-init.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %s
// PR5967
extern void* foo;
@@ -11,6 +11,6 @@ void* bar() { return a; }
// CHECK: load i8** @foo
// CHECK: ret void
-// CHECK-LABEL: define internal void @_GLOBAL__I_a
+// CHECK-LABEL: define internal void @_GLOBAL__sub_I_deferred_global_init.cpp
// 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
index fa177d456255..c5f448641544 100644
--- a/test/CodeGenCXX/delayed-template-parsing.cpp
+++ b/test/CodeGenCXX/delayed-template-parsing.cpp
@@ -1,5 +1,5 @@
-// 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
+// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -fms-extensions -fdelayed-template-parsing -triple=i386-pc-win32 | FileCheck %s
+// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -fms-extensions -fdelayed-template-parsing -triple=x86_64-pc-win32 | FileCheck -check-prefix X64 %s
namespace ClassScopeSpecialization {
struct Type {
diff --git a/test/CodeGenCXX/delete-two-arg.cpp b/test/CodeGenCXX/delete-two-arg.cpp
index f8e6bff29580..be3cf1a900e6 100644
--- a/test/CodeGenCXX/delete-two-arg.cpp
+++ b/test/CodeGenCXX/delete-two-arg.cpp
@@ -1,4 +1,5 @@
-// RUN: not %clang_cc1 -triple i686-pc-linux-gnu %s -o - -emit-llvm -verify | FileCheck %s
+// RUN: %clang_cc1 -triple i686-pc-linux-gnu %s -o - -emit-llvm -verify | FileCheck %s
+// expected-no-diagnostics
typedef __typeof(sizeof(int)) size_t;
diff --git a/test/CodeGenCXX/dependent-type-member-pointer.cpp b/test/CodeGenCXX/dependent-type-member-pointer.cpp
index 99b8ecd555c7..595eca5aab2d 100644
--- a/test/CodeGenCXX/dependent-type-member-pointer.cpp
+++ b/test/CodeGenCXX/dependent-type-member-pointer.cpp
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -emit-llvm-only -verify %s
+// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc -emit-llvm-only -verify %s
// expected-no-diagnostics
// PR7736
diff --git a/test/CodeGenCXX/derived-to-base-conv.cpp b/test/CodeGenCXX/derived-to-base-conv.cpp
index 675c50c42328..f4ef0e52772b 100644
--- a/test/CodeGenCXX/derived-to-base-conv.cpp
+++ b/test/CodeGenCXX/derived-to-base-conv.cpp
@@ -33,9 +33,9 @@ void test0(X x) {
test0_helper(x);
// CHECK-LABEL: define void @_Z5test01X(
// CHECK: [[TMP:%.*]] = alloca [[A:%.*]], align
- // CHECK-NEXT: [[T0:%.*]] = call [[B:%.*]]* @_ZN1XcvR1BEv(
+ // CHECK-NEXT: [[T0:%.*]] = call dereferenceable({{[0-9]+}}) [[B:%.*]]* @_ZN1XcvR1BEv(
// CHECK-NEXT: [[T1:%.*]] = bitcast [[B]]* [[T0]] to [[A]]*
- // CHECK-NEXT: call void @_ZN1AC1ERKS_([[A]]* [[TMP]], [[A]]* [[T1]])
+ // CHECK-NEXT: call void @_ZN1AC1ERKS_([[A]]* [[TMP]], [[A]]* dereferenceable({{[0-9]+}}) [[T1]])
// CHECK-NEXT: call void @_Z12test0_helper1A([[A]]* [[TMP]])
// CHECK-NEXT: call void @_ZN1AD1Ev([[A]]* [[TMP]])
// CHECK-NEXT: ret void
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 f2ecfc1d38cc..d85928370319 100644
--- a/test/CodeGenCXX/derived-to-virtual-base-class-calls-final.cpp
+++ b/test/CodeGenCXX/derived-to-virtual-base-class-calls-final.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %s
struct A { int i; };
struct B { char j; };
@@ -9,7 +9,7 @@ struct D final : virtual C {
virtual void f();
};
-// CHECK-LABEL: define %struct.B* @_Z1fR1D
+// CHECK-LABEL: define dereferenceable({{[0-9]+}}) %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 e111ba0ba8e5..50c17ef4aa10 100644
--- a/test/CodeGenCXX/destructor-exception-spec.cpp
+++ b/test/CodeGenCXX/destructor-exception-spec.cpp
@@ -1,6 +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
+// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm-only %s -std=c++11
+// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm-only -fno-use-cxa-atexit %s -std=c++11
+// RUN: %clang_cc1 -triple %ms_abi_triple -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 799cca28b4a4..5c430480bc28 100644
--- a/test/CodeGenCXX/destructors.cpp
+++ b/test/CodeGenCXX/destructors.cpp
@@ -6,6 +6,13 @@
// CHECK-DAG: @_ZN5test11OD2Ev = alias {{.*}} @_ZN5test11AD2Ev
// CHECK-DAG: @_ZN5test11SD2Ev = alias bitcast {{.*}} @_ZN5test11AD2Ev
+// WIN32-DAG: @_ZN5test01AD1Ev = alias {{.*}} @_ZN5test01AD2Ev
+// WIN32-DAG: @_ZN5test11MD2Ev = alias {{.*}} @_ZN5test11AD2Ev
+// WIN32-DAG: @_ZN5test11ND2Ev = alias {{.*}} @_ZN5test11AD2Ev
+// WIN32-DAG: @_ZN5test11OD2Ev = alias {{.*}} @_ZN5test11AD2Ev
+// WIN32-DAG: @_ZN5test11SD2Ev = alias bitcast {{.*}} @_ZN5test11AD2Ev
+
+
struct A {
int a;
@@ -102,19 +109,19 @@ namespace test0 {
B::~B() try { } catch (int i) {}
// It will suppress the delegation optimization here, though.
-// CHECK-LABEL: define void @_ZN5test01BD1Ev(%"struct.test0::B"* %this) 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
// CHECK: unwind label [[BASE_UNWIND:%[a-zA-Z0-9.]+]]
-// CHECK: invoke void @_ZN5test05VBaseD2Ev
-// CHECK: unwind label [[VBASE_UNWIND:%[a-zA-Z0-9.]+]]
-// CHECK-LABEL: define void @_ZN5test01BD2Ev(%"struct.test0::B"* %this, i8** %vtt) 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
// CHECK: unwind label [[BASE_UNWIND:%[a-zA-Z0-9.]+]]
+// CHECK: invoke void @_ZN5test05VBaseD2Ev
+// CHECK: unwind label [[VBASE_UNWIND:%[a-zA-Z0-9.]+]]
}
// Test base-class aliasing.
@@ -272,14 +279,6 @@ namespace test6 {
// FIXME: way too much EH cleanup code follows
C::~C() { opaque(); }
- // CHECK-LABEL: define void @_ZN5test61CD1Ev(%"struct.test6::C"* %this) unnamed_addr
- // CHECK: invoke void @_ZN5test61CD2Ev
- // CHECK: invoke void @_ZN5test61BILj3EED2Ev
- // CHECK: call void @_ZN5test61BILj2EED2Ev
- // CHECK: ret void
- // CHECK: invoke void @_ZN5test61BILj3EED2Ev
- // CHECK: invoke void @_ZN5test61BILj2EED2Ev
-
// CHECK-LABEL: define void @_ZN5test61CD2Ev(%"struct.test6::C"* %this, i8** %vtt) unnamed_addr
// CHECK: invoke void @_ZN5test66opaqueEv
// CHECK: invoke void @_ZN5test61AD1Ev
@@ -293,6 +292,14 @@ namespace test6 {
// CHECK: invoke void @_ZN5test61AD1Ev
// CHECK: invoke void @_ZN5test61BILj1EED2Ev
// CHECK: invoke void @_ZN5test61BILj0EED2Ev
+
+ // CHECK-LABEL: define void @_ZN5test61CD1Ev(%"struct.test6::C"* %this) unnamed_addr
+ // CHECK: invoke void @_ZN5test61CD2Ev
+ // CHECK: invoke void @_ZN5test61BILj3EED2Ev
+ // CHECK: call void @_ZN5test61BILj2EED2Ev
+ // CHECK: ret void
+ // CHECK: invoke void @_ZN5test61BILj3EED2Ev
+ // CHECK: invoke void @_ZN5test61BILj2EED2Ev
}
// PR 9197
@@ -374,7 +381,7 @@ namespace test10 {
// Checks from test3:
- // CHECK-LABEL: define internal void @_ZN5test312_GLOBAL__N_11DD0Ev(%"struct.test3::<anonymous namespace>::D"* %this) unnamed_addr
+ // 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
@@ -398,7 +405,7 @@ namespace test10 {
// 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-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
@@ -406,7 +413,7 @@ namespace test10 {
// CHECK: declare void @_ZN5test31BD2Ev(
// CHECK: declare void @_ZN5test31AD2Ev(
- // CHECK-LABEL: define internal void @_ZN5test312_GLOBAL__N_11CD0Ev(%"struct.test3::<anonymous namespace>::C"* %this) unnamed_addr
+ // 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
diff --git a/test/CodeGenCXX/dllexport-members.cpp b/test/CodeGenCXX/dllexport-members.cpp
new file mode 100644
index 000000000000..d913c09ec7be
--- /dev/null
+++ b/test/CodeGenCXX/dllexport-members.cpp
@@ -0,0 +1,647 @@
+// RUN: %clang_cc1 -triple i686-windows-msvc -fms-compatibility -emit-llvm -std=c++1y -O0 -o - %s | FileCheck --check-prefix=MSC --check-prefix=M32 %s
+// RUN: %clang_cc1 -triple x86_64-windows-msvc -fms-compatibility -emit-llvm -std=c++1y -O0 -o - %s | FileCheck --check-prefix=MSC --check-prefix=M64 %s
+// RUN: %clang_cc1 -triple i686-windows-gnu -emit-llvm -std=c++1y -O0 -o - %s | FileCheck --check-prefix=GNU --check-prefix=G32 %s
+// RUN: %clang_cc1 -triple x86_64-windows-gnu -emit-llvm -std=c++1y -O0 -o - %s | FileCheck --check-prefix=GNU --check-prefix=G64 %s
+
+// Helper structs to make templates more expressive.
+struct ImplicitInst_Exported {};
+struct ExplicitDecl_Exported {};
+struct ExplicitInst_Exported {};
+struct ExplicitSpec_Exported {};
+struct ExplicitSpec_Def_Exported {};
+struct ExplicitSpec_InlineDef_Exported {};
+struct ExplicitSpec_NotExported {};
+
+extern "C" void* malloc(__SIZE_TYPE__ size);
+extern "C" void free(void* p);
+
+
+//===----------------------------------------------------------------------===//
+// Class members
+//===----------------------------------------------------------------------===//
+
+// Export individual members of a class.
+struct ExportMembers {
+ struct Nested;
+
+ // M32-DAG: define dllexport x86_thiscallcc void @"\01?normalDef@ExportMembers@@QAEXXZ"(%struct.ExportMembers* %this)
+ // M64-DAG: define dllexport void @"\01?normalDef@ExportMembers@@QEAAXXZ"(%struct.ExportMembers* %this)
+ // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?normalInclass@ExportMembers@@QAEXXZ"(%struct.ExportMembers* %this)
+ // M64-DAG: define weak_odr dllexport void @"\01?normalInclass@ExportMembers@@QEAAXXZ"(%struct.ExportMembers* %this)
+ // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?normalInlineDef@ExportMembers@@QAEXXZ"(%struct.ExportMembers* %this)
+ // M64-DAG: define weak_odr dllexport void @"\01?normalInlineDef@ExportMembers@@QEAAXXZ"(%struct.ExportMembers* %this)
+ // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?normalInlineDecl@ExportMembers@@QAEXXZ"(%struct.ExportMembers* %this)
+ // M64-DAG: define weak_odr dllexport void @"\01?normalInlineDecl@ExportMembers@@QEAAXXZ"(%struct.ExportMembers* %this)
+ // G32-DAG: define dllexport x86_thiscallcc void @_ZN13ExportMembers9normalDefEv(%struct.ExportMembers* %this)
+ // G64-DAG: define dllexport void @_ZN13ExportMembers9normalDefEv(%struct.ExportMembers* %this)
+ // G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN13ExportMembers13normalInclassEv(%struct.ExportMembers* %this)
+ // G64-DAG: define weak_odr dllexport void @_ZN13ExportMembers13normalInclassEv(%struct.ExportMembers* %this)
+ // G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN13ExportMembers15normalInlineDefEv(%struct.ExportMembers* %this)
+ // G64-DAG: define weak_odr dllexport void @_ZN13ExportMembers15normalInlineDefEv(%struct.ExportMembers* %this)
+ // G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN13ExportMembers16normalInlineDeclEv(%struct.ExportMembers* %this)
+ // G64-DAG: define weak_odr dllexport void @_ZN13ExportMembers16normalInlineDeclEv(%struct.ExportMembers* %this)
+ // M32-DAG: define linkonce_odr x86_thiscallcc void @"\01?referencedNonExportedInClass@ExportMembers@@QAEXXZ"
+ __declspec(dllexport) void normalDef();
+ __declspec(dllexport) void normalInclass() { referencedNonExportedInClass(); }
+ __declspec(dllexport) void normalInlineDef();
+ __declspec(dllexport) inline void normalInlineDecl();
+ void referencedNonExportedInClass() {}
+
+ // M32-DAG: define dllexport x86_thiscallcc void @"\01?virtualDef@ExportMembers@@UAEXXZ"(%struct.ExportMembers* %this)
+ // M64-DAG: define dllexport void @"\01?virtualDef@ExportMembers@@UEAAXXZ"(%struct.ExportMembers* %this)
+ // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?virtualInclass@ExportMembers@@UAEXXZ"(%struct.ExportMembers* %this)
+ // M64-DAG: define weak_odr dllexport void @"\01?virtualInclass@ExportMembers@@UEAAXXZ"(%struct.ExportMembers* %this)
+ // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?virtualInlineDef@ExportMembers@@UAEXXZ"(%struct.ExportMembers* %this)
+ // M64-DAG: define weak_odr dllexport void @"\01?virtualInlineDef@ExportMembers@@UEAAXXZ"(%struct.ExportMembers* %this)
+ // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?virtualInlineDecl@ExportMembers@@UAEXXZ"(%struct.ExportMembers* %this)
+ // M64-DAG: define weak_odr dllexport void @"\01?virtualInlineDecl@ExportMembers@@UEAAXXZ"(%struct.ExportMembers* %this)
+ // G32-DAG: define dllexport x86_thiscallcc void @_ZN13ExportMembers10virtualDefEv(%struct.ExportMembers* %this)
+ // G64-DAG: define dllexport void @_ZN13ExportMembers10virtualDefEv(%struct.ExportMembers* %this)
+ // G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN13ExportMembers14virtualInclassEv(%struct.ExportMembers* %this)
+ // G64-DAG: define weak_odr dllexport void @_ZN13ExportMembers14virtualInclassEv(%struct.ExportMembers* %this)
+ // G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN13ExportMembers16virtualInlineDefEv(%struct.ExportMembers* %this)
+ // G64-DAG: define weak_odr dllexport void @_ZN13ExportMembers16virtualInlineDefEv(%struct.ExportMembers* %this)
+ // G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN13ExportMembers17virtualInlineDeclEv(%struct.ExportMembers* %this)
+ // G64-DAG: define weak_odr dllexport void @_ZN13ExportMembers17virtualInlineDeclEv(%struct.ExportMembers* %this)
+ __declspec(dllexport) virtual void virtualDef();
+ __declspec(dllexport) virtual void virtualInclass() {}
+ __declspec(dllexport) virtual void virtualInlineDef();
+ __declspec(dllexport) virtual inline void virtualInlineDecl();
+
+ // MSC-DAG: define dllexport void @"\01?staticDef@ExportMembers@@SAXXZ"()
+ // MSC-DAG: define weak_odr dllexport void @"\01?staticInclass@ExportMembers@@SAXXZ"()
+ // MSC-DAG: define weak_odr dllexport void @"\01?staticInlineDef@ExportMembers@@SAXXZ"()
+ // MSC-DAG: define weak_odr dllexport void @"\01?staticInlineDecl@ExportMembers@@SAXXZ"()
+ // GNU-DAG: define dllexport void @_ZN13ExportMembers9staticDefEv()
+ // GNU-DAG: define weak_odr dllexport void @_ZN13ExportMembers13staticInclassEv()
+ // GNU-DAG: define weak_odr dllexport void @_ZN13ExportMembers15staticInlineDefEv()
+ // GNU-DAG: define weak_odr dllexport void @_ZN13ExportMembers16staticInlineDeclEv()
+ __declspec(dllexport) static void staticDef();
+ __declspec(dllexport) static void staticInclass() {}
+ __declspec(dllexport) static void staticInlineDef();
+ __declspec(dllexport) static inline void staticInlineDecl();
+
+ // M32-DAG: define dllexport x86_thiscallcc void @"\01?protectedDef@ExportMembers@@IAEXXZ"(%struct.ExportMembers* %this)
+ // M64-DAG: define dllexport void @"\01?protectedDef@ExportMembers@@IEAAXXZ"(%struct.ExportMembers* %this)
+ // G32-DAG: define dllexport x86_thiscallcc void @_ZN13ExportMembers12protectedDefEv(%struct.ExportMembers* %this)
+ // G64-DAG: define dllexport void @_ZN13ExportMembers12protectedDefEv(%struct.ExportMembers* %this)
+ // MSC-DAG: define dllexport void @"\01?protectedStaticDef@ExportMembers@@KAXXZ"()
+ // GNU-DAG: define dllexport void @_ZN13ExportMembers18protectedStaticDefEv()
+protected:
+ __declspec(dllexport) void protectedDef();
+ __declspec(dllexport) static void protectedStaticDef();
+
+ // M32-DAG: define dllexport x86_thiscallcc void @"\01?privateDef@ExportMembers@@AAEXXZ"(%struct.ExportMembers* %this)
+ // M64-DAG: define dllexport void @"\01?privateDef@ExportMembers@@AEAAXXZ"(%struct.ExportMembers* %this)
+ // G32-DAG: define dllexport x86_thiscallcc void @_ZN13ExportMembers10privateDefEv(%struct.ExportMembers* %this)
+ // G64-DAG: define dllexport void @_ZN13ExportMembers10privateDefEv(%struct.ExportMembers* %this)
+ // MSC-DAG: define dllexport void @"\01?privateStaticDef@ExportMembers@@CAXXZ"()
+ // GNU-DAG: define dllexport void @_ZN13ExportMembers16privateStaticDefEv()
+private:
+ __declspec(dllexport) void privateDef();
+ __declspec(dllexport) static void privateStaticDef();
+
+ // M32-DAG: define x86_thiscallcc void @"\01?ignored@ExportMembers@@QAEXXZ"(%struct.ExportMembers* %this)
+ // M64-DAG: define void @"\01?ignored@ExportMembers@@QEAAXXZ"(%struct.ExportMembers* %this)
+ // G32-DAG: define x86_thiscallcc void @_ZN13ExportMembers7ignoredEv(%struct.ExportMembers* %this)
+ // G64-DAG: define void @_ZN13ExportMembers7ignoredEv(%struct.ExportMembers* %this)
+public:
+ void ignored();
+
+ // MSC-DAG: @"\01?StaticField@ExportMembers@@2HA" = dllexport global i32 1, align 4
+ // MSC-DAG: @"\01?StaticConstField@ExportMembers@@2HB" = dllexport constant i32 1, align 4
+ // MSC-DAG: @"\01?StaticConstFieldEqualInit@ExportMembers@@2HB" = weak_odr dllexport constant i32 1, align 4
+ // MSC-DAG: @"\01?StaticConstFieldBraceInit@ExportMembers@@2HB" = weak_odr dllexport constant i32 1, align 4
+ // MSC-DAG: @"\01?ConstexprField@ExportMembers@@2HB" = weak_odr dllexport constant i32 1, align 4
+ // GNU-DAG: @_ZN13ExportMembers11StaticFieldE = dllexport global i32 1, align 4
+ // GNU-DAG: @_ZN13ExportMembers16StaticConstFieldE = dllexport constant i32 1, align 4
+ // GNU-DAG: @_ZN13ExportMembers25StaticConstFieldEqualInitE = dllexport constant i32 1, align 4
+ // GNU-DAG: @_ZN13ExportMembers25StaticConstFieldBraceInitE = dllexport constant i32 1, align 4
+ // GNU-DAG: @_ZN13ExportMembers14ConstexprFieldE = dllexport constant i32 1, align 4
+ __declspec(dllexport) static int StaticField;
+ __declspec(dllexport) static const int StaticConstField;
+ __declspec(dllexport) static const int StaticConstFieldEqualInit = 1;
+ __declspec(dllexport) static const int StaticConstFieldBraceInit{1};
+ __declspec(dllexport) constexpr static int ConstexprField = 1;
+};
+
+ void ExportMembers::normalDef() {}
+inline void ExportMembers::normalInlineDef() {}
+ void ExportMembers::normalInlineDecl() {}
+ void ExportMembers::virtualDef() {}
+inline void ExportMembers::virtualInlineDef() {}
+ void ExportMembers::virtualInlineDecl() {}
+ void ExportMembers::staticDef() {}
+inline void ExportMembers::staticInlineDef() {}
+ void ExportMembers::staticInlineDecl() {}
+ void ExportMembers::ignored() {}
+ void ExportMembers::protectedDef() {}
+ void ExportMembers::protectedStaticDef() {}
+ void ExportMembers::privateDef() {}
+ void ExportMembers::privateStaticDef() {}
+
+ int ExportMembers::StaticField = 1;
+const int ExportMembers::StaticConstField = 1;
+const int ExportMembers::StaticConstFieldEqualInit;
+const int ExportMembers::StaticConstFieldBraceInit;
+constexpr int ExportMembers::ConstexprField;
+
+
+// Export individual members of a nested class.
+struct ExportMembers::Nested {
+ // M32-DAG: define dllexport x86_thiscallcc void @"\01?normalDef@Nested@ExportMembers@@QAEXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // M64-DAG: define dllexport void @"\01?normalDef@Nested@ExportMembers@@QEAAXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?normalInclass@Nested@ExportMembers@@QAEXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // M64-DAG: define weak_odr dllexport void @"\01?normalInclass@Nested@ExportMembers@@QEAAXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?normalInlineDef@Nested@ExportMembers@@QAEXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // M64-DAG: define weak_odr dllexport void @"\01?normalInlineDef@Nested@ExportMembers@@QEAAXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?normalInlineDecl@Nested@ExportMembers@@QAEXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // M64-DAG: define weak_odr dllexport void @"\01?normalInlineDecl@Nested@ExportMembers@@QEAAXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // G32-DAG: define dllexport x86_thiscallcc void @_ZN13ExportMembers6Nested9normalDefEv(%"struct.ExportMembers::Nested"* %this)
+ // G64-DAG: define dllexport void @_ZN13ExportMembers6Nested9normalDefEv(%"struct.ExportMembers::Nested"* %this)
+ // G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN13ExportMembers6Nested13normalInclassEv(%"struct.ExportMembers::Nested"* %this)
+ // G64-DAG: define weak_odr dllexport void @_ZN13ExportMembers6Nested13normalInclassEv(%"struct.ExportMembers::Nested"* %this)
+ // G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN13ExportMembers6Nested15normalInlineDefEv(%"struct.ExportMembers::Nested"* %this)
+ // G64-DAG: define weak_odr dllexport void @_ZN13ExportMembers6Nested15normalInlineDefEv(%"struct.ExportMembers::Nested"* %this)
+ // G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN13ExportMembers6Nested16normalInlineDeclEv(%"struct.ExportMembers::Nested"* %this)
+ // G64-DAG: define weak_odr dllexport void @_ZN13ExportMembers6Nested16normalInlineDeclEv(%"struct.ExportMembers::Nested"* %this)
+ __declspec(dllexport) void normalDef();
+ __declspec(dllexport) void normalInclass() {}
+ __declspec(dllexport) void normalInlineDef();
+ __declspec(dllexport) inline void normalInlineDecl();
+
+ // M32-DAG: define dllexport x86_thiscallcc void @"\01?virtualDef@Nested@ExportMembers@@UAEXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // M64-DAG: define dllexport void @"\01?virtualDef@Nested@ExportMembers@@UEAAXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?virtualInclass@Nested@ExportMembers@@UAEXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // M64-DAG: define weak_odr dllexport void @"\01?virtualInclass@Nested@ExportMembers@@UEAAXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?virtualInlineDef@Nested@ExportMembers@@UAEXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // M64-DAG: define weak_odr dllexport void @"\01?virtualInlineDef@Nested@ExportMembers@@UEAAXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?virtualInlineDecl@Nested@ExportMembers@@UAEXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // M64-DAG: define weak_odr dllexport void @"\01?virtualInlineDecl@Nested@ExportMembers@@UEAAXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // G32-DAG: define dllexport x86_thiscallcc void @_ZN13ExportMembers6Nested10virtualDefEv(%"struct.ExportMembers::Nested"* %this)
+ // G64-DAG: define dllexport void @_ZN13ExportMembers6Nested10virtualDefEv(%"struct.ExportMembers::Nested"* %this)
+ // G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN13ExportMembers6Nested14virtualInclassEv(%"struct.ExportMembers::Nested"* %this)
+ // G64-DAG: define weak_odr dllexport void @_ZN13ExportMembers6Nested14virtualInclassEv(%"struct.ExportMembers::Nested"* %this)
+ // G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN13ExportMembers6Nested16virtualInlineDefEv(%"struct.ExportMembers::Nested"* %this)
+ // G64-DAG: define weak_odr dllexport void @_ZN13ExportMembers6Nested16virtualInlineDefEv(%"struct.ExportMembers::Nested"* %this)
+ // G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN13ExportMembers6Nested17virtualInlineDeclEv(%"struct.ExportMembers::Nested"* %this)
+ // G64-DAG: define weak_odr dllexport void @_ZN13ExportMembers6Nested17virtualInlineDeclEv(%"struct.ExportMembers::Nested"* %this)
+ __declspec(dllexport) virtual void virtualDef();
+ __declspec(dllexport) virtual void virtualInclass() {}
+ __declspec(dllexport) virtual void virtualInlineDef();
+ __declspec(dllexport) virtual inline void virtualInlineDecl();
+
+ // MSC-DAG: define dllexport void @"\01?staticDef@Nested@ExportMembers@@SAXXZ"()
+ // MSC-DAG: define weak_odr dllexport void @"\01?staticInclass@Nested@ExportMembers@@SAXXZ"()
+ // MSC-DAG: define weak_odr dllexport void @"\01?staticInlineDef@Nested@ExportMembers@@SAXXZ"()
+ // MSC-DAG: define weak_odr dllexport void @"\01?staticInlineDecl@Nested@ExportMembers@@SAXXZ"()
+ // GNU-DAG: define dllexport void @_ZN13ExportMembers6Nested9staticDefEv()
+ // GNU-DAG: define weak_odr dllexport void @_ZN13ExportMembers6Nested13staticInclassEv()
+ // GNU-DAG: define weak_odr dllexport void @_ZN13ExportMembers6Nested15staticInlineDefEv()
+ // GNU-DAG: define weak_odr dllexport void @_ZN13ExportMembers6Nested16staticInlineDeclEv()
+ __declspec(dllexport) static void staticDef();
+ __declspec(dllexport) static void staticInclass() {}
+ __declspec(dllexport) static void staticInlineDef();
+ __declspec(dllexport) static inline void staticInlineDecl();
+
+ // M32-DAG: define dllexport x86_thiscallcc void @"\01?protectedDef@Nested@ExportMembers@@IAEXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // M64-DAG: define dllexport void @"\01?protectedDef@Nested@ExportMembers@@IEAAXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // G32-DAG: define dllexport x86_thiscallcc void @_ZN13ExportMembers6Nested12protectedDefEv(%"struct.ExportMembers::Nested"* %this)
+ // G64-DAG: define dllexport void @_ZN13ExportMembers6Nested12protectedDefEv(%"struct.ExportMembers::Nested"* %this)
+ // MSC-DAG: define dllexport void @"\01?protectedStaticDef@Nested@ExportMembers@@KAXXZ"()
+ // GNU-DAG: define dllexport void @_ZN13ExportMembers6Nested18protectedStaticDefEv()
+protected:
+ __declspec(dllexport) void protectedDef();
+ __declspec(dllexport) static void protectedStaticDef();
+
+ // M32-DAG: define dllexport x86_thiscallcc void @"\01?privateDef@Nested@ExportMembers@@AAEXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // M64-DAG: define dllexport void @"\01?privateDef@Nested@ExportMembers@@AEAAXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // G32-DAG: define dllexport x86_thiscallcc void @_ZN13ExportMembers6Nested10privateDefEv(%"struct.ExportMembers::Nested"* %this)
+ // G64-DAG: define dllexport void @_ZN13ExportMembers6Nested10privateDefEv(%"struct.ExportMembers::Nested"* %this)
+ // MSC-DAG: define dllexport void @"\01?privateStaticDef@Nested@ExportMembers@@CAXXZ"()
+ // GNU-DAG: define dllexport void @_ZN13ExportMembers6Nested16privateStaticDefEv()
+private:
+ __declspec(dllexport) void privateDef();
+ __declspec(dllexport) static void privateStaticDef();
+
+ // M32-DAG: define x86_thiscallcc void @"\01?ignored@Nested@ExportMembers@@QAEXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // M64-DAG: define void @"\01?ignored@Nested@ExportMembers@@QEAAXXZ"(%"struct.ExportMembers::Nested"* %this)
+ // G32-DAG: define x86_thiscallcc void @_ZN13ExportMembers6Nested7ignoredEv(%"struct.ExportMembers::Nested"* %this)
+ // G64-DAG: define void @_ZN13ExportMembers6Nested7ignoredEv(%"struct.ExportMembers::Nested"* %this)
+public:
+ void ignored();
+
+ // MSC-DAG: @"\01?StaticField@Nested@ExportMembers@@2HA" = dllexport global i32 1, align 4
+ // MSC-DAG: @"\01?StaticConstField@Nested@ExportMembers@@2HB" = dllexport constant i32 1, align 4
+ // MSC-DAG: @"\01?StaticConstFieldEqualInit@Nested@ExportMembers@@2HB" = weak_odr dllexport constant i32 1, align 4
+ // MSC-DAG: @"\01?StaticConstFieldBraceInit@Nested@ExportMembers@@2HB" = weak_odr dllexport constant i32 1, align 4
+ // MSC-DAG: @"\01?ConstexprField@Nested@ExportMembers@@2HB" = weak_odr dllexport constant i32 1, align 4
+ // GNU-DAG: @_ZN13ExportMembers6Nested11StaticFieldE = dllexport global i32 1, align 4
+ // GNU-DAG: @_ZN13ExportMembers6Nested16StaticConstFieldE = dllexport constant i32 1, align 4
+ // GNU-DAG: @_ZN13ExportMembers6Nested25StaticConstFieldEqualInitE = dllexport constant i32 1, align 4
+ // GNU-DAG: @_ZN13ExportMembers6Nested25StaticConstFieldBraceInitE = dllexport constant i32 1, align 4
+ // GNU-DAG: @_ZN13ExportMembers6Nested14ConstexprFieldE = dllexport constant i32 1, align 4
+ __declspec(dllexport) static int StaticField;
+ __declspec(dllexport) static const int StaticConstField;
+ __declspec(dllexport) static const int StaticConstFieldEqualInit = 1;
+ __declspec(dllexport) static const int StaticConstFieldBraceInit{1};
+ __declspec(dllexport) constexpr static int ConstexprField = 1;
+};
+
+ void ExportMembers::Nested::normalDef() {}
+inline void ExportMembers::Nested::normalInlineDef() {}
+ void ExportMembers::Nested::normalInlineDecl() {}
+ void ExportMembers::Nested::virtualDef() {}
+inline void ExportMembers::Nested::virtualInlineDef() {}
+ void ExportMembers::Nested::virtualInlineDecl() {}
+ void ExportMembers::Nested::staticDef() {}
+inline void ExportMembers::Nested::staticInlineDef() {}
+ void ExportMembers::Nested::staticInlineDecl() {}
+ void ExportMembers::Nested::ignored() {}
+ void ExportMembers::Nested::protectedDef() {}
+ void ExportMembers::Nested::protectedStaticDef() {}
+ void ExportMembers::Nested::privateDef() {}
+ void ExportMembers::Nested::privateStaticDef() {}
+
+ int ExportMembers::Nested::StaticField = 1;
+const int ExportMembers::Nested::StaticConstField = 1;
+const int ExportMembers::Nested::StaticConstFieldEqualInit;
+const int ExportMembers::Nested::StaticConstFieldBraceInit;
+constexpr int ExportMembers::Nested::ConstexprField;
+
+
+// Export special member functions.
+struct ExportSpecials {
+ // M32-DAG: define dllexport x86_thiscallcc %struct.ExportSpecials* @"\01??0ExportSpecials@@QAE@XZ"(%struct.ExportSpecials* returned %this)
+ // M64-DAG: define dllexport %struct.ExportSpecials* @"\01??0ExportSpecials@@QEAA@XZ"(%struct.ExportSpecials* returned %this)
+ // G32-DAG: define dllexport x86_thiscallcc void @_ZN14ExportSpecialsC1Ev(%struct.ExportSpecials* %this)
+ // G64-DAG: define dllexport void @_ZN14ExportSpecialsC1Ev(%struct.ExportSpecials* %this)
+ // G32-DAG: define dllexport x86_thiscallcc void @_ZN14ExportSpecialsC2Ev(%struct.ExportSpecials* %this)
+ // G64-DAG: define dllexport void @_ZN14ExportSpecialsC2Ev(%struct.ExportSpecials* %this)
+ __declspec(dllexport) ExportSpecials();
+
+ // M32-DAG: define dllexport x86_thiscallcc void @"\01??1ExportSpecials@@QAE@XZ"(%struct.ExportSpecials* %this)
+ // M64-DAG: define dllexport void @"\01??1ExportSpecials@@QEAA@XZ"(%struct.ExportSpecials* %this)
+ // G32-DAG: define dllexport x86_thiscallcc void @_ZN14ExportSpecialsD1Ev(%struct.ExportSpecials* %this)
+ // G64-DAG: define dllexport void @_ZN14ExportSpecialsD1Ev(%struct.ExportSpecials* %this)
+ // G32-DAG: define dllexport x86_thiscallcc void @_ZN14ExportSpecialsD2Ev(%struct.ExportSpecials* %this)
+ // G64-DAG: define dllexport void @_ZN14ExportSpecialsD2Ev(%struct.ExportSpecials* %this)
+ __declspec(dllexport) ~ExportSpecials();
+
+ // M32-DAG: define dllexport x86_thiscallcc %struct.ExportSpecials* @"\01??0ExportSpecials@@QAE@ABU0@@Z"(%struct.ExportSpecials* returned %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
+ // M64-DAG: define dllexport %struct.ExportSpecials* @"\01??0ExportSpecials@@QEAA@AEBU0@@Z"(%struct.ExportSpecials* returned %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
+ // G32-DAG: define dllexport x86_thiscallcc void @_ZN14ExportSpecialsC1ERKS_(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
+ // G64-DAG: define dllexport void @_ZN14ExportSpecialsC1ERKS_(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
+ // G32-DAG: define dllexport x86_thiscallcc void @_ZN14ExportSpecialsC2ERKS_(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
+ // G64-DAG: define dllexport void @_ZN14ExportSpecialsC2ERKS_(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
+ __declspec(dllexport) ExportSpecials(const ExportSpecials&);
+
+ // M32-DAG: define dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportSpecials* @"\01??4ExportSpecials@@QAEAAU0@ABU0@@Z"(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
+ // M64-DAG: define dllexport dereferenceable({{[0-9]+}}) %struct.ExportSpecials* @"\01??4ExportSpecials@@QEAAAEAU0@AEBU0@@Z"(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
+ // G32-DAG: define dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportSpecials* @_ZN14ExportSpecialsaSERKS_(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
+ // G64-DAG: define dllexport dereferenceable({{[0-9]+}}) %struct.ExportSpecials* @_ZN14ExportSpecialsaSERKS_(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
+ __declspec(dllexport) ExportSpecials& operator=(const ExportSpecials&);
+
+ // M32-DAG: define dllexport x86_thiscallcc %struct.ExportSpecials* @"\01??0ExportSpecials@@QAE@$$QAU0@@Z"(%struct.ExportSpecials* returned %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
+ // M64-DAG: define dllexport %struct.ExportSpecials* @"\01??0ExportSpecials@@QEAA@$$QEAU0@@Z"(%struct.ExportSpecials* returned %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
+ // G32-DAG: define dllexport x86_thiscallcc void @_ZN14ExportSpecialsC1EOS_(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
+ // G64-DAG: define dllexport void @_ZN14ExportSpecialsC1EOS_(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
+ // G32-DAG: define dllexport x86_thiscallcc void @_ZN14ExportSpecialsC2EOS_(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
+ // G64-DAG: define dllexport void @_ZN14ExportSpecialsC2EOS_(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
+ __declspec(dllexport) ExportSpecials(ExportSpecials&&);
+
+ // M32-DAG: define dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportSpecials* @"\01??4ExportSpecials@@QAEAAU0@$$QAU0@@Z"(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
+ // M64-DAG: define dllexport dereferenceable({{[0-9]+}}) %struct.ExportSpecials* @"\01??4ExportSpecials@@QEAAAEAU0@$$QEAU0@@Z"(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
+ // G32-DAG: define dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportSpecials* @_ZN14ExportSpecialsaSEOS_(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
+ // G64-DAG: define dllexport dereferenceable({{[0-9]+}}) %struct.ExportSpecials* @_ZN14ExportSpecialsaSEOS_(%struct.ExportSpecials* %this, %struct.ExportSpecials* dereferenceable({{[0-9]+}}))
+ __declspec(dllexport) ExportSpecials& operator=(ExportSpecials&&);
+};
+ExportSpecials::ExportSpecials() {}
+ExportSpecials::~ExportSpecials() {}
+ExportSpecials::ExportSpecials(const ExportSpecials&) {}
+ExportSpecials& ExportSpecials::operator=(const ExportSpecials&) { return *this; }
+ExportSpecials::ExportSpecials(ExportSpecials&&) {}
+ExportSpecials& ExportSpecials::operator=(ExportSpecials&&) { return *this; }
+
+
+// Export class with inline special member functions.
+struct ExportInlineSpecials {
+ // M32-DAG: define weak_odr dllexport x86_thiscallcc %struct.ExportInlineSpecials* @"\01??0ExportInlineSpecials@@QAE@XZ"(%struct.ExportInlineSpecials* returned %this)
+ // M64-DAG: define weak_odr dllexport %struct.ExportInlineSpecials* @"\01??0ExportInlineSpecials@@QEAA@XZ"(
+ // G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN20ExportInlineSpecialsC1Ev(
+ // G64-DAG: define weak_odr dllexport void @_ZN20ExportInlineSpecialsC1Ev(
+ __declspec(dllexport) ExportInlineSpecials() {}
+
+ // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??1ExportInlineSpecials@@QAE@XZ"(
+ // M64-DAG: define weak_odr dllexport void @"\01??1ExportInlineSpecials@@QEAA@XZ"(
+ // G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN20ExportInlineSpecialsD1Ev(
+ // G64-DAG: define weak_odr dllexport void @_ZN20ExportInlineSpecialsD1Ev(
+ __declspec(dllexport) ~ExportInlineSpecials() {}
+
+ // M32-DAG: define weak_odr dllexport x86_thiscallcc %struct.ExportInlineSpecials* @"\01??0ExportInlineSpecials@@QAE@ABU0@@Z"(
+ // M64-DAG: define weak_odr dllexport %struct.ExportInlineSpecials* @"\01??0ExportInlineSpecials@@QEAA@AEBU0@@Z"(
+ // G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN20ExportInlineSpecialsC1ERKS_(
+ // G64-DAG: define weak_odr dllexport void @_ZN20ExportInlineSpecialsC1ERKS_(
+ __declspec(dllexport) inline ExportInlineSpecials(const ExportInlineSpecials&);
+
+ // M32-DAG: define weak_odr dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportInlineSpecials* @"\01??4ExportInlineSpecials@@QAEAAU0@ABU0@@Z"(
+ // M64-DAG: define weak_odr dllexport dereferenceable({{[0-9]+}}) %struct.ExportInlineSpecials* @"\01??4ExportInlineSpecials@@QEAAAEAU0@AEBU0@@Z"(
+ // G32-DAG: define weak_odr dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportInlineSpecials* @_ZN20ExportInlineSpecialsaSERKS_(
+ // G64-DAG: define weak_odr dllexport dereferenceable({{[0-9]+}}) %struct.ExportInlineSpecials* @_ZN20ExportInlineSpecialsaSERKS_(
+ __declspec(dllexport) ExportInlineSpecials& operator=(const ExportInlineSpecials&);
+
+ // M32-DAG: define weak_odr dllexport x86_thiscallcc %struct.ExportInlineSpecials* @"\01??0ExportInlineSpecials@@QAE@$$QAU0@@Z"(
+ // M64-DAG: define weak_odr dllexport %struct.ExportInlineSpecials* @"\01??0ExportInlineSpecials@@QEAA@$$QEAU0@@Z"(
+ // G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN20ExportInlineSpecialsC1EOS_(
+ // G64-DAG: define weak_odr dllexport void @_ZN20ExportInlineSpecialsC1EOS_(
+ __declspec(dllexport) ExportInlineSpecials(ExportInlineSpecials&&) {}
+
+ // M32-DAG: define weak_odr dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportInlineSpecials* @"\01??4ExportInlineSpecials@@QAEAAU0@$$QAU0@@Z"(
+ // M64-DAG: define weak_odr dllexport dereferenceable({{[0-9]+}}) %struct.ExportInlineSpecials* @"\01??4ExportInlineSpecials@@QEAAAEAU0@$$QEAU0@@Z"(
+ // G32-DAG: define weak_odr dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportInlineSpecials* @_ZN20ExportInlineSpecialsaSEOS_(
+ // G64-DAG: define weak_odr dllexport dereferenceable({{[0-9]+}}) %struct.ExportInlineSpecials* @_ZN20ExportInlineSpecialsaSEOS_(
+ __declspec(dllexport) ExportInlineSpecials& operator=(ExportInlineSpecials&&) { return *this; }
+};
+ExportInlineSpecials::ExportInlineSpecials(const ExportInlineSpecials&) {}
+inline ExportInlineSpecials& ExportInlineSpecials::operator=(const ExportInlineSpecials&) { return *this; }
+
+
+// Export defaulted member function definitions.
+struct ExportDefaultedDefs {
+ __declspec(dllexport) ExportDefaultedDefs();
+ __declspec(dllexport) ~ExportDefaultedDefs();
+ __declspec(dllexport) inline ExportDefaultedDefs(const ExportDefaultedDefs&);
+ __declspec(dllexport) ExportDefaultedDefs& operator=(const ExportDefaultedDefs&);
+ __declspec(dllexport) ExportDefaultedDefs(ExportDefaultedDefs&&);
+ __declspec(dllexport) ExportDefaultedDefs& operator=(ExportDefaultedDefs&&);
+};
+
+// M32-DAG: define dllexport x86_thiscallcc %struct.ExportDefaultedDefs* @"\01??0ExportDefaultedDefs@@QAE@XZ"(%struct.ExportDefaultedDefs* returned %this)
+// M64-DAG: define dllexport %struct.ExportDefaultedDefs* @"\01??0ExportDefaultedDefs@@QEAA@XZ"(%struct.ExportDefaultedDefs* returned %this)
+// G32-DAG: define dllexport x86_thiscallcc void @_ZN19ExportDefaultedDefsC1Ev(%struct.ExportDefaultedDefs* %this)
+// G64-DAG: define dllexport void @_ZN19ExportDefaultedDefsC1Ev(%struct.ExportDefaultedDefs* %this)
+// G32-DAG: define dllexport x86_thiscallcc void @_ZN19ExportDefaultedDefsC2Ev(%struct.ExportDefaultedDefs* %this)
+// G64-DAG: define dllexport void @_ZN19ExportDefaultedDefsC2Ev(%struct.ExportDefaultedDefs* %this)
+__declspec(dllexport) ExportDefaultedDefs::ExportDefaultedDefs() = default;
+
+// M32-DAG: define dllexport x86_thiscallcc void @"\01??1ExportDefaultedDefs@@QAE@XZ"(%struct.ExportDefaultedDefs* %this)
+// M64-DAG: define dllexport void @"\01??1ExportDefaultedDefs@@QEAA@XZ"(%struct.ExportDefaultedDefs* %this)
+// G32-DAG: define dllexport x86_thiscallcc void @_ZN19ExportDefaultedDefsD1Ev(%struct.ExportDefaultedDefs* %this)
+// G64-DAG: define dllexport void @_ZN19ExportDefaultedDefsD1Ev(%struct.ExportDefaultedDefs* %this)
+// G32-DAG: define dllexport x86_thiscallcc void @_ZN19ExportDefaultedDefsD2Ev(%struct.ExportDefaultedDefs* %this)
+// G64-DAG: define dllexport void @_ZN19ExportDefaultedDefsD2Ev(%struct.ExportDefaultedDefs* %this)
+ExportDefaultedDefs::~ExportDefaultedDefs() = default;
+
+// M32-DAG: define weak_odr dllexport x86_thiscallcc %struct.ExportDefaultedDefs* @"\01??0ExportDefaultedDefs@@QAE@ABU0@@Z"(%struct.ExportDefaultedDefs* returned %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// M64-DAG: define weak_odr dllexport %struct.ExportDefaultedDefs* @"\01??0ExportDefaultedDefs@@QEAA@AEBU0@@Z"(%struct.ExportDefaultedDefs* returned %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN19ExportDefaultedDefsC1ERKS_(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// G64-DAG: define weak_odr dllexport void @_ZN19ExportDefaultedDefsC1ERKS_(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN19ExportDefaultedDefsC2ERKS_(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// G64-DAG: define weak_odr dllexport void @_ZN19ExportDefaultedDefsC2ERKS_(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
+__declspec(dllexport) ExportDefaultedDefs::ExportDefaultedDefs(const ExportDefaultedDefs&) = default;
+
+// M32-DAG: define weak_odr dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportDefaultedDefs* @"\01??4ExportDefaultedDefs@@QAEAAU0@ABU0@@Z"(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// M64-DAG: define weak_odr dllexport dereferenceable({{[0-9]+}}) %struct.ExportDefaultedDefs* @"\01??4ExportDefaultedDefs@@QEAAAEAU0@AEBU0@@Z"(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// G32-DAG: define weak_odr dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportDefaultedDefs* @_ZN19ExportDefaultedDefsaSERKS_(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// G64-DAG: define weak_odr dllexport dereferenceable({{[0-9]+}}) %struct.ExportDefaultedDefs* @_ZN19ExportDefaultedDefsaSERKS_(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
+inline ExportDefaultedDefs& ExportDefaultedDefs::operator=(const ExportDefaultedDefs&) = default;
+
+// M32-DAG: define dllexport x86_thiscallcc %struct.ExportDefaultedDefs* @"\01??0ExportDefaultedDefs@@QAE@$$QAU0@@Z"(%struct.ExportDefaultedDefs* returned %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// M64-DAG: define dllexport %struct.ExportDefaultedDefs* @"\01??0ExportDefaultedDefs@@QEAA@$$QEAU0@@Z"(%struct.ExportDefaultedDefs* returned %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// G32-DAG: define dllexport x86_thiscallcc void @_ZN19ExportDefaultedDefsC1EOS_(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// G64-DAG: define dllexport void @_ZN19ExportDefaultedDefsC1EOS_(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// G32-DAG: define dllexport x86_thiscallcc void @_ZN19ExportDefaultedDefsC2EOS_(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// G64-DAG: define dllexport void @_ZN19ExportDefaultedDefsC2EOS_(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
+__declspec(dllexport) ExportDefaultedDefs::ExportDefaultedDefs(ExportDefaultedDefs&&) = default;
+
+// M32-DAG: define dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportDefaultedDefs* @"\01??4ExportDefaultedDefs@@QAEAAU0@$$QAU0@@Z"(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// M64-DAG: define dllexport dereferenceable({{[0-9]+}}) %struct.ExportDefaultedDefs* @"\01??4ExportDefaultedDefs@@QEAAAEAU0@$$QEAU0@@Z"(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// G32-DAG: define dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportDefaultedDefs* @_ZN19ExportDefaultedDefsaSEOS_(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// G64-DAG: define dllexport dereferenceable({{[0-9]+}}) %struct.ExportDefaultedDefs* @_ZN19ExportDefaultedDefsaSEOS_(%struct.ExportDefaultedDefs* %this, %struct.ExportDefaultedDefs* dereferenceable({{[0-9]+}}))
+ExportDefaultedDefs& ExportDefaultedDefs::operator=(ExportDefaultedDefs&&) = default;
+
+
+// Export allocation functions.
+struct ExportAlloc {
+ __declspec(dllexport) void* operator new(__SIZE_TYPE__);
+ __declspec(dllexport) void* operator new[](__SIZE_TYPE__);
+ __declspec(dllexport) void operator delete(void*);
+ __declspec(dllexport) void operator delete[](void*);
+};
+
+// M32-DAG: define dllexport i8* @"\01??2ExportAlloc@@SAPAXI@Z"(i32 %n)
+// M64-DAG: define dllexport i8* @"\01??2ExportAlloc@@SAPEAX_K@Z"(i64 %n)
+// G32-DAG: define dllexport i8* @_ZN11ExportAllocnwEj(i32 %n)
+// G64-DAG: define dllexport i8* @_ZN11ExportAllocnwEy(i64 %n)
+void* ExportAlloc::operator new(__SIZE_TYPE__ n) { return malloc(n); }
+
+// M32-DAG: define dllexport i8* @"\01??_UExportAlloc@@SAPAXI@Z"(i32 %n)
+// M64-DAG: define dllexport i8* @"\01??_UExportAlloc@@SAPEAX_K@Z"(i64 %n)
+// G32-DAG: define dllexport i8* @_ZN11ExportAllocnaEj(i32 %n)
+// G64-DAG: define dllexport i8* @_ZN11ExportAllocnaEy(i64 %n)
+void* ExportAlloc::operator new[](__SIZE_TYPE__ n) { return malloc(n); }
+
+// M32-DAG: define dllexport void @"\01??3ExportAlloc@@SAXPAX@Z"(i8* %p)
+// M64-DAG: define dllexport void @"\01??3ExportAlloc@@SAXPEAX@Z"(i8* %p)
+// G32-DAG: define dllexport void @_ZN11ExportAllocdlEPv(i8* %p)
+// G64-DAG: define dllexport void @_ZN11ExportAllocdlEPv(i8* %p)
+void ExportAlloc::operator delete(void* p) { free(p); }
+
+// M32-DAG: define dllexport void @"\01??_VExportAlloc@@SAXPAX@Z"(i8* %p)
+// M64-DAG: define dllexport void @"\01??_VExportAlloc@@SAXPEAX@Z"(i8* %p)
+// G32-DAG: define dllexport void @_ZN11ExportAllocdaEPv(i8* %p)
+// G64-DAG: define dllexport void @_ZN11ExportAllocdaEPv(i8* %p)
+void ExportAlloc::operator delete[](void* p) { free(p); }
+
+
+//===----------------------------------------------------------------------===//
+// Class member templates
+//===----------------------------------------------------------------------===//
+
+struct MemFunTmpl {
+ template<typename T> void normalDef() {}
+ template<typename T> __declspec(dllexport) void exportedNormal() {}
+ template<typename T> static void staticDef() {}
+ template<typename T> __declspec(dllexport) static void exportedStatic() {}
+};
+
+// Export implicit instantiation of an exported member function template.
+void useMemFunTmpl() {
+ // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??$exportedNormal@UImplicitInst_Exported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this)
+ // M64-DAG: define weak_odr dllexport void @"\01??$exportedNormal@UImplicitInst_Exported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this)
+ // G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN10MemFunTmpl14exportedNormalI21ImplicitInst_ExportedEEvv(%struct.MemFunTmpl* %this)
+ // G64-DAG: define weak_odr dllexport void @_ZN10MemFunTmpl14exportedNormalI21ImplicitInst_ExportedEEvv(%struct.MemFunTmpl* %this)
+ MemFunTmpl().exportedNormal<ImplicitInst_Exported>();
+
+ // MSC-DAG: define weak_odr dllexport void @"\01??$exportedStatic@UImplicitInst_Exported@@@MemFunTmpl@@SAXXZ"()
+ // GNU-DAG: define weak_odr dllexport void @_ZN10MemFunTmpl14exportedStaticI21ImplicitInst_ExportedEEvv()
+ MemFunTmpl().exportedStatic<ImplicitInst_Exported>();
+}
+
+
+// Export explicit instantiation declaration of an exported member function
+// template.
+// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??$exportedNormal@UExplicitDecl_Exported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this)
+// M64-DAG: define weak_odr dllexport void @"\01??$exportedNormal@UExplicitDecl_Exported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this)
+// G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN10MemFunTmpl14exportedNormalI21ExplicitDecl_ExportedEEvv(%struct.MemFunTmpl* %this)
+// G64-DAG: define weak_odr dllexport void @_ZN10MemFunTmpl14exportedNormalI21ExplicitDecl_ExportedEEvv(%struct.MemFunTmpl* %this)
+extern template void MemFunTmpl::exportedNormal<ExplicitDecl_Exported>();
+ template void MemFunTmpl::exportedNormal<ExplicitDecl_Exported>();
+
+// MSC-DAG: define weak_odr dllexport void @"\01??$exportedStatic@UExplicitDecl_Exported@@@MemFunTmpl@@SAXXZ"()
+// GNU-DAG: define weak_odr dllexport void @_ZN10MemFunTmpl14exportedStaticI21ExplicitDecl_ExportedEEvv()
+extern template void MemFunTmpl::exportedStatic<ExplicitDecl_Exported>();
+ template void MemFunTmpl::exportedStatic<ExplicitDecl_Exported>();
+
+
+// Export explicit instantiation definition of an exported member function
+// template.
+// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??$exportedNormal@UExplicitInst_Exported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this)
+// M64-DAG: define weak_odr dllexport void @"\01??$exportedNormal@UExplicitInst_Exported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this)
+// G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN10MemFunTmpl14exportedNormalI21ExplicitInst_ExportedEEvv(%struct.MemFunTmpl* %this)
+// G64-DAG: define weak_odr dllexport void @_ZN10MemFunTmpl14exportedNormalI21ExplicitInst_ExportedEEvv(%struct.MemFunTmpl* %this)
+template void MemFunTmpl::exportedNormal<ExplicitInst_Exported>();
+
+// MSC-DAG: define weak_odr dllexport void @"\01??$exportedStatic@UExplicitInst_Exported@@@MemFunTmpl@@SAXXZ"()
+// GNU-DAG: define weak_odr dllexport void @_ZN10MemFunTmpl14exportedStaticI21ExplicitInst_ExportedEEvv()
+template void MemFunTmpl::exportedStatic<ExplicitInst_Exported>();
+
+
+// Export specialization of an exported member function template.
+// M32-DAG: define dllexport x86_thiscallcc void @"\01??$exportedNormal@UExplicitSpec_Def_Exported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this)
+// M64-DAG: define dllexport void @"\01??$exportedNormal@UExplicitSpec_Def_Exported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this)
+// G32-DAG: define dllexport x86_thiscallcc void @_ZN10MemFunTmpl14exportedNormalI25ExplicitSpec_Def_ExportedEEvv(%struct.MemFunTmpl* %this)
+// G64-DAG: define dllexport void @_ZN10MemFunTmpl14exportedNormalI25ExplicitSpec_Def_ExportedEEvv(%struct.MemFunTmpl* %this)
+template<> __declspec(dllexport) void MemFunTmpl::exportedNormal<ExplicitSpec_Def_Exported>() {}
+
+// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??$exportedNormal@UExplicitSpec_InlineDef_Exported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this)
+// M64-DAG: define weak_odr dllexport void @"\01??$exportedNormal@UExplicitSpec_InlineDef_Exported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this)
+// G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN10MemFunTmpl14exportedNormalI31ExplicitSpec_InlineDef_ExportedEEvv(%struct.MemFunTmpl* %this)
+// G64-DAG: define weak_odr dllexport void @_ZN10MemFunTmpl14exportedNormalI31ExplicitSpec_InlineDef_ExportedEEvv(%struct.MemFunTmpl* %this)
+template<> __declspec(dllexport) inline void MemFunTmpl::exportedNormal<ExplicitSpec_InlineDef_Exported>() {}
+
+// MSC-DAG: define dllexport void @"\01??$exportedStatic@UExplicitSpec_Def_Exported@@@MemFunTmpl@@SAXXZ"()
+// GNU-DAG: define dllexport void @_ZN10MemFunTmpl14exportedStaticI25ExplicitSpec_Def_ExportedEEvv()
+template<> __declspec(dllexport) void MemFunTmpl::exportedStatic<ExplicitSpec_Def_Exported>() {}
+
+// MSC-DAG: define weak_odr dllexport void @"\01??$exportedStatic@UExplicitSpec_InlineDef_Exported@@@MemFunTmpl@@SAXXZ"()
+// GNU-DAG: define weak_odr dllexport void @_ZN10MemFunTmpl14exportedStaticI31ExplicitSpec_InlineDef_ExportedEEvv()
+template<> __declspec(dllexport) inline void MemFunTmpl::exportedStatic<ExplicitSpec_InlineDef_Exported>() {}
+
+
+// Not exporting specialization of an exported member function template without
+// explicit dllexport.
+// M32-DAG: define x86_thiscallcc void @"\01??$exportedNormal@UExplicitSpec_NotExported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this)
+// M64-DAG: define void @"\01??$exportedNormal@UExplicitSpec_NotExported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this)
+// G32-DAG: define x86_thiscallcc void @_ZN10MemFunTmpl14exportedNormalI24ExplicitSpec_NotExportedEEvv(%struct.MemFunTmpl* %this)
+// G64-DAG: define void @_ZN10MemFunTmpl14exportedNormalI24ExplicitSpec_NotExportedEEvv(%struct.MemFunTmpl* %this)
+template<> void MemFunTmpl::exportedNormal<ExplicitSpec_NotExported>() {}
+
+// M32-DAG: define void @"\01??$exportedStatic@UExplicitSpec_NotExported@@@MemFunTmpl@@SAXXZ"()
+// GNU-DAG: define void @_ZN10MemFunTmpl14exportedStaticI24ExplicitSpec_NotExportedEEvv()
+template<> void MemFunTmpl::exportedStatic<ExplicitSpec_NotExported>() {}
+
+
+// Export explicit instantiation declaration of a non-exported member function
+// template.
+// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??$normalDef@UExplicitDecl_Exported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this)
+// M64-DAG: define weak_odr dllexport void @"\01??$normalDef@UExplicitDecl_Exported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this)
+// G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN10MemFunTmpl9normalDefI21ExplicitDecl_ExportedEEvv(%struct.MemFunTmpl* %this)
+// G64-DAG: define weak_odr dllexport void @_ZN10MemFunTmpl9normalDefI21ExplicitDecl_ExportedEEvv(%struct.MemFunTmpl* %this)
+extern template __declspec(dllexport) void MemFunTmpl::normalDef<ExplicitDecl_Exported>();
+ template __declspec(dllexport) void MemFunTmpl::normalDef<ExplicitDecl_Exported>();
+
+// M32-DAG: define weak_odr dllexport void @"\01??$staticDef@UExplicitDecl_Exported@@@MemFunTmpl@@SAXXZ"()
+// GNU-DAG: define weak_odr dllexport void @_ZN10MemFunTmpl9staticDefI21ExplicitDecl_ExportedEEvv()
+extern template __declspec(dllexport) void MemFunTmpl::staticDef<ExplicitDecl_Exported>();
+ template __declspec(dllexport) void MemFunTmpl::staticDef<ExplicitDecl_Exported>();
+
+
+// Export explicit instantiation definition of a non-exported member function
+// template.
+// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??$normalDef@UExplicitInst_Exported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this)
+// M64-DAG: define weak_odr dllexport void @"\01??$normalDef@UExplicitInst_Exported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this)
+// G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN10MemFunTmpl9normalDefI21ExplicitInst_ExportedEEvv(%struct.MemFunTmpl* %this)
+// G64-DAG: define weak_odr dllexport void @_ZN10MemFunTmpl9normalDefI21ExplicitInst_ExportedEEvv(%struct.MemFunTmpl* %this)
+template __declspec(dllexport) void MemFunTmpl::normalDef<ExplicitInst_Exported>();
+
+// MSC-DAG: define weak_odr dllexport void @"\01??$staticDef@UExplicitInst_Exported@@@MemFunTmpl@@SAXXZ"()
+// GNU-DAG: define weak_odr dllexport void @_ZN10MemFunTmpl9staticDefI21ExplicitInst_ExportedEEvv()
+template __declspec(dllexport) void MemFunTmpl::staticDef<ExplicitInst_Exported>();
+
+
+// Export specialization of a non-exported member function template.
+// M32-DAG: define dllexport x86_thiscallcc void @"\01??$normalDef@UExplicitSpec_Def_Exported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this)
+// M64-DAG: define dllexport void @"\01??$normalDef@UExplicitSpec_Def_Exported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this)
+// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??$normalDef@UExplicitSpec_InlineDef_Exported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this)
+// M64-DAG: define weak_odr dllexport void @"\01??$normalDef@UExplicitSpec_InlineDef_Exported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this)
+// G32-DAG: define dllexport x86_thiscallcc void @_ZN10MemFunTmpl9normalDefI25ExplicitSpec_Def_ExportedEEvv(%struct.MemFunTmpl* %this)
+// G64-DAG: define dllexport void @_ZN10MemFunTmpl9normalDefI25ExplicitSpec_Def_ExportedEEvv(%struct.MemFunTmpl* %this)
+// G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN10MemFunTmpl9normalDefI31ExplicitSpec_InlineDef_ExportedEEvv(%struct.MemFunTmpl* %this)
+// G64-DAG: define weak_odr dllexport void @_ZN10MemFunTmpl9normalDefI31ExplicitSpec_InlineDef_ExportedEEvv(%struct.MemFunTmpl* %this)
+template<> __declspec(dllexport) void MemFunTmpl::normalDef<ExplicitSpec_Def_Exported>() {}
+template<> __declspec(dllexport) inline void MemFunTmpl::normalDef<ExplicitSpec_InlineDef_Exported>() {}
+
+// MSC-DAG: define dllexport void @"\01??$staticDef@UExplicitSpec_Def_Exported@@@MemFunTmpl@@SAXXZ"()
+// MSC-DAG: define weak_odr dllexport void @"\01??$staticDef@UExplicitSpec_InlineDef_Exported@@@MemFunTmpl@@SAXXZ"()
+// GNU-DAG: define dllexport void @_ZN10MemFunTmpl9staticDefI25ExplicitSpec_Def_ExportedEEvv()
+// GNU-DAG: define weak_odr dllexport void @_ZN10MemFunTmpl9staticDefI31ExplicitSpec_InlineDef_ExportedEEvv()
+template<> __declspec(dllexport) void MemFunTmpl::staticDef<ExplicitSpec_Def_Exported>() {}
+template<> __declspec(dllexport) inline void MemFunTmpl::staticDef<ExplicitSpec_InlineDef_Exported>() {}
+
+
+
+struct MemVarTmpl {
+ template<typename T> static const int StaticVar = 1;
+ template<typename T> __declspec(dllexport) static const int ExportedStaticVar = 1;
+};
+template<typename T> const int MemVarTmpl::StaticVar;
+template<typename T> const int MemVarTmpl::ExportedStaticVar;
+
+// Export implicit instantiation of an exported member variable template.
+// MSC-DAG: @"\01??$ExportedStaticVar@UImplicitInst_Exported@@@MemVarTmpl@@2HB" = weak_odr dllexport constant i32 1, align 4
+// GNU-DAG: @_ZN10MemVarTmpl17ExportedStaticVarI21ImplicitInst_ExportedEE = weak_odr dllexport constant i32 1, align 4
+int useMemVarTmpl() { return MemVarTmpl::ExportedStaticVar<ImplicitInst_Exported>; }
+
+// Export explicit instantiation declaration of an exported member variable
+// template.
+// MSC-DAG: @"\01??$ExportedStaticVar@UExplicitDecl_Exported@@@MemVarTmpl@@2HB" = weak_odr dllexport constant i32 1, align 4
+// GNU-DAG: @_ZN10MemVarTmpl17ExportedStaticVarI21ExplicitDecl_ExportedEE = weak_odr dllexport constant i32 1, align 4
+extern template const int MemVarTmpl::ExportedStaticVar<ExplicitDecl_Exported>;
+ template const int MemVarTmpl::ExportedStaticVar<ExplicitDecl_Exported>;
+
+// Export explicit instantiation definition of an exported member variable
+// template.
+// MSC-DAG: @"\01??$ExportedStaticVar@UExplicitInst_Exported@@@MemVarTmpl@@2HB" = weak_odr dllexport constant i32 1, align 4
+// GNU-DAG: @_ZN10MemVarTmpl17ExportedStaticVarI21ExplicitInst_ExportedEE = weak_odr dllexport constant i32 1, align 4
+template const int MemVarTmpl::ExportedStaticVar<ExplicitInst_Exported>;
+
+// Export specialization of an exported member variable template.
+// MSC-DAG: @"\01??$ExportedStaticVar@UExplicitSpec_Def_Exported@@@MemVarTmpl@@2HB" = dllexport constant i32 1, align 4
+// GNU-DAG: @_ZN10MemVarTmpl17ExportedStaticVarI25ExplicitSpec_Def_ExportedEE = dllexport constant i32 1, align 4
+template<> __declspec(dllexport) const int MemVarTmpl::ExportedStaticVar<ExplicitSpec_Def_Exported> = 1;
+
+// Not exporting specialization of an exported member variable template without
+// explicit dllexport.
+// MSC-DAG: @"\01??$ExportedStaticVar@UExplicitSpec_NotExported@@@MemVarTmpl@@2HB" = constant i32 1, align 4
+// GNU-DAG: @_ZN10MemVarTmpl17ExportedStaticVarI24ExplicitSpec_NotExportedEE = constant i32 1, align 4
+template<> const int MemVarTmpl::ExportedStaticVar<ExplicitSpec_NotExported> = 1;
+
+
+// Export explicit instantiation declaration of a non-exported member variable
+// template.
+// MSC-DAG: @"\01??$StaticVar@UExplicitDecl_Exported@@@MemVarTmpl@@2HB" = weak_odr dllexport constant i32 1, align 4
+// GNU-DAG: @_ZN10MemVarTmpl9StaticVarI21ExplicitDecl_ExportedEE = weak_odr dllexport constant i32 1, align 4
+extern template __declspec(dllexport) const int MemVarTmpl::StaticVar<ExplicitDecl_Exported>;
+ template __declspec(dllexport) const int MemVarTmpl::StaticVar<ExplicitDecl_Exported>;
+
+// Export explicit instantiation definition of a non-exported member variable
+// template.
+// MSC-DAG: @"\01??$StaticVar@UExplicitInst_Exported@@@MemVarTmpl@@2HB" = weak_odr dllexport constant i32 1, align 4
+// GNU-DAG: @_ZN10MemVarTmpl9StaticVarI21ExplicitInst_ExportedEE = weak_odr dllexport constant i32 1, align 4
+template __declspec(dllexport) const int MemVarTmpl::StaticVar<ExplicitInst_Exported>;
+
+// Export specialization of a non-exported member variable template.
+// MSC-DAG: @"\01??$StaticVar@UExplicitSpec_Def_Exported@@@MemVarTmpl@@2HB" = dllexport constant i32 1, align 4
+// GNU-DAG: @_ZN10MemVarTmpl9StaticVarI25ExplicitSpec_Def_ExportedEE = dllexport constant i32 1, align 4
+template<> __declspec(dllexport) const int MemVarTmpl::StaticVar<ExplicitSpec_Def_Exported> = 1;
diff --git a/test/CodeGenCXX/dllexport.cpp b/test/CodeGenCXX/dllexport.cpp
new file mode 100644
index 000000000000..5097abf0c094
--- /dev/null
+++ b/test/CodeGenCXX/dllexport.cpp
@@ -0,0 +1,686 @@
+// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -std=c++1y -O0 -o - %s | FileCheck --check-prefix=MSC --check-prefix=M32 %s
+// RUN: %clang_cc1 -triple x86_64-windows-msvc -emit-llvm -std=c++1y -O0 -o - %s | FileCheck --check-prefix=MSC --check-prefix=M64 %s
+// RUN: %clang_cc1 -triple i686-windows-gnu -emit-llvm -std=c++1y -O0 -o - %s | FileCheck --check-prefix=GNU --check-prefix=G32 %s
+// RUN: %clang_cc1 -triple x86_64-windows-gnu -emit-llvm -std=c++1y -O0 -o - %s | FileCheck --check-prefix=GNU --check-prefix=G64 %s
+
+// RUN: %clang_cc1 -triple i686-pc-win32 -O1 -mconstructor-aliases -std=c++1y -emit-llvm -o - %s | FileCheck %s --check-prefix=MSC --check-prefix=M32
+
+// Helper structs to make templates more expressive.
+struct ImplicitInst_Exported {};
+struct ExplicitDecl_Exported {};
+struct ExplicitInst_Exported {};
+struct ExplicitSpec_Exported {};
+struct ExplicitSpec_Def_Exported {};
+struct ExplicitSpec_InlineDef_Exported {};
+struct ExplicitSpec_NotExported {};
+struct External { int v; };
+
+#define JOIN2(x, y) x##y
+#define JOIN(x, y) JOIN2(x, y)
+#define UNIQ(name) JOIN(name, __LINE__)
+#define USEVAR(var) int UNIQ(use)() { return var; }
+#define USE(func) void UNIQ(use)() { func(); }
+#define USEMEMFUNC(class, func) void (class::*UNIQ(use)())() { return &class::func; }
+#define INSTVAR(var) template int var;
+#define INST(func) template void func();
+
+// The vftable for struct W is comdat largest because we have RTTI.
+// M32-DAG: $"\01??_7W@@6B@" = comdat largest
+
+
+//===----------------------------------------------------------------------===//
+// Globals
+//===----------------------------------------------------------------------===//
+
+// Declarations are not exported.
+// MSC-NOT: @"\01?ExternGlobalDecl@@3HA"
+// GNU-NOT: @ExternGlobalDecl
+__declspec(dllexport) extern int ExternGlobalDecl;
+
+// dllexport implies a definition.
+// MSC-DAG: @"\01?GlobalDef@@3HA" = dllexport global i32 0, align 4
+// GNU-DAG: @GlobalDef = dllexport global i32 0, align 4
+__declspec(dllexport) int GlobalDef;
+
+// Export definition.
+// MSC-DAG: @"\01?GlobalInit1@@3HA" = dllexport global i32 1, align 4
+// GNU-DAG: @GlobalInit1 = dllexport global i32 1, align 4
+__declspec(dllexport) int GlobalInit1 = 1;
+
+// MSC-DAG: @"\01?GlobalInit2@@3HA" = dllexport global i32 1, align 4
+// GNU-DAG: @GlobalInit2 = dllexport global i32 1, align 4
+int __declspec(dllexport) GlobalInit2 = 1;
+
+// Declare, then export definition.
+// MSC-DAG: @"\01?GlobalDeclInit@@3HA" = dllexport global i32 1, align 4
+// GNU-DAG: @GlobalDeclInit = dllexport global i32 1, align 4
+__declspec(dllexport) extern int GlobalDeclInit;
+int GlobalDeclInit = 1;
+
+// Redeclarations
+// MSC-DAG: @"\01?GlobalRedecl1@@3HA" = dllexport global i32 0, align 4
+// GNU-DAG: @GlobalRedecl1 = dllexport global i32 0, align 4
+__declspec(dllexport) extern int GlobalRedecl1;
+__declspec(dllexport) int GlobalRedecl1;
+
+// MSC-DAG: @"\01?GlobalRedecl2@@3HA" = dllexport global i32 0, align 4
+// GNU-DAG: @GlobalRedecl2 = dllexport global i32 0, align 4
+__declspec(dllexport) extern int GlobalRedecl2;
+ int GlobalRedecl2;
+
+// MSC-DAG: @"\01?ExternalGlobal@ns@@3HA" = dllexport global i32 0, align 4
+// GNU-DAG: @_ZN2ns14ExternalGlobalE = dllexport global i32 0, align 4
+namespace ns { __declspec(dllexport) int ExternalGlobal; }
+
+// MSC-DAG: @"\01?ExternalAutoTypeGlobal@@3UExternal@@A" = dllexport global %struct.External zeroinitializer, align 4
+// GNU-DAG: @ExternalAutoTypeGlobal = dllexport global %struct.External zeroinitializer, align 4
+__declspec(dllexport) auto ExternalAutoTypeGlobal = External();
+
+int f();
+// MSC-DAG: @"\01?x@?0??nonInlineStaticLocalsFunc@@YAHXZ@4HA" = internal {{(unnamed_addr )*}}global i32 0
+// MSC-DAG: @"\01?$S1@?0??nonInlineStaticLocalsFunc@@YAHXZ@4IA" = internal {{(unnamed_addr )*}}global i32 0
+int __declspec(dllexport) nonInlineStaticLocalsFunc() {
+ static int x = f();
+ return x++;
+};
+
+// MSC-DAG: @"\01?x@?1??inlineStaticLocalsFunc@@YAHXZ@4HA" = weak_odr dllexport global i32 0
+// MSC-DAG: @"\01??_B?1??inlineStaticLocalsFunc@@YAHXZ@51" = weak_odr dllexport global i32 0
+// Note: MinGW doesn't seem to export the static local here.
+inline int __declspec(dllexport) inlineStaticLocalsFunc() {
+ static int x = f();
+ return x++;
+}
+
+
+
+//===----------------------------------------------------------------------===//
+// Variable templates
+//===----------------------------------------------------------------------===//
+
+// Declarations are not exported.
+
+// dllexport implies a definition.
+// MSC-NOT: @"\01??$VarTmplDef@UExplicitInst_Exported@@@@3HA"
+// GNU-NOT: @_Z10VarTmplDefI21ExplicitInst_ExportedE
+template<typename T> __declspec(dllexport) int VarTmplDef;
+INSTVAR(VarTmplDef<ExplicitInst_Exported>)
+
+// MSC-DAG: @"\01??$VarTmplImplicitDef@UImplicitInst_Exported@@@@3HA" = external dllexport global
+// GNU-DAG: @_Z18VarTmplImplicitDefI21ImplicitInst_ExportedE = external dllexport global
+template<typename T> __declspec(dllexport) int VarTmplImplicitDef;
+USEVAR(VarTmplImplicitDef<ImplicitInst_Exported>)
+
+// Export definition.
+// MSC-DAG: @"\01??$VarTmplInit1@UExplicitInst_Exported@@@@3HA" = weak_odr dllexport global i32 1, align 4
+// GNU-DAG: @_Z12VarTmplInit1I21ExplicitInst_ExportedE = weak_odr dllexport global i32 1, align 4
+template<typename T> __declspec(dllexport) int VarTmplInit1 = 1;
+INSTVAR(VarTmplInit1<ExplicitInst_Exported>)
+
+// MSC-DAG: @"\01??$VarTmplInit2@UExplicitInst_Exported@@@@3HA" = weak_odr dllexport global i32 1, align 4
+// GNU-DAG: @_Z12VarTmplInit2I21ExplicitInst_ExportedE = weak_odr dllexport global i32 1, align 4
+template<typename T> int __declspec(dllexport) VarTmplInit2 = 1;
+INSTVAR(VarTmplInit2<ExplicitInst_Exported>)
+
+// Declare, then export definition.
+// MSC-DAG: @"\01??$VarTmplDeclInit@UExplicitInst_Exported@@@@3HA" = weak_odr dllexport global i32 1, align 4
+// GNU-DAG: @_Z15VarTmplDeclInitI21ExplicitInst_ExportedE = weak_odr dllexport global i32 1, align 4
+template<typename T> __declspec(dllexport) extern int VarTmplDeclInit;
+template<typename T> int VarTmplDeclInit = 1;
+INSTVAR(VarTmplDeclInit<ExplicitInst_Exported>)
+
+// Redeclarations
+// MSC-DAG: @"\01??$VarTmplRedecl1@UExplicitInst_Exported@@@@3HA" = weak_odr dllexport global i32 1, align 4
+// GNU-DAG: @_Z14VarTmplRedecl1I21ExplicitInst_ExportedE = weak_odr dllexport global i32 1, align 4
+template<typename T> __declspec(dllexport) extern int VarTmplRedecl1;
+template<typename T> __declspec(dllexport) int VarTmplRedecl1 = 1;
+INSTVAR(VarTmplRedecl1<ExplicitInst_Exported>)
+
+// MSC-DAG: @"\01??$VarTmplRedecl2@UExplicitInst_Exported@@@@3HA" = weak_odr dllexport global i32 1, align 4
+// GNU-DAG: @_Z14VarTmplRedecl2I21ExplicitInst_ExportedE = weak_odr dllexport global i32 1, align 4
+template<typename T> __declspec(dllexport) extern int VarTmplRedecl2;
+template<typename T> int VarTmplRedecl2 = 1;
+INSTVAR(VarTmplRedecl2<ExplicitInst_Exported>)
+
+// MSC-DAG: @"\01??$ExternalVarTmpl@UExplicitInst_Exported@@@ns@@3HA" = weak_odr dllexport global i32 1, align 4
+// GNU-DAG: @_ZN2ns15ExternalVarTmplI21ExplicitInst_ExportedEE = weak_odr dllexport global i32 1, align 4
+namespace ns { template<typename T> __declspec(dllexport) int ExternalVarTmpl = 1; }
+INSTVAR(ns::ExternalVarTmpl<ExplicitInst_Exported>)
+
+// MSC-DAG: @"\01??$ExternalAutoTypeVarTmpl@UExplicitInst_Exported@@@@3UExternal@@A" = weak_odr dllexport global %struct.External zeroinitializer, align 4
+// GNU-DAG: @_Z23ExternalAutoTypeVarTmplI21ExplicitInst_ExportedE = weak_odr dllexport global %struct.External zeroinitializer, align 4
+template<typename T> __declspec(dllexport) auto ExternalAutoTypeVarTmpl = External();
+template External ExternalAutoTypeVarTmpl<ExplicitInst_Exported>;
+
+
+template<typename T> int VarTmpl = 1;
+template<typename T> __declspec(dllexport) int ExportedVarTmpl = 1;
+
+// Export implicit instantiation of an exported variable template.
+// MSC-DAG: @"\01??$ExportedVarTmpl@UImplicitInst_Exported@@@@3HA" = weak_odr dllexport global i32 1, align 4
+// GNU-DAG: @_Z15ExportedVarTmplI21ImplicitInst_ExportedE = weak_odr dllexport global i32 1, align 4
+USEVAR(ExportedVarTmpl<ImplicitInst_Exported>)
+
+// Export explicit instantiation declaration of an exported variable template.
+// MSC-DAG: @"\01??$ExportedVarTmpl@UImplicitInst_Exported@@@@3HA" = weak_odr dllexport global i32 1, align 4
+// GNU-DAG: @_Z15ExportedVarTmplI21ExplicitDecl_ExportedE = weak_odr dllexport global i32 1, align 4
+extern template int ExportedVarTmpl<ExplicitDecl_Exported>;
+ template int ExportedVarTmpl<ExplicitDecl_Exported>;
+
+// Export explicit instantiation definition of an exported variable template.
+// MSC-DAG: @"\01??$ExportedVarTmpl@UImplicitInst_Exported@@@@3HA" = weak_odr dllexport global i32 1, align 4
+// GNU-DAG: @_Z15ExportedVarTmplI21ExplicitInst_ExportedE = weak_odr dllexport global i32 1, align 4
+template __declspec(dllexport) int ExportedVarTmpl<ExplicitInst_Exported>;
+
+// Export specialization of an exported variable template.
+// MSC-DAG: @"\01??$ExportedVarTmpl@UExplicitSpec_Exported@@@@3HA" = dllexport global i32 0, align 4
+// GNU-DAG: @_Z15ExportedVarTmplI21ExplicitSpec_ExportedE = dllexport global i32 0, align 4
+template<> __declspec(dllexport) int ExportedVarTmpl<ExplicitSpec_Exported>;
+
+// MSC-DAG: @"\01??$ExportedVarTmpl@UExplicitSpec_Def_Exported@@@@3HA" = dllexport global i32 1, align 4
+// GNU-DAG: @_Z15ExportedVarTmplI25ExplicitSpec_Def_ExportedE = dllexport global i32 1, align 4
+template<> __declspec(dllexport) int ExportedVarTmpl<ExplicitSpec_Def_Exported> = 1;
+
+// Not exporting specialization of an exported variable template without
+// explicit dllexport.
+// MSC-DAG: @"\01??$ExportedVarTmpl@UExplicitSpec_NotExported@@@@3HA" = global i32 0, align 4
+// GNU-DAG: @_Z15ExportedVarTmplI24ExplicitSpec_NotExportedE = global i32 0, align 4
+template<> int ExportedVarTmpl<ExplicitSpec_NotExported>;
+
+
+// Export explicit instantiation declaration of a non-exported variable template.
+// MSC-DAG: @"\01??$VarTmpl@UExplicitDecl_Exported@@@@3HA" = weak_odr dllexport global i32 1, align 4
+// GNU-DAG: @_Z7VarTmplI21ExplicitDecl_ExportedE = weak_odr dllexport global i32 1, align 4
+extern template __declspec(dllexport) int VarTmpl<ExplicitDecl_Exported>;
+ template __declspec(dllexport) int VarTmpl<ExplicitDecl_Exported>;
+
+// Export explicit instantiation definition of a non-exported variable template.
+// MSC-DAG: @"\01??$VarTmpl@UExplicitInst_Exported@@@@3HA" = weak_odr dllexport global i32 1, align 4
+// GNU-DAG: @_Z7VarTmplI21ExplicitInst_ExportedE = weak_odr dllexport global i32 1, align 4
+template __declspec(dllexport) int VarTmpl<ExplicitInst_Exported>;
+
+// Export specialization of a non-exported variable template.
+// MSC-DAG: @"\01??$VarTmpl@UExplicitSpec_Exported@@@@3HA" = dllexport global i32 0, align 4
+// GNU-DAG: @_Z7VarTmplI21ExplicitSpec_ExportedE = dllexport global i32 0, align 4
+template<> __declspec(dllexport) int VarTmpl<ExplicitSpec_Exported>;
+
+// MSC-DAG: @"\01??$VarTmpl@UExplicitSpec_Def_Exported@@@@3HA" = dllexport global i32 1, align 4
+// GNU-DAG: @_Z7VarTmplI25ExplicitSpec_Def_ExportedE = dllexport global i32 1, align 4
+template<> __declspec(dllexport) int VarTmpl<ExplicitSpec_Def_Exported> = 1;
+
+
+
+//===----------------------------------------------------------------------===//
+// Functions
+//===----------------------------------------------------------------------===//
+
+// Declarations are not exported.
+
+// Export function definition.
+// MSC-DAG: define dllexport void @"\01?def@@YAXXZ"()
+// GNU-DAG: define dllexport void @_Z3defv()
+__declspec(dllexport) void def() {}
+
+// extern "C"
+// MSC-DAG: define dllexport void @externC()
+// GNU-DAG: define dllexport void @externC()
+extern "C" __declspec(dllexport) void externC() {}
+
+// Export inline function.
+// MSC-DAG: define weak_odr dllexport void @"\01?inlineFunc@@YAXXZ"()
+// GNU-DAG: define weak_odr dllexport void @_Z10inlineFuncv()
+__declspec(dllexport) inline void inlineFunc() {}
+
+// MSC-DAG: define weak_odr dllexport void @"\01?inlineDecl@@YAXXZ"()
+// GNU-DAG: define weak_odr dllexport void @_Z10inlineDeclv()
+__declspec(dllexport) inline void inlineDecl();
+ void inlineDecl() {}
+
+// MSC-DAG: define weak_odr dllexport void @"\01?inlineDef@@YAXXZ"()
+// GNU-DAG: define weak_odr dllexport void @_Z9inlineDefv()
+__declspec(dllexport) void inlineDef();
+ inline void inlineDef() {}
+
+// Redeclarations
+// MSC-DAG: define dllexport void @"\01?redecl1@@YAXXZ"()
+// GNU-DAG: define dllexport void @_Z7redecl1v()
+__declspec(dllexport) void redecl1();
+__declspec(dllexport) void redecl1() {}
+
+// MSC-DAG: define dllexport void @"\01?redecl2@@YAXXZ"()
+// GNU-DAG: define dllexport void @_Z7redecl2v()
+__declspec(dllexport) void redecl2();
+ void redecl2() {}
+
+// Friend functions
+// MSC-DAG: define dllexport void @"\01?friend1@@YAXXZ"()
+// GNU-DAG: define dllexport void @_Z7friend1v()
+// MSC-DAG: define dllexport void @"\01?friend2@@YAXXZ"()
+// GNU-DAG: define dllexport void @_Z7friend2v()
+struct FuncFriend {
+ friend __declspec(dllexport) void friend1();
+ friend __declspec(dllexport) void friend2();
+};
+__declspec(dllexport) void friend1() {}
+ void friend2() {}
+
+// Implicit declarations can be redeclared with dllexport.
+// MSC-DAG: define dllexport noalias i8* @"\01??2@{{YAPAXI|YAPEAX_K}}@Z"(
+// GNU-DAG: define dllexport noalias i8* @_Znw{{[yj]}}(
+void* alloc(__SIZE_TYPE__ n);
+__declspec(dllexport) void* operator new(__SIZE_TYPE__ n) { return alloc(n); }
+
+// MSC-DAG: define dllexport void @"\01?externalFunc@ns@@YAXXZ"()
+// GNU-DAG: define dllexport void @_ZN2ns12externalFuncEv()
+namespace ns { __declspec(dllexport) void externalFunc() {} }
+
+
+
+//===----------------------------------------------------------------------===//
+// Function templates
+//===----------------------------------------------------------------------===//
+
+// Export function template definition.
+// MSC-DAG: define weak_odr dllexport void @"\01??$funcTmplDef@UExplicitInst_Exported@@@@YAXXZ"()
+// GNU-DAG: define weak_odr dllexport void @_Z11funcTmplDefI21ExplicitInst_ExportedEvv()
+template<typename T> __declspec(dllexport) void funcTmplDef() {}
+INST(funcTmplDef<ExplicitInst_Exported>)
+
+// Export inline function template.
+// MSC-DAG: define weak_odr dllexport void @"\01??$inlineFuncTmpl1@UExplicitInst_Exported@@@@YAXXZ"()
+// GNU-DAG: define weak_odr dllexport void @_Z15inlineFuncTmpl1I21ExplicitInst_ExportedEvv()
+template<typename T> __declspec(dllexport) inline void inlineFuncTmpl1() {}
+INST(inlineFuncTmpl1<ExplicitInst_Exported>)
+
+// MSC-DAG: define weak_odr dllexport void @"\01??$inlineFuncTmpl2@UExplicitInst_Exported@@@@YAXXZ"()
+// GNU-DAG: define weak_odr dllexport void @_Z15inlineFuncTmpl2I21ExplicitInst_ExportedEvv()
+template<typename T> inline void __attribute__((dllexport)) inlineFuncTmpl2() {}
+INST(inlineFuncTmpl2<ExplicitInst_Exported>)
+
+// MSC-DAG: define weak_odr dllexport void @"\01??$inlineFuncTmplDecl@UExplicitInst_Exported@@@@YAXXZ"()
+// GNU-DAG: define weak_odr dllexport void @_Z18inlineFuncTmplDeclI21ExplicitInst_ExportedEvv()
+template<typename T> __declspec(dllexport) inline void inlineFuncTmplDecl();
+template<typename T> void inlineFuncTmplDecl() {}
+INST(inlineFuncTmplDecl<ExplicitInst_Exported>)
+
+// MSC-DAG: define weak_odr dllexport void @"\01??$inlineFuncTmplDef@UExplicitInst_Exported@@@@YAXXZ"()
+// GNU-DAG: define weak_odr dllexport void @_Z17inlineFuncTmplDefI21ExplicitInst_ExportedEvv()
+template<typename T> __declspec(dllexport) void inlineFuncTmplDef();
+template<typename T> inline void inlineFuncTmplDef() {}
+INST(inlineFuncTmplDef<ExplicitInst_Exported>)
+
+
+// Redeclarations
+// MSC-DAG: define weak_odr dllexport void @"\01??$funcTmplRedecl1@UExplicitInst_Exported@@@@YAXXZ"()
+// GNU-DAG: define weak_odr dllexport void @_Z15funcTmplRedecl1I21ExplicitInst_ExportedEvv()
+template<typename T> __declspec(dllexport) void funcTmplRedecl1();
+template<typename T> __declspec(dllexport) void funcTmplRedecl1() {}
+INST(funcTmplRedecl1<ExplicitInst_Exported>)
+
+// MSC-DAG: define weak_odr dllexport void @"\01??$funcTmplRedecl2@UExplicitInst_Exported@@@@YAXXZ"()
+// GNU-DAG: define weak_odr dllexport void @_Z15funcTmplRedecl2I21ExplicitInst_ExportedEvv()
+template<typename T> __declspec(dllexport) void funcTmplRedecl2();
+template<typename T> void funcTmplRedecl2() {}
+INST(funcTmplRedecl2<ExplicitInst_Exported>)
+
+// MSC-DAG: define weak_odr dllexport void @"\01??$funcTmplRedecl3@UExplicitInst_Exported@@@@YAXXZ"()
+// GNU-DAG: define weak_odr dllexport void @_Z15funcTmplRedecl3I21ExplicitInst_ExportedEvv()
+template<typename T> __declspec(dllexport) void funcTmplRedecl3();
+template<typename T> void funcTmplRedecl3() {}
+INST(funcTmplRedecl3<ExplicitInst_Exported>)
+
+
+// Function template friends
+// MSC-DAG: define weak_odr dllexport void @"\01??$funcTmplFriend1@UExplicitInst_Exported@@@@YAXXZ"()
+// GNU-DAG: define weak_odr dllexport void @_Z15funcTmplFriend1I21ExplicitInst_ExportedEvv()
+// MSC-DAG: define weak_odr dllexport void @"\01??$funcTmplFriend2@UExplicitInst_Exported@@@@YAXXZ"()
+// GNU-DAG: define weak_odr dllexport void @_Z15funcTmplFriend2I21ExplicitInst_ExportedEvv()
+struct FuncTmplFriend {
+ template<typename T> friend __declspec(dllexport) void funcTmplFriend1();
+ template<typename T> friend __declspec(dllexport) void funcTmplFriend2();
+};
+template<typename T> __declspec(dllexport) void funcTmplFriend1() {}
+template<typename T> void funcTmplFriend2() {}
+INST(funcTmplFriend1<ExplicitInst_Exported>)
+INST(funcTmplFriend2<ExplicitInst_Exported>)
+
+// MSC-DAG: define weak_odr dllexport void @"\01??$externalFuncTmpl@UExplicitInst_Exported@@@ns@@YAXXZ"()
+// GNU-DAG: define weak_odr dllexport void @_ZN2ns16externalFuncTmplI21ExplicitInst_ExportedEEvv()
+namespace ns { template<typename T> __declspec(dllexport) void externalFuncTmpl() {} }
+INST(ns::externalFuncTmpl<ExplicitInst_Exported>)
+
+
+template<typename T> void funcTmpl() {}
+template<typename T> __declspec(dllexport) void exportedFuncTmpl() {}
+
+// Export implicit instantiation of an exported function template.
+// MSC-DAG: define weak_odr dllexport void @"\01??$exportedFuncTmpl@UImplicitInst_Exported@@@@YAXXZ"()
+// GNU-DAG: define weak_odr dllexport void @_Z16exportedFuncTmplI21ImplicitInst_ExportedEvv()
+USE(exportedFuncTmpl<ImplicitInst_Exported>)
+
+// Export explicit instantiation declaration of an exported function template.
+// MSC-DAG: define weak_odr dllexport void @"\01??$exportedFuncTmpl@UExplicitDecl_Exported@@@@YAXXZ"()
+// GNU-DAG: define weak_odr dllexport void @_Z16exportedFuncTmplI21ExplicitDecl_ExportedEvv()
+extern template void exportedFuncTmpl<ExplicitDecl_Exported>();
+ template void exportedFuncTmpl<ExplicitDecl_Exported>();
+
+// Export explicit instantiation definition of an exported function template.
+// MSC-DAG: define weak_odr dllexport void @"\01??$exportedFuncTmpl@UExplicitInst_Exported@@@@YAXXZ"()
+// GNU-DAG: define weak_odr dllexport void @_Z16exportedFuncTmplI21ExplicitInst_ExportedEvv()
+template void exportedFuncTmpl<ExplicitInst_Exported>();
+
+// Export specialization of an exported function template.
+// MSC-DAG: define dllexport void @"\01??$exportedFuncTmpl@UExplicitSpec_Def_Exported@@@@YAXXZ"()
+// GNU-DAG: define dllexport void @_Z16exportedFuncTmplI25ExplicitSpec_Def_ExportedEvv()
+template<> __declspec(dllexport) void exportedFuncTmpl<ExplicitSpec_Def_Exported>() {}
+
+// MSC-DAG: define weak_odr dllexport void @"\01??$exportedFuncTmpl@UExplicitSpec_InlineDef_Exported@@@@YAXXZ"()
+// GNU-DAG: define weak_odr dllexport void @_Z16exportedFuncTmplI31ExplicitSpec_InlineDef_ExportedEvv()
+template<> __declspec(dllexport) inline void exportedFuncTmpl<ExplicitSpec_InlineDef_Exported>() {}
+
+// Not exporting specialization of an exported function template without
+// explicit dllexport.
+// MSC-DAG: define void @"\01??$exportedFuncTmpl@UExplicitSpec_NotExported@@@@YAXXZ"()
+// GNU-DAG: define void @_Z16exportedFuncTmplI24ExplicitSpec_NotExportedEvv()
+template<> void exportedFuncTmpl<ExplicitSpec_NotExported>() {}
+
+
+// Export explicit instantiation declaration of a non-exported function template.
+// MSC-DAG: define weak_odr dllexport void @"\01??$funcTmpl@UExplicitDecl_Exported@@@@YAXXZ"()
+// GNU-DAG: define weak_odr dllexport void @_Z8funcTmplI21ExplicitDecl_ExportedEvv()
+extern template __declspec(dllexport) void funcTmpl<ExplicitDecl_Exported>();
+ template __declspec(dllexport) void funcTmpl<ExplicitDecl_Exported>();
+
+// Export explicit instantiation definition of a non-exported function template.
+// MSC-DAG: define weak_odr dllexport void @"\01??$funcTmpl@UExplicitInst_Exported@@@@YAXXZ"()
+// GNU-DAG: define weak_odr dllexport void @_Z8funcTmplI21ExplicitInst_ExportedEvv()
+template __declspec(dllexport) void funcTmpl<ExplicitInst_Exported>();
+
+// Export specialization of a non-exported function template.
+// MSC-DAG: define dllexport void @"\01??$funcTmpl@UExplicitSpec_Def_Exported@@@@YAXXZ"()
+// GNU-DAG: define dllexport void @_Z8funcTmplI25ExplicitSpec_Def_ExportedEvv()
+template<> __declspec(dllexport) void funcTmpl<ExplicitSpec_Def_Exported>() {}
+
+// MSC-DAG: define weak_odr dllexport void @"\01??$funcTmpl@UExplicitSpec_InlineDef_Exported@@@@YAXXZ"()
+// GNU-DAG: define weak_odr dllexport void @_Z8funcTmplI31ExplicitSpec_InlineDef_ExportedEvv()
+template<> __declspec(dllexport) inline void funcTmpl<ExplicitSpec_InlineDef_Exported>() {}
+
+
+
+//===----------------------------------------------------------------------===//
+// Precedence
+//===----------------------------------------------------------------------===//
+
+// dllexport takes precedence over the dllimport if both are specified.
+// MSC-DAG: @"\01?PrecedenceGlobal1A@@3HA" = dllexport global i32 0, align 4
+// MSC-DAG: @"\01?PrecedenceGlobal1B@@3HA" = dllexport global i32 0, align 4
+// GNU-DAG: @PrecedenceGlobal1A = dllexport global i32 0, align 4
+// GNU-DAG: @PrecedenceGlobal1B = dllexport global i32 0, align 4
+__attribute__((dllimport, dllexport)) int PrecedenceGlobal1A; // dllimport ignored
+__declspec(dllimport) __declspec(dllexport) int PrecedenceGlobal1B; // dllimport ignored
+
+// MSC-DAG: @"\01?PrecedenceGlobal2A@@3HA" = dllexport global i32 0, align 4
+// MSC-DAG: @"\01?PrecedenceGlobal2B@@3HA" = dllexport global i32 0, align 4
+// GNU-DAG: @PrecedenceGlobal2A = dllexport global i32 0, align 4
+// GNU-DAG: @PrecedenceGlobal2B = dllexport global i32 0, align 4
+__attribute__((dllexport, dllimport)) int PrecedenceGlobal2A; // dllimport ignored
+__declspec(dllexport) __declspec(dllimport) int PrecedenceGlobal2B; // dllimport ignored
+
+// MSC-DAG: @"\01?PrecedenceGlobalRedecl1@@3HA" = dllexport global i32 0, align 4
+// GNU-DAG: @PrecedenceGlobalRedecl1 = dllexport global i32 0, align 4
+__declspec(dllexport) extern int PrecedenceGlobalRedecl1;
+__declspec(dllimport) int PrecedenceGlobalRedecl1 = 0;
+
+// MSC-DAG: @"\01?PrecedenceGlobalRedecl2@@3HA" = dllexport global i32 0, align 4
+// GNU-DAG: @PrecedenceGlobalRedecl2 = dllexport global i32 0, align 4
+__declspec(dllimport) extern int PrecedenceGlobalRedecl2;
+__declspec(dllexport) int PrecedenceGlobalRedecl2;
+
+// MSC-DAG: @"\01?PrecedenceGlobalMixed1@@3HA" = dllexport global i32 0, align 4
+// GNU-DAG: @PrecedenceGlobalMixed1 = dllexport global i32 0, align 4
+__attribute__((dllexport)) extern int PrecedenceGlobalMixed1;
+__declspec(dllimport) int PrecedenceGlobalMixed1 = 0;
+
+// MSC-DAG: @"\01?PrecedenceGlobalMixed2@@3HA" = dllexport global i32 0, align 4
+// GNU-DAG: @PrecedenceGlobalMixed2 = dllexport global i32 0, align 4
+__attribute__((dllimport)) extern int PrecedenceGlobalMixed2;
+__declspec(dllexport) int PrecedenceGlobalMixed2;
+
+// MSC-DAG: define dllexport void @"\01?precedence1A@@YAXXZ"
+// MSC-DAG: define dllexport void @"\01?precedence1B@@YAXXZ"
+// GNU-DAG: define dllexport void @_Z12precedence1Av()
+// GNU-DAG: define dllexport void @_Z12precedence1Bv()
+void __attribute__((dllimport, dllexport)) precedence1A() {}
+void __declspec(dllimport) __declspec(dllexport) precedence1B() {}
+
+// MSC-DAG: define dllexport void @"\01?precedence2A@@YAXXZ"
+// MSC-DAG: define dllexport void @"\01?precedence2B@@YAXXZ"
+// GNU-DAG: define dllexport void @_Z12precedence2Av()
+// GNU-DAG: define dllexport void @_Z12precedence2Bv()
+void __attribute__((dllexport, dllimport)) precedence2A() {}
+void __declspec(dllexport) __declspec(dllimport) precedence2B() {}
+
+// MSC-DAG: define dllexport void @"\01?precedenceRedecl1@@YAXXZ"
+// GNU-DAG: define dllexport void @_Z17precedenceRedecl1v()
+void __declspec(dllimport) precedenceRedecl1();
+void __declspec(dllexport) precedenceRedecl1() {}
+
+// MSC-DAG: define dllexport void @"\01?precedenceRedecl2@@YAXXZ"
+// GNU-DAG: define dllexport void @_Z17precedenceRedecl2v()
+void __declspec(dllexport) precedenceRedecl2();
+void __declspec(dllimport) precedenceRedecl2() {}
+
+
+
+//===----------------------------------------------------------------------===//
+// Classes
+//===----------------------------------------------------------------------===//
+
+struct S {
+ void __declspec(dllexport) a() {}
+ // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?a@S@@QAEXXZ"
+
+ struct T {
+ void __declspec(dllexport) a() {}
+ // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?a@T@S@@QAEXXZ"
+ };
+};
+
+
+struct __declspec(dllexport) T {
+ // Copy assignment operator:
+ // M32-DAG: define weak_odr dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.T* @"\01??4T@@QAEAAU0@ABU0@@Z"
+
+ // Explicitly defaulted copy constructur:
+ T(const T&) = default;
+ // M32-DAG: define weak_odr dllexport x86_thiscallcc %struct.T* @"\01??0T@@QAE@ABU0@@Z"
+
+ void a() {}
+ // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?a@T@@QAEXXZ"
+
+ static int b;
+ // M32-DAG: @"\01?b@T@@2HA" = external dllexport global i32
+
+ static int c;
+ // M32-DAG: @"\01?c@T@@2HA" = dllexport global i32 0, align 4
+};
+
+USEVAR(T::b)
+int T::c;
+
+template <typename T> struct __declspec(dllexport) U { void foo() {} };
+// The U<int> specialization below must cause the following to be emitted:
+// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?foo@?$U@H@@QAEXXZ"
+// M32-DAG: define weak_odr dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.U* @"\01??4?$U@H@@QAEAAU0@ABU0@@Z"
+struct __declspec(dllexport) V : public U<int> { };
+
+
+struct __declspec(dllexport) W { virtual void foo() {} };
+// Default ctor:
+// M32-DAG: define weak_odr dllexport x86_thiscallcc %struct.W* @"\01??0W@@QAE@XZ"
+// Copy ctor:
+// M32-DAG: define weak_odr dllexport x86_thiscallcc %struct.W* @"\01??0W@@QAE@ABU0@@Z"
+// vftable:
+// M32-DAG: [[W_VTABLE:@.*]] = private unnamed_addr constant [2 x i8*] [i8* bitcast (%rtti.CompleteObjectLocator* @"\01??_R4W@@6B@" to i8*), i8* bitcast (void (%struct.W*)* @"\01?foo@W@@UAEXXZ" to i8*)], comdat $"\01??_7W@@6B@"
+// M32-DAG: @"\01??_7W@@6B@" = dllexport unnamed_addr alias getelementptr inbounds ([2 x i8*]* [[W_VTABLE]], i32 0, i32 1)
+// G32-DAG: @_ZTV1W = weak_odr dllexport unnamed_addr constant [3 x i8*] [i8* null, i8* bitcast ({ i8*, i8* }* @_ZTI1W to i8*), i8* bitcast (void (%struct.W*)* @_ZN1W3fooEv to i8*)]
+
+struct __declspec(dllexport) X : public virtual W {};
+// vbtable:
+// M32-DAG: @"\01??_8X@@7B@" = weak_odr dllexport unnamed_addr constant [2 x i32] [i32 0, i32 4]
+
+struct __declspec(dllexport) Y {
+ // Move assignment operator:
+ // M32-DAG: define weak_odr dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.Y* @"\01??4Y@@QAEAAU0@$$QAU0@@Z"
+
+ int x;
+};
+
+struct __declspec(dllexport) Z { virtual ~Z() {} };
+// The scalar deleting dtor does not get exported:
+// M32-DAG: define linkonce_odr x86_thiscallcc void @"\01??_GZ@@UAEPAXI@Z"
+
+
+// The user-defined dtor does get exported:
+// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??1Z@@UAE@XZ"
+
+namespace DontUseDtorAlias {
+ struct __declspec(dllexport) A { ~A(); };
+ struct __declspec(dllexport) B : A { ~B(); };
+ A::~A() { }
+ B::~B() { }
+ // Emit a real definition of B's constructor; don't alias it to A's.
+ // M32-DAG: define dllexport x86_thiscallcc void @"\01??1B@DontUseDtorAlias@@QAE@XZ"
+}
+
+struct __declspec(dllexport) DefaultedCtorsDtors {
+ DefaultedCtorsDtors() = default;
+ // M32-DAG: define weak_odr dllexport x86_thiscallcc %struct.DefaultedCtorsDtors* @"\01??0DefaultedCtorsDtors@@QAE@XZ"
+ ~DefaultedCtorsDtors() = default;
+ // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??1DefaultedCtorsDtors@@QAE@XZ"
+};
+
+namespace ReferencedInlineMethodInNestedClass {
+ struct __declspec(dllexport) S {
+ void foo() {
+ t->bar();
+ }
+ struct T {
+ void bar() {}
+ };
+ T *t;
+ };
+ // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?foo@S@ReferencedInlineMethodInNestedClass@@QAEXXZ"
+ // M32-DAG: define linkonce_odr x86_thiscallcc void @"\01?bar@T@S@ReferencedInlineMethodInNestedClass@@QAEXXZ"
+}
+
+// MS ignores DLL attributes on partial specializations.
+template <typename T> struct PartiallySpecializedClassTemplate {};
+template <typename T> struct __declspec(dllexport) PartiallySpecializedClassTemplate<T*> { void f() {} };
+USEMEMFUNC(PartiallySpecializedClassTemplate<void*>, f);
+// M32-DAG: define linkonce_odr x86_thiscallcc void @"\01?f@?$PartiallySpecializedClassTemplate@PAX@@QAEXXZ"
+// G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN33PartiallySpecializedClassTemplateIPvE1fEv
+
+template <typename T> struct ExplicitlySpecializedClassTemplate {};
+template <> struct __declspec(dllexport) ExplicitlySpecializedClassTemplate<void*> { void f() {} };
+USEMEMFUNC(ExplicitlySpecializedClassTemplate<void*>, f);
+// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?f@?$ExplicitlySpecializedClassTemplate@PAX@@QAEXXZ"
+// G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN34ExplicitlySpecializedClassTemplateIPvE1fEv
+
+//===----------------------------------------------------------------------===//
+// Classes with template base classes
+//===----------------------------------------------------------------------===//
+
+template <typename T> struct ClassTemplate { void func() {} };
+template <typename T> struct __declspec(dllexport) ExportedClassTemplate { void func() {} };
+template <typename T> struct __declspec(dllimport) ImportedClassTemplate { void func() {} };
+
+template <typename T> struct ExplicitlySpecializedTemplate { void func() {} };
+template <> struct ExplicitlySpecializedTemplate<int> { void func() {} };
+template <typename T> struct ExplicitlyExportSpecializedTemplate { void func() {} };
+template <> struct __declspec(dllexport) ExplicitlyExportSpecializedTemplate<int> { void func() {} };
+template <typename T> struct ExplicitlyImportSpecializedTemplate { void func() {} };
+template <> struct __declspec(dllimport) ExplicitlyImportSpecializedTemplate<int> { void func() {} };
+
+template <typename T> struct ExplicitlyInstantiatedTemplate { void func() {} };
+template struct ExplicitlyInstantiatedTemplate<int>;
+template <typename T> struct ExplicitlyExportInstantiatedTemplate { void func() {} };
+template struct __declspec(dllexport) ExplicitlyExportInstantiatedTemplate<int>;
+template <typename T> struct ExplicitlyImportInstantiatedTemplate { void func() {} };
+template struct __declspec(dllimport) ExplicitlyImportInstantiatedTemplate<int>;
+
+
+// MS: ClassTemplate<int> gets exported.
+struct __declspec(dllexport) DerivedFromTemplate : public ClassTemplate<int> {};
+USEMEMFUNC(ClassTemplate<int>, func)
+// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?func@?$ClassTemplate@H@@QAEXXZ"
+// G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ClassTemplateIiE4funcEv
+
+// ExportedTemplate is explicitly exported.
+struct __declspec(dllexport) DerivedFromExportedTemplate : public ExportedClassTemplate<int> {};
+// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?func@?$ExportedClassTemplate@H@@QAEXXZ"
+// G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN21ExportedClassTemplateIiE4funcEv
+
+// ImportedClassTemplate is explicitly imported.
+struct __declspec(dllexport) DerivedFromImportedTemplate : public ImportedClassTemplate<int> {};
+USEMEMFUNC(ImportedClassTemplate<int>, func)
+// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?func@?$ImportedClassTemplate@H@@QAEXXZ"
+// G32-DAG: declare dllimport x86_thiscallcc void @_ZN21ImportedClassTemplateIiE4funcEv
+
+// Base class already instantiated without dll attribute.
+struct DerivedFromTemplateD : public ClassTemplate<double> {};
+struct __declspec(dllexport) DerivedFromTemplateD2 : public ClassTemplate<double> {};
+USEMEMFUNC(ClassTemplate<double>, func)
+// M32-DAG: define linkonce_odr x86_thiscallcc void @"\01?func@?$ClassTemplate@N@@QAEXXZ"
+// G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ClassTemplateIdE4funcEv
+
+// MS: Base class already instantiated with different dll attribute.
+struct __declspec(dllimport) DerivedFromTemplateB : public ClassTemplate<bool> {};
+struct __declspec(dllexport) DerivedFromTemplateB2 : public ClassTemplate<bool> {};
+USEMEMFUNC(ClassTemplate<bool>, func)
+// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?func@?$ClassTemplate@_N@@QAEXXZ"
+// G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ClassTemplateIbE4funcEv
+
+// Base class already specialized without dll attribute.
+struct __declspec(dllexport) DerivedFromExplicitlySpecializedTemplate : public ExplicitlySpecializedTemplate<int> {};
+USEMEMFUNC(ExplicitlySpecializedTemplate<int>, func)
+// M32-DAG: define linkonce_odr x86_thiscallcc void @"\01?func@?$ExplicitlySpecializedTemplate@H@@QAEXXZ"
+// G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN29ExplicitlySpecializedTemplateIiE4funcEv
+
+// Base class alredy specialized with export attribute.
+struct __declspec(dllexport) DerivedFromExplicitlyExportSpecializedTemplate : public ExplicitlyExportSpecializedTemplate<int> {};
+USEMEMFUNC(ExplicitlyExportSpecializedTemplate<int>, func)
+// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?func@?$ExplicitlyExportSpecializedTemplate@H@@QAEXXZ"
+// G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN35ExplicitlyExportSpecializedTemplateIiE4funcEv
+
+// Base class already specialized with import attribute.
+struct __declspec(dllexport) DerivedFromExplicitlyImportSpecializedTemplate : public ExplicitlyImportSpecializedTemplate<int> {};
+USEMEMFUNC(ExplicitlyImportSpecializedTemplate<int>, func)
+// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?func@?$ExplicitlyImportSpecializedTemplate@H@@QAEXXZ"
+// G32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @_ZN35ExplicitlyImportSpecializedTemplateIiE4funcEv
+
+// Base class already instantiated without dll attribute.
+struct __declspec(dllexport) DerivedFromExplicitlyInstantiatedTemplate : public ExplicitlyInstantiatedTemplate<int> {};
+USEMEMFUNC(ExplicitlyInstantiatedTemplate<int>, func)
+// M32-DAG: define weak_odr x86_thiscallcc void @"\01?func@?$ExplicitlyInstantiatedTemplate@H@@QAEXXZ"
+// G32-DAG: define weak_odr x86_thiscallcc void @_ZN30ExplicitlyInstantiatedTemplateIiE4funcEv
+
+// Base class already instantiated with export attribute.
+struct __declspec(dllexport) DerivedFromExplicitlyExportInstantiatedTemplate : public ExplicitlyExportInstantiatedTemplate<int> {};
+USEMEMFUNC(ExplicitlyExportInstantiatedTemplate<int>, func)
+// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?func@?$ExplicitlyExportInstantiatedTemplate@H@@QAEXXZ"
+// G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN36ExplicitlyExportInstantiatedTemplateIiE4funcEv
+
+// Base class already instantiated with import attribute.
+struct __declspec(dllexport) DerivedFromExplicitlyImportInstantiatedTemplate : public ExplicitlyImportInstantiatedTemplate<int> {};
+USEMEMFUNC(ExplicitlyImportInstantiatedTemplate<int>, func)
+// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?func@?$ExplicitlyImportInstantiatedTemplate@H@@QAEXXZ"
+// G32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @_ZN36ExplicitlyImportInstantiatedTemplateIiE4funcEv
+
+// MS: A dll attribute propagates through multiple levels of instantiation.
+template <typename T> struct TopClass { void func() {} };
+template <typename T> struct MiddleClass : public TopClass<T> { };
+struct __declspec(dllexport) BottomClass : public MiddleClass<int> { };
+USEMEMFUNC(TopClass<int>, func)
+// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?func@?$TopClass@H@@QAEXXZ"
+// G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN8TopClassIiE4funcEv
diff --git a/test/CodeGenCXX/dllimport-members.cpp b/test/CodeGenCXX/dllimport-members.cpp
new file mode 100644
index 000000000000..6656b92b0022
--- /dev/null
+++ b/test/CodeGenCXX/dllimport-members.cpp
@@ -0,0 +1,875 @@
+// RUN: %clang_cc1 -triple i686-windows-msvc -fms-compatibility -emit-llvm -std=c++1y -O0 -o - %s -DMSABI | FileCheck --check-prefix=MSC --check-prefix=M32 %s
+// RUN: %clang_cc1 -triple x86_64-windows-msvc -fms-compatibility -emit-llvm -std=c++1y -O0 -o - %s -DMSABI | FileCheck --check-prefix=MSC --check-prefix=M64 %s
+// RUN: %clang_cc1 -triple i686-windows-gnu -emit-llvm -std=c++1y -O0 -o - %s | FileCheck --check-prefix=GNU --check-prefix=G32 %s
+// RUN: %clang_cc1 -triple x86_64-windows-gnu -emit-llvm -std=c++1y -O0 -o - %s | FileCheck --check-prefix=GNU --check-prefix=G64 %s
+// RUN: %clang_cc1 -triple i686-windows-msvc -fms-compatibility -emit-llvm -std=c++1y -O1 -o - %s -DMSABI | FileCheck --check-prefix=MO1 %s
+// RUN: %clang_cc1 -triple i686-windows-gnu -emit-llvm -std=c++1y -O1 -o - %s | FileCheck --check-prefix=GO1 %s
+
+// Helper structs to make templates more expressive.
+struct ImplicitInst_Imported {};
+struct ExplicitDecl_Imported {};
+struct ExplicitInst_Imported {};
+struct ExplicitSpec_Imported {};
+struct ExplicitSpec_Def_Imported {};
+struct ExplicitSpec_InlineDef_Imported {};
+struct ExplicitSpec_NotImported {};
+
+#define JOIN2(x, y) x##y
+#define JOIN(x, y) JOIN2(x, y)
+#define UNIQ(name) JOIN(name, __LINE__)
+#define USE(func) void UNIQ(use)() { func(); }
+#define USEMV(cls, var) int UNIQ(use)() { return ref(cls::var); }
+#define USEMF(cls, fun) template<> void useMemFun<__LINE__, cls>() { cls().fun(); }
+#define USESPECIALS(cls) void UNIQ(use)() { useSpecials<cls>(); }
+
+template<typename T>
+T ref(T const& v) { return v; }
+
+template<int Line, typename T>
+void useMemFun();
+
+template<typename T>
+void useSpecials() {
+ T v; // Default constructor
+
+ T c1(static_cast<const T&>(v)); // Copy constructor
+ T c2 = static_cast<const T&>(v); // Copy constructor
+ T c3;
+ c3 = static_cast<const T&>(v); // Copy assignment
+
+ T m1(static_cast<T&&>(v)); // Move constructor
+ T m2 = static_cast<T&&>(v); // Move constructor
+ T m3;
+ m3 = static_cast<T&&>(v); // Move assignment
+}
+
+// Used to force non-trivial special members.
+struct ForceNonTrivial {
+ ForceNonTrivial();
+ ~ForceNonTrivial();
+ ForceNonTrivial(const ForceNonTrivial&);
+ ForceNonTrivial& operator=(const ForceNonTrivial&);
+ ForceNonTrivial(ForceNonTrivial&&);
+ ForceNonTrivial& operator=(ForceNonTrivial&&);
+};
+
+
+
+//===----------------------------------------------------------------------===//
+// Class members
+//===----------------------------------------------------------------------===//
+
+// Import individual members of a class.
+struct ImportMembers {
+ struct Nested;
+
+ // M32-DAG: define x86_thiscallcc void @"\01?normalDef@ImportMembers@@QAEXXZ"(%struct.ImportMembers* %this)
+ // M64-DAG: define void @"\01?normalDef@ImportMembers@@QEAAXXZ"(%struct.ImportMembers* %this)
+ // M32-DAG: declare dllimport x86_thiscallcc void @"\01?normalDecl@ImportMembers@@QAEXXZ"(%struct.ImportMembers*)
+ // M64-DAG: declare dllimport void @"\01?normalDecl@ImportMembers@@QEAAXXZ"(%struct.ImportMembers*)
+ // M32-DAG: declare dllimport x86_thiscallcc void @"\01?normalInclass@ImportMembers@@QAEXXZ"(%struct.ImportMembers*)
+ // M64-DAG: declare dllimport void @"\01?normalInclass@ImportMembers@@QEAAXXZ"(%struct.ImportMembers*)
+ // M32-DAG: declare dllimport x86_thiscallcc void @"\01?normalInlineDef@ImportMembers@@QAEXXZ"(%struct.ImportMembers*)
+ // M64-DAG: declare dllimport void @"\01?normalInlineDef@ImportMembers@@QEAAXXZ"(%struct.ImportMembers*)
+ // M32-DAG: declare dllimport x86_thiscallcc void @"\01?normalInlineDecl@ImportMembers@@QAEXXZ"(%struct.ImportMembers*)
+ // M64-DAG: declare dllimport void @"\01?normalInlineDecl@ImportMembers@@QEAAXXZ"(%struct.ImportMembers*)
+ // G32-DAG: define x86_thiscallcc void @_ZN13ImportMembers9normalDefEv(%struct.ImportMembers* %this)
+ // G64-DAG: define void @_ZN13ImportMembers9normalDefEv(%struct.ImportMembers* %this)
+ // G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers10normalDeclEv(%struct.ImportMembers*)
+ // G64-DAG: declare dllimport void @_ZN13ImportMembers10normalDeclEv(%struct.ImportMembers*)
+ // G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers13normalInclassEv(%struct.ImportMembers*)
+ // G64-DAG: declare dllimport void @_ZN13ImportMembers13normalInclassEv(%struct.ImportMembers*)
+ // G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers15normalInlineDefEv(%struct.ImportMembers*)
+ // G64-DAG: declare dllimport void @_ZN13ImportMembers15normalInlineDefEv(%struct.ImportMembers*)
+ // G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers16normalInlineDeclEv(%struct.ImportMembers*)
+ // G64-DAG: declare dllimport void @_ZN13ImportMembers16normalInlineDeclEv(%struct.ImportMembers*)
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?normalInclass@ImportMembers@@QAEXXZ"(
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?normalInlineDef@ImportMembers@@QAEXXZ"(
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?normalInlineDecl@ImportMembers@@QAEXXZ"(
+ // GO1-DAG: define available_externally dllimport x86_thiscallcc void @_ZN13ImportMembers13normalInclassEv(
+ // GO1-DAG: define available_externally dllimport x86_thiscallcc void @_ZN13ImportMembers15normalInlineDefEv(
+ // GO1-DAG: define available_externally dllimport x86_thiscallcc void @_ZN13ImportMembers16normalInlineDeclEv(
+ __declspec(dllimport) void normalDef(); // dllimport ignored
+ __declspec(dllimport) void normalDecl();
+ __declspec(dllimport) void normalInclass() {}
+ __declspec(dllimport) void normalInlineDef();
+ __declspec(dllimport) inline void normalInlineDecl();
+
+ // M32-DAG: define x86_thiscallcc void @"\01?virtualDef@ImportMembers@@UAEXXZ"(%struct.ImportMembers* %this)
+ // M64-DAG: define void @"\01?virtualDef@ImportMembers@@UEAAXXZ"(%struct.ImportMembers* %this)
+ // M32-DAG: declare dllimport x86_thiscallcc void @"\01?virtualDecl@ImportMembers@@UAEXXZ"(%struct.ImportMembers*)
+ // M64-DAG: declare dllimport void @"\01?virtualDecl@ImportMembers@@UEAAXXZ"(%struct.ImportMembers*)
+ // M32-DAG: declare dllimport x86_thiscallcc void @"\01?virtualInclass@ImportMembers@@UAEXXZ"(%struct.ImportMembers*)
+ // M64-DAG: declare dllimport void @"\01?virtualInclass@ImportMembers@@UEAAXXZ"(%struct.ImportMembers*)
+ // M32-DAG: declare dllimport x86_thiscallcc void @"\01?virtualInlineDef@ImportMembers@@UAEXXZ"(%struct.ImportMembers*)
+ // M64-DAG: declare dllimport void @"\01?virtualInlineDef@ImportMembers@@UEAAXXZ"(%struct.ImportMembers*)
+ // M32-DAG: declare dllimport x86_thiscallcc void @"\01?virtualInlineDecl@ImportMembers@@UAEXXZ"(%struct.ImportMembers*)
+ // M64-DAG: declare dllimport void @"\01?virtualInlineDecl@ImportMembers@@UEAAXXZ"(%struct.ImportMembers*)
+ // G32-DAG: define x86_thiscallcc void @_ZN13ImportMembers10virtualDefEv(%struct.ImportMembers* %this)
+ // G64-DAG: define void @_ZN13ImportMembers10virtualDefEv(%struct.ImportMembers* %this)
+ // G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers11virtualDeclEv(%struct.ImportMembers*)
+ // G64-DAG: declare dllimport void @_ZN13ImportMembers11virtualDeclEv(%struct.ImportMembers*)
+ // G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers14virtualInclassEv(%struct.ImportMembers*)
+ // G64-DAG: declare dllimport void @_ZN13ImportMembers14virtualInclassEv(%struct.ImportMembers*)
+ // G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers16virtualInlineDefEv(%struct.ImportMembers*)
+ // G64-DAG: declare dllimport void @_ZN13ImportMembers16virtualInlineDefEv(%struct.ImportMembers*)
+ // G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers17virtualInlineDeclEv(%struct.ImportMembers*)
+ // G64-DAG: declare dllimport void @_ZN13ImportMembers17virtualInlineDeclEv(%struct.ImportMembers*)
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?virtualInclass@ImportMembers@@UAEXXZ"(
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?virtualInlineDef@ImportMembers@@UAEXXZ"(
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?virtualInlineDecl@ImportMembers@@UAEXXZ"(
+ // GO1-DAG: define available_externally dllimport x86_thiscallcc void @_ZN13ImportMembers14virtualInclassEv(
+ // GO1-DAG: define available_externally dllimport x86_thiscallcc void @_ZN13ImportMembers16virtualInlineDefEv(
+ // GO1-DAG: define available_externally dllimport x86_thiscallcc void @_ZN13ImportMembers17virtualInlineDeclEv(
+ __declspec(dllimport) virtual void virtualDef(); // dllimport ignored
+ __declspec(dllimport) virtual void virtualDecl();
+ __declspec(dllimport) virtual void virtualInclass() {}
+ __declspec(dllimport) virtual void virtualInlineDef();
+ __declspec(dllimport) virtual inline void virtualInlineDecl();
+
+ // MSC-DAG: define void @"\01?staticDef@ImportMembers@@SAXXZ"()
+ // MSC-DAG: declare dllimport void @"\01?staticDecl@ImportMembers@@SAXXZ"()
+ // MSC-DAG: declare dllimport void @"\01?staticInclass@ImportMembers@@SAXXZ"()
+ // MSC-DAG: declare dllimport void @"\01?staticInlineDef@ImportMembers@@SAXXZ"()
+ // MSC-DAG: declare dllimport void @"\01?staticInlineDecl@ImportMembers@@SAXXZ"()
+ // GNU-DAG: define void @_ZN13ImportMembers9staticDefEv()
+ // GNU-DAG: declare dllimport void @_ZN13ImportMembers10staticDeclEv()
+ // GNU-DAG: declare dllimport void @_ZN13ImportMembers13staticInclassEv()
+ // GNU-DAG: declare dllimport void @_ZN13ImportMembers15staticInlineDefEv()
+ // GNU-DAG: declare dllimport void @_ZN13ImportMembers16staticInlineDeclEv()
+ // MO1-DAG: define available_externally dllimport void @"\01?staticInclass@ImportMembers@@SAXXZ"()
+ // MO1-DAG: define available_externally dllimport void @"\01?staticInlineDef@ImportMembers@@SAXXZ"()
+ // MO1-DAG: define available_externally dllimport void @"\01?staticInlineDecl@ImportMembers@@SAXXZ"()
+ // GO1-DAG: define available_externally dllimport void @_ZN13ImportMembers13staticInclassEv()
+ // GO1-DAG: define available_externally dllimport void @_ZN13ImportMembers15staticInlineDefEv()
+ // GO1-DAG: define available_externally dllimport void @_ZN13ImportMembers16staticInlineDeclEv()
+ __declspec(dllimport) static void staticDef(); // dllimport ignored
+ __declspec(dllimport) static void staticDecl();
+ __declspec(dllimport) static void staticInclass() {}
+ __declspec(dllimport) static void staticInlineDef();
+ __declspec(dllimport) static inline void staticInlineDecl();
+
+ // M32-DAG: declare dllimport x86_thiscallcc void @"\01?protectedNormalDecl@ImportMembers@@IAEXXZ"(%struct.ImportMembers*)
+ // M64-DAG: declare dllimport void @"\01?protectedNormalDecl@ImportMembers@@IEAAXXZ"(%struct.ImportMembers*)
+ // G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers19protectedNormalDeclEv(%struct.ImportMembers*)
+ // G64-DAG: declare dllimport void @_ZN13ImportMembers19protectedNormalDeclEv(%struct.ImportMembers*)
+ // MSC-DAG: declare dllimport void @"\01?protectedStaticDecl@ImportMembers@@KAXXZ"()
+ // GNU-DAG: declare dllimport void @_ZN13ImportMembers19protectedStaticDeclEv()
+protected:
+ __declspec(dllimport) void protectedNormalDecl();
+ __declspec(dllimport) static void protectedStaticDecl();
+
+ // M32-DAG: declare dllimport x86_thiscallcc void @"\01?privateNormalDecl@ImportMembers@@AAEXXZ"(%struct.ImportMembers*)
+ // M64-DAG: declare dllimport void @"\01?privateNormalDecl@ImportMembers@@AEAAXXZ"(%struct.ImportMembers*)
+ // G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers17privateNormalDeclEv(%struct.ImportMembers*)
+ // G64-DAG: declare dllimport void @_ZN13ImportMembers17privateNormalDeclEv(%struct.ImportMembers*)
+ // MSC-DAG: declare dllimport void @"\01?privateStaticDecl@ImportMembers@@CAXXZ"()
+ // GNU-DAG: declare dllimport void @_ZN13ImportMembers17privateStaticDeclEv()
+private:
+ __declspec(dllimport) void privateNormalDecl();
+ __declspec(dllimport) static void privateStaticDecl();
+
+ // M32-DAG: declare x86_thiscallcc void @"\01?ignored@ImportMembers@@QAEXXZ"(%struct.ImportMembers*)
+ // M64-DAG: declare void @"\01?ignored@ImportMembers@@QEAAXXZ"(%struct.ImportMembers*)
+ // G32-DAG: declare x86_thiscallcc void @_ZN13ImportMembers7ignoredEv(%struct.ImportMembers*)
+ // G64-DAG: declare void @_ZN13ImportMembers7ignoredEv(%struct.ImportMembers*)
+public:
+ void ignored();
+
+ // MSC-DAG: @"\01?StaticField@ImportMembers@@2HA" = external dllimport global i32
+ // MSC-DAG: @"\01?StaticConstField@ImportMembers@@2HB" = external dllimport constant i32
+ // MSC-DAG: @"\01?StaticConstFieldEqualInit@ImportMembers@@2HB" = available_externally dllimport constant i32 1, align 4
+ // MSC-DAG: @"\01?StaticConstFieldBraceInit@ImportMembers@@2HB" = available_externally dllimport constant i32 1, align 4
+ // MSC-DAG: @"\01?ConstexprField@ImportMembers@@2HB" = available_externally dllimport constant i32 1, align 4
+ // GNU-DAG: @_ZN13ImportMembers11StaticFieldE = external dllimport global i32
+ // GNU-DAG: @_ZN13ImportMembers16StaticConstFieldE = external dllimport constant i32
+ // GNU-DAG: @_ZN13ImportMembers25StaticConstFieldEqualInitE = external dllimport constant i32
+ // GNU-DAG: @_ZN13ImportMembers25StaticConstFieldBraceInitE = external dllimport constant i32
+ // GNU-DAG: @_ZN13ImportMembers14ConstexprFieldE = external dllimport constant i32
+ __declspec(dllimport) static int StaticField;
+ __declspec(dllimport) static const int StaticConstField;
+ __declspec(dllimport) static const int StaticConstFieldEqualInit = 1;
+ __declspec(dllimport) static const int StaticConstFieldBraceInit{1};
+ __declspec(dllimport) constexpr static int ConstexprField = 1;
+
+ template<int Line, typename T> friend void useMemFun();
+};
+
+ void ImportMembers::normalDef() {} // dllimport ignored
+inline void ImportMembers::normalInlineDef() {}
+ void ImportMembers::normalInlineDecl() {}
+ void ImportMembers::virtualDef() {} // dllimport ignored
+inline void ImportMembers::virtualInlineDef() {}
+ void ImportMembers::virtualInlineDecl() {}
+ void ImportMembers::staticDef() {} // dllimport ignored
+inline void ImportMembers::staticInlineDef() {}
+ void ImportMembers::staticInlineDecl() {}
+
+USEMF(ImportMembers, normalDef)
+USEMF(ImportMembers, normalDecl)
+USEMF(ImportMembers, normalInclass)
+USEMF(ImportMembers, normalInlineDef)
+USEMF(ImportMembers, normalInlineDecl)
+USEMF(ImportMembers, virtualDef)
+USEMF(ImportMembers, virtualDecl)
+USEMF(ImportMembers, virtualInclass)
+USEMF(ImportMembers, virtualInlineDef)
+USEMF(ImportMembers, virtualInlineDecl)
+USEMF(ImportMembers, staticDef)
+USEMF(ImportMembers, staticDecl)
+USEMF(ImportMembers, staticInclass)
+USEMF(ImportMembers, staticInlineDef)
+USEMF(ImportMembers, staticInlineDecl)
+USEMF(ImportMembers, protectedNormalDecl)
+USEMF(ImportMembers, protectedStaticDecl)
+USEMF(ImportMembers, privateNormalDecl)
+USEMF(ImportMembers, privateStaticDecl)
+USEMF(ImportMembers, ignored)
+
+USEMV(ImportMembers, StaticField)
+USEMV(ImportMembers, StaticConstField)
+USEMV(ImportMembers, StaticConstFieldEqualInit)
+USEMV(ImportMembers, StaticConstFieldBraceInit)
+USEMV(ImportMembers, ConstexprField)
+
+
+// Import individual members of a nested class.
+struct ImportMembers::Nested {
+ // M32-DAG: define x86_thiscallcc void @"\01?normalDef@Nested@ImportMembers@@QAEXXZ"(%"struct.ImportMembers::Nested"* %this)
+ // M64-DAG: define void @"\01?normalDef@Nested@ImportMembers@@QEAAXXZ"(%"struct.ImportMembers::Nested"* %this)
+ // M32-DAG: declare dllimport x86_thiscallcc void @"\01?normalDecl@Nested@ImportMembers@@QAEXXZ"(%"struct.ImportMembers::Nested"*)
+ // M64-DAG: declare dllimport void @"\01?normalDecl@Nested@ImportMembers@@QEAAXXZ"(%"struct.ImportMembers::Nested"*)
+ // M32-DAG: declare dllimport x86_thiscallcc void @"\01?normalInclass@Nested@ImportMembers@@QAEXXZ"(%"struct.ImportMembers::Nested"*)
+ // M64-DAG: declare dllimport void @"\01?normalInclass@Nested@ImportMembers@@QEAAXXZ"(%"struct.ImportMembers::Nested"*)
+ // M32-DAG: declare dllimport x86_thiscallcc void @"\01?normalInlineDef@Nested@ImportMembers@@QAEXXZ"(%"struct.ImportMembers::Nested"*)
+ // M64-DAG: declare dllimport void @"\01?normalInlineDef@Nested@ImportMembers@@QEAAXXZ"(%"struct.ImportMembers::Nested"*)
+ // M32-DAG: declare dllimport x86_thiscallcc void @"\01?normalInlineDecl@Nested@ImportMembers@@QAEXXZ"(%"struct.ImportMembers::Nested"*)
+ // M64-DAG: declare dllimport void @"\01?normalInlineDecl@Nested@ImportMembers@@QEAAXXZ"(%"struct.ImportMembers::Nested"*)
+ // G32-DAG: define x86_thiscallcc void @_ZN13ImportMembers6Nested9normalDefEv(%"struct.ImportMembers::Nested"* %this)
+ // G64-DAG: define void @_ZN13ImportMembers6Nested9normalDefEv(%"struct.ImportMembers::Nested"* %this)
+ // G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers6Nested10normalDeclEv(%"struct.ImportMembers::Nested"*)
+ // G64-DAG: declare dllimport void @_ZN13ImportMembers6Nested10normalDeclEv(%"struct.ImportMembers::Nested"*)
+ // G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers6Nested13normalInclassEv(%"struct.ImportMembers::Nested"*)
+ // G64-DAG: declare dllimport void @_ZN13ImportMembers6Nested13normalInclassEv(%"struct.ImportMembers::Nested"*)
+ // G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers6Nested15normalInlineDefEv(%"struct.ImportMembers::Nested"*)
+ // G64-DAG: declare dllimport void @_ZN13ImportMembers6Nested15normalInlineDefEv(%"struct.ImportMembers::Nested"*)
+ // G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers6Nested16normalInlineDeclEv(%"struct.ImportMembers::Nested"*)
+ // G64-DAG: declare dllimport void @_ZN13ImportMembers6Nested16normalInlineDeclEv(%"struct.ImportMembers::Nested"*)
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?normalInclass@Nested@ImportMembers@@QAEXXZ"(
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?normalInlineDef@Nested@ImportMembers@@QAEXXZ"(
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?normalInlineDecl@Nested@ImportMembers@@QAEXXZ"(
+ // GO1-DAG: define available_externally dllimport x86_thiscallcc void @_ZN13ImportMembers6Nested13normalInclassEv(
+ // GO1-DAG: define available_externally dllimport x86_thiscallcc void @_ZN13ImportMembers6Nested15normalInlineDefEv(
+ // GO1-DAG: define available_externally dllimport x86_thiscallcc void @_ZN13ImportMembers6Nested16normalInlineDeclEv(
+ __declspec(dllimport) void normalDef(); // dllimport ignored
+ __declspec(dllimport) void normalDecl();
+ __declspec(dllimport) void normalInclass() {}
+ __declspec(dllimport) void normalInlineDef();
+ __declspec(dllimport) inline void normalInlineDecl();
+
+ // M32-DAG: define x86_thiscallcc void @"\01?virtualDef@Nested@ImportMembers@@UAEXXZ"(%"struct.ImportMembers::Nested"* %this)
+ // M64-DAG: define void @"\01?virtualDef@Nested@ImportMembers@@UEAAXXZ"(%"struct.ImportMembers::Nested"* %this)
+ // M32-DAG: declare dllimport x86_thiscallcc void @"\01?virtualDecl@Nested@ImportMembers@@UAEXXZ"(%"struct.ImportMembers::Nested"*)
+ // M64-DAG: declare dllimport void @"\01?virtualDecl@Nested@ImportMembers@@UEAAXXZ"(%"struct.ImportMembers::Nested"*)
+ // M32-DAG: declare dllimport x86_thiscallcc void @"\01?virtualInclass@Nested@ImportMembers@@UAEXXZ"(%"struct.ImportMembers::Nested"*)
+ // M64-DAG: declare dllimport void @"\01?virtualInclass@Nested@ImportMembers@@UEAAXXZ"(%"struct.ImportMembers::Nested"*)
+ // M32-DAG: declare dllimport x86_thiscallcc void @"\01?virtualInlineDef@Nested@ImportMembers@@UAEXXZ"(%"struct.ImportMembers::Nested"*)
+ // M64-DAG: declare dllimport void @"\01?virtualInlineDef@Nested@ImportMembers@@UEAAXXZ"(%"struct.ImportMembers::Nested"*)
+ // M32-DAG: declare dllimport x86_thiscallcc void @"\01?virtualInlineDecl@Nested@ImportMembers@@UAEXXZ"(%"struct.ImportMembers::Nested"*)
+ // M64-DAG: declare dllimport void @"\01?virtualInlineDecl@Nested@ImportMembers@@UEAAXXZ"(%"struct.ImportMembers::Nested"*)
+ // G32-DAG: define x86_thiscallcc void @_ZN13ImportMembers6Nested10virtualDefEv(%"struct.ImportMembers::Nested"* %this)
+ // G64-DAG: define void @_ZN13ImportMembers6Nested10virtualDefEv(%"struct.ImportMembers::Nested"* %this)
+ // G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers6Nested11virtualDeclEv(%"struct.ImportMembers::Nested"*)
+ // G64-DAG: declare dllimport void @_ZN13ImportMembers6Nested11virtualDeclEv(%"struct.ImportMembers::Nested"*)
+ // G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers6Nested14virtualInclassEv(%"struct.ImportMembers::Nested"*)
+ // G64-DAG: declare dllimport void @_ZN13ImportMembers6Nested14virtualInclassEv(%"struct.ImportMembers::Nested"*)
+ // G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers6Nested16virtualInlineDefEv(%"struct.ImportMembers::Nested"*)
+ // G64-DAG: declare dllimport void @_ZN13ImportMembers6Nested16virtualInlineDefEv(%"struct.ImportMembers::Nested"*)
+ // G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers6Nested17virtualInlineDeclEv(%"struct.ImportMembers::Nested"*)
+ // G64-DAG: declare dllimport void @_ZN13ImportMembers6Nested17virtualInlineDeclEv(%"struct.ImportMembers::Nested"*)
+
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?virtualInclass@Nested@ImportMembers@@UAEXXZ"(
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?virtualInlineDef@Nested@ImportMembers@@UAEXXZ"(
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?virtualInlineDecl@Nested@ImportMembers@@UAEXXZ"(
+ // GO1-DAG: define available_externally dllimport x86_thiscallcc void @_ZN13ImportMembers6Nested14virtualInclassEv(
+ // GO1-DAG: define available_externally dllimport x86_thiscallcc void @_ZN13ImportMembers6Nested16virtualInlineDefEv(
+ // GO1-DAG: define available_externally dllimport x86_thiscallcc void @_ZN13ImportMembers6Nested17virtualInlineDeclEv(
+ __declspec(dllimport) virtual void virtualDef(); // dllimport ignored
+ __declspec(dllimport) virtual void virtualDecl();
+ __declspec(dllimport) virtual void virtualInclass() {}
+ __declspec(dllimport) virtual void virtualInlineDef();
+ __declspec(dllimport) virtual inline void virtualInlineDecl();
+
+ // MSC-DAG: define void @"\01?staticDef@Nested@ImportMembers@@SAXXZ"()
+ // MSC-DAG: declare dllimport void @"\01?staticDecl@Nested@ImportMembers@@SAXXZ"()
+ // MSC-DAG: declare dllimport void @"\01?staticInclass@Nested@ImportMembers@@SAXXZ"()
+ // MSC-DAG: declare dllimport void @"\01?staticInlineDef@Nested@ImportMembers@@SAXXZ"()
+ // MSC-DAG: declare dllimport void @"\01?staticInlineDecl@Nested@ImportMembers@@SAXXZ"()
+ // GNU-DAG: define void @_ZN13ImportMembers6Nested9staticDefEv()
+ // GNU-DAG: declare dllimport void @_ZN13ImportMembers6Nested10staticDeclEv()
+ // GNU-DAG: declare dllimport void @_ZN13ImportMembers6Nested13staticInclassEv()
+ // GNU-DAG: declare dllimport void @_ZN13ImportMembers6Nested15staticInlineDefEv()
+ // GNU-DAG: declare dllimport void @_ZN13ImportMembers6Nested16staticInlineDeclEv()
+ // MO1-DAG: define available_externally dllimport void @"\01?staticInclass@Nested@ImportMembers@@SAXXZ"()
+ // MO1-DAG: define available_externally dllimport void @"\01?staticInlineDef@Nested@ImportMembers@@SAXXZ"()
+ // MO1-DAG: define available_externally dllimport void @"\01?staticInlineDecl@Nested@ImportMembers@@SAXXZ"()
+ // GO1-DAG: define available_externally dllimport void @_ZN13ImportMembers6Nested13staticInclassEv()
+ // GO1-DAG: define available_externally dllimport void @_ZN13ImportMembers6Nested15staticInlineDefEv()
+ // GO1-DAG: define available_externally dllimport void @_ZN13ImportMembers6Nested16staticInlineDeclEv()
+ __declspec(dllimport) static void staticDef(); // dllimport ignored
+ __declspec(dllimport) static void staticDecl();
+ __declspec(dllimport) static void staticInclass() {}
+ __declspec(dllimport) static void staticInlineDef();
+ __declspec(dllimport) static inline void staticInlineDecl();
+
+ // M32-DAG: declare dllimport x86_thiscallcc void @"\01?protectedNormalDecl@Nested@ImportMembers@@IAEXXZ"(%"struct.ImportMembers::Nested"*)
+ // M64-DAG: declare dllimport void @"\01?protectedNormalDecl@Nested@ImportMembers@@IEAAXXZ"(%"struct.ImportMembers::Nested"*)
+ // G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers6Nested19protectedNormalDeclEv(%"struct.ImportMembers::Nested"*)
+ // G64-DAG: declare dllimport void @_ZN13ImportMembers6Nested19protectedNormalDeclEv(%"struct.ImportMembers::Nested"*)
+ // MSC-DAG: declare dllimport void @"\01?protectedStaticDecl@Nested@ImportMembers@@KAXXZ"()
+ // GNU-DAG: declare dllimport void @_ZN13ImportMembers6Nested19protectedStaticDeclEv()
+protected:
+ __declspec(dllimport) void protectedNormalDecl();
+ __declspec(dllimport) static void protectedStaticDecl();
+
+ // M32-DAG: declare dllimport x86_thiscallcc void @"\01?privateNormalDecl@Nested@ImportMembers@@AAEXXZ"(%"struct.ImportMembers::Nested"*)
+ // M64-DAG: declare dllimport void @"\01?privateNormalDecl@Nested@ImportMembers@@AEAAXXZ"(%"struct.ImportMembers::Nested"*)
+ // G32-DAG: declare dllimport x86_thiscallcc void @_ZN13ImportMembers6Nested17privateNormalDeclEv(%"struct.ImportMembers::Nested"*)
+ // G64-DAG: declare dllimport void @_ZN13ImportMembers6Nested17privateNormalDeclEv(%"struct.ImportMembers::Nested"*)
+ // MSC-DAG: declare dllimport void @"\01?privateStaticDecl@Nested@ImportMembers@@CAXXZ"()
+ // GNU-DAG: declare dllimport void @_ZN13ImportMembers6Nested17privateStaticDeclEv()
+private:
+ __declspec(dllimport) void privateNormalDecl();
+ __declspec(dllimport) static void privateStaticDecl();
+
+ // M32-DAG: declare x86_thiscallcc void @"\01?ignored@Nested@ImportMembers@@QAEXXZ"(%"struct.ImportMembers::Nested"*)
+ // M64-DAG: declare void @"\01?ignored@Nested@ImportMembers@@QEAAXXZ"(%"struct.ImportMembers::Nested"*)
+ // G32-DAG: declare x86_thiscallcc void @_ZN13ImportMembers6Nested7ignoredEv(%"struct.ImportMembers::Nested"*)
+ // G64-DAG: declare void @_ZN13ImportMembers6Nested7ignoredEv(%"struct.ImportMembers::Nested"*)
+public:
+ void ignored();
+
+ // MSC-DAG: @"\01?StaticField@Nested@ImportMembers@@2HA" = external dllimport global i32
+ // MSC-DAG: @"\01?StaticConstField@Nested@ImportMembers@@2HB" = external dllimport constant i32
+ // MSC-DAG: @"\01?StaticConstFieldEqualInit@Nested@ImportMembers@@2HB" = available_externally dllimport constant i32 1, align 4
+ // MSC-DAG: @"\01?StaticConstFieldBraceInit@Nested@ImportMembers@@2HB" = available_externally dllimport constant i32 1, align 4
+ // MSC-DAG: @"\01?ConstexprField@Nested@ImportMembers@@2HB" = available_externally dllimport constant i32 1, align 4
+ // GNU-DAG: @_ZN13ImportMembers6Nested11StaticFieldE = external dllimport global i32
+ // GNU-DAG: @_ZN13ImportMembers6Nested16StaticConstFieldE = external dllimport constant i32
+ // GNU-DAG: @_ZN13ImportMembers6Nested25StaticConstFieldEqualInitE = external dllimport constant i32
+ // GNU-DAG: @_ZN13ImportMembers6Nested25StaticConstFieldBraceInitE = external dllimport constant i32
+ // GNU-DAG: @_ZN13ImportMembers6Nested14ConstexprFieldE = external dllimport constant i32
+ __declspec(dllimport) static int StaticField;
+ __declspec(dllimport) static const int StaticConstField;
+ __declspec(dllimport) static const int StaticConstFieldEqualInit = 1;
+ __declspec(dllimport) static const int StaticConstFieldBraceInit{1};
+ __declspec(dllimport) constexpr static int ConstexprField = 1;
+
+ template<int Line, typename T> friend void useMemFun();
+};
+
+ void ImportMembers::Nested::normalDef() {} // dllimport ignored
+inline void ImportMembers::Nested::normalInlineDef() {}
+ void ImportMembers::Nested::normalInlineDecl() {}
+ void ImportMembers::Nested::virtualDef() {} // dllimport ignored
+inline void ImportMembers::Nested::virtualInlineDef() {}
+ void ImportMembers::Nested::virtualInlineDecl() {}
+ void ImportMembers::Nested::staticDef() {} // dllimport ignored
+inline void ImportMembers::Nested::staticInlineDef() {}
+ void ImportMembers::Nested::staticInlineDecl() {}
+
+USEMF(ImportMembers::Nested, normalDef)
+USEMF(ImportMembers::Nested, normalDecl)
+USEMF(ImportMembers::Nested, normalInclass)
+USEMF(ImportMembers::Nested, normalInlineDef)
+USEMF(ImportMembers::Nested, normalInlineDecl)
+USEMF(ImportMembers::Nested, virtualDef)
+USEMF(ImportMembers::Nested, virtualDecl)
+USEMF(ImportMembers::Nested, virtualInclass)
+USEMF(ImportMembers::Nested, virtualInlineDef)
+USEMF(ImportMembers::Nested, virtualInlineDecl)
+USEMF(ImportMembers::Nested, staticDef)
+USEMF(ImportMembers::Nested, staticDecl)
+USEMF(ImportMembers::Nested, staticInclass)
+USEMF(ImportMembers::Nested, staticInlineDef)
+USEMF(ImportMembers::Nested, staticInlineDecl)
+USEMF(ImportMembers::Nested, protectedNormalDecl)
+USEMF(ImportMembers::Nested, protectedStaticDecl)
+USEMF(ImportMembers::Nested, privateNormalDecl)
+USEMF(ImportMembers::Nested, privateStaticDecl)
+USEMF(ImportMembers::Nested, ignored)
+
+USEMV(ImportMembers::Nested, StaticField)
+USEMV(ImportMembers::Nested, StaticConstField)
+USEMV(ImportMembers::Nested, StaticConstFieldEqualInit)
+USEMV(ImportMembers::Nested, StaticConstFieldBraceInit)
+USEMV(ImportMembers::Nested, ConstexprField)
+
+
+// Import special member functions.
+struct ImportSpecials {
+ // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportSpecials* @"\01??0ImportSpecials@@QAE@XZ"(%struct.ImportSpecials* returned)
+ // M64-DAG: declare dllimport %struct.ImportSpecials* @"\01??0ImportSpecials@@QEAA@XZ"(%struct.ImportSpecials* returned)
+ // G32-DAG: declare dllimport x86_thiscallcc void @_ZN14ImportSpecialsC1Ev(%struct.ImportSpecials*)
+ // G64-DAG: declare dllimport void @_ZN14ImportSpecialsC1Ev(%struct.ImportSpecials*)
+ __declspec(dllimport) ImportSpecials();
+
+ // M32-DAG: declare dllimport x86_thiscallcc void @"\01??1ImportSpecials@@QAE@XZ"(%struct.ImportSpecials*)
+ // M64-DAG: declare dllimport void @"\01??1ImportSpecials@@QEAA@XZ"(%struct.ImportSpecials*)
+ // G32-DAG: declare dllimport x86_thiscallcc void @_ZN14ImportSpecialsD1Ev(%struct.ImportSpecials*)
+ // G64-DAG: declare dllimport void @_ZN14ImportSpecialsD1Ev(%struct.ImportSpecials*)
+ __declspec(dllimport) ~ImportSpecials();
+
+ // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportSpecials* @"\01??0ImportSpecials@@QAE@ABU0@@Z"(%struct.ImportSpecials* returned, %struct.ImportSpecials* dereferenceable({{[0-9]+}}))
+ // M64-DAG: declare dllimport %struct.ImportSpecials* @"\01??0ImportSpecials@@QEAA@AEBU0@@Z"(%struct.ImportSpecials* returned, %struct.ImportSpecials* dereferenceable({{[0-9]+}}))
+ // G32-DAG: declare dllimport x86_thiscallcc void @_ZN14ImportSpecialsC1ERKS_(%struct.ImportSpecials*, %struct.ImportSpecials* dereferenceable({{[0-9]+}}))
+ // G64-DAG: declare dllimport void @_ZN14ImportSpecialsC1ERKS_(%struct.ImportSpecials*, %struct.ImportSpecials* dereferenceable({{[0-9]+}}))
+ __declspec(dllimport) ImportSpecials(const ImportSpecials&);
+
+ // M32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportSpecials* @"\01??4ImportSpecials@@QAEAAU0@ABU0@@Z"(%struct.ImportSpecials*, %struct.ImportSpecials* dereferenceable({{[0-9]+}}))
+ // M64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportSpecials* @"\01??4ImportSpecials@@QEAAAEAU0@AEBU0@@Z"(%struct.ImportSpecials*, %struct.ImportSpecials* dereferenceable({{[0-9]+}}))
+ // G32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportSpecials* @_ZN14ImportSpecialsaSERKS_(%struct.ImportSpecials*, %struct.ImportSpecials* dereferenceable({{[0-9]+}}))
+ // G64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportSpecials* @_ZN14ImportSpecialsaSERKS_(%struct.ImportSpecials*, %struct.ImportSpecials* dereferenceable({{[0-9]+}}))
+ __declspec(dllimport) ImportSpecials& operator=(const ImportSpecials&);
+
+ // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportSpecials* @"\01??0ImportSpecials@@QAE@$$QAU0@@Z"(%struct.ImportSpecials* returned, %struct.ImportSpecials* dereferenceable({{[0-9]+}}))
+ // M64-DAG: declare dllimport %struct.ImportSpecials* @"\01??0ImportSpecials@@QEAA@$$QEAU0@@Z"(%struct.ImportSpecials* returned, %struct.ImportSpecials* dereferenceable({{[0-9]+}}))
+ // G32-DAG: declare dllimport x86_thiscallcc void @_ZN14ImportSpecialsC1EOS_(%struct.ImportSpecials*, %struct.ImportSpecials* dereferenceable({{[0-9]+}}))
+ // G64-DAG: declare dllimport void @_ZN14ImportSpecialsC1EOS_(%struct.ImportSpecials*, %struct.ImportSpecials* dereferenceable({{[0-9]+}}))
+ __declspec(dllimport) ImportSpecials(ImportSpecials&&);
+
+ // M32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportSpecials* @"\01??4ImportSpecials@@QAEAAU0@$$QAU0@@Z"(%struct.ImportSpecials*, %struct.ImportSpecials* dereferenceable({{[0-9]+}}))
+ // M64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportSpecials* @"\01??4ImportSpecials@@QEAAAEAU0@$$QEAU0@@Z"(%struct.ImportSpecials*, %struct.ImportSpecials* dereferenceable({{[0-9]+}}))
+ // G32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportSpecials* @_ZN14ImportSpecialsaSEOS_(%struct.ImportSpecials*, %struct.ImportSpecials* dereferenceable({{[0-9]+}}))
+ // G64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportSpecials* @_ZN14ImportSpecialsaSEOS_(%struct.ImportSpecials*, %struct.ImportSpecials* dereferenceable({{[0-9]+}}))
+ __declspec(dllimport) ImportSpecials& operator=(ImportSpecials&&);
+};
+USESPECIALS(ImportSpecials)
+
+
+// Export inline special member functions.
+struct ImportInlineSpecials {
+ // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportInlineSpecials* @"\01??0ImportInlineSpecials@@QAE@XZ"(%struct.ImportInlineSpecials* returned)
+ // M64-DAG: declare dllimport %struct.ImportInlineSpecials* @"\01??0ImportInlineSpecials@@QEAA@XZ"(%struct.ImportInlineSpecials* returned)
+ // G32-DAG: declare dllimport x86_thiscallcc void @_ZN20ImportInlineSpecialsC1Ev(%struct.ImportInlineSpecials*)
+ // G64-DAG: declare dllimport void @_ZN20ImportInlineSpecialsC1Ev(%struct.ImportInlineSpecials*)
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc %struct.ImportInlineSpecials* @"\01??0ImportInlineSpecials@@QAE@XZ"(
+ // GO1-DAG: define available_externally dllimport x86_thiscallcc void @_ZN20ImportInlineSpecialsC1Ev(
+ __declspec(dllimport) ImportInlineSpecials() {}
+
+ // M32-DAG: declare dllimport x86_thiscallcc void @"\01??1ImportInlineSpecials@@QAE@XZ"(%struct.ImportInlineSpecials*)
+ // M64-DAG: declare dllimport void @"\01??1ImportInlineSpecials@@QEAA@XZ"(%struct.ImportInlineSpecials*)
+ // G32-DAG: declare dllimport x86_thiscallcc void @_ZN20ImportInlineSpecialsD1Ev(%struct.ImportInlineSpecials*)
+ // G64-DAG: declare dllimport void @_ZN20ImportInlineSpecialsD1Ev(%struct.ImportInlineSpecials*)
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01??1ImportInlineSpecials@@QAE@XZ"(
+ // GO1-DAG: define available_externally dllimport x86_thiscallcc void @_ZN20ImportInlineSpecialsD1Ev(
+ __declspec(dllimport) ~ImportInlineSpecials() {}
+
+ // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportInlineSpecials* @"\01??0ImportInlineSpecials@@QAE@ABU0@@Z"(%struct.ImportInlineSpecials* returned, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
+ // M64-DAG: declare dllimport %struct.ImportInlineSpecials* @"\01??0ImportInlineSpecials@@QEAA@AEBU0@@Z"(%struct.ImportInlineSpecials* returned, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
+ // G32-DAG: declare dllimport x86_thiscallcc void @_ZN20ImportInlineSpecialsC1ERKS_(%struct.ImportInlineSpecials*, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
+ // G64-DAG: declare dllimport void @_ZN20ImportInlineSpecialsC1ERKS_(%struct.ImportInlineSpecials*, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc %struct.ImportInlineSpecials* @"\01??0ImportInlineSpecials@@QAE@ABU0@@Z"(
+ // GO1-DAG: define available_externally dllimport x86_thiscallcc void @_ZN20ImportInlineSpecialsC1ERKS_(
+ __declspec(dllimport) inline ImportInlineSpecials(const ImportInlineSpecials&);
+
+ // M32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @"\01??4ImportInlineSpecials@@QAEAAU0@ABU0@@Z"(%struct.ImportInlineSpecials*, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
+ // M64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @"\01??4ImportInlineSpecials@@QEAAAEAU0@AEBU0@@Z"(%struct.ImportInlineSpecials*, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
+ // G32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @_ZN20ImportInlineSpecialsaSERKS_(%struct.ImportInlineSpecials*, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
+ // G64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @_ZN20ImportInlineSpecialsaSERKS_(%struct.ImportInlineSpecials*, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @"\01??4ImportInlineSpecials@@QAEAAU0@ABU0@@Z"(
+ // GO1-DAG: define available_externally dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @_ZN20ImportInlineSpecialsaSERKS_(
+ __declspec(dllimport) ImportInlineSpecials& operator=(const ImportInlineSpecials&);
+
+ // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportInlineSpecials* @"\01??0ImportInlineSpecials@@QAE@$$QAU0@@Z"(%struct.ImportInlineSpecials* returned, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
+ // M64-DAG: declare dllimport %struct.ImportInlineSpecials* @"\01??0ImportInlineSpecials@@QEAA@$$QEAU0@@Z"(%struct.ImportInlineSpecials* returned, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
+ // G32-DAG: declare dllimport x86_thiscallcc void @_ZN20ImportInlineSpecialsC1EOS_(%struct.ImportInlineSpecials*, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
+ // G64-DAG: declare dllimport void @_ZN20ImportInlineSpecialsC1EOS_(%struct.ImportInlineSpecials*, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc %struct.ImportInlineSpecials* @"\01??0ImportInlineSpecials@@QAE@$$QAU0@@Z"(
+ // GO1-DAG: define available_externally dllimport x86_thiscallcc void @_ZN20ImportInlineSpecialsC1EOS_(
+ __declspec(dllimport) ImportInlineSpecials(ImportInlineSpecials&&) {}
+
+ // M32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @"\01??4ImportInlineSpecials@@QAEAAU0@$$QAU0@@Z"(%struct.ImportInlineSpecials*, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
+ // M64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @"\01??4ImportInlineSpecials@@QEAAAEAU0@$$QEAU0@@Z"(%struct.ImportInlineSpecials*, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
+ // G32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @_ZN20ImportInlineSpecialsaSEOS_(%struct.ImportInlineSpecials*, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
+ // G64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @_ZN20ImportInlineSpecialsaSEOS_(%struct.ImportInlineSpecials*, %struct.ImportInlineSpecials* dereferenceable({{[0-9]+}}))
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @"\01??4ImportInlineSpecials@@QAEAAU0@$$QAU0@@Z"(
+ // GO1-DAG: define available_externally dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportInlineSpecials* @_ZN20ImportInlineSpecialsaSEOS_(
+ __declspec(dllimport) ImportInlineSpecials& operator=(ImportInlineSpecials&&) { return *this; }
+};
+ImportInlineSpecials::ImportInlineSpecials(const ImportInlineSpecials&) {}
+inline ImportInlineSpecials& ImportInlineSpecials::operator=(const ImportInlineSpecials&) { return *this; }
+USESPECIALS(ImportInlineSpecials)
+
+
+// Import defaulted member functions.
+struct ImportDefaulted {
+ // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportDefaulted* @"\01??0ImportDefaulted@@QAE@XZ"(%struct.ImportDefaulted* returned)
+ // M64-DAG: declare dllimport %struct.ImportDefaulted* @"\01??0ImportDefaulted@@QEAA@XZ"(%struct.ImportDefaulted* returned)
+ // G32-DAG: declare dllimport x86_thiscallcc void @_ZN15ImportDefaultedC1Ev(%struct.ImportDefaulted*)
+ // G64-DAG: declare dllimport void @_ZN15ImportDefaultedC1Ev(%struct.ImportDefaulted*)
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc %struct.ImportDefaulted* @"\01??0ImportDefaulted@@QAE@XZ"(%struct.ImportDefaulted* returned %this)
+ // GO1-DAG: define available_externally dllimport x86_thiscallcc void @_ZN15ImportDefaultedC1Ev(%struct.ImportDefaulted* %this)
+ __declspec(dllimport) ImportDefaulted() = default;
+
+ // M32-DAG: declare dllimport x86_thiscallcc void @"\01??1ImportDefaulted@@QAE@XZ"(%struct.ImportDefaulted*)
+ // M64-DAG: declare dllimport void @"\01??1ImportDefaulted@@QEAA@XZ"(%struct.ImportDefaulted*)
+ // G32-DAG: declare dllimport x86_thiscallcc void @_ZN15ImportDefaultedD1Ev(%struct.ImportDefaulted*)
+ // G64-DAG: declare dllimport void @_ZN15ImportDefaultedD1Ev(%struct.ImportDefaulted*)
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01??1ImportDefaulted@@QAE@XZ"(%struct.ImportDefaulted* %this)
+ // GO1-DAG: define available_externally dllimport x86_thiscallcc void @_ZN15ImportDefaultedD1Ev(%struct.ImportDefaulted* %this)
+ __declspec(dllimport) ~ImportDefaulted() = default;
+
+ // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportDefaulted* @"\01??0ImportDefaulted@@QAE@ABU0@@Z"(%struct.ImportDefaulted* returned, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
+ // M64-DAG: declare dllimport %struct.ImportDefaulted* @"\01??0ImportDefaulted@@QEAA@AEBU0@@Z"(%struct.ImportDefaulted* returned, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
+ // G32-DAG: declare dllimport x86_thiscallcc void @_ZN15ImportDefaultedC1ERKS_(%struct.ImportDefaulted*, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
+ // G64-DAG: declare dllimport void @_ZN15ImportDefaultedC1ERKS_(%struct.ImportDefaulted*, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc %struct.ImportDefaulted* @"\01??0ImportDefaulted@@QAE@ABU0@@Z"(%struct.ImportDefaulted* returned %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
+ // GO1-DAG: define available_externally dllimport x86_thiscallcc void @_ZN15ImportDefaultedC1ERKS_(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
+ __declspec(dllimport) ImportDefaulted(const ImportDefaulted&) = default;
+
+ // M32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @"\01??4ImportDefaulted@@QAEAAU0@ABU0@@Z"(%struct.ImportDefaulted*, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
+ // M64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @"\01??4ImportDefaulted@@QEAAAEAU0@AEBU0@@Z"(%struct.ImportDefaulted*, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
+ // G32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @_ZN15ImportDefaultedaSERKS_(%struct.ImportDefaulted*, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
+ // G64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @_ZN15ImportDefaultedaSERKS_(%struct.ImportDefaulted*, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @"\01??4ImportDefaulted@@QAEAAU0@ABU0@@Z"(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
+ // GO1-DAG: define available_externally dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @_ZN15ImportDefaultedaSERKS_(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
+ __declspec(dllimport) ImportDefaulted& operator=(const ImportDefaulted&) = default;
+
+ // M32-DAG: declare dllimport x86_thiscallcc %struct.ImportDefaulted* @"\01??0ImportDefaulted@@QAE@$$QAU0@@Z"(%struct.ImportDefaulted* returned, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
+ // M64-DAG: declare dllimport %struct.ImportDefaulted* @"\01??0ImportDefaulted@@QEAA@$$QEAU0@@Z"(%struct.ImportDefaulted* returned, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
+ // G32-DAG: declare dllimport x86_thiscallcc void @_ZN15ImportDefaultedC1EOS_(%struct.ImportDefaulted*, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
+ // G64-DAG: declare dllimport void @_ZN15ImportDefaultedC1EOS_(%struct.ImportDefaulted*, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc %struct.ImportDefaulted* @"\01??0ImportDefaulted@@QAE@$$QAU0@@Z"(%struct.ImportDefaulted* returned %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
+ // GO1-DAG: define available_externally dllimport x86_thiscallcc void @_ZN15ImportDefaultedC1EOS_(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
+ __declspec(dllimport) ImportDefaulted(ImportDefaulted&&) = default;
+
+ // M32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @"\01??4ImportDefaulted@@QAEAAU0@$$QAU0@@Z"(%struct.ImportDefaulted*, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
+ // M64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @"\01??4ImportDefaulted@@QEAAAEAU0@$$QEAU0@@Z"(%struct.ImportDefaulted*, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
+ // G32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @_ZN15ImportDefaultedaSEOS_(%struct.ImportDefaulted*, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
+ // G64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @_ZN15ImportDefaultedaSEOS_(%struct.ImportDefaulted*, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @"\01??4ImportDefaulted@@QAEAAU0@$$QAU0@@Z"(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
+ // GO1-DAG: define available_externally dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaulted* @_ZN15ImportDefaultedaSEOS_(%struct.ImportDefaulted* %this, %struct.ImportDefaulted* dereferenceable({{[0-9]+}}))
+ __declspec(dllimport) ImportDefaulted& operator=(ImportDefaulted&&) = default;
+
+ ForceNonTrivial v; // ensure special members are non-trivial
+};
+USESPECIALS(ImportDefaulted)
+
+
+// Import defaulted member function definitions.
+struct ImportDefaultedDefs {
+ __declspec(dllimport) inline ImportDefaultedDefs();
+ __declspec(dllimport) inline ~ImportDefaultedDefs();
+
+ __declspec(dllimport) ImportDefaultedDefs(const ImportDefaultedDefs&);
+ __declspec(dllimport) ImportDefaultedDefs& operator=(const ImportDefaultedDefs&);
+
+ __declspec(dllimport) ImportDefaultedDefs(ImportDefaultedDefs&&);
+ __declspec(dllimport) ImportDefaultedDefs& operator=(ImportDefaultedDefs&&);
+};
+
+// M32-DAG: declare dllimport x86_thiscallcc %struct.ImportDefaultedDefs* @"\01??0ImportDefaultedDefs@@QAE@XZ"(%struct.ImportDefaultedDefs* returned)
+// M64-DAG: declare dllimport %struct.ImportDefaultedDefs* @"\01??0ImportDefaultedDefs@@QEAA@XZ"(%struct.ImportDefaultedDefs* returned)
+// G32-DAG: declare dllimport x86_thiscallcc void @_ZN19ImportDefaultedDefsC1Ev(%struct.ImportDefaultedDefs*)
+// G64-DAG: declare dllimport void @_ZN19ImportDefaultedDefsC1Ev(%struct.ImportDefaultedDefs*)
+__declspec(dllimport) ImportDefaultedDefs::ImportDefaultedDefs() = default;
+
+// M32-DAG: declare dllimport x86_thiscallcc void @"\01??1ImportDefaultedDefs@@QAE@XZ"(%struct.ImportDefaultedDefs*)
+// M64-DAG: declare dllimport void @"\01??1ImportDefaultedDefs@@QEAA@XZ"(%struct.ImportDefaultedDefs*)
+// G32-DAG: declare dllimport x86_thiscallcc void @_ZN19ImportDefaultedDefsD1Ev(%struct.ImportDefaultedDefs*)
+// G64-DAG: declare dllimport void @_ZN19ImportDefaultedDefsD1Ev(%struct.ImportDefaultedDefs*)
+__declspec(dllimport) ImportDefaultedDefs::~ImportDefaultedDefs() = default;
+
+// M32-DAG: declare dllimport x86_thiscallcc %struct.ImportDefaultedDefs* @"\01??0ImportDefaultedDefs@@QAE@ABU0@@Z"(%struct.ImportDefaultedDefs* returned, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// M64-DAG: declare dllimport %struct.ImportDefaultedDefs* @"\01??0ImportDefaultedDefs@@QEAA@AEBU0@@Z"(%struct.ImportDefaultedDefs* returned, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// G32-DAG: declare dllimport x86_thiscallcc void @_ZN19ImportDefaultedDefsC1ERKS_(%struct.ImportDefaultedDefs*, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// G64-DAG: declare dllimport void @_ZN19ImportDefaultedDefsC1ERKS_(%struct.ImportDefaultedDefs*, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
+inline ImportDefaultedDefs::ImportDefaultedDefs(const ImportDefaultedDefs&) = default;
+
+// M32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @"\01??4ImportDefaultedDefs@@QAEAAU0@ABU0@@Z"(%struct.ImportDefaultedDefs*, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// M64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @"\01??4ImportDefaultedDefs@@QEAAAEAU0@AEBU0@@Z"(%struct.ImportDefaultedDefs*, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// G32-DAG: declare dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @_ZN19ImportDefaultedDefsaSERKS_(%struct.ImportDefaultedDefs*, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// G64-DAG: declare dllimport dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @_ZN19ImportDefaultedDefsaSERKS_(%struct.ImportDefaultedDefs*, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
+inline ImportDefaultedDefs& ImportDefaultedDefs::operator=(const ImportDefaultedDefs&) = default;
+
+// M32-DAG: define x86_thiscallcc %struct.ImportDefaultedDefs* @"\01??0ImportDefaultedDefs@@QAE@$$QAU0@@Z"(%struct.ImportDefaultedDefs* returned %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// M64-DAG: define %struct.ImportDefaultedDefs* @"\01??0ImportDefaultedDefs@@QEAA@$$QEAU0@@Z"(%struct.ImportDefaultedDefs* returned %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// G32-DAG: define x86_thiscallcc void @_ZN19ImportDefaultedDefsC1EOS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// G64-DAG: define void @_ZN19ImportDefaultedDefsC1EOS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// G32-DAG: define x86_thiscallcc void @_ZN19ImportDefaultedDefsC2EOS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// G64-DAG: define void @_ZN19ImportDefaultedDefsC2EOS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
+ImportDefaultedDefs::ImportDefaultedDefs(ImportDefaultedDefs&&) = default; // dllimport ignored
+
+// M32-DAG: define x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @"\01??4ImportDefaultedDefs@@QAEAAU0@$$QAU0@@Z"(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// M64-DAG: define dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @"\01??4ImportDefaultedDefs@@QEAAAEAU0@$$QEAU0@@Z"(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// G32-DAG: define x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @_ZN19ImportDefaultedDefsaSEOS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
+// G64-DAG: define dereferenceable({{[0-9]+}}) %struct.ImportDefaultedDefs* @_ZN19ImportDefaultedDefsaSEOS_(%struct.ImportDefaultedDefs* %this, %struct.ImportDefaultedDefs* dereferenceable({{[0-9]+}}))
+ImportDefaultedDefs& ImportDefaultedDefs::operator=(ImportDefaultedDefs&&) = default; // dllimport ignored
+
+USESPECIALS(ImportDefaultedDefs)
+
+
+// Import allocation functions.
+struct ImportAlloc {
+ __declspec(dllimport) void* operator new(__SIZE_TYPE__);
+ __declspec(dllimport) void* operator new[](__SIZE_TYPE__);
+ __declspec(dllimport) void operator delete(void*);
+ __declspec(dllimport) void operator delete[](void*);
+};
+
+// M32-DAG: declare dllimport i8* @"\01??2ImportAlloc@@SAPAXI@Z"(i32)
+// M64-DAG: declare dllimport i8* @"\01??2ImportAlloc@@SAPEAX_K@Z"(i64)
+// G32-DAG: declare dllimport i8* @_ZN11ImportAllocnwEj(i32)
+// G64-DAG: declare dllimport i8* @_ZN11ImportAllocnwEy(i64)
+void UNIQ(use)() { new ImportAlloc(); }
+
+// M32-DAG: declare dllimport i8* @"\01??_UImportAlloc@@SAPAXI@Z"(i32)
+// M64-DAG: declare dllimport i8* @"\01??_UImportAlloc@@SAPEAX_K@Z"(i64)
+// G32-DAG: declare dllimport i8* @_ZN11ImportAllocnaEj(i32)
+// G64-DAG: declare dllimport i8* @_ZN11ImportAllocnaEy(i64)
+void UNIQ(use)() { new ImportAlloc[1]; }
+
+// M32-DAG: declare dllimport void @"\01??3ImportAlloc@@SAXPAX@Z"(i8*)
+// M64-DAG: declare dllimport void @"\01??3ImportAlloc@@SAXPEAX@Z"(i8*)
+// G32-DAG: declare dllimport void @_ZN11ImportAllocdlEPv(i8*)
+// G64-DAG: declare dllimport void @_ZN11ImportAllocdlEPv(i8*)
+void UNIQ(use)(ImportAlloc* ptr) { delete ptr; }
+
+// M32-DAG: declare dllimport void @"\01??_VImportAlloc@@SAXPAX@Z"(i8*)
+// M64-DAG: declare dllimport void @"\01??_VImportAlloc@@SAXPEAX@Z"(i8*)
+// G32-DAG: declare dllimport void @_ZN11ImportAllocdaEPv(i8*)
+// G64-DAG: declare dllimport void @_ZN11ImportAllocdaEPv(i8*)
+void UNIQ(use)(ImportAlloc* ptr) { delete[] ptr; }
+
+
+//===----------------------------------------------------------------------===//
+// Class member templates
+//===----------------------------------------------------------------------===//
+
+struct MemFunTmpl {
+ template<typename T> void normalDef() {}
+ template<typename T> __declspec(dllimport) void importedNormal() {}
+ template<typename T> static void staticDef() {}
+ template<typename T> __declspec(dllimport) static void importedStatic() {}
+};
+
+// Import implicit instantiation of an imported member function template.
+// M32-DAG: declare dllimport x86_thiscallcc void @"\01??$importedNormal@UImplicitInst_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*)
+// M64-DAG: declare dllimport void @"\01??$importedNormal@UImplicitInst_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*)
+// G32-DAG: declare dllimport x86_thiscallcc void @_ZN10MemFunTmpl14importedNormalI21ImplicitInst_ImportedEEvv(%struct.MemFunTmpl*)
+// G64-DAG: declare dllimport void @_ZN10MemFunTmpl14importedNormalI21ImplicitInst_ImportedEEvv(%struct.MemFunTmpl*)
+USEMF(MemFunTmpl, importedNormal<ImplicitInst_Imported>)
+
+// MSC-DAG: declare dllimport void @"\01??$importedStatic@UImplicitInst_Imported@@@MemFunTmpl@@SAXXZ"()
+// GNU-DAG: declare dllimport void @_ZN10MemFunTmpl14importedStaticI21ImplicitInst_ImportedEEvv()
+USE(MemFunTmpl::importedStatic<ImplicitInst_Imported>)
+
+
+// Import explicit instantiation declaration of an imported member function
+// template.
+// M32-DAG: declare dllimport x86_thiscallcc void @"\01??$importedNormal@UExplicitDecl_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*)
+// M64-DAG: declare dllimport void @"\01??$importedNormal@UExplicitDecl_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*)
+// G32-DAG: declare dllimport x86_thiscallcc void @_ZN10MemFunTmpl14importedNormalI21ExplicitDecl_ImportedEEvv(%struct.MemFunTmpl*)
+// G64-DAG: declare dllimport void @_ZN10MemFunTmpl14importedNormalI21ExplicitDecl_ImportedEEvv(%struct.MemFunTmpl*)
+extern template void MemFunTmpl::importedNormal<ExplicitDecl_Imported>();
+USEMF(MemFunTmpl, importedNormal<ExplicitDecl_Imported>)
+
+// MSC-DAG: declare dllimport void @"\01??$importedStatic@UExplicitDecl_Imported@@@MemFunTmpl@@SAXXZ"()
+// GNU-DAG: declare dllimport void @_ZN10MemFunTmpl14importedStaticI21ExplicitDecl_ImportedEEvv()
+extern template void MemFunTmpl::importedStatic<ExplicitDecl_Imported>();
+USE(MemFunTmpl::importedStatic<ExplicitDecl_Imported>)
+
+
+// Import explicit instantiation definition of an imported member function
+// template.
+// M32-DAG: declare dllimport x86_thiscallcc void @"\01??$importedNormal@UExplicitInst_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*)
+// M64-DAG: declare dllimport void @"\01??$importedNormal@UExplicitInst_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*)
+// G32-DAG: declare dllimport x86_thiscallcc void @_ZN10MemFunTmpl14importedNormalI21ExplicitInst_ImportedEEvv(%struct.MemFunTmpl*)
+// G64-DAG: declare dllimport void @_ZN10MemFunTmpl14importedNormalI21ExplicitInst_ImportedEEvv(%struct.MemFunTmpl*)
+template void MemFunTmpl::importedNormal<ExplicitInst_Imported>();
+USEMF(MemFunTmpl, importedNormal<ExplicitInst_Imported>)
+
+// MSC-DAG: declare dllimport void @"\01??$importedStatic@UExplicitInst_Imported@@@MemFunTmpl@@SAXXZ"()
+// GNU-DAG: declare dllimport void @_ZN10MemFunTmpl14importedStaticI21ExplicitInst_ImportedEEvv()
+template void MemFunTmpl::importedStatic<ExplicitInst_Imported>();
+USE(MemFunTmpl::importedStatic<ExplicitInst_Imported>)
+
+
+// Import specialization of an imported member function template.
+// M32-DAG: declare dllimport x86_thiscallcc void @"\01??$importedNormal@UExplicitSpec_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*)
+// M64-DAG: declare dllimport void @"\01??$importedNormal@UExplicitSpec_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*)
+// G32-DAG: declare dllimport x86_thiscallcc void @_ZN10MemFunTmpl14importedNormalI21ExplicitSpec_ImportedEEvv(%struct.MemFunTmpl*)
+// G64-DAG: declare dllimport void @_ZN10MemFunTmpl14importedNormalI21ExplicitSpec_ImportedEEvv(%struct.MemFunTmpl*)
+template<> __declspec(dllimport) void MemFunTmpl::importedNormal<ExplicitSpec_Imported>();
+USEMF(MemFunTmpl, importedNormal<ExplicitSpec_Imported>)
+
+// M32-DAG-FIXME: declare dllimport x86_thiscallcc void @"\01??$importedNormal@UExplicitSpec_Def_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*)
+// M64-DAG-FIXME: declare dllimport void @"\01??$importedNormal@UExplicitSpec_Def_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*)
+#ifdef MSABI
+//template<> __declspec(dllimport) void MemFunTmpl::importedNormal<ExplicitSpec_Def_Imported>() {}
+//USEMF(MemFunTmpl, importedNormal<ExplicitSpec_Def_Imported>)
+#endif
+
+// M32-DAG: declare dllimport x86_thiscallcc void @"\01??$importedNormal@UExplicitSpec_InlineDef_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*)
+// M64-DAG: declare dllimport void @"\01??$importedNormal@UExplicitSpec_InlineDef_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*)
+// G32-DAG: declare dllimport x86_thiscallcc void @_ZN10MemFunTmpl14importedNormalI31ExplicitSpec_InlineDef_ImportedEEvv(%struct.MemFunTmpl*)
+// G64-DAG: declare dllimport void @_ZN10MemFunTmpl14importedNormalI31ExplicitSpec_InlineDef_ImportedEEvv(%struct.MemFunTmpl*)
+template<> __declspec(dllimport) inline void MemFunTmpl::importedNormal<ExplicitSpec_InlineDef_Imported>() {}
+USEMF(MemFunTmpl, importedNormal<ExplicitSpec_InlineDef_Imported>)
+
+
+// MSC-DAG: declare dllimport void @"\01??$importedStatic@UExplicitSpec_Imported@@@MemFunTmpl@@SAXXZ"()
+// GNU-DAG: declare dllimport void @_ZN10MemFunTmpl14importedStaticI21ExplicitSpec_ImportedEEvv()
+template<> __declspec(dllimport) void MemFunTmpl::importedStatic<ExplicitSpec_Imported>();
+USE(MemFunTmpl::importedStatic<ExplicitSpec_Imported>)
+
+// MSC-DAG-FIXME: declare dllimport void @"\01??$importedStatic@UExplicitSpec_Def_Imported@@@MemFunTmpl@@SAXXZ"()
+#ifdef MSABI
+//template<> __declspec(dllimport) void MemFunTmpl::importedStatic<ExplicitSpec_Def_Imported>() {}
+//USE(MemFunTmpl::importedStatic<ExplicitSpec_Def_Imported>)
+#endif
+
+// MSC-DAG: declare dllimport void @"\01??$importedStatic@UExplicitSpec_InlineDef_Imported@@@MemFunTmpl@@SAXXZ"()
+// GNU-DAG: declare dllimport void @_ZN10MemFunTmpl14importedStaticI31ExplicitSpec_InlineDef_ImportedEEvv()
+template<> __declspec(dllimport) inline void MemFunTmpl::importedStatic<ExplicitSpec_InlineDef_Imported>() {}
+USE(MemFunTmpl::importedStatic<ExplicitSpec_InlineDef_Imported>)
+
+
+// Not importing specialization of an imported member function template without
+// explicit dllimport.
+// M32-DAG: define x86_thiscallcc void @"\01??$importedNormal@UExplicitSpec_NotImported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl* %this)
+// M64-DAG: define void @"\01??$importedNormal@UExplicitSpec_NotImported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl* %this)
+// G32-DAG: define x86_thiscallcc void @_ZN10MemFunTmpl14importedNormalI24ExplicitSpec_NotImportedEEvv(%struct.MemFunTmpl* %this)
+// G64-DAG: define void @_ZN10MemFunTmpl14importedNormalI24ExplicitSpec_NotImportedEEvv(%struct.MemFunTmpl* %this)
+template<> void MemFunTmpl::importedNormal<ExplicitSpec_NotImported>() {}
+USEMF(MemFunTmpl, importedNormal<ExplicitSpec_NotImported>)
+
+// MSC-DAG: define void @"\01??$importedStatic@UExplicitSpec_NotImported@@@MemFunTmpl@@SAXXZ"()
+// GNU-DAG: define void @_ZN10MemFunTmpl14importedStaticI24ExplicitSpec_NotImportedEEvv()
+template<> void MemFunTmpl::importedStatic<ExplicitSpec_NotImported>() {}
+USE(MemFunTmpl::importedStatic<ExplicitSpec_NotImported>)
+
+
+// Import explicit instantiation declaration of a non-imported member function
+// template.
+// M32-DAG: declare dllimport x86_thiscallcc void @"\01??$normalDef@UExplicitDecl_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*)
+// M64-DAG: declare dllimport void @"\01??$normalDef@UExplicitDecl_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*)
+// G32-DAG: declare dllimport x86_thiscallcc void @_ZN10MemFunTmpl9normalDefI21ExplicitDecl_ImportedEEvv(%struct.MemFunTmpl*)
+// G64-DAG: declare dllimport void @_ZN10MemFunTmpl9normalDefI21ExplicitDecl_ImportedEEvv(%struct.MemFunTmpl*)
+extern template __declspec(dllimport) void MemFunTmpl::normalDef<ExplicitDecl_Imported>();
+USEMF(MemFunTmpl, normalDef<ExplicitDecl_Imported>)
+
+// MSC-DAG: declare dllimport void @"\01??$staticDef@UExplicitDecl_Imported@@@MemFunTmpl@@SAXXZ"()
+// GNU-DAG: declare dllimport void @_ZN10MemFunTmpl9staticDefI21ExplicitDecl_ImportedEEvv()
+extern template __declspec(dllimport) void MemFunTmpl::staticDef<ExplicitDecl_Imported>();
+USE(MemFunTmpl::staticDef<ExplicitDecl_Imported>)
+
+
+// Import explicit instantiation definition of a non-imported member function
+// template.
+// M32-DAG: declare dllimport x86_thiscallcc void @"\01??$normalDef@UExplicitInst_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*)
+// M64-DAG: declare dllimport void @"\01??$normalDef@UExplicitInst_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*)
+// G32-DAG: declare dllimport x86_thiscallcc void @_ZN10MemFunTmpl9normalDefI21ExplicitInst_ImportedEEvv(%struct.MemFunTmpl*)
+// G64-DAG: declare dllimport void @_ZN10MemFunTmpl9normalDefI21ExplicitInst_ImportedEEvv(%struct.MemFunTmpl*)
+template __declspec(dllimport) void MemFunTmpl::normalDef<ExplicitInst_Imported>();
+USEMF(MemFunTmpl, normalDef<ExplicitInst_Imported>)
+
+// MSC-DAG: declare dllimport void @"\01??$staticDef@UExplicitInst_Imported@@@MemFunTmpl@@SAXXZ"()
+// GNU-DAG: declare dllimport void @_ZN10MemFunTmpl9staticDefI21ExplicitInst_ImportedEEvv()
+template __declspec(dllimport) void MemFunTmpl::staticDef<ExplicitInst_Imported>();
+USE(MemFunTmpl::staticDef<ExplicitInst_Imported>)
+
+
+// Import specialization of a non-imported member function template.
+// M32-DAG: declare dllimport x86_thiscallcc void @"\01??$normalDef@UExplicitSpec_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*)
+// M64-DAG: declare dllimport void @"\01??$normalDef@UExplicitSpec_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*)
+// G32-DAG: declare dllimport x86_thiscallcc void @_ZN10MemFunTmpl9normalDefI21ExplicitSpec_ImportedEEvv(%struct.MemFunTmpl*)
+// G64-DAG: declare dllimport void @_ZN10MemFunTmpl9normalDefI21ExplicitSpec_ImportedEEvv(%struct.MemFunTmpl*)
+template<> __declspec(dllimport) void MemFunTmpl::normalDef<ExplicitSpec_Imported>();
+USEMF(MemFunTmpl, normalDef<ExplicitSpec_Imported>)
+
+// M32-DAG-FIXME: declare dllimport x86_thiscallcc void @"\01??$normalDef@UExplicitSpec_Def_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*)
+// M64-DAG-FIXME: declare dllimport void @"\01??$normalDef@UExplicitSpec_Def_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*)
+#ifdef MSABI
+//template<> __declspec(dllimport) void MemFunTmpl::normalDef<ExplicitSpec_Def_Imported>() {}
+//USEMF(MemFunTmpl, normalDef<ExplicitSpec_Def_Imported>)
+#endif
+
+// M32-DAG: declare dllimport x86_thiscallcc void @"\01??$normalDef@UExplicitSpec_InlineDef_Imported@@@MemFunTmpl@@QAEXXZ"(%struct.MemFunTmpl*)
+// M64-DAG: declare dllimport void @"\01??$normalDef@UExplicitSpec_InlineDef_Imported@@@MemFunTmpl@@QEAAXXZ"(%struct.MemFunTmpl*)
+// G32-DAG: declare dllimport x86_thiscallcc void @_ZN10MemFunTmpl9normalDefI31ExplicitSpec_InlineDef_ImportedEEvv(%struct.MemFunTmpl*)
+// G64-DAG: declare dllimport void @_ZN10MemFunTmpl9normalDefI31ExplicitSpec_InlineDef_ImportedEEvv(%struct.MemFunTmpl*)
+template<> __declspec(dllimport) inline void MemFunTmpl::normalDef<ExplicitSpec_InlineDef_Imported>() {}
+USEMF(MemFunTmpl, normalDef<ExplicitSpec_InlineDef_Imported>)
+
+
+// MSC-DAG: declare dllimport void @"\01??$staticDef@UExplicitSpec_Imported@@@MemFunTmpl@@SAXXZ"()
+// GNU-DAG: declare dllimport void @_ZN10MemFunTmpl9staticDefI21ExplicitSpec_ImportedEEvv()
+template<> __declspec(dllimport) void MemFunTmpl::staticDef<ExplicitSpec_Imported>();
+USE(MemFunTmpl::staticDef<ExplicitSpec_Imported>)
+
+// MSC-DAG-FIXME: declare dllimport void @"\01??$staticDef@UExplicitSpec_Def_Imported@@@MemFunTmpl@@SAXXZ"()
+#ifdef MSABI
+//template<> __declspec(dllimport) void MemFunTmpl::staticDef<ExplicitSpec_Def_Imported>() {}
+//USE(MemFunTmpl::staticDef<ExplicitSpec_Def_Imported>)
+#endif
+
+// MSC-DAG: declare dllimport void @"\01??$staticDef@UExplicitSpec_InlineDef_Imported@@@MemFunTmpl@@SAXXZ"()
+// GNU-DAG: declare dllimport void @_ZN10MemFunTmpl9staticDefI31ExplicitSpec_InlineDef_ImportedEEvv()
+template<> __declspec(dllimport) inline void MemFunTmpl::staticDef<ExplicitSpec_InlineDef_Imported>() {}
+USE(MemFunTmpl::staticDef<ExplicitSpec_InlineDef_Imported>)
+
+
+
+struct MemVarTmpl {
+ template<typename T> static const int StaticVar = 1;
+ template<typename T> __declspec(dllimport) static const int ImportedStaticVar = 1;
+};
+
+// Import implicit instantiation of an imported member variable template.
+// MSC-DAG: @"\01??$ImportedStaticVar@UImplicitInst_Imported@@@MemVarTmpl@@2HB" = available_externally dllimport constant i32 1, align 4
+// GNU-DAG: @_ZN10MemVarTmpl17ImportedStaticVarI21ImplicitInst_ImportedEE = external dllimport constant i32
+USEMV(MemVarTmpl, ImportedStaticVar<ImplicitInst_Imported>)
+
+// Import explicit instantiation declaration of an imported member variable
+// template.
+// MSC-DAG: @"\01??$ImportedStaticVar@UExplicitDecl_Imported@@@MemVarTmpl@@2HB" = external dllimport constant i32
+// GNU-DAG: @_ZN10MemVarTmpl17ImportedStaticVarI21ExplicitDecl_ImportedEE = external dllimport constant i32
+extern template const int MemVarTmpl::ImportedStaticVar<ExplicitDecl_Imported>;
+USEMV(MemVarTmpl, ImportedStaticVar<ExplicitDecl_Imported>)
+
+// An explicit instantiation definition of an imported member variable template
+// cannot be imported because the template must be defined which is illegal. The
+// in-class initializer does not count.
+
+// Import specialization of an imported member variable template.
+// MSC-DAG: @"\01??$ImportedStaticVar@UExplicitSpec_Imported@@@MemVarTmpl@@2HB" = external dllimport constant i32
+// GNU-DAG: @_ZN10MemVarTmpl17ImportedStaticVarI21ExplicitSpec_ImportedEE = external dllimport constant i32
+template<> __declspec(dllimport) const int MemVarTmpl::ImportedStaticVar<ExplicitSpec_Imported>;
+USEMV(MemVarTmpl, ImportedStaticVar<ExplicitSpec_Imported>)
+
+// Not importing specialization of a member variable template without explicit
+// dllimport.
+// MSC-DAG: @"\01??$ImportedStaticVar@UExplicitSpec_NotImported@@@MemVarTmpl@@2HB" = external constant i32
+// GNU-DAG: @_ZN10MemVarTmpl17ImportedStaticVarI24ExplicitSpec_NotImportedEE = external constant i32
+template<> const int MemVarTmpl::ImportedStaticVar<ExplicitSpec_NotImported>;
+USEMV(MemVarTmpl, ImportedStaticVar<ExplicitSpec_NotImported>)
+
+
+// Import explicit instantiation declaration of a non-imported member variable
+// template.
+// MSC-DAG: @"\01??$StaticVar@UExplicitDecl_Imported@@@MemVarTmpl@@2HB" = external dllimport constant i32
+// GNU-DAG: @_ZN10MemVarTmpl9StaticVarI21ExplicitDecl_ImportedEE = external dllimport constant i32
+extern template __declspec(dllimport) const int MemVarTmpl::StaticVar<ExplicitDecl_Imported>;
+USEMV(MemVarTmpl, StaticVar<ExplicitDecl_Imported>)
+
+// An explicit instantiation definition of a non-imported member variable template
+// cannot be imported because the template must be defined which is illegal. The
+// in-class initializer does not count.
+
+// Import specialization of a non-imported member variable template.
+// MSC-DAG: @"\01??$StaticVar@UExplicitSpec_Imported@@@MemVarTmpl@@2HB" = external dllimport constant i32
+// GNU-DAG: @_ZN10MemVarTmpl9StaticVarI21ExplicitSpec_ImportedEE = external dllimport constant i32
+template<> __declspec(dllimport) const int MemVarTmpl::StaticVar<ExplicitSpec_Imported>;
+USEMV(MemVarTmpl, StaticVar<ExplicitSpec_Imported>)
diff --git a/test/CodeGenCXX/dllimport-rtti.cpp b/test/CodeGenCXX/dllimport-rtti.cpp
new file mode 100644
index 000000000000..7ed7dadfe402
--- /dev/null
+++ b/test/CodeGenCXX/dllimport-rtti.cpp
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -std=c++1y -O1 -disable-llvm-optzns -o - %s | FileCheck %s
+
+struct __declspec(dllimport) S {
+ virtual void f();
+} s;
+// CHECK-DAG: @"\01??_7S@@6B@" = available_externally dllimport
+// CHECK-DAG: @"\01??_R0?AUS@@@8" = linkonce_odr
+// CHECK-DAG: @"\01??_R1A@?0A@EA@S@@8" = linkonce_odr
+// CHECK-DAG: @"\01??_R2S@@8" = linkonce_odr
+// CHECK-DAG: @"\01??_R3S@@8" = linkonce_odr
+
+struct U : S {
+} u;
diff --git a/test/CodeGenCXX/dllimport.cpp b/test/CodeGenCXX/dllimport.cpp
new file mode 100644
index 000000000000..59f8f6361619
--- /dev/null
+++ b/test/CodeGenCXX/dllimport.cpp
@@ -0,0 +1,771 @@
+// RUN: %clang_cc1 -triple i686-windows-msvc -fno-rtti -emit-llvm -std=c++1y -O0 -o - %s -DMSABI | FileCheck --check-prefix=MSC --check-prefix=M32 %s
+// RUN: %clang_cc1 -triple x86_64-windows-msvc -fno-rtti -emit-llvm -std=c++1y -O0 -o - %s -DMSABI | FileCheck --check-prefix=MSC --check-prefix=M64 %s
+// RUN: %clang_cc1 -triple i686-windows-gnu -fno-rtti -emit-llvm -std=c++1y -O0 -o - %s | FileCheck --check-prefix=GNU --check-prefix=G32 %s
+// RUN: %clang_cc1 -triple x86_64-windows-gnu -fno-rtti -emit-llvm -std=c++1y -O0 -o - %s | FileCheck --check-prefix=GNU --check-prefix=G64 %s
+// RUN: %clang_cc1 -triple i686-windows-msvc -fno-rtti -emit-llvm -std=c++1y -O1 -o - %s -DMSABI | FileCheck --check-prefix=MO1 %s
+// RUN: %clang_cc1 -triple i686-windows-gnu -fno-rtti -emit-llvm -std=c++1y -O1 -o - %s | FileCheck --check-prefix=GO1 %s
+
+// CHECK-NOT doesn't play nice with CHECK-DAG, so use separate run lines.
+// RUN: %clang_cc1 -triple i686-windows-msvc -fno-rtti -emit-llvm -std=c++1y -O0 -o - %s -DMSABI | FileCheck --check-prefix=MSC2 %s
+// RUN: %clang_cc1 -triple i686-windows-gnu -fno-rtti -emit-llvm -std=c++1y -O0 -o - %s | FileCheck --check-prefix=GNU2 %s
+
+// Helper structs to make templates more expressive.
+struct ImplicitInst_Imported {};
+struct ImplicitInst_NotImported {};
+struct ExplicitDecl_Imported {};
+struct ExplicitInst_Imported {};
+struct ExplicitSpec_Imported {};
+struct ExplicitSpec_Def_Imported {};
+struct ExplicitSpec_InlineDef_Imported {};
+struct ExplicitSpec_NotImported {};
+
+#define JOIN2(x, y) x##y
+#define JOIN(x, y) JOIN2(x, y)
+#define UNIQ(name) JOIN(name, __LINE__)
+#define USEVARTYPE(type, var) type UNIQ(use)() { return var; }
+#define USEVAR(var) USEVARTYPE(int, var)
+#define USE(func) void UNIQ(use)() { func(); }
+#define USEMEMFUNC(class, func) void (class::*UNIQ(use)())() { return &class::func; }
+#define USECLASS(class) void UNIQ(USE)() { class x; }
+#define USECOPYASSIGN(class) class& (class::*UNIQ(use)())(class&) { return &class::operator=; }
+#define USEMOVEASSIGN(class) class& (class::*UNIQ(use)())(class&&) { return &class::operator=; }
+
+//===----------------------------------------------------------------------===//
+// Globals
+//===----------------------------------------------------------------------===//
+
+// Import declaration.
+// MSC-DAG: @"\01?ExternGlobalDecl@@3HA" = external dllimport global i32
+// GNU-DAG: @ExternGlobalDecl = external dllimport global i32
+__declspec(dllimport) extern int ExternGlobalDecl;
+USEVAR(ExternGlobalDecl)
+
+// dllimport implies a declaration.
+// MSC-DAG: @"\01?GlobalDecl@@3HA" = external dllimport global i32
+// GNU-DAG: @GlobalDecl = external dllimport global i32
+__declspec(dllimport) int GlobalDecl;
+USEVAR(GlobalDecl)
+
+// Redeclarations
+// MSC-DAG: @"\01?GlobalRedecl1@@3HA" = external dllimport global i32
+// GNU-DAG: @GlobalRedecl1 = external dllimport global i32
+__declspec(dllimport) extern int GlobalRedecl1;
+__declspec(dllimport) extern int GlobalRedecl1;
+USEVAR(GlobalRedecl1)
+
+// MSC-DAG: @"\01?GlobalRedecl2a@@3HA" = external dllimport global i32
+// GNU-DAG: @GlobalRedecl2a = external dllimport global i32
+__declspec(dllimport) int GlobalRedecl2a;
+__declspec(dllimport) int GlobalRedecl2a;
+USEVAR(GlobalRedecl2a)
+
+// M32-DAG: @"\01?GlobalRedecl2b@@3PAHA" = external dllimport global i32*
+// M64-DAG: @"\01?GlobalRedecl2b@@3PEAHEA" = external dllimport global i32*
+// GNU-DAG: @GlobalRedecl2b = external dllimport global i32*
+int *__attribute__((dllimport)) GlobalRedecl2b;
+int *__attribute__((dllimport)) GlobalRedecl2b;
+USEVARTYPE(int*, GlobalRedecl2b)
+
+// MSC-DAG: @"\01?GlobalRedecl2c@@3HA" = external dllimport global i32
+// GNU-DAG: @GlobalRedecl2c = external dllimport global i32
+int GlobalRedecl2c __attribute__((dllimport));
+int GlobalRedecl2c __attribute__((dllimport));
+USEVAR(GlobalRedecl2c)
+
+// NB: MSC issues a warning and makes GlobalRedecl3 dllexport. We follow GCC
+// and drop the dllimport with a warning.
+// MSC-DAG: @"\01?GlobalRedecl3@@3HA" = external global i32
+// GNU-DAG: @GlobalRedecl3 = external global i32
+__declspec(dllimport) extern int GlobalRedecl3;
+ extern int GlobalRedecl3; // dllimport ignored
+USEVAR(GlobalRedecl3)
+
+// MSC-DAG: @"\01?ExternalGlobal@ns@@3HA" = external dllimport global i32
+// GNU-DAG: @_ZN2ns14ExternalGlobalE = external dllimport global i32
+namespace ns { __declspec(dllimport) int ExternalGlobal; }
+USEVAR(ns::ExternalGlobal)
+
+int f();
+// MO1-DAG: @"\01?x@?1??inlineStaticLocalsFunc@@YAHXZ@4HA" = available_externally dllimport global i32 0
+// MO1-DAG: @"\01??_B?1??inlineStaticLocalsFunc@@YAHXZ@51" = available_externally dllimport global i32 0
+inline int __declspec(dllimport) inlineStaticLocalsFunc() {
+ static int x = f();
+ return x++;
+};
+USE(inlineStaticLocalsFunc);
+
+// The address of a dllimport global cannot be used in constant initialization.
+// M32-DAG: @"\01?arr@?0??initializationFunc@@YAPAHXZ@4QBQAHB" = internal global [1 x i32*] zeroinitializer
+// GNU-DAG: @_ZZ18initializationFuncvE3arr = internal global [1 x i32*] zeroinitializer
+int *initializationFunc() {
+ static int *const arr[] = {&ExternGlobalDecl};
+ return arr[0];
+}
+USE(initializationFunc);
+
+
+//===----------------------------------------------------------------------===//
+// Variable templates
+//===----------------------------------------------------------------------===//
+
+// Import declaration.
+// MSC-DAG: @"\01??$ExternVarTmplDecl@UImplicitInst_Imported@@@@3HA" = external dllimport global i32
+// GNU-DAG: @_Z17ExternVarTmplDeclI21ImplicitInst_ImportedE = external dllimport global i32
+template<typename T> __declspec(dllimport) extern int ExternVarTmplDecl;
+USEVAR(ExternVarTmplDecl<ImplicitInst_Imported>)
+
+// dllimport implies a declaration.
+// MSC-DAG: @"\01??$VarTmplDecl@UImplicitInst_Imported@@@@3HA" = external dllimport global i32
+// GNU-DAG: @_Z11VarTmplDeclI21ImplicitInst_ImportedE = external dllimport global i32
+template<typename T> __declspec(dllimport) int VarTmplDecl;
+USEVAR(VarTmplDecl<ImplicitInst_Imported>)
+
+// Redeclarations
+// MSC-DAG: @"\01??$VarTmplRedecl1@UImplicitInst_Imported@@@@3HA" = external dllimport global i32
+// GNU-DAG: @_Z14VarTmplRedecl1I21ImplicitInst_ImportedE = external dllimport global i32
+template<typename T> __declspec(dllimport) extern int VarTmplRedecl1;
+template<typename T> __declspec(dllimport) extern int VarTmplRedecl1;
+USEVAR(VarTmplRedecl1<ImplicitInst_Imported>)
+
+// MSC-DAG: @"\01??$VarTmplRedecl2@UImplicitInst_Imported@@@@3HA" = external dllimport global i32
+// GNU-DAG: @_Z14VarTmplRedecl2I21ImplicitInst_ImportedE = external dllimport global i32
+template<typename T> __declspec(dllimport) int VarTmplRedecl2;
+template<typename T> __declspec(dllimport) int VarTmplRedecl2;
+USEVAR(VarTmplRedecl2<ImplicitInst_Imported>)
+
+// MSC-DAG: @"\01??$VarTmplRedecl3@UImplicitInst_Imported@@@@3HA" = external global i32
+// GNU-DAG: @_Z14VarTmplRedecl3I21ImplicitInst_ImportedE = external global i32
+template<typename T> __declspec(dllimport) extern int VarTmplRedecl3;
+template<typename T> extern int VarTmplRedecl3; // dllimport ignored
+USEVAR(VarTmplRedecl3<ImplicitInst_Imported>)
+
+
+// MSC-DAG: @"\01??$ExternalVarTmpl@UImplicitInst_Imported@@@ns@@3HA" = external dllimport global i32
+// GNU-DAG: @_ZN2ns15ExternalVarTmplI21ImplicitInst_ImportedEE = external dllimport global i32
+namespace ns { template<typename T> __declspec(dllimport) int ExternalVarTmpl; }
+USEVAR(ns::ExternalVarTmpl<ImplicitInst_Imported>)
+
+
+template<typename T> int VarTmpl;
+template<typename T> __declspec(dllimport) int ImportedVarTmpl;
+
+// Import implicit instantiation of an imported variable template.
+// MSC-DAG: @"\01??$ImportedVarTmpl@UImplicitInst_Imported@@@@3HA" = external dllimport global i32
+// GNU-DAG: @_Z15ImportedVarTmplI21ImplicitInst_ImportedE = external dllimport global i32
+USEVAR(ImportedVarTmpl<ImplicitInst_Imported>)
+
+// Import explicit instantiation declaration of an imported variable template.
+// MSC-DAG: @"\01??$ImportedVarTmpl@UExplicitDecl_Imported@@@@3HA" = external dllimport global i32
+// GNU-DAG: @_Z15ImportedVarTmplI21ExplicitDecl_ImportedE = external dllimport global i32
+extern template int ImportedVarTmpl<ExplicitDecl_Imported>;
+USEVAR(ImportedVarTmpl<ExplicitDecl_Imported>)
+
+// An explicit instantiation definition of an imported variable template cannot
+// be imported because the template must be defined which is illegal.
+
+// Import specialization of an imported variable template.
+// MSC-DAG: @"\01??$ImportedVarTmpl@UExplicitSpec_Imported@@@@3HA" = external dllimport global i32
+// GNU-DAG: @_Z15ImportedVarTmplI21ExplicitSpec_ImportedE = external dllimport global i32
+template<> __declspec(dllimport) int ImportedVarTmpl<ExplicitSpec_Imported>;
+USEVAR(ImportedVarTmpl<ExplicitSpec_Imported>)
+
+// Not importing specialization of an imported variable template without
+// explicit dllimport.
+// MSC-DAG: @"\01??$ImportedVarTmpl@UExplicitSpec_NotImported@@@@3HA" = global i32 0, align 4
+// GNU-DAG: @_Z15ImportedVarTmplI24ExplicitSpec_NotImportedE = global i32 0, align 4
+template<> int ImportedVarTmpl<ExplicitSpec_NotImported>;
+USEVAR(ImportedVarTmpl<ExplicitSpec_NotImported>)
+
+// Import explicit instantiation declaration of a non-imported variable template.
+// MSC-DAG: @"\01??$VarTmpl@UExplicitDecl_Imported@@@@3HA" = external dllimport global i32
+// GNU-DAG: @_Z7VarTmplI21ExplicitDecl_ImportedE = external dllimport global i32
+extern template __declspec(dllimport) int VarTmpl<ExplicitDecl_Imported>;
+USEVAR(VarTmpl<ExplicitDecl_Imported>)
+
+// Import explicit instantiation definition of a non-imported variable template.
+// MSC-DAG: @"\01??$VarTmpl@UExplicitInst_Imported@@@@3HA" = external dllimport global i32
+// GNU-DAG: @_Z7VarTmplI21ExplicitInst_ImportedE = external dllimport global i32
+template __declspec(dllimport) int VarTmpl<ExplicitInst_Imported>;
+USEVAR(VarTmpl<ExplicitInst_Imported>)
+
+// Import specialization of a non-imported variable template.
+// MSC-DAG: @"\01??$VarTmpl@UExplicitSpec_Imported@@@@3HA" = external dllimport global i32
+// GNU-DAG: @_Z7VarTmplI21ExplicitSpec_ImportedE = external dllimport global i32
+template<> __declspec(dllimport) int VarTmpl<ExplicitSpec_Imported>;
+USEVAR(VarTmpl<ExplicitSpec_Imported>)
+
+
+
+//===----------------------------------------------------------------------===//
+// Functions
+//===----------------------------------------------------------------------===//
+
+// Import function declaration.
+// MSC-DAG: declare dllimport void @"\01?decl@@YAXXZ"()
+// GNU-DAG: declare dllimport void @_Z4declv()
+__declspec(dllimport) void decl();
+USE(decl)
+
+// extern "C"
+// MSC-DAG: declare dllimport void @externC()
+// GNU-DAG: declare dllimport void @externC()
+extern "C" __declspec(dllimport) void externC();
+USE(externC)
+
+// Import inline function.
+// MSC-DAG: declare dllimport void @"\01?inlineFunc@@YAXXZ"()
+// GNU-DAG: declare dllimport void @_Z10inlineFuncv()
+// MO1-DAG: define available_externally dllimport void @"\01?inlineFunc@@YAXXZ"()
+// GO1-DAG: define available_externally dllimport void @_Z10inlineFuncv()
+__declspec(dllimport) inline void inlineFunc() {}
+USE(inlineFunc)
+
+// MSC-DAG: declare dllimport void @"\01?inlineDecl@@YAXXZ"()
+// GNU-DAG: declare dllimport void @_Z10inlineDeclv()
+// MO1-DAG: define available_externally dllimport void @"\01?inlineDecl@@YAXXZ"()
+// GO1-DAG: define available_externally dllimport void @_Z10inlineDeclv()
+__declspec(dllimport) inline void inlineDecl();
+ void inlineDecl() {}
+USE(inlineDecl)
+
+// MSC-DAG: declare dllimport void @"\01?inlineDef@@YAXXZ"()
+// GNU-DAG: declare dllimport void @_Z9inlineDefv()
+// MO1-DAG: define available_externally dllimport void @"\01?inlineDef@@YAXXZ"()
+// GO1-DAG: define available_externally dllimport void @_Z9inlineDefv()
+__declspec(dllimport) void inlineDef();
+ inline void inlineDef() {}
+USE(inlineDef)
+
+// inline attributes
+// MSC-DAG: declare dllimport void @"\01?noinline@@YAXXZ"()
+// GNU-DAG: declare dllimport void @_Z8noinlinev()
+__declspec(dllimport) __attribute__((noinline)) inline void noinline() {}
+USE(noinline)
+
+// MSC2-NOT: @"\01?alwaysInline@@YAXXZ"()
+// GNU2-NOT: @_Z12alwaysInlinev()
+__declspec(dllimport) __attribute__((always_inline)) inline void alwaysInline() {}
+USE(alwaysInline)
+
+// Redeclarations
+// MSC-DAG: declare dllimport void @"\01?redecl1@@YAXXZ"()
+// GNU-DAG: declare dllimport void @_Z7redecl1v()
+__declspec(dllimport) void redecl1();
+__declspec(dllimport) void redecl1();
+USE(redecl1)
+
+// NB: MSC issues a warning and makes redecl2/redecl3 dllexport. We follow GCC
+// and drop the dllimport with a warning.
+// MSC-DAG: declare void @"\01?redecl2@@YAXXZ"()
+// GNU-DAG: declare void @_Z7redecl2v()
+__declspec(dllimport) void redecl2();
+ void redecl2();
+USE(redecl2)
+
+// MSC-DAG: define void @"\01?redecl3@@YAXXZ"()
+// GNU-DAG: define void @_Z7redecl3v()
+__declspec(dllimport) void redecl3();
+ void redecl3() {} // dllimport ignored
+USE(redecl3)
+
+
+// Friend functions
+// MSC-DAG: declare dllimport void @"\01?friend1@@YAXXZ"()
+// GNU-DAG: declare dllimport void @_Z7friend1v()
+// MSC-DAG: declare void @"\01?friend2@@YAXXZ"()
+// GNU-DAG: declare void @_Z7friend2v()
+// MSC-DAG: define void @"\01?friend3@@YAXXZ"()
+// GNU-DAG: define void @_Z7friend3v()
+struct FuncFriend {
+ friend __declspec(dllimport) void friend1();
+ friend __declspec(dllimport) void friend2();
+ friend __declspec(dllimport) void friend3();
+};
+__declspec(dllimport) void friend1();
+ void friend2(); // dllimport ignored
+ void friend3() {} // dllimport ignored
+USE(friend1)
+USE(friend2)
+USE(friend3)
+
+// Implicit declarations can be redeclared with dllimport.
+// MSC-DAG: declare dllimport noalias i8* @"\01??2@{{YAPAXI|YAPEAX_K}}@Z"(
+// GNU-DAG: declare dllimport noalias i8* @_Znw{{[yj]}}(
+__declspec(dllimport) void* operator new(__SIZE_TYPE__ n);
+void UNIQ(use)() { ::operator new(42); }
+
+// MSC-DAG: declare dllimport void @"\01?externalFunc@ns@@YAXXZ"()
+// GNU-DAG: declare dllimport void @_ZN2ns12externalFuncEv()
+namespace ns { __declspec(dllimport) void externalFunc(); }
+USE(ns::externalFunc)
+
+
+
+//===----------------------------------------------------------------------===//
+// Function templates
+//===----------------------------------------------------------------------===//
+
+// Import function template declaration.
+// MSC-DAG: declare dllimport void @"\01??$funcTmplDecl@UImplicitInst_Imported@@@@YAXXZ"()
+// GNU-DAG: declare dllimport void @_Z12funcTmplDeclI21ImplicitInst_ImportedEvv()
+template<typename T> __declspec(dllimport) void funcTmplDecl();
+USE(funcTmplDecl<ImplicitInst_Imported>)
+
+// Function template definitions cannot be imported.
+
+// Import inline function template.
+// MSC-DAG: declare dllimport void @"\01??$inlineFuncTmpl1@UImplicitInst_Imported@@@@YAXXZ"()
+// GNU-DAG: declare dllimport void @_Z15inlineFuncTmpl1I21ImplicitInst_ImportedEvv()
+// MO1-DAG: define available_externally dllimport void @"\01??$inlineFuncTmpl1@UImplicitInst_Imported@@@@YAXXZ"()
+// GO1-DAG: define available_externally dllimport void @_Z15inlineFuncTmpl1I21ImplicitInst_ImportedEvv()
+template<typename T> __declspec(dllimport) inline void inlineFuncTmpl1() {}
+USE(inlineFuncTmpl1<ImplicitInst_Imported>)
+
+// MSC-DAG: declare dllimport void @"\01??$inlineFuncTmpl2@UImplicitInst_Imported@@@@YAXXZ"()
+// GNU-DAG: declare dllimport void @_Z15inlineFuncTmpl2I21ImplicitInst_ImportedEvv()
+// MO1-DAG: define available_externally dllimport void @"\01??$inlineFuncTmpl2@UImplicitInst_Imported@@@@YAXXZ"()
+// GO1-DAG: define available_externally dllimport void @_Z15inlineFuncTmpl2I21ImplicitInst_ImportedEvv()
+template<typename T> inline void __attribute__((dllimport)) inlineFuncTmpl2() {}
+USE(inlineFuncTmpl2<ImplicitInst_Imported>)
+
+// MSC-DAG: declare dllimport void @"\01??$inlineFuncTmplDecl@UImplicitInst_Imported@@@@YAXXZ"()
+// GNU-DAG: declare dllimport void @_Z18inlineFuncTmplDeclI21ImplicitInst_ImportedEvv()
+// MO1-DAG: define available_externally dllimport void @"\01??$inlineFuncTmplDecl@UImplicitInst_Imported@@@@YAXXZ"()
+// GO1-DAG: define available_externally dllimport void @_Z18inlineFuncTmplDeclI21ImplicitInst_ImportedEvv()
+template<typename T> __declspec(dllimport) inline void inlineFuncTmplDecl();
+template<typename T> void inlineFuncTmplDecl() {}
+USE(inlineFuncTmplDecl<ImplicitInst_Imported>)
+
+// MSC-DAG: declare dllimport void @"\01??$inlineFuncTmplDef@UImplicitInst_Imported@@@@YAXXZ"()
+// GNU-DAG: declare dllimport void @_Z17inlineFuncTmplDefI21ImplicitInst_ImportedEvv()
+// MO1-DAG: define available_externally dllimport void @"\01??$inlineFuncTmplDef@UImplicitInst_Imported@@@@YAXXZ"()
+// GO1-DAG: define available_externally dllimport void @_Z17inlineFuncTmplDefI21ImplicitInst_ImportedEvv()
+template<typename T> __declspec(dllimport) void inlineFuncTmplDef();
+template<typename T> inline void inlineFuncTmplDef() {}
+USE(inlineFuncTmplDef<ImplicitInst_Imported>)
+
+
+// Redeclarations
+// MSC-DAG: declare dllimport void @"\01??$funcTmplRedecl1@UImplicitInst_Imported@@@@YAXXZ"()
+// GNU-DAG: declare dllimport void @_Z15funcTmplRedecl1I21ImplicitInst_ImportedEvv()
+template<typename T> __declspec(dllimport) void funcTmplRedecl1();
+template<typename T> __declspec(dllimport) void funcTmplRedecl1();
+USE(funcTmplRedecl1<ImplicitInst_Imported>)
+
+// MSC-DAG: declare void @"\01??$funcTmplRedecl2@UImplicitInst_NotImported@@@@YAXXZ"()
+// GNU-DAG: declare void @_Z15funcTmplRedecl2I24ImplicitInst_NotImportedEvv()
+template<typename T> __declspec(dllimport) void funcTmplRedecl2();
+template<typename T> void funcTmplRedecl2(); // dllimport ignored
+USE(funcTmplRedecl2<ImplicitInst_NotImported>)
+
+// MSC-DAG: define linkonce_odr void @"\01??$funcTmplRedecl3@UImplicitInst_NotImported@@@@YAXXZ"()
+// GNU-DAG: define linkonce_odr void @_Z15funcTmplRedecl3I24ImplicitInst_NotImportedEvv()
+template<typename T> __declspec(dllimport) void funcTmplRedecl3();
+template<typename T> void funcTmplRedecl3() {} // dllimport ignored
+USE(funcTmplRedecl3<ImplicitInst_NotImported>)
+
+
+// Function template friends
+// MSC-DAG: declare dllimport void @"\01??$funcTmplFriend1@UImplicitInst_Imported@@@@YAXXZ"()
+// GNU-DAG: declare dllimport void @_Z15funcTmplFriend1I21ImplicitInst_ImportedEvv()
+// MSC-DAG: declare void @"\01??$funcTmplFriend2@UImplicitInst_NotImported@@@@YAXXZ"()
+// GNU-DAG: declare void @_Z15funcTmplFriend2I24ImplicitInst_NotImportedEvv()
+// MSC-DAG: define linkonce_odr void @"\01??$funcTmplFriend3@UImplicitInst_NotImported@@@@YAXXZ"()
+// GNU-DAG: define linkonce_odr void @_Z15funcTmplFriend3I24ImplicitInst_NotImportedEvv()
+// MSC-DAG: declare dllimport void @"\01??$funcTmplFriend4@UImplicitInst_Imported@@@@YAXXZ"()
+// GNU-DAG: declare dllimport void @_Z15funcTmplFriend4I21ImplicitInst_ImportedEvv()
+struct FuncTmplFriend {
+ template<typename T> friend __declspec(dllimport) void funcTmplFriend1();
+ template<typename T> friend __declspec(dllimport) void funcTmplFriend2();
+ template<typename T> friend __declspec(dllimport) void funcTmplFriend3();
+ template<typename T> friend __declspec(dllimport) inline void funcTmplFriend4();
+};
+template<typename T> __declspec(dllimport) void funcTmplFriend1();
+template<typename T> void funcTmplFriend2(); // dllimport ignored
+template<typename T> void funcTmplFriend3() {} // dllimport ignored
+template<typename T> inline void funcTmplFriend4() {}
+USE(funcTmplFriend1<ImplicitInst_Imported>)
+USE(funcTmplFriend2<ImplicitInst_NotImported>)
+USE(funcTmplFriend3<ImplicitInst_NotImported>)
+USE(funcTmplFriend4<ImplicitInst_Imported>)
+
+// MSC-DAG: declare dllimport void @"\01??$externalFuncTmpl@UImplicitInst_Imported@@@ns@@YAXXZ"()
+// GNU-DAG: declare dllimport void @_ZN2ns16externalFuncTmplI21ImplicitInst_ImportedEEvv()
+namespace ns { template<typename T> __declspec(dllimport) void externalFuncTmpl(); }
+USE(ns::externalFuncTmpl<ImplicitInst_Imported>)
+
+
+template<typename T> void funcTmpl() {}
+template<typename T> inline void inlineFuncTmpl() {}
+template<typename T> __declspec(dllimport) void importedFuncTmplDecl();
+template<typename T> __declspec(dllimport) inline void importedFuncTmpl() {}
+
+// Import implicit instantiation of an imported function template.
+// MSC-DAG: declare dllimport void @"\01??$importedFuncTmplDecl@UImplicitInst_Imported@@@@YAXXZ"()
+// GNU-DAG: declare dllimport void @_Z20importedFuncTmplDeclI21ImplicitInst_ImportedEvv()
+USE(importedFuncTmplDecl<ImplicitInst_Imported>)
+
+// MSC-DAG: declare dllimport void @"\01??$importedFuncTmpl@UImplicitInst_Imported@@@@YAXXZ"()
+// GNU-DAG: declare dllimport void @_Z16importedFuncTmplI21ImplicitInst_ImportedEvv()
+// MO1-DAG: define available_externally dllimport void @"\01??$importedFuncTmpl@UImplicitInst_Imported@@@@YAXXZ"()
+// GO1-DAG: define available_externally dllimport void @_Z16importedFuncTmplI21ImplicitInst_ImportedEvv()
+USE(importedFuncTmpl<ImplicitInst_Imported>)
+
+// Import explicit instantiation declaration of an imported function template.
+// MSC-DAG: declare dllimport void @"\01??$importedFuncTmpl@UExplicitDecl_Imported@@@@YAXXZ"()
+// GNU-DAG: declare dllimport void @_Z16importedFuncTmplI21ExplicitDecl_ImportedEvv()
+// MO1-DAG: define available_externally dllimport void @"\01??$importedFuncTmpl@UExplicitDecl_Imported@@@@YAXXZ"()
+// GO1-DAG: define available_externally dllimport void @_Z16importedFuncTmplI21ExplicitDecl_ImportedEvv()
+extern template void importedFuncTmpl<ExplicitDecl_Imported>();
+USE(importedFuncTmpl<ExplicitDecl_Imported>)
+
+// Import explicit instantiation definition of an imported function template.
+// MSC-DAG: declare dllimport void @"\01??$importedFuncTmpl@UExplicitInst_Imported@@@@YAXXZ"()
+// GNU-DAG: declare dllimport void @_Z16importedFuncTmplI21ExplicitInst_ImportedEvv()
+// MO1-DAG: define available_externally dllimport void @"\01??$importedFuncTmpl@UExplicitInst_Imported@@@@YAXXZ"()
+// GO1-DAG: define available_externally dllimport void @_Z16importedFuncTmplI21ExplicitInst_ImportedEvv()
+template void importedFuncTmpl<ExplicitInst_Imported>();
+USE(importedFuncTmpl<ExplicitInst_Imported>)
+
+
+// Import specialization of an imported function template.
+// MSC-DAG: declare dllimport void @"\01??$importedFuncTmplDecl@UExplicitSpec_Imported@@@@YAXXZ"()
+// GNU-DAG: declare dllimport void @_Z20importedFuncTmplDeclI21ExplicitSpec_ImportedEvv()
+template<> __declspec(dllimport) void importedFuncTmplDecl<ExplicitSpec_Imported>();
+USE(importedFuncTmplDecl<ExplicitSpec_Imported>)
+
+// MSC-DAG-FIXME: declare dllimport void @"\01??$importedFuncTmplDecl@UExplicitSpec_Def_Imported@@@@YAXXZ"()
+// MO1-DAG-FIXME: define available_externally dllimport void @"\01??$importedFuncTmplDecl@UExplicitSpec_Def_Imported@@@@YAXXZ"()
+#ifdef MSABI
+//template<> __declspec(dllimport) void importedFuncTmplDecl<ExplicitSpec_Def_Imported>() {}
+//USE(importedFuncTmplDecl<ExplicitSpec_Def_Imported>)
+#endif
+
+// MSC-DAG: declare dllimport void @"\01??$importedFuncTmplDecl@UExplicitSpec_InlineDef_Imported@@@@YAXXZ"()
+// GNU-DAG: declare dllimport void @_Z20importedFuncTmplDeclI31ExplicitSpec_InlineDef_ImportedEvv()
+// MO1-DAG: define available_externally dllimport void @"\01??$importedFuncTmplDecl@UExplicitSpec_InlineDef_Imported@@@@YAXXZ"()
+// GO1-DAG: define available_externally dllimport void @_Z20importedFuncTmplDeclI31ExplicitSpec_InlineDef_ImportedEvv()
+template<> __declspec(dllimport) inline void importedFuncTmplDecl<ExplicitSpec_InlineDef_Imported>() {}
+USE(importedFuncTmplDecl<ExplicitSpec_InlineDef_Imported>)
+
+
+// MSC-DAG: declare dllimport void @"\01??$importedFuncTmpl@UExplicitSpec_Imported@@@@YAXXZ"()
+// GNU-DAG: declare dllimport void @_Z16importedFuncTmplI21ExplicitSpec_ImportedEvv()
+template<> __declspec(dllimport) void importedFuncTmpl<ExplicitSpec_Imported>();
+USE(importedFuncTmpl<ExplicitSpec_Imported>)
+
+// MSC-DAG-FIXME: declare dllimport void @"\01??$importedFuncTmpl@UExplicitSpec_Def_Imported@@@@YAXXZ"()
+// MO1-DAG-FIXME: define available_externally dllimport void @"\01??$importedFuncTmpl@UExplicitSpec_Def_Imported@@@@YAXXZ"()
+#ifdef MSABI
+//template<> __declspec(dllimport) void importedFuncTmpl<ExplicitSpec_Def_Imported>() {}
+//USE(importedFuncTmpl<ExplicitSpec_Def_Imported>)
+#endif
+
+// MSC-DAG: declare dllimport void @"\01??$importedFuncTmpl@UExplicitSpec_InlineDef_Imported@@@@YAXXZ"()
+// GNU-DAG: declare dllimport void @_Z16importedFuncTmplI31ExplicitSpec_InlineDef_ImportedEvv()
+// MO1-DAG: define available_externally dllimport void @"\01??$importedFuncTmpl@UExplicitSpec_InlineDef_Imported@@@@YAXXZ"()
+// GO1-DAG: define available_externally dllimport void @_Z16importedFuncTmplI31ExplicitSpec_InlineDef_ImportedEvv()
+template<> __declspec(dllimport) inline void importedFuncTmpl<ExplicitSpec_InlineDef_Imported>() {}
+USE(importedFuncTmpl<ExplicitSpec_InlineDef_Imported>)
+
+
+// Not importing specialization of an imported function template without
+// explicit dllimport.
+// MSC-DAG: define void @"\01??$importedFuncTmpl@UExplicitSpec_NotImported@@@@YAXXZ"()
+// GNU-DAG: define void @_Z16importedFuncTmplI24ExplicitSpec_NotImportedEvv()
+template<> void importedFuncTmpl<ExplicitSpec_NotImported>() {}
+USE(importedFuncTmpl<ExplicitSpec_NotImported>)
+
+
+// Import explicit instantiation declaration of a non-imported function template.
+// MSC-DAG: declare dllimport void @"\01??$funcTmpl@UExplicitDecl_Imported@@@@YAXXZ"()
+// MSC-DAG: declare dllimport void @"\01??$inlineFuncTmpl@UExplicitDecl_Imported@@@@YAXXZ"()
+// GNU-DAG: declare dllimport void @_Z8funcTmplI21ExplicitDecl_ImportedEvv()
+// GNU-DAG: declare dllimport void @_Z14inlineFuncTmplI21ExplicitDecl_ImportedEvv()
+// MO1-DAG: define available_externally dllimport void @"\01??$inlineFuncTmpl@UExplicitDecl_Imported@@@@YAXXZ"()
+// GO1-DAG: define available_externally dllimport void @_Z14inlineFuncTmplI21ExplicitDecl_ImportedEvv()
+extern template __declspec(dllimport) void funcTmpl<ExplicitDecl_Imported>();
+extern template __declspec(dllimport) void inlineFuncTmpl<ExplicitDecl_Imported>();
+USE(funcTmpl<ExplicitDecl_Imported>)
+USE(inlineFuncTmpl<ExplicitDecl_Imported>)
+
+
+// Import explicit instantiation definition of a non-imported function template.
+// MSC-DAG: declare dllimport void @"\01??$funcTmpl@UExplicitInst_Imported@@@@YAXXZ"()
+// MSC-DAG: declare dllimport void @"\01??$inlineFuncTmpl@UExplicitInst_Imported@@@@YAXXZ"()
+// GNU-DAG: declare dllimport void @_Z8funcTmplI21ExplicitInst_ImportedEvv()
+// GNU-DAG: declare dllimport void @_Z14inlineFuncTmplI21ExplicitInst_ImportedEvv()
+// MO1-DAG: define available_externally dllimport void @"\01??$funcTmpl@UExplicitInst_Imported@@@@YAXXZ"()
+// MO1-DAG: define available_externally dllimport void @"\01??$inlineFuncTmpl@UExplicitInst_Imported@@@@YAXXZ"()
+// GO1-DAG: define available_externally dllimport void @_Z8funcTmplI21ExplicitInst_ImportedEvv()
+// GO1-DAG: define available_externally dllimport void @_Z14inlineFuncTmplI21ExplicitInst_ImportedEvv()
+template __declspec(dllimport) void funcTmpl<ExplicitInst_Imported>();
+template __declspec(dllimport) void inlineFuncTmpl<ExplicitInst_Imported>();
+USE(funcTmpl<ExplicitInst_Imported>)
+USE(inlineFuncTmpl<ExplicitInst_Imported>)
+
+
+// Import specialization of a non-imported function template.
+// MSC-DAG: declare dllimport void @"\01??$funcTmpl@UExplicitSpec_Imported@@@@YAXXZ"()
+// GNU-DAG: declare dllimport void @_Z8funcTmplI21ExplicitSpec_ImportedEvv()
+template<> __declspec(dllimport) void funcTmpl<ExplicitSpec_Imported>();
+USE(funcTmpl<ExplicitSpec_Imported>)
+
+// MSC-DAG-FIXME: declare dllimport void @"\01??$funcTmpl@UExplicitSpec_Def_Imported@@@@YAXXZ"()
+// MO1-DAG-FIXME: define available_externally dllimport void @"\01??$funcTmpl@UExplicitSpec_Def_Imported@@@@YAXXZ"()
+#ifdef MSABI
+//template<> __declspec(dllimport) void funcTmpl<ExplicitSpec_Def_Imported>() {}
+//USE(funcTmpl<ExplicitSpec_Def_Imported>)
+#endif
+
+// MSC-DAG: declare dllimport void @"\01??$funcTmpl@UExplicitSpec_InlineDef_Imported@@@@YAXXZ"()
+// GNU-DAG: declare dllimport void @_Z8funcTmplI31ExplicitSpec_InlineDef_ImportedEvv()
+// MO1-DAG: define available_externally dllimport void @"\01??$funcTmpl@UExplicitSpec_InlineDef_Imported@@@@YAXXZ"()
+// GO1-DAG: define available_externally dllimport void @_Z8funcTmplI31ExplicitSpec_InlineDef_ImportedEvv()
+template<> __declspec(dllimport) inline void funcTmpl<ExplicitSpec_InlineDef_Imported>() {}
+USE(funcTmpl<ExplicitSpec_InlineDef_Imported>)
+
+
+
+//===----------------------------------------------------------------------===//
+// Classes
+//===----------------------------------------------------------------------===//
+
+struct __declspec(dllimport) T {
+ void a() {}
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?a@T@@QAEXXZ"
+
+ static int b;
+ // MO1-DAG: @"\01?b@T@@2HA" = external dllimport global i32
+
+ T& operator=(T&) = default;
+ // MO1-DAG: define available_externally dllimport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.T* @"\01??4T@@QAEAAU0@AAU0@@Z"
+
+ T& operator=(T&&) = default;
+ // Note: Don't mark inline move operators dllimport because current MSVC versions don't export them.
+ // MO1-DAG: define linkonce_odr x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.T* @"\01??4T@@QAEAAU0@$$QAU0@@Z"
+};
+USEMEMFUNC(T, a)
+USEVAR(T::b)
+USECOPYASSIGN(T)
+USEMOVEASSIGN(T)
+
+template <typename T> struct __declspec(dllimport) U { void foo() {} };
+// MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01?foo@?$U@H@@QAEXXZ"
+struct __declspec(dllimport) V : public U<int> { };
+USEMEMFUNC(V, foo)
+
+struct __declspec(dllimport) W { virtual void foo() {} };
+USECLASS(W)
+// vftable:
+// MO1-DAG: @"\01??_7W@@6B@" = available_externally dllimport unnamed_addr constant [1 x i8*] [i8* bitcast (void (%struct.W*)* @"\01?foo@W@@UAEXXZ" to i8*)]
+// GO1-DAG: @_ZTV1W = available_externally dllimport unnamed_addr constant [3 x i8*] [i8* null, i8* null, i8* bitcast (void (%struct.W*)* @_ZN1W3fooEv to i8*)]
+
+struct __declspec(dllimport) KeyFuncClass {
+ constexpr KeyFuncClass() {}
+ virtual void foo();
+};
+constexpr KeyFuncClass keyFuncClassVar;
+// G32-DAG: @_ZTV12KeyFuncClass = external dllimport unnamed_addr constant [3 x i8*]
+
+struct __declspec(dllimport) X : public virtual W {};
+USECLASS(X)
+// vbtable:
+// MO1-DAG: @"\01??_8X@@7B@" = available_externally dllimport unnamed_addr constant [2 x i32] [i32 0, i32 4]
+
+struct __declspec(dllimport) Y {
+ int x;
+};
+
+struct __declspec(dllimport) Z { virtual ~Z() {} };
+USECLASS(Z)
+// User-defined dtor:
+// MO1-DAG: define available_externally dllimport x86_thiscallcc void @"\01??1Z@@UAE@XZ"
+
+namespace DontUseDtorAlias {
+ struct __declspec(dllimport) A { ~A(); };
+ struct __declspec(dllimport) B : A { ~B(); };
+ inline A::~A() { }
+ inline B::~B() { }
+ // Emit a real definition of B's constructor; don't alias it to A's.
+ // MO1-DAG: available_externally dllimport x86_thiscallcc void @"\01??1B@DontUseDtorAlias@@QAE@XZ"
+ USECLASS(B)
+}
+
+namespace Vtordisp {
+ // Don't dllimport the vtordisp.
+ // MO1-DAG: define linkonce_odr x86_thiscallcc void @"\01?f@?$C@D@Vtordisp@@$4PPPPPPPM@A@AEXXZ"
+
+ class Base {
+ virtual void f() {}
+ };
+ template <typename T>
+ class __declspec(dllimport) C : virtual public Base {
+ public:
+ C() {}
+ virtual void f() {}
+ };
+ template class C<char>;
+}
+
+namespace ClassTemplateStaticDef {
+ // Regular template static field:
+ template <typename T> struct __declspec(dllimport) S {
+ static int x;
+ };
+ template <typename T> int S<T>::x;
+ // MSC-DAG: @"\01?x@?$S@H@ClassTemplateStaticDef@@2HA" = available_externally dllimport global i32 0
+ int f() { return S<int>::x; }
+
+ // Partial class template specialization static field:
+ template <typename A> struct T;
+ template <typename A> struct __declspec(dllimport) T<A*> {
+ static int x;
+ };
+ template <typename A> int T<A*>::x;
+ // GNU-DAG: @_ZN22ClassTemplateStaticDef1TIPvE1xE = available_externally dllimport global i32 0
+ int g() { return T<void*>::x; }
+}
+
+namespace PR19933 {
+// Don't dynamically initialize dllimport vars.
+// MSC2-NOT: @llvm.global_ctors
+// GNU2-NOT: @llvm.global_ctors
+
+ struct NonPOD { NonPOD(); };
+ template <typename T> struct A { static NonPOD x; };
+ template <typename T> NonPOD A<T>::x;
+ template struct __declspec(dllimport) A<int>;
+ // MSC-DAG: @"\01?x@?$A@H@PR19933@@2UNonPOD@2@A" = available_externally dllimport global %"struct.PR19933::NonPOD" zeroinitializer
+
+ int f();
+ template <typename T> struct B { static int x; };
+ template <typename T> int B<T>::x = f();
+ template struct __declspec(dllimport) B<int>;
+ // MSC-DAG: @"\01?x@?$B@H@PR19933@@2HA" = available_externally dllimport global i32 0
+
+ constexpr int g() { return 42; }
+ template <typename T> struct C { static int x; };
+ template <typename T> int C<T>::x = g();
+ template struct __declspec(dllimport) C<int>;
+ // MSC-DAG: @"\01?x@?$C@H@PR19933@@2HA" = available_externally dllimport global i32 42
+
+ template <int I> struct D { static int x, y; };
+ template <int I> int D<I>::x = I + 1;
+ template <int I> int D<I>::y = I + f();
+ template struct __declspec(dllimport) D<42>;
+ // MSC-DAG: @"\01?x@?$D@$0CK@@PR19933@@2HA" = available_externally dllimport global i32 43
+ // MSC-DAG: @"\01?y@?$D@$0CK@@PR19933@@2HA" = available_externally dllimport global i32 0
+}
+
+// MS ignores DLL attributes on partial specializations.
+template <typename T> struct PartiallySpecializedClassTemplate {};
+template <typename T> struct __declspec(dllimport) PartiallySpecializedClassTemplate<T*> { void f() {} };
+USEMEMFUNC(PartiallySpecializedClassTemplate<void*>, f);
+// M32-DAG: define linkonce_odr x86_thiscallcc void @"\01?f@?$PartiallySpecializedClassTemplate@PAX@@QAEXXZ"
+// G32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @_ZN33PartiallySpecializedClassTemplateIPvE1fEv
+
+template <typename T> struct ExplicitlySpecializedClassTemplate {};
+template <> struct __declspec(dllimport) ExplicitlySpecializedClassTemplate<void*> { void f() {} };
+USEMEMFUNC(ExplicitlySpecializedClassTemplate<void*>, f);
+// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?f@?$ExplicitlySpecializedClassTemplate@PAX@@QAEXXZ"
+// G32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @_ZN34ExplicitlySpecializedClassTemplateIPvE1fEv
+
+//===----------------------------------------------------------------------===//
+// Classes with template base classes
+//===----------------------------------------------------------------------===//
+
+template <typename T> struct ClassTemplate { void func() {} };
+template <typename T> struct __declspec(dllexport) ExportedClassTemplate { void func() {} };
+template <typename T> struct __declspec(dllimport) ImportedClassTemplate { void func() {} };
+
+template <typename T> struct ExplicitlySpecializedTemplate { void func() {} };
+template <> struct ExplicitlySpecializedTemplate<int> { void func() {} };
+template <typename T> struct ExplicitlyExportSpecializedTemplate { void func() {} };
+template <> struct __declspec(dllexport) ExplicitlyExportSpecializedTemplate<int> { void func() {} };
+template <typename T> struct ExplicitlyImportSpecializedTemplate { void func() {} };
+template <> struct __declspec(dllimport) ExplicitlyImportSpecializedTemplate<int> { void func() {} };
+
+template <typename T> struct ExplicitlyInstantiatedTemplate { void func() {} };
+template struct ExplicitlyInstantiatedTemplate<int>;
+template <typename T> struct ExplicitlyExportInstantiatedTemplate { void func() {} };
+template struct __declspec(dllexport) ExplicitlyExportInstantiatedTemplate<int>;
+template <typename T> struct ExplicitlyImportInstantiatedTemplate { void func() {} };
+template struct __declspec(dllimport) ExplicitlyImportInstantiatedTemplate<int>;
+
+
+// MS: ClassTemplate<int> gets imported.
+struct __declspec(dllimport) DerivedFromTemplate : public ClassTemplate<int> {};
+USEMEMFUNC(ClassTemplate<int>, func)
+// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?func@?$ClassTemplate@H@@QAEXXZ"
+// G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ClassTemplateIiE4funcEv
+
+// ImportedTemplate is explicitly imported.
+struct __declspec(dllimport) DerivedFromImportedTemplate : public ImportedClassTemplate<int> {};
+USEMEMFUNC(ImportedClassTemplate<int>, func)
+// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?func@?$ImportedClassTemplate@H@@QAEXXZ"
+// G32-DAG: declare dllimport x86_thiscallcc void @_ZN21ImportedClassTemplateIiE4funcEv
+
+// ExportedTemplate is explicitly exported.
+struct __declspec(dllimport) DerivedFromExportedTemplate : public ExportedClassTemplate<int> {};
+USEMEMFUNC(ExportedClassTemplate<int>, func)
+// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?func@?$ExportedClassTemplate@H@@QAEXXZ"
+// G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN21ExportedClassTemplateIiE4funcEv
+
+// Base class already instantiated without attribute.
+struct DerivedFromTemplateD : public ClassTemplate<double> {};
+struct __declspec(dllimport) DerivedFromTemplateD2 : public ClassTemplate<double> {};
+USEMEMFUNC(ClassTemplate<double>, func)
+// M32-DAG: define linkonce_odr x86_thiscallcc void @"\01?func@?$ClassTemplate@N@@QAEXXZ"
+// G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ClassTemplateIdE4funcEv
+
+// MS: Base class already instantiated with dfferent attribute.
+struct __declspec(dllexport) DerivedFromTemplateB : public ClassTemplate<bool> {};
+struct __declspec(dllimport) DerivedFromTemplateB2 : public ClassTemplate<bool> {};
+USEMEMFUNC(ClassTemplate<bool>, func)
+// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?func@?$ClassTemplate@_N@@QAEXXZ"
+// G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ClassTemplateIbE4funcEv
+
+// Base class already specialized without dll attribute.
+struct __declspec(dllimport) DerivedFromExplicitlySpecializedTemplate : public ExplicitlySpecializedTemplate<int> {};
+USEMEMFUNC(ExplicitlySpecializedTemplate<int>, func)
+// M32-DAG: define linkonce_odr x86_thiscallcc void @"\01?func@?$ExplicitlySpecializedTemplate@H@@QAEXXZ"
+// G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN29ExplicitlySpecializedTemplateIiE4funcEv
+
+// Base class alredy specialized with export attribute.
+struct __declspec(dllimport) DerivedFromExplicitlyExportSpecializedTemplate : public ExplicitlyExportSpecializedTemplate<int> {};
+USEMEMFUNC(ExplicitlyExportSpecializedTemplate<int>, func)
+// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?func@?$ExplicitlyExportSpecializedTemplate@H@@QAEXXZ"
+// G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN35ExplicitlyExportSpecializedTemplateIiE4funcEv
+
+// Base class already specialized with import attribute.
+struct __declspec(dllimport) DerivedFromExplicitlyImportSpecializedTemplate : public ExplicitlyImportSpecializedTemplate<int> {};
+USEMEMFUNC(ExplicitlyImportSpecializedTemplate<int>, func)
+// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?func@?$ExplicitlyImportSpecializedTemplate@H@@QAEXXZ"
+// G32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @_ZN35ExplicitlyImportSpecializedTemplateIiE4funcEv
+
+// Base class already instantiated without dll attribute.
+struct __declspec(dllimport) DerivedFromExplicitlyInstantiatedTemplate : public ExplicitlyInstantiatedTemplate<int> {};
+USEMEMFUNC(ExplicitlyInstantiatedTemplate<int>, func)
+// M32-DAG: define weak_odr x86_thiscallcc void @"\01?func@?$ExplicitlyInstantiatedTemplate@H@@QAEXXZ"
+// G32-DAG: define weak_odr x86_thiscallcc void @_ZN30ExplicitlyInstantiatedTemplateIiE4funcEv
+
+// Base class already instantiated with export attribute.
+struct __declspec(dllimport) DerivedFromExplicitlyExportInstantiatedTemplate : public ExplicitlyExportInstantiatedTemplate<int> {};
+USEMEMFUNC(ExplicitlyExportInstantiatedTemplate<int>, func)
+// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?func@?$ExplicitlyExportInstantiatedTemplate@H@@QAEXXZ"
+// G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN36ExplicitlyExportInstantiatedTemplateIiE4funcEv
+
+// Base class already instantiated with import attribute.
+struct __declspec(dllimport) DerivedFromExplicitlyImportInstantiatedTemplate : public ExplicitlyImportInstantiatedTemplate<int> {};
+USEMEMFUNC(ExplicitlyImportInstantiatedTemplate<int>, func)
+// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?func@?$ExplicitlyImportInstantiatedTemplate@H@@QAEXXZ"
+// G32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @_ZN36ExplicitlyImportInstantiatedTemplateIiE4funcEv
+
+// MS: A dll attribute propagates through multiple levels of instantiation.
+template <typename T> struct TopClass { void func() {} };
+template <typename T> struct MiddleClass : public TopClass<T> { };
+struct __declspec(dllimport) BottomClass : public MiddleClass<int> { };
+USEMEMFUNC(TopClass<int>, func)
+// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?func@?$TopClass@H@@QAEXXZ"
+// G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN8TopClassIiE4funcEv
diff --git a/test/CodeGenCXX/duplicate-mangled-name.cpp b/test/CodeGenCXX/duplicate-mangled-name.cpp
new file mode 100644
index 000000000000..65bfa22ac621
--- /dev/null
+++ b/test/CodeGenCXX/duplicate-mangled-name.cpp
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm-only %s -verify
+
+// rdar://15522601
+class MyClass {
+ static void meth();
+};
+void MyClass::meth() { }
+extern "C" {
+ void _ZN7MyClass4methEv() { } // expected-error {{definition with same mangled name as another definition}}
+}
diff --git a/test/CodeGenCXX/dynamic_cast-no-rtti.cpp b/test/CodeGenCXX/dynamic_cast-no-rtti.cpp
index 0e26de5bcf8b..cde03a3f4e09 100644
--- a/test/CodeGenCXX/dynamic_cast-no-rtti.cpp
+++ b/test/CodeGenCXX/dynamic_cast-no-rtti.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm %s -verify -fno-rtti -o - | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm %s -verify -fno-rtti -triple %itanium_abi_triple -o - | FileCheck %s
// expected-no-diagnostics
struct A {
diff --git a/test/CodeGenCXX/eh.cpp b/test/CodeGenCXX/eh.cpp
index 2a61e61bb818..cb07697fb33f 100644
--- a/test/CodeGenCXX/eh.cpp
+++ b/test/CodeGenCXX/eh.cpp
@@ -34,7 +34,7 @@ void test2() {
// CHECK-NEXT: [[SELECTORVAR:%.*]] = alloca i32
// CHECK-NEXT: [[EXNOBJ:%.*]] = call i8* @__cxa_allocate_exception(i64 16)
// CHECK-NEXT: [[EXN:%.*]] = bitcast i8* [[EXNOBJ]] to [[DSTAR:%[^*]*\*]]
-// CHECK-NEXT: invoke void @_ZN7test2_DC1ERKS_([[DSTAR]] [[EXN]], [[DSTAR]] @d2)
+// CHECK-NEXT: invoke void @_ZN7test2_DC1ERKS_([[DSTAR]] [[EXN]], [[DSTAR]] dereferenceable({{[0-9]+}}) @d2)
// CHECK-NEXT: to label %[[CONT:.*]] unwind label %{{.*}}
// : [[CONT]]: (can't check this in Release-Asserts builds)
// CHECK: call void @__cxa_throw(i8* [[EXNOBJ]], i8* bitcast ({{.*}}* @_ZTI7test2_D to i8*), i8* null) [[NR]]
@@ -184,9 +184,6 @@ namespace test9 {
struct A { A(); };
- // CHECK-LABEL: define void @_ZN5test91AC1Ev(%"struct.test9::A"* %this) unnamed_addr
- // CHECK: call void @_ZN5test91AC2Ev
- // CHECK-NEXT: ret void
// CHECK-LABEL: define void @_ZN5test91AC2Ev(%"struct.test9::A"* %this) unnamed_addr
A::A() try {
@@ -199,6 +196,10 @@ namespace test9 {
// CHECK: call i8* @__cxa_begin_catch
// CHECK: invoke void @_ZN5test96opaqueEv()
// CHECK: invoke void @__cxa_rethrow()
+
+ // CHECK-LABEL: define void @_ZN5test91AC1Ev(%"struct.test9::A"* %this) unnamed_addr
+ // CHECK: call void @_ZN5test91AC2Ev
+ // CHECK-NEXT: ret void
opaque();
}
}
@@ -427,7 +428,7 @@ namespace test16 {
// CHECK-NEXT: [[T0:%.*]] = bitcast i8* [[EXN]] to [[B:%.*]]*
// CHECK-NEXT: invoke void @_ZN6test161AC1Ev([[A]]* [[TEMP]])
// CHECK: store i1 true, i1* [[TEMP_ACTIVE]]
- // CHECK-NEXT: invoke void @_ZN6test161BC1ERKNS_1AE([[B]]* [[T0]], [[A]]* [[TEMP]])
+ // CHECK-NEXT: invoke void @_ZN6test161BC1ERKNS_1AE([[B]]* [[T0]], [[A]]* dereferenceable({{[0-9]+}}) [[TEMP]])
// CHECK: store i1 false, i1* [[EXN_ACTIVE]]
// CHECK-NEXT: invoke void @__cxa_throw(i8* [[EXN]],
diff --git a/test/CodeGenCXX/elide-call-reference.cpp b/test/CodeGenCXX/elide-call-reference.cpp
index 55d30e24c102..0ce856f0c223 100644
--- a/test/CodeGenCXX/elide-call-reference.cpp
+++ b/test/CodeGenCXX/elide-call-reference.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -emit-llvm -triple %itanium_abi_triple -o - | FileCheck %s
// PR5695
struct A { A(const A&); ~A(); };
diff --git a/test/CodeGenCXX/empty-nontrivially-copyable.cpp b/test/CodeGenCXX/empty-nontrivially-copyable.cpp
index 9ee3281505ec..a0977a7e690a 100644
--- a/test/CodeGenCXX/empty-nontrivially-copyable.cpp
+++ b/test/CodeGenCXX/empty-nontrivially-copyable.cpp
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -triple armv7-apple-ios -x c++ -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple arm64-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
@@ -18,7 +19,7 @@ bool foo(Empty e) {
}
void caller(Empty &e) {
-// CHECK: @_Z6callerR5Empty(%struct.Empty* %e)
+// CHECK: @_Z6callerR5Empty(%struct.Empty* dereferenceable({{[0-9]+}}) %e)
// CHECK: call {{.*}} @_ZN5EmptyC1ERKS_(%struct.Empty* [[NEWTMP:%.*]], %struct.Empty*
// CHECK: call {{.*}} @_Z3foo5Empty(%struct.Empty* [[NEWTMP]])
foo(e);
diff --git a/test/CodeGenCXX/enable_if.cpp b/test/CodeGenCXX/enable_if.cpp
new file mode 100644
index 000000000000..00c55c774909
--- /dev/null
+++ b/test/CodeGenCXX/enable_if.cpp
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-pc-linux-gnu| FileCheck %s
+// Test itanium mangling for attribute enable_if
+
+// CHECK: _Z5test1Ua9enable_ifIXeqfL0p_Li1EEEi
+void test1(int i) __attribute__((enable_if(i == 1, ""))) {}
+
+void ext();
+// CHECK: _Z5test2Ua9enable_ifIXneadL_Z3extvELi0EEEi
+void test2(int i) __attribute__((enable_if(&ext != 0, ""))) {}
+
+// CHECK: _Z5test3Ua9enable_ifIXeqfL0p_Li1EEXeqfL0p0_Li2EEEii
+void test3(int i, int j) __attribute__((enable_if(i == 1, ""), enable_if(j == 2, ""))) {}
+
+// CHECK: _ZN5test4IdE1fEUa9enable_ifIXeqfL0p_Li1EEXeqfL0p0_Li2EEEi
+template <typename T>
+class test4 {
+ virtual void f(int i, int j) __attribute__((enable_if(i == 1, ""))) __attribute__((enable_if(j == 2, "")));
+};
+
+template class test4<double>;
diff --git a/test/CodeGenCXX/exceptions-no-rtti.cpp b/test/CodeGenCXX/exceptions-no-rtti.cpp
index 902d6ac2973a..e1ef4f1ddad7 100644
--- a/test/CodeGenCXX/exceptions-no-rtti.cpp
+++ b/test/CodeGenCXX/exceptions-no-rtti.cpp
@@ -1,10 +1,10 @@
// RUN: %clang_cc1 -fno-rtti -fcxx-exceptions -fexceptions %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s
-// CHECK: @_ZTIN5test11AE = linkonce_odr unnamed_addr constant
-// CHECK: @_ZTIN5test11BE = linkonce_odr unnamed_addr constant
-// CHECK: @_ZTIN5test11CE = linkonce_odr unnamed_addr constant
-// CHECK: @_ZTIN5test11DE = linkonce_odr unnamed_addr constant
-// CHECK: @_ZTIPN5test11DE = linkonce_odr unnamed_addr constant {{.*}} @_ZTIN5test11DE
+// CHECK: @_ZTIN5test11AE = linkonce_odr constant
+// CHECK: @_ZTIN5test11BE = linkonce_odr constant
+// CHECK: @_ZTIN5test11CE = linkonce_odr constant
+// CHECK: @_ZTIN5test11DE = linkonce_odr constant
+// CHECK: @_ZTIPN5test11DE = linkonce_odr constant {{.*}} @_ZTIN5test11DE
// PR6974: this shouldn't crash
namespace test0 {
diff --git a/test/CodeGenCXX/exceptions.cpp b/test/CodeGenCXX/exceptions.cpp
index d37e6109db4a..5016e9a794ae 100644
--- a/test/CodeGenCXX/exceptions.cpp
+++ b/test/CodeGenCXX/exceptions.cpp
@@ -279,7 +279,7 @@ namespace test5 {
// CHECK-NEXT: [[ADJ:%.*]] = call i8* @__cxa_get_exception_ptr(i8* [[EXN]])
// CHECK-NEXT: [[SRC:%.*]] = bitcast i8* [[ADJ]] to [[A_T]]*
// CHECK-NEXT: invoke void @_ZN5test51TC1Ev([[T_T]]* [[T]])
- // CHECK: invoke void @_ZN5test51AC1ERKS0_RKNS_1TE([[A_T]]* [[A]], [[A_T]]* [[SRC]], [[T_T]]* [[T]])
+ // CHECK: invoke void @_ZN5test51AC1ERKS0_RKNS_1TE([[A_T]]* [[A]], [[A_T]]* dereferenceable({{[0-9]+}}) [[SRC]], [[T_T]]* dereferenceable({{[0-9]+}}) [[T]])
// CHECK: invoke void @_ZN5test51TD1Ev([[T_T]]* [[T]])
// CHECK: call i8* @__cxa_begin_catch(i8* [[EXN]]) [[NUW]]
// CHECK-NEXT: invoke void @_ZN5test51AD1Ev([[A_T]]* [[A]])
diff --git a/test/CodeGenCXX/explicit-instantiation.cpp b/test/CodeGenCXX/explicit-instantiation.cpp
index 6a4fd822122f..5bd06784cfab 100644
--- a/test/CodeGenCXX/explicit-instantiation.cpp
+++ b/test/CodeGenCXX/explicit-instantiation.cpp
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -emit-llvm -triple i686-pc-linux-gnu -o - %s | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -triple i686-pc-linux-gnu -std=c++1y -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NO-OPT
+// RUN: %clang_cc1 -emit-llvm -triple i686-pc-linux-gnu -std=c++1y -O3 -disable-llvm-optzns -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-OPT
// This check logically is attached to 'template int S<int>::i;' below.
// CHECK: @_ZN1SIiE1iE = weak_odr global i32
@@ -16,6 +17,79 @@ Result plus<T, U, Result>::operator()(const T& t, const U& u) const {
// CHECK-LABEL: define weak_odr i32 @_ZNK4plusIillEclERKiRKl
template struct plus<int, long, long>;
+namespace EarlyInstantiation {
+ // Check that we emit definitions if we instantiate a function definition before
+ // it gets explicitly instantiatied.
+ template<typename T> struct S {
+ constexpr int constexpr_function() { return 0; }
+ auto deduced_return_type() { return 0; }
+ };
+
+ // From an implicit instantiation.
+ constexpr int a = S<char>().constexpr_function();
+ int b = S<char>().deduced_return_type();
+
+ // From an explicit instantiation declaration.
+ extern template struct S<int>;
+ constexpr int c = S<int>().constexpr_function();
+ int d = S<int>().deduced_return_type();
+
+ // CHECK: define weak_odr i32 @_ZN18EarlyInstantiation1SIcE18constexpr_functionEv(
+ // CHECK: define weak_odr i32 @_ZN18EarlyInstantiation1SIcE19deduced_return_typeEv(
+ // CHECK: define weak_odr i32 @_ZN18EarlyInstantiation1SIiE18constexpr_functionEv(
+ // CHECK: define weak_odr i32 @_ZN18EarlyInstantiation1SIiE19deduced_return_typeEv(
+ template struct S<char>;
+ template struct S<int>;
+
+ template<typename T> constexpr int constexpr_function() { return 0; }
+ template<typename T> auto deduced_return_type() { return 0; }
+
+ // From an implicit instantiation.
+ constexpr int e = constexpr_function<char>();
+ int f = deduced_return_type<char>();
+
+ // From an explicit instantiation declaration.
+ extern template int constexpr_function<int>();
+ extern template auto deduced_return_type<int>();
+ constexpr int g = constexpr_function<int>();
+ int h = deduced_return_type<int>();
+
+ // The FIXMEs below are for PR19551.
+ // CHECK: define weak_odr i32 @_ZN18EarlyInstantiation18constexpr_functionIcEEiv(
+ // FIXME: define weak_odr i32 @_ZN18EarlyInstantiation19deduced_return_typeIcEEiv(
+ // CHECK: define weak_odr i32 @_ZN18EarlyInstantiation18constexpr_functionIiEEiv(
+ // FIXME: define weak_odr i32 @_ZN18EarlyInstantiation19deduced_return_typeIiEEiv(
+ template int constexpr_function<char>();
+ // FIXME template auto deduced_return_type<char>();
+ template int constexpr_function<int>();
+ // FIXME template auto deduced_return_type<int>();
+}
+
+namespace LateInstantiation {
+ // Check that we downgrade the linkage to available_externally if we see an
+ // explicit instantiation declaration after the function template is
+ // instantiated.
+ template<typename T> struct S { constexpr int f() { return 0; } };
+ template<typename T> constexpr int f() { return 0; }
+
+ // Trigger eager instantiation of the function definitions.
+ int a, b = S<char>().f() + f<char>() + a;
+ int c, d = S<int>().f() + f<int>() + a;
+
+ // Don't allow some of those definitions to be emitted.
+ extern template struct S<int>;
+ extern template int f<int>();
+
+ // Check that we declare, define, or provide an available-externally
+ // definition as appropriate.
+ // CHECK: define linkonce_odr i32 @_ZN17LateInstantiation1SIcE1fEv(
+ // CHECK: define linkonce_odr i32 @_ZN17LateInstantiation1fIcEEiv(
+ // CHECK-NO-OPT: declare i32 @_ZN17LateInstantiation1SIiE1fEv(
+ // CHECK-NO-OPT: declare i32 @_ZN17LateInstantiation1fIiEEiv(
+ // CHECK-OPT: define available_externally i32 @_ZN17LateInstantiation1SIiE1fEv(
+ // CHECK-OPT: define available_externally i32 @_ZN17LateInstantiation1fIiEEiv(
+}
+
// Check that we emit definitions from explicit instantiations even when they
// occur prior to the definition itself.
template <typename T> struct S {
diff --git a/test/CodeGenCXX/extern-c.cpp b/test/CodeGenCXX/extern-c.cpp
index 5899b9348c5a..fefb216ea1c0 100644
--- a/test/CodeGenCXX/extern-c.cpp
+++ b/test/CodeGenCXX/extern-c.cpp
@@ -1,18 +1,21 @@
-// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck %s
namespace foo {
-// CHECK-NOT: @a = global i32
+// CHECK-NOT: @a = global
extern "C" int a;
-// CHECK-NOT: @_ZN3foo1bE = global i32
+// CHECK-NOT: @_ZN3foo1bE = global
extern int b;
-// CHECK: @_ZN3foo1cE = global i32
+// CHECK: @_ZN3foo1cE = global
int c = 5;
// CHECK-NOT: @_ZN3foo1dE
extern "C" struct d;
+// CHECK-NOT: should_not_appear
+extern "C++" int should_not_appear;
+
}
namespace test1 {
@@ -63,3 +66,10 @@ extern "C" {
// CHECK-NOT: @unused
// CHECK-NOT: @duplicate_internal
}
+
+namespace PR19411 {
+ struct A { void f(); };
+ extern "C" void A::f() { void g(); g(); }
+ // CHECK-LABEL: @_ZN7PR194111A1fEv(
+ // CHECK: call void @g()
+}
diff --git a/test/CodeGenCXX/fastcall.cpp b/test/CodeGenCXX/fastcall.cpp
index 0326ce53bc4a..0820324558ee 100644
--- a/test/CodeGenCXX/fastcall.cpp
+++ b/test/CodeGenCXX/fastcall.cpp
@@ -3,7 +3,7 @@
void __attribute__((fastcall)) foo1(int &y);
void bar1(int &y) {
// CHECK-LABEL: define void @_Z4bar1Ri
- // CHECK: call x86_fastcallcc void @_Z4foo1Ri(i32* inreg %
+ // CHECK: call x86_fastcallcc void @_Z4foo1Ri(i32* inreg dereferenceable({{[0-9]+}}) %
foo1(y);
}
diff --git a/test/CodeGenCXX/field-access-debug-info.cpp b/test/CodeGenCXX/field-access-debug-info.cpp
index fd899ed71e1c..aed4ee5f3a77 100644
--- a/test/CodeGenCXX/field-access-debug-info.cpp
+++ b/test/CodeGenCXX/field-access-debug-info.cpp
@@ -1,8 +1,7 @@
-// RUN: %clang_cc1 -g -S -masm-verbose -o - %s | FileCheck %s
+// RUN: %clang -g -S -emit-llvm %s -o - | FileCheck %s
-// CHECK: abbrev_begin:
-// CHECK: DW_AT_accessibility
-// CHECK-NEXT: DW_FORM_data1
+// CHECK: [ DW_TAG_member ] [p] [{{[^]]*}}] [from int]
+// CHECK: [ DW_TAG_member ] [pr] [{{[^]]*}}] [private] [from int]
class A {
public:
diff --git a/test/CodeGenCXX/flatten.cpp b/test/CodeGenCXX/flatten.cpp
new file mode 100644
index 000000000000..9e0f67f78984
--- /dev/null
+++ b/test/CodeGenCXX/flatten.cpp
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -triple=x86_64-linux-gnu -std=c++11 %s -emit-llvm -o - | FileCheck %s
+
+void f(void) {}
+
+[[gnu::flatten]]
+// CHECK: define void @_Z1gv()
+void g(void) {
+ // CHECK-NOT: call {{.*}} @_Z1fv
+ f();
+}
diff --git a/test/CodeGenCXX/funcsig.cpp b/test/CodeGenCXX/funcsig.cpp
new file mode 100644
index 000000000000..684a796c1905
--- /dev/null
+++ b/test/CodeGenCXX/funcsig.cpp
@@ -0,0 +1,29 @@
+// RUN: %clang_cc1 -std=c++11 -triple i686-pc-win32 %s -fms-extensions -fno-rtti -emit-llvm -o - | FileCheck %s
+
+// Similar to predefined-expr.cpp, but not as exhaustive, since it's basically
+// equivalent to __PRETTY_FUNCTION__.
+
+extern "C" int printf(const char *, ...);
+
+void freeFunc(int *, char) {
+ printf("__FUNCSIG__ %s\n\n", __FUNCSIG__);
+}
+// CHECK: private unnamed_addr constant [{{.*}} x i8] c"void __cdecl freeFunc(int *, char)\00"
+
+struct TopLevelClass {
+ void topLevelMethod(int *, char);
+};
+void TopLevelClass::topLevelMethod(int *, char) {
+ printf("__FUNCSIG__ %s\n\n", __FUNCSIG__);
+}
+// CHECK: private unnamed_addr constant [{{.*}} x i8] c"void __thiscall TopLevelClass::topLevelMethod(int *, char)\00"
+
+namespace NS {
+struct NamespacedClass {
+ void namespacedMethod(int *, char);
+};
+void NamespacedClass::namespacedMethod(int *, char) {
+ printf("__FUNCSIG__ %s\n\n", __FUNCSIG__);
+}
+// CHECK: private unnamed_addr constant [{{.*}} x i8] c"void __thiscall NS::NamespacedClass::namespacedMethod(int *, char)\00"
+}
diff --git a/test/CodeGenCXX/function-template-explicit-specialization.cpp b/test/CodeGenCXX/function-template-explicit-specialization.cpp
index 5d26dcd61cf0..8ff065569757 100644
--- a/test/CodeGenCXX/function-template-explicit-specialization.cpp
+++ b/test/CodeGenCXX/function-template-explicit-specialization.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple %s -o - | FileCheck %s
template<typename T> void a(T);
template<> void a(int) {}
diff --git a/test/CodeGenCXX/function-template-specialization.cpp b/test/CodeGenCXX/function-template-specialization.cpp
index 4a79fb1d6747..eb099df14d00 100644
--- a/test/CodeGenCXX/function-template-specialization.cpp
+++ b/test/CodeGenCXX/function-template-specialization.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple %s -o - | FileCheck %s
template<typename T, typename U>
T* next(T* ptr, const U& diff);
diff --git a/test/CodeGenCXX/global-array-destruction.cpp b/test/CodeGenCXX/global-array-destruction.cpp
index 6ebc13953f67..0397851e0d92 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 ({{.*}}* getelementptr inbounds ([2 x [3 x {{.*}}]]* @_ZGR1u, i32 0, i32 0, i32 0), i64 6)
+// 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: icmp eq {{.*}} @_ZGR1u_
// CHECK: br i1 {{.*}}
diff --git a/test/CodeGenCXX/global-init.cpp b/test/CodeGenCXX/global-init.cpp
index 69631c278905..9c5b03a92845 100644
--- a/test/CodeGenCXX/global-init.cpp
+++ b/test/CodeGenCXX/global-init.cpp
@@ -12,7 +12,7 @@ struct C { void *field; };
struct D { ~D(); };
-// CHECK: @__dso_handle = external unnamed_addr global i8
+// CHECK: @__dso_handle = external global i8
// CHECK: @c = global %struct.C zeroinitializer, align 8
// It's okay if we ever implement the IR-generation optimization to remove this.
@@ -195,11 +195,11 @@ namespace test7 {
// CHECK-NEXT: sub
// CHECK-NEXT: store i32 {{.*}}, i32* @_ZN5test1L1yE
-// CHECK: define internal void @_GLOBAL__I_a() section "__TEXT,__StaticInit,regular,pure_instructions" {
+// CHECK: define internal void @_GLOBAL__sub_I_global_init.cpp() section "__TEXT,__StaticInit,regular,pure_instructions" {
// CHECK: call void [[TEST1_Y_INIT]]
// CHECK: call void [[TEST1_Z_INIT]]
// rdar://problem/8090834: this should be nounwind
-// CHECK-NOEXC: define internal void @_GLOBAL__I_a() [[NUW:#[0-9]+]] section "__TEXT,__StaticInit,regular,pure_instructions" {
+// CHECK-NOEXC: define internal void @_GLOBAL__sub_I_global_init.cpp() [[NUW:#[0-9]+]] section "__TEXT,__StaticInit,regular,pure_instructions" {
// CHECK-NOEXC: attributes [[NUW]] = { nounwind }
diff --git a/test/CodeGenCXX/global-llvm-constant.cpp b/test/CodeGenCXX/global-llvm-constant.cpp
index 2bd43b99a5d9..55933eecfc3e 100644
--- a/test/CodeGenCXX/global-llvm-constant.cpp
+++ b/test/CodeGenCXX/global-llvm-constant.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -o - %s | FileCheck %s
struct A {
A() { x = 10; }
diff --git a/test/CodeGenCXX/globalinit-loc.cpp b/test/CodeGenCXX/globalinit-loc.cpp
new file mode 100644
index 000000000000..eb39aec94d48
--- /dev/null
+++ b/test/CodeGenCXX/globalinit-loc.cpp
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -emit-llvm -g %s -o - | FileCheck %s
+// rdar://problem/14985269.
+//
+// Verify that the global init helper function does not get associated
+// with any source location.
+//
+// CHECK: define internal void @_GLOBAL__sub_I_globalinit_loc.cpp
+// CHECK: !dbg ![[DBG:.*]]
+// CHECK: "_GLOBAL__sub_I_globalinit_loc.cpp", i32 0, {{.*}}, i32 0} ; [ DW_TAG_subprogram ] [line 0] [local] [def]
+// CHECK: ![[DBG]] = metadata !{i32 0, i32 0,
+# 99 "someheader.h"
+class A {
+public:
+ A();
+ int foo() { return 0; }
+};
+# 5 "main.cpp"
+A a;
+
+int f() {
+ return a.foo();
+}
+
diff --git a/test/CodeGenCXX/goto.cpp b/test/CodeGenCXX/goto.cpp
index 904f95fb22be..c1a0eeccf811 100644
--- a/test/CodeGenCXX/goto.cpp
+++ b/test/CodeGenCXX/goto.cpp
@@ -22,7 +22,7 @@ namespace test0 {
// CHECK: store i1 true, i1* [[CLEANUPACTIVE]]
// CHECK: [[NEWCAST:%.*]] = bitcast i8* [[NEW]] to [[V]]*
// CHECK-NEXT: invoke void @_ZN5test01AC1Ev([[A]]* [[TMP]])
- // CHECK: invoke void @_ZN5test01VC1ERKNS_1AE([[V]]* [[NEWCAST]], [[A]]* [[TMP]])
+ // CHECK: invoke void @_ZN5test01VC1ERKNS_1AE([[V]]* [[NEWCAST]], [[A]]* dereferenceable({{[0-9]+}}) [[TMP]])
// CHECK: store i1 false, i1* [[CLEANUPACTIVE]]
// CHECK-NEXT: invoke void @_ZN5test01AD1Ev([[A]]* [[TMP]])
A y;
diff --git a/test/CodeGenCXX/implicit-copy-assign-operator.cpp b/test/CodeGenCXX/implicit-copy-assign-operator.cpp
index 267402122f82..fded035822ab 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-LABEL: define linkonce_odr %struct.D* @_ZN1DaSERS_
+// CHECK-LABEL: define linkonce_odr dereferenceable({{[0-9]+}}) %struct.D* @_ZN1DaSERS_
// CHECK: {{call.*_ZN1AaSERS_}}
// CHECK: {{call.*_ZN1BaSERS_}}
// CHECK: {{call.*_ZN1CaSERKS_}}
@@ -53,4 +53,3 @@ void test_D(D d1, D d2) {
// CHECK: call void @_ZN11CopyByValueC1ERKS_
// CHECK: {{call.*_ZN11CopyByValueaSES_}}
// CHECK: ret
-
diff --git a/test/CodeGenCXX/implicit-copy-constructor.cpp b/test/CodeGenCXX/implicit-copy-constructor.cpp
index bb04318e7307..d0224131c4da 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-LABEL: define linkonce_odr void @_ZN1DC1ERS_(%struct.D* %this, %struct.D*) unnamed_addr
+// CHECK-LABEL: define linkonce_odr void @_ZN1DC1ERS_(%struct.D* %this, %struct.D* dereferenceable({{[0-9]+}})) 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 bf6a14150892..c3c49c3218b3 100644
--- a/test/CodeGenCXX/implicit-instantiation-1.cpp
+++ b/test/CodeGenCXX/implicit-instantiation-1.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm %s -o %t
+// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple %s -o %t
template<typename T>
struct X {
diff --git a/test/CodeGenCXX/inheriting-constructor.cpp b/test/CodeGenCXX/inheriting-constructor.cpp
index c99a20c730e4..9394137e6414 100644
--- a/test/CodeGenCXX/inheriting-constructor.cpp
+++ b/test/CodeGenCXX/inheriting-constructor.cpp
@@ -11,9 +11,9 @@ struct C { template<typename T> C(T); };
struct D : C { using C::C; };
D d(123);
-// CHECK-LABEL: define void @_ZN1BD0Ev
-// CHECK-LABEL: define void @_ZN1BD1Ev
// CHECK-LABEL: define void @_ZN1BD2Ev
+// CHECK-LABEL: define void @_ZN1BD1Ev
+// CHECK-LABEL: define void @_ZN1BD0Ev
// CHECK-LABEL: define linkonce_odr void @_ZN1BC1Ei(
// CHECK: call void @_ZN1BC2Ei(
diff --git a/test/CodeGenCXX/init-priority-attr.cpp b/test/CodeGenCXX/init-priority-attr.cpp
index ef9343ceade9..ff155d07ca2e 100644
--- a/test/CodeGenCXX/init-priority-attr.cpp
+++ b/test/CodeGenCXX/init-priority-attr.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s
-// PR
+// RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -O2 -emit-llvm -o - | FileCheck %s
+// PR11480
void foo(int);
@@ -27,18 +27,24 @@ public:
A C::a = A();
-// CHECK: @llvm.global_ctors = appending global [3 x { i32, void ()* }] [{ i32, void ()* } { i32 200, void ()* @_GLOBAL__I_000200 }, { i32, void ()* } { i32 300, void ()* @_GLOBAL__I_000300 }, { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I_a }]
+// CHECK: @llvm.global_ctors = appending global [3 x { i32, void ()*, i8* }]
+// CHECK: [{ i32, void ()*, i8* } { i32 200, void ()* @_GLOBAL__I_000200, i8* null },
+// CHECK: { i32, void ()*, i8* } { i32 300, void ()* @_GLOBAL__I_000300, i8* null },
+// CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__sub_I_init_priority_attr.cpp, i8* null }]
// CHECK: _GLOBAL__I_000200()
-// CHECK_NEXT: _Z3fooi(i32 3)
+// CHECK: _Z3fooi(i32 3)
+// CHECK-NEXT: ret void
// CHECK: _GLOBAL__I_000300()
-// CHECK_NEXT: _Z3fooi(i32 2)
-// CHECK_NEXT: _Z3fooi(i32 1)
-
-// CHECK: _GLOBAL__I_a()
-// CHECK_NEXT: _Z3fooi(i32 1)
-// CHECK_NEXT: _Z3fooi(i32 4)
+// CHECK: _Z3fooi(i32 2)
+// CHECK-NEXT: _Z3fooi(i32 1)
+// CHECK-NEXT: ret void
+
+// CHECK: _GLOBAL__sub_I_init_priority_attr.cpp()
+// CHECK: _Z3fooi(i32 1)
+// CHECK-NEXT: _Z3fooi(i32 4)
+// CHECK-NEXT: ret void
C c;
A1 a1 __attribute__((init_priority (300)));
diff --git a/test/CodeGenCXX/inline-functions.cpp b/test/CodeGenCXX/inline-functions.cpp
index 9f8e536a3b0c..622cfa9536f3 100644
--- a/test/CodeGenCXX/inline-functions.cpp
+++ b/test/CodeGenCXX/inline-functions.cpp
@@ -1,11 +1,12 @@
-// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -std=c++11 -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s --check-prefix=CHECK --check-prefix=NORMAL
+// RUN: %clang_cc1 %s -std=c++11 -fms-compatibility -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s --check-prefix=CHECK --check-prefix=MSVCCOMPAT
// CHECK: ; ModuleID
struct A {
inline void f();
};
-// CHECK-NOT-LABEL: define void @_ZN1A1fEv
+// CHECK-NOT: define void @_ZN1A1fEv
void A::f() { }
template<typename> struct B { };
@@ -67,3 +68,56 @@ namespace test2 {
}
// CHECK-LABEL: define linkonce_odr void @_ZN5test21fERKNS_1AE
}
+
+// MSVCCOMPAT-LABEL: define weak_odr void @_Z17ExternAndInlineFnv
+// NORMAL-NOT: _Z17ExternAndInlineFnv
+extern inline void ExternAndInlineFn() {}
+
+// MSVCCOMPAT-LABEL: define weak_odr void @_Z18InlineThenExternFnv
+// NORMAL-NOT: _Z18InlineThenExternFnv
+inline void InlineThenExternFn() {}
+extern void InlineThenExternFn();
+
+// CHECK-LABEL: define void @_Z18ExternThenInlineFnv
+extern void ExternThenInlineFn() {}
+
+// MSVCCOMPAT-LABEL: define weak_odr void @_Z25ExternThenInlineThenDefFnv
+// NORMAL-NOT: _Z25ExternThenInlineThenDefFnv
+extern void ExternThenInlineThenDefFn();
+inline void ExternThenInlineThenDefFn();
+void ExternThenInlineThenDefFn() {}
+
+// MSVCCOMPAT-LABEL: define weak_odr void @_Z25InlineThenExternThenDefFnv
+// NORMAL-NOT: _Z25InlineThenExternThenDefFnv
+inline void InlineThenExternThenDefFn();
+extern void InlineThenExternThenDefFn();
+void InlineThenExternThenDefFn() {}
+
+// MSVCCOMPAT-LABEL: define weak_odr i32 @_Z20ExternAndConstexprFnv
+// NORMAL-NOT: _Z17ExternAndConstexprFnv
+extern constexpr int ExternAndConstexprFn() { return 0; }
+
+// CHECK-NOT: _Z11ConstexprFnv
+constexpr int ConstexprFn() { return 0; }
+
+template <typename T>
+extern inline void ExternInlineOnPrimaryTemplate(T);
+
+// CHECK-LABEL: define void @_Z29ExternInlineOnPrimaryTemplateIiEvT_
+template <>
+void ExternInlineOnPrimaryTemplate(int) {}
+
+template <typename T>
+extern inline void ExternInlineOnPrimaryTemplateAndSpecialization(T);
+
+// MSVCCOMPAT-LABEL: define weak_odr void @_Z46ExternInlineOnPrimaryTemplateAndSpecializationIiEvT_
+// NORMAL-NOT: _Z46ExternInlineOnPrimaryTemplateAndSpecializationIiEvT_
+template <>
+extern inline void ExternInlineOnPrimaryTemplateAndSpecialization(int) {}
+
+struct TypeWithInlineMethods {
+ // CHECK-NOT: _ZN21TypeWithInlineMethods9StaticFunEv
+ static void StaticFun() {}
+ // CHECK-NOT: _ZN21TypeWithInlineMethods12NonStaticFunEv
+ void NonStaticFun() { StaticFun(); }
+};
diff --git a/test/CodeGenCXX/instrument-functions.cpp b/test/CodeGenCXX/instrument-functions.cpp
index 253e09610893..587b6389c9a9 100644
--- a/test/CodeGenCXX/instrument-functions.cpp
+++ b/test/CodeGenCXX/instrument-functions.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -S -emit-llvm -o - %s -finstrument-functions | FileCheck %s
+// RUN: %clang_cc1 -S -emit-llvm -triple %itanium_abi_triple -o - %s -finstrument-functions | FileCheck %s
// CHECK: @_Z5test1i
int test1(int x) {
diff --git a/test/CodeGenCXX/int64_uint64.cpp b/test/CodeGenCXX/int64_uint64.cpp
new file mode 100644
index 000000000000..aad6ea0b741d
--- /dev/null
+++ b/test/CodeGenCXX/int64_uint64.cpp
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -triple arm-linux-guneabi \
+// RUN: -target-cpu cortex-a8 \
+// RUN: -emit-llvm -w -O1 -o - %s | FileCheck --check-prefix=CHECK-ARM %s
+
+// RUN: %clang_cc1 -triple arm64-linux-gnueabi \
+// RUN: -target-feature +neon \
+// RUN: -emit-llvm -w -O1 -o - %s | FileCheck --check-prefix=CHECK-AARCH64 %s
+
+// Test if int64_t and uint64_t can be correctly mangled.
+
+#include "arm_neon.h"
+// CHECK-ARM: f1x(
+// CHECK-AARCH64: f1l(
+void f1(int64_t a) {}
+// CHECK-ARM: f2y(
+// CHECK-AARCH64: f2m(
+void f2(uint64_t a) {}
+// CHECK-ARM: f3Px(
+// CHECK-AARCH64: f3Pl(
+void f3(int64_t *ptr) {}
+// CHECK-ARM: f4Py(
+// CHECK-AARCH64: f4Pm(
+void f4(uint64_t *ptr) {}
diff --git a/test/CodeGenCXX/internal-linkage.cpp b/test/CodeGenCXX/internal-linkage.cpp
index 56cb81030922..77b16704dd17 100644
--- a/test/CodeGenCXX/internal-linkage.cpp
+++ b/test/CodeGenCXX/internal-linkage.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -o - %s | FileCheck %s
struct Global { Global(); };
template<typename T> struct X { X() {} };
diff --git a/test/CodeGenCXX/linetable-cleanup.cpp b/test/CodeGenCXX/linetable-cleanup.cpp
index 96b857225267..ce7f2c674ba5 100644
--- a/test/CodeGenCXX/linetable-cleanup.cpp
+++ b/test/CodeGenCXX/linetable-cleanup.cpp
@@ -46,12 +46,14 @@ void bar()
void baz()
{
if (!foo())
- // CHECK: {{.*}} = metadata !{i32 [[@LINE+1]], i32 0, metadata !{{.*}}, null}
+ // CHECK: ![[SCOPE1:.*]] = metadata !{{{.*}}, i32 [[@LINE-1]], {{.*}}} ; [ DW_TAG_lexical_block ]
+ // CHECK: {{.*}} = metadata !{i32 [[@LINE+1]], i32 0, metadata ![[SCOPE1]], null}
return;
if (foo()) {
// no cleanup
- // CHECK: {{.*}} = metadata !{i32 [[@LINE+1]], i32 0, metadata !{{.*}}, null}
+ // CHECK: {{.*}} = metadata !{i32 [[@LINE+2]], i32 0, metadata ![[SCOPE2:.*]], null}
+ // CHECK: ![[SCOPE2]] = metadata !{{{.*}}, i32 [[@LINE-3]], {{.*}}} ; [ DW_TAG_lexical_block ]
return;
}
// CHECK: ![[RETBAZ]] = metadata !{i32 [[@LINE+1]], i32 0, metadata !{{.*}}, null}
diff --git a/test/CodeGenCXX/linetable-eh.cpp b/test/CodeGenCXX/linetable-eh.cpp
new file mode 100644
index 000000000000..14a5067cf3ea
--- /dev/null
+++ b/test/CodeGenCXX/linetable-eh.cpp
@@ -0,0 +1,44 @@
+// RUN: %clang_cc1 -emit-llvm -g -triple x86_64-apple-macosx10.9.0 -munwind-tables -std=c++11 -fcxx-exceptions -fexceptions %s -o - | FileCheck %s
+
+// Test that emitting a landing pad does not affect the line table
+// entries for the code that triggered it.
+
+// CHECK: call void @llvm.dbg.declare
+// CHECK: call void @llvm.dbg.declare(metadata !{{{.*}}}, metadata ![[CURRENT_ADDR:.*]]), !dbg ![[DBG1:.*]]
+// CHECK: unwind label %{{.*}}, !dbg ![[DBG1]]
+// CHECK: store i64 %{{.*}}, i64* %current_address, align 8, !dbg ![[DBG4:.*]]
+// CHECK-NEXT: call void @llvm.dbg.declare(metadata !{{{.*}}}, metadata ![[FOUND_IT:.*]]), !dbg ![[DBG2:.*]]
+// CHECK: = landingpad
+// CHECK-NEXT: cleanup, !dbg ![[DBG3:.*]]
+// CHECK-DAG: ![[CURRENT_ADDR]] = {{.*}} [current_address]
+// CHECK-DAG: ![[FOUND_IT]] = {{.*}} [found_it]
+// CHECK-DAG: ![[DBG1]] = metadata !{i32 256,
+// CHECK-DAG: ![[DBG2]] = metadata !{i32 257,
+// CHECK-DAG: ![[DBG3]] = metadata !{i32 268,
+// CHECK-DAG: ![[DBG4]] = metadata !{i32 256,
+typedef unsigned long long uint64_t;
+template<class _Tp> class shared_ptr {
+public:
+ typedef _Tp element_type;
+ element_type* __ptr_;
+ ~shared_ptr();
+ element_type* operator->() const noexcept {return __ptr_;}
+};
+class Context {
+public:
+ uint64_t GetIt();
+};
+class Foo
+{
+ bool bar();
+ virtual shared_ptr<Context> GetContext () = 0;
+};
+# 253 "Foo.cpp" 3
+bool
+Foo::bar ()
+{
+ uint64_t current_address = GetContext()->GetIt();
+ bool found_it = false;
+# 267 "Foo.cpp" 3
+ return found_it;
+}
diff --git a/test/CodeGenCXX/linetable-fnbegin.cpp b/test/CodeGenCXX/linetable-fnbegin.cpp
new file mode 100644
index 000000000000..ce46306fed0d
--- /dev/null
+++ b/test/CodeGenCXX/linetable-fnbegin.cpp
@@ -0,0 +1,28 @@
+// RUN: %clang_cc1 -emit-llvm -g %s -o - | FileCheck %s
+// Test that the line table info for Foo<T>::bar() is pointing to the
+// right header file.
+// CHECK: define{{.*}}bar
+// CHECK-NOT: define
+// CHECK: ret {{.*}}, !dbg [[DBG:.*]]
+// CHECK: [[HPP:.*]] = metadata !{metadata !"./template.hpp",
+// CHECK: [[SP:.*]] = metadata !{i32 786478, metadata [[HPP]],{{.*}}[ DW_TAG_subprogram ] [line 22] [def] [bar]
+// We shouldn't need a lexical block for this function.
+// CHECK: [[DBG]] = metadata !{i32 23, i32 0, metadata [[SP]], null}
+
+
+# 1 "./template.h" 1
+template <typename T>
+class Foo {
+public:
+ int bar();
+};
+# 21 "./template.hpp"
+template <typename T>
+int Foo<T>::bar() {
+ return 23;
+}
+int main (int argc, const char * argv[])
+{
+ Foo<int> f;
+ return f.bar();
+}
diff --git a/test/CodeGenCXX/linkage.cpp b/test/CodeGenCXX/linkage.cpp
index 19f1b20773c0..60e53c6444e2 100644
--- a/test/CodeGenCXX/linkage.cpp
+++ b/test/CodeGenCXX/linkage.cpp
@@ -1,7 +1,7 @@
// 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_(
+ // CHECK-DAG: define linkonce_odr void @_ZN5test11fIZNS_1gEvE1SEEvT_(
template <typename T> void f(T) {}
inline void *g() {
struct S {
@@ -12,7 +12,7 @@ namespace test1 {
}
namespace test2 {
- // CHECK-DAG-LABEL: define internal void @_ZN5test21fIZNS_L1gEvE1SEEvT_(
+ // CHECK-DAG: define internal void @_ZN5test21fIZNS_L1gEvE1SEEvT_(
template <typename T> void f(T) {}
static inline void *g() {
struct S {
@@ -23,7 +23,7 @@ namespace test2 {
}
namespace test3 {
- // CHECK-DAG-LABEL: define internal void @_ZN5test31fIZNS_1gEvE1SEEvT_(
+ // CHECK-DAG: define internal void @_ZN5test31fIZNS_1gEvE1SEEvT_(
template <typename T> void f(T) {}
void *g() {
struct S {
@@ -34,7 +34,7 @@ namespace test3 {
}
namespace test4 {
- // CHECK-DAG-LABEL: define linkonce_odr void @_ZN5test41fIZNS_1gILi1EEEPvvE1SEEvT_(
+ // CHECK-DAG: define linkonce_odr void @_ZN5test41fIZNS_1gILi1EEEPvvE1SEEvT_(
template <typename T> void f(T) {}
template <int N> inline void *g() {
struct S {
@@ -46,7 +46,7 @@ namespace test4 {
}
namespace test5 {
- // CHECK-DAG-LABEL: define linkonce_odr void @_ZN5test51fIZNS_1gILi1EEEPvvE1SEEvT_(
+ // CHECK-DAG: define linkonce_odr void @_ZN5test51fIZNS_1gILi1EEEPvvE1SEEvT_(
template <typename T> void f(T) {}
template <int N> inline void *g() {
struct S {
@@ -58,7 +58,7 @@ namespace test5 {
}
namespace test6 {
- // CHECK-DAG-LABEL: define linkonce_odr void @_ZN5test61fIZZNS_1gEvEN1S1hEvE1TEEvv(
+ // CHECK-DAG: define linkonce_odr void @_ZN5test61fIZZNS_1gEvEN1S1hEvE1TEEvv(
template <typename T> void f() {}
inline void *g() {
@@ -76,7 +76,7 @@ namespace test6 {
}
namespace test7 {
- // CHECK-DAG-LABEL: define internal void @_ZN5test71fIZZNS_1gEvEN1S1hEvE1TEEvv(
+ // CHECK-DAG: define internal void @_ZN5test71fIZZNS_1gEvEN1S1hEvE1TEEvv(
template <typename T> void f() {}
void *g() {
@@ -94,7 +94,7 @@ namespace test7 {
}
namespace test8 {
- // CHECK-DAG-LABEL: define linkonce_odr void @_ZN5test81fIZNS_1gEvE1SEEvT_(
+ // CHECK-DAG: define linkonce_odr void @_ZN5test81fIZNS_1gEvE1SEEvT_(
template <typename T> void f(T) {}
inline void *g() {
enum S {
@@ -105,7 +105,7 @@ namespace test8 {
}
namespace test9 {
- // CHECK-DAG-LABEL: define linkonce_odr void @_ZN5test91fIPZNS_1gEvE1SEEvT_(
+ // CHECK-DAG: define linkonce_odr void @_ZN5test91fIPZNS_1gEvE1SEEvT_(
template <typename T> void f(T) {}
inline void *g() {
struct S {
@@ -116,7 +116,7 @@ namespace test9 {
}
namespace test10 {
- // CHECK-DAG-LABEL: define linkonce_odr void @_ZN6test101fIPFZNS_1gEvE1SvEEEvT_(
+ // CHECK-DAG: define linkonce_odr void @_ZN6test101fIPFZNS_1gEvE1SvEEEvT_(
template <typename T> void f(T) {}
inline void *g() {
struct S {
@@ -128,7 +128,7 @@ namespace test10 {
}
namespace test11 {
- // CHECK-DAG-LABEL: define internal void @_ZN6test111fIPFZNS_1gEvE1SPNS_12_GLOBAL__N_11IEEEEvT_(
+ // CHECK-DAG: define internal void @_ZN6test111fIPFZNS_1gEvE1SPNS_12_GLOBAL__N_11IEEEEvT_(
namespace {
struct I {
};
@@ -145,7 +145,7 @@ namespace test11 {
}
namespace test12 {
- // CHECK-DAG-LABEL: define linkonce_odr void @_ZN6test123fooIZNS_3barIZNS_3zedEvE2S2EEPvvE2S1EEvv
+ // CHECK-DAG: define linkonce_odr void @_ZN6test123fooIZNS_3barIZNS_3zedEvE2S2EEPvvE2S1EEvv
template <typename T> void foo() {}
template <typename T> inline void *bar() {
enum S1 {
@@ -161,7 +161,7 @@ namespace test12 {
}
namespace test13 {
- // CHECK-DAG-LABEL: define linkonce_odr void @_ZZN6test133fooEvEN1S3barEv(
+ // CHECK-DAG: define linkonce_odr void @_ZZN6test133fooEvEN1S3barEv(
inline void *foo() {
struct S {
static void bar() {}
@@ -172,7 +172,7 @@ namespace test13 {
}
namespace test14 {
- // CHECK-DAG-LABEL: define linkonce_odr void @_ZN6test143fooIZNS_1fEvE1SE3barILPS1_0EEEvv(
+ // CHECK-DAG: 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>; }
@@ -186,7 +186,7 @@ namespace test14 {
}
namespace test15 {
- // CHECK-DAG-LABEL: define linkonce_odr void @_ZN6test153zedIZNS_3fooIiEEPvvE3barEEvv(
+ // CHECK-DAG: define linkonce_odr void @_ZN6test153zedIZNS_3fooIiEEPvvE3barEEvv(
template <class T> void zed() {}
template <class T> void *foo() {
class bar {
@@ -197,7 +197,7 @@ namespace test15 {
}
namespace test16 {
- // CHECK-DAG-LABEL: define linkonce_odr void @_ZN6test163zedIZNS_3fooIiE3barEvE1SEEvv(
+ // CHECK-DAG: define linkonce_odr void @_ZN6test163zedIZNS_3fooIiE3barEvE1SEEvv(
template <class T> void zed() {}
template <class T> struct foo {
static void *bar();
@@ -212,7 +212,7 @@ namespace test16 {
namespace test17 {
// CHECK-DAG: @_ZZN6test173fooILi42EEEPivE3bar = linkonce_odr
- // CHECK-DAG-LABEL: define weak_odr i32* @_ZN6test173fooILi42EEEPiv(
+ // CHECK-DAG: define weak_odr i32* @_ZN6test173fooILi42EEEPiv(
template<int I>
int *foo() {
static int bar;
@@ -220,3 +220,11 @@ namespace test17 {
}
template int *foo<42>();
}
+
+// PR18408
+namespace test18 {
+ template<template<typename> class> struct A {};
+ struct B { template<typename> struct C; };
+ void f(A<B::C>) {}
+ // CHECK-DAG: define void @_ZN6test181fENS_1AINS_1B1CEEE(
+}
diff --git a/test/CodeGenCXX/mangle-abi-examples.cpp b/test/CodeGenCXX/mangle-abi-examples.cpp
index 7124078320b0..6fb82cf8da5f 100644
--- a/test/CodeGenCXX/mangle-abi-examples.cpp
+++ b/test/CodeGenCXX/mangle-abi-examples.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -emit-llvm -triple %itanium_abi_triple -o - | FileCheck %s
// CHECK: @_ZTVZ3foovEN1C1DE =
// CHECK: @_ZTVZN1A3fooEiE1B =
diff --git a/test/CodeGenCXX/mangle-address-space.cpp b/test/CodeGenCXX/mangle-address-space.cpp
index 4a4a1f3f56e9..a0b3c1aff224 100644
--- a/test/CodeGenCXX/mangle-address-space.cpp
+++ b/test/CodeGenCXX/mangle-address-space.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -o - %s | FileCheck %s
// CHECK-LABEL: define void @_Z2f0Pc
void f0(char *p) { }
diff --git a/test/CodeGenCXX/mangle-alias-template.cpp b/test/CodeGenCXX/mangle-alias-template.cpp
index b6719c545233..1dbb3eb67ad7 100644
--- a/test/CodeGenCXX/mangle-alias-template.cpp
+++ b/test/CodeGenCXX/mangle-alias-template.cpp
@@ -11,10 +11,6 @@ template<typename T> void g(T);
template<template<typename> class F> void h(F<int>);
-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-LABEL: define void @_Z1zv(
void z() {
vector<int> VI;
@@ -42,7 +38,4 @@ void z() {
Vec<Vec<int>> VVI;
g(VVI);
// CHECK: call void @_Z1gI6vectorIS0_Ii5allocIiEES1_IS3_EEEvT_(
-
- // CHECK: call void @_Z1hIJidEEv1UIDpT_ES2_
- h({}, 0, 0.0);
}
diff --git a/test/CodeGenCXX/mangle-lambdas.cpp b/test/CodeGenCXX/mangle-lambdas.cpp
index 659b437a0ef3..e8d3f1983d25 100644
--- a/test/CodeGenCXX/mangle-lambdas.cpp
+++ b/test/CodeGenCXX/mangle-lambdas.cpp
@@ -192,7 +192,7 @@ namespace PR12123 {
};
void B::h() { f(); }
}
-// CHECK-LABEL: define linkonce_odr %"struct.PR12123::A"* @_ZZN7PR121231B1fERKSt9type_infoEd_NKUlvE_clEv
+// CHECK-LABEL: define linkonce_odr dereferenceable({{[0-9]+}}) %"struct.PR12123::A"* @_ZZN7PR121231B1fERKSt9type_infoEd_NKUlvE_clEv
namespace PR12808 {
template <typename> struct B {
diff --git a/test/CodeGenCXX/mangle-local-class-names.cpp b/test/CodeGenCXX/mangle-local-class-names.cpp
index 8b950fcd1776..848e4604c4f2 100644
--- a/test/CodeGenCXX/mangle-local-class-names.cpp
+++ b/test/CodeGenCXX/mangle-local-class-names.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -emit-llvm -triple %itanium_abi_triple -o - | FileCheck %s
// CHECK: @_ZZ4FUNCvEN4SSSSC1ERKf
// CHECK: @_ZZ4FUNCvEN4SSSSC2E_0RKf
diff --git a/test/CodeGenCXX/mangle-local-class-vtables.cpp b/test/CodeGenCXX/mangle-local-class-vtables.cpp
index d9d3afe45933..078d735d8f05 100644
--- a/test/CodeGenCXX/mangle-local-class-vtables.cpp
+++ b/test/CodeGenCXX/mangle-local-class-vtables.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -emit-llvm -triple %itanium_abi_triple -o - | FileCheck %s
// CHECK: @_ZTVZN1J1KEvE1C = {{.*}} @_ZTIZN1J1KEvE1C {{.*}} @_ZZN1J1KEvENK1C1FEv
// CHECK: @_ZTIZN1J1KEvE1C = {{.*}} @_ZTSZN1J1KEvE1C
diff --git a/test/CodeGenCXX/mangle-local-classes-nested.cpp b/test/CodeGenCXX/mangle-local-classes-nested.cpp
index fafa5d4e58e6..cee541f8156a 100644
--- a/test/CodeGenCXX/mangle-local-classes-nested.cpp
+++ b/test/CodeGenCXX/mangle-local-classes-nested.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -emit-llvm -triple %itanium_abi_triple -o - | FileCheck %s
// CHECK: @_ZTVZZ1HvEN1S1IEvE1S =
diff --git a/test/CodeGenCXX/mangle-ms-abi-examples.cpp b/test/CodeGenCXX/mangle-ms-abi-examples.cpp
index d6726cab0d58..5dc9d2e71dab 100644
--- a/test/CodeGenCXX/mangle-ms-abi-examples.cpp
+++ b/test/CodeGenCXX/mangle-ms-abi-examples.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fms-extensions -fno-rtti -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s
+// RUN: %clang_cc1 -fms-extensions -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 | FileCheck %s
// CHECK: @"\01??_7D@C@?1??foo@@YAXXZ@6B@" =
// CHECK: @"\01??_7B@?1??foo@A@@QAEXH@Z@6B@" =
@@ -11,7 +11,7 @@ struct A {
B();
}
};
-void foo () {
+inline void foo () {
struct C {
struct D { virtual ~D() {} };
void bar () {
@@ -25,4 +25,6 @@ void foo () {
C::D();
C().bar();
}
-
+void call () {
+ foo();
+}
diff --git a/test/CodeGenCXX/mangle-ms-arg-qualifiers.cpp b/test/CodeGenCXX/mangle-ms-arg-qualifiers.cpp
index 50a238340e18..fae2e1ab2dfa 100644
--- a/test/CodeGenCXX/mangle-ms-arg-qualifiers.cpp
+++ b/test/CodeGenCXX/mangle-ms-arg-qualifiers.cpp
@@ -1,5 +1,5 @@
-// 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
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-pc-win32 | FileCheck -check-prefix=X64 %s
void foo(const unsigned int) {}
// CHECK: "\01?foo@@YAXI@Z"
@@ -37,6 +37,22 @@ void foo_sad(char * const volatile x) {}
// CHECK: "\01?foo_sad@@YAXSAD@Z"
// X64: "\01?foo_sad@@YAXSEAD@Z"
+void foo_piad(char * __restrict x) {}
+// CHECK: "\01?foo_piad@@YAXPIAD@Z"
+// X64: "\01?foo_piad@@YAXPEIAD@Z"
+
+void foo_qiad(char * const __restrict x) {}
+// CHECK: "\01?foo_qiad@@YAXQIAD@Z"
+// X64: "\01?foo_qiad@@YAXQEIAD@Z"
+
+void foo_riad(char * volatile __restrict x) {}
+// CHECK: "\01?foo_riad@@YAXRIAD@Z"
+// X64: "\01?foo_riad@@YAXREIAD@Z"
+
+void foo_siad(char * const volatile __restrict x) {}
+// CHECK: "\01?foo_siad@@YAXSIAD@Z"
+// X64: "\01?foo_siad@@YAXSEIAD@Z"
+
void foo_papad(char ** x) {}
// CHECK: "\01?foo_papad@@YAXPAPAD@Z"
// X64: "\01?foo_papad@@YAXPEAPEAD@Z"
@@ -238,3 +254,7 @@ void mangle_yes_backref2(fun_type *const[], ptr_to_fun_type const[]) {}
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"
+
+void mangle_yes_backref4(int *const __restrict, int *const __restrict) {}
+// CHECK: "\01?mangle_yes_backref4@@YAXQIAH0@Z"
+// X64: "\01?mangle_yes_backref4@@YAXQEIAH0@Z"
diff --git a/test/CodeGenCXX/mangle-ms-back-references-pr13207.cpp b/test/CodeGenCXX/mangle-ms-back-references-pr13207.cpp
index e10cc8e32986..5d4b6722f507 100644
--- a/test/CodeGenCXX/mangle-ms-back-references-pr13207.cpp
+++ b/test/CodeGenCXX/mangle-ms-back-references-pr13207.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 | FileCheck %s
template<class X, class Y, class Z>
class A {};
diff --git a/test/CodeGenCXX/mangle-ms-back-references.cpp b/test/CodeGenCXX/mangle-ms-back-references.cpp
index 4f1732688833..25a058a30dbe 100644
--- a/test/CodeGenCXX/mangle-ms-back-references.cpp
+++ b/test/CodeGenCXX/mangle-ms-back-references.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fms-extensions -fblocks -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s
+// RUN: %clang_cc1 -fms-extensions -fblocks -emit-llvm %s -o - -triple=i386-pc-win32 | FileCheck %s
void f1(const char* a, const char* b) {}
// CHECK: "\01?f1@@YAXPBD0@Z"
diff --git a/test/CodeGenCXX/mangle-ms-cxx11.cpp b/test/CodeGenCXX/mangle-ms-cxx11.cpp
index 6947a53c4d1e..373d2b7b957f 100644
--- a/test/CodeGenCXX/mangle-ms-cxx11.cpp
+++ b/test/CodeGenCXX/mangle-ms-cxx11.cpp
@@ -1,4 +1,7 @@
-// RUN: %clang_cc1 -std=c++11 -fms-extensions -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s
+// RUN: %clang_cc1 -std=c++11 -fms-extensions -emit-llvm %s -o - -triple=i386-pc-win32 | FileCheck %s
+
+// CHECK: "\01?DeducedType@@3HA"
+auto DeducedType = 30;
// CHECK: "\01?LRef@@YAXAAH@Z"
void LRef(int& a) { }
@@ -9,3 +12,130 @@ int RRef(int&& a) { return a; }
// CHECK: "\01?Null@@YAX$$T@Z"
namespace std { typedef decltype(__nullptr) nullptr_t; }
void Null(std::nullptr_t) {}
+
+namespace EnumMangling {
+ extern enum Enum01 { } Enum;
+ extern enum Enum02 : bool { } BoolEnum;
+ extern enum Enum03 : char { } CharEnum;
+ extern enum Enum04 : signed char { } SCharEnum;
+ extern enum Enum05 : unsigned char { } UCharEnum;
+ extern enum Enum06 : short { } SShortEnum;
+ extern enum Enum07 : unsigned short { } UShortEnum;
+ extern enum Enum08 : int { } SIntEnum;
+ extern enum Enum09 : unsigned int { } UIntEnum;
+ extern enum Enum10 : long { } SLongEnum;
+ extern enum Enum11 : unsigned long { } ULongEnum;
+ extern enum Enum12 : long long { } SLongLongEnum;
+ extern enum Enum13 : unsigned long long { } ULongLongEnum;
+// CHECK-DAG: @"\01?Enum@EnumMangling@@3W4Enum01@1@A"
+// CHECK-DAG: @"\01?BoolEnum@EnumMangling@@3W4Enum02@1@A
+// CHECK-DAG: @"\01?CharEnum@EnumMangling@@3W4Enum03@1@A
+// CHECK-DAG: @"\01?SCharEnum@EnumMangling@@3W4Enum04@1@A
+// CHECK-DAG: @"\01?UCharEnum@EnumMangling@@3W4Enum05@1@A
+// CHECK-DAG: @"\01?SShortEnum@EnumMangling@@3W4Enum06@1@A"
+// CHECK-DAG: @"\01?UShortEnum@EnumMangling@@3W4Enum07@1@A"
+// CHECK-DAG: @"\01?SIntEnum@EnumMangling@@3W4Enum08@1@A"
+// CHECK-DAG: @"\01?UIntEnum@EnumMangling@@3W4Enum09@1@A"
+// CHECK-DAG: @"\01?SLongEnum@EnumMangling@@3W4Enum10@1@A"
+// CHECK-DAG: @"\01?ULongEnum@EnumMangling@@3W4Enum11@1@A"
+// CHECK-DAG: @"\01?SLongLongEnum@EnumMangling@@3W4Enum12@1@A"
+// CHECK-DAG: @"\01?ULongLongEnum@EnumMangling@@3W4Enum13@1@A"
+ decltype(Enum) *UseEnum() { return &Enum; }
+ decltype(BoolEnum) *UseBoolEnum() { return &BoolEnum; }
+ decltype(CharEnum) *UseCharEnum() { return &CharEnum; }
+ decltype(SCharEnum) *UseSCharEnum() { return &SCharEnum; }
+ decltype(UCharEnum) *UseUCharEnum() { return &UCharEnum; }
+ decltype(SShortEnum) *UseSShortEnum() { return &SShortEnum; }
+ decltype(UShortEnum) *UseUShortEnum() { return &UShortEnum; }
+ decltype(SIntEnum) *UseSIntEnum() { return &SIntEnum; }
+ decltype(UIntEnum) *UseUIntEnum() { return &UIntEnum; }
+ decltype(SLongEnum) *UseSLongEnum() { return &SLongEnum; }
+ decltype(ULongEnum) *UseULongEnum() { return &ULongEnum; }
+ decltype(SLongLongEnum) *UseSLongLongEnum() { return &SLongLongEnum; }
+ decltype(ULongLongEnum) *UseULongLongEnum() { return &ULongLongEnum; }
+ extern enum class EnumClass01 { } EnumClass;
+ extern enum class EnumClass02 : bool { } BoolEnumClass;
+ extern enum class EnumClass03 : char { } CharEnumClass;
+ extern enum class EnumClass04 : signed char { } SCharEnumClass;
+ extern enum class EnumClass05 : unsigned char { } UCharEnumClass;
+ extern enum class EnumClass06 : short { } SShortEnumClass;
+ extern enum class EnumClass07 : unsigned short { } UShortEnumClass;
+ extern enum class EnumClass08 : int { } SIntEnumClass;
+ extern enum class EnumClass09 : unsigned int { } UIntEnumClass;
+ extern enum class EnumClass10 : long { } SLongEnumClass;
+ extern enum class EnumClass11 : unsigned long { } ULongEnumClass;
+ extern enum class EnumClass12 : long long { } SLongLongEnumClass;
+ extern enum class EnumClass13 : unsigned long long { } ULongLongEnumClass;
+// CHECK-DAG: @"\01?EnumClass@EnumMangling@@3W4EnumClass01@1@A"
+// CHECK-DAG: @"\01?BoolEnumClass@EnumMangling@@3W4EnumClass02@1@A
+// CHECK-DAG: @"\01?CharEnumClass@EnumMangling@@3W4EnumClass03@1@A
+// CHECK-DAG: @"\01?SCharEnumClass@EnumMangling@@3W4EnumClass04@1@A
+// CHECK-DAG: @"\01?UCharEnumClass@EnumMangling@@3W4EnumClass05@1@A
+// CHECK-DAG: @"\01?SShortEnumClass@EnumMangling@@3W4EnumClass06@1@A"
+// CHECK-DAG: @"\01?UShortEnumClass@EnumMangling@@3W4EnumClass07@1@A"
+// CHECK-DAG: @"\01?SIntEnumClass@EnumMangling@@3W4EnumClass08@1@A"
+// CHECK-DAG: @"\01?UIntEnumClass@EnumMangling@@3W4EnumClass09@1@A"
+// CHECK-DAG: @"\01?SLongEnumClass@EnumMangling@@3W4EnumClass10@1@A"
+// CHECK-DAG: @"\01?ULongEnumClass@EnumMangling@@3W4EnumClass11@1@A"
+// CHECK-DAG: @"\01?SLongLongEnumClass@EnumMangling@@3W4EnumClass12@1@A"
+// CHECK-DAG: @"\01?ULongLongEnumClass@EnumMangling@@3W4EnumClass13@1@A"
+ decltype(EnumClass) *UseEnumClass() { return &EnumClass; }
+ decltype(BoolEnumClass) *UseBoolEnumClass() { return &BoolEnumClass; }
+ decltype(CharEnumClass) *UseCharEnumClass() { return &CharEnumClass; }
+ decltype(SCharEnumClass) *UseSCharEnumClass() { return &SCharEnumClass; }
+ decltype(UCharEnumClass) *UseUCharEnumClass() { return &UCharEnumClass; }
+ decltype(SShortEnumClass) *UseSShortEnumClass() { return &SShortEnumClass; }
+ decltype(UShortEnumClass) *UseUShortEnumClass() { return &UShortEnumClass; }
+ decltype(SIntEnumClass) *UseSIntEnumClass() { return &SIntEnumClass; }
+ decltype(UIntEnumClass) *UseUIntEnumClass() { return &UIntEnumClass; }
+ decltype(SLongEnumClass) *UseSLongEnumClass() { return &SLongEnumClass; }
+ decltype(ULongEnumClass) *UseULongEnumClass() { return &ULongEnumClass; }
+ decltype(SLongLongEnumClass) *UseSLongLongEnumClass() { return &SLongLongEnumClass; }
+ decltype(ULongLongEnumClass) *UseULongLongEnumClass() { return &ULongLongEnumClass; }
+}
+
+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
+
+}
+
+inline int define_lambda() {
+ static auto lambda = [] { static int local; ++local; return local; };
+// First, we have the static local variable of type "<lambda_1>" inside of
+// "define_lambda".
+// CHECK-DAG: ?lambda@?1??define_lambda@@YAHXZ@4V<lambda_1>@@A
+// Next, we have the "operator()" for "<lambda_1>" which is inside of
+// "define_lambda".
+// CHECK-DAG: ??R<lambda_1>@?define_lambda@@YAHXZ@QBEHXZ
+// Finally, we have the local which is inside of "<lambda_1>" which is inside of
+// "define_lambda". Hooray.
+// CHECK-DAG: ?local@?2???R<lambda_1>@?define_lambda@@YAHXZ@QBEHXZ@4HA
+ return lambda();
+}
+
+int call_lambda() {
+ return define_lambda();
+}
+
+namespace PR19361 {
+struct A {
+ void foo() __restrict &;
+ void foo() __restrict &&;
+};
+void A::foo() __restrict & {}
+// CHECK-DAG: @"\01?foo@A@PR19361@@QIGAEXXZ"
+void A::foo() __restrict && {}
+// CHECK-DAG: @"\01?foo@A@PR19361@@QIHAEXXZ"
+}
+
+int operator"" _deg(long double) { return 0; }
+// CHECK-DAG: @"\01??__K_deg@@YAHO@Z"
+
+template <char...>
+void templ_fun_with_pack() {}
+
+template void templ_fun_with_pack<>();
+// CHECK-DAG: @"\01??$templ_fun_with_pack@$S@@YAXXZ"
diff --git a/test/CodeGenCXX/mangle-ms-cxx14.cpp b/test/CodeGenCXX/mangle-ms-cxx14.cpp
new file mode 100644
index 000000000000..03995611d252
--- /dev/null
+++ b/test/CodeGenCXX/mangle-ms-cxx14.cpp
@@ -0,0 +1,40 @@
+// RUN: %clang_cc1 -std=c++1y -fms-extensions -emit-llvm %s -o - -triple=i386-pc-win32 | FileCheck %s
+
+template <typename> int x = 0;
+
+// CHECK: "\01??$x@X@@3HA"
+template <> int x<void>;
+// CHECK: "\01??$x@H@@3HA"
+template <> int x<int>;
+
+// CHECK: "\01?FunctionWithLocalType@@YA?A?<auto>@@XZ"
+auto FunctionWithLocalType() {
+ struct LocalType {};
+ return LocalType{};
+}
+
+// CHECK: "\01?ValueFromFunctionWithLocalType@@3ULocalType@?0??FunctionWithLocalType@@YA?A?<auto>@@XZ@A"
+auto ValueFromFunctionWithLocalType = FunctionWithLocalType();
+
+// CHECK: "\01??R<lambda_0>@@QBE?A?<auto>@@XZ"
+auto LambdaWithLocalType = [] {
+ struct LocalType {};
+ return LocalType{};
+};
+
+// CHECK: "\01?ValueFromLambdaWithLocalType@@3ULocalType@?0???R<lambda_0>@@QBE?A?<auto>@@XZ@A"
+auto ValueFromLambdaWithLocalType = LambdaWithLocalType();
+
+template <typename T>
+auto TemplateFuncionWithLocalLambda(T) {
+ auto LocalLambdaWithLocalType = []() {
+ struct LocalType {};
+ return LocalType{};
+ };
+ return LocalLambdaWithLocalType();
+}
+
+// CHECK: "\01?ValueFromTemplateFuncionWithLocalLambda@@3ULocalType@?2???R<lambda_1>@??$TemplateFuncionWithLocalLambda@H@@YA?A?<auto>@@H@Z@QBA?A?3@XZ@A"
+// CHECK: "\01??$TemplateFuncionWithLocalLambda@H@@YA?A?<auto>@@H@Z"
+// CHECK: "\01??R<lambda_1>@??$TemplateFuncionWithLocalLambda@H@@YA?A?<auto>@@H@Z@QBA?A?1@XZ"
+auto ValueFromTemplateFuncionWithLocalLambda = TemplateFuncionWithLocalLambda(0);
diff --git a/test/CodeGenCXX/mangle-ms-return-qualifiers.cpp b/test/CodeGenCXX/mangle-ms-return-qualifiers.cpp
index 87e04c645ece..37bbf099fab0 100644
--- a/test/CodeGenCXX/mangle-ms-return-qualifiers.cpp
+++ b/test/CodeGenCXX/mangle-ms-return-qualifiers.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 | FileCheck %s
void a1() {}
// CHECK: "\01?a1@@YAXXZ"
@@ -164,6 +164,12 @@ int S::* f8() { return 0; }
int S::* const f9() { return 0; }
// CHECK: "\01?f9@@YAQQS@@HXZ"
+int S::* __restrict f10() { return 0; }
+// CHECK: "\01?f10@@YAPIQS@@HXZ"
+
+int S::* const __restrict f11() { return 0; }
+// CHECK: "\01?f11@@YAQIQS@@HXZ"
+
typedef int (*function_pointer)(int);
function_pointer g1() { return 0; }
diff --git a/test/CodeGenCXX/mangle-ms-string-literals.cpp b/test/CodeGenCXX/mangle-ms-string-literals.cpp
new file mode 100644
index 000000000000..a77a04f71e0a
--- /dev/null
+++ b/test/CodeGenCXX/mangle-ms-string-literals.cpp
@@ -0,0 +1,721 @@
+// RUN: %clang_cc1 -x c++ -std=c++11 -emit-llvm %s -o - -triple=i386-pc-win32 | FileCheck %s
+// RUN: %clang_cc1 -x c++ -std=c++11 -emit-llvm %s -o - -triple=x86_64-pc-win32 | FileCheck %s
+
+const char *l255 = "\xff";
+const char *l254 = "\xfe";
+const char *l253 = "\xfd";
+const char *l252 = "\xfc";
+const char *l251 = "\xfb";
+const char *l250 = "\xfa";
+const char *l249 = "\xf9";
+const char *l248 = "\xf8";
+const char *l247 = "\xf7";
+const char *l246 = "\xf6";
+const char *l245 = "\xf5";
+const char *l244 = "\xf4";
+const char *l243 = "\xf3";
+const char *l242 = "\xf2";
+const char *l241 = "\xf1";
+const char *l240 = "\xf0";
+const char *l239 = "\xef";
+const char *l238 = "\xee";
+const char *l237 = "\xed";
+const char *l236 = "\xec";
+const char *l235 = "\xeb";
+const char *l234 = "\xea";
+const char *l233 = "\xe9";
+const char *l232 = "\xe8";
+const char *l231 = "\xe7";
+const char *l230 = "\xe6";
+const char *l229 = "\xe5";
+const char *l228 = "\xe4";
+const char *l227 = "\xe3";
+const char *l226 = "\xe2";
+const char *l225 = "\xe1";
+const char *l224 = "\xe0";
+const char *l223 = "\xdf";
+const char *l222 = "\xde";
+const char *l221 = "\xdd";
+const char *l220 = "\xdc";
+const char *l219 = "\xdb";
+const char *l218 = "\xda";
+const char *l217 = "\xd9";
+const char *l216 = "\xd8";
+const char *l215 = "\xd7";
+const char *l214 = "\xd6";
+const char *l213 = "\xd5";
+const char *l212 = "\xd4";
+const char *l211 = "\xd3";
+const char *l210 = "\xd2";
+const char *l209 = "\xd1";
+const char *l208 = "\xd0";
+const char *l207 = "\xcf";
+const char *l206 = "\xce";
+const char *l205 = "\xcd";
+const char *l204 = "\xcc";
+const char *l203 = "\xcb";
+const char *l202 = "\xca";
+const char *l201 = "\xc9";
+const char *l200 = "\xc8";
+const char *l199 = "\xc7";
+const char *l198 = "\xc6";
+const char *l197 = "\xc5";
+const char *l196 = "\xc4";
+const char *l195 = "\xc3";
+const char *l194 = "\xc2";
+const char *l193 = "\xc1";
+const char *l192 = "\xc0";
+const char *l191 = "\xbf";
+const char *l190 = "\xbe";
+const char *l189 = "\xbd";
+const char *l188 = "\xbc";
+const char *l187 = "\xbb";
+const char *l186 = "\xba";
+const char *l185 = "\xb9";
+const char *l184 = "\xb8";
+const char *l183 = "\xb7";
+const char *l182 = "\xb6";
+const char *l181 = "\xb5";
+const char *l180 = "\xb4";
+const char *l179 = "\xb3";
+const char *l178 = "\xb2";
+const char *l177 = "\xb1";
+const char *l176 = "\xb0";
+const char *l175 = "\xaf";
+const char *l174 = "\xae";
+const char *l173 = "\xad";
+const char *l172 = "\xac";
+const char *l171 = "\xab";
+const char *l170 = "\xaa";
+const char *l169 = "\xa9";
+const char *l168 = "\xa8";
+const char *l167 = "\xa7";
+const char *l166 = "\xa6";
+const char *l165 = "\xa5";
+const char *l164 = "\xa4";
+const char *l163 = "\xa3";
+const char *l162 = "\xa2";
+const char *l161 = "\xa1";
+const char *l160 = "\xa0";
+const char *l159 = "\x9f";
+const char *l158 = "\x9e";
+const char *l157 = "\x9d";
+const char *l156 = "\x9c";
+const char *l155 = "\x9b";
+const char *l154 = "\x9a";
+const char *l153 = "\x99";
+const char *l152 = "\x98";
+const char *l151 = "\x97";
+const char *l150 = "\x96";
+const char *l149 = "\x95";
+const char *l148 = "\x94";
+const char *l147 = "\x93";
+const char *l146 = "\x92";
+const char *l145 = "\x91";
+const char *l144 = "\x90";
+const char *l143 = "\x8f";
+const char *l142 = "\x8e";
+const char *l141 = "\x8d";
+const char *l140 = "\x8c";
+const char *l139 = "\x8b";
+const char *l138 = "\x8a";
+const char *l137 = "\x89";
+const char *l136 = "\x88";
+const char *l135 = "\x87";
+const char *l134 = "\x86";
+const char *l133 = "\x85";
+const char *l132 = "\x84";
+const char *l131 = "\x83";
+const char *l130 = "\x82";
+const char *l129 = "\x81";
+const char *l128 = "\x80";
+const char *l127 = "\x7f";
+const char *l126 = "\x7e";
+const char *l125 = "\x7d";
+const char *l124 = "\x7c";
+const char *l123 = "\x7b";
+const char *l122 = "\x7a";
+const char *l121 = "\x79";
+const char *l120 = "\x78";
+const char *l119 = "\x77";
+const char *l118 = "\x76";
+const char *l117 = "\x75";
+const char *l116 = "\x74";
+const char *l115 = "\x73";
+const char *l114 = "\x72";
+const char *l113 = "\x71";
+const char *l112 = "\x70";
+const char *l111 = "\x6f";
+const char *l110 = "\x6e";
+const char *l109 = "\x6d";
+const char *l108 = "\x6c";
+const char *l107 = "\x6b";
+const char *l106 = "\x6a";
+const char *l105 = "\x69";
+const char *l104 = "\x68";
+const char *l103 = "\x67";
+const char *l102 = "\x66";
+const char *l101 = "\x65";
+const char *l100 = "\x64";
+const char *l99 = "\x63";
+const char *l98 = "\x62";
+const char *l97 = "\x61";
+const char *l96 = "\x60";
+const char *l95 = "\x5f";
+const char *l94 = "\x5e";
+const char *l93 = "\x5d";
+const char *l92 = "\x5c";
+const char *l91 = "\x5b";
+const char *l90 = "\x5a";
+const char *l89 = "\x59";
+const char *l88 = "\x58";
+const char *l87 = "\x57";
+const char *l86 = "\x56";
+const char *l85 = "\x55";
+const char *l84 = "\x54";
+const char *l83 = "\x53";
+const char *l82 = "\x52";
+const char *l81 = "\x51";
+const char *l80 = "\x50";
+const char *l79 = "\x4f";
+const char *l78 = "\x4e";
+const char *l77 = "\x4d";
+const char *l76 = "\x4c";
+const char *l75 = "\x4b";
+const char *l74 = "\x4a";
+const char *l73 = "\x49";
+const char *l72 = "\x48";
+const char *l71 = "\x47";
+const char *l70 = "\x46";
+const char *l69 = "\x45";
+const char *l68 = "\x44";
+const char *l67 = "\x43";
+const char *l66 = "\x42";
+const char *l65 = "\x41";
+const char *l64 = "\x40";
+const char *l63 = "\x3f";
+const char *l62 = "\x3e";
+const char *l61 = "\x3d";
+const char *l60 = "\x3c";
+const char *l59 = "\x3b";
+const char *l58 = "\x3a";
+const char *l57 = "\x39";
+const char *l56 = "\x38";
+const char *l55 = "\x37";
+const char *l54 = "\x36";
+const char *l53 = "\x35";
+const char *l52 = "\x34";
+const char *l51 = "\x33";
+const char *l50 = "\x32";
+const char *l49 = "\x31";
+const char *l48 = "\x30";
+const char *l47 = "\x2f";
+const char *l46 = "\x2e";
+const char *l45 = "\x2d";
+const char *l44 = "\x2c";
+const char *l43 = "\x2b";
+const char *l42 = "\x2a";
+const char *l41 = "\x29";
+const char *l40 = "\x28";
+const char *l39 = "\x27";
+const char *l38 = "\x26";
+const char *l37 = "\x25";
+const char *l36 = "\x24";
+const char *l35 = "\x23";
+const char *l34 = "\x22";
+const char *l33 = "\x21";
+const char *l32 = "\x20";
+const char *l31 = "\x1f";
+const char *l30 = "\x1e";
+const char *l29 = "\x1d";
+const char *l28 = "\x1c";
+const char *l27 = "\x1b";
+const char *l26 = "\x1a";
+const char *l25 = "\x19";
+const char *l24 = "\x18";
+const char *l23 = "\x17";
+const char *l22 = "\x16";
+const char *l21 = "\x15";
+const char *l20 = "\x14";
+const char *l19 = "\x13";
+const char *l18 = "\x12";
+const char *l17 = "\x11";
+const char *l16 = "\x10";
+const char *l15 = "\xf";
+const char *l14 = "\xe";
+const char *l13 = "\xd";
+const char *l12 = "\xc";
+const char *l11 = "\xb";
+const char *l10 = "\xa";
+const char *l9 = "\x9";
+const char *l8 = "\x8";
+const char *l7 = "\x7";
+const char *l6 = "\x6";
+const char *l5 = "\x5";
+const char *l4 = "\x4";
+const char *l3 = "\x3";
+const char *l2 = "\x2";
+const char *l1 = "\x1";
+const char *l0 = "\x0";
+
+// CHECK: @"\01??_C@_01CNACBAHC@?$PP?$AA@"
+// CHECK: @"\01??_C@_01DEBJCBDD@?$PO?$AA@"
+// CHECK: @"\01??_C@_01BPDEHCPA@?$PN?$AA@"
+// CHECK: @"\01??_C@_01GCPEDLB@?$PM?$AA@"
+// CHECK: @"\01??_C@_01EJGONFHG@?$PL?$AA@"
+// CHECK: @"\01??_C@_01FAHFOEDH@?z?$AA@"
+// CHECK: @"\01??_C@_01HLFILHPE@?y?$AA@"
+// CHECK: @"\01??_C@_01GCEDIGLF@?x?$AA@"
+// CHECK: @"\01??_C@_01OFNLJKHK@?w?$AA@"
+// CHECK: @"\01??_C@_01PMMAKLDL@?v?$AA@"
+// CHECK: @"\01??_C@_01NHONPIPI@?u?$AA@"
+// CHECK: @"\01??_C@_01MOPGMJLJ@?t?$AA@"
+// CHECK: @"\01??_C@_01IBLHFPHO@?s?$AA@"
+// CHECK: @"\01??_C@_01JIKMGODP@?r?$AA@"
+// CHECK: @"\01??_C@_01LDIBDNPM@?q?$AA@"
+// CHECK: @"\01??_C@_01KKJKAMLN@?p?$AA@"
+// CHECK: @"\01??_C@_01GHMAACCD@?o?$AA@"
+// CHECK: @"\01??_C@_01HONLDDGC@?n?$AA@"
+// CHECK: @"\01??_C@_01FFPGGAKB@?m?$AA@"
+// CHECK: @"\01??_C@_01EMONFBOA@?l?$AA@"
+// CHECK: @"\01??_C@_01DKMMHCH@?k?$AA@"
+// CHECK: @"\01??_C@_01BKLHPGGG@?j?$AA@"
+// CHECK: @"\01??_C@_01DBJKKFKF@?i?$AA@"
+// CHECK: @"\01??_C@_01CIIBJEOE@?h?$AA@"
+// CHECK: @"\01??_C@_01KPBJIICL@?g?$AA@"
+// CHECK: @"\01??_C@_01LGACLJGK@?f?$AA@"
+// CHECK: @"\01??_C@_01JNCPOKKJ@?e?$AA@"
+// CHECK: @"\01??_C@_01IEDENLOI@?d?$AA@"
+// CHECK: @"\01??_C@_01MLHFENCP@?c?$AA@"
+// CHECK: @"\01??_C@_01NCGOHMGO@?b?$AA@"
+// CHECK: @"\01??_C@_01PJEDCPKN@?a?$AA@"
+// CHECK: @"\01??_C@_01OAFIBOOM@?$OA?$AA@"
+// CHECK: @"\01??_C@_01LIIGDENA@?$NP?$AA@"
+// CHECK: @"\01??_C@_01KBJNAFJB@?$NO?$AA@"
+// CHECK: @"\01??_C@_01IKLAFGFC@?$NN?$AA@"
+// CHECK: @"\01??_C@_01JDKLGHBD@?$NM?$AA@"
+// CHECK: @"\01??_C@_01NMOKPBNE@?$NL?$AA@"
+// CHECK: @"\01??_C@_01MFPBMAJF@?Z?$AA@"
+// CHECK: @"\01??_C@_01OONMJDFG@?Y?$AA@"
+// CHECK: @"\01??_C@_01PHMHKCBH@?X?$AA@"
+// CHECK: @"\01??_C@_01HAFPLONI@?W?$AA@"
+// CHECK: @"\01??_C@_01GJEEIPJJ@?V?$AA@"
+// CHECK: @"\01??_C@_01ECGJNMFK@?U?$AA@"
+// CHECK: @"\01??_C@_01FLHCONBL@?T?$AA@"
+// CHECK: @"\01??_C@_01BEDDHLNM@?S?$AA@"
+// CHECK: @"\01??_C@_01NCIEKJN@?R?$AA@"
+// CHECK: @"\01??_C@_01CGAFBJFO@?Q?$AA@"
+// CHECK: @"\01??_C@_01DPBOCIBP@?P?$AA@"
+// CHECK: @"\01??_C@_01PCEECGIB@?O?$AA@"
+// CHECK: @"\01??_C@_01OLFPBHMA@?N?$AA@"
+// CHECK: @"\01??_C@_01MAHCEEAD@?M?$AA@"
+// CHECK: @"\01??_C@_01NJGJHFEC@?L?$AA@"
+// CHECK: @"\01??_C@_01JGCIODIF@?K?$AA@"
+// CHECK: @"\01??_C@_01IPDDNCME@?J?$AA@"
+// CHECK: @"\01??_C@_01KEBOIBAH@?I?$AA@"
+// CHECK: @"\01??_C@_01LNAFLAEG@?H?$AA@"
+// CHECK: @"\01??_C@_01DKJNKMIJ@?G?$AA@"
+// CHECK: @"\01??_C@_01CDIGJNMI@?F?$AA@"
+// CHECK: @"\01??_C@_01IKLMOAL@?E?$AA@"
+// CHECK: @"\01??_C@_01BBLAPPEK@?D?$AA@"
+// CHECK: @"\01??_C@_01FOPBGJIN@?C?$AA@"
+// CHECK: @"\01??_C@_01EHOKFIMM@?B?$AA@"
+// CHECK: @"\01??_C@_01GMMHALAP@?A?$AA@"
+// CHECK: @"\01??_C@_01HFNMDKEO@?$MA?$AA@"
+// CHECK: @"\01??_C@_01NNHLFPHH@?$LP?$AA@"
+// CHECK: @"\01??_C@_01MEGAGODG@?$LO?$AA@"
+// CHECK: @"\01??_C@_01OPENDNPF@?$LN?$AA@"
+// CHECK: @"\01??_C@_01PGFGAMLE@?$LM?$AA@"
+// CHECK: @"\01??_C@_01LJBHJKHD@?$LL?$AA@"
+// CHECK: @"\01??_C@_01KAAMKLDC@?$LK?$AA@"
+// CHECK: @"\01??_C@_01ILCBPIPB@?$LJ?$AA@"
+// CHECK: @"\01??_C@_01JCDKMJLA@?$LI?$AA@"
+// CHECK: @"\01??_C@_01BFKCNFHP@?$LH?$AA@"
+// CHECK: @"\01??_C@_01MLJOEDO@?$LG?$AA@"
+// CHECK: @"\01??_C@_01CHJELHPN@?$LF?$AA@"
+// CHECK: @"\01??_C@_01DOIPIGLM@?$LE?$AA@"
+// CHECK: @"\01??_C@_01HBMOBAHL@?$LD?$AA@"
+// CHECK: @"\01??_C@_01GINFCBDK@?$LC?$AA@"
+// CHECK: @"\01??_C@_01EDPIHCPJ@?$LB?$AA@"
+// CHECK: @"\01??_C@_01FKODEDLI@?$LA?$AA@"
+// CHECK: @"\01??_C@_01JHLJENCG@?$KP?$AA@"
+// CHECK: @"\01??_C@_01IOKCHMGH@?$KO?$AA@"
+// CHECK: @"\01??_C@_01KFIPCPKE@?$KN?$AA@"
+// CHECK: @"\01??_C@_01LMJEBOOF@?$KM?$AA@"
+// CHECK: @"\01??_C@_01PDNFIICC@?$KL?$AA@"
+// CHECK: @"\01??_C@_01OKMOLJGD@?$KK?$AA@"
+// CHECK: @"\01??_C@_01MBODOKKA@?$KJ?$AA@"
+// CHECK: @"\01??_C@_01NIPINLOB@?$KI?$AA@"
+// CHECK: @"\01??_C@_01FPGAMHCO@?$KH?$AA@"
+// CHECK: @"\01??_C@_01EGHLPGGP@?$KG?$AA@"
+// CHECK: @"\01??_C@_01GNFGKFKM@?$KF?$AA@"
+// CHECK: @"\01??_C@_01HEENJEON@?$KE?$AA@"
+// CHECK: @"\01??_C@_01DLAMACCK@?$KD?$AA@"
+// CHECK: @"\01??_C@_01CCBHDDGL@?$KC?$AA@"
+// CHECK: @"\01??_C@_01JDKGAKI@?$KB?$AA@"
+// CHECK: @"\01??_C@_01BACBFBOJ@?$KA?$AA@"
+// CHECK: @"\01??_C@_01EIPPHLNF@?$JP?$AA@"
+// CHECK: @"\01??_C@_01FBOEEKJE@?$JO?$AA@"
+// CHECK: @"\01??_C@_01HKMJBJFH@?$JN?$AA@"
+// CHECK: @"\01??_C@_01GDNCCIBG@?$JM?$AA@"
+// CHECK: @"\01??_C@_01CMJDLONB@?$JL?$AA@"
+// CHECK: @"\01??_C@_01DFIIIPJA@?$JK?$AA@"
+// CHECK: @"\01??_C@_01BOKFNMFD@?$JJ?$AA@"
+// CHECK: @"\01??_C@_01HLOONBC@?$JI?$AA@"
+// CHECK: @"\01??_C@_01IACGPBNN@?$JH?$AA@"
+// CHECK: @"\01??_C@_01JJDNMAJM@?$JG?$AA@"
+// CHECK: @"\01??_C@_01LCBAJDFP@?$JF?$AA@"
+// CHECK: @"\01??_C@_01KLALKCBO@?$JE?$AA@"
+// CHECK: @"\01??_C@_01OEEKDENJ@?$JD?$AA@"
+// CHECK: @"\01??_C@_01PNFBAFJI@?$JC?$AA@"
+// CHECK: @"\01??_C@_01NGHMFGFL@?$JB?$AA@"
+// CHECK: @"\01??_C@_01MPGHGHBK@?$JA?$AA@"
+// CHECK: @"\01??_C@_01CDNGJIE@?$IP?$AA@"
+// CHECK: @"\01??_C@_01BLCGFIMF@?$IO?$AA@"
+// CHECK: @"\01??_C@_01DAALALAG@?$IN?$AA@"
+// CHECK: @"\01??_C@_01CJBADKEH@?$IM?$AA@"
+// CHECK: @"\01??_C@_01GGFBKMIA@?$IL?$AA@"
+// CHECK: @"\01??_C@_01HPEKJNMB@?$IK?$AA@"
+// CHECK: @"\01??_C@_01FEGHMOAC@?$IJ?$AA@"
+// CHECK: @"\01??_C@_01ENHMPPED@?$II?$AA@"
+// CHECK: @"\01??_C@_01MKOEODIM@?$IH?$AA@"
+// CHECK: @"\01??_C@_01NDPPNCMN@?$IG?$AA@"
+// CHECK: @"\01??_C@_01PINCIBAO@?$IF?$AA@"
+// CHECK: @"\01??_C@_01OBMJLAEP@?$IE?$AA@"
+// CHECK: @"\01??_C@_01KOIICGII@?$ID?$AA@"
+// CHECK: @"\01??_C@_01LHJDBHMJ@?$IC?$AA@"
+// CHECK: @"\01??_C@_01JMLOEEAK@?$IB?$AA@"
+// CHECK: @"\01??_C@_01IFKFHFEL@?$IA?$AA@"
+// CHECK: @"\01??_C@_01BGIBIIDJ@?$HP?$AA@"
+// CHECK: @"\01??_C@_01PJKLJHI@?$HO?$AA@"
+// CHECK: @"\01??_C@_01CELHOKLL@?$HN?$AA@"
+// CHECK: @"\01??_C@_01DNKMNLPK@?$HM?$AA@"
+// CHECK: @"\01??_C@_01HCONENDN@?$HL?$AA@"
+// CHECK: @"\01??_C@_01GLPGHMHM@z?$AA@"
+// CHECK: @"\01??_C@_01EANLCPLP@y?$AA@"
+// CHECK: @"\01??_C@_01FJMABOPO@x?$AA@"
+// CHECK: @"\01??_C@_01NOFIACDB@w?$AA@"
+// CHECK: @"\01??_C@_01MHEDDDHA@v?$AA@"
+// CHECK: @"\01??_C@_01OMGOGALD@u?$AA@"
+// CHECK: @"\01??_C@_01PFHFFBPC@t?$AA@"
+// CHECK: @"\01??_C@_01LKDEMHDF@s?$AA@"
+// CHECK: @"\01??_C@_01KDCPPGHE@r?$AA@"
+// CHECK: @"\01??_C@_01IIACKFLH@q?$AA@"
+// CHECK: @"\01??_C@_01JBBJJEPG@p?$AA@"
+// CHECK: @"\01??_C@_01FMEDJKGI@o?$AA@"
+// CHECK: @"\01??_C@_01EFFIKLCJ@n?$AA@"
+// CHECK: @"\01??_C@_01GOHFPIOK@m?$AA@"
+// CHECK: @"\01??_C@_01HHGOMJKL@l?$AA@"
+// CHECK: @"\01??_C@_01DICPFPGM@k?$AA@"
+// CHECK: @"\01??_C@_01CBDEGOCN@j?$AA@"
+// CHECK: @"\01??_C@_01KBJDNOO@i?$AA@"
+// CHECK: @"\01??_C@_01BDACAMKP@h?$AA@"
+// CHECK: @"\01??_C@_01JEJKBAGA@g?$AA@"
+// CHECK: @"\01??_C@_01INIBCBCB@f?$AA@"
+// CHECK: @"\01??_C@_01KGKMHCOC@e?$AA@"
+// CHECK: @"\01??_C@_01LPLHEDKD@d?$AA@"
+// CHECK: @"\01??_C@_01PAPGNFGE@c?$AA@"
+// CHECK: @"\01??_C@_01OJONOECF@b?$AA@"
+// CHECK: @"\01??_C@_01MCMALHOG@a?$AA@"
+// CHECK: @"\01??_C@_01NLNLIGKH@?$GA?$AA@"
+// CHECK: @"\01??_C@_01IDAFKMJL@_?$AA@"
+// CHECK: @"\01??_C@_01JKBOJNNK@?$FO?$AA@"
+// CHECK: @"\01??_C@_01LBDDMOBJ@?$FN?$AA@"
+// CHECK: @"\01??_C@_01KICIPPFI@?2?$AA@"
+// CHECK: @"\01??_C@_01OHGJGJJP@?$FL?$AA@"
+// CHECK: @"\01??_C@_01POHCFINO@Z?$AA@"
+// CHECK: @"\01??_C@_01NFFPALBN@Y?$AA@"
+// CHECK: @"\01??_C@_01MMEEDKFM@X?$AA@"
+// CHECK: @"\01??_C@_01ELNMCGJD@W?$AA@"
+// CHECK: @"\01??_C@_01FCMHBHNC@V?$AA@"
+// CHECK: @"\01??_C@_01HJOKEEBB@U?$AA@"
+// CHECK: @"\01??_C@_01GAPBHFFA@T?$AA@"
+// CHECK: @"\01??_C@_01CPLAODJH@S?$AA@"
+// CHECK: @"\01??_C@_01DGKLNCNG@R?$AA@"
+// CHECK: @"\01??_C@_01BNIGIBBF@Q?$AA@"
+// CHECK: @"\01??_C@_01EJNLAFE@P?$AA@"
+// CHECK: @"\01??_C@_01MJMHLOMK@O?$AA@"
+// CHECK: @"\01??_C@_01NANMIPIL@N?$AA@"
+// CHECK: @"\01??_C@_01PLPBNMEI@M?$AA@"
+// CHECK: @"\01??_C@_01OCOKONAJ@L?$AA@"
+// CHECK: @"\01??_C@_01KNKLHLMO@K?$AA@"
+// CHECK: @"\01??_C@_01LELAEKIP@J?$AA@"
+// CHECK: @"\01??_C@_01JPJNBJEM@I?$AA@"
+// CHECK: @"\01??_C@_01IGIGCIAN@H?$AA@"
+// CHECK: @"\01??_C@_01BBODEMC@G?$AA@"
+// CHECK: @"\01??_C@_01BIAFAFID@F?$AA@"
+// CHECK: @"\01??_C@_01DDCIFGEA@E?$AA@"
+// CHECK: @"\01??_C@_01CKDDGHAB@D?$AA@"
+// CHECK: @"\01??_C@_01GFHCPBMG@C?$AA@"
+// CHECK: @"\01??_C@_01HMGJMAIH@B?$AA@"
+// CHECK: @"\01??_C@_01FHEEJDEE@A?$AA@"
+// CHECK: @"\01??_C@_01EOFPKCAF@?$EA?$AA@"
+// CHECK: @"\01??_C@_01OGPIMHDM@?$DP?$AA@"
+// CHECK: @"\01??_C@_01PPODPGHN@?$DO?$AA@"
+// CHECK: @"\01??_C@_01NEMOKFLO@?$DN?$AA@"
+// CHECK: @"\01??_C@_01MNNFJEPP@?$DM?$AA@"
+// CHECK: @"\01??_C@_01ICJEACDI@?$DL?$AA@"
+// CHECK: @"\01??_C@_01JLIPDDHJ@?3?$AA@"
+// CHECK: @"\01??_C@_01LAKCGALK@9?$AA@"
+// CHECK: @"\01??_C@_01KJLJFBPL@8?$AA@"
+// CHECK: @"\01??_C@_01COCBENDE@7?$AA@"
+// CHECK: @"\01??_C@_01DHDKHMHF@6?$AA@"
+// CHECK: @"\01??_C@_01BMBHCPLG@5?$AA@"
+// CHECK: @"\01??_C@_01FAMBOPH@4?$AA@"
+// CHECK: @"\01??_C@_01EKENIIDA@3?$AA@"
+// CHECK: @"\01??_C@_01FDFGLJHB@2?$AA@"
+// CHECK: @"\01??_C@_01HIHLOKLC@1?$AA@"
+// CHECK: @"\01??_C@_01GBGANLPD@0?$AA@"
+// CHECK: @"\01??_C@_01KMDKNFGN@?1?$AA@"
+// CHECK: @"\01??_C@_01LFCBOECM@?4?$AA@"
+// CHECK: @"\01??_C@_01JOAMLHOP@?9?$AA@"
+// CHECK: @"\01??_C@_01IHBHIGKO@?0?$AA@"
+// CHECK: @"\01??_C@_01MIFGBAGJ@?$CL?$AA@"
+// CHECK: @"\01??_C@_01NBENCBCI@?$CK?$AA@"
+// CHECK: @"\01??_C@_01PKGAHCOL@?$CJ?$AA@"
+// CHECK: @"\01??_C@_01ODHLEDKK@?$CI?$AA@"
+// CHECK: @"\01??_C@_01GEODFPGF@?8?$AA@"
+// CHECK: @"\01??_C@_01HNPIGOCE@?$CG?$AA@"
+// CHECK: @"\01??_C@_01FGNFDNOH@?$CF?$AA@"
+// CHECK: @"\01??_C@_01EPMOAMKG@$?$AA@"
+// CHECK: @"\01??_C@_01IPJKGB@?$CD?$AA@"
+// CHECK: @"\01??_C@_01BJJEKLCA@?$CC?$AA@"
+// CHECK: @"\01??_C@_01DCLJPIOD@?$CB?$AA@"
+// CHECK: @"\01??_C@_01CLKCMJKC@?5?$AA@"
+// CHECK: @"\01??_C@_01HDHMODJO@?$BP?$AA@"
+// CHECK: @"\01??_C@_01GKGHNCNP@?$BO?$AA@"
+// CHECK: @"\01??_C@_01EBEKIBBM@?$BN?$AA@"
+// CHECK: @"\01??_C@_01FIFBLAFN@?$BM?$AA@"
+// CHECK: @"\01??_C@_01BHBACGJK@?$BL?$AA@"
+// CHECK: @"\01??_C@_01OALBHNL@?$BK?$AA@"
+// CHECK: @"\01??_C@_01CFCGEEBI@?$BJ?$AA@"
+// CHECK: @"\01??_C@_01DMDNHFFJ@?$BI?$AA@"
+// CHECK: @"\01??_C@_01LLKFGJJG@?$BH?$AA@"
+// CHECK: @"\01??_C@_01KCLOFINH@?$BG?$AA@"
+// CHECK: @"\01??_C@_01IJJDALBE@?$BF?$AA@"
+// CHECK: @"\01??_C@_01JAIIDKFF@?$BE?$AA@"
+// CHECK: @"\01??_C@_01NPMJKMJC@?$BD?$AA@"
+// CHECK: @"\01??_C@_01MGNCJNND@?$BC?$AA@"
+// CHECK: @"\01??_C@_01ONPPMOBA@?$BB?$AA@"
+// CHECK: @"\01??_C@_01PEOEPPFB@?$BA?$AA@"
+// CHECK: @"\01??_C@_01DJLOPBMP@?$AP?$AA@"
+// CHECK: @"\01??_C@_01CAKFMAIO@?$AO?$AA@"
+// CHECK: @"\01??_C@_01LIIJDEN@?$AN?$AA@"
+// CHECK: @"\01??_C@_01BCJDKCAM@?$AM?$AA@"
+// CHECK: @"\01??_C@_01FNNCDEML@?$AL?$AA@"
+// CHECK: @"\01??_C@_01EEMJAFIK@?6?$AA@"
+// CHECK: @"\01??_C@_01GPOEFGEJ@?7?$AA@"
+// CHECK: @"\01??_C@_01HGPPGHAI@?$AI?$AA@"
+// CHECK: @"\01??_C@_01PBGHHLMH@?$AH?$AA@"
+// CHECK: @"\01??_C@_01OIHMEKIG@?$AG?$AA@"
+// CHECK: @"\01??_C@_01MDFBBJEF@?$AF?$AA@"
+// CHECK: @"\01??_C@_01NKEKCIAE@?$AE?$AA@"
+// CHECK: @"\01??_C@_01JFALLOMD@?$AD?$AA@"
+// CHECK: @"\01??_C@_01IMBAIPIC@?$AC?$AA@"
+// CHECK: @"\01??_C@_01KHDNNMEB@?$AB?$AA@"
+// CHECK: @"\01??_C@_01LOCGONAA@?$AA?$AA@"
+
+const wchar_t *wl9 = L"\t";
+const wchar_t *wl10 = L"\n";
+const wchar_t *wl11 = L"\v";
+const wchar_t *wl32 = L" ";
+const wchar_t *wl33 = L"!";
+const wchar_t *wl34 = L"\"";
+const wchar_t *wl35 = L"#";
+const wchar_t *wl36 = L"$";
+const wchar_t *wl37 = L"%";
+const wchar_t *wl38 = L"&";
+const wchar_t *wl39 = L"'";
+const wchar_t *wl40 = L"(";
+const wchar_t *wl41 = L")";
+const wchar_t *wl42 = L"*";
+const wchar_t *wl43 = L"+";
+const wchar_t *wl44 = L",";
+const wchar_t *wl45 = L"-";
+const wchar_t *wl46 = L".";
+const wchar_t *wl47 = L"/";
+const wchar_t *wl48 = L"0";
+const wchar_t *wl49 = L"1";
+const wchar_t *wl50 = L"2";
+const wchar_t *wl51 = L"3";
+const wchar_t *wl52 = L"4";
+const wchar_t *wl53 = L"5";
+const wchar_t *wl54 = L"6";
+const wchar_t *wl55 = L"7";
+const wchar_t *wl56 = L"8";
+const wchar_t *wl57 = L"9";
+const wchar_t *wl58 = L":";
+const wchar_t *wl59 = L";";
+const wchar_t *wl60 = L"<";
+const wchar_t *wl61 = L"=";
+const wchar_t *wl62 = L">";
+const wchar_t *wl63 = L"?";
+const wchar_t *wl64 = L"@";
+const wchar_t *wl65 = L"A";
+const wchar_t *wl66 = L"B";
+const wchar_t *wl67 = L"C";
+const wchar_t *wl68 = L"D";
+const wchar_t *wl69 = L"E";
+const wchar_t *wl70 = L"F";
+const wchar_t *wl71 = L"G";
+const wchar_t *wl72 = L"H";
+const wchar_t *wl73 = L"I";
+const wchar_t *wl74 = L"J";
+const wchar_t *wl75 = L"K";
+const wchar_t *wl76 = L"L";
+const wchar_t *wl77 = L"M";
+const wchar_t *wl78 = L"N";
+const wchar_t *wl79 = L"O";
+const wchar_t *wl80 = L"P";
+const wchar_t *wl81 = L"Q";
+const wchar_t *wl82 = L"R";
+const wchar_t *wl83 = L"S";
+const wchar_t *wl84 = L"T";
+const wchar_t *wl85 = L"U";
+const wchar_t *wl86 = L"V";
+const wchar_t *wl87 = L"W";
+const wchar_t *wl88 = L"X";
+const wchar_t *wl89 = L"Y";
+const wchar_t *wl90 = L"Z";
+const wchar_t *wl91 = L"[";
+const wchar_t *wl92 = L"\\";
+const wchar_t *wl93 = L"]";
+const wchar_t *wl94 = L"^";
+const wchar_t *wl95 = L"_";
+const wchar_t *wl96 = L"`";
+const wchar_t *wl97 = L"a";
+const wchar_t *wl98 = L"b";
+const wchar_t *wl99 = L"c";
+const wchar_t *wl100 = L"d";
+const wchar_t *wl101 = L"e";
+const wchar_t *wl102 = L"f";
+const wchar_t *wl103 = L"g";
+const wchar_t *wl104 = L"h";
+const wchar_t *wl105 = L"i";
+const wchar_t *wl106 = L"j";
+const wchar_t *wl107 = L"k";
+const wchar_t *wl108 = L"l";
+const wchar_t *wl109 = L"m";
+const wchar_t *wl110 = L"n";
+const wchar_t *wl111 = L"o";
+const wchar_t *wl112 = L"p";
+const wchar_t *wl113 = L"q";
+const wchar_t *wl114 = L"r";
+const wchar_t *wl115 = L"s";
+const wchar_t *wl116 = L"t";
+const wchar_t *wl117 = L"u";
+const wchar_t *wl118 = L"v";
+const wchar_t *wl119 = L"w";
+const wchar_t *wl120 = L"x";
+const wchar_t *wl121 = L"y";
+const wchar_t *wl122 = L"z";
+const wchar_t *wl123 = L"{";
+const wchar_t *wl124 = L"|";
+const wchar_t *wl125 = L"}";
+const wchar_t *wl126 = L"~";
+
+// CHECK: @"\01??_C@_13KDLDGPGJ@?$AA?7?$AA?$AA@"
+// CHECK: @"\01??_C@_13LBAGMAIH@?$AA?6?$AA?$AA@"
+// CHECK: @"\01??_C@_13JLKKHOC@?$AA?$AL?$AA?$AA@"
+// CHECK: @"\01??_C@_13HOIJIPNN@?$AA?5?$AA?$AA@"
+// CHECK: @"\01??_C@_13MGDFOILI@?$AA?$CB?$AA?$AA@"
+// CHECK: @"\01??_C@_13NEIAEHFG@?$AA?$CC?$AA?$AA@"
+// CHECK: @"\01??_C@_13GMDMCADD@?$AA?$CD?$AA?$AA@"
+// CHECK: @"\01??_C@_13PBOLBIIK@?$AA$?$AA?$AA@"
+// CHECK: @"\01??_C@_13EJFHHPOP@?$AA?$CF?$AA?$AA@"
+// CHECK: @"\01??_C@_13FLOCNAAB@?$AA?$CG?$AA?$AA@"
+// CHECK: @"\01??_C@_13ODFOLHGE@?$AA?8?$AA?$AA@"
+// CHECK: @"\01??_C@_13LLDNKHDC@?$AA?$CI?$AA?$AA@"
+// CHECK: @"\01??_C@_13DIBMAFH@?$AA?$CJ?$AA?$AA@"
+// CHECK: @"\01??_C@_13BBDEGPLJ@?$AA?$CK?$AA?$AA@"
+// CHECK: @"\01??_C@_13KJIIAINM@?$AA?$CL?$AA?$AA@"
+// CHECK: @"\01??_C@_13DEFPDAGF@?$AA?0?$AA?$AA@"
+// CHECK: @"\01??_C@_13IMODFHAA@?$AA?9?$AA?$AA@"
+// CHECK: @"\01??_C@_13JOFGPIOO@?$AA?4?$AA?$AA@"
+// CHECK: @"\01??_C@_13CGOKJPIL@?$AA?1?$AA?$AA@"
+// CHECK: @"\01??_C@_13COJANIEC@?$AA0?$AA?$AA@"
+// CHECK: @"\01??_C@_13JGCMLPCH@?$AA1?$AA?$AA@"
+// CHECK: @"\01??_C@_13IEJJBAMJ@?$AA2?$AA?$AA@"
+// CHECK: @"\01??_C@_13DMCFHHKM@?$AA3?$AA?$AA@"
+// CHECK: @"\01??_C@_13KBPCEPBF@?$AA4?$AA?$AA@"
+// CHECK: @"\01??_C@_13BJEOCIHA@?$AA5?$AA?$AA@"
+// CHECK: @"\01??_C@_13LPLIHJO@?$AA6?$AA?$AA@"
+// CHECK: @"\01??_C@_13LDEHOAPL@?$AA7?$AA?$AA@"
+// CHECK: @"\01??_C@_13OLCEPAKN@?$AA8?$AA?$AA@"
+// CHECK: @"\01??_C@_13FDJIJHMI@?$AA9?$AA?$AA@"
+// CHECK: @"\01??_C@_13EBCNDICG@?$AA?3?$AA?$AA@"
+// CHECK: @"\01??_C@_13PJJBFPED@?$AA?$DL?$AA?$AA@"
+// CHECK: @"\01??_C@_13GEEGGHPK@?$AA?$DM?$AA?$AA@"
+// CHECK: @"\01??_C@_13NMPKAAJP@?$AA?$DN?$AA?$AA@"
+// CHECK: @"\01??_C@_13MOEPKPHB@?$AA?$DO?$AA?$AA@"
+// CHECK: @"\01??_C@_13HGPDMIBE@?$AA?$DP?$AA?$AA@"
+// CHECK: @"\01??_C@_13EFKPHINO@?$AA?$EA?$AA?$AA@"
+// CHECK: @"\01??_C@_13PNBDBPLL@?$AAA?$AA?$AA@"
+// CHECK: @"\01??_C@_13OPKGLAFF@?$AAB?$AA?$AA@"
+// CHECK: @"\01??_C@_13FHBKNHDA@?$AAC?$AA?$AA@"
+// CHECK: @"\01??_C@_13MKMNOPIJ@?$AAD?$AA?$AA@"
+// CHECK: @"\01??_C@_13HCHBIIOM@?$AAE?$AA?$AA@"
+// CHECK: @"\01??_C@_13GAMECHAC@?$AAF?$AA?$AA@"
+// CHECK: @"\01??_C@_13NIHIEAGH@?$AAG?$AA?$AA@"
+// CHECK: @"\01??_C@_13IABLFADB@?$AAH?$AA?$AA@"
+// CHECK: @"\01??_C@_13DIKHDHFE@?$AAI?$AA?$AA@"
+// CHECK: @"\01??_C@_13CKBCJILK@?$AAJ?$AA?$AA@"
+// CHECK: @"\01??_C@_13JCKOPPNP@?$AAK?$AA?$AA@"
+// CHECK: @"\01??_C@_13PHJMHGG@?$AAL?$AA?$AA@"
+// CHECK: @"\01??_C@_13LHMFKAAD@?$AAM?$AA?$AA@"
+// CHECK: @"\01??_C@_13KFHAAPON@?$AAN?$AA?$AA@"
+// CHECK: @"\01??_C@_13BNMMGIII@?$AAO?$AA?$AA@"
+// CHECK: @"\01??_C@_13BFLGCPEB@?$AAP?$AA?$AA@"
+// CHECK: @"\01??_C@_13KNAKEICE@?$AAQ?$AA?$AA@"
+// CHECK: @"\01??_C@_13LPLPOHMK@?$AAR?$AA?$AA@"
+// CHECK: @"\01??_C@_13HADIAKP@?$AAS?$AA?$AA@"
+// CHECK: @"\01??_C@_13JKNELIBG@?$AAT?$AA?$AA@"
+// CHECK: @"\01??_C@_13CCGINPHD@?$AAU?$AA?$AA@"
+// CHECK: @"\01??_C@_13DANNHAJN@?$AAV?$AA?$AA@"
+// CHECK: @"\01??_C@_13IIGBBHPI@?$AAW?$AA?$AA@"
+// CHECK: @"\01??_C@_13NAACAHKO@?$AAX?$AA?$AA@"
+// CHECK: @"\01??_C@_13GILOGAML@?$AAY?$AA?$AA@"
+// CHECK: @"\01??_C@_13HKALMPCF@?$AAZ?$AA?$AA@"
+// CHECK: @"\01??_C@_13MCLHKIEA@?$AA?$FL?$AA?$AA@"
+// CHECK: @"\01??_C@_13FPGAJAPJ@?$AA?2?$AA?$AA@"
+// CHECK: @"\01??_C@_13OHNMPHJM@?$AA?$FN?$AA?$AA@"
+// CHECK: @"\01??_C@_13PFGJFIHC@?$AA?$FO?$AA?$AA@"
+// CHECK: @"\01??_C@_13ENNFDPBH@?$AA_?$AA?$AA@"
+// CHECK: @"\01??_C@_13OFJNNHOA@?$AA?$GA?$AA?$AA@"
+// CHECK: @"\01??_C@_13FNCBLAIF@?$AAa?$AA?$AA@"
+// CHECK: @"\01??_C@_13EPJEBPGL@?$AAb?$AA?$AA@"
+// CHECK: @"\01??_C@_13PHCIHIAO@?$AAc?$AA?$AA@"
+// CHECK: @"\01??_C@_13GKPPEALH@?$AAd?$AA?$AA@"
+// CHECK: @"\01??_C@_13NCEDCHNC@?$AAe?$AA?$AA@"
+// CHECK: @"\01??_C@_13MAPGIIDM@?$AAf?$AA?$AA@"
+// CHECK: @"\01??_C@_13HIEKOPFJ@?$AAg?$AA?$AA@"
+// CHECK: @"\01??_C@_13CACJPPAP@?$AAh?$AA?$AA@"
+// CHECK: @"\01??_C@_13JIJFJIGK@?$AAi?$AA?$AA@"
+// CHECK: @"\01??_C@_13IKCADHIE@?$AAj?$AA?$AA@"
+// CHECK: @"\01??_C@_13DCJMFAOB@?$AAk?$AA?$AA@"
+// CHECK: @"\01??_C@_13KPELGIFI@?$AAl?$AA?$AA@"
+// CHECK: @"\01??_C@_13BHPHAPDN@?$AAm?$AA?$AA@"
+// CHECK: @"\01??_C@_13FECKAND@?$AAn?$AA?$AA@"
+// CHECK: @"\01??_C@_13LNPOMHLG@?$AAo?$AA?$AA@"
+// CHECK: @"\01??_C@_13LFIEIAHP@?$AAp?$AA?$AA@"
+// CHECK: @"\01??_C@_13NDIOHBK@?$AAq?$AA?$AA@"
+// CHECK: @"\01??_C@_13BPINEIPE@?$AAr?$AA?$AA@"
+// CHECK: @"\01??_C@_13KHDBCPJB@?$AAs?$AA?$AA@"
+// CHECK: @"\01??_C@_13DKOGBHCI@?$AAt?$AA?$AA@"
+// CHECK: @"\01??_C@_13ICFKHAEN@?$AAu?$AA?$AA@"
+// CHECK: @"\01??_C@_13JAOPNPKD@?$AAv?$AA?$AA@"
+// CHECK: @"\01??_C@_13CIFDLIMG@?$AAw?$AA?$AA@"
+// CHECK: @"\01??_C@_13HADAKIJA@?$AAx?$AA?$AA@"
+// CHECK: @"\01??_C@_13MIIMMPPF@?$AAy?$AA?$AA@"
+// CHECK: @"\01??_C@_13NKDJGABL@?$AAz?$AA?$AA@"
+// CHECK: @"\01??_C@_13GCIFAHHO@?$AA?$HL?$AA?$AA@"
+// CHECK: @"\01??_C@_13PPFCDPMH@?$AA?$HM?$AA?$AA@"
+// CHECK: @"\01??_C@_13EHOOFIKC@?$AA?$HN?$AA?$AA@"
+// CHECK: @"\01??_C@_13FFFLPHEM@?$AA?$HO?$AA?$AA@"
+
+const char *LongASCIIString = "012345678901234567890123456789ABCDEF";
+// CHECK: @"\01??_C@_0CF@LABBIIMO@012345678901234567890123456789AB@"
+const wchar_t *LongWideString = L"012345678901234567890123456789ABCDEF";
+// CHECK: @"\01??_C@_1EK@KFPEBLPK@?$AA0?$AA1?$AA2?$AA3?$AA4?$AA5?$AA6?$AA7?$AA8?$AA9?$AA0?$AA1?$AA2?$AA3?$AA4?$AA5?$AA6?$AA7?$AA8?$AA9?$AA0?$AA1?$AA2?$AA3?$AA4?$AA5?$AA6?$AA7?$AA8?$AA9?$AAA?$AAB@"
+const wchar_t *UnicodeLiteral = L"\ud7ff";
+// CHECK: @"\01??_C@_13IIHIAFKH@?W?$PP?$AA?$AA@"
diff --git a/test/CodeGenCXX/mangle-ms-template-callback.cpp b/test/CodeGenCXX/mangle-ms-template-callback.cpp
index 687814875132..1a8f82fc8256 100644
--- a/test/CodeGenCXX/mangle-ms-template-callback.cpp
+++ b/test/CodeGenCXX/mangle-ms-template-callback.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fblocks -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s
+// RUN: %clang_cc1 -fblocks -emit-llvm %s -o - -triple=i386-pc-win32 | FileCheck %s
template<typename Signature>
class C;
@@ -70,3 +70,20 @@ void call_bar() {
// CHECK: "\01??$bar@P_EAHH@Z@@YAXP_EAHH@Z@Z"
// FYI blocks are not present in MSVS, so we're free to choose the spec.
}
+
+template <void (*Fn)()> void WrapFnPtr() { Fn(); }
+template <void (&Fn)()> void WrapFnRef() { Fn(); }
+struct Thing {
+ static void VoidStaticMethod();
+};
+void VoidFn();
+void CallWrapper() {
+ WrapFnPtr<VoidFn>();
+ WrapFnRef<VoidFn>();
+ WrapFnPtr<Thing::VoidStaticMethod>();
+ WrapFnRef<Thing::VoidStaticMethod>();
+}
+// CHECK: call {{.*}} @"\01??$WrapFnPtr@$1?VoidFn@@YAXXZ@@YAXXZ"
+// CHECK: call {{.*}} @"\01??$WrapFnRef@$1?VoidFn@@YAXXZ@@YAXXZ"
+// CHECK: call {{.*}} @"\01??$WrapFnPtr@$1?VoidStaticMethod@Thing@@SAXXZ@@YAXXZ"
+// CHECK: call {{.*}} @"\01??$WrapFnRef@$1?VoidStaticMethod@Thing@@SAXXZ@@YAXXZ"
diff --git a/test/CodeGenCXX/mangle-ms-templates-memptrs-2.cpp b/test/CodeGenCXX/mangle-ms-templates-memptrs-2.cpp
new file mode 100644
index 000000000000..e2cbe15dfa9f
--- /dev/null
+++ b/test/CodeGenCXX/mangle-ms-templates-memptrs-2.cpp
@@ -0,0 +1,45 @@
+// RUN: %clang_cc1 -Wno-microsoft -fms-extensions -fno-rtti -std=c++11 -emit-llvm %s -o - -triple=i386-pc-win32 | FileCheck %s
+
+template <typename T, int (T::*)() = nullptr>
+struct J {};
+
+struct __single_inheritance M;
+J<M> m;
+// CHECK-DAG: @"\01?m@@3U?$J@UM@@$0A@@@A"
+
+struct __multiple_inheritance N;
+J<N> n;
+// CHECK-DAG: @"\01?n@@3U?$J@UN@@$HA@@@A"
+
+struct __virtual_inheritance O;
+J<O> o;
+// CHECK-DAG: @"\01?o@@3U?$J@UO@@$IA@A@@@A"
+
+struct P;
+J<P> p;
+// CHECK-DAG: @"\01?p@@3U?$J@UP@@$JA@A@?0@@A"
+
+#pragma pointers_to_members(full_generality, virtual_inheritance)
+
+struct S {
+ int a, b;
+ void f();
+ virtual void g();
+};
+
+struct GeneralBase {
+ virtual void h();
+};
+struct MostGeneral : S, virtual GeneralBase {
+ virtual void h();
+};
+template <void (MostGeneral::*MP)()>
+struct ClassTemplate {
+ ClassTemplate() {}
+};
+
+template struct ClassTemplate<&MostGeneral::h>;
+
+// Test that we mangle in the vbptr offset, which is 12 here.
+//
+// CHECK: define weak_odr x86_thiscallcc %struct.ClassTemplate* @"\01??0?$ClassTemplate@$J??_9MostGeneral@@$BA@AEA@M@3@@QAE@XZ"
diff --git a/test/CodeGenCXX/mangle-ms-templates-memptrs.cpp b/test/CodeGenCXX/mangle-ms-templates-memptrs.cpp
new file mode 100644
index 000000000000..803cac3748b1
--- /dev/null
+++ b/test/CodeGenCXX/mangle-ms-templates-memptrs.cpp
@@ -0,0 +1,143 @@
+// RUN: %clang_cc1 -Wno-microsoft -fno-rtti -std=c++11 -emit-llvm %s -o - -triple=i386-pc-win32 | FileCheck %s
+
+struct U;
+static_assert(sizeof(void (U::*)()) == 2 * sizeof(void*) + 2 * sizeof(int), "");
+
+struct A { int a; };
+struct B { int b; };
+struct I { union { struct { int a, b; }; }; };
+
+struct S { int a, b; void f(); virtual void g(); };
+struct M : A, B { int a, b; void f(); virtual void g(); };
+struct V : virtual A { int a, b; void f(); virtual void g(); };
+struct U { int a, b; void f(); virtual void g(); };
+
+struct C { virtual void f(); };
+struct D { virtual void g(); };
+struct O : C, D { virtual void g(); }; // override of non-primary
+
+// Test data member pointers.
+template <typename T, int T::*F>
+int ReadField(T &o) {
+ return F ? o.*F : 0;
+}
+
+// Redeclare some of the classes so that the implicit attribute goes on the most
+// recent redeclaration rather than the definition.
+struct V;
+
+void ReadFields() {
+ A a;
+ I i;
+ S s;
+ M m;
+ V v;
+ U u;
+ ReadField<S, &S::a>(s);
+ ReadField<M, &M::a>(m);
+ ReadField<V, &V::a>(v);
+ ReadField<U, &U::a>(u);
+ ReadField<S, &S::b>(s);
+ ReadField<M, &M::b>(m);
+ ReadField<V, &V::b>(v);
+ ReadField<U, &U::b>(u);
+ ReadField<S, nullptr>(s);
+ ReadField<M, nullptr>(m);
+ ReadField<V, nullptr>(v);
+ ReadField<U, nullptr>(u);
+
+ // Non-polymorphic null data memptr vs first field memptr.
+ ReadField<A, &A::a>(a);
+ ReadField<A, nullptr>(a);
+
+ // Indirect fields injected from anonymous unions and structs
+ ReadField<I, &I::a>(i);
+ ReadField<I, &I::b>(i);
+}
+
+// CHECK-LABEL: define {{.*}}ReadFields
+// CHECK: call {{.*}} @"\01??$ReadField@US@@$03@@YAHAAUS@@@Z"
+// CHECK: call {{.*}} @"\01??$ReadField@UM@@$0M@@@YAHAAUM@@@Z"
+// CHECK: call {{.*}} @"\01??$ReadField@UV@@$F7A@@@YAHAAUV@@@Z"
+// CHECK: call {{.*}} @"\01??$ReadField@UU@@$G3A@A@@@YAHAAUU@@@Z"
+// CHECK: call {{.*}} @"\01??$ReadField@US@@$07@@YAHAAUS@@@Z"
+// CHECK: call {{.*}} @"\01??$ReadField@UM@@$0BA@@@YAHAAUM@@@Z"
+// CHECK: call {{.*}} @"\01??$ReadField@UV@@$FM@A@@@YAHAAUV@@@Z"
+// CHECK: call {{.*}} @"\01??$ReadField@UU@@$G7A@A@@@YAHAAUU@@@Z"
+
+// MSVC mangles null member pointers in function templates wrong, but it gets
+// them right in class templates.
+// CHECK: call {{.*}} @"\01??$ReadField@US@@$0A@@@YAHAAUS@@@Z"
+// CHECK: call {{.*}} @"\01??$ReadField@UM@@$0A@@@YAHAAUM@@@Z"
+// CHECK: call {{.*}} @"\01??$ReadField@UV@@$FA@?0@@YAHAAUV@@@Z"
+// CHECK: call {{.*}} @"\01??$ReadField@UU@@$GA@A@?0@@YAHAAUU@@@Z"
+
+// Non-polymorphic null data memptr vs first field memptr. MSVC mangles these
+// the same.
+// CHECK: call {{.*}} @"\01??$ReadField@UA@@$0A@@@YAHAAUA@@@Z"
+// CHECK: call {{.*}} @"\01??$ReadField@UA@@$0?0@@YAHAAUA@@@Z"
+
+// Indirect fields are handled as-if they were simply members of their enclosing
+// record.
+// CHECK: call {{.*}} @"\01??$ReadField@UI@@$0A@@@YAHAAUI@@@Z"
+// CHECK: call {{.*}} @"\01??$ReadField@UI@@$03@@YAHAAUI@@@Z"
+
+// Test member function pointers.
+template <typename T, void (T::*MFP)()>
+void CallMethod(T &o) {
+ (o.*MFP)();
+}
+
+void CallMethods() {
+ S s;
+ M m;
+ V v;
+ U u;
+ O o;
+
+ // Non-virtual methods.
+ CallMethod<S, &S::f>(s);
+ CallMethod<M, &M::f>(m);
+ CallMethod<V, &V::f>(v);
+ CallMethod<U, &U::f>(u);
+
+ // Virtual methods requiring thunk mangling.
+ CallMethod<S, &S::g>(s);
+ CallMethod<M, &M::g>(m);
+ CallMethod<V, &V::g>(v);
+ CallMethod<U, &U::g>(u);
+
+ // A member pointer for a non-primary vbase will have a non-zero this
+ // adjustment.
+ CallMethod<O, &O::g>(o);
+
+ // Null member pointers.
+ CallMethod<S, nullptr>(s);
+ CallMethod<M, nullptr>(m);
+ CallMethod<V, nullptr>(v);
+ CallMethod<U, nullptr>(u);
+}
+
+// CHECK-LABEL: define {{.*}}CallMethods
+// CHECK: call {{.*}} @"\01??$CallMethod@US@@$1?f@1@QAEXXZ@@YAXAAUS@@@Z"
+// CHECK: call {{.*}} @"\01??$CallMethod@UM@@$H?f@1@QAEXXZA@@@YAXAAUM@@@Z"
+// CHECK: call {{.*}} @"\01??$CallMethod@UV@@$I?f@1@QAEXXZA@A@@@YAXAAUV@@@Z"
+// CHECK: call {{.*}} @"\01??$CallMethod@UU@@$J?f@1@QAEXXZA@A@A@@@YAXAAUU@@@Z"
+
+// PR17034: MSVC reuses the same thunk for every virtual g method because they
+// are all at vftable offset zero. They then mangle the name of the first thunk
+// created into the name of the template instantiation, which is definitely a
+// bug. We don't follow them here. Instead of ?_91@ backref below, they would
+// get ?_9S@@ in every instantiation after the first.
+
+// CHECK: call {{.*}} @"\01??$CallMethod@US@@$1??_91@$BA@AE@@YAXAAUS@@@Z"
+// CHECK: call {{.*}} @"\01??$CallMethod@UM@@$H??_91@$BA@AEA@@@YAXAAUM@@@Z"
+// CHECK: call {{.*}} @"\01??$CallMethod@UV@@$I??_91@$BA@AEA@A@@@YAXAAUV@@@Z"
+// CHECK: call {{.*}} @"\01??$CallMethod@UU@@$J??_91@$BA@AEA@A@A@@@YAXAAUU@@@Z"
+
+// CHECK: call {{.*}} @"\01??$CallMethod@UO@@$H??_91@$BA@AE3@@YAXAAUO@@@Z"
+
+// CHECK: call {{.*}} @"\01??$CallMethod@US@@$0A@@@YAXAAUS@@@Z"
+// CHECK: call {{.*}} @"\01??$CallMethod@UM@@$0A@@@YAXAAUM@@@Z"
+// CHECK: call {{.*}} @"\01??$CallMethod@UV@@$0A@@@YAXAAUV@@@Z"
+// CHECK: call {{.*}} @"\01??$CallMethod@UU@@$0A@@@YAXAAUU@@@Z"
diff --git a/test/CodeGenCXX/mangle-ms-templates.cpp b/test/CodeGenCXX/mangle-ms-templates.cpp
index 514f5739ffd5..31fda2046c4b 100644
--- a/test/CodeGenCXX/mangle-ms-templates.cpp
+++ b/test/CodeGenCXX/mangle-ms-templates.cpp
@@ -1,5 +1,5 @@
-// 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
+// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -fms-extensions -fdelayed-template-parsing -triple=i386-pc-win32 | FileCheck %s
+// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -fms-extensions -fdelayed-template-parsing -triple=x86_64-pc-win32 | FileCheck -check-prefix X64 %s
template<typename T>
class Class {
@@ -262,3 +262,17 @@ void CallFunctionDefinedWithInjectedName() {
FunctionDefinedWithInjectedName(TypeWithFriendDefinition<int>());
}
// CHECK: @"\01?FunctionDefinedWithInjectedName@@YAXU?$TypeWithFriendDefinition@H@@@Z"
+
+// We need to be able to feed GUIDs through a couple rounds of template
+// substitution.
+template <const _GUID *G>
+struct UUIDType3 {
+ void foo() {}
+};
+template <const _GUID *G>
+struct UUIDType4 : UUIDType3<G> {
+ void bar() { UUIDType4::foo(); }
+};
+template struct UUIDType4<&__uuidof(uuid)>;
+// CHECK: "\01?bar@?$UUIDType4@$1?_GUID_12345678_1234_1234_1234_1234567890ab@@3U__s_GUID@@B@@QAEXXZ"
+// CHECK: "\01?foo@?$UUIDType3@$1?_GUID_12345678_1234_1234_1234_1234567890ab@@3U__s_GUID@@B@@QAEXXZ"
diff --git a/test/CodeGenCXX/mangle-ms-vector-types.cpp b/test/CodeGenCXX/mangle-ms-vector-types.cpp
index 64cb7250a41f..aca492918a1e 100644
--- a/test/CodeGenCXX/mangle-ms-vector-types.cpp
+++ b/test/CodeGenCXX/mangle-ms-vector-types.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fms-extensions -ffreestanding -target-feature +avx -emit-llvm %s -o - -cxx-abi microsoft -triple=i686-pc-win32 | FileCheck %s
+// RUN: %clang_cc1 -fms-extensions -ffreestanding -target-feature +avx -emit-llvm %s -o - -triple=i686-pc-win32 | FileCheck %s
#include <xmmintrin.h>
#include <emmintrin.h>
diff --git a/test/CodeGenCXX/mangle-ms.cpp b/test/CodeGenCXX/mangle-ms.cpp
index 68ec2b3baf68..3285c98546ec 100644
--- a/test/CodeGenCXX/mangle-ms.cpp
+++ b/test/CodeGenCXX/mangle-ms.cpp
@@ -1,5 +1,5 @@
-// 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
+// RUN: %clang_cc1 -fblocks -emit-llvm %s -o - -triple=i386-pc-win32 -std=c++98 | FileCheck %s
+// RUN: %clang_cc1 -fblocks -emit-llvm %s -o - -triple=x86_64-pc-win32 -std=c++98| FileCheck -check-prefix X64 %s
int a;
// CHECK-DAG: @"\01?a@@3HA"
@@ -95,10 +95,18 @@ extern int * const h1 = &a;
// CHECK-DAG: @"\01?h1@@3QAHA"
extern const int * const h2 = &a;
// CHECK-DAG: @"\01?h2@@3QBHB"
+extern int * const __restrict h3 = &a;
+// CHECK-DAG: @"\01?h3@@3QIAHIA"
+// X64-DAG: @"\01?h3@@3QEIAHEIA"
int i[10][20];
// CHECK-DAG: @"\01?i@@3PAY0BE@HA"
+typedef int (*FunT)(int, int);
+FunT FunArr[10][20];
+// CHECK-DAG: @"\01?FunArr@@3PAY0BE@P6AHHH@ZA"
+// X64-DAG: @"\01?FunArr@@3PAY0BE@P6AHHH@ZA"
+
int (__stdcall *j)(signed char, unsigned char);
// CHECK-DAG: @"\01?j@@3P6GHCE@ZA"
@@ -357,10 +365,3 @@ void TypedefNewDelete::operator delete[](void *) { }
// 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 249ec2e99b69..6faf6226efd2 100644
--- a/test/CodeGenCXX/mangle-neon-vectors.cpp
+++ b/test/CodeGenCXX/mangle-neon-vectors.cpp
@@ -1,10 +1,18 @@
-// RUN: %clang_cc1 -triple arm-none-linux-gnueabi -target-feature +neon %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -triple armv7-apple-ios -target-feature +neon %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -triple arm64-apple-ios -target-feature +neon %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -triple arm64-linux-gnu -target-feature +neon %s -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-AARCH64
typedef float float32_t;
+typedef double float64_t;
typedef __fp16 float16_t;
+#if defined(__aarch64__)
+typedef unsigned char poly8_t;
+typedef unsigned short poly16_t;
+#else
typedef signed char poly8_t;
typedef short poly16_t;
-typedef unsigned long long uint64_t;
+#endif
+typedef unsigned __INT64_TYPE__ uint64_t;
typedef __attribute__((neon_vector_type(2))) int int32x2_t;
typedef __attribute__((neon_vector_type(4))) int int32x4_t;
@@ -14,26 +22,53 @@ 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(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;
+#ifdef __aarch64__
+typedef __attribute__((neon_vector_type(2))) float64_t float64x2_t;
+#endif
+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
+// CHECK-AARCH64: 11__Int32x2_t
void f1(int32x2_t v) { }
+
// CHECK: 17__simd128_int32_t
+// CHECK-AARCH64: 11__Int32x4_t
void f2(int32x4_t v) { }
+
// CHECK: 17__simd64_uint64_t
+// CHECK-AARCH64: 12__Uint64x1_t
void f3(uint64x1_t v) { }
+
// CHECK: 18__simd128_uint64_t
+// CHECK-AARCH64: 12__Uint64x2_t
void f4(uint64x2_t v) { }
+
// CHECK: 18__simd64_float32_t
+// CHECK-AARCH64: 13__Float32x2_t
void f5(float32x2_t v) { }
+
// CHECK: 19__simd128_float32_t
+// CHECK-AARCH64: 13__Float32x4_t
void f6(float32x4_t v) { }
+
// CHECK: 18__simd64_float16_t
+// CHECK-AARCH64: 13__Float16x4_t
void f7(float16x4_t v) {}
+
// CHECK: 19__simd128_float16_t
+// CHECK-AARCH64: 13__Float16x8_t
void f8(float16x8_t v) {}
+
// CHECK: 17__simd128_poly8_t
+// CHECK-AARCH64: 12__Poly8x16_t
void f9(poly8x16_t v) {}
+
// CHECK: 18__simd128_poly16_t
+// CHECK-AARCH64: 12__Poly16x8_t
void f10(poly16x8_t v) {}
+
+#ifdef __aarch64__
+// CHECK-AARCH64: 13__Float64x2_t
+void f11(float64x2_t v) { }
+#endif
diff --git a/test/CodeGenCXX/mangle-nullptr-arg.cpp b/test/CodeGenCXX/mangle-nullptr-arg.cpp
index b55ea6dd2dd4..66ed7e5cfe34 100644
--- a/test/CodeGenCXX/mangle-nullptr-arg.cpp
+++ b/test/CodeGenCXX/mangle-nullptr-arg.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -std=c++11 -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck %s
template<int *ip> struct IP {};
diff --git a/test/CodeGenCXX/mangle-std-externc.cpp b/test/CodeGenCXX/mangle-std-externc.cpp
index a478dee4a42c..f0c7d69eed46 100644
--- a/test/CodeGenCXX/mangle-std-externc.cpp
+++ b/test/CodeGenCXX/mangle-std-externc.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 %s -DNS=std -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-STD
-// RUN: %clang_cc1 %s -DNS=n -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-N
+// RUN: %clang_cc1 %s -DNS=std -emit-llvm -triple %itanium_abi_triple -o - | FileCheck %s --check-prefix=CHECK-STD
+// RUN: %clang_cc1 %s -DNS=n -emit-llvm -triple %itanium_abi_triple -o - | FileCheck %s --check-prefix=CHECK-N
// _ZNSt1DISt1CE1iE = std::D<std::C>::i
// CHECK-STD: @_ZNSt1DISt1CE1iE =
diff --git a/test/CodeGenCXX/mangle-subst-std.cpp b/test/CodeGenCXX/mangle-subst-std.cpp
index 6277c7af21c4..678956e11182 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-LABEL: define void @_ZNSt1AC1Ev(%"struct.std::A"* %this) unnamed_addr
// CHECK-LABEL: define void @_ZNSt1AC2Ev(%"struct.std::A"* %this) unnamed_addr
+ // CHECK-LABEL: define void @_ZNSt1AC1Ev(%"struct.std::A"* %this) unnamed_addr
A::A() { }
};
diff --git a/test/CodeGenCXX/mangle-template.cpp b/test/CodeGenCXX/mangle-template.cpp
index 3b7f3027f6c2..998096a57be4 100644
--- a/test/CodeGenCXX/mangle-template.cpp
+++ b/test/CodeGenCXX/mangle-template.cpp
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -verify -Wno-return-type -Wno-main -std=c++11 -emit-llvm -triple %itanium_abi_triple -o - %s | FileCheck %s
+// expected-no-diagnostics
+
namespace test1 {
int x;
template <int& D> class T { };
@@ -145,7 +147,7 @@ namespace test10 {
}
}
-// Report from Jason Merrill on cxx-abi-dev, 2012.01.04.
+// Report from cxx-abi-dev, 2012.01.04.
namespace test11 {
int cmp(char a, char b);
template <typename T, int (*cmp)(T, T)> struct A {};
@@ -156,7 +158,7 @@ namespace test11 {
namespace test12 {
// Make sure we can mangle non-type template args with internal linkage.
- static int f();
+ static int f() {}
const int n = 10;
template<typename T, T v> void test() {}
void use() {
@@ -182,3 +184,25 @@ namespace test13 {
template short returnShort<-32768>();
// CHECK: @_ZN6test1311returnShortILsn32768EEEsv()
}
+
+namespace test14 {
+ template <typename> inline int inl(bool b) {
+ if (b) {
+ static struct {
+ int field;
+ } a;
+ // CHECK: @_ZZN6test143inlIvEEibE1a
+
+ return a.field;
+ } else {
+ static struct {
+ int field;
+ } a;
+ // CHECK: @_ZZN6test143inlIvEEibE1a_0
+
+ return a.field;
+ }
+ }
+
+ int call(bool b) { return inl<void>(b); }
+}
diff --git a/test/CodeGenCXX/mangle-windows.cpp b/test/CodeGenCXX/mangle-windows.cpp
index c087616875c7..85644475ddf5 100644
--- a/test/CodeGenCXX/mangle-windows.cpp
+++ b/test/CodeGenCXX/mangle-windows.cpp
@@ -1,5 +1,5 @@
-// 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-pc-win32 | \
+// RUN: FileCheck --check-prefix=WIN %s
//
// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-mingw32 | \
// RUN: FileCheck --check-prefix=ITANIUM %s
diff --git a/test/CodeGenCXX/mangle.cpp b/test/CodeGenCXX/mangle.cpp
index d836f36c1818..9bdac7f17289 100644
--- a/test/CodeGenCXX/mangle.cpp
+++ b/test/CodeGenCXX/mangle.cpp
@@ -216,9 +216,9 @@ struct S7 {
};
// PR5139
-// CHECK: @_ZN2S7C1Ev
// CHECK: @_ZN2S7C2Ev
// CHECK: @_ZN2S7Ut_C1Ev
+// CHECK: @_ZN2S7C1Ev
S7::S7() {}
// PR5063
@@ -280,13 +280,13 @@ struct Ops {
void *v;
};
-// CHECK-LABEL: define %struct.Ops* @_ZN3OpsplERKS_
+// CHECK-LABEL: define dereferenceable({{[0-9]+}}) %struct.Ops* @_ZN3OpsplERKS_
Ops& Ops::operator+(const Ops&) { return *this; }
-// CHECK-LABEL: define %struct.Ops* @_ZN3OpsmiERKS_
+// CHECK-LABEL: define dereferenceable({{[0-9]+}}) %struct.Ops* @_ZN3OpsmiERKS_
Ops& Ops::operator-(const Ops&) { return *this; }
-// CHECK-LABEL: define %struct.Ops* @_ZN3OpsanERKS_
+// CHECK-LABEL: define dereferenceable({{[0-9]+}}) %struct.Ops* @_ZN3OpsanERKS_
Ops& Ops::operator&(const Ops&) { return *this; }
-// CHECK-LABEL: define %struct.Ops* @_ZN3OpsmlERKS_
+// CHECK-LABEL: define dereferenceable({{[0-9]+}}) %struct.Ops* @_ZN3OpsmlERKS_
Ops& Ops::operator*(const Ops&) { return *this; }
// PR5861
@@ -899,7 +899,7 @@ namespace test39 {
}
namespace test40 {
- // CHECK: i32* @_ZZN6test401fEvE1a_0
+ // CHECK: i32* {{.*}} @_ZZN6test401fEvE1a_0
void h(int&);
inline void f() {
if (0) {
@@ -951,3 +951,43 @@ namespace test44 {
}
// CHECK-LABEL: define linkonce_odr void @_ZN6test443foo3barEv(%"struct.test44::foo"* %this)
}
+
+namespace test45 {
+ struct S {
+ enum e {};
+ };
+ template <typename T>
+ void f(enum T::e *) {}
+ template void f<S>(S::e *);
+ // CHECK-LABEL: define weak_odr void @_ZN6test451fINS_1SEEEvPTeNT_1eE(i32*)
+}
+
+namespace test46 {
+ struct S {
+ struct s {};
+ };
+ template <typename T>
+ void f(struct T::s *) {}
+ template void f<S>(S::s *);
+ // CHECK-LABEL: define weak_odr void @_ZN6test461fINS_1SEEEvPTsNT_1sE(%"struct.test46::S::s"*)
+}
+
+namespace test47 {
+ struct S {
+ class c {};
+ };
+ template <typename T>
+ void f(class T::c *) {}
+ template void f<S>(S::c *);
+ // CHECK-LABEL: define weak_odr void @_ZN6test471fINS_1SEEEvPTsNT_1cE(%"class.test47::S::c"*)
+}
+
+namespace test48 {
+ struct S {
+ union u {};
+ };
+ template <typename T>
+ void f(union T::u *) {}
+ template void f<S>(S::u *);
+ // CHECK-LABEL: define weak_odr void @_ZN6test481fINS_1SEEEvPTuNT_1uE(%"union.test48::S::u"*)
+}
diff --git a/test/CodeGenCXX/member-alignment.cpp b/test/CodeGenCXX/member-alignment.cpp
index 78026d4e0419..43ed5e28e884 100644
--- a/test/CodeGenCXX/member-alignment.cpp
+++ b/test/CodeGenCXX/member-alignment.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple %s -o - | FileCheck %s
// rdar://7268289
diff --git a/test/CodeGenCXX/member-function-pointer-calls.cpp b/test/CodeGenCXX/member-function-pointer-calls.cpp
index 99162ebd5863..67417ef04693 100644
--- a/test/CodeGenCXX/member-function-pointer-calls.cpp
+++ b/test/CodeGenCXX/member-function-pointer-calls.cpp
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -O3 -o - | FileCheck %s
+// RUN: %clang_cc1 %s -triple=x86_64-windows-gnu -emit-llvm -o - | FileCheck %s -check-prefix MINGW64
struct A {
virtual int vf1() { return 1; }
virtual int vf2() { return 2; }
@@ -10,6 +11,8 @@ int f(A* a, int (A::*fp)()) {
// CHECK-LABEL: define i32 @_Z2g1v()
// CHECK: ret i32 1
+// MINGW64-LABEL: define i32 @_Z2g1v()
+// MINGW64: call i32 @_Z1fP1AMS_FivE(%struct.A* %{{.*}}, { i64, i64 }* %{{.*}})
int g1() {
A a;
return f(&a, &A::vf1);
@@ -17,6 +20,8 @@ int g1() {
// CHECK-LABEL: define i32 @_Z2g2v()
// CHECK: ret i32 2
+// MINGW64-LABEL: define i32 @_Z2g2v()
+// MINGW64: call i32 @_Z1fP1AMS_FivE(%struct.A* %{{.*}}, { i64, i64 }* %{{.*}})
int g2() {
A a;
return f(&a, &A::vf2);
diff --git a/test/CodeGenCXX/member-init-anon-union.cpp b/test/CodeGenCXX/member-init-anon-union.cpp
index bfe1667c8c6c..b488fa763d64 100644
--- a/test/CodeGenCXX/member-init-anon-union.cpp
+++ b/test/CodeGenCXX/member-init-anon-union.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -std=c++11 -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -std=c++11 -triple x86_64-linux-gnu -emit-llvm -o - | FileCheck %s
// PR10531.
@@ -21,12 +21,42 @@ int g() {
int a;
int b = 81;
};
- // CHECK: define {{.*}}_Z1gv
+ // CHECK-LABEL: define {{.*}}_Z1gv
// CHECK-NOT: }
// CHECK: call {{.*}}@"[[CONSTRUCT_LOCAL:.*]]C1Ev"
return b;
}
+struct A {
+ A();
+};
+union B {
+ int k;
+ struct {
+ A x;
+ int y = 123;
+ };
+ B() {}
+ B(int n) : k(n) {}
+};
+
+B b1;
+B b2(0);
+
+
+// CHECK-LABEL: define {{.*}} @_ZN1BC2Ei(
+// CHECK-NOT: call void @_ZN1AC1Ev(
+// CHECK-NOT: store i32 123,
+// CHECK: store i32 %
+// CHECK-NOT: call void @_ZN1AC1Ev(
+// CHECK-NOT: store i32 123,
+// CHECK: }
+
+// CHECK-LABEL: define {{.*}} @_ZN1BC2Ev(
+// CHECK: call void @_ZN1AC1Ev(
+// CHECK: store i32 123,
+// CHECK: }
+
// CHECK: define {{.*}}@"[[CONSTRUCT_LOCAL]]C2Ev"
// CHECK-NOT: }
diff --git a/test/CodeGenCXX/member-templates.cpp b/test/CodeGenCXX/member-templates.cpp
index c72dd6e5f528..93d36ff4750a 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-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
+// CHECK-LABEL: define weak_odr void @_ZN1BC1IiEET_(%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
index 7407efed2f9d..c8477f4cbdd3 100644
--- a/test/CodeGenCXX/microsoft-abi-alignment-fail.cpp
+++ b/test/CodeGenCXX/microsoft-abi-alignment-fail.cpp
@@ -1,10 +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
+// RUN: %clang_cc1 -fno-rtti -emit-llvm -triple=i686-pc-win32 -o - %s 2>/dev/null | FileCheck %s
+// RUN: %clang_cc1 -fno-rtti -emit-llvm -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 }
+// CHECK: %struct.A = type <{ i32*, %struct.B }>
+// CHECK-X64: %struct.A = type { i32*, %struct.B }
diff --git a/test/CodeGenCXX/microsoft-abi-arg-order.cpp b/test/CodeGenCXX/microsoft-abi-arg-order.cpp
new file mode 100644
index 000000000000..b47508b302d1
--- /dev/null
+++ b/test/CodeGenCXX/microsoft-abi-arg-order.cpp
@@ -0,0 +1,74 @@
+// RUN: %clang_cc1 -mconstructor-aliases -std=c++11 -fexceptions -emit-llvm %s -o - -triple=i386-pc-win32 | FileCheck %s -check-prefix=X86
+// RUN: %clang_cc1 -mconstructor-aliases -std=c++11 -fexceptions -emit-llvm %s -o - -triple=x86_64-pc-win32 | FileCheck %s -check-prefix=X64
+
+struct A {
+ A(int a);
+ A(const A &o);
+ ~A();
+ int a;
+};
+
+void foo(A a, A b, A c) {
+}
+
+// Order of destruction should be left to right.
+//
+// X86-LABEL: define void @"\01?foo@@YAXUA@@00@Z"
+// X86: ([[argmem_ty:<{ %struct.A, %struct.A, %struct.A }>]]* inalloca)
+// X86: %[[a:[^ ]*]] = getelementptr inbounds [[argmem_ty]]* %0, i32 0, i32 0
+// X86: %[[b:[^ ]*]] = getelementptr inbounds [[argmem_ty]]* %0, i32 0, i32 1
+// X86: %[[c:[^ ]*]] = getelementptr inbounds [[argmem_ty]]* %0, i32 0, i32 2
+// X86: call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[a]])
+// X86: call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[b]])
+// X86: call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[c]])
+// X86: ret void
+
+// X64-LABEL: define void @"\01?foo@@YAXUA@@00@Z"
+// X64: (%struct.A* %[[a:[^,]*]], %struct.A* %[[b:[^,]*]], %struct.A* %[[c:[^)]*]])
+// X64: call void @"\01??1A@@QEAA@XZ"(%struct.A* %[[a]])
+// X64: call void @"\01??1A@@QEAA@XZ"(%struct.A* %[[b]])
+// X64: call void @"\01??1A@@QEAA@XZ"(%struct.A* %[[c]])
+// X64: ret void
+
+
+void call_foo() {
+ foo(A(1), A(2), A(3));
+}
+
+// Order of evaluation should be right to left, and we should clean up the right
+// things as we unwind.
+//
+// X86-LABEL: define void @"\01?call_foo@@YAXXZ"()
+// X86: call i8* @llvm.stacksave()
+// X86: %[[argmem:[^ ]*]] = alloca inalloca [[argmem_ty]]
+// X86: %[[arg3:[^ ]*]] = getelementptr inbounds [[argmem_ty]]* %[[argmem]], i32 0, i32 2
+// X86: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@H@Z"(%struct.A* %[[arg3]], i32 3)
+// X86: %[[arg2:[^ ]*]] = getelementptr inbounds [[argmem_ty]]* %[[argmem]], i32 0, i32 1
+// X86: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@H@Z"(%struct.A* %[[arg2]], i32 2)
+// X86: %[[arg1:[^ ]*]] = getelementptr inbounds [[argmem_ty]]* %[[argmem]], i32 0, i32 0
+// X86: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@H@Z"(%struct.A* %[[arg1]], i32 1)
+// X86: invoke void @"\01?foo@@YAXUA@@00@Z"([[argmem_ty]]* inalloca %[[argmem]])
+// X86: call void @llvm.stackrestore
+// X86: ret void
+//
+// lpad2:
+// X86: call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[arg2]])
+// X86: br label
+//
+// ehcleanup:
+// X86: call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[arg3]])
+
+// X64-LABEL: define void @"\01?call_foo@@YAXXZ"()
+// X64: call %struct.A* @"\01??0A@@QEAA@H@Z"(%struct.A* %[[arg3:[^,]*]], i32 3)
+// X64: invoke %struct.A* @"\01??0A@@QEAA@H@Z"(%struct.A* %[[arg2:[^,]*]], i32 2)
+// X64: invoke %struct.A* @"\01??0A@@QEAA@H@Z"(%struct.A* %[[arg1:[^,]*]], i32 1)
+// X64: call void @"\01?foo@@YAXUA@@00@Z"
+// X64: (%struct.A* %[[arg1]], %struct.A* %[[arg2]], %struct.A* %[[arg3]])
+// X64: ret void
+//
+// lpad2:
+// X64: call void @"\01??1A@@QEAA@XZ"(%struct.A* %[[arg2]])
+// X64: br label
+//
+// ehcleanup:
+// X64: call void @"\01??1A@@QEAA@XZ"(%struct.A* %[[arg3]])
diff --git a/test/CodeGenCXX/microsoft-abi-array-cookies.cpp b/test/CodeGenCXX/microsoft-abi-array-cookies.cpp
index 1ba1f6a5f278..8da4fcf21382 100644
--- a/test/CodeGenCXX/microsoft-abi-array-cookies.cpp
+++ b/test/CodeGenCXX/microsoft-abi-array-cookies.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 | FileCheck %s
struct ClassWithoutDtor {
char x;
diff --git a/test/CodeGenCXX/microsoft-abi-byval-sret.cpp b/test/CodeGenCXX/microsoft-abi-byval-sret.cpp
new file mode 100644
index 000000000000..985b1ce62e92
--- /dev/null
+++ b/test/CodeGenCXX/microsoft-abi-byval-sret.cpp
@@ -0,0 +1,29 @@
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i686-pc-win32 -mconstructor-aliases -fno-rtti | FileCheck %s
+
+struct A {
+ A() : a(42) {}
+ A(const A &o) : a(o.a) {}
+ ~A() {}
+ int a;
+ A foo(A o);
+};
+
+A A::foo(A x) {
+ A y(*this);
+ y.a += x.a;
+ return y;
+}
+
+// CHECK-LABEL: define x86_thiscallcc %struct.A* @"\01?foo@A@@QAE?AU1@U1@@Z"
+// CHECK: (%struct.A* %this, <{ %struct.A*, %struct.A }>* inalloca)
+// CHECK: getelementptr inbounds <{ %struct.A*, %struct.A }>* %{{.*}}, i32 0, i32 0
+// CHECK: load %struct.A**
+// CHECK: ret %struct.A*
+
+int main() {
+ A x;
+ A y = x.foo(x);
+}
+
+// CHECK: call x86_thiscallcc %struct.A* @"\01?foo@A@@QAE?AU1@U1@@Z"
+// CHECK: (%struct.A* %{{[^,]*}}, <{ %struct.A*, %struct.A }>* inalloca %{{[^,]*}})
diff --git a/test/CodeGenCXX/microsoft-abi-byval-vararg.cpp b/test/CodeGenCXX/microsoft-abi-byval-vararg.cpp
new file mode 100644
index 000000000000..6a0a8601c0cc
--- /dev/null
+++ b/test/CodeGenCXX/microsoft-abi-byval-vararg.cpp
@@ -0,0 +1,52 @@
+// RUN: %clang_cc1 -Wno-non-pod-varargs -emit-llvm %s -o - -triple=i686-pc-win32 -mconstructor-aliases -fno-rtti | FileCheck %s
+
+#include <stdarg.h>
+
+struct A {
+ A(int a) : a(a) {}
+ A(const A &o) : a(o.a) {}
+ ~A() {}
+ int a;
+};
+
+int foo(A a, ...) {
+ va_list ap;
+ va_start(ap, a);
+ int sum = 0;
+ for (int i = 0; i < a.a; ++i)
+ sum += va_arg(ap, int);
+ va_end(ap);
+ return sum;
+}
+
+// CHECK-LABEL: define i32 @"\01?foo@@YAHUA@@ZZ"(<{ %struct.A }>* inalloca, ...)
+
+int main() {
+ return foo(A(3), 1, 2, 3);
+}
+// CHECK-LABEL: define i32 @main()
+// CHECK: %[[argmem:[^ ]*]] = alloca inalloca <{ %struct.A, i32, i32, i32 }>
+// CHECK: call i32 {{.*bitcast.*}}@"\01?foo@@YAHUA@@ZZ"{{.*}}(<{ %struct.A, i32, i32, i32 }>* inalloca %[[argmem]])
+
+void varargs_zero(...);
+void varargs_one(int, ...);
+void varargs_two(int, int, ...);
+void varargs_three(int, int, int, ...);
+void call_var_args() {
+ A x(3);
+ varargs_zero(x);
+ varargs_one(1, x);
+ varargs_two(1, 2, x);
+ varargs_three(1, 2, 3, x);
+}
+
+// CHECK-LABEL: define void @"\01?call_var_args@@YAXXZ"()
+// CHECK: call void {{.*bitcast.*varargs_zero.*}}(<{ %struct.A }>* inalloca %{{.*}})
+// CHECK: call void {{.*bitcast.*varargs_one.*}}(<{ i32, %struct.A }>* inalloca %{{.*}})
+// CHECK: call void {{.*bitcast.*varargs_two.*}}(<{ i32, i32, %struct.A }>* inalloca %{{.*}})
+// CHECK: call void {{.*bitcast.*varargs_three.*}}(<{ i32, i32, i32, %struct.A }>* inalloca %{{.*}})
+
+// CHECK-LABEL: declare void @"\01?varargs_zero@@YAXZZ"(...)
+// CHECK-LABEL: declare void @"\01?varargs_one@@YAXHZZ"(i32, ...)
+// CHECK-LABEL: declare void @"\01?varargs_two@@YAXHHZZ"(i32, i32, ...)
+// CHECK-LABEL: declare void @"\01?varargs_three@@YAXHHHZZ"(i32, i32, i32, ...)
diff --git a/test/CodeGenCXX/microsoft-abi-cdecl-method-sret.cpp b/test/CodeGenCXX/microsoft-abi-cdecl-method-sret.cpp
new file mode 100644
index 000000000000..da58c461dcc0
--- /dev/null
+++ b/test/CodeGenCXX/microsoft-abi-cdecl-method-sret.cpp
@@ -0,0 +1,44 @@
+// RUN: %clang_cc1 -triple i386-pc-win32 -emit-llvm %s -o - | FileCheck %s
+
+// PR15768
+
+// A trivial 12 byte struct is returned indirectly.
+struct S {
+ S();
+ int a, b, c;
+};
+
+struct C {
+ S variadic_sret(const char *f, ...);
+ S __cdecl cdecl_sret();
+ S __cdecl byval_and_sret(S a);
+ int c;
+};
+
+S C::variadic_sret(const char *f, ...) { return S(); }
+S C::cdecl_sret() { return S(); }
+S C::byval_and_sret(S a) { return S(); }
+
+// CHECK: define void @"\01?variadic_sret@C@@QAA?AUS@@PBDZZ"(%struct.C* %this, %struct.S* noalias sret %agg.result, i8* %f, ...)
+// CHECK: define void @"\01?cdecl_sret@C@@QAA?AUS@@XZ"(%struct.C* %this, %struct.S* noalias sret %agg.result)
+// CHECK: define void @"\01?byval_and_sret@C@@QAA?AUS@@U2@@Z"(%struct.C* %this, %struct.S* noalias sret %agg.result, %struct.S* byval align 4 %a)
+
+int main() {
+ C c;
+ c.variadic_sret("asdf");
+ c.cdecl_sret();
+ c.byval_and_sret(S());
+}
+// CHECK-LABEL: define i32 @main()
+// CHECK: call void {{.*}} @"\01?variadic_sret@C@@QAA?AUS@@PBDZZ"
+// CHECK: call void @"\01?cdecl_sret@C@@QAA?AUS@@XZ"
+// CHECK: call void @"\01?byval_and_sret@C@@QAA?AUS@@U2@@Z"
+
+// __fastcall has similar issues.
+struct A {
+ S __fastcall f(int x);
+};
+S A::f(int x) {
+ return S();
+}
+// CHECK-LABEL: define x86_fastcallcc void @"\01?f@A@@QAI?AUS@@H@Z"(%struct.A* inreg %this, %struct.S* inreg noalias sret %agg.result, i32 %x)
diff --git a/test/CodeGenCXX/microsoft-abi-constexpr-vs-inheritance.cpp b/test/CodeGenCXX/microsoft-abi-constexpr-vs-inheritance.cpp
index 92db9a789b3c..319f39c3ff48 100644
--- a/test/CodeGenCXX/microsoft-abi-constexpr-vs-inheritance.cpp
+++ b/test/CodeGenCXX/microsoft-abi-constexpr-vs-inheritance.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -std=c++11 -fno-rtti -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s
+// RUN: %clang_cc1 -std=c++11 -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 | FileCheck %s
struct A {
constexpr A(int x) : x(x) {}
diff --git a/test/CodeGenCXX/microsoft-abi-default-cc.cpp b/test/CodeGenCXX/microsoft-abi-default-cc.cpp
index d7fba9911e1b..e3ca39221e88 100644
--- a/test/CodeGenCXX/microsoft-abi-default-cc.cpp
+++ b/test/CodeGenCXX/microsoft-abi-default-cc.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck -check-prefix GCABI %s
-// RUN: %clang_cc1 -emit-llvm %s -o - -DMS_ABI -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck -check-prefix MSABI %s
+// RUN: %clang_cc1 -triple i386-pc-linux -emit-llvm %s -o - | FileCheck -check-prefix GCABI %s
+// RUN: %clang_cc1 -emit-llvm %s -o - -DMS_ABI -triple=i386-pc-win32 | FileCheck -check-prefix MSABI %s
#ifdef MS_ABI
# define METHOD_CC __thiscall
diff --git a/test/CodeGenCXX/microsoft-abi-dynamic-cast.cpp b/test/CodeGenCXX/microsoft-abi-dynamic-cast.cpp
new file mode 100644
index 000000000000..225407b7fa9c
--- /dev/null
+++ b/test/CodeGenCXX/microsoft-abi-dynamic-cast.cpp
@@ -0,0 +1,130 @@
+// RUN: %clang_cc1 -emit-llvm -O1 -o - -triple=i386-pc-win32 %s | FileCheck %s
+
+struct S { char a; };
+struct V { virtual void f(); };
+struct A : virtual V {};
+struct B : S, virtual V {};
+struct T {};
+
+T* test0() { return dynamic_cast<T*>((B*)0); }
+// CHECK-LABEL: define noalias %struct.T* @"\01?test0@@YAPAUT@@XZ"()
+// CHECK: ret %struct.T* null
+
+T* test1(V* x) { return &dynamic_cast<T&>(*x); }
+// CHECK-LABEL: define %struct.T* @"\01?test1@@YAPAUT@@PAUV@@@Z"(%struct.V* %x)
+// CHECK: [[CAST:%.*]] = bitcast %struct.V* %x to i8*
+// CHECK-NEXT: [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8* [[CAST]], i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUV@@@8" to i8*), i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUT@@@8" to i8*), i32 1)
+// CHECK-NEXT: [[RET:%.*]] = bitcast i8* [[CALL]] to %struct.T*
+// CHECK-NEXT: ret %struct.T* [[RET]]
+
+T* test2(A* x) { return &dynamic_cast<T&>(*x); }
+// CHECK-LABEL: define %struct.T* @"\01?test2@@YAPAUT@@PAUA@@@Z"(%struct.A* %x)
+// CHECK: [[CAST:%.*]] = bitcast %struct.A* %x to i8*
+// CHECK-NEXT: [[BITCAST:%.*]] = bitcast %struct.A* %x to i8**
+// CHECK-NEXT: [[VBTBL:%.*]] = load i8** [[BITCAST]], align 4
+// CHECK-NEXT: [[VBOFFP:%.*]] = getelementptr inbounds i8* [[VBTBL]], i32 4
+// CHECK-NEXT: [[VBOFFPCAST:%.*]] = bitcast i8* [[VBOFFP]] to i32*
+// CHECK-NEXT: [[VBOFFS:%.*]] = load i32* [[VBOFFPCAST]], align 4
+// CHECK-NEXT: [[ADJ:%.*]] = getelementptr inbounds i8* [[CAST]], i32 [[VBOFFS]]
+// CHECK-NEXT: [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8* [[ADJ]], i32 [[VBOFFS]], i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUA@@@8" to i8*), i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUT@@@8" to i8*), i32 1)
+// CHECK-NEXT: [[RET:%.*]] = bitcast i8* [[CALL]] to %struct.T*
+// CHECK-NEXT: ret %struct.T* [[RET]]
+
+T* test3(B* x) { return &dynamic_cast<T&>(*x); }
+// CHECK-LABEL: define %struct.T* @"\01?test3@@YAPAUT@@PAUB@@@Z"(%struct.B* %x)
+// CHECK: [[VOIDP:%.*]] = getelementptr inbounds %struct.B* %x, i32 0, i32 0, i32 0
+// CHECK-NEXT: [[VBPTR:%.*]] = getelementptr inbounds i8* [[VOIDP]], i32 4
+// CHECK-NEXT: [[BITCAST:%.*]] = bitcast i8* [[VBPTR:%.*]] to i8**
+// CHECK-NEXT: [[VBTBL:%.*]] = load i8** [[BITCAST]], align 4
+// CHECK-NEXT: [[VBOFFP:%.*]] = getelementptr inbounds i8* [[VBTBL]], i32 4
+// CHECK-NEXT: [[VBOFFPCAST:%.*]] = bitcast i8* [[VBOFFP]] to i32*
+// CHECK-NEXT: [[VBOFFS:%.*]] = load i32* [[VBOFFPCAST]], align 4
+// CHECK-NEXT: [[DELTA:%.*]] = add nsw i32 [[VBOFFS]], 4
+// CHECK-NEXT: [[ADJ:%.*]] = getelementptr inbounds i8* [[VOIDP]], i32 [[DELTA]]
+// CHECK-NEXT: [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8* [[ADJ]], i32 [[DELTA]], i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUB@@@8" to i8*), i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUT@@@8" to i8*), i32 1)
+// CHECK-NEXT: [[RET:%.*]] = bitcast i8* [[CALL]] to %struct.T*
+// CHECK-NEXT: ret %struct.T* [[RET]]
+
+T* test4(V* x) { return dynamic_cast<T*>(x); }
+// CHECK-LABEL: define %struct.T* @"\01?test4@@YAPAUT@@PAUV@@@Z"(%struct.V* %x)
+// CHECK: [[CAST:%.*]] = bitcast %struct.V* %x to i8*
+// CHECK-NEXT: [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8* [[CAST]], i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUV@@@8" to i8*), i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUT@@@8" to i8*), i32 0)
+// CHECK-NEXT: [[RET:%.*]] = bitcast i8* [[CALL]] to %struct.T*
+// CHECK-NEXT: ret %struct.T* [[RET]]
+
+T* test5(A* x) { return dynamic_cast<T*>(x); }
+// CHECK-LABEL: define %struct.T* @"\01?test5@@YAPAUT@@PAUA@@@Z"(%struct.A* %x)
+// CHECK: [[CHECK:%.*]] = icmp eq %struct.A* %x, null
+// CHECK-NEXT: br i1 [[CHECK]]
+// CHECK: [[VOIDP:%.*]] = bitcast %struct.A* %x to i8*
+// CHECK-NEXT: [[BITCAST:%.*]] = bitcast %struct.A* %x to i8**
+// CHECK-NEXT: [[VBTBL:%.*]] = load i8** [[BITCAST]], align 4
+// CHECK-NEXT: [[VBOFFP:%.*]] = getelementptr inbounds i8* [[VBTBL]], i32 4
+// CHECK-NEXT: [[VBOFFPCAST:%.*]] = bitcast i8* [[VBOFFP]] to i32*
+// CHECK-NEXT: [[VBOFFS:%.*]] = load i32* [[VBOFFPCAST:%.*]], align 4
+// CHECK-NEXT: [[ADJ:%.*]] = getelementptr inbounds i8* [[VOIDP]], i32 [[VBOFFS]]
+// CHECK-NEXT: [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8* [[ADJ]], i32 [[VBOFFS]], i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUA@@@8" to i8*), i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUT@@@8" to i8*), i32 0)
+// CHECK-NEXT: [[RES:%.*]] = bitcast i8* [[CALL]] to %struct.T*
+// CHECK-NEXT: br label
+// CHECK: [[RET:%.*]] = phi %struct.T*
+// CHECK-NEXT: ret %struct.T* [[RET]]
+
+T* test6(B* x) { return dynamic_cast<T*>(x); }
+// CHECK-LABEL: define %struct.T* @"\01?test6@@YAPAUT@@PAUB@@@Z"(%struct.B* %x)
+// CHECK: [[CHECK:%.*]] = icmp eq %struct.B* %x, null
+// CHECK-NEXT: br i1 [[CHECK]]
+// CHECK: [[CAST:%.*]] = getelementptr inbounds %struct.B* %x, i32 0, i32 0, i32 0
+// CHECK-NEXT: [[VBPTR:%.*]] = getelementptr inbounds i8* [[CAST]], i32 4
+// CHECK-NEXT: [[BITCAST:%.*]] = bitcast i8* [[VBPTR]] to i8**
+// CHECK-NEXT: [[VBTBL:%.*]] = load i8** [[BITCAST]], align 4
+// CHECK-NEXT: [[VBOFFP:%.*]] = getelementptr inbounds i8* [[VBTBL]], i32 4
+// CHECK-NEXT: [[VBOFFPCAST:%.*]] = bitcast i8* [[VBOFFP]] to i32*
+// CHECK-NEXT: [[VBOFFS:%.*]] = load i32* [[VBOFFPCAST:%.*]], align 4
+// CHECK-NEXT: [[DELTA:%.*]] = add nsw i32 [[VBOFFS]], 4
+// CHECK-NEXT: [[ADJ:%.*]] = getelementptr inbounds i8* [[CAST]], i32 [[DELTA]]
+// CHECK-NEXT: [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8* [[ADJ]], i32 [[DELTA]], i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUB@@@8" to i8*), i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUT@@@8" to i8*), i32 0)
+// CHECK-NEXT: [[RES:%.*]] = bitcast i8* [[CALL]] to %struct.T*
+// CHECK-NEXT: br label
+// CHECK: [[RET:%.*]] = phi %struct.T*
+// CHECK-NEXT: ret %struct.T* [[RET]]
+
+void* test7(V* x) { return dynamic_cast<void*>(x); }
+// CHECK-LABEL: define i8* @"\01?test7@@YAPAXPAUV@@@Z"(%struct.V* %x)
+// CHECK: [[CAST:%.*]] = bitcast %struct.V* %x to i8*
+// CHECK-NEXT: [[RET:%.*]] = tail call i8* @__RTCastToVoid(i8* [[CAST]])
+// CHECK-NEXT: ret i8* [[RET]]
+
+void* test8(A* x) { return dynamic_cast<void*>(x); }
+// CHECK-LABEL: define i8* @"\01?test8@@YAPAXPAUA@@@Z"(%struct.A* %x)
+// CHECK: [[CHECK:%.*]] = icmp eq %struct.A* %x, null
+// CHECK-NEXT: br i1 [[CHECK]]
+// CHECK: [[VOIDP:%.*]] = bitcast %struct.A* %x to i8*
+// CHECK-NEXT: [[BITCAST:%.*]] = bitcast %struct.A* %x to i8**
+// CHECK-NEXT: [[VBTBL:%.*]] = load i8** [[BITCAST]], align 4
+// CHECK-NEXT: [[VBOFFP:%.*]] = getelementptr inbounds i8* [[VBTBL]], i32 4
+// CHECK-NEXT: [[VBOFFPCAST:%.*]] = bitcast i8* [[VBOFFP]] to i32*
+// CHECK-NEXT: [[VBOFFS:%.*]] = load i32* [[VBOFFPCAST:%.*]], align 4
+// CHECK-NEXT: [[ADJ:%.*]] = getelementptr inbounds i8* [[VOIDP]], i32 [[VBOFFS]]
+// CHECK-NEXT: [[RES:%.*]] = tail call i8* @__RTCastToVoid(i8* [[ADJ]])
+// CHECK-NEXT: br label
+// CHECK: [[RET:%.*]] = phi i8*
+// CHECK-NEXT: ret i8* [[RET]]
+
+void* test9(B* x) { return dynamic_cast<void*>(x); }
+// CHECK-LABEL: define i8* @"\01?test9@@YAPAXPAUB@@@Z"(%struct.B* %x)
+// CHECK: [[CHECK:%.*]] = icmp eq %struct.B* %x, null
+// CHECK-NEXT: br i1 [[CHECK]]
+// CHECK: [[CAST:%.*]] = getelementptr inbounds %struct.B* %x, i32 0, i32 0, i32 0
+// CHECK-NEXT: [[VBPTR:%.*]] = getelementptr inbounds i8* [[CAST]], i32 4
+// CHECK-NEXT: [[BITCAST:%.*]] = bitcast i8* [[VBPTR]] to i8**
+// CHECK-NEXT: [[VBTBL:%.*]] = load i8** [[BITCAST]], align 4
+// CHECK-NEXT: [[VBOFFP:%.*]] = getelementptr inbounds i8* [[VBTBL]], i32 4
+// CHECK-NEXT: [[VBOFFPCAST:%.*]] = bitcast i8* [[VBOFFP]] to i32*
+// CHECK-NEXT: [[VBOFFS:%.*]] = load i32* [[VBOFFPCAST:%.*]], align 4
+// CHECK-NEXT: [[DELTA:%.*]] = add nsw i32 [[VBOFFS]], 4
+// CHECK-NEXT: [[ADJ:%.*]] = getelementptr inbounds i8* [[CAST]], i32 [[DELTA]]
+// CHECK-NEXT: [[CALL:%.*]] = tail call i8* @__RTCastToVoid(i8* [[ADJ]])
+// CHECK-NEXT: br label
+// CHECK: [[RET:%.*]] = phi i8*
+// CHECK-NEXT: ret i8* [[RET]]
+
diff --git a/test/CodeGenCXX/microsoft-abi-exceptions.cpp b/test/CodeGenCXX/microsoft-abi-exceptions.cpp
index 7757ea004359..60a3514c640a 100644
--- a/test/CodeGenCXX/microsoft-abi-exceptions.cpp
+++ b/test/CodeGenCXX/microsoft-abi-exceptions.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -cxx-abi microsoft -fexceptions -fno-rtti | FileCheck -check-prefix WIN32 %s
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fexceptions -fno-rtti | FileCheck -check-prefix WIN32 %s
struct A {
A();
@@ -14,17 +14,21 @@ void HasEHCleanup() {
}
// 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 %{{.*}})
+// WIN32-LABEL: define void @"\01?HasEHCleanup@@YAXXZ"() {{.*}} {
+// WIN32: %[[base:.*]] = call i8* @llvm.stacksave()
+// If this call throws, we have to restore the stack.
+// WIN32: invoke 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"
+// If this call throws, we have to cleanup the stacksave.
+// WIN32: invoke i32 @"\01?TakesTwo@@YAHUA@@0@Z"
+// WIN32: call void @llvm.stackrestore(i8* %[[base]])
// 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-NOT: @"\01??1A@@QAE@XZ"
+// WIN32: call void @llvm.stackrestore
// WIN32: }
void TakeRef(const A &a);
@@ -32,20 +36,28 @@ int HasDeactivatedCleanups() {
return TakesTwo((TakeRef(A()), A()), (TakeRef(A()), A()));
}
-// WIN32: define i32 @"\01?HasDeactivatedCleanups@@YAHXZ"() {{.*}} {
+// WIN32-LABEL: define i32 @"\01?HasDeactivatedCleanups@@YAHXZ"() {{.*}} {
// WIN32: %[[isactive:.*]] = alloca i1
-// WIN32: call x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
+// WIN32: call i8* @llvm.stacksave()
+// WIN32: %[[argmem:.*]] = alloca inalloca [[argmem_ty:<{ %struct.A, %struct.A }>]]
+// WIN32: %[[arg1:.*]] = getelementptr inbounds [[argmem_ty]]* %[[argmem]], i32 0, i32 1
+// 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"(%struct.A* %[[arg1:.*]])
+//
+// WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %[[arg1]])
// WIN32: store i1 true, i1* %[[isactive]]
+//
+// WIN32: %[[arg0:.*]] = getelementptr inbounds [[argmem_ty]]* %[[argmem]], i32 0, i32 0
// 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"
+//
+// WIN32: invoke i32 @"\01?TakesTwo@@YAHUA@@0@Z"([[argmem_ty]]* inalloca %[[argmem]])
+// WIN32: call void @llvm.stackrestore
// 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: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"
// WIN32: ret i32
//
// Conditionally destroy arg1.
@@ -60,20 +72,22 @@ int HasConditionalCleanup(bool cond) {
return (cond ? TakesTwo(A(), A()) : CouldThrow());
}
-// WIN32: define i32 @"\01?HasConditionalCleanup@@YAH_N@Z"(i1 zeroext %{{.*}}) {{.*}} {
+// WIN32-LABEL: 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: call i8* @llvm.stacksave()
+// WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %{{.*}})
// 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: invoke i32 @"\01?TakesTwo@@YAHUA@@0@Z"
+// WIN32: call void @llvm.stackrestore
+//
// 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]])
+//
+// Only one dtor in the invoke for arg1
+// WIN32: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}})
+// WIN32-NOT: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"
+// WIN32: call void @llvm.stackrestore
// WIN32: }
// Now test both.
@@ -81,8 +95,7 @@ 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-LABEL: define i32 @"\01?HasConditionalDeactivatedCleanups@@YAH_N@Z"{{.*}} {
// WIN32: alloca i1
// WIN32: %[[arg1_cond:.*]] = alloca i1
// Start all four cleanups as deactivated.
@@ -92,10 +105,10 @@ int HasConditionalDeactivatedCleanups(bool cond) {
// WIN32: store i1 false
// WIN32: br i1
// True condition.
-// WIN32: call x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
+// 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"(%struct.A* %[[arg1]])
+// WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
// WIN32: store i1 true, i1* %[[arg1_cond]]
// WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
// WIN32: store i1 true
@@ -108,13 +121,13 @@ int HasConditionalDeactivatedCleanups(bool cond) {
// 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: invoke 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: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"
// WIN32: }
namespace crash_on_partial_destroy {
diff --git a/test/CodeGenCXX/microsoft-abi-member-pointers.cpp b/test/CodeGenCXX/microsoft-abi-member-pointers.cpp
index c0dcd3cf8316..18e8c827eebe 100755
--- a/test/CodeGenCXX/microsoft-abi-member-pointers.cpp
+++ b/test/CodeGenCXX/microsoft-abi-member-pointers.cpp
@@ -1,7 +1,11 @@
-// RUN: %clang_cc1 -fno-rtti -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s
+// RUN: %clang_cc1 -std=c++11 -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 -fms-extensions | FileCheck %s
+// RUN: %clang_cc1 -std=c++11 -fno-rtti -emit-llvm %s -o - -triple=x86_64-pc-win32 -fms-extensions | FileCheck %s -check-prefix=X64
+// RUN: %clang_cc1 -std=c++11 -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 -DINCOMPLETE_VIRTUAL -fms-extensions -verify
+// RUN: %clang_cc1 -std=c++11 -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 -DINCOMPLETE_VIRTUAL -DMEMFUN -fms-extensions -verify
// FIXME: Test x86_64 member pointers when codegen no longer asserts on records
// with virtual bases.
+#ifndef INCOMPLETE_VIRTUAL
struct B1 {
void foo();
int b;
@@ -56,20 +60,20 @@ int UnspecSingle::*us_d_memptr;
// 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: { i32 0, i32 -1 }, align 8
// CHECK: @"\01?n_d_memptr@@3PQNonZeroVBPtr@@HQ1@" = global { i32, i32 }
-// CHECK: { i32 0, i32 -1 }, align 4
+// CHECK: { i32 0, i32 -1 }, align 8
// CHECK: @"\01?u_d_memptr@@3PQUnspecified@@HQ1@" = global { i32, i32, i32 }
-// CHECK: { i32 0, i32 0, i32 -1 }, align 4
+// CHECK: { i32 0, i32 0, i32 -1 }, align 8
// CHECK: @"\01?us_d_memptr@@3PQUnspecSingle@@HQ1@" = global { i32, i32, i32 }
-// CHECK: { i32 0, i32 0, i32 -1 }, align 4
+// CHECK: { i32 0, i32 0, i32 -1 }, align 8
void (Single ::*s_f_memptr)();
void (Multiple::*m_f_memptr)();
void (Virtual ::*v_f_memptr)();
// 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
+// CHECK: @"\01?m_f_memptr@@3P8Multiple@@AEXXZQ1@" = global { i8*, i32 } zeroinitializer, align 8
+// CHECK: @"\01?v_f_memptr@@3P8Virtual@@AEXXZQ1@" = global { i8*, i32, i32 } zeroinitializer, align 8
// We can define Unspecified after locking in the inheritance model.
struct Unspecified : Multiple, Virtual {
@@ -91,13 +95,13 @@ 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: global { i8*, i32 } { i8* bitcast ({{.*}} @"\01?foo@B2@@QAEXXZ" to i8*), i32 4 }, align 8
// 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: global { i8*, i32, i32 } { i8* bitcast ({{.*}} @"\01?foo@Virtual@@QAEXXZ" to i8*), i32 0, i32 0 }, align 8
// 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: global { i8*, i32, i32, i32 } { i8* bitcast ({{.*}} @"\01?foo@Unspecified@@QAEXXZ" to i8*), i32 0, i32 12, i32 0 }, align 8
// 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
+// CHECK: global { i8*, i32, i32, i32 } { i8* bitcast ({{.*}} @"\01?foo@UnspecSingle@@QAEXXZ" to i8*), i32 0, i32 0, i32 0 }, align 8
}
namespace CastParam {
@@ -119,11 +123,11 @@ void (A::*ptr1)(void *) = (void (A::*)(void *)) &A::foo;
// 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
+// CHECK: global { i8*, i32 } { i8* bitcast (void ({{.*}})* @"\01?foo@A@CastParam@@QAEXPAU12@@Z" to i8*), i32 4 }, align 8
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
+// CHECK: global { i8*, i32 } zeroinitializer, align 8
struct D : C {
virtual void isPolymorphic();
@@ -156,23 +160,23 @@ void EmitNonVirtualMemberPointers() {
void (UnspecWithVBPtr::*u2_f_memptr)() = &UnspecWithVBPtr::foo;
// CHECK: define void @"\01?EmitNonVirtualMemberPointers@@YAXXZ"() {{.*}} {
// CHECK: alloca i8*, align 4
-// CHECK: alloca { i8*, i32 }, align 4
-// CHECK: alloca { i8*, i32, i32 }, align 4
-// CHECK: alloca { i8*, i32, i32, i32 }, align 4
+// CHECK: alloca { i8*, i32 }, align 8
+// CHECK: alloca { i8*, i32, i32 }, align 8
+// CHECK: alloca { i8*, i32, i32, i32 }, align 8
// CHECK: store i8* bitcast (void (%{{.*}}*)* @"\01?foo@Single@@QAEXXZ" to i8*), i8** %{{.*}}, align 4
// CHECK: store { i8*, i32 }
// CHECK: { i8* bitcast (void (%{{.*}}*)* @"\01?foo@Multiple@@QAEXXZ" to i8*), i32 0 },
-// CHECK: { i8*, i32 }* %{{.*}}, align 4
+// CHECK: { i8*, i32 }* %{{.*}}, align 8
// CHECK: store { i8*, i32, i32 }
// CHECK: { i8* bitcast (void (%{{.*}}*)* @"\01?foo@Virtual@@QAEXXZ" to i8*), i32 0, i32 0 },
-// CHECK: { i8*, i32, i32 }* %{{.*}}, align 4
+// CHECK: { i8*, i32, i32 }* %{{.*}}, align 8
// CHECK: store { i8*, i32, i32, i32 }
// CHECK: { i8* bitcast (void (%{{.*}}*)* @"\01?foo@Unspecified@@QAEXXZ" to i8*), i32 0, i32 12, i32 0 },
-// CHECK: { i8*, i32, i32, i32 }* %{{.*}}, align 4
+// CHECK: { i8*, i32, i32, i32 }* %{{.*}}, align 8
// CHECK: store { i8*, i32, i32, i32 }
// CHECK: { i8* bitcast (void (%{{.*}}*)* @"\01?foo@UnspecWithVBPtr@@QAEXXZ" to i8*),
// CHECK: i32 0, i32 4, i32 0 },
-// CHECK: { i8*, i32, i32, i32 }* %{{.*}}, align 4
+// CHECK: { i8*, i32, i32, i32 }* %{{.*}}, align 8
// CHECK: ret void
// CHECK: }
}
@@ -219,27 +223,31 @@ void polymorphicMemPtrs() {
bool nullTestDataUnspecified(int Unspecified::*mp) {
return mp;
// CHECK: define zeroext i1 @"\01?nullTestDataUnspecified@@YA_NPQUnspecified@@H@Z"{{.*}} {
-// CHECK: %{{.*}} = load { i32, i32, i32 }* %{{.*}}, align 4
-// CHECK: store { i32, i32, i32 } {{.*}} align 4
-// CHECK: %[[mp:.*]] = load { i32, i32, i32 }* %{{.*}}, align 4
+// CHECK: %{{.*}} = load { i32, i32, i32 }* %{{.*}}, align 8
+// CHECK: store { i32, i32, i32 } {{.*}} align 8
+// CHECK: %[[mp:.*]] = load { i32, i32, i32 }* %{{.*}}, align 8
// CHECK: %[[mp0:.*]] = extractvalue { i32, i32, i32 } %[[mp]], 0
// CHECK: %[[cmp0:.*]] = icmp ne i32 %[[mp0]], 0
// CHECK: %[[mp1:.*]] = extractvalue { i32, i32, i32 } %[[mp]], 1
// CHECK: %[[cmp1:.*]] = icmp ne i32 %[[mp1]], 0
-// CHECK: %[[and0:.*]] = and i1 %[[cmp0]], %[[cmp1]]
+// CHECK: %[[and0:.*]] = or i1 %[[cmp0]], %[[cmp1]]
// CHECK: %[[mp2:.*]] = extractvalue { i32, i32, i32 } %[[mp]], 2
// CHECK: %[[cmp2:.*]] = icmp ne i32 %[[mp2]], -1
-// CHECK: %[[and1:.*]] = and i1 %[[and0]], %[[cmp2]]
+// CHECK: %[[and1:.*]] = or i1 %[[and0]], %[[cmp2]]
// CHECK: ret i1 %[[and1]]
// CHECK: }
+
+// Pass this large type indirectly.
+// X64-LABEL: define zeroext i1 @"\01?nullTestDataUnspecified@@
+// X64: ({ i32, i32, i32 }*)
}
bool nullTestFunctionUnspecified(void (Unspecified::*mp)()) {
return mp;
// CHECK: define zeroext i1 @"\01?nullTestFunctionUnspecified@@YA_NP8Unspecified@@AEXXZ@Z"{{.*}} {
-// CHECK: %{{.*}} = load { i8*, i32, i32, i32 }* %{{.*}}, align 4
-// CHECK: store { i8*, i32, i32, i32 } {{.*}} align 4
-// CHECK: %[[mp:.*]] = load { i8*, i32, i32, i32 }* %{{.*}}, align 4
+// CHECK: %{{.*}} = load { i8*, i32, i32, i32 }* %{{.*}}, align 8
+// CHECK: store { i8*, i32, i32, i32 } {{.*}} align 8
+// CHECK: %[[mp:.*]] = load { i8*, i32, i32, i32 }* %{{.*}}, align 8
// CHECK: %[[mp0:.*]] = extractvalue { i8*, i32, i32, i32 } %[[mp]], 0
// CHECK: %[[cmp0:.*]] = icmp ne i8* %[[mp0]], null
// CHECK: ret i1 %[[cmp0]]
@@ -252,7 +260,7 @@ int loadDataMemberPointerVirtual(Virtual *o, int Virtual::*memptr) {
// data pointer.
// CHECK: define i32 @"\01?loadDataMemberPointerVirtual@@YAHPAUVirtual@@PQ1@H@Z"{{.*}} {
// CHECK: %[[o:.*]] = load %{{.*}}** %{{.*}}, align 4
-// CHECK: %[[memptr:.*]] = load { i32, i32 }* %{{.*}}, align 4
+// CHECK: %[[memptr:.*]] = load { i32, i32 }* %{{.*}}, align 8
// CHECK: %[[memptr0:.*]] = extractvalue { i32, i32 } %[[memptr:.*]], 0
// CHECK: %[[memptr1:.*]] = extractvalue { i32, i32 } %[[memptr:.*]], 1
// CHECK: %[[v6:.*]] = bitcast %{{.*}}* %[[o]] to i8*
@@ -268,6 +276,11 @@ int loadDataMemberPointerVirtual(Virtual *o, int Virtual::*memptr) {
// CHECK: %[[v12:.*]] = load i32* %[[v11]]
// CHECK: ret i32 %[[v12]]
// CHECK: }
+
+// A two-field data memptr on x64 gets coerced to i64 and is passed in a
+// register or memory.
+// X64-LABEL: define i32 @"\01?loadDataMemberPointerVirtual@@YAHPEAUVirtual@@PEQ1@H@Z"
+// X64: (%struct.Virtual* %o, i64 %memptr.coerce)
}
int loadDataMemberPointerUnspecified(Unspecified *o, int Unspecified::*memptr) {
@@ -276,7 +289,7 @@ int loadDataMemberPointerUnspecified(Unspecified *o, int Unspecified::*memptr) {
// data pointer.
// CHECK: define i32 @"\01?loadDataMemberPointerUnspecified@@YAHPAUUnspecified@@PQ1@H@Z"{{.*}} {
// CHECK: %[[o:.*]] = load %{{.*}}** %{{.*}}, align 4
-// CHECK: %[[memptr:.*]] = load { i32, i32, i32 }* %{{.*}}, align 4
+// CHECK: %[[memptr:.*]] = load { i32, i32, i32 }* %{{.*}}, align 8
// CHECK: %[[memptr0:.*]] = extractvalue { i32, i32, i32 } %[[memptr:.*]], 0
// CHECK: %[[memptr1:.*]] = extractvalue { i32, i32, i32 } %[[memptr:.*]], 1
// CHECK: %[[memptr2:.*]] = extractvalue { i32, i32, i32 } %[[memptr:.*]], 2
@@ -309,6 +322,11 @@ void callMemberPointerSingle(Single *o, void (Single::*memptr)()) {
// CHECK: call x86_thiscallcc void %{{.*}}(%{{.*}} %{{.*}})
// CHECK: ret void
// CHECK: }
+
+// X64-LABEL: define void @"\01?callMemberPointerSingle@@
+// X64: (%struct.Single* %o, i8* %memptr)
+// X64: bitcast i8* %{{[^ ]*}} to void (%struct.Single*)*
+// X64: ret void
}
void callMemberPointerMultiple(Multiple *o, void (Multiple::*memptr)()) {
@@ -355,6 +373,9 @@ bool compareSingleFunctionMemptr(void (Single::*l)(), void (Single::*r)()) {
// CHECK-NOT: icmp
// CHECK: ret i1 %[[r]]
// CHECK: }
+
+// X64-LABEL: define zeroext i1 @"\01?compareSingleFunctionMemptr@@
+// X64: (i8* %{{[^,]*}}, i8* %{{[^)]*}})
}
bool compareNeqSingleFunctionMemptr(void (Single::*l)(), void (Single::*r)()) {
@@ -390,6 +411,9 @@ bool unspecFuncMemptrEq(void (Unspecified::*l)(), void (Unspecified::*r)()) {
// CHECK: %{{.*}} = and i1 %[[bits_or_null]], %[[cmp0]]
// CHECK: ret i1 %{{.*}}
// CHECK: }
+
+// X64-LABEL: define zeroext i1 @"\01?unspecFuncMemptrEq@@
+// X64: ({ i8*, i32, i32, i32 }*, { i8*, i32, i32, i32 }*)
}
bool unspecFuncMemptrNeq(void (Unspecified::*l)(), void (Unspecified::*r)()) {
@@ -432,6 +456,9 @@ bool unspecDataMemptrEq(int Unspecified::*l, int Unspecified::*r) {
// CHECK: and i1
// CHECK: ret i1
// CHECK: }
+
+// X64-LABEL: define zeroext i1 @"\01?unspecDataMemptrEq@@
+// X64: ({ i32, i32, i32 }*, { i32, i32, i32 }*)
}
void (Multiple::*convertB2FuncToMultiple(void (B2::*mp)()))() {
@@ -462,7 +489,7 @@ void (B2::*convertMultipleFuncToB2(void (Multiple::*mp)()))() {
//
// CHECK: define i32 @"\01?convertMultipleFuncToB2@@YAP8B2@@AEXXZP8Multiple@@AEXXZ@Z"{{.*}} {
// CHECK: store
-// CHECK: %[[src:.*]] = load { i8*, i32 }* %{{.*}}, align 4
+// CHECK: %[[src:.*]] = load { i8*, i32 }* %{{.*}}, align 8
// CHECK: extractvalue { i8*, i32 } %[[src]], 0
// CHECK: icmp ne i8* %{{.*}}, null
// CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}}
@@ -487,7 +514,7 @@ 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: load { i8*, i32, i32 }* %{{.*}}, align 8
// CHECK: extractvalue { i8*, i32, i32 } %{{.*}}, 0
// CHECK: icmp ne i8* %{{.*}}, null
// CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}}
@@ -537,3 +564,92 @@ int A::*reinterpret(int C::*mp) {
}
}
+
+namespace Test3 {
+// Make sure we cast 'this' to i8* before using GEP.
+
+struct A {
+ int a;
+ int b;
+};
+
+int *load_data(A *a, int A::*mp) {
+ return &(a->*mp);
+// CHECK-LABEL: define i32* @"\01?load_data@Test3@@YAPAHPAUA@1@PQ21@H@Z"{{.*}} {
+// CHECK: %[[a:.*]] = load %"struct.Test3::A"** %{{.*}}, align 4
+// CHECK: %[[mp:.*]] = load i32* %{{.*}}, align 4
+// CHECK: %[[a_i8:.*]] = bitcast %"struct.Test3::A"* %[[a]] to i8*
+// CHECK: getelementptr inbounds i8* %[[a_i8]], i32 %[[mp]]
+// CHECK: }
+}
+
+}
+
+namespace Test4 {
+
+struct A { virtual void f(); };
+struct B { virtual void g(); };
+struct C : A, B { virtual void g(); };
+
+void (C::*getmp())() {
+ return &C::g;
+}
+// CHECK-LABEL: define i64 @"\01?getmp@Test4@@YAP8C@1@AEXXZXZ"()
+// CHECK: store { i8*, i32 } { i8* bitcast (void (i8*)* @"\01??_9C@Test4@@$BA@AE" to i8*), i32 4 }, { i8*, i32 }* %{{.*}}
+//
+
+// CHECK-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_9C@Test4@@$BA@AE"(i8*)
+// CHECK-NOT: getelementptr
+// CHECK: load void (i8*)*** %{{.*}}
+// CHECK: getelementptr inbounds void (i8*)** %{{.*}}, i64 0
+// CHECK-NOT: getelementptr
+// CHECK: call x86_thiscallcc void %
+
+}
+
+namespace pr20007 {
+struct A {
+ void f();
+ void f(int);
+};
+struct B : public A {};
+void test() { void (B::*a)() = &B::f; }
+// CHECK-LABEL: define void @"\01?test@pr20007@@YAXXZ"
+// CHECK: store i8* bitcast (void (%"struct.pr20007::A"*)* @"\01?f@A@pr20007@@QAEXXZ" to i8*)
+}
+
+namespace pr20007_kw {
+struct A {
+ void f();
+ void f(int);
+};
+struct __single_inheritance B;
+struct B : public A {};
+void test() { void (B::*a)() = &B::f; }
+// CHECK-LABEL: define void @"\01?test@pr20007_kw@@YAXXZ"
+// CHECK: store i8* bitcast (void (%"struct.pr20007_kw::A"*)* @"\01?f@A@pr20007_kw@@QAEXXZ" to i8*)
+}
+
+namespace pr19987 {
+template <typename T>
+struct S {
+ int T::*x;
+};
+
+struct U : S<U> {};
+
+static_assert(sizeof(S<U>::x) == 12, "");
+}
+
+#else
+struct __virtual_inheritance A;
+#ifdef MEMFUN
+int foo(A *a, int (A::*mp)()) {
+ return (a->*mp)(); // expected-error{{requires a complete class type}}
+}
+#else
+int foo(A *a, int A::*mp) {
+ return a->*mp; // expected-error{{requires a complete class type}}
+}
+#endif
+#endif
diff --git a/test/CodeGenCXX/microsoft-abi-methods.cpp b/test/CodeGenCXX/microsoft-abi-methods.cpp
index c996ba5b8473..579e549ab46c 100644
--- a/test/CodeGenCXX/microsoft-abi-methods.cpp
+++ b/test/CodeGenCXX/microsoft-abi-methods.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 | FileCheck %s
class C {
public:
diff --git a/test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp b/test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp
index 802f0ca24175..b1c1482eff6f 100644
--- a/test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp
+++ b/test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fno-rtti -emit-llvm %s -o - -mconstructor-aliases -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s
+// RUN: %clang_cc1 -fno-rtti -emit-llvm %s -o - -mconstructor-aliases -triple=i386-pc-win32 | FileCheck %s
struct Left {
virtual void left();
diff --git a/test/CodeGenCXX/microsoft-abi-non-virtual-base-ordering.cpp b/test/CodeGenCXX/microsoft-abi-non-virtual-base-ordering.cpp
new file mode 100755
index 000000000000..0c82ac328649
--- /dev/null
+++ b/test/CodeGenCXX/microsoft-abi-non-virtual-base-ordering.cpp
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -fno-rtti -emit-llvm -triple=i686-pc-win32 -o - %s 2>/dev/null | FileCheck %s
+// RUN: %clang_cc1 -fno-rtti -emit-llvm -triple=x86_64-pc-win32 -o - %s 2>/dev/null | FileCheck %s
+
+struct C0 { int a; };
+struct C1 { int a; virtual void C1M() {} };
+struct C2 { int a; virtual void C2M() {} };
+struct C3 : C0, C1, C2 {} a;
+
+// Check to see that both C1 and C2 get laid out before C0 does.
+// CHECK: %struct.C3 = type { %struct.C1, %struct.C2, %struct.C0 }
diff --git a/test/CodeGenCXX/microsoft-abi-nontrivial-covariant-thunk.cpp b/test/CodeGenCXX/microsoft-abi-nontrivial-covariant-thunk.cpp
new file mode 100644
index 000000000000..d305dd83271f
--- /dev/null
+++ b/test/CodeGenCXX/microsoft-abi-nontrivial-covariant-thunk.cpp
@@ -0,0 +1,24 @@
+// RUN: %clang_cc1 %s -fno-rtti -emit-llvm-only -o - -triple=i386-pc-win32 -verify
+
+// A is not trivially copyable and must be passed indirectly or with inalloca.
+struct A {
+ A();
+ A(const A &o);
+ virtual ~A();
+ int a;
+};
+
+struct B {
+ B();
+ int b;
+ virtual B *clone(A);
+};
+
+// Converting from C* to B* requires a this adjustment.
+struct C : A, B {
+ C();
+ int c;
+ virtual C *clone(A); // expected-error {{cannot compile this non-trivial argument copy for thunk yet}}
+};
+B::B() {} // force emission
+C::C() {} // force emission
diff --git a/test/CodeGenCXX/microsoft-abi-rtti.cpp b/test/CodeGenCXX/microsoft-abi-rtti.cpp
new file mode 100644
index 000000000000..062f597b3783
--- /dev/null
+++ b/test/CodeGenCXX/microsoft-abi-rtti.cpp
@@ -0,0 +1,267 @@
+// RUN: %clang_cc1 -emit-llvm -o - -triple=i386-pc-win32 2>/dev/null %s | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -o - -triple=x86_64-pc-win32 2>/dev/null %s | FileCheck --check-prefix=X64 %s
+
+struct N {};
+struct M : private N {};
+struct X { virtual void f() {} };
+class Z { virtual void f() {} };
+class V : public X { virtual void f() {} };
+class W : M, virtual V { public: virtual void f() {} };
+class Y : Z, W, virtual V { public: virtual void g() {} } y;
+
+struct A {};
+struct B : A {};
+struct C : B { virtual void f() {} } c;
+
+struct X1 { virtual void f() {} };
+struct V1 : X1 {};
+struct W1 : virtual V1 {};
+struct Y1 : W1, virtual V1 {} y1;
+
+struct A1 { virtual void f() {} };
+struct B1 : virtual A1 { virtual void f() {} B1() {} } b1;
+
+struct Z2 { virtual void f() {} };
+struct Y2 { virtual void f() {} };
+struct A2 : Z2, Y2 {};
+struct B2 : virtual A2 { B2() {} virtual void f() {} } b2;
+
+// CHECK: @"\01??_R4B2@@6BZ2@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 8, i32 4, i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUB2@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3B2@@8" }
+// CHECK: @"\01??_R0?AUB2@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUB2@@\00" }
+// CHECK: @"\01??_R3B2@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 3, i32 4, %rtti.BaseClassDescriptor** getelementptr inbounds ([5 x %rtti.BaseClassDescriptor*]* @"\01??_R2B2@@8", i32 0, i32 0) }
+// CHECK: @"\01??_R2B2@@8" = linkonce_odr constant [5 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@B2@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@A@3FA@A2@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@A@3EA@Z2@@8", %rtti.BaseClassDescriptor* @"\01??_R13A@3EA@Y2@@8", %rtti.BaseClassDescriptor* null]
+// CHECK: @"\01??_R1A@?0A@EA@B2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUB2@@@8" to i8*), i32 3, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3B2@@8" }
+// CHECK: @"\01??_R1A@A@3FA@A2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUA2@@@8" to i8*), i32 2, i32 0, i32 0, i32 4, i32 80, %rtti.ClassHierarchyDescriptor* @"\01??_R3A2@@8" }
+// CHECK: @"\01??_R0?AUA2@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUA2@@\00" }
+// CHECK: @"\01??_R3A2@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 1, i32 3, %rtti.BaseClassDescriptor** getelementptr inbounds ([4 x %rtti.BaseClassDescriptor*]* @"\01??_R2A2@@8", i32 0, i32 0) }
+// CHECK: @"\01??_R2A2@@8" = linkonce_odr constant [4 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@A2@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@Z2@@8", %rtti.BaseClassDescriptor* @"\01??_R13?0A@EA@Y2@@8", %rtti.BaseClassDescriptor* null]
+// CHECK: @"\01??_R1A@?0A@EA@A2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUA2@@@8" to i8*), i32 2, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3A2@@8" }
+// CHECK: @"\01??_R1A@?0A@EA@Z2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUZ2@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3Z2@@8" }
+// CHECK: @"\01??_R0?AUZ2@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUZ2@@\00" }
+// CHECK: @"\01??_R3Z2@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, %rtti.BaseClassDescriptor** getelementptr inbounds ([2 x %rtti.BaseClassDescriptor*]* @"\01??_R2Z2@@8", i32 0, i32 0) }
+// CHECK: @"\01??_R2Z2@@8" = linkonce_odr constant [2 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@Z2@@8", %rtti.BaseClassDescriptor* null]
+// CHECK: @"\01??_R13?0A@EA@Y2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUY2@@@8" to i8*), i32 0, i32 4, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3Y2@@8" }
+// CHECK: @"\01??_R0?AUY2@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUY2@@\00" }
+// CHECK: @"\01??_R3Y2@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, %rtti.BaseClassDescriptor** getelementptr inbounds ([2 x %rtti.BaseClassDescriptor*]* @"\01??_R2Y2@@8", i32 0, i32 0) }
+// CHECK: @"\01??_R2Y2@@8" = linkonce_odr constant [2 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@Y2@@8", %rtti.BaseClassDescriptor* null]
+// CHECK: @"\01??_R1A@?0A@EA@Y2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUY2@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3Y2@@8" }
+// CHECK: @"\01??_R1A@A@3EA@Z2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUZ2@@@8" to i8*), i32 0, i32 0, i32 0, i32 4, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3Z2@@8" }
+// CHECK: @"\01??_R13A@3EA@Y2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUY2@@@8" to i8*), i32 0, i32 4, i32 0, i32 4, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3Y2@@8" }
+// CHECK: @"\01??_R4B2@@6BY2@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 12, i32 8, i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUB2@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3B2@@8" }
+// CHECK: @"\01??_R4A2@@6BZ2@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUA2@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3A2@@8" }
+// CHECK: @"\01??_R4A2@@6BY2@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 4, i32 0, i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUA2@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3A2@@8" }
+// CHECK: @"\01??_R4Y2@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUY2@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3Y2@@8" }
+// CHECK: @"\01??_R4Z2@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUZ2@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3Z2@@8" }
+// CHECK: @"\01??_R4B1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 8, i32 4, i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUB1@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3B1@@8" }
+// CHECK: @"\01??_R0?AUB1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUB1@@\00" }
+// CHECK: @"\01??_R3B1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 2, %rtti.BaseClassDescriptor** getelementptr inbounds ([3 x %rtti.BaseClassDescriptor*]* @"\01??_R2B1@@8", i32 0, i32 0) }
+// CHECK: @"\01??_R2B1@@8" = linkonce_odr constant [3 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@B1@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@A@3FA@A1@@8", %rtti.BaseClassDescriptor* null]
+// CHECK: @"\01??_R1A@?0A@EA@B1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUB1@@@8" to i8*), i32 1, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3B1@@8" }
+// CHECK: @"\01??_R1A@A@3FA@A1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUA1@@@8" to i8*), i32 0, i32 0, i32 0, i32 4, i32 80, %rtti.ClassHierarchyDescriptor* @"\01??_R3A1@@8" }
+// CHECK: @"\01??_R0?AUA1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUA1@@\00" }
+// CHECK: @"\01??_R3A1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, %rtti.BaseClassDescriptor** getelementptr inbounds ([2 x %rtti.BaseClassDescriptor*]* @"\01??_R2A1@@8", i32 0, i32 0) }
+// CHECK: @"\01??_R2A1@@8" = linkonce_odr constant [2 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@A1@@8", %rtti.BaseClassDescriptor* null]
+// CHECK: @"\01??_R1A@?0A@EA@A1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUA1@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3A1@@8" }
+// CHECK: @"\01??_R4A1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUA1@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3A1@@8" }
+// CHECK: @"\01??_R4Y1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 4, i32 0, i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUY1@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3Y1@@8" }
+// CHECK: @"\01??_R0?AUY1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUY1@@\00" }
+// CHECK: @"\01??_R3Y1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 3, i32 6, %rtti.BaseClassDescriptor** getelementptr inbounds ([7 x %rtti.BaseClassDescriptor*]* @"\01??_R2Y1@@8", i32 0, i32 0) }
+// CHECK: @"\01??_R2Y1@@8" = linkonce_odr constant [7 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@Y1@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@W1@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@A@3FA@V1@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@A@3EA@X1@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@A@3FA@V1@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@A@3EA@X1@@8", %rtti.BaseClassDescriptor* null]
+// CHECK: @"\01??_R1A@?0A@EA@Y1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUY1@@@8" to i8*), i32 5, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3Y1@@8" }
+// CHECK: @"\01??_R1A@?0A@EA@W1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUW1@@@8" to i8*), i32 2, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3W1@@8" }
+// CHECK: @"\01??_R0?AUW1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUW1@@\00" }
+// CHECK: @"\01??_R3W1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 3, %rtti.BaseClassDescriptor** getelementptr inbounds ([4 x %rtti.BaseClassDescriptor*]* @"\01??_R2W1@@8", i32 0, i32 0) }
+// CHECK: @"\01??_R2W1@@8" = linkonce_odr constant [4 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@W1@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@A@3FA@V1@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@A@3EA@X1@@8", %rtti.BaseClassDescriptor* null]
+// CHECK: @"\01??_R1A@A@3FA@V1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUV1@@@8" to i8*), i32 1, i32 0, i32 0, i32 4, i32 80, %rtti.ClassHierarchyDescriptor* @"\01??_R3V1@@8" }
+// CHECK: @"\01??_R0?AUV1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUV1@@\00" }
+// CHECK: @"\01??_R3V1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 2, %rtti.BaseClassDescriptor** getelementptr inbounds ([3 x %rtti.BaseClassDescriptor*]* @"\01??_R2V1@@8", i32 0, i32 0) }
+// CHECK: @"\01??_R2V1@@8" = linkonce_odr constant [3 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@V1@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@X1@@8", %rtti.BaseClassDescriptor* null]
+// CHECK: @"\01??_R1A@?0A@EA@V1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUV1@@@8" to i8*), i32 1, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3V1@@8" }
+// CHECK: @"\01??_R1A@?0A@EA@X1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUX1@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3X1@@8" }
+// CHECK: @"\01??_R0?AUX1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUX1@@\00" }
+// CHECK: @"\01??_R3X1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, %rtti.BaseClassDescriptor** getelementptr inbounds ([2 x %rtti.BaseClassDescriptor*]* @"\01??_R2X1@@8", i32 0, i32 0) }
+// CHECK: @"\01??_R2X1@@8" = linkonce_odr constant [2 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@X1@@8", %rtti.BaseClassDescriptor* null]
+// CHECK: @"\01??_R1A@A@3EA@X1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUX1@@@8" to i8*), i32 0, i32 0, i32 0, i32 4, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3X1@@8" }
+// CHECK: @"\01??_R4W1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 4, i32 0, i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUW1@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3W1@@8" }
+// CHECK: @"\01??_R4V1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUV1@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3V1@@8" }
+// CHECK: @"\01??_R4X1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor8* @"\01??_R0?AUX1@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3X1@@8" }
+// CHECK: @"\01??_R4C@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUC@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3C@@8" }
+// CHECK: @"\01??_R0?AUC@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUC@@\00" }
+// CHECK: @"\01??_R3C@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 3, %rtti.BaseClassDescriptor** getelementptr inbounds ([4 x %rtti.BaseClassDescriptor*]* @"\01??_R2C@@8", i32 0, i32 0) }
+// CHECK: @"\01??_R2C@@8" = linkonce_odr constant [4 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@C@@8", %rtti.BaseClassDescriptor* @"\01??_R13?0A@EA@B@@8", %rtti.BaseClassDescriptor* @"\01??_R13?0A@EA@A@@8", %rtti.BaseClassDescriptor* null]
+// CHECK: @"\01??_R1A@?0A@EA@C@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUC@@@8" to i8*), i32 2, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3C@@8" }
+// CHECK: @"\01??_R13?0A@EA@B@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUB@@@8" to i8*), i32 1, i32 4, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3B@@8" }
+// CHECK: @"\01??_R0?AUB@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUB@@\00" }
+// CHECK: @"\01??_R3B@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 2, %rtti.BaseClassDescriptor** getelementptr inbounds ([3 x %rtti.BaseClassDescriptor*]* @"\01??_R2B@@8", i32 0, i32 0) }
+// CHECK: @"\01??_R2B@@8" = linkonce_odr constant [3 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@B@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@A@@8", %rtti.BaseClassDescriptor* null]
+// CHECK: @"\01??_R1A@?0A@EA@B@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUB@@@8" to i8*), i32 1, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3B@@8" }
+// CHECK: @"\01??_R1A@?0A@EA@A@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUA@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3A@@8" }
+// CHECK: @"\01??_R0?AUA@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUA@@\00" }
+// CHECK: @"\01??_R3A@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, %rtti.BaseClassDescriptor** getelementptr inbounds ([2 x %rtti.BaseClassDescriptor*]* @"\01??_R2A@@8", i32 0, i32 0) }
+// CHECK: @"\01??_R2A@@8" = linkonce_odr constant [2 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@A@@8", %rtti.BaseClassDescriptor* null]
+// CHECK: @"\01??_R13?0A@EA@A@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUA@@@8" to i8*), i32 0, i32 4, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3A@@8" }
+// CHECK: @"\01??_R4Y@@6BZ@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AVY@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3Y@@8" }
+// CHECK: @"\01??_R0?AVY@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AVY@@\00" }
+// CHECK: @"\01??_R3Y@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 3, i32 9, %rtti.BaseClassDescriptor** getelementptr inbounds ([10 x %rtti.BaseClassDescriptor*]* @"\01??_R2Y@@8", i32 0, i32 0) }
+// CHECK: @"\01??_R2Y@@8" = linkonce_odr constant [10 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@Y@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EN@Z@@8", %rtti.BaseClassDescriptor* @"\01??_R13?0A@EN@W@@8", %rtti.BaseClassDescriptor* @"\01??_R17?0A@EN@M@@8", %rtti.BaseClassDescriptor* @"\01??_R17?0A@EN@N@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@33FN@V@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@33EJ@X@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@33FN@V@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@33EJ@X@@8", %rtti.BaseClassDescriptor* null]
+// CHECK: @"\01??_R1A@?0A@EA@Y@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AVY@@@8" to i8*), i32 8, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3Y@@8" }
+// CHECK: @"\01??_R1A@?0A@EN@Z@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AVZ@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 77, %rtti.ClassHierarchyDescriptor* @"\01??_R3Z@@8" }
+// CHECK: @"\01??_R0?AVZ@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AVZ@@\00" }
+// CHECK: @"\01??_R3Z@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, %rtti.BaseClassDescriptor** getelementptr inbounds ([2 x %rtti.BaseClassDescriptor*]* @"\01??_R2Z@@8", i32 0, i32 0) }
+// CHECK: @"\01??_R2Z@@8" = linkonce_odr constant [2 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@Z@@8", %rtti.BaseClassDescriptor* null]
+// CHECK: @"\01??_R1A@?0A@EA@Z@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AVZ@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3Z@@8" }
+// CHECK: @"\01??_R13?0A@EN@W@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AVW@@@8" to i8*), i32 4, i32 4, i32 -1, i32 0, i32 77, %rtti.ClassHierarchyDescriptor* @"\01??_R3W@@8" }
+// CHECK: @"\01??_R0?AVW@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AVW@@\00" }
+// CHECK: @"\01??_R3W@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 3, i32 5, %rtti.BaseClassDescriptor** getelementptr inbounds ([6 x %rtti.BaseClassDescriptor*]* @"\01??_R2W@@8", i32 0, i32 0) }
+// CHECK: @"\01??_R2W@@8" = linkonce_odr constant [6 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@W@@8", %rtti.BaseClassDescriptor* @"\01??_R13?0A@EN@M@@8", %rtti.BaseClassDescriptor* @"\01??_R13?0A@EN@N@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@A@3FN@V@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@A@3EJ@X@@8", %rtti.BaseClassDescriptor* null]
+// CHECK: @"\01??_R1A@?0A@EA@W@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AVW@@@8" to i8*), i32 4, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3W@@8" }
+// CHECK: @"\01??_R13?0A@EN@M@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUM@@@8" to i8*), i32 1, i32 4, i32 -1, i32 0, i32 77, %rtti.ClassHierarchyDescriptor* @"\01??_R3M@@8" }
+// CHECK: @"\01??_R0?AUM@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUM@@\00" }
+// CHECK: @"\01??_R3M@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 2, %rtti.BaseClassDescriptor** getelementptr inbounds ([3 x %rtti.BaseClassDescriptor*]* @"\01??_R2M@@8", i32 0, i32 0) }
+// CHECK: @"\01??_R2M@@8" = linkonce_odr constant [3 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@M@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EN@N@@8", %rtti.BaseClassDescriptor* null]
+// CHECK: @"\01??_R1A@?0A@EA@M@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUM@@@8" to i8*), i32 1, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3M@@8" }
+// CHECK: @"\01??_R1A@?0A@EN@N@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUN@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 77, %rtti.ClassHierarchyDescriptor* @"\01??_R3N@@8" }
+// CHECK: @"\01??_R0?AUN@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUN@@\00" }
+// CHECK: @"\01??_R3N@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, %rtti.BaseClassDescriptor** getelementptr inbounds ([2 x %rtti.BaseClassDescriptor*]* @"\01??_R2N@@8", i32 0, i32 0) }
+// CHECK: @"\01??_R2N@@8" = linkonce_odr constant [2 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@N@@8", %rtti.BaseClassDescriptor* null]
+// CHECK: @"\01??_R1A@?0A@EA@N@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUN@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3N@@8" }
+// CHECK: @"\01??_R13?0A@EN@N@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUN@@@8" to i8*), i32 0, i32 4, i32 -1, i32 0, i32 77, %rtti.ClassHierarchyDescriptor* @"\01??_R3N@@8" }
+// CHECK: @"\01??_R1A@A@3FN@V@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AVV@@@8" to i8*), i32 1, i32 0, i32 0, i32 4, i32 93, %rtti.ClassHierarchyDescriptor* @"\01??_R3V@@8" }
+// CHECK: @"\01??_R0?AVV@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AVV@@\00" }
+// CHECK: @"\01??_R3V@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 2, %rtti.BaseClassDescriptor** getelementptr inbounds ([3 x %rtti.BaseClassDescriptor*]* @"\01??_R2V@@8", i32 0, i32 0) }
+// CHECK: @"\01??_R2V@@8" = linkonce_odr constant [3 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@V@@8", %rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@X@@8", %rtti.BaseClassDescriptor* null]
+// CHECK: @"\01??_R1A@?0A@EA@V@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AVV@@@8" to i8*), i32 1, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3V@@8" }
+// CHECK: @"\01??_R1A@?0A@EA@X@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUX@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 64, %rtti.ClassHierarchyDescriptor* @"\01??_R3X@@8" }
+// CHECK: @"\01??_R0?AUX@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUX@@\00" }
+// CHECK: @"\01??_R3X@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, %rtti.BaseClassDescriptor** getelementptr inbounds ([2 x %rtti.BaseClassDescriptor*]* @"\01??_R2X@@8", i32 0, i32 0) }
+// CHECK: @"\01??_R2X@@8" = linkonce_odr constant [2 x %rtti.BaseClassDescriptor*] [%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@X@@8", %rtti.BaseClassDescriptor* null]
+// CHECK: @"\01??_R1A@A@3EJ@X@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUX@@@8" to i8*), i32 0, i32 0, i32 0, i32 4, i32 73, %rtti.ClassHierarchyDescriptor* @"\01??_R3X@@8" }
+// CHECK: @"\01??_R17?0A@EN@M@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUM@@@8" to i8*), i32 1, i32 8, i32 -1, i32 0, i32 77, %rtti.ClassHierarchyDescriptor* @"\01??_R3M@@8" }
+// CHECK: @"\01??_R17?0A@EN@N@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUN@@@8" to i8*), i32 0, i32 8, i32 -1, i32 0, i32 77, %rtti.ClassHierarchyDescriptor* @"\01??_R3N@@8" }
+// CHECK: @"\01??_R1A@33FN@V@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AVV@@@8" to i8*), i32 1, i32 0, i32 4, i32 4, i32 93, %rtti.ClassHierarchyDescriptor* @"\01??_R3V@@8" }
+// CHECK: @"\01??_R1A@33EJ@X@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUX@@@8" to i8*), i32 0, i32 0, i32 4, i32 4, i32 73, %rtti.ClassHierarchyDescriptor* @"\01??_R3X@@8" }
+// CHECK: @"\01??_R4Y@@6BW@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 8, i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AVY@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3Y@@8" }
+// CHECK: @"\01??_R4W@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 4, i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AVW@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3W@@8" }
+// CHECK: @"\01??_R4Z@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AVZ@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3Z@@8" }
+// CHECK: @"\01??_R4V@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AVV@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3V@@8" }
+// CHECK: @"\01??_R4X@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUX@@@8" to i8*), %rtti.ClassHierarchyDescriptor* @"\01??_R3X@@8" }
+
+// X64: @"\01??_R4B2@@6BZ2@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 16, i32 4, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUB2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3B2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4B2@@6BZ2@@@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R0?AUB2@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUB2@@\00" }
+// X64: @"\01??_R3B2@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 3, i32 4, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([5 x i32]* @"\01??_R2B2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R2B2@@8" = linkonce_odr constant [5 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@B2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@A@3FA@A2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@A@3EA@Z2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R17A@3EA@Y2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0]
+// X64: @"\01??_R1A@?0A@EA@B2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUB2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 3, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3B2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R1A@A@3FA@A2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUA2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 2, i32 0, i32 0, i32 4, i32 80, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3A2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R0?AUA2@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUA2@@\00" }
+// X64: @"\01??_R3A2@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 1, i32 3, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([4 x i32]* @"\01??_R2A2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R2A2@@8" = linkonce_odr constant [4 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@A2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@Z2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R17?0A@EA@Y2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0]
+// X64: @"\01??_R1A@?0A@EA@A2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUA2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 2, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3A2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R1A@?0A@EA@Z2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUZ2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3Z2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R0?AUZ2@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUZ2@@\00" }
+// X64: @"\01??_R3Z2@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([2 x i32]* @"\01??_R2Z2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R2Z2@@8" = linkonce_odr constant [2 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@Z2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0]
+// X64: @"\01??_R17?0A@EA@Y2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUY2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 8, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3Y2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R0?AUY2@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUY2@@\00" }
+// X64: @"\01??_R3Y2@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([2 x i32]* @"\01??_R2Y2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R2Y2@@8" = linkonce_odr constant [2 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@Y2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0]
+// X64: @"\01??_R1A@?0A@EA@Y2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUY2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3Y2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R1A@A@3EA@Z2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUZ2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 0, i32 4, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3Z2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R17A@3EA@Y2@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUY2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 8, i32 0, i32 4, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3Y2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R4B2@@6BY2@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 24, i32 12, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUB2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3B2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4B2@@6BY2@@@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R4A2@@6BZ2@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUA2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3A2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4A2@@6BZ2@@@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R4A2@@6BY2@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 8, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUA2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3A2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4A2@@6BY2@@@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R4Y2@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUY2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3Y2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4Y2@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R4Z2@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUZ2@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3Z2@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4Z2@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R4B1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 16, i32 4, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUB1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3B1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4B1@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R0?AUB1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUB1@@\00" }
+// X64: @"\01??_R3B1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 2, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([3 x i32]* @"\01??_R2B1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R2B1@@8" = linkonce_odr constant [3 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@B1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@A@3FA@A1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0]
+// X64: @"\01??_R1A@?0A@EA@B1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUB1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3B1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R1A@A@3FA@A1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUA1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 0, i32 4, i32 80, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3A1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R0?AUA1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUA1@@\00" }
+// X64: @"\01??_R3A1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([2 x i32]* @"\01??_R2A1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R2A1@@8" = linkonce_odr constant [2 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@A1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0]
+// X64: @"\01??_R1A@?0A@EA@A1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUA1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3A1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R4A1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUA1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3A1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4A1@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R4Y1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 8, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUY1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3Y1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4Y1@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R0?AUY1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUY1@@\00" }
+// X64: @"\01??_R3Y1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 3, i32 6, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([7 x i32]* @"\01??_R2Y1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R2Y1@@8" = linkonce_odr constant [7 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@Y1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@W1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@A@3FA@V1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@A@3EA@X1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@A@3FA@V1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@A@3EA@X1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0]
+// X64: @"\01??_R1A@?0A@EA@Y1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUY1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 5, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3Y1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R1A@?0A@EA@W1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUW1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 2, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3W1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R0?AUW1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUW1@@\00" }
+// X64: @"\01??_R3W1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 3, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([4 x i32]* @"\01??_R2W1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R2W1@@8" = linkonce_odr constant [4 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@W1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@A@3FA@V1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@A@3EA@X1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0]
+// X64: @"\01??_R1A@A@3FA@V1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUV1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 0, i32 0, i32 4, i32 80, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3V1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R0?AUV1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUV1@@\00" }
+// X64: @"\01??_R3V1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 2, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([3 x i32]* @"\01??_R2V1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R2V1@@8" = linkonce_odr constant [3 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@V1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@X1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0]
+// X64: @"\01??_R1A@?0A@EA@V1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUV1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3V1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R1A@?0A@EA@X1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUX1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3X1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R0?AUX1@@@8" = linkonce_odr global %rtti.TypeDescriptor8 { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUX1@@\00" }
+// X64: @"\01??_R3X1@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([2 x i32]* @"\01??_R2X1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R2X1@@8" = linkonce_odr constant [2 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@X1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0]
+// X64: @"\01??_R1A@A@3EA@X1@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUX1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 0, i32 4, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3X1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R4W1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 8, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUW1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3W1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4W1@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R4V1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUV1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3V1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4V1@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R4X1@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor8* @"\01??_R0?AUX1@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3X1@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4X1@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R4C@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUC@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3C@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4C@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R0?AUC@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUC@@\00" }
+// X64: @"\01??_R3C@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 3, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([4 x i32]* @"\01??_R2C@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R2C@@8" = linkonce_odr constant [4 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@C@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R17?0A@EA@B@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R17?0A@EA@A@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0]
+// X64: @"\01??_R1A@?0A@EA@C@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUC@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 2, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3C@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R17?0A@EA@B@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUB@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 8, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3B@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R0?AUB@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUB@@\00" }
+// X64: @"\01??_R3B@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 2, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([3 x i32]* @"\01??_R2B@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R2B@@8" = linkonce_odr constant [3 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@B@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@A@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0]
+// X64: @"\01??_R1A@?0A@EA@B@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUB@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3B@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R1A@?0A@EA@A@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUA@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3A@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R0?AUA@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUA@@\00" }
+// X64: @"\01??_R3A@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([2 x i32]* @"\01??_R2A@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R2A@@8" = linkonce_odr constant [2 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@A@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0]
+// X64: @"\01??_R17?0A@EA@A@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUA@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 8, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3A@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R4Y@@6BZ@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AVY@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3Y@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4Y@@6BZ@@@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R0?AVY@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AVY@@\00" }
+// X64: @"\01??_R3Y@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 3, i32 9, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([10 x i32]* @"\01??_R2Y@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R2Y@@8" = linkonce_odr constant [10 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@Y@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EN@Z@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R17?0A@EN@W@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1BA@?0A@EN@M@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1BA@?0A@EN@N@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@73FN@V@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@73EJ@X@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@73FN@V@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@73EJ@X@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0]
+// X64: @"\01??_R1A@?0A@EA@Y@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AVY@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 8, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3Y@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R1A@?0A@EN@Z@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AVZ@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 -1, i32 0, i32 77, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3Z@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R0?AVZ@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AVZ@@\00" }
+// X64: @"\01??_R3Z@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([2 x i32]* @"\01??_R2Z@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R2Z@@8" = linkonce_odr constant [2 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@Z@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0]
+// X64: @"\01??_R1A@?0A@EA@Z@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AVZ@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3Z@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R17?0A@EN@W@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AVW@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 4, i32 8, i32 -1, i32 0, i32 77, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3W@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R0?AVW@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AVW@@\00" }
+// X64: @"\01??_R3W@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 3, i32 5, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([6 x i32]* @"\01??_R2W@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R2W@@8" = linkonce_odr constant [6 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@W@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R17?0A@EN@M@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R17?0A@EN@N@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@A@3FN@V@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@A@3EJ@X@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0]
+// X64: @"\01??_R1A@?0A@EA@W@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AVW@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 4, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3W@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R17?0A@EN@M@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUM@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 8, i32 -1, i32 0, i32 77, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3M@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R0?AUM@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUM@@\00" }
+// X64: @"\01??_R3M@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 2, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([3 x i32]* @"\01??_R2M@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R2M@@8" = linkonce_odr constant [3 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@M@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EN@N@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0]
+// X64: @"\01??_R1A@?0A@EA@M@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUM@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3M@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R1A@?0A@EN@N@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUN@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 -1, i32 0, i32 77, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3N@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R0?AUN@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUN@@\00" }
+// X64: @"\01??_R3N@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([2 x i32]* @"\01??_R2N@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R2N@@8" = linkonce_odr constant [2 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@N@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0]
+// X64: @"\01??_R1A@?0A@EA@N@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUN@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3N@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R17?0A@EN@N@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUN@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 8, i32 -1, i32 0, i32 77, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3N@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R1A@A@3FN@V@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AVV@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 0, i32 0, i32 4, i32 93, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3V@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R0?AVV@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AVV@@\00" }
+// X64: @"\01??_R3V@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 2, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([3 x i32]* @"\01??_R2V@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R2V@@8" = linkonce_odr constant [3 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@V@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@X@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0]
+// X64: @"\01??_R1A@?0A@EA@V@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AVV@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3V@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R1A@?0A@EA@X@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUX@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3X@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R0?AUX@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUX@@\00" }
+// X64: @"\01??_R3X@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([2 x i32]* @"\01??_R2X@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R2X@@8" = linkonce_odr constant [2 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"\01??_R1A@?0A@EA@X@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0]
+// X64: @"\01??_R1A@A@3EJ@X@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUX@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 0, i32 4, i32 73, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3X@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R1BA@?0A@EN@M@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUM@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 16, i32 -1, i32 0, i32 77, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3M@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R1BA@?0A@EN@N@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUN@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 16, i32 -1, i32 0, i32 77, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3N@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R1A@73FN@V@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AVV@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 1, i32 0, i32 8, i32 4, i32 93, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3V@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R1A@73EJ@X@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUX@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 8, i32 4, i32 73, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3X@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R4Y@@6BW@@@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 16, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AVY@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3Y@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4Y@@6BW@@@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R4W@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 8, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AVW@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3W@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4W@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R4Z@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AVZ@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3Z@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4Z@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R4V@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AVV@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3V@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4V@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
+// X64: @"\01??_R4X@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"\01??_R0?AUX@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"\01??_R3X@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"\01??_R4X@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }
diff --git a/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp b/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
index d0750e6ebe91..96c23c66b896 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 -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
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fno-rtti | FileCheck -check-prefix WIN32 %s
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-pc-win32 -mconstructor-aliases -fno-rtti | FileCheck -check-prefix WIN64 %s
struct Empty {};
@@ -47,6 +47,20 @@ struct Big {
int a, b, c, d, e, f;
};
+struct BigWithDtor {
+ BigWithDtor();
+ ~BigWithDtor();
+ int a, b, c, d, e, f;
+};
+
+// WIN32: declare void @"{{.*take_bools_and_chars.*}}"
+// WIN32: (<{ i8, [3 x i8], i8, [3 x i8], %struct.SmallWithDtor,
+// WIN32: i8, [3 x i8], i8, [3 x i8], i32, i8, [3 x i8] }>* inalloca)
+void take_bools_and_chars(char a, char b, SmallWithDtor c, char d, bool e, int f, bool g);
+void call_bools_and_chars() {
+ take_bools_and_chars('A', 'B', SmallWithDtor(), 'D', true, 13, false);
+}
+
// Returning structs that fit into a register.
Small small_return() { return Small(); }
// LINUX-LABEL: define void @_Z12small_returnv(%struct.Small* noalias sret %agg.result)
@@ -103,18 +117,46 @@ void small_arg_with_ctor(SmallWithCtor s) {}
// 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: define void @"\01?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(<{ %struct.SmallWithDtor }>* inalloca) {{.*}} {
+// WIN32: call x86_thiscallcc void @"\01??1SmallWithDtor@@QAE@XZ"
// 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: define void @"\01?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(i32 %s.coerce) {{.*}} {
+// WIN64: call void @"\01??1SmallWithDtor@@QEAA@XZ"
// WIN64: }
+void call_small_arg_with_dtor() {
+ small_arg_with_dtor(SmallWithDtor());
+}
+// The temporary is copied, so it's destroyed in the caller as well as the
+// callee.
+// WIN64-LABEL: define void @"\01?call_small_arg_with_dtor@@YAXXZ"()
+// WIN64: call %struct.SmallWithDtor* @"\01??0SmallWithDtor@@QEAA@XZ"
+// WIN64: call void @"\01?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(i32 %{{.*}})
+// WIN64: call void @"\01??1SmallWithDtor@@QEAA@XZ"
+// WIN64: ret void
+
// 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: define void @"\01?ref_small_arg_with_dtor@@YAXABUSmallWithDtor@@@Z"(%struct.SmallWithDtor* dereferenceable({{[0-9]+}}) %s) {{.*}} {
// WIN32-NOT: call x86_thiscallcc void @"\01??1SmallWithDtor@@QAE@XZ"
// WIN32: }
+// WIN64-LABEL: define void @"\01?ref_small_arg_with_dtor@@YAXAEBUSmallWithDtor@@@Z"(%struct.SmallWithDtor* dereferenceable({{[0-9]+}}) %s)
+
+void big_arg_with_dtor(BigWithDtor s) {}
+// WIN64-LABEL: define void @"\01?big_arg_with_dtor@@YAXUBigWithDtor@@@Z"(%struct.BigWithDtor* %s)
+// WIN64: call void @"\01??1BigWithDtor@@QEAA@XZ"
+// WIN64: }
+
+void call_big_arg_with_dtor() {
+ big_arg_with_dtor(BigWithDtor());
+}
+// We can elide the copy of the temporary in the caller, because this object is
+// larger than 8 bytes and is passed indirectly.
+// WIN64-LABEL: define void @"\01?call_big_arg_with_dtor@@YAXXZ"()
+// WIN64: call %struct.BigWithDtor* @"\01??0BigWithDtor@@QEAA@XZ"
+// WIN64: call void @"\01?big_arg_with_dtor@@YAXUBigWithDtor@@@Z"(%struct.BigWithDtor* %{{.*}})
+// WIN64-NOT: call void @"\01??1BigWithDtor@@QEAA@XZ"
+// WIN64: ret void
// Test that temporaries passed by reference are destroyed in the caller.
void temporary_ref_with_dtor() {
@@ -141,60 +183,65 @@ void eh_cleanup_arg_with_dtor() {
void small_arg_with_vftable(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)
+// WIN32: define void @"\01?small_arg_with_vftable@@YAXUSmallWithVftable@@@Z"(<{ %struct.SmallWithVftable }>* inalloca)
+// WIN64: define void @"\01?small_arg_with_vftable@@YAXUSmallWithVftable@@@Z"(%struct.SmallWithVftable* %s)
void medium_arg_with_copy_ctor(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)
+// WIN32: define void @"\01?medium_arg_with_copy_ctor@@YAXUMediumWithCopyCtor@@@Z"(<{ %struct.MediumWithCopyCtor }>* inalloca)
+// WIN64: define void @"\01?medium_arg_with_copy_ctor@@YAXUMediumWithCopyCtor@@@Z"(%struct.MediumWithCopyCtor* %s)
void big_arg(Big 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)
-// FIXME: Add WIN64 tests. Currently, even the method manglings are wrong (sic!).
class Class {
public:
Small thiscall_method_small() { return Small(); }
// LINUX: define {{.*}} void @_ZN5Class21thiscall_method_smallEv(%struct.Small* noalias sret %agg.result, %class.Class* %this)
- // WIN32: define {{.*}} x86_thiscallcc void @"\01?thiscall_method_small@Class@@QAE?AUSmall@@XZ"(%struct.Small* noalias sret %agg.result, %class.Class* %this)
+ // WIN32: define {{.*}} x86_thiscallcc void @"\01?thiscall_method_small@Class@@QAE?AUSmall@@XZ"(%class.Class* %this, %struct.Small* noalias sret %agg.result)
+ // WIN64: define linkonce_odr void @"\01?thiscall_method_small@Class@@QEAA?AUSmall@@XZ"(%class.Class* %this, %struct.Small* noalias sret %agg.result)
SmallWithCtor thiscall_method_small_with_ctor() { return SmallWithCtor(); }
// LINUX: define {{.*}} void @_ZN5Class31thiscall_method_small_with_ctorEv(%struct.SmallWithCtor* noalias sret %agg.result, %class.Class* %this)
- // WIN32: define {{.*}} x86_thiscallcc void @"\01?thiscall_method_small_with_ctor@Class@@QAE?AUSmallWithCtor@@XZ"(%struct.SmallWithCtor* noalias sret %agg.result, %class.Class* %this)
+ // WIN32: define {{.*}} x86_thiscallcc void @"\01?thiscall_method_small_with_ctor@Class@@QAE?AUSmallWithCtor@@XZ"(%class.Class* %this, %struct.SmallWithCtor* noalias sret %agg.result)
+ // WIN64: define linkonce_odr void @"\01?thiscall_method_small_with_ctor@Class@@QEAA?AUSmallWithCtor@@XZ"(%class.Class* %this, %struct.SmallWithCtor* noalias sret %agg.result)
Small __cdecl cdecl_method_small() { return Small(); }
// LINUX: define {{.*}} void @_ZN5Class18cdecl_method_smallEv(%struct.Small* noalias sret %agg.result, %class.Class* %this)
- // FIXME: Interesting, cdecl returns structures differently for instance
- // methods and global functions. This is not supported by Clang yet...
- // FIXME: Replace WIN32-NOT with WIN32 when this is fixed.
- // WIN32-NOT: define {{.*}} void @"\01?cdecl_method_small@Class@@QAA?AUSmall@@XZ"(%struct.Small* noalias sret %agg.result, %class.Class* %this)
+ // WIN32: define {{.*}} void @"\01?cdecl_method_small@Class@@QAA?AUSmall@@XZ"(%class.Class* %this, %struct.Small* noalias sret %agg.result)
+ // WIN64: define linkonce_odr void @"\01?cdecl_method_small@Class@@QEAA?AUSmall@@XZ"(%class.Class* %this, %struct.Small* noalias sret %agg.result)
Big __cdecl cdecl_method_big() { return Big(); }
// LINUX: define {{.*}} void @_ZN5Class16cdecl_method_bigEv(%struct.Big* noalias sret %agg.result, %class.Class* %this)
- // WIN32: define {{.*}} void @"\01?cdecl_method_big@Class@@QAA?AUBig@@XZ"(%struct.Big* noalias sret %agg.result, %class.Class* %this)
+ // WIN32: define {{.*}} void @"\01?cdecl_method_big@Class@@QAA?AUBig@@XZ"(%class.Class* %this, %struct.Big* noalias sret %agg.result)
+ // WIN64: define linkonce_odr void @"\01?cdecl_method_big@Class@@QEAA?AUBig@@XZ"(%class.Class* %this, %struct.Big* noalias sret %agg.result)
void thiscall_method_arg(Empty s) {}
// LINUX: define {{.*}} void @_ZN5Class19thiscall_method_argE5Empty(%class.Class* %this)
// WIN32: define {{.*}} void @"\01?thiscall_method_arg@Class@@QAEXUEmpty@@@Z"(%class.Class* %this, %struct.Empty* byval align 4 %s)
+ // WIN64: define linkonce_odr void @"\01?thiscall_method_arg@Class@@QEAAXUEmpty@@@Z"(%class.Class* %this, i8 %s.coerce)
void thiscall_method_arg(EmptyWithCtor s) {}
// LINUX: define {{.*}} void @_ZN5Class19thiscall_method_argE13EmptyWithCtor(%class.Class* %this)
// WIN32: define {{.*}} void @"\01?thiscall_method_arg@Class@@QAEXUEmptyWithCtor@@@Z"(%class.Class* %this, %struct.EmptyWithCtor* byval align 4 %s)
+ // WIN64: define linkonce_odr void @"\01?thiscall_method_arg@Class@@QEAAXUEmptyWithCtor@@@Z"(%class.Class* %this, i8 %s.coerce)
void thiscall_method_arg(Small s) {}
// LINUX: define {{.*}} void @_ZN5Class19thiscall_method_argE5Small(%class.Class* %this, %struct.Small* byval align 4 %s)
// WIN32: define {{.*}} void @"\01?thiscall_method_arg@Class@@QAEXUSmall@@@Z"(%class.Class* %this, %struct.Small* byval align 4 %s)
+ // WIN64: define linkonce_odr void @"\01?thiscall_method_arg@Class@@QEAAXUSmall@@@Z"(%class.Class* %this, i32 %s.coerce)
void thiscall_method_arg(SmallWithCtor s) {}
// LINUX: define {{.*}} void @_ZN5Class19thiscall_method_argE13SmallWithCtor(%class.Class* %this, %struct.SmallWithCtor* byval align 4 %s)
// WIN32: define {{.*}} void @"\01?thiscall_method_arg@Class@@QAEXUSmallWithCtor@@@Z"(%class.Class* %this, %struct.SmallWithCtor* byval align 4 %s)
+ // WIN64: define linkonce_odr void @"\01?thiscall_method_arg@Class@@QEAAXUSmallWithCtor@@@Z"(%class.Class* %this, i32 %s.coerce)
void thiscall_method_arg(Big s) {}
// LINUX: define {{.*}} void @_ZN5Class19thiscall_method_argE3Big(%class.Class* %this, %struct.Big* byval align 4 %s)
// WIN32: define {{.*}} void @"\01?thiscall_method_arg@Class@@QAEXUBig@@@Z"(%class.Class* %this, %struct.Big* byval align 4 %s)
+ // WIN64: define linkonce_odr void @"\01?thiscall_method_arg@Class@@QEAAXUBig@@@Z"(%class.Class* %this, %struct.Big* %s)
};
void use_class() {
@@ -218,8 +265,8 @@ struct 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: define void @"\01?g@@YAXUX@@@Z"(<{ %struct.X, [3 x i8] }>* inalloca) {{.*}} {
+// WIN32: call x86_thiscallcc void @"\01??1X@@QAE@XZ"(%struct.X* {{.*}})
// WIN32: }
void f() {
g(X());
@@ -227,3 +274,72 @@ void f() {
// WIN32: define void @"\01?f@@YAXXZ"() {{.*}} {
// WIN32-NOT: call {{.*}} @"\01??1X@@QAE@XZ"
// WIN32: }
+
+
+namespace test2 {
+// We used to crash on this due to the mixture of POD byval and non-trivial
+// byval.
+
+struct NonTrivial {
+ NonTrivial();
+ NonTrivial(const NonTrivial &o);
+ ~NonTrivial();
+ int a;
+};
+struct POD { int b; };
+
+int foo(NonTrivial a, POD b);
+void bar() {
+ POD b;
+ b.b = 13;
+ int c = foo(NonTrivial(), b);
+}
+// WIN32-LABEL: define void @"\01?bar@test2@@YAXXZ"() {{.*}} {
+// WIN32: %[[argmem:[^ ]*]] = alloca inalloca [[argmem_ty:<{ %"struct.test2::NonTrivial", %"struct.test2::POD" }>]]
+// WIN32: getelementptr inbounds [[argmem_ty]]* %[[argmem]], i32 0, i32 1
+// WIN32: call void @llvm.memcpy
+// WIN32: getelementptr inbounds [[argmem_ty]]* %[[argmem]], i32 0, i32 0
+// WIN32: call x86_thiscallcc %"struct.test2::NonTrivial"* @"\01??0NonTrivial@test2@@QAE@XZ"
+// WIN32: call i32 @"\01?foo@test2@@YAHUNonTrivial@1@UPOD@1@@Z"([[argmem_ty]]* inalloca %argmem)
+// WIN32: ret void
+// WIN32: }
+
+}
+
+namespace test3 {
+
+// Check that we padded the inalloca struct to a multiple of 4.
+struct NonTrivial {
+ NonTrivial();
+ NonTrivial(const NonTrivial &o);
+ ~NonTrivial();
+ int a;
+};
+void foo(NonTrivial a, bool b) { }
+// WIN32-LABEL: define void @"\01?foo@test3@@YAXUNonTrivial@1@_N@Z"(<{ %"struct.test3::NonTrivial", i8, [3 x i8] }>* inalloca)
+
+}
+
+// We would crash here because the later definition of ForwardDeclare1 results
+// in a different IR type for the value we want to store. However, the alloca's
+// type will use the argument type selected by fn1.
+struct ForwardDeclare1;
+
+typedef void (*FnPtr1)(ForwardDeclare1);
+void fn1(FnPtr1 a, SmallWithDtor b) { }
+
+struct ForwardDeclare1 {};
+
+void fn2(FnPtr1 a, SmallWithDtor b) { fn1(a, b); };
+// WIN32-LABEL: define void @"\01?fn2@@YAXP6AXUForwardDeclare1@@@ZUSmallWithDtor@@@Z"
+// WIN32: %[[a:[^ ]*]] = getelementptr inbounds [[argmem_ty:<{ {}\*, %struct.SmallWithDtor }>]]* %{{.*}}, i32 0, i32 0
+// WIN32: %[[a1:[^ ]*]] = bitcast {}** %[[a]] to void [[dst_ty:\(%struct.ForwardDeclare1\*\)\*]]*
+// WIN32: %[[argmem:[^ ]*]] = alloca inalloca [[argmem_ty]]
+// WIN32: %[[gep1:[^ ]*]] = getelementptr inbounds [[argmem_ty]]* %[[argmem]], i32 0, i32 1
+// WIN32: %[[bc1:[^ ]*]] = bitcast %struct.SmallWithDtor* %[[gep1]] to i8*
+// WIN32: call void @llvm.memcpy.p0i8.p0i8.i32(i8* %[[bc1]], i8* {{.*}}, i32 4, i32 4, i1 false)
+// WIN32: %[[a2:[^ ]*]] = load void [[dst_ty]]* %[[a1]], align 4
+// WIN32: %[[gep2:[^ ]*]] = getelementptr inbounds [[argmem_ty]]* %[[argmem]], i32 0, i32 0
+// WIN32: %[[addr:[^ ]*]] = bitcast {}** %[[gep2]] to void [[dst_ty]]*
+// WIN32: store void [[dst_ty]] %[[a2]], void [[dst_ty]]* %[[addr]], align 4
+// WIN32: call void @"\01?fn1@@YAXP6AXUForwardDeclare1@@@ZUSmallWithDtor@@@Z"([[argmem_ty]]* inalloca %[[argmem]])
diff --git a/test/CodeGenCXX/microsoft-abi-static-initializers.cpp b/test/CodeGenCXX/microsoft-abi-static-initializers.cpp
index c0b972212357..5f74c54c1c45 100644
--- a/test/CodeGenCXX/microsoft-abi-static-initializers.cpp
+++ b/test/CodeGenCXX/microsoft-abi-static-initializers.cpp
@@ -1,8 +1,9 @@
-// RUN: %clang_cc1 -emit-llvm %s -o - -mconstructor-aliases -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s
+// RUN: %clang_cc1 -fms-extensions -emit-llvm %s -o - -mconstructor-aliases -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 }]
+// CHECK: @llvm.global_ctors = appending global [2 x { i32, void ()*, i8* }]
+// CHECK: [{ i32, void ()*, i8* } { i32 65535, void ()* @"\01??__Efoo@?$B@H@@2VA@@A@YAXXZ",
+// CHECK: i8* bitcast (%class.A* @"\01?foo@?$B@H@@2VA@@A" to i8*) },
+// CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__sub_I_microsoft_abi_static_initializers.cpp, i8* null }]
struct S {
S();
@@ -11,21 +12,34 @@ struct S {
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: define internal void @"\01??__Es@@YAXXZ"()
+// CHECK: call x86_thiscallcc %struct.S* @"\01??0S@@QAE@XZ"
// CHECK: call i32 @atexit(void ()* @"\01??__Fs@@YAXXZ")
// CHECK: ret void
-// CHECK: define internal void @"\01??__Fs@@YAXXZ"() [[NUW]] {
+// CHECK: define internal void @"\01??__Fs@@YAXXZ"()
// CHECK: call x86_thiscallcc void @"\01??1S@@QAE@XZ"
// CHECK: ret void
+// These globals should use distinct guard variables, and not different bits of
+// the same global.
+__declspec(selectany) S selectany1;
+__declspec(selectany) S selectany2;
+// CHECK: define linkonce_odr void @"\01??__Eselectany1@@YAXXZ"()
+// CHECK-NOT: @"\01??_Bselectany1
+// CHECK: call x86_thiscallcc %struct.S* @"\01??0S@@QAE@XZ"
+// CHECK: ret void
+// CHECK: define linkonce_odr void @"\01??__Eselectany2@@YAXXZ"()
+// CHECK-NOT: @"\01??_Bselectany2
+// CHECK: call x86_thiscallcc %struct.S* @"\01??0S@@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: load i32* @"\01?$S1@?0??StaticLocal@@YAXXZ@4IA"
+// CHECK: store i32 {{.*}}, i32* @"\01?$S1@?0??StaticLocal@@YAXXZ@4IA"
// CHECK: ret
void MultipleStatics() {
@@ -66,7 +80,7 @@ void MultipleStatics() {
static S S35;
}
// CHECK-LABEL: define void @"\01?MultipleStatics@@YAXXZ"()
-// CHECK: load i32* @"\01?$S1@?1??MultipleStatics@@YAXXZ@4IA"
+// CHECK: load i32* @"\01?$S1@?0??MultipleStatics@@YAXXZ@4IA"
// CHECK: and i32 {{.*}}, 1
// CHECK: and i32 {{.*}}, 2
// CHECK: and i32 {{.*}}, 4
@@ -74,7 +88,7 @@ void MultipleStatics() {
// CHECK: and i32 {{.*}}, 16
// ...
// CHECK: and i32 {{.*}}, -2147483648
-// CHECK: load i32* @"\01?$S1@?1??MultipleStatics@@YAXXZ@4IA1"
+// CHECK: load i32* @"\01?$S1@?0??MultipleStatics@@YAXXZ@4IA1"
// CHECK: and i32 {{.*}}, 1
// CHECK: and i32 {{.*}}, 2
// CHECK: and i32 {{.*}}, 4
@@ -85,6 +99,7 @@ class A {
public:
A() {}
~A() {}
+ int a;
};
template<typename T>
@@ -104,7 +119,7 @@ inline S &UnreachableStatic() {
return s;
}
-// CHECK-LABEL: define linkonce_odr %struct.S* @"\01?UnreachableStatic@@YAAAUS@@XZ"()
+// CHECK-LABEL: define linkonce_odr dereferenceable({{[0-9]+}}) %struct.S* @"\01?UnreachableStatic@@YAAAUS@@XZ"()
// CHECK: and i32 {{.*}}, 2
// CHECK: or i32 {{.*}}, 2
// CHECK: ret
@@ -114,7 +129,7 @@ inline S &getS() {
return TheS;
}
-// CHECK-LABEL: define linkonce_odr %struct.S* @"\01?getS@@YAAAUS@@XZ"
+// CHECK-LABEL: define linkonce_odr dereferenceable({{[0-9]+}}) %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
@@ -128,27 +143,95 @@ inline S &getS() {
// init.end:
// CHECK: ret %struct.S* @"\01?TheS@?1??getS@@YAAAUS@@XZ@4U2@A"
+inline int enum_in_function() {
+ // CHECK-LABEL: define linkonce_odr i32 @"\01?enum_in_function@@YAHXZ"()
+ static enum e { foo, bar, baz } x;
+ // CHECK: @"\01?x@?1??enum_in_function@@YAHXZ@4W4e@?1??1@YAHXZ@A"
+ static int y;
+ // CHECK: @"\01?y@?1??enum_in_function@@YAHXZ@4HA"
+ return x + y;
+};
+
+struct T {
+ enum e { foo, bar, baz };
+ int enum_in_struct() {
+ // CHECK-LABEL: define linkonce_odr x86_thiscallcc i32 @"\01?enum_in_struct@T@@QAEHXZ"
+ static int x;
+ // CHECK: @"\01?x@?1??enum_in_struct@T@@QAEHXZ@4HA"
+ return x++;
+ }
+};
+
+inline int switch_test(int x) {
+ // CHECK-LABEL: define linkonce_odr i32 @"\01?switch_test@@YAHH@Z"(i32 %x)
+ switch (x) {
+ static int a;
+ // CHECK: @"\01?a@?3??switch_test@@YAHH@Z@4HA"
+ case 0:
+ a++;
+ return 1;
+ case 1:
+ static int b;
+ // CHECK: @"\01?b@?3??switch_test@@YAHH@Z@4HA"
+ return b++;
+ case 2: {
+ static int c;
+ // CHECK: @"\01?c@?4??switch_test@@YAHH@Z@4HA"
+ return b + c++;
+ }
+ };
+}
+
+int f();
+inline void switch_test2() {
+ // CHECK-LABEL: define linkonce_odr void @"\01?switch_test2@@YAXXZ"()
+ // CHECK: @"\01?x@?2??switch_test2@@YAXXZ@4HA"
+ switch (1) default: static int x = f();
+}
+
+namespace DynamicDLLImportInitVSMangling {
+ // Failing to pop the ExprEvalContexts when instantiating a dllimport var with
+ // dynamic initializer would cause subsequent static local numberings to be
+ // incorrect.
+ struct NonPOD { NonPOD(); };
+ template <typename T> struct A { static NonPOD x; };
+ template <typename T> NonPOD A<T>::x;
+ template struct __declspec(dllimport) A<int>;
+
+ inline int switch_test3() {
+ // CHECK-LABEL: define linkonce_odr i32 @"\01?switch_test3@DynamicDLLImportInitVSMangling@@YAHXZ"
+ static int local;
+ // CHECK: @"\01?local@?1??switch_test3@DynamicDLLImportInitVSMangling@@YAHXZ@4HA"
+ return local++;
+ }
+}
+
void force_usage() {
UnreachableStatic();
getS();
(void)B<int>::foo; // (void) - force usage
+ enum_in_function();
+ (void)&T::enum_in_struct;
+ switch_test(1);
+ switch_test2();
+ DynamicDLLImportInitVSMangling::switch_test3();
}
-// 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 ()* @"\01??__Ffoo@?$B@H@@YAXXZ")
+// CHECK: define linkonce_odr void @"\01??__Efoo@?$B@H@@2VA@@A@YAXXZ"()
+// CHECK-NOT: and
+// CHECK-NOT: ?_Bfoo@
+// CHECK: call x86_thiscallcc %class.A* @"\01??0A@@QAE@XZ"
+// CHECK: call i32 @atexit(void ()* @"\01??__Ffoo@?$B@H@@2VA@@A@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 @"\01??__Ffoo@?$B@H@@YAXXZ"
+// CHECK: define internal void @"\01??__Ffoo@?$B@H@@2VA@@A@YAXXZ"
// CHECK: call x86_thiscallcc void @"\01??1A@@QAE@XZ"{{.*}}foo
// CHECK: ret void
-// CHECK: define internal void @_GLOBAL__I_a() [[NUW]] {
+// CHECK: define internal void @_GLOBAL__sub_I_microsoft_abi_static_initializers.cpp()
// 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
index d54520fab72c..f977556aa565 100644
--- a/test/CodeGenCXX/microsoft-abi-structors-alias.cpp
+++ b/test/CodeGenCXX/microsoft-abi-structors-alias.cpp
@@ -1,9 +1,26 @@
-// RUN: %clang_cc1 -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 -fno-rtti -mconstructor-aliases | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 -fno-rtti -mconstructor-aliases -O1 -disable-llvm-optzns | 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"
+// CHECK-DAG: define weak_odr x86_thiscallcc void @"\01??1?$A@D@test1@@AAE@XZ"
+}
+
+namespace test2 {
+struct A {
+ virtual ~A();
+};
+struct B : A {
+ B();
+ virtual ~B();
+};
+
+A::~A() {}
+B::~B() {}
+void foo() {
+ B b;
+}
+// CHECK-DAG: @"\01??1B@test2@@UAE@XZ" = alias bitcast (void (%"struct.test2::A"*)* @"\01??1A@test2@@UAE@XZ" to void (%"struct.test2::B"*)*)
}
diff --git a/test/CodeGenCXX/microsoft-abi-structors.cpp b/test/CodeGenCXX/microsoft-abi-structors.cpp
index c2f1395f47df..7d3992b9940b 100644
--- a/test/CodeGenCXX/microsoft-abi-structors.cpp
+++ b/test/CodeGenCXX/microsoft-abi-structors.cpp
@@ -1,10 +1,12 @@
-// RUN: %clang_cc1 -emit-llvm %s -o - -mconstructor-aliases -cxx-abi microsoft -triple=i386-pc-win32 -fno-rtti > %t
+// RUN: %clang_cc1 -emit-llvm -fno-rtti %s -std=c++11 -o - -mconstructor-aliases -triple=i386-pc-win32 -fno-rtti > %t
// RUN: FileCheck %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: FileCheck --check-prefix DTORS2 %s < %t
+// RUN: FileCheck --check-prefix DTORS3 %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
+// RUN: %clang_cc1 -emit-llvm %s -o - -mconstructor-aliases -triple=x86_64-pc-win32 -fno-rtti | FileCheck --check-prefix DTORS-X64 %s
namespace basic {
@@ -121,6 +123,79 @@ void use_D() { D c; }
} // end namespace basic
+namespace dtor_in_second_nvbase {
+
+struct A {
+ virtual void f(); // A needs vftable to be primary.
+};
+struct B {
+ virtual ~B();
+};
+struct C : A, B {
+ virtual ~C();
+};
+
+C::~C() {
+// CHECK-LABEL: define x86_thiscallcc void @"\01??1C@dtor_in_second_nvbase@@UAE@XZ"
+// CHECK: (%"struct.dtor_in_second_nvbase::C"* %this)
+// No this adjustment!
+// CHECK-NOT: getelementptr
+// CHECK: load %"struct.dtor_in_second_nvbase::C"** %{{.*}}
+// Now we this-adjust before calling ~B.
+// CHECK: bitcast %"struct.dtor_in_second_nvbase::C"* %{{.*}} to i8*
+// CHECK: getelementptr inbounds i8* %{{.*}}, i64 4
+// CHECK: bitcast i8* %{{.*}} to %"struct.dtor_in_second_nvbase::B"*
+// CHECK: call x86_thiscallcc void @"\01??1B@dtor_in_second_nvbase@@UAE@XZ"
+// CHECK: (%"struct.dtor_in_second_nvbase::B"* %{{.*}})
+// CHECK: ret void
+}
+
+void foo() {
+ C c;
+}
+// DTORS2-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_EC@dtor_in_second_nvbase@@W3AEPAXI@Z"
+// DTORS2: (%"struct.dtor_in_second_nvbase::C"* %this, i32 %should_call_delete)
+// Do an adjustment from B* to C*.
+// DTORS2: getelementptr i8* %{{.*}}, i32 -4
+// DTORS2: bitcast i8* %{{.*}} to %"struct.dtor_in_second_nvbase::C"*
+// DTORS2: call x86_thiscallcc void @"\01??_GC@dtor_in_second_nvbase@@UAEPAXI@Z"
+// DTORS2: ret void
+
+}
+
+namespace test2 {
+// Just like dtor_in_second_nvbase, except put that in a vbase of a diamond.
+
+// C's dtor is in the non-primary base.
+struct A { virtual void f(); };
+struct B { virtual ~B(); };
+struct C : A, B { virtual ~C(); int c; };
+
+// Diamond hierarchy, with C as the shared vbase.
+struct D : virtual C { int d; };
+struct E : virtual C { int e; };
+struct F : D, E { ~F(); int f; };
+
+F::~F() {
+// CHECK-LABEL: define x86_thiscallcc void @"\01??1F@test2@@UAE@XZ"(%"struct.test2::F"*)
+// Do an adjustment from C vbase subobject to F as though F was the
+// complete type.
+// CHECK: getelementptr inbounds i8* %{{.*}}, i32 -20
+// CHECK: bitcast i8* %{{.*}} to %"struct.test2::F"*
+// CHECK: store %"struct.test2::F"*
+}
+
+void foo() {
+ F f;
+}
+// DTORS3-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_DF@test2@@UAE@XZ"
+// Do an adjustment from C* to F*.
+// DTORS3: getelementptr i8* %{{.*}}, i32 20
+// DTORS3: bitcast i8* %{{.*}} to %"struct.test2::F"*
+// DTORS3: call x86_thiscallcc void @"\01??1F@test2@@UAE@XZ"
+// DTORS3: ret void
+
+}
namespace constructors {
@@ -299,3 +374,69 @@ void call_nv_deleting_dtor(D *d) {
}
}
+
+namespace test1 {
+struct A { };
+struct B : virtual A {
+ B(int *a);
+ B(const char *a, ...);
+ __cdecl B(short *a);
+};
+B::B(int *a) {}
+B::B(const char *a, ...) {}
+B::B(short *a) {}
+// CHECK: define x86_thiscallcc %"struct.test1::B"* @"\01??0B@test1@@QAE@PAH@Z"
+// CHECK: (%"struct.test1::B"* returned %this, i32* %a, i32 %is_most_derived)
+// CHECK: define %"struct.test1::B"* @"\01??0B@test1@@QAA@PBDZZ"
+// CHECK: (%"struct.test1::B"* returned %this, i32 %is_most_derived, i8* %a, ...)
+
+// FIXME: This should be x86_thiscallcc. MSVC ignores explicit CCs on structors.
+// CHECK: define %"struct.test1::B"* @"\01??0B@test1@@QAA@PAF@Z"
+// CHECK: (%"struct.test1::B"* returned %this, i16* %a, i32 %is_most_derived)
+
+void construct_b() {
+ int a;
+ B b1(&a);
+ B b2("%d %d", 1, 2);
+}
+// CHECK-LABEL: define void @"\01?construct_b@test1@@YAXXZ"()
+// CHECK: call x86_thiscallcc %"struct.test1::B"* @"\01??0B@test1@@QAE@PAH@Z"
+// CHECK: (%"struct.test1::B"* {{.*}}, i32* {{.*}}, i32 1)
+// CHECK: call %"struct.test1::B"* (%"struct.test1::B"*, i32, i8*, ...)* @"\01??0B@test1@@QAA@PBDZZ"
+// CHECK: (%"struct.test1::B"* {{.*}}, i32 1, i8* {{.*}}, i32 1, i32 2)
+}
+
+namespace implicit_copy_vtable {
+// This was a crash that only reproduced in ABIs without key functions.
+struct ImplicitCopy {
+ // implicit copy ctor
+ virtual ~ImplicitCopy();
+};
+void CreateCopy(ImplicitCopy *a) {
+ new ImplicitCopy(*a);
+}
+// CHECK: store {{.*}} @"\01??_7ImplicitCopy@implicit_copy_vtable@@6B@"
+
+struct MoveOnly {
+ MoveOnly(MoveOnly &&o) = default;
+ virtual ~MoveOnly();
+};
+MoveOnly &&f();
+void g() { new MoveOnly(f()); }
+// CHECK: store {{.*}} @"\01??_7MoveOnly@implicit_copy_vtable@@6B@"
+}
+
+// Dtor thunks for classes in anonymous namespaces should be internal, not
+// linkonce_odr.
+namespace {
+struct A {
+ virtual ~A() { }
+};
+}
+void *getA() {
+ return (void*)new A();
+}
+// CHECK: define internal x86_thiscallcc void @"\01??_GA@?A@@UAEPAXI@Z"
+// CHECK: (%"struct.(anonymous namespace)::A"* %this, i32 %should_call_delete)
+// CHECK: define internal x86_thiscallcc void @"\01??1A@?A@@UAE@XZ"
+// CHECK: (%"struct.(anonymous namespace)::A"* %this)
diff --git a/test/CodeGenCXX/microsoft-abi-thunks.cpp b/test/CodeGenCXX/microsoft-abi-thunks.cpp
index f1bc385fdff2..c755b300067d 100644
--- a/test/CodeGenCXX/microsoft-abi-thunks.cpp
+++ b/test/CodeGenCXX/microsoft-abi-thunks.cpp
@@ -1,8 +1,8 @@
-// RUN: %clang_cc1 -fno-rtti -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 >%t 2>&1
+// RUN: %clang_cc1 -fno-rtti -emit-llvm %s -o - -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
+// RUN: %clang_cc1 -fno-rtti -emit-llvm %s -o - -triple=x86_64-pc-win32 2>&1 | FileCheck --check-prefix=MANGLING-X64 %s
void foo(void *);
@@ -61,13 +61,13 @@ struct C : A, B {
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-LABEL: define linkonce_odr 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-LABEL: define linkonce_odr 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
@@ -91,7 +91,7 @@ struct E : D {
E::E() {} // Emits vftable and forces thunk generation.
-// CODEGEN-LABEL: define weak x86_thiscallcc %struct.C* @"\01?goo@E@@QAEPAUB@@XZ"
+// CODEGEN-LABEL: define weak_odr 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
@@ -124,7 +124,7 @@ struct I : D {
I::I() {} // Emits vftable and forces thunk generation.
-// CODEGEN-LABEL: define weak x86_thiscallcc %struct.{{[BF]}}* @"\01?goo@I@@QAEPAUB@@XZ"
+// CODEGEN-LABEL: define weak_odr 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
@@ -152,3 +152,14 @@ struct C : A, B {
};
C c;
}
+
+namespace {
+struct E : D {
+ E();
+ virtual C* goo();
+};
+E::E() {}
+E e;
+// Class with internal linkage has internal linkage thunks.
+// CODEGEN: define internal x86_thiscallcc %struct.C* @"\01?goo@E@?A@@QAEPAUB@@XZ"
+}
diff --git a/test/CodeGenCXX/microsoft-abi-try-throw.cpp b/test/CodeGenCXX/microsoft-abi-try-throw.cpp
new file mode 100644
index 000000000000..95c2cbd817b3
--- /dev/null
+++ b/test/CodeGenCXX/microsoft-abi-try-throw.cpp
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -emit-llvm-only %s -triple=i386-pc-win32 -mconstructor-aliases -fcxx-exceptions -fexceptions -fno-rtti -verify -DTRY
+// RUN: %clang_cc1 -emit-llvm-only %s -triple=i386-pc-win32 -mconstructor-aliases -fcxx-exceptions -fexceptions -fno-rtti -verify -DTHROW
+
+void external();
+
+inline void not_emitted() {
+ throw int(13); // no error
+}
+
+int main() {
+ int rv = 0;
+#ifdef TRY
+ try { // expected-error {{cannot compile this try statement yet}}
+ external();
+ } catch (int) {
+ rv = 1;
+ }
+#endif
+#ifdef THROW
+ throw int(42); // expected-error {{cannot compile this throw expression yet}}
+#endif
+ return rv;
+}
diff --git a/test/CodeGenCXX/microsoft-abi-typeid.cpp b/test/CodeGenCXX/microsoft-abi-typeid.cpp
new file mode 100644
index 000000000000..4ee004d51d21
--- /dev/null
+++ b/test/CodeGenCXX/microsoft-abi-typeid.cpp
@@ -0,0 +1,52 @@
+// RUN: %clang_cc1 -emit-llvm -O1 -o - -triple=i386-pc-win32 %s | FileCheck %s
+
+struct type_info;
+namespace std { using ::type_info; }
+
+struct V { virtual void f(); };
+struct A : virtual V { A(); };
+
+extern A a;
+extern V v;
+extern int b;
+A* fn();
+
+const std::type_info* test0_typeid() { return &typeid(int); }
+// CHECK-LABEL: define %struct.type_info* @"\01?test0_typeid@@YAPBUtype_info@@XZ"()
+// CHECK: ret %struct.type_info* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to %struct.type_info*)
+
+const std::type_info* test1_typeid() { return &typeid(A); }
+// CHECK-LABEL: define %struct.type_info* @"\01?test1_typeid@@YAPBUtype_info@@XZ"()
+// CHECK: ret %struct.type_info* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUA@@@8" to %struct.type_info*)
+
+const std::type_info* test2_typeid() { return &typeid(&a); }
+// CHECK-LABEL: define %struct.type_info* @"\01?test2_typeid@@YAPBUtype_info@@XZ"()
+// CHECK: ret %struct.type_info* bitcast (%rtti.TypeDescriptor7* @"\01??_R0PAUA@@@8" to %struct.type_info*)
+
+const std::type_info* test3_typeid() { return &typeid(*fn()); }
+// CHECK-LABEL: define %struct.type_info* @"\01?test3_typeid@@YAPBUtype_info@@XZ"()
+// CHECK: [[CALL:%.*]] = tail call %struct.A* @"\01?fn@@YAPAUA@@XZ"()
+// CHECK-NEXT: [[CMP:%.*]] = icmp eq %struct.A* [[CALL]], null
+// CHECK-NEXT: br i1 [[CMP]]
+// CHECK: tail call i8* @__RTtypeid(i8* null)
+// CHECK-NEXT: unreachable
+// CHECK: [[THIS:%.*]] = bitcast %struct.A* [[CALL]] to i8*
+// CHECK-NEXT: [[VBTBLP:%.*]] = bitcast %struct.A* [[CALL]] to i8**
+// CHECK-NEXT: [[VBTBL:%.*]] = load i8** [[VBTBLP]], align 4
+// CHECK-NEXT: [[VBSLOT:%.*]] = getelementptr inbounds i8* [[VBTBL]], i32 4
+// CHECK-NEXT: [[VBITCST:%.*]] = bitcast i8* [[VBSLOT]] to i32*
+// CHECK-NEXT: [[VBASE_OFFS:%.*]] = load i32* [[VBITCST]], align 4
+// CHECK-NEXT: [[ADJ:%.*]] = getelementptr inbounds i8* [[THIS]], i32 [[VBASE_OFFS]]
+// CHECK-NEXT: [[RT:%.*]] = tail call i8* @__RTtypeid(i8* [[ADJ]])
+// CHECK-NEXT: [[RET:%.*]] = bitcast i8* [[RT]] to %struct.type_info*
+// CHECK-NEXT: ret %struct.type_info* [[RET]]
+
+const std::type_info* test4_typeid() { return &typeid(b); }
+// CHECK: define %struct.type_info* @"\01?test4_typeid@@YAPBUtype_info@@XZ"()
+// CHECK: ret %struct.type_info* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to %struct.type_info*)
+
+const std::type_info* test5_typeid() { return &typeid(v); }
+// CHECK: define %struct.type_info* @"\01?test5_typeid@@YAPBUtype_info@@XZ"()
+// CHECK: [[RT:%.*]] = tail call i8* @__RTtypeid(i8* bitcast (%struct.V* @"\01?v@@3UV@@A" to i8*))
+// CHECK-NEXT: [[RET:%.*]] = bitcast i8* [[RT]] to %struct.type_info*
+// CHECK-NEXT: ret %struct.type_info* [[RET]]
diff --git a/test/CodeGenCXX/microsoft-abi-vbtables.cpp b/test/CodeGenCXX/microsoft-abi-vbtables.cpp
index 6de556b1d814..8b86d6bd3c8e 100644
--- a/test/CodeGenCXX/microsoft-abi-vbtables.cpp
+++ b/test/CodeGenCXX/microsoft-abi-vbtables.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -fno-rtti -cxx-abi microsoft -triple=i386-pc-win32 -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -fno-rtti -triple=i386-pc-win32 -emit-llvm -o - | FileCheck %s
// See microsoft-abi-structors.cpp for constructor codegen tests.
@@ -477,3 +477,54 @@ F f;
// 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]
}
+
+namespace Test27 {
+// PR17748
+struct A {};
+struct B : virtual A {};
+struct C : virtual B {};
+struct D : C, B {};
+struct E : D {};
+struct F : C, E {};
+struct G : F, D, C, B {};
+G x;
+
+// CHECK-DAG: @"\01??_8G@Test27@@7BB@1@@" =
+// CHECK-DAG: @"\01??_8G@Test27@@7BB@1@F@1@@" =
+// CHECK-DAG: @"\01??_8G@Test27@@7BC@1@@" =
+// CHECK-DAG: @"\01??_8G@Test27@@7BC@1@D@1@@" =
+// CHECK-DAG: @"\01??_8G@Test27@@7BC@1@E@1@@" =
+// CHECK-DAG: @"\01??_8G@Test27@@7BC@1@F@1@@" =
+// CHECK-DAG: @"\01??_8G@Test27@@7BD@1@@" =
+// CHECK-DAG: @"\01??_8G@Test27@@7BF@1@@" =
+}
+
+namespace Test28 {
+// PR17748
+struct A {};
+struct B : virtual A {};
+struct C : virtual B {};
+struct D : C, B {};
+struct E : C, D {};
+struct F : virtual E, virtual D, virtual C {};
+F x;
+
+// CHECK-DAG: @"\01??_8F@Test28@@7B01@@" =
+// CHECK-DAG: @"\01??_8F@Test28@@7BB@1@@" =
+// CHECK-DAG: @"\01??_8F@Test28@@7BC@1@@" =
+// CHECK-DAG: @"\01??_8F@Test28@@7BC@1@D@1@@" =
+// CHECK-DAG: @"\01??_8F@Test28@@7BC@1@D@1@E@1@@" =
+// CHECK-DAG: @"\01??_8F@Test28@@7BC@1@E@1@@" =
+// CHECK-DAG: @"\01??_8F@Test28@@7BD@1@@" =
+// CHECK-DAG: @"\01??_8F@Test28@@7BE@1@@" =
+}
+
+namespace Test29 {
+struct A {};
+struct B : virtual A {};
+struct C : virtual B {};
+struct D : C {};
+D d;
+
+// CHECK-DAG: @"\01??_8D@Test29@@7BB@1@@" = linkonce_odr unnamed_addr constant [2 x i32] zeroinitializer
+}
diff --git a/test/CodeGenCXX/microsoft-abi-vftables.cpp b/test/CodeGenCXX/microsoft-abi-vftables.cpp
new file mode 100644
index 000000000000..825aba010f12
--- /dev/null
+++ b/test/CodeGenCXX/microsoft-abi-vftables.cpp
@@ -0,0 +1,42 @@
+// RUN: %clang_cc1 %s -fno-rtti -triple=i386-pc-win32 -emit-llvm -o - -O1 -disable-llvm-optzns | FileCheck %s -check-prefix=NO-RTTI
+// RUN: %clang_cc1 %s -triple=i386-pc-win32 -emit-llvm -o - -O1 -disable-llvm-optzns | FileCheck %s -check-prefix=RTTI
+
+// RTTI-DAG: $"\01??_7S@@6B@" = comdat largest
+// RTTI-DAG: $"\01??_7V@@6B@" = comdat largest
+// RTTI-DAG: $"\01??_7W@?A@@6B@" = comdat largest
+
+struct S {
+ virtual ~S();
+} s;
+
+// RTTI-DAG: [[VTABLE_S:@.*]] = private unnamed_addr constant [2 x i8*] [i8* bitcast ({{.*}} @"\01??_R4S@@6B@" to i8*), i8* bitcast ({{.*}} @"\01??_GS@@UAEPAXI@Z" to i8*)], comdat $"\01??_7S@@6B@"
+// RTTI-DAG: @"\01??_7S@@6B@" = unnamed_addr alias getelementptr inbounds ([2 x i8*]* [[VTABLE_S]], i32 0, i32 1)
+
+// NO-RTTI-DAG: @"\01??_7S@@6B@" = linkonce_odr unnamed_addr constant [1 x i8*] [i8* bitcast ({{.*}} @"\01??_GS@@UAEPAXI@Z" to i8*)]
+
+struct __declspec(dllimport) U {
+ virtual ~U();
+} u;
+
+// RTTI-DAG: @"\01??_7U@@6B@" = available_externally dllimport unnamed_addr constant [1 x i8*] [i8* bitcast ({{.*}} @"\01??_GU@@UAEPAXI@Z" to i8*)]
+
+// NO-RTTI-DAG: @"\01??_7U@@6B@" = available_externally dllimport unnamed_addr constant [1 x i8*] [i8* bitcast ({{.*}} @"\01??_GU@@UAEPAXI@Z" to i8*)]
+
+struct __declspec(dllexport) V {
+ virtual ~V();
+} v;
+
+// RTTI-DAG: [[VTABLE_V:@.*]] = private unnamed_addr constant [2 x i8*] [i8* bitcast ({{.*}} @"\01??_R4V@@6B@" to i8*), i8* bitcast ({{.*}} @"\01??_GV@@UAEPAXI@Z" to i8*)], comdat $"\01??_7V@@6B@"
+// RTTI-DAG: @"\01??_7V@@6B@" = dllexport unnamed_addr alias getelementptr inbounds ([2 x i8*]* [[VTABLE_V]], i32 0, i32 1)
+
+// NO-RTTI-DAG: @"\01??_7V@@6B@" = weak_odr dllexport unnamed_addr constant [1 x i8*] [i8* bitcast ({{.*}} @"\01??_GV@@UAEPAXI@Z" to i8*)]
+
+namespace {
+struct W {
+ virtual ~W();
+} w;
+}
+// RTTI-DAG: [[VTABLE_W:@.*]] = private unnamed_addr constant [2 x i8*] [i8* bitcast ({{.*}} @"\01??_R4W@?A@@6B@" to i8*), i8* bitcast ({{.*}} @"\01??_GW@?A@@UAEPAXI@Z" to i8*)], comdat $"\01??_7W@?A@@6B@"
+// RTTI-DAG: @"\01??_7W@?A@@6B@" = unnamed_addr alias internal getelementptr inbounds ([2 x i8*]* @1, i32 0, i32 1)
+
+// NO-RTTI-DAG: @"\01??_7W@?A@@6B@" = internal unnamed_addr constant [1 x i8*] [i8* bitcast ({{.*}} @"\01??_GW@?A@@UAEPAXI@Z" to i8*)]
diff --git a/test/CodeGenCXX/microsoft-abi-virtual-inheritance-vtordisps.cpp b/test/CodeGenCXX/microsoft-abi-virtual-inheritance-vtordisps.cpp
index 8e23ade658c4..a6fcdea749ab 100644
--- a/test/CodeGenCXX/microsoft-abi-virtual-inheritance-vtordisps.cpp
+++ b/test/CodeGenCXX/microsoft-abi-virtual-inheritance-vtordisps.cpp
@@ -1,7 +1,7 @@
-// RUN: %clang_cc1 %s -fno-rtti -cxx-abi microsoft -triple=i386-pc-win32 -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -fno-rtti -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
+// RUN: %clang_cc1 %s -fno-rtti -triple=x86_64-pc-win32 -emit-llvm -o %t
struct A {
virtual void f();
@@ -23,7 +23,7 @@ struct D : virtual C {
D::D() {} // Forces vftable emission.
-// CHECK-LABEL: define weak x86_thiscallcc void @"\01?f@D@@$4PPPPPPPM@A@AEXXZ"
+// CHECK-LABEL: define linkonce_odr 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
@@ -34,7 +34,7 @@ D::D() {} // Forces vftable emission.
// 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-LABEL: define linkonce_odr 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
@@ -63,7 +63,7 @@ struct G : virtual F, virtual E {
G::G() {} // Forces vftable emission.
-// CHECK-LABEL: define weak x86_thiscallcc void @"\01?f@E@@$R4BA@M@PPPPPPPM@7AEXXZ"(i8*)
+// CHECK-LABEL: define linkonce_odr 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
diff --git a/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp b/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp
index 7c223ca0a772..2f0fffee696f 100644
--- a/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp
+++ b/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp
@@ -1,9 +1,9 @@
-// RUN: %clang_cc1 %s -fno-rtti -cxx-abi microsoft -triple=i386-pc-win32 -emit-llvm -o %t
+// RUN: %clang_cc1 %s -fno-rtti -triple=i386-pc-win32 -emit-llvm -o %t
// RUN: FileCheck %s < %t
// RUN: FileCheck --check-prefix=CHECK2 %s < %t
// For now, just make sure x86_64 doesn't crash.
-// RUN: %clang_cc1 %s -fno-rtti -cxx-abi microsoft -triple=x86_64-pc-win32 -emit-llvm -o %t
+// RUN: %clang_cc1 %s -fno-rtti -triple=x86_64-pc-win32 -emit-llvm -o %t
struct VBase {
virtual ~VBase();
@@ -312,3 +312,151 @@ D::~D() {
}
}
+
+namespace test2 {
+struct A { A(); };
+struct B : virtual A { B() {} };
+struct C : B, A { C() {} };
+
+// PR18435: Order mattered here. We were generating code for the delegating
+// call to B() from C().
+void callC() { C x; }
+
+// CHECK-LABEL: define linkonce_odr x86_thiscallcc %"struct.test2::C"* @"\01??0C@test2@@QAE@XZ"
+// CHECK: (%"struct.test2::C"* returned %this, i32 %is_most_derived)
+// CHECK: br i1
+// Virtual bases
+// CHECK: call x86_thiscallcc %"struct.test2::A"* @"\01??0A@test2@@QAE@XZ"(%"struct.test2::A"* %{{.*}})
+// CHECK: br label
+// Non-virtual bases
+// CHECK: call x86_thiscallcc %"struct.test2::B"* @"\01??0B@test2@@QAE@XZ"(%"struct.test2::B"* %{{.*}}, i32 0)
+// CHECK: call x86_thiscallcc %"struct.test2::A"* @"\01??0A@test2@@QAE@XZ"(%"struct.test2::A"* %{{.*}})
+// CHECK: ret
+
+// CHECK2-LABEL: define linkonce_odr x86_thiscallcc %"struct.test2::B"* @"\01??0B@test2@@QAE@XZ"
+// CHECK2: (%"struct.test2::B"* returned %this, i32 %is_most_derived)
+// CHECK2: call x86_thiscallcc %"struct.test2::A"* @"\01??0A@test2@@QAE@XZ"(%"struct.test2::A"* %{{.*}})
+// CHECK2: ret
+
+}
+
+namespace test3 {
+// PR19104: A non-virtual call of a virtual method doesn't use vftable thunks,
+// so requires only static adjustment which is different to the one used
+// for virtual calls.
+struct A {
+ virtual void foo();
+};
+
+struct B : virtual A {
+ virtual void bar();
+};
+
+struct C : virtual A {
+ virtual void foo();
+};
+
+struct D : B, C {
+ virtual void bar();
+ int field; // Laid out between C and A subobjects in D.
+};
+
+void D::bar() {
+ // CHECK-LABEL: define x86_thiscallcc void @"\01?bar@D@test3@@UAEXXZ"(%"struct.test3::D"* %this)
+
+ C::foo();
+ // Shouldn't need any vbtable lookups. All we have to do is adjust to C*,
+ // then compensate for the adjustment performed in the C::foo() prologue.
+ // CHECK-NOT: load i8**
+ // CHECK: %[[OBJ_i8:.*]] = bitcast %"struct.test3::D"* %{{.*}} to i8*
+ // CHECK: %[[C_i8:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 8
+ // CHECK: %[[C:.*]] = bitcast i8* %[[C_i8]] to %"struct.test3::C"*
+ // CHECK: %[[C_i8:.*]] = bitcast %"struct.test3::C"* %[[C]] to i8*
+ // CHECK: %[[ARG:.*]] = getelementptr i8* %[[C_i8]], i32 4
+ // CHECK: call x86_thiscallcc void @"\01?foo@C@test3@@UAEXXZ"(i8* %[[ARG]])
+ // CHECK: ret
+}
+}
+
+namespace test4{
+// PR19172: We used to merge method vftable locations wrong.
+
+struct A {
+ virtual ~A() {}
+};
+
+struct B {
+ virtual ~B() {}
+};
+
+struct C : virtual A, B {
+ virtual ~C();
+};
+
+void foo(void*);
+
+C::~C() {
+ // CHECK-LABEL: define x86_thiscallcc void @"\01??1C@test4@@UAE@XZ"(%"struct.test4::C"* %this)
+
+ // In this case "this" points to the most derived class, so no GEPs needed.
+ // CHECK-NOT: getelementptr
+ // CHECK-NOT: bitcast
+ // CHECK: %[[VFPTR_i8:.*]] = bitcast %"struct.test4::C"* %{{.*}} to [1 x i8*]**
+ // CHECK: store [1 x i8*]* @"\01??_7C@test4@@6BB@1@@", [1 x i8*]** %[[VFPTR_i8]]
+
+ foo(this);
+ // CHECK: ret
+}
+
+void destroy(C *obj) {
+ // CHECK-LABEL: define void @"\01?destroy@test4@@YAXPAUC@1@@Z"(%"struct.test4::C"* %obj)
+
+ delete obj;
+ // CHECK: %[[VPTR:.*]] = bitcast %"struct.test4::C"* %[[OBJ:.*]] to void (%"struct.test4::C"*, i32)***
+ // CHECK: %[[VFTABLE:.*]] = load void (%"struct.test4::C"*, i32)*** %[[VPTR]]
+ // CHECK: %[[VFTENTRY:.*]] = getelementptr inbounds void (%"struct.test4::C"*, i32)** %[[VFTABLE]], i64 0
+ // CHECK: %[[VFUN:.*]] = load void (%"struct.test4::C"*, i32)** %[[VFTENTRY]]
+ // CHECK: call x86_thiscallcc void %[[VFUN]](%"struct.test4::C"* %[[OBJ]], i32 1)
+ // CHECK: ret
+}
+
+struct D {
+ virtual void d();
+};
+
+// The first non-virtual base doesn't have a vdtor,
+// but "this adjustment" is not needed.
+struct E : D, B, virtual A {
+ virtual ~E();
+};
+
+E::~E() {
+ // CHECK-LABEL: define x86_thiscallcc void @"\01??1E@test4@@UAE@XZ"(%"struct.test4::E"* %this)
+
+ // In this case "this" points to the most derived class, so no GEPs needed.
+ // CHECK-NOT: getelementptr
+ // CHECK-NOT: bitcast
+ // CHECK: %[[VFPTR_i8:.*]] = bitcast %"struct.test4::E"* %{{.*}} to [1 x i8*]**
+ // CHECK: store [1 x i8*]* @"\01??_7E@test4@@6BD@1@@", [1 x i8*]** %[[VFPTR_i8]]
+ foo(this);
+}
+
+void destroy(E *obj) {
+ // CHECK-LABEL: define void @"\01?destroy@test4@@YAXPAUE@1@@Z"(%"struct.test4::E"* %obj)
+
+ // CHECK-NOT: getelementptr
+ // CHECK: %[[OBJ_i8:.*]] = bitcast %"struct.test4::E"* %[[OBJ:.*]] to i8*
+ // CHECK: %[[B_i8:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 4
+ // CHECK: %[[VPTR:.*]] = bitcast i8* %[[B_i8]] to void (%"struct.test4::E"*, i32)***
+ // CHECK: %[[VFTABLE:.*]] = load void (%"struct.test4::E"*, i32)*** %[[VPTR]]
+ // CHECK: %[[VFTENTRY:.*]] = getelementptr inbounds void (%"struct.test4::E"*, i32)** %[[VFTABLE]], i64 0
+ // CHECK: %[[VFUN:.*]] = load void (%"struct.test4::E"*, i32)** %[[VFTENTRY]]
+ // CHECK: %[[OBJ_i8:.*]] = bitcast %"struct.test4::E"* %[[OBJ]] to i8*
+ // CHECK: %[[B_i8:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 4
+ // FIXME: in fact, the call should take i8* and the bitcast is redundant.
+ // CHECK: %[[B_as_E:.*]] = bitcast i8* %[[B_i8]] to %"struct.test4::E"*
+ // CHECK: call x86_thiscallcc void %[[VFUN]](%"struct.test4::E"* %[[B_as_E]], i32 1)
+ delete obj;
+}
+
+}
diff --git a/test/CodeGenCXX/microsoft-abi-virtual-member-pointers.cpp b/test/CodeGenCXX/microsoft-abi-virtual-member-pointers.cpp
index 51a04c89dcb7..974953c01444 100644
--- a/test/CodeGenCXX/microsoft-abi-virtual-member-pointers.cpp
+++ b/test/CodeGenCXX/microsoft-abi-virtual-member-pointers.cpp
@@ -1,14 +1,23 @@
-// 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
+// RUN: %clang_cc1 -fno-rtti -emit-llvm -triple=i386-pc-win32 %s -o - | FileCheck %s --check-prefix=CHECK32
+// RUN: %clang_cc1 -fno-rtti -emit-llvm -triple=x86_64-pc-win32 %s -o - | FileCheck %s --check-prefix=CHECK64
struct S {
int x, y, z;
};
+// U is not trivially copyable, and requires inalloca to pass by value.
+struct U {
+ int u;
+ U();
+ ~U();
+ U(const U &);
+};
+
struct C {
virtual void foo();
virtual int bar(int, double);
virtual S baz(int);
+ virtual S qux(U);
};
namespace {
@@ -31,18 +40,22 @@ void f() {
void (D::*ptr4)();
ptr4 = &D::foo;
+ S (C::*ptr5)(U);
+ ptr5 = &C::qux;
+
+
// 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: store i8* bitcast (void (%struct.C*, %struct.S*, 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: store i8* bitcast (void (%struct.C*, %struct.S*, 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: }
}
@@ -51,14 +64,14 @@ void f() {
// 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: musttail 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: musttail call void [[CALLEE]](%struct.C* %{{.*}})
// CHECK64: ret void
// CHECK64: }
@@ -66,43 +79,58 @@ void f() {
// 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: [[CALL:%.*]] = musttail 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: [[CALL:%.*]] = musttail 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-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_9C@@$B7AE"(%struct.C* %this, %struct.S* noalias sret %agg.result, i32) unnamed_addr
+// CHECK32: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*, %struct.S*, i32)** %{{.*}}, i64 2
+// CHECK32: [[CALLEE:%.*]] = load void (%struct.C*, %struct.S*, i32)** [[VPTR]]
+// CHECK32: musttail call x86_thiscallcc void [[CALLEE]](%struct.C* %{{.*}}, %struct.S* sret %agg.result, 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-LABEL: define linkonce_odr void @"\01??_9C@@$BBA@AA"(%struct.C* %this, %struct.S* noalias sret %agg.result, i32) unnamed_addr
+// CHECK64: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*, %struct.S*, i32)** %{{.*}}, i64 2
+// CHECK64: [[CALLEE:%.*]] = load void (%struct.C*, %struct.S*, i32)** [[VPTR]]
+// CHECK64: musttail call void [[CALLEE]](%struct.C* %{{.*}}, %struct.S* sret %agg.result, 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-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: musttail 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-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: musttail call void [[CALLEE]](%"struct.(anonymous namespace)::D"* %{{.*}})
+// CHECK64: ret void
+// CHECK64: }
+
+// Thunk for calling the fourth virtual function in C, taking a struct parameter and returning a struct.
+// CHECK32-LABEL: define linkonce_odr x86_thiscallcc %struct.S* @"\01??_9C@@$BM@AE"(%struct.C* %this, <{ %struct.S*, %struct.U }>* inalloca) unnamed_addr
+// CHECK32: [[VPTR:%.*]] = getelementptr inbounds %struct.S* (%struct.C*, <{ %struct.S*, %struct.U }>*)** %{{.*}}, i64 3
+// CHECK32: [[CALLEE:%.*]] = load %struct.S* (%struct.C*, <{ %struct.S*, %struct.U }>*)** [[VPTR]]
+// CHECK32: [[CALL:%.*]] = musttail call x86_thiscallcc %struct.S* [[CALLEE]](%struct.C* %this, <{ %struct.S*, %struct.U }>* inalloca %{{.*}})
+// CHECK32: ret %struct.S* [[CALL]]
+// CHECK32: }
+//
+// CHECK64-LABEL: define linkonce_odr void @"\01??_9C@@$BBI@AA"(%struct.C* %this, %struct.S* noalias sret %agg.result, %struct.U*) unnamed_addr
+// CHECK64: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*, %struct.S*, %struct.U*)** %{{.*}}, i64 3
+// CHECK64: [[CALLEE:%.*]] = load void (%struct.C*, %struct.S*, %struct.U*)** [[VPTR]]
+// CHECK64: musttail call void [[CALLEE]](%struct.C* %this, %struct.S* sret %agg.result, %struct.U* %{{.*}})
// CHECK64: ret void
// CHECK64: }
diff --git a/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-no-thunks.cpp b/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-no-thunks.cpp
new file mode 100644
index 000000000000..86314cff324e
--- /dev/null
+++ b/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-no-thunks.cpp
@@ -0,0 +1,302 @@
+// RUN: %clang_cc1 %s -fno-rtti -triple=i386-pc-win32 -emit-llvm -o %t.ll -fdump-vtable-layouts >%t
+// RUN: FileCheck %s < %t
+// RUN: FileCheck --check-prefix=MANGLING %s < %t.ll
+
+namespace test1 {
+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 X : A, B {
+ // CHECK-LABEL: VFTable for 'test1::A' in 'test1::X' (1 entry)
+ // CHECK-NEXT: 0 | void test1::X::f()
+
+ // CHECK-LABEL: VFTable for 'test1::B' in 'test1::X' (2 entries)
+ // CHECK-NEXT: 0 | void test1::B::g()
+ // CHECK-NEXT: 1 | void test1::B::h()
+
+ // CHECK-LABEL: VFTable indices for 'test1::X' (1 entry)
+ // CHECK-NEXT: 0 | void test1::X::f()
+
+ // MANGLING-DAG: @"\01??_7X@test1@@6BA@1@@"
+ // MANGLING-DAG: @"\01??_7X@test1@@6BB@1@@"
+
+ // Overrides only the left child's method (A::f), needs no thunks.
+ virtual void f();
+} x;
+
+void build_vftable(X *obj) { obj->f(); }
+}
+
+namespace test2 {
+struct A {
+ virtual void f();
+};
+
+struct B {
+ virtual void g();
+ virtual void h();
+};
+
+struct X : A, B {
+ // CHECK-LABEL: VFTable for 'test2::A' in 'test2::X' (1 entry)
+ // CHECK-NEXT: 0 | void test2::A::f()
+
+ // CHECK-LABEL: VFTable for 'test2::B' in 'test2::X' (2 entries)
+ // CHECK-NEXT: 0 | void test2::X::g()
+ // CHECK-NEXT: 1 | void test2::B::h()
+
+ // CHECK-LABEL: VFTable indices for 'test2::X' (1 entry).
+ // CHECK-NEXT: via vfptr at offset 4
+ // CHECK-NEXT: 0 | void test2::X::g()
+
+ // Overrides only the right child's method (B::g), needs this adjustment but
+ // not thunks.
+ virtual void g();
+};
+
+void build_vftable(X *obj) { obj->g(); }
+}
+
+namespace test3 {
+struct A {
+ virtual void f();
+};
+
+struct B {
+ virtual void g();
+ virtual void h();
+};
+
+struct X : A, B {
+ // CHECK-LABEL: VFTable for 'test3::A' in 'test3::X' (2 entries)
+ // CHECK-NEXT: 0 | void test3::A::f()
+ // CHECK-NEXT: 1 | void test3::X::i()
+
+ // CHECK-LABEL: VFTable for 'test3::B' in 'test3::X' (2 entries)
+ // CHECK-NEXT: 0 | void test3::B::g()
+ // CHECK-NEXT: 1 | void test3::B::h()
+
+ // CHECK-LABEL: VFTable indices for 'test3::X' (1 entry).
+ // CHECK-NEXT: 1 | void test3::X::i()
+
+ // Only adds a new method.
+ virtual void i();
+};
+
+void build_vftable(X *obj) { obj->i(); }
+}
+
+namespace test4 {
+struct A {
+ virtual void f();
+};
+
+struct Empty { }; // Doesn't have a vftable!
+
+// Only the right base has a vftable, so it's laid out before the left one!
+struct X : Empty, A {
+ // CHECK-LABEL: VFTable for 'test4::A' in 'test4::X' (1 entry)
+ // CHECK-NEXT: 0 | void test4::X::f()
+
+ // CHECK-LABEL: VFTable indices for 'test4::X' (1 entry).
+ // CHECK-NEXT: 0 | void test4::X::f()
+
+ // MANGLING-DAG: @"\01??_7X@test4@@6B@"
+
+ virtual void f();
+} x;
+
+void build_vftable(X *obj) { obj->f(); }
+}
+
+namespace test5 {
+struct A {
+ virtual void f();
+};
+
+struct B {
+ virtual void g();
+ virtual void h();
+};
+
+struct C : A, B {
+ virtual void f();
+};
+
+struct X : C {
+ // CHECK-LABEL: VFTable for 'test5::A' in 'test5::C' in 'test5::X' (1 entry).
+ // CHECK-NEXT: 0 | void test5::X::f()
+
+ // CHECK-LABEL: VFTable for 'test5::B' in 'test5::C' in 'test5::X' (2 entries).
+ // CHECK-NEXT: 0 | void test5::B::g()
+ // CHECK-NEXT: 1 | void test5::B::h()
+
+ // CHECK-LABEL: VFTable indices for 'test5::X' (1 entry).
+ // CHECK-NEXT: 0 | void test5::X::f()
+
+ // MANGLING-DAG: @"\01??_7X@test5@@6BA@1@@"
+ // MANGLING-DAG: @"\01??_7X@test5@@6BB@1@@"
+
+ // Overrides both C::f and A::f.
+ virtual void f();
+} x;
+
+void build_vftable(X *obj) { obj->f(); }
+}
+
+namespace test6 {
+struct A {
+ virtual void f();
+};
+
+struct B {
+ virtual void g();
+ virtual void h();
+};
+
+struct C : A, B {
+ virtual void g();
+};
+
+struct X : C {
+ // CHECK-LABEL: VFTable for 'test6::A' in 'test6::C' in 'test6::X' (1 entry).
+ // CHECK-NEXT: 0 | void test6::A::f()
+
+ // CHECK-LABEL: VFTable for 'test6::B' in 'test6::C' in 'test6::X' (2 entries).
+ // CHECK-NEXT: 0 | void test6::X::g()
+ // CHECK-NEXT: 1 | void test6::B::h()
+
+ // CHECK-LABEL: VFTable indices for 'test6::X' (1 entry).
+ // CHECK-NEXT: via vfptr at offset 4
+ // CHECK-NEXT: 0 | void test6::X::g()
+
+ // Overrides both C::g and B::g.
+ virtual void g();
+};
+
+void build_vftable(X *obj) { obj->g(); }
+}
+
+namespace test7 {
+struct A {
+ virtual void f();
+};
+
+struct B {
+ virtual void g();
+ virtual void h();
+};
+
+struct C : A, B {
+ // Only adds a new method.
+ virtual void i();
+};
+
+struct X : C {
+ // CHECK-LABEL: VFTable for 'test7::A' in 'test7::C' in 'test7::X' (2 entries).
+ // CHECK-NEXT: 0 | void test7::A::f()
+ // CHECK-NEXT: 1 | void test7::C::i()
+
+ // CHECK-LABEL: VFTable for 'test7::B' in 'test7::C' in 'test7::X' (2 entries).
+ // CHECK-NEXT: 0 | void test7::X::g()
+ // CHECK-NEXT: 1 | void test7::B::h()
+
+ // CHECK-LABEL: VFTable indices for 'test7::X' (1 entry).
+ // CHECK-NEXT: via vfptr at offset 4
+ // CHECK-NEXT: 0 | void test7::X::g()
+
+ // Overrides grandparent's B::g.
+ virtual void g();
+};
+
+void build_vftable(X *obj) { obj->g(); }
+}
+
+namespace test8 {
+struct A {
+ virtual void f();
+};
+
+struct B : A {
+ virtual void g();
+};
+
+// There are two 'A' subobjects in this class.
+struct X : A, B {
+ // CHECK-LABEL: VFTable for 'test8::A' in 'test8::X' (2 entries).
+ // CHECK-NEXT: 0 | void test8::A::f()
+ // CHECK-NEXT: 1 | void test8::X::h()
+
+ // CHECK-LABEL: VFTable for 'test8::A' in 'test8::B' in 'test8::X' (2 entries).
+ // CHECK-NEXT: 0 | void test8::A::f()
+ // CHECK-NEXT: 1 | void test8::B::g()
+
+ // CHECK-LABEL: VFTable indices for 'test8::X' (1 entry).
+ // CHECK-NEXT: 1 | void test8::X::h()
+
+ // MANGLING-DAG: @"\01??_7X@test8@@6BA@1@@"
+ // MANGLING-DAG: @"\01??_7X@test8@@6BB@1@@"
+
+ virtual void h();
+} x;
+
+void build_vftable(X *obj) { obj->h(); }
+}
+
+namespace test9 {
+struct A {
+ virtual void f();
+};
+
+struct B {
+ virtual void g();
+ virtual void h();
+};
+
+struct C : A, B {
+ // Overrides only the left child's method (A::f).
+ virtual void f();
+};
+
+struct D : A, B {
+ // Overrides only the right child's method (B::g).
+ virtual void g();
+};
+
+// 2-level structure with repeating subobject types, but no thunks needed.
+struct X : C, D {
+ // CHECK-LABEL: VFTable for 'test9::A' in 'test9::C' in 'test9::X' (2 entries)
+ // CHECK-NEXT: 0 | void test9::C::f()
+ // CHECK-NEXT: 1 | void test9::X::z()
+
+ // CHECK-LABEL: VFTable for 'test9::B' in 'test9::C' in 'test9::X' (2 entries)
+ // CHECK-NEXT: 0 | void test9::B::g()
+ // CHECK-NEXT: 1 | void test9::B::h()
+
+ // CHECK-LABEL: VFTable for 'test9::A' in 'test9::D' in 'test9::X' (1 entry)
+ // CHECK-NEXT: 0 | void test9::A::f()
+
+ // CHECK-LABEL: VFTable for 'test9::B' in 'test9::D' in 'test9::X' (2 entries)
+ // CHECK-NEXT: 0 | void test9::D::g()
+ // CHECK-NEXT: 1 | void test9::B::h()
+
+ // CHECK-LABEL: VFTable indices for 'test9::X' (1 entry).
+ // CHECK-NEXT: 1 | void test9::X::z()
+
+ // MANGLING-DAG: @"\01??_7X@test9@@6BA@1@C@1@@"
+ // MANGLING-DAG: @"\01??_7X@test9@@6BA@1@D@1@@"
+ // MANGLING-DAG: @"\01??_7X@test9@@6BB@1@C@1@@"
+ // MANGLING-DAG: @"\01??_7X@test9@@6BB@1@D@1@@"
+
+ virtual void z();
+} x;
+
+void build_vftable(test9::X *obj) { obj->z(); }
+}
diff --git a/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-pure-virtual.cpp b/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-pure-virtual.cpp
new file mode 100644
index 000000000000..76182a2e331e
--- /dev/null
+++ b/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-pure-virtual.cpp
@@ -0,0 +1,35 @@
+// RUN: %clang_cc1 %s -fno-rtti -triple=i386-pc-win32 -emit-llvm -o %t.ll -fdump-vtable-layouts >%t
+// RUN: FileCheck %s < %t
+// RUN: FileCheck --check-prefix=MANGLING %s < %t.ll
+
+struct A {
+ virtual void f();
+};
+
+struct B {
+ virtual void g() = 0;
+ virtual void h();
+};
+
+struct C : A, B {
+ // CHECK-LABEL: VFTable for 'A' in 'C' (1 entry)
+ // CHECK-NEXT: 0 | void A::f()
+
+ // CHECK-LABEL: VFTable for 'B' in 'C' (2 entries)
+ // CHECK-NEXT: 0 | void C::g()
+ // CHECK-NEXT: 1 | void B::h()
+
+ // CHECK-LABEL: VFTable indices for 'C' (1 entry).
+ // CHECK-NEXT: via vfptr at offset 4
+ // CHECK-NEXT: 0 | void C::g()
+
+ // MANGLING-DAG: @"\01??_7C@@6BA@@@"
+ // MANGLING-DAG: @"\01??_7C@@6BB@@@"
+
+ // Overrides only the right child's method (B::g),
+ // needs this adjustment but not thunks.
+ virtual void g();
+};
+
+C c;
+void build_vftable(C *obj) { obj->g(); }
diff --git a/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-return-adjustment.cpp b/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-return-adjustment.cpp
new file mode 100644
index 000000000000..2d0bf6362296
--- /dev/null
+++ b/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-return-adjustment.cpp
@@ -0,0 +1,297 @@
+// RUN: %clang_cc1 %s -fno-rtti -triple=i386-pc-win32 -emit-llvm -o %t.ll -fdump-vtable-layouts >%t
+// RUN: FileCheck %s < %t
+// RUN: FileCheck --check-prefix=MANGLING %s < %t.ll
+
+namespace test1 {
+struct A {
+ virtual void g();
+ // Add an extra virtual method so it's easier to check for the absence of thunks.
+ virtual void h();
+};
+
+struct B {
+ virtual void g();
+};
+
+// Overrides a method of two bases at the same time, thus needing thunks.
+struct C : A, B {
+ virtual void g();
+};
+
+struct D {
+ virtual B* foo();
+ virtual void z();
+};
+
+struct X : D {
+ // CHECK-LABEL: VFTable for 'test1::D' in 'test1::X' (3 entries).
+ // CHECK-NEXT: 0 | test1::C *test1::X::foo()
+ // CHECK-NEXT: [return adjustment (to type 'struct test1::B *'): 4 non-virtual]
+ // CHECK-NEXT: 1 | void test1::D::z()
+ // CHECK-NEXT: 2 | test1::C *test1::X::foo()
+
+ // CHECK-LABEL: Thunks for 'test1::C *test1::X::foo()' (1 entry).
+ // CHECK-NEXT: 0 | [return adjustment (to type 'struct test1::B *'): 4 non-virtual]
+
+ // CHECK-LABEL: VFTable indices for 'test1::X' (1 entry).
+ // CHECK-NEXT: 2 | test1::C *test1::X::foo()
+
+ // MANGLING-DAG: @"\01??_7X@test1@@6B@"
+
+ virtual C* foo();
+} x;
+
+void build_vftable(X *obj) { obj->foo(); }
+}
+
+namespace test2 {
+struct A {
+ virtual void g();
+ virtual void h();
+};
+
+struct B {
+ virtual void g();
+};
+
+struct C : A, B {
+ virtual void g();
+};
+
+struct D {
+ virtual B* foo();
+ virtual void z();
+};
+
+struct E : D {
+ virtual C* foo();
+};
+
+struct F : C { };
+
+struct X : E {
+ virtual F* foo();
+ // CHECK-LABEL: VFTable for 'test2::D' in 'test2::E' in 'test2::X' (4 entries).
+ // CHECK-NEXT: 0 | test2::F *test2::X::foo()
+ // CHECK-NEXT: [return adjustment (to type 'struct test2::B *'): 4 non-virtual]
+ // CHECK-NEXT: 1 | void test2::D::z()
+ // CHECK-NEXT: 2 | test2::F *test2::X::foo()
+ // CHECK-NEXT: [return adjustment (to type 'struct test2::C *'): 0 non-virtual]
+ // CHECK-NEXT: 3 | test2::F *test2::X::foo()
+
+ // CHECK-LABEL: Thunks for 'test2::F *test2::X::foo()' (2 entries).
+ // CHECK-NEXT: 0 | [return adjustment (to type 'struct test2::C *'): 0 non-virtual]
+ // CHECK-NEXT: 1 | [return adjustment (to type 'struct test2::B *'): 4 non-virtual]
+
+ // CHECK-LABEL: VFTable indices for 'test2::X' (1 entry).
+ // CHECK-NEXT: 3 | test2::F *test2::X::foo()
+};
+
+void build_vftable(X *obj) { obj->foo(); }
+}
+
+namespace test3 {
+struct A {
+ virtual void g();
+ virtual void h();
+};
+
+struct B {
+ virtual void g();
+};
+
+struct C : A, B {
+ virtual void g();
+};
+
+struct D {
+ virtual B* foo();
+ virtual void z();
+};
+
+struct E : D {
+ virtual C* foo();
+};
+
+struct F : A, C { };
+
+struct X : E {
+ // CHECK-LABEL: VFTable for 'test3::D' in 'test3::E' in 'test3::X' (4 entries).
+ // CHECK-NEXT: 0 | test3::F *test3::X::foo()
+ // CHECK-NEXT: [return adjustment (to type 'struct test3::B *'): 8 non-virtual]
+ // CHECK-NEXT: 1 | void test3::D::z()
+ // CHECK-NEXT: 2 | test3::F *test3::X::foo()
+ // CHECK-NEXT: [return adjustment (to type 'struct test3::C *'): 4 non-virtual]
+ // CHECK-NEXT: 3 | test3::F *test3::X::foo()
+
+ // CHECK-LABEL: Thunks for 'test3::F *test3::X::foo()' (2 entries).
+ // CHECK-NEXT: 0 | [return adjustment (to type 'struct test3::C *'): 4 non-virtual]
+ // CHECK-NEXT: 1 | [return adjustment (to type 'struct test3::B *'): 8 non-virtual]
+
+ // CHECK-LABEL: VFTable indices for 'test3::X' (1 entry).
+ // CHECK-NEXT: 3 | test3::F *test3::X::foo()
+
+ virtual F* foo();
+};
+
+void build_vftable(X *obj) { obj->foo(); }
+}
+
+namespace test4 {
+struct A {
+ virtual void g();
+ virtual void h();
+};
+
+struct B {
+ virtual void g();
+};
+
+struct C : A, B {
+ virtual void g();
+};
+
+struct D {
+ virtual B* foo();
+ virtual void z();
+};
+
+struct E : D {
+ virtual C* foo();
+};
+
+struct F : A, C { };
+
+struct X : D, E {
+ // CHECK-LABEL: VFTable for 'test4::D' in 'test4::X' (3 entries).
+ // CHECK-NEXT: 0 | test4::F *test4::X::foo()
+ // CHECK-NEXT: [return adjustment (to type 'struct test4::B *'): 8 non-virtual]
+ // CHECK-NEXT: 1 | void test4::D::z()
+ // CHECK-NEXT: 2 | test4::F *test4::X::foo()
+
+ // CHECK-LABEL: Thunks for 'test4::F *test4::X::foo()' (1 entry).
+ // CHECK-NEXT: 0 | [return adjustment (to type 'struct test4::B *'): 8 non-virtual]
+
+ // CHECK-LABEL: VFTable for 'test4::D' in 'test4::E' in 'test4::X' (4 entries).
+ // CHECK-NEXT: 0 | test4::F *test4::X::foo()
+ // CHECK-NEXT: [return adjustment (to type 'struct test4::B *'): 8 non-virtual]
+ // CHECK-NEXT: [this adjustment: -4 non-virtual]
+ // CHECK-NEXT: 1 | void test4::D::z()
+ // CHECK-NEXT: 2 | test4::F *test4::X::foo()
+ // CHECK-NEXT: [return adjustment (to type 'struct test4::C *'): 4 non-virtual]
+ // CHECK-NEXT: [this adjustment: -4 non-virtual]
+ // CHECK-NEXT: 3 | test4::F *test4::X::foo()
+ // CHECK-NEXT: [return adjustment (to type 'struct test4::F *'): 0 non-virtual]
+ // CHECK-NEXT: [this adjustment: -4 non-virtual]
+
+ // CHECK-LABEL: Thunks for 'test4::F *test4::X::foo()' (3 entries).
+ // CHECK-NEXT: 0 | [return adjustment (to type 'struct test4::F *'): 0 non-virtual]
+ // CHECK-NEXT: [this adjustment: -4 non-virtual]
+ // CHECK-NEXT: 1 | [return adjustment (to type 'struct test4::C *'): 4 non-virtual]
+ // CHECK-NEXT: [this adjustment: -4 non-virtual]
+ // CHECK-NEXT: 2 | [return adjustment (to type 'struct test4::B *'): 8 non-virtual]
+ // CHECK-NEXT: [this adjustment: -4 non-virtual]
+
+ // CHECK-LABEL: VFTable indices for 'test4::X' (1 entry).
+ // CHECK-NEXT: 2 | test4::F *test4::X::foo()
+
+ virtual F* foo();
+};
+
+void build_vftable(X *obj) { obj->foo(); }
+}
+
+namespace test5 {
+struct A {
+ virtual void g();
+ virtual void h();
+};
+
+struct B {
+ virtual void g();
+};
+
+struct C : A, B {
+ virtual void g();
+};
+
+struct D {
+ virtual B* foo();
+ virtual void z();
+};
+
+struct X : A, D {
+ // CHECK-LABEL: VFTable for 'test5::A' in 'test5::X' (2 entries).
+ // CHECK-NEXT: 0 | void test5::A::g()
+ // CHECK-NEXT: 1 | void test5::A::h()
+
+ // CHECK-LABEL: VFTable for 'test5::D' in 'test5::X' (3 entries).
+ // CHECK-NEXT: 0 | test5::C *test5::X::foo()
+ // CHECK-NEXT: [return adjustment (to type 'struct test5::B *'): 4 non-virtual]
+ // CHECK-NEXT: 1 | void test5::D::z()
+ // CHECK-NEXT: 2 | test5::C *test5::X::foo()
+
+ // CHECK-LABEL: Thunks for 'test5::C *test5::X::foo()' (1 entry).
+ // CHECK-NEXT: 0 | [return adjustment (to type 'struct test5::B *'): 4 non-virtual]
+
+ // CHECK-LABEL: VFTable indices for 'test5::X' (1 entry).
+ // CHECK-NEXT: via vfptr at offset 4
+ // CHECK-NEXT: 2 | test5::C *test5::X::foo()
+
+ virtual C* foo();
+};
+
+void build_vftable(X *obj) { obj->foo(); }
+}
+
+namespace test6 {
+struct A {
+ virtual void g();
+ virtual void h();
+};
+
+struct B {
+ virtual void g();
+};
+
+struct C : A, B {
+ virtual void g();
+};
+
+struct D {
+ virtual B* foo();
+ virtual void z();
+};
+
+struct E : A, D {
+ virtual C* foo();
+};
+
+struct F : A, C { };
+
+struct X : E {
+ // CHECK-LABEL: VFTable for 'test6::A' in 'test6::E' in 'test6::X' (2 entries).
+ // CHECK-NEXT: 0 | void test6::A::g()
+ // CHECK-NEXT: 1 | void test6::A::h()
+
+ // CHECK-LABEL: VFTable for 'test6::D' in 'test6::E' in 'test6::X' (4 entries).
+ // CHECK-NEXT: 0 | test6::F *test6::X::foo()
+ // CHECK-NEXT: [return adjustment (to type 'struct test6::B *'): 8 non-virtual]
+ // CHECK-NEXT: 1 | void test6::D::z()
+ // CHECK-NEXT: 2 | test6::F *test6::X::foo()
+ // CHECK-NEXT: [return adjustment (to type 'struct test6::C *'): 4 non-virtual]
+ // CHECK-NEXT: 3 | test6::F *test6::X::foo()
+
+ // CHECK-LABEL: Thunks for 'test6::F *test6::X::foo()' (2 entries).
+ // CHECK-NEXT: 0 | [return adjustment (to type 'struct test6::C *'): 4 non-virtual]
+ // CHECK-NEXT: 1 | [return adjustment (to type 'struct test6::B *'): 8 non-virtual]
+
+ // CHECK-LABEL: VFTable indices for 'test6::X' (1 entry).
+ // CHECK-NEXT: -- accessible via vfptr at offset 4 --
+ // CHECK-NEXT: 3 | test6::F *test6::X::foo()
+
+ virtual F* foo();
+};
+
+void build_vftable(X *obj) { obj->foo(); }
+}
diff --git a/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-this-adjustment.cpp b/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-this-adjustment.cpp
new file mode 100644
index 000000000000..957980aa95ec
--- /dev/null
+++ b/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-this-adjustment.cpp
@@ -0,0 +1,140 @@
+// RUN: %clang_cc1 %s -fno-rtti -triple=i386-pc-win32 -emit-llvm -o %t.ll -fdump-vtable-layouts >%t
+// RUN: FileCheck %s < %t
+// RUN: FileCheck --check-prefix=MANGLING %s < %t.ll
+
+namespace test1 {
+struct A {
+ virtual void g();
+ // Add an extra virtual method so it's easier to check for the absence of thunks.
+ virtual void h();
+};
+
+struct B {
+ virtual void g(); // Collides with A::g if both are bases of some class.
+};
+
+// Overrides methods of two bases at the same time, thus needing thunks.
+struct X : A, B {
+ // CHECK-LABEL: VFTable for 'test1::A' in 'test1::X' (2 entries).
+ // CHECK-NEXT: 0 | void test1::X::g()
+ // CHECK-NEXT: 1 | void test1::A::h()
+
+ // CHECK-LABEL: VFTable for 'test1::B' in 'test1::X' (1 entry).
+ // CHECK-NEXT: 0 | void test1::X::g()
+ // CHECK-NEXT: [this adjustment: -4 non-virtual]
+
+ // CHECK-LABEL: Thunks for 'void test1::X::g()' (1 entry).
+ // CHECK-NEXT: 0 | [this adjustment: -4 non-virtual]
+
+ // CHECK-LABEL: VFTable indices for 'test1::X' (1 entry).
+ // CHECK-NEXT: 0 | void test1::X::g()
+
+ // MANGLING-DAG: @"\01??_7X@test1@@6BA@1@@"
+ // MANGLING-DAG: @"\01??_7X@test1@@6BB@1@@"
+
+ virtual void g();
+} x;
+
+void build_vftable(X *obj) { obj->g(); }
+}
+
+namespace test2 {
+struct A {
+ virtual void f();
+};
+
+struct B {
+ virtual void g();
+ virtual void h();
+};
+
+struct C {
+ virtual void g();
+};
+
+struct X : A, B, C {
+ // CHECK-LABEL: VFTable for 'test2::A' in 'test2::X' (1 entry).
+ // CHECK-NEXT: 0 | void test2::A::f()
+
+ // CHECK-LABEL: VFTable for 'test2::B' in 'test2::X' (2 entries).
+ // CHECK-NEXT: 0 | void test2::X::g()
+ // CHECK-NEXT: 1 | void test2::B::h()
+
+ // CHECK-LABEL: VFTable for 'test2::C' in 'test2::X' (1 entry).
+ // CHECK-NEXT: 0 | void test2::X::g()
+ // CHECK-NEXT: [this adjustment: -4 non-virtual]
+
+ // CHECK-LABEL: Thunks for 'void test2::X::g()' (1 entry).
+ // CHECK-NEXT: 0 | [this adjustment: -4 non-virtual]
+
+ // CHECK-LABEL: VFTable indices for 'test2::X' (1 entry).
+ // CHECK-NEXT: via vfptr at offset 4
+ // CHECK-NEXT: 0 | void test2::X::g()
+
+ // MANGLING-DAG: @"\01??_7X@test2@@6BA@1@@"
+ // MANGLING-DAG: @"\01??_7X@test2@@6BB@1@@"
+ // MANGLING-DAG: @"\01??_7X@test2@@6BC@1@@"
+
+ virtual void g();
+} x;
+
+void build_vftable(X *obj) { obj->g(); }
+}
+
+namespace test3 {
+struct A {
+ virtual void f();
+};
+
+struct B {
+ virtual void g();
+ virtual void h();
+};
+
+struct C: A, B {
+ // Overrides only the left child's method (A::f), needs no thunks.
+ virtual void f();
+};
+
+struct D: A, B {
+ // Overrides only the right child's method (B::g),
+ // needs this adjustment but not thunks.
+ virtual void g();
+};
+
+// Overrides methods of two bases at the same time, thus needing thunks.
+struct X: C, D {
+ // CHECK-LABEL: VFTable for 'test3::A' in 'test3::C' in 'test3::X' (1 entry).
+ // CHECK-NEXT: 0 | void test3::X::f()
+
+ // CHECK-LABEL: VFTable for 'test3::B' in 'test3::C' in 'test3::X' (2 entries).
+ // CHECK-NEXT: 0 | void test3::X::g()
+ // CHECK-NEXT: 1 | void test3::B::h()
+
+ // CHECK-LABEL: VFTable for 'test3::A' in 'test3::D' in 'test3::X' (1 entry).
+ // CHECK-NEXT: 0 | void test3::X::f()
+ // CHECK-NEXT: [this adjustment: -8 non-virtual]
+
+ // CHECK-LABEL: Thunks for 'void test3::X::f()' (1 entry).
+ // CHECK-NEXT: 0 | [this adjustment: -8 non-virtual]
+
+ // CHECK-LABEL: VFTable for 'test3::B' in 'test3::D' in 'test3::X' (2 entries).
+ // CHECK-NEXT: 0 | void test3::X::g()
+ // CHECK-NEXT: [this adjustment: -8 non-virtual]
+ // CHECK-NEXT: 1 | void test3::B::h()
+
+ // CHECK-LABEL: Thunks for 'void test3::X::g()' (1 entry).
+ // CHECK-NEXT: 0 | [this adjustment: -8 non-virtual]
+
+ // CHECK-LABEL: VFTable indices for 'test3::X' (2 entries).
+ // CHECK-NEXT: via vfptr at offset 0
+ // CHECK-NEXT: 0 | void test3::X::f()
+ // CHECK-NEXT: via vfptr at offset 4
+ // CHECK-NEXT: 0 | void test3::X::g()
+
+ virtual void f();
+ virtual void g();
+} x;
+
+void build_vftable(X *obj) { obj->g(); }
+}
diff --git a/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-vdtors.cpp b/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-vdtors.cpp
new file mode 100644
index 000000000000..a407766f8ed9
--- /dev/null
+++ b/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-vdtors.cpp
@@ -0,0 +1,94 @@
+// RUN: %clang_cc1 %s -fno-rtti -triple=i386-pc-win32 -emit-llvm -o %t.ll -fdump-vtable-layouts >%t
+// RUN: FileCheck %s < %t
+
+struct A {
+ virtual ~A();
+ virtual void z1();
+};
+
+struct B {
+ virtual ~B();
+};
+
+struct C : A, B {
+ // CHECK-LABEL: VFTable for 'A' in 'C' (2 entries).
+ // CHECK-NEXT: 0 | C::~C() [scalar deleting]
+ // CHECK-NEXT: 1 | void A::z1()
+
+ // CHECK-LABEL: VFTable for 'B' in 'C' (1 entry).
+ // CHECK-NEXT: 0 | C::~C() [scalar deleting]
+ // CHECK-NEXT: [this adjustment: -4 non-virtual]
+
+ // CHECK-LABEL: Thunks for 'C::~C()' (1 entry).
+ // CHECK-NEXT: 0 | [this adjustment: -4 non-virtual]
+
+ // CHECK-LABEL: VFTable indices for 'C' (1 entry).
+ // CHECK-NEXT: 0 | C::~C() [scalar deleting]
+ virtual ~C();
+};
+
+void build_vftable(C *obj) { delete obj; }
+
+struct D {
+ // No virtual destructor here!
+ virtual void z4();
+};
+
+struct E : D, B {
+ // Implicit virtual dtor here!
+
+ // CHECK-LABEL: VFTable for 'D' in 'E' (1 entry).
+ // CHECK-NEXT: 0 | void D::z4()
+
+ // CHECK-LABEL: VFTable for 'B' in 'E' (1 entry).
+ // CHECK-NEXT: 0 | E::~E() [scalar deleting]
+ // CHECK-NEXT: [this adjustment: -4 non-virtual]
+
+ // CHECK-LABEL: Thunks for 'E::~E()' (1 entry).
+ // CHECK-NEXT: 0 | [this adjustment: -4 non-virtual]
+
+ // CHECK-LABEL: VFTable indices for 'E' (1 entry).
+ // CHECK-NEXT: -- accessible via vfptr at offset 4 --
+ // CHECK-NEXT: 0 | E::~E() [scalar deleting]
+};
+
+void build_vftable(E *obj) { delete obj; }
+
+struct F : D, B {
+ // Implicit virtual dtor here!
+
+ // CHECK-LABEL: VFTable for 'D' in 'F' (1 entry).
+ // CHECK-NEXT: 0 | void D::z4()
+
+ // CHECK-LABEL: VFTable for 'B' in 'F' (1 entry).
+ // CHECK-NEXT: 0 | F::~F() [scalar deleting]
+ // CHECK-NEXT: [this adjustment: -4 non-virtual]
+
+ // CHECK-LABEL: Thunks for 'F::~F()' (1 entry).
+ // CHECK-NEXT: 0 | [this adjustment: -4 non-virtual]
+
+ // CHECK-LABEL: VFTable indices for 'F' (1 entry).
+ // CHECK-NEXT: -- accessible via vfptr at offset 4 --
+ // CHECK-NEXT: 0 | F::~F() [scalar deleting]
+};
+
+void build_vftable(F *obj) { delete obj; }
+
+struct G : F {
+ // CHECK-LABEL: VFTable for 'D' in 'F' in 'G' (1 entry).
+ // CHECK-NEXT: 0 | void D::z4()
+
+ // CHECK-LABEL: VFTable for 'B' in 'F' in 'G' (1 entry).
+ // CHECK-NEXT: 0 | G::~G() [scalar deleting]
+ // CHECK-NEXT: [this adjustment: -4 non-virtual]
+
+ // CHECK-LABEL: Thunks for 'G::~G()' (1 entry).
+ // CHECK-NEXT: 0 | [this adjustment: -4 non-virtual]
+
+ // CHECK-LABEL: VFTable indices for 'G' (1 entry).
+ // CHECK-NEXT: -- accessible via vfptr at offset 4 --
+ // CHECK-NEXT: 0 | G::~G() [scalar deleting]
+ virtual ~G();
+};
+
+void build_vftable(G *obj) { delete obj; }
diff --git a/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance.cpp b/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance.cpp
deleted file mode 100644
index d93dee11cdee..000000000000
--- a/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance.cpp
+++ /dev/null
@@ -1,579 +0,0 @@
-// 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-return-thunks.cpp b/test/CodeGenCXX/microsoft-abi-vtables-return-thunks.cpp
new file mode 100644
index 000000000000..a4a21106c685
--- /dev/null
+++ b/test/CodeGenCXX/microsoft-abi-vtables-return-thunks.cpp
@@ -0,0 +1,106 @@
+// RUN: %clang_cc1 -fno-rtti %s -emit-llvm -o %t -triple=i386-pc-win32 -fdump-vtable-layouts 2>&1 | FileCheck --check-prefix=VFTABLES %s
+// RUN: FileCheck --check-prefix=GLOBALS %s < %t
+// RUN: FileCheck --check-prefix=CODEGEN %s < %t
+
+namespace test1 {
+
+// Some covariant types.
+struct A { int a; };
+struct B { int b; };
+struct C : A, B { int c; };
+struct D : C { int d; };
+struct E : D { int e; };
+
+// One base class and two overrides, all with covariant return types.
+struct H { virtual B *foo(); };
+struct I : H { virtual C *foo(); };
+struct J : I { virtual D *foo(); J(); };
+struct K : J { virtual E *foo(); K(); };
+
+J::J() {}
+
+// VFTABLES-LABEL: VFTable for 'test1::H' in 'test1::I' in 'test1::J' (3 entries).
+// VFTABLES-NEXT: 0 | test1::D *test1::J::foo()
+// VFTABLES-NEXT: [return adjustment (to type 'struct test1::B *'): 4 non-virtual]
+// VFTABLES-NEXT: 1 | test1::D *test1::J::foo()
+// VFTABLES-NEXT: [return adjustment (to type 'struct test1::C *'): 0 non-virtual]
+// VFTABLES-NEXT: 2 | test1::D *test1::J::foo()
+
+// GLOBALS-LABEL: @"\01??_7J@test1@@6B@" = linkonce_odr unnamed_addr constant [3 x i8*]
+// GLOBALS: @"\01?foo@J@test1@@QAEPAUB@2@XZ"
+// GLOBALS: @"\01?foo@J@test1@@QAEPAUC@2@XZ"
+// GLOBALS: @"\01?foo@J@test1@@UAEPAUD@2@XZ"
+
+K::K() {}
+
+// VFTABLES-LABEL: VFTable for 'test1::H' in 'test1::I' in 'test1::J' in 'test1::K' (4 entries).
+// VFTABLES-NEXT: 0 | test1::E *test1::K::foo()
+// VFTABLES-NEXT: [return adjustment (to type 'struct test1::B *'): 4 non-virtual]
+// VFTABLES-NEXT: 1 | test1::E *test1::K::foo()
+// VFTABLES-NEXT: [return adjustment (to type 'struct test1::C *'): 0 non-virtual]
+// VFTABLES-NEXT: 2 | test1::E *test1::K::foo()
+// VFTABLES-NEXT: [return adjustment (to type 'struct test1::D *'): 0 non-virtual]
+// VFTABLES-NEXT: 3 | test1::E *test1::K::foo()
+
+// Only B to C requires adjustment, but we get 3 thunks in K's vftable, two of
+// which are trivial.
+// GLOBALS-LABEL: @"\01??_7K@test1@@6B@" = linkonce_odr unnamed_addr constant [4 x i8*]
+// GLOBALS: @"\01?foo@K@test1@@QAEPAUB@2@XZ"
+// GLOBALS: @"\01?foo@K@test1@@QAEPAUC@2@XZ"
+// GLOBALS: @"\01?foo@K@test1@@QAEPAUD@2@XZ"
+// GLOBALS: @"\01?foo@K@test1@@UAEPAUE@2@XZ"
+
+// This thunk has a return adjustment.
+// CODEGEN-LABEL: define {{.*}} @"\01?foo@K@test1@@QAEPAUB@2@XZ"
+// CODEGEN: call {{.*}} @"\01?foo@K@test1@@UAEPAUE@2@XZ"
+// CODEGEN: icmp {{.*}}, null
+// CODEGEN: getelementptr
+// CODEGEN: ret
+
+// These two don't.
+// CODEGEN-LABEL: define {{.*}} @"\01?foo@K@test1@@QAEPAUC@2@XZ"
+// CODEGEN: call {{.*}} @"\01?foo@K@test1@@UAEPAUE@2@XZ"
+// CODEGEN-NEXT: ret
+
+// CODEGEN-LABEL: define {{.*}} @"\01?foo@K@test1@@QAEPAUD@2@XZ"
+// CODEGEN: call {{.*}} @"\01?foo@K@test1@@UAEPAUE@2@XZ"
+// CODEGEN-NEXT: ret
+
+}
+
+namespace test2 {
+
+// Covariant types. D* is not trivially convertible to C*.
+struct A { int a; };
+struct B { int b; };
+struct C : B { int c; };
+struct D : A, C { int d; };
+struct E : D { int e; };
+
+// J's foo will require an adjusting thunk, and K will require a trivial thunk.
+struct H { virtual B *foo(); };
+struct I : H { virtual C *foo(); };
+struct J : I { virtual D *foo(); J(); };
+struct K : J { virtual E *foo(); K(); };
+
+J::J() {}
+
+// VFTABLES-LABEL: VFTable for 'test2::H' in 'test2::I' in 'test2::J' (2 entries).
+// VFTABLES-NEXT: 0 | test2::D *test2::J::foo()
+// VFTABLES-NEXT: [return adjustment (to type 'struct test2::B *'): 4 non-virtual]
+// VFTABLES-NEXT: 1 | test2::D *test2::J::foo()
+
+// GLOBALS-LABEL: @"\01??_7J@test2@@6B@" = linkonce_odr unnamed_addr constant [2 x i8*]
+
+K::K() {}
+
+// VFTABLES-LABEL: VFTable for 'test2::H' in 'test2::I' in 'test2::J' in 'test2::K' (3 entries).
+// VFTABLES-NEXT: 0 | test2::E *test2::K::foo()
+// VFTABLES-NEXT: [return adjustment (to type 'struct test2::B *'): 4 non-virtual]
+// VFTABLES-NEXT: 1 | test2::E *test2::K::foo()
+// VFTABLES-NEXT: [return adjustment (to type 'struct test2::D *'): 0 non-virtual]
+// VFTABLES-NEXT: 2 | test2::E *test2::K::foo()
+
+// GLOBALS-LABEL: @"\01??_7K@test2@@6B@" = linkonce_odr unnamed_addr constant [3 x i8*]
+
+}
diff --git a/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp b/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp
index 6fe12b0ef07b..d453f5c55aed 100644
--- a/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp
+++ b/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp
@@ -1,29 +1,17 @@
-// RUN: %clang_cc1 %s -fno-rtti -cxx-abi microsoft -triple=i386-pc-win32 -emit-llvm -fdump-vtable-layouts -o %t.ll > %t
+// RUN: %clang_cc1 %s -fno-rtti -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
-// RUN: FileCheck --check-prefix=CHECK-D %s < %t
-// RUN: FileCheck --check-prefix=CHECK-E %s < %t
-// RUN: FileCheck --check-prefix=CHECK-F %s < %t
-// RUN: FileCheck --check-prefix=CHECK-G %s < %t
-// 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
+// RUN: FileCheck %s < %t
struct A {
- // 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()
- // 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()
+ // CHECK-LABEL: VFTable for 'A' (3 entries)
+ // CHECK-NEXT: 0 | void A::f()
+ // CHECK-NEXT: 1 | void A::g()
+ // CHECK-NEXT: 2 | void A::h()
+ // CHECK-LABEL: VFTable indices for 'A' (3 entries)
+ // CHECK-NEXT: 0 | void A::f()
+ // CHECK-NEXT: 1 | void A::g()
+ // CHECK-NEXT: 2 | void A::h()
virtual void f();
virtual void g();
@@ -32,18 +20,19 @@ struct A {
};
A a;
// EMITS-VFTABLE-DAG: @"\01??_7A@@6B@" = linkonce_odr unnamed_addr constant [3 x i8*]
+void use(A *obj) { obj->f(); }
struct B : A {
- // 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()
- // 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()
+ // CHECK-LABEL: VFTable for 'A' in 'B' (5 entries)
+ // CHECK-NEXT: 0 | void B::f()
+ // CHECK-NEXT: 1 | void A::g()
+ // CHECK-NEXT: 2 | void A::h()
+ // CHECK-NEXT: 3 | void B::i()
+ // CHECK-NEXT: 4 | void B::j()
+ // CHECK-LABEL: VFTable indices for 'B' (3 entries)
+ // CHECK-NEXT: 0 | void B::f()
+ // CHECK-NEXT: 3 | void B::i()
+ // CHECK-NEXT: 4 | void B::j()
virtual void f(); // overrides A::f()
virtual void i();
@@ -51,45 +40,48 @@ struct B : A {
};
B b;
// EMITS-VFTABLE-DAG: @"\01??_7B@@6B@" = linkonce_odr unnamed_addr constant [5 x i8*]
+void use(B *obj) { obj->f(); }
struct C {
- // CHECK-C: VFTable for 'C' (2 entries)
- // CHECK-C-NEXT: 0 | C::~C() [scalar deleting]
- // CHECK-C-NEXT: 1 | void C::f()
- // CHECK-C: VFTable indices for 'C' (2 entries).
- // CHECK-C-NEXT: 0 | C::~C() [scalar deleting]
- // CHECK-C-NEXT: 1 | void C::f()
+ // CHECK-LABEL: VFTable for 'C' (2 entries)
+ // CHECK-NEXT: 0 | C::~C() [scalar deleting]
+ // CHECK-NEXT: 1 | void C::f()
+ // CHECK-LABEL: VFTable indices for 'C' (2 entries).
+ // CHECK-NEXT: 0 | C::~C() [scalar deleting]
+ // CHECK-NEXT: 1 | void C::f()
virtual ~C();
virtual void f();
};
void C::f() {}
// NO-VFTABLE-NOT: @"\01??_7C@@6B@"
+void use(C *obj) { obj->f(); }
struct D {
- // 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]
+ // CHECK-LABEL: VFTable for 'D' (2 entries)
+ // CHECK-NEXT: 0 | void D::f()
+ // CHECK-NEXT: 1 | D::~D() [scalar deleting]
+ // CHECK-LABEL: VFTable indices for 'D' (2 entries)
+ // CHECK-NEXT: 0 | void D::f()
+ // CHECK-NEXT: 1 | D::~D() [scalar deleting]
virtual void f();
virtual ~D();
};
D d;
// EMITS-VFTABLE-DAG: @"\01??_7D@@6B@" = linkonce_odr unnamed_addr constant [2 x i8*]
+void use(D *obj) { obj->f(); }
struct E : A {
- // 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: VFTable indices for 'E' (2 entries).
- // CHECK-E-NEXT: 3 | E::~E() [scalar deleting]
- // CHECK-E-NEXT: 4 | void E::i()
+ // CHECK-LABEL: VFTable for 'A' in 'E' (5 entries)
+ // CHECK-NEXT: 0 | void A::f()
+ // CHECK-NEXT: 1 | void A::g()
+ // CHECK-NEXT: 2 | void A::h()
+ // CHECK-NEXT: 3 | E::~E() [scalar deleting]
+ // CHECK-NEXT: 4 | void E::i()
+ // CHECK-LABEL: VFTable indices for 'E' (2 entries).
+ // CHECK-NEXT: 3 | E::~E() [scalar deleting]
+ // CHECK-NEXT: 4 | void E::i()
// ~E would be the key method, but it isn't used, and MS ABI has no key
// methods.
@@ -98,36 +90,38 @@ struct E : A {
};
void E::i() {}
// NO-VFTABLE-NOT: @"\01??_7E@@6B@"
+void use(E *obj) { obj->i(); }
struct F : A {
- // 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: VFTable indices for 'F' (2 entries).
- // CHECK-F-NEXT: 3 | void F::i()
- // CHECK-F-NEXT: 4 | F::~F() [scalar deleting]
+ // CHECK-LABEL: VFTable for 'A' in 'F' (5 entries)
+ // CHECK-NEXT: 0 | void A::f()
+ // CHECK-NEXT: 1 | void A::g()
+ // CHECK-NEXT: 2 | void A::h()
+ // CHECK-NEXT: 3 | void F::i()
+ // CHECK-NEXT: 4 | F::~F() [scalar deleting]
+ // CHECK-LABEL: VFTable indices for 'F' (2 entries).
+ // CHECK-NEXT: 3 | void F::i()
+ // CHECK-NEXT: 4 | F::~F() [scalar deleting]
virtual void i();
virtual ~F();
};
F f;
// EMITS-VFTABLE-DAG: @"\01??_7F@@6B@" = linkonce_odr unnamed_addr constant [5 x i8*]
+void use(F *obj) { obj->i(); }
struct G : E {
- // 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: 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()
+ // CHECK-LABEL: VFTable for 'A' in 'E' in 'G' (6 entries)
+ // CHECK-NEXT: 0 | void G::f()
+ // CHECK-NEXT: 1 | void A::g()
+ // CHECK-NEXT: 2 | void A::h()
+ // CHECK-NEXT: 3 | G::~G() [scalar deleting]
+ // CHECK-NEXT: 4 | void E::i()
+ // CHECK-NEXT: 5 | void G::j()
+ // CHECK-LABEL: VFTable indices for 'G' (3 entries).
+ // CHECK-NEXT: 0 | void G::f()
+ // CHECK-NEXT: 3 | G::~G() [scalar deleting]
+ // CHECK-NEXT: 5 | void G::j()
virtual void f(); // overrides A::f()
virtual ~G();
@@ -135,6 +129,7 @@ struct G : E {
};
void G::j() {}
// NO-VFTABLE-NOT: @"\01??_7G@@6B@"
+void use(G *obj) { obj->j(); }
// Test that the usual Itanium-style key method does not emit a vtable.
struct H {
@@ -146,23 +141,24 @@ void H::f() {}
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()
+ // CHECK-LABEL: VFTable for 'I' (2 entries)
+ // CHECK-NEXT: 0 | void I::f()
+ // CHECK-NEXT: 1 | void I::g()
virtual void f();
virtual void g();
};
I i;
+void use(I *obj) { obj->f(); }
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)
+ // CHECK-LABEL: VFTable for 'J' (6 entries)
+ // CHECK-NEXT: 0 | void J::foo(long)
+ // CHECK-NEXT: 1 | void J::foo(int)
+ // CHECK-NEXT: 2 | void J::foo(short)
+ // CHECK-NEXT: 3 | void J::bar(long)
+ // CHECK-NEXT: 4 | void J::bar(int)
+ // CHECK-NEXT: 5 | void J::bar(short)
virtual void foo(short);
virtual void bar(short);
virtual void foo(int);
@@ -172,36 +168,38 @@ struct J {
};
J j;
+void use(J *obj) { obj->foo(42); }
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)
+ // CHECK-LABEL: VFTable for 'J' in 'K' (9 entries)
+ // CHECK-NEXT: 0 | void J::foo(long)
+ // CHECK-NEXT: 1 | void J::foo(int)
+ // CHECK-NEXT: 2 | void J::foo(short)
+ // CHECK-NEXT: 3 | void J::bar(long)
+ // CHECK-NEXT: 4 | void J::bar(int)
+ // CHECK-NEXT: 5 | void J::bar(short)
+ // CHECK-NEXT: 6 | void K::bar(double)
+ // CHECK-NEXT: 7 | void K::bar(float)
+ // CHECK-NEXT: 8 | void K::foo(float)
virtual void bar(float);
virtual void foo(float);
virtual void bar(double);
};
K k;
+void use(K *obj) { obj->foo(42.0f); }
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)
+ // CHECK-LABEL: VFTable for 'J' in 'L' (9 entries)
+ // CHECK-NEXT: 0 | void J::foo(long)
+ // CHECK-NEXT: 1 | void L::foo(int)
+ // CHECK-NEXT: 2 | void J::foo(short)
+ // CHECK-NEXT: 3 | void J::bar(long)
+ // CHECK-NEXT: 4 | void J::bar(int)
+ // CHECK-NEXT: 5 | void J::bar(short)
+ // CHECK-NEXT: 6 | void L::foo(float)
+ // CHECK-NEXT: 7 | void L::bar(double)
+ // CHECK-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.
@@ -212,20 +210,21 @@ struct L : J {
};
L l;
+void use(L *obj) { obj->foo(42.0f); }
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)
+ // CHECK-LABEL: VFTable for 'J' in 'M' (11 entries)
+ // CHECK-NEXT: 0 | void J::foo(long)
+ // CHECK-NEXT: 1 | void M::foo(int)
+ // CHECK-NEXT: 2 | void J::foo(short)
+ // CHECK-NEXT: 3 | void J::bar(long)
+ // CHECK-NEXT: 4 | void J::bar(int)
+ // CHECK-NEXT: 5 | void J::bar(short)
+ // CHECK-NEXT: 6 | void M::foo(float)
+ // CHECK-NEXT: 7 | void M::spam(long)
+ // CHECK-NEXT: 8 | void M::spam(int)
+ // CHECK-NEXT: 9 | void M::bar(double)
+ // CHECK-NEXT: 10 | void M::bar(float)
virtual void foo(int);
virtual void spam(int);
@@ -236,13 +235,14 @@ struct M : J {
};
M m;
+void use(M *obj) { obj->foo(42.0f); }
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)
+ // CHECK-LABEL: VFTable for 'N' (4 entries)
+ // CHECK-NEXT: 0 | void N::operator+(int)
+ // CHECK-NEXT: 1 | void N::operator+(short)
+ // CHECK-NEXT: 2 | void N::operator*(int)
+ // CHECK-NEXT: 3 | void N::operator*(short)
virtual void operator+(short);
virtual void operator*(short);
virtual void operator+(int);
@@ -250,3 +250,42 @@ struct N {
};
N n;
+void use(N *obj) { obj->operator+(42); }
+
+struct O { virtual A *f(); };
+struct P : O { virtual B *f(); };
+P p;
+void use(O *obj) { obj->f(); }
+void use(P *obj) { obj->f(); }
+// CHECK-LABEL: VFTable for 'O' (1 entry)
+// CHECK-NEXT: 0 | A *O::f()
+
+// CHECK-LABEL: VFTable for 'O' in 'P' (1 entry)
+// CHECK-NEXT: 0 | B *P::f()
+
+struct Q {
+ // CHECK-LABEL: VFTable for 'Q' (2 entries)
+ // CHECK-NEXT: 0 | void Q::foo(int)
+ // CHECK-NEXT: 1 | void Q::bar(int)
+ void foo(short);
+ void bar(short);
+ virtual void bar(int);
+ virtual void foo(int);
+};
+
+Q q;
+void use(Q *obj) { obj->foo(42); }
+
+// Inherited non-virtual overloads don't participate in the ordering.
+struct R : Q {
+ // CHECK-LABEL: VFTable for 'Q' in 'R' (4 entries)
+ // CHECK-NEXT: 0 | void Q::foo(int)
+ // CHECK-NEXT: 1 | void Q::bar(int)
+ // CHECK-NEXT: 2 | void R::bar(long)
+ // CHECK-NEXT: 3 | void R::foo(long)
+ virtual void bar(long);
+ virtual void foo(long);
+};
+
+R r;
+void use(R *obj) { obj->foo(42l); }
diff --git a/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance-vtordisps.cpp b/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance-vtordisps.cpp
index 3fef0e409349..f63808a89873 100644
--- a/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance-vtordisps.cpp
+++ b/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance-vtordisps.cpp
@@ -1,19 +1,9 @@
-// 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: %clang_cc1 -fno-rtti -emit-llvm -fdump-vtable-layouts %s -o %t.ll -triple=i386-pc-win32 > %t
+// RUN: FileCheck %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
+// RUN: %clang_cc1 -fno-rtti -emit-llvm-only -fdump-vtable-layouts %s -triple=x86_64-pc-win32 > /dev/null
struct V1 {
virtual void f();
@@ -64,11 +54,17 @@ namespace simple {
// 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]
+ // CHECK-LABEL: VFTable for 'V1' in 'simple::A' (2 entries).
+ // CHECK-NEXT: 0 | void simple::A::f()
+ // CHECK-NEXT: [this adjustment: vtordisp at -4, 0 non-virtual]
+ // CHECK-NEXT: 1 | simple::A::~A() [scalar deleting]
+ // CHECK-NEXT: [this adjustment: vtordisp at -4, 0 non-virtual]
+
+ // CHECK-LABEL: Thunks for 'simple::A::~A()' (1 entry).
+ // CHECK-NEXT: 0 | [this adjustment: vtordisp at -4, 0 non-virtual]
+
+ // CHECK-LABEL: Thunks for 'void simple::A::f()' (1 entry).
+ // CHECK-NEXT: 0 | [this adjustment: vtordisp at -4, 0 non-virtual]
virtual void f();
// MANGLING-DAG: @"\01?f@A@simple@@$4PPPPPPPM@A@AEXXZ"
@@ -78,18 +74,28 @@ struct A : virtual V1 {
};
A a;
+void use(A *obj) { obj->f(); }
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]
+ // CHECK-LABEL: VFTable for 'Z' in 'V3' in 'simple::B' (2 entries).
+ // CHECK-NEXT: 0 | void Z::g()
+ // CHECK-NEXT: 1 | simple::B::~B() [scalar deleting]
+ // CHECK-NEXT: [this adjustment: vtordisp at -4, 0 non-virtual]
+
+ // CHECK-LABEL: Thunks for 'simple::B::~B()' (1 entry).
+ // CHECK-NEXT: 0 | [this adjustment: vtordisp at -4, 0 non-virtual]
+
+ // CHECK-LABEL: VFTable for 'V2' in 'V3' in 'simple::B' (2 entries).
+ // CHECK-NEXT: 0 | void simple::B::f()
+ // CHECK-NEXT: [this adjustment: vtordisp at -12, 0 non-virtual]
+ // CHECK-NEXT: 1 | simple::B::~B() [scalar deleting]
+ // CHECK-NEXT: [this adjustment: vtordisp at -12, -8 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]
+ // CHECK-LABEL: Thunks for 'simple::B::~B()' (1 entry).
+ // CHECK-NEXT: 0 | [this adjustment: vtordisp at -12, -8 non-virtual]
+
+ // CHECK-LABEL: Thunks for 'void simple::B::f()' (1 entry).
+ // CHECK-NEXT: 0 | [this adjustment: vtordisp at -12, 0 non-virtual]
// FIXME: The vtordisp thunk should only get emitted for a constructor
// if "this" leaves scope.
@@ -104,24 +110,40 @@ struct B : virtual V3 {
};
B b;
+void use(B *obj) { obj->f(); }
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]
+ // CHECK-LABEL: VFTable for 'Z' in 'V4' in 'simple::C' (2 entries).
+ // CHECK-NEXT: 0 | void Z::g()
+ // CHECK-NEXT: 1 | simple::C::~C() [scalar deleting]
+ // CHECK-NEXT: [this adjustment: vtordisp at -4, 0 non-virtual]
+
+ // CHECK-LABEL: Thunks for 'simple::C::~C()' (1 entry).
+ // CHECK-NEXT: 0 | [this adjustment: vtordisp at -4, 0 non-virtual]
+
+ // CHECK-LABEL: VFTable for 'V1' in 'V4' in 'simple::C' (2 entries).
+ // CHECK-NEXT: 0 | void simple::C::f()
+ // CHECK-NEXT: [this adjustment: vtordisp at -12, 0 non-virtual]
+ // CHECK-NEXT: 1 | simple::C::~C() [scalar deleting]
+ // CHECK-NEXT: [this adjustment: vtordisp at -12, -8 non-virtual]
+
+ // CHECK-LABEL: Thunks for 'simple::C::~C()' (1 entry).
+ // CHECK-NEXT: 0 | [this adjustment: vtordisp at -12, -8 non-virtual]
+
+ // CHECK-LABEL: Thunks for 'void simple::C::f()' (1 entry).
+ // CHECK-NEXT: 0 | [this adjustment: vtordisp at -12, 0 non-virtual]
+
+ // CHECK-LABEL: VFTable for 'V2' in 'V4' in 'simple::C' (2 entries).
+ // CHECK-NEXT: 0 | void simple::C::f()
+ // CHECK-NEXT: [this adjustment: vtordisp at -16, -4 non-virtual]
+ // CHECK-NEXT: 1 | simple::C::~C() [scalar deleting]
+ // CHECK-NEXT: [this adjustment: vtordisp at -16, -12 non-virtual]
+
+ // CHECK-LABEL: Thunks for 'simple::C::~C()' (1 entry).
+ // CHECK-NEXT: 0 | [this adjustment: vtordisp at -16, -12 non-virtual]
+
+ // CHECK-LABEL: Thunks for 'void simple::C::f()' (1 entry).
+ // CHECK-NEXT: 0 | [this adjustment: vtordisp at -16, -4 non-virtual]
int x;
virtual void f();
@@ -134,6 +156,68 @@ struct C : virtual V4 {
};
C c;
+void use(C *obj) { obj->f(); }
+
+class D : B {
+ // CHECK-LABEL: VFTable for 'V2' in 'V3' in 'simple::B' in 'simple::D' (2 entries).
+ // CHECK-NEXT: 0 | void simple::B::f()
+ // CHECK-NEXT: [this adjustment: vtordisp at -12, -4 non-virtual]
+ // CHECK-NEXT: 1 | simple::D::~D() [scalar deleting]
+ // CHECK-NEXT: [this adjustment: vtordisp at -12, -8 non-virtual]
+ D();
+ int z;
+
+ // MANGLING-DAG: @"\01?f@B@simple@@$4PPPPPPPE@3AEXXZ"
+};
+
+D::D() {}
+
+struct E : V3 {
+ virtual void f();
+};
+
+struct F : virtual E {
+ // CHECK-LABEL: VFTable for 'Z' in 'V3' in 'simple::E' in 'simple::F' (2 entries).
+ // CHECK-NEXT: 0 | void simple::F::g()
+ // CHECK-NEXT: [this adjustment: vtordisp at -4, 0 non-virtual]
+ // CHECK-NEXT: 1 | simple::F::~F() [scalar deleting]
+ // CHECK-NEXT: [this adjustment: vtordisp at -4, 0 non-virtual]
+
+ // CHECK-LABEL: VFTable for 'V2' in 'V3' in 'simple::E' in 'simple::F' (2 entries).
+ // CHECK-NEXT: 0 | void simple::E::f()
+ // CHECK-NEXT: 1 | simple::F::~F() [scalar deleting]
+ // CHECK-NEXT: [this adjustment: vtordisp at -12, -8 non-virtual]
+
+ F();
+ virtual void g(); // Force a vtordisp.
+ int f;
+
+ // MANGLING-DAG: @"\01?g@F@simple@@$4PPPPPPPM@A@AEXXZ"{{.*}}??_EF@simple@@$4PPPPPPPM@A@AEPAXI@Z
+ // MANGLING-DAG: ?f@E@simple@@UAEXXZ{{.*}}??_EF@simple@@$4PPPPPPPE@7AEPAXI@Z
+};
+
+F::F() {}
+
+struct G : F {
+ // CHECK-LABEL: VFTable for 'Z' in 'V3' in 'simple::E' in 'simple::F' in 'simple::G' (2 entries).
+ // CHECK-NEXT: 0 | void simple::F::g()
+ // CHECK-NEXT: [this adjustment: vtordisp at -4, -4 non-virtual]
+ // CHECK-NEXT: 1 | simple::G::~G() [scalar deleting]
+ // CHECK-NEXT: [this adjustment: vtordisp at -4, 0 non-virtual]
+
+ // CHECK-LABEL: VFTable for 'V2' in 'V3' in 'simple::E' in 'simple::F' in 'simple::G' (2 entries).
+ // CHECK-NEXT: 0 | void simple::E::f()
+ // CHECK-NEXT: 1 | simple::G::~G() [scalar deleting]
+ // CHECK-NEXT: [this adjustment: vtordisp at -12, -8 non-virtual]
+
+ G();
+ int g;
+
+ // MANGLING-DAG: @"\01?g@F@simple@@$4PPPPPPPM@3AEXXZ"{{.*}}@"\01??_EG@simple@@$4PPPPPPPM@A@AEPAXI@Z"
+ // MANGLING-DAG: @"\01?f@E@simple@@UAEXXZ"{{.*}}@"\01??_EG@simple@@$4PPPPPPPE@7AEPAXI@Z"
+};
+
+G::G() {}
}
namespace extended {
@@ -152,12 +236,16 @@ namespace extended {
// 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]
+ // CHECK-LABEL: VFTable for 'V1' in 'simple::A' in 'extended::A' (2 entries).
+ // CHECK-NEXT: 0 | void simple::A::f()
+ // CHECK-NEXT: [this adjustment: vtordisp at -4, vbptr at 8 to the left,
+ // CHECK-NEXT: vboffset at 8 in the vbtable, 8 non-virtual]
+ // CHECK-NEXT: 1 | extended::A::~A() [scalar deleting]
+ // CHECK-NEXT: [this adjustment: vtordisp at -4, 0 non-virtual]
+
+ // CHECK-LABEL: Thunks for 'void simple::A::f()' (1 entry).
+ // CHECK-NEXT: 0 | [this adjustment: vtordisp at -4, vbptr at 8 to the left,
+ // CHECK-NEXT: vboffset at 8 in the vbtable, 8 non-virtual]
// `vtordispex{8,8,4294967292,8}'
// MANGLING-DAG: @"\01?f@A@simple@@$R477PPPPPPPM@7AEXXZ"
@@ -168,28 +256,38 @@ struct A : virtual simple::A {
};
A a;
+void use(A *obj) { delete obj; }
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).
+ // CHECK-LABEL: 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]
+ // CHECK: 1 | extended::B::~B() [scalar deleting]
+ // CHECK-NEXT: [this adjustment: vtordisp at -4, 0 non-virtual]
+
+ // CHECK-LABEL: Thunks for 'void simple::A::f()' (1 entry).
+ // CHECK-NEXT: 0 | [this adjustment: vtordisp at -4, vbptr at 8 to the left,
+ // CHECK-NEXT: vboffset at 8 in the vbtable, 8 non-virtual]
// vtordisp{4294967292,0}
// MANGLING-DAG: @"\01??_EB@extended@@$4PPPPPPPM@A@AEPAXI@Z"
};
B b;
+void use(B *obj) { delete obj; }
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]
+ // CHECK-LABEL: VFTable for 'V1' in 'simple::A' in 'extended::C' (2 entries).
+ // CHECK-NEXT: 0 | void simple::A::f()
+ // CHECK-NEXT: [this adjustment: vtordisp at -4, vbptr at 12 to the left,
+ // CHECK-NEXT: vboffset at 8 in the vbtable, 8 non-virtual]
+
+ // CHECK-LABEL: Thunks for 'void simple::A::f()' (1 entry).
+ // CHECK-NEXT: 0 | [this adjustment: vtordisp at -4, vbptr at 12 to the left,
+ // CHECK-NEXT: vboffset at 8 in the vbtable, 8 non-virtual]
// `vtordispex{12,8,4294967292,8}'
// MANGLING-DAG: @"\01?f@A@simple@@$R4M@7PPPPPPPM@7AEXXZ"
@@ -199,6 +297,7 @@ struct C : virtual simple::A {
};
C c;
+void use(C *obj) { delete obj; }
struct D : virtual V2 {
virtual void f();
@@ -207,10 +306,14 @@ struct D : virtual V2 {
};
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]
+ // CHECK-LABEL: VFTable for 'V2' in 'extended::D' in 'extended::E' (2 entries).
+ // CHECK-NEXT: 0 | void extended::D::f()
+ // CHECK-NEXT: [this adjustment: vtordisp at -4, vbptr at 8 to the left,
+ // CHECK-NEXT: vboffset at 8 in the vbtable, 12 non-virtual]
+
+ // CHECK-LABEL: Thunks for 'void extended::D::f()' (1 entry).
+ // CHECK-NEXT: 0 | [this adjustment: vtordisp at -4, vbptr at 8 to the left,
+ // CHECK-NEXT: vboffset at 8 in the vbtable, 12 non-virtual]
// `vtordispex{8,8,4294967292,12}'
// MANGLING-DAG: @"\01?f@D@extended@@$R477PPPPPPPM@M@AEXXZ"
@@ -220,12 +323,17 @@ struct E : virtual D {
};
E e;
+void use(E *obj) { delete obj; }
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]
+ // CHECK-LABEL: VFTable for 'V2' in 'extended::D' in 'extended::F' (2 entries).
+ // CHECK-NEXT: 0 | void extended::D::f()
+ // CHECK-NEXT: [this adjustment: vtordisp at -4, vbptr at 20 to the left,
+ // CHECK-NEXT: vboffset at 12 in the vbtable, 12 non-virtual]
+
+ // CHECK-LABEL: Thunks for 'void extended::D::f()' (1 entry).
+ // CHECK-NEXT: 0 | [this adjustment: vtordisp at -4, vbptr at 20 to the left,
+ // CHECK-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"
@@ -235,17 +343,22 @@ struct F : virtual Z, virtual D {
};
F f;
+void use(F *obj) { delete obj; }
struct G : virtual simple::A {
- // VTABLE-EXTENDED-G: VFTable for 'extended::G' (1 entries).
- // VTABLE-EXTENDED-G-NEXT: 0 | void extended::G::g()
+ // CHECK-LABEL: VFTable for 'extended::G' (1 entry).
+ // CHECK-NEXT: 0 | void extended::G::g()
+
+ // CHECK-LABEL: VFTable for 'V1' in 'simple::A' in 'extended::G' (2 entries).
+ // CHECK-NEXT: 0 | void simple::A::f()
+ // CHECK-NEXT: [this adjustment: vtordisp at -4, vbptr at 8 to the left,
+ // CHECK-NEXT: vboffset at 8 in the vbtable, 8 non-virtual]
+ // CHECK-NEXT: 1 | extended::G::~G() [scalar deleting]
+ // CHECK-NEXT: [this adjustment: vtordisp at -4, 0 non-virtual]
- // 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]
+ // CHECK-LABEL: Thunks for 'void simple::A::f()' (1 entry).
+ // CHECK-NEXT: 0 | [this adjustment: vtordisp at -4, vbptr at 8 to the left,
+ // CHECK-NEXT: vboffset at 8 in the vbtable, 8 non-virtual]
// Emits a G's own vfptr, thus moving the vbptr in the layout.
virtual void g();
@@ -256,22 +369,28 @@ struct G : virtual simple::A {
};
G g;
+void use(G *obj) { obj->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]
+ // CHECK-LABEL: VFTable for 'Z' in 'extended::H' (2 entries).
+ // CHECK-NEXT: 0 | void Z::g()
+ // CHECK-NEXT: 1 | extended::H::~H() [scalar deleting]
+
+ // CHECK-LABEL: VFTable for 'V1' in 'simple::A' in 'extended::A' in 'extended::H' (2 entries).
+ // CHECK-NEXT: 0 | void simple::A::f()
+ // CHECK-NEXT: [this adjustment: vtordisp at -4, vbptr at 8 to the left,
+ // CHECK-NEXT: vboffset at 8 in the vbtable, 8 non-virtual]
- // 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]
+ // CHECK-LABEL: Thunks for 'void simple::A::f()' (1 entry).
+ // CHECK-NEXT: 0 | [this adjustment: vtordisp at -4, vbptr at 8 to the left,
+ // CHECK-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;
+void use(H *obj) { delete obj; }
}
namespace pr17738 {
@@ -279,10 +398,14 @@ namespace pr17738 {
// 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]
+ // CHECK-LABEL: VFTable for 'V2' in 'V3' in 'simple::B' in 'pr17738::A' (2 entries).
+ // CHECK-NEXT: 0 | void simple::B::f()
+ // CHECK-NEXT: [this adjustment: vtordisp at -12, vbptr at 20 to the left,
+ // CHECK-NEXT: vboffset at 8 in the vbtable, 16 non-virtual]
+
+ // CHECK-LABEL: Thunks for 'void simple::B::f()' (1 entry).
+ // CHECK-NEXT: 0 | [this adjustment: vtordisp at -12, vbptr at 20 to the left,
+ // CHECK-NEXT: vboffset at 8 in the vbtable, 16 non-virtual]
// MANGLING-DAG: @"\01?f@B@simple@@$R4BE@7PPPPPPPE@BA@AEXXZ"
int a;
@@ -290,6 +413,41 @@ struct A : virtual simple::B {
};
A a;
+void use(A *obj) { delete obj; }
+}
+
+namespace pr19408 {
+// In this test, the vptr used to vcall D::f() is located in the A vbase.
+// The offset of A in different in C and D, so the D vtordisp thunk should
+// adjust "this" so C::f gets the right value.
+struct A {
+ A();
+ virtual void f();
+ int a;
+};
+
+struct B : virtual A {
+ B();
+ int b;
+};
+
+struct C : B {
+ C();
+ virtual void f();
+ int c;
+};
+
+struct D : C {
+ // CHECK-LABEL: VFTable for 'pr19408::A' in 'pr19408::B' in 'pr19408::C' in 'pr19408::D' (1 entry).
+ // CHECK-NEXT: 0 | void pr19408::C::f()
+ // CHECK-NEXT: [this adjustment: vtordisp at -4, -4 non-virtual]
+
+ // MANGLING-DAG: @"\01?f@C@pr19408@@$4PPPPPPPM@3AEXXZ"
+ D();
+ int d;
+};
+
+D::D() {}
}
namespace access {
@@ -322,3 +480,90 @@ struct C : virtual B {
C c;
}
+
+namespace pr19505 {
+struct A {
+ virtual void f();
+ virtual void z();
+};
+
+struct B : A {
+ virtual void f();
+};
+
+struct C : A, B {
+ virtual void g();
+};
+
+struct X : B, virtual C {
+ X() {}
+ virtual void g();
+
+ // CHECK-LABEL: VFTable for 'pr19505::A' in 'pr19505::B' in 'pr19505::C' in 'pr19505::X' (2 entries).
+ // CHECK-NEXT: 0 | void pr19505::B::f()
+ // CHECK-NEXT: 1 | void pr19505::A::z()
+
+ // MANGLING-DAG: @"\01??_7X@pr19505@@6BB@1@@" = {{.*}}@"\01?f@B@pr19505@@UAEXXZ"
+} x;
+
+void build_vftable(X *obj) { obj->g(); }
+}
+
+namespace pr19506 {
+struct A {
+ virtual void f();
+ virtual void g();
+};
+
+struct B : A {
+ virtual void f();
+};
+
+struct C : B {};
+
+struct X : C, virtual B {
+ virtual void g();
+ X() {}
+
+ // CHECK-LABEL: VFTable for 'pr19506::A' in 'pr19506::B' in 'pr19506::X' (2 entries).
+ // CHECK-NEXT: 0 | void pr19506::B::f()
+ // CHECK-NEXT: 1 | void pr19506::X::g()
+ // CHECK-NEXT: [this adjustment: vtordisp at -4, -12 non-virtual]
+
+ // MANGLING-DAG: @"\01??_7X@pr19506@@6BB@1@@" = {{.*}}@"\01?f@B@pr19506@@UAEXXZ"
+} x;
+
+void build_vftable(X *obj) { obj->g(); }
+}
+
+namespace pr19519 {
+// VS2013 CL miscompiles this, just make sure we don't regress.
+
+struct A {
+ virtual void f();
+ virtual void g();
+};
+
+struct B : virtual A {
+ virtual void f();
+ B();
+};
+
+struct C : virtual A {
+ virtual void g();
+};
+
+struct X : B, C {
+ X();
+
+ // CHECK-LABEL: VFTable for 'pr19519::A' in 'pr19519::B' in 'pr19519::X' (2 entries).
+ // CHECK-NEXT: 0 | void pr19519::B::f()
+ // CHECK-NEXT: [this adjustment: vtordisp at -4, -4 non-virtual]
+ // CHECK-NEXT: 1 | void pr19519::C::g()
+ // CHECK-NEXT: [this adjustment: vtordisp at -4, -4 non-virtual]
+
+ // MANGLING-DAG: @"\01??_7X@pr19519@@6B@" = {{.*}}@"\01?g@C@pr19519@@$4PPPPPPPM@3AEXXZ"
+};
+
+X::X() {}
+}
diff --git a/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp b/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp
index b58a0b14cdcd..4ce4e9c2e17e 100644
--- a/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp
+++ b/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp
@@ -1,29 +1,5 @@
-// 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: %clang_cc1 -fno-rtti -emit-llvm -o %t.ll -fdump-vtable-layouts %s -triple=i386-pc-win32 >%t
+// RUN: FileCheck %s < %t
// RUN: FileCheck --check-prefix=MANGLING %s < %t.ll
struct Empty { };
@@ -38,34 +14,35 @@ struct B {
};
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()
+ // CHECK-LABEL: VFTable for 'A' in 'C' (2 entries)
+ // CHECK-NEXT: 0 | void C::f()
+ // CHECK-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()
+ // CHECK-LABEL: VFTable indices for 'C' (1 entry)
+ // CHECK-NEXT: vbtable index 1, vfptr at offset 0
+ // CHECK-NEXT: 0 | void C::f()
// MANGLING-DAG: @"\01??_7C@@6B@"
- virtual void f();
+ virtual void f() {}
};
C c;
+void use(C *obj) { obj->f(); }
struct D: virtual A {
- // VTABLE-D: VFTable for 'D' (1 entries).
- // VTABLE-D-NEXT: 0 | void D::h()
+ // CHECK-LABEL: VFTable for 'D' (1 entry).
+ // CHECK-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()
+ // CHECK-LABEL: VFTable for 'A' in 'D' (2 entries).
+ // CHECK-NEXT: 0 | void D::f()
+ // CHECK-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()
+ // CHECK-LABEL: VFTable indices for 'D' (2 entries).
+ // CHECK-NEXT: via vfptr at offset 0
+ // CHECK-NEXT: 0 | void D::h()
+ // CHECK-NEXT: via vbtable index 1, vfptr at offset 0
+ // CHECK-NEXT: 0 | void D::f()
// MANGLING-DAG: @"\01??_7D@@6B0@@"
// MANGLING-DAG: @"\01??_7D@@6BA@@@"
@@ -74,8 +51,8 @@ struct D: virtual A {
virtual void h();
};
-void D::h() {}
D d;
+void use(D *obj) { obj->h(); }
namespace Test1 {
@@ -86,33 +63,34 @@ 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()
+ Z();
+ // CHECK-LABEL: VFTable for 'A' in 'Test1::Y' in 'Test1::Z' (2 entries).
+ // CHECK-NEXT: 0 | void A::f()
+ // CHECK-NEXT: 1 | void A::z()
- // TEST1-NOT: VFTable indices for 'Test1::Z'
+ // CHECK-NOT: VFTable indices for 'Test1::Z'
// MANGLING-DAG: @"\01??_7Z@Test1@@6B@"
};
-Z z;
+Z::Z() {}
}
namespace Test2 {
struct X: virtual A, virtual B {
- // TEST2: VFTable for 'Test2::X' (1 entries).
- // TEST2-NEXT: 0 | void Test2::X::h()
+ // CHECK-LABEL: VFTable for 'Test2::X' (1 entry).
+ // CHECK-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()
+ // CHECK-LABEL: VFTable for 'A' in 'Test2::X' (2 entries).
+ // CHECK-NEXT: 0 | void A::f()
+ // CHECK-NEXT: 1 | void A::z()
- // TEST2: VFTable for 'B' in 'Test2::X' (1 entries).
- // TEST2-NEXT: 0 | void B::g()
+ // CHECK-LABEL: VFTable for 'B' in 'Test2::X' (1 entry).
+ // CHECK-NEXT: 0 | void B::g()
- // TEST2: VFTable indices for 'Test2::X' (1 entries).
- // TEST2-NEXT: 0 | void Test2::X::h()
+ // CHECK-LABEL: VFTable indices for 'Test2::X' (1 entry).
+ // CHECK-NEXT: 0 | void Test2::X::h()
// MANGLING-DAG: @"\01??_7X@Test2@@6B01@@"
// MANGLING-DAG: @"\01??_7X@Test2@@6BA@@@"
@@ -122,6 +100,7 @@ struct X: virtual A, virtual B {
};
X x;
+void use(X *obj) { obj->h(); }
}
namespace Test3 {
@@ -131,40 +110,45 @@ struct X : virtual A {
};
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()
+ Y();
+ // CHECK-LABEL: VFTable for 'A' in 'Test3::X' in 'Test3::Y' (2 entries).
+ // CHECK-NEXT: 0 | void A::f()
+ // CHECK-NEXT: 1 | void A::z()
- // TEST3-NOT: VFTable indices for 'Test3::Y'
+ // CHECK-NOT: VFTable indices for 'Test3::Y'
// MANGLING-DAG: @"\01??_7Y@Test3@@6B@"
};
-Y y;
+Y::Y() {}
}
namespace Test4 {
struct X: virtual C {
+ X();
// 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()
+ // CHECK-LABEL: VFTable for 'A' in 'C' in 'Test4::X' (2 entries).
+ // CHECK-NEXT: 0 | void C::f()
+ // CHECK-NEXT: [this adjustment: 8 non-virtual]
+ // CHECK-NEXT: 1 | void A::z()
+
+ // CHECK-LABEL: Thunks for 'void C::f()' (1 entry).
+ // CHECK-NEXT: 0 | [this adjustment: 8 non-virtual]
- // TEST4-NOT: VFTable indices for 'Test4::X'
+ // CHECK-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"
+ // MANGLING-DAG: define linkonce_odr x86_thiscallcc void @"\01?f@C@@WPPPPPPPI@AEXXZ"
};
-X x;
+X::X() {}
}
namespace Test5 {
@@ -176,16 +160,16 @@ struct X : A {
};
struct Y : virtual X {
- // TEST5: VFTable for 'Test5::Y' (1 entries).
- // TEST5-NEXT: 0 | void Test5::Y::h()
+ // CHECK-LABEL: VFTable for 'Test5::Y' (1 entry).
+ // CHECK-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()
+ // CHECK-LABEL: VFTable for 'A' in 'Test5::X' in 'Test5::Y' (3 entries).
+ // CHECK-NEXT: 0 | void A::f()
+ // CHECK-NEXT: 1 | void A::z()
+ // CHECK-NEXT: 2 | void Test5::X::g()
- // TEST5: VFTable indices for 'Test5::Y' (1 entries).
- // TEST5-NEXT: 0 | void Test5::Y::h()
+ // CHECK-LABEL: VFTable indices for 'Test5::Y' (1 entry).
+ // CHECK-NEXT: 0 | void Test5::Y::h()
// MANGLING-DAG: @"\01??_7Y@Test5@@6B01@@"
// MANGLING-DAG: @"\01??_7Y@Test5@@6BX@1@@"
@@ -194,21 +178,23 @@ struct Y : virtual X {
};
Y y;
+void use(Y *obj) { obj->h(); }
}
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()
+ X();
+ // CHECK-LABEL: VFTable for 'A' in 'Test6::X' (2 entries).
+ // CHECK-NEXT: 0 | void A::f()
+ // CHECK-NEXT: 1 | void A::z()
- // TEST6-NOT: VFTable indices for 'Test6::X'
+ // CHECK-NOT: VFTable indices for 'Test6::X'
// MANGLING-DAG: @"\01??_7X@Test6@@6B@"
};
-X x;
+X::X() {}
}
namespace Test7 {
@@ -218,36 +204,37 @@ struct X : C {
};
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()
+ Y();
+ // CHECK-LABEL: VFTable for 'A' in 'C' in 'Test7::X' in 'Test7::Y' (2 entries).
+ // CHECK-NEXT: 0 | void C::f()
+ // CHECK-NEXT: [this adjustment: 8 non-virtual]
+ // CHECK-NEXT: 1 | void A::z()
- // TEST7: Thunks for 'void C::f()' (1 entry).
- // TEST7-NEXT: 0 | [this adjustment: 8 non-virtual]
+ // CHECK-LABEL: Thunks for 'void C::f()' (1 entry).
+ // CHECK-NEXT: 0 | [this adjustment: 8 non-virtual]
- // TEST7-NOT: VFTable indices for 'Test7::Y'
+ // CHECK-NOT: VFTable indices for 'Test7::Y'
// MANGLING-DAG: @"\01??_7Y@Test7@@6B@"
};
-Y y;
+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()
+ // CHECK-LABEL: VFTable for 'D' in 'Test8::X' (1 entry).
+ // CHECK-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()
+ // CHECK-LABEL: VFTable for 'A' in 'D' in 'Test8::X' (2 entries).
+ // CHECK-NEXT: 0 | void Test8::X::f()
+ // CHECK-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()
+ // CHECK-LABEL: VFTable indices for 'Test8::X' (1 entry).
+ // CHECK-NEXT: via vbtable index 1, vfptr at offset 0
+ // CHECK-NEXT: 0 | void Test8::X::f()
// MANGLING-DAG: @"\01??_7X@Test8@@6BA@@@"
// MANGLING-DAG: @"\01??_7X@Test8@@6BD@@@"
@@ -256,21 +243,45 @@ struct X : D, C {
};
X x;
+void use(X *obj) { obj->f(); }
// 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()
+struct Z : Y, C {
+ // CHECK-LABEL: VFTable for 'A' in 'Test8::Y' in 'Test8::Z' (2 entries).
+ // CHECK-NEXT: 0 | void Test8::Z::f()
+ // CHECK-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()
+ // CHECK-LABEL: VFTable indices for 'Test8::Z' (1 entry).
+ // CHECK-NEXT: via vbtable index 1, vfptr at offset 0
+ // CHECK-NEXT: 0 | void Test8::Z::f()
virtual void f();
};
Z z;
+void use(Z *obj) { obj->f(); }
+
+// Another diamond inheritance which we miscompiled (PR18967).
+struct W : virtual A {
+ virtual void bar();
+};
+
+struct T : W, C {
+ // CHECK-LABEL: VFTable for 'Test8::W' in 'Test8::T' (1 entry)
+ // CHECK-NEXT: 0 | void Test8::T::bar()
+
+ // CHECK-LABEL: VFTable for 'A' in 'Test8::W' in 'Test8::T' (2 entries)
+ // CHECK-NEXT: 0 | void C::f()
+ // CHECK-NEXT: [this adjustment: -4 non-virtual]
+ // CHECK-NEXT: 1 | void A::z()
+
+ // CHECK-LABEL: Thunks for 'void C::f()' (1 entry).
+ // CHECK-NEXT: 0 | [this adjustment: -4 non-virtual]
+ virtual void bar();
+ int field;
+};
+T t;
+void use(T *obj) { obj->bar(); }
}
namespace Test9 {
@@ -278,15 +289,15 @@ 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()
+ // CHECK-LABEL: VFTable for 'Test9::Y' (1 entry).
+ // CHECK-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()
+ // CHECK-LABEL: VFTable for 'A' in 'Test9::X' in 'Test9::Y' (2 entries).
+ // CHECK-NEXT: 0 | void A::f()
+ // CHECK-NEXT: 1 | void A::z()
- // TEST9-Y: VFTable indices for 'Test9::Y' (1 entries).
- // TEST9-Y-NEXT: 0 | void Test9::Y::h()
+ // CHECK-LABEL: VFTable indices for 'Test9::Y' (1 entry).
+ // CHECK-NEXT: 0 | void Test9::Y::h()
// MANGLING-DAG: @"\01??_7Y@Test9@@6B01@@"
// MANGLING-DAG: @"\01??_7Y@Test9@@6BX@1@@"
@@ -295,115 +306,110 @@ struct Y : virtual X {
};
Y y;
+void use(Y *obj) { obj->h(); }
struct Z : Y, virtual B {
- // TEST9-Z: VFTable for 'Test9::Y' in 'Test9::Z' (1 entries).
- // TEST9-Z-NEXT: 0 | void Test9::Y::h()
+ Z();
+ // CHECK-LABEL: VFTable for 'Test9::Y' in 'Test9::Z' (1 entry).
+ // CHECK-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()
+ // CHECK-LABEL: VFTable for 'A' in 'Test9::X' in 'Test9::Y' in 'Test9::Z' (2 entries).
+ // CHECK-NEXT: 0 | void A::f()
+ // CHECK-NEXT: 1 | void A::z()
- // TEST9-Z: VFTable for 'B' in 'Test9::Z' (1 entries).
- // TEST9-Z-NEXT: 0 | void B::g()
+ // CHECK-LABEL: VFTable for 'B' in 'Test9::Z' (1 entry).
+ // CHECK-NEXT: 0 | void B::g()
- // TEST9-Z-NOT: VFTable indices for 'Test9::Z'
+ // CHECK-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@"
+ // MANGLING-DAG: @"\01??_7Z@Test9@@6B@"
};
-Z z;
+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()
+ W();
+ // CHECK-LABEL: VFTable for 'Test9::Y' in 'Test9::Z' in 'Test9::W' (1 entry).
+ // CHECK-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()
+ // CHECK-LABEL: VFTable for 'A' in 'Test9::X' in 'Test9::Y' in 'Test9::Z' in 'Test9::W' (2 entries).
+ // CHECK-NEXT: 0 | void A::f()
+ // CHECK-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()
+ // CHECK-LABEL: VFTable for 'B' in 'Test9::Z' in 'Test9::W' (1 entry).
+ // CHECK-NEXT: 0 | void B::g()
- // TEST9-W: VFTable for 'D' in 'Test9::W' (1 entries).
- // TEST9-W-NEXT: 0 | void D::h()
+ // CHECK-LABEL: VFTable for 'D' in 'Test9::W' (1 entry).
+ // CHECK-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()
+ // CHECK-LABEL: VFTable for 'A' in 'D' in 'Test9::W' (2 entries).
+ // CHECK-NEXT: 0 | void D::f()
+ // CHECK-NEXT: [this adjustment: -8 non-virtual]
+ // CHECK-NEXT: 1 | void A::z()
- // TEST9-W: Thunks for 'void D::f()' (1 entry).
- // TEST9-W-NEXT: 0 | [this adjustment: -8 non-virtual]
+ // CHECK-LABEL: Thunks for 'void D::f()' (1 entry).
+ // CHECK-NEXT: 0 | [this adjustment: -8 non-virtual]
- // TEST9-W-NOT: VFTable indices for 'Test9::W'
+ // CHECK-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@@"
+ // MANGLING-DAG: @"\01??_7W@Test9@@6B@"
+ // MANGLING-DAG: @"\01??_7W@Test9@@6BY@1@@"
};
-W w;
+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()
+ // CHECK-LABEL: VFTable for 'Test9::Y' in 'Test9::Z' in 'Test9::T' (1 entry).
+ // CHECK-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()
+ // CHECK-LABEL: VFTable for 'A' in 'Test9::X' in 'Test9::Y' in 'Test9::Z' in 'Test9::T' (2 entries).
+ // CHECK-NEXT: 0 | void Test9::T::f()
+ // CHECK-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()
+ // CHECK-LABEL: VFTable for 'B' in 'Test9::Z' in 'Test9::T' (1 entry).
+ // CHECK-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]
+ // CHECK-LABEL: VFTable for 'D' in 'Test9::T' (1 entry).
+ // CHECK-NEXT: 0 | void Test9::T::h()
+ // CHECK-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]
+ // CHECK-LABEL: Thunks for 'void Test9::T::h()' (1 entry).
+ // CHECK-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]
+ // CHECK-LABEL: VFTable for 'A' in 'D' in 'Test9::T' (2 entries).
+ // CHECK-NEXT: 0 | void Test9::T::f()
+ // CHECK-NEXT: [this adjustment: -8 non-virtual]
+ // CHECK-NEXT: 1 | void Test9::T::z()
+ // CHECK-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]
+ // CHECK-LABEL: Thunks for 'void Test9::T::f()' (1 entry).
+ // CHECK-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]
+ // CHECK-LABEL: Thunks for 'void Test9::T::z()' (1 entry).
+ // CHECK-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()
+ // CHECK-LABEL: VFTable indices for 'Test9::T' (4 entries).
+ // CHECK-NEXT: via vfptr at offset 0
+ // CHECK-NEXT: 0 | void Test9::T::h()
+ // CHECK-NEXT: via vbtable index 1, vfptr at offset 0
+ // CHECK-NEXT: 0 | void Test9::T::f()
+ // CHECK-NEXT: 1 | void Test9::T::z()
+ // CHECK-NEXT: via vbtable index 2, vfptr at offset 0
+ // CHECK-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@@"
+ // MANGLING-DAG: @"\01??_7T@Test9@@6B@"
+ // MANGLING-DAG: @"\01??_7T@Test9@@6BY@1@@"
virtual void f();
virtual void g();
@@ -412,22 +418,70 @@ struct T : Z, D, virtual A, virtual B {
};
T t;
+void use(T *obj) { obj->f(); }
}
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()
+ // CHECK-LABEL: VFTable for 'A' in 'C' in 'Test10::X' (2 entries).
+ // CHECK-NEXT: 0 | void Test10::X::f()
+ // CHECK-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()
+ // CHECK-LABEL: VFTable indices for 'Test10::X' (1 entry).
+ // CHECK-NEXT: via vbtable index 1, vfptr at offset 0
+ // CHECK-NEXT: 0 | void Test10::X::f()
virtual void f();
};
void X::f() {}
X x;
+void use(X *obj) { obj->f(); }
+}
+
+namespace Test11 {
+struct X : virtual A {};
+struct Y { virtual void g(); };
+
+struct Z : virtual X, Y {
+ // MANGLING-DAG: @"\01??_7Z@Test11@@6BY@1@@"
+ // MANGLING-DAG: @"\01??_7Z@Test11@@6BX@1@@"
+};
+
+Z z;
+
+struct W : virtual X, A {};
+
+// Used to crash, PR17748.
+W w;
+}
+
+namespace Test12 {
+struct X : B, A { };
+
+struct Y : X {
+ virtual void f(); // Overrides A::f.
+};
+
+struct Z : virtual Y {
+ // CHECK-LABEL: VFTable for 'A' in 'Test12::X' in 'Test12::Y' in 'Test12::Z' (2 entries).
+ // CHECK-NEXT: 0 | void Test12::Y::f()
+ // CHECK-NEXT: 1 | void A::z()
+
+ int z;
+ // MANGLING-DAG: @"\01??_7Z@Test12@@6BA@@@" = {{.*}}@"\01?f@Y@Test12@@UAEXXZ"
+};
+
+struct W : Z {
+ // CHECK-LABEL: VFTable for 'A' in 'Test12::X' in 'Test12::Y' in 'Test12::Z' in 'Test12::W' (2 entries).
+ // CHECK-NEXT: 0 | void Test12::Y::f()
+ // CHECK-NEXT: 1 | void A::z()
+ W();
+
+ int w;
+ // MANGLING-DAG: @"\01??_7W@Test12@@6BA@@@" = {{.*}}@"\01?f@Y@Test12@@UAEXXZ"
+};
+
+W::W() {}
}
namespace vdtors {
@@ -437,15 +491,16 @@ struct X {
};
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()
+ // CHECK-LABEL: VFTable for 'vdtors::X' in 'vdtors::Y' (2 entries).
+ // CHECK-NEXT: 0 | vdtors::Y::~Y() [scalar deleting]
+ // CHECK-NEXT: 1 | void vdtors::X::zzz()
- // VDTORS-Y-NOT: Thunks for 'vdtors::Y::~Y()'
+ // CHECK-NOT: Thunks for 'vdtors::Y::~Y()'
virtual ~Y();
};
Y y;
+void use(Y *obj) { delete obj; }
struct Z {
virtual void z();
@@ -456,59 +511,86 @@ struct W : Z, X {
};
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()
+ // CHECK-LABEL: VFTable for 'vdtors::Z' in 'vdtors::W' in 'vdtors::U' (1 entry).
+ // CHECK-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()
+ // CHECK-LABEL: VFTable for 'vdtors::X' in 'vdtors::W' in 'vdtors::U' (2 entries).
+ // CHECK-NEXT: 0 | vdtors::U::~U() [scalar deleting]
+ // CHECK-NEXT: [this adjustment: -4 non-virtual]
+ // CHECK-NEXT: 1 | void vdtors::X::zzz()
- // VDTORS-U: Thunks for 'vdtors::W::~W()' (1 entry).
- // VDTORS-U-NEXT: 0 | [this adjustment: -4 non-virtual]
+ // CHECK-LABEL: Thunks for 'vdtors::U::~U()' (1 entry).
+ // CHECK-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]
+ // CHECK-LABEL: VFTable indices for 'vdtors::U' (1 entry).
+ // CHECK-NEXT: -- accessible via vbtable index 1, vfptr at offset 4 --
+ // CHECK-NEXT: 0 | vdtors::U::~U() [scalar deleting]
virtual ~U();
};
U u;
+void use(U *obj) { delete obj; }
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()
+ // CHECK-LABEL: VFTable for 'vdtors::Z' in 'vdtors::W' in 'vdtors::V' (1 entry).
+ // CHECK-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()
+ // CHECK-LABEL: VFTable for 'vdtors::X' in 'vdtors::W' in 'vdtors::V' (2 entries).
+ // CHECK-NEXT: 0 | vdtors::V::~V() [scalar deleting]
+ // CHECK-NEXT: [this adjustment: -4 non-virtual]
+ // CHECK-NEXT: 1 | void vdtors::X::zzz()
- // VDTORS-V: Thunks for 'vdtors::W::~W()' (1 entry).
- // VDTORS-V-NEXT: 0 | [this adjustment: -4 non-virtual]
+ // CHECK-LABEL: Thunks for 'vdtors::V::~V()' (1 entry).
+ // CHECK-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]
+ // CHECK-LABEL: VFTable indices for 'vdtors::V' (1 entry).
+ // CHECK-NEXT: -- accessible via vbtable index 1, vfptr at offset 4 --
+ // CHECK-NEXT: 0 | vdtors::V::~V() [scalar deleting]
};
V v;
+void use(V *obj) { delete obj; }
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()
+ // CHECK-LABEL: VFTable for 'vdtors::X' in 'vdtors::T' in 'vdtors::P' (2 entries).
+ // CHECK-NEXT: 0 | vdtors::P::~P() [scalar deleting]
+ // CHECK-NEXT: 1 | void vdtors::X::zzz()
- // VDTORS-P-NOT: Thunks for 'vdtors::P::~P()'
+ // CHECK-NOT: Thunks for 'vdtors::P::~P()'
virtual ~P();
};
P p;
+void use(P *obj) { delete obj; }
+
+struct Q {
+ virtual ~Q();
+};
+
+// PR19172: Yet another diamond we miscompiled.
+struct R : virtual Q, X {
+ // CHECK-LABEL: VFTable for 'vdtors::Q' in 'vdtors::R' (1 entry).
+ // CHECK-NEXT: 0 | vdtors::R::~R() [scalar deleting]
+ // CHECK-NEXT: [this adjustment: -8 non-virtual]
+ // CHECK-LABEL: Thunks for 'vdtors::R::~R()' (1 entry).
+ // CHECK-NEXT: 0 | [this adjustment: -8 non-virtual]
+
+ // CHECK-LABEL: VFTable for 'vdtors::X' in 'vdtors::R' (2 entries).
+ // CHECK-NEXT: 0 | vdtors::R::~R() [scalar deleting]
+ // CHECK-NEXT: 1 | void vdtors::X::zzz()
+
+ // CHECK-LABEL: VFTable indices for 'vdtors::R' (1 entry).
+ // CHECK-NEXT: 0 | vdtors::R::~R() [scalar deleting]
+ virtual ~R();
+};
+
+R r;
+void use(R *obj) { delete obj; }
}
namespace return_adjustment {
@@ -526,50 +608,159 @@ struct Z {
};
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()
+ // CHECK-LABEL: VFTable for 'return_adjustment::Z' in 'return_adjustment::W' (2 entries).
+ // CHECK-NEXT: 0 | return_adjustment::X *return_adjustment::W::foo()
+ // CHECK-NEXT: [return adjustment (to type 'struct A *'): vbase #1, 0 non-virtual]
+ // CHECK-NEXT: 1 | return_adjustment::X *return_adjustment::W::foo()
+
+ // CHECK-LABEL: Thunks for 'return_adjustment::X *return_adjustment::W::foo()' (1 entry).
+ // CHECK-NEXT: 0 | [return adjustment (to type 'struct A *'): vbase #1, 0 non-virtual]
- // RET-W: VFTable indices for 'return_adjustment::W' (1 entries).
- // RET-W-NEXT: 1 | return_adjustment::X *return_adjustment::W::foo()
+ // CHECK-LABEL: VFTable indices for 'return_adjustment::W' (1 entry).
+ // CHECK-NEXT: 1 | return_adjustment::X *return_adjustment::W::foo()
virtual X* foo();
};
-W y;
+W w;
+void use(W *obj) { obj->foo(); }
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()
+ // CHECK-LABEL: VFTable for 'return_adjustment::Z' in 'return_adjustment::W' in 'return_adjustment::T' (3 entries).
+ // CHECK-NEXT: 0 | return_adjustment::Y *return_adjustment::T::foo()
+ // CHECK-NEXT: [return adjustment (to type 'struct A *'): vbase #1, 0 non-virtual]
+ // CHECK-NEXT: 1 | return_adjustment::Y *return_adjustment::T::foo()
+ // CHECK-NEXT: [return adjustment (to type 'struct return_adjustment::X *'): vbase #2, 0 non-virtual]
+ // CHECK-NEXT: 2 | return_adjustment::Y *return_adjustment::T::foo()
+
+ // CHECK-LABEL: Thunks for 'return_adjustment::Y *return_adjustment::T::foo()' (2 entries).
+ // CHECK-NEXT: 0 | [return adjustment (to type 'struct A *'): vbase #1, 0 non-virtual]
+ // CHECK-NEXT: 1 | [return adjustment (to type 'struct return_adjustment::X *'): vbase #2, 0 non-virtual]
- // RET-T: VFTable indices for 'return_adjustment::T' (1 entries).
- // RET-T-NEXT: 2 | return_adjustment::Y *return_adjustment::T::foo()
+ // CHECK-LABEL: VFTable indices for 'return_adjustment::T' (1 entry).
+ // CHECK-NEXT: 2 | return_adjustment::Y *return_adjustment::T::foo()
virtual Y* foo();
};
T t;
+void use(T *obj) { obj->foo(); }
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()
+ // CHECK-LABEL: VFTable for 'return_adjustment::Z' in 'return_adjustment::V' (2 entries).
+ // CHECK-NEXT: 0 | return_adjustment::U *return_adjustment::V::foo()
+ // CHECK-NEXT: [return adjustment (to type 'struct A *'): vbptr at offset 4, vbase #1, 0 non-virtual]
+ // CHECK-NEXT: 1 | return_adjustment::U *return_adjustment::V::foo()
+
+ // CHECK-LABEL: Thunks for 'return_adjustment::U *return_adjustment::V::foo()' (1 entry).
+ // CHECK-NEXT: 0 | [return adjustment (to type 'struct A *'): vbptr at offset 4, vbase #1, 0 non-virtual]
- // RET-V: VFTable indices for 'return_adjustment::V' (1 entries).
- // RET-V-NEXT: 1 | return_adjustment::U *return_adjustment::V::foo()
+ // CHECK-LABEL: VFTable indices for 'return_adjustment::V' (1 entry).
+ // CHECK-NEXT: 1 | return_adjustment::U *return_adjustment::V::foo()
virtual U* foo();
};
V v;
+void use(V *obj) { obj->foo(); }
+}
+
+namespace pr17748 {
+struct A {
+ virtual void f() {}
+};
+
+struct B : virtual A {
+ B() {}
+};
+
+struct C : virtual B, A {
+ C() {}
+};
+C c;
+
+// MANGLING-DAG: @"\01??_7A@pr17748@@6B@"
+// MANGLING-DAG: @"\01??_7B@pr17748@@6B@"
+// MANGLING-DAG: @"\01??_7C@pr17748@@6BA@1@@"
+// MANGLING-DAG: @"\01??_7C@pr17748@@6BB@1@@"
+}
+
+namespace pr19066 {
+struct X : virtual B {};
+
+struct Y : virtual X, B {
+ Y();
+ // CHECK-LABEL: VFTable for 'B' in 'pr19066::X' in 'pr19066::Y' (1 entry).
+ // CHECK-NEXT: 0 | void B::g()
+
+ // CHECK-LABEL: VFTable for 'B' in 'pr19066::Y' (1 entry).
+ // CHECK-NEXT: 0 | void B::g()
+};
+
+Y::Y() {}
+}
+
+namespace pr19240 {
+struct A {
+ virtual void c();
+};
+
+struct B : virtual A {
+ virtual void c();
+};
+
+struct C { };
+
+struct D : virtual A, virtual C, B {};
+
+D obj;
+
+// Each MDC only has one vftable.
+
+// MANGLING-DAG: @"\01??_7D@pr19240@@6B@"
+// MANGLING-DAG: @"\01??_7A@pr19240@@6B@"
+// MANGLING-DAG: @"\01??_7B@pr19240@@6B@"
+
+}
+
+namespace pr19408 {
+// This test is a non-vtordisp version of the reproducer for PR19408.
+struct X : virtual A {
+ int x;
+};
+
+struct Y : X {
+ virtual void f();
+ int y;
+};
+
+struct Z : Y {
+ // CHECK-LABEL: VFTable for 'A' in 'pr19408::X' in 'pr19408::Y' in 'pr19408::Z' (2 entries).
+ // CHECK-NEXT: 0 | void pr19408::Y::f()
+ // CHECK-NEXT: [this adjustment: -4 non-virtual]
+ // CHECK-NEXT: 1 | void A::z()
+
+ Z();
+ int z;
+ // MANGLING-DAG: @"\01??_7Z@pr19408@@6B@" = {{.*}}@"\01?f@Y@pr19408@@W3AEXXZ"
+};
+
+Z::Z() {}
+
+struct W : B, Y {
+ // CHECK-LABEL: VFTable for 'A' in 'pr19408::X' in 'pr19408::Y' in 'pr19408::W' (2 entries).
+ // CHECK-NEXT: 0 | void pr19408::Y::f()
+ // CHECK-NEXT: [this adjustment: -4 non-virtual]
+ // CHECK-NEXT: 1 | void A::z()
+
+ W();
+ int w;
+ // MANGLING-DAG: @"\01??_7W@pr19408@@6BY@1@@" = {{.*}}@"\01?f@Y@pr19408@@W3AEXXZ"
+};
+
+W::W() {}
}
diff --git a/test/CodeGenCXX/microsoft-compatibility.cpp b/test/CodeGenCXX/microsoft-compatibility.cpp
new file mode 100644
index 000000000000..297184a1df2a
--- /dev/null
+++ b/test/CodeGenCXX/microsoft-compatibility.cpp
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 %s -triple i686-pc-win32 -std=c++11 -fms-compatibility -emit-llvm -o - | FileCheck %s
+
+template<class T>
+void destroy(T *p) {
+ p->~T();
+}
+
+extern "C" void f() {
+ int a;
+ destroy((void*)&a);
+}
+
+// CHECK-LABEL: define void @f()
+// CHECK: call void @"\01??$destroy@X@@YAXPAX@Z"
+// CHECK: ret void
+
+// CHECK-LABEL: define linkonce_odr void @"\01??$destroy@X@@YAXPAX@Z"(i8* %p)
+// The pseudo-dtor expr should not generate calls to anything.
+// CHECK-NOT: call
+// CHECK-NOT: invoke
+// CHECK: ret void
diff --git a/test/CodeGenCXX/microsoft-interface.cpp b/test/CodeGenCXX/microsoft-interface.cpp
index 419075a86303..c030d1d0b3b5 100644
--- a/test/CodeGenCXX/microsoft-interface.cpp
+++ b/test/CodeGenCXX/microsoft-interface.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -std=c++11 -fms-extensions -Wno-microsoft -triple=i386-pc-win32 -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -std=c++11 -fms-extensions -Wno-microsoft -triple=i386-pc-windows-gnu -emit-llvm %s -o - | FileCheck %s
__interface I {
int test() {
@@ -20,24 +20,21 @@ 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-LABEL: define i32 @_Z2fnv()
-// CHECK: call void @_ZN1SC1Ev(%struct.S* %s)
-// CHECK: %{{[.0-9A-Z_a-z]+}} = call i32 @_ZN1S4testEv(%struct.S* %s)
+// CHECK: call x86_thiscallcc void @_ZN1SC1Ev(%struct.S* %s)
+// CHECK: %{{[.0-9A-Z_a-z]+}} = call x86_thiscallcc i32 @_ZN1S4testEv(%struct.S* %s)
-// CHECK-LABEL: define linkonce_odr void @_ZN1SC1Ev(%struct.S* %this)
-// CHECK: call void @_ZN1SC2Ev(%struct.S* %{{[.0-9A-Z_a-z]+}})
+// CHECK-LABEL: define linkonce_odr x86_thiscallcc void @_ZN1SC1Ev(%struct.S* %this)
+// CHECK: call x86_thiscallcc void @_ZN1SC2Ev(%struct.S* %{{[.0-9A-Z_a-z]+}})
-// 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-LABEL: define linkonce_odr x86_thiscallcc i32 @_ZN1S4testEv(%struct.S* %this)
+// CHECK: %{{[.0-9A-Z_a-z]+}} = call x86_thiscallcc i32 @_ZN1I4testEv(%__interface.I* %{{[.0-9A-Z_a-z]+}})
-// CHECK-LABEL: define linkonce_odr i32 @_ZN1I4testEv(%__interface.I* %this)
+// CHECK-LABEL: define linkonce_odr x86_thiscallcc i32 @_ZN1I4testEv(%__interface.I* %this)
// CHECK: ret i32 1
-// CHECK-LABEL: define linkonce_odr void @_ZN1SC2Ev(%struct.S* %this)
-// CHECK: call void @_ZN1IC2Ev(%__interface.I* %{{[.0-9A-Z_a-z]+}})
+// CHECK-LABEL: define linkonce_odr x86_thiscallcc void @_ZN1SC2Ev(%struct.S* %this)
+// CHECK: call x86_thiscallcc 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-LABEL: define linkonce_odr void @_ZN1IC2Ev(%__interface.I* %this)
+// CHECK-LABEL: define linkonce_odr x86_thiscallcc 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-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
index 48e93d4aa0f8..7857e478ef82 100644
--- a/test/CodeGenCXX/microsoft-new.cpp
+++ b/test/CodeGenCXX/microsoft-new.cpp
@@ -1,39 +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*
- }
-}
+// 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* @"\01??2@YAPAXIUarbitrary_t@@@Z"(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* @"\01??_US@PR13164@@SAPAXIUarbitrary_t@@@Z"(i32 2, %struct.arbitrary_t*
+ S *s1 = new(arbitrary) S;
+ // CHECK: call i8* @"\01??2@YAPAXIUarbitrary_t@@@Z"(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* @"\01??_U@YAPAXIUarbitrary2_t@@@Z"(i32 2, %struct.arbitrary2_t*
+ }
+}
diff --git a/test/CodeGenCXX/microsoft-no-rtti-data.cpp b/test/CodeGenCXX/microsoft-no-rtti-data.cpp
new file mode 100644
index 000000000000..d4002c28b1a2
--- /dev/null
+++ b/test/CodeGenCXX/microsoft-no-rtti-data.cpp
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 %s -fno-rtti-data -triple=i386-pc-win32 -o - -emit-llvm | FileCheck %s
+
+// vftable shouldn't have RTTI data in it.
+// CHECK: @"\01??_7S@@6B@" = linkonce_odr unnamed_addr constant [1 x i8*] [i8* bitcast ({{.*}} @"\01??_GS@@UAEPAXI@Z" to i8*)]
+
+struct type_info;
+namespace std { using ::type_info; }
+
+struct S {
+ virtual ~S();
+} s;
+
+struct U : S {
+ virtual ~U();
+};
+
+extern S *getS();
+
+const std::type_info &ti = typeid(*getS());
+const U &u = dynamic_cast<U &>(*getS());
+// CHECK: call i8* @__RTDynamicCast(i8* %{{.+}}, i32 0, i8* bitcast ({{.*}} @"\01??_R0?AUS@@@8" to i8*), i8* bitcast ({{.*}} @"\01??_R0?AUU@@@8" to i8*), i32 1)
diff --git a/test/CodeGenCXX/microsoft-templ-uuidof.cpp b/test/CodeGenCXX/microsoft-templ-uuidof.cpp
new file mode 100644
index 000000000000..0ee390863837
--- /dev/null
+++ b/test/CodeGenCXX/microsoft-templ-uuidof.cpp
@@ -0,0 +1,37 @@
+// RUN: %clang_cc1 -emit-llvm %s -o - -DDEFINE_GUID -triple=i386-pc-win32 -fms-extensions | FileCheck %s --check-prefix=CHECK
+
+struct _GUID;
+
+template <typename>
+struct X {
+};
+
+struct __declspec(uuid("{AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA}")) A {};
+
+struct B {};
+
+template <>
+struct __declspec(uuid("{BBBBBBBB-BBBB-BBBB-BBBB-BBBBBBBBBBBB}")) X<B> {};
+
+struct __declspec(uuid("{CCCCCCCC-CCCC-CCCC-CCCC-CCCCCCCCCCCC}")) C {};
+
+const _GUID &xa = __uuidof(X<A>);
+// CHECK-DAG: @"\01?xa@@3ABU_GUID@@B" = {{.*}} @_GUID_aaaaaaaa_aaaa_aaaa_aaaa_aaaaaaaaaaaa
+
+const _GUID &xb = __uuidof(X<B>);
+// CHECK-DAG: @"\01?xb@@3ABU_GUID@@B" = {{.*}} @_GUID_bbbbbbbb_bbbb_bbbb_bbbb_bbbbbbbbbbbb
+const _GUID &xc = __uuidof(X<C>);
+// CHECK-DAG: @"\01?xc@@3ABU_GUID@@B" = {{.*}} @_GUID_cccccccc_cccc_cccc_cccc_cccccccccccc
+
+template <>
+struct __declspec(uuid("{DDDDDDDD-DDDD-DDDD-DDDD-DDDDDDDDDDDD}")) X<C> {};
+
+template <typename>
+struct __declspec(uuid("{EEEEEEEE-EEEE-EEEE-EEEE-EEEEEEEEEEEE}")) Y {
+};
+
+const _GUID &xd = __uuidof(X<C>);
+// CHECK-DAG: @"\01?xd@@3ABU_GUID@@B" = {{.*}} @_GUID_dddddddd_dddd_dddd_dddd_dddddddddddd
+
+const _GUID &yd = __uuidof(Y<X<C> >);
+// CHECK-DAG: @"\01?yd@@3ABU_GUID@@B" = {{.*}} @_GUID_dddddddd_dddd_dddd_dddd_dddddddddddd
diff --git a/test/CodeGenCXX/microsoft-uuidof.cpp b/test/CodeGenCXX/microsoft-uuidof.cpp
index ab3d9b64c6f8..d57ca8380e39 100644
--- a/test/CodeGenCXX/microsoft-uuidof.cpp
+++ b/test/CodeGenCXX/microsoft-uuidof.cpp
@@ -1,6 +1,6 @@
-// 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
+// RUN: %clang_cc1 -emit-llvm %s -o - -DDEFINE_GUID -triple=i386-pc-linux -fms-extensions | FileCheck %s --check-prefix=CHECK-DEFINE-GUID
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-linux -fms-extensions | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm %s -o - -DDEFINE_GUID -DWRONG_GUID -triple=i386-pc-linux -fms-extensions | FileCheck %s --check-prefix=CHECK-DEFINE-WRONG-GUID
#ifdef DEFINE_GUID
struct _GUID {
diff --git a/test/CodeGenCXX/mingw-new-abi.cpp b/test/CodeGenCXX/mingw-new-abi.cpp
new file mode 100644
index 000000000000..2b05253b0985
--- /dev/null
+++ b/test/CodeGenCXX/mingw-new-abi.cpp
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -emit-llvm -triple i386-pc-mingw32 %s -o - | FileCheck --check-prefix=MINGW %s
+// RUN: %clang_cc1 -emit-llvm -triple i386-pc-cygwin %s -o - | FileCheck --check-prefix=CYGWIN %s
+
+namespace test1 {
+ struct foo {
+ // MINGW: declare x86_thiscallcc void @_ZN5test13foo1fEv
+ // CYGWIN: declare void @_ZN5test13foo1fEv
+ void f();
+ };
+ void g(foo *x) {
+ x->f();
+ }
+}
diff --git a/test/CodeGenCXX/mips-size_t-ptrdiff_t.cpp b/test/CodeGenCXX/mips-size_t-ptrdiff_t.cpp
new file mode 100644
index 000000000000..92e704a0a309
--- /dev/null
+++ b/test/CodeGenCXX/mips-size_t-ptrdiff_t.cpp
@@ -0,0 +1,49 @@
+// RUN: %clang_cc1 -x c++ -emit-llvm -triple=mips-unknown-linux-gnu < %s | FileCheck --check-prefix=O32 %s
+// RUN: %clang_cc1 -x c++ -emit-llvm -triple=mips64-unknown-linux-gnu -target-abi n32 < %s | FileCheck --check-prefix=N32 %s
+// RUN: %clang_cc1 -x c++ -emit-llvm -triple=mips64-unknown-linux-gnu -target-abi n64 < %s | FileCheck --check-prefix=N64 %s
+
+// Test that the size_t is correct for the ABI. It's not sufficient to be the
+// correct size, it must be the same type for correct name mangling.
+
+long *alloc_long() {
+ long *rv = new long; // size_t is implicit in the new operator
+ return rv;
+}
+// O32-LABEL: define i32* @_Z10alloc_longv()
+// O32: call noalias i8* @_Znwj(i32 4)
+
+// N32-LABEL: define i32* @_Z10alloc_longv()
+// N32: call noalias i8* @_Znwj(i32 4)
+
+// N64-LABEL: define i64* @_Z10alloc_longv()
+// N64: call noalias i8* @_Znwm(i64 8)
+
+long *alloc_long_array() {
+ long *rv = new long[2];
+ return rv;
+}
+
+// O32-LABEL: define i32* @_Z16alloc_long_arrayv()
+// O32: call noalias i8* @_Znaj(i32 8)
+
+// N32-LABEL: define i32* @_Z16alloc_long_arrayv()
+// N32: call noalias i8* @_Znaj(i32 8)
+
+// N64-LABEL: define i64* @_Z16alloc_long_arrayv()
+// N64: call noalias i8* @_Znam(i64 16)
+
+#include <stddef.h>
+
+void size_t_arg(size_t a) {
+}
+
+// O32-LABEL: _Z10size_t_argj
+// N32-LABEL: _Z10size_t_argj
+// N64-LABEL: _Z10size_t_argm
+
+void ptrdiff_t_arg(ptrdiff_t a) {
+}
+
+// O32-LABEL: _Z13ptrdiff_t_argi
+// N32-LABEL: _Z13ptrdiff_t_argi
+// N64-LABEL: _Z13ptrdiff_t_argl
diff --git a/test/CodeGenCXX/ms-integer-static-data-members-exported.cpp b/test/CodeGenCXX/ms-integer-static-data-members-exported.cpp
new file mode 100644
index 000000000000..3f868f36ff66
--- /dev/null
+++ b/test/CodeGenCXX/ms-integer-static-data-members-exported.cpp
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 -emit-llvm -triple=i386-pc-win32 -fms-compatibility %s -o - | FileCheck %s
+
+enum Enum { zero, one, two };
+
+struct __declspec(dllexport) S {
+ // In MS compatibility mode, this counts as a definition.
+ // Since it is exported, it must be emitted even if it's unreferenced.
+ static const short x = 42;
+
+ // This works for enums too.
+ static const Enum y = two;
+
+ struct NonExported {
+ // dllexport is not inherited by this nested class.
+ // Since z is not referenced, it should not be emitted.
+ static const int z = 42;
+ };
+};
+
+// CHECK: @"\01?x@S@@2FB" = weak_odr dllexport constant i16 42, align 2
+// CHECK: @"\01?y@S@@2W4Enum@@B" = weak_odr dllexport constant i32 2, align 4
+// CHECK-NOT: NonExported
diff --git a/test/CodeGenCXX/ms-integer-static-data-members.cpp b/test/CodeGenCXX/ms-integer-static-data-members.cpp
index 00beaa62f190..b02b679d71a1 100644
--- a/test/CodeGenCXX/ms-integer-static-data-members.cpp
+++ b/test/CodeGenCXX/ms-integer-static-data-members.cpp
@@ -1,7 +1,7 @@
-// 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
+// RUN: %clang_cc1 -emit-llvm -triple=i386-pc-win32 -fms-compatibility %s -o - | FileCheck %s
+// RUN: %clang_cc1 -DINLINE_INIT -emit-llvm -triple=i386-pc-win32 -fms-compatibility %s -o - | FileCheck %s --check-prefix=CHECK-INLINE
+// RUN: %clang_cc1 -DREAL_DEFINITION -emit-llvm -triple=i386-pc-win32 -fms-compatibility %s -o - | FileCheck %s --check-prefix=CHECK-OUTOFLINE
+// RUN: %clang_cc1 -DINLINE_INIT -DREAL_DEFINITION -emit-llvm -triple=i386-pc-win32 -fms-compatibility %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.
diff --git a/test/CodeGenCXX/ms_wide_predefined_expr.cpp b/test/CodeGenCXX/ms_wide_predefined_expr.cpp
index 5f0bcdee8c05..3949d39ad52f 100644
--- a/test/CodeGenCXX/ms_wide_predefined_expr.cpp
+++ b/test/CodeGenCXX/ms_wide_predefined_expr.cpp
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 %s -fms-extensions -triple i686-pc-win32 -emit-llvm -o - | FileCheck %s
-// CHECK: @L__FUNCTION__._Z4funcv = private constant [5 x i16] [i16 102, i16 117, i16 110, i16 99, i16 0], align 2
+// CHECK: @"\01??_C@_19DPFBEKIN@?$AAf?$AAu?$AAn?$AAc?$AA?$AA@" = linkonce_odr unnamed_addr constant [5 x i16] [i16 102, i16 117, i16 110, i16 99, i16 0], align 2
void wprint(const wchar_t*);
diff --git a/test/CodeGenCXX/new-array-init.cpp b/test/CodeGenCXX/new-array-init.cpp
index 0e925c0a67eb..65123ea7feef 100644
--- a/test/CodeGenCXX/new-array-init.cpp
+++ b/test/CodeGenCXX/new-array-init.cpp
@@ -6,8 +6,8 @@ void fn(int n) {
// CHECK: store i32 1
// CHECK: store i32 2
// CHECK: store i32 3
- // CHECK: icmp eq i32*
- // CHECK-NEXT: br i1
+ // CHECK: sub {{.*}}, 12
+ // CHECK: call void @llvm.memset
new int[n] { 1, 2, 3 };
}
@@ -31,3 +31,18 @@ void const_sufficient() {
new int[4] { 1, 2, 3 };
// CHECK: ret void
}
+
+// CHECK-LABEL: define void @_Z22check_array_value_initv
+void check_array_value_init() {
+ struct S;
+ new (int S::*[3][4][5]) ();
+
+ // CHECK: call noalias i8* @_Zna{{.}}(i{{32 240|64 480}})
+ // CHECK: getelementptr inbounds i{{32|64}}* {{.*}}, i{{32|64}} 60
+
+ // CHECK: phi
+ // CHECK: store i{{32|64}} -1,
+ // CHECK: getelementptr inbounds i{{32|64}}* {{.*}}, i{{32|64}} 1
+ // CHECK: icmp eq
+ // CHECK: br i1
+}
diff --git a/test/CodeGenCXX/new.cpp b/test/CodeGenCXX/new.cpp
index 91da77a0838a..862161b19385 100644
--- a/test/CodeGenCXX/new.cpp
+++ b/test/CodeGenCXX/new.cpp
@@ -2,6 +2,9 @@
typedef __typeof__(sizeof(0)) size_t;
+// Declare an 'operator new' template to tickle a bug in __builtin_operator_new.
+template<typename T> void *operator new(size_t, int (*)(T));
+
// Ensure that this declaration doesn't cause operator new to lose its
// 'noalias' attribute.
void *operator new[](size_t);
@@ -33,7 +36,6 @@ 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;
}
@@ -285,7 +287,7 @@ void *operator new(size_t, MyPlacementType);
namespace N3664 {
struct S { S() throw(int); };
- // CHECK-LABEL-LABEL: define void @_ZN5N36641fEv
+ // CHECK-LABEL: define void @_ZN5N36641fEv
void f() {
// CHECK: call noalias i8* @_Znwm(i64 4) [[ATTR_BUILTIN_NEW:#[^ ]*]]
int *p = new int;
@@ -307,7 +309,7 @@ namespace N3664 {
// FIXME: Can we mark this noalias?
// CHECK: declare i8* @_ZnamRKSt9nothrow_t(i64, {{.*}}) [[ATTR_NOBUILTIN_NOUNWIND]]
- // CHECK-LABEL-LABEL: define void @_ZN5N36641gEv
+ // CHECK-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.
@@ -326,6 +328,15 @@ namespace N3664 {
}
}
+namespace builtins {
+ // CHECK-LABEL: define void @_ZN8builtins1fEv
+ void f() {
+ // CHECK: call noalias i8* @_Znwm(i64 4) [[ATTR_BUILTIN_NEW]]
+ // CHECK: call void @_ZdlPv({{.*}}) [[ATTR_BUILTIN_DELETE]]
+ __builtin_operator_delete(__builtin_operator_new(4));
+ }
+}
+
// CHECK-DAG: attributes [[ATTR_NOBUILTIN]] = {{[{].*}} nobuiltin {{.*[}]}}
// CHECK-DAG: attributes [[ATTR_NOBUILTIN_NOUNWIND]] = {{[{].*}} nobuiltin nounwind {{.*[}]}}
diff --git a/test/CodeGenCXX/no-elide-constructors.cpp b/test/CodeGenCXX/no-elide-constructors.cpp
new file mode 100644
index 000000000000..ecb350f43ec9
--- /dev/null
+++ b/test/CodeGenCXX/no-elide-constructors.cpp
@@ -0,0 +1,35 @@
+// RUN: %clang_cc1 -std=c++98 -triple i386-unknown-unknown -fno-elide-constructors -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-CXX98
+// RUN: %clang_cc1 -std=c++11 -triple i386-unknown-unknown -fno-elide-constructors -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-CXX11
+// RUN: %clang_cc1 -std=c++98 -triple i386-unknown-unknown -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-CXX98-ELIDE
+// RUN: %clang_cc1 -std=c++11 -triple i386-unknown-unknown -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-CXX11-ELIDE
+
+// Reduced from PR12208
+class X {
+public:
+ X();
+ X(const X&);
+#if __cplusplus >= 201103L
+ X(X&&);
+#endif
+ ~X();
+};
+
+// CHECK-LABEL: define void @_Z4Testv(
+X Test()
+{
+ X x;
+
+ // Check that the copy constructor for X is called with result variable as
+ // sret argument.
+ // CHECK-CXX98: call void @_ZN1XC1ERKS_(
+ // CHECK-CXX11: call void @_ZN1XC1EOS_(
+ // CHECK-CXX98-ELIDE-NOT: call void @_ZN1XC1ERKS_(
+ // CHECK-CXX11-ELIDE-NOT: call void @_ZN1XC1EOS_(
+
+ // Make sure that the destructor for X is called.
+ // FIXME: This call is present even in the -ELIDE runs, but is guarded by a
+ // branch that is never taken in those cases. We could generate better IR
+ // here.
+ // CHECK: call void @_ZN1XD1Ev(
+ return x;
+}
diff --git a/test/CodeGenCXX/noinline-template.cpp b/test/CodeGenCXX/noinline-template.cpp
index 51a84f74a650..3dd4366f73e3 100644
--- a/test/CodeGenCXX/noinline-template.cpp
+++ b/test/CodeGenCXX/noinline-template.cpp
@@ -1,9 +1,9 @@
-// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -emit-llvm -triple %itanium_abi_triple -o - | FileCheck %s
// This was a problem in Sema, but only shows up as noinline missing
// in CodeGen.
-// CHECK: define linkonce_odr void @_ZN6VectorIiE13growStorageByEv(%struct.Vector* %this) [[NI:#[0-9]+]]
+// CHECK: define linkonce_odr {{.*}}void @_ZN6VectorIiE13growStorageByEv(%struct.Vector* %this) [[NI:#[0-9]+]]
template <class Ty> struct Vector {
void growStorageBy();
diff --git a/test/CodeGenCXX/nrvo.cpp b/test/CodeGenCXX/nrvo.cpp
index b83dd727e0bb..aad287dc3206 100644
--- a/test/CodeGenCXX/nrvo.cpp
+++ b/test/CodeGenCXX/nrvo.cpp
@@ -9,6 +9,14 @@ public:
~X();
};
+template<typename T> struct Y {
+ Y();
+ static Y f() {
+ Y y;
+ return y;
+ }
+};
+
// CHECK-LABEL: define void @_Z5test0v
// CHECK-EH-LABEL: define void @_Z5test0v
X test0() {
@@ -108,12 +116,17 @@ X test2(bool B) {
}
+// CHECK-LABEL: define void @_Z5test3b
X test3(bool B) {
- // FIXME: We don't manage to apply NRVO here, although we could.
- {
+ // CHECK: tail call {{.*}} @_ZN1XC1Ev
+ // CHECK-NOT: call {{.*}} @_ZN1XC1ERKS_
+ // CHECK: call {{.*}} @_ZN1XC1Ev
+ // CHECK: call {{.*}} @_ZN1XC1ERKS_
+ if (B) {
X y;
return y;
}
+ // FIXME: we should NRVO this variable too.
X x;
return x;
}
@@ -156,9 +169,40 @@ X test6() {
return a;
// CHECK: [[A:%.*]] = alloca [[X:%.*]], align 8
// CHECK-NEXT: call {{.*}} @_ZN1XC1Ev([[X]]* [[A]])
- // CHECK-NEXT: call {{.*}} @_ZN1XC1ERKS_([[X]]* {{%.*}}, [[X]]* [[A]])
+ // CHECK-NEXT: call {{.*}} @_ZN1XC1ERKS_([[X]]* {{%.*}}, [[X]]* dereferenceable({{[0-9]+}}) [[A]])
// CHECK-NEXT: call {{.*}} @_ZN1XD1Ev([[X]]* [[A]])
// CHECK-NEXT: ret void
}
+// CHECK-LABEL: define void @_Z5test7b
+X test7(bool b) {
+ // CHECK: tail call {{.*}} @_ZN1XC1Ev
+ // CHECK-NEXT: ret
+ if (b) {
+ X x;
+ return x;
+ }
+ return X();
+}
+
+// CHECK-LABEL: define void @_Z5test8b
+X test8(bool b) {
+ // CHECK: tail call {{.*}} @_ZN1XC1Ev
+ // CHECK-NEXT: ret
+ if (b) {
+ X x;
+ return x;
+ } else {
+ X y;
+ return y;
+ }
+}
+
+Y<int> test9() {
+ Y<int>::f();
+}
+
+// CHECK-LABEL: define linkonce_odr void @_ZN1YIiE1fEv
+// CHECK: tail call {{.*}} @_ZN1YIiEC1Ev
+
// CHECK-EH: attributes [[NR_NUW]] = { noreturn nounwind }
diff --git a/test/CodeGenCXX/pod-member-memcpys.cpp b/test/CodeGenCXX/pod-member-memcpys.cpp
index 5c79568c2ace..31d774c5345e 100644
--- a/test/CodeGenCXX/pod-member-memcpys.cpp
+++ b/test/CodeGenCXX/pod-member-memcpys.cpp
@@ -108,59 +108,59 @@ CALL_AO(InnerClassMember)
CALL_AO(PackedMembers)
// Basic copy-assignment:
-// CHECK-LABEL: define linkonce_odr %struct.Basic* @_ZN5BasicaSERKS_(%struct.Basic* %this, %struct.Basic*)
+// CHECK-LABEL: define linkonce_odr dereferenceable({{[0-9]+}}) %struct.Basic* @_ZN5BasicaSERKS_(%struct.Basic* %this, %struct.Basic* dereferenceable({{[0-9]+}}))
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}})
-// CHECK: call %struct.NonPOD* @_ZN6NonPODaSERKS_
+// CHECK: call dereferenceable({{[0-9]+}}) %struct.NonPOD* @_ZN6NonPODaSERKS_
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}})
// CHECK: ret %struct.Basic*
// PODMember copy-assignment:
-// CHECK-LABEL: define linkonce_odr %struct.PODMember* @_ZN9PODMemberaSERKS_(%struct.PODMember* %this, %struct.PODMember*)
+// CHECK-LABEL: define linkonce_odr dereferenceable({{[0-9]+}}) %struct.PODMember* @_ZN9PODMemberaSERKS_(%struct.PODMember* %this, %struct.PODMember* dereferenceable({{[0-9]+}}))
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 32, i32 4{{.*}})
-// CHECK: call %struct.NonPOD* @_ZN6NonPODaSERKS_
+// CHECK: call dereferenceable({{[0-9]+}}) %struct.NonPOD* @_ZN6NonPODaSERKS_
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}})
// CHECK: ret %struct.PODMember*
// PODLikeMember copy-assignment:
-// CHECK-LABEL: define linkonce_odr %struct.PODLikeMember* @_ZN13PODLikeMemberaSERKS_(%struct.PODLikeMember* %this, %struct.PODLikeMember*)
+// CHECK-LABEL: define linkonce_odr dereferenceable({{[0-9]+}}) %struct.PODLikeMember* @_ZN13PODLikeMemberaSERKS_(%struct.PODLikeMember* %this, %struct.PODLikeMember* dereferenceable({{[0-9]+}}))
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 32, i32 4{{.*}})
-// CHECK: call %struct.NonPOD* @_ZN6NonPODaSERKS_
+// CHECK: call dereferenceable({{[0-9]+}}) %struct.NonPOD* @_ZN6NonPODaSERKS_
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}})
// CHECK: ret %struct.PODLikeMember*
// ArrayMember copy-assignment:
-// CHECK-LABEL: define linkonce_odr %struct.ArrayMember* @_ZN11ArrayMemberaSERKS_(%struct.ArrayMember* %this, %struct.ArrayMember*)
+// CHECK-LABEL: define linkonce_odr dereferenceable({{[0-9]+}}) %struct.ArrayMember* @_ZN11ArrayMemberaSERKS_(%struct.ArrayMember* %this, %struct.ArrayMember* dereferenceable({{[0-9]+}}))
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 64, i32 4{{.*}})
-// CHECK: call %struct.NonPOD* @_ZN6NonPODaSERKS_
+// CHECK: call dereferenceable({{[0-9]+}}) %struct.NonPOD* @_ZN6NonPODaSERKS_
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 64, i32 4{{.*}})
// CHECK: ret %struct.ArrayMember*
// VolatileMember copy-assignment:
-// CHECK-LABEL: define linkonce_odr %struct.VolatileMember* @_ZN14VolatileMemberaSERKS_(%struct.VolatileMember* %this, %struct.VolatileMember*)
+// CHECK-LABEL: define linkonce_odr dereferenceable({{[0-9]+}}) %struct.VolatileMember* @_ZN14VolatileMemberaSERKS_(%struct.VolatileMember* %this, %struct.VolatileMember* dereferenceable({{[0-9]+}}))
// 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: call %struct.NonPOD* @_ZN6NonPODaSERKS_
+// CHECK: call dereferenceable({{[0-9]+}}) %struct.NonPOD* @_ZN6NonPODaSERKS_
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}})
// CHECK: ret %struct.VolatileMember*
// BitfieldMember copy-assignment:
-// CHECK-LABEL: define linkonce_odr %struct.BitfieldMember* @_ZN14BitfieldMemberaSERKS_(%struct.BitfieldMember* %this, %struct.BitfieldMember*)
+// CHECK-LABEL: define linkonce_odr dereferenceable({{[0-9]+}}) %struct.BitfieldMember* @_ZN14BitfieldMemberaSERKS_(%struct.BitfieldMember* %this, %struct.BitfieldMember* dereferenceable({{[0-9]+}}))
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}})
-// CHECK: call %struct.NonPOD* @_ZN6NonPODaSERKS_
+// CHECK: call dereferenceable({{[0-9]+}}) %struct.NonPOD* @_ZN6NonPODaSERKS_
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 3, i32 1{{.*}})
// CHECK: ret %struct.BitfieldMember*
// InnerClass copy-assignment:
-// CHECK-LABEL: define linkonce_odr %struct.InnerClassMember* @_ZN16InnerClassMemberaSERKS_(%struct.InnerClassMember* %this, %struct.InnerClassMember*)
+// CHECK-LABEL: define linkonce_odr dereferenceable({{[0-9]+}}) %struct.InnerClassMember* @_ZN16InnerClassMemberaSERKS_(%struct.InnerClassMember* %this, %struct.InnerClassMember* dereferenceable({{[0-9]+}}))
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 32, i32 4{{.*}})
-// CHECK: call %struct.NonPOD* @_ZN6NonPODaSERKS_
+// CHECK: call dereferenceable({{[0-9]+}}) %struct.NonPOD* @_ZN6NonPODaSERKS_
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}})
// CHECK: ret %struct.InnerClassMember*
// PackedMembers copy-assignment:
-// CHECK-LABEL: define linkonce_odr %struct.PackedMembers* @_ZN13PackedMembersaSERKS_(%struct.PackedMembers* %this, %struct.PackedMembers*)
-// CHECK: call %struct.NonPOD* @_ZN6NonPODaSERKS_
+// CHECK-LABEL: define linkonce_odr dereferenceable({{[0-9]+}}) %struct.PackedMembers* @_ZN13PackedMembersaSERKS_(%struct.PackedMembers* %this, %struct.PackedMembers* dereferenceable({{[0-9]+}}))
+// CHECK: call dereferenceable({{[0-9]+}}) %struct.NonPOD* @_ZN6NonPODaSERKS_
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 1{{.*}})
// CHECK: ret %struct.PackedMembers*
@@ -184,21 +184,21 @@ CALL_CC(PODMember)
CALL_CC(Basic)
// Basic copy-constructor:
-// CHECK-LABEL: define linkonce_odr void @_ZN5BasicC2ERKS_(%struct.Basic* %this, %struct.Basic*)
+// CHECK-LABEL: define linkonce_odr void @_ZN5BasicC2ERKS_(%struct.Basic* %this, %struct.Basic* dereferenceable({{[0-9]+}}))
// 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-LABEL: define linkonce_odr void @_ZN9PODMemberC2ERKS_(%struct.PODMember* %this, %struct.PODMember*)
+// CHECK-LABEL: define linkonce_odr void @_ZN9PODMemberC2ERKS_(%struct.PODMember* %this, %struct.PODMember* dereferenceable({{[0-9]+}}))
// 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-LABEL: define linkonce_odr void @_ZN13PODLikeMemberC2ERKS_(%struct.PODLikeMember* %this, %struct.PODLikeMember*)
+// CHECK-LABEL: define linkonce_odr void @_ZN13PODLikeMemberC2ERKS_(%struct.PODLikeMember* %this, %struct.PODLikeMember* dereferenceable({{[0-9]+}}))
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 32, i32 4{{.*}})
// CHECK: invoke void @_ZN6NonPODC1ERKS_
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}})
@@ -207,14 +207,14 @@ CALL_CC(Basic)
// CHECK: invoke void @_ZN7PODLikeD1Ev
// ArrayMember copy-constructor:
-// CHECK-LABEL: define linkonce_odr void @_ZN11ArrayMemberC2ERKS_(%struct.ArrayMember* %this, %struct.ArrayMember*)
+// CHECK-LABEL: define linkonce_odr void @_ZN11ArrayMemberC2ERKS_(%struct.ArrayMember* %this, %struct.ArrayMember* dereferenceable({{[0-9]+}}))
// 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-LABEL: define linkonce_odr void @_ZN14VolatileMemberC2ERKS_(%struct.VolatileMember* %this, %struct.VolatileMember*)
+// CHECK-LABEL: define linkonce_odr void @_ZN14VolatileMemberC2ERKS_(%struct.VolatileMember* %this, %struct.VolatileMember* dereferenceable({{[0-9]+}}))
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4{{.*}})
// CHECK: load volatile i32* {{.*}}, align 4
// CHECK: store volatile i32 {{.*}}, align 4
@@ -223,34 +223,34 @@ CALL_CC(Basic)
// CHECK: ret void
// BitfieldMember copy-constructor:
-// CHECK-LABEL: define linkonce_odr void @_ZN14BitfieldMemberC2ERKS_(%struct.BitfieldMember* %this, %struct.BitfieldMember*)
+// CHECK-LABEL: define linkonce_odr void @_ZN14BitfieldMemberC2ERKS_(%struct.BitfieldMember* %this, %struct.BitfieldMember* dereferenceable({{[0-9]+}}))
// 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-LABEL: define linkonce_odr void @_ZN16InnerClassMemberC2ERKS_(%struct.InnerClassMember* %this, %struct.InnerClassMember*)
+// CHECK-LABEL: define linkonce_odr void @_ZN16InnerClassMemberC2ERKS_(%struct.InnerClassMember* %this, %struct.InnerClassMember* dereferenceable({{[0-9]+}}))
// 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-LABEL: define linkonce_odr void @_ZN15ReferenceMemberC2ERKS_(%struct.ReferenceMember* %this, %struct.ReferenceMember*)
+// CHECK-LABEL: define linkonce_odr void @_ZN15ReferenceMemberC2ERKS_(%struct.ReferenceMember* %this, %struct.ReferenceMember* dereferenceable({{[0-9]+}}))
// 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-LABEL: define linkonce_odr void @_ZN15BitfieldMember2C2ERKS_(%struct.BitfieldMember2* %this, %struct.BitfieldMember2*)
+// CHECK-2-LABEL: define linkonce_odr void @_ZN15BitfieldMember2C2ERKS_(%struct.BitfieldMember2* %this, %struct.BitfieldMember2* dereferenceable({{[0-9]+}}))
// 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-LABEL: define linkonce_odr void @_ZN13PackedMembersC2ERKS_(%struct.PackedMembers* %this, %struct.PackedMembers*)
+// CHECK-LABEL: define linkonce_odr void @_ZN13PackedMembersC2ERKS_(%struct.PackedMembers* %this, %struct.PackedMembers* dereferenceable({{[0-9]+}}))
// 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 f0199c851dcd..745cf18fce21 100644
--- a/test/CodeGenCXX/pointers-to-data-members.cpp
+++ b/test/CodeGenCXX/pointers-to-data-members.cpp
@@ -202,7 +202,7 @@ namespace BoolPtrToMember {
bool member;
};
- // CHECK-LABEL: define i8* @_ZN15BoolPtrToMember1fERNS_1XEMS0_b
+ // CHECK-LABEL: define dereferenceable({{[0-9]+}}) i8* @_ZN15BoolPtrToMember1fERNS_1XEMS0_b
bool &f(X &x, bool X::*member) {
// CHECK: {{bitcast.* to i8\*}}
// CHECK-NEXT: getelementptr inbounds i8*
diff --git a/test/CodeGenCXX/poly-unsigned.cpp b/test/CodeGenCXX/poly-unsigned.cpp
new file mode 100644
index 000000000000..e2ab430a969e
--- /dev/null
+++ b/test/CodeGenCXX/poly-unsigned.cpp
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -triple arm64-apple-ios -target-feature +neon -ffreestanding -S -emit-llvm -o - %s | FileCheck --check-prefix=CHECK-UNSIGNED-POLY %s
+// RUN: %clang_cc1 -triple arm64-linux-gnu -target-feature +neon -ffreestanding -S -emit-llvm -o - %s | FileCheck --check-prefix=CHECK-UNSIGNED-POLY %s
+// RUN: %clang_cc1 -triple armv7-apple-ios -ffreestanding -target-cpu cortex-a8 -S -emit-llvm -o - %s | FileCheck --check-prefix=CHECK-SIGNED-POLY %s
+
+#include <arm_neon.h>
+
+// Polynomial types really should be universally unsigned, otherwise casting
+// (say) poly8_t "x^7" to poly16_t would change it to "x^15 + x^14 + ... +
+// x^7". Unfortunately 32-bit ARM ended up in a slightly delicate ABI situation
+// so for now it got that wrong.
+
+poly16_t test_poly8(poly8_t pIn) {
+// CHECK-UNSIGNED-POLY: @_Z10test_poly8h
+// CHECK-UNSIGNED-POLY: zext i8 {{.*}} to i16
+
+// CHECK-SIGNED-POLY: @_Z10test_poly8a
+// CHECK-SIGNED-POLY: sext i8 {{.*}} to i16
+
+ return pIn;
+}
diff --git a/test/CodeGenCXX/pr11797.cpp b/test/CodeGenCXX/pr11797.cpp
index 1098372ce389..2a31090e4218 100644
--- a/test/CodeGenCXX/pr11797.cpp
+++ b/test/CodeGenCXX/pr11797.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -fvisibility hidden -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -fvisibility hidden -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %s
namespace std __attribute__ ((__visibility__ ("default"))) {}
#pragma GCC visibility push(default)
diff --git a/test/CodeGenCXX/pr12104.cpp b/test/CodeGenCXX/pr12104.cpp
index a62f04b66834..560ffbe5b35c 100644
--- a/test/CodeGenCXX/pr12104.cpp
+++ b/test/CodeGenCXX/pr12104.cpp
@@ -1,6 +1,6 @@
-// RUN: %clang_cc1 -include %S/pr12104.h %s -emit-llvm -o - | FileCheck %s
-// RUN: %clang_cc1 -x c++ -emit-pch -o %t %S/pr12104.h
-// RUN: %clang_cc1 -include-pch %t %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -include %S/pr12104.h %s -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -x c++ -triple %itanium_abi_triple -emit-pch -o %t %S/pr12104.h
+// RUN: %clang_cc1 -include-pch %t %s -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %s
template struct Patch<1>;
diff --git a/test/CodeGenCXX/pr13396.cpp b/test/CodeGenCXX/pr13396.cpp
index 3d582c51006b..e41dd39fcc6e 100644
--- a/test/CodeGenCXX/pr13396.cpp
+++ b/test/CodeGenCXX/pr13396.cpp
@@ -7,13 +7,13 @@ struct foo {
};
foo::foo() {
- // CHECK-LABEL: define void @_ZN3fooC1Ev(%struct.foo* inreg %this)
// CHECK-LABEL: define void @_ZN3fooC2Ev(%struct.foo* inreg %this)
+ // CHECK-LABEL: define void @_ZN3fooC1Ev(%struct.foo* inreg %this)
}
foo::~foo() {
- // CHECK-LABEL: define void @_ZN3fooD1Ev(%struct.foo* inreg %this)
// CHECK-LABEL: define void @_ZN3fooD2Ev(%struct.foo* inreg %this)
+ // CHECK-LABEL: define void @_ZN3fooD1Ev(%struct.foo* inreg %this)
}
void dummy() {
diff --git a/test/CodeGenCXX/pr18661.cpp b/test/CodeGenCXX/pr18661.cpp
new file mode 100644
index 000000000000..235867831e28
--- /dev/null
+++ b/test/CodeGenCXX/pr18661.cpp
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 %s -triple %itanium_abi_triple -fcxx-exceptions -fms-extensions -emit-llvm -o - | FileCheck %s
+
+extern "C" {
+ void f();
+
+ // In MS mode we don't validate the exception specification.
+ void f() throw() {
+ }
+}
+
+// PR18661: Clang would fail to emit function definition with mismatching
+// exception specification, even though it was just treated as a warning.
+
+// CHECK: define void @f()
diff --git a/test/CodeGenCXX/pr18962.cpp b/test/CodeGenCXX/pr18962.cpp
new file mode 100644
index 000000000000..ab537b4928e3
--- /dev/null
+++ b/test/CodeGenCXX/pr18962.cpp
@@ -0,0 +1,32 @@
+// RUN: %clang_cc1 -triple i686-linux-gnu %s -emit-llvm -o - | FileCheck %s
+
+class A {
+ // append has to have the same prototype as fn1 to tickle the bug.
+ void (*append)(A *);
+};
+
+class B {};
+class D;
+
+// C has to be non-C++98 POD with available tail padding, making the LLVM base
+// type differ from the complete LLVM type.
+class C {
+ // This member creates a circular LLVM type reference to %class.D.
+ D *m_group;
+ B changeListeners;
+};
+class D : C {};
+
+void fn1(A *p1) {
+}
+
+void
+fn2(C *) {
+}
+
+// We end up using an opaque type for 'append' to avoid circular references.
+// CHECK: %class.A = type { {}* }
+// CHECK: %class.C = type { %class.D*, %class.B }
+// CHECK: %class.D = type { %class.C.base, [3 x i8] }
+// CHECK: %class.C.base = type <{ %class.D*, %class.B }>
+// CHECK: %class.B = type { i8 }
diff --git a/test/CodeGenCXX/pr9965.cpp b/test/CodeGenCXX/pr9965.cpp
index c2d54e19215d..46fd60914b0e 100644
--- a/test/CodeGenCXX/pr9965.cpp
+++ b/test/CodeGenCXX/pr9965.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -std=c++11 -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck %s
struct A { A(); };
template<typename T>
struct X : A // default constructor is not trivial
diff --git a/test/CodeGenCXX/pragma-init_seg.cpp b/test/CodeGenCXX/pragma-init_seg.cpp
new file mode 100644
index 000000000000..3f9ff217e6b6
--- /dev/null
+++ b/test/CodeGenCXX/pragma-init_seg.cpp
@@ -0,0 +1,72 @@
+// RUN: %clang_cc1 %s -triple=i686-pc-win32 -fms-extensions -emit-llvm -o - | FileCheck %s
+
+int f();
+
+// CHECK: $"\01?x@selectany_init@@3HA" = comdat any
+// CHECK: $"\01?x@?$A@H@explicit_template_instantiation@@2HB" = comdat any
+// CHECK: $"\01?x@?$A@H@implicit_template_instantiation@@2HB" = comdat any
+
+namespace simple_init {
+#pragma init_seg(compiler)
+int x = f();
+// CHECK: @"\01?x@simple_init@@3HA" = global i32 0, align 4
+// CHECK: @__cxx_init_fn_ptr = private constant void ()* @"\01??__Ex@simple_init@@YAXXZ", section ".CRT$XCC"
+
+#pragma init_seg(lib)
+int y = f();
+// CHECK: @"\01?y@simple_init@@3HA" = global i32 0, align 4
+// CHECK: @__cxx_init_fn_ptr1 = private constant void ()* @"\01??__Ey@simple_init@@YAXXZ", section ".CRT$XCL"
+
+#pragma init_seg(user)
+int z = f();
+// CHECK: @"\01?z@simple_init@@3HA" = global i32 0, align 4
+// No function pointer! This one goes on @llvm.global_ctors.
+}
+
+#pragma init_seg(".asdf")
+
+namespace internal_init {
+namespace {
+int x = f();
+// CHECK: @"\01?x@?A@internal_init@@3HA" = internal global i32 0, align 4
+// CHECK: @__cxx_init_fn_ptr2 = private constant void ()* @"\01??__Ex@?A@internal_init@@YAXXZ", section ".asdf"
+}
+}
+
+namespace selectany_init {
+int __declspec(selectany) x = f();
+// CHECK: @"\01?x@selectany_init@@3HA" = weak_odr global i32 0, comdat $"\01?x@selectany_init@@3HA", align 4
+// CHECK: @__cxx_init_fn_ptr3 = private constant void ()* @"\01??__Ex@selectany_init@@YAXXZ", section ".asdf", comdat $"\01?x@selectany_init@@3HA"
+}
+
+namespace explicit_template_instantiation {
+template <typename T> struct A { static const int x; };
+template <typename T> const int A<T>::x = f();
+template struct A<int>;
+// CHECK: @"\01?x@?$A@H@explicit_template_instantiation@@2HB" = weak_odr global i32 0, comdat $"\01?x@?$A@H@explicit_template_instantiation@@2HB", align 4
+// CHECK: @__cxx_init_fn_ptr4 = private constant void ()* @"\01??__Ex@?$A@H@explicit_template_instantiation@@2HB@YAXXZ", section ".asdf", comdat $"\01?x@?$A@H@explicit_template_instantiation@@2HB"
+}
+
+namespace implicit_template_instantiation {
+template <typename T> struct A { static const int x; };
+template <typename T> const int A<T>::x = f();
+int g() { return A<int>::x; }
+// CHECK: @"\01?x@?$A@H@implicit_template_instantiation@@2HB" = linkonce_odr global i32 0, comdat $"\01?x@?$A@H@implicit_template_instantiation@@2HB", align 4
+// CHECK: @__cxx_init_fn_ptr5 = private constant void ()* @"\01??__Ex@?$A@H@implicit_template_instantiation@@2HB@YAXXZ", section ".asdf", comdat $"\01?x@?$A@H@implicit_template_instantiation@@2HB"
+}
+
+// ... and here's where we emitted user level ctors.
+// CHECK: @llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }]
+// CHECK: [{ i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__sub_I_pragma_init_seg.cpp, i8* null }]
+
+// We have to mark everything used so we can survive globalopt, even through
+// LTO. There's no way LLVM could really understand if data in the .asdf
+// section is really used or dead.
+//
+// CHECK: @llvm.used = appending global [6 x i8*]
+// CHECK: [i8* bitcast (void ()** @__cxx_init_fn_ptr to i8*),
+// CHECK: i8* bitcast (void ()** @__cxx_init_fn_ptr1 to i8*),
+// CHECK: i8* bitcast (void ()** @__cxx_init_fn_ptr2 to i8*),
+// CHECK: i8* bitcast (void ()** @__cxx_init_fn_ptr3 to i8*),
+// CHECK: i8* bitcast (void ()** @__cxx_init_fn_ptr4 to i8*),
+// CHECK: i8* bitcast (void ()** @__cxx_init_fn_ptr5 to i8*)], section "llvm.metadata"
diff --git a/test/CodeGenCXX/pragma-pack-3.cpp b/test/CodeGenCXX/pragma-pack-3.cpp
new file mode 100644
index 000000000000..49509a5b2a8e
--- /dev/null
+++ b/test/CodeGenCXX/pragma-pack-3.cpp
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 %s -triple=i686-apple-darwin10 -emit-llvm -o - | FileCheck %s
+
+struct Base {
+ char a;
+};
+
+struct Derived_1 : virtual Base
+{
+ char b;
+};
+
+#pragma pack(1)
+struct Derived_2 : Derived_1 {
+ // CHECK: %struct.Derived_2 = type { %struct.Derived_1.base, %struct.Base }
+ // CHECK: %struct.Derived_1.base = type <{ i32 (...)**, i8 }>
+};
+
+Derived_2 x;
diff --git a/test/CodeGenCXX/pragma-weak.cpp b/test/CodeGenCXX/pragma-weak.cpp
index c03307914040..e2d464818edb 100644
--- a/test/CodeGenCXX/pragma-weak.cpp
+++ b/test/CodeGenCXX/pragma-weak.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck %s
#pragma weak zex
int zex;
@@ -10,7 +10,7 @@ int zex;
#pragma weak foo
struct S { void foo(); };
void S::foo() {}
-// CHECK-LABEL: define void @_ZN1S3fooEv(
+// CHECK-LABEL: define {{.*}}void @_ZN1S3fooEv(
#pragma weak zed
namespace bar { void zed() {} }
diff --git a/test/CodeGenCXX/predefined-expr.cpp b/test/CodeGenCXX/predefined-expr.cpp
index 9062ee095c3a..f901467c4f4b 100644
--- a/test/CodeGenCXX/predefined-expr.cpp
+++ b/test/CodeGenCXX/predefined-expr.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -std=c++11 %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -std=c++11 %s -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %s
// CHECK: private unnamed_addr constant [15 x i8] c"externFunction\00"
// CHECK: private unnamed_addr constant [26 x i8] c"void NS::externFunction()\00"
@@ -10,7 +10,7 @@
// 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 [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"
@@ -28,13 +28,13 @@
// CHECK: private unnamed_addr constant [46 x i8] c"void NS::Base::functionTemplate1(T) [T = int]\00"
// CHECK: private unnamed_addr constant [23 x i8] c"anonymousUnionFunction\00"
-// CHECK: private unnamed_addr constant [83 x i8] c"void NS::ContainerForAnonymousRecords::<anonymous union>::anonymousUnionFunction()\00"
+// CHECK: private unnamed_addr constant [83 x i8] c"void NS::ContainerForAnonymousRecords::(anonymous union)::anonymousUnionFunction()\00"
// CHECK: private unnamed_addr constant [24 x i8] c"anonymousStructFunction\00"
-// CHECK: private unnamed_addr constant [85 x i8] c"void NS::ContainerForAnonymousRecords::<anonymous struct>::anonymousStructFunction()\00"
+// CHECK: private unnamed_addr constant [85 x i8] c"void NS::ContainerForAnonymousRecords::(anonymous struct)::anonymousStructFunction()\00"
// CHECK: private unnamed_addr constant [23 x i8] c"anonymousClassFunction\00"
-// CHECK: private unnamed_addr constant [83 x i8] c"void NS::ContainerForAnonymousRecords::<anonymous class>::anonymousClassFunction()\00"
+// CHECK: private unnamed_addr constant [83 x i8] c"void NS::ContainerForAnonymousRecords::(anonymous class)::anonymousClassFunction()\00"
// CHECK: private unnamed_addr constant [12 x i8] c"~Destructor\00"
// CHECK: private unnamed_addr constant [30 x i8] c"NS::Destructor::~Destructor()\00"
@@ -93,7 +93,7 @@
// CHECK: private unnamed_addr constant [59 x i8] c"void ClassInTopLevelNamespace::topLevelNamespaceFunction()\00"
// CHECK: private unnamed_addr constant [27 x i8] c"anonymousNamespaceFunction\00"
-// CHECK: private unnamed_addr constant [84 x i8] c"void <anonymous namespace>::ClassInAnonymousNamespace::anonymousNamespaceFunction()\00"
+// CHECK: private unnamed_addr constant [84 x i8] c"void (anonymous namespace)::ClassInAnonymousNamespace::anonymousNamespaceFunction()\00"
// CHECK: private unnamed_addr constant [19 x i8] c"localClassFunction\00"
// CHECK: private unnamed_addr constant [59 x i8] c"void NS::localClass(int)::LocalClass::localClassFunction()\00"
diff --git a/test/CodeGenCXX/ptr-to-member-function.cpp b/test/CodeGenCXX/ptr-to-member-function.cpp
index 914a90a4be1a..e02b2096be99 100644
--- a/test/CodeGenCXX/ptr-to-member-function.cpp
+++ b/test/CodeGenCXX/ptr-to-member-function.cpp
@@ -1,8 +1,7 @@
-// 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 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 CHECK-LP32 --input-file=%t-32.s %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -emit-llvm %s -o - | \
+// RUN: FileCheck -check-prefix CHECK-LP64 %s
+// RUN: %clang_cc1 -triple i386-apple-darwin -std=c++11 -emit-llvm %s -o - | \
+// RUN: FileCheck -check-prefix CHECK-LP32 %s
// 13.3.3.2 Ranking implicit conversion sequences
extern "C" int printf(...);
@@ -64,8 +63,8 @@ int main()
B1 c = B1(2);
}
-// CHECK-LP64: callq __ZN1XcvM1BFvvEEv
-// CHECK-LP64: callq __Z1gM1CFvvE
+// CHECK-LP64: call { i64, i64 } @_ZN1XcvM1BFvvEEv
+// CHECK-LP64: call void @_Z1gM1CFvvE
-// CHECK-LP32: calll L__ZN1XcvM1BFvvEEv
-// CHECK-LP32: calll __Z1gM1CFvvE
+// CHECK-LP32: call i64 @_ZN1XcvM1BFvvEEv
+// CHECK-LP32: call void @_Z1gM1CFvvE
diff --git a/test/CodeGenCXX/reference-cast.cpp b/test/CodeGenCXX/reference-cast.cpp
index 60ea393af96c..c4be5b78c2e4 100644
--- a/test/CodeGenCXX/reference-cast.cpp
+++ b/test/CodeGenCXX/reference-cast.cpp
@@ -3,7 +3,7 @@
// PR6024
extern int i;
-// CHECK: define i32* @_Z16lvalue_noop_castv() [[NUW:#[0-9]+]]
+// CHECK: define dereferenceable({{[0-9]+}}) i32* @_Z16lvalue_noop_castv() [[NUW:#[0-9]+]]
const int &lvalue_noop_cast() {
if (i == 0)
// CHECK: store i32 17, i32*
@@ -15,7 +15,7 @@ const int &lvalue_noop_cast() {
return 17;
}
-// CHECK-LABEL: define i16* @_Z20lvalue_integral_castv()
+// CHECK-LABEL: define dereferenceable({{[0-9]+}}) 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-LABEL: define i16* @_Z29lvalue_floating_integral_castv()
+// CHECK-LABEL: define dereferenceable({{[0-9]+}}) 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-LABEL: define float* @_Z29lvalue_integral_floating_castv()
+// CHECK-LABEL: define dereferenceable({{[0-9]+}}) 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-LABEL: define float* @_Z20lvalue_floating_castv()
+// CHECK-LABEL: define dereferenceable({{[0-9]+}}) 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-LABEL: define i8* @_Z24lvalue_integer_bool_castv()
+// CHECK-LABEL: define dereferenceable({{[0-9]+}}) 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-LABEL: define i8* @_Z25lvalue_floating_bool_castv()
+// CHECK-LABEL: define dereferenceable({{[0-9]+}}) 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-LABEL: define i8* @_Z26lvalue_ptrmem_to_bool_castv()
+// CHECK-LABEL: define dereferenceable({{[0-9]+}}) 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-LABEL: define i8* @_Z27lvalue_ptrmem_to_bool_cast2v
+// CHECK-LABEL: define dereferenceable({{[0-9]+}}) i8* @_Z27lvalue_ptrmem_to_bool_cast2v
const bool &lvalue_ptrmem_to_bool_cast2() {
if (i == 0)
// CHECK: {{call.*_Z30get_pointer_to_member_functionv}}
diff --git a/test/CodeGenCXX/reference-field.cpp b/test/CodeGenCXX/reference-field.cpp
index 031202925952..54e914d0f3fc 100644
--- a/test/CodeGenCXX/reference-field.cpp
+++ b/test/CodeGenCXX/reference-field.cpp
@@ -1,6 +1,8 @@
-// RUN: %clang_cc1 -emit-llvm -o - %s -O2 | grep "@_Z1bv"
+// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -o - %s -O2 | FileCheck %s
// Make sure the call to b() doesn't get optimized out.
extern struct x {char& x,y;}y;
int b();
int a() { if (!&y.x) b(); }
+
+// CHECK: @_Z1bv
diff --git a/test/CodeGenCXX/reference-init.cpp b/test/CodeGenCXX/reference-init.cpp
index d47b1f37489c..3a3eaeee78f6 100644
--- a/test/CodeGenCXX/reference-init.cpp
+++ b/test/CodeGenCXX/reference-init.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm-only -verify %s
+// RUN: %clang_cc1 -emit-llvm-only -triple %itanium_abi_triple -verify %s
// expected-no-diagnostics
struct XPTParamDescriptor {};
diff --git a/test/CodeGenCXX/references.cpp b/test/CodeGenCXX/references.cpp
index ec7a3d5daa8f..454c306a13a7 100644
--- a/test/CodeGenCXX/references.cpp
+++ b/test/CodeGenCXX/references.cpp
@@ -241,7 +241,7 @@ struct A {
};
// CHECK-LABEL: define internal void @__cxx_global_var_init
-// CHECK: call void @_ZN2N31AC1Ei(%"struct.N3::A"* @_ZGRN2N35sA123E, i32 123)
+// CHECK: call void @_ZN2N31AC1Ei(%"struct.N3::A"* @_ZGRN2N35sA123E_, i32 123)
// CHECK: call i32 @__cxa_atexit
// CHECK: ret void
const A &sA123 = A(123);
@@ -256,7 +256,7 @@ struct A {
void f() {
// CHECK-LABEL: define void @_ZN2N41fEv
- // CHECK: call void @_ZN2N41AC1Ev(%"struct.N4::A"* @_ZGRZN2N41fEvE2ar)
+ // CHECK: call void @_ZN2N41AC1Ev(%"struct.N4::A"* @_ZGRZN2N41fEvE2ar_)
// CHECK: call i32 @__cxa_atexit
// CHECK: ret void
static const A& ar = A();
diff --git a/test/CodeGenCXX/return.cpp b/test/CodeGenCXX/return.cpp
index 1975055fdb74..5c1cfdaeed75 100644
--- a/test/CodeGenCXX/return.cpp
+++ b/test/CodeGenCXX/return.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s
-// RUN: %clang_cc1 -emit-llvm -O -o - %s | FileCheck %s --check-prefix=CHECK-OPT
+// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -o - %s | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -O -o - %s | FileCheck %s --check-prefix=CHECK-OPT
// CHECK: @_Z9no_return
// CHECK-OPT: @_Z9no_return
diff --git a/test/CodeGenCXX/rtti-fundamental.cpp b/test/CodeGenCXX/rtti-fundamental.cpp
index 2495e969bff8..e70c3aa36597 100644
--- a/test/CodeGenCXX/rtti-fundamental.cpp
+++ b/test/CodeGenCXX/rtti-fundamental.cpp
@@ -15,102 +15,107 @@ namespace __cxxabiv1 {
}
// void
-// CHECK: @_ZTIv = unnamed_addr constant
-// CHECK: @_ZTIPv = unnamed_addr constant
-// CHECK: @_ZTIPKv = unnamed_addr constant
+// CHECK: @_ZTIv = constant
+// CHECK: @_ZTIPv = constant
+// CHECK: @_ZTIPKv = constant
// std::nullptr_t
-// CHECK: @_ZTIDn = unnamed_addr constant
-// CHECK: @_ZTIPDn = unnamed_addr constant
-// CHECK: @_ZTIPKDn = unnamed_addr constant
+// CHECK: @_ZTIDn = constant
+// CHECK: @_ZTIPDn = constant
+// CHECK: @_ZTIPKDn = constant
// bool
-// CHECK: @_ZTIb = unnamed_addr constant
-// CHECK: @_ZTIPb = unnamed_addr constant
-// CHECK: @_ZTIPKb = unnamed_addr constant
+// CHECK: @_ZTIb = constant
+// CHECK: @_ZTIPb = constant
+// CHECK: @_ZTIPKb = constant
// wchar_t
-// CHECK: @_ZTIw = unnamed_addr constant
-// CHECK: @_ZTIPw = unnamed_addr constant
-// CHECK: @_ZTIPKw = unnamed_addr constant
+// CHECK: @_ZTIw = constant
+// CHECK: @_ZTIPw = constant
+// CHECK: @_ZTIPKw = constant
// char
-// CHECK: @_ZTIc = unnamed_addr constant
-// CHECK: @_ZTIPc = unnamed_addr constant
-// CHECK: @_ZTIPKc = unnamed_addr constant
+// CHECK: @_ZTIc = constant
+// CHECK: @_ZTIPc = constant
+// CHECK: @_ZTIPKc = constant
// unsigned char
-// CHECK: @_ZTIh = unnamed_addr constant
-// CHECK: @_ZTIPh = unnamed_addr constant
-// CHECK: @_ZTIPKh = unnamed_addr constant
+// CHECK: @_ZTIh = constant
+// CHECK: @_ZTIPh = constant
+// CHECK: @_ZTIPKh = constant
// signed char
-// CHECK: @_ZTIa = unnamed_addr constant
-// CHECK: @_ZTIPa = unnamed_addr constant
-// CHECK: @_ZTIPKa = unnamed_addr constant
+// CHECK: @_ZTIa = constant
+// CHECK: @_ZTIPa = constant
+// CHECK: @_ZTIPKa = constant
// short
-// CHECK: @_ZTIs = unnamed_addr constant
-// CHECK: @_ZTIPs = unnamed_addr constant
-// CHECK: @_ZTIPKs = unnamed_addr constant
+// CHECK: @_ZTIs = constant
+// CHECK: @_ZTIPs = constant
+// CHECK: @_ZTIPKs = constant
// unsigned short
-// CHECK: @_ZTIt = unnamed_addr constant
-// CHECK: @_ZTIPt = unnamed_addr constant
-// CHECK: @_ZTIPKt = unnamed_addr constant
+// CHECK: @_ZTIt = constant
+// CHECK: @_ZTIPt = constant
+// CHECK: @_ZTIPKt = constant
// int
-// CHECK: @_ZTIi = unnamed_addr constant
-// CHECK: @_ZTIPi = unnamed_addr constant
-// CHECK: @_ZTIPKi = unnamed_addr constant
+// CHECK: @_ZTIi = constant
+// CHECK: @_ZTIPi = constant
+// CHECK: @_ZTIPKi = constant
// unsigned int
-// CHECK: @_ZTIj = unnamed_addr constant
-// CHECK: @_ZTIPj = unnamed_addr constant
-// CHECK: @_ZTIPKj = unnamed_addr constant
+// CHECK: @_ZTIj = constant
+// CHECK: @_ZTIPj = constant
+// CHECK: @_ZTIPKj = constant
// long
-// CHECK: @_ZTIl = unnamed_addr constant
-// CHECK: @_ZTIPl = unnamed_addr constant
-// CHECK: @_ZTIPKl = unnamed_addr constant
+// CHECK: @_ZTIl = constant
+// CHECK: @_ZTIPl = constant
+// CHECK: @_ZTIPKl = constant
// unsigned long
-// CHECK: @_ZTIm = unnamed_addr constant
-// CHECK: @_ZTIPm = unnamed_addr constant
-// CHECK: @_ZTIPKm = unnamed_addr constant
+// CHECK: @_ZTIm = constant
+// CHECK: @_ZTIPm = constant
+// CHECK: @_ZTIPKm = constant
// long long
-// CHECK: @_ZTIx = unnamed_addr constant
-// CHECK: @_ZTIPx = unnamed_addr constant
-// CHECK: @_ZTIPKx = unnamed_addr constant
+// CHECK: @_ZTIx = constant
+// CHECK: @_ZTIPx = constant
+// CHECK: @_ZTIPKx = constant
// unsigned long long
-// CHECK: @_ZTIy = unnamed_addr constant
-// CHECK: @_ZTIPy = unnamed_addr constant
-// CHECK: @_ZTIPKy = unnamed_addr constant
+// CHECK: @_ZTIy = constant
+// CHECK: @_ZTIPy = constant
+// CHECK: @_ZTIPKy = constant
+
+// half
+// CHECK: @_ZTIDh = constant
+// CHECK: @_ZTIPDh = constant
+// CHECK: @_ZTIPKDh = constant
// float
-// CHECK: @_ZTIf = unnamed_addr constant
-// CHECK: @_ZTIPf = unnamed_addr constant
-// CHECK: @_ZTIPKf = unnamed_addr constant
+// CHECK: @_ZTIf = constant
+// CHECK: @_ZTIPf = constant
+// CHECK: @_ZTIPKf = constant
// double
-// CHECK: @_ZTId = unnamed_addr constant
-// CHECK: @_ZTIPd = unnamed_addr constant
-// CHECK: @_ZTIPKd = unnamed_addr constant
+// CHECK: @_ZTId = constant
+// CHECK: @_ZTIPd = constant
+// CHECK: @_ZTIPKd = constant
// long double
-// CHECK: @_ZTIe = unnamed_addr constant
-// CHECK: @_ZTIPe = unnamed_addr constant
-// CHECK: @_ZTIPKe = unnamed_addr constant
+// CHECK: @_ZTIe = constant
+// CHECK: @_ZTIPe = constant
+// CHECK: @_ZTIPKe = constant
// char16_t
-// CHECK: @_ZTIDs = unnamed_addr constant
-// CHECK: @_ZTIPDs = unnamed_addr constant
-// CHECK: @_ZTIPKDs = unnamed_addr constant
+// CHECK: @_ZTIDs = constant
+// CHECK: @_ZTIPDs = constant
+// CHECK: @_ZTIPKDs = constant
// char32_t
-// CHECK: @_ZTIDi = unnamed_addr constant
-// CHECK: @_ZTIPDi = unnamed_addr constant
-// CHECK: @_ZTIPKDi = unnamed_addr constant
+// CHECK: @_ZTIDi = constant
+// CHECK: @_ZTIPDi = constant
+// CHECK: @_ZTIPKDi = constant
diff --git a/test/CodeGenCXX/rtti-linkage.cpp b/test/CodeGenCXX/rtti-linkage.cpp
index 42fe43523404..3b06d426e5a9 100644
--- a/test/CodeGenCXX/rtti-linkage.cpp
+++ b/test/CodeGenCXX/rtti-linkage.cpp
@@ -1,56 +1,75 @@
-// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -fhidden-weak-vtables -emit-llvm -o - | FileCheck %s
-// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -fvisibility hidden -fhidden-weak-vtables -emit-llvm -o - | FileCheck -check-prefix=CHECK-WITH-HIDDEN %s
+// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-BOTH
+// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -fvisibility hidden -emit-llvm -o - | FileCheck -check-prefix=CHECK-WITH-HIDDEN -check-prefix=CHECK-BOTH %s
#include <typeinfo>
+// CHECK-BOTH: _ZTSP1C = internal constant
+// CHECK-BOTH: _ZTS1C = internal constant
+// CHECK-BOTH: _ZTI1C = internal constant
+// CHECK-BOTH: _ZTIP1C = internal constant
+// CHECK-BOTH: _ZTSPP1C = internal constant
+// CHECK-BOTH: _ZTIPP1C = internal constant
+// CHECK-BOTH: _ZTSM1Ci = internal constant
+// CHECK-BOTH: _ZTIM1Ci = internal constant
+// CHECK-BOTH: _ZTSPM1Ci = internal constant
+// CHECK-BOTH: _ZTIPM1Ci = internal constant
+// CHECK-BOTH: _ZTSM1CS_ = internal constant
+// CHECK-BOTH: _ZTIM1CS_ = internal constant
+// CHECK-BOTH: _ZTSM1CPS_ = internal constant
+// CHECK-BOTH: _ZTIM1CPS_ = internal constant
+// CHECK-BOTH: _ZTSM1A1C = internal constant
+// CHECK: _ZTS1A = linkonce_odr constant
+// CHECK-WITH-HIDDEN: _ZTS1A = linkonce_odr hidden constant
+// CHECK: _ZTI1A = linkonce_odr constant
+// CHECK-WITH-HIDDEN: _ZTI1A = linkonce_odr hidden constant
+// CHECK-BOTH: _ZTIM1A1C = internal constant
+// CHECK-BOTH: _ZTSM1AP1C = internal constant
+// CHECK-BOTH: _ZTIM1AP1C = internal constant
+
// CHECK-WITH-HIDDEN: _ZTSFN12_GLOBAL__N_11DEvE = internal constant
// CHECK-WITH-HIDDEN: @_ZTSPK2T4 = linkonce_odr hidden constant
// CHECK-WITH-HIDDEN: @_ZTS2T4 = linkonce_odr hidden constant
-// CHECK-WITH-HIDDEN: @_ZTI2T4 = linkonce_odr hidden unnamed_addr constant
-// CHECK-WITH-HIDDEN: @_ZTIPK2T4 = linkonce_odr hidden unnamed_addr constant
-
-// CHECK: _ZTSP1C = internal constant
-// CHECK: _ZTS1C = internal constant
-// CHECK: _ZTI1C = internal unnamed_addr constant
-// CHECK: _ZTIP1C = internal unnamed_addr constant
-// CHECK: _ZTSPP1C = internal constant
-// CHECK: _ZTIPP1C = internal unnamed_addr constant
-// CHECK: _ZTSM1Ci = internal constant
-// CHECK: _ZTIM1Ci = internal unnamed_addr constant
-// CHECK: _ZTSPM1Ci = internal constant
-// CHECK: _ZTIPM1Ci = internal unnamed_addr constant
-// CHECK: _ZTSM1CS_ = internal constant
-// CHECK: _ZTIM1CS_ = internal unnamed_addr constant
-// CHECK: _ZTSM1CPS_ = internal constant
-// CHECK: _ZTIM1CPS_ = internal unnamed_addr constant
-// CHECK: _ZTSM1A1C = internal constant
-// CHECK: _ZTS1A = linkonce_odr constant
-// CHECK: _ZTI1A = linkonce_odr hidden unnamed_addr constant
-// CHECK: _ZTIM1A1C = internal unnamed_addr constant
-// CHECK: _ZTSM1AP1C = internal constant
-// CHECK: _ZTIM1AP1C = internal unnamed_addr constant
+// CHECK-WITH-HIDDEN: @_ZTI2T4 = linkonce_odr hidden constant
+// CHECK-WITH-HIDDEN: @_ZTIPK2T4 = linkonce_odr hidden constant
+// CHECK-WITH-HIDDEN: @_ZTSZ2t5vE1A = internal constant
+// CHECK-WITH-HIDDEN: @_ZTIZ2t5vE1A = internal constant
+// CHECK-WITH-HIDDEN: @_ZTSPZ2t7vE1A = linkonce_odr hidden constant
+// CHECK-WITH-HIDDEN: @_ZTSZ2t7vE1A = linkonce_odr hidden constant
+// CHECK-WITH-HIDDEN: @_ZTIZ2t7vE1A = linkonce_odr hidden constant
+// CHECK-WITH-HIDDEN: @_ZTIPZ2t7vE1A = linkonce_odr hidden constant
+// CHECK-WITH-HIDDEN: @_ZTSZ2t6vE1A = linkonce_odr hidden constant
+// CHECK-WITH-HIDDEN: @_ZTIZ2t6vE1A = linkonce_odr hidden constant
+
// CHECK: _ZTSN12_GLOBAL__N_11DE = internal constant
-// CHECK: _ZTIN12_GLOBAL__N_11DE = internal unnamed_addr constant
+// CHECK: _ZTIN12_GLOBAL__N_11DE = internal constant
// CHECK: _ZTSPN12_GLOBAL__N_11DE = internal constant
-// CHECK: _ZTIPN12_GLOBAL__N_11DE = internal unnamed_addr constant
+// CHECK: _ZTIPN12_GLOBAL__N_11DE = internal constant
// CHECK: _ZTSFN12_GLOBAL__N_11DEvE = internal constant
-// CHECK: _ZTIFN12_GLOBAL__N_11DEvE = internal unnamed_addr constant
+// CHECK: _ZTIFN12_GLOBAL__N_11DEvE = internal constant
// CHECK: _ZTSFvN12_GLOBAL__N_11DEE = internal constant
-// CHECK: _ZTIFvN12_GLOBAL__N_11DEE = internal unnamed_addr constant
+// CHECK: _ZTIFvN12_GLOBAL__N_11DEE = internal constant
// CHECK: _ZTSPFvvE = linkonce_odr constant
// CHECK: _ZTSFvvE = linkonce_odr constant
-// CHECK: _ZTIFvvE = linkonce_odr hidden unnamed_addr constant
-// CHECK: _ZTIPFvvE = linkonce_odr hidden unnamed_addr constant
+// CHECK: _ZTIFvvE = linkonce_odr constant
+// CHECK: _ZTIPFvvE = linkonce_odr constant
// CHECK: _ZTSN12_GLOBAL__N_11EE = internal constant
-// CHECK: _ZTIN12_GLOBAL__N_11EE = internal unnamed_addr constant
+// CHECK: _ZTIN12_GLOBAL__N_11EE = internal constant
// CHECK: _ZTSA10_i = linkonce_odr constant
-// CHECK: _ZTIA10_i = linkonce_odr hidden unnamed_addr constant
-// CHECK: _ZTI1TILj0EE = linkonce_odr unnamed_addr constant
-// CHECK: _ZTI1TILj1EE = weak_odr unnamed_addr constant
+// CHECK: _ZTIA10_i = linkonce_odr constant
+// CHECK: _ZTI1TILj0EE = linkonce_odr constant
+// CHECK: _ZTI1TILj1EE = weak_odr constant
// CHECK: _ZTI1TILj2EE = external constant
+// CHECK: _ZTSZ2t5vE1A = internal constant
+// CHECK: _ZTIZ2t5vE1A = internal constant
// CHECK: _ZTS1B = constant
-// CHECK: _ZTI1B = unnamed_addr constant
+// CHECK: _ZTI1B = constant
// CHECK: _ZTS1F = linkonce_odr constant
+// CHECK: _ZTSPZ2t7vE1A = linkonce_odr constant
+// CHECK: _ZTSZ2t7vE1A = linkonce_odr constant
+// CHECK: _ZTIZ2t7vE1A = linkonce_odr constant
+// CHECK: _ZTIPZ2t7vE1A = linkonce_odr constant
+// CHECK: _ZTSZ2t6vE1A = linkonce_odr constant
+// CHECK: _ZTIZ2t6vE1A = linkonce_odr constant
// CHECK: _ZTIN12_GLOBAL__N_11DE to
@@ -138,3 +157,25 @@ struct T4 {};
void t4(const T4 *ptr) {
const void *value = &typeid(ptr);
}
+
+// rdar://16265084
+void t5() {
+ struct A {};
+ const void *value = &typeid(A);
+}
+
+inline void t6() {
+ struct A {};
+ const void *value = &typeid(A);
+}
+void t6_helper() {
+ t6();
+}
+
+inline void t7() {
+ struct A {};
+ const void *value = &typeid(A*);
+}
+void t7_helper() {
+ t7();
+}
diff --git a/test/CodeGenCXX/rtti-visibility.cpp b/test/CodeGenCXX/rtti-visibility.cpp
index 40cee061942a..5945be5c73a2 100644
--- a/test/CodeGenCXX/rtti-visibility.cpp
+++ b/test/CodeGenCXX/rtti-visibility.cpp
@@ -1,17 +1,15 @@
// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -emit-llvm -o %t
-// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -fhidden-weak-vtables -emit-llvm -o %t.hidden
// RUN: FileCheck --check-prefix=CHECK-TEST1 %s < %t
// RUN: FileCheck --check-prefix=CHECK-TEST2 %s < %t
-// RUN: FileCheck --check-prefix=CHECK-TEST2-HIDDEN %s < %t.hidden
#include <typeinfo>
namespace Test1 {
// A is explicitly marked hidden, so all RTTI data should also be marked hidden.
// CHECK-TEST1: @_ZTSN5Test11AE = linkonce_odr hidden constant
- // CHECK-TEST1: @_ZTIN5Test11AE = linkonce_odr hidden unnamed_addr constant
+ // CHECK-TEST1: @_ZTIN5Test11AE = linkonce_odr hidden constant
// CHECK-TEST1: @_ZTSPN5Test11AE = linkonce_odr hidden constant
- // CHECK-TEST1: @_ZTIPN5Test11AE = linkonce_odr hidden unnamed_addr constant
+ // CHECK-TEST1: @_ZTIPN5Test11AE = linkonce_odr hidden constant
struct __attribute__((visibility("hidden"))) A { };
void f() {
@@ -23,12 +21,8 @@ namespace Test1 {
namespace Test2 {
// A is weak, so its linkage should be linkoce_odr, but not marked hidden.
// CHECK-TEST2: @_ZTSN5Test21AE = linkonce_odr constant
- // CHECK-TEST2: @_ZTIN5Test21AE = linkonce_odr unnamed_addr constant
+ // CHECK-TEST2: @_ZTIN5Test21AE = linkonce_odr constant
struct A { };
-
- // With -fhidden-weak-vtables, the typeinfo for A is marked hidden, but not its name.
- // CHECK-TEST2-HIDDEN: _ZTSN5Test21AE = linkonce_odr constant
- // CHECK-TEST2-HIDDEN: @_ZTIN5Test21AE = linkonce_odr hidden unnamed_addr constant
void f() {
(void)typeid(A);
}
diff --git a/test/CodeGenCXX/runtimecc.cpp b/test/CodeGenCXX/runtimecc.cpp
index 646c61e0fd8f..20448838f919 100644
--- a/test/CodeGenCXX/runtimecc.cpp
+++ b/test/CodeGenCXX/runtimecc.cpp
@@ -45,7 +45,7 @@ namespace test1 {
// CHECK: declare arm_aapcscc void @__cxa_throw(i8*, i8*, i8*)
-// CHECK-LABEL: define internal arm_aapcscc void @_GLOBAL__I_a()
+// CHECK-LABEL: define internal arm_aapcscc void @_GLOBAL__sub_I_runtimecc.cpp()
// CHECK: call arm_aapcscc void @__cxx_global_var_init()
diff --git a/test/CodeGenCXX/rvalue-references.cpp b/test/CodeGenCXX/rvalue-references.cpp
index 2e0fa829ec90..66705bfc6b3c 100644
--- a/test/CodeGenCXX/rvalue-references.cpp
+++ b/test/CodeGenCXX/rvalue-references.cpp
@@ -7,8 +7,8 @@ struct B : Spacer, A { };
B &getB();
-// CHECK-LABEL: define %struct.A* @_Z4getAv()
-// CHECK: call %struct.B* @_Z4getBv()
+// CHECK-LABEL: define dereferenceable({{[0-9]+}}) %struct.A* @_Z4getAv()
+// CHECK: call dereferenceable({{[0-9]+}}) %struct.B* @_Z4getBv()
// CHECK-NEXT: bitcast %struct.B*
// CHECK-NEXT: getelementptr inbounds i8*
// CHECK-NEXT: bitcast i8* {{.*}} to %struct.A*
@@ -19,17 +19,17 @@ int &getIntLValue();
int &&getIntXValue();
int getIntPRValue();
-// CHECK-LABEL: define i32* @_Z2f0v()
-// CHECK: call i32* @_Z12getIntLValuev()
+// CHECK-LABEL: define dereferenceable({{[0-9]+}}) i32* @_Z2f0v()
+// CHECK: call dereferenceable({{[0-9]+}}) i32* @_Z12getIntLValuev()
// CHECK-NEXT: ret i32*
int &&f0() { return static_cast<int&&>(getIntLValue()); }
-// CHECK-LABEL: define i32* @_Z2f1v()
-// CHECK: call i32* @_Z12getIntXValuev()
+// CHECK-LABEL: define dereferenceable({{[0-9]+}}) i32* @_Z2f1v()
+// CHECK: call dereferenceable({{[0-9]+}}) i32* @_Z12getIntXValuev()
// CHECK-NEXT: ret i32*
int &&f1() { return static_cast<int&&>(getIntXValue()); }
-// CHECK-LABEL: define i32* @_Z2f2v
+// CHECK-LABEL: define dereferenceable({{[0-9]+}}) i32* @_Z2f2v
// CHECK: call i32 @_Z13getIntPRValuev()
// CHECK-NEXT: store i32 {{.*}}, i32*
// CHECK-NEXT: ret i32*
@@ -95,7 +95,7 @@ namespace test1 {
};
// CHECK-LABEL: define void @_ZN5test11BC2Ei(
- // CHECK: [[T0:%.*]] = call i32* @_ZN5test14moveERi(
+ // CHECK: [[T0:%.*]] = call dereferenceable({{[0-9]+}}) i32* @_ZN5test14moveERi(
// CHECK-NEXT: [[T1:%.*]] = load i32* [[T0]]
// CHECK-NEXT: call void @_ZN5test11AC1Ei({{.*}}, i32 [[T1]])
// CHECK-NEXT: ret void
diff --git a/test/CodeGenCXX/scoped-enums.cpp b/test/CodeGenCXX/scoped-enums.cpp
index 159172d1662e..218013a4c58b 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 | FileCheck %s
+// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck %s
// PR9923
enum class Color { red, blue, green };
diff --git a/test/CodeGenCXX/sparcv9-abi.cpp b/test/CodeGenCXX/sparcv9-abi.cpp
new file mode 100644
index 000000000000..128d648cebd5
--- /dev/null
+++ b/test/CodeGenCXX/sparcv9-abi.cpp
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -triple sparcv9-unknown-unknown -emit-llvm %s -o - | FileCheck %s
+
+struct pod {
+ int a, b;
+};
+
+void f0();
+void f1(struct pod);
+
+struct notpod {
+ int a, b;
+ ~notpod() { f0(); }
+};
+
+void f2(struct notpod);
+
+// CHECK-LABEL: caller
+// CHECK: call void @_Z2f13pod(i64
+// CHECK: call void @_Z2f26notpod(%struct.notpod*
+void caller()
+{
+ pod p1;
+ notpod p2;
+ f1(p1);
+ f2(p2);
+}
diff --git a/test/CodeGenCXX/specialized-static-data-mem-init.cpp b/test/CodeGenCXX/specialized-static-data-mem-init.cpp
index c2a2ddb11254..68799624f26e 100644
--- a/test/CodeGenCXX/specialized-static-data-mem-init.cpp
+++ b/test/CodeGenCXX/specialized-static-data-mem-init.cpp
@@ -1,9 +1,9 @@
-// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -emit-llvm -triple %itanium_abi_triple -o - | FileCheck %s
// rdar: // 8562966
// pr8409
-// CHECK: @_ZN1CIiE11needs_guardE = weak_odr global
-// CHECK: @_ZGVN1CIiE11needs_guardE = weak_odr global
+// CHECK: @_ZN1CIiE11needs_guardE = linkonce_odr global
+// CHECK: @_ZGVN1CIiE11needs_guardE = linkonce_odr global
struct K
{
diff --git a/test/CodeGenCXX/split-stacks.cpp b/test/CodeGenCXX/split-stacks.cpp
new file mode 100644
index 000000000000..3e120344d6b6
--- /dev/null
+++ b/test/CodeGenCXX/split-stacks.cpp
@@ -0,0 +1,33 @@
+// RUN: %clang -target x86_64-linux-gnu -fsplit-stack -S -std=c++11 %s -emit-llvm -o - | FileCheck -check-prefix=CHECK-SEGSTK %s
+// RUN: %clang -target x86_64-linux-gnu -S -std=c++11 %s -emit-llvm -o - | FileCheck -check-prefix=CHECK-NOSEGSTK %s
+
+int foo() {
+ return 0;
+}
+
+template <typename T>
+[[gnu::no_split_stack]]
+int tnosplit() {
+ return 0;
+}
+
+[[gnu::no_split_stack]]
+int nosplit() {
+ return tnosplit<int>();
+}
+
+// CHECK-SEGSTK: define i32 @_Z3foov() [[SS:#[0-9]+]] {
+// CHECK-SEGSTK: define i32 @_Z7nosplitv() [[NSS1:#[0-9]+]] {
+// CHECK-SEGSTK: define linkonce_odr i32 @_Z8tnosplitIiEiv() [[NSS2:#[0-9]+]] {
+// CHECK-SEGSTK-NOT: [[NSS1]] = { {{.*}} "split-stack" {{.*}} }
+// CHECK-SEGSTK-NOT: [[NSS2]] = { {{.*}} "split-stack" {{.*}} }
+// CHECK-SEGSTK: [[SS]] = { {{.*}} "split-stack" {{.*}} }
+// CHECK-SEGSTK-NOT: [[NSS1]] = { {{.*}} "split-stack" {{.*}} }
+// CHECK-SEGSTK-NOT: [[NSS2]] = { {{.*}} "split-stack" {{.*}} }
+
+// CHECK-NOSEGSTK: define i32 @_Z3foov() [[NSS0:#[0-9]+]] {
+// CHECK-NOSEGSTK: define i32 @_Z7nosplitv() [[NSS1:#[0-9]+]] {
+// CHECK-NOSEGSTK: define linkonce_odr i32 @_Z8tnosplitIiEiv() [[NSS2:#[0-9]+]] {
+// CHECK-NOSEGSTK-NOT: [[NSS1]] = { {{.*}} "split-stack" {{.*}} }
+// CHECK-NOSEGSTK-NOT: [[NSS2]] = { {{.*}} "split-stack" {{.*}} }
+// CHECK-NOSEGSTK-NOT: [[NSS3]] = { {{.*}} "split-stack" {{.*}} }
diff --git a/test/CodeGenCXX/static-init-3.cpp b/test/CodeGenCXX/static-init-3.cpp
index dc28d5a32a63..083e00144c18 100644
--- a/test/CodeGenCXX/static-init-3.cpp
+++ b/test/CodeGenCXX/static-init-3.cpp
@@ -16,8 +16,8 @@ struct X1
}
};
-// CHECK: @_ZN2X1I2X2I1BEE8instanceE = weak_odr global %struct.X2* null, align 8
-// CHECJ: @_ZN2X1I2X2I1AEE8instanceE = weak_odr global %struct.X2* null, align 8
+// CHECK: @_ZN2X1I2X2I1BEE8instanceE = linkonce_odr global %struct.X2* null, align 8
+// CHECJ: @_ZN2X1I2X2I1AEE8instanceE = linkonce_odr global %struct.X2* null, align 8
template<class T> T & X1<T>::instance = X1<T>::get();
class A { };
diff --git a/test/CodeGenCXX/static-init.cpp b/test/CodeGenCXX/static-init.cpp
index f522775c109e..d23ead47f385 100644
--- a/test/CodeGenCXX/static-init.cpp
+++ b/test/CodeGenCXX/static-init.cpp
@@ -103,14 +103,14 @@ namespace test2 {
B::B() {
static int x = foo();
}
- // CHECK-LABEL: define void @_ZN5test21BC1Ev
+ // 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()
// CHECK: store i32 [[T0]], i32* @_ZZN5test21BC1EvE1x,
// CHECK: call void @__cxa_guard_release(i64* @_ZGVZN5test21BC1EvE1x)
- // CHECK-LABEL: define void @_ZN5test21BC2Ev
+ // 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()
@@ -122,15 +122,15 @@ namespace test2 {
B::~B() {
static int y = foo();
}
- // CHECK-LABEL: define void @_ZN5test21BD1Ev(
- // CHECK: call 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()
// CHECK: store i32 [[T0]], i32* @_ZZN5test21BD1EvE1y,
// CHECK: call void @__cxa_guard_release(i64* @_ZGVZN5test21BD1EvE1y)
+
+ // CHECK-LABEL: define void @_ZN5test21BD1Ev(
+ // CHECK: call void @_ZN5test21BD2Ev(
}
// This shouldn't error out.
@@ -149,6 +149,6 @@ namespace test3 {
union U { char x; int i; };
static U u = { 'a' };
}
- // CHECK-LABEL: define void @_ZN5test31BC1Ev(
// CHECK-LABEL: define void @_ZN5test31BC2Ev(
+ // CHECK-LABEL: define void @_ZN5test31BC1Ev(
}
diff --git a/test/CodeGenCXX/static-member-variable-explicit-specialization.cpp b/test/CodeGenCXX/static-member-variable-explicit-specialization.cpp
index 50772bf647d1..98c09b84797d 100644
--- a/test/CodeGenCXX/static-member-variable-explicit-specialization.cpp
+++ b/test/CodeGenCXX/static-member-variable-explicit-specialization.cpp
@@ -12,21 +12,21 @@ 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 }]
+// CHECK: @llvm.global_ctors = appending global [7 x { i32, void ()*, i8* }]
+// CHECK: [{ i32, void ()*, i8* } { i32 65535, void ()* @[[unordered1:[^,]*]], i8* bitcast (i32* @_ZN1AIsE1aE to i8*) },
+// CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @[[unordered2:[^,]*]], i8* bitcast (i16* @_Z1xIsE to i8*) },
+// CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @[[unordered3:[^,]*]], i8* bitcast (i32* @_ZN2ns1aIiE1iE to i8*) },
+// CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @[[unordered4:[^,]*]], i8* bitcast (i32* @_ZN2ns1b1iIiEE to i8*) },
+// CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @[[unordered5:[^,]*]], i8* bitcast (i32* @_ZN1AIvE1aE to i8*) },
+// CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @[[unordered6:[^,]*]], i8* @_Z1xIcE },
+// CHECK: { i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__sub_I_static_member_variable_explicit_specialization.cpp, i8* null }]
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.
+// An explicit specialization is ordered, and goes in __GLOBAL_sub_I_static_member_variable_explicit_specialization.cpp.
template<> struct A<int> { static int a; };
int A<int>::a = foo();
@@ -82,7 +82,7 @@ template int b::i<int>;
// CHECK: store {{.*}} @_Z1xIcE
// CHECK: ret
-// CHECK: define internal void @_GLOBAL__I_a()
+// CHECK: define internal void @_GLOBAL__sub_I_static_member_variable_explicit_specialization.cpp()
// We call unique stubs for every ordered dynamic initializer in the TU.
// CHECK: call
// CHECK: call
diff --git a/test/CodeGenCXX/stmtexpr.cpp b/test/CodeGenCXX/stmtexpr.cpp
index 5d4d6bcce458..7bf19bbfb46d 100644
--- a/test/CodeGenCXX/stmtexpr.cpp
+++ b/test/CodeGenCXX/stmtexpr.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -Wno-unused-value -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -Wno-unused-value -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck %s
// rdar: //8540501
extern "C" int printf(...);
extern "C" void abort();
diff --git a/test/CodeGenCXX/template-dependent-bind-temporary.cpp b/test/CodeGenCXX/template-dependent-bind-temporary.cpp
index ca980c3ff685..47d8279a4774 100644
--- a/test/CodeGenCXX/template-dependent-bind-temporary.cpp
+++ b/test/CodeGenCXX/template-dependent-bind-temporary.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -emit-llvm -triple %itanium_abi_triple -o - | FileCheck %s
// rdar: //8620524
// PR7851
struct string {
diff --git a/test/CodeGenCXX/template-inner-struct-visibility-hidden.cpp b/test/CodeGenCXX/template-inner-struct-visibility-hidden.cpp
index de86f10f6c30..137792b26a43 100644
--- a/test/CodeGenCXX/template-inner-struct-visibility-hidden.cpp
+++ b/test/CodeGenCXX/template-inner-struct-visibility-hidden.cpp
@@ -1,9 +1,9 @@
-// RUN: %clang_cc1 -fvisibility hidden -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -fvisibility hidden -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck %s
// Verify that symbols are hidden.
// CHECK: @_ZN1CIiE5Inner6Inner26StaticE = weak_odr hidden global
-// CHECK-LABEL: define weak_odr hidden void @_ZN1CIiE5Inner1fEv
-// CHECK-LABEL: 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 80283a1edd04..90b8099f0a26 100644
--- a/test/CodeGenCXX/template-instantiation.cpp
+++ b/test/CodeGenCXX/template-instantiation.cpp
@@ -5,10 +5,14 @@
//
// CHECK-NOT: @_ZTVN5test118stdio_sync_filebufIwEE = constant
// CHECK-NOT: _ZTVN5test315basic_fstreamXXIcEE
-// CHECK: @_ZTVN5test018stdio_sync_filebufIwEE = unnamed_addr constant
+// CHECK-NOT: @_ZTVN5test018stdio_sync_filebufIA1_iEE
+// CHECK-NOT: @_ZTVN5test018stdio_sync_filebufIA2_iEE
+// CHECK: @_ZTVN5test018stdio_sync_filebufIA3_iEE = weak_odr unnamed_addr constant
-// CHECK: @_ZN7PR100011SIiE3arrE = weak_odr global [3 x i32]
-// CHECK-NOT: @_ZN7PR100011SIiE3arr2E = weak_odr global [3 x i32]A
+// CHECK: @_ZN7PR100011SIiE3arrE = linkonce_odr global [3 x i32]
+// CHECK-NOT: @_ZN7PR100011SIiE3arr2E = linkonce_odr global [3 x i32]A
+
+// CHECK: @_ZTVN5test018stdio_sync_filebufIA4_iEE = linkonce_odr unnamed_addr constant
// CHECK-NOT: _ZTVN5test31SIiEE
// CHECK-NOT: _ZTSN5test31SIiEE
@@ -39,11 +43,21 @@ namespace test0 {
virtual void xsgetn();
};
- // This specialization should cause the vtable to be emitted, even with
- // the following extern template declaration.
- template<> void stdio_sync_filebuf<wchar_t>::xsgetn() {
+ // This specialization is not a key function, so doesn't cause the vtable to
+ // be instantiated unless we're instantiating a class definition anyway.
+ template<> void stdio_sync_filebuf<int[1]>::xsgetn() {
+ }
+ template<> void stdio_sync_filebuf<int[2]>::xsgetn() {
+ }
+ template<> void stdio_sync_filebuf<int[3]>::xsgetn() {
}
- extern template class stdio_sync_filebuf<wchar_t>;
+ template<> void stdio_sync_filebuf<int[4]>::xsgetn() {
+ }
+ extern template class stdio_sync_filebuf<int[2]>;
+
+ // These two both cause vtables to be emitted.
+ template class stdio_sync_filebuf<int[3]>;
+ stdio_sync_filebuf<int[4]> implicit_instantiation;
}
namespace test1 {
diff --git a/test/CodeGenCXX/temporaries.cpp b/test/CodeGenCXX/temporaries.cpp
index e8a7a1f25596..7f5c7af03865 100644
--- a/test/CodeGenCXX/temporaries.cpp
+++ b/test/CodeGenCXX/temporaries.cpp
@@ -3,8 +3,8 @@
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,
+ // 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
@@ -14,17 +14,32 @@ namespace PR16263 {
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
+ // 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
+ // 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
+ // CHECK: @_ZGRN7PR162631uE_ = private global {{.*}} zeroinitializer
+ // CHECK: @_ZN7PR162631uE = constant i32* {{.*}} @_ZGRN7PR162631uE_ {{.*}} 12
+}
+
+namespace PR20227 {
+ struct A { ~A(); };
+ struct B { virtual ~B(); };
+ struct C : B {};
+
+ A &&a = dynamic_cast<A&&>(A{});
+ // CHECK: @_ZGRN7PR202271aE_ = private global
+
+ B &&b = dynamic_cast<C&&>(dynamic_cast<B&&>(C{}));
+ // CHECK: @_ZGRN7PR202271bE_ = private global
+
+ B &&c = static_cast<C&&>(static_cast<B&&>(C{}));
+ // CHECK: @_ZGRN7PR202271cE_ = private global
}
struct A {
@@ -310,7 +325,7 @@ int& f(int);
void g() {
// CHECK: call void @_ZN3T121AC1Ev
// CHECK-NEXT: call i32 @_ZN3T121A1fEv(
- // CHECK-NEXT: call i32* @_ZN3T121fEi(
+ // CHECK-NEXT: call dereferenceable({{[0-9]+}}) i32* @_ZN3T121fEi(
// CHECK-NEXT: call void @_ZN3T121AD1Ev(
int& i = f(A().f());
}
@@ -325,7 +340,7 @@ namespace PR6648 {
struct D;
D& zed(B);
void foobar() {
- // CHECK: call %"struct.PR6648::D"* @_ZN6PR66483zedENS_1BE
+ // CHECK: call nonnull %"struct.PR6648::D"* @_ZN6PR66483zedENS_1BE
zed(foo);
}
}
@@ -412,10 +427,10 @@ namespace Elision {
// CHECK-NEXT: [[J:%.*]] = alloca [[A]], align 8
// CHECK: call void @_ZN7Elision1AC1Ev([[A]]* [[I]])
- // CHECK: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[I]], [[A]]* [[X:%.*]])
+ // CHECK: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[I]], [[A]]* dereferenceable({{[0-9]+}}) [[X:%.*]])
A i = (c ? A() : x);
- // CHECK: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[J]], [[A]]* [[X]])
+ // CHECK: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[J]], [[A]]* dereferenceable({{[0-9]+}}) [[X]])
// CHECK: call void @_ZN7Elision1AC1Ev([[A]]* [[J]])
A j = (c ? x : A());
@@ -435,10 +450,10 @@ namespace Elision {
A test3(int v, A x) {
if (v < 5)
// CHECK: call void @_ZN7Elision1AC1Ev([[A]]* [[RET:%.*]])
- // CHECK: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[RET]], [[A]]* [[X:%.*]])
+ // CHECK: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[RET]], [[A]]* dereferenceable({{[0-9]+}}) [[X:%.*]])
return (v < 0 ? A() : x);
else
- // CHECK: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[RET]], [[A]]* [[X]])
+ // CHECK: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[RET]], [[A]]* dereferenceable({{[0-9]+}}) [[X]])
// CHECK: call void @_ZN7Elision1AC1Ev([[A]]* [[RET]])
return (v > 10 ? x : A());
@@ -456,7 +471,7 @@ namespace Elision {
// CHECK-NEXT: [[XS0:%.*]] = getelementptr inbounds [2 x [[A]]]* [[XS]], i64 0, i64 0
// CHECK-NEXT: call void @_ZN7Elision1AC1Ev([[A]]* [[XS0]])
// CHECK-NEXT: [[XS1:%.*]] = getelementptr inbounds [[A]]* [[XS0]], i64 1
- // CHECK-NEXT: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[XS1]], [[A]]* [[X]])
+ // CHECK-NEXT: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[XS1]], [[A]]* dereferenceable({{[0-9]+}}) [[X]])
A xs[] = { A(), x };
// CHECK-NEXT: [[BEGIN:%.*]] = getelementptr inbounds [2 x [[A]]]* [[XS]], i32 0, i32 0
@@ -483,7 +498,7 @@ namespace Elision {
// CHECK: call void @_ZN7Elision1BC1Ev([[B]]* [[BT0]])
// CHECK-NEXT: [[AM:%.*]] = getelementptr inbounds [[B]]* [[BT0]], i32 0, i32 0
- // CHECK-NEXT: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[AT0]], [[A]]* [[AM]])
+ // CHECK-NEXT: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[AT0]], [[A]]* dereferenceable({{[0-9]+}}) [[AM]])
// CHECK-NEXT: call void @_ZN7Elision5takeAENS_1AE([[A]]* [[AT0]])
// CHECK-NEXT: call void @_ZN7Elision1AD1Ev([[A]]* [[AT0]])
// CHECK-NEXT: call void @_ZN7Elision1BD1Ev([[B]]* [[BT0]])
@@ -491,13 +506,13 @@ namespace Elision {
// CHECK-NEXT: call void @_ZN7Elision1BC1Ev([[B]]* [[BT1]])
// CHECK-NEXT: [[AM:%.*]] = getelementptr inbounds [[B]]* [[BT1]], i32 0, i32 0
- // CHECK-NEXT: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[X]], [[A]]* [[AM]])
+ // CHECK-NEXT: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[X]], [[A]]* dereferenceable({{[0-9]+}}) [[AM]])
// CHECK-NEXT: call void @_ZN7Elision1BD1Ev([[B]]* [[BT1]])
A x = B().a;
// CHECK-NEXT: call void @_ZN7Elision1BC1Ev([[B]]* [[BT2]])
// CHECK-NEXT: [[AM:%.*]] = getelementptr inbounds [[B]]* [[BT2]], i32 0, i32 0
- // CHECK-NEXT: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[RET:%.*]], [[A]]* [[AM]])
+ // CHECK-NEXT: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[RET:%.*]], [[A]]* dereferenceable({{[0-9]+}}) [[AM]])
// CHECK-NEXT: call void @_ZN7Elision1BD1Ev([[B]]* [[BT2]])
return B().a;
@@ -596,23 +611,23 @@ namespace BindToSubobject {
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
+ // 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
+ // 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 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
@@ -623,8 +638,8 @@ namespace BindToSubobject {
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 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
@@ -637,9 +652,9 @@ namespace Bitfield {
// Do not lifetime extend the S() temporary here.
// CHECK: alloca
// CHECK: call {{.*}}memset
- // CHECK: store i32 {{.*}}, i32* @_ZGRN8Bitfield1rE
+ // CHECK: store i32 {{.*}}, i32* @_ZGRN8Bitfield1rE_
// CHECK: call void @_ZN8Bitfield1SD1
- // CHECK: store i32* @_ZGRN8Bitfield1rE, i32** @_ZN8Bitfield1rE, align 8
+ // CHECK: store i32* @_ZGRN8Bitfield1rE_, i32** @_ZN8Bitfield1rE, align 8
int &&r = S().a;
}
@@ -652,14 +667,14 @@ namespace Vector {
};
// CHECK: alloca
// CHECK: extractelement
- // CHECK: store i32 {{.*}}, i32* @_ZGRN6Vector1rE
- // CHECK: store i32* @_ZGRN6Vector1rE, i32** @_ZN6Vector1rE,
+ // 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,
+ // 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;
@@ -761,8 +776,8 @@ namespace PR14130 {
struct S { S(int); };
struct U { S &&s; };
U v { { 0 } };
- // CHECK: call void @_ZN7PR141301SC1Ei({{.*}} @_ZGRN7PR141301vE, i32 0)
- // CHECK: store {{.*}} @_ZGRN7PR141301vE, {{.*}} @_ZN7PR141301vE
+ // CHECK: call void @_ZN7PR141301SC1Ei({{.*}} @_ZGRN7PR141301vE_, i32 0)
+ // CHECK: store {{.*}} @_ZGRN7PR141301vE_, {{.*}} @_ZN7PR141301vE
}
namespace Ctor {
diff --git a/test/CodeGenCXX/throw-expression-dtor.cpp b/test/CodeGenCXX/throw-expression-dtor.cpp
index cb4a6c69bddd..b883b856be3c 100644
--- a/test/CodeGenCXX/throw-expression-dtor.cpp
+++ b/test/CodeGenCXX/throw-expression-dtor.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -emit-llvm-only -verify -fcxx-exceptions -fexceptions
+// RUN: %clang_cc1 %s -emit-llvm-only -verify -triple %itanium_abi_triple -fcxx-exceptions -fexceptions
// expected-no-diagnostics
// PR7281
diff --git a/test/CodeGenCXX/throw-expressions.cpp b/test/CodeGenCXX/throw-expressions.cpp
index d9bf8fdd59ea..4dd5322fba51 100644
--- a/test/CodeGenCXX/throw-expressions.cpp
+++ b/test/CodeGenCXX/throw-expressions.cpp
@@ -67,3 +67,48 @@ int test6(bool x, bool y, int z) {
//
// end:
// CHECK: ret i32
+
+namespace DR1560 {
+ struct A {
+ ~A();
+ };
+ extern bool b;
+ A get();
+ // CHECK-LABEL: @_ZN6DR15601bE
+ const A &r = b ? get() : throw 0;
+ // CHECK-NOT: call {{.*}}@_ZN6DR15601AD1Ev
+ // CHECK: call {{.*}} @__cxa_atexit({{.*}} @_ZN6DR15601AD1Ev {{.*}} @_ZGRN6DR15601rE
+ // CHECK-NOT: call {{.*}}@_ZN6DR15601AD1Ev
+}
+
+// CHECK-LABEL: define void @_Z5test7b(
+void test7(bool cond) {
+ // CHECK: br i1
+ //
+ // x.true:
+ // CHECK: call void @__cxa_throw(
+ // CHECK-NEXT: unreachable
+ //
+ // x.false:
+ // CHECK: br label
+ //
+ // end:
+ // CHECK: ret void
+ cond ? throw test7 : val;
+}
+
+// CHECK-LABEL: define dereferenceable(4) i32* @_Z5test8b(
+int &test8(bool cond) {
+ // CHECK: br i1
+ //
+ // x.true:
+ // CHECK: br label
+ //
+ // x.false:
+ // CHECK: call void @__cxa_throw(
+ // CHECK-NEXT: unreachable
+ //
+ // end:
+ // CHECK: ret i32* @val
+ return cond ? val : ((throw "foo"));
+}
diff --git a/test/CodeGenCXX/thunk-use-after-free.cpp b/test/CodeGenCXX/thunk-use-after-free.cpp
index d70e9025683d..14f2356ea456 100644
--- a/test/CodeGenCXX/thunk-use-after-free.cpp
+++ b/test/CodeGenCXX/thunk-use-after-free.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm-only -O1 %s
+// RUN: %clang_cc1 -emit-llvm-only -triple %itanium_abi_triple -O1 %s
// This used to crash under asan and valgrind.
// PR12284
diff --git a/test/CodeGenCXX/thunks.cpp b/test/CodeGenCXX/thunks.cpp
index defb70681d93..89e4db394821 100644
--- a/test/CodeGenCXX/thunks.cpp
+++ b/test/CodeGenCXX/thunks.cpp
@@ -1,6 +1,5 @@
// 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 -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 {
@@ -251,9 +250,7 @@ namespace Test10 {
struct B { virtual void foo(); };
struct C : A, B { void foo() {} };
- // CHECK-HIDDEN-LABEL: define linkonce_odr void @_ZN6Test101C3fooEv
- // CHECK-HIDDEN-LABEL: define linkonce_odr hidden void @_ZThn8_N6Test101C3fooEv
-
+ // Test later.
void test() {
C c;
}
@@ -366,6 +363,10 @@ namespace Test15 {
/**** The following has to go at the end of the file ****/
+// This is from Test10:
+// CHECK-LABEL: define linkonce_odr void @_ZN6Test101C3fooEv
+// CHECK-LABEL: define linkonce_odr void @_ZThn8_N6Test101C3fooEv
+
// This is from Test5:
// CHECK-LABEL: define linkonce_odr void @_ZTv0_n24_N5Test51B1fEv
// CHECK-LABEL: define internal void @_ZThn8_N6Test4B12_GLOBAL__N_11C1fEv(
diff --git a/test/CodeGenCXX/tls-init-funcs.cpp b/test/CodeGenCXX/tls-init-funcs.cpp
index 17299dcb7b6c..d47329cdc29f 100644
--- a/test/CodeGenCXX/tls-init-funcs.cpp
+++ b/test/CodeGenCXX/tls-init-funcs.cpp
@@ -1,10 +1,34 @@
-// RUN: %clang_cc1 -triple x86_64-apple-macosx10.8 -std=c++11 -S -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.8 -std=c++1y -S -emit-llvm %s -o - | FileCheck %s
// CHECK: @a = internal thread_local global
+// CHECK: @_Z2vtIiE = internal thread_local global i32 5
+// CHECK: @_ZZ3inlvE3loc = linkonce_odr thread_local global i32 0
// CHECK: @_tlv_atexit({{.*}}@_ZN1AD1Ev
+// CHECK: call i32* @_ZTW3ext()
+// CHECK: declare i32* @_ZTW3ext()
+// CHECK: define weak i32* @_ZTW2vtIiE()
+// CHECK: define weak i32* @_ZTW2vtIvE()
+// CHECK: define {{.*}} @_ZTW1a
struct A {
~A();
};
thread_local A a;
+
+extern thread_local int ext;
+int &get_ext() { return ext; }
+
+template <typename T>
+thread_local int vt = 5;
+
+int get_vt() { return vt<int>; }
+
+inline int &inl() {
+ thread_local int loc;
+ return loc;
+}
+int &use_inl() { return inl(); }
+
+template int vt<void>;
+int &get_vt_void() { return vt<void>; }
diff --git a/test/CodeGenCXX/trivial-constructor-init.cpp b/test/CodeGenCXX/trivial-constructor-init.cpp
index 65ed45e259c5..9130e4e5d959 100644
--- a/test/CodeGenCXX/trivial-constructor-init.cpp
+++ b/test/CodeGenCXX/trivial-constructor-init.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm %s -o - -std=c++11 | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm %s -o - -std=c++11 -triple %itanium_abi_triple | FileCheck %s
extern "C" int printf(...);
diff --git a/test/CodeGenCXX/unary-type-trait.cpp b/test/CodeGenCXX/type-traits.cpp
index 3c6f9c03aa41..93cc6b56f1d2 100644
--- a/test/CodeGenCXX/unary-type-trait.cpp
+++ b/test/CodeGenCXX/type-traits.cpp
@@ -2,3 +2,5 @@
// expected-no-diagnostics
bool a() { return __is_pod(int); }
+
+bool b() { return __is_trivially_constructible(int, int, int); }
diff --git a/test/CodeGenCXX/type_visibility.cpp b/test/CodeGenCXX/type_visibility.cpp
index 11e5091fd279..a7b7198a23fa 100644
--- a/test/CodeGenCXX/type_visibility.cpp
+++ b/test/CodeGenCXX/type_visibility.cpp
@@ -29,11 +29,11 @@ namespace temp0 {
// 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
+ // VARS: @_ZTIN5temp01BINS_1AEEE = weak_odr constant
// 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
+ // VARS-HIDDEN: @_ZTIN5temp01BINS_1AEEE = weak_odr hidden constant
}
namespace temp1 {
@@ -46,11 +46,11 @@ namespace temp1 {
// 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
+ // VARS: @_ZTIN5temp11BINS_1AEEE = weak_odr constant
// 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
+ // VARS-HIDDEN: @_ZTIN5temp11BINS_1AEEE = weak_odr constant
}
namespace temp2 {
@@ -63,11 +63,11 @@ namespace temp2 {
// 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
+ // VARS: @_ZTIN5temp21BINS_1AEEE = weak_odr constant
// 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
+ // VARS-HIDDEN: @_ZTIN5temp21BINS_1AEEE = weak_odr hidden constant
}
namespace temp3 {
@@ -80,11 +80,11 @@ namespace temp3 {
// 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
+ // VARS: @_ZTIN5temp31BINS_1AEEE = weak_odr hidden constant
// 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
+ // VARS-HIDDEN: @_ZTIN5temp31BINS_1AEEE = weak_odr hidden constant
}
namespace temp4 {
@@ -97,11 +97,11 @@ namespace temp4 {
// 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
+ // VARS: @_ZTIN5temp41BINS_1AEEE = weak_odr hidden constant
// 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
+ // VARS-HIDDEN: @_ZTIN5temp41BINS_1AEEE = weak_odr hidden constant
}
namespace type0 {
@@ -113,11 +113,11 @@ namespace type0 {
// FUNS-LABEL: define void @_ZN5type01A3fooEv(
// VARS: @_ZTVN5type01AE = unnamed_addr constant
// VARS: @_ZTSN5type01AE = constant
- // VARS: @_ZTIN5type01AE = unnamed_addr constant
+ // VARS: @_ZTIN5type01AE = constant
// FUNS-HIDDEN-LABEL: define hidden void @_ZN5type01A3fooEv(
// VARS-HIDDEN: @_ZTVN5type01AE = unnamed_addr constant
// VARS-HIDDEN: @_ZTSN5type01AE = constant
- // VARS-HIDDEN: @_ZTIN5type01AE = unnamed_addr constant
+ // VARS-HIDDEN: @_ZTIN5type01AE = constant
}
namespace type1 {
@@ -129,11 +129,11 @@ namespace type1 {
// FUNS-LABEL: define hidden void @_ZN5type11A3fooEv(
// VARS: @_ZTVN5type11AE = unnamed_addr constant
// VARS: @_ZTSN5type11AE = constant
- // VARS: @_ZTIN5type11AE = unnamed_addr constant
+ // VARS: @_ZTIN5type11AE = constant
// FUNS-HIDDEN-LABEL: define hidden void @_ZN5type11A3fooEv(
// VARS-HIDDEN: @_ZTVN5type11AE = unnamed_addr constant
// VARS-HIDDEN: @_ZTSN5type11AE = constant
- // VARS-HIDDEN: @_ZTIN5type11AE = unnamed_addr constant
+ // VARS-HIDDEN: @_ZTIN5type11AE = constant
}
namespace type2 {
@@ -145,11 +145,11 @@ namespace type2 {
// FUNS-LABEL: define void @_ZN5type21A3fooEv(
// VARS: @_ZTVN5type21AE = hidden unnamed_addr constant
// VARS: @_ZTSN5type21AE = hidden constant
- // VARS: @_ZTIN5type21AE = hidden unnamed_addr constant
+ // VARS: @_ZTIN5type21AE = hidden constant
// 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
+ // VARS-HIDDEN: @_ZTIN5type21AE = hidden constant
}
namespace type3 {
@@ -161,10 +161,10 @@ namespace type3 {
// FUNS-LABEL: define void @_ZN5type31A3fooEv(
// VARS: @_ZTVN5type31AE = hidden unnamed_addr constant
// VARS: @_ZTSN5type31AE = hidden constant
- // VARS: @_ZTIN5type31AE = hidden unnamed_addr constant
+ // VARS: @_ZTIN5type31AE = hidden constant
// 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
+ // VARS-HIDDEN: @_ZTIN5type31AE = hidden constant
}
diff --git a/test/CodeGenCXX/typeid-should-throw.cpp b/test/CodeGenCXX/typeid-should-throw.cpp
new file mode 100644
index 000000000000..1d8fc85896af
--- /dev/null
+++ b/test/CodeGenCXX/typeid-should-throw.cpp
@@ -0,0 +1,82 @@
+// RUN: %clang_cc1 %s -triple %itanium_abi_triple -Wno-unused-value -emit-llvm -o - -std=c++11 | FileCheck %s
+namespace std {
+struct type_info;
+}
+
+struct A {
+ virtual ~A();
+ operator bool();
+};
+struct B : A {};
+
+void f1(A *x) { typeid(false, *x); }
+// CHECK-LABEL: define void @_Z2f1P1A
+// CHECK: icmp eq {{.*}}, null
+// CHECK-NEXT: br i1
+
+void f2(bool b, A *x, A *y) { typeid(b ? *x : *y); }
+// CHECK-LABEL: define void @_Z2f2bP1AS0_
+// CHECK: icmp eq {{.*}}, null
+// CHECK-NEXT: br i1
+
+void f3(bool b, A *x, A &y) { typeid(b ? *x : y); }
+// CHECK-LABEL: define void @_Z2f3bP1ARS_
+// CHECK: icmp eq {{.*}}, null
+// CHECK-NEXT: br i1
+
+void f4(bool b, A &x, A *y) { typeid(b ? x : *y); }
+// CHECK-LABEL: define void @_Z2f4bR1APS_
+// CHECK: icmp eq {{.*}}, null
+// CHECK-NEXT: br i1
+
+void f5(volatile A *x) { typeid(*x); }
+// CHECK-LABEL: define void @_Z2f5PV1A
+// CHECK: icmp eq {{.*}}, null
+// CHECK-NEXT: br i1
+
+void f6(A *x) { typeid((B &)*(B *)x); }
+// CHECK-LABEL: define void @_Z2f6P1A
+// CHECK: icmp eq {{.*}}, null
+// CHECK-NEXT: br i1
+
+void f7(A *x) { typeid((*x)); }
+// CHECK-LABEL: define void @_Z2f7P1A
+// CHECK: icmp eq {{.*}}, null
+// CHECK-NEXT: br i1
+
+void f8(A *x) { typeid(x[0]); }
+// CHECK-LABEL: define void @_Z2f8P1A
+// CHECK: icmp eq {{.*}}, null
+// CHECK-NEXT: br i1
+
+void f9(A *x) { typeid(0[x]); }
+// CHECK-LABEL: define void @_Z2f9P1A
+// CHECK: icmp eq {{.*}}, null
+// CHECK-NEXT: br i1
+
+void f10(A *x, A *y) { typeid(*y ?: *x); }
+// CHECK-LABEL: define void @_Z3f10P1AS0_
+// CHECK: icmp eq {{.*}}, null
+// CHECK-NEXT: br i1
+
+void f11(A *x, A &y) { typeid(*x ?: y); }
+// CHECK-LABEL: define void @_Z3f11P1ARS_
+// CHECK: icmp eq {{.*}}, null
+// CHECK-NEXT: br i1
+
+void f12(A &x, A *y) { typeid(x ?: *y); }
+// CHECK-LABEL: define void @_Z3f12R1APS_
+// CHECK: icmp eq {{.*}}, null
+// CHECK-NEXT: br i1
+
+void f13(A &x, A &y) { typeid(x ?: y); }
+// CHECK-LABEL: define void @_Z3f13R1AS0_
+// CHECK-NOT: icmp eq {{.*}}, null
+
+void f14(A *x) { typeid((const A &)(A)*x); }
+// CHECK-LABEL: define void @_Z3f14P1A
+// CHECK-NOT: icmp eq {{.*}}, null
+
+void f15(A *x) { typeid((A &&)*(A *)nullptr); }
+// CHECK-LABEL: define void @_Z3f15P1A
+// CHECK-NOT: icmp eq {{.*}}, null
diff --git a/test/CodeGenCXX/uncopyable-args.cpp b/test/CodeGenCXX/uncopyable-args.cpp
new file mode 100644
index 000000000000..77996f656e01
--- /dev/null
+++ b/test/CodeGenCXX/uncopyable-args.cpp
@@ -0,0 +1,206 @@
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-windows-msvc -emit-llvm -o - %s | FileCheck %s -check-prefix=WIN64
+
+namespace trivial {
+// Trivial structs should be passed directly.
+struct A {
+ void *p;
+};
+void foo(A);
+void bar() {
+ foo({});
+}
+// CHECK-LABEL: define void @_ZN7trivial3barEv()
+// CHECK: alloca %"struct.trivial::A"
+// CHECK: load i8**
+// CHECK: call void @_ZN7trivial3fooENS_1AE(i8* %{{.*}})
+// CHECK-LABEL: declare void @_ZN7trivial3fooENS_1AE(i8*)
+
+// WIN64-LABEL: declare void @"\01?foo@trivial@@YAXUA@1@@Z"(i64)
+}
+
+namespace default_ctor {
+struct A {
+ A();
+ void *p;
+};
+void foo(A);
+void bar() {
+ // Core issue 1590. We can pass this type in registers, even though C++
+ // normally doesn't permit copies when using braced initialization.
+ foo({});
+}
+// CHECK-LABEL: define void @_ZN12default_ctor3barEv()
+// CHECK: alloca %"struct.default_ctor::A"
+// CHECK: call void @_Z{{.*}}C1Ev(
+// CHECK: load i8**
+// CHECK: call void @_ZN12default_ctor3fooENS_1AE(i8* %{{.*}})
+// CHECK-LABEL: declare void @_ZN12default_ctor3fooENS_1AE(i8*)
+
+// WIN64-LABEL: declare void @"\01?foo@default_ctor@@YAXUA@1@@Z"(i64)
+}
+
+namespace move_ctor {
+// The presence of a move constructor implicitly deletes the trivial copy ctor
+// and means that we have to pass this struct by address.
+struct A {
+ A();
+ A(A &&o);
+ void *p;
+};
+void foo(A);
+void bar() {
+ foo({});
+}
+// FIXME: The copy ctor is implicitly deleted.
+// CHECK-DISABLED-LABEL: define void @_ZN9move_ctor3barEv()
+// CHECK-DISABLED: call void @_Z{{.*}}C1Ev(
+// CHECK-DISABLED-NOT: call
+// CHECK-DISABLED: call void @_ZN9move_ctor3fooENS_1AE(%"struct.move_ctor::A"* %{{.*}})
+// CHECK-DISABLED-LABEL: declare void @_ZN9move_ctor3fooENS_1AE(%"struct.move_ctor::A"*)
+
+// WIN64-LABEL: declare void @"\01?foo@move_ctor@@YAXUA@1@@Z"(%"struct.move_ctor::A"*)
+}
+
+namespace all_deleted {
+struct A {
+ A();
+ A(const A &o) = delete;
+ A(A &&o) = delete;
+ void *p;
+};
+void foo(A);
+void bar() {
+ foo({});
+}
+// FIXME: The copy ctor is deleted.
+// CHECK-DISABLED-LABEL: define void @_ZN11all_deleted3barEv()
+// CHECK-DISABLED: call void @_Z{{.*}}C1Ev(
+// CHECK-DISABLED-NOT call
+// CHECK-DISABLED: call void @_ZN11all_deleted3fooENS_1AE(%"struct.all_deleted::A"* %{{.*}})
+// CHECK-DISABLED-LABEL: declare void @_ZN11all_deleted3fooENS_1AE(%"struct.all_deleted::A"*)
+
+// WIN64-LABEL: declare void @"\01?foo@all_deleted@@YAXUA@1@@Z"(%"struct.all_deleted::A"*)
+}
+
+namespace implicitly_deleted {
+struct A {
+ A();
+ A &operator=(A &&o);
+ void *p;
+};
+void foo(A);
+void bar() {
+ foo({});
+}
+// FIXME: The copy and move ctors are implicitly deleted.
+// CHECK-DISABLED-LABEL: define void @_ZN18implicitly_deleted3barEv()
+// CHECK-DISABLED: call void @_Z{{.*}}C1Ev(
+// CHECK-DISABLED-NOT call
+// CHECK-DISABLED: call void @_ZN18implicitly_deleted3fooENS_1AE(%"struct.implicitly_deleted::A"* %{{.*}})
+// CHECK-DISABLED-LABEL: declare void @_ZN18implicitly_deleted3fooENS_1AE(%"struct.implicitly_deleted::A"*)
+
+// WIN64-LABEL: declare void @"\01?foo@implicitly_deleted@@YAXUA@1@@Z"(%"struct.implicitly_deleted::A"*)
+}
+
+namespace one_deleted {
+struct A {
+ A();
+ A(A &&o) = delete;
+ void *p;
+};
+void foo(A);
+void bar() {
+ foo({});
+}
+// FIXME: The copy constructor is implicitly deleted.
+// CHECK-DISABLED-LABEL: define void @_ZN11one_deleted3barEv()
+// CHECK-DISABLED: call void @_Z{{.*}}C1Ev(
+// CHECK-DISABLED-NOT call
+// CHECK-DISABLED: call void @_ZN11one_deleted3fooENS_1AE(%"struct.one_deleted::A"* %{{.*}})
+// CHECK-DISABLED-LABEL: declare void @_ZN11one_deleted3fooENS_1AE(%"struct.one_deleted::A"*)
+
+// WIN64-LABEL: declare void @"\01?foo@one_deleted@@YAXUA@1@@Z"(%"struct.one_deleted::A"*)
+}
+
+namespace copy_defaulted {
+struct A {
+ A();
+ A(const A &o) = default;
+ A(A &&o) = delete;
+ void *p;
+};
+void foo(A);
+void bar() {
+ foo({});
+}
+// CHECK-LABEL: define void @_ZN14copy_defaulted3barEv()
+// CHECK: call void @_Z{{.*}}C1Ev(
+// CHECK: load i8**
+// CHECK: call void @_ZN14copy_defaulted3fooENS_1AE(i8* %{{.*}})
+// CHECK-LABEL: declare void @_ZN14copy_defaulted3fooENS_1AE(i8*)
+
+// WIN64-LABEL: declare void @"\01?foo@copy_defaulted@@YAXUA@1@@Z"(i64)
+}
+
+namespace move_defaulted {
+struct A {
+ A();
+ A(const A &o) = delete;
+ A(A &&o) = default;
+ void *p;
+};
+void foo(A);
+void bar() {
+ foo({});
+}
+// CHECK-LABEL: define void @_ZN14move_defaulted3barEv()
+// CHECK: call void @_Z{{.*}}C1Ev(
+// CHECK: load i8**
+// CHECK: call void @_ZN14move_defaulted3fooENS_1AE(i8* %{{.*}})
+// CHECK-LABEL: declare void @_ZN14move_defaulted3fooENS_1AE(i8*)
+
+// WIN64-LABEL: declare void @"\01?foo@move_defaulted@@YAXUA@1@@Z"(%"struct.move_defaulted::A"*)
+}
+
+namespace trivial_defaulted {
+struct A {
+ A();
+ A(const A &o) = default;
+ void *p;
+};
+void foo(A);
+void bar() {
+ foo({});
+}
+// CHECK-LABEL: define void @_ZN17trivial_defaulted3barEv()
+// CHECK: call void @_Z{{.*}}C1Ev(
+// CHECK: load i8**
+// CHECK: call void @_ZN17trivial_defaulted3fooENS_1AE(i8* %{{.*}})
+// CHECK-LABEL: declare void @_ZN17trivial_defaulted3fooENS_1AE(i8*)
+
+// WIN64-LABEL: declare void @"\01?foo@trivial_defaulted@@YAXUA@1@@Z"(i64)
+}
+
+namespace two_copy_ctors {
+struct A {
+ A();
+ A(const A &) = default;
+ A(const A &, int = 0);
+ void *p;
+};
+struct B : A {};
+
+void foo(B);
+void bar() {
+ foo({});
+}
+// FIXME: This class has a non-trivial copy ctor and a trivial copy ctor. It's
+// not clear whether we should pass by address or in registers.
+// CHECK-DISABLED-LABEL: define void @_ZN14two_copy_ctors3barEv()
+// CHECK-DISABLED: call void @_Z{{.*}}C1Ev(
+// CHECK-DISABLED: call void @_ZN14two_copy_ctors3fooENS_1BE(%"struct.two_copy_ctors::B"* %{{.*}})
+// CHECK-DISABLED-LABEL: declare void @_ZN14two_copy_ctors3fooENS_1BE(%"struct.two_copy_ctors::B"*)
+
+// WIN64-LABEL: declare void @"\01?foo@two_copy_ctors@@YAXUB@1@@Z"(%"struct.two_copy_ctors::B"*)
+}
diff --git a/test/CodeGenCXX/value-init.cpp b/test/CodeGenCXX/value-init.cpp
index fad459b481bf..423d9736b4a8 100644
--- a/test/CodeGenCXX/value-init.cpp
+++ b/test/CodeGenCXX/value-init.cpp
@@ -262,6 +262,59 @@ namespace PR11124 {
void r170806_a(bool b = bool());
void r170806_b() { r170806_a(); }
+namespace PR20256 {
+ struct data { int i; };
+
+ template<typename T = int>
+ data g() {
+ data d; // not value-init
+ return d;
+ }
+ template data g();
+ // CHECK-LABEL: define {{.*}} @_ZN7PR202561gIiEENS_4dataEv(
+ // CHECK-NOT: store
+ // CHECK-NOT: memset
+ // CHECK: }
+
+ template<typename ...T>
+ data h(T ...t) {
+ data d(t...); // value-init
+ return d;
+ }
+ template data h();
+ // CHECK-LABEL: define {{.*}} @_ZN7PR202561hIJEEENS_4dataEDpT_(
+ // CHECK: call void @llvm.memset
+ // CHECK: }
+
+
+ template<typename T = int>
+ data j() {
+ data d = {}; // value-init
+ return d;
+ }
+ template data j();
+ // CHECK-LABEL: define {{.*}} @_ZN7PR202561jIiEENS_4dataEv(
+ // CHECK: call void @llvm.memset
+ // CHECK: }
+
+ data f() {
+ data d; // not value-init
+ return d;
+ }
+ // CHECK-LABEL: define {{.*}} @_ZN7PR202561fEv(
+ // CHECK-NOT: store
+ // CHECK-NOT: memset
+ // CHECK: }
+
+ data i() {
+ data d = {}; // value-init
+ return d;
+ }
+ // CHECK-LABEL: define {{.*}} @_ZN7PR202561iEv(
+ // CHECK: call void @llvm.memset
+ // CHECK: }
+}
+
// 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
diff --git a/test/CodeGenCXX/vararg-non-pod.cpp b/test/CodeGenCXX/vararg-non-pod.cpp
index 9497179ddf05..613b28c736f0 100644
--- a/test/CodeGenCXX/vararg-non-pod.cpp
+++ b/test/CodeGenCXX/vararg-non-pod.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -Wno-error=non-pod-varargs -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -Wno-error=non-pod-varargs -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck %s
struct X {
X();
diff --git a/test/CodeGenCXX/virt-dtor-gen.cpp b/test/CodeGenCXX/virt-dtor-gen.cpp
index 78a0b8193d74..ba836896c2cd 100644
--- a/test/CodeGenCXX/virt-dtor-gen.cpp
+++ b/test/CodeGenCXX/virt-dtor-gen.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -o - -emit-llvm %s | FileCheck %s
+// RUN: %clang_cc1 -o - -triple %itanium_abi_triple -emit-llvm %s | FileCheck %s
// PR5483
// Make sure we generate all three forms of the destructor when it is virtual.
@@ -7,4 +7,4 @@ class Foo {
};
Foo::~Foo() {}
-// CHECK-LABEL: define void @_ZN3FooD0Ev(%class.Foo* %this) unnamed_addr
+// CHECK-LABEL: define {{.*}}void @_ZN3FooD0Ev(%class.Foo* %this) unnamed_addr
diff --git a/test/CodeGenCXX/virt-dtor-key.cpp b/test/CodeGenCXX/virt-dtor-key.cpp
index a8fa371d3fa8..40c5a537cc53 100644
--- a/test/CodeGenCXX/virt-dtor-key.cpp
+++ b/test/CodeGenCXX/virt-dtor-key.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s
-// CHECK: @_ZTI3foo = unnamed_addr constant
+// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck %s
+// CHECK: @_ZTI3foo = constant
class foo {
foo();
virtual ~foo();
diff --git a/test/CodeGenCXX/virt-template-vtable.cpp b/test/CodeGenCXX/virt-template-vtable.cpp
index a6067d62c61d..a71db48a79a0 100644
--- a/test/CodeGenCXX/virt-template-vtable.cpp
+++ b/test/CodeGenCXX/virt-template-vtable.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %s
template<class T> class A {
public:
diff --git a/test/CodeGenCXX/virtual-base-cast.cpp b/test/CodeGenCXX/virtual-base-cast.cpp
index 40e68f672232..6a4894b63b70 100644
--- a/test/CodeGenCXX/virtual-base-cast.cpp
+++ b/test/CodeGenCXX/virtual-base-cast.cpp
@@ -1,5 +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
+// RUN: %clang_cc1 -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(); };
diff --git a/test/CodeGenCXX/virtual-base-ctor.cpp b/test/CodeGenCXX/virtual-base-ctor.cpp
index 2d81ebd3a407..8c28965c5c2f 100644
--- a/test/CodeGenCXX/virtual-base-ctor.cpp
+++ b/test/CodeGenCXX/virtual-base-ctor.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -emit-llvm -o - -O2 | FileCheck %s
+// RUN: %clang_cc1 %s -emit-llvm -triple %itanium_abi_triple -o - -O2 | FileCheck %s
struct B;
extern B x;
diff --git a/test/CodeGenCXX/virtual-base-destructor-call.cpp b/test/CodeGenCXX/virtual-base-destructor-call.cpp
index 5014eaf2643b..3d790715822e 100644
--- a/test/CodeGenCXX/virtual-base-destructor-call.cpp
+++ b/test/CodeGenCXX/virtual-base-destructor-call.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %s
struct basic_ios{~basic_ios(); };
diff --git a/test/CodeGenCXX/virtual-bases.cpp b/test/CodeGenCXX/virtual-bases.cpp
index 2878e95b52cd..e9c568c31b48 100644
--- a/test/CodeGenCXX/virtual-bases.cpp
+++ b/test/CodeGenCXX/virtual-bases.cpp
@@ -12,16 +12,16 @@ struct B : virtual A {
B();
};
-// CHECK-LABEL: define void @_ZN1BC1Ev(%struct.B* %this) unnamed_addr
// CHECK-LABEL: define void @_ZN1BC2Ev(%struct.B* %this, i8** %vtt) unnamed_addr
+// CHECK-LABEL: define void @_ZN1BC1Ev(%struct.B* %this) unnamed_addr
B::B() { }
struct C : virtual A {
C(bool);
};
-// 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
+// CHECK-LABEL: define void @_ZN1CC1Eb(%struct.C* %this, i1 zeroext) unnamed_addr
C::C(bool) { }
// PR6251
diff --git a/test/CodeGenCXX/virtual-destructor-calls.cpp b/test/CodeGenCXX/virtual-destructor-calls.cpp
index ae3704f36928..3e7fa8293af8 100644
--- a/test/CodeGenCXX/virtual-destructor-calls.cpp
+++ b/test/CodeGenCXX/virtual-destructor-calls.cpp
@@ -20,16 +20,16 @@ struct B : A {
// CHECK: @_ZN1CD1Ev = alias {{.*}} @_ZN1CD2Ev
// CHECK: @_ZN1CD2Ev = alias bitcast {{.*}} @_ZN1BD2Ev
-// Deleting dtor: defers to the complete dtor.
-// 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-LABEL: define void @_ZN1BD2Ev(%struct.B* %this) unnamed_addr
// CHECK: call void @_ZN6MemberD1Ev
// CHECK: call void @_ZN1AD2Ev
+// Deleting dtor: defers to the complete dtor.
+// CHECK-LABEL: define void @_ZN1BD0Ev(%struct.B* %this) unnamed_addr
+// CHECK: call void @_ZN1BD1Ev
+// CHECK: call void @_ZdlPv
+
B::~B() { }
struct C : B {
diff --git a/test/CodeGenCXX/virtual-destructor-synthesis.cpp b/test/CodeGenCXX/virtual-destructor-synthesis.cpp
index 90f66a817db1..80d1b1e4ec75 100644
--- a/test/CodeGenCXX/virtual-destructor-synthesis.cpp
+++ b/test/CodeGenCXX/virtual-destructor-synthesis.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %s
struct box {
virtual ~box();
diff --git a/test/CodeGenCXX/virtual-function-calls.cpp b/test/CodeGenCXX/virtual-function-calls.cpp
index e1b380fe7369..0a6fc6b3f284 100644
--- a/test/CodeGenCXX/virtual-function-calls.cpp
+++ b/test/CodeGenCXX/virtual-function-calls.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -std=c++11 -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -triple %itanium_abi_triple -std=c++11 -emit-llvm -o - | FileCheck %s
// PR5021
namespace PR5021 {
@@ -8,7 +8,7 @@ struct A {
};
void f(A *a) {
- // CHECK: call void %
+ // CHECK: call {{.*}}void %
a->f('c');
}
@@ -45,7 +45,7 @@ namespace VirtualNoreturn {
// CHECK: @_ZN15VirtualNoreturn1f
void f(A *p) {
p->f();
- // CHECK: call void %{{[^#]*$}}
+ // CHECK: call {{.*}}void %{{[^#]*$}}
// CHECK-NOT: unreachable
}
}
diff --git a/test/CodeGenCXX/virtual-implicit-copy-assignment.cpp b/test/CodeGenCXX/virtual-implicit-copy-assignment.cpp
index 70bc6fceb361..031046597e8b 100644
--- a/test/CodeGenCXX/virtual-implicit-copy-assignment.cpp
+++ b/test/CodeGenCXX/virtual-implicit-copy-assignment.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck %s
struct D;
struct B {
diff --git a/test/CodeGenCXX/virtual-implicit-move-assignment.cpp b/test/CodeGenCXX/virtual-implicit-move-assignment.cpp
index d8ac1ed4c489..7c28fb11215c 100644
--- a/test/CodeGenCXX/virtual-implicit-move-assignment.cpp
+++ b/test/CodeGenCXX/virtual-implicit-move-assignment.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm -std=c++11 -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -std=c++11 -o - %s | FileCheck %s
struct D;
struct B {
diff --git a/test/CodeGenCXX/virtual-inherited-destructor.cpp b/test/CodeGenCXX/virtual-inherited-destructor.cpp
index 509d40ae2fef..3ca7b6df8c3d 100644
--- a/test/CodeGenCXX/virtual-inherited-destructor.cpp
+++ b/test/CodeGenCXX/virtual-inherited-destructor.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -emit-llvm-only
+// RUN: %clang_cc1 %s -triple %itanium_abi_triple -emit-llvm-only
struct A { virtual ~A(); };
struct B : A {
diff --git a/test/CodeGenCXX/virtual-pseudo-destructor-call.cpp b/test/CodeGenCXX/virtual-pseudo-destructor-call.cpp
index 0d3574e46d33..b14a34d8b587 100644
--- a/test/CodeGenCXX/virtual-pseudo-destructor-call.cpp
+++ b/test/CodeGenCXX/virtual-pseudo-destructor-call.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %s
struct A {
virtual ~A();
diff --git a/test/CodeGenCXX/visibility-hidden-extern-templates.cpp b/test/CodeGenCXX/visibility-hidden-extern-templates.cpp
index 549e674740ff..95e8e089cc12 100644
--- a/test/CodeGenCXX/visibility-hidden-extern-templates.cpp
+++ b/test/CodeGenCXX/visibility-hidden-extern-templates.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -O1 -emit-llvm -o - -fvisibility hidden %s | FileCheck %s
+// RUN: %clang_cc1 -O1 -triple %itanium_abi_triple -emit-llvm -o - -fvisibility hidden %s | FileCheck %s
template<typename T>
struct X {
@@ -14,13 +14,13 @@ extern template struct X<char>;
// <rdar://problem/8109763>
void test_X(X<int> xi, X<char> xc) {
- // CHECK-LABEL: define weak_odr hidden void @_ZN1XIiE1fEv
+ // CHECK-LABEL: define weak_odr hidden {{.*}}void @_ZN1XIiE1fEv
xi.f();
- // CHECK-LABEL: define weak_odr hidden void @_ZN1XIiE1gEv
+ // CHECK-LABEL: define weak_odr hidden {{.*}}void @_ZN1XIiE1gEv
xi.g();
- // CHECK: declare void @_ZN1XIcE1fEv
+ // CHECK: declare {{.*}}void @_ZN1XIcE1fEv
xc.f();
- // CHECK-LABEL: define available_externally void @_ZN1XIcE1gEv
+ // CHECK-LABEL: define available_externally {{.*}}void @_ZN1XIcE1gEv
xc.g();
}
diff --git a/test/CodeGenCXX/visibility-ms-compat.cpp b/test/CodeGenCXX/visibility-ms-compat.cpp
index 25446cdf06f9..963b2a4e6d69 100644
--- a/test/CodeGenCXX/visibility-ms-compat.cpp
+++ b/test/CodeGenCXX/visibility-ms-compat.cpp
@@ -27,7 +27,7 @@ namespace test0 {
const std::type_info &ti = typeid(A);
// CHECK-GLOBAL: @_ZTSN5test01AE = linkonce_odr constant
- // CHECK-GLOBAL: @_ZTIN5test01AE = linkonce_odr unnamed_addr constant
+ // CHECK-GLOBAL: @_ZTIN5test01AE = linkonce_odr constant
// CHECK-GLOBAL: @_ZN5test02tiE = hidden constant
}
@@ -43,7 +43,7 @@ namespace test1 {
const std::type_info &ti = typeid(A);
// CHECK-GLOBAL: @_ZTSN5test11AE = linkonce_odr hidden constant
- // CHECK-GLOBAL: @_ZTIN5test11AE = linkonce_odr hidden unnamed_addr constant
+ // CHECK-GLOBAL: @_ZTIN5test11AE = linkonce_odr hidden constant
// CHECK-GLOBAL: @_ZN5test12tiE = hidden constant
}
@@ -59,7 +59,7 @@ namespace test2 {
const std::type_info &ti = typeid(A);
// CHECK-GLOBAL: @_ZTSN5test21AE = linkonce_odr constant
- // CHECK-GLOBAL: @_ZTIN5test21AE = linkonce_odr unnamed_addr constant
+ // CHECK-GLOBAL: @_ZTIN5test21AE = linkonce_odr constant
// CHECK-GLOBAL: @_ZN5test22tiE = hidden constant
}
@@ -76,7 +76,7 @@ namespace test3 {
const std::type_info &ti = typeid(B<A>);
// CHECK-GLOBAL: @_ZTSN5test31BINS_1AEEE = linkonce_odr constant
- // CHECK-GLOBAL: @_ZTIN5test31BINS_1AEEE = linkonce_odr unnamed_addr constant
+ // CHECK-GLOBAL: @_ZTIN5test31BINS_1AEEE = linkonce_odr constant
}
namespace test4 {
@@ -92,7 +92,7 @@ namespace test4 {
const std::type_info &ti = typeid(B<A>);
// CHECK-GLOBAL: @_ZTSN5test41BINS_1AEEE = linkonce_odr constant
- // CHECK-GLOBAL: @_ZTIN5test41BINS_1AEEE = linkonce_odr unnamed_addr constant
+ // CHECK-GLOBAL: @_ZTIN5test41BINS_1AEEE = linkonce_odr constant
}
namespace test5 {
@@ -108,5 +108,5 @@ namespace test5 {
const std::type_info &ti = typeid(B<A>);
// CHECK-GLOBAL: @_ZTSN5test51BINS_1AEEE = linkonce_odr hidden constant
- // CHECK-GLOBAL: @_ZTIN5test51BINS_1AEEE = linkonce_odr hidden unnamed_addr constant
+ // CHECK-GLOBAL: @_ZTIN5test51BINS_1AEEE = linkonce_odr hidden constant
}
diff --git a/test/CodeGenCXX/vla.cpp b/test/CodeGenCXX/vla.cpp
index b22f21c3faf3..a6616d374fed 100644
--- a/test/CodeGenCXX/vla.cpp
+++ b/test/CodeGenCXX/vla.cpp
@@ -9,7 +9,7 @@ template<typename T> int S<T>::n = 5;
int f() {
// Make sure that the reference here is enough to trigger the instantiation of
// the static data member.
- // CHECK: @_ZN1SIiE1nE = weak_odr global i32 5
+ // CHECK: @_ZN1SIiE1nE = linkonce_odr global i32 5
int a[S<int>::n];
return sizeof a;
}
diff --git a/test/CodeGenCXX/volatile-1.cpp b/test/CodeGenCXX/volatile-1.cpp
index 71ff1ed7d689..20389364b524 100644
--- a/test/CodeGenCXX/volatile-1.cpp
+++ b/test/CodeGenCXX/volatile-1.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -Wno-unused-value -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -Wno-unused-value -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck %s
// CHECK: @i = global [[INT:i[0-9]+]] 0
volatile int i, j, k;
@@ -248,11 +248,11 @@ void test() {
// gcc.
// Not a use. gcc forgets to do the assignment.
- // CHECK-NEXT: call
+ // CHECK-NEXT: call {{.*}}void
((a=a),a);
// Not a use. gcc gets this wrong, it doesn't emit the copy!
- // CHECK-NEXT: call
+ // CHECK-NEXT: call {{.*}}void
(void)(a=a);
// Not a use. gcc got this wrong in 4.2 and omitted the side effects
diff --git a/test/CodeGenCXX/volatile.cpp b/test/CodeGenCXX/volatile.cpp
index 38c8829347c2..f6ae0c525ab2 100644
--- a/test/CodeGenCXX/volatile.cpp
+++ b/test/CodeGenCXX/volatile.cpp
@@ -15,7 +15,7 @@ namespace test0 {
void test(A t) {
// CHECK: [[ARR:%.*]] = load [[A:%.*]]** @_ZN5test05arrayE, align 8
// CHECK-NEXT: [[IDX:%.*]] = getelementptr inbounds [[A]]* [[ARR]], i64 0
- // CHECK-NEXT: [[TMP:%.*]] = call [[A]]* @_ZNV5test01AaSERVKS0_([[A]]* [[IDX]], [[A]]* [[T:%.*]])
+ // CHECK-NEXT: [[TMP:%.*]] = call dereferenceable({{[0-9]+}}) [[A]]* @_ZNV5test01AaSERVKS0_([[A]]* [[IDX]], [[A]]* dereferenceable({{[0-9]+}}) [[T:%.*]])
// CHECK-NEXT: ret void
array[0] = t;
}
diff --git a/test/CodeGenCXX/vtable-available-externally.cpp b/test/CodeGenCXX/vtable-available-externally.cpp
index 282bd2a172ad..e07d48463f4f 100644
--- a/test/CodeGenCXX/vtable-available-externally.cpp
+++ b/test/CodeGenCXX/vtable-available-externally.cpp
@@ -35,7 +35,7 @@ void g() {
// updated correctly.
// CHECK-TEST2: @_ZTSN5Test21AE = constant
-// CHECK-TEST2: @_ZTIN5Test21AE = unnamed_addr constant
+// CHECK-TEST2: @_ZTIN5Test21AE = constant
// CHECK-TEST2: @_ZTVN5Test21AE = unnamed_addr constant
namespace Test2 {
struct A {
diff --git a/test/CodeGenCXX/vtable-cast-crash.cpp b/test/CodeGenCXX/vtable-cast-crash.cpp
index cc419fd4f522..58f9e0bf8f76 100644
--- a/test/CodeGenCXX/vtable-cast-crash.cpp
+++ b/test/CodeGenCXX/vtable-cast-crash.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm-only %s
+// RUN: %clang_cc1 -emit-llvm-only -triple %itanium_abi_triple %s
struct A
{
A();
diff --git a/test/CodeGenCXX/vtable-key-function-arm.cpp b/test/CodeGenCXX/vtable-key-function-arm.cpp
index 08efe8a141ea..6f1265b6277d 100644
--- a/test/CodeGenCXX/vtable-key-function-arm.cpp
+++ b/test/CodeGenCXX/vtable-key-function-arm.cpp
@@ -4,7 +4,7 @@
// The 'a' variants ask for the v-table first.
// The 'b' variants ask for the v-table second.
// The 'c' variants ask for the v-table third.
-// We do a separate CHECK-LATE pass because the RTTI defintion gets
+// We do a separate CHECK-LATE pass because the RTTI definition gets
// changed after the fact, which causes reordering of the globals.
// These are not separated into namespaces because the way that Sema
@@ -91,7 +91,7 @@ struct Test2a {
Test2a::Test2a() { use(typeid(Test2a)); }
// CHECK: @_ZTV6Test2a = unnamed_addr constant
// CHECK-LATE: @_ZTS6Test2a = constant
-// CHECK-LATE: @_ZTI6Test2a = unnamed_addr constant
+// CHECK-LATE: @_ZTI6Test2a = constant
// 'bar' becomes the key function when 'foo' is defined inline.
void Test2a::bar() {}
@@ -112,7 +112,7 @@ void Test2b::bar() {}
Test2b::Test2b() { use(typeid(Test2b)); }
// CHECK: @_ZTV6Test2b = unnamed_addr constant
// CHECK-LATE: @_ZTS6Test2b = constant
-// CHECK-LATE: @_ZTI6Test2b = unnamed_addr constant
+// CHECK-LATE: @_ZTI6Test2b = constant
inline void Test2b::foo() {}
@@ -132,7 +132,7 @@ inline void Test2c::foo() {}
Test2c::Test2c() { use(typeid(Test2c)); }
// CHECK: @_ZTV6Test2c = unnamed_addr constant
// CHECK: @_ZTS6Test2c = constant
-// CHECK: @_ZTI6Test2c = unnamed_addr constant
+// CHECK: @_ZTI6Test2c = constant
/*** Test3a ******************************************************************/
@@ -146,7 +146,7 @@ struct Test3a {
Test3a::Test3a() { use(typeid(Test3a)); }
// CHECK: @_ZTV6Test3a = linkonce_odr unnamed_addr constant
// CHECK-LATE: @_ZTS6Test3a = linkonce_odr constant
-// CHECK-LATE: @_ZTI6Test3a = linkonce_odr unnamed_addr constant
+// CHECK-LATE: @_ZTI6Test3a = linkonce_odr constant
// There ceases to be a key function after these declarations.
inline void Test3a::bar() {}
@@ -167,7 +167,7 @@ inline void Test3b::bar() {}
Test3b::Test3b() { use(typeid(Test3b)); }
// CHECK: @_ZTV6Test3b = linkonce_odr unnamed_addr constant
// CHECK-LATE: @_ZTS6Test3b = linkonce_odr constant
-// CHECK-LATE: @_ZTI6Test3b = linkonce_odr unnamed_addr constant
+// CHECK-LATE: @_ZTI6Test3b = linkonce_odr constant
inline void Test3b::foo() {}
@@ -187,7 +187,7 @@ inline void Test3c::foo() {}
Test3c::Test3c() { use(typeid(Test3c)); }
// CHECK: @_ZTV6Test3c = linkonce_odr unnamed_addr constant
// CHECK: @_ZTS6Test3c = linkonce_odr constant
-// CHECK: @_ZTI6Test3c = linkonce_odr unnamed_addr constant
+// CHECK: @_ZTI6Test3c = linkonce_odr constant
/*** Test4a ******************************************************************/
@@ -201,7 +201,7 @@ template <class T> struct Test4a {
template <> Test4a<int>::Test4a() { use(typeid(Test4a)); }
// CHECK: @_ZTV6Test4aIiE = linkonce_odr unnamed_addr constant
// CHECK: @_ZTS6Test4aIiE = linkonce_odr constant
-// CHECK: @_ZTI6Test4aIiE = linkonce_odr unnamed_addr constant
+// CHECK: @_ZTI6Test4aIiE = linkonce_odr constant
// There ceases to be a key function after these declarations.
template <> inline void Test4a<int>::bar() {}
@@ -222,7 +222,7 @@ template <> inline void Test4b<int>::bar() {}
template <> Test4b<int>::Test4b() { use(typeid(Test4b)); }
// CHECK: @_ZTV6Test4bIiE = linkonce_odr unnamed_addr constant
// CHECK: @_ZTS6Test4bIiE = linkonce_odr constant
-// CHECK: @_ZTI6Test4bIiE = linkonce_odr unnamed_addr constant
+// CHECK: @_ZTI6Test4bIiE = linkonce_odr constant
template <> inline void Test4b<int>::foo() {}
@@ -242,7 +242,7 @@ template <> inline void Test4c<int>::foo() {}
template <> Test4c<int>::Test4c() { use(typeid(Test4c)); }
// CHECK: @_ZTV6Test4cIiE = linkonce_odr unnamed_addr constant
// CHECK: @_ZTS6Test4cIiE = linkonce_odr constant
-// CHECK: @_ZTI6Test4cIiE = linkonce_odr unnamed_addr constant
+// CHECK: @_ZTI6Test4cIiE = linkonce_odr constant
/*** Test5a ******************************************************************/
@@ -259,7 +259,7 @@ template <> inline void Test5a<int>::foo();
template <> Test5a<int>::Test5a() { use(typeid(Test5a)); }
// CHECK: @_ZTV6Test5aIiE = linkonce_odr unnamed_addr constant
// CHECK: @_ZTS6Test5aIiE = linkonce_odr constant
-// CHECK: @_ZTI6Test5aIiE = linkonce_odr unnamed_addr constant
+// CHECK: @_ZTI6Test5aIiE = linkonce_odr constant
// There ceases to be a key function after these declarations.
template <> inline void Test5a<int>::bar() {}
@@ -281,7 +281,7 @@ template <> inline void Test5b<int>::bar() {}
template <> Test5b<int>::Test5b() { use(typeid(Test5b)); }
// CHECK: @_ZTV6Test5bIiE = linkonce_odr unnamed_addr constant
// CHECK: @_ZTS6Test5bIiE = linkonce_odr constant
-// CHECK: @_ZTI6Test5bIiE = linkonce_odr unnamed_addr constant
+// CHECK: @_ZTI6Test5bIiE = linkonce_odr constant
template <> inline void Test5a<int>::foo();
template <> inline void Test5b<int>::foo() {}
@@ -304,4 +304,4 @@ template <> inline void Test5c<int>::foo() {}
template <> Test5c<int>::Test5c() { use(typeid(Test5c)); }
// CHECK: @_ZTV6Test5cIiE = linkonce_odr unnamed_addr constant
// CHECK: @_ZTS6Test5cIiE = linkonce_odr constant
-// CHECK: @_ZTI6Test5cIiE = linkonce_odr unnamed_addr constant
+// CHECK: @_ZTI6Test5cIiE = linkonce_odr constant
diff --git a/test/CodeGenCXX/vtable-key-function-ios.cpp b/test/CodeGenCXX/vtable-key-function-ios.cpp
index bcd3e889d2ef..bf2e1f9720b5 100644
--- a/test/CodeGenCXX/vtable-key-function-ios.cpp
+++ b/test/CodeGenCXX/vtable-key-function-ios.cpp
@@ -4,7 +4,7 @@
// The 'a' variants ask for the v-table first.
// The 'b' variants ask for the v-table second.
// The 'c' variants ask for the v-table third.
-// We do a separate CHECK-LATE pass because the RTTI defintion gets
+// We do a separate CHECK-LATE pass because the RTTI definition gets
// changed after the fact, which causes reordering of the globals.
// These are not separated into namespaces because the way that Sema
@@ -59,7 +59,7 @@ struct Test1a {
Test1a::Test1a() { use(typeid(Test1a)); }
// CHECK: @_ZTV6Test1a = linkonce_odr unnamed_addr constant
// CHECK-LATE: @_ZTS6Test1a = linkonce_odr constant
-// CHECK-LATE: @_ZTI6Test1a = linkonce_odr unnamed_addr constant
+// CHECK-LATE: @_ZTI6Test1a = linkonce_odr constant
// This defines the key function.
inline void Test1a::foo() {}
@@ -79,7 +79,7 @@ inline void Test1b::foo() {}
Test1b::Test1b() { use(typeid(Test1b)); }
// CHECK: @_ZTV6Test1b = linkonce_odr unnamed_addr constant
// CHECK: @_ZTS6Test1b = linkonce_odr constant
-// CHECK: @_ZTI6Test1b = linkonce_odr unnamed_addr constant
+// CHECK: @_ZTI6Test1b = linkonce_odr constant
/*** Test2a ******************************************************************/
@@ -93,7 +93,7 @@ struct Test2a {
Test2a::Test2a() { use(typeid(Test2a)); }
// CHECK: @_ZTV6Test2a = linkonce_odr unnamed_addr constant
// CHECK-LATE: @_ZTS6Test2a = linkonce_odr constant
-// CHECK-LATE: @_ZTI6Test2a = linkonce_odr unnamed_addr constant
+// CHECK-LATE: @_ZTI6Test2a = linkonce_odr constant
void Test2a::bar() {}
inline void Test2a::foo() {}
@@ -112,7 +112,7 @@ void Test2b::bar() {}
Test2b::Test2b() { use(typeid(Test2b)); }
// CHECK: @_ZTV6Test2b = linkonce_odr unnamed_addr constant
// CHECK-LATE: @_ZTS6Test2b = linkonce_odr constant
-// CHECK-LATE: @_ZTI6Test2b = linkonce_odr unnamed_addr constant
+// CHECK-LATE: @_ZTI6Test2b = linkonce_odr constant
inline void Test2b::foo() {}
@@ -131,7 +131,7 @@ inline void Test2c::foo() {}
Test2c::Test2c() { use(typeid(Test2c)); }
// CHECK: @_ZTV6Test2c = linkonce_odr unnamed_addr constant
// CHECK: @_ZTS6Test2c = linkonce_odr constant
-// CHECK: @_ZTI6Test2c = linkonce_odr unnamed_addr constant
+// CHECK: @_ZTI6Test2c = linkonce_odr constant
/*** Test3a ******************************************************************/
@@ -145,7 +145,7 @@ struct Test3a {
Test3a::Test3a() { use(typeid(Test3a)); }
// CHECK: @_ZTV6Test3a = linkonce_odr unnamed_addr constant
// CHECK-LATE: @_ZTS6Test3a = linkonce_odr constant
-// CHECK-LATE: @_ZTI6Test3a = linkonce_odr unnamed_addr constant
+// CHECK-LATE: @_ZTI6Test3a = linkonce_odr constant
// This defines the key function.
inline void Test3a::bar() {}
@@ -165,7 +165,7 @@ inline void Test3b::bar() {}
Test3b::Test3b() { use(typeid(Test3b)); }
// CHECK: @_ZTV6Test3b = linkonce_odr unnamed_addr constant
// CHECK-LATE: @_ZTS6Test3b = linkonce_odr constant
-// CHECK-LATE: @_ZTI6Test3b = linkonce_odr unnamed_addr constant
+// CHECK-LATE: @_ZTI6Test3b = linkonce_odr constant
// This defines the key function.
inline void Test3b::foo() {}
@@ -186,4 +186,4 @@ inline void Test3c::foo() {}
Test3c::Test3c() { use(typeid(Test3c)); }
// CHECK: @_ZTV6Test3c = linkonce_odr unnamed_addr constant
// CHECK: @_ZTS6Test3c = linkonce_odr constant
-// CHECK: @_ZTI6Test3c = linkonce_odr unnamed_addr constant
+// CHECK: @_ZTI6Test3c = linkonce_odr constant
diff --git a/test/CodeGenCXX/vtable-layout-abi-examples.cpp b/test/CodeGenCXX/vtable-layout-abi-examples.cpp
index 8f084a9c5b7b..b8ac6f512b48 100644
--- a/test/CodeGenCXX/vtable-layout-abi-examples.cpp
+++ b/test/CodeGenCXX/vtable-layout-abi-examples.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 2>/dev/null
// RUN: FileCheck --check-prefix=CHECK-1 %s < %t
// RUN: FileCheck --check-prefix=CHECK-2 %s < %t
// RUN: FileCheck --check-prefix=CHECK-3 %s < %t
diff --git a/test/CodeGenCXX/vtable-linkage.cpp b/test/CodeGenCXX/vtable-linkage.cpp
index c17e33387e52..9c08b3037ca1 100644
--- a/test/CodeGenCXX/vtable-linkage.cpp
+++ b/test/CodeGenCXX/vtable-linkage.cpp
@@ -1,8 +1,6 @@
// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o %t
-// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -fhidden-weak-vtables -emit-llvm -o %t.hidden
// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -disable-llvm-optzns -O3 -emit-llvm -o %t.opt
// RUN: FileCheck --check-prefix=CHECK %s < %t
-// RUN: FileCheck --check-prefix=CHECK-HIDDEN %s < %t.hidden
// RUN: FileCheck --check-prefix=CHECK-OPT %s < %t.opt
namespace {
@@ -93,57 +91,47 @@ void use_F() {
// and hidden visibility (rdar://problem/7523229).
// CHECK-DAG: @_ZTV1C = linkonce_odr unnamed_addr constant
// CHECK-DAG: @_ZTS1C = linkonce_odr constant
-// CHECK-DAG: @_ZTI1C = linkonce_odr unnamed_addr constant
+// CHECK-DAG: @_ZTI1C = linkonce_odr 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-DAG: @_ZTV1D = unnamed_addr constant
// CHECK-DAG: @_ZTS1D = constant
-// CHECK-DAG: @_ZTI1D = unnamed_addr constant
+// CHECK-DAG: @_ZTI1D = constant
// E<char> is an explicit specialization with a key function defined
// in this translation unit, so its vtable should have external
// linkage.
// CHECK-DAG: @_ZTV1EIcE = unnamed_addr constant
// CHECK-DAG: @_ZTS1EIcE = constant
-// CHECK-DAG: @_ZTI1EIcE = unnamed_addr constant
+// CHECK-DAG: @_ZTI1EIcE = 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-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
+// CHECK-DAG: @_ZTI1EIsE = weak_odr constant
// F<short> is an explicit template instantiation without a key
// function, so its vtable should have weak_odr linkage
// 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
+// CHECK-DAG: @_ZTI1FIsE = weak_odr 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-DAG: @_ZTV1EIlE = linkonce_odr unnamed_addr constant
// CHECK-DAG: @_ZTS1EIlE = linkonce_odr constant
-// CHECK-DAG: @_ZTI1EIlE = linkonce_odr unnamed_addr constant
+// CHECK-DAG: @_ZTI1EIlE = linkonce_odr constant
// F<long> is an implicit template instantiation with no key function,
// so its vtable should have linkonce_odr linkage.
// CHECK-DAG: @_ZTV1FIlE = linkonce_odr unnamed_addr constant
// CHECK-DAG: @_ZTS1FIlE = linkonce_odr constant
-// CHECK-DAG: @_ZTI1FIlE = linkonce_odr unnamed_addr constant
+// CHECK-DAG: @_ZTI1FIlE = linkonce_odr constant
// F<int> is an explicit template instantiation declaration without a
// key function, so its vtable should have external linkage.
@@ -160,19 +148,19 @@ void use_F() {
// internal linkage.
// CHECK-DAG: @"_ZTV3$_0" = internal unnamed_addr constant
// CHECK-DAG: @"_ZTS3$_0" = internal constant
-// CHECK-DAG: @"_ZTI3$_0" = internal unnamed_addr constant
+// CHECK-DAG: @"_ZTI3$_0" = internal constant
// The A vtable should have internal linkage since it is inside an anonymous
// namespace.
// 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
+// CHECK-DAG: @_ZTIN12_GLOBAL__N_11AE = internal constant
// F<char> is an explicit specialization without a key function, so
// its vtable should have linkonce_odr linkage.
// CHECK-DAG: @_ZTV1FIcE = linkonce_odr unnamed_addr constant
// CHECK-DAG: @_ZTS1FIcE = linkonce_odr constant
-// CHECK-DAG: @_ZTI1FIcE = linkonce_odr unnamed_addr constant
+// CHECK-DAG: @_ZTI1FIcE = linkonce_odr constant
// CHECK-DAG: @_ZTV1GIiE = linkonce_odr unnamed_addr constant
template <typename T>
diff --git a/test/CodeGenCXX/weak-extern-typeinfo.cpp b/test/CodeGenCXX/weak-extern-typeinfo.cpp
index 3c3406e55970..38f6a3e46233 100644
--- a/test/CodeGenCXX/weak-extern-typeinfo.cpp
+++ b/test/CodeGenCXX/weak-extern-typeinfo.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -emit-llvm -triple %itanium_abi_triple -o - | FileCheck %s
// rdar://10246395
#define WEAK __attribute__ ((weak))
@@ -32,16 +32,16 @@ void V1::foo() { }
void V2::foo() { }
// CHECK: @_ZTS1A = weak_odr constant
-// CHECK: @_ZTI1A = weak_odr unnamed_addr constant
+// CHECK: @_ZTI1A = weak_odr constant
// CHECK: @_ZTS1B = weak_odr constant
-// CHECK: @_ZTI1B = weak_odr unnamed_addr constant
+// CHECK: @_ZTI1B = weak_odr constant
// CHECK: @_ZTS1C = weak_odr constant
// CHECK: @_ZTS2T1 = linkonce_odr constant
-// CHECK: @_ZTI2T1 = linkonce_odr unnamed_addr constant
+// CHECK: @_ZTI2T1 = linkonce_odr constant
// CHECK: @_ZTS1T = linkonce_odr constant
-// CHECK: @_ZTI1T = linkonce_odr unnamed_addr constant
-// CHECK: @_ZTI1C = weak_odr unnamed_addr constant
+// CHECK: @_ZTI1T = linkonce_odr constant
+// CHECK: @_ZTI1C = weak_odr constant
// CHECK: @_ZTS2V1 = weak_odr constant
-// CHECK: @_ZTI2V1 = weak_odr unnamed_addr constant
+// CHECK: @_ZTI2V1 = weak_odr constant
// CHECK: @_ZTS2V2 = weak_odr constant
-// CHECK: @_ZTI2V2 = weak_odr unnamed_addr constant
+// CHECK: @_ZTI2V2 = weak_odr constant
diff --git a/test/CodeGenCXX/weak-external.cpp b/test/CodeGenCXX/weak-external.cpp
index dad54f6861b0..a2c53a59dcd5 100644
--- a/test/CodeGenCXX/weak-external.cpp
+++ b/test/CodeGenCXX/weak-external.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang -fexceptions %s -S -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -triple %itanium_abi_triple %s -S -emit-llvm -o - | FileCheck %s
// PR4262
// CHECK-NOT: _ZNSs12_S_constructIPKcEEPcT_S3_RKSaIcESt20forward_iterator_tag
diff --git a/test/CodeGenCXX/windows-itanium-exceptions.cpp b/test/CodeGenCXX/windows-itanium-exceptions.cpp
new file mode 100644
index 000000000000..e2c4190ac9f6
--- /dev/null
+++ b/test/CodeGenCXX/windows-itanium-exceptions.cpp
@@ -0,0 +1,47 @@
+// RUN: %clang_cc1 -emit-llvm -triple thumbv7-windows-itanium -fexceptions -fcxx-exceptions %s -o - | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -triple i686-windows-itanium -fexceptions -fcxx-exceptions %s -o - | FileCheck %s
+// REQUIRES: asserts
+
+void except() {
+ throw 32;
+}
+
+void attempt() {
+ try { except(); } catch (...) { }
+}
+
+// CHECK: @_ZTIi = external constant i8*
+
+// CHECK: define {{.*}}void @_Z6exceptv() {{.*}} {
+// CHECK: %exception = call {{.*}}i8* @__cxa_allocate_exception(i32 4)
+// CHECK: %0 = bitcast i8* %exception to i32*
+// CHECK: store i32 32, i32* %0
+// CHECK: call {{.*}}void @__cxa_throw(i8* %exception, i8* bitcast (i8** @_ZTIi to i8*), i8* null)
+// CHECK: unreachable
+// CHECK: }
+
+// CHECK: define {{.*}}void @_Z7attemptv() {{.*}} {
+// CHECK: %exn.slot = alloca i8*
+// CHECK: %ehselector.slot = alloca i32
+// CHECK: invoke {{.*}}void @_Z6exceptv()
+// CHECK: to label %invoke.cont unwind label %lpad
+// CHECK: invoke.cont:
+// CHECK: br label %try.cont
+// CHECK: lpad:
+// CHECK: %0 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+// CHECK: catch i8* null
+// CHECK: %1 = extractvalue { i8*, i32 } %0, 0
+// CHECK: store i8* %1, i8** %exn.slot
+// CHECK: %2 = extractvalue { i8*, i32 } %0, 1
+// CHECK: store i32 %2, i32* %ehselector.slot
+// CHECK: br label %catch
+// CHECK: catch:
+// CHECK: %exn = load i8** %exn.slot
+// CHECK: %3 = call {{.*}}i8* @__cxa_begin_catch(i8* %{{2|exn}})
+// CHECK: call {{.*}}void @__cxa_end_catch()
+// CHECK: br label %try.cont
+// CHECK: try.cont:
+// CHECK: ret void
+// CHECK: }
+
+