/*
* 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
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
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;
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;
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:
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'