diff options
author | mrs <mrs@138bc75d-0d04-0410-961f-82ee72b054a4> | 1996-09-30 21:34:04 +0000 |
---|---|---|
committer | mrs <mrs@138bc75d-0d04-0410-961f-82ee72b054a4> | 1996-09-30 21:34:04 +0000 |
commit | 3cc0b4b927b943873f4aa7dea40aad5c448f14ba (patch) | |
tree | 7df90e2fe04ce0e37b684ebb2fa65e27a632aaa8 /gcc/cp | |
parent | 5da6226800b028774529c6e5b1b06b0b04c23c54 (diff) | |
download | gcc-3cc0b4b927b943873f4aa7dea40aad5c448f14ba.tar.gz |
89th Cygnus<->FSF quick merge
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@12883 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 171 | ||||
-rw-r--r-- | gcc/cp/Make-lang.in | 50 | ||||
-rw-r--r-- | gcc/cp/call.c | 19 | ||||
-rw-r--r-- | gcc/cp/class.c | 5 | ||||
-rw-r--r-- | gcc/cp/config-lang.in | 4 | ||||
-rw-r--r-- | gcc/cp/cp-tree.def | 1 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 3 | ||||
-rw-r--r-- | gcc/cp/decl.c | 125 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 29 | ||||
-rw-r--r-- | gcc/cp/error.c | 11 | ||||
-rw-r--r-- | gcc/cp/except.c | 2 | ||||
-rw-r--r-- | gcc/cp/exception.cc | 111 | ||||
-rw-r--r-- | gcc/cp/expr.c | 2 | ||||
-rw-r--r-- | gcc/cp/gxxint.texi | 7 | ||||
-rw-r--r-- | gcc/cp/inc/exception | 42 | ||||
-rw-r--r-- | gcc/cp/inc/new | 38 | ||||
-rw-r--r-- | gcc/cp/inc/new.h | 13 | ||||
-rw-r--r-- | gcc/cp/inc/typeinfo | 71 | ||||
-rw-r--r-- | gcc/cp/init.c | 29 | ||||
-rw-r--r-- | gcc/cp/input.c | 2 | ||||
-rw-r--r-- | gcc/cp/lex.c | 40 | ||||
-rw-r--r-- | gcc/cp/method.c | 6 | ||||
-rw-r--r-- | gcc/cp/new.cc | 6 | ||||
-rw-r--r-- | gcc/cp/parse.y | 83 | ||||
-rw-r--r-- | gcc/cp/pt.c | 77 | ||||
-rw-r--r-- | gcc/cp/rtti.c | 235 | ||||
-rw-r--r-- | gcc/cp/tinfo.cc | 125 | ||||
-rw-r--r-- | gcc/cp/tinfo2.cc | 311 | ||||
-rw-r--r-- | gcc/cp/tree.c | 18 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 57 | ||||
-rw-r--r-- | gcc/cp/typeck2.c | 13 |
31 files changed, 1417 insertions, 289 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 1888c1bec00..7a518d14f36 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,174 @@ +Mon Sep 30 12:58:40 1996 Mike Stump <mrs@cygnus.com> + + * input.c (sub_getch): Handle 8-bit characters in string literals. + +Sun Sep 29 03:12:01 1996 Jason Merrill <jason@yorick.cygnus.com> + + * tree.c (mapcar): Handle CONSTRUCTORs. + (copy_to_permanent): Handle expression_obstack properly. + + * Make-lang.in (cplib2.txt): Also depend on the headers. + + * rtti.c (get_tinfo_var): Don't assume that POINTER_SIZE == + INT_TYPE_SIZE. + (expand_class_desc): Use USItype for offset field. + * tinfo.h (struct __class_type_info): Likewise. + + * method.c (build_overload_int): TYPE_PRECISION should be applied + to types. + +Sat Sep 28 14:44:50 1996 Jason Merrill <jason@yorick.cygnus.com> + + * call.c (build_new_op): A COND_EXPR involving void must be a + builtin. + +Fri Sep 27 16:40:30 1996 Jason Merrill <jason@yorick.cygnus.com> + + * typeck.c (build_x_component_ref): New fn. + (build_object_ref): Use it. + * parse.y (primary): Use it. + * decl2.c (build_expr_from_tree): Use it. + * cp-tree.h: Declare it. + + * decl.c (start_decl): variable-sized arrays cannot be initialized. + * error.c (dump_type_suffix): Handle variable arrays. + +Fri Sep 27 13:14:05 1996 Brendan Kehoe <brendan@lisa.cygnus.com> + + * Make-lang.in (exception.o): Put back compiling it with -fPIC. + +Fri Sep 27 03:00:09 1996 Jason Merrill <jason@yorick.cygnus.com> + + * decl.c (lookup_name_real): Don't try to look up anything in a + TYPENAME_TYPE. + + * tinfo2.cc (__throw_type_match_rtti): Oops. + +Thu Sep 26 22:11:05 1996 Brendan Kehoe <brendan@lisa.cygnus.com> + + * Make-lang.in (exception.o): Use -fno-PIC for now. + +Thu Sep 26 10:59:00 1996 Jason Merrill <jason@yorick.cygnus.com> + + * rtti.c (build_dynamic_cast): Pass tinfo fns rather than + calling them. + (get_tinfo_fn_dynamic): Extracted from build_typeid. + * tinfo2.cc (__dynamic_cast): Adjust. + + * rtti.c (build_typeid): Use resolves_to_fixed_type_p. + (build_x_typeid): Likewise. + + * parse.y: Call build_x_typeid instead of build_typeid. + * cp-tree.def: Add TYPEID_EXPR. + * pt.c (tsubst_copy): Handle typeid. + * decl2.c (build_expr_from_tree): Likewise. + * rtti.c (build_x_typeid): Throw bad_typeid from here. + (build_typeid): Not here. + * cp-tree.h: Declare build_x_typeid. + +Wed Sep 25 17:26:16 1996 Jason Merrill <jason@yorick.cygnus.com> + + * call.c (convert_like): Pull out constant values. + + * tree.c (mapcar): Use build_cplus_array_type, not build_array_type. + +Wed Sep 25 17:28:53 1996 Michael Meissner <meissner@tiktok.cygnus.com> + + * decl.c (init_decl_processing): Create short int types before + creating size_t in case a machine description needs to use + unsigned short for size_t. + +Tue Sep 24 18:18:44 1996 Jason Merrill <jason@yorick.cygnus.com> + + * Make-lang.in (exception.o): Turn off pic. + + * tinfo2.cc (__throw_type_match_rtti): Fix cv-variants of the same + type, multi-level ptr conversions. + + * rtti.c (call_void_fn): Renamed and genericized from throw_bad_cast. + (throw_bad_cast): Use it. + (throw_bad_typeid): New fn. + (build_typeid): Throw bad_typeid as needed. + Use build_call. + (synthesize_tinfo_fn): Handle functions and arrays before checking + for cv-quals. + + * Remove .h from standard C++ headers, add new.h, move into inc + subdirectory. + + * exception*: Remove pointer from object, constructors. Add + default exception::what that uses type_info::name. Add + __throw_bad_typeid. + + * init.c (build_new): Don't add a cookie to new (void *) T[2]. + +Mon Sep 23 15:21:53 1996 Jason Merrill <jason@yorick.cygnus.com> + + * Make-lang.in: Building C++ code depends on cc1plus. + +Mon Sep 23 12:38:40 1996 Brendan Kehoe <brendan@lisa.cygnus.com> + + * decl.c (struct saved_scope): Declare PROCESSING_TEMPLATE_DECL as + a HOST_WIDE_INT, not a tree. + +Mon Sep 23 12:36:02 1996 Jason Merrill <jason@yorick.cygnus.com> + + * exception.cc: Don't include <stdlib.h>. + + * Make-lang.in (c++.clean): Remove cplib2.*. + +Mon Sep 23 09:42:19 1996 Doug Evans <dje@canuck.cygnus.com> + + * parse.y (component_decl_1, component_costructor_declarator case): + Pass attributes/prefix_attributes in tree list. + +Mon Sep 23 01:18:50 1996 Jason Merrill <jason@yorick.cygnus.com> + + * tinfo{,2}.cc: #include <stddef.h> instead of <stdlib.h>. + +Sun Sep 22 05:31:22 1996 Jason Merrill <jason@yorick.cygnus.com> + + * lex.c (do_identifier): Don't do deferred lookup in a template + header. + + * typeck2.c (store_init_value): Oops. + + * new.{h,cc}, exception.{h,cc}, typeinfo.h, tinfo{2.cc,.cc,.h}: + New files for C++ lang-support library. + * Make-lang.in (CXX_EXTRA_HEADERS): Define. + (CXX_LIB2FUNCS): Define. + And rules for building the C++ lang-support code. + * config-lang.in (headers): Define. + (lib2funcs): Define. + +Sat Sep 21 19:17:28 1996 Jason Merrill <jason@yorick.cygnus.com> + + * decl2.c (build_expr_from_tree): If CONSTRUCTOR has a type, call + digest_init. + * pt.c (tsubst_copy): Compute type for CONSTRUCTOR. + * typeck2.c (store_init_value): Check for initializing pmf with { } + here. + (process_init_constructor): Not here. + +Thu Sep 19 16:41:07 1996 Jason Merrill <jason@yorick.cygnus.com> + + * pt.c (begin_template_parm_list): Increment + processing_template_decl here. + (end_template_parm_list): Not here. + (process_template_parm): No need to add 1 to it now. + * *.c: Use processing_template_decl instead of current_template_parms + to check for being in a template. + + * pt.c (uses_template_parms): Handle SCOPE_REF. Fix CONSTRUCTOR. + (tsubst_copy): Handle CONSTRUCTOR. + (instantiate_decl): Set up context properly for variables. + * decl2.c (build_expr_from_tree): Handle CONSTRUCTOR. + * class.c (finish_struct): Reverse CLASSTYPE_TAGS. + +Wed Sep 18 13:30:20 1996 Brendan Kehoe <brendan@lisa.cygnus.com> + + * lex.c (enum tree_node_kind) [GATHER_STATISTICS]: Put the enum back. + Wed Sep 18 04:24:07 1996 Jason Merrill <jason@yorick.cygnus.com> * method.c (make_thunk): Call comdat_linkage before setting the diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in index c6a227bbebb..f7265c96124 100644 --- a/gcc/cp/Make-lang.in +++ b/gcc/cp/Make-lang.in @@ -52,6 +52,15 @@ GXX_CROSS_NAME = `t='$(program_transform_cross_name)'; echo g++ | sed $$t` # The name to use for the demangler program. DEMANGLER_PROG = c++filt + +# Extra headers to install. +CXX_EXTRA_HEADERS = $(srcdir)/cp/inc/typeinfo $(srcdir)/cp/inc/exception \ + $(srcdir)/cp/inc/new $(srcdir)/cp/inc/new.h + +# Extra code to include in libgcc2. +CXX_LIB2FUNCS = tinfo.o tinfo2.o new.o exception.o +CXX_LIB2SRCS = $(srcdir)/cp/new.cc $(srcdir)/cp/exception.cc \ + $(srcdir)/cp/tinfo.cc $(srcdir)/cp/tinfo2.cc $(srcdir)/cp/tinfo.h # Define the names for selecting c++ in LANGUAGES. # Note that it would be nice to move the dependency on g++ @@ -105,6 +114,46 @@ c++.rest.encap: $(DEMANGLER_PROG) c++.info: c++.dvi: + +# C++ language-support library pieces for libgcc. +tinfo.o: cc1plus $(srcdir)/cp/tinfo.cc + $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \ + -c $(srcdir)/cp/tinfo.cc +tinfo2.o: cc1plus $(srcdir)/cp/tinfo2.cc + $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \ + -c $(srcdir)/cp/tinfo2.cc +exception.o: cc1plus $(srcdir)/cp/exception.cc + $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \ + -c -O0 -fexceptions $(srcdir)/cp/exception.cc +new.o: cc1plus $(srcdir)/cp/new.cc + $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \ + -c $(srcdir)/cp/new.cc + +# We want to update cplib2.txt if any of the source files change... +cplib2.txt: $(CXX_LIB2SRCS) $(CXX_EXTRA_HEADERS) cplib2.ready + if [ -f cc1plus ]; then \ + echo $(CXX_LIB2FUNCS) > cplib2.new; \ + else \ + echo "" > cplib2.new; \ + fi + mv -f cplib2.new cplib2.txt + +# Or if it would be different. +cplib2.ready: $(GCC_PASSES) $(LIBGCC2_DEPS) stmp-int-hdrs + @if [ -r cplib2.txt ]; then \ + if [ -f cc1plus ]; then \ + echo $(CXX_LIB2FUNCS) > cplib2.new; \ + else \ + echo "" > cplib2.new; \ + fi; \ + if cmp -s cplib2.new cplib2.txt; then \ + touch cplib2.ready; \ + fi; \ + rm -f cplib2.new; \ + fi + @if [ -f cplib2.ready ]; then true; else \ + touch cplib2.ready; \ + fi # Install hooks: # cc1plus is installed elsewhere as part of $(COMPILERS). @@ -165,6 +214,7 @@ c++.uninstall: c++.mostlyclean: -rm -f cp/*$(objext) $(DEMANGLER_PROG) c++.clean: + -rm -f cplib2.txt cplib2.ready c++.distclean: -rm -f cp/config.status cp/Makefile -rm -f cp/parse.output diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 0b749f68fb3..9ae201c9313 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -1410,7 +1410,7 @@ build_scoped_method_call (exp, basetype, name, parms) || basetype == error_mark_node) return error_mark_node; - if (current_template_parms) + if (processing_template_decl) { if (TREE_CODE (name) == BIT_NOT_EXPR) { @@ -1681,7 +1681,7 @@ build_method_call (instance, name, parms, basetype_path, flags) || (instance != NULL_TREE && TREE_TYPE (instance) == error_mark_node)) return error_mark_node; - if (current_template_parms) + if (processing_template_decl) { if (TREE_CODE (name) == BIT_NOT_EXPR) { @@ -4545,9 +4545,16 @@ build_new_op (code, flags, arg1, arg2, arg3) if (arg3 && TREE_CODE (arg3) == OFFSET_REF) arg3 = resolve_offset_ref (arg3); - if (! IS_OVERLOAD_TYPE (TREE_TYPE (arg1)) - && (! arg2 || ! IS_OVERLOAD_TYPE (TREE_TYPE (arg2))) - && (! arg3 || ! IS_OVERLOAD_TYPE (TREE_TYPE (arg3)))) + if (code == COND_EXPR) + { + if (TREE_CODE (TREE_TYPE (arg2)) == VOID_TYPE + || TREE_CODE (TREE_TYPE (arg3)) == VOID_TYPE + || (! IS_OVERLOAD_TYPE (TREE_TYPE (arg2)) + && ! IS_OVERLOAD_TYPE (TREE_TYPE (arg3)))) + goto builtin; + } + else if (! IS_OVERLOAD_TYPE (TREE_TYPE (arg1)) + && (! arg2 || ! IS_OVERLOAD_TYPE (TREE_TYPE (arg2)))) goto builtin; if (code == POSTINCREMENT_EXPR || code == POSTDECREMENT_EXPR) @@ -4871,6 +4878,8 @@ convert_like (convs, expr) case IDENTITY_CONV: if (type_unknown_p (expr)) expr = instantiate_type (TREE_TYPE (convs), expr, 1); + if (TREE_READONLY_DECL_P (expr)) + expr = decl_constant_value (expr); return expr; case AMBIG_CONV: /* Call build_user_type_conversion again for the error. */ diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 676b1363326..424c10cb87d 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -4341,7 +4341,10 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon) defined for this type. */ if (CLASSTYPE_TAGS (t) || dummy) { - x = CLASSTYPE_TAGS (t); + /* The list of tags was built up in pushtag in reverse order; we need + to fix that so that enumerators will be processed in forward order + in template instantiation. */ + CLASSTYPE_TAGS (t) = x = nreverse (CLASSTYPE_TAGS (t)); while (x) { tree tag = TYPE_NAME (TREE_VALUE (x)); diff --git a/gcc/cp/config-lang.in b/gcc/cp/config-lang.in index 7a9a5c558c7..66fe112519e 100644 --- a/gcc/cp/config-lang.in +++ b/gcc/cp/config-lang.in @@ -33,3 +33,7 @@ compilers="cc1plus\$(exeext)" stagestuff="g++\$(exeext) g++-cross\$(exeext) cc1plus\$(exeext)" diff_excludes="-x cp/parse.c -x cp/parse.h" + +headers='$(CXX_EXTRA_HEADERS)' + +lib2funcs=cplib2.txt diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def index de30bda436b..ab271ea63fd 100644 --- a/gcc/cp/cp-tree.def +++ b/gcc/cp/cp-tree.def @@ -120,6 +120,7 @@ DEFTREECODE (DYNAMIC_CAST_EXPR, "dynamic_cast_expr", "1", 1) DEFTREECODE (SIZEOF_EXPR, "sizeof_expr", "1", 1) DEFTREECODE (ARROW_EXPR, "arrow_expr", "e", 1) DEFTREECODE (DOTSTAR_EXPR, "dotstar_expr", "e", 2) +DEFTREECODE (TYPEID_EXPR, "typeid_expr", "e", 1) DEFTREECODE (EXPR_STMT, "expr_stmt", "e", 1) DEFTREECODE (COMPOUND_STMT, "compound_stmt", "e", 1) diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 12552ec3180..0d5189f2139 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -2169,7 +2169,9 @@ extern void finish_repo PROTO((void)); /* in rtti.c */ extern tree get_tinfo_fn PROTO((tree)); +extern tree get_tinfo_fn_dynamic PROTO((tree)); extern tree build_typeid PROTO((tree)); +extern tree build_x_typeid PROTO((tree)); extern tree get_typeid PROTO((tree)); extern tree build_dynamic_cast PROTO((tree, tree)); @@ -2454,6 +2456,7 @@ extern tree default_conversion PROTO((tree)); extern tree build_object_ref PROTO((tree, tree, tree)); extern tree build_component_ref_1 PROTO((tree, tree, int)); extern tree build_component_ref PROTO((tree, tree, tree, int)); +extern tree build_x_component_ref PROTO((tree, tree, tree, int)); extern tree build_x_indirect_ref PROTO((tree, char *)); extern tree build_indirect_ref PROTO((tree, char *)); extern tree build_x_array_ref PROTO((tree, tree)); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 01af1a56a86..245d521cf64 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -1773,6 +1773,7 @@ struct saved_scope { int minimal_parse_mode; tree last_function_parms; tree template_parms; + HOST_WIDE_INT processing_template_decl; tree previous_class_type, previous_class_values; }; static struct saved_scope *current_saved_scope; @@ -1869,6 +1870,7 @@ maybe_push_to_top_level (pseudo) s->minimal_parse_mode = minimal_parse_mode; s->last_function_parms = last_function_parms; s->template_parms = current_template_parms; + s->processing_template_decl = processing_template_decl; s->previous_class_type = previous_class_type; s->previous_class_values = previous_class_values; @@ -1884,7 +1886,10 @@ maybe_push_to_top_level (pseudo) minimal_parse_mode = 0; previous_class_type = previous_class_values = NULL_TREE; if (!pseudo) - current_template_parms = NULL_TREE; + { + current_template_parms = NULL_TREE; + processing_template_decl = 0; + } s->prev = current_saved_scope; s->old_bindings = old_bindings; @@ -1943,6 +1948,7 @@ pop_from_top_level () minimal_parse_mode = s->minimal_parse_mode; last_function_parms = s->last_function_parms; current_template_parms = s->template_parms; + processing_template_decl = s->processing_template_decl; previous_class_type = s->previous_class_type; previous_class_values = s->previous_class_values; @@ -2078,7 +2084,7 @@ pushtag (name, type, globalize) TYPE_NAME (type) = d; DECL_CONTEXT (d) = context; - if (! globalize && current_template_parms && IS_AGGR_TYPE (type)) + if (! globalize && processing_template_decl && IS_AGGR_TYPE (type)) push_template_decl (d); /* If it is anonymous, then we are called from pushdecl, @@ -2110,7 +2116,7 @@ pushtag (name, type, globalize) TYPE_MAIN_DECL (type) = d; DECL_CONTEXT (d) = context; - if (! globalize && current_template_parms && IS_AGGR_TYPE (type)) + if (! globalize && processing_template_decl && IS_AGGR_TYPE (type)) push_template_decl (d); d = pushdecl_class_level (d); @@ -2723,7 +2729,7 @@ duplicate_decls (newdecl, olddecl) /* Lay the type out, unless already done. */ if (oldtype != TREE_TYPE (newdecl) && TREE_TYPE (newdecl) != error_mark_node - && !(current_template_parms && uses_template_parms (newdecl))) + && !(processing_template_decl && uses_template_parms (newdecl))) layout_type (TREE_TYPE (newdecl)); if ((TREE_CODE (newdecl) == VAR_DECL @@ -2731,7 +2737,7 @@ duplicate_decls (newdecl, olddecl) || TREE_CODE (newdecl) == RESULT_DECL || TREE_CODE (newdecl) == FIELD_DECL || TREE_CODE (newdecl) == TYPE_DECL) - && !(current_template_parms && uses_template_parms (newdecl))) + && !(processing_template_decl && uses_template_parms (newdecl))) layout_decl (newdecl, 0); /* Merge the type qualifiers. */ @@ -4312,7 +4318,7 @@ make_typename_type (context, name) else if (TREE_CODE (name) != IDENTIFIER_NODE) my_friendly_abort (2000); - if (! current_template_parms + if (! processing_template_decl || ! uses_template_parms (context) || context == current_class_type) { @@ -4325,11 +4331,11 @@ make_typename_type (context, name) return TREE_TYPE (t); } - if (current_template_parms) + if (processing_template_decl) push_obstacks (&permanent_obstack, &permanent_obstack); t = make_lang_type (TYPENAME_TYPE); d = build_decl (TYPE_DECL, name, t); - if (current_template_parms) + if (processing_template_decl) pop_obstacks (); TYPE_CONTEXT (t) = context; @@ -4389,7 +4395,8 @@ lookup_name_real (name, prefer_type, nonclass) val = lookup_namespace_name (type, name); } else if (! IS_AGGR_TYPE (type) - || TREE_CODE (type) == TEMPLATE_TYPE_PARM) + || TREE_CODE (type) == TEMPLATE_TYPE_PARM + || TREE_CODE (type) == TYPENAME_TYPE) /* Someone else will give an error about this if needed. */ val = NULL_TREE; else if (TYPE_BEING_DEFINED (type)) @@ -4421,7 +4428,7 @@ lookup_name_real (name, prefer_type, nonclass) val = NULL_TREE; #if 1 - if (got_scope && current_template_parms + if (got_scope && processing_template_decl && got_scope != current_class_type && uses_template_parms (got_scope) && val && TREE_CODE (val) == TYPE_DECL @@ -4805,6 +4812,12 @@ init_decl_processing () record_builtin_type (RID_MAX, "long long unsigned", long_long_unsigned_type_node); + short_integer_type_node = make_signed_type (SHORT_TYPE_SIZE); + record_builtin_type (RID_SHORT, "short int", short_integer_type_node); + short_unsigned_type_node = make_unsigned_type (SHORT_TYPE_SIZE); + record_builtin_type (RID_MAX, "short unsigned int", short_unsigned_type_node); + record_builtin_type (RID_MAX, "unsigned short", short_unsigned_type_node); + /* `unsigned long' is the standard type for sizeof. Traditionally, use a signed type. Note that stddef.h uses `unsigned long', @@ -4824,12 +4837,8 @@ init_decl_processing () TREE_TYPE (TYPE_SIZE (long_integer_type_node)) = sizetype; TREE_TYPE (TYPE_SIZE (long_long_integer_type_node)) = sizetype; TREE_TYPE (TYPE_SIZE (long_long_unsigned_type_node)) = sizetype; - - short_integer_type_node = make_signed_type (SHORT_TYPE_SIZE); - record_builtin_type (RID_SHORT, "short int", short_integer_type_node); - short_unsigned_type_node = make_unsigned_type (SHORT_TYPE_SIZE); - record_builtin_type (RID_MAX, "short unsigned int", short_unsigned_type_node); - record_builtin_type (RID_MAX, "unsigned short", short_unsigned_type_node); + TREE_TYPE (TYPE_SIZE (short_integer_type_node)) = sizetype; + TREE_TYPE (TYPE_SIZE (short_unsigned_type_node)) = sizetype; /* Define both `signed char' and `unsigned char'. */ signed_char_type_node = make_signed_type (CHAR_TYPE_SIZE); @@ -5646,7 +5655,7 @@ shadow_tag (declspecs) && TYPE_SIZE (value) == NULL_TREE) { SET_CLASSTYPE_TEMPLATE_SPECIALIZATION (value); - if (current_template_parms) + if (processing_template_decl) push_template_decl (TYPE_MAIN_DECL (value)); } else if (CLASSTYPE_TEMPLATE_INSTANTIATION (value)) @@ -5782,7 +5791,7 @@ start_decl (declarator, declspecs, initialized) type = TREE_TYPE (decl); /* Don't lose if destructors must be executed at file-level. */ - if (! current_template_parms && TREE_STATIC (decl) + if (! processing_template_decl && TREE_STATIC (decl) && TYPE_NEEDS_DESTRUCTOR (complete_type (type)) && !TREE_PERMANENT (decl)) { @@ -5829,11 +5838,23 @@ start_decl (declarator, declspecs, initialized) break; default: - if (TREE_CODE (type) == ARRAY_TYPE && ! current_template_parms - && TYPE_SIZE (complete_type (TREE_TYPE (type))) == NULL_TREE) + if (! processing_template_decl) { - cp_error ("elements of array `%#D' have incomplete type", decl); - initialized = 0; + if (TYPE_SIZE (type) != NULL_TREE + && ! TREE_CONSTANT (TYPE_SIZE (type))) + { + cp_error + ("variable-sized object `%D' may not be initialized", decl); + initialized = 0; + } + + if (TREE_CODE (type) == ARRAY_TYPE + && TYPE_SIZE (complete_type (TREE_TYPE (type))) == NULL_TREE) + { + cp_error + ("elements of array `%#D' have incomplete type", decl); + initialized = 0; + } } } @@ -5901,7 +5922,7 @@ start_decl (declarator, declspecs, initialized) else tem = pushdecl (decl); - if (current_template_parms) + if (processing_template_decl) { if (! current_function_decl) push_template_decl (tem); @@ -5922,7 +5943,7 @@ start_decl (declarator, declspecs, initialized) DECL_COMMON (tem) = flag_conserve_space || ! TREE_PUBLIC (tem); #endif - if (! current_template_parms) + if (! processing_template_decl) start_decl_1 (tem); /* Corresponding pop_obstacks is done in `cp_finish_decl'. */ @@ -5942,7 +5963,7 @@ start_decl (declarator, declspecs, initialized) use temporary storage. Do this even if we will ignore the value. */ if (toplevel_bindings_p () && debug_temp_inits) { - if (current_template_parms + if (processing_template_decl || TYPE_NEEDS_CONSTRUCTING (type) || TREE_CODE (type) == REFERENCE_TYPE) /* In this case, the initializer must lay down in permanent @@ -6002,7 +6023,7 @@ start_decl_1 (decl) && TREE_CODE (decl) != TEMPLATE_DECL && IS_AGGR_TYPE (type) && ! DECL_EXTERNAL (decl)) { - if ((! current_template_parms || ! uses_template_parms (type)) + if ((! processing_template_decl || ! uses_template_parms (type)) && TYPE_SIZE (complete_type (type)) == NULL_TREE) { cp_error ("aggregate `%#D' has incomplete type and cannot be initialized", @@ -6228,7 +6249,7 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags) return; } - if (current_template_parms) + if (processing_template_decl) { if (init && DECL_INITIAL (decl)) DECL_INITIAL (decl) = init; @@ -6796,7 +6817,7 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags) /* If requested, warn about definitions of large data objects. */ if (warn_larger_than - && ! current_template_parms + && ! processing_template_decl && (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL) && !DECL_EXTERNAL (decl)) { @@ -8393,7 +8414,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) /* If this involves a template parameter, it'll be constant, but we don't know what the value is yet. */ - if (current_template_parms) + if (processing_template_decl) { itype = make_node (INTEGER_TYPE); TYPE_MIN_VALUE (itype) = size_zero_node; @@ -9481,7 +9502,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) } if (current_lang_name == lang_name_cplusplus - && ! current_template_parms + && ! processing_template_decl && ! (IDENTIFIER_LENGTH (original_name) == 4 && IDENTIFIER_POINTER (original_name)[0] == 'm' && strcmp (IDENTIFIER_POINTER (original_name), "main") == 0) @@ -9873,7 +9894,7 @@ grokparms (first_parm, funcdef_flag) any_init++; if (TREE_CODE (init) == SAVE_EXPR) PARM_DECL_EXPR (init) = 1; - else if (current_template_parms) + else if (processing_template_decl) ; else if (TREE_CODE (init) == VAR_DECL || TREE_CODE (init) == PARM_DECL) @@ -9893,7 +9914,7 @@ grokparms (first_parm, funcdef_flag) } else init = require_instantiated_type (type, init, integer_zero_node); - if (! current_template_parms + if (! processing_template_decl && ! can_convert_arg (type, TREE_TYPE (init), init)) cp_pedwarn ("invalid type `%T' for default argument to `%#D'", TREE_TYPE (init), decl); @@ -10229,7 +10250,7 @@ grok_op_properties (decl, virtualp, friendp) { if ((name == ansi_opname[(int) POSTINCREMENT_EXPR] || name == ansi_opname[(int) POSTDECREMENT_EXPR]) - && ! current_template_parms + && ! processing_template_decl && TREE_VALUE (TREE_CHAIN (argtypes)) != integer_type_node) { if (methodp) @@ -10688,7 +10709,7 @@ finish_enum (enumtype, values) register tree pair; register tree value = DECL_INITIAL (TREE_VALUE (values)); - if (! current_template_parms) + if (! processing_template_decl) { /* Speed up the main loop by performing some precalculations */ TREE_TYPE (TREE_VALUE (values)) = enumtype; @@ -10700,7 +10721,7 @@ finish_enum (enumtype, values) for (pair = TREE_CHAIN (values); pair; pair = TREE_CHAIN (pair)) { value = DECL_INITIAL (TREE_VALUE (pair)); - if (! current_template_parms) + if (! processing_template_decl) { TREE_TYPE (TREE_VALUE (pair)) = enumtype; TREE_TYPE (value) = enumtype; @@ -10717,7 +10738,7 @@ finish_enum (enumtype, values) TYPE_VALUES (enumtype) = values; - if (current_template_parms) + if (processing_template_decl) return enumtype; { @@ -10786,7 +10807,7 @@ build_enumerator (name, value) if (value) STRIP_TYPE_NOPS (value); - if (! current_template_parms) + if (! processing_template_decl) { /* Validate and default VALUE. */ if (value != NULL_TREE) @@ -10807,7 +10828,7 @@ build_enumerator (name, value) } /* Default based on previous value. */ - if (value == NULL_TREE && ! current_template_parms) + if (value == NULL_TREE && ! processing_template_decl) { value = enum_next_value; if (enum_overflow) @@ -10849,7 +10870,7 @@ build_enumerator (name, value) GNU_xref_decl (current_function_decl, decl); } - if (! current_template_parms) + if (! processing_template_decl) { /* Set basis for default for next value. */ enum_next_value = build_binary_op_nodefault (PLUS_EXPR, value, @@ -11059,7 +11080,7 @@ start_function (declspecs, declarator, attrs, pre_parsed_p) announce_function (decl1); - if (! current_template_parms) + if (! processing_template_decl) { if (TYPE_SIZE (complete_type (TREE_TYPE (fntype))) == NULL_TREE) { @@ -11105,7 +11126,7 @@ start_function (declspecs, declarator, attrs, pre_parsed_p) If we already have a decl for this name, and it is a FUNCTION_DECL, use the old decl. */ - if (current_template_parms) + if (processing_template_decl) push_template_decl (decl1); else if (pre_parsed_p == 0) { @@ -11129,7 +11150,7 @@ start_function (declspecs, declarator, attrs, pre_parsed_p) || flag_alt_external_templates)) { if (DECL_THIS_INLINE (decl1) || DECL_TEMPLATE_INSTANTIATION (decl1) - || current_template_parms) + || processing_template_decl) DECL_EXTERNAL (decl1) = (interface_only || (DECL_THIS_INLINE (decl1) && ! flag_implement_inlines)); @@ -11246,7 +11267,7 @@ start_function (declspecs, declarator, attrs, pre_parsed_p) of this function only. Tiemann moved up here from bottom of fn. */ temporary_allocation (); - if (current_template_parms) + if (processing_template_decl) { extern tree last_tree; ++minimal_parse_mode; @@ -11395,7 +11416,7 @@ store_parm_decls () pushdecl (parm); } - if (! current_template_parms + if (! processing_template_decl && (cleanup = maybe_build_cleanup (parm), cleanup)) { expand_decl (parm); @@ -11433,7 +11454,7 @@ store_parm_decls () /* Initialize the RTL code for the function. */ DECL_SAVED_INSNS (fndecl) = NULL_RTX; - if (! current_template_parms) + if (! processing_template_decl) expand_function_start (fndecl, parms_have_cleanups); /* Create a binding contour which can be used to catch @@ -11458,7 +11479,7 @@ store_parm_decls () } /* Take care of exception handling things. */ - if (! current_template_parms && flag_exceptions) + if (! processing_template_decl && flag_exceptions) { rtx insns; start_sequence (); @@ -11589,7 +11610,7 @@ finish_function (lineno, call_poplevel, nested) store_parm_decls (); } - if (current_template_parms) + if (processing_template_decl) { if (DECL_CONSTRUCTOR_P (fndecl) && call_poplevel) { @@ -12017,7 +12038,7 @@ finish_function (lineno, call_poplevel, nested) to the FUNCTION_DECL node itself. */ BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl; - if (! current_template_parms) + if (! processing_template_decl) { /* So we can tell if jump_optimize sets it to 1. */ can_reach_end = 0; @@ -12070,7 +12091,7 @@ finish_function (lineno, call_poplevel, nested) /* Free all the tree nodes making up this function. */ /* Switch back to allocating nodes permanently until we start another function. */ - if (current_template_parms) + if (processing_template_decl) { --minimal_parse_mode; DECL_SAVED_TREE (fndecl) = TREE_CHAIN (DECL_SAVED_TREE (fndecl)); @@ -12086,7 +12107,7 @@ finish_function (lineno, call_poplevel, nested) was an actual function definition. */ DECL_INITIAL (fndecl) = error_mark_node; /* And we need the arguments for template instantiation. */ - if (! current_template_parms) + if (! processing_template_decl) { if (! DECL_CONSTRUCTOR_P (fndecl) || !(TYPE_USES_VIRTUAL_BASECLASSES @@ -12178,7 +12199,7 @@ start_method (declspecs, declarator) if (flag_default_inline) DECL_INLINE (fndecl) = 1; - if (current_template_parms && ! current_function_decl) + if (processing_template_decl && ! current_function_decl) push_template_decl (fndecl); /* We read in the parameters on the maybepermanent_obstack, @@ -12437,7 +12458,7 @@ cplus_expand_expr_stmt (exp) push_temp_slots (); target_temp_slot_level = temp_slot_level; - if (current_template_parms) + if (processing_template_decl) { add_tree (build_min_nt (EXPR_STMT, exp)); return; diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 39a25729286..2a26a59a8f5 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -1053,7 +1053,7 @@ grok_array_decl (array_expr, index_exp) if (type == error_mark_node || index_exp == error_mark_node) return error_mark_node; - if (current_template_parms) + if (processing_template_decl) return build_min (ARRAY_REF, type ? TREE_TYPE (type) : NULL_TREE, array_expr, index_exp); @@ -1133,7 +1133,7 @@ delete_sanity (exp, size, doing_vec, use_global_delete) if (exp == error_mark_node) return exp; - if (current_template_parms) + if (processing_template_decl) { t = build_min (DELETE_EXPR, void_type_node, exp, size); DELETE_EXPR_USE_GLOBAL (t) = use_global_delete; @@ -1455,7 +1455,7 @@ grokfield (declarator, declspecs, init, asmspec_tree, attrlist) because `decl_const_value' would mis-interpret it as only meaning that this VAR_DECL is defined. */ init = build1 (NOP_EXPR, TREE_TYPE (value), init); - else if (current_template_parms) + else if (processing_template_decl) ; else if (! TREE_CONSTANT (init)) { @@ -1476,7 +1476,7 @@ grokfield (declarator, declspecs, init, asmspec_tree, attrlist) /* The corresponding pop_obstacks is in cp_finish_decl. */ push_obstacks_nochange (); - if (current_template_parms && ! current_function_decl + if (processing_template_decl && ! current_function_decl && (TREE_CODE (value) == VAR_DECL || TREE_CODE (value) == FUNCTION_DECL)) push_template_decl (value); @@ -1500,7 +1500,7 @@ grokfield (declarator, declspecs, init, asmspec_tree, attrlist) DECL_ASSEMBLER_NAME (value) = build_static_name (current_class_type, DECL_NAME (value)); } - if (! current_template_parms) + if (! processing_template_decl) pending_statics = perm_tree_cons (NULL_TREE, value, pending_statics); /* Static consts need not be initialized in the class definition. */ @@ -1839,7 +1839,7 @@ setup_vtbl_ptr () if (base_init_expr == 0 && DECL_CONSTRUCTOR_P (current_function_decl)) { - if (current_template_parms) + if (processing_template_decl) add_tree (build_min_nt (CTOR_INITIALIZER, current_member_init_list, current_base_init_list)); @@ -3412,13 +3412,26 @@ build_expr_from_tree (t) } case COMPONENT_REF: - return build_component_ref + return build_x_component_ref (build_expr_from_tree (TREE_OPERAND (t, 0)), TREE_OPERAND (t, 1), NULL_TREE, 1); case THROW_EXPR: return build_throw (build_expr_from_tree (TREE_OPERAND (t, 0))); + case CONSTRUCTOR: + { + tree r = build_nt (CONSTRUCTOR, NULL_TREE, + build_expr_from_tree (CONSTRUCTOR_ELTS (t))); + + if (TREE_TYPE (t)) + return digest_init (TREE_TYPE (t), r, 0); + return r; + } + + case TYPEID_EXPR: + return build_x_typeid (build_expr_from_tree (TREE_OPERAND (t, 0))); + default: return t; } @@ -3629,7 +3642,7 @@ mark_used (decl) tree decl; { TREE_USED (decl) = 1; - if (current_template_parms) + if (processing_template_decl) return; assemble_external (decl); /* Is it a synthesized method that needs to be synthesized? */ diff --git a/gcc/cp/error.c b/gcc/cp/error.c index 755b54b8bd5..80eb8e9c33c 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -487,7 +487,16 @@ dump_type_suffix (t, v) case ARRAY_TYPE: OB_PUTC ('['); if (TYPE_DOMAIN (t)) - OB_PUTI (TREE_INT_CST_LOW (TYPE_MAX_VALUE (TYPE_DOMAIN (t))) + 1); + { + if (TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (t))) == INTEGER_CST) + OB_PUTI (TREE_INT_CST_LOW (TYPE_MAX_VALUE (TYPE_DOMAIN (t))) + 1); + else if (TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (t))) == MINUS_EXPR) + dump_expr (TREE_OPERAND (TYPE_MAX_VALUE (TYPE_DOMAIN (t)), 0), 0); + else + dump_expr (fold (build_binary_op + (PLUS_EXPR, TYPE_MAX_VALUE (TYPE_DOMAIN (t)), + integer_one_node, 1)), 0); + } OB_PUTC (']'); dump_type_suffix (TREE_TYPE (t), v); break; diff --git a/gcc/cp/except.c b/gcc/cp/except.c index 2863e21645a..fefcd021f6b 100644 --- a/gcc/cp/except.c +++ b/gcc/cp/except.c @@ -1132,7 +1132,7 @@ build_throw (e) { if (e != error_mark_node) { - if (current_template_parms) + if (processing_template_decl) return build_min (THROW_EXPR, void_type_node, e); e = build1 (THROW_EXPR, void_type_node, e); TREE_SIDE_EFFECTS (e) = 1; diff --git a/gcc/cp/exception.cc b/gcc/cp/exception.cc new file mode 100644 index 00000000000..8cf227a719a --- /dev/null +++ b/gcc/cp/exception.cc @@ -0,0 +1,111 @@ +// Functions for Exception Support for -*- C++ -*- +// Copyright (C) 1994, 1995, 1996 Free Software Foundation + +// 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, 59 Temple Place - Suite 330, +// Boston, MA 02111-1307, USA. + +// As a special exception, if you link this library with other files, +// some of which are compiled with GCC, to produce an executable, +// this library does not by itself cause the resulting executable +// to be covered by the GNU General Public License. +// This exception does not however invalidate any other reasons why +// the executable file might be covered by the GNU General Public License. + +#pragma implementation "exception" + +#include "typeinfo" +#include "exception" + +/* terminate (), unexpected (), set_terminate (), set_unexpected () as + well as the default terminate func and default unexpected func */ + +void +__default_terminate () +{ + abort (); +} + +void +__default_unexpected () +{ + __default_terminate (); +} + +static terminate_handler __terminate_func = __default_terminate; +static unexpected_handler __unexpected_func = __default_unexpected; + +terminate_handler +set_terminate (terminate_handler func) +{ + terminate_handler old = __terminate_func; + + __terminate_func = func; + return old; +} + +unexpected_handler +set_unexpected (unexpected_handler func) +{ + unexpected_handler old = __unexpected_func; + + __unexpected_func = func; + return old; +} + +void +terminate () +{ + __terminate_func (); +} + +void +unexpected () +{ + __unexpected_func (); +} + +extern "C" void +__throw_bad_cast (void) +{ + throw bad_cast (); +} + +extern "C" void +__throw_bad_typeid (void) +{ + throw bad_typeid (); +} + +extern "C" void +__throw_bad_exception (void) +{ + throw bad_exception (); +} + +bool +uncaught_exception () +{ + extern void *__eh_type; + extern bool __eh_in_catch; + return __eh_type && ! __eh_in_catch; +} + +const char * exception:: +what () const +{ + return typeid (*this).name (); +} diff --git a/gcc/cp/expr.c b/gcc/cp/expr.c index 7e8673b50a3..506d64c7284 100644 --- a/gcc/cp/expr.c +++ b/gcc/cp/expr.c @@ -373,7 +373,7 @@ do_case (start, end) if (end && pedantic) pedwarn ("ANSI C++ forbids range expressions in switch statement"); - if (current_template_parms) + if (processing_template_decl) { add_tree (build_min_nt (CASE_LABEL, start, end)); return; diff --git a/gcc/cp/gxxint.texi b/gcc/cp/gxxint.texi index be3d89659e3..dbfc2346883 100644 --- a/gcc/cp/gxxint.texi +++ b/gcc/cp/gxxint.texi @@ -1176,10 +1176,9 @@ thrown is used instead. All code that originates exceptions, even code that throws exceptions as a side effect, like dynamic casting, and all code that catches exceptions must be compiled with either -frtti, or -fno-rtti. It is not possible to mix rtti base exception handling -objects with code that doesn't use rtti. Also, -frtti can alter the -binary layout of classes, so mixing -frtti code and -fno-rtti code can -be dangerous. The exceptions to this, are code that doesn't catch or -throw exceptions, catch (...), and code that just rethrows an exception. +objects with code that doesn't use rtti. The exceptions to this, are +code that doesn't catch or throw exceptions, catch (...), and code that +just rethrows an exception. Currently we use the normal mangling used in building functions names (int's are "i", const char * is PCc) to build the non-rtti base type diff --git a/gcc/cp/inc/exception b/gcc/cp/inc/exception new file mode 100644 index 00000000000..d38806b81c4 --- /dev/null +++ b/gcc/cp/inc/exception @@ -0,0 +1,42 @@ +// Exception Handling support header for -*- C++ -*- +// Copyright (C) 1995, 1996 Free Software Foundation + +#ifndef __EXCEPTION__ +#define __EXCEPTION__ + +#pragma interface "exception" + +extern "C++" { + +#if 0 +namespace std { +#endif + +class exception { +public: + exception () { } + virtual ~exception () { } + virtual const char* what () const; +}; + +class bad_exception : public exception { +public: + bad_exception () { } + virtual ~bad_exception () { } +}; + +typedef void (*terminate_handler) (); +typedef void (*unexpected_handler) (); + +terminate_handler set_terminate (terminate_handler); +void terminate (void); +unexpected_handler set_unexpected (unexpected_handler); +void unexpected (void); +bool uncaught_exception (); +} // extern "C++" + +#if 0 +} // namespace std +#endif + +#endif diff --git a/gcc/cp/inc/new b/gcc/cp/inc/new new file mode 100644 index 00000000000..4bfb960c851 --- /dev/null +++ b/gcc/cp/inc/new @@ -0,0 +1,38 @@ +// The -*- C++ -*- dynamic memory management header. +// Copyright (C) 1994, 1996 Free Software Foundation + +#ifndef __NEW__ +#define __NEW__ + +#pragma interface "new" +#include <stddef.h> + +extern "C++" { + +#if 0 +namespace std { +#endif + +typedef void (*new_handler)(); +extern "C" new_handler set_new_handler (new_handler); + +#if 0 +} // namespace std +#endif + +// G++ implementation internals +extern new_handler __new_handler; +extern "C" void __default_new_handler (void); + +// replaceable signatures +void *operator new (size_t); +void *operator new[] (size_t); +void operator delete (void *); +void operator delete[] (void *); + +// default placement versions of operator new +inline void *operator new(size_t, void *place) { return place; } +inline void *operator new[](size_t, void *place) { return place; } +} // extern "C++" + +#endif diff --git a/gcc/cp/inc/new.h b/gcc/cp/inc/new.h new file mode 100644 index 00000000000..eed0910b668 --- /dev/null +++ b/gcc/cp/inc/new.h @@ -0,0 +1,13 @@ +// -*- C++ -*- forwarding header. + +#ifndef __NEW_H__ +#define __NEW_H__ + +#include <new> + +#if 0 +using std::new_handler; +using std::set_new_handler; +#endif + +#endif // __NEW_H__ diff --git a/gcc/cp/inc/typeinfo b/gcc/cp/inc/typeinfo new file mode 100644 index 00000000000..bad3b66a8d1 --- /dev/null +++ b/gcc/cp/inc/typeinfo @@ -0,0 +1,71 @@ +// RTTI support for -*- C++ -*- +// Copyright (C) 1994, 1995, 1996 Free Software Foundation + +#ifndef __TYPEINFO__ +#define __TYPEINFO__ + +#include <exception> + +extern "C++" { + +#if 0 +namespace std { +#endif + +class type_info { +private: + // assigning type_info is not supported. made private. + type_info& operator= (const type_info&); + type_info (const type_info&); + +protected: + type_info (const char *n): _name (n) { } + + const char *_name; + +public: + // destructor + virtual ~type_info (); + + bool before (const type_info& arg); + const char* name () const + { return _name; } + bool operator== (const type_info& arg) const; + bool operator!= (const type_info& arg) const; +}; + +// We can't rely on common symbols being shared between translation units +// under Windows. Sigh. + +#ifndef _WIN32 +inline bool type_info:: +operator== (const type_info& arg) const +{ + return &arg == this; +} + +inline bool type_info:: +operator!= (const type_info& arg) const +{ + return &arg != this; +} +#endif + +class bad_cast : public exception { +public: + bad_cast() { } + virtual ~bad_cast() { } +}; + +class bad_typeid : public exception { + public: + bad_typeid () { } + virtual ~bad_typeid () { } +}; + +#if 0 +} // namespace std +#endif + +} // extern "C++" +#endif diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 8ac11e888d6..af629caf051 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -1803,7 +1803,7 @@ build_offset_ref (type, name) tree basebinfo = NULL_TREE; int dtor = 0; - if (current_template_parms) + if (processing_template_decl) return build_min_nt (SCOPE_REF, type, name); /* Handle namespace names fully here. */ @@ -2601,6 +2601,7 @@ build_new (placement, decl, init, use_global_new) tree alloc_expr, alloc_temp; int has_array = 0; enum tree_code code = NEW_EXPR; + int use_cookie; tree pending_sizes = NULL_TREE; @@ -2648,7 +2649,7 @@ build_new (placement, decl, init, use_global_new) { if (this_nelts == NULL_TREE) error ("new of array type fails to specify size"); - else if (current_template_parms) + else if (processing_template_decl) { nelts = this_nelts; absdcl = TREE_OPERAND (absdcl, 0); @@ -2718,7 +2719,7 @@ build_new (placement, decl, init, use_global_new) decl = TYPE_NAME (type); } - if (current_template_parms) + if (processing_template_decl) { tree t; if (has_array) @@ -2801,9 +2802,25 @@ build_new (placement, decl, init, use_global_new) return error_mark_node; } +#if 1 /* Get a little extra space to store a couple of things before the new'ed - array. */ - if (has_array && TYPE_VEC_NEW_USES_COOKIE (true_type)) + array, if this isn't the default placement new. */ + + use_cookie = (has_array && TYPE_VEC_NEW_USES_COOKIE (true_type) + && ! (placement && ! TREE_CHAIN (placement) + && TREE_TYPE (TREE_VALUE (placement)) == ptr_type_node)); +#else + /* Get a little extra space to store a couple of things before the new'ed + array, if this is either non-placement new or new (nothrow). */ + + use_cookie = (has_array && TYPE_VEC_NEW_USES_COOKIE (true_type) + && (! placement + || (IS_AGGR_TYPE (TREE_TYPE (placement)) + && (TYPE_IDENTIFIER (TREE_TYPE (placement)) + == get_identifier ("nothrow_t"))))); +#endif + + if (use_cookie) { tree extra = BI_header_size; @@ -2857,7 +2874,7 @@ build_new (placement, decl, init, use_global_new) sure we have some extra bytes in that case for the BI_header_size cookies? And how does that interact with the code below? (mrs) */ /* Finish up some magic for new'ed arrays */ - if (has_array && TYPE_VEC_NEW_USES_COOKIE (true_type) && rval != NULL_TREE) + if (use_cookie && rval != NULL_TREE) { tree extra = BI_header_size; tree cookie, exp1; diff --git a/gcc/cp/input.c b/gcc/cp/input.c index 364b8e21813..e142bf4f99d 100644 --- a/gcc/cp/input.c +++ b/gcc/cp/input.c @@ -163,7 +163,7 @@ sub_getch () return getch (); } if (input) - return input->str[input->offset++]; + return (unsigned char)input->str[input->offset++]; } return getc (finput); } diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c index f5701f45450..f91d939b2d9 100644 --- a/gcc/cp/lex.c +++ b/gcc/cp/lex.c @@ -2654,7 +2654,7 @@ do_identifier (token, parsing) cp_error ("enum `%D' is private", id); /* protected is OK, since it's an enum of `this'. */ } - if (! current_template_parms + if (! processing_template_decl || (DECL_INITIAL (id) && TREE_CODE (DECL_INITIAL (id)) == TEMPLATE_CONST_PARM)) id = DECL_INITIAL (id); @@ -2691,7 +2691,7 @@ do_scoped_id (token, parsing) yychar = yylex (); if (! id) { - if (current_template_parms) + if (processing_template_decl) { id = build_min_nt (LOOKUP_EXPR, token, NULL_TREE); LOOKUP_EXPR_GLOBAL (id) = 1; @@ -2716,7 +2716,7 @@ do_scoped_id (token, parsing) else if (TREE_CODE (id) != TREE_LIST) mark_used (id); } - if (TREE_CODE (id) == CONST_DECL && ! current_template_parms) + if (TREE_CODE (id) == CONST_DECL && ! processing_template_decl) { /* XXX CHS - should we set TREE_USED of the constant? */ id = DECL_INITIAL (id); @@ -2726,7 +2726,7 @@ do_scoped_id (token, parsing) TREE_CONSTANT (id) = 1; } - if (current_template_parms) + if (processing_template_decl) { if (is_overloaded_fn (id)) { @@ -3796,19 +3796,19 @@ real_yylex () len = p - token_buffer - 1; } #endif - if (current_template_parms) + if (processing_template_decl) push_obstacks (&permanent_obstack, &permanent_obstack); yylval.ttype = build_string ((len + 1) * WCHAR_BYTES, widep); - if (current_template_parms) + if (processing_template_decl) pop_obstacks (); TREE_TYPE (yylval.ttype) = wchar_array_type_node; } else { - if (current_template_parms) + if (processing_template_decl) push_obstacks (&permanent_obstack, &permanent_obstack); yylval.ttype = build_string (p - token_buffer, token_buffer + 1); - if (current_template_parms) + if (processing_template_decl) pop_obstacks (); TREE_TYPE (yylval.ttype) = char_array_type_node; } @@ -4027,6 +4027,30 @@ is_rid (t) } #ifdef GATHER_STATISTICS +/* The original for tree_node_kind is in the toplevel tree.c; changes there + need to be brought into here, unless this were actually put into a header + instead. */ +/* Statistics-gathering stuff. */ +typedef enum +{ + d_kind, + t_kind, + b_kind, + s_kind, + r_kind, + e_kind, + c_kind, + id_kind, + op_id_kind, + perm_list_kind, + temp_list_kind, + vec_kind, + x_kind, + lang_decl, + lang_type, + all_kinds +} tree_node_kind; + extern int tree_node_counts[]; extern int tree_node_sizes[]; #endif diff --git a/gcc/cp/method.c b/gcc/cp/method.c index c7c63d7cdd0..b127002b070 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -369,7 +369,7 @@ build_overload_int (value) OB_PUTC ('_'); return; } - else if (current_template_parms + else if (processing_template_decl && TREE_CODE (value) != INTEGER_CST) /* We don't ever want this output, but it's inconvenient not to be able to build the string. This should cause assembler @@ -382,7 +382,7 @@ build_overload_int (value) } my_friendly_assert (TREE_CODE (value) == INTEGER_CST, 243); - if (TYPE_PRECISION (value) == 2 * HOST_BITS_PER_WIDE_INT) + if (TYPE_PRECISION (TREE_TYPE (value)) == 2 * HOST_BITS_PER_WIDE_INT) { if (tree_int_cst_lt (value, integer_zero_node)) { @@ -1656,7 +1656,7 @@ hack_identifier (value, name) return value; } - if (TREE_CODE (type) == REFERENCE_TYPE && ! current_template_parms) + if (TREE_CODE (type) == REFERENCE_TYPE && ! processing_template_decl) value = convert_from_reference (value); return value; } diff --git a/gcc/cp/new.cc b/gcc/cp/new.cc new file mode 100644 index 00000000000..297b395e1db --- /dev/null +++ b/gcc/cp/new.cc @@ -0,0 +1,6 @@ +// Implementation file for the -*- C++ -*- dynamic memory management header. +// Copyright (C) 1996 Free Software Foundation +// This file is part of GNU CC. + +#pragma implementation "new" +#include "new" diff --git a/gcc/cp/parse.y b/gcc/cp/parse.y index c0a2c453deb..774bb047142 100644 --- a/gcc/cp/parse.y +++ b/gcc/cp/parse.y @@ -990,7 +990,7 @@ compstmtend: already_scoped_stmt: '{' { - if (current_template_parms) + if (processing_template_decl) { $<ttype>$ = build_min_nt (COMPOUND_STMT, NULL_TREE); COMPOUND_STMT_NO_SCOPE ($<ttype>$) = 1; @@ -999,7 +999,7 @@ already_scoped_stmt: } compstmtend { - if (current_template_parms) + if (processing_template_decl) { TREE_OPERAND ($<ttype>2, 0) = TREE_CHAIN ($<ttype>2); TREE_CHAIN ($<ttype>2) = NULL_TREE; @@ -1287,10 +1287,10 @@ primary: | boolean.literal | string { - if (current_template_parms) + if (processing_template_decl) push_obstacks (&permanent_obstack, &permanent_obstack); $$ = combine_strings ($$); - if (current_template_parms) + if (processing_template_decl) pop_obstacks (); } | '(' expr ')' @@ -1455,7 +1455,7 @@ primary: check_for_new_type ("const_cast", $3); $$ = build_const_cast (type, $6); } | TYPEID '(' expr ')' - { $$ = build_typeid ($3); } + { $$ = build_x_typeid ($3); } | TYPEID '(' type_id ')' { tree type = groktypename ($3.t); check_for_new_type ("typeid", $3); @@ -1473,20 +1473,20 @@ primary: | overqualified_id %prec HYPERUNARY { $$ = build_offset_ref (OP0 ($$), OP1 ($$)); } | overqualified_id '(' nonnull_exprlist ')' - { if (current_template_parms) + { if (processing_template_decl) $$ = build_min_nt (CALL_EXPR, copy_to_permanent ($1), $3, NULL_TREE); else $$ = build_member_call (OP0 ($$), OP1 ($$), $3); } | overqualified_id LEFT_RIGHT - { if (current_template_parms) + { if (processing_template_decl) $$ = build_min_nt (CALL_EXPR, copy_to_permanent ($1), NULL_TREE, NULL_TREE); else $$ = build_member_call (OP0 ($$), OP1 ($$), NULL_TREE); } | object unqualified_id %prec UNARY - { $$ = build_component_ref ($$, $2, NULL_TREE, 1); } + { $$ = build_x_component_ref ($$, $2, NULL_TREE, 1); } | object overqualified_id %prec UNARY - { if (current_template_parms) + { if (processing_template_decl) $$ = build_min_nt (COMPONENT_REF, $1, copy_to_permanent ($2)); else $$ = build_object_ref ($$, OP0 ($2), OP1 ($2)); } @@ -2294,7 +2294,7 @@ named_class_head: && TYPE_SIZE ($$) == NULL_TREE) { SET_CLASSTYPE_TEMPLATE_SPECIALIZATION ($$); - if (current_template_parms) + if (processing_template_decl) push_template_decl (TYPE_MAIN_DECL ($$)); } else if (CLASSTYPE_TEMPLATE_INSTANTIATION ($$)) @@ -2496,7 +2496,7 @@ left_curly: pushtag (TYPE_IDENTIFIER ($<ttype>0), t, 0); $<ttype>0 = t; } - if (current_template_parms && TYPE_CONTEXT (t) + if (processing_template_decl && TYPE_CONTEXT (t) && ! current_class_type) push_template_decl (TYPE_STUB_DECL (t)); pushclass (t, 0); @@ -2507,7 +2507,7 @@ left_curly: && TYPE_SIZE (t) == NULL_TREE) { SET_CLASSTYPE_TEMPLATE_SPECIALIZATION (t); - if (current_template_parms) + if (processing_template_decl) push_template_decl (TYPE_MAIN_DECL (t)); } else if (CLASSTYPE_TEMPLATE_INSTANTIATION (t)) @@ -2672,7 +2672,8 @@ component_decl_1: $$ = grokfield ($2, specs, $5, $3, build_tree_list ($4, attrs)); } | component_constructor_declarator maybeasm maybe_attribute maybe_init - { $$ = grokfield ($$, NULL_TREE, $4, $2, $3); } + { $$ = grokfield ($$, NULL_TREE, $4, $2, + build_tree_list ($3, NULL_TREE)); } | using_decl { $$ = do_class_using_decl ($1); } ; @@ -3242,7 +3243,7 @@ compstmt_or_error: compstmt: '{' { - if (current_template_parms) + if (processing_template_decl) { $<ttype>$ = build_min_nt (COMPOUND_STMT, NULL_TREE); add_tree ($<ttype>$); @@ -3250,7 +3251,7 @@ compstmt: } .pushlevel compstmtend .poplevel { - if (current_template_parms) + if (processing_template_decl) { TREE_OPERAND ($<ttype>2, 0) = TREE_CHAIN ($<ttype>2); TREE_CHAIN ($<ttype>2) = NULL_TREE; @@ -3263,7 +3264,7 @@ compstmt: simple_if: IF { - if (current_template_parms) + if (processing_template_decl) { $<ttype>$ = build_min_nt (IF_STMT, NULL_TREE, NULL_TREE, NULL_TREE); @@ -3273,7 +3274,7 @@ simple_if: } .pushlevel paren_cond_or_null { - if (current_template_parms) + if (processing_template_decl) { if (last_tree != $<ttype>2) { @@ -3292,7 +3293,7 @@ simple_if: } implicitly_scoped_stmt { - if (current_template_parms) + if (processing_template_decl) { TREE_OPERAND ($<ttype>2, 1) = TREE_CHAIN ($<ttype>2); TREE_CHAIN ($<ttype>2) = NULL_TREE; @@ -3306,7 +3307,7 @@ implicitly_scoped_stmt: { finish_stmt (); } | .pushlevel { - if (current_template_parms) + if (processing_template_decl) { $<ttype>$ = build_min_nt (COMPOUND_STMT, NULL_TREE); add_tree ($<ttype>$); @@ -3314,7 +3315,7 @@ implicitly_scoped_stmt: } simple_stmt .poplevel { - if (current_template_parms) + if (processing_template_decl) { TREE_OPERAND ($<ttype>2, 0) = TREE_CHAIN ($<ttype>2); TREE_CHAIN ($<ttype>2) = NULL_TREE; @@ -3336,7 +3337,7 @@ simple_stmt: | expr ';' { tree expr = $1; - if (! current_template_parms) + if (! processing_template_decl) { emit_line_note (input_filename, lineno); /* Do default conversion if safe and possibly important, @@ -3350,10 +3351,10 @@ simple_stmt: clear_momentary (); finish_stmt (); } | simple_if ELSE - { if (! current_template_parms) expand_start_else (); } + { if (! processing_template_decl) expand_start_else (); } implicitly_scoped_stmt { - if (current_template_parms) + if (processing_template_decl) { TREE_OPERAND ($<ttype>1, 2) = TREE_CHAIN ($<ttype>1); TREE_CHAIN ($<ttype>1) = NULL_TREE; @@ -3365,12 +3366,12 @@ simple_stmt: .poplevel { finish_stmt (); } | simple_if %prec IF - { if (! current_template_parms) expand_end_cond (); + { if (! processing_template_decl) expand_end_cond (); do_poplevel (); finish_stmt (); } | WHILE { - if (current_template_parms) + if (processing_template_decl) { $<ttype>$ = build_min_nt (WHILE_STMT, NULL_TREE, NULL_TREE); add_tree ($<ttype>$); @@ -3385,7 +3386,7 @@ simple_stmt: } .pushlevel paren_cond_or_null { - if (current_template_parms) + if (processing_template_decl) { if (last_tree != $<ttype>2) { @@ -3404,7 +3405,7 @@ simple_stmt: } already_scoped_stmt .poplevel { - if (current_template_parms) + if (processing_template_decl) { TREE_OPERAND ($<ttype>2, 1) = TREE_CHAIN ($<ttype>2); TREE_CHAIN ($<ttype>2) = NULL_TREE; @@ -3416,7 +3417,7 @@ simple_stmt: } | DO { - if (current_template_parms) + if (processing_template_decl) { $<ttype>$ = build_min_nt (DO_STMT, NULL_TREE, NULL_TREE); add_tree ($<ttype>$); @@ -3430,7 +3431,7 @@ simple_stmt: } implicitly_scoped_stmt WHILE { - if (current_template_parms) + if (processing_template_decl) { TREE_OPERAND ($<ttype>2, 0) = TREE_CHAIN ($<ttype>2); TREE_CHAIN ($<ttype>2) = NULL_TREE; @@ -3444,7 +3445,7 @@ simple_stmt: } paren_expr_or_null ';' { - if (current_template_parms) + if (processing_template_decl) TREE_OPERAND ($<ttype>2, 1) = $6; else { @@ -3456,7 +3457,7 @@ simple_stmt: finish_stmt (); } | FOR - { if (current_template_parms) + { if (processing_template_decl) { $<ttype>$ = build_min_nt (FOR_STMT, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE); @@ -3476,7 +3477,7 @@ simple_stmt: } '(' for.init.statement { - if (current_template_parms) + if (processing_template_decl) { if (last_tree != $<ttype>2) { @@ -3494,7 +3495,7 @@ simple_stmt: } .pushlevel xcond ';' { - if (current_template_parms) + if (processing_template_decl) { if (last_tree != $<ttype>2) { @@ -3515,13 +3516,13 @@ simple_stmt: /* Don't let the tree nodes for $10 be discarded by clear_momentary during the parsing of the next stmt. */ { - if (current_template_parms) + if (processing_template_decl) TREE_OPERAND ($<ttype>2, 2) = $10; push_momentary (); } already_scoped_stmt .poplevel { - if (current_template_parms) + if (processing_template_decl) { TREE_OPERAND ($<ttype>2, 3) = TREE_CHAIN ($<ttype>2); TREE_CHAIN ($<ttype>2) = NULL_TREE; @@ -3542,7 +3543,7 @@ simple_stmt: finish_stmt (); } | SWITCH .pushlevel '(' condition ')' { - if (current_template_parms) + if (processing_template_decl) { $<ttype>$ = build_min_nt (SWITCH_STMT, $4, NULL_TREE); add_tree ($<ttype>$); @@ -3559,7 +3560,7 @@ simple_stmt: } implicitly_scoped_stmt { - if (current_template_parms) + if (processing_template_decl) { TREE_OPERAND ($<ttype>6, 1) = TREE_CHAIN ($<ttype>6); TREE_CHAIN ($<ttype>6) = NULL_TREE; @@ -3583,13 +3584,13 @@ simple_stmt: stmt | BREAK ';' { emit_line_note (input_filename, lineno); - if (current_template_parms) + if (processing_template_decl) add_tree (build_min_nt (BREAK_STMT)); else if ( ! expand_exit_something ()) error ("break statement not within loop or switch"); } | CONTINUE ';' { emit_line_note (input_filename, lineno); - if (current_template_parms) + if (processing_template_decl) add_tree (build_min_nt (CONTINUE_STMT)); else if (! expand_continue_loop (0)) error ("continue statement not within a loop"); } @@ -3637,7 +3638,7 @@ simple_stmt: } | GOTO '*' expr ';' { - if (current_template_parms) + if (processing_template_decl) add_tree (build_min_nt (GOTO_STMT, $3)); else { emit_line_note (input_filename, lineno); @@ -3645,7 +3646,7 @@ simple_stmt: } | GOTO identifier ';' { - if (current_template_parms) + if (processing_template_decl) add_tree (build_min_nt (GOTO_STMT, $2)); else { diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index f8161fae649..5b7caf37fbe 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -80,6 +80,7 @@ begin_template_parm_list () { pushlevel (0); declare_pseudo_global_level (); + ++processing_template_decl; } /* Process information from new template parameter NEXT and append it to the @@ -141,7 +142,7 @@ process_template_parm (list, next) decl = build_decl (CONST_DECL, DECL_NAME (parm), TREE_TYPE (parm)); DECL_INITIAL (decl) = tinfo; DECL_INITIAL (parm) = tinfo; - TEMPLATE_CONST_SET_INFO (tinfo, idx, processing_template_decl + 1); + TEMPLATE_CONST_SET_INFO (tinfo, idx, processing_template_decl); } else { @@ -150,7 +151,7 @@ process_template_parm (list, next) decl = build_decl (TYPE_DECL, TREE_VALUE (parm), t); TYPE_MAIN_DECL (t) = decl; parm = decl; - TEMPLATE_TYPE_SET_INFO (t, idx, processing_template_decl + 1); + TEMPLATE_TYPE_SET_INFO (t, idx, processing_template_decl); } SET_DECL_ARTIFICIAL (decl); pushdecl (decl); @@ -171,7 +172,6 @@ end_template_parm_list (parms) tree parm; tree saved_parmlist = make_tree_vec (list_length (parms)); - ++processing_template_decl; current_template_parms = tree_cons (build_int_2 (0, processing_template_decl), saved_parmlist, current_template_parms); @@ -187,7 +187,7 @@ end_template_parm_list (parms) void end_template_decl () { - if (! current_template_parms) + if (! processing_template_decl) return; /* This matches the pushlevel in begin_template_parm_list. */ @@ -404,7 +404,7 @@ coerce_template_parms (parms, arglist, in_decl) if (is_type) { val = groktypename (arg); - if (! current_template_parms) + if (! processing_template_decl) { tree t = target_type (val); if (IS_AGGR_TYPE (t) @@ -419,12 +419,12 @@ coerce_template_parms (parms, arglist, in_decl) { tree t = tsubst (TREE_TYPE (parm), &TREE_VEC_ELT (vec, 0), TREE_VEC_LENGTH (vec), in_decl); - if (current_template_parms) + if (processing_template_decl) val = arg; else val = digest_init (t, arg, (tree *) 0); - if (val == error_mark_node || current_template_parms) + if (val == error_mark_node || processing_template_decl) ; /* 14.2: Other template-arguments must be constant-expressions, @@ -743,10 +743,10 @@ lookup_template_class (d1, arglist, in_decl) if (TYPE_BEING_DEFINED (ctx) && ctx == current_class_type) { - tree save_parms = current_template_parms; - current_template_parms = NULL_TREE; + int save_temp = processing_template_decl; + processing_template_decl = 0; t = xref_tag_from_type (TREE_TYPE (template), id, 0); - current_template_parms = save_parms; + processing_template_decl = save_temp; } else { @@ -910,10 +910,13 @@ uses_template_parms (t) case TYPENAME_TYPE: return 1; + case SCOPE_REF: + return uses_template_parms (TREE_OPERAND (t, 0)); + case CONSTRUCTOR: if (TREE_TYPE (t) && TYPE_PTRMEMFUNC_P (TREE_TYPE (t))) return uses_template_parms (TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (t))); - /* else fall through */ + return uses_template_parms (TREE_OPERAND (t, 1)); default: switch (TREE_CODE_CLASS (TREE_CODE (t))) @@ -1384,7 +1387,7 @@ tsubst (t, args, nargs, in_decl) { tree max = tsubst_expr (TYPE_MAX_VALUE (t), args, nargs, in_decl); - if (current_template_parms) + if (processing_template_decl) { tree itype = make_node (INTEGER_TYPE); TYPE_MIN_VALUE (itype) = size_zero_node; @@ -1986,6 +1989,7 @@ tsubst_copy (t, args, nargs, in_decl) case SIZEOF_EXPR: case ARROW_EXPR: case THROW_EXPR: + case TYPEID_EXPR: return build1 (code, NULL_TREE, tsubst_copy (TREE_OPERAND (t, 0), args, nargs, in_decl)); @@ -2139,6 +2143,11 @@ tsubst_copy (t, args, nargs, in_decl) else return t; + case CONSTRUCTOR: + return build + (CONSTRUCTOR, tsubst (TREE_TYPE (t), args, nargs, in_decl), NULL_TREE, + tsubst_copy (CONSTRUCTOR_ELTS (t), args, nargs, in_decl)); + default: return t; } @@ -2153,7 +2162,7 @@ tsubst_expr (t, args, nargs, in_decl) if (t == NULL_TREE || t == error_mark_node) return t; - if (current_template_parms) + if (processing_template_decl) return tsubst_copy (t, args, nargs, in_decl); switch (TREE_CODE (t)) @@ -3255,6 +3264,8 @@ instantiate_decl (d) int nested = in_function_p (); int d_defined; int pattern_defined; + int line = lineno; + char *file = input_filename; if (TREE_CODE (d) == FUNCTION_DECL) { @@ -3297,9 +3308,19 @@ instantiate_decl (d) variable is a static const initialized in the class body. */ if (TREE_CODE (d) == VAR_DECL && ! DECL_INITIAL (d) && DECL_INITIAL (pattern)) - DECL_INITIAL (d) = tsubst_expr - (DECL_INITIAL (pattern), &TREE_VEC_ELT (args, 0), - TREE_VEC_LENGTH (args), tmpl); + { + lineno = DECL_SOURCE_LINE (d); + input_filename = DECL_SOURCE_FILE (d); + + pushclass (DECL_CONTEXT (d), 2); + DECL_INITIAL (d) = tsubst_expr + (DECL_INITIAL (pattern), &TREE_VEC_ELT (args, 0), + TREE_VEC_LENGTH (args), tmpl); + popclass (1); + + lineno = line; + input_filename = file; + } if (! pattern_defined || (TREE_CODE (d) == FUNCTION_DECL && ! DECL_INLINE (d) @@ -3320,6 +3341,9 @@ instantiate_decl (d) push_to_top_level (); + lineno = DECL_SOURCE_LINE (d); + input_filename = DECL_SOURCE_FILE (d); + /* Trick tsubst into giving us a new decl in case the template changed. */ save_ti = DECL_TEMPLATE_INFO (pattern); DECL_TEMPLATE_INFO (pattern) = NULL_TREE; @@ -3328,9 +3352,13 @@ instantiate_decl (d) /* And set up DECL_INITIAL, since tsubst doesn't. */ if (TREE_CODE (td) == VAR_DECL) - DECL_INITIAL (td) = tsubst_expr - (DECL_INITIAL (pattern), &TREE_VEC_ELT (args, 0), - TREE_VEC_LENGTH (args), tmpl); + { + pushclass (DECL_CONTEXT (d), 2); + DECL_INITIAL (td) = tsubst_expr + (DECL_INITIAL (pattern), &TREE_VEC_ELT (args, 0), + TREE_VEC_LENGTH (args), tmpl); + popclass (1); + } /* Convince duplicate_decls to use the DECL_ARGUMENTS from the new decl. */ if (TREE_CODE (d) == FUNCTION_DECL) @@ -3354,11 +3382,6 @@ instantiate_decl (d) else if (TREE_CODE (d) == FUNCTION_DECL) { tree t = DECL_SAVED_TREE (pattern); - int line = lineno; - char *file = input_filename; - - lineno = DECL_SOURCE_LINE (d); - input_filename = DECL_SOURCE_FILE (d); start_function (NULL_TREE, d, NULL_TREE, 1); store_parm_decls (); @@ -3392,11 +3415,11 @@ instantiate_decl (d) TREE_VEC_LENGTH (args), tmpl); finish_function (lineno, 0, nested); - - lineno = line; - input_filename = file; } + lineno = line; + input_filename = file; + pop_from_top_level (); pop_tinst_level (); diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c index 69513ac9d7a..f51ea644953 100644 --- a/gcc/cp/rtti.c +++ b/gcc/cp/rtti.c @@ -30,6 +30,10 @@ Boston, MA 02111-1307, USA. */ #undef NULL #define NULL 0 +#ifndef INT_TYPE_SIZE +#define INT_TYPE_SIZE BITS_PER_WORD +#endif + extern tree define_function (); extern tree build_t_desc_overload (); extern struct obstack *permanent_obstack; @@ -111,13 +115,59 @@ build_headof (exp) return build (PLUS_EXPR, type, exp, convert (ptrdiff_type_node, offset)); } + +/* Build a call to a generic entry point taking and returning void. */ + +static tree +call_void_fn (name) + char *name; +{ + tree d = get_identifier (name); + tree type; + + if (IDENTIFIER_GLOBAL_VALUE (d)) + d = IDENTIFIER_GLOBAL_VALUE (d); + else + { + push_obstacks (&permanent_obstack, &permanent_obstack); + + type = build_function_type (void_type_node, void_list_node); + d = build_lang_decl (FUNCTION_DECL, d, type); + DECL_EXTERNAL (d) = 1; + TREE_PUBLIC (d) = 1; + DECL_ARTIFICIAL (d) = 1; + pushdecl_top_level (d); + make_function_rtl (d); + assemble_external (d); + + pop_obstacks (); + } + + return build_call (d, void_type_node, NULL_TREE); +} + +/* Get a bad_cast node for the program to throw... + + See libstdc++/exception.cc for __throw_bad_cast */ + +static tree +throw_bad_cast () +{ + return call_void_fn ("__throw_bad_cast"); +} + +static tree +throw_bad_typeid () +{ + return call_void_fn ("__throw_bad_typeid"); +} -/* Return the type_info node associated with the expression EXP. If EXP is - a reference to a polymorphic class, return the dynamic type; otherwise - return the static type of the expression. */ +/* Return the type_info function associated with the expression EXP. If + EXP is a reference to a polymorphic class, return the dynamic type; + otherwise return the static type of the expression. */ tree -build_typeid (exp) +get_tinfo_fn_dynamic (exp) tree exp; { tree type; @@ -127,14 +177,6 @@ build_typeid (exp) type = TREE_TYPE (exp); - /* Strip top-level cv-qualifiers. */ - type = TYPE_MAIN_VARIANT (type); - - /* if b is an instance of B, typeid(b) == typeid(B). Do this before - reference trickiness. */ - if (TREE_CODE (exp) == VAR_DECL && TREE_CODE (type) == RECORD_TYPE) - return get_typeid (type); - /* peel back references, so they match. */ if (TREE_CODE (type) == REFERENCE_TYPE) type = TREE_TYPE (type); @@ -142,12 +184,8 @@ build_typeid (exp) /* Peel off cv qualifiers. */ type = TYPE_MAIN_VARIANT (type); - /* Apply trivial conversion T -> T& for dereferenced ptrs. */ - if (TREE_CODE (type) == RECORD_TYPE) - type = build_reference_type (type); - /* If exp is a reference to polymorphic type, get the real type_info. */ - if (TREE_CODE (type) == REFERENCE_TYPE && TYPE_VIRTUAL_P (TREE_TYPE (type))) + if (TYPE_VIRTUAL_P (type) && ! resolves_to_fixed_type_p (exp, 0)) { /* build reference to type_info from vtable. */ tree t; @@ -156,7 +194,7 @@ build_typeid (exp) warning ("taking dynamic typeid of object without -frtti"); /* If we don't have rtti stuff, get to a sub-object that does. */ - if (!CLASSTYPE_VFIELDS (TREE_TYPE (type))) + if (! CLASSTYPE_VFIELDS (type)) { exp = build_unary_op (ADDR_EXPR, exp, 0); exp = build_headof_sub (exp); @@ -168,14 +206,57 @@ build_typeid (exp) else t = build_vfn_ref ((tree *) 0, exp, integer_zero_node); TREE_TYPE (t) = build_pointer_type (tinfo_fn_type); - - t = build (CALL_EXPR, TREE_TYPE (tinfo_fn_type), t, NULL_TREE, NULL_TREE); - TREE_SIDE_EFFECTS (t) = 1; - return convert_from_reference (t); + return t; } /* otherwise return the type_info for the static type of the expr. */ - return get_typeid (type); + return get_tinfo_fn (TYPE_MAIN_VARIANT (type)); +} + +tree +build_typeid (exp) + tree exp; +{ + exp = get_tinfo_fn_dynamic (exp); + exp = build_call (exp, TREE_TYPE (tinfo_fn_type), NULL_TREE); + return convert_from_reference (exp); +} + +tree +build_x_typeid (exp) + tree exp; +{ + tree cond = NULL_TREE; + tree type = TREE_TYPE (tinfo_fn_type); + int nonnull; + + if (processing_template_decl) + return build_min_nt (TYPEID_EXPR, exp); + + if (TREE_CODE (exp) == INDIRECT_REF + && TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == POINTER_TYPE + && TYPE_VIRTUAL_P (TREE_TYPE (exp)) + && ! resolves_to_fixed_type_p (exp, &nonnull) + && ! nonnull) + { + exp = stabilize_reference (exp); + cond = convert (boolean_type_node, TREE_OPERAND (exp, 0)); + } + + exp = get_tinfo_fn_dynamic (exp); + exp = build_call (exp, type, NULL_TREE); + + if (cond) + { + tree bad = throw_bad_typeid (); + + bad = build_compound_expr + (tree_cons (NULL_TREE, bad, build_tree_list + (NULL_TREE, convert (type, integer_zero_node)))); + exp = build (COND_EXPR, type, cond, exp, bad); + } + + return convert_from_reference (exp); } tree @@ -193,7 +274,7 @@ get_tinfo_var (type) If our struct layout or the type_info classes are changed, this will need to be modified. */ if (TYPE_VOLATILE (type) || TYPE_READONLY (type)) - size = 4 * POINTER_SIZE; + size = 3 * POINTER_SIZE + INT_TYPE_SIZE; else if (TREE_CODE (type) == POINTER_TYPE && ! (TREE_CODE (TREE_TYPE (type)) == OFFSET_TYPE || TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE)) @@ -207,7 +288,7 @@ get_tinfo_var (type) (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), 0)))) size = 3 * POINTER_SIZE; else - size = 4 * POINTER_SIZE; + size = 3 * POINTER_SIZE + INT_TYPE_SIZE; } else size = 2 * POINTER_SIZE; @@ -266,9 +347,8 @@ tree get_typeid_1 (type) tree type; { - tree t = build (CALL_EXPR, TREE_TYPE (tinfo_fn_type), - default_conversion (get_tinfo_fn (type)), NULL_TREE, NULL_TREE); - TREE_SIDE_EFFECTS (t) = 1; + tree t = build_call + (get_tinfo_fn (type), TREE_TYPE (tinfo_fn_type), NULL_TREE); return convert_from_reference (t); } @@ -296,37 +376,6 @@ get_typeid (type) return get_typeid_1 (type); } -/* Get a bad_cast node for the program to throw... - - See libstdc++/exception.cc for __throw_bad_cast */ - -static tree -throw_bad_cast () -{ - tree d = get_identifier ("__throw_bad_cast"); - tree type; - - if (IDENTIFIER_GLOBAL_VALUE (d)) - return IDENTIFIER_GLOBAL_VALUE (d); - - push_obstacks (&permanent_obstack, &permanent_obstack); - - type = build_function_type (void_type_node, void_list_node); - d = build_lang_decl (FUNCTION_DECL, d, type); - DECL_EXTERNAL (d) = 1; - TREE_PUBLIC (d) = 1; - DECL_ARTIFICIAL (d) = 1; - pushdecl_top_level (d); - make_function_rtl (d); - assemble_external (d); - - pop_obstacks (); - - d = build (CALL_EXPR, void_type_node, default_conversion (d), NULL_TREE, NULL_TREE); - TREE_SIDE_EFFECTS (d) = 1; - return d; -} - /* Check whether TEST is null before returning RESULT. If TEST is used in RESULT, it must have previously had a save_expr applied to it. */ @@ -355,7 +404,7 @@ build_dynamic_cast (type, expr) if (type == error_mark_node || expr == error_mark_node) return error_mark_node; - if (current_template_parms) + if (processing_template_decl) { tree t = build_min (DYNAMIC_CAST_EXPR, type, expr); return t; @@ -497,19 +546,22 @@ build_dynamic_cast (type, expr) expr2 = build_headof (expr1); if (ec == POINTER_TYPE) - td1 = build_typeid (build_indirect_ref (expr, NULL_PTR)); + td1 = get_tinfo_fn_dynamic (build_indirect_ref (expr, NULL_PTR)); else - td1 = build_typeid (expr); + td1 = get_tinfo_fn_dynamic (expr); + td1 = decay_conversion (td1); - td2 = get_typeid (TREE_TYPE (type)); - td3 = get_typeid (TREE_TYPE (exprtype)); + td2 = decay_conversion + (get_tinfo_fn (TYPE_MAIN_VARIANT (TREE_TYPE (type)))); + td3 = decay_conversion + (get_tinfo_fn (TYPE_MAIN_VARIANT (TREE_TYPE (exprtype)))); elems = tree_cons - (NULL_TREE, TREE_OPERAND (td1, 0), tree_cons - (NULL_TREE, TREE_OPERAND (td2, 0), tree_cons + (NULL_TREE, td1, tree_cons + (NULL_TREE, td2, tree_cons (NULL_TREE, build_int_2 (1, 0), tree_cons (NULL_TREE, expr2, tree_cons - (NULL_TREE, TREE_OPERAND (td3, 0), tree_cons + (NULL_TREE, td3, tree_cons (NULL_TREE, expr1, NULL_TREE)))))); dcast_fn = get_identifier ("__dynamic_cast"); @@ -520,14 +572,12 @@ build_dynamic_cast (type, expr) tree tmp; push_obstacks (&permanent_obstack, &permanent_obstack); - tmp = build_reference_type - (build_type_variant (type_info_type_node, 1, 0)); tmp = tree_cons - (NULL_TREE, tmp, tree_cons - (NULL_TREE, tmp, tree_cons + (NULL_TREE, TREE_TYPE (td1), tree_cons + (NULL_TREE, TREE_TYPE (td1), tree_cons (NULL_TREE, integer_type_node, tree_cons (NULL_TREE, ptr_type_node, tree_cons - (NULL_TREE, tmp, tree_cons + (NULL_TREE, TREE_TYPE (td1), tree_cons (NULL_TREE, ptr_type_node, void_list_node)))))); tmp = build_function_type (ptr_type_node, tmp); dcast_fn = build_lang_decl (FUNCTION_DECL, dcast_fn, tmp); @@ -540,15 +590,16 @@ build_dynamic_cast (type, expr) pop_obstacks (); } - result = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (dcast_fn)), - decay_conversion (dcast_fn), elems, NULL_TREE); - TREE_SIDE_EFFECTS (result) = 1; + result = build_call + (dcast_fn, TREE_TYPE (TREE_TYPE (dcast_fn)), elems); if (tc == REFERENCE_TYPE) { expr1 = throw_bad_cast (); - expr1 = build_compound_expr (tree_cons (NULL_TREE, expr1, - build_tree_list (NULL_TREE, convert (type, integer_zero_node)))); + expr1 = build_compound_expr + (tree_cons (NULL_TREE, expr1, + build_tree_list (NULL_TREE, convert + (type, integer_zero_node)))); TREE_TYPE (expr1) = type; result = save_expr (result); return build (COND_EXPR, type, result, result, expr1); @@ -625,9 +676,7 @@ expand_si_desc (tdecl, type) pop_obstacks (); } - fn = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)), - decay_conversion (fn), elems, NULL_TREE); - TREE_SIDE_EFFECTS (fn) = 1; + fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems); expand_expr_stmt (fn); } @@ -668,7 +717,7 @@ expand_class_desc (tdecl, type) (FIELD_DECL, NULL_TREE, build_pointer_type (build_type_variant (type_info_type_node, 1, 0))); fields [1] = build_lang_field_decl - (FIELD_DECL, NULL_TREE, sizetype); + (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node); DECL_BIT_FIELD (fields[1]) = 1; DECL_FIELD_SIZE (fields[1]) = 29; @@ -805,9 +854,7 @@ expand_class_desc (tdecl, type) pop_obstacks (); } - fn = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)), - decay_conversion (fn), elems, NULL_TREE); - TREE_SIDE_EFFECTS (fn) = 1; + fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems); expand_expr_stmt (fn); } @@ -854,9 +901,7 @@ expand_ptr_desc (tdecl, type) pop_obstacks (); } - fn = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)), - decay_conversion (fn), elems, NULL_TREE); - TREE_SIDE_EFFECTS (fn) = 1; + fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems); expand_expr_stmt (fn); } @@ -905,9 +950,7 @@ expand_attr_desc (tdecl, type) pop_obstacks (); } - fn = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)), - decay_conversion (fn), elems, NULL_TREE); - TREE_SIDE_EFFECTS (fn) = 1; + fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems); expand_expr_stmt (fn); } @@ -947,9 +990,7 @@ expand_generic_desc (tdecl, type, fnname) pop_obstacks (); } - fn = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)), - decay_conversion (fn), elems, NULL_TREE); - TREE_SIDE_EFFECTS (fn) = 1; + fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems); expand_expr_stmt (fn); } @@ -994,10 +1035,12 @@ synthesize_tinfo_fn (fndecl) tmp = build_binary_op (EQ_EXPR, tmp, integer_zero_node, 1); expand_start_cond (tmp, 0); - if (TYPE_VOLATILE (type) || TYPE_READONLY (type)) - expand_attr_desc (tdecl, type); + if (TREE_CODE (type) == FUNCTION_TYPE) + expand_generic_desc (tdecl, type, "__rtti_func"); else if (TREE_CODE (type) == ARRAY_TYPE) expand_generic_desc (tdecl, type, "__rtti_array"); + else if (TYPE_VOLATILE (type) || TYPE_READONLY (type)) + expand_attr_desc (tdecl, type); else if (TREE_CODE (type) == POINTER_TYPE) { if (TREE_CODE (TREE_TYPE (type)) == OFFSET_TYPE) @@ -1022,8 +1065,6 @@ synthesize_tinfo_fn (fndecl) } else if (TREE_CODE (type) == ENUMERAL_TYPE) expand_generic_desc (tdecl, type, "__rtti_user"); - else if (TREE_CODE (type) == FUNCTION_TYPE) - expand_generic_desc (tdecl, type, "__rtti_func"); else my_friendly_abort (252); diff --git a/gcc/cp/tinfo.cc b/gcc/cp/tinfo.cc new file mode 100644 index 00000000000..d82aaaf0431 --- /dev/null +++ b/gcc/cp/tinfo.cc @@ -0,0 +1,125 @@ +// Methods for type_info for -*- C++ -*- Run Time Type Identification. +// Copyright (C) 1994, 1996 Free Software Foundation + +// 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, 59 Temple Place - Suite 330, +// Boston, MA 02111-1307, USA. + +// As a special exception, if you link this library with other files, +// some of which are compiled with GCC, to produce an executable, +// this library does not by itself cause the resulting executable +// to be covered by the GNU General Public License. +// This exception does not however invalidate any other reasons why +// the executable file might be covered by the GNU General Public License. + +#include <stddef.h> +#include "tinfo.h" +#include "new" // for placement new + +// This file contains the minimal working set necessary to link with code +// that uses virtual functions and -frtti but does not actually use RTTI +// functionality. + +type_info:: +~type_info () +{ } + +extern "C" void +__rtti_class (void *addr, const char *name, + const __class_type_info::base_info *bl, size_t bn) +{ new (addr) __class_type_info (name, bl, bn); } + +extern "C" void +__rtti_si (void *addr, const char *n, const type_info *ti) +{ + new (addr) __si_type_info + (n, static_cast <const __user_type_info &> (*ti)); +} + +extern "C" void +__rtti_user (void *addr, const char *name) +{ new (addr) __user_type_info (name); } + +// dynamic_cast helper methods. +// Returns a pointer to the desired sub-object or 0. + +void * __user_type_info:: +dcast (const type_info& to, int, void *addr, const type_info *, void *) const +{ return (*this == to) ? addr : 0; } + +void * __si_type_info:: +dcast (const type_info& to, int require_public, void *addr, + const type_info *sub, void *subptr) const +{ + if (*this == to) + return addr; + return base.dcast (to, require_public, addr, sub, subptr); +} + +void* __class_type_info:: +dcast (const type_info& desired, int is_public, void *objptr, + const type_info *sub, void *subptr) const +{ + if (*this == desired) + return objptr; + + void *match_found = 0; + for (int i = 0; i < n_bases; i++) + { + if (is_public && base_list[i].access != PUBLIC) + continue; + + void *p = (char *)objptr + base_list[i].offset; + if (base_list[i].is_virtual) + p = *(void **)p; + p = base_list[i].base->dcast (desired, is_public, p, sub, subptr); + if (p) + { + if (match_found == 0) + match_found = p; + else if (match_found != p) + { + if (sub) + { + // Perhaps we're downcasting from *sub to desired; see if + // subptr is a subobject of exactly one of {match_found,p}. + + const __user_type_info &d = + static_cast <const __user_type_info &> (desired); + + void *os = d.dcast (*sub, 1, match_found); + void *ns = d.dcast (*sub, 1, p); + + if (os == ns) + /* ambiguous -- subptr is a virtual base */; + else if (os == subptr) + continue; + else if (ns == subptr) + { + match_found = p; + continue; + } + } + + // base found at two different pointers, + // conversion is not unique + return 0; + } + } + } + + return match_found; +} diff --git a/gcc/cp/tinfo2.cc b/gcc/cp/tinfo2.cc new file mode 100644 index 00000000000..10290a8e52b --- /dev/null +++ b/gcc/cp/tinfo2.cc @@ -0,0 +1,311 @@ +// Methods for type_info for -*- C++ -*- Run Time Type Identification. +// Copyright (C) 1994, 1996 Free Software Foundation + +// 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, 59 Temple Place - Suite 330, +// Boston, MA 02111-1307, USA. + +// As a special exception, if you link this library with other files, +// some of which are compiled with GCC, to produce an executable, +// this library does not by itself cause the resulting executable +// to be covered by the GNU General Public License. +// This exception does not however invalidate any other reasons why +// the executable file might be covered by the GNU General Public License. + +#include <stddef.h> +#include "tinfo.h" +#include "new" // for placement new + +// service function for comparing types by name. + +static inline int +fast_compare (const char *n1, const char *n2) { + int c; + if (n1 == n2) return 0; + if (n1 == 0) return *n2; + else if (n2 == 0) return *n1; + + c = (int)*n1++ - (int)*n2++; + return c == 0 ? strcmp (n1, n2) : c; +}; + +bool +type_info::before (const type_info &arg) +{ + return fast_compare (name (), arg.name ()) < 0; +} + +#ifdef _WIN32 +bool type_info:: +operator== (const type_info& arg) const +{ + return fast_compare (name (), arg.name ()) == 0; +} + +bool type_info:: +operator!= (const type_info& arg) const +{ + return fast_compare (name (), arg.name ()) != 0; +} +#endif + +// type info for pointer type. + +struct __pointer_type_info : public type_info { + const type_info& type; + + __pointer_type_info (const char *n, const type_info& ti) + : type_info (n), type (ti) {} +}; + +// type info for attributes + +struct __attr_type_info : public type_info { + enum cv { NONE = 0, CONST = 1, VOLATILE = 2, CONSTVOL = 1 | 2 }; + + const type_info& type; + cv attr; + + __attr_type_info (const char *n, cv a, const type_info& t) + : type_info (n), type (t), attr (a) {} +}; + +// type_info for builtin type + +struct __builtin_type_info : public type_info { + __builtin_type_info (const char *n): type_info (n) {} +}; + +// type info for function. + +struct __func_type_info : public type_info { + __func_type_info (const char *n) : type_info (n) {} +}; + +// type info for pointer to member function. + +struct __ptmf_type_info : public type_info { + __ptmf_type_info (const char *n) : type_info (n) {} +}; + +// type info for pointer to data member. + +struct __ptmd_type_info : public type_info { + __ptmd_type_info (const char *n): type_info (n) {} +}; + +// type info for array. + +struct __array_type_info : public type_info { + __array_type_info (const char *n): type_info (n) {} +}; + +// Entry points for the compiler. + +/* Low level match routine used by compiler to match types of catch + variables and thrown objects. */ + +extern "C" void* +__throw_type_match_rtti (void *catch_type_r, void *throw_type_r, void *objptr) +{ + const type_info &catch_type = *(const type_info *)catch_type_r; + const type_info &throw_type = *(const type_info *)throw_type_r; + + if (catch_type == throw_type) + return objptr; + +#if 0 + printf ("We want to match a %s against a %s!\n", + throw_type.name (), catch_type.name ()); +#endif + + void *new_objptr = 0; + + if (const __user_type_info *p + = dynamic_cast <const __user_type_info *> (&throw_type)) + { + /* The 1 skips conversions to private bases. */ + new_objptr = p->dcast (catch_type, 1, objptr); + } + else if (const __pointer_type_info *fr = + dynamic_cast <const __pointer_type_info *> (&throw_type)) + { + const __pointer_type_info *to = + dynamic_cast <const __pointer_type_info *> (&catch_type); + + if (! to) + goto fail; + + const type_info *subfr = &fr->type, *subto = &to->type; + __attr_type_info::cv cvfrom, cvto; + + if (const __attr_type_info *at + = dynamic_cast <const __attr_type_info *> (subfr)) + { + cvfrom = at->attr; + subfr = &at->type; + } + else + cvfrom = __attr_type_info::NONE; + + if (const __attr_type_info *at + = dynamic_cast <const __attr_type_info *> (subto)) + { + cvto = at->attr; + subto = &at->type; + } + else + cvto = __attr_type_info::NONE; + + if (((cvfrom & __attr_type_info::CONST) + > (cvto & __attr_type_info::CONST)) + || ((cvfrom & __attr_type_info::VOLATILE) + > (cvto & __attr_type_info::VOLATILE))) + goto fail; + + if (*subto == *subfr) + new_objptr = objptr; + else if (*subto == typeid (void) + && dynamic_cast <const __func_type_info *> (subfr) == 0) + new_objptr = objptr; + else if (const __user_type_info *p + = dynamic_cast <const __user_type_info *> (subfr)) + { + /* The 1 skips conversions to private bases. */ + new_objptr = p->dcast (*subto, 1, objptr); + } + else if (const __pointer_type_info *pfr + = dynamic_cast <const __pointer_type_info *> (subfr)) + { + // Multi-level pointer conversion. + + const __pointer_type_info *pto + = dynamic_cast <const __pointer_type_info *> (subto); + + if (! pto) + goto fail; + + bool constp = (cvto & __attr_type_info::CONST); + for (subto = &pto->type, subfr = &pfr->type; ; + subto = &pto->type, subfr = &pfr->type) + { + if (const __attr_type_info *at + = dynamic_cast <const __attr_type_info *> (subfr)) + { + cvfrom = at->attr; + subfr = &at->type; + } + else + cvfrom = __attr_type_info::NONE; + + if (const __attr_type_info *at + = dynamic_cast <const __attr_type_info *> (subto)) + { + cvto = at->attr; + subto = &at->type; + } + else + cvto = __attr_type_info::NONE; + + if (((cvfrom & __attr_type_info::CONST) + > (cvto & __attr_type_info::CONST)) + || ((cvfrom & __attr_type_info::VOLATILE) + > (cvto & __attr_type_info::VOLATILE))) + goto fail; + + if (! constp + && (((cvfrom & __attr_type_info::CONST) + < (cvto & __attr_type_info::CONST)) + || ((cvfrom & __attr_type_info::VOLATILE) + < (cvto & __attr_type_info::VOLATILE)))) + goto fail; + + if (*subto == *subfr) + { + new_objptr = objptr; + break; + } + + pto = dynamic_cast <const __pointer_type_info *> (subto); + pfr = dynamic_cast <const __pointer_type_info *> (subfr); + if (! pto || ! pfr) + goto fail; + + if (! (cvto & __attr_type_info::CONST)) + constp = false; + } + } + } + fail: + +#if 0 + if (new_objptr) + printf ("It converts, delta is %d\n", new_objptr-objptr); +#endif + return new_objptr; +} + +extern "C" void +__rtti_ptr (void *addr, const char *n, const type_info *ti) +{ new (addr) __pointer_type_info (n, *ti); } + +extern "C" void +__rtti_attr (void *addr, const char *n, int attrval, const type_info *ti) +{ + new (addr) __attr_type_info + (n, static_cast <__attr_type_info::cv> (attrval), *ti); +} + +extern "C" void +__rtti_func (void *addr, const char *name) +{ new (addr) __func_type_info (name); } + +extern "C" void +__rtti_ptmf (void *addr, const char *name) +{ new (addr) __ptmf_type_info (name); } + +extern "C" void +__rtti_ptmd (void *addr, const char *name) +{ new (addr) __ptmd_type_info (name); } + +extern "C" void +__rtti_array (void *addr, const char *name) +{ new (addr) __array_type_info (name); } + +extern "C" void * +__dynamic_cast (const type_info& (*from)(void), const type_info& (*to)(void), + int require_public, void *address, + const type_info & (*sub)(void), void *subptr) +{ + return static_cast <const __user_type_info &> (from ()).dcast + (to (), require_public, address, &(sub ()), subptr); +} + +// type_info nodes and functions for the builtin types. The mangling here +// must match the mangling in gcc/cp/rtti.c. + +#define BUILTIN(mangled) \ +unsigned char __ti##mangled [sizeof (__builtin_type_info)] \ + __attribute__ ((aligned (__alignof__ (void *)))); \ +extern "C" const type_info &__tf##mangled (void) { \ + if ((*(void **) __ti##mangled) == 0) \ + new (__ti##mangled) __builtin_type_info (#mangled); \ + return *(type_info *)__ti##mangled; \ +} + +BUILTIN (v); BUILTIN (x); BUILTIN (l); BUILTIN (i); BUILTIN (s); BUILTIN (b); +BUILTIN (c); BUILTIN (w); BUILTIN (r); BUILTIN (d); BUILTIN (f); +BUILTIN (Ui); BUILTIN (Ul); BUILTIN (Ux); BUILTIN (Us); BUILTIN (Uc); diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index ceb9acc3aec..0d0dc05318e 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -356,6 +356,7 @@ break_out_calls (exp) extern struct obstack *current_obstack; extern struct obstack permanent_obstack, class_obstack; extern struct obstack *saveable_obstack; +extern struct obstack *expression_obstack; /* Here is how primitive or already-canonicalized types' hash codes are made. MUST BE CONSISTENT WITH tree.c !!! */ @@ -421,7 +422,7 @@ build_cplus_array_type_1 (elt_type, index_type) saveable_obstack = &permanent_obstack; } - if (current_template_parms) + if (processing_template_decl) { t = make_node (ARRAY_TYPE); TREE_TYPE (t) = elt_type; @@ -1615,8 +1616,8 @@ mapcar (t, func) mapcar (TYPE_ARG_TYPES (t), func)); return cp_build_type_variant (tmp, TYPE_READONLY (t), TYPE_VOLATILE (t)); case ARRAY_TYPE: - tmp = build_array_type (mapcar (TREE_TYPE (t), func), - mapcar (TYPE_DOMAIN (t), func)); + tmp = build_cplus_array_type (mapcar (TREE_TYPE (t), func), + mapcar (TYPE_DOMAIN (t), func)); return cp_build_type_variant (tmp, TYPE_READONLY (t), TYPE_VOLATILE (t)); case INTEGER_TYPE: tmp = build_index_type (mapcar (TYPE_MAX_VALUE (t), func)); @@ -1632,6 +1633,11 @@ mapcar (t, func) mapcar (TREE_CHAIN (TYPE_ARG_TYPES (t)), func)); return cp_build_type_variant (tmp, TYPE_READONLY (t), TYPE_VOLATILE (t)); + case CONSTRUCTOR: + t = copy_node (t); + CONSTRUCTOR_ELTS (t) = mapcar (CONSTRUCTOR_ELTS (t), func); + return t; + case RECORD_TYPE: if (TYPE_PTRMEMFUNC_P (t)) return build_ptrmemfunc_type @@ -1673,20 +1679,20 @@ copy_to_permanent (t) { register struct obstack *ambient_obstack = current_obstack; register struct obstack *ambient_saveable_obstack = saveable_obstack; - int resume; + register struct obstack *ambient_expression_obstack = expression_obstack; if (t == NULL_TREE || TREE_PERMANENT (t)) return t; saveable_obstack = &permanent_obstack; current_obstack = saveable_obstack; - resume = suspend_momentary (); + expression_obstack = saveable_obstack; t = mapcar (t, perm_manip); - resume_momentary (resume); current_obstack = ambient_obstack; saveable_obstack = ambient_saveable_obstack; + expression_obstack = ambient_expression_obstack; return t; } diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 944acc62e46..8d77956c064 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -83,7 +83,7 @@ require_complete_type (value) { tree type; - if (current_template_parms) + if (processing_template_decl) return value; type = TREE_TYPE (value); @@ -132,8 +132,7 @@ complete_type (type) else if (TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type)) { tree t = complete_type (TREE_TYPE (type)); - if (TYPE_SIZE (t) != NULL_TREE - && current_template_parms == NULL_TREE) + if (TYPE_SIZE (t) != NULL_TREE && ! processing_template_decl) layout_type (type); TYPE_NEEDS_CONSTRUCTING (type) = TYPE_NEEDS_CONSTRUCTING (TYPE_MAIN_VARIANT (t)); @@ -1275,7 +1274,7 @@ c_sizeof (type) enum tree_code code = TREE_CODE (type); tree t; - if (current_template_parms) + if (processing_template_decl) return build_min (SIZEOF_EXPR, sizetype, type); if (code == FUNCTION_TYPE) @@ -1341,7 +1340,7 @@ tree expr_sizeof (e) tree e; { - if (current_template_parms) + if (processing_template_decl) return build_min (SIZEOF_EXPR, sizetype, e); if (TREE_CODE (e) == COMPONENT_REF @@ -1623,8 +1622,8 @@ build_object_ref (datum, basetype, field) { tree binfo = binfo_or_else (basetype, dtype); if (binfo) - return build_component_ref (build_scoped_ref (datum, basetype), - field, binfo, 1); + return build_x_component_ref (build_scoped_ref (datum, basetype), + field, binfo, 1); } return error_mark_node; } @@ -1709,7 +1708,7 @@ build_component_ref (datum, component, basetype_path, protect) register tree field = NULL; register tree ref; - if (current_template_parms) + if (processing_template_decl) return build_min_nt (COMPONENT_REF, datum, component); /* If DATUM is a COMPOUND_EXPR or COND_EXPR, move our reference @@ -1937,6 +1936,22 @@ build_component_ref (datum, component, basetype_path, protect) return ref; } + +/* Variant of build_component_ref for use in expressions, which should + never have REFERENCE_TYPE. */ + +tree +build_x_component_ref (datum, component, basetype_path, protect) + tree datum, component, basetype_path; + int protect; +{ + tree t = build_component_ref (datum, component, basetype_path, protect); + + if (! processing_template_decl) + t = convert_from_reference (t); + + return t; +} /* Given an expression PTR for a pointer, return an expression for the value pointed to. @@ -1952,7 +1967,7 @@ build_x_indirect_ref (ptr, errorstring) { tree rval; - if (current_template_parms) + if (processing_template_decl) return build_min_nt (INDIRECT_REF, ptr); rval = build_opfncall (INDIRECT_REF, LOOKUP_NORMAL, ptr, NULL_TREE, NULL_TREE); @@ -2213,7 +2228,7 @@ build_x_function_call (function, params, decl) if (function == error_mark_node) return error_mark_node; - if (current_template_parms) + if (processing_template_decl) return build_min_nt (CALL_EXPR, function, params, NULL_TREE); type = TREE_TYPE (function); @@ -2908,7 +2923,7 @@ build_x_binary_op (code, arg1, arg2) { tree rval; - if (current_template_parms) + if (processing_template_decl) return build_min_nt (code, arg1, arg2); if (flag_ansi_overloading) @@ -3958,7 +3973,7 @@ build_x_unary_op (code, xarg) enum tree_code code; tree xarg; { - if (current_template_parms) + if (processing_template_decl) return build_min_nt (code, xarg, NULL_TREE); /* & rec, on incomplete RECORD_TYPEs is the simple opr &, not an @@ -4005,7 +4020,7 @@ condition_conversion (expr) tree expr; { tree t; - if (current_template_parms) + if (processing_template_decl) return expr; t = convert (boolean_type_node, expr); t = fold (build1 (CLEANUP_POINT_EXPR, boolean_type_node, t)); @@ -4653,7 +4668,7 @@ build_x_conditional_expr (ifexp, op1, op2) { tree rval = NULL_TREE; - if (current_template_parms) + if (processing_template_decl) return build_min_nt (COND_EXPR, ifexp, op1, op2); if (flag_ansi_overloading) @@ -4988,7 +5003,7 @@ build_x_compound_expr (list) tree rest = TREE_CHAIN (list); tree result; - if (current_template_parms) + if (processing_template_decl) return build_min_nt (COMPOUND_EXPR, list, NULL_TREE); if (rest == NULL_TREE) @@ -5068,7 +5083,7 @@ build_static_cast (type, expr) if (TREE_CODE (expr) == OFFSET_REF) expr = resolve_offset_ref (expr); - if (current_template_parms) + if (processing_template_decl) { tree t = build_min (STATIC_CAST_EXPR, type, expr); return t; @@ -5160,7 +5175,7 @@ build_reinterpret_cast (type, expr) if (TREE_CODE (expr) == OFFSET_REF) expr = resolve_offset_ref (expr); - if (current_template_parms) + if (processing_template_decl) { tree t = build_min (REINTERPRET_CAST_EXPR, type, expr); return t; @@ -5252,7 +5267,7 @@ build_const_cast (type, expr) if (TREE_CODE (expr) == OFFSET_REF) expr = resolve_offset_ref (expr); - if (current_template_parms) + if (processing_template_decl) { tree t = build_min (CONST_CAST_EXPR, type, expr); return t; @@ -5361,7 +5376,7 @@ build_c_cast (type, expr, allow_nonconverting) return error_mark_node; } - if (current_template_parms) + if (processing_template_decl) { tree t = build_min (CAST_EXPR, type, min_tree_cons (NULL_TREE, value, NULL_TREE)); @@ -5993,7 +6008,7 @@ build_x_modify_expr (lhs, modifycode, rhs) enum tree_code modifycode; tree rhs; { - if (current_template_parms) + if (processing_template_decl) return build_min_nt (MODOP_EXPR, lhs, build_min_nt (modifycode, NULL_TREE, NULL_TREE), rhs); @@ -7022,7 +7037,7 @@ c_expand_return (retval) return; } - if (current_template_parms) + if (processing_template_decl) { add_tree (build_min_nt (RETURN_STMT, retval)); return; diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index 16b29dc0c5d..786ca79706c 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -607,6 +607,10 @@ store_init_value (decl, init) } } + if (TYPE_PTRMEMFUNC_P (type) && TREE_CODE (init) == CONSTRUCTOR + && TREE_TYPE (init) == NULL_TREE) + cp_pedwarn ("initializer list for `%T'", type); + /* End of special C++ code. */ /* Digest the specified initializer into an expression. */ @@ -1011,9 +1015,6 @@ process_init_constructor (type, init, elts) sorry ("initializer list for object using virtual functions"); return error_mark_node; } - - if (TYPE_PTRMEMFUNC_P (type)) - cp_pedwarn ("initializer list for `%T'", type); } for (field = TYPE_FIELDS (type); field && tail; @@ -1262,7 +1263,7 @@ build_x_arrow (datum) if (type == error_mark_node) return error_mark_node; - if (current_template_parms) + if (processing_template_decl) return build_min_nt (ARROW_EXPR, rval); if (TREE_CODE (rval) == OFFSET_REF) @@ -1338,7 +1339,7 @@ build_m_component_ref (datum, component) tree rettype; tree binfo; - if (current_template_parms) + if (processing_template_decl) return build_min_nt (DOTSTAR_EXPR, datum, component); if (TYPE_PTRMEMFUNC_P (TREE_TYPE (component))) @@ -1423,7 +1424,7 @@ build_functional_cast (exp, parms) else type = exp; - if (current_template_parms) + if (processing_template_decl) return build_min (CAST_EXPR, type, parms); if (IS_SIGNATURE (type)) |