Fix gdb.base/align-*.exp and Clang + LTO and AIX GCC
authorPedro Alves <pedro@palves.net>
Wed, 29 Mar 2023 12:21:20 +0000 (13:21 +0100)
committerPedro Alves <pedro@palves.net>
Thu, 6 Apr 2023 15:52:34 +0000 (16:52 +0100)
Clang with LTO (clang -flto) garbage collects unused global variables,
Thus, gdb.base/align-c.exp and gdb.base/align-c++.exp fail with
hundreds of FAILs like so:

 $ make check \
    TESTS="gdb.*/align-*.exp" \
    RUNTESTFLAGS="CC_FOR_TARGET='clang -flto' CXX_FOR_TARGET='clang++ -flto'"
 ...
 FAIL: gdb.base/align-c.exp: get integer valueof "a_char"
 FAIL: gdb.base/align-c.exp: print _Alignof(char)
 FAIL: gdb.base/align-c.exp: get integer valueof "a_char_x_char"
 FAIL: gdb.base/align-c.exp: print _Alignof(struct align_pair_char_x_char)
 FAIL: gdb.base/align-c.exp: get integer valueof "a_char_x_unsigned_char"
 ...

AIX GCC has the same issue, and there the easier way of adding
__attribute__((used)) to globals does not help.

So add explicit uses of all globals to the generated code.

For the C++ test, that reveals that the static variable members of the
generated structs are not defined anywhere, leading to undefined
references.  Fixed by emitting initialization for all static members.

Lastly, I noticed that CXX_FOR_TARGET was being ignored -- that's
because the align-c++.exp testcase is compiling with the C compiler
driver.  Fixed by passing "c++" as option to prepare_for_testing.

Change-Id: I874b717afde7b6fb1e45e526912b518a20a12716

gdb/testsuite/gdb.base/align.exp.tcl

index 6a75a14d8874ff8d2a910196d56bfdb729aad7fa..550afe1c47d39f1f67b9b46ed7a9c6dd3f16f6d5 100644 (file)
@@ -94,12 +94,15 @@ proc prepare_test_source_file { lang } {
                puts $outfile "DEF_WITH_1_STATIC ($utype, $uinner);"
                set joined "static_${utype}_x_${uinner}"
                puts $outfile "struct align_pair_$joined item_${joined};"
+               puts $outfile "$utype align_pair_${joined}::one = 0;"
                puts $outfile "unsigned a_${joined}"
                puts $outfile "  = ${align_func} (struct align_pair_${joined});"
 
                puts $outfile "DEF_WITH_2_STATIC ($utype, $uinner);"
                set joined "static_${utype}_x_static_${uinner}"
                puts $outfile "struct align_pair_$joined item_${joined};"
+               puts $outfile "$utype align_pair_${joined}::one = 0;"
+               puts $outfile "$uinner align_pair_${joined}::two = 0;"
                puts $outfile "unsigned a_${joined}"
                puts $outfile "  = ${align_func} (struct align_pair_${joined});"
            }
@@ -107,12 +110,53 @@ proc prepare_test_source_file { lang } {
     }
 
     # Epilogue.
-    puts $outfile {
+    puts $outfile "
        int main() {
-           return 0;
+    "
+
+    # Clang with LTO garbage collects unused global variables, even at
+    # -O0.  Likewise AIX GCC.  Add uses to all global variables to
+    # prevent it.
+
+    if { $lang == "c" } {
+       puts $outfile "a_void++;"
+    }
+
+    # First, add uses for single items.
+    foreach type $typelist {
+       set utype [join [split $type] _]
+       puts $outfile "item_$utype++;"
+       if { $lang == "c" } {
+           puts $outfile "a_$utype++;"
+       }
+    }
+
+    # Now add uses for all pairs.
+    foreach type $typelist {
+       set utype [join [split $type] _]
+       foreach inner $typelist {
+           set uinner [join [split $inner] _]
+           set joined "${utype}_x_${uinner}"
+           puts $outfile "item_${joined}.one++;"
+           puts $outfile "a_${joined}++;"
+
+           if { $lang == "c++" } {
+               set joined "static_${utype}_x_${uinner}"
+               puts $outfile "item_${joined}.one++;"
+               puts $outfile "a_${joined}++;"
+
+               set joined "static_${utype}_x_static_${uinner}"
+               puts $outfile "item_${joined}.one++;"
+               puts $outfile "a_${joined}++;"
+           }
        }
     }
 
+    puts $outfile "
+           return 0;
+       }
+    "
+
     close $outfile
 
     return $filename
@@ -127,6 +171,7 @@ proc run_alignment_test { lang } {
 
     set flags {debug}
     if { "$lang" == "c++" } {
+       lappend flags "c++"
        lappend flags "additional_flags=-std=c++11"
     }
     standard_testfile $filename