aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2025-12-11 17:57:07 +0100
committerlemon <lsof@mailbox.org>2025-12-11 17:57:07 +0100
commit31f6b60f650a72d7727d386cef160f4baae70f38 (patch)
tree6618de25658d1de7be052b2b0a0cdc13c826ad78
parent79db8917a7d6722f0a64d4fa912efa5e96a1a2c3 (diff)
_Alignof and stuff
-rw-r--r--c/c.c29
-rw-r--r--common.h2
-rw-r--r--embedfilesdir.c9
-rw-r--r--io.c4
-rw-r--r--test/13-c11.c22
5 files changed, 53 insertions, 13 deletions
diff --git a/c/c.c b/c/c.c
index d5e4d9e..259058f 100644
--- a/c/c.c
+++ b/c/c.c
@@ -443,13 +443,17 @@ subscriptcheck(const struct expr *ex, const struct expr *rhs, const struct span
return ty;
}
-static void /* 6.5.3.4 The sizeof operator */
-sizeofcheck(const struct span *span, union type ty)
+static void /* 6.5.3.4 The sizeof and _Alignof operators */
+sizeofalignofcheck(const struct span *span, enum toktag tt, union type ty, const struct expr *ex)
{
if (isincomplete(ty))
- error(span, "cannot apply sizeof to incomplete type '%ty'", ty);
+ error(span, "cannot apply %'tt to incomplete type '%ty'", tt);
else if (ty.t == TYFUNC)
- error(span, "cannot apply sizeof to function type '%ty'", ty);
+ error(span, "cannot apply %'tt to function type '%ty'", tt);
+ else if (tt == TKWsizeof && ex && ex->t == EGETF && ex->fld.bitsiz)
+ error(span, "cannot apply %'tt to bitfield", tt);
+ if (tt != TKWsizeof && ex && ccopt.pedant)
+ warn(span, "%'tt applied to an expression is a GNU extension", tt);
}
static bool /* 6.5.8 Relational operators */
@@ -998,25 +1002,28 @@ Unary:
ex = mkexpr(ESYM, tk.span, decl->ty, .qual = decl->qual, .sym = decl);
}
break;
- case TKWsizeof:
+ case TKWsizeof: case TKW_Alignof: case TKWalignof:
span = tk.span;
- if (!match(cm, NULL, '(')) /* sizeof expr */
+ if (!match(cm, NULL, '(')) /* sizeof/alignof expr */
goto Unops;
- else if (isdecltok(cm)) { /* sizeof (type) */
+ else if (isdecltok(cm)) { /* sizeof/alignof (type) */
+ enum toktag tt = tk.t;
struct declstate st = { DCASTEXPR };
ty = pdecl(&st, cm).ty;
peek(cm, &tk);
if (expect(cm, ')', NULL))
joinspan(&span.ex, tk.span.ex);
- } else { /* sizeof expr */
+ sizeofalignofcheck(&span, tt, ty, NULL);
+ } else { /* sizeof/alignof expr */
+ enum toktag tt = tk.t;
tmp = commaexpr(cm);
peek(cm, &tk);
if (expect(cm, ')', NULL))
joinspan(&span.ex, tk.span.ex);
ppostfixopers(cm, &tmp);
ty = tmp.ty;
+ sizeofalignofcheck(&span, tt, ty, &tmp);
}
- sizeofcheck(&span, ty);
ex = mkexpr(ENUMLIT, span, mktype(targ_sizetype), .u = typesize(ty));
break;
case TKW__builtin_va_arg:
@@ -1081,8 +1088,8 @@ Unary:
error(&span, "cannot take address of bitfield");
ex = mkexpr(EADDROF, span, mkptrtype(ex.ty, ex.qual), .sub = exprdup(cm, &ex));
break;
- case TKWsizeof:
- sizeofcheck(&span, ex.ty);
+ case TKWsizeof: case TKW_Alignof: case TKWalignof:
+ sizeofalignofcheck(&span, unops[nunop].tt, ex.ty, &ex);
ex = mkexpr(ENUMLIT, span, mktype(targ_sizetype), .u = typesize(ex.ty));
break;
default: assert(0);
diff --git a/common.h b/common.h
index ce7d604..2b2bfd7 100644
--- a/common.h
+++ b/common.h
@@ -16,6 +16,7 @@ typedef unsigned short ushort;
typedef unsigned long long uvlong;
typedef signed long long vlong;
typedef unsigned uint;
+
#if __STDC_VERSION__ >= 202311L
#define NORETURN [[noreturn]]
#elif __STDC_VERSION__ >= 201112L
@@ -29,6 +30,7 @@ typedef unsigned uint;
#else
#define HAS_BUILTIN(_) 0
#endif
+
#define static_assert(x) _Static_assert(x, #x)
#define in_range(x, Lo, Hi) ((uint) (x) - (Lo) <= (Hi) - (Lo)) /* lo <= x <= hi; lo > 0, hi > 0 */
#define alignup(x, A) (((x) + ((A) - 1)) & -(A))
diff --git a/embedfilesdir.c b/embedfilesdir.c
index 72a2ce1..7d97f98 100644
--- a/embedfilesdir.c
+++ b/embedfilesdir.c
@@ -87,6 +87,15 @@ typedef __builtin_va_list __gnuc_va_list;\n\
#define noreturn _Noreturn\n\
")},
+{"stdalign.h", S("\
+#if __STDC_VERSION__ < 202311L\n\
+#define alignas _Alignas\n\
+#define alignof _Alignof\n\
+#define __alignas_is_defined 1\n\
+#define __alignof_is_defined 1\n\
+#endif\n\
+")},
+
{NULL}
};
diff --git a/io.c b/io.c
index b2d4364..dc4cd5d 100644
--- a/io.c
+++ b/io.c
@@ -595,8 +595,8 @@ vbfmt(struct wbuf *out, const char *fmt, va_list ap)
#include "c/keywords.def"
#undef _
};
- n += bfmt(buf, "%s", tab[tok->t - TKWBEGIN_]);
- break;
+ tok->s = tab[tok->t - TKWBEGIN_];
+ tok->len = strlen(tok->s);
}
goto Tok;
}
diff --git a/test/13-c11.c b/test/13-c11.c
new file mode 100644
index 0000000..479c2d7
--- /dev/null
+++ b/test/13-c11.c
@@ -0,0 +1,22 @@
+/* CFLAGS: -std=c11 -Werror */
+/* EXPECT:
+*/
+
+#include <stdlib.h>
+#include <stdnoreturn.h>
+#include <stdalign.h>
+
+noreturn void quit(int x) {
+ exit(x);
+}
+
+int foo(int x) {
+ if (x < 0) quit(alignof(int *));
+ else return x;
+}
+
+struct x{int h:2;} X;
+int main(int argc, char **argv) {
+ return foo(0);
+}
+