Fixes for C enums used in an API and the definition of the enum has not been parsed.

For D, this fixes a segfault in SWIG.

Java, C#, D, Go now produce code that compiles, although the definition of the
enum is needed in order to use the enum properly from the target language.
This commit is contained in:
William S Fulton 2014-03-28 07:54:03 +00:00
commit cd2085aae7
7 changed files with 149 additions and 49 deletions

View file

@ -5,5 +5,8 @@ See the RELEASENOTES file for a summary of changes in each release.
Version 3.0.1 (in progress) Version 3.0.1 (in progress)
=========================== ===========================
2014-03-28: wsfulton
[Java C# D Go] Fix for usage of snprintf in Lua runtime which Visual Studio does not have.
2014-03-23: v-for-vandal 2014-03-23: v-for-vandal
[Lua] Fix for usage of snprintf in Lua runtime which Visual Studio does not have. [Lua] Fix for usage of snprintf in Lua runtime which Visual Studio does not have.

View file

@ -580,6 +580,7 @@ C_TEST_CASES += \
enums \ enums \
enum_forward \ enum_forward \
enum_macro \ enum_macro \
enum_missing \
extern_declaration \ extern_declaration \
funcptr \ funcptr \
function_typedef \ function_typedef \

View file

@ -0,0 +1,39 @@
%module enum_missing
// Test when SWIG does not parse the enum definition
%{
enum AVPixelFormat {
AV_PIX_FMT_NONE = -1,
AV_PIX_FMT_YUV420P
};
enum AVPixelFormat2 {
AV_PIX_FMT_NONE2 = -1,
AV_PIX_FMT_YUV420P2
};
%}
%inline %{
typedef struct AVCodecContext {
enum AVPixelFormat pix_fmt;
enum AVPixelFormat2 pix_fmt2;
} AVCodecContext;
enum AVPixelFormat global_fmt;
enum AVPixelFormat2 global_fmt2;
enum AVPixelFormat use_pixel_format(enum AVPixelFormat px) {
return px;
}
enum AVPixelFormat * use_pixel_format_ptr(enum AVPixelFormat *px) {
return px;
}
const enum AVPixelFormat2 use_pixel_format2(const enum AVPixelFormat2 px) {
return px;
}
const enum AVPixelFormat2 * use_pixel_format_ptr2(const enum AVPixelFormat2 *px) {
return px;
}
%}

View file

@ -3165,25 +3165,37 @@ public:
* ----------------------------------------------------------------------------- */ * ----------------------------------------------------------------------------- */
void substituteClassnameSpecialVariable(SwigType *classnametype, String *tm, const char *classnamespecialvariable) { void substituteClassnameSpecialVariable(SwigType *classnametype, String *tm, const char *classnamespecialvariable) {
String *replacementname;
if (SwigType_isenum(classnametype)) { if (SwigType_isenum(classnametype)) {
String *enumname = getEnumName(classnametype); String *enumname = getEnumName(classnametype);
if (enumname) if (enumname) {
Replaceall(tm, classnamespecialvariable, enumname); replacementname = Copy(enumname);
else } else {
Replaceall(tm, classnamespecialvariable, NewStringf("int")); bool anonymous_enum = (Cmp(classnametype, "enum ") == 0);
if (anonymous_enum) {
replacementname = NewString("int");
} else {
// An unknown enum - one that has not been parsed (neither a C enum forward reference nor a definition)
replacementname = SwigType_base(classnametype);
Replace(replacementname, "enum ", "", DOH_REPLACE_ANY);
Setattr(swig_types_hash, replacementname, classnametype);
}
}
} else { } else {
String *classname = getProxyName(classnametype); String *classname = getProxyName(classnametype); // getProxyName() works for pointers to classes too
if (classname) { if (classname) {
Replaceall(tm, classnamespecialvariable, classname); // getProxyName() works for pointers to classes too replacementname = Copy(classname);
} else { // use $descriptor if SWIG does not know anything about this type. Note that any typedefs are resolved. } else {
String *descriptor = NewStringf("SWIGTYPE%s", SwigType_manglestr(classnametype)); // use $descriptor if SWIG does not know anything about this type. Note that any typedefs are resolved.
Replaceall(tm, classnamespecialvariable, descriptor); replacementname = NewStringf("SWIGTYPE%s", SwigType_manglestr(classnametype));
// Add to hash table so that the type wrapper classes can be created later // Add to hash table so that the type wrapper classes can be created later
Setattr(swig_types_hash, descriptor, classnametype); Setattr(swig_types_hash, replacementname, classnametype);
Delete(descriptor);
} }
} }
Replaceall(tm, classnamespecialvariable, replacementname);
Delete(replacementname);
} }
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
@ -3273,6 +3285,9 @@ public:
Replaceall(swigtype, "$imclassname", imclass_name); Replaceall(swigtype, "$imclassname", imclass_name);
Replaceall(swigtype, "$dllimport", dllimport); Replaceall(swigtype, "$dllimport", dllimport);
// For unknown enums
Replaceall(swigtype, "$enumvalues", "");
Printv(f_swigtype, swigtype, NIL); Printv(f_swigtype, swigtype, NIL);
addCloseNamespace(0, f_swigtype); addCloseNamespace(0, f_swigtype);

View file

@ -568,8 +568,7 @@ public:
writeTypeWrapperClass(swig_type.key, swig_type.item); writeTypeWrapperClass(swig_type.key, swig_type.item);
} }
// Add the proxy functions (and classes, if they are not written to a // Add the proxy functions (and classes, if they are not written to a separate file).
// seperate file).
replaceModuleVariables(proxy_dmodule_code); replaceModuleVariables(proxy_dmodule_code);
Printv(proxy_d_file, proxy_dmodule_code, NIL); Printv(proxy_d_file, proxy_dmodule_code, NIL);
@ -1399,7 +1398,7 @@ public:
// generates a getter function (which is the same as a read only property // generates a getter function (which is the same as a read only property
// in D) which retrieves the value via by calling the C wrapper. // in D) which retrieves the value via by calling the C wrapper.
// Note that this is only called for global constants, static member // Note that this is only called for global constants, static member
// constants are already handeled in staticmemberfunctionHandler(). // constants are already handled in staticmemberfunctionHandler().
Swig_save("constantWrapper", n, "value", NIL); Swig_save("constantWrapper", n, "value", NIL);
Swig_save("constantWrapper", n, "tmap:ctype:out", "tmap:imtype:out", "tmap:dtype:out", "tmap:out:null", "tmap:imtype:outattributes", "tmap:dtype:outattributes", NIL); Swig_save("constantWrapper", n, "tmap:ctype:out", "tmap:imtype:out", "tmap:dtype:out", "tmap:out:null", "tmap:imtype:outattributes", "tmap:dtype:outattributes", NIL);
@ -3602,7 +3601,7 @@ private:
* package if one is set. * package if one is set.
* *
* This is only used for dependencies created in generated code, user- * This is only used for dependencies created in generated code, user-
* (i.e. typemap-) specified import statements are handeled seperately. * (i.e. typemap-) specified import statements are handled separately.
* --------------------------------------------------------------------------- */ * --------------------------------------------------------------------------- */
void requireDType(const String *nspace, const String *symname) { void requireDType(const String *nspace, const String *symname) {
String *dmodule = createModuleName(nspace, symname); String *dmodule = createModuleName(nspace, symname);
@ -4054,10 +4053,10 @@ private:
// TODO: Fix const-correctness of methods called in here and make type const. // TODO: Fix const-correctness of methods called in here and make type const.
// We make use of the fact that this function is called at least once for // We make use of the fact that this function is called at least once for
// every type encountered which is written to a seperate file, which allows // every type encountered which is written to a separate file, which allows
// us to handle imports here. // us to handle imports here.
// When working in split proxy module mode, each generated proxy class/enum // When working in split proxy module mode, each generated proxy class/enum
// is written to a seperate module. This requires us to add a corresponding // is written to a separate module. This requires us to add a corresponding
// import when a type is used in another generated module. If we are not // import when a type is used in another generated module. If we are not
// working in split proxy module mode, this is not relevant and the // working in split proxy module mode, this is not relevant and the
// generated module name is discarded. // generated module name is discarded.
@ -4066,35 +4065,39 @@ private:
if (SwigType_isenum(type)) { if (SwigType_isenum(type)) {
// RESEARCH: Make sure that we really cannot get here for anonymous enums. // RESEARCH: Make sure that we really cannot get here for anonymous enums.
Node *n = enumLookup(type); Node *n = enumLookup(type);
String *enum_name = Getattr(n, "sym:name"); if (n) {
String *enum_name = Getattr(n, "sym:name");
Node *p = parentNode(n); Node *p = parentNode(n);
if (p && !Strcmp(nodeType(p), "class")) { if (p && !Strcmp(nodeType(p), "class")) {
// This is a nested enum. // This is a nested enum.
String *parent_name = Getattr(p, "sym:name"); String *parent_name = Getattr(p, "sym:name");
String *nspace = Getattr(p, "sym:nspace"); String *nspace = Getattr(p, "sym:nspace");
// An enum nested in a class is not written to a seperate module (this // An enum nested in a class is not written to a separate module (this
// would not even be possible in D), so just import the parent. // would not even be possible in D), so just import the parent.
requireDType(nspace, parent_name); requireDType(nspace, parent_name);
String *module = createModuleName(nspace, parent_name); String *module = createModuleName(nspace, parent_name);
if (inProxyModule(module)) { if (inProxyModule(module)) {
type_name = NewStringf("%s.%s", parent_name, enum_name); type_name = NewStringf("%s.%s", parent_name, enum_name);
} else {
type_name = NewStringf("%s%s.%s.%s", package, module, parent_name, enum_name);
}
} else { } else {
type_name = NewStringf("%s%s.%s.%s", package, module, parent_name, enum_name); // A non-nested enum is written to a separate module, import it.
String *nspace = Getattr(n, "sym:nspace");
requireDType(nspace, enum_name);
String *module = createModuleName(nspace, enum_name);
if (inProxyModule(module)) {
type_name = Copy(enum_name);
} else {
type_name = NewStringf("%s%s.%s", package, module, enum_name);
}
} }
} else { } else {
// A non-nested enum is written to a seperate module, import it. type_name = NewStringf("int");
String *nspace = Getattr(n, "sym:nspace");
requireDType(nspace, enum_name);
String *module = createModuleName(nspace, enum_name);
if (inProxyModule(module)) {
type_name = Copy(enum_name);
} else {
type_name = NewStringf("%s%s.%s", package, module, enum_name);
}
} }
} else { } else {
Node *n = classLookup(type); Node *n = classLookup(type);

View file

@ -79,6 +79,9 @@ class GO:public Language {
bool making_variable_wrappers; bool making_variable_wrappers;
// True when working with a static member function. // True when working with a static member function.
bool is_static_member_function; bool is_static_member_function;
// A hash table of enum types that we have seen but which may not have
// been defined. The index is a SwigType.
Hash *undefined_enum_types;
// A hash table of types that we have seen but which may not have // A hash table of types that we have seen but which may not have
// been defined. The index is a SwigType. // been defined. The index is a SwigType.
Hash *undefined_types; Hash *undefined_types;
@ -124,6 +127,7 @@ public:
class_methods(NULL), class_methods(NULL),
making_variable_wrappers(false), making_variable_wrappers(false),
is_static_member_function(false), is_static_member_function(false),
undefined_enum_types(NULL),
undefined_types(NULL), undefined_types(NULL),
defined_types(NULL), defined_types(NULL),
go_imports(NULL) { go_imports(NULL) {
@ -451,6 +455,7 @@ private:
// Set up the hash table for types not defined by SWIG. // Set up the hash table for types not defined by SWIG.
undefined_enum_types = NewHash();
undefined_types = NewHash(); undefined_types = NewHash();
defined_types = NewHash(); defined_types = NewHash();
go_imports = NewHash(); go_imports = NewHash();
@ -463,6 +468,13 @@ private:
// Write out definitions for the types not defined by SWIG. // Write out definitions for the types not defined by SWIG.
if (Len(undefined_enum_types) > 0)
Printv(f_go_wrappers, "\n", NULL);
for (Iterator p = First(undefined_enum_types); p.key; p = Next(p)) {
String *name = p.item;
Printv(f_go_wrappers, "type ", name, " int\n", NULL);
}
Printv(f_go_wrappers, "\n", NULL); Printv(f_go_wrappers, "\n", NULL);
for (Iterator p = First(undefined_types); p.key; p = Next(p)) { for (Iterator p = First(undefined_types); p.key; p = Next(p)) {
String *ty = goType(NULL, p.key); String *ty = goType(NULL, p.key);
@ -481,6 +493,7 @@ private:
} }
Delete(ty); Delete(ty);
} }
Delete(undefined_enum_types);
Delete(undefined_types); Delete(undefined_types);
Delete(defined_types); Delete(defined_types);
@ -4494,11 +4507,18 @@ private:
SwigType *t = SwigType_typedef_resolve_all(type); SwigType *t = SwigType_typedef_resolve_all(type);
Node *e = Language::enumLookup(t); if (SwigType_isenum(t)) {
if (e) { Node *e = Language::enumLookup(t);
ret = goEnumName(e); if (e) {
} else if (Strcmp(t, "enum ") == 0) { ret = goEnumName(e);
ret = NewString("int"); } else if (Strcmp(t, "enum ") == 0) {
ret = NewString("int");
} else {
// An unknown enum - one that has not been parsed (neither a C enum forward reference nor a definition)
ret = SwigType_base(t);
Replace(ret, "enum ", "", DOH_REPLACE_ANY);
Setattr(undefined_enum_types, t, ret);
}
} else if (SwigType_isfunctionpointer(type) || SwigType_isfunction(type)) { } else if (SwigType_isfunctionpointer(type) || SwigType_isfunction(type)) {
ret = NewString("_swig_fnptr"); ret = NewString("_swig_fnptr");
} else if (SwigType_ismemberpointer(type)) { } else if (SwigType_ismemberpointer(type)) {
@ -4809,8 +4829,13 @@ private:
} }
} }
if (Language::enumLookup(t) != NULL || Strcmp(t, "enum ") == 0) { if (Language::enumLookup(t) != NULL) {
is_int = true; is_int = true;
} else {
SwigType *tstripped = SwigType_strip_qualifiers(t);
if (SwigType_isenum(tstripped))
is_int = true;
Delete(tstripped);
} }
Delete(t); Delete(t);

View file

@ -3083,10 +3083,19 @@ public:
if (SwigType_isenum(classnametype)) { if (SwigType_isenum(classnametype)) {
String *enumname = getEnumName(classnametype, jnidescriptor); String *enumname = getEnumName(classnametype, jnidescriptor);
if (enumname) if (enumname) {
replacementname = Copy(enumname); replacementname = Copy(enumname);
else } else {
replacementname = NewString("int"); bool anonymous_enum = (Cmp(classnametype, "enum ") == 0);
if (anonymous_enum) {
replacementname = NewString("int");
} else {
// An unknown enum - one that has not been parsed (neither a C enum forward reference nor a definition)
replacementname = SwigType_base(classnametype);
Replace(replacementname, "enum ", "", DOH_REPLACE_ANY);
Setattr(swig_types_hash, replacementname, classnametype);
}
}
} else { } else {
String *classname = getProxyName(classnametype, jnidescriptor); // getProxyName() works for pointers to classes too String *classname = getProxyName(classnametype, jnidescriptor); // getProxyName() works for pointers to classes too
if (classname) { if (classname) {
@ -3186,6 +3195,11 @@ public:
Replaceall(swigtype, "$javaclassname", classname); Replaceall(swigtype, "$javaclassname", classname);
Replaceall(swigtype, "$module", module_class_name); Replaceall(swigtype, "$module", module_class_name);
Replaceall(swigtype, "$imclassname", imclass_name); Replaceall(swigtype, "$imclassname", imclass_name);
// For unknown enums
Replaceall(swigtype, "$static ", "");
Replaceall(swigtype, "$enumvalues", "");
Printv(f_swigtype, swigtype, NIL); Printv(f_swigtype, swigtype, NIL);
Delete(f_swigtype); Delete(f_swigtype);