aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/BlocksRuntime/block-static.c25
-rw-r--r--test/BlocksRuntime/blockimport.c51
-rw-r--r--test/BlocksRuntime/byrefaccess.c34
-rw-r--r--test/BlocksRuntime/byrefcopy.c41
-rw-r--r--test/BlocksRuntime/byrefcopycopy.c46
-rw-r--r--test/BlocksRuntime/byrefcopyinner.c32
-rw-r--r--test/BlocksRuntime/byrefcopyint.c69
-rw-r--r--test/BlocksRuntime/byrefcopystack.c41
-rw-r--r--test/BlocksRuntime/byrefsanity.c73
-rw-r--r--test/BlocksRuntime/byrefstruct.c57
-rw-r--r--test/BlocksRuntime/c99.c20
-rw-r--r--test/BlocksRuntime/cast.c37
-rw-r--r--test/BlocksRuntime/constassign.c28
-rw-r--r--test/BlocksRuntime/copy-block-literal-rdar6439600.c29
-rw-r--r--test/BlocksRuntime/copyconstructor.C85
-rw-r--r--test/BlocksRuntime/copynull.c37
-rw-r--r--test/BlocksRuntime/dispatch_async.c57
-rw-r--r--test/BlocksRuntime/dispatch_call_Block_with_release.c31
-rw-r--r--test/BlocksRuntime/fail.c107
-rw-r--r--test/BlocksRuntime/flagsisa.c21
-rw-r--r--test/BlocksRuntime/globalexpression.c42
-rw-r--r--test/BlocksRuntime/goto.c34
-rw-r--r--test/BlocksRuntime/hasdescriptor.c29
-rw-r--r--test/BlocksRuntime/josh.C32
-rw-r--r--test/BlocksRuntime/k-and-r.c33
-rw-r--r--test/BlocksRuntime/large-struct.c51
-rw-r--r--test/BlocksRuntime/localisglobal.c42
-rw-r--r--test/BlocksRuntime/macro.c14
-rw-r--r--test/BlocksRuntime/makefile70
-rw-r--r--test/BlocksRuntime/modglobal.c18
-rw-r--r--test/BlocksRuntime/nestedimport.c44
-rw-r--r--test/BlocksRuntime/nullblockisa.c43
-rw-r--r--test/BlocksRuntime/objectRRGC.c77
-rw-r--r--test/BlocksRuntime/objectassign.c76
-rw-r--r--test/BlocksRuntime/orbars.c23
-rw-r--r--test/BlocksRuntime/rdar6396238.c32
-rw-r--r--test/BlocksRuntime/rdar6405500.c29
-rw-r--r--test/BlocksRuntime/rdar6414583.c31
-rw-r--r--test/BlocksRuntime/recursive-block.c55
-rw-r--r--test/BlocksRuntime/recursive-test.c74
-rw-r--r--test/BlocksRuntime/recursiveassign.c44
-rw-r--r--test/BlocksRuntime/reference.C95
-rw-r--r--test/BlocksRuntime/rettypepromotion.c36
-rw-r--r--test/BlocksRuntime/returnfunctionptr.c23
-rw-r--r--test/BlocksRuntime/shorthandexpression.c24
-rw-r--r--test/BlocksRuntime/sizeof.c26
-rw-r--r--test/BlocksRuntime/small-struct.c45
-rw-r--r--test/BlocksRuntime/structmember.c45
-rw-r--r--test/BlocksRuntime/testfilerunner.h110
-rw-r--r--test/BlocksRuntime/testfilerunner.m805
-rw-r--r--test/BlocksRuntime/varargs-bad-assign.c44
-rw-r--r--test/BlocksRuntime/varargs.c39
-rw-r--r--test/BlocksRuntime/variadic.c66
-rw-r--r--test/BlocksRuntime/voidarg.c27
-rw-r--r--test/CMakeLists.txt65
-rw-r--r--test/asan/CMakeLists.txt156
-rw-r--r--test/asan/TestCases/Android/coverage-android.cc67
-rw-r--r--test/asan/TestCases/Android/lit.local.cfg11
-rw-r--r--test/asan/TestCases/Darwin/asan_gen_prefixes.cc14
-rw-r--r--test/asan/TestCases/Darwin/cstring_literals_regtest.mm23
-rw-r--r--test/asan/TestCases/Darwin/dyld_insert_libraries_reexec.cc33
-rw-r--r--test/asan/TestCases/Darwin/interception-in-shared-lib-test.cc32
-rw-r--r--test/asan/TestCases/Darwin/interface_symbols_darwin.c39
-rw-r--r--test/asan/TestCases/Darwin/lit.local.cfg9
-rw-r--r--test/asan/TestCases/Darwin/malloc_set_zone_name-mprotect.cc51
-rw-r--r--test/asan/TestCases/Darwin/malloc_zone-protected.cc20
-rw-r--r--test/asan/TestCases/Darwin/objc-odr.mm23
-rw-r--r--test/asan/TestCases/Darwin/reexec-insert-libraries-env.cc25
-rw-r--r--test/asan/TestCases/Darwin/suppressions-darwin.cc34
-rw-r--r--test/asan/TestCases/Darwin/unset-insert-libraries-on-exec.cc25
-rw-r--r--test/asan/TestCases/Helpers/blacklist-extra.cc5
-rw-r--r--test/asan/TestCases/Helpers/echo-env.cc19
-rw-r--r--test/asan/TestCases/Helpers/init-order-atexit-extra.cc16
-rw-r--r--test/asan/TestCases/Helpers/init-order-pthread-create-extra.cc2
-rw-r--r--test/asan/TestCases/Helpers/initialization-blacklist-extra.cc15
-rw-r--r--test/asan/TestCases/Helpers/initialization-blacklist-extra2.cc4
-rw-r--r--test/asan/TestCases/Helpers/initialization-blacklist.txt3
-rw-r--r--test/asan/TestCases/Helpers/initialization-bug-extra.cc5
-rw-r--r--test/asan/TestCases/Helpers/initialization-bug-extra2.cc6
-rw-r--r--test/asan/TestCases/Helpers/initialization-constexpr-extra.cc3
-rw-r--r--test/asan/TestCases/Helpers/initialization-nobug-extra.cc9
-rw-r--r--test/asan/TestCases/Helpers/lit.local.cfg3
-rw-r--r--test/asan/TestCases/Linux/asan-asm-stacktrace-test.cc33
-rw-r--r--test/asan/TestCases/Linux/asan_dlopen_test.cc15
-rw-r--r--test/asan/TestCases/Linux/asan_prelink_test.cc29
-rw-r--r--test/asan/TestCases/Linux/asan_preload_test-1.cc30
-rw-r--r--test/asan/TestCases/Linux/asan_preload_test-2.cc24
-rw-r--r--test/asan/TestCases/Linux/asan_rt_confict_test-1.cc13
-rw-r--r--test/asan/TestCases/Linux/asan_rt_confict_test-2.cc25
-rw-r--r--test/asan/TestCases/Linux/clang_gcc_abi.cc44
-rw-r--r--test/asan/TestCases/Linux/clone_test.cc45
-rw-r--r--test/asan/TestCases/Linux/coverage-and-lsan.cc20
-rw-r--r--test/asan/TestCases/Linux/coverage-caller-callee-total-count.cc41
-rw-r--r--test/asan/TestCases/Linux/coverage-caller-callee.cc74
-rw-r--r--test/asan/TestCases/Linux/coverage-direct-large.cc45
-rw-r--r--test/asan/TestCases/Linux/coverage-direct.cc44
-rw-r--r--test/asan/TestCases/Linux/coverage-disabled.cc18
-rw-r--r--test/asan/TestCases/Linux/coverage-fork-direct.cc38
-rw-r--r--test/asan/TestCases/Linux/coverage-fork.cc38
-rw-r--r--test/asan/TestCases/Linux/coverage-levels.cc20
-rw-r--r--test/asan/TestCases/Linux/coverage-maybe-open-file.cc31
-rw-r--r--test/asan/TestCases/Linux/coverage-module-unloaded.cc56
-rw-r--r--test/asan/TestCases/Linux/coverage-sandboxing.cc85
-rw-r--r--test/asan/TestCases/Linux/coverage-tracing.cc22
-rw-r--r--test/asan/TestCases/Linux/coverage.cc71
-rw-r--r--test/asan/TestCases/Linux/function-sections-are-bad.cc41
-rw-r--r--test/asan/TestCases/Linux/globals-gc-sections.cc13
-rw-r--r--test/asan/TestCases/Linux/initialization-bug-any-order.cc36
-rw-r--r--test/asan/TestCases/Linux/interception-in-shared-lib-test.cc32
-rw-r--r--test/asan/TestCases/Linux/interception_malloc_test.cc23
-rw-r--r--test/asan/TestCases/Linux/interception_readdir_r_test.cc62
-rw-r--r--test/asan/TestCases/Linux/interception_test.cc22
-rw-r--r--test/asan/TestCases/Linux/interface_symbols_linux.c35
-rw-r--r--test/asan/TestCases/Linux/kernel-area.cc24
-rw-r--r--test/asan/TestCases/Linux/leak.cc16
-rw-r--r--test/asan/TestCases/Linux/lit.local.cfg9
-rw-r--r--test/asan/TestCases/Linux/malloc-in-qsort.cc56
-rw-r--r--test/asan/TestCases/Linux/malloc_delete_mismatch.cc33
-rw-r--r--test/asan/TestCases/Linux/odr-violation.cc42
-rw-r--r--test/asan/TestCases/Linux/overflow-in-qsort.cc51
-rw-r--r--test/asan/TestCases/Linux/preinit_test.cc33
-rw-r--r--test/asan/TestCases/Linux/ptrace.cc56
-rw-r--r--test/asan/TestCases/Linux/rlimit_mmap_test.cc16
-rw-r--r--test/asan/TestCases/Linux/shmctl.cc27
-rw-r--r--test/asan/TestCases/Linux/sized_delete_test.cc93
-rw-r--r--test/asan/TestCases/Linux/stack-trace-dlclose.cc45
-rw-r--r--test/asan/TestCases/Linux/stress_dtls.c116
-rw-r--r--test/asan/TestCases/Linux/swapcontext_test.cc90
-rw-r--r--test/asan/TestCases/Linux/syscalls.cc25
-rw-r--r--test/asan/TestCases/Linux/uar_signals.cc70
-rw-r--r--test/asan/TestCases/Linux/unpoison_tls.cc35
-rw-r--r--test/asan/TestCases/Posix/allow_user_segv.cc59
-rw-r--r--test/asan/TestCases/Posix/asan-symbolize-sanity-test.cc63
-rw-r--r--test/asan/TestCases/Posix/asprintf.cc20
-rw-r--r--test/asan/TestCases/Posix/assign_large_valloc_to_global.cc9
-rw-r--r--test/asan/TestCases/Posix/glob.cc33
-rw-r--r--test/asan/TestCases/Posix/glob_test_root/aa0
-rw-r--r--test/asan/TestCases/Posix/glob_test_root/ab0
-rw-r--r--test/asan/TestCases/Posix/glob_test_root/ba0
-rw-r--r--test/asan/TestCases/Posix/init-order-dlopen.cc72
-rw-r--r--test/asan/TestCases/Posix/ioctl.cc24
-rw-r--r--test/asan/TestCases/Posix/large_allocator_unpoisons_on_free.cc39
-rw-r--r--test/asan/TestCases/Posix/lit.local.cfg9
-rw-r--r--test/asan/TestCases/Posix/new_array_cookie_test.cc24
-rw-r--r--test/asan/TestCases/Posix/new_array_cookie_uaf_test.cc38
-rw-r--r--test/asan/TestCases/Posix/new_array_cookie_with_new_from_class.cc38
-rw-r--r--test/asan/TestCases/Posix/readv.cc32
-rw-r--r--test/asan/TestCases/Posix/shared-lib-test.cc57
-rw-r--r--test/asan/TestCases/Posix/start-deactivated.cc69
-rw-r--r--test/asan/TestCases/Posix/strerror_r_test.cc14
-rw-r--r--test/asan/TestCases/Posix/tsd_dtor_leak.cc39
-rw-r--r--test/asan/TestCases/Posix/wait.cc45
-rw-r--r--test/asan/TestCases/Posix/wait4.cc43
-rw-r--r--test/asan/TestCases/Posix/waitid.cc28
-rw-r--r--test/asan/TestCases/Windows/aligned_mallocs.cc29
-rw-r--r--test/asan/TestCases/Windows/allocators_sanity.cc37
-rw-r--r--test/asan/TestCases/Windows/beginthreadex.cc21
-rw-r--r--test/asan/TestCases/Windows/bitfield.cc21
-rw-r--r--test/asan/TestCases/Windows/bitfield_uaf.cc34
-rw-r--r--test/asan/TestCases/Windows/calloc_left_oob.cc17
-rw-r--r--test/asan/TestCases/Windows/calloc_right_oob.cc17
-rw-r--r--test/asan/TestCases/Windows/calloc_uaf.cc20
-rw-r--r--test/asan/TestCases/Windows/crt_initializers.cc31
-rw-r--r--test/asan/TestCases/Windows/demangled_names.cc50
-rw-r--r--test/asan/TestCases/Windows/dll_aligned_mallocs.cc34
-rw-r--r--test/asan/TestCases/Windows/dll_allocators_sanity.cc39
-rw-r--r--test/asan/TestCases/Windows/dll_and_lib.cc19
-rw-r--r--test/asan/TestCases/Windows/dll_cerr.cc23
-rw-r--r--test/asan/TestCases/Windows/dll_host.cc49
-rw-r--r--test/asan/TestCases/Windows/dll_intercept_memchr.cc21
-rw-r--r--test/asan/TestCases/Windows/dll_intercept_memcpy.cc32
-rw-r--r--test/asan/TestCases/Windows/dll_intercept_memcpy_indirect.cc34
-rw-r--r--test/asan/TestCases/Windows/dll_intercept_memset.cc32
-rw-r--r--test/asan/TestCases/Windows/dll_intercept_strlen.cc28
-rw-r--r--test/asan/TestCases/Windows/dll_large_function.cc12
-rw-r--r--test/asan/TestCases/Windows/dll_malloc_left_oob.cc23
-rw-r--r--test/asan/TestCases/Windows/dll_malloc_uaf.cc28
-rw-r--r--test/asan/TestCases/Windows/dll_noreturn.cc28
-rw-r--r--test/asan/TestCases/Windows/dll_null_deref.cc18
-rw-r--r--test/asan/TestCases/Windows/dll_operator_array_new_left_oob.cc25
-rw-r--r--test/asan/TestCases/Windows/dll_operator_array_new_with_dtor_left_oob.cc33
-rw-r--r--test/asan/TestCases/Windows/dll_poison_unpoison.cc35
-rw-r--r--test/asan/TestCases/Windows/dll_seh.cc60
-rw-r--r--test/asan/TestCases/Windows/dll_stack_use_after_return.cc28
-rw-r--r--test/asan/TestCases/Windows/dll_thread_stack_array_left_oob.cc36
-rw-r--r--test/asan/TestCases/Windows/double_free.cc21
-rw-r--r--test/asan/TestCases/Windows/double_operator_delete.cc25
-rw-r--r--test/asan/TestCases/Windows/global_const_string.cc12
-rw-r--r--test/asan/TestCases/Windows/global_const_string_oob.cc20
-rw-r--r--test/asan/TestCases/Windows/hello_world.cc9
-rw-r--r--test/asan/TestCases/Windows/intercept_memcpy.cc31
-rw-r--r--test/asan/TestCases/Windows/intercept_strdup.cc27
-rw-r--r--test/asan/TestCases/Windows/intercept_strlen.cc27
-rw-r--r--test/asan/TestCases/Windows/lit.local.cfg14
-rw-r--r--test/asan/TestCases/Windows/longjmp.cc26
-rw-r--r--test/asan/TestCases/Windows/malloc_left_oob.cc17
-rw-r--r--test/asan/TestCases/Windows/malloc_right_oob.cc17
-rw-r--r--test/asan/TestCases/Windows/malloc_uaf.cc20
-rw-r--r--test/asan/TestCases/Windows/null_deref.cc15
-rw-r--r--test/asan/TestCases/Windows/null_deref_multiple_dlls.cc40
-rw-r--r--test/asan/TestCases/Windows/operator_array_new_left_oob.cc17
-rw-r--r--test/asan/TestCases/Windows/operator_array_new_right_oob.cc18
-rw-r--r--test/asan/TestCases/Windows/operator_array_new_uaf.cc24
-rw-r--r--test/asan/TestCases/Windows/operator_array_new_with_dtor_left_oob.cc25
-rw-r--r--test/asan/TestCases/Windows/operator_delete_wrong_argument.cc12
-rw-r--r--test/asan/TestCases/Windows/operator_new_left_oob.cc17
-rw-r--r--test/asan/TestCases/Windows/operator_new_right_oob.cc17
-rw-r--r--test/asan/TestCases/Windows/operator_new_uaf.cc22
-rw-r--r--test/asan/TestCases/Windows/realloc_left_oob.cc17
-rw-r--r--test/asan/TestCases/Windows/realloc_right_oob.cc17
-rw-r--r--test/asan/TestCases/Windows/realloc_uaf.cc20
-rw-r--r--test/asan/TestCases/Windows/report_after_syminitialize.cc19
-rw-r--r--test/asan/TestCases/Windows/seh.cc56
-rw-r--r--test/asan/TestCases/Windows/stack_array_left_oob.cc16
-rw-r--r--test/asan/TestCases/Windows/stack_array_right_oob.cc16
-rw-r--r--test/asan/TestCases/Windows/stack_array_sanity.cc12
-rw-r--r--test/asan/TestCases/Windows/stack_use_after_return.cc22
-rw-r--r--test/asan/TestCases/Windows/thread_simple.cc26
-rw-r--r--test/asan/TestCases/Windows/thread_stack_array_left_oob.cc27
-rw-r--r--test/asan/TestCases/Windows/thread_stack_array_right_oob.cc27
-rw-r--r--test/asan/TestCases/Windows/thread_stack_reuse.cc37
-rw-r--r--test/asan/TestCases/Windows/thread_stress.cc30
-rw-r--r--test/asan/TestCases/Windows/throw_catch.cc73
-rw-r--r--test/asan/TestCases/Windows/use_after_realloc.cc23
-rw-r--r--test/asan/TestCases/Windows/use_after_return_linkage.cc12
-rw-r--r--test/asan/TestCases/Windows/windows_h.cc7
-rw-r--r--test/asan/TestCases/Windows/wrong_downcast_on_heap.cc26
-rw-r--r--test/asan/TestCases/Windows/wrong_downcast_on_stack.cc26
-rw-r--r--test/asan/TestCases/alloca_big_alignment.cc18
-rw-r--r--test/asan/TestCases/alloca_detect_custom_size_.cc23
-rw-r--r--test/asan/TestCases/alloca_instruments_all_paddings.cc23
-rw-r--r--test/asan/TestCases/alloca_overflow_partial.cc18
-rw-r--r--test/asan/TestCases/alloca_overflow_right.cc18
-rw-r--r--test/asan/TestCases/alloca_safe_access.cc17
-rw-r--r--test/asan/TestCases/alloca_underflow_left.cc18
-rw-r--r--test/asan/TestCases/allocator_returns_null.cc83
-rw-r--r--test/asan/TestCases/asan_and_llvm_coverage_test.cc10
-rw-r--r--test/asan/TestCases/atexit_stats.cc18
-rw-r--r--test/asan/TestCases/blacklist.cc38
-rw-r--r--test/asan/TestCases/contiguous_container.cc75
-rw-r--r--test/asan/TestCases/contiguous_container_crash.cc41
-rw-r--r--test/asan/TestCases/current_allocated_bytes.cc44
-rw-r--r--test/asan/TestCases/debug_locate.cc80
-rw-r--r--test/asan/TestCases/debug_mapping.cc24
-rw-r--r--test/asan/TestCases/debug_ppc64_mapping.cc37
-rw-r--r--test/asan/TestCases/debug_report.cc48
-rw-r--r--test/asan/TestCases/debug_stacks.cc62
-rw-r--r--test/asan/TestCases/deep_call_stack.cc25
-rw-r--r--test/asan/TestCases/deep_stack_uaf.cc36
-rw-r--r--test/asan/TestCases/deep_tail_call.cc20
-rw-r--r--test/asan/TestCases/deep_thread_stack.cc58
-rw-r--r--test/asan/TestCases/default_blacklist.cc6
-rw-r--r--test/asan/TestCases/default_options.cc18
-rw-r--r--test/asan/TestCases/describe_address.cc19
-rw-r--r--test/asan/TestCases/dlclose-test.cc99
-rw-r--r--test/asan/TestCases/double-free.cc27
-rw-r--r--test/asan/TestCases/dump_instruction_bytes.cc20
-rw-r--r--test/asan/TestCases/force_inline_opt0.cc14
-rw-r--r--test/asan/TestCases/free_hook_realloc.cc37
-rw-r--r--test/asan/TestCases/frexp_interceptor.cc16
-rw-r--r--test/asan/TestCases/gc-test.cc50
-rw-r--r--test/asan/TestCases/global-demangle.cc17
-rw-r--r--test/asan/TestCases/global-location.cc38
-rw-r--r--test/asan/TestCases/global-overflow.cc21
-rw-r--r--test/asan/TestCases/heap-overflow-large.cc23
-rw-r--r--test/asan/TestCases/heap-overflow.cc24
-rw-r--r--test/asan/TestCases/heavy_uar_test.cc60
-rw-r--r--test/asan/TestCases/huge_negative_hea_oob.cc13
-rw-r--r--test/asan/TestCases/init-order-atexit.cc34
-rw-r--r--test/asan/TestCases/init-order-pthread-create.cc32
-rw-r--r--test/asan/TestCases/initialization-blacklist.cc29
-rw-r--r--test/asan/TestCases/initialization-bug.cc45
-rw-r--r--test/asan/TestCases/initialization-constexpr.cc27
-rw-r--r--test/asan/TestCases/initialization-nobug.cc48
-rw-r--r--test/asan/TestCases/inline.cc19
-rw-r--r--test/asan/TestCases/interception_failure_test.cc22
-rw-r--r--test/asan/TestCases/interface_test.cc10
-rw-r--r--test/asan/TestCases/intra-object-overflow.cc31
-rw-r--r--test/asan/TestCases/invalid-free.cc23
-rw-r--r--test/asan/TestCases/large_func_test.cc53
-rw-r--r--test/asan/TestCases/log-path_test.cc44
-rw-r--r--test/asan/TestCases/log_path_fork_test.cc.disabled22
-rw-r--r--test/asan/TestCases/longjmp.cc25
-rw-r--r--test/asan/TestCases/lsan_annotations.cc16
-rw-r--r--test/asan/TestCases/malloc_context_size.cc27
-rw-r--r--test/asan/TestCases/malloc_fill.cc22
-rw-r--r--test/asan/TestCases/max_redzone.cc26
-rw-r--r--test/asan/TestCases/memcmp_strict_test.cc15
-rw-r--r--test/asan/TestCases/memcmp_test.cc17
-rw-r--r--test/asan/TestCases/memset_test.cc71
-rw-r--r--test/asan/TestCases/mmap_limit_mb.cc33
-rw-r--r--test/asan/TestCases/no_asan_gen_globals.c11
-rw-r--r--test/asan/TestCases/null_deref.cc19
-rw-r--r--test/asan/TestCases/on_error_callback.cc19
-rw-r--r--test/asan/TestCases/partial_right.cc13
-rw-r--r--test/asan/TestCases/poison_partial.cc19
-rw-r--r--test/asan/TestCases/print_summary.cc14
-rw-r--r--test/asan/TestCases/printf-1.c25
-rw-r--r--test/asan/TestCases/printf-2.c27
-rw-r--r--test/asan/TestCases/printf-3.c22
-rw-r--r--test/asan/TestCases/printf-4.c23
-rw-r--r--test/asan/TestCases/printf-5.c25
-rw-r--r--test/asan/TestCases/sanity_check_pure_c.c21
-rw-r--r--test/asan/TestCases/sleep_before_dying.c10
-rw-r--r--test/asan/TestCases/stack-buffer-overflow-with-position.cc44
-rw-r--r--test/asan/TestCases/stack-buffer-overflow.cc16
-rw-r--r--test/asan/TestCases/stack-frame-demangle.cc22
-rw-r--r--test/asan/TestCases/stack-oob-frames.cc59
-rw-r--r--test/asan/TestCases/stack-overflow.cc114
-rw-r--r--test/asan/TestCases/stack-use-after-return.cc80
-rw-r--r--test/asan/TestCases/strdup_oob_test.cc20
-rw-r--r--test/asan/TestCases/strip_path_prefix.c12
-rw-r--r--test/asan/TestCases/strncpy-overflow.cc30
-rw-r--r--test/asan/TestCases/suppressions-function.cc29
-rw-r--r--test/asan/TestCases/suppressions-interceptor.cc24
-rw-r--r--test/asan/TestCases/suppressions-library.cc39
-rw-r--r--test/asan/TestCases/throw_call_test.cc52
-rw-r--r--test/asan/TestCases/throw_catch.cc64
-rw-r--r--test/asan/TestCases/throw_invoke_test.cc54
-rw-r--r--test/asan/TestCases/time_interceptor.cc22
-rw-r--r--test/asan/TestCases/uar_and_exceptions.cc43
-rw-r--r--test/asan/TestCases/unaligned_loads_and_stores.cc52
-rw-r--r--test/asan/TestCases/use-after-delete.cc31
-rw-r--r--test/asan/TestCases/use-after-free-right.cc36
-rw-r--r--test/asan/TestCases/use-after-free.cc36
-rw-r--r--test/asan/TestCases/use-after-poison.cc20
-rw-r--r--test/asan/TestCases/use-after-scope-dtor-order.cc26
-rw-r--r--test/asan/TestCases/use-after-scope-inlined.cc28
-rw-r--r--test/asan/TestCases/use-after-scope-nobug.cc15
-rw-r--r--test/asan/TestCases/use-after-scope-temp.cc29
-rw-r--r--test/asan/TestCases/use-after-scope.cc17
-rw-r--r--test/asan/TestCases/zero_page_pc.cc12
-rw-r--r--test/asan/Unit/lit.site.cfg.in24
-rw-r--r--test/asan/android_commands/android_common.py29
-rwxr-xr-xtest/asan/android_commands/android_compile.py36
-rwxr-xr-xtest/asan/android_commands/android_run.py34
-rw-r--r--test/asan/lit.cfg153
-rw-r--r--test/asan/lit.site.cfg.in19
-rw-r--r--test/builtins/Unit/absvdi2_test.c (renamed from test/Unit/absvdi2_test.c)0
-rw-r--r--test/builtins/Unit/absvsi2_test.c (renamed from test/Unit/absvsi2_test.c)0
-rw-r--r--test/builtins/Unit/absvti2_test.c (renamed from test/Unit/absvti2_test.c)6
-rw-r--r--test/builtins/Unit/adddf3vfp_test.c (renamed from test/Unit/adddf3vfp_test.c)0
-rw-r--r--test/builtins/Unit/addsf3vfp_test.c (renamed from test/Unit/addsf3vfp_test.c)0
-rw-r--r--test/builtins/Unit/addtf3_test.c81
-rw-r--r--test/builtins/Unit/addvdi3_test.c (renamed from test/Unit/addvdi3_test.c)0
-rw-r--r--test/builtins/Unit/addvsi3_test.c (renamed from test/Unit/addvsi3_test.c)0
-rw-r--r--test/builtins/Unit/addvti3_test.c (renamed from test/Unit/addvti3_test.c)6
-rw-r--r--test/builtins/Unit/ashldi3_test.c (renamed from test/Unit/ashldi3_test.c)0
-rw-r--r--test/builtins/Unit/ashlti3_test.c (renamed from test/Unit/ashlti3_test.c)6
-rw-r--r--test/builtins/Unit/ashrdi3_test.c (renamed from test/Unit/ashrdi3_test.c)0
-rw-r--r--test/builtins/Unit/ashrti3_test.c (renamed from test/Unit/ashrti3_test.c)6
-rw-r--r--test/builtins/Unit/bswapdi2_test.c (renamed from test/Unit/bswapdi2_test.c)0
-rw-r--r--test/builtins/Unit/bswapsi2_test.c (renamed from test/Unit/bswapsi2_test.c)0
-rw-r--r--test/builtins/Unit/clear_cache_test.c (renamed from test/Unit/clear_cache_test.c)0
-rw-r--r--test/builtins/Unit/clzdi2_test.c (renamed from test/Unit/clzdi2_test.c)0
-rw-r--r--test/builtins/Unit/clzsi2_test.c (renamed from test/Unit/clzsi2_test.c)0
-rw-r--r--test/builtins/Unit/clzti2_test.c (renamed from test/Unit/clzti2_test.c)6
-rw-r--r--test/builtins/Unit/cmpdi2_test.c (renamed from test/Unit/cmpdi2_test.c)0
-rw-r--r--test/builtins/Unit/cmpti2_test.c (renamed from test/Unit/cmpti2_test.c)6
-rw-r--r--test/builtins/Unit/comparedf2_test.c (renamed from test/Unit/comparedf2_test.c)0
-rw-r--r--test/builtins/Unit/comparesf2_test.c (renamed from test/Unit/comparesf2_test.c)0
-rw-r--r--test/builtins/Unit/ctzdi2_test.c (renamed from test/Unit/ctzdi2_test.c)0
-rw-r--r--test/builtins/Unit/ctzsi2_test.c (renamed from test/Unit/ctzsi2_test.c)0
-rw-r--r--test/builtins/Unit/ctzti2_test.c (renamed from test/Unit/ctzti2_test.c)6
-rw-r--r--test/builtins/Unit/divdc3_test.c (renamed from test/Unit/divdc3_test.c)0
-rw-r--r--test/builtins/Unit/divdf3vfp_test.c (renamed from test/Unit/divdf3vfp_test.c)0
-rw-r--r--test/builtins/Unit/divdi3_test.c (renamed from test/Unit/divdi3_test.c)0
-rw-r--r--test/builtins/Unit/divmodsi4_test.c (renamed from test/Unit/divmodsi4_test.c)0
-rw-r--r--test/builtins/Unit/divsc3_test.c (renamed from test/Unit/divsc3_test.c)0
-rw-r--r--test/builtins/Unit/divsf3vfp_test.c (renamed from test/Unit/divsf3vfp_test.c)0
-rw-r--r--test/builtins/Unit/divsi3_test.c (renamed from test/Unit/divsi3_test.c)0
-rw-r--r--test/builtins/Unit/divtc3_test.c (renamed from test/Unit/divtc3_test.c)0
-rw-r--r--test/builtins/Unit/divtf3_test.c94
-rw-r--r--test/builtins/Unit/divti3_test.c (renamed from test/Unit/divti3_test.c)6
-rw-r--r--test/builtins/Unit/divxc3_test.c (renamed from test/Unit/divxc3_test.c)0
-rw-r--r--test/builtins/Unit/enable_execute_stack_test.c (renamed from test/Unit/enable_execute_stack_test.c)0
-rw-r--r--test/builtins/Unit/endianness.h (renamed from test/Unit/endianness.h)0
-rw-r--r--test/builtins/Unit/eqdf2vfp_test.c (renamed from test/Unit/eqdf2vfp_test.c)0
-rw-r--r--test/builtins/Unit/eqsf2vfp_test.c (renamed from test/Unit/eqsf2vfp_test.c)0
-rw-r--r--test/builtins/Unit/eqtf2_test.c89
-rw-r--r--test/builtins/Unit/extebdsfdf2vfp_test.c (renamed from test/Unit/extebdsfdf2vfp_test.c)0
-rw-r--r--test/builtins/Unit/extenddftf2_test.c82
-rw-r--r--test/builtins/Unit/extendsftf2_test.c83
-rw-r--r--test/builtins/Unit/ffsdi2_test.c (renamed from test/Unit/ffsdi2_test.c)0
-rw-r--r--test/builtins/Unit/ffsti2_test.c (renamed from test/Unit/ffsti2_test.c)6
-rw-r--r--test/builtins/Unit/fixdfdi_test.c (renamed from test/Unit/fixdfdi_test.c)0
-rw-r--r--test/builtins/Unit/fixdfsivfp_test.c (renamed from test/Unit/fixdfsivfp_test.c)0
-rw-r--r--test/builtins/Unit/fixdfti_test.c (renamed from test/Unit/fixdfti_test.c)6
-rw-r--r--test/builtins/Unit/fixsfdi_test.c (renamed from test/Unit/fixsfdi_test.c)0
-rw-r--r--test/builtins/Unit/fixsfsivfp_test.c (renamed from test/Unit/fixsfsivfp_test.c)0
-rw-r--r--test/builtins/Unit/fixsfti_test.c (renamed from test/Unit/fixsfti_test.c)6
-rw-r--r--test/builtins/Unit/fixunsdfdi_test.c (renamed from test/Unit/fixunsdfdi_test.c)0
-rw-r--r--test/builtins/Unit/fixunsdfsi_test.c (renamed from test/Unit/fixunsdfsi_test.c)0
-rw-r--r--test/builtins/Unit/fixunsdfsivfp_test.c (renamed from test/Unit/fixunsdfsivfp_test.c)0
-rw-r--r--test/builtins/Unit/fixunsdfti_test.c (renamed from test/Unit/fixunsdfti_test.c)4
-rw-r--r--test/builtins/Unit/fixunssfdi_test.c (renamed from test/Unit/fixunssfdi_test.c)0
-rw-r--r--test/builtins/Unit/fixunssfsi_test.c (renamed from test/Unit/fixunssfsi_test.c)0
-rw-r--r--test/builtins/Unit/fixunssfsivfp_test.c (renamed from test/Unit/fixunssfsivfp_test.c)0
-rw-r--r--test/builtins/Unit/fixunssfti_test.c (renamed from test/Unit/fixunssfti_test.c)6
-rw-r--r--test/builtins/Unit/fixunstfdi_test.c (renamed from test/Unit/fixunstfdi_test.c)0
-rw-r--r--test/builtins/Unit/fixunsxfdi_test.c (renamed from test/Unit/fixunsxfdi_test.c)0
-rw-r--r--test/builtins/Unit/fixunsxfsi_test.c (renamed from test/Unit/fixunsxfsi_test.c)0
-rw-r--r--test/builtins/Unit/fixunsxfti_test.c (renamed from test/Unit/fixunsxfti_test.c)6
-rw-r--r--test/builtins/Unit/fixxfdi_test.c (renamed from test/Unit/fixxfdi_test.c)0
-rw-r--r--test/builtins/Unit/fixxfti_test.c (renamed from test/Unit/fixxfti_test.c)6
-rw-r--r--test/builtins/Unit/floatdidf_test.c (renamed from test/Unit/floatdidf_test.c)0
-rw-r--r--test/builtins/Unit/floatdisf_test.c (renamed from test/Unit/floatdisf_test.c)0
-rw-r--r--test/builtins/Unit/floatdixf_test.c (renamed from test/Unit/floatdixf_test.c)0
-rw-r--r--test/builtins/Unit/floatsidfvfp_test.c (renamed from test/Unit/floatsidfvfp_test.c)0
-rw-r--r--test/builtins/Unit/floatsisfvfp_test.c (renamed from test/Unit/floatsisfvfp_test.c)0
-rw-r--r--test/builtins/Unit/floatsitf_test.c58
-rw-r--r--test/builtins/Unit/floattidf_test.c (renamed from test/Unit/floattidf_test.c)6
-rw-r--r--test/builtins/Unit/floattisf_test.c (renamed from test/Unit/floattisf_test.c)6
-rw-r--r--test/builtins/Unit/floattixf_test.c (renamed from test/Unit/floattixf_test.c)6
-rw-r--r--test/builtins/Unit/floatundidf_test.c (renamed from test/Unit/floatundidf_test.c)0
-rw-r--r--test/builtins/Unit/floatundisf_test.c (renamed from test/Unit/floatundisf_test.c)0
-rw-r--r--test/builtins/Unit/floatundixf_test.c (renamed from test/Unit/floatundixf_test.c)0
-rw-r--r--test/builtins/Unit/floatunsitf_test.c55
-rw-r--r--test/builtins/Unit/floatunssidfvfp_test.c (renamed from test/Unit/floatunssidfvfp_test.c)0
-rw-r--r--test/builtins/Unit/floatunssisfvfp_test.c (renamed from test/Unit/floatunssisfvfp_test.c)0
-rw-r--r--test/builtins/Unit/floatuntidf_test.c (renamed from test/Unit/floatuntidf_test.c)6
-rw-r--r--test/builtins/Unit/floatuntisf_test.c (renamed from test/Unit/floatuntisf_test.c)6
-rw-r--r--test/builtins/Unit/floatuntixf_test.c (renamed from test/Unit/floatuntixf_test.c)6
-rw-r--r--test/builtins/Unit/fp_test.h223
-rw-r--r--test/builtins/Unit/gcc_personality_test.c (renamed from test/Unit/gcc_personality_test.c)0
-rw-r--r--test/builtins/Unit/gcc_personality_test_helper.cxx (renamed from test/Unit/gcc_personality_test_helper.cxx)0
-rw-r--r--test/builtins/Unit/gedf2vfp_test.c (renamed from test/Unit/gedf2vfp_test.c)0
-rw-r--r--test/builtins/Unit/gesf2vfp_test.c (renamed from test/Unit/gesf2vfp_test.c)0
-rw-r--r--test/builtins/Unit/getf2_test.c89
-rw-r--r--test/builtins/Unit/gtdf2vfp_test.c (renamed from test/Unit/gtdf2vfp_test.c)0
-rw-r--r--test/builtins/Unit/gtsf2vfp_test.c (renamed from test/Unit/gtsf2vfp_test.c)0
-rw-r--r--test/builtins/Unit/gttf2_test.c89
-rw-r--r--test/builtins/Unit/ledf2vfp_test.c (renamed from test/Unit/ledf2vfp_test.c)0
-rw-r--r--test/builtins/Unit/lesf2vfp_test.c (renamed from test/Unit/lesf2vfp_test.c)0
-rw-r--r--test/builtins/Unit/letf2_test.c89
-rw-r--r--test/builtins/Unit/lshrdi3_test.c (renamed from test/Unit/lshrdi3_test.c)0
-rw-r--r--test/builtins/Unit/lshrti3_test.c (renamed from test/Unit/lshrti3_test.c)6
-rw-r--r--test/builtins/Unit/ltdf2vfp_test.c (renamed from test/Unit/ltdf2vfp_test.c)0
-rw-r--r--test/builtins/Unit/ltsf2vfp_test.c (renamed from test/Unit/ltsf2vfp_test.c)0
-rw-r--r--test/builtins/Unit/lttf2_test.c89
-rw-r--r--test/builtins/Unit/moddi3_test.c (renamed from test/Unit/moddi3_test.c)0
-rw-r--r--test/builtins/Unit/modsi3_test.c (renamed from test/Unit/modsi3_test.c)0
-rw-r--r--test/builtins/Unit/modti3_test.c (renamed from test/Unit/modti3_test.c)6
-rw-r--r--test/builtins/Unit/muldc3_test.c (renamed from test/Unit/muldc3_test.c)0
-rw-r--r--test/builtins/Unit/muldf3vfp_test.c (renamed from test/Unit/muldf3vfp_test.c)0
-rw-r--r--test/builtins/Unit/muldi3_test.c (renamed from test/Unit/muldi3_test.c)0
-rw-r--r--test/builtins/Unit/mulodi4_test.c (renamed from test/Unit/mulodi4_test.c)0
-rw-r--r--test/builtins/Unit/mulosi4_test.c (renamed from test/Unit/mulosi4_test.c)0
-rw-r--r--test/builtins/Unit/muloti4_test.c (renamed from test/Unit/muloti4_test.c)6
-rw-r--r--test/builtins/Unit/mulsc3_test.c (renamed from test/Unit/mulsc3_test.c)0
-rw-r--r--test/builtins/Unit/mulsf3vfp_test.c (renamed from test/Unit/mulsf3vfp_test.c)0
-rw-r--r--test/builtins/Unit/multc3_test.c (renamed from test/Unit/multc3_test.c)0
-rw-r--r--test/builtins/Unit/multf3_test.c95
-rw-r--r--test/builtins/Unit/multi3_test.c (renamed from test/Unit/multi3_test.c)6
-rw-r--r--test/builtins/Unit/mulvdi3_test.c (renamed from test/Unit/mulvdi3_test.c)0
-rw-r--r--test/builtins/Unit/mulvsi3_test.c (renamed from test/Unit/mulvsi3_test.c)0
-rw-r--r--test/builtins/Unit/mulvti3_test.c (renamed from test/Unit/mulvti3_test.c)6
-rw-r--r--test/builtins/Unit/mulxc3_test.c (renamed from test/Unit/mulxc3_test.c)0
-rw-r--r--test/builtins/Unit/nedf2vfp_test.c (renamed from test/Unit/nedf2vfp_test.c)0
-rw-r--r--test/builtins/Unit/negdf2vfp_test.c (renamed from test/Unit/negdf2vfp_test.c)0
-rw-r--r--test/builtins/Unit/negdi2_test.c (renamed from test/Unit/negdi2_test.c)0
-rw-r--r--test/builtins/Unit/negsf2vfp_test.c (renamed from test/Unit/negsf2vfp_test.c)0
-rw-r--r--test/builtins/Unit/negti2_test.c (renamed from test/Unit/negti2_test.c)6
-rw-r--r--test/builtins/Unit/negvdi2_test.c (renamed from test/Unit/negvdi2_test.c)0
-rw-r--r--test/builtins/Unit/negvsi2_test.c (renamed from test/Unit/negvsi2_test.c)0
-rw-r--r--test/builtins/Unit/negvti2_test.c (renamed from test/Unit/negvti2_test.c)6
-rw-r--r--test/builtins/Unit/nesf2vfp_test.c (renamed from test/Unit/nesf2vfp_test.c)0
-rw-r--r--test/builtins/Unit/netf2_test.c89
-rw-r--r--test/builtins/Unit/paritydi2_test.c (renamed from test/Unit/paritydi2_test.c)0
-rw-r--r--test/builtins/Unit/paritysi2_test.c (renamed from test/Unit/paritysi2_test.c)0
-rw-r--r--test/builtins/Unit/parityti2_test.c (renamed from test/Unit/parityti2_test.c)6
-rw-r--r--test/builtins/Unit/popcountdi2_test.c (renamed from test/Unit/popcountdi2_test.c)0
-rw-r--r--test/builtins/Unit/popcountsi2_test.c (renamed from test/Unit/popcountsi2_test.c)0
-rw-r--r--test/builtins/Unit/popcountti2_test.c (renamed from test/Unit/popcountti2_test.c)6
-rw-r--r--test/builtins/Unit/powidf2_test.c (renamed from test/Unit/powidf2_test.c)0
-rw-r--r--test/builtins/Unit/powisf2_test.c (renamed from test/Unit/powisf2_test.c)0
-rw-r--r--test/builtins/Unit/powitf2_test.c (renamed from test/Unit/powitf2_test.c)0
-rw-r--r--test/builtins/Unit/powixf2_test.c (renamed from test/Unit/powixf2_test.c)0
-rw-r--r--test/builtins/Unit/ppc/DD.h (renamed from test/Unit/ppc/DD.h)0
-rw-r--r--test/builtins/Unit/ppc/fixtfdi_test.c (renamed from test/Unit/ppc/fixtfdi_test.c)0
-rw-r--r--test/builtins/Unit/ppc/floatditf_test.c (renamed from test/Unit/ppc/floatditf_test.c)0
-rw-r--r--test/builtins/Unit/ppc/floatditf_test.h (renamed from test/Unit/ppc/floatditf_test.h)0
-rw-r--r--test/builtins/Unit/ppc/floatunditf_test.c (renamed from test/Unit/ppc/floatunditf_test.c)0
-rw-r--r--test/builtins/Unit/ppc/floatunditf_test.h (renamed from test/Unit/ppc/floatunditf_test.h)0
-rw-r--r--test/builtins/Unit/ppc/qadd_test.c (renamed from test/Unit/ppc/qadd_test.c)0
-rw-r--r--test/builtins/Unit/ppc/qdiv_test.c (renamed from test/Unit/ppc/qdiv_test.c)0
-rw-r--r--test/builtins/Unit/ppc/qmul_test.c (renamed from test/Unit/ppc/qmul_test.c)0
-rw-r--r--test/builtins/Unit/ppc/qsub_test.c (renamed from test/Unit/ppc/qsub_test.c)0
-rwxr-xr-xtest/builtins/Unit/ppc/test (renamed from test/Unit/ppc/test)0
-rw-r--r--test/builtins/Unit/subdf3vfp_test.c (renamed from test/Unit/subdf3vfp_test.c)0
-rw-r--r--test/builtins/Unit/subsf3vfp_test.c (renamed from test/Unit/subsf3vfp_test.c)0
-rw-r--r--test/builtins/Unit/subtf3_test.c74
-rw-r--r--test/builtins/Unit/subvdi3_test.c (renamed from test/Unit/subvdi3_test.c)0
-rw-r--r--test/builtins/Unit/subvsi3_test.c (renamed from test/Unit/subvsi3_test.c)0
-rw-r--r--test/builtins/Unit/subvti3_test.c (renamed from test/Unit/subvti3_test.c)6
-rwxr-xr-xtest/builtins/Unit/test (renamed from test/Unit/test)0
-rw-r--r--test/builtins/Unit/trampoline_setup_test.c (renamed from test/Unit/trampoline_setup_test.c)0
-rw-r--r--test/builtins/Unit/truncdfsf2vfp_test.c (renamed from test/Unit/truncdfsf2vfp_test.c)0
-rw-r--r--test/builtins/Unit/trunctfdf2_test.c76
-rw-r--r--test/builtins/Unit/trunctfsf2_test.c75
-rw-r--r--test/builtins/Unit/ucmpdi2_test.c (renamed from test/Unit/ucmpdi2_test.c)0
-rw-r--r--test/builtins/Unit/ucmpti2_test.c (renamed from test/Unit/ucmpti2_test.c)6
-rw-r--r--test/builtins/Unit/udivdi3_test.c (renamed from test/Unit/udivdi3_test.c)0
-rw-r--r--test/builtins/Unit/udivmoddi4_test.c (renamed from test/Unit/udivmoddi4_test.c)0
-rw-r--r--test/builtins/Unit/udivmodsi4_test.c (renamed from test/Unit/udivmodsi4_test.c)0
-rw-r--r--test/builtins/Unit/udivmodti4_test.c (renamed from test/Unit/udivmodti4_test.c)6
-rw-r--r--test/builtins/Unit/udivsi3_test.c (renamed from test/Unit/udivsi3_test.c)0
-rw-r--r--test/builtins/Unit/udivti3_test.c (renamed from test/Unit/udivti3_test.c)6
-rw-r--r--test/builtins/Unit/umoddi3_test.c (renamed from test/Unit/umoddi3_test.c)0
-rw-r--r--test/builtins/Unit/umodsi3_test.c (renamed from test/Unit/umodsi3_test.c)0
-rw-r--r--test/builtins/Unit/umodti3_test.c (renamed from test/Unit/umodti3_test.c)6
-rw-r--r--test/builtins/Unit/unorddf2vfp_test.c (renamed from test/Unit/unorddf2vfp_test.c)0
-rw-r--r--test/builtins/Unit/unordsf2vfp_test.c (renamed from test/Unit/unordsf2vfp_test.c)0
-rw-r--r--test/builtins/Unit/unordtf2_test.c65
-rw-r--r--test/builtins/timing/ashldi3.c (renamed from test/timing/ashldi3.c)0
-rw-r--r--test/builtins/timing/ashrdi3.c (renamed from test/timing/ashrdi3.c)0
-rw-r--r--test/builtins/timing/divdi3.c (renamed from test/timing/divdi3.c)0
-rw-r--r--test/builtins/timing/floatdidf.c (renamed from test/timing/floatdidf.c)0
-rw-r--r--test/builtins/timing/floatdisf.c (renamed from test/timing/floatdisf.c)0
-rw-r--r--test/builtins/timing/floatdixf.c (renamed from test/timing/floatdixf.c)0
-rw-r--r--test/builtins/timing/floatundidf.c (renamed from test/timing/floatundidf.c)0
-rw-r--r--test/builtins/timing/floatundisf.c (renamed from test/timing/floatundisf.c)0
-rw-r--r--test/builtins/timing/floatundixf.c (renamed from test/timing/floatundixf.c)0
-rw-r--r--test/builtins/timing/lshrdi3.c (renamed from test/timing/lshrdi3.c)0
-rw-r--r--test/builtins/timing/moddi3.c (renamed from test/timing/moddi3.c)0
-rw-r--r--test/builtins/timing/modsi3.c (renamed from test/timing/modsi3.c)0
-rw-r--r--test/builtins/timing/muldi3.c (renamed from test/timing/muldi3.c)0
-rw-r--r--test/builtins/timing/negdi2.c (renamed from test/timing/negdi2.c)0
-rwxr-xr-xtest/builtins/timing/time (renamed from test/timing/time)0
-rw-r--r--test/builtins/timing/timing.h (renamed from test/timing/timing.h)0
-rw-r--r--test/builtins/timing/udivdi3.c (renamed from test/timing/udivdi3.c)0
-rw-r--r--test/builtins/timing/umoddi3.c (renamed from test/timing/umoddi3.c)0
-rw-r--r--test/dfsan/CMakeLists.txt15
-rw-r--r--test/dfsan/Inputs/flags_abilist.txt10
-rw-r--r--test/dfsan/basic.c28
-rw-r--r--test/dfsan/custom.cc958
-rw-r--r--test/dfsan/dump_labels.c69
-rw-r--r--test/dfsan/flags.c24
-rw-r--r--test/dfsan/fncall.c26
-rw-r--r--test/dfsan/label_count.c75
-rw-r--r--test/dfsan/lit.cfg26
-rw-r--r--test/dfsan/lit.site.cfg.in5
-rw-r--r--test/dfsan/propagate.c47
-rw-r--r--test/dfsan/vararg.c24
-rw-r--r--test/dfsan/write_callback.c110
-rw-r--r--test/lit.common.cfg89
-rw-r--r--test/lit.common.configured.in38
-rw-r--r--test/lsan/CMakeLists.txt23
-rw-r--r--test/lsan/TestCases/cleanup_in_tsd_destructor.cc45
-rw-r--r--test/lsan/TestCases/disabler.cc23
-rw-r--r--test/lsan/TestCases/disabler_in_tsd_destructor.cc38
-rw-r--r--test/lsan/TestCases/do_leak_check_override.cc36
-rw-r--r--test/lsan/TestCases/fork.cc24
-rw-r--r--test/lsan/TestCases/fork_threaded.cc43
-rw-r--r--test/lsan/TestCases/high_allocator_contention.cc48
-rw-r--r--test/lsan/TestCases/ignore_object.cc24
-rw-r--r--test/lsan/TestCases/ignore_object_errors.cc22
-rw-r--r--test/lsan/TestCases/large_allocation_leak.cc18
-rw-r--r--test/lsan/TestCases/leak_check_at_exit.cc21
-rw-r--r--test/lsan/TestCases/leak_check_before_thread_started.cc32
-rw-r--r--test/lsan/TestCases/link_turned_off.cc24
-rw-r--r--test/lsan/TestCases/new_array_with_dtor_0.cc19
-rw-r--r--test/lsan/TestCases/pointer_to_self.cc18
-rw-r--r--test/lsan/TestCases/print_suppressions.cc33
-rw-r--r--test/lsan/TestCases/register_root_region.cc32
-rw-r--r--test/lsan/TestCases/sanity_check_pure_c.c10
-rw-r--r--test/lsan/TestCases/stale_stack_leak.cc43
-rw-r--r--test/lsan/TestCases/suppressions_default.cc28
-rw-r--r--test/lsan/TestCases/suppressions_file.cc26
-rw-r--r--test/lsan/TestCases/swapcontext.cc47
-rw-r--r--test/lsan/TestCases/use_after_return.cc23
-rw-r--r--test/lsan/TestCases/use_globals_initialized.cc21
-rw-r--r--test/lsan/TestCases/use_globals_uninitialized.cc21
-rw-r--r--test/lsan/TestCases/use_poisoned_asan.cc25
-rw-r--r--test/lsan/TestCases/use_registers.cc52
-rw-r--r--test/lsan/TestCases/use_stacks.cc20
-rw-r--r--test/lsan/TestCases/use_stacks_threaded.cc37
-rw-r--r--test/lsan/TestCases/use_tls_dynamic.cc50
-rw-r--r--test/lsan/TestCases/use_tls_pthread_specific_dynamic.cc37
-rw-r--r--test/lsan/TestCases/use_tls_pthread_specific_static.cc31
-rw-r--r--test/lsan/TestCases/use_tls_static.cc21
-rw-r--r--test/lsan/TestCases/use_unaligned.cc23
-rw-r--r--test/lsan/lit.common.cfg51
-rw-r--r--test/lsan/lit.site.cfg.in8
-rw-r--r--test/msan/CMakeLists.txt23
-rw-r--r--test/msan/Linux/getresid.cc25
-rw-r--r--test/msan/Linux/glob.cc27
-rw-r--r--test/msan/Linux/glob_altdirfunc.cc78
-rw-r--r--test/msan/Linux/glob_nomatch.cc21
-rw-r--r--test/msan/Linux/glob_test_root/aa0
-rw-r--r--test/msan/Linux/glob_test_root/ab0
-rw-r--r--test/msan/Linux/glob_test_root/ba0
-rw-r--r--test/msan/Linux/lit.local.cfg9
-rw-r--r--test/msan/Linux/sunrpc.cc40
-rw-r--r--test/msan/Linux/sunrpc_bytes.cc38
-rw-r--r--test/msan/Linux/sunrpc_string.cc35
-rw-r--r--test/msan/Linux/syscalls.cc115
-rw-r--r--test/msan/Linux/tcgetattr.cc21
-rw-r--r--test/msan/Linux/xattr.cc145
-rw-r--r--test/msan/Linux/xattr_test_root/a0
-rw-r--r--test/msan/Unit/lit.site.cfg.in14
-rw-r--r--test/msan/allocator_returns_null.cc81
-rw-r--r--test/msan/backtrace.cc26
-rw-r--r--test/msan/c-strdup.c17
-rw-r--r--test/msan/chained_origin.cc66
-rw-r--r--test/msan/chained_origin_empty_stack.cc34
-rw-r--r--test/msan/chained_origin_limits.cc178
-rw-r--r--test/msan/chained_origin_memcpy.cc61
-rw-r--r--test/msan/chained_origin_with_signals.cc36
-rw-r--r--test/msan/check_mem_is_initialized.cc33
-rw-r--r--test/msan/coverage-levels.cc28
-rw-r--r--test/msan/cxa_atexit.cc28
-rw-r--r--test/msan/death-callback.cc39
-rw-r--r--test/msan/default_blacklist.cc3
-rw-r--r--test/msan/dlerror.cc14
-rw-r--r--test/msan/dso-origin.cc48
-rw-r--r--test/msan/dtls_test.c60
-rw-r--r--test/msan/errno.cc17
-rw-r--r--test/msan/fork.cc121
-rw-r--r--test/msan/ftime.cc14
-rw-r--r--test/msan/getaddrinfo-positive.cc23
-rw-r--r--test/msan/getaddrinfo.cc24
-rw-r--r--test/msan/getc_unlocked.c32
-rw-r--r--test/msan/getline.cc36
-rw-r--r--test/msan/heap-origin.cc31
-rw-r--r--test/msan/iconv.cc48
-rw-r--r--test/msan/if_indextoname.cc23
-rw-r--r--test/msan/ifaddrs.cc50
-rw-r--r--test/msan/initgroups.cc11
-rw-r--r--test/msan/inline.cc20
-rw-r--r--test/msan/insertvalue_origin.cc35
-rw-r--r--test/msan/ioctl.cc20
-rw-r--r--test/msan/ioctl_custom.cc33
-rw-r--r--test/msan/ioctl_sound.cc29
-rw-r--r--test/msan/keep-going-dso.cc33
-rw-r--r--test/msan/keep-going.cc34
-rw-r--r--test/msan/lit.cfg30
-rw-r--r--test/msan/lit.site.cfg.in5
-rw-r--r--test/msan/mallinfo.cc12
-rw-r--r--test/msan/mktime.cc26
-rw-r--r--test/msan/mmap_below_shadow.cc28
-rw-r--r--test/msan/msan_check_mem_is_initialized.cc28
-rw-r--r--test/msan/msan_dump_shadow.cc22
-rw-r--r--test/msan/msan_print_shadow.cc122
-rw-r--r--test/msan/msan_print_shadow2.cc49
-rw-r--r--test/msan/msan_print_shadow3.cc16
-rw-r--r--test/msan/mul_by_const.cc27
-rw-r--r--test/msan/no_sanitize_memory.cc34
-rw-r--r--test/msan/no_sanitize_memory_prop.cc24
-rw-r--r--test/msan/obstack.cc37
-rw-r--r--test/msan/param_tls_limit.cc74
-rw-r--r--test/msan/poison_in_free.cc16
-rw-r--r--test/msan/print_stats.cc45
-rw-r--r--test/msan/pthread_getattr_np_deadlock.cc22
-rw-r--r--test/msan/rand_r.cc18
-rw-r--r--test/msan/readdir64.cc27
-rw-r--r--test/msan/report-demangling.cc19
-rw-r--r--test/msan/scandir.cc56
-rw-r--r--test/msan/scandir_null.cc34
-rw-r--r--test/msan/scandir_test_root/aaa0
-rw-r--r--test/msan/scandir_test_root/aab0
-rw-r--r--test/msan/scandir_test_root/bbb0
-rw-r--r--test/msan/select.cc22
-rw-r--r--test/msan/select_float_origin.cc24
-rw-r--r--test/msan/select_origin.cc22
-rw-r--r--test/msan/setlocale.cc13
-rw-r--r--test/msan/signal_stress_test.cc71
-rw-r--r--test/msan/sigwait.cc30
-rw-r--r--test/msan/sigwaitinfo.cc31
-rw-r--r--test/msan/stack-origin.cc31
-rw-r--r--test/msan/stack-origin2.cc41
-rw-r--r--test/msan/strerror_r-non-gnu.c18
-rw-r--r--test/msan/strlen_of_shadow.cc24
-rw-r--r--test/msan/strxfrm.cc15
-rw-r--r--test/msan/sync_lock_set_and_test.cc7
-rw-r--r--test/msan/textdomain.cc12
-rw-r--r--test/msan/times.cc20
-rw-r--r--test/msan/tls_reuse.cc26
-rw-r--r--test/msan/tsearch.cc36
-rw-r--r--test/msan/tzset.cc16
-rw-r--r--test/msan/unaligned_read_origin.cc16
-rw-r--r--test/msan/unpoison_string.cc16
-rw-r--r--test/msan/use-after-free.cc34
-rw-r--r--test/msan/vector_cvt.cc23
-rw-r--r--test/msan/vector_select.cc13
-rw-r--r--test/profile/CMakeLists.txt16
-rw-r--r--test/profile/Inputs/instrprof-dlopen-func.c1
-rw-r--r--test/profile/Inputs/instrprof-dlopen-func2.c1
-rw-r--r--test/profile/Inputs/instrprof-dlopen-main.c47
-rw-r--r--test/profile/Inputs/instrprof-dynamic-a.cpp7
-rw-r--r--test/profile/Inputs/instrprof-dynamic-b.cpp7
-rw-r--r--test/profile/Inputs/instrprof-dynamic-header.h5
-rw-r--r--test/profile/Inputs/instrprof-dynamic-main.cpp9
-rw-r--r--test/profile/instrprof-basic.c31
-rw-r--r--test/profile/instrprof-dlopen.test34
-rw-r--r--test/profile/instrprof-dynamic-one-shared.test23
-rw-r--r--test/profile/instrprof-dynamic-two-shared.test24
-rw-r--r--test/profile/instrprof-reset-counters.c19
-rw-r--r--test/profile/instrprof-set-filename.c14
-rw-r--r--test/profile/instrprof-without-libc.c60
-rw-r--r--test/profile/instrprof-write-file-atexit-explicitly.c17
-rw-r--r--test/profile/instrprof-write-file-only.c35
-rw-r--r--test/profile/instrprof-write-file.c34
-rw-r--r--test/profile/lit.cfg53
-rw-r--r--test/profile/lit.site.cfg.in11
-rw-r--r--test/sanitizer_common/CMakeLists.txt46
-rw-r--r--test/sanitizer_common/TestCases/Linux/aligned_alloc.c8
-rw-r--r--test/sanitizer_common/TestCases/Linux/clock_gettime.c11
-rw-r--r--test/sanitizer_common/TestCases/Linux/getpass.cc32
-rw-r--r--test/sanitizer_common/TestCases/Linux/getpwnam_r_invalid_user.cc19
-rw-r--r--test/sanitizer_common/TestCases/Linux/lit.local.cfg9
-rw-r--r--test/sanitizer_common/TestCases/Linux/mlock_test.cc13
-rw-r--r--test/sanitizer_common/TestCases/Linux/open_memstream.cc57
-rw-r--r--test/sanitizer_common/TestCases/Linux/ptrace.cc60
-rw-r--r--test/sanitizer_common/TestCases/Linux/timerfd.cc52
-rw-r--r--test/sanitizer_common/TestCases/corelimit.cc16
-rw-r--r--test/sanitizer_common/TestCases/malloc_hook.cc38
-rw-r--r--test/sanitizer_common/TestCases/print-stack-trace.cc24
-rw-r--r--test/sanitizer_common/TestCases/pthread_mutexattr_get.cc19
-rw-r--r--test/sanitizer_common/Unit/lit.site.cfg.in15
-rw-r--r--test/sanitizer_common/lit.common.cfg38
-rw-r--r--test/sanitizer_common/lit.site.cfg.in9
-rw-r--r--test/tsan/CMakeLists.txt27
-rw-r--r--test/tsan/Linux/lit.local.cfg9
-rw-r--r--test/tsan/Linux/mutex_robust.cc36
-rw-r--r--test/tsan/Linux/mutex_robust2.cc41
-rw-r--r--test/tsan/Linux/user_fopen.cc34
-rw-r--r--test/tsan/Linux/user_malloc.cc27
-rw-r--r--test/tsan/Unit/lit.site.cfg.in14
-rw-r--r--test/tsan/aligned_vs_unaligned_race.cc34
-rw-r--r--test/tsan/allocator_returns_null.cc64
-rw-r--r--test/tsan/atexit.cc29
-rw-r--r--test/tsan/atexit2.cc26
-rw-r--r--test/tsan/atomic_free.cc19
-rw-r--r--test/tsan/atomic_free2.cc19
-rw-r--r--test/tsan/atomic_norace.cc61
-rw-r--r--test/tsan/atomic_race.cc80
-rw-r--r--test/tsan/atomic_stack.cc29
-rw-r--r--test/tsan/barrier.cc37
-rw-r--r--test/tsan/bench.h59
-rw-r--r--test/tsan/bench_acquire_only.cc19
-rw-r--r--test/tsan/bench_acquire_release.cc18
-rw-r--r--test/tsan/bench_local_mutex.cc27
-rw-r--r--test/tsan/bench_mutex.cc28
-rw-r--r--test/tsan/bench_release_only.cc23
-rw-r--r--test/tsan/bench_rwmutex.cc25
-rw-r--r--test/tsan/bench_shadow_flush.cc48
-rw-r--r--test/tsan/bench_single_writer.cc23
-rw-r--r--test/tsan/bench_ten_mutexes.cc26
-rw-r--r--test/tsan/benign_race.cc39
-rw-r--r--test/tsan/blacklist.cc30
-rw-r--r--test/tsan/blacklist2.cc49
-rw-r--r--test/tsan/cond.c53
-rw-r--r--test/tsan/cond_cancel.c37
-rw-r--r--test/tsan/cond_race.cc40
-rw-r--r--test/tsan/cond_version.c44
-rw-r--r--test/tsan/deadlock_detector_stress_test.cc596
-rw-r--r--test/tsan/deep_stack1.cc44
-rw-r--r--test/tsan/default_options.cc32
-rwxr-xr-xtest/tsan/deflake.bash17
-rw-r--r--test/tsan/dlclose.cc58
-rw-r--r--test/tsan/fd_close_norace.cc33
-rw-r--r--test/tsan/fd_close_norace2.cc30
-rw-r--r--test/tsan/fd_dup_norace.cc34
-rw-r--r--test/tsan/fd_location.cc33
-rw-r--r--test/tsan/fd_pipe_norace.cc33
-rw-r--r--test/tsan/fd_pipe_race.cc37
-rw-r--r--test/tsan/fd_socket_connect_norace.cc45
-rw-r--r--test/tsan/fd_socket_norace.cc52
-rw-r--r--test/tsan/fd_socketpair_norace.cc37
-rw-r--r--test/tsan/fd_stdout_race.cc41
-rw-r--r--test/tsan/fork_atexit.cc37
-rw-r--r--test/tsan/fork_deadlock.cc48
-rw-r--r--test/tsan/fork_multithreaded.cc42
-rw-r--r--test/tsan/fork_multithreaded3.cc40
-rw-r--r--test/tsan/free_race.c49
-rw-r--r--test/tsan/free_race.c.supp2
-rw-r--r--test/tsan/free_race2.c26
-rw-r--r--test/tsan/getline_nohang.cc39
-rw-r--r--test/tsan/global_race.cc28
-rw-r--r--test/tsan/global_race2.cc28
-rw-r--r--test/tsan/global_race3.cc32
-rw-r--r--test/tsan/halt_on_error.cc27
-rw-r--r--test/tsan/heap_race.cc20
-rw-r--r--test/tsan/ignore_free.cc35
-rw-r--r--test/tsan/ignore_lib0.cc30
-rw-r--r--test/tsan/ignore_lib0.cc.supp2
-rw-r--r--test/tsan/ignore_lib1.cc42
-rw-r--r--test/tsan/ignore_lib1.cc.supp2
-rw-r--r--test/tsan/ignore_lib2.cc33
-rw-r--r--test/tsan/ignore_lib2.cc.supp2
-rw-r--r--test/tsan/ignore_lib3.cc33
-rw-r--r--test/tsan/ignore_lib3.cc.supp2
-rw-r--r--test/tsan/ignore_lib_lib.h25
-rw-r--r--test/tsan/ignore_malloc.cc38
-rw-r--r--test/tsan/ignore_race.cc31
-rw-r--r--test/tsan/ignore_sync.cc30
-rw-r--r--test/tsan/inlined_memcpy_race.cc38
-rw-r--r--test/tsan/inlined_memcpy_race2.cc38
-rw-r--r--test/tsan/interface_atomic_test.c16
-rw-r--r--test/tsan/java.h21
-rw-r--r--test/tsan/java_alloc.cc38
-rw-r--r--test/tsan/java_finalizer.cc27
-rw-r--r--test/tsan/java_lock.cc36
-rw-r--r--test/tsan/java_lock_move.cc41
-rw-r--r--test/tsan/java_lock_rec.cc55
-rw-r--r--test/tsan/java_lock_rec_race.cc49
-rw-r--r--test/tsan/java_move_overlap.cc72
-rw-r--r--test/tsan/java_move_overlap_race.cc53
-rw-r--r--test/tsan/java_race.cc25
-rw-r--r--test/tsan/java_race_move.cc33
-rw-r--r--test/tsan/java_rwlock.cc36
-rw-r--r--test/tsan/libcxx/lit.local.cfg10
-rw-r--r--test/tsan/libcxx/std_shared_ptr.cc24
-rw-r--r--test/tsan/lit.cfg65
-rw-r--r--test/tsan/lit.site.cfg.in10
-rw-r--r--test/tsan/load_shared_lib.cc66
-rw-r--r--test/tsan/longjmp.cc22
-rw-r--r--test/tsan/longjmp2.cc24
-rw-r--r--test/tsan/longjmp3.cc48
-rw-r--r--test/tsan/longjmp4.cc51
-rw-r--r--test/tsan/malloc_overflow.cc23
-rw-r--r--test/tsan/malloc_stack.cc25
-rw-r--r--test/tsan/map32bit.cc41
-rw-r--r--test/tsan/memcpy_race.cc42
-rw-r--r--test/tsan/mmap_large.cc20
-rw-r--r--test/tsan/mop_with_offset.cc36
-rw-r--r--test/tsan/mop_with_offset2.cc36
-rw-r--r--test/tsan/must_deadlock.cc50
-rw-r--r--test/tsan/mutex_bad_read_lock.cc19
-rw-r--r--test/tsan/mutex_bad_read_unlock.cc20
-rw-r--r--test/tsan/mutex_bad_unlock.cc18
-rw-r--r--test/tsan/mutex_cycle2.c35
-rw-r--r--test/tsan/mutex_destroy_locked.cc22
-rw-r--r--test/tsan/mutex_double_lock.cc29
-rw-r--r--test/tsan/mutexset1.cc37
-rw-r--r--test/tsan/mutexset2.cc37
-rw-r--r--test/tsan/mutexset3.cc45
-rw-r--r--test/tsan/mutexset4.cc45
-rw-r--r--test/tsan/mutexset5.cc46
-rw-r--r--test/tsan/mutexset6.cc53
-rw-r--r--test/tsan/mutexset7.cc40
-rw-r--r--test/tsan/mutexset8.cc39
-rw-r--r--test/tsan/printf-1.c16
-rw-r--r--test/tsan/process_sleep.h7
-rw-r--r--test/tsan/pthread_atfork_deadlock.c33
-rw-r--r--test/tsan/race_on_barrier.c31
-rw-r--r--test/tsan/race_on_barrier2.c31
-rw-r--r--test/tsan/race_on_heap.cc47
-rw-r--r--test/tsan/race_on_mutex.c42
-rw-r--r--test/tsan/race_on_mutex2.c24
-rw-r--r--test/tsan/race_on_puts.cc29
-rw-r--r--test/tsan/race_on_read.cc41
-rw-r--r--test/tsan/race_on_speculative_load.cc27
-rw-r--r--test/tsan/race_on_write.cc39
-rw-r--r--test/tsan/race_with_finished_thread.cc43
-rw-r--r--test/tsan/signal_errno.cc49
-rw-r--r--test/tsan/signal_longjmp.cc69
-rw-r--r--test/tsan/signal_malloc.cc26
-rw-r--r--test/tsan/signal_recursive.cc132
-rw-r--r--test/tsan/signal_sync.cc58
-rw-r--r--test/tsan/signal_write.cc27
-rw-r--r--test/tsan/sigsuspend.cc44
-rw-r--r--test/tsan/simple_race.c29
-rw-r--r--test/tsan/simple_race.cc29
-rw-r--r--test/tsan/simple_stack.c66
-rw-r--r--test/tsan/simple_stack2.cc53
-rw-r--r--test/tsan/sleep_sync.cc30
-rw-r--r--test/tsan/sleep_sync2.cc22
-rw-r--r--test/tsan/stack_race.cc22
-rw-r--r--test/tsan/stack_race2.cc29
-rw-r--r--test/tsan/static_init1.cc27
-rw-r--r--test/tsan/static_init2.cc33
-rw-r--r--test/tsan/static_init3.cc47
-rw-r--r--test/tsan/static_init4.cc37
-rw-r--r--test/tsan/static_init5.cc42
-rw-r--r--test/tsan/static_init6.cc42
-rw-r--r--test/tsan/sunrpc.cc25
-rw-r--r--test/tsan/suppress_same_address.cc29
-rw-r--r--test/tsan/suppress_same_stacks.cc27
-rw-r--r--test/tsan/suppressions_global.cc29
-rw-r--r--test/tsan/suppressions_global.cc.supp2
-rw-r--r--test/tsan/suppressions_race.cc31
-rw-r--r--test/tsan/suppressions_race.cc.supp2
-rw-r--r--test/tsan/suppressions_race2.cc31
-rw-r--r--test/tsan/suppressions_race2.cc.supp2
-rwxr-xr-xtest/tsan/test_output.sh66
-rw-r--r--test/tsan/thread_detach.c20
-rw-r--r--test/tsan/thread_end_with_ignore.cc24
-rw-r--r--test/tsan/thread_end_with_ignore2.cc12
-rw-r--r--test/tsan/thread_end_with_ignore3.cc22
-rw-r--r--test/tsan/thread_leak.c17
-rw-r--r--test/tsan/thread_leak2.c17
-rw-r--r--test/tsan/thread_leak3.c17
-rw-r--r--test/tsan/thread_leak4.c18
-rw-r--r--test/tsan/thread_leak5.c20
-rw-r--r--test/tsan/thread_name.cc47
-rw-r--r--test/tsan/thread_name2.cc36
-rw-r--r--test/tsan/tiny_race.c21
-rw-r--r--test/tsan/tls_race.cc21
-rw-r--r--test/tsan/tls_race2.cc29
-rw-r--r--test/tsan/tsan-vs-gvn.cc38
-rw-r--r--test/tsan/unaligned_norace.cc84
-rw-r--r--test/tsan/unaligned_race.cc139
-rw-r--r--test/tsan/vfork.cc51
-rw-r--r--test/tsan/virtual_inheritance_compile_bug.cc15
-rw-r--r--test/tsan/vptr_benign_race.cc51
-rw-r--r--test/tsan/vptr_harmful_race.cc51
-rw-r--r--test/tsan/vptr_harmful_race2.cc51
-rw-r--r--test/tsan/vptr_harmful_race3.cc53
-rw-r--r--test/tsan/vptr_harmful_race4.cc34
-rw-r--r--test/tsan/write_in_reader_lock.cc35
-rw-r--r--test/ubsan/CMakeLists.txt25
-rw-r--r--test/ubsan/TestCases/Float/cast-overflow.cpp134
-rw-r--r--test/ubsan/TestCases/Integer/add-overflow.cpp32
-rw-r--r--test/ubsan/TestCases/Integer/div-overflow.cpp10
-rw-r--r--test/ubsan/TestCases/Integer/div-zero.cpp15
-rw-r--r--test/ubsan/TestCases/Integer/incdec-overflow.cpp16
-rw-r--r--test/ubsan/TestCases/Integer/mul-overflow.cpp14
-rw-r--r--test/ubsan/TestCases/Integer/negate-overflow.cpp12
-rw-r--r--test/ubsan/TestCases/Integer/no-recover.cpp22
-rw-r--r--test/ubsan/TestCases/Integer/shift.cpp37
-rw-r--r--test/ubsan/TestCases/Integer/sub-overflow.cpp31
-rw-r--r--test/ubsan/TestCases/Integer/summary.cpp10
-rw-r--r--test/ubsan/TestCases/Integer/uadd-overflow.cpp32
-rw-r--r--test/ubsan/TestCases/Integer/uincdec-overflow.cpp16
-rw-r--r--test/ubsan/TestCases/Integer/umul-overflow.cpp19
-rw-r--r--test/ubsan/TestCases/Integer/usub-overflow.cpp31
-rw-r--r--test/ubsan/TestCases/Misc/bool.cpp10
-rw-r--r--test/ubsan/TestCases/Misc/bounds.cpp15
-rw-r--r--test/ubsan/TestCases/Misc/deduplication.cpp25
-rw-r--r--test/ubsan/TestCases/Misc/enum.cpp17
-rw-r--r--test/ubsan/TestCases/Misc/missing_return.cpp17
-rw-r--r--test/ubsan/TestCases/Misc/nonnull-arg.cpp58
-rw-r--r--test/ubsan/TestCases/Misc/nonnull.cpp15
-rw-r--r--test/ubsan/TestCases/Misc/unreachable.cpp6
-rw-r--r--test/ubsan/TestCases/Misc/vla.c11
-rw-r--r--test/ubsan/TestCases/TypeCheck/Function/function.cpp24
-rw-r--r--test/ubsan/TestCases/TypeCheck/Function/lit.local.cfg3
-rw-r--r--test/ubsan/TestCases/TypeCheck/misaligned.cpp105
-rw-r--r--test/ubsan/TestCases/TypeCheck/null.cpp38
-rw-r--r--test/ubsan/TestCases/TypeCheck/vptr-virtual-base.cpp19
-rw-r--r--test/ubsan/TestCases/TypeCheck/vptr.cpp166
-rw-r--r--test/ubsan/lit.common.cfg56
-rw-r--r--test/ubsan/lit.site.cfg.in8
945 files changed, 28902 insertions, 104 deletions
diff --git a/test/BlocksRuntime/block-static.c b/test/BlocksRuntime/block-static.c
new file mode 100644
index 000000000000..d38c816cf015
--- /dev/null
+++ b/test/BlocksRuntime/block-static.c
@@ -0,0 +1,25 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// testfilerunner CONFIG
+
+#include <stdio.h>
+
+
+int main(int argc, char **argv) {
+ static int numberOfSquesals = 5;
+
+ ^{ numberOfSquesals = 6; }();
+
+ if (numberOfSquesals == 6) {
+ printf("%s: success\n", argv[0]);
+ return 0;
+ }
+ printf("**** did not update static local, rdar://6177162\n");
+ return 1;
+
+}
+
diff --git a/test/BlocksRuntime/blockimport.c b/test/BlocksRuntime/blockimport.c
new file mode 100644
index 000000000000..178fce4395e5
--- /dev/null
+++ b/test/BlocksRuntime/blockimport.c
@@ -0,0 +1,51 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+/*
+ * blockimport.c
+ * testObjects
+ *
+ * Created by Blaine Garst on 10/13/08.
+ *
+ */
+
+
+//
+// pure C nothing more needed
+// CONFIG rdar://6289344
+
+#include <stdio.h>
+#include <Block.h>
+#include <Block_private.h>
+
+
+
+
+int main(int argc, char *argv[]) {
+ int i = 1;
+ int (^intblock)(void) = ^{ return i*10; };
+
+ void (^vv)(void) = ^{
+ if (argc > 0) {
+ printf("intblock returns %d\n", intblock());
+ }
+ };
+
+#if 0
+ //printf("Block dump %s\n", _Block_dump(vv));
+ {
+ struct Block_layout *layout = (struct Block_layout *)(void *)vv;
+ printf("isa %p\n", layout->isa);
+ printf("flags %x\n", layout->flags);
+ printf("descriptor %p\n", layout->descriptor);
+ printf("descriptor->size %d\n", layout->descriptor->size);
+ }
+#endif
+ void (^vvcopy)(void) = Block_copy(vv);
+ Block_release(vvcopy);
+ printf("%s: success\n", argv[0]);
+ return 0;
+}
diff --git a/test/BlocksRuntime/byrefaccess.c b/test/BlocksRuntime/byrefaccess.c
new file mode 100644
index 000000000000..4565553338ac
--- /dev/null
+++ b/test/BlocksRuntime/byrefaccess.c
@@ -0,0 +1,34 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+//
+// byrefaccess.m
+// test that byref access to locals is accurate
+// testObjects
+//
+// Created by Blaine Garst on 5/13/08.
+//
+// CONFIG
+
+#include <stdio.h>
+
+
+void callVoidVoid(void (^closure)(void)) {
+ closure();
+}
+
+int main(int argc, char *argv[]) {
+ __block int i = 10;
+
+ callVoidVoid(^{ ++i; });
+
+ if (i != 11) {
+ printf("*** %s didn't update i\n", argv[0]);
+ return 1;
+ }
+ printf("%s: success\n", argv[0]);
+ return 0;
+}
diff --git a/test/BlocksRuntime/byrefcopy.c b/test/BlocksRuntime/byrefcopy.c
new file mode 100644
index 000000000000..513b63c2725d
--- /dev/null
+++ b/test/BlocksRuntime/byrefcopy.c
@@ -0,0 +1,41 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+//
+// byrefcopy.m
+// testObjects
+//
+// Created by Blaine Garst on 5/13/08.
+//
+
+#include <stdio.h>
+#include <Block.h>
+#include <Block_private.h>
+
+// CONFIG
+
+void callVoidVoid(void (^closure)(void)) {
+ closure();
+}
+
+int main(int argc, char *argv[]) {
+ int __block i = 10;
+
+ void (^block)(void) = ^{ ++i; };
+ //printf("original (old style) is %s\n", _Block_dump_old(block));
+ //printf("original (new style) is %s\n", _Block_dump(block));
+ void (^blockcopy)(void) = Block_copy(block);
+ //printf("copy is %s\n", _Block_dump(blockcopy));
+ // use a copy & see that it updates i
+ callVoidVoid(block);
+
+ if (i != 11) {
+ printf("*** %s didn't update i\n", argv[0]);
+ return 1;
+ }
+ printf("%s: success\n", argv[0]);
+ return 0;
+}
diff --git a/test/BlocksRuntime/byrefcopycopy.c b/test/BlocksRuntime/byrefcopycopy.c
new file mode 100644
index 000000000000..d6fafc152e1d
--- /dev/null
+++ b/test/BlocksRuntime/byrefcopycopy.c
@@ -0,0 +1,46 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// CONFIG rdar://6255170
+
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <Block.h>
+#include <Block_private.h>
+#include <assert.h>
+
+
+int
+main(int argc, char *argv[])
+{
+ __block int var = 0;
+ int shouldbe = 0;
+ void (^b)(void) = ^{ var++; /*printf("var is at %p with value %d\n", &var, var);*/ };
+ __typeof(b) _b;
+ //printf("before copy...\n");
+ b(); ++shouldbe;
+ size_t i;
+
+ for (i = 0; i < 10; i++) {
+ _b = Block_copy(b); // make a new copy each time
+ assert(_b);
+ ++shouldbe;
+ _b(); // should still update the stack
+ Block_release(_b);
+ }
+
+ //printf("after...\n");
+ b(); ++shouldbe;
+
+ if (var != shouldbe) {
+ printf("Hmm, var is %d but should be %d\n", var, shouldbe);
+ return 1;
+ }
+ printf("%s: Success!!\n", argv[0]);
+
+ return 0;
+}
diff --git a/test/BlocksRuntime/byrefcopyinner.c b/test/BlocksRuntime/byrefcopyinner.c
new file mode 100644
index 000000000000..07770933afe3
--- /dev/null
+++ b/test/BlocksRuntime/byrefcopyinner.c
@@ -0,0 +1,32 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+#include <Block.h>
+#include <stdio.h>
+
+// CONFIG rdar://6225809
+// fixed in 5623
+
+int main(int argc, char *argv[]) {
+ __block int a = 42;
+ int* ap = &a; // just to keep the address on the stack.
+
+ void (^b)(void) = ^{
+ //a; // workaround, a should be implicitly imported
+ Block_copy(^{
+ a = 2;
+ });
+ };
+
+ Block_copy(b);
+
+ if(&a == ap) {
+ printf("**** __block heap storage should have been created at this point\n");
+ return 1;
+ }
+ printf("%s: Success\n", argv[0]);
+ return 0;
+}
diff --git a/test/BlocksRuntime/byrefcopyint.c b/test/BlocksRuntime/byrefcopyint.c
new file mode 100644
index 000000000000..d632f88a0bc5
--- /dev/null
+++ b/test/BlocksRuntime/byrefcopyint.c
@@ -0,0 +1,69 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+/*
+ * byrefcopyint.c
+ * testObjects
+ *
+ * Created by Blaine Garst on 12/1/08.
+ *
+ */
+
+//
+// byrefcopyid.m
+// testObjects
+//
+// Created by Blaine Garst on 5/13/08.
+//
+
+// Tests copying of blocks with byref ints
+// CONFIG rdar://6414583 -C99
+
+#include <stdio.h>
+#include <string.h>
+#include <Block.h>
+#include <Block_private.h>
+
+
+
+
+typedef void (^voidVoid)(void);
+
+voidVoid dummy;
+
+void callVoidVoid(voidVoid closure) {
+ closure();
+}
+
+
+voidVoid testRoutine(const char *whoami) {
+ __block int dumbo = strlen(whoami);
+ dummy = ^{
+ //printf("incring dumbo from %d\n", dumbo);
+ ++dumbo;
+ };
+
+
+ voidVoid copy = Block_copy(dummy);
+
+
+ return copy;
+}
+
+int main(int argc, char *argv[]) {
+ voidVoid array[100];
+ for (int i = 0; i < 100; ++i) {
+ array[i] = testRoutine(argv[0]);
+ array[i]();
+ }
+ for (int i = 0; i < 100; ++i) {
+ Block_release(array[i]);
+ }
+
+
+ printf("%s: success\n", argv[0]);
+ return 0;
+}
diff --git a/test/BlocksRuntime/byrefcopystack.c b/test/BlocksRuntime/byrefcopystack.c
new file mode 100644
index 000000000000..d119afa3668f
--- /dev/null
+++ b/test/BlocksRuntime/byrefcopystack.c
@@ -0,0 +1,41 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+//
+// byrefcopystack.m
+// testObjects
+//
+// Created by Blaine Garst on 5/13/08.
+//
+
+
+
+#include <stdio.h>
+#include <Block.h>
+
+// CONFIG rdar://6255170
+
+void (^bumpi)(void);
+int (^geti)(void);
+
+void setClosures() {
+ int __block i = 10;
+ bumpi = Block_copy(^{ ++i; });
+ geti = Block_copy(^{ return i; });
+}
+
+int main(int argc, char *argv[]) {
+ setClosures();
+ bumpi();
+ int i = geti();
+
+ if (i != 11) {
+ printf("*** %s didn't update i\n", argv[0]);
+ return 1;
+ }
+ printf("%s: success\n", argv[0]);
+ return 0;
+}
diff --git a/test/BlocksRuntime/byrefsanity.c b/test/BlocksRuntime/byrefsanity.c
new file mode 100644
index 000000000000..dfa16b0ddd6a
--- /dev/null
+++ b/test/BlocksRuntime/byrefsanity.c
@@ -0,0 +1,73 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// CONFIG
+
+
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <Block.h>
+
+int
+main(int argc, char *argv[])
+{
+ __block int var = 0;
+ void (^b)(void) = ^{ var++; };
+
+ //sanity(b);
+ b();
+ printf("%s: success!\n", argv[0]);
+ return 0;
+}
+
+
+#if 1
+/* replicated internal data structures: BEWARE, MAY CHANGE!!! */
+
+enum {
+ BLOCK_REFCOUNT_MASK = (0xffff),
+ BLOCK_NEEDS_FREE = (1 << 24),
+ BLOCK_HAS_COPY_DISPOSE = (1 << 25),
+ BLOCK_NO_COPY = (1 << 26), // interim byref: no copies allowed
+ BLOCK_IS_GC = (1 << 27),
+ BLOCK_IS_GLOBAL = (1 << 28),
+};
+
+struct byref_id {
+ struct byref_id *forwarding;
+ int flags;//refcount;
+ int size;
+ void (*byref_keep)(struct byref_id *dst, struct byref_id *src);
+ void (*byref_destroy)(struct byref_id *);
+ int var;
+};
+struct Block_basic2 {
+ void *isa;
+ int Block_flags; // int32_t
+ int Block_size; // XXX should be packed into Block_flags
+ void (*Block_invoke)(void *);
+ void (*Block_copy)(void *dst, void *src);
+ void (*Block_dispose)(void *);
+ struct byref_id *ref;
+};
+
+void sanity(void *arg) {
+ struct Block_basic2 *bb = (struct Block_basic2 *)arg;
+ if ( ! (bb->Block_flags & BLOCK_HAS_COPY_DISPOSE)) {
+ printf("missing copy/dispose helpers for byref data\n");
+ exit(1);
+ }
+ struct byref_id *ref = bb->ref;
+ if (ref->forwarding != ref) {
+ printf("forwarding pointer should be %p but is %p\n", ref, ref->forwarding);
+ exit(1);
+ }
+}
+#endif
+
+
+
diff --git a/test/BlocksRuntime/byrefstruct.c b/test/BlocksRuntime/byrefstruct.c
new file mode 100644
index 000000000000..a3dc44e2c36e
--- /dev/null
+++ b/test/BlocksRuntime/byrefstruct.c
@@ -0,0 +1,57 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// -*- mode:C; c-basic-offset:4; tab-width:4; intent-tabs-mode:nil; -*-
+// CONFIG
+
+#import <stdio.h>
+#import <stdlib.h>
+#import <string.h>
+
+typedef struct {
+ unsigned long ps[30];
+ int qs[30];
+} BobTheStruct;
+
+int main (int argc, const char * argv[]) {
+ __block BobTheStruct fiddly;
+ BobTheStruct copy;
+
+ void (^incrementFiddly)() = ^{
+ int i;
+ for(i=0; i<30; i++) {
+ fiddly.ps[i]++;
+ fiddly.qs[i]++;
+ }
+ };
+
+ memset(&fiddly, 0xA5, sizeof(fiddly));
+ memset(&copy, 0x2A, sizeof(copy));
+
+ int i;
+ for(i=0; i<30; i++) {
+ fiddly.ps[i] = i * i * i;
+ fiddly.qs[i] = -i * i * i;
+ }
+
+ copy = fiddly;
+ incrementFiddly();
+
+ if ( &copy == &fiddly ) {
+ printf("%s: struct wasn't copied.", argv[0]);
+ exit(1);
+ }
+ for(i=0; i<30; i++) {
+ //printf("[%d]: fiddly.ps: %lu, copy.ps: %lu, fiddly.qs: %d, copy.qs: %d\n", i, fiddly.ps[i], copy.ps[i], fiddly.qs[i], copy.qs[i]);
+ if ( (fiddly.ps[i] != copy.ps[i] + 1) || (fiddly.qs[i] != copy.qs[i] + 1) ) {
+ printf("%s: struct contents were not incremented.", argv[0]);
+ exit(1);
+ }
+ }
+
+ printf("%s: success\n", argv[0]);
+ return 0;
+}
diff --git a/test/BlocksRuntime/c99.c b/test/BlocksRuntime/c99.c
new file mode 100644
index 000000000000..8f31ab3fdfb8
--- /dev/null
+++ b/test/BlocksRuntime/c99.c
@@ -0,0 +1,20 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+//
+// c99.m
+//
+// CONFIG C99 rdar://problem/6399225
+
+#import <stdio.h>
+#import <stdlib.h>
+
+int main(int argc, char *argv[]) {
+ void (^blockA)(void) = ^ { ; };
+ blockA();
+ printf("%s: success\n", argv[0]);
+ exit(0);
+}
diff --git a/test/BlocksRuntime/cast.c b/test/BlocksRuntime/cast.c
new file mode 100644
index 000000000000..5bef2c19def5
--- /dev/null
+++ b/test/BlocksRuntime/cast.c
@@ -0,0 +1,37 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+/*
+ * cast.c
+ * testObjects
+ *
+ * Created by Blaine Garst on 2/17/09.
+ *
+ */
+
+// PURPOSE should allow casting of a Block reference to an arbitrary pointer and back
+// CONFIG open
+
+#include <stdio.h>
+
+
+
+int main(int argc, char *argv[]) {
+
+ void (^aBlock)(void);
+ int *ip;
+ char *cp;
+ double *dp;
+
+ ip = (int *)aBlock;
+ cp = (char *)aBlock;
+ dp = (double *)aBlock;
+ aBlock = (void (^)(void))ip;
+ aBlock = (void (^)(void))cp;
+ aBlock = (void (^)(void))dp;
+ printf("%s: success", argv[0]);
+ return 0;
+}
diff --git a/test/BlocksRuntime/constassign.c b/test/BlocksRuntime/constassign.c
new file mode 100644
index 000000000000..537cb2df0597
--- /dev/null
+++ b/test/BlocksRuntime/constassign.c
@@ -0,0 +1,28 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+//
+// constassign.c
+// bocktest
+//
+// Created by Blaine Garst on 3/21/08.
+//
+// shouldn't be able to assign to a const pointer
+// CONFIG error: assignment of read-only
+
+#import <stdio.h>
+
+void foo(void) { printf("I'm in foo\n"); }
+void bar(void) { printf("I'm in bar\n"); }
+
+int main(int argc, char *argv[]) {
+ void (*const fptr)(void) = foo;
+ void (^const blockA)(void) = ^ { printf("hello\n"); };
+ blockA = ^ { printf("world\n"); } ;
+ fptr = bar;
+ printf("%s: success\n", argv[0]);
+ return 0;
+}
diff --git a/test/BlocksRuntime/copy-block-literal-rdar6439600.c b/test/BlocksRuntime/copy-block-literal-rdar6439600.c
new file mode 100644
index 000000000000..6fa488eee4ff
--- /dev/null
+++ b/test/BlocksRuntime/copy-block-literal-rdar6439600.c
@@ -0,0 +1,29 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// CONFIG open rdar://6439600
+
+#import <stdio.h>
+#import <stdlib.h>
+
+#define NUMBER_OF_BLOCKS 100
+int main (int argc, const char * argv[]) {
+ int (^x[NUMBER_OF_BLOCKS])();
+ int i;
+
+ for(i=0; i<NUMBER_OF_BLOCKS; i++) x[i] = ^{ return i; };
+
+ for(i=0; i<NUMBER_OF_BLOCKS; i++) {
+ if (x[i]() != i) {
+ printf("%s: failure, %d != %d\n", argv[0], x[i](), i);
+ exit(1);
+ }
+ }
+
+ printf("%s: success\n", argv[0]);
+
+ return 0;
+}
diff --git a/test/BlocksRuntime/copyconstructor.C b/test/BlocksRuntime/copyconstructor.C
new file mode 100644
index 000000000000..626d33e80e80
--- /dev/null
+++ b/test/BlocksRuntime/copyconstructor.C
@@ -0,0 +1,85 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+#include <stdio.h>
+#include <Block.h>
+
+// CONFIG C++ rdar://6243400,rdar://6289367
+
+
+int constructors = 0;
+int destructors = 0;
+
+
+#define CONST const
+
+class TestObject
+{
+public:
+ TestObject(CONST TestObject& inObj);
+ TestObject();
+ ~TestObject();
+
+ TestObject& operator=(CONST TestObject& inObj);
+
+ int version() CONST { return _version; }
+private:
+ mutable int _version;
+};
+
+TestObject::TestObject(CONST TestObject& inObj)
+
+{
+ ++constructors;
+ _version = inObj._version;
+ //printf("%p (%d) -- TestObject(const TestObject&) called\n", this, _version);
+}
+
+
+TestObject::TestObject()
+{
+ _version = ++constructors;
+ //printf("%p (%d) -- TestObject() called\n", this, _version);
+}
+
+
+TestObject::~TestObject()
+{
+ //printf("%p -- ~TestObject() called\n", this);
+ ++destructors;
+}
+
+
+TestObject& TestObject::operator=(CONST TestObject& inObj)
+{
+ //printf("%p -- operator= called\n", this);
+ _version = inObj._version;
+ return *this;
+}
+
+
+
+void testRoutine() {
+ TestObject one;
+
+ void (^b)(void) = ^{ printf("my const copy of one is %d\n", one.version()); };
+}
+
+
+
+int main(int argc, char *argv[]) {
+ testRoutine();
+ if (constructors == 0) {
+ printf("No copy constructors!!!\n");
+ return 1;
+ }
+ if (constructors != destructors) {
+ printf("%d constructors but only %d destructors\n", constructors, destructors);
+ return 1;
+ }
+ printf("%s:success\n", argv[0]);
+ return 0;
+}
diff --git a/test/BlocksRuntime/copynull.c b/test/BlocksRuntime/copynull.c
new file mode 100644
index 000000000000..c49e499f3ab6
--- /dev/null
+++ b/test/BlocksRuntime/copynull.c
@@ -0,0 +1,37 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+/*
+ * copynull.c
+ * testObjects
+ *
+ * Created by Blaine Garst on 10/15/08.
+ *
+ */
+
+#import <stdio.h>
+#import <Block.h>
+#import <Block_private.h>
+
+// CONFIG rdar://6295848
+
+int main(int argc, char *argv[]) {
+
+ void (^block)(void) = (void (^)(void))0;
+ void (^blockcopy)(void) = Block_copy(block);
+
+ if (blockcopy != (void (^)(void))0) {
+ printf("whoops, somehow we copied NULL!\n");
+ return 1;
+ }
+ // make sure we can also
+ Block_release(blockcopy);
+ // and more secretly
+ //_Block_destroy(blockcopy);
+
+ printf("%s: success\n", argv[0]);
+ return 0;
+}
diff --git a/test/BlocksRuntime/dispatch_async.c b/test/BlocksRuntime/dispatch_async.c
new file mode 100644
index 000000000000..e3e517c54650
--- /dev/null
+++ b/test/BlocksRuntime/dispatch_async.c
@@ -0,0 +1,57 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+#include <CoreFoundation/CoreFoundation.h>
+
+#include <dispatch/dispatch.h>
+#include <unistd.h>
+//#import <Foundation/Foundation.h>
+#include <Block.h>
+
+// CONFIG rdar://problem/6371811
+
+const char *whoami = "nobody";
+
+void EnqueueStuff(dispatch_queue_t q)
+{
+ __block CFIndex counter;
+
+ // above call has a side effect: it works around:
+ // <rdar://problem/6225809> __block variables not implicitly imported into intermediate scopes
+ dispatch_async(q, ^{
+ counter = 0;
+ });
+
+
+ dispatch_async(q, ^{
+ //printf("outer block.\n");
+ counter++;
+ dispatch_async(q, ^{
+ //printf("inner block.\n");
+ counter--;
+ if(counter == 0) {
+ printf("%s: success\n", whoami);
+ exit(0);
+ }
+ });
+ if(counter == 0) {
+ printf("already done? inconceivable!\n");
+ exit(1);
+ }
+ });
+}
+
+int main (int argc, const char * argv[]) {
+ dispatch_queue_t q = dispatch_queue_create("queue", NULL);
+
+ whoami = argv[0];
+
+ EnqueueStuff(q);
+
+ dispatch_main();
+ printf("shouldn't get here\n");
+ return 1;
+}
diff --git a/test/BlocksRuntime/dispatch_call_Block_with_release.c b/test/BlocksRuntime/dispatch_call_Block_with_release.c
new file mode 100644
index 000000000000..9e06f69ba762
--- /dev/null
+++ b/test/BlocksRuntime/dispatch_call_Block_with_release.c
@@ -0,0 +1,31 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+#include <stdio.h>
+#include <Block.h>
+
+// CONFIG
+
+void callsomething(const char *format, int argument) {
+}
+
+void
+dispatch_call_Block_with_release2(void *block)
+{
+ void (^b)(void) = (void (^)(void))block;
+ b();
+ Block_release(b);
+}
+
+int main(int argc, char *argv[]) {
+ void (^b1)(void) = ^{ callsomething("argc is %d\n", argc); };
+ void (^b2)(void) = ^{ callsomething("hellow world\n", 0); }; // global block now
+
+ dispatch_call_Block_with_release2(Block_copy(b1));
+ dispatch_call_Block_with_release2(Block_copy(b2));
+ printf("%s: Success\n", argv[0]);
+ return 0;
+}
diff --git a/test/BlocksRuntime/fail.c b/test/BlocksRuntime/fail.c
new file mode 100644
index 000000000000..28dbc2d1521f
--- /dev/null
+++ b/test/BlocksRuntime/fail.c
@@ -0,0 +1,107 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+/*
+ * fail.c
+ * testObjects
+ *
+ * Created by Blaine Garst on 9/16/08.
+ *
+ */
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdbool.h>
+
+
+bool readfile(char *buffer, const char *from) {
+ int fd = open(from, 0);
+ if (fd < 0) return false;
+ int count = read(fd, buffer, 512);
+ if (count < 0) return false;
+ buffer[count] = 0; // zap newline
+ return true;
+}
+
+// basic idea, take compiler args, run compiler, and verify that expected failure matches any existing one
+
+int main(int argc, char *argv[]) {
+ if (argc == 1) return 0;
+ char *copy[argc+1]; // make a copy
+ // find and strip off -e "errorfile"
+ char *errorfile = NULL;
+ int counter = 0, i = 0;
+ for (i = 1; i < argc; ++i) { // skip 0 arg which is "fail"
+ if (!strncmp(argv[i], "-e", 2)) {
+ errorfile = argv[++i];
+ }
+ else {
+ copy[counter++] = argv[i];
+ }
+ }
+ copy[counter] = NULL;
+ pid_t child = fork();
+ char buffer[512];
+ if (child == 0) {
+ // in child
+ sprintf(buffer, "/tmp/errorfile_%d", getpid());
+ close(1);
+ int fd = creat(buffer, 0777);
+ if (fd != 1) {
+ fprintf(stderr, "didn't open custom error file %s as 1, got %d\n", buffer, fd);
+ exit(1);
+ }
+ close(2);
+ dup(1);
+ int result = execv(copy[0], copy);
+ exit(10);
+ }
+ if (child < 0) {
+ printf("fork failed\n");
+ exit(1);
+ }
+ int status = 0;
+ pid_t deadchild = wait(&status);
+ if (deadchild != child) {
+ printf("wait got %d instead of %d\n", deadchild, child);
+ exit(1);
+ }
+ if (WEXITSTATUS(status) == 0) {
+ printf("compiler exited normally, not good under these circumstances\n");
+ exit(1);
+ }
+ //printf("exit status of child %d was %d\n", child, WEXITSTATUS(status));
+ sprintf(buffer, "/tmp/errorfile_%d", child);
+ if (errorfile) {
+ //printf("ignoring error file: %s\n", errorfile);
+ char desired[512];
+ char got[512];
+ bool gotErrorFile = readfile(desired, errorfile);
+ bool gotOutput = readfile(got, buffer);
+ if (!gotErrorFile && gotOutput) {
+ printf("didn't read errorfile %s, it should have something from\n*****\n%s\n*****\nin it.\n",
+ errorfile, got);
+ exit(1);
+ }
+ else if (gotErrorFile && gotOutput) {
+ char *where = strstr(got, desired);
+ if (!where) {
+ printf("didn't find contents of %s in %s\n", errorfile, buffer);
+ exit(1);
+ }
+ }
+ else {
+ printf("errorfile %s and output %s inconsistent\n", errorfile, buffer);
+ exit(1);
+ }
+ }
+ unlink(buffer);
+ printf("success\n");
+ exit(0);
+}
+
diff --git a/test/BlocksRuntime/flagsisa.c b/test/BlocksRuntime/flagsisa.c
new file mode 100644
index 000000000000..5d4b2dcb4030
--- /dev/null
+++ b/test/BlocksRuntime/flagsisa.c
@@ -0,0 +1,21 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+#include <stdio.h>
+
+/* CONFIG rdar://6310599
+ */
+
+int main(int argc, char *argv[])
+{
+ __block int flags;
+ __block void *isa;
+
+ ^{ flags=1; isa = (void *)isa; };
+ printf("%s: success\n", argv[0]);
+ return 0;
+}
+
diff --git a/test/BlocksRuntime/globalexpression.c b/test/BlocksRuntime/globalexpression.c
new file mode 100644
index 000000000000..eeedd75e7078
--- /dev/null
+++ b/test/BlocksRuntime/globalexpression.c
@@ -0,0 +1,42 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// testfilerunner CONFIG
+
+#import <stdio.h>
+#import <Block.h>
+
+int global;
+
+void (^gblock)(int) = ^(int x){ global = x; };
+
+int main(int argc, char *argv[]) {
+ gblock(1);
+ if (global != 1) {
+ printf("%s: *** did not set global to 1\n", argv[0]);
+ return 1;
+ }
+ void (^gblockcopy)(int) = Block_copy(gblock);
+ if (gblockcopy != gblock) {
+ printf("global copy %p not a no-op %p\n", (void *)gblockcopy, (void *)gblock);
+ return 1;
+ }
+ Block_release(gblockcopy);
+ gblock(3);
+ if (global != 3) {
+ printf("%s: *** did not set global to 3\n", argv[0]);
+ return 1;
+ }
+ gblockcopy = Block_copy(gblock);
+ gblockcopy(5);
+ if (global != 5) {
+ printf("%s: *** did not set global to 5\n", argv[0]);
+ return 1;
+ }
+ printf("%s: Success!\n", argv[0]);
+ return 0;
+}
+
diff --git a/test/BlocksRuntime/goto.c b/test/BlocksRuntime/goto.c
new file mode 100644
index 000000000000..7e5b08adbe8e
--- /dev/null
+++ b/test/BlocksRuntime/goto.c
@@ -0,0 +1,34 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+/*
+ * goto.c
+ * testObjects
+ *
+ * Created by Blaine Garst on 10/17/08.
+ *
+ */
+
+// CONFIG rdar://6289031
+
+#include <stdio.h>
+
+int main(int argc, char *argv[])
+{
+ __block int val = 0;
+
+ ^{ val = 1; }();
+
+ if (val == 0) {
+ goto out_bad; // error: local byref variable val is in the scope of this goto
+ }
+
+ printf("%s: Success!\n", argv[0]);
+ return 0;
+out_bad:
+ printf("%s: val not updated!\n", argv[0]);
+ return 1;
+}
diff --git a/test/BlocksRuntime/hasdescriptor.c b/test/BlocksRuntime/hasdescriptor.c
new file mode 100644
index 000000000000..429adb9bdb14
--- /dev/null
+++ b/test/BlocksRuntime/hasdescriptor.c
@@ -0,0 +1,29 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+
+
+// CONFIG C
+
+#include <stdio.h>
+#include <Block_private.h>
+
+
+int main(int argc, char *argv[]) {
+ void (^inner)(void) = ^ { printf("argc was %d\n", argc); };
+ void (^outer)(void) = ^{
+ inner();
+ inner();
+ };
+ //printf("size of inner is %ld\n", Block_size(inner));
+ //printf("size of outer is %ld\n", Block_size(outer));
+ if (Block_size(inner) != Block_size(outer)) {
+ printf("not the same size, using old compiler??\n");
+ return 1;
+ }
+ printf("%s: Success\n", argv[0]);
+ return 0;
+}
diff --git a/test/BlocksRuntime/josh.C b/test/BlocksRuntime/josh.C
new file mode 100644
index 000000000000..dbc7369e8c39
--- /dev/null
+++ b/test/BlocksRuntime/josh.C
@@ -0,0 +1,32 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// CONFIG C++ GC RR open rdar://6347910
+
+
+
+struct MyStruct {
+ int something;
+};
+
+struct TestObject {
+
+ void test(void){
+ {
+ MyStruct first; // works
+ }
+ void (^b)(void) = ^{
+ MyStruct inner; // fails to compile!
+ };
+ }
+};
+
+
+
+int main(int argc, char *argv[]) {
+ printf("%s: Success\n", argv[0]);
+ return 0;
+}
diff --git a/test/BlocksRuntime/k-and-r.c b/test/BlocksRuntime/k-and-r.c
new file mode 100644
index 000000000000..16b9cc643b50
--- /dev/null
+++ b/test/BlocksRuntime/k-and-r.c
@@ -0,0 +1,33 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// -*- mode:C; c-basic-offset:4; tab-width:4; intent-tabs-mode:nil; -*-
+// CONFIG error: incompatible block pointer types assigning
+
+#import <stdio.h>
+#import <stdlib.h>
+
+int main(int argc, char *argv[]) {
+#ifndef __cplusplus
+ char (^rot13)();
+ rot13 = ^(char c) { return (char)(((c - 'a' + 13) % 26) + 'a'); };
+ char n = rot13('a');
+ char c = rot13('p');
+ if ( n != 'n' || c != 'c' ) {
+ printf("%s: rot13('a') returned %c, rot13('p') returns %c\n", argv[0], n, c);
+ exit(1);
+ }
+#else
+// yield characteristic error message for C++
+#error incompatible block pointer types assigning
+#endif
+#ifndef __clang__
+// yield characteristic error message for C++
+#error incompatible block pointer types assigning
+#endif
+ printf("%s: success\n", argv[0]);
+ exit(0);
+}
diff --git a/test/BlocksRuntime/large-struct.c b/test/BlocksRuntime/large-struct.c
new file mode 100644
index 000000000000..1867bd02dfab
--- /dev/null
+++ b/test/BlocksRuntime/large-struct.c
@@ -0,0 +1,51 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// -*- mode:C; c-basic-offset:4; tab-width:4; intent-tabs-mode:nil; -*-
+// CONFIG
+
+#import <stdio.h>
+#import <stdlib.h>
+#import <string.h>
+
+typedef struct {
+ unsigned long ps[30];
+ int qs[30];
+} BobTheStruct;
+
+int main (int argc, const char * argv[]) {
+ BobTheStruct inny;
+ BobTheStruct outty;
+ BobTheStruct (^copyStruct)(BobTheStruct);
+ int i;
+
+ memset(&inny, 0xA5, sizeof(inny));
+ memset(&outty, 0x2A, sizeof(outty));
+
+ for(i=0; i<30; i++) {
+ inny.ps[i] = i * i * i;
+ inny.qs[i] = -i * i * i;
+ }
+
+ copyStruct = ^(BobTheStruct aBigStruct){ return aBigStruct; }; // pass-by-value intrinsically copies the argument
+
+ outty = copyStruct(inny);
+
+ if ( &inny == &outty ) {
+ printf("%s: struct wasn't copied.", argv[0]);
+ exit(1);
+ }
+ for(i=0; i<30; i++) {
+ if ( (inny.ps[i] != outty.ps[i]) || (inny.qs[i] != outty.qs[i]) ) {
+ printf("%s: struct contents did not match.", argv[0]);
+ exit(1);
+ }
+ }
+
+ printf("%s: success\n", argv[0]);
+
+ return 0;
+}
diff --git a/test/BlocksRuntime/localisglobal.c b/test/BlocksRuntime/localisglobal.c
new file mode 100644
index 000000000000..75a79dff48ee
--- /dev/null
+++ b/test/BlocksRuntime/localisglobal.c
@@ -0,0 +1,42 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+/*
+ * localisglobal.c
+ * testObjects
+ *
+ * Created by Blaine Garst on 9/29/08.
+ *
+ * works in all configurations
+ * CONFIG rdar://6230297
+ */
+
+#include <stdio.h>
+
+void (^global)(void) = ^{ printf("hello world\n"); };
+
+int aresame(void *first, void *second) {
+ long *f = (long *)first;
+ long *s = (long *)second;
+ return *f == *s;
+}
+int main(int argc, char *argv[]) {
+ int i = 10;
+ void (^local)(void) = ^ { printf("hi %d\n", i); };
+ void (^localisglobal)(void) = ^ { printf("hi\n"); };
+
+ if (aresame(local, localisglobal)) {
+ printf("local block could be global, but isn't\n");
+ return 1;
+ }
+ if (!aresame(global, localisglobal)) {
+ printf("local block is not global, not stack, what is it??\n");
+ return 1;
+ }
+ printf("%s: success\n", argv[0]);
+ return 0;
+
+}
diff --git a/test/BlocksRuntime/macro.c b/test/BlocksRuntime/macro.c
new file mode 100644
index 000000000000..988c0689b8f8
--- /dev/null
+++ b/test/BlocksRuntime/macro.c
@@ -0,0 +1,14 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// CONFIG open rdar://6718399
+#include <Block.h>
+
+void foo() {
+ void (^bbb)(void) = Block_copy(^ {
+ int j, cnt;
+ });
+}
diff --git a/test/BlocksRuntime/makefile b/test/BlocksRuntime/makefile
new file mode 100644
index 000000000000..2734bcae35f5
--- /dev/null
+++ b/test/BlocksRuntime/makefile
@@ -0,0 +1,70 @@
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+CCDIR=/usr/bin
+#CCDIR=/Volumes/Keep/gcc/usr/bin
+
+all: std
+
+clean:
+ rm -fr *.dSYM *.o *-bin testfilerunner
+
+TFR = ~public/bin/testfilerunner
+
+testfilerunner: testfilerunner.h testfilerunner.m
+ gcc -fobjc-gc-only -g -arch x86_64 -arch i386 -std=gnu99 testfilerunner.m -o testfilerunner -framework Foundation
+
+tests:
+ grep CONFIG *.[cmCM] | $(TFR) $(CCDIR) --
+
+open:
+ grep CONFIG *.[cmCM] | $(TFR) $(CCDIR) -open --
+
+fast:
+ grep CONFIG *.[cmCM] | $(TFR) -fast $(CCDIR) --
+
+std:
+ grep CONFIG *.[cmCM] | $(TFR) --
+
+clang:
+ grep CONFIG *.[cmCM] | $(TFR) -clang -fast --
+
+fastd:
+ grep CONFIG *.[cmCM] | $(TFR) -fast --
+
+
+# Hack Alert: arguably most of the following belongs in libclosure's Makefile; sticking it here until I get around to grokking what goes on in that file.
+sudid:
+ @echo Enabling sudo: # Hack Alert: enable sudo first thing so we don't hang at the password prompt later
+ @sudo echo Thanks
+
+
+RootsDirectory ?= /tmp/
+# Note: the libsystem project (built by the libsystemroot target below) uses the ALTUSRLOCALLIBSYSTEM variable, so we use it here to maintain parity
+ALTUSRLOCALLIBSYSTEM ?= $(RootsDirectory)/alt-usr-local-lib-system/
+altusrlocallibsystem:
+ ditto /usr/local/lib/system $(ALTUSRLOCALLIBSYSTEM) # FIXME: conditionalize this copy
+
+
+# <rdar://problem/6456031> ER: option to not require extra privileges (-nosudo or somesuch)
+Buildit ?= ~rc/bin/buildit -rootsDirectory $(RootsDirectory) -arch i386 -arch ppc -arch x86_64
+blocksroot: sudid clean altusrlocallibsystem
+ sudo $(Buildit) ..
+ ditto $(RootsDirectory)/libclosure.roots/libclosure~dst/usr/local/lib/system $(ALTUSRLOCALLIBSYSTEM)
+
+
+LibsystemVersion ?= 121
+LibsystemPath ?= ~rc/Software/SnowLeopard/Projects/Libsystem/Libsystem-$(LibsystemVersion)
+LibsystemTmpPath ?= $(RootsDirectory)/Libsystem-$(LibsystemVersion)
+libsystemroot: blocksroot
+ ditto $(LibsystemPath) $(LibsystemTmpPath) # FIXME: conditionalize this copy
+ sudo ALTUSRLOCALLIBSYSTEM=$(ALTUSRLOCALLIBSYSTEM) $(Buildit) $(LibsystemTmpPath)
+
+
+# Defaults to product of the libsystemroot target but does not automatically rebuild that, make both targets if you want a fresh root
+LibsystemRootPath ?= $(RootsDirectory)/Libsystem-$(LibsystemVersion).roots/Libsystem-$(LibsystemVersion)~dst/usr/lib/
+roottests:
+ grep CONFIG *.[cmCM] | $(TFR) -dyld $(LibsystemRootPath) -- # FIXME: figure out if I can "call" the std target instead of duplicating it
+
diff --git a/test/BlocksRuntime/modglobal.c b/test/BlocksRuntime/modglobal.c
new file mode 100644
index 000000000000..562d5a5cc418
--- /dev/null
+++ b/test/BlocksRuntime/modglobal.c
@@ -0,0 +1,18 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+#include <stdio.h>
+
+// CONFIG
+
+int AGlobal;
+
+int main(int argc, char *argv[]) {
+ void (^f)(void) = ^ { AGlobal++; };
+
+ printf("%s: success\n", argv[0]);
+ return 0;
+
+}
diff --git a/test/BlocksRuntime/nestedimport.c b/test/BlocksRuntime/nestedimport.c
new file mode 100644
index 000000000000..e8066922fbba
--- /dev/null
+++ b/test/BlocksRuntime/nestedimport.c
@@ -0,0 +1,44 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+//
+// nestedimport.m
+// testObjects
+//
+// Created by Blaine Garst on 6/24/08.
+//
+// pure C nothing more needed
+// CONFIG
+
+
+#include <stdio.h>
+#include <stdlib.h>
+
+
+int Global = 0;
+
+void callVoidVoid(void (^closure)(void)) {
+ closure();
+}
+
+int main(int argc, char *argv[]) {
+ int i = 1;
+
+ void (^vv)(void) = ^{
+ if (argc > 0) {
+ callVoidVoid(^{ Global = i; });
+ }
+ };
+
+ i = 2;
+ vv();
+ if (Global != 1) {
+ printf("%s: error, Global not set to captured value\n", argv[0]);
+ exit(1);
+ }
+ printf("%s: success\n", argv[0]);
+ return 0;
+}
diff --git a/test/BlocksRuntime/nullblockisa.c b/test/BlocksRuntime/nullblockisa.c
new file mode 100644
index 000000000000..ba0282e82084
--- /dev/null
+++ b/test/BlocksRuntime/nullblockisa.c
@@ -0,0 +1,43 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+//
+// nullblockisa.m
+// testObjects
+//
+// Created by Blaine Garst on 9/24/08.
+//
+// CONFIG rdar://6244520
+
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <Block_private.h>
+
+
+void check(void (^b)(void)) {
+ struct _custom {
+ struct Block_layout layout;
+ struct Block_byref *innerp;
+ } *custom = (struct _custom *)(void *)(b);
+ //printf("block is at %p, size is %lx, inner is %p\n", (void *)b, Block_size(b), innerp);
+ if (custom->innerp->isa != (void *)NULL) {
+ printf("not a NULL __block isa\n");
+ exit(1);
+ }
+ return;
+}
+
+int main(int argc, char *argv[]) {
+
+ __block int i;
+
+ check(^{ printf("%d\n", ++i); });
+ printf("%s: success\n", argv[0]);
+ return 0;
+}
+
diff --git a/test/BlocksRuntime/objectRRGC.c b/test/BlocksRuntime/objectRRGC.c
new file mode 100644
index 000000000000..2cefea2afd3a
--- /dev/null
+++ b/test/BlocksRuntime/objectRRGC.c
@@ -0,0 +1,77 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+/*
+ * objectRRGC.c
+ * testObjects
+ *
+ * Created by Blaine Garst on 10/31/08.
+ *
+ * Test that the runtime honors the new callouts properly for retain/release and GC
+ * CON FIG C rdar://6175959
+ */
+
+
+
+#include <stdio.h>
+#include <Block_private.h>
+
+
+int AssignCalled = 0;
+int DisposeCalled = 0;
+
+// local copy instead of libSystem.B.dylib copy
+void _Block_object_assign(void *destAddr, const void *object, const int isWeak) {
+ //printf("_Block_object_assign(%p, %p, %d) called\n", destAddr, object, isWeak);
+ AssignCalled = 1;
+}
+
+void _Block_object_dispose(const void *object, const int isWeak) {
+ //printf("_Block_object_dispose(%p, %d) called\n", object, isWeak);
+ DisposeCalled = 1;
+}
+
+struct MyStruct {
+ long isa;
+ long field;
+};
+
+typedef struct MyStruct *__attribute__((NSObject)) MyStruct_t;
+
+int main(int argc, char *argv[]) {
+ // create a block
+ struct MyStruct X;
+ MyStruct_t xp = (MyStruct_t)&X;
+ xp->field = 10;
+ void (^myBlock)(void) = ^{ printf("field is %ld\n", xp->field); };
+ // should be a copy helper generated with a calls to above routines
+ // Lets find out!
+ struct Block_layout *bl = (struct Block_layout *)(void *)myBlock;
+ if ((bl->flags & BLOCK_HAS_DESCRIPTOR) != BLOCK_HAS_DESCRIPTOR) {
+ printf("using old runtime layout!\n");
+ return 1;
+ }
+ if ((bl->flags & BLOCK_HAS_COPY_DISPOSE) != BLOCK_HAS_COPY_DISPOSE) {
+ printf("no copy dispose!!!!\n");
+ return 1;
+ }
+ // call helper routines directly. These will, in turn, we hope, call the stubs above
+ long destBuffer[256];
+ //printf("destbuffer is at %p, block at %p\n", destBuffer, (void *)bl);
+ //printf("dump is %s\n", _Block_dump(myBlock));
+ bl->descriptor->copy(destBuffer, bl);
+ bl->descriptor->dispose(bl);
+ if (AssignCalled == 0) {
+ printf("did not call assign helper!\n");
+ return 1;
+ }
+ if (DisposeCalled == 0) {
+ printf("did not call dispose helper\n");
+ return 1;
+ }
+ printf("%s: Success!\n", argv[0]);
+ return 0;
+}
diff --git a/test/BlocksRuntime/objectassign.c b/test/BlocksRuntime/objectassign.c
new file mode 100644
index 000000000000..1c4f4841419e
--- /dev/null
+++ b/test/BlocksRuntime/objectassign.c
@@ -0,0 +1,76 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+/*
+ * objectassign.c
+ * testObjects
+ *
+ * Created by Blaine Garst on 10/28/08.
+ *
+ * This just tests that the compiler is issuing the proper helper routines
+ * CONFIG C rdar://6175959
+ */
+
+
+#include <stdio.h>
+#include <Block_private.h>
+
+
+int AssignCalled = 0;
+int DisposeCalled = 0;
+
+// local copy instead of libSystem.B.dylib copy
+void _Block_object_assign(void *destAddr, const void *object, const int isWeak) {
+ //printf("_Block_object_assign(%p, %p, %d) called\n", destAddr, object, isWeak);
+ AssignCalled = 1;
+}
+
+void _Block_object_dispose(const void *object, const int isWeak) {
+ //printf("_Block_object_dispose(%p, %d) called\n", object, isWeak);
+ DisposeCalled = 1;
+}
+
+struct MyStruct {
+ long isa;
+ long field;
+};
+
+typedef struct MyStruct *__attribute__((NSObject)) MyStruct_t;
+
+int main(int argc, char *argv[]) {
+ if (__APPLE_CC__ < 5627) {
+ printf("need compiler version %d, have %d\n", 5627, __APPLE_CC__);
+ return 0;
+ }
+ // create a block
+ struct MyStruct X;
+ MyStruct_t xp = (MyStruct_t)&X;
+ xp->field = 10;
+ void (^myBlock)(void) = ^{ printf("field is %ld\n", xp->field); };
+ // should be a copy helper generated with a calls to above routines
+ // Lets find out!
+ struct Block_layout *bl = (struct Block_layout *)(void *)myBlock;
+ if ((bl->flags & BLOCK_HAS_COPY_DISPOSE) != BLOCK_HAS_COPY_DISPOSE) {
+ printf("no copy dispose!!!!\n");
+ return 1;
+ }
+ // call helper routines directly. These will, in turn, we hope, call the stubs above
+ long destBuffer[256];
+ //printf("destbuffer is at %p, block at %p\n", destBuffer, (void *)bl);
+ //printf("dump is %s\n", _Block_dump(myBlock));
+ bl->descriptor->copy(destBuffer, bl);
+ bl->descriptor->dispose(bl);
+ if (AssignCalled == 0) {
+ printf("did not call assign helper!\n");
+ return 1;
+ }
+ if (DisposeCalled == 0) {
+ printf("did not call dispose helper\n");
+ return 1;
+ }
+ printf("%s: Success!\n", argv[0]);
+ return 0;
+}
diff --git a/test/BlocksRuntime/orbars.c b/test/BlocksRuntime/orbars.c
new file mode 100644
index 000000000000..18a9244452f1
--- /dev/null
+++ b/test/BlocksRuntime/orbars.c
@@ -0,0 +1,23 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+/*
+ * orbars.c
+ * testObjects
+ *
+ * Created by Blaine Garst on 9/17/08.
+ *
+ * CONFIG rdar://6276695 error: before ‘|’ token
+ */
+
+#include <stdio.h>
+
+int main(int argc, char *argv[]) {
+ int i = 10;
+ void (^b)(void) = ^(void){ | i | printf("hello world, %d\n", ++i); };
+ printf("%s: success :-(\n", argv[0]);
+ return 0;
+}
diff --git a/test/BlocksRuntime/rdar6396238.c b/test/BlocksRuntime/rdar6396238.c
new file mode 100644
index 000000000000..280415643a1a
--- /dev/null
+++ b/test/BlocksRuntime/rdar6396238.c
@@ -0,0 +1,32 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// CONFIG rdar://6396238
+
+#include <stdio.h>
+#include <stdlib.h>
+
+static int count = 0;
+
+void (^mkblock(void))(void)
+{
+ count++;
+ return ^{
+ count++;
+ };
+}
+
+int main (int argc, const char * argv[]) {
+ mkblock()();
+ if (count != 2) {
+ printf("%s: failure, 2 != %d\n", argv[0], count);
+ exit(1);
+ } else {
+ printf("%s: success\n", argv[0]);
+ exit(0);
+ }
+ return 0;
+}
diff --git a/test/BlocksRuntime/rdar6405500.c b/test/BlocksRuntime/rdar6405500.c
new file mode 100644
index 000000000000..1ab4624bcfce
--- /dev/null
+++ b/test/BlocksRuntime/rdar6405500.c
@@ -0,0 +1,29 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// CONFIG rdar://6405500
+
+#include <stdio.h>
+#include <stdlib.h>
+#import <dispatch/dispatch.h>
+#import <objc/objc-auto.h>
+
+int main (int argc, const char * argv[]) {
+ __block void (^blockFu)(size_t t);
+ blockFu = ^(size_t t){
+ if (t == 20) {
+ printf("%s: success\n", argv[0]);
+ exit(0);
+ } else
+ dispatch_async(dispatch_get_main_queue(), ^{ blockFu(20); });
+ };
+
+ dispatch_apply(10, dispatch_get_concurrent_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT), blockFu);
+
+ dispatch_main();
+ printf("shouldn't get here\n");
+ return 1;
+}
diff --git a/test/BlocksRuntime/rdar6414583.c b/test/BlocksRuntime/rdar6414583.c
new file mode 100644
index 000000000000..2ada04d3ddcc
--- /dev/null
+++ b/test/BlocksRuntime/rdar6414583.c
@@ -0,0 +1,31 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// CONFIG rdar://6414583
+
+// a smaller case of byrefcopyint
+
+#include <Block.h>
+#include <dispatch/dispatch.h>
+#include <stdio.h>
+
+int main(int argc, char *argv[]) {
+ __block int c = 1;
+
+ //printf("&c = %p - c = %i\n", &c, c);
+
+ int i;
+ for(i =0; i < 2; i++) {
+ dispatch_block_t block = Block_copy(^{ c = i; });
+
+ block();
+// printf("%i: &c = %p - c = %i\n", i, &c, c);
+
+ Block_release(block);
+ }
+ printf("%s: success\n", argv[0]);
+ return 0;
+}
diff --git a/test/BlocksRuntime/recursive-block.c b/test/BlocksRuntime/recursive-block.c
new file mode 100644
index 000000000000..454ad48267df
--- /dev/null
+++ b/test/BlocksRuntime/recursive-block.c
@@ -0,0 +1,55 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+#include <stdio.h>
+#include <Block.h>
+#include <Block_private.h>
+#include <stdlib.h>
+
+// CONFIG
+
+
+int cumulation = 0;
+
+int doSomething(int i) {
+ cumulation += i;
+ return cumulation;
+}
+
+void dirtyStack() {
+ int i = random();
+ int j = doSomething(i);
+ int k = doSomething(j);
+ doSomething(i + j + k);
+}
+
+typedef void (^voidVoid)(void);
+
+voidVoid testFunction() {
+ int i = random();
+ __block voidVoid inner = ^{ doSomething(i); };
+ //printf("inner, on stack, is %p\n", (void*)inner);
+ /*__block*/ voidVoid outer = ^{
+ //printf("will call inner block %p\n", (void *)inner);
+ inner();
+ };
+ //printf("outer looks like: %s\n", _Block_dump(outer));
+ voidVoid result = Block_copy(outer);
+ //Block_release(inner);
+ return result;
+}
+
+
+int main(int argc, char **argv) {
+ voidVoid block = testFunction();
+ dirtyStack();
+ block();
+ Block_release(block);
+
+ printf("%s: success\n", argv[0]);
+
+ return 0;
+}
diff --git a/test/BlocksRuntime/recursive-test.c b/test/BlocksRuntime/recursive-test.c
new file mode 100644
index 000000000000..f79914863121
--- /dev/null
+++ b/test/BlocksRuntime/recursive-test.c
@@ -0,0 +1,74 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// CONFIG open rdar://6416474
+// was rdar://5847976
+// was rdar://6348320
+
+#include <stdio.h>
+#include <Block.h>
+
+int verbose = 0;
+
+int main(int argc, char* argv[]) {
+
+ if (argc > 1) verbose = 1;
+
+ __block void (^recursive_local_block)(int);
+
+ if (verbose) printf("recursive_local_block is a local recursive block\n");
+ recursive_local_block = ^(int i) {
+ if (verbose) printf("%d\n", i);
+ if (i > 0) {
+ recursive_local_block(i - 1);
+ }
+ };
+
+ if (verbose) printf("recursive_local_block's address is %p, running it:\n", (void*)recursive_local_block);
+ recursive_local_block(5);
+
+ if (verbose) printf("Creating other_local_block: a local block that calls recursive_local_block\n");
+
+ void (^other_local_block)(int) = ^(int i) {
+ if (verbose) printf("other_local_block running\n");
+ recursive_local_block(i);
+ };
+
+ if (verbose) printf("other_local_block's address is %p, running it:\n", (void*)other_local_block);
+
+ other_local_block(5);
+
+#if __APPLE_CC__ >= 5627
+ if (verbose) printf("Creating other_copied_block: a Block_copy of a block that will call recursive_local_block\n");
+
+ void (^other_copied_block)(int) = Block_copy(^(int i) {
+ if (verbose) printf("other_copied_block running\n");
+ recursive_local_block(i);
+ });
+
+ if (verbose) printf("other_copied_block's address is %p, running it:\n", (void*)other_copied_block);
+
+ other_copied_block(5);
+#endif
+
+ __block void (^recursive_copy_block)(int);
+
+ if (verbose) printf("Creating recursive_copy_block: a Block_copy of a block that will call recursive_copy_block recursively\n");
+
+ recursive_copy_block = Block_copy(^(int i) {
+ if (verbose) printf("%d\n", i);
+ if (i > 0) {
+ recursive_copy_block(i - 1);
+ }
+ });
+
+ if (verbose) printf("recursive_copy_block's address is %p, running it:\n", (void*)recursive_copy_block);
+
+ recursive_copy_block(5);
+
+ printf("%s: Success\n", argv[0]);
+ return 0;
+}
diff --git a/test/BlocksRuntime/recursiveassign.c b/test/BlocksRuntime/recursiveassign.c
new file mode 100644
index 000000000000..f0070cbe5c93
--- /dev/null
+++ b/test/BlocksRuntime/recursiveassign.c
@@ -0,0 +1,44 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+/*
+ * recursiveassign.c
+ * testObjects
+ *
+ * Created by Blaine Garst on 12/3/08.
+ *
+ */
+
+// CONFIG rdar://6639533
+
+// The compiler is prefetching x->forwarding before evaluting code that recomputes forwarding and so the value goes to a place that is never seen again.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <Block.h>
+
+
+int main(int argc, char* argv[]) {
+
+ __block void (^recursive_copy_block)(int) = ^(int arg) { printf("got wrong Block\n"); exit(1); };
+
+
+ recursive_copy_block = Block_copy(^(int i) {
+ if (i > 0) {
+ recursive_copy_block(i - 1);
+ }
+ else {
+ printf("done!\n");
+ }
+ });
+
+
+ recursive_copy_block(5);
+
+ printf("%s: Success\n", argv[0]);
+ return 0;
+}
+
diff --git a/test/BlocksRuntime/reference.C b/test/BlocksRuntime/reference.C
new file mode 100644
index 000000000000..f86f11e86ce1
--- /dev/null
+++ b/test/BlocksRuntime/reference.C
@@ -0,0 +1,95 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+#import <Block.h>
+#import <stdio.h>
+#import <stdlib.h>
+
+// CONFIG C++
+
+int recovered = 0;
+
+
+
+int constructors = 0;
+int destructors = 0;
+
+#define CONST const
+
+class TestObject
+{
+public:
+ TestObject(CONST TestObject& inObj);
+ TestObject();
+ ~TestObject();
+
+ TestObject& operator=(CONST TestObject& inObj);
+
+ void test(void);
+
+ int version() CONST { return _version; }
+private:
+ mutable int _version;
+};
+
+TestObject::TestObject(CONST TestObject& inObj)
+
+{
+ ++constructors;
+ _version = inObj._version;
+ //printf("%p (%d) -- TestObject(const TestObject&) called", this, _version);
+}
+
+
+TestObject::TestObject()
+{
+ _version = ++constructors;
+ //printf("%p (%d) -- TestObject() called\n", this, _version);
+}
+
+
+TestObject::~TestObject()
+{
+ //printf("%p -- ~TestObject() called\n", this);
+ ++destructors;
+}
+
+#if 1
+TestObject& TestObject::operator=(CONST TestObject& inObj)
+{
+ //printf("%p -- operator= called", this);
+ _version = inObj._version;
+ return *this;
+}
+#endif
+
+void TestObject::test(void) {
+ void (^b)(void) = ^{ recovered = _version; };
+ void (^b2)(void) = Block_copy(b);
+ b2();
+ Block_release(b2);
+}
+
+
+
+void testRoutine() {
+ TestObject one;
+
+
+ one.test();
+}
+
+
+
+int main(int argc, char *argv[]) {
+ testRoutine();
+ if (recovered == 1) {
+ printf("%s: success\n", argv[0]);
+ exit(0);
+ }
+ printf("%s: *** didn't recover byref block variable\n", argv[0]);
+ exit(1);
+}
diff --git a/test/BlocksRuntime/rettypepromotion.c b/test/BlocksRuntime/rettypepromotion.c
new file mode 100644
index 000000000000..597eafe8b858
--- /dev/null
+++ b/test/BlocksRuntime/rettypepromotion.c
@@ -0,0 +1,36 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+/*
+ * rettypepromotion.c
+ * testObjects
+ *
+ * Created by Blaine Garst on 11/3/08.
+ *
+ */
+
+// CONFIG error:
+// C++ and C give different errors so we don't check for an exact match.
+// The error is that enum's are defined to be ints, always, even if defined with explicit long values
+
+
+#include <stdio.h>
+#include <stdlib.h>
+
+enum { LESS = -1, EQUAL, GREATER };
+
+void sortWithBlock(long (^comp)(void *arg1, void *arg2)) {
+}
+
+int main(int argc, char *argv[]) {
+ sortWithBlock(^(void *arg1, void *arg2) {
+ if (random()) return LESS;
+ if (random()) return EQUAL;
+ if (random()) return GREATER;
+ });
+ printf("%s: Success\n", argv[0]);
+ return 0;
+}
diff --git a/test/BlocksRuntime/returnfunctionptr.c b/test/BlocksRuntime/returnfunctionptr.c
new file mode 100644
index 000000000000..6c7df631f8db
--- /dev/null
+++ b/test/BlocksRuntime/returnfunctionptr.c
@@ -0,0 +1,23 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+
+// CONFIG rdar://6339747 but wasn't
+
+#include <stdio.h>
+
+int (*funcptr)(long);
+
+int (*(^b)(char))(long);
+
+int main(int argc, char *argv[]) {
+ // implicit is fine
+ b = ^(char x) { return funcptr; };
+ // explicit never parses
+ b = ^int (*(char x))(long) { return funcptr; };
+ printf("%s: Success\n", argv[0]);
+ return 0;
+}
diff --git a/test/BlocksRuntime/shorthandexpression.c b/test/BlocksRuntime/shorthandexpression.c
new file mode 100644
index 000000000000..bf4582072b48
--- /dev/null
+++ b/test/BlocksRuntime/shorthandexpression.c
@@ -0,0 +1,24 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+/*
+ * shorthandexpression.c
+ * testObjects
+ *
+ * Created by Blaine Garst on 9/16/08.
+ *
+ * CONFIG error:
+ */
+
+
+void foo() {
+ void (^b)(void) = ^(void)printf("hello world\n");
+}
+
+int main(int argc, char *argv[]) {
+ printf("%s: this shouldn't compile\n", argv[0]);
+ return 1;
+}
diff --git a/test/BlocksRuntime/sizeof.c b/test/BlocksRuntime/sizeof.c
new file mode 100644
index 000000000000..1f84fc16f38f
--- /dev/null
+++ b/test/BlocksRuntime/sizeof.c
@@ -0,0 +1,26 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+/*
+ * sizeof.c
+ * testObjects
+ *
+ * Created by Blaine Garst on 2/17/09.
+ *
+ */
+
+#include <stdio.h>
+
+// CONFIG error:
+
+int main(int argc, char *argv[]) {
+
+ void (^aBlock)(void) = ^{ printf("hellow world\n"); };
+
+ printf("the size of a block is %ld\n", sizeof(*aBlock));
+ printf("%s: success\n", argv[0]);
+ return 0;
+}
diff --git a/test/BlocksRuntime/small-struct.c b/test/BlocksRuntime/small-struct.c
new file mode 100644
index 000000000000..434f3c179f7e
--- /dev/null
+++ b/test/BlocksRuntime/small-struct.c
@@ -0,0 +1,45 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// -*- mode:C; c-basic-offset:4; tab-width:4; intent-tabs-mode:nil; -*-
+// CONFIG
+
+#import <stdio.h>
+#import <stdlib.h>
+#import <string.h>
+
+typedef struct {
+ int a;
+ int b;
+} MiniStruct;
+
+int main (int argc, const char * argv[]) {
+ MiniStruct inny;
+ MiniStruct outty;
+ MiniStruct (^copyStruct)(MiniStruct);
+
+ memset(&inny, 0xA5, sizeof(inny));
+ memset(&outty, 0x2A, sizeof(outty));
+
+ inny.a = 12;
+ inny.b = 42;
+
+ copyStruct = ^(MiniStruct aTinyStruct){ return aTinyStruct; }; // pass-by-value intrinsically copies the argument
+
+ outty = copyStruct(inny);
+
+ if ( &inny == &outty ) {
+ printf("%s: struct wasn't copied.", argv[0]);
+ exit(1);
+ }
+ if ( (inny.a != outty.a) || (inny.b != outty.b) ) {
+ printf("%s: struct contents did not match.", argv[0]);
+ exit(1);
+ }
+
+ printf("%s: success\n", argv[0]);
+ return 0;
+}
diff --git a/test/BlocksRuntime/structmember.c b/test/BlocksRuntime/structmember.c
new file mode 100644
index 000000000000..c451d3f348c9
--- /dev/null
+++ b/test/BlocksRuntime/structmember.c
@@ -0,0 +1,45 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+/*
+ * structmember.c
+ * testObjects
+ *
+ * Created by Blaine Garst on 9/30/08.
+ * CONFIG
+ */
+#include <Block.h>
+#include <Block_private.h>
+#include <stdio.h>
+
+// CONFIG
+
+int main(int argc, char *argv[]) {
+ struct stuff {
+ long int a;
+ long int b;
+ long int c;
+ } localStuff = { 10, 20, 30 };
+ int d;
+
+ void (^a)(void) = ^ { printf("d is %d", d); };
+ void (^b)(void) = ^ { printf("d is %d, localStuff.a is %lu", d, localStuff.a); };
+
+ unsigned nominalsize = Block_size(b) - Block_size(a);
+#if __cplusplus__
+ // need copy+dispose helper for C++ structures
+ nominalsize += 2*sizeof(void*);
+#endif
+ if ((Block_size(b) - Block_size(a)) != nominalsize) {
+ printf("sizeof a is %ld, sizeof b is %ld, expected %d\n", Block_size(a), Block_size(b), nominalsize);
+ printf("dump of b is %s\n", _Block_dump(b));
+ return 1;
+ }
+ printf("%s: Success\n", argv[0]);
+ return 0;
+}
+
+
diff --git a/test/BlocksRuntime/testfilerunner.h b/test/BlocksRuntime/testfilerunner.h
new file mode 100644
index 000000000000..d4e54f029047
--- /dev/null
+++ b/test/BlocksRuntime/testfilerunner.h
@@ -0,0 +1,110 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+//
+// testfilerunner.h
+// testObjects
+//
+// Created by Blaine Garst on 9/24/08.
+//
+
+#import <Cocoa/Cocoa.h>
+
+/*
+ variations:
+ four source types: C, ObjC, C++, ObjC++,
+ and for ObjC or ObjC++ we have
+ RR and GC capabilities
+ we assume C++ friendly includes for C/ObjC even if C++ isn't used
+
+
+ four compilers: C, ObjC, C++, ObjC++
+ and for ObjC or ObjC++ we can compile
+ RR, RR+GC, GC+RR, GC
+ although to test RR+GC we need to build a shell "main" in both modes
+ and/or run with GC disabled if possible.
+
+ To maximize coverage we mark files with capabilities and then ask them to be
+ compiled with each variation of compiler and option.
+ If the file doesn't have the capability it politely refuses.
+*/
+
+enum options {
+ Do64 = (1 << 0),
+ DoCPP = (1 << 1),
+ DoOBJC = (1 << 3),
+ DoGC = (1 << 4),
+ DoRR = (1 << 5),
+ DoRRGC = (1 << 6), // -fobjc-gc but main w/o so it runs in RR mode
+ DoGCRR = (1 << 7), // -fobjc-gc & run GC mode
+
+ //DoDashG = (1 << 8),
+ DoDashO = (1 << 9),
+ DoDashOs = (1 << 10),
+ DoDashO2 = (1 << 11),
+
+ DoC99 = (1 << 12), // -std=c99
+};
+
+
+@class TestFileExeGenerator;
+
+// this class will actually compile and/or run a target binary
+// XXX we don't track which dynamic libraries requested/used nor set them up
+@interface TestFileExe : NSObject {
+ NSPointerArray *compileLine;
+ int options;
+ bool shouldFail;
+ TestFileExeGenerator *generator;
+ __strong char *binaryName;
+ __strong char *sourceName;
+ __strong char *libraryPath;
+ __strong char *frameworkPath;
+}
+@property int options;
+@property(assign) NSPointerArray *compileLine;
+@property(assign) TestFileExeGenerator *generator;
+@property bool shouldFail;
+@property __strong char *binaryName;
+@property __strong char *sourceName;
+@property __strong char *libraryPath;
+@property __strong char *frameworkPath;
+- (bool) compileUnlessExists:(bool)skip;
+- (bool) run;
+@property(readonly) __strong char *radar;
+@end
+
+// this class generates an appropriate set of configurations to compile
+// we don't track which gcc we use but we should XXX
+@interface TestFileExeGenerator : NSObject {
+ bool hasObjC;
+ bool hasRR;
+ bool hasGC;
+ bool hasCPlusPlus;
+ bool wantsC99;
+ bool wants64;
+ bool wants32;
+ bool supposedToNotCompile;
+ bool open; // this problem is still open - e.g. unresolved
+ __strong char *radar; // for things already known to go wrong
+ __strong char *filename;
+ __strong char *compilerPath;
+ __strong char *errorString;
+ __strong char *warningString;
+ NSPointerArray *extraLibraries;
+}
+@property bool hasObjC, hasRR, hasGC, hasCPlusPlus, wantsC99, supposedToNotCompile, open, wants32, wants64;
+@property(assign) __strong char *radar;
+@property __strong char *filename;
+@property __strong char *compilerPath;
+@property __strong char *errorString;
+@property __strong char *warningString;
+- (TestFileExe *)lineForOptions:(int)options; // nil if no can do
++ (NSArray *)generatorsFromFILE:(FILE *)fd;
++ (NSArray *)generatorsFromPath:(NSString *)path;
+@end
+
+
diff --git a/test/BlocksRuntime/testfilerunner.m b/test/BlocksRuntime/testfilerunner.m
new file mode 100644
index 000000000000..459adf889f6e
--- /dev/null
+++ b/test/BlocksRuntime/testfilerunner.m
@@ -0,0 +1,805 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+//
+// testfilerunner.m
+// testObjects
+//
+// Created by Blaine Garst on 9/24/08.
+//
+
+#import "testfilerunner.h"
+#import <Foundation/Foundation.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdbool.h>
+
+bool Everything = false; // do it also with 3 levels of optimization
+bool DoClang = false;
+
+static bool isDirectory(char *path);
+static bool isExecutable(char *path);
+static bool isYounger(char *source, char *binary);
+static bool readErrorFile(char *buffer, const char *from);
+
+__strong char *gcstrcpy2(__strong const char *arg, char *endp) {
+ unsigned size = endp - arg + 1;
+ __strong char *result = NSAllocateCollectable(size, 0);
+ strncpy(result, arg, size);
+ result[size-1] = 0;
+ return result;
+}
+__strong char *gcstrcpy1(__strong char *arg) {
+ unsigned size = strlen(arg) + 1;
+ __strong char *result = NSAllocateCollectable(size, 0);
+ strncpy(result, arg, size);
+ result[size-1] = 0;
+ return result;
+}
+
+@implementation TestFileExe
+
+@synthesize options, compileLine, shouldFail, binaryName, sourceName;
+@synthesize generator;
+@synthesize libraryPath, frameworkPath;
+
+- (NSString *)description {
+ NSMutableString *result = [NSMutableString new];
+ if (shouldFail) [result appendString:@"fail"];
+ for (id x in compileLine) {
+ [result appendString:[NSString stringWithFormat:@" %s", (char *)x]];
+ }
+ return result;
+}
+
+- (__strong char *)radar {
+ return generator.radar;
+}
+
+- (bool) compileUnlessExists:(bool)skip {
+ if (shouldFail) {
+ printf("don't use this to compile anymore!\n");
+ return false;
+ }
+ if (skip && isExecutable(binaryName) && !isYounger(sourceName, binaryName)) return true;
+ int argc = [compileLine count];
+ char *argv[argc+1];
+ for (int i = 0; i < argc; ++i)
+ argv[i] = (char *)[compileLine pointerAtIndex:i];
+ argv[argc] = NULL;
+ pid_t child = fork();
+ if (child == 0) {
+ execv(argv[0], argv);
+ exit(10); // shouldn't happen
+ }
+ if (child < 0) {
+ printf("fork failed\n");
+ return false;
+ }
+ int status = 0;
+ pid_t deadchild = wait(&status);
+ if (deadchild != child) {
+ printf("wait got %d instead of %d\n", deadchild, child);
+ exit(1);
+ }
+ if (WEXITSTATUS(status) == 0) {
+ return true;
+ }
+ printf("run failed\n");
+ return false;
+}
+
+bool lookforIn(char *lookfor, const char *format, pid_t child) {
+ char buffer[512];
+ char got[512];
+ sprintf(buffer, format, child);
+ bool gotOutput = readErrorFile(got, buffer);
+ if (!gotOutput) {
+ printf("**** didn't get an output file %s to analyze!!??\n", buffer);
+ return false;
+ }
+ char *where = strstr(got, lookfor);
+ if (!where) {
+ printf("didn't find '%s' in output file %s\n", lookfor, buffer);
+ return false;
+ }
+ unlink(buffer);
+ return true;
+}
+
+- (bool) compileWithExpectedFailure {
+ if (!shouldFail) {
+ printf("Why am I being called?\n");
+ return false;
+ }
+ int argc = [compileLine count];
+ char *argv[argc+1];
+ for (int i = 0; i < argc; ++i)
+ argv[i] = (char *)[compileLine pointerAtIndex:i];
+ argv[argc] = NULL;
+ pid_t child = fork();
+ char buffer[512];
+ if (child == 0) {
+ // in child
+ sprintf(buffer, "/tmp/errorfile_%d", getpid());
+ close(1);
+ int fd = creat(buffer, 0777);
+ if (fd != 1) {
+ fprintf(stderr, "didn't open custom error file %s as 1, got %d\n", buffer, fd);
+ exit(1);
+ }
+ close(2);
+ dup(1);
+ int result = execv(argv[0], argv);
+ exit(10);
+ }
+ if (child < 0) {
+ printf("fork failed\n");
+ return false;
+ }
+ int status = 0;
+ pid_t deadchild = wait(&status);
+ if (deadchild != child) {
+ printf("wait got %d instead of %d\n", deadchild, child);
+ exit(11);
+ }
+ if (WIFEXITED(status)) {
+ if (WEXITSTATUS(status) == 0) {
+ return false;
+ }
+ }
+ else {
+ printf("***** compiler borked/ICEd/died unexpectedly (status %x)\n", status);
+ return false;
+ }
+ char *error = generator.errorString;
+
+ if (!error) return true;
+#if 0
+ char got[512];
+ sprintf(buffer, "/tmp/errorfile_%d", child);
+ bool gotOutput = readErrorFile(got, buffer);
+ if (!gotOutput) {
+ printf("**** didn't get an error file %s to analyze!!??\n", buffer);
+ return false;
+ }
+ char *where = strstr(got, error);
+ if (!where) {
+ printf("didn't find '%s' in error file %s\n", error, buffer);
+ return false;
+ }
+ unlink(buffer);
+#else
+ if (!lookforIn(error, "/tmp/errorfile_%d", child)) return false;
+#endif
+ return true;
+}
+
+- (bool) run {
+ if (shouldFail) return true;
+ if (sizeof(long) == 4 && options & Do64) {
+ return true; // skip 64-bit tests
+ }
+ int argc = 1;
+ char *argv[argc+1];
+ argv[0] = binaryName;
+ argv[argc] = NULL;
+ pid_t child = fork();
+ if (child == 0) {
+ // set up environment
+ char lpath[1024];
+ char fpath[1024];
+ char *myenv[3];
+ int counter = 0;
+ if (libraryPath) {
+ sprintf(lpath, "DYLD_LIBRARY_PATH=%s", libraryPath);
+ myenv[counter++] = lpath;
+ }
+ if (frameworkPath) {
+ sprintf(fpath, "DYLD_FRAMEWORK_PATH=%s", frameworkPath);
+ myenv[counter++] = fpath;
+ }
+ myenv[counter] = NULL;
+ if (generator.warningString) {
+ // set up stdout/stderr
+ char outfile[1024];
+ sprintf(outfile, "/tmp/stdout_%d", getpid());
+ close(2);
+ close(1);
+ creat(outfile, 0700);
+ dup(1);
+ }
+ execve(argv[0], argv, myenv);
+ exit(10); // shouldn't happen
+ }
+ if (child < 0) {
+ printf("fork failed\n");
+ return false;
+ }
+ int status = 0;
+ pid_t deadchild = wait(&status);
+ if (deadchild != child) {
+ printf("wait got %d instead of %d\n", deadchild, child);
+ exit(1);
+ }
+ if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
+ if (generator.warningString) {
+ if (!lookforIn(generator.warningString, "/tmp/stdout_%d", child)) return false;
+ }
+ return true;
+ }
+ printf("**** run failed for %s\n", binaryName);
+ return false;
+}
+
+@end
+
+@implementation TestFileExeGenerator
+@synthesize filename, compilerPath, errorString;
+@synthesize hasObjC, hasRR, hasGC, hasCPlusPlus, wantsC99, supposedToNotCompile, open, wants32, wants64;
+@synthesize radar;
+@synthesize warningString;
+
+- (void)setFilename:(__strong char *)name {
+ filename = gcstrcpy1(name);
+}
+- (void)setCompilerPath:(__strong char *)name {
+ compilerPath = gcstrcpy1(name);
+}
+
+- (void)forMostThings:(NSMutableArray *)lines options:(int)options {
+ TestFileExe *item = nil;
+ item = [self lineForOptions:options];
+ if (item) [lines addObject:item];
+ item = [self lineForOptions:options|Do64];
+ if (item) [lines addObject:item];
+ item = [self lineForOptions:options|DoCPP];
+ if (item) [lines addObject:item];
+ item = [self lineForOptions:options|Do64|DoCPP];
+ if (item) [lines addObject:item];
+}
+
+/*
+ DoDashG = (1 << 8),
+ DoDashO = (1 << 9),
+ DoDashOs = (1 << 10),
+ DoDashO2 = (1 << 11),
+*/
+
+- (void)forAllThings:(NSMutableArray *)lines options:(int)options {
+ [self forMostThings:lines options:options];
+ if (!Everything) {
+ return;
+ }
+ // now do it with three explicit optimization flags
+ [self forMostThings:lines options:options | DoDashO];
+ [self forMostThings:lines options:options | DoDashOs];
+ [self forMostThings:lines options:options | DoDashO2];
+}
+
+- (NSArray *)allLines {
+ NSMutableArray *result = [NSMutableArray new];
+ TestFileExe *item = nil;
+
+ int options = 0;
+ [self forAllThings:result options:0];
+ [self forAllThings:result options:DoOBJC | DoRR];
+ [self forAllThings:result options:DoOBJC | DoGC];
+ [self forAllThings:result options:DoOBJC | DoGCRR];
+ //[self forAllThings:result options:DoOBJC | DoRRGC];
+
+ return result;
+}
+
+- (void)addLibrary:(const char *)dashLSomething {
+ if (!extraLibraries) {
+ extraLibraries = [NSPointerArray pointerArrayWithOptions:
+ NSPointerFunctionsStrongMemory |
+ NSPointerFunctionsCStringPersonality];
+ }
+ [extraLibraries addPointer:(void *)dashLSomething];
+}
+
+- (TestFileExe *)lineForOptions:(int)options { // nil if no can do
+ if (hasObjC && !(options & DoOBJC)) return nil;
+ if (hasCPlusPlus && !(options & DoCPP)) return nil;
+ if (hasObjC) {
+ if (!hasGC && (options & (DoGC|DoGCRR))) return nil; // not smart enough
+ if (!hasRR && (options & (DoRR|DoRRGC))) return nil;
+ }
+ NSPointerArray *pa = [NSPointerArray pointerArrayWithOptions:
+ NSPointerFunctionsStrongMemory |
+ NSPointerFunctionsCStringPersonality];
+ // construct path
+ char path[512];
+ path[0] = 0;
+ if (!compilerPath) compilerPath = "/usr/bin";
+ if (compilerPath) {
+ strcat(path, compilerPath);
+ strcat(path, "/");
+ }
+ if (options & DoCPP) {
+ strcat(path, DoClang ? "clang++" : "g++-4.2");
+ }
+ else {
+ strcat(path, DoClang ? "clang" : "gcc-4.2");
+ }
+ [pa addPointer:gcstrcpy1(path)];
+ if (options & DoOBJC) {
+ if (options & DoCPP) {
+ [pa addPointer:"-ObjC++"];
+ }
+ else {
+ [pa addPointer:"-ObjC"];
+ }
+ }
+ [pa addPointer:"-g"];
+ if (options & DoDashO) [pa addPointer:"-O"];
+ else if (options & DoDashO2) [pa addPointer:"-O2"];
+ else if (options & DoDashOs) [pa addPointer:"-Os"];
+ if (wantsC99 && (! (options & DoCPP))) {
+ [pa addPointer:"-std=c99"];
+ [pa addPointer:"-fblocks"];
+ }
+ [pa addPointer:"-arch"];
+ [pa addPointer: (options & Do64) ? "x86_64" : "i386"];
+
+ if (options & DoOBJC) {
+ switch (options & (DoRR|DoGC|DoGCRR|DoRRGC)) {
+ case DoRR:
+ break;
+ case DoGC:
+ [pa addPointer:"-fobjc-gc-only"];
+ break;
+ case DoGCRR:
+ [pa addPointer:"-fobjc-gc"];
+ break;
+ case DoRRGC:
+ printf("DoRRGC unsupported right now\n");
+ [pa addPointer:"-c"];
+ return nil;
+ }
+ [pa addPointer:"-framework"];
+ [pa addPointer:"Foundation"];
+ }
+ [pa addPointer:gcstrcpy1(filename)];
+ [pa addPointer:"-o"];
+
+ path[0] = 0;
+ strcat(path, filename);
+ strcat(path, ".");
+ strcat(path, (options & Do64) ? "64" : "32");
+ if (options & DoOBJC) {
+ switch (options & (DoRR|DoGC|DoGCRR|DoRRGC)) {
+ case DoRR: strcat(path, "-rr"); break;
+ case DoGC: strcat(path, "-gconly"); break;
+ case DoGCRR: strcat(path, "-gcrr"); break;
+ case DoRRGC: strcat(path, "-rrgc"); break;
+ }
+ }
+ if (options & DoCPP) strcat(path, "++");
+ if (options & DoDashO) strcat(path, "-O");
+ else if (options & DoDashO2) strcat(path, "-O2");
+ else if (options & DoDashOs) strcat(path, "-Os");
+ if (wantsC99) strcat(path, "-C99");
+ strcat(path, DoClang ? "-clang" : "-gcc");
+ strcat(path, "-bin");
+ TestFileExe *result = [TestFileExe new];
+ result.binaryName = gcstrcpy1(path); // could snarf copy in pa
+ [pa addPointer:result.binaryName];
+ for (id cString in extraLibraries) {
+ [pa addPointer:cString];
+ }
+
+ result.sourceName = gcstrcpy1(filename); // could snarf copy in pa
+ result.compileLine = pa;
+ result.options = options;
+ result.shouldFail = supposedToNotCompile;
+ result.generator = self;
+ return result;
+}
+
++ (NSArray *)generatorsFromPath:(NSString *)path {
+ FILE *fp = fopen([path fileSystemRepresentation], "r");
+ if (fp == NULL) return nil;
+ NSArray *result = [self generatorsFromFILE:fp];
+ fclose(fp);
+ return result;
+}
+
+#define LOOKFOR "CON" "FIG"
+
+char *__strong parseRadar(char *line) {
+ line = strstr(line, "rdar:"); // returns beginning
+ char *endp = line + strlen("rdar:");
+ while (*endp && *endp != ' ' && *endp != '\n')
+ ++endp;
+ return gcstrcpy2(line, endp);
+}
+
+- (void)parseLibraries:(const char *)line {
+ start:
+ line = strstr(line, "-l");
+ char *endp = (char *)line + 2;
+ while (*endp && *endp != ' ' && *endp != '\n')
+ ++endp;
+ [self addLibrary:gcstrcpy2(line, endp)];
+ if (strstr(endp, "-l")) {
+ line = endp;
+ goto start;
+ }
+}
+
++ (TestFileExeGenerator *)generatorFromLine:(char *)line filename:(char *)filename {
+ TestFileExeGenerator *item = [TestFileExeGenerator new];
+ item.filename = gcstrcpy1(filename);
+ if (strstr(line, "GC")) item.hasGC = true;
+ if (strstr(line, "RR")) item.hasRR = true;
+ if (strstr(line, "C++")) item.hasCPlusPlus = true;
+ if (strstr(line, "-C99")) {
+ item.wantsC99 = true;
+ }
+ if (strstr(line, "64")) item.wants64 = true;
+ if (strstr(line, "32")) item.wants32 = true;
+ if (strstr(line, "-l")) [item parseLibraries:line];
+ if (strstr(line, "open")) item.open = true;
+ if (strstr(line, "FAIL")) item.supposedToNotCompile = true; // old
+ // compile time error
+ if (strstr(line, "error:")) {
+ item.supposedToNotCompile = true;
+ // zap newline
+ char *error = strstr(line, "error:") + strlen("error:");
+ // make sure we have something before the newline
+ char *newline = strstr(error, "\n");
+ if (newline && ((newline-error) > 1)) {
+ *newline = 0;
+ item.errorString = gcstrcpy1(strstr(line, "error:") + strlen("error: "));
+ }
+ }
+ // run time warning
+ if (strstr(line, "runtime:")) {
+ // zap newline
+ char *error = strstr(line, "runtime:") + strlen("runtime:");
+ // make sure we have something before the newline
+ char *newline = strstr(error, "\n");
+ if (newline && ((newline-error) > 1)) {
+ *newline = 0;
+ item.warningString = gcstrcpy1(strstr(line, "runtime:") + strlen("runtime:"));
+ }
+ }
+ if (strstr(line, "rdar:")) item.radar = parseRadar(line);
+ if (item.hasGC || item.hasRR) item.hasObjC = true;
+ if (!item.wants32 && !item.wants64) { // give them both if they ask for neither
+ item.wants32 = item.wants64 = true;
+ }
+ return item;
+}
+
++ (NSArray *)generatorsFromFILE:(FILE *)fp {
+ NSMutableArray *result = [NSMutableArray new];
+ // pretend this is a grep LOOKFOR *.[cmCM][cmCM] input
+ // look for
+ // filename: ... LOOKFOR [GC] [RR] [C++] [FAIL ...]
+ char buf[512];
+ while (fgets(buf, 512, fp)) {
+ char *config = strstr(buf, LOOKFOR);
+ if (!config) continue;
+ char *filename = buf;
+ char *end = strchr(buf, ':');
+ *end = 0;
+ [result addObject:[self generatorFromLine:config filename:filename]];
+ }
+ return result;
+}
+
++ (TestFileExeGenerator *)generatorFromFilename:(char *)filename {
+ FILE *fp = fopen(filename, "r");
+ if (!fp) {
+ printf("didn't open %s!!\n", filename);
+ return nil;
+ }
+ char buf[512];
+ while (fgets(buf, 512, fp)) {
+ char *config = strstr(buf, LOOKFOR);
+ if (!config) continue;
+ fclose(fp);
+ return [self generatorFromLine:config filename:filename];
+ }
+ fclose(fp);
+ // guess from filename
+ char *ext = strrchr(filename, '.');
+ if (!ext) return nil;
+ TestFileExeGenerator *result = [TestFileExeGenerator new];
+ result.filename = gcstrcpy1(filename);
+ if (!strncmp(ext, ".m", 2)) {
+ result.hasObjC = true;
+ result.hasRR = true;
+ result.hasGC = true;
+ }
+ else if (!strcmp(ext, ".c")) {
+ ;
+ }
+ else if (!strcmp(ext, ".M") || !strcmp(ext, ".mm")) {
+ result.hasObjC = true;
+ result.hasRR = true;
+ result.hasGC = true;
+ result.hasCPlusPlus = true;
+ }
+ else if (!strcmp(ext, ".cc")
+ || !strcmp(ext, ".cp")
+ || !strcmp(ext, ".cxx")
+ || !strcmp(ext, ".cpp")
+ || !strcmp(ext, ".CPP")
+ || !strcmp(ext, ".c++")
+ || !strcmp(ext, ".C")) {
+ result.hasCPlusPlus = true;
+ }
+ else {
+ printf("unknown extension, file %s ignored\n", filename);
+ result = nil;
+ }
+ return result;
+
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"%s: %s%s%s%s%s%s",
+ filename,
+ LOOKFOR,
+ hasGC ? " GC" : "",
+ hasRR ? " RR" : "",
+ hasCPlusPlus ? " C++" : "",
+ wantsC99 ? "C99" : "",
+ supposedToNotCompile ? " FAIL" : ""];
+}
+
+@end
+
+void printDetails(NSArray *failures, const char *whatAreThey) {
+ if ([failures count]) {
+ NSMutableString *output = [NSMutableString new];
+ printf("%s:\n", whatAreThey);
+ for (TestFileExe *line in failures) {
+ printf("%s", line.binaryName);
+ char *radar = line.generator.radar;
+ if (radar)
+ printf(" (due to %s?),", radar);
+ printf(" recompile via:\n%s\n\n", line.description.UTF8String);
+ }
+ printf("\n");
+ }
+}
+
+void help(const char *whoami) {
+ printf("Usage: %s [-fast] [-e] [-dyld librarypath] [gcc4.2dir] [-- | source1 ...]\n", whoami);
+ printf(" -fast don't recompile if binary younger than source\n");
+ printf(" -open only run tests that are thought to still be unresolved\n");
+ printf(" -clang use the clang and clang++ compilers\n");
+ printf(" -e compile all variations also with -Os, -O2, -O3\n");
+ printf(" -dyld p override DYLD_LIBRARY_PATH and DYLD_FRAMEWORK_PATH to p when running tests\n");
+ printf(" <compilerpath> directory containing gcc-4.2 (or clang) that you wish to use to compile the tests\n");
+ printf(" -- assume stdin is a grep CON" "FIG across the test sources\n");
+ printf(" otherwise treat each remaining argument as a single test file source\n");
+ printf("%s will compile and run individual test files under a variety of compilers, c, obj-c, c++, and objc++\n", whoami);
+ printf(" .c files are compiled with all four compilers\n");
+ printf(" .m files are compiled with objc and objc++ compilers\n");
+ printf(" .C files are compiled with c++ and objc++ compilers\n");
+ printf(" .M files are compiled only with the objc++ compiler\n");
+ printf("(actually all forms of extensions recognized by the compilers are honored, .cc, .c++ etc.)\n");
+ printf("\nTest files should run to completion with no output and exit (return) 0 on success.\n");
+ printf("Further they should be able to be compiled and run with GC on or off and by the C++ compilers\n");
+ printf("A line containing the string CON" "FIG within the source enables restrictions to the above assumptions\n");
+ printf("and other options.\n");
+ printf("Following CON" "FIG the string\n");
+ printf(" C++ restricts the test to only be run by c++ and objc++ compilers\n");
+ printf(" GC restricts the test to only be compiled and run with GC on\n");
+ printf(" RR (retain/release) restricts the test to only be compiled and run with GC off\n");
+ printf("Additionally,\n");
+ printf(" -C99 restricts the C versions of the test to -fstd=c99 -fblocks\n");
+ printf(" -O adds the -O optimization level\n");
+ printf(" -O2 adds the -O2 optimization level\n");
+ printf(" -Os adds the -Os optimization level\n");
+ printf("Files that are known to exhibit unresolved problems can provide the term \"open\" and this can");
+ printf("in turn allow highlighting of fixes that have regressed as well as identify that fixes are now available.\n");
+ printf("Files that exhibit known bugs may provide\n");
+ printf(" rdar://whatever such that if they fail the rdar will get cited\n");
+ printf("Files that are expected to fail to compile should provide, as their last token sequence,\n");
+ printf(" error:\n");
+ printf(" or error: substring to match.\n");
+ printf("Files that are expected to produce a runtime error message should provide, as their last token sequence,\n");
+ printf(" warning: string to match\n");
+ printf("\n%s will compile and run all configurations of the test files and report a summary at the end. Good luck.\n", whoami);
+ printf(" Blaine Garst blaine@apple.com\n");
+}
+
+int main(int argc, char *argv[]) {
+ printf("running on %s-bit architecture\n", sizeof(long) == 4 ? "32" : "64");
+ char *compilerDir = "/usr/bin";
+ NSMutableArray *generators = [NSMutableArray new];
+ bool doFast = false;
+ bool doStdin = false;
+ bool onlyOpen = false;
+ char *libraryPath = getenv("DYLD_LIBRARY_PATH");
+ char *frameworkPath = getenv("DYLD_FRAMEWORK_PATH");
+ // process options
+ while (argc > 1) {
+ if (!strcmp(argv[1], "-fast")) {
+ doFast = true;
+ --argc;
+ ++argv;
+ }
+ else if (!strcmp(argv[1], "-dyld")) {
+ doFast = true;
+ --argc;
+ ++argv;
+ frameworkPath = argv[1];
+ libraryPath = argv[1];
+ --argc;
+ ++argv;
+ }
+ else if (!strcmp(argv[1], "-open")) {
+ onlyOpen = true;
+ --argc;
+ ++argv;
+ }
+ else if (!strcmp(argv[1], "-clang")) {
+ DoClang = true;
+ --argc;
+ ++argv;
+ }
+ else if (!strcmp(argv[1], "-e")) {
+ Everything = true;
+ --argc;
+ ++argv;
+ }
+ else if (!strcmp(argv[1], "--")) {
+ doStdin = true;
+ --argc;
+ ++argv;
+ }
+ else if (!strcmp(argv[1], "-")) {
+ help(argv[0]);
+ return 1;
+ }
+ else if (argc > 1 && isDirectory(argv[1])) {
+ compilerDir = argv[1];
+ ++argv;
+ --argc;
+ }
+ else
+ break;
+ }
+ // process remaining arguments, or stdin
+ if (argc == 1) {
+ if (doStdin)
+ generators = (NSMutableArray *)[TestFileExeGenerator generatorsFromFILE:stdin];
+ else {
+ help(argv[0]);
+ return 1;
+ }
+ }
+ else while (argc > 1) {
+ TestFileExeGenerator *generator = [TestFileExeGenerator generatorFromFilename:argv[1]];
+ if (generator) [generators addObject:generator];
+ ++argv;
+ --argc;
+ }
+ // see if we can generate all possibilities
+ NSMutableArray *failureToCompile = [NSMutableArray new];
+ NSMutableArray *failureToFailToCompile = [NSMutableArray new];
+ NSMutableArray *failureToRun = [NSMutableArray new];
+ NSMutableArray *successes = [NSMutableArray new];
+ for (TestFileExeGenerator *generator in generators) {
+ //NSLog(@"got %@", generator);
+ if (onlyOpen && !generator.open) {
+ //printf("skipping resolved test %s\n", generator.filename);
+ continue; // skip closed if onlyOpen
+ }
+ if (!onlyOpen && generator.open) {
+ //printf("skipping open test %s\n", generator.filename);
+ continue; // skip open if not asked for onlyOpen
+ }
+ generator.compilerPath = compilerDir;
+ NSArray *tests = [generator allLines];
+ for (TestFileExe *line in tests) {
+ line.frameworkPath = frameworkPath; // tell generators about it instead XXX
+ line.libraryPath = libraryPath; // tell generators about it instead XXX
+ if ([line shouldFail]) {
+ if (doFast) continue; // don't recompile & don't count as success
+ if ([line compileWithExpectedFailure]) {
+ [successes addObject:line];
+ }
+ else
+ [failureToFailToCompile addObject:line];
+ }
+ else if ([line compileUnlessExists:doFast]) {
+ if ([line run]) {
+ printf("%s ran successfully\n", line.binaryName);
+ [successes addObject:line];
+ }
+ else {
+ [failureToRun addObject:line];
+ }
+ }
+ else {
+ [failureToCompile addObject:line];
+ }
+ }
+ }
+ printf("\n--- results ---\n\n%lu successes\n%lu unexpected compile failures\n%lu failure to fail to compile errors\n%lu run failures\n",
+ [successes count], [failureToCompile count], [failureToFailToCompile count], [failureToRun count]);
+ printDetails(failureToCompile, "unexpected compile failures");
+ printDetails(failureToFailToCompile, "should have failed to compile but didn't failures");
+ printDetails(failureToRun, "run failures");
+
+ if (onlyOpen && [successes count]) {
+ NSMutableSet *radars = [NSMutableSet new];
+ printf("The following tests ran successfully suggesting that they are now resolved:\n");
+ for (TestFileExe *line in successes) {
+ printf("%s\n", line.binaryName);
+ if (line.radar) [radars addObject:line.generator];
+ }
+ if ([radars count]) {
+ printf("The following radars may be resolved:\n");
+ for (TestFileExeGenerator *line in radars) {
+ printf("%s\n", line.radar);
+ }
+ }
+ }
+
+ return [failureToCompile count] + [failureToRun count];
+}
+
+#include <sys/stat.h>
+
+static bool isDirectory(char *path) {
+ struct stat statb;
+ int retval = stat(path, &statb);
+ if (retval != 0) return false;
+ if (statb.st_mode & S_IFDIR) return true;
+ return false;
+}
+
+static bool isExecutable(char *path) {
+ struct stat statb;
+ int retval = stat(path, &statb);
+ if (retval != 0) return false;
+ if (!(statb.st_mode & S_IFREG)) return false;
+ if (statb.st_mode & S_IXUSR) return true;
+ return false;
+}
+
+static bool isYounger(char *source, char *binary) {
+ struct stat statb;
+ int retval = stat(binary, &statb);
+ if (retval != 0) return true; // if doesn't exit, lie
+
+ struct stat stata;
+ retval = stat(source, &stata);
+ if (retval != 0) return true; // we're hosed
+ // the greater the timeval the younger it is
+ if (stata.st_mtimespec.tv_sec > statb.st_mtimespec.tv_sec) return true;
+ if (stata.st_mtimespec.tv_nsec > statb.st_mtimespec.tv_nsec) return true;
+ return false;
+}
+
+static bool readErrorFile(char *buffer, const char *from) {
+ int fd = open(from, 0);
+ if (fd < 0) {
+ printf("didn't open %s, (might not have been created?)\n", buffer);
+ return false;
+ }
+ int count = read(fd, buffer, 512);
+ if (count < 1) {
+ printf("read error on %s\n", buffer);
+ return false;
+ }
+ buffer[count-1] = 0; // zap newline
+ return true;
+}
diff --git a/test/BlocksRuntime/varargs-bad-assign.c b/test/BlocksRuntime/varargs-bad-assign.c
new file mode 100644
index 000000000000..b978668b95c0
--- /dev/null
+++ b/test/BlocksRuntime/varargs-bad-assign.c
@@ -0,0 +1,44 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// -*- mode:C; c-basic-offset:4; tab-width:4; intent-tabs-mode:nil; -*-
+// HACK ALERT: gcc and g++ give different errors, referencing the line number to ensure that it checks for the right error; MUST KEEP IN SYNC WITH THE TEST
+// CONFIG 27: error:
+
+#import <stdio.h>
+#import <stdlib.h>
+#import <string.h>
+#import <stdarg.h>
+
+
+int main (int argc, const char * argv[]) {
+ int (^sumn)(int n, ...);
+ int six = 0;
+
+ sumn = ^(int a, int b, int n, ...){
+ int result = 0;
+ va_list numbers;
+ int i;
+
+ va_start(numbers, n);
+ for (i = 0 ; i < n ; i++) {
+ result += va_arg(numbers, int);
+ }
+ va_end(numbers);
+
+ return result;
+ };
+
+ six = sumn(3, 1, 2, 3);
+
+ if ( six != 6 ) {
+ printf("%s: Expected 6 but got %d\n", argv[0], six);
+ exit(1);
+ }
+
+ printf("%s: success\n", argv[0]);
+ return 0;
+}
diff --git a/test/BlocksRuntime/varargs.c b/test/BlocksRuntime/varargs.c
new file mode 100644
index 000000000000..01affc76e68c
--- /dev/null
+++ b/test/BlocksRuntime/varargs.c
@@ -0,0 +1,39 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// -*- mode:C; c-basic-offset:4; tab-width:4; intent-tabs-mode:nil; -*-
+// CONFIG
+
+#import <stdio.h>
+#import <stdlib.h>
+#import <string.h>
+#import <stdarg.h>
+
+
+int main (int argc, const char * argv[]) {
+ int (^sumn)(int n, ...) = ^(int n, ...){
+ int result = 0;
+ va_list numbers;
+ int i;
+
+ va_start(numbers, n);
+ for (i = 0 ; i < n ; i++) {
+ result += va_arg(numbers, int);
+ }
+ va_end(numbers);
+
+ return result;
+ };
+ int six = sumn(3, 1, 2, 3);
+
+ if ( six != 6 ) {
+ printf("%s: Expected 6 but got %d\n", argv[0], six);
+ exit(1);
+ }
+
+ printf("%s: success\n", argv[0]);
+ return 0;
+}
diff --git a/test/BlocksRuntime/variadic.c b/test/BlocksRuntime/variadic.c
new file mode 100644
index 000000000000..1d80657e9886
--- /dev/null
+++ b/test/BlocksRuntime/variadic.c
@@ -0,0 +1,66 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+/*
+ * variadic.c
+ * testObjects
+ *
+ * Created by Blaine Garst on 2/17/09.
+ *
+ */
+
+// PURPOSE Test that variadic arguments compile and work for Blocks
+// CONFIG
+
+#include <stdarg.h>
+#include <stdio.h>
+
+int main(int argc, char *argv[]) {
+
+ long (^addthem)(const char *, ...) = ^long (const char *format, ...){
+ va_list argp;
+ const char *p;
+ int i;
+ char c;
+ double d;
+ long result = 0;
+ va_start(argp, format);
+ //printf("starting...\n");
+ for (p = format; *p; p++) switch (*p) {
+ case 'i':
+ i = va_arg(argp, int);
+ //printf("i: %d\n", i);
+ result += i;
+ break;
+ case 'd':
+ d = va_arg(argp, double);
+ //printf("d: %g\n", d);
+ result += (int)d;
+ break;
+ case 'c':
+ c = va_arg(argp, int);
+ //printf("c: '%c'\n", c);
+ result += c;
+ break;
+ }
+ //printf("...done\n\n");
+ return result;
+ };
+ long testresult = addthem("ii", 10, 20);
+ if (testresult != 30) {
+ printf("got wrong result: %ld\n", testresult);
+ return 1;
+ }
+ testresult = addthem("idc", 30, 40.0, 'a');
+ if (testresult != (70+'a')) {
+ printf("got different wrong result: %ld\n", testresult);
+ return 1;
+ }
+ printf("%s: Success\n", argv[0]);
+ return 0;
+}
+
+
diff --git a/test/BlocksRuntime/voidarg.c b/test/BlocksRuntime/voidarg.c
new file mode 100644
index 000000000000..a8f034b47c10
--- /dev/null
+++ b/test/BlocksRuntime/voidarg.c
@@ -0,0 +1,27 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+/*
+ * voidarg.c
+ * testObjects
+ *
+ * Created by Blaine Garst on 2/17/09.
+ *
+ */
+
+// PURPOSE should complain about missing 'void' but both GCC and clang are supporting K&R instead
+// CONFIG open error:
+
+#include <stdio.h>
+
+int Global;
+
+void (^globalBlock)() = ^{ ++Global; }; // should be void (^gb)(void) = ...
+
+int main(int argc, char *argv[]) {
+ printf("%s: success", argv[0]);
+ return 0;
+}
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
new file mode 100644
index 000000000000..2ceb86463ae0
--- /dev/null
+++ b/test/CMakeLists.txt
@@ -0,0 +1,65 @@
+configure_lit_site_cfg(
+ ${CMAKE_CURRENT_SOURCE_DIR}/lit.common.configured.in
+ ${CMAKE_CURRENT_BINARY_DIR}/lit.common.configured)
+
+# BlocksRuntime and builtins testsuites are not yet ported to lit.
+# add_subdirectory(BlocksRuntime)
+# add_subdirectory(builtins)
+
+set(SANITIZER_COMMON_LIT_TEST_DEPS)
+# When ANDROID, we build tests with the host compiler (i.e. CMAKE_C_COMPILER),
+# and run tests with tools from the host toolchain.
+if(NOT ANDROID)
+ if(NOT COMPILER_RT_STANDALONE_BUILD)
+ # Use LLVM utils and Clang from the same build tree.
+ list(APPEND SANITIZER_COMMON_LIT_TEST_DEPS
+ clang clang-headers FileCheck count not llvm-nm llvm-symbolizer
+ compiler-rt-headers)
+ if (COMPILER_RT_HAS_PROFILE)
+ list(APPEND SANITIZER_COMMON_LIT_TEST_DEPS profile)
+ endif()
+ endif()
+ if(UNIX)
+ list(APPEND SANITIZER_COMMON_LIT_TEST_DEPS SanitizerLintCheck)
+ endif()
+endif()
+
+# Run sanitizer tests only if we're sure that clang would produce
+# working binaries.
+if(COMPILER_RT_CAN_EXECUTE_TESTS)
+ if(COMPILER_RT_HAS_ASAN)
+ add_subdirectory(asan)
+ endif()
+ if(COMPILER_RT_HAS_DFSAN)
+ add_subdirectory(dfsan)
+ endif()
+ if(COMPILER_RT_HAS_LSAN)
+ add_subdirectory(lsan)
+ endif()
+ if(COMPILER_RT_HAS_MSAN)
+ add_subdirectory(msan)
+ endif()
+ if(COMPILER_RT_HAS_PROFILE)
+ add_subdirectory(profile)
+ endif()
+ if(COMPILER_RT_HAS_SANITIZER_COMMON)
+ add_subdirectory(sanitizer_common)
+ endif()
+ if(COMPILER_RT_HAS_TSAN)
+ add_subdirectory(tsan)
+ endif()
+ if(COMPILER_RT_HAS_UBSAN)
+ add_subdirectory(ubsan)
+ endif()
+endif()
+
+if(COMPILER_RT_STANDALONE_BUILD)
+ # Now that we've traversed all the directories and know all the lit testsuites,
+ # introduce a rule to run to run all of them.
+ get_property(LLVM_LIT_TESTSUITES GLOBAL PROPERTY LLVM_LIT_TESTSUITES)
+ get_property(LLVM_LIT_DEPENDS GLOBAL PROPERTY LLVM_LIT_DEPENDS)
+ add_lit_target(check-all
+ "Running all regression tests"
+ ${LLVM_LIT_TESTSUITES}
+ DEPENDS ${LLVM_LIT_DEPENDS})
+endif()
diff --git a/test/asan/CMakeLists.txt b/test/asan/CMakeLists.txt
new file mode 100644
index 000000000000..14f7f506da51
--- /dev/null
+++ b/test/asan/CMakeLists.txt
@@ -0,0 +1,156 @@
+set(ASAN_LIT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
+
+set(ASAN_TESTSUITES)
+
+macro(get_bits_for_arch arch bits)
+ if (${arch} STREQUAL "arm" OR
+ ${arch} STREQUAL "i386" OR
+ ${arch} STREQUAL "i686" OR
+ ${arch} STREQUAL "mips")
+ set(bits 32)
+ elseif (${arch} STREQUAL "aarch64" OR
+ ${arch} STREQUAL "x86_64" OR
+ ${arch} STREQUAL "mips64")
+ set(bits 64)
+ else()
+ message(FATAL_ERROR "Unknown target architecture: ${arch}")
+ endif()
+endmacro()
+
+# TODO: merge with non-ANDROID case
+if(ANDROID)
+ foreach(arch ${ASAN_SUPPORTED_ARCH})
+ set(ASAN_TEST_TARGET_CC ${CMAKE_CXX_COMPILER})
+ set(ASAN_TEST_TARGET_CFLAGS ${COMPILER_RT_TEST_COMPILER_CFLAGS})
+ set(ASAN_TEST_CONFIG_SUFFIX "-${arch}-android")
+ get_bits_for_arch(${arch} ASAN_TEST_BITS)
+ set(ASAN_TEST_DYNAMIC True)
+ set(ASAN_TEST_TARGET_ARCH "${arch}-android")
+ string(TOUPPER ${arch} ARCH_UPPER_CASE)
+ set(CONFIG ${ARCH_UPPER_CASE}AndroidConfig)
+ configure_lit_site_cfg(
+ ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in
+ ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG}/lit.site.cfg
+ )
+ list(APPEND ASAN_TESTSUITES
+ ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG})
+ endforeach()
+
+else() # Not Android
+
+ if(CAN_TARGET_arm)
+ # This is only true if we are cross-compiling.
+ # Build all tests with host compiler and use host tools.
+ set(ASAN_TEST_TARGET_CC ${COMPILER_RT_TEST_COMPILER})
+ set(ASAN_TEST_TARGET_CFLAGS ${COMPILER_RT_TEST_COMPILER_CFLAGS})
+ set(ASAN_TEST_CONFIG_SUFFIX "-arm-linux")
+ set(ASAN_TEST_BITS "32")
+ set(ASAN_TEST_DYNAMIC False)
+ configure_lit_site_cfg(
+ ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in
+ ${CMAKE_CURRENT_BINARY_DIR}/ARMLinuxConfig/lit.site.cfg
+ )
+ list(APPEND ASAN_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/ARMLinuxConfig)
+ endif()
+
+ if(CAN_TARGET_aarch64)
+ # This is only true if we are cross-compiling.
+ # Build all tests with host compiler and use host tools.
+ set(ASAN_TEST_TARGET_CC ${COMPILER_RT_TEST_COMPILER})
+ set(ASAN_TEST_TARGET_CFLAGS ${COMPILER_RT_TEST_COMPILER_CFLAGS})
+ set(ASAN_TEST_CONFIG_SUFFIX "-aarch64-linux")
+ set(ASAN_TEST_BITS "64")
+ set(ASAN_TEST_DYNAMIC False)
+ configure_lit_site_cfg(
+ ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in
+ ${CMAKE_CURRENT_BINARY_DIR}/AArch64LinuxConfig/lit.site.cfg
+ )
+ list(APPEND ASAN_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/AArch64LinuxConfig)
+ endif()
+
+ if(CAN_TARGET_x86_64 OR CAN_TARGET_powerpc64 OR CAN_TARGET_mips64 OR CAN_TARGET_mips64el)
+ set(ASAN_TEST_CONFIG_SUFFIX "64")
+ set(ASAN_TEST_BITS "64")
+ set(ASAN_TEST_TARGET_CFLAGS ${TARGET_64_BIT_CFLAGS})
+ set(ASAN_TEST_DYNAMIC False)
+ configure_lit_site_cfg(
+ ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in
+ ${CMAKE_CURRENT_BINARY_DIR}/64bitConfig/lit.site.cfg
+ )
+ list(APPEND ASAN_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/64bitConfig)
+ if(COMPILER_RT_BUILD_SHARED_ASAN)
+ set(ASAN_TEST_CONFIG_SUFFIX "64-Dynamic")
+ set(ASAN_TEST_DYNAMIC True)
+ configure_lit_site_cfg(
+ ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in
+ ${CMAKE_CURRENT_BINARY_DIR}/64bitConfig-dynamic/lit.site.cfg)
+ list(APPEND ASAN_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/64bitConfig-dynamic)
+ endif()
+ endif()
+
+ if(CAN_TARGET_i386)
+ set(ASAN_TEST_CONFIG_SUFFIX "32")
+ set(ASAN_TEST_BITS "32")
+ set(ASAN_TEST_TARGET_CFLAGS ${TARGET_32_BIT_CFLAGS})
+ set(ASAN_TEST_DYNAMIC False)
+ set(ASAN_TEST_TARGET_ARCH "i386")
+ configure_lit_site_cfg(
+ ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in
+ ${CMAKE_CURRENT_BINARY_DIR}/32bitConfig/lit.site.cfg
+ )
+ list(APPEND ASAN_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/32bitConfig)
+ if(COMPILER_RT_BUILD_SHARED_ASAN)
+ set(ASAN_TEST_CONFIG_SUFFIX "32-Dynamic")
+ set(ASAN_TEST_DYNAMIC True)
+ configure_lit_site_cfg(
+ ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in
+ ${CMAKE_CURRENT_BINARY_DIR}/32bitConfig-dynamic/lit.site.cfg)
+ list(APPEND ASAN_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/32bitConfig-dynamic)
+ endif()
+ endif()
+
+ if(CAN_TARGET_mips OR CAN_TARGET_mipsel)
+ set(ASAN_TEST_CONFIG_SUFFIX "32")
+ set(ASAN_TEST_BITS "32")
+ set(ASAN_TEST_TARGET_CFLAGS ${TARGET_32_BIT_CFLAGS})
+ set(ASAN_TEST_DYNAMIC False)
+ configure_lit_site_cfg(
+ ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in
+ ${CMAKE_CURRENT_BINARY_DIR}/32bitConfig/lit.site.cfg
+ )
+ list(APPEND ASAN_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/32bitConfig)
+ if(COMPILER_RT_BUILD_SHARED_ASAN)
+ set(ASAN_TEST_CONFIG_SUFFIX "32-Dynamic")
+ set(ASAN_TEST_DYNAMIC True)
+ configure_lit_site_cfg(
+ ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in
+ ${CMAKE_CURRENT_BINARY_DIR}/32bitConfig-dynamic/lit.site.cfg)
+ list(APPEND ASAN_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/32bitConfig-dynamic)
+ endif()
+ endif()
+endif() # Not Android
+
+if(COMPILER_RT_INCLUDE_TESTS)
+ configure_lit_site_cfg(
+ ${CMAKE_CURRENT_SOURCE_DIR}/Unit/lit.site.cfg.in
+ ${CMAKE_CURRENT_BINARY_DIR}/Unit/lit.site.cfg)
+endif()
+
+set(ASAN_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS})
+if(COMPILER_RT_STANDALONE_BUILD)
+ add_executable(FileCheck IMPORTED GLOBAL)
+ set_property(TARGET FileCheck PROPERTY IMPORTED_LOCATION ${LLVM_TOOLS_BINARY_DIR}/FileCheck)
+ list(APPEND ASAN_TEST_DEPS FileCheck)
+else()
+ list(APPEND ASAN_TEST_DEPS asan)
+endif()
+
+# FIXME: support unit test in the android test runner
+if(COMPILER_RT_INCLUDE_TESTS AND NOT ANDROID)
+ list(APPEND ASAN_TEST_DEPS AsanUnitTests)
+ list(APPEND ASAN_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/Unit)
+endif()
+add_lit_testsuite(check-asan "Running the AddressSanitizer tests"
+ ${ASAN_TESTSUITES}
+ DEPENDS ${ASAN_TEST_DEPS})
+set_target_properties(check-asan PROPERTIES FOLDER "ASan tests")
diff --git a/test/asan/TestCases/Android/coverage-android.cc b/test/asan/TestCases/Android/coverage-android.cc
new file mode 100644
index 000000000000..071a2e3e1faa
--- /dev/null
+++ b/test/asan/TestCases/Android/coverage-android.cc
@@ -0,0 +1,67 @@
+// Test for direct coverage writing with dlopen.
+
+// Test normal exit.
+// RUN: %clangxx_asan -mllvm -asan-coverage=1 -DSHARED %s -shared -o %T/libcoverage_android_test_1.so -fPIC
+// RUN: %clangxx_asan -mllvm -asan-coverage=1 -DSO_DIR=\"%device\" %s -o %t
+
+// RUN: adb shell rm -rf %device/coverage-android
+// RUN: rm -rf %T/coverage-android
+
+// RUN: adb shell mkdir -p %device/coverage-android/direct
+// RUN: mkdir -p %T/coverage-android/direct
+// RUN: ASAN_OPTIONS=coverage=1:coverage_direct=1:coverage_dir=%device/coverage-android/direct:verbosity=1 %run %t
+// RUN: adb pull %device/coverage-android/direct %T/coverage-android/direct
+// RUN: ls; pwd
+// RUN: cd %T/coverage-android/direct
+// RUN: %sancov rawunpack *.sancov.raw
+// RUN: %sancov print *.sancov |& FileCheck %s
+
+
+// Test sudden death.
+// RUN: %clangxx_asan -mllvm -asan-coverage=1 -DSHARED -DKILL %s -shared -o %T/libcoverage_android_test_1.so -fPIC
+// RUN: %clangxx_asan -mllvm -asan-coverage=1 -DSO_DIR=\"%device\" %s -o %t
+
+// RUN: adb shell rm -rf %device/coverage-android-kill
+// RUN: rm -rf %T/coverage-android-kill
+
+// RUN: adb shell mkdir -p %device/coverage-android-kill/direct
+// RUN: mkdir -p %T/coverage-android-kill/direct
+// RUN: ASAN_OPTIONS=coverage=1:coverage_direct=1:coverage_dir=%device/coverage-android-kill/direct:verbosity=1 not %run %t
+// RUN: adb pull %device/coverage-android-kill/direct %T/coverage-android-kill/direct
+// RUN: ls; pwd
+// RUN: cd %T/coverage-android-kill/direct
+// RUN: %sancov rawunpack *.sancov.raw
+// RUN: %sancov print *.sancov |& FileCheck %s
+
+#include <assert.h>
+#include <dlfcn.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <signal.h>
+
+#ifdef SHARED
+extern "C" {
+void bar() {
+ printf("bar\n");
+#ifdef KILL
+ kill(getpid(), SIGKILL);
+#endif
+}
+}
+#else
+
+int main(int argc, char **argv) {
+ fprintf(stderr, "PID: %d\n", getpid());
+ void *handle1 =
+ dlopen(SO_DIR "/libcoverage_android_test_1.so", RTLD_LAZY);
+ assert(handle1);
+ void (*bar1)() = (void (*)())dlsym(handle1, "bar");
+ assert(bar1);
+ bar1();
+
+ return 0;
+}
+#endif
+
+// CHECK: 2 PCs total
diff --git a/test/asan/TestCases/Android/lit.local.cfg b/test/asan/TestCases/Android/lit.local.cfg
new file mode 100644
index 000000000000..42513dd3aa61
--- /dev/null
+++ b/test/asan/TestCases/Android/lit.local.cfg
@@ -0,0 +1,11 @@
+def getRoot(config):
+ if not config.parent:
+ return config
+ return getRoot(config.parent)
+
+root = getRoot(config)
+
+if root.android != "TRUE":
+ config.unsupported = True
+
+config.substitutions.append( ("%device", "/data/local/tmp/Output") )
diff --git a/test/asan/TestCases/Darwin/asan_gen_prefixes.cc b/test/asan/TestCases/Darwin/asan_gen_prefixes.cc
new file mode 100644
index 000000000000..13363ac47255
--- /dev/null
+++ b/test/asan/TestCases/Darwin/asan_gen_prefixes.cc
@@ -0,0 +1,14 @@
+// Make sure __asan_gen_* strings have the correct prefixes on Darwin
+// ("L" in __TEXT,__cstring, "l" in __TEXT,__const
+
+// RUN: %clang_asan %s -S -o %t.s
+// RUN: cat %t.s | FileCheck %s || exit 1
+
+int x, y, z;
+int main() { return 0; }
+// CHECK: .section{{.*}}__TEXT,__const
+// CHECK: l___asan_gen_
+// CHECK: .section{{.*}}__TEXT,__cstring,cstring_literals
+// CHECK: L___asan_gen_
+// CHECK: L___asan_gen_
+// CHECK: L___asan_gen_
diff --git a/test/asan/TestCases/Darwin/cstring_literals_regtest.mm b/test/asan/TestCases/Darwin/cstring_literals_regtest.mm
new file mode 100644
index 000000000000..bcb15d8f39b0
--- /dev/null
+++ b/test/asan/TestCases/Darwin/cstring_literals_regtest.mm
@@ -0,0 +1,23 @@
+// Regression test for
+// https://code.google.com/p/address-sanitizer/issues/detail?id=274.
+
+// RUN: %clang_asan %s -framework Foundation -o %t
+// RUN: %run %t 2>&1 | FileCheck %s
+#import <Foundation/Foundation.h>
+
+#include <stdio.h>
+
+int main() {
+ NSString* version_file = @"MAJOR=35\n";
+ int major = 0, minor = 0, build = 0, patch = 0;
+ NSScanner* scanner = [NSScanner scannerWithString:version_file];
+ NSString *res = nil;
+ if ([scanner scanString:@"MAJOR=" intoString:nil] &&
+ [scanner scanInt:&major]) {
+ res = [NSString stringWithFormat:@"%d.%d.%d.%d",
+ major, minor, build, patch];
+ }
+ printf("%s\n", [res UTF8String]);
+ // CHECK: 35.0.0.0
+ return 0;
+}
diff --git a/test/asan/TestCases/Darwin/dyld_insert_libraries_reexec.cc b/test/asan/TestCases/Darwin/dyld_insert_libraries_reexec.cc
new file mode 100644
index 000000000000..b1bb4567f900
--- /dev/null
+++ b/test/asan/TestCases/Darwin/dyld_insert_libraries_reexec.cc
@@ -0,0 +1,33 @@
+// When DYLD-inserting the ASan dylib from a different location than the
+// original, make sure we don't try to reexec.
+
+// RUN: mkdir -p %T/dyld_insert_libraries_reexec
+// RUN: cp `%clang_asan %s -fsanitize=address -### 2>&1 \
+// RUN: | grep "libclang_rt.asan_osx_dynamic.dylib" \
+// RUN: | sed -e 's/.*"\(.*libclang_rt.asan_osx_dynamic.dylib\)".*/\1/'` \
+// RUN: %T/dyld_insert_libraries_reexec/libclang_rt.asan_osx_dynamic.dylib
+// RUN: %clangxx_asan %s -o %T/dyld_insert_libraries_reexec/a.out
+// RUN: DYLD_INSERT_LIBRARIES=@executable_path/libclang_rt.asan_osx_dynamic.dylib \
+// RUN: ASAN_OPTIONS=verbosity=1 %run %T/dyld_insert_libraries_reexec/a.out 2>&1 \
+// RUN: | FileCheck %s
+// RUN: ASAN_OPTIONS=verbosity=1 %run %T/dyld_insert_libraries_reexec/a.out 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-NOINSERT %s
+
+#include <stdio.h>
+
+int main() {
+ printf("Passed\n");
+ return 0;
+}
+
+// CHECK-NOINSERT: Parsed ASAN_OPTIONS: verbosity=1
+// CHECK-NOINSERT: exec()-ing the program with
+// CHECK-NOINSERT: DYLD_INSERT_LIBRARIES
+// CHECK-NOINSERT: to enable ASan wrappers.
+// CHECK-NOINSERT: Passed
+
+// CHECK: Parsed ASAN_OPTIONS: verbosity=1
+// CHECK-NOT: exec()-ing the program with
+// CHECK-NOT: DYLD_INSERT_LIBRARIES
+// CHECK-NOT: to enable ASan wrappers.
+// CHECK: Passed
diff --git a/test/asan/TestCases/Darwin/interception-in-shared-lib-test.cc b/test/asan/TestCases/Darwin/interception-in-shared-lib-test.cc
new file mode 100644
index 000000000000..e472a9dc6972
--- /dev/null
+++ b/test/asan/TestCases/Darwin/interception-in-shared-lib-test.cc
@@ -0,0 +1,32 @@
+// Check that memset() call from a shared library gets intercepted.
+// Please always keep this file in sync with
+// ../Linux/interception-in-shared-lib-test.cc.
+
+// RUN: %clangxx_asan -O0 %s -DSHARED_LIB \
+// RUN: -shared -o %T/libinterception-in-shared-lib-test.so \
+// RUN: -fPIC
+// TODO(glider): figure out how to set rpath in a more portable way and unite
+// this test with ../Linux/interception-in-shared-lib-test.cc.
+// RUN: %clangxx_asan -O0 %s -o %t -Wl,-rpath,@executable-path -L%T -linterception-in-shared-lib-test && \
+// RUN: not %run %t 2>&1 | FileCheck %s
+
+#include <stdio.h>
+#include <string.h>
+
+#if defined(SHARED_LIB)
+extern "C"
+void my_memset(void *p, size_t sz) {
+ memset(p, 0, sz);
+}
+#else
+extern "C" void my_memset(void *p, size_t sz);
+
+int main(int argc, char *argv[]) {
+ char buf[10];
+ my_memset(buf, 11);
+ // CHECK: {{.*ERROR: AddressSanitizer: stack-buffer-overflow}}
+ // CHECK: {{WRITE of size 11 at 0x.* thread T0}}
+ // CHECK: {{0x.* in my_memset .*interception-in-shared-lib-test.cc:19}}
+ return 0;
+}
+#endif
diff --git a/test/asan/TestCases/Darwin/interface_symbols_darwin.c b/test/asan/TestCases/Darwin/interface_symbols_darwin.c
new file mode 100644
index 000000000000..8680d678cf91
--- /dev/null
+++ b/test/asan/TestCases/Darwin/interface_symbols_darwin.c
@@ -0,0 +1,39 @@
+// Check the presence of interface symbols in the ASan runtime dylib.
+// If you're changing this file, please also change
+// ../Linux/interface_symbols.c
+
+// RUN: %clang_asan -dead_strip -O2 %s -o %t.exe
+// RUN: rm -f %t.symbols %t.interface
+
+// RUN: nm -g `%clang_asan %s -fsanitize=address -### 2>&1 | grep "libclang_rt.asan_osx_dynamic.dylib" | sed -e 's/.*"\(.*libclang_rt.asan_osx_dynamic.dylib\)".*/\1/'` \
+// RUN: | grep " T " | sed "s/.* T //" \
+// RUN: | grep "__asan_" | sed "s/___asan_/__asan_/" \
+// RUN: | sed -E "s/__asan_init_v[0-9]+/__asan_init/" \
+// RUN: | grep -v "__asan_default_options" \
+// RUN: | grep -v "__asan_on_error" > %t.symbols
+
+// RUN: cat %p/../../../../lib/asan/asan_interface_internal.h \
+// RUN: | sed "s/\/\/.*//" | sed "s/typedef.*//" \
+// RUN: | grep -v "OPTIONAL" \
+// RUN: | grep "__asan_.*(" | sed "s/.* __asan_/__asan_/;s/(.*//" \
+// RUN: > %t.interface
+// RUN: echo __asan_report_load1 >> %t.interface
+// RUN: echo __asan_report_load2 >> %t.interface
+// RUN: echo __asan_report_load4 >> %t.interface
+// RUN: echo __asan_report_load8 >> %t.interface
+// RUN: echo __asan_report_load16 >> %t.interface
+// RUN: echo __asan_report_store1 >> %t.interface
+// RUN: echo __asan_report_store2 >> %t.interface
+// RUN: echo __asan_report_store4 >> %t.interface
+// RUN: echo __asan_report_store8 >> %t.interface
+// RUN: echo __asan_report_store16 >> %t.interface
+// RUN: echo __asan_report_load_n >> %t.interface
+// RUN: echo __asan_report_store_n >> %t.interface
+// RUN: echo __asan_get_current_fake_stack >> %t.interface
+// RUN: echo __asan_addr_is_in_fake_stack >> %t.interface
+// RUN: for i in `jot - 0 10`; do echo __asan_stack_malloc_$i >> %t.interface; done
+// RUN: for i in `jot - 0 10`; do echo __asan_stack_free_$i >> %t.interface; done
+
+// RUN: cat %t.interface | sort -u | diff %t.symbols -
+
+int main() { return 0; }
diff --git a/test/asan/TestCases/Darwin/lit.local.cfg b/test/asan/TestCases/Darwin/lit.local.cfg
new file mode 100644
index 000000000000..a85dfcd24c08
--- /dev/null
+++ b/test/asan/TestCases/Darwin/lit.local.cfg
@@ -0,0 +1,9 @@
+def getRoot(config):
+ if not config.parent:
+ return config
+ return getRoot(config.parent)
+
+root = getRoot(config)
+
+if root.host_os not in ['Darwin']:
+ config.unsupported = True
diff --git a/test/asan/TestCases/Darwin/malloc_set_zone_name-mprotect.cc b/test/asan/TestCases/Darwin/malloc_set_zone_name-mprotect.cc
new file mode 100644
index 000000000000..2c643bc03c52
--- /dev/null
+++ b/test/asan/TestCases/Darwin/malloc_set_zone_name-mprotect.cc
@@ -0,0 +1,51 @@
+// Regression test for a bug in malloc_create_zone()
+// (https://code.google.com/p/address-sanitizer/issues/detail?id=203)
+// The old implementation of malloc_create_zone() didn't always return a
+// page-aligned address, so we can only test on a best-effort basis.
+
+// RUN: %clangxx_asan %s -o %t
+// RUN: %run %t 2>&1
+
+#include <malloc/malloc.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+const int kNumIter = 4096;
+const int kNumZones = 100;
+int main() {
+ char *mem[kNumIter * 2];
+ // Allocate memory chunks from different size classes up to 1 page.
+ // (For the case malloc() returns memory chunks in descending order)
+ for (int i = 0; i < kNumIter; i++) {
+ mem[i] = (char*)malloc(8 * i);
+ }
+ // Try to allocate a page-aligned malloc zone. Otherwise the mprotect() call
+ // in malloc_set_zone_name() will silently fail.
+ malloc_zone_t *zone = NULL;
+ bool aligned = false;
+ for (int i = 0; i < kNumZones; i++) {
+ zone = malloc_create_zone(0, 0);
+ if (((uintptr_t)zone & (~0xfff)) == (uintptr_t)zone) {
+ aligned = true;
+ break;
+ }
+ }
+ if (!aligned) {
+ printf("Warning: couldn't allocate a page-aligned zone.");
+ return 0;
+ }
+ // malloc_set_zone_name() calls mprotect(zone, 4096, PROT_READ | PROT_WRITE),
+ // modifies the zone contents and then calls mprotect(zone, 4096, PROT_READ).
+ malloc_set_zone_name(zone, "foobar");
+ // Allocate memory chunks from different size classes again.
+ for (int i = 0; i < kNumIter; i++) {
+ mem[i + kNumIter] = (char*)malloc(8 * i);
+ }
+ // Access the allocated memory chunks and free them.
+ for (int i = 0; i < kNumIter * 2; i++) {
+ memset(mem[i], 'a', 8 * (i % kNumIter));
+ free(mem[i]);
+ }
+ return 0;
+}
diff --git a/test/asan/TestCases/Darwin/malloc_zone-protected.cc b/test/asan/TestCases/Darwin/malloc_zone-protected.cc
new file mode 100644
index 000000000000..362b60e20b55
--- /dev/null
+++ b/test/asan/TestCases/Darwin/malloc_zone-protected.cc
@@ -0,0 +1,20 @@
+// Make sure the zones created by malloc_create_zone() are write-protected.
+#include <malloc/malloc.h>
+#include <stdio.h>
+
+// RUN: %clangxx_asan %s -o %t
+// RUN: not %run %t 2>&1 | FileCheck %s
+
+
+void *pwn(malloc_zone_t *unused_zone, size_t unused_size) {
+ printf("PWNED\n");
+ return NULL;
+}
+
+int main() {
+ malloc_zone_t *zone = malloc_create_zone(0, 0);
+ zone->malloc = pwn;
+ void *v = malloc_zone_malloc(zone, 1);
+ // CHECK-NOT: PWNED
+ return 0;
+}
diff --git a/test/asan/TestCases/Darwin/objc-odr.mm b/test/asan/TestCases/Darwin/objc-odr.mm
new file mode 100644
index 000000000000..72bc39c80dd4
--- /dev/null
+++ b/test/asan/TestCases/Darwin/objc-odr.mm
@@ -0,0 +1,23 @@
+// Regression test for
+// https://code.google.com/p/address-sanitizer/issues/detail?id=360.
+
+// RUN: %clang_asan %s -o %t -framework Foundation
+// RUN: %run %t 2>&1 | FileCheck %s
+
+#import <Foundation/Foundation.h>
+
+void f() {
+ int y = 7;
+ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
+ dispatch_sync(dispatch_get_main_queue(), ^{
+ printf("num = %d\n", y);
+ });
+ });
+}
+
+int main() {
+ NSLog(@"Hello world");
+}
+
+// CHECK-NOT: AddressSanitizer: odr-violation
+// CHECK: Hello world
diff --git a/test/asan/TestCases/Darwin/reexec-insert-libraries-env.cc b/test/asan/TestCases/Darwin/reexec-insert-libraries-env.cc
new file mode 100644
index 000000000000..59ddd634b400
--- /dev/null
+++ b/test/asan/TestCases/Darwin/reexec-insert-libraries-env.cc
@@ -0,0 +1,25 @@
+// Make sure ASan doesn't hang in an exec loop if DYLD_INSERT_LIBRARIES is set.
+// This is a regression test for
+// https://code.google.com/p/address-sanitizer/issues/detail?id=159
+
+// RUN: %clangxx_asan %s -o %t
+// RUN: %clangxx -DSHARED_LIB %s \
+// RUN: -dynamiclib -o darwin-dummy-shared-lib-so.dylib
+
+// FIXME: the following command line may hang in the case of a regression.
+// RUN: DYLD_INSERT_LIBRARIES=darwin-dummy-shared-lib-so.dylib \
+// RUN: %run %t 2>&1 | FileCheck %s || exit 1
+
+#if !defined(SHARED_LIB)
+#include <stdio.h>
+#include <stdlib.h>
+
+int main() {
+ const char kEnvName[] = "DYLD_INSERT_LIBRARIES";
+ printf("%s=%s\n", kEnvName, getenv(kEnvName));
+ // CHECK: {{DYLD_INSERT_LIBRARIES=.*darwin-dummy-shared-lib-so.dylib.*}}
+ return 0;
+}
+#else // SHARED_LIB
+void foo() {}
+#endif // SHARED_LIB
diff --git a/test/asan/TestCases/Darwin/suppressions-darwin.cc b/test/asan/TestCases/Darwin/suppressions-darwin.cc
new file mode 100644
index 000000000000..9a8f56d5dc50
--- /dev/null
+++ b/test/asan/TestCases/Darwin/suppressions-darwin.cc
@@ -0,0 +1,34 @@
+// Check that without suppressions, we catch the issue.
+// RUN: %clangxx_asan -O0 %s -o %t -framework Foundation
+// RUN: not %run %t 2>&1 | FileCheck --check-prefix=CHECK-CRASH %s
+
+// Check that suppressing the interceptor by name works.
+// RUN: echo "interceptor_name:memmove" > %t.supp
+// RUN: ASAN_OPTIONS=suppressions=%t.supp %run %t 2>&1 | FileCheck --check-prefix=CHECK-IGNORE %s
+
+// Check that suppressing by interceptor name works even without the symbolizer
+// RUN: ASAN_OPTIONS=suppressions=%t.supp:symbolize=false %run %t 2>&1 | FileCheck --check-prefix=CHECK-IGNORE %s
+
+// Check that suppressing all reports from a library works.
+// RUN: echo "interceptor_via_lib:CoreFoundation" > %t.supp
+// RUN: ASAN_OPTIONS=suppressions=%t.supp %run %t 2>&1 | FileCheck --check-prefix=CHECK-IGNORE %s
+
+// Check that suppressing library works even without the symbolizer.
+// RUN: ASAN_OPTIONS=suppressions=%t.supp:symbolize=false %run %t 2>&1 | FileCheck --check-prefix=CHECK-IGNORE %s
+
+#include <CoreFoundation/CoreFoundation.h>
+
+int main() {
+ char *a = (char *)malloc(6);
+ strcpy(a, "hello");
+ CFStringRef str =
+ CFStringCreateWithBytes(kCFAllocatorDefault, (unsigned char *)a, 10,
+ kCFStringEncodingUTF8, FALSE); // BOOM
+ fprintf(stderr, "Ignored.\n");
+ free(a);
+}
+
+// CHECK-CRASH: AddressSanitizer: heap-buffer-overflow
+// CHECK-CRASH-NOT: Ignored.
+// CHECK-IGNORE-NOT: AddressSanitizer: heap-buffer-overflow
+// CHECK-IGNORE: Ignored.
diff --git a/test/asan/TestCases/Darwin/unset-insert-libraries-on-exec.cc b/test/asan/TestCases/Darwin/unset-insert-libraries-on-exec.cc
new file mode 100644
index 000000000000..ed476b223af3
--- /dev/null
+++ b/test/asan/TestCases/Darwin/unset-insert-libraries-on-exec.cc
@@ -0,0 +1,25 @@
+// Make sure ASan removes the runtime library from DYLD_INSERT_LIBRARIES before
+// executing other programs.
+
+// RUN: %clangxx_asan %s -o %t
+// RUN: %clangxx %p/../Helpers/echo-env.cc -o %T/echo-env
+// RUN: %clangxx -DSHARED_LIB %s \
+// RUN: -dynamiclib -o %t-darwin-dummy-shared-lib-so.dylib
+
+// Make sure DYLD_INSERT_LIBRARIES doesn't contain the runtime library before
+// execl().
+
+// RUN: %run %t %T/echo-env >/dev/null 2>&1
+// RUN: DYLD_INSERT_LIBRARIES=%t-darwin-dummy-shared-lib-so.dylib \
+// RUN: %run %t %T/echo-env 2>&1 | FileCheck %s || exit 1
+
+#if !defined(SHARED_LIB)
+#include <unistd.h>
+int main(int argc, char *argv[]) {
+ execl(argv[1], argv[1], "DYLD_INSERT_LIBRARIES", NULL);
+ // CHECK: {{DYLD_INSERT_LIBRARIES = .*darwin-dummy-shared-lib-so.dylib.*}}
+ return 0;
+}
+#else // SHARED_LIB
+void foo() {}
+#endif // SHARED_LIB
diff --git a/test/asan/TestCases/Helpers/blacklist-extra.cc b/test/asan/TestCases/Helpers/blacklist-extra.cc
new file mode 100644
index 000000000000..627115cdda2b
--- /dev/null
+++ b/test/asan/TestCases/Helpers/blacklist-extra.cc
@@ -0,0 +1,5 @@
+// This function is broken, but this file is blacklisted
+int externalBrokenFunction(int argc) {
+ char x[10] = {0};
+ return x[argc * 10]; // BOOM
+}
diff --git a/test/asan/TestCases/Helpers/echo-env.cc b/test/asan/TestCases/Helpers/echo-env.cc
new file mode 100644
index 000000000000..65e91c155c84
--- /dev/null
+++ b/test/asan/TestCases/Helpers/echo-env.cc
@@ -0,0 +1,19 @@
+// Helper binary for
+// lit_tests/TestCases/Darwin/unset-insert-libraries-on-exec.cc
+// Prints the environment variable with the given name.
+#include <stdio.h>
+#include <stdlib.h>
+
+int main(int argc, char *argv[]) {
+ if (argc != 2) {
+ printf("Usage: %s ENVNAME\n", argv[0]);
+ exit(1);
+ }
+ const char *value = getenv(argv[1]);
+ if (value) {
+ printf("%s = %s\n", argv[1], value);
+ } else {
+ printf("%s not set.\n", argv[1]);
+ }
+ return 0;
+}
diff --git a/test/asan/TestCases/Helpers/init-order-atexit-extra.cc b/test/asan/TestCases/Helpers/init-order-atexit-extra.cc
new file mode 100644
index 000000000000..e4189d19d099
--- /dev/null
+++ b/test/asan/TestCases/Helpers/init-order-atexit-extra.cc
@@ -0,0 +1,16 @@
+#include <stdio.h>
+
+class C {
+ public:
+ C() { value = 42; }
+ ~C() { }
+ int value;
+};
+
+C c;
+
+void AccessC() {
+ printf("C value: %d\n", c.value);
+}
+
+int main() { return 0; }
diff --git a/test/asan/TestCases/Helpers/init-order-pthread-create-extra.cc b/test/asan/TestCases/Helpers/init-order-pthread-create-extra.cc
new file mode 100644
index 000000000000..d4606f0afb52
--- /dev/null
+++ b/test/asan/TestCases/Helpers/init-order-pthread-create-extra.cc
@@ -0,0 +1,2 @@
+void *bar(void *input);
+void *glob2 = bar((void*)0x2345);
diff --git a/test/asan/TestCases/Helpers/initialization-blacklist-extra.cc b/test/asan/TestCases/Helpers/initialization-blacklist-extra.cc
new file mode 100644
index 000000000000..09aed2112d5e
--- /dev/null
+++ b/test/asan/TestCases/Helpers/initialization-blacklist-extra.cc
@@ -0,0 +1,15 @@
+int zero_init() { return 0; }
+int badGlobal = zero_init();
+int readBadGlobal() { return badGlobal; }
+
+namespace badNamespace {
+class BadClass {
+ public:
+ BadClass() { value = 0; }
+ int value;
+};
+// Global object with non-trivial constructor.
+BadClass bad_object;
+} // namespace badNamespace
+
+int accessBadObject() { return badNamespace::bad_object.value; }
diff --git a/test/asan/TestCases/Helpers/initialization-blacklist-extra2.cc b/test/asan/TestCases/Helpers/initialization-blacklist-extra2.cc
new file mode 100644
index 000000000000..69455a0a6fc9
--- /dev/null
+++ b/test/asan/TestCases/Helpers/initialization-blacklist-extra2.cc
@@ -0,0 +1,4 @@
+int zero_init();
+int badSrcGlobal = zero_init();
+int readBadSrcGlobal() { return badSrcGlobal; }
+
diff --git a/test/asan/TestCases/Helpers/initialization-blacklist.txt b/test/asan/TestCases/Helpers/initialization-blacklist.txt
new file mode 100644
index 000000000000..83294635622d
--- /dev/null
+++ b/test/asan/TestCases/Helpers/initialization-blacklist.txt
@@ -0,0 +1,3 @@
+global:*badGlobal*=init
+type:*badNamespace::BadClass*=init
+src:*initialization-blacklist-extra2.cc=init
diff --git a/test/asan/TestCases/Helpers/initialization-bug-extra.cc b/test/asan/TestCases/Helpers/initialization-bug-extra.cc
new file mode 100644
index 000000000000..3c4cb411defa
--- /dev/null
+++ b/test/asan/TestCases/Helpers/initialization-bug-extra.cc
@@ -0,0 +1,5 @@
+// This file simply declares a dynamically initialized var by the name of 'y'.
+int initY() {
+ return 5;
+}
+int y = initY();
diff --git a/test/asan/TestCases/Helpers/initialization-bug-extra2.cc b/test/asan/TestCases/Helpers/initialization-bug-extra2.cc
new file mode 100644
index 000000000000..a3d8f190e58b
--- /dev/null
+++ b/test/asan/TestCases/Helpers/initialization-bug-extra2.cc
@@ -0,0 +1,6 @@
+// 'z' is dynamically initialized global from different TU.
+extern int z;
+int __attribute__((noinline)) initY() {
+ return z + 1;
+}
+int y = initY();
diff --git a/test/asan/TestCases/Helpers/initialization-constexpr-extra.cc b/test/asan/TestCases/Helpers/initialization-constexpr-extra.cc
new file mode 100644
index 000000000000..b32466a981b3
--- /dev/null
+++ b/test/asan/TestCases/Helpers/initialization-constexpr-extra.cc
@@ -0,0 +1,3 @@
+// Constexpr:
+int getCoolestInteger();
+static int coolest_integer = getCoolestInteger();
diff --git a/test/asan/TestCases/Helpers/initialization-nobug-extra.cc b/test/asan/TestCases/Helpers/initialization-nobug-extra.cc
new file mode 100644
index 000000000000..886165affd76
--- /dev/null
+++ b/test/asan/TestCases/Helpers/initialization-nobug-extra.cc
@@ -0,0 +1,9 @@
+// Linker initialized:
+int getAB();
+static int ab = getAB();
+// Function local statics:
+int countCalls();
+static int one = countCalls();
+// Trivial constructor, non-trivial destructor:
+int getStructWithDtorValue();
+static int val = getStructWithDtorValue();
diff --git a/test/asan/TestCases/Helpers/lit.local.cfg b/test/asan/TestCases/Helpers/lit.local.cfg
new file mode 100644
index 000000000000..2fc4d99456b0
--- /dev/null
+++ b/test/asan/TestCases/Helpers/lit.local.cfg
@@ -0,0 +1,3 @@
+# Sources in this directory are helper files for tests which test functionality
+# involving multiple translation units.
+config.suffixes = []
diff --git a/test/asan/TestCases/Linux/asan-asm-stacktrace-test.cc b/test/asan/TestCases/Linux/asan-asm-stacktrace-test.cc
new file mode 100644
index 000000000000..5332c992a0db
--- /dev/null
+++ b/test/asan/TestCases/Linux/asan-asm-stacktrace-test.cc
@@ -0,0 +1,33 @@
+// Check that a stack unwinding algorithm works corretly even with the assembly
+// instrumentation.
+
+// REQUIRES: x86_64-supported-target
+// RUN: %clangxx_asan -g -O1 %s -fno-inline-functions -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -mllvm -asan-instrument-assembly -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -g -O1 %s -fno-inline-functions -fomit-frame-pointer -momit-leaf-frame-pointer -mllvm -asan-instrument-assembly -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -g0 -O1 %s -fno-unwind-tables -fno-asynchronous-unwind-tables -fno-exceptions -fno-inline-functions -fomit-frame-pointer -momit-leaf-frame-pointer -mllvm -asan-instrument-assembly -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-nounwind
+
+#include <cstddef>
+
+// CHECK: READ of size 4
+// CHECK-NEXT: {{#0 0x[0-9a-fA-F]+ in foo}}
+// CHECK-NEXT: {{#1 0x[0-9a-fA-F]+ in main}}
+
+// CHECK-nounwind: READ of size 4
+// CHECK-nounwind-NEXT: {{#0 0x[0-9a-fA-F]+ in foo}}
+
+__attribute__((noinline)) int foo(size_t n, int *buffer) {
+ int r;
+ __asm__("movl (%[buffer], %[n], 4), %[r] \n\t"
+ : [r] "=r"(r)
+ : [buffer] "r"(buffer), [n] "r"(n)
+ : "memory");
+ return r;
+}
+
+int main() {
+ const size_t n = 16;
+ int *buffer = new int[n];
+ foo(n, buffer);
+ delete[] buffer;
+ return 0;
+}
diff --git a/test/asan/TestCases/Linux/asan_dlopen_test.cc b/test/asan/TestCases/Linux/asan_dlopen_test.cc
new file mode 100644
index 000000000000..f1e31b0a0553
--- /dev/null
+++ b/test/asan/TestCases/Linux/asan_dlopen_test.cc
@@ -0,0 +1,15 @@
+// Test that dlopen of dynamic runtime is prohibited.
+//
+// RUN: %clangxx %s -DRT=\"%shared_libasan\" -o %t -ldl
+// RUN: not %run %t 2>&1 | FileCheck %s
+// REQUIRES: asan-dynamic-runtime
+// XFAIL: android
+
+#include <dlfcn.h>
+
+int main(int argc, char **argv) {
+ dlopen(RT, RTLD_LAZY);
+ return 0;
+}
+
+// CHECK: ASan runtime does not come first in initial library list
diff --git a/test/asan/TestCases/Linux/asan_prelink_test.cc b/test/asan/TestCases/Linux/asan_prelink_test.cc
new file mode 100644
index 000000000000..6145c01f7342
--- /dev/null
+++ b/test/asan/TestCases/Linux/asan_prelink_test.cc
@@ -0,0 +1,29 @@
+// Test if asan works with prelink.
+// It does not actually use prelink, but relies on ld's flag -Ttext-segment
+// or gold's flag -Ttext (we try the first flag first, if that fails we
+// try the second flag).
+//
+// RUN: %clangxx_asan -c %s -o %t.o
+// RUN: %clangxx_asan -DBUILD_SO=1 -fPIC -shared %s -o %t.so -Wl,-Ttext-segment=0x3600000000 ||\
+// RUN: %clangxx_asan -DBUILD_SO=1 -fPIC -shared %s -o %t.so -Wl,-Ttext=0x3600000000
+// RUN: %clangxx_asan %t.o %t.so -Wl,-R. -o %t
+// RUN: ASAN_OPTIONS=verbosity=1 %run %t 2>&1 | FileCheck %s
+
+// GNU driver doesn't handle .so files properly.
+// REQUIRES: x86_64-supported-target, asan-64-bits, Clang
+#if BUILD_SO
+int G;
+int *getG() {
+ return &G;
+}
+#else
+#include <stdio.h>
+extern int *getG();
+int main(int argc, char **argv) {
+ long p = (long)getG();
+ printf("SO mapped at %lx\n", p & ~0xffffffffUL);
+ *getG() = 0;
+}
+#endif
+// CHECK: 0x003000000000, 0x004fffffffff{{.*}} MidMem
+// CHECK: SO mapped at 3600000000
diff --git a/test/asan/TestCases/Linux/asan_preload_test-1.cc b/test/asan/TestCases/Linux/asan_preload_test-1.cc
new file mode 100644
index 000000000000..e5eab5545b83
--- /dev/null
+++ b/test/asan/TestCases/Linux/asan_preload_test-1.cc
@@ -0,0 +1,30 @@
+// Test that non-sanitized executables work with sanitized shared libs
+// and preloaded runtime.
+//
+// RUN: %clangxx -DBUILD_SO=1 -fPIC -shared %s -o %t.so
+// RUN: %clangxx %s %t.so -o %t
+//
+// RUN: %clangxx_asan -DBUILD_SO=1 -fPIC -shared %s -o %t.so
+// RUN: LD_PRELOAD=%shared_libasan not %run %t 2>&1 | FileCheck %s
+
+// REQUIRES: asan-dynamic-runtime
+
+// This way of setting LD_PRELOAD does not work with Android test runner.
+// REQUIRES: not-android
+
+#if BUILD_SO
+char dummy;
+void do_access(const void *p) {
+ // CHECK: AddressSanitizer: heap-buffer-overflow
+ dummy = ((const char *)p)[1];
+}
+#else
+#include <stdlib.h>
+extern void do_access(const void *p);
+int main(int argc, char **argv) {
+ void *p = malloc(1);
+ do_access(p);
+ free(p);
+ return 0;
+}
+#endif
diff --git a/test/asan/TestCases/Linux/asan_preload_test-2.cc b/test/asan/TestCases/Linux/asan_preload_test-2.cc
new file mode 100644
index 000000000000..00b32e15d17d
--- /dev/null
+++ b/test/asan/TestCases/Linux/asan_preload_test-2.cc
@@ -0,0 +1,24 @@
+// Test that preloaded runtime works with unsanitized executables.
+//
+// RUN: %clangxx %s -o %t
+// RUN: LD_PRELOAD=%shared_libasan not %run %t 2>&1 | FileCheck %s
+
+// REQUIRES: asan-dynamic-runtime
+
+// This way of setting LD_PRELOAD does not work with Android test runner.
+// REQUIRES: not-android
+
+#include <stdlib.h>
+
+extern "C" void *memset(void *p, int val, size_t n);
+
+void do_access(void *p) {
+ // CHECK: AddressSanitizer: heap-buffer-overflow
+ memset(p, 0, 2);
+}
+
+int main(int argc, char **argv) {
+ void *p = malloc(1);
+ do_access(p);
+ return 0;
+}
diff --git a/test/asan/TestCases/Linux/asan_rt_confict_test-1.cc b/test/asan/TestCases/Linux/asan_rt_confict_test-1.cc
new file mode 100644
index 000000000000..30f1c17700c8
--- /dev/null
+++ b/test/asan/TestCases/Linux/asan_rt_confict_test-1.cc
@@ -0,0 +1,13 @@
+// Test that preloading dynamic runtime to statically sanitized
+// executable is prohibited.
+//
+// RUN: %clangxx_asan_static %s -o %t
+// RUN: LD_PRELOAD=%shared_libasan not %run %t 2>&1 | FileCheck %s
+
+// REQUIRES: asan-dynamic-runtime
+// XFAIL: android
+
+#include <stdlib.h>
+int main(int argc, char **argv) { return 0; }
+
+// CHECK: Your application is linked against incompatible ASan runtimes
diff --git a/test/asan/TestCases/Linux/asan_rt_confict_test-2.cc b/test/asan/TestCases/Linux/asan_rt_confict_test-2.cc
new file mode 100644
index 000000000000..4c935e2b0f3b
--- /dev/null
+++ b/test/asan/TestCases/Linux/asan_rt_confict_test-2.cc
@@ -0,0 +1,25 @@
+// Test that mixed static/dynamic sanitization of program objects
+// is prohibited.
+//
+// RUN: %clangxx_asan -DBUILD_SO=1 -fPIC -shared %s -o %t.so
+// RUN: %clangxx_asan_static %s %t.so -o %t
+// RUN: not %run %t 2>&1 | FileCheck %s
+
+// REQUIRES: asan-dynamic-runtime
+// XFAIL: android
+
+#if BUILD_SO
+char dummy;
+void do_access(const void *p) { dummy = ((const char *)p)[1]; }
+#else
+#include <stdlib.h>
+extern void do_access(const void *p);
+int main(int argc, char **argv) {
+ void *p = malloc(1);
+ do_access(p);
+ free(p);
+ return 0;
+}
+#endif
+
+// CHECK: Your application is linked against incompatible ASan runtimes
diff --git a/test/asan/TestCases/Linux/clang_gcc_abi.cc b/test/asan/TestCases/Linux/clang_gcc_abi.cc
new file mode 100644
index 000000000000..e833881661d2
--- /dev/null
+++ b/test/asan/TestCases/Linux/clang_gcc_abi.cc
@@ -0,0 +1,44 @@
+// RUN: %clangxx_asan -O0 -x c %s -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O1 -x c %s -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O2 -x c %s -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O3 -x c %s -o %t && not %run %t 2>&1 | FileCheck %s
+
+// REQUIRES: arm-supported-target
+// XFAIL: armv7l-unknown-linux-gnueabihf
+
+#include <stdlib.h>
+
+int boom() {
+ volatile int three = 3;
+ char *s = (char *)malloc(three);
+// CHECK: #1 0x{{.*}} in boom {{.*}}clang_gcc_abi.cc:[[@LINE-1]]
+ return s[three]; //BOOM
+}
+
+__attribute__((naked, noinline)) void gcc_abi() {
+// CHECK: #2 0x{{.*}} in gcc_abi {{.*}}clang_gcc_abi.cc:[[@LINE+1]]
+ asm volatile("str fp, [sp, #-8]!\n\t"
+ "str lr, [sp, #4]\n\t"
+ "add fp, sp, #4\n\t"
+ "bl boom\n\t"
+ "sub sp, fp, #4\n\t"
+ "ldr fp, [sp]\n\t"
+ "add sp, sp, #4\n\t"
+ "ldr pc, [sp], #4\n\t"
+ );
+}
+
+__attribute__((naked, noinline)) void clang_abi() {
+// CHECK: #3 0x{{.*}} in clang_abi {{.*}}clang_gcc_abi.cc:[[@LINE+1]]
+ asm volatile("push {r11, lr}\n\t"
+ "mov r11, sp\n\t"
+ "bl gcc_abi\n\t"
+ "add r0, r0, #1\n\t"
+ "pop {r11, pc}\n\t"
+ );
+}
+
+int main() {
+ clang_abi();
+// CHECK: #4 0x{{.*}} in main {{.*}}clang_gcc_abi.cc:[[@LINE-1]]
+}
diff --git a/test/asan/TestCases/Linux/clone_test.cc b/test/asan/TestCases/Linux/clone_test.cc
new file mode 100644
index 000000000000..e9c1f166eb45
--- /dev/null
+++ b/test/asan/TestCases/Linux/clone_test.cc
@@ -0,0 +1,45 @@
+// Regression test for:
+// http://code.google.com/p/address-sanitizer/issues/detail?id=37
+
+// RUN: %clangxx_asan -O0 %s -o %t && %run %t | FileCheck %s
+// RUN: %clangxx_asan -O1 %s -o %t && %run %t | FileCheck %s
+// RUN: %clangxx_asan -O2 %s -o %t && %run %t | FileCheck %s
+// RUN: %clangxx_asan -O3 %s -o %t && %run %t | FileCheck %s
+// XFAIL: arm-linux-gnueabi
+
+#include <stdio.h>
+#include <sched.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+int Child(void *arg) {
+ char x[32] = {0}; // Stack gets poisoned.
+ printf("Child: %p\n", x);
+ _exit(1); // NoReturn, stack will remain unpoisoned unless we do something.
+}
+
+int main(int argc, char **argv) {
+ const int kStackSize = 1 << 20;
+ char child_stack[kStackSize + 1];
+ char *sp = child_stack + kStackSize; // Stack grows down.
+ printf("Parent: %p\n", sp);
+ pid_t clone_pid = clone(Child, sp, CLONE_FILES | CLONE_VM, NULL);
+ int status;
+ pid_t wait_result = waitpid(clone_pid, &status, __WCLONE);
+ if (wait_result < 0) {
+ perror("waitpid");
+ return 0;
+ }
+ if (wait_result == clone_pid && WIFEXITED(status)) {
+ // Make sure the child stack was indeed unpoisoned.
+ for (int i = 0; i < kStackSize; i++)
+ child_stack[i] = i;
+ int ret = child_stack[argc - 1];
+ printf("PASSED\n");
+ // CHECK: PASSED
+ return ret;
+ }
+ return 0;
+}
diff --git a/test/asan/TestCases/Linux/coverage-and-lsan.cc b/test/asan/TestCases/Linux/coverage-and-lsan.cc
new file mode 100644
index 000000000000..4cb8e2af3084
--- /dev/null
+++ b/test/asan/TestCases/Linux/coverage-and-lsan.cc
@@ -0,0 +1,20 @@
+// Make sure coverage is dumped even if there are reported leaks.
+//
+// RUN: %clangxx_asan -fsanitize-coverage=1 %s -o %t
+//
+// RUN: rm -rf %T/coverage-and-lsan
+//
+// RUN: mkdir -p %T/coverage-and-lsan/normal
+// RUN: ASAN_OPTIONS=coverage=1:coverage_dir=%T/coverage-and-lsan:verbosity=1 not %run %t 2>&1 | FileCheck %s
+// RUN: %sancov print %T/coverage-and-lsan/*.sancov 2>&1
+//
+// REQUIRES: leak-detection
+
+int *g = new int;
+int main(int argc, char **argv) {
+ g = 0;
+ return 0;
+}
+
+// CHECK: LeakSanitizer: detected memory leaks
+// CHECK: CovDump:
diff --git a/test/asan/TestCases/Linux/coverage-caller-callee-total-count.cc b/test/asan/TestCases/Linux/coverage-caller-callee-total-count.cc
new file mode 100644
index 000000000000..0201425106f9
--- /dev/null
+++ b/test/asan/TestCases/Linux/coverage-caller-callee-total-count.cc
@@ -0,0 +1,41 @@
+// Test __sanitizer_get_total_unique_coverage for caller-callee coverage
+
+// RUN: %clangxx_asan -fsanitize-coverage=4 %s -o %t
+// RUN: ASAN_OPTIONS=coverage=1 %run %t
+// RUN: rm -f caller-callee*.sancov
+//
+// REQUIRES: asan-64-bits
+
+#include <sanitizer/common_interface_defs.h>
+#include <stdio.h>
+#include <assert.h>
+int P = 0;
+struct Foo {virtual void f() {if (P) printf("Foo::f()\n");}};
+struct Foo1 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
+struct Foo2 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
+
+Foo *foo[3] = {new Foo, new Foo1, new Foo2};
+
+uintptr_t CheckNewTotalUniqueCoverageIsLargerAndReturnIt(uintptr_t old_total) {
+ uintptr_t new_total = __sanitizer_get_total_unique_coverage();
+ assert(new_total > old_total);
+ return new_total;
+}
+
+int main(int argc, char **argv) {
+ uintptr_t total = CheckNewTotalUniqueCoverageIsLargerAndReturnIt(0);
+ foo[0]->f();
+ total = CheckNewTotalUniqueCoverageIsLargerAndReturnIt(total);
+ foo[1]->f();
+ total = CheckNewTotalUniqueCoverageIsLargerAndReturnIt(total);
+ foo[2]->f();
+ total = CheckNewTotalUniqueCoverageIsLargerAndReturnIt(total);
+ // Ok, called every function once.
+ // Now call them again from another call site. Should get new coverage.
+ foo[0]->f();
+ total = CheckNewTotalUniqueCoverageIsLargerAndReturnIt(total);
+ foo[1]->f();
+ total = CheckNewTotalUniqueCoverageIsLargerAndReturnIt(total);
+ foo[2]->f();
+ total = CheckNewTotalUniqueCoverageIsLargerAndReturnIt(total);
+}
diff --git a/test/asan/TestCases/Linux/coverage-caller-callee.cc b/test/asan/TestCases/Linux/coverage-caller-callee.cc
new file mode 100644
index 000000000000..cd318962b8e0
--- /dev/null
+++ b/test/asan/TestCases/Linux/coverage-caller-callee.cc
@@ -0,0 +1,74 @@
+// Test caller-callee coverage with large number of threads
+// and various numbers of callers and callees.
+
+// RUN: %clangxx_asan -fsanitize-coverage=4 %s -o %t
+// RUN: ASAN_OPTIONS=coverage=1:verbosity=1 %run %t 10 1 2>&1 | FileCheck %s --check-prefix=CHECK-10-1
+// RUN: ASAN_OPTIONS=coverage=1:verbosity=1 %run %t 9 2 2>&1 | FileCheck %s --check-prefix=CHECK-9-2
+// RUN: ASAN_OPTIONS=coverage=1:verbosity=1 %run %t 7 3 2>&1 | FileCheck %s --check-prefix=CHECK-7-3
+// RUN: ASAN_OPTIONS=coverage=1:verbosity=1 %run %t 17 1 2>&1 | FileCheck %s --check-prefix=CHECK-17-1
+// RUN: ASAN_OPTIONS=coverage=1:verbosity=1 %run %t 15 2 2>&1 | FileCheck %s --check-prefix=CHECK-15-2
+// RUN: ASAN_OPTIONS=coverage=1:verbosity=1 %run %t 18 3 2>&1 | FileCheck %s --check-prefix=CHECK-18-3
+// RUN: rm -f caller-callee*.sancov
+//
+// REQUIRES: asan-64-bits
+//
+// CHECK-10-1: CovDump: 10 caller-callee pairs written
+// CHECK-9-2: CovDump: 18 caller-callee pairs written
+// CHECK-7-3: CovDump: 21 caller-callee pairs written
+// CHECK-17-1: CovDump: 14 caller-callee pairs written
+// CHECK-15-2: CovDump: 28 caller-callee pairs written
+// CHECK-18-3: CovDump: 42 caller-callee pairs written
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+int P = 0;
+struct Foo {virtual void f() {if (P) printf("Foo::f()\n");}};
+struct Foo1 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
+struct Foo2 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
+struct Foo3 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
+struct Foo4 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
+struct Foo5 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
+struct Foo6 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
+struct Foo7 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
+struct Foo8 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
+struct Foo9 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
+struct Foo10 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
+struct Foo11 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
+struct Foo12 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
+struct Foo13 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
+struct Foo14 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
+struct Foo15 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
+struct Foo16 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
+struct Foo17 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
+struct Foo18 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
+struct Foo19 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
+
+Foo *foo[20] = {
+ new Foo, new Foo1, new Foo2, new Foo3, new Foo4, new Foo5, new Foo6,
+ new Foo7, new Foo8, new Foo9, new Foo10, new Foo11, new Foo12, new Foo13,
+ new Foo14, new Foo15, new Foo16, new Foo17, new Foo18, new Foo19,
+};
+
+int n_functions = 10;
+int n_callers = 2;
+
+void *Thread(void *arg) {
+ if (n_callers >= 1) for (int i = 0; i < 2000; i++) foo[i % n_functions]->f();
+ if (n_callers >= 2) for (int i = 0; i < 2000; i++) foo[i % n_functions]->f();
+ if (n_callers >= 3) for (int i = 0; i < 2000; i++) foo[i % n_functions]->f();
+ return arg;
+}
+
+int main(int argc, char **argv) {
+ if (argc >= 2)
+ n_functions = atoi(argv[1]);
+ if (argc >= 3)
+ n_callers = atoi(argv[2]);
+ const int kNumThreads = 16;
+ pthread_t t[kNumThreads];
+ for (int i = 0; i < kNumThreads; i++)
+ pthread_create(&t[i], 0, Thread, 0);
+ for (int i = 0; i < kNumThreads; i++)
+ pthread_join(t[i], 0);
+}
diff --git a/test/asan/TestCases/Linux/coverage-direct-large.cc b/test/asan/TestCases/Linux/coverage-direct-large.cc
new file mode 100644
index 000000000000..78aa68621ad1
--- /dev/null
+++ b/test/asan/TestCases/Linux/coverage-direct-large.cc
@@ -0,0 +1,45 @@
+// Test for direct coverage writing with lots of data.
+// Current implementation maps output file in chunks of 64K. This test overflows
+// 1 chunk.
+// RUN: %clangxx_asan -fsanitize-coverage=1 -O0 %s -o %t
+
+// RUN: rm -rf %T/coverage-direct-large
+
+// RUN: mkdir -p %T/coverage-direct-large/normal && cd %T/coverage-direct-large/normal
+// RUN: ASAN_OPTIONS=coverage=1:coverage_direct=0:verbosity=1 %run %t
+// RUN: %sancov print *.sancov >out.txt
+// RUN: cd ../..
+
+// RUN: mkdir -p %T/coverage-direct-large/direct && cd %T/coverage-direct-large/direct
+// RUN: ASAN_OPTIONS=coverage=1:coverage_direct=1:verbosity=1 %run %t
+// RUN: %sancov rawunpack *.sancov.raw
+// RUN: %sancov print *.sancov >out.txt
+// RUN: cd ../..
+
+// RUN: diff -u coverage-direct-large/normal/out.txt coverage-direct-large/direct/out.txt
+//
+// XFAIL: android
+
+#define F0(Q, x) Q(x)
+#define F1(Q, x) \
+ F0(Q, x##0) F0(Q, x##1) F0(Q, x##2) F0(Q, x##3) F0(Q, x##4) F0(Q, x##5) \
+ F0(Q, x##6) F0(Q, x##7) F0(Q, x##8) F0(Q, x##9)
+#define F2(Q, x) \
+ F1(Q, x##0) F1(Q, x##1) F1(Q, x##2) F1(Q, x##3) F1(Q, x##4) F1(Q, x##5) \
+ F1(Q, x##6) F1(Q, x##7) F1(Q, x##8) F1(Q, x##9)
+#define F3(Q, x) \
+ F2(Q, x##0) F2(Q, x##1) F2(Q, x##2) F2(Q, x##3) F2(Q, x##4) F2(Q, x##5) \
+ F2(Q, x##6) F2(Q, x##7) F2(Q, x##8) F2(Q, x##9)
+#define F4(Q, x) \
+ F3(Q, x##0) F3(Q, x##1) F3(Q, x##2) F3(Q, x##3) F3(Q, x##4) F3(Q, x##5) \
+ F3(Q, x##6) F3(Q, x##7) F3(Q, x##8) F3(Q, x##9)
+
+#define DECL(x) __attribute__((noinline)) void x() {}
+#define CALL(x) x();
+
+F4(DECL, f)
+
+int main(void) {
+ F4(CALL, f)
+ return 0;
+}
diff --git a/test/asan/TestCases/Linux/coverage-direct.cc b/test/asan/TestCases/Linux/coverage-direct.cc
new file mode 100644
index 000000000000..2cc1aed0a0fa
--- /dev/null
+++ b/test/asan/TestCases/Linux/coverage-direct.cc
@@ -0,0 +1,44 @@
+// Test for direct coverage writing with dlopen.
+// RUN: %clangxx_asan -fsanitize-coverage=1 -DSHARED %s -shared -o %T/libcoverage_direct_test_1.so -fPIC
+// RUN: %clangxx_asan -fsanitize-coverage=1 -DSO_DIR=\"%T\" %s -o %t
+
+// RUN: rm -rf %T/coverage-direct
+
+// RUN: mkdir -p %T/coverage-direct/normal
+// RUN: ASAN_OPTIONS=coverage=1:coverage_direct=0:coverage_dir=%T/coverage-direct/normal:verbosity=1 %run %t
+// RUN: %sancov print %T/coverage-direct/normal/*.sancov >%T/coverage-direct/normal/out.txt
+
+// RUN: mkdir -p %T/coverage-direct/direct
+// RUN: ASAN_OPTIONS=coverage=1:coverage_direct=1:coverage_dir=%T/coverage-direct/direct:verbosity=1 %run %t
+// RUN: cd %T/coverage-direct/direct
+// RUN: %sancov rawunpack *.sancov.raw
+// RUN: %sancov print *.sancov >out.txt
+// RUN: cd ../..
+
+// RUN: diff -u coverage-direct/normal/out.txt coverage-direct/direct/out.txt
+//
+// XFAIL: android
+
+#include <assert.h>
+#include <dlfcn.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#ifdef SHARED
+extern "C" {
+void bar() { printf("bar\n"); }
+}
+#else
+
+int main(int argc, char **argv) {
+ fprintf(stderr, "PID: %d\n", getpid());
+ void *handle1 =
+ dlopen(SO_DIR "/libcoverage_direct_test_1.so", RTLD_LAZY);
+ assert(handle1);
+ void (*bar1)() = (void (*)())dlsym(handle1, "bar");
+ assert(bar1);
+ bar1();
+
+ return 0;
+}
+#endif
diff --git a/test/asan/TestCases/Linux/coverage-disabled.cc b/test/asan/TestCases/Linux/coverage-disabled.cc
new file mode 100644
index 000000000000..a75b26dc02e9
--- /dev/null
+++ b/test/asan/TestCases/Linux/coverage-disabled.cc
@@ -0,0 +1,18 @@
+// Test that no data is collected without a runtime flag.
+//
+// RUN: %clangxx_asan -fsanitize-coverage=1 %s -o %t
+//
+// RUN: rm -rf %T/coverage-disabled
+//
+// RUN: mkdir -p %T/coverage-disabled/normal
+// RUN: ASAN_OPTIONS=coverage_direct=0:coverage_dir=%T/coverage-disabled/normal:verbosity=1 %run %t
+// RUN: not %sancov print %T/coverage-disabled/normal/*.sancov 2>&1
+//
+// RUN: mkdir -p %T/coverage-disabled/direct
+// RUN: ASAN_OPTIONS=coverage_direct=1:coverage_dir=%T/coverage-disabled/direct:verbosity=1 %run %t
+// RUN: cd %T/coverage-disabled/direct
+// RUN: not %sancov rawunpack *.sancov
+
+int main(int argc, char **argv) {
+ return 0;
+}
diff --git a/test/asan/TestCases/Linux/coverage-fork-direct.cc b/test/asan/TestCases/Linux/coverage-fork-direct.cc
new file mode 100644
index 000000000000..51cbbd821b8e
--- /dev/null
+++ b/test/asan/TestCases/Linux/coverage-fork-direct.cc
@@ -0,0 +1,38 @@
+// RUN: %clangxx_asan -fsanitize-coverage=1 %s -o %t
+// RUN: rm -rf %T/coverage-fork-direct
+// RUN: mkdir -p %T/coverage-fork-direct && cd %T/coverage-fork-direct
+// RUN: (ASAN_OPTIONS=coverage=1:coverage_direct=1:verbosity=1 %run %t; \
+// RUN: %sancov rawunpack *.sancov.raw; %sancov print *.sancov) 2>&1
+//
+// XFAIL: android
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+__attribute__((noinline))
+void foo() { printf("foo\n"); }
+
+__attribute__((noinline))
+void bar() { printf("bar\n"); }
+
+__attribute__((noinline))
+void baz() { printf("baz\n"); }
+
+int main(int argc, char **argv) {
+ pid_t child_pid = fork();
+ if (child_pid == 0) {
+ fprintf(stderr, "Child PID: %d\n", getpid());
+ baz();
+ } else {
+ fprintf(stderr, "Parent PID: %d\n", getpid());
+ foo();
+ bar();
+ }
+ return 0;
+}
+
+// CHECK-DAG: Child PID: [[ChildPID:[0-9]+]]
+// CHECK-DAG: Parent PID: [[ParentPID:[0-9]+]]
+// CHECK-DAG: read 3 PCs from {{.*}}.[[ParentPID]].sancov
+// CHECK-DAG: read 1 PCs from {{.*}}.[[ChildPID]].sancov
diff --git a/test/asan/TestCases/Linux/coverage-fork.cc b/test/asan/TestCases/Linux/coverage-fork.cc
new file mode 100644
index 000000000000..38c200942609
--- /dev/null
+++ b/test/asan/TestCases/Linux/coverage-fork.cc
@@ -0,0 +1,38 @@
+// RUN: %clangxx_asan -fsanitize-coverage=1 %s -o %t
+// RUN: export ASAN_OPTIONS=coverage=1:coverage_direct=0:verbosity=1
+// RUN: rm -rf %T/coverage-fork
+// RUN: mkdir -p %T/coverage-fork && cd %T/coverage-fork
+// RUN: %run %t 2>&1 | FileCheck %s
+//
+// XFAIL: android
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+__attribute__((noinline))
+void foo() { printf("foo\n"); }
+
+__attribute__((noinline))
+void bar() { printf("bar\n"); }
+
+__attribute__((noinline))
+void baz() { printf("baz\n"); }
+
+int main(int argc, char **argv) {
+ pid_t child_pid = fork();
+ if (child_pid == 0) {
+ fprintf(stderr, "Child PID: %d\n", getpid());
+ baz();
+ } else {
+ fprintf(stderr, "Parent PID: %d\n", getpid());
+ foo();
+ bar();
+ }
+ return 0;
+}
+
+// CHECK-DAG: Child PID: [[ChildPID:[0-9]+]]
+// CHECK-DAG: [[ChildPID]].sancov: 1 PCs written
+// CHECK-DAG: Parent PID: [[ParentPID:[0-9]+]]
+// CHECK-DAG: [[ParentPID]].sancov: 3 PCs written
diff --git a/test/asan/TestCases/Linux/coverage-levels.cc b/test/asan/TestCases/Linux/coverage-levels.cc
new file mode 100644
index 000000000000..748ef1f08db5
--- /dev/null
+++ b/test/asan/TestCases/Linux/coverage-levels.cc
@@ -0,0 +1,20 @@
+// Test various levels of coverage
+//
+// RUN: %clangxx_asan -O1 -fsanitize-coverage=1 %s -o %t
+// RUN: ASAN_OPTIONS=coverage=1:verbosity=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK1
+// RUN: %clangxx_asan -O1 -fsanitize-coverage=2 %s -o %t
+// RUN: ASAN_OPTIONS=coverage=1:verbosity=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK2
+// RUN: %clangxx_asan -O1 -fsanitize-coverage=3 %s -o %t
+// RUN: ASAN_OPTIONS=coverage=1:verbosity=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK3
+//
+// REQUIRES: asan-64-bits
+
+volatile int sink;
+int main(int argc, char **argv) {
+ if (argc == 0)
+ sink = 0;
+}
+
+// CHECK1: 1 PCs written
+// CHECK2: 2 PCs written
+// CHECK3: 3 PCs written
diff --git a/test/asan/TestCases/Linux/coverage-maybe-open-file.cc b/test/asan/TestCases/Linux/coverage-maybe-open-file.cc
new file mode 100644
index 000000000000..4664cef7f5af
--- /dev/null
+++ b/test/asan/TestCases/Linux/coverage-maybe-open-file.cc
@@ -0,0 +1,31 @@
+// FIXME: https://code.google.com/p/address-sanitizer/issues/detail?id=316
+// XFAIL: android
+//
+// RUN: %clangxx_asan -fsanitize-coverage=1 %s -o %t
+// RUN: rm -rf %T/coverage-maybe-open-file
+// RUN: mkdir -p %T/coverage-maybe-open-file && cd %T/coverage-maybe-open-file
+// RUN: ASAN_OPTIONS=coverage=1 %run %t | FileCheck %s --check-prefix=CHECK-success
+// RUN: ASAN_OPTIONS=coverage=0 %run %t | FileCheck %s --check-prefix=CHECK-fail
+// RUN: [ "$(cat test.sancov.packed)" == "test" ]
+// RUN: cd .. && rm -rf %T/coverage-maybe-open-file
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sanitizer/common_interface_defs.h>
+
+int main(int argc, char **argv) {
+ int fd = __sanitizer_maybe_open_cov_file("test");
+ if (fd > 0) {
+ printf("SUCCESS\n");
+ const char s[] = "test\n";
+ write(fd, s, strlen(s));
+ close(fd);
+ } else {
+ printf("FAIL\n");
+ }
+}
+
+// CHECK-success: SUCCESS
+// CHECK-fail: FAIL
diff --git a/test/asan/TestCases/Linux/coverage-module-unloaded.cc b/test/asan/TestCases/Linux/coverage-module-unloaded.cc
new file mode 100644
index 000000000000..449841e78189
--- /dev/null
+++ b/test/asan/TestCases/Linux/coverage-module-unloaded.cc
@@ -0,0 +1,56 @@
+// Check that unloading a module doesn't break coverage dumping for remaining
+// modules.
+// RUN: %clangxx_asan -fsanitize-coverage=1 -DSHARED %s -shared -o %T/libcoverage_module_unloaded_test_1.so -fPIC
+// RUN: %clangxx_asan -fsanitize-coverage=1 -DSHARED %s -shared -o %T/libcoverage_module_unloaded_test_2.so -fPIC
+// RUN: %clangxx_asan -fsanitize-coverage=1 -DSO_DIR=\"%T\" %s -o %t
+// RUN: export ASAN_OPTIONS=coverage=1:verbosity=1
+// RUN: mkdir -p %T/coverage-module-unloaded && cd %T/coverage-module-unloaded
+// RUN: %run %t 2>&1 | FileCheck %s
+// RUN: %run %t foo 2>&1 | FileCheck %s
+// RUN: cd .. && rm coverage-module-unloaded -r
+//
+// https://code.google.com/p/address-sanitizer/issues/detail?id=263
+// XFAIL: android
+
+#include <assert.h>
+#include <dlfcn.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#ifdef SHARED
+extern "C" {
+void bar() { printf("bar\n"); }
+}
+#else
+
+int main(int argc, char **argv) {
+ fprintf(stderr, "PID: %d\n", getpid());
+ void *handle1 =
+ dlopen(SO_DIR "/libcoverage_module_unloaded_test_1.so", RTLD_LAZY);
+ assert(handle1);
+ void (*bar1)() = (void (*)())dlsym(handle1, "bar");
+ assert(bar1);
+ bar1();
+ void *handle2 =
+ dlopen(SO_DIR "/libcoverage_module_unloaded_test_2.so", RTLD_LAZY);
+ assert(handle2);
+ void (*bar2)() = (void (*)())dlsym(handle2, "bar");
+ assert(bar2);
+ bar2();
+
+ // It matters whether the unloaded module has a higher or lower address range
+ // than the remaining one. Make sure to test both cases.
+ if (argc < 2)
+ dlclose(bar1 < bar2 ? handle1 : handle2);
+ else
+ dlclose(bar1 < bar2 ? handle2 : handle1);
+ return 0;
+}
+#endif
+
+// CHECK: PID: [[PID:[0-9]+]]
+// CHECK: [[PID]].sancov: 1 PCs written
+// CHECK: .so.[[PID]]
+// If we get coverage for both DSOs, it means the module wasn't unloaded and
+// this test is useless.
+// CHECK-NOT: .so.[[PID]]
diff --git a/test/asan/TestCases/Linux/coverage-sandboxing.cc b/test/asan/TestCases/Linux/coverage-sandboxing.cc
new file mode 100644
index 000000000000..56f9c40f4cc0
--- /dev/null
+++ b/test/asan/TestCases/Linux/coverage-sandboxing.cc
@@ -0,0 +1,85 @@
+// RUN: %clangxx_asan -fsanitize-coverage=2 -DSHARED %s -shared -o %T/libcoverage_sandboxing_test.so -fPIC
+// RUN: %clangxx_asan -fsanitize-coverage=1 %s -o %t -Wl,-R,\$ORIGIN -L%T -lcoverage_sandboxing_test
+// RUN: export ASAN_OPTIONS=coverage=1:verbosity=1
+// RUN: rm -rf %T/coverage_sandboxing_test
+// RUN: mkdir %T/coverage_sandboxing_test && cd %T/coverage_sandboxing_test
+// RUN: mkdir vanilla && cd vanilla
+// RUN: %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-vanilla
+// RUN: mkdir ../sandbox1 && cd ../sandbox1
+// RUN: %run %t a 2>&1 | FileCheck %s --check-prefix=CHECK-sandbox
+// RUN: %sancov unpack coverage_sandboxing_test.sancov.packed
+// RUN: mkdir ../sandbox2 && cd ../sandbox2
+// RUN: %run %t a b 2>&1 | FileCheck %s --check-prefix=CHECK-sandbox
+// RUN: %sancov unpack coverage_sandboxing_test.sancov.packed
+// RUN: cd ..
+// RUN: %sancov print vanilla/libcoverage_sandboxing_test.so.*.sancov > vanilla.txt
+// RUN: %sancov print sandbox1/libcoverage_sandboxing_test.so.*.sancov > sandbox1.txt
+// RUN: %sancov print sandbox2/libcoverage_sandboxing_test.so.*.sancov > sandbox2.txt
+// RUN: diff vanilla.txt sandbox1.txt
+// RUN: diff vanilla.txt sandbox2.txt
+// RUN: cd ../ && rm coverage_sandboxing_test -r
+// https://code.google.com/p/address-sanitizer/issues/detail?id=263
+// XFAIL: android
+
+#include <assert.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sanitizer/common_interface_defs.h>
+
+#define bb0(n) \
+ case n: \
+ fprintf(stderr, "foo: %d\n", n); \
+ break;
+
+#define bb1(n) bb0(n) bb0(n + 1)
+#define bb2(n) bb1(n) bb1(n + 2)
+#define bb3(n) bb2(n) bb2(n + 4)
+#define bb4(n) bb3(n) bb3(n + 8)
+#define bb5(n) bb4(n) bb4(n + 16)
+#define bb6(n) bb5(n) bb5(n + 32)
+#define bb7(n) bb6(n) bb6(n + 64)
+#define bb8(n) bb7(n) bb7(n + 128)
+
+#ifdef SHARED
+void foo(int i) {
+ switch(i) {
+ // 256 basic blocks
+ bb8(0)
+ }
+}
+#else
+extern void foo(int i);
+
+int main(int argc, char **argv) {
+ assert(argc <= 3);
+ for (int i = 0; i < 256; i++) foo(i);
+ fprintf(stderr, "PID: %d\n", getpid());
+ if (argc == 1) {
+ // Vanilla mode, dump to individual files.
+ return 0;
+ }
+ // Dump to packed file.
+ int fd = creat("coverage_sandboxing_test.sancov.packed", 0660);
+ __sanitizer_sandbox_arguments args = {0};
+ args.coverage_sandboxed = 1;
+ args.coverage_fd = fd;
+ if (argc == 2)
+ // Write to packed file, do not split into blocks.
+ args.coverage_max_block_size = 0;
+ else if (argc == 3)
+ // Write to packed file, split into blocks (as if writing to a socket).
+ args.coverage_max_block_size = 100;
+ __sanitizer_sandbox_on_notify(&args);
+ return 0;
+}
+#endif
+
+// CHECK-vanilla: PID: [[PID:[0-9]+]]
+// CHECK-vanilla: [[PID]].sancov: 1 PCs written
+// CHECK-vanilla: .so.[[PID]].sancov: 258 PCs written
+
+// CHECK-sandbox: PID: [[PID:[0-9]+]]
+// CHECK-sandbox: 258 PCs written to packed file
diff --git a/test/asan/TestCases/Linux/coverage-tracing.cc b/test/asan/TestCases/Linux/coverage-tracing.cc
new file mode 100644
index 000000000000..89ab0d283add
--- /dev/null
+++ b/test/asan/TestCases/Linux/coverage-tracing.cc
@@ -0,0 +1,22 @@
+// Test -mllvm -sanitizer-coverage-experimental-tracing
+//
+// RUN: %clangxx_asan -O1 -fsanitize-coverage=1 -mllvm -sanitizer-coverage-experimental-tracing %s -o %t
+// RUN: rm -rf %T/coverage-tracing
+// RUN: mkdir -p %T/coverage-tracing
+// RUN: ASAN_OPTIONS=coverage=1:coverage_dir=%T/coverage-tracing:verbosity=1 %run %t 1 2 3 4 2>&1 | FileCheck %s
+// RUN: rm -rf %T/coverage-tracing
+//
+// REQUIRES: asan-64-bits
+
+volatile int sink;
+int main(int argc, char **argv) {
+ volatile int i = 0;
+ do {
+ sink = 0;
+ i++;
+ } while (i < argc);
+ return 0;
+}
+
+// CHECK: CovDump: Trace: {{[3-9]}} PCs written
+// CHECK: CovDump: Trace: {{[6-9]}} Events written
diff --git a/test/asan/TestCases/Linux/coverage.cc b/test/asan/TestCases/Linux/coverage.cc
new file mode 100644
index 000000000000..f6eb0ae9285b
--- /dev/null
+++ b/test/asan/TestCases/Linux/coverage.cc
@@ -0,0 +1,71 @@
+// RUN: %clangxx_asan -fsanitize-coverage=1 -DSHARED %s -shared -o %T/libcoverage_test.so -fPIC
+// RUN: %clangxx_asan -fsanitize-coverage=1 %s -o %t -Wl,-R,\$ORIGIN -L%T -lcoverage_test
+// RUN: export ASAN_OPTIONS=coverage=1:verbosity=1
+// RUN: mkdir -p %T/coverage && cd %T/coverage
+// RUN: %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-main
+// RUN: %run %t foo 2>&1 | FileCheck %s --check-prefix=CHECK-foo
+// RUN: %run %t bar 2>&1 | FileCheck %s --check-prefix=CHECK-bar
+// RUN: %run %t foo bar 2>&1 | FileCheck %s --check-prefix=CHECK-foo-bar
+// RUN: not %run %t foo bar 4 2>&1 | FileCheck %s --check-prefix=CHECK-report
+// RUN: not %run %t foo bar 4 5 2>&1 | FileCheck %s --check-prefix=CHECK-segv
+// RUN: cd .. && rm coverage -r
+//
+// https://code.google.com/p/address-sanitizer/issues/detail?id=263
+// XFAIL: android
+
+#include "sanitizer/common_interface_defs.h"
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifdef SHARED
+void bar() { printf("bar\n"); }
+#else
+__attribute__((noinline))
+void foo() { printf("foo\n"); }
+extern void bar();
+
+int G[4];
+
+int main(int argc, char **argv) {
+ fprintf(stderr, "PID: %d\n", getpid());
+ for (int i = 1; i < argc; i++) {
+ if (!strcmp(argv[i], "foo")) {
+ uintptr_t old_coverage = __sanitizer_get_total_unique_coverage();
+ foo();
+ uintptr_t new_coverage = __sanitizer_get_total_unique_coverage();
+ assert(new_coverage > old_coverage);
+ }
+ if (!strcmp(argv[i], "bar"))
+ bar();
+ }
+ if (argc == 5) {
+ static volatile char *zero = 0;
+ *zero = 0; // SEGV if argc == 5.
+ }
+ return G[argc]; // Buffer overflow if argc >= 4.
+}
+#endif
+
+// CHECK-main: PID: [[PID:[0-9]+]]
+// CHECK-main: [[PID]].sancov: 1 PCs written
+// CHECK-main-NOT: .so.[[PID]]
+//
+// CHECK-foo: PID: [[PID:[0-9]+]]
+// CHECK-foo: [[PID]].sancov: 2 PCs written
+// CHECK-foo-NOT: .so.[[PID]]
+//
+// CHECK-bar: PID: [[PID:[0-9]+]]
+// CHECK-bar: [[PID]].sancov: 1 PCs written
+// CHECK-bar: .so.[[PID]].sancov: 1 PCs written
+//
+// CHECK-foo-bar: PID: [[PID:[0-9]+]]
+// CHECK-foo-bar: [[PID]].sancov: 2 PCs written
+// CHECK-foo-bar: so.[[PID]].sancov: 1 PCs written
+//
+// CHECK-report: AddressSanitizer: global-buffer-overflow
+// CHECK-report: PCs written
+//
+// CHECK-segv: AddressSanitizer: SEGV
+// CHECK-segv: PCs written
diff --git a/test/asan/TestCases/Linux/function-sections-are-bad.cc b/test/asan/TestCases/Linux/function-sections-are-bad.cc
new file mode 100644
index 000000000000..15aaccbc957f
--- /dev/null
+++ b/test/asan/TestCases/Linux/function-sections-are-bad.cc
@@ -0,0 +1,41 @@
+// Check that --gc-sections does not throw away (or localize) parts of sanitizer
+// interface.
+// RUN: %clang_asan %s -Wl,--gc-sections -ldl -o %t
+// RUN: %clang_asan %s -DBUILD_SO -fPIC -o %t-so.so -shared
+// RUN: %run %t 2>&1
+
+// REQUIRES: asan-64-bits
+
+#ifndef BUILD_SO
+#include <assert.h>
+#include <dlfcn.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int main(int argc, char *argv[]) {
+ char path[4096];
+ snprintf(path, sizeof(path), "%s-so.so", argv[0]);
+
+ void *handle = dlopen(path, RTLD_LAZY);
+ if (!handle) fprintf(stderr, "%s\n", dlerror());
+ assert(handle != 0);
+
+ typedef void (*F)();
+ F f = (F)dlsym(handle, "call_rtl_from_dso");
+ printf("%s\n", dlerror());
+ assert(dlerror() == 0);
+ f();
+
+ dlclose(handle);
+ return 0;
+}
+
+#else // BUILD_SO
+
+#include <sanitizer/asan_interface.h>
+extern "C" void call_rtl_from_dso() {
+ volatile int32_t x;
+ volatile int32_t y = __sanitizer_unaligned_load32((void *)&x);
+}
+
+#endif // BUILD_SO
diff --git a/test/asan/TestCases/Linux/globals-gc-sections.cc b/test/asan/TestCases/Linux/globals-gc-sections.cc
new file mode 100644
index 000000000000..72a9e9498f85
--- /dev/null
+++ b/test/asan/TestCases/Linux/globals-gc-sections.cc
@@ -0,0 +1,13 @@
+// RUN: %clangxx_asan %s -o %t -Wl,--gc-sections -ffunction-sections -mllvm -asan-globals=0
+// RUN: %clangxx_asan %s -o %t -Wl,--gc-sections -ffunction-sections -mllvm -asan-globals=1
+
+// https://code.google.com/p/address-sanitizer/issues/detail?id=260
+// XFAIL: *
+
+int undefined();
+
+int (*unused)() = undefined;
+
+int main() {
+ return 0;
+}
diff --git a/test/asan/TestCases/Linux/initialization-bug-any-order.cc b/test/asan/TestCases/Linux/initialization-bug-any-order.cc
new file mode 100644
index 000000000000..a462f4a163f1
--- /dev/null
+++ b/test/asan/TestCases/Linux/initialization-bug-any-order.cc
@@ -0,0 +1,36 @@
+// Test to make sure basic initialization order errors are caught.
+// Check that on Linux initialization order bugs are caught
+// independently on order in which we list source files (if we specify
+// strict init-order checking).
+
+// RUN: %clangxx_asan -O0 %s %p/../Helpers/initialization-bug-extra.cc -o %t
+// RUN: ASAN_OPTIONS=strict_init_order=true not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O0 %p/../Helpers/initialization-bug-extra.cc %s -o %t
+// RUN: ASAN_OPTIONS=strict_init_order=true not %run %t 2>&1 | FileCheck %s
+
+// Do not test with optimization -- the error may be optimized away.
+
+#include <cstdio>
+
+// 'y' is a dynamically initialized global residing in a different TU. This
+// dynamic initializer will read the value of 'y' before main starts. The
+// result is undefined behavior, which should be caught by initialization order
+// checking.
+extern int y;
+int __attribute__((noinline)) initX() {
+ return y + 1;
+ // CHECK: {{AddressSanitizer: initialization-order-fiasco}}
+ // CHECK: {{READ of size .* at 0x.* thread T0}}
+ // CHECK: {{#0 0x.* in .*initX.* .*initialization-bug-any-order.cc:}}[[@LINE-3]]
+ // CHECK: {{0x.* is located 0 bytes inside of global variable .*y.*}}
+}
+
+// This initializer begins our initialization order problems.
+static int x = initX();
+
+int main() {
+ // ASan should have caused an exit before main runs.
+ printf("PASS\n");
+ // CHECK-NOT: PASS
+ return 0;
+}
diff --git a/test/asan/TestCases/Linux/interception-in-shared-lib-test.cc b/test/asan/TestCases/Linux/interception-in-shared-lib-test.cc
new file mode 100644
index 000000000000..b828d5524ee0
--- /dev/null
+++ b/test/asan/TestCases/Linux/interception-in-shared-lib-test.cc
@@ -0,0 +1,32 @@
+// Check that memset() call from a shared library gets intercepted.
+// Please always keep this file in sync with
+// ../Darwin/interception-in-shared-lib-test.cc.
+
+// RUN: %clangxx_asan -O0 %s -DSHARED_LIB \
+// RUN: -shared -o %T/libinterception-in-shared-lib-test.so \
+// RUN: -fPIC
+// TODO(glider): figure out how to set rpath in a more portable way and unite
+// this test with ../Darwin/interception-in-shared-lib-test.cc.
+// RUN: %clangxx_asan -O0 %s -o %t -Wl,-R,\$ORIGIN -L%T -linterception-in-shared-lib-test && \
+// RUN: not %run %t 2>&1 | FileCheck %s
+
+#include <stdio.h>
+#include <string.h>
+
+#if defined(SHARED_LIB)
+extern "C"
+void my_memset(void *p, size_t sz) {
+ memset(p, 0, sz);
+}
+#else
+extern "C" void my_memset(void *p, size_t sz);
+
+int main(int argc, char *argv[]) {
+ char buf[10];
+ my_memset(buf, 11);
+ // CHECK: {{.*ERROR: AddressSanitizer: stack-buffer-overflow}}
+ // CHECK: {{WRITE of size 11 at 0x.* thread T0}}
+ // CHECK: {{0x.* in my_memset .*interception-in-shared-lib-test.cc:19}}
+ return 0;
+}
+#endif
diff --git a/test/asan/TestCases/Linux/interception_malloc_test.cc b/test/asan/TestCases/Linux/interception_malloc_test.cc
new file mode 100644
index 000000000000..f6d6d340bd9c
--- /dev/null
+++ b/test/asan/TestCases/Linux/interception_malloc_test.cc
@@ -0,0 +1,23 @@
+// ASan interceptor can be accessed with __interceptor_ prefix.
+
+// RUN: %clangxx_asan -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O1 %s -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O2 %s -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+extern "C" void *__interceptor_malloc(size_t size);
+extern "C" void *malloc(size_t size) {
+ write(2, "malloc call\n", sizeof("malloc call\n") - 1);
+ return __interceptor_malloc(size);
+}
+
+int main() {
+ char *x = (char*)malloc(10 * sizeof(char));
+ free(x);
+ return (int)strtol(x, 0, 10);
+ // CHECK: malloc call
+ // CHECK: heap-use-after-free
+}
diff --git a/test/asan/TestCases/Linux/interception_readdir_r_test.cc b/test/asan/TestCases/Linux/interception_readdir_r_test.cc
new file mode 100644
index 000000000000..93b553c3744f
--- /dev/null
+++ b/test/asan/TestCases/Linux/interception_readdir_r_test.cc
@@ -0,0 +1,62 @@
+// FIXME: https://code.google.com/p/address-sanitizer/issues/detail?id=316
+// XFAIL: android
+//
+// RUN: %clangxx_asan -O0 %s -DTEMP_DIR='"'"%T"'"' -o %t && %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O1 %s -DTEMP_DIR='"'"%T"'"' -o %t && %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O2 %s -DTEMP_DIR='"'"%T"'"' -o %t && %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O3 %s -DTEMP_DIR='"'"%T"'"' -o %t && %run %t 2>&1 | FileCheck %s
+//
+// RUN: %clangxx_asan -O0 %s -D_FILE_OFFSET_BITS=64 -DTEMP_DIR='"'"%T"'"' -o %t && %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O1 %s -D_FILE_OFFSET_BITS=64 -DTEMP_DIR='"'"%T"'"' -o %t && %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O2 %s -D_FILE_OFFSET_BITS=64 -DTEMP_DIR='"'"%T"'"' -o %t && %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O3 %s -D_FILE_OFFSET_BITS=64 -DTEMP_DIR='"'"%T"'"' -o %t && %run %t 2>&1 | FileCheck %s
+
+#include <dirent.h>
+#include <memory.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+int main() {
+ // Ensure the readdir_r interceptor doesn't erroneously mark the entire dirent
+ // as written when the end of the directory pointer is reached.
+ fputs("test1: reading the " TEMP_DIR " directory...\n", stderr);
+ DIR *d = opendir(TEMP_DIR);
+ struct dirent *result = (struct dirent *)(0xfeedbeef);
+ // We assume the temp dir for this test doesn't have crazy long file names.
+ char entry_buffer[4096];
+ memset(entry_buffer, 0xab, sizeof(entry_buffer));
+ unsigned count = 0;
+ do {
+ // Stamp the entry struct to try to trick the interceptor.
+ ((struct dirent *)entry_buffer)->d_reclen = 9999;
+ if (readdir_r(d, (struct dirent *)entry_buffer, &result) != 0)
+ abort();
+ ++count;
+ } while (result != NULL);
+ fprintf(stderr, "read %d entries\n", count);
+ closedir(d);
+ // CHECK: test1: reading the {{.*}} directory...
+ // CHECK-NOT: stack-buffer-overflow
+ // CHECK: read {{.*}} entries
+
+ // Ensure the readdir64_r interceptor doesn't have the bug either.
+ fputs("test2: reading the " TEMP_DIR " directory...\n", stderr);
+ d = opendir(TEMP_DIR);
+ struct dirent64 *result64;
+ memset(entry_buffer, 0xab, sizeof(entry_buffer));
+ count = 0;
+ do {
+ // Stamp the entry struct to try to trick the interceptor.
+ ((struct dirent64 *)entry_buffer)->d_reclen = 9999;
+ if (readdir64_r(d, (struct dirent64 *)entry_buffer, &result64) != 0)
+ abort();
+ ++count;
+ } while (result64 != NULL);
+ fprintf(stderr, "read %d entries\n", count);
+ closedir(d);
+ // CHECK: test2: reading the {{.*}} directory...
+ // CHECK-NOT: stack-buffer-overflow
+ // CHECK: read {{.*}} entries
+}
diff --git a/test/asan/TestCases/Linux/interception_test.cc b/test/asan/TestCases/Linux/interception_test.cc
new file mode 100644
index 000000000000..fb9d01cfe6d7
--- /dev/null
+++ b/test/asan/TestCases/Linux/interception_test.cc
@@ -0,0 +1,22 @@
+// ASan interceptor can be accessed with __interceptor_ prefix.
+
+// RUN: %clangxx_asan -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O1 %s -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O2 %s -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s
+#include <stdlib.h>
+#include <stdio.h>
+
+extern "C" long __interceptor_strtol(const char *nptr, char **endptr, int base);
+extern "C" long strtol(const char *nptr, char **endptr, int base) {
+ fprintf(stderr, "my_strtol_interceptor\n");
+ return __interceptor_strtol(nptr, endptr, base);
+}
+
+int main() {
+ char *x = (char*)malloc(10 * sizeof(char));
+ free(x);
+ return (int)strtol(x, 0, 10);
+ // CHECK: my_strtol_interceptor
+ // CHECK: heap-use-after-free
+}
diff --git a/test/asan/TestCases/Linux/interface_symbols_linux.c b/test/asan/TestCases/Linux/interface_symbols_linux.c
new file mode 100644
index 000000000000..a616732ff9f8
--- /dev/null
+++ b/test/asan/TestCases/Linux/interface_symbols_linux.c
@@ -0,0 +1,35 @@
+// Check the presence of interface symbols in compiled file.
+
+// RUN: %clang_asan -O2 %s -o %t.exe
+// RUN: nm -D %t.exe | grep " T " | sed "s/.* T //" \
+// RUN: | grep "__asan_" | sed "s/___asan_/__asan_/" \
+// RUN: | sed -E "s/__asan_init_v[0-9]+/__asan_init/" \
+// RUN: | grep -v "__asan_default_options" \
+// RUN: | grep -v "__asan_stack_" \
+// RUN: | grep -v "__asan_on_error" > %t.symbols
+// RUN: cat %p/../../../../lib/asan/asan_interface_internal.h \
+// RUN: | sed "s/\/\/.*//" | sed "s/typedef.*//" \
+// RUN: | grep -v "OPTIONAL" \
+// RUN: | grep "__asan_.*(" | sed "s/.* __asan_/__asan_/;s/(.*//" \
+// RUN: > %t.interface
+// RUN: echo __asan_report_load1 >> %t.interface
+// RUN: echo __asan_report_load2 >> %t.interface
+// RUN: echo __asan_report_load4 >> %t.interface
+// RUN: echo __asan_report_load8 >> %t.interface
+// RUN: echo __asan_report_load16 >> %t.interface
+// RUN: echo __asan_report_store1 >> %t.interface
+// RUN: echo __asan_report_store2 >> %t.interface
+// RUN: echo __asan_report_store4 >> %t.interface
+// RUN: echo __asan_report_store8 >> %t.interface
+// RUN: echo __asan_report_store16 >> %t.interface
+// RUN: echo __asan_report_load_n >> %t.interface
+// RUN: echo __asan_report_store_n >> %t.interface
+// RUN: echo __asan_get_current_fake_stack >> %t.interface
+// RUN: echo __asan_addr_is_in_fake_stack >> %t.interface
+// RUN: cat %t.interface | sort -u | diff %t.symbols -
+
+// FIXME: nm -D on powerpc somewhy shows ASan interface symbols residing
+// in "initialized data section".
+// REQUIRES: x86_64-supported-target,i386-supported-target,asan-static-runtime
+
+int main() { return 0; }
diff --git a/test/asan/TestCases/Linux/kernel-area.cc b/test/asan/TestCases/Linux/kernel-area.cc
new file mode 100644
index 000000000000..8dd509f84975
--- /dev/null
+++ b/test/asan/TestCases/Linux/kernel-area.cc
@@ -0,0 +1,24 @@
+// FIXME: https://code.google.com/p/address-sanitizer/issues/detail?id=316
+// XFAIL: android
+//
+// Test that kernel area is not sanitized on 32-bit machines.
+//
+// RUN: %clangxx_asan %s -o %t
+// RUN: ASAN_OPTIONS=verbosity=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-%kernel_bits
+// RUN: ASAN_OPTIONS=verbosity=1:full_address_space=0 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-%kernel_bits
+// RUN: ASAN_OPTIONS=verbosity=1:full_address_space=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-kernel-64-bits
+//
+// CHECK-kernel-32-bits: || `[0x38000000, 0xbfffffff]` || HighMem ||
+// CHECK-kernel-32-bits: || `[0x27000000, 0x37ffffff]` || HighShadow ||
+// CHECK-kernel-32-bits: || `[0x24000000, 0x26ffffff]` || ShadowGap ||
+//
+// CHECK-kernel-64-bits: || `[0x40000000, 0xffffffff]` || HighMem ||
+// CHECK-kernel-64-bits: || `[0x28000000, 0x3fffffff]` || HighShadow ||
+// CHECK-kernel-64-bits: || `[0x24000000, 0x27ffffff]` || ShadowGap ||
+//
+// REQUIRES: asan-32-bits
+
+int main() {
+ return 0;
+}
+
diff --git a/test/asan/TestCases/Linux/leak.cc b/test/asan/TestCases/Linux/leak.cc
new file mode 100644
index 000000000000..36dc6ddb8adf
--- /dev/null
+++ b/test/asan/TestCases/Linux/leak.cc
@@ -0,0 +1,16 @@
+// Minimal test for LeakSanitizer+AddressSanitizer.
+// REQUIRES: leak-detection
+//
+// RUN: %clangxx_asan %s -o %t
+// RUN: ASAN_OPTIONS=detect_leaks=1 not %run %t 2>&1 | FileCheck %s
+// RUN: ASAN_OPTIONS="" not %run %t 2>&1 | FileCheck %s
+// RUN: ASAN_OPTIONS=detect_leaks=0 %run %t
+#include <stdio.h>
+int *t;
+
+int main(int argc, char **argv) {
+ t = new int[argc - 1];
+ printf("t: %p\n", t);
+ t = 0;
+}
+// CHECK: LeakSanitizer: detected memory leaks
diff --git a/test/asan/TestCases/Linux/lit.local.cfg b/test/asan/TestCases/Linux/lit.local.cfg
new file mode 100644
index 000000000000..57271b8078a4
--- /dev/null
+++ b/test/asan/TestCases/Linux/lit.local.cfg
@@ -0,0 +1,9 @@
+def getRoot(config):
+ if not config.parent:
+ return config
+ return getRoot(config.parent)
+
+root = getRoot(config)
+
+if root.host_os not in ['Linux']:
+ config.unsupported = True
diff --git a/test/asan/TestCases/Linux/malloc-in-qsort.cc b/test/asan/TestCases/Linux/malloc-in-qsort.cc
new file mode 100644
index 000000000000..545bc7e42a17
--- /dev/null
+++ b/test/asan/TestCases/Linux/malloc-in-qsort.cc
@@ -0,0 +1,56 @@
+// RUN: %clangxx_asan -O2 %s -o %t
+// RUN: ASAN_OPTIONS=fast_unwind_on_malloc=1 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-FAST
+// RUN: ASAN_OPTIONS=fast_unwind_on_malloc=0 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-SLOW
+
+// Test how well we unwind in presence of qsort in the stack
+// (i.e. if we can unwind through a function compiled w/o frame pointers).
+// https://code.google.com/p/address-sanitizer/issues/detail?id=137
+
+// Fast unwinder is only available on x86_64 and i386.
+// REQUIRES: x86_64-supported-target
+
+// REQUIRES: compiler-rt-optimized
+
+#include <stdlib.h>
+#include <stdio.h>
+
+int *GlobalPtr;
+
+extern "C" {
+int QsortCallback(const void *a, const void *b) {
+ char *x = (char*)a;
+ char *y = (char*)b;
+ printf("Calling QsortCallback\n");
+ GlobalPtr = new int[10];
+ return (int)*x - (int)*y;
+}
+
+__attribute__((noinline))
+void MyQsort(char *a, size_t size) {
+ printf("Calling qsort\n");
+ qsort(a, size, sizeof(char), QsortCallback);
+ printf("Done\n"); // Avoid tail call.
+}
+} // extern "C"
+
+int main() {
+ char a[2] = {1, 2};
+ MyQsort(a, 2);
+ return GlobalPtr[10];
+}
+
+// Fast unwind: can not unwind through qsort.
+// FIXME: this test does not properly work with slow unwind yet.
+
+// CHECK-FAST: ERROR: AddressSanitizer: heap-buffer-overflow
+// CHECK-FAST: is located 0 bytes to the right
+// CHECK-FAST: #0{{.*}}operator new
+// CHECK-FAST-NEXT: #1{{.*}}QsortCallback
+// CHECK-FAST-NOT: MyQsort
+//
+// CHECK-SLOW: ERROR: AddressSanitizer: heap-buffer-overflow
+// CHECK-SLOW: is located 0 bytes to the right
+// CHECK-SLOW: #0{{.*}}operator new
+// CHECK-SLOW-NEXT: #1{{.*}}QsortCallback
+// CHECK-SLOW: #{{.*}}MyQsort
+// CHECK-SLOW-NEXT: #{{.*}}main
diff --git a/test/asan/TestCases/Linux/malloc_delete_mismatch.cc b/test/asan/TestCases/Linux/malloc_delete_mismatch.cc
new file mode 100644
index 000000000000..18d65ce0008f
--- /dev/null
+++ b/test/asan/TestCases/Linux/malloc_delete_mismatch.cc
@@ -0,0 +1,33 @@
+// Check that we detect malloc/delete mismatch only if the approptiate flag
+// is set.
+
+// RUN: %clangxx_asan -g %s -o %t 2>&1
+
+// Find error and provide malloc context.
+// RUN: ASAN_OPTIONS=alloc_dealloc_mismatch=1 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=ALLOC-STACK
+
+// No error here.
+// RUN: ASAN_OPTIONS=alloc_dealloc_mismatch=0 %run %t
+
+// Also works if no malloc context is available.
+// RUN: ASAN_OPTIONS=alloc_dealloc_mismatch=1:malloc_context_size=0:fast_unwind_on_malloc=0 not %run %t 2>&1 | FileCheck %s
+// RUN: ASAN_OPTIONS=alloc_dealloc_mismatch=1:malloc_context_size=0:fast_unwind_on_malloc=1 not %run %t 2>&1 | FileCheck %s
+// XFAIL: arm-linux-gnueabi
+// XFAIL: armv7l-unknown-linux-gnueabihf
+#include <stdlib.h>
+
+static volatile char *x;
+
+int main() {
+ x = (char*)malloc(10);
+ x[0] = 0;
+ delete x;
+}
+// CHECK: ERROR: AddressSanitizer: alloc-dealloc-mismatch (malloc vs operator delete) on 0x
+// CHECK-NEXT: #0{{.*}}operator delete
+// CHECK: #{{.*}}main
+// CHECK: is located 0 bytes inside of 10-byte region
+// CHECK-NEXT: allocated by thread T0 here:
+// ALLOC-STACK-NEXT: #0{{.*}}malloc
+// ALLOC-STACK: #{{.*}}main
+// CHECK: HINT: {{.*}} you may set ASAN_OPTIONS=alloc_dealloc_mismatch=0
diff --git a/test/asan/TestCases/Linux/odr-violation.cc b/test/asan/TestCases/Linux/odr-violation.cc
new file mode 100644
index 000000000000..ddc68a2db0f1
--- /dev/null
+++ b/test/asan/TestCases/Linux/odr-violation.cc
@@ -0,0 +1,42 @@
+// FIXME: https://code.google.com/p/address-sanitizer/issues/detail?id=316
+// XFAIL: android
+//
+// Different size: detect a bug if detect_odr_violation>=1
+// RUN: %clangxx_asan -DBUILD_SO=1 -fPIC -shared %s -o %t-ODR-SO.so
+// RUN: %clangxx_asan %s %t-ODR-SO.so -Wl,-R. -o %t-ODR-EXE
+// RUN: ASAN_OPTIONS=detect_odr_violation=1 not %run %t-ODR-EXE 2>&1 | FileCheck %s
+// RUN: ASAN_OPTIONS=detect_odr_violation=2 not %run %t-ODR-EXE 2>&1 | FileCheck %s
+// RUN: ASAN_OPTIONS=detect_odr_violation=0 %run %t-ODR-EXE 2>&1 | FileCheck %s --check-prefix=DISABLED
+// RUN: not %run %t-ODR-EXE 2>&1 | FileCheck %s
+//
+// Same size: report a bug only if detect_odr_violation>=2.
+// RUN: %clangxx_asan -DBUILD_SO=1 -fPIC -shared %s -o %t-ODR-SO.so -DSZ=100
+// RUN: ASAN_OPTIONS=detect_odr_violation=1 %run %t-ODR-EXE 2>&1 | FileCheck %s --check-prefix=DISABLED
+// RUN: ASAN_OPTIONS=detect_odr_violation=2 not %run %t-ODR-EXE 2>&1 | FileCheck %s
+// RUN: not %run %t-ODR-EXE 2>&1 | FileCheck %s
+
+// GNU driver doesn't handle .so files properly.
+// REQUIRES: Clang
+
+#ifndef SZ
+# define SZ 4
+#endif
+
+#if BUILD_SO
+namespace foo { char G[SZ]; }
+#else
+#include <stdio.h>
+namespace foo { char G[100]; }
+// CHECK: ERROR: AddressSanitizer: odr-violation
+// CHECK: size=100 'foo::G' {{.*}}odr-violation.cc:[[@LINE-2]]:22
+// CHECK: size={{4|100}} 'foo::G'
+int main(int argc, char **argv) {
+ printf("PASS: %p\n", &foo::G);
+}
+#endif
+
+// CHECK: These globals were registered at these points:
+// CHECK: ODR-EXE
+// CHECK: ODR-SO
+// CHECK: SUMMARY: AddressSanitizer: odr-violation: global 'foo::G' at {{.*}}odr-violation.cc
+// DISABLED: PASS
diff --git a/test/asan/TestCases/Linux/overflow-in-qsort.cc b/test/asan/TestCases/Linux/overflow-in-qsort.cc
new file mode 100644
index 000000000000..79b654e117cd
--- /dev/null
+++ b/test/asan/TestCases/Linux/overflow-in-qsort.cc
@@ -0,0 +1,51 @@
+// RUN: %clangxx_asan -O2 %s -o %t
+// RUN: ASAN_OPTIONS=fast_unwind_on_fatal=1 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-FAST
+// RUN: ASAN_OPTIONS=fast_unwind_on_fatal=0 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-SLOW
+
+// Test how well we unwind in presence of qsort in the stack
+// (i.e. if we can unwind through a function compiled w/o frame pointers).
+// https://code.google.com/p/address-sanitizer/issues/detail?id=137
+
+// Fast unwinder is only available on x86_64 and i386.
+// REQUIRES: x86_64-supported-target
+
+#include <stdlib.h>
+#include <stdio.h>
+
+int global_array[10];
+volatile int one = 1;
+
+extern "C" {
+int QsortCallback(const void *a, const void *b) {
+ char *x = (char*)a;
+ char *y = (char*)b;
+ printf("Calling QsortCallback\n");
+ global_array[one * 10] = 0; // BOOM
+ return (int)*x - (int)*y;
+}
+
+__attribute__((noinline))
+void MyQsort(char *a, size_t size) {
+ printf("Calling qsort\n");
+ qsort(a, size, sizeof(char), QsortCallback);
+ printf("Done\n"); // Avoid tail call.
+}
+} // extern "C"
+
+int main() {
+ char a[2] = {1, 2};
+ MyQsort(a, 2);
+}
+
+// Fast unwind: can not unwind through qsort.
+
+// CHECK-FAST: ERROR: AddressSanitizer: global-buffer-overflow
+// CHECK-FAST: #0{{.*}} in QsortCallback
+// CHECK-FAST-NOT: MyQsort
+// CHECK-FAST: is located 0 bytes to the right of global variable 'global_array
+
+// CHECK-SLOW: ERROR: AddressSanitizer: global-buffer-overflow
+// CHECK-SLOW: #0{{.*}} in QsortCallback
+// CHECK-SLOW: #{{.*}} in MyQsort
+// CHECK-SLOW: #{{.*}} in main
+// CHECK-SLOW: is located 0 bytes to the right of global variable 'global_array
diff --git a/test/asan/TestCases/Linux/preinit_test.cc b/test/asan/TestCases/Linux/preinit_test.cc
new file mode 100644
index 000000000000..10dde67d6a9b
--- /dev/null
+++ b/test/asan/TestCases/Linux/preinit_test.cc
@@ -0,0 +1,33 @@
+// FIXME: https://code.google.com/p/address-sanitizer/issues/detail?id=316
+// XFAIL: android
+//
+// RUN: %clangxx -DFUNC=zzzz %s -shared -o %t.so -fPIC
+// RUN: %clangxx_asan -DFUNC=main %s -o %t -Wl,-R. %t.so
+// RUN: %run %t
+
+// GNU driver doesn't handle .so files properly.
+// REQUIRES: Clang
+
+// This test ensures that we call __asan_init early enough.
+// We build a shared library w/o asan instrumentation
+// and the binary with asan instrumentation.
+// Both files include the same header (emulated by -DFUNC here)
+// with C++ template magic which runs global initializer at library load time.
+// The function get() is instrumented with asan, but called
+// before the usual constructors are run.
+// So, we must make sure that __asan_init is executed even earlier.
+//
+// See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56393
+
+struct A {
+ int foo() const { return 0; }
+};
+A get () { return A(); }
+template <class> struct O {
+ static A const e;
+};
+template <class T> A const O <T>::e = get();
+int FUNC() {
+ return O<int>::e.foo();
+}
+
diff --git a/test/asan/TestCases/Linux/ptrace.cc b/test/asan/TestCases/Linux/ptrace.cc
new file mode 100644
index 000000000000..7e5acb64c7a1
--- /dev/null
+++ b/test/asan/TestCases/Linux/ptrace.cc
@@ -0,0 +1,56 @@
+// FIXME: https://code.google.com/p/address-sanitizer/issues/detail?id=316
+// XFAIL: android
+//
+// RUN: %clangxx_asan -O0 %s -o %t && %run %t
+// RUN: %clangxx_asan -DPOSITIVE -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s
+// REQUIRES: x86_64-supported-target,i386-supported-target
+
+#include <assert.h>
+#include <stdio.h>
+#include <sys/ptrace.h>
+#include <sys/types.h>
+#include <sys/user.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+int main(void) {
+ pid_t pid;
+ pid = fork();
+ if (pid == 0) { // child
+ ptrace(PTRACE_TRACEME, 0, NULL, NULL);
+ execl("/bin/true", "true", NULL);
+ } else {
+ wait(NULL);
+ user_regs_struct regs;
+ int res;
+ user_regs_struct * volatile pregs = &regs;
+#ifdef POSITIVE
+ ++pregs;
+#endif
+ res = ptrace(PTRACE_GETREGS, pid, NULL, pregs);
+ // CHECK: AddressSanitizer: stack-buffer-overflow
+ // CHECK: {{.*ptrace.cc:}}[[@LINE-2]]
+ assert(!res);
+#if __WORDSIZE == 64
+ printf("%zx\n", regs.rip);
+#else
+ printf("%lx\n", regs.eip);
+#endif
+
+ user_fpregs_struct fpregs;
+ res = ptrace(PTRACE_GETFPREGS, pid, NULL, &fpregs);
+ assert(!res);
+ printf("%lx\n", (unsigned long)fpregs.cwd);
+
+#if __WORDSIZE == 32
+ user_fpxregs_struct fpxregs;
+ res = ptrace(PTRACE_GETFPXREGS, pid, NULL, &fpxregs);
+ assert(!res);
+ printf("%lx\n", (unsigned long)fpxregs.mxcsr);
+#endif
+
+ ptrace(PTRACE_CONT, pid, NULL, NULL);
+ wait(NULL);
+ }
+ return 0;
+}
diff --git a/test/asan/TestCases/Linux/rlimit_mmap_test.cc b/test/asan/TestCases/Linux/rlimit_mmap_test.cc
new file mode 100644
index 000000000000..7f37727b2eeb
--- /dev/null
+++ b/test/asan/TestCases/Linux/rlimit_mmap_test.cc
@@ -0,0 +1,16 @@
+// Check that we properly report mmap failure.
+// RUN: %clangxx_asan %s -o %t && not %run %t 2>&1 | FileCheck %s
+#include <stdlib.h>
+#include <assert.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+
+static volatile void *x;
+
+int main(int argc, char **argv) {
+ struct rlimit mmap_resource_limit = { 0, 0 };
+ assert(0 == setrlimit(RLIMIT_AS, &mmap_resource_limit));
+ x = malloc(10000000);
+// CHECK: ERROR: Failed to mmap
+ return 0;
+}
diff --git a/test/asan/TestCases/Linux/shmctl.cc b/test/asan/TestCases/Linux/shmctl.cc
new file mode 100644
index 000000000000..e1752bc894c0
--- /dev/null
+++ b/test/asan/TestCases/Linux/shmctl.cc
@@ -0,0 +1,27 @@
+// FIXME: https://code.google.com/p/address-sanitizer/issues/detail?id=316
+// XFAIL: android
+//
+// RUN: %clangxx_asan -O1 %s -o %t && %run %t 2>&1
+// Regression test for
+// https://code.google.com/p/address-sanitizer/issues/detail?id=250
+#include <stdio.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <assert.h>
+
+int main() {
+ int id = shmget(IPC_PRIVATE, 4096, 0644 | IPC_CREAT);
+ assert(id > -1);
+ struct shmid_ds ds;
+ int res = shmctl(id, IPC_STAT, &ds);
+ assert(res > -1);
+ printf("shm_segsz: %zd\n", ds.shm_segsz);
+ assert(ds.shm_segsz == 4096);
+ assert(-1 != shmctl(id, IPC_RMID, 0));
+
+ struct shm_info shmInfo;
+ res = shmctl(0, SHM_INFO, (struct shmid_ds *)&shmInfo);
+ assert(res > -1);
+
+ return 0;
+}
diff --git a/test/asan/TestCases/Linux/sized_delete_test.cc b/test/asan/TestCases/Linux/sized_delete_test.cc
new file mode 100644
index 000000000000..823e3c0bf88e
--- /dev/null
+++ b/test/asan/TestCases/Linux/sized_delete_test.cc
@@ -0,0 +1,93 @@
+// RUN: %clangxx_asan -Xclang -fsized-deallocation -O0 %s -o %t
+// RUN: not %run %t scalar 2>&1 | FileCheck %s -check-prefix=SCALAR
+// RUN: ASAN_OPTIONS=new_delete_type_mismatch=1 not %run %t scalar 2>&1 | FileCheck %s -check-prefix=SCALAR
+// RUN: not %run %t array 2>&1 | FileCheck %s -check-prefix=ARRAY
+// RUN: ASAN_OPTIONS=new_delete_type_mismatch=1 not %run %t array 2>&1 | FileCheck %s -check-prefix=ARRAY
+// RUN: ASAN_OPTIONS=new_delete_type_mismatch=0 %run %t scalar
+// RUN: ASAN_OPTIONS=new_delete_type_mismatch=0 %run %t array
+
+// Sized-delete is implemented with a weak delete() definition.
+// Weak symbols are kind of broken on Android.
+// XFAIL: android
+
+#include <new>
+#include <stdio.h>
+#include <string>
+
+inline void break_optimization(void *arg) {
+ __asm__ __volatile__("" : : "r" (arg) : "memory");
+}
+
+struct S12 {
+ int a, b, c;
+};
+
+struct S20 {
+ int a, b, c, d, e;
+};
+
+struct D1 {
+ int a, b, c;
+ ~D1() { fprintf(stderr, "D1::~D1\n"); }
+};
+
+struct D2 {
+ int a, b, c, d, e;
+ ~D2() { fprintf(stderr, "D2::~D2\n"); }
+};
+
+void Del12(S12 *x) {
+ break_optimization(x);
+ delete x;
+}
+void Del12NoThrow(S12 *x) {
+ break_optimization(x);
+ operator delete(x, std::nothrow);
+}
+void Del12Ar(S12 *x) {
+ break_optimization(x);
+ delete [] x;
+}
+void Del12ArNoThrow(S12 *x) {
+ break_optimization(x);
+ operator delete[](x, std::nothrow);
+}
+
+int main(int argc, char **argv) {
+ if (argc != 2) return 1;
+ std::string flag = argv[1];
+ // These are correct.
+ Del12(new S12);
+ Del12NoThrow(new S12);
+ Del12Ar(new S12[100]);
+ Del12ArNoThrow(new S12[100]);
+
+ // Here we pass wrong type of pointer to delete,
+ // but [] and nothrow variants of delete are not sized.
+ Del12Ar(reinterpret_cast<S12*>(new S20[100]));
+ Del12NoThrow(reinterpret_cast<S12*>(new S20));
+ Del12ArNoThrow(reinterpret_cast<S12*>(new S20[100]));
+ fprintf(stderr, "OK SO FAR\n");
+ // SCALAR: OK SO FAR
+ // ARRAY: OK SO FAR
+ if (flag == "scalar") {
+ // Here asan should bark as we are passing a wrong type of pointer
+ // to sized delete.
+ Del12(reinterpret_cast<S12*>(new S20));
+ // SCALAR: AddressSanitizer: new-delete-type-mismatch
+ // SCALAR: object passed to delete has wrong type:
+ // SCALAR: size of the allocated type: 20 bytes;
+ // SCALAR: size of the deallocated type: 12 bytes.
+ // SCALAR: is located 0 bytes inside of 20-byte region
+ // SCALAR: SUMMARY: AddressSanitizer: new-delete-type-mismatch
+ } else if (flag == "array") {
+ D1 *d1 = reinterpret_cast<D1*>(new D2[10]);
+ break_optimization(d1);
+ delete [] d1;
+ // ARRAY-NOT: D2::~D2
+ // ARRAY: D1::~D1
+ // ARRAY: AddressSanitizer: new-delete-type-mismatch
+ // ARRAY: size of the allocated type: 20{{4|8}} bytes;
+ // ARRAY: size of the deallocated type: 12{{4|8}} bytes.
+ }
+}
diff --git a/test/asan/TestCases/Linux/stack-trace-dlclose.cc b/test/asan/TestCases/Linux/stack-trace-dlclose.cc
new file mode 100644
index 000000000000..e494e5661d1d
--- /dev/null
+++ b/test/asan/TestCases/Linux/stack-trace-dlclose.cc
@@ -0,0 +1,45 @@
+// FIXME: https://code.google.com/p/address-sanitizer/issues/detail?id=316
+// XFAIL: android
+//
+// RUN: %clangxx_asan -DSHARED %s -shared -o %T/stack_trace_dlclose.so -fPIC
+// RUN: %clangxx_asan -DSO_DIR=\"%T\" %s -o %t
+// RUN: ASAN_OPTIONS=exitcode=0 %run %t 2>&1 | FileCheck %s
+// XFAIL: arm-linux-gnueabi
+// XFAIL: armv7l-unknown-linux-gnueabihf
+
+#include <assert.h>
+#include <dlfcn.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <sanitizer/common_interface_defs.h>
+
+#ifdef SHARED
+extern "C" {
+void *foo() {
+ return malloc(1);
+}
+}
+#else
+void *handle;
+
+int main(int argc, char **argv) {
+ void *handle = dlopen(SO_DIR "/stack_trace_dlclose.so", RTLD_LAZY);
+ assert(handle);
+ void *(*foo)() = (void *(*)())dlsym(handle, "foo");
+ assert(foo);
+ void *p = foo();
+ assert(p);
+ dlclose(handle);
+
+ free(p);
+ free(p); // double-free
+
+ return 0;
+}
+#endif
+
+// CHECK: {{ #0 0x.* in malloc}}
+// CHECK: {{ #1 0x.* \(<unknown module>\)}}
+// CHECK: {{ #2 0x.* in main}}
diff --git a/test/asan/TestCases/Linux/stress_dtls.c b/test/asan/TestCases/Linux/stress_dtls.c
new file mode 100644
index 000000000000..cb901ee59953
--- /dev/null
+++ b/test/asan/TestCases/Linux/stress_dtls.c
@@ -0,0 +1,116 @@
+// REQUIRES: asan-64-bits
+// Stress test dynamic TLS + dlopen + threads.
+//
+// Note that glibc 2.15 seems utterly broken on this test,
+// it fails with ~17 DSOs dlopen-ed.
+// glibc 2.19 seems fine.
+//
+//
+// RUN: %clangxx_asan -x c -DSO_NAME=f0 %s -shared -o %t-f0.so -fPIC
+// RUN: %clangxx_asan -x c -DSO_NAME=f1 %s -shared -o %t-f1.so -fPIC
+// RUN: %clangxx_asan -x c -DSO_NAME=f2 %s -shared -o %t-f2.so -fPIC
+// RUN: %clangxx_asan %s -ldl -pthread -o %t
+// RUN: %run %t 0 3
+// RUN: %run %t 2 3
+// RUN: ASAN_OPTIONS=verbosity=2 %run %t 10 2 2>&1 | FileCheck %s
+// RUN: ASAN_OPTIONS=verbosity=2:intercept_tls_get_addr=1 %run %t 10 2 2>&1 | FileCheck %s
+// RUN: ASAN_OPTIONS=verbosity=2:intercept_tls_get_addr=0 %run %t 10 2 2>&1 | FileCheck %s --check-prefix=CHECK0
+// CHECK: __tls_get_addr
+// CHECK: Creating thread 0
+// CHECK: __tls_get_addr
+// CHECK: Creating thread 1
+// CHECK: __tls_get_addr
+// CHECK: Creating thread 2
+// CHECK: __tls_get_addr
+// CHECK: Creating thread 3
+// CHECK: __tls_get_addr
+// Make sure that TLS slots don't leak
+// CHECK-NOT: num_live_dtls 5
+//
+// CHECK0-NOT: __tls_get_addr
+/*
+cc=your-compiler
+
+$cc stress_dtls.c -pthread -ldl
+for((i=0;i<100;i++)); do
+ $cc -fPIC -shared -DSO_NAME=f$i -o a.out-f$i.so stress_dtls.c;
+done
+./a.out 2 4 # <<<<<< 2 threads, 4 libs
+./a.out 3 50 # <<<<<< 3 threads, 50 libs
+*/
+#ifndef SO_NAME
+#define _GNU_SOURCE
+#include <assert.h>
+#include <dlfcn.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <stdint.h>
+
+typedef void **(*f_t)();
+
+__thread int my_tls;
+
+#define MAX_N_FUNCTIONS 1000
+f_t Functions[MAX_N_FUNCTIONS];
+
+void *PrintStuff(void *unused) {
+ uintptr_t stack;
+ // fprintf(stderr, "STACK: %p TLS: %p SELF: %p\n", &stack, &my_tls,
+ // (void *)pthread_self());
+ int i;
+ for (i = 0; i < MAX_N_FUNCTIONS; i++) {
+ if (!Functions[i]) break;
+ uintptr_t dtls = (uintptr_t)Functions[i]();
+ fprintf(stderr, " dtls[%03d]: %lx\n", i, dtls);
+ *(long*)dtls = 42; // check that this is writable.
+ }
+ return NULL;
+}
+
+int main(int argc, char *argv[]) {
+ int num_threads = 1;
+ int num_libs = 1;
+ if (argc >= 2)
+ num_threads = atoi(argv[1]);
+ if (argc >= 3)
+ num_libs = atoi(argv[2]);
+ assert(num_libs <= MAX_N_FUNCTIONS);
+
+ int lib;
+ for (lib = 0; lib < num_libs; lib++) {
+ char buf[4096];
+ snprintf(buf, sizeof(buf), "%s-f%d.so", argv[0], lib);
+ void *handle = dlopen(buf, RTLD_LAZY);
+ if (!handle) {
+ fprintf(stderr, "%s\n", dlerror());
+ exit(1);
+ }
+ snprintf(buf, sizeof(buf), "f%d", lib);
+ Functions[lib] = (f_t)dlsym(handle, buf);
+ if (!Functions[lib]) {
+ fprintf(stderr, "%s\n", dlerror());
+ exit(1);
+ }
+ fprintf(stderr, "LIB[%03d] %s: %p\n", lib, buf, Functions[lib]);
+ PrintStuff(0);
+
+ int i;
+ for (i = 0; i < num_threads; i++) {
+ pthread_t t;
+ fprintf(stderr, "Creating thread %d\n", i);
+ pthread_create(&t, 0, PrintStuff, 0);
+ pthread_join(t, 0);
+ }
+ }
+ return 0;
+}
+#else // SO_NAME
+#ifndef DTLS_SIZE
+# define DTLS_SIZE (1 << 17)
+#endif
+__thread void *huge_thread_local_array[DTLS_SIZE];
+void **SO_NAME() {
+ return &huge_thread_local_array[0];
+}
+#endif
diff --git a/test/asan/TestCases/Linux/swapcontext_test.cc b/test/asan/TestCases/Linux/swapcontext_test.cc
new file mode 100644
index 000000000000..86ed5930bcf4
--- /dev/null
+++ b/test/asan/TestCases/Linux/swapcontext_test.cc
@@ -0,0 +1,90 @@
+// Check that ASan plays well with easy cases of makecontext/swapcontext.
+
+// RUN: %clangxx_asan -O0 %s -o %t && %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O2 %s -o %t && %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O3 %s -o %t && %run %t 2>&1 | FileCheck %s
+//
+// This test is too sublte to try on non-x86 arch for now.
+// REQUIRES: x86_64-supported-target,i386-supported-target
+
+#include <stdio.h>
+#include <ucontext.h>
+#include <unistd.h>
+
+ucontext_t orig_context;
+ucontext_t child_context;
+
+const int kStackSize = 1 << 20;
+
+__attribute__((noinline))
+void Throw() {
+ throw 1;
+}
+
+__attribute__((noinline))
+void ThrowAndCatch() {
+ try {
+ Throw();
+ } catch(int a) {
+ printf("ThrowAndCatch: %d\n", a);
+ }
+}
+
+void Child(int mode) {
+ char x[32] = {0}; // Stack gets poisoned.
+ printf("Child: %p\n", x);
+ ThrowAndCatch(); // Simulate __asan_handle_no_return().
+ // (a) Do nothing, just return to parent function.
+ // (b) Jump into the original function. Stack remains poisoned unless we do
+ // something.
+ if (mode == 1) {
+ if (swapcontext(&child_context, &orig_context) < 0) {
+ perror("swapcontext");
+ _exit(0);
+ }
+ }
+}
+
+int Run(int arg, int mode, char *child_stack) {
+ printf("Child stack: %p\n", child_stack);
+ // Setup child context.
+ getcontext(&child_context);
+ child_context.uc_stack.ss_sp = child_stack;
+ child_context.uc_stack.ss_size = kStackSize / 2;
+ if (mode == 0) {
+ child_context.uc_link = &orig_context;
+ }
+ makecontext(&child_context, (void (*)())Child, 1, mode);
+ if (swapcontext(&orig_context, &child_context) < 0) {
+ perror("swapcontext");
+ return 0;
+ }
+ // Touch childs's stack to make sure it's unpoisoned.
+ for (int i = 0; i < kStackSize; i++) {
+ child_stack[i] = i;
+ }
+ return child_stack[arg];
+}
+
+int main(int argc, char **argv) {
+ char stack[kStackSize + 1];
+ // CHECK: WARNING: ASan doesn't fully support makecontext/swapcontext
+ int ret = 0;
+ ret += Run(argc - 1, 0, stack);
+ printf("Test1 passed\n");
+ // CHECK: Test1 passed
+ ret += Run(argc - 1, 1, stack);
+ printf("Test2 passed\n");
+ // CHECK: Test2 passed
+ char *heap = new char[kStackSize + 1];
+ ret += Run(argc - 1, 0, heap);
+ printf("Test3 passed\n");
+ // CHECK: Test3 passed
+ ret += Run(argc - 1, 1, heap);
+ printf("Test4 passed\n");
+ // CHECK: Test4 passed
+
+ delete [] heap;
+ return ret;
+}
diff --git a/test/asan/TestCases/Linux/syscalls.cc b/test/asan/TestCases/Linux/syscalls.cc
new file mode 100644
index 000000000000..bcdd5bc82119
--- /dev/null
+++ b/test/asan/TestCases/Linux/syscalls.cc
@@ -0,0 +1,25 @@
+// FIXME: https://code.google.com/p/address-sanitizer/issues/detail?id=316
+// XFAIL: android
+//
+// RUN: %clangxx_asan -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s
+
+#include <assert.h>
+#include <errno.h>
+#include <glob.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <sanitizer/linux_syscall_hooks.h>
+
+/* Test the presence of __sanitizer_syscall_ in the tool runtime, and general
+ sanity of their behaviour. */
+
+int main(int argc, char *argv[]) {
+ char buf[1000];
+ __sanitizer_syscall_pre_recvmsg(0, buf - 1, 0);
+ // CHECK: AddressSanitizer: stack-buffer-{{.*}}erflow
+ // CHECK: READ of size {{.*}} at {{.*}} thread T0
+ // CHECK: #0 {{.*}} in __sanitizer_syscall{{.*}}recvmsg
+ return 0;
+}
diff --git a/test/asan/TestCases/Linux/uar_signals.cc b/test/asan/TestCases/Linux/uar_signals.cc
new file mode 100644
index 000000000000..f42c3f666554
--- /dev/null
+++ b/test/asan/TestCases/Linux/uar_signals.cc
@@ -0,0 +1,70 @@
+// This test checks that the implementation of use-after-return
+// is async-signal-safe.
+// RUN: %clangxx_asan -O1 %s -o %t -pthread && %run %t
+// REQUIRES: stable-runtime
+#include <signal.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/time.h>
+#include <pthread.h>
+
+int *g;
+int n_signals;
+
+typedef void (*Sigaction)(int, siginfo_t *, void *);
+
+void SignalHandler(int, siginfo_t*, void*) {
+ int local;
+ g = &local;
+ n_signals++;
+ // printf("s: %p\n", &local);
+}
+
+static void EnableSigprof(Sigaction SignalHandler) {
+ struct sigaction sa;
+ sa.sa_sigaction = SignalHandler;
+ sa.sa_flags = SA_RESTART | SA_SIGINFO;
+ sigemptyset(&sa.sa_mask);
+ if (sigaction(SIGPROF, &sa, NULL) != 0) {
+ perror("sigaction");
+ abort();
+ }
+ struct itimerval timer;
+ timer.it_interval.tv_sec = 0;
+ timer.it_interval.tv_usec = 1;
+ timer.it_value = timer.it_interval;
+ if (setitimer(ITIMER_PROF, &timer, 0) != 0) {
+ perror("setitimer");
+ abort();
+ }
+}
+
+void RecursiveFunction(int depth) {
+ if (depth == 0) return;
+ int local;
+ g = &local;
+ // printf("r: %p\n", &local);
+ // printf("[%2d] n_signals: %d\n", depth, n_signals);
+ RecursiveFunction(depth - 1);
+ RecursiveFunction(depth - 1);
+}
+
+void *Thread(void *) {
+ RecursiveFunction(18);
+ return NULL;
+}
+
+int main(int argc, char **argv) {
+ EnableSigprof(SignalHandler);
+
+ for (int i = 0; i < 4; i++) {
+ fprintf(stderr, ".");
+ const int kNumThread = sizeof(void*) == 8 ? 16 : 8;
+ pthread_t t[kNumThread];
+ for (int i = 0; i < kNumThread; i++)
+ pthread_create(&t[i], 0, Thread, 0);
+ for (int i = 0; i < kNumThread; i++)
+ pthread_join(t[i], 0);
+ }
+ fprintf(stderr, "\n");
+}
diff --git a/test/asan/TestCases/Linux/unpoison_tls.cc b/test/asan/TestCases/Linux/unpoison_tls.cc
new file mode 100644
index 000000000000..9c1d74b28e5f
--- /dev/null
+++ b/test/asan/TestCases/Linux/unpoison_tls.cc
@@ -0,0 +1,35 @@
+// Test that TLS is unpoisoned on thread death.
+// REQUIRES: x86_64-supported-target,i386-supported-target
+
+// RUN: %clangxx_asan -O1 %s -pthread -o %t && %run %t 2>&1
+
+#include <assert.h>
+#include <pthread.h>
+#include <stdio.h>
+
+#include <sanitizer/asan_interface.h>
+
+__thread int64_t tls_var[2];
+
+volatile int64_t *p_tls_var;
+
+void *first(void *arg) {
+ ASAN_POISON_MEMORY_REGION(&tls_var, sizeof(tls_var));
+ p_tls_var = tls_var;
+ return 0;
+}
+
+void *second(void *arg) {
+ assert(tls_var == p_tls_var);
+ *p_tls_var = 1;
+ return 0;
+}
+
+int main(int argc, char *argv[]) {
+ pthread_t p;
+ assert(0 == pthread_create(&p, 0, first, 0));
+ assert(0 == pthread_join(p, 0));
+ assert(0 == pthread_create(&p, 0, second, 0));
+ assert(0 == pthread_join(p, 0));
+ return 0;
+}
diff --git a/test/asan/TestCases/Posix/allow_user_segv.cc b/test/asan/TestCases/Posix/allow_user_segv.cc
new file mode 100644
index 000000000000..b6443fab85df
--- /dev/null
+++ b/test/asan/TestCases/Posix/allow_user_segv.cc
@@ -0,0 +1,59 @@
+// Regression test for
+// https://code.google.com/p/address-sanitizer/issues/detail?id=180
+
+// RUN: %clangxx_asan -O0 %s -o %t && ASAN_OPTIONS=allow_user_segv_handler=true not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O2 %s -o %t && ASAN_OPTIONS=allow_user_segv_handler=true not %run %t 2>&1 | FileCheck %s
+
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+struct sigaction original_sigaction_sigbus;
+struct sigaction original_sigaction_sigsegv;
+
+void User_OnSIGSEGV(int signum, siginfo_t *siginfo, void *context) {
+ fprintf(stderr, "User sigaction called\n");
+ struct sigaction original_sigaction;
+ if (signum == SIGBUS)
+ original_sigaction = original_sigaction_sigbus;
+ else if (signum == SIGSEGV)
+ original_sigaction = original_sigaction_sigsegv;
+ else {
+ printf("Invalid signum");
+ exit(1);
+ }
+ if (original_sigaction.sa_flags | SA_SIGINFO)
+ original_sigaction.sa_sigaction(signum, siginfo, context);
+ else
+ original_sigaction.sa_handler(signum);
+}
+
+int DoSEGV() {
+ volatile int *x = 0;
+ return *x;
+}
+
+int InstallHandler(int signum, struct sigaction *original_sigaction) {
+ struct sigaction user_sigaction;
+ user_sigaction.sa_sigaction = User_OnSIGSEGV;
+ user_sigaction.sa_flags = SA_SIGINFO;
+ if (sigaction(signum, &user_sigaction, original_sigaction)) {
+ perror("sigaction");
+ return 1;
+ }
+ return 0;
+}
+
+int main() {
+ // Let's install handlers for both SIGSEGV and SIGBUS, since pre-Yosemite
+ // 32-bit Darwin triggers SIGBUS instead.
+ if (InstallHandler(SIGSEGV, &original_sigaction_sigsegv)) return 1;
+ if (InstallHandler(SIGBUS, &original_sigaction_sigbus)) return 1;
+ fprintf(stderr, "User sigaction installed\n");
+ return DoSEGV();
+}
+
+// CHECK: User sigaction installed
+// CHECK-NEXT: User sigaction called
+// CHECK-NEXT: ASAN:SIGSEGV
+// CHECK: AddressSanitizer: SEGV on unknown address
diff --git a/test/asan/TestCases/Posix/asan-symbolize-sanity-test.cc b/test/asan/TestCases/Posix/asan-symbolize-sanity-test.cc
new file mode 100644
index 000000000000..6ed02f4d5374
--- /dev/null
+++ b/test/asan/TestCases/Posix/asan-symbolize-sanity-test.cc
@@ -0,0 +1,63 @@
+// FIXME: https://code.google.com/p/address-sanitizer/issues/detail?id=316
+// XFAIL: android
+//
+// Check that asan_symbolize.py script works (for binaries, ASan RTL and
+// shared object files.
+
+// RUN: %clangxx_asan -O0 -DSHARED_LIB %s -fPIC -shared -o %t-so.so
+// RUN: %clangxx_asan -O0 %s -o %t
+// RUN: env ASAN_OPTIONS=symbolize=0 not %run %t 2>&1 | %asan_symbolize | FileCheck %s
+// XFAIL: arm-linux-gnueabi
+// XFAIL: armv7l-unknown-linux-gnueabihf
+
+#if !defined(SHARED_LIB)
+#include <dlfcn.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <string>
+
+using std::string;
+
+typedef void (fun_t)(int*, int);
+
+int main(int argc, char *argv[]) {
+ string path = string(argv[0]) + "-so.so";
+ printf("opening %s ... \n", path.c_str());
+ void *lib = dlopen(path.c_str(), RTLD_NOW);
+ if (!lib) {
+ printf("error in dlopen(): %s\n", dlerror());
+ return 1;
+ }
+ fun_t *inc2 = (fun_t*)dlsym(lib, "inc2");
+ if (!inc2) return 1;
+ printf("ok\n");
+ int *array = (int*)malloc(40);
+ inc2(array, 1);
+ inc2(array, -1); // BOOM
+ // CHECK: ERROR: AddressSanitizer: heap-buffer-overflow
+ // CHECK: READ of size 4 at 0x{{.*}}
+ // CHECK: #0 {{.*}} in inc2 {{.*}}asan-symbolize-sanity-test.cc:[[@LINE+21]]
+ // CHECK: #1 {{.*}} in main {{.*}}asan-symbolize-sanity-test.cc:[[@LINE-4]]
+ // CHECK: allocated by thread T{{.*}} here:
+ // CHECK: #{{.*}} in {{(wrap_|__interceptor_)?}}malloc
+ // CHECK: #{{.*}} in main {{.*}}asan-symbolize-sanity-test.cc:[[@LINE-9]]
+ return 0;
+}
+#else // SHARED_LIBS
+#include <stdio.h>
+#include <string.h>
+
+int pad[10];
+int GLOB[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+extern "C"
+void inc(int index) {
+ GLOB[index]++;
+}
+
+extern "C"
+void inc2(int *a, int index) {
+ a[index]++;
+}
+#endif // SHARED_LIBS
diff --git a/test/asan/TestCases/Posix/asprintf.cc b/test/asan/TestCases/Posix/asprintf.cc
new file mode 100644
index 000000000000..6946e5013d2c
--- /dev/null
+++ b/test/asan/TestCases/Posix/asprintf.cc
@@ -0,0 +1,20 @@
+// RUN: %clangxx_asan -O0 %s -o %t && %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O3 %s -o %t && %run %t 2>&1 | FileCheck %s
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+
+int main(int argc, char **argv) {
+ char *p;
+ int res = asprintf(&p, "%d", argc);
+ fprintf(stderr, "x%d %sx\n", res, p);
+ // CHECK: x1 1x
+ free(p);
+ fprintf(stderr, "DONE\n");
+ // CHECK: DONE
+ return 0;
+}
diff --git a/test/asan/TestCases/Posix/assign_large_valloc_to_global.cc b/test/asan/TestCases/Posix/assign_large_valloc_to_global.cc
new file mode 100644
index 000000000000..ad547ce0ce1b
--- /dev/null
+++ b/test/asan/TestCases/Posix/assign_large_valloc_to_global.cc
@@ -0,0 +1,9 @@
+// Make sure we don't report a leak nor hang.
+// RUN: %clangxx_asan -O3 %s -o %t && %run %t
+#include <stdlib.h>
+#include <unistd.h>
+#if !defined(__APPLE__) && !defined(__FreeBSD__)
+# include <malloc.h>
+#endif // !__APPLE__ && !__FreeBSD__
+int *p = (int*)valloc(1 << 20);
+int main() { }
diff --git a/test/asan/TestCases/Posix/glob.cc b/test/asan/TestCases/Posix/glob.cc
new file mode 100644
index 000000000000..e0eeb33cca24
--- /dev/null
+++ b/test/asan/TestCases/Posix/glob.cc
@@ -0,0 +1,33 @@
+// FIXME: https://code.google.com/p/address-sanitizer/issues/detail?id=316
+// XFAIL: android
+//
+// RUN: %clangxx_asan -O0 %s -o %t && %run %t %p 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O3 %s -o %t && %run %t %p 2>&1 | FileCheck %s
+// XFAIL: arm-linux-gnueabi
+
+#include <assert.h>
+#include <glob.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <string>
+
+
+int main(int argc, char *argv[]) {
+ std::string path = argv[1];
+ std::string pattern = path + "/glob_test_root/*a";
+ printf("pattern: %s\n", pattern.c_str());
+
+ glob_t globbuf;
+ int res = glob(pattern.c_str(), 0, 0, &globbuf);
+
+ printf("%d %s\n", errno, strerror(errno));
+ assert(res == 0);
+ assert(globbuf.gl_pathc == 2);
+ printf("%zu\n", strlen(globbuf.gl_pathv[0]));
+ printf("%zu\n", strlen(globbuf.gl_pathv[1]));
+ globfree(&globbuf);
+ printf("PASS\n");
+ // CHECK: PASS
+ return 0;
+}
diff --git a/test/asan/TestCases/Posix/glob_test_root/aa b/test/asan/TestCases/Posix/glob_test_root/aa
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/asan/TestCases/Posix/glob_test_root/aa
diff --git a/test/asan/TestCases/Posix/glob_test_root/ab b/test/asan/TestCases/Posix/glob_test_root/ab
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/asan/TestCases/Posix/glob_test_root/ab
diff --git a/test/asan/TestCases/Posix/glob_test_root/ba b/test/asan/TestCases/Posix/glob_test_root/ba
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/asan/TestCases/Posix/glob_test_root/ba
diff --git a/test/asan/TestCases/Posix/init-order-dlopen.cc b/test/asan/TestCases/Posix/init-order-dlopen.cc
new file mode 100644
index 000000000000..6f204775eb4e
--- /dev/null
+++ b/test/asan/TestCases/Posix/init-order-dlopen.cc
@@ -0,0 +1,72 @@
+// Regression test for
+// https://code.google.com/p/address-sanitizer/issues/detail?id=178
+
+// Assume we're on Darwin and try to pass -U to the linker. If this flag is
+// unsupported, don't use it.
+// RUN: %clangxx_asan -O0 -DSHARED_LIB %s \
+// RUN: -fPIC -shared -o %t-so.so -Wl,-U,_inc_global || \
+// RUN: %clangxx_asan -O0 -DSHARED_LIB %s \
+// RUN: -fPIC -shared -o %t-so.so
+// If the linker doesn't support --export-dynamic (which is ELF-specific),
+// try to link without that option.
+// FIXME: find a better solution.
+// RUN: %clangxx_asan -O0 %s -pthread -o %t -Wl,--export-dynamic || \
+// RUN: %clangxx_asan -O0 %s -pthread -o %t
+// RUN: ASAN_OPTIONS=strict_init_order=true %run %t 2>&1 | FileCheck %s
+#if !defined(SHARED_LIB)
+#include <dlfcn.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <string>
+
+using std::string;
+
+int foo() {
+ return 42;
+}
+int global = foo();
+
+__attribute__((visibility("default")))
+extern "C"
+void inc_global() {
+ global++;
+}
+
+void *global_poller(void *arg) {
+ while (true) {
+ if (global != 42)
+ break;
+ usleep(100);
+ }
+ return 0;
+}
+
+int main(int argc, char *argv[]) {
+ pthread_t p;
+ pthread_create(&p, 0, global_poller, 0);
+ string path = string(argv[0]) + "-so.so";
+ if (0 == dlopen(path.c_str(), RTLD_NOW)) {
+ fprintf(stderr, "dlerror: %s\n", dlerror());
+ return 1;
+ }
+ pthread_join(p, 0);
+ printf("PASSED\n");
+ // CHECK: PASSED
+ return 0;
+}
+#else // SHARED_LIB
+#include <stdio.h>
+#include <unistd.h>
+
+extern "C" void inc_global();
+
+int slow_init() {
+ sleep(1);
+ inc_global();
+ return 42;
+}
+
+int slowly_init_glob = slow_init();
+#endif // SHARED_LIB
diff --git a/test/asan/TestCases/Posix/ioctl.cc b/test/asan/TestCases/Posix/ioctl.cc
new file mode 100644
index 000000000000..78f152fe93fe
--- /dev/null
+++ b/test/asan/TestCases/Posix/ioctl.cc
@@ -0,0 +1,24 @@
+// RUN: %clangxx_asan -O0 -g %s -o %t && ASAN_OPTIONS=handle_ioctl=1 not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O3 -g %s -o %t && ASAN_OPTIONS=handle_ioctl=1 not %run %t 2>&1 | FileCheck %s
+
+// RUN: %clangxx_asan -O0 -g %s -o %t && %run %t
+// RUN: %clangxx_asan -O3 -g %s -o %t && %run %t
+
+#include <assert.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+int main(int argc, char **argv) {
+ int fd = socket(AF_INET, SOCK_DGRAM, 0);
+
+ int nonblock;
+ int res = ioctl(fd, FIONBIO, &nonblock + 1);
+ // CHECK: AddressSanitizer: stack-buffer-overflow
+ // CHECK: READ of size 4 at
+ // CHECK: {{#.* in main .*ioctl.cc:}}[[@LINE-3]]
+ assert(res == 0);
+ close(fd);
+ return 0;
+}
diff --git a/test/asan/TestCases/Posix/large_allocator_unpoisons_on_free.cc b/test/asan/TestCases/Posix/large_allocator_unpoisons_on_free.cc
new file mode 100644
index 000000000000..0a4998049cb0
--- /dev/null
+++ b/test/asan/TestCases/Posix/large_allocator_unpoisons_on_free.cc
@@ -0,0 +1,39 @@
+// Test that LargeAllocator unpoisons memory before releasing it to the OS.
+// RUN: %clangxx_asan %s -o %t
+// The memory is released only when the deallocated chunk leaves the quarantine,
+// otherwise the mmap(p, ...) call overwrites the malloc header.
+// RUN: ASAN_OPTIONS=quarantine_size=1 %run %t
+
+#include <assert.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#ifdef __ANDROID__
+#include <malloc.h>
+void *my_memalign(size_t boundary, size_t size) {
+ return memalign(boundary, size);
+}
+#else
+void *my_memalign(size_t boundary, size_t size) {
+ void *p;
+ posix_memalign(&p, boundary, size);
+ return p;
+}
+#endif
+
+int main() {
+ const long kPageSize = sysconf(_SC_PAGESIZE);
+ void *p = my_memalign(kPageSize, 1024 * 1024);
+ free(p);
+
+ char *q = (char *)mmap(p, kPageSize, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
+ assert(q == p);
+
+ memset(q, 42, kPageSize);
+
+ munmap(q, kPageSize);
+ return 0;
+}
diff --git a/test/asan/TestCases/Posix/lit.local.cfg b/test/asan/TestCases/Posix/lit.local.cfg
new file mode 100644
index 000000000000..60a9460820a6
--- /dev/null
+++ b/test/asan/TestCases/Posix/lit.local.cfg
@@ -0,0 +1,9 @@
+def getRoot(config):
+ if not config.parent:
+ return config
+ return getRoot(config.parent)
+
+root = getRoot(config)
+
+if root.host_os in ['Windows']:
+ config.unsupported = True
diff --git a/test/asan/TestCases/Posix/new_array_cookie_test.cc b/test/asan/TestCases/Posix/new_array_cookie_test.cc
new file mode 100644
index 000000000000..85d51f361835
--- /dev/null
+++ b/test/asan/TestCases/Posix/new_array_cookie_test.cc
@@ -0,0 +1,24 @@
+// REQUIRES: asan-64-bits
+// RUN: %clangxx_asan -O3 %s -o %t
+// RUN: not %run %t 2>&1 | FileCheck %s
+// RUN: ASAN_OPTIONS=poison_array_cookie=1 not %run %t 2>&1 | FileCheck %s
+// RUN: ASAN_OPTIONS=poison_array_cookie=0 not %run %t 2>&1 | FileCheck %s --check-prefix=NO_COOKIE
+#include <stdio.h>
+#include <stdlib.h>
+struct C {
+ int x;
+ ~C() {
+ fprintf(stderr, "ZZZZZZZZ\n");
+ exit(1);
+ }
+};
+
+int main(int argc, char **argv) {
+ C *buffer = new C[argc];
+ buffer[-2].x = 10;
+// CHECK: AddressSanitizer: heap-buffer-overflow
+// CHECK: in main {{.*}}new_array_cookie_test.cc:[[@LINE-2]]
+// CHECK: is located 0 bytes inside of 12-byte region
+// NO_COOKIE: ZZZZZZZZ
+ delete [] buffer;
+}
diff --git a/test/asan/TestCases/Posix/new_array_cookie_uaf_test.cc b/test/asan/TestCases/Posix/new_array_cookie_uaf_test.cc
new file mode 100644
index 000000000000..c35ccebb8c79
--- /dev/null
+++ b/test/asan/TestCases/Posix/new_array_cookie_uaf_test.cc
@@ -0,0 +1,38 @@
+// REQUIRES: asan-64-bits
+// RUN: %clangxx_asan -O3 %s -o %t
+// RUN: ASAN_OPTIONS=poison_array_cookie=1 not %run %t 2>&1 | FileCheck %s --check-prefix=COOKIE
+// RUN: ASAN_OPTIONS=poison_array_cookie=0 not %run %t 2>&1 | FileCheck %s --check-prefix=NO_COOKIE
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+int dtor_counter;
+struct C {
+ int x;
+ ~C() {
+ dtor_counter++;
+ fprintf(stderr, "DTOR %d\n", dtor_counter);
+ }
+};
+
+__attribute__((noinline)) void Delete(C *c) { delete[] c; }
+__attribute__((no_sanitize_address)) void Write42ToCookie(C *c) {
+ long *p = reinterpret_cast<long*>(c);
+ p[-1] = 42;
+}
+
+int main(int argc, char **argv) {
+ C *buffer = new C[argc];
+ delete [] buffer;
+ Write42ToCookie(buffer);
+ delete [] buffer;
+// COOKIE: DTOR 1
+// COOKIE-NOT: DTOR 2
+// COOKIE: AddressSanitizer: loaded array cookie from free-d memory
+// COOKIE: AddressSanitizer: attempting double-free
+// NO_COOKIE: DTOR 1
+// NO_COOKIE: DTOR 43
+// NO_COOKIE-NOT: DTOR 44
+// NO_COOKIE-NOT: AddressSanitizer: loaded array cookie from free-d memory
+// NO_COOKIE: AddressSanitizer: attempting double-free
+
+}
diff --git a/test/asan/TestCases/Posix/new_array_cookie_with_new_from_class.cc b/test/asan/TestCases/Posix/new_array_cookie_with_new_from_class.cc
new file mode 100644
index 000000000000..1cea6f68adb2
--- /dev/null
+++ b/test/asan/TestCases/Posix/new_array_cookie_with_new_from_class.cc
@@ -0,0 +1,38 @@
+// Test that we do not poison the array cookie if the operator new is defined
+// inside the class.
+// RUN: %clangxx_asan %s -o %t && %run %t
+//
+// XFAIL: android
+// XFAIL: armv7l-unknown-linux-gnueabihf
+#include <new>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <assert.h>
+struct Foo {
+ void *operator new(size_t s) { return Allocate(s); }
+ void *operator new[] (size_t s) { return Allocate(s); }
+ ~Foo();
+ static void *allocated;
+ static void *Allocate(size_t s) {
+ assert(!allocated);
+ return allocated = ::new char[s];
+ }
+};
+
+Foo::~Foo() {}
+void *Foo::allocated;
+
+Foo *getFoo(size_t n) {
+ return new Foo[n];
+}
+
+int main() {
+ Foo *foo = getFoo(10);
+ fprintf(stderr, "foo : %p\n", foo);
+ fprintf(stderr, "alloc: %p\n", Foo::allocated);
+ assert(reinterpret_cast<uintptr_t>(foo) ==
+ reinterpret_cast<uintptr_t>(Foo::allocated) + sizeof(void*));
+ *reinterpret_cast<uintptr_t*>(Foo::allocated) = 42;
+ return 0;
+}
diff --git a/test/asan/TestCases/Posix/readv.cc b/test/asan/TestCases/Posix/readv.cc
new file mode 100644
index 000000000000..27436a1ad3d9
--- /dev/null
+++ b/test/asan/TestCases/Posix/readv.cc
@@ -0,0 +1,32 @@
+// RUN: %clangxx_asan -O0 %s -o %t && %run %t
+// RUN: %clangxx_asan -O0 %s -DPOSITIVE -o %t && not %run %t 2>&1 | FileCheck %s
+
+// Test the readv() interceptor.
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/uio.h>
+#include <time.h>
+
+int main() {
+ char buf[2011];
+ struct iovec iov[2];
+#ifdef POSITIVE
+ char * volatile buf_ = buf;
+ iov[0].iov_base = buf_ - 1;
+#else
+ iov[0].iov_base = buf + 1;
+#endif
+ iov[0].iov_len = 5;
+ iov[1].iov_base = buf + 10;
+ iov[1].iov_len = 2000;
+ int fd = open("/etc/hosts", O_RDONLY);
+ assert(fd > 0);
+ readv(fd, iov, 2);
+ // CHECK: WRITE of size 5 at
+ close(fd);
+ return 0;
+}
diff --git a/test/asan/TestCases/Posix/shared-lib-test.cc b/test/asan/TestCases/Posix/shared-lib-test.cc
new file mode 100644
index 000000000000..a0827b5fefbf
--- /dev/null
+++ b/test/asan/TestCases/Posix/shared-lib-test.cc
@@ -0,0 +1,57 @@
+// RUN: %clangxx_asan -O0 -DSHARED_LIB %s -fPIC -shared -o %t-so.so
+// RUN: %clangxx_asan -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O1 -DSHARED_LIB %s -fPIC -shared -o %t-so.so
+// RUN: %clangxx_asan -O1 %s -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O2 -DSHARED_LIB %s -fPIC -shared -o %t-so.so
+// RUN: %clangxx_asan -O2 %s -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O3 -DSHARED_LIB %s -fPIC -shared -o %t-so.so
+// RUN: %clangxx_asan -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s
+// XFAIL: arm-linux-gnueabi
+
+#if !defined(SHARED_LIB)
+#include <dlfcn.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <string>
+
+using std::string;
+
+typedef void (fun_t)(int x);
+
+int main(int argc, char *argv[]) {
+ string path = string(argv[0]) + "-so.so";
+ printf("opening %s ... \n", path.c_str());
+ void *lib = dlopen(path.c_str(), RTLD_NOW);
+ if (!lib) {
+ printf("error in dlopen(): %s\n", dlerror());
+ return 1;
+ }
+ fun_t *inc = (fun_t*)dlsym(lib, "inc");
+ if (!inc) return 1;
+ printf("ok\n");
+ inc(1);
+ inc(-1); // BOOM
+ // CHECK: {{.*ERROR: AddressSanitizer: global-buffer-overflow}}
+ // CHECK: {{READ of size 4 at 0x.* thread T0}}
+ // CHECK: {{ #0 0x.*}}
+ // CHECK: {{ #1 0x.* in main .*shared-lib-test.cc:}}[[@LINE-4]]
+ return 0;
+}
+#else // SHARED_LIB
+#include <stdio.h>
+#include <string.h>
+
+int pad[10];
+int GLOB[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+extern "C"
+void inc(int index) {
+ GLOB[index]++;
+}
+
+extern "C"
+void inc2(int *a, int index) {
+ a[index]++;
+}
+#endif // SHARED_LIB
diff --git a/test/asan/TestCases/Posix/start-deactivated.cc b/test/asan/TestCases/Posix/start-deactivated.cc
new file mode 100644
index 000000000000..d60677a8a5bb
--- /dev/null
+++ b/test/asan/TestCases/Posix/start-deactivated.cc
@@ -0,0 +1,69 @@
+// Test for ASAN_OPTIONS=start_deactivated=1 mode.
+// Main executable is uninstrumented, but linked to ASan runtime. The shared
+// library is instrumented. Memory errors before dlopen are not detected.
+
+// RUN: %clangxx_asan -O0 -DSHARED_LIB %s -fPIC -shared -o %t-so.so
+// RUN: %clangxx -O0 %s -c -o %t.o
+// RUN: %clangxx_asan -O0 %t.o -o %t
+// RUN: ASAN_OPTIONS=start_deactivated=1 not %run %t 2>&1 | FileCheck %s
+// XFAIL: arm-linux-gnueabi
+// XFAIL: armv7l-unknown-linux-gnueabihf
+
+#if !defined(SHARED_LIB)
+#include <dlfcn.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <string>
+
+#include "sanitizer/asan_interface.h"
+
+void test_malloc_shadow() {
+ char *p = (char *)malloc(100);
+ char *q = (char *)__asan_region_is_poisoned(p + 95, 8);
+ fprintf(stderr, "=%zd=\n", q ? q - (p + 95) : -1);
+ free(p);
+}
+
+typedef void (*Fn)();
+
+int main(int argc, char *argv[]) {
+ test_malloc_shadow();
+ // CHECK: =-1=
+
+ std::string path = std::string(argv[0]) + "-so.so";
+ void *dso = dlopen(path.c_str(), RTLD_NOW);
+ if (!dso) {
+ fprintf(stderr, "dlopen failed: %s\n", dlerror());
+ return 1;
+ }
+
+ test_malloc_shadow();
+ // CHECK: =5=
+
+ void *fn = dlsym(dso, "do_another_bad_thing");
+ if (!fn) {
+ fprintf(stderr, "dlsym failed: %s\n", dlerror());
+ return 1;
+ }
+
+ ((Fn)fn)();
+ // CHECK: AddressSanitizer: heap-buffer-overflow
+ // CHECK: READ of size 1
+ // CHECK: {{#0 .* in do_another_bad_thing}}
+ // CHECK: is located 5 bytes to the right of 100-byte region
+ // CHECK: in do_another_bad_thing
+
+ return 0;
+}
+#else // SHARED_LIB
+#include <stdio.h>
+#include <stdlib.h>
+
+extern "C" void do_another_bad_thing() {
+ char *volatile p = (char *)malloc(100);
+ printf("%hhx\n", p[105]);
+}
+#endif // SHARED_LIB
diff --git a/test/asan/TestCases/Posix/strerror_r_test.cc b/test/asan/TestCases/Posix/strerror_r_test.cc
new file mode 100644
index 000000000000..e6df441770df
--- /dev/null
+++ b/test/asan/TestCases/Posix/strerror_r_test.cc
@@ -0,0 +1,14 @@
+// RUN: %clangxx_asan -O0 %s -o %t && %run %t
+
+// Regression test for PR17138.
+
+#include <assert.h>
+#include <string.h>
+#include <stdio.h>
+
+int main() {
+ char buf[1024];
+ char *res = (char *)strerror_r(300, buf, sizeof(buf));
+ printf("%p\n", res);
+ return 0;
+}
diff --git a/test/asan/TestCases/Posix/tsd_dtor_leak.cc b/test/asan/TestCases/Posix/tsd_dtor_leak.cc
new file mode 100644
index 000000000000..32253afc8b25
--- /dev/null
+++ b/test/asan/TestCases/Posix/tsd_dtor_leak.cc
@@ -0,0 +1,39 @@
+// Regression test for a leak in tsd:
+// https://code.google.com/p/address-sanitizer/issues/detail?id=233
+// RUN: %clangxx_asan -O1 %s -pthread -o %t
+// RUN: ASAN_OPTIONS=quarantine_size=1 %run %t
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <sanitizer/allocator_interface.h>
+
+static pthread_key_t tsd_key;
+
+void *Thread(void *) {
+ pthread_setspecific(tsd_key, malloc(10));
+ return 0;
+}
+
+static volatile void *v;
+
+void Dtor(void *tsd) {
+ v = malloc(10000);
+ free(tsd);
+ free((void*)v); // The bug was that this was leaking.
+}
+
+int main() {
+ assert(0 == pthread_key_create(&tsd_key, Dtor));
+ size_t old_heap_size = 0;
+ for (int i = 0; i < 10; i++) {
+ pthread_t t;
+ pthread_create(&t, 0, Thread, 0);
+ pthread_join(t, 0);
+ size_t new_heap_size = __sanitizer_get_heap_size();
+ fprintf(stderr, "heap size: new: %zd old: %zd\n", new_heap_size, old_heap_size);
+ if (old_heap_size)
+ assert(old_heap_size == new_heap_size);
+ old_heap_size = new_heap_size;
+ }
+}
diff --git a/test/asan/TestCases/Posix/wait.cc b/test/asan/TestCases/Posix/wait.cc
new file mode 100644
index 000000000000..99d0212acfab
--- /dev/null
+++ b/test/asan/TestCases/Posix/wait.cc
@@ -0,0 +1,45 @@
+// RUN: %clangxx_asan -DWAIT -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -DWAIT -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s
+
+// RUN: %clangxx_asan -DWAITPID -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -DWAITPID -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s
+
+// RUN: %clangxx_asan -DWAIT3 -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -DWAIT3 -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s
+
+// RUN: %clangxx_asan -DWAIT3_RUSAGE -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -DWAIT3_RUSAGE -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s
+
+
+#include <assert.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+int main(int argc, char **argv) {
+ pid_t pid = fork();
+ if (pid) { // parent
+ int x[3];
+ int *status = x + argc * 3;
+ int res;
+#if defined(WAIT)
+ res = wait(status);
+#elif defined(WAITPID)
+ res = waitpid(pid, status, WNOHANG);
+#elif defined(WAIT3)
+ res = wait3(status, WNOHANG, NULL);
+#elif defined(WAIT3_RUSAGE)
+ struct rusage *ru = (struct rusage*)(x + argc * 3);
+ int good_status;
+ res = wait3(&good_status, WNOHANG, ru);
+#endif
+ // CHECK: stack-buffer-overflow
+ // CHECK: {{WRITE of size .* at 0x.* thread T0}}
+ // CHECK: {{in .*wait}}
+ // CHECK: {{in main .*wait.cc:}}
+ // CHECK: is located in stack of thread T0 at offset
+ // CHECK: {{in main}}
+ return res == -1 ? 1 : 0;
+ }
+ // child
+ return 0;
+}
diff --git a/test/asan/TestCases/Posix/wait4.cc b/test/asan/TestCases/Posix/wait4.cc
new file mode 100644
index 000000000000..b95246efa0e4
--- /dev/null
+++ b/test/asan/TestCases/Posix/wait4.cc
@@ -0,0 +1,43 @@
+// RUN: %clangxx_asan -DWAIT4 -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -DWAIT4 -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s
+
+// RUN: %clangxx_asan -DWAIT4_RUSAGE -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -DWAIT4_RUSAGE -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s
+
+// XFAIL: android
+
+#include <assert.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+int main(int argc, char **argv) {
+ // This test passes on some versions of Android NDK and fails on other.
+ // https://code.google.com/p/memory-sanitizer/issues/detail?id=64
+ // Make it fail unconditionally on Android.
+#ifdef __ANDROID__
+ return 0;
+#endif
+
+ pid_t pid = fork();
+ if (pid) { // parent
+ int x[3];
+ int *status = x + argc * 3;
+ int res;
+#if defined(WAIT4)
+ res = wait4(pid, status, WNOHANG, NULL);
+#elif defined(WAIT4_RUSAGE)
+ struct rusage *ru = (struct rusage*)(x + argc * 3);
+ int good_status;
+ res = wait4(pid, &good_status, WNOHANG, ru);
+#endif
+ // CHECK: stack-buffer-overflow
+ // CHECK: {{WRITE of size .* at 0x.* thread T0}}
+ // CHECK: {{in .*wait}}
+ // CHECK: {{in main .*wait4.cc:}}
+ // CHECK: is located in stack of thread T0 at offset
+ // CHECK: {{in main}}
+ return res == -1 ? 1 : 0;
+ }
+ // child
+ return 0;
+}
diff --git a/test/asan/TestCases/Posix/waitid.cc b/test/asan/TestCases/Posix/waitid.cc
new file mode 100644
index 000000000000..8b516dca9086
--- /dev/null
+++ b/test/asan/TestCases/Posix/waitid.cc
@@ -0,0 +1,28 @@
+// RUN: %clangxx_asan -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s
+
+#include <assert.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <signal.h>
+
+int main(int argc, char **argv) {
+ pid_t pid = fork();
+ if (pid) { // parent
+ int x[3];
+ int *status = x + argc * 3;
+ int res;
+
+ siginfo_t *si = (siginfo_t*)(x + argc * 3);
+ res = waitid(P_ALL, 0, si, WEXITED | WNOHANG);
+ // CHECK: stack-buffer-overflow
+ // CHECK: {{WRITE of size .* at 0x.* thread T0}}
+ // CHECK: {{in .*waitid}}
+ // CHECK: {{in main .*waitid.cc:}}
+ // CHECK: is located in stack of thread T0 at offset
+ // CHECK: {{in main}}
+ return res != -1;
+ }
+ // child
+ return 0;
+}
diff --git a/test/asan/TestCases/Windows/aligned_mallocs.cc b/test/asan/TestCases/Windows/aligned_mallocs.cc
new file mode 100644
index 000000000000..df740b64e51c
--- /dev/null
+++ b/test/asan/TestCases/Windows/aligned_mallocs.cc
@@ -0,0 +1,29 @@
+// RUN: %clang_cl_asan -O0 %s -Fe%t
+// RUN: %run %t
+
+#include <windows.h>
+
+#define CHECK_ALIGNED(ptr,alignment) \
+ do { \
+ if (((uintptr_t)(ptr) % (alignment)) != 0) \
+ return __LINE__; \
+ } \
+ while(0)
+
+int main(void) {
+ int *p = (int*)_aligned_malloc(1024 * sizeof(int), 32);
+ CHECK_ALIGNED(p, 32);
+ p[512] = 0;
+ _aligned_free(p);
+
+ p = (int*)_aligned_malloc(128, 128);
+ CHECK_ALIGNED(p, 128);
+ p = (int*)_aligned_realloc(p, 2048 * sizeof(int), 128);
+ CHECK_ALIGNED(p, 128);
+ p[1024] = 0;
+ if (_aligned_msize(p, 128, 0) != 2048 * sizeof(int))
+ return __LINE__;
+ _aligned_free(p);
+
+ return 0;
+}
diff --git a/test/asan/TestCases/Windows/allocators_sanity.cc b/test/asan/TestCases/Windows/allocators_sanity.cc
new file mode 100644
index 000000000000..66a862d7aca5
--- /dev/null
+++ b/test/asan/TestCases/Windows/allocators_sanity.cc
@@ -0,0 +1,37 @@
+// RUN: %clang_cl_asan -O0 %s -Fe%t
+// RUN: %run %t | FileCheck %s
+
+#include <malloc.h>
+#include <stdio.h>
+
+int main() {
+ int *p = (int*)malloc(1024 * sizeof(int));
+ p[512] = 0;
+ free(p);
+
+ p = (int*)malloc(128);
+ p = (int*)realloc(p, 2048 * sizeof(int));
+ p[1024] = 0;
+ free(p);
+
+ p = (int*)calloc(16, sizeof(int));
+ if (p[8] != 0)
+ return 1;
+ p[15]++;
+ if (16 * sizeof(int) != _msize(p))
+ return 2;
+ free(p);
+
+ p = new int;
+ *p = 42;
+ delete p;
+
+ p = new int[42];
+ p[15]++;
+ delete [] p;
+
+ printf("All ok\n");
+// CHECK: All ok
+
+ return 0;
+}
diff --git a/test/asan/TestCases/Windows/beginthreadex.cc b/test/asan/TestCases/Windows/beginthreadex.cc
new file mode 100644
index 000000000000..f2b2b4511ad8
--- /dev/null
+++ b/test/asan/TestCases/Windows/beginthreadex.cc
@@ -0,0 +1,21 @@
+// RUN: %clang_cl_asan -O0 %s -Fe%t
+// RUN: %run %t
+
+#include <windows.h>
+#include <process.h>
+
+unsigned WINAPI thread_proc(void *) {
+ volatile char stack_buffer[42];
+ for (int i = 0; i < sizeof(stack_buffer); ++i)
+ stack_buffer[i] = 42;
+ return 0;
+}
+
+int main() {
+ HANDLE thr = (HANDLE)_beginthreadex(NULL, 0, thread_proc, NULL, 0, NULL);
+ if (thr == 0)
+ return 1;
+ if (WAIT_OBJECT_0 != WaitForSingleObject(thr, INFINITE))
+ return 2;
+ CloseHandle(thr);
+}
diff --git a/test/asan/TestCases/Windows/bitfield.cc b/test/asan/TestCases/Windows/bitfield.cc
new file mode 100644
index 000000000000..253a759b98df
--- /dev/null
+++ b/test/asan/TestCases/Windows/bitfield.cc
@@ -0,0 +1,21 @@
+// RUN: %clang_cl_asan -O0 %s -Fe%t
+// RUN: %run %t
+
+#include <windows.h>
+
+typedef struct _S {
+ unsigned int bf1:1;
+ unsigned int bf2:2;
+ unsigned int bf3:3;
+ unsigned int bf4:4;
+} S;
+
+int main(void) {
+ S *s = (S*)malloc(sizeof(S));
+ s->bf1 = 1;
+ s->bf2 = 2;
+ s->bf3 = 3;
+ s->bf4 = 4;
+ free(s);
+ return 0;
+}
diff --git a/test/asan/TestCases/Windows/bitfield_uaf.cc b/test/asan/TestCases/Windows/bitfield_uaf.cc
new file mode 100644
index 000000000000..f49d671e3eb3
--- /dev/null
+++ b/test/asan/TestCases/Windows/bitfield_uaf.cc
@@ -0,0 +1,34 @@
+// RUN: %clang_cl_asan -O0 %s -Fe%t
+// RUN: not %run %t 2>&1 | FileCheck %s
+
+#include <windows.h>
+
+typedef struct _S {
+ unsigned int bf1:1;
+ unsigned int bf2:2;
+ unsigned int bf3:3;
+ unsigned int bf4:4;
+} S;
+
+void make_access(S *s) {
+ s->bf2 = 2;
+// CHECK: AddressSanitizer: heap-use-after-free on address [[ADDR:0x[0-9a-f]+]]
+// CHECK: READ of size {{[124]}} at [[ADDR]]
+// CHECK: {{#0 .* make_access .*bitfield_uaf.cc}}:[[@LINE-3]]
+// CHECK: {{#1 .* main}}
+}
+
+int main(void) {
+ S *s = (S*)malloc(sizeof(S));
+ free(s);
+// CHECK: [[ADDR]] is located 0 bytes inside of 4-byte region
+// CHECK-LABEL: freed by thread T0 here:
+// CHECK: {{#0 .* free }}
+// CHECK: {{#1 .* main .*bitfield_uaf.cc}}:[[@LINE-4]]
+// CHECK-LABEL: previously allocated by thread T0 here:
+// CHECK: {{#0 .* malloc }}
+// CHECK: {{#1 .* main .*bitfield_uaf.cc}}:[[@LINE-8]]
+ make_access(s);
+ return 0;
+}
+
diff --git a/test/asan/TestCases/Windows/calloc_left_oob.cc b/test/asan/TestCases/Windows/calloc_left_oob.cc
new file mode 100644
index 000000000000..459025bde92c
--- /dev/null
+++ b/test/asan/TestCases/Windows/calloc_left_oob.cc
@@ -0,0 +1,17 @@
+// RUN: %clang_cl_asan -O0 %s -Fe%t
+// RUN: not %run %t 2>&1 | FileCheck %s
+
+#include <malloc.h>
+
+int main() {
+ int *buffer = (int*)calloc(42, sizeof(int));
+ buffer[-1] = 42;
+// CHECK: AddressSanitizer: heap-buffer-overflow on address [[ADDR:0x[0-9a-f]+]]
+// CHECK: WRITE of size 4 at [[ADDR]] thread T0
+// CHECK-NEXT: {{#0 .* main .*calloc_left_oob.cc}}:[[@LINE-3]]
+// CHECK: [[ADDR]] is located 4 bytes to the left of 168-byte region
+// CHECK: allocated by thread T0 here:
+// CHECK-NEXT: {{#0 .* calloc }}
+// CHECK-NEXT: {{#1 .* main .*calloc_left_oob.cc}}:[[@LINE-8]]
+ free(buffer);
+}
diff --git a/test/asan/TestCases/Windows/calloc_right_oob.cc b/test/asan/TestCases/Windows/calloc_right_oob.cc
new file mode 100644
index 000000000000..c976b87d9707
--- /dev/null
+++ b/test/asan/TestCases/Windows/calloc_right_oob.cc
@@ -0,0 +1,17 @@
+// RUN: %clang_cl_asan -O0 %s -Fe%t
+// RUN: not %run %t 2>&1 | FileCheck %s
+
+#include <malloc.h>
+
+int main() {
+ int *buffer = (int*)calloc(42, sizeof(int));
+ buffer[42] = 42;
+// CHECK: AddressSanitizer: heap-buffer-overflow on address [[ADDR:0x[0-9a-f]+]]
+// CHECK: WRITE of size 4 at [[ADDR]] thread T0
+// CHECK-NEXT: {{#0 .* main .*calloc_right_oob.cc}}:[[@LINE-3]]
+// CHECK: [[ADDR]] is located 0 bytes to the right of 168-byte region
+// CHECK: allocated by thread T0 here:
+// CHECK-NEXT: {{#0 .* calloc }}
+// CHECK-NEXT: {{#1 .* main .*calloc_right_oob.cc}}:[[@LINE-8]]
+ free(buffer);
+}
diff --git a/test/asan/TestCases/Windows/calloc_uaf.cc b/test/asan/TestCases/Windows/calloc_uaf.cc
new file mode 100644
index 000000000000..db5e70741b72
--- /dev/null
+++ b/test/asan/TestCases/Windows/calloc_uaf.cc
@@ -0,0 +1,20 @@
+// RUN: %clang_cl_asan -O0 %s -Fe%t
+// RUN: not %run %t 2>&1 | FileCheck %s
+
+#include <malloc.h>
+
+int main() {
+ int *buffer = (int*)calloc(42, sizeof(int));
+ free(buffer);
+ buffer[0] = 42;
+// CHECK: AddressSanitizer: heap-use-after-free on address [[ADDR:0x[0-9a-f]+]]
+// CHECK: WRITE of size 4 at [[ADDR]] thread T0
+// CHECK-NEXT: {{#0 .* main .*calloc_uaf.cc}}:[[@LINE-3]]
+// CHECK: [[ADDR]] is located 0 bytes inside of 168-byte region
+// CHECK: freed by thread T0 here:
+// CHECK-NEXT: {{#0 .* free }}
+// CHECK-NEXT: {{#1 .* main .*calloc_uaf.cc}}:[[@LINE-8]]
+// CHECK: previously allocated by thread T0 here:
+// CHECK-NEXT: {{#0 .* calloc }}
+// CHECK-NEXT: {{#1 .* main .*calloc_uaf.cc}}:[[@LINE-12]]
+}
diff --git a/test/asan/TestCases/Windows/crt_initializers.cc b/test/asan/TestCases/Windows/crt_initializers.cc
new file mode 100644
index 000000000000..084f8a45e18a
--- /dev/null
+++ b/test/asan/TestCases/Windows/crt_initializers.cc
@@ -0,0 +1,31 @@
+// RUN: %clang_cl_asan -O0 %s -Fe%t
+// RUN: %run %t | FileCheck %s
+
+// This is a test for http://code.google.com/p/address-sanitizer/issues/detail?id=305
+
+#include <stdio.h>
+
+typedef void (*FPTR)();
+
+// __xi_a and __xi_z are defined in VC/crt/src/crt0dat.c
+// and are located in .CRT$XIA and .CRT$XIZ respectively.
+extern "C" FPTR __xi_a, __xi_z;
+
+int main() {
+ unsigned count = 0;
+
+ // Iterate through CRT initializers.
+ for (FPTR* it = &__xi_a; it < &__xi_z; ++it) {
+ if (*it)
+ count++;
+ }
+
+ printf("Number of nonzero CRT initializers: %u\n", count);
+// CHECK: Number of nonzero CRT initializers
+}
+
+void call_me_maybe() {}
+
+#pragma data_seg(".CRT$XIB")
+// Add an initializer that shouldn't get its own redzone.
+FPTR run_on_startup = call_me_maybe;
diff --git a/test/asan/TestCases/Windows/demangled_names.cc b/test/asan/TestCases/Windows/demangled_names.cc
new file mode 100644
index 000000000000..a528555b1e16
--- /dev/null
+++ b/test/asan/TestCases/Windows/demangled_names.cc
@@ -0,0 +1,50 @@
+// RUN: %clang_cl_asan -O0 %s -Fe%t
+// RUN: not %run %t 2>&1 | FileCheck %s
+//
+// This test makes sure ASan symbolizes stack traces the way they are typically
+// symbolized on Windows.
+#include <malloc.h>
+
+namespace foo {
+// A template function in a namespace.
+template<int x>
+void bar(char *p) {
+ *p = x;
+}
+
+// A regular function in a namespace.
+void spam(char *p) {
+ bar<42>(p);
+}
+}
+
+// A multi-argument template with a bool template parameter.
+template<typename T, bool U>
+void baz(T t) {
+ if (U)
+ foo::spam(t);
+}
+
+template<typename T>
+struct A {
+ A(T v) { v_ = v; }
+ ~A();
+ char *v_;
+};
+
+// A destructor of a template class.
+template<>
+A<char*>::~A() {
+ baz<char*, true>(v_);
+}
+
+int main() {
+ char *buffer = (char*)malloc(42);
+ free(buffer);
+ A<char*> a(buffer);
+// CHECK: AddressSanitizer: heap-use-after-free on address [[ADDR:0x[0-9a-f]+]]
+// CHECK: foo::bar<42> {{.*}}demangled_names.cc
+// CHECK: foo::spam {{.*}}demangled_names.cc
+// CHECK: baz<char *,1> {{.*}}demangled_names.cc
+// CHECK: A<char *>::~A<char *> {{.*}}demangled_names.cc
+}
diff --git a/test/asan/TestCases/Windows/dll_aligned_mallocs.cc b/test/asan/TestCases/Windows/dll_aligned_mallocs.cc
new file mode 100644
index 000000000000..8b2c4d6dd957
--- /dev/null
+++ b/test/asan/TestCases/Windows/dll_aligned_mallocs.cc
@@ -0,0 +1,34 @@
+// RUN: %clang_cl_asan -O0 %p/dll_host.cc -Fe%t
+// RUN: %clang_cl_asan -LD -O0 %s -Fe%t.dll
+// RUN: %run %t %t.dll | FileCheck %s
+
+#include <malloc.h>
+#include <stdio.h>
+
+#define CHECK_ALIGNED(ptr,alignment) \
+ do { \
+ if (((uintptr_t)(ptr) % (alignment)) != 0) \
+ return __LINE__; \
+ } \
+ while(0)
+
+extern "C" __declspec(dllexport)
+int test_function() {
+ int *p = (int*)_aligned_malloc(1024 * sizeof(int), 32);
+ CHECK_ALIGNED(p, 32);
+ p[512] = 0;
+ _aligned_free(p);
+
+ p = (int*)_aligned_malloc(128, 128);
+ CHECK_ALIGNED(p, 128);
+ p = (int*)_aligned_realloc(p, 2048 * sizeof(int), 128);
+ CHECK_ALIGNED(p, 128);
+ p[1024] = 0;
+ if (_aligned_msize(p, 128, 0) != 2048 * sizeof(int))
+ return __LINE__;
+ _aligned_free(p);
+
+ printf("All ok\n");
+// CHECK: All ok
+ return 0;
+}
diff --git a/test/asan/TestCases/Windows/dll_allocators_sanity.cc b/test/asan/TestCases/Windows/dll_allocators_sanity.cc
new file mode 100644
index 000000000000..1d31f37ca904
--- /dev/null
+++ b/test/asan/TestCases/Windows/dll_allocators_sanity.cc
@@ -0,0 +1,39 @@
+// RUN: %clang_cl_asan -O0 %p/dll_host.cc -Fe%t
+// RUN: %clang_cl_asan -LD -O0 %s -Fe%t.dll
+// RUN: %run %t %t.dll | FileCheck %s
+
+#include <malloc.h>
+#include <stdio.h>
+
+extern "C" __declspec(dllexport)
+int test_function() {
+ int *p = (int*)malloc(1024 * sizeof(int));
+ p[512] = 0;
+ free(p);
+
+ p = (int*)malloc(128);
+ p = (int*)realloc(p, 2048 * sizeof(int));
+ p[1024] = 0;
+ free(p);
+
+ p = (int*)calloc(16, sizeof(int));
+ if (p[8] != 0)
+ return 1;
+ p[15]++;
+ if (16 * sizeof(int) != _msize(p))
+ return 2;
+ free(p);
+
+ p = new int;
+ *p = 42;
+ delete p;
+
+ p = new int[42];
+ p[15]++;
+ delete [] p;
+
+ printf("All ok\n");
+// CHECK: All ok
+
+ return 0;
+}
diff --git a/test/asan/TestCases/Windows/dll_and_lib.cc b/test/asan/TestCases/Windows/dll_and_lib.cc
new file mode 100644
index 000000000000..bddaa32df73b
--- /dev/null
+++ b/test/asan/TestCases/Windows/dll_and_lib.cc
@@ -0,0 +1,19 @@
+// Just make sure we can link an implib into another DLL
+// This used to fail between r212699 and r212814.
+// RUN: %clang_cl_asan -DCONFIG=1 %s -c -Fo%t.1.obj
+// RUN: link /nologo /DLL /OUT:%t.1.dll %t.1.obj %asan_dll_thunk
+// RUN: %clang_cl_asan -DCONFIG=2 %s -c -Fo%t.2.obj
+// RUN: link /nologo /DLL /OUT:%t.2.dll %t.2.obj %t.1.lib %asan_dll_thunk
+// REQUIRES: asan-static-runtime
+
+#if CONFIG==1
+extern "C" __declspec(dllexport) int f1() {
+ int x = 0;
+ return 1;
+}
+#else
+extern "C" __declspec(dllexport) int f2() {
+ int x = 0;
+ return 2;
+}
+#endif
diff --git a/test/asan/TestCases/Windows/dll_cerr.cc b/test/asan/TestCases/Windows/dll_cerr.cc
new file mode 100644
index 000000000000..8f1a699ba801
--- /dev/null
+++ b/test/asan/TestCases/Windows/dll_cerr.cc
@@ -0,0 +1,23 @@
+// RUN: %clang_cl_asan -O0 %p/dll_host.cc -Fe%t
+// RUN: %clang_cl_asan -LD -O0 %s -Fe%t.dll
+// RUN: %run %t %t.dll 2>&1 | FileCheck %s
+
+// Test that it works correctly even with ICF enabled.
+// RUN: %clang_cl_asan -LD -O0 %s -Fe%t.dll -link /OPT:REF /OPT:ICF
+// RUN: %run %t %t.dll 2>&1 | FileCheck %s
+
+#include <iostream>
+
+extern "C" __declspec(dllexport)
+int test_function() {
+ // Just make sure we can use cout.
+ std::cout << "All ok\n";
+// CHECK: All ok
+
+ // This line forces a declaration of some global basic_ostream internal object that
+ // calls memcpy() in its constructor. This doesn't work if __asan_init is not
+ // called early enough.
+ std::cout << 42;
+// CHECK: 42
+ return 0;
+}
diff --git a/test/asan/TestCases/Windows/dll_host.cc b/test/asan/TestCases/Windows/dll_host.cc
new file mode 100644
index 000000000000..d3b4c149d009
--- /dev/null
+++ b/test/asan/TestCases/Windows/dll_host.cc
@@ -0,0 +1,49 @@
+// This is a host program for DLL tests.
+//
+// Just make sure we can compile this.
+// The actual compile&run sequence is to be done by the DLL tests.
+// RUN: %clang_cl_asan -O0 %s -Fe%t
+//
+// Get the list of ASan wrappers exported by the main module RTL:
+// RUN: dumpbin /EXPORTS %t | grep -o "__asan_wrap[^ ]*" | grep -v @ | sort | uniq > %t.exported_wrappers
+//
+// Get the list of ASan wrappers imported by the DLL RTL:
+// RUN: grep INTERCEPT_LIBRARY_FUNCTION %p/../../../../lib/asan/asan_win_dll_thunk.cc | grep -v define | sed "s/.*(\(.*\)).*/__asan_wrap_\1/" | sort | uniq > %t.dll_imports
+//
+// Now make sure the DLL thunk imports everything:
+// RUN: echo
+// RUN: echo "=== NOTE === If you see a mismatch below, please update asan_win_dll_thunk.cc"
+// RUN: diff %t.dll_imports %t.exported_wrappers
+// REQUIRES: asan-static-runtime
+
+#include <stdio.h>
+#include <windows.h>
+
+int main(int argc, char **argv) {
+ if (argc != 2) {
+ printf("Usage: %s [client].dll\n", argv[0]);
+ return 101;
+ }
+
+ const char *dll_name = argv[1];
+
+ HMODULE h = LoadLibrary(dll_name);
+ if (!h) {
+ printf("Could not load DLL: %s (code: %lu)!\n",
+ dll_name, GetLastError());
+ return 102;
+ }
+
+ typedef int (*test_function)();
+ test_function gf = (test_function)GetProcAddress(h, "test_function");
+ if (!gf) {
+ printf("Could not locate test_function in the DLL!\n");
+ FreeLibrary(h);
+ return 103;
+ }
+
+ int ret = gf();
+
+ FreeLibrary(h);
+ return ret;
+}
diff --git a/test/asan/TestCases/Windows/dll_intercept_memchr.cc b/test/asan/TestCases/Windows/dll_intercept_memchr.cc
new file mode 100644
index 000000000000..1435bdc50127
--- /dev/null
+++ b/test/asan/TestCases/Windows/dll_intercept_memchr.cc
@@ -0,0 +1,21 @@
+// RUN: %clang_cl_asan -O0 %p/dll_host.cc -Fe%t
+// RUN: %clang_cl_asan -LD -O0 %s -Fe%t.dll
+// RUN: not %run %t %t.dll 2>&1 | FileCheck %s
+
+#include <string.h>
+
+extern "C" __declspec(dllexport)
+int test_function() {
+ char buff[6] = "Hello";
+
+ memchr(buff, 'z', 7);
+// CHECK: AddressSanitizer: stack-buffer-overflow on address [[ADDR:0x[0-9a-f]+]]
+// CHECK: READ of size 7 at [[ADDR]] thread T0
+// CHECK-NEXT: __asan_wrap_memchr
+// CHECK-NEXT: memchr
+// CHECK-NEXT: test_function {{.*}}dll_intercept_memchr.cc:[[@LINE-5]]
+// CHECK: Address [[ADDR]] is located in stack of thread T0 at offset {{.*}} in frame
+// CHECK-NEXT: test_function {{.*}}dll_intercept_memchr.cc
+// CHECK: 'buff' <== Memory access at offset {{.*}} overflows this variable
+ return 0;
+}
diff --git a/test/asan/TestCases/Windows/dll_intercept_memcpy.cc b/test/asan/TestCases/Windows/dll_intercept_memcpy.cc
new file mode 100644
index 000000000000..736e6969d521
--- /dev/null
+++ b/test/asan/TestCases/Windows/dll_intercept_memcpy.cc
@@ -0,0 +1,32 @@
+// RUN: %clang_cl_asan -O0 %p/dll_host.cc -Fe%t
+// RUN: %clang_cl_asan -LD -O0 %s -Fe%t.dll
+// RUN: not %run %t %t.dll 2>&1 | FileCheck %s
+
+// Test that it works correctly even with ICF enabled.
+// RUN: %clang_cl_asan -LD -O0 %s -Fe%t.dll -link /OPT:REF /OPT:ICF
+// RUN: not %run %t %t.dll 2>&1 | FileCheck %s
+
+#include <stdio.h>
+#include <string.h>
+
+extern "C" __declspec(dllexport)
+int test_function() {
+ char buff1[6] = "Hello", buff2[5];
+
+ memcpy(buff2, buff1, 5);
+ if (buff1[2] != buff2[2])
+ return 2;
+ printf("Initial test OK\n");
+ fflush(0);
+// CHECK: Initial test OK
+
+ memcpy(buff2, buff1, 6);
+// CHECK: AddressSanitizer: stack-buffer-overflow on address [[ADDR:0x[0-9a-f]+]]
+// CHECK: WRITE of size 6 at [[ADDR]] thread T0
+// CHECK-NEXT: __asan_{{.*}}memcpy
+// CHECK-NEXT: test_function {{.*}}dll_intercept_memcpy.cc:[[@LINE-4]]
+// CHECK: Address [[ADDR]] is located in stack of thread T0 at offset {{.*}} in frame
+// CHECK-NEXT: test_function {{.*}}dll_intercept_memcpy.cc
+// CHECK: 'buff2' <== Memory access at offset {{.*}} overflows this variable
+ return 0;
+}
diff --git a/test/asan/TestCases/Windows/dll_intercept_memcpy_indirect.cc b/test/asan/TestCases/Windows/dll_intercept_memcpy_indirect.cc
new file mode 100644
index 000000000000..c5f44df3faaf
--- /dev/null
+++ b/test/asan/TestCases/Windows/dll_intercept_memcpy_indirect.cc
@@ -0,0 +1,34 @@
+// RUN: %clang_cl_asan -O0 %p/dll_host.cc -Fe%t
+// RUN: %clang_cl_asan -LD -O0 %s -Fe%t.dll
+// RUN: not %run %t %t.dll 2>&1 | FileCheck %s
+
+#include <stdio.h>
+#include <string.h>
+
+void call_memcpy(void* (*f)(void *, const void *, size_t),
+ void *a, const void *b, size_t c) {
+ f(a, b, c);
+}
+
+extern "C" __declspec(dllexport)
+int test_function() {
+ char buff1[6] = "Hello", buff2[5];
+
+ call_memcpy(&memcpy, buff2, buff1, 5);
+ if (buff1[2] != buff2[2])
+ return 2;
+ printf("Initial test OK\n");
+ fflush(0);
+// CHECK: Initial test OK
+
+ call_memcpy(&memcpy, buff2, buff1, 6);
+// CHECK: AddressSanitizer: stack-buffer-overflow on address [[ADDR:0x[0-9a-f]+]]
+// CHECK: WRITE of size 6 at [[ADDR]] thread T0
+// CHECK-NEXT: __asan_{{.*}}memcpy
+// CHECK-NEXT: call_memcpy
+// CHECK-NEXT: test_function {{.*}}dll_intercept_memcpy_indirect.cc:[[@LINE-5]]
+// CHECK: Address [[ADDR]] is located in stack of thread T0 at offset {{.*}} in frame
+// CHECK-NEXT: test_function {{.*}}dll_intercept_memcpy_indirect.cc
+// CHECK: 'buff2' <== Memory access at offset {{.*}} overflows this variable
+ return 0;
+}
diff --git a/test/asan/TestCases/Windows/dll_intercept_memset.cc b/test/asan/TestCases/Windows/dll_intercept_memset.cc
new file mode 100644
index 000000000000..d4be376f2458
--- /dev/null
+++ b/test/asan/TestCases/Windows/dll_intercept_memset.cc
@@ -0,0 +1,32 @@
+// RUN: %clang_cl_asan -O0 %p/dll_host.cc -Fe%t
+// RUN: %clang_cl_asan -LD -O0 %s -Fe%t.dll
+// RUN: not %run %t %t.dll 2>&1 | FileCheck %s
+
+// Test that it works correctly even with ICF enabled.
+// RUN: %clang_cl_asan -LD -O0 %s -Fe%t.dll -link /OPT:REF /OPT:ICF
+// RUN: not %run %t %t.dll 2>&1 | FileCheck %s
+
+#include <stdio.h>
+#include <string.h>
+
+extern "C" __declspec(dllexport)
+int test_function() {
+ char buff[5] = "aaaa";
+
+ memset(buff, 'b', 5);
+ if (buff[2] != 'b')
+ return 2;
+ printf("Initial test OK\n");
+ fflush(0);
+// CHECK: Initial test OK
+
+ memset(buff, 'c', 6);
+// CHECK: AddressSanitizer: stack-buffer-overflow on address [[ADDR:0x[0-9a-f]+]]
+// CHECK: WRITE of size 6 at [[ADDR]] thread T0
+// CHECK-NEXT: __asan_memset
+// CHECK-NEXT: test_function {{.*}}dll_intercept_memset.cc:[[@LINE-4]]
+// CHECK: Address [[ADDR]] is located in stack of thread T0 at offset {{.*}} in frame
+// CHECK-NEXT: test_function {{.*}}dll_intercept_memset.cc
+// CHECK: 'buff' <== Memory access at offset {{.*}} overflows this variable
+ return 0;
+}
diff --git a/test/asan/TestCases/Windows/dll_intercept_strlen.cc b/test/asan/TestCases/Windows/dll_intercept_strlen.cc
new file mode 100644
index 000000000000..f41d47858bee
--- /dev/null
+++ b/test/asan/TestCases/Windows/dll_intercept_strlen.cc
@@ -0,0 +1,28 @@
+// RUN: %clang_cl_asan -O0 %p/dll_host.cc -Fe%t
+// RUN: %clang_cl_asan -LD -O0 %s -Fe%t.dll
+// RUN: not %run %t %t.dll 2>&1 | FileCheck %s
+
+#include <stdio.h>
+#include <string.h>
+
+extern "C" __declspec(dllexport)
+int test_function() {
+ char str[] = "Hello!";
+ if (6 != strlen(str))
+ return 1;
+ printf("Initial test OK\n");
+ fflush(0);
+// CHECK: Initial test OK
+
+ str[6] = '!'; // Removes '\0' at the end!
+ int len = strlen(str);
+// CHECK: AddressSanitizer: stack-buffer-overflow on address [[ADDR:0x[0-9a-f]+]]
+// FIXME: Should be READ of size 1, see issue 155.
+// CHECK: READ of size {{[0-9]+}} at [[ADDR]] thread T0
+// CHECK-NEXT: {{#0 .*}}strlen
+// CHECK-NEXT: {{#1 .* test_function .*}}dll_intercept_strlen.cc:[[@LINE-5]]
+//
+// CHECK: Address [[ADDR]] is located in stack of thread T0 at offset {{.*}} in frame
+// CHECK-NEXT: test_function {{.*}}dll_intercept_strlen.cc:
+ return len > 42;
+}
diff --git a/test/asan/TestCases/Windows/dll_large_function.cc b/test/asan/TestCases/Windows/dll_large_function.cc
new file mode 100644
index 000000000000..039d01f84ba5
--- /dev/null
+++ b/test/asan/TestCases/Windows/dll_large_function.cc
@@ -0,0 +1,12 @@
+// Make sure we can link a DLL with large functions which would mean
+// functions such as __asan_loadN and __asan_storeN will be called
+// from the DLL. We simulate the large function with
+// -mllvm -asan-instrumentation-with-call-threshold=0.
+// RUN: %clang_cl_asan %s -c -Fo%t.obj -mllvm -asan-instrumentation-with-call-threshold=0
+// RUN: link /nologo /DLL /OUT:%t.dll %t.obj %asan_dll_thunk
+// REQUIRES: asan-static-runtime
+
+void f(long* foo, long* bar) {
+ // One load and one store
+ *foo = *bar;
+}
diff --git a/test/asan/TestCases/Windows/dll_malloc_left_oob.cc b/test/asan/TestCases/Windows/dll_malloc_left_oob.cc
new file mode 100644
index 000000000000..0653ea45f6ef
--- /dev/null
+++ b/test/asan/TestCases/Windows/dll_malloc_left_oob.cc
@@ -0,0 +1,23 @@
+// RUN: %clang_cl_asan -O0 %p/dll_host.cc -Fe%t
+// RUN: %clang_cl_asan -LD -O0 %s -Fe%t.dll
+// RUN: not %run %t %t.dll 2>&1 | FileCheck %s
+
+#include <malloc.h>
+extern "C" __declspec(dllexport)
+int test_function() {
+ char *buffer = (char*)malloc(42);
+ buffer[-1] = 42;
+// CHECK: AddressSanitizer: heap-buffer-overflow on address [[ADDR:0x[0-9a-f]+]]
+// CHECK: WRITE of size 1 at [[ADDR]] thread T0
+// CHECK-NEXT: test_function {{.*}}dll_malloc_left_oob.cc:[[@LINE-3]]
+// CHECK-NEXT: main {{.*}}dll_host.cc
+//
+// CHECK: [[ADDR]] is located 1 bytes to the left of 42-byte region
+// CHECK-LABEL: allocated by thread T0 here:
+// CHECK-NEXT: malloc
+// CHECK-NEXT: test_function {{.*}}dll_malloc_left_oob.cc:[[@LINE-10]]
+// CHECK-NEXT: main {{.*}}dll_host.cc
+// CHECK-LABEL: SUMMARY
+ free(buffer);
+ return 0;
+}
diff --git a/test/asan/TestCases/Windows/dll_malloc_uaf.cc b/test/asan/TestCases/Windows/dll_malloc_uaf.cc
new file mode 100644
index 000000000000..b286380ac445
--- /dev/null
+++ b/test/asan/TestCases/Windows/dll_malloc_uaf.cc
@@ -0,0 +1,28 @@
+// RUN: %clang_cl_asan -O0 %p/dll_host.cc -Fe%t
+// RUN: %clang_cl_asan -LD -O0 %s -Fe%t.dll
+// RUN: not %run %t %t.dll 2>&1 | FileCheck %s
+
+#include <malloc.h>
+
+extern "C" __declspec(dllexport)
+int test_function() {
+ int *buffer = (int*)malloc(42);
+ free(buffer);
+ buffer[0] = 42;
+// CHECK: AddressSanitizer: heap-use-after-free on address [[ADDR:0x[0-9a-f]+]]
+// CHECK: WRITE of size 4 at [[ADDR]] thread T0
+// CHECK-NEXT: test_function {{.*}}dll_malloc_uaf.cc:[[@LINE-3]]
+// CHECK-NEXT: main {{.*}}dll_host
+//
+// CHECK: [[ADDR]] is located 0 bytes inside of 42-byte region
+// CHECK-LABEL: freed by thread T0 here:
+// CHECK-NEXT: free
+// CHECK-NEXT: test_function {{.*}}dll_malloc_uaf.cc:[[@LINE-10]]
+// CHECK-NEXT: main {{.*}}dll_host
+//
+// CHECK-LABEL: previously allocated by thread T0 here:
+// CHECK-NEXT: malloc
+// CHECK-NEXT: test_function {{.*}}dll_malloc_uaf.cc:[[@LINE-16]]
+// CHECK-NEXT: main {{.*}}dll_host
+ return 0;
+}
diff --git a/test/asan/TestCases/Windows/dll_noreturn.cc b/test/asan/TestCases/Windows/dll_noreturn.cc
new file mode 100644
index 000000000000..6ec90725145f
--- /dev/null
+++ b/test/asan/TestCases/Windows/dll_noreturn.cc
@@ -0,0 +1,28 @@
+// RUN: %clang_cl_asan -O0 %p/dll_host.cc -Fe%t
+// RUN: %clang_cl_asan -LD -O0 %s -Fe%t.dll
+// RUN: not %run %t %t.dll 2>&1 | FileCheck %s
+
+#include <process.h>
+
+void noreturn_f() {
+ int subscript = -1;
+ char buffer[42];
+ buffer[subscript] = 42;
+ _exit(1);
+// CHECK: AddressSanitizer: stack-buffer-overflow on address [[ADDR:0x[0-9a-f]+]]
+// CHECK: WRITE of size 1 at [[ADDR]] thread T0
+// CHECK-NEXT: noreturn_f {{.*}}dll_noreturn.cc:[[@LINE-4]]
+// CHECK-NEXT: test_function {{.*}}dll_noreturn.cc
+// CHECK-NEXT: main {{.*}}dll_host.cc
+//
+// CHECK: Address [[ADDR]] is located in stack of thread T0 at offset [[OFFSET:.*]] in frame
+// CHECK-NEXT: noreturn_f {{.*}}dll_noreturn.cc
+// CHECK: 'buffer' <== Memory access at offset [[OFFSET]] underflows this variable
+// CHECK-LABEL: SUMMARY
+}
+
+extern "C" __declspec(dllexport)
+int test_function() {
+ noreturn_f();
+ return 0;
+}
diff --git a/test/asan/TestCases/Windows/dll_null_deref.cc b/test/asan/TestCases/Windows/dll_null_deref.cc
new file mode 100644
index 000000000000..0fb18de29163
--- /dev/null
+++ b/test/asan/TestCases/Windows/dll_null_deref.cc
@@ -0,0 +1,18 @@
+// RUN: %clang_cl_asan -O0 %p/dll_host.cc -Fe%t
+// RUN: %clang_cl_asan -LD -O0 %s -Fe%t.dll
+// RUN: not %run %t %t.dll 2>&1 | FileCheck %s
+
+__attribute__((noinline))
+static void NullDeref(int *ptr) {
+ // CHECK: ERROR: AddressSanitizer: access-violation on unknown address
+ // CHECK: {{0x0*000.. .*pc 0x.*}}
+ ptr[10]++; // BOOM
+}
+
+extern "C" __declspec(dllexport)
+int test_function() {
+ NullDeref((int*)0);
+ // CHECK: {{ #1 0x.* in test_function .*\dll_null_deref.cc:}}[[@LINE-1]]
+ // CHECK: AddressSanitizer can not provide additional info.
+ return 0;
+}
diff --git a/test/asan/TestCases/Windows/dll_operator_array_new_left_oob.cc b/test/asan/TestCases/Windows/dll_operator_array_new_left_oob.cc
new file mode 100644
index 000000000000..736ce80cc32a
--- /dev/null
+++ b/test/asan/TestCases/Windows/dll_operator_array_new_left_oob.cc
@@ -0,0 +1,25 @@
+// RUN: %clang_cl_asan -O0 %p/dll_host.cc -Fe%t
+// RUN: %clang_cl_asan -LD -O0 %s -Fe%t.dll
+// RUN: not %run %t %t.dll 2>&1 | FileCheck %s
+
+extern "C" __declspec(dllexport)
+int test_function() {
+ char *buffer = new char[42];
+ buffer[-1] = 42;
+// CHECK: AddressSanitizer: heap-buffer-overflow on address [[ADDR:0x[0-9a-f]+]]
+// CHECK: WRITE of size 1 at [[ADDR]] thread T0
+// CHECK-NEXT: test_function {{.*}}dll_operator_array_new_left_oob.cc:[[@LINE-3]]
+// CHECK-NEXT: main {{.*}}dll_host.cc
+//
+// CHECK: [[ADDR]] is located 1 bytes to the left of 42-byte region
+// CHECK-LABEL: allocated by thread T0 here:
+// FIXME: Should get rid of the malloc/free frames called from the inside of
+// operator new/delete in DLLs when using -MT CRT.
+// FIXME: The 'operator new' frame should have [].
+// CHECK: operator new
+// CHECK-NEXT: test_function {{.*}}dll_operator_array_new_left_oob.cc:[[@LINE-13]]
+// CHECK-NEXT: main {{.*}}dll_host.cc
+// CHECK-LABEL: SUMMARY
+ delete [] buffer;
+ return 0;
+}
diff --git a/test/asan/TestCases/Windows/dll_operator_array_new_with_dtor_left_oob.cc b/test/asan/TestCases/Windows/dll_operator_array_new_with_dtor_left_oob.cc
new file mode 100644
index 000000000000..8306a737bfff
--- /dev/null
+++ b/test/asan/TestCases/Windows/dll_operator_array_new_with_dtor_left_oob.cc
@@ -0,0 +1,33 @@
+// RUN: %clang_cl_asan -O0 %p/dll_host.cc -Fe%t
+// RUN: %clang_cl_asan -LD -O0 %s -Fe%t.dll
+// RUN: not %run %t %t.dll 2>&1 | FileCheck %s
+
+struct C {
+ int x;
+ ~C() {}
+};
+
+extern "C" __declspec(dllexport)
+int test_function() {
+ C *buffer = new C[42];
+ buffer[-2].x = 42;
+// CHECK: AddressSanitizer: heap-buffer-overflow on address [[ADDR:0x[0-9a-f]+]]
+// CHECK: WRITE of size 4 at [[ADDR]] thread T0
+// CHECK-NEXT: test_function {{.*}}dll_operator_array_new_with_dtor_left_oob.cc:[[@LINE-3]]
+// CHECK-NEXT: main {{.*}}dll_host.cc
+//
+// FIXME: Currently it says "4 bytes ... left of 172-byte region",
+// should be "8 bytes ... left of 168-byte region", see
+// https://code.google.com/p/address-sanitizer/issues/detail?id=314
+// CHECK: [[ADDR]] is located {{.*}} bytes to the left of 172-byte region
+// FIXME: Should get rid of the malloc/free frames called from the inside of
+// operator new/delete in DLLs when using -MT CRT.
+// FIXME: The operator new frame should have [].
+// CHECK-LABEL: allocated by thread T0 here:
+// CHECK: operator new
+// CHECK-NEXT: test_function {{.*}}dll_operator_array_new_with_dtor_left_oob.cc:[[@LINE-16]]
+// CHECK-NEXT: main {{.*}}dll_host.cc
+// CHECK-LABEL: SUMMARY
+ delete [] buffer;
+ return 0;
+}
diff --git a/test/asan/TestCases/Windows/dll_poison_unpoison.cc b/test/asan/TestCases/Windows/dll_poison_unpoison.cc
new file mode 100644
index 000000000000..d486cb122251
--- /dev/null
+++ b/test/asan/TestCases/Windows/dll_poison_unpoison.cc
@@ -0,0 +1,35 @@
+// RUN: %clang_cl_asan -O0 %p/dll_host.cc -Fe%t
+// RUN: %clang_cl_asan -LD -O0 %s -Fe%t.dll
+// RUN: not %run %t %t.dll 2>&1 | FileCheck %s
+
+#include <sanitizer/asan_interface.h>
+
+void should_not_crash(volatile char *c) {
+ *c = 42;
+}
+
+void should_crash(volatile char *c) {
+ *c = 42;
+}
+
+extern "C" __declspec(dllexport)
+int test_function() {
+ char buffer[256];
+ should_not_crash(&buffer[0]);
+ __asan_poison_memory_region(buffer, 128);
+ should_not_crash(&buffer[192]);
+ __asan_unpoison_memory_region(buffer, 64);
+ should_not_crash(&buffer[32]);
+
+ should_crash(&buffer[96]);
+// CHECK: AddressSanitizer: use-after-poison on address [[ADDR:0x[0-9a-f]+]]
+// CHECK-NEXT: WRITE of size 1 at [[ADDR]] thread T0
+// CHECK-NEXT: should_crash {{.*}}\dll_poison_unpoison.cc
+// CHECK-NEXT: test_function {{.*}}\dll_poison_unpoison.cc:[[@LINE-4]]
+// CHECK-NEXT: main
+//
+// CHECK: [[ADDR]] is located in stack of thread T0 at offset [[OFFSET:.*]] in frame
+// CHECK-NEXT: test_function {{.*}}\dll_poison_unpoison.cc
+// CHECK: 'buffer' <== Memory access at offset [[OFFSET]] is inside this variable
+ return 0;
+}
diff --git a/test/asan/TestCases/Windows/dll_seh.cc b/test/asan/TestCases/Windows/dll_seh.cc
new file mode 100644
index 000000000000..6e4c724e504d
--- /dev/null
+++ b/test/asan/TestCases/Windows/dll_seh.cc
@@ -0,0 +1,60 @@
+// Clang doesn't support SEH on Windows yet, so for the time being we
+// build this program in two parts: the code with SEH is built with CL,
+// the rest is built with Clang. This represents the typical scenario when we
+// build a large project using "clang-cl -fallback -fsanitize=address".
+//
+// RUN: %clang_cl_asan -O0 %p/dll_host.cc -Fe%t
+//
+// Check both -GS and -GS- builds:
+// RUN: cl -LD -c %s -Fo%t.obj
+// RUN: %clang_cl_asan -LD -O0 %s -Fe%t.dll %t.obj
+// RUN: %run %t %t.dll
+//
+// RUN: cl -LD -GS- -c %s -Fo%t.obj
+// RUN: %clang_cl_asan -LD -O0 %s -Fe%t.dll %t.obj
+// RUN: %run %t %t.dll
+
+#include <windows.h>
+#include <assert.h>
+#include <stdio.h>
+
+// Should just "#include <sanitizer/asan_interface.h>" when C++ exceptions are
+// supported and we don't need to use CL.
+extern "C" bool __asan_address_is_poisoned(void *p);
+
+void ThrowAndCatch();
+
+#if !defined(__clang__)
+__declspec(noinline)
+void Throw() {
+ int local, zero = 0;
+ fprintf(stderr, "Throw: %p\n", &local);
+ local = 5 / zero;
+}
+
+__declspec(noinline)
+void ThrowAndCatch() {
+ int local;
+ __try {
+ Throw();
+ } __except(EXCEPTION_EXECUTE_HANDLER) {
+ fprintf(stderr, "__except: %p\n", &local);
+ }
+}
+#else
+
+extern "C" __declspec(dllexport)
+int test_function() {
+ char x[32];
+ fprintf(stderr, "Before: %p poisoned: %d\n", &x,
+ __asan_address_is_poisoned(x + 32));
+ assert(__asan_address_is_poisoned(x + 32));
+ ThrowAndCatch();
+ fprintf(stderr, "After: %p poisoned: %d\n", &x,
+ __asan_address_is_poisoned(x + 32));
+ // FIXME: Invert this assertion once we fix
+ // https://code.google.com/p/address-sanitizer/issues/detail?id=258
+ assert(!__asan_address_is_poisoned(x + 32));
+ return 0;
+}
+#endif
diff --git a/test/asan/TestCases/Windows/dll_stack_use_after_return.cc b/test/asan/TestCases/Windows/dll_stack_use_after_return.cc
new file mode 100644
index 000000000000..6cd74c265b8f
--- /dev/null
+++ b/test/asan/TestCases/Windows/dll_stack_use_after_return.cc
@@ -0,0 +1,28 @@
+// RUN: %clang_cl_asan -O0 %p/dll_host.cc -Fe%t
+// RUN: %clang_cl_asan -LD -O0 %s -Fe%t.dll
+// RUN: env ASAN_OPTIONS=detect_stack_use_after_return=1 not %run %t %t.dll 2>&1 | FileCheck %s
+
+#include <malloc.h>
+
+char *x;
+
+void foo() {
+ char stack_buffer[42];
+ x = &stack_buffer[13];
+}
+
+extern "C" __declspec(dllexport)
+int test_function() {
+ foo();
+ *x = 42;
+// CHECK: AddressSanitizer: stack-use-after-return
+// CHECK: WRITE of size 1 at [[ADDR:.*]] thread T0
+// CHECK-NEXT: test_function {{.*}}dll_stack_use_after_return.cc:[[@LINE-3]]
+// CHECK-NEXT: main
+//
+// CHECK: Address [[ADDR]] is located in stack of thread T0 at offset [[OFFSET:.*]] in frame
+// CHECK-NEXT: #0 {{.*}} foo {{.*}}dll_stack_use_after_return.cc
+// CHECK: 'stack_buffer' <== Memory access at offset [[OFFSET]] is inside this variable
+ return 0;
+}
+
diff --git a/test/asan/TestCases/Windows/dll_thread_stack_array_left_oob.cc b/test/asan/TestCases/Windows/dll_thread_stack_array_left_oob.cc
new file mode 100644
index 000000000000..8f53623419ce
--- /dev/null
+++ b/test/asan/TestCases/Windows/dll_thread_stack_array_left_oob.cc
@@ -0,0 +1,36 @@
+// RUN: %clang_cl_asan -O0 %p/dll_host.cc -Fe%t
+// RUN: %clang_cl_asan -LD -O0 %s -Fe%t.dll
+// RUN: not %run %t %t.dll 2>&1 | FileCheck %s
+
+#include <windows.h>
+#include <malloc.h>
+
+DWORD WINAPI thread_proc(void *context) {
+ int subscript = -1;
+ char stack_buffer[42];
+ stack_buffer[subscript] = 42;
+// CHECK: AddressSanitizer: stack-buffer-overflow on address [[ADDR:0x[0-9a-f]+]]
+// CHECK: WRITE of size 1 at [[ADDR]] thread T1
+// CHECK-NEXT: thread_proc {{.*}}dll_thread_stack_array_left_oob.cc:[[@LINE-3]]
+//
+// CHECK: Address [[ADDR]] is located in stack of thread T1 at offset [[OFFSET:.*]] in frame
+// CHECK-NEXT: thread_proc {{.*}}dll_thread_stack_array_left_oob.cc
+//
+// CHECK: 'stack_buffer' <== Memory access at offset [[OFFSET]] underflows this variable
+
+ return 0;
+}
+
+extern "C" __declspec(dllexport)
+int test_function() {
+ HANDLE thr = CreateThread(NULL, 0, thread_proc, NULL, 0, NULL);
+// CHECK-LABEL: Thread T1 created by T0 here:
+// CHECK: test_function {{.*}}dll_thread_stack_array_left_oob.cc:[[@LINE-2]]
+// CHECK-NEXT: main {{.*}}dll_host.cc
+// CHECK-LABEL: SUMMARY
+ if (thr == 0)
+ return 1;
+ if (WAIT_OBJECT_0 != WaitForSingleObject(thr, INFINITE))
+ return 2;
+ return 0;
+}
diff --git a/test/asan/TestCases/Windows/double_free.cc b/test/asan/TestCases/Windows/double_free.cc
new file mode 100644
index 000000000000..18a9fcb44a75
--- /dev/null
+++ b/test/asan/TestCases/Windows/double_free.cc
@@ -0,0 +1,21 @@
+// RUN: %clang_cl_asan -O0 %s -Fe%t
+// RUN: not %run %t 2>&1 | FileCheck %s
+
+#include <malloc.h>
+
+int main() {
+ int *x = (int*)malloc(42 * sizeof(int));
+ free(x);
+ free(x);
+// CHECK: AddressSanitizer: attempting double-free on [[ADDR:0x[0-9a-f]+]]
+// CHECK-NEXT: {{#0 .* free }}
+// CHECK-NEXT: {{#1 .* main .*double_free.cc}}:[[@LINE-3]]
+// CHECK: [[ADDR]] is located 0 bytes inside of 168-byte region
+// CHECK-LABEL: freed by thread T0 here:
+// CHECK-NEXT: {{#0 .* free }}
+// CHECK-NEXT: {{#1 .* main .*double_free.cc}}:[[@LINE-8]]
+// CHECK-LABEL: previously allocated by thread T0 here:
+// CHECK-NEXT: {{#0 .* malloc }}
+// CHECK-NEXT: {{#1 .* main .*double_free.cc}}:[[@LINE-12]]
+ return 0;
+}
diff --git a/test/asan/TestCases/Windows/double_operator_delete.cc b/test/asan/TestCases/Windows/double_operator_delete.cc
new file mode 100644
index 000000000000..eae4a64c2b92
--- /dev/null
+++ b/test/asan/TestCases/Windows/double_operator_delete.cc
@@ -0,0 +1,25 @@
+// RUN: %clang_cl_asan -O0 %s -Fe%t
+// RUN: not %run %t 2>&1 | FileCheck %s
+
+#include <malloc.h>
+
+int main() {
+ int *x = new int[42];
+ delete [] x;
+ delete [] x;
+// CHECK: AddressSanitizer: attempting double-free on [[ADDR:0x[0-9a-f]+]]
+// FIXME: The 'operator delete' frame should have [].
+// CHECK-NEXT: {{#0 .* operator delete}}
+// CHECK-NEXT: {{#1 .* main .*double_operator_delete.cc}}:[[@LINE-4]]
+// CHECK: [[ADDR]] is located 0 bytes inside of 168-byte region
+// CHECK-LABEL: freed by thread T0 here:
+// FIXME: The 'operator delete' frame should have [].
+// CHECK-NEXT: {{#0 .* operator delete}}
+// CHECK-NEXT: {{#1 .* main .*double_operator_delete.cc}}:[[@LINE-10]]
+// CHECK-LABEL: previously allocated by thread T0 here:
+// FIXME: The 'operator new' frame should have [].
+// CHECK-NEXT: {{#0 .* operator new}}
+// CHECK-NEXT: {{#1 .* main .*double_operator_delete.cc}}:[[@LINE-15]]
+ return 0;
+}
+
diff --git a/test/asan/TestCases/Windows/global_const_string.cc b/test/asan/TestCases/Windows/global_const_string.cc
new file mode 100644
index 000000000000..8c147c917c88
--- /dev/null
+++ b/test/asan/TestCases/Windows/global_const_string.cc
@@ -0,0 +1,12 @@
+// RUN: %clang_cl_asan -O0 %s -Fe%t
+// RUN: %run %t | FileCheck %s
+
+#include <windows.h>
+#include <stdio.h>
+
+int main(void) {
+ static const char *foo = "foobarspam";
+ printf("Global string is `%s`\n", foo);
+// CHECK: Global string is `foobarspam`
+ return 0;
+}
diff --git a/test/asan/TestCases/Windows/global_const_string_oob.cc b/test/asan/TestCases/Windows/global_const_string_oob.cc
new file mode 100644
index 000000000000..b39e3dbb3b4e
--- /dev/null
+++ b/test/asan/TestCases/Windows/global_const_string_oob.cc
@@ -0,0 +1,20 @@
+// RUN: %clang_cl_asan -O0 %s -Fe%t
+// RUN: not %run %t 2>&1 | FileCheck %s
+
+#include <windows.h>
+#include <stdio.h>
+
+extern "C" const char *foo = "foobarspam";
+
+int main(void) {
+ if (foo[16])
+ printf("Boo\n");
+// CHECK-NOT: Boo
+// CHECK: AddressSanitizer: global-buffer-overflow on address [[ADDR:0x[0-9a-f]+]]
+// CHECK: READ of size 1 at [[ADDR]] thread T0
+// CHECK-NEXT: {{#0 .* main .*global_const_string_oob.cc:}}[[@LINE-5]]
+// CHECK: [[ADDR]] is located 5 bytes to the right of global variable [[STR:.*]] defined in {{'.*global_const_string_oob.cc:7:.*' .*}} of size 11
+// CHECK: [[STR]] is ascii string 'foobarspam'
+ return 0;
+}
+
diff --git a/test/asan/TestCases/Windows/hello_world.cc b/test/asan/TestCases/Windows/hello_world.cc
new file mode 100644
index 000000000000..400ca1b3eacc
--- /dev/null
+++ b/test/asan/TestCases/Windows/hello_world.cc
@@ -0,0 +1,9 @@
+// RUN: %clang_cl_asan -O0 %s -Fe%t
+// RUN: %run %t | FileCheck %s
+
+#include <stdio.h>
+
+int main() {
+ printf("Hello, world!\n");
+// CHECK: Hello, world!
+}
diff --git a/test/asan/TestCases/Windows/intercept_memcpy.cc b/test/asan/TestCases/Windows/intercept_memcpy.cc
new file mode 100644
index 000000000000..9ee984b1873d
--- /dev/null
+++ b/test/asan/TestCases/Windows/intercept_memcpy.cc
@@ -0,0 +1,31 @@
+// RUN: %clang_cl_asan -O0 %s -Fe%t
+// RUN: not %run %t 2>&1 | FileCheck %s
+
+#include <stdio.h>
+#include <string.h>
+
+void call_memcpy(void* (*f)(void *, const void *, size_t),
+ void *a, const void *b, size_t c) {
+ f(a, b, c);
+}
+
+int main() {
+ char buff1[6] = "Hello", buff2[5];
+
+ call_memcpy(&memcpy, buff2, buff1, 5);
+ if (buff1[2] != buff2[2])
+ return 2;
+ printf("Initial test OK\n");
+ fflush(0);
+// CHECK: Initial test OK
+
+ call_memcpy(&memcpy, buff2, buff1, 6);
+// CHECK: AddressSanitizer: stack-buffer-overflow on address [[ADDR:0x[0-9a-f]+]]
+// CHECK: WRITE of size 6 at [[ADDR]] thread T0
+// CHECK-NEXT: __asan_{{.*}}memcpy
+// CHECK-NEXT: call_memcpy
+// CHECK-NEXT: main {{.*}}intercept_memcpy.cc:[[@LINE-5]]
+// CHECK: Address [[ADDR]] is located in stack of thread T0 at offset {{.*}} in frame
+// CHECK-NEXT: #0 {{.*}} main
+// CHECK: 'buff2' <== Memory access at offset {{.*}} overflows this variable
+}
diff --git a/test/asan/TestCases/Windows/intercept_strdup.cc b/test/asan/TestCases/Windows/intercept_strdup.cc
new file mode 100644
index 000000000000..edb1f2f99245
--- /dev/null
+++ b/test/asan/TestCases/Windows/intercept_strdup.cc
@@ -0,0 +1,27 @@
+// RUN: %clang_cl_asan -O0 %s -Fe%t
+// RUN: not %run %t 2>&1 | FileCheck %s
+
+#include <stdio.h>
+#include <string.h>
+#include <malloc.h>
+
+int main() {
+ char *ptr = _strdup("Hello");
+ int subscript = 1;
+ ptr[subscript] = '3';
+ printf("%s\n", ptr);
+ fflush(0);
+// CHECK: H3llo
+
+ subscript = -1;
+ ptr[subscript] = 42;
+// CHECK: AddressSanitizer: heap-buffer-overflow on address [[ADDR:0x[0-9a-f]+]]
+// CHECK: WRITE of size 1 at [[ADDR]] thread T0
+// CHECK: {{#0 .* main .*}}intercept_strdup.cc:[[@LINE-3]]
+// CHECK: [[ADDR]] is located 1 bytes to the left of 6-byte region
+// CHECK: allocated by thread T0 here:
+// CHECK: {{#0 .* malloc }}
+// CHECK: {{#1 .*strdup}}
+// CHECK: {{#2 .* main .*}}intercept_strdup.cc:[[@LINE-16]]
+ free(ptr);
+}
diff --git a/test/asan/TestCases/Windows/intercept_strlen.cc b/test/asan/TestCases/Windows/intercept_strlen.cc
new file mode 100644
index 000000000000..928a286bedfa
--- /dev/null
+++ b/test/asan/TestCases/Windows/intercept_strlen.cc
@@ -0,0 +1,27 @@
+// RUN: %clang_cl_asan -O0 %s -Fe%t
+// RUN: not %run %t 2>&1 | FileCheck %s
+
+#include <stdio.h>
+#include <string.h>
+
+int main() {
+ char str[] = "Hello";
+ if (5 != strlen(str))
+ return 1;
+
+ printf("Initial test OK\n");
+ fflush(0);
+// CHECK: Initial test OK
+
+ str[5] = '!'; // Losing '\0' at the end.
+ int len = strlen(str);
+// CHECK: AddressSanitizer: stack-buffer-overflow on address [[ADDR:0x[0-9a-f]+]]
+// FIXME: Should be READ of size 1, see issue 155.
+// CHECK: READ of size {{[0-9]+}} at [[ADDR]] thread T0
+// CHECK: strlen
+// CHECK-NEXT: main {{.*}}intercept_strlen.cc:[[@LINE-5]]
+// CHECK: Address [[ADDR]] is located in stack of thread T0 at offset {{.*}} in frame
+// CHECK-NEXT: main {{.*}}intercept_strlen.cc
+// CHECK: 'str' <== Memory access at offset {{.*}} overflows this variable
+ return len < 6;
+}
diff --git a/test/asan/TestCases/Windows/lit.local.cfg b/test/asan/TestCases/Windows/lit.local.cfg
new file mode 100644
index 000000000000..13ef6d428251
--- /dev/null
+++ b/test/asan/TestCases/Windows/lit.local.cfg
@@ -0,0 +1,14 @@
+def getRoot(config):
+ if not config.parent:
+ return config
+ return getRoot(config.parent)
+
+root = getRoot(config)
+
+# We only run a small set of tests on Windows for now.
+# Override the parent directory's "unsupported" decision until we can handle
+# all of its tests.
+if root.host_os in ['Windows']:
+ config.unsupported = False
+else:
+ config.unsupported = True
diff --git a/test/asan/TestCases/Windows/longjmp.cc b/test/asan/TestCases/Windows/longjmp.cc
new file mode 100644
index 000000000000..443933e8ab62
--- /dev/null
+++ b/test/asan/TestCases/Windows/longjmp.cc
@@ -0,0 +1,26 @@
+// RUN: %clangxx_asan -O %s -o %t && %run %t
+
+// FIXME: merge this with the common longjmp test when we can run common
+// tests on Windows.
+
+#include <assert.h>
+#include <setjmp.h>
+#include <stdio.h>
+#include <sanitizer/asan_interface.h>
+
+static jmp_buf buf;
+
+int main() {
+ char x[32];
+ fprintf(stderr, "\nTestLongJmp\n");
+ fprintf(stderr, "Before: %p poisoned: %d\n", &x,
+ __asan_address_is_poisoned(x + 32));
+ assert(__asan_address_is_poisoned(x + 32));
+ if (0 == setjmp(buf))
+ longjmp(buf, 1);
+ fprintf(stderr, "After: %p poisoned: %d\n", &x,
+ __asan_address_is_poisoned(x + 32));
+ // FIXME: Invert this assertion once we fix
+ // https://code.google.com/p/address-sanitizer/issues/detail?id=258
+ assert(!__asan_address_is_poisoned(x + 32));
+}
diff --git a/test/asan/TestCases/Windows/malloc_left_oob.cc b/test/asan/TestCases/Windows/malloc_left_oob.cc
new file mode 100644
index 000000000000..ec133c393da2
--- /dev/null
+++ b/test/asan/TestCases/Windows/malloc_left_oob.cc
@@ -0,0 +1,17 @@
+// RUN: %clang_cl_asan -O0 %s -Fe%t
+// RUN: not %run %t 2>&1 | FileCheck %s
+
+#include <malloc.h>
+
+int main() {
+ char *buffer = (char*)malloc(42);
+ buffer[-1] = 42;
+// CHECK: AddressSanitizer: heap-buffer-overflow on address [[ADDR:0x[0-9a-f]+]]
+// CHECK: WRITE of size 1 at [[ADDR]] thread T0
+// CHECK-NEXT: {{#0 .* main .*malloc_left_oob.cc}}:[[@LINE-3]]
+// CHECK: [[ADDR]] is located 1 bytes to the left of 42-byte region
+// CHECK: allocated by thread T0 here:
+// CHECK-NEXT: {{#0 .* malloc }}
+// CHECK-NEXT: {{#1 .* main .*malloc_left_oob.cc}}:[[@LINE-8]]
+ free(buffer);
+}
diff --git a/test/asan/TestCases/Windows/malloc_right_oob.cc b/test/asan/TestCases/Windows/malloc_right_oob.cc
new file mode 100644
index 000000000000..9975316d3e02
--- /dev/null
+++ b/test/asan/TestCases/Windows/malloc_right_oob.cc
@@ -0,0 +1,17 @@
+// RUN: %clang_cl_asan -O0 %s -Fe%t
+// RUN: not %run %t 2>&1 | FileCheck %s
+
+#include <malloc.h>
+
+int main() {
+ char *buffer = (char*)malloc(42);
+ buffer[42] = 42;
+// CHECK: AddressSanitizer: heap-buffer-overflow on address [[ADDR:0x[0-9a-f]+]]
+// CHECK: WRITE of size 1 at [[ADDR]] thread T0
+// CHECK-NEXT: {{#0 .* main .*malloc_right_oob.cc}}:[[@LINE-3]]
+// CHECK: [[ADDR]] is located 0 bytes to the right of 42-byte region
+// CHECK: allocated by thread T0 here:
+// CHECK-NEXT: {{#0 .* malloc }}
+// CHECK-NEXT: {{#1 .* main .*malloc_right_oob.cc}}:[[@LINE-8]]
+ free(buffer);
+}
diff --git a/test/asan/TestCases/Windows/malloc_uaf.cc b/test/asan/TestCases/Windows/malloc_uaf.cc
new file mode 100644
index 000000000000..f58478947bf4
--- /dev/null
+++ b/test/asan/TestCases/Windows/malloc_uaf.cc
@@ -0,0 +1,20 @@
+// RUN: %clang_cl_asan -O0 %s -Fe%t
+// RUN: not %run %t 2>&1 | FileCheck %s
+
+#include <malloc.h>
+
+int main() {
+ char *buffer = (char*)malloc(42);
+ free(buffer);
+ buffer[0] = 42;
+// CHECK: AddressSanitizer: heap-use-after-free on address [[ADDR:0x[0-9a-f]+]]
+// CHECK: WRITE of size 1 at [[ADDR]] thread T0
+// CHECK-NEXT: {{#0 .* main .*malloc_uaf.cc}}:[[@LINE-3]]
+// CHECK: [[ADDR]] is located 0 bytes inside of 42-byte region
+// CHECK: freed by thread T0 here:
+// CHECK-NEXT: {{#0 .* free }}
+// CHECK-NEXT: {{#1 .* main .*malloc_uaf.cc}}:[[@LINE-8]]
+// CHECK: previously allocated by thread T0 here:
+// CHECK-NEXT: {{#0 .* malloc }}
+// CHECK-NEXT: {{#1 .* main .*malloc_uaf.cc}}:[[@LINE-12]]
+}
diff --git a/test/asan/TestCases/Windows/null_deref.cc b/test/asan/TestCases/Windows/null_deref.cc
new file mode 100644
index 000000000000..202000f59db7
--- /dev/null
+++ b/test/asan/TestCases/Windows/null_deref.cc
@@ -0,0 +1,15 @@
+// RUN: %clangxx_asan -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s
+// FIXME: merge this with the common null_deref test when we can run common
+// tests on Windows.
+
+__attribute__((noinline))
+static void NullDeref(int *ptr) {
+ // CHECK: ERROR: AddressSanitizer: access-violation on unknown address
+ // CHECK: {{0x0*000.. .*pc 0x.*}}
+ ptr[10]++; // BOOM
+}
+int main() {
+ NullDeref((int*)0);
+ // CHECK: {{ #1 0x.* in main.*null_deref.cc:}}[[@LINE-1]]
+ // CHECK: AddressSanitizer can not provide additional info.
+}
diff --git a/test/asan/TestCases/Windows/null_deref_multiple_dlls.cc b/test/asan/TestCases/Windows/null_deref_multiple_dlls.cc
new file mode 100644
index 000000000000..62fe544ae545
--- /dev/null
+++ b/test/asan/TestCases/Windows/null_deref_multiple_dlls.cc
@@ -0,0 +1,40 @@
+// Make sure everything works even if the main module doesn't have any stack
+// variables, thus doesn't explicitly reference any symbol exported by the
+// runtime thunk.
+//
+// RUN: %clang_cl_asan -LD -O0 -DDLL1 %s -Fe%t1.dll
+// RUN: %clang_cl_asan -LD -O0 -DDLL2 %s -Fe%t2.dll
+// RUN: %clang_cl_asan -O0 -DEXE %s %t1.lib %t2.lib -Fe%t
+// RUN: not %run %t 2>&1 | FileCheck %s
+
+#include <malloc.h>
+#include <string.h>
+
+extern "C" {
+#if defined(EXE)
+__declspec(dllimport) void foo1();
+__declspec(dllimport) void foo2();
+
+int main() {
+ foo1();
+ foo2();
+}
+#elif defined(DLL1)
+__declspec(dllexport) void foo1() {}
+#elif defined(DLL2)
+__attribute__((noinline))
+static void NullDeref(int *ptr) {
+ // CHECK: ERROR: AddressSanitizer: access-violation on unknown address
+ // CHECK: {{0x0*000.. .*pc 0x.*}}
+ ptr[10]++; // BOOM
+}
+
+__declspec(dllexport) void foo2() {
+ NullDeref((int*)0);
+ // CHECK: {{ #1 0x.* in foo2.*null_deref_multiple_dlls.cc:}}[[@LINE-1]]
+ // CHECK: AddressSanitizer can not provide additional info.
+}
+#else
+# error oops!
+#endif
+}
diff --git a/test/asan/TestCases/Windows/operator_array_new_left_oob.cc b/test/asan/TestCases/Windows/operator_array_new_left_oob.cc
new file mode 100644
index 000000000000..20a0f1927e5b
--- /dev/null
+++ b/test/asan/TestCases/Windows/operator_array_new_left_oob.cc
@@ -0,0 +1,17 @@
+// RUN: %clang_cl_asan -O0 %s -Fe%t
+// RUN: not %run %t 2>&1 | FileCheck %s
+
+int main() {
+ char *buffer = new char[42];
+ buffer[-1] = 42;
+// CHECK: AddressSanitizer: heap-buffer-overflow on address [[ADDR:0x[0-9a-f]+]]
+// CHECK: WRITE of size 1 at [[ADDR]] thread T0
+// CHECK-NEXT: {{#0 .* main .*operator_array_new_left_oob.cc}}:[[@LINE-3]]
+//
+// CHECK: [[ADDR]] is located 1 bytes to the left of 42-byte region
+// CHECK-LABEL: allocated by thread T0 here:
+// FIXME: The 'operator new' frame should have [].
+// CHECK-NEXT: {{#0 .* operator new}}
+// CHECK-NEXT: {{#1 .* main .*operator_array_new_left_oob.cc}}:[[@LINE-10]]
+ delete [] buffer;
+}
diff --git a/test/asan/TestCases/Windows/operator_array_new_right_oob.cc b/test/asan/TestCases/Windows/operator_array_new_right_oob.cc
new file mode 100644
index 000000000000..23775ef6066e
--- /dev/null
+++ b/test/asan/TestCases/Windows/operator_array_new_right_oob.cc
@@ -0,0 +1,18 @@
+// RUN: %clang_cl_asan -O0 %s -Fe%t
+// RUN: not %run %t 2>&1 | FileCheck %s
+
+#include <windows.h>
+
+int main() {
+ char *buffer = new char[42];
+ buffer[42] = 42;
+// CHECK: AddressSanitizer: heap-buffer-overflow on address [[ADDR:0x[0-9a-f]+]]
+// CHECK: WRITE of size 1 at [[ADDR]] thread T0
+// CHECK: {{#0 .* main .*operator_array_new_right_oob.cc}}:[[@LINE-3]]
+// CHECK: [[ADDR]] is located 0 bytes to the right of 42-byte region
+// CHECK: allocated by thread T0 here:
+// FIXME: The 'operator new' frame should have [].
+// CHECK: {{#0 .* operator new}}
+// CHECK: {{#1 .* main .*operator_array_new_right_oob.cc}}:[[@LINE-9]]
+ delete [] buffer;
+}
diff --git a/test/asan/TestCases/Windows/operator_array_new_uaf.cc b/test/asan/TestCases/Windows/operator_array_new_uaf.cc
new file mode 100644
index 000000000000..b638ef1df415
--- /dev/null
+++ b/test/asan/TestCases/Windows/operator_array_new_uaf.cc
@@ -0,0 +1,24 @@
+// RUN: %clang_cl_asan -O0 %s -Fe%t
+// RUN: not %run %t 2>&1 | FileCheck %s
+
+#include <windows.h>
+
+int main() {
+ char *buffer = new char[42];
+ delete [] buffer;
+ buffer[0] = 42;
+// CHECK: AddressSanitizer: heap-use-after-free on address [[ADDR:0x[0-9a-f]+]]
+// CHECK: WRITE of size 1 at [[ADDR]] thread T0
+// CHECK: {{#0 .* main .*operator_array_new_uaf.cc}}:[[@LINE-3]]
+// CHECK: [[ADDR]] is located 0 bytes inside of 42-byte region
+// CHECK-LABEL: freed by thread T0 here:
+// FIXME: The 'operator delete' frame should have [].
+// CHECK: {{#0 .* operator delete}}
+// CHECK: {{#1 .* main .*operator_array_new_uaf.cc}}:[[@LINE-9]]
+// CHECK-LABEL: previously allocated by thread T0 here:
+// FIXME: The 'operator new' frame should have [].
+// CHECK: {{#0 .* operator new}}
+// CHECK: {{#1 .* main .*operator_array_new_uaf.cc}}:[[@LINE-14]]
+ return 0;
+}
+
diff --git a/test/asan/TestCases/Windows/operator_array_new_with_dtor_left_oob.cc b/test/asan/TestCases/Windows/operator_array_new_with_dtor_left_oob.cc
new file mode 100644
index 000000000000..63f2929bd89b
--- /dev/null
+++ b/test/asan/TestCases/Windows/operator_array_new_with_dtor_left_oob.cc
@@ -0,0 +1,25 @@
+// RUN: %clang_cl_asan -O0 %s -Fe%t
+// RUN: not %run %t 2>&1 | FileCheck %s
+
+struct C {
+ int x;
+ ~C() {}
+};
+
+int main() {
+ C *buffer = new C[42];
+ buffer[-2].x = 42;
+// CHECK: AddressSanitizer: heap-buffer-overflow on address [[ADDR:0x[0-9a-f]+]]
+// CHECK: WRITE of size 4 at [[ADDR]] thread T0
+// CHECK-NEXT: {{#0 .* main .*operator_array_new_with_dtor_left_oob.cc}}:[[@LINE-3]]
+//
+// FIXME: Currently it says "4 bytes ... left of 172-byte region",
+// should be "8 bytes ... left of 168-byte region", see
+// https://code.google.com/p/address-sanitizer/issues/detail?id=314
+// CHECK: [[ADDR]] is located {{.*}} bytes to the left of 172-byte region
+// CHECK-LABEL: allocated by thread T0 here:
+// FIXME: The 'operator new' frame should have [].
+// CHECK-NEXT: {{#0 .* operator new}}
+// CHECK-NEXT: {{#1 .* main .*operator_array_new_with_dtor_left_oob.cc}}:[[@LINE-13]]
+ delete [] buffer;
+}
diff --git a/test/asan/TestCases/Windows/operator_delete_wrong_argument.cc b/test/asan/TestCases/Windows/operator_delete_wrong_argument.cc
new file mode 100644
index 000000000000..c3e7daca55b0
--- /dev/null
+++ b/test/asan/TestCases/Windows/operator_delete_wrong_argument.cc
@@ -0,0 +1,12 @@
+// RUN: %clang_cl_asan -O0 %s -Fe%t
+// RUN: not %run %t 2>&1 | FileCheck %s
+
+#include <windows.h>
+
+int main() {
+ int *x = new int[42];
+ delete (x + 1);
+// CHECK: AddressSanitizer: attempting free on address which was not malloc()-ed
+// CHECK: {{#0 0x.* operator delete }}
+// CHECK: {{#1 .* main .*operator_delete_wrong_argument.cc}}:[[@LINE-3]]
+}
diff --git a/test/asan/TestCases/Windows/operator_new_left_oob.cc b/test/asan/TestCases/Windows/operator_new_left_oob.cc
new file mode 100644
index 000000000000..c077f11d68f9
--- /dev/null
+++ b/test/asan/TestCases/Windows/operator_new_left_oob.cc
@@ -0,0 +1,17 @@
+// RUN: %clang_cl_asan -O0 %s -Fe%t
+// RUN: not %run %t 2>&1 | FileCheck %s
+
+#include <windows.h>
+
+int main() {
+ char *buffer = new char;
+ buffer[-1] = 42;
+// CHECK: AddressSanitizer: heap-buffer-overflow on address [[ADDR:0x[0-9a-f]+]]
+// CHECK: WRITE of size 1 at [[ADDR]] thread T0
+// CHECK: {{#0 .* main .*operator_new_left_oob.cc}}:[[@LINE-3]]
+// CHECK: [[ADDR]] is located 1 bytes to the left of 1-byte region
+// CHECK: allocated by thread T0 here:
+// CHECK: {{#0 .* operator new }}
+// CHECK: {{#1 .* main .*operator_new_left_oob.cc}}:[[@LINE-8]]
+ delete buffer;
+}
diff --git a/test/asan/TestCases/Windows/operator_new_right_oob.cc b/test/asan/TestCases/Windows/operator_new_right_oob.cc
new file mode 100644
index 000000000000..7a66d1714b97
--- /dev/null
+++ b/test/asan/TestCases/Windows/operator_new_right_oob.cc
@@ -0,0 +1,17 @@
+// RUN: %clang_cl_asan -O0 %s -Fe%t
+// RUN: not %run %t 2>&1 | FileCheck %s
+
+#include <windows.h>
+
+int main() {
+ char *buffer = new char;
+ buffer[1] = 42;
+// CHECK: AddressSanitizer: heap-buffer-overflow on address [[ADDR:0x[0-9a-f]+]]
+// CHECK: WRITE of size 1 at [[ADDR]] thread T0
+// CHECK: {{#0 .* main .*operator_new_right_oob.cc}}:[[@LINE-3]]
+// CHECK: [[ADDR]] is located 0 bytes to the right of 1-byte region
+// CHECK: allocated by thread T0 here:
+// CHECK: {{#0 .* operator new }}
+// CHECK: {{#1 .* main .*operator_new_right_oob.cc}}:[[@LINE-8]]
+ delete buffer;
+}
diff --git a/test/asan/TestCases/Windows/operator_new_uaf.cc b/test/asan/TestCases/Windows/operator_new_uaf.cc
new file mode 100644
index 000000000000..c435458f0c1c
--- /dev/null
+++ b/test/asan/TestCases/Windows/operator_new_uaf.cc
@@ -0,0 +1,22 @@
+// RUN: %clang_cl_asan -O0 %s -Fe%t
+// RUN: not %run %t 2>&1 | FileCheck %s
+
+#include <windows.h>
+
+int main() {
+ char *buffer = new char;
+ delete buffer;
+ *buffer = 42;
+// CHECK: AddressSanitizer: heap-use-after-free on address [[ADDR:0x[0-9a-f]+]]
+// CHECK: WRITE of size 1 at [[ADDR]] thread T0
+// CHECK: {{#0 .* main .*operator_new_uaf.cc}}:[[@LINE-3]]
+// CHECK: [[ADDR]] is located 0 bytes inside of 1-byte region
+// CHECK-LABEL: freed by thread T0 here:
+// CHECK: {{#0 .* operator delete }}
+// CHECK: {{#1 .* main .*operator_new_uaf.cc}}:[[@LINE-8]]
+// CHECK-LABEL: previously allocated by thread T0 here:
+// CHECK: {{#0 .* operator new }}
+// CHECK: {{#1 .* main .*operator_new_uaf.cc}}:[[@LINE-12]]
+ return 0;
+}
+
diff --git a/test/asan/TestCases/Windows/realloc_left_oob.cc b/test/asan/TestCases/Windows/realloc_left_oob.cc
new file mode 100644
index 000000000000..7d30e1d5c4ad
--- /dev/null
+++ b/test/asan/TestCases/Windows/realloc_left_oob.cc
@@ -0,0 +1,17 @@
+// RUN: %clang_cl_asan -O0 %s -Fe%t
+// RUN: not %run %t 2>&1 | FileCheck %s
+
+#include <malloc.h>
+
+int main() {
+ char *buffer = (char*)realloc(0, 42);
+ buffer[-1] = 42;
+// CHECK: AddressSanitizer: heap-buffer-overflow on address [[ADDR:0x[0-9a-f]+]]
+// CHECK: WRITE of size 1 at [[ADDR]] thread T0
+// CHECK-NEXT: {{#0 .* main .*realloc_left_oob.cc}}:[[@LINE-3]]
+// CHECK: [[ADDR]] is located 1 bytes to the left of 42-byte region
+// CHECK: allocated by thread T0 here:
+// CHECK-NEXT: {{#0 .* realloc }}
+// CHECK-NEXT: {{#1 .* main .*realloc_left_oob.cc}}:[[@LINE-8]]
+ free(buffer);
+}
diff --git a/test/asan/TestCases/Windows/realloc_right_oob.cc b/test/asan/TestCases/Windows/realloc_right_oob.cc
new file mode 100644
index 000000000000..f741390bd4e9
--- /dev/null
+++ b/test/asan/TestCases/Windows/realloc_right_oob.cc
@@ -0,0 +1,17 @@
+// RUN: %clang_cl_asan -O0 %s -Fe%t
+// RUN: not %run %t 2>&1 | FileCheck %s
+
+#include <malloc.h>
+
+int main() {
+ char *buffer = (char*)realloc(0, 42);
+ buffer[42] = 42;
+// CHECK: AddressSanitizer: heap-buffer-overflow on address [[ADDR:0x[0-9a-f]+]]
+// CHECK: WRITE of size 1 at [[ADDR]] thread T0
+// CHECK-NEXT: {{#0 .* main .*realloc_right_oob.cc}}:[[@LINE-3]]
+// CHECK: [[ADDR]] is located 0 bytes to the right of 42-byte region
+// CHECK: allocated by thread T0 here:
+// CHECK-NEXT: {{#0 .* realloc }}
+// CHECK-NEXT: {{#1 .* main .*realloc_right_oob.cc}}:[[@LINE-8]]
+ free(buffer);
+}
diff --git a/test/asan/TestCases/Windows/realloc_uaf.cc b/test/asan/TestCases/Windows/realloc_uaf.cc
new file mode 100644
index 000000000000..c5b6953cf76a
--- /dev/null
+++ b/test/asan/TestCases/Windows/realloc_uaf.cc
@@ -0,0 +1,20 @@
+// RUN: %clang_cl_asan -O0 %s -Fe%t
+// RUN: not %run %t 2>&1 | FileCheck %s
+
+#include <malloc.h>
+
+int main() {
+ char *buffer = (char*)realloc(0, 42);
+ free(buffer);
+ buffer[0] = 42;
+// CHECK: AddressSanitizer: heap-use-after-free on address [[ADDR:0x[0-9a-f]+]]
+// CHECK: WRITE of size 1 at [[ADDR]] thread T0
+// CHECK-NEXT: {{#0 .* main .*realloc_uaf.cc}}:[[@LINE-3]]
+// CHECK: [[ADDR]] is located 0 bytes inside of 42-byte region
+// CHECK: freed by thread T0 here:
+// CHECK-NEXT: {{#0 .* free }}
+// CHECK-NEXT: {{#1 .* main .*realloc_uaf.cc}}:[[@LINE-8]]
+// CHECK: previously allocated by thread T0 here:
+// CHECK-NEXT: {{#0 .* realloc }}
+// CHECK-NEXT: {{#1 .* main .*realloc_uaf.cc}}:[[@LINE-12]]
+}
diff --git a/test/asan/TestCases/Windows/report_after_syminitialize.cc b/test/asan/TestCases/Windows/report_after_syminitialize.cc
new file mode 100644
index 000000000000..faf5e35db5f5
--- /dev/null
+++ b/test/asan/TestCases/Windows/report_after_syminitialize.cc
@@ -0,0 +1,19 @@
+// RUN: %clangxx_asan -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s
+
+#include <windows.h>
+#include <dbghelp.h>
+
+int main() {
+ // Make sure the RTL recovers from "no options enabled" dbghelp setup.
+ SymSetOptions(0);
+
+ // Make sure the RTL recovers from "fInvadeProcess=FALSE".
+ if (!SymInitialize(GetCurrentProcess(), 0, FALSE))
+ return 42;
+
+ *(volatile int*)0 = 42;
+ // CHECK: ERROR: AddressSanitizer: access-violation on unknown address
+ // CHECK-NEXT: {{WARNING: .*DbgHelp}}
+ // CHECK: {{#0 0x.* in main.*report_after_syminitialize.cc:}}[[@LINE-3]]
+ // CHECK: AddressSanitizer can not provide additional info.
+}
diff --git a/test/asan/TestCases/Windows/seh.cc b/test/asan/TestCases/Windows/seh.cc
new file mode 100644
index 000000000000..50cf6ddba8d6
--- /dev/null
+++ b/test/asan/TestCases/Windows/seh.cc
@@ -0,0 +1,56 @@
+// Clang doesn't support SEH on Windows yet, so for the time being we
+// build this program in two parts: the code with SEH is built with CL,
+// the rest is built with Clang. This represents the typical scenario when we
+// build a large project using "clang-cl -fallback -fsanitize=address".
+//
+// Check both -GS and -GS- builds:
+// RUN: cl -c %s -Fo%t.obj
+// RUN: %clangxx_asan -o %t.exe %s %t.obj
+// RUN: %run %t.exe
+//
+// RUN: cl -GS- -c %s -Fo%t.obj
+// RUN: %clangxx_asan -o %t.exe %s %t.obj
+// RUN: %run %t.exe
+
+#include <windows.h>
+#include <assert.h>
+#include <stdio.h>
+
+// Should just "#include <sanitizer/asan_interface.h>" when C++ exceptions are
+// supported and we don't need to use CL.
+extern "C" bool __asan_address_is_poisoned(void *p);
+
+void ThrowAndCatch();
+
+#if !defined(__clang__)
+__declspec(noinline)
+void Throw() {
+ int local, zero = 0;
+ fprintf(stderr, "Throw: %p\n", &local);
+ local = 5 / zero;
+}
+
+__declspec(noinline)
+void ThrowAndCatch() {
+ int local;
+ __try {
+ Throw();
+ } __except(EXCEPTION_EXECUTE_HANDLER) {
+ fprintf(stderr, "__except: %p\n", &local);
+ }
+}
+#else
+
+int main() {
+ char x[32];
+ fprintf(stderr, "Before: %p poisoned: %d\n", &x,
+ __asan_address_is_poisoned(x + 32));
+ assert(__asan_address_is_poisoned(x + 32));
+ ThrowAndCatch();
+ fprintf(stderr, "After: %p poisoned: %d\n", &x,
+ __asan_address_is_poisoned(x + 32));
+ // FIXME: Invert this assertion once we fix
+ // https://code.google.com/p/address-sanitizer/issues/detail?id=258
+ assert(!__asan_address_is_poisoned(x + 32));
+}
+#endif
diff --git a/test/asan/TestCases/Windows/stack_array_left_oob.cc b/test/asan/TestCases/Windows/stack_array_left_oob.cc
new file mode 100644
index 000000000000..040d855b48e2
--- /dev/null
+++ b/test/asan/TestCases/Windows/stack_array_left_oob.cc
@@ -0,0 +1,16 @@
+// RUN: %clang_cl_asan -O0 %s -Fe%t
+// RUN: not %run %t 2>&1 | FileCheck %s
+
+#include <stdio.h>
+
+int main() {
+ int subscript = -1;
+ char buffer[42];
+ buffer[subscript] = 42;
+// CHECK: AddressSanitizer: stack-buffer-overflow on address [[ADDR:0x[0-9a-f]+]]
+// CHECK: WRITE of size 1 at [[ADDR]] thread T0
+// CHECK-NEXT: {{#0 .* main .*stack_array_left_oob.cc}}:[[@LINE-3]]
+// CHECK: Address [[ADDR]] is located in stack of thread T0 at offset [[OFFSET:.*]] in frame
+// CHECK-NEXT: {{#0 .* main .*stack_array_left_oob.cc}}
+// CHECK: 'buffer' <== Memory access at offset [[OFFSET]] underflows this variable
+}
diff --git a/test/asan/TestCases/Windows/stack_array_right_oob.cc b/test/asan/TestCases/Windows/stack_array_right_oob.cc
new file mode 100644
index 000000000000..a370246aa072
--- /dev/null
+++ b/test/asan/TestCases/Windows/stack_array_right_oob.cc
@@ -0,0 +1,16 @@
+// RUN: %clang_cl_asan -O0 %s -Fe%t
+// RUN: not %run %t 2>&1 | FileCheck %s
+
+#include <stdio.h>
+
+int main() {
+ int subscript = 42;
+ char buffer[42];
+ buffer[subscript] = 42;
+// CHECK: AddressSanitizer: stack-buffer-overflow on address [[ADDR:0x[0-9a-f]+]]
+// CHECK: WRITE of size 1 at [[ADDR]] thread T0
+// CHECK-NEXT: {{#0 .* main .*stack_array_right_oob.cc}}:[[@LINE-3]]
+// CHECK: Address [[ADDR]] is located in stack of thread T0 at offset [[OFFSET:.*]] in frame
+// CHECK-NEXT: {{#0 .* main .*stack_array_right_oob.cc}}
+// CHECK: 'buffer' <== Memory access at offset [[OFFSET]] overflows this variable
+}
diff --git a/test/asan/TestCases/Windows/stack_array_sanity.cc b/test/asan/TestCases/Windows/stack_array_sanity.cc
new file mode 100644
index 000000000000..1aef1a923d24
--- /dev/null
+++ b/test/asan/TestCases/Windows/stack_array_sanity.cc
@@ -0,0 +1,12 @@
+// RUN: %clang_cl_asan -O0 %s -Fe%t
+// RUN: %run %t | FileCheck %s
+
+#include <stdio.h>
+
+int main() {
+ int subscript = 1;
+ char buffer[42];
+ buffer[subscript] = 42;
+ printf("OK\n");
+// CHECK: OK
+}
diff --git a/test/asan/TestCases/Windows/stack_use_after_return.cc b/test/asan/TestCases/Windows/stack_use_after_return.cc
new file mode 100644
index 000000000000..7955f2685308
--- /dev/null
+++ b/test/asan/TestCases/Windows/stack_use_after_return.cc
@@ -0,0 +1,22 @@
+// RUN: %clang_cl_asan -O0 %s -Fe%t
+// RUN: env ASAN_OPTIONS=detect_stack_use_after_return=1 not %run %t 2>&1 | FileCheck %s
+
+char *x;
+
+void foo() {
+ char stack_buffer[42];
+ x = &stack_buffer[13];
+}
+
+int main() {
+ foo();
+ *x = 42;
+// CHECK: AddressSanitizer: stack-use-after-return
+// CHECK: WRITE of size 1 at {{.*}} thread T0
+// CHECK-NEXT: {{#0 0x.* in main .*stack_use_after_return.cc}}:[[@LINE-3]]
+//
+// CHECK: is located in stack of thread T0 at offset [[OFFSET:.*]] in frame
+// CHECK-NEXT: {{#0 0x.* in foo .*stack_use_after_return.cc}}
+//
+// CHECK: 'stack_buffer' <== Memory access at offset [[OFFSET]] is inside this variable
+}
diff --git a/test/asan/TestCases/Windows/thread_simple.cc b/test/asan/TestCases/Windows/thread_simple.cc
new file mode 100644
index 000000000000..14bb82f042aa
--- /dev/null
+++ b/test/asan/TestCases/Windows/thread_simple.cc
@@ -0,0 +1,26 @@
+// RUN: %clang_cl_asan -O0 %s -Fe%t
+// RUN: %run %t
+
+#include <windows.h>
+
+DWORD WINAPI thread_proc(void *) {
+ volatile char stack_buffer[42];
+ for (int i = 0; i < sizeof(stack_buffer); ++i)
+ stack_buffer[i] = 42;
+ return 0x42;
+}
+
+int main() {
+ DWORD exitcode;
+ HANDLE thr = CreateThread(NULL, 0, thread_proc, NULL, 0, NULL);
+ if (thr == 0)
+ return 1;
+ if (WAIT_OBJECT_0 != WaitForSingleObject(thr, INFINITE))
+ return 2;
+
+ GetExitCodeThread(thr, &exitcode);
+ if (exitcode != 0x42)
+ return 3;
+ CloseHandle(thr);
+}
+
diff --git a/test/asan/TestCases/Windows/thread_stack_array_left_oob.cc b/test/asan/TestCases/Windows/thread_stack_array_left_oob.cc
new file mode 100644
index 000000000000..17b9b1bf8ecb
--- /dev/null
+++ b/test/asan/TestCases/Windows/thread_stack_array_left_oob.cc
@@ -0,0 +1,27 @@
+// RUN: %clang_cl_asan -O0 %s -Fe%t
+// RUN: not %run %t 2>&1 | FileCheck %s
+
+#include <windows.h>
+
+DWORD WINAPI thread_proc(void *) {
+ int subscript = -1;
+ volatile char stack_buffer[42];
+ stack_buffer[subscript] = 42;
+// CHECK: AddressSanitizer: stack-buffer-overflow on address [[ADDR:0x[0-9a-f]+]]
+// CHECK: WRITE of size 1 at [[ADDR]] thread T1
+// CHECK: {{#0 .* thread_proc .*thread_stack_array_left_oob.cc}}:[[@LINE-3]]
+// CHECK: Address [[ADDR]] is located in stack of thread T1 at offset {{.*}} in frame
+// CHECK: thread_proc
+ return 0;
+}
+
+int main() {
+ HANDLE thr = CreateThread(NULL, 0, thread_proc, NULL, 0, NULL);
+// CHECK: Thread T1 created by T0 here:
+// CHECK: {{#[01] .* main .*thread_stack_array_left_oob.cc}}:[[@LINE-2]]
+
+ // A failure to create a thread should fail the test!
+ if (thr == 0) return 0;
+
+ WaitForSingleObject(thr, INFINITE);
+}
diff --git a/test/asan/TestCases/Windows/thread_stack_array_right_oob.cc b/test/asan/TestCases/Windows/thread_stack_array_right_oob.cc
new file mode 100644
index 000000000000..601a1b8a8760
--- /dev/null
+++ b/test/asan/TestCases/Windows/thread_stack_array_right_oob.cc
@@ -0,0 +1,27 @@
+// RUN: %clang_cl_asan -O0 %s -Fe%t
+// RUN: not %run %t 2>&1 | FileCheck %s
+
+#include <windows.h>
+
+DWORD WINAPI thread_proc(void *) {
+ int subscript = 42;
+ volatile char stack_buffer[42];
+ stack_buffer[subscript] = 42;
+// CHECK: AddressSanitizer: stack-buffer-overflow on address [[ADDR:0x[0-9a-f]+]]
+// CHECK: WRITE of size 1 at [[ADDR]] thread T1
+// CHECK: {{#0 .* thread_proc .*thread_stack_array_right_oob.cc}}:[[@LINE-3]]
+// CHECK: Address [[ADDR]] is located in stack of thread T1 at offset {{.*}} in frame
+// CHECK: thread_proc
+ return 0;
+}
+
+int main(void) {
+ HANDLE thr = CreateThread(NULL, 0, thread_proc, NULL, 0, NULL);
+// CHECK: Thread T1 created by T0 here:
+// CHECK: {{#[01] .* main .*thread_stack_array_right_oob.cc}}:[[@LINE-2]]
+
+ // A failure to create a thread should fail the test!
+ if (thr == 0) return 0;
+
+ WaitForSingleObject(thr, INFINITE);
+}
diff --git a/test/asan/TestCases/Windows/thread_stack_reuse.cc b/test/asan/TestCases/Windows/thread_stack_reuse.cc
new file mode 100644
index 000000000000..7da3a807dac1
--- /dev/null
+++ b/test/asan/TestCases/Windows/thread_stack_reuse.cc
@@ -0,0 +1,37 @@
+// RUN: %clang_cl_asan -O0 %s -Fe%t
+// RUN: %run %t
+
+#include <windows.h>
+
+DWORD WINAPI thread_proc_1(void *) {
+ volatile int x, y, z;
+ x = 1;
+ y = 2;
+ z = 3;
+ return 0;
+}
+
+DWORD WINAPI thread_proc_2(void *) {
+ volatile char stack_buffer[42];
+ for (int i = 0; i < sizeof(stack_buffer); ++i)
+ stack_buffer[i] = 42;
+ return 0;
+}
+
+int main(void) {
+ HANDLE thr = NULL;
+
+ thr = CreateThread(NULL, 0, thread_proc_1, NULL, 0, NULL);
+ if (thr == 0)
+ return 1;
+ if (WAIT_OBJECT_0 != WaitForSingleObject(thr, INFINITE))
+ return 2;
+
+ thr = CreateThread(NULL, 0, thread_proc_2, NULL, 0, NULL);
+ if (thr == 0)
+ return 3;
+ if (WAIT_OBJECT_0 != WaitForSingleObject(thr, INFINITE))
+ return 4;
+ CloseHandle(thr);
+}
+
diff --git a/test/asan/TestCases/Windows/thread_stress.cc b/test/asan/TestCases/Windows/thread_stress.cc
new file mode 100644
index 000000000000..74be8d88c665
--- /dev/null
+++ b/test/asan/TestCases/Windows/thread_stress.cc
@@ -0,0 +1,30 @@
+// RUN: %clang_cl_asan -O0 %s -Fe%t
+// RUN: %run %t
+
+#include <windows.h>
+
+DWORD WINAPI thread_proc(void *) {
+ volatile char stack_buffer[42];
+ for (int i = 0; i < sizeof(stack_buffer); ++i)
+ stack_buffer[i] = 42;
+ return 0;
+}
+
+int main(void) {
+ for (int iter = 0; iter < 1024; ++iter) {
+ const int NUM_THREADS = 8;
+ HANDLE thr[NUM_THREADS];
+ for (int i = 0; i < NUM_THREADS; ++i) {
+ thr[i] = CreateThread(NULL, 0, thread_proc, NULL, 0, NULL);
+ if (thr[i] == 0)
+ return 1;
+ }
+ for (int i = 0; i < NUM_THREADS; ++i) {
+ if (WAIT_OBJECT_0 != WaitForSingleObject(thr[i], INFINITE))
+ return 2;
+ CloseHandle(thr[i]);
+ }
+ }
+ return 0;
+}
+
diff --git a/test/asan/TestCases/Windows/throw_catch.cc b/test/asan/TestCases/Windows/throw_catch.cc
new file mode 100644
index 000000000000..5313d25b26d6
--- /dev/null
+++ b/test/asan/TestCases/Windows/throw_catch.cc
@@ -0,0 +1,73 @@
+// Clang doesn't support exceptions on Windows yet, so for the time being we
+// build this program in two parts: the code with exceptions is built with CL,
+// the rest is built with Clang. This represents the typical scenario when we
+// build a large project using "clang-cl -fallback -fsanitize=address".
+//
+// RUN: cl -c %s -Fo%t.obj
+// RUN: %clangxx_asan -o %t.exe %s %t.obj
+// RUN: %run %t.exe
+
+#include <assert.h>
+#include <stdio.h>
+
+// Should just "#include <sanitizer/asan_interface.h>" when C++ exceptions are
+// supported and we don't need to use CL.
+extern "C" bool __asan_address_is_poisoned(void *p);
+
+void ThrowAndCatch();
+void TestThrowInline();
+
+#if !defined(__clang__)
+__declspec(noinline)
+void Throw() {
+ int local;
+ fprintf(stderr, "Throw: %p\n", &local);
+ throw 1;
+}
+
+__declspec(noinline)
+void ThrowAndCatch() {
+ int local;
+ try {
+ Throw();
+ } catch(...) {
+ fprintf(stderr, "Catch: %p\n", &loc