re PR c++/13699 (Extern "C" routine in different namespaces accepted with different exception signature)

2008-07-16  Dodji Seketeli  <dseketel@redhat.com>

	PR c++/13699
	* gcc/cp/name-lookup.c (lookup_extern_c_fun_binding_in_all_ns):
	New function.
	(pushdecl_maybe_friend): Check if a redeclaration of extern C function
	complies with exception specification constraints.

From-SVN: r137904
This commit is contained in:
Dodji Seketeli 2008-07-16 23:44:02 +00:00 committed by Dodji Seketeli
parent 7386e3ee26
commit ecba6c56db
4 changed files with 100 additions and 0 deletions

View File

@ -1,3 +1,11 @@
2008-07-16 Dodji Seketeli <dseketel@redhat.com>
PR c++/13699
* gcc/cp/name-lookup.c (lookup_extern_c_fun_binding_in_all_ns):
New function.
(pushdecl_maybe_friend): Check if a redeclaration of extern C function
complies with exception specification constraints.
2008-07-14 Jason Merrill <jason@redhat.com>
* lex.c (init_reswords): Always set D_OBJC.

View File

@ -50,6 +50,7 @@ static bool qualified_lookup_using_namespace (tree, tree,
struct scope_binding *, int);
static tree lookup_type_current_level (tree);
static tree push_using_directive (tree);
static cxx_binding* lookup_extern_c_fun_binding_in_all_ns (tree);
/* The :: namespace. */
@ -763,6 +764,48 @@ pushdecl_maybe_friend (tree x, bool is_friend)
}
}
/* If x has C linkage-specification, (extern "C"),
lookup its binding, in case it's already bound to an object.
The lookup is done in all namespaces.
If we find an existing binding, make sure it has the same
exception specification as x, otherwise, bail in error [7.5, 7.6]. */
if ((TREE_CODE (x) == FUNCTION_DECL)
&& DECL_EXTERN_C_P (x)
/* We should ignore declarations happening in system headers. */
&& !DECL_IN_SYSTEM_HEADER (x))
{
cxx_binding *function_binding =
lookup_extern_c_fun_binding_in_all_ns (x);
if (function_binding
&& !DECL_IN_SYSTEM_HEADER (function_binding->value))
{
tree previous = function_binding->value;
/* In case either x or previous is declared to throw an exception,
make sure both exception speficications are equal. */
if (decls_match (x, previous))
{
tree x_exception_spec = NULL_TREE;
tree previous_exception_spec = NULL_TREE;
x_exception_spec =
TYPE_RAISES_EXCEPTIONS (TREE_TYPE (x));
previous_exception_spec =
TYPE_RAISES_EXCEPTIONS (TREE_TYPE (previous));
if (!comp_except_specs (previous_exception_spec,
x_exception_spec,
true))
{
pedwarn ("declaration of %q#D with C language linkage", x);
pedwarn ("conflicts with previous declaration %q+#D",
previous);
pedwarn ("due to different exception specifications");
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
}
}
}
}
if (TREE_CODE (x) == FUNCTION_DECL || DECL_FUNCTION_TEMPLATE_P (x))
check_default_args (x);
@ -1831,6 +1874,39 @@ binding_for_name (cxx_scope *scope, tree name)
return result;
}
/* Walk through the bindings associated to the name of FUNCTION,
and return the first binding that declares a function with a
"C" linkage specification, a.k.a 'extern "C"'.
This function looks for the binding, regardless of which scope it
has been defined in. It basically looks in all the known scopes.
Note that this function does not lookup for bindings of builtin functions
or for functions declared in system headers. */
static cxx_binding*
lookup_extern_c_fun_binding_in_all_ns (tree function)
{
tree name;
cxx_binding *iter;
gcc_assert (function && TREE_CODE (function) == FUNCTION_DECL);
name = DECL_NAME (function);
gcc_assert (name && TREE_CODE (name) == IDENTIFIER_NODE);
for (iter = IDENTIFIER_NAMESPACE_BINDINGS (name);
iter;
iter = iter->previous)
{
if (iter->value
&& TREE_CODE (iter->value) == FUNCTION_DECL
&& DECL_EXTERN_C_P (iter->value)
&& !DECL_ARTIFICIAL (iter->value))
{
return iter;
}
}
return NULL;
}
/* Insert another USING_DECL into the current binding level, returning
this declaration. If this is a redeclaration, do nothing, and
return NULL_TREE if this not in namespace scope (in namespace

View File

@ -1,3 +1,8 @@
2008-07-16 Dodji Seketeli <dseketel@redhat.com>
PR c++/13699
* g++.dg/lookup/extern-c-redecl.C: New test.
2008-07-15 Richard Guenther <rguenther@suse.de>
PR middle-end/36369

View File

@ -0,0 +1,11 @@
// Contributed by Dodji Seketeli <dseketel@redhat.com>
// Origin: PR c++/13699
// { dg-do compile }
namespace A {
extern "C" void foo_func () throw(); // { dg-error "conflicts" }
}
// next line should trigger an error because
// it conflicts with previous declaration of foo_func (), due to
// different exception specifications.
extern "C" void foo_func (); // { dg-error "C language|exception specifications" }