blob: e69fa2df2822119f83a79f2e15d2ea303d2e964b [file]
%module cpp11_auto_variable_new_expression
// An 'auto' variable initialised by a new-expression deduces a pointer to the type allocated. Each variable is passed
// to a function taking exactly the type it should deduce, which fails if SWIG deduced any other type.
// Read only, as setting a pointer variable warns that it may leak memory.
%immutable;
%warnfilter(SWIGWARN_CPP11_AUTO) plus_after_initialiser;
%warnfilter(SWIGWARN_CPP11_AUTO) plus_after_array;
%warnfilter(SWIGWARN_CPP11_AUTO) parenthesised_type_id;
%warnfilter(SWIGWARN_CPP11_AUTO) lambda_auto;
// A macro spanning more than one line gets locator comments round its expansion, which must not stop the deduction.
%define NEW_WIDGET(A, B)
new Widget(A, B)
%enddef
%{
#include <new>
#include <utility>
#define NEW_WIDGET(A, B) new Widget(A, B)
// Storage for the placement new-expression, which SWIG does not need to see.
static double placement_storage[4];
%}
%inline %{
struct Widget {
int value;
Widget() : value(7) {}
Widget(int a, int b) : value(a + b) {}
};
typedef Widget WidgetAlias;
namespace space {
struct Scoped {
int value;
Scoped() : value(11) {}
};
}
template<typename T> struct Box {
T value;
Box(T v) : value(v) {}
};
int global_count = 3;
int global_values[3] = {40, 41, 42};
int int_value(int *p) { return *p; }
int pointed_int_value(int **p) { return **p; }
int const_int_value(const int *p) { return *p; }
unsigned int unsigned_value(unsigned int *p) { return *p; }
unsigned int const_unsigned_value(const unsigned int *p) { return *p; }
unsigned long unsigned_long_value(unsigned long *p) { return *p; }
unsigned short unsigned_short_value(unsigned short *p) { return *p; }
int unsigned_char_value(unsigned char *p) { return *p; }
int signed_char_value(signed char *p) { return *p; }
double double_value(double *p) { return *p; }
int widget_value(Widget *w) { return w->value; }
int scoped_value(space::Scoped *s) { return s->value; }
int box_value(Box<int> *b) { return b->value; }
int pair_sum(std::pair<int, int> *p) { return p->first + p->second; }
int row_sum(int (*rows)[3], int row) { return rows[row][0] + rows[row][1] + rows[row][2]; }
int null_pointers(int **pointers, int count) { int n = 0; for (int i = 0; i < count; ++i) n += pointers[i] ? 0 : 1; return n; }
int null_widgets(Widget **widgets, int count) { int n = 0; for (int i = 0; i < count; ++i) n += widgets[i] ? 0 : 1; return n; }
int widget_at(Widget *widgets, int i) { return widgets[i].value; }
int int_at(int *values, int i) { return values[i]; }
// The forms of new-expression, each giving a pointer to what it allocates.
auto bare_int = new int;
auto parens_int = new int(5);
auto braced_int = new int{6};
auto nested_parens_int = new int((8));
auto const_int = new const int(9);
auto trailing_const_int = new int const(10);
auto double_number = new double(2.5);
// The fundamental types spelt with more than one word, in any order.
auto unsigned_int = new unsigned(12);
auto unsigned_int_empty = new unsigned int();
auto unsigned_int_array = new unsigned int[2]{24, 25};
auto const_unsigned_int = new const unsigned int(26);
auto unsigned_long_number = new unsigned long(27);
auto long_unsigned_int = new long unsigned int(28);
auto unsigned_short_number = new unsigned short(29);
auto unsigned_char_number = new unsigned char(30);
auto signed_char_number = new signed char(31);
auto plain_widget = new Widget;
auto args_widget = new Widget(1, 2);
auto braced_widget = new Widget{3, 4};
auto aliased_widget = new WidgetAlias(2, 3);
auto scoped_widget = new space::Scoped();
auto global_widget = new ::Widget(4, 4);
auto star_widget = new Widget(global_count > 2 ? 1 : 2, 3);
// A template-id, including one whose template arguments are separated by a comma.
auto boxed = new Box<int>(13);
auto paired = new std::pair<int, int>(3, 4);
// An array new-expression gives a pointer to the first element.
auto int_array = new int[3]{20, 21, 22};
auto sized_array = new int[global_count]();
auto widget_array = new Widget[2]{{1, 1}, {2, 3}};
auto rows = new int[2][3]{{1, 2, 3}, {4, 5, 6}};
auto int_pointers = new int *[2]();
auto widget_pointers = new Widget *[3]();
// A placement new-expression, and one naming the global allocation function.
auto placed_widget = new (placement_storage) Widget(5, 6);
auto nothrow_int = new (std::nothrow) int(14);
auto global_new_int = ::new int(23);
// The type allocated can itself be deduced.
auto auto_int = new auto(15);
auto auto_double = new auto(3.5);
auto const_auto_int = new const auto(16);
auto auto_braced = new auto{global_count};
auto auto_paren_address = new auto(&(global_count));
auto auto_unsigned = new auto(32u);
auto decltype_int = new decltype(global_count)(17);
// The placeholder is deduced from any expression an 'auto' variable is deduced from.
auto auto_sum = new auto(global_count + 1);
auto auto_scaled = new auto(global_count * 2.5);
auto auto_narrowed = new auto(static_cast<unsigned short>(global_count));
auto auto_widget = new auto(Widget(2, 5));
auto const_auto_difference = new const auto{global_count - 1};
// The placeholder is deduced from a subscript as well.
int *subscript_int = new auto(global_values[1]);
int *nested_subscript_int = new auto((global_values[0] + global_values[2]));
int *braced_subscript_int = new auto{global_values[2]};
auto subscript_auto = new auto(global_values[0]);
// An expression the grammar does not parse, such as a lambda, deduces no type but is kept as written.
int *lambda_int = new auto([](int x) { return x * 2; }(21));
int *nested_lambda_int = new auto(([](int x) { return x; }(40) + 3));
int *braced_lambda_int = new auto{[] { return 44; }()};
auto lambda_auto = new auto([](int x) { return x; });
// The placeholder can be decorated, and a declaration can declare more than one variable.
auto *decorated_widget = new Widget(9, 9);
const auto *decorated_const_int = new int(18);
auto first_int = new int(19), second_int = new int(20);
auto plain_number = 21, *number_pointer = new int(22);
namespace inner {
auto nested_widget = new Widget(10, 10);
}
auto macro_widget = NEW_WIDGET(6, 6);
// The new-expression is part of a larger expression, or is a form SWIG does not parse, and no type is deduced.
auto plus_after_initialiser = new int(5) + 0;
auto plus_after_array = new int[3] + 1;
auto parenthesised_type_id = new (int *[3]);
// An ordinary variable after all of these is still seen.
int after_all = 99;
%}
// The value of a new-expression default argument is compiled into the wrapper with compactdefaultargs.
%feature("compactdefaultargs") auto_default;
%feature("compactdefaultargs") subscript_default;
%feature("compactdefaultargs") lambda_default;
%inline %{
// GCC 11 and earlier take the 'auto' of 'new auto' in a default argument for an auto parameter, so they are given 'new int'.
#if defined(SWIG) || !defined(__GNUC__) || defined(__clang__) || __GNUC__ >= 12
#define NEW_AUTO new auto
#else
#define NEW_AUTO new int
#endif
int auto_default(int *p = NEW_AUTO(global_count + 4)) { int v = *p; delete p; return v; }
int subscript_default(int *p = NEW_AUTO(global_values[1])) { int v = *p; delete p; return v; }
int lambda_default(int *p = NEW_AUTO([] { return 43; }()), int k = 1) { int v = *p * k; delete p; return v; }
%}
%template(BoxInt) Box<int>;