Add testcase from bugzilla #301204.
Testcase by Chantry Xavier (shiningxc@gmail.com).


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@12715 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/configure.in b/configure.in
index 4ccbc1f..5c66f45 100644
--- a/configure.in
+++ b/configure.in
@@ -1747,6 +1747,25 @@
 AM_CONDITIONAL(BUILD_AVX_TESTS, test x$ac_have_as_avx = xyes)
 
 
+# Does the C compiler support the "ifunc" attribute
+# Note, this doesn't generate a C-level symbol.  It generates a
+# automake-level symbol (BUILD_IFUNC_TESTS), used in test Makefile.am's
+AC_MSG_CHECKING([if gcc supports the ifunc attribute])
+
+AC_COMPILE_IFELSE([AC_LANG_SOURCE([[]], [[
+  void bar(void) {}
+  void foo(void) __attribute__((ifunc("bar")));
+]])], [
+ac_have_ifunc_attr=yes
+AC_MSG_RESULT([yes])
+], [
+ac_have_ifunc_attr=no
+AC_MSG_RESULT([no])
+])
+
+AM_CONDITIONAL(BUILD_IFUNC_TESTS, test x$ac_have_ifunc_attr = xyes)
+
+
 # XXX JRS 2010 Oct 13: what is this for?  For sure, we don't need this
 # when building the tool executables.  I think we should get rid of it.
 #
diff --git a/none/tests/Makefile.am b/none/tests/Makefile.am
index 17ad44d..7fec5b2 100644
--- a/none/tests/Makefile.am
+++ b/none/tests/Makefile.am
@@ -95,6 +95,7 @@
 	fork.stderr.exp fork.stdout.exp fork.vgtest \
 	fucomip.stderr.exp fucomip.vgtest \
 	gxx304.stderr.exp gxx304.vgtest \
+	ifunc.stderr.exp ifunc.stdout.exp ifunc.vgtest \
 	manythreads.stdout.exp manythreads.stderr.exp manythreads.vgtest \
 	map_unaligned.stderr.exp map_unaligned.vgtest \
 	map_unmap.stderr.exp map_unmap.stdout.exp map_unmap.vgtest \
@@ -227,6 +228,9 @@
    check_PROGRAMS += rlimit64_nofile 
 endif
 
+if BUILD_IFUNC_TESTS
+   check_PROGRAMS += ifunc
+endif
 
 AM_CFLAGS   += $(AM_FLAG_M3264_PRI)
 AM_CXXFLAGS += $(AM_FLAG_M3264_PRI)
diff --git a/none/tests/ifunc.c b/none/tests/ifunc.c
new file mode 100644
index 0000000..523d923
--- /dev/null
+++ b/none/tests/ifunc.c
@@ -0,0 +1,21 @@
+/* This test made valgrind run in an infinite loop. See bugzilla #301204 */
+#include <stdio.h>
+
+static void mytest(int d)
+{
+    printf("%d\n", d);
+}
+
+static void (*resolve_test(void))(void)
+{
+    return (void (*)(void))&mytest;
+}
+
+void test(int d)
+    __attribute__((ifunc("resolve_test")));
+
+int main()
+{
+    test(5);
+    return 0;
+}
diff --git a/none/tests/ifunc.stderr.exp b/none/tests/ifunc.stderr.exp
new file mode 100644
index 0000000..139597f
--- /dev/null
+++ b/none/tests/ifunc.stderr.exp
@@ -0,0 +1,2 @@
+
+
diff --git a/none/tests/ifunc.stdout.exp b/none/tests/ifunc.stdout.exp
new file mode 100644
index 0000000..7ed6ff8
--- /dev/null
+++ b/none/tests/ifunc.stdout.exp
@@ -0,0 +1 @@
+5
diff --git a/none/tests/ifunc.vgtest b/none/tests/ifunc.vgtest
new file mode 100644
index 0000000..42b8f9f
--- /dev/null
+++ b/none/tests/ifunc.vgtest
@@ -0,0 +1 @@
+prog: ifunc