Commit 7cd6ea64 by Nathan Sidwell Committed by Nathan Sidwell

[C++ PATCH] hash-table for extern-c fns.

https://gcc.gnu.org/ml/gcc-patches/2017-10/msg00614.html
	* name-lookup.c (extern_c_fns): Rename to ...
	(extern_c_decls): ... here.
	(check_extern_c_conflict, extern_c_linkage_bindings): Update.
	(do_pushdecl): Check extern-c fns and vars.

	* g++.dg/lookup/extern-c-redecl6.C: New.
	* g++.dg/lookup/extern-c-hidden.C: Adjust diagnostics.
	* g++.dg/lookup/extern-c-redecl.C: Likewise.
	* g++.old-deja/g++.other/using9.C: Likewise.

From-SVN: r253622
parent 507ea98d
2017-10-10 Nathan Sidwell <nathan@acm.org> 2017-10-10 Nathan Sidwell <nathan@acm.org>
* name-lookup.c (extern_c_fns): Rename to ...
(extern_c_decls): ... here.
(check_extern_c_conflict, extern_c_linkage_bindings): Update.
(do_pushdecl): Check extern-c fns and vars.
* cp-tree.h (default_hash_traits <lang_identifier *>): Delete * cp-tree.h (default_hash_traits <lang_identifier *>): Delete
specialization. specialization.
......
...@@ -2511,13 +2511,13 @@ update_binding (cp_binding_level *level, cxx_binding *binding, tree *slot, ...@@ -2511,13 +2511,13 @@ update_binding (cp_binding_level *level, cxx_binding *binding, tree *slot,
return decl; return decl;
} }
/* Table of identifiers to extern C functions (or LISTS thereof). */ /* Table of identifiers to extern C declarations (or LISTS thereof). */
static GTY(()) hash_table<named_decl_hash> *extern_c_fns; static GTY(()) hash_table<named_decl_hash> *extern_c_decls;
/* DECL has C linkage. If we have an existing instance, make sure it /* DECL has C linkage. If we have an existing instance, make sure the
has the same exception specification [7.5, 7.6]. If there's no new one is compatible. Make sure it has the same exception
instance, add DECL to the map. */ specification [7.5, 7.6]. Add DECL to the map. */
static void static void
check_extern_c_conflict (tree decl) check_extern_c_conflict (tree decl)
...@@ -2526,10 +2526,10 @@ check_extern_c_conflict (tree decl) ...@@ -2526,10 +2526,10 @@ check_extern_c_conflict (tree decl)
if (DECL_ARTIFICIAL (decl) || DECL_IN_SYSTEM_HEADER (decl)) if (DECL_ARTIFICIAL (decl) || DECL_IN_SYSTEM_HEADER (decl))
return; return;
if (!extern_c_fns) if (!extern_c_decls)
extern_c_fns = hash_table<named_decl_hash>::create_ggc (127); extern_c_decls = hash_table<named_decl_hash>::create_ggc (127);
tree *slot = extern_c_fns tree *slot = extern_c_decls
->find_slot_with_hash (DECL_NAME (decl), ->find_slot_with_hash (DECL_NAME (decl),
IDENTIFIER_HASH_VALUE (DECL_NAME (decl)), INSERT); IDENTIFIER_HASH_VALUE (DECL_NAME (decl)), INSERT);
if (tree old = *slot) if (tree old = *slot)
...@@ -2543,9 +2543,10 @@ check_extern_c_conflict (tree decl) ...@@ -2543,9 +2543,10 @@ check_extern_c_conflict (tree decl)
about a (possible) mismatch, when inserting the decl. */ about a (possible) mismatch, when inserting the decl. */
else if (!decls_match (decl, old)) else if (!decls_match (decl, old))
mismatch = 1; mismatch = 1;
else if (!comp_except_specs (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (old)), else if (TREE_CODE (decl) == FUNCTION_DECL
TYPE_RAISES_EXCEPTIONS (TREE_TYPE (decl)), && !comp_except_specs (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (old)),
ce_normal)) TYPE_RAISES_EXCEPTIONS (TREE_TYPE (decl)),
ce_normal))
mismatch = -1; mismatch = -1;
else if (DECL_ASSEMBLER_NAME_SET_P (old)) else if (DECL_ASSEMBLER_NAME_SET_P (old))
SET_DECL_ASSEMBLER_NAME (decl, DECL_ASSEMBLER_NAME (old)); SET_DECL_ASSEMBLER_NAME (decl, DECL_ASSEMBLER_NAME (old));
...@@ -2553,12 +2554,12 @@ check_extern_c_conflict (tree decl) ...@@ -2553,12 +2554,12 @@ check_extern_c_conflict (tree decl)
if (mismatch) if (mismatch)
{ {
pedwarn (input_location, 0, pedwarn (input_location, 0,
"declaration of %q#D with C language linkage", decl); "conflicting C language linkage declaration %q#D", decl);
pedwarn (DECL_SOURCE_LOCATION (old), 0, inform (DECL_SOURCE_LOCATION (old),
"conflicts with previous declaration %q#D", old); "previous declaration %q#D", old);
if (mismatch < 0) if (mismatch < 0)
pedwarn (input_location, 0, inform (input_location,
"due to different exception specifications"); "due to different exception specifications");
} }
else else
{ {
...@@ -2587,8 +2588,8 @@ check_extern_c_conflict (tree decl) ...@@ -2587,8 +2588,8 @@ check_extern_c_conflict (tree decl)
tree tree
c_linkage_bindings (tree name) c_linkage_bindings (tree name)
{ {
if (extern_c_fns) if (extern_c_decls)
if (tree *slot = extern_c_fns if (tree *slot = extern_c_decls
->find_slot_with_hash (name, IDENTIFIER_HASH_VALUE (name), NO_INSERT)) ->find_slot_with_hash (name, IDENTIFIER_HASH_VALUE (name), NO_INSERT))
{ {
tree result = *slot; tree result = *slot;
...@@ -3030,9 +3031,8 @@ do_pushdecl (tree decl, bool is_friend) ...@@ -3030,9 +3031,8 @@ do_pushdecl (tree decl, bool is_friend)
else else
*slot = head; *slot = head;
} }
if (TREE_CODE (match) == FUNCTION_DECL if (DECL_EXTERN_C_P (match))
&& DECL_EXTERN_C_P (match)) /* We need to check and register the decl now. */
/* We need to check and register the fn now. */
check_extern_c_conflict (match); check_extern_c_conflict (match);
} }
return match; return match;
...@@ -3113,7 +3113,9 @@ do_pushdecl (tree decl, bool is_friend) ...@@ -3113,7 +3113,9 @@ do_pushdecl (tree decl, bool is_friend)
} }
else if (VAR_P (decl)) else if (VAR_P (decl))
maybe_register_incomplete_var (decl); maybe_register_incomplete_var (decl);
else if (TREE_CODE (decl) == FUNCTION_DECL && DECL_EXTERN_C_P (decl))
if ((VAR_P (decl) || TREE_CODE (decl) == FUNCTION_DECL)
&& DECL_EXTERN_C_P (decl))
check_extern_c_conflict (decl); check_extern_c_conflict (decl);
} }
else else
......
2017-10-10 Nathan Sidwell <nathan@acm.org>
* g++.dg/lookup/extern-c-redecl6.C: New.
* g++.dg/lookup/extern-c-hidden.C: Adjust diagnostics.
* g++.dg/lookup/extern-c-redecl.C: Likewise.
* g++.old-deja/g++.other/using9.C: Likewise.
2017-10-10 Paolo Carlini <paolo.carlini@oracle.com> 2017-10-10 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/78006 PR c++/78006
......
// Make sure unhidding an extern-c still checks it is compatible // Make sure unhidding an extern-c still checks it is compatible
extern "C" float fabsf (float); // { dg-error "conflicts with previous declaration" } extern "C" float fabsf (float); // { dg-message "previous declaration" }
namespace Bob namespace Bob
{ {
extern "C" float fabsf (float, float); // { dg-error "C language" } extern "C" float fabsf (float, float); // { dg-error "C language" }
extern "C" double fabs (double, double); // { dg-error "conflicts with previous declaration" } extern "C" double fabs (double, double); // { dg-message "previous declaration" }
} }
extern "C" double fabs (double); // { dg-error "C language" } extern "C" double fabs (double); // { dg-error "C language" }
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
// { dg-do compile } // { dg-do compile }
namespace A { namespace A {
extern "C" void foo_func () throw(); // { dg-error "conflicts" } extern "C" void foo_func () throw(); // { dg-message "previous" }
} }
// next line should trigger an error because // next line should trigger an error because
// it conflicts with previous declaration of foo_func (), due to // it conflicts with previous declaration of foo_func (), due to
......
extern "C" {
int i; // { dg-message "previous" }
float f; // { dg-message "previous" }
void fn (); // { dg-message "previous" }
int ai1[1]; // { dg-message "previous" }
extern int ai[];
namespace OK
{
int i;
float f;
void fn ();
extern int ai1[];
int ai[2];
}
namespace BAD
{
long i; // { dg-error "C language linkage" }
double f; // { dg-error "C language linkage" }
int fn (); // { dg-error "C language linkage" }
int ai1[2]; // { dg-error "C language linkage" }
}
}
...@@ -13,7 +13,7 @@ struct x {}; ...@@ -13,7 +13,7 @@ struct x {};
using ::x; using ::x;
using ::a; using ::a;
extern "C" void foo (); // { dg-error "previous declaration" } extern "C" void foo (); // { dg-message "previous declaration" }
namespace { namespace {
extern "C" int foo (); // { dg-error "C.*linkage" } extern "C" int foo (); // { dg-error "C.*linkage" }
......
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