aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Doc/Manual/CPlusPlus11.html22
-rw-r--r--Examples/test-suite/c_delete.i14
-rw-r--r--Examples/test-suite/c_delete_function.i7
-rw-r--r--Examples/test-suite/common.mk2
-rw-r--r--Examples/test-suite/cpp11_default_delete.i64
-rw-r--r--Source/CParse/cscanner.c3
-rw-r--r--Source/CParse/parser.y66
-rw-r--r--Source/Modules/allocate.cxx26
8 files changed, 173 insertions, 31 deletions
diff --git a/Doc/Manual/CPlusPlus11.html b/Doc/Manual/CPlusPlus11.html
index 3caec748e..95d748791 100644
--- a/Doc/Manual/CPlusPlus11.html
+++ b/Doc/Manual/CPlusPlus11.html
@@ -33,7 +33,7 @@
<li><a href="#CPlusPlus11_New_string_literals">New string literals</a>
<li><a href="#CPlusPlus11_User_defined_literals">User-defined literals</a>
<li><a href="#CPlusPlus11_Thread_local_storage">Thread-local storage</a>
-<li><a href="#CPlusPlus11_Defaulting/deleting_of_standard_functions_on_C++_objects">Defaulting/deleting of standard functions on C++ objects</a>
+<li><a href="#CPlusPlus11_Defaulted_deleted">Defaulting/deleting of standard functions on C++ objects</a>
<li><a href="#CPlusPlus11_Type_long_long_int">Type long long int</a>
<li><a href="#CPlusPlus11_Static_assertions">Static assertions</a>
<li><a href="#CPlusPlus11_Allow_sizeof_to_work_on_members_of_classes_without_an_explicit_object">Allow sizeof to work on members of classes without an explicit object</a>
@@ -739,23 +739,27 @@ A variable will be thread local if accessed from different threads from the targ
same way that it will be thread local if accessed from C++ code.
</p>
-<H3><a name="CPlusPlus11_Defaulting/deleting_of_standard_functions_on_C++_objects"></a>7.2.21 Defaulting/deleting of standard functions on C++ objects</H3>
+<H3><a name="CPlusPlus11_defaulted_deleted"></a>7.2.21 Explicitly defaulted functions and deleted functions</H3>
-<p>SWIG correctly parses the <tt>= delete</tt> and <tt>= default</tt>
-keywords. For example:</p>
+<p>SWIG handles explicitly defaulted functions, that is, <tt>= default</tt> added to a function declaration. Deleted definitions, which are also called deleted functions, have <tt>= delete</tt> added to the function declaration.
+For example:</p>
<div class="code"><pre>
struct NonCopyable {
NonCopyable&amp; operator=(const NonCopyable&amp;) = delete; /* Removes operator= */
- NonCopyable(const NonCopyable&amp;) = delete; /* Removed copy constructor */
- NonCopyable() = default; /* Explicitly allows the empty constructor */
- void *operator new(std::size_t) = delete; /* Removes new NonCopyable */
+ NonCopyable(const NonCopyable&amp;) = delete; /* Removed copy constructor */
+ NonCopyable() = default; /* Explicitly allows the empty constructor */
+ void *operator new(std::size_t) = delete; /* Removes new NonCopyable */
};
</pre></div>
-<p>This feature is specific to C++ only. The defaulting/deleting is currently ignored, because SWIG
-automatically produces wrappers for special constructors and operators specific to the target language.</p>
+<p>
+Wrappers for deleted functions will not be available in the target language.
+Wrappers for defaulted functions will of course be available in the target language.
+Explicitly defaulted functions have no direct effect for SWIG wrapping as the declaration is handled
+much like any other method declaration parsed by SWIG.
+</p>
<H3><a name="CPlusPlus11_Type_long_long_int"></a>7.2.22 Type long long int</H3>
diff --git a/Examples/test-suite/c_delete.i b/Examples/test-suite/c_delete.i
new file mode 100644
index 000000000..d47032095
--- /dev/null
+++ b/Examples/test-suite/c_delete.i
@@ -0,0 +1,14 @@
+%module c_delete
+
+/* check C++ delete keyword is okay in C wrappers */
+
+%inline %{
+struct delete {
+ int delete;
+};
+%}
+
+%rename(DeleteGlobalVariable) delete;
+%inline %{
+int delete = 0;
+%}
diff --git a/Examples/test-suite/c_delete_function.i b/Examples/test-suite/c_delete_function.i
new file mode 100644
index 000000000..e1fba7495
--- /dev/null
+++ b/Examples/test-suite/c_delete_function.i
@@ -0,0 +1,7 @@
+%module c_delete_function
+
+/* check C++ delete keyword is okay in C wrappers */
+
+%inline %{
+double delete(double d) { return d; }
+%}
diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk
index e25d36715..0d360830d 100644
--- a/Examples/test-suite/common.mk
+++ b/Examples/test-suite/common.mk
@@ -552,6 +552,8 @@ endif
C_TEST_CASES += \
arrays \
bom_utf8 \
+ c_delete \
+ c_delete_function \
char_constant \
const_const \
constant_expr \
diff --git a/Examples/test-suite/cpp11_default_delete.i b/Examples/test-suite/cpp11_default_delete.i
index be4cc6cc9..49a677060 100644
--- a/Examples/test-suite/cpp11_default_delete.i
+++ b/Examples/test-suite/cpp11_default_delete.i
@@ -1,9 +1,12 @@
-/* This testcase checks whether SWIG correctly parses the default and delete
- keywords which keep or remove default C++ object construction functions. */
+/* This testcase checks whether SWIG correctly parses C++11 explicitly defaulted functions and deleted functions */
%module cpp11_default_delete
-%{
-#include <stdlib.h>
+%warnfilter(SWIGWARN_LANG_OVERLOAD_IGNORED, SWIGWARN_LANG_OVERLOAD_SHADOW) trivial::trivial(trivial&&);
+%warnfilter(SWIGWARN_LANG_OVERLOAD_IGNORED, SWIGWARN_LANG_OVERLOAD_SHADOW) trivial::operator =(trivial&&);
+
+%rename(Assignment) *::operator=;
+
+%inline %{
class NonCopyable {
public:
@@ -14,11 +17,56 @@ public:
};
struct A1 {
- void f(int i);
- void f(double i) = delete; /* Don't cast double to int. Compiler returns an error */
+ void func(int i) {}
+ A1() = default;
+ ~A1() = default;
+ void func(double i) = delete; /* Don't cast double to int. Compiler returns an error */
+private:
+ A1(const A1&);
};
+A1::A1(const A1&) = default;
+
struct A2 {
- void f(int i);
- template<class T> void f(T) = delete; /* Only accept int */
+ void func(int i) {}
+ virtual void fff(int) = delete;
+ virtual ~A2() = default;
+ template<class T> void func(T) = delete;
+};
+
+struct trivial {
+ trivial() = default;
+ trivial(const trivial&) = default;
+ trivial(trivial&&) = default;
+ trivial& operator=(const trivial&) = default;
+ trivial& operator=(trivial&&) = default;
+ ~trivial() = default;
+};
+
+struct nontrivial1 {
+ nontrivial1();
+};
+nontrivial1::nontrivial1() = default;
+
+struct sometype {
+ sometype() = delete;
+ sometype(int) = delete;
+ sometype(double);
+};
+sometype::sometype(double) {}
+
+/* Not working with prerelease of gcc-4.8
+struct nonew {
+ void *operator new(std::size_t) = delete;
+ void *operator new[](std::size_t) = delete;
+};
+*/
+
+struct moveonly {
+ moveonly() = default;
+ moveonly(const moveonly&) = delete;
+ moveonly(moveonly&&) = default;
+ moveonly& operator=(const moveonly&) = delete;
+ moveonly& operator=(moveonly&&) = default;
+ ~moveonly() = default;
};
%}
diff --git a/Source/CParse/cscanner.c b/Source/CParse/cscanner.c
index e91dfb3d3..8b484f8a7 100644
--- a/Source/CParse/cscanner.c
+++ b/Source/CParse/cscanner.c
@@ -728,6 +728,9 @@ int yylex(void) {
if (strcmp(yytext, "delete") == 0) {
return (DELETE_KW);
}
+ if (strcmp(yytext, "default") == 0) {
+ return (DEFAULT);
+ }
if (strcmp(yytext, "using") == 0) {
return (USING);
}
diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y
index ce0c91c43..1328d6e0d 100644
--- a/Source/CParse/parser.y
+++ b/Source/CParse/parser.y
@@ -447,6 +447,14 @@ static void add_symbols(Node *n) {
n = nextSibling(n);
continue;
}
+ if (cparse_cplusplus) {
+ String *value = Getattr(n, "value");
+ if (value && Strcmp(value, "delete") == 0) {
+ /* C++11 deleted definition / deleted function */
+ SetFlag(n,"deleted");
+ SetFlag(n,"feature:ignore");
+ }
+ }
if (only_csymbol || GetFlag(n,"feature:ignore")) {
/* Only add to C symbol table and continue */
Swig_symbol_add(0, n);
@@ -1715,7 +1723,7 @@ static void tag_nodes(Node *n, const_String_or_char_ptr attrname, DOH *value) {
%token NATIVE INLINE
%token TYPEMAP EXCEPT ECHO APPLY CLEAR SWIGTEMPLATE FRAGMENT
%token WARN
-%token LESSTHAN GREATERTHAN DELETE_KW
+%token LESSTHAN GREATERTHAN DELETE_KW DEFAULT
%token LESSTHANOREQUALTO GREATERTHANOREQUALTO EQUALTO NOTEQUALTO
%token ARROW
%token QUESTIONMARK
@@ -1775,7 +1783,7 @@ static void tag_nodes(Node *n, const_String_or_char_ptr attrname, DOH *value) {
%type <str> ellipsis variadic;
%type <type> type rawtype type_right anon_bitfield_type decltype ;
%type <bases> base_list inherit raw_inherit;
-%type <dtype> definetype def_args etype;
+%type <dtype> definetype def_args etype default_delete deleted_definition explicit_default;
%type <dtype> expr exprnum exprcompound valexpr;
%type <id> ename ;
%type <id> template_decl;
@@ -4696,6 +4704,8 @@ cpp_constructor_decl : storage_class type LPAREN parms RPAREN ctor_end {
Delete(code);
}
SetFlag($$,"feature:new");
+ if ($6.defarg)
+ Setattr($$,"value",$6.defarg);
} else {
$$ = 0;
}
@@ -4723,6 +4733,8 @@ cpp_destructor_decl : NOT idtemplate LPAREN parms RPAREN cpp_end {
}
Setattr($$,"throws",$6.throws);
Setattr($$,"throw",$6.throwf);
+ if ($6.val)
+ Setattr($$,"value",$6.val);
add_symbols($$);
}
@@ -4738,9 +4750,8 @@ cpp_destructor_decl : NOT idtemplate LPAREN parms RPAREN cpp_end {
Delete(name);
Setattr($$,"throws",$7.throws);
Setattr($$,"throw",$7.throwf);
- if ($7.val) {
- Setattr($$,"value","0");
- }
+ if ($7.val)
+ Setattr($$,"value",$7.val);
if (Len(scanner_ccode)) {
String *code = Copy(scanner_ccode);
Setattr($$,"code",code);
@@ -4982,11 +4993,19 @@ cpp_swig_directive: pragma_directive { $$ = $1; }
cpp_end : cpp_const SEMI {
Clear(scanner_ccode);
+ $$.val = 0;
+ $$.throws = $1.throws;
+ $$.throwf = $1.throwf;
+ }
+ | cpp_const EQUAL default_delete SEMI {
+ Clear(scanner_ccode);
+ $$.val = $3.val;
$$.throws = $1.throws;
$$.throwf = $1.throwf;
}
| cpp_const LBRACE {
skip_balanced('{','}');
+ $$.val = 0;
$$.throws = $1.throws;
$$.throwf = $1.throwf;
}
@@ -6143,11 +6162,15 @@ definetype : { /* scanner_check_typedef(); */ } expr {
} else if ($$.type != T_CHAR && $$.type != T_WSTRING && $$.type != T_WCHAR) {
$$.rawval = 0;
}
+ $$.qualifier = 0;
$$.bitfield = 0;
$$.throws = 0;
$$.throwf = 0;
scanner_ignore_typedef();
}
+ | default_delete {
+ $$ = $1;
+ }
/*
| string {
$$.val = NewString($1);
@@ -6160,6 +6183,38 @@ definetype : { /* scanner_check_typedef(); */ } expr {
*/
;
+default_delete : deleted_definition {
+ $$ = $1;
+ }
+ | explicit_default {
+ $$ = $1;
+ }
+ ;
+
+/* For C++ deleted definition '= delete' */
+deleted_definition : DELETE_KW {
+ $$.val = NewString("delete");
+ $$.rawval = 0;
+ $$.type = T_STRING;
+ $$.qualifier = 0;
+ $$.bitfield = 0;
+ $$.throws = 0;
+ $$.throwf = 0;
+ }
+ ;
+
+/* For C++ explicitly defaulted functions '= default' */
+explicit_default : DEFAULT {
+ $$.val = NewString("default");
+ $$.rawval = 0;
+ $$.type = T_STRING;
+ $$.qualifier = 0;
+ $$.bitfield = 0;
+ $$.throws = 0;
+ $$.throwf = 0;
+ }
+ ;
+
/* Some stuff for handling enums */
ename : ID { $$ = $1; }
@@ -6711,6 +6766,7 @@ template_decl : LESSTHAN valparms GREATERTHAN {
;
idstring : ID { $$ = $1; }
+ | default_delete { $$ = $1.val; }
| string { $$ = $1; }
;
diff --git a/Source/Modules/allocate.cxx b/Source/Modules/allocate.cxx
index dee044bf3..b7daae59c 100644
--- a/Source/Modules/allocate.cxx
+++ b/Source/Modules/allocate.cxx
@@ -659,7 +659,7 @@ Allocate():
}
if (!Getattr(n, "allocate:has_destructor")) {
- /* No destructor was defined. We need to check a few things here too */
+ /* No destructor was defined */
List *bases = Getattr(n, "allbases");
int allows_destruct = 1;
@@ -676,13 +676,13 @@ Allocate():
}
if (!Getattr(n, "allocate:has_assign")) {
- /* No destructor was defined. We need to check a few things here too */
+ /* No assignment operator was defined */
List *bases = Getattr(n, "allbases");
int allows_assign = 1;
for (int i = 0; i < Len(bases); i++) {
Node *n = Getitem(bases, i);
- /* If base class does not allow default destructor, we don't allow it either */
+ /* If base class does not allow assignment, we don't allow it either */
if (Getattr(n, "allocate:has_assign")) {
allows_assign = !Getattr(n, "allocate:noassign");
}
@@ -693,13 +693,13 @@ Allocate():
}
if (!Getattr(n, "allocate:has_new")) {
- /* No destructor was defined. We need to check a few things here too */
+ /* No new operator was defined */
List *bases = Getattr(n, "allbases");
int allows_new = 1;
for (int i = 0; i < Len(bases); i++) {
Node *n = Getitem(bases, i);
- /* If base class does not allow default destructor, we don't allow it either */
+ /* If base class does not allow new operator, we don't allow it either */
if (Getattr(n, "allocate:has_new")) {
allows_new = !Getattr(n, "allocate:nonew");
}
@@ -779,18 +779,26 @@ Allocate():
if (cplus_mode != PUBLIC) {
if (Strcmp(name, "operator =") == 0) {
/* Look for a private assignment operator */
- Setattr(inclass, "allocate:has_assign", "1");
+ if (!GetFlag(n, "deleted"))
+ Setattr(inclass, "allocate:has_assign", "1");
Setattr(inclass, "allocate:noassign", "1");
} else if (Strcmp(name, "operator new") == 0) {
/* Look for a private new operator */
- Setattr(inclass, "allocate:has_new", "1");
+ if (!GetFlag(n, "deleted"))
+ Setattr(inclass, "allocate:has_new", "1");
Setattr(inclass, "allocate:nonew", "1");
}
} else {
if (Strcmp(name, "operator =") == 0) {
- Setattr(inclass, "allocate:has_assign", "1");
+ if (!GetFlag(n, "deleted"))
+ Setattr(inclass, "allocate:has_assign", "1");
+ else
+ Setattr(inclass, "allocate:noassign", "1");
} else if (Strcmp(name, "operator new") == 0) {
- Setattr(inclass, "allocate:has_new", "1");
+ if (!GetFlag(n, "deleted"))
+ Setattr(inclass, "allocate:has_new", "1");
+ else
+ Setattr(inclass, "allocate:nonew", "1");
}
/* Look for smart pointer operator */
if ((Strcmp(name, "operator ->") == 0) && (!GetFlag(n, "feature:ignore"))) {