From 15b2ec53e33e375d0c8976571087331aa7012817 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 26 Sep 2022 18:14:19 +0100 Subject: [PATCH] Runtime tables deterministic ordering (4) Output C/C++ type strings (| separated) in swig_type_info tables in fixed order. The types are output in alphabetically sorted order, with an exception. The final type is a fully resolved type, but does not necessarily include default template parameters. This type is the one used by SWIG_TypePrettyName which is commonly used to display a type when the wrong type is passed in as a parameter. Previously the order was not very deterministic due to the use of internal hash tables which do not have an ordering guarantee. --- CHANGES.current | 7 ++++++ Lib/swigrun.swg | 6 ++--- Source/Swig/typesys.c | 55 ++++++++++++++++++++++++++++++------------- 3 files changed, 48 insertions(+), 20 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index 2475aa5f4..ac2c2d099 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,13 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2022-09-29: wsfulton + #2303 Type tables are now output in a fixed order whereas previously + the order may change with any minor input code change. This shouldn't + affect users except SWIG_TypePrettyName may output a different C/C++ + typedef to a type - it's used mostly for showing errors when the type + passed to a function is wrong. + 2022-09-29: olly [PHP] Dynamic class properties are no longer supported by default. diff --git a/Lib/swigrun.swg b/Lib/swigrun.swg index 9ec98ccf2..f632c4cb6 100644 --- a/Lib/swigrun.swg +++ b/Lib/swigrun.swg @@ -358,9 +358,9 @@ SWIG_TypeName(const swig_type_info *ty) { SWIGRUNTIME const char * SWIG_TypePrettyName(const swig_type_info *type) { /* The "str" field contains the equivalent pretty names of the - type, separated by vertical-bar characters. We choose - to print the last name, as it is often (?) the most - specific. */ + type, separated by vertical-bar characters. Choose the last + name. It should be the most specific; a fully resolved name + but not necessarily with default template parameters expanded. */ if (!type) return NULL; if (type->str != NULL) { const char *last_name = type->str; diff --git a/Source/Swig/typesys.c b/Source/Swig/typesys.c index f7fc73026..cadceb3eb 100644 --- a/Source/Swig/typesys.c +++ b/Source/Swig/typesys.c @@ -2136,22 +2136,22 @@ void SwigType_emit_type_table(File *f_forward, File *f_table) { /*#define DEBUG 1*/ #ifdef DEBUG Printf(stdout, "---r_mangled---\n"); - Printf(stdout, "%s\n", r_mangled); + Swig_print(r_mangled, 2); Printf(stdout, "---r_resolved---\n"); - Printf(stdout, "%s\n", r_resolved); + Swig_print(r_resolved, 2); Printf(stdout, "---r_ltype---\n"); - Printf(stdout, "%s\n", r_ltype); + Swig_print(r_ltype, 2); Printf(stdout, "---subclass---\n"); - Printf(stdout, "%s\n", subclass); + Swig_print(subclass, 2); Printf(stdout, "---conversions---\n"); - Printf(stdout, "%s\n", conversions); + Swig_print(conversions, 2); Printf(stdout, "---r_clientdata---\n"); - Printf(stdout, "%s\n", r_clientdata); + Swig_print(r_clientdata, 2); #endif table = NewStringEmpty(); @@ -2169,8 +2169,6 @@ void SwigType_emit_type_table(File *f_forward, File *f_table) { for (ki = First(mangled_list); ki.item; ki = Next(ki)) { List *el; Iterator ei; - SwigType *lt; - SwigType *rt = 0; String *nt; String *ln; String *rn; @@ -2179,6 +2177,8 @@ void SwigType_emit_type_table(File *f_forward, File *f_table) { Iterator ltiter; Hash *nthash; String *cast_temp_conv; + String *resolved_lstr = 0; + List *ntlist; cast_temp = NewStringEmpty(); cast_temp_conv = NewStringEmpty(); @@ -2197,8 +2197,8 @@ void SwigType_emit_type_table(File *f_forward, File *f_table) { nthash = NewHash(); ltiter = First(lthash); while (ltiter.key) { - lt = ltiter.key; - rt = SwigType_typedef_resolve_all(lt); + SwigType *lt = ltiter.key; + SwigType *rt = SwigType_typedef_resolve_all(lt); /* we save the original type and the fully resolved version */ ln = SwigType_lstr(lt, 0); rn = SwigType_lstr(rt, 0); @@ -2208,6 +2208,12 @@ void SwigType_emit_type_table(File *f_forward, File *f_table) { Setattr(nthash, rn, "1"); Setattr(nthash, ln, "1"); } + if (!resolved_lstr) { + resolved_lstr = Copy(rn); + } else if (Len(rn) < Len(resolved_lstr)) { + Delete(resolved_lstr); + resolved_lstr = Copy(rn); + } if (SwigType_istemplate(rt)) { String *dt = Swig_symbol_template_deftype(rt, 0); String *dn = SwigType_lstr(dt, 0); @@ -2217,22 +2223,38 @@ void SwigType_emit_type_table(File *f_forward, File *f_table) { Delete(dt); Delete(dn); } + Delete(rt); + Delete(rn); + Delete(ln); ltiter = Next(ltiter); } /* now build nt */ - ltiter = First(nthash); + ntlist = sorted_list_from_hash(nthash); + ltiter = First(ntlist); nt = 0; - while (ltiter.key) { - if (nt) { - Printf(nt, "|%s", ltiter.key); - } else { - nt = NewString(ltiter.key); + while (ltiter.item) { + if (!Equal(resolved_lstr, ltiter.item)) { + if (nt) { + Printf(nt, "|%s", ltiter.item); + } else { + nt = NewString(ltiter.item); + } } ltiter = Next(ltiter); } + /* Last in list is a resolved type used by SWIG_TypePrettyName. + * There can be more than one resolved type and the chosen one is simply the + * shortest in length, arguably the most user friendly/readable. */ + if (nt) { + Printf(nt, "|%s", resolved_lstr); + } else { + nt = NewString(resolved_lstr); + } + Delete(ntlist); Delete(nthash); + Delete(resolved_lstr); Printf(types, "\"%s\", \"%s\", 0, 0, (void*)%s, 0};\n", ki.item, nt, cd); @@ -2265,7 +2287,6 @@ void SwigType_emit_type_table(File *f_forward, File *f_table) { Delete(cast_temp_conv); Delete(cast_temp); Delete(nt); - Delete(rt); } /* print the tables in the proper order */ SortList(table_list, compare_strings);