From 486754660bb926339aefcf012a3f848592babb8b Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Sat, 28 Jul 2018 11:06:01 +0000 Subject: Vendor import of clang trunk r338150: https://llvm.org/svn/llvm-project/cfe/trunk@338150 --- .../Inputs/override-bit-field-layout.layout | 16 + test/CodeGenCXX/Inputs/std-compare.h | 437 ++++++++++++ test/CodeGenCXX/PR19955.cpp | 24 +- test/CodeGenCXX/PR26569.cpp | 14 +- test/CodeGenCXX/PR28220.cpp | 2 +- test/CodeGenCXX/PR37481.cpp | 17 + test/CodeGenCXX/abstract-class-ctors-dtors.cpp | 2 +- test/CodeGenCXX/address-space-cast.cpp | 15 + test/CodeGenCXX/address-space-ref.cpp | 6 +- test/CodeGenCXX/alignment.cpp | 48 +- test/CodeGenCXX/alloc-size.cpp | 34 + test/CodeGenCXX/amdgcn-func-arg.cpp | 94 +++ test/CodeGenCXX/amdgcn-string-literal.cpp | 28 + test/CodeGenCXX/amdgcn_declspec_get.cpp | 27 + test/CodeGenCXX/apple-kext-guard-variable.cpp | 2 +- test/CodeGenCXX/arm-swiftcall.cpp | 10 + test/CodeGenCXX/array-default-argument.cpp | 2 +- test/CodeGenCXX/assign-construct-memcpy.cpp | 30 +- test/CodeGenCXX/atomic-dllexport.cpp | 4 +- test/CodeGenCXX/atomic-inline.cpp | 61 +- test/CodeGenCXX/attr-target-mv-diff-ns.cpp | 54 ++ test/CodeGenCXX/attr-target-mv-func-ptrs.cpp | 45 ++ test/CodeGenCXX/attr-target-mv-member-funcs.cpp | 137 ++++ test/CodeGenCXX/attr-target-mv-modules.cpp | 29 + .../CodeGenCXX/attr-target-mv-out-of-line-defs.cpp | 39 ++ test/CodeGenCXX/attr-target-mv-overloads.cpp | 50 ++ test/CodeGenCXX/attr-x86-interrupt.cpp | 12 +- test/CodeGenCXX/block-capture.cpp | 13 + test/CodeGenCXX/block-inalloca.cpp | 11 + test/CodeGenCXX/builtin-operator-new-delete.cpp | 71 ++ test/CodeGenCXX/builtins.cpp | 16 + test/CodeGenCXX/captured-statements.cpp | 2 +- test/CodeGenCXX/catch-undef-behavior.cpp | 6 +- test/CodeGenCXX/cfi-cross-dso.cpp | 2 +- test/CodeGenCXX/cfi-icall.cpp | 2 +- test/CodeGenCXX/cfi-mfcall-incomplete.cpp | 12 + test/CodeGenCXX/cfi-mfcall.cpp | 30 + test/CodeGenCXX/cfi-ms-vbase-derived-cast.cpp | 2 +- test/CodeGenCXX/cfi-ms-vbase-nvcall.cpp | 2 +- test/CodeGenCXX/cfi-vcall-check-after-args.cpp | 12 + test/CodeGenCXX/char8_t.cpp | 9 + test/CodeGenCXX/code-seg.cpp | 139 ++++ test/CodeGenCXX/code-seg1.cpp | 87 +++ test/CodeGenCXX/code-seg2.cpp | 111 +++ test/CodeGenCXX/code-seg3.cpp | 65 ++ test/CodeGenCXX/conditional-temporaries.cpp | 2 + test/CodeGenCXX/const-base-cast.cpp | 2 +- test/CodeGenCXX/const-global-linkage.cpp | 4 +- test/CodeGenCXX/const-init-cxx11.cpp | 2 +- test/CodeGenCXX/constructor-alias.cpp | 2 +- .../constructor-destructor-return-this.cpp | 12 +- test/CodeGenCXX/constructor-direct-call.cpp | 4 +- test/CodeGenCXX/constructors.cpp | 15 +- test/CodeGenCXX/copy-constructor-elim.cpp | 2 +- test/CodeGenCXX/copy-constructor-synthesis-2.cpp | 6 +- test/CodeGenCXX/copy-constructor-synthesis.cpp | 4 +- test/CodeGenCXX/ctor-dtor-alias.cpp | 55 +- test/CodeGenCXX/cxx0x-delegating-ctors.cpp | 2 +- test/CodeGenCXX/cxx0x-initializer-array.cpp | 2 +- test/CodeGenCXX/cxx0x-initializer-references.cpp | 2 +- .../cxx0x-initializer-stdinitializerlist.cpp | 90 +-- test/CodeGenCXX/cxx11-initializer-aggregate.cpp | 68 ++ test/CodeGenCXX/cxx11-initializer-array-new.cpp | 2 +- test/CodeGenCXX/cxx11-thread-local.cpp | 12 +- test/CodeGenCXX/cxx1z-aligned-allocation.cpp | 14 +- test/CodeGenCXX/cxx1z-eval-order.cpp | 6 +- test/CodeGenCXX/cxx1z-initializer-aggregate.cpp | 18 + test/CodeGenCXX/cxx1z-inline-variables.cpp | 34 + test/CodeGenCXX/cxx1z-lambda-star-this.cpp | 6 +- test/CodeGenCXX/cxx2a-compare.cpp | 188 ++++++ test/CodeGenCXX/cxx2a-destroying-delete.cpp | 24 +- test/CodeGenCXX/debug-info-access.cpp | 2 +- test/CodeGenCXX/debug-info-class-nolimit.cpp | 2 +- test/CodeGenCXX/debug-info-codeview-unnamed.cpp | 108 +++ .../debug-info-codeview-var-templates.cpp | 35 + test/CodeGenCXX/debug-info-composite-cc.cpp | 50 ++ test/CodeGenCXX/debug-info-enum-class.cpp | 6 +- test/CodeGenCXX/debug-info-enum.cpp | 2 +- test/CodeGenCXX/debug-info-line-if.cpp | 2 +- test/CodeGenCXX/debug-info-ms-dtor-thunks.cpp | 12 +- test/CodeGenCXX/debug-info-ms-vbase.cpp | 8 +- test/CodeGenCXX/debug-info-range-for-var-names.cpp | 35 + test/CodeGenCXX/debug-info-scope.cpp | 2 +- test/CodeGenCXX/debug-info-static-member.cpp | 6 +- test/CodeGenCXX/debug-info-template.cpp | 6 +- test/CodeGenCXX/debug-info-thunk-msabi.cpp | 4 +- test/CodeGenCXX/debug-info-thunk.cpp | 302 ++++++++- test/CodeGenCXX/debug-info-vla.cpp | 6 +- test/CodeGenCXX/debug-info-windows-dtor.cpp | 4 +- test/CodeGenCXX/delayed-template-parsing.cpp | 4 +- test/CodeGenCXX/derived-cast.cpp | 27 + test/CodeGenCXX/destructors.cpp | 12 +- test/CodeGenCXX/devirtualize-ms-dtor.cpp | 16 + test/CodeGenCXX/discard-name-values.cpp | 33 +- test/CodeGenCXX/dllexport-alias.cpp | 4 +- test/CodeGenCXX/dllexport-ctor-closure.cpp | 30 +- test/CodeGenCXX/dllexport-dtor-thunks.cpp | 4 +- test/CodeGenCXX/dllexport-members.cpp | 660 +++++++++--------- test/CodeGenCXX/dllexport-ms-friend.cpp | 2 +- test/CodeGenCXX/dllexport-pr26549.cpp | 2 +- test/CodeGenCXX/dllexport-vtable-thunks.cpp | 4 +- test/CodeGenCXX/dllexport.cpp | 572 ++++++++-------- test/CodeGenCXX/dllimport-dtor-thunks.cpp | 20 +- test/CodeGenCXX/dllimport-members.cpp | 684 +++++++++---------- test/CodeGenCXX/dllimport-memptr-global.cpp | 24 +- test/CodeGenCXX/dllimport-missing-key.cpp | 20 + test/CodeGenCXX/dllimport-rtti.cpp | 22 +- test/CodeGenCXX/dllimport-template-sdm.cpp | 53 ++ test/CodeGenCXX/dllimport.cpp | 424 ++++++------ test/CodeGenCXX/dso-local-executable.cpp | 62 ++ test/CodeGenCXX/duplicate-mangled-name.cpp | 10 +- test/CodeGenCXX/eh.cpp | 8 +- test/CodeGenCXX/exceptions-cxx-ehsc.cpp | 8 +- test/CodeGenCXX/exceptions-cxx-new.cpp | 26 +- test/CodeGenCXX/exceptions-seh-filter-captures.cpp | 22 +- test/CodeGenCXX/exceptions-seh.cpp | 42 +- test/CodeGenCXX/explicit-instantiation.cpp | 4 +- test/CodeGenCXX/extern-c.cpp | 16 +- test/CodeGenCXX/finegrain-bitfield-type.cpp | 22 + test/CodeGenCXX/float128-declarations.cpp | 4 + test/CodeGenCXX/float16-declarations.cpp | 26 +- test/CodeGenCXX/funcsig.cpp | 14 +- test/CodeGenCXX/global-llvm-constant.cpp | 4 +- test/CodeGenCXX/hidden-dllimport.cpp | 10 + test/CodeGenCXX/homogeneous-aggregates.cpp | 8 +- test/CodeGenCXX/inheriting-constructor.cpp | 176 ++--- test/CodeGenCXX/initializer-list-ctor-order.cpp | 4 +- test/CodeGenCXX/inline-dllexport-member.cpp | 4 +- test/CodeGenCXX/inline-functions.cpp | 36 +- test/CodeGenCXX/inline-hint.cpp | 6 +- test/CodeGenCXX/internal-linkage.cpp | 2 +- test/CodeGenCXX/invariant.group-for-vptrs.cpp | 2 +- .../lambda-expressions-inside-auto-functions.cpp | 9 +- .../lambda-to-function-pointer-conversion.cpp | 18 + test/CodeGenCXX/linetable-eh.cpp | 2 +- test/CodeGenCXX/mangle-abi-tag.cpp | 4 +- test/CodeGenCXX/mangle-mingw.cpp | 19 + test/CodeGenCXX/mangle-ms-abi-examples.cpp | 8 +- test/CodeGenCXX/mangle-ms-arg-qualifiers.cpp | 252 +++---- .../mangle-ms-back-references-pr13207.cpp | 66 +- test/CodeGenCXX/mangle-ms-back-references.cpp | 34 +- test/CodeGenCXX/mangle-ms-cxx11.cpp | 176 ++--- test/CodeGenCXX/mangle-ms-cxx14.cpp | 34 +- test/CodeGenCXX/mangle-ms-md5.cpp | 6 +- test/CodeGenCXX/mangle-ms-return-qualifiers.cpp | 118 ++-- test/CodeGenCXX/mangle-ms-string-literals.cpp | 746 +++++++++++---------- test/CodeGenCXX/mangle-ms-template-callback.cpp | 36 +- test/CodeGenCXX/mangle-ms-templates-memptrs-2.cpp | 18 +- test/CodeGenCXX/mangle-ms-templates-memptrs.cpp | 60 +- test/CodeGenCXX/mangle-ms-templates.cpp | 156 ++--- test/CodeGenCXX/mangle-ms-vector-types.cpp | 81 ++- test/CodeGenCXX/mangle-ms.cpp | 236 +++---- test/CodeGenCXX/mangle-windows.cpp | 28 +- test/CodeGenCXX/member-function-pointer-calls.cpp | 4 +- test/CodeGenCXX/microsoft-abi-arg-order.cpp | 44 +- test/CodeGenCXX/microsoft-abi-array-cookies.cpp | 18 +- test/CodeGenCXX/microsoft-abi-byval-sret.cpp | 16 +- test/CodeGenCXX/microsoft-abi-byval-thunks.cpp | 24 +- test/CodeGenCXX/microsoft-abi-byval-vararg.cpp | 16 +- .../CodeGenCXX/microsoft-abi-cdecl-method-sret.cpp | 16 +- .../microsoft-abi-constexpr-vs-inheritance.cpp | 4 +- test/CodeGenCXX/microsoft-abi-default-cc.cpp | 14 +- test/CodeGenCXX/microsoft-abi-dynamic-cast.cpp | 36 +- test/CodeGenCXX/microsoft-abi-eh-catch.cpp | 26 +- test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp | 154 +++-- test/CodeGenCXX/microsoft-abi-eh-inlineasm.cpp | 18 + test/CodeGenCXX/microsoft-abi-eh-terminate.cpp | 6 +- test/CodeGenCXX/microsoft-abi-emit-dependent.cpp | 11 + test/CodeGenCXX/microsoft-abi-extern-template.cpp | 14 +- test/CodeGenCXX/microsoft-abi-member-pointers.cpp | 282 +++++--- test/CodeGenCXX/microsoft-abi-methods.cpp | 32 +- ...crosoft-abi-multiple-nonvirtual-inheritance.cpp | 55 +- test/CodeGenCXX/microsoft-abi-rtti.cpp | 476 ++++++------- test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp | 227 +++---- .../microsoft-abi-static-initializers.cpp | 98 +-- test/CodeGenCXX/microsoft-abi-structors-alias.cpp | 8 +- .../microsoft-abi-structors-delayed-template.cpp | 2 +- test/CodeGenCXX/microsoft-abi-structors.cpp | 134 ++-- .../microsoft-abi-thread-safe-statics.cpp | 56 +- test/CodeGenCXX/microsoft-abi-throw.cpp | 60 +- test/CodeGenCXX/microsoft-abi-thunks.cpp | 76 +-- test/CodeGenCXX/microsoft-abi-try-throw.cpp | 12 +- test/CodeGenCXX/microsoft-abi-typeid.cpp | 26 +- test/CodeGenCXX/microsoft-abi-vbtables.cpp | 376 +++++------ test/CodeGenCXX/microsoft-abi-vftables.cpp | 34 +- ...microsoft-abi-virtual-inheritance-vtordisps.cpp | 15 +- .../microsoft-abi-virtual-inheritance.cpp | 143 ++-- .../microsoft-abi-virtual-member-pointers.cpp | 48 +- .../CodeGenCXX/microsoft-abi-vmemptr-conflicts.cpp | 32 +- test/CodeGenCXX/microsoft-abi-vmemptr-fastcall.cpp | 2 +- test/CodeGenCXX/microsoft-abi-vmemptr-vbase.cpp | 2 +- ...s-multiple-nonvirtual-inheritance-no-thunks.cpp | 22 +- ...ultiple-nonvirtual-inheritance-pure-virtual.cpp | 4 +- ...le-nonvirtual-inheritance-return-adjustment.cpp | 2 +- ...iple-nonvirtual-inheritance-this-adjustment.cpp | 28 +- .../microsoft-abi-vtables-return-thunks.cpp | 60 +- .../microsoft-abi-vtables-single-inheritance.cpp | 18 +- ...t-abi-vtables-virtual-inheritance-vtordisps.cpp | 70 +- .../microsoft-abi-vtables-virtual-inheritance.cpp | 112 ++-- test/CodeGenCXX/microsoft-compatibility.cpp | 8 +- test/CodeGenCXX/microsoft-inaccessible-base.cpp | 4 +- test/CodeGenCXX/microsoft-interface.cpp | 14 +- test/CodeGenCXX/microsoft-new.cpp | 8 +- test/CodeGenCXX/microsoft-no-rtti-data.cpp | 6 +- test/CodeGenCXX/microsoft-templ-uuidof.cpp | 12 +- test/CodeGenCXX/microsoft-uuidof.cpp | 20 +- test/CodeGenCXX/mingw-new-abi.cpp | 4 +- test/CodeGenCXX/mingw-w64-seh-exceptions.cpp | 4 +- test/CodeGenCXX/ms-eh-personality.cpp | 20 - test/CodeGenCXX/ms-inline-asm-return.cpp | 16 +- .../ms-integer-static-data-members-exported.cpp | 4 +- test/CodeGenCXX/ms-integer-static-data-members.cpp | 14 +- test/CodeGenCXX/ms-novtable.cpp | 10 +- test/CodeGenCXX/ms-property.cpp | 48 +- test/CodeGenCXX/ms-thread_local.cpp | 10 +- test/CodeGenCXX/ms-thunks-unprototyped-return.cpp | 15 + test/CodeGenCXX/ms-thunks-unprototyped.cpp | 73 ++ test/CodeGenCXX/ms_wide_predefined_expr.cpp | 2 +- test/CodeGenCXX/msabi-blocks.cpp | 56 +- test/CodeGenCXX/msabi-swiftcall-cc.cpp | 67 ++ test/CodeGenCXX/naked.cpp | 2 +- test/CodeGenCXX/new-array-init.cpp | 10 +- test/CodeGenCXX/no-opt-volatile-memcpy.cpp | 12 +- test/CodeGenCXX/optnone-pragma-optimize-off.cpp | 16 + test/CodeGenCXX/override-bit-field-layout.cpp | 20 + test/CodeGenCXX/personality.cpp | 42 ++ test/CodeGenCXX/pod-member-memcpys.cpp | 68 +- test/CodeGenCXX/pr20719.cpp | 4 +- test/CodeGenCXX/pr20897.cpp | 8 +- test/CodeGenCXX/pr27030.cpp | 2 +- test/CodeGenCXX/pr28360.cpp | 6 +- test/CodeGenCXX/pr30731.cpp | 2 +- test/CodeGenCXX/pr33080.cpp | 18 +- test/CodeGenCXX/pragma-init_seg.cpp | 32 +- test/CodeGenCXX/pragma-weak.cpp | 2 +- test/CodeGenCXX/reference-init.cpp | 10 +- test/CodeGenCXX/regcall.cpp | 52 +- test/CodeGenCXX/rtti-fundamental.cpp | 71 +- test/CodeGenCXX/rtti-hidden.cpp | 10 + test/CodeGenCXX/rtti-mingw64.cpp | 4 +- test/CodeGenCXX/runtime-dllstorage.cpp | 85 +-- test/CodeGenCXX/sanitize-no-dtor-callback.cpp | 6 +- test/CodeGenCXX/sections.cpp | 44 +- .../specialized-static-data-mem-init.cpp | 4 +- test/CodeGenCXX/split-stacks.cpp | 12 +- test/CodeGenCXX/stack-reuse-exceptions.cpp | 189 ++++++ test/CodeGenCXX/stack-reuse-miscompile.cpp | 36 +- test/CodeGenCXX/strict-vtable-pointers.cpp | 353 ++++++++-- test/CodeGenCXX/tail-padding.cpp | 34 + test/CodeGenCXX/temporaries.cpp | 123 +++- test/CodeGenCXX/trap-fnattr.cpp | 12 +- test/CodeGenCXX/trivial_abi.cpp | 239 +++++++ test/CodeGenCXX/type-metadata-memfun.cpp | 31 + test/CodeGenCXX/type-metadata.cpp | 71 +- test/CodeGenCXX/ubsan-ctor-srcloc.cpp | 26 + test/CodeGenCXX/ubsan-devirtualized-calls.cpp | 10 +- test/CodeGenCXX/ubsan-function-noexcept.cpp | 15 + test/CodeGenCXX/ubsan-vtable-checks.cpp | 10 +- test/CodeGenCXX/unaligned-member-qualifier.cpp | 8 +- test/CodeGenCXX/uncopyable-args.cpp | 46 +- test/CodeGenCXX/value-init.cpp | 24 +- test/CodeGenCXX/vararg-non-pod-ms-compat.cpp | 6 +- test/CodeGenCXX/varargs.cpp | 2 +- test/CodeGenCXX/virt-template-vtable.cpp | 8 +- test/CodeGenCXX/virtual-base-cast.cpp | 8 +- test/CodeGenCXX/virtual-base-ctor.cpp | 2 +- test/CodeGenCXX/virtual-bases.cpp | 36 +- test/CodeGenCXX/virtual-destructor-calls.cpp | 6 +- test/CodeGenCXX/virtual-function-attrs.cpp | 6 +- test/CodeGenCXX/virtual-function-calls.cpp | 2 +- test/CodeGenCXX/visibility-pr36810.cpp | 23 + test/CodeGenCXX/vla-consruct.cpp | 4 + test/CodeGenCXX/vla.cpp | 32 +- test/CodeGenCXX/volatile-1.cpp | 4 +- test/CodeGenCXX/vtable-assume-load.cpp | 4 +- test/CodeGenCXX/vtable-available-externally.cpp | 154 ++++- test/CodeGenCXX/vtable-key-function-ios.cpp | 56 +- test/CodeGenCXX/vtable-key-function-win-comdat.cpp | 6 +- test/CodeGenCXX/wasm-eh.cpp | 384 +++++++++++ test/CodeGenCXX/weak-extern-typeinfo.cpp | 28 +- ...-implicit-dllexport-template-specialization.cpp | 4 +- test/CodeGenCXX/windows-itanium-exceptions.cpp | 2 +- test/CodeGenCXX/windows-itanium-type-info.cpp | 18 +- 283 files changed, 9532 insertions(+), 4621 deletions(-) create mode 100644 test/CodeGenCXX/Inputs/override-bit-field-layout.layout create mode 100644 test/CodeGenCXX/Inputs/std-compare.h create mode 100644 test/CodeGenCXX/PR37481.cpp create mode 100644 test/CodeGenCXX/address-space-cast.cpp create mode 100644 test/CodeGenCXX/amdgcn-func-arg.cpp create mode 100644 test/CodeGenCXX/amdgcn-string-literal.cpp create mode 100644 test/CodeGenCXX/amdgcn_declspec_get.cpp create mode 100644 test/CodeGenCXX/attr-target-mv-diff-ns.cpp create mode 100644 test/CodeGenCXX/attr-target-mv-func-ptrs.cpp create mode 100644 test/CodeGenCXX/attr-target-mv-member-funcs.cpp create mode 100644 test/CodeGenCXX/attr-target-mv-modules.cpp create mode 100644 test/CodeGenCXX/attr-target-mv-out-of-line-defs.cpp create mode 100644 test/CodeGenCXX/attr-target-mv-overloads.cpp create mode 100644 test/CodeGenCXX/block-capture.cpp create mode 100644 test/CodeGenCXX/block-inalloca.cpp create mode 100644 test/CodeGenCXX/builtin-operator-new-delete.cpp create mode 100644 test/CodeGenCXX/cfi-mfcall-incomplete.cpp create mode 100644 test/CodeGenCXX/cfi-mfcall.cpp create mode 100644 test/CodeGenCXX/cfi-vcall-check-after-args.cpp create mode 100644 test/CodeGenCXX/char8_t.cpp create mode 100644 test/CodeGenCXX/code-seg.cpp create mode 100644 test/CodeGenCXX/code-seg1.cpp create mode 100644 test/CodeGenCXX/code-seg2.cpp create mode 100644 test/CodeGenCXX/code-seg3.cpp create mode 100644 test/CodeGenCXX/cxx2a-compare.cpp create mode 100644 test/CodeGenCXX/debug-info-codeview-unnamed.cpp create mode 100644 test/CodeGenCXX/debug-info-codeview-var-templates.cpp create mode 100644 test/CodeGenCXX/debug-info-composite-cc.cpp create mode 100644 test/CodeGenCXX/debug-info-range-for-var-names.cpp create mode 100644 test/CodeGenCXX/derived-cast.cpp create mode 100644 test/CodeGenCXX/devirtualize-ms-dtor.cpp create mode 100644 test/CodeGenCXX/dllimport-missing-key.cpp create mode 100644 test/CodeGenCXX/dllimport-template-sdm.cpp create mode 100644 test/CodeGenCXX/dso-local-executable.cpp create mode 100644 test/CodeGenCXX/finegrain-bitfield-type.cpp create mode 100644 test/CodeGenCXX/hidden-dllimport.cpp create mode 100644 test/CodeGenCXX/lambda-to-function-pointer-conversion.cpp create mode 100644 test/CodeGenCXX/mangle-mingw.cpp create mode 100644 test/CodeGenCXX/microsoft-abi-eh-inlineasm.cpp create mode 100644 test/CodeGenCXX/microsoft-abi-emit-dependent.cpp delete mode 100644 test/CodeGenCXX/ms-eh-personality.cpp create mode 100644 test/CodeGenCXX/ms-thunks-unprototyped-return.cpp create mode 100644 test/CodeGenCXX/ms-thunks-unprototyped.cpp create mode 100644 test/CodeGenCXX/msabi-swiftcall-cc.cpp create mode 100644 test/CodeGenCXX/optnone-pragma-optimize-off.cpp create mode 100644 test/CodeGenCXX/override-bit-field-layout.cpp create mode 100644 test/CodeGenCXX/personality.cpp create mode 100644 test/CodeGenCXX/rtti-hidden.cpp create mode 100644 test/CodeGenCXX/stack-reuse-exceptions.cpp create mode 100644 test/CodeGenCXX/tail-padding.cpp create mode 100644 test/CodeGenCXX/trivial_abi.cpp create mode 100644 test/CodeGenCXX/type-metadata-memfun.cpp create mode 100644 test/CodeGenCXX/ubsan-ctor-srcloc.cpp create mode 100644 test/CodeGenCXX/ubsan-function-noexcept.cpp create mode 100644 test/CodeGenCXX/visibility-pr36810.cpp create mode 100644 test/CodeGenCXX/wasm-eh.cpp (limited to 'test/CodeGenCXX') diff --git a/test/CodeGenCXX/Inputs/override-bit-field-layout.layout b/test/CodeGenCXX/Inputs/override-bit-field-layout.layout new file mode 100644 index 0000000000000..8e67dce65026b --- /dev/null +++ b/test/CodeGenCXX/Inputs/override-bit-field-layout.layout @@ -0,0 +1,16 @@ + +*** Dumping AST Record Layout +Type: struct S1 + +Layout: + +*** Dumping AST Record Layout +Type: struct S2 + +Layout: diff --git a/test/CodeGenCXX/Inputs/std-compare.h b/test/CodeGenCXX/Inputs/std-compare.h new file mode 100644 index 0000000000000..a6ab605bb5276 --- /dev/null +++ b/test/CodeGenCXX/Inputs/std-compare.h @@ -0,0 +1,437 @@ +#ifndef STD_COMPARE_H +#define STD_COMPARE_H + +namespace std { +inline namespace __1 { + +// exposition only +enum class _EqResult : unsigned char { + __zero = 0, + __equal = __zero, + __equiv = __equal, + __nonequal = 1, + __nonequiv = __nonequal +}; + +enum class _OrdResult : signed char { + __less = -1, + __greater = 1 +}; + +enum class _NCmpResult : signed char { + __unordered = -127 +}; + +struct _CmpUnspecifiedType; +using _CmpUnspecifiedParam = void (_CmpUnspecifiedType::*)(); + +class weak_equality { + constexpr explicit weak_equality(_EqResult __val) noexcept : __value_(__val) {} + +public: + static const weak_equality equivalent; + static const weak_equality nonequivalent; + + friend constexpr bool operator==(weak_equality __v, _CmpUnspecifiedParam) noexcept; + friend constexpr bool operator==(_CmpUnspecifiedParam, weak_equality __v) noexcept; + friend constexpr bool operator!=(weak_equality __v, _CmpUnspecifiedParam) noexcept; + friend constexpr bool operator!=(_CmpUnspecifiedParam, weak_equality __v) noexcept; + friend constexpr weak_equality operator<=>(weak_equality __v, _CmpUnspecifiedParam) noexcept; + friend constexpr weak_equality operator<=>(_CmpUnspecifiedParam, weak_equality __v) noexcept; + + // test helper + constexpr bool test_eq(weak_equality const &other) const noexcept { + return __value_ == other.__value_; + } + +private: + _EqResult __value_; +}; + +inline constexpr weak_equality weak_equality::equivalent(_EqResult::__equiv); +inline constexpr weak_equality weak_equality::nonequivalent(_EqResult::__nonequiv); +inline constexpr bool operator==(weak_equality __v, _CmpUnspecifiedParam) noexcept { + return __v.__value_ == _EqResult::__zero; +} +inline constexpr bool operator==(_CmpUnspecifiedParam, weak_equality __v) noexcept { + return __v.__value_ == _EqResult::__zero; +} +inline constexpr bool operator!=(weak_equality __v, _CmpUnspecifiedParam) noexcept { + return __v.__value_ != _EqResult::__zero; +} +inline constexpr bool operator!=(_CmpUnspecifiedParam, weak_equality __v) noexcept { + return __v.__value_ != _EqResult::__zero; +} + +inline constexpr weak_equality operator<=>(weak_equality __v, _CmpUnspecifiedParam) noexcept { + return __v; +} +inline constexpr weak_equality operator<=>(_CmpUnspecifiedParam, weak_equality __v) noexcept { + return __v; +} + +class strong_equality { + explicit constexpr strong_equality(_EqResult __val) noexcept : __value_(__val) {} + +public: + static const strong_equality equal; + static const strong_equality nonequal; + static const strong_equality equivalent; + static const strong_equality nonequivalent; + + // conversion + constexpr operator weak_equality() const noexcept { + return __value_ == _EqResult::__zero ? weak_equality::equivalent + : weak_equality::nonequivalent; + } + + // comparisons + friend constexpr bool operator==(strong_equality __v, _CmpUnspecifiedParam) noexcept; + friend constexpr bool operator!=(strong_equality __v, _CmpUnspecifiedParam) noexcept; + friend constexpr bool operator==(_CmpUnspecifiedParam, strong_equality __v) noexcept; + friend constexpr bool operator!=(_CmpUnspecifiedParam, strong_equality __v) noexcept; + + friend constexpr strong_equality operator<=>(strong_equality __v, _CmpUnspecifiedParam) noexcept; + friend constexpr strong_equality operator<=>(_CmpUnspecifiedParam, strong_equality __v) noexcept; + + // test helper + constexpr bool test_eq(strong_equality const &other) const noexcept { + return __value_ == other.__value_; + } + +private: + _EqResult __value_; +}; + +inline constexpr strong_equality strong_equality::equal(_EqResult::__equal); +inline constexpr strong_equality strong_equality::nonequal(_EqResult::__nonequal); +inline constexpr strong_equality strong_equality::equivalent(_EqResult::__equiv); +inline constexpr strong_equality strong_equality::nonequivalent(_EqResult::__nonequiv); +constexpr bool operator==(strong_equality __v, _CmpUnspecifiedParam) noexcept { + return __v.__value_ == _EqResult::__zero; +} +constexpr bool operator==(_CmpUnspecifiedParam, strong_equality __v) noexcept { + return __v.__value_ == _EqResult::__zero; +} +constexpr bool operator!=(strong_equality __v, _CmpUnspecifiedParam) noexcept { + return __v.__value_ != _EqResult::__zero; +} +constexpr bool operator!=(_CmpUnspecifiedParam, strong_equality __v) noexcept { + return __v.__value_ != _EqResult::__zero; +} + +constexpr strong_equality operator<=>(strong_equality __v, _CmpUnspecifiedParam) noexcept { + return __v; +} +constexpr strong_equality operator<=>(_CmpUnspecifiedParam, strong_equality __v) noexcept { + return __v; +} + +class partial_ordering { + using _ValueT = signed char; + explicit constexpr partial_ordering(_EqResult __v) noexcept + : __value_(_ValueT(__v)) {} + explicit constexpr partial_ordering(_OrdResult __v) noexcept + : __value_(_ValueT(__v)) {} + explicit constexpr partial_ordering(_NCmpResult __v) noexcept + : __value_(_ValueT(__v)) {} + + constexpr bool __is_ordered() const noexcept { + return __value_ != _ValueT(_NCmpResult::__unordered); + } + +public: + // valid values + static const partial_ordering less; + static const partial_ordering equivalent; + static const partial_ordering greater; + static const partial_ordering unordered; + + // conversion + constexpr operator weak_equality() const noexcept { + return __value_ == 0 ? weak_equality::equivalent : weak_equality::nonequivalent; + } + + // comparisons + friend constexpr bool operator==(partial_ordering __v, _CmpUnspecifiedParam) noexcept; + friend constexpr bool operator!=(partial_ordering __v, _CmpUnspecifiedParam) noexcept; + friend constexpr bool operator<(partial_ordering __v, _CmpUnspecifiedParam) noexcept; + friend constexpr bool operator<=(partial_ordering __v, _CmpUnspecifiedParam) noexcept; + friend constexpr bool operator>(partial_ordering __v, _CmpUnspecifiedParam) noexcept; + friend constexpr bool operator>=(partial_ordering __v, _CmpUnspecifiedParam) noexcept; + friend constexpr bool operator==(_CmpUnspecifiedParam, partial_ordering __v) noexcept; + friend constexpr bool operator!=(_CmpUnspecifiedParam, partial_ordering __v) noexcept; + friend constexpr bool operator<(_CmpUnspecifiedParam, partial_ordering __v) noexcept; + friend constexpr bool operator<=(_CmpUnspecifiedParam, partial_ordering __v) noexcept; + friend constexpr bool operator>(_CmpUnspecifiedParam, partial_ordering __v) noexcept; + friend constexpr bool operator>=(_CmpUnspecifiedParam, partial_ordering __v) noexcept; + + friend constexpr partial_ordering operator<=>(partial_ordering __v, _CmpUnspecifiedParam) noexcept; + friend constexpr partial_ordering operator<=>(_CmpUnspecifiedParam, partial_ordering __v) noexcept; + + // test helper + constexpr bool test_eq(partial_ordering const &other) const noexcept { + return __value_ == other.__value_; + } + +private: + _ValueT __value_; +}; + +inline constexpr partial_ordering partial_ordering::less(_OrdResult::__less); +inline constexpr partial_ordering partial_ordering::equivalent(_EqResult::__equiv); +inline constexpr partial_ordering partial_ordering::greater(_OrdResult::__greater); +inline constexpr partial_ordering partial_ordering::unordered(_NCmpResult ::__unordered); +constexpr bool operator==(partial_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v.__is_ordered() && __v.__value_ == 0; +} +constexpr bool operator<(partial_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v.__is_ordered() && __v.__value_ < 0; +} +constexpr bool operator<=(partial_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v.__is_ordered() && __v.__value_ <= 0; +} +constexpr bool operator>(partial_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v.__is_ordered() && __v.__value_ > 0; +} +constexpr bool operator>=(partial_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v.__is_ordered() && __v.__value_ >= 0; +} +constexpr bool operator==(_CmpUnspecifiedParam, partial_ordering __v) noexcept { + return __v.__is_ordered() && 0 == __v.__value_; +} +constexpr bool operator<(_CmpUnspecifiedParam, partial_ordering __v) noexcept { + return __v.__is_ordered() && 0 < __v.__value_; +} +constexpr bool operator<=(_CmpUnspecifiedParam, partial_ordering __v) noexcept { + return __v.__is_ordered() && 0 <= __v.__value_; +} +constexpr bool operator>(_CmpUnspecifiedParam, partial_ordering __v) noexcept { + return __v.__is_ordered() && 0 > __v.__value_; +} +constexpr bool operator>=(_CmpUnspecifiedParam, partial_ordering __v) noexcept { + return __v.__is_ordered() && 0 >= __v.__value_; +} +constexpr bool operator!=(partial_ordering __v, _CmpUnspecifiedParam) noexcept { + return !__v.__is_ordered() || __v.__value_ != 0; +} +constexpr bool operator!=(_CmpUnspecifiedParam, partial_ordering __v) noexcept { + return !__v.__is_ordered() || __v.__value_ != 0; +} + +constexpr partial_ordering operator<=>(partial_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v; +} +constexpr partial_ordering operator<=>(_CmpUnspecifiedParam, partial_ordering __v) noexcept { + return __v < 0 ? partial_ordering::greater : (__v > 0 ? partial_ordering::less : __v); +} + +class weak_ordering { + using _ValueT = signed char; + explicit constexpr weak_ordering(_EqResult __v) noexcept : __value_(_ValueT(__v)) {} + explicit constexpr weak_ordering(_OrdResult __v) noexcept : __value_(_ValueT(__v)) {} + +public: + static const weak_ordering less; + static const weak_ordering equivalent; + static const weak_ordering greater; + + // conversions + constexpr operator weak_equality() const noexcept { + return __value_ == 0 ? weak_equality::equivalent + : weak_equality::nonequivalent; + } + constexpr operator partial_ordering() const noexcept { + return __value_ == 0 ? partial_ordering::equivalent + : (__value_ < 0 ? partial_ordering::less : partial_ordering::greater); + } + + // comparisons + friend constexpr bool operator==(weak_ordering __v, _CmpUnspecifiedParam) noexcept; + friend constexpr bool operator!=(weak_ordering __v, _CmpUnspecifiedParam) noexcept; + friend constexpr bool operator<(weak_ordering __v, _CmpUnspecifiedParam) noexcept; + friend constexpr bool operator<=(weak_ordering __v, _CmpUnspecifiedParam) noexcept; + friend constexpr bool operator>(weak_ordering __v, _CmpUnspecifiedParam) noexcept; + friend constexpr bool operator>=(weak_ordering __v, _CmpUnspecifiedParam) noexcept; + friend constexpr bool operator==(_CmpUnspecifiedParam, weak_ordering __v) noexcept; + friend constexpr bool operator!=(_CmpUnspecifiedParam, weak_ordering __v) noexcept; + friend constexpr bool operator<(_CmpUnspecifiedParam, weak_ordering __v) noexcept; + friend constexpr bool operator<=(_CmpUnspecifiedParam, weak_ordering __v) noexcept; + friend constexpr bool operator>(_CmpUnspecifiedParam, weak_ordering __v) noexcept; + friend constexpr bool operator>=(_CmpUnspecifiedParam, weak_ordering __v) noexcept; + + friend constexpr weak_ordering operator<=>(weak_ordering __v, _CmpUnspecifiedParam) noexcept; + friend constexpr weak_ordering operator<=>(_CmpUnspecifiedParam, weak_ordering __v) noexcept; + + // test helper + constexpr bool test_eq(weak_ordering const &other) const noexcept { + return __value_ == other.__value_; + } + +private: + _ValueT __value_; +}; + +inline constexpr weak_ordering weak_ordering::less(_OrdResult::__less); +inline constexpr weak_ordering weak_ordering::equivalent(_EqResult::__equiv); +inline constexpr weak_ordering weak_ordering::greater(_OrdResult::__greater); +constexpr bool operator==(weak_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v.__value_ == 0; +} +constexpr bool operator!=(weak_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v.__value_ != 0; +} +constexpr bool operator<(weak_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v.__value_ < 0; +} +constexpr bool operator<=(weak_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v.__value_ <= 0; +} +constexpr bool operator>(weak_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v.__value_ > 0; +} +constexpr bool operator>=(weak_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v.__value_ >= 0; +} +constexpr bool operator==(_CmpUnspecifiedParam, weak_ordering __v) noexcept { + return 0 == __v.__value_; +} +constexpr bool operator!=(_CmpUnspecifiedParam, weak_ordering __v) noexcept { + return 0 != __v.__value_; +} +constexpr bool operator<(_CmpUnspecifiedParam, weak_ordering __v) noexcept { + return 0 < __v.__value_; +} +constexpr bool operator<=(_CmpUnspecifiedParam, weak_ordering __v) noexcept { + return 0 <= __v.__value_; +} +constexpr bool operator>(_CmpUnspecifiedParam, weak_ordering __v) noexcept { + return 0 > __v.__value_; +} +constexpr bool operator>=(_CmpUnspecifiedParam, weak_ordering __v) noexcept { + return 0 >= __v.__value_; +} + +constexpr weak_ordering operator<=>(weak_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v; +} +constexpr weak_ordering operator<=>(_CmpUnspecifiedParam, weak_ordering __v) noexcept { + return __v < 0 ? weak_ordering::greater : (__v > 0 ? weak_ordering::less : __v); +} + +class strong_ordering { + using _ValueT = signed char; + explicit constexpr strong_ordering(_EqResult __v) noexcept : __value_(static_cast(__v)) {} + explicit constexpr strong_ordering(_OrdResult __v) noexcept : __value_(static_cast(__v)) {} + +public: + static const strong_ordering less; + static const strong_ordering equal; + static const strong_ordering equivalent; + static const strong_ordering greater; + + // conversions + constexpr operator weak_equality() const noexcept { + return __value_ == 0 ? weak_equality::equivalent + : weak_equality::nonequivalent; + } + constexpr operator strong_equality() const noexcept { + return __value_ == 0 ? strong_equality::equal + : strong_equality::nonequal; + } + constexpr operator partial_ordering() const noexcept { + return __value_ == 0 ? partial_ordering::equivalent + : (__value_ < 0 ? partial_ordering::less : partial_ordering::greater); + } + constexpr operator weak_ordering() const noexcept { + return __value_ == 0 ? weak_ordering::equivalent + : (__value_ < 0 ? weak_ordering::less : weak_ordering::greater); + } + + // comparisons + friend constexpr bool operator==(strong_ordering __v, _CmpUnspecifiedParam) noexcept; + friend constexpr bool operator!=(strong_ordering __v, _CmpUnspecifiedParam) noexcept; + friend constexpr bool operator<(strong_ordering __v, _CmpUnspecifiedParam) noexcept; + friend constexpr bool operator<=(strong_ordering __v, _CmpUnspecifiedParam) noexcept; + friend constexpr bool operator>(strong_ordering __v, _CmpUnspecifiedParam) noexcept; + friend constexpr bool operator>=(strong_ordering __v, _CmpUnspecifiedParam) noexcept; + friend constexpr bool operator==(_CmpUnspecifiedParam, strong_ordering __v) noexcept; + friend constexpr bool operator!=(_CmpUnspecifiedParam, strong_ordering __v) noexcept; + friend constexpr bool operator<(_CmpUnspecifiedParam, strong_ordering __v) noexcept; + friend constexpr bool operator<=(_CmpUnspecifiedParam, strong_ordering __v) noexcept; + friend constexpr bool operator>(_CmpUnspecifiedParam, strong_ordering __v) noexcept; + friend constexpr bool operator>=(_CmpUnspecifiedParam, strong_ordering __v) noexcept; + + friend constexpr strong_ordering operator<=>(strong_ordering __v, _CmpUnspecifiedParam) noexcept; + friend constexpr strong_ordering operator<=>(_CmpUnspecifiedParam, strong_ordering __v) noexcept; + + // test helper + constexpr bool test_eq(strong_ordering const &other) const noexcept { + return __value_ == other.__value_; + } + +private: + _ValueT __value_; +}; + +inline constexpr strong_ordering strong_ordering::less(_OrdResult::__less); +inline constexpr strong_ordering strong_ordering::equal(_EqResult::__equal); +inline constexpr strong_ordering strong_ordering::equivalent(_EqResult::__equiv); +inline constexpr strong_ordering strong_ordering::greater(_OrdResult::__greater); + +constexpr bool operator==(strong_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v.__value_ == 0; +} +constexpr bool operator!=(strong_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v.__value_ != 0; +} +constexpr bool operator<(strong_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v.__value_ < 0; +} +constexpr bool operator<=(strong_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v.__value_ <= 0; +} +constexpr bool operator>(strong_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v.__value_ > 0; +} +constexpr bool operator>=(strong_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v.__value_ >= 0; +} +constexpr bool operator==(_CmpUnspecifiedParam, strong_ordering __v) noexcept { + return 0 == __v.__value_; +} +constexpr bool operator!=(_CmpUnspecifiedParam, strong_ordering __v) noexcept { + return 0 != __v.__value_; +} +constexpr bool operator<(_CmpUnspecifiedParam, strong_ordering __v) noexcept { + return 0 < __v.__value_; +} +constexpr bool operator<=(_CmpUnspecifiedParam, strong_ordering __v) noexcept { + return 0 <= __v.__value_; +} +constexpr bool operator>(_CmpUnspecifiedParam, strong_ordering __v) noexcept { + return 0 > __v.__value_; +} +constexpr bool operator>=(_CmpUnspecifiedParam, strong_ordering __v) noexcept { + return 0 >= __v.__value_; +} + +constexpr strong_ordering operator<=>(strong_ordering __v, _CmpUnspecifiedParam) noexcept { + return __v; +} +constexpr strong_ordering operator<=>(_CmpUnspecifiedParam, strong_ordering __v) noexcept { + return __v < 0 ? strong_ordering::greater : (__v > 0 ? strong_ordering::less : __v); +} + +// named comparison functions +constexpr bool is_eq(weak_equality __cmp) noexcept { return __cmp == 0; } +constexpr bool is_neq(weak_equality __cmp) noexcept { return __cmp != 0; } +constexpr bool is_lt(partial_ordering __cmp) noexcept { return __cmp < 0; } +constexpr bool is_lteq(partial_ordering __cmp) noexcept { return __cmp <= 0; } +constexpr bool is_gt(partial_ordering __cmp) noexcept { return __cmp > 0; } +constexpr bool is_gteq(partial_ordering __cmp) noexcept { return __cmp >= 0; } + +} // namespace __1 +} // end namespace std + +#endif // STD_COMPARE_H diff --git a/test/CodeGenCXX/PR19955.cpp b/test/CodeGenCXX/PR19955.cpp index 100108437752f..5175b74aae7f2 100644 --- a/test/CodeGenCXX/PR19955.cpp +++ b/test/CodeGenCXX/PR19955.cpp @@ -6,22 +6,22 @@ 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 +// CHECK-DAG: @"?varp@@3PAHA" = dso_local global i32* null +// X64-DAG: @"?varp@@3PEAHEA" = dso_local 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-DAG: @"?funp@@3P6AXXZA" = dso_local global void ()* null +// X64-DAG: @"?funp@@3P6AXXZEA" = dso_local global void ()* null -// CHECK-LABEL: @"\01??__Evarp@@YAXXZ" -// CHECK-DAG: store i32* @"\01?var@@3HA", i32** @"\01?varp@@3PAHA" +// CHECK-LABEL: @"??__Evarp@@YAXXZ" +// CHECK-DAG: store i32* @"?var@@3HA", i32** @"?varp@@3PAHA" -// X64-LABEL: @"\01??__Evarp@@YAXXZ" -// X64-DAG: store i32* @"\01?var@@3HA", i32** @"\01?varp@@3PEAHEA" +// X64-LABEL: @"??__Evarp@@YAXXZ" +// X64-DAG: store i32* @"?var@@3HA", i32** @"?varp@@3PEAHEA" -// CHECK-LABEL: @"\01??__Efunp@@YAXXZ"() -// CHECK-DAG: store void ()* @"\01?fun@@YAXXZ", void ()** @"\01?funp@@3P6AXXZA" +// CHECK-LABEL: @"??__Efunp@@YAXXZ"() +// CHECK-DAG: store void ()* @"?fun@@YAXXZ", void ()** @"?funp@@3P6AXXZA" -// X64-LABEL: @"\01??__Efunp@@YAXXZ"() -// X64-DAG: store void ()* @"\01?fun@@YAXXZ", void ()** @"\01?funp@@3P6AXXZEA" +// X64-LABEL: @"??__Efunp@@YAXXZ"() +// X64-DAG: store void ()* @"?fun@@YAXXZ", void ()** @"?funp@@3P6AXXZEA" diff --git a/test/CodeGenCXX/PR26569.cpp b/test/CodeGenCXX/PR26569.cpp index 859b6e26f0c43..379b50c9276c3 100644 --- a/test/CodeGenCXX/PR26569.cpp +++ b/test/CodeGenCXX/PR26569.cpp @@ -9,12 +9,12 @@ class B : virtual A {}; extern template class __declspec(dllimport) B; class __declspec(dllexport) C : B {}; -// CHECK-DAG: @[[VTABLE_C:.*]] = private unnamed_addr constant { [2 x i8*] } { [2 x i8*] [i8* bitcast (%rtti.CompleteObjectLocator* @"\01??_R4C@@6B@" to i8*), i8* bitcast (void (%class.A*)* @"\01?m_fn1@A@@EAEXXZ" to i8*)] } -// CHECK-DAG: @[[VTABLE_B:.*]] = private unnamed_addr constant { [2 x i8*] } { [2 x i8*] [i8* bitcast (%rtti.CompleteObjectLocator* @"\01??_R4?$B@H@@6B@" to i8*), i8* bitcast (void (%class.A*)* @"\01?m_fn1@A@@EAEXXZ" to i8*)] }, comdat($"\01??_S?$B@H@@6B@") -// CHECK-DAG: @[[VTABLE_A:.*]] = private unnamed_addr constant { [2 x i8*] } { [2 x i8*] [i8* bitcast (%rtti.CompleteObjectLocator* @"\01??_R4A@@6B@" to i8*), i8* bitcast (void (%class.A*)* @"\01?m_fn1@A@@EAEXXZ" to i8*)] }, comdat($"\01??_SA@@6B@") +// CHECK-DAG: @[[VTABLE_C:.*]] = private unnamed_addr constant { [2 x i8*] } { [2 x i8*] [i8* bitcast (%rtti.CompleteObjectLocator* @"??_R4C@@6B@" to i8*), i8* bitcast (void (%class.A*)* @"?m_fn1@A@@EAEXXZ" to i8*)] } +// CHECK-DAG: @[[VTABLE_B:.*]] = private unnamed_addr constant { [2 x i8*] } { [2 x i8*] [i8* bitcast (%rtti.CompleteObjectLocator* @"??_R4?$B@H@@6B@" to i8*), i8* bitcast (void (%class.A*)* @"?m_fn1@A@@EAEXXZ" to i8*)] }, comdat($"??_S?$B@H@@6B@") +// CHECK-DAG: @[[VTABLE_A:.*]] = private unnamed_addr constant { [2 x i8*] } { [2 x i8*] [i8* bitcast (%rtti.CompleteObjectLocator* @"??_R4A@@6B@" to i8*), i8* bitcast (void (%class.A*)* @"?m_fn1@A@@EAEXXZ" to i8*)] }, comdat($"??_SA@@6B@") -// CHECK-DAG: @"\01??_7C@@6B@" = dllexport unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* @[[VTABLE_C]], i32 0, i32 0, i32 1) -// CHECK-DAG: @"\01??_S?$B@H@@6B@" = unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* @[[VTABLE_B]], i32 0, i32 0, i32 1) -// CHECK-DAG: @"\01??_SA@@6B@" = unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* @[[VTABLE_A]], i32 0, i32 0, i32 1) +// CHECK-DAG: @"??_7C@@6B@" = dllexport unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* @[[VTABLE_C]], i32 0, i32 0, i32 1) +// CHECK-DAG: @"??_S?$B@H@@6B@" = unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* @[[VTABLE_B]], i32 0, i32 0, i32 1) +// CHECK-DAG: @"??_SA@@6B@" = unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* @[[VTABLE_A]], i32 0, i32 0, i32 1) -// CHECK-DAG: @"\01??_8?$B@H@@7B@" = available_externally dllimport unnamed_addr constant [2 x i32] [i32 0, i32 4] +// CHECK-DAG: @"??_8?$B@H@@7B@" = available_externally dllimport unnamed_addr constant [2 x i32] [i32 0, i32 4] diff --git a/test/CodeGenCXX/PR28220.cpp b/test/CodeGenCXX/PR28220.cpp index 6262c87de2062..5863b6dced85e 100644 --- a/test/CodeGenCXX/PR28220.cpp +++ b/test/CodeGenCXX/PR28220.cpp @@ -14,6 +14,6 @@ template S U::u; template S U::u; -// CHECK-NOT: define internal void @"\01??__Eu@?$U@H@@2U?$S@H@@A@YAXXZ"( +// CHECK-NOT: define internal void @"??__Eu@?$U@H@@2U?$S@H@@A@YAXXZ"( S &i = U::u; diff --git a/test/CodeGenCXX/PR37481.cpp b/test/CodeGenCXX/PR37481.cpp new file mode 100644 index 0000000000000..fba2ffdc8488f --- /dev/null +++ b/test/CodeGenCXX/PR37481.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -o /dev/null -emit-llvm -std=c++17 -triple x86_64-pc-windows-msvc %s + +struct Foo { + virtual void f(); + virtual void g(); +}; + +void Foo::f() {} +void Foo::g() {} + +template +void h() {} + +void x() { + h<&Foo::f>(); + h<&Foo::g>(); +} diff --git a/test/CodeGenCXX/abstract-class-ctors-dtors.cpp b/test/CodeGenCXX/abstract-class-ctors-dtors.cpp index f36922413d83c..f1d207649a4af 100644 --- a/test/CodeGenCXX/abstract-class-ctors-dtors.cpp +++ b/test/CodeGenCXX/abstract-class-ctors-dtors.cpp @@ -1,6 +1,6 @@ // RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s -// Check that we dont emit the complete constructor/destructor for this class. +// Check that we don't emit the complete constructor/destructor for this class. struct A { virtual void f() = 0; A(); diff --git a/test/CodeGenCXX/address-space-cast.cpp b/test/CodeGenCXX/address-space-cast.cpp new file mode 100644 index 0000000000000..334a1a63e6277 --- /dev/null +++ b/test/CodeGenCXX/address-space-cast.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 %s -triple=amdgcn-amd-amdhsa -emit-llvm -o - | FileCheck %s + +#define __private__ __attribute__((address_space(5))) + +void func_pchar(__private__ char *x); + +void test_cast(char *gen_ptr) { + // CHECK: %[[cast:.*]] = addrspacecast i8* %{{.*}} to i8 addrspace(5)* + // CHECK-NEXT: store i8 addrspace(5)* %[[cast]] + __private__ char *priv_ptr = (__private__ char *)gen_ptr; + + // CHECK: %[[cast:.*]] = addrspacecast i8* %{{.*}} to i8 addrspace(5)* + // CHECK-NEXT: call void @_Z10func_pcharPU3AS5c(i8 addrspace(5)* %[[cast]]) + func_pchar((__private__ char *)gen_ptr); +} diff --git a/test/CodeGenCXX/address-space-ref.cpp b/test/CodeGenCXX/address-space-ref.cpp index de6bddca66a72..5f0a42950328d 100644 --- a/test/CodeGenCXX/address-space-ref.cpp +++ b/test/CodeGenCXX/address-space-ref.cpp @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 %s -std=c++11 -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-prefixes=CHECK,NULL-INVALID +// RUN: %clang_cc1 %s -std=c++11 -triple=x86_64-apple-darwin10 -fno-delete-null-pointer-checks -emit-llvm -o - | FileCheck %s -check-prefixes=CHECK,NULL-VALID // For a reference to a complete type, output the dereferenceable attribute (in // any address space). @@ -29,6 +30,7 @@ bc & bar2(bc &x, bc & y) { return x; } -// CHECK: define nonnull %class.bc* @_Z4bar2R2bcS0_(%class.bc* nonnull %x, %class.bc* nonnull %y) +// NULL-INVALID: define nonnull %class.bc* @_Z4bar2R2bcS0_(%class.bc* nonnull %x, %class.bc* nonnull %y) +// NULL-VALID: define %class.bc* @_Z4bar2R2bcS0_(%class.bc* %x, %class.bc* %y) diff --git a/test/CodeGenCXX/alignment.cpp b/test/CodeGenCXX/alignment.cpp index 4c44badd21cda..37509fcb4dd55 100644 --- a/test/CodeGenCXX/alignment.cpp +++ b/test/CodeGenCXX/alignment.cpp @@ -1,4 +1,6 @@ -// RUN: %clang_cc1 %s -emit-llvm -o - -triple=x86_64-apple-darwin10 | FileCheck %s +// RUN: %clang_cc1 %s -emit-llvm -o - -triple=x86_64-apple-darwin10 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NOCOMPAT +// RUN: %clang_cc1 %s -emit-llvm -o - -triple=x86_64-apple-darwin10 -fclang-abi-compat=6.0 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-V6COMPAT +// RUN: %clang_cc1 %s -emit-llvm -o - -triple=x86_64-scei-ps4 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-V6COMPAT extern int int_source(); extern void int_sink(int x); @@ -54,11 +56,13 @@ namespace test0 { // CHECK: [[B_P:%.*]] = bitcast i8* [[T1]] to [[B]]* // CHECK: [[FIELD_P:%.*]] = bitcast [[B]]* [[B_P]] to i8* // CHECK: [[TRUNC:%.*]] = trunc i32 [[CALL]] to i8 - // CHECK: [[OLD_VALUE:%.*]] = load i8, i8* [[FIELD_P]], align 2 + // CHECK-V6COMPAT: [[OLD_VALUE:%.*]] = load i8, i8* [[FIELD_P]], align 2 + // CHECK-NOCOMPAT: [[OLD_VALUE:%.*]] = load i8, i8* [[FIELD_P]], align 4 // CHECK: [[T0:%.*]] = and i8 [[TRUNC]], 3 // CHECK: [[T1:%.*]] = and i8 [[OLD_VALUE]], -4 // CHECK: [[T2:%.*]] = or i8 [[T1]], [[T0]] - // CHECK: store i8 [[T2]], i8* [[FIELD_P]], align 2 + // CHECK-V6COMPAT: store i8 [[T2]], i8* [[FIELD_P]], align 2 + // CHECK-NOCOMPAT: store i8 [[T2]], i8* [[FIELD_P]], align 4 c.onebit = int_source(); // CHECK: [[C_P:%.*]] = load [[C]]*, [[C]]** @@ -66,7 +70,8 @@ namespace test0 { // CHECK: [[T1:%.*]] = getelementptr inbounds i8, i8* [[T0]], i64 8 // CHECK: [[B_P:%.*]] = bitcast i8* [[T1]] to [[B]]* // CHECK: [[FIELD_P:%.*]] = bitcast [[B]]* [[B_P]] to i8* - // CHECK: [[VALUE:%.*]] = load i8, i8* [[FIELD_P]], align 2 + // CHECK-V6COMPAT: [[VALUE:%.*]] = load i8, i8* [[FIELD_P]], align 2 + // CHECK-NOCOMPAT: [[VALUE:%.*]] = load i8, i8* [[FIELD_P]], align 4 // CHECK: [[T0:%.*]] = shl i8 [[VALUE]], 6 // CHECK: [[T1:%.*]] = ashr i8 [[T0]], 6 // CHECK: [[T2:%.*]] = sext i8 [[T1]] to i32 @@ -83,11 +88,13 @@ namespace test0 { // CHECK: [[B_P:%.*]] = bitcast i8* [[T1]] to [[B]]* // CHECK: [[FIELD_P:%.*]] = bitcast [[B]]* [[B_P]] to i8* // CHECK: [[TRUNC:%.*]] = trunc i32 [[CALL]] to i8 - // CHECK: [[OLD_VALUE:%.*]] = load i8, i8* [[FIELD_P]], align 2 + // CHECK-V6COMPAT: [[OLD_VALUE:%.*]] = load i8, i8* [[FIELD_P]], align 2 + // CHECK-NOCOMPAT: [[OLD_VALUE:%.*]] = load i8, i8* [[FIELD_P]], align 4 // CHECK: [[T0:%.*]] = and i8 [[TRUNC]], 3 // CHECK: [[T1:%.*]] = and i8 [[OLD_VALUE]], -4 // CHECK: [[T2:%.*]] = or i8 [[T1]], [[T0]] - // CHECK: store i8 [[T2]], i8* [[FIELD_P]], align 2 + // CHECK-V6COMPAT: store i8 [[T2]], i8* [[FIELD_P]], align 2 + // CHECK-NOCOMPAT: store i8 [[T2]], i8* [[FIELD_P]], align 4 c->onebit = int_source(); // CHECK: [[C_P:%.*]] = load [[C:%.*]]*, [[C]]** @@ -95,7 +102,8 @@ namespace test0 { // CHECK: [[T1:%.*]] = getelementptr inbounds i8, i8* [[T0]], i64 8 // CHECK: [[B_P:%.*]] = bitcast i8* [[T1]] to [[B:%.*]]* // CHECK: [[FIELD_P:%.*]] = bitcast [[B]]* [[B_P]] to i8* - // CHECK: [[VALUE:%.*]] = load i8, i8* [[FIELD_P]], align 2 + // CHECK-V6COMPAT: [[VALUE:%.*]] = load i8, i8* [[FIELD_P]], align 2 + // CHECK-NOCOMPAT: [[VALUE:%.*]] = load i8, i8* [[FIELD_P]], align 4 // CHECK: [[T0:%.*]] = shl i8 [[VALUE]], 6 // CHECK: [[T1:%.*]] = ashr i8 [[T0]], 6 // CHECK: [[T2:%.*]] = sext i8 [[T1]] to i32 @@ -107,7 +115,8 @@ namespace test0 { // in an alignment-2 variable. // CHECK-LABEL: @_ZN5test01dEv void d() { - // CHECK: [[C_P:%.*]] = alloca [[C:%.*]], align 2 + // CHECK-V6COMPAT: [[C_P:%.*]] = alloca [[C:%.*]], align 2 + // CHECK-NOCOMPAT: [[C_P:%.*]] = alloca [[C:%.*]], align 4 C c; // CHECK: [[CALL:%.*]] = call i32 @_Z10int_sourcev() @@ -116,18 +125,21 @@ namespace test0 { // CHECK: [[B_P:%.*]] = bitcast i8* [[T1]] to [[B]]* // CHECK: [[FIELD_P:%.*]] = bitcast [[B]]* [[B_P]] to i8* // CHECK: [[TRUNC:%.*]] = trunc i32 [[CALL]] to i8 - // CHECK: [[OLD_VALUE:%.*]] = load i8, i8* [[FIELD_P]], align 2 + // CHECK-V6COMPAT: [[OLD_VALUE:%.*]] = load i8, i8* [[FIELD_P]], align 2 + // CHECK-NOCOMPAT: [[OLD_VALUE:%.*]] = load i8, i8* [[FIELD_P]], align 4 // CHECK: [[T0:%.*]] = and i8 [[TRUNC]], 3 // CHECK: [[T1:%.*]] = and i8 [[OLD_VALUE]], -4 // CHECK: [[T2:%.*]] = or i8 [[T1]], [[T0]] - // CHECK: store i8 [[T2]], i8* [[FIELD_P]], align 2 + // CHECK-V6COMPAT: store i8 [[T2]], i8* [[FIELD_P]], align 2 + // CHECK-NOCOMPAT: store i8 [[T2]], i8* [[FIELD_P]], align 4 c.onebit = int_source(); // CHECK: [[T0:%.*]] = bitcast [[C]]* [[C_P]] to i8* // CHECK: [[T1:%.*]] = getelementptr inbounds i8, i8* [[T0]], i64 8 // CHECK: [[B_P:%.*]] = bitcast i8* [[T1]] to [[B:%.*]]* // CHECK: [[FIELD_P:%.*]] = bitcast [[B]]* [[B_P]] to i8* - // CHECK: [[VALUE:%.*]] = load i8, i8* [[FIELD_P]], align 2 + // CHECK-V6COMPAT: [[VALUE:%.*]] = load i8, i8* [[FIELD_P]], align 2 + // CHECK-NOCOMPAT: [[VALUE:%.*]] = load i8, i8* [[FIELD_P]], align 4 // CHECK: [[T0:%.*]] = shl i8 [[VALUE]], 6 // CHECK: [[T1:%.*]] = ashr i8 [[T0]], 6 // CHECK: [[T2:%.*]] = sext i8 [[T1]] to i32 @@ -204,7 +216,7 @@ namespace test1 { // CHECK: [[ARRAY_P:%.*]] = getelementptr inbounds [[A]], [[A]]* [[A_P]], i32 0, i32 0 // CHECK: [[T0:%.*]] = bitcast [[ARRAY]]* [[RESULT]] to i8* // CHECK: [[T1:%.*]] = bitcast [[ARRAY]]* [[ARRAY_P]] to i8* - // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[T0]], i8* [[T1]], i64 16, i32 16, i1 false) + // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 64 [[T0]], i8* align 16 [[T1]], i64 16, i1 false) AlignedArray result = a.aArray; } @@ -223,7 +235,7 @@ namespace test1 { // CHECK: [[ARRAY_P:%.*]] = getelementptr inbounds [[A]], [[A]]* [[A_P]], i32 0, i32 0 // CHECK: [[T0:%.*]] = bitcast [[ARRAY]]* [[RESULT]] to i8* // CHECK: [[T1:%.*]] = bitcast [[ARRAY]]* [[ARRAY_P]] to i8* - // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[T0]], i8* [[T1]], i64 16, i32 16, i1 false) + // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 64 [[T0]], i8* align 16 [[T1]], i64 16, i1 false) AlignedArray result = b.aArray; } @@ -234,7 +246,7 @@ namespace test1 { // CHECK: [[ARRAY_P:%.*]] = getelementptr inbounds [[B]], [[B]]* [[B_P]], i32 0, i32 2 // CHECK: [[T0:%.*]] = bitcast [[ARRAY]]* [[RESULT]] to i8* // CHECK: [[T1:%.*]] = bitcast [[ARRAY]]* [[ARRAY_P]] to i8* - // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[T0]], i8* [[T1]], i64 16, i32 8, i1 false) + // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 64 [[T0]], i8* align 8 [[T1]], i64 16, i1 false) AlignedArray result = b.bArray; } @@ -245,7 +257,7 @@ namespace test1 { // CHECK: [[ARRAY_P:%.*]] = getelementptr inbounds [[B]], [[B]]* [[B_P]], i32 0, i32 2 // CHECK: [[T0:%.*]] = bitcast [[ARRAY]]* [[RESULT]] to i8* // CHECK: [[T1:%.*]] = bitcast [[ARRAY]]* [[ARRAY_P]] to i8* - // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[T0]], i8* [[T1]], i64 16, i32 8, i1 false) + // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 64 [[T0]], i8* align 8 [[T1]], i64 16, i1 false) AlignedArray result = b->bArray; } @@ -256,7 +268,7 @@ namespace test1 { // CHECK: [[ARRAY_P:%.*]] = getelementptr inbounds [[B]], [[B]]* [[B_P]], i32 0, i32 2 // CHECK: [[T0:%.*]] = bitcast [[ARRAY]]* [[RESULT]] to i8* // CHECK: [[T1:%.*]] = bitcast [[ARRAY]]* [[ARRAY_P]] to i8* - // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[T0]], i8* [[T1]], i64 16, i32 16, i1 false) + // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 64 [[T0]], i8* align 16 [[T1]], i64 16, i1 false) B b; AlignedArray result = b.bArray; } @@ -277,7 +289,7 @@ namespace test1 { // CHECK: [[ARRAY_P:%.*]] = getelementptr inbounds [[A]], [[A]]* [[A_P]], i32 0, i32 0 // CHECK: [[T0:%.*]] = bitcast [[ARRAY]]* [[RESULT]] to i8* // CHECK: [[T1:%.*]] = bitcast [[ARRAY]]* [[ARRAY_P]] to i8* - // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[T0]], i8* [[T1]], i64 16, i32 16, i1 false) + // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 64 [[T0]], i8* align 16 [[T1]], i64 16, i1 false) D d; AlignedArray result = d.aArray; } @@ -292,7 +304,7 @@ namespace test1 { // CHECK: [[ARRAY_P:%.*]] = getelementptr inbounds [[B]], [[B]]* [[B_P]], i32 0, i32 2 // CHECK: [[T0:%.*]] = bitcast [[ARRAY]]* [[RESULT]] to i8* // CHECK: [[T1:%.*]] = bitcast [[ARRAY]]* [[ARRAY_P]] to i8* - // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[T0]], i8* [[T1]], i64 16, i32 8, i1 false) + // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 64 [[T0]], i8* align 8 [[T1]], i64 16, i1 false) D d; AlignedArray result = d.bArray; } diff --git a/test/CodeGenCXX/alloc-size.cpp b/test/CodeGenCXX/alloc-size.cpp index e93e231b70e82..e68e52c86bf26 100644 --- a/test/CodeGenCXX/alloc-size.cpp +++ b/test/CodeGenCXX/alloc-size.cpp @@ -69,4 +69,38 @@ int testIt() { __builtin_object_size(dependent_calloc<7, 8>(), 0) + __builtin_object_size(dependent_calloc2(), 0); } +} // namespace templated_alloc_size + +// Be sure that an ExprWithCleanups doesn't deter us. +namespace alloc_size_with_cleanups { +struct Foo { + ~Foo(); +}; + +void *my_malloc(const Foo &, int N) __attribute__((alloc_size(2))); + +// CHECK-LABEL: define i32 @_ZN24alloc_size_with_cleanups6testItEv +int testIt() { + int *const p = (int *)my_malloc(Foo{}, 3); + // CHECK: ret i32 3 + return __builtin_object_size(p, 0); +} +} // namespace alloc_size_with_cleanups + +class C { +public: + void *my_malloc(int N) __attribute__((alloc_size(2))); + void *my_calloc(int N, int M) __attribute__((alloc_size(2, 3))); +}; + +// CHECK-LABEL: define i32 @_Z16callMemberMallocv +int callMemberMalloc() { + // CHECK: ret i32 16 + return __builtin_object_size(C().my_malloc(16), 0); +} + +// CHECK-LABEL: define i32 @_Z16callMemberCallocv +int callMemberCalloc() { + // CHECK: ret i32 32 + return __builtin_object_size(C().my_calloc(16, 2), 0); } diff --git a/test/CodeGenCXX/amdgcn-func-arg.cpp b/test/CodeGenCXX/amdgcn-func-arg.cpp new file mode 100644 index 0000000000000..9ac143a520052 --- /dev/null +++ b/test/CodeGenCXX/amdgcn-func-arg.cpp @@ -0,0 +1,94 @@ +// RUN: %clang_cc1 -O0 -triple amdgcn -emit-llvm %s -o - | FileCheck %s + +class A { +public: + int x; + A():x(0) {} + ~A() {} +}; + +class B { +int x[100]; +}; + +A g_a; +B g_b; + +void func_with_ref_arg(A &a); +void func_with_ref_arg(B &b); + +// CHECK-LABEL: define void @_Z22func_with_indirect_arg1A(%class.A addrspace(5)* %a) +// CHECK: %p = alloca %class.A*, align 8, addrspace(5) +// CHECK: %[[r1:.+]] = addrspacecast %class.A* addrspace(5)* %p to %class.A** +// CHECK: %[[r0:.+]] = addrspacecast %class.A addrspace(5)* %a to %class.A* +// CHECK: store %class.A* %[[r0]], %class.A** %[[r1]], align 8 +void func_with_indirect_arg(A a) { + A *p = &a; +} + +// CHECK-LABEL: define void @_Z22test_indirect_arg_autov() +// CHECK: %a = alloca %class.A, align 4, addrspace(5) +// CHECK: %[[r0:.+]] = addrspacecast %class.A addrspace(5)* %a to %class.A* +// CHECK: %agg.tmp = alloca %class.A, align 4, addrspace(5) +// CHECK: %[[r1:.+]] = addrspacecast %class.A addrspace(5)* %agg.tmp to %class.A* +// CHECK: call void @_ZN1AC1Ev(%class.A* %[[r0]]) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64 +// CHECK: %[[r4:.+]] = addrspacecast %class.A* %[[r1]] to %class.A addrspace(5)* +// CHECK: call void @_Z22func_with_indirect_arg1A(%class.A addrspace(5)* %[[r4]]) +// CHECK: call void @_ZN1AD1Ev(%class.A* %[[r1]]) +// CHECK: call void @_Z17func_with_ref_argR1A(%class.A* dereferenceable(4) %[[r0]]) +// CHECK: call void @_ZN1AD1Ev(%class.A* %[[r0]]) +void test_indirect_arg_auto() { + A a; + func_with_indirect_arg(a); + func_with_ref_arg(a); +} + +// CHECK: define void @_Z24test_indirect_arg_globalv() +// CHECK: %agg.tmp = alloca %class.A, align 4, addrspace(5) +// CHECK: %[[r0:.+]] = addrspacecast %class.A addrspace(5)* %agg.tmp to %class.A* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64 +// CHECK: %[[r2:.+]] = addrspacecast %class.A* %[[r0]] to %class.A addrspace(5)* +// CHECK: call void @_Z22func_with_indirect_arg1A(%class.A addrspace(5)* %[[r2]]) +// CHECK: call void @_ZN1AD1Ev(%class.A* %[[r0]]) +// CHECK: call void @_Z17func_with_ref_argR1A(%class.A* dereferenceable(4) addrspacecast (%class.A addrspace(1)* @g_a to %class.A*)) +void test_indirect_arg_global() { + func_with_indirect_arg(g_a); + func_with_ref_arg(g_a); +} + +// CHECK-LABEL: define void @_Z19func_with_byval_arg1B(%class.B addrspace(5)* byval align 4 %b) +// CHECK: %p = alloca %class.B*, align 8, addrspace(5) +// CHECK: %[[r1:.+]] = addrspacecast %class.B* addrspace(5)* %p to %class.B** +// CHECK: %[[r0:.+]] = addrspacecast %class.B addrspace(5)* %b to %class.B* +// CHECK: store %class.B* %[[r0]], %class.B** %[[r1]], align 8 +void func_with_byval_arg(B b) { + B *p = &b; +} + +// CHECK-LABEL: define void @_Z19test_byval_arg_autov() +// CHECK: %b = alloca %class.B, align 4, addrspace(5) +// CHECK: %[[r0:.+]] = addrspacecast %class.B addrspace(5)* %b to %class.B* +// CHECK: %agg.tmp = alloca %class.B, align 4, addrspace(5) +// CHECK: %[[r1:.+]] = addrspacecast %class.B addrspace(5)* %agg.tmp to %class.B* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64 +// CHECK: %[[r4:.+]] = addrspacecast %class.B* %[[r1]] to %class.B addrspace(5)* +// CHECK: call void @_Z19func_with_byval_arg1B(%class.B addrspace(5)* byval align 4 %[[r4]]) +// CHECK: call void @_Z17func_with_ref_argR1B(%class.B* dereferenceable(400) %[[r0]]) +void test_byval_arg_auto() { + B b; + func_with_byval_arg(b); + func_with_ref_arg(b); +} + +// CHECK-LABEL: define void @_Z21test_byval_arg_globalv() +// CHECK: %agg.tmp = alloca %class.B, align 4, addrspace(5) +// CHECK: %[[r0:.+]] = addrspacecast %class.B addrspace(5)* %agg.tmp to %class.B* +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64 +// CHECK: %[[r2:.+]] = addrspacecast %class.B* %[[r0]] to %class.B addrspace(5)* +// CHECK: call void @_Z19func_with_byval_arg1B(%class.B addrspace(5)* byval align 4 %[[r2]]) +// CHECK: call void @_Z17func_with_ref_argR1B(%class.B* dereferenceable(400) addrspacecast (%class.B addrspace(1)* @g_b to %class.B*)) +void test_byval_arg_global() { + func_with_byval_arg(g_b); + func_with_ref_arg(g_b); +} diff --git a/test/CodeGenCXX/amdgcn-string-literal.cpp b/test/CodeGenCXX/amdgcn-string-literal.cpp new file mode 100644 index 0000000000000..7fd05351c863b --- /dev/null +++ b/test/CodeGenCXX/amdgcn-string-literal.cpp @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -emit-llvm %s -o - | FileCheck %s + +// CHECK: @.str = private unnamed_addr addrspace(4) constant [6 x i8] c"g_str\00", align 1 +// CHECK: @g_str = addrspace(1) global i8* addrspacecast (i8 addrspace(4)* getelementptr inbounds ([6 x i8], [6 x i8] addrspace(4)* @.str, i32 0, i32 0) to i8*), align 8 +// CHECK: @g_array = addrspace(1) global [8 x i8] c"g_array\00", align 1 +// CHECK: @.str.1 = private unnamed_addr addrspace(4) constant [6 x i8] c"l_str\00", align 1 +// CHECK: @_ZZ1fvE7l_array = private unnamed_addr addrspace(4) constant [8 x i8] c"l_array\00", align 1 + +const char* g_str = "g_str"; +char g_array[] = "g_array"; + +void g(const char* p); + +// CHECK-LABEL: define void @_Z1fv() +void f() { + const char* l_str = "l_str"; + + // CHECK: call void @llvm.memcpy.p0i8.p4i8.i64 + char l_array[] = "l_array"; + + g(g_str); + g(g_array); + g(l_str); + g(l_array); + + const char* p = g_str; + g(p); +} diff --git a/test/CodeGenCXX/amdgcn_declspec_get.cpp b/test/CodeGenCXX/amdgcn_declspec_get.cpp new file mode 100644 index 0000000000000..93f7a36af141f --- /dev/null +++ b/test/CodeGenCXX/amdgcn_declspec_get.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -emit-llvm -O3 -fdeclspec \ +// RUN: -disable-llvm-passes -o - %s | FileCheck %s + +int get_x(); + +struct A { + __declspec(property(get = _get_x)) int x; + static int _get_x(void) { + return get_x(); + }; +}; + +extern const A a; + +// CHECK-LABEL: define void @_Z4testv() +// CHECK: %i = alloca i32, align 4, addrspace(5) +// CHECK: %[[ii:.*]] = addrspacecast i32 addrspace(5)* %i to i32* +// CHECK: %[[cast:.*]] = bitcast i32 addrspace(5)* %i to i8 addrspace(5)* +// CHECK: call void @llvm.lifetime.start.p5i8(i64 4, i8 addrspace(5)* %[[cast]]) +// CHECK: %call = call i32 @_ZN1A6_get_xEv() +// CHECK: store i32 %call, i32* %[[ii]] +// CHECK: %[[cast2:.*]] = bitcast i32 addrspace(5)* %i to i8 addrspace(5)* +// CHECK: call void @llvm.lifetime.end.p5i8(i64 4, i8 addrspace(5)* %[[cast2]]) +void test() +{ + int i = a.x; +} diff --git a/test/CodeGenCXX/apple-kext-guard-variable.cpp b/test/CodeGenCXX/apple-kext-guard-variable.cpp index 76875a0b69ae7..ea4c1483ce707 100644 --- a/test/CodeGenCXX/apple-kext-guard-variable.cpp +++ b/test/CodeGenCXX/apple-kext-guard-variable.cpp @@ -1,4 +1,4 @@ -// RUN: %clang -target x86_64-apple-darwin10 -S -o %t.s -mkernel -Xclang -verify %s +// RUN: %clang -target x86_64-apple-darwin10 -S -o %t.s -Wno-stdlibcxx-not-found -mkernel -Xclang -verify %s // rdar://problem/9143356 diff --git a/test/CodeGenCXX/arm-swiftcall.cpp b/test/CodeGenCXX/arm-swiftcall.cpp index 5c932c77b1da3..36a5afad4c624 100644 --- a/test/CodeGenCXX/arm-swiftcall.cpp +++ b/test/CodeGenCXX/arm-swiftcall.cpp @@ -113,3 +113,13 @@ TEST(struct_indirect_1) // Should not be byval. // CHECK-LABEL: define {{.*}} void @take_struct_indirect_1({{.*}}*{{( %.*)?}}) + +// Do a simple standalone test here of a function definition to ensure that +// we don't have problems due to failure to eagerly synthesize a copy +// constructor declaration. +class struct_trivial { + int x; +}; +// CHECK-LABEL define void @test_struct_trivial(i32{{( %.*)?}}) +extern "C" SWIFTCALL +void test_struct_trivial(struct_trivial triv) {} diff --git a/test/CodeGenCXX/array-default-argument.cpp b/test/CodeGenCXX/array-default-argument.cpp index a07e3908392a4..23bc9fdbb703b 100644 --- a/test/CodeGenCXX/array-default-argument.cpp +++ b/test/CodeGenCXX/array-default-argument.cpp @@ -12,7 +12,7 @@ struct B { }; void f(); -// CHECK-LABEL: define void @_Z1gv() +// CHECK-LABEL: define {{(dso_local )?}}void @_Z1gv() void g() { // CHECK: br label %[[LOOP:.*]] diff --git a/test/CodeGenCXX/assign-construct-memcpy.cpp b/test/CodeGenCXX/assign-construct-memcpy.cpp index 3d42051324093..5e52b1625b61f 100644 --- a/test/CodeGenCXX/assign-construct-memcpy.cpp +++ b/test/CodeGenCXX/assign-construct-memcpy.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin12 -emit-llvm -o - -std=c++11 %s -DPOD | FileCheck %s -check-prefix=CHECK-POD +/// RUN: %clang_cc1 -triple x86_64-apple-darwin12 -emit-llvm -o - -std=c++11 %s -DPOD | FileCheck %s -check-prefix=CHECK-POD // RUN: %clang_cc1 -triple x86_64-apple-darwin12 -emit-llvm -o - -std=c++11 %s | FileCheck %s -check-prefix=CHECK-NONPOD // Declare the reserved placement operators. @@ -23,47 +23,47 @@ struct foo { foo *test1(void *f, const foo &x) { return new (f) foo(x); // CHECK-POD: test1 -// CHECK-POD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 24, i32 8 +// CHECK-POD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} align 8 {{.*}} align 8 {{.*}}i64 24 // CHECK-NONPOD: test1 -// CHECK-NONPOD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 24, i32 8 +// CHECK-NONPOD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} align 8 {{.*}} align 8 {{.*}}i64 24 } foo *test2(const foo &x) { return new foo(x); // CHECK-POD: test2 -// CHECK-POD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 24, i32 8 +// CHECK-POD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} align 16 {{.*}} align 8 {{.*}}i64 24 // CHECK-NONPOD: test2 -// CHECK-NONPOD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 24, i32 8 +// CHECK-NONPOD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} align 16 {{.*}} align 8 {{.*}}i64 24 } foo test3(const foo &x) { foo f = x; return f; // CHECK-POD: test3 -// CHECK-POD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 24, i32 8 +// CHECK-POD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} align 8 {{.*}} align 8 {{.*}}i64 24 // CHECK-NONPOD: test3 -// CHECK-NONPOD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 24, i32 8 +// CHECK-NONPOD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} align 8 {{.*}} align 8 {{.*}}i64 24 } foo *test4(foo &&x) { return new foo(x); // CHECK-POD: test4 -// CHECK-POD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 24, i32 8 +// CHECK-POD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} align 16 {{.*}} align 8 {{.*}}i64 24 // CHECK-NONPOD: test4 -// CHECK-NONPOD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 24, i32 8 +// CHECK-NONPOD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} align 16 {{.*}} align 8 {{.*}}i64 24 } void test5(foo &f, const foo &x) { f = x; // CHECK-POD: test5 -// CHECK-POD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 24, i32 8 +// CHECK-POD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} align 8 {{.*}} align 8 {{.*}}i64 24 // CHECK-NONPOD: test5 -// CHECK-NONPOD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 17, i32 8 +// CHECK-NONPOD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} align 8 {{.*}} align 8 {{.*}}i64 17 } extern foo globtest; @@ -71,10 +71,10 @@ extern foo globtest; void test6(foo &&x) { globtest = move(x); // CHECK-POD: test6 -// CHECK-POD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 24, i32 8 +// CHECK-POD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} align 8 {{.*}} align 8 {{.*}}i64 24 // CHECK-NONPOD: test6 -// CHECK-NONPOD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 17, i32 8 +// CHECK-NONPOD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} align 8 {{.*}} align 8 {{.*}}i64 17 } void byval(foo f); @@ -82,8 +82,8 @@ void byval(foo f); void test7(const foo &x) { byval(x); // CHECK-POD: test7 -// CHECK-POD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 24, i32 8 +// CHECK-POD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} align 8 {{.*}} align 8 {{.*}}i64 24 // CHECK-NONPOD: test7 -// CHECK-NONPOD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 24, i32 8 +// CHECK-NONPOD: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} align 8 {{.*}} align 8 {{.*}}i64 24 } diff --git a/test/CodeGenCXX/atomic-dllexport.cpp b/test/CodeGenCXX/atomic-dllexport.cpp index ae14222431605..20c500555c2ee 100644 --- a/test/CodeGenCXX/atomic-dllexport.cpp +++ b/test/CodeGenCXX/atomic-dllexport.cpp @@ -3,7 +3,7 @@ struct __declspec(dllexport) SomeStruct { // Copy assignment operator should be produced, and exported: - // M32: define weak_odr dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.SomeStruct* @"\01??4SomeStruct@@QAEAAU0@ABU0@@Z" - // M64: define weak_odr dllexport dereferenceable({{[0-9]+}}) %struct.SomeStruct* @"\01??4SomeStruct@@QEAAAEAU0@AEBU0@@Z" + // M32: define weak_odr dso_local dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.SomeStruct* @"??4SomeStruct@@QAEAAU0@ABU0@@Z" + // M64: define weak_odr dso_local dllexport dereferenceable({{[0-9]+}}) %struct.SomeStruct* @"??4SomeStruct@@QEAAAEAU0@AEBU0@@Z" _Atomic(int) mData; }; diff --git a/test/CodeGenCXX/atomic-inline.cpp b/test/CodeGenCXX/atomic-inline.cpp index fe727589d2e27..327f85d5667fd 100644 --- a/test/CodeGenCXX/atomic-inline.cpp +++ b/test/CodeGenCXX/atomic-inline.cpp @@ -1,6 +1,52 @@ // RUN: %clang_cc1 %s -std=c++11 -emit-llvm -o - -triple=x86_64-linux-gnu | FileCheck %s // RUN: %clang_cc1 %s -std=c++11 -emit-llvm -o - -triple=x86_64-linux-gnu -target-cpu core2 | FileCheck %s --check-prefix=CORE2 -// Check the atomic code generation for cpu targets w/wo cx16 support. +// RUN: %clang_cc1 %s -std=c++11 -emit-llvm -o - -triple=i386-linux-gnu -target-cpu i386 | FileCheck %s --check-prefix=I386 +// RUN: %clang_cc1 %s -std=c++11 -emit-llvm -o - -triple=i386-linux-gnu -target-cpu i486 | FileCheck %s --check-prefix=I486 +// Check the atomic code generation for cpu targets w/wo cx, cx8 and cx16 support. + +struct alignas(4) AM4 { + short f1, f2; +}; +AM4 m4; +AM4 load4() { + AM4 am; + // CHECK-LABEL: @_Z5load4v + // CHECK: load atomic i32, {{.*}} monotonic + // CORE2-LABEL: @_Z5load4v + // CORE2: load atomic i32, {{.*}} monotonic + // I386-LABEL: @_Z5load4v + // I386: call i32 @__atomic_load_4 + // I486-LABEL: @_Z5load4v + // I486: load atomic i32, {{.*}} monotonic + __atomic_load(&m4, &am, 0); + return am; +} + +AM4 s4; +void store4() { + // CHECK-LABEL: @_Z6store4v + // CHECK: store atomic i32 {{.*}} monotonic + // CORE2-LABEL: @_Z6store4v + // CORE2: store atomic i32 {{.*}} monotonic + // I386-LABEL: @_Z6store4v + // I386: call void @__atomic_store_4 + // I486-LABEL: @_Z6store4v + // I486: store atomic i32 {{.*}} monotonic + __atomic_store(&m4, &s4, 0); +} + +bool cmpxchg4() { + AM4 am; + // CHECK-LABEL: @_Z8cmpxchg4v + // CHECK: cmpxchg i32* {{.*}} monotonic + // CORE2-LABEL: @_Z8cmpxchg4v + // CORE2: cmpxchg i32* {{.*}} monotonic + // I386-LABEL: @_Z8cmpxchg4v + // I386: call zeroext i1 @__atomic_compare_exchange_4 + // I486-LABEL: @_Z8cmpxchg4v + // I486: cmpxchg i32* {{.*}} monotonic + return __atomic_compare_exchange(&m4, &s4, &am, 0, 0, 0); +} struct alignas(8) AM8 { int f1, f2; @@ -12,6 +58,10 @@ AM8 load8() { // CHECK: load atomic i64, {{.*}} monotonic // CORE2-LABEL: @_Z5load8v // CORE2: load atomic i64, {{.*}} monotonic + // I386-LABEL: @_Z5load8v + // I386: call i64 @__atomic_load_8 + // I486-LABEL: @_Z5load8v + // I486: call i64 @__atomic_load_8 __atomic_load(&m8, &am, 0); return am; } @@ -22,6 +72,10 @@ void store8() { // CHECK: store atomic i64 {{.*}} monotonic // CORE2-LABEL: @_Z6store8v // CORE2: store atomic i64 {{.*}} monotonic + // I386-LABEL: @_Z6store8v + // I386: call void @__atomic_store_8 + // I486-LABEL: @_Z6store8v + // I486: call void @__atomic_store_8 __atomic_store(&m8, &s8, 0); } @@ -31,6 +85,10 @@ bool cmpxchg8() { // CHECK: cmpxchg i64* {{.*}} monotonic // CORE2-LABEL: @_Z8cmpxchg8v // CORE2: cmpxchg i64* {{.*}} monotonic + // I386-LABEL: @_Z8cmpxchg8v + // I386: call zeroext i1 @__atomic_compare_exchange_8 + // I486-LABEL: @_Z8cmpxchg8v + // I486: call zeroext i1 @__atomic_compare_exchange_8 return __atomic_compare_exchange(&m8, &s8, &am, 0, 0, 0); } @@ -66,4 +124,3 @@ bool cmpxchg16() { // CORE2: cmpxchg i128* {{.*}} monotonic return __atomic_compare_exchange(&m16, &s16, &am, 0, 0, 0); } - diff --git a/test/CodeGenCXX/attr-target-mv-diff-ns.cpp b/test/CodeGenCXX/attr-target-mv-diff-ns.cpp new file mode 100644 index 0000000000000..4dc2b67b46444 --- /dev/null +++ b/test/CodeGenCXX/attr-target-mv-diff-ns.cpp @@ -0,0 +1,54 @@ +// RUN: %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s +// Test ensures that this properly differentiates between types in different +// namespaces. +int __attribute__((target("sse4.2"))) foo(int) { return 0; } +int __attribute__((target("arch=sandybridge"))) foo(int); +int __attribute__((target("arch=ivybridge"))) foo(int) {return 1;} +int __attribute__((target("default"))) foo(int) { return 2; } + +namespace ns { +int __attribute__((target("sse4.2"))) foo(int) { return 0; } +int __attribute__((target("arch=sandybridge"))) foo(int); +int __attribute__((target("arch=ivybridge"))) foo(int) {return 1;} +int __attribute__((target("default"))) foo(int) { return 2; } +} + +int bar() { + return foo(1) + ns::foo(2); +} + +// CHECK: @_Z3fooi.ifunc = ifunc i32 (i32), i32 (i32)* ()* @_Z3fooi.resolver +// CHECK: @_ZN2ns3fooEi.ifunc = ifunc i32 (i32), i32 (i32)* ()* @_ZN2ns3fooEi.resolver + +// CHECK: define i32 @_Z3fooi.sse4.2(i32) +// CHECK: ret i32 0 +// CHECK: define i32 @_Z3fooi.arch_ivybridge(i32) +// CHECK: ret i32 1 +// CHECK: define i32 @_Z3fooi(i32) +// CHECK: ret i32 2 + +// CHECK: define i32 @_ZN2ns3fooEi.sse4.2(i32) +// CHECK: ret i32 0 +// CHECK: define i32 @_ZN2ns3fooEi.arch_ivybridge(i32) +// CHECK: ret i32 1 +// CHECK: define i32 @_ZN2ns3fooEi(i32) +// CHECK: ret i32 2 + +// CHECK: define i32 @_Z3barv() +// CHECK: call i32 @_Z3fooi.ifunc(i32 1) +// CHECK: call i32 @_ZN2ns3fooEi.ifunc(i32 2) + +// CHECK: define i32 (i32)* @_Z3fooi.resolver() comdat +// CHECK: ret i32 (i32)* @_Z3fooi.arch_sandybridge +// CHECK: ret i32 (i32)* @_Z3fooi.arch_ivybridge +// CHECK: ret i32 (i32)* @_Z3fooi.sse4.2 +// CHECK: ret i32 (i32)* @_Z3fooi +// +// CHECK: define i32 (i32)* @_ZN2ns3fooEi.resolver() comdat +// CHECK: ret i32 (i32)* @_ZN2ns3fooEi.arch_sandybridge +// CHECK: ret i32 (i32)* @_ZN2ns3fooEi.arch_ivybridge +// CHECK: ret i32 (i32)* @_ZN2ns3fooEi.sse4.2 +// CHECK: ret i32 (i32)* @_ZN2ns3fooEi + +// CHECK: declare i32 @_Z3fooi.arch_sandybridge(i32) +// CHECK: declare i32 @_ZN2ns3fooEi.arch_sandybridge(i32) diff --git a/test/CodeGenCXX/attr-target-mv-func-ptrs.cpp b/test/CodeGenCXX/attr-target-mv-func-ptrs.cpp new file mode 100644 index 0000000000000..290d6b5c64895 --- /dev/null +++ b/test/CodeGenCXX/attr-target-mv-func-ptrs.cpp @@ -0,0 +1,45 @@ +// RUN: %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s +void temp(); +void temp(int); +using FP = void(*)(int); +void b() { + FP f = temp; +} + +int __attribute__((target("sse4.2"))) foo(int) { return 0; } +int __attribute__((target("arch=sandybridge"))) foo(int); +int __attribute__((target("arch=ivybridge"))) foo(int) {return 1;} +int __attribute__((target("default"))) foo(int) { return 2; } + +struct S { +int __attribute__((target("sse4.2"))) foo(int) { return 0; } +int __attribute__((target("arch=sandybridge"))) foo(int); +int __attribute__((target("arch=ivybridge"))) foo(int) {return 1;} +int __attribute__((target("default"))) foo(int) { return 2; } +}; + +using FuncPtr = int (*)(int); +using MemFuncPtr = int (S::*)(int); + +void f(FuncPtr, MemFuncPtr); + +int bar() { + FuncPtr Free = &foo; + MemFuncPtr Member = &S::foo; + S s; + f(foo, &S::foo); + return Free(1) + (s.*Member)(2); +} + + +// CHECK: @_Z3fooi.ifunc +// CHECK: @_ZN1S3fooEi.ifunc + +// CHECK: define i32 @_Z3barv() +// Store to Free of ifunc +// CHECK: store i32 (i32)* @_Z3fooi.ifunc +// Store to Member of ifunc +// CHECK: store { i64, i64 } { i64 ptrtoint (i32 (%struct.S*, i32)* @_ZN1S3fooEi.ifunc to i64), i64 0 }, { i64, i64 }* [[MEMBER:%[a-z]+]] + +// Call to 'f' with the ifunc +// CHECK: call void @_Z1fPFiiEM1SFiiE(i32 (i32)* @_Z3fooi.ifunc diff --git a/test/CodeGenCXX/attr-target-mv-member-funcs.cpp b/test/CodeGenCXX/attr-target-mv-member-funcs.cpp new file mode 100644 index 0000000000000..2e5db3b705e46 --- /dev/null +++ b/test/CodeGenCXX/attr-target-mv-member-funcs.cpp @@ -0,0 +1,137 @@ +// RUN: %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s + +struct S { + int __attribute__((target("sse4.2"))) foo(int) { return 0; } + int __attribute__((target("arch=sandybridge"))) foo(int); + int __attribute__((target("arch=ivybridge"))) foo(int) { return 1; } + int __attribute__((target("default"))) foo(int) { return 2; } + + S &__attribute__((target("arch=ivybridge"))) operator=(const S &) { + return *this; + } + S &__attribute__((target("default"))) operator=(const S &) { + return *this; + } +}; + +struct ConvertTo { + __attribute__((target("arch=ivybridge"))) operator S() const { + return S{}; + } + __attribute__((target("default"))) operator S() const { + return S{}; + } +}; + +int bar() { + S s; + S s2; + s2 = s; + + ConvertTo C; + s2 = static_cast(C); + + return s.foo(0); +} + +struct S2 { + int __attribute__((target("sse4.2"))) foo(int); + int __attribute__((target("arch=sandybridge"))) foo(int); + int __attribute__((target("arch=ivybridge"))) foo(int); + int __attribute__((target("default"))) foo(int); +}; + +int bar2() { + S2 s; + return s.foo(0); +} + +int __attribute__((target("sse4.2"))) S2::foo(int) { return 0; } +int __attribute__((target("arch=ivybridge"))) S2::foo(int) { return 1; } +int __attribute__((target("default"))) S2::foo(int) { return 2; } + +template +struct templ { + int __attribute__((target("sse4.2"))) foo(int) { return 0; } + int __attribute__((target("arch=sandybridge"))) foo(int); + int __attribute__((target("arch=ivybridge"))) foo(int) { return 1; } + int __attribute__((target("default"))) foo(int) { return 2; } +}; + +int templ_use() { + templ a; + templ b; + return a.foo(1) + b.foo(2); +} + +// CHECK: @_ZN1SaSERKS_.ifunc = ifunc %struct.S* (%struct.S*, %struct.S*), %struct.S* (%struct.S*, %struct.S*)* ()* @_ZN1SaSERKS_.resolver +// CHECK: @_ZNK9ConvertTocv1SEv.ifunc = ifunc void (%struct.ConvertTo*), void (%struct.ConvertTo*)* ()* @_ZNK9ConvertTocv1SEv.resolver +// CHECK: @_ZN1S3fooEi.ifunc = ifunc i32 (%struct.S*, i32), i32 (%struct.S*, i32)* ()* @_ZN1S3fooEi.resolver +// CHECK: @_ZN2S23fooEi.ifunc = ifunc i32 (%struct.S2*, i32), i32 (%struct.S2*, i32)* ()* @_ZN2S23fooEi.resolver +// Templates: +// CHECK: @_ZN5templIiE3fooEi.ifunc = ifunc i32 (%struct.templ*, i32), i32 (%struct.templ*, i32)* ()* @_ZN5templIiE3fooEi.resolver +// CHECK: @_ZN5templIdE3fooEi.ifunc = ifunc i32 (%struct.templ.0*, i32), i32 (%struct.templ.0*, i32)* ()* @_ZN5templIdE3fooEi.resolver + +// CHECK: define i32 @_Z3barv() +// CHECK: %s = alloca %struct.S, align 1 +// CHECK: %s2 = alloca %struct.S, align 1 +// CHECK: %C = alloca %struct.ConvertTo, align 1 +// CHECK: call dereferenceable(1) %struct.S* @_ZN1SaSERKS_.ifunc(%struct.S* %s2 +// CHECK: call void @_ZNK9ConvertTocv1SEv.ifunc(%struct.ConvertTo* %C) +// CHECK: call dereferenceable(1) %struct.S* @_ZN1SaSERKS_.ifunc(%struct.S* %s2 +// CHECK: call i32 @_ZN1S3fooEi.ifunc(%struct.S* %s, i32 0) + +// CHECK: define %struct.S* (%struct.S*, %struct.S*)* @_ZN1SaSERKS_.resolver() comdat +// CHECK: ret %struct.S* (%struct.S*, %struct.S*)* @_ZN1SaSERKS_.arch_ivybridge +// CHECK: ret %struct.S* (%struct.S*, %struct.S*)* @_ZN1SaSERKS_ + +// CHECK: define void (%struct.ConvertTo*)* @_ZNK9ConvertTocv1SEv.resolver() comdat +// CHECK: ret void (%struct.ConvertTo*)* @_ZNK9ConvertTocv1SEv.arch_ivybridge +// CHECK: ret void (%struct.ConvertTo*)* @_ZNK9ConvertTocv1SEv + +// CHECK: define i32 (%struct.S*, i32)* @_ZN1S3fooEi.resolver() comdat +// CHECK: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi.arch_sandybridge +// CHECK: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi.arch_ivybridge +// CHECK: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi.sse4.2 +// CHECK: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi + +// CHECK: define i32 @_Z4bar2v() +// CHECK:call i32 @_ZN2S23fooEi.ifunc +// define i32 (%struct.S2*, i32)* @_ZN2S23fooEi.resolver() comdat +// CHECK: ret i32 (%struct.S2*, i32)* @_ZN2S23fooEi.arch_sandybridge +// CHECK: ret i32 (%struct.S2*, i32)* @_ZN2S23fooEi.arch_ivybridge +// CHECK: ret i32 (%struct.S2*, i32)* @_ZN2S23fooEi.sse4.2 +// CHECK: ret i32 (%struct.S2*, i32)* @_ZN2S23fooEi + +// CHECK: define i32 @_ZN2S23fooEi.sse4.2(%struct.S2* %this, i32) +// CHECK: define i32 @_ZN2S23fooEi.arch_ivybridge(%struct.S2* %this, i32) +// CHECK: define i32 @_ZN2S23fooEi(%struct.S2* %this, i32) + +// CHECK: define i32 @_Z9templ_usev() +// CHECK: call i32 @_ZN5templIiE3fooEi.ifunc +// CHECK: call i32 @_ZN5templIdE3fooEi.ifunc + + +// CHECK: define i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi.resolver() comdat +// CHECK: ret i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi.arch_sandybridge +// CHECK: ret i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi.arch_ivybridge +// CHECK: ret i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi.sse4.2 +// CHECK: ret i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi +// +// CHECK: define i32 (%struct.templ.0*, i32)* @_ZN5templIdE3fooEi.resolver() comdat +// CHECK: ret i32 (%struct.templ.0*, i32)* @_ZN5templIdE3fooEi.arch_sandybridge +// CHECK: ret i32 (%struct.templ.0*, i32)* @_ZN5templIdE3fooEi.arch_ivybridge +// CHECK: ret i32 (%struct.templ.0*, i32)* @_ZN5templIdE3fooEi.sse4.2 +// CHECK: ret i32 (%struct.templ.0*, i32)* @_ZN5templIdE3fooEi + +// CHECK: define linkonce_odr i32 @_ZN1S3fooEi.sse4.2(%struct.S* %this, i32) +// CHECK: ret i32 0 + +// CHECK: declare i32 @_ZN1S3fooEi.arch_sandybridge(%struct.S*, i32) + +// CHECK: define linkonce_odr i32 @_ZN1S3fooEi.arch_ivybridge(%struct.S* %this, i32) +// CHECK: ret i32 1 + +// CHECK: define linkonce_odr i32 @_ZN1S3fooEi(%struct.S* %this, i32) +// CHECK: ret i32 2 + diff --git a/test/CodeGenCXX/attr-target-mv-modules.cpp b/test/CodeGenCXX/attr-target-mv-modules.cpp new file mode 100644 index 0000000000000..6ff2046831e63 --- /dev/null +++ b/test/CodeGenCXX/attr-target-mv-modules.cpp @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -fmodules -emit-llvm %s -o - | FileCheck %s +#pragma clang module build A +module A {} +#pragma clang module contents +#pragma clang module begin A +__attribute__((target("default"))) void f(); +__attribute__((target("sse4.2"))) void f(); +#pragma clang module end +#pragma clang module endbuild + +#pragma clang module build B +module B {} +#pragma clang module contents +#pragma clang module begin B +__attribute__((target("default"))) void f(); +__attribute__((target("sse4.2"))) void f(); +#pragma clang module end +#pragma clang module endbuild + +#pragma clang module import A +#pragma clang module import B +void g() { f(); } + +// Negative tests to validate that the resolver only calls each 1x. +// CHECK: define void ()* @_Z1fv.resolver +// CHECK: ret void ()* @_Z1fv.sse4.2 +// CHECK-NOT: ret void ()* @_Z1fv.sse4.2 +// CHECK: ret void ()* @_Z1fv +// CHECK-NOT: ret void ()* @_Z1fv diff --git a/test/CodeGenCXX/attr-target-mv-out-of-line-defs.cpp b/test/CodeGenCXX/attr-target-mv-out-of-line-defs.cpp new file mode 100644 index 0000000000000..63353c12d29a2 --- /dev/null +++ b/test/CodeGenCXX/attr-target-mv-out-of-line-defs.cpp @@ -0,0 +1,39 @@ +// RUN: %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s +struct S { + int __attribute__((target("sse4.2"))) foo(int); + int __attribute__((target("arch=sandybridge"))) foo(int); + int __attribute__((target("arch=ivybridge"))) foo(int); + int __attribute__((target("default"))) foo(int); +}; + +int __attribute__((target("default"))) S::foo(int) { return 2; } +int __attribute__((target("sse4.2"))) S::foo(int) { return 0; } +int __attribute__((target("arch=ivybridge"))) S::foo(int) { return 1; } + +int bar() { + S s; + return s.foo(0); +} + +// CHECK: @_ZN1S3fooEi.ifunc = ifunc i32 (%struct.S*, i32), i32 (%struct.S*, i32)* ()* @_ZN1S3fooEi.resolver + +// CHECK: define i32 @_ZN1S3fooEi(%struct.S* %this, i32) +// CHECK: ret i32 2 + +// CHECK: define i32 @_ZN1S3fooEi.sse4.2(%struct.S* %this, i32) +// CHECK: ret i32 0 + +// CHECK: define i32 @_ZN1S3fooEi.arch_ivybridge(%struct.S* %this, i32) +// CHECK: ret i32 1 + +// CHECK: define i32 @_Z3barv() +// CHECK: %s = alloca %struct.S, align 1 +// CHECK: %call = call i32 @_ZN1S3fooEi.ifunc(%struct.S* %s, i32 0) + +// CHECK: define i32 (%struct.S*, i32)* @_ZN1S3fooEi.resolver() comdat +// CHECK: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi.arch_sandybridge +// CHECK: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi.arch_ivybridge +// CHECK: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi.sse4.2 +// CHECK: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi + +// CHECK: declare i32 @_ZN1S3fooEi.arch_sandybridge(%struct.S*, i32) diff --git a/test/CodeGenCXX/attr-target-mv-overloads.cpp b/test/CodeGenCXX/attr-target-mv-overloads.cpp new file mode 100644 index 0000000000000..c72ea77fa46f6 --- /dev/null +++ b/test/CodeGenCXX/attr-target-mv-overloads.cpp @@ -0,0 +1,50 @@ +// RUN: %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s + +int __attribute__((target("sse4.2"))) foo_overload(int) { return 0; } +int __attribute__((target("arch=sandybridge"))) foo_overload(int); +int __attribute__((target("arch=ivybridge"))) foo_overload(int) {return 1;} +int __attribute__((target("default"))) foo_overload(int) { return 2; } +int __attribute__((target("sse4.2"))) foo_overload(void) { return 0; } +int __attribute__((target("arch=sandybridge"))) foo_overload(void); +int __attribute__((target("arch=ivybridge"))) foo_overload(void) {return 1;} +int __attribute__((target("default"))) foo_overload(void) { return 2; } + +int bar2() { + return foo_overload() + foo_overload(1); +} + +// CHECK: @_Z12foo_overloadv.ifunc = ifunc i32 (), i32 ()* ()* @_Z12foo_overloadv.resolver +// CHECK: @_Z12foo_overloadi.ifunc = ifunc i32 (i32), i32 (i32)* ()* @_Z12foo_overloadi.resolver + + +// CHECK: define i32 @_Z12foo_overloadi.sse4.2(i32) +// CHECK: ret i32 0 +// CHECK: define i32 @_Z12foo_overloadi.arch_ivybridge(i32) +// CHECK: ret i32 1 +// CHECK: define i32 @_Z12foo_overloadi(i32) +// CHECK: ret i32 2 +// CHECK: define i32 @_Z12foo_overloadv.sse4.2() +// CHECK: ret i32 0 +// CHECK: define i32 @_Z12foo_overloadv.arch_ivybridge() +// CHECK: ret i32 1 +// CHECK: define i32 @_Z12foo_overloadv() +// CHECK: ret i32 2 + +// CHECK: define i32 @_Z4bar2v() +// CHECK: call i32 @_Z12foo_overloadv.ifunc() +// CHECK: call i32 @_Z12foo_overloadi.ifunc(i32 1) + +// CHECK: define i32 ()* @_Z12foo_overloadv.resolver() comdat +// CHECK: ret i32 ()* @_Z12foo_overloadv.arch_sandybridge +// CHECK: ret i32 ()* @_Z12foo_overloadv.arch_ivybridge +// CHECK: ret i32 ()* @_Z12foo_overloadv.sse4.2 +// CHECK: ret i32 ()* @_Z12foo_overloadv + +// CHECK: define i32 (i32)* @_Z12foo_overloadi.resolver() comdat +// CHECK: ret i32 (i32)* @_Z12foo_overloadi.arch_sandybridge +// CHECK: ret i32 (i32)* @_Z12foo_overloadi.arch_ivybridge +// CHECK: ret i32 (i32)* @_Z12foo_overloadi.sse4.2 +// CHECK: ret i32 (i32)* @_Z12foo_overloadi + +// CHECK: declare i32 @_Z12foo_overloadv.arch_sandybridge() +// CHECK: declare i32 @_Z12foo_overloadi.arch_sandybridge(i32) diff --git a/test/CodeGenCXX/attr-x86-interrupt.cpp b/test/CodeGenCXX/attr-x86-interrupt.cpp index 5000104690350..30cf58b1e2e3d 100644 --- a/test/CodeGenCXX/attr-x86-interrupt.cpp +++ b/test/CodeGenCXX/attr-x86-interrupt.cpp @@ -26,10 +26,10 @@ static void foo9(int *a) __attribute__((interrupt)) {} // X86_LINUX: define x86_intrcc void @{{.*}}foo8{{.*}}(i32* %{{.+}}) // X86_LINUX: define linkonce_odr x86_intrcc void @{{.*}}foo9{{.*}}(i32* %{{.+}}) // X86_64_WIN: @llvm.used = appending global [3 x i8*] [i8* bitcast (void (i32*, i64)* @{{.*}}foo7{{.*}} to i8*), i8* bitcast (void (i32*)* @{{.*}}foo8{{.*}} to i8*), i8* bitcast (void (i32*)* @{{.*}}foo9{{.*}} to i8*)], section "llvm.metadata" -// X86_64_WIN: define x86_intrcc void @{{.*}}foo7{{.*}}(i32* %{{.+}}, i64 %{{.+}}) -// X86_64_WIN: define x86_intrcc void @{{.*}}foo8{{.*}}(i32* %{{.+}}) -// X86_64_WIN: define linkonce_odr x86_intrcc void @{{.*}}foo9{{.*}}(i32* %{{.+}}) +// X86_64_WIN: define dso_local x86_intrcc void @{{.*}}foo7{{.*}}(i32* %{{.+}}, i64 %{{.+}}) +// X86_64_WIN: define dso_local x86_intrcc void @{{.*}}foo8{{.*}}(i32* %{{.+}}) +// X86_64_WIN: define linkonce_odr dso_local x86_intrcc void @{{.*}}foo9{{.*}}(i32* %{{.+}}) // X86_WIN: @llvm.used = appending global [3 x i8*] [i8* bitcast (void (i32*, i32)* @{{.*}}foo7{{.*}} to i8*), i8* bitcast (void (i32*)* @{{.*}}foo8{{.*}} to i8*), i8* bitcast (void (i32*)* @{{.*}}foo9{{.*}} to i8*)], section "llvm.metadata" -// X86_WIN: define x86_intrcc void @{{.*}}foo7{{.*}}(i32* %{{.+}}, i32 %{{.+}}) -// X86_WIN: define x86_intrcc void @{{.*}}foo8{{.*}}(i32* %{{.+}}) -// X86_WIN: define linkonce_odr x86_intrcc void @{{.*}}foo9{{.*}}(i32* %{{.+}}) +// X86_WIN: define dso_local x86_intrcc void @{{.*}}foo7{{.*}}(i32* %{{.+}}, i32 %{{.+}}) +// X86_WIN: define dso_local x86_intrcc void @{{.*}}foo8{{.*}}(i32* %{{.+}}) +// X86_WIN: define linkonce_odr dso_local x86_intrcc void @{{.*}}foo9{{.*}}(i32* %{{.+}}) diff --git a/test/CodeGenCXX/block-capture.cpp b/test/CodeGenCXX/block-capture.cpp new file mode 100644 index 0000000000000..623838357a389 --- /dev/null +++ b/test/CodeGenCXX/block-capture.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -x c++ -std=c++11 -fblocks -emit-llvm %s -o - | FileCheck %s + +// CHECK: %struct.__block_byref_baz = type { i8*, %struct.__block_byref_baz*, i32, i32, i32 } +// CHECK: [[baz:%[0-9a-z_]*]] = alloca %struct.__block_byref_baz +// CHECK: [[bazref:%[0-9a-z_\.]*]] = getelementptr inbounds %struct.__block_byref_baz, %struct.__block_byref_baz* [[baz]], i32 0, i32 1 +// CHECK: store %struct.__block_byref_baz* [[baz]], %struct.__block_byref_baz** [[bazref]] +// CHECK: [[disposable:%[0-9a-z_]*]] = bitcast %struct.__block_byref_baz* [[baz]] to i8* +// CHECK: call void @_Block_object_dispose(i8* [[disposable]] + +int main() { + __block int baz = [&]() { return 0; }(); + return 0; +} diff --git a/test/CodeGenCXX/block-inalloca.cpp b/test/CodeGenCXX/block-inalloca.cpp new file mode 100644 index 0000000000000..b827dde7abdc7 --- /dev/null +++ b/test/CodeGenCXX/block-inalloca.cpp @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fblocks -emit-llvm -o - %s | FileCheck %s + +struct S { + S(const struct S &) {} +}; + +void (^b)(S) = ^(S) {}; + +// CHECK: [[DESCRIPTOR:%.*]] = getelementptr inbounds <{ i8*, %struct.S, [3 x i8] }>, <{ i8*, %struct.S, [3 x i8] }>* %0, i32 0, i32 0 +// CHECK: load i8*, i8** [[DESCRIPTOR]] + diff --git a/test/CodeGenCXX/builtin-operator-new-delete.cpp b/test/CodeGenCXX/builtin-operator-new-delete.cpp new file mode 100644 index 0000000000000..712805a62390a --- /dev/null +++ b/test/CodeGenCXX/builtin-operator-new-delete.cpp @@ -0,0 +1,71 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown %s \ +// RUN: -faligned-allocation -fsized-deallocation -emit-llvm -o - \ +// RUN: | FileCheck %s + +typedef __SIZE_TYPE__ size_t; + +// Declare an 'operator new' template to tickle a bug in __builtin_operator_new. +template 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); + +namespace std { + struct nothrow_t {}; + enum class align_val_t : size_t { __zero = 0, + __max = (size_t)-1 }; +} +std::nothrow_t nothrow; + +// Declare the reserved placement operators. +void *operator new(size_t, void*) throw(); +void operator delete(void*, void*) throw(); +void *operator new[](size_t, void*) throw(); +void operator delete[](void*, void*) throw(); + +// Declare the replaceable global allocation operators. +void *operator new(size_t, const std::nothrow_t &) throw(); +void *operator new[](size_t, const std::nothrow_t &) throw(); +void operator delete(void *, const std::nothrow_t &) throw(); +void operator delete[](void *, const std::nothrow_t &) throw(); + +// Declare some other placement operators. +void *operator new(size_t, void*, bool) throw(); +void *operator new[](size_t, void*, bool) throw(); + + +// CHECK-LABEL: define void @test_basic( +extern "C" void test_basic() { + // CHECK: call i8* @_Znwm(i64 4) [[ATTR_BUILTIN_NEW:#[^ ]*]] + // CHECK: call void @_ZdlPv({{.*}}) [[ATTR_BUILTIN_DELETE:#[^ ]*]] + // CHECK: ret void + __builtin_operator_delete(__builtin_operator_new(4)); +} +// CHECK: declare noalias i8* @_Znwm(i64) [[ATTR_NOBUILTIN:#[^ ]*]] +// CHECK: declare void @_ZdlPv(i8*) [[ATTR_NOBUILTIN_NOUNWIND:#[^ ]*]] + +// CHECK-LABEL: define void @test_aligned_alloc( +extern "C" void test_aligned_alloc() { + // CHECK: call i8* @_ZnwmSt11align_val_t(i64 4, i64 4) [[ATTR_BUILTIN_NEW:#[^ ]*]] + // CHECK: call void @_ZdlPvSt11align_val_t({{.*}}, i64 4) [[ATTR_BUILTIN_DELETE:#[^ ]*]] + __builtin_operator_delete(__builtin_operator_new(4, std::align_val_t(4)), std::align_val_t(4)); +} +// CHECK: declare noalias i8* @_ZnwmSt11align_val_t(i64, i64) [[ATTR_NOBUILTIN:#[^ ]*]] +// CHECK: declare void @_ZdlPvSt11align_val_t(i8*, i64) [[ATTR_NOBUILTIN_NOUNWIND:#[^ ]*]] + + +// CHECK-LABEL: define void @test_sized_delete( +extern "C" void test_sized_delete() { + // CHECK: call i8* @_Znwm(i64 4) [[ATTR_BUILTIN_NEW:#[^ ]*]] + // CHECK: call void @_ZdlPvm({{.*}}, i64 4) [[ATTR_BUILTIN_DELETE:#[^ ]*]] + __builtin_operator_delete(__builtin_operator_new(4), 4); +} +// CHECK: declare void @_ZdlPvm(i8*, i64) [[ATTR_NOBUILTIN_UNWIND:#[^ ]*]] + + +// CHECK-DAG: attributes [[ATTR_NOBUILTIN]] = {{[{].*}} nobuiltin {{.*[}]}} +// CHECK-DAG: attributes [[ATTR_NOBUILTIN_NOUNWIND]] = {{[{].*}} nobuiltin nounwind {{.*[}]}} + +// CHECK-DAG: attributes [[ATTR_BUILTIN_NEW]] = {{[{].*}} builtin {{.*[}]}} +// CHECK-DAG: attributes [[ATTR_BUILTIN_DELETE]] = {{[{].*}} builtin {{.*[}]}} diff --git a/test/CodeGenCXX/builtins.cpp b/test/CodeGenCXX/builtins.cpp index a49deea2524c5..33c714e9e1861 100644 --- a/test/CodeGenCXX/builtins.cpp +++ b/test/CodeGenCXX/builtins.cpp @@ -30,3 +30,19 @@ long y = __builtin_abs(-2l); extern const char char_memchr_arg[32]; char *memchr_result = __builtin_char_memchr(char_memchr_arg, 123, 32); // CHECK: call i8* @memchr(i8* getelementptr inbounds ([32 x i8], [32 x i8]* @char_memchr_arg, i32 0, i32 0), i32 123, i64 32) + +int constexpr_overflow_result() { + constexpr int x = 1; + // CHECK: alloca i32 + constexpr int y = 2; + // CHECK: alloca i32 + int z; + // CHECK: [[Z:%.+]] = alloca i32 + + __builtin_sadd_overflow(x, y, &z); + return z; + // CHECK: [[RET_PTR:%.+]] = extractvalue { i32, i1 } %0, 0 + // CHECK: store i32 [[RET_PTR]], i32* [[Z]] + // CHECK: [[RET_VAL:%.+]] = load i32, i32* [[Z]] + // CHECK: ret i32 [[RET_VAL]] +} diff --git a/test/CodeGenCXX/captured-statements.cpp b/test/CodeGenCXX/captured-statements.cpp index 95e73e548399b..c8832f1db714a 100644 --- a/test/CodeGenCXX/captured-statements.cpp +++ b/test/CodeGenCXX/captured-statements.cpp @@ -182,7 +182,7 @@ void test_capture_lambda() { } inline int test_captured_linkage() { - // CHECK-7: @_ZZ21test_captured_linkagevE1i = linkonce_odr global i32 0 + // CHECK-7: @_ZZ21test_captured_linkagevE1i = linkonce_odr {{(dso_local )?}}global i32 0 int j; #pragma clang __debug captured { diff --git a/test/CodeGenCXX/catch-undef-behavior.cpp b/test/CodeGenCXX/catch-undef-behavior.cpp index e8287538982b8..4513936e49a30 100644 --- a/test/CodeGenCXX/catch-undef-behavior.cpp +++ b/test/CodeGenCXX/catch-undef-behavior.cpp @@ -206,7 +206,7 @@ void bad_downcast_pointer(S *p) { // CHECK: %[[NONNULL:.*]] = icmp ne {{.*}}, null // CHECK: br i1 %[[NONNULL]], - // A null poiner access is guarded without -fsanitize=null. + // A null pointer access is guarded without -fsanitize=null. // DOWNCAST-NULL: %[[NONNULL:.*]] = icmp ne {{.*}}, null // DOWNCAST-NULL: br i1 %[[NONNULL]], @@ -371,7 +371,7 @@ class C : public A, public B // align=16 void downcast_pointer(B *b) { (void) static_cast(b); // Alignment check from EmitTypeCheck(TCK_DowncastPointer, ...) - // CHECK: [[SUB:%[.a-z0-9]*]] = getelementptr i8, i8* {{.*}}, i64 -16 + // CHECK: [[SUB:%[.a-z0-9]*]] = getelementptr inbounds i8, i8* {{.*}}, i64 -16 // CHECK-NEXT: [[C:%.+]] = bitcast i8* [[SUB]] to %class.C* // null check goes here // CHECK: [[FROM_PHI:%.+]] = phi %class.C* [ [[C]], {{.*}} ], {{.*}} @@ -388,7 +388,7 @@ void downcast_pointer(B *b) { void downcast_reference(B &b) { (void) static_cast(b); // Alignment check from EmitTypeCheck(TCK_DowncastReference, ...) - // CHECK: [[SUB:%[.a-z0-9]*]] = getelementptr i8, i8* {{.*}}, i64 -16 + // CHECK: [[SUB:%[.a-z0-9]*]] = getelementptr inbounds i8, i8* {{.*}}, i64 -16 // CHECK-NEXT: [[C:%.+]] = bitcast i8* [[SUB]] to %class.C* // Objectsize check goes here // CHECK: [[C_INT:%.+]] = ptrtoint %class.C* [[C]] to i64 diff --git a/test/CodeGenCXX/cfi-cross-dso.cpp b/test/CodeGenCXX/cfi-cross-dso.cpp index bfa0705c6f8f4..6d5e0591191cc 100644 --- a/test/CodeGenCXX/cfi-cross-dso.cpp +++ b/test/CodeGenCXX/cfi-cross-dso.cpp @@ -26,7 +26,7 @@ void g() { b.f(); } -// MS: @[[B_VTABLE:.*]] = private unnamed_addr constant { [2 x i8*] } {{.*}}@"\01??_R4B@?A@@6B@"{{.*}}@"\01?f@B@?A@@UEAAXXZ" +// MS: @[[B_VTABLE:.*]] = private unnamed_addr constant { [2 x i8*] } {{.*}}@"??_R4B@?A@@6B@"{{.*}}@"?f@B@?A@@UEAAXXZ" // CHECK: %[[VT:.*]] = load void (%struct.A*)**, void (%struct.A*)*** // CHECK: %[[VT2:.*]] = bitcast {{.*}}%[[VT]] to i8*, !nosanitize diff --git a/test/CodeGenCXX/cfi-icall.cpp b/test/CodeGenCXX/cfi-icall.cpp index 5f5778fc1f7c0..e53aeefd8a9be 100644 --- a/test/CodeGenCXX/cfi-icall.cpp +++ b/test/CodeGenCXX/cfi-icall.cpp @@ -21,7 +21,7 @@ void g() { } // ITANIUM: define internal void @_ZN12_GLOBAL__N_11fENS_1SE({{.*}} !type [[TS1:![0-9]+]] !type [[TS2:![0-9]+]] -// MS: define internal void @"\01?f@?A@@YAXUS@?A@@@Z"({{.*}} !type [[TS1:![0-9]+]] !type [[TS2:![0-9]+]] +// MS: define internal void @"?f@?A@@YAXUS@?A@@@Z"({{.*}} !type [[TS1:![0-9]+]] !type [[TS2:![0-9]+]] // CHECK: [[VOIDS1]] = distinct !{} // CHECK: [[TS1]] = !{i64 0, [[VOIDS1]]} diff --git a/test/CodeGenCXX/cfi-mfcall-incomplete.cpp b/test/CodeGenCXX/cfi-mfcall-incomplete.cpp new file mode 100644 index 0000000000000..345be124e93b8 --- /dev/null +++ b/test/CodeGenCXX/cfi-mfcall-incomplete.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux -fsanitize=cfi-mfcall -fsanitize-trap=cfi-mfcall -fvisibility hidden -emit-llvm -o - %s | FileCheck %s + +struct S; + +void f(S *s, void (S::*p)()) { + // CHECK-NOT: llvm.type.test + // CHECK: llvm.type.test{{.*}}!"_ZTSM1SFvvE.virtual" + // CHECK-NOT: llvm.type.test + (s->*p)(); +} + +// CHECK: declare i1 @llvm.type.test diff --git a/test/CodeGenCXX/cfi-mfcall.cpp b/test/CodeGenCXX/cfi-mfcall.cpp new file mode 100644 index 0000000000000..c16b20b8dcec8 --- /dev/null +++ b/test/CodeGenCXX/cfi-mfcall.cpp @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux -fsanitize=cfi-mfcall -fsanitize-trap=cfi-mfcall -fvisibility hidden -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux -fsanitize=cfi-mfcall -fsanitize-trap=cfi-mfcall -fvisibility default -emit-llvm -o - %s | FileCheck --check-prefix=DEFAULT %s + +struct B1 {}; +struct B2 {}; +struct B3 : B2 {}; +struct S : B1, B3 {}; + +// DEFAULT-NOT: llvm.type.test + +void f(S *s, void (S::*p)()) { + // CHECK: [[OFFSET:%.*]] = sub i64 {{.*}}, 1 + // CHECK: [[VFPTR:%.*]] = getelementptr i8, i8* %{{.*}}, i64 [[OFFSET]] + // CHECK: [[TT:%.*]] = call i1 @llvm.type.test(i8* [[VFPTR]], metadata !"_ZTSM1SFvvE.virtual") + // CHECK: br i1 [[TT]], label {{.*}}, label %[[TRAP1:[^,]*]] + + // CHECK: [[TRAP1]]: + // CHECK-NEXT: llvm.trap + + // CHECK: [[NVFPTR:%.*]] = bitcast void (%struct.S*)* {{.*}} to i8* + // CHECK: [[TT1:%.*]] = call i1 @llvm.type.test(i8* [[NVFPTR]], metadata !"_ZTSM2B1FvvE") + // CHECK: [[OR1:%.*]] = or i1 false, [[TT1]] + // CHECK: [[TT2:%.*]] = call i1 @llvm.type.test(i8* [[NVFPTR]], metadata !"_ZTSM2B2FvvE") + // CHECK: [[OR2:%.*]] = or i1 [[OR1]], [[TT2]] + // CHECK: br i1 [[OR2]], label {{.*}}, label %[[TRAP2:[^,]*]] + + // CHECK: [[TRAP2]]: + // CHECK-NEXT: llvm.trap + (s->*p)(); +} diff --git a/test/CodeGenCXX/cfi-ms-vbase-derived-cast.cpp b/test/CodeGenCXX/cfi-ms-vbase-derived-cast.cpp index 3276d8f33edc2..6142ca56878fb 100644 --- a/test/CodeGenCXX/cfi-ms-vbase-derived-cast.cpp +++ b/test/CodeGenCXX/cfi-ms-vbase-derived-cast.cpp @@ -8,7 +8,7 @@ struct foo { template struct bar : virtual public foo { void f() { - // CHECK: define{{.*}}@"\01?f@?$bar@Ubaz@@@@UEAAXXZ" + // CHECK: define{{.*}}@"?f@?$bar@Ubaz@@@@UEAAXXZ" // Load "this", vbtable, vbase offset and vtable. // CHECK: load // CHECK: load diff --git a/test/CodeGenCXX/cfi-ms-vbase-nvcall.cpp b/test/CodeGenCXX/cfi-ms-vbase-nvcall.cpp index ab610628232e2..d4232555c9d8a 100644 --- a/test/CodeGenCXX/cfi-ms-vbase-nvcall.cpp +++ b/test/CodeGenCXX/cfi-ms-vbase-nvcall.cpp @@ -16,7 +16,7 @@ struct baz : public bar { }; void f(baz *z) { - // CHECK: define{{.*}}@"\01?f@@YAXPEAUbaz@@@Z" + // CHECK: define{{.*}}@"?f@@YAXPEAUbaz@@@Z" // Load z, vbtable, vbase offset and vtable. // CHECK: load // CHECK: load diff --git a/test/CodeGenCXX/cfi-vcall-check-after-args.cpp b/test/CodeGenCXX/cfi-vcall-check-after-args.cpp new file mode 100644 index 0000000000000..4c2ea8c9e85fd --- /dev/null +++ b/test/CodeGenCXX/cfi-vcall-check-after-args.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -flto -flto-unit -triple x86_64-unknown-linux -fvisibility hidden -fsanitize=cfi-vcall -fsanitize-trap=cfi-vcall -emit-llvm -o - %s | FileCheck %s + +struct A { + virtual void f(int); +}; + +int g(); +void f(A *a) { + // CHECK: call i32 @_Z1gv() + // CHECK: call i1 @llvm.type.test + a->f(g()); +} diff --git a/test/CodeGenCXX/char8_t.cpp b/test/CodeGenCXX/char8_t.cpp new file mode 100644 index 0000000000000..f24f12d6df404 --- /dev/null +++ b/test/CodeGenCXX/char8_t.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -std=c++17 -emit-llvm -fchar8_t -triple x86_64-linux %s -o - | FileCheck %s +// RUN: %clang_cc1 -std=c++17 -emit-llvm -fchar8_t -triple x86_64-windows %s -o - -verify + +// CHECK: define void @_Z1fDu( +void f(char8_t c) {} // expected-error {{cannot mangle this built-in char8_t type yet}} + +// CHECK: define weak_odr void @_Z1gIiEvDTplplcvT__ELA4_KDuELDu114EE +template void g(decltype(T() + u8"foo" + u8'r')) {} +template void g(const char8_t*); diff --git a/test/CodeGenCXX/code-seg.cpp b/test/CodeGenCXX/code-seg.cpp new file mode 100644 index 0000000000000..7dad9274208ab --- /dev/null +++ b/test/CodeGenCXX/code-seg.cpp @@ -0,0 +1,139 @@ +// RUN: %clang_cc1 -emit-llvm -triple i686-pc-win32 -fms-extensions -verify -o - %s | FileCheck %s +// expected-no-diagnostics + +// Simple case + +int __declspec(code_seg("foo_one")) bar_one() { return 1; } +//CHECK: define {{.*}}bar_one{{.*}} section "foo_one" + +// Simple case - explicit attribute used over pragma +#pragma code_seg("foo_two") +int __declspec(code_seg("foo_three")) bar2() { return 2; } +//CHECK: define {{.*}}bar2{{.*}} section "foo_three" + +// Check that attribute on one function doesn't affect another +int another1() { return 1001; } +//CHECK: define {{.*}}another1{{.*}} section "foo_two" + +// Member functions + +struct __declspec(code_seg("foo_four")) Foo { + int bar3() {return 0;} + int bar4(); + int __declspec(code_seg("foo_six")) bar6() { return 6; } + int bar7() { return 7; } + struct Inner { + int bar5() { return 5; } + } z; + virtual int baz1() { return 1; } +}; + +struct __declspec(code_seg("foo_four")) FooTwo : Foo { + int baz1() { return 20; } +}; + +int caller1() { + Foo f; return f.bar3(); +} + +//CHECK: define {{.*}}bar3@Foo{{.*}} section "foo_four" +int Foo::bar4() { return 4; } +//CHECK: define {{.*}}bar4@Foo{{.*}} section "foo_four" + +#pragma code_seg("someother") + +int caller2() { + Foo f; + Foo *fp = new FooTwo; + return f.z.bar5() + f.bar6() + f.bar7() + fp->baz1(); +} +// MS Compiler and Docs do not match for nested routines +// Doc says: define {{.*}}bar5@Inner@Foo{{.*}} section "foo_four" +// Compiler says: define {{.*}}bar5@Inner@Foo{{.*}} section "foo_two" +// A bug has been reported: see https://reviews.llvm.org/D22931, the +// Microsoft feedback page is no longer available. +//CHECK: define {{.*}}bar5@Inner@Foo{{.*}} section "foo_two" +//CHECK: define {{.*}}bar6@Foo{{.*}} section "foo_six" +//CHECK: define {{.*}}bar7@Foo{{.*}} section "foo_four" +// Check that code_seg active at class declaration is not used on member +// declared outside class when it is not active. + +#pragma code_seg(push,"AnotherSeg") + +struct FooThree { + int bar8(); + int bar9() { return 9; } +}; + +#pragma code_seg(pop) + + +int FooThree::bar8() {return 0;} + +int caller3() +{ + FooThree f; + return f.bar8() + f.bar9(); +} + +//CHECK: define {{.*}}bar8@FooThree{{.*}} section "someother" +//CHECK: define {{.*}}bar9@FooThree{{.*}} section "AnotherSeg" + +struct NonTrivialCopy { + NonTrivialCopy(); + NonTrivialCopy(const NonTrivialCopy&); + ~NonTrivialCopy(); +}; + +// check the section for compiler-generated function with declspec. + +struct __declspec(code_seg("foo_seven")) FooFour { + FooFour() {} + int __declspec(code_seg("foo_eight")) bar10(int t) { return t; } + NonTrivialCopy f; +}; + +//CHECK: define {{.*}}0FooFour@@QAE@ABU0@@Z{{.*}} section "foo_seven" +// check the section for compiler-generated function with no declspec. + +struct FooFive { + FooFive() {} + int __declspec(code_seg("foo_nine")) bar11(int t) { return t; } + NonTrivialCopy f; +}; + +//CHECK: define {{.*}}0FooFive@@QAE@ABU0@@Z{{.*}} section "someother" + +#pragma code_seg("YetAnother") +int caller4() +{ + FooFour z1; + FooFour z2 = z1; + FooFive y1; + FooFive y2 = y1; + return z2.bar10(0) + y2.bar11(1); +} + +//CHECK: define {{.*}}bar10@FooFour{{.*}} section "foo_eight" +//CHECK: define {{.*}}bar11@FooFive{{.*}} section "foo_nine" + +struct FooSix { + #pragma code_seg("foo_ten") + int bar12() { return 12; } + #pragma code_seg("foo_eleven") + int bar13() { return 13; } +}; + +int bar14() { return 14; } +//CHECK: define {{.*}}bar14{{.*}} section "foo_eleven" + +int caller5() +{ + FooSix fsix; + return fsix.bar12() + fsix.bar13(); +} + +//CHECK: define {{.*}}bar12@FooSix{{.*}} section "foo_ten" +//CHECK: define {{.*}}bar13@FooSix{{.*}} section "foo_eleven" +//CHECK: define {{.*}}baz1@FooTwo{{.*}} section "foo_four" + diff --git a/test/CodeGenCXX/code-seg1.cpp b/test/CodeGenCXX/code-seg1.cpp new file mode 100644 index 0000000000000..93be3e520a546 --- /dev/null +++ b/test/CodeGenCXX/code-seg1.cpp @@ -0,0 +1,87 @@ +// RUN: %clang_cc1 -emit-llvm -triple i686-pc-win32 -fms-extensions -verify -o - %s | FileCheck %s +// expected-no-diagnostics +// The Microsoft document says: "When this attribute is applied to a class, +// all member functions of the class and nested classes - this includes +// compiler-generated special member functions - are put in the specified segment." +// But the MS compiler does not always follow that. A bug has been reported: +// see https://reviews.llvm.org/D22931, the Microsoft feedback page is no +// longer available. +// The MS compiler will apply a declspec from the parent class if there is no +// #pragma code_seg active at the class definition. If there is an active +// code_seg that is used instead. + +// No active code_seg + +struct __declspec(code_seg("foo_outer")) Foo1 { + struct Inner { + void bar1(); + static void bar2(); + }; +}; +void Foo1::Inner::bar1() {} +void Foo1::Inner::bar2() {} + +//CHECK: define {{.*}}bar1@Inner@Foo1{{.*}} section "foo_outer" +//CHECK: define {{.*}}bar2@Inner@Foo1{{.*}} section "foo_outer" + +struct __declspec(code_seg("foo_outer")) Foo2 { + struct __declspec(code_seg("foo_inner")) Inner { + void bar1(); + static void bar2(); + }; +}; +void Foo2::Inner::bar1() {} +void Foo2::Inner::bar2() {} + +//CHECK: define {{.*}}bar1@Inner@Foo2{{.*}} section "foo_inner" +//CHECK: define {{.*}}bar2@Inner@Foo2{{.*}} section "foo_inner" + +#pragma code_seg(push, "otherseg") +struct __declspec(code_seg("foo_outer")) Foo3 { + struct Inner { + void bar1(); + static void bar2(); + }; +}; +void Foo3::Inner::bar1() {} +void Foo3::Inner::bar2() {} + +//CHECK: define {{.*}}bar1@Inner@Foo3{{.*}} section "otherseg" +//CHECK: define {{.*}}bar2@Inner@Foo3{{.*}} section "otherseg" + +struct __declspec(code_seg("foo_outer")) Foo4 { + struct __declspec(code_seg("foo_inner")) Inner { + void bar1(); + static void bar2(); + }; +}; +void Foo4::Inner::bar1() {} +void Foo4::Inner::bar2() {} + +//CHECK: define {{.*}}bar1@Inner@Foo4{{.*}} section "foo_inner" +//CHECK: define {{.*}}bar2@Inner@Foo4{{.*}} section "foo_inner" + +#pragma code_seg(pop) +// Back to no active pragma +struct __declspec(code_seg("foo_outer")) Foo5 { + struct Inner { + void bar1(); + static void bar2(); + struct __declspec(code_seg("inner1_seg")) Inner1 { + struct Inner2 { + void bar1(); + static void bar2(); + }; + }; + }; +}; +void Foo5::Inner::bar1() {} +void Foo5::Inner::bar2() {} +void Foo5::Inner::Inner1::Inner2::bar1() {} +void Foo5::Inner::Inner1::Inner2::bar2() {} + +//CHECK: define {{.*}}bar1@Inner@Foo5{{.*}} section "foo_outer" +//CHECK: define {{.*}}bar2@Inner@Foo5{{.*}} section "foo_outer" +//CHECK: define {{.*}}bar1@Inner2@Inner1@Inner@Foo5{{.*}} section "inner1_seg" +//CHECK: define {{.*}}bar2@Inner2@Inner1@Inner@Foo5{{.*}} section "inner1_seg" + diff --git a/test/CodeGenCXX/code-seg2.cpp b/test/CodeGenCXX/code-seg2.cpp new file mode 100644 index 0000000000000..ab72bf44cb89e --- /dev/null +++ b/test/CodeGenCXX/code-seg2.cpp @@ -0,0 +1,111 @@ +// RUN: %clang_cc1 -emit-llvm -triple i686-pc-win32 -std=c++11 -fms-extensions -verify -o - %s | FileCheck %s +// expected-no-diagnostics + +// Class member templates + +#pragma code_seg(push, "something") + +template +struct __declspec(code_seg("foo_one")) ClassOne { + int bar1(T t) { return int(t); } + int bar2(T t); + int bar3(T t); +}; + +template +int ClassOne::bar2(T t) { + return int(t); +} + +int caller1() { + ClassOne coi; + return coi.bar1(6) + coi.bar2(3); +} + +//CHECK: define {{.*}}bar1@?$ClassOne{{.*}} section "foo_one" +//CHECK: define {{.*}}bar2@?$ClassOne{{.*}} section "foo_one" + + +template +struct ClassTwo { + int bar11(T t) { return int(t); } + int bar22(T t); + int bar33(T t); +}; + +#pragma code_seg("newone") + +template +int ClassTwo::bar22(T t) { + return int(t); +} + +#pragma code_seg("someother") + +template +int ClassTwo::bar33(T t) { + return int(t); +} + +#pragma code_seg("yetanother") + +int caller2() { + ClassTwo coi; + return coi.bar11(6) + coi.bar22(3) + coi.bar33(44); +} + +//CHECK: define {{.*}}bar11@?$ClassTwo{{.*}} section "something" +//CHECK: define {{.*}}bar22@?$ClassTwo{{.*}} section "newone" +//CHECK: define {{.*}}bar33@?$ClassTwo{{.*}} section "someother" + +template<> +struct ClassOne +{ + int bar44(double d) { return 1; } +}; +template<> +struct __declspec(code_seg("foo_three")) ClassOne +{ + int bar55(long d) { return 1; } +}; + +#pragma code_seg("onemore") +int caller3() { + ClassOne d; + ClassOne l; + return d.bar44(1.0)+l.bar55(1); +} + +//CHECK: define {{.*}}bar44{{.*}} section "yetanother" +//CHECK: define {{.*}}bar55{{.*}} section "foo_three" + + +// Function templates +template +int __declspec(code_seg("foo_four")) bar66(T t) { return int(t); } + +// specializations do not take the segment from primary +template<> +int bar66(int i) { return 0; } + +#pragma code_seg(pop) + +template<> +int bar66(char c) { return 0; } + +struct A1 {int i;}; +template<> +int __declspec(code_seg("foo_five")) bar66(A1 a) { return a.i; } + +int caller4() +{ +// but instantiations do use the section from the primary +return bar66(0) + bar66(1.0) + bar66('c'); +} +//CHECK: define {{.*}}bar66@H{{.*}} section "onemore" +//CHECK-NOT: define {{.*}}bar66@D{{.*}} section +//CHECK: define {{.*}}bar66@UA1{{.*}} section "foo_five" +//CHECK: define {{.*}}bar66@N{{.*}} section "foo_four" + + + diff --git a/test/CodeGenCXX/code-seg3.cpp b/test/CodeGenCXX/code-seg3.cpp new file mode 100644 index 0000000000000..d6f267747e3c1 --- /dev/null +++ b/test/CodeGenCXX/code-seg3.cpp @@ -0,0 +1,65 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -fms-extensions %s -triple x86_64-pc-win32 +// expected-no-diagnostics + +// Non-Member Function Overloading is involved + +int __declspec(code_seg("foo_one")) bar_one(int) { return 1; } +//CHECK: define {{.*}}bar_one{{.*}} section "foo_one" +int __declspec(code_seg("foo_two")) bar_one(int,float) { return 11; } +//CHECK: define {{.*}}bar_one{{.*}} section "foo_two" +int __declspec(code_seg("foo_three")) bar_one(float) { return 12; } +//CHECK: define {{.*}}bar_one{{.*}} section "foo_three" + +// virtual function overloading is involved + +struct __declspec(code_seg("my_one")) Base3 { + virtual int barA(int) { return 1; } + virtual int barA(int,float) { return 2; } + virtual int barA(float) { return 3; } + + virtual void __declspec(code_seg("my_two")) barB(int) { } + virtual void __declspec(code_seg("my_three")) barB(float) { } + virtual void __declspec(code_seg("my_four")) barB(int, float) { } + +}; + +//CHECK: define {{.*}}barA@Base3{{.*}} section "my_one" +//CHECK: define {{.*}}barA@Base3{{.*}} section "my_one" +//CHECK: define {{.*}}barA@Base3{{.*}} section "my_one" +//CHECK: define {{.*}}barB@Base3{{.*}} section "my_two" +//CHECK: define {{.*}}barB@Base3{{.*}} section "my_three" +//CHECK: define {{.*}}barB@Base3{{.*}} section "my_four" + +#pragma code_seg("another") +// Member functions +struct __declspec(code_seg("foo_four")) Foo { + int bar3() {return 0;} + __declspec(code_seg("foo_lala")) int bar4() {return 0;} }; int caller() {Foo f; return f.bar3() + f.bar4(); } + +//CHECK: define {{.*}}bar3@Foo{{.*}} section "foo_four" +//CHECK: define {{.*}}bar4@Foo{{.*}} section "foo_lala" + +// Lambdas +#pragma code_seg("something") + +int __declspec(code_seg("foo")) bar1() +{ + int lala = 4; + auto l = [=](int i) { return i+4; }; + return l(-4); +} + +//CHECK: define {{.*}}bar1{{.*}} section "foo" +//CHECK: define {{.*}}lambda{{.*}}bar1{{.*}} section "something" + +double __declspec(code_seg("foo")) bar2() +{ + double lala = 4.0; + auto l = [=](double d) __declspec(code_seg("another")) { return d+4.0; }; + return l(4.0); +} + +//CHECK: define {{.*}}bar2{{.*}} section "foo" +//CHECK: define {{.*}}lambda{{.*}}bar2{{.*}} section "another" + + diff --git a/test/CodeGenCXX/conditional-temporaries.cpp b/test/CodeGenCXX/conditional-temporaries.cpp index a3cc2fef1e8fd..e08de61f9d41d 100644 --- a/test/CodeGenCXX/conditional-temporaries.cpp +++ b/test/CodeGenCXX/conditional-temporaries.cpp @@ -1,4 +1,6 @@ +// REQUIRES: amdgpu-registered-target // RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 -O3 | FileCheck %s +// RUN: %clang_cc1 -emit-llvm %s -o - -triple=amdgcn-amd-amdhsa -O3 | FileCheck %s namespace { diff --git a/test/CodeGenCXX/const-base-cast.cpp b/test/CodeGenCXX/const-base-cast.cpp index dd980d5469bf4..bb08b9d21fcfc 100644 --- a/test/CodeGenCXX/const-base-cast.cpp +++ b/test/CodeGenCXX/const-base-cast.cpp @@ -7,4 +7,4 @@ struct B { char y; }; struct C : A,B {}; unsigned char x = ((char*)(B*)(C*)0x1000) - (char*)0x1000; -// CHECK: @x = global i8 1 +// CHECK: @x = {{(dso_local )?}}global i8 1 diff --git a/test/CodeGenCXX/const-global-linkage.cpp b/test/CodeGenCXX/const-global-linkage.cpp index e1e9321974792..2ec64cfeeecf1 100644 --- a/test/CodeGenCXX/const-global-linkage.cpp +++ b/test/CodeGenCXX/const-global-linkage.cpp @@ -4,7 +4,7 @@ const int x = 10; const int y = 20; const volatile int z = 30; // CHECK-NOT: @x -// CHECK: @z = constant i32 30 +// CHECK: @z = {{(dso_local )?}}constant i32 30 // CHECK: @_ZL1y = internal constant i32 20 const int& b() { return y; } @@ -12,6 +12,6 @@ const char z1[] = "asdf"; const char z2[] = "zxcv"; const volatile char z3[] = "zxcv"; // CHECK-NOT: @z1 -// CHECK: @z3 = constant +// CHECK: @z3 = {{(dso_local )?}}constant // CHECK: @_ZL2z2 = internal constant const char* b2() { return z2; } diff --git a/test/CodeGenCXX/const-init-cxx11.cpp b/test/CodeGenCXX/const-init-cxx11.cpp index c4962bc08ad69..801d7b1e19cc4 100644 --- a/test/CodeGenCXX/const-init-cxx11.cpp +++ b/test/CodeGenCXX/const-init-cxx11.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -w -triple x86_64-elf-gnu -emit-llvm -o - %s -std=c++11 | FileCheck %s +// RUN: %clang_cc1 -w -fmerge-all-constants -triple x86_64-elf-gnu -emit-llvm -o - %s -std=c++11 | FileCheck %s // FIXME: The padding in all these objects should be zero-initialized. namespace StructUnion { diff --git a/test/CodeGenCXX/constructor-alias.cpp b/test/CodeGenCXX/constructor-alias.cpp index 8359bb90a051d..ee2e57b711c96 100644 --- a/test/CodeGenCXX/constructor-alias.cpp +++ b/test/CodeGenCXX/constructor-alias.cpp @@ -9,4 +9,4 @@ struct B { B::B() { } -// CHECK: @_ZN1BC1Ev = alias void (%struct.B*), void (%struct.B*)* @_ZN1BC2Ev +// CHECK: @_ZN1BC1Ev = unnamed_addr alias void (%struct.B*), void (%struct.B*)* @_ZN1BC2Ev diff --git a/test/CodeGenCXX/constructor-destructor-return-this.cpp b/test/CodeGenCXX/constructor-destructor-return-this.cpp index 164fda3c1c38f..f6450e2d4d77d 100644 --- a/test/CodeGenCXX/constructor-destructor-return-this.cpp +++ b/test/CodeGenCXX/constructor-destructor-return-this.cpp @@ -45,8 +45,8 @@ B::~B() { } // 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@@UAE@XZ"(%class.B* %this) +// CHECKMS-LABEL: define dso_local x86_thiscallcc %class.B* @"??0B@@QAE@PAH@Z"(%class.B* returned %this, i32* %i) +// CHECKMS-LABEL: define dso_local x86_thiscallcc void @"??1B@@UAE@XZ"(%class.B* %this) class C : public A, public B { public: @@ -83,8 +83,8 @@ C::~C() { } // CHECKIOS5-LABEL: define void @_ZN1CD0Ev(%class.C* %this) // CHECKIOS5-LABEL: define void @_ZThn8_N1CD0Ev(%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) +// CHECKMS-LABEL: define dso_local x86_thiscallcc %class.C* @"??0C@@QAE@PAHPAD@Z"(%class.C* returned %this, i32* %i, i8* %c) +// CHECKMS-LABEL: define dso_local x86_thiscallcc void @"??1C@@UAE@XZ"(%class.C* %this) class D : public virtual A { public: @@ -110,8 +110,8 @@ D::~D() { } // 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@@UAE@XZ"(%class.D* %this) +// CHECKMS-LABEL: define dso_local x86_thiscallcc %class.D* @"??0D@@QAE@XZ"(%class.D* returned %this, i32 %is_most_derived) +// CHECKMS-LABEL: define dso_local x86_thiscallcc void @"??1D@@UAE@XZ"(%class.D* %this) class E { public: diff --git a/test/CodeGenCXX/constructor-direct-call.cpp b/test/CodeGenCXX/constructor-direct-call.cpp index 9567d0968dae4..bcddc0fa7a496 100644 --- a/test/CodeGenCXX/constructor-direct-call.cpp +++ b/test/CodeGenCXX/constructor-direct-call.cpp @@ -9,7 +9,7 @@ void f1() { Test1 var; var.Test1::Test1(); - // CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* %{{.*}}, i8* %{{.*}}, i32 4, i32 4, i1 false) + // CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %{{.*}}, i8* align 4 %{{.*}}, i32 4, i1 false) var.Test1::Test1(var); } @@ -28,7 +28,7 @@ void f2() { // 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) + // CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %{{.*}}, i8* align 4 %{{.*}}, i32 8, i1 false) var.Test2::Test2(var); } diff --git a/test/CodeGenCXX/constructors.cpp b/test/CodeGenCXX/constructors.cpp index a898140383407..9322c410f272b 100644 --- a/test/CodeGenCXX/constructors.cpp +++ b/test/CodeGenCXX/constructors.cpp @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin10 %s -emit-llvm -o - | FileCheck %s --implicit-check-not=should_not_appear_in_output +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 %s -emit-llvm -o - | FileCheck %s --implicit-check-not=should_not_appear_in_output --check-prefixes=CHECK,NULL-INVALID +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 %s -emit-llvm -fno-delete-null-pointer-checks -o - | FileCheck %s --implicit-check-not=should_not_appear_in_output --check-prefixes=CHECK,NULL-VALID struct Member { int x; Member(); Member(int); Member(const Member &); }; struct VBase { int x; VBase(); VBase(int); VBase(const VBase &); }; @@ -21,10 +22,12 @@ struct A { A::A(struct Undeclared &ref) : mem(0) {} // Check that delegation works. -// CHECK-LABEL: define void @_ZN1AC2ER10Undeclared(%struct.A* %this, %struct.Undeclared* nonnull %ref) unnamed_addr +// NULL-INVALID-LABEL: define void @_ZN1AC2ER10Undeclared(%struct.A* %this, %struct.Undeclared* nonnull %ref) unnamed_addr +// NULL-VALID-LABEL: define void @_ZN1AC2ER10Undeclared(%struct.A* %this, %struct.Undeclared* %ref) unnamed_addr // CHECK: call void @_ZN6MemberC1Ei( -// CHECK-LABEL: define void @_ZN1AC1ER10Undeclared(%struct.A* %this, %struct.Undeclared* nonnull %ref) unnamed_addr +// NULL-INVALID-LABEL: define void @_ZN1AC1ER10Undeclared(%struct.A* %this, %struct.Undeclared* nonnull %ref) unnamed_addr +// NULL-VALID-LABEL: define void @_ZN1AC1ER10Undeclared(%struct.A* %this, %struct.Undeclared* %ref) unnamed_addr // CHECK: call void @_ZN1AC2ER10Undeclared( A::A(ValueClass v) : mem(v.y - v.x) {} @@ -43,11 +46,13 @@ struct B : A { B::B(struct Undeclared &ref) : A(ref), mem(1) {} -// CHECK-LABEL: define void @_ZN1BC2ER10Undeclared(%struct.B* %this, %struct.Undeclared* nonnull %ref) unnamed_addr +// NULL-INVALID-LABEL: define void @_ZN1BC2ER10Undeclared(%struct.B* %this, %struct.Undeclared* nonnull %ref) unnamed_addr +// NULL-VALID-LABEL: define void @_ZN1BC2ER10Undeclared(%struct.B* %this, %struct.Undeclared* %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 +// NULL-INVALID-LABEL: define void @_ZN1BC1ER10Undeclared(%struct.B* %this, %struct.Undeclared* nonnull %ref) unnamed_addr +// NULL-VALID-LABEL: define void @_ZN1BC1ER10Undeclared(%struct.B* %this, %struct.Undeclared* %ref) unnamed_addr // CHECK: call void @_ZN1BC2ER10Undeclared( diff --git a/test/CodeGenCXX/copy-constructor-elim.cpp b/test/CodeGenCXX/copy-constructor-elim.cpp index 4abe456e4b29d..7ba231071e76d 100644 --- a/test/CodeGenCXX/copy-constructor-elim.cpp +++ b/test/CodeGenCXX/copy-constructor-elim.cpp @@ -56,4 +56,4 @@ extern "C" V f() { return gv1; } // Make sure that we obey the destination's alignment requirements when emitting // the copy. // CHECK-LABEL: define {{.*}} @f( -// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}({{.*}}, i8* bitcast (%struct.V* @gv1 to i8*), {{i64|i32}} 4, i32 4, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i64|i32}}({{.*}}align 4{{.*}}, i8* align 8 bitcast (%struct.V* @gv1 to i8*), {{i64|i32}} 4, i1 false) diff --git a/test/CodeGenCXX/copy-constructor-synthesis-2.cpp b/test/CodeGenCXX/copy-constructor-synthesis-2.cpp index 9d7e18e80f673..7940101c0cfbd 100644 --- a/test/CodeGenCXX/copy-constructor-synthesis-2.cpp +++ b/test/CodeGenCXX/copy-constructor-synthesis-2.cpp @@ -10,15 +10,15 @@ extern PR23373 pr23373_a; PR23373 pr23373_b(pr23373_a); // CHECK-LABEL: define {{.*}} @__cxx_global_var_init( -// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i32|i64}}({{.*}} @pr23373_b{{.*}}, {{.*}} @pr23373_a{{.*}}, [[W:i32|i64]] 4, i32 4, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.{{i32|i64}}({{.*}}align 4{{.*}}@pr23373_b{{.*}}, {{.*}}align 4{{.*}} @pr23373_a{{.*}}, [[W:i32|i64]] 4, i1 false) PR23373 pr23373_f() { return pr23373_a; } // CHECK-LABEL: define {{.*}} @_Z9pr23373_fv( -// CHECK: call void @llvm.memcpy.p0i8.p0i8.[[W]]({{.*}}, [[W]] 4, i32 4, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.[[W]]({{.*}}align 4{{.*}}align 4{{.*}}, [[W]] 4, i1 false) void pr23373_g(PR23373 &a, PR23373 &b) { a = b; } // CHECK-LABEL: define {{.*}} @_Z9pr23373_g -// CHECK: call void @llvm.memcpy.p0i8.p0i8.[[W]]({{.*}}, [[W]] 4, i32 4, i1 false) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.[[W]]({{.*}}align 4{{.*}}align 4{{.*}}, [[W]] 4, i1 false) struct A { virtual void a(); }; A x(A& y) { return y; } diff --git a/test/CodeGenCXX/copy-constructor-synthesis.cpp b/test/CodeGenCXX/copy-constructor-synthesis.cpp index 5a2cc1440f742..4fdd8a35c4ded 100644 --- a/test/CodeGenCXX/copy-constructor-synthesis.cpp +++ b/test/CodeGenCXX/copy-constructor-synthesis.cpp @@ -143,7 +143,7 @@ void f(B b1) { // CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds [[A]], [[A]]* [[OTHER]], i32 0, i32 1 // 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: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[T4]], i8* align 8 [[T5]], i64 8, i1 false) // CHECK-NEXT: ret [[A]]* [[THIS]] // CHECK-LABEL: define linkonce_odr void @_ZN6PR66281BC2ERKS0_(%"struct.PR6628::B"* %this, %"struct.PR6628::B"* dereferenceable({{[0-9]+}})) unnamed_addr @@ -172,7 +172,7 @@ void f(B b1) { // CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds [[A]], [[A]]* [[OTHER]], i32 0, i32 1 // 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: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[T4]], i8* align 8 [[T5]], i64 8, i1 false) // CHECK-NEXT: ret void } diff --git a/test/CodeGenCXX/ctor-dtor-alias.cpp b/test/CodeGenCXX/ctor-dtor-alias.cpp index 6826ee5796caf..4715111a1439e 100644 --- a/test/CodeGenCXX/ctor-dtor-alias.cpp +++ b/test/CodeGenCXX/ctor-dtor-alias.cpp @@ -1,5 +1,7 @@ -// RUN: %clang_cc1 %s -triple i686-linux -emit-llvm -o - -mconstructor-aliases | FileCheck --check-prefix=NOOPT %s - +// RUN: %clang_cc1 %s -triple i686-linux -emit-llvm -o - -mconstructor-aliases > %t +// RUN: FileCheck --check-prefix=NOOPT1 --input-file=%t %s +// RUN: FileCheck --check-prefix=NOOPT2 --input-file=%t %s +// RUN: FileCheck --check-prefix=NOOPT3 --input-file=%t %s // RUN: %clang_cc1 %s -triple i686-linux -emit-llvm -o - -mconstructor-aliases -O1 -disable-llvm-passes > %t // RUN: FileCheck --check-prefix=CHECK1 --input-file=%t %s // RUN: FileCheck --check-prefix=CHECK2 --input-file=%t %s @@ -11,16 +13,23 @@ // RUN: %clang_cc1 %s -triple i686-pc-windows-gnu -emit-llvm -o - -mconstructor-aliases -O1 -disable-llvm-passes | FileCheck --check-prefix=COFF %s namespace test1 { -// Test that we produce the apropriate comdats when creating aliases to +// Test that we produce the appropriate comdats when creating aliases to // weak_odr constructors and destructors. -// CHECK1: @_ZN5test16foobarIvEC1Ev = weak_odr alias void {{.*}} @_ZN5test16foobarIvEC2Ev -// CHECK1: @_ZN5test16foobarIvED1Ev = weak_odr alias void (%"struct.test1::foobar"*), void (%"struct.test1::foobar"*)* @_ZN5test16foobarIvED2Ev +// CHECK1: @_ZN5test16foobarIvEC1Ev = weak_odr unnamed_addr alias void {{.*}} @_ZN5test16foobarIvEC2Ev +// CHECK1: @_ZN5test16foobarIvED1Ev = weak_odr unnamed_addr alias void (%"struct.test1::foobar"*), void (%"struct.test1::foobar"*)* @_ZN5test16foobarIvED2Ev // CHECK1: define weak_odr void @_ZN5test16foobarIvEC2Ev({{.*}} comdat($_ZN5test16foobarIvEC5Ev) // CHECK1: define weak_odr void @_ZN5test16foobarIvED2Ev({{.*}} comdat($_ZN5test16foobarIvED5Ev) // CHECK1: define weak_odr void @_ZN5test16foobarIvED0Ev({{.*}} comdat($_ZN5test16foobarIvED5Ev) // CHECK1-NOT: comdat +// This should happen regardless of the opt level. +// NOOPT1: @_ZN5test16foobarIvEC1Ev = weak_odr unnamed_addr alias void {{.*}} @_ZN5test16foobarIvEC2Ev +// NOOPT1: @_ZN5test16foobarIvED1Ev = weak_odr unnamed_addr alias void (%"struct.test1::foobar"*), void (%"struct.test1::foobar"*)* @_ZN5test16foobarIvED2Ev +// NOOPT1: define weak_odr void @_ZN5test16foobarIvEC2Ev({{.*}} comdat($_ZN5test16foobarIvEC5Ev) +// NOOPT1: define weak_odr void @_ZN5test16foobarIvED2Ev({{.*}} comdat($_ZN5test16foobarIvED5Ev) +// NOOPT1: define weak_odr void @_ZN5test16foobarIvED0Ev({{.*}} comdat($_ZN5test16foobarIvED5Ev) + // COFF doesn't support comdats with arbitrary names (C5/D5). // COFF: define weak_odr {{.*}} void @_ZN5test16foobarIvEC2Ev({{.*}} comdat align // COFF: define weak_odr {{.*}} void @_ZN5test16foobarIvEC1Ev({{.*}} comdat align @@ -37,12 +46,17 @@ template struct foobar; } namespace test2 { -// test that when the destrucor is linkonce_odr we just replace every use of +// test that when the destructor is linkonce_odr we just replace every use of // C1 with C2. // CHECK1: define internal void @__cxx_global_var_init() // CHECK1: call void @_ZN5test26foobarIvEC2Ev // CHECK1: define linkonce_odr void @_ZN5test26foobarIvEC2Ev({{.*}} comdat align + +// At -O0, we should still emit the complete constructor. +// NOOPT1: define internal void @__cxx_global_var_init() +// NOOPT1: call void @_ZN5test26foobarIvEC1Ev +// NOOPT1: define linkonce_odr void @_ZN5test26foobarIvEC1Ev({{.*}} comdat align void g(); template struct foobar { foobar() { g(); } @@ -57,6 +71,11 @@ namespace test3 { // CHECK1: define internal void @__cxx_global_var_init.1() // CHECK1: call i32 @__cxa_atexit{{.*}}_ZN5test312_GLOBAL__N_11AD2Ev // CHECK1: define internal void @_ZN5test312_GLOBAL__N_11AD2Ev( + +// We can use an alias for internal symbols at -O0. +// NOOPT2: _ZN5test312_GLOBAL__N_11BD1Ev = internal unnamed_addr alias void {{.*}} @_ZN5test312_GLOBAL__N_11BD2Ev +// NOOPT2: define internal void @__cxx_global_var_init.1() +// NOOPT2: call i32 @__cxa_atexit{{.*}}_ZN5test312_GLOBAL__N_11BD1Ev namespace { struct A { ~A() {} @@ -77,11 +96,12 @@ namespace test4 { // CHECK1: call i32 @__cxa_atexit{{.*}}_ZN5test41AD2Ev // CHECK1: define linkonce_odr void @_ZN5test41AD2Ev({{.*}} comdat align - // test that we don't do this optimization at -O0 so that the debugger can - // see both destructors. - // NOOPT: define internal void @__cxx_global_var_init.2() - // NOOPT: call i32 @__cxa_atexit{{.*}}@_ZN5test41BD2Ev - // NOOPT: define linkonce_odr void @_ZN5test41BD2Ev({{.*}} comdat align + // Test that we don't do this optimization at -O0 and call the complete + // destructor for B instead. This enables the debugger to see both + // destructors. + // NOOPT2: define internal void @__cxx_global_var_init.2() + // NOOPT2: call i32 @__cxa_atexit{{.*}}@_ZN5test41BD1Ev + // NOOPT2: define linkonce_odr void @_ZN5test41BD1Ev({{.*}} comdat align struct A { virtual ~A() {} }; @@ -129,6 +149,11 @@ namespace test7 { // out if we should). // pr17875. // CHECK3: define void @_ZN5test71BD2Ev + + // At -O0, we should emit both destructors, the complete can be an alias to + // the base one. + // NOOPT3: @_ZN5test71BD1Ev = unnamed_addr alias void {{.*}} @_ZN5test71BD2Ev + // NOOPT3: define void @_ZN5test71BD2Ev template struct A { ~A() {} }; @@ -141,7 +166,7 @@ namespace test7 { namespace test8 { // Test that we replace ~zed with ~bar which is an alias to ~foo. - // CHECK4: @_ZN5test83barD2Ev = alias {{.*}} @_ZN5test83fooD2Ev + // CHECK4: @_ZN5test83barD2Ev = unnamed_addr alias {{.*}} @_ZN5test83fooD2Ev // CHECK4: define internal void @__cxx_global_var_init.5() // CHECK4: call i32 @__cxa_atexit({{.*}}@_ZN5test83barD2Ev struct foo { @@ -232,8 +257,8 @@ struct foo : public bar { ~foo(); }; foo::~foo() {} -// CHECK6: @_ZN6test113fooD2Ev = alias {{.*}} @_ZN6test113barD2Ev -// CHECK6: @_ZN6test113fooD1Ev = alias {{.*}} @_ZN6test113fooD2Ev +// CHECK6: @_ZN6test113fooD2Ev = unnamed_addr alias {{.*}} @_ZN6test113barD2Ev +// CHECK6: @_ZN6test113fooD1Ev = unnamed_addr alias {{.*}} @_ZN6test113fooD2Ev } namespace test12 { @@ -243,6 +268,6 @@ struct foo { }; template class foo<1>; -// CHECK6: @_ZN6test123fooILi1EED1Ev = weak_odr alias {{.*}} @_ZN6test123fooILi1EED2Ev +// CHECK6: @_ZN6test123fooILi1EED1Ev = weak_odr unnamed_addr alias {{.*}} @_ZN6test123fooILi1EED2Ev // CHECK6: define weak_odr void @_ZN6test123fooILi1EED2Ev({{.*}}) {{.*}} comdat($_ZN6test123fooILi1EED5Ev) } diff --git a/test/CodeGenCXX/cxx0x-delegating-ctors.cpp b/test/CodeGenCXX/cxx0x-delegating-ctors.cpp index dcc055696e4dd..614983d4fc596 100644 --- a/test/CodeGenCXX/cxx0x-delegating-ctors.cpp +++ b/test/CodeGenCXX/cxx0x-delegating-ctors.cpp @@ -66,7 +66,7 @@ namespace PR12890 { X::X(int) : X() {} } // CHECK: define {{.*}} @_ZN7PR128901XC1Ei(%"class.PR12890::X"* %this, i32) -// CHECK: call void @llvm.memset.p0i8.{{i32|i64}}(i8* {{.*}}, i8 0, {{i32|i64}} 4, i32 4, i1 false) +// CHECK: call void @llvm.memset.p0i8.{{i32|i64}}(i8* align 4 {{.*}}, i8 0, {{i32|i64}} 4, i1 false) namespace PR14588 { void other(); diff --git a/test/CodeGenCXX/cxx0x-initializer-array.cpp b/test/CodeGenCXX/cxx0x-initializer-array.cpp index de10aee67f13e..4a7e452304cc1 100644 --- a/test/CodeGenCXX/cxx0x-initializer-array.cpp +++ b/test/CodeGenCXX/cxx0x-initializer-array.cpp @@ -39,7 +39,7 @@ namespace ValueInitArrayOfMemPtr { // CHECK: store i32 -1, Agg2 b = { n }; - // CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* %{{.*}}, i8* bitcast ([3 x i32]* @[[THREE_NULL_MEMPTRS]] to i8*), i32 12, i32 4, i1 false) + // CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %{{.*}}, i8* align 4 bitcast ([3 x i32]* @[[THREE_NULL_MEMPTRS]] to i8*), i32 12, i1 false) } // Test dynamic initialization. diff --git a/test/CodeGenCXX/cxx0x-initializer-references.cpp b/test/CodeGenCXX/cxx0x-initializer-references.cpp index 318c8ea0d7703..595d27ca2e834 100644 --- a/test/CodeGenCXX/cxx0x-initializer-references.cpp +++ b/test/CodeGenCXX/cxx0x-initializer-references.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++11 -S -triple armv7-none-eabi -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -std=c++11 -S -triple armv7-none-eabi -fmerge-all-constants -emit-llvm -o - %s | FileCheck %s namespace reference { struct A { diff --git a/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp b/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp index 67215ef48fb38..e3c7e26afa817 100644 --- a/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp +++ b/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -std=c++11 -triple x86_64-none-linux-gnu -emit-llvm -o - %s | FileCheck -check-prefixes=X86,CHECK %s -// RUN: %clang_cc1 -std=c++11 -triple amdgcn-amd-amdhsa-amdgiz -DNO_TLS -emit-llvm -o - %s | FileCheck -check-prefixes=AMD,CHECK %s +// RUN: %clang_cc1 -std=c++11 -triple x86_64-none-linux-gnu -fmerge-all-constants -emit-llvm -o - %s | FileCheck -check-prefixes=X86,CHECK %s +// RUN: %clang_cc1 -std=c++11 -triple amdgcn-amd-amdhsa -DNO_TLS -fmerge-all-constants -emit-llvm -o - %s | FileCheck -check-prefixes=AMDGCN,CHECK %s namespace std { typedef decltype(sizeof(int)) size_t; @@ -49,8 +49,8 @@ struct wantslist1 { }; // X86: @_ZGR15globalInitList1_ = internal constant [3 x i32] [i32 1, i32 2, i32 3] // X86: @globalInitList1 = global %{{[^ ]+}} { i32* getelementptr inbounds ([3 x i32], [3 x i32]* @_ZGR15globalInitList1_, i32 0, i32 0), i{{32|64}} 3 } -// AMD: @_ZGR15globalInitList1_ = internal addrspace(1) constant [3 x i32] [i32 1, i32 2, i32 3] -// AMD: @globalInitList1 = addrspace(1) global %{{[^ ]+}} { i32* addrspacecast (i32 addrspace(1)* getelementptr inbounds ([3 x i32], [3 x i32] addrspace(1)* @_ZGR15globalInitList1_, i32 0, i32 0) to i32*), i{{32|64}} 3 } +// AMDGCN: @_ZGR15globalInitList1_ = internal addrspace(1) constant [3 x i32] [i32 1, i32 2, i32 3] +// AMDGCN: @globalInitList1 = addrspace(1) global %{{[^ ]+}} { i32* addrspacecast (i32 addrspace(1)* getelementptr inbounds ([3 x i32], [3 x i32] addrspace(1)* @_ZGR15globalInitList1_, i32 0, i32 0) to i32*), i{{32|64}} 3 } std::initializer_list globalInitList1 = {1, 2, 3}; #ifndef NO_TLS @@ -67,28 +67,28 @@ std::initializer_list thread_local x = {1, 2, 3, 4}; // X86: @globalInitList2 = global %{{[^ ]+}} zeroinitializer // X86: @_ZGR15globalInitList2_ = internal global [2 x %[[WITHARG:[^ ]*]]] zeroinitializer -// AMD: @globalInitList2 = addrspace(1) global %{{[^ ]+}} zeroinitializer -// AMD: @_ZGR15globalInitList2_ = internal addrspace(1) global [2 x %[[WITHARG:[^ ]*]]] zeroinitializer +// AMDGCN: @globalInitList2 = addrspace(1) global %{{[^ ]+}} zeroinitializer +// AMDGCN: @_ZGR15globalInitList2_ = internal addrspace(1) global [2 x %[[WITHARG:[^ ]*]]] zeroinitializer // X86: @_ZN15partly_constant1kE = global i32 0, align 4 // X86: @_ZN15partly_constant2ilE = global {{.*}} null, align 8 -// X86: @[[PARTLY_CONSTANT_OUTER:_ZGRN15partly_constant2ilE.*]] = internal global {{.*}} zeroinitializer, align 8 -// X86: @[[PARTLY_CONSTANT_INNER:_ZGRN15partly_constant2ilE.*]] = internal global [3 x {{.*}}] zeroinitializer, align 8 -// X86: @[[PARTLY_CONSTANT_FIRST:_ZGRN15partly_constant2ilE.*]] = internal constant [3 x i32] [i32 1, i32 2, i32 3], align 4 -// X86: @[[PARTLY_CONSTANT_SECOND:_ZGRN15partly_constant2ilE.*]] = internal global [2 x i32] zeroinitializer, align 4 -// X86: @[[PARTLY_CONSTANT_THIRD:_ZGRN15partly_constant2ilE.*]] = internal constant [4 x i32] [i32 5, i32 6, i32 7, i32 8], align 4 -// AMD: @_ZN15partly_constant1kE = addrspace(1) global i32 0, align 4 -// AMD: @_ZN15partly_constant2ilE = addrspace(2) global {{.*}} null, align 8 -// AMD: @[[PARTLY_CONSTANT_OUTER:_ZGRN15partly_constant2ilE.*]] = internal addrspace(2) global {{.*}} zeroinitializer, align 8 -// AMD: @[[PARTLY_CONSTANT_INNER:_ZGRN15partly_constant2ilE.*]] = internal addrspace(2) global [3 x {{.*}}] zeroinitializer, align 8 -// AMD: @[[PARTLY_CONSTANT_FIRST:_ZGRN15partly_constant2ilE.*]] = internal addrspace(2) constant [3 x i32] [i32 1, i32 2, i32 3], align 4 -// AMD: @[[PARTLY_CONSTANT_SECOND:_ZGRN15partly_constant2ilE.*]] = internal addrspace(2) global [2 x i32] zeroinitializer, align 4 -// AMD: @[[PARTLY_CONSTANT_THIRD:_ZGRN15partly_constant2ilE.*]] = internal addrspace(2) constant [4 x i32] [i32 5, i32 6, i32 7, i32 8], align 4 +// X86: @[[PARTLY_CONSTANT_OUTER:_ZGRN15partly_constant2ilE_]] = internal global {{.*}} zeroinitializer, align 8 +// X86: @[[PARTLY_CONSTANT_INNER:_ZGRN15partly_constant2ilE0_]] = internal global [3 x {{.*}}] zeroinitializer, align 8 +// X86: @[[PARTLY_CONSTANT_FIRST:_ZGRN15partly_constant2ilE1_]] = internal constant [3 x i32] [i32 1, i32 2, i32 3], align 4 +// X86: @[[PARTLY_CONSTANT_SECOND:_ZGRN15partly_constant2ilE2_]] = internal global [2 x i32] zeroinitializer, align 4 +// X86: @[[PARTLY_CONSTANT_THIRD:_ZGRN15partly_constant2ilE3_]] = internal constant [4 x i32] [i32 5, i32 6, i32 7, i32 8], align 4 +// AMDGCN: @_ZN15partly_constant1kE = addrspace(1) global i32 0, align 4 +// AMDGCN: @_ZN15partly_constant2ilE = addrspace(4) global {{.*}} null, align 8 +// AMDGCN: @[[PARTLY_CONSTANT_OUTER:_ZGRN15partly_constant2ilE_]] = internal addrspace(4) global {{.*}} zeroinitializer, align 8 +// AMDGCN: @[[PARTLY_CONSTANT_INNER:_ZGRN15partly_constant2ilE0_]] = internal addrspace(4) global [3 x {{.*}}] zeroinitializer, align 8 +// AMDGCN: @[[PARTLY_CONSTANT_FIRST:_ZGRN15partly_constant2ilE1_]] = internal addrspace(4) constant [3 x i32] [i32 1, i32 2, i32 3], align 4 +// AMDGCN: @[[PARTLY_CONSTANT_SECOND:_ZGRN15partly_constant2ilE2_]] = internal addrspace(4) global [2 x i32] zeroinitializer, align 4 +// AMDGCN: @[[PARTLY_CONSTANT_THIRD:_ZGRN15partly_constant2ilE3_]] = internal addrspace(4) constant [4 x i32] [i32 5, i32 6, i32 7, i32 8], align 4 // X86: @[[REFTMP1:.*]] = private constant [2 x i32] [i32 42, i32 43], align 4 // X86: @[[REFTMP2:.*]] = private constant [3 x %{{.*}}] [%{{.*}} { i32 1 }, %{{.*}} { i32 2 }, %{{.*}} { i32 3 }], align 4 -// AMD: @[[REFTMP1:.*]] = private addrspace(2) constant [2 x i32] [i32 42, i32 43], align 4 -// AMD: @[[REFTMP2:.*]] = private addrspace(2) constant [3 x %{{.*}}] [%{{.*}} { i32 1 }, %{{.*}} { i32 2 }, %{{.*}} { i32 3 }], align 4 +// AMDGCN: @[[REFTMP1:.*]] = private addrspace(4) constant [2 x i32] [i32 42, i32 43], align 4 +// AMDGCN: @[[REFTMP2:.*]] = private addrspace(4) constant [3 x %{{.*}}] [%{{.*}} { i32 1 }, %{{.*}} { i32 2 }, %{{.*}} { i32 3 }], align 4 // CHECK: appending global @@ -101,15 +101,15 @@ std::initializer_list thread_local x = {1, 2, 3, 4}; // CHECK-LABEL: define internal void @__cxx_global_var_init // X86: call void @_ZN8witharg1C1ERK10destroyme1(%[[WITHARG]]* getelementptr inbounds ([2 x %[[WITHARG]]], [2 x %[[WITHARG]]]* @_ZGR15globalInitList2_, i{{32|64}} 0, i{{32|64}} 0 // X86: call void @_ZN8witharg1C1ERK10destroyme1(%[[WITHARG]]* getelementptr inbounds ([2 x %[[WITHARG]]], [2 x %[[WITHARG]]]* @_ZGR15globalInitList2_, i{{32|64}} 0, i{{32|64}} 1 -// AMD: call void @_ZN8witharg1C1ERK10destroyme1(%[[WITHARG]]* getelementptr inbounds ([2 x %[[WITHARG]]], [2 x %[[WITHARG]]]* addrspacecast ({{[^@]+}} @_ZGR15globalInitList2_ {{[^)]+}}), i{{32|64}} 0, i{{32|64}} 0 -// AMD: call void @_ZN8witharg1C1ERK10destroyme1(%[[WITHARG]]* getelementptr inbounds ([2 x %[[WITHARG]]], [2 x %[[WITHARG]]]* addrspacecast ({{[^@]+}} @_ZGR15globalInitList2_ {{[^)]+}}), i{{32|64}} 0, i{{32|64}} 1 +// AMDGCN: call void @_ZN8witharg1C1ERK10destroyme1(%[[WITHARG]]* getelementptr inbounds ([2 x %[[WITHARG]]], [2 x %[[WITHARG]]]* addrspacecast ({{[^@]+}} @_ZGR15globalInitList2_ {{[^)]+}}), i{{32|64}} 0, i{{32|64}} 0 +// AMDGCN: call void @_ZN8witharg1C1ERK10destroyme1(%[[WITHARG]]* getelementptr inbounds ([2 x %[[WITHARG]]], [2 x %[[WITHARG]]]* addrspacecast ({{[^@]+}} @_ZGR15globalInitList2_ {{[^)]+}}), i{{32|64}} 0, i{{32|64}} 1 // CHECK: call i32 @__cxa_atexit // X86: store %[[WITHARG]]* getelementptr inbounds ([2 x %[[WITHARG]]], [2 x %[[WITHARG]]]* @_ZGR15globalInitList2_, i64 0, i64 0), // X86: %[[WITHARG]]** getelementptr inbounds (%{{.*}}, %{{.*}}* @globalInitList2, i32 0, i32 0), align 8 // X86: store i64 2, i64* getelementptr inbounds (%{{.*}}, %{{.*}}* @globalInitList2, i32 0, i32 1), align 8 -// AMD: store %[[WITHARG]]* getelementptr inbounds ([2 x %[[WITHARG]]], [2 x %[[WITHARG]]]* addrspacecast ({{[^@]+}} @_ZGR15globalInitList2_ {{[^)]+}}), i64 0, i64 0), -// AMD: %[[WITHARG]]** getelementptr inbounds (%{{.*}}, %{{.*}}* addrspacecast ({{[^@]+}} @globalInitList2 {{[^)]+}}), i32 0, i32 0), align 8 -// AMD: store i64 2, i64* getelementptr inbounds (%{{.*}}, %{{.*}}* addrspacecast ({{[^@]+}} @globalInitList2 {{[^)]+}}), i32 0, i32 1), align 8 +// AMDGCN: store %[[WITHARG]]* getelementptr inbounds ([2 x %[[WITHARG]]], [2 x %[[WITHARG]]]* addrspacecast ({{[^@]+}} @_ZGR15globalInitList2_ {{[^)]+}}), i64 0, i64 0), +// AMDGCN: %[[WITHARG]]** getelementptr inbounds (%{{.*}}, %{{.*}}* addrspacecast ({{[^@]+}} @globalInitList2 {{[^)]+}}), i32 0, i32 0), align 8 +// AMDGCN: store i64 2, i64* getelementptr inbounds (%{{.*}}, %{{.*}}* addrspacecast ({{[^@]+}} @globalInitList2 {{[^)]+}}), i32 0, i32 1), align 8 // CHECK: call void @_ZN10destroyme1D1Ev // CHECK-NEXT: call void @_ZN10destroyme1D1Ev // CHECK-NEXT: ret void @@ -121,8 +121,8 @@ void fn1(int i) { // CHECK-LABEL: define void @_Z3fn1i // temporary array // X86: [[array:%[^ ]+]] = alloca [3 x i32] - // AMD: [[alloca:%[^ ]+]] = alloca [3 x i32], align 4, addrspace(5) - // AMD: [[array:%[^ ]+]] = addrspacecast [3 x i32] addrspace(5)* [[alloca]] to [3 x i32]* + // AMDGCN: [[alloca:%[^ ]+]] = alloca [3 x i32], align 4, addrspace(5) + // AMDGCN: [[array:%[^ ]+]] = addrspacecast [3 x i32] addrspace(5)* [[alloca]] to [3 x i32]* // CHECK: getelementptr inbounds [3 x i32], [3 x i32]* [[array]], i{{32|64}} 0 // CHECK-NEXT: store i32 1, i32* // CHECK-NEXT: getelementptr @@ -236,36 +236,6 @@ void fn9() { // CHECK: ret void } -struct haslist1 { - std::initializer_list il; - haslist1(int i); -}; - -// CHECK-LABEL: define void @_ZN8haslist1C2Ei -haslist1::haslist1(int i) -// CHECK: alloca [3 x i32] -// CHECK: store i32 % -// CHECK: store i32 2 -// CHECK: store i32 3 - : il{i, 2, 3} -{ - destroyme2 dm2; -} - -struct haslist2 { - std::initializer_list il; - haslist2(); -}; - -// CHECK-LABEL: define void @_ZN8haslist2C2Ev -haslist2::haslist2() - : il{destroyme1(), destroyme1()} -{ - destroyme2 dm2; - // CHECK: call void @_ZN10destroyme2D1Ev - // CHECK: call void @_ZN10destroyme1D1Ev -} - void fn10(int i) { // CHECK-LABEL: define void @_Z4fn10i // CHECK: alloca [3 x i32] @@ -405,7 +375,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 ({{.*}}, {{.*}}* {{.*}}@[[PARTLY_CONSTANT_INNER]]{{.*}}, i64 0, i64 2, i32 1) // CHECK-NOT: @[[PARTLY_CONSTANT_THIRD]], // // Outer init list. @@ -518,12 +488,12 @@ namespace B19773010 { // CHECK-LABEL: @_ZN9B197730102f1Ev testcase a{{"", ENUM_CONSTANT}}; // X86: store %"struct.B19773010::pair"* getelementptr inbounds ([1 x %"struct.B19773010::pair"], [1 x %"struct.B19773010::pair"]* bitcast ([1 x { i8*, i32 }]* @.ref.tmp{{.*}} to [1 x %"struct.B19773010::pair"]*), i64 0, i64 0), %"struct.B19773010::pair"** %{{.*}}, align 8 - // AMD: store %"struct.B19773010::pair"* getelementptr inbounds ([1 x %"struct.B19773010::pair"], [1 x %"struct.B19773010::pair"]* addrspacecast{{.*}} bitcast ([1 x { i8*, i32 }] addrspace(2)* @.ref.tmp{{.*}} to [1 x %"struct.B19773010::pair"] addrspace(2)*){{.*}}, i64 0, i64 0), %"struct.B19773010::pair"** %{{.*}}, align 8 + // AMDGCN: store %"struct.B19773010::pair"* getelementptr inbounds ([1 x %"struct.B19773010::pair"], [1 x %"struct.B19773010::pair"]* addrspacecast{{.*}} bitcast ([1 x { i8*, i32 }] addrspace(4)* @.ref.tmp{{.*}} to [1 x %"struct.B19773010::pair"] addrspace(4)*){{.*}}, i64 0, i64 0), %"struct.B19773010::pair"** %{{.*}}, align 8 } void f2() { // CHECK-LABEL: @_ZN9B197730102f2Ev // X86: store %"struct.B19773010::pair"* getelementptr inbounds ([1 x %"struct.B19773010::pair"], [1 x %"struct.B19773010::pair"]* bitcast ([1 x { i8*, i32 }]* @_ZGRZN9B197730102f2EvE1p_ to [1 x %"struct.B19773010::pair"]*), i64 0, i64 0), %"struct.B19773010::pair"** getelementptr inbounds ([2 x %"class.std::initializer_list.10"], [2 x %"class.std::initializer_list.10"]* @_ZZN9B197730102f2EvE1p, i64 0, i64 1, i32 0), align 16 - // AMD: store %"struct.B19773010::pair"* getelementptr inbounds ([1 x %"struct.B19773010::pair"], [1 x %"struct.B19773010::pair"]* addrspacecast{{.*}} bitcast ([1 x { i8*, i32 }] addrspace(1)* @_ZGRZN9B197730102f2EvE1p_ to [1 x %"struct.B19773010::pair"] addrspace(1)*){{.*}}, i64 0, i64 0), %"struct.B19773010::pair"** getelementptr inbounds ([2 x %"class.std::initializer_list.10"], [2 x %"class.std::initializer_list.10"]* addrspacecast{{.*}}@_ZZN9B197730102f2EvE1p{{.*}}, i64 0, i64 1, i32 0), align 8 + // AMDGCN: store %"struct.B19773010::pair"* getelementptr inbounds ([1 x %"struct.B19773010::pair"], [1 x %"struct.B19773010::pair"]* addrspacecast{{.*}} bitcast ([1 x { i8*, i32 }] addrspace(1)* @_ZGRZN9B197730102f2EvE1p_ to [1 x %"struct.B19773010::pair"] addrspace(1)*){{.*}}, i64 0, i64 0), %"struct.B19773010::pair"** getelementptr inbounds ([2 x %"class.std::initializer_list.10"], [2 x %"class.std::initializer_list.10"]* addrspacecast{{.*}}@_ZZN9B197730102f2EvE1p{{.*}}, i64 0, i64 1, i32 0), align 8 static std::initializer_list> a, p[2] = {a, {{"", ENUM_CONSTANT}}}; } diff --git a/test/CodeGenCXX/cxx11-initializer-aggregate.cpp b/test/CodeGenCXX/cxx11-initializer-aggregate.cpp index 8bf35966f5b99..325607f69fb5d 100644 --- a/test/CodeGenCXX/cxx11-initializer-aggregate.cpp +++ b/test/CodeGenCXX/cxx11-initializer-aggregate.cpp @@ -11,6 +11,42 @@ namespace NonAggregateCopyInAggregateInit { // PR32044 struct C { A &&p; } c{{1}}; } +namespace NearlyZeroInit { + // CHECK-DAG: @_ZN14NearlyZeroInit1aE = global {{.*}} <{ i32 1, i32 2, i32 3, [120 x i32] zeroinitializer }> + int a[123] = {1, 2, 3}; + // CHECK-DAG: @_ZN14NearlyZeroInit1bE = global {{.*}} { i32 1, <{ i32, [2147483647 x i32] }> <{ i32 2, [2147483647 x i32] zeroinitializer }> } + struct B { int n; int arr[1024 * 1024 * 1024 * 2u]; } b = {1, {2}}; +} + +namespace PR37560 { + union U { + char x; + int a; + }; + // FIXME: [dcl.init]p2, the padding bits of the union object should be + // initialized to 0, not undef, which would allow us to collapse the tail + // of these arrays to zeroinitializer. + // CHECK-DAG: @_ZN7PR375601cE = global <{ { i8, [3 x i8] } }> <{ { i8, [3 x i8] } { i8 0, [3 x i8] undef } }> + U c[1] = {}; + // CHECK-DAG: @_ZN7PR375601dE = global {{.*}} <{ { i8, [3 x i8] } { i8 97, [3 x i8] undef }, %"{{[^"]*}}" { i32 123 }, { i8, [3 x i8] } { i8 98, [3 x i8] undef }, { i8, [3 x i8] } { i8 0, [3 x i8] undef }, + U d[16] = {'a', {.a = 123}, 'b'}; + // CHECK-DAG: @_ZN7PR375601eE = global {{.*}} <{ %"{{[^"]*}}" { i32 123 }, %"{{[^"]*}}" { i32 456 }, { i8, [3 x i8] } { i8 0, [3 x i8] undef }, + U e[16] = {{.a = 123}, {.a = 456}}; + + union V { + int a; + char x; + }; + // CHECK-DAG: @_ZN7PR375601fE = global [1 x %"{{[^"]*}}"] zeroinitializer + V f[1] = {}; + // CHECK-DAG: @_ZN7PR375601gE = global {{.*}} <{ { i8, [3 x i8] } { i8 97, [3 x i8] undef }, %"{{[^"]*}}" { i32 123 }, { i8, [3 x i8] } { i8 98, [3 x i8] undef }, [13 x %"{{[^"]*}}"] zeroinitializer }> + V g[16] = {{.x = 'a'}, {.a = 123}, {.x = 'b'}}; + // CHECK-DAG: @_ZN7PR375601hE = global {{.*}} <{ %"{{[^"]*}}" { i32 123 }, %"{{[^"]*}}" { i32 456 }, [14 x %"{{[^"]*}}"] zeroinitializer }> + V h[16] = {{.a = 123}, {.a = 456}}; + // CHECK-DAG: @_ZN7PR375601iE = global [4 x %"{{[^"]*}}"] [%"{{[^"]*}}" { i32 123 }, %"{{[^"]*}}" { i32 456 }, %"{{[^"]*}}" zeroinitializer, %"{{[^"]*}}" zeroinitializer] + V i[4] = {{.a = 123}, {.a = 456}}; +} + // CHECK-LABEL: define {{.*}}@_Z3fn1i( int fn1(int x) { // CHECK: %[[INITLIST:.*]] = alloca %struct.A @@ -51,3 +87,35 @@ namespace NonTrivialInit { // meaningful. B b[30] = {}; } + +namespace ZeroInit { + enum { Zero, One }; + constexpr int zero() { return 0; } + constexpr int *null() { return nullptr; } + struct Filler { + int x; + Filler(); + }; + struct S1 { + int x; + }; + + // These declarations, if implemented elementwise, require huge + // amout of memory and compiler time. + unsigned char data_1[1024 * 1024 * 1024 * 2u] = { 0 }; + unsigned char data_2[1024 * 1024 * 1024 * 2u] = { Zero }; + unsigned char data_3[1024][1024][1024] = {{{0}}}; + unsigned char data_4[1024 * 1024 * 1024 * 2u] = { zero() }; + int *data_5[1024 * 1024 * 512] = { nullptr }; + int *data_6[1024 * 1024 * 512] = { null() }; + struct S1 data_7[1024 * 1024 * 512] = {{0}}; + char data_8[1000 * 1000 * 1000] = {}; + int (&&data_9)[1000 * 1000 * 1000] = {0}; + unsigned char data_10[1024 * 1024 * 1024 * 2u] = { 1 }; + unsigned char data_11[1024 * 1024 * 1024 * 2u] = { One }; + unsigned char data_12[1024][1024][1024] = {{{1}}}; + + // This variable must be initialized elementwise. + Filler data_e1[1024] = {}; + // CHECK: getelementptr inbounds {{.*}} @_ZN8ZeroInit7data_e1E +} diff --git a/test/CodeGenCXX/cxx11-initializer-array-new.cpp b/test/CodeGenCXX/cxx11-initializer-array-new.cpp index 59f96031fc40a..6e242124fea00 100644 --- a/test/CodeGenCXX/cxx11-initializer-array-new.cpp +++ b/test/CodeGenCXX/cxx11-initializer-array-new.cpp @@ -154,7 +154,7 @@ void *r = new T[n][3]{ { 1, 2, 3 }, { 4, 5, 6 } }; // // 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: call void @llvm.memset.p0i8.i64(i8* align 4 %[[REST]], i8 0, i64 %[[SIZE]], i1 false) // // CHECK: } diff --git a/test/CodeGenCXX/cxx11-thread-local.cpp b/test/CodeGenCXX/cxx11-thread-local.cpp index 3231a76ba9208..70f5a47fd3b8c 100644 --- a/test/CodeGenCXX/cxx11-thread-local.cpp +++ b/test/CodeGenCXX/cxx11-thread-local.cpp @@ -166,7 +166,8 @@ int f() { // DARWIN: call cxx_fast_tlscc void @_ZTHN1XIiE1mE() // CHECK: ret {{.*}}* @_ZN1XIiE1mE -// CHECK: define internal {{.*}} @[[VF_M_INIT]]() +// LINUX: define internal void @[[VF_M_INIT]]() +// DARWIN: define internal cxx_fast_tlscc void @[[VF_M_INIT]]() // LINUX-SAME: comdat($_ZN1VIfE1mE) // DARWIN-NOT: comdat // CHECK: load i8, i8* bitcast (i64* @_ZGVN1VIfE1mE to i8*) @@ -178,7 +179,8 @@ int f() { // CHECK: store i64 1, i64* @_ZGVN1VIfE1mE // CHECK: br label -// CHECK: define internal {{.*}} @[[XF_M_INIT]]() +// LINUX: define internal void @[[XF_M_INIT]]() +// DARWIN: define internal cxx_fast_tlscc void @[[XF_M_INIT]]() // LINUX-SAME: comdat($_ZN1XIfE1mE) // DARWIN-NOT: comdat // CHECK: load i8, i8* bitcast (i64* @_ZGVN1XIfE1mE to i8*) @@ -268,7 +270,8 @@ void set_anon_i() { // LINUX-LABEL: define internal i32* @_ZTWN12_GLOBAL__N_16anon_iE() // DARWIN-LABEL: define internal cxx_fast_tlscc i32* @_ZTWN12_GLOBAL__N_16anon_iE() -// CHECK: define internal {{.*}} @[[V_M_INIT]]() +// LINUX: define internal void @[[V_M_INIT]]() +// DARWIN: define internal cxx_fast_tlscc void @[[V_M_INIT]]() // LINUX-SAME: comdat($_ZN1VIiE1mE) // DARWIN-NOT: comdat // CHECK: load i8, i8* bitcast (i64* @_ZGVN1VIiE1mE to i8*) @@ -280,7 +283,8 @@ void set_anon_i() { // CHECK: store i64 1, i64* @_ZGVN1VIiE1mE // CHECK: br label -// CHECK: define internal {{.*}} @[[X_M_INIT]]() +// LINUX: define internal void @[[X_M_INIT]]() +// DARWIN: define internal cxx_fast_tlscc void @[[X_M_INIT]]() // LINUX-SAME: comdat($_ZN1XIiE1mE) // DARWIN-NOT: comdat // CHECK: load i8, i8* bitcast (i64* @_ZGVN1XIiE1mE to i8*) diff --git a/test/CodeGenCXX/cxx1z-aligned-allocation.cpp b/test/CodeGenCXX/cxx1z-aligned-allocation.cpp index 4c579978cb96b..2e2bfc5b941ba 100644 --- a/test/CodeGenCXX/cxx1z-aligned-allocation.cpp +++ b/test/CodeGenCXX/cxx1z-aligned-allocation.cpp @@ -29,10 +29,10 @@ struct OVERALIGNED A { A(); int n[128]; }; // CHECK-LABEL: define {{.*}} @_Z2a0v() // CHECK: %[[ALLOC:.*]] = call i8* @_ZnwmSt11align_val_t(i64 512, i64 32) // CHECK: call void @_ZdlPvSt11align_val_t(i8* %[[ALLOC]], i64 32) -// CHECK-MS-LABEL: define {{.*}} @"\01?a0@@YAPEAXXZ"() -// CHECK-MS: %[[ALLOC:.*]] = call i8* @"\01??2@YAPEAX_KW4align_val_t@std@@@Z"(i64 512, i64 32) +// CHECK-MS-LABEL: define {{.*}} @"?a0@@YAPEAXXZ"() +// CHECK-MS: %[[ALLOC:.*]] = call i8* @"??2@YAPEAX_KW4align_val_t@std@@@Z"(i64 512, i64 32) // CHECK-MS: cleanuppad -// CHECK-MS: call void @"\01??3@YAXPEAXW4align_val_t@std@@@Z"(i8* %[[ALLOC]], i64 32) +// CHECK-MS: call void @"??3@YAXPEAXW4align_val_t@std@@@Z"(i8* %[[ALLOC]], i64 32) void *a0() { return new A; } // FIXME: Why don't we call the sized array deallocation overload in this case? @@ -44,13 +44,13 @@ void *a0() { return new A; } // CHECK-NOT: store // CHECK: invoke void @_ZN1AC1Ev( // CHECK: call void @_ZdaPvSt11align_val_t(i8* %[[ALLOC]], i64 32) -// CHECK-MS-LABEL: define {{.*}} @"\01?a1@@YAPEAXJ@Z"( -// CHECK-MS: %[[ALLOC:.*]] = call i8* @"\01??_U@YAPEAX_KW4align_val_t@std@@@Z"(i64 %{{.*}}, i64 32) +// CHECK-MS-LABEL: define {{.*}} @"?a1@@YAPEAXJ@Z"( +// CHECK-MS: %[[ALLOC:.*]] = call i8* @"??_U@YAPEAX_KW4align_val_t@std@@@Z"(i64 %{{.*}}, i64 32) // No array cookie. // CHECK-MS-NOT: store -// CHECK-MS: invoke %struct.A* @"\01??0A@@QEAA@XZ"( +// CHECK-MS: invoke %struct.A* @"??0A@@QEAA@XZ"( // CHECK-MS: cleanuppad -// CHECK-MS: call void @"\01??_V@YAXPEAXW4align_val_t@std@@@Z"(i8* %[[ALLOC]], i64 32) +// CHECK-MS: call void @"??_V@YAXPEAXW4align_val_t@std@@@Z"(i8* %[[ALLOC]], i64 32) void *a1(long n) { return new A[n]; } // CHECK-LABEL: define {{.*}} @_Z2a2P1A( diff --git a/test/CodeGenCXX/cxx1z-eval-order.cpp b/test/CodeGenCXX/cxx1z-eval-order.cpp index 1106719a4748f..04c1b50f497e8 100644 --- a/test/CodeGenCXX/cxx1z-eval-order.cpp +++ b/test/CodeGenCXX/cxx1z-eval-order.cpp @@ -56,13 +56,13 @@ void (*get_f())(A); void postfix_before_args() { // CHECK: call {{.*}}@{{.*}}get_f{{.*}}( // CHECK-ITANIUM: call {{.*}}@_ZN1AC1Ev( - // CHECK-WINDOWS: call {{.*}}@"\01??0A@@Q{{AE|EAA}}@XZ"( + // CHECK-WINDOWS: call {{.*}}@"??0A@@Q{{AE|EAA}}@XZ"( // CHECK: call {{.*}}%{{.*}}( get_f()(A{}); // CHECK: call {{.*}}@{{.*}}side_effect{{.*}}( // CHECK-ITANIUM: call {{.*}}@_ZN1AC1Ev( - // CHECK-WINDOWS: call {{.*}}@"\01??0A@@Q{{AE|EAA}}@XZ"( + // CHECK-WINDOWS: call {{.*}}@"??0A@@Q{{AE|EAA}}@XZ"( // CHECK: call {{.*}}@{{.*}}callee{{.*}}( (side_effect(), callee)(A{}); // CHECK: } @@ -126,7 +126,7 @@ void *operator new(decltype(sizeof(0)), C); void alloc_before_init() { struct Q { Q(A) {} }; // CHECK-ITANIUM: call {{.*}}@_Znw{{.*}}( - // CHECK-WINDOWS: call {{.*}}@"\01??2@YAP{{EAX_K|AXI}}@Z"( + // CHECK-WINDOWS: call {{.*}}@"??2@YAP{{EAX_K|AXI}}@Z"( // CHECK: call {{.*}}@{{.*}}make_a{{.*}}( delete new Q(make_a()); diff --git a/test/CodeGenCXX/cxx1z-initializer-aggregate.cpp b/test/CodeGenCXX/cxx1z-initializer-aggregate.cpp index 9110e49f93a1a..f59ec51136fef 100644 --- a/test/CodeGenCXX/cxx1z-initializer-aggregate.cpp +++ b/test/CodeGenCXX/cxx1z-initializer-aggregate.cpp @@ -112,3 +112,21 @@ namespace Dynamic { // A_CLEANUP: // CHECK: call void @_ZN7Dynamic1AD1Ev({{.*}} @_ZN7Dynamic2d3E } + +namespace Instantiated1 { + struct A { A(); }; + struct B : A { using A::A; }; + template B v({}); + template B v<0>; + // CHECK-LABEL: define {{.*}}global_var_init{{.*}} comdat($_ZN13Instantiated11vILi0EEE) { + // CHECK: call void @_ZN13Instantiated11BC1Ev(%{{.*}}* @_ZN13Instantiated11vILi0EEE) +} + +namespace Instantiated2 { + struct A { A(); }; + struct B : A {}; + template B v({}); + template B v<0>; + // CHECK-LABEL: define {{.*}}global_var_init{{.*}} comdat($_ZN13Instantiated21vILi0EEE) { + // CHECK: call void @_ZN13Instantiated21AC2Ev( +} diff --git a/test/CodeGenCXX/cxx1z-inline-variables.cpp b/test/CodeGenCXX/cxx1z-inline-variables.cpp index 2d16acd8a8c23..938ebbbeb3abe 100644 --- a/test/CodeGenCXX/cxx1z-inline-variables.cpp +++ b/test/CodeGenCXX/cxx1z-inline-variables.cpp @@ -58,14 +58,22 @@ template struct X { static int a; static inline int b; static int c; + static const int d; + static int e; }; // CHECK: @_ZN1XIiE1aE = linkonce_odr global i32 10 // CHECK: @_ZN1XIiE1bE = global i32 20 // CHECK-NOT: @_ZN1XIiE1cE +// CHECK: @_ZN1XIiE1dE = linkonce_odr constant i32 40 +// CHECK: @_ZN1XIiE1eE = linkonce_odr global i32 50 template<> inline int X::a = 10; int &use3 = X::a; template<> int X::b = 20; template<> inline int X::c = 30; +template constexpr int X::d = 40; +template inline int X::e = 50; +const int *use_x_int_d = &X::d; +const int *use_x_int_e = &X::e; template struct Y; template<> struct Y { @@ -103,3 +111,29 @@ int e = d; // CHECK-NOT: __cxa_guard_acquire(i64* @_ZGV1b) // CHECK: call i32 @_Z1fv // CHECK-NOT: __cxa_guard_release(i64* @_ZGV1b) + +namespace PR35599 { +struct Marker1 {}; +struct Marker2 {}; + +template +struct Foo { + struct Bar { Bar(); }; + inline static Bar bar; +}; + +void run() { + // All we want here are ODR uses. Anything that requires that the type is + // complete is uninteresting. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-value" + Foo::bar; +#pragma clang diagnostic pop + static_cast(Foo::bar); +} + +// CHECK-LABEL: define {{.*}}global_var_init{{.*}}comdat +// CHECK: call void @_ZN7PR355993FooINS_7Marker1EE3BarC1Ev +// CHECK-LABEL: define {{.*}}global_var_init{{.*}}comdat +// CHECK: call void @_ZN7PR355993FooINS_7Marker2EE3BarC1Ev +} diff --git a/test/CodeGenCXX/cxx1z-lambda-star-this.cpp b/test/CodeGenCXX/cxx1z-lambda-star-this.cpp index a7e4aadbd573f..114791c6558b3 100644 --- a/test/CodeGenCXX/cxx1z-lambda-star-this.cpp +++ b/test/CodeGenCXX/cxx1z-lambda-star-this.cpp @@ -10,13 +10,13 @@ namespace ns1 { int X = A{}.foo()(); } //end ns1 -//CHECK: @"\01?foo@A@@QAE?A?@@XZ"(%struct.A* %this, %class.anon* noalias sret %[[A_LAMBDA_RETVAL:.*]]) +//CHECK: @"?foo@A@@QAE?A?@@XZ"(%struct.A* %this, %class.anon* noalias sret %[[A_LAMBDA_RETVAL:.*]]) // get the first object with the closure type, which is of type 'struct.A' //CHECK: %[[I0:.+]] = getelementptr inbounds %[[A_LAMBDA]], %[[A_LAMBDA]]* %[[A_LAMBDA_RETVAL]], i32 0, i32 0 //CHECK: %[[I1:.+]] = bitcast %struct.A* %[[I0]] to i8* //CHECK: %[[I2:.+]] = bitcast %struct.A* %this1 to i8* // copy the contents ... -//CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* %[[I1]], i8* %[[I2]], i32 8, i32 8, i1 false) +//CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 %[[I1]], i8* align 8 %[[I2]], i32 8, i1 false) struct B { double b = 222; @@ -26,6 +26,6 @@ struct B { namespace ns2 { int X = B{}.bar()(); } -//CHECK: @"\01?bar@B@@QAE?A?@@XZ"(%struct.B* %this, %class.anon.0* noalias sret %agg.result) +//CHECK: @"?bar@B@@QAE?A?@@XZ"(%struct.B* %this, %class.anon.0* noalias sret %agg.result) //CHECK: %[[I20:.+]] = getelementptr inbounds %class.anon.0, %class.anon.0* %agg.result, i32 0, i32 0 //CHECK: store %struct.B* %this1, %struct.B** %[[I20]], align 4 diff --git a/test/CodeGenCXX/cxx2a-compare.cpp b/test/CodeGenCXX/cxx2a-compare.cpp new file mode 100644 index 0000000000000..ef6bb5556e225 --- /dev/null +++ b/test/CodeGenCXX/cxx2a-compare.cpp @@ -0,0 +1,188 @@ +// RUN: %clang_cc1 -std=c++2a -emit-llvm %s -o - -triple %itanium_abi_triple | \ +// RUN: FileCheck %s \ +// RUN: '-DWE="class.std::__1::weak_equality"' \ +// RUN: '-DSO="class.std::__1::strong_ordering"' \ +// RUN: '-DSE="class.std::__1::strong_equality"' \ +// RUN: '-DPO="class.std::__1::partial_ordering"' \ +// RUN: -DEQ=0 -DLT=-1 -DGT=1 -DUNORD=-127 -DNE=1 + +#include "Inputs/std-compare.h" + +// Ensure we don't emit definitions for the global variables +// since the builtins shouldn't ODR use them. +// CHECK-NOT: constant %[[SO]] +// CHECK-NOT: constant %[[SE]] +// CHECK-NOT: constant %[[WE]] +// CHECK-NOT: constant %[[PO]] + +// CHECK-LABEL: @_Z11test_signedii +auto test_signed(int x, int y) { + // CHECK: %[[DEST:retval|agg.result]] + // CHECK: %cmp.lt = icmp slt i32 %0, %1 + // CHECK: %sel.lt = select i1 %cmp.lt, i8 [[LT]], i8 [[GT]] + // CHECK: %cmp.eq = icmp eq i32 %0, %1 + // CHECK: %sel.eq = select i1 %cmp.eq, i8 [[EQ]], i8 %sel.lt + // CHECK: %__value_ = getelementptr inbounds %[[SO]], %[[SO]]* %[[DEST]] + // CHECK: store i8 %sel.eq, i8* %__value_, align 1 + // CHECK: ret + return x <=> y; +} + +// CHECK-LABEL: @_Z13test_unsignedjj +auto test_unsigned(unsigned x, unsigned y) { + // CHECK: %[[DEST:retval|agg.result]] + // CHECK: %cmp.lt = icmp ult i32 %0, %1 + // CHECK: %sel.lt = select i1 %cmp.lt, i8 [[LT]], i8 [[GT]] + // CHECK: %cmp.eq = icmp eq i32 %0, %1 + // CHECK: %sel.eq = select i1 %cmp.eq, i8 [[EQ]], i8 %sel.lt + // CHECK: %__value_ = getelementptr inbounds %[[SO]], %[[SO]]* %[[DEST]] + // CHECK: store i8 %sel.eq, i8* %__value_ + // CHECK: ret + return x <=> y; +} + +// CHECK-LABEL: @_Z10float_testdd +auto float_test(double x, double y) { + // CHECK: %[[DEST:retval|agg.result]] + // CHECK: %cmp.eq = fcmp oeq double %0, %1 + // CHECK: %sel.eq = select i1 %cmp.eq, i8 [[EQ]], i8 [[UNORD]] + // CHECK: %cmp.gt = fcmp ogt double %0, %1 + // CHECK: %sel.gt = select i1 %cmp.gt, i8 [[GT]], i8 %sel.eq + // CHECK: %cmp.lt = fcmp olt double %0, %1 + // CHECK: %sel.lt = select i1 %cmp.lt, i8 [[LT]], i8 %sel.gt + // CHECK: %__value_ = getelementptr inbounds %[[PO]], %[[PO]]* %[[DEST]] + // CHECK: store i8 %sel.lt, i8* %__value_ + // CHECK: ret + return x <=> y; +} + +// CHECK-LABEL: @_Z8ptr_testPiS_ +auto ptr_test(int *x, int *y) { + // CHECK: %[[DEST:retval|agg.result]] + // CHECK: %cmp.lt = icmp ult i32* %0, %1 + // CHECK: %sel.lt = select i1 %cmp.lt, i8 [[LT]], i8 [[GT]] + // CHECK: %cmp.eq = icmp eq i32* %0, %1 + // CHECK: %sel.eq = select i1 %cmp.eq, i8 [[EQ]], i8 %sel.lt + // CHECK: %__value_ = getelementptr inbounds %[[SO]], %[[SO]]* %[[DEST]] + // CHECK: store i8 %sel.eq, i8* %__value_, align 1 + // CHECK: ret + return x <=> y; +} + +struct MemPtr {}; +using MemPtrT = void (MemPtr::*)(); +using MemDataT = int(MemPtr::*); + +// CHECK-LABEL: @_Z12mem_ptr_testM6MemPtrFvvES1_ +auto mem_ptr_test(MemPtrT x, MemPtrT y) { + // CHECK: %[[DEST:retval|agg.result]] + // CHECK: %cmp.ptr = icmp eq [[TY:i[0-9]+]] %lhs.memptr.ptr, %rhs.memptr.ptr + // CHECK: %cmp.ptr.null = icmp eq [[TY]] %lhs.memptr.ptr, 0 + // CHECK: %cmp.adj = icmp eq [[TY]] %lhs.memptr.adj, %rhs.memptr.adj + // CHECK: %[[OR:.*]] = or i1 + // CHECK-SAME %cmp.adj + // CHECK: %memptr.eq = and i1 %cmp.ptr, %[[OR]] + // CHECK: %sel.eq = select i1 %memptr.eq, i8 [[EQ]], i8 [[NE]] + // CHECK: %__value_ = getelementptr inbounds %[[SE]], %[[SE]]* %[[DEST]] + // CHECK: store i8 %sel.eq, i8* %__value_, align 1 + // CHECK: ret + return x <=> y; +} + +// CHECK-LABEL: @_Z13mem_data_testM6MemPtriS0_ +auto mem_data_test(MemDataT x, MemDataT y) { + // CHECK: %[[DEST:retval|agg.result]] + // CHECK: %[[CMP:.*]] = icmp eq i{{[0-9]+}} %0, %1 + // CHECK: %sel.eq = select i1 %[[CMP]], i8 [[EQ]], i8 [[NE]] + // CHECK: %__value_ = getelementptr inbounds %[[SE]], %[[SE]]* %[[DEST]] + // CHECK: store i8 %sel.eq, i8* %__value_, align 1 + return x <=> y; +} + +// CHECK-LABEL: @_Z13test_constantv +auto test_constant() { + // CHECK: %[[DEST:retval|agg.result]] + // CHECK-NOT: icmp + // CHECK: %__value_ = getelementptr inbounds %[[SO]], %[[SO]]* %[[DEST]] + // CHECK-NEXT: store i8 -1, i8* %__value_ + // CHECK: ret + const int x = 42; + const int y = 101; + return x <=> y; +} + +// CHECK-LABEL: @_Z16test_nullptr_objPiDn +auto test_nullptr_obj(int* x, decltype(nullptr) y) { + // CHECK: %[[DEST:retval|agg.result]] + // CHECK: %cmp.eq = icmp eq i32* %0, null + // CHECK: %sel.eq = select i1 %cmp.eq, i8 [[EQ]], i8 [[NE]] + // CHECK: %__value_ = getelementptr inbounds %[[SE]], %[[SE]]* %[[DEST]] + // CHECK: store i8 %sel.eq, i8* %__value_, align 1 + return x <=> y; +} + +// CHECK-LABEL: @_Z18unscoped_enum_testijxy +void unscoped_enum_test(int i, unsigned u, long long l, unsigned long long ul) { + enum EnumA : int { A }; + enum EnumB : unsigned { B }; + // CHECK: %[[I:.*]] = load {{.*}} %i.addr + // CHECK: icmp slt i32 {{.*}} %[[I]] + (void)(A <=> i); + + // CHECK: %[[U:.*]] = load {{.*}} %u.addr + // CHECK: icmp ult i32 {{.*}} %[[U]] + (void)(A <=> u); + + // CHECK: %[[L:.*]] = load {{.*}} %l.addr + // CHECK: icmp slt i64 {{.*}} %[[L]] + (void)(A <=> l); + + // CHECK: %[[U2:.*]] = load {{.*}} %u.addr + // CHECK: icmp ult i32 {{.*}} %[[U2]] + (void)(B <=> u); + + // CHECK: %[[UL:.*]] = load {{.*}} %ul.addr + // CHECK: icmp ult i64 {{.*}} %[[UL]] + (void)(B <=> ul); +} + +namespace NullptrTest { +using nullptr_t = decltype(nullptr); + +// CHECK-LABEL: @_ZN11NullptrTest4testEDnDn( +auto test(nullptr_t x, nullptr_t y) { + // CHECK: %[[DEST:retval|agg.result]] + // CHECK-NOT: select + // CHECK: %__value_ = getelementptr inbounds %[[SE]], %[[SE]]* %[[DEST]] + // CHECK-NEXT: store i8 [[EQ]], i8* %__value_ + // CHECK: ret + return x <=> y; +} +} // namespace NullptrTest + +namespace ComplexTest { + +auto test_float(_Complex float x, _Complex float y) { + // CHECK: %[[DEST:retval|agg.result]] + // CHECK: %cmp.eq.r = fcmp oeq float %x.real, %y.real + // CHECK: %cmp.eq.i = fcmp oeq float %x.imag, %y.imag + // CHECK: %and.eq = and i1 %cmp.eq.r, %cmp.eq.i + // CHECK: %sel.eq = select i1 %and.eq, i8 [[EQ]], i8 [[NE]] + // CHECK: %__value_ = getelementptr inbounds %[[WE]], %[[WE]]* %[[DEST]] + // CHECK: store i8 %sel.eq, i8* %__value_, align 1 + return x <=> y; +} + +// CHECK-LABEL: @_ZN11ComplexTest8test_intECiS0_( +auto test_int(_Complex int x, _Complex int y) { + // CHECK: %[[DEST:retval|agg.result]] + // CHECK: %cmp.eq.r = icmp eq i32 %x.real, %y.real + // CHECK: %cmp.eq.i = icmp eq i32 %x.imag, %y.imag + // CHECK: %and.eq = and i1 %cmp.eq.r, %cmp.eq.i + // CHECK: %sel.eq = select i1 %and.eq, i8 [[EQ]], i8 [[NE]] + // CHECK: %__value_ = getelementptr inbounds %[[SE]], %[[SE]]* %[[DEST]] + // CHECK: store i8 %sel.eq, i8* %__value_, align 1 + return x <=> y; +} + +} // namespace ComplexTest diff --git a/test/CodeGenCXX/cxx2a-destroying-delete.cpp b/test/CodeGenCXX/cxx2a-destroying-delete.cpp index 2e4d40715e153..60c5970cb94f4 100644 --- a/test/CodeGenCXX/cxx2a-destroying-delete.cpp +++ b/test/CodeGenCXX/cxx2a-destroying-delete.cpp @@ -21,7 +21,7 @@ void delete_A(A *a) { delete a; } // Ensure that we call the destroying delete and not the destructor. // CHECK-NOT: call // CHECK-ITANIUM: call void @_ZN1AdlEPS_St19destroying_delete_t(%{{.*}}* %[[a]]) -// CHECK-MSABI: call void @"\01??3A@@SAXPEAU0@Udestroying_delete_t@std@@@Z"(%{{.*}}* %[[a]], i8 +// CHECK-MSABI: call void @"??3A@@SAXPEAU0@Udestroying_delete_t@std@@@Z"(%{{.*}}* %[[a]], i8 // CHECK-NOT: call // CHECK: } @@ -65,7 +65,7 @@ void delete_C(C *c) { delete c; } // // CHECK-NOT: call // CHECK-ITANIUM: call void @_ZN1AdlEPS_St19destroying_delete_t(%{{.*}}* %[[a]]) -// CHECK-MSABI: call void @"\01??3A@@SAXPEAU0@Udestroying_delete_t@std@@@Z"(%{{.*}}* %[[a]], i8 +// CHECK-MSABI: call void @"??3A@@SAXPEAU0@Udestroying_delete_t@std@@@Z"(%{{.*}}* %[[a]], i8 // CHECK-NOT: call // CHECK: } @@ -78,15 +78,15 @@ void delete_D(D *d) { delete d; } // CHECK: br i1 // // CHECK-NOT: call -// CHECK: %[[VTABLE:.*]] = load -// CHECK: %[[DTOR:.*]] = load -// // For MS, we don't add a new vtable slot to the primary vtable for the virtual // destructor. Instead we cast to the VDel base class. // CHECK-MSABI: bitcast {{.*}} %[[d]] // CHECK-MSABI-NEXT: getelementptr {{.*}}, i64 8 // CHECK-MSABI-NEXT: %[[d:.*]] = bitcast i8* // +// CHECK: %[[VTABLE:.*]] = load +// CHECK: %[[DTOR:.*]] = load +// // CHECK: call {{void|i8\*}} %[[DTOR]](%{{.*}}* %[[d]] // CHECK-MSABI-SAME: , i32 1) // CHECK-NOT: call @@ -100,7 +100,7 @@ void delete_G(G *g) { delete g; } // CHECK-LABEL: define {{.*}}delete_G // CHECK-NOT: call // CHECK-ITANIUM: call void @_ZN1FdlEPS_St19destroying_delete_tmSt11align_val_t(%{{.*}}* %[[a]], i64 32, i64 16) -// CHECK-MSABI: call void @"\01??3F@@SAXPEAU0@Udestroying_delete_t@std@@_KW4align_val_t@2@@Z"(%{{.*}}* %[[a]], i8 {{[^,]*}}, i64 32, i64 16) +// CHECK-MSABI: call void @"??3F@@SAXPEAU0@Udestroying_delete_t@std@@_KW4align_val_t@2@@Z"(%{{.*}}* %[[a]], i8 {{[^,]*}}, i64 32, i64 16) // CHECK-NOT: call // CHECK: } @@ -116,7 +116,7 @@ H::~H() { call_in_dtor(); } // CHECK-ITANIUM-NOT: call // CHECK-ITANIUM: } -// CHECK-MSABI: define {{.*}} @"\01??_GH@@UEAAPEAXI@Z"( +// CHECK-MSABI: define {{.*}} @"??_GH@@UEAAPEAXI@Z"( // CHECK-MSABI-NOT: call{{ }} // CHECK-MSABI: load i32 // CHECK-MSABI: icmp eq i32 {{.*}}, 0 @@ -125,10 +125,10 @@ H::~H() { call_in_dtor(); } // CHECK-MSABI-NOT: call{{ }} // CHECK-MSABI: getelementptr {{.*}}, i64 24 // CHECK-MSABI-NOT: call{{ }} -// CHECK-MSABI: call void @"\01??3F@@SAXPEAU0@Udestroying_delete_t@std@@_KW4align_val_t@2@@Z"({{.*}}, i64 48, i64 16) +// CHECK-MSABI: call void @"??3F@@SAXPEAU0@Udestroying_delete_t@std@@_KW4align_val_t@2@@Z"({{.*}}, i64 48, i64 16) // CHECK-MSABI: br label %[[RETURN:.*]] // -// CHECK-MSABI: call void @"\01??_DH@@QEAAXXZ"( +// CHECK-MSABI: call void @"??1H@@UEAA@XZ"( // CHECK-MSABI: br label %[[RETURN]] // // CHECK-MSABI: } @@ -143,7 +143,7 @@ I::~I() { call_in_dtor(); } // CHECK-ITANIUM-NOT: call // CHECK-ITANIUM: } -// CHECK-MSABI: define {{.*}} @"\01??_GI@@UEAAPEAXI@Z"( +// CHECK-MSABI: define {{.*}} @"??_GI@@UEAAPEAXI@Z"( // CHECK-MSABI-NOT: call{{ }} // CHECK-MSABI: load i32 // CHECK-MSABI: icmp eq i32 {{.*}}, 0 @@ -152,10 +152,10 @@ I::~I() { call_in_dtor(); } // CHECK-MSABI-NOT: call{{ }} // CHECK-MSABI: getelementptr {{.*}}, i64 24 // CHECK-MSABI-NOT: call{{ }} -// CHECK-MSABI: call void @"\01??3F@@SAXPEAU0@Udestroying_delete_t@std@@_KW4align_val_t@2@@Z"({{.*}}, i64 96, i64 32) +// CHECK-MSABI: call void @"??3F@@SAXPEAU0@Udestroying_delete_t@std@@_KW4align_val_t@2@@Z"({{.*}}, i64 96, i64 32) // CHECK-MSABI: br label %[[RETURN:.*]] // -// CHECK-MSABI: call void @"\01??_DI@@QEAAXXZ"( +// CHECK-MSABI: call void @"??1I@@UEAA@XZ"( // CHECK-MSABI: br label %[[RETURN]] // // CHECK-MSABI: } diff --git a/test/CodeGenCXX/debug-info-access.cpp b/test/CodeGenCXX/debug-info-access.cpp index 82f29ea4d38af..44d6b4da17a36 100644 --- a/test/CodeGenCXX/debug-info-access.cpp +++ b/test/CodeGenCXX/debug-info-access.cpp @@ -10,7 +10,7 @@ struct A { }; -// CHECK: !DIDerivedType(tag: DW_TAG_inheritance,{{.*}} baseType: ![[A]],{{.*}} flags: DIFlagPublic) +// CHECK: !DIDerivedType(tag: DW_TAG_inheritance,{{.*}} baseType: ![[A]],{{.*}} flags: DIFlagPublic, extraData: i32 0) class B : public A { public: // CHECK-DAG: !DISubprogram(name: "pub",{{.*}} line: [[@LINE+1]],{{.*}} flags: DIFlagPublic | DIFlagPrototyped, diff --git a/test/CodeGenCXX/debug-info-class-nolimit.cpp b/test/CodeGenCXX/debug-info-class-nolimit.cpp index 0b3b38dd17b10..b184b9e08da7f 100644 --- a/test/CodeGenCXX/debug-info-class-nolimit.cpp +++ b/test/CodeGenCXX/debug-info-class-nolimit.cpp @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -triple x86_64-apple-darwin -debug-info-kind=standalone -o - -emit-llvm %s | FileCheck %s // We had a bug in -fstandalone-debug where UnicodeString would not be completed -// when it was required to be complete. This orginally manifested as an +// when it was required to be complete. This originally manifested as an // assertion in CodeView emission on Windows with some dllexport stuff, but it's // more general than that. diff --git a/test/CodeGenCXX/debug-info-codeview-unnamed.cpp b/test/CodeGenCXX/debug-info-codeview-unnamed.cpp new file mode 100644 index 0000000000000..dd4cc9cb47873 --- /dev/null +++ b/test/CodeGenCXX/debug-info-codeview-unnamed.cpp @@ -0,0 +1,108 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -debug-info-kind=limited -S -emit-llvm -std=c++11 -o - %s | FileCheck --check-prefix LINUX %s +// RUN: %clang_cc1 -triple x86_64-windows-msvc -debug-info-kind=limited -gcodeview -S -emit-llvm -std=c++11 -o - %s | FileCheck --check-prefix MSVC %s + +int main(int argc, char* argv[], char* arge[]) { + // + // In CodeView, the LF_MFUNCTION entry for "bar()" refers to the forward + // reference of the unnamed struct. Visual Studio requires a unique + // identifier to match the LF_STRUCTURE forward reference to the definition. + // + struct { void bar() {} } one; + // + // LINUX: !{{[0-9]+}} = !DILocalVariable(name: "one" + // LINUX-SAME: type: [[TYPE_OF_ONE:![0-9]+]] + // LINUX-SAME: ) + // LINUX: [[TYPE_OF_ONE]] = distinct !DICompositeType( + // LINUX-SAME: tag: DW_TAG_structure_type + // LINUX-NOT: name: + // LINUX-NOT: identifier: + // LINUX-SAME: ) + // + // MSVC: !{{[0-9]+}} = !DILocalVariable(name: "one" + // MSVC-SAME: type: [[TYPE_OF_ONE:![0-9]+]] + // MSVC-SAME: ) + // MSVC: [[TYPE_OF_ONE]] = distinct !DICompositeType + // MSVC-SAME: tag: DW_TAG_structure_type + // MSVC-SAME: name: "" + // MSVC-SAME: identifier: ".?AU@?1??main@@9@" + // MSVC-SAME: ) + + + // In CodeView, the LF_POINTER entry for "ptr2unnamed" refers to the forward + // reference of the unnamed struct. Visual Studio requires a unique + // identifier to match the LF_STRUCTURE forward reference to the definition. + // + struct { int bar; } two = { 42 }; + int decltype(two)::*ptr2unnamed = &decltype(two)::bar; + // + // LINUX: !{{[0-9]+}} = !DILocalVariable(name: "two" + // LINUX-SAME: type: [[TYPE_OF_TWO:![0-9]+]] + // LINUX-SAME: ) + // LINUX: [[TYPE_OF_TWO]] = distinct !DICompositeType( + // LINUX-SAME: tag: DW_TAG_structure_type + // LINUX-NOT: name: + // LINUX-NOT: identifier: + // LINUX-SAME: ) + // + // MSVC: !{{[0-9]+}} = !DILocalVariable(name: "two" + // MSVC-SAME: type: [[TYPE_OF_TWO:![0-9]+]] + // MSVC-SAME: ) + // MSVC: [[TYPE_OF_TWO]] = distinct !DICompositeType + // MSVC-SAME: tag: DW_TAG_structure_type + // MSVC-SAME: name: "" + // MSVC-SAME: identifier: ".?AU@?2??main@@9@" + // MSVC-SAME: ) + + + // In DWARF, named structures which are not externally visibile do not + // require an identifier. In CodeView, named structures are given an + // identifier. + // + struct named { int bar; int named::* p2mem; } three = { 42, &named::bar }; + // + // LINUX: !{{[0-9]+}} = !DILocalVariable(name: "three" + // LINUX-SAME: type: [[TYPE_OF_THREE:![0-9]+]] + // LINUX-SAME: ) + // LINUX: [[TYPE_OF_THREE]] = distinct !DICompositeType( + // LINUX-SAME: tag: DW_TAG_structure_type + // LINUX-SAME: name: "named" + // LINUX-NOT: identifier: + // LINUX-SAME: ) + // + // MSVC: !{{[0-9]+}} = !DILocalVariable(name: "three" + // MSVC-SAME: type: [[TYPE_OF_THREE:![0-9]+]] + // MSVC-SAME: ) + // MSVC: [[TYPE_OF_THREE]] = distinct !DICompositeType + // MSVC-SAME: tag: DW_TAG_structure_type + // MSVC-SAME: name: "named" + // MSVC-SAME: identifier: ".?AUnamed@?1??main@@9@" + // MSVC-SAME: ) + + + // In CodeView, the LF_MFUNCTION entry for the lambda "operator()" routine + // refers to the forward reference of the unnamed LF_CLASS for the lambda. + // Visual Studio requires a unique identifier to match the forward reference + // of the LF_CLASS to its definition. + // + auto four = [argc](int i) -> int { return argc == i ? 1 : 0; }; + // + // LINUX: !{{[0-9]+}} = !DILocalVariable(name: "four" + // LINUX-SAME: type: [[TYPE_OF_FOUR:![0-9]+]] + // LINUX-SAME: ) + // LINUX: [[TYPE_OF_FOUR]] = distinct !DICompositeType( + // LINUX-SAME: tag: DW_TAG_class_type + // LINUX-NOT: name: + // LINUX-NOT: identifier: + // LINUX-SAME: ) + // + // MSVC: !{{[0-9]+}} = !DILocalVariable(name: "four" + // MSVC-SAME: type: [[TYPE_OF_FOUR:![0-9]+]] + // MSVC-SAME: ) + // MSVC: [[TYPE_OF_FOUR]] = distinct !DICompositeType + // MSVC-SAME: tag: DW_TAG_class_type + // MSVC-NOT: name: + // MSVC-SAME: identifier: ".?AV@?0??main@@9@" + // MSVC-SAME: ) + + return 0; +} diff --git a/test/CodeGenCXX/debug-info-codeview-var-templates.cpp b/test/CodeGenCXX/debug-info-codeview-var-templates.cpp new file mode 100644 index 0000000000000..0470c133688cb --- /dev/null +++ b/test/CodeGenCXX/debug-info-codeview-var-templates.cpp @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 %s -std=c++14 -triple=i686-pc-windows-msvc -debug-info-kind=limited -gcodeview -emit-llvm -o - | FileCheck %s + +// Don't emit static data member debug info for variable templates. +// PR38004 + +struct TestImplicit { + template + static const __SIZE_TYPE__ size_var = sizeof(T); +}; +int instantiate_test1() { return TestImplicit::size_var + TestImplicit::size_var; } +TestImplicit gv1; + +// CHECK: ![[empty:[0-9]+]] = !{} + +// CHECK: ![[A:[^ ]*]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "TestImplicit", +// CHECK-SAME: elements: ![[empty]] + +template bool vtpl; +struct TestSpecialization { + template static const auto sdm = vtpl; + template <> static const auto sdm = false; +} gv2; + +// CHECK: ![[A:[^ ]*]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "TestSpecialization", +// CHECK-SAME: elements: ![[empty]] + +template bool a; +template struct b; +struct TestPartial { + template static auto d = a; + template static auto d> = d; +} c; + +// CHECK: ![[A:[^ ]*]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "TestPartial", +// CHECK-SAME: elements: ![[empty]] diff --git a/test/CodeGenCXX/debug-info-composite-cc.cpp b/test/CodeGenCXX/debug-info-composite-cc.cpp new file mode 100644 index 0000000000000..d4d4046105e14 --- /dev/null +++ b/test/CodeGenCXX/debug-info-composite-cc.cpp @@ -0,0 +1,50 @@ +// RUN: %clang_cc1 -emit-llvm -debug-info-kind=standalone -triple %itanium_abi_triple %s -o - | FileCheck %s + +// Not trivially copyable because of the explicit destructor. +// CHECK-DAG: !DICompositeType({{.*}}, name: "RefDtor",{{.*}}flags: DIFlagTypePassByReference +struct RefDtor { + int i; + ~RefDtor() {} +} refDtor; + +// Not trivially copyable because of the explicit copy constructor. +// CHECK-DAG: !DICompositeType({{.*}}, name: "RefCopy",{{.*}}flags: DIFlagTypePassByReference +struct RefCopy { + int i; + RefCopy() = default; + RefCopy(RefCopy &Copy) {} +} refCopy; + +// POD-like type even though it defines a destructor. +// CHECK-DAG: !DICompositeType({{.*}}, name: "Podlike", {{.*}}flags: DIFlagTypePassByValue +struct Podlike { + int i; + Podlike() = default; + Podlike(Podlike &&Move) = default; + ~Podlike() = default; +} podlike; + + +// This is a POD type. +// CHECK-DAG: !DICompositeType({{.*}}, name: "Pod",{{.*}}flags: DIFlagTypePassByValue +struct Pod { + int i; +} pod; + +// This is definitely not a POD type. +// CHECK-DAG: !DICompositeType({{.*}}, name: "Complex",{{.*}}flags: DIFlagTypePassByReference +struct Complex { + Complex() {} + Complex(Complex &Copy) : i(Copy.i) {}; + int i; +} complex; + +// This type is manually marked as trivial_abi. +// CHECK-DAG: !DICompositeType({{.*}}, name: "Marked",{{.*}}flags: DIFlagTypePassByValue +struct __attribute__((trivial_abi)) Marked { + int *p; + Marked(); + ~Marked(); + Marked(const Marked &) noexcept; + Marked &operator=(const Marked &); +} marked; diff --git a/test/CodeGenCXX/debug-info-enum-class.cpp b/test/CodeGenCXX/debug-info-enum-class.cpp index b615d5b09626f..e857bb1959133 100644 --- a/test/CodeGenCXX/debug-info-enum-class.cpp +++ b/test/CodeGenCXX/debug-info-enum-class.cpp @@ -15,7 +15,7 @@ D d; // CHECK-SAME: baseType: ![[INT:[0-9]+]] // CHECK-SAME: size: 32 // CHECK-NOT: offset: -// CHECK-NOT: flags: +// CHECK-SAME: flags: DIFlagFixedEnum // CHECK-SAME: ){{$}} // CHECK: ![[INT]] = !DIBasicType(name: "int" // CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "B" @@ -23,12 +23,12 @@ D d; // CHECK-SAME: baseType: ![[ULONG:[0-9]+]] // CHECK-SAME: size: 64 // CHECK-NOT: offset: -// CHECK-NOT: flags: +// CHECK-SAME: flags: DIFlagFixedEnum // CHECK-SAME: ){{$}} // CHECK: ![[ULONG]] = !DIBasicType(name: "long unsigned int" // CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "C" // CHECK-SAME: line: 5 -// CHECK-NOT: baseType: +// CHECK-SAME: baseType: ![[ULONG:[0-9]+]] // CHECK-SAME: size: 32 // CHECK-NOT: offset: // CHECK-NOT: flags: diff --git a/test/CodeGenCXX/debug-info-enum.cpp b/test/CodeGenCXX/debug-info-enum.cpp index 8f54f9d712247..447edba446dc2 100644 --- a/test/CodeGenCXX/debug-info-enum.cpp +++ b/test/CodeGenCXX/debug-info-enum.cpp @@ -11,7 +11,7 @@ namespace test1 { // CHECK-SAME: identifier: "_ZTSN5test11eE" // CHECK: [[TEST1]] = !DINamespace(name: "test1" // CHECK: [[TEST1_ENUMS]] = !{[[TEST1_E:![0-9]*]]} -// CHECK: [[TEST1_E]] = !DIEnumerator(name: "E", value: 0) +// CHECK: [[TEST1_E]] = !DIEnumerator(name: "E", value: 0, isUnsigned: true) enum e { E }; void foo() { int v = E; diff --git a/test/CodeGenCXX/debug-info-line-if.cpp b/test/CodeGenCXX/debug-info-line-if.cpp index 41770b1356194..7e6cdb2eb9d81 100644 --- a/test/CodeGenCXX/debug-info-line-if.cpp +++ b/test/CodeGenCXX/debug-info-line-if.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -debug-info-kind=limited -std=c++11 -S -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -debug-info-kind=limited -std=c++11 -S -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s // PR19864 extern int v[2]; int a = 0, b = 0; diff --git a/test/CodeGenCXX/debug-info-ms-dtor-thunks.cpp b/test/CodeGenCXX/debug-info-ms-dtor-thunks.cpp index f876267eb5d69..d6fdee62d6772 100644 --- a/test/CodeGenCXX/debug-info-ms-dtor-thunks.cpp +++ b/test/CodeGenCXX/debug-info-ms-dtor-thunks.cpp @@ -4,11 +4,11 @@ struct __declspec(dllexport) S { virtual ~S(); }; struct __declspec(dllexport) T { virtual ~T(); }; struct __declspec(dllexport) U : S, T { virtual ~U(); }; -// CHECK-LABEL: define {{.*}} @"\01??_GS@@UAEPAXI@Z" -// CHECK: call x86_thiscallcc void @"\01??_DS@@QAEXXZ"(%struct.S* %this1){{.*}}!dbg !{{[0-9]+}} +// CHECK-LABEL: define {{.*}} @"??_GS@@UAEPAXI@Z" +// CHECK: call x86_thiscallcc void @"??1S@@UAE@XZ"(%struct.S* %this1){{.*}}!dbg !{{[0-9]+}} -// CHECK-LABEL: define {{.*}} @"\01??_GT@@UAEPAXI@Z" -// CHECK: call x86_thiscallcc void @"\01??_DT@@QAEXXZ"(%struct.T* %this1){{.*}}!dbg !{{[0-9]+}} +// CHECK-LABEL: define {{.*}} @"??_GT@@UAEPAXI@Z" +// CHECK: call x86_thiscallcc void @"??1T@@UAE@XZ"(%struct.T* %this1){{.*}}!dbg !{{[0-9]+}} -// CHECK-LABEL: define {{.*}} @"\01??_GU@@UAEPAXI@Z" -// CHECK: call x86_thiscallcc void @"\01??_DU@@QAEXXZ"(%struct.U* %this1){{.*}}!dbg !{{[0-9]+}} +// CHECK-LABEL: define {{.*}} @"??_GU@@UAEPAXI@Z" +// CHECK: call x86_thiscallcc void @"??1U@@UAE@XZ"(%struct.U* %this1){{.*}}!dbg !{{[0-9]+}} diff --git a/test/CodeGenCXX/debug-info-ms-vbase.cpp b/test/CodeGenCXX/debug-info-ms-vbase.cpp index 3de3a751cba1a..04c9a6d2ba74e 100644 --- a/test/CodeGenCXX/debug-info-ms-vbase.cpp +++ b/test/CodeGenCXX/debug-info-ms-vbase.cpp @@ -8,7 +8,7 @@ // CHECK: ![[elements]] = !{![[NoPrimaryBase_base:[0-9]+]]} // CHECK: ![[NoPrimaryBase_base]] = !DIDerivedType(tag: DW_TAG_inheritance, scope: ![[NoPrimaryBase]], -// CHECK-SAME: baseType: ![[HasVirtualMethod:[0-9]+]], offset: 4, flags: DIFlagVirtual) +// CHECK-SAME: baseType: ![[HasVirtualMethod:[0-9]+]], offset: 4, flags: DIFlagVirtual, extraData: i32 0) // CHECK: ![[HasVirtualMethod]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "HasVirtualMethod" @@ -18,11 +18,11 @@ // CHECK: ![[elements]] = !{![[SecondaryVTable_base:[0-9]+]], ![[HasVirtualMethod_base:[0-9]+]], ![[vshape:[0-9]+]]} // CHECK: ![[SecondaryVTable_base]] = !DIDerivedType(tag: DW_TAG_inheritance, scope: ![[HasPrimaryBase]], -// CHECK-SAME: baseType: ![[SecondaryVTable:[0-9]+]], offset: 4, flags: DIFlagVirtual) +// CHECK-SAME: baseType: ![[SecondaryVTable:[0-9]+]], offset: 4, flags: DIFlagVirtual, extraData: i32 4) // CHECK: ![[SecondaryVTable]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "SecondaryVTable" -// CHECK: ![[HasVirtualMethod_base]] = !DIDerivedType(tag: DW_TAG_inheritance, scope: ![[HasPrimaryBase]], baseType: ![[HasVirtualMethod]]) +// CHECK: ![[HasVirtualMethod_base]] = !DIDerivedType(tag: DW_TAG_inheritance, scope: ![[HasPrimaryBase]], baseType: ![[HasVirtualMethod]], extraData: i32 0) // CHECK: ![[HasIndirectVirtualBase:[0-9]+]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "HasIndirectVirtualBase" // CHECK-SAME: elements: ![[elements:[0-9]+]] @@ -41,7 +41,7 @@ // CHECK: ![[elements]] = !{![[POD_base:[0-9]+]]} // CHECK: ![[POD_base]] = !DIDerivedType(tag: DW_TAG_inheritance, scope: ![[DynamicNoVFPtr]], -// CHECK-SAME: baseType: ![[POD:[0-9]+]], offset: 4, flags: DIFlagVirtual) +// CHECK-SAME: baseType: ![[POD:[0-9]+]], offset: 4, flags: DIFlagVirtual, extraData: i32 0) // CHECK: ![[POD]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "POD" diff --git a/test/CodeGenCXX/debug-info-range-for-var-names.cpp b/test/CodeGenCXX/debug-info-range-for-var-names.cpp new file mode 100644 index 0000000000000..6cd70fe0820dc --- /dev/null +++ b/test/CodeGenCXX/debug-info-range-for-var-names.cpp @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited %s -o - | FileCheck %s + +struct vec { + using itr = int*; + itr begin() { return nullptr; } + itr end() { return nullptr; } +}; + +void test() { + vec as, bs, cs; + + for (auto a : as) + for (auto b : bs) + for (auto c : cs) { + } +} + +// CHECK: call void @llvm.dbg.declare(metadata %struct.vec** {{.*}}, metadata ![[RANGE1:[0-9]+]] +// CHECK: call void @llvm.dbg.declare(metadata i32** {{.*}}, metadata ![[BEGIN1:[0-9]+]] +// CHECK: call void @llvm.dbg.declare(metadata i32** {{.*}}, metadata ![[END1:[0-9]+]] +// CHECK: call void @llvm.dbg.declare(metadata %struct.vec** {{.*}}, metadata ![[RANGE2:[0-9]+]] +// CHECK: call void @llvm.dbg.declare(metadata i32** {{.*}}, metadata ![[BEGIN2:[0-9]+]] +// CHECK: call void @llvm.dbg.declare(metadata i32** {{.*}}, metadata ![[END2:[0-9]+]] +// CHECK: call void @llvm.dbg.declare(metadata %struct.vec** {{.*}}, metadata ![[RANGE3:[0-9]+]] +// CHECK: call void @llvm.dbg.declare(metadata i32** {{.*}}, metadata ![[BEGIN3:[0-9]+]] +// CHECK: call void @llvm.dbg.declare(metadata i32** {{.*}}, metadata ![[END3:[0-9]+]] +// CHECK: ![[RANGE1]] = !DILocalVariable(name: "__range1", +// CHECK: ![[BEGIN1]] = !DILocalVariable(name: "__begin1", +// CHECK: ![[END1]] = !DILocalVariable(name: "__end1", +// CHECK: ![[RANGE2]] = !DILocalVariable(name: "__range2", +// CHECK: ![[BEGIN2]] = !DILocalVariable(name: "__begin2", +// CHECK: ![[END2]] = !DILocalVariable(name: "__end2", +// CHECK: ![[RANGE3]] = !DILocalVariable(name: "__range3", +// CHECK: ![[BEGIN3]] = !DILocalVariable(name: "__begin3", +// CHECK: ![[END3]] = !DILocalVariable(name: "__end3", diff --git a/test/CodeGenCXX/debug-info-scope.cpp b/test/CodeGenCXX/debug-info-scope.cpp index e81eccc5168f2..1124282697492 100644 --- a/test/CodeGenCXX/debug-info-scope.cpp +++ b/test/CodeGenCXX/debug-info-scope.cpp @@ -58,7 +58,7 @@ void func() { } int x[] = {1, 2}; - // CHECK: = !DILocalVariable(name: "__range" + // CHECK: = !DILocalVariable(name: "__range1" // CHECK-SAME: scope: [[RANGE_FOR:![0-9]*]] // CHECK-NOT: line: // CHECK-SAME: ){{$}} diff --git a/test/CodeGenCXX/debug-info-static-member.cpp b/test/CodeGenCXX/debug-info-static-member.cpp index 3537754ced760..702d1f87e752c 100644 --- a/test/CodeGenCXX/debug-info-static-member.cpp +++ b/test/CodeGenCXX/debug-info-static-member.cpp @@ -3,9 +3,9 @@ // RUN: %clangxx -target x86_64-unknown-unknown -g -std=c++11 %s -emit-llvm -S -o - | FileCheck %s // PR14471 -// CHECK: @_ZN1C1aE = global i32 4, align 4, !dbg [[A:![0-9]+]] -// CHECK: @_ZN1C1bE = global i32 2, align 4, !dbg [[B:![0-9]+]] -// CHECK: @_ZN1C1cE = global i32 1, align 4, !dbg [[C:![0-9]+]] +// CHECK: @_ZN1C1aE = dso_local global i32 4, align 4, !dbg [[A:![0-9]+]] +// CHECK: @_ZN1C1bE = dso_local global i32 2, align 4, !dbg [[B:![0-9]+]] +// CHECK: @_ZN1C1cE = dso_local global i32 1, align 4, !dbg [[C:![0-9]+]] enum X { Y diff --git a/test/CodeGenCXX/debug-info-template.cpp b/test/CodeGenCXX/debug-info-template.cpp index 0c34145162159..4b330a0b0a118 100644 --- a/test/CodeGenCXX/debug-info-template.cpp +++ b/test/CodeGenCXX/debug-info-template.cpp @@ -1,8 +1,8 @@ // RUN: %clang -S -emit-llvm -target x86_64-unknown_unknown -g %s -o - -std=c++11 | FileCheck %s -// CHECK: @tci = global %"struct.TC::nested" zeroinitializer, align 1, !dbg [[TCI:![0-9]+]] -// CHECK: @tcn = global %struct.TC zeroinitializer, align 1, !dbg [[TCN:![0-9]+]] -// CHECK: @nn = global %struct.NN zeroinitializer, align 1, !dbg [[NN:![0-9]+]] +// CHECK: @tci = dso_local global %"struct.TC::nested" zeroinitializer, align 1, !dbg [[TCI:![0-9]+]] +// CHECK: @tcn = dso_local global %struct.TC zeroinitializer, align 1, !dbg [[TCN:![0-9]+]] +// CHECK: @nn = dso_local global %struct.NN zeroinitializer, align 1, !dbg [[NN:![0-9]+]] // CHECK: !DICompileUnit( // CHECK: [[EMPTY:![0-9]*]] = !{} diff --git a/test/CodeGenCXX/debug-info-thunk-msabi.cpp b/test/CodeGenCXX/debug-info-thunk-msabi.cpp index 5c705ac0ac134..565992ad2a3d2 100644 --- a/test/CodeGenCXX/debug-info-thunk-msabi.cpp +++ b/test/CodeGenCXX/debug-info-thunk-msabi.cpp @@ -3,10 +3,10 @@ class __declspec(dllexport) A { A(int * = new int) {} }; -// CHECK: define {{.*}}void @"\01??_FA@@AAEXXZ" +// CHECK: define {{.*}}void @"??_FA@@AAEXXZ" // CHECK-SAME: !dbg ![[SP:[0-9]+]] // CHECK-NOT: {{ret }} -// CHECK: call x86_thiscallcc %class.A* @"\01??0A@@AAE@PAH@Z" +// CHECK: call x86_thiscallcc %class.A* @"??0A@@AAE@PAH@Z" // CHECK-SAME: !dbg ![[DBG:[0-9]+]] // CHECK: ret void, !dbg // diff --git a/test/CodeGenCXX/debug-info-thunk.cpp b/test/CodeGenCXX/debug-info-thunk.cpp index f7d16f493256e..56dec93f6b391 100644 --- a/test/CodeGenCXX/debug-info-thunk.cpp +++ b/test/CodeGenCXX/debug-info-thunk.cpp @@ -1,29 +1,277 @@ -// RUN: %clang_cc1 %s -triple %itanium_abi_triple -debug-info-kind=limited -S -emit-llvm -o - | FileCheck %s - -struct A { - virtual void f(); -}; - -struct B { - virtual void f(); -}; - -struct C : A, B { - virtual void f(); -}; - -void C::f() { } -// CHECK: define {{.*}}void @_ZThn{{[48]}}_N1C1fEv -// CHECK-SAME: !dbg ![[SP:[0-9]+]] -// CHECK-NOT: {{ret }} -// CHECK: = load{{.*}} !dbg ![[DBG:[0-9]+]] -// CHECK-NOT: {{ret }} -// CHECK: ret void, !dbg ![[DBG]] +// RUN: %clang_cc1 %s -triple=x86_64-pc-windows-msvc -debug-info-kind=limited -S -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple %itanium_abi_triple -debug-info-kind=limited -S -emit-llvm -o - | FileCheck %s -check-prefix=ITANIUM // -// CHECK: ![[SP]] = distinct !DISubprogram(linkageName: "_ZThn{{[48]}}_N1C1fEv" -// CHECK-SAME: line: 15 -// CHECK-SAME: isDefinition: true -// CHECK-SAME: DIFlagArtificial -// CHECK-SAME: ){{$}} +// Validate we emit a "DIFlagThunk" flag on DISubprogram entries for thunks. +// This flag is used for emitting S_THUNK32 symbols for CodeView debugging. // -// CHECK: ![[DBG]] = !DILocation(line: 0 +// NOTE: +// Because thunks are compiler generated and don't exist in the source, this +// test is dependent upon the linkage name to identify the thunk. Any changes +// in the name mangling may require this test to be updated. +// +// NOTE: +// The FileCheck directives below use CHECK-DAG because the thunks may not be +// emitted in source order. +// + +namespace Test1 { + struct A { + virtual void f(); + }; + + struct B { + virtual void f(); + }; + + struct C : A, B { + virtual void c(); + + virtual void f(); + }; + +// CHECK-DAG: DISubprogram{{.*}}linkageName: "?f@C@Test1@@W7EAAXXZ"{{.*}} flags: {{.*}}DIFlagThunk + void C::f() { } +} + +namespace Test2 { + struct V1 { }; + struct V2 : virtual V1 { }; + + struct A { + virtual V1 *f(); + }; + + struct B : A { + virtual void b(); + + virtual V2 *f(); + }; + +// CHECK-DAG: DISubprogram{{.*}}linkageName: "?f@B@Test2@@QEAAPEAUV1@2@XZ"{{.*}} flags: {{.*}}DIFlagThunk + V2 *B::f() { return 0; } +} + +namespace Test3 { + struct A { + virtual void f(); + }; + + struct B { + virtual void f(); + }; + + struct __attribute__((visibility("protected"))) C : A, B { + virtual void c(); + + virtual void f(); + }; + +// CHECK-DAG: DISubprogram{{.*}}linkageName: "?f@C@Test3@@W7EAAXXZ"{{.*}} flags: {{.*}}DIFlagThunk + void C::f() { } +} + +namespace Test4 { + struct A { + virtual void f(); + }; + + struct B { + virtual void f(); + }; + + namespace { + struct C : A, B { + virtual void c(); + virtual void f(); + }; + } + void C::c() {} +// CHECK-DAG: DISubprogram{{.*}}linkageName: "?f@C@?A@Test4@@W7EAAXXZ"{{.*}} flags: {{.*}}DIFlagThunk + void C::f() {} + + // Force C::f to be used. + void f() { + C c; + c.f(); + } +} + +namespace Test5 { + struct X { + X(); + X(const X&); + X &operator=(const X&); + ~X(); + }; + + struct P { + P(); + P(const P&); + ~P(); + X first; + X second; + }; + + P getP(); + + struct Base1 { + int i; + + virtual X f() { return X(); } + }; + + struct Base2 { + float real; + + virtual X f() { return X(); } + }; + + struct Thunks : Base1, Base2 { + long l; + + virtual X f(); + }; + +// CHECK-DAG: DISubprogram{{.*}}linkageName: "?f@Thunks@Test5@@WBA@EAA?AUX@2@XZ"{{.*}} flags: {{.*}}DIFlagThunk + X Thunks::f() { return X(); } +} + +namespace Test6 { + struct X { + X(); + X(const X&); + X &operator=(const X&); + ~X(); + }; + + struct Small { short s; }; + struct Large { + char array[1024]; + }; + + class A { + protected: + virtual void foo() = 0; + }; + + class B : public A { + protected: + virtual void bar() = 0; + }; + + class C : public A { + protected: + virtual void baz(X, X&, _Complex float, Small, Small&, Large) = 0; + }; + + class D : public B, + public C { +// CHECK-DAG: DISubprogram{{.*}}linkageName: "?foo@D@Test6@@G7EAAXXZ"{{.*}} flags: {{.*}}DIFlagThunk + void foo() {} + void bar() {} + void baz(X, X&, _Complex float, Small, Small&, Large); + }; + + void D::baz(X, X&, _Complex float, Small, Small&, Large) { } + + void testD() { D d; } +} + +namespace Test7 { + struct A { virtual void foo(); }; + struct B { virtual void foo(); }; +// CHECK-DAG: DISubprogram{{.*}}linkageName: "?foo@C@Test7@@W7EAAXXZ"{{.*}} flags: {{.*}}DIFlagThunk + struct C : A, B { void foo() {} }; + + // Test later. + void test() { + C c; + } +} + +namespace Test8 { + struct A { virtual A* f(); }; + struct B : virtual A { virtual A* f(); }; + struct C : B { virtual C* f(); }; +// CHECK-DAG: DISubprogram{{.*}}linkageName: "?f@C@Test8@@QEAAPEAUA@2@XZ"{{.*}} flags: {{.*}}DIFlagThunk + C* C::f() { return 0; } +} + +namespace Test9 { + struct B1 { + virtual B1 &foo1(); + }; + struct Pad1 { + virtual ~Pad1(); + }; + struct Proxy1 : Pad1, B1 { + virtual ~Proxy1(); + }; + struct D : virtual Proxy1 { + virtual ~D(); + virtual D &foo1(); + }; +// CHECK-DAG: DISubprogram{{.*}}linkageName: "?foo1@D@Test9@@$4PPPPPPPE@A@EAAAEAUB1@2@XZ"{{.*}} flags: {{.*}}DIFlagThunk +// CHECK-DAG: DISubprogram{{.*}}linkageName: "?foo1@D@Test9@@$4PPPPPPPE@A@EAAAEAU12@XZ"{{.*}} flags: {{.*}}DIFlagThunk + D& D::foo1() { + return *this; + } +} + +namespace Test10 { + class A { + virtual void f(); + }; + class B { + virtual void f(); + }; + class C : public A, public B { + virtual void f(); + }; +// CHECK-DAG: DISubprogram{{.*}}linkageName: "?f@C@Test10@@G7EAAXXZ"{{.*}} flags: {{.*}}DIFlagThunk + void C::f() { + } +} + +namespace Test11 { + class A { + public: + virtual void f(); + }; + + void test() { +// CHECK-DAG: DISubprogram{{.*}}linkageName: "??_9A@Test11@@$BA@AA"{{.*}} flags: {{.*}}DIFlagThunk + void (A::*p)() = &A::f; + } +} + +namespace Test12 { + struct A { + virtual void f(); + }; + + struct B { + virtual void f(); + }; + + struct C : A, B { + virtual void f(); + }; + + void C::f() { } + // ITANIUM: define {{.*}}void @_ZThn{{[48]}}_N6Test121C1fEv + // ITANIUM-SAME: !dbg ![[SP:[0-9]+]] + // ITANIUM-NOT: {{ret }} + // ITANIUM: = load{{.*}} !dbg ![[DBG:[0-9]+]] + // ITANIUM-NOT: {{ret }} + // ITANIUM: ret void, !dbg ![[DBG]] + // + // ITANIUM: ![[SP]] = distinct !DISubprogram(linkageName: "_ZThn{{[48]}}_N6Test121C1fEv" + // ITANIUM-SAME: line: 261 + // ITANIUM-SAME: isDefinition: true + // ITANIUM-SAME: DIFlagArtificial + // ITANIUM-SAME: DIFlagThunk + // ITANIUM-SAME: ){{$}} + // + // ITANIUM: ![[DBG]] = !DILocation(line: 0 +} diff --git a/test/CodeGenCXX/debug-info-vla.cpp b/test/CodeGenCXX/debug-info-vla.cpp index 88f3a3f55dab9..6c35f301f968e 100644 --- a/test/CodeGenCXX/debug-info-vla.cpp +++ b/test/CodeGenCXX/debug-info-vla.cpp @@ -1,4 +1,4 @@ -// RUN: %clang -target x86_64-unknown-unknown -fverbose-asm -g -O0 -S -emit-llvm %s -o - -std=c++11 | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited -std=c++11 -triple x86_64-unknown-unknown %s -o - | FileCheck %s void f(int m) { @@ -13,8 +13,10 @@ int (*fp)(int[][*]) = nullptr; // CHECK: [[ELEM_TYPE]] = !{[[NOCOUNT:.*]]} // CHECK: [[NOCOUNT]] = !DISubrange(count: -1) // +// CHECK: [[VAR:![0-9]+]] = !DILocalVariable(name: "__vla_expr", {{.*}}flags: DIFlagArtificial // CHECK: !DICompositeType(tag: DW_TAG_array_type, // CHECK-NOT: size: // CHECK-SAME: elements: [[ELEM_TYPE:![0-9]+]] -// CHECK: [[ELEM_TYPE]] = !{[[THREE:.*]], [[NOCOUNT]]} +// CHECK: [[ELEM_TYPE]] = !{[[THREE:.*]], [[VARRANGE:![0-9]+]]} // CHECK: [[THREE]] = !DISubrange(count: 3) +// CHECK: [[VARRANGE]] = !DISubrange(count: [[VAR]]) diff --git a/test/CodeGenCXX/debug-info-windows-dtor.cpp b/test/CodeGenCXX/debug-info-windows-dtor.cpp index 8eb744a61bc78..0b3d7e17e3faa 100644 --- a/test/CodeGenCXX/debug-info-windows-dtor.cpp +++ b/test/CodeGenCXX/debug-info-windows-dtor.cpp @@ -14,8 +14,8 @@ struct AB: A, B { template struct AB; -// CHECK: define {{.*}}@"\01??_E?$AB@H@@W3AEPAXI@Z"({{.*}} !dbg [[THUNK_VEC_DEL_DTOR:![0-9]*]] -// CHECK: call {{.*}}@"\01??_G?$AB@H@@UAEPAXI@Z"({{.*}}) #{{[0-9]*}}, !dbg [[THUNK_LOC:![0-9]*]] +// CHECK: define {{.*}}@"??_E?$AB@H@@W3AEPAXI@Z"({{.*}} !dbg [[THUNK_VEC_DEL_DTOR:![0-9]*]] +// CHECK: call {{.*}}@"??_G?$AB@H@@UAEPAXI@Z"({{.*}}) #{{[0-9]*}}, !dbg [[THUNK_LOC:![0-9]*]] // CHECK: define // CHECK: [[THUNK_VEC_DEL_DTOR]] = distinct !DISubprogram diff --git a/test/CodeGenCXX/delayed-template-parsing.cpp b/test/CodeGenCXX/delayed-template-parsing.cpp index c5f4486415440..c0e9425d5184e 100644 --- a/test/CodeGenCXX/delayed-template-parsing.cpp +++ b/test/CodeGenCXX/delayed-template-parsing.cpp @@ -11,8 +11,8 @@ namespace ClassScopeSpecialization { void call() { Type T; -// CHECK: call {{.*}} @"\01??$Foo@$0A@@Type@ClassScopeSpecialization@@QAEXXZ" -// X64: call {{.*}} @"\01??$Foo@$0A@@Type@ClassScopeSpecialization@@QEAAXXZ" +// CHECK: call {{.*}} @"??$Foo@$0A@@Type@ClassScopeSpecialization@@QAEXXZ" +// X64: call {{.*}} @"??$Foo@$0A@@Type@ClassScopeSpecialization@@QEAAXXZ" T.Foo<0>(); } } diff --git a/test/CodeGenCXX/derived-cast.cpp b/test/CodeGenCXX/derived-cast.cpp new file mode 100644 index 0000000000000..bf2b258c5e9f8 --- /dev/null +++ b/test/CodeGenCXX/derived-cast.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm %s -o - | FileCheck %s + +class A { + int a; +}; + +class B { + int b; +public: + A *getAsA(); +}; + +class X : public A, public B { + int x; +}; + +// PR35909 - https://bugs.llvm.org/show_bug.cgi?id=35909 + +A *B::getAsA() { + return static_cast(this); + + // CHECK-LABEL: define %class.A* @_ZN1B6getAsAEv + // CHECK: %[[THIS:.*]] = load %class.B*, %class.B** + // CHECK-NEXT: %[[BC:.*]] = bitcast %class.B* %[[THIS]] to i8* + // CHECK-NEXT: getelementptr inbounds i8, i8* %[[BC]], i64 -4 +} + diff --git a/test/CodeGenCXX/destructors.cpp b/test/CodeGenCXX/destructors.cpp index 180e82de9fffb..ba8333b00dd6c 100644 --- a/test/CodeGenCXX/destructors.cpp +++ b/test/CodeGenCXX/destructors.cpp @@ -96,7 +96,7 @@ namespace test0 { // complete destructor alias tested above -// CHECK2-LABEL: @_ZN5test01AD1Ev = alias {{.*}} @_ZN5test01AD2Ev +// CHECK2-LABEL: @_ZN5test01AD1Ev = unnamed_addr alias {{.*}} @_ZN5test01AD2Ev // CHECK2-LABEL: define void @_ZN5test01AD2Ev(%"struct.test0::A"* %this) unnamed_addr // CHECK2: invoke void @_ZN5test06MemberD1Ev // CHECK2: unwind label [[MEM_UNWIND:%[a-zA-Z0-9.]+]] @@ -104,7 +104,7 @@ namespace test0 { // CHECK2: unwind label [[BASE_UNWIND:%[a-zA-Z0-9.]+]] // In C++11, the destructors are often known not to throw. -// CHECK2v11-LABEL: @_ZN5test01AD1Ev = alias {{.*}} @_ZN5test01AD2Ev +// CHECK2v11-LABEL: @_ZN5test01AD1Ev = unnamed_addr alias {{.*}} @_ZN5test01AD2Ev // CHECK2v11-LABEL: define void @_ZN5test01AD2Ev(%"struct.test0::A"* %this) unnamed_addr // CHECK2v11: call void @_ZN5test06MemberD1Ev // CHECK2v11: call void @_ZN5test04BaseD2Ev @@ -153,15 +153,15 @@ namespace test1 { struct M : A { ~M(); }; M::~M() {} - // CHECK3: @_ZN5test11MD2Ev = alias {{.*}} @_ZN5test11AD2Ev + // CHECK3: @_ZN5test11MD2Ev = unnamed_addr alias {{.*}} @_ZN5test11AD2Ev struct N : A, Empty { ~N(); }; N::~N() {} - // CHECK3: @_ZN5test11ND2Ev = alias {{.*}} @_ZN5test11AD2Ev + // CHECK3: @_ZN5test11ND2Ev = unnamed_addr alias {{.*}} @_ZN5test11AD2Ev struct O : Empty, A { ~O(); }; O::~O() {} - // CHECK3: @_ZN5test11OD2Ev = alias {{.*}} @_ZN5test11AD2Ev + // CHECK3: @_ZN5test11OD2Ev = unnamed_addr alias {{.*}} @_ZN5test11AD2Ev struct P : NonEmpty, A { ~P(); }; P::~P() {} // CHECK3-LABEL: define void @_ZN5test11PD2Ev(%"struct.test1::P"* %this) unnamed_addr @@ -174,7 +174,7 @@ namespace test1 { struct S : A { ~S(); int x; }; S::~S() {} - // CHECK4: @_ZN5test11SD2Ev = alias {{.*}}, bitcast {{.*}} @_ZN5test11AD2Ev + // CHECK4: @_ZN5test11SD2Ev = unnamed_addr alias {{.*}}, bitcast {{.*}} @_ZN5test11AD2Ev struct T : A { ~T(); B x; }; T::~T() {} // CHECK4-LABEL: define void @_ZN5test11TD2Ev(%"struct.test1::T"* %this) unnamed_addr diff --git a/test/CodeGenCXX/devirtualize-ms-dtor.cpp b/test/CodeGenCXX/devirtualize-ms-dtor.cpp new file mode 100644 index 0000000000000..d999b0c2dc405 --- /dev/null +++ b/test/CodeGenCXX/devirtualize-ms-dtor.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -std=c++11 -triple x86_64-windows-msvc %s -emit-llvm -o - | FileCheck %s + +// If we de-virtualize ~Foo, we still need to call ??1Foo, not ??_DFoo. + +struct Base { + virtual ~Base(); +}; +struct Foo final : Base { +}; +void f(Foo *p) { + p->~Foo(); +} + +// CHECK-LABEL: define{{.*}} void @"?f@@YAXPEAUFoo@@@Z"(%struct.Foo* %p) +// CHECK: call void @"??1Foo@@UEAA@XZ" +// CHECK: ret void diff --git a/test/CodeGenCXX/discard-name-values.cpp b/test/CodeGenCXX/discard-name-values.cpp index 49cb7d2fc0587..d4d7527c28561 100644 --- a/test/CodeGenCXX/discard-name-values.cpp +++ b/test/CodeGenCXX/discard-name-values.cpp @@ -1,10 +1,29 @@ -// RUN: %clang_cc1 -emit-llvm -triple=armv7-apple-darwin -emit-llvm -std=c++11 %s -o - -O1 | FileCheck %s -// RUN: %clang_cc1 -emit-llvm -triple=armv7-apple-darwin -emit-llvm -std=c++11 %s -o - -O1 -discard-value-names | FileCheck %s --check-prefix=DISCARDVALUE +// RUN: %clang_cc1 -emit-llvm -triple=armv7-apple-darwin -std=c++11 %s -o - -O1 \ +// RUN: | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -triple=armv7-apple-darwin -std=c++11 %s -o - -O1 \ +// RUN: -discard-value-names | FileCheck %s --check-prefix=DISCARDVALUE -int foo(int bar) { - return bar; -} +extern "C" void branch(); + +bool test(bool pred) { + // DISCARDVALUE: br i1 %0, label %2, label %3 + // CHECK: br i1 %pred, label %if.then, label %if.end + + if (pred) { + // DISCARDVALUE: ;