Commit 44fd0e80 by Ollie Wild Committed by Ollie Wild

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
parent 9ab78e53
2007-08-17 Ollie Wild <aaw@google.com>
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 <pcarlini@suse.de> 2007-08-17 Paolo Carlini <pcarlini@suse.de>
PR c++/32112 PR c++/32112
......
...@@ -2099,6 +2099,20 @@ do_nonmember_using_decl (tree scope, tree name, tree oldval, tree oldtype, ...@@ -2099,6 +2099,20 @@ do_nonmember_using_decl (tree scope, tree name, tree oldval, tree oldtype,
return; 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 /* It is impossible to overload a built-in function; any explicit
declaration eliminates the built-in declaration. So, if OLDVAL declaration eliminates the built-in declaration. So, if OLDVAL
is a built-in, then we can just pretend it isn't there. */ 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, ...@@ -2108,87 +2122,91 @@ do_nonmember_using_decl (tree scope, tree name, tree oldval, tree oldtype,
&& !DECL_HIDDEN_FRIEND_P (oldval)) && !DECL_HIDDEN_FRIEND_P (oldval))
oldval = NULL_TREE; oldval = NULL_TREE;
/* Check for using functions. */ if (decls.value)
if (decls.value && is_overloaded_fn (decls.value))
{ {
tree tmp, tmp1; /* Check for using functions. */
if (is_overloaded_fn (decls.value))
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))
{ {
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 *newval = oldval;
scope has the same name and the same parameter types as a for (tmp = decls.value; tmp; tmp = OVL_NEXT (tmp))
function introduced by a using declaration the program is
ill-formed. */
for (tmp1 = oldval; tmp1; tmp1 = OVL_NEXT (tmp1))
{ {
tree old_fn = OVL_CURRENT (tmp1); tree new_fn = OVL_CURRENT (tmp);
if (new_fn == old_fn) /* [namespace.udecl]
/* The function already exists in the current namespace. */
break; If a function declaration in namespace scope or block
else if (OVL_USED (tmp1)) scope has the same name and the same parameter types as a
continue; /* this is a using decl */ function introduced by a using declaration the program is
else if (compparms (TYPE_ARG_TYPES (TREE_TYPE (new_fn)), ill-formed. */
TYPE_ARG_TYPES (TREE_TYPE (old_fn)))) for (tmp1 = oldval; tmp1; tmp1 = OVL_NEXT (tmp1))
{ {
gcc_assert (!DECL_ANTICIPATED (old_fn) tree old_fn = OVL_CURRENT (tmp1);
|| DECL_HIDDEN_FRIEND_P (old_fn));
/* There was already a non-using declaration in if (new_fn == old_fn)
this scope with the same parameter types. If both /* The function already exists in the current namespace. */
are the same extern "C" functions, that's ok. */
if (decls_match (new_fn, old_fn))
break; 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); gcc_assert (!DECL_ANTICIPATED (old_fn)
break; || 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 /* If we broke out of the loop, there's no reason to add
longer know the type of the set of functions. */ this function to the using declarations for this
if (*newval && TREE_CODE (*newval) == OVERLOAD) scope. */
TREE_TYPE (*newval) = unknown_type_node; if (tmp1)
/* Add this new function to the set. */ continue;
*newval = build_overload (OVL_CURRENT (tmp), *newval);
/* If there is only one function, then we use its type. (A /* If we are adding to an existing OVERLOAD, then we no
using-declaration naming a single function can be used in longer know the type of the set of functions. */
contexts where overload resolution cannot be if (*newval && TREE_CODE (*newval) == OVERLOAD)
performed.) */ TREE_TYPE (*newval) = unknown_type_node;
if (TREE_CODE (*newval) != OVERLOAD) /* Add this new function to the set. */
{ *newval = build_overload (OVL_CURRENT (tmp), *newval);
*newval = ovl_cons (*newval, NULL_TREE); /* If there is only one function, then we use its type. (A
TREE_TYPE (*newval) = TREE_TYPE (OVL_CURRENT (tmp)); 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 else
{ *newval = oldval;
*newval = decls.value;
if (oldval && !decls_match (*newval, oldval))
error ("%qD is already declared in this scope", name);
}
if (decls.type && TREE_CODE (decls.type) == TREE_LIST) 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, ...@@ -2198,13 +2216,16 @@ do_nonmember_using_decl (tree scope, tree name, tree oldval, tree oldtype,
else else
{ {
*newtype = decls.type; *newtype = decls.type;
if (oldtype && *newtype && !same_type_p (oldtype, *newtype)) if (oldtype && *newtype && !decls_match (oldtype, *newtype))
{ error ("%qD is already declared in this scope", name);
error ("using declaration %qD introduced ambiguous type %qT",
name, oldtype);
return;
}
} }
/* 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. */ /* Process a using-declaration at function scope. */
......
2007-08-17 Ollie Wild <aaw@google.com>
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 <pcarlini@suse.de> 2007-08-17 Paolo Carlini <pcarlini@suse.de>
PR c++/32190 PR c++/32190
// Copyright (C) 2007 Free Software Foundation
// Contributed by Ollie Wild <aaw@google.com>
// Origin: Volker Reichelt <reichelt@gcc.gnu.org>
// { dg-do compile }
// PR 31749: ICE with redeclaration of builtin
namespace std
{
union abort;
}
void abort();
using std::abort;
// Copyright (C) 2007 Free Software Foundation
// Contributed by Ollie Wild <aaw@google.com>
// Origin: Volker Reichelt <reichelt@gcc.gnu.org>
// { dg-do compile }
// PR 31749: ICE with redeclaration of builtin
namespace std
{
union abort;
}
union abort;
using std::abort; // { dg-error "" }
// Copyright (C) 2007 Free Software Foundation
// Contributed by Ollie Wild <aaw@google.com>
// { 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;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment