Message ID | 56B911A2.9000100@redhat.com |
---|---|
State | New |
Headers | show |
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
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); +}