From 44fd0e80635189f48f24654cb1e9620c39d5314b Mon Sep 17 00:00:00 2001 From: Ollie Wild Date: Fri, 17 Aug 2007 21:42:38 +0000 Subject: [PATCH] re PR c++/31749 (ICE with invalid redeclaration of builtin) PR c++/31749 gcc/cp/ * name-lookup.c (do_nonmember_using_decl): Shift implicit type declarations into appropriate slots for comparison. Fix type comparison. gcc/testsuite/ * g++.dg/lookup/builtin3.C: New test. * g++.dg/lookup/builtin4.C: New test. * g++.dg/lookup/using19.C: New test. From-SVN: r127600 --- gcc/cp/ChangeLog | 7 ++ gcc/cp/name-lookup.c | 163 ++++++++++++++----------- gcc/testsuite/ChangeLog | 7 ++ gcc/testsuite/g++.dg/lookup/builtin3.C | 15 +++ gcc/testsuite/g++.dg/lookup/builtin4.C | 15 +++ gcc/testsuite/g++.dg/lookup/using19.C | 21 ++++ 6 files changed, 157 insertions(+), 71 deletions(-) create mode 100644 gcc/testsuite/g++.dg/lookup/builtin3.C create mode 100644 gcc/testsuite/g++.dg/lookup/builtin4.C create mode 100644 gcc/testsuite/g++.dg/lookup/using19.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index f01075db591..9556496041f 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2007-08-17 Ollie Wild + + PR c++/31749 + * name-lookup.c (do_nonmember_using_decl): Shift implicit type + declarations into appropriate slots for comparison. Fix type + comparison. + 2007-08-17 Paolo Carlini PR c++/32112 diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index 48b387a747f..5f7e718d328 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -2099,6 +2099,20 @@ do_nonmember_using_decl (tree scope, tree name, tree oldval, tree oldtype, return; } + /* Shift the old and new bindings around so we're comparing class and + enumeration names to each other. */ + if (oldval && DECL_IMPLICIT_TYPEDEF_P (oldval)) + { + oldtype = oldval; + oldval = NULL_TREE; + } + + if (decls.value && DECL_IMPLICIT_TYPEDEF_P (decls.value)) + { + decls.type = decls.value; + 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. */ @@ -2108,87 +2122,91 @@ do_nonmember_using_decl (tree scope, tree name, tree oldval, tree oldtype, && !DECL_HIDDEN_FRIEND_P (oldval)) oldval = NULL_TREE; - /* Check for using functions. */ - if (decls.value && is_overloaded_fn (decls.value)) + if (decls.value) { - tree tmp, tmp1; - - if (oldval && !is_overloaded_fn (oldval)) - { - if (!DECL_IMPLICIT_TYPEDEF_P (oldval)) - error ("%qD is already declared in this scope", name); - oldval = NULL_TREE; - } - - *newval = oldval; - for (tmp = decls.value; tmp; tmp = OVL_NEXT (tmp)) + /* Check for using functions. */ + if (is_overloaded_fn (decls.value)) { - tree new_fn = OVL_CURRENT (tmp); + tree tmp, tmp1; - /* [namespace.udecl] + if (oldval && !is_overloaded_fn (oldval)) + { + error ("%qD is already declared in this scope", name); + oldval = NULL_TREE; + } - If a function declaration in namespace scope or block - scope has the same name and the same parameter types as a - function introduced by a using declaration the program is - ill-formed. */ - for (tmp1 = oldval; tmp1; tmp1 = OVL_NEXT (tmp1)) + *newval = oldval; + for (tmp = decls.value; tmp; tmp = OVL_NEXT (tmp)) { - tree old_fn = OVL_CURRENT (tmp1); - - if (new_fn == old_fn) - /* The function already exists in the current namespace. */ - break; - else if (OVL_USED (tmp1)) - continue; /* this is a using decl */ - else if (compparms (TYPE_ARG_TYPES (TREE_TYPE (new_fn)), - TYPE_ARG_TYPES (TREE_TYPE (old_fn)))) + tree new_fn = OVL_CURRENT (tmp); + + /* [namespace.udecl] + + If a function declaration in namespace scope or block + scope has the same name and the same parameter types as a + function introduced by a using declaration the program is + ill-formed. */ + for (tmp1 = oldval; tmp1; tmp1 = OVL_NEXT (tmp1)) { - gcc_assert (!DECL_ANTICIPATED (old_fn) - || DECL_HIDDEN_FRIEND_P (old_fn)); + tree old_fn = OVL_CURRENT (tmp1); - /* 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 (new_fn == old_fn) + /* The function already exists in the current namespace. */ break; - else + else if (OVL_USED (tmp1)) + continue; /* this is a using decl */ + else if (compparms (TYPE_ARG_TYPES (TREE_TYPE (new_fn)), + TYPE_ARG_TYPES (TREE_TYPE (old_fn)))) { - error ("%qD is already declared in this scope", name); - break; + 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)) + break; + else + { + error ("%qD is already declared in this scope", name); + break; + } } } - } - - /* If we broke out of the loop, there's no reason to add - this function to the using declarations for this - scope. */ - if (tmp1) - continue; - /* If we are adding to an existing OVERLOAD, then we no - longer know the type of the set of functions. */ - if (*newval && TREE_CODE (*newval) == OVERLOAD) - TREE_TYPE (*newval) = unknown_type_node; - /* Add this new function to the set. */ - *newval = build_overload (OVL_CURRENT (tmp), *newval); - /* If there is only one function, then we use its type. (A - using-declaration naming a single function can be used in - contexts where overload resolution cannot be - performed.) */ - if (TREE_CODE (*newval) != OVERLOAD) - { - *newval = ovl_cons (*newval, NULL_TREE); - TREE_TYPE (*newval) = TREE_TYPE (OVL_CURRENT (tmp)); + /* If we broke out of the loop, there's no reason to add + this function to the using declarations for this + scope. */ + if (tmp1) + continue; + + /* If we are adding to an existing OVERLOAD, then we no + longer know the type of the set of functions. */ + if (*newval && TREE_CODE (*newval) == OVERLOAD) + TREE_TYPE (*newval) = unknown_type_node; + /* Add this new function to the set. */ + *newval = build_overload (OVL_CURRENT (tmp), *newval); + /* If there is only one function, then we use its type. (A + using-declaration naming a single function can be used in + contexts where overload resolution cannot be + performed.) */ + if (TREE_CODE (*newval) != OVERLOAD) + { + *newval = ovl_cons (*newval, NULL_TREE); + TREE_TYPE (*newval) = TREE_TYPE (OVL_CURRENT (tmp)); + } + OVL_USED (*newval) = 1; } - OVL_USED (*newval) = 1; + } + else + { + *newval = decls.value; + if (oldval && !decls_match (*newval, oldval)) + error ("%qD is already declared in this scope", name); } } else - { - *newval = decls.value; - if (oldval && !decls_match (*newval, oldval)) - error ("%qD is already declared in this scope", name); - } + *newval = oldval; if (decls.type && TREE_CODE (decls.type) == TREE_LIST) { @@ -2198,13 +2216,16 @@ do_nonmember_using_decl (tree scope, tree name, tree oldval, tree oldtype, else { *newtype = decls.type; - if (oldtype && *newtype && !same_type_p (oldtype, *newtype)) - { - error ("using declaration %qD introduced ambiguous type %qT", - name, oldtype); - return; - } + if (oldtype && *newtype && !decls_match (oldtype, *newtype)) + error ("%qD is already declared in this scope", name); } + + /* If *newval is empty, shift any class or enumeration name down. */ + if (!*newval) + { + *newval = *newtype; + *newtype = NULL_TREE; + } } /* Process a using-declaration at function scope. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e08a3272c34..2a637d5f372 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2007-08-17 Ollie Wild + + PR c++/31749 + * g++.dg/lookup/builtin3.C: New test. + * g++.dg/lookup/builtin4.C: New test. + * g++.dg/lookup/using19.C: New test. + 2007-08-17 Paolo Carlini PR c++/32190 diff --git a/gcc/testsuite/g++.dg/lookup/builtin3.C b/gcc/testsuite/g++.dg/lookup/builtin3.C new file mode 100644 index 00000000000..3a29d878313 --- /dev/null +++ b/gcc/testsuite/g++.dg/lookup/builtin3.C @@ -0,0 +1,15 @@ +// Copyright (C) 2007 Free Software Foundation +// Contributed by Ollie Wild +// Origin: Volker Reichelt +// { dg-do compile } + +// PR 31749: ICE with redeclaration of builtin + +namespace std +{ + union abort; +} + +void abort(); + +using std::abort; diff --git a/gcc/testsuite/g++.dg/lookup/builtin4.C b/gcc/testsuite/g++.dg/lookup/builtin4.C new file mode 100644 index 00000000000..b1785dcc7fb --- /dev/null +++ b/gcc/testsuite/g++.dg/lookup/builtin4.C @@ -0,0 +1,15 @@ +// Copyright (C) 2007 Free Software Foundation +// Contributed by Ollie Wild +// Origin: Volker Reichelt +// { dg-do compile } + +// PR 31749: ICE with redeclaration of builtin + +namespace std +{ + union abort; +} + +union abort; + +using std::abort; // { dg-error "" } diff --git a/gcc/testsuite/g++.dg/lookup/using19.C b/gcc/testsuite/g++.dg/lookup/using19.C new file mode 100644 index 00000000000..973998bc021 --- /dev/null +++ b/gcc/testsuite/g++.dg/lookup/using19.C @@ -0,0 +1,21 @@ +// Copyright (C) 2007 Free Software Foundation +// Contributed by Ollie Wild +// { dg-do compile } + + +// C++ Standard, 7.3.3, clause 10: +// "Since a using-declaration is a declaration, the restrictions on +// declarations of the same name in the same declarative region (3.3) also +// apply to using-declarations." + +namespace M +{ + union A; + void B(); +} + +void A(); +union B; + +using M::A; +using M::B; -- 2.30.2