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