Commit 0964c98c by Janis Johnson Committed by Janis Johnson

fnptr-by-value-1_main.c: New file.

	* gcc.dg/compat/fnptr-by-value-1_main.c: New file.
	* gcc.dg/compat/fnptr-by-value-1_x.c: New file.
	* gcc.dg/compat/fnptr-by-value-1_y.c: New file.
	* gcc.dg/compat/struct-align-1.h: New file.
	* gcc.dg/compat/struct-align-1_main.c: New file.
	* gcc.dg/compat/struct-align-1_x.c: New file.
	* gcc.dg/compat/struct-align-1_y.c: New file.
	* gcc.dg/compat/struct-align-2.h: New file.
	* gcc.dg/compat/struct-align-2_main.c: New file.
	* gcc.dg/compat/struct-align-2_x.c: New file.
	* gcc.dg/compat/struct-align-2_y.c: New file.

From-SVN: r68901
parent c3427c7d
2003-07-03 Janis Johnson <janis187@us.ibm.com> 2003-07-03 Janis Johnson <janis187@us.ibm.com>
* gcc.dg/compat/fnptr-by-value-1_main.c: New file.
* gcc.dg/compat/fnptr-by-value-1_x.c: New file.
* gcc.dg/compat/fnptr-by-value-1_y.c: New file.
* gcc.dg/compat/struct-align-1.h: New file.
* gcc.dg/compat/struct-align-1_main.c: New file.
* gcc.dg/compat/struct-align-1_x.c: New file.
* gcc.dg/compat/struct-align-1_y.c: New file.
* gcc.dg/compat/struct-align-2.h: New file.
* gcc.dg/compat/struct-align-2_main.c: New file.
* gcc.dg/compat/struct-align-2_x.c: New file.
* gcc.dg/compat/struct-align-2_y.c: New file.
* gcc.dg/compat/compat-common.h (DEBUG_FINI): New. * gcc.dg/compat/compat-common.h (DEBUG_FINI): New.
* gcc.dg/compat/scalar-by-value-1_x.c: Use it. * gcc.dg/compat/scalar-by-value-1_x.c: Use it.
* gcc.dg/compat/scalar-by-value-2_x.c: Ditto. * gcc.dg/compat/scalar-by-value-2_x.c: Ditto.
......
/* Test passing function pointers. */
extern void fnptr_by_value_1_x (void);
extern void exit (int);
int fails;
int
main ()
{
fnptr_by_value_1_x ();
exit (0);
}
#include "compat-common.h"
/* Turn off checking for variable arguments with -DSKIPVA. */
#ifdef SKIPVA
const int test_va = 0;
#else
const int test_va = 1;
#endif
typedef void (*fpi)(int);
typedef void (*fpd)(double);
extern void test1a (fpi);
extern void test1b (fpi, int);
extern void test1c (double, fpd);
extern void test2a (fpi, fpd);
extern void test2b (fpi, fpd, int);
extern void test2c (fpi, int, fpd);
extern void test2d (int, fpi, fpd);
extern void test2e (fpi, fpd, int, double);
extern void test2f (fpi, int, fpd, double);
extern void test2g (fpi, int, double, fpd);
extern void test2h (double, fpd, fpi, int);
extern void test2i (double, fpd, int, fpi);
extern void test2j (int, double, fpi, fpd);
int f1_val;
double f2_val;
void f1 (int i) { f1_val = i; }
void f2 (double x) { f2_val = x; }
void
checki (int x, int v)
{
if (x != v)
DEBUG_CHECK
}
void
checkd (double x, double v)
{
if (x != v)
DEBUG_CHECK
}
void
testit (void)
{
DEBUG_FPUTS ("test1a: ");
test1a (f1);
checki (f1_val, 1);
DEBUG_NL;
DEBUG_FPUTS ("test1b: ");
test1b (f1, 2);
checki (f1_val, 2);
DEBUG_NL;
DEBUG_FPUTS ("test1c: ");
test1c (3.0, f2);
checkd (f2_val, 3.0);
DEBUG_NL;
DEBUG_FPUTS ("test2a: ");
test2a (f1, f2);
checki (f1_val, 10);
checkd (f2_val, 10.0);
DEBUG_NL;
DEBUG_FPUTS ("test2b: ");
test2b (f1, f2, 11);
checki (f1_val, 11);
checkd (f2_val, 11.0);
DEBUG_NL;
DEBUG_FPUTS ("test2c: ");
test2c (f1, 12, f2);
checki (f1_val, 12);
checkd (f2_val, 12.0);
DEBUG_NL;
DEBUG_FPUTS ("test2d: ");
test2d (13, f1, f2);
checki (f1_val, 13);
checkd (f2_val, 13.0);
DEBUG_NL;
DEBUG_FPUTS ("test2e: ");
test2e (f1, f2, 14, 15.0);
checki (f1_val, 14);
checkd (f2_val, 15.0);
DEBUG_NL;
DEBUG_FPUTS ("test2f: ");
test2f (f1, 16, f2, 17.0);
checki (f1_val, 16);
checkd (f2_val, 17.0);
DEBUG_NL;
DEBUG_FPUTS ("test2g: ");
test2g (f1, 18, 19.0, f2);
checki (f1_val, 18);
checkd (f2_val, 19.0);
DEBUG_NL;
DEBUG_FPUTS ("test2h: ");
test2h (20.0, f2, f1, 21);
checkd (f2_val, 20.0);
checki (f1_val, 21);
DEBUG_NL;
DEBUG_FPUTS ("test2i: ");
test2i (22.0, f2, 23, f1);
checkd (f2_val, 22.0);
checki (f1_val, 23);
DEBUG_NL;
DEBUG_FPUTS ("test2j: ");
test2j (24, 25.0, f1, f2);
checki (f1_val, 24);
checkd (f2_val, 25.0);
if (test_va)
{
DEBUG_NL;
DEBUG_FPUTS ("testva: ");
testva (1, f1);
DEBUG_NL;
DEBUG_FPUTS (" ");
testva (2, f1, f1);
DEBUG_NL;
DEBUG_FPUTS (" ");
testva (3, f1, f1, f1);
DEBUG_NL;
DEBUG_FPUTS (" ");
testva (4, f1, f1, f1, f1);
DEBUG_NL;
DEBUG_FPUTS (" ");
testva (5, f1, f1, f1, f1, f1);
DEBUG_NL;
DEBUG_FPUTS (" ");
testva (6, f1, f1, f1, f1, f1, f1);
DEBUG_NL;
DEBUG_FPUTS (" ");
testva (7, f1, f1, f1, f1, f1, f1, f1);
DEBUG_NL;
DEBUG_FPUTS (" ");
testva (8, f1, f1, f1, f1, f1, f1, f1, f1);
DEBUG_NL;
DEBUG_FPUTS (" ");
testva (9, f1, f1, f1, f1, f1, f1, f1, f1, f1);
DEBUG_NL;
DEBUG_FPUTS (" ");
testva (10, f1, f1, f1, f1, f1, f1, f1, f1, f1, f1);
DEBUG_NL;
DEBUG_FPUTS (" ");
testva (11, f1, f1, f1, f1, f1, f1, f1, f1, f1, f1, f1);
DEBUG_NL;
DEBUG_FPUTS (" ");
testva (12, f1, f1, f1, f1, f1, f1, f1, f1, f1, f1, f1, f1);
}
DEBUG_NL;
}
void
fnptr_by_value_1_x ()
{
DEBUG_INIT
testit ();
DEBUG_FINI
if (fails != 0)
abort ();
}
#include <stdarg.h>
#include "compat-common.h"
typedef void (*fpi)(int);
typedef void (*fpd)(double);
extern int f1_val;
extern void checki (int, int);
void
test1a (fpi f)
{
(*f)(1);
}
void
test1b (fpi f, int i)
{
(*f)(i);
}
void
test1c (double x, fpd f)
{
(*f)(x);
}
void
test2a (fpi f1, fpd f2)
{
(*f1)(10);
(*f2)(10.0);
}
void
test2b (fpi f1, fpd f2, int i)
{
(*f1)(i);
(*f2)((double)i);
}
void
test2c (fpi f1, int i, fpd f2)
{
(*f1)(i);
(*f2)((double)i);
}
void
test2d (int i, fpi f1, fpd f2)
{
(*f1)(i);
(*f2)((double)i);
}
void
test2e (fpi f1, fpd f2, int i, double x)
{
(*f1)(i);
(*f2)(x);
}
void
test2f (fpi f1, int i, fpd f2, double x)
{
(*f1)(i);
(*f2)(x);
}
void
test2g (fpi f1, int i, double x, fpd f2)
{
(*f1)(i);
(*f2)(x);
}
void
test2h (double x, fpd f1, fpi f2, int i)
{
(*f1)(x);
(*f2)(i);
}
void
test2i (double x, fpd f1, int i, fpi f2)
{
(*f1)(x);
(*f2)(i);
}
void
test2j (int i, double x, fpi f1, fpd f2)
{
(*f1)(i);
(*f2)(x);
}
void
testva (int n, ...)
{
int i;
va_list ap;
va_start (ap, n);
for (i = 0; i < n; i++)
{
fpi fp = va_arg (ap, fpi);
(*fp)(i);
checki (f1_val, i);
}
}
/* Define several variants of a struct for which the alignment differs
between powerpc64-linux and powerpc64-aix. This might be interesting
for other targets as well. */
#define DESC_orig "original"
struct B1_orig {
char c;
double d;
};
struct A2_orig {
double d;
};
struct B2_orig {
char c;
struct A2_orig a2;
};
struct A3_orig {
double d;
int i;
};
struct B3_orig {
char c;
struct A3_orig a3;
};
#define DESC_p_all "packed attribute for all"
struct B1_p_all {
char c;
double d;
} __attribute__ ((packed));
struct A2_p_all {
double d;
} __attribute__ ((packed));
struct B2_p_all {
char c;
struct A2_p_all a2;
} __attribute__ ((packed));
struct A3_p_all {
double d;
int i;
} __attribute__ ((packed));
struct B3_p_all {
char c;
struct A3_p_all a3;
} __attribute__ ((packed));
#define DESC_p_inner "packed attribute for inner"
struct B1_p_inner {
char c;
double d;
};
struct A2_p_inner {
double d;
} __attribute__ ((packed));
struct B2_p_inner {
char c;
struct A2_p_inner a2;
};
struct A3_p_inner {
double d;
int i;
} __attribute__ ((packed));
struct B3_p_inner {
char c;
struct A3_p_inner a3;
};
#define DESC_p_outer "packed attribute for outer"
struct B1_p_outer {
char c;
double d;
} __attribute__ ((packed));
struct A2_p_outer {
double d;
};
struct B2_p_outer {
char c;
struct A2_p_outer a2;
} __attribute__ ((packed));
struct A3_p_outer {
double d;
int i;
};
struct B3_p_outer {
char c;
struct A3_p_outer a3;
} __attribute__ ((packed));
#define DESC_a_max "maximum useful struct alignment for all"
struct B1_a_max {
char c;
double d;
} __attribute__ ((aligned));
struct A2_a_max {
double d;
} __attribute__ ((aligned));
struct B2_a_max {
char c;
struct A2_a_max a2;
} __attribute__ ((aligned));
struct A3_a_max {
double d;
int i;
} __attribute__ ((aligned));
struct B3_a_max {
char c;
struct A3_a_max a3;
} __attribute__ ((aligned));
#define DESC_m_outer_p_inner "maximum alignment for outer, packed inner"
struct B1_m_outer_p_inner {
char c;
double d;
} __attribute__ ((aligned)) __attribute__ ((packed));
struct A2_m_outer_p_inner {
double d;
} __attribute__ ((packed));
struct B2_m_outer_p_inner {
char c;
struct A2_m_outer_p_inner a2;
} __attribute__ ((aligned));
struct A3_m_outer_p_inner {
double d;
int i;
} __attribute__ ((packed));
struct B3_m_outer_p_inner {
char c;
struct A3_m_outer_p_inner a3;
} __attribute__ ((aligned));
#define DESC_m_inner_p_outer "maximum alignment for inner, packed outer"
struct B1_m_inner_p_outer {
char c;
double d;
} __attribute__ ((aligned)) __attribute__ ((packed));
struct A2_m_inner_p_outer {
double d;
} __attribute__ ((aligned));
struct B2_m_inner_p_outer {
char c;
struct A2_m_inner_p_outer a2;
} __attribute__ ((packed));
struct A3_m_inner_p_outer {
double d;
int i;
} __attribute__ ((aligned));
struct B3_m_inner_p_outer {
char c;
struct A3_m_inner_p_outer a3;
} __attribute__ ((packed));
/* Test compatibility of structure layout and alignment for structs
which contain doubles. The original structs here are from PR 10645. */
extern void struct_align_1_x (void);
extern void exit (int);
int fails;
int
main ()
{
struct_align_1_x ();
exit (0);
}
#include "compat-common.h"
#include "struct-align-1.h"
#define SETUP(NAME,V1,V2,V3) \
char v1_##NAME = V1; \
double v2_##NAME = V2; \
int v3_##NAME = V3; \
\
struct B1_##NAME b1_##NAME = { V1, V2 }; \
struct B2_##NAME b2_##NAME = { V1, { V2 } }; \
struct B3_##NAME b3_##NAME = { V1, { V2, V3 } }; \
\
struct B1_##NAME ab1_##NAME[2] = \
{ { V1, V2 }, { V1, V2 } }; \
struct B2_##NAME ab2_##NAME[2] = \
{ { V1, { V2 } }, { V1, { V2 } } }; \
struct B3_##NAME ab3_##NAME[2] = \
{ { V1, { V2, V3 } }, { V1, { V2, V3 } } }; \
\
extern void test_##NAME (void); \
extern void checkp1_##NAME (struct B1_##NAME *); \
extern void checkp2_##NAME (struct B2_##NAME *); \
extern void checkp3_##NAME (struct B3_##NAME *); \
extern void checkg1_##NAME (void); \
extern void checkg2_##NAME (void); \
extern void checkg3_##NAME (void); \
\
void \
pass1_##NAME (struct B1_##NAME s) \
{ \
checkp1_##NAME (&s); \
} \
\
void \
pass2_##NAME (struct B2_##NAME s) \
{ \
checkp2_##NAME (&s); \
} \
\
void \
pass3_##NAME (struct B3_##NAME s) \
{ \
checkp3_##NAME (&s); \
} \
\
struct B1_##NAME \
return1_##NAME (void) \
{ \
return ab1_##NAME[0]; \
} \
\
struct B2_##NAME \
return2_##NAME (void) \
{ \
return ab2_##NAME[0]; \
} \
\
struct B3_##NAME \
return3_##NAME (void) \
{ \
return ab3_##NAME[0]; \
}
#define CHECK(NAME) test_##NAME()
SETUP (orig, 49, 1.0, 111111)
SETUP (p_all, 50, 2.0, 222222)
SETUP (p_inner, 51, 3.0, 333333)
SETUP (p_outer, 52, 4.0, 444444)
SETUP (a_max, 53, 5.0, 555555)
SETUP (m_outer_p_inner, 54, 6.0, 666666)
SETUP (m_inner_p_outer, 55, 7.0, 777777)
void
struct_align_1_x (void)
{
DEBUG_INIT
CHECK (orig);
CHECK (p_all);
CHECK (p_inner);
CHECK (p_outer);
CHECK (a_max);
CHECK (m_outer_p_inner);
CHECK (m_inner_p_outer);
DEBUG_FINI
if (fails != 0)
abort ();
}
#include "compat-common.h"
#include "struct-align-1.h"
#define TEST(NAME) \
extern char v1_##NAME; \
extern double v2_##NAME; \
extern int v3_##NAME; \
\
extern struct B1_##NAME b1_##NAME, ab1_##NAME[2]; \
extern struct B2_##NAME b2_##NAME, ab2_##NAME[2]; \
extern struct B3_##NAME b3_##NAME, ab3_##NAME[2]; \
\
extern void pass1_##NAME (struct B1_##NAME); \
extern void pass2_##NAME (struct B2_##NAME); \
extern void pass3_##NAME (struct B3_##NAME); \
extern struct B1_##NAME return1_##NAME (void); \
extern struct B2_##NAME return2_##NAME (void); \
extern struct B3_##NAME return3_##NAME (void); \
\
void \
checkp1_##NAME (struct B1_##NAME *p) \
{ \
if (p->c != v1_##NAME) \
DEBUG_CHECK; \
if (p->d != v2_##NAME) \
DEBUG_CHECK; \
} \
\
void \
checkp2_##NAME (struct B2_##NAME *p) \
{ \
if (p->c != v1_##NAME) \
DEBUG_CHECK; \
if (p->a2.d != v2_##NAME) \
DEBUG_CHECK; \
} \
\
void \
checkp3_##NAME (struct B3_##NAME *p) \
{ \
if (p->c != v1_##NAME) \
DEBUG_CHECK; \
if (p->a3.d != v2_##NAME) \
DEBUG_CHECK; \
if (p->a3.i != v3_##NAME) \
DEBUG_CHECK; \
} \
\
void \
test_##NAME (void) \
{ \
struct B1_##NAME s1; \
struct B2_##NAME s2; \
struct B3_##NAME s3; \
DEBUG_FPUTS (DESC_##NAME); \
DEBUG_NL; \
DEBUG_FPUTS (" global variable"); \
checkp1_##NAME (&b1_##NAME); \
checkp2_##NAME (&b2_##NAME); \
checkp3_##NAME (&b3_##NAME); \
DEBUG_NL; \
DEBUG_FPUTS (" global array"); \
checkp1_##NAME (&ab1_##NAME[1]); \
checkp2_##NAME (&ab2_##NAME[1]); \
checkp3_##NAME (&ab3_##NAME[1]); \
DEBUG_NL; \
DEBUG_FPUTS (" argument"); \
pass1_##NAME (b1_##NAME); \
pass2_##NAME (b2_##NAME); \
pass3_##NAME (b3_##NAME); \
DEBUG_NL; \
DEBUG_FPUTS (" function result"); \
s1 = return1_##NAME (); \
checkp1_##NAME (&s1); \
s2 = return2_##NAME (); \
checkp2_##NAME (&s2); \
s3 = return3_##NAME (); \
checkp3_##NAME (&s3); \
DEBUG_NL; \
}
TEST (orig)
TEST (p_all)
TEST (p_inner)
TEST (p_outer)
TEST (a_max)
TEST (m_outer_p_inner)
TEST (m_inner_p_outer)
/* Define several variants of struct epoll_event from the Linux kernel,
specifying various attributes that affect alignment and size.
This test was developed for systems for which int is 32 bits and
long long is 64 bits; it might need to be disabled for systems where
either of those is not true. */
#define DESC_orig "original"
struct epoll_event_orig {
unsigned int events;
unsigned long long data;
};
#define DESC_structmax "maximum useful struct alignment"
struct epoll_event_structmax {
unsigned int events;
unsigned long long data;
} __attribute__ ((aligned));
#define DESC_struct4 "4-byte struct alignment"
struct epoll_event_struct4 {
unsigned int events;
unsigned long long data;
} __attribute__ ((aligned(4)));
#define DESC_struct8 "8-byte struct alignment"
struct epoll_event_struct8 {
unsigned int events;
unsigned long long data;
} __attribute__ ((aligned(8)));
#define DESC_data4 "4-byte alignment for data"
struct epoll_event_data4 {
unsigned int events;
unsigned long long data __attribute__ ((aligned(4)));
};
#define DESC_data8 "8-byte alignment for data"
struct epoll_event_data8 {
unsigned int events;
unsigned long long data __attribute__ ((aligned(8)));
};
#define DESC_p "packed attribute"
struct epoll_event_p {
unsigned int events;
unsigned long long data;
} __attribute__ ((packed));
#define DESC_pstruct4 "packed attribute, 4-byte struct alignment"
struct epoll_event_pstruct4 {
unsigned int events;
unsigned long long data;
} __attribute__ ((packed)) __attribute__ ((aligned(4)));
#define DESC_pstruct8 "packed attribute, 8-byte struct alignment"
struct epoll_event_pstruct8 {
unsigned int events;
unsigned long long data;
} __attribute__ ((packed)) __attribute__ ((aligned(8)));
#define DESC_pdata4 "packed attribute, 4-byte alignment for data"
struct epoll_event_pdata4 {
unsigned int events;
unsigned long long data __attribute__ ((aligned(4)));
} __attribute__ ((packed));
#define DESC_pdata8 "packed attribute, 8-byte alignment for data"
struct epoll_event_pdata8 {
unsigned int events;
unsigned long long data __attribute__ ((aligned(8)));
} __attribute__ ((packed));
/* Test compatibility of structure layout and alignment for a struct
containing an int and a long long, with various combinations of
packed and aligned attributes. The struct is from the Linux kernel. */
extern void struct_align_2_x (void);
extern void exit (int);
int fails;
int
main ()
{
struct_align_2_x ();
exit (0);
}
/* Disable this test for 16-bit targets. */
#if __INT_MAX__ > 32767
#include "compat-common.h"
#include "struct-align-2.h"
#define SETUP(NAME,V1,V2,V3) \
struct outer_##NAME { \
int i; \
struct epoll_event_##NAME ee; \
}; \
\
unsigned int v1_##NAME = V1; \
unsigned int v2_##NAME = V2; \
unsigned long long v3_##NAME = V3; \
\
struct outer_##NAME s_##NAME[2] = \
{ {V1, { V2, V3 } }, { V1, { V2, V3 } } }; \
\
extern void test_##NAME (void); \
extern void checkp_##NAME (struct outer_##NAME *); \
extern void checkg_##NAME (void); \
\
void \
pass_##NAME (struct outer_##NAME s) \
{ \
checkp_##NAME (&s); \
} \
\
struct outer_##NAME \
return_##NAME (void) \
{ \
return s_##NAME[0]; \
}
#define CHECK(NAME) \
test_##NAME()
SETUP (orig,101, 102, 0x0101010101010101ULL)
SETUP (structmax, 103, 104, 0x1212121212121212ULL)
SETUP (struct4, 105, 106, 0x2323232323232323ULL)
SETUP (struct8, 107, 108, 0x3434343434343434ULL)
SETUP (data4, 109, 110, 0x4545454545454545ULL)
SETUP (data8, 111, 112, 0x5656565656565656ULL)
SETUP (p, 113, 114, 0x6767676767676767ULL)
SETUP (pstruct4, 115, 116, 0x7878787878787878ULL)
SETUP (pstruct8, 117, 118, 0x8989898989898989ULL)
SETUP (pdata4, 119, 120, 0x9A9A9A9A9A9A9A9AULL)
SETUP (pdata8, 121, 122, 0xABABABABABABABABULL)
void
struct_align_2_x (void)
{
DEBUG_INIT
CHECK (orig);
CHECK (structmax);
CHECK (struct4);
CHECK (struct8);
CHECK (data4);
CHECK (data8);
CHECK (p);
CHECK (pstruct4);
CHECK (pstruct8);
CHECK (pdata4);
CHECK (pdata8);
DEBUG_FINI
if (fails != 0)
abort ();
}
#else
void struct_align_2_x (void) {}
#endif /* __INT_MAX__ */
/* Disable this test for 16-bit targets. */
#if __INT_MAX__ > 32767
#include "compat-common.h"
#include "struct-align-2.h"
#define TEST(NAME) \
struct outer_##NAME { \
int i; \
struct epoll_event_##NAME ee; \
}; \
\
extern unsigned int v1_##NAME; \
extern unsigned int v2_##NAME; \
extern unsigned long long v3_##NAME; \
\
extern struct outer_##NAME s_##NAME[2]; \
\
extern void pass_##NAME (struct outer_##NAME); \
extern struct outer_##NAME return_##NAME (void); \
\
void \
checkp_##NAME (struct outer_##NAME *p) \
{ \
if (p->i != v1_##NAME) \
DEBUG_CHECK; \
if (p->ee.events != v2_##NAME) \
DEBUG_CHECK; \
if (p->ee.data != v3_##NAME) \
DEBUG_CHECK; \
} \
\
void \
test_##NAME (void) \
{ \
struct outer_##NAME s; \
DEBUG_FPUTS (DESC_##NAME); \
DEBUG_NL; \
DEBUG_FPUTS (" global array"); \
checkp_##NAME (&s_##NAME[0]); \
checkp_##NAME (&s_##NAME[1]); \
DEBUG_NL; \
DEBUG_FPUTS (" argument"); \
pass_##NAME (s_##NAME[0]); \
DEBUG_NL; \
DEBUG_FPUTS (" function result"); \
s = return_##NAME (); \
checkp_##NAME (&s); \
DEBUG_NL; \
}
TEST (orig)
TEST (structmax)
TEST (struct4)
TEST (struct8)
TEST (data4)
TEST (data8)
TEST (p)
TEST (pstruct4)
TEST (pstruct8)
TEST (pdata4)
TEST (pdata8)
#else
int i; /* prevent compiling an empty file */
#endif /* __INT_MAX__ */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment