richi asked for a testcase for 60731, and since we didn't already have support for tests using dlopen, I had to add it. Does this approach make sense?
commit c0a86bbbb75658fcf59ae8f08c7e4588c865346c
Author: Jason Merrill <ja...@redhat.com>
Date:   Fri Apr 4 06:15:02 2014 -0400

    	PR c++/60731
    	* lib/gcc-dg.exp (dg-build-dso): New.
    	(gcc-dg-test-1): Handle dg-do-what "dso".
    	* lib/target-supports.exp (add_options_for_dlopen): New.
    	(check_effective_target_dlopen): Use it.
    	* g++.dg/dso/dlclose1.C: New.
    	* g++.dg/dso/dlclose1-dso.cc: New.

diff --git a/gcc/testsuite/g++.dg/dso/dlclose1-dso.cc b/gcc/testsuite/g++.dg/dso/dlclose1-dso.cc
new file mode 100644
index 0000000..cede483
--- /dev/null
+++ b/gcc/testsuite/g++.dg/dso/dlclose1-dso.cc
@@ -0,0 +1,9 @@
+// { dg-options "-fno-gnu-unique" }
+
+// A static variable in an inline function uses STB_GNU_UNIQUE normally.
+inline int foo() { static int i; return ++i; }
+
+extern "C" int fn()
+{
+  return foo();
+}
diff --git a/gcc/testsuite/g++.dg/dso/dlclose1.C b/gcc/testsuite/g++.dg/dso/dlclose1.C
new file mode 100644
index 0000000..95b6fea
--- /dev/null
+++ b/gcc/testsuite/g++.dg/dso/dlclose1.C
@@ -0,0 +1,30 @@
+// PR c++/60731
+// { dg-do run { target dlopen } }
+// { dg-add-options dlopen }
+// { dg-build-dso "dlclose1-dso.cc" }
+
+#include <dlfcn.h>
+extern "C" void abort();
+extern "C" int printf (const char *, ...);
+
+// Open and close the DSO for each call so that statics are reinitialized.
+int call()
+{
+  void *h = dlopen ("./dlclose1-dso.so", RTLD_NOW);
+  if (!h) { printf ("dlopen failed: %s\n", dlerror()); abort(); }
+  int (*fn)() = (int(*)())dlsym (h, "fn");
+  if (!fn) { printf ("dlsym failed: %s\n", dlerror()); abort(); }
+  int r = fn();
+  dlclose (h);
+  return r;
+}
+
+int main() {
+  int i = call();
+  int j = call();
+  if (i != j)
+    {
+      printf ("mismatch: %d != %d\n", i, j);
+      abort();
+    }
+}
diff --git a/gcc/testsuite/lib/gcc-dg.exp b/gcc/testsuite/lib/gcc-dg.exp
index f9d52bc..ce8ed5d 100644
--- a/gcc/testsuite/lib/gcc-dg.exp
+++ b/gcc/testsuite/lib/gcc-dg.exp
@@ -144,6 +144,11 @@ proc gcc-dg-test-1 { target_compile prog do_what extra_tool_flags } {
 	    # The following line is needed for targets like the i960 where
 	    # the default output file is b.out.  Sigh.
 	}
+	"dso" {
+	    set compile_type "executable"
+	    set output_file "[file rootname [file tail $prog]].so"
+	    set extra_tool_flags "$extra_tool_flags -fPIC -shared"
+	}
 	"repo" {
 	    set compile_type "object"
 	    set output_file "[file rootname [file tail $prog]].o"
@@ -181,6 +186,7 @@ proc gcc-dg-test-1 { target_compile prog do_what extra_tool_flags } {
 	lappend options "additional_flags=$extra_tool_flags"
     }
 
+    verbose "$target_compile $prog $output_file $compile_type $options" 4
     set comp_output [$target_compile "$prog" "$output_file" "$compile_type" $options]
 
     # Look for an internal compiler error, which sometimes masks the fact
@@ -208,6 +214,26 @@ proc gcc-dg-test { prog do_what extra_tool_flags } {
     return [gcc-dg-test-1 gcc_target_compile $prog $do_what $extra_tool_flags]
 }
 
+# Usage: { dg-build-dso "file.ext" }
+# Compiles the specified file into "file.so" (treating that compilation as
+# a separate test) for use by the main test, and schedules it for removal
+# when the main test is complete.  The DSO source file should not use "dg-do".
+# This relies on a couple of local variable names in dg-test.
+
+proc dg-build-dso { args } {
+    global srcdir dg-do-what-default
+    upvar prog main_file
+    upvar dg-final-code final-code
+
+    set file [lindex $args 1]
+    set dir "[file dirname $main_file]"
+    set dg-do-what-default dso
+    dg-test -keep-output $dir/$file "" ""
+
+    set output_file "[file rootname [file tail $file]].so"
+    append final-code "remove-build-file $output_file"
+}
+
 proc gcc-dg-prune { system text } {
     global additional_prunes
 
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index 0d2ccd5..6f4d28a 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -746,7 +746,14 @@ proc check_effective_target_mmap {} {
 
 # Return 1 if the target supports dlopen, 0 otherwise.
 proc check_effective_target_dlopen {} {
-    return [check_function_available "dlopen"]
+    return [check_no_compiler_messages dlopen executable {
+	#include <dlfcn.h>
+	int main(void) { dlopen ("dummy.so", RTLD_LAZY); }
+    } [add_options_for_dlopen ""]]
+}
+
+proc add_options_for_dlopen { flags } {
+    return "$flags -ldl"
 }
 
 # Return 1 if the target supports clone, 0 otherwise.

Reply via email to