+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>
PR debug/49815
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;
otherwise the name is found in ridpointers from RID_INDEX. */
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
* 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
extern bool in_late_binary_op;
extern const char *c_addr_space_name (addr_space_t as);
extern tree identifier_global_value (tree);
+extern tree c_linkage_bindings (tree);
extern void record_builtin_type (enum rid, const char *, tree);
extern tree build_void_list_node (void);
extern void start_fname_decls (void);
static void
handle_pragma_redefine_extname (cpp_reader * ARG_UNUSED (dummy))
{
- tree oldname, newname, decl, x;
+ tree oldname, newname, decls, x;
enum cpp_ttype t;
+ bool found;
if (pragma_lex (&oldname) != CPP_NAME)
GCC_BAD ("malformed #pragma redefine_extname, ignored");
if (t != CPP_EOF)
warning (OPT_Wpragmas, "junk at end of %<#pragma redefine_extname%>");
- decl = identifier_global_value (oldname);
- if (decl
- && (TREE_PUBLIC (decl) || DECL_EXTERNAL (decl))
- && (TREE_CODE (decl) == FUNCTION_DECL
- || TREE_CODE (decl) == VAR_DECL)
- && has_c_linkage (decl))
+ found = false;
+ for (decls = c_linkage_bindings (oldname);
+ decls; )
{
- if (DECL_ASSEMBLER_NAME_SET_P (decl))
+ tree decl;
+ if (TREE_CODE (decls) == TREE_LIST)
{
- const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
- name = targetm.strip_name_encoding (name);
-
- if (strcmp (name, IDENTIFIER_POINTER (newname)))
- warning (OPT_Wpragmas, "#pragma redefine_extname ignored due to "
- "conflict with previous rename");
+ decl = TREE_VALUE (decls);
+ decls = TREE_CHAIN (decls);
}
else
- change_decl_assembler_name (decl, newname);
+ {
+ decl = decls;
+ decls = NULL_TREE;
+ }
+
+ if ((TREE_PUBLIC (decl) || DECL_EXTERNAL (decl))
+ && (TREE_CODE (decl) == FUNCTION_DECL
+ || TREE_CODE (decl) == VAR_DECL))
+ {
+ found = true;
+ if (DECL_ASSEMBLER_NAME_SET_P (decl))
+ {
+ const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+ name = targetm.strip_name_encoding (name);
+
+ if (strcmp (name, IDENTIFIER_POINTER (newname)))
+ warning (OPT_Wpragmas, "#pragma redefine_extname ignored due to "
+ "conflict with previous rename");
+ }
+ else
+ change_decl_assembler_name (decl, newname);
+ }
}
- else
+
+ if (!found)
/* 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
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>
* parser.c (cp_parser_initializer_list): Handle C99 .id= and [N]=
cleanup = NULL_TREE;
/* 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);
if (asmspec_tree && asmspec_tree != error_mark_node)
asmspec = TREE_STRING_POINTER (asmspec_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);
+static tree lookup_extern_c_fun_in_all_ns (tree);
/* The :: namespace. */
&& !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);
+ tree previous = lookup_extern_c_fun_in_all_ns (x);
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))
"due to different exception specifications");
return error_mark_node;
}
+ if (DECL_ASSEMBLER_NAME_SET_P (previous))
+ SET_DECL_ASSEMBLER_NAME (x,
+ DECL_ASSEMBLER_NAME (previous));
}
else
{
}
/* 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"'.
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)
+static tree
+lookup_extern_c_fun_in_all_ns (tree function)
{
tree name;
cxx_binding *iter;
iter;
iter = iter->previous)
{
- if (iter->value
- && TREE_CODE (iter->value) == FUNCTION_DECL
- && DECL_EXTERN_C_P (iter->value)
- && !DECL_ARTIFICIAL (iter->value))
+ tree ovl;
+ for (ovl = iter->value; ovl; ovl = OVL_NEXT (ovl))
{
- return iter;
+ tree decl = OVL_CURRENT (ovl);
+ if (decl
+ && TREE_CODE (decl) == FUNCTION_DECL
+ && DECL_EXTERN_C_P (decl)
+ && !DECL_ARTIFICIAL (decl))
+ {
+ return decl;
+ }
}
}
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
this declaration. If this is a redeclaration, do nothing, and
return NULL_TREE if this not in namespace scope (in namespace
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
* g++.dg/opt/builtins2.C: New.
/* { dg-final { scan-assembler-not "foo" } } */
/* { dg-final { scan-assembler "_Z3bazv" } } */
/* { 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
#error
#pragma redefine_extname baz baq
extern int baz(void);
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;