This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
extern "C" namespaces
- To: <gcc at gcc dot gnu dot org>
- Subject: extern "C" namespaces
- From: Richard Smith <richard at sphinx dot mythic-beasts dot com>
- Date: Mon, 3 Sep 2001 13:42:17 +0100 (BST)
Dear all,
I've been trying to track down the bug in gcc-3.0.1 that causes the
following program to compile without warning, but fail to assemble:
extern "C"
{
# include <cstdio> // illegal to include this here.
}
int main()
{
int x = std::abs(42);
}
[richard@verdi richard]$ g++-3 abs-test.cc
/tmp/ccUZ98Nv.s: Assembler messages:
/tmp/ccUZ98Nv.s:54: Fatal error: Symbol abs already defined.
... which is caused by the two abs functions (on long and int
respectively) being given the same symbol: "abs". No error is
produced because one overload is in the global namespace and is
imported into std:: with a using declaration and the other is
defined there. This particular case can be easily solved by moving
the test for conflictingly named extern "C" functions in
duplicate_decls() in cp/decl.c. [patch 1, below]
However, this patch does not solve the real problem: the following
test program will produce an error with this patch, but as soon as
the using fish::soup line is removed the, duplicate_decls() is not
called, and no compliation error is given.
extern "C"
{
namespace fish
{
void soup(float) {}
}
using fish::soup;
void soup(int) {}
}
In my opinion, it would be worth going one step further and give a
compiler error (or at the very least, a warning) if a namespace is
nested in an extern "C" block. [patch 2, below] Even this doesn't
completely solve the problem, because the following code would
still compile without warning but give an asembler error:
namespace fish
{
extern "C" void soup(float) {}
}
extern "C" void soup(int) {}
It would be nice to be able to get an error in this case too, but I
can't see a simple way of doing this. Any comments/suggestions would
be greatly appreciated.
--
Richard Smith
// patch 1 (against 3.0.1)
diff -urpX diff_ignore gcc-3.0.1-src/gcc/cp/decl.c
gcc-3.0.1.mf-src/gcc/cp/decl.c
--- gcc-3.0.1-src/gcc/cp/decl.c Tue Aug 28 11:03:28 2001
+++ gcc-3.0.1.mf-src/gcc/cp/decl.c Fri Aug 31 18:22:19 2001
@@ -3258,6 +3258,14 @@ duplicate_decls (newdecl, olddecl)
}
else if (!types_match)
{
+ if (TREE_CODE (newdecl) == FUNCTION_DECL
+ && DECL_EXTERN_C_P (newdecl) && DECL_EXTERN_C_P (olddecl))
+ {
+ cp_error ("declaration of C function `%#D' conflicts with",
+ newdecl);
+ cp_error_at ("previous declaration `%#D' here", olddecl);
+ }
+
if (CP_DECL_CONTEXT (newdecl) != CP_DECL_CONTEXT (olddecl))
/* These are certainly not duplicate declarations; they're
from different scopes. */
@@ -3289,14 +3297,8 @@ duplicate_decls (newdecl, olddecl)
}
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
- if (DECL_EXTERN_C_P (newdecl) && DECL_EXTERN_C_P (olddecl))
- {
- cp_error ("declaration of C function `%#D' conflicts with",
- newdecl);
- cp_error_at ("previous declaration `%#D' here", olddecl);
- }
- else if (compparms (TYPE_ARG_TYPES (TREE_TYPE (newdecl)),
- TYPE_ARG_TYPES (TREE_TYPE (olddecl))))
+ if (compparms (TYPE_ARG_TYPES (TREE_TYPE (newdecl)),
+ TYPE_ARG_TYPES (TREE_TYPE (olddecl))))
{
cp_error ("new declaration `%#D'", newdecl);
cp_error_at ("ambiguates old declaration `%#D'", olddecl);
// patch 2 (against 3.0.1)
diff -urpX diff_ignore gcc-3.0.1-src/gcc/cp/decl.c
gcc-3.0.1.mf-src/gcc/cp/decl.c
--- gcc-3.0.1-src/gcc/cp/decl.c Tue Aug 28 11:03:28 2001
+++ gcc-3.0.1.mf-src/gcc/cp/decl.c Mon Sep 3 13:32:42 2001
@@ -2334,6 +2334,9 @@ push_namespace (name)
}
}
+ if (current_lang_name == lang_name_c)
+ cp_error ("namespace with C linkage");
+
if (need_new)
{
/* Make a new namespace, binding the name to it. */
@@ -6420,7 +6423,11 @@ init_decl_processing ()
/* Create the `std' namespace. */
if (flag_honor_std)
{
+ /* Become extern "C++" for the push_namespace to avoid
+ getting a "namespace with C linkage error" */
+ current_lang_name = lang_name_cplusplus;
push_namespace (std_identifier);
+ current_lang_name = lang_name_c;
std_node = current_namespace;
pop_namespace ();
fake_std_node = error_mark_node;
@@ -6539,7 +6546,11 @@ init_decl_processing ()
layout_type (vtbl_ptr_type_node);
record_builtin_type (RID_MAX, NULL_PTR, vtbl_ptr_type_node);
+ /* Become extern "C++" for the push_namespace to avoid
+ getting a "namespace with C linkage error" */
+ current_lang_name = lang_name_cplusplus;
push_namespace (get_identifier ("__cxxabiv1"));
+ current_lang_name = lang_name_c;
abi_node = current_namespace;
pop_namespace ();