ref: da40be16dc3adcabf313f467b6ac91bca512038b
parent: 80e7f658d5789313b32f2fb7677032766aca5c42
author: Roberto E. Vargas Caballero <[email protected]>
date: Tue Sep 24 18:01:10 EDT 2013
Detect unnamed structs When a struct is declared without tag it is a unnamed struct. If it is not declared a variable at the same time the struct is defined is not posible use this struct, because it is not posible declare a variable of this type.
--- a/decl.c
+++ b/decl.c
@@ -85,8 +85,11 @@
static void
new_struct(register struct ctype *tp)
{
+ struct symbol *sym = NULL;
+
if (yytoken == IDEN) {
- (namespace(NS_STRUCT, -1)->ctype = tp)->refcnt++;
+ sym = namespace(NS_STRUCT, -1);
+ (sym->ctype = tp)->refcnt++;
next();
}
if (nr_structs == NR_MAXSTRUCTS)
@@ -93,7 +96,9 @@
error("too much structs/unions/enum defined");
if (structp == &structbuf[NR_STRUCT_LEVEL])
error("too much nested structs/unions");
- tp->c_struct = *structp++ = nr_structs;
+ tp->ns = *structp++ = nr_structs;
+ tp->forward = 1;
+ tp->sym = sym;
}
static struct ctype * spec(void);
@@ -114,7 +119,7 @@
error("storage specifier in a struct/union field declaration");
}
- do { /* TODO: detect unnamed structs */
+ do {
declarator(base, ns);
tp = decl_type(base);
(cursym->ctype = tp)->refcnt++;
@@ -135,7 +140,7 @@
error("struct/union already defined");
do
- struct_dcl(tp->c_struct);
+ struct_dcl(tp->ns);
while (!accept('}'));
tp->forward = 0;
@@ -336,6 +341,10 @@
tp->c_register || tp->c_const || tp->c_volatile) {
warn(options.useless,
"useless storage class specifier in empty declaration");
+ }
+ if (!tp->sym && type != ENUM) {
+ warn(options.useless,
+ "unnamed struct/union that defines no instances");
}
} else {
warn(options.useless,
--- a/symbol.h
+++ b/symbol.h
@@ -35,7 +35,10 @@
bool forward : 1;
union {
unsigned len;
- unsigned char c_struct;
+ struct {
+ struct symbol *sym;
+ unsigned char ns;
+ };
};
struct ctype *base;
unsigned char refcnt;