diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 37f32279a82..8d84a8bfe81 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,20 @@ +2001-04-19 Mark Mitchell + + * cp-tree.h (DECL_LANGUAGE): Don't assume DECL_LANG_SPECIFIC is + set. + (SET_DECL_LANGUAGE): New macro. + * decl.c (duplicate_decls): Use SET_DECL_LANGUAGE. + (pushdecl): Likewise. + (build_library_fn_1): Likewise. + (build_cp_library_fn): Likewise. + (grokfndecl): Likewise. + (grokvardecl): Mark `extern "C"' variables as having C linkage. + * decl2.c (grokclassfn): Use SET_DECL_LANGUAGE. + * lex.c (retrofit_lang_decl): Likewise. + * mangle.c (mangle_decl_string): Don't mangle the names of + variables declared with C language linkage. + * semantics.c (finish_member_declaration): Use SET_DECL_LANGUAGE. + 2001-04-18 John David Anglin * semantics.c (simplify_aggr_init_exprs_r): Don't restore diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index a30623a7bd7..b1359a102cb 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -1919,9 +1919,24 @@ struct lang_decl #define DECL_IN_MEMORY_P(NODE) \ (DECL_RTL_SET_P (NODE) && GET_CODE (DECL_RTL (NODE)) == MEM) -/* For FUNCTION_DECLs: return the language in which this decl - was declared. */ -#define DECL_LANGUAGE(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.language) +/* For a FUNCTION_DECL or a VAR_DECL, the language linkage for the + declaration. Some entities (like a member function in a local + class, or a local variable) do not have linkage at all, and this + macro should not be used in those cases. + + Implementation note: A FUNCTION_DECL without DECL_LANG_SPECIFIC was + created by language-independent code, and has C linkage. Most + VAR_DECLs have C++ linkage, and do not have DECL_LANG_SPECIFIC, but + we do create DECL_LANG_SPECIFIC for variables with non-C++ linkage. */ +#define DECL_LANGUAGE(NODE) \ + (DECL_LANG_SPECIFIC (NODE) \ + ? DECL_LANG_SPECIFIC(NODE)->decl_flags.language \ + : (TREE_CODE (NODE) == FUNCTION_DECL \ + ? lang_c : lang_cplusplus)) + +/* Set the language linkage for NODE to LANGUAGE. */ +#define SET_DECL_LANGUAGE(NODE, LANGUAGE) \ + (DECL_LANG_SPECIFIC (NODE)->decl_flags.language = LANGUAGE) /* For FUNCTION_DECLs: nonzero means that this function is a constructor. */ #define DECL_CONSTRUCTOR_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.constructor_attr) diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index fb6b8a3c27b..b72cf4fa4b6 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -3203,7 +3203,7 @@ duplicate_decls (newdecl, olddecl) /* Make the old declaration consistent with the new one so that all remnants of the builtin-ness of this function will be banished. */ - DECL_LANGUAGE (olddecl) = DECL_LANGUAGE (newdecl); + SET_DECL_LANGUAGE (olddecl, DECL_LANGUAGE (newdecl)); SET_DECL_RTL (olddecl, DECL_RTL (newdecl)); COPY_DECL_ASSEMBLER_NAME (olddecl, newdecl); SET_IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (newdecl), @@ -3362,7 +3362,7 @@ duplicate_decls (newdecl, olddecl) int foo () { bar (); } is OK. */ if (current_lang_depth () == 0) - DECL_LANGUAGE (newdecl) = DECL_LANGUAGE (olddecl); + SET_DECL_LANGUAGE (newdecl, DECL_LANGUAGE (olddecl)); else { cp_error_at ("previous declaration of `%#D' with %L linkage", @@ -3676,7 +3676,7 @@ duplicate_decls (newdecl, olddecl) if (! types_match) { - DECL_LANGUAGE (olddecl) = DECL_LANGUAGE (newdecl); + SET_DECL_LANGUAGE (olddecl, DECL_LANGUAGE (newdecl)); COPY_DECL_ASSEMBLER_NAME (newdecl, olddecl); SET_DECL_RTL (olddecl, DECL_RTL (newdecl)); } @@ -3691,7 +3691,7 @@ duplicate_decls (newdecl, olddecl) if (new_defines_function) /* If defining a function declared with other language linkage, use the previously declared language linkage. */ - DECL_LANGUAGE (newdecl) = DECL_LANGUAGE (olddecl); + SET_DECL_LANGUAGE (newdecl, DECL_LANGUAGE (olddecl)); else if (types_match) { /* If redeclaring a builtin function, and not a definition, @@ -3980,7 +3980,7 @@ pushdecl (x) if (DECL_NON_THUNK_FUNCTION_P (x) && ! DECL_LANG_SPECIFIC (x)) { retrofit_lang_decl (x); - DECL_LANGUAGE (x) = lang_c; + SET_DECL_LANGUAGE (x, lang_c); } if (DECL_NON_THUNK_FUNCTION_P (x) && ! DECL_FUNCTION_MEMBER_P (x)) @@ -6727,7 +6727,7 @@ build_library_fn_1 (name, operator_code, type) DECL_ARTIFICIAL (fn) = 1; TREE_NOTHROW (fn) = 1; SET_OVERLOADED_OPERATOR_CODE (fn, operator_code); - DECL_LANGUAGE (fn) = lang_c; + SET_DECL_LANGUAGE (fn, lang_c); return fn; } @@ -6754,7 +6754,7 @@ build_cp_library_fn (name, operator_code, type) tree fn = build_library_fn_1 (name, operator_code, type); TREE_NOTHROW (fn) = TYPE_NOTHROW_P (type); DECL_CONTEXT (fn) = FROB_CONTEXT (current_namespace); - DECL_LANGUAGE (fn) = lang_cplusplus; + SET_DECL_LANGUAGE (fn, lang_cplusplus); set_mangled_name_for_decl (fn); return fn; } @@ -8759,7 +8759,7 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals, && ctype == NULL_TREE /* NULL_TREE means global namespace. */ && DECL_CONTEXT (decl) == NULL_TREE) - DECL_LANGUAGE (decl) = lang_c; + SET_DECL_LANGUAGE (decl, lang_c); /* Should probably propagate const out from type to decl I bet (mrs). */ if (staticp) @@ -9031,9 +9031,13 @@ grokvardecl (type, declarator, specbits_in, initialized, constp, in_namespace) else context = NULL_TREE; - if (processing_template_decl && context) - /* For global variables, declared in a template, we need the - full lang_decl. */ + /* For namespace-scope variables, declared in a template, we + need the full lang_decl. The same is true for + namespace-scope variables that do not have C++ language + linkage. */ + if (context + && (processing_template_decl + || current_lang_name != lang_name_cplusplus)) decl = build_lang_decl (VAR_DECL, declarator, type); else decl = build_decl (VAR_DECL, declarator, type); diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index f8524cb3c50..42df4e71366 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -1008,7 +1008,7 @@ grokclassfn (ctype, function, flags, quals) /* Even within an `extern "C"' block, members get C++ linkage. See [dcl.link] for details. */ - DECL_LANGUAGE (function) = lang_cplusplus; + SET_DECL_LANGUAGE (function, lang_cplusplus); if (fn_name == NULL_TREE) { diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c index 5120f204ed3..cb6a4d92461 100644 --- a/gcc/cp/lex.c +++ b/gcc/cp/lex.c @@ -1509,11 +1509,11 @@ retrofit_lang_decl (t) DECL_LANG_SPECIFIC (t) = ld; if (current_lang_name == lang_name_cplusplus) - DECL_LANGUAGE (t) = lang_cplusplus; + SET_DECL_LANGUAGE (t, lang_cplusplus); else if (current_lang_name == lang_name_c) - DECL_LANGUAGE (t) = lang_c; + SET_DECL_LANGUAGE (t, lang_c); else if (current_lang_name == lang_name_java) - DECL_LANGUAGE (t) = lang_java; + SET_DECL_LANGUAGE (t, lang_java); else my_friendly_abort (64); #ifdef GATHER_STATISTICS diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c index 18f99a10fbf..7b6857d6793 100644 --- a/gcc/cp/mangle.c +++ b/gcc/cp/mangle.c @@ -2085,17 +2085,15 @@ mangle_decl_string (decl) if (TREE_CODE (decl) == TYPE_DECL) write_type (TREE_TYPE (decl)); else if (/* The names of `extern "C"' functions are not mangled. */ - (TREE_CODE (decl) == FUNCTION_DECL + (DECL_EXTERN_C_FUNCTION_P (decl) /* But overloaded operator names *are* mangled. */ - && !DECL_OVERLOADED_OPERATOR_P (decl) - /* If there's no DECL_LANG_SPECIFIC, it's a function built - by language-independent code, which never builds - functions with C++ linkage. */ - && (!DECL_LANG_SPECIFIC (decl) - || DECL_EXTERN_C_FUNCTION_P (decl))) + && !DECL_OVERLOADED_OPERATOR_P (decl)) /* The names of global variables aren't mangled either. */ || (TREE_CODE (decl) == VAR_DECL - && CP_DECL_CONTEXT (decl) == global_namespace)) + && CP_DECL_CONTEXT (decl) == global_namespace) + /* And neither are `extern "C"' variables. */ + || (TREE_CODE (decl) == VAR_DECL + && DECL_EXTERN_C_P (decl))) write_string (IDENTIFIER_POINTER (DECL_NAME (decl))); else { diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 87dd778450c..2141e5ca209 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -1910,7 +1910,7 @@ finish_member_declaration (decl) A C language linkage is ignored for the names of class members and the member function type of class member functions. */ if (DECL_LANG_SPECIFIC (decl) && DECL_LANGUAGE (decl) == lang_c) - DECL_LANGUAGE (decl) = lang_cplusplus; + SET_DECL_LANGUAGE (decl, lang_cplusplus); /* Put functions on the TYPE_METHODS list and everything else on the TYPE_FIELDS list. Note that these are built up in reverse order. diff --git a/gcc/testsuite/g++.old-deja/g++.other/linkage7.C b/gcc/testsuite/g++.old-deja/g++.other/linkage7.C new file mode 100644 index 00000000000..207a63278f9 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.other/linkage7.C @@ -0,0 +1,14 @@ +// Build don't link: +// Origin: Mark Mitchell + +namespace N { + extern "C" int i; + + void f () { + i = 3; + } +}; + +int i; + +int main () { N::f (); }