From 425ed781f7a27bc415e13a1901899e2c7b11e4c8 Mon Sep 17 00:00:00 2001 From: Nick Bowler Date: Tue, 28 Aug 2012 20:44:09 -0400 Subject: [PATCH] Don't allow restrict-qualified pointers to functions. Such pointers are prohibited by the C language, so we must reject them. --- src/parse-decl.c | 27 ++++++++++++++++++++++++++- test/declgen.c | 6 ++++++ tests/cdecl99-c-invalid.sh | 4 ++++ 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/src/parse-decl.c b/src/parse-decl.c index 45cf67f..4489532 100644 --- a/src/parse-decl.c +++ b/src/parse-decl.c @@ -1,6 +1,6 @@ /* * Parse and validate C declarations. - * Copyright © 2011 Nick Bowler + * Copyright © 2011-2012 Nick Bowler * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -364,6 +364,27 @@ normalize_specs(struct cdecl_declarator **p, struct cdecl_declarator *d) return 0; } +static int +check_qualifiers(struct cdecl_declarator **p, struct cdecl_declarator *d) +{ + struct cdecl_declspec *spec; + struct cdecl_pointer *ptr; + + if (!d->child || d->child->type != CDECL_DECL_POINTER) + return 0; + + ptr = &d->child->u.pointer; + for (spec = ptr->qualifiers; spec; spec = spec->next) { + if (spec->type == CDECL_QUAL_RESTRICT + && d->type == CDECL_DECL_FUNCTION) { + fprintf(stderr, "function pointers cannot be restrict-qualified\n"); + return -1; + } + } + + return 0; +} + /* * Traverse the parse tree, calling a function on every declarator in a * depth-first preorder traversal. The function is given a pointer to the @@ -445,6 +466,8 @@ struct cdecl *cdecl_parse_decl(const char *declstr) goto err; if (!forall_declarators(i, normalize_specs)) goto err; + if (!forall_declarators(i, check_qualifiers)) + goto err; if (!valid_declspecs(i, true)) goto err; @@ -494,6 +517,8 @@ struct cdecl *cdecl_parse_english(const char *english) goto err; if (!forall_declarators(i, normalize_specs)) goto err; + if (!forall_declarators(i, check_qualifiers)) + goto err; if (!valid_declspecs(i, true)) goto err; diff --git a/test/declgen.c b/test/declgen.c index 3f4c394..4fb39cb 100644 --- a/test/declgen.c +++ b/test/declgen.c @@ -402,6 +402,12 @@ struct cdecl_declarator *gen_declarators(struct gen_rng *rng) break; case 2: gen_function(rng, d); + if (p && p->type == CDECL_DECL_POINTER) { + struct cdecl_pointer *ptr = &p->u.pointer; + + gen_free_declspecs(ptr->qualifiers); + ptr->qualifiers = gen_qualifiers(rng, false); + } limit = 1; break; default: diff --git a/tests/cdecl99-c-invalid.sh b/tests/cdecl99-c-invalid.sh index 5ffb3b3..4370e58 100755 --- a/tests/cdecl99-c-invalid.sh +++ b/tests/cdecl99-c-invalid.sh @@ -30,8 +30,12 @@ test_decl explain 'long long long x' test_decl declare 'x as long long long' test_decl explain 'inline int x' test_decl declare 'x as inline int' +# C99§6.7.3#2: Types other than opinter types derived from object or incomplete +# types shall not be restrict-qualified. test_decl explain 'restrict int x' test_decl declare 'x as restrict int' +test_decl explain 'int (*restrict f)(void)' +test_decl declare 'f as restrict pointer to function (void) returning int' test_decl explain 'static auto int x' test_decl declare 'x as static auto int' test_decl explain 'auto x' -- 2.43.0