X-Git-Url: https://git.draconx.ca/gitweb/cdecl99.git/blobdiff_plain/c807d652225fe170ee442591bb2a0bfc91c8618c..7f52c6d4be39c4d5ece844011de3581fe718b199:/src/normalize.c diff --git a/src/normalize.c b/src/normalize.c index 8cd0020..b326e2d 100644 --- a/src/normalize.c +++ b/src/normalize.c @@ -107,6 +107,12 @@ sort_specs(struct cdecl_declspec *l1, size_t n) return merge_specs(l1, l2); } +/* + * Mask to clear the type/storage specifier bits on one side of the comparison + * to ensure that only function specifiers and qualifiers comapare equal below. + */ +#define SPEC_DUP_MASK (~(CDECL_SPEC_TYPE|CDECL_SPEC_STOR|0u)) + /* * C allows declaration specifiers to appear in any order, and allows arbitrary * repetition of some kinds of specifiers. Normalize the specifier lists by @@ -120,16 +126,16 @@ struct cdecl_declspec *cdecl__normalize_specs(struct cdecl_declspec *specs) for (c = specs; c; c = c->next) count++; - specs = sort_specs(specs, count); - for (c = specs, l = NULL; c; l = c, c = c->next) { - if (!(c->type & (CDECL_SPEC_QUAL|CDECL_SPEC_FUNC))) - continue; + if (!(l = specs = sort_specs(specs, count))) + return NULL; - if (l && l->type == c->type) { + while ((c = l->next)) { + if ((l->type & SPEC_DUP_MASK) == c->type) { l->next = c->next; free(c); - c = l; + } else { + l = c; } }