C++11 ref-qualifier support added

Fixes #1059

Methods with rvalue ref-qualifiers are ignored by default as it is not
possible to have an rvalue temporary from the target language (which is
needed to call the rvalue ref-qualified method).
A warning 405 is shown mentioning the ignored rvalue ref-qualifier method
which can be seen with the -Wextra option.

  cpp_refqualifier.i:15: Warning 405: Method with rvalue ref-qualifier ignored h() const &&.

Usually rvalue and lvalue ref-qualifier overloaded methods are written - the
lvalue method will then be wrapped.
This commit is contained in:
William S Fulton 2017-08-19 01:02:34 +01:00
commit 9e19fe7868
10 changed files with 145 additions and 18 deletions

View file

@ -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 \

View file

@ -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 && {}
};
%}

View file

@ -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() &&;
};

View file

@ -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.

View file

@ -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();
}
}

View file

@ -0,0 +1,6 @@
import cpp11_ref_qualifiers
h = cpp11_ref_qualifiers.Host()
h.h1()
h.h2()
h.h()

View file

@ -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 <id> identifier;
%type <dtype> initializer cpp_const exception_specification;
%type <dtype> initializer cpp_const exception_specification cv_ref_qualifier;
%type <id> storage_class extern_string;
%type <pl> parms ptail rawparms varargs_parms ;
%type <pl> templateparameters templateparameterstail;
@ -1576,7 +1587,8 @@ static String *add_qualifier_to_declarator(SwigType *type, SwigType *qualifier)
%type <dtype> expr exprnum exprcompound valexpr;
%type <id> ename ;
%type <id> less_valparms_greater;
%type <str> type_qualifier ;
%type <str> type_qualifier;
%type <str> ref_qualifier;
%type <id> type_qualifier_raw;
%type <id> idstring idstringopt;
%type <id> 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;
}
;

View file

@ -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

View file

@ -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;

View file

@ -1681,6 +1681,7 @@ String *Swig_name_str(Node *n) {
* "MyNameSpace::MyTemplate<MyNameSpace::ABC >::~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);