From 16f23458bce22958e27176ca64f8df57c985cb1a Mon Sep 17 00:00:00 2001 From: Mike Pall Date: Thu, 15 Nov 2012 00:21:01 +0100 Subject: [PATCH] FFI: Change priority of table initializer variants for structs. --- doc/ext_ffi_semantics.html | 14 +++++++------- src/lj_cconv.c | 5 +++-- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/doc/ext_ffi_semantics.html b/doc/ext_ffi_semantics.html index bf9f9bee..30aa9648 100644 --- a/doc/ext_ffi_semantics.html +++ b/doc/ext_ffi_semantics.html @@ -517,17 +517,17 @@ A VLA is only initialized with the element(s) given in the table. Depending on the use case, you may need to explicitly add a NULL or 0 terminator to a VLA. -
  • If the table has a non-empty hash part, a -struct/union is initialized by looking up each field -name (as a string key) in the table. Each non-nil value is -used to initialize the corresponding field.
  • - -
  • Otherwise a struct/union is initialized in the +
  • A struct/union can be initialized in the order of the declaration of its fields. Each field is initialized with -the consecutive table elements, starting at either index [0] +consecutive table elements, starting at either index [0] or [1]. This process stops at the first nil table element.
  • +
  • Otherwise, if neither index [0] nor [1] is present, +a struct/union is initialized by looking up each field +name (as a string key) in the table. Each non-nil value is +used to initialize the corresponding field.
  • +
  • Uninitialized fields of a struct are filled with zero bytes, except for the trailing VLA of a VLS.
  • diff --git a/src/lj_cconv.c b/src/lj_cconv.c index b81b4e90..7b32e35d 100644 --- a/src/lj_cconv.c +++ b/src/lj_cconv.c @@ -493,17 +493,19 @@ static void cconv_substruct_tab(CTState *cts, CType *d, uint8_t *dp, id = df->sib; if (ctype_isfield(df->info) || ctype_isbitfield(df->info)) { TValue *tv; - int32_t i = *ip; + int32_t i = *ip, iz = i; if (!gcref(df->name)) continue; /* Ignore unnamed fields. */ if (i >= 0) { retry: tv = (TValue *)lj_tab_getint(t, i); if (!tv || tvisnil(tv)) { if (i == 0) { i = 1; goto retry; } /* 1-based tables. */ + if (iz == 0) { *ip = i = -1; goto tryname; } /* Init named fields. */ break; /* Stop at first nil. */ } *ip = i + 1; } else { + tryname: tv = (TValue *)lj_tab_getstr(t, gco2str(gcref(df->name))); if (!tv || tvisnil(tv)) continue; } @@ -524,7 +526,6 @@ static void cconv_struct_tab(CTState *cts, CType *d, { int32_t i = 0; memset(dp, 0, d->size); /* Much simpler to clear the struct first. */ - if (t->hmask) i = -1; else if (t->asize == 0) return; /* Fast exit. */ cconv_substruct_tab(cts, d, dp, t, &i, flags); }