[PATCH] D27607: [ubsan] Treat ObjC's BOOL as if its range is always {0, 1}
fjricci added a comment. On platforms where `BOOL` == `signed char`, is it actually undefined behavior (or is it just bad programming practice) to store a value other than 0 or 1 in your `BOOL`? I can't find any language specs suggesting that it is, and given that it's just a typedef for a `signed char`, I don't see why it would be. If it's not actually undefined behavior, could we make it controllable via a separate fsanitize switch (like we have for unsigned integer overflow, which is also potentially bad practice but not actually undefined behavior). Repository: rL LLVM https://reviews.llvm.org/D27607 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D27607: [ubsan] Treat ObjC's BOOL as if its range is always {0, 1}
fjricci added a comment. Awesome, good to know. Thanks! Repository: rL LLVM https://reviews.llvm.org/D27607 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D34210: Add __has_feature(leak_sanitizer)
fjricci created this revision. Stand-alone leak sanitizer builds are supported with -fsanitize=leak, adds an attribute for consistency with the rest of the sanitizer attributes. https://reviews.llvm.org/D34210 Files: lib/Lex/PPMacroExpansion.cpp test/Lexer/has_feature_leak_sanitizer.cpp Index: test/Lexer/has_feature_leak_sanitizer.cpp === --- /dev/null +++ test/Lexer/has_feature_leak_sanitizer.cpp @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -E -fsanitize=leak %s -o - | FileCheck --check-prefix=CHECK-LSAN %s +// RUN: %clang_cc1 -E %s -o - | FileCheck --check-prefix=CHECK-NO-LSAN %s + +#if __has_feature(leak_sanitizer) +int LeakSanitizerEnabled(); +#else +int LeakSanitizerDisabled(); +#endif + +// CHECK-LSAN: LeakSanitizerEnabled +// CHECK-NO-LSAN: LeakSanitizerDisabled Index: lib/Lex/PPMacroExpansion.cpp === --- lib/Lex/PPMacroExpansion.cpp +++ lib/Lex/PPMacroExpansion.cpp @@ -1133,6 +1133,7 @@ .Case("enumerator_attributes", true) .Case("nullability", true) .Case("nullability_on_arrays", true) + .Case("leak_sanitizer", LangOpts.Sanitize.has(SanitizerKind::Leak)) .Case("memory_sanitizer", LangOpts.Sanitize.has(SanitizerKind::Memory)) .Case("thread_sanitizer", LangOpts.Sanitize.has(SanitizerKind::Thread)) .Case("dataflow_sanitizer", LangOpts.Sanitize.has(SanitizerKind::DataFlow)) Index: test/Lexer/has_feature_leak_sanitizer.cpp === --- /dev/null +++ test/Lexer/has_feature_leak_sanitizer.cpp @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -E -fsanitize=leak %s -o - | FileCheck --check-prefix=CHECK-LSAN %s +// RUN: %clang_cc1 -E %s -o - | FileCheck --check-prefix=CHECK-NO-LSAN %s + +#if __has_feature(leak_sanitizer) +int LeakSanitizerEnabled(); +#else +int LeakSanitizerDisabled(); +#endif + +// CHECK-LSAN: LeakSanitizerEnabled +// CHECK-NO-LSAN: LeakSanitizerDisabled Index: lib/Lex/PPMacroExpansion.cpp === --- lib/Lex/PPMacroExpansion.cpp +++ lib/Lex/PPMacroExpansion.cpp @@ -1133,6 +1133,7 @@ .Case("enumerator_attributes", true) .Case("nullability", true) .Case("nullability_on_arrays", true) + .Case("leak_sanitizer", LangOpts.Sanitize.has(SanitizerKind::Leak)) .Case("memory_sanitizer", LangOpts.Sanitize.has(SanitizerKind::Memory)) .Case("thread_sanitizer", LangOpts.Sanitize.has(SanitizerKind::Thread)) .Case("dataflow_sanitizer", LangOpts.Sanitize.has(SanitizerKind::DataFlow)) ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D34210: Add __has_feature(leak_sanitizer)
fjricci added a comment. Currently, the way that we tell users to gate on sanitizer-specific behavior is with `__has_feature(foo_sanitizer)`, as far as I know, it's the only way to do so. LSan provides several API functions for users, ie `__lsan_ignore_object`. If a user program wants to use these API functions in their program, they need a way to check that LSan is enabled at compilation time (even if LSan doesn't actually modify the compile step). I'm not sure of a better or more consistent way to allow that to happen. https://reviews.llvm.org/D34210 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D34210: Add __has_feature(leak_sanitizer)
fjricci abandoned this revision. fjricci added a comment. Weak hooks do provide a good solution, abandoning for now (although it may need to be reconsidered if we get a windows LSan port up and running). https://reviews.llvm.org/D34210 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D34210: Add __has_feature(leak_sanitizer)
fjricci reclaimed this revision. fjricci added a comment. As I've looked into this further, I do think we need `has_feature(leak_sanitizer)` after all. For example, if a user program calls `pthread_create()` with a custom stack size, leak sanitizer will intercept the call to `pthread_create()`, and may modify the stack size set by the user (lsan's interceptor for `pthread_create` calls `AdjustStackSize` in sanitizer_common). Without `has_feature(leak_sanitizer)`, there's no good way for the user program to account for these sorts of modifications. There are most likely other interceptors which will cause similar issues, this is just the first example I ran into. https://reviews.llvm.org/D34210 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D34784: [OpenMP] Add flag for specifying the target device architecture for OpenMP device offloading
fjricci added inline comments. Comment at: lib/Driver/ToolChain.cpp:851 + XOpenMPTargetArg->setBaseArg(A); + A = XOpenMPTargetArg.release(); + DAL->append(A); Hahnfeld wrote: > This is a memory leak that is currently triggered in > `tests/Driver/openmp-offload-gpu.c` and found by ASan. How to fix this? I'm > not really familiar with OptTable... Even with the follow-up patch to fix the memory leak, I'm still seeing this pointer leaked (on Darwin with ASan and detect_leaks=1). I've tried playing around with a few fixes myself, but haven't been able to get anything working. https://reviews.llvm.org/D34784 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D36482: Enable SanitizerKind::Vptr on NetBSD/X86 and X86_64
fjricci added a comment. Please add a test for this. Repository: rL LLVM https://reviews.llvm.org/D36482 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D32192: Enable leak sanitizer builds for darwin
fjricci created this revision. Support for leak sanitizer on darwin has been added to compiler-rt, this patch adds compiler support. https://reviews.llvm.org/D32192 Files: lib/Driver/ToolChains/Darwin.cpp Index: lib/Driver/ToolChains/Darwin.cpp === --- lib/Driver/ToolChains/Darwin.cpp +++ lib/Driver/ToolChains/Darwin.cpp @@ -1035,6 +1035,8 @@ const SanitizerArgs &Sanitize = getSanitizerArgs(); if (Sanitize.needsAsanRt()) AddLinkSanitizerLibArgs(Args, CmdArgs, "asan"); + if (Sanitize.needsLsanRt()) +AddLinkSanitizerLibArgs(Args, CmdArgs, "lsan"); if (Sanitize.needsUbsanRt()) AddLinkSanitizerLibArgs(Args, CmdArgs, "ubsan"); if (Sanitize.needsTsanRt()) @@ -1896,9 +1898,11 @@ if (!isMacosxVersionLT(10, 9)) Res |= SanitizerKind::Vptr; Res |= SanitizerKind::SafeStack; +Res |= SanitizerKind::Leak; if (IsX86_64) Res |= SanitizerKind::Thread; } else if (isTargetIOSSimulator() || isTargetTvOSSimulator()) { +Res |= SanitizerKind::Leak; if (IsX86_64) Res |= SanitizerKind::Thread; } Index: lib/Driver/ToolChains/Darwin.cpp === --- lib/Driver/ToolChains/Darwin.cpp +++ lib/Driver/ToolChains/Darwin.cpp @@ -1035,6 +1035,8 @@ const SanitizerArgs &Sanitize = getSanitizerArgs(); if (Sanitize.needsAsanRt()) AddLinkSanitizerLibArgs(Args, CmdArgs, "asan"); + if (Sanitize.needsLsanRt()) +AddLinkSanitizerLibArgs(Args, CmdArgs, "lsan"); if (Sanitize.needsUbsanRt()) AddLinkSanitizerLibArgs(Args, CmdArgs, "ubsan"); if (Sanitize.needsTsanRt()) @@ -1896,9 +1898,11 @@ if (!isMacosxVersionLT(10, 9)) Res |= SanitizerKind::Vptr; Res |= SanitizerKind::SafeStack; +Res |= SanitizerKind::Leak; if (IsX86_64) Res |= SanitizerKind::Thread; } else if (isTargetIOSSimulator() || isTargetTvOSSimulator()) { +Res |= SanitizerKind::Leak; if (IsX86_64) Res |= SanitizerKind::Thread; } ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D34210: Add __has_feature(leak_sanitizer)
fjricci added a comment. Yeah, I think that makes sense. Life will get a bit tricky when Windows support gets added and we can't use weak hooks to determine whether LSan is running, but I'm sure there's a way to handle that. https://reviews.llvm.org/D34210 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D34210: Add __has_feature(leak_sanitizer)
fjricci added a comment. In https://reviews.llvm.org/D34210#804084, @smeenai wrote: > COFF supports weak externals: https://stackoverflow.com/a/11529277/382079. > Would it suffice here? Looks like it could work, thanks. https://reviews.llvm.org/D34210 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D32192: Enable leak sanitizer builds for darwin
fjricci updated this revision to Diff 95986. fjricci added a comment. Add test cases https://reviews.llvm.org/D32192 Files: lib/Driver/ToolChains/Darwin.cpp test/Driver/fsanitize.c test/Driver/sanitizer-ld.c Index: test/Driver/sanitizer-ld.c === --- test/Driver/sanitizer-ld.c +++ test/Driver/sanitizer-ld.c @@ -409,6 +409,15 @@ // CHECK-ASAN-DARWIN106-CXX: libclang_rt.asan_osx_dynamic.dylib // CHECK-ASAN-DARWIN106-CXX-NOT: -lc++abi +// RUN: %clangxx -fsanitize=leak %s -### -o %t.o 2>&1 \ +// RUN: -mmacosx-version-min=10.6 \ +// RUN: -target x86_64-apple-darwin13.4.0 -fuse-ld=ld -stdlib=platform \ +// RUN: --sysroot=%S/Inputs/basic_linux_tree \ +// RUN: | FileCheck --check-prefix=CHECK-LSAN-DARWIN106-CXX %s +// CHECK-LSAN-DARWIN106-CXX: "{{.*}}ld{{(.exe)?}}" +// CHECK-LSAN-DARWIN106-CXX: libclang_rt.lsan_osx_dynamic.dylib +// CHECK-LSAN-DARWIN106-CXX-NOT: -lc++abi + // RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ // RUN: -target x86_64-unknown-linux -fuse-ld=ld -fsanitize=safe-stack \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ Index: test/Driver/fsanitize.c === --- test/Driver/fsanitize.c +++ test/Driver/fsanitize.c @@ -358,6 +358,27 @@ // RUN: %clang -target i386-pc-openbsd -fsanitize=address %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ASAN-OPENBSD // CHECK-ASAN-OPENBSD: unsupported option '-fsanitize=address' for target 'i386-pc-openbsd' +// RUN: %clang -target x86_64-apple-darwin -fsanitize=leak %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LSAN-X86-64-DARWIN +// CHECK-LSAN-X86-64-DARWIN-NOT: unsupported option + +// RUN: %clang -target x86_64-apple-iossimulator -fsanitize=leak %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LSAN-X86-64-IOSSIMULATOR +// CHECK-LSAN-X86-64-IOSSIMULATOR-NOT: unsupported option + +// RUN: %clang -target x86_64-apple-tvossimulator -fsanitize=leak %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LSAN-X86-64-TVOSSIMULATOR +// CHECK-LSAN-X86-64-TVOSSIMULATOR-NOT: unsupported option + +// RUN: %clang -target i386-apple-darwin -fsanitize=leak %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LSAN-I386-DARWIN +// CHECK-LSAN-I386-DARWIN-NOT: unsupported option + +// RUN: %clang -target arm-apple-ios -fsanitize=leak %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LSAN-ARM-IOS +// CHECK-LSAN-ARM-IOS-NOT: unsupported option + +// RUN: %clang -target i386-apple-iossimulator -fsanitize=leak %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LSAN-I386-IOSSIMULATOR +// CHECK-LSAN-I386-IOSSIMULATOR-NOT: unsupported option + +// RUN: %clang -target i386-apple-tvossimulator -fsanitize=leak %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LSAN-I386-TVOSSIMULATOR +// CHECK-LSAN-I386-TVOSSIMULATOR-NOT: unsupported option + // RUN: %clang -target i686-linux-gnu -fsanitize=efficiency-cache-frag %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ESAN-X86 // RUN: %clang -target i686-linux-gnu -fsanitize=efficiency-working-set %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ESAN-X86 // CHECK-ESAN-X86: error: unsupported option '-fsanitize=efficiency-{{.*}}' for target 'i686--linux-gnu' Index: lib/Driver/ToolChains/Darwin.cpp === --- lib/Driver/ToolChains/Darwin.cpp +++ lib/Driver/ToolChains/Darwin.cpp @@ -1035,6 +1035,8 @@ const SanitizerArgs &Sanitize = getSanitizerArgs(); if (Sanitize.needsAsanRt()) AddLinkSanitizerLibArgs(Args, CmdArgs, "asan"); + if (Sanitize.needsLsanRt()) +AddLinkSanitizerLibArgs(Args, CmdArgs, "lsan"); if (Sanitize.needsUbsanRt()) AddLinkSanitizerLibArgs(Args, CmdArgs, "ubsan"); if (Sanitize.needsTsanRt()) @@ -1892,6 +1894,7 @@ const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64; SanitizerMask Res = ToolChain::getSupportedSanitizers(); Res |= SanitizerKind::Address; + Res |= SanitizerKind::Leak; if (isTargetMacOS()) { if (!isMacosxVersionLT(10, 9)) Res |= SanitizerKind::Vptr; Index: test/Driver/sanitizer-ld.c === --- test/Driver/sanitizer-ld.c +++ test/Driver/sanitizer-ld.c @@ -409,6 +409,15 @@ // CHECK-ASAN-DARWIN106-CXX: libclang_rt.asan_osx_dynamic.dylib // CHECK-ASAN-DARWIN106-CXX-NOT: -lc++abi +// RUN: %clangxx -fsanitize=leak %s -### -o %t.o 2>&1 \ +// RUN: -mmacosx-version-min=10.6 \ +// RUN: -target x86_64-apple-darwin13.4.0 -fuse-ld=ld -stdlib=platform \ +// RUN: --sysroot=%S/Inputs/basic_linux_tree \ +// RUN: | FileCheck --check-prefix=CHECK-LSAN-DARWIN106-CXX %s +// CHECK-LSAN-DARWIN106-CXX: "{{.*}}ld{{(.exe)?}}" +// CHECK-LSAN-DARWIN106-CXX: libclang_rt.lsan_osx_dynamic.dylib +// CHECK-LSAN-DARWIN106-CXX-NOT: -lc++abi + // RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ // RUN: -target x86_64-unknown-linux -fuse-ld=ld -fsanitize=sa
[PATCH] D32192: Enable leak sanitizer builds for darwin
This revision was automatically updated to reflect the committed changes. Closed by commit rL300894: Enable leak sanitizer builds for darwin (authored by fjricci). Changed prior to commit: https://reviews.llvm.org/D32192?vs=95986&id=96019#toc Repository: rL LLVM https://reviews.llvm.org/D32192 Files: cfe/trunk/lib/Driver/ToolChains/Darwin.cpp cfe/trunk/test/Driver/fsanitize.c cfe/trunk/test/Driver/sanitizer-ld.c Index: cfe/trunk/test/Driver/sanitizer-ld.c === --- cfe/trunk/test/Driver/sanitizer-ld.c +++ cfe/trunk/test/Driver/sanitizer-ld.c @@ -409,6 +409,15 @@ // CHECK-ASAN-DARWIN106-CXX: libclang_rt.asan_osx_dynamic.dylib // CHECK-ASAN-DARWIN106-CXX-NOT: -lc++abi +// RUN: %clangxx -fsanitize=leak %s -### -o %t.o 2>&1 \ +// RUN: -mmacosx-version-min=10.6 \ +// RUN: -target x86_64-apple-darwin13.4.0 -fuse-ld=ld -stdlib=platform \ +// RUN: --sysroot=%S/Inputs/basic_linux_tree \ +// RUN: | FileCheck --check-prefix=CHECK-LSAN-DARWIN106-CXX %s +// CHECK-LSAN-DARWIN106-CXX: "{{.*}}ld{{(.exe)?}}" +// CHECK-LSAN-DARWIN106-CXX: libclang_rt.lsan_osx_dynamic.dylib +// CHECK-LSAN-DARWIN106-CXX-NOT: -lc++abi + // RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ // RUN: -target x86_64-unknown-linux -fuse-ld=ld -fsanitize=safe-stack \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ Index: cfe/trunk/test/Driver/fsanitize.c === --- cfe/trunk/test/Driver/fsanitize.c +++ cfe/trunk/test/Driver/fsanitize.c @@ -358,6 +358,27 @@ // RUN: %clang -target i386-pc-openbsd -fsanitize=address %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ASAN-OPENBSD // CHECK-ASAN-OPENBSD: unsupported option '-fsanitize=address' for target 'i386-pc-openbsd' +// RUN: %clang -target x86_64-apple-darwin -fsanitize=leak %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LSAN-X86-64-DARWIN +// CHECK-LSAN-X86-64-DARWIN-NOT: unsupported option + +// RUN: %clang -target x86_64-apple-iossimulator -fsanitize=leak %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LSAN-X86-64-IOSSIMULATOR +// CHECK-LSAN-X86-64-IOSSIMULATOR-NOT: unsupported option + +// RUN: %clang -target x86_64-apple-tvossimulator -fsanitize=leak %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LSAN-X86-64-TVOSSIMULATOR +// CHECK-LSAN-X86-64-TVOSSIMULATOR-NOT: unsupported option + +// RUN: %clang -target i386-apple-darwin -fsanitize=leak %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LSAN-I386-DARWIN +// CHECK-LSAN-I386-DARWIN-NOT: unsupported option + +// RUN: %clang -target arm-apple-ios -fsanitize=leak %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LSAN-ARM-IOS +// CHECK-LSAN-ARM-IOS-NOT: unsupported option + +// RUN: %clang -target i386-apple-iossimulator -fsanitize=leak %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LSAN-I386-IOSSIMULATOR +// CHECK-LSAN-I386-IOSSIMULATOR-NOT: unsupported option + +// RUN: %clang -target i386-apple-tvossimulator -fsanitize=leak %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LSAN-I386-TVOSSIMULATOR +// CHECK-LSAN-I386-TVOSSIMULATOR-NOT: unsupported option + // RUN: %clang -target i686-linux-gnu -fsanitize=efficiency-cache-frag %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ESAN-X86 // RUN: %clang -target i686-linux-gnu -fsanitize=efficiency-working-set %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ESAN-X86 // CHECK-ESAN-X86: error: unsupported option '-fsanitize=efficiency-{{.*}}' for target 'i686--linux-gnu' Index: cfe/trunk/lib/Driver/ToolChains/Darwin.cpp === --- cfe/trunk/lib/Driver/ToolChains/Darwin.cpp +++ cfe/trunk/lib/Driver/ToolChains/Darwin.cpp @@ -1035,6 +1035,8 @@ const SanitizerArgs &Sanitize = getSanitizerArgs(); if (Sanitize.needsAsanRt()) AddLinkSanitizerLibArgs(Args, CmdArgs, "asan"); + if (Sanitize.needsLsanRt()) +AddLinkSanitizerLibArgs(Args, CmdArgs, "lsan"); if (Sanitize.needsUbsanRt()) AddLinkSanitizerLibArgs(Args, CmdArgs, "ubsan"); if (Sanitize.needsTsanRt()) @@ -1892,6 +1894,7 @@ const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64; SanitizerMask Res = ToolChain::getSupportedSanitizers(); Res |= SanitizerKind::Address; + Res |= SanitizerKind::Leak; if (isTargetMacOS()) { if (!isMacosxVersionLT(10, 9)) Res |= SanitizerKind::Vptr; Index: cfe/trunk/test/Driver/sanitizer-ld.c === --- cfe/trunk/test/Driver/sanitizer-ld.c +++ cfe/trunk/test/Driver/sanitizer-ld.c @@ -409,6 +409,15 @@ // CHECK-ASAN-DARWIN106-CXX: libclang_rt.asan_osx_dynamic.dylib // CHECK-ASAN-DARWIN106-CXX-NOT: -lc++abi +// RUN: %clangxx -fsanitize=leak %s -### -o %t.o 2>&1 \ +// RUN: -mmacosx-version-min=10.6 \ +// RUN: -target x86_64-apple-darwin13.4.0 -fuse-ld=ld -stdlib=platform \ +// RUN: --sysroot=%S/Inputs/basic_linux_tree \ +// RUN: | FileCheck -