From 270d8c65bd24496ae43ba4bc9b5050fa039ca2ce Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Tue, 11 Dec 2001 20:11:34 +0000 Subject: [PATCH] re PR c++/51 (g++ reports error for ISO C++ example) cp: PR g++/51 * parse.y (frob_specs): Indicate it is a language linkage which contained the extern. * decl.c (grokdeclarator): Allow extern language linkage with other specifiers. testsuite: * g++.dg/other/linkage1.C: New test. * g++.old-deja/g++.brendan/err-msg2.C: Alter to avoid two specifiers. From-SVN: r47891 --- gcc/cp/ChangeLog | 8 ++++++++ gcc/cp/decl.c | 10 +++++++++- gcc/cp/parse.y | 8 +++++++- gcc/testsuite/ChangeLog | 6 ++++++ gcc/testsuite/g++.dg/other/linkage1.C | 14 ++++++++++++++ gcc/testsuite/g++.old-deja/g++.brendan/err-msg2.C | 6 +++++- 6 files changed, 49 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/g++.dg/other/linkage1.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 880ef3fd021..71186885f32 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,11 @@ +2001-12-11 Nathan Sidwell + + PR g++/51 + * parse.y (frob_specs): Indicate it is a language linkage which + contained the extern. + * decl.c (grokdeclarator): Allow extern language linkage with + other specifiers. + 2001-12-10 Nathan Sidwell PR g++/72 diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 8bf940e4ffd..690e34c7a8d 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -9603,6 +9603,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) int explicit_int = 0; int explicit_char = 0; int defaulted_int = 0; + int extern_langp = 0; + tree typedef_decl = NULL_TREE; const char *name; tree typedef_type = NULL_TREE; @@ -10043,6 +10045,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) } else if (RIDBIT_SETP (i, specbits)) pedwarn ("duplicate `%s'", IDENTIFIER_POINTER (id)); + if (i == (int)RID_EXTERN + && TREE_PURPOSE (spec) == error_mark_node) + /* This extern was part of a language linkage. */ + extern_langp = 1; RIDBIT_SET (i, specbits); goto found; } @@ -10318,7 +10324,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) if (RIDBIT_ANY_SET (specbits)) { if (RIDBIT_SETP (RID_STATIC, specbits)) nclasses++; - if (RIDBIT_SETP (RID_EXTERN, specbits)) nclasses++; + if (RIDBIT_SETP (RID_EXTERN, specbits) && !extern_langp) nclasses++; if (decl_context == PARM && nclasses > 0) error ("storage class specifiers invalid in parameter declarations"); if (RIDBIT_SETP (RID_TYPEDEF, specbits)) @@ -10329,6 +10335,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) } if (RIDBIT_SETP (RID_AUTO, specbits)) nclasses++; if (RIDBIT_SETP (RID_REGISTER, specbits)) nclasses++; + if (!nclasses && !friendp && extern_langp) + nclasses++; } /* Give error if `virtual' is used outside of class declaration. */ diff --git a/gcc/cp/parse.y b/gcc/cp/parse.y index a27f288eedc..28a1456663f 100644 --- a/gcc/cp/parse.y +++ b/gcc/cp/parse.y @@ -119,7 +119,13 @@ frob_specs (specs_attrs, lookups) current_declspecs = build_tree_list (NULL_TREE, current_declspecs); if (have_extern_spec && !used_extern_spec) { - current_declspecs = tree_cons (NULL_TREE, + /* We have to indicate that there is an "extern", but that it + was part of a language specifier. For instance, + + extern "C" typedef int (*Ptr) (); + + is well formed. */ + current_declspecs = tree_cons (error_mark_node, get_identifier ("extern"), current_declspecs); used_extern_spec = 1; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 99d04fdf6b3..1ff35b297dd 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2001-12-11 Nathan Sidwell + + * g++.dg/other/linkage1.C: New test. + * g++.old-deja/g++.brendan/err-msg2.C: Alter to avoid two + specifiers. + 2001-12-11 Neil Booth * gcc.dg/concat.c: New test. diff --git a/gcc/testsuite/g++.dg/other/linkage1.C b/gcc/testsuite/g++.dg/other/linkage1.C new file mode 100644 index 00000000000..c2676bac1c2 --- /dev/null +++ b/gcc/testsuite/g++.dg/other/linkage1.C @@ -0,0 +1,14 @@ +// { dg-do compile } + +// Copyright (C) 2001 Free Software Foundation, Inc. +// Contributed by Nathan Sidwell 9 Dec 2001 + +// PR 51 +// This example snippet is from the ISO C++ standard, sect 7.5 para 4: + +extern "C" typedef void FUNC_c(); + +class C { + public: + static FUNC_c* q; +}; diff --git a/gcc/testsuite/g++.old-deja/g++.brendan/err-msg2.C b/gcc/testsuite/g++.old-deja/g++.brendan/err-msg2.C index 0bfb4c22414..a0cfd6a4b5d 100644 --- a/gcc/testsuite/g++.old-deja/g++.brendan/err-msg2.C +++ b/gcc/testsuite/g++.old-deja/g++.brendan/err-msg2.C @@ -1,4 +1,8 @@ // Build don't link: // GROUPS passed error-messages + typedef void (*pfv)(double, double); -extern "C" typedef void (*pfv)(double, double);// ERROR - multiple.* +extern "C" { + typedef void (*pfv)(double, double); // ERROR - conflicting linkage - XFAIL +} +