diff mbox

C++ PATCH for c++/69657 (abs not inlined)

Message ID 56B911A2.9000100@redhat.com
State New
Headers show

Commit Message

Jason Merrill Feb. 8, 2016, 10:07 p.m. UTC
The issue in this bug was that due to changes in the libstdc++ headers, 
the built-in abs declaration was getting hidden by a using-declaration, 
so that then when the built-in got an explicit declaration, the original 
declaration wasn't there anymore and so the new declaration didn't get 
marked as built-in.

Fixed by overloading an anticipated built-in rather than clobbering it 
when we see a using-declaration of the same name.

Tested x86_64-pc-linux-gnu, applying to trunk.

Comments

Rainer Orth Feb. 9, 2016, 8:29 p.m. UTC | #1
Jason Merrill <jason@redhat.com> writes:

> The issue in this bug was that due to changes in the libstdc++ headers, the
> built-in abs declaration was getting hidden by a using-declaration, so that
> then when the built-in got an explicit declaration, the original
> declaration wasn't there anymore and so the new declaration didn't get
> marked as built-in.
>
> Fixed by overloading an anticipated built-in rather than clobbering it when
> we see a using-declaration of the same name.
>
> Tested x86_64-pc-linux-gnu, applying to trunk.

This patch broke Solaris bootstrap (seen on i386-pc-solaris2.12):

/var/gcc/reghunt/trunk/gcc/c-family/c-lex.c: In function 'c_fileinfo* get_fileinfo(const char*)':
/var/gcc/reghunt/trunk/gcc/c-family/c-lex.c:102:62: error: overloaded function with no contextual type information
     file_info_tree = splay_tree_new ((splay_tree_compare_fn) strcmp,
                                                              ^~~~~~
/var/gcc/reghunt/trunk/gcc/c-family/c-lex.c:104:39: error: overloaded function with no contextual type information
          (splay_tree_delete_value_fn) free);
                                       ^~~~
make[3]: *** [c-family/c-lex.o] Error 1

Comparing c-lex.ii before and after the patch, I see that they differ
like this:

-# 508 "/var/gcc/reghunt/trunk/gcc/system.h"
+# 452 "/var/gcc/reghunt/trunk/gcc/system.h"
+extern void free (void *);
+# 496 "/var/gcc/reghunt/trunk/gcc/system.h"
+extern void *malloc (size_t);
+
+
+
+extern void *calloc (size_t, size_t);
+
+
+
+extern void *realloc (void *, size_t);
+
+
+
 }

and indeed auto-host.h changed:

--- /var/gcc/reghunt/of-no-cti/28675/gcc/auto-host.h    2016-02-09 19:53:23.6030
78417 +0100
+++ auto-host.h 2016-02-09 20:28:39.946901958 +0100
@@ -743 +743 @@
-#define HAVE_DECL_CALLOC 1
+#define HAVE_DECL_CALLOC 0
@@ -846 +846 @@
-#define HAVE_DECL_FREE 1
+#define HAVE_DECL_FREE 0
@@ -937 +937 @@
-#define HAVE_DECL_MALLOC 1
+#define HAVE_DECL_MALLOC 0
@@ -958 +958 @@
-#define HAVE_DECL_REALLOC 1
+#define HAVE_DECL_REALLOC 0

The calloc configure test now fails like this:

conftest.cpp: In function 'int main()':
conftest.cpp:150:28: error: overloaded function with no contextual type information
 char *(*pfn) = (char *(*)) calloc ;
                            ^~~~~~

The test boils down to

typedef unsigned int size_t;
namespace std {
extern void *calloc(size_t, size_t);
}
using std::calloc;
int
main ()
{
  char *(*pfn) = (char *(*)) calloc ;
  return 0;
}

	Rainer
diff mbox

Patch

commit 8f47c80051a73a75fb44900d9edb1444142c3d5f
Author: Jason Merrill <jason@redhat.com>
Date:   Mon Feb 8 16:39:42 2016 -0500

    	PR c++/69657
    	* name-lookup.c (do_nonmember_using_decl): Leave anticipated
    	built-ins alone.

diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 92d99aa..227d6f2 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -2583,15 +2583,6 @@  do_nonmember_using_decl (tree scope, tree name, tree oldval, tree oldtype,
       decls.value = NULL_TREE;
     }
 
-  /* It is impossible to overload a built-in function; any explicit
-     declaration eliminates the built-in declaration.  So, if OLDVAL
-     is a built-in, then we can just pretend it isn't there.  */
-  if (oldval
-      && TREE_CODE (oldval) == FUNCTION_DECL
-      && DECL_ANTICIPATED (oldval)
-      && !DECL_HIDDEN_FRIEND_P (oldval))
-    oldval = NULL_TREE;
-
   if (decls.value)
     {
       /* Check for using functions.  */
@@ -2610,6 +2601,10 @@  do_nonmember_using_decl (tree scope, tree name, tree oldval, tree oldtype,
 	    {
 	      tree new_fn = OVL_CURRENT (tmp);
 
+	      /* Don't import functions that haven't been declared.  */
+	      if (DECL_ANTICIPATED (new_fn))
+		continue;
+
 	      /* [namespace.udecl]
 
 		 If a function declaration in namespace scope or block
@@ -2627,13 +2622,13 @@  do_nonmember_using_decl (tree scope, tree name, tree oldval, tree oldtype,
 		    continue; /* this is a using decl */
 		  else if (compparms_for_decl_and_using_decl (new_fn, old_fn))
 		    {
-		      gcc_assert (!DECL_ANTICIPATED (old_fn)
-				  || DECL_HIDDEN_FRIEND_P (old_fn));
-
 		      /* There was already a non-using declaration in
 			 this scope with the same parameter types. If both
 			 are the same extern "C" functions, that's ok.  */
-		      if (decls_match (new_fn, old_fn))
+		      if (DECL_ANTICIPATED (old_fn)
+			  && !DECL_HIDDEN_FRIEND_P (old_fn))
+			/* Ignore anticipated built-ins.  */;
+		      else if (decls_match (new_fn, old_fn))
 			break;
 		      else
 			{
@@ -2669,6 +2664,14 @@  do_nonmember_using_decl (tree scope, tree name, tree oldval, tree oldtype,
 	}
       else
 	{
+	  /* If we're declaring a non-function and OLDVAL is an anticipated
+	     built-in, just pretend it isn't there.  */
+	  if (oldval
+	      && TREE_CODE (oldval) == FUNCTION_DECL
+	      && DECL_ANTICIPATED (oldval)
+	      && !DECL_HIDDEN_FRIEND_P (oldval))
+	    oldval = NULL_TREE;
+
 	  *newval = decls.value;
 	  if (oldval && !decls_match (*newval, oldval))
 	    error ("%qD is already declared in this scope", name);
diff --git a/gcc/testsuite/g++.dg/lookup/builtin6.C b/gcc/testsuite/g++.dg/lookup/builtin6.C
new file mode 100644
index 0000000..456ade7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/builtin6.C
@@ -0,0 +1,23 @@ 
+// PR c++/69657
+// { dg-options -fdump-tree-gimple }
+// { dg-final { scan-tree-dump "ABS_EXPR" "gimple" } }
+
+namespace foo
+{
+  inline double
+  abs(double x)
+  { return __builtin_fabs(x); }
+}
+using foo::abs;
+
+extern "C" int abs(int);
+
+namespace bar {
+  using ::abs;
+}
+
+int
+wrapper (int x)
+{
+  return bar::abs (x) + bar::abs(x);
+}