From: Mike Stump Date: Mon, 3 Apr 1995 19:28:01 +0000 (+0000) Subject: 62nd Cygnus<->FSF merge X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=faae18abc203528841d2aa8c6481f0c5f0638a7e;p=gcc.git 62nd Cygnus<->FSF merge From-SVN: r9298 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 3f1f604c649..1f68bf6ca99 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,116 @@ +Sun Apr 2 23:43:51 1995 Jason Merrill + + * search.c (compute_access): Don't try to do access control on + nested types. + +Fri Mar 31 10:14:23 1995 Jason Merrill + + * repo.c: New file to handle things repo. + + * pt.c (instantiate_template): Call repo_template_used if the + definition is accessible. + (mark_function_instantiated): Split out from + do_function_instantiation. + (mark_class_instantiated): Split out from do_type_instantiation. + + * parse.y (template_instantiate_once): Call repo_template_used. + + * lex.c (lang_init): Call init_repo. + + * decl2.c: Handle flag_use_repository. + (finish_file): Call finish_repo. + + * decl.c (start_method): Call repo_template_used if this is a + template method. + + * Makefile.in (CXX_OBJS): Add repo.o. + (repo.o): Add dependencies. + + * Make-lang.in (CXX_SRCS): Add repo.c. + + * decl.c (start_function): If DECL_INTERFACE_KNOWN and + DECL_NOT_REALLY_EXTERN are both set, unset DECL_EXTERNAL. + + * typeck.c (build_binary_op_nodefault): Identify the invalid operand + types used. + + * decl.c (duplicate_decls): Propagate DECL_NOT_REALLY_EXTERN. + +Thu Mar 30 17:54:42 1995 Jason Merrill + + * typeck.c (build_binary_op_nodefault): Tidy up use of build_type + and result_type. When checking for comparison between signed + and unsigned, use result_type rather than the (possibly shortened) + type of op0. Also, don't warn about equality comparison of a + signed operand to an unsigned constant that fits in the signed + type. + + * method.c (do_build_copy_constructor): Reverse + current_base_init_list after we've built it up. + +Thu Mar 30 14:35:18 1995 Mike Stump + + * except.c (build_throw): Never warn about the value of throw not + being used. + +Thu Mar 30 13:16:54 1995 Mike Stump + + * except.c (expand_start_catch_block): Check for bad catch parameter + declarations. + +Thu Mar 30 13:06:11 1995 Jason Merrill + + * decl.c (finish_function): Only set DECL_NOT_REALLY_EXTERN if + DECL_EXTERNAL is not already set. + +Thu Mar 30 11:26:24 1995 Mike Stump + + * method.c (emit_thunk): Let poplevel know that the last level is + for a function so it can create a BLOCK_NODE and set DECL_INITIAL. + +Thu Mar 30 11:15:06 1995 Jason Merrill + + * decl2.c (import_export_inline): Don't set DECL_NOT_REALLY_EXTERN + here. + + * decl.c (grokdeclarator): OK, don't abort if we see a decl with + METHOD_TYPE. + (finish_function): Set DECL_EXTERNAL and DECL_NOT_REALLY_EXTERN on + all deferred inlines. + +Wed Mar 29 19:35:02 1995 Jason Merrill + + * cp-tree.h (DECL_THIS_INLINE): New macro. + (DECL_NOT_REALLY_EXTERN): New macro. + (DECL_THIS_STATIC): New macro. + + * decl.c: Lose all references to current_extern_inline. Break + inline semantics into DECL_INLINE for actual inlining and + DECL_THIS_INLINE for the linkage wierdness. Use DECL_THIS_STATIC. + * decl2.c: Use DECL_NOT_REALLY_EXTERN to indicate that we want to + emit an inline here. Associated changes. + * lex.c: Ditto. + * pt.c: Ditto. + * typeck.c: Ditto. + + * call.c (build_method_call): Don't bother trying to handle inlines + specially. + * cvt.c (convert_to_aggr): Ditto. + + * pt.c (do_function_instantiation): Handle instantiation of + public inlines, too. + +Wed Mar 29 16:04:25 1995 Mike Stump + + * except.c (init_exception_processing): Change the interface for + __throw_type_match and add decl for new rtti matching routine + __throw_type_match_rtti. + (build_eh_type): New routine to build a run time descriptor for the + expression given. + (expand_start_catch_block): Update to use new calling convention for + the matcher. + (expand_throw): Update to use build_eh_type. + Mon Mar 27 07:14:33 1995 Warner Losh * g++.c: Removed __NetBSD__ from conditional. diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in index 75bd8dacb99..3eadf90a2ab 100644 --- a/gcc/cp/Make-lang.in +++ b/gcc/cp/Make-lang.in @@ -76,7 +76,7 @@ CXX_SRCS = $(srcdir)/cp/call.c $(srcdir)/cp/decl2.c \ $(srcdir)/cp/errfn.c $(srcdir)/cp/gc.c $(srcdir)/cp/method.c \ $(srcdir)/cp/search.c $(srcdir)/cp/typeck.c $(srcdir)/cp/decl.c \ $(srcdir)/cp/error.c $(srcdir)/cp/init.c $(srcdir)/cp/parse.y \ - $(srcdir)/cp/sig.c $(srcdir)/cp/typeck2.c + $(srcdir)/cp/sig.c $(srcdir)/cp/typeck2.c $(srcdir)/cp/repo.c cc1plus: $(P) $(CXX_SRCS) $(LIBDEPS) stamp-objlist c-common.o c-pragma.o cd cp; $(MAKE) $(FLAGS_TO_PASS) $(CXX_FLAGS_TO_PASS) ../cc1plus diff --git a/gcc/cp/Makefile.in b/gcc/cp/Makefile.in index 6007f00d042..98fea7eb2ae 100644 --- a/gcc/cp/Makefile.in +++ b/gcc/cp/Makefile.in @@ -159,7 +159,7 @@ INCLUDES = -I. -I.. -I$(srcdir) -I$(srcdir)/.. -I$(srcdir)/../config CXX_OBJS = call.o decl.o errfn.o expr.o pt.o sig.o typeck2.o \ class.o decl2.o error.o gc.o lex.o parse.o ptree.o spew.o typeck.o cvt.o \ - edsel.o except.o init.o method.o search.o tree.o xref.o + edsel.o except.o init.o method.o search.o tree.o xref.o repo.o # Language-independent object files. OBJS = `cat ../stamp-objlist` ../c-common.o ../c-pragma.o @@ -247,6 +247,7 @@ pt.o : pt.c $(CONFIG_H) $(CXX_TREE_H) decl.h $(PARSE_H) error.o : error.c $(CONFIG_H) $(CXX_TREE_H) errfn.o : errfn.c $(CONFIG_H) $(CXX_TREE_H) sig.o : sig.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h +repo.o : repo.c $(CONFIG.H) $(CXX_TREE_H) # These exist for maintenance purposes. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 9ba6d1894e7..151d02f0d7a 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -2575,14 +2575,8 @@ build_method_call (instance, name, parms, basetype_path, flags) if (TREE_CODE (function) == FUNCTION_DECL) { is_constructor = DECL_CONSTRUCTOR_P (function); - if (DECL_INLINE (function)) - function = build1 (ADDR_EXPR, build_pointer_type (fntype), function); - else - { - assemble_external (function); - TREE_USED (function) = 1; - function = default_conversion (function); - } + TREE_USED (function) = 1; + function = default_conversion (function); } else { diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 98ea89f09f1..5dd853aff73 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -954,9 +954,11 @@ struct lang_decl_flags unsigned saved_inline : 1; unsigned use_template : 2; - unsigned declared_static : 1; + unsigned c_static : 1; unsigned nonconverting : 1; - unsigned dummy : 6; + unsigned declared_inline : 1; + unsigned not_really_extern : 1; + unsigned dummy : 4; tree access; tree context; @@ -1234,10 +1236,14 @@ struct lang_decl #define DELTA2_FROM_PTRMEMFUNC(NODE) (build_component_ref (build_component_ref ((NODE), pfn_or_delta2_identifier, 0, 0), delta2_identifier, 0, 0)) #define PFN_FROM_PTRMEMFUNC(NODE) (build_component_ref (build_component_ref ((NODE), pfn_or_delta2_identifier, 0, 0), pfn_identifier, 0, 0)) -/* Nonzero for VAR_DECL and FUNCTION_DECL node means that `external' was +/* Nonzero for VAR_DECL and FUNCTION_DECL node means that `extern' was specified in its declaration. */ #define DECL_THIS_EXTERN(NODE) (DECL_LANG_FLAG_2(NODE)) +/* Nonzero for VAR_DECL and FUNCTION_DECL node means that `static' was + specified in its declaration. */ +#define DECL_THIS_STATIC(NODE) (DECL_LANG_FLAG_6(NODE)) + /* Nonzero for SAVE_EXPR if used to initialize a PARM_DECL. */ #define PARM_DECL_EXPR(NODE) (TREE_LANG_FLAG_2(NODE)) @@ -1338,13 +1344,26 @@ struct lang_decl /* We know what we're doing with this decl now. */ #define DECL_INTERFACE_KNOWN(NODE) DECL_LANG_FLAG_5 (NODE) -/* This decl was declared to have internal linkage. */ -#define DECL_DECLARED_STATIC(NODE) \ - (DECL_LANG_SPECIFIC (NODE)->decl_flags.declared_static) +/* This decl was declared or deduced to have internal linkage. This is + only meaningful if TREE_PUBLIC is set. */ +#define DECL_C_STATIC(NODE) \ + (DECL_LANG_SPECIFIC (NODE)->decl_flags.c_static) + +/* This function was declared inline. This flag controls the linkage + semantics of 'inline'; whether or not the function is inlined is + controlled by DECL_INLINE. */ +#define DECL_THIS_INLINE(NODE) \ + (DECL_LANG_SPECIFIC (NODE)->decl_flags.declared_inline) + +/* DECL_EXTERNAL must be set on a decl until the decl is actually emitted, + so that assemble_external will work properly. So we have this flag to + tell us whether the decl is really not external. */ +#define DECL_NOT_REALLY_EXTERN(NODE) \ + (DECL_LANG_SPECIFIC (NODE)->decl_flags.not_really_extern) #define DECL_PUBLIC(NODE) \ - (TREE_CODE (NODE) == FUNCTION_DECL ? ! DECL_DECLARED_STATIC (NODE) \ - : TREE_PUBLIC (NODE)) + (TREE_CODE (NODE) == FUNCTION_DECL \ + ? ! DECL_C_STATIC (NODE) : TREE_PUBLIC (NODE)) #define THUNK_DELTA(DECL) ((DECL)->decl.frame_size.i) diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c index 0ceabf01533..8cee211285a 100644 --- a/gcc/cp/cvt.c +++ b/gcc/cp/cvt.c @@ -1090,10 +1090,7 @@ convert_to_aggr (type, expr, msgp, protect) return NULL_TREE; fntype = TREE_TYPE (function); - if (DECL_INLINE (function) && TREE_CODE (function) == FUNCTION_DECL) - function = build1 (ADDR_EXPR, build_pointer_type (fntype), function); - else - function = default_conversion (function); + function = default_conversion (function); result = build_nt (CALL_EXPR, function, convert_arguments (NULL_TREE, TYPE_ARG_TYPES (fntype), diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index c6c63791c44..de9e5b72e4e 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -406,10 +406,6 @@ tree current_function_return_value; static int warn_about_return_type; -/* Nonzero when starting a function declared `extern inline'. */ - -static int current_extern_inline; - /* Nonzero means give `double' the same size as `float'. */ extern int flag_short_double; @@ -2082,13 +2078,11 @@ warn_extern_redeclared_static (newdecl, olddecl) = "`%D' was declared implicitly `extern' and later `static'"; if (flag_traditional - || TREE_CODE (newdecl) == TYPE_DECL - || (! warn_extern_inline - && DECL_INLINE (newdecl))) + || TREE_CODE (newdecl) == TYPE_DECL) return; name = DECL_ASSEMBLER_NAME (newdecl); - if (TREE_PUBLIC (name) && ! DECL_PUBLIC (newdecl)) + if (TREE_PUBLIC (name) && DECL_THIS_STATIC (newdecl)) { /* It's okay to redeclare an ANSI built-in function as static, or to declare a non-ANSI built-in function as anything. */ @@ -2516,8 +2510,9 @@ duplicate_decls (newdecl, olddecl) if (TREE_CODE (newdecl) == FUNCTION_DECL) { - DECL_DECLARED_STATIC (newdecl) = DECL_DECLARED_STATIC (olddecl); + DECL_C_STATIC (newdecl) = DECL_C_STATIC (olddecl); DECL_INTERFACE_KNOWN (newdecl) = DECL_INTERFACE_KNOWN (olddecl); + DECL_NOT_REALLY_EXTERN (newdecl) = DECL_NOT_REALLY_EXTERN (olddecl); } } else @@ -2537,14 +2532,16 @@ duplicate_decls (newdecl, olddecl) } } - /* If either decl says `inline', this fn is inline, - unless its definition was passed already. */ - if (DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) == NULL_TREE) - DECL_INLINE (olddecl) = 1; - DECL_INLINE (newdecl) = DECL_INLINE (olddecl); - if (TREE_CODE (newdecl) == FUNCTION_DECL) { + DECL_THIS_INLINE (newdecl) |= DECL_THIS_INLINE (olddecl); + + /* If either decl says `inline', this fn is inline, unless its + definition was passed already. */ + if (DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) == NULL_TREE) + DECL_INLINE (olddecl) = 1; + DECL_INLINE (newdecl) = DECL_INLINE (olddecl); + if (! types_match) { DECL_LANGUAGE (olddecl) = DECL_LANGUAGE (newdecl); @@ -2968,7 +2965,7 @@ pushdecl (x) /* If this is an extern function declaration, see if we have a global definition or declaration for the function. */ if (oldlocal == NULL_TREE - && DECL_EXTERNAL (x) && !DECL_INLINE (x) + && DECL_EXTERNAL (x) && oldglobal != NULL_TREE && TREE_CODE (x) == FUNCTION_DECL && TREE_CODE (oldglobal) == FUNCTION_DECL) @@ -3454,11 +3451,7 @@ redeclaration_error_message (newdecl, olddecl) /* defining the same name twice is no good. */ if (DECL_INITIAL (olddecl) != NULL_TREE - && DECL_INITIAL (newdecl) != NULL_TREE - /* However, defining once as extern inline and a second - time in another way is ok. */ - && !(DECL_INLINE (olddecl) && DECL_EXTERNAL (olddecl) - && !(DECL_INLINE (newdecl) && DECL_EXTERNAL (newdecl)))) + && DECL_INITIAL (newdecl) != NULL_TREE) { if (DECL_NAME (olddecl) == NULL_TREE) return "`%#D' not declared in class"; @@ -6393,55 +6386,7 @@ finish_decl (decl, init, asmspec_tree, need_pop, flags) signature_error (decl, TREE_TYPE (type)); if (TREE_CODE (decl) == FUNCTION_DECL) - { -#if 0 - /* C++: Handle overloaded functions with default parameters. */ - if (DECL_OVERLOADED (decl)) - { - tree parmtypes = TYPE_ARG_TYPES (type); - tree prev = NULL_TREE; - tree original_name = DECL_NAME (decl); - struct lang_decl *tmp_lang_decl = DECL_LANG_SPECIFIC (decl); - /* All variants will share an uncollectible lang_decl. */ - copy_decl_lang_specific (decl); - - while (parmtypes && parmtypes != void_list_node) - { - /* The default value for the parameter in parmtypes is - stored in the TREE_PURPOSE of the TREE_LIST. */ - if (TREE_PURPOSE (parmtypes)) - { - tree fnname, fndecl; - tree *argp; - - argp = prev ? & TREE_CHAIN (prev) - : & TYPE_ARG_TYPES (type); - - *argp = NULL_TREE; - fnname = build_decl_overload (original_name, - TYPE_ARG_TYPES (type), 0); - *argp = parmtypes; - fndecl = build_decl (FUNCTION_DECL, fnname, type); - DECL_EXTERNAL (fndecl) = DECL_EXTERNAL (decl); - TREE_PUBLIC (fndecl) = TREE_PUBLIC (decl); - DECL_INLINE (fndecl) = DECL_INLINE (decl); - /* Keep G++ from thinking this function is unused. - It is only used to speed up search in name space. */ - TREE_USED (fndecl) = 1; - TREE_ASM_WRITTEN (fndecl) = 1; - DECL_INITIAL (fndecl) = NULL_TREE; - DECL_LANG_SPECIFIC (fndecl) = DECL_LANG_SPECIFIC (decl); - fndecl = pushdecl (fndecl); - DECL_INITIAL (fndecl) = error_mark_node; - DECL_RTL (fndecl) = DECL_RTL (decl); - } - prev = parmtypes; - parmtypes = TREE_CHAIN (parmtypes); - } - DECL_LANG_SPECIFIC (decl) = tmp_lang_decl; - } -#endif - } + ; else if (DECL_EXTERNAL (decl)) ; else if (TREE_STATIC (decl) && type != error_mark_node) @@ -6775,13 +6720,13 @@ bad_specifiers (object, type, virtualp, quals, inlinep, friendp, raises) not look, and -1 if we should not call `grokclassfn' at all. */ static tree grokfndecl (ctype, type, declarator, virtualp, flags, quals, - raises, check, publicp) + raises, check, publicp, inlinep) tree ctype, type; tree declarator; int virtualp; enum overload_flags flags; tree quals, raises; - int check, publicp; + int check, publicp, inlinep; { tree cname, decl; int staticp = ctype && TREE_CODE (type) == FUNCTION_TYPE; @@ -6814,10 +6759,21 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals, definition or EOF) if appropriate. */ TREE_PUBLIC (decl) = 1; - if (publicp) - ; - else - DECL_DECLARED_STATIC (decl) = 1; + if (ctype == NULL_TREE && ! strcmp (IDENTIFIER_POINTER (declarator), "main")) + { + if (inlinep) + error ("cannot declare `main' to be inline"); + else if (! publicp) + error ("cannot declare `main' to be static"); + inlinep = 0; + publicp = 1; + } + + if (! publicp) + DECL_C_STATIC (decl) = 1; + + if (inlinep) + DECL_THIS_INLINE (decl) = DECL_INLINE (decl) = 1; DECL_EXTERNAL (decl) = 1; if (quals != NULL_TREE && TREE_CODE (type) == FUNCTION_TYPE) @@ -9060,37 +9016,30 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) } /* Tell grokfndecl if it needs to set TREE_PUBLIC on the node. */ - publicp = (RIDBIT_SETP (RID_EXTERN, specbits) - || (ctype != NULL_TREE - && funcdef_flag >= 0 - && RIDBIT_NOTSETP (RID_INLINE, specbits)) - || (friendp - && ! funcdef_flag - && RIDBIT_NOTSETP (RID_STATIC, specbits) - && RIDBIT_NOTSETP (RID_INLINE, specbits))); + publicp = (! friendp + || RIDBIT_SETP (RID_EXTERN, specbits) + || ! (funcdef_flag < 0 || inlinep)); decl = grokfndecl (ctype, type, declarator, virtualp, flags, quals, - raises, friendp ? -1 : 0, publicp); + raises, friendp ? -1 : 0, publicp, inlinep); if (decl == NULL_TREE) return NULL_TREE; decl = build_decl_attribute_variant (decl, decl_machine_attr); if (explicitp == 2) DECL_NONCONVERTING_P (decl) = 1; - - DECL_INLINE (decl) = inlinep; } else if (TREE_CODE (type) == METHOD_TYPE) { + /* We only get here for friend declarations of + members of other classes. */ /* All method decls are public, so tell grokfndecl to set TREE_PUBLIC, also. */ decl = grokfndecl (ctype, type, declarator, virtualp, flags, quals, - raises, friendp ? -1 : 0, 1); + raises, friendp ? -1 : 0, 1, 0); if (decl == NULL_TREE) return NULL_TREE; - - DECL_INLINE (decl) = inlinep; } else if (TYPE_SIZE (type) == NULL_TREE && !staticp && (TREE_CODE (type) != ARRAY_TYPE || initialized == 0)) @@ -9255,16 +9204,16 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) type = build_cplus_method_type (build_type_variant (ctype, constp, volatilep), TREE_TYPE (type), TYPE_ARG_TYPES (type)); - /* Record presence of `static'. In C++, `inline' is like `static'. */ - publicp - = !(RIDBIT_SETP (RID_STATIC, specbits) - || RIDBIT_SETP (RID_INLINE, specbits)); + /* Record presence of `static'. In C++, `inline' implies `static'. */ + publicp = (ctype != NULL_TREE + || (!RIDBIT_SETP (RID_STATIC, specbits) + && !RIDBIT_SETP (RID_INLINE, specbits))); decl = grokfndecl (ctype, type, original_name, virtualp, flags, quals, raises, processing_template_decl ? 0 : friendp ? 2 : 1, - publicp); + publicp, inlinep); if (decl == NULL_TREE) return NULL_TREE; @@ -9282,14 +9231,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) cp_pedwarn ("cannot declare member function `%D' to have static linkage", decl); illegal_static = 1; } - else if (! ctype - && IDENTIFIER_LENGTH (original_name) == 4 - && IDENTIFIER_POINTER (original_name)[0] == 'm' - && ! strcmp (IDENTIFIER_POINTER (original_name), "main")) - { - error ("cannot declare function `main' to have static linkage"); - illegal_static = 1; - } else if (current_function_decl) { /* FIXME need arm citation */ @@ -9303,28 +9244,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) RIDBIT_RESET (RID_STATIC, specbits); } } - - /* Record presence of `inline', if it is reasonable. */ - if (inlinep) - { - tree last = tree_last (TYPE_ARG_TYPES (type)); - - if (! ctype - && ! strcmp (IDENTIFIER_POINTER (original_name), "main")) - error ("cannot inline function `main'"); - else if (last && last != void_list_node) - cp_warning ("cannot inline function `%D' which takes `...'", original_name); - else - /* Assume that otherwise the function can be inlined. */ - DECL_INLINE (decl) = 1; - - if (RIDBIT_SETP (RID_EXTERN, specbits)) - { - current_extern_inline = 1; - if (pedantic) - pedwarn ("ANSI C++ does not permit `extern inline'"); - } - } } else { @@ -9398,6 +9317,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) if (RIDBIT_SETP (RID_EXTERN, specbits)) DECL_THIS_EXTERN (decl) = 1; + if (RIDBIT_SETP (RID_STATIC, specbits)) + DECL_THIS_STATIC (decl) = 1; + /* Record constancy and volatility. */ if (constp) @@ -10723,7 +10645,6 @@ start_function (declspecs, declarator, raises, pre_parsed_p) current_function_returns_value = 0; current_function_returns_null = 0; warn_about_return_type = 0; - current_extern_inline = 0; current_function_assigns_this = 0; current_function_just_assigned_this = 0; current_function_parms_stored = 0; @@ -10781,11 +10702,6 @@ start_function (declspecs, declarator, raises, pre_parsed_p) doing_friend = 1; } - if ( !(DECL_VINDEX (decl1) - && write_virtuals >= 2 - && CLASSTYPE_VTABLE_NEEDS_WRITING (ctype))) - current_extern_inline = DECL_THIS_EXTERN (decl1) && DECL_INLINE (decl1); - raises = TYPE_RAISES_EXCEPTIONS (fntype); /* In a fcn definition, arg types must be complete. */ @@ -10890,18 +10806,21 @@ start_function (declspecs, declarator, raises, pre_parsed_p) TREE_STATIC (decl1) = 1; if (DECL_INTERFACE_KNOWN (decl1)) - /* We know. */; + { + if (DECL_NOT_REALLY_EXTERN (decl1)) + DECL_EXTERNAL (decl1) = 0; + } /* If this function belongs to an interface, it is public. If it belongs to someone else's interface, it is also external. It doesn't matter whether it's inline or not. */ else if (interface_unknown == 0) { - if (DECL_DECLARED_STATIC (decl1) || DECL_TEMPLATE_INSTANTIATION (decl1)) + if (DECL_THIS_INLINE (decl1) || DECL_TEMPLATE_INSTANTIATION (decl1)) DECL_EXTERNAL (decl1) = (interface_only - || (DECL_INLINE (decl1) && ! flag_implement_inlines)); + || (DECL_THIS_INLINE (decl1) && ! flag_implement_inlines)); else - DECL_EXTERNAL (decl1) = current_extern_inline; + DECL_EXTERNAL (decl1) = 0; DECL_INTERFACE_KNOWN (decl1) = 1; } else @@ -10909,19 +10828,15 @@ start_function (declspecs, declarator, raises, pre_parsed_p) /* This is a definition, not a reference. So clear DECL_EXTERNAL. */ DECL_EXTERNAL (decl1) = 0; - - if (DECL_INLINE (decl1) && (DECL_FUNCTION_MEMBER_P (decl1) - || DECL_TEMPLATE_INSTANTIATION (decl1) - || current_extern_inline)) - /* We know nothing yet */; + + if (DECL_THIS_INLINE (decl1) && ! DECL_C_STATIC (decl1)) + DECL_DEFER_OUTPUT (decl1) = 1; else { DECL_INTERFACE_KNOWN (decl1) = 1; - if (DECL_DECLARED_STATIC (decl1)) + if (DECL_C_STATIC (decl1)) TREE_PUBLIC (decl1) = 0; } - - DECL_DEFER_OUTPUT (decl1) = ! DECL_INTERFACE_KNOWN (decl1); } /* Record the decl so that the function name is defined. @@ -11728,9 +11643,10 @@ finish_function (lineno, call_poplevel, nested) if (DECL_SAVED_INSNS (fndecl) && ! TREE_ASM_WRITTEN (fndecl)) { /* Set DECL_EXTERNAL so that assemble_external will be called as - necessary. We'll clear it again in import_export_inline. */ - if (TREE_PUBLIC (fndecl)) - DECL_EXTERNAL (fndecl) = 1; + necessary. We'll clear it again in finish_file. */ + if (! DECL_EXTERNAL (fndecl)) + DECL_NOT_REALLY_EXTERN (fndecl) = 1; + DECL_EXTERNAL (fndecl) = 1; mark_inline_for_output (fndecl); } @@ -11857,11 +11773,16 @@ start_method (declspecs, declarator, raises) return void_type_node; } + DECL_THIS_INLINE (fndecl) = 1; + if (flag_default_inline) DECL_INLINE (fndecl) = 1; if (processing_template_defn) - SET_DECL_IMPLICIT_INSTANTIATION (fndecl); + { + SET_DECL_IMPLICIT_INSTANTIATION (fndecl); + repo_template_used (fndecl); + } /* We read in the parameters on the maybepermanent_obstack, but we won't be getting back to them until after we @@ -12207,7 +12128,6 @@ struct cp_function int returns_value; int returns_null; int warn_about_return_type; - int extern_inline; int assigns_this; int just_assigned_this; int parms_stored; @@ -12247,7 +12167,6 @@ push_cp_function_context (context) p->returns_value = current_function_returns_value; p->returns_null = current_function_returns_null; p->warn_about_return_type = warn_about_return_type; - p->extern_inline = current_extern_inline; p->binding_level = current_binding_level; p->ctor_label = ctor_label; p->dtor_label = dtor_label; @@ -12295,7 +12214,6 @@ pop_cp_function_context (context) current_function_returns_value = p->returns_value; current_function_returns_null = p->returns_null; warn_about_return_type = p->warn_about_return_type; - current_extern_inline = p->extern_inline; current_binding_level = p->binding_level; ctor_label = p->ctor_label; dtor_label = p->dtor_label; diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 55ad97e0269..edce5802375 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -148,6 +148,10 @@ int warn_ctor_dtor_privacy = 1; int flag_vtable_thunks; +/* True if we want to deal with repository information. */ + +int flag_use_repository; + /* Nonzero means give string constants the type `const char *' to get extra warnings from them. These warnings will be too numerous to be useful, except in thoroughly ANSIfied programs. */ @@ -399,7 +403,8 @@ static struct { char *string; int *variable; int on_value;} lang_f_options[] = {"nonansi-builtins", &flag_no_nonansi_builtin, 0}, {"gnu-keywords", &flag_no_gnu_keywords, 0}, {"operator-names", &flag_operator_names, 1}, - {"check-new", &flag_check_new, 1} + {"check-new", &flag_check_new, 1}, + {"repo", &flag_use_repository, 1} }; /* Decode the string P as a language-specific option. @@ -2466,13 +2471,7 @@ mark_vtable_entries (decl) fnaddr = TREE_VALUE (entries); TREE_OPERAND (fnaddr, 0) = fn = abort_fndecl; } - if (TREE_PUBLIC (fn) && ! TREE_ASM_WRITTEN (fn)) - { - int save_extern = DECL_EXTERNAL (fn); - DECL_EXTERNAL (fn) = 1; - assemble_external (fn); - DECL_EXTERNAL (fn) = save_extern; - } + assemble_external (fn); } } @@ -2513,12 +2512,11 @@ import_export_vtable (decl, type, final) if (! found && ! final) { - /* This check only works before the method definitions are seen, - since DECL_INLINE may get bashed. */ tree method; for (method = CLASSTYPE_METHODS (type); method != NULL_TREE; method = DECL_NEXT_METHOD (method)) - if (DECL_VINDEX (method) != NULL_TREE && ! DECL_INLINE (method) + if (DECL_VINDEX (method) != NULL_TREE + && ! DECL_THIS_INLINE (method) && ! DECL_ABSTRACT_VIRTUAL_P (method)) { found = 1; @@ -2528,15 +2526,17 @@ import_export_vtable (decl, type, final) if (final || ! found) { +#ifdef ASSEMBLE_EXTERNAL + if (TREE_PUBLIC (decl)) + cp_error ("all virtual functions redeclared inline"); +#endif TREE_PUBLIC (decl) = 0; DECL_EXTERNAL (decl) = 0; - DECL_INTERFACE_KNOWN (decl) = 1; } else { TREE_PUBLIC (decl) = 1; DECL_EXTERNAL (decl) = 1; - DECL_INTERFACE_KNOWN (decl) = 0; } } } @@ -2570,7 +2570,7 @@ finish_prevtable_vardecl (prev, vars) method = DECL_NEXT_METHOD (method)) { if (DECL_VINDEX (method) != NULL_TREE - && !DECL_DECLARED_STATIC (method) + && !DECL_THIS_INLINE (method) && !DECL_ABSTRACT_VIRTUAL_P (method)) { SET_CLASSTYPE_INTERFACE_KNOWN (ctype); @@ -2747,23 +2747,21 @@ import_export_inline (decl) if (DECL_INTERFACE_KNOWN (decl)) return; - DECL_EXTERNAL (decl) = 0; - if (DECL_TEMPLATE_INSTANTIATION (decl)) { if (DECL_IMPLICIT_INSTANTIATION (decl) && flag_implicit_templates) TREE_PUBLIC (decl) = 0; else - DECL_EXTERNAL (decl) = 1; + DECL_NOT_REALLY_EXTERN (decl) = 0; } else if (DECL_FUNCTION_MEMBER_P (decl)) { tree ctype = DECL_CLASS_CONTEXT (decl); if (CLASSTYPE_INTERFACE_KNOWN (ctype)) { - DECL_EXTERNAL (decl) - = (CLASSTYPE_INTERFACE_ONLY (ctype) - || (DECL_INLINE (decl) && ! flag_implement_inlines)); + DECL_NOT_REALLY_EXTERN (decl) + = ! (CLASSTYPE_INTERFACE_ONLY (ctype) + || (DECL_THIS_INLINE (decl) && ! flag_implement_inlines)); } else TREE_PUBLIC (decl) = 0; @@ -3045,6 +3043,8 @@ finish_file () assemble_constructor (IDENTIFIER_POINTER (fnname)); } + permanent_allocation (1); + /* Done with C language context needs. */ pop_lang_context (); @@ -3115,8 +3115,9 @@ finish_file () { TREE_CHAIN (last) = TREE_CHAIN (place); - if (! DECL_EXTERNAL (decl)) + if (DECL_NOT_REALLY_EXTERN (decl)) { + DECL_EXTERNAL (decl) = 0; reconsider = 1; temporary_allocation (); output_inline_function (decl); @@ -3142,7 +3143,7 @@ finish_file () emit_thunk (vars); else if (TREE_CODE (vars) == FUNCTION_DECL && ! DECL_INTERFACE_KNOWN (vars) - && DECL_DECLARED_STATIC (vars)) + && DECL_C_STATIC (vars)) TREE_PUBLIC (vars) = 0; } @@ -3162,7 +3163,8 @@ finish_file () } } - permanent_allocation (1); + finish_repo (); + this_time = get_run_time (); parse_time -= this_time - start_time; varconst_time += this_time - start_time; diff --git a/gcc/cp/except.c b/gcc/cp/except.c index 607d5034f2a..6c849fcdd5f 100644 --- a/gcc/cp/except.c +++ b/gcc/cp/except.c @@ -780,9 +780,14 @@ init_exception_processing () push_lang_context (lang_name_c); catch_match_fndecl = - define_function ("__throw_type_match", - build_function_type (integer_type_node, - tree_cons (NULL_TREE, string_type_node, tree_cons (NULL_TREE, ptr_type_node, void_list_node))), + define_function (flag_rtti + ? "__throw_type_match_rtti" + : "__throw_type_match", + build_function_type (ptr_type_node, + tree_cons (NULL_TREE, ptr_type_node, + tree_cons (NULL_TREE, ptr_type_node, + tree_cons (NULL_TREE, ptr_type_node, + void_list_node)))), NOT_BUILT_IN, pushdecl, 0); @@ -1131,6 +1136,31 @@ expand_leftover_cleanups () } } +/* Build a type value for use at runtime for a exp that is thrown or + matched against by the exception handling system. */ +static tree +build_eh_type (exp) + tree exp; +{ + char *typestring; + tree type; + + if (flag_rtti) + { + exp = build_typeid (exp); + return build1 (ADDR_EXPR, ptr_type_node, exp); + } + type = TREE_TYPE (exp); + + /* peel back references, so they match. */ + if (TREE_CODE (type) == REFERENCE_TYPE) + type = TREE_TYPE (type); + + typestring = build_overload_name (type, 1, 1); + exp = combine_strings (build_string (strlen (typestring)+1, typestring)); + return build1 (ADDR_EXPR, ptr_type_node, exp); +} + /* call this to start a catch block. Typename is the typename, and identifier is the variable to place the object in or NULL if the variable doesn't matter. If typename is NULL, that means its a "catch (...)" or catch @@ -1142,8 +1172,7 @@ expand_start_catch_block (declspecs, declarator) { rtx false_label_rtx; rtx protect_label_rtx; - tree type; - tree decl; + tree decl = NULL_TREE; tree init; if (! doing_eh (1)) @@ -1152,33 +1181,6 @@ expand_start_catch_block (declspecs, declarator) /* Create a binding level for the parm. */ expand_start_bindings (0); - if (declspecs) - { - tree init_type; - decl = grokdeclarator (declarator, declspecs, CATCHPARM, 1, NULL_TREE); - - /* Figure out the type that the initializer is. */ - init_type = TREE_TYPE (decl); - if (TREE_CODE (init_type) != REFERENCE_TYPE) - init_type = build_reference_type (init_type); - - init = convert_from_reference (save_expr (make_tree (init_type, saved_throw_value))); - - /* Do we need the below two lines? */ - /* Let `finish_decl' know that this initializer is ok. */ - DECL_INITIAL (decl) = init; - /* This needs to be preallocated under the try block, - in a union of all catch variables. */ - pushdecl (decl); - type = TREE_TYPE (decl); - - /* peel back references, so they match. */ - if (TREE_CODE (type) == REFERENCE_TYPE) - type = TREE_TYPE (type); - } - else - type = NULL_TREE; - /* These are saved for the exception table. */ push_rtl_perm (); false_label_rtx = gen_label_rtx (); @@ -1187,34 +1189,50 @@ expand_start_catch_block (declspecs, declarator) push_label_entry (&false_label_stack, false_label_rtx); push_label_entry (&false_label_stack, protect_label_rtx); - if (type) + if (declspecs) { - tree params; - char *typestring; + tree exp; rtx call_rtx, return_value_rtx; - tree catch_match_fcall; - tree catchmatch_arg, argval; - - typestring = build_overload_name (type, 1, 1); - - params = tree_cons (NULL_TREE, - combine_strings (build_string (strlen (typestring)+1, typestring)), - tree_cons (NULL_TREE, - make_tree (ptr_type_node, saved_throw_type), - NULL_TREE)); - catch_match_fcall = build_function_call (CatchMatch, params); - call_rtx = expand_call (catch_match_fcall, NULL_RTX, 0); + tree init_type; + + decl = grokdeclarator (declarator, declspecs, CATCHPARM, 1, NULL_TREE); + + if (decl == NULL_TREE) + { + error ("invalid catch parameter"); + return; + } + + /* Figure out the type that the initializer is. */ + init_type = TREE_TYPE (decl); + if (TREE_CODE (init_type) != REFERENCE_TYPE) + init_type = build_reference_type (init_type); + + exp = make_tree (ptr_type_node, saved_throw_value); + exp = tree_cons (NULL_TREE, + build_eh_type (decl), + tree_cons (NULL_TREE, + make_tree (ptr_type_node, saved_throw_type), + tree_cons (NULL_TREE, exp, NULL_TREE))); + exp = build_function_call (CatchMatch, exp); + call_rtx = expand_call (exp, NULL_RTX, 0); assemble_external (TREE_OPERAND (CatchMatch, 0)); - return_value_rtx = - hard_function_value (integer_type_node, catch_match_fcall); + return_value_rtx = hard_function_value (ptr_type_node, exp); /* did the throw type match function return TRUE? */ - emit_cmp_insn (return_value_rtx, const0_rtx, NE, NULL_RTX, + emit_cmp_insn (return_value_rtx, const0_rtx, EQ, NULL_RTX, GET_MODE (return_value_rtx), 0, 0); /* if it returned FALSE, jump over the catch block, else fall into it */ - emit_jump_insn (gen_bne (false_label_rtx)); + emit_jump_insn (gen_beq (false_label_rtx)); + + init = convert_from_reference (save_expr (make_tree (init_type, call_rtx))); + + /* Do we need the below two lines? */ + /* Let `finish_decl' know that this initializer is ok. */ + DECL_INITIAL (decl) = init; + decl = pushdecl (decl); finish_decl (decl, init, NULL_TREE, 0, LOOKUP_ONLYCONVERTING); } else @@ -1535,7 +1553,6 @@ expand_throw (exp) tree exp; { rtx label; - tree type; if (! doing_eh (1)) return; @@ -1548,26 +1565,28 @@ expand_throw (exp) if (exp) { + tree throw_type; + rtx throw_type_rtx; + rtx throw_value_rtx; + /* throw expression */ /* First, decay it. */ exp = default_conversion (exp); - type = TREE_TYPE (exp); - { - char *typestring = build_overload_name (type, 1, 1); - tree throw_type = build1 (ADDR_EXPR, ptr_type_node, combine_strings (build_string (strlen (typestring)+1, typestring))); - rtx throw_type_rtx = expand_expr (throw_type, NULL_RTX, VOIDmode, 0); - rtx throw_value_rtx; - - /* Make a copy of the thrown object. WP 15.1.5 */ - exp = build_new (NULL_TREE, type, build_tree_list (NULL_TREE, exp), 0); - - if (exp == error_mark_node) - error (" in thrown expression"); - throw_value_rtx = expand_expr (exp, NULL_RTX, VOIDmode, 0); - emit_move_insn (saved_throw_value, throw_value_rtx); - emit_move_insn (saved_throw_type, throw_type_rtx); - } + /* Make a copy of the thrown object. WP 15.1.5 */ + exp = build_new (NULL_TREE, TREE_TYPE (exp), + build_tree_list (NULL_TREE, exp), + 0); + + if (exp == error_mark_node) + error (" in thrown expression"); + + throw_type = build_eh_type (build_indirect_ref (exp, NULL_PTR)); + throw_type_rtx = expand_expr (throw_type, NULL_RTX, VOIDmode, 0); + + throw_value_rtx = expand_expr (exp, NULL_RTX, VOIDmode, 0); + emit_move_insn (saved_throw_value, throw_value_rtx); + emit_move_insn (saved_throw_type, throw_type_rtx); } else { @@ -1665,6 +1684,7 @@ build_throw (e) { e = build1 (THROW_EXPR, void_type_node, e); TREE_SIDE_EFFECTS (e) = 1; + TREE_USED (e) = 1; } return e; } diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c index 895f2694e87..6d46976769a 100644 --- a/gcc/cp/lex.c +++ b/gcc/cp/lex.c @@ -362,6 +362,7 @@ lang_init () if (flag_cadillac) cadillac_start (); if (flag_gnu_xref) GNU_xref_begin (input_filename); + init_repo (input_filename); } void @@ -1448,7 +1449,7 @@ store_pending_inline (decl, t) punt them now, or output them now if we're doing implementations and we know no overrides will exist. Otherwise, we delay until end-of-file, to see if the definition is really required. */ - if (DECL_INLINE (decl)) + if (DECL_THIS_INLINE (decl)) /* delay_to_eof == 0 */; else if (current_class_type && !interface_unknown) { diff --git a/gcc/cp/method.c b/gcc/cp/method.c index adbb97e0e50..1bf168438ed 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -1936,7 +1936,7 @@ emit_thunk (thunk_fndecl) emit_insn (gen_rtx (USE, VOIDmode, need_use[--need_use_count])); expand_end_bindings (NULL, 1, 0); - poplevel (0, 0, 0); + poplevel (0, 0, 1); /* From now on, allocate rtl in current_obstack, not in saveable_obstack. Note that that may have been done above, in save_for_inline_copying. @@ -2122,6 +2122,7 @@ do_build_copy_constructor (fndecl) = tree_cons (DECL_NAME (fields), init, current_member_init_list); } current_member_init_list = nreverse (current_member_init_list); + current_base_init_list = nreverse (current_base_init_list); setup_vtbl_ptr (); } diff --git a/gcc/cp/parse.y b/gcc/cp/parse.y index d8d7eb8ef2e..a4bbd55bdfb 100644 --- a/gcc/cp/parse.y +++ b/gcc/cp/parse.y @@ -897,6 +897,8 @@ template_instantiate_once: pop_obstacks (); end_template_instantiation ($1); + repo_template_used (t); + /* Now go after the methods & class data. */ instantiate_member_templates ($1); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index ce5e4f8515d..5b5dceb7962 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -1450,6 +1450,7 @@ tsubst (t, args, nargs, in_decl) TREE_STATIC (r) = 0; DECL_INTERFACE_KNOWN (r) = 0; DECL_INLINE (r) = DECL_INLINE (t); + DECL_THIS_INLINE (r) = DECL_THIS_INLINE (t); { #if 0 /* Maybe later. -jason */ struct tinst_level *til = tinst_for_decl(); @@ -1751,6 +1752,7 @@ instantiate_template (tmpl, targ_ptr) else if (t->text) { SET_DECL_IMPLICIT_INSTANTIATION (fndecl); + repo_template_used (fndecl); p = (struct pending_inline *) permalloc (sizeof (struct pending_inline)); p->parm_vec = t->parm_vec; p->bindings = targs; @@ -2384,7 +2386,7 @@ do_pending_expansions () DECIDE (0); if (DECL_EXPLICIT_INSTANTIATION (t)) - DECIDE (! DECL_EXTERNAL (t)); + DECIDE (DECL_NOT_REALLY_EXTERN (t)); else if (! flag_implicit_templates) DECIDE (0); @@ -2486,6 +2488,22 @@ add_pending_template (pt) p->id = pt; } +void +mark_function_instantiated (result, extern_p) + tree result; + int extern_p; +{ + if (DECL_TEMPLATE_INSTANTIATION (result)) + SET_DECL_EXPLICIT_INSTANTIATION (result); + TREE_PUBLIC (result) = 1; + + if (! extern_p) + { + DECL_INTERFACE_KNOWN (result) = 1; + DECL_NOT_REALLY_EXTERN (result) = 1; + } +} + /* called from the parser. */ void do_function_instantiation (declspecs, declarator, storage) @@ -2495,10 +2513,17 @@ do_function_instantiation (declspecs, declarator, storage) tree name = DECL_NAME (decl); tree fn = IDENTIFIER_GLOBAL_VALUE (name); tree result = NULL_TREE; + int extern_p = 0; if (fn) { for (fn = get_first_fn (fn); fn; fn = DECL_CHAIN (fn)) - if (TREE_CODE (fn) == TEMPLATE_DECL) + if (decls_match (fn, decl) + && DECL_DEFER_OUTPUT (fn)) + { + result = fn; + break; + } + else if (TREE_CODE (fn) == TEMPLATE_DECL) { int ntparms = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (fn)); tree *targs = (tree *) malloc (sizeof (tree) * ntparms); @@ -2518,27 +2543,40 @@ do_function_instantiation (declspecs, declarator, storage) } } if (! result) - cp_error ("no matching template for `%D' found", decl); + { + cp_error ("no matching template for `%D' found", decl); + return; + } if (flag_external_templates) return; - SET_DECL_EXPLICIT_INSTANTIATION (result); - TREE_PUBLIC (result) = 1; - if (storage == NULL_TREE) - { - DECL_INTERFACE_KNOWN (result) = 1; - DECL_EXTERNAL (result) = 0; - TREE_STATIC (result) = 1; - } - else if (storage == ridpointers[(int) RID_EXTERN]) ; + else if (storage == ridpointers[(int) RID_EXTERN]) + extern_p = 1; else cp_error ("storage class `%D' applied to template instantiation", storage); + mark_function_instantiated (result, extern_p); } +void +mark_class_instantiated (t, extern_p) + tree t; + int extern_p; +{ + SET_CLASSTYPE_EXPLICIT_INSTANTIATION (t); + SET_CLASSTYPE_INTERFACE_KNOWN (t); + CLASSTYPE_INTERFACE_ONLY (t) = extern_p; + CLASSTYPE_VTABLE_NEEDS_WRITING (t) = ! extern_p; + TYPE_DECL_SUPPRESS_DEBUG (TYPE_NAME (t)) = extern_p; + if (! extern_p) + { + CLASSTYPE_DEBUG_REQUESTED (t) = 1; + rest_of_type_compilation (t, 1); + } +} void do_type_instantiation (name, storage) tree name, storage; @@ -2578,18 +2616,7 @@ do_type_instantiation (name, storage) } if (! CLASSTYPE_TEMPLATE_SPECIALIZATION (t)) - { - SET_CLASSTYPE_EXPLICIT_INSTANTIATION (t); - SET_CLASSTYPE_INTERFACE_KNOWN (t); - CLASSTYPE_INTERFACE_ONLY (t) = extern_p; - CLASSTYPE_VTABLE_NEEDS_WRITING (t) = ! extern_p; - TYPE_DECL_SUPPRESS_DEBUG (TYPE_NAME (t)) = extern_p; - if (! extern_p) - { - CLASSTYPE_DEBUG_REQUESTED (t) = 1; - rest_of_type_compilation (t, 1); - } - } + mark_class_instantiated (t, extern_p); { tree tmp; @@ -2615,8 +2642,7 @@ do_type_instantiation (name, storage) if (! extern_p) { DECL_INTERFACE_KNOWN (tmp) = 1; - DECL_EXTERNAL (tmp) = 0; - TREE_STATIC (tmp) = 1; + DECL_NOT_REALLY_EXTERN (tmp) = 1; } } diff --git a/gcc/cp/repo.c b/gcc/cp/repo.c new file mode 100644 index 00000000000..78c8dddb20d --- /dev/null +++ b/gcc/cp/repo.c @@ -0,0 +1,278 @@ +/* Code to maintain a C++ template repository. + Copyright (C) 1995 Free Software Foundation, Inc. + Contributed by Jason Merrill (jason@cygnus.com) + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* My strategy here is as follows: + + Everything should be emitted in a translation unit where it is used. + The results of the automatic process should be easily reproducible with + explicit code. + + I'm thinking of compiling with -frepo, running a Perl script to update + files, and then being able to rebuild everything with -fno-implicit. + Full automation can come later. */ + +#include +#include "tree.h" +#include "cp-tree.h" +#include "input.h" + +extern char * rindex (); + +static tree pending_repo; +static char repo_name[1024]; +static FILE *repo_file; + +extern int flag_use_repository; +extern int errorcount, sorrycount; + +static int repo_changed; + +#define IDENTIFIER_REPO_USED(NODE) (TREE_LANG_FLAG_3 (NODE)) +#define IDENTIFIER_REPO_CHOSEN(NODE) (TREE_LANG_FLAG_4 (NODE)) + +/* Record the flags used to compile this translation unit. */ + +void +repo_compile_flags (argc, argv) + int argc; + char **argv; +{ +} + +/* If this template has not been seen before, add a note to the repository + saying where the declaration was. This may be used to find the + definition at link time. */ + +void +repo_template_declared (t) + tree t; +{} + +/* Note where the definition of a template lives so that instantiations can + be generated later. */ + +void +repo_template_defined (t) + tree t; +{} + +/* Note where the definition of a class lives to that template + instantiations can use it. */ + +void +repo_class_defined (t) + tree t; +{} + +/* Note that a template has been used. If we can see the definition, offer + to emit it. */ + +void +repo_template_used (t) + tree t; +{ + tree id; + + if (! flag_use_repository) + return; + + if (TREE_CODE_CLASS (TREE_CODE (t)) == 't') + { + id = DECL_ASSEMBLER_NAME (TYPE_MAIN_DECL (t)); + if (IDENTIFIER_REPO_CHOSEN (id)) + mark_class_instantiated (t, 0); + } + else if (TREE_CODE_CLASS (TREE_CODE (t)) == 'd') + { + id = DECL_ASSEMBLER_NAME (t); + if (IDENTIFIER_REPO_CHOSEN (id)) + mark_function_instantiated (t, 0); + } + else + my_friendly_abort (1); + + if (! IDENTIFIER_REPO_USED (id)) + { + repo_changed = 1; + IDENTIFIER_REPO_USED (id) = 1; + } + pending_repo = perm_tree_cons (NULL_TREE, t, pending_repo); +} + +/* Note that the vtable for a class has been used, and offer to emit it. */ + +void +repo_vtable_used (t) + tree t; +{ + if (! flag_use_repository) + return; + + pending_repo = perm_tree_cons (NULL_TREE, t, pending_repo); +} + +/* Note that an inline with external linkage has been used, and offer to + emit it. */ + +void +repo_inline_used (fn) + tree fn; +{ + if (! flag_use_repository) + return; + + /* Member functions of polymorphic classes go with their vtables. */ + if (DECL_FUNCTION_MEMBER_P (fn) && TYPE_VIRTUAL_P (DECL_CLASS_CONTEXT (fn))) + { + repo_vtable_used (DECL_CLASS_CONTEXT (fn)); + return; + } + + pending_repo = perm_tree_cons (NULL_TREE, fn, pending_repo); +} + +/* Note that a particular typeinfo node has been used, and offer to + emit it. */ + +void +repo_tinfo_used (ti) + tree ti; +{ +} + +static void +open_repo_file (filename) + char *filename; +{ + register char *p, *q; + char *file = filename; + char *s = rindex (file, '/'); + if (s == NULL) + s = file; + else + ++s; + + for (p = repo_name, q = file; q < s; ) + *p++ = *q++; + *p++ = '.'; + strcpy (p, q); + strcat (p, ".repo"); + + repo_file = fopen (repo_name, "r"); +} + +void +init_repo (filename) + char *filename; +{ + char buf[1024]; + + if (! flag_use_repository) + return; + + open_repo_file (filename); + + if (repo_file == 0) + return; + + while (fgets (buf, 1024, repo_file)) + { + int len = strlen (buf) - 1; + if (buf[len] != '\n') + error ("repository info line too long in %s", repo_name); + buf[len] = '\0'; + + switch (buf[0]) + { + case 'A': + case 'M': + break; + case 'C': + case 'O': + { + tree id = get_identifier (&buf[2]); + IDENTIFIER_REPO_USED (id) = 1; + if (buf[0] == 'C') + IDENTIFIER_REPO_CHOSEN (id) = 1; + } + break; + default: + error ("mysterious repository information in %s", repo_name); + } + } +} + +static void +reopen_repo_file_for_write () +{ + if (repo_file) + fclose (repo_file); + repo_file = fopen (repo_name, "w"); + + if (repo_file == 0) + { + error ("man't create repository information file `%s'", repo_name); + flag_use_repository = 0; + } +} + +/* Emit any pending repos. */ + +void +finish_repo () +{ + tree t; + int changed = 0; + + if (! flag_use_repository) + return; + + /* Do we have to write out a new info file? */ + + if (! repo_changed || errorcount || sorrycount) + goto out; + + reopen_repo_file_for_write (); + + if (repo_file == 0) + goto out; + + for (t = pending_repo; t; t = TREE_CHAIN (t)) + { + tree val = TREE_VALUE (t); + char type; + + if (TREE_CODE_CLASS (TREE_CODE (val)) == 't') + val = TYPE_MAIN_DECL (val); + val = DECL_ASSEMBLER_NAME (val); + + if (! IDENTIFIER_REPO_USED (val)) + continue; + IDENTIFIER_REPO_USED (val) = 0; + + type = IDENTIFIER_REPO_CHOSEN (val) ? 'C' : 'O'; + + fprintf (repo_file, "%c %s\n", type, IDENTIFIER_POINTER (val)); + } + + out: + if (repo_file) + fclose (repo_file); +} diff --git a/gcc/cp/search.c b/gcc/cp/search.c index 3e44bd2a3cf..c0f2f2f8771 100644 --- a/gcc/cp/search.c +++ b/gcc/cp/search.c @@ -793,6 +793,10 @@ compute_access (basetype_path, field) } #endif + /* We don't currently support access control on nested types. */ + if (TREE_CODE (field) == TYPE_DECL) + return access_public; + previous_scope = current_scope (); context = DECL_CLASS_CONTEXT (field); diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index ff9bba1c3d2..d83c3cba52e 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -2880,7 +2880,7 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) tree build_type = 0; /* Nonzero means after finally constructing the expression - give it this type. Otherwise, give it type RESULT_TYPE. */ + convert it to this type. */ tree final_type = 0; /* Nonzero if this is an operation like MIN or MAX which can @@ -3155,34 +3155,39 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) else cp_pedwarn ("comparison of distinct pointer types `%T' and `%T' lacks a cast", type0, type1); + + if (result_type == NULL_TREE) + result_type = ptr_type_node; } else if (code0 == POINTER_TYPE && TREE_CODE (op1) == INTEGER_CST && integer_zerop (op1)) - op1 = null_pointer_node; + result_type = type0; else if (code1 == POINTER_TYPE && TREE_CODE (op0) == INTEGER_CST && integer_zerop (op0)) - op0 = null_pointer_node; + result_type = type1; else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE) { + result_type = type0; error ("ANSI C++ forbids comparison between pointer and integer"); - op1 = convert (TREE_TYPE (op0), op1); } else if (code0 == INTEGER_TYPE && code1 == POINTER_TYPE) { + result_type = type1; error ("ANSI C++ forbids comparison between pointer and integer"); - op0 = convert (TREE_TYPE (op1), op0); } else if (TYPE_PTRMEMFUNC_P (type0) && TREE_CODE (op1) == INTEGER_CST && integer_zerop (op1)) { op0 = build_component_ref (op0, index_identifier, 0, 0); op1 = integer_zero_node; + result_type = TREE_TYPE (op0); } else if (TYPE_PTRMEMFUNC_P (type1) && TREE_CODE (op0) == INTEGER_CST && integer_zerop (op0)) { op0 = build_component_ref (op1, index_identifier, 0, 0); op1 = integer_zero_node; + result_type = TREE_TYPE (op0); } else if (TYPE_PTRMEMFUNC_P (type0) && TYPE_PTRMEMFUNC_P (type1) && (TYPE_PTRMEMFUNC_FN_TYPE (type0) @@ -3258,11 +3263,6 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) { return build_binary_op (code, op1, op0, 1); } - - type0 = TREE_TYPE (op0); - type1 = TREE_TYPE (op1); - if (result_type == NULL_TREE) - result_type = type0; break; case MAX_EXPR: @@ -3272,29 +3272,15 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) shorten = 1; else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE) { - if (! comp_target_types (type0, type1, 1)) + if (comp_target_types (type0, type1, 1)) + result_type = common_type (type0, type1); + else { cp_pedwarn ("comparison of distinct pointer types `%T' and `%T' lacks a cast", type0, type1); result_type = ptr_type_node; } -#if 0 - else if ((TYPE_SIZE (TREE_TYPE (type0)) != 0) - != (TYPE_SIZE (TREE_TYPE (type1)) != 0)) - cp_pedwarn ("comparison of %scomplete and %scomplete pointers", - TYPE_SIZE (TREE_TYPE (type0)) == 0 ? "in" : "", - TYPE_SIZE (TREE_TYPE (type1)) == 0 ? "in" : "", - type0, type1); - else if (pedantic - && TREE_CODE (TREE_TYPE (type0)) == FUNCTION_TYPE) - pedwarn ("ANSI C++ forbids ordered comparisons of pointers to functions"); -#endif - else - result_type = common_type (type0, type1); } - - if (result_type == NULL_TREE) - result_type = type0; break; case LE_EXPR: @@ -3307,50 +3293,37 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) short_compare = 1; else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE) { - if (! comp_target_types (type0, type1, 1)) - cp_pedwarn ("comparison of distinct pointer types `%T' and `%T' lacks a cast", - type0, type1); -#if 0 - else if ((TYPE_SIZE (TREE_TYPE (type0)) != 0) - != (TYPE_SIZE (TREE_TYPE (type1)) != 0)) - cp_pedwarn ("comparison of %scomplete and %scomplete pointers", - TYPE_SIZE (TREE_TYPE (type0)) == 0 ? "in" : "", - TYPE_SIZE (TREE_TYPE (type1)) == 0 ? "in" : "", - type0, type1); - else if (pedantic - && TREE_CODE (TREE_TYPE (type0)) == FUNCTION_TYPE) - pedwarn ("ANSI C++ forbids ordered comparisons of pointers to functions"); -#endif - else + if (comp_target_types (type0, type1, 1)) result_type = common_type (type0, type1); + else + { + cp_pedwarn ("comparison of distinct pointer types `%T' and `%T' lacks a cast", + type0, type1); + result_type = ptr_type_node; + } } else if (code0 == POINTER_TYPE && TREE_CODE (op1) == INTEGER_CST && integer_zerop (op1)) - op1 = null_pointer_node; + result_type = type0; else if (code1 == POINTER_TYPE && TREE_CODE (op0) == INTEGER_CST && integer_zerop (op0)) - op0 = null_pointer_node; + result_type = type1; else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE) { + result_type = type0; if (pedantic) pedwarn ("ANSI C++ forbids comparison between pointer and integer"); else if (! flag_traditional) warning ("comparison between pointer and integer"); - op1 = convert (TREE_TYPE (op0), op1); } else if (code0 == INTEGER_TYPE && code1 == POINTER_TYPE) { + result_type = type1; if (pedantic) pedwarn ("ANSI C++ forbids comparison between pointer and integer"); else if (! flag_traditional) warning ("comparison between pointer and integer"); - op0 = convert (TREE_TYPE (op1), op0); } - - type0 = TREE_TYPE (op0); - type1 = TREE_TYPE (op1); - if (result_type == NULL_TREE) - result_type = type0; break; } @@ -3496,26 +3469,38 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) int op0_signed = ! TREE_UNSIGNED (TREE_TYPE (orig_op0)); int op1_signed = ! TREE_UNSIGNED (TREE_TYPE (orig_op1)); - tree comp_type = TREE_TYPE (op0); - int unsignedp0, unsignedp1; tree primop0 = get_narrower (op0, &unsignedp0); tree primop1 = get_narrower (op1, &unsignedp1); /* Give warnings for comparisons between signed and unsigned - quantities that may fail. Do not warn if the signed quantity - is an unsuffixed integer literal (or some static constant - expression involving such literals) and it is positive. - Do not warn if the comparison is being done in a signed type, - since the signed type will only be chosen if it can represent - all the values of the unsigned type. */ + quantities that may fail. */ /* Do the checking based on the original operand trees, so that casts will be considered, but default promotions won't be. */ - if (TREE_UNSIGNED (comp_type) - && ((op0_signed && (TREE_CODE (orig_op0) != INTEGER_CST - || tree_int_cst_sgn (orig_op0) == -1)) - || (op1_signed && (TREE_CODE (orig_op1) != INTEGER_CST - || tree_int_cst_sgn (orig_op1) == -1)))) + + /* Do not warn if the comparison is being done in a signed type, + since the signed type will only be chosen if it can represent + all the values of the unsigned type. */ + if (! TREE_UNSIGNED (result_type)) + /* OK */; + /* Do not warn if the signed quantity is an unsuffixed + integer literal (or some static constant expression + involving such literals) and it is non-negative. */ + else if ((op0_signed && TREE_CODE (orig_op0) == INTEGER_CST + && tree_int_cst_sgn (orig_op0) >= 0) + || (op1_signed && TREE_CODE (orig_op1) == INTEGER_CST + && tree_int_cst_sgn (orig_op1) >= 0)) + /* OK */; + /* Do not warn if the comparison is an equality operation, + the unsigned quantity is an integral constant and it does + not use the most significant bit of result_type. */ + else if ((resultcode == EQ_EXPR || resultcode == NE_EXPR) + && ((op0_signed && TREE_CODE (orig_op1) == INTEGER_CST + && int_fits_type_p (orig_op1, signed_type (result_type)) + || (op1_signed && TREE_CODE (orig_op0) == INTEGER_CST + && int_fits_type_p (orig_op0, signed_type (result_type)))))) + /* OK */; + else warning ("comparison between signed and unsigned"); /* Warn if two unsigned values are being compared in a size @@ -3526,8 +3511,8 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) have all bits set that are set in the ~ operand when it is extended. */ - else if (TREE_CODE (primop0) == BIT_NOT_EXPR - ^ TREE_CODE (primop1) == BIT_NOT_EXPR) + if (TREE_CODE (primop0) == BIT_NOT_EXPR + ^ TREE_CODE (primop1) == BIT_NOT_EXPR) { if (TREE_CODE (primop0) == BIT_NOT_EXPR) primop0 = get_narrower (TREE_OPERAND (op0, 0), &unsignedp0); @@ -3556,7 +3541,7 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) } bits = TYPE_PRECISION (TREE_TYPE (primop)); - if (bits < TYPE_PRECISION (comp_type) + if (bits < TYPE_PRECISION (result_type) && bits < HOST_BITS_PER_LONG && unsignedp) { mask = (~ (HOST_WIDE_INT) 0) << bits; @@ -3566,9 +3551,9 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) } else if (unsignedp0 && unsignedp1 && (TYPE_PRECISION (TREE_TYPE (primop0)) - < TYPE_PRECISION (comp_type)) + < TYPE_PRECISION (result_type)) && (TYPE_PRECISION (TREE_TYPE (primop1)) - < TYPE_PRECISION (comp_type))) + < TYPE_PRECISION (result_type))) warning ("comparison of promoted ~unsigned with unsigned"); } } @@ -3582,7 +3567,8 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) if (!result_type) { - binary_op_error (error_code); + cp_error ("invalid operands `%T' and `%T' to binary `%O'", + TREE_TYPE (orig_op0), TREE_TYPE (orig_op1), error_code); return error_mark_node; } @@ -4467,7 +4453,7 @@ mark_addressable (exp) be non-zero in the case of processing a default function. The second may be non-zero in the case of a template function. */ x = DECL_MAIN_VARIANT (x); - if ((DECL_INLINE (x) || DECL_PENDING_INLINE_INFO (x)) + if ((DECL_THIS_INLINE (x) || DECL_PENDING_INLINE_INFO (x)) && (DECL_CONTEXT (x) == NULL_TREE || TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (x))) != 't' || ! CLASSTYPE_INTERFACE_ONLY (DECL_CONTEXT (x))))