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:
parent
7386e3ee26
commit
ecba6c56db
4 changed files with 100 additions and 0 deletions
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
11
gcc/testsuite/g++.dg/lookup/extern-c-redecl.C
Normal file
11
gcc/testsuite/g++.dg/lookup/extern-c-redecl.C
Normal 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" }
|
Loading…
Add table
Reference in a new issue