Merge branch 'alexey-pelykh-cpp11_strongly_typed_enums__direct_inject_in_java'
* alexey-pelykh-cpp11_strongly_typed_enums__direct_inject_in_java: Enhance cpp11_strongly_typed_enumerations testcase and turn it on Simplify/improve strongly typed enum implementation for Java Rewrite some Java director nested class support code for strongly typed enums Expand director_nested_class test to test more than one level of nesting Add director_nested_class testcase Removed useless code (it does not affect output, at least on our testcases) Java/Fix: swig_connect_director used not-fully-qualified classname (proper) Java/Fix: swig_connect_director used not-fully-qualified classname Java: fix generation of ProxyName when JNI descriptor is requested - for inner classes '$' should be used as separator instead of '/' Java: fix invalid director 'self' variable type name (wasn't fully qualified) Clean-up test suite and fix issue with nspace, as well as keep the fix for Class::Struct::EnumClass being JNI-referenced as Struct_EnumClass C++11 strongly-typed enums fix for Java only (proper) Revert "C++11 strongly-typed enums fix for Java only" Additional test cases for C++11 strongly-typed enums C++11 strongly-typed enums fix for Java only
This commit is contained in:
commit
296d45aec5
7 changed files with 245 additions and 34 deletions
|
|
@ -527,6 +527,7 @@ CPP11_TEST_CASES = \
|
|||
cpp11_rvalue_reference3 \
|
||||
cpp11_sizeof_object \
|
||||
cpp11_static_assert \
|
||||
cpp11_strongly_typed_enumerations \
|
||||
cpp11_thread_local \
|
||||
cpp11_template_double_brackets \
|
||||
cpp11_template_explicit \
|
||||
|
|
@ -539,7 +540,6 @@ CPP11_TEST_CASES = \
|
|||
# Broken C++11 test cases.
|
||||
CPP11_TEST_BROKEN = \
|
||||
# cpp11_hash_tables \ # not fully implemented yet
|
||||
# cpp11_strongly_typed_enumerations \ # SWIG not quite getting this right yet in all langs
|
||||
# cpp11_variadic_templates \ # Broken for some languages (such as Java)
|
||||
# cpp11_reference_wrapper \ # No typemaps
|
||||
|
||||
|
|
|
|||
|
|
@ -2,10 +2,6 @@
|
|||
strongly typed enums. Enums with the same type are comparable. Enum classes
|
||||
require support for nested classes. */
|
||||
%module cpp11_strongly_typed_enumerations
|
||||
%warnfilter(302) Val1;
|
||||
%warnfilter(302) Val2;
|
||||
%warnfilter(302) Val3;
|
||||
%warnfilter(302) Val4;
|
||||
|
||||
/* Forward declarations (illegally accepted by SWIG - oh well!) */
|
||||
enum Enum1 : short;
|
||||
|
|
@ -17,14 +13,14 @@ enum : unsigned short;
|
|||
enum class Enum1 {
|
||||
Val1,
|
||||
Val2,
|
||||
Val3 = 100,
|
||||
Val4 /* = 101 */
|
||||
Val3 = 13,
|
||||
Val4
|
||||
};
|
||||
|
||||
enum class Enum2 : short {
|
||||
Val1,
|
||||
Val2,
|
||||
Val3 = 100,
|
||||
Val3 = 23,
|
||||
Val4
|
||||
};
|
||||
%}
|
||||
|
|
@ -39,24 +35,24 @@ enum class Enum5; // Legal in C++11, because enum class declarati
|
|||
enum class Enum6 : unsigned int; // Legal C++11.
|
||||
|
||||
enum Enum4 : unsigned int {
|
||||
Val1, Val2, Val3 = 100, Val4
|
||||
Val1, Val2, Val3 = 43, Val4
|
||||
};
|
||||
|
||||
enum class Enum5 {
|
||||
Val1, Val2, Val3 = 100, Val4
|
||||
Val1, Val2, Val3 = 53, Val4
|
||||
};
|
||||
|
||||
enum class Enum6 : unsigned int {
|
||||
Val1, Val2, Val3 = 300, Val4
|
||||
Val1, Val2, Val3 = 63, Val4
|
||||
};
|
||||
|
||||
typedef enum class Enum7 : unsigned int {
|
||||
Val1, Val2, Val3 = 300, Val4
|
||||
Val1, Val2, Val3 = 73, Val4
|
||||
} Enum7td;
|
||||
|
||||
// enum inherits from non-primitive type
|
||||
enum class Enum8 : size_t {
|
||||
Val1, Val2, Val3 = 300, Val4
|
||||
Val1, Val2, Val3 = 83, Val4
|
||||
};
|
||||
|
||||
template <typename T> struct TType {
|
||||
|
|
@ -64,7 +60,7 @@ template <typename T> struct TType {
|
|||
};
|
||||
|
||||
enum class Enum10 : TType<int>::type_name {
|
||||
Val1, Val2, Val3 = 300, Val4
|
||||
Val1, Val2, Val3 = 103, Val4
|
||||
};
|
||||
|
||||
// forward declaration, no definition of enum
|
||||
|
|
@ -73,6 +69,116 @@ struct UseEnum11 {
|
|||
Enum11 myenum11;
|
||||
};
|
||||
|
||||
class Class1
|
||||
{
|
||||
public:
|
||||
enum class Enum12
|
||||
{
|
||||
Val1 = 1121,
|
||||
Val2 = 1122,
|
||||
Val3,
|
||||
Val4
|
||||
};
|
||||
|
||||
enum Enum13
|
||||
{
|
||||
Val1 = 1131,
|
||||
Val2 = 1132,
|
||||
Val3,
|
||||
Val4
|
||||
};
|
||||
|
||||
enum class Enum14
|
||||
{
|
||||
Val1 = 1141,
|
||||
Val2 = 1142,
|
||||
Val3,
|
||||
Val4
|
||||
};
|
||||
|
||||
struct Struct1
|
||||
{
|
||||
enum class Enum12
|
||||
{
|
||||
Val1 = 3121,
|
||||
Val2 = 3122,
|
||||
Val3,
|
||||
Val4
|
||||
};
|
||||
|
||||
enum Enum13
|
||||
{
|
||||
Val1 = 3131,
|
||||
Val2 = 3132,
|
||||
Val3,
|
||||
Val4
|
||||
};
|
||||
|
||||
enum class Enum14
|
||||
{
|
||||
Val1 = 3141,
|
||||
Val2 = 3142,
|
||||
Val3,
|
||||
Val4
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
class Class2
|
||||
{
|
||||
public:
|
||||
enum class Enum12
|
||||
{
|
||||
Val1 = 2121,
|
||||
Val2 = 2122,
|
||||
Val3,
|
||||
Val4
|
||||
};
|
||||
|
||||
enum Enum13
|
||||
{
|
||||
Val1 = 2131,
|
||||
Val2 = 2132,
|
||||
Val3,
|
||||
Val4
|
||||
};
|
||||
|
||||
enum class Enum14
|
||||
{
|
||||
Val1 = 2141,
|
||||
Val2 = 2142,
|
||||
Val3,
|
||||
Val4
|
||||
};
|
||||
|
||||
struct Struct1
|
||||
{
|
||||
enum class Enum12
|
||||
{
|
||||
Val1 = 4121,
|
||||
Val2 = 4122,
|
||||
Val3,
|
||||
Val4
|
||||
};
|
||||
|
||||
enum Enum13
|
||||
{
|
||||
Val1 = 4131,
|
||||
Val2 = 4132,
|
||||
Val3,
|
||||
Val4
|
||||
};
|
||||
|
||||
enum class Enum14
|
||||
{
|
||||
Val1 = 4141,
|
||||
Val2 = 4142,
|
||||
Val3,
|
||||
Val4
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
TODO
|
||||
enum class MyClass {AAA, BBB, CCC};
|
||||
|
|
|
|||
25
Examples/test-suite/director_nested_class.i
Normal file
25
Examples/test-suite/director_nested_class.i
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
%module(directors="1") director_nested_class
|
||||
|
||||
|
||||
%feature("director") DirectorOuter::DirectorInner;
|
||||
%feature("director") DirectorOuter::DirectorInner::DirectorInnerInner;
|
||||
|
||||
%inline %{
|
||||
struct DirectorOuter {
|
||||
struct DirectorInner {
|
||||
virtual ~DirectorInner() {}
|
||||
virtual int vmethod(int input) const = 0;
|
||||
struct DirectorInnerInner {
|
||||
DirectorInnerInner(DirectorInner *din = 0) {}
|
||||
virtual ~DirectorInnerInner() {}
|
||||
virtual int innervmethod(int input) const = 0;
|
||||
};
|
||||
};
|
||||
static int callMethod(const DirectorInner &di, int value) {
|
||||
return di.vmethod(value);
|
||||
}
|
||||
static int callInnerInnerMethod(const DirectorInner::DirectorInnerInner &di, int value) {
|
||||
return di.innervmethod(value);
|
||||
}
|
||||
};
|
||||
%}
|
||||
41
Examples/test-suite/java/director_nested_class_runme.java
Normal file
41
Examples/test-suite/java/director_nested_class_runme.java
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
|
||||
import director_nested_class.*;
|
||||
|
||||
public class director_nested_class_runme {
|
||||
|
||||
static {
|
||||
try {
|
||||
System.loadLibrary("director_nested_class");
|
||||
} catch (UnsatisfiedLinkError e) {
|
||||
System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e);
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String argv[]) {
|
||||
|
||||
director_nested_class_Derived d = new director_nested_class_Derived();
|
||||
|
||||
if (DirectorOuter.callMethod(d, 999) != 9990) {
|
||||
throw new RuntimeException("callMethod(999) failed");
|
||||
}
|
||||
|
||||
director_nested_class_DerivedInnerInner dinner = new director_nested_class_DerivedInnerInner();
|
||||
|
||||
if (DirectorOuter.callInnerInnerMethod(dinner, 999) != 999000) {
|
||||
throw new RuntimeException("callMethod(999) failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class director_nested_class_Derived extends DirectorOuter.DirectorInner {
|
||||
public int vmethod(int input) {
|
||||
return input * 10;
|
||||
}
|
||||
}
|
||||
|
||||
class director_nested_class_DerivedInnerInner extends DirectorOuter.DirectorInner.DirectorInnerInner {
|
||||
public int innervmethod(int input) {
|
||||
return input * 1000;
|
||||
}
|
||||
}
|
||||
|
|
@ -209,7 +209,7 @@ public:
|
|||
String *symname = Copy(Getattr(n, "sym:name"));
|
||||
if (symname && !GetFlag(n, "feature:flatnested")) {
|
||||
for (Node *outer_class = Getattr(n, "nested:outer"); outer_class; outer_class = Getattr(outer_class, "nested:outer")) {
|
||||
Push(symname, ".");
|
||||
Push(symname, jnidescriptor ? "$" : ".");
|
||||
Push(symname, Getattr(outer_class, "sym:name"));
|
||||
}
|
||||
}
|
||||
|
|
@ -838,7 +838,7 @@ public:
|
|||
bool is_destructor = (Cmp(Getattr(n, "nodeType"), "destructor") == 0);
|
||||
|
||||
if (!Getattr(n, "sym:overloaded")) {
|
||||
if (!addSymbol(Getattr(n, "sym:name"), n, imclass_name))
|
||||
if (!addSymbol(symname, n, imclass_name))
|
||||
return SWIG_ERROR;
|
||||
}
|
||||
|
||||
|
|
@ -2959,6 +2959,16 @@ public:
|
|||
// Use the C syntax to make a true Java constant and hope that it compiles as Java code
|
||||
value = Getattr(n, "enumvalue") ? Copy(Getattr(n, "enumvalue")) : Copy(Getattr(n, "enumvalueex"));
|
||||
} else {
|
||||
String *newsymname = 0;
|
||||
if (!getCurrentClass() || !proxy_flag) {
|
||||
String *enumClassPrefix = getEnumClassPrefix();
|
||||
if (enumClassPrefix) {
|
||||
// A global scoped enum
|
||||
newsymname = Swig_name_member(0, enumClassPrefix, symname);
|
||||
symname = newsymname;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the enumvalue from a JNI call
|
||||
if (!getCurrentClass() || !cparse_cplusplus || !proxy_flag) {
|
||||
// Strange hack to change the name
|
||||
|
|
@ -2967,8 +2977,9 @@ public:
|
|||
value = NewStringf("%s.%s()", full_imclass_name ? full_imclass_name : imclass_name, Swig_name_get(getNSpace(), symname));
|
||||
} else {
|
||||
memberconstantHandler(n);
|
||||
value = NewStringf("%s.%s()", full_imclass_name ? full_imclass_name : imclass_name, Swig_name_get(getNSpace(), Swig_name_member(0, proxy_class_name, symname)));
|
||||
value = NewStringf("%s.%s()", full_imclass_name ? full_imclass_name : imclass_name, Swig_name_get(getNSpace(), Swig_name_member(0, getEnumClassPrefix(), symname)));
|
||||
}
|
||||
Delete(newsymname);
|
||||
}
|
||||
}
|
||||
return value;
|
||||
|
|
@ -3632,7 +3643,6 @@ public:
|
|||
* --------------------------------------------------------------- */
|
||||
|
||||
int classDirectorMethod(Node *n, Node *parent, String *super) {
|
||||
String *classname = Getattr(parent, "sym:name");
|
||||
String *c_classname = Getattr(parent, "name");
|
||||
String *name = Getattr(n, "name");
|
||||
String *symname = Getattr(n, "sym:name");
|
||||
|
|
@ -3666,14 +3676,7 @@ public:
|
|||
String *imcall_args = NewString("");
|
||||
int classmeth_off = curr_class_dmethod - first_class_dmethod;
|
||||
bool ignored_method = GetFlag(n, "feature:ignore") ? true : false;
|
||||
String *qualified_classname = Copy(classname);
|
||||
String *nspace = getNSpace();
|
||||
|
||||
if (nspace && package)
|
||||
Insert(qualified_classname, 0, NewStringf("%s.%s.", package, nspace));
|
||||
else if(nspace)
|
||||
Insert(qualified_classname, 0, NewStringf("%s.", nspace));
|
||||
|
||||
String *qualified_classname = getProxyName(getClassName());
|
||||
|
||||
// Kludge Alert: functionWrapper sets sym:overload properly, but it
|
||||
// isn't at this point, so we have to manufacture it ourselves. At least
|
||||
|
|
@ -3796,7 +3799,6 @@ public:
|
|||
}
|
||||
|
||||
Delete(adjustedreturntypeparm);
|
||||
Delete(qualified_classname);
|
||||
|
||||
Swig_director_parms_fixup(l);
|
||||
|
||||
|
|
@ -4437,18 +4439,15 @@ public:
|
|||
* ------------------------------------------------------------ */
|
||||
|
||||
int classDirectorEnd(Node *n) {
|
||||
String *classname = Getattr(n, "sym:name");
|
||||
String *full_classname = Getattr(n, "name");
|
||||
String *classname = getProxyName(full_classname, true);
|
||||
String *director_classname = directorClassName(n);
|
||||
String *internal_classname;
|
||||
|
||||
Wrapper *w = NewWrapper();
|
||||
|
||||
if (Len(package_path) > 0 && Len(getNSpace()) > 0)
|
||||
internal_classname = NewStringf("%s/%s/%s", package_path, getNSpace(), classname);
|
||||
else if (Len(package_path) > 0)
|
||||
if (Len(package_path) > 0)
|
||||
internal_classname = NewStringf("%s/%s", package_path, classname);
|
||||
else if (Len(getNSpace()) > 0)
|
||||
internal_classname = NewStringf("%s/%s", getNSpace(), classname);
|
||||
else
|
||||
internal_classname = NewStringf("%s", classname);
|
||||
|
||||
|
|
|
|||
|
|
@ -57,7 +57,9 @@ extern "C" {
|
|||
/* Some status variables used during parsing */
|
||||
static int InClass = 0; /* Parsing C++ or not */
|
||||
static String *ClassName = 0; /* This is the real name of the current class */
|
||||
static String *EnumClassName = 0; /* Enum class name */
|
||||
static String *ClassPrefix = 0; /* Class prefix */
|
||||
static String *EnumClassPrefix = 0; /* Prefix for strongly typed enums (including ClassPrefix) */
|
||||
static String *NSpace = 0; /* Namespace for the nspace feature */
|
||||
static String *ClassType = 0; /* Fully qualified type name to use */
|
||||
static String *DirectorClassName = 0; /* Director name of the current class */
|
||||
|
|
@ -1650,10 +1652,24 @@ int Language::enumDeclaration(Node *n) {
|
|||
String *oldNSpace = NSpace;
|
||||
NSpace = Getattr(n, "sym:nspace");
|
||||
|
||||
String *oldEnumClassPrefix = EnumClassPrefix;
|
||||
if (GetFlag(n, "scopedenum")) {
|
||||
assert(Getattr(n, "sym:name"));
|
||||
assert(Getattr(n, "name"));
|
||||
EnumClassPrefix = ClassPrefix ? NewStringf("%s_", ClassPrefix) : NewString("");
|
||||
Printv(EnumClassPrefix, Getattr(n, "sym:name"), NIL);
|
||||
EnumClassName = Copy(Getattr(n, "name"));
|
||||
}
|
||||
if (!ImportMode) {
|
||||
emit_children(n);
|
||||
}
|
||||
|
||||
if (GetFlag(n, "scopedenum")) {
|
||||
Delete(EnumClassName);
|
||||
EnumClassName = 0;
|
||||
Delete(EnumClassPrefix);
|
||||
EnumClassPrefix = oldEnumClassPrefix;
|
||||
}
|
||||
NSpace = oldNSpace;
|
||||
|
||||
return SWIG_OK;
|
||||
|
|
@ -1720,12 +1736,14 @@ int Language::memberconstantHandler(Node *n) {
|
|||
String *symname = Getattr(n, "sym:name");
|
||||
String *value = Getattr(n, "value");
|
||||
|
||||
String *mrename = Swig_name_member(0, ClassPrefix, symname);
|
||||
String *mrename = Swig_name_member(0, EnumClassPrefix, symname);
|
||||
Setattr(n, "sym:name", mrename);
|
||||
|
||||
String *new_name = 0;
|
||||
if (Extend)
|
||||
new_name = Copy(value);
|
||||
else if (EnumClassName)
|
||||
new_name = NewStringf("%s::%s", isNonVirtualProtectedAccess(n) ? DirectorClassName : EnumClassName, name);
|
||||
else
|
||||
new_name = NewStringf("%s::%s", isNonVirtualProtectedAccess(n) ? DirectorClassName : ClassName, name);
|
||||
Setattr(n, "name", new_name);
|
||||
|
|
@ -2369,6 +2387,7 @@ int Language::classDeclaration(Node *n) {
|
|||
int oldInClass = InClass;
|
||||
String *oldClassType = ClassType;
|
||||
String *oldClassPrefix = ClassPrefix;
|
||||
String *oldEnumClassPrefix = EnumClassPrefix;
|
||||
String *oldClassName = ClassName;
|
||||
String *oldDirectorClassName = DirectorClassName;
|
||||
String *oldNSpace = NSpace;
|
||||
|
|
@ -2410,6 +2429,7 @@ int Language::classDeclaration(Node *n) {
|
|||
Push(ClassPrefix, "_");
|
||||
Push(ClassPrefix, Getattr(outerClass, "sym:name"));
|
||||
}
|
||||
EnumClassPrefix = Copy(ClassPrefix);
|
||||
if (strip) {
|
||||
ClassType = Copy(name);
|
||||
} else {
|
||||
|
|
@ -2477,6 +2497,8 @@ int Language::classDeclaration(Node *n) {
|
|||
CurrentClass = oldCurrentClass;
|
||||
Delete(ClassType);
|
||||
ClassType = oldClassType;
|
||||
Delete(EnumClassPrefix);
|
||||
EnumClassPrefix = oldEnumClassPrefix;
|
||||
Delete(ClassPrefix);
|
||||
ClassPrefix = oldClassPrefix;
|
||||
Delete(ClassName);
|
||||
|
|
@ -2962,6 +2984,12 @@ int Language::variableWrapper(Node *n) {
|
|||
Delattr(n,"varset");
|
||||
Delattr(n,"varget");
|
||||
|
||||
String *newsymname = 0;
|
||||
if (!CurrentClass && EnumClassPrefix) {
|
||||
newsymname = Swig_name_member(0, EnumClassPrefix, symname);
|
||||
symname = newsymname;
|
||||
}
|
||||
|
||||
/* If no way to set variables. We simply create functions */
|
||||
int assignable = is_assignable(n);
|
||||
int flags = use_naturalvar_mode(n);
|
||||
|
|
@ -3019,6 +3047,7 @@ int Language::variableWrapper(Node *n) {
|
|||
functionWrapper(n);
|
||||
Delattr(n, "varget");
|
||||
Swig_restore(n);
|
||||
Delete(newsymname);
|
||||
return SWIG_OK;
|
||||
}
|
||||
|
||||
|
|
@ -3612,6 +3641,14 @@ String *Language::getClassPrefix() const {
|
|||
return ClassPrefix;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* Language::getEnumClassPrefix()
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
String *Language::getEnumClassPrefix() const {
|
||||
return EnumClassPrefix;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* Language::getClassType()
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
|
|
|||
|
|
@ -291,6 +291,9 @@ protected:
|
|||
/* Return the current class prefix */
|
||||
String *getClassPrefix() const;
|
||||
|
||||
/* Return the current enum class prefix */
|
||||
String *getEnumClassPrefix() const;
|
||||
|
||||
/* Fully qualified type name to use */
|
||||
String *getClassType() const;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue