Browse Source

FFI: Change priority of table initializer variants for structs.

Mike Pall 12 years ago
parent
commit
16f23458bc
2 changed files with 10 additions and 9 deletions
  1. 7 7
      doc/ext_ffi_semantics.html
  2. 3 2
      src/lj_cconv.c

+ 7 - 7
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
 <tt>NULL</tt> or <tt>0</tt> terminator to a VLA.</li>
 
-<li>If the table has a non-empty hash part, a
-<tt>struct</tt>/<tt>union</tt> is initialized by looking up each field
-name (as a string key) in the table. Each non-<tt>nil</tt> value is
-used to initialize the corresponding field.</li>
-
-<li>Otherwise a <tt>struct</tt>/<tt>union</tt> is initialized in the
+<li>A <tt>struct</tt>/<tt>union</tt> 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 <tt>[0]</tt>
+consecutive table elements, starting at either index <tt>[0]</tt>
 or <tt>[1]</tt>. This process stops at the first <tt>nil</tt> table
 element.</li>
 
+<li>Otherwise, if neither index <tt>[0]</tt> nor <tt>[1]</tt> is present,
+a <tt>struct</tt>/<tt>union</tt> is initialized by looking up each field
+name (as a string key) in the table. Each non-<tt>nil</tt> value is
+used to initialize the corresponding field.</li>
+
 <li>Uninitialized fields of a <tt>struct</tt> are filled with zero
 bytes, except for the trailing VLA of a VLS.</li>
 

+ 3 - 2
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);
 }