aboutsummaryrefslogtreecommitdiff
path: root/gdb/testsuite/gdb.base/infcall-nested-structs.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/testsuite/gdb.base/infcall-nested-structs.c')
-rw-r--r--gdb/testsuite/gdb.base/infcall-nested-structs.c157
1 files changed, 157 insertions, 0 deletions
diff --git a/gdb/testsuite/gdb.base/infcall-nested-structs.c b/gdb/testsuite/gdb.base/infcall-nested-structs.c
new file mode 100644
index 0000000..f024ac6
--- /dev/null
+++ b/gdb/testsuite/gdb.base/infcall-nested-structs.c
@@ -0,0 +1,157 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2018 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* This file is used for testing GDBs ability to pass structures to, and
+ return structures from, functions. All of the structures in this test
+ are special in that they are small structures containing only 1 or 2
+ scalar fields, the fields can be inside nested structures, and there can
+ be empty structures around too.
+
+ This test was originally written for RiscV which has some special ABI
+ rules for structures like these, however, there should be no harm in
+ running these tests on other targets, though in many cases the
+ structures will treated no differently to the structures already covered
+ in the structs.exp test script. */
+
+#include <string.h>
+
+/* Useful abreviations. */
+typedef char tc;
+typedef short ts;
+typedef int ti;
+typedef long tl;
+typedef long long tll;
+typedef float tf;
+typedef double td;
+typedef long double tld;
+
+#ifdef TEST_COMPLEX
+typedef float _Complex tfc;
+typedef double _Complex tdc;
+typedef long double _Complex tldc;
+#endif /* TEST_COMPLEX */
+
+#define MAKE_CHECK_FUNCS(TYPE) \
+ int \
+ check_arg_ ## TYPE (struct TYPE arg) \
+ { \
+ return cmp_ ## TYPE (arg, ref_val_ ## TYPE); \
+ } \
+ \
+ struct TYPE \
+ rtn_str_ ## TYPE (void) \
+ { \
+ return (ref_val_ ## TYPE); \
+ }
+
+#define REF_VAL(NAME) struct NAME ref_val_ ## NAME
+#define ES(NAME) struct { } NAME
+
+#if defined tA && ! defined tB
+
+/* Structures with a single field nested to various depths, along with
+ some empty structures. */
+struct struct01 { ES(es1); struct { struct { tA a; } s1; } s2; };
+struct struct02 { tA a; struct { struct { ES(es1); } s1; } s2; };
+struct struct03 { struct { struct { ES(es1); } s1; } s2; ES(es1); struct { struct { tA a; } s3; } s4;};
+struct struct04 { ES(es1); ES(es2); tA a; ES(es3); };
+
+int cmp_struct01 (struct struct01 a, struct struct01 b)
+{ return a.s2.s1.a == b.s2.s1.a; }
+
+int cmp_struct02 (struct struct02 a, struct struct02 b)
+{ return a.a == b.a; }
+
+int cmp_struct03 (struct struct03 a, struct struct03 b)
+{ return a.s4.s3.a == b.s4.s3.a; }
+
+int cmp_struct04 (struct struct04 a, struct struct04 b)
+{ return a.a == b.a; }
+
+REF_VAL(struct01) = { {}, { { 'a' } } };
+REF_VAL(struct02) = { 'a', { { {} } } };
+REF_VAL(struct03) = { { { {} } }, {}, { { 'a' } } };
+REF_VAL(struct04) = { {}, {}, 'a', {} };
+
+#elif defined tA && defined tB
+
+/* These structures all have 2 fields, nested to various depths, along
+ with some empty structures. */
+struct struct01 { struct { tA a; } s1; ES (e1); struct { struct { tB b; } s2;} s3;};
+struct struct02 { struct { struct { tA a; } s1; ES(e1); } s2; struct { struct { tB b; } s3;} s4; ES(e2);};
+struct struct03 { ES(e1); tA a; ES (e2); struct { struct { tB b; } s2;} s3;};
+struct struct04 { ES(e1); ES (e2); struct { struct { struct { tA a; struct { ES(e3); } s1; tB b; } s2; } s3;} s4;};
+
+int cmp_struct01 (struct struct01 a, struct struct01 b)
+{ return a.s1.a == b.s1.a && a.s3.s2.b == b.s3.s2.b; }
+
+int cmp_struct02 (struct struct02 a, struct struct02 b)
+{ return a.s2.s1.a == b.s2.s1.a && a.s4.s3.b == b.s4.s3.b; }
+
+int cmp_struct03 (struct struct03 a, struct struct03 b)
+{ return a.a == b.a && a.s3.s2.b == b.s3.s2.b; }
+
+int cmp_struct04 (struct struct04 a, struct struct04 b)
+{ return a.s4.s3.s2.a == b.s4.s3.s2.a && a.s4.s3.s2.b == b.s4.s3.s2.b; }
+
+REF_VAL(struct01) = { { 'a' }, {}, { { '1' } } };
+REF_VAL(struct02) = { { { 'a' }, {} }, { { '1' } }, {} };
+REF_VAL(struct03) = { {}, 'a', {}, { { '1' } } };
+REF_VAL(struct04) = { {}, {}, { { { 'a', {}, '1'} } } } ;
+
+#else
+
+#error "Incorrect configuration of tA and tB defines"
+
+#endif
+
+/* Create all of the functions GDB will call to check functionality. */
+MAKE_CHECK_FUNCS(struct01)
+MAKE_CHECK_FUNCS(struct02)
+MAKE_CHECK_FUNCS(struct03)
+MAKE_CHECK_FUNCS(struct04)
+
+#define CALL_LINE(NAME) val += check_arg_ ## NAME (rtn_str_ ## NAME ())
+
+int
+call_all ()
+{
+ int val;
+
+ CALL_LINE(struct01);
+ CALL_LINE(struct02);
+ CALL_LINE(struct03);
+ CALL_LINE(struct04);
+
+ return (val != 4);
+}
+
+void
+breakpt (void)
+{
+ /* Nothing. */
+}
+
+int
+main ()
+{
+ int res;
+
+ res = call_all ();
+ breakpt (); /* Break Here. */
+ return res;
+}