From: Bart Van Assche <bvanassche@acm.org>
To: linux-sparse@vger.kernel.org
Cc: Linus Torvalds <torvalds@linux-foundation.org>,
Bart Van Assche <bvanassche@acm.org>
Subject: [PATCH 55/73] preprocessor: Add support for __has_embed
Date: Mon, 9 Nov 2026 12:32:41 -0800 [thread overview]
Message-ID: <20261109203259.362845-56-bvanassche@acm.org> (raw)
In-Reply-To: <20261109203259.362845-1-bvanassche@acm.org>
Add support for the C23 __has_embed preprocessor operator to check resource
availability and parameters prior to inclusion via #embed. Predefine the
__STDC_EMBED_NOT_FOUND__, __STDC_EMBED_FOUND__, and __STDC_EMBED_EMPTY__
constants to allow portable feature detection in preprocessor expressions.
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
ident-list.h | 9 +
pre-process.c | 445 +++++++++++++++++++++++-
predefine.c | 3 +
validation/preprocessor/c23-has-embed.c | 69 ++++
4 files changed, 522 insertions(+), 4 deletions(-)
create mode 100644 validation/preprocessor/c23-has-embed.c
diff --git a/ident-list.h b/ident-list.h
index bc5df947913a..f51f2048f5ca 100644
--- a/ident-list.h
+++ b/ident-list.h
@@ -84,6 +84,15 @@ __IDENT(__FUNCTION___ident, "__FUNCTION__", 0);
__IDENT(__PRETTY_FUNCTION___ident, "__PRETTY_FUNCTION__", 0);
__IDENT(__has_include_ident, "__has_include", 0);
__IDENT(__has_include_next_ident, "__has_include_next", 0);
+__IDENT(__has_embed_ident, "__has_embed", 0);
+IDENT(limit);
+IDENT(prefix);
+IDENT(suffix);
+IDENT(if_empty);
+__IDENT(__limit___ident, "__limit__", 0);
+__IDENT(__prefix___ident, "__prefix__", 0);
+__IDENT(__suffix___ident, "__suffix__", 0);
+__IDENT(__if_empty___ident, "__if_empty__", 0);
/* Sparse commands */
IDENT_RESERVED(__context__);
diff --git a/pre-process.c b/pre-process.c
index aac194cf4c01..e8b3511c225e 100644
--- a/pre-process.c
+++ b/pre-process.c
@@ -764,6 +764,7 @@ static struct token **substitute(struct token **list, const struct token *body,
}
static bool parse_has_include(struct token **list, int how);
+static bool parse_has_embed(struct token **list);
static void reject_outside_directive(struct token *token)
{
@@ -805,7 +806,8 @@ static int expand(struct token **list, struct symbol *sym)
}
if (expanding == &__has_include_ident ||
- expanding == &__has_include_next_ident) {
+ expanding == &__has_include_next_ident ||
+ expanding == &__has_embed_ident) {
bool ok;
if (!in_cond_expr) {
@@ -814,8 +816,10 @@ static int expand(struct token **list, struct symbol *sym)
}
if (expanding == &__has_include_ident)
ok = parse_has_include(list, 0);
- else
+ else if (expanding == &__has_include_next_ident)
ok = parse_has_include(list, 1);
+ else
+ ok = parse_has_embed(list);
if (!ok)
replace_with_bool(token, 0);
return 0;
@@ -1099,7 +1103,7 @@ static bool collect_angle_filename(struct token **next_p, char *buf,
struct token *t = *next_p;
char *ptr = buf;
- while (!eof_token(t) && !match_op(t, '>')) {
+ while (!eof_token(t = scan_next(&t)) && !match_op(t, '>')) {
const char *s = (token_type(t) == TOKEN_STRING) ?
t->string->data :
show_token(t);
@@ -1123,7 +1127,7 @@ static bool collect_angle_filename(struct token **next_p, char *buf,
sparse_error(pos, "empty filename");
return false;
}
- *next_p = t->next;
+ *next_p = scan_next(&t->next);
return true;
}
@@ -1231,6 +1235,432 @@ err:
return false;
}
+static void replace_with_int(struct token *token, int val)
+{
+ static const char *const digits[] = { "0", "1", "2" };
+ token_type(token) = TOKEN_NUMBER;
+ token->number = (val >= 0 && val <= 2) ? digits[val] : "0";
+}
+
+#define MAX_EMBED_SIZE (16 * 1024 * 1024)
+
+enum embed_param_kind {
+ EMBED_PARAM_NONE = 0,
+ EMBED_PARAM_LIMIT = 1 << 0,
+ EMBED_PARAM_PREFIX = 1 << 1,
+ EMBED_PARAM_SUFFIX = 1 << 2,
+ EMBED_PARAM_IF_EMPTY = 1 << 3,
+};
+
+static enum embed_param_kind classify_embed_param(struct ident *id)
+{
+ if (id == &limit_ident || id == &__limit___ident)
+ return EMBED_PARAM_LIMIT;
+ if (id == &prefix_ident || id == &__prefix___ident)
+ return EMBED_PARAM_PREFIX;
+ if (id == &suffix_ident || id == &__suffix___ident)
+ return EMBED_PARAM_SUFFIX;
+ if (id == &if_empty_ident || id == &__if_empty___ident)
+ return EMBED_PARAM_IF_EMPTY;
+ return EMBED_PARAM_NONE;
+}
+
+static struct token *dup_token_range(struct token *start, struct token *end)
+{
+ struct token *head = &eof_token_entry;
+ struct token **tail = &head;
+ struct token *p;
+
+ if (!start || !end)
+ return &eof_token_entry;
+ for (p = start;; p = p->next) {
+ struct token *t = __alloc_token(0);
+ *t = *p;
+ *tail = t;
+ tail = &t->next;
+ if (p == end)
+ break;
+ }
+ *tail = &eof_token_entry;
+ return head;
+}
+
+static bool eval_embed_limit_expr(struct position pos, struct token *pstart,
+ struct token *pend,
+ unsigned long long *limit_val)
+{
+ struct token *copy = dup_token_range(pstart, pend);
+ struct expression *expr = NULL;
+ long long sval;
+
+ if (eof_token(copy)) {
+ sparse_error(pos, "expected expression in #embed limit");
+ return false;
+ }
+ in_cond_expr++;
+ expand_list(©);
+ for (struct token *t = copy; !eof_token(t); t = t->next) {
+ if (token_type(t) != TOKEN_IDENT)
+ continue;
+ if (standard >= STANDARD_C23 && t->ident == &true_ident) {
+ replace_with_bool(t, 1);
+ } else if (standard >= STANDARD_C23 &&
+ t->ident == &false_ident) {
+ replace_with_bool(t, 0);
+ } else if (t->ident == &defined_ident) {
+ in_cond_expr--;
+ sparse_error(t->pos,
+ "'defined' cannot appear in #embed limit");
+ return false;
+ } else {
+ token_type(t) = TOKEN_ZERO_IDENT;
+ }
+ }
+ in_cond_expr--;
+ copy = constant_expression(copy, &expr);
+ if (!expr || !eof_token(copy)) {
+ sparse_error(pos, "invalid #embed limit");
+ return false;
+ }
+ sval = get_expression_value(expr);
+ if (!expr->ctype || expr->type != EXPR_VALUE)
+ return false;
+ if (sval < 0 && !(expr->ctype->ctype.modifiers & MOD_UNSIGNED)) {
+ sparse_error(expr->pos, "negative #embed limit");
+ return false;
+ }
+ *limit_val = (unsigned long long)sval;
+ return true;
+}
+
+static int test_embed_file(const char *path, const char *filename,
+ int has_limit, unsigned long long limit_val,
+ unsigned long long *size)
+{
+ int fd;
+ struct stat st;
+ size_t plen = strlen(path);
+ size_t flen = strlen(filename);
+ char fullname[PATH_MAX];
+
+ if (plen + flen + 2 > sizeof(fullname))
+ return 0;
+ memcpy(fullname, path, plen);
+ if (plen && path[plen - 1] != '/') {
+ fullname[plen] = '/';
+ plen++;
+ }
+ memcpy(fullname + plen, filename, flen + 1);
+ fd = open(fullname, O_RDONLY | O_NONBLOCK);
+ if (fd < 0)
+ return 0;
+ if (fstat(fd, &st) < 0 || S_ISDIR(st.st_mode)) {
+ close(fd);
+ return 0;
+ }
+ if (S_ISREG(st.st_mode)) {
+ unsigned long long eff = st.st_size;
+
+ close(fd);
+ if (has_limit && limit_val < eff)
+ eff = limit_val;
+ if (eff > MAX_EMBED_SIZE)
+ return 0;
+ *size = eff;
+ return 1;
+ }
+ if (S_ISCHR(st.st_mode)) {
+ unsigned char b;
+ ssize_t r;
+
+ if (has_limit && limit_val == 0) {
+ close(fd);
+ *size = 0;
+ return 1;
+ }
+ if (has_limit && limit_val > MAX_EMBED_SIZE) {
+ close(fd);
+ return 0;
+ }
+ r = read(fd, &b, 1);
+ close(fd);
+ if (r == 0) {
+ *size = 0;
+ return 1;
+ }
+ if (r > 0 && has_limit) {
+ *size = 1;
+ return 1;
+ }
+ return 0;
+ }
+ close(fd);
+ return 0;
+}
+
+static int check_has_embed(struct stream *stream, const char *filename,
+ int expect, int has_limit,
+ unsigned long long limit_val,
+ unsigned long long *size)
+{
+ const char **path;
+
+ /* Absolute path? */
+ if (filename[0] == '/')
+ return test_embed_file("", filename, has_limit, limit_val,
+ size);
+
+ set_stream_include_path(stream);
+ path = expect ? angle_includepath : quote_includepath;
+ if (!path)
+ return 0;
+ while (*path != NULL) {
+ if (test_embed_file(*path++, filename, has_limit, limit_val,
+ size))
+ return 1;
+ }
+ return 0;
+}
+
+static bool parse_has_embed(struct token **list)
+{
+ struct token *token = *list;
+ struct token *lparen = scan_next(&token->next);
+ struct token *next;
+ struct token *params, **param_p, *rparen, *after_rparen;
+ struct stream *stream = input_streams + token->pos.stream;
+ char filename[PATH_MAX];
+ int expect = 0;
+ int val = 0;
+ unsigned long long filesize = 0;
+ int has_limit = 0;
+ unsigned long long limit_val = ~0ULL;
+ unsigned int seen_params = 0;
+ int supported = 1;
+
+ if (!match_op(lparen, '(')) {
+ sparse_error(token->pos, "expected '(' after %s",
+ show_token(token));
+ return false;
+ }
+ next = scan_next(&lparen->next);
+ if (match_op(next, '<')) {
+ expect = '>';
+ next = next->next;
+ if (!collect_angle_filename(&next, filename, sizeof(filename),
+ token->pos))
+ goto err;
+ } else if (token_type(next) == TOKEN_STRING) {
+ if (!extract_string_filename(&next, filename, sizeof(filename)))
+ goto err;
+ } else {
+ struct token **p = &lparen->next;
+ int depth = 1;
+
+ rparen = scan_next(p);
+ while (!eof_token(rparen)) {
+ if (match_op(rparen, '('))
+ depth++;
+ else if (match_op(rparen, ')') && !--depth)
+ break;
+ p = &rparen->next;
+ rparen = scan_next(p);
+ }
+ if (!match_op(rparen, ')')) {
+ sparse_error(rparen->pos, "expected ')'");
+ token->next = rparen;
+ return false;
+ }
+ *p = &eof_token_entry;
+ expand_list(&lparen->next);
+ p = &lparen->next;
+ while (!eof_token(*p))
+ p = &(*p)->next;
+ *p = rparen;
+ next = lparen->next;
+ if (match_op(next, '<')) {
+ expect = '>';
+ next = next->next;
+ if (!collect_angle_filename(&next, filename,
+ sizeof(filename),
+ token->pos))
+ goto err;
+ } else if (token_type(next) == TOKEN_STRING) {
+ if (!extract_string_filename(&next, filename,
+ sizeof(filename)))
+ goto err;
+ } else {
+ sparse_error(next->pos,
+ "expected \"FILENAME\" or <FILENAME>");
+ goto err;
+ }
+ }
+
+ /* Isolate optional parameters before matching ')' */
+ params = next;
+ {
+ struct token **p = ¶ms;
+ int depth = 1;
+
+ rparen = scan_next(p);
+ while (!eof_token(rparen)) {
+ if (match_op(rparen, '('))
+ depth++;
+ else if (match_op(rparen, ')') && !--depth)
+ break;
+ p = &rparen->next;
+ rparen = scan_next(p);
+ }
+ if (!match_op(rparen, ')')) {
+ sparse_error(rparen->pos, "expected ')'");
+ token->next = rparen;
+ return false;
+ }
+ after_rparen = rparen->next;
+ *p = &eof_token_entry;
+ }
+
+ param_p = ¶ms;
+ while (!eof_token(next = scan_next(param_p))) {
+ if (token_type(next) == TOKEN_IDENT) {
+ struct ident *id;
+ struct position id_pos;
+ enum embed_param_kind kind;
+
+ if (!expand_one_symbol(param_p))
+ continue;
+ next = *param_p;
+ if (token_type(next) != TOKEN_IDENT) {
+ supported = 0;
+ param_p = &next->next;
+ continue;
+ }
+ id = next->ident;
+ id_pos = next->pos;
+ if (match_op(next->next, ':') &&
+ match_op(next->next->next, ':')) {
+ struct token *attr = next->next->next->next;
+
+ if (token_type(attr) != TOKEN_IDENT) {
+ sparse_error(attr->pos,
+ "identifier expected");
+ token->next = after_rparen;
+ return false;
+ }
+ supported = 0;
+ next = attr->next;
+ if (match_op(next, '(')) {
+ int depth = 1;
+
+ next = next->next;
+ while (!eof_token(next) && depth > 0) {
+ if (match_op(next, '('))
+ depth++;
+ else if (match_op(next, ')'))
+ depth--;
+ next = next->next;
+ }
+ }
+ param_p = &next;
+ continue;
+ }
+
+ kind = classify_embed_param(id);
+ if (kind != EMBED_PARAM_NONE) {
+ struct token *pstart, *pend = NULL;
+ int depth = 1;
+
+ if (seen_params & kind) {
+ sparse_error(
+ id_pos,
+ "duplicate embed parameter '%s'",
+ show_ident(id));
+ token->next = after_rparen;
+ return false;
+ }
+ seen_params |= kind;
+
+ next = scan_next(&next->next);
+ if (!match_op(next, '(')) {
+ sparse_error(
+ id_pos,
+ "expected '(' after '%s'",
+ show_ident(id));
+ token->next = after_rparen;
+ return false;
+ }
+ pstart = next->next;
+ next = next->next;
+ while (!eof_token(next) && depth > 0) {
+ if (match_op(next, '('))
+ depth++;
+ else if (match_op(next, ')') &&
+ !--depth)
+ break;
+ pend = next;
+ next = next->next;
+ }
+ if (!match_op(next, ')')) {
+ sparse_error(id_pos, "expected ')'");
+ token->next = after_rparen;
+ return false;
+ }
+ next = next->next;
+ if (kind == EMBED_PARAM_LIMIT) {
+ if (!eval_embed_limit_expr(
+ id_pos, pstart, pend,
+ &limit_val)) {
+ token->next = after_rparen;
+ return false;
+ }
+ has_limit = 1;
+ }
+ param_p = &next;
+ continue;
+ }
+
+ /* Unknown non-prefixed parameter */
+ supported = 0;
+ next = scan_next(&next->next);
+ if (match_op(next, '(')) {
+ int depth = 1;
+
+ next = next->next;
+ while (!eof_token(next) && depth > 0) {
+ if (match_op(next, '('))
+ depth++;
+ else if (match_op(next, ')'))
+ depth--;
+ next = next->next;
+ }
+ }
+ param_p = &next;
+ continue;
+ }
+ supported = 0;
+ param_p = &next->next;
+ }
+
+ if (!supported) {
+ val = 0;
+ } else if (!check_has_embed(stream, filename, expect, has_limit,
+ limit_val, &filesize)) {
+ val = 0;
+ } else if (filesize == 0 || (has_limit && limit_val == 0)) {
+ val = 2;
+ } else {
+ val = 1;
+ }
+
+ replace_with_int(token, val);
+ token->next = after_rparen;
+ return true;
+
+err:
+ token->next = skip_balanced_parens(lparen);
+ return false;
+}
+
static int free_preprocessor_line(struct token *token)
{
while (token_type(token) != TOKEN_EOF) {
@@ -1933,6 +2363,12 @@ static int expression_value(struct token **where)
replace_with_bool(p, 0);
break;
}
+ if (p->ident == &__has_embed_ident) {
+ if (parse_has_embed(list))
+ continue;
+ replace_with_bool(p, 0);
+ break;
+ }
if (!expand_one_symbol(list))
continue;
if (token_type(p) != TOKEN_IDENT)
@@ -2598,6 +3034,7 @@ static void init_preprocessor(void)
{ "__has_feature", NULL, expand_has_feature },
{ "__has_include", NULL, NULL },
{ "__has_include_next", NULL, NULL },
+ { "__has_embed", NULL, NULL },
};
for (i = 0; i < ARRAY_SIZE(normal); i++) {
diff --git a/predefine.c b/predefine.c
index d6ab0785abad..5639fc6862e3 100644
--- a/predefine.c
+++ b/predefine.c
@@ -123,6 +123,9 @@ void predefined_macros(void)
predefine("__STDC_NO_COMPLEX__", 1, "1");
predefine("__STDC_NO_THREADS__", 1, "1");
}
+ predefine("__STDC_EMBED_NOT_FOUND__", 1, "0");
+ predefine("__STDC_EMBED_FOUND__", 1, "1");
+ predefine("__STDC_EMBED_EMPTY__", 1, "2");
predefine("__CHAR_BIT__", 1, "%d", bits_in_char);
if (funsigned_char)
diff --git a/validation/preprocessor/c23-has-embed.c b/validation/preprocessor/c23-has-embed.c
new file mode 100644
index 000000000000..8ae7bb1d081f
--- /dev/null
+++ b/validation/preprocessor/c23-has-embed.c
@@ -0,0 +1,69 @@
+#if defined(__has_embed)
+int has_macro = 1;
+#endif
+
+#if __has_embed("options.h") == __STDC_EMBED_FOUND__
+int found_options = 1;
+#endif
+
+#if __has_embed("options.h" limit(0)) == __STDC_EMBED_EMPTY__
+int limit_zero_empty = 1;
+#endif
+
+#if __has_embed("options.h" __limit__(0)) == __STDC_EMBED_EMPTY__
+int dunder_limit_zero_empty = 1;
+#endif
+
+#if __has_embed("options.h" limit(5)) == __STDC_EMBED_FOUND__
+int limit_five_found = 1;
+#endif
+
+#if __has_embed("nonexistent_embed_12345.bin") == __STDC_EMBED_NOT_FOUND__
+int not_found = 1;
+#endif
+
+#if __has_embed("options.h" prefix(1) suffix(2)) == __STDC_EMBED_FOUND__ && \
+ __has_embed("options.h" __prefix__(1) __suffix__(2) __if_empty__(3)) == \
+ __STDC_EMBED_FOUND__
+int standard_params = 1;
+#endif
+
+#if __has_embed("options.h" unknown_vendor::param(1)) == \
+ __STDC_EMBED_NOT_FOUND__
+int unknown_param = 1;
+#endif
+
+#define HAS_EMB __has_embed
+#if HAS_EMB("options.h") == __STDC_EMBED_FOUND__
+int aliased_has_embed = 1;
+#endif
+
+#if __has_embed("/dev/null") == __STDC_EMBED_EMPTY__
+int dev_null_empty = 1;
+#endif
+
+#if __has_embed("options.h" limit(1ULL << 63)) == __STDC_EMBED_FOUND__ && \
+ __has_embed("options.h" limit(0xffffffffffffffffULL)) == \
+ __STDC_EMBED_FOUND__
+int large_unsigned_limit = 1;
+#endif
+
+/*
+ * check-name: c23-has-embed
+ * check-command: sparse -std=c23 -E -I.. $file
+ *
+ * check-output-start
+
+int has_macro = 1;
+int found_options = 1;
+int limit_zero_empty = 1;
+int dunder_limit_zero_empty = 1;
+int limit_five_found = 1;
+int not_found = 1;
+int standard_params = 1;
+int unknown_param = 1;
+int aliased_has_embed = 1;
+int dev_null_empty = 1;
+int large_unsigned_limit = 1;
+ * check-output-end
+ */
next prev parent reply other threads:[~2026-11-09 20:33 UTC|newest]
Thread overview: 74+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-09 20:31 Bart Van Assche
2026-11-09 20:31 ` [PATCH 01/73] Makefile: Pass '--' to rm in clean target to handle dash-prefixed files Bart Van Assche
2026-11-09 20:31 ` [PATCH 02/73] sparse-llvm: Use LLVMCreateBuilderForModule() with LLVM 24 and later Bart Van Assche
2026-11-09 20:31 ` [PATCH 03/73] typeof_unqual: Strip qualifiers and address space from types and arrays Bart Van Assche
2026-11-09 20:31 ` [PATCH 04/73] bitfield: Pack consecutive _Bool bitfields into byte containers Bart Van Assche
2026-11-09 20:31 ` [PATCH 05/73] allocate: Harden slab allocation bounds, zeroing, and mmap checks Bart Van Assche
2026-11-09 20:31 ` [PATCH 06/73] tokenize: Support 4096-byte identifiers and fix escape bounds Bart Van Assche
2026-11-09 20:31 ` [PATCH 07/73] pre-process: Fix macro expansion and include directive handling Bart Van Assche
2026-11-09 20:31 ` [PATCH 08/73] options, lib: Harden warning buffers and command-line option parsing Bart Van Assche
2026-11-09 20:31 ` [PATCH 09/73] builtin: Fix atomic builtin type checking and object_size bounds Bart Van Assche
2026-11-09 20:31 ` [PATCH 10/73] parse, show-parse: Fix attribute propagation, enum overflow, and bounds Bart Van Assche
2026-11-09 20:31 ` [PATCH 11/73] target-openrisc: Set target_openrisc.mach to MACH_OPENRISC Bart Van Assche
2026-11-09 20:31 ` [PATCH 12/73] evaluate: Fix pointer arithmetic, incomplete types, and qualifiers Bart Van Assche
2026-11-09 20:31 ` [PATCH 13/73] expand: Fix static initializer folding and floating-point casts Bart Van Assche
2026-11-09 20:32 ` [PATCH 14/73] inline: Copy union cast types and VLA bounds when inlining Bart Van Assche
2026-11-09 20:32 ` [PATCH 15/73] linearize, flow: Fix asm operands, switch case bounds, and DSE Bart Van Assche
2026-11-09 20:32 ` [PATCH 16/73] memops, ssa: Walk parent insns in reverse and skip mixed-size SSA Bart Van Assche
2026-11-09 20:32 ` [PATCH 17/73] simplify: Prevent overflow on LLONG_MIN negation and fix simplifications Bart Van Assche
2026-11-09 20:32 ` [PATCH 18/73] sparse: Gate context failure warning on Wcontext and catch underflow Bart Van Assche
2026-11-09 20:32 ` [PATCH 19/73] ast-model: Return AST_N_COLUMNS and inspect child nodes lazily Bart Van Assche
2026-11-09 20:32 ` [PATCH 20/73] c2xml: Guard against recursive symbols and free xmlGetProp() string Bart Van Assche
2026-11-09 20:32 ` [PATCH 21/73] compile-i386: Fix buffer bounds, unsigned '<=' codegen, and null checks Bart Van Assche
2026-11-09 20:32 ` [PATCH 22/73] ctags: Fix line comparison order and handle SYM_RESTRICT and SYM_LABEL Bart Van Assche
2026-11-09 20:32 ` [PATCH 23/73] dissect: Unwrap array element type via base_type() Bart Van Assche
2026-11-09 20:32 ` [PATCH 24/73] example: Fix show_op() rotating buffer dimensions Bart Van Assche
2026-11-09 20:32 ` [PATCH 25/73] graph: Check PSEUDO_SYM before dereferencing insn->func->sym Bart Van Assche
2026-11-09 20:32 ` [PATCH 26/73] scheck: Fix slice() upper bit index calculation Bart Van Assche
2026-11-09 20:32 ` [PATCH 27/73] sparse-llvm: Support arbitrary struct member counts and fix operand types Bart Van Assche
2026-11-09 20:32 ` [PATCH 28/73] inline: Duplicate generic expressions instead of evaluating them Bart Van Assche
2026-11-09 20:32 ` [PATCH 29/73] lib: Avoid mutating fmt before va_start() in warning() Bart Van Assche
2026-11-09 20:32 ` [PATCH 30/73] cse, canon: Cast pointers to uintptr_t before relational comparison Bart Van Assche
2026-11-09 20:32 ` [PATCH 31/73] context: Add "conditional context increment" model Bart Van Assche
2026-11-09 20:32 ` [PATCH 32/73] expand: Simplify signed constants early Bart Van Assche
2026-11-09 20:32 ` [PATCH 33/73] bitwise: Allow all-bits-set as a restricted value Bart Van Assche
2026-11-09 20:32 ` [PATCH 34/73] bitwise: Allow restricted ordered compares with unrestricted values Bart Van Assche
2026-11-09 20:32 ` [PATCH 35/73] bitwise: Keep unrestricted values unrestricted after a cast Bart Van Assche
2026-11-09 20:32 ` [PATCH 36/73] bitwise: Don't remove MOD_SPECIFIER from 'bitwise' types Bart Van Assche
2026-11-09 20:32 ` [PATCH 37/73] bitwise: Allow both regular casts and forced casts for restricted values Bart Van Assche
2026-11-09 20:32 ` [PATCH 38/73] clang-format: Add .clang-format configuration file Bart Van Assche
2026-11-09 20:32 ` [PATCH 39/73] options: Add support for -std=c23, -std=c2x and -std=gnu23 Bart Van Assche
2026-11-09 20:32 ` [PATCH 40/73] preprocessor: Add support for #elifdef and #elifndef Bart Van Assche
2026-11-09 20:32 ` [PATCH 41/73] preprocessor: Add support for __has_include and __has_include_next Bart Van Assche
2026-11-09 20:32 ` [PATCH 42/73] c23: Add support for static_assert, alignas, alignof, thread_local Bart Van Assche
2026-11-09 20:32 ` [PATCH 43/73] c23: Add support for bool, true, and false keywords Bart Van Assche
2026-11-09 20:32 ` [PATCH 44/73] c23: Add support for nullptr and nullptr_t Bart Van Assche
2026-11-09 20:32 ` [PATCH 45/73] c23: Add support for digit separators in numeric literals Bart Van Assche
2026-11-09 20:32 ` [PATCH 46/73] c23: Support unnamed parameters in function definitions Bart Van Assche
2026-11-09 20:32 ` [PATCH 47/73] c23: Support variadic functions without named parameters Bart Van Assche
2026-11-09 20:32 ` [PATCH 48/73] c23: Support labels before declarations and at block ends Bart Van Assche
2026-11-09 20:32 ` [PATCH 49/73] c23: Support auto type inference Bart Van Assche
2026-11-09 20:32 ` [PATCH 50/73] c23: Support constexpr object specifier Bart Van Assche
2026-11-09 20:32 ` [PATCH 51/73] c23: Support enumerations with fixed underlying types Bart Van Assche
2026-11-09 20:32 ` [PATCH 52/73] c23: Support standard [[]] attribute syntax Bart Van Assche
2026-11-09 20:32 ` [PATCH 53/73] preprocessor: Add support for __has_c_attribute Bart Van Assche
2026-11-09 20:32 ` [PATCH 54/73] c23: Support empty initializer braces {} Bart Van Assche
2026-11-09 20:32 ` Bart Van Assche [this message]
2026-11-09 20:32 ` [PATCH 56/73] preprocessor: Add support for #embed directive Bart Van Assche
2026-11-09 20:32 ` [PATCH 57/73] c23: Add support for u8 character constants and string literals Bart Van Assche
2026-11-09 20:32 ` [PATCH 58/73] preprocessor: Add support for __VA_OPT__ Bart Van Assche
2026-11-09 20:32 ` [PATCH 59/73] c23: Treat empty parameter list () as (void) and reject K&R functions Bart Van Assche
2026-11-09 20:32 ` [PATCH 60/73] c23: Support storage-class specifiers in compound literals Bart Van Assche
2026-11-09 20:32 ` [PATCH 61/73] c23: Add support for _BitInt(N) Bart Van Assche
2026-11-09 20:32 ` [PATCH 62/73] enum: Support machine mode attributes on enumeration types Bart Van Assche
2026-11-09 20:32 ` [PATCH 63/73] enum: Support __attribute__((packed)) " Bart Van Assche
2026-11-09 20:32 ` [PATCH 64/73] expand: Ignore top-level non-array address space in compare_types() Bart Van Assche
2026-11-09 20:32 ` [PATCH 65/73] builtin: Support __builtin_infer_alloc_token() as a size_t ICE Bart Van Assche
2026-11-09 20:32 ` [PATCH 66/73] builtin: Add support for Linux kernel compiler builtins Bart Van Assche
2026-11-09 20:32 ` [PATCH 67/73] builtin: Add support for __builtin_has_attribute() Bart Van Assche
2026-11-09 20:32 ` [PATCH 68/73] cleanup: Support __attribute__((cleanup(...))) in linearize and -Wcontext Bart Van Assche
2026-11-09 20:32 ` [PATCH 69/73] builtin: Do not evaluate __builtin_clz(0) and __builtin_ctz(0) Bart Van Assche
2026-11-09 20:32 ` [PATCH 70/73] pre-process: Support long token and string expansions dynamically Bart Van Assche
2026-11-09 20:32 ` [PATCH 71/73] x86: Undefine conflicting bitness macros when parsing -m flags Bart Van Assche
2026-11-09 20:32 ` [PATCH 72/73] evaluate: Accept conditional expressions with only one void side Bart Van Assche
2026-11-09 20:32 ` [PATCH 73/73] ci: Add Linux kernel GitHub Actions workflow and build script Bart Van Assche
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261109203259.362845-56-bvanassche@acm.org \
--to=bvanassche@acm.org \
--cc=linux-sparse@vger.kernel.org \
--cc=torvalds@linux-foundation.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox