Index: compiler-rt/trunk/test/CMakeLists.txt =================================================================== --- compiler-rt/trunk/test/CMakeLists.txt +++ compiler-rt/trunk/test/CMakeLists.txt @@ -19,7 +19,7 @@ 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 + clang clang-headers FileCheck count not llvm-config llvm-nm llvm-symbolizer compiler-rt-headers) if (COMPILER_RT_HAS_PROFILE) list(APPEND SANITIZER_COMMON_LIT_TEST_DEPS profile) Index: compiler-rt/trunk/test/cfi/CMakeLists.txt =================================================================== --- compiler-rt/trunk/test/cfi/CMakeLists.txt +++ compiler-rt/trunk/test/cfi/CMakeLists.txt @@ -3,12 +3,10 @@ ${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg ) -set(CFI_TEST_DEPS) +set(CFI_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS}) if(NOT COMPILER_RT_STANDALONE_BUILD) list(APPEND CFI_TEST_DEPS - FileCheck - clang - not + opt ubsan ) if(LLVM_ENABLE_PIC AND LLVM_BINUTILS_INCDIR) Index: compiler-rt/trunk/test/cfi/anon-namespace.cpp =================================================================== --- compiler-rt/trunk/test/cfi/anon-namespace.cpp +++ compiler-rt/trunk/test/cfi/anon-namespace.cpp @@ -68,20 +68,7 @@ #ifdef TU2 int main() { -#ifdef B32 - break_optimization(new Deriver); -#endif - -#ifdef B64 - break_optimization(new Deriver); - break_optimization(new Deriver); -#endif - -#ifdef BM - break_optimization(new Deriver); - break_optimization(new Deriver); - break_optimization(new Deriver); -#endif + create_derivers(); A *a = mkb(); break_optimization(a); Index: compiler-rt/trunk/test/cfi/bad-cast.cpp =================================================================== --- compiler-rt/trunk/test/cfi/bad-cast.cpp +++ compiler-rt/trunk/test/cfi/bad-cast.cpp @@ -87,20 +87,7 @@ }; int main(int argc, char **argv) { -#ifdef B32 - break_optimization(new Deriver); -#endif - -#ifdef B64 - break_optimization(new Deriver); - break_optimization(new Deriver); -#endif - -#ifdef BM - break_optimization(new Deriver); - break_optimization(new Deriver); - break_optimization(new Deriver); -#endif + create_derivers(); B *b = new B; break_optimization(b); Index: compiler-rt/trunk/test/cfi/create-derivers.test =================================================================== --- compiler-rt/trunk/test/cfi/create-derivers.test +++ compiler-rt/trunk/test/cfi/create-derivers.test @@ -0,0 +1,20 @@ +REQUIRES: asserts + +RUN: %clangxx_cfi -c -o %t1.o %S/simple-fail.cpp +RUN: opt -lowerbitsets -debug-only=lowerbitsets -o /dev/null %t1.o 2>&1 | FileCheck --check-prefix=B0 %s +B0: {{1B|B@@}}: {{.*}} size 1 + +RUN: %clangxx_cfi -DB32 -c -o %t2.o %S/simple-fail.cpp +RUN: opt -lowerbitsets -debug-only=lowerbitsets -o /dev/null %t2.o 2>&1 | FileCheck --check-prefix=B32 %s +B32: {{1B|B@@}}: {{.*}} size 24 +B32-NOT: all-ones + +RUN: %clangxx_cfi -DB64 -c -o %t3.o %S/simple-fail.cpp +RUN: opt -lowerbitsets -debug-only=lowerbitsets -o /dev/null %t3.o 2>&1 | FileCheck --check-prefix=B64 %s +B64: {{1B|B@@}}: {{.*}} size 54 +B64-NOT: all-ones + +RUN: %clangxx_cfi -DBM -c -o %t4.o %S/simple-fail.cpp +RUN: opt -lowerbitsets -debug-only=lowerbitsets -o /dev/null %t4.o 2>&1 | FileCheck --check-prefix=BM %s +BM: {{1B|B@@}}: {{.*}} size 84 +BM-NOT: all-ones Index: compiler-rt/trunk/test/cfi/lit.cfg =================================================================== --- compiler-rt/trunk/test/cfi/lit.cfg +++ compiler-rt/trunk/test/cfi/lit.cfg @@ -2,7 +2,7 @@ import os config.name = 'cfi' -config.suffixes = ['.cpp'] +config.suffixes = ['.cpp', '.test'] config.test_source_root = os.path.dirname(__file__) clangxx = ' '.join([config.clang] + config.cxx_mode_flags) Index: compiler-rt/trunk/test/cfi/multiple-inheritance.cpp =================================================================== --- compiler-rt/trunk/test/cfi/multiple-inheritance.cpp +++ compiler-rt/trunk/test/cfi/multiple-inheritance.cpp @@ -46,26 +46,8 @@ void C::g() {} int main(int argc, char **argv) { -#ifdef B32 - break_optimization(new Deriver); - break_optimization(new Deriver); -#endif - -#ifdef B64 - break_optimization(new Deriver); - break_optimization(new Deriver); - break_optimization(new Deriver); - break_optimization(new Deriver); -#endif - -#ifdef BM - break_optimization(new Deriver); - break_optimization(new Deriver); - break_optimization(new Deriver); - break_optimization(new Deriver); - break_optimization(new Deriver); - break_optimization(new Deriver); -#endif + create_derivers(); + create_derivers(); C *c = new C; break_optimization(c); Index: compiler-rt/trunk/test/cfi/nvcall.cpp =================================================================== --- compiler-rt/trunk/test/cfi/nvcall.cpp +++ compiler-rt/trunk/test/cfi/nvcall.cpp @@ -40,20 +40,7 @@ void B::g() {} int main() { -#ifdef B32 - break_optimization(new Deriver); -#endif - -#ifdef B64 - break_optimization(new Deriver); - break_optimization(new Deriver); -#endif - -#ifdef BM - break_optimization(new Deriver); - break_optimization(new Deriver); - break_optimization(new Deriver); -#endif + create_derivers(); A *a = new A; break_optimization(a); Index: compiler-rt/trunk/test/cfi/overwrite.cpp =================================================================== --- compiler-rt/trunk/test/cfi/overwrite.cpp +++ compiler-rt/trunk/test/cfi/overwrite.cpp @@ -39,20 +39,7 @@ void *fake_vtable[] = { 0, 0, (void *)&foo }; int main() { -#ifdef B32 - break_optimization(new Deriver); -#endif - -#ifdef B64 - break_optimization(new Deriver); - break_optimization(new Deriver); -#endif - -#ifdef BM - break_optimization(new Deriver); - break_optimization(new Deriver); - break_optimization(new Deriver); -#endif + create_derivers(); A *a = new A; *((void **)a) = fake_vtable + 2; // UB here Index: compiler-rt/trunk/test/cfi/sibling.cpp =================================================================== --- compiler-rt/trunk/test/cfi/sibling.cpp +++ compiler-rt/trunk/test/cfi/sibling.cpp @@ -37,20 +37,7 @@ }; int main() { -#ifdef B32 - break_optimization(new Deriver); -#endif - -#ifdef B64 - break_optimization(new Deriver); - break_optimization(new Deriver); -#endif - -#ifdef BM - break_optimization(new Deriver); - break_optimization(new Deriver); - break_optimization(new Deriver); -#endif + create_derivers(); B *b = new B; break_optimization(b); Index: compiler-rt/trunk/test/cfi/simple-fail.cpp =================================================================== --- compiler-rt/trunk/test/cfi/simple-fail.cpp +++ compiler-rt/trunk/test/cfi/simple-fail.cpp @@ -74,20 +74,7 @@ void B::f() {} int main() { -#ifdef B32 - break_optimization(new Deriver); -#endif - -#ifdef B64 - break_optimization(new Deriver); - break_optimization(new Deriver); -#endif - -#ifdef BM - break_optimization(new Deriver); - break_optimization(new Deriver); - break_optimization(new Deriver); -#endif + create_derivers(); A *a = new A; break_optimization(a); Index: compiler-rt/trunk/test/cfi/utils.h =================================================================== --- compiler-rt/trunk/test/cfi/utils.h +++ compiler-rt/trunk/test/cfi/utils.h @@ -5,49 +5,63 @@ __asm__ __volatile__("" : : "r" (arg) : "memory"); } -// Tests will instantiate this class to pad out bit sets to test out the various -// ways we can represent the bit set (32-bit inline, 64-bit inline, memory). -// This class has 37 virtual member functions, which forces us to use a -// pointer-aligned bitset. +// Tests will instantiate this class to pad out bit sets to test out the +// various ways we can represent the bit set (32-bit inline, 64-bit inline, +// memory). Instantiating this class will trigger the instantiation of I +// templates with I virtual tables for classes deriving from T, I-2 of which +// will be of size sizeof(void*) * 5, 1 of which will be of size sizeof(void*) +// * 3, and 1 of which will be of size sizeof(void*) * 9. (Under the MS ABI +// each virtual table will be sizeof(void*) bytes smaller). Each category +// of virtual tables is aligned to a different power of 2, precluding the +// all-ones optimization. As a result, the bit vector for the base class will +// need to contain at least I*2 entries to accommodate all the derived virtual +// tables. template -class Deriver : T { +struct Deriver : T { + Deriver() { + break_optimization(new Deriver); + } virtual void f() {} virtual void g() {} - virtual void f1() {} - virtual void f2() {} - virtual void f3() {} - virtual void f4() {} - virtual void f5() {} - virtual void f6() {} - virtual void f7() {} - virtual void f8() {} - virtual void f9() {} - virtual void f10() {} - virtual void f11() {} - virtual void f12() {} - virtual void f13() {} - virtual void f14() {} - virtual void f15() {} - virtual void f16() {} - virtual void f17() {} - virtual void f18() {} - virtual void f19() {} - virtual void f20() {} - virtual void f21() {} - virtual void f22() {} - virtual void f23() {} - virtual void f24() {} - virtual void f25() {} - virtual void f26() {} - virtual void f27() {} - virtual void f28() {} - virtual void f29() {} - virtual void f30() {} - virtual void f31() {} - virtual void f32() {} - virtual void f33() {} - virtual void f34() {} - virtual void f35() {} + virtual void h() {} }; +template +struct Deriver : T { + virtual void f() {} + void g() {} +}; + +template +struct Deriver : T { + Deriver() { + break_optimization(new Deriver); + } + virtual void f() {} + virtual void g() {} + virtual void h() {} + virtual void i() {} + virtual void j() {} + virtual void k() {} + virtual void l() {} +}; + +// Instantiate enough classes to force CFI checks for type T to use bit +// vectors of size 32 (if B32 defined), 64 (if B64 defined) or >64 (if BM +// defined). +template +void create_derivers() { +#ifdef B32 + break_optimization(new Deriver); +#endif + +#ifdef B64 + break_optimization(new Deriver); +#endif + +#ifdef BM + break_optimization(new Deriver); +#endif +} + #endif Index: compiler-rt/trunk/test/cfi/vdtor.cpp =================================================================== --- compiler-rt/trunk/test/cfi/vdtor.cpp +++ compiler-rt/trunk/test/cfi/vdtor.cpp @@ -37,20 +37,7 @@ B::~B() {} int main() { -#ifdef B32 - break_optimization(new Deriver); -#endif - -#ifdef B64 - break_optimization(new Deriver); - break_optimization(new Deriver); -#endif - -#ifdef BM - break_optimization(new Deriver); - break_optimization(new Deriver); - break_optimization(new Deriver); -#endif + create_derivers(); A *a = new A; break_optimization(a); Index: compiler-rt/trunk/test/lit.common.cfg =================================================================== --- compiler-rt/trunk/test/lit.common.cfg +++ compiler-rt/trunk/test/lit.common.cfg @@ -5,6 +5,7 @@ # It is mostly copied from lit.cfg used by Clang. import os import platform +import re import subprocess import lit.formats @@ -138,3 +139,17 @@ config.lto_flags = ["-fuse-ld=lld-link2"] else: config.lto_supported = False + +# Ask llvm-config about assertion mode. +try: + llvm_config_cmd = subprocess.Popen( + [os.path.join(config.llvm_tools_dir, 'llvm-config'), '--assertion-mode'], + stdout = subprocess.PIPE, + env=config.environment) +except OSError: + print("Could not find llvm-config in " + llvm_tools_dir) + exit(42) + +if re.search(r'ON', llvm_config_cmd.stdout.read().decode('ascii')): + config.available_features.add('asserts') +llvm_config_cmd.wait()