diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index f985b55d1..36eded830 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -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 diff --git a/Examples/test-suite/cpp11_strongly_typed_enumerations.i b/Examples/test-suite/cpp11_strongly_typed_enumerations.i index ed466369e..0c5f12e1f 100644 --- a/Examples/test-suite/cpp11_strongly_typed_enumerations.i +++ b/Examples/test-suite/cpp11_strongly_typed_enumerations.i @@ -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 struct TType { @@ -64,7 +60,7 @@ template struct TType { }; enum class Enum10 : TType::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}; diff --git a/Examples/test-suite/director_nested_class.i b/Examples/test-suite/director_nested_class.i new file mode 100644 index 000000000..f3d627f3c --- /dev/null +++ b/Examples/test-suite/director_nested_class.i @@ -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); + } +}; +%} diff --git a/Examples/test-suite/java/director_nested_class_runme.java b/Examples/test-suite/java/director_nested_class_runme.java new file mode 100644 index 000000000..5144413b7 --- /dev/null +++ b/Examples/test-suite/java/director_nested_class_runme.java @@ -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; + } +} diff --git a/Source/Modules/java.cxx b/Source/Modules/java.cxx index 2d07c55c4..d84100e07 100644 --- a/Source/Modules/java.cxx +++ b/Source/Modules/java.cxx @@ -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); diff --git a/Source/Modules/lang.cxx b/Source/Modules/lang.cxx index 4fc1471b0..7f106a257 100644 --- a/Source/Modules/lang.cxx +++ b/Source/Modules/lang.cxx @@ -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() * ----------------------------------------------------------------------------- */ diff --git a/Source/Modules/swigmod.h b/Source/Modules/swigmod.h index 664a18bd5..a30fdf8fa 100644 --- a/Source/Modules/swigmod.h +++ b/Source/Modules/swigmod.h @@ -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;