This is the mail archive of the gcc-patches@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]
Other format: [Raw text]

C++ PATCH: PR 27227


This patch fixes PR c++/27227, a rejects-valid regression involving
linkage specifications.  Two variables with C linkage are the same
variable, even if they appear in different namespaces.

I also noticed that we were silently ignoring the linkage
specification on:

  extern int i;
  extern "C" int i;

which is clearly wrong; either we should honor the specification or
issue an error.  It turns out that the standard is presently unclear
in this respect; it makes such sequences errors for functions, but is
silent with respect to variables.  DR 563 is about this issue, and it
seems clear to me that this should be an error, as it is for
functions.  So, that's what I implemented; that's clearly an
improvement over the current behavior of silently ignoring the
specification.

Tested on x86_64-unknown-linux-gnu, applied on the mainline.  I will
apply to 4.1 as soon as testing completes.

--
Mark Mitchell
CodeSourcery
mark@codesourcery.com
(650) 331-3385 x713

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-14  Mark Mitchell  <mark@codesourcery.com>

	PR c++/27227
	* g++.dg/lookup/linkage1.C: New test.
	* g++.dg/lookup/linkage2.C: Likewise.

Index: gcc/cp/decl.c
===================================================================
--- gcc/cp/decl.c	(revision 114635)
+++ gcc/cp/decl.c	(working copy)
@@ -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 oldd
 	  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: gcc/testsuite/g++.dg/lookup/linkage2.C
===================================================================
--- gcc/testsuite/g++.dg/lookup/linkage2.C	(revision 0)
+++ gcc/testsuite/g++.dg/lookup/linkage2.C	(revision 0)
@@ -0,0 +1,7 @@
+// PR c++/27227
+
+namespace x {
+  extern "C" const int y;
+}
+using x::y;
+extern "C" int const y=0;
Index: gcc/testsuite/g++.dg/lookup/linkage1.C
===================================================================
--- gcc/testsuite/g++.dg/lookup/linkage1.C	(revision 0)
+++ gcc/testsuite/g++.dg/lookup/linkage1.C	(revision 0)
@@ -0,0 +1,4 @@
+// DR 563
+
+extern int i; // { dg-error "linkage" }
+extern "C" int i; // { dg-error "linkage" }


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