1# Copyright 2018-2023 Free Software Foundation, Inc.
2
3# This program is free software; you can redistribute it and/or modify
4# it under the terms of the GNU General Public License as published by
5# the Free Software Foundation; either version 3 of the License, or
6# (at your option) any later version.
7#
8# This program is distributed in the hope that it will be useful,
9# but WITHOUT ANY WARRANTY; without even the implied warranty of
10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11# GNU General Public License for more details.
12#
13# You should have received a copy of the GNU General Public License
14# along with this program.  If not, see <http://www.gnu.org/licenses/>.
15
16# This file is part of the gdb testsuite
17
18# This tests that C++ alignof works in gdb, and that it agrees with
19# the compiler.
20
21if {[skip_cplus_tests]} { continue }
22
23# The types we're going to test.
24
25set typelist {
26    char {unsigned char}
27    short {unsigned short}
28    int {unsigned int}
29    long {unsigned long}
30    {long long} {unsigned long long}
31    float
32    double {long double}
33    empty
34    bigenum
35    vstruct
36    bfstruct
37    arrstruct
38    derived
39    derived2
40}
41
42if {[has_int128_cxx]} {
43    # Note we don't check "unsigned __int128" yet because at least gcc
44    # canonicalizes the name to "__int128 unsigned", and there isn't a
45    # c-exp.y production for this.
46    # https://sourceware.org/bugzilla/show_bug.cgi?id=20991
47    lappend typelist __int128
48}
49
50# Create the test file.
51
52set filename [standard_output_file align.cc]
53set outfile [open $filename w]
54
55# Prologue.
56puts $outfile {
57    template<typename T, typename U>
58    struct align_pair
59    {
60	T one;
61	U two;
62    };
63
64    template<typename T, typename U>
65    struct align_union
66    {
67	T one;
68	U two;
69    };
70
71    enum bigenum { VALUE = 0xffffffffull };
72
73    struct empty { };
74
75    struct vstruct { virtual ~vstruct() {}  char c; };
76
77    struct bfstruct { unsigned b : 3; };
78
79    struct arrstruct { short fld[7]; };
80
81    unsigned a_int3 = alignof (int[3]);
82
83#if defined __GNUC__ && !defined __clang__
84    /* As a GNU C extension, GCC allows void pointer arithmetic, with
85       sizeof (void) == 1.
86       Another GNU C extension is __alignof__, which can be used to get
87       __alignof__ (void), which is also 1.  This is unavailabe on clang.
88       GCC used to only warn for alignof (void), but starting with GCC 12.1,
89       as well as GCC 11.3, it will generate an error (note that using
90       -std=gnu++11 does not prevent the error).
91       So we avoid using alignof, and use __alignof__ instead.  */
92    unsigned a_void = __alignof__ (void);
93#else
94    /* No support for __alignof__ (void), hardcode value.  */
95    unsigned a_void = 1;
96#endif
97
98    struct base { char c; };
99    struct derived : public virtual base { int i; };
100
101    struct b2 : public virtual base { char d; };
102    struct derived2 : public b2, derived { char e; };
103}
104
105# First emit single items.
106foreach type $typelist {
107    set utype [join [split $type] _]
108    puts $outfile "$type item_$utype;"
109    puts $outfile "unsigned a_$utype\n  = alignof ($type);"
110    puts $outfile "typedef $type t_$utype;"
111    puts $outfile "t_$utype item_t_$utype;"
112}
113
114# Now emit all pairs.
115foreach type $typelist {
116    set utype [join [split $type] _]
117    foreach inner $typelist {
118	set uinner [join [split $inner] _]
119	puts $outfile "align_pair<$type, $inner> item_${utype}_x_${uinner};"
120	puts $outfile "unsigned a_${utype}_x_${uinner}"
121	puts $outfile "  = alignof (align_pair<$type, $inner>);"
122
123	puts $outfile "align_union<$type, $inner> item_${utype}_u_${uinner};"
124	puts $outfile "unsigned a_${utype}_u_${uinner}"
125	puts $outfile "  = alignof (align_union<$type, $inner>);"
126    }
127}
128
129# Epilogue.
130puts $outfile {
131    int main() {
132	return 0;
133    }
134}
135
136close $outfile
137
138standard_testfile $filename
139
140if {[prepare_for_testing "failed to prepare" $testfile $srcfile \
141	 {debug nowarnings c++ additional_flags=-std=c++11}]} {
142    return -1
143}
144
145if {![runto_main]} {
146    perror "test suppressed"
147    return
148}
149
150proc maybe_xfail {type} {
151    # See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69560
152    # The g++ implementation of alignof is changing to match C11.
153    if {[is_x86_like_target]
154	&& [test_compiler_info {gcc-[0-8]-*}]
155	&& ($type == "double" || $type == "long long"
156	    || $type == "unsigned long long")} {
157	setup_xfail *-*-*
158    }
159}
160
161foreach type $typelist {
162    set utype [join [split $type] _]
163    set expected [get_integer_valueof a_$utype 0]
164
165    maybe_xfail $type
166    gdb_test "print alignof($type)" " = $expected"
167
168    maybe_xfail $type
169    gdb_test "print alignof(t_$utype)" " = $expected"
170
171    maybe_xfail $type
172    gdb_test "print alignof(typeof(item_$utype))" " = $expected"
173
174    foreach inner $typelist {
175	set uinner [join [split $inner] _]
176	set expected [get_integer_valueof a_${utype}_x_${uinner} 0]
177	gdb_test "print alignof(align_pair<${type},${inner}>)" " = $expected"
178
179	set expected [get_integer_valueof a_${utype}_u_${uinner} 0]
180	gdb_test "print alignof(align_union<${type},${inner}>)" " = $expected"
181    }
182}
183
184set expected [get_integer_valueof a_int3 0]
185gdb_test "print alignof(int\[3\])" " = $expected"
186
187set expected [get_integer_valueof a_void 0]
188gdb_test "print alignof(void)" " = $expected"
189