diff options
author | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2020-10-06 02:31:25 +0200 |
---|---|---|
committer | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2020-10-06 02:31:25 +0200 |
commit | c0e96d6d3b95ae3f34ca54720e8a1196b201e119 (patch) | |
tree | 7e103eecaa9a28cc0ef59e5c280eaaf18e0924f0 | |
parent | b9453d0493bc672af908f83483e708880617ba8e (diff) | |
parent | ce9cf5b77cd8da6797da79af1298ecd4ed170a4d (diff) | |
download | sparse-c0e96d6d3b95ae3f34ca54720e8a1196b201e119.tar.gz |
Merge branch 'flex-array-base'
-rw-r--r-- | evaluate.c | 3 | ||||
-rw-r--r-- | options.c | 6 | ||||
-rw-r--r-- | options.h | 3 | ||||
-rw-r--r-- | sparse.1 | 21 | ||||
-rw-r--r-- | symbol.c | 48 | ||||
-rw-r--r-- | symbol.h | 8 | ||||
-rw-r--r-- | validation/flex-array-align.c | 18 | ||||
-rw-r--r-- | validation/flex-array-array.c | 15 | ||||
-rw-r--r-- | validation/flex-array-error.c | 26 | ||||
-rw-r--r-- | validation/flex-array-nested.c | 29 | ||||
-rw-r--r-- | validation/flex-array-sizeof.c | 18 |
11 files changed, 177 insertions, 18 deletions
@@ -2253,6 +2253,9 @@ static struct symbol *evaluate_sizeof(struct expression *expr) size = bits_in_char; } + if (has_flexible_array(type) && Wflexible_array_sizeof) + warning(expr->pos, "using sizeof on a flexible structure"); + if (is_array_type(type) && size < 0) { // VLA, 1-dimension only struct expression *base, *size; struct symbol *base_type; @@ -100,6 +100,9 @@ int Wdesignated_init = 1; int Wdo_while = 0; int Wenum_mismatch = 1; int Wexternal_function_has_definition = 1; +int Wflexible_array_array = 1; +int Wflexible_array_nested = 0; +int Wflexible_array_sizeof = 0; int Wimplicit_int = 1; int Winit_cstring = 0; int Wint_to_pointer_cast = 1; @@ -840,6 +843,9 @@ static const struct flag warnings[] = { { "do-while", &Wdo_while }, { "enum-mismatch", &Wenum_mismatch }, { "external-function-has-definition", &Wexternal_function_has_definition }, + { "flexible-array-array", &Wflexible_array_array }, + { "flexible-array-nested", &Wflexible_array_nested }, + { "flexible-array-sizeof", &Wflexible_array_sizeof }, { "implicit-int", &Wimplicit_int }, { "init-cstring", &Winit_cstring }, { "int-to-pointer-cast", &Wint_to_pointer_cast }, @@ -99,6 +99,9 @@ extern int Wdesignated_init; extern int Wdo_while; extern int Wenum_mismatch; extern int Wexternal_function_has_definition; +extern int Wflexible_array_array; +extern int Wflexible_array_nested; +extern int Wflexible_array_sizeof; extern int Wimplicit_int; extern int Winit_cstring; extern int Wint_to_pointer_cast; @@ -257,6 +257,27 @@ Sparse issues these warnings by default. To turn them off, use \fB\-Wno\-external\-function\-has\-definition\fR. . .TP +.B -Wflexible-array-array +Warn about arrays of structures containing a flexible array. + +Sparse issues these warnings by default. To turn them off, use +\fB-Wno-flexible-array-array\fR. +. +.TP +.B -Wflexible-array-nested +Warn about structures containing a flexible array being contained into +another structure, union or array. + +Sparse does not issue these warnings by default. +. +.TP +.B -Wflexible-array-sizeof +Warn about using the sizeof operator on a structure containing a flexible array, +possibly recursively. + +Sparse does not issue these warnings by default. +. +.TP .B \-Winit\-cstring Warn about initialization of a char array with a too long constant C string. @@ -87,6 +87,8 @@ struct struct_union_info { unsigned long max_align; unsigned long bit_size; int align_size; + char has_flex_array; + struct symbol *flex_array; }; /* @@ -94,13 +96,8 @@ struct struct_union_info { */ static void lay_out_union(struct symbol *sym, struct struct_union_info *info) { - examine_symbol_type(sym); - - // Unnamed bitfields do not affect alignment. - if (sym->ident || !is_bitfield_type(sym)) { - if (sym->ctype.alignment > info->max_align) - info->max_align = sym->ctype.alignment; - } + if (sym->bit_size < 0 && is_array_type(sym)) + sparse_error(sym->pos, "flexible array member '%s' in a union", show_ident(sym->ident)); if (sym->bit_size > info->bit_size) info->bit_size = sym->bit_size; @@ -125,24 +122,18 @@ static void lay_out_struct(struct symbol *sym, struct struct_union_info *info) unsigned long bit_size, align_bit_mask; int base_size; - examine_symbol_type(sym); - - // Unnamed bitfields do not affect alignment. - if (sym->ident || !is_bitfield_type(sym)) { - if (sym->ctype.alignment > info->max_align) - info->max_align = sym->ctype.alignment; - } - bit_size = info->bit_size; base_size = sym->bit_size; /* - * Unsized arrays cause us to not align the resulting - * structure size + * If the member is unsized, either it's a flexible array or + * it's invalid and a warning has already been issued. */ if (base_size < 0) { - info->align_size = 0; + if (!is_array_type(sym)) + return; base_size = 0; + info->flex_array = sym; } align_bit_mask = bytes_to_bits(sym->ctype.alignment) - 1; @@ -196,6 +187,20 @@ static struct symbol * examine_struct_union_type(struct symbol *sym, int advance sparse_error(member->pos, "member '%s' has __auto_type", show_ident(member->ident)); member->ctype.base_type = &incomplete_ctype; } + if (info.flex_array) + sparse_error(info.flex_array->pos, "flexible array member '%s' is not last", show_ident(info.flex_array->ident)); + examine_symbol_type(member); + + if (member->ctype.alignment > info.max_align) { + // Unnamed bitfields do not affect alignment. + if (member->ident || !is_bitfield_type(member)) + info.max_align = member->ctype.alignment; + } + + if (has_flexible_array(member)) + info.has_flex_array = 1; + if (has_flexible_array(member) && Wflexible_array_nested) + warning(sym->pos, "nested flexible arrays"); fn(member, &info); } END_FOR_EACH_PTR(member); @@ -206,6 +211,11 @@ static struct symbol * examine_struct_union_type(struct symbol *sym, int advance bit_align = bytes_to_bits(sym->ctype.alignment)-1; bit_size = (bit_size + bit_align) & ~bit_align; } + if (info.flex_array) { + info.has_flex_array = 1; + } + if (info.has_flex_array) + sym->has_flex_array = 1; sym->bit_size = bit_size; return sym; } @@ -261,6 +271,8 @@ static struct symbol * examine_array_type(struct symbol *sym) bit_size = -1; } } + if (has_flexible_array(base_type) && Wflexible_array_array) + warning(sym->pos, "array of flexible structures"); alignment = base_type->ctype.alignment; if (!sym->ctype.alignment) sym->ctype.alignment = alignment; @@ -185,6 +185,7 @@ struct symbol { examined:1, expanding:1, evaluated:1, + has_flex_array:1, string:1, designated_init:1, forced_arg:1, @@ -509,6 +510,13 @@ static inline int is_extern_inline(struct symbol *sym) is_function(sym->ctype.base_type); } +static inline int has_flexible_array(struct symbol *type) +{ + if (type->type == SYM_NODE) + type = type->ctype.base_type; + return type->has_flex_array; +} + static inline int get_sym_type(struct symbol *type) { if (type->type == SYM_NODE) diff --git a/validation/flex-array-align.c b/validation/flex-array-align.c new file mode 100644 index 00000000..9f28942a --- /dev/null +++ b/validation/flex-array-align.c @@ -0,0 +1,18 @@ +struct s { + __INT32_TYPE__ x; + __INT16_TYPE__ y; + unsigned char f[]; +}; + +static int foo(struct s *s) +{ + return (sizeof(*s) << 16) | __builtin_offsetof(typeof(*s), f); +} + +/* + * check-name: flex-array-align + * check-command: test-linearize -Wno-flexible-array-sizeof $file + * + * check-output-ignore + * check-output-contains: ret\\..*\\$0x80006 + */ diff --git a/validation/flex-array-array.c b/validation/flex-array-array.c new file mode 100644 index 00000000..921a0698 --- /dev/null +++ b/validation/flex-array-array.c @@ -0,0 +1,15 @@ +struct s { + int i; + long f[]; +}; + +static struct s a[2]; + +/* + * check-name: flex-array-array + * check-command: sparse -Wflexible-array-array $file + * + * check-error-start +flex-array-array.c:6:18: warning: array of flexible structures + * check-error-end + */ diff --git a/validation/flex-array-error.c b/validation/flex-array-error.c new file mode 100644 index 00000000..2b7e6953 --- /dev/null +++ b/validation/flex-array-error.c @@ -0,0 +1,26 @@ +struct s { + int i; + long f[]; + int j; +}; + +union u { + int i; + long f[]; +}; + +// trigger the examination of the offending types +static int foo(struct s *s, union u *u) +{ + return __builtin_offsetof(typeof(*s), i) + + __builtin_offsetof(typeof(*u), i); +} + +/* + * check-name: flex-array-error + * + * check-error-start +flex-array-error.c:3:14: error: flexible array member 'f' is not last +flex-array-error.c:9:14: error: flexible array member 'f' in a union + * check-error-end + */ diff --git a/validation/flex-array-nested.c b/validation/flex-array-nested.c new file mode 100644 index 00000000..63767683 --- /dev/null +++ b/validation/flex-array-nested.c @@ -0,0 +1,29 @@ +struct f { + int i; + long f[]; +}; + +struct s { + struct f f; +}; + +union u { + struct f f; +}; + +// trigger the examination of the offending types +static int foo(struct s *s, union u *u) +{ + return __builtin_offsetof(typeof(*s), f) + + __builtin_offsetof(typeof(*u), f); +} + +/* + * check-name: flex-array-nested + * check-command: sparse -Wflexible-array-nested $file + * + * check-error-start +flex-array-nested.c:6:8: warning: nested flexible arrays +flex-array-nested.c:10:7: warning: nested flexible arrays + * check-error-end + */ diff --git a/validation/flex-array-sizeof.c b/validation/flex-array-sizeof.c new file mode 100644 index 00000000..05394e19 --- /dev/null +++ b/validation/flex-array-sizeof.c @@ -0,0 +1,18 @@ +struct s { + int i; + long f[]; +}; + +static int foo(struct s *s) +{ + return sizeof(*s); +} + +/* + * check-name: flex-array-sizeof + * check-command: sparse -Wflexible-array-sizeof $file + * + * check-error-start +flex-array-sizeof.c:8:16: warning: using sizeof on a flexible structure + * check-error-end + */ |