From b77355427575385b6f0b6c0a914600b79b4e4412 Mon Sep 17 00:00:00 2001 From: Rui Ueyama Date: Thu, 3 Sep 2020 01:22:17 +0900 Subject: [PATCH] Ignore const, volatile, auto, register, restrict or _Noreturn. --- parse.c | 37 ++++++++++++++++++++++++++++--------- test/compat.c | 17 +++++++++++++++++ test/const.c | 14 ++++++++++++++ test/test.h | 1 + tokenize.c | 3 ++- 5 files changed, 62 insertions(+), 10 deletions(-) create mode 100644 test/compat.c create mode 100644 test/const.c diff --git a/parse.c b/parse.c index ad37ba9..481be3b 100644 --- a/parse.c +++ b/parse.c @@ -353,7 +353,9 @@ static void push_tag_scope(Token *tok, Type *ty) { // | "typedef" | "static" | "extern" // | "signed" | "unsigned" // | struct-decl | union-decl | typedef-name -// | enum-specifier)+ +// | enum-specifier +// | "const" | "volatile" | "auto" | "register" | "restrict" +// | "__restrict" | "__restrict__" | "_Noreturn")+ // // The order of typenames in a type-specifier doesn't matter. For // example, `int long static` means the same as `static long int`. @@ -405,6 +407,13 @@ static Type *declspec(Token **rest, Token *tok, VarAttr *attr) { continue; } + // These keywords are recognized but ignored. + if (consume(&tok, tok, "const") || consume(&tok, tok, "volatile") || + consume(&tok, tok, "auto") || consume(&tok, tok, "register") || + consume(&tok, tok, "restrict") || consume(&tok, tok, "__restrict") || + consume(&tok, tok, "__restrict__") || consume(&tok, tok, "_Noreturn")) + continue; + if (equal(tok, "_Alignas")) { if (!attr) error_tok(tok, "_Alignas is not allowed in this context"); @@ -593,10 +602,21 @@ static Type *type_suffix(Token **rest, Token *tok, Type *ty) { return ty; } -// declarator = "*"* ("(" ident ")" | "(" declarator ")" | ident) type-suffix -static Type *declarator(Token **rest, Token *tok, Type *ty) { - while (consume(&tok, tok, "*")) +// pointers = ("*" ("const" | "volatile" | "restrict")*)* +static Type *pointers(Token **rest, Token *tok, Type *ty) { + while (consume(&tok, tok, "*")) { ty = pointer_to(ty); + while (equal(tok, "const") || equal(tok, "volatile") || equal(tok, "restrict") || + equal(tok, "__restrict") || equal(tok, "__restrict__")) + tok = tok->next; + } + *rest = tok; + return ty; +} + +// declarator = pointers ("(" ident ")" | "(" declarator ")" | ident) type-suffix +static Type *declarator(Token **rest, Token *tok, Type *ty) { + ty = pointers(&tok, tok, ty); if (equal(tok, "(")) { Token *start = tok; @@ -614,12 +634,9 @@ static Type *declarator(Token **rest, Token *tok, Type *ty) { return ty; } -// abstract-declarator = "*"* ("(" abstract-declarator ")")? type-suffix +// abstract-declarator = pointers ("(" abstract-declarator ")")? type-suffix static Type *abstract_declarator(Token **rest, Token *tok, Type *ty) { - while (equal(tok, "*")) { - ty = pointer_to(ty); - tok = tok->next; - } + ty = pointers(&tok, tok, ty); if (equal(tok, "(")) { Token *start = tok; @@ -1095,6 +1112,8 @@ static bool is_typename(Token *tok) { static char *kw[] = { "void", "_Bool", "char", "short", "int", "long", "struct", "union", "typedef", "enum", "static", "extern", "_Alignas", "signed", "unsigned", + "const", "volatile", "auto", "register", "restrict", "__restrict", + "__restrict__", "_Noreturn", }; for (int i = 0; i < sizeof(kw) / sizeof(*kw); i++) diff --git a/test/compat.c b/test/compat.c new file mode 100644 index 0000000..a636204 --- /dev/null +++ b/test/compat.c @@ -0,0 +1,17 @@ +#include "test.h" + +_Noreturn noreturn_fn(int restrict x) { + exit(0); +} + +int main() { + { volatile x; } + { int volatile x; } + { volatile int x; } + { volatile int volatile volatile x; } + { int volatile * volatile volatile x; } + { auto ** restrict __restrict __restrict__ const volatile *x; } + + printf("OK\n"); + return 0; +} diff --git a/test/const.c b/test/const.c new file mode 100644 index 0000000..a45478b --- /dev/null +++ b/test/const.c @@ -0,0 +1,14 @@ +#include "test.h" + +int main() { + { const x; } + { int const x; } + { const int x; } + { const int const const x; } + ASSERT(5, ({ const x = 5; x; })); + ASSERT(8, ({ const x = 8; int *const y=&x; *y; })); + ASSERT(6, ({ const x = 6; *(const * const)&x; })); + + printf("OK\n"); + return 0; +} diff --git a/test/test.h b/test/test.h index 6f84030..c1c82cd 100644 --- a/test/test.h +++ b/test/test.h @@ -5,3 +5,4 @@ int printf(char *fmt, ...); int sprintf(char *buf, char *fmt, ...); int strcmp(char *p, char *q); int memcmp(char *p, char *q, long n); +void exit(int n); diff --git a/tokenize.c b/tokenize.c index 2d10682..144e6e3 100644 --- a/tokenize.c +++ b/tokenize.c @@ -134,7 +134,8 @@ static bool is_keyword(Token *tok) { "struct", "union", "short", "long", "void", "typedef", "_Bool", "enum", "static", "goto", "break", "continue", "switch", "case", "default", "extern", "_Alignof", "_Alignas", "do", "signed", - "unsigned", + "unsigned", "const", "volatile", "auto", "register", "restrict", + "__restrict", "__restrict__", "_Noreturn", }; for (int i = 0; i < sizeof(kw) / sizeof(*kw); i++)