2013-05-21 Cary Coutant gold/ * symtab.h (Symbol::is_cxx_vtable): New function. * target-reloc.h (relocate_section): Check for vtable symbol. * testsuite/Makefile.am (missing_key_func.sh): New test case. * testsuite/Makefile.in: Regenerate. * testsuite/missing_key_func.cc: New test source. * testsuite/missing_key_func.sh: New test script. diff --git a/gold/symtab.h b/gold/symtab.h index 689d99f..9299ea8 100644 --- a/gold/symtab.h +++ b/gold/symtab.h @@ -817,6 +817,11 @@ class Symbol is_predefined() const { return this->is_predefined_; } + // Return true if this is a C++ vtable symbol. + bool + is_cxx_vtable() const + { return is_prefix_of("_ZTV", this->name_); } + protected: // Instances of this class should always be created at a specific // size. diff --git a/gold/target-reloc.h b/gold/target-reloc.h index cf5e389..b544c78 100644 --- a/gold/target-reloc.h +++ b/gold/target-reloc.h @@ -411,7 +411,13 @@ relocate_section( } if (issue_undefined_symbol_error(sym)) - gold_undefined_symbol_at_location(sym, relinfo, i, offset); + { + gold_undefined_symbol_at_location(sym, relinfo, i, offset); + if (sym->is_cxx_vtable()) + gold_info(_("%s: the vtable symbol may be undefined because " + "the class is missing its key function"), + program_name); + } else if (sym != NULL && sym->visibility() != elfcpp::STV_DEFAULT && (sym->is_undefined() || sym->is_from_dynobj())) diff --git a/gold/testsuite/Makefile.am b/gold/testsuite/Makefile.am index 785adab..4936e14 100644 --- a/gold/testsuite/Makefile.am +++ b/gold/testsuite/Makefile.am @@ -974,6 +974,20 @@ debug_msg.err: debug_msg.o odr_violation1.o odr_violation2.o gcctestdir/ld exit 1; \ fi +# Test error message when a vtable is undefined. +check_SCRIPTS += missing_key_func.sh +check_DATA += missing_key_func.err +MOSTLYCLEANFILES += missing_key_func.err +missing_key_func.o: missing_key_func.cc + $(CXXCOMPILE) -O0 -g -c -o $@ $(srcdir)/missing_key_func.cc +missing_key_func.err: missing_key_func.o gcctestdir/ld + @echo $(CXXLINK) -Bgcctestdir/ -o missing_key_func missing_key_func.o "2>$@" + @if $(CXXLINK) -Bgcctestdir/ -o missing_key_func missing_key_func.o 2>$@; \ + then \ + echo 1>&2 "Link of missing_key_func should have failed"; \ + rm -f $@; \ + exit 1; \ + fi if HAVE_ZLIB diff --git a/gold/testsuite/Makefile.in b/gold/testsuite/Makefile.in index 1e00b15..495b7d0 100644 --- a/gold/testsuite/Makefile.in +++ b/gold/testsuite/Makefile.in @@ -69,6 +69,8 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \ # Test --detect-odr-violations +# Test error message when a vtable is undefined. + # Similar to --detect-odr-violations: check for undefined symbols in .so's # Test --dynamic-list, --dynamic-list-data, --dynamic-list-cpp-new, @@ -87,11 +89,11 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_sht_rel_addend_test.sh \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ merge_string_literals.sh \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_shared.sh weak_plt.sh \ -@GCC_TRUE@@NATIVE_LINKER_TRUE@ debug_msg.sh undef_symbol.sh \ -@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_1.sh ver_test_2.sh \ -@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_4.sh ver_test_5.sh \ -@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_7.sh ver_test_10.sh \ -@GCC_TRUE@@NATIVE_LINKER_TRUE@ relro_test.sh \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ debug_msg.sh missing_key_func.sh \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ undef_symbol.sh ver_test_1.sh \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_2.sh ver_test_4.sh \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_5.sh ver_test_7.sh \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_10.sh relro_test.sh \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_matching_test.sh \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_3.sh \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_4.sh \ @@ -122,7 +124,8 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_sht_rel_addend_test.stdout \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ merge_string_literals.stdout \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_shared.dbg \ -@GCC_TRUE@@NATIVE_LINKER_TRUE@ weak_plt_shared.so debug_msg.err +@GCC_TRUE@@NATIVE_LINKER_TRUE@ weak_plt_shared.so debug_msg.err \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ missing_key_func.err @GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_4 = incremental_test \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ incremental_test.cmdline \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ gc_comdat_test gc_tls_test \ @@ -225,7 +228,8 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ many_sections_check.h @GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_26 = many_sections_define.h \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ many_sections_check.h \ -@GCC_TRUE@@NATIVE_LINKER_TRUE@ debug_msg.err +@GCC_TRUE@@NATIVE_LINKER_TRUE@ debug_msg.err \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ missing_key_func.err @GCC_FALSE@initpri1_DEPENDENCIES = @NATIVE_LINKER_FALSE@initpri1_DEPENDENCIES = @GCC_FALSE@initpri2_DEPENDENCIES = @@ -3767,6 +3771,8 @@ weak_plt.sh.log: weak_plt.sh @p='weak_plt.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post) debug_msg.sh.log: debug_msg.sh @p='debug_msg.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post) +missing_key_func.sh.log: missing_key_func.sh + @p='missing_key_func.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post) undef_symbol.sh.log: undef_symbol.sh @p='undef_symbol.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post) ver_test_1.sh.log: ver_test_1.sh @@ -4663,6 +4669,16 @@ uninstall-am: @GCC_TRUE@@NATIVE_LINKER_TRUE@ rm -f $@; \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ exit 1; \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ fi +@GCC_TRUE@@NATIVE_LINKER_TRUE@missing_key_func.o: missing_key_func.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -O0 -g -c -o $@ $(srcdir)/missing_key_func.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@missing_key_func.err: missing_key_func.o gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ @echo $(CXXLINK) -Bgcctestdir/ -o missing_key_func missing_key_func.o "2>$@" +@GCC_TRUE@@NATIVE_LINKER_TRUE@ @if $(CXXLINK) -Bgcctestdir/ -o missing_key_func missing_key_func.o 2>$@; \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ then \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ echo 1>&2 "Link of missing_key_func should have failed"; \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ rm -f $@; \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ exit 1; \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ fi @GCC_TRUE@@HAVE_ZLIB_TRUE@@NATIVE_LINKER_TRUE@debug_msg_cdebug.o: debug_msg.cc gcctestdir/as @GCC_TRUE@@HAVE_ZLIB_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -Bgcctestdir/ -O0 -g -Wa,--compress-debug-sections -c -w -o $@ $(srcdir)/debug_msg.cc @GCC_TRUE@@HAVE_ZLIB_TRUE@@NATIVE_LINKER_TRUE@odr_violation1_cdebug.o: odr_violation1.cc gcctestdir/as diff --git a/gold/testsuite/missing_key_func.cc b/gold/testsuite/missing_key_func.cc new file mode 100644 index 0000000..5a5b7d9 --- /dev/null +++ b/gold/testsuite/missing_key_func.cc @@ -0,0 +1,46 @@ +// basic_test.cc -- a test case for gold + +// Copyright 2013 Free Software Foundation, Inc. +// Written by Cary Coutant . + +// This file is part of gold. + +// 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, write to the Free Software +// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +// MA 02110-1301, USA. + +// Define a class, but leave its key function undefined. + +class C +{ + public: + C() : c(1) { } + virtual void set(); + virtual void clear(); + int c; +}; + +void +C::clear() +{ + c = 0; +} + +int +main() +{ + C c; + c.clear(); + return c.c; +} diff --git a/gold/testsuite/missing_key_func.sh b/gold/testsuite/missing_key_func.sh new file mode 100755 index 0000000..54c7b57 --- /dev/null +++ b/gold/testsuite/missing_key_func.sh @@ -0,0 +1,58 @@ +#!/bin/sh + +# missing_key_func.sh -- a test case for printing error messages when +# a class is missing its key function. + +# Copyright 2013 Free Software Foundation, Inc. +# Written by Cary Coutant + +# This file is part of gold. + +# 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, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +# MA 02110-1301, USA. + +# This file goes with debug_msg.cc, a C++ source file constructed to +# have undefined references. We compile that file with debug +# information and then try to link it, and make sure the proper errors +# are displayed. The errors will be found in debug_msg.err. + +check() +{ + if ! grep -q "$2" "$1" + then + echo "Did not find expected error in $1:" + echo " $2" + echo "" + echo "Actual error output below:" + cat "$1" + exit 1 + fi +} + +check_missing() +{ + if grep -q "$2" "$1" + then + echo "Found unexpected error in $1:" + echo " $2" + echo "" + echo "Actual error output below:" + cat "$1" + exit 1 + fi +} + +check missing_key_func.err "error: undefined reference to 'vtable for C'" +check missing_key_func.err "class is missing its key function"