Skip to content

Commit 5441b40

Browse files
authored
Add use of Clang __attribute__((nonnull)) in Emscripten system headers. (#16545)
* Add use of Clang __attribute__((nonnull)) in Emscripten system headers. * Fix annotation on emscripten_futex_wake * Remove nonnull on emscripten_fetch_wait * Fix annotation and tests * Add use of _Nonnull attribute * Fix test * Break up long lines in webgl2_ext.h * Add notes about null pointers in emmalloc.h
1 parent 97cb6d9 commit 5441b40

21 files changed

+352
-271
lines changed

system/include/emscripten/atomic.h

Lines changed: 40 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -19,63 +19,63 @@ extern "C" {
1919

2020
// Atomically stores the given value to the memory location, and returns the
2121
// value that was there prior to the store.
22-
uint8_t emscripten_atomic_exchange_u8(void/*uint8_t*/ *addr, uint8_t newVal);
23-
uint16_t emscripten_atomic_exchange_u16(void/*uint16_t*/ *addr, uint16_t newVal);
24-
uint32_t emscripten_atomic_exchange_u32(void/*uint32_t*/ *addr, uint32_t newVal);
25-
uint64_t emscripten_atomic_exchange_u64(void/*uint64_t*/ *addr, uint64_t newVal);
22+
uint8_t emscripten_atomic_exchange_u8(void/*uint8_t*/ *addr __attribute__((nonnull)), uint8_t newVal);
23+
uint16_t emscripten_atomic_exchange_u16(void/*uint16_t*/ *addr __attribute__((nonnull)), uint16_t newVal);
24+
uint32_t emscripten_atomic_exchange_u32(void/*uint32_t*/ *addr __attribute__((nonnull)), uint32_t newVal);
25+
uint64_t emscripten_atomic_exchange_u64(void/*uint64_t*/ *addr __attribute__((nonnull)), uint64_t newVal);
2626

2727
// CAS returns the *old* value that was in the memory location before the
2828
// operation took place.
2929
// That is, if the return value when calling this function equals to 'oldVal',
3030
// then the operation succeeded, otherwise it was ignored.
31-
uint8_t emscripten_atomic_cas_u8(void/*uint8_t*/ *addr, uint8_t oldVal, uint8_t newVal);
32-
uint16_t emscripten_atomic_cas_u16(void/*uint16_t*/ *addr, uint16_t oldVal, uint16_t newVal);
33-
uint32_t emscripten_atomic_cas_u32(void/*uint32_t*/ *addr, uint32_t oldVal, uint32_t newVal);
34-
uint64_t emscripten_atomic_cas_u64(void/*uint64_t*/ *addr, uint64_t oldVal, uint64_t newVal);
31+
uint8_t emscripten_atomic_cas_u8(void/*uint8_t*/ *addr __attribute__((nonnull)), uint8_t oldVal, uint8_t newVal);
32+
uint16_t emscripten_atomic_cas_u16(void/*uint16_t*/ *addr __attribute__((nonnull)), uint16_t oldVal, uint16_t newVal);
33+
uint32_t emscripten_atomic_cas_u32(void/*uint32_t*/ *addr __attribute__((nonnull)), uint32_t oldVal, uint32_t newVal);
34+
uint64_t emscripten_atomic_cas_u64(void/*uint64_t*/ *addr __attribute__((nonnull)), uint64_t oldVal, uint64_t newVal);
3535

36-
uint8_t emscripten_atomic_load_u8(const void/*uint8_t*/ *addr);
37-
uint16_t emscripten_atomic_load_u16(const void/*uint16_t*/ *addr);
38-
uint32_t emscripten_atomic_load_u32(const void/*uint32_t*/ *addr);
39-
float emscripten_atomic_load_f32(const void/*float*/ *addr);
40-
uint64_t emscripten_atomic_load_u64(const void/*uint64_t*/ *addr);
41-
double emscripten_atomic_load_f64(const void/*double*/ *addr);
36+
uint8_t emscripten_atomic_load_u8(const void/*uint8_t*/ *addr __attribute__((nonnull)));
37+
uint16_t emscripten_atomic_load_u16(const void/*uint16_t*/ *addr __attribute__((nonnull)));
38+
uint32_t emscripten_atomic_load_u32(const void/*uint32_t*/ *addr __attribute__((nonnull)));
39+
float emscripten_atomic_load_f32(const void/*float*/ *addr __attribute__((nonnull)));
40+
uint64_t emscripten_atomic_load_u64(const void/*uint64_t*/ *addr __attribute__((nonnull)));
41+
double emscripten_atomic_load_f64(const void/*double*/ *addr __attribute__((nonnull)));
4242

4343
// Returns the value that was stored (i.e. 'val')
44-
uint8_t emscripten_atomic_store_u8(void/*uint8_t*/ *addr, uint8_t val);
45-
uint16_t emscripten_atomic_store_u16(void/*uint16_t*/ *addr, uint16_t val);
46-
uint32_t emscripten_atomic_store_u32(void/*uint32_t*/ *addr, uint32_t val);
47-
float emscripten_atomic_store_f32(void/*float*/ *addr, float val);
48-
uint64_t emscripten_atomic_store_u64(void/*uint64_t*/ *addr, uint64_t val);
49-
double emscripten_atomic_store_f64(void/*double*/ *addr, double val);
44+
uint8_t emscripten_atomic_store_u8(void/*uint8_t*/ *addr __attribute__((nonnull)), uint8_t val);
45+
uint16_t emscripten_atomic_store_u16(void/*uint16_t*/ *addr __attribute__((nonnull)), uint16_t val);
46+
uint32_t emscripten_atomic_store_u32(void/*uint32_t*/ *addr __attribute__((nonnull)), uint32_t val);
47+
float emscripten_atomic_store_f32(void/*float*/ *addr __attribute__((nonnull)), float val);
48+
uint64_t emscripten_atomic_store_u64(void/*uint64_t*/ *addr __attribute__((nonnull)), uint64_t val);
49+
double emscripten_atomic_store_f64(void/*double*/ *addr __attribute__((nonnull)), double val);
5050

5151
void emscripten_atomic_fence(void);
5252

5353
// Each of the functions below (add, sub, and, or, xor) return the value that
5454
// was in the memory location before the operation occurred.
55-
uint8_t emscripten_atomic_add_u8(void/*uint8_t*/ *addr, uint8_t val);
56-
uint16_t emscripten_atomic_add_u16(void/*uint16_t*/ *addr, uint16_t val);
57-
uint32_t emscripten_atomic_add_u32(void/*uint32_t*/ *addr, uint32_t val);
58-
uint64_t emscripten_atomic_add_u64(void/*uint64_t*/ *addr, uint64_t val);
55+
uint8_t emscripten_atomic_add_u8(void/*uint8_t*/ *addr __attribute__((nonnull)), uint8_t val);
56+
uint16_t emscripten_atomic_add_u16(void/*uint16_t*/ *addr __attribute__((nonnull)), uint16_t val);
57+
uint32_t emscripten_atomic_add_u32(void/*uint32_t*/ *addr __attribute__((nonnull)), uint32_t val);
58+
uint64_t emscripten_atomic_add_u64(void/*uint64_t*/ *addr __attribute__((nonnull)), uint64_t val);
5959

60-
uint8_t emscripten_atomic_sub_u8(void/*uint8_t*/ *addr, uint8_t val);
61-
uint16_t emscripten_atomic_sub_u16(void/*uint16_t*/ *addr, uint16_t val);
62-
uint32_t emscripten_atomic_sub_u32(void/*uint32_t*/ *addr, uint32_t val);
63-
uint64_t emscripten_atomic_sub_u64(void/*uint64_t*/ *addr, uint64_t val);
60+
uint8_t emscripten_atomic_sub_u8(void/*uint8_t*/ *addr __attribute__((nonnull)), uint8_t val);
61+
uint16_t emscripten_atomic_sub_u16(void/*uint16_t*/ *addr __attribute__((nonnull)), uint16_t val);
62+
uint32_t emscripten_atomic_sub_u32(void/*uint32_t*/ *addr __attribute__((nonnull)), uint32_t val);
63+
uint64_t emscripten_atomic_sub_u64(void/*uint64_t*/ *addr __attribute__((nonnull)), uint64_t val);
6464

65-
uint8_t emscripten_atomic_and_u8(void/*uint8_t*/ *addr, uint8_t val);
66-
uint16_t emscripten_atomic_and_u16(void/*uint16_t*/ *addr, uint16_t val);
67-
uint32_t emscripten_atomic_and_u32(void/*uint32_t*/ *addr, uint32_t val);
68-
uint64_t emscripten_atomic_and_u64(void/*uint64_t*/ *addr, uint64_t val);
65+
uint8_t emscripten_atomic_and_u8(void/*uint8_t*/ *addr __attribute__((nonnull)), uint8_t val);
66+
uint16_t emscripten_atomic_and_u16(void/*uint16_t*/ *addr __attribute__((nonnull)), uint16_t val);
67+
uint32_t emscripten_atomic_and_u32(void/*uint32_t*/ *addr __attribute__((nonnull)), uint32_t val);
68+
uint64_t emscripten_atomic_and_u64(void/*uint64_t*/ *addr __attribute__((nonnull)), uint64_t val);
6969

70-
uint8_t emscripten_atomic_or_u8(void/*uint8_t*/ *addr, uint8_t val);
71-
uint16_t emscripten_atomic_or_u16(void/*uint16_t*/ *addr, uint16_t val);
72-
uint32_t emscripten_atomic_or_u32(void/*uint32_t*/ *addr, uint32_t val);
73-
uint64_t emscripten_atomic_or_u64(void/*uint64_t*/ *addr, uint64_t val);
70+
uint8_t emscripten_atomic_or_u8(void/*uint8_t*/ *addr __attribute__((nonnull)), uint8_t val);
71+
uint16_t emscripten_atomic_or_u16(void/*uint16_t*/ *addr __attribute__((nonnull)), uint16_t val);
72+
uint32_t emscripten_atomic_or_u32(void/*uint32_t*/ *addr __attribute__((nonnull)), uint32_t val);
73+
uint64_t emscripten_atomic_or_u64(void/*uint64_t*/ *addr __attribute__((nonnull)), uint64_t val);
7474

75-
uint8_t emscripten_atomic_xor_u8(void/*uint8_t*/ *addr, uint8_t val);
76-
uint16_t emscripten_atomic_xor_u16(void/*uint16_t*/ *addr, uint16_t val);
77-
uint32_t emscripten_atomic_xor_u32(void/*uint32_t*/ *addr, uint32_t val);
78-
uint64_t emscripten_atomic_xor_u64(void/*uint64_t*/ *addr, uint64_t val);
75+
uint8_t emscripten_atomic_xor_u8(void/*uint8_t*/ *addr __attribute__((nonnull)), uint8_t val);
76+
uint16_t emscripten_atomic_xor_u16(void/*uint16_t*/ *addr __attribute__((nonnull)), uint16_t val);
77+
uint32_t emscripten_atomic_xor_u32(void/*uint32_t*/ *addr __attribute__((nonnull)), uint32_t val);
78+
uint64_t emscripten_atomic_xor_u64(void/*uint64_t*/ *addr __attribute__((nonnull)), uint64_t val);
7979

8080
#ifdef __cplusplus
8181
}

system/include/emscripten/console.h

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ extern "C" {
1111

1212
// Write directly JavaScript console. This can be useful for debugging since it
1313
// bypasses the stdio and filesystem sub-systems.
14-
void emscripten_console_log(const char *utf8String);
15-
void emscripten_console_warn(const char *utf8String);
16-
void emscripten_console_error(const char *utf8String);
14+
void emscripten_console_log(const char *utf8String __attribute__((nonnull)));
15+
void emscripten_console_warn(const char *utf8String __attribute__((nonnull)));
16+
void emscripten_console_error(const char *utf8String __attribute__((nonnull)));
1717

1818
// Write to the out() and err() hooks directly (defined in shell.js).
1919
// These have different behavior compared to console.log/err.
@@ -23,16 +23,16 @@ void emscripten_console_error(const char *utf8String);
2323
// printErr, if provided on the Module object.
2424
// These functions are mainly intended for internal use.
2525
// See https://github.com/emscripten-core/emscripten/issues/14804
26-
void _emscripten_out(const char *utf8String);
27-
void _emscripten_err(const char *utf8String);
26+
void _emscripten_out(const char *utf8String __attribute__((nonnull)));
27+
void _emscripten_err(const char *utf8String __attribute__((nonnull)));
2828
void _emscripten_dbg(const char *utf8String);
2929

3030
// Similar to the above functions but operate with printf-like semantics.
31-
void emscripten_console_logf(const char *utf8String, ...) __attribute__((__format__(printf, 1, 2)));
32-
void emscripten_console_warnf(const char *utf8String, ...) __attribute__((__format__(printf, 1, 2)));
33-
void emscripten_console_errorf(const char *utf8String, ...)__attribute__((__format__(printf, 1, 2)));
34-
void _emscripten_outf(const char *utf8String, ...) __attribute__((__format__(printf, 1, 2)));
35-
void _emscripten_errf(const char *utf8String, ...) __attribute__((__format__(printf, 1, 2)));
31+
void emscripten_console_logf(const char *utf8String __attribute__((nonnull)), ...) __attribute__((__format__(printf, 1, 2)));
32+
void emscripten_console_warnf(const char *utf8String __attribute__((nonnull)), ...) __attribute__((__format__(printf, 1, 2)));
33+
void emscripten_console_errorf(const char *utf8String __attribute__((nonnull)), ...)__attribute__((__format__(printf, 1, 2)));
34+
void _emscripten_outf(const char *utf8String __attribute__((nonnull)), ...) __attribute__((__format__(printf, 1, 2)));
35+
void _emscripten_errf(const char *utf8String __attribute__((nonnull)), ...) __attribute__((__format__(printf, 1, 2)));
3636
void _emscripten_dbgf(const char *utf8String, ...) __attribute__((__format__(printf, 1, 2)));
3737

3838
#ifdef __cplusplus

system/include/emscripten/emmalloc.h

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,34 +13,39 @@ extern "C" {
1313
// *extremely slow*, use for debugging allocation test cases.
1414
void emmalloc_dump_memory_regions(void);
1515

16-
// Allocates size bytes with the given pow-2 alignment.
16+
// Allocates size bytes with the given pow-2 alignment. If the WebAssembly memory runs out of
17+
// free bytes, this function will abort execution, or if building with -sABORTING_MALLOC=0,
18+
// return a null pointer.
1719
void *memalign(size_t alignment, size_t size);
1820
void *emmalloc_memalign(size_t alignment, size_t size);
1921
void *aligned_alloc(size_t alignment, size_t size);
2022

21-
// Allocates size bytes with default alignment (8 bytes)
23+
// Allocates size bytes with default alignment (8 bytes). Like above, either aborts or returns
24+
// null on OOM.
2225
void *malloc(size_t size);
2326
void *emmalloc_malloc(size_t size);
2427

2528
// Returns the number of bytes that are actually allocated to the given pointer ptr.
2629
// E.g. due to alignment or size requirements, the actual size of the allocation can be
27-
// larger than what was requested.
30+
// larger than what was requested. It is ok to pass a null pointer to these functions, in which
31+
// case 0 will be returned.
2832
size_t malloc_usable_size(void *ptr);
2933
size_t emmalloc_usable_size(void *ptr);
3034

3135
// Frees a memory pointer allocated with any of the memory allocation functions declared
3236
// in this file, e.g.
3337
// (emmalloc_)memalign, (emmalloc_)malloc, (emmalloc_)calloc, aligned_alloc,
3438
// (emmalloc_)realloc, emmalloc_realloc_try, emmalloc_realloc_uninitialized, (emmalloc_)aligned_realloc
39+
// It is ok to pass null in ptr, which will be a no-op.
3540
void free(void *ptr);
3641
void emmalloc_free(void *ptr);
3742

3843
// Performs a reallocation of the given memory pointer to a new size. If the memory region
3944
// pointed by ptr cannot be resized in place, a new memory region will be allocated, old
4045
// memory copied over, and the old memory area freed. The pointer ptr must have been
4146
// allocated with one of the emmalloc memory allocation functions (malloc, memalign, ...).
42-
// If called with size == 0, the pointer ptr is freed, and a null pointer is returned. If
43-
// called with null ptr, a new pointer is allocated.
47+
// If called with size == 0, the pointer ptr is freed, and a null pointer is returned.
48+
// If called with null ptr, a new pointer is allocated.
4449
// If there is not enough memory, the old memory block is not freed and null pointer is
4550
// returned.
4651
void *realloc(void *ptr, size_t size);

system/include/emscripten/emscripten.h

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,11 @@
3232
extern "C" {
3333
#endif
3434

35-
void emscripten_run_script(const char *script);
36-
int emscripten_run_script_int(const char *script);
37-
char *emscripten_run_script_string(const char *script);
38-
void emscripten_async_run_script(const char *script, int millis);
39-
void emscripten_async_load_script(const char *script, em_callback_func onload, em_callback_func onerror);
35+
void emscripten_run_script(const char *script __attribute__((nonnull)));
36+
int emscripten_run_script_int(const char *script __attribute__((nonnull)));
37+
char *emscripten_run_script_string(const char *script __attribute__((nonnull)));
38+
void emscripten_async_run_script(const char *script __attribute__((nonnull)), int millis);
39+
void emscripten_async_load_script(const char *script __attribute__((nonnull)), em_callback_func onload, em_callback_func onerror);
4040

4141
void emscripten_set_main_loop(em_callback_func func, int fps, int simulate_infinite_loop);
4242

@@ -45,7 +45,7 @@ void emscripten_set_main_loop(em_callback_func func, int fps, int simulate_infin
4545
#define EM_TIMING_SETIMMEDIATE 2
4646

4747
int emscripten_set_main_loop_timing(int mode, int value);
48-
void emscripten_get_main_loop_timing(int *mode, int *value);
48+
void emscripten_get_main_loop_timing(int *mode, int *value); // Pass a null pointer to skip receiving that particular value
4949
void emscripten_set_main_loop_arg(em_arg_callback_func func, void *arg, int fps, int simulate_infinite_loop);
5050
void emscripten_pause_main_loop(void);
5151
void emscripten_resume_main_loop(void);
@@ -79,22 +79,22 @@ double emscripten_get_device_pixel_ratio(void);
7979

8080
char *emscripten_get_window_title();
8181
void emscripten_set_window_title(const char *);
82-
void emscripten_get_screen_size(int *width, int *height);
82+
void emscripten_get_screen_size(int *width __attribute__((nonnull)), int *height __attribute__((nonnull)));
8383
void emscripten_hide_mouse(void);
8484
void emscripten_set_canvas_size(int width, int height) __attribute__((deprecated("This variant does not allow specifying the target canvas", "Use emscripten_set_canvas_element_size() instead")));
85-
void emscripten_get_canvas_size(int *width, int *height, int *isFullscreen) __attribute__((deprecated("This variant does not allow specifying the target canvas", "Use emscripten_get_canvas_element_size() and emscripten_get_fullscreen_status() instead")));
85+
void emscripten_get_canvas_size(int *width __attribute__((nonnull)), int *height __attribute__((nonnull)), int *isFullscreen __attribute__((nonnull))) __attribute__((deprecated("This variant does not allow specifying the target canvas", "Use emscripten_get_canvas_element_size() and emscripten_get_fullscreen_status() instead")));
8686

8787
double emscripten_get_now(void);
8888
float emscripten_random(void);
8989

9090
// IDB
9191

9292
typedef void (*em_idb_onload_func)(void*, void*, int);
93-
void emscripten_idb_async_load(const char *db_name, const char *file_id, void* arg, em_idb_onload_func onload, em_arg_callback_func onerror);
94-
void emscripten_idb_async_store(const char *db_name, const char *file_id, void* ptr, int num, void* arg, em_arg_callback_func onstore, em_arg_callback_func onerror);
95-
void emscripten_idb_async_delete(const char *db_name, const char *file_id, void* arg, em_arg_callback_func ondelete, em_arg_callback_func onerror);
93+
void emscripten_idb_async_load(const char *db_name __attribute__((nonnull)), const char *file_id __attribute__((nonnull)), void* arg, em_idb_onload_func onload, em_arg_callback_func onerror);
94+
void emscripten_idb_async_store(const char *db_name __attribute__((nonnull)), const char *file_id __attribute__((nonnull)), void* ptr, int num, void* arg, em_arg_callback_func onstore, em_arg_callback_func onerror);
95+
void emscripten_idb_async_delete(const char *db_name __attribute__((nonnull)), const char *file_id __attribute__((nonnull)), void* arg, em_arg_callback_func ondelete, em_arg_callback_func onerror);
9696
typedef void (*em_idb_exists_func)(void*, int);
97-
void emscripten_idb_async_exists(const char *db_name, const char *file_id, void* arg, em_idb_exists_func oncheck, em_arg_callback_func onerror);
97+
void emscripten_idb_async_exists(const char *db_name __attribute__((nonnull)), const char *file_id __attribute__((nonnull)), void* arg, em_idb_exists_func oncheck, em_arg_callback_func onerror);
9898

9999
// IDB "sync"
100100

system/include/emscripten/eventloop.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,15 @@ extern "C" {
1515

1616
void emscripten_unwind_to_js_event_loop(void) __attribute__((__noreturn__));
1717

18-
int emscripten_set_timeout(void (*cb)(void *user_data), double msecs, void *user_data);
18+
int emscripten_set_timeout(void (*cb)(void *user_data) __attribute__((nonnull)), double msecs, void *user_data);
1919
void emscripten_clear_timeout(int id);
20-
void emscripten_set_timeout_loop(EM_BOOL (*cb)(double time, void *user_data), double interval_ms, void *user_data);
20+
void emscripten_set_timeout_loop(EM_BOOL (*cb)(double time, void *user_data) __attribute__((nonnull)), double interval_ms, void *user_data);
2121

22-
int emscripten_set_immediate(void (*cb)(void *user_data), void *user_data);
22+
int emscripten_set_immediate(void (*cb)(void *user_data) __attribute__((nonnull)), void *user_data);
2323
void emscripten_clear_immediate(int id);
2424
void emscripten_set_immediate_loop(EM_BOOL (*cb)(void *user_data), void *user_data);
2525

26-
int emscripten_set_interval(void (*cb)(void *user_data), double interval_ms, void *user_data);
26+
int emscripten_set_interval(void (*cb)(void *user_data) __attribute__((nonnull)), double interval_ms, void *user_data);
2727
void emscripten_clear_interval(int id);
2828

2929
void emscripten_runtime_keepalive_push();

system/include/emscripten/exports.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ extern "C" {
1616

1717
// Returns a function pointer to the given exported function by name. Cast the returned pointer
1818
// to its proper signature before calling the function.
19-
void *emscripten_get_exported_function(const char *fname);
19+
void *emscripten_get_exported_function(const char *fname __attribute__((nonnull)));
2020

2121
#ifdef __cplusplus
2222
}

0 commit comments

Comments
 (0)