This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

extern "C" namespaces


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 ();




Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]