From 45b533945f0851ec234ca846e1af5ee1e4df0b6e Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Wed, 30 Dec 2015 11:49:41 +0000 Subject: Vendor import of clang trunk r256633: https://llvm.org/svn/llvm-project/cfe/trunk@256633 --- test/CodeGenCXX/2006-11-20-GlobalSymbols.cpp | 2 +- test/CodeGenCXX/2007-01-02-UnboundedArray.cpp | 2 +- test/CodeGenCXX/2009-03-17-dbg.cpp | 2 +- test/CodeGenCXX/2009-04-23-bool2.cpp | 2 +- test/CodeGenCXX/2009-06-16-DebugInfoCrash.cpp | 2 +- test/CodeGenCXX/2010-03-09-AnonAggregate.cpp | 2 +- test/CodeGenCXX/2010-05-10-Var-DbgInfo.cpp | 2 +- test/CodeGenCXX/2010-05-12-PtrToMember-Dbg.cpp | 4 +- test/CodeGenCXX/2010-06-21-LocalVarDbg.cpp | 2 +- test/CodeGenCXX/2010-06-22-BitfieldInit.cpp | 2 +- test/CodeGenCXX/2010-06-22-ZeroBitfield.cpp | 2 +- test/CodeGenCXX/2010-07-23-DeclLoc.cpp | 2 +- test/CodeGenCXX/PR20038.cpp | 6 +- test/CodeGenCXX/PR24289.cpp | 82 ++++++ test/CodeGenCXX/alignment.cpp | 299 ++++++++++++++++++++ test/CodeGenCXX/arm.cpp | 26 +- test/CodeGenCXX/armv7k.cpp | 68 +++++ test/CodeGenCXX/attr-disable-tail-calls.cpp | 35 +++ test/CodeGenCXX/attr-notail.cpp | 17 ++ test/CodeGenCXX/attr.cpp | 2 +- test/CodeGenCXX/attribute_internal_linkage.cpp | 79 ++++++ test/CodeGenCXX/cast-to-ref-bool.cpp | 9 + test/CodeGenCXX/catch-undef-behavior.cpp | 39 ++- test/CodeGenCXX/cfi-blacklist.cpp | 30 ++ test/CodeGenCXX/cfi-cast.cpp | 32 ++- test/CodeGenCXX/cfi-cross-dso.cpp | 45 +++ test/CodeGenCXX/cfi-icall.cpp | 23 ++ test/CodeGenCXX/cfi-ms-rtti.cpp | 4 +- test/CodeGenCXX/cfi-nvcall.cpp | 8 +- test/CodeGenCXX/cfi-vcall.cpp | 70 ++--- test/CodeGenCXX/const-init-cxx11.cpp | 1 + test/CodeGenCXX/constructor-alias.cpp | 2 +- .../constructor-destructor-return-this.cpp | 2 + test/CodeGenCXX/cp-blocks-linetables.cpp | 2 +- test/CodeGenCXX/crash.cpp | 3 +- test/CodeGenCXX/ctor-dtor-alias.cpp | 2 +- test/CodeGenCXX/ctor-globalopt.cpp | 6 +- .../cxx0x-initializer-stdinitializerlist.cpp | 2 +- test/CodeGenCXX/cxx11-initializer-array-new.cpp | 10 +- test/CodeGenCXX/cxx11-thread-local-reference.cpp | 17 +- test/CodeGenCXX/cxx11-thread-local.cpp | 85 ++++-- test/CodeGenCXX/debug-info-access.cpp | 2 +- test/CodeGenCXX/debug-info-anon-namespace.cpp | 26 ++ test/CodeGenCXX/debug-info-anon-union-vars.cpp | 23 +- test/CodeGenCXX/debug-info-artificial-arg.cpp | 2 +- test/CodeGenCXX/debug-info-blocks.cpp | 2 +- test/CodeGenCXX/debug-info-char16.cpp | 2 +- test/CodeGenCXX/debug-info-class-nolimit.cpp | 8 +- .../debug-info-codeview-display-name.cpp | 73 +++++ test/CodeGenCXX/debug-info-context.cpp | 2 +- test/CodeGenCXX/debug-info-cxx0x.cpp | 2 +- test/CodeGenCXX/debug-info-cxx1y.cpp | 2 +- test/CodeGenCXX/debug-info-decl-nested.cpp | 2 +- test/CodeGenCXX/debug-info-determinism.cpp | 4 +- test/CodeGenCXX/debug-info-dup-fwd-decl.cpp | 2 +- test/CodeGenCXX/debug-info-enum-class.cpp | 2 +- test/CodeGenCXX/debug-info-enum.cpp | 2 +- test/CodeGenCXX/debug-info-explicit-cast.cpp | 46 +++ test/CodeGenCXX/debug-info-flex-member.cpp | 2 +- test/CodeGenCXX/debug-info-function-context.cpp | 2 +- test/CodeGenCXX/debug-info-fwd-ref.cpp | 2 +- test/CodeGenCXX/debug-info-gline-tables-only.cpp | 2 +- test/CodeGenCXX/debug-info-global-ctor-dtor.cpp | 4 +- test/CodeGenCXX/debug-info-global.cpp | 2 +- test/CodeGenCXX/debug-info-globalinit.cpp | 2 +- test/CodeGenCXX/debug-info-indirect-field-decl.cpp | 2 +- test/CodeGenCXX/debug-info-large-constant.cpp | 2 +- test/CodeGenCXX/debug-info-limited.cpp | 3 +- test/CodeGenCXX/debug-info-line-if.cpp | 2 +- test/CodeGenCXX/debug-info-line.cpp | 4 +- test/CodeGenCXX/debug-info-method-nodebug.cpp | 2 +- test/CodeGenCXX/debug-info-method.cpp | 9 +- test/CodeGenCXX/debug-info-method2.cpp | 2 +- test/CodeGenCXX/debug-info-namespace.cpp | 13 +- test/CodeGenCXX/debug-info-nullptr.cpp | 2 +- .../debug-info-ptr-to-member-function.cpp | 4 +- test/CodeGenCXX/debug-info-qualifiers.cpp | 6 +- test/CodeGenCXX/debug-info-rvalue-ref.cpp | 4 +- test/CodeGenCXX/debug-info-scope.cpp | 18 +- test/CodeGenCXX/debug-info-static-fns.cpp | 6 +- ...debug-info-template-explicit-specialization.cpp | 4 +- test/CodeGenCXX/debug-info-template-fwd.cpp | 2 +- test/CodeGenCXX/debug-info-template-limit.cpp | 2 +- test/CodeGenCXX/debug-info-template-member.cpp | 3 +- .../debug-info-template-partial-specialization.cpp | 2 +- test/CodeGenCXX/debug-info-template-quals.cpp | 2 +- test/CodeGenCXX/debug-info-template-recursive.cpp | 2 +- test/CodeGenCXX/debug-info-thunk.cpp | 2 +- test/CodeGenCXX/debug-info-union-template.cpp | 2 +- test/CodeGenCXX/debug-info-union.cpp | 2 +- test/CodeGenCXX/debug-info-use-after-free.cpp | 2 +- test/CodeGenCXX/debug-info-uuid.cpp | 4 +- test/CodeGenCXX/debug-info-varargs.cpp | 4 +- test/CodeGenCXX/debug-info-vtable-optzn.cpp | 4 +- test/CodeGenCXX/debug-info-wchar.cpp | 2 +- test/CodeGenCXX/debug-info-windows-dtor.cpp | 8 +- test/CodeGenCXX/debug-info.cpp | 16 +- test/CodeGenCXX/debug-lambda-expressions.cpp | 10 +- test/CodeGenCXX/debug-lambda-this.cpp | 2 +- test/CodeGenCXX/default-destructor-synthesis.cpp | 38 --- test/CodeGenCXX/delete-two-arg.cpp | 4 +- test/CodeGenCXX/destructor-debug-info.cpp | 2 +- test/CodeGenCXX/destructors.cpp | 2 +- test/CodeGenCXX/dllexport-alias.cpp | 4 +- test/CodeGenCXX/dllexport-members.cpp | 18 +- test/CodeGenCXX/dllexport.cpp | 52 +++- test/CodeGenCXX/dllimport-rtti.cpp | 4 +- test/CodeGenCXX/dllimport.cpp | 48 +++- test/CodeGenCXX/duplicate-mangled-name.cpp | 36 ++- test/CodeGenCXX/enable_if.cpp | 9 + test/CodeGenCXX/exceptions-cxx-new.cpp | 77 +++++ test/CodeGenCXX/exceptions-seh-filter-captures.cpp | 11 +- test/CodeGenCXX/exceptions-seh.cpp | 34 ++- test/CodeGenCXX/exceptions.cpp | 22 +- test/CodeGenCXX/extern-c.cpp | 4 +- test/CodeGenCXX/funcattrs-global-ctor-dtor.cpp | 12 + test/CodeGenCXX/globalinit-loc.cpp | 4 +- test/CodeGenCXX/homogeneous-aggregates.cpp | 2 +- test/CodeGenCXX/init-invariant.cpp | 2 +- test/CodeGenCXX/inline-dllexport-member.cpp | 6 +- test/CodeGenCXX/inline-functions.cpp | 50 ++-- test/CodeGenCXX/invariant.group-for-vptrs.cpp | 74 +++++ test/CodeGenCXX/lambda-expressions.cpp | 2 +- test/CodeGenCXX/linetable-cleanup.cpp | 2 +- test/CodeGenCXX/linetable-eh.cpp | 2 +- test/CodeGenCXX/linetable-fnbegin.cpp | 8 +- test/CodeGenCXX/linetable-virtual-variadic.cpp | 8 +- test/CodeGenCXX/lpad-linetable.cpp | 2 +- test/CodeGenCXX/main-norecurse.cpp | 8 + test/CodeGenCXX/mangle-literal-suffix.cpp | 6 +- test/CodeGenCXX/mangle-ms-cxx11.cpp | 43 +++ test/CodeGenCXX/mangle-ms-cxx14.cpp | 29 +- test/CodeGenCXX/mangle-ms-vector-types.cpp | 6 +- test/CodeGenCXX/mangle-ms.cpp | 65 +++++ test/CodeGenCXX/mangle-variadic-templates.cpp | 12 +- test/CodeGenCXX/member-alignment.cpp | 15 +- test/CodeGenCXX/member-function-pointers.cpp | 2 + test/CodeGenCXX/member-initializers.cpp | 35 --- test/CodeGenCXX/microsoft-abi-arg-order.cpp | 10 +- test/CodeGenCXX/microsoft-abi-array-cookies.cpp | 8 +- test/CodeGenCXX/microsoft-abi-dynamic-cast.cpp | 25 +- test/CodeGenCXX/microsoft-abi-eh-catch.cpp | 92 +++--- test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp | 65 +++-- test/CodeGenCXX/microsoft-abi-eh-terminate.cpp | 10 +- test/CodeGenCXX/microsoft-abi-member-pointers.cpp | 50 ++++ test/CodeGenCXX/microsoft-abi-structors-alias.cpp | 18 +- test/CodeGenCXX/microsoft-abi-structors.cpp | 38 ++- .../microsoft-abi-thread-safe-statics.cpp | 14 +- test/CodeGenCXX/microsoft-abi-try-throw.cpp | 14 +- test/CodeGenCXX/microsoft-abi-vftables.cpp | 6 +- ...microsoft-abi-virtual-inheritance-vtordisps.cpp | 6 +- .../microsoft-abi-virtual-inheritance.cpp | 30 +- .../microsoft-abi-vtables-single-inheritance.cpp | 15 + ...t-abi-vtables-virtual-inheritance-vtordisps.cpp | 4 +- test/CodeGenCXX/microsoft-compatibility.cpp | 10 + test/CodeGenCXX/ms-inline-asm-fields.cpp | 31 ++ test/CodeGenCXX/ms-integer-static-data-members.cpp | 4 +- test/CodeGenCXX/ms-property.cpp | 113 ++++++++ test/CodeGenCXX/new-alias.cpp | 2 +- test/CodeGenCXX/new.cpp | 11 +- test/CodeGenCXX/observe-noexcept.cpp | 47 ++++ test/CodeGenCXX/partial-destruction.cpp | 31 ++ test/CodeGenCXX/partial-init.cpp | 27 ++ test/CodeGenCXX/pass-object-size.cpp | 27 ++ test/CodeGenCXX/pointers-to-data-members.cpp | 38 --- test/CodeGenCXX/pragma-loop-safety.cpp | 33 ++- test/CodeGenCXX/pragma-loop.cpp | 60 ++-- test/CodeGenCXX/pragma-unroll.cpp | 23 +- test/CodeGenCXX/redefine_extname.cpp | 6 + test/CodeGenCXX/sanitize-dtor-bit-field.cpp | 84 ++++++ test/CodeGenCXX/sanitize-dtor-callback.cpp | 67 ++++- test/CodeGenCXX/sanitize-dtor-derived-class.cpp | 71 +++++ test/CodeGenCXX/sanitize-dtor-fn-attribute.cpp | 43 +++ .../sanitize-dtor-nontrivial-virtual-base.cpp | 82 ++++++ test/CodeGenCXX/sanitize-dtor-repress-aliasing.cpp | 30 ++ test/CodeGenCXX/sanitize-dtor-tail-call.cpp | 23 ++ test/CodeGenCXX/sanitize-dtor-trivial.cpp | 15 + test/CodeGenCXX/sanitize-dtor-vtable.cpp | 47 ++++ test/CodeGenCXX/sanitize-no-dtor-callback.cpp | 23 ++ test/CodeGenCXX/scoped-enums-debug-info.cpp | 2 +- test/CodeGenCXX/sel-address.mm | 14 - test/CodeGenCXX/static-init-wasm.cpp | 54 ++++ test/CodeGenCXX/static-init.cpp | 23 +- test/CodeGenCXX/strict-vtable-pointers.cpp | 219 ++++++++++++++ test/CodeGenCXX/thunks.cpp | 30 +- test/CodeGenCXX/tls-init-funcs.cpp | 10 +- test/CodeGenCXX/typeid-cxx11.cpp | 4 +- test/CodeGenCXX/uncopyable-args.cpp | 6 +- test/CodeGenCXX/vararg-non-pod-ms-compat.cpp | 2 +- test/CodeGenCXX/virtual-base-ctor.cpp | 2 +- test/CodeGenCXX/virtual-destructor-calls.cpp | 2 +- test/CodeGenCXX/visibility.cpp | 3 + test/CodeGenCXX/vtable-assume-load.cpp | 313 +++++++++++++++++++++ test/CodeGenCXX/vtable-available-externally.cpp | 241 +++++++++++++++- test/CodeGenCXX/vtable-holder-self-reference.cpp | 2 +- test/CodeGenCXX/vtable-key-function-ios.cpp | 3 + test/CodeGenCXX/vtable-key-function-win-comdat.cpp | 25 ++ test/CodeGenCXX/vtable-linkage.cpp | 11 +- test/CodeGenCXX/warn-padded-packed.cpp | 2 +- test/CodeGenCXX/wasm-args-returns.cpp | 100 +++++++ test/CodeGenCXX/x86_64-arguments.cpp | 9 + 201 files changed, 3895 insertions(+), 699 deletions(-) create mode 100644 test/CodeGenCXX/PR24289.cpp create mode 100644 test/CodeGenCXX/alignment.cpp create mode 100644 test/CodeGenCXX/armv7k.cpp create mode 100644 test/CodeGenCXX/attr-disable-tail-calls.cpp create mode 100644 test/CodeGenCXX/attr-notail.cpp create mode 100644 test/CodeGenCXX/attribute_internal_linkage.cpp create mode 100644 test/CodeGenCXX/cast-to-ref-bool.cpp create mode 100644 test/CodeGenCXX/cfi-blacklist.cpp create mode 100644 test/CodeGenCXX/cfi-cross-dso.cpp create mode 100644 test/CodeGenCXX/cfi-icall.cpp create mode 100644 test/CodeGenCXX/debug-info-anon-namespace.cpp create mode 100644 test/CodeGenCXX/debug-info-codeview-display-name.cpp create mode 100644 test/CodeGenCXX/debug-info-explicit-cast.cpp delete mode 100644 test/CodeGenCXX/default-destructor-synthesis.cpp create mode 100644 test/CodeGenCXX/exceptions-cxx-new.cpp create mode 100644 test/CodeGenCXX/funcattrs-global-ctor-dtor.cpp create mode 100644 test/CodeGenCXX/invariant.group-for-vptrs.cpp create mode 100644 test/CodeGenCXX/main-norecurse.cpp delete mode 100644 test/CodeGenCXX/member-initializers.cpp create mode 100644 test/CodeGenCXX/ms-inline-asm-fields.cpp create mode 100644 test/CodeGenCXX/ms-property.cpp create mode 100644 test/CodeGenCXX/observe-noexcept.cpp create mode 100644 test/CodeGenCXX/partial-init.cpp create mode 100644 test/CodeGenCXX/pass-object-size.cpp create mode 100644 test/CodeGenCXX/sanitize-dtor-bit-field.cpp create mode 100644 test/CodeGenCXX/sanitize-dtor-derived-class.cpp create mode 100644 test/CodeGenCXX/sanitize-dtor-fn-attribute.cpp create mode 100644 test/CodeGenCXX/sanitize-dtor-nontrivial-virtual-base.cpp create mode 100644 test/CodeGenCXX/sanitize-dtor-repress-aliasing.cpp create mode 100644 test/CodeGenCXX/sanitize-dtor-tail-call.cpp create mode 100644 test/CodeGenCXX/sanitize-dtor-trivial.cpp create mode 100644 test/CodeGenCXX/sanitize-dtor-vtable.cpp create mode 100644 test/CodeGenCXX/sanitize-no-dtor-callback.cpp delete mode 100644 test/CodeGenCXX/sel-address.mm create mode 100644 test/CodeGenCXX/static-init-wasm.cpp create mode 100644 test/CodeGenCXX/strict-vtable-pointers.cpp create mode 100644 test/CodeGenCXX/vtable-assume-load.cpp create mode 100644 test/CodeGenCXX/vtable-key-function-win-comdat.cpp create mode 100644 test/CodeGenCXX/wasm-args-returns.cpp (limited to 'test/CodeGenCXX') diff --git a/test/CodeGenCXX/2006-11-20-GlobalSymbols.cpp b/test/CodeGenCXX/2006-11-20-GlobalSymbols.cpp index 34594f43a0b9..74a7fb642208 100644 --- a/test/CodeGenCXX/2006-11-20-GlobalSymbols.cpp +++ b/test/CodeGenCXX/2006-11-20-GlobalSymbols.cpp @@ -1,7 +1,7 @@ // PR1013 // Check to make sure debug symbols use the correct name for globals and // functions. Will not assemble if it fails to. -// RUN: %clang_cc1 -emit-llvm -g -o - %s | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited -o - %s | FileCheck %s // CHECK: f\01oo" int foo __asm__("f\001oo"); diff --git a/test/CodeGenCXX/2007-01-02-UnboundedArray.cpp b/test/CodeGenCXX/2007-01-02-UnboundedArray.cpp index 0cd83fa7ed4c..c76b7ef2163c 100644 --- a/test/CodeGenCXX/2007-01-02-UnboundedArray.cpp +++ b/test/CodeGenCXX/2007-01-02-UnboundedArray.cpp @@ -1,6 +1,6 @@ // Make sure unbounded arrays compile with debug information. // -// RUN: %clang_cc1 -emit-llvm -g %s -o - +// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited %s -o - // PR1068 diff --git a/test/CodeGenCXX/2009-03-17-dbg.cpp b/test/CodeGenCXX/2009-03-17-dbg.cpp index e2e6c5a2dd29..22d905910ba3 100644 --- a/test/CodeGenCXX/2009-03-17-dbg.cpp +++ b/test/CodeGenCXX/2009-03-17-dbg.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm %s -o /dev/null -g +// RUN: %clang_cc1 -emit-llvm %s -o /dev/null -debug-info-kind=limited template inline void f(const T1&,const T2&) { } diff --git a/test/CodeGenCXX/2009-04-23-bool2.cpp b/test/CodeGenCXX/2009-04-23-bool2.cpp index cf81cc42eae4..33c2c02d736c 100644 --- a/test/CodeGenCXX/2009-04-23-bool2.cpp +++ b/test/CodeGenCXX/2009-04-23-bool2.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm %s -o /dev/null +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm %s -o /dev/null // g++.old-deja/g++.jason/bool2.C from gcc testsuite. // Crashed before 67975 went in. struct F { diff --git a/test/CodeGenCXX/2009-06-16-DebugInfoCrash.cpp b/test/CodeGenCXX/2009-06-16-DebugInfoCrash.cpp index 500520b567f5..870e15ca5f2a 100644 --- a/test/CodeGenCXX/2009-06-16-DebugInfoCrash.cpp +++ b/test/CodeGenCXX/2009-06-16-DebugInfoCrash.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm %s -o /dev/null -g +// RUN: %clang_cc1 -emit-llvm %s -o /dev/null -debug-info-kind=limited // This crashes if we try to emit debug info for TEMPLATE_DECL members. template class K2PtrVectorBase {}; template class K2Vector {}; diff --git a/test/CodeGenCXX/2010-03-09-AnonAggregate.cpp b/test/CodeGenCXX/2010-03-09-AnonAggregate.cpp index 99883d82636e..056b500ce40b 100644 --- a/test/CodeGenCXX/2010-03-09-AnonAggregate.cpp +++ b/test/CodeGenCXX/2010-03-09-AnonAggregate.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -g -S -o %t %s +// RUN: %clang_cc1 -debug-info-kind=limited -S -o %t %s // PR: 6554 // More then one anonymous aggregates on one line creates chaos when MDNode uniquness is // combined with RAUW operation. diff --git a/test/CodeGenCXX/2010-05-10-Var-DbgInfo.cpp b/test/CodeGenCXX/2010-05-10-Var-DbgInfo.cpp index 802f4c3d67f7..2b39e7d78716 100644 --- a/test/CodeGenCXX/2010-05-10-Var-DbgInfo.cpp +++ b/test/CodeGenCXX/2010-05-10-Var-DbgInfo.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -g %s -o /dev/null +// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited %s -o /dev/null // PR 7104 struct A { diff --git a/test/CodeGenCXX/2010-05-12-PtrToMember-Dbg.cpp b/test/CodeGenCXX/2010-05-12-PtrToMember-Dbg.cpp index 048811f6e641..355c3c98dd66 100644 --- a/test/CodeGenCXX/2010-05-12-PtrToMember-Dbg.cpp +++ b/test/CodeGenCXX/2010-05-12-PtrToMember-Dbg.cpp @@ -1,5 +1,5 @@ -//RUN: %clang_cc1 -emit-llvm -g -o - %s | FileCheck %s -//CHECK: DW_TAG_auto_variable +//RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited -o - %s | FileCheck %s +//CHECK: DILocalVariable( class Foo { public: diff --git a/test/CodeGenCXX/2010-06-21-LocalVarDbg.cpp b/test/CodeGenCXX/2010-06-21-LocalVarDbg.cpp index 2542378e909a..c0c8bf66501b 100644 --- a/test/CodeGenCXX/2010-06-21-LocalVarDbg.cpp +++ b/test/CodeGenCXX/2010-06-21-LocalVarDbg.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -g -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -debug-info-kind=limited -emit-llvm %s -o - | FileCheck %s // Do not use function name to create named metadata used to hold // local variable info. For example. llvm.dbg.lv.~A is an invalid name. diff --git a/test/CodeGenCXX/2010-06-22-BitfieldInit.cpp b/test/CodeGenCXX/2010-06-22-BitfieldInit.cpp index f82e527844fd..ae02cd9f871a 100644 --- a/test/CodeGenCXX/2010-06-22-BitfieldInit.cpp +++ b/test/CodeGenCXX/2010-06-22-BitfieldInit.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -g %s -o - +// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited %s -o - struct TEST2 { int subid:32; diff --git a/test/CodeGenCXX/2010-06-22-ZeroBitfield.cpp b/test/CodeGenCXX/2010-06-22-ZeroBitfield.cpp index c2f37f740549..0f600e77b6ea 100644 --- a/test/CodeGenCXX/2010-06-22-ZeroBitfield.cpp +++ b/test/CodeGenCXX/2010-06-22-ZeroBitfield.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -g %s -o - +// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited %s -o - struct s8_0 { unsigned : 0; }; struct s8_1 { double x; }; struct s8 { s8_0 a; s8_1 b; }; diff --git a/test/CodeGenCXX/2010-07-23-DeclLoc.cpp b/test/CodeGenCXX/2010-07-23-DeclLoc.cpp index 3bd66da62afe..a88d605f565e 100644 --- a/test/CodeGenCXX/2010-07-23-DeclLoc.cpp +++ b/test/CodeGenCXX/2010-07-23-DeclLoc.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -g %s -o - | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited %s -o - | FileCheck %s // Require the template function declaration refer to the correct filename. // First, locate the function decl in metadata, and pluck out the file handle: // CHECK: !DISubprogram(name: "extract_dwarf_data_from_header diff --git a/test/CodeGenCXX/PR20038.cpp b/test/CodeGenCXX/PR20038.cpp index 0a10244db0e7..2d7043dcda33 100644 --- a/test/CodeGenCXX/PR20038.cpp +++ b/test/CodeGenCXX/PR20038.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple %itanium_abi_triple -g -mllvm -no-discriminators -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple %itanium_abi_triple -debug-info-kind=limited -mllvm -no-discriminators -emit-llvm %s -o - | FileCheck %s struct C { ~C(); @@ -6,8 +6,8 @@ struct C { extern bool b; // CHECK: call {{.*}}, !dbg [[DTOR_CALL1_LOC:![0-9]*]] // CHECK: call {{.*}}, !dbg [[DTOR_CALL2_LOC:![0-9]*]] -// CHECK: [[FUN1:.*]] = !DISubprogram(name: "fun1",{{.*}} isDefinition: true -// CHECK: [[FUN2:.*]] = !DISubprogram(name: "fun2",{{.*}} isDefinition: true +// CHECK: [[FUN1:.*]] = distinct !DISubprogram(name: "fun1",{{.*}} isDefinition: true +// CHECK: [[FUN2:.*]] = distinct !DISubprogram(name: "fun2",{{.*}} isDefinition: true // CHECK: [[DTOR_CALL1_LOC]] = !DILocation(line: [[@LINE+1]], scope: [[FUN1]]) void fun1() { b && (C(), 1); } // CHECK: [[DTOR_CALL2_LOC]] = !DILocation(line: [[@LINE+1]], scope: [[FUN2]]) diff --git a/test/CodeGenCXX/PR24289.cpp b/test/CodeGenCXX/PR24289.cpp new file mode 100644 index 000000000000..364b5b23385d --- /dev/null +++ b/test/CodeGenCXX/PR24289.cpp @@ -0,0 +1,82 @@ +// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-pc-linux-gnu -std=c++11 | FileCheck %s + +namespace std { +template +struct initializer_list { + const T *Begin; + __SIZE_TYPE__ Size; + + constexpr initializer_list(const T *B, __SIZE_TYPE__ S) + : Begin(B), Size(S) {} +}; +} + +void f() { + static std::initializer_list> a{ + {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}}; + static std::initializer_list> b{ + {0}, {0}, {0}, {0}}; + static std::initializer_list> c{ + {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}}; + static std::initializer_list> d{ + {0}, {0}, {0}, {0}, {0}}; + static std::initializer_list> e{ + {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}}; +} + +// CHECK-DAG: @_ZZ1fvE1a = internal global %{{.*}} { %{{.*}}* getelementptr inbounds ([14 x %{{.*}}], [14 x %{{.*}}] +// CHECK-DAG: * @_ZGRZ1fvE1a_, i32 0, i32 0), i64 14 } +// CHECK-DAG: @_ZGRZ1fvE1a0_ = internal constant [1 x i32] zeroinitializer +// CHECK-DAG: @_ZGRZ1fvE1a1_ = internal constant [1 x i32] zeroinitializer +// CHECK-DAG: @_ZGRZ1fvE1a2_ = internal constant [1 x i32] zeroinitializer +// CHECK-DAG: @_ZGRZ1fvE1a3_ = internal constant [1 x i32] zeroinitializer +// CHECK-DAG: @_ZGRZ1fvE1a4_ = internal constant [1 x i32] zeroinitializer +// CHECK-DAG: @_ZGRZ1fvE1a5_ = internal constant [1 x i32] zeroinitializer +// CHECK-DAG: @_ZGRZ1fvE1a6_ = internal constant [1 x i32] zeroinitializer +// CHECK-DAG: @_ZGRZ1fvE1a7_ = internal constant [1 x i32] zeroinitializer +// CHECK-DAG: @_ZGRZ1fvE1a8_ = internal constant [1 x i32] zeroinitializer +// CHECK-DAG: @_ZGRZ1fvE1a9_ = internal constant [1 x i32] zeroinitializer +// CHECK-DAG: @_ZGRZ1fvE1aA_ = internal constant [1 x i32] zeroinitializer +// CHECK-DAG: @_ZGRZ1fvE1aB_ = internal constant [1 x i32] zeroinitializer +// CHECK-DAG: @_ZGRZ1fvE1aC_ = internal constant [1 x i32] zeroinitializer +// CHECK-DAG: @_ZGRZ1fvE1aD_ = internal constant [1 x i32] zeroinitializer +// CHECK-DAG: @_ZGRZ1fvE1a_ = internal constant [14 x %{{.*}}] [%{{.*}} { i32* getelementptr inbounds ([1 x i32], [1 x i32]* @_ZGRZ1fvE1a0_, i32 0, i32 0), i64 1 }, %{{.*}} { i32* getelementptr inbounds ([1 x i32], [1 x i32]* @_ZGRZ1fvE1a1_, i32 0, i32 0), i64 1 }, %{{.*}} { i32* getelementptr inbounds ([1 x i32], [1 x i32]* @_ZGRZ1fvE1a2_, i32 0, i32 0), i64 1 }, %{{.*}} { i32* getelementptr inbounds ([1 x i32], [1 x i32]* @_ZGRZ1fvE1a3_, i32 0, i32 0), i64 1 }, %{{.*}} { i32* getelementptr inbounds ([1 x i32], [1 x i32]* @_ZGRZ1fvE1a4_, i32 0, i32 0), i64 1 }, %{{.*}} { i32* getelementptr inbounds ([1 x i32], [1 x i32]* @_ZGRZ1fvE1a5_, i32 0, i32 0), i64 1 }, %{{.*}} { i32* getelementptr inbounds ([1 x i32], [1 x i32]* @_ZGRZ1fvE1a6_, i32 0, i32 0), i64 1 }, %{{.*}} { i32* getelementptr inbounds ([1 x i32], [1 x i32]* @_ZGRZ1fvE1a7_, i32 0, i32 0), i64 1 }, %{{.*}} { i32* getelementptr inbounds ([1 x i32], [1 x i32]* @_ZGRZ1fvE1a8_, i32 0, i32 0), i64 1 }, %{{.*}} { i32* getelementptr inbounds ([1 x i32], [1 x i32]* @_ZGRZ1fvE1a9_, i32 0, i32 0), i64 1 }, %{{.*}} { i32* getelementptr inbounds ([1 x i32], [1 x i32]* @_ZGRZ1fvE1aA_, i32 0, i32 0), i64 1 }, %{{.*}} { i32* getelementptr inbounds ([1 x i32], [1 x i32]* @_ZGRZ1fvE1aB_, i32 0, i32 0), i64 1 }, %{{.*}} { i32* getelementptr inbounds ([1 x i32], [1 x i32]* @_ZGRZ1fvE1aC_, i32 0, i32 0), i64 1 }, %{{.*}} { i32* getelementptr inbounds ([1 x i32], [1 x i32]* @_ZGRZ1fvE1aD_, i32 0, i32 0), i64 1 }] +// CHECK-DAG: @_ZZ1fvE1b = internal global %{{.*}} { %{{.*}}* getelementptr inbounds ([4 x %{{.*}}], [4 x %{{.*}}]* +// CHECK-DAG: @_ZGRZ1fvE1b_, i32 0, i32 0), i64 4 } +// CHECK-DAG: @_ZGRZ1fvE1b0_ = internal constant [1 x i32] zeroinitializer +// CHECK-DAG: @_ZGRZ1fvE1b1_ = internal constant [1 x i32] zeroinitializer +// CHECK-DAG: @_ZGRZ1fvE1b2_ = internal constant [1 x i32] zeroinitializer +// CHECK-DAG: @_ZGRZ1fvE1b3_ = internal constant [1 x i32] zeroinitializer +// CHECK-DAG: @_ZGRZ1fvE1b_ = internal constant [4 x %{{.*}}] [%{{.*}} { i32* getelementptr inbounds ([1 x i32], [1 x i32]* @_ZGRZ1fvE1b0_, i32 0, i32 0), i64 1 }, %{{.*}} { i32* getelementptr inbounds ([1 x i32], [1 x i32]* @_ZGRZ1fvE1b1_, i32 0, i32 0), i64 1 }, %{{.*}} { i32* getelementptr inbounds ([1 x i32], [1 x i32]* @_ZGRZ1fvE1b2_, i32 0, i32 0), i64 1 }, %{{.*}} { i32* getelementptr inbounds ([1 x i32], [1 x i32]* @_ZGRZ1fvE1b3_, i32 0, i32 0), i64 1 }] +// CHECK-DAG: @_ZZ1fvE1c = internal global %{{.*}} { %{{.*}}* getelementptr inbounds ([9 x %{{.*}}], [9 x %{{.*}}]* +// CHECK-DAG: @_ZGRZ1fvE1c_, i32 0, i32 0), i64 9 } +// CHECK-DAG: @_ZGRZ1fvE1c0_ = internal constant [1 x i32] zeroinitializer +// CHECK-DAG: @_ZGRZ1fvE1c1_ = internal constant [1 x i32] zeroinitializer +// CHECK-DAG: @_ZGRZ1fvE1c2_ = internal constant [1 x i32] zeroinitializer +// CHECK-DAG: @_ZGRZ1fvE1c3_ = internal constant [1 x i32] zeroinitializer +// CHECK-DAG: @_ZGRZ1fvE1c4_ = internal constant [1 x i32] zeroinitializer +// CHECK-DAG: @_ZGRZ1fvE1c5_ = internal constant [1 x i32] zeroinitializer +// CHECK-DAG: @_ZGRZ1fvE1c6_ = internal constant [1 x i32] zeroinitializer +// CHECK-DAG: @_ZGRZ1fvE1c7_ = internal constant [1 x i32] zeroinitializer +// CHECK-DAG: @_ZGRZ1fvE1c8_ = internal constant [1 x i32] zeroinitializer +// CHECK-DAG: @_ZGRZ1fvE1c_ = internal constant [9 x %{{.*}}] [%{{.*}} { i32* getelementptr inbounds ([1 x i32], [1 x i32]* @_ZGRZ1fvE1c0_, i32 0, i32 0), i64 1 }, %{{.*}} { i32* getelementptr inbounds ([1 x i32], [1 x i32]* @_ZGRZ1fvE1c1_, i32 0, i32 0), i64 1 }, %{{.*}} { i32* getelementptr inbounds ([1 x i32], [1 x i32]* @_ZGRZ1fvE1c2_, i32 0, i32 0), i64 1 }, %{{.*}} { i32* getelementptr inbounds ([1 x i32], [1 x i32]* @_ZGRZ1fvE1c3_, i32 0, i32 0), i64 1 }, %{{.*}} { i32* getelementptr inbounds ([1 x i32], [1 x i32]* @_ZGRZ1fvE1c4_, i32 0, i32 0), i64 1 }, %{{.*}} { i32* getelementptr inbounds ([1 x i32], [1 x i32]* @_ZGRZ1fvE1c5_, i32 0, i32 0), i64 1 }, %{{.*}} { i32* getelementptr inbounds ([1 x i32], [1 x i32]* @_ZGRZ1fvE1c6_, i32 0, i32 0), i64 1 }, %{{.*}} { i32* getelementptr inbounds ([1 x i32], [1 x i32]* @_ZGRZ1fvE1c7_, i32 0, i32 0), i64 1 }, %{{.*}} { i32* getelementptr inbounds ([1 x i32], [1 x i32]* @_ZGRZ1fvE1c8_, i32 0, i32 0), i64 1 }] +// CHECK-DAG: @_ZZ1fvE1d = internal global %{{.*}} { %{{.*}}* getelementptr inbounds ([5 x %{{.*}}], [5 x %{{.*}}]* @_ZGRZ1fvE1d_, i32 0, i32 0), i64 5 } +// CHECK-DAG: @_ZGRZ1fvE1d0_ = internal constant [1 x i32] zeroinitializer +// CHECK-DAG: @_ZGRZ1fvE1d1_ = internal constant [1 x i32] zeroinitializer +// CHECK-DAG: @_ZGRZ1fvE1d2_ = internal constant [1 x i32] zeroinitializer +// CHECK-DAG: @_ZGRZ1fvE1d3_ = internal constant [1 x i32] zeroinitializer +// CHECK-DAG: @_ZGRZ1fvE1d4_ = internal constant [1 x i32] zeroinitializer +// CHECK-DAG: @_ZGRZ1fvE1d_ = internal constant [5 x %{{.*}}] [%{{.*}} { i32* getelementptr inbounds ([1 x i32], [1 x i32]* @_ZGRZ1fvE1d0_, i32 0, i32 0), i64 1 }, %{{.*}} { i32* getelementptr inbounds ([1 x i32], [1 x i32]* @_ZGRZ1fvE1d1_, i32 0, i32 0), i64 1 }, %{{.*}} { i32* getelementptr inbounds ([1 x i32], [1 x i32]* @_ZGRZ1fvE1d2_, i32 0, i32 0), i64 1 }, %{{.*}} { i32* getelementptr inbounds ([1 x i32], [1 x i32]* @_ZGRZ1fvE1d3_, i32 0, i32 0), i64 1 }, %{{.*}} { i32* getelementptr inbounds ([1 x i32], [1 x i32]* @_ZGRZ1fvE1d4_, i32 0, i32 0), i64 1 }] +// CHECK-DAG: @_ZZ1fvE1e = internal global %{{.*}} { %{{.*}}* getelementptr inbounds ([11 x %{{.*}}], [11 x %{{.*}}]* @_ZGRZ1fvE1e_, i32 0, i32 0), i64 11 } +// CHECK-DAG: @_ZGRZ1fvE1e0_ = internal constant [1 x i32] zeroinitializer +// CHECK-DAG: @_ZGRZ1fvE1e1_ = internal constant [1 x i32] zeroinitializer +// CHECK-DAG: @_ZGRZ1fvE1e2_ = internal constant [1 x i32] zeroinitializer +// CHECK-DAG: @_ZGRZ1fvE1e3_ = internal constant [1 x i32] zeroinitializer +// CHECK-DAG: @_ZGRZ1fvE1e4_ = internal constant [1 x i32] zeroinitializer +// CHECK-DAG: @_ZGRZ1fvE1e5_ = internal constant [1 x i32] zeroinitializer +// CHECK-DAG: @_ZGRZ1fvE1e6_ = internal constant [1 x i32] zeroinitializer +// CHECK-DAG: @_ZGRZ1fvE1e7_ = internal constant [1 x i32] zeroinitializer +// CHECK-DAG: @_ZGRZ1fvE1e8_ = internal constant [1 x i32] zeroinitializer +// CHECK-DAG: @_ZGRZ1fvE1e9_ = internal constant [1 x i32] zeroinitializer +// CHECK-DAG: @_ZGRZ1fvE1eA_ = internal constant [1 x i32] zeroinitializer +// CHECK-DAG: @_ZGRZ1fvE1e_ = internal constant [11 x %{{.*}}] [%{{.*}} { i32* getelementptr inbounds ([1 x i32], [1 x i32]* @_ZGRZ1fvE1e0_, i32 0, i32 0), i64 1 }, %{{.*}} { i32* getelementptr inbounds ([1 x i32], [1 x i32]* @_ZGRZ1fvE1e1_, i32 0, i32 0), i64 1 }, %{{.*}} { i32* getelementptr inbounds ([1 x i32], [1 x i32]* @_ZGRZ1fvE1e2_, i32 0, i32 0), i64 1 }, %{{.*}} { i32* getelementptr inbounds ([1 x i32], [1 x i32]* @_ZGRZ1fvE1e3_, i32 0, i32 0), i64 1 }, %{{.*}} { i32* getelementptr inbounds ([1 x i32], [1 x i32]* @_ZGRZ1fvE1e4_, i32 0, i32 0), i64 1 }, %{{.*}} { i32* getelementptr inbounds ([1 x i32], [1 x i32]* @_ZGRZ1fvE1e5_, i32 0, i32 0), i64 1 }, %{{.*}} { i32* getelementptr inbounds ([1 x i32], [1 x i32]* @_ZGRZ1fvE1e6_, i32 0, i32 0), i64 1 }, %{{.*}} { i32* getelementptr inbounds ([1 x i32], [1 x i32]* @_ZGRZ1fvE1e7_, i32 0, i32 0), i64 1 }, %{{.*}} { i32* getelementptr inbounds ([1 x i32], [1 x i32]* @_ZGRZ1fvE1e8_, i32 0, i32 0), i64 1 }, %{{.*}} { i32* getelementptr inbounds ([1 x i32], [1 x i32]* @_ZGRZ1fvE1e9_, i32 0, i32 0), i64 1 }, %{{.*}} { i32* getelementptr inbounds ([1 x i32], [1 x i32]* @_ZGRZ1fvE1eA_, i32 0, i32 0), i64 1 }] diff --git a/test/CodeGenCXX/alignment.cpp b/test/CodeGenCXX/alignment.cpp new file mode 100644 index 000000000000..2a1fe71f961b --- /dev/null +++ b/test/CodeGenCXX/alignment.cpp @@ -0,0 +1,299 @@ +// RUN: %clang_cc1 %s -emit-llvm -o - -triple=x86_64-apple-darwin10 | FileCheck %s + +extern int int_source(); +extern void int_sink(int x); + +namespace test0 { + struct A { + int aField; + int bField; + }; + + struct B { + int onebit : 2; + int twobit : 6; + int intField; + }; + + struct __attribute__((packed, aligned(2))) C : A, B { + }; + + // These accesses should have alignment 4 because they're at offset 0 + // in a reference with an assumed alignment of 4. + // CHECK-LABEL: @_ZN5test01aERNS_1BE + void a(B &b) { + // CHECK: [[CALL:%.*]] = call i32 @_Z10int_sourcev() + // CHECK: [[B_P:%.*]] = load [[B:%.*]]*, [[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 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 4 + b.onebit = int_source(); + + // CHECK: [[B_P:%.*]] = load [[B]]*, [[B]]** + // CHECK: [[FIELD_P:%.*]] = bitcast [[B]]* [[B_P]] to i8* + // CHECK: [[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 + // CHECK: call void @_Z8int_sinki(i32 [[T2]]) + int_sink(b.onebit); + } + + // These accesses should have alignment 2 because they're at offset 8 + // in a reference/pointer with an assumed alignment of 2. + // CHECK-LABEL: @_ZN5test01bERNS_1CE + void b(C &c) { + // CHECK: [[CALL:%.*]] = call i32 @_Z10int_sourcev() + // CHECK: [[C_P:%.*]] = load [[C:%.*]]*, [[C]]** + // 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: [[TRUNC:%.*]] = trunc i32 [[CALL]] to i8 + // CHECK: [[OLD_VALUE:%.*]] = load i8, i8* [[FIELD_P]], align 2 + // 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 + c.onebit = int_source(); + + // CHECK: [[C_P:%.*]] = load [[C]]*, [[C]]** + // 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: [[T0:%.*]] = shl i8 [[VALUE]], 6 + // CHECK: [[T1:%.*]] = ashr i8 [[T0]], 6 + // CHECK: [[T2:%.*]] = sext i8 [[T1]] to i32 + // CHECK: call void @_Z8int_sinki(i32 [[T2]]) + int_sink(c.onebit); + } + + // CHECK-LABEL: @_ZN5test01cEPNS_1CE + void c(C *c) { + // CHECK: [[CALL:%.*]] = call i32 @_Z10int_sourcev() + // CHECK: [[C_P:%.*]] = load [[C]]*, [[C]]** + // 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: [[TRUNC:%.*]] = trunc i32 [[CALL]] to i8 + // CHECK: [[OLD_VALUE:%.*]] = load i8, i8* [[FIELD_P]], align 2 + // 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 + c->onebit = int_source(); + + // CHECK: [[C_P:%.*]] = load [[C:%.*]]*, [[C]]** + // 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: [[T0:%.*]] = shl i8 [[VALUE]], 6 + // CHECK: [[T1:%.*]] = ashr i8 [[T0]], 6 + // CHECK: [[T2:%.*]] = sext i8 [[T1]] to i32 + // CHECK: call void @_Z8int_sinki(i32 [[T2]]) + int_sink(c->onebit); + } + + // These accesses should have alignment 2 because they're at offset 8 + // in an alignment-2 variable. + // CHECK-LABEL: @_ZN5test01dEv + void d() { + // CHECK: [[C_P:%.*]] = alloca [[C:%.*]], align 2 + C c; + + // CHECK: [[CALL:%.*]] = call i32 @_Z10int_sourcev() + // 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: [[TRUNC:%.*]] = trunc i32 [[CALL]] to i8 + // CHECK: [[OLD_VALUE:%.*]] = load i8, i8* [[FIELD_P]], align 2 + // 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 + 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: [[T0:%.*]] = shl i8 [[VALUE]], 6 + // CHECK: [[T1:%.*]] = ashr i8 [[T0]], 6 + // CHECK: [[T2:%.*]] = sext i8 [[T1]] to i32 + // CHECK: call void @_Z8int_sinki(i32 [[T2]]) + int_sink(c.onebit); + } + + // These accesses should have alignment 8 because they're at offset 8 + // in an alignment-16 variable. + // CHECK-LABEL: @_ZN5test01eEv + void e() { + // CHECK: [[C_P:%.*]] = alloca [[C:%.*]], align 16 + __attribute__((aligned(16))) C c; + + // CHECK: [[CALL:%.*]] = call i32 @_Z10int_sourcev() + // 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: [[TRUNC:%.*]] = trunc i32 [[CALL]] to i8 + // CHECK: [[OLD_VALUE:%.*]] = load i8, i8* [[FIELD_P]], align 8 + // 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 8 + 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 8 + // CHECK: [[T0:%.*]] = shl i8 [[VALUE]], 6 + // CHECK: [[T1:%.*]] = ashr i8 [[T0]], 6 + // CHECK: [[T2:%.*]] = sext i8 [[T1]] to i32 + // CHECK: call void @_Z8int_sinki(i32 [[T2]]) + int_sink(c.onebit); + } +} + +namespace test1 { + struct Array { + int elts[4]; + }; + + struct A { + __attribute__((aligned(16))) Array aArray; + }; + + struct B : virtual A { + void *bPointer; // puts bArray at offset 16 + Array bArray; + }; + + struct C : virtual A { // must be viable as primary base + // Non-empty, nv-size not a multiple of 16. + void *cPointer1; + void *cPointer2; + }; + + // Proof of concept that the non-virtual components of B do not have + // to be 16-byte-aligned. + struct D : C, B {}; + + // For the following tests, we want to assign into a variable whose + // alignment is high enough that it will absolutely not be the + // constraint on the memcpy alignment. + typedef __attribute__((aligned(64))) Array AlignedArray; + + // CHECK-LABEL: @_ZN5test11aERNS_1AE + void a(A &a) { + // CHECK: [[RESULT:%.*]] = alloca [[ARRAY:%.*]], align 64 + // CHECK: [[A_P:%.*]] = load [[A:%.*]]*, [[A]]** + // 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) + AlignedArray result = a.aArray; + } + + // CHECK-LABEL: @_ZN5test11bERNS_1BE + void b(B &b) { + // CHECK: [[RESULT:%.*]] = alloca [[ARRAY]], align 64 + // CHECK: [[B_P:%.*]] = load [[B:%.*]]*, [[B]]** + // CHECK: [[VPTR_P:%.*]] = bitcast [[B]]* [[B_P]] to i8** + // CHECK: [[VPTR:%.*]] = load i8*, i8** [[VPTR_P]], align 8 + // CHECK: [[T0:%.*]] = getelementptr i8, i8* [[VPTR]], i64 -24 + // CHECK: [[OFFSET_P:%.*]] = bitcast i8* [[T0]] to i64* + // CHECK: [[OFFSET:%.*]] = load i64, i64* [[OFFSET_P]], align 8 + // CHECK: [[T0:%.*]] = bitcast [[B]]* [[B_P]] to i8* + // CHECK: [[T1:%.*]] = getelementptr inbounds i8, i8* [[T0]], i64 [[OFFSET]] + // CHECK: [[A_P:%.*]] = bitcast i8* [[T1]] to [[A]]* + // 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) + AlignedArray result = b.aArray; + } + + // CHECK-LABEL: @_ZN5test11cERNS_1BE + void c(B &b) { + // CHECK: [[RESULT:%.*]] = alloca [[ARRAY]], align 64 + // CHECK: [[B_P:%.*]] = load [[B]]*, [[B]]** + // 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) + AlignedArray result = b.bArray; + } + + // CHECK-LABEL: @_ZN5test11dEPNS_1BE + void d(B *b) { + // CHECK: [[RESULT:%.*]] = alloca [[ARRAY]], align 64 + // CHECK: [[B_P:%.*]] = load [[B]]*, [[B]]** + // 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) + AlignedArray result = b->bArray; + } + + // CHECK-LABEL: @_ZN5test11eEv + void e() { + // CHECK: [[B_P:%.*]] = alloca [[B]], align 16 + // CHECK: [[RESULT:%.*]] = alloca [[ARRAY]], align 64 + // 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) + B b; + AlignedArray result = b.bArray; + } + + // CHECK-LABEL: @_ZN5test11fEv + void f() { + // TODO: we should devirtualize this derived-to-base conversion. + // CHECK: [[D_P:%.*]] = alloca [[D:%.*]], align 16 + // CHECK: [[RESULT:%.*]] = alloca [[ARRAY]], align 64 + // CHECK: [[VPTR_P:%.*]] = bitcast [[D]]* [[D_P]] to i8** + // CHECK: [[VPTR:%.*]] = load i8*, i8** [[VPTR_P]], align 16 + // CHECK: [[T0:%.*]] = getelementptr i8, i8* [[VPTR]], i64 -24 + // CHECK: [[OFFSET_P:%.*]] = bitcast i8* [[T0]] to i64* + // CHECK: [[OFFSET:%.*]] = load i64, i64* [[OFFSET_P]], align 8 + // CHECK: [[T0:%.*]] = bitcast [[D]]* [[D_P]] to i8* + // CHECK: [[T1:%.*]] = getelementptr inbounds i8, i8* [[T0]], i64 [[OFFSET]] + // CHECK: [[A_P:%.*]] = bitcast i8* [[T1]] to [[A]]* + // 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) + D d; + AlignedArray result = d.aArray; + } + + // CHECK-LABEL: @_ZN5test11gEv + void g() { + // CHECK: [[D_P:%.*]] = alloca [[D]], align 16 + // CHECK: [[RESULT:%.*]] = alloca [[ARRAY]], align 64 + // CHECK: [[T0:%.*]] = bitcast [[D]]* [[D_P]] to i8* + // CHECK: [[T1:%.*]] = getelementptr inbounds i8, i8* [[T0]], i64 24 + // CHECK: [[B_P:%.*]] = bitcast i8* [[T1]] to [[B:%.*]]* + // 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) + D d; + AlignedArray result = d.bArray; + } +} diff --git a/test/CodeGenCXX/arm.cpp b/test/CodeGenCXX/arm.cpp index 0fadfe97b49a..11ae6b24c26e 100644 --- a/test/CodeGenCXX/arm.cpp +++ b/test/CodeGenCXX/arm.cpp @@ -152,8 +152,8 @@ namespace test3 { void e(A *x) { // CHECK-LABEL: define void @_ZN5test31eEPNS_1AE( // CHECK: icmp eq {{.*}}, null - // CHECK: getelementptr {{.*}}, i64 -8 - // CHECK: getelementptr {{.*}}, i64 4 + // CHECK: getelementptr {{.*}}, i32 -8 + // CHECK: getelementptr {{.*}}, i32 4 // CHECK: bitcast {{.*}} to i32* // CHECK: load // CHECK: invoke {{.*}} @_ZN5test31AD1Ev @@ -164,8 +164,8 @@ namespace test3 { void f(A (*x)[20]) { // CHECK-LABEL: define void @_ZN5test31fEPA20_NS_1AE( // CHECK: icmp eq {{.*}}, null - // CHECK: getelementptr {{.*}}, i64 -8 - // CHECK: getelementptr {{.*}}, i64 4 + // CHECK: getelementptr {{.*}}, i32 -8 + // CHECK: getelementptr {{.*}}, i32 4 // CHECK: bitcast {{.*}} to i32* // CHECK: load // CHECK: invoke {{.*}} @_ZN5test31AD1Ev @@ -223,8 +223,8 @@ namespace test4 { void e(A *x) { // CHECK-LABEL: define void @_ZN5test41eEPNS_1AE( - // CHECK: [[ALLOC:%.*]] = getelementptr inbounds {{.*}}, i64 -8 - // CHECK: getelementptr inbounds {{.*}}, i64 4 + // CHECK: [[ALLOC:%.*]] = getelementptr inbounds {{.*}}, i32 -8 + // CHECK: getelementptr inbounds {{.*}}, i32 4 // CHECK: bitcast // CHECK: [[T0:%.*]] = load i32, i32* // CHECK: [[T1:%.*]] = mul i32 4, [[T0]] @@ -235,8 +235,8 @@ namespace test4 { void f(A (*x)[20]) { // CHECK-LABEL: define void @_ZN5test41fEPA20_NS_1AE( - // CHECK: [[ALLOC:%.*]] = getelementptr inbounds {{.*}}, i64 -8 - // CHECK: getelementptr inbounds {{.*}}, i64 4 + // CHECK: [[ALLOC:%.*]] = getelementptr inbounds {{.*}}, i32 -8 + // CHECK: getelementptr inbounds {{.*}}, i32 4 // CHECK: bitcast // CHECK: [[T0:%.*]] = load i32, i32* // CHECK: [[T1:%.*]] = mul i32 4, [[T0]] @@ -293,7 +293,7 @@ namespace test7 { // CHECK-LABEL: define void @_ZN5test74testEv() {{.*}} personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) void test() { - // CHECK: [[T0:%.*]] = load atomic i8, i8* bitcast (i32* @_ZGVZN5test74testEvE1x to i8*) acquire, align 1 + // CHECK: [[T0:%.*]] = load atomic i8, i8* bitcast (i32* @_ZGVZN5test74testEvE1x to i8*) acquire, align 4 // CHECK-NEXT: [[T1:%.*]] = and i8 [[T0]], 1 // CHECK-NEXT: [[T2:%.*]] = icmp eq i8 [[T1]], 0 // CHECK-NEXT: br i1 [[T2]] @@ -328,7 +328,7 @@ namespace test8 { // CHECK-LABEL: define void @_ZN5test84testEv() {{.*}} personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) void test() { - // CHECK: [[T0:%.*]] = load atomic i8, i8* bitcast (i32* @_ZGVZN5test84testEvE1x to i8*) acquire, align 1 + // CHECK: [[T0:%.*]] = load atomic i8, i8* bitcast (i32* @_ZGVZN5test84testEvE1x to i8*) acquire, align 4 // CHECK-NEXT: [[T1:%.*]] = and i8 [[T0]], 1 // CHECK-NEXT: [[T2:%.*]] = icmp eq i8 [[T1]], 0 // CHECK-NEXT: br i1 [[T2]] @@ -388,7 +388,7 @@ namespace test9 { // CHECK-NEXT: store i32 16, i32* [[T0]] // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i32, i32* [[T0]], i32 1 // CHECK-NEXT: store i32 [[N]], i32* [[T1]] -// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds i8, i8* [[ALLOC]], i64 16 +// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds i8, i8* [[ALLOC]], i32 16 // CHECK-NEXT: bitcast i8* [[T0]] to [[TEST9]]* // Array allocation follows. @@ -400,8 +400,8 @@ namespace test9 { // CHECK-NEXT: [[T0:%.*]] = icmp eq [[TEST9]]* [[BEGIN]], null // CHECK-NEXT: br i1 [[T0]], // CHECK: [[T0:%.*]] = bitcast [[TEST9]]* [[BEGIN]] to i8* -// CHECK-NEXT: [[ALLOC:%.*]] = getelementptr inbounds i8, i8* [[T0]], i64 -16 -// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds i8, i8* [[ALLOC]], i64 4 +// CHECK-NEXT: [[ALLOC:%.*]] = getelementptr inbounds i8, i8* [[T0]], i32 -16 +// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds i8, i8* [[ALLOC]], i32 4 // CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to i32* // CHECK-NEXT: [[N:%.*]] = load i32, i32* [[T1]] // CHECK-NEXT: [[END:%.*]] = getelementptr inbounds [[TEST9]], [[TEST9]]* [[BEGIN]], i32 [[N]] diff --git a/test/CodeGenCXX/armv7k.cpp b/test/CodeGenCXX/armv7k.cpp new file mode 100644 index 000000000000..9b27b651fe37 --- /dev/null +++ b/test/CodeGenCXX/armv7k.cpp @@ -0,0 +1,68 @@ +// RUN: %clang_cc1 %s -triple=thumbv7k-apple-watchos -emit-llvm -o - -target-abi aapcs16 | FileCheck %s +// RUN: %clang_cc1 %s -triple=thumbv7k-apple-watchos -emit-llvm -o - -target-abi aapcs16 | FileCheck -check-prefix=CHECK-GLOBALS %s + +// __cxa_guard_acquire argument is 64-bit +// rdar://11540122 +struct A { + A(); +}; + +void f() { + // CHECK: call i32 @__cxa_guard_acquire(i32* + static A a; +} + +// ARM64 uses the C++11 definition of POD. +// rdar://12650514 +namespace test1 { + // This class is POD in C++11 and cannot have objects allocated in + // its tail-padding. + struct ABase {}; + struct A : ABase { + int x; + char c; + }; + + struct B : A { + char d; + }; + + int test() { + return sizeof(B); + } + // CHECK: define i32 @_ZN5test14testEv() + // CHECK: ret i32 12 +} + +namespace std { + class type_info; +} + +// ARM64 uses string comparisons for what would otherwise be +// default-visibility weak RTTI. rdar://12650568 +namespace test2 { + struct A { + virtual void foo(); + }; + void A::foo() {} + // Tested below because these globals get kindof oddly rearranged. + + struct __attribute__((visibility("hidden"))) B {}; + const std::type_info &b0 = typeid(B); + // CHECK-GLOBALS: @_ZTSN5test21BE = linkonce_odr hidden constant + // CHECK-GLOBALS: @_ZTIN5test21BE = linkonce_odr hidden constant { {{.*}}, i8* getelementptr inbounds ([11 x i8], [11 x i8]* @_ZTSN5test21BE, i32 0, i32 0) } + + const std::type_info &b1 = typeid(B*); + // CHECK-GLOBALS: @_ZTSPN5test21BE = linkonce_odr hidden constant + // CHECK-GLOBALS: @_ZTIPN5test21BE = linkonce_odr hidden constant { {{.*}}, i8* getelementptr inbounds ([12 x i8], [12 x i8]* @_ZTSPN5test21BE, i32 0, i32 0), i32 0, i8* bitcast + + struct C {}; + const std::type_info &c0 = typeid(C); + // CHECK-GLOBALS: @_ZTSN5test21CE = linkonce_odr constant [11 x i8] c"N5test21CE\00" + // CHECK-GLOBALS: @_ZTIN5test21CE = linkonce_odr constant { {{.*}}, i8* getelementptr inbounds ([11 x i8], [11 x i8]* @_ZTSN5test21CE, i32 0, i32 0) } +} + +// va_list should be based on "char *" rather than "void *". + +// CHECK: define void @_Z11whatsVaListPc +void whatsVaList(__builtin_va_list l) {} diff --git a/test/CodeGenCXX/attr-disable-tail-calls.cpp b/test/CodeGenCXX/attr-disable-tail-calls.cpp new file mode 100644 index 000000000000..b9a3c2712f08 --- /dev/null +++ b/test/CodeGenCXX/attr-disable-tail-calls.cpp @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 -triple=x86_64-apple-darwin -std=c++11 -emit-llvm -o - %s | FileCheck %s + +class B { +public: + [[clang::disable_tail_calls]] virtual int m1() { return 1; } + virtual int m2() { return 2; } + int m3() { return 3; } + [[clang::disable_tail_calls]] int m4(); +}; + +class D : public B { +public: + int m1() override { return 11; } + [[clang::disable_tail_calls]] int m2() override { return 22; } +}; + +int foo1() { + B *b = new B; + D *d = new D; + int t = 0; + t += b->m1() + b->m2() + b->m3() + b->m4(); + t += d->m1() + d->m2(); + return t; +} + +// CHECK: define linkonce_odr i32 @_ZN1B2m3Ev(%class.B* %this) [[ATTRFALSE:#[0-9]+]] +// CHECK: declare i32 @_ZN1B2m4Ev(%class.B*) [[ATTRTRUE0:#[0-9]+]] +// CHECK: define linkonce_odr i32 @_ZN1B2m1Ev(%class.B* %this) unnamed_addr [[ATTRTRUE1:#[0-9]+]] +// CHECK: define linkonce_odr i32 @_ZN1B2m2Ev(%class.B* %this) unnamed_addr [[ATTRFALSE:#[0-9]+]] +// CHECK: define linkonce_odr i32 @_ZN1D2m1Ev(%class.D* %this) unnamed_addr [[ATTRFALSE:#[0-9]+]] +// CHECK: define linkonce_odr i32 @_ZN1D2m2Ev(%class.D* %this) unnamed_addr [[ATTRTRUE1:#[0-9]+]] + +// CHECK: attributes [[ATTRFALSE]] = { {{.*}}"disable-tail-calls"="false"{{.*}} } +// CHECK: attributes [[ATTRTRUE0]] = { {{.*}}"disable-tail-calls"="true"{{.*}} } +// CHECK: attributes [[ATTRTRUE1]] = { {{.*}}"disable-tail-calls"="true"{{.*}} } diff --git a/test/CodeGenCXX/attr-notail.cpp b/test/CodeGenCXX/attr-notail.cpp new file mode 100644 index 000000000000..80af424ff3e1 --- /dev/null +++ b/test/CodeGenCXX/attr-notail.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -triple=x86_64-apple-darwin -std=c++11 -emit-llvm -o - %s | FileCheck %s + +class Class1 { +public: + [[clang::not_tail_called]] int m1(); + int m2(); +}; + +int foo1(int a, Class1 *c1) { + if (a) + return c1->m1(); + return c1->m2(); +} + +// CHECK-LABEL: define i32 @_Z4foo1iP6Class1( +// CHECK: %{{[a-z0-9]+}} = notail call i32 @_ZN6Class12m1Ev(%class.Class1* +// CHECK: %{{[a-z0-9]+}} = call i32 @_ZN6Class12m2Ev(%class.Class1* diff --git a/test/CodeGenCXX/attr.cpp b/test/CodeGenCXX/attr.cpp index 8bcff363c723..67993b4227a1 100644 --- a/test/CodeGenCXX/attr.cpp +++ b/test/CodeGenCXX/attr.cpp @@ -1,6 +1,6 @@ // RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm -o - %s | FileCheck %s -// CHECK: @test2 = alias i32 ()* @_Z5test1v +// CHECK: @test2 = alias i32 (), i32 ()* @_Z5test1v // CHECK: define i32 @_Z3foov() [[NUW:#[0-9]+]] align 1024 int foo() __attribute__((aligned(1024))); diff --git a/test/CodeGenCXX/attribute_internal_linkage.cpp b/test/CodeGenCXX/attribute_internal_linkage.cpp new file mode 100644 index 000000000000..21cd44e916f2 --- /dev/null +++ b/test/CodeGenCXX/attribute_internal_linkage.cpp @@ -0,0 +1,79 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -std=c++11 -emit-llvm -o - %s | FileCheck %s + +__attribute__((internal_linkage)) void f() {} +// CHECK-DAG: define internal void @_ZL1fv + +class A { +public: + static int y __attribute__((internal_linkage)); + static int y2 [[clang::internal_linkage]]; +// CHECK-DAG: @_ZN1A1yE = internal global +// CHECK-DAG: @_ZN1A2y2E = internal global + void f1() __attribute__((internal_linkage)); +// CHECK-DAG: define internal void @_ZN1A2f1Ev + void f2() __attribute__((internal_linkage)) {} +// CHECK-DAG: define internal void @_ZN1A2f2Ev + static void f4() __attribute__((internal_linkage)) {} +// CHECK-DAG: define internal void @_ZN1A2f4Ev + A() __attribute__((internal_linkage)) {} +// CHECK-DAG: define internal void @_ZN1AC1Ev +// CHECK-DAG: define internal void @_ZN1AC2Ev + ~A() __attribute__((internal_linkage)) {} +// CHECK-DAG: define internal void @_ZN1AD1Ev +// CHECK-DAG: define internal void @_ZN1AD2Ev +}; + +int A::y; +int A::y2; + +void A::f1() { +} + +// Forward declaration w/o an attribute. +class B; + +// Internal_linkage on a class affects all its members. +class __attribute__((internal_linkage)) B { +public: + B() {} + // CHECK-DAG: define internal void @_ZNL1BC1Ev + // CHECK-DAG: define internal void @_ZNL1BC2Ev + ~B() {} + // CHECK-DAG: define internal void @_ZNL1BD1Ev + // CHECK-DAG: define internal void @_ZNL1BD2Ev + void f() {}; + // CHECK-DAG: define internal void @_ZNL1B1fEv + static int x; + // CHECK-DAG: @_ZNL1B1xE = internal global +}; + +int B::x; + +// Forward declaration with the attribute. +class __attribute__((internal_linkage)) C; +class C { +public: + static int x; + // CHECK-DAG: @_ZNL1C1xE = internal global +}; + +int C::x; + +__attribute__((internal_linkage)) void g(); +void g() {} +// CHECK-DAG: define internal void @_ZL1gv() + +void use() { + A a; + a.f1(); + a.f2(); + A::f4(); + f(); + int &Y = A::y; + int &Y2 = A::y2; + B b; + b.f(); + int &XX2 = B::x; + g(); + int &XX3 = C::x; +} diff --git a/test/CodeGenCXX/cast-to-ref-bool.cpp b/test/CodeGenCXX/cast-to-ref-bool.cpp new file mode 100644 index 000000000000..10647205de39 --- /dev/null +++ b/test/CodeGenCXX/cast-to-ref-bool.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o - %s | FileCheck %s + +// CHECK-LABEL: main +int main(int argc, char **argv) { + // CHECK: load i8, i8* % + // CHECK-NEXT: trunc i8 %{{.+}} to i1 + bool b = (bool &)argv[argc][1]; + return b; +} diff --git a/test/CodeGenCXX/catch-undef-behavior.cpp b/test/CodeGenCXX/catch-undef-behavior.cpp index d08fe764cdbf..3ca7f6d65ad4 100644 --- a/test/CodeGenCXX/catch-undef-behavior.cpp +++ b/test/CodeGenCXX/catch-undef-behavior.cpp @@ -1,9 +1,8 @@ -// RUN: %clang_cc1 -std=c++11 -fsanitize=signed-integer-overflow,integer-divide-by-zero,float-divide-by-zero,shift-base,shift-exponent,unreachable,return,vla-bound,alignment,null,vptr,object-size,float-cast-overflow,bool,enum,array-bounds,function -fsanitize-recover=signed-integer-overflow,integer-divide-by-zero,float-divide-by-zero,shift-base,shift-exponent,vla-bound,alignment,null,vptr,object-size,float-cast-overflow,bool,enum,array-bounds,function -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s +// RUN: %clang_cc1 -std=c++11 -fsanitize=signed-integer-overflow,integer-divide-by-zero,float-divide-by-zero,shift-base,shift-exponent,unreachable,return,vla-bound,alignment,null,vptr,object-size,float-cast-overflow,bool,enum,array-bounds,function -fsanitize-recover=signed-integer-overflow,integer-divide-by-zero,float-divide-by-zero,shift-base,shift-exponent,vla-bound,alignment,null,vptr,object-size,float-cast-overflow,bool,enum,array-bounds,function -emit-llvm %s -o - -triple x86_64-linux-gnu | opt -instnamer -S | FileCheck %s // RUN: %clang_cc1 -std=c++11 -fsanitize=vptr,address -fsanitize-recover=vptr,address -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=CHECK-ASAN // RUN: %clang_cc1 -std=c++11 -fsanitize=vptr -fsanitize-recover=vptr -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=DOWNCAST-NULL // RUN: %clang_cc1 -std=c++11 -fsanitize=function -emit-llvm %s -o - -triple x86_64-linux-gnux32 | FileCheck %s --check-prefix=CHECK-X32 // RUN: %clang_cc1 -std=c++11 -fsanitize=function -emit-llvm %s -o - -triple i386-linux-gnu | FileCheck %s --check-prefix=CHECK-X86 -// REQUIRES: asserts struct S { double d; @@ -369,15 +368,15 @@ 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-NEXT: [[C:%[0-9]*]] = bitcast i8* [[SUB]] to %class.C* + // CHECK-NEXT: [[C:%.+]] = bitcast i8* [[SUB]] to %class.C* // null check goes here - // CHECK: [[FROM_PHI:%[0-9]*]] = phi %class.C* [ [[C]], {{.*}} ], {{.*}} + // CHECK: [[FROM_PHI:%.+]] = phi %class.C* [ [[C]], {{.*}} ], {{.*}} // Objectsize check goes here - // CHECK: [[C_INT:%[0-9]*]] = ptrtoint %class.C* [[FROM_PHI]] to i64 - // CHECK-NEXT: [[MASKED:%[0-9]*]] = and i64 [[C_INT]], 15 - // CHECK-NEXT: [[TEST:%[0-9]*]] = icmp eq i64 [[MASKED]], 0 + // CHECK: [[C_INT:%.+]] = ptrtoint %class.C* [[FROM_PHI]] to i64 + // CHECK-NEXT: [[MASKED:%.+]] = and i64 [[C_INT]], 15 + // CHECK-NEXT: [[TEST:%.+]] = icmp eq i64 [[MASKED]], 0 // AND the alignment test with the objectsize test. - // CHECK-NEXT: [[AND:%[0-9]*]] = and i1 {{.*}}, [[TEST]] + // CHECK-NEXT: [[AND:%.+]] = and i1 {{.*}}, [[TEST]] // CHECK-NEXT: br i1 [[AND]] } @@ -386,13 +385,13 @@ 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-NEXT: [[C:%[0-9]*]] = bitcast i8* [[SUB]] to %class.C* + // CHECK-NEXT: [[C:%.+]] = bitcast i8* [[SUB]] to %class.C* // Objectsize check goes here - // CHECK: [[C_INT:%[0-9]*]] = ptrtoint %class.C* [[C]] to i64 - // CHECK-NEXT: [[MASKED:%[0-9]*]] = and i64 [[C_INT]], 15 - // CHECK-NEXT: [[TEST:%[0-9]*]] = icmp eq i64 [[MASKED]], 0 + // CHECK: [[C_INT:%.+]] = ptrtoint %class.C* [[C]] to i64 + // CHECK-NEXT: [[MASKED:%.+]] = and i64 [[C_INT]], 15 + // CHECK-NEXT: [[TEST:%.+]] = icmp eq i64 [[MASKED]], 0 // AND the alignment test with the objectsize test. - // CHECK: [[AND:%[0-9]*]] = and i1 {{.*}}, [[TEST]] + // CHECK: [[AND:%.+]] = and i1 {{.*}}, [[TEST]] // CHECK-NEXT: br i1 [[AND]] } @@ -400,18 +399,18 @@ void downcast_reference(B &b) { // CHECK-X32: @_Z22indirect_function_callPFviE({{.*}} prologue <{ i32, i8* }> <{ i32 1413875435, i8* bitcast ({ i8*, i8* }* @_ZTIFvPFviEE to i8*) }> // CHECK-X86: @_Z22indirect_function_callPFviE({{.*}} prologue <{ i32, i8* }> <{ i32 1413875435, i8* bitcast ({ i8*, i8* }* @_ZTIFvPFviEE to i8*) }> void indirect_function_call(void (*p)(int)) { - // CHECK: [[PTR:%[0-9]*]] = bitcast void (i32)* {{.*}} to <{ i32, i8* }>* + // CHECK: [[PTR:%.+]] = bitcast void (i32)* {{.*}} to <{ i32, i8* }>* // Signature check - // CHECK-NEXT: [[SIGPTR:%[0-9]*]] = getelementptr <{ i32, i8* }>, <{ i32, i8* }>* [[PTR]], i32 0, i32 0 - // CHECK-NEXT: [[SIG:%[0-9]*]] = load i32, i32* [[SIGPTR]] - // CHECK-NEXT: [[SIGCMP:%[0-9]*]] = icmp eq i32 [[SIG]], 1413876459 + // CHECK-NEXT: [[SIGPTR:%.+]] = getelementptr <{ i32, i8* }>, <{ i32, i8* }>* [[PTR]], i32 0, i32 0 + // CHECK-NEXT: [[SIG:%.+]] = load i32, i32* [[SIGPTR]] + // CHECK-NEXT: [[SIGCMP:%.+]] = icmp eq i32 [[SIG]], 1413876459 // CHECK-NEXT: br i1 [[SIGCMP]] // RTTI pointer check - // CHECK: [[RTTIPTR:%[0-9]*]] = getelementptr <{ i32, i8* }>, <{ i32, i8* }>* [[PTR]], i32 0, i32 1 - // CHECK-NEXT: [[RTTI:%[0-9]*]] = load i8*, i8** [[RTTIPTR]] - // CHECK-NEXT: [[RTTICMP:%[0-9]*]] = icmp eq i8* [[RTTI]], bitcast ({ i8*, i8* }* @_ZTIFviE to i8*) + // CHECK: [[RTTIPTR:%.+]] = getelementptr <{ i32, i8* }>, <{ i32, i8* }>* [[PTR]], i32 0, i32 1 + // CHECK-NEXT: [[RTTI:%.+]] = load i8*, i8** [[RTTIPTR]] + // CHECK-NEXT: [[RTTICMP:%.+]] = icmp eq i8* [[RTTI]], bitcast ({ i8*, i8* }* @_ZTIFviE to i8*) // CHECK-NEXT: br i1 [[RTTICMP]] p(42); } diff --git a/test/CodeGenCXX/cfi-blacklist.cpp b/test/CodeGenCXX/cfi-blacklist.cpp new file mode 100644 index 000000000000..32ed05bcc520 --- /dev/null +++ b/test/CodeGenCXX/cfi-blacklist.cpp @@ -0,0 +1,30 @@ +// RUN: echo "type:attr:uuid" > %t.txt +// RUN: %clang_cc1 -fms-extensions -fsanitize=cfi-vcall -fsanitize-blacklist=%t.txt -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=NOUUID %s +// RUN: echo "type:std::*" > %t.txt +// RUN: %clang_cc1 -fms-extensions -fsanitize=cfi-vcall -fsanitize-blacklist=%t.txt -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=NOSTD %s + +struct __declspec(uuid("00000000-0000-0000-0000-000000000000")) S1 { + virtual void f(); +}; + +namespace std { + +struct S2 { + virtual void f(); +}; + +} + +// CHECK: define{{.*}}s1f +// NOSTD: llvm.bitset.test +// NOUUID-NOT: llvm.bitset.test +void s1f(S1 *s1) { + s1->f(); +} + +// CHECK: define{{.*}}s2f +// NOSTD-NOT: llvm.bitset.test +// NOUUID: llvm.bitset.test +void s2f(std::S2 *s2) { + s2->f(); +} diff --git a/test/CodeGenCXX/cfi-cast.cpp b/test/CodeGenCXX/cfi-cast.cpp index 09089634442c..0b96cb6506c0 100644 --- a/test/CodeGenCXX/cfi-cast.cpp +++ b/test/CodeGenCXX/cfi-cast.cpp @@ -18,7 +18,7 @@ struct C : A {}; // CHECK-DCAST-LABEL: define void @_Z3abpP1A void abp(A *a) { - // CHECK-DCAST: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"1B") + // CHECK-DCAST: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B") // CHECK-DCAST-NEXT: br i1 [[P]], label %[[CONTBB:[^ ]*]], label %[[TRAPBB:[^ ,]*]] // CHECK-DCAST: [[TRAPBB]] @@ -32,7 +32,7 @@ void abp(A *a) { // CHECK-DCAST-LABEL: define void @_Z3abrR1A void abr(A &a) { - // CHECK-DCAST: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"1B") + // CHECK-DCAST: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B") // CHECK-DCAST-NEXT: br i1 [[P]], label %[[CONTBB:[^ ]*]], label %[[TRAPBB:[^ ,]*]] // CHECK-DCAST: [[TRAPBB]] @@ -46,7 +46,7 @@ void abr(A &a) { // CHECK-DCAST-LABEL: define void @_Z4abrrO1A void abrr(A &&a) { - // CHECK-DCAST: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"1B") + // CHECK-DCAST: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B") // CHECK-DCAST-NEXT: br i1 [[P]], label %[[CONTBB:[^ ]*]], label %[[TRAPBB:[^ ,]*]] // CHECK-DCAST: [[TRAPBB]] @@ -60,7 +60,7 @@ void abrr(A &&a) { // CHECK-UCAST-LABEL: define void @_Z3vbpPv void vbp(void *p) { - // CHECK-UCAST: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"1B") + // CHECK-UCAST: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B") // CHECK-UCAST-NEXT: br i1 [[P]], label %[[CONTBB:[^ ]*]], label %[[TRAPBB:[^ ,]*]] // CHECK-UCAST: [[TRAPBB]] @@ -74,7 +74,7 @@ void vbp(void *p) { // CHECK-UCAST-LABEL: define void @_Z3vbrRc void vbr(char &r) { - // CHECK-UCAST: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"1B") + // CHECK-UCAST: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B") // CHECK-UCAST-NEXT: br i1 [[P]], label %[[CONTBB:[^ ]*]], label %[[TRAPBB:[^ ,]*]] // CHECK-UCAST: [[TRAPBB]] @@ -88,7 +88,7 @@ void vbr(char &r) { // CHECK-UCAST-LABEL: define void @_Z4vbrrOc void vbrr(char &&r) { - // CHECK-UCAST: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"1B") + // CHECK-UCAST: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B") // CHECK-UCAST-NEXT: br i1 [[P]], label %[[CONTBB:[^ ]*]], label %[[TRAPBB:[^ ,]*]] // CHECK-UCAST: [[TRAPBB]] @@ -103,7 +103,23 @@ void vbrr(char &&r) { // CHECK-UCAST-LABEL: define void @_Z3vcpPv // CHECK-UCAST-STRICT-LABEL: define void @_Z3vcpPv void vcp(void *p) { - // CHECK-UCAST: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"1A") - // CHECK-UCAST-STRICT: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"1C") + // CHECK-UCAST: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1A") + // CHECK-UCAST-STRICT: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1C") static_cast(p); } + +// CHECK-UCAST-LABEL: define void @_Z3bcpP1B +// CHECK-UCAST-STRICT-LABEL: define void @_Z3bcpP1B +void bcp(B *p) { + // CHECK-UCAST: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1A") + // CHECK-UCAST-STRICT: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1C") + (C *)p; +} + +// CHECK-UCAST-LABEL: define void @_Z8bcp_callP1B +// CHECK-UCAST-STRICT-LABEL: define void @_Z8bcp_callP1B +void bcp_call(B *p) { + // CHECK-UCAST: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1A") + // CHECK-UCAST-STRICT: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1C") + ((C *)p)->f(); +} diff --git a/test/CodeGenCXX/cfi-cross-dso.cpp b/test/CodeGenCXX/cfi-cross-dso.cpp new file mode 100644 index 000000000000..fbe6fc83a5c3 --- /dev/null +++ b/test/CodeGenCXX/cfi-cross-dso.cpp @@ -0,0 +1,45 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux -fsanitize=cfi-vcall -fsanitize-cfi-cross-dso -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=ITANIUM %s +// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc -fsanitize=cfi-vcall -fsanitize-cfi-cross-dso -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=MS %s + +struct A { + A(); + virtual void f(); +}; + +A::A() {} +void A::f() {} + +void caller(A* a) { + a->f(); +} + +namespace { +struct B { + virtual void f(); +}; + +void B::f() {} +} // namespace + +void g() { + B b; + b.f(); +} + +// MS: @[[B_VTABLE:.*]] = private unnamed_addr constant [2 x i8*] {{.*}}@"\01??_R4B@?A@@6B@"{{.*}}@"\01?f@B@?A@@UEAAXXZ" + +// CHECK: %[[VT:.*]] = load void (%struct.A*)**, void (%struct.A*)*** +// CHECK: %[[VT2:.*]] = bitcast {{.*}}%[[VT]] to i8*, !nosanitize +// ITANIUM: %[[TEST:.*]] = call i1 @llvm.bitset.test(i8* %[[VT2]], metadata !"_ZTS1A"), !nosanitize +// MS: %[[TEST:.*]] = call i1 @llvm.bitset.test(i8* %[[VT2]], metadata !"?AUA@@"), !nosanitize +// CHECK: br i1 %[[TEST]], label %[[CONT:.*]], label %[[SLOW:.*]], {{.*}} !nosanitize +// CHECK: [[SLOW]] +// ITANIUM: call void @__cfi_slowpath(i64 7004155349499253778, i8* %[[VT2]]) {{.*}} !nosanitize +// MS: call void @__cfi_slowpath(i64 -8005289897957287421, i8* %[[VT2]]) {{.*}} !nosanitize +// CHECK: br label %[[CONT]], !nosanitize +// CHECK: [[CONT]] +// CHECK: call void %{{.*}}(%struct.A* %{{.*}}) + +// No hash-based bit set entry for (anonymous namespace)::B +// ITANIUM-NOT: !{i64 {{.*}}, [3 x i8*]* @_ZTVN12_GLOBAL__N_11BE, +// MS-NOT: !{i64 {{.*}}, [2 x i8*]* @[[B_VTABLE]], diff --git a/test/CodeGenCXX/cfi-icall.cpp b/test/CodeGenCXX/cfi-icall.cpp new file mode 100644 index 000000000000..eceb92a4421c --- /dev/null +++ b/test/CodeGenCXX/cfi-icall.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux -fsanitize=cfi-icall -fsanitize-trap=cfi-icall -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=ITANIUM %s +// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc -fsanitize=cfi-icall -fsanitize-trap=cfi-icall -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=MS %s + +// Tests that we assign unnamed metadata nodes to functions whose types have +// internal linkage. + +namespace { + +struct S {}; + +void f(S *s) { +} + +} + +void g() { + void (*fp)(S *) = f; + // CHECK: call i1 @llvm.bitset.test(i8* {{.*}}, metadata ![[VOIDS:[0-9]+]]) + fp(0); +} + +// ITANIUM: !{![[VOIDS]], void (%"struct.(anonymous namespace)::S"*)* @_ZN12_GLOBAL__N_11fEPNS_1SE, i64 0} +// MS: !{![[VOIDS]], void (%"struct.(anonymous namespace)::S"*)* @"\01?f@?A@@YAXPEAUS@?A@@@Z", i64 0} diff --git a/test/CodeGenCXX/cfi-ms-rtti.cpp b/test/CodeGenCXX/cfi-ms-rtti.cpp index 5203a6bb0c8b..b6e9175c865c 100644 --- a/test/CodeGenCXX/cfi-ms-rtti.cpp +++ b/test/CodeGenCXX/cfi-ms-rtti.cpp @@ -8,5 +8,5 @@ struct A { A::A() {} -// RTTI: !{!"A@@", [2 x i8*]* {{.*}}, i64 8} -// NO-RTTI: !{!"A@@", [1 x i8*]* {{.*}}, i64 0} +// RTTI: !{!"?AUA@@", [2 x i8*]* {{.*}}, i64 8} +// NO-RTTI: !{!"?AUA@@", [1 x i8*]* {{.*}}, i64 0} diff --git a/test/CodeGenCXX/cfi-nvcall.cpp b/test/CodeGenCXX/cfi-nvcall.cpp index b0db478c9d0c..be4d8448a2e0 100644 --- a/test/CodeGenCXX/cfi-nvcall.cpp +++ b/test/CodeGenCXX/cfi-nvcall.cpp @@ -17,8 +17,8 @@ struct C : A { // CHECK-LABEL: @bg // CHECK-STRICT-LABEL: @bg extern "C" void bg(B *b) { - // CHECK: call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"1B") - // CHECK-STRICT: call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"1B") + // CHECK: call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B") + // CHECK-STRICT: call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B") b->g(); } @@ -29,7 +29,7 @@ extern "C" void cg(C *c) { // In this case C's layout is the same as its base class, so we allow // c to be of type A in non-strict mode. - // CHECK: call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"1A") - // CHECK-STRICT: call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"1C") + // CHECK: call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1A") + // CHECK-STRICT: call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1C") c->g(); } diff --git a/test/CodeGenCXX/cfi-vcall.cpp b/test/CodeGenCXX/cfi-vcall.cpp index 5cb5e02cf585..daa0531e85d6 100644 --- a/test/CodeGenCXX/cfi-vcall.cpp +++ b/test/CodeGenCXX/cfi-vcall.cpp @@ -60,8 +60,8 @@ void D::h() { // ITANIUM: define void @_Z2afP1A // MS: define void @"\01?af@@YAXPEAUA@@@Z" void af(A *a) { - // ITANIUM: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* [[VT:%[^ ]*]], metadata !"1A") - // MS: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* [[VT:%[^ ]*]], metadata !"A@@") + // ITANIUM: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* [[VT:%[^ ]*]], metadata !"_ZTS1A") + // MS: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* [[VT:%[^ ]*]], metadata !"?AUA@@") // CHECK-NEXT: br i1 [[P]], label %[[CONTBB:[^ ,]*]], label %[[TRAPBB:[^ ,]*]] // CHECK-NEXT: {{^$}} @@ -82,24 +82,24 @@ void af(A *a) { // ITANIUM: define internal void @_Z3df1PN12_GLOBAL__N_11DE // MS: define internal void @"\01?df1@@YAXPEAUD@?A@@@Z" void df1(D *d) { - // ITANIUM: {{%[^ ]*}} = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"[{{.*}}cfi-vcall.cpp]N12_GLOBAL__N_11DE") - // MS: {{%[^ ]*}} = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"A@@") + // ITANIUM: {{%[^ ]*}} = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata ![[DTYPE:[0-9]+]]) + // MS: {{%[^ ]*}} = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"?AUA@@") d->f(); } // ITANIUM: define internal void @_Z3dg1PN12_GLOBAL__N_11DE // MS: define internal void @"\01?dg1@@YAXPEAUD@?A@@@Z" void dg1(D *d) { - // ITANIUM: {{%[^ ]*}} = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"1B") - // MS: {{%[^ ]*}} = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"B@@") + // ITANIUM: {{%[^ ]*}} = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B") + // MS: {{%[^ ]*}} = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"?AUB@@") d->g(); } // ITANIUM: define internal void @_Z3dh1PN12_GLOBAL__N_11DE // MS: define internal void @"\01?dh1@@YAXPEAUD@?A@@@Z" void dh1(D *d) { - // ITANIUM: {{%[^ ]*}} = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"[{{.*}}cfi-vcall.cpp]N12_GLOBAL__N_11DE") - // MS: {{%[^ ]*}} = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"[{{.*}}cfi-vcall.cpp]D@?A@@") + // ITANIUM: {{%[^ ]*}} = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata ![[DTYPE]]) + // MS: {{%[^ ]*}} = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata ![[DTYPE:[0-9]+]]) d->h(); } @@ -150,8 +150,8 @@ struct D : C { // ITANIUM: define void @_ZN5test21fEPNS_1DE // MS: define void @"\01?f@test2@@YAXPEAUD@1@@Z" void f(D *d) { - // ITANIUM: {{%[^ ]*}} = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"N5test21DE") - // MS: {{%[^ ]*}} = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"A@test2@@") + // ITANIUM: {{%[^ ]*}} = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTSN5test21DE") + // MS: {{%[^ ]*}} = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"?AUA@test2@@") d->m_fn1(); } @@ -161,28 +161,28 @@ void f(D *d) { // MS: !llvm.bitsets = !{[[X:[^,]*(,[^,]*){8}]]} // ITANIUM: !llvm.bitsets = !{[[X:[^,]*(,[^,]*){14}]]} -// ITANIUM-DAG: !{!"1A", [3 x i8*]* @_ZTV1A, i64 16} -// ITANIUM-DAG: !{!"1A", [7 x i8*]* @_ZTCN12_GLOBAL__N_11DE0_1B, i64 32} -// ITANIUM-DAG: !{!"1B", [7 x i8*]* @_ZTCN12_GLOBAL__N_11DE0_1B, i64 32} -// ITANIUM-DAG: !{!"1A", [9 x i8*]* @_ZTCN12_GLOBAL__N_11DE8_1C, i64 64} -// ITANIUM-DAG: !{!"1C", [9 x i8*]* @_ZTCN12_GLOBAL__N_11DE8_1C, i64 32} -// ITANIUM-DAG: !{!"1A", [12 x i8*]* @_ZTVN12_GLOBAL__N_11DE, i64 32} -// ITANIUM-DAG: !{!"1B", [12 x i8*]* @_ZTVN12_GLOBAL__N_11DE, i64 32} -// ITANIUM-DAG: !{!"1C", [12 x i8*]* @_ZTVN12_GLOBAL__N_11DE, i64 88} -// ITANIUM-DAG: !{!"[{{.*}}cfi-vcall.cpp]N12_GLOBAL__N_11DE", [12 x i8*]* @_ZTVN12_GLOBAL__N_11DE, i64 32} -// ITANIUM-DAG: !{!"1A", [7 x i8*]* @_ZTV1B, i64 32} -// ITANIUM-DAG: !{!"1B", [7 x i8*]* @_ZTV1B, i64 32} -// ITANIUM-DAG: !{!"1A", [5 x i8*]* @_ZTV1C, i64 32} -// ITANIUM-DAG: !{!"1C", [5 x i8*]* @_ZTV1C, i64 32} -// ITANIUM-DAG: !{!"1A", [3 x i8*]* @_ZTVZ3foovE2FA, i64 16} -// ITANIUM-DAG: !{!"[{{.*}}cfi-vcall.cpp]Z3foovE2FA", [3 x i8*]* @_ZTVZ3foovE2FA, i64 16} - -// MS-DAG: !{!"A@@", [2 x i8*]* @[[VTA]], i64 8} -// MS-DAG: !{!"B@@", [3 x i8*]* @[[VTB]], i64 8} -// MS-DAG: !{!"A@@", [2 x i8*]* @[[VTAinB]], i64 8} -// MS-DAG: !{!"A@@", [2 x i8*]* @[[VTAinC]], i64 8} -// MS-DAG: !{!"B@@", [3 x i8*]* @[[VTBinD]], i64 8} -// MS-DAG: !{!"[{{.*}}cfi-vcall.cpp]D@?A@@", [3 x i8*]* @[[VTBinD]], i64 8} -// MS-DAG: !{!"A@@", [2 x i8*]* @[[VTAinBinD]], i64 8} -// MS-DAG: !{!"A@@", [2 x i8*]* @[[VTFA]], i64 8} -// MS-DAG: !{!"[{{.*}}cfi-vcall.cpp]FA@?1??foo@@YAXXZ@", [2 x i8*]* @[[VTFA]], i64 8} +// ITANIUM-DAG: !{!"_ZTS1A", [3 x i8*]* @_ZTV1A, i64 16} +// ITANIUM-DAG: !{!"_ZTS1A", [7 x i8*]* @_ZTCN12_GLOBAL__N_11DE0_1B, i64 32} +// ITANIUM-DAG: !{!"_ZTS1B", [7 x i8*]* @_ZTCN12_GLOBAL__N_11DE0_1B, i64 32} +// ITANIUM-DAG: !{!"_ZTS1A", [9 x i8*]* @_ZTCN12_GLOBAL__N_11DE8_1C, i64 64} +// ITANIUM-DAG: !{!"_ZTS1C", [9 x i8*]* @_ZTCN12_GLOBAL__N_11DE8_1C, i64 32} +// ITANIUM-DAG: !{!"_ZTS1A", [12 x i8*]* @_ZTVN12_GLOBAL__N_11DE, i64 32} +// ITANIUM-DAG: !{!"_ZTS1B", [12 x i8*]* @_ZTVN12_GLOBAL__N_11DE, i64 32} +// ITANIUM-DAG: !{!"_ZTS1C", [12 x i8*]* @_ZTVN12_GLOBAL__N_11DE, i64 88} +// ITANIUM-DAG: !{![[DTYPE]], [12 x i8*]* @_ZTVN12_GLOBAL__N_11DE, i64 32} +// ITANIUM-DAG: !{!"_ZTS1A", [7 x i8*]* @_ZTV1B, i64 32} +// ITANIUM-DAG: !{!"_ZTS1B", [7 x i8*]* @_ZTV1B, i64 32} +// ITANIUM-DAG: !{!"_ZTS1A", [5 x i8*]* @_ZTV1C, i64 32} +// ITANIUM-DAG: !{!"_ZTS1C", [5 x i8*]* @_ZTV1C, i64 32} +// ITANIUM-DAG: !{!"_ZTS1A", [3 x i8*]* @_ZTVZ3foovE2FA, i64 16} +// ITANIUM-DAG: !{!{{[0-9]+}}, [3 x i8*]* @_ZTVZ3foovE2FA, i64 16} + +// MS-DAG: !{!"?AUA@@", [2 x i8*]* @[[VTA]], i64 8} +// MS-DAG: !{!"?AUB@@", [3 x i8*]* @[[VTB]], i64 8} +// MS-DAG: !{!"?AUA@@", [2 x i8*]* @[[VTAinB]], i64 8} +// MS-DAG: !{!"?AUA@@", [2 x i8*]* @[[VTAinC]], i64 8} +// MS-DAG: !{!"?AUB@@", [3 x i8*]* @[[VTBinD]], i64 8} +// MS-DAG: !{![[DTYPE]], [3 x i8*]* @[[VTBinD]], i64 8} +// MS-DAG: !{!"?AUA@@", [2 x i8*]* @[[VTAinBinD]], i64 8} +// MS-DAG: !{!"?AUA@@", [2 x i8*]* @[[VTFA]], i64 8} +// MS-DAG: !{!{{[0-9]+}}, [2 x i8*]* @[[VTFA]], i64 8} diff --git a/test/CodeGenCXX/const-init-cxx11.cpp b/test/CodeGenCXX/const-init-cxx11.cpp index 5127c302aa0d..99be265e2126 100644 --- a/test/CodeGenCXX/const-init-cxx11.cpp +++ b/test/CodeGenCXX/const-init-cxx11.cpp @@ -350,6 +350,7 @@ namespace VirtualMembers { virtual void f(); }; // CHECK: @_ZN14VirtualMembersL13sGlobalMemoryE = internal global { i8** } { i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN14VirtualMembers12nsMemoryImplE, i64 0, i64 2) } + __attribute__((used)) static nsMemoryImpl sGlobalMemory; template diff --git a/test/CodeGenCXX/constructor-alias.cpp b/test/CodeGenCXX/constructor-alias.cpp index 18a47775012d..8359bb90a051 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*)* @_ZN1BC2Ev +// CHECK: @_ZN1BC1Ev = 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 893e3a079ff2..9d47d1706bbe 100644 --- a/test/CodeGenCXX/constructor-destructor-return-this.cpp +++ b/test/CodeGenCXX/constructor-destructor-return-this.cpp @@ -1,6 +1,8 @@ //RUN: %clang_cc1 %s -emit-llvm -o - -triple=i686-unknown-linux | FileCheck --check-prefix=CHECKGEN %s //RUN: %clang_cc1 %s -emit-llvm -o - -triple=thumbv7-apple-ios6.0 -target-abi apcs-gnu | FileCheck --check-prefix=CHECKARM %s //RUN: %clang_cc1 %s -emit-llvm -o - -triple=thumbv7-apple-ios5.0 -target-abi apcs-gnu | FileCheck --check-prefix=CHECKIOS5 %s +//RUN: %clang_cc1 %s -emit-llvm -o - -triple=wasm32-unknown-unknown \ +//RUN: | FileCheck --check-prefix=CHECKARM %s //RUN: %clang_cc1 %s -emit-llvm -o - -triple=i386-pc-win32 -fno-rtti | FileCheck --check-prefix=CHECKMS %s // FIXME: these tests crash on the bots when run with -triple=x86_64-pc-win32 diff --git a/test/CodeGenCXX/cp-blocks-linetables.cpp b/test/CodeGenCXX/cp-blocks-linetables.cpp index d5dd46cbe0d0..46ab16e95986 100644 --- a/test/CodeGenCXX/cp-blocks-linetables.cpp +++ b/test/CodeGenCXX/cp-blocks-linetables.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fblocks -g -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -fblocks -debug-info-kind=limited -emit-llvm %s -o - | FileCheck %s // Ensure that we generate a line table entry for the block cleanup. // CHECK: define {{.*}} @__main_block_invoke // CHECK: _NSConcreteStackBlock diff --git a/test/CodeGenCXX/crash.cpp b/test/CodeGenCXX/crash.cpp index 2785d8d74bc8..d12c021a6dcc 100644 --- a/test/CodeGenCXX/crash.cpp +++ b/test/CodeGenCXX/crash.cpp @@ -1,6 +1,5 @@ -// XFAIL: hexagon // RUN: %clang_cc1 %s -std=c++11 -emit-llvm-only -// RUN: %clang_cc1 -emit-obj -o %t -gline-tables-only -std=c++11 %s +// RUN: %clang_cc1 -emit-obj -o %t -debug-info-kind=line-tables-only -std=c++11 %s // CHECK that we don't crash. // PR11676's example is ill-formed: diff --git a/test/CodeGenCXX/ctor-dtor-alias.cpp b/test/CodeGenCXX/ctor-dtor-alias.cpp index a7bafb830d1a..018e958aab53 100644 --- a/test/CodeGenCXX/ctor-dtor-alias.cpp +++ b/test/CodeGenCXX/ctor-dtor-alias.cpp @@ -15,7 +15,7 @@ namespace test1 { // weak_odr constructors and destructors. // CHECK1: @_ZN5test16foobarIvEC1Ev = weak_odr alias void {{.*}} @_ZN5test16foobarIvEC2Ev -// CHECK1: @_ZN5test16foobarIvED1Ev = weak_odr alias void (%"struct.test1::foobar"*)* @_ZN5test16foobarIvED2Ev +// CHECK1: @_ZN5test16foobarIvED1Ev = weak_odr 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) diff --git a/test/CodeGenCXX/ctor-globalopt.cpp b/test/CodeGenCXX/ctor-globalopt.cpp index bcab60916aec..0951278d3178 100644 --- a/test/CodeGenCXX/ctor-globalopt.cpp +++ b/test/CodeGenCXX/ctor-globalopt.cpp @@ -1,10 +1,10 @@ // RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck %s -// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -o - %s -O1 | FileCheck %s --check-prefix=O1 +// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -o - %s -O2 | opt - -S -globalopt -o - | FileCheck %s --check-prefix=O1 // RUN: %clang_cc1 -triple %ms_abi_triple -emit-llvm -o - %s | FileCheck %s -// RUN: %clang_cc1 -triple %ms_abi_triple -emit-llvm -o - %s -O1 | FileCheck %s --check-prefix=O1 +// RUN: %clang_cc1 -triple %ms_abi_triple -emit-llvm -o - %s -O2 | opt - -S -globalopt -o - | FileCheck %s --check-prefix=O1 // Check that GlobalOpt can eliminate static constructors for simple implicit -// constructors. This is a targetted integration test to make sure that LLVM's +// constructors. This is a targeted integration test to make sure that LLVM's // optimizers are able to process Clang's IR. GlobalOpt in particular is // sensitive to the casts we emit. diff --git a/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp b/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp index 6d5d3971bd74..311edaabb5db 100644 --- a/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp +++ b/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp @@ -502,7 +502,7 @@ namespace B19773010 { } void f2() { // CHECK-LABEL: @_ZN9B197730102f2Ev - // CHECK: 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 8 + // CHECK: 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 static std::initializer_list> a, p[2] = {a, {{"", ENUM_CONSTANT}}}; } diff --git a/test/CodeGenCXX/cxx11-initializer-array-new.cpp b/test/CodeGenCXX/cxx11-initializer-array-new.cpp index 2beb44ecf3b2..c662190ff386 100644 --- a/test/CodeGenCXX/cxx11-initializer-array-new.cpp +++ b/test/CodeGenCXX/cxx11-initializer-array-new.cpp @@ -28,7 +28,7 @@ void *p = new S[2][3]{ { 1, 2, 3 }, { 4, 5, 6 } }; // // { 4, 5, 6 } // -// CHECK: %[[S_1:.*]] = getelementptr inbounds [3 x %[[S]]], [3 x %[[S]]]* %[[S_0]], i32 1 +// CHECK: %[[S_1:.*]] = getelementptr inbounds [3 x %[[S]]], [3 x %[[S]]]* %[[S_0]], i64 1 // // CHECK: %[[S_1_0:.*]] = getelementptr inbounds [3 x %[[S]]], [3 x %[[S]]]* %[[S_1]], i64 0, i64 0 // CHECK: call void @_ZN1SC1Ei(%[[S]]* %[[S_1_0]], i32 4) @@ -72,7 +72,7 @@ void *q = new S[n][3]{ { 1, 2, 3 }, { 4, 5, 6 } }; // // { 4, 5, 6 } // -// CHECK: %[[S_1:.*]] = getelementptr inbounds [3 x %[[S]]], [3 x %[[S]]]* %[[S_0]], i32 1 +// CHECK: %[[S_1:.*]] = getelementptr inbounds [3 x %[[S]]], [3 x %[[S]]]* %[[S_0]], i64 1 // // CHECK: %[[S_1_0:.*]] = getelementptr inbounds [3 x %[[S]]], [3 x %[[S]]]* %[[S_1]], i64 0, i64 0 // CHECK: call void @_ZN1SC1Ei(%[[S]]* %[[S_1_0]], i32 4) @@ -83,7 +83,7 @@ void *q = new S[n][3]{ { 1, 2, 3 }, { 4, 5, 6 } }; // // And the rest. // -// CHECK: %[[S_2:.*]] = getelementptr inbounds [3 x %[[S]]], [3 x %[[S]]]* %[[S_1]], i32 1 +// CHECK: %[[S_2:.*]] = getelementptr inbounds [3 x %[[S]]], [3 x %[[S]]]* %[[S_1]], i64 1 // CHECK: %[[S_2_AS_S:.*]] = bitcast [3 x %[[S]]]* %[[S_2]] to %[[S]]* // // CHECK: %[[REST:.*]] = sub i64 %[[ELTS]], 6 @@ -135,7 +135,7 @@ void *r = new T[n][3]{ { 1, 2, 3 }, { 4, 5, 6 } }; // // { 4, 5, 6 } // -// CHECK: %[[T_1:.*]] = getelementptr inbounds [3 x %[[T]]], [3 x %[[T]]]* %[[T_0]], i32 1 +// CHECK: %[[T_1:.*]] = getelementptr inbounds [3 x %[[T]]], [3 x %[[T]]]* %[[T_0]], i64 1 // // CHECK: %[[T_1_0:.*]] = getelementptr inbounds [3 x %[[T]]], [3 x %[[T]]]* %[[T_1]], i64 0, i64 0 // CHECK: %[[T_1_0_0:.*]] = getelementptr inbounds %[[T]], %[[T]]* %[[T_1_0]], i32 0, i32 0 @@ -149,7 +149,7 @@ void *r = new T[n][3]{ { 1, 2, 3 }, { 4, 5, 6 } }; // // And the rest gets memset to 0. // -// CHECK: %[[T_2:.*]] = getelementptr inbounds [3 x %[[T]]], [3 x %[[T]]]* %[[T_1]], i32 1 +// CHECK: %[[T_2:.*]] = getelementptr inbounds [3 x %[[T]]], [3 x %[[T]]]* %[[T_1]], i64 1 // CHECK: %[[T_2_AS_T:.*]] = bitcast [3 x %[[T]]]* %[[T_2]] to %[[T]]* // // CHECK: %[[SIZE:.*]] = sub i64 %{{.*}}, 24 diff --git a/test/CodeGenCXX/cxx11-thread-local-reference.cpp b/test/CodeGenCXX/cxx11-thread-local-reference.cpp index c3e165a41625..8b2ac5eed800 100644 --- a/test/CodeGenCXX/cxx11-thread-local-reference.cpp +++ b/test/CodeGenCXX/cxx11-thread-local-reference.cpp @@ -1,11 +1,14 @@ -// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s +// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck --check-prefix=CHECK --check-prefix=LINUX %s +// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple x86_64-apple-darwin12 | FileCheck --check-prefix=CHECK --check-prefix=DARWIN %s int &f(); -// CHECK: @r = thread_local global i32* null +// LINUX: @r = thread_local global i32* null +// DARWIN: @r = internal thread_local global i32* null thread_local int &r = f(); -// CHECK: @_ZTH1r = alias void ()* @__tls_init +// LINUX: @_ZTH1r = alias void (), void ()* @__tls_init +// DARWIN: @_ZTH1r = internal alias void (), void ()* @__tls_init int &g() { return r; } @@ -14,13 +17,17 @@ int &g() { return r; } // CHECK: store i32* %{{.*}}, i32** @r, align 8 // CHECK-LABEL: define dereferenceable({{[0-9]+}}) i32* @_Z1gv() -// CHECK: call i32* @_ZTW1r() +// LINUX: call i32* @_ZTW1r() +// DARWIN: call cxx_fast_tlscc i32* @_ZTW1r() // CHECK: ret i32* %{{.*}} -// CHECK: define weak_odr hidden i32* @_ZTW1r() { +// LINUX: define weak_odr hidden i32* @_ZTW1r() { +// DARWIN: define cxx_fast_tlscc i32* @_ZTW1r() [[ATTR:#[0-9]+]] { // CHECK: call void @_ZTH1r() // CHECK: load i32*, i32** @r, align 8 // CHECK: ret i32* %{{.*}} // CHECK-LABEL: define internal void @__tls_init() // CHECK: call void @[[R_INIT]]() + +// DARWIN: attributes [[ATTR]] = { nounwind } diff --git a/test/CodeGenCXX/cxx11-thread-local.cpp b/test/CodeGenCXX/cxx11-thread-local.cpp index 9b16319088c0..b5bcc5e23ecd 100644 --- a/test/CodeGenCXX/cxx11-thread-local.cpp +++ b/test/CodeGenCXX/cxx11-thread-local.cpp @@ -1,9 +1,13 @@ -// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s +// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck --check-prefix=CHECK --check-prefix=LINUX %s +// RUN: %clang_cc1 -std=c++11 -femulated-tls -emit-llvm %s -o - \ +// RUN: -triple x86_64-linux-gnu 2>&1 | FileCheck --check-prefix=CHECK --check-prefix=LINUX %s +// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple x86_64-apple-darwin12 | FileCheck --check-prefix=CHECK --check-prefix=DARWIN %s int f(); int g(); -// CHECK: @a = thread_local global i32 0 +// LINUX: @a = thread_local global i32 0 +// DARWIN: @a = internal thread_local global i32 0 thread_local int a = f(); extern thread_local int b; // CHECK: @c = global i32 0 @@ -12,9 +16,22 @@ int c = b; static thread_local int d = g(); struct U { static thread_local int m; }; -// CHECK: @_ZN1U1mE = thread_local global i32 0 +// LINUX: @_ZN1U1mE = thread_local global i32 0 +// DARWIN: @_ZN1U1mE = internal thread_local global i32 0 thread_local int U::m = f(); +namespace MismatchedInitType { + // Check that we don't crash here when we're forced to create a new global + // variable (with a different type) when we add the initializer. + union U { + int a; + float f; + constexpr U() : f(0.0) {} + }; + static thread_local U u; + void *p = &u; +} + template struct V { static thread_local int m; }; template thread_local int V::m = g(); @@ -43,10 +60,12 @@ int e = V::m; // CHECK: @llvm.global_ctors = appending global {{.*}} @[[GLOBAL_INIT:[^ ]*]] -// CHECK: @_ZTH1a = alias void ()* @__tls_init -// CHECK: @_ZTHL1d = internal alias void ()* @__tls_init -// CHECK: @_ZTHN1U1mE = alias void ()* @__tls_init -// CHECK: @_ZTHN1VIiE1mE = linkonce_odr alias void ()* @__tls_init +// LINUX: @_ZTH1a = alias void (), void ()* @__tls_init +// DARWIN: @_ZTH1a = internal alias void (), void ()* @__tls_init +// CHECK: @_ZTHL1d = internal alias void (), void ()* @__tls_init +// LINUX: @_ZTHN1U1mE = alias void (), void ()* @__tls_init +// DARWIN: @_ZTHN1U1mE = internal alias void (), void ()* @__tls_init +// CHECK: @_ZTHN1VIiE1mE = linkonce_odr alias void (), void ()* @__tls_init // Individual variable initialization functions: @@ -72,17 +91,20 @@ int f() { } // CHECK: define {{.*}} @[[C_INIT:.*]]() -// CHECK: call i32* @_ZTW1b() +// LINUX: call i32* @_ZTW1b() +// DARWIN: call cxx_fast_tlscc i32* @_ZTW1b() // CHECK-NEXT: load i32, i32* %{{.*}}, align 4 // CHECK-NEXT: store i32 %{{.*}}, i32* @c, align 4 -// CHECK-LABEL: define weak_odr hidden i32* @_ZTW1b() -// CHECK: br i1 icmp ne (void ()* @_ZTH1b, void ()* null), +// LINUX-LABEL: define weak_odr hidden i32* @_ZTW1b() +// LINUX: br i1 icmp ne (void ()* @_ZTH1b, void ()* null), // not null: -// CHECK: call void @_ZTH1b() -// CHECK: br label +// LINUX: call void @_ZTH1b() +// LINUX: br label // finally: -// CHECK: ret i32* @b +// LINUX: ret i32* @b +// DARWIN-LABEL: declare cxx_fast_tlscc i32* @_ZTW1b() +// There is no definition of the thread wrapper on Darwin for external TLV. // CHECK: define {{.*}} @[[D_INIT:.*]]() // CHECK: call i32 @_Z1gv() @@ -93,11 +115,13 @@ int f() { // CHECK-NEXT: store i32 %{{.*}}, i32* @_ZN1U1mE, align 4 // CHECK: define {{.*}} @[[E_INIT:.*]]() -// CHECK: call i32* @_ZTWN1VIiE1mE() +// LINUX: call i32* @_ZTWN1VIiE1mE() +// DARWIN: call cxx_fast_tlscc i32* @_ZTWN1VIiE1mE() // CHECK-NEXT: load i32, i32* %{{.*}}, align 4 // CHECK-NEXT: store i32 %{{.*}}, i32* @e, align 4 -// CHECK-LABEL: define weak_odr hidden i32* @_ZTWN1VIiE1mE() +// LINUX-LABEL: define weak_odr hidden i32* @_ZTWN1VIiE1mE() +// DARWIN-LABEL: define weak_odr hidden cxx_fast_tlscc i32* @_ZTWN1VIiE1mE() // CHECK: call void @_ZTHN1VIiE1mE() // CHECK: ret i32* @_ZN1VIiE1mE @@ -109,24 +133,28 @@ struct T { ~T(); }; void tls_dtor() { // CHECK: load i8, i8* @_ZGVZ8tls_dtorvE1s // CHECK: call void @_ZN1SC1Ev(%struct.S* @_ZZ8tls_dtorvE1s) - // CHECK: call i32 @__cxa_thread_atexit({{.*}}@_ZN1SD1Ev {{.*}} @_ZZ8tls_dtorvE1s{{.*}} @__dso_handle + // LINUX: call i32 @__cxa_thread_atexit({{.*}}@_ZN1SD1Ev {{.*}} @_ZZ8tls_dtorvE1s{{.*}} @__dso_handle + // DARWIN: call i32 @_tlv_atexit({{.*}}@_ZN1SD1Ev {{.*}} @_ZZ8tls_dtorvE1s{{.*}} @__dso_handle // CHECK: store i8 1, i8* @_ZGVZ8tls_dtorvE1s static thread_local S s; // CHECK: load i8, i8* @_ZGVZ8tls_dtorvE1t // CHECK-NOT: _ZN1T - // CHECK: call i32 @__cxa_thread_atexit({{.*}}@_ZN1TD1Ev {{.*}}@_ZZ8tls_dtorvE1t{{.*}} @__dso_handle + // LINUX: call i32 @__cxa_thread_atexit({{.*}}@_ZN1TD1Ev {{.*}}@_ZZ8tls_dtorvE1t{{.*}} @__dso_handle + // DARWIN: call i32 @_tlv_atexit({{.*}}@_ZN1TD1Ev {{.*}}@_ZZ8tls_dtorvE1t{{.*}} @__dso_handle // CHECK: store i8 1, i8* @_ZGVZ8tls_dtorvE1t static thread_local T t; // CHECK: load i8, i8* @_ZGVZ8tls_dtorvE1u // CHECK: call void @_ZN1SC1Ev(%struct.S* @_ZGRZ8tls_dtorvE1u_) - // CHECK: call i32 @__cxa_thread_atexit({{.*}}@_ZN1SD1Ev {{.*}} @_ZGRZ8tls_dtorvE1u_{{.*}} @__dso_handle + // LINUX: call i32 @__cxa_thread_atexit({{.*}}@_ZN1SD1Ev {{.*}} @_ZGRZ8tls_dtorvE1u_{{.*}} @__dso_handle + // DARWIN: call i32 @_tlv_atexit({{.*}}@_ZN1SD1Ev {{.*}} @_ZGRZ8tls_dtorvE1u_{{.*}} @__dso_handle // CHECK: store i8 1, i8* @_ZGVZ8tls_dtorvE1u static thread_local const S &u = S(); } -// CHECK: declare i32 @__cxa_thread_atexit(void (i8*)*, i8*, i8*) +// LINUX: declare i32 @__cxa_thread_atexit(void (i8*)*, i8*, i8*) +// DARWIN: declare i32 @_tlv_atexit(void (i8*)*, i8*, i8*) // CHECK: define {{.*}} @_Z7PR15991v( int PR15991() { @@ -141,7 +169,8 @@ struct PR19254 { }; // CHECK: define {{.*}} @_ZN7PR192541fEv( int PR19254::f() { - // CHECK: call void @_ZTHN7PR192541nE( + // LINUX: call void @_ZTHN7PR192541nE( + // DARWIN: call cxx_fast_tlscc i32* @_ZTWN7PR192541nE( return this->n; } @@ -151,7 +180,8 @@ thread_local int anon_i{1}; void set_anon_i() { anon_i = 2; } -// CHECK-LABEL: define internal i32* @_ZTWN12_GLOBAL__N_16anon_iE() +// 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 {{.*}} @[[V_M_INIT:.*]]() // CHECK: load i8, i8* bitcast (i64* @_ZGVN1VIiE1mE to i8*) @@ -171,28 +201,31 @@ void set_anon_i() { // CHECK: define {{.*}}@__tls_init() // CHECK: load i8, i8* @__tls_guard // CHECK: %[[NEED_TLS_INIT:.*]] = icmp eq i8 %{{.*}}, 0 -// CHECK: store i8 1, i8* @__tls_guard // CHECK: br i1 %[[NEED_TLS_INIT]], // init: +// CHECK: store i8 1, i8* @__tls_guard // CHECK: call void @[[A_INIT]]() // CHECK: call void @[[D_INIT]]() // CHECK: call void @[[U_M_INIT]]() // CHECK: call void @[[V_M_INIT]]() -// CHECK: define weak_odr hidden i32* @_ZTW1a() { +// LIUNX: define weak_odr hidden i32* @_ZTW1a() { +// DARWIN: define cxx_fast_tlscc i32* @_ZTW1a() // CHECK: call void @_ZTH1a() // CHECK: ret i32* @a // CHECK: } -// CHECK: declare extern_weak void @_ZTH1b() +// LINUX: declare extern_weak void @_ZTH1b() -// CHECK-LABEL: define internal i32* @_ZTWL1d() +// LINUX-LABEL: define internal i32* @_ZTWL1d() +// DARWIN-LABEL: define internal cxx_fast_tlscc i32* @_ZTWL1d() // CHECK: call void @_ZTHL1d() // CHECK: ret i32* @_ZL1d -// CHECK-LABEL: define weak_odr hidden i32* @_ZTWN1U1mE() +// LINUX-LABEL: define weak_odr hidden i32* @_ZTWN1U1mE() +// DARWIN-LABEL: define cxx_fast_tlscc i32* @_ZTWN1U1mE() // CHECK: call void @_ZTHN1U1mE() // CHECK: ret i32* @_ZN1U1mE diff --git a/test/CodeGenCXX/debug-info-access.cpp b/test/CodeGenCXX/debug-info-access.cpp index 86237b3bc328..1699bab96104 100644 --- a/test/CodeGenCXX/debug-info-access.cpp +++ b/test/CodeGenCXX/debug-info-access.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -g -triple %itanium_abi_triple %s -o - | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited -triple %itanium_abi_triple %s -o - | FileCheck %s // Test the various accessibility flags in the debug info. struct A { // CHECK-DAG: !DISubprogram(name: "pub_default",{{.*}} line: [[@LINE+1]],{{.*}} flags: DIFlagPrototyped, diff --git a/test/CodeGenCXX/debug-info-anon-namespace.cpp b/test/CodeGenCXX/debug-info-anon-namespace.cpp new file mode 100644 index 000000000000..4e3e08af2b74 --- /dev/null +++ b/test/CodeGenCXX/debug-info-anon-namespace.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited -triple x86_64-scei-ps4 -O0 %s -o - | FileCheck --check-prefix=PS4 %s +// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited -triple x86_64-unknown-linux-gnu -O0 %s -o - | FileCheck --check-prefix=NON-PS4 %s + +namespace +{ + int a = 5; +} +int *b = &a; + +namespace +{ + namespace { + int a1 = 5; + } + int a2 = 7; +} +int *b1 = &a1; +int *b2 = &a2; + + +// PS4: [[NS:![0-9]+]] = !DINamespace +// PS4: [[NS2:![0-9]+]] = !DINamespace +// PS4: !DIImportedEntity(tag: DW_TAG_imported_module, scope: !0, entity: [[NS]]) +// PS4: !DIImportedEntity(tag: DW_TAG_imported_module, scope: [[NS]], entity: [[NS2]], line: {{[0-9]+}}) +// NON-PS4-NOT: !DIImportedEntity + diff --git a/test/CodeGenCXX/debug-info-anon-union-vars.cpp b/test/CodeGenCXX/debug-info-anon-union-vars.cpp index ad3b6d4c6234..5b0370eb749d 100644 --- a/test/CodeGenCXX/debug-info-anon-union-vars.cpp +++ b/test/CodeGenCXX/debug-info-anon-union-vars.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -gdwarf-4 -triple x86_64-linux-gnu %s -o - | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited -triple x86_64-linux-gnu %s -o - | FileCheck %s // Make sure that we emit a global variable for each of the members of the // anonymous union. @@ -29,13 +29,30 @@ void foo() { i = 8; } +// A funky reinterpret cast idiom that we used to crash on. +template +unsigned char *buildBytes(const T v) { + static union { + unsigned char result[sizeof(T)]; + T value; + }; + value = v; + return result; +} + +void instantiate(int x) { + buildBytes(x); +} + // CHECK: [[FILE:.*]] = !DIFile(filename: "{{.*}}debug-info-anon-union-vars.cpp", // CHECK: !DIGlobalVariable(name: "c",{{.*}} file: [[FILE]], line: 6,{{.*}} isLocal: true, isDefinition: true // CHECK: !DIGlobalVariable(name: "d",{{.*}} file: [[FILE]], line: 6,{{.*}} isLocal: true, isDefinition: true // CHECK: !DIGlobalVariable(name: "a",{{.*}} file: [[FILE]], line: 6,{{.*}} isLocal: true, isDefinition: true // CHECK: !DIGlobalVariable(name: "b",{{.*}} file: [[FILE]], line: 6,{{.*}} isLocal: true, isDefinition: true -// CHECK: !DILocalVariable(tag: DW_TAG_auto_variable, name: "i", {{.*}}, flags: DIFlagArtificial -// CHECK: !DILocalVariable(tag: DW_TAG_auto_variable, name: "c", {{.*}}, flags: DIFlagArtificial +// CHECK: !DIGlobalVariable(name: "result", {{.*}} isLocal: false, isDefinition: true +// CHECK: !DIGlobalVariable(name: "value", {{.*}} isLocal: false, isDefinition: true +// CHECK: !DILocalVariable(name: "i", {{.*}}, flags: DIFlagArtificial +// CHECK: !DILocalVariable(name: "c", {{.*}}, flags: DIFlagArtificial // CHECK: !DILocalVariable( // CHECK-NOT: name: // CHECK: type: ![[UNION:[0-9]+]] diff --git a/test/CodeGenCXX/debug-info-artificial-arg.cpp b/test/CodeGenCXX/debug-info-artificial-arg.cpp index dc3ac8a45406..c840df672aa0 100644 --- a/test/CodeGenCXX/debug-info-artificial-arg.cpp +++ b/test/CodeGenCXX/debug-info-artificial-arg.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -g -triple x86_64-apple-darwin %s -o - | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited -triple x86_64-apple-darwin %s -o - | FileCheck %s template class B { public: diff --git a/test/CodeGenCXX/debug-info-blocks.cpp b/test/CodeGenCXX/debug-info-blocks.cpp index 7762726dc77f..ed0d659eeae1 100644 --- a/test/CodeGenCXX/debug-info-blocks.cpp +++ b/test/CodeGenCXX/debug-info-blocks.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -gline-tables-only -fblocks -S -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -debug-info-kind=line-tables-only -fblocks -S -emit-llvm -o - | FileCheck %s struct A { A(); diff --git a/test/CodeGenCXX/debug-info-char16.cpp b/test/CodeGenCXX/debug-info-char16.cpp index 912da6f86e5c..83ffea6f791a 100644 --- a/test/CodeGenCXX/debug-info-char16.cpp +++ b/test/CodeGenCXX/debug-info-char16.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -std=c++11 -g %s -o -| FileCheck %s +// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -std=c++11 -debug-info-kind=limited %s -o -| FileCheck %s // 16 is DW_ATE_UTF (0x10) encoding attribute. char16_t char_a = u'h'; diff --git a/test/CodeGenCXX/debug-info-class-nolimit.cpp b/test/CodeGenCXX/debug-info-class-nolimit.cpp index 11d1792e6f33..ce47f9fa495a 100644 --- a/test/CodeGenCXX/debug-info-class-nolimit.cpp +++ b/test/CodeGenCXX/debug-info-class-nolimit.cpp @@ -1,6 +1,7 @@ -// RUN: %clang_cc1 -triple x86_64-unk-unk -fstandalone-debug -o - -emit-llvm -g %s | FileCheck %s -// On Darwin, this should be the default: -// RUN: %clang_cc1 -triple x86_64-apple-darwin -o - -emit-llvm -g %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-unk-unk -debug-info-kind=standalone -o - -emit-llvm %s | FileCheck %s +// On Darwin, "full" debug info is the default, so really these tests are +// identical, as cc1 no longer chooses the effective value of DebugInfoKind. +// RUN: %clang_cc1 -triple x86_64-apple-darwin -debug-info-kind=standalone -o - -emit-llvm %s | FileCheck %s namespace rdar14101097_1 { // see also PR16214 // Check that we emit debug info for the definition of a struct if the @@ -33,4 +34,3 @@ void bar() { struct foo { }; } - diff --git a/test/CodeGenCXX/debug-info-codeview-display-name.cpp b/test/CodeGenCXX/debug-info-codeview-display-name.cpp new file mode 100644 index 000000000000..1d0300c76c01 --- /dev/null +++ b/test/CodeGenCXX/debug-info-codeview-display-name.cpp @@ -0,0 +1,73 @@ +// RUN: %clang_cc1 -fblocks -debug-info-kind=limited -gcodeview -emit-llvm %s -o - -triple=x86_64-pc-win32 -std=c++98 | \ +// RUN: grep 'DISubprogram' | sed -e 's/.*name: "\([^"]*\)".*/"\1"/' | FileCheck %s + +void freefunc() { } +// CHECK-DAG: "freefunc" + +namespace N { + int b() { return 0; } +// CHECK-DAG: "N::b" + namespace { void func() { } } +// CHECK-DAG: "N::`anonymous namespace'::func +} + +void _c(void) { + N::func(); +} +// CHECK-DAG: "_c" + +struct foo { + int operator+(int); + foo(){} +// CHECK-DAG: "foo::foo" + + ~foo(){} +// CHECK-DAG: "foo::~foo" + + foo(int i){} +// CHECK-DAG: "foo::foo" + + foo(char *q){} +// CHECK-DAG: "foo::foo" + + static foo* static_method() { return 0; } +// CHECK-DAG: "foo::static_method" + +}; + +void use_foo() { + foo f1, f2(1), f3((char*)0); + foo::static_method(); +} + +// CHECK-DAG: "foo::operator+" +int foo::operator+(int a) { return a; } + +// PR17371 +struct OverloadedNewDelete { + // __cdecl + void *operator new(__SIZE_TYPE__); + void *operator new[](__SIZE_TYPE__); + void operator delete(void *); + void operator delete[](void *); + // __thiscall + int operator+(int); +}; + +void *OverloadedNewDelete::operator new(__SIZE_TYPE__ s) { return 0; } +void *OverloadedNewDelete::operator new[](__SIZE_TYPE__ s) { return 0; } +void OverloadedNewDelete::operator delete(void *) { } +void OverloadedNewDelete::operator delete[](void *) { } +int OverloadedNewDelete::operator+(int x) { return x; }; + +// CHECK-DAG: "OverloadedNewDelete::operator new" +// CHECK-DAG: "OverloadedNewDelete::operator new[]" +// CHECK-DAG: "OverloadedNewDelete::operator delete" +// CHECK-DAG: "OverloadedNewDelete::operator delete[]" +// CHECK-DAG: "OverloadedNewDelete::operator+" + +template +void fn_tmpl() {} + +template void fn_tmpl(); +// CHECK-DAG: "fn_tmpl" diff --git a/test/CodeGenCXX/debug-info-context.cpp b/test/CodeGenCXX/debug-info-context.cpp index d6d44a158c3b..1f7fa046752b 100644 --- a/test/CodeGenCXX/debug-info-context.cpp +++ b/test/CodeGenCXX/debug-info-context.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -g -triple x86_64-apple-darwin %s -o - | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited -triple x86_64-apple-darwin %s -o - | FileCheck %s // PR11345 class locale { diff --git a/test/CodeGenCXX/debug-info-cxx0x.cpp b/test/CodeGenCXX/debug-info-cxx0x.cpp index 9d303755be0e..4c31f60c0d96 100644 --- a/test/CodeGenCXX/debug-info-cxx0x.cpp +++ b/test/CodeGenCXX/debug-info-cxx0x.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm-only -std=c++11 -g %s +// RUN: %clang_cc1 -emit-llvm-only -std=c++11 -debug-info-kind=limited %s namespace PR9414 { int f() { diff --git a/test/CodeGenCXX/debug-info-cxx1y.cpp b/test/CodeGenCXX/debug-info-cxx1y.cpp index 026be3d52232..37f95959911c 100644 --- a/test/CodeGenCXX/debug-info-cxx1y.cpp +++ b/test/CodeGenCXX/debug-info-cxx1y.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm-only -std=c++14 -emit-llvm -g %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm-only -std=c++14 -emit-llvm -debug-info-kind=limited %s -o - | FileCheck %s // CHECK: [[EMPTY:![0-9]*]] = !{} // CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "foo", diff --git a/test/CodeGenCXX/debug-info-decl-nested.cpp b/test/CodeGenCXX/debug-info-decl-nested.cpp index 2c3524175392..feab1d709094 100644 --- a/test/CodeGenCXX/debug-info-decl-nested.cpp +++ b/test/CodeGenCXX/debug-info-decl-nested.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++11 -g -emit-llvm -g -triple x86_64-apple-darwin %s -o %t +// RUN: %clang_cc1 -std=c++11 -debug-info-kind=standalone -emit-llvm -triple x86_64-apple-darwin %s -o %t // RUN: cat %t | FileCheck %s -check-prefix=CHECK0 // RUN: cat %t | FileCheck %s -check-prefix=CHECK1 // RUN: cat %t | FileCheck %s -check-prefix=CHECK2 diff --git a/test/CodeGenCXX/debug-info-determinism.cpp b/test/CodeGenCXX/debug-info-determinism.cpp index a96a14e9edcd..ea88b8042a1d 100644 --- a/test/CodeGenCXX/debug-info-determinism.cpp +++ b/test/CodeGenCXX/debug-info-determinism.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -S -emit-llvm -g -o %t1.ll %s -// RUN: %clang_cc1 -S -emit-llvm -g -o %t2.ll %s +// RUN: %clang_cc1 -S -emit-llvm -debug-info-kind=limited -o %t1.ll %s +// RUN: %clang_cc1 -S -emit-llvm -debug-info-kind=limited -o %t2.ll %s // RUN: diff %t1.ll %t2.ll template struct C { diff --git a/test/CodeGenCXX/debug-info-dup-fwd-decl.cpp b/test/CodeGenCXX/debug-info-dup-fwd-decl.cpp index db9d2e9f491d..f7a2cfe7bae6 100644 --- a/test/CodeGenCXX/debug-info-dup-fwd-decl.cpp +++ b/test/CodeGenCXX/debug-info-dup-fwd-decl.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -g -triple x86_64-apple-darwin -fstandalone-debug %s -o - | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -debug-info-kind=standalone -triple x86_64-apple-darwin %s -o - | FileCheck %s class Test { diff --git a/test/CodeGenCXX/debug-info-enum-class.cpp b/test/CodeGenCXX/debug-info-enum-class.cpp index ded18bffe377..71e6e2b2574e 100644 --- a/test/CodeGenCXX/debug-info-enum-class.cpp +++ b/test/CodeGenCXX/debug-info-enum-class.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -g -triple x86_64-apple-darwin -std=c++11 %s -o - | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited -triple x86_64-apple-darwin -std=c++11 %s -o - | FileCheck %s enum class A { A1=1 }; // underlying type is int by default enum class B: unsigned long { B1=1 }; // underlying type is unsigned long diff --git a/test/CodeGenCXX/debug-info-enum.cpp b/test/CodeGenCXX/debug-info-enum.cpp index 613ffef7ddb2..8f54f9d71224 100644 --- a/test/CodeGenCXX/debug-info-enum.cpp +++ b/test/CodeGenCXX/debug-info-enum.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -g %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -debug-info-kind=limited %s -o - | FileCheck %s // CHECK: !DICompileUnit( // CHECK-SAME: enums: [[ENUMS:![0-9]*]] diff --git a/test/CodeGenCXX/debug-info-explicit-cast.cpp b/test/CodeGenCXX/debug-info-explicit-cast.cpp new file mode 100644 index 000000000000..028a7760d8b9 --- /dev/null +++ b/test/CodeGenCXX/debug-info-explicit-cast.cpp @@ -0,0 +1,46 @@ +// RUN: %clangxx -c -target %itanium_abi_triple -g %s -emit-llvm -S -o - | FileCheck %s +// RUN: %clangxx -c -target %ms_abi_triple -g %s -emit-llvm -S -o - | FileCheck %s + +struct Foo { + int A; + Foo() : A(1){}; +}; + +struct Bar { + int B; + Bar() : B(2){}; +}; + +struct Baz { + int C; + Baz() : C(3){}; +}; + +struct Qux { + int d() { return 4; } + Qux() {}; +}; + +struct Quux { + int E; + Quux() : E(5){}; +}; + +typedef int(Qux::*TD)(); +typedef int(Qux::*TD1)(); +int Val = reinterpret_cast(0)->C; +int main() { + Bar *PB = new Bar; + TD d = &Qux::d; + (void)reinterpret_cast(d); + + return reinterpret_cast(PB)->A + reinterpret_cast(0)->E; +} + +// CHECK-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "Foo", +// CHECK-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "Bar", +// CHECK-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "Baz", +// CHECK-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "Qux", +// CHECK-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "Quux", +// CHECK-DAG: !DIDerivedType(tag: DW_TAG_typedef, name: "TD", +// CHECK-DAG: !DIDerivedType(tag: DW_TAG_typedef, name: "TD1", diff --git a/test/CodeGenCXX/debug-info-flex-member.cpp b/test/CodeGenCXX/debug-info-flex-member.cpp index afc9d250c92b..8dcdaeb935d0 100644 --- a/test/CodeGenCXX/debug-info-flex-member.cpp +++ b/test/CodeGenCXX/debug-info-flex-member.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -g -triple x86_64-apple-darwin %s -o - | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited -triple x86_64-apple-darwin %s -o - | FileCheck %s // CHECK: !DISubrange(count: -1) diff --git a/test/CodeGenCXX/debug-info-function-context.cpp b/test/CodeGenCXX/debug-info-function-context.cpp index 9ae96112b57a..24f9f1bda639 100644 --- a/test/CodeGenCXX/debug-info-function-context.cpp +++ b/test/CodeGenCXX/debug-info-function-context.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -g -triple x86_64-pc-linux-gnu %s -o - | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited -triple x86_64-pc-linux-gnu %s -o - | FileCheck %s struct C { void member_function(); diff --git a/test/CodeGenCXX/debug-info-fwd-ref.cpp b/test/CodeGenCXX/debug-info-fwd-ref.cpp index 247d36411cdd..219e7963797d 100644 --- a/test/CodeGenCXX/debug-info-fwd-ref.cpp +++ b/test/CodeGenCXX/debug-info-fwd-ref.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -g -triple x86_64-apple-darwin %s -o - | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited -triple x86_64-apple-darwin %s -o - | FileCheck %s struct baz { int h; diff --git a/test/CodeGenCXX/debug-info-gline-tables-only.cpp b/test/CodeGenCXX/debug-info-gline-tables-only.cpp index b766c73cc22a..d98b27872d62 100644 --- a/test/CodeGenCXX/debug-info-gline-tables-only.cpp +++ b/test/CodeGenCXX/debug-info-gline-tables-only.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -fno-rtti -gline-tables-only -S -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -fno-rtti -debug-info-kind=line-tables-only -S -emit-llvm -o - | FileCheck %s // Checks that clang with "-gline-tables-only" doesn't emit debug info // for variables and types. diff --git a/test/CodeGenCXX/debug-info-global-ctor-dtor.cpp b/test/CodeGenCXX/debug-info-global-ctor-dtor.cpp index a08045ddf34a..4c61cf78cccb 100644 --- a/test/CodeGenCXX/debug-info-global-ctor-dtor.cpp +++ b/test/CodeGenCXX/debug-info-global-ctor-dtor.cpp @@ -1,6 +1,6 @@ -// RUN: %clang_cc1 %s -g -triple %itanium_abi_triple -fno-use-cxa-atexit -S -emit-llvm -o - \ +// RUN: %clang_cc1 %s -debug-info-kind=limited -triple %itanium_abi_triple -fno-use-cxa-atexit -S -emit-llvm -o - \ // RUN: | FileCheck %s --check-prefix=CHECK-NOKEXT -// RUN: %clang_cc1 %s -g -triple %itanium_abi_triple -fno-use-cxa-atexit -fapple-kext -S -emit-llvm -o - \ +// RUN: %clang_cc1 %s -debug-info-kind=limited -triple %itanium_abi_triple -fno-use-cxa-atexit -fapple-kext -S -emit-llvm -o - \ // RUN: | FileCheck %s --check-prefix=CHECK-KEXT class A { diff --git a/test/CodeGenCXX/debug-info-global.cpp b/test/CodeGenCXX/debug-info-global.cpp index 8292361eea8f..920db82409bc 100644 --- a/test/CodeGenCXX/debug-info-global.cpp +++ b/test/CodeGenCXX/debug-info-global.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple x86_64-none-linux-gnu -emit-llvm -g %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-none-linux-gnu -emit-llvm -debug-info-kind=limited %s -o - | FileCheck %s // Multiple references to the same constant should result in only one entry in // the globals list. diff --git a/test/CodeGenCXX/debug-info-globalinit.cpp b/test/CodeGenCXX/debug-info-globalinit.cpp index f8c0ebd29b7e..09c7d59bffed 100644 --- a/test/CodeGenCXX/debug-info-globalinit.cpp +++ b/test/CodeGenCXX/debug-info-globalinit.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin10.0.0 -emit-llvm -o - %s -std=c++11 -g | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin10.0.0 -emit-llvm -o - %s -std=c++11 -debug-info-kind=limited | FileCheck %s void crash() { volatile char *ptr = 0; diff --git a/test/CodeGenCXX/debug-info-indirect-field-decl.cpp b/test/CodeGenCXX/debug-info-indirect-field-decl.cpp index 08f71d4b1e16..19f8d01e1ab6 100644 --- a/test/CodeGenCXX/debug-info-indirect-field-decl.cpp +++ b/test/CodeGenCXX/debug-info-indirect-field-decl.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -g -triple x86_64-apple-darwin %s -o - | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited -triple x86_64-apple-darwin %s -o - | FileCheck %s // // Test that indirect field decls are handled gracefully. // rdar://problem/16348575 diff --git a/test/CodeGenCXX/debug-info-large-constant.cpp b/test/CodeGenCXX/debug-info-large-constant.cpp index 2daa1894e15d..5a0d4d2b85bb 100644 --- a/test/CodeGenCXX/debug-info-large-constant.cpp +++ b/test/CodeGenCXX/debug-info-large-constant.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -g -triple=x86_64-apple-darwin %s -o /dev/null +// RUN: %clang_cc1 -debug-info-kind=limited -triple=x86_64-apple-darwin %s -o /dev/null // PR 8913 typedef __uint128_t word128; diff --git a/test/CodeGenCXX/debug-info-limited.cpp b/test/CodeGenCXX/debug-info-limited.cpp index d56e5b670a16..b209e3a850de 100644 --- a/test/CodeGenCXX/debug-info-limited.cpp +++ b/test/CodeGenCXX/debug-info-limited.cpp @@ -14,8 +14,7 @@ A *foo (A* x) { } // CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "B" -// CHECK-NOT: DIFlagFwdDecl -// CHECK-SAME: ){{$}} +// CHECK-SAME: flags: DIFlagFwdDecl class B { public: diff --git a/test/CodeGenCXX/debug-info-line-if.cpp b/test/CodeGenCXX/debug-info-line-if.cpp index 71097259df63..29806351c94c 100644 --- a/test/CodeGenCXX/debug-info-line-if.cpp +++ b/test/CodeGenCXX/debug-info-line-if.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -g -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 %s // PR19864 extern int v[2]; int a = 0, b = 0; diff --git a/test/CodeGenCXX/debug-info-line.cpp b/test/CodeGenCXX/debug-info-line.cpp index 7f8e117315c0..9fb6ba8ac70e 100644 --- a/test/CodeGenCXX/debug-info-line.cpp +++ b/test/CodeGenCXX/debug-info-line.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -w -gline-tables-only -std=c++11 -fexceptions -fcxx-exceptions -S -emit-llvm %s -o - | FileCheck %s -// RUN: %clang_cc1 -w -gline-tables-only -std=c++11 -fexceptions -fcxx-exceptions -S -emit-llvm %s -o - -triple i686-linux-gnu | FileCheck %s +// RUN: %clang_cc1 -w -debug-info-kind=line-tables-only -std=c++11 -fexceptions -fcxx-exceptions -S -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -w -debug-info-kind=line-tables-only -std=c++11 -fexceptions -fcxx-exceptions -S -emit-llvm %s -o - -triple i686-linux-gnu | FileCheck %s // XFAIL: win32 diff --git a/test/CodeGenCXX/debug-info-method-nodebug.cpp b/test/CodeGenCXX/debug-info-method-nodebug.cpp index 474053a4caa9..0301e2f48947 100644 --- a/test/CodeGenCXX/debug-info-method-nodebug.cpp +++ b/test/CodeGenCXX/debug-info-method-nodebug.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -g %s -o - | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited %s -o - | FileCheck %s class C { void present(); diff --git a/test/CodeGenCXX/debug-info-method.cpp b/test/CodeGenCXX/debug-info-method.cpp index 3ce05bd2d6b3..bdd14e0b735d 100644 --- a/test/CodeGenCXX/debug-info-method.cpp +++ b/test/CodeGenCXX/debug-info-method.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -std=c++11 -g %s -o - | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -std=c++11 -debug-info-kind=limited %s -o - | FileCheck %s // CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "A",{{.*}} identifier: "_ZTS1A") // CHECK: !DISubprogram(name: "foo", linkageName: "_ZN1A3fooEiS_3$_0" // CHECK-SAME: DIFlagProtected @@ -8,9 +8,10 @@ // CHECK: !DIDerivedType(tag: DW_TAG_ptr_to_member_type, baseType: ![[MEMFUNTYPE:[0-9]+]] // CHECK: ![[MEMFUNTYPE]] = !DISubroutineType(types: ![[MEMFUNARGS:[0-9]+]]) // CHECK: ![[MEMFUNARGS]] = {{.*}}, ![[THISTYPE]], -// CHECK: !DILocalVariable(tag: DW_TAG_arg_variable -// CHECK: !DILocalVariable(tag: DW_TAG_arg_variable -// CHECK: !DILocalVariable(tag: DW_TAG_arg_variable +// CHECK: !DILocalVariable(name: "this", arg: 1 +// CHECK: !DILocalVariable(arg: 2 +// CHECK: !DILocalVariable(arg: 3 +// CHECK: !DILocalVariable(arg: 4 union { int a; float b; diff --git a/test/CodeGenCXX/debug-info-method2.cpp b/test/CodeGenCXX/debug-info-method2.cpp index a365312b2584..40664366e81f 100644 --- a/test/CodeGenCXX/debug-info-method2.cpp +++ b/test/CodeGenCXX/debug-info-method2.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fno-standalone-debug -x c++ -g -S -emit-llvm < %s | FileCheck %s +// RUN: %clang_cc1 -x c++ -debug-info-kind=limited -S -emit-llvm < %s | FileCheck %s // rdar://10336845 // Preserve type qualifiers in -flimit-debug-info mode. diff --git a/test/CodeGenCXX/debug-info-namespace.cpp b/test/CodeGenCXX/debug-info-namespace.cpp index 8a00d9b4a5eb..4933ae967452 100644 --- a/test/CodeGenCXX/debug-info-namespace.cpp +++ b/test/CodeGenCXX/debug-info-namespace.cpp @@ -1,6 +1,6 @@ -// RUN: %clang_cc1 -g -fno-standalone-debug -S -emit-llvm %s -o - | FileCheck %s -// RUN: %clang_cc1 -g -gline-tables-only -S -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-GMLT %s -// RUN: %clang_cc1 -g -fstandalone-debug -S -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-NOLIMIT %s +// RUN: %clang_cc1 -debug-info-kind=limited -S -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -debug-info-kind=line-tables-only -S -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-GMLT %s +// RUN: %clang_cc1 -debug-info-kind=standalone -S -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-NOLIMIT %s namespace A { #line 1 "foo.cpp" @@ -67,10 +67,10 @@ void B::func_fwd() {} // CHECK: [[BAR:![0-9]+]] = !DICompositeType(tag: DW_TAG_structure_type, name: "bar", // CHECK-SAME: line: 6 // CHECK-SAME: DIFlagFwdDecl -// CHECK: [[F1:![0-9]+]] = !DISubprogram(name: "f1",{{.*}} line: 4 +// CHECK: [[F1:![0-9]+]] = distinct !DISubprogram(name: "f1",{{.*}} line: 4 // CHECK-SAME: isDefinition: true -// CHECK: [[FUNC:![0-9]+]] = !DISubprogram(name: "func",{{.*}} isDefinition: true -// CHECK: [[FUNC_FWD:![0-9]+]] = !DISubprogram(name: "func_fwd",{{.*}} line: 47,{{.*}} isDefinition: true +// CHECK: [[FUNC:![0-9]+]] = distinct !DISubprogram(name: "func",{{.*}} isDefinition: true +// CHECK: [[FUNC_FWD:![0-9]+]] = distinct !DISubprogram(name: "func_fwd",{{.*}} line: 47,{{.*}} isDefinition: true // CHECK: [[I:![0-9]+]] = !DIGlobalVariable(name: "i",{{.*}} scope: [[NS]], // CHECK: [[VAR_FWD:![0-9]+]] = !DIGlobalVariable(name: "var_fwd",{{.*}} scope: [[NS]], // CHECK-SAME: line: 44 @@ -110,5 +110,4 @@ void B::func_fwd() {} // CHECK-NOLIMIT-NOT: DIFlagFwdDecl // CHECK-NOLIMIT-SAME: ){{$}} -// REQUIRES: shell-preserves-root // REQUIRES: dw2 diff --git a/test/CodeGenCXX/debug-info-nullptr.cpp b/test/CodeGenCXX/debug-info-nullptr.cpp index 36baacc6dbea..3054ef849bc9 100644 --- a/test/CodeGenCXX/debug-info-nullptr.cpp +++ b/test/CodeGenCXX/debug-info-nullptr.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -std=c++11 -g %s -o -| FileCheck %s +// RUN: %clang_cc1 -emit-llvm -std=c++11 -debug-info-kind=limited %s -o -| FileCheck %s void foo() { decltype(nullptr) t = 0; diff --git a/test/CodeGenCXX/debug-info-ptr-to-member-function.cpp b/test/CodeGenCXX/debug-info-ptr-to-member-function.cpp index 1b2cb578e60f..cac16b600890 100644 --- a/test/CodeGenCXX/debug-info-ptr-to-member-function.cpp +++ b/test/CodeGenCXX/debug-info-ptr-to-member-function.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 %s -triple x86_64-apple-darwin -g -emit-llvm -o - | FileCheck -check-prefix=CHECK -check-prefix=DARWIN-X64 %s -// RUN: %clang_cc1 %s -triple x86_64-pc-win32 -g -emit-llvm -o - | FileCheck -check-prefix=CHECK -check-prefix=WIN32-X64 %s +// RUN: %clang_cc1 %s -triple x86_64-apple-darwin -debug-info-kind=limited -emit-llvm -o - | FileCheck -check-prefix=CHECK -check-prefix=DARWIN-X64 %s +// RUN: %clang_cc1 %s -triple x86_64-pc-win32 -debug-info-kind=limited -emit-llvm -o - | FileCheck -check-prefix=CHECK -check-prefix=WIN32-X64 %s struct T { int method(); diff --git a/test/CodeGenCXX/debug-info-qualifiers.cpp b/test/CodeGenCXX/debug-info-qualifiers.cpp index 9458e1f825ef..c48c9b5d9963 100644 --- a/test/CodeGenCXX/debug-info-qualifiers.cpp +++ b/test/CodeGenCXX/debug-info-qualifiers.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++11 -emit-llvm -g -triple x86_64-apple-darwin %s -o - | FileCheck %s +// RUN: %clang_cc1 -std=c++11 -emit-llvm -debug-info-kind=limited -triple x86_64-apple-darwin %s -o - | FileCheck %s // Test (r)value and CVR qualifiers on C++11 non-static member functions. class A { public: @@ -22,13 +22,13 @@ public: void g() { A a; // The type of pl is "void (A::*)() const &". - // CHECK: !DILocalVariable(tag: DW_TAG_auto_variable, name: "pl", + // CHECK: !DILocalVariable(name: "pl", // CHECK-SAME: line: [[@LINE+3]] // CHECK-SAME: type: ![[PL:[0-9]+]] // CHECK: !DIDerivedType(tag: DW_TAG_ptr_to_member_type, baseType: ![[PLSR]] auto pl = &A::l; - // CHECK: !DILocalVariable(tag: DW_TAG_auto_variable, name: "pr", + // CHECK: !DILocalVariable(name: "pr", // CHECK-SAME: line: [[@LINE+3]] // CHECK-SAME: type: ![[PR:[0-9]+]] // CHECK: !DIDerivedType(tag: DW_TAG_ptr_to_member_type, baseType: ![[PRSR]] diff --git a/test/CodeGenCXX/debug-info-rvalue-ref.cpp b/test/CodeGenCXX/debug-info-rvalue-ref.cpp index 00b5bcc20ad3..edb93ae46cda 100644 --- a/test/CodeGenCXX/debug-info-rvalue-ref.cpp +++ b/test/CodeGenCXX/debug-info-rvalue-ref.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++11 -emit-llvm -g -triple x86_64-apple-darwin %s -o - | FileCheck %s +// RUN: %clang_cc1 -std=c++11 -emit-llvm -debug-info-kind=limited -triple x86_64-apple-darwin %s -o - | FileCheck %s extern "C" { extern int printf(const char * format, ...); @@ -8,5 +8,5 @@ void foo (int &&i) printf("%d\n", i); } -// CHECK: !DIDerivedType(tag: DW_TAG_rvalue_reference_type, baseType: ![[INT:[0-9]+]]) +// CHECK: !DIDerivedType(tag: DW_TAG_rvalue_reference_type, baseType: ![[INT:[0-9]+]], size: 64, align: 64) // CHECK: ![[INT]] = !DIBasicType(name: "int" diff --git a/test/CodeGenCXX/debug-info-scope.cpp b/test/CodeGenCXX/debug-info-scope.cpp index 478b7895e4ec..e81eccc5168f 100644 --- a/test/CodeGenCXX/debug-info-scope.cpp +++ b/test/CodeGenCXX/debug-info-scope.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -g -std=c++11 -emit-llvm %s -o -| FileCheck %s +// RUN: %clang_cc1 -debug-info-kind=limited -std=c++11 -emit-llvm %s -o -| FileCheck %s // // Two variables with the same name in subsequent if staments need to be in separate scopes. // @@ -9,14 +9,14 @@ int src(); void f(); void func() { - // CHECK: = !DILocalVariable(tag: DW_TAG_auto_variable, name: "i" + // CHECK: = !DILocalVariable(name: "i" // CHECK-SAME: scope: [[IF1:![0-9]*]] // CHECK-SAME: line: [[@LINE+2]] // CHECK: [[IF1]] = distinct !DILexicalBlock({{.*}}line: [[@LINE+1]]) if (int i = src()) f(); - // CHECK: = !DILocalVariable(tag: DW_TAG_auto_variable, name: "i" + // CHECK: = !DILocalVariable(name: "i" // CHECK-SAME: scope: [[IF2:![0-9]*]] // CHECK-SAME: line: [[@LINE+2]] // CHECK: [[IF2]] = distinct !DILexicalBlock({{.*}}line: [[@LINE+1]]) @@ -25,12 +25,12 @@ void func() { } else f(); - // CHECK: = !DILocalVariable(tag: DW_TAG_auto_variable, name: "i" + // CHECK: = !DILocalVariable(name: "i" // CHECK-SAME: scope: [[FOR:![0-9]*]] // CHECK-SAME: line: [[@LINE+2]] // CHECK: [[FOR]] = distinct !DILexicalBlock({{.*}}line: [[@LINE+1]]) for (int i = 0; - // CHECK: = !DILocalVariable(tag: DW_TAG_auto_variable, name: "b" + // CHECK: = !DILocalVariable(name: "b" // CHECK-SAME: scope: [[FOR_BODY:![0-9]*]] // CHECK-SAME: line: [[@LINE+6]] // CHECK: [[FOR_BODY]] = distinct !DILexicalBlock({{.*}}line: [[@LINE-4]]) @@ -41,7 +41,7 @@ void func() { bool b = i != 10; ++i) f(); - // CHECK: = !DILocalVariable(tag: DW_TAG_auto_variable, name: "i" + // CHECK: = !DILocalVariable(name: "i" // CHECK-SAME: scope: [[FOR:![0-9]*]] // CHECK-SAME: line: [[@LINE+2]] // CHECK: [[FOR]] = distinct !DILexicalBlock({{.*}}line: [[@LINE+1]]) @@ -50,7 +50,7 @@ void func() { // or using declarations) as direct children, they just waste // space/relocations/etc. // CHECK: [[FOR_LOOP_INCLUDING_COND:!.*]] = distinct !DILexicalBlock(scope: [[FOR]],{{.*}} line: [[@LINE-4]]) - // CHECK: = !DILocalVariable(tag: DW_TAG_auto_variable, name: "b" + // CHECK: = !DILocalVariable(name: "b" // CHECK-SAME: scope: [[FOR_COMPOUND:![0-9]*]] // CHECK-SAME: line: [[@LINE+2]] // CHECK: [[FOR_COMPOUND]] = distinct !DILexicalBlock(scope: [[FOR_LOOP_INCLUDING_COND]],{{.*}} line: [[@LINE-8]]) @@ -58,13 +58,13 @@ void func() { } int x[] = {1, 2}; - // CHECK: = !DILocalVariable(tag: DW_TAG_auto_variable, name: "__range" + // CHECK: = !DILocalVariable(name: "__range" // CHECK-SAME: scope: [[RANGE_FOR:![0-9]*]] // CHECK-NOT: line: // CHECK-SAME: ){{$}} // CHECK: [[RANGE_FOR]] = distinct !DILexicalBlock({{.*}}, line: [[@LINE+1]]) for (int i : x) { - // CHECK: = !DILocalVariable(tag: DW_TAG_auto_variable, name: "i" + // CHECK: = !DILocalVariable(name: "i" // CHECK-SAME: scope: [[RANGE_FOR_BODY:![0-9]*]] // CHECK-SAME: line: [[@LINE-3]] // CHECK: [[RANGE_FOR_BODY]] = distinct !DILexicalBlock(scope: [[RANGE_FOR]],{{.*}} line: [[@LINE-4]]) diff --git a/test/CodeGenCXX/debug-info-static-fns.cpp b/test/CodeGenCXX/debug-info-static-fns.cpp index 3f8d8e838930..59c7471f7ca6 100644 --- a/test/CodeGenCXX/debug-info-static-fns.cpp +++ b/test/CodeGenCXX/debug-info-static-fns.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -g -triple x86_64-apple-darwin %s -o - | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited -triple x86_64-apple-darwin %s -o - | FileCheck %s namespace A { static int a(int b) { return b + 4; } @@ -7,7 +7,7 @@ namespace A { } // Verify that a is present and mangled. -// CHECK: !DISubprogram(name: "a", linkageName: "_ZN1AL1aEi", +// CHECK: define internal i32 @_ZN1AL1aEi({{.*}} !dbg [[DBG:![0-9]+]] +// CHECK: [[DBG]] = distinct !DISubprogram(name: "a", linkageName: "_ZN1AL1aEi", // CHECK-SAME: line: 4 // CHECK-SAME: isDefinition: true -// CHECK-SAME: function: i32 (i32)* @_ZN1AL1aEi diff --git a/test/CodeGenCXX/debug-info-template-explicit-specialization.cpp b/test/CodeGenCXX/debug-info-template-explicit-specialization.cpp index 4dadc4f5531b..04c63ae2ff24 100644 --- a/test/CodeGenCXX/debug-info-template-explicit-specialization.cpp +++ b/test/CodeGenCXX/debug-info-template-explicit-specialization.cpp @@ -1,8 +1,8 @@ -// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -g %s -o - -fno-standalone-debug | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -debug-info-kind=limited %s -o - | FileCheck %s // Run again with -gline-tables-only and verify we don't crash. We won't output // type info at all. -// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -g %s -o - -gline-tables-only | FileCheck %s -check-prefix LINES-ONLY +// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -debug-info-kind=line-tables-only %s -o - | FileCheck %s -check-prefix LINES-ONLY // LINES-ONLY-NOT: !DICompositeType(tag: DW_TAG_structure_type diff --git a/test/CodeGenCXX/debug-info-template-fwd.cpp b/test/CodeGenCXX/debug-info-template-fwd.cpp index 25daabce21c0..8b8d29cad0e4 100644 --- a/test/CodeGenCXX/debug-info-template-fwd.cpp +++ b/test/CodeGenCXX/debug-info-template-fwd.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin -g -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin -debug-info-kind=limited -emit-llvm -o - | FileCheck %s // This test is for a crash when emitting debug info for not-yet-completed // types. // Test that we don't actually emit a forward decl for the offending class: diff --git a/test/CodeGenCXX/debug-info-template-limit.cpp b/test/CodeGenCXX/debug-info-template-limit.cpp index 2b4930311487..5c4ac0cc3e15 100644 --- a/test/CodeGenCXX/debug-info-template-limit.cpp +++ b/test/CodeGenCXX/debug-info-template-limit.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -fno-standalone-debug -triple %itanium_abi_triple -g %s -o - | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited -triple %itanium_abi_triple %s -o - | FileCheck %s // Check that this pointer type is TC // CHECK: ![[LINE:[0-9]+]] = !DICompositeType(tag: DW_TAG_class_type, name: "TC"{{.*}}, identifier: "_ZTS2TCIiE") diff --git a/test/CodeGenCXX/debug-info-template-member.cpp b/test/CodeGenCXX/debug-info-template-member.cpp index dee82dce6bed..b94ff05df44e 100644 --- a/test/CodeGenCXX/debug-info-template-member.cpp +++ b/test/CodeGenCXX/debug-info-template-member.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -g -fno-standalone-debug -triple x86_64-apple-darwin %s -o - | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited -triple x86_64-apple-darwin %s -o - | FileCheck %s struct MyClass { template int add(int j) { @@ -98,4 +98,3 @@ inline void f1() { void f2() { virt d; // emit 'virt' } - diff --git a/test/CodeGenCXX/debug-info-template-partial-specialization.cpp b/test/CodeGenCXX/debug-info-template-partial-specialization.cpp index c184f0499686..0435a6fd3d7c 100644 --- a/test/CodeGenCXX/debug-info-template-partial-specialization.cpp +++ b/test/CodeGenCXX/debug-info-template-partial-specialization.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -g %s -o - -fstandalone-debug | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple %s -o - -debug-info-kind=standalone | FileCheck %s namespace __pointer_type_imp { template struct __pointer_type1 {}; diff --git a/test/CodeGenCXX/debug-info-template-quals.cpp b/test/CodeGenCXX/debug-info-template-quals.cpp index 1f249117522a..1e8bdb1ad714 100644 --- a/test/CodeGenCXX/debug-info-template-quals.cpp +++ b/test/CodeGenCXX/debug-info-template-quals.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -g -triple x86_64-apple-darwin %s -o - | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited -triple x86_64-apple-darwin %s -o - | FileCheck %s template struct basic_string { diff --git a/test/CodeGenCXX/debug-info-template-recursive.cpp b/test/CodeGenCXX/debug-info-template-recursive.cpp index ef04d03bb78f..9693b386c9d1 100644 --- a/test/CodeGenCXX/debug-info-template-recursive.cpp +++ b/test/CodeGenCXX/debug-info-template-recursive.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -g -triple x86_64-apple-darwin %s -o - | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited -triple x86_64-apple-darwin %s -o - | FileCheck %s class base { }; diff --git a/test/CodeGenCXX/debug-info-thunk.cpp b/test/CodeGenCXX/debug-info-thunk.cpp index 935110ffbdce..cd00ec937318 100644 --- a/test/CodeGenCXX/debug-info-thunk.cpp +++ b/test/CodeGenCXX/debug-info-thunk.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -triple %itanium_abi_triple -g -S -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple %itanium_abi_triple -debug-info-kind=limited -S -emit-llvm -o - | FileCheck %s struct A { virtual void f(); diff --git a/test/CodeGenCXX/debug-info-union-template.cpp b/test/CodeGenCXX/debug-info-union-template.cpp index 0616d724c9f2..d9219fcba99e 100644 --- a/test/CodeGenCXX/debug-info-union-template.cpp +++ b/test/CodeGenCXX/debug-info-union-template.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -g -triple x86_64-linux-gnu %s -o - | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited -triple x86_64-linux-gnu %s -o - | FileCheck %s // Make sure that the union type has template parameters. diff --git a/test/CodeGenCXX/debug-info-union.cpp b/test/CodeGenCXX/debug-info-union.cpp index a81a560e6280..19e67418f9dc 100644 --- a/test/CodeGenCXX/debug-info-union.cpp +++ b/test/CodeGenCXX/debug-info-union.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -g -triple x86_64-apple-darwin -std=c++11 %s -o - | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited -triple x86_64-apple-darwin -std=c++11 %s -o - | FileCheck %s union E { int a; diff --git a/test/CodeGenCXX/debug-info-use-after-free.cpp b/test/CodeGenCXX/debug-info-use-after-free.cpp index 0f28a9063fb8..f87763b9050d 100644 --- a/test/CodeGenCXX/debug-info-use-after-free.cpp +++ b/test/CodeGenCXX/debug-info-use-after-free.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -g -triple %itanium_abi_triple -emit-llvm-only %s +// RUN: %clang_cc1 -debug-info-kind=limited -triple %itanium_abi_triple -emit-llvm-only %s // Check that we don't crash. // PR12305, PR12315 diff --git a/test/CodeGenCXX/debug-info-uuid.cpp b/test/CodeGenCXX/debug-info-uuid.cpp index fd6e31d7d5b6..a304f37078b6 100644 --- a/test/CodeGenCXX/debug-info-uuid.cpp +++ b/test/CodeGenCXX/debug-info-uuid.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -emit-llvm -fms-extensions -triple=x86_64-pc-win32 -g %s -o - -std=c++11 | FileCheck %s -// RUN: %clang_cc1 -emit-llvm -fms-extensions -triple=x86_64-unknown-unknown -g %s -o - -std=c++11 2>&1 | FileCheck %s --check-prefix=CHECK-ITANIUM +// RUN: %clang_cc1 -emit-llvm -fms-extensions -triple=x86_64-pc-win32 -debug-info-kind=limited %s -o - -std=c++11 | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -fms-extensions -triple=x86_64-unknown-unknown -debug-info-kind=limited %s -o - -std=c++11 2>&1 | FileCheck %s --check-prefix=CHECK-ITANIUM // CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "tmpl_guid<&__uuidof(uuid)>" // CHECK-SAME: templateParams: [[TGIARGS:![0-9]*]] diff --git a/test/CodeGenCXX/debug-info-varargs.cpp b/test/CodeGenCXX/debug-info-varargs.cpp index edcb0e5a53d4..52bffe6c9285 100644 --- a/test/CodeGenCXX/debug-info-varargs.cpp +++ b/test/CodeGenCXX/debug-info-varargs.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -g %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -debug-info-kind=limited %s -o - | FileCheck %s struct A { @@ -20,7 +20,7 @@ void b(int c, ...) { A a; - // CHECK: !DILocalVariable(tag: DW_TAG_auto_variable, name: "fptr" + // CHECK: !DILocalVariable(name: "fptr" // CHECK-SAME: line: [[@LINE+2]] // CHECK-SAME: type: ![[PST:[0-9]+]] void (*fptr)(int, ...) = b; diff --git a/test/CodeGenCXX/debug-info-vtable-optzn.cpp b/test/CodeGenCXX/debug-info-vtable-optzn.cpp index f15571eab996..8b49e951795b 100644 --- a/test/CodeGenCXX/debug-info-vtable-optzn.cpp +++ b/test/CodeGenCXX/debug-info-vtable-optzn.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -emit-llvm -g -triple x86_64-apple-darwin %s -o - | FileCheck %s -// RUN: %clang_cc1 -emit-llvm -g -triple amd64-unknown-freebsd %s -o - | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -debug-info-kind=standalone -triple x86_64-apple-darwin %s -o - | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -debug-info-kind=standalone -triple amd64-unknown-freebsd %s -o - | FileCheck %s // // This tests that the "emit debug info for a C++ class only in the // module that has its vtable" optimization is disabled by default on diff --git a/test/CodeGenCXX/debug-info-wchar.cpp b/test/CodeGenCXX/debug-info-wchar.cpp index bb01f575c591..1ecdd568b68c 100644 --- a/test/CodeGenCXX/debug-info-wchar.cpp +++ b/test/CodeGenCXX/debug-info-wchar.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -g %s -o -| FileCheck %s +// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited %s -o -| FileCheck %s void foo() { // CHECK: !DIBasicType(name: "wchar_t" const wchar_t w = L'x'; diff --git a/test/CodeGenCXX/debug-info-windows-dtor.cpp b/test/CodeGenCXX/debug-info-windows-dtor.cpp index 2f425fdd5bea..e5a51abae68b 100644 --- a/test/CodeGenCXX/debug-info-windows-dtor.cpp +++ b/test/CodeGenCXX/debug-info-windows-dtor.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple i386-unknown-windows-msvc -std=c++11 -emit-llvm -gline-tables-only %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple i386-unknown-windows-msvc -std=c++11 -emit-llvm -debug-info-kind=line-tables-only %s -o - | FileCheck %s struct A { virtual ~A() {} @@ -14,9 +14,9 @@ struct AB: A, B { template struct AB; -// CHECK-LABEL: define {{.*}}@"\01??_E?$AB@H@@W3AEPAXI@Z" +// 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-LABEL: define +// CHECK: define -// CHECK: [[THUNK_VEC_DEL_DTOR:![0-9]*]] = !DISubprogram({{.*}}function: {{.*}}@"\01??_E?$AB@H@@W3AEPAXI@Z" +// CHECK: [[THUNK_VEC_DEL_DTOR]] = distinct !DISubprogram // CHECK: [[THUNK_LOC]] = !DILocation(line: 15, scope: [[THUNK_VEC_DEL_DTOR]]) diff --git a/test/CodeGenCXX/debug-info.cpp b/test/CodeGenCXX/debug-info.cpp index 13753684800a..29ed9e93156d 100644 --- a/test/CodeGenCXX/debug-info.cpp +++ b/test/CodeGenCXX/debug-info.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -triple x86_64-none-linux-gnu -emit-llvm -g %s -o - | FileCheck %s -// RUN: %clang_cc1 -triple i686-pc-windows-msvc -emit-llvm -g %s -o - | FileCheck %s --check-prefix=MSVC +// RUN: %clang_cc1 -triple x86_64-none-linux-gnu -emit-llvm -debug-info-kind=limited %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple i686-pc-windows-msvc -emit-llvm -debug-info-kind=limited %s -o - | FileCheck %s --check-prefix=MSVC template struct Identity { typedef T Type; @@ -114,9 +114,9 @@ foo func(foo f) { // CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "b" // CHECK-SAME: DIFlagFwdDecl -// CHECK: [[FUNC:![0-9]+]] = !DISubprogram(name: "func", linkageName: "_ZN7pr147634funcENS_3fooE" -// CHECK-SAME: type: [[FUNC_TYPE:![0-9]*]] -// CHECK-SAME: isDefinition: true +// CHECK: [[FUNC:![0-9]+]] = distinct !DISubprogram(name: "func", linkageName: "_ZN7pr147634funcENS_3fooE" +// CHECK-SAME: type: [[FUNC_TYPE:![0-9]*]] +// CHECK-SAME: isDefinition: true } void foo() { @@ -142,11 +142,13 @@ incomplete (*x)[3]; } // For some reason function arguments ended up down here -// CHECK: ![[F]] = !DILocalVariable(tag: DW_TAG_arg_variable, name: "f", arg: 1, scope: [[FUNC]] +// CHECK: ![[F]] = !DILocalVariable(name: "f", arg: 1, scope: [[FUNC]] // CHECK-SAME: type: !"[[FOO]]" // CHECK: ![[EXPR]] = !DIExpression(DW_OP_deref) -// CHECK: !DILocalVariable(tag: DW_TAG_auto_variable, name: "c" +// CHECK: !DILocalVariable(name: "c" +// CHECK-NOT: arg: +// CHECK-SAME: ) namespace pr16214 { struct a { diff --git a/test/CodeGenCXX/debug-lambda-expressions.cpp b/test/CodeGenCXX/debug-lambda-expressions.cpp index a53274af3435..a022fad1b6b9 100644 --- a/test/CodeGenCXX/debug-lambda-expressions.cpp +++ b/test/CodeGenCXX/debug-lambda-expressions.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin10.0.0 -emit-llvm -o - %s -fexceptions -std=c++11 -g | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin10.0.0 -emit-llvm -o - %s -fexceptions -std=c++11 -debug-info-kind=limited | FileCheck %s auto var = [](int i) { return i+1; }; void *use = &var; @@ -20,16 +20,16 @@ int d(int x) { D y[10]; return [x,y] { return y[x].x; }(); } // CHECK: ![[INT:[0-9]+]] = !DIBasicType(name: "int" // A: 10 -// CHECK: ![[A_FUNC:.*]] = !DISubprogram(name: "a"{{.*}}, line: [[A_LINE:[0-9]+]]{{.*}}, isDefinition: true +// CHECK: ![[A_FUNC:.*]] = distinct !DISubprogram(name: "a"{{.*}}, line: [[A_LINE:[0-9]+]]{{.*}}, isDefinition: true // B: 14 -// CHECK: ![[B_FUNC:.*]] = !DISubprogram(name: "b"{{.*}}, line: [[B_LINE:[0-9]+]]{{.*}}, isDefinition: true +// CHECK: ![[B_FUNC:.*]] = distinct !DISubprogram(name: "b"{{.*}}, line: [[B_LINE:[0-9]+]]{{.*}}, isDefinition: true // C: 17 -// CHECK: ![[C_FUNC:.*]] = !DISubprogram(name: "c"{{.*}}, line: [[C_LINE:[0-9]+]]{{.*}}, isDefinition: true +// CHECK: ![[C_FUNC:.*]] = distinct !DISubprogram(name: "c"{{.*}}, line: [[C_LINE:[0-9]+]]{{.*}}, isDefinition: true // D: 18 -// CHECK: ![[D_FUNC:.*]] = !DISubprogram(name: "d"{{.*}}, line: [[D_LINE:[0-9]+]]{{.*}}, isDefinition: true +// CHECK: ![[D_FUNC:.*]] = distinct !DISubprogram(name: "d"{{.*}}, line: [[D_LINE:[0-9]+]]{{.*}}, isDefinition: true // Back to A. -- 78 diff --git a/test/CodeGenCXX/debug-lambda-this.cpp b/test/CodeGenCXX/debug-lambda-this.cpp index e3ef67091701..0c413449a3ec 100644 --- a/test/CodeGenCXX/debug-lambda-this.cpp +++ b/test/CodeGenCXX/debug-lambda-this.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin10.0.0 -emit-llvm -o - %s -fexceptions -std=c++11 -g | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin10.0.0 -emit-llvm -o - %s -fexceptions -std=c++11 -debug-info-kind=limited | FileCheck %s struct D { D(); diff --git a/test/CodeGenCXX/default-destructor-synthesis.cpp b/test/CodeGenCXX/default-destructor-synthesis.cpp deleted file mode 100644 index af780044d193..000000000000 --- a/test/CodeGenCXX/default-destructor-synthesis.cpp +++ /dev/null @@ -1,38 +0,0 @@ -// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -O2 -o - | FileCheck %s -static int count = 0; - -struct S { - S() { count++; } - ~S() { count--; } -}; - -struct P { - P() { count++; } - ~P() { count--; } -}; - -struct Q { - Q() { count++; } - ~Q() { count--; } -}; - -struct M : Q, P { - S s; - Q q; - P p; - P p_arr[3]; - Q q_arr[2][3]; -}; - -// CHECK: define i32 @_Z1fv() [[NUW:#[0-9]+]] -int f() { - { - count = 1; - M a; - } - - // CHECK: ret i32 1 - return count; -} - -// CHECK: attributes [[NUW]] = { nounwind{{.*}} } diff --git a/test/CodeGenCXX/delete-two-arg.cpp b/test/CodeGenCXX/delete-two-arg.cpp index e5a4cfa3ee6d..85275b3eb176 100644 --- a/test/CodeGenCXX/delete-two-arg.cpp +++ b/test/CodeGenCXX/delete-two-arg.cpp @@ -30,7 +30,7 @@ namespace test2 { // CHECK: [[NEW:%.*]] = call noalias i8* @_Znaj(i32 44) // CHECK-NEXT: [[T0:%.*]] = bitcast i8* [[NEW]] to i32* // CHECK-NEXT: store i32 10, i32* [[T0]] - // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8, i8* [[NEW]], i64 4 + // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8, i8* [[NEW]], i32 4 // CHECK-NEXT: [[T2:%.*]] = bitcast i8* [[T1]] to [[A]]* // CHECK-NEXT: ret [[A]]* [[T2]] return ::new A[10]; @@ -44,7 +44,7 @@ namespace test2 { // CHECK-NEXT: [[T1:%.*]] = icmp eq [[A]]* [[T0]], null // CHECK-NEXT: br i1 [[T1]], // CHECK: [[T2:%.*]] = bitcast [[A]]* [[T0]] to i8* - // CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds i8, i8* [[T2]], i64 -4 + // CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds i8, i8* [[T2]], i32 -4 // CHECK-NEXT: [[T4:%.*]] = bitcast i8* [[T3]] to i32* // CHECK-NEXT: [[T5:%.*]] = load i32, i32* [[T4]] // CHECK-NEXT: call void @_ZdaPv(i8* [[T3]]) diff --git a/test/CodeGenCXX/destructor-debug-info.cpp b/test/CodeGenCXX/destructor-debug-info.cpp index 2534364aa4c4..7b10f8339420 100644 --- a/test/CodeGenCXX/destructor-debug-info.cpp +++ b/test/CodeGenCXX/destructor-debug-info.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -g -S -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -debug-info-kind=limited -S -emit-llvm %s -o - | FileCheck %s class A { int a; }; class B { diff --git a/test/CodeGenCXX/destructors.cpp b/test/CodeGenCXX/destructors.cpp index b47c6c6b1d43..529603142d31 100644 --- a/test/CodeGenCXX/destructors.cpp +++ b/test/CodeGenCXX/destructors.cpp @@ -151,7 +151,7 @@ namespace test1 { struct S : A { ~S(); int x; }; S::~S() {} - // CHECK4: @_ZN5test11SD2Ev = alias bitcast {{.*}} @_ZN5test11AD2Ev + // CHECK4: @_ZN5test11SD2Ev = 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/dllexport-alias.cpp b/test/CodeGenCXX/dllexport-alias.cpp index 479595d05751..a3dc61edde5d 100644 --- a/test/CodeGenCXX/dllexport-alias.cpp +++ b/test/CodeGenCXX/dllexport-alias.cpp @@ -14,5 +14,5 @@ A::A() {} A::~A() {} -// CHECK: @_ZN1AC1Ev = dllexport alias void (%class.A*)* @_ZN1AC2Ev -// CHECK: @_ZN1AD1Ev = dllexport alias void (%class.A*)* @_ZN1AD2Ev +// CHECK: @_ZN1AC1Ev = dllexport alias void (%class.A*), void (%class.A*)* @_ZN1AC2Ev +// CHECK: @_ZN1AD1Ev = dllexport alias void (%class.A*), void (%class.A*)* @_ZN1AD2Ev diff --git a/test/CodeGenCXX/dllexport-members.cpp b/test/CodeGenCXX/dllexport-members.cpp index 4038d0ba467d..76f692dbd301 100644 --- a/test/CodeGenCXX/dllexport-members.cpp +++ b/test/CodeGenCXX/dllexport-members.cpp @@ -110,10 +110,10 @@ public: // MSC-DAG: @"\01?StaticField@ExportMembers@@2HA" = dllexport global i32 1, align 4 // MSC-DAG: @"\01?StaticConstField@ExportMembers@@2HB" = dllexport constant i32 1, align 4 - // MSC-DAG: @"\01?StaticConstFieldEqualInit@ExportMembers@@2HB" = dllexport constant i32 1, comdat, align 4 - // MSC-DAG: @"\01?StaticConstFieldBraceInit@ExportMembers@@2HB" = dllexport constant i32 1, comdat, align 4 + // MSC-DAG: @"\01?StaticConstFieldEqualInit@ExportMembers@@2HB" = weak_odr dllexport constant i32 1, comdat, align 4 + // MSC-DAG: @"\01?StaticConstFieldBraceInit@ExportMembers@@2HB" = weak_odr dllexport constant i32 1, comdat, align 4 // MSC-DAG: @"\01?StaticConstFieldRefNotDef@ExportMembers@@2HB" = weak_odr dllexport constant i32 1, comdat, align 4 - // MSC-DAG: @"\01?ConstexprField@ExportMembers@@2HB" = dllexport constant i32 1, comdat, align 4 + // MSC-DAG: @"\01?ConstexprField@ExportMembers@@2HB" = weak_odr dllexport constant i32 1, comdat, align 4 // GNU-DAG: @_ZN13ExportMembers11StaticFieldE = dllexport global i32 1, align 4 // GNU-DAG: @_ZN13ExportMembers16StaticConstFieldE = dllexport constant i32 1, align 4 // GNU-DAG: @_ZN13ExportMembers25StaticConstFieldEqualInitE = dllexport constant i32 1, align 4 @@ -236,10 +236,10 @@ public: // MSC-DAG: @"\01?StaticField@Nested@ExportMembers@@2HA" = dllexport global i32 1, align 4 // MSC-DAG: @"\01?StaticConstField@Nested@ExportMembers@@2HB" = dllexport constant i32 1, align 4 - // MSC-DAG: @"\01?StaticConstFieldEqualInit@Nested@ExportMembers@@2HB" = dllexport constant i32 1, comdat, align 4 - // MSC-DAG: @"\01?StaticConstFieldBraceInit@Nested@ExportMembers@@2HB" = dllexport constant i32 1, comdat, align 4 + // MSC-DAG: @"\01?StaticConstFieldEqualInit@Nested@ExportMembers@@2HB" = weak_odr dllexport constant i32 1, comdat, align 4 + // MSC-DAG: @"\01?StaticConstFieldBraceInit@Nested@ExportMembers@@2HB" = weak_odr dllexport constant i32 1, comdat, align 4 // MSC-DAG: @"\01?StaticConstFieldRefNotDef@Nested@ExportMembers@@2HB" = weak_odr dllexport constant i32 1, comdat, align 4 - // MSC-DAG: @"\01?ConstexprField@Nested@ExportMembers@@2HB" = dllexport constant i32 1, comdat, align 4 + // MSC-DAG: @"\01?ConstexprField@Nested@ExportMembers@@2HB" = weak_odr dllexport constant i32 1, comdat, align 4 // GNU-DAG: @_ZN13ExportMembers6Nested11StaticFieldE = dllexport global i32 1, align 4 // GNU-DAG: @_ZN13ExportMembers6Nested16StaticConstFieldE = dllexport constant i32 1, align 4 // GNU-DAG: @_ZN13ExportMembers6Nested25StaticConstFieldEqualInitE = dllexport constant i32 1, align 4 @@ -623,13 +623,13 @@ extern template const int MemVarTmpl::ExportedStaticVar; template const int MemVarTmpl::ExportedStaticVar; // Export specialization of an exported member variable template. -// MSC-DAG: @"\01??$ExportedStaticVar@UExplicitSpec_Def_Exported@@@MemVarTmpl@@2HB" = dllexport constant i32 1, align 4 +// MSC-DAG: @"\01??$ExportedStaticVar@UExplicitSpec_Def_Exported@@@MemVarTmpl@@2HB" = weak_odr dllexport constant i32 1, comdat, align 4 // GNU-DAG: @_ZN10MemVarTmpl17ExportedStaticVarI25ExplicitSpec_Def_ExportedEE = dllexport constant i32 1, align 4 template<> __declspec(dllexport) const int MemVarTmpl::ExportedStaticVar = 1; // Not exporting specialization of an exported member variable template without // explicit dllexport. -// MSC-DAG: @"\01??$ExportedStaticVar@UExplicitSpec_NotExported@@@MemVarTmpl@@2HB" = constant i32 1, align 4 +// MSC-DAG: @"\01??$ExportedStaticVar@UExplicitSpec_NotExported@@@MemVarTmpl@@2HB" = weak_odr constant i32 1, comdat, align 4 // GNU-DAG: @_ZN10MemVarTmpl17ExportedStaticVarI24ExplicitSpec_NotExportedEE = constant i32 1, align 4 template<> const int MemVarTmpl::ExportedStaticVar = 1; @@ -648,6 +648,6 @@ extern template __declspec(dllexport) const int MemVarTmpl::StaticVar; // Export specialization of a non-exported member variable template. -// MSC-DAG: @"\01??$StaticVar@UExplicitSpec_Def_Exported@@@MemVarTmpl@@2HB" = dllexport constant i32 1, align 4 +// MSC-DAG: @"\01??$StaticVar@UExplicitSpec_Def_Exported@@@MemVarTmpl@@2HB" = weak_odr dllexport constant i32 1, comdat, align 4 // GNU-DAG: @_ZN10MemVarTmpl9StaticVarI25ExplicitSpec_Def_ExportedEE = dllexport constant i32 1, align 4 template<> __declspec(dllexport) const int MemVarTmpl::StaticVar = 1; diff --git a/test/CodeGenCXX/dllexport.cpp b/test/CodeGenCXX/dllexport.cpp index c598880b625e..1412ad866bd3 100644 --- a/test/CodeGenCXX/dllexport.cpp +++ b/test/CodeGenCXX/dllexport.cpp @@ -544,6 +544,7 @@ struct A { struct __declspec(dllexport) B { B(A = 0) {} }; + } // // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??_FB@PR23801@@QAEXXZ"({{.*}}) comdat @@ -582,7 +583,7 @@ void W::foo() {} // M32-DAG: define weak_odr dllexport x86_thiscallcc %struct.W* @"\01??0W@@QAE@ABU0@@Z" // vftable: // M32-DAG: [[W_VTABLE:@.*]] = private unnamed_addr constant [2 x i8*] [i8* bitcast (%rtti.CompleteObjectLocator* @"\01??_R4W@@6B@" to i8*), i8* bitcast (void (%struct.W*)* @"\01?foo@W@@UAEXXZ" to i8*)], comdat($"\01??_7W@@6B@") -// M32-DAG: @"\01??_7W@@6B@" = dllexport unnamed_addr alias getelementptr inbounds ([2 x i8*], [2 x i8*]* [[W_VTABLE]], i32 0, i32 1) +// M32-DAG: @"\01??_7W@@6B@" = dllexport unnamed_addr alias i8*, getelementptr inbounds ([2 x i8*], [2 x i8*]* [[W_VTABLE]], i32 0, i32 1) // G32-DAG: @_ZTV1W = dllexport unnamed_addr constant [3 x i8*] [i8* null, i8* bitcast ({ i8*, i8* }* @_ZTI1W to i8*), i8* bitcast (void (%struct.W*)* @_ZN1W3fooEv to i8*)] struct __declspec(dllexport) X : public virtual W {}; @@ -611,7 +612,6 @@ namespace UseDtorAlias { B::~B() { } // Emit a alias definition of B's constructor. // M32-DAG: @"\01??1B@UseDtorAlias@@QAE@XZ" = dllexport alias {{.*}} @"\01??1A@UseDtorAlias@@QAE@XZ" - } struct __declspec(dllexport) DefaultedCtorsDtors { @@ -729,6 +729,54 @@ extern template struct PR23770DerivedTemplate; template struct __declspec(dllexport) PR23770DerivedTemplate; // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?f@?$PR23770BaseTemplate@H@@QAEXXZ" +namespace InClassInits { + +struct __declspec(dllexport) S { + int x = 42; +}; +// M32-DAG: define weak_odr dllexport x86_thiscallcc %"struct.InClassInits::S"* @"\01??0S@InClassInits@@QAE@XZ" + +// dllexport an already instantiated class template. +template struct Base { + int x = 42; +}; +Base base; +struct __declspec(dllexport) T : Base { }; +// M32-DAG: define weak_odr dllexport x86_thiscallcc %"struct.InClassInits::Base"* @"\01??0?$Base@H@InClassInits@@QAE@XZ" + +struct A { A(int); }; +struct __declspec(dllexport) U { + // Class with both default constructor closure and in-class initializer. + U(A = 0) {} + int x = 0; +}; +// M32-DAG: define weak_odr dllexport x86_thiscallcc %"struct.InClassInits::U"* @"\01??0U@InClassInits@@QAE@UA@1@@Z" + +struct Evil { + template struct Base { + int x = 0; + }; + struct S : Base {}; + // The already instantiated Base becomes dllexported below, but the + // in-class initializer for Base<>::x still hasn't been parsed, so emitting + // the default ctor must still be delayed. + struct __declspec(dllexport) T : Base {}; +}; +// M32-DAG: define weak_odr dllexport x86_thiscallcc %"struct.InClassInits::Evil::Base"* @"\01??0?$Base@H@Evil@InClassInits@@QAE@XZ" + +template struct Foo {}; +template struct Bar { + Bar &operator=(Foo) {} +}; +struct __declspec(dllexport) Baz { + Bar n; +}; +// After parsing Baz, in ActOnFinishCXXNonNestedClass we would synthesize +// Baz's operator=, causing instantiation of Foo after which +// ActOnFinishCXXNonNestedClass is called, and we would bite our own tail. +// M32-DAG: define weak_odr dllexport x86_thiscallcc dereferenceable(1) %"struct.InClassInits::Baz"* @"\01??4Baz@InClassInits@@QAEAAU01@ABU01@@Z" +} + //===----------------------------------------------------------------------===// // Classes with template base classes diff --git a/test/CodeGenCXX/dllimport-rtti.cpp b/test/CodeGenCXX/dllimport-rtti.cpp index 6fe67daa38d7..071ce278a5bb 100644 --- a/test/CodeGenCXX/dllimport-rtti.cpp +++ b/test/CodeGenCXX/dllimport-rtti.cpp @@ -19,7 +19,9 @@ struct U : S { struct __declspec(dllimport) V { virtual void f(); } v; -// GNU-DAG: @_ZTV1V = external dllimport +// GNU-DAG: @_ZTV1V = available_externally dllimport +// GNU-DAG: @_ZTS1V = linkonce_odr +// GNU-DAG: @_ZTI1V = linkonce_odr struct W { __declspec(dllimport) virtual void f(); diff --git a/test/CodeGenCXX/dllimport.cpp b/test/CodeGenCXX/dllimport.cpp index 0f15ff0291b9..b9c850b8b87b 100644 --- a/test/CodeGenCXX/dllimport.cpp +++ b/test/CodeGenCXX/dllimport.cpp @@ -2,8 +2,8 @@ // RUN: %clang_cc1 -triple x86_64-windows-msvc -fno-rtti -fno-threadsafe-statics -fms-extensions -emit-llvm -std=c++1y -O0 -o - %s -DMSABI -w | FileCheck --check-prefix=MSC --check-prefix=M64 %s // RUN: %clang_cc1 -triple i686-windows-gnu -fno-rtti -fno-threadsafe-statics -fms-extensions -emit-llvm -std=c++1y -O0 -o - %s -w | FileCheck --check-prefix=GNU --check-prefix=G32 %s // RUN: %clang_cc1 -triple x86_64-windows-gnu -fno-rtti -fno-threadsafe-statics -fms-extensions -emit-llvm -std=c++1y -O0 -o - %s -w | FileCheck --check-prefix=GNU --check-prefix=G64 %s -// RUN: %clang_cc1 -triple i686-windows-msvc -fno-rtti -fno-threadsafe-statics -fms-extensions -fms-compatibility-version=18.00 -emit-llvm -std=c++1y -O1 -o - %s -DMSABI -w | FileCheck --check-prefix=MO1 --check-prefix=M18 %s -// RUN: %clang_cc1 -triple i686-windows-msvc -fno-rtti -fno-threadsafe-statics -fms-extensions -fms-compatibility-version=19.00 -emit-llvm -std=c++1y -O1 -o - %s -DMSABI -w | FileCheck --check-prefix=MO1 --check-prefix=M19 %s +// RUN: %clang_cc1 -triple i686-windows-msvc -fno-rtti -fno-threadsafe-statics -fms-extensions -fms-compatibility-version=18.00 -emit-llvm -std=c++1y -O1 -disable-llvm-optzns -o - %s -DMSABI -w | FileCheck --check-prefix=MO1 --check-prefix=M18 %s +// RUN: %clang_cc1 -triple i686-windows-msvc -fno-rtti -fno-threadsafe-statics -fms-extensions -fms-compatibility-version=19.00 -emit-llvm -std=c++1y -O1 -disable-llvm-optzns -o - %s -DMSABI -w | FileCheck --check-prefix=MO1 --check-prefix=M19 %s // RUN: %clang_cc1 -triple i686-windows-gnu -fno-rtti -fno-threadsafe-statics -fms-extensions -emit-llvm -std=c++1y -O1 -o - %s -w | FileCheck --check-prefix=GO1 %s // CHECK-NOT doesn't play nice with CHECK-DAG, so use separate run lines. @@ -86,7 +86,7 @@ USEVAR(GlobalRedecl3) namespace ns { __declspec(dllimport) int ExternalGlobal; } USEVAR(ns::ExternalGlobal) -int f(); +int __declspec(dllimport) f(); // MO1-DAG: @"\01?x@?1??inlineStaticLocalsFunc@@YAHXZ@4HA" = available_externally dllimport global i32 0 // MO1-DAG: @"\01??_B?1??inlineStaticLocalsFunc@@YAHXZ@51" = available_externally dllimport global i32 0 inline int __declspec(dllimport) inlineStaticLocalsFunc() { @@ -314,6 +314,46 @@ void UNIQ(use)() { ::operator new(42); } namespace ns { __declspec(dllimport) void externalFunc(); } USE(ns::externalFunc) +// A dllimport function referencing non-imported vars or functions must not be available_externally. +__declspec(dllimport) int ImportedVar; +int NonImportedVar; +__declspec(dllimport) int ImportedFunc(); +int NonImportedFunc(); +__declspec(dllimport) inline int ReferencingImportedVar() { return ImportedVar; } +// MO1-DAG: define available_externally dllimport i32 @"\01?ReferencingImportedVar@@YAHXZ" +__declspec(dllimport) inline int ReferencingNonImportedVar() { return NonImportedVar; } +// MO1-DAG: declare dllimport i32 @"\01?ReferencingNonImportedVar@@YAHXZ"() +__declspec(dllimport) inline int ReferencingImportedFunc() { return ImportedFunc(); } +// MO1-DAG: define available_externally dllimport i32 @"\01?ReferencingImportedFunc@@YAHXZ" +__declspec(dllimport) inline int ReferencingNonImportedFunc() { return NonImportedFunc(); } +// MO1-DAG: declare dllimport i32 @"\01?ReferencingNonImportedFunc@@YAHXZ"() +USE(ReferencingImportedVar) +USE(ReferencingNonImportedVar) +USE(ReferencingImportedFunc) +USE(ReferencingNonImportedFunc) +// References to operator new and delete count too, despite not being DeclRefExprs. +__declspec(dllimport) inline int *ReferencingNonImportedNew() { return new int[2]; } +// MO1-DAG: declare dllimport i32* @"\01?ReferencingNonImportedNew@@YAPAHXZ" +__declspec(dllimport) inline int *ReferencingNonImportedDelete() { delete (int*)nullptr; } +// MO1-DAG: declare dllimport i32* @"\01?ReferencingNonImportedDelete@@YAPAHXZ" +USE(ReferencingNonImportedNew) +USE(ReferencingNonImportedDelete) +__declspec(dllimport) void* operator new[](__SIZE_TYPE__); +__declspec(dllimport) void operator delete(void*); +__declspec(dllimport) inline int *ReferencingImportedNew() { return new int[2]; } +// MO1-DAG: define available_externally dllimport i32* @"\01?ReferencingImportedNew@@YAPAHXZ" +__declspec(dllimport) inline int *ReferencingImportedDelete() { delete (int*)nullptr; } +// MO1-DAG: define available_externally dllimport i32* @"\01?ReferencingImportedDelete@@YAPAHXZ" +USE(ReferencingImportedNew) +USE(ReferencingImportedDelete) + +// A dllimport function with a TLS variable must not be available_externally. +__declspec(dllimport) inline void FunctionWithTLSVar() { static __thread int x = 42; } +// MO1-DAG: declare dllimport void @"\01?FunctionWithTLSVar@@YAXXZ" +__declspec(dllimport) inline void FunctionWithNormalVar() { static int x = 42; } +// MO1-DAG: define available_externally dllimport void @"\01?FunctionWithNormalVar@@YAXXZ" +USE(FunctionWithTLSVar) +USE(FunctionWithNormalVar) //===----------------------------------------------------------------------===// @@ -581,7 +621,7 @@ struct __declspec(dllimport) KeyFuncClass { constexpr KeyFuncClass() {} virtual void foo(); }; -constexpr KeyFuncClass keyFuncClassVar; +extern constexpr KeyFuncClass keyFuncClassVar = {}; // G32-DAG: @_ZTV12KeyFuncClass = external dllimport unnamed_addr constant [3 x i8*] struct __declspec(dllimport) X : public virtual W {}; diff --git a/test/CodeGenCXX/duplicate-mangled-name.cpp b/test/CodeGenCXX/duplicate-mangled-name.cpp index e57012e8c414..104bb6eb4d62 100644 --- a/test/CodeGenCXX/duplicate-mangled-name.cpp +++ b/test/CodeGenCXX/duplicate-mangled-name.cpp @@ -1,4 +1,7 @@ -// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm-only %s -verify +// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm-only %s -verify -DTEST1 +// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm-only %s -verify -DTEST2 + +#ifdef TEST1 // rdar://15522601 class MyClass { @@ -8,3 +11,34 @@ void MyClass::meth() { } // expected-note {{previous}} extern "C" { void _ZN7MyClass4methEv() { } // expected-error {{definition with same mangled name as another definition}} } + +#elif TEST2 + +// We expect no warnings here, as there is only declaration of _ZN1TD1Ev function, no definitions. +extern "C" void _ZN1TD1Ev(); +struct T { + ~T() {} +}; + +void foo() { + _ZN1TD1Ev(); + T t; +} + +extern "C" void _ZN2T2D2Ev() {}; // expected-note {{previous definition is here}} + +struct T2 { + ~T2() {} // expected-error {{definition with same mangled name as another definition}} +}; + +void bar() { + _ZN2T2D2Ev(); + T2 t; +} + +#else + +#error Unknwon test + +#endif + diff --git a/test/CodeGenCXX/enable_if.cpp b/test/CodeGenCXX/enable_if.cpp index 00c55c774909..e17695b413b6 100644 --- a/test/CodeGenCXX/enable_if.cpp +++ b/test/CodeGenCXX/enable_if.cpp @@ -1,4 +1,13 @@ // RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-pc-linux-gnu| FileCheck %s + +// Test address-of overloading logic +int test5(int); +template +T test5(T) __attribute__((enable_if(1, "better than non-template"))); + +// CHECK: @_Z5test5IiEUa9enable_ifIXLi1EEET_S0_ +int (*Ptr)(int) = &test5; + // Test itanium mangling for attribute enable_if // CHECK: _Z5test1Ua9enable_ifIXeqfL0p_Li1EEEi diff --git a/test/CodeGenCXX/exceptions-cxx-new.cpp b/test/CodeGenCXX/exceptions-cxx-new.cpp new file mode 100644 index 000000000000..3767f3321c3e --- /dev/null +++ b/test/CodeGenCXX/exceptions-cxx-new.cpp @@ -0,0 +1,77 @@ +// RUN: %clang_cc1 %s -triple i686-pc-win32 -fms-extensions -fexceptions -fcxx-exceptions -fnew-ms-eh -emit-llvm -o - -std=c++11 | FileCheck %s + +int f(int); + +void test_catch() { + try { + f(1); + } catch (int) { + f(2); + } catch (double) { + f(3); + } +} + +// CHECK-LABEL: define void @"\01?test_catch@@YAXXZ"( +// CHECK: invoke i32 @"\01?f@@YAHH@Z"(i32 1) +// CHECK: to label %[[NORMAL:.*]] unwind label %[[CATCHSWITCH:.*]] + +// CHECK: [[CATCHSWITCH]] +// CHECK: %[[CATCHSWITCHPAD:.*]] = catchswitch within none [label %[[CATCH_INT:.*]], label %[[CATCH_DOUBLE:.*]]] unwind to caller + +// CHECK: [[CATCH_INT]] +// CHECK: %[[CATCHPAD_INT:.*]] = catchpad within %[[CATCHSWITCHPAD]] [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null] +// CHECK: call i32 @"\01?f@@YAHH@Z"(i32 2) +// CHECK: catchret from %[[CATCHPAD_INT]] to label %[[LEAVE_INT_CATCH:.*]] + +// CHECK: [[LEAVE_INT_CATCH]] +// CHECK: br label %[[LEAVE_FUNC:.*]] + +// CHECK: [[LEAVE_FUNC]] +// CHECK: ret void + +// CHECK: [[CATCH_DOUBLE]] +// CHECK: %[[CATCHPAD_DOUBLE:.*]] = catchpad within %[[CATCHSWITCHPAD]] [%rtti.TypeDescriptor2* @"\01??_R0N@8", i32 0, i8* null] +// CHECK: call i32 @"\01?f@@YAHH@Z"(i32 3) +// CHECK: catchret from %[[CATCHPAD_DOUBLE]] to label %[[LEAVE_DOUBLE_CATCH:.*]] + +// CHECK: [[LEAVE_DOUBLE_CATCH]] +// CHECK: br label %[[LEAVE_FUNC]] + +// CHECK: [[NORMAL]] +// CHECK: br label %[[LEAVE_FUNC]] + +struct Cleanup { + ~Cleanup() { f(-1); } +}; + +void test_cleanup() { + Cleanup C; + f(1); +} + +// CHECK-LABEL: define {{.*}} @"\01?test_cleanup@@YAXXZ"( +// CHECK: invoke i32 @"\01?f@@YAHH@Z"(i32 1) +// CHECK: to label %[[LEAVE_FUNC:.*]] unwind label %[[CLEANUP:.*]] + +// CHECK: [[LEAVE_FUNC]] +// CHECK: call x86_thiscallcc void @"\01??_DCleanup@@QAE@XZ"( +// CHECK: ret void + +// CHECK: [[CLEANUP]] +// CHECK: %[[CLEANUPPAD:.*]] = cleanuppad within none [] +// CHECK: call x86_thiscallcc void @"\01??_DCleanup@@QAE@XZ"( +// CHECK: cleanupret from %[[CLEANUPPAD]] unwind to caller + + +// CHECK-LABEL: define {{.*}} void @"\01??1Cleanup@@QAE@XZ"( +// CHECK: invoke i32 @"\01?f@@YAHH@Z"(i32 -1) +// CHECK: to label %[[LEAVE_FUNC:.*]] unwind label %[[TERMINATE:.*]] + +// CHECK: [[LEAVE_FUNC]] +// CHECK: ret void + +// CHECK: [[TERMINATE]] +// CHECK: cleanuppad within none [] +// CHECK-NEXT: call void @"\01?terminate@@YAXXZ"() + diff --git a/test/CodeGenCXX/exceptions-seh-filter-captures.cpp b/test/CodeGenCXX/exceptions-seh-filter-captures.cpp index 26ef90f5a6f3..4e8be72089d5 100644 --- a/test/CodeGenCXX/exceptions-seh-filter-captures.cpp +++ b/test/CodeGenCXX/exceptions-seh-filter-captures.cpp @@ -21,9 +21,10 @@ extern "C" void test_freefunc(int p1) { // CHECK: invoke void @might_crash() // CHECK-LABEL: define internal i32 @"\01?filt$0@0@test_freefunc@@"(i8* %exception_pointers, i8* %frame_pointer) -// CHECK: %[[p1_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void (i32)* @test_freefunc to i8*), i8* %frame_pointer, i32 0) +// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (void (i32)* @test_freefunc to i8*), i8* %frame_pointer) +// CHECK: %[[p1_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void (i32)* @test_freefunc to i8*), i8* %[[fp]], i32 0) // CHECK: %[[p1_ptr:[^ ]*]] = bitcast i8* %[[p1_i8]] to i32* -// CHECK: %[[l1_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void (i32)* @test_freefunc to i8*), i8* %frame_pointer, i32 1) +// CHECK: %[[l1_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void (i32)* @test_freefunc to i8*), i8* %[[fp]], i32 1) // CHECK: %[[l1_ptr:[^ ]*]] = bitcast i8* %[[l1_i8]] to i32* // CHECK: %[[s1:[^ ]*]] = load i32, i32* @"\01?s1@?1??test_freefunc@@9@4HA", align 4 // CHECK: %[[l1:[^ ]*]] = load i32, i32* %[[l1_ptr]] @@ -50,7 +51,8 @@ void S::test_method() { // CHECK: invoke void @might_crash() // CHECK-LABEL: define internal i32 @"\01?filt$0@0@test_method@S@@"(i8* %exception_pointers, i8* %frame_pointer) -// CHECK: %[[l1_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void (%struct.S*)* @"\01?test_method@S@@QEAAXXZ" to i8*), i8* %frame_pointer, i32 0) +// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (void (%struct.S*)* @"\01?test_method@S@@QEAAXXZ" to i8*), i8* %frame_pointer) +// CHECK: %[[l1_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void (%struct.S*)* @"\01?test_method@S@@QEAAXXZ" to i8*), i8* %[[fp]], i32 0) // CHECK: %[[l1_ptr:[^ ]*]] = bitcast i8* %[[l1_i8]] to i32* // CHECK: %[[l1:[^ ]*]] = load i32, i32* %[[l1_ptr]] // CHECK: call i32 (i32, ...) @basic_filter(i32 %[[l1]]) @@ -74,7 +76,8 @@ void test_lambda() { // CHECK: invoke void @might_crash() // CHECK-LABEL: define internal i32 @"\01?filt$0@0@?R@?test_lambda@@YAXXZ@"(i8* %exception_pointers, i8* %frame_pointer) -// CHECK: %[[l2_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void (%class.anon*)* @"\01??R@?test_lambda@@YAXXZ@QEBAXXZ" to i8*), i8* %frame_pointer, i32 0) +// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (void (%class.anon*)* @"\01??R@?test_lambda@@YAXXZ@QEBAXXZ" to i8*), i8* %frame_pointer) +// CHECK: %[[l2_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void (%class.anon*)* @"\01??R@?test_lambda@@YAXXZ@QEBAXXZ" to i8*), i8* %[[fp]], i32 0) // CHECK: %[[l2_ptr:[^ ]*]] = bitcast i8* %[[l2_i8]] to i32* // CHECK: %[[l2:[^ ]*]] = load i32, i32* %[[l2_ptr]] // CHECK: call i32 (i32, ...) @basic_filter(i32 %[[l2]]) diff --git a/test/CodeGenCXX/exceptions-seh.cpp b/test/CodeGenCXX/exceptions-seh.cpp index 187ad4bc710e..abbe95be3404 100644 --- a/test/CodeGenCXX/exceptions-seh.cpp +++ b/test/CodeGenCXX/exceptions-seh.cpp @@ -32,13 +32,9 @@ extern "C" void use_cxx() { // CXXEH: ret void // // CXXEH: [[lpad]] -// CXXEH: landingpad { i8*, i32 } -// CXXEH-NEXT: cleanup +// CXXEH: cleanuppad // CXXEH: call void @"\01??1HasCleanup@@QEAA@XZ"(%struct.HasCleanup* %{{.*}}) -// CXXEH: br label %[[resume:[^ ]*]] -// -// CXXEH: [[resume]] -// CXXEH: resume +// CXXEH: cleanupret // NOCXX-LABEL: define void @use_cxx() // NOCXX-NOT: invoke @@ -64,17 +60,21 @@ extern "C" void use_seh() { // CHECK: invoke void @might_throw() #[[NOINLINE:[0-9]+]] // CHECK: to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]] // -// CHECK: [[cont]] -// CHECK: br label %[[ret:[^ ]*]] -// // CHECK: [[lpad]] -// CHECK: landingpad { i8*, i32 } -// CHECK-NEXT: catch i8* +// CHECK-NEXT: %[[switch:.*]] = catchswitch within none [label %[[cpad:.*]]] unwind to caller // -// CHECK: br label %[[ret]] +// CHECK: [[cpad]] +// CHECK-NEXT: catchpad within %[[switch]] +// CHECK: catchret {{.*}} label %[[except:[^ ]*]] +// +// CHECK: [[except]] +// CHECK: br label %[[ret:[^ ]*]] // // CHECK: [[ret]] // CHECK: ret void +// +// CHECK: [[cont]] +// CHECK: br label %[[ret]] void use_seh_in_lambda() { ([]() { @@ -89,7 +89,7 @@ void use_seh_in_lambda() { // CXXEH-LABEL: define void @"\01?use_seh_in_lambda@@YAXXZ"() // CXXEH-SAME: personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) -// CXXEH: landingpad { i8*, i32 } +// CXXEH: cleanuppad // NOCXX-LABEL: define void @"\01?use_seh_in_lambda@@YAXXZ"() // NOCXX-NOT: invoke @@ -98,7 +98,7 @@ void use_seh_in_lambda() { // CHECK-LABEL: define internal void @"\01??R@?use_seh_in_lambda@@YAXXZ@QEBAXXZ"(%class.anon* %this) // CXXEH-SAME: personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) // CHECK: invoke void @might_throw() #[[NOINLINE]] -// CHECK: landingpad { i8*, i32 } +// CHECK: catchpad static int my_unique_global; @@ -122,8 +122,7 @@ void use_inline() { // CHECK-SAME: personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) // CHECK: invoke void @might_throw() // -// CHECK: landingpad { i8*, i32 } -// CHECK-NEXT: catch i8* bitcast (i32 (i8*, i8*)* @"\01?filt$0@0@use_seh_in_inline_func@@" to i8*) +// CHECK: catchpad {{.*}} [i8* bitcast (i32 (i8*, i8*)* @"\01?filt$0@0@use_seh_in_inline_func@@" to i8*)] // // CHECK: invoke void @might_throw() // @@ -131,8 +130,7 @@ void use_inline() { // CHECK: call void @"\01?fin$0@0@use_seh_in_inline_func@@"(i8 0, i8* %[[fp]]) // CHECK: ret void // -// CHECK: landingpad { i8*, i32 } -// CHECK-NEXT: cleanup +// CHECK: cleanuppad // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress() // CHECK: call void @"\01?fin$0@0@use_seh_in_inline_func@@"(i8 1, i8* %[[fp]]) diff --git a/test/CodeGenCXX/exceptions.cpp b/test/CodeGenCXX/exceptions.cpp index e8f6c7996a16..ff76b11350db 100644 --- a/test/CodeGenCXX/exceptions.cpp +++ b/test/CodeGenCXX/exceptions.cpp @@ -1,6 +1,9 @@ // RUN: %clang_cc1 %s -triple=x86_64-linux-gnu -emit-llvm -o - -fcxx-exceptions -fexceptions | FileCheck %s -typedef typeof(sizeof(0)) size_t; +typedef __typeof(sizeof(0)) size_t; + +// Declare the reserved global placement new. +void *operator new(size_t, void*); // This just shouldn't crash. namespace test0 { @@ -526,4 +529,21 @@ namespace test11 { // (After this is a terminate landingpad.) } +namespace test12 { + struct A { + void operator delete(void *, void *); + A(); + }; + + A *test(void *ptr) { + return new (ptr) A(); + } + // CHECK-LABEL: define {{.*}} @_ZN6test124testEPv( + // CHECK: [[PTR:%.*]] = load i8*, i8* + // CHECK-NEXT: [[CAST:%.*]] = bitcast i8* [[PTR]] to [[A:%.*]]* + // CHECK-NEXT: invoke void @_ZN6test121AC1Ev([[A]]* [[CAST]]) + // CHECK: ret [[A]]* [[CAST]] + // CHECK: invoke void @_ZN6test121AdlEPvS1_(i8* [[PTR]], i8* [[PTR]]) +} + // CHECK: attributes [[NI_NR_NUW]] = { noinline noreturn nounwind } diff --git a/test/CodeGenCXX/extern-c.cpp b/test/CodeGenCXX/extern-c.cpp index e68738b9db58..5b59a38ba0d7 100644 --- a/test/CodeGenCXX/extern-c.cpp +++ b/test/CodeGenCXX/extern-c.cpp @@ -59,10 +59,10 @@ extern "C" { // CHECK-NOT: @unused // CHECK-NOT: @duplicate_internal - // CHECK: @internal_var = internal alias i32* @_Z12internal_var + // CHECK: @internal_var = internal alias i32, i32* @_Z12internal_var // CHECK-NOT: @unused // CHECK-NOT: @duplicate_internal - // CHECK: @internal_fn = internal alias i32 ()* @_Z11internal_fnv + // CHECK: @internal_fn = internal alias i32 (), i32 ()* @_Z11internal_fnv // CHECK-NOT: @unused // CHECK-NOT: @duplicate_internal } diff --git a/test/CodeGenCXX/funcattrs-global-ctor-dtor.cpp b/test/CodeGenCXX/funcattrs-global-ctor-dtor.cpp new file mode 100644 index 000000000000..b98cb24d5691 --- /dev/null +++ b/test/CodeGenCXX/funcattrs-global-ctor-dtor.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 %s -triple x86_64-apple-darwin -S -stack-protector 2 -emit-llvm -o - | FileCheck %s + +class A { + public: + virtual ~A() {} +}; + +A g; + +// CHECK: define internal void @__cxx_global_var_init() [[ATTR0:#[0-9]+]] +// CHECK: define internal void @_GLOBAL__sub_I_funcattrs_global_ctor_dtor.cpp() [[ATTR0]] +// CHECK: attributes [[ATTR0]] = {{{.*}} sspstrong {{.*}}} diff --git a/test/CodeGenCXX/globalinit-loc.cpp b/test/CodeGenCXX/globalinit-loc.cpp index 27120526fc30..203eb2142667 100644 --- a/test/CodeGenCXX/globalinit-loc.cpp +++ b/test/CodeGenCXX/globalinit-loc.cpp @@ -1,10 +1,10 @@ -// RUN: %clang_cc1 -emit-llvm -g %s -o - | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited %s -o - | FileCheck %s // rdar://problem/14985269. // // Verify that the global init helper function does not get associated // with any source location. // -// CHECK: define internal {{.*}}void @_GLOBAL__sub_I_globalinit_loc.cpp +// CHECK: define internal {{.*}}void @_GLOBAL__sub_I_globalinit_loc.cpp({{.*}} { // CHECK: !dbg ![[DBG:.*]] // CHECK: !DISubprogram(linkageName: "_GLOBAL__sub_I_globalinit_loc.cpp" // CHECK-NOT: line: diff --git a/test/CodeGenCXX/homogeneous-aggregates.cpp b/test/CodeGenCXX/homogeneous-aggregates.cpp index fbbb1ebed465..67911c0d7f90 100644 --- a/test/CodeGenCXX/homogeneous-aggregates.cpp +++ b/test/CodeGenCXX/homogeneous-aggregates.cpp @@ -91,7 +91,7 @@ struct HVAWithEmptyBase : Float1, Empty, Float2 { float z; }; // ARM32: define arm_aapcs_vfpcc void @_Z15with_empty_base16HVAWithEmptyBase(%struct.HVAWithEmptyBase %a.coerce) void CC with_empty_base(HVAWithEmptyBase a) {} -// FIXME: MSVC doesn't consider this an HVA becuase of the empty base. +// FIXME: MSVC doesn't consider this an HVA because of the empty base. // X64: define x86_vectorcallcc void @"\01_Z15with_empty_base16HVAWithEmptyBase@@16"(float %a.0, float %a.1, float %a.2) struct HVAWithEmptyBitField : Float1, Float2 { diff --git a/test/CodeGenCXX/init-invariant.cpp b/test/CodeGenCXX/init-invariant.cpp index 8af4ae6fde46..7f348257f263 100644 --- a/test/CodeGenCXX/init-invariant.cpp +++ b/test/CodeGenCXX/init-invariant.cpp @@ -56,5 +56,5 @@ void e() { // CHECK-LABEL: define void @_Z1ev( // CHECK: call void @_ZN1AC1Ev(%struct.A* nonnull @_ZZ1evE1a) -// CHECK: call {{.*}}@llvm.invariant.start(i64 4, i8* bitcast ({{.*}} @_ZZ1evE1a to i8*)) +// CHECK: call {{.*}}@llvm.invariant.start(i64 4, i8* nonnull bitcast ({{.*}} @_ZZ1evE1a to i8*)) // CHECK-NOT: llvm.invariant.end diff --git a/test/CodeGenCXX/inline-dllexport-member.cpp b/test/CodeGenCXX/inline-dllexport-member.cpp index 4bc1d4ce633a..2160f32e0b4f 100644 --- a/test/CodeGenCXX/inline-dllexport-member.cpp +++ b/test/CodeGenCXX/inline-dllexport-member.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple i686-windows-gnu -fms-compatibility -g -emit-llvm %s -o - \ +// RUN: %clang_cc1 -triple i686-windows-win32 -fms-extensions -debug-info-kind=limited -emit-llvm %s -o - \ // RUN: | FileCheck %s struct __declspec(dllexport) s { @@ -6,6 +6,6 @@ struct __declspec(dllexport) s { }; // CHECK: ![[SCOPE:[0-9]+]] = distinct !DICompileUnit( -// CHECK: !DIGlobalVariable(name: "ui", linkageName: "_ZN1s2uiE", scope: ![[SCOPE]], -// CHECK-SAME: variable: i32* @_ZN1s2uiE +// CHECK: !DIGlobalVariable(name: "ui", linkageName: "\01?ui@s@@2IB", scope: ![[SCOPE]], +// CHECK-SAME: variable: i32* @"\01?ui@s@@2IB" diff --git a/test/CodeGenCXX/inline-functions.cpp b/test/CodeGenCXX/inline-functions.cpp index 20da1f631809..f1169f91913e 100644 --- a/test/CodeGenCXX/inline-functions.cpp +++ b/test/CodeGenCXX/inline-functions.cpp @@ -1,12 +1,13 @@ // RUN: %clang_cc1 %s -std=c++11 -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s --check-prefix=CHECK --check-prefix=NORMAL -// RUN: %clang_cc1 %s -std=c++11 -fms-compatibility -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s --check-prefix=CHECK --check-prefix=MSVCCOMPAT +// RUN: %clang_cc1 %s -std=c++11 -fms-compatibility -triple=x86_64-pc-win32 -emit-llvm -o - | FileCheck %s --check-prefix=CHECK --check-prefix=MSVCCOMPAT // CHECK: ; ModuleID struct A { inline void f(); }; -// CHECK-NOT: define void @_ZN1A1fEv +// NORMAL-NOT: define void @_ZN1A1fEv +// MSVCCOMPAT-NOT: define void @"\01?f@A@@QEAAXXZ" void A::f() { } template struct B { }; @@ -15,18 +16,21 @@ template<> struct B { inline void f(); }; -// CHECK-NOT: _ZN1BIcE1fEv +// NORMAL-NOT: _ZN1BIcE1fEv +// MSVCCOMPAT-NOT: @"\01?f@?$B@D@@QEAAXXZ" void B::f() { } // We need a final CHECK line here. -// CHECK-LABEL: define void @_Z1fv +// NORMAL-LABEL: define void @_Z1fv +// MSVCCOMPAT-LABEL: define void @"\01?f@@YAXXZ" void f() { } // inline void f1(int); -// CHECK-LABEL: define linkonce_odr void @_Z2f1i +// NORMAL-LABEL: define linkonce_odr void @_Z2f1i +// MSVCCOMPAT-LABEL: define linkonce_odr void @"\01?f1@@YAXH@Z" void f1(int) { } void test_f1() { f1(17); } @@ -39,7 +43,8 @@ namespace test1 { void g() {} }; - // CHECK-LABEL: define linkonce_odr void @_ZN5test11C4funcEv( + // NORMAL-LABEL: define linkonce_odr void @_ZN5test11C4funcEv( + // MSVCCOMPAT-LABEL: define linkonce_odr void @"\01?func@C@test1@@QEAAXXZ"( class C { public: @@ -66,59 +71,65 @@ namespace test2 { A a; f(a); } - // CHECK-LABEL: define linkonce_odr void @_ZN5test21fERKNS_1AE + // NORMAL-LABEL: define linkonce_odr void @_ZN5test21fERKNS_1AE + // MSVCCOMPAT-LABEL: define linkonce_odr void @"\01?f@test2@@YAXAEBUA@1@@Z" } -// MSVCCOMPAT-LABEL: define weak_odr void @_Z17ExternAndInlineFnv // NORMAL-NOT: _Z17ExternAndInlineFnv +// MSVCCOMPAT-LABEL: define weak_odr void @"\01?ExternAndInlineFn@@YAXXZ" extern inline void ExternAndInlineFn() {} -// MSVCCOMPAT-LABEL: define weak_odr void @_Z18InlineThenExternFnv // NORMAL-NOT: _Z18InlineThenExternFnv +// MSVCCOMPAT-LABEL: define weak_odr void @"\01?InlineThenExternFn@@YAXXZ" inline void InlineThenExternFn() {} extern void InlineThenExternFn(); -// CHECK-LABEL: define void @_Z18ExternThenInlineFnv +// NORMAL-LABEL: define void @_Z18ExternThenInlineFnv +// MSVCCOMPAT-LABEL: define void @"\01?ExternThenInlineFn@@YAXXZ" extern void ExternThenInlineFn() {} -// MSVCCOMPAT-LABEL: define weak_odr void @_Z25ExternThenInlineThenDefFnv // NORMAL-NOT: _Z25ExternThenInlineThenDefFnv +// MSVCCOMPAT-LABEL: define weak_odr void @"\01?ExternThenInlineThenDefFn@@YAXXZ" extern void ExternThenInlineThenDefFn(); inline void ExternThenInlineThenDefFn(); void ExternThenInlineThenDefFn() {} -// MSVCCOMPAT-LABEL: define weak_odr void @_Z25InlineThenExternThenDefFnv // NORMAL-NOT: _Z25InlineThenExternThenDefFnv +// MSVCCOMPAT-LABEL: define weak_odr void @"\01?InlineThenExternThenDefFn@@YAXXZ" inline void InlineThenExternThenDefFn(); extern void InlineThenExternThenDefFn(); void InlineThenExternThenDefFn() {} -// MSVCCOMPAT-LABEL: define weak_odr i32 @_Z20ExternAndConstexprFnv // NORMAL-NOT: _Z17ExternAndConstexprFnv +// MSVCCOMPAT-LABEL: define weak_odr i32 @"\01?ExternAndConstexprFn@@YAHXZ" extern constexpr int ExternAndConstexprFn() { return 0; } -// CHECK-NOT: _Z11ConstexprFnv +// NORMAL-NOT: _Z11ConstexprFnv +// MSVCCOMPAT-NOT: @"\01?ConstexprFn@@YAHXZ" constexpr int ConstexprFn() { return 0; } template extern inline void ExternInlineOnPrimaryTemplate(T); -// CHECK-LABEL: define void @_Z29ExternInlineOnPrimaryTemplateIiEvT_ +// NORMAL-LABEL: define void @_Z29ExternInlineOnPrimaryTemplateIiEvT_ +// MSVCCOMPAT-LABEL: define void @"\01??$ExternInlineOnPrimaryTemplate@H@@YAXH@Z" template <> void ExternInlineOnPrimaryTemplate(int) {} template extern inline void ExternInlineOnPrimaryTemplateAndSpecialization(T); -// MSVCCOMPAT-LABEL: define weak_odr void @_Z46ExternInlineOnPrimaryTemplateAndSpecializationIiEvT_ // NORMAL-NOT: _Z46ExternInlineOnPrimaryTemplateAndSpecializationIiEvT_ +// MSVCCOMPAT-LABEL: define weak_odr void @"\01??$ExternInlineOnPrimaryTemplateAndSpecialization@H@@YAXH@Z" template <> extern inline void ExternInlineOnPrimaryTemplateAndSpecialization(int) {} struct TypeWithInlineMethods { - // CHECK-NOT: _ZN21TypeWithInlineMethods9StaticFunEv + // NORMAL-NOT: _ZN21TypeWithInlineMethods9StaticFunEv + // MSVCCOMPAT-NOT: @"\01?StaticFun@TypeWithInlineMethods@@SAXXZ" static void StaticFun() {} - // CHECK-NOT: _ZN21TypeWithInlineMethods12NonStaticFunEv + // NORMAL-NOT: _ZN21TypeWithInlineMethods12NonStaticFunEv + // MSVCCOMPAT-NOT: @"\01?NonStaticFun@TypeWithInlineMethods@@QEAAXXZ" void NonStaticFun() { StaticFun(); } }; @@ -134,5 +145,6 @@ struct S { }; __attribute__((used)) inline S Foo() { return S(); } -// CHECK-LABEL: define linkonce_odr void @_ZN7PR229593FooEv( +// NORMAL-LABEL: define linkonce_odr void @_ZN7PR229593FooEv( +// MSVCCOMPAT-LABEL: define linkonce_odr i8 @"\01?Foo@PR22959@@YA?AU?$S@H@1@XZ"( } diff --git a/test/CodeGenCXX/invariant.group-for-vptrs.cpp b/test/CodeGenCXX/invariant.group-for-vptrs.cpp new file mode 100644 index 000000000000..ca737ee23fb4 --- /dev/null +++ b/test/CodeGenCXX/invariant.group-for-vptrs.cpp @@ -0,0 +1,74 @@ +// RUN: %clang_cc1 -triple=x86_64-pc-linux-gnu -emit-llvm %s -fstrict-vtable-pointers -O1 -o - -disable-llvm-optzns | FileCheck %s + +struct A { + virtual void foo(); +}; + +struct D : A { + void foo(); +}; + +// CHECK-LABEL: define void @_Z21testExternallyVisiblev() +void testExternallyVisible() { + A *a = new A; + + // CHECK: load {{.*}} !invariant.group ![[A_MD:[0-9]+]] + a->foo(); + + D *d = new D; + // CHECK: call void @_ZN1DC1Ev( + // CHECK: load {{.*}} !invariant.group ![[D_MD:[0-9]+]] + d->foo(); + A *a2 = d; + // CHECK: load {{.*}} !invariant.group ![[A_MD]] + a2->foo(); +} +// CHECK-LABEL: } + +namespace { + +struct B { + virtual void bar(); +}; + +struct C : B { + void bar(); +}; + +} + +// CHECK-LABEL: define void @_Z21testInternallyVisibleb( +void testInternallyVisible(bool p) { + B *b = new B; + // CHECK: = load {{.*}}, !invariant.group ![[B_MD:[0-9]+]] + b->bar(); + + // CHECK: call void @_ZN12_GLOBAL__N_11CC1Ev( + C *c = new C; + // CHECK: = load {{.*}}, !invariant.group ![[C_MD:[0-9]+]] + c->bar(); +} + +// Checking A::A() +// CHECK-LABEL: define linkonce_odr void @_ZN1AC2Ev( +// CHECK: store {{.*}}, !invariant.group ![[A_MD]] +// CHECK-LABEL: } + +// Checking D::D() +// CHECK-LABEL: define linkonce_odr void @_ZN1DC2Ev( +// CHECK: = call i8* @llvm.invariant.group.barrier(i8* +// CHECK: call void @_ZN1AC2Ev(%struct.A* +// CHECK: store {{.*}} !invariant.group ![[D_MD]] + +// Checking B::B() +// CHECK-LABEL: define internal void @_ZN12_GLOBAL__N_11BC2Ev( +// CHECK: store {{.*}}, !invariant.group ![[B_MD]] + +// Checking C::C() +// CHECK-LABEL: define internal void @_ZN12_GLOBAL__N_11CC2Ev( +// CHECK: store {{.*}}, !invariant.group ![[C_MD]] + +// CHECK: ![[A_MD]] = !{!"_ZTS1A"} +// CHECK: ![[D_MD]] = !{!"_ZTS1D"} +// CHECK: ![[B_MD]] = distinct !{} +// CHECK: ![[C_MD]] = distinct !{} diff --git a/test/CodeGenCXX/lambda-expressions.cpp b/test/CodeGenCXX/lambda-expressions.cpp index 28a8841b600a..2ea0561f9e92 100644 --- a/test/CodeGenCXX/lambda-expressions.cpp +++ b/test/CodeGenCXX/lambda-expressions.cpp @@ -81,7 +81,7 @@ int g() { }; // PR14773 -// CHECK: [[ARRVAL:%[0-9a-zA-Z]*]] = load i32, i32* getelementptr inbounds ([0 x i32], [0 x i32]* @_ZZ14staticarrayrefvE5array, i32 0, i64 0), align 4 +// CHECK: [[ARRVAL:%[0-9a-zA-Z]*]] = load i32, i32* getelementptr inbounds ([0 x i32], [0 x i32]* @_ZZ14staticarrayrefvE5array, i64 0, i64 0), align 4 // CHECK-NEXT: store i32 [[ARRVAL]] void staticarrayref(){ static int array[] = {}; diff --git a/test/CodeGenCXX/linetable-cleanup.cpp b/test/CodeGenCXX/linetable-cleanup.cpp index 99aa814a9332..fbef05e53267 100644 --- a/test/CodeGenCXX/linetable-cleanup.cpp +++ b/test/CodeGenCXX/linetable-cleanup.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -g -triple x86_64-apple-darwin10 %s -o - | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited -triple x86_64-apple-darwin10 %s -o - | FileCheck %s // Check the line numbers for cleanup code with EH in combination with // simple return expressions. diff --git a/test/CodeGenCXX/linetable-eh.cpp b/test/CodeGenCXX/linetable-eh.cpp index 219aab1bf54b..8c0a3971c599 100644 --- a/test/CodeGenCXX/linetable-eh.cpp +++ b/test/CodeGenCXX/linetable-eh.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -g -triple x86_64-apple-macosx10.9.0 -munwind-tables -std=c++11 -fcxx-exceptions -fexceptions %s -o - | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited -triple x86_64-apple-macosx10.9.0 -munwind-tables -std=c++11 -fcxx-exceptions -fexceptions %s -o - | FileCheck %s // Test that emitting a landing pad does not affect the line table // entries for the code that triggered it. diff --git a/test/CodeGenCXX/linetable-fnbegin.cpp b/test/CodeGenCXX/linetable-fnbegin.cpp index 1f752ff0b4ec..f4cf53b0c5f5 100644 --- a/test/CodeGenCXX/linetable-fnbegin.cpp +++ b/test/CodeGenCXX/linetable-fnbegin.cpp @@ -1,13 +1,13 @@ -// RUN: %clang_cc1 -emit-llvm -g %s -o - | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited %s -o - | FileCheck %s // Test that the line table info for Foo::bar() is pointing to the // right header file. // CHECK: define{{.*}}bar // CHECK-NOT: define // CHECK: ret {{.*}}, !dbg [[DBG:.*]] // CHECK: [[HPP:.*]] = !DIFile(filename: "./template.hpp", -// CHECK: [[SP:.*]] = !DISubprogram(name: "bar", -// CHECK-SAME: file: [[HPP]], line: 22 -// CHECK-SAME: isDefinition: true +// CHECK: [[SP:.*]] = distinct !DISubprogram(name: "bar", +// CHECK-SAME: file: [[HPP]], line: 22 +// CHECK-SAME: isDefinition: true // We shouldn't need a lexical block for this function. // CHECK: [[DBG]] = !DILocation(line: 23, scope: [[SP]]) diff --git a/test/CodeGenCXX/linetable-virtual-variadic.cpp b/test/CodeGenCXX/linetable-virtual-variadic.cpp index 115f1ae71408..8d1bf47814f8 100644 --- a/test/CodeGenCXX/linetable-virtual-variadic.cpp +++ b/test/CodeGenCXX/linetable-virtual-variadic.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -gline-tables-only %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -debug-info-kind=line-tables-only %s -o - | FileCheck %s // Crasher for PR22929. class Base { virtual void VariadicFunction(...); @@ -10,7 +10,7 @@ class Derived : public virtual Base { void Derived::VariadicFunction(...) { } -// CHECK-LABEL: define void @_ZN7Derived16VariadicFunctionEz( +// CHECK: define void @_ZN7Derived16VariadicFunctionEz({{.*}} !dbg ![[SP:[0-9]+]] // CHECK: ret void, !dbg ![[LOC:[0-9]+]] // CHECK-LABEL: define void @_ZT{{.+}}N7Derived16VariadicFunctionEz( // CHECK: ret void, !dbg ![[LOC:[0-9]+]] @@ -18,6 +18,6 @@ void Derived::VariadicFunction(...) { } // CHECK: !llvm.dbg.cu = !{![[CU:[0-9]+]]} // // CHECK: ![[CU]] = distinct !DICompileUnit({{.*}} subprograms: ![[SPs:[0-9]+]] -// CHECK: ![[SPs]] = !{![[SP:[0-9]+]]} -// CHECK: ![[SP]] = !DISubprogram(name: "VariadicFunction",{{.*}} function: {{[^:]+}} @_ZN7Derived16VariadicFunctionEz +// CHECK: ![[SPs]] = !{![[SP]]} +// CHECK: ![[SP]] = distinct !DISubprogram(name: "VariadicFunction" // CHECK: ![[LOC]] = !DILocation({{.*}}scope: ![[SP]]) diff --git a/test/CodeGenCXX/lpad-linetable.cpp b/test/CodeGenCXX/lpad-linetable.cpp index 7f1d2214d8fc..69236693c9c2 100644 --- a/test/CodeGenCXX/lpad-linetable.cpp +++ b/test/CodeGenCXX/lpad-linetable.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -emit-llvm -g -triple x86_64-apple-darwin10 %s -o - | FileCheck %s +// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -emit-llvm -debug-info-kind=limited -triple x86_64-apple-darwin10 %s -o - | FileCheck %s // The landing pad should have the line number of the closing brace of the function. // rdar://problem/13888152 // CHECK: ret i32 diff --git a/test/CodeGenCXX/main-norecurse.cpp b/test/CodeGenCXX/main-norecurse.cpp new file mode 100644 index 000000000000..0f3640260962 --- /dev/null +++ b/test/CodeGenCXX/main-norecurse.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s + +// CHECK: define {{.*}} @main({{.*}}) #0 +int main(int argc, char **argv) { + return 1; +} + +// CHECK: attributes #0 = { norecurse{{.*}} } diff --git a/test/CodeGenCXX/mangle-literal-suffix.cpp b/test/CodeGenCXX/mangle-literal-suffix.cpp index ab557d5a1bfa..d3ca9ffc378d 100644 --- a/test/CodeGenCXX/mangle-literal-suffix.cpp +++ b/test/CodeGenCXX/mangle-literal-suffix.cpp @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 -triple mips-none-none -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple mips-none-none -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=FP64 +// RUN: %clang_cc1 -triple powerpc64-none-none -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=FP128 template void g3(char (&buffer)[sizeof(T() + 5.0)]) {} template void g3(char (&)[sizeof(double)]); @@ -6,7 +7,8 @@ template void g3(char (&)[sizeof(double)]); template void g4(char (&buffer)[sizeof(T() + 5.0L)]) {} template void g4(char (&)[sizeof(long double)]); -// CHECK: _Z2g4IiEvRAszplcvT__ELe4014000000000000E_c +// FP64: _Z2g4IiEvRAszplcvT__ELe4014000000000000E_c +// FP128: _Z2g4IiEvRAszplcvT__ELg00000000000000004014000000000000E_c template void g5(char (&buffer)[sizeof(T() + 5)]) {} template void g5(char (&)[sizeof(int)]); diff --git a/test/CodeGenCXX/mangle-ms-cxx11.cpp b/test/CodeGenCXX/mangle-ms-cxx11.cpp index 3f4075f7f372..999def87fc5e 100644 --- a/test/CodeGenCXX/mangle-ms-cxx11.cpp +++ b/test/CodeGenCXX/mangle-ms-cxx11.cpp @@ -243,3 +243,46 @@ void f() {} template void f(); // CHECK-DAG: @"\01??$f@$$YAliasA@PR20047@@@PR20047@@YAXXZ" } + +namespace UnnamedType { +struct A { + struct {} *TD; +}; + +void f(decltype(*A::TD)) {} +// CHECK-DAG: @"\01?f@UnnamedType@@YAXAAU@A@1@@Z" + +template +struct B { + enum { + } *e; +}; + +void f(decltype(B::e)) {} +// CHECK-DAG: @"\01?f@UnnamedType@@YAXPAW4@?$B@H@1@@Z +} + +namespace PR24651 { +template +void f(T) {} + +void g() { + enum {} E; + f(E); + { + enum {} E; + f(E); + } +} +// CHECK-DAG: @"\01??$f@W4@?1??g@PR24651@@YAXXZ@@PR24651@@YAXW4@?1??g@0@YAXXZ@@Z" +// CHECK-DAG: @"\01??$f@W4@?2??g@PR24651@@YAXXZ@@PR24651@@YAXW4@?2??g@0@YAXXZ@@Z" +} + +namespace PR18204 { +template +int f(T *); +static union { + int n = f(this); +}; +// CHECK-DAG: @"\01??$f@T@PR18204@@@PR18204@@YAHPAT@0@@Z" +} diff --git a/test/CodeGenCXX/mangle-ms-cxx14.cpp b/test/CodeGenCXX/mangle-ms-cxx14.cpp index 51627dd89e19..9d30c406c8c7 100644 --- a/test/CodeGenCXX/mangle-ms-cxx14.cpp +++ b/test/CodeGenCXX/mangle-ms-cxx14.cpp @@ -3,27 +3,27 @@ template int x = 0; -// CHECK: "\01??$x@X@@3HA" +// CHECK-DAG: "\01??$x@X@@3HA" template <> int x; -// CHECK: "\01??$x@H@@3HA" +// CHECK-DAG: "\01??$x@H@@3HA" template <> int x; -// CHECK: "\01?FunctionWithLocalType@@YA?A?@@XZ" +// CHECK-DAG: "\01?FunctionWithLocalType@@YA?A?@@XZ" auto FunctionWithLocalType() { struct LocalType {}; return LocalType{}; } -// CHECK: "\01?ValueFromFunctionWithLocalType@@3ULocalType@?1??FunctionWithLocalType@@YA?A?@@XZ@A" +// CHECK-DAG: "\01?ValueFromFunctionWithLocalType@@3ULocalType@?1??FunctionWithLocalType@@YA?A?@@XZ@A" auto ValueFromFunctionWithLocalType = FunctionWithLocalType(); -// CHECK: "\01??R@@QBE?A?@@XZ" +// CHECK-DAG: "\01??R@@QBE?A?@@XZ" auto LambdaWithLocalType = [] { struct LocalType {}; return LocalType{}; }; -// CHECK: "\01?ValueFromLambdaWithLocalType@@3ULocalType@?1???R@@QBE?A?@@XZ@A" +// CHECK-DAG: "\01?ValueFromLambdaWithLocalType@@3ULocalType@?1???R@@QBE?A?@@XZ@A" auto ValueFromLambdaWithLocalType = LambdaWithLocalType(); template @@ -39,6 +39,19 @@ auto TemplateFuncionWithLocalLambda(T) { // MSVC2013-DAG: "\01?ValueFromTemplateFuncionWithLocalLambda@@3ULocalType@?2???R@??$TemplateFuncionWithLocalLambda@H@@YA?A?@@H@Z@QBE?A?3@XZ@A" // MSVC2015-DAG: "\01?ValueFromTemplateFuncionWithLocalLambda@@3ULocalType@?1???R@??$TemplateFuncionWithLocalLambda@H@@YA?A?@@H@Z@QBE?A?3@XZ@A" // MSVC2015-DAG: "\01?ValueFromTemplateFuncionWithLocalLambda@@3ULocalType@?1???R@??$TemplateFuncionWithLocalLambda@H@@YA?A?@@H@Z@QBE?A?3@XZ@A" -// CHECK: "\01??$TemplateFuncionWithLocalLambda@H@@YA?A?@@H@Z" -// CHECK: "\01??R@??$TemplateFuncionWithLocalLambda@H@@YA?A?@@H@Z@QBE?A?1@XZ" +// CHECK-DAG: "\01??$TemplateFuncionWithLocalLambda@H@@YA?A?@@H@Z" +// CHECK-DAG: "\01??R@??$TemplateFuncionWithLocalLambda@H@@YA?A?@@H@Z@QBE?A?1@XZ" auto ValueFromTemplateFuncionWithLocalLambda = TemplateFuncionWithLocalLambda(0); + +struct S; +template +int WithPMD = 0; + +template <> int WithPMD; +// CHECK-DAG: "\01??$WithPMD@$GA@A@?0@@3HA" + +template +struct Foo {}; + +Foo<&x, &x> Zoo; +// CHECK-DAG: "\01?Zoo@@3U?$Foo@$1??$x@H@@3HA$1?1@3HA@@A" diff --git a/test/CodeGenCXX/mangle-ms-vector-types.cpp b/test/CodeGenCXX/mangle-ms-vector-types.cpp index aca492918a1e..53a1a43fe4af 100644 --- a/test/CodeGenCXX/mangle-ms-vector-types.cpp +++ b/test/CodeGenCXX/mangle-ms-vector-types.cpp @@ -27,7 +27,11 @@ void foo256i(__m256i) {} // We have a custom mangling for vector types not standardized by Intel. void foov8hi(__v8hi) {} -// CHECK: define void @"\01?foov8hi@@YAXT__clang_vec8_F@@@Z" +// CHECK: define void @"\01?foov8hi@@YAXT?$__vector@F$07@__clang@@@Z" + +typedef __attribute__((ext_vector_type(4))) int vi4b; +void foovi4b(vi4b) {} +// CHECK: define void @"\01?foovi4b@@YAXT?$__vector@H$03@__clang@@@Z" // Clang does not support vectors of complex types, so we can't test the // mangling of them. diff --git a/test/CodeGenCXX/mangle-ms.cpp b/test/CodeGenCXX/mangle-ms.cpp index 0da5c6f1f8df..c2a311423a9d 100644 --- a/test/CodeGenCXX/mangle-ms.cpp +++ b/test/CodeGenCXX/mangle-ms.cpp @@ -21,6 +21,10 @@ int _c(void) {return N::anonymous + c;} // CHECK-DAG: @"\01?_c@@YAHXZ" // X64-DAG: @"\01?_c@@YAHXZ" +const int &NeedsReferenceTemporary = 2; +// CHECK-DAG: @"\01?NeedsReferenceTemporary@@3ABHB" = constant i32* @"\01?$RT1@NeedsReferenceTemporary@@3ABHB" +// X64-DAG: @"\01?NeedsReferenceTemporary@@3AEBHEB" = constant i32* @"\01?$RT1@NeedsReferenceTemporary@@3AEBHEB" + class foo { static const short d; // CHECK-DAG: @"\01?d@foo@@0FB" @@ -389,3 +393,64 @@ template void fn_tmpl(); extern "C" void __attribute__((overloadable)) overloaded_fn() {} // CHECK-DAG: @"\01?overloaded_fn@@$$J0YAXXZ" + +namespace UnnamedType { +struct S { + typedef struct {} *T1[1]; + typedef struct {} T2; + typedef struct {} *T3, T4; + using T5 = struct {}; + using T6 = struct {} *; +}; +void f(S::T1) {} +void f(S::T2) {} +void f(S::T3) {} +void f(S::T4) {} +void f(S::T5) {} +void f(S::T6) {} +// CHECK-DAG: @"\01?f@UnnamedType@@YAXQAPAU@S@1@@Z" +// CHECK-DAG: @"\01?f@UnnamedType@@YAXUT2@S@1@@Z" +// CHECK-DAG: @"\01?f@UnnamedType@@YAXPAUT4@S@1@@Z" +// CHECK-DAG: @"\01?f@UnnamedType@@YAXUT4@S@1@@Z" +// CHECK-DAG: @"\01?f@UnnamedType@@YAXUT5@S@1@@Z" +// CHECK-DAG: @"\01?f@UnnamedType@@YAXPAU@S@1@@Z" + +// X64-DAG: @"\01?f@UnnamedType@@YAXQEAPEAU@S@1@@Z" +// X64-DAG: @"\01?f@UnnamedType@@YAXUT2@S@1@@Z" +// X64-DAG: @"\01?f@UnnamedType@@YAXPEAUT4@S@1@@Z"(%"struct.UnnamedType::S::T4" +// X64-DAG: @"\01?f@UnnamedType@@YAXUT4@S@1@@Z" +// X64-DAG: @"\01?f@UnnamedType@@YAXUT5@S@1@@Z" +// X64-DAG: @"\01?f@UnnamedType@@YAXPEAU@S@1@@Z" +} + +namespace PassObjectSize { +// NOTE: This mangling is subject to change. +// Reiterating from the comment in MicrosoftMangle, the scheme is pretend a +// parameter of type __clang::__pass_object_sizeN exists after each pass object +// size param P, where N is the Type of the pass_object_size attribute on P. +// +// e.g. we want to mangle: +// void foo(void *const __attribute__((pass_object_size(0)))); +// as if it were +// namespace __clang { enum __pass_object_size0 : size_t {}; } +// void foo(void *const, __clang::__pass_object_size0); +// where __clang is a top-level namespace. + +// CHECK-DAG: define i32 @"\01?foo@PassObjectSize@@YAHQAHW4__pass_object_size0@__clang@@@Z" +int foo(int *const i __attribute__((pass_object_size(0)))) { return 0; } +// CHECK-DAG: define i32 @"\01?bar@PassObjectSize@@YAHQAHW4__pass_object_size1@__clang@@@Z" +int bar(int *const i __attribute__((pass_object_size(1)))) { return 0; } +// CHECK-DAG: define i32 @"\01?qux@PassObjectSize@@YAHQAHW4__pass_object_size1@__clang@@0W4__pass_object_size0@3@@Z" +int qux(int *const i __attribute__((pass_object_size(1))), int *const j __attribute__((pass_object_size(0)))) { return 0; } +// CHECK-DAG: define i32 @"\01?zot@PassObjectSize@@YAHQAHW4__pass_object_size1@__clang@@01@Z" +int zot(int *const i __attribute__((pass_object_size(1))), int *const j __attribute__((pass_object_size(1)))) { return 0; } +} + +namespace Atomic { +// CHECK-DAG: define void @"\01?f@Atomic@@YAXU?$_Atomic@H@__clang@@@Z"( +void f(_Atomic(int)) {} +} +namespace Complex { +// CHECK-DAG: define void @"\01?f@Complex@@YAXU?$_Complex@H@__clang@@@Z"( +void f(_Complex int) {} +} diff --git a/test/CodeGenCXX/mangle-variadic-templates.cpp b/test/CodeGenCXX/mangle-variadic-templates.cpp index 264cc113cd57..d2c1b7726590 100644 --- a/test/CodeGenCXX/mangle-variadic-templates.cpp +++ b/test/CodeGenCXX/mangle-variadic-templates.cpp @@ -3,11 +3,12 @@ template struct X { }; -template struct identity { }; +template struct identity { using type = T; }; template struct add_reference; template struct tuple { }; template struct int_tuple { }; template class ...Templates> struct template_tuple { }; +template using ArrayOfN = int[sizeof...(T)]; // CHECK-LABEL: define weak_odr void @_Z2f0IJEEv1XIXsZT_EJDpRT_EE template @@ -65,3 +66,12 @@ template class ...Templates> template_tuple f7() {} // CHECK-LABEL: define weak_odr void @_Z2f7IJ8identity13add_referenceEE14template_tupleIJDpT_EEv template template_tuple f7(); + +template void f8(ArrayOfN&) {} +// CHECK-LABEL: define weak_odr void @_Z2f8IiJ8identityIiES0_IfEEEvRAsPiDpT0_T_DpNS3_4typeEE_i +template void f8, identity>(int (&)[6]); + +template void f10(ArrayOfN &) {} +// FIXME: This is wrong; should be @_Z3f10IJifEEvRAsZT__i +// CHECK-LABEL: define weak_odr void @_Z3f10IJifEEvRAsPDpT_E_i +template void f10(int (&)[2]); diff --git a/test/CodeGenCXX/member-alignment.cpp b/test/CodeGenCXX/member-alignment.cpp index 43ed5e28e884..ff6bb442b847 100644 --- a/test/CodeGenCXX/member-alignment.cpp +++ b/test/CodeGenCXX/member-alignment.cpp @@ -1,4 +1,9 @@ -// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple %s -o - | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple %s -o - | \ +// RUN: FileCheck -check-prefix CHECK-ITANIUM %s +// RUN: %clang_cc1 -emit-llvm -triple wasm32-unknown-unknown %s -o - | \ +// RUN: FileCheck -check-prefix CHECK-WEBASSEMBLY32 %s +// RUN: %clang_cc1 -emit-llvm -triple wasm64-unknown-unknown %s -o - | \ +// RUN: FileCheck -check-prefix CHECK-WEBASSEMBLY64 %s // rdar://7268289 @@ -10,10 +15,14 @@ public: void t::bar(void) { -// CHECK: _ZN1t3barEv{{.*}} align 2 +// CHECK-ITANIUM: @_ZN1t3barEv({{.*}}) #0 align 2 { +// CHECK-WEBASSEMBLY32: @_ZN1t3barEv({{.*}}) #0 { +// CHECK-WEBASSEMBLY64: @_ZN1t3barEv({{.*}}) #0 { } void t::foo(void) { -// CHECK: _ZN1t3fooEv{{.*}} align 2 +// CHECK-ITANIUM: @_ZN1t3fooEv({{.*}}) unnamed_addr #0 align 2 { +// CHECK-WEBASSEMBLY32: @_ZN1t3fooEv({{.*}}) unnamed_addr #0 { +// CHECK-WEBASSEMBLY64: @_ZN1t3fooEv({{.*}}) unnamed_addr #0 { } diff --git a/test/CodeGenCXX/member-function-pointers.cpp b/test/CodeGenCXX/member-function-pointers.cpp index 7ffe4cd9d284..faeb8550c3c4 100644 --- a/test/CodeGenCXX/member-function-pointers.cpp +++ b/test/CodeGenCXX/member-function-pointers.cpp @@ -8,6 +8,8 @@ // RUN: %clang_cc1 %s -emit-llvm -o - -triple=le32-unknown-nacl | FileCheck -check-prefix GLOBAL-ARM %s // MIPS uses the same representation of method pointers as ARM. // RUN: %clang_cc1 %s -emit-llvm -o - -triple=mips-unknown-linux-gnu | FileCheck -check-prefix GLOBAL-ARM %s +// WebAssembly uses the same representation of method pointers as ARM. +// RUN: %clang_cc1 %s -emit-llvm -o - -triple=wasm32-unknown-unknown | FileCheck -check-prefix GLOBAL-ARM %s struct A { int a; void f(); virtual void vf1(); virtual void vf2(); }; struct B { int b; virtual void g(); }; diff --git a/test/CodeGenCXX/member-initializers.cpp b/test/CodeGenCXX/member-initializers.cpp deleted file mode 100644 index c98e6bf92362..000000000000 --- a/test/CodeGenCXX/member-initializers.cpp +++ /dev/null @@ -1,35 +0,0 @@ -// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin10 -O3 | FileCheck %s - -struct A { - virtual int f() { return 1; } -}; - -struct B : A { - B() : i(f()) { } - - virtual int f() { return 2; } - - int i; -}; - -// CHECK-LABEL: define i32 @_Z1fv() #0 -int f() { - B b; - - // CHECK: ret i32 2 - return b.i; -} - -// Test that we don't try to fold the default value of j when initializing i. -// CHECK: define i32 @_Z9test_foldv() [[NUW_RN:#[0-9]+]] -int test_fold() { - struct A { - A(const int j = 1) : i(j) { } - int i; - }; - - // CHECK: ret i32 2 - return A(2).i; -} - -// CHECK: attributes [[NUW_RN]] = { nounwind readnone{{.*}} } diff --git a/test/CodeGenCXX/microsoft-abi-arg-order.cpp b/test/CodeGenCXX/microsoft-abi-arg-order.cpp index cbef1045080e..68c141f1620f 100644 --- a/test/CodeGenCXX/microsoft-abi-arg-order.cpp +++ b/test/CodeGenCXX/microsoft-abi-arg-order.cpp @@ -42,18 +42,19 @@ void call_foo() { // X86: call i8* @llvm.stacksave() // X86: %[[argmem:[^ ]*]] = alloca inalloca [[argmem_ty]] // X86: %[[arg3:[^ ]*]] = getelementptr inbounds [[argmem_ty]], [[argmem_ty]]* %[[argmem]], i32 0, i32 2 -// X86: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@H@Z"(%struct.A* %[[arg3]], i32 3) +// X86: call x86_thiscallcc %struct.A* @"\01??0A@@QAE@H@Z"(%struct.A* %[[arg3]], i32 3) // X86: %[[arg2:[^ ]*]] = getelementptr inbounds [[argmem_ty]], [[argmem_ty]]* %[[argmem]], i32 0, i32 1 // X86: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@H@Z"(%struct.A* %[[arg2]], i32 2) // X86: %[[arg1:[^ ]*]] = getelementptr inbounds [[argmem_ty]], [[argmem_ty]]* %[[argmem]], i32 0, i32 0 // X86: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@H@Z"(%struct.A* %[[arg1]], i32 1) -// X86: invoke void @"\01?foo@@YAXUA@@00@Z"([[argmem_ty]]* inalloca %[[argmem]]) +// X86: call void @"\01?foo@@YAXUA@@00@Z"([[argmem_ty]]* inalloca %[[argmem]]) // X86: call void @llvm.stackrestore // X86: ret void // // lpad2: +// X86: cleanuppad within none [] // X86: call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[arg2]]) -// X86: br label +// X86: cleanupret // // ehcleanup: // X86: call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[arg3]]) @@ -67,8 +68,9 @@ void call_foo() { // X64: ret void // // lpad2: +// X64: cleanuppad within none [] // X64: call void @"\01??1A@@QEAA@XZ"(%struct.A* %[[arg2]]) -// X64: br label +// X64: cleanupret // // ehcleanup: // X64: call void @"\01??1A@@QEAA@XZ"(%struct.A* %[[arg3]]) diff --git a/test/CodeGenCXX/microsoft-abi-array-cookies.cpp b/test/CodeGenCXX/microsoft-abi-array-cookies.cpp index 62ead4fb69d3..75c0621347a5 100644 --- a/test/CodeGenCXX/microsoft-abi-array-cookies.cpp +++ b/test/CodeGenCXX/microsoft-abi-array-cookies.cpp @@ -28,12 +28,12 @@ void check_array_cookies_simple() { // 46 = 42 + size of cookie (4) // CHECK: [[COOKIE:%.*]] = bitcast i8* [[ALLOCATED]] to i32* // CHECK: store i32 42, i32* [[COOKIE]] -// CHECK: [[ARRAY:%.*]] = getelementptr inbounds i8, i8* [[ALLOCATED]], i64 4 +// CHECK: [[ARRAY:%.*]] = getelementptr inbounds i8, i8* [[ALLOCATED]], i32 4 // CHECK: bitcast i8* [[ARRAY]] to [[CLASS:%.*]]* delete [] array; // CHECK: [[ARRAY_AS_CHAR:%.*]] = bitcast [[CLASS]]* {{%.*}} to i8* -// CHECK: getelementptr inbounds i8, i8* [[ARRAY_AS_CHAR]], i64 -4 +// CHECK: getelementptr inbounds i8, i8* [[ARRAY_AS_CHAR]], i32 -4 } struct __attribute__((aligned(8))) ClassWithAlignment { @@ -50,12 +50,12 @@ void check_array_cookies_aligned() { // 344 = 42*8 + size of cookie (8, due to alignment) // CHECK: [[COOKIE:%.*]] = bitcast i8* [[ALLOCATED]] to i32* // CHECK: store i32 42, i32* [[COOKIE]] -// CHECK: [[ARRAY:%.*]] = getelementptr inbounds i8, i8* [[ALLOCATED]], i64 8 +// CHECK: [[ARRAY:%.*]] = getelementptr inbounds i8, i8* [[ALLOCATED]], i32 8 // CHECK: bitcast i8* [[ARRAY]] to [[CLASS:%.*]]* delete [] array; // CHECK: [[ARRAY_AS_CHAR:%.*]] = bitcast [[CLASS]]* -// CHECK: getelementptr inbounds i8, i8* [[ARRAY_AS_CHAR]], i64 -8 +// CHECK: getelementptr inbounds i8, i8* [[ARRAY_AS_CHAR]], i32 -8 } namespace PR23990 { diff --git a/test/CodeGenCXX/microsoft-abi-dynamic-cast.cpp b/test/CodeGenCXX/microsoft-abi-dynamic-cast.cpp index 0fef6255ada9..e9eba6ed0b20 100644 --- a/test/CodeGenCXX/microsoft-abi-dynamic-cast.cpp +++ b/test/CodeGenCXX/microsoft-abi-dynamic-cast.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -O1 -o - -triple=i386-pc-win32 %s | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -O1 -o - -fexceptions -triple=i386-pc-win32 %s | FileCheck %s struct S { char a; }; struct V { virtual void f(); }; @@ -60,7 +60,7 @@ T* test5(A* x) { return dynamic_cast(x); } // CHECK-NEXT: [[VBOFFP:%.*]] = getelementptr inbounds i32, i32* [[VBTBL]], i32 1 // CHECK-NEXT: [[VBOFFS:%.*]] = load i32, i32* [[VBOFFP]], align 4 // CHECK-NEXT: [[ADJ:%.*]] = getelementptr inbounds i8, i8* [[VOIDP]], i32 [[VBOFFS]] -// CHECK-NEXT: [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8* [[ADJ]], i32 [[VBOFFS]], i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUA@@@8" to i8*), i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUT@@@8" to i8*), i32 0) +// CHECK-NEXT: [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8* [[ADJ]], i32 [[VBOFFS]], i8* nonnull bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUA@@@8" to i8*), i8* nonnull bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUT@@@8" to i8*), i32 0) // CHECK-NEXT: [[RES:%.*]] = bitcast i8* [[CALL]] to %struct.T* // CHECK-NEXT: br label // CHECK: [[RET:%.*]] = phi %struct.T* @@ -78,7 +78,7 @@ T* test6(B* x) { return dynamic_cast(x); } // CHECK-NEXT: [[VBOFFS:%.*]] = load i32, i32* [[VBOFFP]], align 4 // CHECK-NEXT: [[DELTA:%.*]] = add nsw i32 [[VBOFFS]], 4 // CHECK-NEXT: [[ADJ:%.*]] = getelementptr inbounds i8, i8* [[CAST]], i32 [[DELTA]] -// CHECK-NEXT: [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8* [[ADJ]], i32 [[DELTA]], i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUB@@@8" to i8*), i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUT@@@8" to i8*), i32 0) +// CHECK-NEXT: [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8* [[ADJ]], i32 [[DELTA]], i8* nonnull bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUB@@@8" to i8*), i8* nonnull bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUT@@@8" to i8*), i32 0) // CHECK-NEXT: [[RES:%.*]] = bitcast i8* [[CALL]] to %struct.T* // CHECK-NEXT: br label // CHECK: [[RET:%.*]] = phi %struct.T* @@ -122,3 +122,22 @@ void* test9(B* x) { return dynamic_cast(x); } // CHECK: [[RET:%.*]] = phi i8* // CHECK-NEXT: ret i8* [[RET]] +namespace PR25606 { +struct Cleanup { + ~Cleanup(); +}; +struct S1 { virtual ~S1(); }; +struct S2 : virtual S1 {}; +struct S3 : S2 {}; + +S3 *f(S2 &s) { + Cleanup c; + return dynamic_cast(&s); +} +// CHECK-LABEL: define %"struct.PR25606::S3"* @"\01?f@PR25606@@YAPAUS3@1@AAUS2@1@@Z"( +// CHECK: [[CALL:%.*]] = invoke i8* @__RTDynamicCast + +// CHECK: [[BC:%.*]] = bitcast i8* [[CALL]] to %"struct.PR25606::S3"* +// CHECK: call x86_thiscallcc void @"\01??_DCleanup@PR25606@@QAE@XZ"( +// CHECK: ret %"struct.PR25606::S3"* [[BC]] +} diff --git a/test/CodeGenCXX/microsoft-abi-eh-catch.cpp b/test/CodeGenCXX/microsoft-abi-eh-catch.cpp index d7268bf38529..69ec34754813 100644 --- a/test/CodeGenCXX/microsoft-abi-eh-catch.cpp +++ b/test/CodeGenCXX/microsoft-abi-eh-catch.cpp @@ -1,4 +1,7 @@ -// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple=x86_64-pc-windows-msvc -mconstructor-aliases -fexceptions -fcxx-exceptions | FileCheck -check-prefix WIN64 %s +// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple=x86_64-pc-windows-msvc \ +// RUN: -mconstructor-aliases -fexceptions -fcxx-exceptions -fnew-ms-eh \ +// RUN: -O1 -disable-llvm-optzns \ +// RUN: | FileCheck -check-prefix WIN64 %s extern "C" void might_throw(); @@ -16,21 +19,24 @@ extern "C" void catch_all() { // WIN64-LABEL: define void @catch_all() // WIN64: invoke void @might_throw() -// WIN64-NEXT: to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]] +// WIN64-NEXT: to label %[[cont:[^ ]*]] unwind label %[[catchswitch_lpad:[^ ]*]] // -// WIN64: [[cont]] -// WIN64: br label %[[ret:[^ ]*]] +// WIN64: [[catchswitch_lpad]] +// WIN64: %[[catchswitch:[^ ]*]] = catchswitch within none [label %[[catchpad_lpad:[^ ]*]]] unwind to caller // -// WIN64: [[lpad]] -// WIN64: landingpad { i8*, i32 } -// WIN64-NEXT: catch i8* null -// WIN64: call void @llvm.eh.begincatch(i8* %{{[^,]*}}, i8* null) +// WIN64: [[catchpad_lpad]] +// WIN64: catchpad within %[[catchswitch]] [i8* null, i32 64, i8* null] // WIN64: call void @recover() -// WIN64: call void @llvm.eh.endcatch() -// WIN64: br label %[[ret]] +// WIN64: catchret from %{{.*}} to label %[[catchret:[^ ]*]] +// +// WIN64: [[catchret]] +// WIN64-NEXT: br label %[[ret:[^ ]*]] // // WIN64: [[ret]] // WIN64: ret void +// +// WIN64: [[cont]] +// WIN64: br label %[[ret]] extern "C" void catch_int() { try { @@ -41,12 +47,19 @@ extern "C" void catch_int() { } // WIN64-LABEL: define void @catch_int() -// WIN64: landingpad { i8*, i32 } -// WIN64: %[[e_i8:[^ ]*]] = bitcast i32* %[[e_addr:[^ ]*]] to i8* -// WIN64: call void @llvm.eh.begincatch(i8* %{{.*}}, i8* %[[e_i8]]) +// WIN64: catchpad within %{{[^ ]*}} [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i32* %[[e_addr:[^\]]*]]] +// +// The catchpad instruction starts the lifetime of 'e'. Unfortunately, that +// leaves us with nowhere to put lifetime.start, so we don't emit lifetime +// markers for now. +// WIN64-NOT: lifetime.start +// // WIN64: %[[e_i8:[^ ]*]] = bitcast i32* %[[e_addr]] to i8* -// WIN64: call void @handle_exception(i8* %[[e_i8]]) -// WIN64: call void @llvm.eh.endcatch() +// WIN64-NOT: lifetime.start +// WIN64: call void @handle_exception +// WIN64-SAME: (i8* %[[e_i8]]) +// WIN64-NOT: lifetime.end +// WIN64: catchret extern "C" void catch_int_unnamed() { try { @@ -56,9 +69,8 @@ extern "C" void catch_int_unnamed() { } // WIN64-LABEL: define void @catch_int_unnamed() -// WIN64: landingpad { i8*, i32 } -// WIN64: call void @llvm.eh.begincatch(i8* %{{.*}}, i8* null) -// WIN64: call void @llvm.eh.endcatch() +// WIN64: catchpad within %{{.*}} [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null] +// WIN64: catchret struct A { A(); @@ -84,12 +96,10 @@ extern "C" void catch_a_byval() { // WIN64-LABEL: define void @catch_a_byval() // WIN64: %[[e_addr:[^ ]*]] = alloca %struct.A -// WIN64: landingpad { i8*, i32 } -// WIN64: %[[e_i8:[^ ]*]] = bitcast %struct.A* %[[e_addr]] to i8* -// WIN64: call void @llvm.eh.begincatch(i8* %{{.*}}, i8* %[[e_i8]]) +// WIN64: catchpad within %{{[^ ]*}} [%rtti.TypeDescriptor7* @"\01??_R0?AUA@@@8", i32 0, %struct.A* %[[e_addr]]] // WIN64: %[[e_i8:[^ ]*]] = bitcast %struct.A* %[[e_addr]] to i8* // WIN64: call void @handle_exception(i8* %[[e_i8]]) -// WIN64: call void @llvm.eh.endcatch() +// WIN64: catchret extern "C" void catch_a_ref() { try { @@ -101,13 +111,11 @@ extern "C" void catch_a_ref() { // WIN64-LABEL: define void @catch_a_ref() // WIN64: %[[e_addr:[^ ]*]] = alloca %struct.A* -// WIN64: landingpad { i8*, i32 } -// WIN64: %[[e_i8:[^ ]*]] = bitcast %struct.A** %[[e_addr]] to i8* -// WIN64: call void @llvm.eh.begincatch(i8* %{{.*}}, i8* %[[e_i8]]) +// WIN64: catchpad within %{{[^ ]*}} [%rtti.TypeDescriptor7* @"\01??_R0?AUA@@@8", i32 8, %struct.A** %[[e_addr]]] // WIN64: %[[eptr:[^ ]*]] = load %struct.A*, %struct.A** %[[e_addr]] // WIN64: %[[eptr_i8:[^ ]*]] = bitcast %struct.A* %[[eptr]] to i8* // WIN64: call void @handle_exception(i8* %[[eptr_i8]]) -// WIN64: call void @llvm.eh.endcatch() +// WIN64: catchret extern "C" void fn_with_exc_spec() throw(int) { might_throw(); @@ -131,24 +139,26 @@ extern "C" void catch_nested() { // WIN64-LABEL: define void @catch_nested() // WIN64: invoke void @might_throw() -// WIN64-NEXT: to label %[[cont1:[^ ]*]] unwind label %[[lp1:[^ ]*]] -// WIN64: [[cont1]] +// WIN64-NEXT: to label %{{.*}} unwind label %[[catchswitch_outer:[^ ]*]] // -// WIN64: [[lp1]] -// WIN64: landingpad { i8*, i32 } -// WIN64: call void @llvm.eh.begincatch(i8* %{{.*}}, i8* null) +// WIN64: [[catchswitch_outer]] +// WIN64: %[[catchswitch_outer_scope:[^ ]*]] = catchswitch within none [label %[[catch_int_outer:[^ ]*]]] unwind to caller +// +// WIN64: [[catch_int_outer]] +// WIN64: %[[catchpad:[^ ]*]] = catchpad within %[[catchswitch_outer_scope]] [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null] // WIN64: invoke void @might_throw() -// WIN64-NEXT: to label %[[cont2:[^ ]*]] unwind label %[[lp2:[^ ]*]] +// WIN64-NEXT: to label %[[cont2:[^ ]*]] unwind label %[[catchswitch_inner:[^ ]*]] // -// WIN64: [[cont2]] -// WIN64-NEXT: br label %[[trycont:[^ ]*]] +// WIN64: [[catchswitch_inner]] +// WIN64: %[[catchswitch_inner_scope:[^ ]*]] = catchswitch within %[[catchpad]] [label %[[catch_int_inner:[^ ]*]]] unwind to caller // -// WIN64: [[lp2]] -// WIN64: landingpad { i8*, i32 } -// WIN64: call void @llvm.eh.begincatch(i8* %{{.*}}, i8* null) +// WIN64: [[catch_int_inner]] +// WIN64: catchpad within %[[catchswitch_inner_scope]] [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null] // WIN64-NEXT: call void @might_throw() -// WIN64-NEXT: call void @llvm.eh.endcatch() -// WIN64-NEXT: br label %[[trycont]] +// WIN64: catchret {{.*}} to label %[[catchret2:[^ ]*]] +// +// WIN64: [[catchret2]] +// WIN64: catchret {{.*}} to label %[[mainret:[^ ]*]] // -// WIN64: [[trycont]] -// WIN64: call void @llvm.eh.endcatch() +// WIN64: [[mainret]] +// WIN64: ret void diff --git a/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp b/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp index 68f1430ace57..bf05c693ec0d 100644 --- a/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp +++ b/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fexceptions -fcxx-exceptions -fno-rtti | FileCheck -check-prefix WIN32 %s +// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fexceptions -fcxx-exceptions -fno-rtti | FileCheck -check-prefix WIN32 %s struct A { A(); @@ -17,18 +17,18 @@ void HasEHCleanup() { // WIN32-LABEL: define void @"\01?HasEHCleanup@@YAXXZ"() {{.*}} { // WIN32: %[[base:.*]] = call i8* @llvm.stacksave() // If this call throws, we have to restore the stack. -// WIN32: invoke void @"\01?getA@@YA?AUA@@XZ"(%struct.A* sret %{{.*}}) +// WIN32: call void @"\01?getA@@YA?AUA@@XZ"(%struct.A* sret %{{.*}}) // If this call throws, we have to cleanup the first temporary. // WIN32: invoke void @"\01?getA@@YA?AUA@@XZ"(%struct.A* sret %{{.*}}) // If this call throws, we have to cleanup the stacksave. -// WIN32: invoke i32 @"\01?TakesTwo@@YAHUA@@0@Z" -// WIN32: call void @llvm.stackrestore(i8* %[[base]]) +// WIN32: call i32 @"\01?TakesTwo@@YAHUA@@0@Z" +// WIN32: call void @llvm.stackrestore // WIN32: ret void // // There should be one dtor call for unwinding from the second getA. -// WIN32: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ" +// WIN32: cleanuppad +// WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}}) // WIN32-NOT: @"\01??1A@@QAE@XZ" -// WIN32: call void @llvm.stackrestore // WIN32: } void TakeRef(const A &a); @@ -41,7 +41,7 @@ int HasDeactivatedCleanups() { // WIN32: call i8* @llvm.stacksave() // WIN32: %[[argmem:.*]] = alloca inalloca [[argmem_ty:<{ %struct.A, %struct.A }>]] // WIN32: %[[arg1:.*]] = getelementptr inbounds [[argmem_ty]], [[argmem_ty]]* %[[argmem]], i32 0, i32 1 -// WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" +// WIN32: call x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" // WIN32: invoke void @"\01?TakeRef@@YAXABUA@@@Z" // // WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %[[arg1]]) @@ -54,16 +54,15 @@ int HasDeactivatedCleanups() { // WIN32: store i1 false, i1* %[[isactive]] // // WIN32: invoke i32 @"\01?TakesTwo@@YAHUA@@0@Z"([[argmem_ty]]* inalloca %[[argmem]]) -// WIN32: call void @llvm.stackrestore // Destroy the two const ref temporaries. -// WIN32: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ" -// WIN32: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ" +// WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}}) +// WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}}) // WIN32: ret i32 // // Conditionally destroy arg1. // WIN32: %[[cond:.*]] = load i1, i1* %[[isactive]] // WIN32: br i1 %[[cond]] -// WIN32: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[arg1]]) +// WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[arg1]]) // WIN32: } // Test putting the cleanups inside a conditional. @@ -76,18 +75,18 @@ int HasConditionalCleanup(bool cond) { // WIN32: store i1 false // WIN32: br i1 // WIN32: call i8* @llvm.stacksave() -// WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %{{.*}}) +// WIN32: call x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %{{.*}}) // WIN32: store i1 true // WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %{{.*}}) -// WIN32: invoke i32 @"\01?TakesTwo@@YAHUA@@0@Z" +// WIN32: call i32 @"\01?TakesTwo@@YAHUA@@0@Z" +// // WIN32: call void @llvm.stackrestore // // WIN32: call i32 @"\01?CouldThrow@@YAHXZ"() // // Only one dtor in the invoke for arg1 -// WIN32: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}}) +// WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}}) // WIN32-NOT: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ" -// WIN32: call void @llvm.stackrestore // WIN32: } // Now test both. @@ -105,7 +104,7 @@ int HasConditionalDeactivatedCleanups(bool cond) { // WIN32: store i1 false // WIN32: br i1 // True condition. -// WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" +// WIN32: call x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" // WIN32: store i1 true // WIN32: invoke void @"\01?TakeRef@@YAXABUA@@@Z" // WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" @@ -120,14 +119,14 @@ int HasConditionalDeactivatedCleanups(bool cond) { // False condition. // WIN32: invoke i32 @"\01?CouldThrow@@YAHXZ"() // Two normal cleanups for TakeRef args. -// WIN32: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ" -// WIN32: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ" +// WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}}) +// WIN32-NOT: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ" // WIN32: ret i32 // // Somewhere in the landing pad soup, we conditionally destroy arg1. // WIN32: %[[isactive:.*]] = load i1, i1* %[[arg1_cond]] // WIN32: br i1 %[[isactive]] -// WIN32: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ" +// WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}}) // WIN32: } namespace crash_on_partial_destroy { @@ -150,22 +149,22 @@ C::C() { foo(); } // Verify that we don't bother with a vbtable lookup when adjusting the this // pointer to call a base destructor from a constructor while unwinding. // WIN32-LABEL: define {{.*}} @"\01??0C@crash_on_partial_destroy@@QAE@XZ"{{.*}} { -// WIN32: landingpad +// WIN32: cleanuppad // // We shouldn't do any vbptr loads, just constant GEPs. // WIN32-NOT: load // WIN32: getelementptr i8, i8* %{{.*}}, i32 4 // WIN32-NOT: load // WIN32: bitcast i8* %{{.*}} to %"struct.crash_on_partial_destroy::B"* -// WIN32: invoke x86_thiscallcc void @"\01??1B@crash_on_partial_destroy@@UAE@XZ" +// WIN32: call x86_thiscallcc void @"\01??1B@crash_on_partial_destroy@@UAE@XZ" // // WIN32-NOT: load // WIN32: bitcast %"struct.crash_on_partial_destroy::C"* %{{.*}} to i8* // WIN32-NOT: load -// WIN32: getelementptr inbounds i8, i8* %{{.*}}, i64 4 +// WIN32: getelementptr inbounds i8, i8* %{{.*}}, i32 4 // WIN32-NOT: load // WIN32: bitcast i8* %{{.*}} to %"struct.crash_on_partial_destroy::A"* -// WIN32: call x86_thiscallcc void @"\01??1A@crash_on_partial_destroy@@UAE@XZ" +// WIN32: call x86_thiscallcc void @"\01??1A@crash_on_partial_destroy@@UAE@XZ"({{.*}}) // WIN32: } } @@ -187,7 +186,23 @@ void f() { // WIN32: call x86_thiscallcc void @"\01??1C@dont_call_terminate@@QAE@XZ"({{.*}}) // // WIN32: [[lpad]] -// WIN32-NEXT: landingpad -// WIN32-NEXT: cleanup +// WIN32-NEXT: cleanuppad // WIN32: call x86_thiscallcc void @"\01??1C@dont_call_terminate@@QAE@XZ"({{.*}}) } + +namespace noexcept_false_dtor { +struct D { + ~D() noexcept(false); +}; +void f() { + D d; + CouldThrow(); +} +} + +// WIN32-LABEL: define void @"\01?f@noexcept_false_dtor@@YAXXZ"() +// WIN32: invoke i32 @"\01?CouldThrow@@YAHXZ"() +// WIN32: call x86_thiscallcc void @"\01??1D@noexcept_false_dtor@@QAE@XZ"(%"struct.noexcept_false_dtor::D"* %{{.*}}) +// WIN32: cleanuppad +// WIN32: call x86_thiscallcc void @"\01??1D@noexcept_false_dtor@@QAE@XZ"(%"struct.noexcept_false_dtor::D"* %{{.*}}) +// WIN32: cleanupret diff --git a/test/CodeGenCXX/microsoft-abi-eh-terminate.cpp b/test/CodeGenCXX/microsoft-abi-eh-terminate.cpp index cbc1686893d7..0b8d270e1379 100644 --- a/test/CodeGenCXX/microsoft-abi-eh-terminate.cpp +++ b/test/CodeGenCXX/microsoft-abi-eh-terminate.cpp @@ -6,10 +6,10 @@ void never_throws() noexcept(true) { may_throw(); } -// CHECK-LABEL: define void @"\01?never_throws@@YAXXZ" +// CHECK-LABEL: define void @"\01?never_throws@@YAXXZ"() +// CHECK-SAME: personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) // CHECK: invoke void @"\01?may_throw@@YAXXZ"() - -// CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) -// MSVC2013: call void @"\01?terminate@@YAXXZ"() -// MSVC2015: call void @__std_terminate() +// CHECK: cleanuppad within none [] +// MSVC2013: call void @"\01?terminate@@YAXXZ"() +// MSVC2015: call void @__std_terminate() // CHECK-NEXT: unreachable diff --git a/test/CodeGenCXX/microsoft-abi-member-pointers.cpp b/test/CodeGenCXX/microsoft-abi-member-pointers.cpp index a509d57194f2..fd22c0034203 100755 --- a/test/CodeGenCXX/microsoft-abi-member-pointers.cpp +++ b/test/CodeGenCXX/microsoft-abi-member-pointers.cpp @@ -729,3 +729,53 @@ typedef void (D::*DMemPtrTy)(); // CHECK: @"\01??_9C@pr23878@@$BA@AE" to i8*), i32 0, i32 4 DMemPtrTy get_memptr() { return &D::f; } } + +class C {}; + +typedef void (C::*f)(); + +class CA : public C { +public: + void OnHelp(void); + int OnHelp(int); +}; + +// CHECK-LABEL: foo_fun +void foo_fun() { + // CHECK: store i8* bitcast (void (%class.CA*)* @"\01?OnHelp@CA@@QAEXXZ" to i8*), i8** + f func = (f)&CA::OnHelp; +} +namespace PR24703 { +struct S; + +void f(int S::*&p) {} +// CHECK-LABEL: define void @"\01?f@PR24703@@YAXAAPQS@1@H@Z"( +} + +namespace ReferenceToMPTWithIncompleteClass { +struct S; +struct J; +struct K; +extern K *k; + +// CHECK-LABEL: @"\01?f@ReferenceToMPTWithIncompleteClass@@YAIAAPQS@1@H@Z"( +// CHECK: ret i32 12 +unsigned f(int S::*&p) { return sizeof p; } + +// CHECK-LABEL: @"\01?g@ReferenceToMPTWithIncompleteClass@@YA_NAAPQJ@1@H0@Z"( +bool g(int J::*&p, int J::*&q) { return p == q; } + +// CHECK-LABEL: @"\01?h@ReferenceToMPTWithIncompleteClass@@YAHAAPQK@1@H@Z"( +int h(int K::*&p) { return k->*p; } +} + +namespace PMFInTemplateArgument { +template +void JSMethod(); +class A { + int printd(int); + void printd(); +}; +void A::printd() { JSMethod(); } +// CHECK-LABEL: @"\01??$JSMethod@VA@PMFInTemplateArgument@@$1?printd@12@AAEHH@Z@PMFInTemplateArgument@@YAXXZ"( +} diff --git a/test/CodeGenCXX/microsoft-abi-structors-alias.cpp b/test/CodeGenCXX/microsoft-abi-structors-alias.cpp index f977556aa565..08df374f2fc9 100644 --- a/test/CodeGenCXX/microsoft-abi-structors-alias.cpp +++ b/test/CodeGenCXX/microsoft-abi-structors-alias.cpp @@ -22,5 +22,21 @@ B::~B() {} void foo() { B b; } -// CHECK-DAG: @"\01??1B@test2@@UAE@XZ" = alias bitcast (void (%"struct.test2::A"*)* @"\01??1A@test2@@UAE@XZ" to void (%"struct.test2::B"*)*) +// CHECK-DAG: @"\01??1B@test2@@UAE@XZ" = alias void (%"struct.test2::B"*), bitcast (void (%"struct.test2::A"*)* @"\01??1A@test2@@UAE@XZ" to void (%"struct.test2::B"*)*) } + +namespace test3 { +struct A { virtual ~A(); }; +A::~A() {} +} +// CHECK-DAG: define x86_thiscallcc void @"\01??1A@test3@@UAE@XZ"( +namespace test3 { +template +struct B : A { + virtual ~B() { } +}; +template struct B; +} +// This has to be weak, and emitting weak aliases is fragile, so we don't do the +// aliasing. +// CHECK-DAG: define weak_odr x86_thiscallcc void @"\01??1?$B@H@test3@@UAE@XZ"( diff --git a/test/CodeGenCXX/microsoft-abi-structors.cpp b/test/CodeGenCXX/microsoft-abi-structors.cpp index 594dea473ef1..3fb97b9a3632 100644 --- a/test/CodeGenCXX/microsoft-abi-structors.cpp +++ b/test/CodeGenCXX/microsoft-abi-structors.cpp @@ -5,6 +5,7 @@ // RUN: FileCheck --check-prefix DTORS %s < %t // RUN: FileCheck --check-prefix DTORS2 %s < %t // RUN: FileCheck --check-prefix DTORS3 %s < %t +// RUN: FileCheck --check-prefix DTORS4 %s < %t // // RUN: %clang_cc1 -emit-llvm %s -o - -mconstructor-aliases -triple=x86_64-pc-win32 -fno-rtti | FileCheck --check-prefix DTORS-X64 %s @@ -161,7 +162,7 @@ C::~C() { // CHECK: load %"struct.dtor_in_second_nvbase::C"*, %"struct.dtor_in_second_nvbase::C"** %{{.*}} // Now we this-adjust before calling ~B. // CHECK: bitcast %"struct.dtor_in_second_nvbase::C"* %{{.*}} to i8* -// CHECK: getelementptr inbounds i8, i8* %{{.*}}, i64 4 +// CHECK: getelementptr inbounds i8, i8* %{{.*}}, i32 4 // CHECK: bitcast i8* %{{.*}} to %"struct.dtor_in_second_nvbase::B"* // CHECK: call x86_thiscallcc void @"\01??1B@dtor_in_second_nvbase@@UAE@XZ" // CHECK: (%"struct.dtor_in_second_nvbase::B"* %{{.*}}) @@ -176,7 +177,7 @@ void foo() { // Do an adjustment from B* to C*. // DTORS2: getelementptr i8, i8* %{{.*}}, i32 -4 // DTORS2: bitcast i8* %{{.*}} to %"struct.dtor_in_second_nvbase::C"* -// DTORS2: %[[CALL:.*]] = call x86_thiscallcc i8* @"\01??_GC@dtor_in_second_nvbase@@UAEPAXI@Z" +// DTORS2: %[[CALL:.*]] = tail call x86_thiscallcc i8* @"\01??_GC@dtor_in_second_nvbase@@UAEPAXI@Z" // DTORS2: ret i8* %[[CALL]] } @@ -246,11 +247,11 @@ C::C() { // // CHECK: [[INIT_VBASES]] // CHECK-NEXT: %[[this_i8:.*]] = bitcast %"struct.constructors::C"* %{{.*}} to i8* - // CHECK-NEXT: %[[vbptr_off:.*]] = getelementptr inbounds i8, i8* %[[this_i8]], i64 0 + // CHECK-NEXT: %[[vbptr_off:.*]] = getelementptr inbounds i8, i8* %[[this_i8]], i32 0 // CHECK-NEXT: %[[vbptr:.*]] = bitcast i8* %[[vbptr_off]] to i32** // CHECK-NEXT: store i32* getelementptr inbounds ([2 x i32], [2 x i32]* @"\01??_8C@constructors@@7B@", i32 0, i32 0), i32** %[[vbptr]] // CHECK-NEXT: bitcast %"struct.constructors::C"* %{{.*}} to i8* - // CHECK-NEXT: getelementptr inbounds i8, i8* %{{.*}}, i64 4 + // CHECK-NEXT: getelementptr inbounds i8, i8* %{{.*}}, i32 4 // CHECK-NEXT: bitcast i8* %{{.*}} to %"struct.constructors::A"* // CHECK-NEXT: call x86_thiscallcc %"struct.constructors::A"* @"\01??0A@constructors@@QAE@XZ"(%"struct.constructors::A"* %{{.*}}) // CHECK-NEXT: br label %[[SKIP_VBASES]] @@ -281,11 +282,11 @@ D::D() { // // CHECK: [[INIT_VBASES]] // CHECK-NEXT: %[[this_i8:.*]] = bitcast %"struct.constructors::D"* %{{.*}} to i8* - // CHECK-NEXT: %[[vbptr_off:.*]] = getelementptr inbounds i8, i8* %[[this_i8]], i64 0 + // CHECK-NEXT: %[[vbptr_off:.*]] = getelementptr inbounds i8, i8* %[[this_i8]], i32 0 // CHECK-NEXT: %[[vbptr:.*]] = bitcast i8* %[[vbptr_off]] to i32** // CHECK-NEXT: store i32* getelementptr inbounds ([2 x i32], [2 x i32]* @"\01??_8D@constructors@@7B@", i32 0, i32 0), i32** %[[vbptr]] // CHECK-NEXT: bitcast %"struct.constructors::D"* %{{.*}} to i8* - // CHECK-NEXT: getelementptr inbounds i8, i8* %{{.*}}, i64 4 + // CHECK-NEXT: getelementptr inbounds i8, i8* %{{.*}}, i32 4 // CHECK-NEXT: bitcast i8* %{{.*}} to %"struct.constructors::A"* // CHECK-NEXT: call x86_thiscallcc %"struct.constructors::A"* @"\01??0A@constructors@@QAE@XZ"(%"struct.constructors::A"* %{{.*}}) // CHECK-NEXT: br label %[[SKIP_VBASES]] @@ -308,14 +309,14 @@ E::E() { // // CHECK: [[INIT_VBASES]] // CHECK-NEXT: %[[this_i8:.*]] = bitcast %"struct.constructors::E"* %{{.*}} to i8* - // CHECK-NEXT: %[[offs:.*]] = getelementptr inbounds i8, i8* %[[this_i8]], i64 0 + // CHECK-NEXT: %[[offs:.*]] = getelementptr inbounds i8, i8* %[[this_i8]], i32 0 // CHECK-NEXT: %[[vbptr_E:.*]] = bitcast i8* %[[offs]] to i32** // CHECK-NEXT: store i32* getelementptr inbounds ([3 x i32], [3 x i32]* @"\01??_8E@constructors@@7B01@@", i32 0, i32 0), i32** %[[vbptr_E]] - // CHECK-NEXT: %[[offs:.*]] = getelementptr inbounds i8, i8* %[[this_i8]], i64 4 + // CHECK-NEXT: %[[offs:.*]] = getelementptr inbounds i8, i8* %[[this_i8]], i32 4 // CHECK-NEXT: %[[vbptr_C:.*]] = bitcast i8* %[[offs]] to i32** // CHECK-NEXT: store i32* getelementptr inbounds ([2 x i32], [2 x i32]* @"\01??_8E@constructors@@7BC@1@@", i32 0, i32 0), i32** %[[vbptr_C]] // CHECK-NEXT: bitcast %"struct.constructors::E"* %{{.*}} to i8* - // CHECK-NEXT: getelementptr inbounds i8, i8* %{{.*}}, i64 4 + // CHECK-NEXT: getelementptr inbounds i8, i8* %{{.*}}, i32 4 // CHECK-NEXT: bitcast i8* %{{.*}} to %"struct.constructors::A"* // CHECK-NEXT: call x86_thiscallcc %"struct.constructors::A"* @"\01??0A@constructors@@QAE@XZ"(%"struct.constructors::A"* %{{.*}}) // CHECK: call x86_thiscallcc %"struct.constructors::C"* @"\01??0C@constructors@@QAE@XZ"(%"struct.constructors::C"* %{{.*}}, i32 0) @@ -407,9 +408,7 @@ B::B(short *a) {} // CHECK: (%"struct.test1::B"* returned %this, i32* %a, i32 %is_most_derived) // CHECK: define %"struct.test1::B"* @"\01??0B@test1@@QAA@PBDZZ" // CHECK: (%"struct.test1::B"* returned %this, i32 %is_most_derived, i8* %a, ...) - -// FIXME: This should be x86_thiscallcc. MSVC ignores explicit CCs on structors. -// CHECK: define %"struct.test1::B"* @"\01??0B@test1@@QAA@PAF@Z" +// CHECK: define x86_thiscallcc %"struct.test1::B"* @"\01??0B@test1@@QAE@PAF@Z" // CHECK: (%"struct.test1::B"* returned %this, i16* %a, i32 %is_most_derived) void construct_b() { @@ -458,3 +457,18 @@ void *getA() { // CHECK: (%"struct.(anonymous namespace)::A"* %this, i32 %should_call_delete) // CHECK: define internal x86_thiscallcc void @"\01??1A@?A@@UAE@XZ" // CHECK: (%"struct.(anonymous namespace)::A"* %this) + +// Check that we correctly transform __stdcall to __thiscall for ctors and +// dtors. +class G { + public: + __stdcall G() {}; +// DTORS4: define linkonce_odr x86_thiscallcc %class.G* @"\01??0G@@QAE@XZ" + __stdcall ~G() {}; +// DTORS4: define linkonce_odr x86_thiscallcc void @"\01??1G@@QAE@XZ" +}; + +extern void testG() { + G g; +} + diff --git a/test/CodeGenCXX/microsoft-abi-thread-safe-statics.cpp b/test/CodeGenCXX/microsoft-abi-thread-safe-statics.cpp index 89a62c2cb390..29b434eaf2c5 100644 --- a/test/CodeGenCXX/microsoft-abi-thread-safe-statics.cpp +++ b/test/CodeGenCXX/microsoft-abi-thread-safe-statics.cpp @@ -39,15 +39,11 @@ extern inline S &f() { // CHECK-NEXT: ret %struct.S* @"\01?s@?1??f@@YAAAUS@@XZ@4U2@A" // CHECK: [[lpad:.*]]: -// CHECK-NEXT: landingpad { i8*, i32 } -// CHECK-NEXT: cleanup +// CHECK-NEXT: cleanuppad within none [] // CHECK: %[[guard:.*]] = load i32, i32* @"\01??__J?1??f@@YAAAUS@@XZ@51" // CHECK-NEXT: %[[mask:.*]] = and i32 %[[guard]], -2 // CHECK-NEXT: store i32 %[[mask]], i32* @"\01??__J?1??f@@YAAAUS@@XZ@51" -// CHECK-NEXT: br label %[[eh_resume:.*]] -// -// CHECK: [[eh_resume]]: -// CHECK: resume { i8*, i32 } +// CHECK-NEXT: cleanupret {{.*}} unwind to caller return s; } @@ -79,11 +75,9 @@ extern inline S &g() { // CHECK-NEXT: ret %struct.S* @"\01?s@?1??g@@YAAAUS@@XZ@4U2@A" // // CHECK: [[lpad]]: +// CHECK-NEXT: cleanuppad within none [] // CHECK: call void @_Init_thread_abort(i32* @"\01?$TSS0@?1??g@@YAAAUS@@XZ") -// CHECK-NEXT: br label %[[eh_resume:.*]] -// -// CHECK: [[eh_resume]]: -// CHECK: resume { i8*, i32 } +// CHECK-NEXT: cleanupret {{.*}} unwind to caller return s; } diff --git a/test/CodeGenCXX/microsoft-abi-try-throw.cpp b/test/CodeGenCXX/microsoft-abi-try-throw.cpp index fed39761714e..6b1d2bf2a513 100644 --- a/test/CodeGenCXX/microsoft-abi-try-throw.cpp +++ b/test/CodeGenCXX/microsoft-abi-try-throw.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fcxx-exceptions -fexceptions -fno-rtti -DTRY | FileCheck %s -check-prefix=TRY +// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fcxx-exceptions -fexceptions -fno-rtti -DTRY -fnew-ms-eh | FileCheck %s -check-prefix=TRY // RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fcxx-exceptions -fexceptions -fno-rtti -DTHROW | FileCheck %s -check-prefix=THROW // THROW-DAG: @"\01??_R0H@8" = linkonce_odr global %rtti.TypeDescriptor2 { i8** @"\01??_7type_info@@6B@", i8* null, [3 x i8] c".H\00" }, comdat @@ -6,8 +6,6 @@ // THROW-DAG: @_CTA1H = linkonce_odr unnamed_addr constant %eh.CatchableTypeArray.1 { i32 1, [1 x %eh.CatchableType*] [%eh.CatchableType* @"_CT??_R0H@84"] }, section ".xdata", comdat // THROW-DAG: @_TI1H = linkonce_odr unnamed_addr constant %eh.ThrowInfo { i32 0, i8* null, i8* null, i8* bitcast (%eh.CatchableTypeArray.1* @_CTA1H to i8*) }, section ".xdata", comdat -// TRY-DAG: @llvm.eh.handlertype.PAH.1 = private unnamed_addr constant %eh.CatchHandlerType { i32 1, i8* bitcast (%rtti.TypeDescriptor4* @"\01??_R0PAH@8" to i8*) }, section "llvm.metadata" - void external(); inline void not_emitted() { @@ -21,12 +19,12 @@ int main() { external(); // TRY: invoke void @"\01?external@@YAXXZ" } catch (int) { rv = 1; - // TRY: call void @llvm.eh.begincatch(i8* %{{.*}}, i8* null) - // TRY: call void @llvm.eh.endcatch() + // TRY: catchpad within {{.*}} [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null] + // TRY: catchret } #endif #ifdef THROW - // THROW: store i32 42, i32* %[[mem_for_throw:.*]] + // THROW: store i32 42, i32* %[[mem_for_throw:.*]], align 4 // THROW: %[[cast:.*]] = bitcast i32* %[[mem_for_throw]] to i8* // THROW: call void @_CxxThrowException(i8* %[[cast]], %eh.ThrowInfo* @_TI1H) throw int(42); @@ -41,7 +39,7 @@ void qual_catch() { external(); } catch (const int *) { } - // TRY: catch %eh.CatchHandlerType* @llvm.eh.handlertype.PAH.1 - // TRY: call i32 @llvm.eh.typeid.for(i8* bitcast (%eh.CatchHandlerType* @llvm.eh.handlertype.PAH.1 to i8*)) + // TRY: catchpad within {{.*}} [%rtti.TypeDescriptor4* @"\01??_R0PAH@8", i32 1, i8* null] + // TRY: catchret } #endif diff --git a/test/CodeGenCXX/microsoft-abi-vftables.cpp b/test/CodeGenCXX/microsoft-abi-vftables.cpp index 1a48411f5aff..340675b188d5 100644 --- a/test/CodeGenCXX/microsoft-abi-vftables.cpp +++ b/test/CodeGenCXX/microsoft-abi-vftables.cpp @@ -9,7 +9,7 @@ struct S { } s; // RTTI-DAG: [[VTABLE_S:@.*]] = private unnamed_addr constant [2 x i8*] [i8* bitcast ({{.*}} @"\01??_R4S@@6B@" to i8*), i8* bitcast ({{.*}} @"\01??_GS@@UAEPAXI@Z" to i8*)], comdat($"\01??_7S@@6B@") -// RTTI-DAG: @"\01??_7S@@6B@" = unnamed_addr alias getelementptr inbounds ([2 x i8*], [2 x i8*]* [[VTABLE_S]], i32 0, i32 1) +// RTTI-DAG: @"\01??_7S@@6B@" = unnamed_addr alias i8*, getelementptr inbounds ([2 x i8*], [2 x i8*]* [[VTABLE_S]], i32 0, i32 1) // NO-RTTI-DAG: @"\01??_7S@@6B@" = linkonce_odr unnamed_addr constant [1 x i8*] [i8* bitcast ({{.*}} @"\01??_GS@@UAEPAXI@Z" to i8*)] @@ -26,7 +26,7 @@ struct __declspec(dllexport) V { } v; // RTTI-DAG: [[VTABLE_V:@.*]] = private unnamed_addr constant [2 x i8*] [i8* bitcast ({{.*}} @"\01??_R4V@@6B@" to i8*), i8* bitcast ({{.*}} @"\01??_GV@@UAEPAXI@Z" to i8*)], comdat($"\01??_7V@@6B@") -// RTTI-DAG: @"\01??_7V@@6B@" = dllexport unnamed_addr alias getelementptr inbounds ([2 x i8*], [2 x i8*]* [[VTABLE_V]], i32 0, i32 1) +// RTTI-DAG: @"\01??_7V@@6B@" = dllexport unnamed_addr alias i8*, getelementptr inbounds ([2 x i8*], [2 x i8*]* [[VTABLE_V]], i32 0, i32 1) // NO-RTTI-DAG: @"\01??_7V@@6B@" = weak_odr dllexport unnamed_addr constant [1 x i8*] [i8* bitcast ({{.*}} @"\01??_GV@@UAEPAXI@Z" to i8*)] @@ -36,7 +36,7 @@ struct W { } w; } // RTTI-DAG: [[VTABLE_W:@.*]] = private unnamed_addr constant [2 x i8*] [i8* bitcast ({{.*}} @"\01??_R4W@?A@@6B@" to i8*), i8* bitcast ({{.*}} @"\01??_GW@?A@@UAEPAXI@Z" to i8*)] -// RTTI-DAG: @"\01??_7W@?A@@6B@" = internal unnamed_addr alias getelementptr inbounds ([2 x i8*], [2 x i8*]* [[VTABLE_W]], i32 0, i32 1) +// RTTI-DAG: @"\01??_7W@?A@@6B@" = internal unnamed_addr alias i8*, getelementptr inbounds ([2 x i8*], [2 x i8*]* [[VTABLE_W]], i32 0, i32 1) // NO-RTTI-DAG: @"\01??_7W@?A@@6B@" = internal unnamed_addr constant [1 x i8*] [i8* bitcast ({{.*}} @"\01??_GW@?A@@UAEPAXI@Z" to i8*)] diff --git a/test/CodeGenCXX/microsoft-abi-virtual-inheritance-vtordisps.cpp b/test/CodeGenCXX/microsoft-abi-virtual-inheritance-vtordisps.cpp index 204da8db1536..bb73f8773ccb 100644 --- a/test/CodeGenCXX/microsoft-abi-virtual-inheritance-vtordisps.cpp +++ b/test/CodeGenCXX/microsoft-abi-virtual-inheritance-vtordisps.cpp @@ -26,7 +26,7 @@ D::D() {} // Forces vftable emission. // CHECK-LABEL: define linkonce_odr x86_thiscallcc void @"\01?f@D@@$4PPPPPPPM@A@AEXXZ" // CHECK: %[[ECX:.*]] = load %struct.D*, %struct.D** %{{.*}} // CHECK: %[[ECX_i8:.*]] = bitcast %struct.D* %[[ECX]] to i8* -// CHECK: %[[VTORDISP_PTR_i8:.*]] = getelementptr i8, i8* %[[ECX_i8]], i32 -4 +// CHECK: %[[VTORDISP_PTR_i8:.*]] = getelementptr inbounds i8, i8* %[[ECX_i8]], i32 -4 // CHECK: %[[VTORDISP_PTR:.*]] = bitcast i8* %[[VTORDISP_PTR_i8]] to i32* // CHECK: %[[VTORDISP:.*]] = load i32, i32* %[[VTORDISP_PTR]] // CHECK: %[[VTORDISP_NEG:.*]] = sub i32 0, %[[VTORDISP]] @@ -37,7 +37,7 @@ D::D() {} // Forces vftable emission. // CHECK-LABEL: define linkonce_odr x86_thiscallcc void @"\01?f@D@@$4PPPPPPPI@3AEXXZ" // CHECK: %[[ECX:.*]] = load %struct.D*, %struct.D** %{{.*}} // CHECK: %[[ECX_i8:.*]] = bitcast %struct.D* %[[ECX]] to i8* -// CHECK: %[[VTORDISP_PTR_i8:.*]] = getelementptr i8, i8* %[[ECX_i8]], i32 -8 +// CHECK: %[[VTORDISP_PTR_i8:.*]] = getelementptr inbounds i8, i8* %[[ECX_i8]], i32 -8 // CHECK: %[[VTORDISP_PTR:.*]] = bitcast i8* %[[VTORDISP_PTR_i8]] to i32* // CHECK: %[[VTORDISP:.*]] = load i32, i32* %[[VTORDISP_PTR]] // CHECK: %[[VTORDISP_NEG:.*]] = sub i32 0, %[[VTORDISP]] @@ -66,7 +66,7 @@ G::G() {} // Forces vftable emission. // CHECK-LABEL: define linkonce_odr x86_thiscallcc void @"\01?f@E@@$R4BA@M@PPPPPPPM@7AEXXZ"(i8*) // CHECK: %[[ECX:.*]] = load %struct.E*, %struct.E** %{{.*}} // CHECK: %[[ECX_i8:.*]] = bitcast %struct.E* %[[ECX]] to i8* -// CHECK: %[[VTORDISP_PTR_i8:.*]] = getelementptr i8, i8* %[[ECX_i8]], i32 -4 +// CHECK: %[[VTORDISP_PTR_i8:.*]] = getelementptr inbounds i8, i8* %[[ECX_i8]], i32 -4 // CHECK: %[[VTORDISP_PTR:.*]] = bitcast i8* %[[VTORDISP_PTR_i8]] to i32* // CHECK: %[[VTORDISP:.*]] = load i32, i32* %[[VTORDISP_PTR]] // CHECK: %[[VTORDISP_NEG:.*]] = sub i32 0, %[[VTORDISP]] diff --git a/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp b/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp index b868d1f0b516..8897a384430c 100644 --- a/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp +++ b/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp @@ -91,7 +91,7 @@ B::~B() { // CHECK2: %[[B:.*]] = bitcast i8* %[[B_i8]] to %struct.B* // CHECK2: call x86_thiscallcc void @"\01??1B@@UAE@XZ"(%struct.B* %[[B]]) // CHECK2: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8* - // CHECK2: %[[VBASE_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_i8]], i64 8 + // CHECK2: %[[VBASE_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_i8]], i32 8 // CHECK2: %[[VBASE:.*]] = bitcast i8* %[[VBASE_i8]] to %struct.VBase* // CHECK2: call x86_thiscallcc void @"\01??1VBase@@UAE@XZ"(%struct.VBase* %[[VBASE]]) // CHECK2: ret @@ -290,7 +290,7 @@ D::~D() { // CHECK: store %"struct.diamond::D"* %[[THIS]], %"struct.diamond::D"** %[[THIS_VAL:.*]], align 4 // CHECK: %[[THIS:.*]] = load %"struct.diamond::D"*, %"struct.diamond::D"** %[[THIS_VAL]] // CHECK: %[[D_i8:.*]] = bitcast %"struct.diamond::D"* %[[THIS]] to i8* - // CHECK: %[[C_i8:.*]] = getelementptr inbounds i8, i8* %[[D_i8]], i64 4 + // CHECK: %[[C_i8:.*]] = getelementptr inbounds i8, i8* %[[D_i8]], i32 4 // CHECK: %[[C:.*]] = bitcast i8* %[[C_i8]] to %"struct.diamond::C"* // CHECK: %[[C_i8:.*]] = bitcast %"struct.diamond::C"* %[[C]] to i8* // CHECK: %[[ARG_i8:.*]] = getelementptr i8, i8* %{{.*}}, i32 16 @@ -455,3 +455,29 @@ void destroy(E *obj) { } } + +namespace test5 { +// PR25370: Don't zero-initialize vbptrs in virtual bases. +struct A { + virtual void f(); +}; + +struct B : virtual A { + int Field; +}; + +struct C : B { + C(); +}; + +C::C() : B() {} +// CHECK-LABEL: define x86_thiscallcc %"struct.test5::C"* @"\01??0C@test5@@QAE@XZ"( +// CHECK: %[[THIS:.*]] = load %"struct.test5::C"*, %"struct.test5::C"** +// CHECK: br i1 %{{.*}}, label %[[INIT_VBASES:.*]], label %[[SKIP_VBASES:.*]] + +// CHECK: %[[SKIP_VBASES]] +// CHECK: %[[B:.*]] = bitcast %"struct.test5::C"* %[[THIS]] to %"struct.test5::B"* +// CHECK: %[[B_i8:.*]] = bitcast %"struct.test5::B"* %[[B]] to i8* +// CHECK: %[[FIELD:.*]] = getelementptr inbounds i8, i8* %[[B_i8]], i32 4 +// CHECK: call void @llvm.memset.p0i8.i32(i8* %[[FIELD]], i8 0, i32 4, i32 4, i1 false) +} diff --git a/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp b/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp index baed35145f98..aa39d6de615a 100644 --- a/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp +++ b/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp @@ -299,3 +299,18 @@ struct S { }; S::S() {} + +struct T { + struct U {}; +}; +struct V : T { + // CHECK-LABEL: VFTable for 'V' (2 entries). + // CHECK-NEXT: 0 | void V::U() + // CHECK-NEXT: 1 | void V::f() + using T::U; + virtual void f(); + virtual void U(); + V(); +}; + +V::V() {} diff --git a/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance-vtordisps.cpp b/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance-vtordisps.cpp index 1f6d4202154a..e26d333bad12 100644 --- a/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance-vtordisps.cpp +++ b/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance-vtordisps.cpp @@ -33,7 +33,7 @@ void use_somewhere_else(void*); namespace simple { // In case of a single-layer virtual inheritance, the "this" adjustment for a -// virtual method is done staically: +// virtual method is done statically: // struct A { // virtual void f(); // Expects "(A*)this" in ECX // }; @@ -222,7 +222,7 @@ G::G() {} namespace extended { // If a virtual function requires vtordisp adjustment and the final overrider -// is defined in another vitual base of the most derived class, +// is defined in another virtual base of the most derived class, // we need to know two vbase offsets. // In this case, we should use the extended form of vtordisp thunks, called // vtordispex thunks. diff --git a/test/CodeGenCXX/microsoft-compatibility.cpp b/test/CodeGenCXX/microsoft-compatibility.cpp index 297184a1df2a..36760243d49b 100644 --- a/test/CodeGenCXX/microsoft-compatibility.cpp +++ b/test/CodeGenCXX/microsoft-compatibility.cpp @@ -1,5 +1,15 @@ // RUN: %clang_cc1 %s -triple i686-pc-win32 -std=c++11 -fms-compatibility -emit-llvm -o - | FileCheck %s +template +struct S { + static const int x[]; +}; + +template <> +const int S::x[] = {1}; + +// CHECK-LABEL: @"\01?x@?$S@D@@2QBHB" = weak_odr constant [1 x i32] [i32 1], comdat + template void destroy(T *p) { p->~T(); diff --git a/test/CodeGenCXX/ms-inline-asm-fields.cpp b/test/CodeGenCXX/ms-inline-asm-fields.cpp new file mode 100644 index 000000000000..a78d511485aa --- /dev/null +++ b/test/CodeGenCXX/ms-inline-asm-fields.cpp @@ -0,0 +1,31 @@ +// REQUIRES: x86-registered-target +// RUN: %clang_cc1 %s -triple i386-apple-darwin10 -fasm-blocks -emit-llvm -o - | FileCheck %s + +struct A { + int a1; + int a2; + struct B { + int b1; + int b2; + } a3; +}; + +namespace asdf { +A a_global; +} + +extern "C" int test_param_field(A p) { +// CHECK: define i32 @test_param_field(%struct.A* byval align 4 %p) +// CHECK: getelementptr inbounds %struct.A, %struct.A* %p, i32 0, i32 0 +// CHECK: call i32 asm sideeffect inteldialect "mov eax, dword ptr $1" +// CHECK: ret i32 + __asm mov eax, p.a1 +} + +extern "C" int test_namespace_global() { +// CHECK: define i32 @test_namespace_global() +// CHECK: call i32 asm sideeffect inteldialect "mov eax, dword ptr $1", "{{.*}}"(i32* getelementptr inbounds (%struct.A, %struct.A* @_ZN4asdf8a_globalE, i32 0, i32 2, i32 1)) +// CHECK: ret i32 + __asm mov eax, asdf::a_global.a3.b2 +} + diff --git a/test/CodeGenCXX/ms-integer-static-data-members.cpp b/test/CodeGenCXX/ms-integer-static-data-members.cpp index 5e5b81d4a591..b2bfc92d264c 100644 --- a/test/CodeGenCXX/ms-integer-static-data-members.cpp +++ b/test/CodeGenCXX/ms-integer-static-data-members.cpp @@ -42,10 +42,10 @@ const int S::OutOfLine_Def_Ref = 5; // CHECK-DAG: @"\01?Inline_NotDef_Ref@S@@2HB" = linkonce_odr constant i32 5, comdat, align 4 // Inline initialization, real definiton, not referenced. -// CHECK-DAG: @"\01?Inline_Def_NotRef@S@@2HB" = constant i32 5, align 4 +// CHECK-NOT: @"\01?Inline_Def_NotRef@S@@2HB" = constant i32 5, align 4 // Inline initialization, real definiton, referenced. -// CHECK-DAG: @"\01?Inline_Def_Ref@S@@2HB" = constant i32 5, comdat, align 4 +// CHECK-DAG: @"\01?Inline_Def_Ref@S@@2HB" = linkonce_odr constant i32 5, comdat, align 4 // Out-of-line initialization. // CHECK-DAG: @"\01?OutOfLine_Def_NotRef@S@@2HB" = constant i32 5, align 4 diff --git a/test/CodeGenCXX/ms-property.cpp b/test/CodeGenCXX/ms-property.cpp new file mode 100644 index 000000000000..49e957b58e33 --- /dev/null +++ b/test/CodeGenCXX/ms-property.cpp @@ -0,0 +1,113 @@ +// RUN: %clang_cc1 -emit-llvm -triple=x86_64-pc-win32 -fms-compatibility %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple=x86_64-pc-win32 -fms-compatibility -emit-pch -o %t %s +// RUN: %clang_cc1 -emit-llvm -triple=x86_64-pc-win32 -fms-compatibility -include-pch %t -verify %s -o - | FileCheck %s +// expected-no-diagnostics + +#ifndef HEADER +#define HEADER + +class Test1 { +private: + int x_; + double y_; + +public: + Test1(int x) : x_(x) {} + __declspec(property(get = get_x)) int X; + int get_x() const { return x_; } + static Test1 *GetTest1() { return new Test1(10); } +}; + +class S { +public: + __declspec(property(get=GetX,put=PutX)) int x[]; + int GetX(int i, int j) { return i+j; } + void PutX(int i, int j, int k) { j = i = k; } +}; + +template +class St { +public: + __declspec(property(get=GetX,put=PutX)) T x[]; + T GetX(T i, T j) { return i+j; } + T GetX() { return 0; } + T PutX(T i, T j, T k) { return j = i = k; } + __declspec(property(get=GetY,put=PutY)) T y[]; + char GetY(char i, Test1 j) { return i+j.get_x(); } + void PutY(char i, int j, double k) { j = i = k; } +}; + +template +void foo(T i, T j) { + St bar; + Test1 t(i); + bar.x[i][j] = bar.x[i][j]; + bar.y[t.X][j] = bar.x[i][j]; + bar.x[i][j] = bar.y[bar.x[i][j]][t]; +} + +int idx() { return 7; } + +// CHECK-LABEL: main +int main(int argc, char **argv) { + Test1 t(argc); + S *p1 = 0; + St *p2 = 0; + // CHECK: call i32 @"\01?GetX@S@@QEAAHHH@Z"(%class.S* %{{.+}}, i32 223, i32 11) + int j = p1->x[223][11]; + // CHECK: [[J:%.+]] = load i32, i32* % + // CHECK-NEXT: call void @"\01?PutX@S@@QEAAXHHH@Z"(%class.S* %{{.+}}, i32 23, i32 1, i32 [[J]]) + p1->x[23][1] = j; + // CHECK: call float @"\01?GetX@?$St@M@@QEAAMMM@Z"(%class.St* %{{.+}}, float 2.230000e+02, float 1.100000e+01) + float j1 = p2->x[223][11]; + // CHECK: [[J1:%.+]] = load float, float* % + // CHECK-NEXT: [[CALL:%.+]] = call float @"\01?PutX@?$St@M@@QEAAMMMM@Z"(%class.St* %{{.+}}, float 2.300000e+01, float 1.000000e+00, float [[J1]]) + // CHECK-NEXT: [[CONV:%.+]] = fptosi float [[CALL]] to i32 + // CHECK-NEXT: store i32 [[CONV]], i32* + argc = p2->x[23][1] = j1; + // CHECK: [[IDX:%.+]] = call i32 @"\01?idx@@YAHXZ"() + // CHECK-NEXT: [[CONV:%.+]] = sitofp i32 [[IDX]] to float + // CHECK-NEXT: [[GET:%.+]] = call float @"\01?GetX@?$St@M@@QEAAMMM@Z"(%class.St* %{{.+}}, float [[CONV]], float 1.000000e+00) + // CHECK-NEXT: [[INC:%.+]] = fadd float [[GET]], 1.000000e+00 + // CHECK-NEXT: [[CONV:%.+]] = sitofp i32 [[IDX]] to float + // CHECK-NEXT: call float @"\01?PutX@?$St@M@@QEAAMMMM@Z"(%class.St* %{{.+}}, float [[CONV]], float 1.000000e+00, float [[INC]]) + ++p2->x[idx()][1]; + // CHECK: call void @"\01??$foo@H@@YAXHH@Z"(i32 %{{.+}}, i32 %{{.+}}) + foo(argc, (int)argv[0][0]); + // CHECK: [[P2:%.+]] = load %class.St*, %class.St** % + // CHECK: [[T_X:%.+]] = call i32 @"\01?get_x@Test1@@QEBAHXZ"(%class.Test1* %{{.+}}) + // CHECK: [[P1:%.+]] = load %class.S*, %class.S** % + // CHECK: [[P1_X_22_33:%.+]] = call i32 @"\01?GetX@S@@QEAAHHH@Z"(%class.S* [[P1]], i32 22, i32 33) + // CHECK: [[CAST:%.+]] = sitofp i32 [[P1_X_22_33]] to double + // CHECK: [[ARGC:%.+]] = load i32, i32* % + // CHECK: [[CAST2:%.+]] = trunc i32 [[T_X]] to i8 + // CHECK: call void @"\01?PutY@?$St@M@@QEAAXDHN@Z"(%class.St* [[P2]], i8 [[CAST2]], i32 [[ARGC]], double [[CAST]]) + p2->y[t.X][argc] = p1->x[22][33]; + // CHECK: [[P2_1:%.+]] = load %class.St*, %class.St** + // CHECK: [[P2_2:%.+]] = load %class.St*, %class.St** + // CHECK: [[P1:%.+]] = load %class.S*, %class.S** + // CHECK: [[ARGC:%.+]] = load i32, i32* % + // CHECK: [[P1_X_ARGC_0:%.+]] = call i32 @"\01?GetX@S@@QEAAHHH@Z"(%class.S* [[P1]], i32 [[ARGC]], i32 0) + // CHECK: [[CAST:%.+]] = trunc i32 [[P1_X_ARGC_0]] to i8 + // CHECK: [[P2_Y_p1_X_ARGC_0_T:%.+]] = call i8 @"\01?GetY@?$St@M@@QEAADDVTest1@@@Z"(%class.St* [[P2_2]], i8 [[CAST]], %class.Test1* %{{.+}}) + // CHECK: [[CAST:%.+]] = sitofp i8 [[P2_Y_p1_X_ARGC_0_T]] to float + // CHECK: [[J:%.+]] = load i32, i32* % + // CHECK: [[CAST1:%.+]] = sitofp i32 [[J]] to float + // CHECK: [[J:%.+]] = load i32, i32* % + // CHECK: [[CAST2:%.+]] = sitofp i32 [[J]] to float + // CHECK: call float @"\01?PutX@?$St@M@@QEAAMMMM@Z"(%class.St* [[P2_1]], float [[CAST2]], float [[CAST1]], float [[CAST]]) + p2->x[j][j] = p2->y[p1->x[argc][0]][t]; + // CHECK: [[CALL:%.+]] = call %class.Test1* @"\01?GetTest1@Test1@@SAPEAV1@XZ"() + // CHECK-NEXT: call i32 @"\01?get_x@Test1@@QEBAHXZ"(%class.Test1* [[CALL]]) + return Test1::GetTest1()->X; +} + +// CHECK: define linkonce_odr void @"\01??$foo@H@@YAXHH@Z"(i32 %{{.+}}, i32 %{{.+}}) +// CHECK: call i32 @"\01?GetX@?$St@H@@QEAAHHH@Z"(%class.St{{.+}}* [[BAR:%.+]], i32 %{{.+}} i32 %{{.+}}) +// CHECK: call i32 @"\01?PutX@?$St@H@@QEAAHHHH@Z"(%class.St{{.+}}* [[BAR]], i32 %{{.+}}, i32 %{{.+}}, i32 %{{.+}}) +// CHECK: call i32 @"\01?GetX@?$St@H@@QEAAHHH@Z"(%class.St{{.+}}* [[BAR]], i32 %{{.+}} i32 %{{.+}}) +// CHECK: call void @"\01?PutY@?$St@H@@QEAAXDHN@Z"(%class.St{{.+}}* [[BAR]], i8 %{{.+}}, i32 %{{.+}}, double %{{.+}} +// CHECK: call i32 @"\01?GetX@?$St@H@@QEAAHHH@Z"(%class.St{{.+}}* [[BAR]], i32 %{{.+}} i32 %{{.+}}) +// CHECK: call i8 @"\01?GetY@?$St@H@@QEAADDVTest1@@@Z"(%class.St{{.+}}* [[BAR]], i8 %{{.+}}, %class.Test1* %{{.+}}) +// CHECK: call i32 @"\01?PutX@?$St@H@@QEAAHHHH@Z"(%class.St{{.+}}* [[BAR]], i32 %{{.+}}, i32 %{{.+}}, i32 %{{.+}}) +#endif //HEADER diff --git a/test/CodeGenCXX/new-alias.cpp b/test/CodeGenCXX/new-alias.cpp index 7ddc1f988086..4afd942e3cdb 100644 --- a/test/CodeGenCXX/new-alias.cpp +++ b/test/CodeGenCXX/new-alias.cpp @@ -5,7 +5,7 @@ using size_t = decltype(sizeof(0)); extern "C" char *something(long long x) { } -// CHECK: @_Znwm = alias i8* (i64)* @something +// CHECK: @_Znwm = alias i8* (i64), i8* (i64)* @something void *operator new(size_t) __attribute__((alias("something"))); // PR16715: don't assert here. diff --git a/test/CodeGenCXX/new.cpp b/test/CodeGenCXX/new.cpp index c8e0acba7b05..6d6f70138616 100644 --- a/test/CodeGenCXX/new.cpp +++ b/test/CodeGenCXX/new.cpp @@ -371,12 +371,9 @@ namespace builtins { // CHECK-DAG: attributes [[ATTR_NOBUILTIN]] = {{[{].*}} nobuiltin {{.*[}]}} // CHECK-DAG: attributes [[ATTR_NOBUILTIN_NOUNWIND]] = {{[{].*}} nobuiltin nounwind {{.*[}]}} -// CHECK: attributes [[ATTR_NOUNWIND]] = -// CHECK-NOT: builtin -// CHECK-NOT: attributes -// CHECK: nounwind -// CHECK-NOT: builtin -// CHECK: attributes - // CHECK-DAG: attributes [[ATTR_BUILTIN_NEW]] = {{[{].*}} builtin {{.*[}]}} // CHECK-DAG: attributes [[ATTR_BUILTIN_DELETE]] = {{[{].*}} builtin {{.*[}]}} + +// The ([^b}|...) monstrosity is matching a character that's not the start of 'builtin'. +// Add more letters if this matches some other attribute. +// CHECK-DAG: attributes [[ATTR_NOUNWIND]] = {{([^b]|b[^u]|bu[^i]|bui[^l])*}} nounwind {{([^b]|b[^u]|bu[^i]|bui[^l])*$}} diff --git a/test/CodeGenCXX/observe-noexcept.cpp b/test/CodeGenCXX/observe-noexcept.cpp new file mode 100644 index 000000000000..76046a6168a9 --- /dev/null +++ b/test/CodeGenCXX/observe-noexcept.cpp @@ -0,0 +1,47 @@ +// RUN: %clang_cc1 -triple powerpc64le-unknown-unknown -std=c++11 -fopenmp -fexceptions -fcxx-exceptions -O0 -emit-llvm %s -o - | FileCheck %s + +// Check that regions that install a terminate scope in the exception stack can +// correctly generate complex arithmetic. + +// CHECK-LABEL: ffcomplex +void ffcomplex (int a) { + double _Complex dc = (double)a; + + // CHECK: call { double, double } @__muldc3(double %{{.+}}, double %{{.+}}, double %{{.+}}, double %{{.+}}) + dc *= dc; + // CHECK: call {{.+}} @__kmpc_fork_call({{.+}} [[REGNAME1:@.*]] to void (i32*, i32*, ...)*), { double, double }* %{{.+}}) + #pragma omp parallel + { + dc *= dc; + } + // CHECK: ret void +} + +// CHECK: define internal {{.+}}[[REGNAME1]]( +// CHECK-NOT: invoke +// CHECK: call { double, double } @__muldc3(double %{{.+}}, double %{{.+}}, double %{{.+}}, double %{{.+}}) +// CHECK-NOT: invoke +// CHECK: ret void + +// Check if we are observing the function pointer attribute regardless what is +// in the exception specification of the callees. +void fnoexcp(void) noexcept; + +// CHECK-LABEL: foo +void foo(int a, int b) { + + void (*fptr)(void) noexcept = fnoexcp; + + // CHECK: call {{.+}} @__kmpc_fork_call({{.+}} [[REGNAME2:@.*]] to void (i32*, i32*, ...)*), void ()** %{{.+}}) + #pragma omp parallel + { + fptr(); + } + // CHECK: ret void +} + +// CHECK: define internal {{.+}}[[REGNAME2]]( +// CHECK-NOT: invoke +// CHECK: call void %{{[0-9]+}}() +// CHECK-NOT: invoke +// CHECK: ret void diff --git a/test/CodeGenCXX/partial-destruction.cpp b/test/CodeGenCXX/partial-destruction.cpp index d135149592a1..4097fbfaa19c 100644 --- a/test/CodeGenCXX/partial-destruction.cpp +++ b/test/CodeGenCXX/partial-destruction.cpp @@ -173,3 +173,34 @@ namespace test3 { // invoke void @_ZN5test31BD1Ev( } } + +namespace test4 { + struct A { A(unsigned i); ~A(); }; + void test() { + A v[2][3] = { { A(0), A(1), A(2) }, { A(3), A(4), A(5) } }; + } +} +// CHECK-LABEL: define void @_ZN5test44testEv() +// CHECK: [[ARRAY:%.*]] = alloca [2 x [3 x [[A:%.*]]]], align +// CHECK: [[A0:%.*]] = getelementptr inbounds [2 x [3 x [[A]]]], [2 x [3 x [[A]]]]* [[ARRAY]], i64 0, i64 0 +// CHECK-NEXT: store [3 x [[A]]]* [[A0]], +// CHECK-NEXT: [[A00:%.*]] = getelementptr inbounds [3 x [[A]]], [3 x [[A]]]* [[A0]], i64 0, i64 0 +// CHECK-NEXT: store [[A]]* [[A00]], +// CHECK-NEXT: invoke void @_ZN5test41AC1Ej([[A]]* [[A00]], i32 0) +// CHECK: [[A01:%.*]] = getelementptr inbounds [[A]], [[A]]* [[A00]], i64 1 +// CHECK-NEXT: store [[A]]* [[A01]], +// CHECK-NEXT: invoke void @_ZN5test41AC1Ej([[A]]* [[A01]], i32 1) +// CHECK: [[A02:%.*]] = getelementptr inbounds [[A]], [[A]]* [[A01]], i64 1 +// CHECK-NEXT: store [[A]]* [[A02]], +// CHECK-NEXT: invoke void @_ZN5test41AC1Ej([[A]]* [[A02]], i32 2) +// CHECK: [[A1:%.*]] = getelementptr inbounds [3 x [[A]]], [3 x [[A]]]* [[A0]], i64 1 +// CHECK-NEXT: store [3 x [[A]]]* [[A1]], +// CHECK-NEXT: [[A10:%.*]] = getelementptr inbounds [3 x [[A]]], [3 x [[A]]]* [[A1]], i64 0, i64 0 +// CHECK-NEXT: store [[A]]* [[A10]], +// CHECK-NEXT: invoke void @_ZN5test41AC1Ej([[A]]* [[A10]], i32 3) +// CHECK: [[A11:%.*]] = getelementptr inbounds [[A]], [[A]]* [[A10]], i64 1 +// CHECK-NEXT: store [[A]]* [[A11]], +// CHECK-NEXT: invoke void @_ZN5test41AC1Ej([[A]]* [[A11]], i32 4) +// CHECK: [[A12:%.*]] = getelementptr inbounds [[A]], [[A]]* [[A11]], i64 1 +// CHECK-NEXT: store [[A]]* [[A12]], +// CHECK-NEXT: invoke void @_ZN5test41AC1Ej([[A]]* [[A12]], i32 5) diff --git a/test/CodeGenCXX/partial-init.cpp b/test/CodeGenCXX/partial-init.cpp new file mode 100644 index 000000000000..cb94660915ca --- /dev/null +++ b/test/CodeGenCXX/partial-init.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -std=c++11 -fcxx-exceptions -fexceptions -S -emit-llvm -o - %s | FileCheck %s + +namespace std { + struct string { + const char *p; + string(const char *s); + ~string(); + }; +} + +struct Bar { + int a; +}; + +struct Foo { + std::string c; + Bar d[32]; +}; + +static Foo table[] = { + { "blerg" }, +}; + +// CHECK: define internal void @__cxx_global_var_init +// CHECK: invoke {{.*}} @_ZNSt6stringC1EPKc( +// CHECK-NOT: unreachable +// CHECK: br label diff --git a/test/CodeGenCXX/pass-object-size.cpp b/test/CodeGenCXX/pass-object-size.cpp new file mode 100644 index 000000000000..254669b97627 --- /dev/null +++ b/test/CodeGenCXX/pass-object-size.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -O0 %s -o - 2>&1 -std=c++11 | FileCheck %s + +int gi; + +namespace lambdas { +// CHECK-LABEL: define void @_ZN7lambdas7LambdasEPc +void Lambdas(char *ptr) { + auto L1 = [](void *const p __attribute__((pass_object_size(0)))) { + return __builtin_object_size(p, 0); + }; + + int i = 0; + auto L2 = [&i](void *const p __attribute__((pass_object_size(0)))) { + return __builtin_object_size(p, 0) + i; + }; + + // CHECK: @llvm.objectsize + gi = L1(ptr); + // CHECK: @llvm.objectsize + gi = L2(ptr); +} + +// CHECK-DAG: define internal i64 @"_ZZN7lambdas7LambdasEPcENK3$_0clEPvU17pass_object_size0" +// CHECK-NOT: call i64 @llvm.objectsize +// CHECK-DAG: define internal i64 @"_ZZN7lambdas7LambdasEPcENK3$_1clEPvU17pass_object_size0" +// CHECK-NOT: call i64 @llvm.objectsize +} diff --git a/test/CodeGenCXX/pointers-to-data-members.cpp b/test/CodeGenCXX/pointers-to-data-members.cpp index 94337d98a195..fd1b9b8215f4 100644 --- a/test/CodeGenCXX/pointers-to-data-members.cpp +++ b/test/CodeGenCXX/pointers-to-data-members.cpp @@ -1,8 +1,6 @@ // RUN: %clang_cc1 %s -emit-llvm -o %t.ll -triple=x86_64-apple-darwin10 // RUN: FileCheck %s < %t.ll // RUN: FileCheck -check-prefix=CHECK-GLOBAL %s < %t.ll -// RUN: %clang_cc1 %s -emit-llvm -o %t-opt.ll -triple=x86_64-apple-darwin10 -O3 -// RUN: FileCheck --check-prefix=CHECK-O3 %s < %t-opt.ll struct A { int a; int b; }; struct B { int b; }; @@ -131,40 +129,6 @@ A::A() : a() {} } -namespace PR7139 { - -struct pair { - int first; - int second; -}; - -typedef int pair::*ptr_to_member_type; - -struct ptr_to_member_struct { - ptr_to_member_type data; - int i; -}; - -struct A { - ptr_to_member_struct a; - - A() : a() {} -}; - -// CHECK-O3: define zeroext i1 @_ZN6PR71395checkEv() [[NUW:#[0-9]+]] -bool check() { - // CHECK-O3: ret i1 true - return A().a.data == 0; -} - -// CHECK-O3: define zeroext i1 @_ZN6PR71396check2Ev() [[NUW]] -bool check2() { - // CHECK-O3: ret i1 true - return ptr_to_member_type() == 0; -} - -} - namespace VirtualBases { struct A { @@ -294,5 +258,3 @@ union U { U u; // CHECK-GLOBAL: @_ZN11IndirectPDM1uE = global %"union.IndirectPDM::U" { %union.anon { i64 -1 } }, align 8 } - -// CHECK-O3: attributes [[NUW]] = { nounwind readnone{{.*}} } diff --git a/test/CodeGenCXX/pragma-loop-safety.cpp b/test/CodeGenCXX/pragma-loop-safety.cpp index d12e41274918..393f0a3e43fe 100644 --- a/test/CodeGenCXX/pragma-loop-safety.cpp +++ b/test/CodeGenCXX/pragma-loop-safety.cpp @@ -2,48 +2,53 @@ // Verify assume_safety vectorization is recognized. void vectorize_test(int *List, int Length) { -// CHECK: define {{.*}} @_Z14vectorize_testPii +// CHECK: define {{.*}} @_Z14vectorize_test // CHECK: [[LOAD1_IV:.+]] = load i32, i32* [[IV1:[^,]+]], {{.*}}!llvm.mem.parallel_loop_access ![[LOOP1_ID:[0-9]+]] // CHECK-NEXT: [[LOAD1_LEN:.+]] = load i32, i32* [[LEN1:.+]], {{.*}}!llvm.mem.parallel_loop_access ![[LOOP1_ID]] // CHECK-NEXT: [[CMP1:.+]] = icmp slt i32[[LOAD1_IV]],[[LOAD1_LEN]] -// CHECK-NEXT: br i1[[CMP1]], label %[[LOOP1_BODY:[^,]+]], label %[[LOOP1_END:[^,]+]], !llvm.loop ![[LOOP1_HINTS:[0-9]+]] -#pragma clang loop vectorize(assume_safety) +// CHECK-NEXT: br i1[[CMP1]], label %[[LOOP1_BODY:[^,]+]], label %[[LOOP1_END:[^,]+]] +#pragma clang loop vectorize(assume_safety) interleave(disable) unroll(disable) for (int i = 0; i < Length; i++) { - // CHECK: [[LOOP1_BODY]] - // CHECK-NEXT: [[RHIV1:.+]] = load i32, i32* [[IV1]], {{.*}}!llvm.mem.parallel_loop_access ![[LOOP1_ID]] + // CHECK: [[RHIV1:.+]] = load i32, i32* [[IV1]], {{.*}}!llvm.mem.parallel_loop_access ![[LOOP1_ID]] // CHECK-NEXT: [[CALC1:.+]] = mul nsw i32[[RHIV1]], 2 // CHECK-NEXT: [[SIV1:.+]] = load i32, i32* [[IV1]]{{.*}}!llvm.mem.parallel_loop_access ![[LOOP1_ID]] // CHECK-NEXT: [[INDEX1:.+]] = sext i32[[SIV1]] to i64 // CHECK-NEXT: [[ARRAY1:.+]] = load i32*, i32** [[LIST1:.*]], {{.*}}!llvm.mem.parallel_loop_access ![[LOOP1_ID]] // CHECK-NEXT: [[PTR1:.+]] = getelementptr inbounds i32, i32*[[ARRAY1]], i64[[INDEX1]] // CHECK-NEXT: store i32[[CALC1]], i32*[[PTR1]], {{.*}}!llvm.mem.parallel_loop_access ![[LOOP1_ID]] + // CHECK-NEXT: br label [[LOOP1_INC:[^,]+]] List[i] = i * 2; + + // CHECK: br label [[LOOP1_COND:[^,]+]], !llvm.loop ![[LOOP1_HINTS:[0-9]+]] } - // CHECK: [[LOOP1_END]] } // Verify assume_safety interleaving is recognized. void interleave_test(int *List, int Length) { -// CHECK: define {{.*}} @_Z15interleave_testPii +// CHECK: define {{.*}} @_Z15interleave_test // CHECK: [[LOAD2_IV:.+]] = load i32, i32* [[IV2:[^,]+]], {{.*}}!llvm.mem.parallel_loop_access ![[LOOP2_ID:[0-9]+]] // CHECK-NEXT: [[LOAD2_LEN:.+]] = load i32, i32* [[LEN2:.+]], {{.*}}!llvm.mem.parallel_loop_access ![[LOOP2_ID]] // CHECK-NEXT: [[CMP2:.+]] = icmp slt i32[[LOAD2_IV]],[[LOAD2_LEN]] -// CHECK-NEXT: br i1[[CMP2]], label %[[LOOP2_BODY:[^,]+]], label %[[LOOP2_END:[^,]+]], !llvm.loop ![[LOOP2_HINTS:[0-9]+]] -#pragma clang loop interleave(assume_safety) +// CHECK-NEXT: br i1[[CMP2]], label %[[LOOP2_BODY:[^,]+]], label %[[LOOP2_END:[^,]+]] +#pragma clang loop interleave(assume_safety) vectorize(disable) unroll(disable) for (int i = 0; i < Length; i++) { - // CHECK: [[LOOP2_BODY]] - // CHECK-NEXT: [[RHIV2:.+]] = load i32, i32* [[IV2]], {{.*}}!llvm.mem.parallel_loop_access ![[LOOP2_ID]] + // CHECK: [[RHIV2:.+]] = load i32, i32* [[IV2]], {{.*}}!llvm.mem.parallel_loop_access ![[LOOP2_ID]] // CHECK-NEXT: [[CALC2:.+]] = mul nsw i32[[RHIV2]], 2 // CHECK-NEXT: [[SIV2:.+]] = load i32, i32* [[IV2]]{{.*}}!llvm.mem.parallel_loop_access ![[LOOP2_ID]] // CHECK-NEXT: [[INDEX2:.+]] = sext i32[[SIV2]] to i64 // CHECK-NEXT: [[ARRAY2:.+]] = load i32*, i32** [[LIST2:.*]], {{.*}}!llvm.mem.parallel_loop_access ![[LOOP2_ID]] // CHECK-NEXT: [[PTR2:.+]] = getelementptr inbounds i32, i32*[[ARRAY2]], i64[[INDEX2]] // CHECK-NEXT: store i32[[CALC2]], i32*[[PTR2]], {{.*}}!llvm.mem.parallel_loop_access ![[LOOP2_ID]] + // CHECK-NEXT: br label [[LOOP2_INC:[^,]+]] List[i] = i * 2; + + // CHECK: br label [[LOOP2_COND:[^,]+]], !llvm.loop ![[LOOP2_HINTS:[0-9]+]] } - // CHECK: [[LOOP2_END]] } -// CHECK: ![[LOOP1_HINTS]] = distinct !{![[LOOP1_HINTS]], ![[INTENABLE_1:.*]]} +// CHECK: ![[LOOP1_HINTS]] = distinct !{![[LOOP1_HINTS]], ![[INTERLEAVE_1:[0-9]+]], ![[INTENABLE_1:[0-9]+]], ![[UNROLL_DISABLE:[0-9]+]]} +// CHECK: ![[INTERLEAVE_1]] = !{!"llvm.loop.interleave.count", i32 1} // CHCCK: ![[INTENABLE_1]] = !{!"llvm.loop.vectorize.enable", i1 true} -// CHECK: ![[LOOP2_HINTS]] = distinct !{![[LOOP2_HINTS]], ![[INTENABLE_1:.*]]} +// CHECK: ![[UNROLL_DISABLE]] = !{!"llvm.loop.unroll.disable"} +// CHECK: ![[LOOP2_HINTS]] = distinct !{![[LOOP2_HINTS]], ![[WIDTH_1:[0-9]+]], ![[INTENABLE_1]], ![[UNROLL_DISABLE]]} +// CHECK: ![[WIDTH_1]] = !{!"llvm.loop.vectorize.width", i32 1} diff --git a/test/CodeGenCXX/pragma-loop.cpp b/test/CodeGenCXX/pragma-loop.cpp index dd40c1d72600..b85e0b49b9df 100644 --- a/test/CodeGenCXX/pragma-loop.cpp +++ b/test/CodeGenCXX/pragma-loop.cpp @@ -10,7 +10,7 @@ void while_test(int *List, int Length) { #pragma clang loop vectorize_width(4) #pragma clang loop unroll(full) while (i < Length) { - // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_1:.*]] + // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_1:.*]] List[i] = i * 2; i++; } @@ -36,7 +36,7 @@ void for_test(int *List, int Length) { #pragma clang loop interleave_count(static_cast(Tuner::Interleave)) #pragma clang loop unroll_count(static_cast(Tuner::Unroll)) for (int i = 0; i < Length; i++) { - // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_3:.*]] + // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_3:.*]] List[i] = i * 2; } } @@ -48,7 +48,7 @@ void for_range_test() { #pragma clang loop vectorize_width(2) interleave_count(2) for (int i : List) { - // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_4:.*]] + // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_4:.*]] List[i] = i; } } @@ -57,7 +57,7 @@ void for_range_test() { void disable_test(int *List, int Length) { #pragma clang loop vectorize(disable) unroll(disable) for (int i = 0; i < Length; i++) { - // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_5:.*]] + // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_5:.*]] List[i] = i * 2; } } @@ -71,7 +71,7 @@ void for_define_test(int *List, int Length, int Value) { #pragma clang loop vectorize_width(VECWIDTH) interleave_count(INTCOUNT) #pragma clang loop unroll_count(UNROLLCOUNT) for (int i = 0; i < Length; i++) { - // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_6:.*]] + // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_6:.*]] List[i] = i * Value; } } @@ -80,13 +80,13 @@ void for_define_test(int *List, int Length, int Value) { void for_contant_expression_test(int *List, int Length) { #pragma clang loop vectorize_width(1 + 4) for (int i = 0; i < Length; i++) { - // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_7:.*]] + // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_7:.*]] List[i] = i; } #pragma clang loop vectorize_width(3 + VECWIDTH) for (int i = 0; i < Length; i++) { - // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_8:.*]] + // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_8:.*]] List[i] += i; } } @@ -96,7 +96,7 @@ template void for_template_test(A *List, int Length, A Value) { #pragma clang loop vectorize_width(8) interleave_count(8) unroll_count(8) for (int i = 0; i < Length; i++) { - // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_9:.*]] + // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_9:.*]] List[i] = i * Value; } } @@ -110,7 +110,7 @@ void for_template_define_test(A *List, int Length, A Value) { #pragma clang loop vectorize_width(VWidth) interleave_count(ICount) #pragma clang loop unroll_count(UCount) for (int i = 0; i < Length; i++) { - // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_10:.*]] + // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_10:.*]] List[i] = i * Value; } } @@ -120,26 +120,26 @@ template void for_template_constant_expression_test(A *List, int Length) { #pragma clang loop vectorize_width(V) interleave_count(I) unroll_count(U) for (int i = 0; i < Length; i++) { - // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_11:.*]] + // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_11:.*]] List[i] = i; } #pragma clang loop vectorize_width(V * 2 + VECWIDTH) interleave_count(I * 2 + INTCOUNT) unroll_count(U * 2 + UNROLLCOUNT) for (int i = 0; i < Length; i++) { - // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_12:.*]] + // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_12:.*]] List[i] += i; } const int Scale = 4; #pragma clang loop vectorize_width(Scale * V) interleave_count(Scale * I) unroll_count(Scale * U) for (int i = 0; i < Length; i++) { - // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_13:.*]] + // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_13:.*]] List[i] += i; } #pragma clang loop vectorize_width((Scale * V) + 2) for (int i = 0; i < Length; i++) { - // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_14:.*]] + // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_14:.*]] List[i] += i; } } @@ -157,35 +157,35 @@ void template_test(double *List, int Length) { for_template_constant_expression_test(List, Length); } -// CHECK: ![[LOOP_1]] = distinct !{![[LOOP_1]], ![[UNROLL_FULL:.*]], ![[WIDTH_4:.*]], ![[INTERLEAVE_4:.*]], ![[INTENABLE_1:.*]]} -// CHECK: ![[UNROLL_FULL]] = !{!"llvm.loop.unroll.full"} +// CHECK: ![[LOOP_1]] = distinct !{![[LOOP_1]], ![[WIDTH_4:.*]], ![[INTERLEAVE_4:.*]], ![[INTENABLE_1:.*]], ![[UNROLL_FULL:.*]]} // CHECK: ![[WIDTH_4]] = !{!"llvm.loop.vectorize.width", i32 4} // CHECK: ![[INTERLEAVE_4]] = !{!"llvm.loop.interleave.count", i32 4} // CHECK: ![[INTENABLE_1]] = !{!"llvm.loop.vectorize.enable", i1 true} -// CHECK: ![[LOOP_2]] = distinct !{![[LOOP_2:.*]], ![[UNROLL_DISABLE:.*]], ![[INTERLEAVE_4:.*]], ![[WIDTH_8:.*]]} -// CHECK: ![[UNROLL_DISABLE]] = !{!"llvm.loop.unroll.disable"} +// CHECK: ![[UNROLL_FULL]] = !{!"llvm.loop.unroll.full"} +// CHECK: ![[LOOP_2]] = distinct !{![[LOOP_2:.*]], ![[WIDTH_8:.*]], ![[INTERLEAVE_4:.*]], ![[UNROLL_DISABLE:.*]]} // CHECK: ![[WIDTH_8]] = !{!"llvm.loop.vectorize.width", i32 8} -// CHECK: ![[LOOP_3]] = distinct !{![[LOOP_3]], ![[UNROLL_8:.*]], ![[INTERLEAVE_4:.*]], ![[ENABLE_1:.*]]} +// CHECK: ![[UNROLL_DISABLE]] = !{!"llvm.loop.unroll.disable"} +// CHECK: ![[LOOP_3]] = distinct !{![[LOOP_3]], ![[INTERLEAVE_4:.*]], ![[UNROLL_8:.*]], ![[INTENABLE_1:.*]]} // CHECK: ![[UNROLL_8]] = !{!"llvm.loop.unroll.count", i32 8} -// CHECK: ![[LOOP_4]] = distinct !{![[LOOP_4]], ![[INTERLEAVE_2:.*]], ![[WIDTH_2:.*]]} -// CHECK: ![[INTERLEAVE_2]] = !{!"llvm.loop.interleave.count", i32 2} +// CHECK: ![[LOOP_4]] = distinct !{![[LOOP_4]], ![[WIDTH_2:.*]], ![[INTERLEAVE_2:.*]]} // CHECK: ![[WIDTH_2]] = !{!"llvm.loop.vectorize.width", i32 2} -// CHECK: ![[LOOP_5]] = distinct !{![[LOOP_5]], ![[UNROLL_DISABLE:.*]], ![[WIDTH_1:.*]]} +// CHECK: ![[INTERLEAVE_2]] = !{!"llvm.loop.interleave.count", i32 2} +// CHECK: ![[LOOP_5]] = distinct !{![[LOOP_5]], ![[WIDTH_1:.*]], ![[UNROLL_DISABLE:.*]]} // CHECK: ![[WIDTH_1]] = !{!"llvm.loop.vectorize.width", i32 1} -// CHECK: ![[LOOP_6]] = distinct !{![[LOOP_6]], ![[UNROLL_8:.*]], ![[INTERLEAVE_2:.*]], ![[WIDTH_2:.*]]} +// CHECK: ![[LOOP_6]] = distinct !{![[LOOP_6]], ![[WIDTH_2:.*]], ![[INTERLEAVE_2:.*]], ![[UNROLL_8:.*]]} // CHECK: ![[LOOP_7]] = distinct !{![[LOOP_7]], ![[WIDTH_5:.*]]} // CHECK: ![[WIDTH_5]] = !{!"llvm.loop.vectorize.width", i32 5} // CHECK: ![[LOOP_8]] = distinct !{![[LOOP_8]], ![[WIDTH_5:.*]]} -// CHECK: ![[LOOP_9]] = distinct !{![[LOOP_9]], ![[UNROLL_8:.*]], ![[INTERLEAVE_8:.*]], ![[WIDTH_8:.*]]} +// CHECK: ![[LOOP_9]] = distinct !{![[LOOP_9]], ![[WIDTH_8:.*]], ![[INTERLEAVE_8:.*]], ![[UNROLL_8:.*]]} // CHECK: ![[INTERLEAVE_8]] = !{!"llvm.loop.interleave.count", i32 8} -// CHECK: ![[LOOP_10]] = distinct !{![[LOOP_10]], ![[UNROLL_8:.*]], ![[INTERLEAVE_2:.*]], ![[WIDTH_2:.*]]} -// CHECK: ![[LOOP_11]] = distinct !{![[LOOP_11]], ![[UNROLL_8:.*]], ![[INTERLEAVE_4:.*]], ![[WIDTH_2:.*]]} -// CHECK: ![[LOOP_12]] = distinct !{![[LOOP_12]], ![[UNROLL_24:.*]], ![[INTERLEAVE_10:.*]], ![[WIDTH_6:.*]]} -// CHECK: ![[UNROLL_24]] = !{!"llvm.loop.unroll.count", i32 24} -// CHECK: ![[INTERLEAVE_10]] = !{!"llvm.loop.interleave.count", i32 10} +// CHECK: ![[LOOP_10]] = distinct !{![[LOOP_10]], ![[WIDTH_2:.*]], ![[INTERLEAVE_2:.*]], ![[UNROLL_8:.*]]} +// CHECK: ![[LOOP_11]] = distinct !{![[LOOP_11]], ![[WIDTH_2:.*]], ![[INTERLEAVE_4:.*]], ![[UNROLL_8:.*]]} +// CHECK: ![[LOOP_12]] = distinct !{![[LOOP_12]], ![[WIDTH_6:.*]], ![[INTERLEAVE_10:.*]], ![[UNROLL_24:.*]]} // CHECK: ![[WIDTH_6]] = !{!"llvm.loop.vectorize.width", i32 6} -// CHECK: ![[LOOP_13]] = distinct !{![[LOOP_13]], ![[UNROLL_32:.*]], ![[INTERLEAVE_16:.*]], ![[WIDTH_8:.*]]} -// CHECK: ![[UNROLL_32]] = !{!"llvm.loop.unroll.count", i32 32} +// CHECK: ![[INTERLEAVE_10]] = !{!"llvm.loop.interleave.count", i32 10} +// CHECK: ![[UNROLL_24]] = !{!"llvm.loop.unroll.count", i32 24} +// CHECK: ![[LOOP_13]] = distinct !{![[LOOP_13]], ![[WIDTH_8:.*]], ![[INTERLEAVE_16:.*]], ![[UNROLL_32:.*]]} // CHECK: ![[INTERLEAVE_16]] = !{!"llvm.loop.interleave.count", i32 16} +// CHECK: ![[UNROLL_32]] = !{!"llvm.loop.unroll.count", i32 32} // CHECK: ![[LOOP_14]] = distinct !{![[LOOP_14]], ![[WIDTH_10:.*]]} // CHECK: ![[WIDTH_10]] = !{!"llvm.loop.vectorize.width", i32 10} diff --git a/test/CodeGenCXX/pragma-unroll.cpp b/test/CodeGenCXX/pragma-unroll.cpp index 8b73fa6c8aab..8f079092480a 100644 --- a/test/CodeGenCXX/pragma-unroll.cpp +++ b/test/CodeGenCXX/pragma-unroll.cpp @@ -7,7 +7,7 @@ void while_test(int *List, int Length) { #pragma unroll while (i < Length) { - // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_1:.*]] + // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_1:.*]] List[i] = i * 2; i++; } @@ -15,6 +15,7 @@ void while_test(int *List, int Length) { // Verify do loop is recognized after multi-option pragma clang loop directive. void do_test(int *List, int Length) { + // CHECK: define {{.*}} @_Z7do_test int i = 0; #pragma nounroll @@ -27,20 +28,22 @@ void do_test(int *List, int Length) { // Verify for loop is recognized after unroll pragma. void for_test(int *List, int Length) { +// CHECK: define {{.*}} @_Z8for_test #pragma unroll 8 for (int i = 0; i < Length; i++) { - // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_3:.*]] + // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_3:.*]] List[i] = i * 2; } } // Verify c++11 for range loop is recognized after unroll pragma. void for_range_test() { + // CHECK: define {{.*}} @_Z14for_range_test double List[100]; #pragma unroll(4) for (int i : List) { - // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_4:.*]] + // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_4:.*]] List[i] = i; } } @@ -49,9 +52,10 @@ void for_range_test() { // Verify defines are correctly resolved in unroll pragmas. void for_define_test(int *List, int Length, int Value) { +// CHECK: define {{.*}} @_Z15for_define_test #pragma unroll(UNROLLCOUNT) for (int i = 0; i < Length; i++) { - // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_5:.*]] + // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_5:.*]] List[i] = i * Value; } } @@ -59,9 +63,10 @@ void for_define_test(int *List, int Length, int Value) { // Verify metadata is generated when template is used. template void for_template_test(A *List, int Length, A Value) { +// CHECK: define {{.*}} @_Z13template_test #pragma unroll 8 for (int i = 0; i < Length; i++) { - // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_6:.*]] + // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_6:.*]] List[i] = i * Value; } } @@ -69,9 +74,11 @@ void for_template_test(A *List, int Length, A Value) { // Verify define is resolved correctly when template is used. template void for_template_define_test(A *List, int Length, A Value) { +// CHECK: define {{.*}} @_Z24for_template_define_test + #pragma unroll(UNROLLCOUNT) for (int i = 0; i < Length; i++) { - // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_7:.*]] + // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_7:.*]] List[i] = i * Value; } } @@ -86,8 +93,8 @@ void template_test(double *List, int Length) { for_template_define_test(List, Length, Value); } -// CHECK: ![[LOOP_1]] = distinct !{![[LOOP_1]], ![[UNROLL_FULL:.*]]} -// CHECK: ![[UNROLL_FULL]] = !{!"llvm.loop.unroll.full"} +// CHECK: ![[LOOP_1]] = distinct !{![[LOOP_1]], ![[UNROLL_ENABLE:.*]]} +// CHECK: ![[UNROLL_ENABLE]] = !{!"llvm.loop.unroll.enable"} // CHECK: ![[LOOP_2]] = distinct !{![[LOOP_2:.*]], ![[UNROLL_DISABLE:.*]]} // CHECK: ![[UNROLL_DISABLE]] = !{!"llvm.loop.unroll.disable"} // CHECK: ![[LOOP_3]] = distinct !{![[LOOP_3]], ![[UNROLL_8:.*]]} diff --git a/test/CodeGenCXX/redefine_extname.cpp b/test/CodeGenCXX/redefine_extname.cpp index f76fe6252fef..41860d47ffe8 100644 --- a/test/CodeGenCXX/redefine_extname.cpp +++ b/test/CodeGenCXX/redefine_extname.cpp @@ -28,3 +28,9 @@ extern "C" { // CHECK: define i32 @bar() } +// Check that #pragma redefine_extname applies to C code only, and shouldn't be +// applied to C++. +#pragma redefine_extname foo_cpp bar_cpp +extern int foo_cpp() { return 1; } +// CHECK-NOT: define i32 @bar_cpp() + diff --git a/test/CodeGenCXX/sanitize-dtor-bit-field.cpp b/test/CodeGenCXX/sanitize-dtor-bit-field.cpp new file mode 100644 index 000000000000..d4497f6aac0b --- /dev/null +++ b/test/CodeGenCXX/sanitize-dtor-bit-field.cpp @@ -0,0 +1,84 @@ +// Test -fsanitize-memory-use-after-dtor +// RUN: %clang_cc1 -O0 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -O1 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s + +// 24 bytes total +struct Packed { + // Packed into 4 bytes + unsigned int a : 1; + unsigned int b : 1; + //unsigned int c : 1; + // Force alignment to next 4 bytes + unsigned int : 0; + unsigned int d : 1; + // Force alignment, 8 more bytes + double e = 5.0; + // 4 bytes + unsigned int f : 1; + ~Packed() {} +}; +Packed p; + + +// 1 byte total +struct Empty { + unsigned int : 0; + ~Empty() {} +}; +Empty e; + + +// 4 byte total +struct Simple { + unsigned int a : 1; + ~Simple() {} +}; +Simple s; + + +// 8 bytes total +struct Anon { + // 1 byte + unsigned int a : 1; + unsigned int b : 2; + // Force alignment to next byte + unsigned int : 0; + unsigned int c : 1; + ~Anon() {} +}; +Anon an; + + +struct CharStruct { + char c; + ~CharStruct(); +}; + +struct Adjacent { + CharStruct a; + int b : 1; + CharStruct c; + ~Adjacent() {} +}; +Adjacent ad; + + +// CHECK-LABEL: define {{.*}}PackedD2Ev +// CHECK: call void @__sanitizer_dtor_callback{{.*}}i64 17 +// CHECK: ret void + +// CHECK-LABEL: define {{.*}}EmptyD2Ev +// CHECK-NOT: call void @__sanitizer_dtor_callback{{.*}}i64 0 +// CHECK: ret void + +// CHECK-LABEL: define {{.*}}SimpleD2Ev +// CHECK: call void @__sanitizer_dtor_callback{{.*}}i64 1 +// CHECK: ret void + +// CHECK-LABEL: define {{.*}}AnonD2Ev +// CHECK: call void @__sanitizer_dtor_callback{{.*}}i64 5 +// CHECK: ret void + +// CHECK-LABEL: define {{.*}}AdjacentD2Ev +// CHECK: call void @__sanitizer_dtor_callback{{.*}}i64 1 +// CHECK: ret void diff --git a/test/CodeGenCXX/sanitize-dtor-callback.cpp b/test/CodeGenCXX/sanitize-dtor-callback.cpp index 4912a27229f9..e208a6f7e5a5 100644 --- a/test/CodeGenCXX/sanitize-dtor-callback.cpp +++ b/test/CodeGenCXX/sanitize-dtor-callback.cpp @@ -1,17 +1,70 @@ // Test -fsanitize-memory-use-after-dtor -// RUN: %clang_cc1 -fsanitize=memory -fsanitize-memory-use-after-dtor -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s -// RUN: %clang_cc1 -fsanitize=memory -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s -check-prefix=NO_DTOR_CHECK +// RUN: %clang_cc1 -fsanitize=memory -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s + +// Sanitizing dtor is emitted in dtor for every class, and only +// poisons once. struct Simple { + int x; ~Simple() {} }; Simple s; // Simple internal member is poisoned by compiler-generated dtor -// CHECK-LABEL: @_ZN6SimpleD2Ev +// CHECK-LABEL: define {{.*}}SimpleD1Ev +// CHECK: call void {{.*}}SimpleD2Ev +// CHECK: ret void + +struct Inlined { + int y; + inline ~Inlined() {} +}; +Inlined i; +// Simple internal member is poisoned by compiler-generated dtor +// CHECK-LABEL: define {{.*}}InlinedD1Ev +// CHECK: call void {{.*}}InlinedD2Ev +// CHECK: ret void + +struct Defaulted_Trivial { + ~Defaulted_Trivial() = default; +}; +void create_def_trivial() { + Defaulted_Trivial def_trivial; +} +// The compiler is explicitly signalled to handle object cleanup. +// No complex member attributes. Compiler destroys inline, so +// no destructor defined. +// CHECK-LABEL: define {{.*}}create_def_trivial +// CHECK-NOT: call {{.*}}Defaulted_Trivial +// CHECK: ret void + +struct Defaulted_Non_Trivial { + Simple s; + ~Defaulted_Non_Trivial() = default; +}; +Defaulted_Non_Trivial def_non_trivial; +// Explicitly compiler-generated dtor poisons object. +// By including a Simple member in the struct, the compiler is +// forced to generate a non-trivial destructor. +// CHECK-LABEL: define {{.*}}Defaulted_Non_TrivialD1Ev +// CHECK: call void {{.*}}Defaulted_Non_TrivialD2 +// CHECK: ret void + + +// Note: ordering is important. In the emitted bytecode, these +// second dtors defined after the first. Explicitly checked here +// to confirm that all invoked dtors have member poisoning +// instrumentation inserted. +// CHECK-LABEL: define {{.*}}SimpleD2Ev // CHECK: call void @__sanitizer_dtor_callback +// CHECK-NOT: call void @__sanitizer_dtor_callback // CHECK: ret void -// Compiling without the flag does not generate member-poisoning dtor -// NO_DTOR_CHECK-LABEL: @_ZN6SimpleD2Ev -// NO_DTOR_CHECK-NOT: call void @sanitizer_dtor_callback -// NO_DTOR_CHECK: ret void +// CHECK-LABEL: define {{.*}}InlinedD2Ev +// CHECK: call void @__sanitizer_dtor_callback +// CHECK-NOT: call void @__sanitizer_dtor_callback +// CHECK: ret void + +// CHECK-LABEL: define {{.*}}Defaulted_Non_TrivialD2Ev +// CHECK: call void @__sanitizer_dtor_callback +// CHECK-NOT: call void @__sanitizer_dtor_callback +// CHECK: ret void diff --git a/test/CodeGenCXX/sanitize-dtor-derived-class.cpp b/test/CodeGenCXX/sanitize-dtor-derived-class.cpp new file mode 100644 index 000000000000..f3134711824d --- /dev/null +++ b/test/CodeGenCXX/sanitize-dtor-derived-class.cpp @@ -0,0 +1,71 @@ +// RUN: %clang_cc1 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -O1 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s + +// Base dtor poisons members +// Complete dtor poisons vtable ptr after destroying members and +// virtual bases + +class Base { + public: + int x; + Base() { + x = 5; + } + virtual ~Base() { + x += 1; + } +}; + +class Derived : public Base { + public: + int y; + Derived() { + y = 10; + } + ~Derived() { + y += 1; + } +}; + +Derived d; + +// Invoke base destructor. No vtable pointer to poison. +// CHECK-LABEL: define {{.*}}DerivedD1Ev +// CHECK-NOT: call void @__sanitizer_dtor_callback +// CHECK: call void {{.*}}DerivedD2Ev +// CHECK-NOT: call void @__sanitizer_dtor_callback +// CHECK: ret void + +// CHECK-LABEL: define {{.*}}DerivedD0Ev +// CHECK-NOT: call void @__sanitizer_dtor_callback +// CHECK: call void {{.*}}DerivedD1Ev +// CHECK-NOT: call void @__sanitizer_dtor_callback +// CHECK: ret void + +// Invokes base destructor, and poison vtable pointer. +// CHECK-LABEL: define {{.*}}BaseD1Ev +// CHECK-NOT: call void @__sanitizer_dtor_callback +// CHECK: call void {{.*}}BaseD2Ev +// CHECK-NOT: call void @__sanitizer_dtor_callback +// CHECK: ret void + +// CHECK-LABEL: define {{.*}}BaseD0Ev +// CHECK-NOT: call void @__sanitizer_dtor_callback +// CHECK: call void {{.*}}BaseD1Ev +// CHECK-NOT: call void @__sanitizer_dtor_callback +// CHECK: ret void + +// Poison members and vtable ptr. +// CHECK-LABEL: define {{.*}}BaseD2Ev +// CHECK: call void @__sanitizer_dtor_callback +// CHECK: call void @__sanitizer_dtor_callback{{.*}}i64 8 +// CHECK-NOT: call void @__sanitizer_dtor_callback +// CHECK: ret void + +// Poison members and destroy non-virtual base. +// CHECK-LABEL: define {{.*}}DerivedD2Ev +// CHECK: call void @__sanitizer_dtor_callback +// CHECK-NOT: call void @__sanitizer_dtor_callback +// CHECK: call void {{.*}}BaseD2Ev +// CHECK: call void @__sanitizer_dtor_callback{{.*}}i64 8 +// CHECK: ret void diff --git a/test/CodeGenCXX/sanitize-dtor-fn-attribute.cpp b/test/CodeGenCXX/sanitize-dtor-fn-attribute.cpp new file mode 100644 index 000000000000..4af26770223f --- /dev/null +++ b/test/CodeGenCXX/sanitize-dtor-fn-attribute.cpp @@ -0,0 +1,43 @@ +// Test -fsanitize-memory-use-after-dtor +// RUN: %clang_cc1 -fsanitize=memory -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s + +// The no_sanitize_memory attribute, when applied to a destructor, +// represses emission of sanitizing callback + +template class Vector { + public: + int size; + ~Vector() {} +}; + +struct No_San { + Vector v; + int x; + No_San() { } + __attribute__((no_sanitize_memory)) ~No_San() = default; +}; + +int main() { + No_San *ns = new No_San(); + ns->~No_San(); + return 0; +} + +// Repressing the sanitization attribute results in no msan +// instrumentation of the destructor +// CHECK: define {{.*}}No_SanD1Ev{{.*}} [[ATTRIBUTE:#[0-9]+]] +// CHECK-NOT: call void {{.*}}sanitizer_dtor_callback +// CHECK: ret void + +// CHECK: define {{.*}}No_SanD2Ev{{.*}} [[ATTRIBUTE:#[0-9]+]] +// CHECK-NOT: call void {{.*}}sanitizer_dtor_callback +// CHECK: call void {{.*}}VectorIiED2Ev +// CHECK-NOT: call void {{.*}}sanitizer_dtor_callback +// CHECK: ret void + +// CHECK: define {{.*}}VectorIiED2Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback +// CHECK: ret void + +// When attribute is repressed, the destructor does not emit any tail calls +// CHECK-NOT: attributes [[ATTRIBUTE]] = {{.*}} sanitize_memory diff --git a/test/CodeGenCXX/sanitize-dtor-nontrivial-virtual-base.cpp b/test/CodeGenCXX/sanitize-dtor-nontrivial-virtual-base.cpp new file mode 100644 index 000000000000..27eb64b55347 --- /dev/null +++ b/test/CodeGenCXX/sanitize-dtor-nontrivial-virtual-base.cpp @@ -0,0 +1,82 @@ +// RUN: %clang_cc1 -fsanitize=memory -O0 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -fsanitize=memory -O1 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s + +template +class Vector { +public: + int size; + ~Vector() { + size += 1; + } +}; + +struct Base { + int b1; + double b2; + Base() { + b1 = 5; + b2 = 10.989; + } + virtual ~Base() {} +}; + +struct VirtualBase { + int vb1; + int vb2; + VirtualBase() { + vb1 = 10; + vb2 = 11; + } + virtual ~VirtualBase() {} +}; + +struct Derived : public Base, public virtual VirtualBase { + int d1; + Vector v; + int d2; + Derived() { + d1 = 10; + } + ~Derived() {} +}; + +Derived d; + +// Destruction order: +// Derived: int, Vector, Base, VirtualBase + +// CHECK-LABEL: define {{.*}}ZN7DerivedD1Ev +// CHECK: call void {{.*}}ZN11VirtualBaseD2Ev +// CHECK: ret void + +// CHECK-LABEL: define {{.*}}ZN7DerivedD0Ev +// CHECK: ret void + +// CHECK-LABEL: define {{.*}}ZN11VirtualBaseD1Ev +// CHECK: ret void + +// CHECK-LABEL: define {{.*}}ZN11VirtualBaseD0Ev +// CHECK: ret void + +// poison 2 ints +// CHECK-LABEL: define {{.*}}ZN11VirtualBaseD2Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 8) +// CHECK: ret void + +// poison int and double +// CHECK-LABEL: define {{.*}}ZN4BaseD2Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 16) +// CHECK: ret void + +// poison int, ignore vector, poison int +// CHECK-LABEL: define {{.*}}ZN7DerivedD2Ev +// CHECK: call void {{.*}}ZN6VectorIiED1Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 4) +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 4) +// CHECK: call void {{.*}}ZN4BaseD2Ev +// CHECK: ret void + +// poison int +// CHECK-LABEL: define {{.*}}ZN6VectorIiED2Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 4) +// CHECK: ret void diff --git a/test/CodeGenCXX/sanitize-dtor-repress-aliasing.cpp b/test/CodeGenCXX/sanitize-dtor-repress-aliasing.cpp new file mode 100644 index 000000000000..28624a0e7aec --- /dev/null +++ b/test/CodeGenCXX/sanitize-dtor-repress-aliasing.cpp @@ -0,0 +1,30 @@ +// Test -fsanitize-memory-use-after-dtor +// RUN: %clang_cc1 -fsanitize=memory -O1 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -fsanitize=memory -O2 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s + +template +class Vector { +public: + int size; + ~Vector() {} +}; + +// Virtual function table for the derived class only contains +// its own destructors, with no aliasing to base class dtors. +struct Base { + Vector v; + int x; + Base() { x = 5; } + virtual ~Base() {} +}; + +struct Derived : public Base { + int z; + Derived() { z = 10; } + ~Derived() {} +}; + +Derived d; + +// Definition of virtual function table +// CHECK: @_ZTV7Derived = {{.*}}@_ZN7DerivedD1Ev{{.*}}@_ZN7DerivedD0Ev diff --git a/test/CodeGenCXX/sanitize-dtor-tail-call.cpp b/test/CodeGenCXX/sanitize-dtor-tail-call.cpp new file mode 100644 index 000000000000..de2fd8c75c88 --- /dev/null +++ b/test/CodeGenCXX/sanitize-dtor-tail-call.cpp @@ -0,0 +1,23 @@ +// Test -fsanitize-memory-use-after-dtor +// RUN: %clang_cc1 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -O1 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s + +struct Simple { + int x_; + Simple() { + x_ = 5; + } + ~Simple() { + x_ += 1; + } +}; + +Simple s; +// Simple internal member is poisoned by compiler-generated dtor +// CHECK: define {{.*}}SimpleD2Ev{{.*}} [[ATTRIBUTE:#[0-9]+]] +// CHECK: {{^ *}}call void @__sanitizer_dtor_callback +// CHECK-NOT: call void @__sanitizer_dtor_callback +// CHECK: ret void + +// Destructor does not emit any tail calls +// CHECK: attributes [[ATTRIBUTE]] = {{.*}}"disable-tail-calls"="true" diff --git a/test/CodeGenCXX/sanitize-dtor-trivial.cpp b/test/CodeGenCXX/sanitize-dtor-trivial.cpp new file mode 100644 index 000000000000..39f580af97e7 --- /dev/null +++ b/test/CodeGenCXX/sanitize-dtor-trivial.cpp @@ -0,0 +1,15 @@ +// Test -fsanitize-memory-use-after-dtor +// RUN: %clang_cc1 -O0 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -O1 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s + +// TODO Success pending on resolution of issue: +// https://github.com/google/sanitizers/issues/596 +// XFAIL: * + +struct Trivial { + int a; + int b; +}; +Trivial t; + +// CHECK: call void @__sanitizer_dtor_callback diff --git a/test/CodeGenCXX/sanitize-dtor-vtable.cpp b/test/CodeGenCXX/sanitize-dtor-vtable.cpp new file mode 100644 index 000000000000..78be7949c32c --- /dev/null +++ b/test/CodeGenCXX/sanitize-dtor-vtable.cpp @@ -0,0 +1,47 @@ +// RUN: %clang_cc1 -O0 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -O1 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s + +class A { + public: + int x; + A() {} + virtual ~A() {} +}; +A a; + +class B : virtual public A { + public: + int y; + B() {} + ~B() {} +}; +B b; + +// CHECK-LABEL: define {{.*}}AD1Ev +// CHECK-NOT: call void @__sanitizer_dtor_callback +// CHECK: call void {{.*}}AD2Ev +// CHECK-NOT: call void @__sanitizer_dtor_callback +// CHECK: ret void + +// After invoking base dtor and dtor for virtual base, poison vtable ptr. +// CHECK-LABEL: define {{.*}}BD1Ev +// CHECK-NOT: call void @__sanitizer_dtor_callback +// CHECK: call void {{.*}}BD2Ev +// CHECK-NOT: call void @__sanitizer_dtor_callback +// CHECK: call void {{.*}}AD2Ev +// CHECK: call void @__sanitizer_dtor_callback{{.*}}i64 8 +// CHECK-NOT: call void @__sanitizer_dtor_callback +// CHECK: ret void + +// Since no virtual bases, poison vtable ptr here. +// CHECK-LABEL: define {{.*}}AD2Ev +// CHECK: call void @__sanitizer_dtor_callback +// CHECK: call void @__sanitizer_dtor_callback{{.*}}i64 8 +// CHECK-NOT: call void @__sanitizer_dtor_callback +// CHECK: ret void + +// Poison members +// CHECK-LABEL: define {{.*}}BD2Ev +// CHECK: call void @__sanitizer_dtor_callback +// CHECK-NOT: call void @__sanitizer_dtor_callback +// CHECK: ret void diff --git a/test/CodeGenCXX/sanitize-no-dtor-callback.cpp b/test/CodeGenCXX/sanitize-no-dtor-callback.cpp new file mode 100644 index 000000000000..2c355766216d --- /dev/null +++ b/test/CodeGenCXX/sanitize-no-dtor-callback.cpp @@ -0,0 +1,23 @@ +// Test without the flag -fsanitize-memory-use-after-dtor, to ensure that +// instrumentation is not erroneously inserted +// RUN: %clang_cc1 -fsanitize=memory -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s + +struct Simple { + ~Simple() {} +}; +Simple s; +// CHECK-LABEL: define {{.*}}SimpleD1Ev +// CHECK-NOT: call void @__sanitizer_dtor_callback + +struct Inlined { + inline ~Inlined() {} +}; +Inlined i; +// CHECK-LABEL: define {{.*}}InlinedD1Ev +// CHECK-NOT: call void @__sanitizer_dtor_callback + +// CHECK-LABEL: define {{.*}}SimpleD2Ev +// CHECK-NOT: call void @__sanitizer_dtor_callback + +// CHECK-LABEL: define {{.*}}InlinedD2Ev +// CHECK-NOT: call void @__sanitizer_dtor_callback diff --git a/test/CodeGenCXX/scoped-enums-debug-info.cpp b/test/CodeGenCXX/scoped-enums-debug-info.cpp index 52658fc28d74..131e31b021ae 100644 --- a/test/CodeGenCXX/scoped-enums-debug-info.cpp +++ b/test/CodeGenCXX/scoped-enums-debug-info.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++11 -emit-llvm -g -o - %s | FileCheck %s +// RUN: %clang_cc1 -std=c++11 -emit-llvm -debug-info-kind=limited -o - %s | FileCheck %s // Test that we are emitting debug info and base types for scoped enums. // CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "Color" diff --git a/test/CodeGenCXX/sel-address.mm b/test/CodeGenCXX/sel-address.mm deleted file mode 100644 index c3db9a7d00e5..000000000000 --- a/test/CodeGenCXX/sel-address.mm +++ /dev/null @@ -1,14 +0,0 @@ -// RUN: %clang_cc1 %s -verify -emit-llvm -o %t -// pr7390 - -void f(const SEL& v2) {} -void g() { - f(@selector(dealloc)); - - SEL s = @selector(dealloc); - SEL* ps = &s; - - @selector(dealloc) = s; // expected-error {{expression is not assignable}} - - SEL* ps2 = &@selector(dealloc); -} diff --git a/test/CodeGenCXX/static-init-wasm.cpp b/test/CodeGenCXX/static-init-wasm.cpp new file mode 100644 index 000000000000..2d187b5c05fc --- /dev/null +++ b/test/CodeGenCXX/static-init-wasm.cpp @@ -0,0 +1,54 @@ +// RUN: %clang_cc1 -emit-llvm -triple=wasm32-unknown-unknown -o - %s \ +// RUN: | FileCheck %s -check-prefix=WEBASSEMBLY32 +// RUN: %clang_cc1 -emit-llvm -triple=wasm64-unknown-unknown -o - %s \ +// RUN: | FileCheck %s -check-prefix=WEBASSEMBLY64 + +// Test that we don't create common blocks. +int tentative; +// WEBASSEMBLY32: @tentative = global i32 0, align 4 +// WEBASSEMBLY64: @tentative = global i32 0, align 4 + +// Test that WebAssembly uses the ARM-style ABI in which the static +// variable's guard variable is tested via "load i8 and test the +// bottom bit" rather than the Itanium/x86 ABI which uses "load i8 +// and compare with zero". +int f(); +void g() { + static int a = f(); +} +// WEBASSEMBLY32-LABEL: @_Z1gv() +// WEBASSEMBLY32: %[[R0:.+]] = load atomic i8, i8* bitcast (i32* @_ZGVZ1gvE1a to i8*) acquire, align 4 +// WEBASSEMBLY32-NEXT: %[[R1:.+]] = and i8 %[[R0]], 1 +// WEBASSEMBLY32-NEXT: %[[R2:.+]] = icmp eq i8 %[[R1]], 0 +// WEBASSEMBLY32-NEXT: br i1 %[[R2]], label %[[CHECK:.+]], label %[[END:.+]] +// WEBASSEMBLY32: [[CHECK]] +// WEBASSEMBLY32: call i32 @__cxa_guard_acquire +// WEBASSEMBLY32: [[END]] +// WEBASSEMBLY32: call void @__cxa_guard_release +// +// WEBASSEMBLY64-LABEL: @_Z1gv() +// WEBASSEMBLY64: %[[R0:.+]] = load atomic i8, i8* bitcast (i64* @_ZGVZ1gvE1a to i8*) acquire, align 8 +// WEBASSEMBLY64-NEXT: %[[R1:.+]] = and i8 %[[R0]], 1 +// WEBASSEMBLY64-NEXT: %[[R2:.+]] = icmp eq i8 %[[R1]], 0 +// WEBASSEMBLY64-NEXT: br i1 %[[R2]], label %[[CHECK:.+]], label %[[END:.+]] +// WEBASSEMBLY64: [[CHECK]] +// WEBASSEMBLY64: call i32 @__cxa_guard_acquire +// WEBASSEMBLY64: [[END]] +// WEBASSEMBLY64: call void @__cxa_guard_release + +// Test various aspects of static constructor calls. +struct A { + A(); +}; + +A theA; + +// WEBASSEMBLY32: define internal void @__cxx_global_var_init() #0 section ".text.__startup" { +// WEBASSEMBLY32: call %struct.A* @_ZN1AC1Ev(%struct.A* @theA) +// WEBASSEMBLY32: define internal void @_GLOBAL__sub_I_static_init_wasm.cpp() #0 section ".text.__startup" { +// WEBASSEMBLY32: call void @__cxx_global_var_init() +// +// WEBASSEMBLY64: define internal void @__cxx_global_var_init() #0 section ".text.__startup" { +// WEBASSEMBLY64: call %struct.A* @_ZN1AC1Ev(%struct.A* @theA) +// WEBASSEMBLY64: define internal void @_GLOBAL__sub_I_static_init_wasm.cpp() #0 section ".text.__startup" { +// WEBASSEMBLY64: call void @__cxx_global_var_init() diff --git a/test/CodeGenCXX/static-init.cpp b/test/CodeGenCXX/static-init.cpp index 25489f022ce6..541f6416efd0 100644 --- a/test/CodeGenCXX/static-init.cpp +++ b/test/CodeGenCXX/static-init.cpp @@ -6,9 +6,10 @@ // CHECK: @_ZZN5test31BC1EvE1u = internal global { i8, [3 x i8] } { i8 97, [3 x i8] undef }, align 4 -// CHECK: @_ZZ2h2vE1i = linkonce_odr global i32 0, comdat, align -// CHECK: @_ZGVZ2h2vE1i = linkonce_odr global i64 0, comdat{{$}} +// CHECK: @_ZZ2h2vE1i = linkonce_odr global i32 0, comdat, align 4 +// CHECK: @_ZGVZ2h2vE1i = linkonce_odr global i64 0, comdat, align 8{{$}} // CHECK: @_ZZN5test1L6getvarEiE3var = internal constant [4 x i32] [i32 1, i32 0, i32 2, i32 4], align 16 +// CHECK: @_ZZN5test414useStaticLocalEvE3obj = linkonce_odr global %"struct.test4::HasVTable" zeroinitializer, comdat, align 8 struct A { A(); @@ -16,7 +17,7 @@ struct A { }; void f() { - // CHECK: load atomic i8, i8* bitcast (i64* @_ZGVZ1fvE1a to i8*) acquire, align 1 + // CHECK: load atomic i8, i8* bitcast (i64* @_ZGVZ1fvE1a to i8*) acquire, align 8 // CHECK: call i32 @__cxa_guard_acquire // CHECK: call void @_ZN1AC1Ev // CHECK: call i32 @__cxa_atexit(void (i8*)* bitcast (void (%struct.A*)* @_ZN1AD1Ev to void (i8*)*), i8* getelementptr inbounds (%struct.A, %struct.A* @_ZZ1fvE1a, i32 0, i32 0), i8* @__dso_handle) @@ -154,3 +155,19 @@ namespace test3 { // CHECK-LABEL: define void @_ZN5test31BC2Ev( // CHECK-LABEL: define void @_ZN5test31BC1Ev( } + +// We forgot to set the comdat when replacing the global with a different type. +namespace test4 { +struct HasVTable { + virtual void f(); +}; +inline HasVTable &useStaticLocal() { + static HasVTable obj; + return obj; +} +void useit() { + useStaticLocal(); +} +// CHECK: define linkonce_odr dereferenceable(8) %"struct.test4::HasVTable"* @_ZN5test414useStaticLocalEv() +// CHECK: ret %"struct.test4::HasVTable"* @_ZZN5test414useStaticLocalEvE3obj +} diff --git a/test/CodeGenCXX/strict-vtable-pointers.cpp b/test/CodeGenCXX/strict-vtable-pointers.cpp new file mode 100644 index 000000000000..ee3919149cab --- /dev/null +++ b/test/CodeGenCXX/strict-vtable-pointers.cpp @@ -0,0 +1,219 @@ +// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -fstrict-vtable-pointers -disable-llvm-optzns -O2 -emit-llvm -o %t.ll +// RUN: FileCheck --check-prefix=CHECK-CTORS %s < %t.ll +// RUN: FileCheck --check-prefix=CHECK-NEW %s < %t.ll +// RUN: FileCheck --check-prefix=CHECK-DTORS %s < %t.ll +// RUN: FileCheck --check-prefix=CHECK-LINK-REQ %s < %t.ll + +typedef __typeof__(sizeof(0)) size_t; +void *operator new(size_t, void*) throw(); + +struct NotTrivialDtor { + ~NotTrivialDtor(); +}; + +struct DynamicBase1 { + NotTrivialDtor obj; + virtual void foo(); +}; + +struct DynamicDerived : DynamicBase1 { + void foo(); +}; + +struct DynamicBase2 { + virtual void bar(); + ~DynamicBase2() { + bar(); + } +}; + +struct DynamicDerivedMultiple : DynamicBase1, DynamicBase2 { + virtual void foo(); + virtual void bar(); +}; + +struct StaticBase { + NotTrivialDtor obj; + void bar(); +}; + +struct DynamicFromStatic : StaticBase { + virtual void bar(); +}; + +struct DynamicFromVirtualStatic1 : virtual StaticBase { +}; + +struct DynamicFromVirtualStatic2 : virtual StaticBase { +}; + +struct DynamicFrom2Virtuals : + DynamicFromVirtualStatic1, + DynamicFromVirtualStatic2 { +}; + +// CHECK-NEW-LABEL: define void @_Z12LocalObjectsv() +// CHECK-NEW-NOT: @llvm.invariant.group.barrier( +// CHECK-NEW-LABEL: } +void LocalObjects() { + DynamicBase1 DB; + DB.foo(); + DynamicDerived DD; + DD.foo(); + + DynamicBase2 DB2; + DB2.bar(); + + StaticBase SB; + SB.bar(); + + DynamicDerivedMultiple DDM; + DDM.foo(); + DDM.bar(); + + DynamicFromStatic DFS; + DFS.bar(); + DynamicFromVirtualStatic1 DFVS1; + DFVS1.bar(); + DynamicFrom2Virtuals DF2V; + DF2V.bar(); +} + +struct DynamicFromVirtualStatic1; +// CHECK-CTORS-LABEL: define linkonce_odr void @_ZN25DynamicFromVirtualStatic1C1Ev +// CHECK-CTORS-NOT: @llvm.invariant.group.barrier( +// CHECK-CTORS-LABEL: } + +struct DynamicFrom2Virtuals; +// CHECK-CTORS-LABEL: define linkonce_odr void @_ZN20DynamicFrom2VirtualsC1Ev +// CHECK-CTORS: call i8* @llvm.invariant.group.barrier( +// CHECK-CTORS-LABEL: } + + +// CHECK-NEW-LABEL: define void @_Z9Pointers1v() +// CHECK-NEW-NOT: @llvm.invariant.group.barrier( +// CHECK-NEW-LABEL: call void @_ZN12DynamicBase1C1Ev( + +// CHECK-NEW: %[[THIS3:.*]] = call i8* @llvm.invariant.group.barrier(i8* %[[THIS2:.*]]) +// CHECK-NEW: %[[THIS4:.*]] = bitcast i8* %[[THIS3]] to %[[DynamicDerived:.*]]* +// CHECK-NEW: call void @_ZN14DynamicDerivedC1Ev(%[[DynamicDerived:.*]]* %[[THIS4]]) +// CHECK-NEW-LABEL: } +void Pointers1() { + DynamicBase1 *DB = new DynamicBase1; + DB->foo(); + + DynamicDerived *DD = new (DB) DynamicDerived; + DD->foo(); + DD->~DynamicDerived(); +} + +// CHECK-NEW-LABEL: define void @_Z14HackingObjectsv() +// CHECK-NEW: call void @_ZN12DynamicBase1C1Ev +// CHECK-NEW: call i8* @llvm.invariant.group.barrier( +// CHECK-NEW: call void @_ZN14DynamicDerivedC1Ev( +// CHECK-NEW: call i8* @llvm.invariant.group.barrier( +// CHECK-NEW: call void @_ZN12DynamicBase1C1Ev( +// CHECK-NEW-LABEL: } +void HackingObjects() { + DynamicBase1 DB; + DB.foo(); + + DynamicDerived *DB2 = new (&DB) DynamicDerived; + // Using DB now is prohibited. + DB2->foo(); + DB2->~DynamicDerived(); + + // We have to get back to the previous type to avoid calling wrong destructor + new (&DB) DynamicBase1; + DB.foo(); +} + +/*** Testing Constructors ***/ +struct DynamicBase1; +// CHECK-CTORS-LABEL: define linkonce_odr void @_ZN12DynamicBase1C2Ev( +// CHECK-CTORS-NOT: call i8* @llvm.invariant.group.barrier( +// CHECK-CTORS-LABEL: } + + +struct DynamicDerived; + +// CHECK-CTORS-LABEL: define linkonce_odr void @_ZN14DynamicDerivedC2Ev( +// CHECK-CTORS: %[[THIS0:.*]] = load %[[DynamicDerived:.*]]*, %[[DynamicDerived]]** {{.*}} +// CHECK-CTORS: %[[THIS1:.*]] = bitcast %[[DynamicDerived:.*]]* %[[THIS0]] to i8* +// CHECK-CTORS: %[[THIS2:.*]] = call i8* @llvm.invariant.group.barrier(i8* %[[THIS1:.*]]) +// CHECK-CTORS: %[[THIS3:.*]] = bitcast i8* %[[THIS2]] to %[[DynamicDerived]]* +// CHECK-CTORS: %[[THIS4:.*]] = bitcast %[[DynamicDerived]]* %[[THIS3]] to %[[DynamicBase:.*]]* +// CHECK-CTORS: call void @_ZN12DynamicBase1C2Ev(%[[DynamicBase]]* %[[THIS4]]) + +// CHECK-CTORS: %[[THIS5:.*]] = bitcast %struct.DynamicDerived* %[[THIS0]] to i32 (...)*** +// CHECK-CTORS: store {{.*}} %[[THIS5]] +// CHECK-CTORS-LABEL: } + +struct DynamicDerivedMultiple; +// CHECK-CTORS-LABEL: define linkonce_odr void @_ZN22DynamicDerivedMultipleC2Ev( + +// CHECK-CTORS: %[[THIS0:.*]] = load %[[CLASS:.*]]*, %[[CLASS]]** {{.*}} +// CHECK-CTORS: %[[THIS1:.*]] = bitcast %[[CLASS:.*]]* %[[THIS0]] to i8* +// CHECK-CTORS: %[[THIS2:.*]] = call i8* @llvm.invariant.group.barrier(i8* %[[THIS1]]) +// CHECK-CTORS: %[[THIS3:.*]] = bitcast i8* %[[THIS2]] to %[[CLASS]]* +// CHECK-CTORS: %[[THIS4:.*]] = bitcast %[[CLASS]]* %[[THIS3]] to %[[BASE_CLASS:.*]]* +// CHECK-CTORS: call void @_ZN12DynamicBase1C2Ev(%[[BASE_CLASS]]* %[[THIS4]]) + +// CHECK-CTORS: call i8* @llvm.invariant.group.barrier( + +// CHECK-CTORS: call void @_ZN12DynamicBase2C2Ev( +// CHECK-CTORS-NOT: @llvm.invariant.group.barrier + + +// CHECK-CTORS: %[[THIS10:.*]] = bitcast %struct.DynamicDerivedMultiple* %[[THIS0]] to i32 (...)*** +// CHECK-CTORS: store {{.*}} @_ZTV22DynamicDerivedMultiple, i64 0, i64 2) {{.*}} %[[THIS10]] +// CHECK-CTORS: %[[THIS11:.*]] = bitcast %struct.DynamicDerivedMultiple* %[[THIS0]] to i8* +// CHECK-CTORS: %[[THIS_ADD:.*]] = getelementptr inbounds i8, i8* %[[THIS11]], i64 16 +// CHECK-CTORS: %[[THIS12:.*]] = bitcast i8* %[[THIS_ADD]] to i32 (...)*** + + +// CHECK-CTORS: store {{.*}} @_ZTV22DynamicDerivedMultiple, i64 0, i64 6) {{.*}} %[[THIS12]] +// CHECK-CTORS-LABEL: } + +struct DynamicFromStatic; +// CHECK-CTORS-LABEL: define linkonce_odr void @_ZN17DynamicFromStaticC2Ev( +// CHECK-CTORS-NOT: @llvm.invariant.group.barrier( +// CHECK-CTORS-LABEL: } + + +/** DTORS **/ +// CHECK-DTORS-LABEL: define linkonce_odr void @_ZN10StaticBaseD2Ev( +// CHECK-DTORS-NOT: call i8* @llvm.invariant.group.barrier( +// CHECK-DTORS-LABEL: } + + +// CHECK-DTORS-LABEL: define linkonce_odr void @_ZN25DynamicFromVirtualStatic2D2Ev( +// CHECK-DTORS-NOT: invariant.barrier +// CHECK-DTORS-LABEL: } + +// CHECK-DTORS-LABEL: define linkonce_odr void @_ZN17DynamicFromStaticD2Ev +// CHECK-DTORS-NOT: call i8* @llvm.invariant.group.barrier( +// CHECK-DTORS-LABEL: } + + +// CHECK-DTORS-LABEL: define linkonce_odr void @_ZN22DynamicDerivedMultipleD2Ev( + +// CHECK-DTORS-LABEL: define linkonce_odr void @_ZN12DynamicBase2D2Ev( +// CHECK-DTORS: call i8* @llvm.invariant.group.barrier( +// CHECK-DTORS-LABEL: } + +// CHECK-DTORS-LABEL: define linkonce_odr void @_ZN12DynamicBase1D2Ev +// CHECK-DTORS: call i8* @llvm.invariant.group.barrier( +// CHECK-DTORS-LABEL: } + +// CHECK-DTORS-LABEL: define linkonce_odr void @_ZN14DynamicDerivedD2Ev +// CHECK-DTORS-NOT: call i8* @llvm.invariant.group.barrier( +// CHECK-DTORS-LABEL: } + + +// CHECK-LINK-REQ: !llvm.module.flags = !{![[FIRST:.*]], ![[SEC:.*]]{{.*}}} + +// CHECK-LINK-REQ: ![[FIRST]] = !{i32 1, !"StrictVTablePointers", i32 1} +// CHECK-LINK-REQ: ![[SEC]] = !{i32 3, !"StrictVTablePointersRequirement", ![[META:.*]]} +// CHECK-LINK-REQ: ![[META]] = !{!"StrictVTablePointers", i32 1} + diff --git a/test/CodeGenCXX/thunks.cpp b/test/CodeGenCXX/thunks.cpp index 38afb9d0dbf7..3a598b90afe1 100644 --- a/test/CodeGenCXX/thunks.cpp +++ b/test/CodeGenCXX/thunks.cpp @@ -1,5 +1,9 @@ -// RUN: %clang_cc1 %s -triple=x86_64-pc-linux-gnu -munwind-tables -emit-llvm -o - | FileCheck %s -// RUN: %clang_cc1 %s -triple=x86_64-pc-linux-gnu -munwind-tables -emit-llvm -o - -O1 -disable-llvm-optzns | FileCheck %s +// RUN: %clang_cc1 %s -triple=x86_64-pc-linux-gnu -munwind-tables -emit-llvm -o %t +// RUN: %clang_cc1 %s -triple=x86_64-pc-linux-gnu -munwind-tables -emit-llvm -o %t.opt -O1 -disable-llvm-optzns +// RUN: FileCheck %s < %t +// RUN: FileCheck %s < %t.opt +// RUN: FileCheck --check-prefix=CHECK-NONOPT %s < %t +// RUN: FileCheck --check-prefix=CHECK-OPT %s < %t.opt namespace Test1 { @@ -380,13 +384,25 @@ D::~D() {} /**** The following has to go at the end of the file ****/ +// checking without opt +// CHECK-NONOPT-LABEL: define internal void @_ZThn8_N6Test4B12_GLOBAL__N_11C1fEv( +// CHECK-NONOPT-NOT: comdat + +// This is from Test5: +// CHECK-NONOPT-LABEL: define linkonce_odr void @_ZTv0_n24_N5Test51B1fEv + +// This is from Test10: +// CHECK-NONOPT-LABEL: define linkonce_odr void @_ZN6Test101C3fooEv +// CHECK-NONOPT-LABEL: define linkonce_odr void @_ZThn8_N6Test101C3fooEv + +// Checking with opt +// CHECK-OPT-LABEL: define internal void @_ZThn8_N6Test4B12_GLOBAL__N_11C1fEv(%"struct.Test4B::(anonymous namespace)::C"* %this) unnamed_addr #0 align 2 + // This is from Test5: -// CHECK-LABEL: define internal void @_ZThn8_N6Test4B12_GLOBAL__N_11C1fEv( -// CHECK-NOT: comdat -// CHECK-LABEL: define linkonce_odr void @_ZTv0_n24_N5Test51B1fEv +// CHECK-OPT-LABEL: define linkonce_odr void @_ZTv0_n24_N5Test51B1fEv // This is from Test10: -// CHECK-LABEL: define linkonce_odr void @_ZN6Test101C3fooEv -// CHECK-LABEL: define linkonce_odr void @_ZThn8_N6Test101C3fooEv +// CHECK-OPT-LABEL: define linkonce_odr void @_ZN6Test101C3fooEv +// CHECK-OPT-LABEL: define linkonce_odr void @_ZThn8_N6Test101C3fooEv // CHECK: attributes [[NUW]] = { nounwind uwtable{{.*}} } diff --git a/test/CodeGenCXX/tls-init-funcs.cpp b/test/CodeGenCXX/tls-init-funcs.cpp index d47329cdc29f..a2a563b84f22 100644 --- a/test/CodeGenCXX/tls-init-funcs.cpp +++ b/test/CodeGenCXX/tls-init-funcs.cpp @@ -1,13 +1,13 @@ // RUN: %clang_cc1 -triple x86_64-apple-macosx10.8 -std=c++1y -S -emit-llvm %s -o - | FileCheck %s // CHECK: @a = internal thread_local global -// CHECK: @_Z2vtIiE = internal thread_local global i32 5 +// CHECK: @_Z2vtIiE = linkonce_odr thread_local global i32 5 // CHECK: @_ZZ3inlvE3loc = linkonce_odr thread_local global i32 0 // CHECK: @_tlv_atexit({{.*}}@_ZN1AD1Ev -// CHECK: call i32* @_ZTW3ext() -// CHECK: declare i32* @_ZTW3ext() -// CHECK: define weak i32* @_ZTW2vtIiE() -// CHECK: define weak i32* @_ZTW2vtIvE() +// CHECK: call cxx_fast_tlscc i32* @_ZTW3ext() +// CHECK: declare cxx_fast_tlscc i32* @_ZTW3ext() +// CHECK: define weak_odr hidden cxx_fast_tlscc i32* @_ZTW2vtIiE() +// CHECK: define weak_odr hidden cxx_fast_tlscc i32* @_ZTW2vtIvE() // CHECK: define {{.*}} @_ZTW1a struct A { diff --git a/test/CodeGenCXX/typeid-cxx11.cpp b/test/CodeGenCXX/typeid-cxx11.cpp index 4e32d2dcb5a5..5c10ca5b21a5 100644 --- a/test/CodeGenCXX/typeid-cxx11.cpp +++ b/test/CodeGenCXX/typeid-cxx11.cpp @@ -18,8 +18,8 @@ struct A { virtual ~A(); }; struct B : virtual A {}; struct C { int n; }; -// CHECK: @_ZN5Test1L5itemsE = internal constant [4 x {{.*}}] [{{.*}} @_ZTIN5Test11AE {{.*}}, {{.*}}, {{.*}} @_ZN5Test19make_implINS_1AEEEPvv }, {{.*}} @_ZTIN5Test11BE {{.*}} @_ZN5Test19make_implINS_1BEEEPvv {{.*}} @_ZTIN5Test11CE {{.*}} @_ZN5Test19make_implINS_1CEEEPvv {{.*}} @_ZTIi {{.*}} @_ZN5Test19make_implIiEEPvv }] -constexpr Item items[] = { +// CHECK: @_ZN5Test15itemsE = constant [4 x {{.*}}] [{{.*}} @_ZTIN5Test11AE {{.*}}, {{.*}}, {{.*}} @_ZN5Test19make_implINS_1AEEEPvv }, {{.*}} @_ZTIN5Test11BE {{.*}} @_ZN5Test19make_implINS_1BEEEPvv {{.*}} @_ZTIN5Test11CE {{.*}} @_ZN5Test19make_implINS_1CEEEPvv {{.*}} @_ZTIi {{.*}} @_ZN5Test19make_implIiEEPvv }] +extern constexpr Item items[] = { item("A"), item("B"), item("C"), item("int") }; diff --git a/test/CodeGenCXX/uncopyable-args.cpp b/test/CodeGenCXX/uncopyable-args.cpp index 814cb6215d15..c1d284a74185 100644 --- a/test/CodeGenCXX/uncopyable-args.cpp +++ b/test/CodeGenCXX/uncopyable-args.cpp @@ -76,7 +76,7 @@ void bar() { // FIXME: The copy ctor is deleted. // CHECK-DISABLED-LABEL: define void @_ZN11all_deleted3barEv() // CHECK-DISABLED: call void @_Z{{.*}}C1Ev( -// CHECK-DISABLED-NOT call +// CHECK-DISABLED-NOT: call // CHECK-DISABLED: call void @_ZN11all_deleted3fooENS_1AE(%"struct.all_deleted::A"* %{{.*}}) // CHECK-DISABLED-LABEL: declare void @_ZN11all_deleted3fooENS_1AE(%"struct.all_deleted::A"*) @@ -96,7 +96,7 @@ void bar() { // FIXME: The copy and move ctors are implicitly deleted. // CHECK-DISABLED-LABEL: define void @_ZN18implicitly_deleted3barEv() // CHECK-DISABLED: call void @_Z{{.*}}C1Ev( -// CHECK-DISABLED-NOT call +// CHECK-DISABLED-NOT: call // CHECK-DISABLED: call void @_ZN18implicitly_deleted3fooENS_1AE(%"struct.implicitly_deleted::A"* %{{.*}}) // CHECK-DISABLED-LABEL: declare void @_ZN18implicitly_deleted3fooENS_1AE(%"struct.implicitly_deleted::A"*) @@ -116,7 +116,7 @@ void bar() { // FIXME: The copy constructor is implicitly deleted. // CHECK-DISABLED-LABEL: define void @_ZN11one_deleted3barEv() // CHECK-DISABLED: call void @_Z{{.*}}C1Ev( -// CHECK-DISABLED-NOT call +// CHECK-DISABLED-NOT: call // CHECK-DISABLED: call void @_ZN11one_deleted3fooENS_1AE(%"struct.one_deleted::A"* %{{.*}}) // CHECK-DISABLED-LABEL: declare void @_ZN11one_deleted3fooENS_1AE(%"struct.one_deleted::A"*) diff --git a/test/CodeGenCXX/vararg-non-pod-ms-compat.cpp b/test/CodeGenCXX/vararg-non-pod-ms-compat.cpp index 530a4284b4ec..64b1c525a614 100644 --- a/test/CodeGenCXX/vararg-non-pod-ms-compat.cpp +++ b/test/CodeGenCXX/vararg-non-pod-ms-compat.cpp @@ -18,7 +18,7 @@ void test(X x) { // X64: alloca %struct.X // X64: %[[agg:[^ ]*]] = alloca %struct.X - // X64: %[[valptr:[^ ]*]] = getelementptr %struct.X, %struct.X* %[[agg]], i32 0, i32 0 + // X64: %[[valptr:[^ ]*]] = getelementptr inbounds %struct.X, %struct.X* %[[agg]], i32 0, i32 0 // X64: %[[val:[^ ]*]] = load i32, i32* %[[valptr]] // X64: call void (...) @"\01?vararg@@YAXZZ"(i32 %[[val]]) diff --git a/test/CodeGenCXX/virtual-base-ctor.cpp b/test/CodeGenCXX/virtual-base-ctor.cpp index 8c28965c5c2f..20a88cd37105 100644 --- a/test/CodeGenCXX/virtual-base-ctor.cpp +++ b/test/CodeGenCXX/virtual-base-ctor.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -emit-llvm -triple %itanium_abi_triple -o - -O2 | FileCheck %s +// RUN: %clang_cc1 %s -emit-llvm -triple %itanium_abi_triple -o - -O2 | opt - -S -globalopt -o - | FileCheck %s struct B; extern B x; diff --git a/test/CodeGenCXX/virtual-destructor-calls.cpp b/test/CodeGenCXX/virtual-destructor-calls.cpp index f0e3dc58b641..e13adfcc85cf 100644 --- a/test/CodeGenCXX/virtual-destructor-calls.cpp +++ b/test/CodeGenCXX/virtual-destructor-calls.cpp @@ -17,7 +17,7 @@ struct B : A { // CHECK: @_ZN1BD1Ev = alias {{.*}} @_ZN1BD2Ev // (aliases from C) -// CHECK: @_ZN1CD2Ev = alias bitcast {{.*}} @_ZN1BD2Ev +// CHECK: @_ZN1CD2Ev = alias {{.*}}, bitcast {{.*}} @_ZN1BD2Ev // CHECK: @_ZN1CD1Ev = alias {{.*}} @_ZN1CD2Ev // Base dtor: actually calls A's base dtor. diff --git a/test/CodeGenCXX/visibility.cpp b/test/CodeGenCXX/visibility.cpp index 7239cbe00225..aff6554282ca 100644 --- a/test/CodeGenCXX/visibility.cpp +++ b/test/CodeGenCXX/visibility.cpp @@ -1,5 +1,8 @@ // 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 -fvisibility hidden -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-HIDDEN +// For clang, "internal" is just an alias for "hidden". We could use it for some +// optimization purposes on 32-bit x86, but it's not worth it. +// RUN: %clang_cc1 %s -std=c++11 -triple=x86_64-apple-darwin10 -fvisibility internal -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-HIDDEN #define HIDDEN __attribute__((visibility("hidden"))) #define PROTECTED __attribute__((visibility("protected"))) diff --git a/test/CodeGenCXX/vtable-assume-load.cpp b/test/CodeGenCXX/vtable-assume-load.cpp new file mode 100644 index 000000000000..30cfc00ec7ba --- /dev/null +++ b/test/CodeGenCXX/vtable-assume-load.cpp @@ -0,0 +1,313 @@ +// RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -emit-llvm -o %t.ll -O1 -disable-llvm-optzns -fms-extensions -fstrict-vtable-pointers +// RUN: %clang_cc1 %s -triple i686-pc-win32 -emit-llvm -o %t.ms.ll -O1 -disable-llvm-optzns -fms-extensions -fstrict-vtable-pointers +// FIXME: Assume load should not require -fstrict-vtable-pointers + +// RUN: FileCheck --check-prefix=CHECK1 --input-file=%t.ll %s +// RUN: FileCheck --check-prefix=CHECK2 --input-file=%t.ll %s +// RUN: FileCheck --check-prefix=CHECK3 --input-file=%t.ll %s +// RUN: FileCheck --check-prefix=CHECK4 --input-file=%t.ll %s +// RUN: FileCheck --check-prefix=CHECK-MS --input-file=%t.ms.ll %s +// RUN: FileCheck --check-prefix=CHECK6 --input-file=%t.ll %s +// RUN: FileCheck --check-prefix=CHECK7 --input-file=%t.ll %s +// RUN: FileCheck --check-prefix=CHECK8 --input-file=%t.ll %s +// RUN: FileCheck --check-prefix=CHECK9 --input-file=%t.ll %s +namespace test1 { + +struct A { + A(); + virtual void foo(); +}; + +struct B : A { + virtual void foo(); +}; + +void g(A *a) { a->foo(); } + +// CHECK1-LABEL: define void @_ZN5test14fooAEv() +// CHECK1: call void @_ZN5test11AC1Ev(%"struct.test1::A"* +// CHECK1: %[[VTABLE:.*]] = load i8**, i8*** %{{.*}} +// CHECK1: %[[CMP:.*]] = icmp eq i8** %[[VTABLE]], getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5test11AE, i64 0, i64 2) +// CHECK1: call void @llvm.assume(i1 %[[CMP]]) +// CHECK1-LABEL: } + +void fooA() { + A a; + g(&a); +} + +// CHECK1-LABEL: define void @_ZN5test14fooBEv() +// CHECK1: call void @_ZN5test11BC1Ev(%"struct.test1::B"* %{{.*}}) +// CHECK1: %[[VTABLE:.*]] = load i8**, i8*** %{{.*}} +// CHECK1: %[[CMP:.*]] = icmp eq i8** %[[VTABLE]], getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5test11BE, i64 0, i64 2) +// CHECK1: call void @llvm.assume(i1 %[[CMP]]) +// CHECK1-LABEL: } + +void fooB() { + B b; + g(&b); +} +// there should not be any assumes in the ctor that calls base ctor +// CHECK1-LABEL: define linkonce_odr void @_ZN5test11BC2Ev(%"struct.test1::B"* +// CHECK1-NOT: @llvm.assume( +// CHECK1-LABEL: } +} +namespace test2 { +struct A { + A(); + virtual void foo(); +}; + +struct B { + B(); + virtual void bar(); +}; + +struct C : A, B { + C(); + virtual void foo(); +}; +void g(A *a) { a->foo(); } +void h(B *b) { b->bar(); } + +// CHECK2-LABEL: define void @_ZN5test24testEv() +// CHECK2: call void @_ZN5test21CC1Ev(%"struct.test2::C"* +// CHECK2: %[[VTABLE:.*]] = load i8**, i8*** {{.*}} +// CHECK2: %[[CMP:.*]] = icmp eq i8** %[[VTABLE]], getelementptr inbounds ([6 x i8*], [6 x i8*]* @_ZTVN5test21CE, i64 0, i64 2) +// CHECK2: call void @llvm.assume(i1 %[[CMP]]) + +// CHECK2: %[[V2:.*]] = bitcast %"struct.test2::C"* %{{.*}} to i8* +// CHECK2: %[[ADD_PTR:.*]] = getelementptr inbounds i8, i8* %[[V2]], i64 8 +// CHECK2: %[[V3:.*]] = bitcast i8* %[[ADD_PTR]] to i8*** +// CHECK2: %[[VTABLE2:.*]] = load i8**, i8*** %[[V3]] +// CHECK2: %[[CMP2:.*]] = icmp eq i8** %[[VTABLE2]], getelementptr inbounds ([6 x i8*], [6 x i8*]* @_ZTVN5test21CE, i64 0, i64 5) +// CHECK2: call void @llvm.assume(i1 %[[CMP2]]) + +// CHECK2: call void @_ZN5test21gEPNS_1AE( +// CHECK2-LABEL: } + +void test() { + C c; + g(&c); + h(&c); +} +} + +namespace test3 { +struct A { + A(); +}; + +struct B : A { + B(); + virtual void foo(); +}; + +struct C : virtual A, B { + C(); + virtual void foo(); +}; +void g(B *a) { a->foo(); } + +// CHECK3-LABEL: define void @_ZN5test34testEv() +// CHECK3: call void @_ZN5test31CC1Ev(%"struct.test3::C"* +// CHECK3: %[[CMP:.*]] = icmp eq i8** %{{.*}}, getelementptr inbounds ([4 x i8*], [4 x i8*]* @_ZTVN5test31CE, i64 0, i64 3) +// CHECK3: call void @llvm.assume(i1 %[[CMP]]) +// CHECK3-LABLEL: } +void test() { + C c; + g(&c); +} +} // test3 + +namespace test4 { +struct A { + A(); + virtual void foo(); +}; + +struct B : virtual A { + B(); + virtual void foo(); +}; +struct C : B { + C(); + virtual void foo(); +}; + +void g(C *c) { c->foo(); } + +// CHECK4-LABEL: define void @_ZN5test44testEv() +// CHECK4: call void @_ZN5test41CC1Ev(%"struct.test4::C"* +// CHECK4: %[[VTABLE:.*]] = load i8**, i8*** %{{.*}} +// CHECK4: %[[CMP:.*]] = icmp eq i8** %[[VTABLE]], getelementptr inbounds ([5 x i8*], [5 x i8*]* @_ZTVN5test41CE, i64 0, i64 4) +// CHECK4: call void @llvm.assume(i1 %[[CMP]] + +// CHECK4: %[[VTABLE2:.*]] = load i8**, i8*** %{{.*}} +// CHECK4: %[[CMP2:.*]] = icmp eq i8** %[[VTABLE2]], getelementptr inbounds ([5 x i8*], [5 x i8*]* @_ZTVN5test41CE, i64 0, i64 4) +// CHECK4: call void @llvm.assume(i1 %[[CMP2]]) +// CHECK4-LABEL: } + +void test() { + C c; + g(&c); +} +} // test4 + +namespace testMS { + +struct __declspec(novtable) S { + virtual void foo(); +}; + +void g(S &s) { s.foo(); } + +// if struct has novtable specifier, then we can't generate assumes +// CHECK-MS-LABEL: define void @"\01?test@testMS@@YAXXZ"() +// CHECK-MS: call x86_thiscallcc %"struct.testMS::S"* @"\01??0S@testMS@@QAE@XZ"( +// CHECK-MS-NOT: @llvm.assume +// CHECK-MS-LABEL: } + +void test() { + S s; + g(s); +} + +} // testMS + +namespace test6 { +struct A { + A(); + virtual void foo(); + virtual ~A() {} +}; +struct B : A { + B(); +}; +// FIXME: Because A's vtable is external, and no virtual functions are hidden, +// it's safe to generate assumption loads. +// CHECK6-LABEL: define void @_ZN5test61gEv() +// CHECK6: call void @_ZN5test61AC1Ev( +// CHECK6-NOT: call void @llvm.assume( + +// We can't emit assumption loads for B, because if we would refer to vtable +// it would refer to functions that will not be able to find (like implicit +// inline destructor). + +// CHECK6-LABEL: call void @_ZN5test61BC1Ev( +// CHECK6-NOT: call void @llvm.assume( +// CHECK6-LABEL: } +void g() { + A *a = new A; + B *b = new B; +} +} + +namespace test7 { +// Because A's key function is defined here, vtable is generated in this TU +// CHECK7: @_ZTVN5test71AE = unnamed_addr constant +struct A { + A(); + virtual void foo(); + virtual void bar(); +}; +void A::foo() {} + +// CHECK7-LABEL: define void @_ZN5test71gEv() +// CHECK7: call void @_ZN5test71AC1Ev( +// CHECK7: call void @llvm.assume( +// CHECK7-LABEL: } +void g() { + A *a = new A(); + a->bar(); +} +} + +namespace test8 { + +struct A { + virtual void foo(); + virtual void bar(); +}; + +// CHECK8-DAG: @_ZTVN5test81BE = available_externally unnamed_addr constant +struct B : A { + B(); + void foo(); + void bar(); +}; + +// CHECK8-DAG: @_ZTVN5test81CE = linkonce_odr unnamed_addr constant +struct C : A { + C(); + void bar(); + void foo() {} +}; +inline void C::bar() {} + +struct D : A { + D(); + void foo(); + void inline bar(); +}; +void D::bar() {} + +// CHECK8-DAG: @_ZTVN5test81EE = linkonce_odr unnamed_addr constant +struct E : A { + E(); +}; + +// CHECK8-LABEL: define void @_ZN5test81bEv() +// CHECK8: call void @llvm.assume( +// CHECK8-LABEL: } +void b() { + B b; + b.bar(); +} + +// FIXME: C has inline virtual functions which prohibits as from generating +// assumption loads, but because vtable is generated in this TU (key function +// defined here) it would be correct to refer to it. +// CHECK8-LABEL: define void @_ZN5test81cEv() +// CHECK8-NOT: call void @llvm.assume( +// CHECK8-LABEL: } +void c() { + C c; + c.bar(); +} + +// FIXME: We could generate assumption loads here. +// CHECK8-LABEL: define void @_ZN5test81dEv() +// CHECK8-NOT: call void @llvm.assume( +// CHECK8-LABEL: } +void d() { + D d; + d.bar(); +} + +// CHECK8-LABEL: define void @_ZN5test81eEv() +// CHECK8: call void @llvm.assume( +// CHECK8-LABEL: } +void e() { + E e; + e.bar(); +} +} + +namespace test9 { + +struct S { + S(); + __attribute__((visibility("hidden"))) virtual void doStuff(); +}; + +// CHECK9-LABEL: define void @_ZN5test94testEv() +// CHECK9-NOT: @llvm.assume( +// CHECK9: } +void test() { + S *s = new S(); + s->doStuff(); + delete s; +} +} + diff --git a/test/CodeGenCXX/vtable-available-externally.cpp b/test/CodeGenCXX/vtable-available-externally.cpp index e07d48463f4f..f38d177666e6 100644 --- a/test/CodeGenCXX/vtable-available-externally.cpp +++ b/test/CodeGenCXX/vtable-available-externally.cpp @@ -1,7 +1,17 @@ -// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -emit-llvm -o %t +// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -emit-llvm -o %t +// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -O2 -disable-llvm-optzns -emit-llvm -o %t.opt // RUN: FileCheck --check-prefix=CHECK-TEST1 %s < %t // RUN: FileCheck --check-prefix=CHECK-TEST2 %s < %t // RUN: FileCheck --check-prefix=CHECK-TEST5 %s < %t +// RUN: FileCheck --check-prefix=CHECK-TEST8 %s < %t.opt +// RUN: FileCheck --check-prefix=CHECK-TEST9 %s < %t.opt +// RUN: FileCheck --check-prefix=CHECK-TEST10 %s < %t.opt +// RUN: FileCheck --check-prefix=CHECK-TEST11 %s < %t.opt +// RUN: FileCheck --check-prefix=CHECK-TEST12 %s < %t.opt +// RUN: FileCheck --check-prefix=CHECK-TEST13 %s < %t.opt +// RUN: FileCheck --check-prefix=CHECK-TEST14 %s < %t.opt +// RUN: FileCheck --check-prefix=CHECK-TEST15 %s < %t.opt +// RUN: FileCheck --check-prefix=CHECK-TEST16 %s < %t.opt #include @@ -152,3 +162,232 @@ struct c28 : virtual c11{ void f6 (); }; } + +namespace Test8 { +// CHECK-TEST8: @_ZTVN5Test81YE = available_externally unnamed_addr constant +// vtable for X is not generated because there are no stores here +struct X { + X(); + virtual void foo(); +}; +struct Y : X { + void foo(); +}; + +void g(X* p) { p->foo(); } +void f() { + Y y; + g(&y); + X x; + g(&x); +} + +} // Test8 + +namespace Test9 { +// All virtual functions are outline, so we can assume that it will +// be generated in translation unit where foo is defined. +// CHECK-TEST9-DAG: @_ZTVN5Test91AE = available_externally unnamed_addr constant +// CHECK-TEST9-DAG: @_ZTVN5Test91BE = available_externally unnamed_addr constant +struct A { + virtual void foo(); + virtual void bar(); +}; +void A::bar() {} + +struct B : A { + void foo(); +}; + +void g() { + A a; + a.foo(); + B b; + b.foo(); +} + +} // Test9 + +namespace Test10 { + +// because A's key function is defined here, vtable is generated in this TU +// CHECK-TEST10-DAG: @_ZTVN6Test101AE = unnamed_addr constant +struct A { + virtual void foo(); + virtual void bar(); +}; +void A::foo() {} + +// Because key function is inline we will generate vtable as linkonce_odr. +// CHECK-TEST10-DAG: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant +struct D : A { + void bar(); +}; +inline void D::bar() {} + +// Because B has outline all virtual functions, we can refer to them. +// CHECK-TEST10-DAG: @_ZTVN6Test101BE = available_externally unnamed_addr constant +struct B : A { + void foo(); + void bar(); +}; + +// C's key function (car) is outline, but C has inline virtual function so we +// can't guarantee that we will be able to refer to bar from name +// so (at the moment) we can't emit vtable available_externally. +// CHECK-TEST10-DAG: @_ZTVN6Test101CE = external unnamed_addr constant +struct C : A { + void bar() {} // defined in body - not key function + virtual inline void gar(); // inline in body - not key function + virtual void car(); +}; + +// no key function, vtable will be generated everywhere it will be used +// CHECK-TEST10-DAG: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant +struct E : A {}; + +void g(A& a) { + a.foo(); + a.bar(); +} + +void f() { + A a; + g(a); + B b; + g(b); + C c; + g(c); + D d; + g(d); + E e; + g(e); +} + +} // Test10 + +namespace Test11 { +struct D; +// Can emit C's vtable available_externally. +// CHECK-TEST11: @_ZTVN6Test111CE = available_externally unnamed_addr constant +struct C { + virtual D& operator=(const D&); +}; + +// Cannot emit B's vtable available_externally, because we cannot create +// a reference to the inline virtual B::operator= function. +// CHECK-TEST11: @_ZTVN6Test111DE = external unnamed_addr constant +struct D : C { + virtual void key(); +}; +D f(); + +void g(D& a) { + C c; + c = a; + a.key(); + a.key(); +} +void g() { + D d; + d = f(); + g(d); +} +} // Test 11 + +namespace Test12 { + +// CHECK-TEST12: @_ZTVN6Test121AE = external unnamed_addr constant +struct A { + virtual void foo(); + virtual ~A() {} +}; +// CHECK-TEST12: @_ZTVN6Test121BE = external unnamed_addr constant +struct B : A { + void foo(); +}; + +void g() { + A a; + a.foo(); + B b; + b.foo(); +} +} + +namespace Test13 { + +// CHECK-TEST13-DAG: @_ZTVN6Test131AE = available_externally unnamed_addr constant +// CHECK-TEST13-DAG: @_ZTVN6Test131BE = external unnamed_addr constant +struct A { + virtual ~A(); +}; +struct B : A { + virtual void f(); + void operator delete(void *); + ~B() {} +}; + +void g() { + A *b = new B; +} +} + +namespace Test14 { + +// CHECK-TEST14: @_ZTVN6Test141AE = available_externally unnamed_addr constant +struct A { + virtual void f(); + void operator delete(void *); + ~A(); +}; + +void g() { + A *b = new A; + delete b; +} +} + +namespace Test15 { +// In this test D's vtable has two slots for function f(), but uses only one, +// so the second slot is set to null. +// CHECK-TEST15: @_ZTVN6Test151DE = available_externally unnamed_addr constant +struct A { virtual void f() {} }; +struct B : virtual A {}; +struct C : virtual A {}; +struct D : B, C { + virtual void g(); + void f(); +}; + +void test() { + D * d = new D; + d->f(); +} +} + +namespace Test16 { +// S has virtual method that is hidden, because of it we can't +// generate available_externally vtable for it. +// CHECK-TEST16-DAG: @_ZTVN6Test161SE = external unnamed_addr constant +// CHECK-TEST16-DAG: @_ZTVN6Test162S2E = available_externally + +struct S { + __attribute__((visibility("hidden"))) virtual void doStuff(); +}; + +struct S2 { + virtual void doStuff(); + __attribute__((visibility("hidden"))) void unused(); + +}; + +void test() { + S *s = new S; + s->doStuff(); + + S2 *s2 = new S2; + s2->doStuff(); +} +} + diff --git a/test/CodeGenCXX/vtable-holder-self-reference.cpp b/test/CodeGenCXX/vtable-holder-self-reference.cpp index 8f5314e7211c..727de7a5f759 100644 --- a/test/CodeGenCXX/vtable-holder-self-reference.cpp +++ b/test/CodeGenCXX/vtable-holder-self-reference.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -gdwarf-2 -x c++ -o - %s | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -dwarf-version=2 -debug-info-kind=limited -x c++ -o - %s | FileCheck %s // // PR21941: crasher for self-referencing DW_TAG_structure_type node. If we get // rid of self-referenceing structure_types (PR21902), then it should be safe diff --git a/test/CodeGenCXX/vtable-key-function-ios.cpp b/test/CodeGenCXX/vtable-key-function-ios.cpp index bf2e1f9720b5..d17aa695d2b5 100644 --- a/test/CodeGenCXX/vtable-key-function-ios.cpp +++ b/test/CodeGenCXX/vtable-key-function-ios.cpp @@ -1,6 +1,9 @@ // RUN: %clang_cc1 %s -triple=armv7-apple-darwin -emit-llvm -o - | FileCheck %s // RUN: %clang_cc1 %s -triple=armv7-apple-darwin -emit-llvm -o - | FileCheck -check-prefix=CHECK-LATE %s +// RUN: %clang_cc1 %s -triple=x86_64-pc-windows-gnu -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple=x86_64-pc-windows-gnu -emit-llvm -o - | FileCheck -check-prefix=CHECK-LATE %s + // The 'a' variants ask for the v-table first. // The 'b' variants ask for the v-table second. // The 'c' variants ask for the v-table third. diff --git a/test/CodeGenCXX/vtable-key-function-win-comdat.cpp b/test/CodeGenCXX/vtable-key-function-win-comdat.cpp new file mode 100644 index 000000000000..3dd1be7dc69c --- /dev/null +++ b/test/CodeGenCXX/vtable-key-function-win-comdat.cpp @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 %s -triple=x86_64-pc-windows-gnu -emit-llvm -o - | FileCheck %s + +namespace std { class type_info; } +extern void use(const std::type_info &rtti); + +struct Test1a { + Test1a(); + virtual void foo(); + virtual void bar(); +}; + +// V-table needs to be defined weakly. +Test1a::Test1a() { use(typeid(Test1a)); } +// This defines the key function. +inline void Test1a::foo() {} + +// CHECK: $_ZTV6Test1a = comdat any +// CHECK: $_ZTS6Test1a = comdat any +// CHECK: $_ZTI6Test1a = comdat any +// CHECK-NOT: $_ZTS6Test1a.1 = comdat any +// CHECK-NOT: $_ZTI6Test1a.1 = comdat any + +// CHECK: @_ZTV6Test1a = linkonce_odr unnamed_addr constant {{.*}} ({ i8*, i8* }* @_ZTI6Test1a to i8*) +// CHECK: @_ZTS6Test1a = linkonce_odr constant +// CHECK: @_ZTI6Test1a = linkonce_odr constant {{.*}} [8 x i8]* @_ZTS6Test1a diff --git a/test/CodeGenCXX/vtable-linkage.cpp b/test/CodeGenCXX/vtable-linkage.cpp index 5cbd3897a1ff..ff398ffa61dd 100644 --- a/test/CodeGenCXX/vtable-linkage.cpp +++ b/test/CodeGenCXX/vtable-linkage.cpp @@ -139,10 +139,11 @@ void use_F() { // CHECK-OPT-DAG: @_ZTV1FIiE = external unnamed_addr constant // E is an explicit template instantiation declaration. It has a -// key function that is not instantiated, so we should only reference -// its vtable, not define it. +// key function is not instantiated, so we know that vtable definition +// will be generated in TU where key function will be defined +// so we can mark it as available_externally (only with optimizations) // CHECK-DAG: @_ZTV1EIiE = external unnamed_addr constant -// CHECK-OPT-DAG: @_ZTV1EIiE = external unnamed_addr constant +// CHECK-OPT-DAG: @_ZTV1EIiE = available_externally unnamed_addr constant // The anonymous struct for e has no linkage, so the vtable should have // internal linkage. @@ -196,8 +197,8 @@ void use_H() { // CHECK-DAG: @_ZTT1IIiE = external unnamed_addr constant // CHECK-NOT: @_ZTC1IIiE // -// CHECK-OPT-DAG: @_ZTV1IIiE = external unnamed_addr constant -// CHECK-OPT-DAG: @_ZTT1IIiE = external unnamed_addr constant +// CHECK-OPT-DAG: @_ZTV1IIiE = available_externally unnamed_addr constant +// CHECK-OPT-DAG: @_ZTT1IIiE = available_externally unnamed_addr constant struct VBase1 { virtual void f(); }; struct VBase2 : virtual VBase1 {}; template struct I : VBase2 {}; diff --git a/test/CodeGenCXX/warn-padded-packed.cpp b/test/CodeGenCXX/warn-padded-packed.cpp index 4203bb3dda10..f2af60865e05 100644 --- a/test/CodeGenCXX/warn-padded-packed.cpp +++ b/test/CodeGenCXX/warn-padded-packed.cpp @@ -69,7 +69,7 @@ struct S12 { struct S13 { // expected-warning {{padding size of 'S13' with 6 bits to alignment boundary}} char c; - bool b : 10; // expected-warning {{size of bit-field 'b' (10 bits) exceeds the size of its type}} + bool b : 10; }; // The warnings are emitted when the layout of the structs is computed, so we have to use them. diff --git a/test/CodeGenCXX/wasm-args-returns.cpp b/test/CodeGenCXX/wasm-args-returns.cpp new file mode 100644 index 000000000000..2b80430014d0 --- /dev/null +++ b/test/CodeGenCXX/wasm-args-returns.cpp @@ -0,0 +1,100 @@ +// RUN: %clang_cc1 -O1 -triple wasm32-unknown-unknown -emit-llvm -o - %s \ +// RUN: | FileCheck %s +// RUN: %clang_cc1 -O1 -triple wasm64-unknown-unknown -emit-llvm -o - %s \ +// RUN: | FileCheck %s + +#define concat_(x, y) x ## y +#define concat(x, y) concat_(x, y) + +#define test(T) \ + T forward(T x) { return x; } \ + void use(T x); \ + T concat(def_, T)(void); \ + void concat(test_, T)(void) { use(concat(def_, T)()); } + +struct one_field { double d; }; +test(one_field); +// CHECK: define double @_Z7forward9one_field(double %{{.*}}) +// +// CHECK: define void @_Z14test_one_fieldv() +// CHECK: %[[call:.*]] = tail call double @_Z13def_one_fieldv() +// CHECK: tail call void @_Z3use9one_field(double %[[call]]) +// CHECK: ret void +// +// CHECK: declare void @_Z3use9one_field(double) +// CHECK: declare double @_Z13def_one_fieldv() + +struct two_fields { double d, e; }; +test(two_fields); +// CHECK: define void @_Z7forward10two_fields(%struct.two_fields* noalias nocapture sret %{{.*}}, %struct.two_fields* byval nocapture readonly align 8 %{{.*}}) +// +// CHECK: define void @_Z15test_two_fieldsv() +// CHECK: %[[tmp:.*]] = alloca %struct.two_fields, align 8 +// CHECK: call void @_Z14def_two_fieldsv(%struct.two_fields* nonnull sret %[[tmp]]) +// CHECK: call void @_Z3use10two_fields(%struct.two_fields* byval nonnull align 8 %[[tmp]]) +// CHECK: ret void +// +// CHECK: declare void @_Z3use10two_fields(%struct.two_fields* byval align 8) +// CHECK: declare void @_Z14def_two_fieldsv(%struct.two_fields* sret) + +struct copy_ctor { + double d; + copy_ctor(copy_ctor const&); +}; +test(copy_ctor); +// CHECK: define void @_Z7forward9copy_ctor(%struct.copy_ctor* noalias sret %{{.*}}, %struct.copy_ctor* %{{.*}}) +// +// CHECK: declare %struct.copy_ctor* @_ZN9copy_ctorC1ERKS_(%struct.copy_ctor* returned, %struct.copy_ctor* dereferenceable(8)) +// +// CHECK: define void @_Z14test_copy_ctorv() +// CHECK: %[[tmp:.*]] = alloca %struct.copy_ctor, align 8 +// CHECK: call void @_Z13def_copy_ctorv(%struct.copy_ctor* nonnull sret %[[tmp]]) +// CHECK: call void @_Z3use9copy_ctor(%struct.copy_ctor* nonnull %[[tmp]]) +// CHECK: ret void +// +// CHECK: declare void @_Z3use9copy_ctor(%struct.copy_ctor*) +// CHECK: declare void @_Z13def_copy_ctorv(%struct.copy_ctor* sret) + +struct __attribute__((aligned(16))) aligned_copy_ctor { + double d, e; + aligned_copy_ctor(aligned_copy_ctor const&); +}; +test(aligned_copy_ctor); +// CHECK: define void @_Z7forward17aligned_copy_ctor(%struct.aligned_copy_ctor* noalias sret %{{.*}}, %struct.aligned_copy_ctor* %{{.*}}) +// +// CHECK: declare %struct.aligned_copy_ctor* @_ZN17aligned_copy_ctorC1ERKS_(%struct.aligned_copy_ctor* returned, %struct.aligned_copy_ctor* dereferenceable(16)) +// +// CHECK: define void @_Z22test_aligned_copy_ctorv() +// CHECK: %[[tmp:.*]] = alloca %struct.aligned_copy_ctor, align 16 +// CHECK: call void @_Z21def_aligned_copy_ctorv(%struct.aligned_copy_ctor* nonnull sret %[[tmp]]) +// CHECK: call void @_Z3use17aligned_copy_ctor(%struct.aligned_copy_ctor* nonnull %[[tmp]]) +// CHECK: ret void +// +// CHECK: declare void @_Z3use17aligned_copy_ctor(%struct.aligned_copy_ctor*) +// CHECK: declare void @_Z21def_aligned_copy_ctorv(%struct.aligned_copy_ctor* sret) + +struct empty {}; +test(empty); +// CHECK: define void @_Z7forward5empty() +// +// CHECK: define void @_Z10test_emptyv() +// CHECK: tail call void @_Z9def_emptyv() +// CHECK: tail call void @_Z3use5empty() +// CHECK: ret void +// +// CHECK: declare void @_Z3use5empty() +// CHECK: declare void @_Z9def_emptyv() + +struct one_bitfield { + int d:3; +}; +test(one_bitfield); +// CHECK: define i32 @_Z7forward12one_bitfield(i32 %{{.*}}) +// +// CHECK: define void @_Z17test_one_bitfieldv() +// CHECK: %[[call:.*]] = tail call i32 @_Z16def_one_bitfieldv() +// CHECK: tail call void @_Z3use12one_bitfield(i32 %[[call]]) +// CHECK: ret void +// +// CHECK: declare void @_Z3use12one_bitfield(i32) +// CHECK: declare i32 @_Z16def_one_bitfieldv() diff --git a/test/CodeGenCXX/x86_64-arguments.cpp b/test/CodeGenCXX/x86_64-arguments.cpp index 64202b4d02c6..c7eca2386af7 100644 --- a/test/CodeGenCXX/x86_64-arguments.cpp +++ b/test/CodeGenCXX/x86_64-arguments.cpp @@ -212,3 +212,12 @@ int FuncForDerivedPacked(DerivedPacked d) { return d.three; } } + +namespace test11 { +union U { + float f1; + char __attribute__((__vector_size__(1))) f2; +}; +int f(union U u) { return u.f2[1]; } +// CHECK-LABEL: define i32 @_ZN6test111fENS_1UE(i32 +} -- cgit v1.2.3