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# The types we're going to test.
19
20set typelist {
21    char {unsigned char}
22    short {unsigned short}
23    int {unsigned int}
24    long {unsigned long}
25    {long long} {unsigned long long}
26    float
27    double {long double}
28}
29
30if {[has_int128_c]} {
31    # Note we don't check "unsigned __int128" yet because at least gcc
32    # canonicalizes the name to "__int128 unsigned", and there isn't a
33    # c-exp.y production for this.
34    # https://sourceware.org/bugzilla/show_bug.cgi?id=20991
35    lappend typelist __int128
36}
37
38# Build source file for testing alignment handling of language LANG.
39# Returns the name of the newly created source file.
40proc prepare_test_source_file { lang } {
41    global typelist
42
43    # Create the test file.
44
45    if { $lang == "c++" } {
46	set suffix "cpp"
47	set align_func "alignof"
48    } else {
49	set suffix "c"
50	set align_func "_Alignof"
51    }
52
53    set filename [standard_output_file "align.$suffix"]
54    set outfile [open $filename w]
55
56    # Prologue.
57    puts -nonewline $outfile "#define DEF(T,U) struct align_pair_ ## T ## _x_ ## U "
58    puts $outfile "{ T one; U two; }"
59    if { $lang == "c++" } {
60	puts -nonewline $outfile "#define DEF_WITH_1_STATIC(T,U) struct align_pair_static_ ## T ## _x_ ## U "
61	puts $outfile "{ static T one; U two; }"
62	puts -nonewline $outfile "#define DEF_WITH_2_STATIC(T,U) struct align_pair_static_ ## T ## _x_static_ ## U "
63	puts $outfile "{ static T one; static U two; }"
64    }
65    if { $lang == "c" } {
66	puts $outfile "unsigned a_void = ${align_func} (void);"
67    }
68
69    # First emit single items.
70    foreach type $typelist {
71	set utype [join [split $type] _]
72	if {$type != $utype} {
73	    puts $outfile "typedef $type $utype;"
74	}
75	puts $outfile "$type item_$utype;"
76	if { $lang == "c" } {
77	    puts $outfile "unsigned a_$utype\n  = ${align_func} ($type);"
78	}
79	set utype [join [split $type] _]
80    }
81
82    # Now emit all pairs.
83    foreach type $typelist {
84	set utype [join [split $type] _]
85	foreach inner $typelist {
86	    set uinner [join [split $inner] _]
87	    puts $outfile "DEF ($utype, $uinner);"
88	    set joined "${utype}_x_${uinner}"
89	    puts $outfile "struct align_pair_$joined item_${joined};"
90	    puts $outfile "unsigned a_${joined}"
91	    puts $outfile "  = ${align_func} (struct align_pair_${joined});"
92
93	    if { $lang == "c++" } {
94		puts $outfile "DEF_WITH_1_STATIC ($utype, $uinner);"
95		set joined "static_${utype}_x_${uinner}"
96		puts $outfile "struct align_pair_$joined item_${joined};"
97		puts $outfile "unsigned a_${joined}"
98		puts $outfile "  = ${align_func} (struct align_pair_${joined});"
99
100		puts $outfile "DEF_WITH_2_STATIC ($utype, $uinner);"
101		set joined "static_${utype}_x_static_${uinner}"
102		puts $outfile "struct align_pair_$joined item_${joined};"
103		puts $outfile "unsigned a_${joined}"
104		puts $outfile "  = ${align_func} (struct align_pair_${joined});"
105	    }
106	}
107    }
108
109    # Epilogue.
110    puts $outfile {
111	int main() {
112	    return 0;
113	}
114    }
115
116    close $outfile
117
118    return $filename
119}
120
121# Run the alignment test for the language LANG.
122proc run_alignment_test { lang } {
123    global testfile srcfile typelist
124    global subdir
125
126    set filename [prepare_test_source_file $lang]
127
128    set flags {debug}
129    if { "$lang" == "c++" } {
130	lappend flags "additional_flags=-std=c++11"
131    }
132    standard_testfile $filename
133    if {[prepare_for_testing "failed to prepare" "$testfile" $srcfile $flags]} {
134	return -1
135    }
136
137    if {![runto_main]} {
138	perror "test suppressed"
139	return
140    }
141
142    if { $lang == "c++" } {
143	set align_func "alignof"
144    } else {
145	set align_func "_Alignof"
146    }
147
148    foreach type $typelist {
149	set utype [join [split $type] _]
150	if { $lang == "c" } {
151	    set expected [get_integer_valueof a_$utype 0]
152	    gdb_test "print ${align_func}($type)" " = $expected"
153	}
154
155	foreach inner $typelist {
156	    set uinner [join [split $inner] _]
157	    set expected [get_integer_valueof a_${utype}_x_${uinner} 0]
158	    gdb_test "print ${align_func}(struct align_pair_${utype}_x_${uinner})" \
159		" = $expected"
160
161	    if { $lang == "c++" } {
162		set expected [get_integer_valueof a_static_${utype}_x_${uinner} 0]
163		gdb_test "print ${align_func}(struct align_pair_static_${utype}_x_${uinner})" \
164		    " = $expected"
165
166		set expected [get_integer_valueof a_static_${utype}_x_static_${uinner} 0]
167		gdb_test "print ${align_func}(struct align_pair_static_${utype}_x_static_${uinner})" \
168		    " = $expected"
169	    }
170	}
171    }
172
173    if { $lang == "c" } {
174	set expected [get_integer_valueof a_void 0]
175	gdb_test "print ${align_func}(void)" " = $expected"
176    }
177}
178
179run_alignment_test $lang
180