aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2021-01-23 21:24:02 +0100
committerLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2021-01-23 21:24:02 +0100
commit56dbccf50c2185571f34c3dfaf4753942f6a2372 (patch)
tree12dd19aa3f3683465ee9d20ff93e7a912aaa4dbc
parent98d8b65e122b5180d81a653487a7392e6083d9f3 (diff)
parent817412f75790c3ccae1bf9f23922864c837a9347 (diff)
downloadsparse-56dbccf50c2185571f34c3dfaf4753942f6a2372.tar.gz
Merge branch 'unnamed-qual'
* handle qualified anonymous structures
-rw-r--r--symbol.c28
1 files changed, 28 insertions, 0 deletions
diff --git a/symbol.c b/symbol.c
index aa02c8c5..91352a3a 100644
--- a/symbol.c
+++ b/symbol.c
@@ -25,6 +25,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+#include <assert.h>
#include "lib.h"
#include "allocate.h"
@@ -175,6 +176,31 @@ static void lay_out_struct(struct symbol *sym, struct struct_union_info *info)
// warning (sym->pos, "regular: offset=%d", sym->offset);
}
+///
+// propagate properties of anonymous structs or unions into their members.
+//
+// :note: GCC seems to only propagate the qualifiers.
+// :note: clang doesn't propagate anything at all.
+static void examine_anonymous_member(struct symbol *sym)
+{
+ unsigned long mod = sym->ctype.modifiers & MOD_QUALIFIER;
+ struct symbol *sub;
+
+ if (sym->type == SYM_NODE)
+ sym = sym->ctype.base_type;
+ if (sym->type != SYM_STRUCT && sym->type != SYM_UNION)
+ return;
+
+ FOR_EACH_PTR(sym->symbol_list, sub) {
+ assert(sub->type == SYM_NODE);
+ sub->ctype.modifiers |= mod;
+
+ // if nested, propagate all the way down
+ if (!sub->ident)
+ examine_anonymous_member(sub);
+ } END_FOR_EACH_PTR(sub);
+}
+
static struct symbol * examine_struct_union_type(struct symbol *sym, int advance)
{
struct struct_union_info info = {
@@ -196,6 +222,8 @@ static struct symbol * examine_struct_union_type(struct symbol *sym, int advance
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->ident)
+ examine_anonymous_member(member);
if (member->ctype.alignment > info.max_align && !sym->packed) {
// Unnamed bitfields do not affect alignment.