Checked C macro test cases.
The Checked C compiler now supports an alternate syntax and macros for backward compatibility. The technical details of the syntax and macros are documented at https://github.com/secure-sw-dev/checkedc/wiki/Proposed-extension-changes-to-improve-backward-compatibility. This change modifies some of the tests in existing files to use the new syntax. It only modifies a small fraction of the tests because of the syntactic nature of the changes. This avoids duplicating test files, making it easier to modify tests later.
This commit is contained in:
Родитель
24a60e59df
Коммит
44b52ca721
|
@ -13,5 +13,8 @@
|
|||
#define dynamic_bounds_cast _Dynamic_bounds_cast
|
||||
#define assume_bounds_cast _Assume_bounds_cast
|
||||
#define return_value _Return_value
|
||||
|
||||
#define _Dynamic_bounds_cast_M(T, e1, ... ) _Dynamic_bounds_cast<T>(e1, __VA_ARGS__)
|
||||
#define _Dynamic_bounds_cast_M_N(T, e1 ) _Dynamic_bounds_cast<T>(e1)
|
||||
#define _Assume_bounds_cast_M(T, e1, ... ) _Assume_bounds_cast<T>(e1, __VA_ARGS__)
|
||||
#define _Assume_bounds_cast_M_N(T, e1 ) _Assume_bounds_cast<T>(e1)
|
||||
#endif /* __STDCHECKED_H */
|
||||
|
|
|
@ -16,9 +16,9 @@
|
|||
// A function with an interface similar to snprintf but without the variable
|
||||
// number of arguments. The purpose is to test such a call interface in checked
|
||||
// scope.
|
||||
void iface(char * restrict s : itype(restrict _Nt_array_ptr<char>) count(n-1),
|
||||
size_t n _Where n > 0,
|
||||
const char * restrict src : itype(restrict _Nt_array_ptr<const char>)) {
|
||||
void iface(char * restrict s _Itype( char* _Nt_array restrict) count(n-1),
|
||||
size_t n _Where( n > 0),
|
||||
const char * restrict src _Itype( const char* _Nt_array restrict)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -36,7 +36,7 @@ void iface_array_ptr(char * restrict s : itype(restrict _Array_ptr<char>) count(
|
|||
|
||||
|
||||
|
||||
void iface_test1(_Array_ptr<char> p : count(len), size_t len) {
|
||||
void iface_test1(char* _Array p _Count(len), size_t len) {
|
||||
|
||||
char buf _Checked[50];
|
||||
iface_array_ptr(buf, 50, "Hello world");
|
||||
|
@ -53,7 +53,7 @@ void iface_test2(_Nt_array_ptr<char> p : count(len), size_t len) {
|
|||
iface(p, len + 1, "Hello world");
|
||||
}
|
||||
|
||||
void test3(_Array_ptr<char> buf : count(len), size_t len) {
|
||||
void test3(char* _Array buf _Count(len), size_t len) {
|
||||
_Unchecked{ snprintf_array_ptr(buf, len, "Hello world - 3"); }
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ void failing_test_2(void);
|
|||
void failing_test_3(void);
|
||||
void failing_test_4(int k);
|
||||
void failing_test_5(array_ptr<char> pc : count(len), unsigned len);
|
||||
void failing_test_6(array_ptr<char> pc : count(len), unsigned len);
|
||||
void failing_test_6(char* _Array pc _Count(len), unsigned len);
|
||||
void failing_test_7(array_ptr<char> pc : count(len), unsigned len);
|
||||
void failing_test_8(unsigned len);
|
||||
|
||||
|
@ -41,7 +41,7 @@ void handle_error(int err) {
|
|||
|
||||
// This signature for main is exactly what we want here,
|
||||
// it also means any uses of argv[i] are checked too!
|
||||
int main(int argc, array_ptr<char*> 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
|
||||
// clang implementation raises a SIGILL when a bounds check fails. This
|
||||
|
@ -115,7 +115,7 @@ int main(int argc, array_ptr<char*> argv : count(argc)) {
|
|||
// CHECK-FAIL-4-NOT: Unexpected Success
|
||||
failing_test_4(5);
|
||||
} else if (strcmp(argv[1], "fail5") == 0) {
|
||||
array_ptr<char> p : count(12) = "\0\0\0\0\0\0\0\0abcd";
|
||||
char* _Array p _Count(12) = "\0\0\0\0\0\0\0\0abcd";
|
||||
// CHECK-FAIL-5: Successful pointer conversion
|
||||
// CHECK-FAIL-5-NOT: Unexpected Success
|
||||
_Static_assert(sizeof(int) <= 8, "update test for integers larger than 64 bits.");
|
||||
|
@ -128,7 +128,7 @@ int main(int argc, array_ptr<char*> argv : count(argc)) {
|
|||
failing_test_6(p, 1);
|
||||
failing_test_6(p, 0);
|
||||
} else if (strcmp(argv[1], "fail7") == 0) {
|
||||
array_ptr<char> p : count(4) = "abcd";
|
||||
char* _Array p _Count(4) = "abcd";
|
||||
// CHECK-FAIL-7: Successful conversion to void *
|
||||
// CHECK-FAIL-7-NOT: Unexpected Success
|
||||
failing_test_7(p, 1);
|
||||
|
@ -157,24 +157,24 @@ int main(int argc, array_ptr<char*> argv : count(argc)) {
|
|||
// dynamic_check((r+3) != NULL) && dynamic_check(r <= r && r+15 <= r+10) - > OK
|
||||
// dynamic_check("abcdef", count(2)) -> OK.
|
||||
void passing_test_1(void) {
|
||||
ptr<int> q = 0;
|
||||
int* _Single q = 0;
|
||||
int r checked[10] = {0,1,2,3,4,5,6,7,8,9};
|
||||
array_ptr<int> s : count(5) = r;
|
||||
int* _Array s _Count(5) = r;
|
||||
|
||||
q = _Dynamic_bounds_cast<ptr<int>>(r);
|
||||
printf("Printable0\n");
|
||||
|
||||
q = _Dynamic_bounds_cast<array_ptr<int>>(r, count(3));
|
||||
q = _Dynamic_bounds_cast_M(int* _Array, r, _Count(3));
|
||||
printf("Printable1\n");
|
||||
|
||||
q = _Dynamic_bounds_cast<array_ptr<int>>(r+3, count(3));
|
||||
printf("Printable2\n");
|
||||
|
||||
q = _Dynamic_bounds_cast<array_ptr<int>>(r, bounds(s, s+3));
|
||||
q = _Dynamic_bounds_cast_M(int* _Array, r, _Bounds(s, s+3));
|
||||
printf("Printable3\n");
|
||||
|
||||
nt_array_ptr<const char> p : count(2) =
|
||||
_Dynamic_bounds_cast<nt_array_ptr<const char>>("abcdef", count(2));
|
||||
const char* _Nt_array p _Count(2) =
|
||||
_Dynamic_bounds_cast<nt_array_ptr<const char>>("abcdef", _Count(2));
|
||||
printf("Printable4\n");
|
||||
|
||||
puts("Expected Success");
|
||||
|
@ -191,14 +191,14 @@ void passing_test_2(void) {
|
|||
q = _Dynamic_bounds_cast<ptr<int>>(NULL);
|
||||
printf("Printable0\n");
|
||||
|
||||
q = _Dynamic_bounds_cast<array_ptr<int>>(NULL, bounds(r, r+5));
|
||||
q = _Dynamic_bounds_cast_M(int*_Array, NULL, _Bounds(r, r+5));
|
||||
printf("Printable1\n");
|
||||
|
||||
s = NULL;
|
||||
q = _Dynamic_bounds_cast<ptr<int>>(s);
|
||||
printf("Printable2\n");
|
||||
|
||||
q = _Dynamic_bounds_cast<array_ptr<int>>(s, bounds(r, r+5));
|
||||
q = _Dynamic_bounds_cast_M(int* _Array, s, _Bounds(r, r+5));
|
||||
printf("Printable3\n");
|
||||
|
||||
puts("Expected Success");
|
||||
|
@ -210,7 +210,7 @@ void passing_test_3(void) {
|
|||
ptr<int> pi = &i;
|
||||
ptr<void> pv = pi;
|
||||
void *unchecked_pv = 0;
|
||||
ptr<void> p1 = _Dynamic_bounds_cast<ptr<void>>(pi);
|
||||
void* _Single p1 = _Dynamic_bounds_cast_M_N(void* _Single, pi);
|
||||
printf("Passed p1");
|
||||
ptr<void> p2 = _Dynamic_bounds_cast<ptr<void>>(pv);
|
||||
printf("Passed p2");
|
||||
|
@ -218,7 +218,7 @@ void passing_test_3(void) {
|
|||
printf("Passed unchecked_pv");
|
||||
ptr<void> p3 = _Assume_bounds_cast<ptr<void>>(unchecked_pv);
|
||||
printf("Passed p3");
|
||||
void *p4 = _Assume_bounds_cast<void *>(unchecked_pv);
|
||||
void *p4 = _Assume_bounds_cast_M_N(void *, unchecked_pv);
|
||||
printf("Passed p4");
|
||||
puts("Expected Success");
|
||||
}
|
||||
|
@ -227,7 +227,7 @@ void passing_test_3(void) {
|
|||
void failing_test_1(void) {
|
||||
ptr<int> q = 0;
|
||||
int r checked[10] = {0,1,2,3,4,5,6,7,8,9};
|
||||
q = _Dynamic_bounds_cast<array_ptr<int>>(r, count(15));
|
||||
q = _Dynamic_bounds_cast_M(int* _Array, r, _Count(15));
|
||||
|
||||
printf("Unprintable\n");
|
||||
|
||||
|
@ -238,7 +238,7 @@ void failing_test_1(void) {
|
|||
void failing_test_2(void) {
|
||||
ptr<int> q = 0;
|
||||
int r checked[10] = {0,1,2,3,4,5,6,7,8,9};
|
||||
q = _Dynamic_bounds_cast<array_ptr<int>>(r+8, count(3));
|
||||
q = _Dynamic_bounds_cast_M(int* _Array, r+8, _Count(3));
|
||||
|
||||
printf("Unprintable\n");
|
||||
|
||||
|
@ -251,13 +251,13 @@ void failing_test_3(void) {
|
|||
int r checked[10] = {0,1,2,3,4,5,6,7,8,9};
|
||||
array_ptr<int> s : count(5) = r;
|
||||
|
||||
q = _Dynamic_bounds_cast<ptr<int>>(r);
|
||||
q = _Dynamic_bounds_cast_M_N(int* _Single, r);
|
||||
printf("Printable0\n");
|
||||
|
||||
q = _Dynamic_bounds_cast<array_ptr<int>>(r, count(5));
|
||||
printf("Printable1\n");
|
||||
|
||||
q = _Dynamic_bounds_cast<array_ptr<int>>(r, bounds(s, s+3));
|
||||
q = _Dynamic_bounds_cast_M(int* _Array, r, _Bounds(s, s+3));
|
||||
printf("Printable2\n");
|
||||
|
||||
s = 0;
|
||||
|
@ -273,7 +273,7 @@ void failing_test_3(void) {
|
|||
// k = 5
|
||||
void failing_test_4(int k) {
|
||||
int r checked[10] = {0,1,2,3,4,5,6,7,8,9};
|
||||
array_ptr<int> s : count(3) = _Dynamic_bounds_cast<array_ptr<int>>(r, count(5));
|
||||
int* _Array s _Count(3) = _Dynamic_bounds_cast_M(array_ptr<int>, r, _Count(5));
|
||||
|
||||
printf("Printable1\n");
|
||||
printf("Unprintable2: %d\n", *(s+k));
|
||||
|
@ -283,7 +283,7 @@ void failing_test_4(int k) {
|
|||
|
||||
// TEst dynamic checks involving possibly failig conversions to ptr<int>.
|
||||
void failing_test_5(array_ptr<char> pc : count(len), unsigned len) {
|
||||
ptr<int> pi = _Dynamic_bounds_cast<ptr<int>>(pc);
|
||||
int* _Single pi = _Dynamic_bounds_cast_M_N(int* _Single, pc);
|
||||
if (len < sizeof(int))
|
||||
puts("Unexpected Success");
|
||||
else if (*pi == 0)
|
||||
|
@ -311,8 +311,8 @@ void failing_test_7(array_ptr<char> pc : count(len), unsigned len) {
|
|||
// Test dynamic checks involving possibly failing conversions from
|
||||
// string literals.
|
||||
void failing_test_8(unsigned len) {
|
||||
nt_array_ptr<const char> p : count(len) =
|
||||
_Dynamic_bounds_cast<nt_array_ptr<const char>>("123456", count(len));
|
||||
const char* _Nt_array p _Count(len) =
|
||||
_Dynamic_bounds_cast_M(const char *_Nt_array, "123456", _Count(len));
|
||||
if (len > 6)
|
||||
puts("Unexpected Success");
|
||||
else if ((len == 0 && p != 0) || *p == '1')
|
||||
|
|
|
@ -1,110 +1,110 @@
|
|||
// This test shows how existential types can be used in combination
|
||||
// with generic functions and structs to create type-safe callback library
|
||||
// and client code.
|
||||
//
|
||||
// RUN: %clang %s -o %t1 %checkedc_target_flags
|
||||
|
||||
// RUN: %checkedc_rununder %t1 -DARR | FileCheck %s --check-prefix TEST
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
// Library code
|
||||
|
||||
#define MAX_CB 100
|
||||
|
||||
typedef int event_id;
|
||||
|
||||
#define EVENT_START 0
|
||||
#define EVENT_PAUSE 1
|
||||
#define EVENT_STOP 2
|
||||
|
||||
struct cb_info _For_any(T) {
|
||||
T *data;
|
||||
void (*cb)(event_id id, T *data);
|
||||
};
|
||||
|
||||
struct map_entry {
|
||||
event_id id;
|
||||
_Exists(T, struct cb_info<T>) info;
|
||||
};
|
||||
|
||||
int num_entries = 0;
|
||||
struct map_entry cb_map[MAX_CB];
|
||||
|
||||
_For_any(T) void reg_cb(event_id id, struct cb_info<T> info) {
|
||||
_Exists(A, struct cb_info<A>) opaque_info = _Pack(info, _Exists(A, struct cb_info<A>), T);
|
||||
struct map_entry entry;
|
||||
entry.id = id;
|
||||
entry.info = opaque_info;
|
||||
cb_map[num_entries] = entry;
|
||||
num_entries += 1;
|
||||
}
|
||||
|
||||
void handle(event_id id) {
|
||||
for (int i = 0; i < num_entries; i++) {
|
||||
if (cb_map[i].id == id) {
|
||||
_Unpack (T) struct cb_info<T> cb_inf = cb_map[i].info;
|
||||
cb_inf.cb(id, cb_inf.data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// User code
|
||||
void cb_start(event_id id, char *task_name) {
|
||||
printf("cb_start: id = %d, task_name = %s\n", id, task_name);
|
||||
}
|
||||
|
||||
void cb_pause(event_id id, int *resume_in) {
|
||||
printf("cb_pause: id = %d, resume_in = %ds\n", id, *resume_in);
|
||||
}
|
||||
|
||||
struct continue_info {
|
||||
int follow_by;
|
||||
};
|
||||
|
||||
void cb_stop(event_id id, struct continue_info *info) {
|
||||
printf("cb_stop: id = %d, follow_by = %d\n", id, info->follow_by);
|
||||
}
|
||||
|
||||
void client_register() {
|
||||
struct cb_info<char> start_info = { "task1", &cb_start };
|
||||
struct cb_info<char> start_info2 = { "task2", &cb_start };
|
||||
|
||||
// Unfortunately, we need to malloc the client-passed arguments to the callback.
|
||||
// This is because type parameters can only appear as pointers inside generic structs.
|
||||
// Eventually, we relax this constraint.
|
||||
int *resume_in = (int *) malloc(sizeof(int));
|
||||
*resume_in = 42;
|
||||
struct cb_info<int> pause_info = { resume_in, &cb_pause };
|
||||
|
||||
struct continue_info *cont_info = (struct continue_info *) malloc(sizeof(struct continue_info));
|
||||
cont_info->follow_by = 100;
|
||||
struct cb_info<struct continue_info> stop_info = { cont_info, &cb_stop };
|
||||
|
||||
reg_cb<char>(EVENT_START, start_info);
|
||||
reg_cb<char>(EVENT_START, start_info2);
|
||||
reg_cb<int>(EVENT_PAUSE, pause_info);
|
||||
reg_cb<struct continue_info>(EVENT_STOP, stop_info);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
client_register();
|
||||
handle(EVENT_START);
|
||||
// TEST: cb_start: id = 0, task_name = task1
|
||||
// TEST: cb_start: id = 0, task_name = task2
|
||||
|
||||
handle(EVENT_PAUSE);
|
||||
// TEST: cb_pause: id = 1, resume_in = 42s
|
||||
|
||||
handle(EVENT_STOP);
|
||||
// TEST: cb_stop: id = 2, follow_by = 100
|
||||
|
||||
handle(EVENT_PAUSE);
|
||||
// TEST: cb_pause: id = 1, resume_in = 42s
|
||||
handle(EVENT_PAUSE);
|
||||
// TEST: cb_pause: id = 1, resume_in = 42s
|
||||
}
|
||||
|
||||
|
||||
// This test shows how existential types can be used in combination
|
||||
// with generic functions and structs to create type-safe callback library
|
||||
// and client code.
|
||||
//
|
||||
// RUN: %clang %s -o %t1 %checkedc_target_flags
|
||||
|
||||
// RUN: %checkedc_rununder %t1 -DARR | FileCheck %s --check-prefix TEST
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
// Library code
|
||||
|
||||
#define MAX_CB 100
|
||||
|
||||
typedef int event_id;
|
||||
|
||||
#define EVENT_START 0
|
||||
#define EVENT_PAUSE 1
|
||||
#define EVENT_STOP 2
|
||||
|
||||
struct cb_info _For_any(T) {
|
||||
T *data;
|
||||
void (*cb)(event_id id, T *data);
|
||||
};
|
||||
|
||||
struct map_entry {
|
||||
event_id id;
|
||||
_Exists(T, struct cb_info<T>) info;
|
||||
};
|
||||
|
||||
int num_entries = 0;
|
||||
struct map_entry cb_map[MAX_CB];
|
||||
|
||||
_For_any(T) void reg_cb(event_id id, struct cb_info<T> info) {
|
||||
_Exists(A, struct cb_info<A>) opaque_info = _Pack(info, _Exists(A, struct cb_info<A>), T);
|
||||
struct map_entry entry;
|
||||
entry.id = id;
|
||||
entry.info = opaque_info;
|
||||
cb_map[num_entries] = entry;
|
||||
num_entries += 1;
|
||||
}
|
||||
|
||||
void handle(event_id id) {
|
||||
for (int i = 0; i < num_entries; i++) {
|
||||
if (cb_map[i].id == id) {
|
||||
_Unpack (T) struct cb_info<T> cb_inf = cb_map[i].info;
|
||||
cb_inf.cb(id, cb_inf.data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// User code
|
||||
void cb_start(event_id id, char *task_name) {
|
||||
printf("cb_start: id = %d, task_name = %s\n", id, task_name);
|
||||
}
|
||||
|
||||
void cb_pause(event_id id, int *resume_in) {
|
||||
printf("cb_pause: id = %d, resume_in = %ds\n", id, *resume_in);
|
||||
}
|
||||
|
||||
struct continue_info {
|
||||
int follow_by;
|
||||
};
|
||||
|
||||
void cb_stop(event_id id, struct continue_info *info) {
|
||||
printf("cb_stop: id = %d, follow_by = %d\n", id, info->follow_by);
|
||||
}
|
||||
|
||||
void client_register() {
|
||||
struct cb_info<char> start_info = { "task1", &cb_start };
|
||||
struct cb_info<char> start_info2 = { "task2", &cb_start };
|
||||
|
||||
// Unfortunately, we need to malloc the client-passed arguments to the callback.
|
||||
// This is because type parameters can only appear as pointers inside generic structs.
|
||||
// Eventually, we relax this constraint.
|
||||
int *resume_in = (int *) malloc(sizeof(int));
|
||||
*resume_in = 42;
|
||||
struct cb_info<int> pause_info = { resume_in, &cb_pause };
|
||||
|
||||
struct continue_info *cont_info = (struct continue_info *) malloc(sizeof(struct continue_info));
|
||||
cont_info->follow_by = 100;
|
||||
struct cb_info<struct continue_info> stop_info = { cont_info, &cb_stop };
|
||||
|
||||
reg_cb<char>(EVENT_START, start_info);
|
||||
reg_cb<char>(EVENT_START, start_info2);
|
||||
reg_cb<int>(EVENT_PAUSE, pause_info);
|
||||
reg_cb<struct continue_info>(EVENT_STOP, stop_info);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
client_register();
|
||||
handle(EVENT_START);
|
||||
// TEST: cb_start: id = 0, task_name = task1
|
||||
// TEST: cb_start: id = 0, task_name = task2
|
||||
|
||||
handle(EVENT_PAUSE);
|
||||
// TEST: cb_pause: id = 1, resume_in = 42s
|
||||
|
||||
handle(EVENT_STOP);
|
||||
// TEST: cb_stop: id = 2, follow_by = 100
|
||||
|
||||
handle(EVENT_PAUSE);
|
||||
// TEST: cb_pause: id = 1, resume_in = 42s
|
||||
handle(EVENT_PAUSE);
|
||||
// TEST: cb_pause: id = 1, resume_in = 42s
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,107 +1,107 @@
|
|||
// Run-time test for existential types
|
||||
// There are no expected failures in the execution of this test.
|
||||
// We're just checking that using _Pack, _Unpack and existentials
|
||||
// works as inteded.
|
||||
// The test itself implement a simple counter interface in two different ways:
|
||||
// with a regular counter and a mod 2 counter.
|
||||
// We run the two counters in a loop, and then check that the output matches
|
||||
// what we expect.
|
||||
//
|
||||
// RUN: %clang %s -o %t1 %checkedc_target_flags
|
||||
|
||||
// RUN: %checkedc_rununder %t1 -DARR | FileCheck %s --check-prefix TEST
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
struct Counter _For_any(T) {
|
||||
T *state;
|
||||
void (*inc)(T *st);
|
||||
void (*dec)(T *st);
|
||||
int (*getVal)();
|
||||
};
|
||||
|
||||
// Regular counter
|
||||
|
||||
void incIntCounter(int *x) {
|
||||
*x = (*x) + 1;
|
||||
}
|
||||
|
||||
void decIntCounter(int *x) {
|
||||
*x = (*x) - 1;
|
||||
}
|
||||
|
||||
int getValIntCounter(int *x) {
|
||||
return *x;
|
||||
}
|
||||
|
||||
_Exists(T, struct Counter<T>) getCounter() {
|
||||
struct Counter<int> ct;
|
||||
int *x = malloc(sizeof(int));
|
||||
*x = 0;
|
||||
ct.state = x;
|
||||
ct.inc = incIntCounter;
|
||||
ct.dec = decIntCounter;
|
||||
ct.getVal = getValIntCounter;
|
||||
return _Pack(ct, _Exists(T, struct Counter<T>), int);
|
||||
}
|
||||
|
||||
// Mod2 counter
|
||||
|
||||
void toggleMod2Counter(char *x) {
|
||||
*x = !(*x);
|
||||
}
|
||||
|
||||
int getValMod2Counter(char *x) {
|
||||
return *x;
|
||||
}
|
||||
|
||||
_Exists(T, struct Counter<T>) getMod2Counter() {
|
||||
struct Counter<char> ct;
|
||||
char *x = malloc(sizeof(char));
|
||||
*x = 0;
|
||||
ct.state = x;
|
||||
ct.inc = toggleMod2Counter;
|
||||
ct.dec = toggleMod2Counter;
|
||||
ct.getVal = getValMod2Counter;
|
||||
return _Pack(ct, _Exists(T, struct Counter<T>), char);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
_Exists(T, struct Counter<T>) counters[2];
|
||||
counters[0] = getCounter();
|
||||
counters[1] = getMod2Counter();
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
_Unpack (U) struct Counter<U> unpackCt = counters[i];
|
||||
for (int j = 0; j < 10; j++) {
|
||||
printf("counter = %d\n", unpackCt.getVal(unpackCt.state));
|
||||
unpackCt.inc(unpackCt.state);
|
||||
}
|
||||
printf("---\n");
|
||||
}
|
||||
|
||||
// TEST: counter = 0
|
||||
// TEST: counter = 1
|
||||
// TEST: counter = 2
|
||||
// TEST: counter = 3
|
||||
// TEST: counter = 4
|
||||
// TEST: counter = 5
|
||||
// TEST: counter = 6
|
||||
// TEST: counter = 7
|
||||
// TEST: counter = 8
|
||||
// TEST: counter = 9
|
||||
// TEST: ---
|
||||
// TEST: counter = 0
|
||||
// TEST: counter = 1
|
||||
// TEST: counter = 0
|
||||
// TEST: counter = 1
|
||||
// TEST: counter = 0
|
||||
// TEST: counter = 1
|
||||
// TEST: counter = 0
|
||||
// TEST: counter = 1
|
||||
// TEST: counter = 0
|
||||
// TEST: counter = 1
|
||||
|
||||
return 0;
|
||||
}
|
||||
// Run-time test for existential types
|
||||
// There are no expected failures in the execution of this test.
|
||||
// We're just checking that using _Pack, _Unpack and existentials
|
||||
// works as inteded.
|
||||
// The test itself implement a simple counter interface in two different ways:
|
||||
// with a regular counter and a mod 2 counter.
|
||||
// We run the two counters in a loop, and then check that the output matches
|
||||
// what we expect.
|
||||
//
|
||||
// RUN: %clang %s -o %t1 %checkedc_target_flags
|
||||
|
||||
// RUN: %checkedc_rununder %t1 -DARR | FileCheck %s --check-prefix TEST
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
struct Counter _For_any(T) {
|
||||
T *state;
|
||||
void (*inc)(T *st);
|
||||
void (*dec)(T *st);
|
||||
int (*getVal)();
|
||||
};
|
||||
|
||||
// Regular counter
|
||||
|
||||
void incIntCounter(int *x) {
|
||||
*x = (*x) + 1;
|
||||
}
|
||||
|
||||
void decIntCounter(int *x) {
|
||||
*x = (*x) - 1;
|
||||
}
|
||||
|
||||
int getValIntCounter(int *x) {
|
||||
return *x;
|
||||
}
|
||||
|
||||
_Exists(T, struct Counter<T>) getCounter() {
|
||||
struct Counter<int> ct;
|
||||
int *x = malloc(sizeof(int));
|
||||
*x = 0;
|
||||
ct.state = x;
|
||||
ct.inc = incIntCounter;
|
||||
ct.dec = decIntCounter;
|
||||
ct.getVal = getValIntCounter;
|
||||
return _Pack(ct, _Exists(T, struct Counter<T>), int);
|
||||
}
|
||||
|
||||
// Mod2 counter
|
||||
|
||||
void toggleMod2Counter(char *x) {
|
||||
*x = !(*x);
|
||||
}
|
||||
|
||||
int getValMod2Counter(char *x) {
|
||||
return *x;
|
||||
}
|
||||
|
||||
_Exists(T, struct Counter<T>) getMod2Counter() {
|
||||
struct Counter<char> ct;
|
||||
char *x = malloc(sizeof(char));
|
||||
*x = 0;
|
||||
ct.state = x;
|
||||
ct.inc = toggleMod2Counter;
|
||||
ct.dec = toggleMod2Counter;
|
||||
ct.getVal = getValMod2Counter;
|
||||
return _Pack(ct, _Exists(T, struct Counter<T>), char);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
_Exists(T, struct Counter<T>) counters[2];
|
||||
counters[0] = getCounter();
|
||||
counters[1] = getMod2Counter();
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
_Unpack (U) struct Counter<U> unpackCt = counters[i];
|
||||
for (int j = 0; j < 10; j++) {
|
||||
printf("counter = %d\n", unpackCt.getVal(unpackCt.state));
|
||||
unpackCt.inc(unpackCt.state);
|
||||
}
|
||||
printf("---\n");
|
||||
}
|
||||
|
||||
// TEST: counter = 0
|
||||
// TEST: counter = 1
|
||||
// TEST: counter = 2
|
||||
// TEST: counter = 3
|
||||
// TEST: counter = 4
|
||||
// TEST: counter = 5
|
||||
// TEST: counter = 6
|
||||
// TEST: counter = 7
|
||||
// TEST: counter = 8
|
||||
// TEST: counter = 9
|
||||
// TEST: ---
|
||||
// TEST: counter = 0
|
||||
// TEST: counter = 1
|
||||
// TEST: counter = 0
|
||||
// TEST: counter = 1
|
||||
// TEST: counter = 0
|
||||
// TEST: counter = 1
|
||||
// TEST: counter = 0
|
||||
// TEST: counter = 1
|
||||
// TEST: counter = 0
|
||||
// TEST: counter = 1
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -141,9 +141,9 @@ extern int Multiply(struct Vector vec1, struct Vector vec2) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
extern int Multiply2(ptr<struct Vector> vec1p, ptr<struct Vector> vec2p) {
|
||||
extern int Multiply2(struct Vector *_Single vec1p, struct Vector *_Single vec2p) {
|
||||
if (vec1p->len != vec2p->len) {
|
||||
return 1;
|
||||
return 1;
|
||||
}
|
||||
for (int i = 0; i < vec1p->len; i++) {
|
||||
vec1p->data[i] *= vec2p->data[i];
|
||||
|
@ -151,6 +151,7 @@ extern int Multiply2(ptr<struct Vector> vec1p, ptr<struct Vector> vec2p) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Declaring checked arrays of function pointers
|
||||
//
|
||||
|
@ -167,6 +168,10 @@ ptr<int(int x, int y)> array_of_ptr_to_func checked[10];
|
|||
extern ptr<int(int x, int y)> array_of_ptr_to_func checked[];
|
||||
ptr<int(int x checked[10], int y)> aptr2 checked[10];
|
||||
ptr<int(int x nt_checked[10], int y)> aptr3 nt_checked[10];
|
||||
int (*_Single m_array_of_ptr_to_func checked[10])(int x, int y);
|
||||
extern int (*_Single m_array_of_ptr_to_func checked[]) (int x, int y) ;
|
||||
int (*_Single m_aptr2 checked[10])(int x checked[10], int y) ;
|
||||
int (*_Single m_aptr3 nt_checked[10])(int x nt_checked[10], int y);
|
||||
|
||||
//
|
||||
// Declaring pointers to arrays and arrays of pointers
|
||||
|
@ -176,12 +181,19 @@ ptr<int checked[5]> ptr_to_array;
|
|||
ptr<int nt_checked[5]> ptr_to_nullterm_array;
|
||||
array_ptr<int checked[5]> array_ptr_to_array;
|
||||
array_ptr<int nt_checked[5]> array_ptr_to_nullterm_array;
|
||||
int (*_Single m_ptr_to_array) checked[5] ;
|
||||
int (*_Single m_ptr_to_nullterm_array) nt_checked[5] ;
|
||||
int (*_Array m_array_ptr_to_array) checked[5] ;
|
||||
int (*_Array m_array_ptr_to_nullterm_array) nt_checked[5] ;
|
||||
|
||||
|
||||
int(*unchecked_ptr_to_incomplete_array)checked[];
|
||||
ptr<int checked[]> ptr_to_incomplete_array;
|
||||
ptr<int nt_checked[]> ptr_to_nullterm_incomplete_array;
|
||||
array_ptr<int checked[]> array_ptr_to_incomplete_array;
|
||||
array_ptr<int nt_checked[]> array_ptr_to_nullterm_incomplete_array;
|
||||
int (*_Array m_array_ptr_to_incomplete_array) checked[] ;
|
||||
int (*_Array m_array_ptr_to_nullterm_incomplete_array) nt_checked[] ;
|
||||
|
||||
// Declaring checked arrays of pointers
|
||||
int *array_of_unchecked_ptrs checked[5];
|
||||
|
@ -192,12 +204,18 @@ array_ptr<int> array_of_array_ptrs checked[5];
|
|||
array_ptr<int> nullterm_array_of_array_ptrs nt_checked[5];
|
||||
nt_array_ptr<int> array_of_nullterm_array_ptrs checked[5];
|
||||
nt_array_ptr<int> nullterm_array_of_nullterm_array_ptrs nt_checked[5];
|
||||
int *_Array m_nullterm_array_of_array_ptrs nt_checked[5];
|
||||
int *_Nt_array m_array_of_nullterm_array_ptrs checked[5];
|
||||
int *_Nt_array m_nullterm_array_of_nullterm_array_ptrs nt_checked[5];
|
||||
|
||||
|
||||
// Declare an unchecked pointer to checked arrays of pointers
|
||||
int *(*uncheckedptr_to_array_of_unchecked_ptrs) checked[5];
|
||||
ptr<int>(*unchecked_ptr_to_array_of_ptrs) checked[5];
|
||||
array_ptr<int>(*unchecked_ptr_to_array_of_array_ptrs) checked[5];
|
||||
array_ptr<int>(*unchecked_ptr_to_null_term_array_of_array_ptrs) nt_checked[5];
|
||||
int *_Array (*m_unchecked_ptr_to_array_of_array_ptrs) checked[5];
|
||||
int *_Array (*m_unchecked_ptr_to_null_term_array_of_array_ptrs) nt_checked[5];
|
||||
|
||||
// Declare ptr to checked arrays of pointers
|
||||
ptr<int *checked[5]> ptr_to_array_of_unchecked_ptrs;
|
||||
|
@ -205,6 +223,8 @@ ptr<ptr<int> checked[5]> ptr_to_array_of_ptrs;
|
|||
ptr<array_ptr<int> checked[5]> ptr_to_array_of_array_ptrs;
|
||||
ptr<array_ptr<int> nt_checked[5]> ptr_to_nullterm_array_of_array_ptrs;
|
||||
ptr<nt_array_ptr<int> nt_checked[5]> ptr_to_nullterm_array_of_nullterm_array_ptrs;
|
||||
int (*_Array *_Single m_ptr_to_nullterm_array_of_array_ptrs) nt_checked[5];
|
||||
int *_Nt_array (*_Single m_ptr_to_nullterm_array_of_nullterm_array_ptrs) nt_checked[5];
|
||||
|
||||
// Declare ptr to a checked array of function pointers
|
||||
ptr<int (*checked[5])(int x, int y)> ptr_to_array_of_unchecked_func_ptrs;
|
||||
|
@ -215,6 +235,10 @@ ptr<ptr<ptr<int>(ptr<int> x, ptr<int> y)>checked[5]>
|
|||
ptr_to_array_of_checked_func_ptrs_with_ptr_parameters;
|
||||
ptr<ptr<ptr<int> (ptr<int> x, ptr<int> y)>nt_checked[5]>
|
||||
ptr_to_nullterm_array_of_checked_func_ptrs_with_ptr_parameters;
|
||||
int (*_Single *_Single *_Single
|
||||
m_ptr_to_array_of_checked_func_ptrs_with_ptr_parameters checked[5])(int *_Single x, int *_Single y);
|
||||
int (*_Single *_Single *_Single
|
||||
m_ptr_to_nullterm_array_of_checked_func_ptrs_with_ptr_parameters nt_checked[5])(int* _Single x, int* _Single y);
|
||||
|
||||
|
||||
//
|
||||
|
@ -236,37 +260,37 @@ void parse_operators_with_types(void) {
|
|||
int s1 = sizeof(int checked[10]);
|
||||
int s2 = sizeof(ptr<int checked[5]>);
|
||||
int s3 = sizeof(array_ptr<int checked[5]>);
|
||||
int s4 = sizeof(ptr<int>checked[5]);
|
||||
int s5 = sizeof(array_ptr<int> checked[5]);
|
||||
int s4 = sizeof(int (*_Single)checked[5]);
|
||||
int s5 = sizeof(int (*_Single)checked[5]);
|
||||
|
||||
// null-terminated versions.
|
||||
int s6 = sizeof(int nt_checked[10]);
|
||||
int s7 = sizeof(ptr<int nt_checked[5]>);
|
||||
int s8 = sizeof(array_ptr<int nt_checked[5]>);
|
||||
int s9 = sizeof(ptr<int> nt_checked[5]);
|
||||
int s10 = sizeof(array_ptr<int> nt_checked[5]);
|
||||
int s9 = sizeof(int (*_Single) nt_checked[5]);
|
||||
int s10 = sizeof(int (*_Array) nt_checked[5]);
|
||||
|
||||
int s20 = _Alignof(int checked[10]);
|
||||
int s21 = _Alignof(ptr<int checked[5]>);
|
||||
int s22 = _Alignof(array_ptr<int checked[5]>);
|
||||
int s23 = _Alignof(ptr<int> checked[5]);
|
||||
int s24 = _Alignof(array_ptr<int>checked[5]);
|
||||
int s25 = _Alignof(nt_array_ptr<int>checked[5]);
|
||||
int s24 = _Alignof(int (*_Array)checked[5]);
|
||||
int s25 = _Alignof(int *_Nt_array checked[5]);
|
||||
|
||||
// null-terminated versions.
|
||||
int s26 = _Alignof(int nt_checked[10]);
|
||||
int s27 = _Alignof(ptr<int nt_checked[5]>);
|
||||
int s28 = _Alignof(array_ptr<int nt_checked[5]>);
|
||||
int s29 = _Alignof(ptr<int> nt_checked[5]);
|
||||
int s30 = _Alignof(array_ptr<int> nt_checked[5]);
|
||||
int s31 = _Alignof(nt_array_ptr<int> nt_checked[5]);
|
||||
int s30 = _Alignof(int *_Array nt_checked[5]);
|
||||
int s31 = _Alignof(int *_Nt_array nt_checked[5]);
|
||||
|
||||
// Test parsing of some cast operations that should pass checking
|
||||
// of bounds declarations
|
||||
int x = 0;
|
||||
int arr checked[5];
|
||||
ptr<int> px = (ptr<int>) &x;
|
||||
array_ptr<int> pax = (array_ptr<int>) &x;
|
||||
int* _Array pax = (int* _Array) &x;
|
||||
pax = arr;
|
||||
// ptr to array type
|
||||
ptr<int checked[5]> parr = 0;
|
||||
|
|
|
@ -8,25 +8,25 @@
|
|||
|
||||
// Top level declarations with different storage classes and
|
||||
// storage classes omitted.
|
||||
extern array_ptr<int> a : count(5);
|
||||
extern array_ptr<int> b : count(3 + 2);
|
||||
extern int* _Array a : count(5);
|
||||
extern int* _Array b _Count(3 + 2);
|
||||
extern int cLen;
|
||||
extern array_ptr<int> c : count(cLen);
|
||||
extern array_ptr<int> d : byte_count(20);
|
||||
extern int* _Array c : count(cLen);
|
||||
extern int* _Array d _Byte_count(20);
|
||||
extern array_ptr<int> e : byte_count(5 * sizeof(int));
|
||||
extern array_ptr<int> f : byte_count(cLen * sizeof(int));
|
||||
extern array_ptr<int> g : bounds(unknown);
|
||||
extern array_ptr<int> h : bounds(f - 2, f + 3);
|
||||
extern array_ptr<int> i : count(5), j : bounds(i - 2, i + 3),
|
||||
k : bounds(j + 2, j + 5);
|
||||
extern int* _Array i : count(5),* _Array j _Bounds(i - 2, i + 3),
|
||||
* _Array k _Bounds(j + 2, j + 5);
|
||||
|
||||
static float vals[5] = { 0.0, 1.0, 2.0, 3.0, 4.0 };
|
||||
static array_ptr<float> l : count(5) = vals;
|
||||
static _Thread_local array_ptr<int> m : count(5);
|
||||
|
||||
array_ptr<int> b : count(3 + 2) = 0;
|
||||
array_ptr<int> d : byte_count(20) = 0;
|
||||
array_ptr<int> g : bounds(unknown) = 0;
|
||||
int* _Array d : byte_count(20) = 0;
|
||||
int* _Array g _Bounds(unknown) = 0;
|
||||
|
||||
// Declare a bounds for a checked array. This is legal, but
|
||||
// unnecessary.
|
||||
|
@ -42,25 +42,26 @@ extern void f1(array_ptr<int> arr : count(5)) {
|
|||
array_ptr<int> s : byte_count(20) = arr;
|
||||
array_ptr<int> t : byte_count(5 * sizeof(int)) = arr;
|
||||
array_ptr<int> u : byte_count(len * sizeof(int)) = arr;
|
||||
array_ptr<int> v : bounds(v, v + 5) = arr;
|
||||
array_ptr<int> w : bounds(unknown) = arr;
|
||||
array_ptr<int> x : bounds(unknown);
|
||||
array_ptr<int> midarr : bounds(midarr - 1, midarr - 1 + 2) = arr + 2;
|
||||
int* _Array v _Bounds(v, v + 5) = arr;
|
||||
int* _Array w _Bounds(unknown) = arr;
|
||||
int* _Array x _Bounds(unknown);
|
||||
int* _Array midarr _Bounds(midarr - 1, midarr - 1 + 2) = arr + 2;
|
||||
|
||||
static array_ptr<int> cache1 : count(5);
|
||||
static array_ptr<int> cache1_ptr : bounds(cache1 - 2, cache1 + 3);
|
||||
}
|
||||
|
||||
// Multiple declarators in one declaration
|
||||
extern void f2(array_ptr<int> arr : count(5)) {
|
||||
array_ptr<int> p : count(5) = 0, q : count(3 + 2) = arr;
|
||||
extern void f2(int* _Array arr _Count(5)) {
|
||||
int* _Array p _Count(5) = 0, * _Array q _Count(3 + 2) = arr;
|
||||
int len = 5;
|
||||
array_ptr<int> r : count(len) = arr, s : byte_count(20) = arr;
|
||||
array_ptr<int> t : byte_count(5 * sizeof(int)) = arr,
|
||||
u : bounds(u, u + 5) = arr,
|
||||
v : bounds(unknown) = arr;
|
||||
int* _Array r _Count(len) = arr, * _Array s _Byte_count(20) = arr;
|
||||
int* _Array t : byte_count(5 * sizeof(int)) = arr,
|
||||
* _Array u _Bounds(u, u + 5) = arr,
|
||||
* _Array v _Bounds(unknown) = arr;
|
||||
}
|
||||
|
||||
|
||||
// Parenthesized subexpressions
|
||||
extern void f3(array_ptr<int> arr : count(5)) {
|
||||
array_ptr<int> p : count((5)) = arr;
|
||||
|
@ -70,9 +71,9 @@ extern void f3(array_ptr<int> arr : count(5)) {
|
|||
array_ptr<int> s : byte_count((20)) = arr;
|
||||
array_ptr<int> t : byte_count(5 * (sizeof(int))) = arr;
|
||||
array_ptr<int> u : byte_count((len) * sizeof(int)) = arr;
|
||||
array_ptr<int> v : bounds(v, (v + 5) + len - len) = arr;
|
||||
array_ptr<int> w: bounds((w + len - (len)), (w + len)) = arr;
|
||||
array_ptr<int> midarr : bounds(midarr - 1, (midarr - 1) + 2) = arr + 2;
|
||||
int* _Array v _Bounds(v, (v + 5) + len - len) = arr;
|
||||
int* _Array w _Bounds((w + len - (len)), (w + len)) = arr;
|
||||
int* _Array midarr _Bounds(midarr - 1, (midarr - 1) + 2) = arr + 2;
|
||||
}
|
||||
|
||||
|
||||
|
@ -84,10 +85,10 @@ extern void f4(array_ptr<int> arr : count(len), int len) {
|
|||
// unknown is a contextual a keyword if it follows 'bounds' '('
|
||||
array_ptr<int> q : bounds(unknown) = arr;
|
||||
array_ptr<int> r : bounds(unknown + arr, arr + len) = arr; // expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
array_ptr<int> s : bounds(arr + unknown, arr + len) = arr;
|
||||
array_ptr<int> t : bounds(t, t + count) = arr;
|
||||
int* _Array s _Bounds(arr + unknown, arr + len) = arr;
|
||||
int* _Array t _Bounds(t, t + count) = arr;
|
||||
int bounds = len;
|
||||
array_ptr<int> u : bounds(u, u + bounds) = arr;
|
||||
int* _Array u _Bounds(u, u + bounds) = arr;
|
||||
}
|
||||
|
||||
// Checked array declarations
|
||||
|
@ -99,11 +100,11 @@ extern void f5(void) {
|
|||
int arr4 checked[5] : count(len);
|
||||
int arr7 checked[5] : byte_count(5 * sizeof(int));
|
||||
int arr8 checked[5] : byte_count(len * sizeof(int));
|
||||
auto int arr5 checked[5] : bounds(arr5, arr5 + 5);
|
||||
auto int arr6 checked[5] : bounds(arr5, arr5 + len);
|
||||
auto int arr5 checked[5] _Bounds(arr5, arr5 + 5);
|
||||
auto int arr6 checked[5] _Bounds(arr5, arr5 + len);
|
||||
|
||||
static int cache checked[5] : count(5);
|
||||
static array_ptr<int> cache_ptr : bounds(cache - 2, cache + 3);
|
||||
static int cache checked[5] _Count(5);
|
||||
static int* _Array cache_ptr _Bounds(cache - 2, cache + 3);
|
||||
}
|
||||
|
||||
// Parsing of more complicated declarations with bounds declarations
|
||||
|
@ -114,7 +115,7 @@ extern void f6(int *arr checked[] : count(5)) {
|
|||
int len = 5;
|
||||
array_ptr<int *> r : count(len) = arr;
|
||||
array_ptr<int *> s : byte_count(5 * sizeof(int)) = arr;
|
||||
array_ptr<int *> t : byte_count(len * sizeof(int)) = arr;
|
||||
array_ptr<int *> t _Byte_count(len * sizeof(int)) = arr;
|
||||
// redundant but legal bounds expressions on arrays.
|
||||
int *arr1 checked[5] : count(5);
|
||||
int *arr2 checked[5] : count(3 + 2);
|
||||
|
@ -122,29 +123,30 @@ extern void f6(int *arr checked[] : count(5)) {
|
|||
// Checked array of unchecked pointers to functions. We have to parenthesize
|
||||
// the inner declarator to avoid : count(len) being parsed as part of the
|
||||
// type of arr, not a bounds expression.
|
||||
int ((*arr4 checked[5])(int, int)) : count(5);
|
||||
int ((*arr5 checked[5])(int, int)) : count(len);
|
||||
int ((*arr6 checked[5])(int, int)) : bounds(arr5, arr5 + len);
|
||||
int ((*arr4 checked[5])(int, int)) _Count(5);
|
||||
int ((*arr5 checked[5])(int, int)) _Count(len);
|
||||
int ((*arr6 checked[5])(int, int)) _Bounds(arr5, arr5 + len);
|
||||
// Checked array of checked pointers to functions
|
||||
ptr<int(int, int)> arr7 checked[5] : count(5) = {0};
|
||||
ptr<int(int, int)> arr8 checked[5] : bounds(arr8, arr8 + 5) = {0};
|
||||
// Array_ptrs to checked pointers to functions.
|
||||
array_ptr<ptr<int (int, int)>> u : count(5) = 0;
|
||||
typedef int (*_Single func_u)(int, int);
|
||||
func_u* _Array u : count(5) = 0;
|
||||
array_ptr<ptr<int (int, int)>> v : bounds(v, v + 5) = 0;
|
||||
array_ptr<ptr<int (int, int)>> w : bounds(v, v + 5) = 0;
|
||||
array_ptr<ptr<int (int len, array_ptr<int> arr : count(len))>> x : bounds(x, x + 5) = 0;
|
||||
}
|
||||
|
||||
// Bounds expressions with incorrect syntax or semantics
|
||||
extern void f7(array_ptr<int> arr : count(5)) {
|
||||
array_ptr<int> p : bounds(start, end + 5) = 0; // expected-error {{undeclared identifier 'start'}} expected-error {{undeclared identifier 'end'}}
|
||||
array_ptr<int> q : count(len) = 0; // expected-error {{undeclared identifier 'len'}}
|
||||
array_ptr<int> r : byte_count(len) = 0; // expected-error {{undeclared identifier 'len'}}
|
||||
array_ptr<int> s : 6 + 6 = 0; // expected-error {{expected bounds expression}}
|
||||
array_ptr<int> t : 6 + 6, u : count(5) = arr; // expected-error {{expected bounds expression}}
|
||||
array_ptr<int> v : boounds(a, b + 5) = 0; // expected-error {{expected bounds expression}}
|
||||
array_ptr<int> w : coount(5) = 0; // expected-error {{expected bounds expression}}
|
||||
array_ptr<ptr<int (int len, array_ptr<int> arr : count(badvar))>> x // expected-error {{undeclared identifier 'badvar'}}
|
||||
: bounds(x, x + 5) = 0;
|
||||
extern void f7(int* _Array arr _Count(5)) {
|
||||
int* _Array p _Bounds(start, end + 5) = 0; // expected-error {{undeclared identifier 'start'}} expected-error {{undeclared identifier 'end'}}
|
||||
int* _Array q : count(len) = 0; // expected-error {{undeclared identifier 'len'}}
|
||||
int* _Array r : byte_count(len) = 0; // expected-error {{undeclared identifier 'len'}}
|
||||
int* _Array s : 6 + 6 = 0; // expected-error {{expected bounds expression}}
|
||||
int* _Array t : 6 + 6, * _Array u _Count(5) = arr; // expected-error {{expected bounds expression}}
|
||||
int* _Array v _Boounds(a, b + 5) = 0; // expected-error {{expected ';' at end of declaration}}
|
||||
int* _Array w _Coount(5) = 0; // expected-error {{expected ';' at end of declaration}}
|
||||
typedef int (*_Single func_xx)(int len, int* _Array _Count(badvar)); // expected-error {{undeclared identifier 'badvar'}}
|
||||
func_xx *_Array x
|
||||
_Bounds(x, x + 5) = 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -35,13 +35,13 @@ extern void f6(int **p : itype(array_ptr<ptr<int>>) byte_count(y), int y) {
|
|||
extern void f10(int **p : count(y) itype(ptr<int> checked[]), int y) {
|
||||
}
|
||||
|
||||
extern void f11(int **p : itype(ptr<int> checked[]) count(y), int y) {
|
||||
extern void f11(int **p _Itype(int* _Single checked[]) count(y), int y) {
|
||||
}
|
||||
|
||||
extern void f12(int **p : itype(ptr<int> checked[10]) count(10), int y) {
|
||||
extern void f12(int **p _Itype(int* _Single checked[10]) count(10), int y) {
|
||||
}
|
||||
|
||||
extern void f13(int **p : count(10) itype(ptr<int> checked[10]), int y) {
|
||||
extern void f13(int **p _Count(10) _Itype(int* _Single checked[10]), int y) {
|
||||
}
|
||||
|
||||
// Second parameter has interop type annotation
|
||||
|
@ -57,23 +57,23 @@ extern void g3(int y, int **p : bounds(p, p + y) itype(array_ptr<ptr<int>>)) {
|
|||
extern void g4(int y, int **p : itype(array_ptr<ptr<int>>) bounds(p, p + y)) {
|
||||
}
|
||||
|
||||
extern void g5(int y, int **p : byte_count(y) itype(array_ptr<ptr<int>>)) {
|
||||
extern void g5(int y, int **p _Byte_count(y) _Itype(int* _Single *_Array)) {
|
||||
}
|
||||
|
||||
extern void g6(int y, int **p : itype(array_ptr<ptr<int>>) byte_count(y)) {
|
||||
extern void g6(int y, int **p : itype(int* _Single *_Array) byte_count(y)) {
|
||||
}
|
||||
|
||||
|
||||
extern void g10(int y, int **p : count(y) itype(ptr<int> checked[])) {
|
||||
}
|
||||
|
||||
extern void g11(int y, int **p : itype(ptr<int> checked[]) count(y)) {
|
||||
extern void g11(int y, int **p _Itype(int* _Single checked[]) count(y)) {
|
||||
}
|
||||
|
||||
extern void g12(int y, int **p : itype(ptr<int> checked[10]) count(10)) {
|
||||
extern void g12(int y, int **p _Itype(int* _Single checked[10]) count(10)) {
|
||||
}
|
||||
|
||||
extern void g13(int y, int **p : count(10) itype(ptr<int> checked[10])) {
|
||||
extern void g13(int y, int **p _Count(10) itype(int* _Single checked[10])) {
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -86,12 +86,11 @@ extern int **h1(int y, ptr<int> p) : itype(array_ptr<ptr<int>>) byte_count(y) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
extern int **h2(int y, ptr<int> p) : count(y) itype(array_ptr<ptr<int>>) {
|
||||
extern int **h2(int y, int* _Single p) _Count(y) _Itype(int* _Single *_Array) {
|
||||
*p = y;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Global variables with interop type and bounds annotations
|
||||
//
|
||||
|
@ -99,8 +98,8 @@ extern int **h2(int y, ptr<int> p) : count(y) itype(array_ptr<ptr<int>>) {
|
|||
int size;
|
||||
int **a1 : itype(array_ptr<ptr<int>>) count(size) = 0;
|
||||
int **a2 : count(size) itype(array_ptr<array_ptr<int>>) = 0;
|
||||
int a3[10] : itype(int checked[10]) byte_count(10 * sizeof(int));
|
||||
extern int a4[] : count(size) itype(int checked[]);
|
||||
int a3[10] _Itype(int checked[10]) byte_count(10 * sizeof(int));
|
||||
extern int a4[] _Count(size) _Itype(int checked[]);
|
||||
|
||||
//
|
||||
// Structure members with interop pointer type annotations
|
||||
|
@ -113,8 +112,8 @@ struct S1 {
|
|||
float **data3 : bounds(data3, data3 + len) itype(array_ptr<ptr<float>>);
|
||||
float **data4 : itype(array_ptr<ptr<float>>) bounds(data3, data3 + len);
|
||||
float data5[4] : itype(float checked[4]) count(3);
|
||||
float data6[4] : count(3) itype(float checked[4]);
|
||||
float *data7[] : itype(ptr<float> checked[]) count(len);
|
||||
float data6[4] _Count(3) _Itype(float checked[4]);
|
||||
float *data7[] _Itype(ptr<float> checked[]) count(len);
|
||||
};
|
||||
|
||||
struct S2 {
|
||||
|
@ -133,7 +132,7 @@ typedef ptr<const int> pcint;
|
|||
extern void f40(int **x : itype(ppint) bounds(x, x + len), int len) {
|
||||
}
|
||||
|
||||
extern void f41(int **x : count(len) itype(ppint), int len) {
|
||||
extern void f41(int **x _Count(len) itype(ppint), int len) {
|
||||
}
|
||||
|
||||
/// Test some error condtions
|
||||
|
@ -142,6 +141,6 @@ extern void f50(int **x : itype(ppint) itype(ppint)); // expected-error {{only
|
|||
|
||||
extern void f51(int **x : count(5) count(6)); // expected-error {{only one bounds expression allowed}}
|
||||
|
||||
extern void f53(int ** x : itype(ppint) count(5) itype(ppint)); // expected-error {{only one itype expression allowed}}
|
||||
extern void f53(int ** x _Itype(ppint) count(5) _Itype(ppint)); // expected-error {{only one itype expression allowed}}
|
||||
|
||||
extern void f53(int ** x : count(5) itype(ppint) count(5)); // expected-error {{only one bounds expression allowed}}
|
||||
extern void f53(int ** x _Count(5) itype(ppint) count(5)); // expected-error {{only one bounds expression allowed}}
|
||||
|
|
|
@ -26,8 +26,8 @@ extern void f3(int *p : itype(int checked[]), int y) {
|
|||
extern void f4(int *p : itype(int checked[10]), int y) {
|
||||
}
|
||||
|
||||
extern void f5(int **p : itype(ptr<ptr<int>>), int y) {
|
||||
**p = y;
|
||||
extern void f5(int **p _Itype(int* _Single *_Single), int y) {
|
||||
**p = y;
|
||||
}
|
||||
|
||||
extern void f6(int **p : itype(array_ptr<ptr<int>>), int y) {
|
||||
|
@ -36,7 +36,7 @@ extern void f6(int **p : itype(array_ptr<ptr<int>>), int y) {
|
|||
extern void f7(int **p : itype(ptr<int> checked[]), int y) {
|
||||
}
|
||||
|
||||
extern void f8(int **p : itype(int * checked[10]), int y) {
|
||||
extern void f8(int **p _Itype(int * checked[10]), int y) {
|
||||
}
|
||||
|
||||
// Second parameter has interop type annotation
|
||||
|
@ -60,10 +60,10 @@ extern void g5(int y, int **p : itype(ptr<ptr<int>>)) {
|
|||
extern void g6(int y, int **p : itype(ptr<array_ptr<int>>)) {
|
||||
}
|
||||
|
||||
extern void g7(int y, int **p : itype(array_ptr<ptr<int>>)) {
|
||||
extern void g7(int y, int **p _Itype(int *_Single *_Array)) {
|
||||
}
|
||||
|
||||
extern void g8(int y, int **p : itype(ptr<int> checked[])) {
|
||||
extern void g8(int y, int **p _Itype(int* _Single checked[])) {
|
||||
}
|
||||
|
||||
extern void g9(int y, int **p : itype(int * checked[10])) {
|
||||
|
@ -86,7 +86,7 @@ extern int **h3(void) : itype(ptr<ptr<int>>) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
extern int **h4(void) : itype(array_ptr<ptr<int>>) {
|
||||
extern int **h4(void) _Itype(int *_Single *_Array) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -100,9 +100,9 @@ int **a3 : itype(ptr<ptr<int>>) = 0;
|
|||
int **a4 : itype(ptr<array_ptr<int>>) = 0;
|
||||
int **a5 : itype(array_ptr<ptr<int>>) = 0;
|
||||
int **a6 : itype(array_ptr<array_ptr<int>>) = 0;
|
||||
int ***a7 : itype(ptr<ptr<ptr<int>>>) = 0;
|
||||
int a8[10] : itype(int checked[10]);
|
||||
extern int a9[] : itype(int checked[]);
|
||||
int ***a7 _Itype(ptr<ptr<ptr<int>>>) = 0;
|
||||
int a8[10] _Itype(int checked[10]);
|
||||
extern int a9[] _Itype(int checked[]);
|
||||
//
|
||||
// Structure members with interop pointer type annotations
|
||||
//
|
||||
|
@ -114,8 +114,8 @@ struct S1 {
|
|||
float **data4 : itype(ptr<array_ptr<float>>);
|
||||
float **data5 : itype(array_ptr<ptr<float>>);
|
||||
float ***data6 : itype(ptr<ptr<ptr<float>>>);
|
||||
float data7[4] : itype(float checked[4]);
|
||||
float data8[] : itype(float checked[]);
|
||||
float data7[4] _Itype(float checked[4]);
|
||||
float data8[] _Itype(float checked[]);
|
||||
};
|
||||
|
||||
///
|
||||
|
@ -133,12 +133,12 @@ extern void f32(const int a[10] : itype(const int checked[10])) {
|
|||
extern void f33(const int *x : itype(ptr<const int>)) {
|
||||
}
|
||||
|
||||
extern const int *f34(void) : itype(ptr<const int>) {
|
||||
extern const int *f34(void) _Itype(const int * _Single ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const int *a10 : itype(ptr<const int>) = 0;
|
||||
int *const a11 : itype(const ptr<int>) = 0;
|
||||
const int *a10 _Itype(const int * _Single ) = 0;
|
||||
int *const a11 _Itype(int* const _Single) = 0;
|
||||
|
||||
// First dimension of an array interop type for a parameter can
|
||||
// have modifiers or the static keyword
|
||||
|
@ -152,7 +152,7 @@ extern void f36(int a[static const 10] : itype(int checked[static const 10])) {
|
|||
extern void f37(int a[volatile 10] : itype(int checked[volatile 10])) {
|
||||
}
|
||||
|
||||
extern void f38(const int *const x : itype(const int checked[const])) {
|
||||
extern void f38(const int *const x _Itype(const int checked[const])) {
|
||||
}
|
||||
|
||||
///
|
||||
|
@ -160,14 +160,16 @@ extern void f38(const int *const x : itype(const int checked[const])) {
|
|||
///
|
||||
|
||||
typedef ptr<int> pint;
|
||||
typedef ptr<const int> pcint;
|
||||
typedef const int * _Single pcint;
|
||||
|
||||
|
||||
extern void f40(int *x : itype(pint)) {
|
||||
}
|
||||
|
||||
extern void f41(const int *x : itype(pcint)) {
|
||||
extern void f41(const int *x _Itype(pcint)) {
|
||||
}
|
||||
|
||||
|
||||
// Identifier not allowed in a type name
|
||||
|
||||
void f50(int *p : itype(ptr<int> a)) { // expected-error {{type name cannot have identifier in it}}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#include <stdchecked.h>
|
||||
|
||||
struct S1 {
|
||||
array_ptr<int> arr : count(5);
|
||||
int* _Array arr _Count(5);
|
||||
};
|
||||
|
||||
struct S2 {
|
||||
|
@ -33,7 +33,7 @@ struct S6 {
|
|||
};
|
||||
|
||||
struct S7 {
|
||||
array_ptr<int> arr : bounds(arr, arr + 5);
|
||||
int* _Array arr _Bounds(arr, arr + 5);
|
||||
};
|
||||
|
||||
// Structure with a variable length array at the end
|
||||
|
@ -45,7 +45,7 @@ struct S8 {
|
|||
// Pointer into the middle of an array
|
||||
struct S9 {
|
||||
int start;
|
||||
array_ptr<int> arr : bounds(arr - start, arr - start + 5);
|
||||
int* _Array arr _Bounds(arr - start, arr - start + 5);
|
||||
};
|
||||
|
||||
struct S10 {
|
||||
|
@ -62,7 +62,7 @@ struct S11 {
|
|||
|
||||
struct S12 {
|
||||
int count;
|
||||
array_ptr<int> arr : count(count);
|
||||
int* _Array arr _Count(count);
|
||||
};
|
||||
|
||||
struct S13 {
|
||||
|
@ -78,7 +78,7 @@ struct S13 {
|
|||
array_ptr<int> arr3 : bounds(unknown + arr2, unknown + arr2 + 5); // expected-error {{expected ')'}} \
|
||||
// expected-note {{to match this '('}}
|
||||
// not a keyword
|
||||
array_ptr<int> arr4 : bounds(arr3, arr3 + unknown);
|
||||
int* _Array arr4 _Bounds(arr3, arr3 + unknown);
|
||||
};
|
||||
|
||||
struct S14 {
|
||||
|
@ -94,7 +94,7 @@ struct S14 {
|
|||
// not a keyword as an argument.
|
||||
array_ptr<int> arr3 : bounds(bounds + arr2, bounds + arr2 + 5);
|
||||
// not a keyword
|
||||
array_ptr<int> arr4 : bounds(arr3, arr3 + bounds);
|
||||
int* _Array arr4 _Bounds(arr3, arr3 + bounds);
|
||||
};
|
||||
|
||||
//
|
||||
|
@ -127,8 +127,8 @@ struct S15 {
|
|||
// Members that are arrays and that have bounds specified for them.
|
||||
// Legal but not too interestting.
|
||||
int arr13[10] : count(9);
|
||||
int arr14[10] : byte_count(9 * sizeof(int));
|
||||
int arr15[10] : bounds(arr15, arr15 + 9);
|
||||
int arr14[10] _Byte_count(9 * sizeof(int));
|
||||
int arr15[10] _Bounds(arr15, arr15 + 9);
|
||||
};
|
||||
|
||||
// Members that are pointers to functions that have bounds declarations on
|
||||
|
@ -151,19 +151,19 @@ extern void S16(void) {
|
|||
int(*s1)(array_ptr<int> : count(5));
|
||||
int(*s2)(array_ptr<int> arg : count(5));
|
||||
int(*s3)(int n, array_ptr<int> arg : count(n));
|
||||
int(*s4)(array_ptr<int> arg : count(n), int n);
|
||||
int(*s4)(int* _Array arg _Count(n), int n);
|
||||
// Use 'byte_count' instead of 'count'.
|
||||
int(*t1)(array_ptr<int> : byte_count(5 * sizeof(int)));
|
||||
int(*t2)(array_ptr<int> arg : count(5 * sizeof(int)));
|
||||
int(*t3)(int n, array_ptr<int> arg : count(n * sizeof(int)));
|
||||
int(*t4)(array_ptr<int> arg : count(n * sizeof(int)), int n);
|
||||
int(*t3)(int n, int* _Array arg _Count(n * sizeof(int)));
|
||||
int(*t4)(int* _Array arg _Count(n * sizeof(int)), int n);
|
||||
}
|
||||
|
||||
struct S17 {
|
||||
// Members that are pointers to functions that have bounds on
|
||||
// arguments or return values.
|
||||
int (*f1)(int len, array_ptr<int> arr : count(len));
|
||||
array_ptr<int> (*f2)(int len, array_ptr<int> arr : count(len)) : count(len);
|
||||
int (*f1)(int len, int* _Array arr _Count(len));
|
||||
int* _Array (*f2)(int len, int* _Array arr _Count(len)) _Count(len);
|
||||
// same as f1, but checked ptr
|
||||
ptr<int (int len, array_ptr<int> arr : count(len))> f3;
|
||||
// same as f2, but checked ptr
|
||||
|
@ -180,8 +180,8 @@ struct S17 {
|
|||
// Bounds distributed across multiple nested members
|
||||
struct S18 {
|
||||
struct S19 {
|
||||
array_ptr<int> lower;
|
||||
array_ptr<int> upper;
|
||||
int* _Array lower;
|
||||
int* _Array upper;
|
||||
} pair;
|
||||
array_ptr<int> arr1 : bounds(pair.lower, pair.upper);
|
||||
struct S20 {
|
||||
|
@ -193,7 +193,7 @@ struct S18 {
|
|||
struct S21 {
|
||||
struct {
|
||||
array_ptr<int> lower;
|
||||
array_ptr<int> upper;
|
||||
int* _Array upper;
|
||||
} pair;
|
||||
array_ptr<int> arr1 : bounds(pair.lower, pair.upper);
|
||||
struct {
|
||||
|
@ -210,7 +210,7 @@ struct S22 {
|
|||
};
|
||||
|
||||
struct S23 {
|
||||
array_ptr<int> arr : 6 + 6; // expected-error {{expected bounds expression}}
|
||||
int* _Array arr : 6 + 6; // expected-error {{expected bounds expression}}
|
||||
};
|
||||
|
||||
// Misspell bounds to cause an semantic checking error.
|
||||
|
@ -227,7 +227,7 @@ struct S24 {
|
|||
// and generate several errors.
|
||||
struct S25 {
|
||||
int len;
|
||||
array_ptr<int> arr : coount(5); // expected-error {{expected bounds expression}} \
|
||||
int* _Array arr : coount(5); // expected-error {{expected bounds expression}} \
|
||||
// expected-warning {{implicit declaration of function 'coount'}}
|
||||
};
|
||||
|
||||
|
@ -246,7 +246,7 @@ struct S27 {
|
|||
// Omit the argument to count to cause a parsing error.
|
||||
struct S28 {
|
||||
int len;
|
||||
array_ptr<int> arr : count(); //expected-error {{expected expression}}
|
||||
int* _Array arr _Count(); //expected-error {{expected expression}}
|
||||
};
|
||||
|
||||
//
|
||||
|
@ -264,7 +264,7 @@ int f1(void) {
|
|||
int buffer checked[100];
|
||||
struct S30 {
|
||||
int len;
|
||||
array_ptr<int> arr : bounds(buffer, buffer + len); // expected-error 2 {{use of undeclared member 'buffer'}}
|
||||
int* _Array arr _Bounds(buffer, buffer + len); // expected-error 2 {{use of undeclared member 'buffer'}}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -302,7 +302,7 @@ union U1 {
|
|||
// with the same size that are arrays of scalars.
|
||||
union U2 {
|
||||
array_ptr<int> ip : count(4);
|
||||
array_ptr<char> cp : count(4 * sizeof(int));
|
||||
char* _Array cp _Count(4 * sizeof(int));
|
||||
};
|
||||
|
||||
// Unions where dynamic tags are used to ensure correct use of members.
|
||||
|
@ -328,7 +328,7 @@ struct S32 {
|
|||
int tag : 1;
|
||||
union {
|
||||
array_ptr<char> cp : count(tag ? len : 0);
|
||||
array_ptr<int> ip : count(!tag ? 0 : len);
|
||||
int* _Array ip _Count(!tag ? 0 : len);
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -336,7 +336,7 @@ struct S32 {
|
|||
union U5 {
|
||||
_Bool isInteger;
|
||||
ptr<int> ip;
|
||||
ptr<float> fp;
|
||||
float* _Single fp;
|
||||
};
|
||||
|
||||
union U6 {
|
||||
|
|
|
@ -1,25 +1,25 @@
|
|||
// Feature tests of parsing new Checked C member bounds declarations.
|
||||
//
|
||||
// The following lines are for the LLVM test harness:
|
||||
//
|
||||
// RUN: %clang_cc1 -verify %s
|
||||
|
||||
#include <stdchecked.h>
|
||||
|
||||
_Static_assert(sizeof(void*) > sizeof(int),
|
||||
"Pointers must be larger than ints");
|
||||
|
||||
// Unions of pointers and integers, where the least significant
|
||||
// bit is used as a tag.
|
||||
|
||||
// We tag integers with 1 instead of trying to tag pointers with 1.
|
||||
// Null pointers tagged with 1 are not allowed by the current
|
||||
// Checked C definition.
|
||||
|
||||
#define is_tagged_int(p) ((int)(p) & 1)
|
||||
#define untag_int(p) ((p) & ~1)
|
||||
|
||||
union U4 {
|
||||
array_ptr<int> ip : bounds(ip, is_tagged_int(ip) ? ip : ip + 5); // expected-warning {{cast to smaller integer type 'int' from '_Array_ptr<int>'}}
|
||||
int i;
|
||||
};
|
||||
// Feature tests of parsing new Checked C member bounds declarations.
|
||||
//
|
||||
// The following lines are for the LLVM test harness:
|
||||
//
|
||||
// RUN: %clang_cc1 -verify %s
|
||||
|
||||
#include <stdchecked.h>
|
||||
|
||||
_Static_assert(sizeof(void*) > sizeof(int),
|
||||
"Pointers must be larger than ints");
|
||||
|
||||
// Unions of pointers and integers, where the least significant
|
||||
// bit is used as a tag.
|
||||
|
||||
// We tag integers with 1 instead of trying to tag pointers with 1.
|
||||
// Null pointers tagged with 1 are not allowed by the current
|
||||
// Checked C definition.
|
||||
|
||||
#define is_tagged_int(p) ((int)(p) & 1)
|
||||
#define untag_int(p) ((p) & ~1)
|
||||
|
||||
union U4 {
|
||||
array_ptr<int> ip : bounds(ip, is_tagged_int(ip) ? ip : ip + 5); // expected-warning {{cast to smaller integer type 'int' from '_Array_ptr<int>'}}
|
||||
int i;
|
||||
};
|
||||
|
|
|
@ -39,11 +39,11 @@ extern void f5(ptr<ptr<ptr<int>>> p, int y) {
|
|||
***p = y;
|
||||
}
|
||||
|
||||
extern void f6(array_ptr<int> p : count(1), int y) {
|
||||
*p = y;
|
||||
extern void f6(int *_Array p _Count(1), int y) {
|
||||
*p = y;
|
||||
}
|
||||
|
||||
extern void f7(array_ptr<int> p : count(1), int y) {
|
||||
extern void f7(int *_Array p _Count(1), int y) {
|
||||
*p = y;
|
||||
f6(p, y);
|
||||
}
|
||||
|
@ -57,8 +57,8 @@ extern void f9(nt_array_ptr<int> p : count(1), int y) {
|
|||
f8(p, y);
|
||||
}
|
||||
|
||||
extern void f10(nt_array_ptr<nt_array_ptr<int>> p : count(1),
|
||||
nt_array_ptr<int> y) {
|
||||
extern void f10(int *_Nt_array *_Nt_array p _Count(1),
|
||||
int *_Nt_array y) {
|
||||
*p = y;
|
||||
}
|
||||
|
||||
|
@ -92,9 +92,9 @@ extern void g6(int y, array_ptr<int> p : count(1)) {
|
|||
f7(p, y);
|
||||
}
|
||||
|
||||
extern void g7(int y, nt_array_ptr<int> p : count(1)) {
|
||||
*p = y;
|
||||
f9(p, y);
|
||||
extern void g7(int y, int *_Nt_array p _Count(1)) {
|
||||
*p = y;
|
||||
f9(p, y);
|
||||
}
|
||||
|
||||
|
||||
|
@ -131,17 +131,15 @@ extern array_ptr<int> h6(int y, array_ptr<int> p) {
|
|||
return p;
|
||||
}
|
||||
|
||||
|
||||
extern array_ptr<ptr<int>> h7(int y, array_ptr<ptr<int>> p : count(1)) {
|
||||
extern int *_Single *_Array h7(int y, int *_Single *_Array p _Count(1)) {
|
||||
**p = y;
|
||||
return p;
|
||||
}
|
||||
|
||||
extern nt_array_ptr<int> h8(int y, nt_array_ptr<int> p) {
|
||||
extern int *_Nt_array h8(int y, int *_Nt_array p) {
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
extern nt_array_ptr<ptr<int>> h9(int y, nt_array_ptr<ptr<int>> p : count(1)) {
|
||||
**p = y;
|
||||
return p;
|
||||
|
@ -156,8 +154,8 @@ extern void k1(int y)
|
|||
int v = y;
|
||||
ptr<int> t1 = &v;
|
||||
array_ptr<int> t2 : count(1) = &v;
|
||||
array_ptr<ptr<int>> t3 : count(1) = &t1;
|
||||
nt_array_ptr<int> t4 = 0;
|
||||
int *_Single *_Array t3 _Count(1) = &t1;
|
||||
int *_Nt_array t4 = 0;
|
||||
*t1 = 0;
|
||||
*t2 = 0;
|
||||
*t3 = 0;
|
||||
|
@ -182,9 +180,9 @@ extern int Multiply(struct Vector vec1, struct Vector vec2) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
extern int Multiply2(ptr<struct Vector> vec1p, ptr<struct Vector> vec2p) {
|
||||
extern int Multiply2(struct Vector* _Single vec1p, struct Vector* _Single vec2p) {
|
||||
if (vec1p->len != vec2p->len) {
|
||||
return 1;
|
||||
return 1;
|
||||
}
|
||||
for (int i = 0; i < vec1p->len; i++) {
|
||||
vec1p->data[i] *= vec2p->data[i];
|
||||
|
@ -209,8 +207,8 @@ ptr<int (int x, int y)> ptrfunc;
|
|||
// Function types have no size, so bounds checking does not make sense.
|
||||
//
|
||||
// Allowed: An array_ptr to an array of function pointers.
|
||||
array_ptr<ptr<int(int x, int y)>> array_ptr_of_ptrfunc;
|
||||
nt_array_ptr<ptr<int(int x, int y)>> nullterm_array_ptr_of_ptrfunc;
|
||||
int (*_Single *_Array array_ptr_of_ptrfunc)(int x, int y) ;
|
||||
int (*_Single *_Nt_array nullterm_array_ptr_of_ptrfunc)(int x, int y);
|
||||
|
||||
//
|
||||
// Declaring pointers to arrays and arrays of pointers
|
||||
|
@ -241,9 +239,9 @@ nt_array_ptr<int> nullterm_array_of_nullterm_pointers nt_checked[5];
|
|||
|
||||
// Declare an unchecked pointer to arrays of pointers
|
||||
int *(*uncheckedptr_to_array_of_unchecked_ptrs)[5];
|
||||
ptr<int>(*unchecked_ptr_to_array_of_ptrs)[5];
|
||||
array_ptr<int>(*unchecked_ptr_to_array_of_array_ptrs)[5];
|
||||
nt_array_ptr<int>(*unchecked_ptr_to_array_of_null_term_array_ptrs)[5];
|
||||
int* _Single(*unchecked_ptr_to_array_of_ptrs)[5];
|
||||
int *_Array(*unchecked_ptr_to_array_of_array_ptrs)[5];
|
||||
int *_Nt_array(*unchecked_ptr_to_array_of_null_term_array_ptrs)[5];
|
||||
|
||||
int *(*uncheckedptr_to_nullterm_array_of_unchecked_ptrs) nt_checked[5];
|
||||
ptr<int>(*unchecked_ptr_to_nullterm_array_of_ptrs) nt_checked[5];
|
||||
|
@ -257,17 +255,18 @@ ptr<array_ptr<int>[5]> ptr_to_array_of_array_ptrs;
|
|||
ptr<nt_array_ptr<int>[5]> ptr_to_array_of_nullterm_array_ptrs;
|
||||
|
||||
// Declare ptr to nullterm arrays of pointers
|
||||
ptr<int *nt_checked[5]> ptr_to_nullterm_array_of_unchecked_ptrs;
|
||||
ptr<ptr<int>nt_checked[5]> ptr_to_nullterm_array_of_ptrs;
|
||||
ptr<array_ptr<int>nt_checked[5]> ptr_to_nullterm_array_of_array_ptrs;
|
||||
ptr<nt_array_ptr<int>nt_checked[5]> ptr_to_nullterm_array_of_nullterm_array_ptrs;
|
||||
int * *_Single ptr_to_nullterm_array_of_unchecked_ptrs nt_checked[5];
|
||||
int *_Single ptr_to_nullterm_array_of_ptrs nt_checked[5];
|
||||
int *_Array *_Single ptr_to_nullterm_array_of_array_ptrs nt_checked[5];
|
||||
int *_Nt_array *_Single ptr_to_nullterm_array_of_nullterm_array_ptrs nt_checked[5];
|
||||
|
||||
|
||||
// Declare ptr to an array of function pointers
|
||||
ptr<int (*[5])(int x, int y)> ptr_to_array_of_unchecked_func_ptrs;
|
||||
ptr<ptr<int (int x, int y)>[5]> ptr_to_array_of_checked_func_ptrs;
|
||||
// Make parameter and return types be ptrs too.
|
||||
ptr<ptr<ptr<int> (ptr<int> x, ptr<int> y)>[5]> ptr_to_array_of_checked_func_ptrs_with_ptr_parameters;
|
||||
ptr<ptr<int* _Single (int* _Single x, int* _Single y)>[5]>
|
||||
ptr_to_array_of_checked_func_ptrs_with_ptr_parameters;
|
||||
|
||||
//
|
||||
// Typedefs using checked pointer types
|
||||
|
@ -277,8 +276,8 @@ typedef ptr<int> t_ptr_int;
|
|||
typedef ptr<int (int x, int y)> t_ptr_func;
|
||||
typedef array_ptr<int> t_array_ptr_int;
|
||||
typedef array_ptr<ptr<int>> t_array_ptr_ptr_int;
|
||||
typedef nt_array_ptr<int> t_nullterm_array_ptr_int;
|
||||
typedef nt_array_ptr<ptr<int>> t_nullterm_array_ptr_ptr_int;
|
||||
typedef int *_Nt_array t_nullterm_array_ptr_int;
|
||||
typedef int *_Single *_Nt_array t_nullterm_array_ptr_ptr_int;
|
||||
|
||||
//
|
||||
// Operators that take types
|
||||
|
@ -314,7 +313,7 @@ void parse_operators_with_types(void) {
|
|||
int s28 = _Alignof(int(int x, int y));
|
||||
int s29 = _Alignof(ptr<int>(int x, int y));
|
||||
// These are OK
|
||||
int s30 = _Alignof(ptr<int(int x, int y)>);
|
||||
int s30 = _Alignof(int (*_Single)(int x, int y));
|
||||
int s31 = _Alignof(int(*)(int x, int y));
|
||||
|
||||
// Test parsing of some cast operations that should pass checking
|
||||
|
@ -331,4 +330,6 @@ void parse_operators_with_types(void) {
|
|||
// ptr to function type
|
||||
ptr<int (int x, int y)> pfunc = (ptr<int (int x, int y)>) 0;
|
||||
ptr<ptr<int (int x, int y)>[5]> ptr_to_pfunc_arr = (ptr<ptr<int (int x, int y)>[5]>) 0;
|
||||
int (*_Single (*_Single m_ptr_to_pfunc_arr)[5])(int x, int y)= (int (*_Single (*_Single)[5])(int x, int y)) 0;
|
||||
|
||||
}
|
||||
|
|
|
@ -10,10 +10,10 @@ extern int cLen;
|
|||
extern array_ptr<int> f : byte_count(cLen * sizeof(int));
|
||||
extern array_ptr<int> g : bounds(f - 2, f + 3) rel_align(char);
|
||||
extern array_ptr<int> h : bounds(f - 2, f + 3) rel_align_value(sizeof(char));
|
||||
extern array_ptr<int> i : count(5), j : bounds(i - 2, i + 3) rel_align(char),
|
||||
l : bounds(i - 2, i + 3) rel_align_value(sizeof(char)),
|
||||
k : bounds(j + 2, j + 5) rel_align(char),
|
||||
m : bounds(j + 2, j + 5) rel_align_value(sizeof(char));
|
||||
extern int* _Array i _Count(5), * _Array j _Bounds(i - 2, i + 3) rel_align(char),
|
||||
* _Array l _Bounds(i - 2, i + 3) rel_align_value(sizeof(char)),
|
||||
* _Array k _Bounds(j + 2, j + 5) rel_align(char),
|
||||
* _Array m _Bounds(j + 2, j + 5) rel_align_value(sizeof(char));
|
||||
|
||||
char buf checked[128] : count(128);
|
||||
array_ptr<char> cursor : bounds(buf, buf + 128) rel_align(char) = buf + 64;
|
||||
|
@ -28,8 +28,8 @@ extern void f1(array_ptr<int> arr : count(5)) {
|
|||
array_ptr<int> midarr1 : bounds(midarr1 - 1, midarr1 - 1 + 2) rel_align_value(sizeof(char)) = arr + 2;
|
||||
|
||||
static array_ptr<int> cache1 : count(5);
|
||||
static array_ptr<int> cache1_ptr : bounds(cache1 - 2, cache1 + 3) rel_align(char);
|
||||
static array_ptr<int> cache1_ptr1 : bounds(cache1 - 2, cache1 + 3) rel_align_value(sizeof(char));
|
||||
static int* _Array cache1_ptr _Bounds(cache1 - 2, cache1 + 3) rel_align(char);
|
||||
static int* _Array cache1_ptr1 _Bounds(cache1 - 2, cache1 + 3) rel_align_value(sizeof(char));
|
||||
}
|
||||
|
||||
extern void f2(array_ptr<int> arr : count(5)) {
|
||||
|
@ -38,9 +38,9 @@ extern void f2(array_ptr<int> arr : count(5)) {
|
|||
u : bounds(u, u + 5) rel_align(char) = arr,
|
||||
v : bounds(unknown) = arr;
|
||||
|
||||
array_ptr<int> t1 : byte_count(5 * sizeof(int)) = arr,
|
||||
u1 : bounds(u1, u1 + 5) rel_align_value(sizeof(int)) = arr,
|
||||
v1 : bounds(unknown) = arr;
|
||||
int* _Array t1 _Byte_count(5 * sizeof(int)) = arr,
|
||||
* _Array u1 _Bounds(u1, u1 + 5) rel_align_value(sizeof(int)) = arr,
|
||||
* _Array v1 _Bounds(unknown) = arr;
|
||||
}
|
||||
|
||||
extern void f3(array_ptr<int> arr : count(5)) {
|
||||
|
@ -51,7 +51,7 @@ extern void f3(array_ptr<int> arr : count(5)) {
|
|||
|
||||
array_ptr<int> v1 : bounds(v1, (v1 + 5) + len - len) rel_align_value(sizeof(char)) = arr;
|
||||
array_ptr<int> w1 : bounds((w1 + len - (len)), (w1 + len)) rel_align_value(sizeof(char)) = arr;
|
||||
array_ptr<int> midarr1 : bounds(midarr1 - 1, (midarr1 - 1) + 2) rel_align_value(1) = arr + 2;
|
||||
int* _Array midarr1 _Bounds(midarr1 - 1, (midarr1 - 1) + 2) rel_align_value(1) = arr + 2;
|
||||
}
|
||||
|
||||
extern void f4(array_ptr<int> arr : count(len), int len) {
|
||||
|
@ -63,7 +63,7 @@ extern void f4(array_ptr<int> arr : count(len), int len) {
|
|||
array_ptr<int> t1 : bounds(t, t + count) rel_align_value(sizeof(char)) = arr;
|
||||
int bounds = len;
|
||||
array_ptr<int> u : bounds(u, u + bounds) rel_align(char) = arr;
|
||||
array_ptr<int> u1 : bounds(u1, u1 + bounds) rel_align_value(sizeof(char)) = arr;
|
||||
int* _Array u1 _Bounds(u1, u1 + bounds) rel_align_value(sizeof(char)) = arr;
|
||||
}
|
||||
|
||||
extern void f5(void) {
|
||||
|
@ -76,7 +76,7 @@ extern void f5(void) {
|
|||
|
||||
static int cache checked[5] : count(5);
|
||||
static array_ptr<int> cache_ptr : bounds(cache - 2, cache + 3) rel_align(char);
|
||||
static array_ptr<int> cache_ptr1 : bounds(cache - 2, cache + 3) rel_align_value(sizeof(char));
|
||||
static int* _Array cache_ptr1 _Bounds(cache - 2, cache + 3) rel_align_value(sizeof(char));
|
||||
}
|
||||
|
||||
extern void f6(int *arr checked[] : count(5)) {
|
||||
|
@ -127,11 +127,11 @@ extern array_ptr<int> f9s(int start, array_ptr<int> arr : bounds(arr - start, ar
|
|||
extern array_ptr<int> f10(int bounds, array_ptr<int> arr : count(bounds))
|
||||
: bounds(arr, arr + bounds) rel_align(char);
|
||||
|
||||
extern array_ptr<int> f10s(int bounds, array_ptr<int> arr : count(bounds))
|
||||
: bounds(arr, arr + bounds) rel_align_value(sizeof(char));
|
||||
extern int* _Array f10s(int bounds, int* _Array arr _Count(bounds))
|
||||
_Bounds(arr, arr + bounds) rel_align_value(sizeof(char));
|
||||
|
||||
extern array_ptr<int> f11(array_ptr<int> arr : bounds(arr, arr + 5) rel_align(char))
|
||||
: bounds(arr, arr + 5) rel_align(char) {
|
||||
extern int* _Array f11(int* _Array arr _Bounds(arr, arr + 5) rel_align(char))
|
||||
_Bounds(arr, arr + 5) rel_align(char) {
|
||||
return arr;
|
||||
}
|
||||
|
||||
|
@ -165,8 +165,8 @@ extern array_ptr<ptr<int>> f14(array_ptr<ptr<int>> arr : count(5))
|
|||
return arr;
|
||||
}
|
||||
|
||||
extern array_ptr<ptr<int>> f14s(array_ptr<ptr<int>> arr : count(5))
|
||||
: bounds(arr, arr + 5) rel_align_value(5) {
|
||||
extern array_ptr<ptr<int>> f14s(array_ptr<ptr<int>> arr _Count(5))
|
||||
_Bounds(arr, arr + 5) rel_align_value(5) {
|
||||
return arr;
|
||||
}
|
||||
|
||||
|
@ -175,8 +175,8 @@ extern array_ptr<int[10]> f15(array_ptr<int[10]> arr : count(5))
|
|||
return arr;
|
||||
}
|
||||
|
||||
extern array_ptr<int[10]> f15s(array_ptr<int[10]> arr : count(5))
|
||||
: bounds(arr, arr + 3) rel_align_value(sizeof(char)) {
|
||||
extern array_ptr<int[10]> f15s(array_ptr<int[10]> arr _Count(5))
|
||||
_Bounds(arr, arr + 3) rel_align_value(sizeof(char)) {
|
||||
return arr;
|
||||
}
|
||||
|
||||
|
@ -189,15 +189,15 @@ extern void f16(void) {
|
|||
: bounds(arg2, arg2 + n) rel_align(char)> r3 = 0;
|
||||
ptr<int(array_ptr<int> arg3 : count(n), int n)
|
||||
: bounds(arg3, arg3 + n) rel_align_value(sizeof(char))> r4 = 0;
|
||||
typedef int func2(array_ptr<int> arr : count(len), int len)
|
||||
: bounds(arr, arr + len) rel_align(char);
|
||||
typedef int func2(int* _Array arr _Count(len), int len)
|
||||
_Bounds(arr, arr + len) rel_align(char);
|
||||
}
|
||||
|
||||
extern array_ptr<int> f17(int len, array_ptr<int> arr : count(len)) : boounds(arr, arr + len) rel_align(1) { // expected-error {{expected bounds expression}}
|
||||
}
|
||||
extern array_ptr<int> f18(int len, array_ptr<int> arr : count(len)) : boounds(arr, arr + len) rel_align(char) { // expected-error {{expected bounds expression}}
|
||||
}
|
||||
extern array_ptr<int> f19(int len, array_ptr<int> arr : count(len)) : boounds(arr, arr + len) rel_align_value(len) { // expected-error {{expected bounds expression}}
|
||||
extern int* _Array f19(int len, int* _Array arr _Count(len)) : boounds(arr, arr + len) rel_align_value(len) { // expected-error {{expected bounds expression}}
|
||||
}
|
||||
|
||||
int f20(void) {
|
||||
|
@ -205,7 +205,7 @@ int f20(void) {
|
|||
struct S30 {
|
||||
int len;
|
||||
array_ptr<int> arr : bounds(buffer, buffer + len) rel_align(char); // expected-error 2 {{use of undeclared member 'buffer'}}
|
||||
array_ptr<int> arr1: bounds(buffer, buffer + len) rel_align_value(sizeof(len));// expected-error 2 {{use of undeclared member 'buffer'}}
|
||||
int* _Array arr1 _Bounds(buffer, buffer + len) rel_align_value(sizeof(len));// expected-error 2 {{use of undeclared member 'buffer'}}
|
||||
array_ptr<int> arr2: bounds(buffer, buffer + len) rel_align_value(sizeof(char));// expected-error 2 {{use of undeclared member 'buffer'}}
|
||||
};
|
||||
}
|
||||
|
@ -229,12 +229,13 @@ extern array_ptr<int> f25(int len, array_ptr<int> arr : count(len)) : boounds(ar
|
|||
|
||||
extern array_ptr<int> f26(int len, array_ptr<int> arr : count(len)) : boounds() rel_align(1) {} // expected-error {{expected bounds expression or bounds-safe interface type}}
|
||||
|
||||
extern array_ptr<int> f27(int len, array_ptr<int> arr : count(len)) : boounds() rel_alive(1) { // expected-error {{expected bounds expression or bounds-safe interface type}}
|
||||
extern int* _Array f27(int len, int* _Array arr _Count(len)) : boounds() rel_alive(1) { // expected-error {{expected bounds expression or bounds-safe interface type}}
|
||||
}
|
||||
|
||||
extern void f28(void) {
|
||||
array_ptr<int> arg : bo0unds(arg, arg + 5) rel_alive(1) = 0; // expected-error {{expected bounds expression or bounds-safe interface type}}
|
||||
array_ptr<int> arg1 : bo0unds rel_alive(1) = 0; // expected-error {{expected bounds expression or bounds-safe interface type}}
|
||||
array_ptr<int> arg2 : bo0unds rel_align(1) = 0; // expected-error {{expected bounds expression or bounds-safe interface type}}
|
||||
int* _Array arg _Bo0unds(arg, arg + 5) rel_alive(1) = 0; // expected-error {{expected ';' at end of declaration}}
|
||||
int* _Array arg1 _Bo0unds rel_alive(1) = 0; // expected-error {{expected ';' at end of declaration}}
|
||||
int* _Array arg2 _Bo0unds rel_align(1) = 0; // expected-error {{expected ';' at end of declaration}}
|
||||
}
|
||||
|
||||
struct S1 {
|
||||
|
@ -245,8 +246,8 @@ struct S1 {
|
|||
struct S2 {
|
||||
int start;
|
||||
array_ptr<int> arr : bounds(arr - start, arr - start + 5) rel_align(char);
|
||||
array_ptr<int> arr1 : bounds(arr1 - start, arr1 - start + 5)
|
||||
rel_align_value(sizeof(char) + sizeof(char));
|
||||
int* _Array arr1 _Bounds(arr1 - start, arr1 - start + 5)
|
||||
rel_align_value(sizeof(char) + sizeof(char));
|
||||
};
|
||||
|
||||
struct S3 {
|
||||
|
@ -261,7 +262,7 @@ struct S3 {
|
|||
array_ptr<int> arr5 : bounds(unknown + arr2, unknown + arr2 + 5) rel_align_value(sizeof(char));// expected-error {{expected ')'}} \
|
||||
// expected-note {{to match this '('}} \
|
||||
// expected-error {{expected range bounds expression}}
|
||||
array_ptr<int> arr6 : bounds(arr2, arr2 + unknown) rel_align_value(1);
|
||||
int* _Array arr6 _Bounds(arr2, arr2 + unknown) rel_align_value(1);
|
||||
};
|
||||
|
||||
struct S4 {
|
||||
|
@ -273,7 +274,7 @@ struct S4 {
|
|||
|
||||
array_ptr<int> arr5 : bounds(bounds + arr5, bounds + arr5 + 2) rel_align_value(sizeof(int));
|
||||
array_ptr<int> arr6 : bounds(bounds + arr2, bounds + arr2 + 5) rel_align_value(sizeof(char));
|
||||
array_ptr<int> arr7 : bounds(arr6, arr6 + bounds) rel_align_value(sizeof(char));
|
||||
int* _Array arr7 _Bounds(arr6, arr6 + bounds) rel_align_value(sizeof(char));
|
||||
};
|
||||
|
||||
struct S5 {
|
||||
|
@ -289,7 +290,7 @@ struct S5 {
|
|||
int *arr12 : bounds(arr12, arr12 + 9) rel_align(char);
|
||||
int *arr13 : bounds(arr13, arr13 + 9) rel_align_value(sizeof(char));
|
||||
int arr14[10] : bounds(arr14, arr14 + 9) rel_align(char);
|
||||
int arr15[10] : bounds(arr15, arr15 + 9) rel_align_value(sizeof(char));
|
||||
int arr15[10] _Bounds(arr15, arr15 + 9) rel_align_value(sizeof(char));
|
||||
};
|
||||
|
||||
extern void S6(void) {
|
||||
|
@ -299,8 +300,8 @@ extern void S6(void) {
|
|||
: bounds(arg1, arg1 + 5) rel_align_value(sizeof(char))> r2 = 0;
|
||||
ptr<int(array_ptr<int> arg2 : count(n), int n)
|
||||
: bounds(arg2, arg2 + n) rel_align(char)> r3 = 0;
|
||||
ptr<int(array_ptr<int> arg3 : count(n), int n)
|
||||
: bounds(arg3, arg3 + n) rel_align_value(n)> r4 = 0; // expected-error {{expression is not an integer constant expression}}
|
||||
ptr<int(int* _Array arg3 _Count(n), int n)
|
||||
_Bounds(arg3, arg3 + n) rel_align_value(n)> r4 = 0; // expected-error {{expression is not an integer constant expression}}
|
||||
}
|
||||
|
||||
struct S7 {
|
||||
|
@ -312,7 +313,7 @@ struct S7 {
|
|||
array_ptr<int> arr1 : bounds(pair.lower, pair.upper) rel_align_value(sizeof(pair));
|
||||
struct S9 {
|
||||
array_ptr<int> arr2 : bounds(pair.lower, pair.upper) rel_align(char);
|
||||
array_ptr<int> arr3 : bounds(pair.lower, pair.upper) rel_align_value(sizeof(pair));
|
||||
int* _Array arr3 _Bounds(pair.lower, pair.upper) rel_align_value(sizeof(pair));
|
||||
} nested;
|
||||
};
|
||||
|
||||
|
@ -325,14 +326,14 @@ struct S10 {
|
|||
array_ptr<int> arr1 : bounds(pair.lower, pair.upper) rel_align_value(sizeof(char));
|
||||
struct {
|
||||
array_ptr<int> arr2 : bounds(pair.lower, pair.upper) rel_align(char);
|
||||
array_ptr<int> arr3 : bounds(pair.lower, pair.upper) rel_align_value(sizeof(pair));
|
||||
int* _Array arr3 _Bounds(pair.lower, pair.upper) rel_align_value(sizeof(pair));
|
||||
} nested;
|
||||
};
|
||||
|
||||
struct S11 {
|
||||
array_ptr<int> arr : bounds(arr, unknown_id) rel_align(char); // expected-error {{use of undeclared member}}
|
||||
|
||||
array_ptr<int> arr1: bounds(arr1, unknown_id) rel_align_value(sizeof(char)); // expected-error {{use of undeclared member}}
|
||||
int* _Array arr1 _Bounds(arr1, unknown_id) rel_align_value(sizeof(char)); // expected-error {{use of undeclared member}}
|
||||
|
||||
};
|
||||
|
||||
|
@ -350,16 +351,16 @@ struct S13 {
|
|||
|
||||
array_ptr<int> arr1: bounds() rel_align_value(len); // expected-error {{expected expression}} \
|
||||
// expected-error {{expression is not an integer constant expression}}
|
||||
array_ptr<int> arr3 : bounds() rel_align(); // expected-error {{expected expression}} expected-error {{expected a type}}
|
||||
int* _Array arr3 _Bounds() rel_align(); // expected-error {{expected expression}} expected-error {{expected a type}}
|
||||
|
||||
array_ptr<int> arr4 : bounds() rel_align_value(); // expected-error 2 {{expected expression}}
|
||||
int* _Array arr4 _Bounds() rel_align_value(); // expected-error 2 {{expected expression}}
|
||||
};
|
||||
|
||||
array_ptr<int> global_bound;
|
||||
|
||||
struct S14 {
|
||||
int len;
|
||||
array_ptr<int> arr : bounds(global_bound, global_bound + len) rel_align(int); // expected-error 2 {{use of undeclared member 'global_bound'}}
|
||||
int* _Array arr _Bounds(global_bound, global_bound + len) rel_align(int); // expected-error 2 {{use of undeclared member 'global_bound'}}
|
||||
|
||||
array_ptr<int> arr1
|
||||
: bounds(global_bound, global_bound + len) rel_align_value(sizeof(int)); // expected-error 2 {{use of undeclared member 'global_bound'}}
|
||||
|
|
|
@ -18,10 +18,10 @@ extern array_ptr<int> f5(array_ptr<int> arr : byte_count(5 * sizeof(int)))
|
|||
: byte_count(5 * sizeof(int));
|
||||
extern array_ptr<int> f6(array_ptr<int> arr : bounds(arr, arr + 5))
|
||||
: bounds(arr, arr + 5);
|
||||
extern array_ptr<int> f7(int start,
|
||||
array_ptr<int> arr : bounds(arr - start, arr - start + 5))
|
||||
: bounds(arr - start, arr - start + 5);
|
||||
extern array_ptr<char> f8(void) : bounds(unknown);
|
||||
extern int* _Array f7(int start,
|
||||
int* _Array arr _Bounds(arr - start, arr - start + 5))
|
||||
_Bounds(arr - start, arr - start + 5);
|
||||
extern char* _Array f8(void) _Bounds(unknown);
|
||||
|
||||
// Parsing of return bounds expressions containing return_value. Test this by
|
||||
// expanding count/byte_count expressions into bounds expressions.
|
||||
|
@ -35,8 +35,8 @@ extern array_ptr<int> f3a(int len, array_ptr<int> arr : count(len))
|
|||
// only when they immediately follow a ':';
|
||||
extern array_ptr<char> f9(int count) : count(count);
|
||||
extern array_ptr<char> f10(int unknown) : count(unknown);
|
||||
extern array_ptr<int> f11(int bounds, array_ptr<int> arr : count(bounds))
|
||||
: bounds(arr, arr + bounds);
|
||||
extern int* _Array f11(int bounds, int* _Array arr _Count(bounds))
|
||||
_Bounds(arr, arr + bounds);
|
||||
|
||||
// Parsing function definitions.
|
||||
extern array_ptr<int> f1(array_ptr<int> arr : count(5)) : count(5) {
|
||||
|
@ -53,11 +53,12 @@ extern array_ptr<int> f3(int len,
|
|||
return arr;
|
||||
}
|
||||
|
||||
extern array_ptr<int> f4(array_ptr<int> arr : byte_count(20))
|
||||
: byte_count(20) {
|
||||
extern int* _Array f4(int* _Array arr _Byte_count(20))
|
||||
_Byte_count(20) {
|
||||
return arr;
|
||||
}
|
||||
|
||||
|
||||
extern array_ptr<int> f5(array_ptr<int> arr : byte_count(5 * sizeof(int)))
|
||||
: byte_count(5 * sizeof(int)) {
|
||||
return arr;
|
||||
|
@ -68,10 +69,10 @@ extern array_ptr<int> f6(array_ptr<int> arr : bounds(arr, arr + 5))
|
|||
return arr;
|
||||
}
|
||||
|
||||
extern array_ptr<int> f7(int start,
|
||||
array_ptr<int> arr : bounds(arr - start, arr - start + 5))
|
||||
: bounds(arr - start, arr - start + 5) {
|
||||
return arr;
|
||||
extern int* _Array f7(int start,
|
||||
int* _Array arr _Bounds(arr - start, arr - start + 5))
|
||||
_Bounds(arr - start, arr - start + 5) {
|
||||
return arr;
|
||||
}
|
||||
|
||||
extern array_ptr<char> f8(void) : bounds(unknown) {
|
||||
|
@ -92,8 +93,8 @@ extern array_ptr<char> f10(int unknown) : count(unknown) {
|
|||
|
||||
// 'bounds' is a contextual keyword. It is only a keyword when it
|
||||
// immediately follows the ':' in a bounds declaration.
|
||||
extern array_ptr<int> f11(int bounds, array_ptr<int> arr : count(bounds))
|
||||
: bounds(arr, arr + bounds) {
|
||||
extern int* _Array f11(int bounds, int* _Array arr _Count(bounds))
|
||||
_Bounds(arr, arr + bounds) {
|
||||
return arr;
|
||||
}
|
||||
|
||||
|
@ -128,8 +129,10 @@ extern array_ptr<int[10]> f16(array_ptr<int[10]> arr : count(5))
|
|||
return arr;
|
||||
}
|
||||
|
||||
extern array_ptr<int[10]> f17(array_ptr<int[10]> arr : count(5))
|
||||
: bounds(arr, arr + 3) {
|
||||
typedef int (* _Array arrayptr10)[10];
|
||||
|
||||
extern arrayptr10 f17(arrayptr10 arr _Count(5))
|
||||
_Bounds(arr, arr + 3) {
|
||||
return arr;
|
||||
}
|
||||
|
||||
|
@ -151,8 +154,10 @@ extern ptr<array_ptr<int>(int len) : count(len)> f19(int len) {
|
|||
}
|
||||
|
||||
// Check that return_value can be used. Expand count to a bounds expression.
|
||||
extern ptr<array_ptr<int>(int len) : bounds(return_value, len + return_value)>
|
||||
f19a(int len) { return 0; }
|
||||
typedef int* _Array f19a_temp(int len) _Bounds(return_value, return_value + len);
|
||||
extern f19a_temp* _Single f19a(int len) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Like the prior function, but returns an unchecked pointer instead. The
|
||||
// unchecked pointer points to a function that takes in a length and returns an
|
||||
|
@ -170,8 +175,9 @@ extern array_ptr<int> (*f20(int arg))(int len) : count(len) {
|
|||
|
||||
// Function that returns an array pointer to ptrs to functions that take in a
|
||||
// length and return array_ptr<int>s of that length.
|
||||
extern array_ptr<ptr<array_ptr<int>(int len) : count(len)>> f21(int arg)
|
||||
: count(arg) {
|
||||
typedef int* _Array f21_temp(int len) _Count(len);
|
||||
typedef f21_temp* _Single f21_temp2;
|
||||
extern f21_temp2* _Array f21(int arg) _Count(arg) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -209,7 +215,7 @@ extern void f24(void) {
|
|||
// Use 'bounds' instead of 'count'.
|
||||
ptr<array_ptr<int>(array_ptr<int> arg : count(5)) : bounds(arg, arg + 5)>
|
||||
r1 = 0;
|
||||
ptr<int(array_ptr<int> arg : count(n), int n) : bounds(arg, arg + n)> r2 = 0;
|
||||
int (*_Single r2)(int* _Array arg _Count(n), int n) _Bounds(arg, arg + n) = 0;
|
||||
// Unchecked pointers to functions.
|
||||
int(*s1)(array_ptr<int> : count(5)) = 0;
|
||||
int(*s2)(array_ptr<int> arg : count(5)) = 0;
|
||||
|
@ -218,8 +224,8 @@ extern void f24(void) {
|
|||
// Use 'byte_count' instead of 'count'.
|
||||
int(*t1)(array_ptr<int> : byte_count(5 * sizeof(int))) = 0;
|
||||
int(*t2)(array_ptr<int> arg : count(5 * sizeof(int))) = 0;
|
||||
int(*t3)(int n, array_ptr<int> arg : count(n * sizeof(int))) = 0;
|
||||
int(*t4)(array_ptr<int> arg : count(n * sizeof(int)), int n) = 0;
|
||||
int(*t3)(int n, int* _Array arg _Count(n * sizeof(int))) = 0;
|
||||
int(*t4)(int* _Array arg _Count(n * sizeof(int)), int n) = 0;
|
||||
}
|
||||
|
||||
typedef array_ptr<int> func1(int len) : count(len);
|
||||
|
@ -237,7 +243,7 @@ extern array_ptr<char> f26(void) : count(len) { // expected-error {{use of undec
|
|||
}
|
||||
|
||||
// Misspell bounds to cause a parsing error.
|
||||
extern array_ptr<int> f27(int len, array_ptr<int> arr : count(len)) : boounds(arr, arr + len)) { // expected-error {{expected bounds expression}}
|
||||
extern int* _Array f27(int len, int* _Array arr _Count(len)) : boounds(arr, arr + len)) { // expected-error {{expected bounds expression}}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -252,7 +258,7 @@ extern array_ptr<int> f29(int len, array_ptr<int> arr : count(len)) : bounds(arr
|
|||
}
|
||||
|
||||
// Omit both arguments to bounds to cause a parsing error
|
||||
extern array_ptr<int> f30(int len, array_ptr<int> arr : count(len)) : bounds() { // expected-error {{expected expression}}
|
||||
extern int* _Array f30(int len, int* _Array arr _Count(len)) _Bounds() { // expected-error {{expected expression}}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -283,7 +289,7 @@ int *(f33(int i)) : count(10) { // expected-error {{unexpected bounds expression
|
|||
// _Return value can only be used in a return bounds expression
|
||||
//
|
||||
|
||||
int f40(array_ptr<int> a : bounds(return_value, return_value + 10)); // expected-error 2 {{_Return_value can be used only in a return bounds expression}}
|
||||
int f40(int* _Array a _Bounds(return_value, return_value + 10)); // expected-error 2 {{_Return_value can be used only in a return bounds expression}}
|
||||
|
||||
int f41(void) {
|
||||
return_value = 0; // expected-error {{_Return_value can be used only in a return bounds expression}}
|
||||
|
|
|
@ -10,15 +10,15 @@
|
|||
// expected-no-diagnostics
|
||||
|
||||
// Testing for function declaration with function body, with parameters
|
||||
_For_any(T, S) _Ptr<T> TestDefinitionWithParameter(_Ptr<T> at, _Ptr<T> bt, _Ptr<S> cs) {
|
||||
_For_any(T, S) T* _Single TestDefinitionWithParameter(T* _Single at, T* _Single bt, _Ptr<S> cs) {
|
||||
_Ptr<T> newT = at;
|
||||
return newT;
|
||||
}
|
||||
|
||||
// Testing for function declaration without function body, without parameters.
|
||||
_For_any(R) _Ptr<R> TestDeclarationWithNoParameter(void);
|
||||
_For_any(R) R* _Single TestDeclarationWithNoParameter(void);
|
||||
// Testing for function declaration without function body, with parameters
|
||||
_For_any(Q) _Ptr<Q> TestDeclarationWithParameter(_Ptr<Q> aq, _Ptr<Q> bq, _Ptr<Q> cq);
|
||||
_For_any(Q) Q* _Single TestDeclarationWithParameter(Q* _Single aq, _Ptr<Q> bq, _Ptr<Q> cq);
|
||||
|
||||
int callPolymorphicTypes() {
|
||||
int num = 0;
|
||||
|
|
|
@ -7,9 +7,9 @@
|
|||
//
|
||||
// RUN: %clang_cc1 -verify %s
|
||||
|
||||
_For_any(R) _Ptr<R> foo(void);
|
||||
_For_any(R) R* _Single foo(void);
|
||||
// Testing scope created by for any specifier is exited successfully.
|
||||
R *thisShouldProduceError; //expected-error{{unknown type name 'R'}}
|
||||
_For_any() void foo2(void); // expected-error{{expected type variable identifier}}
|
||||
_For_any(R, ) _Ptr<R> foo3(void); // expected-error{{expected type variable identifier}}
|
||||
_For_any(R T) _Ptr<R> foo4(void); // expected-error{{expected , or )}}
|
||||
_For_any(R T) R* _Single foo4(void); // expected-error{{expected , or )}}
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
// RUN: %clang_cc1 -verify %s
|
||||
// expected-no-diagnostics
|
||||
|
||||
_For_any(T) _Ptr<T> foo(_Ptr<T> a, _Ptr<T> b) {
|
||||
_For_any(T) T* _Single foo(T* _Single a, T* _Single b) {
|
||||
return a;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
//
|
||||
// RUN: %clang_cc1 -verify %s
|
||||
|
||||
_For_any(T) _Ptr<T> Foo(_Ptr<T> a, _Ptr<T> b) {
|
||||
_For_any(T) T* _Single Foo(T* _Single a, T* _Single b) {
|
||||
return a;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
static char *test : itype(ptr<char>);
|
||||
char p = 5;
|
||||
static char *init : itype(ptr<char>) = &p;
|
||||
static char *init _Itype(char* _Single) = &p;
|
||||
|
||||
int testfn(char *buf : count(len), size_t len)
|
||||
_Checked {
|
||||
|
@ -18,7 +18,7 @@ _Checked {
|
|||
}
|
||||
|
||||
|
||||
int main(int argc, array_ptr<char*> argv : count(argc)) {
|
||||
int main(int argc, char**_Array argv : count(argc)) {
|
||||
// CHECK: Starting test
|
||||
puts("Starting test");
|
||||
testfn(init, 1);
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
// Test taking addresses of members using in bounds expressions for checked members.
|
||||
struct S1 {
|
||||
_Array_ptr<int> p : count(len);
|
||||
int* _Array p _Count(len);
|
||||
int len;
|
||||
};
|
||||
|
||||
|
@ -79,7 +79,7 @@ extern void f3(struct S1 *s1, struct S2 *s2, struct S1_Nested *s1_nested, struct
|
|||
_Array_ptr<int> *p6 = &(s2->s).p; // expected-error {{cannot take address of member with bounds}}
|
||||
_Array_ptr<int> *p7 = &s1_nested->p; // expected-error {{cannot take address of member with bounds}}
|
||||
_Array_ptr<int> *p8 = &(s1_nested->p); // expected-error {{cannot take address of member with bounds}}
|
||||
_Array_ptr<int> *p9 = &(s1_nested)->p; // expected-error {{cannot take address of member with bounds}}
|
||||
int* _Array *p9 = &(s1_nested)->p; // expected-error {{cannot take address of member with bounds}}
|
||||
}
|
||||
|
||||
// Test taking addresses of members with bounds-safe interfaces.
|
||||
|
@ -128,7 +128,7 @@ extern checked void f5(struct S3 s3, struct S4 s4, struct S3_Nested s3_nested) {
|
|||
_Ptr<int> p9 = &(s3_nested.child).len; // expected-error {{cannot take address of member used in member bounds}}
|
||||
_Ptr<struct Nested_Len> p10 = &s3_nested.child; // expected-error {{cannot take address of member used in member bounds}}
|
||||
_Ptr<struct Nested_Len> p11 = &(s3_nested).child; // expected-error {{cannot take address of member used in member bounds}}
|
||||
_Ptr<struct Nested_Len> p12 = &(s3_nested.child); // expected-error {{cannot take address of member used in member bounds}}
|
||||
struct Nested_Len* _Single p12 = &(s3_nested.child); // expected-error {{cannot take address of member used in member bounds}}
|
||||
}
|
||||
|
||||
extern void f6(struct S3 *s3, struct S4 *s4, struct S3_Nested *s3_nested) {
|
||||
|
@ -159,7 +159,7 @@ extern checked void f7(_Ptr<struct S3> s3, _Ptr<struct S4> s4, _Ptr<struct S3_Ne
|
|||
_Ptr<int> p9 = &(s3_nested->child).len; // expected-error {{cannot take address of member used in member bounds}}
|
||||
_Ptr<struct Nested_Len> p10 = &s3_nested->child; // expected-error {{cannot take address of member used in member bounds}}
|
||||
_Ptr<struct Nested_Len> p11 = &(s3_nested)->child; // expected-error {{cannot take address of member used in member bounds}}
|
||||
_Ptr<struct Nested_Len> p12 = &(s3_nested->child); // expected-error {{cannot take address of member used in member bounds}}
|
||||
struct Nested_Len* _Single p12 = &(s3_nested->child); // expected-error {{cannot take address of member used in member bounds}}
|
||||
}
|
||||
|
||||
extern void f8(struct S3 s3, struct S4 s4, struct S3_Nested s3_nested) {
|
||||
|
@ -195,7 +195,7 @@ extern checked void f10(struct S3 s3, struct S4 s4, struct S3_Nested s3_nested)
|
|||
_Ptr<_Array_ptr<int>> p6 = &(s4.s).p; // expected-error {{cannot take address of member with bounds}}
|
||||
_Ptr<_Array_ptr<int>> p7 = &s3_nested.p; // expected-error {{cannot take address of member with bounds}}
|
||||
_Ptr<_Array_ptr<int>> p8 = &(s3_nested.p); // expected-error {{cannot take address of member with bounds}}
|
||||
_Ptr<_Array_ptr<int>> p9 = &(s3_nested).p; // expected-error {{cannot take address of member with bounds}}
|
||||
int* _Array *_Single p9 = &(s3_nested).p; // expected-error {{cannot take address of member with bounds}}
|
||||
}
|
||||
|
||||
extern checked void f11(_Ptr<struct S3> s3, _Ptr<struct S4> s4, _Ptr<struct S3_Nested> s3_nested) {
|
||||
|
@ -207,7 +207,7 @@ extern checked void f11(_Ptr<struct S3> s3, _Ptr<struct S4> s4, _Ptr<struct S3_N
|
|||
_Ptr<_Array_ptr<int>> p6 = &(s4->s).p; // expected-error {{cannot take address of member with bounds}}
|
||||
_Ptr<_Array_ptr<int>> p7 = &s3_nested->p; // expected-error {{cannot take address of member with bounds}}
|
||||
_Ptr<_Array_ptr<int>> p8 = &(s3_nested->p); // expected-error {{cannot take address of member with bounds}}
|
||||
_Ptr<_Array_ptr<int>> p9 = &(s3_nested)->p; // expected-error {{cannot take address of member with bounds}}
|
||||
int* _Array *_Single p9 = &(s3_nested)->p; // expected-error {{cannot take address of member with bounds}}
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -234,7 +234,7 @@ struct S8 {
|
|||
|
||||
|
||||
extern void f30(struct S5 *s5) {
|
||||
_Ptr<int _Checked[10]> p1 = &s5->arr; // this is OK because arr can't be modified.
|
||||
int(* _Single p1) _Checked[10] = &s5->arr; // this is OK because arr can't be modified.
|
||||
}
|
||||
|
||||
extern void f31(struct S6 *s6) {
|
||||
|
@ -252,7 +252,7 @@ extern checked void f33(_Ptr<struct S7> s7) {
|
|||
}
|
||||
|
||||
extern checked void f33a(struct S7 *s7 : itype(_Ptr<struct S7>)) {
|
||||
_Ptr<int _Checked[10]> p1 = &s7->arr; // this is OK because arr can't be modified.
|
||||
int(* _Single p1) _Checked[10]= &s7->arr; // this is OK because arr can't be modified.
|
||||
}
|
||||
|
||||
|
||||
|
@ -268,7 +268,7 @@ extern checked void f35(_Ptr<struct S8> s8) {
|
|||
|
||||
extern checked void f35a(struct S8 *s8 : itype(_Ptr<struct S8>)) {
|
||||
_Ptr<int> p1 = &s8->len; // expected-error {{cannot take address of member used in member bounds}}
|
||||
_Ptr<int _Checked[10]> p2 = &s8->arr; // this is OK because arr can't be modified.
|
||||
int (* _Single p2) _Checked[10]= &s8->arr; // this is OK because arr can't be modified.
|
||||
}
|
||||
|
||||
// Spot check bounds for a flexible array member.
|
||||
|
@ -300,7 +300,7 @@ extern void f40(struct S9 *s9) {
|
|||
|
||||
extern void f41(struct S10 *s10) {
|
||||
_Ptr<int> p1 = &s10->len; // expected-error {{cannot take address of member used in member bounds}}
|
||||
_Ptr<int _Checked[]> p2 = &s10->arr; // this is OK because arr can't be modified.
|
||||
int (*_Single p2) _Checked[] = &s10->arr; // this is OK because arr can't be modified.
|
||||
}
|
||||
|
||||
extern void f42(struct S11 *s11) {
|
||||
|
@ -318,7 +318,7 @@ extern void f44(struct S12 *s12) {
|
|||
|
||||
extern checked void f45(_Ptr<struct S12> s12) {
|
||||
_Ptr<int> p1 = &s12->len; // expected-error {{cannot take address of member used in member bounds}}
|
||||
_Ptr<int _Checked[]> p2 = &s12->arr; // this is OK because arr can't be modified.
|
||||
int (*_Single p2) _Checked[] = &s12->arr; // this is OK because arr can't be modified.
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -339,7 +339,7 @@ void f46(struct S20 s) {
|
|||
_Ptr<_Array_ptr<int>> p3 = &s.upper; // expected-error {{cannot take address of member used in member bounds}}
|
||||
_Ptr<_Array_ptr<int>> p4 = &s.upper; // expected-error {{cannot take address of member used in member bounds}}
|
||||
_Ptr<_Array_ptr<int>> p5 = &s.q; // expected-error {{cannot take address of member with bounds}}
|
||||
_Ptr<int> p6 = &s.len; // expected-error {{cannot take address of member used in member bounds}}
|
||||
int* _Single p6 = &s.len; // expected-error {{cannot take address of member used in member bounds}}
|
||||
}
|
||||
|
||||
|
||||
|
@ -362,7 +362,8 @@ extern void f60(_Array_ptr<int> x : count(len), int len) {
|
|||
_Ptr<_Array_ptr<int>> py = &y; // expected-error {{cannot take address of variable 'y' with bounds}}
|
||||
_Ptr<_Array_ptr<int>> pg = &global_var1; // expected-error {{cannot take address of variable 'global_var1' with bounds}}
|
||||
_Ptr<int _Checked[]> parr1 = &global_arr1;
|
||||
_Ptr<int _Checked[]> parr2 = &(global_arr1);
|
||||
int (*_Single parr2) _Checked[]= &(global_arr1);
|
||||
|
||||
|
||||
if (len >= 0 && len < 10) {
|
||||
int arr _Checked[10] : count(len);
|
||||
|
@ -387,7 +388,7 @@ extern _Checked void f62(int *x : count(len), int len) {
|
|||
_Ptr<_Array_ptr<int>> px1 = &x; // expected-error {{cannot take address of variable 'x' with bounds}}
|
||||
_Ptr<_Array_ptr<int>> px2 = &(x); // expected-error {{cannot take address of variable 'x' with bounds}}
|
||||
_Ptr<_Array_ptr<int>> px3 = (&x); // expected-error {{cannot take address of variable 'x' with bounds}}
|
||||
_Ptr<_Array_ptr<int>> pg = &global_var2; // expected-error {{cannot take address of variable 'global_var2' with bounds}}
|
||||
int* _Array *_Single pg = &global_var2; // expected-error {{cannot take address of variable 'global_var2' with bounds}}
|
||||
|
||||
_Ptr<int _Checked[]> parr1 = &global_arr2;
|
||||
_Ptr<int _Checked[]> parr2 = &(global_arr2);
|
||||
|
|
|
@ -13,7 +13,7 @@ int gtmp;
|
|||
int *g1 = >mp;
|
||||
ptr<int> g2 = >mp;
|
||||
array_ptr<int> g3 = >mp;
|
||||
array_ptr<int> g4 : count(1) = >mp;
|
||||
int* _Array g4 _Count(1) = >mp;
|
||||
|
||||
|
||||
extern void check_exprs(int *arg1, ptr<int> arg2, array_ptr<int> arg3,
|
||||
|
@ -31,7 +31,7 @@ extern void check_exprs(int *arg1, ptr<int> arg2, array_ptr<int> arg3,
|
|||
array_ptr<int> arr1 : count(3) = (int checked[3]){0, 1, 2};
|
||||
array_ptr<int> arr2 : count(4) = (int checked[3]){0, 1, 2}; // expected-error {{declared bounds for 'arr2' are invalid after initialization}}
|
||||
array_ptr<struct S1> arr_struct1 : count(1) = &(struct S1){0};
|
||||
array_ptr<struct S1> arr_struct2 : count(2) = &(struct S1){0}; // expected-error {{declared bounds for 'arr_struct2' are invalid after initialization}}
|
||||
struct S1* _Array arr_struct2 _Count(2) = &(struct S1){0}; // expected-error {{declared bounds for 'arr_struct2' are invalid after initialization}}
|
||||
|
||||
// TODO: assignments of variables with array types
|
||||
// to pointer variables, and reads/writes of struct members.
|
||||
|
@ -119,7 +119,7 @@ extern void check_exprs(int *arg1, ptr<int> arg2, array_ptr<int> arg3,
|
|||
int *t1 = &tmp1;
|
||||
ptr<int> t2 = &tmp1;
|
||||
array_ptr<int> t3 = &tmp1;
|
||||
array_ptr<int> t4 : count(1) = &tmp1;
|
||||
int* _Array t4 : count(1) = &tmp1;
|
||||
|
||||
t1 = arg1;
|
||||
t2 = arg1; // expected-error {{expression has unknown bounds}}
|
||||
|
@ -212,12 +212,12 @@ extern void check_exprs(int *arg1, ptr<int> arg2, array_ptr<int> arg3,
|
|||
|
||||
nt_array_ptr<int> g11 : bounds(unknown) = 0;
|
||||
nt_array_ptr<int> g12 = (int nt_checked[]) { 1, 0 }; // default bounds of count(0);
|
||||
nt_array_ptr<int> g13 : count(1) = (int nt_checked[]) { 1, 0 };
|
||||
int* _Nt_array g13 _Count(1) = (int nt_checked[]) { 1, 0 };
|
||||
|
||||
struct S2 {
|
||||
nt_array_ptr<int> f1 : bounds(unknown);
|
||||
nt_array_ptr<int> f2;
|
||||
nt_array_ptr<int> f3 : count(1);
|
||||
int* _Nt_array f3 _Count(1);
|
||||
};
|
||||
|
||||
extern void check_exprs_nullterm(nt_array_ptr<int> arg1 : bounds(unknown),
|
||||
|
@ -231,7 +231,7 @@ extern void check_exprs_nullterm(nt_array_ptr<int> arg1 : bounds(unknown),
|
|||
arg3 = 0;
|
||||
arg1 = (nt_array_ptr<int>)0xabcd;
|
||||
arg2 = (nt_array_ptr<int>)0xabcd; // expected-error {{inferred bounds for 'arg2' are unknown after assignment}}
|
||||
arg3 = (nt_array_ptr<int>)0xabcd; // expected-error {{inferred bounds for 'arg3' are unknown after assignment}}
|
||||
arg3 = (int* _Nt_array)0xabcd; // expected-error {{inferred bounds for 'arg3' are unknown after assignment}}
|
||||
|
||||
// address-of
|
||||
arg1 = &*arg1;
|
||||
|
@ -291,7 +291,7 @@ extern void check_exprs_nullterm(nt_array_ptr<int> arg1 : bounds(unknown),
|
|||
// locals assigned from parameters
|
||||
nt_array_ptr<int> t1 : bounds(unknown);
|
||||
nt_array_ptr<int> t2 = 0;
|
||||
nt_array_ptr<int> t3 : count(1) = 0;
|
||||
int* _Nt_array t3 _Count(1) = 0;
|
||||
|
||||
t1 = arg1;
|
||||
t2 = arg1; // expected-error {{inferred bounds for 't2' are unknown after assignment}}
|
||||
|
@ -311,7 +311,7 @@ extern void check_exprs_nullterm(nt_array_ptr<int> arg1 : bounds(unknown),
|
|||
int i1;
|
||||
nt_array_ptr<int> c2 : count(u1) = 0;
|
||||
nt_array_ptr<int> c3 : count(u1 * u2 + 2 * i1) = 0;
|
||||
nt_array_ptr<int> c4 : count(i1) = 0;
|
||||
int* _Nt_array c4 _Count(i1) = 0;
|
||||
|
||||
c1 = c2;
|
||||
c2 = c1; // expected-error {{it is not possible to prove that the inferred bounds of 'c2' imply the declared bounds of 'c2' after assignment}}
|
||||
|
@ -425,7 +425,7 @@ extern void test_f6(array_ptr<int> p : count(0));
|
|||
|
||||
extern void check_call_args(int *arg1, ptr<int> arg2, array_ptr<int> arg3,
|
||||
array_ptr<int> arg4 : count(1),
|
||||
array_ptr<int> arg5 : count(arglen), int arglen,
|
||||
int* _Array arg5 _Count(arglen), int arglen,
|
||||
array_ptr<int> arg6 : count(arglen_u), unsigned int arglen_u) {
|
||||
test_f1(arg1);
|
||||
test_f2(arg1); // expected-error {{expression has unknown bounds}}
|
||||
|
@ -480,7 +480,7 @@ extern void check_nullterm_call_args(
|
|||
nt_array_ptr<char> arg2,
|
||||
nt_array_ptr<char> arg3 : count(1),
|
||||
nt_array_ptr<char> arg4 : count(arglen), int arglen,
|
||||
nt_array_ptr<char> arg5 : count(arglen_u), unsigned int arglen_u) {
|
||||
char* _Nt_array arg5 _Count(arglen_u), unsigned int arglen_u) {
|
||||
test_nullterm_f1(arg1);
|
||||
test_nullterm_f2(arg1); // expected-error {{argument has unknown bounds}}
|
||||
test_nullterm_f3(arg1); // expected-error {{argument has unknown bounds}}
|
||||
|
@ -520,14 +520,14 @@ extern void test_bsi_f1(int *p);
|
|||
extern void test_bsi_f2(int *p : itype(ptr<int>));
|
||||
extern void test_bsi_f3(int *p : itype(array_ptr<int>));
|
||||
extern void test_bsi_f4(int *p : count(1));
|
||||
extern void test_bsi_f5(int *p : count(len), int len);
|
||||
extern void test_bsi_f5(int *p _Count(len), int len);
|
||||
extern void test_bsi_f6(int((*compar)(const int *, const int *)) :
|
||||
itype(_Ptr<int(_Ptr<const int>, _Ptr<const int>)>));
|
||||
extern int test_cmp(_Ptr<const int> a, _Ptr<const int> b);
|
||||
|
||||
extern void check_call_bsi(int *arg1, ptr<int> arg2, array_ptr<int> arg3,
|
||||
array_ptr<int> arg4 : count(1),
|
||||
array_ptr<int> arg5 : count(arglen), int arglen) {
|
||||
int* _Array arg5 : count(arglen), int arglen) {
|
||||
test_bsi_f1(arg1); // no checking expected when passing unchecked pointers.
|
||||
test_bsi_f2(arg1);
|
||||
test_bsi_f3(arg1);
|
||||
|
@ -583,7 +583,7 @@ extern int test_nullterm_cmp(nt_array_ptr<const int> a, nt_array_ptr<const int>
|
|||
extern void check_nullterm_call_bsi(int *arg1 : itype(nt_array_ptr<int>),
|
||||
nt_array_ptr<int> arg2 : bounds(unknown),
|
||||
nt_array_ptr<int> arg3,
|
||||
nt_array_ptr<int> arg4 : count(1),
|
||||
int* _Nt_array arg4 _Count(1),
|
||||
nt_array_ptr<int> arg5 : count(arglen),
|
||||
int arglen,
|
||||
int **arg6,
|
||||
|
@ -631,7 +631,7 @@ extern void check_nullterm_call_bsi(int *arg1 : itype(nt_array_ptr<int>),
|
|||
}
|
||||
}
|
||||
|
||||
nt_array_ptr<char> nullterm_return1(void);
|
||||
char* _Nt_array nullterm_return1(void);
|
||||
nt_array_ptr<char> nullterm_return2(void) : bounds(unknown);
|
||||
|
||||
void check_nullterm_return_use(void) {
|
||||
|
@ -639,7 +639,7 @@ void check_nullterm_return_use(void) {
|
|||
p = nullterm_return2(); // expected-error {{inferred bounds for 'p' are unknown after assignment}}
|
||||
}
|
||||
|
||||
nt_array_ptr<char> check_nullterm_return1(void) {
|
||||
char* _Nt_array check_nullterm_return1(void) {
|
||||
nt_array_ptr<char> p : bounds(unknown) = 0;
|
||||
return p; // expected-error {{return value has unknown bounds, bounds expected because the function 'check_nullterm_return1' has bounds}}
|
||||
}
|
||||
|
|
|
@ -7,10 +7,10 @@
|
|||
|
||||
void f1()
|
||||
_Checked{
|
||||
_Array_ptr<int> p : count(2) = 0;
|
||||
_Array_ptr<int> p _Count(2) = 0;
|
||||
int val = 5;
|
||||
int val1 _Checked[3];
|
||||
_Array_ptr<int> q : count(1) = &val;
|
||||
_Array_ptr<int> q _Count(1) = &val;
|
||||
_Bundled {
|
||||
p = q;
|
||||
*(p+1) = 4; // expected-error {{out-of-bounds memory access}}
|
||||
|
@ -26,7 +26,7 @@ _Checked{
|
|||
_Array_ptr<int> p : count(2) = 0;
|
||||
int val = 5;
|
||||
int val1 _Checked[3];
|
||||
_Array_ptr<int> q : count(1) = &val;
|
||||
int* _Array q _Count(1) = &val;
|
||||
_Bundled {
|
||||
p = val1; // expected-warning {{cannot prove declared bounds for 'p' are valid after assignment}}
|
||||
p++;
|
||||
|
@ -44,7 +44,7 @@ _Checked{
|
|||
_Array_ptr<int> p : count(2) = 0;
|
||||
int val = 5;
|
||||
int val1 _Checked[3];
|
||||
_Array_ptr<int> q : count(1) = &val;
|
||||
int* _Array q _Count(1) = &val;
|
||||
_Bundled {
|
||||
p = q,
|
||||
*(p+1) = 4, // expected-error {{out-of-bounds memory access}}
|
||||
|
@ -63,7 +63,7 @@ _Checked{
|
|||
_Array_ptr<int> p : count(2) = 0;
|
||||
int val = 5;
|
||||
int val1 _Checked[8];
|
||||
_Array_ptr<int> q : count(1) = &val;
|
||||
int* _Array q : count(1) = &val;
|
||||
_Bundled {
|
||||
p = val1; // expected-warning {{cannot prove declared bounds for 'p' are valid after assignment}}
|
||||
p++;
|
||||
|
@ -81,7 +81,7 @@ _Checked{
|
|||
_Array_ptr<int> p : count(2) = 0;
|
||||
int val = 5;
|
||||
int val1 _Checked[3];
|
||||
_Array_ptr<int> q : count(1) = &val;
|
||||
int* _Array q : count(1) = &val;
|
||||
_Bundled {
|
||||
p = flag ? q : val1;
|
||||
*(p+1) = 4; // expected-error {{expression has unknown bounds}}
|
||||
|
@ -94,7 +94,7 @@ _Checked{
|
|||
|
||||
void f6(int flag)
|
||||
_Checked{
|
||||
_Array_ptr<int> p : count(2) = 0;
|
||||
int* _Array p _Count(2) = 0;
|
||||
int val = 5;
|
||||
int val1 _Checked[3];
|
||||
_Array_ptr<int> q : count(1) = &val;
|
||||
|
@ -138,7 +138,7 @@ _Checked{
|
|||
_Array_ptr<int> p : count(2) = 0;
|
||||
int val = 5;
|
||||
int val1 _Checked[3];
|
||||
_Array_ptr<int> q : count(1) = &val;
|
||||
_Array_ptr<int> q _Count(1) = &val;
|
||||
p = val1;
|
||||
p++;
|
||||
p++;
|
||||
|
@ -150,10 +150,10 @@ _Checked{
|
|||
|
||||
void f9(int flag)
|
||||
_Checked{
|
||||
_Array_ptr<int> p : count(2) = 0;
|
||||
_Array_ptr<int> p _Count(2) = 0;
|
||||
int val = 5;
|
||||
int val1 _Checked[3];
|
||||
_Array_ptr<int> q : count(1) = &val;
|
||||
int* _Array q _Count(1) = &val;
|
||||
p = val1,
|
||||
p++,
|
||||
p++,
|
||||
|
@ -166,7 +166,7 @@ _Checked{
|
|||
int val = 5;
|
||||
_Array_ptr<int> q : count(2) = &val; // expected-error {{declared bounds for 'q' are invalid after initialization}}
|
||||
_Bundled {
|
||||
_Array_ptr<int> r : count(2) = &val; // expected-error {{declared bounds for 'r' are invalid after initialization}}
|
||||
int* _Array r _Count(2) = &val; // expected-error {{declared bounds for 'r' are invalid after initialization}}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -174,7 +174,7 @@ void f11()
|
|||
_Checked{
|
||||
int val = 5;
|
||||
int valarr _Checked[4];
|
||||
_Array_ptr<int> q : count(2) = &val; // expected-error {{declared bounds for 'q' are invalid after initialization}}
|
||||
int* _Array q _Count(2) = &val; // expected-error {{declared bounds for 'q' are invalid after initialization}}
|
||||
_Bundled {
|
||||
_Array_ptr<int> r : count(2) = &val;
|
||||
r = valarr;
|
||||
|
@ -186,7 +186,7 @@ _Checked{
|
|||
_Array_ptr<int> p : count(2) = 0;
|
||||
int val = 5;
|
||||
int val1 _Checked[3];
|
||||
_Array_ptr<int> q : count(1) = &val;
|
||||
int* _Array q _Count(1) = &val;
|
||||
L1:
|
||||
_Bundled {
|
||||
p = val1;
|
||||
|
@ -202,8 +202,7 @@ _Checked{
|
|||
|
||||
extern _Array_ptr<int> my_malloc(int len) : count(len);
|
||||
extern void copy1(_Array_ptr<int> to, _Array_ptr<int> from : count(n), int n);
|
||||
extern _Array_ptr<int> copy2(_Array_ptr<int> to, _Array_ptr<int> from : count(n), int n, int new_n) : count(new_n);
|
||||
|
||||
extern int* _Array copy2(int* _Array to, int* _Array from _Count(n), int n, int new_n) _Count(new_n);
|
||||
|
||||
_Array_ptr<int> resize1(_Array_ptr<int> buf : count(buflen), int buflen, int len) : count(len) {
|
||||
_Array_ptr<int> tmp : count(len) = my_malloc(len);
|
||||
|
@ -216,7 +215,7 @@ _Array_ptr<int> resize1(_Array_ptr<int> buf : count(buflen), int buflen, int len
|
|||
}
|
||||
|
||||
int buflen = 0;
|
||||
_Array_ptr<int> buf : count(buflen) = 0;
|
||||
_Array_ptr<int> buf _Count(buflen) = 0;
|
||||
|
||||
void resize2(int newlen) {
|
||||
_Array_ptr<int> tmp : count(newlen) = my_malloc(newlen);
|
||||
|
@ -235,7 +234,7 @@ _Array_ptr<int> g4 : count(1) = >mp;
|
|||
int *h1 = >mp;
|
||||
_Ptr<int> h2 = >mp;
|
||||
_Array_ptr<int> h3 = >mp;
|
||||
_Array_ptr<int> h4 : count(1) = >mp;
|
||||
int* _Array h4 _Count(1) = >mp;
|
||||
|
||||
|
||||
void gf0(void) {
|
||||
|
@ -314,8 +313,8 @@ extern void test_bsi_f6(int((*compar)(const int *, const int *)) :
|
|||
extern int test_cmp(_Ptr<const int> a, _Ptr<const int> b);
|
||||
|
||||
extern void check_call_bsi(int *arg1, _Ptr<int> arg2, _Array_ptr<int> arg3,
|
||||
_Array_ptr<int> arg4 : count(1),
|
||||
_Array_ptr<int> arg5 : count(arglen), int arglen) {
|
||||
int* _Array arg4 _Count(1),
|
||||
int* _Array arg5 _Count(arglen), int arglen) {
|
||||
|
||||
_Bundled {
|
||||
test_bsi_f1(arg1); // no checking expected when passing unchecked pointers.
|
||||
|
@ -388,14 +387,14 @@ struct Node {
|
|||
};
|
||||
|
||||
struct Group {
|
||||
_Array_ptr<struct Node> list : count (n);
|
||||
struct Node* _Array list _Count(n);
|
||||
unsigned int n;
|
||||
};
|
||||
|
||||
extern unsigned int my_strlen(_Nt_array_ptr<char>);
|
||||
|
||||
// get the first name that starts with the letters 'Ar'
|
||||
_Nt_array_ptr<char> get_name(_Array_ptr<struct Group> groups : count(gcnt), unsigned int gcnt)
|
||||
char* _Nt_array get_name(_Array_ptr<struct Group> groups : count(gcnt), unsigned int gcnt)
|
||||
_Checked {
|
||||
unsigned int n = 0;
|
||||
_Array_ptr<struct Node> group : count(n) = 0;
|
||||
|
@ -407,7 +406,7 @@ _Checked {
|
|||
}
|
||||
for (int j = 0; j < n; j++) {
|
||||
_Nt_array_ptr<char> name = group[j].name;
|
||||
unsigned int m = my_strlen(name) _Where name : count(m);
|
||||
unsigned int m = my_strlen(name) _Where (name : count(m));
|
||||
if (m >= 2 && name[0] == 'A' && name[1] == 'r')
|
||||
return name;
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ extern void f1() {
|
|||
array_ptr<int> v7 : byte_count(5 * sizeof(int)) = 0;
|
||||
array_ptr<int> v8 : byte_count(5 * sizeof(int)); // expected-error {{automatic variable 'v8' with bounds must have initializer}}
|
||||
array_ptr<int> v9 : bounds(v9, v9 + 5) = 0;
|
||||
array_ptr<int> v10 : bounds(v10, v10 + 5); // expected-error {{automatic variable 'v10' with bounds must have initializer}}
|
||||
int* _Array v10 _Bounds(v10, v10 + 5); // expected-error {{automatic variable 'v10' with bounds must have initializer}}
|
||||
|
||||
ptr<int> v20 = 0;
|
||||
ptr<int> v21; // expected-error {{automatic variable 'v21' with _Ptr type must have initializer}}
|
||||
|
@ -50,7 +50,7 @@ nt_array_ptr<int> g31 : count(0) = (int checked[]) { 0, [2] = 2, 3, 5, 0 };
|
|||
nt_array_ptr<char> g32 : count(5) = "abcde";
|
||||
array_ptr<char> g33 : count(5) = "abcde";
|
||||
array_ptr<char> g34 : count(5) = (char[5]) { 'a', 'b', 'c', 'd', 'e' };
|
||||
array_ptr<char> g35 : count(5) = (char checked[5]) { 'a', 'b', 'c', 'd', 'e' };
|
||||
char* _Array g35 _Count(5) = (char checked[5]) { 'a', 'b', 'c', 'd', 'e' };
|
||||
|
||||
//
|
||||
// Checked arrays of checked pointers
|
||||
|
@ -61,7 +61,7 @@ nt_array_ptr<char> g37 nt_checked[] = { "the", "brown", "fox", "jumped",
|
|||
|
||||
void callback1(int a);
|
||||
void callback2(int a);
|
||||
nt_array_ptr<ptr<void(int)>> callback_table = (ptr<void(int)>[]) { callback1, callback2, 0 };
|
||||
void(*_Single *_Nt_array callback_table)(int) = (ptr<void(int)>[]) { callback1, callback2, 0 };
|
||||
|
||||
void f3(char *escape) {
|
||||
}
|
||||
|
@ -122,8 +122,8 @@ void f5(void) checked {
|
|||
nt_array_ptr<char> t32 : count(5) = "abcde";
|
||||
|
||||
array_ptr<char> t33 : count(5) = "abcde";
|
||||
array_ptr<char> t34 = (char[5]) { 'a', 'b', 'c', 'd', 'e' };
|
||||
array_ptr<char> t35 : count(5) = (char checked[5]) { 'a', 'b', 'c', 'd', 'e' };
|
||||
char* _Array t34 = (char[5]) { 'a', 'b', 'c', 'd', 'e' };
|
||||
char* _Array t35 _Count(5) = (char checked[5]) { 'a', 'b', 'c', 'd', 'e' };
|
||||
|
||||
//
|
||||
// Make sure parentheses are ignored.
|
||||
|
@ -135,8 +135,8 @@ void f5(void) checked {
|
|||
// Checked arrays of checked pointers.
|
||||
//
|
||||
nt_array_ptr<char> t38 checked[3][2] = { [1] = "ab", "cd", "ef", "jk" };
|
||||
nt_array_ptr<char> t39 nt_checked[] = { "the", "brown", "fox", "jumped",
|
||||
"over", "the", "fence", 0 };
|
||||
char* _Nt_array t39 nt_checked[] = { "the", "brown", "fox", "jumped",
|
||||
"over", "the", "fence", 0 };
|
||||
|
||||
char c = ((char *[2]) { "abc", "def" })[0][0]; // expected-error {{type in a checked\
|
||||
scope must use only checked types or parameter/return types with bounds-safe interfaces}}
|
||||
|
@ -147,7 +147,7 @@ void f5(void) checked {
|
|||
void f6(void) {
|
||||
ptr<int> p = 0; // initializer required.
|
||||
array_ptr<int> q : count(5) = 0; // has bounds; initializer required.
|
||||
array_ptr<int> lower, upper; // no bounds; initializer not required.
|
||||
int* _Array lower,* _Array upper; // no bounds; initializer not required.
|
||||
lower = q;
|
||||
upper = q + 5;
|
||||
|
||||
|
@ -172,7 +172,7 @@ void f6(void) {
|
|||
// Check { 0 } initialization idiom where first member is a floating point number.
|
||||
struct FloatWithVariableBuffer {
|
||||
float weight;
|
||||
array_ptr<int> buf : count(len);
|
||||
int* _Array buf _Count(len);
|
||||
int len;
|
||||
};
|
||||
|
||||
|
@ -193,8 +193,8 @@ void f6(void) {
|
|||
|
||||
struct checked_value_no_bounds {
|
||||
int x;
|
||||
array_ptr<int> lower;
|
||||
array_ptr<int> upper;
|
||||
int* _Array lower;
|
||||
int* _Array upper;
|
||||
float y;
|
||||
};
|
||||
|
||||
|
@ -206,8 +206,8 @@ void f6(void) {
|
|||
|
||||
struct checked_value_has_bounds {
|
||||
int x;
|
||||
array_ptr<char> lower : count(5);
|
||||
array_ptr<char> upper : count(5);
|
||||
array_ptr<char> lower _Count(5);
|
||||
array_ptr<char> upper _Count(5);
|
||||
float y;
|
||||
};
|
||||
|
||||
|
@ -232,8 +232,8 @@ void f6(void) {
|
|||
|
||||
union u_checked_value_has_bounds {
|
||||
int x;
|
||||
array_ptr<char> lower : count(5);
|
||||
array_ptr<char> upper : count(5);
|
||||
char* _Array lower : count(5);
|
||||
char* _Array upper : count(5);
|
||||
float y;
|
||||
};
|
||||
union u_checked_value_has_bounds init_U2 = { 0 }; // has bounds; initializer required and we did, should pass
|
||||
|
@ -250,7 +250,7 @@ void f6(void) {
|
|||
|
||||
typedef struct {
|
||||
int data;
|
||||
array_ptr<char> name : count(20);
|
||||
array_ptr<char> name _Count(20);
|
||||
struct Node* next;
|
||||
} Node;
|
||||
|
||||
|
@ -354,7 +354,7 @@ void f11 (void) checked {
|
|||
//a struct with unchecked pointers with bounds exprs in a checked scope
|
||||
typedef struct {
|
||||
int x;
|
||||
int* p : count(1);
|
||||
int* p _Count(1);
|
||||
char* cp : count(5);
|
||||
} S;
|
||||
S s1; // expected-error {{containing an unchecked pointer with a bounds expression in a checked scope must have an initializer}}
|
||||
|
|
|
@ -11,6 +11,10 @@
|
|||
// expression first. Then we check against prior kinds of expressions. //
|
||||
//--------------------------------------------------------------------------//
|
||||
|
||||
#define _Dynamic_bounds_cast_M(T, e1, ... ) _Dynamic_bounds_cast<T>(e1, __VA_ARGS__)
|
||||
#define _Dynamic_bounds_cast_M_N(T, e1 ) _Dynamic_bounds_cast<T>(e1)
|
||||
#define _Assume_bounds_cast_M(T, e1, ... ) _Assume_bounds_cast<T>(e1, __VA_ARGS__)
|
||||
#define _Assume_bounds_cast_M_N(T, e1 ) _Assume_bounds_cast<T>(e1)
|
||||
|
||||
//--------------------------------------------------------------------------//
|
||||
// Constants //
|
||||
|
@ -25,13 +29,13 @@ extern int f1_1(_Array_ptr<int> p : count(0));
|
|||
extern int f1_2(_Array_ptr<int> p : count(1));
|
||||
extern int f1_2(_Array_ptr<int> p : count(1));
|
||||
extern int f1_3(_Array_ptr<int> p : count(5));
|
||||
extern int f1_3(_Array_ptr<int> p : count(5));
|
||||
extern int f1_3(int* _Array p _Count(5));
|
||||
|
||||
// Integer constant inequality
|
||||
extern int f1_4(_Array_ptr<int> p : count(0));
|
||||
extern int f1_4(_Array_ptr<int> p : count(1)); // expected-error {{conflicting parameter bounds}}
|
||||
extern int f1_5(_Array_ptr<int> p : count(0));
|
||||
extern int f1_5(_Array_ptr<int> p : count(5)); // expected-error {{conflicting parameter bounds}}
|
||||
extern int f1_5(int* _Array p _Count(5)); // expected-error {{conflicting parameter bounds}}
|
||||
|
||||
// Character constant equality
|
||||
extern int f1_6(_Array_ptr<int> p : count('a'));
|
||||
|
@ -43,7 +47,7 @@ extern int f1_7(_Array_ptr<int> p : count('b')); // expected-error {{confl
|
|||
|
||||
// Character constant vs. integer constant inequality
|
||||
extern int f1_8(_Array_ptr<int> p : count(0));
|
||||
extern int f1_8(_Array_ptr<int> p : count('a')); // expected-error {{conflicting parameter bounds}}
|
||||
extern int f1_8(int* _Array p _Count('a')); // expected-error {{conflicting parameter bounds}}
|
||||
|
||||
|
||||
// Floating-point constants,
|
||||
|
@ -76,7 +80,7 @@ extern int f3_1(_Array_ptr<int> p : count((int) 0.0F));
|
|||
extern int f3_2(_Array_ptr<int> p : count((int) 5.0f));
|
||||
extern int f3_2(_Array_ptr<int> p : count((int) 5.0f));
|
||||
extern int f3_2(_Array_ptr<int> p : count((int) 5.0F));
|
||||
extern int f3_2(_Array_ptr<int> p : count((int) 5.0F));
|
||||
extern int f3_2(int* _Array p _Count((int) 5.0F));
|
||||
|
||||
// Inequality of floating point constants with type float.
|
||||
extern int f4_1(_Array_ptr<int> p : count((int) 0.0f));
|
||||
|
@ -84,14 +88,14 @@ extern int f4_1(_Array_ptr<int> p : count((int) 5.0f)); // expected-error {{con
|
|||
extern int f4_2(_Array_ptr<int> p : count((int) 0.0F));
|
||||
extern int f4_2(_Array_ptr<int> p : count((int) 5.0F)); // expected-error {{conflicting parameter bounds}}
|
||||
extern int f4_3(_Array_ptr<int> p : count((int) 0.0f));
|
||||
extern int f4_3(_Array_ptr<int> p : count((int) 5.0F)); // expected-error {{conflicting parameter bounds}}
|
||||
extern int f4_3(int* _Array p _Count((int) 5.0F)); // expected-error {{conflicting parameter bounds}}
|
||||
|
||||
// Inequality of floating point constants with type float and type double.
|
||||
|
||||
extern int f5_1(_Array_ptr<int> p : count((int) 0.0));
|
||||
extern int f5_1(_Array_ptr<int> p : count((int) 0.0f)); // expected-error {{conflicting parameter bounds}}
|
||||
extern int f5_2(_Array_ptr<int> p : count((int) 0.0));
|
||||
extern int f5_2(_Array_ptr<int> p : count((int) 0.0F)); // expected-error {{conflicting parameter bounds}}
|
||||
extern int f5_2(int* _Array p _Count((int) 0.0F)); // expected-error {{conflicting parameter bounds}}
|
||||
|
||||
// Equality of floating point constants with type long double.
|
||||
extern int f6_1(_Array_ptr<int> p : count((int) 0.0l));
|
||||
|
@ -99,7 +103,7 @@ extern int f6_1(_Array_ptr<int> p : count((int) 1.0l)); // expected-error {{con
|
|||
extern int f6_2(_Array_ptr<int> p : count((int) 0.0l));
|
||||
extern int f6_2(_Array_ptr<int> p : count((int) 5.0L)); // expected-error {{conflicting parameter bounds}}
|
||||
extern int f6_3(_Array_ptr<int> p : count((int) 0.0l));
|
||||
extern int f6_3(_Array_ptr<int> p : count((int) 5.0l)); // expected-error {{conflicting parameter bounds}}
|
||||
extern int f6_3(int* _Array p _Count((int) 5.0l)); // expected-error {{conflicting parameter bounds}}
|
||||
|
||||
// Inequality of floating point constants with type double and type
|
||||
// long double.
|
||||
|
@ -115,7 +119,7 @@ extern int f7_2(_Array_ptr<int> p : count((int) 0.0L)); // expected-error {{con
|
|||
extern int f8_1(_Array_ptr<int> p : count((int) 0.0f));
|
||||
extern int f8_1(_Array_ptr<int> p : count((int) 0.0l)); // expected-error {{conflicting parameter bounds}}
|
||||
extern int f8_2(_Array_ptr<int> p : count((int) 0.0f));
|
||||
extern int f8_2(_Array_ptr<int> p : count((int) 0.0L)); // expected-error {{conflicting parameter bounds}}
|
||||
extern int f8_2(int* _Array p _Count((int) 0.0L)); // expected-error {{conflicting parameter bounds}}
|
||||
|
||||
// We omit inequality of floating point constants and integer constants. We
|
||||
// insert an explicit cast for integers so that the enclosing expressions
|
||||
|
@ -126,7 +130,7 @@ extern int f9_1(_Array_ptr<int> p : count((int) 0.0)); // expected-error {{conf
|
|||
extern int f9_2(_Array_ptr<int> p : count((int) 5));
|
||||
extern int f9_2(_Array_ptr<int> p : count((int) 5.0f)); // expected-error {{conflicting parameter bounds}}
|
||||
extern int f9_3(_Array_ptr<int> p : count((int) 150));
|
||||
extern int f9_3(_Array_ptr<int> p : count((int) 1.5e2L)); // expected-error {{conflicting parameter bounds}}
|
||||
extern int f9_3(int* _Array p _Count((int) 1.5e2L)); // expected-error {{conflicting parameter bounds}}
|
||||
|
||||
//-----------------------------------------------------//
|
||||
// Variables //
|
||||
|
@ -141,7 +145,7 @@ extern _Array_ptr<int> arr1_1 : count(arr1_len);
|
|||
|
||||
// Global variable inequality.
|
||||
extern _Array_ptr<int> arr1_2 : count(arr1_len);
|
||||
extern _Array_ptr<int> arr1_2 : count(arr2_len); // expected-error {{variable redeclaration has conflicting bounds}}
|
||||
extern int* _Array arr1_2 _Count(arr2_len); // expected-error {{variable redeclaration has conflicting bounds}}
|
||||
|
||||
// Parameter variable equality. Positions of arguments matter, not
|
||||
// variable names.
|
||||
|
@ -152,7 +156,7 @@ extern int f20_2(int d, _Array_ptr<int> arr1 : count(d));
|
|||
|
||||
// Parameter variable inequality.
|
||||
extern int f20_3(_Array_ptr<int> arr1 : count(a), int a, int b);
|
||||
extern int f20_3(_Array_ptr<int> arr1 : count(b), int a, int b); // expected-error {{conflicting parameter bounds}}
|
||||
extern int f20_3(int* _Array arr1 _Count(b), int a, int b); // expected-error {{conflicting parameter bounds}}
|
||||
|
||||
// We can't check parameter variable vs. global variable inequality just
|
||||
// using redeclarations of functions. Parameter bounds can only refer to
|
||||
|
@ -165,7 +169,7 @@ extern _Array_ptr<int> arr1_3 : count(arr1_len); // expected-error {{variable re
|
|||
|
||||
// Parameter variable vs. constant inequality.
|
||||
extern int f21_1(_Array_ptr<int> arr1 : count(len), int len);
|
||||
extern int f21_1(_Array_ptr<int> arr1 : count(5), int len); // expected-error {{conflicting parameter bounds}}
|
||||
extern int f21_1(int* _Array arr1 _Count(5), int len); // expected-error {{conflicting parameter bounds}}
|
||||
|
||||
//-----------------------------------------------------//
|
||||
// Unary operator expressions. //
|
||||
|
@ -189,8 +193,8 @@ extern int f30_6(int a, _Array_ptr<int> p : count(!a));
|
|||
extern int f30_6(int a, _Array_ptr<int> p : count(!a));
|
||||
extern int f30_7(int a, _Array_ptr<int> p : byte_count(sizeof(a)));
|
||||
extern int f30_7(int a, _Array_ptr<int> p : byte_count(sizeof(a)));
|
||||
extern int f30_8(int a, _Array_ptr<int> p : byte_count(sizeof(int[2])));
|
||||
extern int f30_8(int a, _Array_ptr<int> p : byte_count(sizeof(int[2])));
|
||||
extern int f30_8(int a, int* _Array p _Byte_count(sizeof(int[2])));
|
||||
extern int f30_8(int a, int* _Array p _Byte_count(sizeof(int[2])));
|
||||
|
||||
// Inequality of integer unary operator expressions. The argument expression
|
||||
// and enclosing expression are identical; only the operators
|
||||
|
@ -222,8 +226,8 @@ extern int f31_8(_Array_ptr<int> p : count(sizeof(a)), int a);
|
|||
extern int f31_8(_Array_ptr<int> p : count(+a), int a); // expected-error {{conflicting parameter bounds}}
|
||||
extern int f31_9(_Array_ptr<int> p : count(sizeof(a)), int a);
|
||||
extern int f31_9(_Array_ptr<int> p : count(~a), int a); // expected-error {{conflicting parameter bounds}}
|
||||
extern int f31_10(_Array_ptr<int> p : count(sizeof(a)), int a);
|
||||
extern int f31_10(_Array_ptr<int> p : count(!a), int a); // expected-error {{conflicting parameter bounds}}
|
||||
extern int f31_10(int* _Array p _Count(sizeof(a)), int a);
|
||||
extern int f31_10(int* _Array p _Count(!a), int a); // expected-error {{conflicting parameter bounds}}
|
||||
|
||||
// inequality of sizeof(expression) vs. size(type).
|
||||
extern int f31_11(int a, _Array_ptr<int> p : byte_count(sizeof(a)));
|
||||
|
@ -234,8 +238,8 @@ extern int f32_1(int a, _Array_ptr<int> p : bounds(&arr4[5], &arr4[50]));
|
|||
extern int f32_1(int a, _Array_ptr<int> p : bounds(&arr4[6], &arr4[50])); // expected-error {{conflicting parameter bounds}}
|
||||
|
||||
// Inequality of dereference expressions
|
||||
extern int f32_2(_Ptr<int> plen, _Array_ptr<int> p : count(*plen), _Ptr<int> slen);
|
||||
extern int f32_2(_Ptr<int> plen, _Array_ptr<int> p : count(*slen), _Ptr<int> slen); // expected-error {{conflicting parameter bounds}}
|
||||
extern int f32_2(int* _Single plen, int* _Array p _Count(*plen), int* _Single slen);
|
||||
extern int f32_2(int* _Single plen, int* _Array p _Count(*slen), int* _Single slen); // expected-error {{conflicting parameter bounds}}
|
||||
|
||||
// Inequality of dereference expressions vs. other unary operators
|
||||
extern int f32_3(_Ptr<int> plen, _Array_ptr<int> p : count(*plen), int slen);
|
||||
|
@ -249,7 +253,7 @@ extern int f32_5(_Array_ptr<int> p : count((int) (5.0)), int a); // expected-er
|
|||
|
||||
// Inequality of unary operator expressions and variables.
|
||||
extern int f32_6(_Array_ptr<int> p : count(!a), int a);
|
||||
extern int f32_6(_Array_ptr<int> p : count(a), int a); // expected-error {{conflicting parameter bounds}}
|
||||
extern int f32_6(int* _Array p _Count(a), int a); // expected-error {{conflicting parameter bounds}}
|
||||
|
||||
//-----------------------------------------------------//
|
||||
// Binary operator expressions. //
|
||||
|
@ -263,7 +267,7 @@ extern int f40_1(int a, int b, _Array_ptr<int> p : count(a * b));
|
|||
extern int f40_2(int a, int b, _Array_ptr<int> p : count(a / b));
|
||||
extern int f40_2(int a, int b, _Array_ptr<int> p : count(a / b));
|
||||
extern int f40_3(int a, int b, _Array_ptr<int> p : count(a % b));
|
||||
extern int f40_3(int a, int b, _Array_ptr<int> p : count(a % b));
|
||||
extern int f40_3(int a, int b, int* _Array p _Count(a % b));
|
||||
|
||||
// Additive operators.
|
||||
extern int f40_4(int a, int b, _Array_ptr<int> p : count(a + b));
|
||||
|
@ -275,7 +279,7 @@ extern int f40_5(int a, int b, _Array_ptr<int> p : count(a - b));
|
|||
extern int f40_6(int a, int b, _Array_ptr<int> p : count(a << b));
|
||||
extern int f40_6(int a, int b, _Array_ptr<int> p : count(a << b));
|
||||
extern int f40_7(int a, int b, _Array_ptr<int> p : count(a >> b));
|
||||
extern int f40_7(int a, int b, _Array_ptr<int> p : count(a >> b));
|
||||
extern int f40_7(int a, int b, int* _Array p _Count(a >> b));
|
||||
|
||||
// Relational operators.
|
||||
extern int f41_1(int a, int b, _Array_ptr<int> p : count(a < b));
|
||||
|
@ -285,13 +289,13 @@ extern int f41_2(int a, int b, _Array_ptr<int> p : count(a > b));
|
|||
extern int f41_3(int a, int b, _Array_ptr<int> p : count(a <= b));
|
||||
extern int f41_3(int a, int b, _Array_ptr<int> p : count(a <= b));
|
||||
extern int f41_4(int a, int b, _Array_ptr<int> p : count(a >= b));
|
||||
extern int f41_4(int a, int b, _Array_ptr<int> p : count(a >= b));
|
||||
extern int f41_4(int a, int b, int* _Array p _Count(a >= b));
|
||||
|
||||
// Equality operators.
|
||||
extern int f41_5(int a, int b, _Array_ptr<int> p : count(a == b));
|
||||
extern int f41_5(int a, int b, _Array_ptr<int> p : count(a == b));
|
||||
extern int f41_6(int a, int b, _Array_ptr<int> p : count(a != b));
|
||||
extern int f41_6(int a, int b, _Array_ptr<int> p : count(a != b));
|
||||
extern int f41_6(int a, int b, int* _Array p _Count(a != b));
|
||||
|
||||
// Bitwise operators.
|
||||
extern int f41_7(int a, int b, _Array_ptr<int> p : count(a & b));
|
||||
|
@ -312,8 +316,8 @@ extern int f43_1(int a, _Array_ptr<int> b, _Array_ptr<int> p : bounds(b, b + a))
|
|||
extern int f43_1(int a, _Array_ptr<int> b, _Array_ptr<int> p : bounds(b, b + a));
|
||||
extern int f43_2(int a, _Array_ptr<int> b, _Array_ptr<int> p : bounds(b - a, b));
|
||||
extern int f43_2(int a, _Array_ptr<int> b, _Array_ptr<int> p : bounds(b - a, b));
|
||||
extern int f43_3(_Array_ptr<int> a, _Array_ptr<int> b, _Array_ptr<int> p : count(b - a));
|
||||
extern int f43_3(_Array_ptr<int> a, _Array_ptr<int> b, _Array_ptr<int> p : count(b - a));
|
||||
extern int f43_3(int* _Array a, int* _Array b, int* _Array p _Count(b - a));
|
||||
extern int f43_3(int* _Array a, int* _Array b, int* _Array p _Count(b - a));
|
||||
|
||||
// Inequality of binary operators on integers.
|
||||
//
|
||||
|
@ -324,7 +328,7 @@ extern int f43_3(_Array_ptr<int> a, _Array_ptr<int> b, _Array_ptr<int> p : count
|
|||
#define TESTOP /
|
||||
#define FUNC(index) NAME(50, index)
|
||||
|
||||
extern int FUNC(1)(int a, int b, _Array_ptr<int> p : count(a TESTOP b));
|
||||
extern int FUNC(1)(int a, int b, int* _Array p _Count(a TESTOP b));
|
||||
extern int FUNC(1)(int a, int b, _Array_ptr<int> p : count(a * b)); // expected-error {{conflicting parameter bounds}}
|
||||
|
||||
// Remainder vs. prior binary operators.
|
||||
|
@ -351,7 +355,7 @@ extern int FUNC(1)(int a, int b, _Array_ptr<int> p : count(a * b)); // expected
|
|||
extern int FUNC(2)(int a, int b, _Array_ptr<int> p : count(a TESTOP b));
|
||||
extern int FUNC(2)(int a, int b, _Array_ptr<int> p : count(a / b)); // expected-error {{conflicting parameter bounds}}
|
||||
|
||||
extern int FUNC(3)(int a, int b, _Array_ptr<int> p : count(a TESTOP b));
|
||||
extern int FUNC(3)(int a, int b, int* _Array p _Count(a TESTOP b));
|
||||
extern int FUNC(3)(int a, int b, _Array_ptr<int> p : count(a % b)); // expected-error {{conflicting parameter bounds}}
|
||||
|
||||
// Minus vs. prior binary operators.
|
||||
|
@ -369,7 +373,7 @@ extern int FUNC(2)(int a, int b, _Array_ptr<int> p : count(a / b)); // expected
|
|||
extern int FUNC(3)(int a, int b, _Array_ptr<int> p : count(a TESTOP b));
|
||||
extern int FUNC(3)(int a, int b, _Array_ptr<int> p : count(a % b)); // expected-error {{conflicting parameter bounds}}
|
||||
|
||||
extern int FUNC(4)(int a, int b, _Array_ptr<int> p : count(a TESTOP b));
|
||||
extern int FUNC(4)(int a, int b, int* _Array p _Count(a TESTOP b));
|
||||
extern int FUNC(4)(int a, int b, _Array_ptr<int> p : count(a + b)); // expected-error {{conflicting parameter bounds}}
|
||||
|
||||
// << vs. prior binary operators
|
||||
|
@ -390,8 +394,8 @@ extern int FUNC(3)(int a, int b, _Array_ptr<int> p : count(a % b)); // expected
|
|||
extern int FUNC(4)(int a, int b, _Array_ptr<int> p : count(a TESTOP b));
|
||||
extern int FUNC(4)(int a, int b, _Array_ptr<int> p : count(a + b)); // expected-error {{conflicting parameter bounds}}
|
||||
|
||||
extern int FUNC(5)(int a, int b, _Array_ptr<int> p : count(a TESTOP b));
|
||||
extern int FUNC(5)(int a, int b, _Array_ptr<int> p : count(a - b)); // expected-error {{conflicting parameter bounds}}
|
||||
extern int FUNC(5)(int a, int b, int* _Array p _Count(a TESTOP b));
|
||||
extern int FUNC(5)(int a, int b, int* _Array p _Count(a - b)); // expected-error {{conflicting parameter bounds}}
|
||||
|
||||
// >> vs. prior binary operators
|
||||
#undef TESTOP
|
||||
|
@ -414,8 +418,8 @@ extern int FUNC(4)(int a, int b, _Array_ptr<int> p : count(a + b)); // expected
|
|||
extern int FUNC(5)(int a, int b, _Array_ptr<int> p : count(a TESTOP b));
|
||||
extern int FUNC(5)(int a, int b, _Array_ptr<int> p : count(a - b)); // expected-error {{conflicting parameter bounds}}
|
||||
|
||||
extern int FUNC(6)(int a, int b, _Array_ptr<int> p : count(a TESTOP b));
|
||||
extern int FUNC(6)(int a, int b, _Array_ptr<int> p : count(a << b)); // expected-error {{conflicting parameter bounds}}
|
||||
extern int FUNC(6)(int a, int b, int* _Array p _Count(a TESTOP b));
|
||||
extern int FUNC(6)(int a, int b, int* _Array p _Count(a << b)); // expected-error {{conflicting parameter bounds}}
|
||||
|
||||
// < vs. prior binary operators
|
||||
#undef TESTOP
|
||||
|
@ -875,8 +879,8 @@ extern int FUNC(14)(int a, int b, _Array_ptr<int> p : count(a ^ b)); // expecte
|
|||
extern int FUNC(15)(int a, int b, _Array_ptr<int> p : count(a TESTOP b));
|
||||
extern int FUNC(15)(int a, int b, _Array_ptr<int> p : count(a | b)); // expected-error {{conflicting parameter bounds}}
|
||||
|
||||
extern int FUNC(15)(int a, int b, _Array_ptr<int> p : count(a TESTOP b));
|
||||
extern int FUNC(15)(int a, int b, _Array_ptr<int> p : count(a && b)); // expected-error {{conflicting parameter bounds}}
|
||||
extern int FUNC(15)(int a, int b, int* _Array p _Count(a TESTOP b));
|
||||
extern int FUNC(15)(int a, int b, int* _Array p _Count(a && b)); // expected-error {{conflicting parameter bounds}}
|
||||
|
||||
// Additive pointer operators.
|
||||
extern int f67_1(int a, int b, _Array_ptr<int> p : bounds(p, p + a));
|
||||
|
@ -906,7 +910,7 @@ extern int f80_1(int a, _Array_ptr<int> b, _Array_ptr<char> p : bounds(b, (_Arra
|
|||
|
||||
extern int f80_2(int a, _Array_ptr<int> b, _Array_ptr<char> p : bounds((apint) b, (apint) b + a));
|
||||
extern int f80_2(int a, _Array_ptr<int> b, _Array_ptr<char> p : bounds((apint) b, (apint) b + a));
|
||||
extern int f80_2(int a, _Array_ptr<int> b, _Array_ptr<char> p : bounds((_Array_ptr<int>) b, (_Array_ptr<int>) b + a));
|
||||
extern int f80_2(int a, int* _Array b, char* _Array p _Bounds((int* _Array) b, (int* _Array) b + a));
|
||||
|
||||
// Inequality of C-style cast operators.
|
||||
// We embed the expression being varied inside another
|
||||
|
@ -929,8 +933,8 @@ extern int f80_5(int a, _Array_ptr<int> b,
|
|||
|
||||
extern int f80_5(int a, _Array_ptr<int> b,
|
||||
_Array_ptr<char> p : bounds(b, (_Array_ptr<int>) ((apint) b + a)));
|
||||
extern int f80_5(int a, _Array_ptr<int> b,
|
||||
_Array_ptr<char> p : bounds(b, (_Array_ptr<int>) ((apchar) b + a))); // expected-error {{conflicting parameter bounds}}
|
||||
extern int f80_5(int a, int* _Array b,
|
||||
char* _Array p _Bounds(b, (int* _Array) ((apchar) b + a))); // expected-error {{conflicting parameter bounds}}
|
||||
|
||||
// Inequality of C-style cast operators vs. other expressions
|
||||
|
||||
|
@ -973,7 +977,7 @@ extern int f91_2(struct S *a, _Array_ptr<int> b : count(c->f1), struct S *c);
|
|||
extern int f91_2(struct S *a, _Array_ptr<int> b : count(c->f1), struct S *c);
|
||||
|
||||
extern int f91_3(struct S *a, _Array_ptr<int> b : count(a->f2), struct S *c);
|
||||
extern int f91_3(struct S *a, _Array_ptr<int> b : count(a->f2), struct S *c);
|
||||
extern int f91_3(struct S *a, int* _Array b _Count(a->f2), struct S *c);
|
||||
|
||||
// Inequality of member accesses
|
||||
extern int f92_1(struct S a, _Array_ptr<int> b : count(a.f1));
|
||||
|
@ -992,7 +996,7 @@ extern int f93_2(struct S *a, _Array_ptr<int> b : count(a->f1), struct S *c);
|
|||
extern int f93_2(struct S *a, _Array_ptr<int> b : count(c->f1), struct S *c); // expected-error {{conflicting parameter bounds}}
|
||||
|
||||
extern int f93_3(struct S *a, _Array_ptr<int> b : count(a->f1), struct S *c);
|
||||
extern int f93_3(struct S *a, _Array_ptr<int> b : count(c->f2), struct S *c); // expected-error {{conflicting parameter bounds}}
|
||||
extern int f93_3(struct S *a, int* _Array b _Count(c->f2), struct S *c); // expected-error {{conflicting parameter bounds}}
|
||||
|
||||
//
|
||||
// Check equality of canonicalized expressions
|
||||
|
@ -1019,8 +1023,8 @@ extern int f201_1(int a, _Array_ptr<int> b,
|
|||
|
||||
extern int f201_2(int a, _Array_ptr<int> b,
|
||||
_Array_ptr<char> p : bounds(b, (_Array_ptr<int>) (void *) b + a));
|
||||
extern int f201_2(int a, _Array_ptr<int> b,
|
||||
_Array_ptr<char> p : bounds(b, (_Array_ptr<int>) (int *) b + a));
|
||||
extern int f201_2(int a, int* _Array b,
|
||||
char* _Array p _Bounds(b, (int* _Array) (int *) b + a));
|
||||
|
||||
// Casts between signed/unsigned integers that have the same bit size.
|
||||
//
|
||||
|
@ -1043,15 +1047,15 @@ extern int f202_1(int a, _Array_ptr<int> b,
|
|||
|
||||
extern int f202_2(unsigned int a,
|
||||
_Array_ptr<int> b, _Array_ptr<char> p : bounds(b, b + a));
|
||||
extern int f202_2(unsigned int a, _Array_ptr<int> b,
|
||||
_Array_ptr<char> p : bounds(b, b + (unsigned) (int) a));
|
||||
extern int f202_2(unsigned int a, int* _Array b,
|
||||
char* _Array p _Bounds(b, b + (unsigned) (int) a));
|
||||
|
||||
// C-style casts and implicit casts to/from the same types.
|
||||
extern int f203_1(short int a, _Array_ptr<int> b : count(a + 1));
|
||||
extern int f203_1(short int a, _Array_ptr<int> b : count((int) a + 1));
|
||||
|
||||
extern int f203_2(short int a, _Array_ptr<int> b, _Array_ptr<char> p : bounds(b, b + a));
|
||||
extern int f203_2(short int a, _Array_ptr<int> b, _Array_ptr<char> p : bounds(b, b + (int) a));
|
||||
extern int f203_2(short int a, int* _Array b, char* _Array p _Bounds(b, b + (int) a));
|
||||
|
||||
//
|
||||
// & and * operations that cancel are ignored.
|
||||
|
@ -1073,9 +1077,9 @@ extern int f211_1(_Array_ptr<int> b : bounds(*(&arr), arr + 5));
|
|||
|
||||
// address-of an array does nothing at runtime However, we have to make sure
|
||||
// the types are compatible.
|
||||
extern int f211_2(_Array_ptr<int> b : bounds(&arr, &arr));
|
||||
extern int f211_2(int* _Array b _Bounds(&arr, &arr));
|
||||
extern int f211_2(_Array_ptr<int> b : bounds((int (*) _Checked[10]) arr, (int (*) _Checked[10]) arr));
|
||||
extern int f211_2(_Array_ptr<int> b : bounds(&arr, (int (*) _Checked[10]) arr));
|
||||
extern int f211_2(int* _Array b _Bounds(&arr, (int (*) _Checked[10]) arr));
|
||||
|
||||
//-----------------------------------------------------//
|
||||
// Checked C bounds cast expressions. //
|
||||
|
@ -1094,17 +1098,17 @@ extern void f212_2(_Array_ptr<char> a : bounds(_Assume_bounds_cast<_Array_ptr<in
|
|||
extern void f212_3(_Array_ptr<char> a : bounds(_Assume_bounds_cast<_Array_ptr<int>>(a, count(1)), _Assume_bounds_cast<_Array_ptr<int>>(a, count(2)) + 3));
|
||||
extern void f212_3(_Array_ptr<char> a : bounds(_Dynamic_bounds_cast<_Array_ptr<int>>(a, count(1)), _Assume_bounds_cast<_Array_ptr<int>>(a, count(2)) + 3)); // expected-error {{conflicting parameter bounds}}
|
||||
|
||||
extern void f212_4(_Array_ptr<char> a : bounds(_Dynamic_bounds_cast<_Array_ptr<int>>(a, count(1)), _Assume_bounds_cast<_Array_ptr<int>>(a, count(2)) + 3));
|
||||
extern void f212_4(_Array_ptr<char> a : bounds(_Dynamic_bounds_cast<_Array_ptr<int>>(a, count(1)), _Dynamic_bounds_cast<_Array_ptr<int>>(a, count(2)) + 3)); // expected-error {{conflicting parameter bounds}}
|
||||
extern void f212_4(char* _Array a _Bounds(_Dynamic_bounds_cast_M(int* _Array, a, count(1)), _Assume_bounds_cast_M(int* _Array, a, count(2)) + 3));
|
||||
extern void f212_4(char* _Array a _Bounds(_Dynamic_bounds_cast_M(int* _Array, a, count(1)), _Dynamic_bounds_cast_M(int* _Array, a, count(2)) + 3)); // expected-error {{conflicting parameter bounds}}
|
||||
|
||||
extern void f212_5(_Array_ptr<char> a : bounds(_Dynamic_bounds_cast<_Array_ptr<int>>(a, count(1)), _Assume_bounds_cast<_Array_ptr<int>>(a, count(2)) + 3));
|
||||
extern void f212_5(_Array_ptr<char> a : bounds(_Dynamic_bounds_cast<_Array_ptr<int>>(a, count(5)), _Assume_bounds_cast<_Array_ptr<int>>(a, count(2)) + 3)); // expected-error {{conflicting parameter bounds}}
|
||||
extern void f212_5(char* _Array a _Bounds(_Dynamic_bounds_cast_M(int* _Array, a, count(1)), _Assume_bounds_cast_M(int* _Array, a, count(2)) + 3));
|
||||
extern void f212_5(char* _Array a _Bounds(_Dynamic_bounds_cast_M(int* _Array, a, count(5)), _Assume_bounds_cast_M(int* _Array, a, count(2)) + 3)); // expected-error {{conflicting parameter bounds}}
|
||||
|
||||
extern void f212_6(_Array_ptr<char> a : bounds(_Dynamic_bounds_cast<_Array_ptr<int>>(a, count(1)), _Assume_bounds_cast<_Array_ptr<int>>(a, count(2)) + 3));
|
||||
extern void f212_6(_Array_ptr<char> a : bounds(_Dynamic_bounds_cast<_Array_ptr<int>>(a, count(1)), _Assume_bounds_cast<_Array_ptr<int>>(a, bounds(a, a + 2)) + 3)); // expected-error {{conflicting parameter bounds}}
|
||||
extern void f212_6(char* _Array a _Bounds(_Dynamic_bounds_cast_M(int* _Array, a, count(1)), _Assume_bounds_cast_M(int* _Array, a, count(2)) + 3));
|
||||
extern void f212_6(char* _Array a _Bounds(_Dynamic_bounds_cast_M(int* _Array, a, count(1)), _Assume_bounds_cast_M(int* _Array, a, bounds(a, a + 2)) + 3)); // expected-error {{conflicting parameter bounds}}
|
||||
|
||||
extern void f212_7(_Array_ptr<char> a : bounds(_Dynamic_bounds_cast<_Array_ptr<int>>(b, count(1)), b + 3), _Array_ptr<int> b : count(1));
|
||||
extern void f212_7(_Array_ptr<char> a : bounds(b, b + 3), _Array_ptr<int> b : count(1)); // expected-error {{conflicting parameter bounds}}
|
||||
extern void f212_7(char* _Array a _Bounds(_Dynamic_bounds_cast_M(int* _Array, b, count(1)), b + 3), int* _Array b _Count(1));
|
||||
extern void f212_7(char* _Array a _Bounds(b, b + 3), int* _Array b _Count(1)); // expected-error {{conflicting parameter bounds}}
|
||||
|
||||
extern void f212_8(_Array_ptr<char> a : bounds(b, _Assume_bounds_cast<_Array_ptr<int>>(b, count(1)) + 3), _Array_ptr<int> b : count(1));
|
||||
extern void f212_8(_Array_ptr<char> a : bounds(b, b + 3), _Array_ptr<int> b : count(1)); // expected-error {{conflicting parameter bounds}}
|
||||
extern void f212_8(char* _Array a _Bounds(b, _Assume_bounds_cast_M(int* _Array, b, count(1)) + 3), int* _Array b _Count(1));
|
||||
extern void f212_8(char* _Array a _Bounds(b, b + 3), int* _Array b _Count(1)); // expected-error {{conflicting parameter bounds}}
|
||||
|
|
|
@ -36,7 +36,7 @@ void f1(int i, int* loc) {
|
|||
array_ptr<int> as2a : count(i -= 1) = 0; // expected-error {{assignment expression not allowed in count expression}}
|
||||
array_ptr<int> as2b : byte_count(i -= 1) = 0; // expected-error {{assignment expression not allowed in byte count expression}}
|
||||
array_ptr<int> as2c : bounds(loc -= 1, loc) = 0; // expected-error {{assignment expression not allowed in bounds expression}}
|
||||
array_ptr<int> as2d : bounds(loc, loc -= 1) = 0; // expected-error {{assignment expression not allowed in bounds expression}}
|
||||
int* _Array as2d _Bounds(loc, loc -= 1) = 0; // expected-error {{assignment expression not allowed in bounds expression}}
|
||||
|
||||
array_ptr<int> as3a : count(i *= 1) = 0; // expected-error {{assignment expression not allowed in count expression}}
|
||||
array_ptr<int> as3b : byte_count(i *= 1) = 0; // expected-error {{assignment expression not allowed in byte count expression}}
|
||||
|
@ -46,7 +46,7 @@ void f1(int i, int* loc) {
|
|||
array_ptr<int> as4a : count(i /= 1) = 0; // expected-error {{assignment expression not allowed in count expression}}
|
||||
array_ptr<int> as4b : byte_count(i /= 1) = 0; // expected-error {{assignment expression not allowed in byte count expression}}
|
||||
array_ptr<int> as4c : bounds(loc + (i /= 1), loc) = 0; // expected-error {{assignment expression not allowed in bounds expression}}
|
||||
array_ptr<int> as4d : bounds(loc, loc + (i /= 1)) = 0; // expected-error {{assignment expression not allowed in bounds expression}}
|
||||
int* _Array as4d _Bounds(loc, loc + (i /= 1)) = 0; // expected-error {{assignment expression not allowed in bounds expression}}
|
||||
|
||||
array_ptr<int> as5a : count(i %= 1) = 0; // expected-error {{assignment expression not allowed in count expression}}
|
||||
array_ptr<int> as5b : byte_count(i %= 1) = 0; // expected-error {{assignment expression not allowed in byte count expression}}
|
||||
|
@ -56,7 +56,7 @@ void f1(int i, int* loc) {
|
|||
array_ptr<int> as6a : count(i <<= 1) = 0; // expected-error {{assignment expression not allowed in count expression}}
|
||||
array_ptr<int> as6b : byte_count(i <<= 1) = 0; // expected-error {{assignment expression not allowed in byte count expression}}
|
||||
array_ptr<int> as6c : bounds(loc + (i <<= 1), loc) = 0; // expected-error {{assignment expression not allowed in bounds expression}}
|
||||
array_ptr<int> as6d : bounds(loc, loc + (i <<= 1)) = 0; // expected-error {{assignment expression not allowed in bounds expression}}
|
||||
int* _Array as6d _Bounds(loc, loc + (i <<= 1)) = 0; // expected-error {{assignment expression not allowed in bounds expression}}
|
||||
|
||||
array_ptr<int> as7a : count(i >>= 1) = 0; // expected-error {{assignment expression not allowed in count expression}}
|
||||
array_ptr<int> as7b : byte_count(i >>= 1) = 0; // expected-error {{assignment expression not allowed in byte count expression}}
|
||||
|
@ -66,7 +66,7 @@ void f1(int i, int* loc) {
|
|||
array_ptr<int> as8a : count(i &= 1) = 0; // expected-error {{assignment expression not allowed in count expression}}
|
||||
array_ptr<int> as8b : byte_count(i &= 1) = 0; // expected-error {{assignment expression not allowed in byte count expression}}
|
||||
array_ptr<int> as8c : bounds(loc + (i &= 1), loc) = 0; // expected-error {{assignment expression not allowed in bounds expression}}
|
||||
array_ptr<int> as8d : bounds(loc, loc + (i &= 1)) = 0; // expected-error {{assignment expression not allowed in bounds expression}}
|
||||
int* _Array as8d _Bounds(loc, loc + (i &= 1)) = 0; // expected-error {{assignment expression not allowed in bounds expression}}
|
||||
|
||||
array_ptr<int> as9a : count(i ^= 1) = 0; // expected-error {{assignment expression not allowed in count expression}}
|
||||
array_ptr<int> as9b : byte_count(i ^= 1) = 0; // expected-error {{assignment expression not allowed in byte count expression}}
|
||||
|
@ -75,8 +75,8 @@ void f1(int i, int* loc) {
|
|||
|
||||
array_ptr<int> as10a : count(i |= 1) = 0; // expected-error {{assignment expression not allowed in count expression}}
|
||||
array_ptr<int> as10b : byte_count(i |= 1) = 0; // expected-error {{assignment expression not allowed in byte count expression}}
|
||||
array_ptr<int> as10c : bounds(loc + (i |= 1), loc) = 0; // expected-error {{assignment expression not allowed in bounds expression}}
|
||||
array_ptr<int> as10d : bounds(loc, loc + (i|= 1)) = 0; // expected-error {{assignment expression not allowed in bounds expression}}
|
||||
int* _Array as10c _Bounds(loc + (i |= 1), loc) = 0; // expected-error {{assignment expression not allowed in bounds expression}}
|
||||
int* _Array as10d _Bounds(loc, loc + (i|= 1)) = 0; // expected-error {{assignment expression not allowed in bounds expression}}
|
||||
|
||||
array_ptr<int> as11a : count(i++) = 0; // expected-error {{increment expression not allowed in count expression}}
|
||||
array_ptr<int> as11b : byte_count(i++) = 0; // expected-error {{increment expression not allowed in byte count expression}}
|
||||
|
@ -85,8 +85,8 @@ void f1(int i, int* loc) {
|
|||
|
||||
array_ptr<int> as12a : count(++i) = 0; // expected-error {{increment expression not allowed in count expression}}
|
||||
array_ptr<int> as12b : byte_count(++i) = 0; // expected-error {{increment expression not allowed in byte count expression}}
|
||||
array_ptr<int> as12c : bounds(++loc, loc) = 0; // expected-error {{increment expression not allowed in bounds expression}}
|
||||
array_ptr<int> as12d : bounds(loc, ++loc) = 0; // expected-error {{increment expression not allowed in bounds expression}}
|
||||
int* _Array as12c _Bounds(++loc, loc) = 0; // expected-error {{increment expression not allowed in bounds expression}}
|
||||
int* _Array as12d _Bounds(loc, ++loc) = 0; // expected-error {{increment expression not allowed in bounds expression}}
|
||||
|
||||
array_ptr<int> as13a : count(i--) = 0; // expected-error {{decrement expression not allowed in count expression}}
|
||||
array_ptr<int> as13b : byte_count(i--) = 0; // expected-error {{decrement expression not allowed in byte count expression}}
|
||||
|
@ -95,8 +95,8 @@ void f1(int i, int* loc) {
|
|||
|
||||
array_ptr<int> as14a : count(--i) = 0; // expected-error {{decrement expression not allowed in count expression}}
|
||||
array_ptr<int> as14b : byte_count(--i) = 0; // expected-error {{decrement expression not allowed in byte count expression}}
|
||||
array_ptr<int> as14c : bounds(--loc, loc) = 0; // expected-error {{decrement expression not allowed in bounds expression}}
|
||||
array_ptr<int> as14d : bounds(loc, --loc) = 0; // expected-error {{decrement expression not allowed in bounds expression}}
|
||||
int* _Array as14c _Bounds(--loc, loc) = 0; // expected-error {{decrement expression not allowed in bounds expression}}
|
||||
int* _Array as14d _Bounds(loc, --loc) = 0; // expected-error {{decrement expression not allowed in bounds expression}}
|
||||
|
||||
array_ptr<int> as15a : count(f0int()) = 0; // expected-error {{call expression not allowed in count expression}}
|
||||
array_ptr<int> as15b : byte_count(f0int()) = 0; // expected-error {{call expression not allowed in byte count expression}}
|
||||
|
@ -105,8 +105,8 @@ void f1(int i, int* loc) {
|
|||
|
||||
array_ptr<int> as16a : count(f0int() + 1) = 0; // expected-error {{call expression not allowed in count expression}}
|
||||
array_ptr<int> as16b : byte_count(f0int() + 1) = 0; // expected-error {{call expression not allowed in byte count expression}}
|
||||
array_ptr<int> as16c : bounds(f0ptr() + 1, loc) = 0; // expected-error {{call expression not allowed in bounds expression}}
|
||||
array_ptr<int> as16d : bounds(loc, f0ptr() + 1) = 0; // expected-error {{call expression not allowed in bounds expression}}
|
||||
int* _Array as16c _Bounds(f0ptr() + 1, loc) = 0; // expected-error {{call expression not allowed in bounds expression}}
|
||||
int* _Array as16d _Bounds(loc, f0ptr() + 1) = 0; // expected-error {{call expression not allowed in bounds expression}}
|
||||
|
||||
array_ptr<int> as17a : count(j) = 0; // expected-error {{volatile expression not allowed in count expression}}
|
||||
array_ptr<int> as17b : byte_count(j) = 0; // expected-error {{volatile expression not allowed in byte count expression}}
|
||||
|
@ -115,8 +115,8 @@ void f1(int i, int* loc) {
|
|||
|
||||
array_ptr<int> as18a : count(i + j) = 0; // expected-error {{volatile expression not allowed in count expression}}
|
||||
array_ptr<int> as18b : byte_count(i + j) = 0; // expected-error {{volatile expression not allowed in byte count expression}}
|
||||
array_ptr<int> as18c : bounds(loc + (i + j), loc) = 0; // expected-error {{volatile expression not allowed in bounds expression}}
|
||||
array_ptr<int> as18d : bounds(loc, loc + (i + j)) = 0; // expected-error {{volatile expression not allowed in bounds expression}}
|
||||
int* _Array as18c _Bounds(loc + (i + j), loc) = 0; // expected-error {{volatile expression not allowed in bounds expression}}
|
||||
int* _Array as18d _Bounds(loc, loc + (i + j)) = 0; // expected-error {{volatile expression not allowed in bounds expression}}
|
||||
}
|
||||
|
||||
// Expressions explicitly allowed by spec within Non-Modifying Expressions
|
||||
|
@ -149,8 +149,8 @@ void f2(int i, int* loc) {
|
|||
|
||||
array_ptr<int> as4a : count(&i == &j) = 0;
|
||||
array_ptr<int> as4b : byte_count(&i == &j) = 0;
|
||||
array_ptr<int> as4c : bounds(&i, loc) = 0;
|
||||
array_ptr<int> as4d : bounds(loc, &i) = 0;
|
||||
int* _Array as4c _Bounds(&i, loc) = 0;
|
||||
int* _Array as4d _Bounds(loc, &i) = 0;
|
||||
|
||||
array_ptr<int> as5a : count(*pi) = 0;
|
||||
array_ptr<int> as5b : byte_count(*pi) = 0;
|
||||
|
@ -159,33 +159,33 @@ void f2(int i, int* loc) {
|
|||
|
||||
array_ptr<int> as6a : count((int)'a') = 0;
|
||||
array_ptr<int> as6b : byte_count((int)'a') = 0;
|
||||
array_ptr<int> as6c : bounds((int*)0, loc) = 0;
|
||||
array_ptr<int> as6d : bounds(loc, (int*)0) = 0;
|
||||
int* _Array as6c _Bounds((int*)0, loc) = 0;
|
||||
int* _Array as6d _Bounds(loc, (int*)0) = 0;
|
||||
|
||||
array_ptr<int> as7a : count(+i) = 0;
|
||||
array_ptr<int> as7b : byte_count(+i) = 0;
|
||||
array_ptr<int> as7c : bounds(loc + (+i), loc) = 0;
|
||||
array_ptr<int> as7d : bounds(loc, loc + (+i)) = 0;
|
||||
int* _Array as7d _Bounds(loc, loc + (+i)) = 0;
|
||||
|
||||
array_ptr<int> as8a : count(-i) = 0;
|
||||
array_ptr<int> as8b : byte_count(-i) = 0;
|
||||
array_ptr<int> as8c : bounds(loc + -i, loc) = 0;
|
||||
array_ptr<int> as8d : bounds(loc, loc + -i) = 0;
|
||||
int* _Array as8d _Bounds(loc, loc + -i) = 0;
|
||||
|
||||
array_ptr<int> as9a : count(~i) = 0;
|
||||
array_ptr<int> as9b : byte_count(~i) = 0;
|
||||
array_ptr<int> as9c : bounds(loc + ~i, loc) = 0;
|
||||
array_ptr<int> as9d : bounds(loc, loc + ~i) = 0;
|
||||
int* _Array as9d _Bounds(loc, loc + ~i) = 0;
|
||||
|
||||
array_ptr<int> as10a : count(!i) = 0;
|
||||
array_ptr<int> as10b : byte_count(!i) = 0;
|
||||
array_ptr<int> as10c : bounds(loc + !i, loc) = 0;
|
||||
array_ptr<int> as10d : bounds(loc, loc + !i) = 0;
|
||||
int* _Array as10c _Bounds(loc + !i, loc) = 0;
|
||||
int* _Array as10d _Bounds(loc, loc + !i) = 0;
|
||||
|
||||
array_ptr<int> as11a : count(sizeof(i)) = 0;
|
||||
array_ptr<int> as11b : byte_count(sizeof(i)) = 0;
|
||||
array_ptr<int> as11c : bounds(loc + sizeof(loc), loc) = 0;
|
||||
array_ptr<int> as11d : bounds(loc, loc + sizeof(loc)) = 0;
|
||||
int* _Array as11d _Bounds(loc, loc + sizeof(loc)) = 0;
|
||||
|
||||
array_ptr<int> as12a : count(i * 1 / 1 % 1) = 0;
|
||||
array_ptr<int> as12b : byte_count(i * 1 / 1 % 1) = 0;
|
||||
|
@ -195,7 +195,7 @@ void f2(int i, int* loc) {
|
|||
array_ptr<int> as13a : count(i + 1 - 1) = 0;
|
||||
array_ptr<int> as13b : byte_count(i + 1 - 1) = 0;
|
||||
array_ptr<int> as13c : bounds(loc + 1 - 1, loc) = 0;
|
||||
array_ptr<int> as13d : bounds(loc, loc + 1 - 1) = 0;
|
||||
int* _Array as13d _Bounds(loc, loc + 1 - 1) = 0;
|
||||
|
||||
array_ptr<int> as14a : count(i << 1 >> 1) = 0;
|
||||
array_ptr<int> as14b : byte_count(i << 1 >> 1) = 0;
|
||||
|
@ -203,7 +203,7 @@ void f2(int i, int* loc) {
|
|||
array_ptr<int> as14d : bounds(loc, loc + (i << 1 >> 1)) = 0;
|
||||
|
||||
array_ptr<int> as15a : count(i < j) = 0;
|
||||
array_ptr<int> as15b : byte_count(i < j) = 0;
|
||||
int* _Array as15b _Byte_count(i < j) = 0;
|
||||
|
||||
array_ptr<int> as16a : count(i > j) = 0;
|
||||
array_ptr<int> as16b : byte_count(i > j) = 0;
|
||||
|
@ -212,12 +212,12 @@ void f2(int i, int* loc) {
|
|||
array_ptr<int> as17b : byte_count(i <= j) = 0;
|
||||
|
||||
array_ptr<int> as18a : count(i >= j) = 0;
|
||||
array_ptr<int> as18b : byte_count(i >= j) = 0;
|
||||
int* _Array as18b _Byte_count(i >= j) = 0;
|
||||
|
||||
array_ptr<int> as19a : count(i == j) = 0;
|
||||
array_ptr<int> as19b : byte_count(i == j) = 0;
|
||||
array_ptr<int> as19c : bounds(loc + (loc == loc2), loc) = 0;
|
||||
array_ptr<int> as19d : bounds(loc, loc + (loc == loc2)) = 0;
|
||||
int* _Array as19d _Bounds(loc, loc + (loc == loc2)) = 0;
|
||||
|
||||
array_ptr<int> as20a : count(i & j) = 0;
|
||||
array_ptr<int> as20b : byte_count(i & j) = 0;
|
||||
|
@ -236,8 +236,8 @@ void f2(int i, int* loc) {
|
|||
|
||||
array_ptr<int> as25a : count(i ? j : 0) = 0;
|
||||
array_ptr<int> as25b : byte_count(i ? j : 0) = 0;
|
||||
array_ptr<int> as25c : bounds(i ? loc : loc2, loc) = 0;
|
||||
array_ptr<int> as25d : bounds(loc, i ? loc : loc2) = 0;
|
||||
int* _Array as25c _Bounds(i ? loc : loc2, loc) = 0;
|
||||
int* _Array as25d _Bounds(loc, i ? loc : loc2) = 0;
|
||||
|
||||
array_ptr<int> as26a : count(u1.m1) = 0;
|
||||
array_ptr<int> as26b : byte_count(u1.m1) = 0;
|
||||
|
@ -247,12 +247,12 @@ void f2(int i, int* loc) {
|
|||
array_ptr<int> as27a : count(s1.m1) = 0;
|
||||
array_ptr<int> as27b : byte_count(s1.m1) = 0;
|
||||
array_ptr<int> as27c : bounds(s1.m2, loc) = 0;
|
||||
array_ptr<int> as27d : bounds(loc, s1.m2) = 0;
|
||||
int* _Array as27d _Bounds(loc, s1.m2) = 0;
|
||||
|
||||
array_ptr<int> as28a : count(ps1->m1) = 0;
|
||||
array_ptr<int> as28b : byte_count(ps1->m1) = 0;
|
||||
array_ptr<int> as28c : bounds(ps1->m2, loc) = 0;
|
||||
array_ptr<int> as28d : bounds(loc, ps1->m2) = 0;
|
||||
int* _Array as28d _Bounds(loc, ps1->m2) = 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -270,7 +270,7 @@ void f3(void) {
|
|||
// TODO: this will eventually be allowed when we add support for current_expr_value.
|
||||
(arr[i++]).p = 0; // expected-error {{contain a modifying expression}}
|
||||
// TODO: this will eventually be allowed when we add support for current_expr_value.
|
||||
array_ptr<int> a : count(5) = arr[i++].p; // expected-error {{contain a modifying expression}}
|
||||
int* _Array a _Count(5) = arr[i++].p; // expected-error {{contain a modifying expression}}
|
||||
// TODO: this will eventually be allowed when we add support for current_expr_value.
|
||||
f3_helper(arr[i++].p); // expected-error {{contain a modifying expression}}
|
||||
}
|
||||
|
@ -295,7 +295,7 @@ void f5(void) {
|
|||
int i = 0;
|
||||
ptr<int> p = &i;
|
||||
array_ptr<ptr<int>> r : count(1) = &p;
|
||||
array_ptr<ptr<int>> s : count(1) = &p;
|
||||
int* _Single *_Array s _Count(1) = &p;
|
||||
// TODO: this will eventually be allowed when we add support for current_expr_value.
|
||||
_Array_ptr<int> t : count(1) = *(r = s); // expected-error {{contain a modifying expression}}
|
||||
// TODO: this will eventually be allowed when we add support for current_expr_value.
|
||||
|
|
|
@ -12,16 +12,16 @@ extern void f1() {
|
|||
int b[10];
|
||||
|
||||
int *p = 0;
|
||||
array_ptr<int> checkedc_p : bounds(checkedc_p, checkedc_p + 1) = 0;
|
||||
int* _Array checkedc_p : bounds(checkedc_p, checkedc_p + 1) = 0;
|
||||
c = _Dynamic_bounds_cast<ptr<int>>(p); // expected-error {{expression has unknown bounds}}
|
||||
c = _Dynamic_bounds_cast<ptr<int>>(p); // expected-error {{expression has unknown bounds}}
|
||||
a = _Assume_bounds_cast<array_ptr<int>>(p, count(4));
|
||||
checkedc_p = _Assume_bounds_cast<array_ptr<int>>(p, bounds(p, p + 1));
|
||||
checkedc_p = _Dynamic_bounds_cast<array_ptr<int>>(p, bounds(p, p + 1)); // expected-error {{expression has unknown bounds}}
|
||||
a = _Assume_bounds_cast<array_ptr<int>>(p, count(1));
|
||||
a = _Assume_bounds_cast<int* _Array>(p, count(1));
|
||||
a = _Assume_bounds_cast<array_ptr<int>>(p, bounds(p, p + 1));
|
||||
array_ptr<int> d = _Assume_bounds_cast<array_ptr<int>>(p, count(4));
|
||||
c = _Dynamic_bounds_cast<ptr<int>>(p); // expected-error {{expression has unknown bounds}}
|
||||
c = _Dynamic_bounds_cast<int* _Single>(p); // expected-error {{expression has unknown bounds}}
|
||||
}
|
||||
|
||||
struct S1 {
|
||||
|
@ -31,7 +31,7 @@ struct S1 {
|
|||
} pair;
|
||||
array_ptr<int> arr1 : bounds(pair.lower, pair.upper);
|
||||
struct {
|
||||
array_ptr<int> arr2 : bounds(pair.lower, pair.upper);
|
||||
int* _Array arr2 : bounds(pair.lower, pair.upper);
|
||||
} nested;
|
||||
};
|
||||
|
||||
|
@ -52,8 +52,8 @@ extern void f3() {
|
|||
p = _Dynamic_bounds_cast<int *>(r); // expected-error {{expression has unknown bounds}}
|
||||
q = _Assume_bounds_cast<ptr<int>>(p);
|
||||
q = _Dynamic_bounds_cast<ptr<int>>(p); // expected-error {{expression has unknown bounds}}
|
||||
q = _Dynamic_bounds_cast<ptr<int>>(r); // expected-error {{expression has unknown bounds}}
|
||||
q = _Dynamic_bounds_cast<ptr<int>>(r) + 3; // expected-error{{arithmetic on _Ptr type}}
|
||||
q = _Dynamic_bounds_cast_M_N(int* _Single, r); // expected-error {{expression has unknown bounds}}
|
||||
q = _Dynamic_bounds_cast_M_N(int* _Single, r) + 3; // expected-error{{arithmetic on _Ptr type}}
|
||||
|
||||
*(_Assume_bounds_cast<ptr<int>>(r) + 2) = 4; // expected-error{{arithmetic on _Ptr type}}
|
||||
// For the statement below, the compiler figures out that r + 2 is out of bounds r : count(1).
|
||||
|
@ -63,7 +63,7 @@ extern void f3() {
|
|||
// t : count(3) normals to bounds(t, t + 3), and t[3] is out of that range.
|
||||
int n = (_Dynamic_bounds_cast<array_ptr<int>>(t, count(3)))[3]; // expected-error {{out-of-bounds memory access}}
|
||||
s1 = _Dynamic_bounds_cast<array_ptr<int>>(p, count(5)); // expected-error {{expression has unknown bounds}}
|
||||
s2 = _Assume_bounds_cast<array_ptr<int>>(r, count(5));
|
||||
s2 = _Assume_bounds_cast<int* _Array>(r, count(5));
|
||||
}
|
||||
|
||||
extern ptr<int> f4(int arr checked[]) {
|
||||
|
@ -83,7 +83,7 @@ checked int *f5(int *p, ptr<int> q, array_ptr<int> r, array_ptr<int> s: count(2)
|
|||
int b checked[5][5];
|
||||
for (int i = 0; i < 5; i++) {
|
||||
for (int j = 0; j < 5; j++) {
|
||||
b[i][j] += *q + *(_Dynamic_bounds_cast<array_ptr<int>>(r, count(1))); // expected-error {{expression has unknown bounds}}
|
||||
b[i][j] += *q + *(_Dynamic_bounds_cast<int* _Array>(r, count(1))); // expected-error {{expression has unknown bounds}}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -143,8 +143,8 @@ extern void f18(int i) {
|
|||
r = _Dynamic_bounds_cast<array_ptr<int>>(p, count(1)); // expected-error {{expression has unknown bounds}} expected-error {{declared bounds for 'r' are invalid after assignment}}
|
||||
r = _Dynamic_bounds_cast<array_ptr<int>>(p, bounds(p, p + 1)); // expected-error {{expression has unknown bounds}} expected-error {{declared bounds for 'r' are invalid after assignment}}
|
||||
|
||||
r = _Dynamic_bounds_cast<array_ptr<int>>(i, count(5)); // expected-error {{expression has unknown bounds}}
|
||||
r = _Dynamic_bounds_cast<array_ptr<int>>(i, bounds(i, i + 1)); // expected-error 2 {{expected expression with pointer}}
|
||||
r = _Dynamic_bounds_cast<int* _Array>(i, count(5)); // expected-error {{expression has unknown bounds}}
|
||||
r = _Dynamic_bounds_cast<int* _Array>(i, bounds(i, i + 1)); // expected-error 2 {{expected expression with pointer}}
|
||||
|
||||
int len;
|
||||
|
||||
|
@ -185,7 +185,7 @@ extern void f19(){
|
|||
x = _Dynamic_bounds_cast<array_ptr<int>>(b, bounds(p, p + 1)); // expected-error {{to have a pointer}}
|
||||
|
||||
x = _Dynamic_bounds_cast<array_ptr<int>>(p, count(b)); // expected-error {{invalid argument type}}
|
||||
x = _Dynamic_bounds_cast<array_ptr<int>>(p, bounds(p, 1)); // expected-error {{expected expression with}}
|
||||
x = _Dynamic_bounds_cast<int* _Array>(p, bounds(p, 1)); // expected-error {{expected expression with}}
|
||||
x = _Dynamic_bounds_cast<array_ptr<int>>(p, bounds(p, p + 1)); // expected-error {{declared bounds for 'x' are invalid after assignment}}
|
||||
}
|
||||
|
||||
|
@ -206,7 +206,7 @@ extern void f20(void *p) {
|
|||
}
|
||||
|
||||
extern void f21(array_ptr<char> buf : count(len), int len) {
|
||||
array_ptr<int> intbuf : count(12) = _Dynamic_bounds_cast<array_ptr<int>>(buf, bounds(intbuf, intbuf + 12));
|
||||
int* _Array intbuf _Count(12) = _Dynamic_bounds_cast<int* _Array>(buf, bounds(intbuf, intbuf + 12));
|
||||
int i = intbuf[12]; // expected-error {{out-of-bounds memory access}} \
|
||||
// expected-note {{accesses memory at or above the upper bound}} \
|
||||
// expected-note {{(expanded) inferred bounds are 'bounds(intbuf, intbuf + 12)'}}
|
||||
|
@ -220,7 +220,7 @@ extern void f22() {
|
|||
}
|
||||
|
||||
extern void f23() {
|
||||
array_ptr<char> buf : count(10) = _Assume_bounds_cast<array_ptr<char>>(h7(), count(10));
|
||||
array_ptr<char> buf _Count(10) = _Assume_bounds_cast<array_ptr<char>>(h7(), count(10));
|
||||
char c = buf[10]; // expected-error {{out-of-bounds memory access}} \
|
||||
// expected-note {{accesses memory at or above the upper bound}} \
|
||||
// expected-note {{(expanded) inferred bounds are 'bounds(buf, buf + 10)'}}
|
||||
|
@ -244,7 +244,7 @@ extern void f24() {
|
|||
}
|
||||
|
||||
extern void f25(array_ptr<char> buf : count(len), int len) {
|
||||
array_ptr<int> intbuf : count(6) = _Dynamic_bounds_cast<array_ptr<int>>(buf + 5, count(6));
|
||||
int* _Array intbuf _Count(6) = _Dynamic_bounds_cast<int* _Array>(buf + 5, count(6));
|
||||
int i = intbuf[6]; // expected-error {{out-of-bounds memory access}} \
|
||||
// expected-note {{accesses memory at or above the upper bound}} \
|
||||
// expected-note {{(expanded) inferred bounds are 'bounds(intbuf, intbuf + 6)'}}
|
||||
|
|
|
@ -52,8 +52,8 @@ extern void count_exprs(void) {
|
|||
array_ptr<int> t7 : count(c7) = 0;
|
||||
array_ptr<int> t8 : count(c8) = 0;
|
||||
array_ptr<int> t9 : count(c9) = 0;
|
||||
array_ptr<int> t10 : count(c10) = 0;
|
||||
array_ptr<int> t11 : count(c11) = 0;
|
||||
int* _Array t10 _Count(c10) = 0;
|
||||
int* _Array t11 _Count(c11) = 0;
|
||||
// Spot-check type checking of count expressions involving file-scoped
|
||||
// variables.
|
||||
array_ptr<int> t12 : count(A) = 0;
|
||||
|
@ -72,8 +72,8 @@ extern void count_exprs(void) {
|
|||
array_ptr<int> t22 : byte_count(c7) = 0;
|
||||
array_ptr<int> t23 : byte_count(c8) = 0;
|
||||
array_ptr<int> t24 : byte_count(c9) = 0;
|
||||
array_ptr<int> t25 : byte_count(c10) = 0;
|
||||
array_ptr<int> t26 : byte_count(c11) = 0;
|
||||
int* _Array t25 _Byte_count(c10) = 0;
|
||||
int* _Array t26 _Byte_count(c11) = 0;
|
||||
// Spot-check type checking of byte_count expressions involving file-scoped
|
||||
// variables.
|
||||
array_ptr<int> t27 : byte_count(A) = 0;
|
||||
|
@ -93,8 +93,8 @@ extern void count_exprs(void) {
|
|||
|
||||
nt_array_ptr<char> t54 : byte_count(c7) = 0;
|
||||
nt_array_ptr<char> t55 : byte_count(c8) = 0;
|
||||
nt_array_ptr<char> t56 : byte_count(c9) = 0;
|
||||
nt_array_ptr<char> t57 : byte_count(A) = 0;
|
||||
char* _Nt_array t56 _Byte_count(c9) = 0;
|
||||
char* _Nt_array t57 _Byte_count(A) = 0;
|
||||
|
||||
}
|
||||
|
||||
|
@ -114,7 +114,7 @@ extern void count_exprs_with_integral_operands(void) {
|
|||
array_ptr<int> t1 : count(c1) = 0;
|
||||
array_ptr<int> t2 : count(c2) = 0;
|
||||
array_ptr<int> t3 : count(s.f) = 0;
|
||||
nt_array_ptr<int> t4 : count(c2) = 0;
|
||||
int* _Nt_array t4 _Count(c2) = 0;
|
||||
}
|
||||
|
||||
float globalFloat = 8;
|
||||
|
@ -153,8 +153,8 @@ extern void invalid_count_exprs(void) {
|
|||
array_ptr<int> t9 : count(test_func) = 0; // expected-error {{invalid argument type}}
|
||||
array_ptr<int> t10 : count(func_ptr) = 0; // expected-error {{invalid argument type}}
|
||||
array_ptr<int> t11 : count("test") = 0; // expected-error {{invalid argument type}}
|
||||
array_ptr<int> t12 : count(5.0f) = 0; // expected-error {{invalid argument type}}
|
||||
array_ptr<int> t13 : count(globalFloat) = 0; // expected-error {{invalid argument type}}
|
||||
int* _Array t12 _Count(5.0f) = 0; // expected-error {{invalid argument type}}
|
||||
int* _Array t13 _Count(globalFloat) = 0; // expected-error {{invalid argument type}}
|
||||
|
||||
#ifndef __STDC_NO_COMPLEX__
|
||||
array_ptr<int> t14 : count(c8) = 0; // expected-error {{invalid argument type}}
|
||||
|
@ -170,8 +170,8 @@ extern void invalid_count_exprs(void) {
|
|||
array_ptr<int> t22 : byte_count(s.f) = 0; // expected-error {{invalid argument type}}
|
||||
array_ptr<int> t23 : byte_count(func_ptr) = 0; // expected-error {{invalid argument type}}
|
||||
array_ptr<int> t24 : byte_count("test") = 0; // expected-error {{invalid argument type}}
|
||||
array_ptr<int> t25 : byte_count(5.0f) = 0; // expected-error {{invalid argument type}}
|
||||
array_ptr<int> t26 : byte_count(globalFloat) = 0; // expected-error {{invalid argument type}}
|
||||
int* _Array t25 _Byte_count(5.0f) = 0; // expected-error {{invalid argument type}}
|
||||
int* _Array t26 _Byte_count(globalFloat) = 0; // expected-error {{invalid argument type}}
|
||||
|
||||
#ifndef __STDC_NO_COMPLEX__
|
||||
array_ptr<int> t27 : byte_count(c8) = 0; // expected-error {{invalid argument type}}
|
||||
|
@ -200,8 +200,8 @@ extern void bounds_exprs(void) {
|
|||
array_ptr<int> t5 : bounds(array_ptr_lb, unchecked_ptr_ub) = i;
|
||||
array_ptr<int> t6 : bounds(ptr_lb, ptr_ub) = i;
|
||||
array_ptr<int> t7 : bounds(unchecked_ptr_lb, ptr_ub) = i;
|
||||
array_ptr<int> t8 : bounds(ptr_lb, unchecked_ptr_ub) = i;
|
||||
array_ptr<int> t9 : bounds(unchecked_ptr_lb, unchecked_ptr_ub) = i;
|
||||
int* _Array t8 _Bounds(ptr_lb, unchecked_ptr_ub) = i;
|
||||
int* _Array t9 _Bounds(unchecked_ptr_lb, unchecked_ptr_ub) = i;
|
||||
|
||||
// spot check mixed uses of nt_array_ptr and other pointer types.
|
||||
array_ptr<int> t9a : bounds(nt_array_ptr_lb, ptr_ub) = i;
|
||||
|
@ -213,8 +213,8 @@ extern void bounds_exprs(void) {
|
|||
|
||||
array_ptr<int> t10 : bounds(i, i + 1) = i;
|
||||
array_ptr<int> t11 : bounds(i, array_ptr_ub) = i;
|
||||
array_ptr<int> t11a : bounds(i, nt_array_ptr_ub) = i;
|
||||
array_ptr<int> t13 : bounds(i, ptr_ub) = i;
|
||||
int* _Array t11a _Bounds(i, nt_array_ptr_ub) = i;
|
||||
int* _Array t13 _Bounds(i, ptr_ub) = i;
|
||||
|
||||
array_ptr<void> void_array_ptr_lb = i, void_array_ptr_ub = i + 1;
|
||||
ptr<void> void_ptr_lb = i, void_ptr_ub = i + 1;
|
||||
|
@ -229,7 +229,7 @@ extern void bounds_exprs(void) {
|
|||
array_ptr<int> t26 : bounds(void_ptr_lb, void_ptr_ub) = i;
|
||||
array_ptr<int> t27 : bounds(void_unchecked_ptr_lb, void_ptr_ub) = i;
|
||||
array_ptr<int> t28 : bounds(void_ptr_lb, void_unchecked_ptr_ub) = i;
|
||||
array_ptr<int> t29 : bounds(void_unchecked_ptr_lb, void_unchecked_ptr_ub) = i;
|
||||
int* _Array t29 _Bounds(void_unchecked_ptr_lb, void_unchecked_ptr_ub) = i;
|
||||
|
||||
// check combinations of pointers to void and pointers to non-void types
|
||||
|
||||
|
@ -240,8 +240,8 @@ extern void bounds_exprs(void) {
|
|||
array_ptr<int> t46 : bounds(array_ptr_lb, void_ptr_ub) = i;
|
||||
array_ptr<int> t47 : bounds(unchecked_ptr_lb, void_array_ptr_ub) = i;
|
||||
array_ptr<int> t48 : bounds(void_unchecked_ptr_lb, array_ptr_ub) = i;
|
||||
array_ptr<int> t49 : bounds(void_array_ptr_lb, unchecked_ptr_ub) = i;
|
||||
array_ptr<int> t50 : bounds(array_ptr_lb, void_unchecked_ptr_ub) = i;
|
||||
int* _Array t49 _Bounds(void_array_ptr_lb, unchecked_ptr_ub) = i;
|
||||
int* _Array t50 _Bounds(array_ptr_lb, void_unchecked_ptr_ub) = i;
|
||||
|
||||
array_ptr<int> t51 : bounds(void_ptr_lb, ptr_ub) = i;
|
||||
array_ptr<int> t52 : bounds(ptr_lb, void_ptr_ub) = i;
|
||||
|
@ -261,8 +261,8 @@ extern void bounds_exprs(void) {
|
|||
array_ptr<char> t73 : bounds(unchecked_ptr_lb, ptr_ub) = (array_ptr<char>) i;
|
||||
array_ptr<char> t75 : bounds(void_array_ptr_lb, array_ptr_ub) = (array_ptr<char>) i;
|
||||
array_ptr<char> t76 : bounds(void_unchecked_ptr_lb, array_ptr_ub) = (array_ptr<char>) i;
|
||||
array_ptr<char> t77 : bounds(array_ptr_lb, void_unchecked_ptr_ub) = (array_ptr<char>) i;
|
||||
array_ptr<char> t77a : bounds(nt_array_ptr_lb, void_unchecked_ptr_ub) = (array_ptr<char>) i;
|
||||
char* _Array t77 _Bounds(array_ptr_lb, void_unchecked_ptr_ub) = (char* _Array) i;
|
||||
char* _Array t77a _Bounds(nt_array_ptr_lb, void_unchecked_ptr_ub) = (char* _Array) i;
|
||||
|
||||
// use an array-typed value as the lower bound. This should be converted
|
||||
// implicitly to be a pointer type.
|
||||
|
@ -271,7 +271,7 @@ extern void bounds_exprs(void) {
|
|||
array_ptr<char> t80 : bounds(i, nt_array_ptr_ub) = (array_ptr<char>) i;
|
||||
|
||||
// spot check that typechecking looks through typedefs
|
||||
typedef array_ptr<int> int_array_ptr;
|
||||
typedef int* _Array int_array_ptr;
|
||||
typedef ptr<int> int_ptr;
|
||||
typedef int *int_unchecked_ptr;
|
||||
typedef nt_array_ptr<int> int_nt_array_ptr;
|
||||
|
@ -292,7 +292,7 @@ extern void bounds_exprs(void) {
|
|||
array_ptr<int> t98 : bounds(ptr_lb, typedef_unchecked_ptr_ub) = i;
|
||||
array_ptr<int> t99 : bounds(typedef_unchecked_ptr_lb, unchecked_ptr_ub) = i;
|
||||
array_ptr<int> t100 : bounds(typedef_nt_array_ptr_lb, unchecked_ptr_ub) = i;
|
||||
array_ptr<int> t101 : bounds(typedef_array_ptr_lb, typedef_nt_array_ptr_ub) = i;
|
||||
int* _Array t101 _Bounds(typedef_array_ptr_lb, typedef_nt_array_ptr_ub) = i;
|
||||
|
||||
// check that type qualifiers are discarded when comparing pointer types
|
||||
// in bounds expressions
|
||||
|
@ -323,7 +323,7 @@ extern void bounds_exprs(void) {
|
|||
const int *unchecked_ptr_const_ub = i + 1;
|
||||
const int *const const_unchecked_ptr_const_ub = i + 1;
|
||||
|
||||
array_ptr<int> t121 : bounds(array_ptr_const_lb, array_ptr_ub) = i;
|
||||
int* _Array t121 _Bounds(array_ptr_const_lb, array_ptr_ub) = i;
|
||||
array_ptr<int> t122 : bounds(const_array_ptr_lb, array_ptr_ub) = i;
|
||||
array_ptr<int> t123 : bounds(const_array_ptr_const_lb, array_ptr_ub) = i;
|
||||
|
||||
|
@ -333,7 +333,7 @@ extern void bounds_exprs(void) {
|
|||
|
||||
array_ptr<int> t127 : bounds(const_array_ptr_lb, array_ptr_const_ub) = i;
|
||||
array_ptr<int> t128 : bounds(array_ptr_const_lb, const_array_ptr_ub) = i;
|
||||
array_ptr<int> t129 : bounds(const_array_ptr_const_lb, const_array_ptr_const_ub) = i;
|
||||
int* _Array t129 _Bounds(const_array_ptr_const_lb, const_array_ptr_const_ub) = i;
|
||||
|
||||
array_ptr<int> t130 : bounds(ptr_lb, array_ptr_ub) = i;
|
||||
array_ptr<int> t131 : bounds(array_ptr_lb, ptr_ub) = i;
|
||||
|
@ -346,7 +346,7 @@ extern void bounds_exprs(void) {
|
|||
|
||||
// spot check const nt_array_ptr
|
||||
array_ptr<int> t140 : bounds(nt_array_ptr_lb, const_nt_array_ptr_ub) = i;
|
||||
array_ptr<int> t141 : bounds(const_nt_array_ptr_lb, nt_array_ptr_ub) = i;
|
||||
int* _Array t141 _Bounds(const_nt_array_ptr_lb, nt_array_ptr_ub) = i;
|
||||
}
|
||||
|
||||
extern void invalid_bounds_exprs(void) {
|
||||
|
@ -392,7 +392,7 @@ extern void bounds_exprs(void) {
|
|||
array_ptr<int> t13 : bounds(c13, c13) = 0; // expected-error 2 {{expected expression with pointer type}}
|
||||
array_ptr<int> t14 : bounds(c14, c14) = 0; // expected-error 2 {{expected expression with pointer type}}
|
||||
array_ptr<int> t15 : bounds(c15, c15) = 0; // expected-error 2 {{expected expression with pointer type}}
|
||||
array_ptr<int> t16 : bounds(test_func, test_func) = 0; // expected-error 2 {{invalid argument type 'void (*)(void)' to bounds expression}}
|
||||
int* _Array t16 _Bounds(test_func, test_func) = 0; // expected-error 2 {{invalid argument type 'void (*)(void)' to bounds expression}}
|
||||
|
||||
// have values with different levels of indirection
|
||||
array_ptr<int> t17 : bounds(double_indir, c3) = 0; // expected-error {{expected expression with pointer type}}
|
||||
|
@ -420,7 +420,7 @@ extern void bounds_exprs(void) {
|
|||
array_ptr<int> t32 : bounds(int_unchecked_ptr_lb, char_ptr_ub) = i; // expected-error {{pointer type mismatch}}
|
||||
array_ptr<char> t33 : bounds(char_array_ptr_lb, int_ptr_ub) = (array_ptr<char>) i; // expected-error {{pointer type mismatch}}
|
||||
array_ptr<char> t34 : bounds(char_ptr_lb, int_ptr_ub) = (array_ptr<char>) i; // expected-error {{pointer type mismatch}}
|
||||
array_ptr<char> t35 : bounds(char_unchecked_ptr_lb, int_ptr_ub) = (array_ptr<char>) i; // expected-error {{pointer type mismatch}}
|
||||
char* _Array t35 _Bounds(char_unchecked_ptr_lb, int_ptr_ub) = (char* _Array) i; // expected-error {{pointer type mismatch}}
|
||||
|
||||
// spot check nt_array_ptr with invalid bounds expression
|
||||
nt_array_ptr<char> t40 : bounds(int_array_ptr_lb, char_array_ptr_ub) = 0; // expected-error {{pointer type mismatch}}
|
||||
|
@ -510,8 +510,8 @@ struct S1 g51 : count(5) = { 0 }; // expected-error {{expected 'g51' to have a
|
|||
union U1 g52 : count(5) = { 0 }; // expected-error {{expected 'g52' to have a pointer or array type}}
|
||||
enum E1 g53 : count(5) = EnumVal1; // expected-error {{expected 'g53' to have a pointer or array type}}
|
||||
ptr<int> g54: count(1) = 0; // expected-error {{bounds declaration not allowed because 'g54' has a _Ptr type}}
|
||||
array_ptr<void> g55 : count(1) = 0; // expected-error {{expected 'g55' to have a non-void pointer type}}
|
||||
void((*g56)(void)) : count(1); // expected-error {{bounds declaration not allowed because 'g56' has a function pointer type}}
|
||||
void* _Array g55 _Count(1) = 0; // expected-error {{expected 'g55' to have a non-void pointer type}}
|
||||
void((*g56)(void)) _Count(1); // expected-error {{bounds declaration not allowed because 'g56' has a function pointer type}}
|
||||
|
||||
// byte_count
|
||||
float g60 : byte_count(8); // expected-error {{expected 'g60' to have a pointer, array, or integer type}}
|
||||
|
@ -526,8 +526,8 @@ float g70 : bounds(s1, s1 + 1); // expected-error {{expected 'g70' t
|
|||
double g71 : bounds(s1, s1 + 1); // expected-error {{expected 'g71' to have a pointer, array, or integer type}}
|
||||
struct S1 g72 : bounds(s1, s1 + 1) = { 0 }; // expected-error {{expected 'g72' to have a pointer, array, or integer type}}
|
||||
union U1 g73 : bounds(s1, s1 + 1) = { 0 }; // expected-error {{expected 'g73' to have a pointer, array, or integer type}}
|
||||
ptr<int> g74 : bounds(s1, s1 + 1) = 0; // expected-error {{bounds declaration not allowed because 'g74' has a _Ptr type}}
|
||||
void((*g75)(void)) : bounds(s1, s1 + 1); // expected-error {{bounds declaration not allowed because 'g75' has a function pointer type}}
|
||||
int* _Single g74 _Bounds(s1, s1 + 1) = 0; // expected-error {{bounds declaration not allowed because 'g74' has a _Ptr type}}
|
||||
void((*g75)(void)) _Bounds(s1, s1 + 1); // expected-error {{bounds declaration not allowed because 'g75' has a function pointer type}}
|
||||
|
||||
//
|
||||
// Test bounds declarations for local variables.
|
||||
|
@ -554,7 +554,7 @@ void local_var_bounds_decl(void)
|
|||
array_ptr<void> t11 : bounds(t3, t3 + 5) = t3;
|
||||
int t13 checked[5] : bounds(t13, t13 + 5);
|
||||
unsigned int t14 checked[5] : bounds(t14, t14 + 5);
|
||||
unsigned int t14a nt_checked[5] : bounds(t14, t14 + 4);
|
||||
unsigned int t14a nt_checked[5] _Bounds(t14, t14 + 4);
|
||||
}
|
||||
|
||||
void int_local_var_bounds_decl(void) {
|
||||
|
@ -587,8 +587,8 @@ void invalid_local_var_bounds_decl(void)
|
|||
union U1 t52 : count(5) = { 0 }; // expected-error {{expected 't52' to have a pointer or array type}}
|
||||
enum E1 t53 : count(5) = EnumVal1; // expected-error {{expected 't53' to have a pointer or array type}}
|
||||
ptr<int> t54 : count(1) = 0; // expected-error {{bounds declaration not allowed because 't54' has a _Ptr type}}
|
||||
array_ptr<void> t55 : count(1) = 0; // expected-error {{expected 't55' to have a non-void pointer type}}
|
||||
array_ptr<void (void)> t56 : count(1); // expected-error {{declared as _Array_ptr to function of type 'void (void)'; use _Ptr to function instead}}
|
||||
void* _Array t55 _Count(1) = 0; // expected-error {{expected 't55' to have a non-void pointer type}}
|
||||
array_ptr<void (void)> t56 _Count(1); // expected-error {{declared as _Array_ptr to function of type 'void (void)'; use _Ptr to function instead}}
|
||||
|
||||
int *t57 : count(1) = 0; // expected-error {{bounds declaration not allowed for local variable with unchecked pointer type}}
|
||||
int t58[5] : count(5); // expected-error {{bounds declaration not allowed for local variable with unchecked array type}}
|
||||
|
@ -601,8 +601,8 @@ void invalid_local_var_bounds_decl(void)
|
|||
ptr<int> t64 : byte_count(sizeof(int)) = 0; // expected-error {{bounds declaration not allowed because 't64' has a _Ptr type}}
|
||||
array_ptr<void (void)> t65 : byte_count(1); // expected-error {{declared as _Array_ptr to function of type 'void (void)'; use _Ptr to function instead}}
|
||||
|
||||
int *t67 : byte_count(sizeof(int)) = 0; // expected-error {{bounds declaration not allowed for local variable with unchecked pointer type}}
|
||||
int t68[5] : byte_count(5 * sizeof(int)); // expected-error {{bounds declaration not allowed for local variable with unchecked array type}}
|
||||
int *t67 _Byte_count(sizeof(int)) = 0; // expected-error {{bounds declaration not allowed for local variable with unchecked pointer type}}
|
||||
int t68[5] _Byte_count(5 * sizeof(int)); // expected-error {{bounds declaration not allowed for local variable with unchecked array type}}
|
||||
|
||||
// bounds
|
||||
float t70 : bounds(arr, arr + 1); // expected-error {{expected 't70' to have a pointer, array, or integer type}}
|
||||
|
@ -613,7 +613,7 @@ void invalid_local_var_bounds_decl(void)
|
|||
array_ptr<void (void)> t75 : bounds(arr, arr + 1); // expected-error {{declared as _Array_ptr to function of type 'void (void)'; use _Ptr to function instead}}
|
||||
|
||||
int *t78 : bounds(arr, arr + 1) = 0; // expected-error {{bounds declaration not allowed for local variable with unchecked pointer type}}
|
||||
int t79[5] : bounds(arr, arr + 1); // expected-error {{bounds declaration not allowed for local variable with unchecked array type}}
|
||||
int t79[5] _Bounds(arr, arr + 1); // expected-error {{bounds declaration not allowed for local variable with unchecked array type}}
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -634,8 +634,8 @@ void param_var_bounds_decl(
|
|||
array_ptr<int> t4 : byte_count(5 * sizeof(int)),
|
||||
array_ptr<void> t5 : byte_count(5 * sizeof(int)),
|
||||
int *t6 : byte_count(5 * sizeof(int)),
|
||||
int t7 checked[5] : byte_count(5 * sizeof(int)),
|
||||
unsigned int t8 checked[5] : byte_count(5 * sizeof(int)),
|
||||
int t7 checked[5] _Byte_count(5 * sizeof(int)),
|
||||
unsigned int t8 checked[5] _Byte_count(5 * sizeof(int)),
|
||||
unsigned int t9[5] : byte_count(5 * sizeof(int)),
|
||||
|
||||
// bounds
|
||||
|
@ -719,8 +719,8 @@ void invalid_param_var_bounds_decl(
|
|||
double t61 : byte_count(8), // expected-error {{expected 't61' to have a pointer, array, or integer type}}
|
||||
struct S1 t62 : byte_count(8), // expected-error {{expected 't62' to have a pointer, array, or integer type}}
|
||||
union U1 t63 : byte_count(8), // expected-error {{expected 't63' to have a pointer, array, or integer type}}
|
||||
ptr<int> t64 : byte_count(8), // expected-error {{bounds declaration not allowed because 't64' has a _Ptr type}}
|
||||
void((*t65)(void)) : byte_count(1),// expected-error {{bounds declaration not allowed because 't65' has a function pointer type}}
|
||||
int* _Single t64 _Byte_count(8), // expected-error {{bounds declaration not allowed because 't64' has a _Ptr type}}
|
||||
void((*t65)(void)) _Byte_count(1),// expected-error {{bounds declaration not allowed because 't65' has a function pointer type}}
|
||||
|
||||
// bounds
|
||||
float t70 : bounds(s1, s1 + 1), // expected-error {{expected 't70' to have a pointer, array, or integer type}}
|
||||
|
@ -742,8 +742,8 @@ extern void anonymous_invalid_param_var_bounds_decl(
|
|||
int : count(5), // expected-error {{expected '' to have a pointer or array type}}
|
||||
long int : count(5), // expected-error {{expected '' to have a pointer or array type}}
|
||||
unsigned short int : count(5), // expected-error {{expected '' to have a pointer or array type}}
|
||||
unsigned int : count(5), // expected-error {{expected '' to have a pointer or array type}}
|
||||
unsigned long : count(5), // expected-error {{expected '' to have a pointer or array type}}
|
||||
unsigned int _Count(5), // expected-error {{expected '' to have a pointer or array type}}
|
||||
unsigned long _Count(5), // expected-error {{expected '' to have a pointer or array type}}
|
||||
|
||||
float : count(5), // expected-error {{expected '' to have a pointer or array type}}
|
||||
double : count(5), // expected-error {{expected '' to have a pointer or array type}}
|
||||
|
@ -755,12 +755,12 @@ extern void anonymous_invalid_param_var_bounds_decl(
|
|||
void((*)(void)) : count(1), // expected-error {{bounds declaration not allowed because '' has a function pointer type}}
|
||||
|
||||
// byte_count
|
||||
float : byte_count(8), // expected-error {{expected '' to have a pointer, array, or integer type}}
|
||||
double : byte_count(8), // expected-error {{expected '' to have a pointer, array, or integer type}}
|
||||
struct S1 : byte_count(8), // expected-error {{expected '' to have a pointer, array, or integer type}}
|
||||
union U1 : byte_count(8), // expected-error {{expected '' to have a pointer, array, or integer type}}
|
||||
ptr<int> : byte_count(8), // expected-error {{bounds declaration not allowed because '' has a _Ptr type}}
|
||||
void((*)(void)) : byte_count(1),// expected-error {{bounds declaration not allowed because '' has a function pointer type}}
|
||||
float _Byte_count(8), // expected-error {{expected '' to have a pointer, array, or integer type}}
|
||||
double _Byte_count(8), // expected-error {{expected '' to have a pointer, array, or integer type}}
|
||||
struct S1 _Byte_count(8), // expected-error {{expected '' to have a pointer, array, or integer type}}
|
||||
union U1 _Byte_count(8), // expected-error {{expected '' to have a pointer, array, or integer type}}
|
||||
int* _Single _Byte_count(8), // expected-error {{bounds declaration not allowed because '' has a _Ptr type}}
|
||||
void((*)(void)) _Byte_count(1),// expected-error {{bounds declaration not allowed because '' has a function pointer type}}
|
||||
|
||||
// bounds
|
||||
float : bounds(s1, s1 + 1), // expected-error {{expected '' to have a pointer, array, or integer type}}
|
||||
|
@ -798,7 +798,7 @@ struct S4 {
|
|||
int f7 checked[5] : byte_count(5 * sizeof(int));
|
||||
int f7a nt_checked[5] : byte_count(4 * sizeof(int));
|
||||
unsigned int f8 checked[5] : byte_count(5 * sizeof(int));
|
||||
unsigned int f9[5] : byte_count(5 * sizeof(int));
|
||||
unsigned int f9[5] _Byte_count(5 * sizeof(int));
|
||||
};
|
||||
|
||||
// bounds
|
||||
|
@ -810,9 +810,9 @@ struct S6 {
|
|||
int *f12 : bounds(f12, f12 + 5);
|
||||
int f13 checked[5] : bounds(f13, f13 + 5);
|
||||
unsigned int f14 checked[5] : bounds(f14, f14 + 5);
|
||||
unsigned int f14a nt_checked[5] : bounds(f14a, f14a + 5);
|
||||
unsigned int f14a nt_checked[5] _Bounds(f14a, f14a + 5);
|
||||
int f15[5] : bounds(f15, f15 + 5);
|
||||
unsigned int f16[5] : bounds(f16, f16 + 5);
|
||||
unsigned int f16[5] _Bounds(f16, f16 + 5);
|
||||
};
|
||||
|
||||
//
|
||||
|
@ -873,10 +873,11 @@ struct s8 {
|
|||
double g71 : bounds(s1, s1 + 1); // expected-error {{expected 'g71' to have a pointer, array, or integer type}}
|
||||
struct S1 g72 : bounds(s1, s1 + 1); // expected-error {{expected 'g72' to have a pointer, array, or integer type}}
|
||||
union U1 g73 : bounds(s1, s1 + 1); // expected-error {{expected 'g73' to have a pointer, array, or integer type}}
|
||||
ptr<int> g74 : bounds(s1, s1 + 1); // expected-error {{bounds declaration not allowed because 'g74' has a _Ptr type}}
|
||||
void((*g75)(void)) : bounds(s1, s1 + 1); // expected-error {{bounds declaration not allowed because 'g75' has a function pointer type}}
|
||||
int* _Single g74 _Bounds(s1, s1 + 1); // expected-error {{bounds declaration not allowed because 'g74' has a _Ptr type}}
|
||||
void((*g75)(void)) _Bounds(s1, s1 + 1); // expected-error {{bounds declaration not allowed because 'g75' has a function pointer type}}
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// Test function return bounds declarations.
|
||||
//
|
||||
|
@ -886,7 +887,7 @@ struct s8 {
|
|||
//
|
||||
|
||||
// count
|
||||
array_ptr<int> fn1(void) : count(5) { return 0; }
|
||||
int* _Array fn1(void) _Count(5) { return 0; }
|
||||
nt_array_ptr<int> fn1a(void) : count(0) { return 0; }
|
||||
int *fn2(void) : count(5) { return 0; }
|
||||
int *fn3(int len) : count(len) { return 0; }
|
||||
|
@ -899,7 +900,7 @@ extern int *fn6(void) : byte_count(5 * sizeof(int));
|
|||
|
||||
// bounds
|
||||
array_ptr<int> fn10(void) : bounds(s1, s1 + 5) { return 0; }
|
||||
nt_array_ptr<int> fn10a(void) : bounds(s1, s1 + 5) { return 0; }
|
||||
int* _Nt_array fn10a(void) _Bounds(s1, s1 + 5) { return 0; }
|
||||
array_ptr<void> fn11(void) : bounds(s1, s1 + 5) { return 0; }
|
||||
int *fn12(void) : bounds(s1, s1 + 5) { return 0; }
|
||||
|
||||
|
@ -1005,9 +1006,9 @@ void fn122(array_ptr<void> mid : bounds((char *)p1, (char *)p1 + (5 * sizeof(int
|
|||
// function pointers.
|
||||
|
||||
// Unchecked function pointers
|
||||
void fn200(void (*fnptr)(array_ptr<int> p1 : count(5)));
|
||||
void fn201(void (*fnptr)(int p1 : count(5))); // expected-error {{expected 'p1' to have a pointer or array type}}
|
||||
void fn202(void (*fnptr)(array_ptr<void> p1 : count(5))); // expected-error {{expected 'p1' to have a non-void pointer type}}
|
||||
void fn200(void (*fnptr)(int* _Array p1 _Count(5)));
|
||||
void fn201(void (*fnptr)(int p1 _Count(5))); // expected-error {{expected 'p1' to have a pointer or array type}}
|
||||
void fn202(void (*fnptr)(void* _Array p1 _Count(5))); // expected-error {{expected 'p1' to have a non-void pointer type}}
|
||||
|
||||
void fn203(int (*fnptr)(array_ptr<int> p1 : byte_count(5 * sizeof(int))));
|
||||
void fn204(int (*fnptr)(int * : byte_count(5 * sizeof(int))));
|
||||
|
@ -1039,8 +1040,8 @@ void fn231(ptr<void (array_ptr<void> p1 : bounds((char *)p1, (char *)p1 + (5 * s
|
|||
|
||||
// Function pointers with multiple arguments.
|
||||
void fn240(ptr<int (array_ptr<int> mid : bounds(p1, p1 + 5), array_ptr<int> p1)> fnptr);
|
||||
void fn241(ptr<int (array_ptr<void> mid : bounds((char *)p1, (char *)p1 + (5 * sizeof(int))),
|
||||
array_ptr<int> p1)> fnptr);
|
||||
void fn241(ptr<int (void* _Array mid _Bounds((char *)p1, (char *)p1 + (5 * sizeof(int))),
|
||||
int* _Array p1)> fnptr);
|
||||
|
||||
//
|
||||
// Spot check bounds-safe interfaces on parameters of function pointer types
|
||||
|
@ -1056,7 +1057,7 @@ void fn252(int(*fnptr)(int *p1 : bounds(p1, p1 + 5)));
|
|||
void fn260(array_ptr<int> (*fnptr)(void) : count(5));
|
||||
void fn261(array_ptr<int>(*fnptr)(int i) : count(i));
|
||||
void fn262(int (*fnptr)(void) : count(5)); // expected-error {{count bounds expression only allowed for pointer return type}}
|
||||
void fn263(array_ptr<void> (*fnptr)(void) : count(5)); // expected-error {{count bounds expression not allowed for a void pointer return type}}
|
||||
void fn263(void* _Array (*fnptr)(void) _Count(5)); // expected-error {{count bounds expression not allowed for a void pointer return type}}
|
||||
|
||||
//
|
||||
// Test bounds declarations for function pointers
|
||||
|
@ -1065,7 +1066,7 @@ void fn263(array_ptr<void> (*fnptr)(void) : count(5)); // expected-error {{count
|
|||
void function_pointers(void) {
|
||||
// Assignments to function pointers with return bounds on array_ptr types
|
||||
array_ptr<int>(*t1)(void) : count(5) = fn1;
|
||||
nt_array_ptr<int>(*t1a)(void) : count(0) = fn1a;
|
||||
int* _Nt_array(*t1a)(void) _Count(0) = fn1a;
|
||||
// Assignment to function pointers with bounds-safe interfaces on
|
||||
// unchecked pointer return types. Unchecked pointers are compatible with
|
||||
// unchecked pointers with bounds-safe interfaces. This extends recursively
|
||||
|
@ -1079,13 +1080,13 @@ void function_pointers(void) {
|
|||
ptr<int *(int j) : count(j)> t7 = fn3;
|
||||
|
||||
array_ptr<int>(*t8)(void) : byte_count(5 * sizeof(int)) = fn4;
|
||||
array_ptr<void>(*t9)(void) : byte_count(5 * sizeof(int)) = fn5;
|
||||
void* _Array(*t9)(void) _Byte_count(5 * sizeof(int)) = fn5;
|
||||
int *(*t10)(void) = fn6;
|
||||
int *(*t11)(void) : byte_count(5*sizeof(int)) = fn6;
|
||||
ptr<int *(void) : byte_count(5*sizeof(int))> t12 = fn6;
|
||||
|
||||
array_ptr<int>(*t13)(void) : bounds(s1, s1 + 5) = fn10;
|
||||
nt_array_ptr<int>(*t13a)(void) : bounds(s1, s1 + 5) = fn10a;
|
||||
int* _Nt_array(*t13a)(void) _Bounds(s1, s1 + 5) = fn10a;
|
||||
int *(*t14)(void) = fn12;
|
||||
int *(*t15)(void) : bounds(s1, s1 + 5) = fn12;
|
||||
int *(*t16)(void) : bounds(s1, s1 + 6) = fn12; // expected-warning {{incompatible function pointer types}}
|
||||
|
@ -1095,7 +1096,7 @@ void function_pointers(void) {
|
|||
// function.
|
||||
ptr<array_ptr<int>(void) : count(5)> t100 = fn1;
|
||||
// The reverse is not allowed
|
||||
array_ptr<int>(*t101)(void) : count(5) = t100; // expected-error {{incompatible type}}
|
||||
int* _Array(*t101)(void) _Count(5) = t100; // expected-error {{incompatible type}}
|
||||
|
||||
// Calls that pass function pointers with bounds
|
||||
fn200(fn100);
|
||||
|
@ -1143,7 +1144,7 @@ void invalid_function_pointers(void) {
|
|||
array_ptr<int>(*t1)(void) : count(4) = fn1; // expected-error {{incompatible type}}
|
||||
ptr<array_ptr<int>(void) : count(4)> t1a = fn1; // expected-error {{incompatible type}}
|
||||
array_ptr<int>(*t4)(void) : byte_count(6 * sizeof(int)) = fn4; // expected-error {{incompatible type}}
|
||||
array_ptr<int>(*t10)(void) : bounds(s1, s1 + 4) = fn10; // expected-error {{incompatible type}}
|
||||
int* _Array(*t10)(void) _Bounds(s1, s1 + 4) = fn10; // expected-error {{incompatible type}}
|
||||
}
|
||||
|
||||
// Test type checking of return_value
|
||||
|
@ -1154,4 +1155,4 @@ array_ptr<int> f301(void) : bounds(return_value, return_value + 10);
|
|||
array_ptr<int> f302(void) : bounds(return_value - 5, return_value + 5);
|
||||
array_ptr<int> f303(void) : count(return_value); // expected-error {{invalid argument type}}
|
||||
array_ptr<int> f304(void) : bounds(arr, arr + (return_value << 5)); // expected-error {{invalid operands to binary expression}}
|
||||
array_ptr<void> f305(void) : bounds(return_value, return_value + 5); // expected-error {{arithmetic on a pointer to void}}
|
||||
void* _Array f305(void) _Bounds(return_value, return_value + 5); // expected-error {{arithmetic on a pointer to void}}
|
||||
|
|
|
@ -147,8 +147,8 @@ extern void check_assign(int val, int p[10], int q[], int r checked[10], int s c
|
|||
array_ptr<int> t10 = s;
|
||||
array_ptr<int> t9b = w;
|
||||
array_ptr<int> t11 = t;
|
||||
array_ptr<int> t11a = u;
|
||||
array_ptr<int> t12 = u;
|
||||
int* _Array t11a = u;
|
||||
int* _Array t12 = u;
|
||||
nt_array_ptr<int> t12a = x;
|
||||
nt_array_ptr<int> t12b = u; // expected-error {{expression of incompatible type 'int _Checked[10]'}}
|
||||
array_ptr<int> t13 = s2d[0];
|
||||
|
@ -158,8 +158,8 @@ extern void check_assign(int val, int p[10], int q[], int r checked[10], int s c
|
|||
array_ptr<int> t14 = t2d[0];
|
||||
array_ptr<int> t15 = u2d[0];
|
||||
array_ptr<int> t15a = x2d[0];
|
||||
nt_array_ptr<int> t15b : bounds(unknown) = x2d[0];
|
||||
nt_array_ptr<int> t15c = u2d[0]; // expected-error {{expression of incompatible type 'int _Checked[10]'}}
|
||||
int* _Nt_array t15b _Bounds(unknown) = x2d[0];
|
||||
int* _Nt_array t15c = u2d[0]; // expected-error {{expression of incompatible type 'int _Checked[10]'}}
|
||||
|
||||
// Multi-dimensional array type conversions to pointer types.
|
||||
int *t16 = s2d[0]; // expected-error {{expression of incompatible type 'int _Checked[10]'}}
|
||||
|
@ -471,9 +471,9 @@ extern void check_condexpr(int val) {
|
|||
|
||||
// N and M are arbitrary positive integer constants below.
|
||||
int *t1 = val ? p : p; // T[N] and T[M] OK;
|
||||
array_ptr<int> t2 = val ? p : r; // T[N] and T checked[M] OK
|
||||
array_ptr<int> t2a = val ? p : v; // T[N] and T nt_checked[M] OK.
|
||||
nt_array_ptr<int> t2b = val ? p : v; // expected-error {{incompatible type}}
|
||||
int* _Array t2 = val ? p : r; // T[N] and T checked[M] OK
|
||||
int* _Array t2a = val ? p : v; // T[N] and T nt_checked[M] OK.
|
||||
int* _Nt_array t2b = val ? p : v; // expected-error {{incompatible type}}
|
||||
// T[N] and T nt_checked[M] produce
|
||||
// only array_ptr.
|
||||
array_ptr<int> t3 = val ? r : p; // T checked[N] and T[M] OK
|
||||
|
@ -487,7 +487,7 @@ extern void check_condexpr(int val) {
|
|||
// But they produce only array_ptr.
|
||||
nt_array_ptr<int> t4d = val ? v : r; // expected-error {{incompatible type}}
|
||||
// But they produce only array_ptr
|
||||
nt_array_ptr<int> t4e = val ? v : v; // T nt_checked[M] and T nt_checked[N] OK.
|
||||
int* _Nt_array t4e = val ? v : v; // T nt_checked[M] and T nt_checked[N] OK.
|
||||
|
||||
// omit assignment because type of expression is not valid when there is an error.
|
||||
val ? s : r; // expected-error {{pointer type mismatch}}
|
||||
|
@ -514,9 +514,9 @@ extern void check_condexpr(int val) {
|
|||
array_ptr<int> t5 = val ? r : 0;
|
||||
array_ptr<int> t5a = val ? v : 0;
|
||||
array_ptr<int> t6 = val ? 0 : r;
|
||||
nt_array_ptr<int> t6a = val ? 0 : v; // expected-warning {{cannot prove declared bounds for 't6a' are valid after initialization}}
|
||||
int* _Nt_array t6a = val ? 0 : v; // expected-warning {{cannot prove declared bounds for 't6a' are valid after initialization}}
|
||||
array_ptr<float> t7 = val ? u : 0;
|
||||
array_ptr<float> t8 = val ? 0 : u;
|
||||
float* _Array t8 = val ? 0 : u;
|
||||
}
|
||||
|
||||
extern void check_condexpr_2d(int val) {
|
||||
|
@ -621,7 +621,7 @@ extern void check_condexpr_cv(void)
|
|||
array_ptr<const int> t32 = val ? r_const : r; // array_ptr<const int> and array_ptr<int> OK
|
||||
array_ptr<const int> t33 = val ? r_const : r_const; // array_ptr<const int> and array_ptr<const int> OK
|
||||
|
||||
array_ptr<const int> t25a = val ? p : s_const; // int * and nt_array_ptr<const int> OK
|
||||
const int* _Array t25a = val ? p : s_const; // int * and nt_array_ptr<const int> OK
|
||||
array_ptr<const int> t26a = val ? s_const : p; // nt_array_ptr<const int> and int * OK
|
||||
array_ptr<const int> t27a = val ? p_const : s; // const int * and nt_array_ptr<int> OK
|
||||
array_ptr<const int> t28a = val ? s : p_const; // nt_array_ptr<int> and const int * OK
|
||||
|
@ -633,7 +633,7 @@ extern void check_condexpr_cv(void)
|
|||
array_ptr<const int> t33b = val ? r_const : s_const; // array_ptr<const int> and nt_array_ptr<const int> OK
|
||||
array_ptr<const int> t33c = val ? s : s_const; // nt_array_ptr<int> and nt_array_ptr<const int> OK
|
||||
array_ptr<const int> t33d = val ? s_const : s; // nt_array_ptr<const int> and nt_array_ptr<int> OK
|
||||
array_ptr<const int> t33e = val ? s_const : s_const; // nt_array_ptr<const int> and nt_array_ptr<const int> OK
|
||||
const int* _Array t33e = val ? s_const : s_const; // nt_array_ptr<const int> and nt_array_ptr<const int> OK
|
||||
|
||||
array_ptr<int> t34 = val ? p : r_const; // expected-warning {{discards qualifiers}}
|
||||
// int * and array_ptr<const int> produce array_ptr<const int>
|
||||
|
@ -651,8 +651,8 @@ extern void check_condexpr_cv(void)
|
|||
// array_ptr<int> and array_ptr<const int> produce array_ptr<const int>
|
||||
array_ptr<int> t41 = val ? r_const : r; // expected-warning {{discards qualifiers}}
|
||||
// array_ptr<const int> and array_ptr<int> produce array_ptr<const int>
|
||||
array_ptr<int> t42 = val ? r_const : r_const; // expected-warning {{discards qualifiers}}
|
||||
// array_ptr<const int> and array_ptr<const int> produce array_ptr<const int>
|
||||
int* _Array t42 = val ? r_const : r_const; // expected-warning {{discards qualifiers}}
|
||||
// array_ptr<const int> and array_ptr<const int> produce array_ptr<const int>
|
||||
|
||||
array_ptr<int> t34a = val ? p : s_const; // expected-warning {{discards qualifiers}}
|
||||
// int * and nt_array_ptr<const int> produce array_ptr<const int>
|
||||
|
@ -680,7 +680,7 @@ extern void check_condexpr_cv(void)
|
|||
// nt_array_ptr<int> and nt_array_ptr<const int> produce array_ptr<const int>
|
||||
array_ptr<int> t43d = val ? s_const : s; // expected-warning {{discards qualifiers}}
|
||||
// nt_array_ptr<const int> and nt_array_ptr<int> produce array_ptr<const int>
|
||||
array_ptr<int> t42e = val ? s_const : s_const; // expected-warning {{discards qualifiers}}
|
||||
int* _Array t42e = val ? s_const : s_const; // expected-warning {{discards qualifiers}}
|
||||
// nt_array_ptr<const int> and nt_array_ptr<const int> produce array_ptr<const int>
|
||||
|
||||
// test different kinds of pointers with volatile modifers
|
||||
|
@ -719,7 +719,7 @@ extern void check_condexpr_cv(void)
|
|||
array_ptr<volatile int> t82d = val ? s_volatile : s; // nt_array_ptr<volatile int> and nt_array_ptr<int> OK
|
||||
array_ptr<volatile int> t82e = val ? s_volatile : s_volatile; // nt_array_ptr<volatile int> and nt_array_ptr<volatile int> OK
|
||||
|
||||
array_ptr<int> t83 = val ? p : r_volatile; // expected-warning {{discards qualifiers}}
|
||||
int* _Array t83 = val ? p : r_volatile; // expected-warning {{discards qualifiers}}
|
||||
// int * and array_ptr<volatile int> produce array_ptr<volatile int>
|
||||
array_ptr<int> t84 = val ? r_volatile : p; // expected-warning {{discards qualifiers}}
|
||||
// array_ptr<volatile int> and int * produce array_ptr<volatile int>
|
||||
|
@ -762,7 +762,7 @@ extern void check_condexpr_cv(void)
|
|||
// nt_array_ptr<int> and nt_array_ptr<volatile int> produce array_ptr<volatile int>
|
||||
array_ptr<int> t92d = val ? s_volatile : s; // expected-warning {{discards qualifiers}}
|
||||
// nt_array_ptr<volatile int> and nt_array_ptr<int> produce array_ptr<volatile int>
|
||||
array_ptr<int> t92e = val ? s_volatile : s_volatile; // expected-warning {{discards qualifiers}}
|
||||
int* _Array t92e = val ? s_volatile : s_volatile; // expected-warning {{discards qualifiers}}
|
||||
// nt_array_ptr<volatile int> and nt_array_ptr<volatile int> produce array_ptr<volatile int>
|
||||
}
|
||||
|
||||
|
@ -827,7 +827,7 @@ extern void f13(_Bool p, int y) {
|
|||
extern void f1_void(void *p, int y) {
|
||||
}
|
||||
|
||||
extern void f2_void(ptr<void> p, int y) {
|
||||
extern void f2_void(void* _Single p, int y) {
|
||||
}
|
||||
|
||||
extern void f3_void(array_ptr<void> p, int y) {
|
||||
|
@ -1037,7 +1037,7 @@ extern void check_call_void(void) {
|
|||
|
||||
// TODO: s will need bounds information
|
||||
void *s = 0;
|
||||
ptr<void> t = 0;
|
||||
void* _Single t = 0;
|
||||
array_ptr<void> u = 0;
|
||||
|
||||
// Test different kinds of pointers where the parameter type is a pointer to void and
|
||||
|
@ -1885,14 +1885,14 @@ extern void check_vla(int i) {
|
|||
|
||||
// Test assigning an unchecked pointer with an nt_array_ptr
|
||||
// bounds-safe interface to a checked nt_array_ptr.
|
||||
extern void check_nt_bounds_safe_interface(const char *interop_string : itype(nt_array_ptr<const char>),
|
||||
char **interop_ptr : itype(nt_array_ptr<ptr<char>>),
|
||||
extern void check_nt_bounds_safe_interface(const char *interop_string : itype(const char* _Nt_array),
|
||||
char **interop_ptr _Itype(nt_array_ptr<ptr<char>>),
|
||||
char checked_arr nt_checked[3],
|
||||
char unchecked_arr[3]) {
|
||||
// LHS of assignment has nt_array_ptr<T> type and RHS of assignment
|
||||
// is an unchecked pointer with nt_array_ptr<T> bounds-safe interface.
|
||||
nt_array_ptr<const char> checked_str = interop_string;
|
||||
nt_array_ptr<ptr<char>> checked_ptr = interop_ptr;
|
||||
const char* _Nt_array checked_str = interop_string;
|
||||
char* _Single * _Nt_array checked_ptr = interop_ptr;
|
||||
|
||||
// LHS of assignment has nt_array_ptr<T> type and RHS of assigment
|
||||
// is an unchecked pointer with nt_array_ptr<U> bounds-safe interface,
|
||||
|
|
|
@ -89,8 +89,8 @@ scope must have a pointer, array or function type that uses only checked types o
|
|||
//
|
||||
|
||||
int *t40[10]; // expected-error {{local variable in a checked scope must have a checked type}}
|
||||
ptr<int> t41[10]; // expected-error {{local variable in a checked scope must have a checked type}}
|
||||
array_ptr<int> t42[10]; // expected-error {{local variable in a checked scope must have a checked type}}
|
||||
int* _Single t41[10]; // expected-error {{local variable in a checked scope must have a checked type}}
|
||||
int* _Array t42[10]; // expected-error {{local variable in a checked scope must have a checked type}}
|
||||
|
||||
int *t43 checked[10]; // expected-error {{local variable in a checked \
|
||||
scope must have a pointer, array or function type that uses only checked types or parameter/return types with bounds-safe interfaces}}
|
||||
|
@ -101,7 +101,7 @@ scope must have a pointer, array or function type that uses only checked types o
|
|||
scope must have a pointer, array or function type that uses only checked types or parameter/return types with bounds-safe interfaces}}
|
||||
ptr<int> *t47 checked[10][15]; // expected-error {{local variable in a checked \
|
||||
scope must have a pointer, array or function type that uses only checked types or parameter/return types with bounds-safe interfaces}}
|
||||
array_ptr<int> t48 checked[3][2] = {0};
|
||||
int* _Array t48 checked[3][2] = {0};
|
||||
|
||||
//
|
||||
// Checked pointers to function types that use constructed types.
|
||||
|
@ -111,7 +111,7 @@ scope must have a pointer, array or function type that uses only checked types o
|
|||
ptr<int *(int, int)> t60 = 0; // expected-error {{local variable in a checked \
|
||||
scope must have a pointer, array or function type that uses only checked types or parameter/return types with bounds-safe interfaces}}
|
||||
ptr<ptr<int>(int, int)> t61 = 0;
|
||||
ptr<array_ptr<int>(int, int)> t62 = 0;
|
||||
ptr<int* _Array(int, int)> t62 = 0;
|
||||
|
||||
// Function with different kinds of pointer arguments.
|
||||
ptr<void(int *)> t63 = 0; // expected-error {{local variable in a checked \
|
||||
|
@ -144,7 +144,7 @@ SCOPE_KIND int func4(int p[]) { // expected-error {{parameter in a checked scop
|
|||
return 0;
|
||||
}
|
||||
|
||||
SCOPE_KIND int func5(ptr<int> p, int *q) { // expected-error {{parameter in a checked scope must have a checked type or a bounds-safe interface}}
|
||||
SCOPE_KIND int func5(int* _Single p, int *q) { // expected-error {{parameter in a checked scope must have a checked type or a bounds-safe interface}}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -165,7 +165,7 @@ SCOPE_KIND int func9(ptr<int> p) {
|
|||
}
|
||||
|
||||
// Test for checked function specifier & checked block.
|
||||
int* func11(array_ptr<int> x, int len) SCOPE_KIND {
|
||||
int* func11(int* _Array x, int len) SCOPE_KIND {
|
||||
int *upa; // expected-error {{local variable in a checked scope must have a checked type}}
|
||||
return upa;
|
||||
}
|
||||
|
@ -261,14 +261,14 @@ int a, b, c;
|
|||
}
|
||||
|
||||
int KNR_func5(a, b)
|
||||
ptr<int> a;
|
||||
int* _Single a;
|
||||
int b;
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int KNR_func6(a, b)
|
||||
ptr<char> a;
|
||||
char*_Single a;
|
||||
ptr<int> b;
|
||||
{
|
||||
return 1;
|
||||
|
@ -277,7 +277,7 @@ ptr<int> b;
|
|||
#pragma CHECKED_SCOPE ON
|
||||
void KNR_test(void) {
|
||||
ptr<int> px = 0;
|
||||
ptr<char> py = 0;
|
||||
char*_Single py = 0;
|
||||
int a,b,c;
|
||||
KNR_func4(a,b,c); // expected-error {{function without a prototype cannot be used or declared in a checked scope}}
|
||||
KNR_func5(px,a); // expected-error {{function without a prototype cannot be used or declared in a checked scope}}
|
||||
|
@ -302,7 +302,7 @@ int func20(void) SCOPE_KIND {
|
|||
int func21(void) {
|
||||
SCOPE_KIND {
|
||||
int a = 5;
|
||||
ptr<int> pa = &a;
|
||||
int* _Single pa = &a;
|
||||
int b checked[5][5];
|
||||
for (int i = 0; i < 5; i++) {
|
||||
for (int j = 0; j < 5; j++) {
|
||||
|
@ -389,8 +389,8 @@ checked void func27(void) {
|
|||
|
||||
void func28(void) {
|
||||
int *upa;
|
||||
array_ptr<int> pb;
|
||||
ptr<int> pc = 0;
|
||||
int* _Array pb;
|
||||
int* _Single pc = 0;
|
||||
}
|
||||
|
||||
int func29(void) {
|
||||
|
@ -401,10 +401,10 @@ int func29(void) {
|
|||
int *a; // expected-error {{member in a checked scope must have a checked type}}
|
||||
char *b; // expected-error {{member in a checked scope must have a checked type}}
|
||||
ptr<int> pc;
|
||||
array_ptr<int> pd : count(len);
|
||||
int* _Array pd _Count(len);
|
||||
int len;
|
||||
short e[10]; // expected-error {{member in a checked scope must have a checked type}}
|
||||
int *f : itype(ptr<int>);
|
||||
int *f : itype(int* _Single);
|
||||
char *g : itype(array_ptr<char>);
|
||||
} a = {0};
|
||||
}
|
||||
|
@ -414,7 +414,7 @@ int func29(void) {
|
|||
void func30(void) {
|
||||
int a = 5;
|
||||
int len = 10;
|
||||
array_ptr<int> pa : count(len) = 0;
|
||||
int* _Array pa _Count(len) = 0;
|
||||
/// checked is a function declaration specifier unless followed by '{' or '['
|
||||
checked int len2; // expected-error {{'_Checked' can only appear on functions}}
|
||||
checked [5][5]; // expected-error {{expected identifier}}
|
||||
|
@ -427,7 +427,7 @@ SCOPE_KIND int * func40(int *p, int *q) unchecked {// expected-error {{return in
|
|||
// expected-error 2 {{parameter in a checked scope must have a checked type or a bounds-safe interface}}
|
||||
int a = 5;
|
||||
*p = *q = 0;
|
||||
ptr<int> pa = &a;
|
||||
int* _Single pa = &a;
|
||||
int b[5][5];
|
||||
for (int i = 0; i < 5; i++) {
|
||||
for (int j = 0; j < 5; j++) {
|
||||
|
@ -437,7 +437,7 @@ SCOPE_KIND int * func40(int *p, int *q) unchecked {// expected-error {{return in
|
|||
return 0;
|
||||
}
|
||||
|
||||
SCOPE_KIND int * func41(int *p, ptr<int> q, array_ptr<int> r, array_ptr<int> s : count(2)) unchecked { // expected-error {{return in a checked scope must have a checked type or a bounds-safe interface}} \
|
||||
SCOPE_KIND int * func41(int *p, int* _Single q, int* _Array r, int* _Array s _Count(2)) unchecked { // expected-error {{return in a checked scope must have a checked type or a bounds-safe interface}} \
|
||||
// expected-error {{parameter in a checked scope must have a checked type or a bounds-safe interface}}
|
||||
int a = 5;
|
||||
checked {
|
||||
|
@ -540,7 +540,7 @@ SCOPE_KIND int func45(int *p, int *q) unchecked { // expected-error 2 {{paramete
|
|||
int func46(ptr<int> p, int *q) unchecked {
|
||||
int a = 5;
|
||||
int *upa;
|
||||
array_ptr<int> pc;
|
||||
int* _Array pc;
|
||||
SCOPE_KIND {
|
||||
upa = &a; // expected-error {{local variable used in a checked scope must have a checked type}}
|
||||
pc = &a;
|
||||
|
@ -551,11 +551,11 @@ int func46(ptr<int> p, int *q) unchecked {
|
|||
upa = &a; // expected-error {{local variable used in a checked scope must have a checked type}}
|
||||
pc = &a;
|
||||
}
|
||||
ptr<int> pb = p;
|
||||
int* _Single pb = p;
|
||||
return *pb;
|
||||
}
|
||||
|
||||
SCOPE_KIND array_ptr<int> func47(void) {
|
||||
SCOPE_KIND int* _Array func47(void) {
|
||||
int *upa; // expected-error {{local variable in a checked scope must have a checked type}}
|
||||
unchecked {
|
||||
int *upb;
|
||||
|
@ -590,7 +590,7 @@ int func49(void) {
|
|||
int len;
|
||||
short e[10];
|
||||
char f[10];
|
||||
int *g : itype(ptr<int>);
|
||||
int *g : itype(int* _Single);
|
||||
char *h : itype(array_ptr<char>);
|
||||
} b; // expected-error {{containing a checked pointer must have an initializer}}
|
||||
|
||||
|
@ -613,7 +613,7 @@ unchecked int * func50(int *p, int *q) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
unchecked int * func51(int *p, ptr<int> q, array_ptr<int> r, array_ptr<int> s : count(2)) {
|
||||
unchecked int * func51(int *p, int* _Single q, int* _Array r, array_ptr<int> s : count(2)) {
|
||||
int a = 5;
|
||||
SCOPE_KIND {
|
||||
*p = 1; // expected-error {{parameter used in a checked scope must have a checked type or a bounds-safe interface}}
|
||||
|
@ -632,7 +632,7 @@ unchecked int * func51(int *p, ptr<int> q, array_ptr<int> r, array_ptr<int> s :
|
|||
return 0;
|
||||
}
|
||||
|
||||
unchecked int func52(ptr<int> p, int q[], int r[5]) unchecked {
|
||||
unchecked int func52(int* _Single p, int q[], int r[5]) unchecked {
|
||||
int a = 5;
|
||||
checked {
|
||||
int *upa = &a; // expected-error {{local variable in a checked scope must have a checked type}}
|
||||
|
@ -866,9 +866,9 @@ void test_addrof_checked_scope(void) SCOPE_KIND {
|
|||
x = b; // BinaryOperator (ImplicitCastExpr _Ptr (_Array_ptr)) \
|
||||
// expected-error {{expression has unknown bounds, cast to ptr<T> expects source to have bounds}}
|
||||
|
||||
array_ptr<int> ax = &a[i];
|
||||
array_ptr<int> ay = &b[2];
|
||||
array_ptr<int> az = &i;
|
||||
int* _Array ax = &a[i];
|
||||
int* _Array ay = &b[2];
|
||||
int* _Array az = &i;
|
||||
|
||||
ax = &a[i];
|
||||
ay = &b[3];
|
||||
|
@ -879,7 +879,7 @@ void test_addrof_checked_scope(void) SCOPE_KIND {
|
|||
// &b[i] result type = array_ptr<int>
|
||||
array_ptr<int> px = &(*(b+i));
|
||||
array_ptr<int> py = &b[i];
|
||||
array_ptr<int> pz = &(*(a+i));
|
||||
int* _Array pz = &(*(a+i));
|
||||
|
||||
px = &(*(b+i));
|
||||
py = &b[i];
|
||||
|
@ -911,9 +911,9 @@ void test_addrof_unchecked_scope(void) unchecked {
|
|||
// expected-error {{expression has unknown bounds, cast to ptr<T> expects source to have bounds}}
|
||||
|
||||
// checkSingleAssignmentConstraints(int * -> _Array_ptr<int> implicit casting)
|
||||
array_ptr<int> ax = &a[i]; // ImplicitCastExpr _Array_ptr<int>(UnaryOperator)
|
||||
array_ptr<int> ay = &b[0]; // ImplicitCastExpr _Array_ptr<int>(UnaryOperator)
|
||||
array_ptr<int> az = &i; // ImplicitCastExpr _Array_ptr<int>(UnaryOperator)
|
||||
int* _Array ax = &a[i]; // ImplicitCastExpr _Array_ptr<int>(UnaryOperator)
|
||||
int* _Array ay = &b[0]; // ImplicitCastExpr _Array_ptr<int>(UnaryOperator)
|
||||
int* _Array az = &i; // ImplicitCastExpr _Array_ptr<int>(UnaryOperator)
|
||||
|
||||
ax = &a[i]; // ImplicitCastExpr _Array_ptr<int>(UnaryOperator)
|
||||
ay = &b[0]; // ImplicitCastExpr _Array_ptr<int>(UnaryOperator)
|
||||
|
@ -935,8 +935,8 @@ void test_addrof_unchecked_scope(void) unchecked {
|
|||
pz = &(*(a+i)); // UnaryOperator _Array_ptr<int>()
|
||||
}
|
||||
|
||||
int *gptr0 : itype(ptr<int>);
|
||||
int *gptr1 : itype(array_ptr<int>);
|
||||
int *gptr0 _Itype(ptr<int>);
|
||||
int *gptr1 _Itype(array_ptr<int>);
|
||||
int *gptr2;
|
||||
|
||||
extern void check_indirection_unchecked(int p[10], const int const_p[10], int y) SCOPE_KIND {
|
||||
|
@ -981,7 +981,8 @@ extern void check_assign(int val, int p[10], int q[], int r checked[10], int s c
|
|||
// not propagate through typedefs
|
||||
|
||||
int *t1, *t2, *t3, *t4, *t5, *t6;
|
||||
array_ptr<int> t7, t8, t9, t10, t11, t12, t13, t14, t15;
|
||||
int* _Array t7, *_Array t8, *_Array t9,
|
||||
*_Array t10,*_Array t11,*_Array t12,*_Array t13,*_Array t14,*_Array t15;
|
||||
int *t16, *t17, *t18;
|
||||
int (*t19)[10];
|
||||
int (*t20)[10];
|
||||
|
@ -1122,7 +1123,7 @@ extern void f13(_Bool p, int y) {
|
|||
extern void f1_void(void *p, int y) {
|
||||
}
|
||||
|
||||
extern void f2_void(ptr<void> p, int y) {
|
||||
extern void f2_void(void* _Single p, int y) {
|
||||
}
|
||||
|
||||
extern void f3_void(array_ptr<void> p, int y) {
|
||||
|
@ -1228,7 +1229,7 @@ SCOPE_KIND int *h3(void) { // expected-error {{return in a checked scope must
|
|||
return global; // expected-error {{variable used in a checked scope must have a checked type}}
|
||||
}
|
||||
|
||||
SCOPE_KIND ptr<int> h4(void) {
|
||||
SCOPE_KIND int* _Single h4(void) {
|
||||
return global; // expected-error {{variable used in a checked scope must have a checked type}}
|
||||
}
|
||||
|
||||
|
@ -1256,7 +1257,7 @@ SCOPE_KIND ptr<int> h10(void) {
|
|||
return global_arr1; // expected-error {{variable used in a checked scope must have a checked type}}
|
||||
}
|
||||
|
||||
SCOPE_KIND array_ptr<int> h11(int arr checked[10]) {
|
||||
SCOPE_KIND int* _Array h11(int arr checked[10]) {
|
||||
return arr;
|
||||
}
|
||||
|
||||
|
@ -1276,7 +1277,7 @@ SCOPE_KIND int *h15(int arr checked[]) { // expected-error {{return in a check
|
|||
return 0;
|
||||
}
|
||||
|
||||
SCOPE_KIND array_ptr<int> h18(int arr checked[]) {
|
||||
SCOPE_KIND int* _Array h18(int arr checked[]) {
|
||||
return arr;
|
||||
}
|
||||
|
||||
|
@ -1286,7 +1287,8 @@ SCOPE_KIND int(*h19(int arr[10][10]))[10]{ // expected-error {{return in a che
|
|||
}
|
||||
|
||||
int global_arr2[10][10];
|
||||
SCOPE_KIND ptr<int[10]> h20(void) { // expected-error {{must have a pointer, array or function type that uses only checked types or parameter/return types with bounds-safe interfaces}}
|
||||
typedef int unchecked_arr_type[10];
|
||||
SCOPE_KIND unchecked_arr_type* _Single h20(void) { // expected-error {{must have a pointer, array or function type that uses only checked types or parameter/return types with bounds-safe interfaces}}
|
||||
return global_arr2; // expected-error {{variable used in a checked scope must have a checked type}}
|
||||
}
|
||||
|
||||
|
@ -1365,7 +1367,7 @@ void check_pointer_difference(int flag) {
|
|||
float val_float[5];
|
||||
int *p_int = val_int;
|
||||
float *p_float = val_float;
|
||||
array_ptr<int> r_int = val_int;
|
||||
int* _Array r_int = val_int;
|
||||
|
||||
int a_int[5];
|
||||
int checked_a_int checked[5];
|
||||
|
@ -1404,13 +1406,13 @@ void check_pointer_compare(void) {
|
|||
int *p_int = val_int;
|
||||
float *p_float = val_float;
|
||||
|
||||
ptr<int> q_int = 0;
|
||||
int* _Single q_int = 0;
|
||||
q_int = val_int;
|
||||
ptr<float> q_float = 0;
|
||||
float* _Single q_float = 0;
|
||||
q_float = val_float;
|
||||
|
||||
array_ptr<int> r_int = val_int;
|
||||
array_ptr<float> r_float = val_float;
|
||||
float* _Array r_float = val_float;
|
||||
|
||||
SCOPE_KIND {
|
||||
// relational comparisons between pointers and unchecked arrays;
|
||||
|
@ -1517,7 +1519,7 @@ SCOPE_KIND void check_cast_operator(void) {
|
|||
aparr = (array_ptr<int [5]>) &arr; // expected-error {{type in a checked scope must use only checked types or parameter/return types with bounds-safe interfaces}}
|
||||
|
||||
// ptr to variadic/unchecked func pointer
|
||||
ptr<int(int,int)> vpa = 0;
|
||||
int (* _Single vpa)(int,int) = 0;
|
||||
vpa = (ptr<int(int,...)>) &arr; // expected-error {{type in a checked scope cannot have variable arguments}}
|
||||
vpa = (ptr<int(int,ptr<int(int, ...)>)>) &arr; // expected-error {{type in a checked scope cannot have variable arguments}}
|
||||
vpa = (ptr<int*(int,int)>) &arr; // expected-error {{type in a checked scope must use only checked types or parameter/return types with bounds-safe interfaces}}
|
||||
|
@ -1550,8 +1552,8 @@ SCOPE_KIND void check_cast_operator(void) {
|
|||
|
||||
unchecked {
|
||||
int *p;
|
||||
ptr<int> q = 0;
|
||||
array_ptr<int> r : count(5) = 0;
|
||||
int* _Single q = 0;
|
||||
int* _Array r _Count(5) = 0;
|
||||
SCOPE_KIND {
|
||||
p = _Dynamic_bounds_cast<int *>(q); // expected-error {{local variable used in a checked scope must have a checked type}} \
|
||||
// expected-error {{type in a checked scope must be a checked pointer or array type}} \
|
||||
|
@ -1570,8 +1572,8 @@ SCOPE_KIND void check_cast_operator(void) {
|
|||
|
||||
vpa = _Assume_bounds_cast<ptr<int(int,...)>>(r); // expected-error {{_Assume_bounds_cast not allowed in a checked scope or function}}
|
||||
vpa = _Assume_bounds_cast<ptr<int(int,ptr<int(int, ...)>)>>(r); // expected-error {{_Assume_bounds_cast not allowed in a checked scope or function}}
|
||||
vpa = _Assume_bounds_cast<ptr<int*(int,int)>>(r); // expected-error {{_Assume_bounds_cast not allowed in a checked scope or function}}
|
||||
vpa = _Assume_bounds_cast<ptr<int(int,ptr<int(int, ...)>, ...)>>(r); // expected-error {{_Assume_bounds_cast not allowed in a checked scope or function}}
|
||||
vpa = _Assume_bounds_cast_M_N(ptr<int*(int,int)> ,r); // expected-error {{_Assume_bounds_cast not allowed in a checked scope or function}}
|
||||
vpa = _Assume_bounds_cast_M_N(ptr<int(int,ptr<int(int, ...)>, ...)>, r); // expected-error {{_Assume_bounds_cast not allowed in a checked scope or function}}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1628,7 +1630,7 @@ void check_checked_constructed_type_variadic(void) SCOPE_KIND {
|
|||
ptr<int(int, ptr<int(int,int)>, ...)> e = 0; // expected-error {{variable in a checked scope cannot have variable arguments}}
|
||||
ptr<int(int, ptr<int(int,...)>, ...)> f = 0; // expected-error {{variable in a checked scope cannot have variable arguments}}
|
||||
int (*g)(int, ...); // expected-error {{local variable in a checked scope must have a checked type}} //expected-error {{local variable in a checked scope cannot have variable arguments}}
|
||||
ptr<int*(int, int)> h = 0; // expected-error {{must have a pointer, array or function type that uses only checked types or parameter/return types with bounds-safe interfaces}}
|
||||
int* (*_Single h)(int, int) = 0; // expected-error {{must have a pointer, array or function type that uses only checked types or parameter/return types with bounds-safe interfaces}}
|
||||
|
||||
unchecked {
|
||||
ptr<int(int,...)> var_b = 0;
|
||||
|
@ -1660,7 +1662,7 @@ SCOPE_KIND void checked_check_variadic1(int (*fptr)(int, ptr<int>, array_ptr<int
|
|||
(*fptr)(5, a, b, a, b, a);
|
||||
}
|
||||
|
||||
void checked_check_variadic2(int (*fptr)(int, ptr<int>, array_ptr<int>, ...)) SCOPE_KIND {
|
||||
void checked_check_variadic2(int (*fptr)(int, int* _Single, int* _Array, ...)) SCOPE_KIND {
|
||||
ptr<int> a = 0;
|
||||
array_ptr<int> b;
|
||||
(*fptr)(5, a, b, a, b, a); // expected-error {{parameter used in a checked scope must have a checked type or a bounds-safe interface}} \
|
||||
|
@ -1707,8 +1709,8 @@ extern void test_function_pointer(void) SCOPE_KIND {
|
|||
ptr<int(int*)> fn4 = &id_intp; // expected-error {{must have a pointer, array or function type that uses only checked types or parameter/return types with bounds-safe interfaces}}
|
||||
ptr<int(int*)> fn5 = id_intp; // expected-error {{must have a pointer, array or function type that uses only checked types or parameter/return types with bounds-safe interfaces}}
|
||||
|
||||
ptr<ptr<int>(ptr<int>)> fn8 = &id_checked_intp;
|
||||
ptr<ptr<int>(ptr<int>)> fn9 = id_checked_intp;
|
||||
int* _Single (*_Single fn8)(int* _Single) = &id_checked_intp;
|
||||
int* _Single (*_Single fn9)(int* _Single) = id_checked_intp;
|
||||
|
||||
int val0;
|
||||
// address-of (&) operator produces array_ptr<T> except for function type
|
||||
|
@ -1740,8 +1742,8 @@ extern void test_cast_to_nt_array_ptr(void) checked {
|
|||
nt_array_ptr<int> p6 = (nt_array_ptr<int>)arr_i; // expected-error {{'_Array_ptr<int>' cannot be cast to '_Nt_array_ptr<int>' in a checked scope because '_Array_ptr<int>' might not point to a null-terminated array}}
|
||||
p6 = (nt_array_ptr<int>)p5; // expected-error {{'_Array_ptr<int>' cannot be cast to '_Nt_array_ptr<int>' in a checked scope because '_Array_ptr<int>' might not point to a null-terminated array}}
|
||||
array_ptr<char> p7 : count(5) = arr_c;
|
||||
nt_array_ptr<char> p8 = (nt_array_ptr<char>)arr_c; // expected-error {{'_Array_ptr<char>' cannot be cast to '_Nt_array_ptr<char>' in a checked scope because '_Array_ptr<char>' might not point to a null-terminated array}}
|
||||
p8 = (nt_array_ptr<char>)p7; // expected-error {{'_Array_ptr<char>' cannot be cast to '_Nt_array_ptr<char>' in a checked scope because '_Array_ptr<char>' might not point to a null-terminated array}}
|
||||
char* _Nt_array p8 = (char* _Nt_array)arr_c; // expected-error {{'_Array_ptr<char>' cannot be cast to '_Nt_array_ptr<char>' in a checked scope because '_Array_ptr<char>' might not point to a null-terminated array}}
|
||||
p8 = (char* _Nt_array)p7; // expected-error {{'_Array_ptr<char>' cannot be cast to '_Nt_array_ptr<char>' in a checked scope because '_Array_ptr<char>' might not point to a null-terminated array}}
|
||||
|
||||
// Test casting nt_array_ptr to nt_array_ptr
|
||||
nt_array_ptr<char> p9 = "hello";
|
||||
|
@ -1756,8 +1758,8 @@ extern void test_cast_to_nt_array_ptr(void) checked {
|
|||
|
||||
// Test casting array_ptr to nt_array_ptr.
|
||||
p6 = (nt_array_ptr<int>)arr_i; // allowed here; disallowed in a checked scope.
|
||||
p6 = (nt_array_ptr<int>)p5; // allowed here; disallowed in a checked scope.
|
||||
p8 = (nt_array_ptr<char>)p7; // allowed here; disallowed in a checked scope.
|
||||
p6 = (int *_Nt_array)p5; // allowed here; disallowed in a checked scope.
|
||||
p8 = (char* _Nt_array)p7; // allowed here; disallowed in a checked scope.
|
||||
|
||||
// Test casting nt_array_ptr to nt_array_ptr
|
||||
p10 = (nt_array_ptr<char>)p9; // allowed in both checked and unchecked scopes.
|
||||
|
@ -1766,7 +1768,7 @@ extern void test_cast_to_nt_array_ptr(void) checked {
|
|||
int arr_i_unchecked[5];
|
||||
p6 = (nt_array_ptr<int>)arr_i_unchecked; // allowed
|
||||
char arr_c_unchecked[5];
|
||||
p8 = (nt_array_ptr<char>)arr_c_unchecked; // allowed
|
||||
p8 = (char* _Nt_array)arr_c_unchecked; // allowed
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#include <stdchecked.h>
|
||||
|
||||
// Parameters with simple types.
|
||||
checked int f1(int *s : itype(ptr<int>)) {
|
||||
checked int f1(int *s _Itype(int *_Single)) {
|
||||
int t1 = *s; // Allowed in checked scope.
|
||||
int t2 = *(s + 4); // expected-error {{arithmetic on _Ptr type}}
|
||||
int t3 = s[4]; // expected-error {{subscript of '_Ptr<int>'}}
|
||||
|
@ -32,8 +32,8 @@ checked int f1(int *s : itype(ptr<int>)) {
|
|||
array_ptr<int> t4 : count(1) = s;
|
||||
s = t4;
|
||||
|
||||
array_ptr<float> t5 : count(1) = s; // expected-error {{incompatible type}}
|
||||
array_ptr<float> t6 = 0;
|
||||
float* _Array t5 _Count(1) = s; // expected-error {{incompatible type}}
|
||||
float* _Array t6 = 0;
|
||||
s = t6; // expected-error {{incompatible type}}
|
||||
|
||||
return 0;
|
||||
|
@ -51,7 +51,7 @@ checked int f2(int *s : count(len), int len) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
checked int f3(int *s : itype(array_ptr<int>), int len) {
|
||||
checked int f3(int *s _Itype(int *_Array), int len) {
|
||||
array_ptr<int> t1 = s + 5; // allowed
|
||||
int t2 = *s; // expected-error {{expression has unknown bounds}}
|
||||
int t3 = s[4]; // expected-error {{expression has unknown bounds}}
|
||||
|
@ -61,8 +61,8 @@ checked int f3(int *s : itype(array_ptr<int>), int len) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
checked int f4(int *s : itype(int checked[4])) {
|
||||
array_ptr<int> t1 = s + 4;
|
||||
checked int f4(int *s _Itype(int checked[4])){
|
||||
int *_Array t1 = s + 4;
|
||||
int t2 = *s;
|
||||
int t3 = s[3];
|
||||
*(s + 3) = 0;
|
||||
|
@ -83,8 +83,8 @@ checked int f5(int *s : itype(int checked[])) {
|
|||
|
||||
// Test cases where a bounds-safe interface type is implied by a bounds
|
||||
// expression on an unchecked type
|
||||
checked int f6(int *s : count(4)) {
|
||||
array_ptr<int> t1 = s + 3;
|
||||
checked int f6(int *s _Count(4)) {
|
||||
int *_Array t1 = s + 3;
|
||||
int t2 = *s;
|
||||
int t3 = s[3];
|
||||
*(s + 3) = 0;
|
||||
|
@ -103,8 +103,8 @@ checked int f7(int *s : bounds(s, s + 4)) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
checked int f8(int *s : byte_count(4 * sizeof(int))) {
|
||||
array_ptr<int> t1 = s + 3;
|
||||
checked int f8(int *s _Byte_count(4 * sizeof(int))) {
|
||||
int *_Array t1 = s + 3;
|
||||
int t2 = *s;
|
||||
int t3 = s[3];
|
||||
*(s + 3) = 0;
|
||||
|
@ -113,11 +113,11 @@ checked int f8(int *s : byte_count(4 * sizeof(int))) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
checked int* func10(ptr<int> p, int *q : itype(ptr<int>)) : itype(ptr<int>) {
|
||||
checked int* func10(int *_Single p, int *q _Itype(int *_Single)) _Itype(int *_Single) {
|
||||
int a = 5;
|
||||
ptr<int> pa = &a;
|
||||
ptr<int> pb = p;
|
||||
ptr<int> pc = q;
|
||||
int *_Single pa = &a;
|
||||
int *_Single pb = p;
|
||||
int *_Single pc = q;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -137,43 +137,43 @@ int *gptr : bounds(garr, garr + 5);
|
|||
int gval : bounds(garr, garr + 10);
|
||||
|
||||
checked void test_globals(void) {
|
||||
// ptr<int>
|
||||
// int *_Single
|
||||
int t1 = *g1; // Allowed in checked scope.
|
||||
int t2 = *(g1 + 4); // expected-error {{arithmetic on _Ptr type}}
|
||||
int t3 = g1[4]; // expected-error {{subscript of '_Ptr<int>'}}
|
||||
*(g1 + 4) = 0; // expected-error {{arithmetic on _Ptr type}}
|
||||
g1[4] = 0; // expected-error {{subscript of '_Ptr<int>'}}
|
||||
|
||||
array_ptr<int> t4 : count(1) = g1;
|
||||
int *_Array t4 _Count(1) = g1;
|
||||
g1 = t4;
|
||||
|
||||
array_ptr<float> t5 : count(1) = g1; // expected-error {{incompatible type}}
|
||||
array_ptr<float> t6 = 0;
|
||||
float* _Array t5 _Count(1) = g1; // expected-error {{incompatible type}}
|
||||
float* _Array t6 = 0;
|
||||
g1 = t6; // expected-error {{incompatible type}}
|
||||
|
||||
// array_ptr<int> with bounds.
|
||||
// int *_Array with bounds.
|
||||
int t11 = *g2;
|
||||
int t12 = *(g2 + 4);
|
||||
int t12 = *(g2 + 4);
|
||||
int t13 = g2[4];
|
||||
*(g2 + 4) = 0;
|
||||
g2[4] = 0;
|
||||
|
||||
// array_ptr<int> without bounds
|
||||
array_ptr<int> t21 = g3 + 4; // allowed
|
||||
// int *_Array without bounds
|
||||
int *_Array t21 = g3 + 4; // allowed
|
||||
int t22 = *g3; // expected-error {{expression has unknown bounds}}
|
||||
int t23 = g3[4]; // expected-error {{expression has unknown bounds}}
|
||||
*(g3 + 4) = 0; // expected-error {{expression has unknown bounds}}
|
||||
g3[4] = 0; // expected-error {{expression has unknown bounds}}
|
||||
|
||||
// int checked[5]
|
||||
array_ptr<int> t31 = g4 + 4;
|
||||
int *_Array t31 = g4 + 4;
|
||||
int t32 = *g4;
|
||||
int t33 = g4[4];
|
||||
*(g4 + 4) = 0;
|
||||
g4[4] = 0;
|
||||
|
||||
// int checked[]
|
||||
array_ptr<int> t41 = g5+ 4;
|
||||
int *_Array t41 = g5+ 4;
|
||||
int t42 = *g5; // expected-error {{expression has unknown bounds}}
|
||||
int t43 = g5[4]; // expected-error {{expression has unknown bounds}}
|
||||
*(g5 + 4) = 0; // expected-error {{expression has unknown bounds}}
|
||||
|
@ -187,9 +187,8 @@ void f10(int *p : itype(ptr<int>));
|
|||
void f11(int *p : count(4));
|
||||
void f12(int *p : itype(array_ptr<int>));
|
||||
void f13(int *p : itype(int checked[]));
|
||||
void f14(int *p : itype(int checked[4]));
|
||||
void f15(ptr<int> p, int *q : itype(ptr<int>));
|
||||
|
||||
void f14(int *p _Itype(int checked[4]));
|
||||
void f15(int *_Single p, int *q _Itype(int *_Single));
|
||||
|
||||
extern int empty_global_arr[] : itype(int checked[]);
|
||||
|
||||
|
@ -197,7 +196,7 @@ extern int empty_global_arr[] : itype(int checked[]);
|
|||
checked int test_call_parameters(void) {
|
||||
ptr<int> param1 = 0;
|
||||
array_ptr<int> param2 : count(4) = 0;
|
||||
array_ptr<int> param3;
|
||||
int *_Array param3;
|
||||
int arr1 checked[4];
|
||||
f10(param1);
|
||||
f10(param2);
|
||||
|
@ -243,8 +242,8 @@ checked void f11d(int *lower : itype(array_ptr<int>),
|
|||
checked void f11e(char *buf : bounds(buf, end),
|
||||
char *end : itype(_Array_ptr<char>));
|
||||
checked void f12a(int *p : itype(array_ptr<int>));
|
||||
checked void f13a(int *p : itype(int checked[]));
|
||||
checked void f14a(int *p : itype(int checked[4]));
|
||||
checked void f13a(int *p _Itype(int checked[]));
|
||||
checked void f14a(int *p _Itype(int checked[4]));
|
||||
checked void f15a(ptr<int> p, int *q : itype(ptr<int>));
|
||||
|
||||
|
||||
|
@ -255,13 +254,14 @@ checked int* f20(int a checked[][5], int b checked[][5]) : itype(ptr<int>) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
checked int* f21(int *a : itype(ptr<int>), int *b : itype(array_ptr<int>)) : itype(array_ptr<int>) checked {
|
||||
checked int* f21(int *a _Itype(int *_Single), int *b _Itype(int *_Array))
|
||||
_Itype(int *_Array) checked {
|
||||
int e checked[5][5];
|
||||
_Unchecked {
|
||||
int *upa = f20(e, e);
|
||||
}
|
||||
int *upa = f20(e, e); // expected-error {{local variable in a checked scope must have a checked type}}
|
||||
ptr<int> pb = f20(e, e);
|
||||
int *_Single pb = f20(e, e);
|
||||
return pb;
|
||||
}
|
||||
|
||||
|
@ -273,7 +273,7 @@ checked int *f21b(int *b : count(4)) : byte_count(4 * sizeof(int)) {
|
|||
return b;
|
||||
}
|
||||
|
||||
checked int *f21c(int *b : count(4)) : bounds(return_value, return_value + 4) {
|
||||
checked int *f21c(int *b : count(4)) _Bounds(return_value, return_value + 4) {
|
||||
return b;
|
||||
}
|
||||
|
||||
|
@ -287,7 +287,7 @@ checked int *f21d(int *b : count(4)) :
|
|||
// Test checked return types implied by a bounds-safe interface
|
||||
checked void test_checked_returns(void) {
|
||||
int arr1 checked[5][5];
|
||||
ptr<int> t1 = f20(arr1, arr1);
|
||||
int *_Single t1 = f20(arr1, arr1);
|
||||
|
||||
int arr2 checked[4];
|
||||
array_ptr<int> t2 = f21(0, arr2);
|
||||
|
@ -308,7 +308,7 @@ checked int* f22() : itype(array_ptr<int>); // expected-error {{function withou
|
|||
// Illegal interface types for parameters in a checked scope.
|
||||
//
|
||||
|
||||
checked int* f23(int a[] : itype(int *), char b[] : itype(char *)) : itype(int *) checked {// expected-error 3 {{type must be a checked type}}
|
||||
checked int* f23(int a[] _Itype(int *), char b[] _Itype(char *)) _Itype(int *) checked {// expected-error 3 {{type must be a checked type}}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
@ -318,7 +318,7 @@ checked int* f23(int a[] : itype(int *), char b[] : itype(char *)) : itype(int *
|
|||
|
||||
// Return a ptr from a checked scope for a function with a
|
||||
// a bounds-safe interface return type of ptr.
|
||||
int *f30(void) : itype(ptr<int>) {
|
||||
int *f30(void) _Itype(int *_Single) {
|
||||
checked{
|
||||
ptr<int> p = 0;
|
||||
return p;
|
||||
|
@ -339,7 +339,7 @@ int *f31(int len) : count(len) {
|
|||
// Return an ptr from a checked scope for a function with a
|
||||
// a bounds-safe interface return type of ptr, where the
|
||||
// returned value has a bounds-safe interface type.
|
||||
int *f32(int * p : itype(ptr<int>)) : itype(ptr<int >) {
|
||||
int *f32(int * p _Itype(int *_Single)) _Itype(ptr<int >) {
|
||||
checked{
|
||||
return p;
|
||||
}
|
||||
|
@ -385,7 +385,7 @@ int *f36(void) : itype(ptr<int>) {
|
|||
|
||||
int ga = 5;
|
||||
|
||||
checked int * func37(void) : itype(array_ptr<int>) _Unchecked {
|
||||
checked int * func37(void) _Itype(int *_Array) _Unchecked {
|
||||
int *upa = &ga;
|
||||
return upa;
|
||||
}
|
||||
|
@ -402,8 +402,8 @@ checked int * func38(void) : itype(ptr<int>) _Unchecked {
|
|||
#pragma CHECKED_SCOPE ON
|
||||
struct S1 {
|
||||
int *f1 : itype(ptr<int>);
|
||||
int *f2 : count(5);
|
||||
int *f3 : count(len);
|
||||
int *f2 _Count(5);
|
||||
int *f3 _Count(len);
|
||||
int *f4 : bounds(f5, f5 + 5); // use of f5 here is intentional.
|
||||
int *f5 : bounds(f5, f5 + len);
|
||||
int len;
|
||||
|
@ -523,15 +523,15 @@ struct S2 {
|
|||
int *f4 : itype(array_ptr<int>);
|
||||
int arr[5] : itype(int checked[5]);
|
||||
// pointer to function that returns a ptr<ptr<int>>
|
||||
int **((*fp1)(int *param : itype(ptr<int>))) :
|
||||
itype(ptr<ptr<ptr<int>> (int *param : itype(ptr<int>))>);
|
||||
int **((*fp1)(int *param _Itype(int *_Single))) :
|
||||
itype(int *_Single *_Single (*_Single)(int *param _Itype(int *_Single)));
|
||||
|
||||
// pointer to function that returns an array_ptr<ptr<int>>
|
||||
int **((*fp2)(int *param : itype(ptr<int>),int len)) :
|
||||
itype(ptr<array_ptr<ptr<int>>(int *param : itype(ptr<int>), int len) : count(len)>);
|
||||
};
|
||||
|
||||
checked int test_struct3(struct S2 *p : itype(ptr<struct S2>)) {
|
||||
checked int test_struct3(struct S2 *p _Itype(ptr<struct S2>)) {
|
||||
(*(p->fp1))(p->f1) + 5; // expected-error {{arithmetic on _Ptr type}}
|
||||
*((*(p->fp1))(p->f1)) + 5; // expected-error {{arithmetic on _Ptr type}}
|
||||
(*(p->fp2))(p->f1, 5) + 4;
|
||||
|
@ -545,7 +545,7 @@ checked int test_struct3(struct S2 *p : itype(ptr<struct S2>)) {
|
|||
}
|
||||
|
||||
// Unchecked version - there should be no error messages.
|
||||
unchecked int test_struct4(struct S2 *p : itype(ptr<struct S2>)) {
|
||||
unchecked int test_struct4(struct S2 *p _Itype(ptr<struct S2>)) {
|
||||
(*(p->fp1))(p->f1) + 5;
|
||||
*((*(p->fp1))(p->f1)) + 5;
|
||||
(*(p->fp2))(p->f1, 5) + 4;
|
||||
|
@ -576,7 +576,7 @@ base_with_interfaces table2[10] : itype(fnptr_interface checked[10]);
|
|||
// In a checked scope, table1 and table2 are retyped as having checked types
|
||||
// based on their bounds-safe interfaces. That means that the result of an
|
||||
// indirect function call through table1 or table2 has typr Ptr.
|
||||
checked void test1_array_of_function_pointers(ptr<int> arg1, ptr<ptr<int>> arg2, int num) {
|
||||
checked void test1_array_of_function_pointers(int *_Single arg1, ptr<int *_Single> arg2, int num) {
|
||||
ptr<int> result1 = (*(table1[num]))(arg1, arg2);
|
||||
(*(table1[num]))(arg1, arg2) + 5; // expected-error {{arithmetic on _Ptr type}}
|
||||
(*(table2[num]))(arg1, arg2);
|
||||
|
@ -626,25 +626,25 @@ int mblen(const char *s : count(n), size_t n);
|
|||
|
||||
void (*signal(int sig,
|
||||
void ((*func)(int)) :
|
||||
itype(_Ptr<void (int)>) // bound-safe interface for func
|
||||
) : itype(_Ptr<void (int)>) // bounds-safe interface for signal return
|
||||
)(int);
|
||||
itype(_Ptr<void (int)>) // bound-safe interface for func
|
||||
) _Itype(_Ptr<void (int)>) // bounds-safe interface for signal return
|
||||
)(int);
|
||||
|
||||
void handler(int); // for testing signal.
|
||||
|
||||
void test_bounds_safe_interface(void) {
|
||||
array_ptr<int> arr0 : count(4) = checked_calloc(4, sizeof(size_t));
|
||||
int *_Array arr0 _Count(4) = checked_calloc(4, sizeof(size_t));
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
_Unchecked{
|
||||
checked_malloc(arr0[i]);
|
||||
}
|
||||
ptr<int> arr1 = checked_malloc(10);
|
||||
checked_malloc(arr0[i]);
|
||||
}
|
||||
int *_Single arr1 = checked_malloc(10);
|
||||
#pragma CHECKED_SCOPE OFF
|
||||
void *unchecked_ptr;
|
||||
#pragma CHECKED_SCOPE ON
|
||||
array_ptr<int> arr2 = checked_realloc(arr1, 20);
|
||||
array_ptr<int> arr3 = checked_realloc(unchecked_ptr, 20); // expected-error {{local variable used in a checked scope must have a checked type}}
|
||||
int *_Array arr2 = checked_realloc(arr1, 20);
|
||||
int *_Array arr3 = checked_realloc(unchecked_ptr, 20); // expected-error {{local variable used in a checked scope must have a checked type}}
|
||||
|
||||
_Unchecked {
|
||||
typedef void (*return_fn)(int);
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
#include <stdchecked.h>
|
||||
|
||||
int printf(const char * restrict format : itype(restrict _Nt_array_ptr<const char>), ...);
|
||||
int printf(const char * restrict format _Itype( const char* _Nt_array restrict ), ...);
|
||||
|
||||
// Test for pragma set/clear/set.
|
||||
#if BOUNDS_ONLY
|
||||
|
@ -40,18 +40,18 @@ int printf(const char * restrict format : itype(restrict _Nt_array_ptr<const cha
|
|||
|
||||
// Test for checked function in top-level checked scope.
|
||||
// Check if paremeter, return, local variable is checked type
|
||||
int* checked_func0(ptr<int> p, int *q : itype(ptr<int>), int r[], array_ptr<int> s : count(len), int len) { // expected-error {{return in a checked scope must have a checked type or a bounds-safe interface}} \
|
||||
int* checked_func0(int* _Single p, int *q _Itype(int* _Single), int r[], int* _Array s _Count(len), int len) { // expected-error {{return in a checked scope must have a checked type or a bounds-safe interface}} \
|
||||
// expected-error {{parameter in a checked scope must have a checked type or a bounds-safe interface}}
|
||||
int a = 5;
|
||||
int *upa = &a; // expected-error {{local variable in a checked scope must have a checked type}}
|
||||
int *upb = q; // expected-error {{local variable in a checked scope must have a checked type}}
|
||||
ptr<int> pc = p;
|
||||
array_ptr<int> pd = q;
|
||||
int* _Single pc = p;
|
||||
int* _Array pd = q;
|
||||
int e[5][5]; // expected-error {{local variable in a checked scope must have a checked type}}
|
||||
return upa;
|
||||
}
|
||||
|
||||
unchecked int* unchecked_func0(ptr<int> p, int *q : itype(ptr<int>), int r[], array_ptr<int> s : count(len), int len) {
|
||||
unchecked int* unchecked_func0(int* _Single p, int *q _Itype(int* _Single), int r[], int* _Array s _Count(len), int len) {
|
||||
int a = 5;
|
||||
int *upa = &a;
|
||||
int *upb = q;
|
||||
|
@ -62,13 +62,13 @@ unchecked int* unchecked_func0(ptr<int> p, int *q : itype(ptr<int>), int r[], ar
|
|||
}
|
||||
|
||||
|
||||
array_ptr<int> checked_func1_checked_body(int *x, int *y) { // expected-error 2 {{parameter in a checked scope must have a checked type or a bounds-safe interface}}
|
||||
int* _Array checked_func1_checked_body(int *x, int *y) { // expected-error 2 {{parameter in a checked scope must have a checked type or a bounds-safe interface}}
|
||||
int *upa = x; // expected-error {{local variable in a checked scope must have a checked type}}
|
||||
int *upb = y; // expected-error {{local variable in a checked scope must have a checked type}}
|
||||
return upb;
|
||||
}
|
||||
|
||||
unchecked array_ptr<int> unchecked_func1_checked_body(int *x, int *y) {
|
||||
unchecked int* _Array unchecked_func1_checked_body(int *x, int *y) {
|
||||
#if BOUNDS_ONLY
|
||||
#pragma CHECKED_SCOPE _Bounds_only
|
||||
#else
|
||||
|
@ -82,7 +82,7 @@ unchecked array_ptr<int> unchecked_func1_checked_body(int *x, int *y) {
|
|||
return upb;
|
||||
}
|
||||
|
||||
unchecked array_ptr<int> unchecked_func1_unchecked_body(int *x, int *y) {
|
||||
unchecked int* _Array unchecked_func1_unchecked_body(int *x, int *y) {
|
||||
int *upa = x;
|
||||
int *upb = y;
|
||||
return upb;
|
||||
|
@ -109,12 +109,12 @@ int* checked_func2_unchecked_parm_unchecked_ret(int a [][5], int b [][5]) { // e
|
|||
// expected-error {{return in a checked scope must have a checked type or a bounds-safe interface}}
|
||||
}
|
||||
|
||||
int* checked_func_check_call(int *a : itype(ptr<int>), int *b : itype(array_ptr<int>)) : itype(array_ptr<int>) {
|
||||
int* checked_func_check_call(int *a _Itype(int* _Single), int *b _Itype(int* _Array)) _Itype(int* _Array) {
|
||||
int e checked[5][5];
|
||||
int f[5][5]; // expected-error {{local variable in a checked scope must have a checked type}}
|
||||
int *upa = checked_func2_checked_parm_checked_ret(e, e); // expected-error {{local variable in a checked scope must have a checked type}}
|
||||
ptr<int> pb = checked_func2_checked_parm_checked_ret(e, e);
|
||||
ptr<int> pc = 0;
|
||||
int* _Single pb = checked_func2_checked_parm_checked_ret(e, e);
|
||||
int* _Single pc = 0;
|
||||
pc = checked_func2_unchecked_parm_checked_ret(f, f);
|
||||
return upa;
|
||||
}
|
||||
|
@ -235,7 +235,7 @@ int * checked_func_uc1_pragma(int *p, int *q) { // expected-error {{return in a
|
|||
return upa; // expected-error {{local variable used in a checked scope must have a checked type}}
|
||||
}
|
||||
|
||||
ptr<int> checked_func_u1(int *p, ptr<int> q, array_ptr<int> r, array_ptr<int> s : count(2)) { // expected-error {{parameter in a checked scope must have a checked type or a bounds-safe interface}}
|
||||
int* _Single checked_func_u1(int *p, int* _Single q, int* _Array r, int* _Array s _Count(2)) { // expected-error {{parameter in a checked scope must have a checked type or a bounds-safe interface}}
|
||||
int a = 5;
|
||||
*p = 1;
|
||||
*q = 2;
|
||||
|
@ -254,7 +254,7 @@ ptr<int> checked_func_u1(int *p, ptr<int> q, array_ptr<int> r, array_ptr<int> s
|
|||
return q;
|
||||
}
|
||||
|
||||
ptr<int> checked_func_u1_pragma(int *p, ptr<int> q, array_ptr<int> r, array_ptr<int> s : count(2)) {// expected-error {{parameter in a checked scope must have a checked type or a bounds-safe interface}}
|
||||
int* _Single checked_func_u1_pragma(int *p, int* _Single q, int* _Array r, int* _Array s _Count(2)) {// expected-error {{parameter in a checked scope must have a checked type or a bounds-safe interface}}
|
||||
int a = 5;
|
||||
*p = 1;
|
||||
*q = 2;
|
||||
|
@ -283,7 +283,7 @@ ptr<int> checked_func_u1_pragma(int *p, ptr<int> q, array_ptr<int> r, array_ptr<
|
|||
return q;
|
||||
}
|
||||
|
||||
int * checked_func_uc(void) : itype(array_ptr<int>) unchecked {
|
||||
int * checked_func_uc(void) _Itype(int* _Array) unchecked {
|
||||
int a = 5;
|
||||
int *upa = &a;
|
||||
int b[5][5];
|
||||
|
@ -303,7 +303,7 @@ int * checked_func_uc(void) : itype(array_ptr<int>) unchecked {
|
|||
return upa;
|
||||
}
|
||||
|
||||
int * checked_func_uc_pragma(void) : itype(array_ptr<int>) {
|
||||
int * checked_func_uc_pragma(void) _Itype(int* _Array) {
|
||||
#pragma CHECKED_SCOPE OFF
|
||||
int a = 5;
|
||||
int *upa = &a;
|
||||
|
@ -329,7 +329,7 @@ int * checked_func_uc_pragma(void) : itype(array_ptr<int>) {
|
|||
return upa;
|
||||
}
|
||||
|
||||
int checked_func_ucu1(int *p, int *q, int *r : itype(ptr<int>), int *s : itype(array_ptr<int>)) unchecked { // expected-error 2 {{parameter in a checked scope must have a checked type or a bounds-safe interface}}
|
||||
int checked_func_ucu1(int *p, int *q, int *r _Itype(int* _Single), int *s _Itype(int* _Array)) unchecked { // expected-error 2 {{parameter in a checked scope must have a checked type or a bounds-safe interface}}
|
||||
int sum = 0;
|
||||
int a = 5;
|
||||
int *upa = &a;
|
||||
|
@ -343,7 +343,7 @@ int checked_func_ucu1(int *p, int *q, int *r : itype(ptr<int>), int *s : itype(a
|
|||
return sum;
|
||||
}
|
||||
|
||||
int checked_func_ucu1_pragma(int *p, int *q, int *r : itype(ptr<int>), int *s : itype(array_ptr<int>)) { // expected-error 2 {{parameter in a checked scope must have a checked type or a bounds-safe interface}}
|
||||
int checked_func_ucu1_pragma(int *p, int *q, int *r _Itype(int* _Single), int *s _Itype(int* _Array)) { // expected-error 2 {{parameter in a checked scope must have a checked type or a bounds-safe interface}}
|
||||
#pragma CHECKED_SCOPE OFF
|
||||
int sum = 0;
|
||||
int a = 5;
|
||||
|
@ -364,7 +364,7 @@ int checked_func_ucu1_pragma(int *p, int *q, int *r : itype(ptr<int>), int *s :
|
|||
return sum;
|
||||
}
|
||||
|
||||
int checked_func_ucu2(ptr<int> p, int *q) unchecked { // expected-error {{parameter in a checked scope must have a checked type or a bounds-safe interface}}
|
||||
int checked_func_ucu2(int* _Single p, int *q) unchecked { // expected-error {{parameter in a checked scope must have a checked type or a bounds-safe interface}}
|
||||
int a = 5;
|
||||
int *upa;
|
||||
array_ptr<int> pc;
|
||||
|
@ -450,8 +450,8 @@ unchecked int * unchecked_func3_checked_body(int *p, int q[]) {
|
|||
unchecked array_ptr<int> unchecked_func4_unchecked_body(int p[], int q[10], int r[][10]) {
|
||||
int *upa;
|
||||
int *upb;
|
||||
array_ptr<int> pb;
|
||||
ptr<int> pc = 0;
|
||||
int* _Array pb;
|
||||
int* _Single pc = 0;
|
||||
upa = pb; // expected-error {{assigning to 'int *' from incompatible type '_Array_ptr<int>'}}
|
||||
upa = pc; // expected-error {{assigning to 'int *' from incompatible type '_Ptr<int>'}}
|
||||
upb = pb; // expected-error {{assigning to 'int *' from incompatible type '_Array_ptr<int>'}}
|
||||
|
@ -468,7 +468,7 @@ unchecked array_ptr<int> unchecked_func4_checked_body(int p[], int q[10], int r[
|
|||
int *upa; // expected-error {{local variable in a checked scope must have a checked type}}
|
||||
int *upb; // expected-error {{local variable in a checked scope must have a checked type}}
|
||||
array_ptr<int> pb;
|
||||
ptr<int> pc = 0;
|
||||
int* _Single pc = 0;
|
||||
upa = pb;
|
||||
upa = pc;
|
||||
upb = pb;
|
||||
|
@ -530,8 +530,8 @@ int **a4 : itype(ptr<array_ptr<int>>) = 0;
|
|||
int **a5 : itype(array_ptr<ptr<int>>) = 0;
|
||||
int **a6 : itype(array_ptr<array_ptr<int>>) = 0;
|
||||
int ***a7 : itype(ptr<ptr<ptr<int>>>) = 0;
|
||||
int a8[10] : itype(int checked[10]);
|
||||
extern int a9[] : itype(int checked[]);
|
||||
int a8[10] _Itype(int checked[10]);
|
||||
extern int a9[] _Itype(int checked[]);
|
||||
#pragma CHECKED_SCOPE OFF
|
||||
int *a10;
|
||||
#if BOUNDS_ONLY
|
||||
|
@ -575,7 +575,7 @@ struct S0 {
|
|||
float *data11; // expected-error {{member in a checked scope must have a checked type or a bounds-safe interface}}
|
||||
float **data12; // expected-error {{member in a checked scope must have a checked type or a bounds-safe interface}}
|
||||
float ***data13;// expected-error {{member in a checked scope must have a checked type or a bounds-safe interface}}
|
||||
float *data14 : itype(float *); // expected-error {{type must be a checked type}}
|
||||
float *data14 _Itype(float *); // expected-error {{type must be a checked type}}
|
||||
};
|
||||
|
||||
typedef struct _S1 {
|
||||
|
@ -593,7 +593,7 @@ typedef struct _S1 {
|
|||
#endif
|
||||
char *b; // expected-error {{member in a checked scope must have a checked type or a bounds-safe interface}}
|
||||
ptr<int> pc;
|
||||
array_ptr<int> pd : count(len);
|
||||
int* _Array pd _Count(len);
|
||||
#pragma CHECKED_SCOPE OFF
|
||||
#if BOUNDS_ONLY
|
||||
#pragma CHECKED_SCOPE _Bounds_only
|
||||
|
@ -633,7 +633,7 @@ int checked_func_with_checked_struct(void) {
|
|||
int *a; // expected-error {{member in a checked scope must have a checked type or a bounds-safe interface}}
|
||||
char *b; // expected-error {{member in a checked scope must have a checked type or a bounds-safe interface}}
|
||||
ptr<int> pc;
|
||||
array_ptr<int> pd : count(len);
|
||||
int* _Array pd _Count(len);
|
||||
short e[10]; // expected-error {{member in a checked scope must have a checked type or a bounds-safe interface}}
|
||||
char f[10]; // expected-error {{member in a checked scope must have a checked type or a bounds-safe interface}}
|
||||
int len;
|
||||
|
@ -702,7 +702,7 @@ extern void variadic_func5(int cnt, ptr<int> p, ...) { // expected-error {{vari
|
|||
#endif
|
||||
void checked_func_call_variadic(void) {
|
||||
ptr<int> a = 0;
|
||||
array_ptr<int> b;
|
||||
int* _Array b;
|
||||
printf("check function call variadic %d\n", *a);
|
||||
#pragma CHECKED_SCOPE OFF
|
||||
printf("check function call variadic %d\n", *a);
|
||||
|
|
|
@ -1,204 +1,204 @@
|
|||
// Test type checking of generic structs.
|
||||
//
|
||||
// RUN: %clang_cc1 -verify -verify-ignore-unexpected=note %s
|
||||
|
||||
// A struct we can use with existential types.
|
||||
struct Foo _For_any(T) {
|
||||
T *elem;
|
||||
};
|
||||
|
||||
// Test that we can parse existential types both as function arguments
|
||||
// and in (uninitialized) expressions.
|
||||
void TestParseExistentialType(_Exists(T, struct Foo<T>) exist) {
|
||||
_Exists(U, struct Foo<U>) localVar;
|
||||
}
|
||||
|
||||
// Test that we can't directly access fields of an existential:
|
||||
// we need to unwrap the existential first.
|
||||
void TestCantAccessFieldsInExistential(_Exists(T, struct Foo<T>) exist) {
|
||||
exist.elem = 0; // expected-error {{member reference base type 'Exists(T, struct Foo<T>)' is not a structure or union}}
|
||||
}
|
||||
|
||||
// Test that pack returns an existential type.
|
||||
void TestPackReturnType() {
|
||||
struct Foo<int> fooInt;
|
||||
_Exists(T, struct Foo<T>) foo = _Pack(fooInt, _Exists(U, struct Foo<U>), int);
|
||||
}
|
||||
|
||||
// Test that the type of the witness in _Pack(witness-expr, exist-type, subst-type)
|
||||
// matches the given existential type.
|
||||
void TestWitnessMismatch() {
|
||||
struct Foo<int> fooInt;
|
||||
struct Foo<struct Foo<int> > fooNested;
|
||||
_Exists(T, struct Foo<T>) foo = _Pack(fooInt, _Exists(T, struct Foo<T>), int); // ok: witness and expected types match
|
||||
_Pack(fooInt, _Exists(T, struct Foo<T>), char); // expected-error {{witness type does not match existential type}}
|
||||
_Pack(fooNested, _Exists(T, struct Foo<T>), int); // expected-error {{witness type does not match existential type}}
|
||||
_Exists(T, struct Foo<struct Foo<T> >) e = _Pack(fooNested, _Exists(T, struct Foo<struct Foo<T> >), int); // ok
|
||||
_Exists(T, struct Foo<T>) e2 = _Pack(fooNested, _Exists(T, struct Foo<T>), struct Foo<int>); // ok
|
||||
}
|
||||
|
||||
// Test that the same expression can be packed in different ways,
|
||||
// if we change the substitution and return types.
|
||||
void TestMultiplePacks() {
|
||||
struct Foo<struct Foo<struct Foo<int> > > fooInt3;
|
||||
_Pack(fooInt3, _Exists(T, struct Foo<T>), struct Foo<struct Foo<int> >); // expected-warning {{expression result unused}}
|
||||
_Pack(fooInt3, _Exists(T, struct Foo<struct Foo<T> >), struct Foo<int>); // expected-warning {{expression result unused}}
|
||||
_Pack(fooInt3, _Exists(T, struct Foo<T>), struct Foo<struct Foo<int> >); // expected-warning {{expression result unused}}
|
||||
}
|
||||
|
||||
// Test different packings of a struct that contains multiple type parameters.
|
||||
void TestMultipleTypeParams() {
|
||||
struct Bar _For_any(A, B, C) {
|
||||
};
|
||||
struct Cat;
|
||||
struct Dog;
|
||||
struct Sheep;
|
||||
struct Bar<struct Cat, struct Dog, struct Sheep> bar;
|
||||
_Pack(bar, _Exists(T, struct Bar<T, struct Dog, struct Sheep>), struct Cat); // expected-warning {{expression result unused}}
|
||||
_Pack(bar, _Exists(T, struct Bar<struct Cat, T, struct Sheep>), struct Dog); // expected-warning {{expression result unused}}
|
||||
_Pack(bar, _Exists(T, struct Bar<struct Cat, struct Dog, T>), struct Sheep); // expected-warning {{expression result unused}}
|
||||
|
||||
_Pack(bar, _Exists(T, struct Bar<T, T, T>), struct Cat); // expected-error {{witness type does not match existential type}}
|
||||
}
|
||||
|
||||
// Test that we can pack and unpack a simple generic.
|
||||
void TestSimpleUnpack() {
|
||||
struct Foo _For_any(A) {
|
||||
A *a;
|
||||
void (*op)(A*);
|
||||
};
|
||||
struct Foo<int> fooInt;
|
||||
_Exists(T2, struct Foo<T2>) packedFoo = _Pack(fooInt, _Exists(T2, struct Foo<T2>), int);
|
||||
|
||||
// TODO: the error message should reference 'struct Foo<F>' and not 'struct Foo<T2>'.
|
||||
// This is happening because incorrect canonicalization of existential types (and of type applications).
|
||||
// Fix once that problem is fixed.
|
||||
// Let's do an incorrect unpack.
|
||||
// This is incorrect because _Unpack leaves 'U' abstract, so we can't recover the original
|
||||
// 'int' type argument.
|
||||
_Unpack (F) struct Foo<int> incorrect = packedFoo; // expected-error {{initializing 'struct Foo<int>' with an expression of incompatible type 'struct Foo<T2>'}}
|
||||
|
||||
// Now let's try a correct unpack.
|
||||
_Unpack (U) struct Foo<U> unpackedFoo = packedFoo;
|
||||
U *a2 = unpackedFoo.a;
|
||||
unpackedFoo.op(a2);
|
||||
}
|
||||
|
||||
_Exists(A, struct Foo<A>) foo1;
|
||||
_Exists(A, _Exists(B, struct Foo<A>)) foo2;
|
||||
_Exists(A, _Exists(B, struct Foo<B>)) foo3;
|
||||
_Exists(A, _Exists(B, _Exists(C, struct Foo<int>))) foo4;
|
||||
|
||||
// Test that existential types can handle different levels of
|
||||
// depth while still being detected as compatible.
|
||||
_For_any(T) void TestCanonicalization(T *x) {
|
||||
_Exists(A, struct Foo<A>) bar1;
|
||||
_Exists(A, _Exists(B, struct Foo<A>)) bar2;
|
||||
_Exists(A, _Exists(B, struct Foo<B>)) bar3;
|
||||
_Exists(A, _Exists(B, _Exists(C, struct Foo<int>))) bar4;
|
||||
|
||||
bar1 = foo1;
|
||||
bar2 = foo2;
|
||||
bar3 = foo3;
|
||||
bar4 = foo4;
|
||||
|
||||
foo1 = bar1;
|
||||
foo2 = bar2;
|
||||
foo3 = bar3;
|
||||
foo4 = bar4;
|
||||
|
||||
foo1 = foo1;
|
||||
foo2 = foo2;
|
||||
foo3 = foo3;
|
||||
foo4 = foo4;
|
||||
|
||||
bar1 = bar1;
|
||||
bar2 = bar2;
|
||||
bar3 = bar3;
|
||||
bar4 = bar4;
|
||||
|
||||
// TODO: fix 'struct Foo<T>' in canonical types below after we've fixed canonicalization of type applications
|
||||
bar1 = foo2; // expected-error {{assigning to 'Exists(A, struct Foo<B>)' from incompatible type 'Exists(A, Exists(B, struct Foo<T>))'}}
|
||||
bar2 = foo3; // expected-error {{assigning to 'Exists(A, Exists(B, struct Foo<B>))' (aka 'Exists((0, 0), Exists((1, 0), struct Foo<T>))') from incompatible type 'Exists(A, Exists(B, struct Foo<B>))' (aka 'Exists((0, 0), Exists((1, 0), struct Foo<B>))')}}
|
||||
bar3 = foo4; // expected-error {{assigning to 'Exists(A, Exists(B, struct Foo<B>))' from incompatible type 'Exists(A, Exists(B, Exists(C, struct Foo<int>)))'}}
|
||||
bar4 = foo1; // expected-error {{assigning to 'Exists(A, Exists(B, Exists(C, struct Foo<int>)))' from incompatible type 'Exists(A, struct Foo<T>)'}}
|
||||
|
||||
_Exists(A, _Exists(B, struct Foo<T>)) zoom1;
|
||||
zoom1 = foo2; // expected-error {{assigning to 'Exists(A, Exists(B, struct Foo<T>))' (aka 'Exists((1, 0), Exists((2, 0), struct Foo<T>))') from incompatible type 'Exists(A, Exists(B, struct Foo<T>))' (aka 'Exists((0, 0), Exists((1, 0), struct Foo<T>))')}}
|
||||
zoom1 = foo3; // expected-error {{assigning to 'Exists(A, Exists(B, struct Foo<T>))' from incompatible type 'Exists(A, Exists(B, struct Foo<B>))'}}
|
||||
}
|
||||
|
||||
// Test that the names of bound variables inside existential types don't matter
|
||||
// for compatibility purposes.
|
||||
void TestAlphaEquivalence() {
|
||||
struct Pair _For_any(T1, T2) {
|
||||
};
|
||||
|
||||
_Exists(A, struct Foo<A>) a1;
|
||||
_Exists(B, struct Foo<B>) a2;
|
||||
a1 = a2;
|
||||
a2 = a1;
|
||||
|
||||
_Exists(A, _Exists(B, struct Pair<int, char>)) b1;
|
||||
_Exists(T1, _Exists(T2, struct Pair<int, char>)) b2;
|
||||
b1 = b2;
|
||||
b2 = b1;
|
||||
|
||||
_Exists(A, A*****) c1;
|
||||
_Exists(B, B*****) c2;
|
||||
c1 = c2;
|
||||
c2 = c1;
|
||||
|
||||
struct Foo<_Exists(A, A *)> foo1;
|
||||
struct Foo<_Exists(B, B *)> foo2;
|
||||
foo1 = foo2;
|
||||
foo2 = foo1;
|
||||
|
||||
_Exists(A, _Exists(B, struct Foo<_Exists(C, struct Foo<B>)>)) d1;
|
||||
_Exists(T1, _Exists(T2, struct Foo<_Exists(T3, struct Foo<T2>)>)) d2;
|
||||
d1 = d2;
|
||||
d2 = d1;
|
||||
}
|
||||
|
||||
// Test that parsing malformed existential types fails without
|
||||
// a compiler crash.
|
||||
void TestParseMalformedExistential() {
|
||||
_Exists(int, T) e1; // expected-error {{expected type variable identifier}} expected-warning {{type specifier missing, defaults to 'int'}}
|
||||
_Exists(int T) e2; // expected-error {{expected type variable identifier}} expected-warning {{type specifier missing, defaults to 'int'}}
|
||||
_Exists(T int) e3; // expected-error {{expected ','}} expected-warning {{type specifier missing, defaults to 'int'}}
|
||||
_Exists(T, int e4; // expected-error {{expected ')'}} expected-warning {{type specifier missing, defaults to 'int'}}
|
||||
_Exists(T, T*)) e5; // expected-error {{expected identifier or '('}}
|
||||
}
|
||||
|
||||
// Test that while typechecking _Pack expressions we check that the return type
|
||||
// (which is the second argument to the pack) is an existential type.
|
||||
// If not, we should display an error.
|
||||
void TestPackReturnExpectsExistential() {
|
||||
struct Foo _For_any(T) {};
|
||||
struct Foo<int> fooInt;
|
||||
_Exists(T, struct Foo<T>) fooExists = _Pack(fooInt, struct Foo<int>, int); // expected-error {{return type of a pack expression must be an existential type, but got 'struct Foo<int>' instead}}
|
||||
}
|
||||
|
||||
// Test that we display an error message if the user tries
|
||||
// to unpack multiple type variables (this will be supported in the future).
|
||||
void TestUnpackWithMultipleTypeVars() {
|
||||
struct Foo _For_any(T) {};
|
||||
_Exists(T, struct Foo<T>) fooExist;
|
||||
_Unpack (A, B, C) struct Foo<A> fooAbs = fooExist; // expected-error {{expected ')'}} expected-error {{expected identifier or '('}}
|
||||
}
|
||||
|
||||
// Test that we check that the initializer to an unpack declaration
|
||||
// has an existential type.
|
||||
void TestUnpackRequiresExistentialInit() {
|
||||
struct Foo _For_any(T) {};
|
||||
struct Foo<int> fooInt;
|
||||
_Exists(B, struct Foo<B>) fooExist = _Pack(fooInt, _Exists(C, struct Foo<C>), int);
|
||||
_Unpack (A) struct Foo<A> fooA = fooInt; // expected-error {{unpack specifer expects an initializer that has an existential type}}
|
||||
_Unpack (B) struct Foo<B> fooB = fooExist;
|
||||
}
|
||||
|
||||
// Test that we can handle a malformed unpack specifier that's missing the type variable.
|
||||
void TestUnpackMissingTypeVariable() {
|
||||
struct Foo _For_any(T) {};
|
||||
_Unpack (int) struct Foo<A> fooA; // expected-error {{expected type variable identifier}} expected-error {{unknown type name 'A'}}
|
||||
// Test type checking of generic structs.
|
||||
//
|
||||
// RUN: %clang_cc1 -verify -verify-ignore-unexpected=note %s
|
||||
|
||||
// A struct we can use with existential types.
|
||||
struct Foo _For_any(T) {
|
||||
T *elem;
|
||||
};
|
||||
|
||||
// Test that we can parse existential types both as function arguments
|
||||
// and in (uninitialized) expressions.
|
||||
void TestParseExistentialType(_Exists(T, struct Foo<T>) exist) {
|
||||
_Exists(U, struct Foo<U>) localVar;
|
||||
}
|
||||
|
||||
// Test that we can't directly access fields of an existential:
|
||||
// we need to unwrap the existential first.
|
||||
void TestCantAccessFieldsInExistential(_Exists(T, struct Foo<T>) exist) {
|
||||
exist.elem = 0; // expected-error {{member reference base type 'Exists(T, struct Foo<T>)' is not a structure or union}}
|
||||
}
|
||||
|
||||
// Test that pack returns an existential type.
|
||||
void TestPackReturnType() {
|
||||
struct Foo<int> fooInt;
|
||||
_Exists(T, struct Foo<T>) foo = _Pack(fooInt, _Exists(U, struct Foo<U>), int);
|
||||
}
|
||||
|
||||
// Test that the type of the witness in _Pack(witness-expr, exist-type, subst-type)
|
||||
// matches the given existential type.
|
||||
void TestWitnessMismatch() {
|
||||
struct Foo<int> fooInt;
|
||||
struct Foo<struct Foo<int> > fooNested;
|
||||
_Exists(T, struct Foo<T>) foo = _Pack(fooInt, _Exists(T, struct Foo<T>), int); // ok: witness and expected types match
|
||||
_Pack(fooInt, _Exists(T, struct Foo<T>), char); // expected-error {{witness type does not match existential type}}
|
||||
_Pack(fooNested, _Exists(T, struct Foo<T>), int); // expected-error {{witness type does not match existential type}}
|
||||
_Exists(T, struct Foo<struct Foo<T> >) e = _Pack(fooNested, _Exists(T, struct Foo<struct Foo<T> >), int); // ok
|
||||
_Exists(T, struct Foo<T>) e2 = _Pack(fooNested, _Exists(T, struct Foo<T>), struct Foo<int>); // ok
|
||||
}
|
||||
|
||||
// Test that the same expression can be packed in different ways,
|
||||
// if we change the substitution and return types.
|
||||
void TestMultiplePacks() {
|
||||
struct Foo<struct Foo<struct Foo<int> > > fooInt3;
|
||||
_Pack(fooInt3, _Exists(T, struct Foo<T>), struct Foo<struct Foo<int> >); // expected-warning {{expression result unused}}
|
||||
_Pack(fooInt3, _Exists(T, struct Foo<struct Foo<T> >), struct Foo<int>); // expected-warning {{expression result unused}}
|
||||
_Pack(fooInt3, _Exists(T, struct Foo<T>), struct Foo<struct Foo<int> >); // expected-warning {{expression result unused}}
|
||||
}
|
||||
|
||||
// Test different packings of a struct that contains multiple type parameters.
|
||||
void TestMultipleTypeParams() {
|
||||
struct Bar _For_any(A, B, C) {
|
||||
};
|
||||
struct Cat;
|
||||
struct Dog;
|
||||
struct Sheep;
|
||||
struct Bar<struct Cat, struct Dog, struct Sheep> bar;
|
||||
_Pack(bar, _Exists(T, struct Bar<T, struct Dog, struct Sheep>), struct Cat); // expected-warning {{expression result unused}}
|
||||
_Pack(bar, _Exists(T, struct Bar<struct Cat, T, struct Sheep>), struct Dog); // expected-warning {{expression result unused}}
|
||||
_Pack(bar, _Exists(T, struct Bar<struct Cat, struct Dog, T>), struct Sheep); // expected-warning {{expression result unused}}
|
||||
|
||||
_Pack(bar, _Exists(T, struct Bar<T, T, T>), struct Cat); // expected-error {{witness type does not match existential type}}
|
||||
}
|
||||
|
||||
// Test that we can pack and unpack a simple generic.
|
||||
void TestSimpleUnpack() {
|
||||
struct Foo _For_any(A) {
|
||||
A *a;
|
||||
void (*op)(A*);
|
||||
};
|
||||
struct Foo<int> fooInt;
|
||||
_Exists(T2, struct Foo<T2>) packedFoo = _Pack(fooInt, _Exists(T2, struct Foo<T2>), int);
|
||||
|
||||
// TODO: the error message should reference 'struct Foo<F>' and not 'struct Foo<T2>'.
|
||||
// This is happening because incorrect canonicalization of existential types (and of type applications).
|
||||
// Fix once that problem is fixed.
|
||||
// Let's do an incorrect unpack.
|
||||
// This is incorrect because _Unpack leaves 'U' abstract, so we can't recover the original
|
||||
// 'int' type argument.
|
||||
_Unpack (F) struct Foo<int> incorrect = packedFoo; // expected-error {{initializing 'struct Foo<int>' with an expression of incompatible type 'struct Foo<T2>'}}
|
||||
|
||||
// Now let's try a correct unpack.
|
||||
_Unpack (U) struct Foo<U> unpackedFoo = packedFoo;
|
||||
U *a2 = unpackedFoo.a;
|
||||
unpackedFoo.op(a2);
|
||||
}
|
||||
|
||||
_Exists(A, struct Foo<A>) foo1;
|
||||
_Exists(A, _Exists(B, struct Foo<A>)) foo2;
|
||||
_Exists(A, _Exists(B, struct Foo<B>)) foo3;
|
||||
_Exists(A, _Exists(B, _Exists(C, struct Foo<int>))) foo4;
|
||||
|
||||
// Test that existential types can handle different levels of
|
||||
// depth while still being detected as compatible.
|
||||
_For_any(T) void TestCanonicalization(T *x) {
|
||||
_Exists(A, struct Foo<A>) bar1;
|
||||
_Exists(A, _Exists(B, struct Foo<A>)) bar2;
|
||||
_Exists(A, _Exists(B, struct Foo<B>)) bar3;
|
||||
_Exists(A, _Exists(B, _Exists(C, struct Foo<int>))) bar4;
|
||||
|
||||
bar1 = foo1;
|
||||
bar2 = foo2;
|
||||
bar3 = foo3;
|
||||
bar4 = foo4;
|
||||
|
||||
foo1 = bar1;
|
||||
foo2 = bar2;
|
||||
foo3 = bar3;
|
||||
foo4 = bar4;
|
||||
|
||||
foo1 = foo1;
|
||||
foo2 = foo2;
|
||||
foo3 = foo3;
|
||||
foo4 = foo4;
|
||||
|
||||
bar1 = bar1;
|
||||
bar2 = bar2;
|
||||
bar3 = bar3;
|
||||
bar4 = bar4;
|
||||
|
||||
// TODO: fix 'struct Foo<T>' in canonical types below after we've fixed canonicalization of type applications
|
||||
bar1 = foo2; // expected-error {{assigning to 'Exists(A, struct Foo<B>)' from incompatible type 'Exists(A, Exists(B, struct Foo<T>))'}}
|
||||
bar2 = foo3; // expected-error {{assigning to 'Exists(A, Exists(B, struct Foo<B>))' (aka 'Exists((0, 0), Exists((1, 0), struct Foo<T>))') from incompatible type 'Exists(A, Exists(B, struct Foo<B>))' (aka 'Exists((0, 0), Exists((1, 0), struct Foo<B>))')}}
|
||||
bar3 = foo4; // expected-error {{assigning to 'Exists(A, Exists(B, struct Foo<B>))' from incompatible type 'Exists(A, Exists(B, Exists(C, struct Foo<int>)))'}}
|
||||
bar4 = foo1; // expected-error {{assigning to 'Exists(A, Exists(B, Exists(C, struct Foo<int>)))' from incompatible type 'Exists(A, struct Foo<T>)'}}
|
||||
|
||||
_Exists(A, _Exists(B, struct Foo<T>)) zoom1;
|
||||
zoom1 = foo2; // expected-error {{assigning to 'Exists(A, Exists(B, struct Foo<T>))' (aka 'Exists((1, 0), Exists((2, 0), struct Foo<T>))') from incompatible type 'Exists(A, Exists(B, struct Foo<T>))' (aka 'Exists((0, 0), Exists((1, 0), struct Foo<T>))')}}
|
||||
zoom1 = foo3; // expected-error {{assigning to 'Exists(A, Exists(B, struct Foo<T>))' from incompatible type 'Exists(A, Exists(B, struct Foo<B>))'}}
|
||||
}
|
||||
|
||||
// Test that the names of bound variables inside existential types don't matter
|
||||
// for compatibility purposes.
|
||||
void TestAlphaEquivalence() {
|
||||
struct Pair _For_any(T1, T2) {
|
||||
};
|
||||
|
||||
_Exists(A, struct Foo<A>) a1;
|
||||
_Exists(B, struct Foo<B>) a2;
|
||||
a1 = a2;
|
||||
a2 = a1;
|
||||
|
||||
_Exists(A, _Exists(B, struct Pair<int, char>)) b1;
|
||||
_Exists(T1, _Exists(T2, struct Pair<int, char>)) b2;
|
||||
b1 = b2;
|
||||
b2 = b1;
|
||||
|
||||
_Exists(A, A*****) c1;
|
||||
_Exists(B, B*****) c2;
|
||||
c1 = c2;
|
||||
c2 = c1;
|
||||
|
||||
struct Foo<_Exists(A, A *)> foo1;
|
||||
struct Foo<_Exists(B, B *)> foo2;
|
||||
foo1 = foo2;
|
||||
foo2 = foo1;
|
||||
|
||||
_Exists(A, _Exists(B, struct Foo<_Exists(C, struct Foo<B>)>)) d1;
|
||||
_Exists(T1, _Exists(T2, struct Foo<_Exists(T3, struct Foo<T2>)>)) d2;
|
||||
d1 = d2;
|
||||
d2 = d1;
|
||||
}
|
||||
|
||||
// Test that parsing malformed existential types fails without
|
||||
// a compiler crash.
|
||||
void TestParseMalformedExistential() {
|
||||
_Exists(int, T) e1; // expected-error {{expected type variable identifier}} expected-warning {{type specifier missing, defaults to 'int'}}
|
||||
_Exists(int T) e2; // expected-error {{expected type variable identifier}} expected-warning {{type specifier missing, defaults to 'int'}}
|
||||
_Exists(T int) e3; // expected-error {{expected ','}} expected-warning {{type specifier missing, defaults to 'int'}}
|
||||
_Exists(T, int e4; // expected-error {{expected ')'}} expected-warning {{type specifier missing, defaults to 'int'}}
|
||||
_Exists(T, T*)) e5; // expected-error {{expected identifier or '('}}
|
||||
}
|
||||
|
||||
// Test that while typechecking _Pack expressions we check that the return type
|
||||
// (which is the second argument to the pack) is an existential type.
|
||||
// If not, we should display an error.
|
||||
void TestPackReturnExpectsExistential() {
|
||||
struct Foo _For_any(T) {};
|
||||
struct Foo<int> fooInt;
|
||||
_Exists(T, struct Foo<T>) fooExists = _Pack(fooInt, struct Foo<int>, int); // expected-error {{return type of a pack expression must be an existential type, but got 'struct Foo<int>' instead}}
|
||||
}
|
||||
|
||||
// Test that we display an error message if the user tries
|
||||
// to unpack multiple type variables (this will be supported in the future).
|
||||
void TestUnpackWithMultipleTypeVars() {
|
||||
struct Foo _For_any(T) {};
|
||||
_Exists(T, struct Foo<T>) fooExist;
|
||||
_Unpack (A, B, C) struct Foo<A> fooAbs = fooExist; // expected-error {{expected ')'}} expected-error {{expected identifier or '('}}
|
||||
}
|
||||
|
||||
// Test that we check that the initializer to an unpack declaration
|
||||
// has an existential type.
|
||||
void TestUnpackRequiresExistentialInit() {
|
||||
struct Foo _For_any(T) {};
|
||||
struct Foo<int> fooInt;
|
||||
_Exists(B, struct Foo<B>) fooExist = _Pack(fooInt, _Exists(C, struct Foo<C>), int);
|
||||
_Unpack (A) struct Foo<A> fooA = fooInt; // expected-error {{unpack specifer expects an initializer that has an existential type}}
|
||||
_Unpack (B) struct Foo<B> fooB = fooExist;
|
||||
}
|
||||
|
||||
// Test that we can handle a malformed unpack specifier that's missing the type variable.
|
||||
void TestUnpackMissingTypeVariable() {
|
||||
struct Foo _For_any(T) {};
|
||||
_Unpack (int) struct Foo<A> fooA; // expected-error {{expected type variable identifier}} expected-error {{unknown type name 'A'}}
|
||||
}
|
|
@ -14,7 +14,7 @@
|
|||
//
|
||||
//
|
||||
|
||||
void f1(int *p : itype(ptr<int>)) {
|
||||
void f1(int *p _Itype(int* _Single)) {
|
||||
}
|
||||
|
||||
void f2(int *p : count(len), int len) {
|
||||
|
@ -23,7 +23,7 @@ void f2(int *p : count(len), int len) {
|
|||
void f3(int *p : byte_count(len * sizeof(int)), int len) {
|
||||
}
|
||||
|
||||
void f4(int *p : bounds(p, p + len), int len) {
|
||||
void f4(int *p _Bounds(p, p + len), int len) {
|
||||
}
|
||||
|
||||
// single-dimensional array parameters
|
||||
|
@ -48,7 +48,7 @@ void f2_incomplete_arr(int p[] : count(len), int len) {
|
|||
void f3_incomplete_arr(int p[] : byte_count(len * sizeof(int)), int len) {
|
||||
}
|
||||
|
||||
void f4_incomplete_arr(int p[] : bounds(p, p + len), int len) {
|
||||
void f4_incomplete_arr(int p[] _Bounds(p, p + len), int len) {
|
||||
}
|
||||
|
||||
// multi-dimensional array parameters
|
||||
|
@ -73,7 +73,7 @@ void f2_incomplete_md_arr(int p[][10] : count(len), int len) {
|
|||
void f3_incomplete_md_arr(int p[][10] : byte_count(len * sizeof(int[10])), int len) {
|
||||
}
|
||||
|
||||
void f4_incomplete_md_arr(int p[][10] : bounds(p, p + len), int len) {
|
||||
void f4_incomplete_md_arr(int p[][10] _Bounds(p, p + len), int len) {
|
||||
}
|
||||
|
||||
// void * parameters with interop declarations. Note that count bounds
|
||||
|
@ -88,7 +88,7 @@ void f2_void(void *p : count(len), int len) { // expected-error {{expected 'p' t
|
|||
void f3_void(void *p : byte_count(len * sizeof(int)), int len) {
|
||||
}
|
||||
|
||||
void f4_void(void *p : bounds(p, (char *)p + len), int len) {
|
||||
void f4_void(void *p _Bounds(p, (char *)p + len), int len) {
|
||||
}
|
||||
|
||||
void g1(ptr<int> p) {
|
||||
|
@ -158,7 +158,7 @@ void g2_complete_array_arg(void) {
|
|||
|
||||
// Test passing multi-diemensional arrays through bounds-safe
|
||||
// interfaces.
|
||||
void g2_md(array_ptr<int checked[10]> ap : count(len), int len) {
|
||||
void g2_md(int (* _Array ap) checked[10] _Count(len), int len) {
|
||||
if (len >= 10) {
|
||||
f1_complete_md_arr(ap); // expected-error {{it is not possible to prove argument meets declared bounds for 1st parameter}}
|
||||
f2_complete_md_arr(ap); // expected-error {{it is not possible to prove argument meets declared bounds for 1st parameter}}
|
||||
|
@ -172,7 +172,7 @@ void g2_md(array_ptr<int checked[10]> ap : count(len), int len) {
|
|||
f4_incomplete_md_arr(ap, len);
|
||||
}
|
||||
|
||||
void g2_incomplete_md_array_param(int ap checked[][10] : count(len), int len) {
|
||||
void g2_incomplete_md_array_param(int ap checked[][10] _Count(len), int len) {
|
||||
f1_incomplete_md_arr(ap);
|
||||
f2_incomplete_md_arr(ap, len);
|
||||
f3_incomplete_md_arr(ap, len);
|
||||
|
@ -217,7 +217,7 @@ void g3(ptr<float> p) {
|
|||
f1(p); // expected-error {{incompatible type}}
|
||||
}
|
||||
|
||||
void g4(array_ptr<float> ap : count(len), int len) {
|
||||
void g4(float* _Array ap _Count(len), int len) {
|
||||
f2(ap, len); // expected-error {{incompatible type}}
|
||||
f3(ap, len); // expected-error {{incompatible type}}
|
||||
f4(ap, len); // expected-error {{incompatible type}}
|
||||
|
@ -261,10 +261,10 @@ void f1_const(const int *p : itype(ptr<const int>)) {
|
|||
void f2_const(const int *p : count(len), int len) {
|
||||
}
|
||||
|
||||
void f3_const(const int *p : byte_count(len * sizeof(int)), int len) {
|
||||
void f3_const(const int *p _Byte_count(len * sizeof(int)), int len) {
|
||||
}
|
||||
|
||||
void f4_const(const int *p : bounds(p, p + len), int len) {
|
||||
void f4_const(const int *p _Bounds(p, p + len), int len) {
|
||||
}
|
||||
|
||||
// Pointers to non-const qualified data can be passed to parameters that are pointers
|
||||
|
@ -278,7 +278,7 @@ void g10(ptr<const int> p) {
|
|||
f1_const(p);
|
||||
}
|
||||
|
||||
void g11(array_ptr<int> ap : count(len), int len) {
|
||||
void g11(int* _Array ap _Count(len), int len) {
|
||||
f2_const(ap, len);
|
||||
f3_const(ap, len);
|
||||
f4_const(ap, len);
|
||||
|
@ -346,7 +346,7 @@ void g20(ptr<int> p) {
|
|||
v1 = p;
|
||||
}
|
||||
|
||||
void g21(array_ptr<int> ap : count(10)) {
|
||||
void g21(int* _Array ap _Count(10)) {
|
||||
v2 = ap;
|
||||
v3 = ap;
|
||||
v4 = ap;
|
||||
|
@ -363,7 +363,7 @@ void g22(ptr<float> p) {
|
|||
v1 = p; // expected-error {{incompatible type}}
|
||||
}
|
||||
|
||||
void g23(array_ptr<float> ap : count(10)) {
|
||||
void g23(float* _Array ap _Count(10)) {
|
||||
v2 = ap; // expected-error {{incompatible type}}
|
||||
v3 = ap; // expected-error {{incompatible type}}
|
||||
v4 = ap; // expected-error {{incompatible type}}
|
||||
|
@ -387,7 +387,7 @@ void g26(ptr<void> p) {
|
|||
v1_void = p;
|
||||
}
|
||||
|
||||
void g27(array_ptr<void> ap : byte_count(10 * sizeof(int))) {
|
||||
void g27(void* _Array ap _Byte_count(10 * sizeof(int))) {
|
||||
v3 = ap;
|
||||
v4 = ap;
|
||||
v3_void = ap;
|
||||
|
@ -411,10 +411,10 @@ void g30(ptr<int> p) {
|
|||
const_v1 = p;
|
||||
}
|
||||
|
||||
void g31(array_ptr<int> ap : count(10)) {
|
||||
const_v2 = ap;
|
||||
const_v3 = ap;
|
||||
const_v4 = ap; // expected-error {{it is not possible to prove that the inferred bounds of 'const_v4' imply the declared bounds of 'const_v4' after assignment}}
|
||||
void g31(int* _Array ap _Count(10)) {
|
||||
const_v2 = ap;
|
||||
const_v3 = ap;
|
||||
const_v4 = ap; // expected-error {{it is not possible to prove that the inferred bounds of 'const_v4' imply the declared bounds of 'const_v4' after assignment}}
|
||||
}
|
||||
|
||||
// Pointers to const-data should not be assigned to pointers to non-const qualified
|
||||
|
@ -434,7 +434,7 @@ void g34(ptr<int> p) {
|
|||
v1_const = p; // expected-error {{cannot assign to variable}}
|
||||
}
|
||||
|
||||
void g35(array_ptr<int> ap : count(10)) {
|
||||
void g35(int* _Array ap _Count(10)) {
|
||||
v2_const = ap; // expected-error {{cannot assign to variable 'v2_const' with const-qualified}}
|
||||
v3_const = ap; // expected-error {{cannot assign to variable 'v3_const' with const-qualified}}
|
||||
v4_const = ap; // expected-error {{cannot assign to variable 'v4_const' with const-qualified}}
|
||||
|
@ -460,7 +460,7 @@ struct S1_void {
|
|||
void *arr3 : bounds(arr3, (char *) arr3 + 10 * sizeof(int));
|
||||
};
|
||||
|
||||
void g40(ptr<struct S1> p, ptr<int> p1, array_ptr<int> p2 : count(10)) {
|
||||
void g40(struct S1* _Single p, int* _Single p1, int* _Array p2 _Count(10)) {
|
||||
p->pint = p1;
|
||||
p->arr1 = p2;
|
||||
p->arr2 = p2;
|
||||
|
@ -529,7 +529,7 @@ struct S3 {
|
|||
int *const arr3 : bounds(arr3, arr3 + 10);
|
||||
};
|
||||
|
||||
void g47(ptr<struct S3> p, ptr<int> p1, array_ptr<int> p2 : count(10)) {
|
||||
void g47(struct S3* _Single p, void* _Single p1, int* _Array p2 _Count(10)) {
|
||||
p->pint = p1; // expected-error {{cannot assign to non-static data member 'pint' with const-qualified type }}
|
||||
p->arr1 = p2; // expected-error {{cannot assign to non-static data member 'arr1' with const-qualified type}}
|
||||
p->arr2 = p2; // expected-error {{cannot assign to non-static data member 'arr2' with const-qualified type}}
|
||||
|
@ -615,7 +615,7 @@ void g82(callback_fn3 fn) {
|
|||
|
||||
// Assign a checked pointer to the dereference of an
|
||||
// unchecked pointer with a bounds-safe interface.
|
||||
void g90(int **interop_ptr : itype(array_ptr<ptr<int>>) count(3), ptr<int> checked_ptr) {
|
||||
void g90(int **interop_ptr _Itype(array_ptr<ptr<int>>) count(3), int* _Single checked_ptr) {
|
||||
*interop_ptr = checked_ptr;
|
||||
*(interop_ptr - 1) = checked_ptr;
|
||||
*(2 + interop_ptr) = checked_ptr;
|
||||
|
|
|
@ -10,7 +10,7 @@ _Itype_for_any(T) void* oneTypeVariable(void* a : itype(_Ptr<T>), void* b : ityp
|
|||
return a;
|
||||
}
|
||||
|
||||
_Itype_for_any(T, Q) void* manyTypeVariables(void* a : itype(_Ptr<T>), void* b : itype(_Ptr<Q>)) : itype(_Ptr<Q>) {
|
||||
_Itype_for_any(T, Q) void* manyTypeVariables(void* a _Itype(T* _Single), void* b _Itype(Q* _Single)) _Itype(Q* _Single) {
|
||||
return b;
|
||||
}
|
||||
|
||||
|
@ -19,13 +19,12 @@ _Itype_for_any(T)
|
|||
void* validItypeGenericFunction(int a, void* b : itype(_Ptr<T>), void* c : itype(_Ptr<T>)) : itype(_Ptr<T>);
|
||||
|
||||
_Itype_for_any(T)
|
||||
void* validItypeGenericFunction(int a, void* b : itype(_Ptr<T>) , void* c : itype(_Ptr<T>) ) : itype(_Ptr<T>) {
|
||||
_Ptr<T> m = b;
|
||||
void* validItypeGenericFunction(int a, void* b _Itype(T* _Single) , void* c _Itype(T* _Single) ) _Itype(T* _Single) {
|
||||
T* _Single m = b;
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CallItypeGenericFunctions(void) {
|
||||
int a = 0, b = 0, c = 0, d = 0;
|
||||
_Ptr<int> ap = &a;
|
||||
|
|
|
@ -37,7 +37,7 @@ void f4(void) unchecked {
|
|||
|
||||
// Test you can always `free` a `malloc`d ptr
|
||||
void f11(void) {
|
||||
ptr<int> x = malloc<int>(sizeof(int));
|
||||
int* _Single x = malloc _TyArgs(int) (sizeof(int));
|
||||
free<int>(x);
|
||||
}
|
||||
|
||||
|
@ -78,9 +78,9 @@ void f22(void) {
|
|||
|
||||
// Test you can always `free` a `realloc`d array_ptr
|
||||
void f23(void) {
|
||||
array_ptr<int> x : count(4) = malloc<int>(4 * sizeof(int));
|
||||
array_ptr<int> y : count(8) = realloc<int>(x, 8 * sizeof(int));
|
||||
free<int>(y);
|
||||
int* _Array x _Count(4) = malloc _TyArgs(int) (4 * sizeof(int));
|
||||
int* _Array y _Count(8) = realloc _TyArgs(int) (x, 8 * sizeof(int));
|
||||
free _TyArgs(int) (y);
|
||||
}
|
||||
|
||||
// Test you can always `free` a `aligned_alloc`d array_ptr
|
||||
|
|
|
@ -81,7 +81,7 @@ union U7 {
|
|||
// embedded in objects.
|
||||
//
|
||||
|
||||
extern ptr<int> f1(); // expected-error {{function with no prototype cannot have a return type that is a checked type}}
|
||||
extern int* _Single f1(); // expected-error {{function with no prototype cannot have a return type that is a checked type}}
|
||||
extern array_ptr<int> f2();// expected-error {{function with no prototype cannot have a return type that is a checked type}}
|
||||
extern struct S1 f3(); // expected-error {{function with no prototype cannot have a return type that is a structure with a member with a checked type}}
|
||||
extern struct S2 f4(); // expected-error {{function with no prototype cannot have a return type that is a structure with a member with a checked type}}
|
||||
|
@ -106,7 +106,7 @@ extern int (*f19())(ptr<int>); // expected-error {{function with no prototype c
|
|||
|
||||
// Returns an unchecked pointer to a no-prototype function returning a checked
|
||||
// value (ptr<int>)
|
||||
extern ptr<int> (*f20(void))(); // expected-error {{function with no prototype cannot have a return type that is a checked type}}
|
||||
extern int* _Single (*f20(void))(); // expected-error {{function with no prototype cannot have a return type that is a checked type}}
|
||||
// Returns a checked pointer to a function with a checked argument (ptr<int>)
|
||||
extern ptr<int (ptr<int>)> f21(); // expected-error {{function with no prototype cannot have a return type that is a checked type}}
|
||||
|
||||
|
@ -120,7 +120,7 @@ extern ptr<int (ptr<int>)> f21(); // expected-error {{function with no prototype
|
|||
// pointers to function types that take or return checked values.
|
||||
|
||||
extern ptr<int> *f30();
|
||||
extern array_ptr<int> *f31();
|
||||
extern int* _Array *f31();
|
||||
extern struct S1 *f32();
|
||||
extern struct S2 *f33();
|
||||
extern struct S3 *f34();
|
||||
|
@ -139,7 +139,7 @@ extern struct S9 *f41();
|
|||
extern array_ptr<int> f50() : count(5); // expected-error {{function with no prototype cannot have a return type that is a checked type}}
|
||||
extern int f51() : byte_count(10);
|
||||
extern int *f52() : byte_count(10);
|
||||
extern int *f53() : itype(ptr<int>);
|
||||
extern int *f53() _Itype(ptr<int>);
|
||||
|
||||
// No prototype functions cannot be redeclared to take arguments that are
|
||||
// checked values or objects with checked values embedded within them.
|
||||
|
@ -148,7 +148,7 @@ extern void f60();
|
|||
extern void f60(ptr<int>); // expected-error {{cannot redeclare a function with no prototype to have an argument type that is a checked type}}
|
||||
|
||||
extern void f61();
|
||||
extern void f61(array_ptr<int>); // expected-error {{cannot redeclare a function with no prototype to have an argument type that is a checked type}}
|
||||
extern void f61(int* _Array); // expected-error {{cannot redeclare a function with no prototype to have an argument type that is a checked type}}
|
||||
|
||||
extern void f62();
|
||||
extern void f62(struct S1); // expected-error {{cannot redeclare a function with no prototype to have an argument type that is a structure with a member with a checked type}}
|
||||
|
@ -202,7 +202,7 @@ extern void f80(int checked[]); // expected-error {{cannot redeclare a function
|
|||
// Function type arguments.
|
||||
|
||||
extern void f81();
|
||||
extern void f81(ptr<int> f(void)); // expected-error {{cannot redeclare a function with no prototype to have an argument type that is a checked type}}
|
||||
extern void f81(int* _Single f(void)); // expected-error {{cannot redeclare a function with no prototype to have an argument type that is a checked type}}
|
||||
|
||||
extern void f82();
|
||||
extern void f82(int f(ptr<int>)); // expected-error {{cannot redeclare a function with no prototype to have an argument type that is a checked type}}
|
||||
|
@ -216,7 +216,7 @@ extern void f84(int f()); // expected-error {{conflicting types for 'f84'}}
|
|||
// No prototype functions can be redeclared with bounds-safe interfaces on integer and
|
||||
// unchecked pointer arguments.
|
||||
extern void f85();
|
||||
extern void f85(char *p : bounds(p, p + len), int len);
|
||||
extern void f85(char *p _Bounds(p, p + len), int len);
|
||||
|
||||
//
|
||||
// Redeclaring a function with a checked argument as a no prototype function is not allowed.
|
||||
|
@ -236,10 +236,10 @@ extern void f91();
|
|||
//
|
||||
|
||||
struct S20 {
|
||||
ptr<int> (*f)(); // expected-error {{function with no prototype cannot have a return type that is a checked type}}
|
||||
int* _Single (*f)(); // expected-error {{function with no prototype cannot have a return type that is a checked type}}
|
||||
};
|
||||
|
||||
typedef ptr<int> functype1(); // expected-error {{function with no prototype cannot have a return type that is a checked type}}
|
||||
typedef int* _Single functype1(); // expected-error {{function with no prototype cannot have a return type that is a checked type}}
|
||||
|
||||
// Check the obscure case of a function being declared as a no-prototype, then
|
||||
// being declared to have a prototype with an incomplete type, and then
|
||||
|
@ -249,7 +249,7 @@ struct S21;
|
|||
extern void f100();
|
||||
extern void f100(struct S21);
|
||||
struct S21 {
|
||||
ptr<int> m;
|
||||
int* _Single m;
|
||||
};
|
||||
|
||||
extern void f100(struct S21 x) { // expected-error {{cannot redeclare a function with no prototype to have an argument type that is a structure with a member with a checked type}}
|
||||
|
|
|
@ -1,32 +1,32 @@
|
|||
// Feature tests of typechecking new Checked C bounds declarations.
|
||||
//
|
||||
// The following lines are for the LLVM test harness:
|
||||
//
|
||||
// RUN: %clang_cc1 -Wno-check-bounds-decls -verify -verify-ignore-unexpected=note %s
|
||||
|
||||
#include <stdchecked.h>
|
||||
|
||||
_Static_assert(sizeof(void*) > sizeof(int),
|
||||
"Pointers must be larger than ints");
|
||||
|
||||
enum E1 {
|
||||
EnumVal1,
|
||||
EnumVal2
|
||||
};
|
||||
|
||||
void int_local_var_bounds_decl(void) {
|
||||
// bounds declarations are allowed for integer variables to support
|
||||
// casting of pointers to integers and back. We usually expect this
|
||||
// to happen within expressions, but to allow uniform use of language
|
||||
// features, we allow bounds on integer-typed variables.
|
||||
int a1 checked[5];
|
||||
|
||||
// byte_count
|
||||
int t21 : byte_count(5 * sizeof(int)) = (int)a1; // expected-warning {{cast to smaller integer type 'int' from '_Array_ptr<int>'}}
|
||||
|
||||
// bounds
|
||||
int t25 : bounds(a1, a1 + 5) = (int)a1; // expected-warning {{cast to smaller integer type 'int' from '_Array_ptr<int>'}}
|
||||
long int t26 : bounds(a1, a1 + 5) = (int)a1; // expected-warning {{cast to smaller integer type 'int' from '_Array_ptr<int>'}}
|
||||
unsigned long int t27 : bounds(a1, a1 + 5) = (int)a1; // expected-warning {{cast to smaller integer type 'int' from '_Array_ptr<int>'}}
|
||||
enum E1 t28 : bounds(a1, a1 + 5) = (int)a1; // expected-warning {{cast to smaller integer type 'int' from '_Array_ptr<int>'}}
|
||||
}
|
||||
// Feature tests of typechecking new Checked C bounds declarations.
|
||||
//
|
||||
// The following lines are for the LLVM test harness:
|
||||
//
|
||||
// RUN: %clang_cc1 -Wno-check-bounds-decls -verify -verify-ignore-unexpected=note %s
|
||||
|
||||
#include <stdchecked.h>
|
||||
|
||||
_Static_assert(sizeof(void*) > sizeof(int),
|
||||
"Pointers must be larger than ints");
|
||||
|
||||
enum E1 {
|
||||
EnumVal1,
|
||||
EnumVal2
|
||||
};
|
||||
|
||||
void int_local_var_bounds_decl(void) {
|
||||
// bounds declarations are allowed for integer variables to support
|
||||
// casting of pointers to integers and back. We usually expect this
|
||||
// to happen within expressions, but to allow uniform use of language
|
||||
// features, we allow bounds on integer-typed variables.
|
||||
int a1 checked[5];
|
||||
|
||||
// byte_count
|
||||
int t21 _Byte_count(5 * sizeof(int)) = (int)a1; // expected-warning {{cast to smaller integer type 'int' from '_Array_ptr<int>'}}
|
||||
|
||||
// bounds
|
||||
int t25 : bounds(a1, a1 + 5) = (int)a1; // expected-warning {{cast to smaller integer type 'int' from '_Array_ptr<int>'}}
|
||||
long int t26 : bounds(a1, a1 + 5) = (int)a1; // expected-warning {{cast to smaller integer type 'int' from '_Array_ptr<int>'}}
|
||||
unsigned long int t27 : bounds(a1, a1 + 5) = (int)a1; // expected-warning {{cast to smaller integer type 'int' from '_Array_ptr<int>'}}
|
||||
enum E1 t28 _Bounds(a1, a1 + 5) = (int)a1; // expected-warning {{cast to smaller integer type 'int' from '_Array_ptr<int>'}}
|
||||
}
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
// Feature tests of typechecking new Checked C bounds declarations.
|
||||
//
|
||||
// The following lines are for the LLVM test harness:
|
||||
//
|
||||
// RUN: %clang_cc1 -Wno-check-bounds-decls -verify -verify-ignore-unexpected=note %s
|
||||
|
||||
#include <stdchecked.h>
|
||||
|
||||
_Static_assert(sizeof(void*) > sizeof(long),
|
||||
"Pointers must be larger than longs");
|
||||
|
||||
void int_local_var_bounds_decl(void) {
|
||||
// bounds declarations are allowed for integer variables to support
|
||||
// casting of pointers to integers and back. We usually expect this
|
||||
// to happen within expressions, but to allow uniform use of language
|
||||
// features, we allow bounds on integer-typed variables.
|
||||
int a1 checked[5];
|
||||
|
||||
long int t22 : byte_count(5 * sizeof(int)) = (long int)a1; // expected-warning {{cast to smaller integer type 'long' from '_Array_ptr<int>'}}
|
||||
unsigned long int t23 : byte_count(5 * sizeof(int)) = (unsigned long int) a1; // expected-warning {{cast to smaller integer type 'unsigned long' from '_Array_ptr<int>'}}
|
||||
}
|
||||
// Feature tests of typechecking new Checked C bounds declarations.
|
||||
//
|
||||
// The following lines are for the LLVM test harness:
|
||||
//
|
||||
// RUN: %clang_cc1 -Wno-check-bounds-decls -verify -verify-ignore-unexpected=note %s
|
||||
|
||||
#include <stdchecked.h>
|
||||
|
||||
_Static_assert(sizeof(void*) > sizeof(long),
|
||||
"Pointers must be larger than longs");
|
||||
|
||||
void int_local_var_bounds_decl(void) {
|
||||
// bounds declarations are allowed for integer variables to support
|
||||
// casting of pointers to integers and back. We usually expect this
|
||||
// to happen within expressions, but to allow uniform use of language
|
||||
// features, we allow bounds on integer-typed variables.
|
||||
int a1 checked[5];
|
||||
|
||||
long int t22 : byte_count(5 * sizeof(int)) = (long int)a1; // expected-warning {{cast to smaller integer type 'long' from '_Array_ptr<int>'}}
|
||||
unsigned long int t23 : byte_count(5 * sizeof(int)) = (unsigned long int) a1; // expected-warning {{cast to smaller integer type 'unsigned long' from '_Array_ptr<int>'}}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ int f0(int a) {
|
|||
return a;
|
||||
}
|
||||
|
||||
void local_convert(int(*f1)(int), ptr<int(int)> f2) {
|
||||
void local_convert(int(*f1)(int), int (*_Single f2)(int)) {
|
||||
// There's no good reason to do this to any function pointers
|
||||
// and it's definitely not safe.
|
||||
ptr<int(int)> local_weird_unsafe1 = (ptr<int(int)>)~(long)f1; // expected-error {{can only cast function names or null pointers to checked function pointer type '_Ptr<int (int)>'}}
|
||||
|
@ -24,7 +24,7 @@ void local_convert(int(*f1)(int), ptr<int(int)> f2) {
|
|||
ptr<int(int)> local_weird_unsafe8 = (ptr<int(int)>) + (long)f2; // expected-error {{can only cast function names or null pointers to checked function pointer type '_Ptr<int (int)>'}}
|
||||
ptr<int(int)> local_weird_unsafe9 = (ptr<int(int)>) + (long)f0; // expected-error {{can only cast function names or null pointers to checked function pointer type '_Ptr<int (int)>'}}
|
||||
ptr<int(int)> local_weird_unsafe10 = (ptr<int(int)>) - (long)f1; // expected-error {{can only cast function names or null pointers to checked function pointer type '_Ptr<int (int)>'}}
|
||||
ptr<int(int)> local_weird_unsafe11 = (ptr<int(int)>) - (long)f2; // expected-error {{can only cast function names or null pointers to checked function pointer type '_Ptr<int (int)>'}}
|
||||
ptr<int(int)> local_weird_unsafe12 = (ptr<int(int)>) - (long)f0; // expected-error {{can only cast function names or null pointers to checked function pointer type '_Ptr<int (int)>'}}
|
||||
int (*_Single local_weird_unsafe11)(int) = (int (*_Single )(int)) - (long)f2; // expected-error {{can only cast function names or null pointers to checked function pointer type '_Ptr<int (int)>'}}
|
||||
int (*_Single local_weird_unsafe12)(int) = (int (*_Single )(int)) - (long)f0; // expected-error {{can only cast function names or null pointers to checked function pointer type '_Ptr<int (int)>'}}
|
||||
|
||||
}
|
|
@ -14,7 +14,7 @@ _Static_assert(sizeof(void*) == sizeof(long),
|
|||
struct S1 {
|
||||
int len;
|
||||
// bound declaration on a long-typed member.
|
||||
long p : bounds((char *)p, (char *)p + len);
|
||||
long p _Bounds((char *)p, (char *)p + len);
|
||||
};
|
||||
|
||||
extern struct S1 f1(); // expected-error {{function with no prototype cannot have a return type that is a structure with a member with a checked type}}
|
||||
|
@ -25,7 +25,7 @@ extern void f2(struct S1); // expected-error {{cannot redeclare a function with
|
|||
extern void f3();
|
||||
extern void f3(long p : bounds((char *)p, (char *)p + len), int len);
|
||||
|
||||
extern void f4(long p : bounds((char *)p, (char *)p + len), int len);
|
||||
extern void f4(long p _Bounds((char *)p, (char *)p + len), int len);
|
||||
extern void f4();
|
||||
|
||||
//
|
||||
|
@ -70,6 +70,7 @@ extern int f10(int a, _Array_ptr<int> b,
|
|||
// expected-warning 2 {{cast to '_Array_ptr<int>' from smaller integer type 'short'}} \
|
||||
// expected-warning 2 {{cast to smaller integer type 'short' from '_Array_ptr<int>'}}
|
||||
|
||||
extern int f11(int a, _Array_ptr<int> b, _Array_ptr<char> p : bounds(b, b + a));
|
||||
extern int f11(int a, _Array_ptr<int> b,
|
||||
_Array_ptr<char> p : bounds(b, (_Array_ptr<int>) (void *) (long) b + a));
|
||||
extern int f11(int a, int* _Array b, char* _Array p _Bounds(b, b + a));
|
||||
extern int f11(int a, int* _Array b,
|
||||
char* _Array p _Bounds(b, (int* _Array) (void *) (long) b + a));
|
||||
|
||||
|
|
|
@ -13,11 +13,11 @@ extern void check_indirection_unsafe_ptr(int *p, const int *const_p, int y) {
|
|||
y = *const_p;
|
||||
}
|
||||
|
||||
extern void check_indirection_ptr(ptr<int> p, ptr<const int> const_p, int y) {
|
||||
*p = y;
|
||||
y = *p;
|
||||
*const_p = y; // expected-error {{read-only variable is not assignable}}
|
||||
y = *const_p;
|
||||
extern void check_indirection_ptr(int* _Single p, const int *_Single const_p, int y) {
|
||||
*p = y;
|
||||
y = *p;
|
||||
*const_p = y; // expected-error {{read-only variable is not assignable}}
|
||||
y = *const_p;
|
||||
}
|
||||
|
||||
extern void check_indirection_array_ptr(array_ptr<int> p : count(1),
|
||||
|
@ -84,17 +84,17 @@ extern void check_subscript_nt_array_ptr(nt_array_ptr<int> p : count(1),
|
|||
|
||||
// Test restrictions on null-terminated pointer types.
|
||||
void check_nullterm_restrictions(void) {
|
||||
nt_array_ptr<int> t1 = 0; // integer types are OK.
|
||||
nt_array_ptr<ptr<int>> t2 = 0; // pointer types are OK.
|
||||
int* _Nt_array t1 = 0; // integer types are OK.
|
||||
int* _Single *_Nt_array t2 = 0; // pointer types are OK.
|
||||
enum E { Null, Blue, White };
|
||||
nt_array_ptr<enum E> t3 = 0; // enum types are OK
|
||||
enum E* _Nt_array t3 = 0; // enum types are OK
|
||||
|
||||
nt_array_ptr<void> t10 = 0; // expected-error {{only integer and pointer types are allowed}}
|
||||
nt_array_ptr<float> t11 = 0; // expected-error {{only integer and pointer types are allowed}}
|
||||
nt_array_ptr<double> t12 = 0; // expected-error {{only integer and pointer types are allowed}}
|
||||
nt_array_ptr<int checked[5]> t13 = 0; // expected-error {{only integer and pointer types are allowed}}
|
||||
void* _Nt_array t10 = 0; // expected-error {{only integer and pointer types are allowed}}
|
||||
float* _Nt_array t11 = 0; // expected-error {{only integer and pointer types are allowed}}
|
||||
double* _Nt_array t12 = 0; // expected-error {{only integer and pointer types are allowed}}
|
||||
int* _Nt_array t13 checked[5] = 0; // expected-error {{array initializer must be an initializer list}}
|
||||
struct S { int i; };
|
||||
nt_array_ptr<struct S> t14 = 0; // expected-error {{only integer and pointer types are allowed}}
|
||||
struct S* _Nt_array t14 = 0; // expected-error {{only integer and pointer types are allowed}}
|
||||
}
|
||||
|
||||
|
||||
|
@ -120,13 +120,13 @@ extern void check_assign(int val, int *p, ptr<int> q, array_ptr<int> r,
|
|||
// T * = nt_array_ptr<T> not OK
|
||||
ptr<int> t8 = r; // expected-error {{expression has unknown bounds}}
|
||||
// ptr<T> = array_ptr<T> OK
|
||||
ptr<int> t8a = v; // ptr<T> = nt_array_ptr<T> OK.
|
||||
array_ptr<int> t9 = q; // array_ptr<T> = ptr<T> OK
|
||||
array_ptr<int> t10a = v; // array_ptr<T> = nt_array_ptr<T> OK.
|
||||
nt_array_ptr<int> t10b = q; // expected-error {{incompatible type}}
|
||||
// nt_array_ptr<T> = ptr<T> not OK.
|
||||
nt_array_ptr<int> t10ca = r; // expected-error {{incompatible type}}
|
||||
// nt_array_ptr<T> = array_ptr<T> not OK.
|
||||
int* _Single t8a = v; // ptr<T> = nt_array_ptr<T> OK.
|
||||
int* _Array t9 = q; // array_ptr<T> = ptr<T> OK
|
||||
int* _Array t10a = v; // array_ptr<T> = nt_array_ptr<T> OK.
|
||||
int* _Nt_array t10b = q; // expected-error {{incompatible type}}
|
||||
// nt_array_ptr<T> = ptr<T> not OK.
|
||||
int* _Nt_array t10ca = r; // expected-error {{incompatible type}}
|
||||
// nt_array_ptr<T> = array_ptr<T> not OK.
|
||||
|
||||
// check assigning different kinds of pointers with different referent
|
||||
// types
|
||||
|
@ -172,7 +172,7 @@ extern void check_assign(int val, int *p, ptr<int> q, array_ptr<int> r,
|
|||
// array_ptr<T> = S * not OK;
|
||||
array_ptr<float> t25 = q; // expected-error {{incompatible type}}
|
||||
// array_ptr<T> = ptr<S> not OK;
|
||||
array_ptr<float> t26 = r; // expected-error {{incompatible type}}
|
||||
float* _Array t26 = r; // expected-error {{incompatible type}}
|
||||
// array_ptr<T> = array_ptr<S> not OK
|
||||
|
||||
// C compilers enforcing C99 conversion rules allow implicit
|
||||
|
@ -210,8 +210,8 @@ extern void check_assign(int val, int *p, ptr<int> q, array_ptr<int> r,
|
|||
ptr<int> t38 = (_Bool)(1); // expected-error {{incompatible type}}
|
||||
ptr<float> t39 = (_Bool)(1); // expected-error {{incompatible type}}
|
||||
array_ptr<int> t40 = (_Bool)(1); // expected-error {{incompatible type}}
|
||||
array_ptr<float> t41 = (_Bool)(1); // expected-error {{incompatible type}}
|
||||
nt_array_ptr<int> t41a = (_Bool)(1); // expected-error {{incompatible type}}
|
||||
float* _Array t41 = (_Bool)(1); // expected-error {{incompatible type}}
|
||||
int* _Nt_array t41a = (_Bool)(1); // expected-error {{incompatible type}}
|
||||
|
||||
// Implicit conversion of 0 to a safe pointer type is OK.
|
||||
ptr<int> t42 = 0;
|
||||
|
@ -242,7 +242,7 @@ extern void check_assign(int val, int *p, ptr<int> q, array_ptr<int> r,
|
|||
|
||||
array_ptr<int> t53 = unchecked_ptr_to_checked_ptr; // expected-error {{incompatible type}}
|
||||
array_ptr<int> t54 = checked_ptr_to_checked_ptr; // expected-error {{incompatible type}}
|
||||
array_ptr<int> t56 = array_ptr_to_checked_ptr; // expected-error {{incompatible type}}
|
||||
int* _Array t56 = array_ptr_to_checked_ptr; // expected-error {{incompatible type}}
|
||||
|
||||
unchecked_ptr_to_checked_ptr = q; // expected-error {{incompatible type}}
|
||||
checked_ptr_to_checked_ptr = p; // expected-error {{incompatible type}}
|
||||
|
@ -336,12 +336,12 @@ check_assign_void_unchecked(int val, int *p, ptr<int> q,
|
|||
array_ptr<int> t25 = u;
|
||||
nt_array_ptr<int> t25a = (void *)&val; // expected-error {{incompatible type}}
|
||||
// nt_array_ptr<int> = void * not OK.
|
||||
nt_array_ptr<int> t25b = s; // expected-error {{incompatible type}}
|
||||
// nt_array_ptr<int> = void * not OK, even with obunds
|
||||
nt_array_ptr<int> t25c = t; // expected-error {{incompatible type}}
|
||||
// nt_array_ptr<int> = ptr<void> not OK.
|
||||
nt_array_ptr<int> t25d = u; // expected-error {{incompatible type}}
|
||||
// nt_array_ptr<int> = array_ptr<void> not OK.
|
||||
int* _Nt_array t25b = s; // expected-error {{incompatible type}}
|
||||
// int* _Nt_array = void * not OK, even with obunds
|
||||
int* _Nt_array t25c = t; // expected-error {{incompatible type}}
|
||||
// int* _Nt_array = void* _Single not OK.
|
||||
int* _Nt_array t25d = u; // expected-error {{incompatible type}}
|
||||
// int* _Nt_array = void* _Array not OK.
|
||||
// conversions between integers and safe void pointers.
|
||||
int t26 = t; // expected-error {{incompatible type}}
|
||||
// int = ptr<void> not OK;
|
||||
|
@ -367,8 +367,8 @@ check_assign_void_unchecked(int val, int *p, ptr<int> q,
|
|||
array_ptr<void> t35 = (_Bool)(1); // expected-error {{incompatible type}}
|
||||
|
||||
// Implicit conversion of 0 to a safe void pointer type is OK.
|
||||
ptr<void> t37 = 0;
|
||||
array_ptr<void> t38 = 0;
|
||||
void* _Single t37 = 0;
|
||||
void* _Array t38 = 0;
|
||||
}
|
||||
|
||||
// Test assignments between different kinds of pointers where the
|
||||
|
@ -377,7 +377,7 @@ check_assign_void_unchecked(int val, int *p, ptr<int> q,
|
|||
// Checked scope
|
||||
struct CheckedData1 {
|
||||
int len;
|
||||
array_ptr<int> p : count(len);
|
||||
int* _Array p : count(len);
|
||||
};
|
||||
|
||||
extern void
|
||||
|
@ -1214,8 +1214,8 @@ extern void check_call(void) {
|
|||
int val = 0;
|
||||
float fval = 0.0;
|
||||
int *p = 0;
|
||||
ptr<int> q = 0;
|
||||
array_ptr<int> r : count(1) = 0;
|
||||
int* _Single q = 0;
|
||||
int* _Array r : count(1) = 0;
|
||||
|
||||
|
||||
float *s = 0;
|
||||
|
@ -1523,12 +1523,12 @@ extern void check_call_void_checked(void) checked {
|
|||
extern void check_call_void_checked_bounds_only(void) checked bounds_only {
|
||||
int val = 0;
|
||||
float fval = 0.0;
|
||||
ptr<int> q = 0;
|
||||
array_ptr<int> r : count(1) = 0;
|
||||
int* _Single q = 0;
|
||||
int* _Array r : count(1) = 0;
|
||||
ptr<struct CheckedData1> s = 0;
|
||||
ptr<void> t = 0;
|
||||
array_ptr<void> u : byte_count(sizeof(struct CheckedData1)) = 0;
|
||||
nt_array_ptr<int> v : count(1) = 0;
|
||||
void* _Single t = 0;
|
||||
void* _Array u : byte_count(sizeof(struct CheckedData1)) = 0;
|
||||
int* _Nt_array v : count(1) = 0;
|
||||
|
||||
// Test different kinds of pointers where the parameter type is a pointer to void and
|
||||
// the referent type is not a void pointer.
|
||||
|
@ -1832,7 +1832,7 @@ array_ptr<void> check_voidptr_return21(int *p) {
|
|||
return p;
|
||||
}
|
||||
|
||||
array_ptr<void> check_voidptr_return21a(int *p) : byte_count(sizeof(int)) {
|
||||
void* _Array check_voidptr_return21a(int *p) : byte_count(sizeof(int)) {
|
||||
return p; // expected-error {{return value has unknown bounds, bounds expected because the function 'check_voidptr_return21a' has bounds}}
|
||||
}
|
||||
|
||||
|
@ -1874,7 +1874,7 @@ array_ptr<void> check_voidptr_return28(nt_array_ptr<int> p : count(1)) {
|
|||
return p;
|
||||
}
|
||||
|
||||
array_ptr<void> check_voidptr_return29(ptr<struct CheckedData1> p) {
|
||||
void* _Array check_voidptr_return29(ptr<struct CheckedData1> p) {
|
||||
return p;
|
||||
}
|
||||
|
||||
|
@ -2483,8 +2483,8 @@ void check_pointer_equality_compare(void)
|
|||
array_ptr<void> r_void = val_int;
|
||||
array_ptr<void> r2_void = val_int;
|
||||
|
||||
nt_array_ptr<int> s_int = 0;
|
||||
nt_array_ptr<int> s2_int = 0;
|
||||
int* _Nt_array s_int = 0;
|
||||
int* _Nt_array s2_int = 0;
|
||||
nt_array_ptr<char> s_char = 0;
|
||||
|
||||
// equality/inequality comparisons using different kinds of pointers to float
|
||||
|
@ -2762,8 +2762,8 @@ void check_illegal_operators(void)
|
|||
int val[5];
|
||||
int *p = val;
|
||||
ptr<int> q = &val[0];
|
||||
array_ptr<int> r = val;
|
||||
nt_array_ptr<int> s = 0;
|
||||
int* _Array r = val;
|
||||
int* _Nt_array s = 0;
|
||||
|
||||
p * 5; // expected-error {{invalid operands to binary expression}}
|
||||
5 * p; // expected-error {{invalid operands to binary expression}}
|
||||
|
@ -3051,9 +3051,9 @@ extern void test_sprintf(char *s);
|
|||
void check_address_of_types(char s[10],
|
||||
char *c : itype(char _Checked[10]),
|
||||
char buf _Nt_checked[],
|
||||
_Nt_array_ptr<char> str,
|
||||
_Array_ptr<char> arr : count(10),
|
||||
_Ptr<char> p) {
|
||||
char* _Nt_array str,
|
||||
char* _Array arr : count(10),
|
||||
char* _Single p) {
|
||||
_Unchecked {
|
||||
test_sprintf(s);
|
||||
test_sprintf(&*s);
|
||||
|
|
|
@ -1,59 +1,59 @@
|
|||
// Test type checking of static variables.
|
||||
// Static variable declarations should not use free type variables.
|
||||
//
|
||||
// RUN: %clang_cc1 -verify %s
|
||||
|
||||
struct S _For_any(X, Y, Z) { };
|
||||
|
||||
// Global static variable declarations can use bound type variables.
|
||||
static _Exists(T, struct S<T, T, T>) gs;
|
||||
|
||||
//
|
||||
// Test that declarations of static variables cannot use free type variables.
|
||||
//
|
||||
|
||||
_For_any(T, U, V) void f1(_Ptr<T> pt, struct S<T, U, V> s) {
|
||||
static T t; // expected-error {{static variable 't' has a type that uses a type variable bound in an enclosing scope (type is 'T' and type variable is 'T')}} \
|
||||
// expected-note@15 {{type variable 'T' declared here}}
|
||||
|
||||
static _Ptr<U> p; // expected-error {{static variable 'p' has a type that uses a type variable bound in an enclosing scope (type is '_Ptr<U>' and type variable is 'U')}} \
|
||||
// expected-note@15 {{type variable 'U' declared here}}
|
||||
|
||||
static _Array_ptr<V> a1; // expected-error {{static variable 'a1' has a type that uses a type variable bound in an enclosing scope (type is '_Array_ptr<V>' and type variable is 'V')}} \
|
||||
// expected-note@15 {{type variable 'V' declared here}}
|
||||
|
||||
static _Array_ptr<_Array_ptr<T>> a2; // expected-error {{static variable 'a2' has a type that uses a type variable bound in an enclosing scope (type is '_Array_ptr<_Array_ptr<T>>' and type variable is 'T')}} \
|
||||
// expected-note@15 {{type variable 'T' declared here}}
|
||||
|
||||
static struct S<T, U, T> s1; // expected-error {{static variable 's1' has a type that uses a type variable bound in an enclosing scope (type is 'struct S<T, U, T>' and type variable is 'T')}} \
|
||||
// expected-note@15 {{type variable 'T' declared here}} \
|
||||
// expected-error {{static variable 's1' has a type that uses a type variable bound in an enclosing scope (type is 'struct S<T, U, T>' and type variable is 'U')}} \
|
||||
// expected-note@15 {{type variable 'U' declared here}}
|
||||
|
||||
static _Exists(T, _Ptr<U>) e1; // expected-error {{static variable 'e1' has a type that uses a type variable bound in an enclosing scope (type is 'Exists(T, _Ptr<U>)' and type variable is 'U')}} \
|
||||
// expected-note@15 {{type variable 'U' declared here}}
|
||||
|
||||
static _Exists(T, struct S<T, U, V>) e2; // expected-error {{static variable 'e2' has a type that uses a type variable bound in an enclosing scope (type is 'Exists(T, struct S<T, U, V>)' and type variable is 'U')}} \
|
||||
// expected-note@15 {{type variable 'U' declared here}} \
|
||||
// expected-error {{static variable 'e2' has a type that uses a type variable bound in an enclosing scope (type is 'Exists(T, struct S<T, U, V>)' and type variable is 'V')}} \
|
||||
// expected-note@15 {{type variable 'V' declared here}}
|
||||
|
||||
static _Exists(A, struct S<T, U, V>) e3; // expected-error {{static variable 'e3' has a type that uses a type variable bound in an enclosing scope (type is 'Exists(A, struct S<T, U, V>)' and type variable is 'T')}} \
|
||||
// expected-note@15 {{type variable 'T' declared here}} \
|
||||
// expected-error {{static variable 'e3' has a type that uses a type variable bound in an enclosing scope (type is 'Exists(A, struct S<T, U, V>)' and type variable is 'U')}} \
|
||||
// expected-note@15 {{type variable 'U' declared here}} \
|
||||
// expected-error {{static variable 'e3' has a type that uses a type variable bound in an enclosing scope (type is 'Exists(A, struct S<T, U, V>)' and type variable is 'V')}} \
|
||||
// expected-note@15 {{type variable 'V' declared here}}
|
||||
|
||||
// Static variable declarations can use integral and pointer types and bound type variables.
|
||||
static int i;
|
||||
static struct S<char, _Ptr<int>, double> s2;
|
||||
static _Exists(T, _Ptr<T>) e4;
|
||||
static _Exists(A, struct S<A, _Ptr<A>, _Array_ptr<A>>) e5;
|
||||
|
||||
// Non-static variable declarations can use free type variables.
|
||||
_Ptr<T> q = 0;
|
||||
_Array_ptr<_Array_ptr<U>> a3;
|
||||
struct S<T, U, V> s3;
|
||||
_Exists(U, _Ptr<T>) e6;
|
||||
}
|
||||
// Test type checking of static variables.
|
||||
// Static variable declarations should not use free type variables.
|
||||
//
|
||||
// RUN: %clang_cc1 -verify %s
|
||||
|
||||
struct S _For_any(X, Y, Z) { };
|
||||
|
||||
// Global static variable declarations can use bound type variables.
|
||||
static _Exists(T, struct S<T, T, T>) gs;
|
||||
|
||||
//
|
||||
// Test that declarations of static variables cannot use free type variables.
|
||||
//
|
||||
|
||||
_For_any(T, U, V) void f1(_Ptr<T> pt, struct S<T, U, V> s) {
|
||||
static T t; // expected-error {{static variable 't' has a type that uses a type variable bound in an enclosing scope (type is 'T' and type variable is 'T')}} \
|
||||
// expected-note@15 {{type variable 'T' declared here}}
|
||||
|
||||
static _Ptr<U> p; // expected-error {{static variable 'p' has a type that uses a type variable bound in an enclosing scope (type is '_Ptr<U>' and type variable is 'U')}} \
|
||||
// expected-note@15 {{type variable 'U' declared here}}
|
||||
|
||||
static _Array_ptr<V> a1; // expected-error {{static variable 'a1' has a type that uses a type variable bound in an enclosing scope (type is '_Array_ptr<V>' and type variable is 'V')}} \
|
||||
// expected-note@15 {{type variable 'V' declared here}}
|
||||
|
||||
static _Array_ptr<_Array_ptr<T>> a2; // expected-error {{static variable 'a2' has a type that uses a type variable bound in an enclosing scope (type is '_Array_ptr<_Array_ptr<T>>' and type variable is 'T')}} \
|
||||
// expected-note@15 {{type variable 'T' declared here}}
|
||||
|
||||
static struct S<T, U, T> s1; // expected-error {{static variable 's1' has a type that uses a type variable bound in an enclosing scope (type is 'struct S<T, U, T>' and type variable is 'T')}} \
|
||||
// expected-note@15 {{type variable 'T' declared here}} \
|
||||
// expected-error {{static variable 's1' has a type that uses a type variable bound in an enclosing scope (type is 'struct S<T, U, T>' and type variable is 'U')}} \
|
||||
// expected-note@15 {{type variable 'U' declared here}}
|
||||
|
||||
static _Exists(T, _Ptr<U>) e1; // expected-error {{static variable 'e1' has a type that uses a type variable bound in an enclosing scope (type is 'Exists(T, _Ptr<U>)' and type variable is 'U')}} \
|
||||
// expected-note@15 {{type variable 'U' declared here}}
|
||||
|
||||
static _Exists(T, struct S<T, U, V>) e2; // expected-error {{static variable 'e2' has a type that uses a type variable bound in an enclosing scope (type is 'Exists(T, struct S<T, U, V>)' and type variable is 'U')}} \
|
||||
// expected-note@15 {{type variable 'U' declared here}} \
|
||||
// expected-error {{static variable 'e2' has a type that uses a type variable bound in an enclosing scope (type is 'Exists(T, struct S<T, U, V>)' and type variable is 'V')}} \
|
||||
// expected-note@15 {{type variable 'V' declared here}}
|
||||
|
||||
static _Exists(A, struct S<T, U, V>) e3; // expected-error {{static variable 'e3' has a type that uses a type variable bound in an enclosing scope (type is 'Exists(A, struct S<T, U, V>)' and type variable is 'T')}} \
|
||||
// expected-note@15 {{type variable 'T' declared here}} \
|
||||
// expected-error {{static variable 'e3' has a type that uses a type variable bound in an enclosing scope (type is 'Exists(A, struct S<T, U, V>)' and type variable is 'U')}} \
|
||||
// expected-note@15 {{type variable 'U' declared here}} \
|
||||
// expected-error {{static variable 'e3' has a type that uses a type variable bound in an enclosing scope (type is 'Exists(A, struct S<T, U, V>)' and type variable is 'V')}} \
|
||||
// expected-note@15 {{type variable 'V' declared here}}
|
||||
|
||||
// Static variable declarations can use integral and pointer types and bound type variables.
|
||||
static int i;
|
||||
static struct S<char, _Ptr<int>, double> s2;
|
||||
static _Exists(T, _Ptr<T>) e4;
|
||||
static _Exists(A, struct S<A, _Ptr<A>, _Array_ptr<A>>) e5;
|
||||
|
||||
// Non-static variable declarations can use free type variables.
|
||||
_Ptr<T> q = 0;
|
||||
_Array_ptr<_Array_ptr<U>> a3;
|
||||
struct S<T, U, V> s3;
|
||||
_Exists(U, _Ptr<T>) e6;
|
||||
}
|
||||
|
|
|
@ -6,15 +6,15 @@
|
|||
#include <stdchecked.h>
|
||||
|
||||
extern void f1() {
|
||||
array_ptr<int> a : count(1) = 0;
|
||||
int* _Array a _Count(1) = 0;
|
||||
int i;
|
||||
ptr<int> c = 0;
|
||||
int b[10];
|
||||
int p[10];
|
||||
|
||||
array_ptr<int> checkedc_p : bounds(checkedc_p, checkedc_p + 1) = 0;
|
||||
a = _Dynamic_bounds_cast<array_ptr<int>>(b, count(10));
|
||||
c = _Dynamic_bounds_cast<int>(p); // expected-error {{expected _Ptr or * type}}
|
||||
a = _Dynamic_bounds_cast_M(int* _Array, b, count(10));
|
||||
c = _Dynamic_bounds_cast_M_N(int ,p); // expected-error {{expected _Ptr or * type}}
|
||||
}
|
||||
|
||||
extern void f2() {
|
||||
|
@ -30,8 +30,8 @@ extern void f3() {
|
|||
char p[10];
|
||||
ptr<int> c = 0;
|
||||
array_ptr<int> a : count(2) = 0;
|
||||
a = _Assume_bounds_cast<array_ptr<int>>(p, count(p + 2)); // expected-error {{invalid argument type 'char *' to count expression}}
|
||||
c = _Assume_bounds_cast<ptr<int>>(p, count(1)); // expected-error {{expected _Array_ptr type}}
|
||||
a = _Assume_bounds_cast_M (int* _Array , p, count(p + 2)); // expected-error {{invalid argument type 'char *' to count expression}}
|
||||
c = _Assume_bounds_cast_M(int* _Single ,p, count(1)); // expected-error {{expected _Array_ptr type}}
|
||||
}
|
||||
|
||||
extern void f4() {
|
||||
|
@ -69,21 +69,21 @@ extern array_ptr<int> h4(void) : count(3) {
|
|||
|
||||
extern void f6() {
|
||||
int i[2];
|
||||
array_ptr<int> int_array_ptr_lb = i, int_array_ptr_ub = i + 1;
|
||||
ptr<int> int_ptr_lb = i, int_ptr_ub = i + 1;
|
||||
int* _Array int_array_ptr_lb = i, *_Array int_array_ptr_ub = i + 1;
|
||||
int* _Single int_ptr_lb = i, *_Single int_ptr_ub = i + 1;
|
||||
int *int_unchecked_ptr_lb = i, *int_unchecked_ptr_ub = i + 1;
|
||||
|
||||
array_ptr<char> char_array_ptr_lb = (array_ptr<char>)i,
|
||||
char_array_ptr_ub = (array_ptr<char>)i + 1;
|
||||
ptr<char> char_ptr_lb = (ptr<char>)i, char_ptr_ub = (ptr<char>)(i + 1);
|
||||
char* _Array char_array_ptr_lb = (char* _Array)i,
|
||||
*_Array char_array_ptr_ub = (char* _Array)i + 1;
|
||||
char* _Single char_ptr_lb = (char* _Single)i, *_Single char_ptr_ub = (char* _Single)(i + 1);
|
||||
char *char_unchecked_ptr_lb = (char *)i,
|
||||
*char_unchecked_ptr_ub = (char *)i + 1;
|
||||
|
||||
array_ptr<int> t20 : bounds(int_array_ptr_lb, char_array_ptr_ub) = // expected-error {{pointer type mismatch}}
|
||||
_Assume_bounds_cast<array_ptr<int>>(i, bounds(int_array_ptr_lb, char_array_ptr_ub)); // expected-error {{pointer type mismatch}}
|
||||
int* _Array t20 _Bounds(int_array_ptr_lb, char_array_ptr_ub) = // expected-error {{pointer type mismatch}}
|
||||
_Assume_bounds_cast_M(int* _Array, i, _Bounds(int_array_ptr_lb, char_array_ptr_ub)); // expected-error {{pointer type mismatch}}
|
||||
|
||||
array_ptr<int> t21 : bounds(int_ptr_lb, char_array_ptr_ub) = // expected-error {{pointer type mismatch}}
|
||||
_Assume_bounds_cast<array_ptr<int>>(i, bounds(int_ptr_lb, int_array_ptr_ub));
|
||||
int* _Array t21 _Bounds(int_ptr_lb, char_array_ptr_ub) = // expected-error {{pointer type mismatch}}
|
||||
_Assume_bounds_cast_M(int* _Array ,i, bounds(int_ptr_lb, int_array_ptr_ub));
|
||||
}
|
||||
|
||||
extern void f7(void *p) {
|
||||
|
@ -95,19 +95,19 @@ extern void f7(void *p) {
|
|||
|
||||
extern void f8() {
|
||||
int *p;
|
||||
ptr<int> q = 0;
|
||||
ptr<int> r = 0;
|
||||
ptr<int *> s = 0;
|
||||
ptr<ptr<int>> t = 0;
|
||||
r = _Assume_bounds_cast<ptr<int>>(q);
|
||||
p = _Assume_bounds_cast<int *>(q);
|
||||
r = _Dynamic_bounds_cast<ptr<int>>(q);
|
||||
p = _Dynamic_bounds_cast<int *>(q);
|
||||
s = _Assume_bounds_cast<ptr<int *>>(q);
|
||||
t = _Assume_bounds_cast<ptr<ptr<int>>>(q);
|
||||
t = _Dynamic_bounds_cast<ptr<ptr<int>>>(q);
|
||||
r = _Assume_bounds_cast<ptr<int>>(q);
|
||||
p = _Assume_bounds_cast<int *>(q);
|
||||
int* _Single q = 0;
|
||||
int* _Single r = 0;
|
||||
int* *_Single s = 0;
|
||||
int* _Single *_Single t = 0;
|
||||
r = _Dynamic_bounds_cast_M_N(int* _Single, q);
|
||||
p = _Assume_bounds_cast_M_N(int * , q);
|
||||
r = _Dynamic_bounds_cast_M_N(int* _Single , q);
|
||||
p = _Dynamic_bounds_cast_M_N(int * ,q);
|
||||
s = _Assume_bounds_cast_M_N(int * *_Single, q);
|
||||
t = _Assume_bounds_cast_M_N(int* _Single *_Single , q);
|
||||
t = _Dynamic_bounds_cast_M_N(int* _Single *_Single ,q);
|
||||
r = _Dynamic_bounds_cast_M_N(int* _Single ,q);
|
||||
p = _Assume_bounds_cast_M_N(int *,q);
|
||||
|
||||
}
|
||||
|
||||
|
@ -172,19 +172,19 @@ extern void f11() {
|
|||
q = _Dynamic_bounds_cast<ptr<int>>(rr, count(1)); // expected-error{{expected _Array_ptr type}}
|
||||
q = _Dynamic_bounds_cast<ptr<int>>(rr, bounds(rr, rr + 1)); // expected-error{{expected _Array_ptr type}}
|
||||
|
||||
p = _Dynamic_bounds_cast<int *>(q, count(1)); // expected-error {{expected _Array_ptr type}}
|
||||
q = _Dynamic_bounds_cast<ptr<int>>(q, count(1)); // expected-error {{expected _Array_ptr type}}
|
||||
q = _Dynamic_bounds_cast<ptr<int>>(i, count(1)); // expected-error {{expected _Array_ptr type}}
|
||||
p = _Dynamic_bounds_cast<int *>(i, count(1)); // expected-error {{expected _Array_ptr type}}
|
||||
q = _Dynamic_bounds_cast<ptr<int>>(i, bounds(i, i + 1)); // expected-error 2 {{expected expression with pointer type}}
|
||||
p = _Dynamic_bounds_cast<int *>(i, bounds(i, i + 1)); // expected-error 2 {{expected expression with pointer type}}
|
||||
p = _Dynamic_bounds_cast_M(int *, q, count(1)); // expected-error {{expected _Array_ptr type}}
|
||||
q = _Dynamic_bounds_cast_M(int* _Single, q, count(1)); // expected-error {{expected _Array_ptr type}}
|
||||
q = _Dynamic_bounds_cast_M(int* _Single, i, count(1)); // expected-error {{expected _Array_ptr type}}
|
||||
p = _Dynamic_bounds_cast_M(int *, i, count(1)); // expected-error {{expected _Array_ptr type}}
|
||||
q = _Dynamic_bounds_cast_M(int* _Single, i, bounds(i, i + 1)); // expected-error 2 {{expected expression with pointer type}}
|
||||
p = _Dynamic_bounds_cast_M(int *, i, bounds(i, i + 1)); // expected-error 2 {{expected expression with pointer type}}
|
||||
|
||||
q = _Dynamic_bounds_cast<ptr<int>>(p, count(1)); // expected-error {{expected _Array_ptr type}}
|
||||
p = _Dynamic_bounds_cast<int *>(p, count(1)); // expected-error {{expected _Array_ptr type}}
|
||||
q = _Dynamic_bounds_cast<ptr<int>>(p, bounds(p, p + 1)); // expected-error {{expected _Array_ptr type}}
|
||||
p = _Dynamic_bounds_cast<int *>(p, bounds(p, p + 1)); // expected-error {{expected _Array_ptr type}}
|
||||
|
||||
q = _Assume_bounds_cast<ptr<int>>(r, count(1)) + 3; // expected-error{{expected _Array_ptr type}}
|
||||
c = _Dynamic_bounds_cast<ptr<int>>(p, count(4)); // expected-error{{expected _Array_ptr type}}
|
||||
q = _Dynamic_bounds_cast_M(int* _Single, p, count(1)); // expected-error {{expected _Array_ptr type}}
|
||||
p = _Dynamic_bounds_cast_M(int *, p, count(1)); // expected-error {{expected _Array_ptr type}}
|
||||
q = _Dynamic_bounds_cast_M(int* _Single, p, bounds(p, p + 1)); // expected-error {{expected _Array_ptr type}}
|
||||
p = _Dynamic_bounds_cast_M(int *, p, bounds(p, p + 1)); // expected-error {{expected _Array_ptr type}}
|
||||
|
||||
q = _Dynamic_bounds_cast_M(int* _Single, r, count(1)) + 3; // expected-error{{expected _Array_ptr type}}
|
||||
c = _Dynamic_bounds_cast_M(int* _Single, p, count(4)); // expected-error{{expected _Array_ptr type}}
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче