diff options
author | nathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4> | 2001-12-11 20:11:34 +0000 |
---|---|---|
committer | nathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4> | 2001-12-11 20:11:34 +0000 |
commit | 179d1a034e3bcead5a5a35e826fdbb83b4f47fa9 (patch) | |
tree | b72e75e6df8ea8e5735b8bb1b61a5f6d3a51eeea /gcc/cp | |
parent | a96b8d2649821430d45535fe1e71e46ee94fe393 (diff) | |
download | gcc-179d1a034e3bcead5a5a35e826fdbb83b4f47fa9.tar.gz |
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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@47891 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/cp/decl.c | 10 | ||||
-rw-r--r-- | gcc/cp/parse.y | 8 |
3 files changed, 24 insertions, 2 deletions
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 <nathan@codesourcery.com> + + 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 <nathan@codesourcery.com> 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; |