+ /* 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_ARTIFICIAL (x)
+ && !DECL_IN_SYSTEM_HEADER (x))
+ {
+ cxx_binding *function_binding =
+ lookup_extern_c_fun_binding_in_all_ns (x);
+ tree previous = (function_binding
+ ? function_binding->value
+ : NULL_TREE);
+ if (previous
+ && !DECL_ARTIFICIAL (previous)
+ && !DECL_IN_SYSTEM_HEADER (previous)
+ && DECL_CONTEXT (previous) != DECL_CONTEXT (x))
+ {
+ tree previous = function_binding->value;
+
+ /* In case either x or previous is declared to throw an exception,
+ make sure both exception specifications 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 (input_location, 0, "declaration of %q#D with C language linkage",
+ x);
+ pedwarn (input_location, 0, "conflicts with previous declaration %q+#D",
+ previous);
+ pedwarn (input_location, 0, "due to different exception specifications");
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
+ }
+ }
+ else
+ {
+ pedwarn (input_location, 0,
+ "declaration of %q#D with C language linkage", x);
+ pedwarn (input_location, 0,
+ "conflicts with previous declaration %q+#D",
+ previous);
+ }
+ }
+ }