diff options
| -rw-r--r-- | c/c.c | 29 | ||||
| -rw-r--r-- | common.h | 2 | ||||
| -rw-r--r-- | embedfilesdir.c | 9 | ||||
| -rw-r--r-- | io.c | 4 | ||||
| -rw-r--r-- | test/13-c11.c | 22 |
5 files changed, 53 insertions, 13 deletions
@@ -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); @@ -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} }; @@ -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); +} + |