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:
parent
15f4b3b19d
commit
cd2085aae7
7 changed files with 149 additions and 49 deletions
|
|
@ -5,5 +5,8 @@ See the RELEASENOTES file for a summary of changes in each release.
|
|||
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
|
||||
[Lua] Fix for usage of snprintf in Lua runtime which Visual Studio does not have.
|
||||
|
|
|
|||
|
|
@ -580,6 +580,7 @@ C_TEST_CASES += \
|
|||
enums \
|
||||
enum_forward \
|
||||
enum_macro \
|
||||
enum_missing \
|
||||
extern_declaration \
|
||||
funcptr \
|
||||
function_typedef \
|
||||
|
|
|
|||
39
Examples/test-suite/enum_missing.i
Normal file
39
Examples/test-suite/enum_missing.i
Normal 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;
|
||||
}
|
||||
%}
|
||||
|
||||
|
|
@ -3165,25 +3165,37 @@ public:
|
|||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
void substituteClassnameSpecialVariable(SwigType *classnametype, String *tm, const char *classnamespecialvariable) {
|
||||
String *replacementname;
|
||||
if (SwigType_isenum(classnametype)) {
|
||||
String *enumname = getEnumName(classnametype);
|
||||
if (enumname)
|
||||
Replaceall(tm, classnamespecialvariable, enumname);
|
||||
else
|
||||
Replaceall(tm, classnamespecialvariable, NewStringf("int"));
|
||||
if (enumname) {
|
||||
replacementname = Copy(enumname);
|
||||
} else {
|
||||
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 {
|
||||
String *classname = getProxyName(classnametype);
|
||||
String *classname = getProxyName(classnametype); // getProxyName() works for pointers to classes too
|
||||
if (classname) {
|
||||
Replaceall(tm, classnamespecialvariable, classname); // getProxyName() works for pointers to classes too
|
||||
} else { // use $descriptor if SWIG does not know anything about this type. Note that any typedefs are resolved.
|
||||
String *descriptor = NewStringf("SWIGTYPE%s", SwigType_manglestr(classnametype));
|
||||
Replaceall(tm, classnamespecialvariable, descriptor);
|
||||
replacementname = Copy(classname);
|
||||
} else {
|
||||
// use $descriptor if SWIG does not know anything about this type. Note that any typedefs are resolved.
|
||||
replacementname = NewStringf("SWIGTYPE%s", SwigType_manglestr(classnametype));
|
||||
|
||||
// Add to hash table so that the type wrapper classes can be created later
|
||||
Setattr(swig_types_hash, descriptor, classnametype);
|
||||
Delete(descriptor);
|
||||
Setattr(swig_types_hash, replacementname, classnametype);
|
||||
}
|
||||
}
|
||||
Replaceall(tm, classnamespecialvariable, replacementname);
|
||||
|
||||
Delete(replacementname);
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
|
|
@ -3273,6 +3285,9 @@ public:
|
|||
Replaceall(swigtype, "$imclassname", imclass_name);
|
||||
Replaceall(swigtype, "$dllimport", dllimport);
|
||||
|
||||
// For unknown enums
|
||||
Replaceall(swigtype, "$enumvalues", "");
|
||||
|
||||
Printv(f_swigtype, swigtype, NIL);
|
||||
|
||||
addCloseNamespace(0, f_swigtype);
|
||||
|
|
|
|||
|
|
@ -568,8 +568,7 @@ public:
|
|||
writeTypeWrapperClass(swig_type.key, swig_type.item);
|
||||
}
|
||||
|
||||
// Add the proxy functions (and classes, if they are not written to a
|
||||
// seperate file).
|
||||
// Add the proxy functions (and classes, if they are not written to a separate file).
|
||||
replaceModuleVariables(proxy_dmodule_code);
|
||||
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
|
||||
// in D) which retrieves the value via by calling the C wrapper.
|
||||
// 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, "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.
|
||||
*
|
||||
* 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) {
|
||||
String *dmodule = createModuleName(nspace, symname);
|
||||
|
|
@ -4054,10 +4053,10 @@ private:
|
|||
// 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
|
||||
// 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.
|
||||
// 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
|
||||
// working in split proxy module mode, this is not relevant and the
|
||||
// generated module name is discarded.
|
||||
|
|
@ -4066,35 +4065,39 @@ private:
|
|||
if (SwigType_isenum(type)) {
|
||||
// RESEARCH: Make sure that we really cannot get here for anonymous enums.
|
||||
Node *n = enumLookup(type);
|
||||
String *enum_name = Getattr(n, "sym:name");
|
||||
if (n) {
|
||||
String *enum_name = Getattr(n, "sym:name");
|
||||
|
||||
Node *p = parentNode(n);
|
||||
if (p && !Strcmp(nodeType(p), "class")) {
|
||||
// This is a nested enum.
|
||||
String *parent_name = Getattr(p, "sym:name");
|
||||
String *nspace = Getattr(p, "sym:nspace");
|
||||
Node *p = parentNode(n);
|
||||
if (p && !Strcmp(nodeType(p), "class")) {
|
||||
// This is a nested enum.
|
||||
String *parent_name = Getattr(p, "sym:name");
|
||||
String *nspace = Getattr(p, "sym:nspace");
|
||||
|
||||
// An enum nested in a class is not written to a seperate module (this
|
||||
// would not even be possible in D), so just import the parent.
|
||||
requireDType(nspace, parent_name);
|
||||
// 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.
|
||||
requireDType(nspace, parent_name);
|
||||
|
||||
String *module = createModuleName(nspace, parent_name);
|
||||
if (inProxyModule(module)) {
|
||||
type_name = NewStringf("%s.%s", parent_name, enum_name);
|
||||
String *module = createModuleName(nspace, parent_name);
|
||||
if (inProxyModule(module)) {
|
||||
type_name = NewStringf("%s.%s", parent_name, enum_name);
|
||||
} else {
|
||||
type_name = NewStringf("%s%s.%s.%s", package, module, parent_name, enum_name);
|
||||
}
|
||||
} 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 {
|
||||
// A non-nested enum is written to a seperate 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);
|
||||
}
|
||||
type_name = NewStringf("int");
|
||||
}
|
||||
} else {
|
||||
Node *n = classLookup(type);
|
||||
|
|
|
|||
|
|
@ -79,6 +79,9 @@ class GO:public Language {
|
|||
bool making_variable_wrappers;
|
||||
// True when working with a 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
|
||||
// been defined. The index is a SwigType.
|
||||
Hash *undefined_types;
|
||||
|
|
@ -124,6 +127,7 @@ public:
|
|||
class_methods(NULL),
|
||||
making_variable_wrappers(false),
|
||||
is_static_member_function(false),
|
||||
undefined_enum_types(NULL),
|
||||
undefined_types(NULL),
|
||||
defined_types(NULL),
|
||||
go_imports(NULL) {
|
||||
|
|
@ -451,6 +455,7 @@ private:
|
|||
|
||||
// Set up the hash table for types not defined by SWIG.
|
||||
|
||||
undefined_enum_types = NewHash();
|
||||
undefined_types = NewHash();
|
||||
defined_types = NewHash();
|
||||
go_imports = NewHash();
|
||||
|
|
@ -463,6 +468,13 @@ private:
|
|||
|
||||
// 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);
|
||||
for (Iterator p = First(undefined_types); p.key; p = Next(p)) {
|
||||
String *ty = goType(NULL, p.key);
|
||||
|
|
@ -481,6 +493,7 @@ private:
|
|||
}
|
||||
Delete(ty);
|
||||
}
|
||||
Delete(undefined_enum_types);
|
||||
Delete(undefined_types);
|
||||
Delete(defined_types);
|
||||
|
||||
|
|
@ -4494,11 +4507,18 @@ private:
|
|||
|
||||
SwigType *t = SwigType_typedef_resolve_all(type);
|
||||
|
||||
Node *e = Language::enumLookup(t);
|
||||
if (e) {
|
||||
ret = goEnumName(e);
|
||||
} else if (Strcmp(t, "enum ") == 0) {
|
||||
ret = NewString("int");
|
||||
if (SwigType_isenum(t)) {
|
||||
Node *e = Language::enumLookup(t);
|
||||
if (e) {
|
||||
ret = goEnumName(e);
|
||||
} 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)) {
|
||||
ret = NewString("_swig_fnptr");
|
||||
} 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;
|
||||
} else {
|
||||
SwigType *tstripped = SwigType_strip_qualifiers(t);
|
||||
if (SwigType_isenum(tstripped))
|
||||
is_int = true;
|
||||
Delete(tstripped);
|
||||
}
|
||||
|
||||
Delete(t);
|
||||
|
|
|
|||
|
|
@ -3083,10 +3083,19 @@ public:
|
|||
|
||||
if (SwigType_isenum(classnametype)) {
|
||||
String *enumname = getEnumName(classnametype, jnidescriptor);
|
||||
if (enumname)
|
||||
if (enumname) {
|
||||
replacementname = Copy(enumname);
|
||||
else
|
||||
replacementname = NewString("int");
|
||||
} else {
|
||||
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 {
|
||||
String *classname = getProxyName(classnametype, jnidescriptor); // getProxyName() works for pointers to classes too
|
||||
if (classname) {
|
||||
|
|
@ -3186,6 +3195,11 @@ public:
|
|||
Replaceall(swigtype, "$javaclassname", classname);
|
||||
Replaceall(swigtype, "$module", module_class_name);
|
||||
Replaceall(swigtype, "$imclassname", imclass_name);
|
||||
|
||||
// For unknown enums
|
||||
Replaceall(swigtype, "$static ", "");
|
||||
Replaceall(swigtype, "$enumvalues", "");
|
||||
|
||||
Printv(f_swigtype, swigtype, NIL);
|
||||
|
||||
Delete(f_swigtype);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue