re PR c++/27227 (rejects valid code with some extern "C")
authorMark Mitchell <mark@codesourcery.com>
Wed, 14 Jun 2006 17:44:36 +0000 (17:44 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Wed, 14 Jun 2006 17:44:36 +0000 (17:44 +0000)
PR c++/27227
* decl.c (decls_match): Allow an extern "C" variable declarations
from different namespaces to match.
(duplicate_decls): Disallow redeclaring a variable with a
different linkage specification.
PR c++/27227
* g++.dg/lookup/linkage1.C: New test.
* g++.dg/lookup/linkage2.C: Likewise.

From-SVN: r114647

gcc/cp/ChangeLog
gcc/cp/decl.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/lookup/linkage1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/lookup/linkage2.C [new file with mode: 0644]

index 129f5df0deb08824e32b18904bc2dfe27ed933c0..b7eee4f78b9485dc690780409782777437dc0ef7 100644 (file)
@@ -1,3 +1,11 @@
+2006-06-13  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/27227
+       * decl.c (decls_match): Allow an extern "C" variable declarations
+       from different namespaces to match.
+       (duplicate_decls): Disallow redeclaring a variable with a
+       different linkage specification.
+
 2006-06-13  Jakub Jelinek  <jakub@redhat.com>
 
        PR middle-end/27793
index 206fced6b3947820d8f38e3017d6fde939423aa3..2d92fe382d5af07a5f903150f241c9b143f0f6fd 100644 (file)
@@ -999,7 +999,13 @@ decls_match (tree newdecl, tree olddecl)
       /* Need to check scope for variable declaration (VAR_DECL).
         For typedef (TYPE_DECL), scope is ignored.  */
       if (TREE_CODE (newdecl) == VAR_DECL
-         && CP_DECL_CONTEXT (newdecl) != CP_DECL_CONTEXT (olddecl))
+         && CP_DECL_CONTEXT (newdecl) != CP_DECL_CONTEXT (olddecl)
+         /* [dcl.link]
+            Two declarations for an object with C language linkage
+            with the same name (ignoring the namespace that qualify
+            it) that appear in different namespace scopes refer to
+            the same object.  */
+         && !(DECL_EXTERN_C_P (olddecl) && DECL_EXTERN_C_P (newdecl)))
        return 0;
 
       if (TREE_TYPE (newdecl) == error_mark_node)
@@ -1453,14 +1459,42 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
          warning (0, "prototype for %q+#D", newdecl);
          warning (0, "%Jfollows non-prototype definition here", olddecl);
        }
-      else if (TREE_CODE (olddecl) == FUNCTION_DECL
+      else if ((TREE_CODE (olddecl) == FUNCTION_DECL
+               || TREE_CODE (olddecl) == VAR_DECL)
               && DECL_LANGUAGE (newdecl) != DECL_LANGUAGE (olddecl))
        {
-         /* extern "C" int foo ();
-            int foo () { bar (); }
-            is OK.  */
+         /* [dcl.link]
+            If two declarations of the same function or object
+            specify different linkage-specifications ..., the program
+            is ill-formed.... Except for functions with C++ linkage,
+            a function declaration without a linkage specification
+            shall not precede the first linkage specification for
+            that function.  A function can be declared without a
+            linkage specification after an explicit linkage
+            specification has been seen; the linkage explicitly
+            specified in the earlier declaration is not affected by
+            such a function declaration.
+
+            DR 563 raises the question why the restrictions on
+            functions should not also apply to objects.  Older
+            versions of G++ silently ignore the linkage-specification
+            for this example:
+
+              namespace N { 
+                 extern int i;
+                extern "C" int i;
+               }
+
+             which is clearly wrong.  Therefore, we now treat objects
+            like functions.  */
          if (current_lang_depth () == 0)
-           SET_DECL_LANGUAGE (newdecl, DECL_LANGUAGE (olddecl));
+           {
+             /* There is no explicit linkage-specification, so we use
+                the linkage from the previous declaration.  */
+             if (!DECL_LANG_SPECIFIC (newdecl))
+               retrofit_lang_decl (newdecl);
+             SET_DECL_LANGUAGE (newdecl, DECL_LANGUAGE (olddecl));
+           }
          else
            {
              error ("previous declaration of %q+#D with %qL linkage",
index 8b799550604812019341742499e1124ad96591ff..2760477d778556d257b2c3cc2c83763078c401ac 100644 (file)
@@ -1,3 +1,9 @@
+2006-06-14  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/27227
+       * g++.dg/lookup/linkage1.C: New test.
+       * g++.dg/lookup/linkage2.C: Likewise.
+
 2006-06-14  Andreas Krebbel  <krebbel1@de.ibm.com>
 
        PR middle-end/27959
diff --git a/gcc/testsuite/g++.dg/lookup/linkage1.C b/gcc/testsuite/g++.dg/lookup/linkage1.C
new file mode 100644 (file)
index 0000000..6f6bdfd
--- /dev/null
@@ -0,0 +1,4 @@
+// DR 563
+
+extern int i; // { dg-error "linkage" }
+extern "C" int i; // { dg-error "linkage" }
diff --git a/gcc/testsuite/g++.dg/lookup/linkage2.C b/gcc/testsuite/g++.dg/lookup/linkage2.C
new file mode 100644 (file)
index 0000000..994264d
--- /dev/null
@@ -0,0 +1,7 @@
+// PR c++/27227
+
+namespace x {
+  extern "C" const int y;
+}
+using x::y;
+extern "C" int const y=0;