diff options
author | Mark Mitchell <mark@codesourcery.com> | 2006-06-14 17:44:36 +0000 |
---|---|---|
committer | Mark Mitchell <mmitchel@gcc.gnu.org> | 2006-06-14 17:44:36 +0000 |
commit | ace4831de98f6caf6450cf57528f5a15eec6c9e1 (patch) | |
tree | 222304b644d89c1c1cd28e8b5be65b80e93e6bf3 | |
parent | c3b11a40d026d3b25038f3300180e1b58a9b3b99 (diff) | |
download | gcc-ace4831de98f6caf6450cf57528f5a15eec6c9e1.zip gcc-ace4831de98f6caf6450cf57528f5a15eec6c9e1.tar.gz gcc-ace4831de98f6caf6450cf57528f5a15eec6c9e1.tar.bz2 |
re PR c++/27227 (rejects valid code with some extern "C")
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
-rw-r--r-- | gcc/cp/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/cp/decl.c | 46 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/lookup/linkage1.C | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/lookup/linkage2.C | 7 |
5 files changed, 65 insertions, 6 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 129f5df..b7eee4f 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -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 diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 206fced..2d92fe3 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -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", diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 8b79955..2760477 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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 index 0000000..6f6bdfd --- /dev/null +++ b/gcc/testsuite/g++.dg/lookup/linkage1.C @@ -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 index 0000000..994264d --- /dev/null +++ b/gcc/testsuite/g++.dg/lookup/linkage2.C @@ -0,0 +1,7 @@ +// PR c++/27227 + +namespace x { + extern "C" const int y; +} +using x::y; +extern "C" int const y=0; |