diff options
-rw-r--r-- | cc.h | 4 | ||||
-rw-r--r-- | expr.c | 15 | ||||
-rw-r--r-- | test/nullptr.c | 4 | ||||
-rw-r--r-- | test/nullptr.qbe | 3 | ||||
-rw-r--r-- | type.c | 2 |
5 files changed, 25 insertions, 3 deletions
@@ -166,7 +166,8 @@ enum typekind { TYPEARRAY, TYPEFUNC, TYPESTRUCT, - TYPEUNION + TYPEUNION, + TYPENULLPTR, }; enum typeprop { @@ -446,6 +447,7 @@ extern struct type typeint, typeuint; extern struct type typelong, typeulong; extern struct type typellong, typeullong; extern struct type typefloat, typedouble, typeldouble; +extern struct type typenullptr; extern struct type *typeadjvalist; /* targ */ @@ -175,6 +175,8 @@ nullpointer(struct expr *e) { if (e->kind != EXPRCONST) return false; + if (e->type->kind == TYPENULLPTR) + return true; if (!(e->type->prop & PROPINT) && (e->type->kind != TYPEPOINTER || e->type->base != &typevoid)) return false; return e->u.constant.u == 0; @@ -188,8 +190,8 @@ exprassign(struct expr *e, struct type *t) et = e->type; switch (t->kind) { case TYPEBOOL: - if (!(et->prop & PROPARITH) && et->kind != TYPEPOINTER) - error(&tok.loc, "assignment to bool must be from arithmetic or pointer type"); + if (!(et->prop & PROPARITH) && et->kind != TYPEPOINTER && et->kind != TYPENULLPTR) + error(&tok.loc, "assignment to bool must be from arithmetic, pointer, or nullptr_t type"); break; case TYPEPOINTER: if (nullpointer(e)) @@ -201,6 +203,10 @@ exprassign(struct expr *e, struct type *t) if ((et->qual & t->qual) != et->qual) error(&tok.loc, "assignment to pointer discards qualifiers"); break; + case TYPENULLPTR: + if (!nullpointer(e)) + error(&tok.loc, "assignment to nullptr_t must be from null pointer constant or expression with type nullptr_t"); + break; case TYPESTRUCT: case TYPEUNION: if (!typecompatible(t, et)) @@ -699,6 +705,11 @@ primaryexpr(struct scope *s) e->u.constant.u = tok.kind == TTRUE; next(); break; + case TNULLPTR: + e = mkexpr(EXPRCONST, &typenullptr, NULL); + e->u.constant.u = 0; + next(); + break; case TLPAREN: next(); e = expr(s); diff --git a/test/nullptr.c b/test/nullptr.c new file mode 100644 index 0000000..8f5b436 --- /dev/null +++ b/test/nullptr.c @@ -0,0 +1,4 @@ +typeof(nullptr) x = 0; +_Static_assert(sizeof x == sizeof(char *)); +int *y = nullptr; +bool z = nullptr; diff --git a/test/nullptr.qbe b/test/nullptr.qbe new file mode 100644 index 0000000..c805942 --- /dev/null +++ b/test/nullptr.qbe @@ -0,0 +1,3 @@ +export data $x = align 8 { l 0, } +export data $y = align 8 { l 0, } +export data $z = align 1 { b 0, } @@ -39,6 +39,8 @@ struct type typefloat = FLTTYPE(TYPEFLOAT, 4); struct type typedouble = FLTTYPE(TYPEDOUBLE, 8); struct type typeldouble = FLTTYPE(TYPELDOUBLE, 16); +struct type typenullptr = {.kind = TYPENULLPTR, .size = 8, .align = 8, .prop = PROPSCALAR}; + struct type *typeadjvalist; struct type * |