Improved C++0x rvalue reference implementation differentiating lvalue and rvalue references. The previous implementation treated rvalue references as lvalue references which leads to a number of different wrapping issues.

git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/branches/gsoc2009-matevz@12160 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
William S Fulton 2010-07-18 00:19:22 +00:00
commit d8cc75946b
13 changed files with 399 additions and 32 deletions

View file

@ -3968,15 +3968,19 @@ cpp_template_decl : TEMPLATE LESSTHAN template_parms GREATERTHAN { template_para
Delete(Namespaceprefix);
Namespaceprefix = Swig_symbol_qualifiedscopename(0);
if (error) $$ = 0;
}
| TEMPLATE cpptype idcolon { /* Explicit template instantiation */
}
/* Explicit template instantiation */
| TEMPLATE cpptype idcolon {
Swig_warning(WARN_PARSE_EXPLICIT_TEMPLATE, cparse_file, cparse_line, "Explicit template instantiation ignored.\n");
$$ = 0;
}
| EXTERN TEMPLATE cpptype idcolon { /* Explicit template instantiation without the translation unit */
$$ = 0;
}
/* Explicit template instantiation without the translation unit */
| EXTERN TEMPLATE cpptype idcolon {
Swig_warning(WARN_PARSE_EXPLICIT_TEMPLATE, cparse_file, cparse_line, "Explicit template instantiation ignored.\n");
$$ = 0;
}
$$ = 0;
}
;
cpp_temp_possible: c_decl {
@ -4395,6 +4399,23 @@ cpp_conversion_operator : storage_class COPERATOR type pointer LPAREN parms RPAR
Setattr($$,"conversion_operator","1");
add_symbols($$);
}
| storage_class COPERATOR type LAND LPAREN parms RPAREN cpp_vend {
SwigType *decl;
$$ = new_node("cdecl");
Setattr($$,"type",$3);
Setattr($$,"name",$2);
Setattr($$,"storage",$1);
decl = NewStringEmpty();
SwigType_add_rvalue_reference(decl);
SwigType_add_function(decl,$6);
if ($8.qualifier) {
SwigType_push(decl,$8.qualifier);
}
Setattr($$,"decl",decl);
Setattr($$,"parms",$6);
Setattr($$,"conversion_operator","1");
add_symbols($$);
}
| storage_class COPERATOR type LPAREN parms RPAREN cpp_vend {
String *t = NewStringEmpty();
@ -4902,6 +4923,15 @@ declarator : pointer notso_direct_declarator {
}
$$.type = $1;
}
| pointer LAND notso_direct_declarator {
$$ = $3;
SwigType_add_rvalue_reference($1);
if ($$.type) {
SwigType_push($1,$$.type);
Delete($$.type);
}
$$.type = $1;
}
| direct_declarator {
$$ = $1;
if (!$$.type) $$.type = NewStringEmpty();
@ -4920,7 +4950,7 @@ declarator : pointer notso_direct_declarator {
/* Adds one S/R conflict */
$$ = $2;
$$.type = NewStringEmpty();
SwigType_add_reference($$.type);
SwigType_add_rvalue_reference($$.type);
if ($2.type) {
SwigType_push($$.type,$2.type);
Delete($2.type);
@ -4990,6 +5020,15 @@ declarator : pointer notso_direct_declarator {
}
$$.type = $1;
}
| pointer LAND PERIOD PERIOD PERIOD notso_direct_declarator {
$$ = $6;
SwigType_add_rvalue_reference($1);
if ($$.type) {
SwigType_push($1,$$.type);
Delete($$.type);
}
$$.type = $1;
}
| PERIOD PERIOD PERIOD direct_declarator {
$$ = $4;
if (!$$.type) $$.type = NewStringEmpty();
@ -5008,7 +5047,7 @@ declarator : pointer notso_direct_declarator {
/* Adds one S/R conflict */
$$ = $5;
$$.type = NewStringEmpty();
SwigType_add_reference($$.type);
SwigType_add_rvalue_reference($$.type);
if ($5.type) {
SwigType_push($$.type,$5.type);
Delete($5.type);
@ -5047,6 +5086,16 @@ declarator : pointer notso_direct_declarator {
}
$$.type = $1;
}
| pointer idcolon DSTAR LAND PERIOD PERIOD PERIOD notso_direct_declarator {
$$ = $8;
SwigType_add_memberpointer($1,$2);
SwigType_add_rvalue_reference($1);
if ($$.type) {
SwigType_push($1,$$.type);
Delete($$.type);
}
$$.type = $1;
}
| idcolon DSTAR AND PERIOD PERIOD PERIOD notso_direct_declarator {
SwigType *t = NewStringEmpty();
$$ = $7;
@ -5058,6 +5107,17 @@ declarator : pointer notso_direct_declarator {
}
$$.type = t;
}
| idcolon DSTAR LAND PERIOD PERIOD PERIOD notso_direct_declarator {
SwigType *t = NewStringEmpty();
$$ = $7;
SwigType_add_memberpointer(t,$1);
SwigType_add_rvalue_reference(t);
if ($$.type) {
SwigType_push(t,$$.type);
Delete($$.type);
}
$$.type = t;
}
;
notso_direct_declarator : idcolon {
@ -5191,6 +5251,13 @@ direct_declarator : idcolon {
}
SwigType_add_reference($$.type);
}
| LPAREN LAND direct_declarator RPAREN {
$$ = $3;
if (!$$.type) {
$$.type = NewStringEmpty();
}
SwigType_add_rvalue_reference($$.type);
}
| LPAREN idcolon DSTAR direct_declarator RPAREN {
SwigType *t;
$$ = $4;
@ -5283,6 +5350,13 @@ abstract_declarator : pointer {
$$.parms = 0;
$$.have_parms = 0;
}
| pointer LAND {
$$.type = $1;
SwigType_add_rvalue_reference($$.type);
$$.id = 0;
$$.parms = 0;
$$.have_parms = 0;
}
| pointer AND direct_abstract_declarator {
$$ = $3;
SwigType_add_reference($1);
@ -5292,6 +5366,15 @@ abstract_declarator : pointer {
}
$$.type = $1;
}
| pointer LAND direct_abstract_declarator {
$$ = $3;
SwigType_add_rvalue_reference($1);
if ($$.type) {
SwigType_push($1,$$.type);
Delete($$.type);
}
$$.type = $1;
}
| direct_abstract_declarator {
$$ = $1;
}
@ -5304,6 +5387,15 @@ abstract_declarator : pointer {
Delete($2.type);
}
}
| LAND direct_abstract_declarator {
$$ = $2;
$$.type = NewStringEmpty();
SwigType_add_rvalue_reference($$.type);
if ($2.type) {
SwigType_push($$.type,$2.type);
Delete($2.type);
}
}
| AND {
$$.id = 0;
$$.parms = 0;
@ -5311,6 +5403,13 @@ abstract_declarator : pointer {
$$.type = NewStringEmpty();
SwigType_add_reference($$.type);
}
| LAND {
$$.id = 0;
$$.parms = 0;
$$.have_parms = 0;
$$.type = NewStringEmpty();
SwigType_add_rvalue_reference($$.type);
}
| idcolon DSTAR {
$$.type = NewStringEmpty();
SwigType_add_memberpointer($$.type,$1);
@ -5821,6 +5920,13 @@ valexpr : exprnum { $$ = $1; }
$$.val = NewStringf("(%s) %s", SwigType_str($2.val,0), $5.val);
}
}
| LPAREN expr LAND RPAREN expr %prec CAST {
$$ = $5;
if ($5.type != T_STRING) {
SwigType_add_rvalue_reference($2.val);
$$.val = NewStringf("(%s) %s", SwigType_str($2.val,0), $5.val);
}
}
| LPAREN expr pointer AND RPAREN expr %prec CAST {
$$ = $6;
if ($6.type != T_STRING) {
@ -5829,10 +5935,22 @@ valexpr : exprnum { $$ = $1; }
$$.val = NewStringf("(%s) %s", SwigType_str($2.val,0), $6.val);
}
}
| LPAREN expr pointer LAND RPAREN expr %prec CAST {
$$ = $6;
if ($6.type != T_STRING) {
SwigType_push($2.val,$3);
SwigType_add_rvalue_reference($2.val);
$$.val = NewStringf("(%s) %s", SwigType_str($2.val,0), $6.val);
}
}
| AND expr {
$$ = $2;
$$.val = NewStringf("&%s",$2.val);
}
| LAND expr {
$$ = $2;
$$.val = NewStringf("&&%s",$2.val);
}
| STAR expr {
$$ = $2;
$$.val = NewStringf("*%s",$2.val);

View file

@ -1160,6 +1160,7 @@ public:
break;
}
case T_REFERENCE:
case T_RVALUE_REFERENCE:
case T_USER:
case T_ARRAY:
Clear(value);
@ -1930,6 +1931,7 @@ public:
break;
case T_POINTER:
case T_REFERENCE:
case T_RVALUE_REFERENCE:
case T_USER:
if (is_shadow(t)) {
return NewString(Char(is_shadow(t)));

View file

@ -68,6 +68,19 @@ static String *Swig_clocal(SwigType *t, const_String_or_char_ptr name, const_Str
Delete(lstrname);
}
break;
case T_RVALUE_REFERENCE:
if (value) {
String *lstrname = SwigType_lstr(t, name);
String *lstr = SwigType_lstr(t, 0);
Printf(decl, "%s = (%s) &%s_defrvalue", lstrname, lstr, name);
Delete(lstrname);
Delete(lstr);
} else {
String *lstrname = SwigType_lstr(t, name);
Printf(decl, "%s = 0", lstrname);
Delete(lstrname);
}
break;
case T_VOID:
break;
case T_VARARGS:
@ -229,6 +242,34 @@ int Swig_cargs(Wrapper *w, ParmList *p) {
Delete(defname);
Delete(defvalue);
}
} else if (tycode == T_RVALUE_REFERENCE) {
if (pvalue) {
SwigType *tvalue;
String *defname, *defvalue, *rvalue, *qvalue;
rvalue = SwigType_typedef_resolve_all(pvalue);
qvalue = SwigType_typedef_qualified(rvalue);
defname = NewStringf("%s_defrvalue", lname);
tvalue = Copy(type);
SwigType_del_rvalue_reference(tvalue);
tycode = SwigType_type(tvalue);
if (tycode != T_USER) {
/* plain primitive type, we copy the the def value */
String *lstr = SwigType_lstr(tvalue, defname);
defvalue = NewStringf("%s = %s", lstr, qvalue);
Delete(lstr);
} else {
/* user type, we copy the reference value */
String *str = SwigType_str(type, defname);
defvalue = NewStringf("%s = %s", str, qvalue);
Delete(str);
}
Wrapper_add_localv(w, defname, defvalue, NIL);
Delete(tvalue);
Delete(rvalue);
Delete(qvalue);
Delete(defname);
Delete(defvalue);
}
} else if (!pvalue && ((tycode == T_POINTER) || (tycode == T_STRING))) {
pvalue = (String *) "0";
}
@ -269,6 +310,13 @@ String *Swig_cresult(SwigType *t, const_String_or_char_ptr name, const_String_or
Delete(lstr);
}
break;
case T_RVALUE_REFERENCE:
{
String *lstr = SwigType_lstr(t, 0);
Printf(fcall, "%s = (%s) &", name, lstr);
Delete(lstr);
}
break;
case T_USER:
Printf(fcall, "%s = ", name);
break;

View file

@ -43,6 +43,7 @@ char cvsroot_stype_c[] = "$Id$";
*
* 'p.' = Pointer (*)
* 'r.' = Reference (&)
* 'z.' = Rvalue reference (&&)
* 'a(n).' = Array of size n [n]
* 'f(..,..).' = Function with arguments (args)
* 'q(str).' = Qualifier (such as const or volatile) (const, volatile)
@ -235,7 +236,7 @@ int SwigType_isconst(SwigType *t) {
int SwigType_ismutable(SwigType *t) {
int r;
SwigType *qt = SwigType_typedef_resolve_all(t);
if (SwigType_isreference(qt) || SwigType_isarray(qt)) {
if (SwigType_isreference(qt) || SwigType_isrvalue_reference(qt) || SwigType_isarray(qt)) {
Delete(SwigType_pop(qt));
}
r = SwigType_isconst(qt);
@ -423,6 +424,16 @@ SwigType *SwigType_default(SwigType *t) {
Delete(nr);
#else
def = NewString("r.SWIGTYPE");
#endif
} else if (SwigType_isrvalue_reference(r)) {
#ifdef SWIG_NEW_TYPE_DEFAULT
SwigType *nr = Copy(r);
SwigType_del_rvalue_reference(nr);
def = NewString("z.");
SwigType_add_default(def, nr);
Delete(nr);
#else
def = NewString("z.SWIGTYPE");
#endif
} else if (SwigType_isarray(r)) {
if (strcmp(cr, "a().SWIGTYPE") == 0) {
@ -597,6 +608,12 @@ String *SwigType_str(SwigType *s, const_String_or_char_ptr id) {
Insert(result, 0, "(");
Append(result, ")");
}
} else if (SwigType_isrvalue_reference(element)) {
Insert(result, 0, "&&");
if ((nextelement) && ((SwigType_isfunction(nextelement) || (SwigType_isarray(nextelement))))) {
Insert(result, 0, "(");
Append(result, ")");
}
} else if (SwigType_isarray(element)) {
DOH *size;
Append(result, "[");
@ -661,7 +678,7 @@ SwigType *SwigType_ltype(SwigType *s) {
SwigType *tt = Copy(tc);
td = 0;
while ((td = SwigType_typedef_resolve(tt))) {
if (td && (SwigType_isconst(td) || SwigType_isarray(td) || SwigType_isreference(td))) {
if (td && (SwigType_isconst(td) || SwigType_isarray(td) || SwigType_isreference(td) || SwigType_isrvalue_reference(td))) {
/* We need to use the typedef type */
Delete(tt);
tt = td;
@ -701,6 +718,13 @@ SwigType *SwigType_ltype(SwigType *s) {
Append(result, "p.");
}
firstarray = 0;
} else if (SwigType_isrvalue_reference(element)) {
if (notypeconv) {
Append(result, element);
} else {
Append(result, "p.");
}
firstarray = 0;
} else if (SwigType_isarray(element) && firstarray) {
if (notypeconv) {
Append(result, element);
@ -765,6 +789,7 @@ String *SwigType_rcaststr(SwigType *s, const_String_or_char_ptr name) {
int clear = 1;
int firstarray = 1;
int isreference = 0;
int isfunction = 0;
int isarray = 0;
result = NewStringEmpty();
@ -777,14 +802,14 @@ String *SwigType_rcaststr(SwigType *s, const_String_or_char_ptr name) {
rs = s;
}
if ((SwigType_isconst(rs) || SwigType_isarray(rs) || SwigType_isreference(rs))) {
if ((SwigType_isconst(rs) || SwigType_isarray(rs) || SwigType_isreference(rs) || SwigType_isrvalue_reference(rs))) {
td = 0;
} else {
td = SwigType_typedef_resolve(rs);
}
if (td) {
if ((SwigType_isconst(td) || SwigType_isarray(td) || SwigType_isreference(td))) {
if ((SwigType_isconst(td) || SwigType_isarray(td) || SwigType_isreference(td) || SwigType_isrvalue_reference(td))) {
elements = SwigType_split(td);
} else {
elements = SwigType_split(rs);
@ -836,6 +861,14 @@ String *SwigType_rcaststr(SwigType *s, const_String_or_char_ptr name) {
Append(result, ")");
}
isreference = 1;
} else if (SwigType_isrvalue_reference(element)) {
Insert(result, 0, "&&");
if ((nextelement) && ((SwigType_isfunction(nextelement) || (SwigType_isarray(nextelement))))) {
Insert(result, 0, "(");
Append(result, ")");
}
isreference = 1;
clear = 0;
} else if (SwigType_isarray(element)) {
DOH *size;
if (firstarray && !isreference) {
@ -865,6 +898,7 @@ String *SwigType_rcaststr(SwigType *s, const_String_or_char_ptr name) {
}
Append(result, ")");
Delete(parms);
isfunction = 1;
} else {
String *bs = SwigType_namestr(element);
Insert(result, 0, " ");
@ -880,10 +914,12 @@ String *SwigType_rcaststr(SwigType *s, const_String_or_char_ptr name) {
cast = NewStringf("(%s)", result);
}
if (name) {
if (isreference) {
if (isarray)
Clear(cast);
Append(cast, "*");
if (!isfunction) {
if (isreference) {
if (isarray)
Clear(cast);
Append(cast, "*");
}
}
Append(cast, name);
}
@ -914,6 +950,12 @@ String *SwigType_lcaststr(SwigType *s, const_String_or_char_ptr name) {
Delete(str);
if (name)
Append(result, name);
} else if (SwigType_isrvalue_reference(s)) {
String *str = SwigType_str(s, 0);
Printf(result, "(%s)", str);
Delete(str);
if (name)
Append(result, name);
} else if (SwigType_isqualifier(s)) {
String *lstr = SwigType_lstr(s, 0);
Printf(result, "(%s)%s", lstr, name);

View file

@ -94,6 +94,7 @@ extern "C" {
#define T_FUNCTION 37
#define T_MPOINTER 38
#define T_VARARGS 39
#define T_RVALUE_REFERENCE 40
#define T_SYMBOL 98
#define T_ERROR 99
@ -123,6 +124,8 @@ extern "C" {
extern SwigType *SwigType_pop_arrays(SwigType *t);
extern SwigType *SwigType_add_reference(SwigType *t);
extern SwigType *SwigType_del_reference(SwigType *t);
extern SwigType *SwigType_add_rvalue_reference(SwigType *t);
extern SwigType *SwigType_del_rvalue_reference(SwigType *t);
extern SwigType *SwigType_add_qualifier(SwigType *t, const_String_or_char_ptr qual);
extern SwigType *SwigType_del_qualifier(SwigType *t);
extern SwigType *SwigType_add_function(SwigType *t, ParmList *parms);
@ -146,6 +149,7 @@ extern "C" {
extern int SwigType_ismemberpointer(SwigType *t);
extern int SwigType_isreference(SwigType *t);
extern int SwigType_isreference_return(SwigType *t);
extern int SwigType_isrvalue_reference(SwigType *t);
extern int SwigType_isarray(SwigType *t);
extern int SwigType_prefix_is_simple_1D_array(SwigType *t);
extern int SwigType_isfunction(SwigType *t);

View file

@ -942,13 +942,13 @@ int typemap_replace_vars(String *s, ParmList *locals, SwigType *type, SwigType *
$*n_ltype
*/
if (SwigType_ispointer(ftype) || (SwigType_isarray(ftype)) || (SwigType_isreference(ftype))) {
if (!(SwigType_isarray(type) || SwigType_ispointer(type) || SwigType_isreference(type))) {
if (SwigType_ispointer(ftype) || (SwigType_isarray(ftype)) || (SwigType_isreference(ftype)) || (SwigType_isrvalue_reference(ftype))) {
if (!(SwigType_isarray(type) || SwigType_ispointer(type) || SwigType_isreference(type) || SwigType_isrvalue_reference(type))) {
star_type = Copy(ftype);
} else {
star_type = Copy(type);
}
if (!SwigType_isreference(star_type)) {
if (!(SwigType_isreference(star_type) || SwigType_isrvalue_reference(star_type))) {
if (SwigType_isarray(star_type)) {
SwigType_del_element(star_type);
} else {

View file

@ -45,6 +45,7 @@ char cvsroot_typeobj_c[] = "$Id$";
*
* 'p.' = Pointer (*)
* 'r.' = Reference (&)
* 'z.' = Rvalue reference (&&)
* 'a(n).' = Array of size n [n]
* 'f(..,..).' = Function with arguments (args)
* 'q(str).' = Qualifier (such as const or volatile) (const, volatile)
@ -75,6 +76,7 @@ char cvsroot_typeobj_c[] = "$Id$";
*
* SwigType_add_pointer()
* SwigType_add_reference()
* SwigType_add_rvalue_reference()
* SwigType_add_array()
*
* These are used to build new types. There are also functions to undo these
@ -82,12 +84,14 @@ char cvsroot_typeobj_c[] = "$Id$";
*
* SwigType_del_pointer()
* SwigType_del_reference()
* SwigType_del_rvalue_reference()
* SwigType_del_array()
*
* In addition, there are query functions
*
* SwigType_ispointer()
* SwigType_isreference()
* SwigType_isrvalue_reference()
* SwigType_isarray()
*
* Finally, there are some data extraction functions that can be used to
@ -409,6 +413,41 @@ int SwigType_isreference(SwigType *t) {
return 0;
}
/* -----------------------------------------------------------------------------
* Rvalue References
*
* SwigType_add_rvalue_reference()
* SwigType_del_rvalue_reference()
* SwigType_isrvalue_reference()
*
* Add, remove, and test if a type is a rvalue reference. The deletion and query
* functions take into account qualifiers (if any).
* ----------------------------------------------------------------------------- */
SwigType *SwigType_add_rvalue_reference(SwigType *t) {
Insert(t, 0, "z.");
return t;
}
SwigType *SwigType_del_rvalue_reference(SwigType *t) {
char *c = Char(t);
int check = strncmp(c, "z.", 2);
assert(check == 0);
Delslice(t, 0, 2);
return t;
}
int SwigType_isrvalue_reference(SwigType *t) {
char *c;
if (!t)
return 0;
c = Char(t);
if (strncmp(c, "z.", 2) == 0) {
return 1;
}
return 0;
}
/* -----------------------------------------------------------------------------
* Qualifiers
*

View file

@ -1206,6 +1206,8 @@ int SwigType_type(SwigType *t) {
return T_ARRAY;
if (strncmp(c, "r.", 2) == 0)
return T_REFERENCE;
if (strncmp(c, "z.", 2) == 0)
return T_RVALUE_REFERENCE;
if (strncmp(c, "m(", 2) == 0)
return T_MPOINTER;
if (strncmp(c, "q(", 2) == 0) {
@ -1540,6 +1542,11 @@ void SwigType_remember_clientdata(SwigType *t, const_String_or_char_ptr clientda
SwigType_del_reference(tt);
SwigType_add_pointer(tt);
SwigType_remember_clientdata(tt, clientdata);
} else if (SwigType_isrvalue_reference(t)) {
SwigType *tt = Copy(t);
SwigType_del_rvalue_reference(tt);
SwigType_add_pointer(tt);
SwigType_remember_clientdata(tt, clientdata);
}
}