diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index e3448dcbc..b47b6e33b 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -561,6 +561,7 @@ CPP11_TEST_CASES += \ cpp11_noexcept \ cpp11_null_pointer_constant \ cpp11_raw_string_literals \ + cpp11_ref_qualifiers \ cpp11_result_of \ cpp11_rvalue_reference \ cpp11_rvalue_reference2 \ diff --git a/Examples/test-suite/cpp11_ref_qualifiers.i b/Examples/test-suite/cpp11_ref_qualifiers.i new file mode 100644 index 000000000..fa1d68d0e --- /dev/null +++ b/Examples/test-suite/cpp11_ref_qualifiers.i @@ -0,0 +1,16 @@ +%module cpp11_ref_qualifiers + +%inline %{ +class Host { +public: + void h1() & {} + void h2() const & {} + void h3() && {} + void h4() const && {} + + void h() & {} + void h() const & {} + void h() && {} + void h() const && {} +}; +%} diff --git a/Examples/test-suite/errors/cpp_refqualifier.i b/Examples/test-suite/errors/cpp_refqualifier.i new file mode 100644 index 000000000..1cbcd936d --- /dev/null +++ b/Examples/test-suite/errors/cpp_refqualifier.i @@ -0,0 +1,18 @@ +%module cpp_refqualifier + +%ignore Host::h_ignored; + +class Host { +public: + void h1() &; + void h2() const &; + void h3() &&; + void h4() const &&; + + void h() &; + void h() const &; + void h() &&; + void h() const &&; + + void h_ignored() &&; +}; diff --git a/Examples/test-suite/errors/cpp_refqualifier.stderr b/Examples/test-suite/errors/cpp_refqualifier.stderr new file mode 100644 index 000000000..866d9b530 --- /dev/null +++ b/Examples/test-suite/errors/cpp_refqualifier.stderr @@ -0,0 +1,6 @@ +cpp_refqualifier.i:9: Warning 405: Method with rvalue ref-qualifier ignored h3() &&. +cpp_refqualifier.i:10: Warning 405: Method with rvalue ref-qualifier ignored h4() const &&. +cpp_refqualifier.i:14: Warning 405: Method with rvalue ref-qualifier ignored h() &&. +cpp_refqualifier.i:15: Warning 405: Method with rvalue ref-qualifier ignored h() const &&. +cpp_refqualifier.i:13: Warning 512: Overloaded method Host::h() const & ignored, +cpp_refqualifier.i:12: Warning 512: using non-const method Host::h() & instead. diff --git a/Examples/test-suite/java/cpp11_ref_qualifiers_runme.java b/Examples/test-suite/java/cpp11_ref_qualifiers_runme.java new file mode 100644 index 000000000..49afe8039 --- /dev/null +++ b/Examples/test-suite/java/cpp11_ref_qualifiers_runme.java @@ -0,0 +1,22 @@ + +import cpp11_ref_qualifiers.*; + +public class cpp11_ref_qualifiers_runme { + + static { + try { + System.loadLibrary("cpp11_ref_qualifiers"); + } 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[]) { + Host h = new Host(); + h.h1(); + h.h2(); + h.h(); + } +} + diff --git a/Examples/test-suite/python/cpp11_ref_qualifiers_runme.py b/Examples/test-suite/python/cpp11_ref_qualifiers_runme.py new file mode 100644 index 000000000..24ce1d2bf --- /dev/null +++ b/Examples/test-suite/python/cpp11_ref_qualifiers_runme.py @@ -0,0 +1,6 @@ +import cpp11_ref_qualifiers + +h = cpp11_ref_qualifiers.Host() +h.h1() +h.h2() +h.h() diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y index a4167b12d..9a101b1d2 100644 --- a/Source/CParse/parser.y +++ b/Source/CParse/parser.y @@ -485,6 +485,16 @@ static void add_symbols(Node *n) { SetFlag(n,"deleted"); SetFlag(n,"feature:ignore"); } + { + String *refqualifier = Getattr(n, "refqualifier"); + if (Equal(refqualifier, "&&") && strncmp(Char(symname), "$ignore", 7) != 0) { + SWIG_WARN_NODE_BEGIN(n); + Swig_warning(WARN_TYPE_RVALUE_REF_QUALIFIER_IGNORED, Getfile(n), Getline(n), + "Method with rvalue ref-qualifier ignored %s.\n", Swig_name_decl(n)); + SWIG_WARN_NODE_END(n); + SetFlag(n, "feature:ignore"); + } + } } if (only_csymbol || GetFlag(n,"feature:ignore") || strncmp(Char(symname),"$ignore",7) == 0) { /* Only add to C symbol table and continue */ @@ -1451,6 +1461,7 @@ static String *add_qualifier_to_declarator(SwigType *type, SwigType *qualifier) String *rawval; int type; String *qualifier; + String *refqualifier; String *bitfield; Parm *throws; String *throwf; @@ -1560,7 +1571,7 @@ static String *add_qualifier_to_declarator(SwigType *type, SwigType *qualifier) /* Misc */ %type identifier; -%type initializer cpp_const exception_specification; +%type initializer cpp_const exception_specification cv_ref_qualifier; %type storage_class extern_string; %type parms ptail rawparms varargs_parms ; %type templateparameters templateparameterstail; @@ -1576,7 +1587,8 @@ static String *add_qualifier_to_declarator(SwigType *type, SwigType *qualifier) %type expr exprnum exprcompound valexpr; %type ename ; %type less_valparms_greater; -%type type_qualifier ; +%type type_qualifier; +%type ref_qualifier; %type type_qualifier_raw; %type idstring idstringopt; %type pragma_lang; @@ -3063,6 +3075,7 @@ c_decl : storage_class type declarator initializer c_decl_tail { $$ = new_node("cdecl"); if ($4.qualifier) decl = add_qualifier_to_declarator($3.type, $4.qualifier); + Setattr($$,"refqualifier",$4.refqualifier); Setattr($$,"type",$2); Setattr($$,"storage",$1); Setattr($$,"name",$3.id); @@ -3136,6 +3149,7 @@ c_decl : storage_class type declarator initializer c_decl_tail { | storage_class AUTO declarator cpp_const ARROW cpp_alternate_rettype initializer c_decl_tail { $$ = new_node("cdecl"); if ($4.qualifier) SwigType_push($3.type, $4.qualifier); + Setattr($$,"refqualifier",$4.refqualifier); Setattr($$,"type",$6); Setattr($$,"storage",$1); Setattr($$,"name",$3.id); @@ -3198,6 +3212,7 @@ c_decl_tail : SEMI { | COMMA declarator initializer c_decl_tail { $$ = new_node("cdecl"); if ($3.qualifier) SwigType_push($2.type,$3.qualifier); + Setattr($$,"refqualifier",$3.refqualifier); Setattr($$,"name",$2.id); Setattr($$,"decl",$2.type); Setattr($$,"parms",$2.parms); @@ -3236,13 +3251,15 @@ c_decl_tail : SEMI { initializer : def_args { $$ = $1; $$.qualifier = 0; + $$.refqualifier = 0; $$.throws = 0; $$.throwf = 0; $$.nexcept = 0; } - | type_qualifier def_args { + | cv_ref_qualifier def_args { $$ = $2; - $$.qualifier = $1; + $$.qualifier = $1.qualifier; + $$.refqualifier = $1.refqualifier; $$.throws = 0; $$.throwf = 0; $$.nexcept = 0; @@ -3250,13 +3267,15 @@ initializer : def_args { | exception_specification def_args { $$ = $2; $$.qualifier = 0; + $$.refqualifier = 0; $$.throws = $1.throws; $$.throwf = $1.throwf; $$.nexcept = $1.nexcept; } - | type_qualifier exception_specification def_args { + | cv_ref_qualifier exception_specification def_args { $$ = $3; - $$.qualifier = $1; + $$.qualifier = $1.qualifier; + $$.refqualifier = $1.refqualifier; $$.throws = $2.throws; $$.throwf = $2.throwf; $$.nexcept = $2.nexcept; @@ -4809,6 +4828,7 @@ cpp_vend : cpp_const SEMI { Clear(scanner_ccode); $$.val = 0; $$.qualifier = $1.qualifier; + $$.refqualifier = 0; $$.bitfield = 0; $$.throws = $1.throws; $$.throwf = $1.throwf; @@ -4818,6 +4838,7 @@ cpp_vend : cpp_const SEMI { Clear(scanner_ccode); $$.val = $3.val; $$.qualifier = $1.qualifier; + $$.refqualifier = 0; $$.bitfield = 0; $$.throws = $1.throws; $$.throwf = $1.throwf; @@ -4827,6 +4848,7 @@ cpp_vend : cpp_const SEMI { skip_balanced('{','}'); $$.val = 0; $$.qualifier = $1.qualifier; + $$.refqualifier = 0; $$.bitfield = 0; $$.throws = $1.throws; $$.throwf = $1.throwf; @@ -5828,6 +5850,29 @@ pointer : STAR type_qualifier pointer { } ; +/* cv-qualifier plus C++11 ref-qualifier for non-static member functions */ +cv_ref_qualifier : type_qualifier { + $$.qualifier = $1; + $$.refqualifier = 0; + } + | type_qualifier ref_qualifier { + $$.qualifier = $1; + $$.refqualifier = $2; + } + | ref_qualifier { + $$.qualifier = 0; + $$.refqualifier = $1; + } + ; + +ref_qualifier : AND { + $$ = NewString("&"); + } + | LAND { + $$ = NewString("&&"); + } + ; + type_qualifier : type_qualifier_raw { $$ = NewStringEmpty(); if ($1) SwigType_add_qualifier($$,$1); @@ -6049,6 +6094,7 @@ definetype : { /* scanner_check_typedef(); */ } expr { $$.rawval = NewStringf("%s", $$.val); } $$.qualifier = 0; + $$.refqualifier = 0; $$.bitfield = 0; $$.throws = 0; $$.throwf = 0; @@ -6074,6 +6120,7 @@ deleted_definition : DELETE_KW { $$.rawval = 0; $$.type = T_STRING; $$.qualifier = 0; + $$.refqualifier = 0; $$.bitfield = 0; $$.throws = 0; $$.throwf = 0; @@ -6087,6 +6134,7 @@ explicit_default : DEFAULT { $$.rawval = 0; $$.type = T_STRING; $$.qualifier = 0; + $$.refqualifier = 0; $$.bitfield = 0; $$.throws = 0; $$.throwf = 0; @@ -6616,25 +6664,29 @@ exception_specification : THROW LPAREN parms RPAREN { } ; -cpp_const : type_qualifier { +cpp_const : cv_ref_qualifier { $$.throws = 0; $$.throwf = 0; $$.nexcept = 0; - $$.qualifier = $1; + $$.qualifier = $1.qualifier; + $$.refqualifier = $1.refqualifier; } | exception_specification { $$ = $1; $$.qualifier = 0; + $$.refqualifier = 0; } - | type_qualifier exception_specification { + | cv_ref_qualifier exception_specification { $$ = $2; - $$.qualifier = $1; + $$.qualifier = $1.qualifier; + $$.refqualifier = $1.refqualifier; } | empty { $$.throws = 0; $$.throwf = 0; $$.nexcept = 0; - $$.qualifier = 0; + $$.qualifier = 0; + $$.refqualifier = 0; } ; diff --git a/Source/Include/swigwarn.h b/Source/Include/swigwarn.h index 0b4c7eeb5..dd32aef3a 100644 --- a/Source/Include/swigwarn.h +++ b/Source/Include/swigwarn.h @@ -153,6 +153,7 @@ #define WARN_TYPE_INCOMPLETE 402 #define WARN_TYPE_ABSTRACT 403 #define WARN_TYPE_REDEFINED 404 +#define WARN_TYPE_RVALUE_REF_QUALIFIER_IGNORED 405 #define WARN_TYPEMAP_SOURCETARGET 450 #define WARN_TYPEMAP_CHARLEAK 451 diff --git a/Source/Modules/main.cxx b/Source/Modules/main.cxx index 12b83b2e4..9822b6af7 100644 --- a/Source/Modules/main.cxx +++ b/Source/Modules/main.cxx @@ -38,14 +38,15 @@ int NoExcept = 0; int SwigRuntime = 0; // 0 = no option, 1 = -runtime, 2 = -noruntime /* Suppress warning messages for private inheritance, preprocessor evaluation etc... - WARN_PP_EVALUATION 202 - WARN_PARSE_PRIVATE_INHERIT 309 - WARN_TYPE_ABSTRACT 403 - WARN_LANG_OVERLOAD_CONST 512 - WARN_PARSE_BUILTIN_NAME 321 - WARN_PARSE_REDUNDANT 322 + WARN_PP_EVALUATION 202 + WARN_PARSE_PRIVATE_INHERIT 309 + WARN_PARSE_BUILTIN_NAME 321 + WARN_PARSE_REDUNDANT 322 + WARN_TYPE_ABSTRACT 403 + WARN_TYPE_RVALUE_REF_QUALIFIER_IGNORED 405 + WARN_LANG_OVERLOAD_CONST 512 */ -#define EXTRA_WARNINGS "202,309,403,512,321,322" +#define EXTRA_WARNINGS "202,309,403,405,512,321,322" extern "C" { extern String *ModuleName; diff --git a/Source/Swig/naming.c b/Source/Swig/naming.c index ce1dbe806..69b9e2190 100644 --- a/Source/Swig/naming.c +++ b/Source/Swig/naming.c @@ -1681,6 +1681,7 @@ String *Swig_name_str(Node *n) { * "MyNameSpace::MyTemplate::~MyTemplate()" * "MyNameSpace::ABC::ABC(int,double)" * "MyNameSpace::ABC::constmethod(int) const" + * "MyNameSpace::ABC::refqualifiermethod(int) const &" * "MyNameSpace::ABC::variablename" * * ----------------------------------------------------------------------------- */ @@ -1688,6 +1689,7 @@ String *Swig_name_str(Node *n) { String *Swig_name_decl(Node *n) { String *qname; String *decl; + String *refqualifier = Getattr(n, "refqualifier"); qname = Swig_name_str(n); @@ -1695,6 +1697,8 @@ String *Swig_name_decl(Node *n) { decl = NewStringf("%s", qname); else decl = NewStringf("%s(%s)%s", qname, ParmList_errorstr(Getattr(n, "parms")), SwigType_isconst(Getattr(n, "decl")) ? " const" : ""); + if (refqualifier) + Printv(decl, " ", refqualifier, NIL); Delete(qname);