Fix Checked C tests on Mac OS (#502)
This change updates the Checked C tests so that they run properly on Apple ARM64 hardware running a recent version of MacOS. The changes consist of: - Using SIGTRAP signal handlers catch runtime checking failures instead of SIGILL. - Only run Linux-specific header file tests on Linux. - Add a bounds-safe interface specific to MacOS so that errno work properly in a checked scope. Testing: check-checkedc passes on Windows x86 and MacOS 13.4.1
This commit is contained in:
Родитель
a37445f262
Коммит
9544bafa10
|
@ -24,7 +24,11 @@
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
#if defined(_WIN32) || defined(_WIN64)
|
||||||
__declspec(dllimport) int* __cdecl _errno(void) : itype(_Ptr<int>);
|
__declspec(dllimport) int* __cdecl _errno(void) : itype(_Ptr<int>);
|
||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
|
#if defined(__aarch64__)
|
||||||
|
extern int * __error(void) : itype(_Ptr<int>);
|
||||||
|
#else
|
||||||
extern int* __errno_location(void) : itype(_Ptr<int>);
|
extern int* __errno_location(void) : itype(_Ptr<int>);
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
extern int* __errno_location(void) : itype(_Ptr<int>) __THROW __attribute_const__;
|
extern int* __errno_location(void) : itype(_Ptr<int>) __THROW __attribute_const__;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// UNSUPPORTED: system-windows
|
// UNSUPPORTED: !linux
|
||||||
//
|
//
|
||||||
// Test include files for all combinations of Checked C enabled/disabled,
|
// Test include files for all combinations of Checked C enabled/disabled,
|
||||||
// and implicit inclusion of checked headers enabled/disabled. By default, both
|
// and implicit inclusion of checked headers enabled/disabled. By default, both
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// UNSUPPORTED: system-windows
|
// UNSUPPORTED: !linux
|
||||||
//
|
//
|
||||||
// Test include files for all combinations of Checked C enabled/disabled,
|
// Test include files for all combinations of Checked C enabled/disabled,
|
||||||
// and implicit inclusion of checked headers enabled/disabled. By default, both
|
// and implicit inclusion of checked headers enabled/disabled. By default, both
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// UNSUPPORTED: system-windows
|
// UNSUPPORTED: !linux
|
||||||
//
|
//
|
||||||
// Test include files for all combinations of Checked C enabled/disabled,
|
// Test include files for all combinations of Checked C enabled/disabled,
|
||||||
// and implicit inclusion of checked headers enabled/disabled. By default, both
|
// and implicit inclusion of checked headers enabled/disabled. By default, both
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// Test bounds checking in checked scopes of uses of
|
// Test bounds checking in checked scopes of uses of
|
||||||
// arrays that have declared bounds. The declared bounds
|
// arrays that have declared bounds. The declared bounds
|
||||||
// override bounds based on the size of the 1st
|
// override bounds based on the size of the 1st
|
||||||
// dimension of the array.
|
// dimension of the array.
|
||||||
//
|
//
|
||||||
// RUN: %clang %s -o %t1 -Werror -Wno-unused-value %checkedc_target_flags
|
// RUN: %clang %s -o %t1 -Werror -Wno-unused-value %checkedc_target_flags
|
||||||
|
@ -62,9 +62,12 @@ int write_fail(int testnum, int pos, ptr<struct S1> s, ptr<struct S3> s3);
|
||||||
int main(int argc, array_ptr<char*> argv : count(argc)) {
|
int main(int argc, array_ptr<char*> argv : count(argc)) {
|
||||||
|
|
||||||
// Set up the handler for a failing bounds check. Currently the Checked C
|
// Set up the handler for a failing bounds check. Currently the Checked C
|
||||||
// clang implementation raises a SIGILL when a bounds check fails. This
|
// clang implementation raises a SIGILL or SIGTRIP when a bounds check fails,
|
||||||
// may change in the future.
|
// dpending on the target OS. This may change in the future.
|
||||||
signal(SIGILL, handle_error);
|
signal(SIGILL, handle_error);
|
||||||
|
#if defined(__APPLE__) && defined(__aarch64__)
|
||||||
|
signal(SIGTRAP, handle_error);
|
||||||
|
#endif
|
||||||
|
|
||||||
// This makes sure output is not buffered for when
|
// This makes sure output is not buffered for when
|
||||||
// we hit errors.
|
// we hit errors.
|
||||||
|
@ -177,7 +180,7 @@ unexpected_success:
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
int write_fail(int testnum, int pos, ptr<struct S1> s,
|
int write_fail(int testnum, int pos, ptr<struct S1> s,
|
||||||
ptr<struct S3> s3) checked {
|
ptr<struct S3> s3) checked {
|
||||||
int result = 0;
|
int result = 0;
|
||||||
switch (testnum) {
|
switch (testnum) {
|
||||||
|
|
|
@ -96,9 +96,12 @@ void read_test(int failure_point, int *p : count(p_len), int p_len,
|
||||||
int main(int argc, array_ptr<char*> argv : count(argc)) {
|
int main(int argc, array_ptr<char*> argv : count(argc)) {
|
||||||
|
|
||||||
// Set up the handler for a failing bounds check. Currently the Checked C
|
// Set up the handler for a failing bounds check. Currently the Checked C
|
||||||
// clang implementation raises a SIGILL when a bounds check fails. This
|
// clang implementation raises a SIGILL or SIGTRAP when a bounds check fails,
|
||||||
// may change in the future.
|
// depending on the target platform. This may change in the future.
|
||||||
signal(SIGILL, handle_error);
|
signal(SIGILL, handle_error);
|
||||||
|
#if defined(__APPLE__) && defined(__aarch64__)
|
||||||
|
signal(SIGTRAP, handle_error);
|
||||||
|
#endif
|
||||||
|
|
||||||
// This makes sure output is not buffered for when
|
// This makes sure output is not buffered for when
|
||||||
// we hit errors.
|
// we hit errors.
|
||||||
|
@ -163,14 +166,14 @@ void write_driver(int failure_point, int *a1 : count(10),
|
||||||
dynamic_check(s1->len >= 5);
|
dynamic_check(s1->len >= 5);
|
||||||
switch (failure_point) {
|
switch (failure_point) {
|
||||||
// Vary global variable.
|
// Vary global variable.
|
||||||
case 0:
|
case 0:
|
||||||
write_test(failure_point, a1, 10, a2, 10, a3, 2, b1, 10, b2, 0, s1);
|
write_test(failure_point, a1, 10, a2, 10, a3, 2, b1, 10, b2, 0, s1);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
global_arr_len = 0;
|
global_arr_len = 0;
|
||||||
write_test(failure_point, a1, 10, a2, 10, a3, 2, b1, 10, b2, 0, s1);
|
write_test(failure_point, a1, 10, a2, 10, a3, 2, b1, 10, b2, 0, s1);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
global_arr_len = 1;
|
global_arr_len = 1;
|
||||||
write_test(failure_point, a1, 10, a2, 10, a3, 2, b1, 10, b2, 0, s1);
|
write_test(failure_point, a1, 10, a2, 10, a3, 2, b1, 10, b2, 0, s1);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -88,9 +88,12 @@ void handle_error(int err) {
|
||||||
int main(int argc, array_ptr<char*> argv : count(argc)) {
|
int main(int argc, array_ptr<char*> argv : count(argc)) {
|
||||||
|
|
||||||
// Set up the handler for a failing bounds check. Currently the Checked C
|
// Set up the handler for a failing bounds check. Currently the Checked C
|
||||||
// clang implementation raises a SIGILL when a bounds check fails. This
|
// clang implementation raises a SIGILL or SIGTRAP when a bounds check fails,
|
||||||
// may change in the future.
|
// depending on the target platform. This may change in the future.
|
||||||
signal(SIGILL, handle_error);
|
signal(SIGILL, handle_error);
|
||||||
|
#if defined(__APPLE__) && defined(__aarch64__)
|
||||||
|
signal(SIGTRAP, handle_error);
|
||||||
|
#endif
|
||||||
|
|
||||||
// This makes sure output is not buffered for when
|
// This makes sure output is not buffered for when
|
||||||
// we hit errors.
|
// we hit errors.
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
// struct S v;
|
// struct S v;
|
||||||
// *(v.f)
|
// *(v.f)
|
||||||
//
|
//
|
||||||
// Uses are tested in read, assignment,increment, and compound assignment
|
// Uses are tested in read, assignment,increment, and compound assignment
|
||||||
// expressions. The type of use is controlled by the macro names TEST_READ,
|
// expressions. The type of use is controlled by the macro names TEST_READ,
|
||||||
// TEST_WRITE, TEST_INCREMENT, and TEST_COMPOUND_ASSIGNMENT. The file must
|
// TEST_WRITE, TEST_INCREMENT, and TEST_COMPOUND_ASSIGNMENT. The file must
|
||||||
// be compiled with exactly one of those macro names defined.
|
// be compiled with exactly one of those macro names defined.
|
||||||
|
@ -137,9 +137,12 @@ void handle_error(int err) {
|
||||||
int main(int argc, array_ptr<char*> argv : count(argc)) {
|
int main(int argc, array_ptr<char*> argv : count(argc)) {
|
||||||
|
|
||||||
// Set up the handler for a failing bounds check. Currently the Checked C
|
// Set up the handler for a failing bounds check. Currently the Checked C
|
||||||
// clang implementation raises a SIGILL when a bounds check fails. This
|
// clang implementation raises a SIGILL or SIGTRAP when a bounds check fails,
|
||||||
// may change in the future.
|
// depending on the target platform. This may change in the future.
|
||||||
signal(SIGILL, handle_error);
|
signal(SIGILL, handle_error);
|
||||||
|
#if defined(__APPLE__) && defined(__aarch64__)
|
||||||
|
signal(SIGTRAP, handle_error);
|
||||||
|
#endif
|
||||||
|
|
||||||
// This makes sure output is not buffered for when
|
// This makes sure output is not buffered for when
|
||||||
// we hit errors.
|
// we hit errors.
|
||||||
|
@ -149,7 +152,7 @@ int main(int argc, array_ptr<char*> argv : count(argc)) {
|
||||||
puts("Error Setting Up Buffering");
|
puts("Error Setting Up Buffering");
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argc < 2) {
|
if (argc < 2) {
|
||||||
// CHECK-NOT: Requires Argument
|
// CHECK-NOT: Requires Argument
|
||||||
puts("Requires Argument");
|
puts("Requires Argument");
|
||||||
|
@ -385,7 +388,7 @@ void failing_test_1(void) {
|
||||||
puts("Unexpected Success");
|
puts("Unexpected Success");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Struct member bounds describe empty range (a + 2 > a),
|
// Struct member bounds describe empty range (a + 2 > a),
|
||||||
// no deref
|
// no deref
|
||||||
void failing_test_2(void) {
|
void failing_test_2(void) {
|
||||||
int a checked[3] = { 0, 0, 0 };
|
int a checked[3] = { 0, 0, 0 };
|
||||||
|
|
|
@ -73,9 +73,12 @@ void handle_error(int err) {
|
||||||
int main(int argc, array_ptr<char*> argv : count(argc)) {
|
int main(int argc, array_ptr<char*> argv : count(argc)) {
|
||||||
|
|
||||||
// Set up the handler for a failing bounds check. Currently the Checked C
|
// Set up the handler for a failing bounds check. Currently the Checked C
|
||||||
// clang implementation raises a SIGILL when a bounds check fails. This
|
// clang implementation raises a SIGILL or SIGTRAP when a bounds check fails,
|
||||||
// may change in the future.
|
// depending on the target platform. This may change in the future.
|
||||||
signal(SIGILL, handle_error);
|
signal(SIGILL, handle_error);
|
||||||
|
#if defined(__APPLE__) && defined(__aarch64__)
|
||||||
|
signal(SIGTRAP, handle_error);
|
||||||
|
#endif
|
||||||
|
|
||||||
// This makes sure output is not buffered for when
|
// This makes sure output is not buffered for when
|
||||||
// we hit errors.
|
// we hit errors.
|
||||||
|
@ -101,7 +104,7 @@ int main(int argc, array_ptr<char*> argv : count(argc)) {
|
||||||
puts("Beginning test");
|
puts("Beginning test");
|
||||||
int testcase = atoi(argv[1]);
|
int testcase = atoi(argv[1]);
|
||||||
switch (testcase) {
|
switch (testcase) {
|
||||||
case 1:
|
case 1:
|
||||||
test1();
|
test1();
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
|
|
|
@ -40,7 +40,13 @@ void fail1(int x) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, array_ptr<char*> argv : count(argc)) {
|
int main(int argc, array_ptr<char*> argv : count(argc)) {
|
||||||
|
// Set up the handler for a failing bounds check. Currently the Checked C
|
||||||
|
// clang implementation raises a SIGILL or SIGTRAP when a bounds check fails,
|
||||||
|
// depending on the target platform. This may change in the future.
|
||||||
signal(SIGILL, handle_error);
|
signal(SIGILL, handle_error);
|
||||||
|
#if defined(__APPLE__) && defined(__aarch64__)
|
||||||
|
signal(SIGTRAP, handle_error);
|
||||||
|
#endif
|
||||||
|
|
||||||
// This makes sure output is not buffered for when
|
// This makes sure output is not buffered for when
|
||||||
// we hit errors.
|
// we hit errors.
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// Test bounds checking of uses of array subscript expressions.
|
// Test bounds checking of uses of array subscript expressions.
|
||||||
//
|
//
|
||||||
// Uses are tested in read, assignment,increment, and compound assignment
|
// Uses are tested in read, assignment,increment, and compound assignment
|
||||||
// expressions. The type of use is controlled by the macro names TEST_READ,
|
// expressions. The type of use is controlled by the macro names TEST_READ,
|
||||||
// TEST_WRITE, TEST_INCREMENT, and TEST_COMPOUND_ASSIGNMENT. The file must
|
// TEST_WRITE, TEST_INCREMENT, and TEST_COMPOUND_ASSIGNMENT. The file must
|
||||||
// be compiled with exactly one of those macro names defined.
|
// be compiled with exactly one of those macro names defined.
|
||||||
|
@ -198,12 +198,15 @@ void handle_error(int err) {
|
||||||
int main(int argc, array_ptr<char*> argv : count(argc)) {
|
int main(int argc, array_ptr<char*> argv : count(argc)) {
|
||||||
|
|
||||||
// Set up the handler for a failing bounds check. Currently the Checked C
|
// Set up the handler for a failing bounds check. Currently the Checked C
|
||||||
// clang implementation raises a SIGILL when a bounds check fails. This
|
// clang implementation raises a SIGILL or SIGTRAP when a bounds check fails,
|
||||||
// may change in the future.
|
// depending on the target platform. This may change in the future.
|
||||||
signal(SIGILL, handle_error);
|
signal(SIGILL, handle_error);
|
||||||
|
#if defined(__APPLE__) && defined(__aarch64__)
|
||||||
|
signal(SIGTRAP, handle_error);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Unfortunately, using atoi everywhere below isn't super
|
// Unfortunately, using atoi everywhere below isn't super
|
||||||
// great, as it will return 0 if it can't parse, which is a valid,
|
// great, as it will return 0 if it can't parse, which is a valid,
|
||||||
// non-erroring index. This is why we use CHECK-*-NOT to make sure
|
// non-erroring index. This is why we use CHECK-*-NOT to make sure
|
||||||
// the tests fail before getting to certain output.
|
// the tests fail before getting to certain output.
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
// controlled by the macro BOUNDS_INTERFACE.
|
// controlled by the macro BOUNDS_INTERFACE.
|
||||||
//
|
//
|
||||||
// To shorten test times (and keep the parallelism more balanced when tests are
|
// To shorten test times (and keep the parallelism more balanced when tests are
|
||||||
// run in parallel), separate test suite driver files are used for these
|
// run in parallel), separate test suite driver files are used for these
|
||||||
// additional cases.
|
// additional cases.
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
|
@ -109,7 +109,7 @@
|
||||||
// RUN: %checkedc_rununder %t1 nt_constant_bounds compound 0 | FileCheck %s --check-prefixes=NT-CB-COMPOUND-START,NT-CB-COMPOUND-SUCCESS
|
// RUN: %checkedc_rununder %t1 nt_constant_bounds compound 0 | FileCheck %s --check-prefixes=NT-CB-COMPOUND-START,NT-CB-COMPOUND-SUCCESS
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
// Test operations on a pointer to a null-terminated array with bounds dependent on the value of an argument n.
|
// Test operations on a pointer to a null-terminated array with bounds dependent on the value of an argument n.
|
||||||
// The pointer points an array of n integers, where the integers are initialized to 0, 2 ...2 * (n-1).
|
// The pointer points an array of n integers, where the integers are initialized to 0, 2 ...2 * (n-1).
|
||||||
// 3rd argument = array length. 4th argument = element to do operation on.
|
// 3rd argument = array length. 4th argument = element to do operation on.
|
||||||
//
|
//
|
||||||
|
@ -153,7 +153,7 @@
|
||||||
// i.e. with a stride of 2.
|
// i.e. with a stride of 2.
|
||||||
// The 3rd argument = the array length (n), the 4th and 5th argument specify the
|
// The 3rd argument = the array length (n), the 4th and 5th argument specify the
|
||||||
// element to do the operation on. The 4th argument is the 1st dimension index,
|
// element to do the operation on. The 4th argument is the 1st dimension index,
|
||||||
// and the 5th argument is the 2nd dimension index.
|
// and the 5th argument is the 2nd dimension index.
|
||||||
//
|
//
|
||||||
// RUN: %checkedc_rununder %t1 md_dependent_bounds read 2 2 0 | FileCheck %s --check-prefixes=MD-DB-READ-START,MD-DB-READ-FAIL
|
// RUN: %checkedc_rununder %t1 md_dependent_bounds read 2 2 0 | FileCheck %s --check-prefixes=MD-DB-READ-START,MD-DB-READ-FAIL
|
||||||
// RUN: %checkedc_rununder %t1 md_dependent_bounds read 3 -1 1 | FileCheck %s --check-prefixes=MD-DB-READ-START,MD-DB-READ-FAIL
|
// RUN: %checkedc_rununder %t1 md_dependent_bounds read 3 -1 1 | FileCheck %s --check-prefixes=MD-DB-READ-START,MD-DB-READ-FAIL
|
||||||
|
@ -203,8 +203,8 @@
|
||||||
#include <stdchecked.h>
|
#include <stdchecked.h>
|
||||||
|
|
||||||
#define SIZE 100 // pre-allocated array size. We return pointers to
|
#define SIZE 100 // pre-allocated array size. We return pointers to
|
||||||
// pre-allocated static arrays so that we can check
|
// pre-allocated static arrays so that we can check
|
||||||
// operations that use the pointer to modify memory.
|
// operations that use the pointer to modify memory.
|
||||||
#define CONSTANT_SIZE 5 // constant bound value.
|
#define CONSTANT_SIZE 5 // constant bound value.
|
||||||
|
|
||||||
|
|
||||||
|
@ -307,7 +307,7 @@ array_ptr<int> g_const_bounds(void) : count(CONSTANT_SIZE)
|
||||||
#ifdef BOUNDS_INTERFACE
|
#ifdef BOUNDS_INTERFACE
|
||||||
int *g_nt_dependent_bounds(unsigned int i) : itype(nt_array_ptr<int>) count(i)
|
int *g_nt_dependent_bounds(unsigned int i) : itype(nt_array_ptr<int>) count(i)
|
||||||
#else
|
#else
|
||||||
nt_array_ptr<int> g_nt_dependent_bounds(unsigned int i) : count(i)
|
nt_array_ptr<int> g_nt_dependent_bounds(unsigned int i) : count(i)
|
||||||
#endif
|
#endif
|
||||||
unchecked {
|
unchecked {
|
||||||
if (i >= SIZE + 1)
|
if (i >= SIZE + 1)
|
||||||
|
@ -321,8 +321,8 @@ unchecked {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocate and initialize a zero-terminated integer array of
|
// Allocate and initialize a zero-terminated integer array of
|
||||||
// size i + 1, with the array initialized with
|
// size i + 1, with the array initialized with
|
||||||
// values 1, 2, .. CONSTANT_SIZE - 1, 0.
|
// values 1, 2, .. CONSTANT_SIZE - 1, 0.
|
||||||
#ifdef BOUNDS_INTERFACE
|
#ifdef BOUNDS_INTERFACE
|
||||||
int *g_nt_const_bounds(void) : itype(nt_array_ptr<int>) count(CONSTANT_SIZE)
|
int *g_nt_const_bounds(void) : itype(nt_array_ptr<int>) count(CONSTANT_SIZE)
|
||||||
#else
|
#else
|
||||||
|
@ -333,7 +333,7 @@ nt_array_ptr<int> g_nt_const_bounds(void) : count(CONSTANT_SIZE)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocate and initialize an array of size i of 3-element arrays.
|
// Allocate and initialize an array of size i of 3-element arrays.
|
||||||
// with the array elements initialized by the sequence
|
// with the array elements initialized by the sequence
|
||||||
// 1, 3, 5 ... (i - 1) * 3 * 2 + 5 (i.e. with a stride of 2).
|
// 1, 3, 5 ... (i - 1) * 3 * 2 + 5 (i.e. with a stride of 2).
|
||||||
#ifdef BOUNDS_INTERFACE
|
#ifdef BOUNDS_INTERFACE
|
||||||
arrty *g_md_dependent_bounds(unsigned int i) : itype(array_ptr<int checked[3]>) count(i)
|
arrty *g_md_dependent_bounds(unsigned int i) : itype(array_ptr<int checked[3]>) count(i)
|
||||||
|
@ -345,7 +345,7 @@ array_ptr<int checked[3]> g_md_dependent_bounds(unsigned int i) : count(i)
|
||||||
return NULL;
|
return NULL;
|
||||||
// TODO: after incorporating dataflow information into bounds declaration
|
// TODO: after incorporating dataflow information into bounds declaration
|
||||||
// checking, this dynamic_bounds_cast won't be needed.
|
// checking, this dynamic_bounds_cast won't be needed.
|
||||||
array_ptr<int checked[3]> result : count(i) =
|
array_ptr<int checked[3]> result : count(i) =
|
||||||
dynamic_bounds_cast<array_ptr<int checked[3]>>(arr_2d, count(i));
|
dynamic_bounds_cast<array_ptr<int checked[3]>>(arr_2d, count(i));
|
||||||
int_md_array_init(result, i, 2);
|
int_md_array_init(result, i, 2);
|
||||||
return result;
|
return result;
|
||||||
|
@ -659,7 +659,7 @@ int compute_val(int dim1, int dim2) {
|
||||||
void test_md_dependent_bounds(int argc, array_ptr<nt_array_ptr<char>> argv : count(argc),
|
void test_md_dependent_bounds(int argc, array_ptr<nt_array_ptr<char>> argv : count(argc),
|
||||||
int idx) {
|
int idx) {
|
||||||
// g_md_dependent_bounds(i) returns a pointer to i 3-element arrays.
|
// g_md_dependent_bounds(i) returns a pointer to i 3-element arrays.
|
||||||
// where the array elements are initialzied to the sequence
|
// where the array elements are initialzied to the sequence
|
||||||
// 1, 3, 5 ... 3 * 2 * i (i.e. with a stride of 2).
|
// 1, 3, 5 ... 3 * 2 * i (i.e. with a stride of 2).
|
||||||
// The pointer value is arr_2d. i must be < SIZE
|
// The pointer value is arr_2d. i must be < SIZE
|
||||||
// (the size of arr_1d)
|
// (the size of arr_1d)
|
||||||
|
@ -698,7 +698,7 @@ void test_md_dependent_bounds(int argc, array_ptr<nt_array_ptr<char>> argv : cou
|
||||||
// MD-DB-WRITE-FAIL-NOT: Passed md dependent bounds write
|
// MD-DB-WRITE-FAIL-NOT: Passed md dependent bounds write
|
||||||
// MD-DB-WRITE-SUCCESS: Passed md dependent bounds write
|
// MD-DB-WRITE-SUCCESS: Passed md dependent bounds write
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case INC: {
|
case INC: {
|
||||||
puts("Starting md dependent bounds increment");
|
puts("Starting md dependent bounds increment");
|
||||||
// MD-DB-INC-START: Starting md dependent bounds increment
|
// MD-DB-INC-START: Starting md dependent bounds increment
|
||||||
|
@ -740,12 +740,15 @@ void test_md_dependent_bounds(int argc, array_ptr<nt_array_ptr<char>> argv : cou
|
||||||
int main(int argc, array_ptr<nt_array_ptr<char>> argv : count(argc)) {
|
int main(int argc, array_ptr<nt_array_ptr<char>> argv : count(argc)) {
|
||||||
|
|
||||||
// Set up the handler for a failing bounds check. Currently the Checked C
|
// Set up the handler for a failing bounds check. Currently the Checked C
|
||||||
// clang implementation raises a SIGILL when a bounds check fails. This
|
// clang implementation raises a SIGILL or SIGTRAP when a bounds check fails,
|
||||||
// may change in the future.
|
// depending on the target platform. This may change in the future.
|
||||||
signal(SIGILL, handle_error);
|
signal(SIGILL, handle_error);
|
||||||
|
#if defined(__APPLE__) && defined(__aarch64__)
|
||||||
|
signal(SIGTRAP, handle_error);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Unfortunately, using atoi everywhere below isn't super
|
// Unfortunately, using atoi everywhere below isn't super
|
||||||
// great, as it will return 0 if it can't parse, which is a valid,
|
// great, as it will return 0 if it can't parse, which is a valid,
|
||||||
// non-erroring index. This is why we use CHECK-*-NOT to make sure
|
// non-erroring index. This is why we use CHECK-*-NOT to make sure
|
||||||
// the tests fail before getting to certain output.
|
// the tests fail before getting to certain output.
|
||||||
|
|
||||||
|
|
|
@ -5,14 +5,14 @@
|
||||||
// struct S v;
|
// struct S v;
|
||||||
// v.f[e]
|
// v.f[e]
|
||||||
//
|
//
|
||||||
// Uses are tested in read, assignment,increment, and compound assignment
|
// Uses are tested in read, assignment,increment, and compound assignment
|
||||||
// expressions. The type of use is controlled by the macro names TEST_READ,
|
// expressions. The type of use is controlled by the macro names TEST_READ,
|
||||||
// TEST_WRITE, TEST_INCREMENT, and TEST_COMPOUND_ASSIGNMENT. The file must
|
// TEST_WRITE, TEST_INCREMENT, and TEST_COMPOUND_ASSIGNMENT. The file must
|
||||||
// be compiled with exactly one of those macro names defined.
|
// be compiled with exactly one of those macro names defined.
|
||||||
//
|
//
|
||||||
// The source code for this test is parameterized by the member access operator
|
// The source code for this test is parameterized by the member access operator
|
||||||
// so that it can be re-used for member expressions formed using the arrow
|
// so that it can be re-used for member expressions formed using the arrow
|
||||||
// operator. The member access operator is controlled by macro name ARROW.
|
// operator. The member access operator is controlled by macro name ARROW.
|
||||||
// When the the macro name is undefined, the dot (.) operator is used. When it is
|
// When the the macro name is undefined, the dot (.) operator is used. When it is
|
||||||
// defined, the arrow (->) operator is used.
|
// defined, the arrow (->) operator is used.
|
||||||
//
|
//
|
||||||
|
@ -123,9 +123,12 @@ void handle_error(int err) {
|
||||||
int main(int argc, array_ptr<char*> argv : count(argc)) {
|
int main(int argc, array_ptr<char*> argv : count(argc)) {
|
||||||
|
|
||||||
// Set up the handler for a failing bounds check. Currently the Checked C
|
// Set up the handler for a failing bounds check. Currently the Checked C
|
||||||
// clang implementation raises a SIGILL when a bounds check fails. This
|
// clang implementation raises a SIGILL or SIGTRAP when a bounds check fails,
|
||||||
// may change in the future.
|
// depending on the target platform. This may change in the future.
|
||||||
signal(SIGILL, handle_error);
|
signal(SIGILL, handle_error);
|
||||||
|
#if defined(__APPLE__) && defined(__aarch64__)
|
||||||
|
signal(SIGTRAP, handle_error);
|
||||||
|
#endif
|
||||||
|
|
||||||
// This makes sure output is not buffered for when
|
// This makes sure output is not buffered for when
|
||||||
// we hit errors.
|
// we hit errors.
|
||||||
|
@ -135,7 +138,7 @@ int main(int argc, array_ptr<char*> argv : count(argc)) {
|
||||||
puts("Error Setting Up Buffering");
|
puts("Error Setting Up Buffering");
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argc < 2) {
|
if (argc < 2) {
|
||||||
// CHECK-NOT: Requires Argument
|
// CHECK-NOT: Requires Argument
|
||||||
puts("Requires Argument");
|
puts("Requires Argument");
|
||||||
|
@ -145,14 +148,14 @@ int main(int argc, array_ptr<char*> argv : count(argc)) {
|
||||||
int v checked[5] = { 0, 1, 2, 3, 4};
|
int v checked[5] = { 0, 1, 2, 3, 4};
|
||||||
struct S1 s1 = { v, 5 };
|
struct S1 s1 = { v, 5 };
|
||||||
struct S2 s2 = { { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, -1 };
|
struct S2 s2 = { { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, -1 };
|
||||||
|
|
||||||
// CHECK: Starting Test
|
// CHECK: Starting Test
|
||||||
puts("Starting Test");
|
puts("Starting Test");
|
||||||
#ifdef ARROW_OPERATOR
|
#ifdef ARROW_OPERATOR
|
||||||
puts("Using arrow operator"); // ARROW: Using arrow operator
|
puts("Using arrow operator"); // ARROW: Using arrow operator
|
||||||
#else
|
#else
|
||||||
puts("Using dot operator");
|
puts("Using dot operator");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
if (strcmp(argv[1], "pass1") == 0) {
|
if (strcmp(argv[1], "pass1") == 0) {
|
||||||
|
@ -341,7 +344,7 @@ void failing_test_2(int i) {
|
||||||
TEST_OP(s.arr[i], 1);
|
TEST_OP(s.arr[i], 1);
|
||||||
printf("Unreachable: %d\n", s.arr[i]);
|
printf("Unreachable: %d\n", s.arr[i]);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
puts("Unexpected Success");
|
puts("Unexpected Success");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,9 +44,12 @@ void handle_error(int err) {
|
||||||
int main(int argc, char**_Array argv _Count(argc)) {
|
int main(int argc, char**_Array argv _Count(argc)) {
|
||||||
|
|
||||||
// Set up the handler for a failing bounds check. Currently the Checked C
|
// Set up the handler for a failing bounds check. Currently the Checked C
|
||||||
// clang implementation raises a SIGILL when a bounds check fails. This
|
// clang implementation raises a SIGILL or SIGTRAP when a bounds check fails,
|
||||||
// may change in the future.
|
// depending on the target platform. This may change in the future.
|
||||||
signal(SIGILL, handle_error);
|
signal(SIGILL, handle_error);
|
||||||
|
#if defined(__APPLE__) && defined(__aarch64__)
|
||||||
|
signal(SIGTRAP, handle_error);
|
||||||
|
#endif
|
||||||
|
|
||||||
// This makes sure output is not buffered for when
|
// This makes sure output is not buffered for when
|
||||||
// we hit errors.
|
// we hit errors.
|
||||||
|
|
|
@ -23,9 +23,13 @@ void handle_error(int err) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
// Currently the Checked C clang implementation raises a SIGILL when a
|
// Set up the handler for a failing dynamic check. Currently the Checked C
|
||||||
// dynamic check fails. This may change in the future.
|
// clang implementation raises a SIGILL or SIGTRAP when a dynamic check fails,
|
||||||
|
// depending on the target platform. This may change in the future.
|
||||||
signal(SIGILL, handle_error);
|
signal(SIGILL, handle_error);
|
||||||
|
#if defined(__APPLE__) && defined(__aarch64__)
|
||||||
|
signal(SIGTRAP, handle_error);
|
||||||
|
#endif
|
||||||
|
|
||||||
f1(50);
|
f1(50);
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
//
|
//
|
||||||
// The following lines are for the LLVM test harness:
|
// The following lines are for the LLVM test harness:
|
||||||
//
|
//
|
||||||
|
// RUN %clang -###
|
||||||
// RUN: %clang -Xclang -verify -o %t.exe %s %checkedc_target_flags
|
// RUN: %clang -Xclang -verify -o %t.exe %s %checkedc_target_flags
|
||||||
// RUN: %checkedc_rununder %t.exe
|
// RUN: %checkedc_rununder %t.exe
|
||||||
|
|
||||||
|
@ -15,9 +16,13 @@ void handle_error(int err) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
// Currently the Checked C clang implementation raises a SIGILL when a
|
// Set up the handler for a failing dynamic check. Currently the Checked C
|
||||||
// dynamic check fails. This may change in the future.
|
// clang implementation raises a SIGILL or SIGTRAP when a dynamic check fails,
|
||||||
|
// depending on the target platform. This may change in the future.
|
||||||
signal(SIGILL, handle_error);
|
signal(SIGILL, handle_error);
|
||||||
|
#if defined(__APPLE__) && defined(__aarch64__)
|
||||||
|
signal(SIGTRAP, handle_error);
|
||||||
|
#endif
|
||||||
|
|
||||||
// This is expected fail at runtime. It is simple enough for clang to issue a warning
|
// This is expected fail at runtime. It is simple enough for clang to issue a warning
|
||||||
dynamic_check(false); // expected-warning {{dynamic check will always fail}}
|
dynamic_check(false); // expected-warning {{dynamic check will always fail}}
|
||||||
|
|
|
@ -128,6 +128,9 @@ void pass3() {
|
||||||
|
|
||||||
int main(int argc, array_ptr<char *> argv : count(argc)) {
|
int main(int argc, array_ptr<char *> argv : count(argc)) {
|
||||||
signal(SIGILL, handle_error);
|
signal(SIGILL, handle_error);
|
||||||
|
#if defined(__APPLE__) && defined(__aarch64__)
|
||||||
|
signal(SIGTRAP, handle_error);
|
||||||
|
#endif
|
||||||
|
|
||||||
// This makes sure output is not buffered for when
|
// This makes sure output is not buffered for when
|
||||||
// we hit errors.
|
// we hit errors.
|
||||||
|
|
Загрузка…
Ссылка в новой задаче