diff mbox

C++ PATCH for c++/45603 (ICE with user declaration of __cxa_guard_acquire)

Message ID 4E17409B.6000209@redhat.com
State New
Headers show

Commit Message

Jason Merrill July 8, 2011, 5:38 p.m. UTC
The testcase is kind of bogus, but we ought to be more robust.

Tested x86_64-pc-linux-gnu, applied to trunk.
diff mbox

Patch

commit f6ac9e35ced48b4e646f1cb0a8b5cab869ad91f6
Author: Jason Merrill <jason@redhat.com>
Date:   Fri Jul 8 13:05:01 2011 -0400

    	PR c++/45603
    	* decl.c (expand_static_init): Don't get confused by user
    	declaration of __cxa_guard_acquire.

diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index e36739b..266d049 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -6646,7 +6646,6 @@  expand_static_init (tree decl, tree init)
       tree if_stmt = NULL_TREE, inner_if_stmt = NULL_TREE;
       tree then_clause = NULL_TREE, inner_then_clause = NULL_TREE;
       tree guard, guard_addr;
-      tree acquire_fn, release_fn, abort_fn;
       tree flag, begin;
 
       /* Emit code to perform this initialization but once.  This code
@@ -6696,29 +6695,31 @@  expand_static_init (tree decl, tree init)
 
       if (flag_threadsafe_statics)
 	{
+	  tree vfntype = NULL_TREE;
+	  tree acquire_name, release_name, abort_name;
+	  tree acquire_fn, release_fn, abort_fn;
 	  guard_addr = build_address (guard);
 
-	  acquire_fn = get_identifier ("__cxa_guard_acquire");
-	  release_fn = get_identifier ("__cxa_guard_release");
-	  abort_fn = get_identifier ("__cxa_guard_abort");
-	  if (!get_global_value_if_present (acquire_fn, &acquire_fn))
-	    {
-	      tree vfntype = build_function_type_list (void_type_node,
-						       TREE_TYPE (guard_addr),
-						       NULL_TREE);
-	      acquire_fn = push_library_fn
-		(acquire_fn, build_function_type_list (integer_type_node,
+	  acquire_name = get_identifier ("__cxa_guard_acquire");
+	  release_name = get_identifier ("__cxa_guard_release");
+	  abort_name = get_identifier ("__cxa_guard_abort");
+	  acquire_fn = identifier_global_value (acquire_name);
+	  release_fn = identifier_global_value (release_name);
+	  abort_fn = identifier_global_value (abort_name);
+	  if (!acquire_fn)
+	    acquire_fn = push_library_fn
+	      (acquire_name, build_function_type_list (integer_type_node,
 						       TREE_TYPE (guard_addr),
 						       NULL_TREE),
-		 NULL_TREE);
-	      release_fn = push_library_fn (release_fn, vfntype, NULL_TREE);
-	      abort_fn = push_library_fn (abort_fn, vfntype, NULL_TREE);
-	    }
-	  else
-	    {
-	      release_fn = identifier_global_value (release_fn);
-	      abort_fn = identifier_global_value (abort_fn);
-	    }
+	       NULL_TREE);
+	  if (!release_fn || !abort_fn)
+	    vfntype = build_function_type_list (void_type_node,
+						TREE_TYPE (guard_addr),
+						NULL_TREE);
+	  if (!release_fn)
+	    release_fn = push_library_fn (release_name, vfntype, NULL_TREE);
+	  if (!abort_fn)
+	    abort_fn = push_library_fn (abort_name, vfntype, NULL_TREE);
 
 	  inner_if_stmt = begin_if_stmt ();
 	  finish_if_stmt_cond (build_call_n (acquire_fn, 1, guard_addr),
diff --git a/gcc/testsuite/g++.dg/abi/guard3.C b/gcc/testsuite/g++.dg/abi/guard3.C
new file mode 100644
index 0000000..fd9d00e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/guard3.C
@@ -0,0 +1,14 @@ 
+// PR c++/45603
+
+extern "C" int __cxa_guard_acquire();
+
+struct A
+{
+  ~A();
+};
+
+A* f()
+{
+  static A a;
+  return &a;
+}