Commit 3a636414 by Jason Merrill Committed by Jason Merrill

re PR c++/30112 (pragma redefine_extname fails when namespaces are involved)

	PR c++/30112
gcc/c-family/
	* c-common.h: Declare c_linkage_bindings.
	* c-pragma.c (handle_pragma_redefine_extname): Use it.
gcc/
	* c-decl.c (c_linkage_bindings): Define.
gcc/cp/
	* decl.c (cp_finish_decl): Apply pragma redefine_extname in
	other namespaces as well.
	* name-lookup.c (c_linkage_bindings): Define.
	(lookup_extern_c_fun_in_all_ns): Rename from
	lookup_extern_c_fun_binding_in_all_ns.  Return tree.
	(pushdecl_maybe_friend_1): Adjust.  Copy DECL_ASSEMBLER_NAME.

Co-Authored-By: Mark Glisse <marc.glisse@normalesup.org>

From-SVN: r176650
parent 8b9b2275
2011-07-22 Jason Merrill <jason@redhat.com>
PR c++/30112
* c-decl.c (c_linkage_bindings): Define.
2011-07-22 Eric Botcazou <ebotcazou@adacore.com> 2011-07-22 Eric Botcazou <ebotcazou@adacore.com>
PR debug/49815 PR debug/49815
......
...@@ -8501,6 +8501,14 @@ identifier_global_value (tree t) ...@@ -8501,6 +8501,14 @@ identifier_global_value (tree t)
return 0; return 0;
} }
/* In C, the only C-linkage public declaration is at file scope. */
tree
c_linkage_bindings (tree name)
{
return identifier_global_value (name);
}
/* Record a builtin type for C. If NAME is non-NULL, it is the name used; /* Record a builtin type for C. If NAME is non-NULL, it is the name used;
otherwise the name is found in ridpointers from RID_INDEX. */ otherwise the name is found in ridpointers from RID_INDEX. */
......
2011-07-22 Jason Merrill <jason@redhat.com> 2011-07-22 Jason Merrill <jason@redhat.com>
PR c++/30112
* c-common.h: Declare c_linkage_bindings.
* c-pragma.c (handle_pragma_redefine_extname): Use it.
PR c++/49813 PR c++/49813
* c-opts.c (set_std_cxx0x): Set flag_isoc94 and flag_isoc99. * c-opts.c (set_std_cxx0x): Set flag_isoc94 and flag_isoc99.
* c-pretty-print.c (pp_c_cv_qualifiers): Check c_dialect_cxx as well * c-pretty-print.c (pp_c_cv_qualifiers): Check c_dialect_cxx as well
......
...@@ -710,6 +710,7 @@ extern void c_register_addr_space (const char *str, addr_space_t as); ...@@ -710,6 +710,7 @@ extern void c_register_addr_space (const char *str, addr_space_t as);
extern bool in_late_binary_op; extern bool in_late_binary_op;
extern const char *c_addr_space_name (addr_space_t as); extern const char *c_addr_space_name (addr_space_t as);
extern tree identifier_global_value (tree); extern tree identifier_global_value (tree);
extern tree c_linkage_bindings (tree);
extern void record_builtin_type (enum rid, const char *, tree); extern void record_builtin_type (enum rid, const char *, tree);
extern tree build_void_list_node (void); extern tree build_void_list_node (void);
extern void start_fname_decls (void); extern void start_fname_decls (void);
......
...@@ -417,8 +417,9 @@ static void handle_pragma_redefine_extname (cpp_reader *); ...@@ -417,8 +417,9 @@ static void handle_pragma_redefine_extname (cpp_reader *);
static void static void
handle_pragma_redefine_extname (cpp_reader * ARG_UNUSED (dummy)) handle_pragma_redefine_extname (cpp_reader * ARG_UNUSED (dummy))
{ {
tree oldname, newname, decl, x; tree oldname, newname, decls, x;
enum cpp_ttype t; enum cpp_ttype t;
bool found;
if (pragma_lex (&oldname) != CPP_NAME) if (pragma_lex (&oldname) != CPP_NAME)
GCC_BAD ("malformed #pragma redefine_extname, ignored"); GCC_BAD ("malformed #pragma redefine_extname, ignored");
...@@ -428,13 +429,27 @@ handle_pragma_redefine_extname (cpp_reader * ARG_UNUSED (dummy)) ...@@ -428,13 +429,27 @@ handle_pragma_redefine_extname (cpp_reader * ARG_UNUSED (dummy))
if (t != CPP_EOF) if (t != CPP_EOF)
warning (OPT_Wpragmas, "junk at end of %<#pragma redefine_extname%>"); warning (OPT_Wpragmas, "junk at end of %<#pragma redefine_extname%>");
decl = identifier_global_value (oldname); found = false;
if (decl for (decls = c_linkage_bindings (oldname);
&& (TREE_PUBLIC (decl) || DECL_EXTERNAL (decl)) decls; )
{
tree decl;
if (TREE_CODE (decls) == TREE_LIST)
{
decl = TREE_VALUE (decls);
decls = TREE_CHAIN (decls);
}
else
{
decl = decls;
decls = NULL_TREE;
}
if ((TREE_PUBLIC (decl) || DECL_EXTERNAL (decl))
&& (TREE_CODE (decl) == FUNCTION_DECL && (TREE_CODE (decl) == FUNCTION_DECL
|| TREE_CODE (decl) == VAR_DECL) || TREE_CODE (decl) == VAR_DECL))
&& has_c_linkage (decl))
{ {
found = true;
if (DECL_ASSEMBLER_NAME_SET_P (decl)) if (DECL_ASSEMBLER_NAME_SET_P (decl))
{ {
const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
...@@ -447,7 +462,9 @@ handle_pragma_redefine_extname (cpp_reader * ARG_UNUSED (dummy)) ...@@ -447,7 +462,9 @@ handle_pragma_redefine_extname (cpp_reader * ARG_UNUSED (dummy))
else else
change_decl_assembler_name (decl, newname); change_decl_assembler_name (decl, newname);
} }
else }
if (!found)
/* We have to add this to the rename list even if there's already /* We have to add this to the rename list even if there's already
a global value that doesn't meet the above criteria, because in a global value that doesn't meet the above criteria, because in
C++ "struct foo {...};" puts "foo" in the current namespace but C++ "struct foo {...};" puts "foo" in the current namespace but
......
2011-07-22 Jason Merrill <jason@redhat.com>
Mark Glisse <marc.glisse@normalesup.org>
PR c++/30112
* decl.c (cp_finish_decl): Apply pragma redefine_extname in
other namespaces as well.
* name-lookup.c (c_linkage_bindings): Define.
(lookup_extern_c_fun_in_all_ns): Rename from
lookup_extern_c_fun_binding_in_all_ns. Return tree.
(pushdecl_maybe_friend_1): Adjust. Copy DECL_ASSEMBLER_NAME.
2011-07-20 Jason Merrill <jason@redhat.com> 2011-07-20 Jason Merrill <jason@redhat.com>
* parser.c (cp_parser_initializer_list): Handle C99 .id= and [N]= * parser.c (cp_parser_initializer_list): Handle C99 .id= and [N]=
......
...@@ -5919,7 +5919,7 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, ...@@ -5919,7 +5919,7 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
cleanup = NULL_TREE; cleanup = NULL_TREE;
/* If a name was specified, get the string. */ /* If a name was specified, get the string. */
if (global_scope_p (current_binding_level)) if (at_namespace_scope_p ())
asmspec_tree = maybe_apply_renaming_pragma (decl, asmspec_tree); asmspec_tree = maybe_apply_renaming_pragma (decl, asmspec_tree);
if (asmspec_tree && asmspec_tree != error_mark_node) if (asmspec_tree && asmspec_tree != error_mark_node)
asmspec = TREE_STRING_POINTER (asmspec_tree); asmspec = TREE_STRING_POINTER (asmspec_tree);
......
...@@ -52,7 +52,7 @@ static bool qualified_lookup_using_namespace (tree, tree, ...@@ -52,7 +52,7 @@ static bool qualified_lookup_using_namespace (tree, tree,
struct scope_binding *, int); struct scope_binding *, int);
static tree lookup_type_current_level (tree); static tree lookup_type_current_level (tree);
static tree push_using_directive (tree); static tree push_using_directive (tree);
static cxx_binding* lookup_extern_c_fun_binding_in_all_ns (tree); static tree lookup_extern_c_fun_in_all_ns (tree);
/* The :: namespace. */ /* The :: namespace. */
...@@ -768,18 +768,12 @@ pushdecl_maybe_friend_1 (tree x, bool is_friend) ...@@ -768,18 +768,12 @@ pushdecl_maybe_friend_1 (tree x, bool is_friend)
&& !DECL_ARTIFICIAL (x) && !DECL_ARTIFICIAL (x)
&& !DECL_IN_SYSTEM_HEADER (x)) && !DECL_IN_SYSTEM_HEADER (x))
{ {
cxx_binding *function_binding = tree previous = lookup_extern_c_fun_in_all_ns (x);
lookup_extern_c_fun_binding_in_all_ns (x);
tree previous = (function_binding
? function_binding->value
: NULL_TREE);
if (previous if (previous
&& !DECL_ARTIFICIAL (previous) && !DECL_ARTIFICIAL (previous)
&& !DECL_IN_SYSTEM_HEADER (previous) && !DECL_IN_SYSTEM_HEADER (previous)
&& DECL_CONTEXT (previous) != DECL_CONTEXT (x)) && DECL_CONTEXT (previous) != DECL_CONTEXT (x))
{ {
tree previous = function_binding->value;
/* In case either x or previous is declared to throw an exception, /* In case either x or previous is declared to throw an exception,
make sure both exception specifications are equal. */ make sure both exception specifications are equal. */
if (decls_match (x, previous)) if (decls_match (x, previous))
...@@ -805,6 +799,9 @@ pushdecl_maybe_friend_1 (tree x, bool is_friend) ...@@ -805,6 +799,9 @@ pushdecl_maybe_friend_1 (tree x, bool is_friend)
"due to different exception specifications"); "due to different exception specifications");
return error_mark_node; return error_mark_node;
} }
if (DECL_ASSEMBLER_NAME_SET_P (previous))
SET_DECL_ASSEMBLER_NAME (x,
DECL_ASSEMBLER_NAME (previous));
} }
else else
{ {
...@@ -1996,14 +1993,14 @@ binding_for_name (cp_binding_level *scope, tree name) ...@@ -1996,14 +1993,14 @@ binding_for_name (cp_binding_level *scope, tree name)
} }
/* Walk through the bindings associated to the name of FUNCTION, /* Walk through the bindings associated to the name of FUNCTION,
and return the first binding that declares a function with a and return the first declaration of a function with a
"C" linkage specification, a.k.a 'extern "C"'. "C" linkage specification, a.k.a 'extern "C"'.
This function looks for the binding, regardless of which scope it This function looks for the binding, regardless of which scope it
has been defined in. It basically looks in all the known scopes. has been defined in. It basically looks in all the known scopes.
Note that this function does not lookup for bindings of builtin functions Note that this function does not lookup for bindings of builtin functions
or for functions declared in system headers. */ or for functions declared in system headers. */
static cxx_binding* static tree
lookup_extern_c_fun_binding_in_all_ns (tree function) lookup_extern_c_fun_in_all_ns (tree function)
{ {
tree name; tree name;
cxx_binding *iter; cxx_binding *iter;
...@@ -2017,17 +2014,52 @@ lookup_extern_c_fun_binding_in_all_ns (tree function) ...@@ -2017,17 +2014,52 @@ lookup_extern_c_fun_binding_in_all_ns (tree function)
iter; iter;
iter = iter->previous) iter = iter->previous)
{ {
if (iter->value tree ovl;
&& TREE_CODE (iter->value) == FUNCTION_DECL for (ovl = iter->value; ovl; ovl = OVL_NEXT (ovl))
&& DECL_EXTERN_C_P (iter->value) {
&& !DECL_ARTIFICIAL (iter->value)) tree decl = OVL_CURRENT (ovl);
if (decl
&& TREE_CODE (decl) == FUNCTION_DECL
&& DECL_EXTERN_C_P (decl)
&& !DECL_ARTIFICIAL (decl))
{ {
return iter; return decl;
}
} }
} }
return NULL; return NULL;
} }
/* Returns a list of C-linkage decls with the name NAME. */
tree
c_linkage_bindings (tree name)
{
tree decls = NULL_TREE;
cxx_binding *iter;
for (iter = IDENTIFIER_NAMESPACE_BINDINGS (name);
iter;
iter = iter->previous)
{
tree ovl;
for (ovl = iter->value; ovl; ovl = OVL_NEXT (ovl))
{
tree decl = OVL_CURRENT (ovl);
if (decl
&& DECL_EXTERN_C_P (decl)
&& !DECL_ARTIFICIAL (decl))
{
if (decls == NULL_TREE)
decls = decl;
else
decls = tree_cons (NULL_TREE, decl, decls);
}
}
}
return decls;
}
/* Insert another USING_DECL into the current binding level, returning /* Insert another USING_DECL into the current binding level, returning
this declaration. If this is a redeclaration, do nothing, and this declaration. If this is a redeclaration, do nothing, and
return NULL_TREE if this not in namespace scope (in namespace return NULL_TREE if this not in namespace scope (in namespace
......
2011-07-22 Jason Merrill <jason@redhat.com> 2011-07-22 Jason Merrill <jason@redhat.com>
Mark Glisse <marc.glisse@normalesup.org>
PR c++/30112
* g++.dg/other/pragma-re-1.C: Add namespace cases.
PR c++/49813 PR c++/49813
* g++.dg/opt/builtins2.C: New. * g++.dg/opt/builtins2.C: New.
......
...@@ -2,6 +2,12 @@ ...@@ -2,6 +2,12 @@
/* { dg-final { scan-assembler-not "foo" } } */ /* { dg-final { scan-assembler-not "foo" } } */
/* { dg-final { scan-assembler "_Z3bazv" } } */ /* { dg-final { scan-assembler "_Z3bazv" } } */
/* { dg-final { scan-assembler-not "baq" } } */ /* { dg-final { scan-assembler-not "baq" } } */
/* { dg-final { scan-assembler "tut" } } */
/* { dg-final { scan-assembler-not "gee" } } */
/* { dg-final { scan-assembler "bang" } } */
/* { dg-final { scan-assembler-not "whiz" } } */
/* { dg-final { scan-assembler "eek" } } */
/* { dg-final { scan-assembler-not "boo" } } */
#ifndef __PRAGMA_REDEFINE_EXTNAME #ifndef __PRAGMA_REDEFINE_EXTNAME
#error #error
...@@ -17,3 +23,35 @@ int (*p)(void) = foo; ...@@ -17,3 +23,35 @@ int (*p)(void) = foo;
#pragma redefine_extname baz baq #pragma redefine_extname baz baq
extern int baz(void); extern int baz(void);
int (*q)(void) = baz; int (*q)(void) = baz;
// PR c++/30112
// These are expected to work.
#pragma redefine_extname gee tut
namespace somewhere {
extern "C" int gee(void);
int (*r)(void) = gee;
extern "C" int whiz(void);
int whiz(int);
}
#pragma redefine_extname whiz bang
int (*s)() = somewhere::whiz;
namespace elsewhere {
extern "C" int whiz(void);
}
int (*t)() = elsewhere::whiz;
namespace A
{
extern "C" int boo(void);
}
namespace B
{
extern "C" int boo(void);
}
#pragma redefine_extname boo eek
int (*u)() = A::boo;
int (*v)() = B::boo;
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